[Pkg-golang-commits] [SCM] Packaging for Google Go branch, upstream-sid, updated. upstream/1.0.2-1-g04b08da

Michael Stapelberg michael at stapelberg.de
Mon Mar 4 20:49:45 UTC 2013


The following commit has been merged in the upstream-sid branch:
commit 04b08da9af0c450d645ab7389d1467308cfc2db8
Author: Michael Stapelberg <stapelberg at debian.org>
Date:   Mon Mar 4 21:27:36 2013 +0100

    Imported Upstream version 1.1~hg20130304

diff --git a/AUTHORS b/AUTHORS
index 42d7e82..de75396 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -16,16 +16,23 @@ Aleksandar Dezelin <dezelin at gmail.com>
 Alex Brainman <alex.brainman at gmail.com>
 Alexander Orlov <alexander.orlov at loxal.net>
 Alexander Reece <awreece at gmail.com>
+Alexander Surma <surma at surmair.de>
 Alexey Borzenkov <snaury at gmail.com>
+Amir Mohammad Saied <amir at gluegadget.com>
 Amrut Joshi <amrut.joshi at gmail.com>
 Andrei Vieru <euvieru at gmail.com>
 Andrew Balholm <andybalholm at gmail.com>
+Andrew Harding <andrew at spacemonkey.com>
+Andrew Lutomirski <andy at luto.us>
 Andrew Pritchard <awpritchard at gmail.com>
+Andrew Radev <andrey.radev at gmail.com>
 Andrew Skiba <skibaa at gmail.com>
+Andrew Wilkins <axwalk at gmail.com>
 Andrey Mirtchovski <mirtchovski at gmail.com>
 Andy Davis <andy at bigandian.com>
 Anh Hai Trinh <anh.hai.trinh at gmail.com>
 Anschel Schaffer-Cohen <anschelsc at gmail.com>
+Anthony Eufemio <anthony.eufemio at gmail.com>
 Anthony Martin <ality at pbrane.org>
 Anthony Starks <ajstarks at gmail.com>
 Aron Nopanen <aron.nopanen at gmail.com>
@@ -34,19 +41,25 @@ Ben Olive <sionide21 at gmail.com>
 Benjamin Black <b at b3k.us>
 Benny Siegert <bsiegert at gmail.com>
 Berengar Lehr <berengar.lehr at gmx.de>
-Brian Dellisanti <briandellisanti at gmail.com>
 Bjorn Tillenius <bjorn at tillenius.me>
 Bjorn Tipling <bjorn.tipling at gmail.com>
 Blake Mizerany <blake.mizerany at gmail.com>
 Bobby Powers <bobbypowers at gmail.com>
+Brian Dellisanti <briandellisanti at gmail.com>
+Brian Ketelsen <bketelsen at gmail.com>
 Caine Tighe <arctanofyourface at gmail.com>
+Caleb Spare <cespare at gmail.com>
+Carlos Castillo <cookieo9 at gmail.com>
+Casey Marshall <casey.marshall at gmail.com>
 Charles L. Dorian <cldorian at gmail.com>
 Chris Dollin <ehog.hedge at gmail.com>
 Chris Farmiloe <chrisfarms at gmail.com>
 Chris Jones <chris at cjones.org>
 Chris Lennert <calennert at gmail.com>
 Christian Himpel <chressie at googlemail.com>
+Christine Hansmann <chhansmann at gmail.com>
 Christoph Hack <christoph at tux21b.org>
+Christopher Cahoon <chris.cahoon at gmail.com>
 Christopher Nielsen <m4dh4tt3r at gmail.com>
 Christopher Redden <christopher.redden at gmail.com>
 Christopher Wedgwood <cw at f00f.org>
@@ -54,6 +67,7 @@ Clement Skau <clementskau at gmail.com>
 Conrad Meyer <cemeyer at cs.washington.edu>
 Corey Thomasson <cthom.lists at gmail.com>
 Damian Gryski <dgryski at gmail.com>
+Dan Callahan <dan.callahan at gmail.com>
 Dan Sinclair <dan.sinclair at gmail.com>
 Daniel Fleischman <danielfleischman at gmail.com>
 Daniel Krech <eikeon at eikeon.com>
@@ -69,12 +83,19 @@ David Titarenco <david.titarenco at gmail.com>
 Dean Prichard <dean.prichard at gmail.com>
 Devon H. O'Dell <devon.odell at gmail.com>
 Dmitry Chestnykh <dchest at gmail.com>
+Dominik Honnef <dominik.honnef at gmail.com>
+Donovan Hide <donovanhide at gmail.com>
+Dustin Shields-Cloues <dcloues at gmail.com>
 Eden Li <eden.li at gmail.com>
+Egon Elbre <egonelbre at gmail.com>
 Eivind Uggedal <eivind at uggedal.com>
+Elias Naur <elias.naur at gmail.com>
 Emil Hessman <c.emil.hessman at gmail.com>
 Eoghan Sherry <ejsherry at gmail.com>
 Eric Clark <zerohp at gmail.com>
-Eric Eisner <eric.d.eisner at gmail.com>
+Eric Milliken <emilliken at gmail.com>
+Eric Roshan-Eisner <eric.d.eisner at gmail.com>
+Erik St. Martin <alakriti at gmail.com>
 Esko Luontola <esko.luontola at gmail.com>
 Evan Shaw <chickencha at gmail.com>
 Fan Hongjian <fan.howard at gmail.com>
@@ -83,11 +104,14 @@ Firmansyah Adiputra <frm.adiputra at gmail.com>
 Florian Uekermann <florian at uekermann-online.de>
 Florian Weimer <fw at deneb.enyo.de>
 Francisco Souza <franciscossouza at gmail.com>
+Frithjof Schulze <schulze at math.uni-hannover.de>
 Gary Burd <gary at beagledreams.com>
+Georg Reinke <guelfey at gmail.com>
 Gideon Jan-Wessel Redelinghuys <gjredelinghuys at gmail.com>
 Giles Lean <giles.lean at pobox.com>
 Google Inc.
 Graham Miller <graham.miller at gmail.com>
+Greg Ward <greg at gerg.ca>
 Gustav Paul <gustav.paul at gmail.com>
 Gustavo Niemeyer <gustavo at niemeyer.net>
 Gwenael Treguier <gwenn.kahz at gmail.com>
@@ -97,6 +121,7 @@ Hong Ruiqi <hongruiqi at gmail.com>
 Icarus Sparry <golang at icarus.freeuk.com>
 Ingo Oeser <nightlyone at googlemail.com>
 Isaac Wagner <ibw at isaacwagner.me>
+James David Chalfant <james.chalfant at gmail.com>
 James Fysh <james.fysh at gmail.com>
 James Gray <james at james4k.com>
 James Meneghello <rawrz0r at gmail.com>
@@ -109,20 +134,30 @@ Jan Newmarch <jan.newmarch at gmail.com>
 Jan Ziak <0xe2.0x9a.0x9b at gmail.com>
 Jani Monoses <jani.monoses at ubuntu.com>
 Jaroslavas Počepko <jp at webmaster.ms>
+Jason Travis <infomaniac7 at gmail.com>
 Jeff Hodges <jeff at somethingsimilar.com>
 Jeff R. Allen <jra at nella.org>
+Jeff Wendling <jeff at spacemonkey.com>
 Jeremy Jackins <jeremyjackins at gmail.com>
 Jim McGrath <jimmc2 at gmail.com>
+Jimmy Zelinskie <jimmyzelinskie at gmail.com>
+Jingcheng Zhang <diogin at gmail.com>
+Joakim Sernbrant <serbaut at gmail.com>
 Joe Poirier <jdpoirier at gmail.com>
 John Asmuth <jasmuth at gmail.com>
+John Graham-Cumming <jgc at jgc.org> <jgrahamc at gmail.com>
+Jonathan Gold <jgold.bg at gmail.com>
 Jonathan Mark <jhmark at xenops.com>
 Jonathan Wills <runningwild at gmail.com>
 Jongmin Kim <atomaths at gmail.com>
 Jose Luis Vázquez González <josvazg at gmail.com>
 Josh Goebel <dreamer3 at gmail.com>
+Josh Holland <jrh at joshh.co.uk>
 Jukka-Pekka Kekkonen <karatepekka at gmail.com>
 Julian Phillips <julian at quantumfyre.co.uk>
+Julien Schmidt <google at julienschmidt.com>
 Kai Backman <kaib at golang.org>
+Kamil Kisiel <kamil at kamilkisiel.net> <kamil.kisiel at gmail.com>
 Kei Son <hey.calmdown at gmail.com>
 Keith Rarick <kr at xph.us>
 Ken Friedenbach <kenliz at cruzio.com>
@@ -130,6 +165,7 @@ Ken Rockot <ken at oz.gs>
 Kevin Ballard <kevin at sb.org>
 Kyle Consalus <consalus at gmail.com>
 Kyle Lemons <kyle at kylelemons.net>
+L Campbell <unpantsu at gmail.com>
 Lai Jiangshan <eag0628 at gmail.com>
 Lorenzo Stoakes <lstoakes at gmail.com>
 Luca Greco <luca.greco at alcacoop.it>
@@ -141,6 +177,7 @@ Martin Neubauer <m.ne at gmx.net>
 Mateusz Czapliński <czapkofan at gmail.com>
 Mathieu Lonjaret <mathieu.lonjaret at gmail.com>
 Mats Lidell <mats.lidell at cag.se>
+Matt Jibson <matt.jibson at gmail.com>
 Matthew Horsnell <matthew.horsnell at gmail.com>
 Micah Stetson <micah.stetson at gmail.com>
 Michael Chaten <mchaten at gmail.com>
@@ -148,6 +185,8 @@ Michael Elkins <michael.elkins at gmail.com>
 Michael Gehring <mg at ebfe.org>
 Michael Hoisie <hoisie at gmail.com>
 Michael Lewis <mikelikespie at gmail.com>
+Michael Stapelberg <michael at stapelberg.de>
+Michael Teichgräber <mteichgraeber at gmx.de>
 Michał Derkacz <ziutek at lnet.pl>
 Miek Gieben <miek at miek.nl>
 Mikael Tillenius <mikti42 at gmail.com>
@@ -155,67 +194,99 @@ Mike Rosset <mike.rosset at gmail.com>
 Miki Tebeka <miki.tebeka at gmail.com>
 Mikio Hara <mikioh.mikioh at gmail.com>
 Mikkel Krautz <mikkel at krautz.dk>
+Miquel Sabaté Solà <mikisabate at gmail.com>
 Moriyoshi Koizumi <mozo at mozo.jp>
 Môshe van der Sterre <moshevds at gmail.com>
 ngmoco, LLC
 Nicholas Waples <nwaples at gmail.com>
+Nick Craig-Wood <nick at craig-wood.com> <nickcw at gmail.com>
 Nigel Kerr <nigel.kerr at gmail.com>
+Oling Cat <olingcat at gmail.com>
 Olivier Antoine <olivier.antoine at gmail.com>
 Olivier Duperray <duperray.olivier at gmail.com>
+Olivier Saingre <osaingre at gmail.com>
 Padraig Kitterick <padraigkitterick at gmail.com>
 Paolo Giarrusso <p.giarrusso at gmail.com>
 Pascal S. de Kloe <pascal at quies.net>
+Patrick Crosby <patrick at stathat.com>
 Patrick Gavlin <pgavlin at gmail.com>
+Patrick Higgins <patrick.allen.higgins at gmail.com>
 Patrick Mylund Nielsen <patrick at patrickmn.com>
+Patrick Smith <pat42smith at gmail.com>
 Paul Lalonde <paul.a.lalonde at gmail.com>
 Paul Sbarra <Sbarra.Paul at gmail.com>
 Petar Maymounkov <petarm at gmail.com>
+Peter Armitage <peter.armitage at gmail.com>
 Peter Froehlich <peter.hans.froehlich at gmail.com>
 Peter Kleiweg <pkleiweg at xs4all.nl>
 Peter Mundy <go.peter.90 at gmail.com>
+Péter Surányi <speter.go1 at gmail.com>
+Peter Waller <peter.waller at gmail.com>
 Peter Williams <pwil3058 at gmail.com>
 Pieter Droogendijk <pieter at binky.org.uk>
 Quan Yong Zhai <qyzhai at gmail.com>
 Raif S. Naffah <go at naffah-raif.name>
 Rémy Oudompheng <oudomphe at phare.normalesup.org>
+Richard Eric Gavaletz <gavaletz at gmail.com>
+Rick Arnold <rickarnoldjr at gmail.com>
 Risto Jaakko Saarelma <rsaarelm at gmail.com>
+Robert Daniel Kortschak <dan.kortschak at adelaide.edu.au>
+Robert Dinu <r at oktett.se>
 Robert Figueiredo <robfig at gmail.com>
 Robert Hencke <robert.hencke at gmail.com>
+Robin Eklind <r.eklind.87 at gmail.com>
+Rodrigo Rafael Monti Kochenburger <divoxx at gmail.com>
 Roger Pau Monné <royger at gmail.com>
 Roger Peppe <rogpeppe at gmail.com>
 Ron Minnich <rminnich at gmail.com>
 Ross Light <rlight2 at gmail.com>
 Ryan Hitchman <hitchmanr at gmail.com>
+Ryan Slade <ryanslade at gmail.com>
 Sanjay Menakuru <balasanjay at gmail.com>
 Scott Lawrence <bytbox at gmail.com>
 Sebastien Binet	<seb.binet at gmail.com>
 Sébastien Paolacci <sebastien.paolacci at gmail.com>
 Sergei Skorobogatov <skorobo at rambler.ru>
 Sergey 'SnakE'  Gromov <snake.scaly at gmail.com>
-Sergio Luis O. B. Correia <sergio at larces.uece.br>
+Sergio Luis O. B. Correia <sergio at correia.cc>
+Shane Hansen <shanemhansen at gmail.com>
+Shawn Smith <shawn.p.smith at gmail.com>
 Shenghou Ma <minux.ma at gmail.com>
+Shivakumar GN <shivakumar.gn at gmail.com>
 Spring Mc <heresy.mc at gmail.com>
 Stefan Nilsson <snilsson at nada.kth.se> <trolleriprofessorn at gmail.com>
 Stéphane Travostino <stephane.travostino at gmail.com>
+Stephen McQuay <stephen at mcquay.me>
 Stephen Weinberg <stephen at q5comm.com>
+Steven Elliot Harris <seharris at gmail.com>
 Sven Almgren <sven at tras.se>
 Szabolcs Nagy <nsz at port70.net>
+Taj Khattra <taj.khattra at gmail.com>
 Tarmigan Casebolt <tarmigan at gmail.com>
 Taru Karttunen <taruti at taruti.net>
+Thomas Alan Copeland <talan.copeland at gmail.com>
+Thomas Kappler <tkappler at gmail.com>
 Timo Savola <timo.savola at gmail.com>
+Tobias Columbus <tobias.columbus at gmail.com>
 Tor Andersson <tor.andersson at gmail.com>
+Tyler Bunnell <tylerbunnell at gmail.com>
 Ugorji Nwoke <ugorji at gmail.com>
+Uriel Mangado <uriel at berlinblue.org>
 Vadim Vygonets <unixdj at gmail.com>
 Vincent Ambo <tazjin at googlemail.com>
 Vincent Vanackere <vincent.vanackere at gmail.com>
 Vinu Rajashekhar <vinutheraj at gmail.com>
+Vladimir Nikishenko <vova616 at gmail.com>
 Volker Dobler <dr.volker.dobler at gmail.com>
 Wei Guangjing <vcc.163 at gmail.com>
+Willem van der Schyff <willemvds at gmail.com>
 William Josephson <wjosephson at gmail.com>
+Xing Xing <mikespook at gmail.com>
 Yasuhiro Matsumoto <mattn.jp at gmail.com>
 Yissakhar Z. Beck <yissakhar.beck at gmail.com>
 Yongjian Xu <i3dmaster at gmail.com>
 Yoshiyuki Kanno <nekotaroh at gmail.com> <yoshiyuki.kanno at stoic.co.jp>
+Yusuke Kagiwada <block.rxckin.beats at gmail.com>
 Yuusei Kuwana <kuwana at kumama.org>
 Yuval Pavel Zholkover <paulzhol at gmail.com>
 Ziad Hatahet <hatahet at gmail.com>
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index e24b38a..01f4128 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -36,24 +36,34 @@ Abhinav Gupta <abhinav.g90 at gmail.com>
 Adam Langley <agl at golang.org>
 Adrian O'Grady <elpollouk at gmail.com>
 Akshat Kumar <seed at mail.nanosouffle.net>
+Alan Donovan <adonovan at google.com>
 Albert Strasheim <fullung at gmail.com>
 Aleksandar Dezelin <dezelin at gmail.com>
 Alex Brainman <alex.brainman at gmail.com>
+Alex Bramley <abramley at google.com>
 Alexander Orlov <alexander.orlov at loxal.net>
 Alexander Reece <awreece at gmail.com>
+Alexander Surma <surma at surmair.de>
 Alexandru Moșoi <brtzsnr at gmail.com>
 Alexey Borzenkov <snaury at gmail.com>
+Amir Mohammad Saied <amir at gluegadget.com>
 Amrut Joshi <amrut.joshi at gmail.com>
 Andrea Spadaccini <spadaccio at google.com>
+Andreas Jellinghaus <andreas at ionisiert.de> <anj at google.com>
 Andrei Vieru <euvieru at gmail.com>
 Andrew Balholm <andybalholm at gmail.com>
 Andrew Gerrand <adg at golang.org>
+Andrew Harding <andrew at spacemonkey.com>
+Andrew Lutomirski <andy at luto.us>
 Andrew Pritchard <awpritchard at gmail.com>
+Andrew Radev <andrey.radev at gmail.com>
 Andrew Skiba <skibaa at gmail.com>
+Andrew Wilkins <axwalk at gmail.com>
 Andrey Mirtchovski <mirtchovski at gmail.com>
 Andy Davis <andy at bigandian.com>
 Anh Hai Trinh <anh.hai.trinh at gmail.com>
 Anschel Schaffer-Cohen <anschelsc at gmail.com>
+Anthony Eufemio <anthony.eufemio at gmail.com>
 Anthony Martin <ality at pbrane.org>
 Anthony Starks <ajstarks at gmail.com>
 Aron Nopanen <aron.nopanen at gmail.com>
@@ -67,17 +77,24 @@ Ben Olive <sionide21 at gmail.com>
 Benjamin Black <b at b3k.us>
 Benny Siegert <bsiegert at gmail.com>
 Berengar Lehr <Berengar.Lehr at gmx.de>
-Bill Neubauer <wcn at golang.org> <wcn at google.com>
+Bill Neubauer <wcn at golang.org> <wcn at google.com> <bill.neubauer at gmail.com>
 Bill Thiede <couchmoney at gmail.com>
 Bjorn Tillenius <bjorn at tillenius.me>
 Bjorn Tipling <bjorn.tipling at gmail.com>
 Blake Mizerany <blake.mizerany at gmail.com>
 Bobby Powers <bobbypowers at gmail.com>
 Brad Fitzpatrick <bradfitz at golang.org> <bradfitz at gmail.com>
-Brian Dellisanti <briandellisanti at gmail.com>
 Brendan O'Dea <bod at golang.org>
+Brian Dellisanti <briandellisanti at gmail.com>
+Brian Ketelsen <bketelsen at gmail.com>
+Brian Slesinsky <skybrian at google.com>
 Caine Tighe <arctanofyourface at gmail.com>
+Caleb Spare <cespare at gmail.com>
+Carl Mastrangelo <notcarl at google.com>
+Carl Shapiro <cshapiro at google.com> <cshapiro at golang.org>
+Carlos Castillo <cookieo9 at gmail.com>
 Cary Hull <chull at google.com>
+Casey Marshall <casey.marshall at gmail.com>
 Charles L. Dorian <cldorian at gmail.com>
 Chris Dollin <ehog.hedge at gmail.com>
 Chris Farmiloe <chrisfarms at gmail.com>
@@ -85,15 +102,20 @@ Chris Hundt <hundt at google.com>
 Chris Jones <chris at cjones.org> <chris.jones.yar at gmail.com>
 Chris Lennert <calennert at gmail.com>
 Christian Himpel <chressie at googlemail.com> <chressie at gmail.com>
+Christine Hansmann <chhansmann at gmail.com>
 Christoph Hack <christoph at tux21b.org>
+Christopher Cahoon <chris.cahoon at gmail.com>
 Christopher Nielsen <m4dh4tt3r at gmail.com>
 Christopher Redden <christopher.redden at gmail.com>
+Christopher Swenson <cswenson at google.com>
 Christopher Wedgwood <cw at f00f.org>
 Clement Skau <clementskau at gmail.com>
 Colby Ranger <cranger at google.com>
 Conrad Meyer <cemeyer at cs.washington.edu>
 Corey Thomasson <cthom.lists at gmail.com>
+Cosmos Nicolaou <cnicolaou at google.com>
 Damian Gryski <dgryski at gmail.com>
+Dan Callahan <dan.callahan at gmail.com>
 Dan Sinclair <dan.sinclair at gmail.com>
 Daniel Fleischman <danielfleischman at gmail.com>
 Daniel Krech <eikeon at eikeon.com>
@@ -101,6 +123,7 @@ Daniel Morsing <daniel.morsing at gmail.com>
 Daniel Nadasi <dnadasi at google.com>
 Daniel Theophanes <kardianos at gmail.com>
 Darren Elwood <darren at textnode.com>
+Dave Borowitz <dborowitz at google.com>
 Dave Cheney <dave at cheney.net>
 Dave Grijalva <dgrijalva at ngmoco.com>
 David Anderson <danderson at google.com>
@@ -109,18 +132,26 @@ David du Colombier <0intro at gmail.com>
 David Forsythe <dforsythe at gmail.com>
 David G. Andersen <dave.andersen at gmail.com>
 David Jakob Fritz <david.jakob.fritz at gmail.com>
+David McLeish <davemc at google.com>
 David Symonds <dsymonds at golang.org>
 David Titarenco <david.titarenco at gmail.com>
 Dean Prichard <dean.prichard at gmail.com>
 Devon H. O'Dell <devon.odell at gmail.com>
 Dmitriy Vyukov <dvyukov at google.com>
 Dmitry Chestnykh <dchest at gmail.com>
+Dominik Honnef <dominik.honnef at gmail.com>
+Donovan Hide <donovanhide at gmail.com>
+Dustin Shields-Cloues <dcloues at gmail.com>
 Eden Li <eden.li at gmail.com>
+Egon Elbre <egonelbre at gmail.com>
 Eivind Uggedal <eivind at uggedal.com>
+Elias Naur <elias.naur at gmail.com>
 Emil Hessman <c.emil.hessman at gmail.com>
 Eoghan Sherry <ejsherry at gmail.com>
 Eric Clark <zerohp at gmail.com>
-Eric Eisner <eric.d.eisner at gmail.com>
+Eric Milliken <emilliken at gmail.com>
+Eric Roshan-Eisner <eric.d.eisner at gmail.com>
+Erik St. Martin <alakriti at gmail.com>
 Esko Luontola <esko.luontola at gmail.com>
 Evan Martin <evan.martin at gmail.com>
 Evan Shaw <chickencha at gmail.com>
@@ -129,18 +160,26 @@ Fazlul Shahriar <fshahriar at gmail.com>
 Firmansyah Adiputra <frm.adiputra at gmail.com>
 Florian Uekermann <florian at uekermann-online.de> <f1 at uekermann-online.de>
 Florian Weimer <fw at deneb.enyo.de>
+Francesc Campoy <campoy at golang.org>
 Francisco Souza <franciscossouza at gmail.com>
+Frithjof Schulze <schulze at math.uni-hannover.de>
 Fumitoshi Ukai <ukai at google.com>
+Gaal Yahas <gaal at google.com>
 Gary Burd <gary at beagledreams.com> <gary.burd at gmail.com>
+Georg Reinke <guelfey at gmail.com>
 Gideon Jan-Wessel Redelinghuys <gjredelinghuys at gmail.com>
 Giles Lean <giles.lean at pobox.com>
 Graham Miller <graham.miller at gmail.com>
+Greg Ward <greg at gerg.ca>
 Gustav Paul <gustav.paul at gmail.com>
+Gustavo Franco <gustavorfranco at gmail.com>
 Gustavo Niemeyer <gustavo at niemeyer.net> <n13m3y3r at gmail.com>
 Gwenael Treguier <gwenn.kahz at gmail.com>
+Han-Wen Nienhuys <hanwen at google.com>
 Harley Laue <losinggeneration at gmail.com>
 Hector Chu <hectorchu at gmail.com>
 Hong Ruiqi <hongruiqi at gmail.com>
+Hossein Sheikh Attar <hattar at google.com>
 Ian Lance Taylor <iant at golang.org>
 Icarus Sparry <golang at icarus.freeuk.com>
 Ingo Oeser <nightlyone at googlemail.com> <nightlyone at gmail.com>
@@ -148,6 +187,7 @@ Isaac Wagner <ibw at isaacwagner.me>
 Ivan Krasin <krasin at golang.org>
 Jacob Baskin <jbaskin at google.com>
 James Aguilar <jaguilar at google.com>
+James David Chalfant <james.chalfant at gmail.com>
 James Fysh <james.fysh at gmail.com>
 James Gray <james at james4k.com>
 James Meneghello <rawrz0r at gmail.com>
@@ -161,18 +201,28 @@ Jan Newmarch <jan.newmarch at gmail.com>
 Jan Ziak <0xe2.0x9a.0x9b at gmail.com>
 Jani Monoses <jani.monoses at ubuntu.com> <jani.monoses at gmail.com>
 Jaroslavas Počepko <jp at webmaster.ms>
+Jason Travis <infomaniac7 at gmail.com>
 Jean-Marc Eurin <jmeurin at google.com>
 Jeff Hodges <jeff at somethingsimilar.com>
 Jeff R. Allen <jra at nella.org> <jeff.allen at gmail.com>
+Jeff Wendling <jeff at spacemonkey.com>
 Jeremy Jackins <jeremyjackins at gmail.com>
+Jeremy Schlatter <jeremy.schlatter at gmail.com>
 Jim McGrath <jimmc2 at gmail.com>
+Jimmy Zelinskie <jimmyzelinskie at gmail.com>
+Jingcheng Zhang <diogin at gmail.com>
+Joakim Sernbrant <serbaut at gmail.com>
 Joe Poirier <jdpoirier at gmail.com>
 Joel Sing <jsing at google.com>
 Johan Euphrosine <proppy at google.com>
 John Asmuth <jasmuth at gmail.com>
 John Beisley <huin at google.com>
 John DeNero <denero at google.com>
+John Graham-Cumming <jgc at jgc.org> <jgrahamc at gmail.com>
 Jonathan Allie <jonallie at google.com>
+Jonathan Feinberg <feinberg at google.com>
+Jonathan Gold <jgold.bg at gmail.com>
+Jonathan Hseu <jhseu at google.com>
 Jonathan Mark <jhmark at xenops.com> <jhmark000 at gmail.com>
 Jonathan Pittman <jmpittman at google.com> <jonathan.mark.pittman at gmail.com>
 Jonathan Wills <runningwild at gmail.com>
@@ -180,9 +230,12 @@ Jongmin Kim <atomaths at gmail.com>
 Jos Visser <josv at google.com>
 Jose Luis Vázquez González <josvazg at gmail.com>
 Josh Goebel <dreamer3 at gmail.com>
+Josh Holland <jrh at joshh.co.uk>
 Jukka-Pekka Kekkonen <karatepekka at gmail.com>
 Julian Phillips <julian at quantumfyre.co.uk>
+Julien Schmidt <google at julienschmidt.com>
 Kai Backman <kaib at golang.org>
+Kamil Kisiel <kamil at kamilkisiel.net> <kamil.kisiel at gmail.com>
 Kei Son <hey.calmdown at gmail.com>
 Keith Rarick <kr at xph.us>
 Ken Friedenbach <kenliz at cruzio.com>
@@ -192,6 +245,7 @@ Kevin Ballard <kevin at sb.org>
 Kirklin McDonald <kirklin.mcdonald at gmail.com>
 Kyle Consalus <consalus at gmail.com>
 Kyle Lemons <kyle at kylelemons.net> <kevlar at google.com>
+L Campbell <unpantsu at gmail.com>
 Lai Jiangshan <eag0628 at gmail.com>
 Larry Hosken <lahosken at golang.org>
 Lorenzo Stoakes <lstoakes at gmail.com>
@@ -200,6 +254,7 @@ Luca Greco <luca.greco at alcacoop.it>
 Lucio De Re <lucio.dere at gmail.com>
 Luit van Drongelen <luitvd at gmail.com>
 Luuk van Dijk <lvd at golang.org> <lvd at google.com>
+Manu Garg <manugarg at google.com>
 Marcel van Lohuizen <mpvl at golang.org>
 Mark Zavislak <zavislak at google.com>
 Markus Duft <markus.duft at salomon.at>
@@ -208,7 +263,10 @@ Martin Neubauer <m.ne at gmx.net>
 Mateusz Czapliński <czapkofan at gmail.com>
 Mathieu Lonjaret <mathieu.lonjaret at gmail.com>
 Mats Lidell <mats.lidell at cag.se> <mats.lidell at gmail.com>
+Matt Brown <mdbrown at google.com>
+Matt Jibson <matt.jibson at gmail.com>
 Matt Jones <mrjones at google.com>
+Matthew Dempsky <mdempsky at google.com>
 Matthew Horsnell <matthew.horsnell at gmail.com>
 Maxim Pimenov <mpimenov at google.com>
 Maxim Ushakov <ushakov at google.com>
@@ -218,8 +276,11 @@ Michael Elkins <michael.elkins at gmail.com>
 Michael Gehring <mg at ebfe.org>
 Michael Hoisie <hoisie at gmail.com>
 Michael Lewis <mikelikespie at gmail.com>
+Michael Matloob <matloob at google.com>
 Michael Shields <mshields at google.com>
+Michael Stapelberg <michael at stapelberg.de> <mstplbrg at googlemail.com>
 Michael T. Jones <mtj at google.com> <michael.jones at gmail.com>
+Michael Teichgräber <mteichgraeber at gmx.de> <mt4swm at googlemail.com>
 Michał Derkacz <ziutek at lnet.pl>
 Miek Gieben <miek at miek.nl> <remigius.gieben at gmail.com>
 Mikael Tillenius <mikti42 at gmail.com>
@@ -229,27 +290,39 @@ Mike Solomon <msolo at gmail.com>
 Miki Tebeka <miki.tebeka at gmail.com>
 Mikio Hara <mikioh.mikioh at gmail.com>
 Mikkel Krautz <mikkel at krautz.dk> <krautz at gmail.com>
+Miquel Sabaté Solà <mikisabate at gmail.com>
 Moriyoshi Koizumi <mozo at mozo.jp>
 Môshe van der Sterre <moshevds at gmail.com>
 Nicholas Waples <nwaples at gmail.com>
+Nick Craig-Wood <nick at craig-wood.com> <nickcw at gmail.com>
 Nigel Kerr <nigel.kerr at gmail.com>
 Nigel Tao <nigeltao at golang.org>
+Oling Cat <olingcat at gmail.com>
 Olivier Antoine <olivier.antoine at gmail.com>
 Olivier Duperray <duperray.olivier at gmail.com>
+Olivier Saingre <osaingre at gmail.com>
 Padraig Kitterick <padraigkitterick at gmail.com>
 Paolo Giarrusso <p.giarrusso at gmail.com>
 Pascal S. de Kloe <pascal at quies.net>
+Patrick Crosby <patrick at stathat.com>
 Patrick Gavlin <pgavlin at gmail.com>
+Patrick Higgins <patrick.allen.higgins at gmail.com>
 Patrick Mylund Nielsen <patrick at patrickmn.com>
+Patrick Smith <pat42smith at gmail.com>
 Paul Borman <borman at google.com>
+Paul Chang <paulchang at google.com>
 Paul Lalonde <paul.a.lalonde at gmail.com>
 Paul Sbarra <Sbarra.Paul at gmail.com>
+Pawel Szczur <filemon at google.com>
 Petar Maymounkov <petarm at gmail.com>
+Peter Armitage <peter.armitage at gmail.com>
 Peter Froehlich <peter.hans.froehlich at gmail.com>
 Peter Kleiweg <pkleiweg at xs4all.nl>
 Peter McKenzie <petermck at google.com>
 Peter Mundy <go.peter.90 at gmail.com>
+Péter Surányi <speter.go1 at gmail.com>
 Péter Szabó <pts at google.com>
+Peter Waller <peter.waller at gmail.com>
 Peter Weinberger <pjw at golang.org>
 Peter Williams <pwil3058 at gmail.com>
 Phil Pennock <pdp at golang.org>
@@ -258,11 +331,17 @@ Quan Yong Zhai <qyzhai at gmail.com>
 Raif S. Naffah <go at naffah-raif.name>
 Raph Levien <raph at google.com>
 Rémy Oudompheng <oudomphe at phare.normalesup.org> <remyoudompheng at gmail.com>
+Richard Eric Gavaletz <gavaletz at gmail.com>
+Rick Arnold <rickarnoldjr at gmail.com>
 Risto Jaakko Saarelma <rsaarelm at gmail.com>
 Rob Pike <r at golang.org>
+Robert Daniel Kortschak <dan.kortschak at adelaide.edu.au>
+Robert Dinu <r at oktett.se>
 Robert Figueiredo <robfig at gmail.com>
 Robert Griesemer <gri at golang.org>
 Robert Hencke <robert.hencke at gmail.com>
+Robin Eklind <r.eklind.87 at gmail.com>
+Rodrigo Rafael Monti Kochenburger <divoxx at gmail.com>
 Roger Pau Monné <royger at gmail.com>
 Roger Peppe <rogpeppe at gmail.com>
 Ron Minnich <rminnich at gmail.com>
@@ -270,6 +349,7 @@ Ross Light <rlight2 at gmail.com>
 Russ Cox <rsc at golang.org>
 Ryan Barrett <ryanb at google.com>
 Ryan Hitchman <hitchmanr at gmail.com>
+Ryan Slade <ryanslade at gmail.com>
 Sam Thorogood <thorogood at google.com> <sam.thorogood at gmail.com>
 Sameer Ajmani <sameer at golang.org> <ajmani at gmail.com>
 Sanjay Menakuru <balasanjay at gmail.com>
@@ -279,36 +359,53 @@ Sebastien Binet	<seb.binet at gmail.com>
 Sébastien Paolacci <sebastien.paolacci at gmail.com>
 Sergei Skorobogatov <skorobo at rambler.ru>
 Sergey 'SnakE' Gromov <snake.scaly at gmail.com>
-Sergio Luis O. B. Correia <sergio at larces.uece.br>
+Sergio Luis O. B. Correia <sergio at correia.cc>
+Shane Hansen <shanemhansen at gmail.com>
+Shawn Ledbetter <sledbetter at google.com>
+Shawn Smith <shawn.p.smith at gmail.com>
 Shenghou Ma <minux.ma at gmail.com>
+Shivakumar GN <shivakumar.gn at gmail.com>
 Spring Mc <heresy.mc at gmail.com>
 Stefan Nilsson <snilsson at nada.kth.se> <trolleriprofessorn at gmail.com>
 Stéphane Travostino <stephane.travostino at gmail.com>
 Stephen Ma <stephenm at golang.org>
+Stephen McQuay <stephen at mcquay.me>
 Stephen Weinberg <stephen at q5comm.com>
+Steven Elliot Harris <seharris at gmail.com>
 Sugu Sougoumarane <ssougou at gmail.com>
 Sven Almgren <sven at tras.se>
 Szabolcs Nagy <nsz at port70.net>
+Taj Khattra <taj.khattra at gmail.com>
 Tarmigan Casebolt <tarmigan at gmail.com>
 Taru Karttunen <taruti at taruti.net>
+Thomas Alan Copeland <talan.copeland at gmail.com>
+Thomas Kappler <tkappler at gmail.com>
 Timo Savola <timo.savola at gmail.com>
+Tobias Columbus <tobias.columbus at gmail.com> <tobias.columbus at googlemail.com>
 Tom Szymanski <tgs at google.com>
 Tor Andersson <tor.andersson at gmail.com>
 Trevor Strohman <trevor.strohman at gmail.com>
+Tyler Bunnell <tylerbunnell at gmail.com>
 Ugorji Nwoke <ugorji at gmail.com>
+Uriel Mangado <uriel at berlinblue.org>
 Vadim Vygonets <unixdj at gmail.com>
+Vega Garcia Luis Alfonso <vegacom at gmail.com>
 Vincent Ambo <tazjin at googlemail.com>
 Vincent Vanackere <vincent.vanackere at gmail.com>
 Vinu Rajashekhar <vinutheraj at gmail.com>
 Vish Subramanian <vish at google.com>
+Vladimir Nikishenko <vova616 at gmail.com>
 Volker Dobler <dr.volker.dobler at gmail.com>
 Wei Guangjing <vcc.163 at gmail.com>
+Willem van der Schyff <willemvds at gmail.com>
 William Chan <willchan at chromium.org>
 William Josephson <wjosephson at gmail.com>
+Xing Xing <mikespook at gmail.com>
 Yasuhiro Matsumoto <mattn.jp at gmail.com>
 Yissakhar Z. Beck <yissakhar.beck at gmail.com>
 Yongjian Xu <i3dmaster at gmail.com>
 Yoshiyuki Kanno <nekotaroh at gmail.com> <yoshiyuki.kanno at stoic.co.jp>
+Yusuke Kagiwada <block.rxckin.beats at gmail.com>
 Yuusei Kuwana <kuwana at kumama.org>
 Yuval Pavel Zholkover <paulzhol at gmail.com>
 Yves Junqueira <yves.junqueira at gmail.com>
diff --git a/VERSION b/VERSION
deleted file mode 100644
index 1764d79..0000000
--- a/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-go1.0.2
\ No newline at end of file
diff --git a/api/README b/api/README
index 6adc554..897abc8 100644
--- a/api/README
+++ b/api/README
@@ -5,6 +5,9 @@ Each file is a list of of API features, one per line.
 go1.txt (and similarly named files) are frozen once a version has been
 shipped. Each file adds new lines but does not remove any.
 
+except.txt lists features that may disappear without breaking true
+compatibility.
+
 next.txt is the only file intended to be mutated. It's a list of
 features that may be added to the next version. It only affects
 warning output from the go api tool.
diff --git a/api/except.txt b/api/except.txt
new file mode 100644
index 0000000..7f8f81d
--- /dev/null
+++ b/api/except.txt
@@ -0,0 +1,3 @@
+pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
+pkg text/template/parse, type DotNode bool
+pkg text/template/parse, type Node interface { Copy, String, Type }
diff --git a/api/go1.txt b/api/go1.txt
index 601c1f3..d90d765 100644
--- a/api/go1.txt
+++ b/api/go1.txt
@@ -12,10 +12,10 @@ pkg archive/tar, const TypeXHeader ideal-char
 pkg archive/tar, func NewReader(io.Reader) *Reader
 pkg archive/tar, func NewWriter(io.Writer) *Writer
 pkg archive/tar, method (*Reader) Next() (*Header, error)
-pkg archive/tar, method (*Reader) Read([]byte) (int, error)
+pkg archive/tar, method (*Reader) Read([]uint8) (int, error)
 pkg archive/tar, method (*Writer) Close() error
 pkg archive/tar, method (*Writer) Flush() error
-pkg archive/tar, method (*Writer) Write([]byte) (int, error)
+pkg archive/tar, method (*Writer) Write([]uint8) (int, error)
 pkg archive/tar, method (*Writer) WriteHeader(*Header) error
 pkg archive/tar, type Header struct
 pkg archive/tar, type Header struct, AccessTime time.Time
@@ -29,7 +29,7 @@ pkg archive/tar, type Header struct, ModTime time.Time
 pkg archive/tar, type Header struct, Mode int64
 pkg archive/tar, type Header struct, Name string
 pkg archive/tar, type Header struct, Size int64
-pkg archive/tar, type Header struct, Typeflag byte
+pkg archive/tar, type Header struct, Typeflag uint8
 pkg archive/tar, type Header struct, Uid int
 pkg archive/tar, type Header struct, Uname string
 pkg archive/tar, type Reader struct
@@ -67,7 +67,7 @@ pkg archive/zip, type FileHeader struct, Comment string
 pkg archive/zip, type FileHeader struct, CompressedSize uint32
 pkg archive/zip, type FileHeader struct, CreatorVersion uint16
 pkg archive/zip, type FileHeader struct, ExternalAttrs uint32
-pkg archive/zip, type FileHeader struct, Extra []byte
+pkg archive/zip, type FileHeader struct, Extra []uint8
 pkg archive/zip, type FileHeader struct, Flags uint16
 pkg archive/zip, type FileHeader struct, Method uint16
 pkg archive/zip, type FileHeader struct, ModifiedDate uint16
@@ -90,38 +90,38 @@ pkg bufio, func NewReaderSize(io.Reader, int) *Reader
 pkg bufio, func NewWriter(io.Writer) *Writer
 pkg bufio, func NewWriterSize(io.Writer, int) *Writer
 pkg bufio, method (*Reader) Buffered() int
-pkg bufio, method (*Reader) Peek(int) ([]byte, error)
-pkg bufio, method (*Reader) Read([]byte) (int, error)
-pkg bufio, method (*Reader) ReadByte() (byte, error)
-pkg bufio, method (*Reader) ReadBytes(byte) ([]byte, error)
-pkg bufio, method (*Reader) ReadLine() ([]byte, bool, error)
-pkg bufio, method (*Reader) ReadRune() (rune, int, error)
-pkg bufio, method (*Reader) ReadSlice(byte) ([]byte, error)
-pkg bufio, method (*Reader) ReadString(byte) (string, error)
+pkg bufio, method (*Reader) Peek(int) ([]uint8, error)
+pkg bufio, method (*Reader) Read([]uint8) (int, error)
+pkg bufio, method (*Reader) ReadByte() (uint8, error)
+pkg bufio, method (*Reader) ReadBytes(uint8) ([]uint8, error)
+pkg bufio, method (*Reader) ReadLine() ([]uint8, bool, error)
+pkg bufio, method (*Reader) ReadRune() (int32, int, error)
+pkg bufio, method (*Reader) ReadSlice(uint8) ([]uint8, error)
+pkg bufio, method (*Reader) ReadString(uint8) (string, error)
 pkg bufio, method (*Reader) UnreadByte() error
 pkg bufio, method (*Reader) UnreadRune() error
 pkg bufio, method (*Writer) Available() int
 pkg bufio, method (*Writer) Buffered() int
 pkg bufio, method (*Writer) Flush() error
-pkg bufio, method (*Writer) Write([]byte) (int, error)
-pkg bufio, method (*Writer) WriteByte(byte) error
-pkg bufio, method (*Writer) WriteRune(rune) (int, error)
+pkg bufio, method (*Writer) Write([]uint8) (int, error)
+pkg bufio, method (*Writer) WriteByte(uint8) error
+pkg bufio, method (*Writer) WriteRune(int32) (int, error)
 pkg bufio, method (*Writer) WriteString(string) (int, error)
 pkg bufio, method (ReadWriter) Available() int
 pkg bufio, method (ReadWriter) Flush() error
-pkg bufio, method (ReadWriter) Peek(int) ([]byte, error)
-pkg bufio, method (ReadWriter) Read([]byte) (int, error)
-pkg bufio, method (ReadWriter) ReadByte() (byte, error)
-pkg bufio, method (ReadWriter) ReadBytes(byte) ([]byte, error)
-pkg bufio, method (ReadWriter) ReadLine() ([]byte, bool, error)
-pkg bufio, method (ReadWriter) ReadRune() (rune, int, error)
-pkg bufio, method (ReadWriter) ReadSlice(byte) ([]byte, error)
-pkg bufio, method (ReadWriter) ReadString(byte) (string, error)
+pkg bufio, method (ReadWriter) Peek(int) ([]uint8, error)
+pkg bufio, method (ReadWriter) Read([]uint8) (int, error)
+pkg bufio, method (ReadWriter) ReadByte() (uint8, error)
+pkg bufio, method (ReadWriter) ReadBytes(uint8) ([]uint8, error)
+pkg bufio, method (ReadWriter) ReadLine() ([]uint8, bool, error)
+pkg bufio, method (ReadWriter) ReadRune() (int32, int, error)
+pkg bufio, method (ReadWriter) ReadSlice(uint8) ([]uint8, error)
+pkg bufio, method (ReadWriter) ReadString(uint8) (string, error)
 pkg bufio, method (ReadWriter) UnreadByte() error
 pkg bufio, method (ReadWriter) UnreadRune() error
-pkg bufio, method (ReadWriter) Write([]byte) (int, error)
-pkg bufio, method (ReadWriter) WriteByte(byte) error
-pkg bufio, method (ReadWriter) WriteRune(rune) (int, error)
+pkg bufio, method (ReadWriter) Write([]uint8) (int, error)
+pkg bufio, method (ReadWriter) WriteByte(uint8) error
+pkg bufio, method (ReadWriter) WriteRune(int32) (int, error)
 pkg bufio, method (ReadWriter) WriteString(string) (int, error)
 pkg bufio, type ReadWriter struct
 pkg bufio, type ReadWriter struct, embedded *Reader
@@ -133,73 +133,73 @@ pkg bufio, var ErrInvalidUnreadByte error
 pkg bufio, var ErrInvalidUnreadRune error
 pkg bufio, var ErrNegativeCount error
 pkg bytes, const MinRead ideal-int
-pkg bytes, func Compare([]byte) int
-pkg bytes, func Contains([]byte) bool
-pkg bytes, func Count([]byte) int
-pkg bytes, func Equal([]byte) bool
-pkg bytes, func EqualFold([]byte) bool
-pkg bytes, func Fields([]byte) [][]byte
-pkg bytes, func FieldsFunc([]byte, func(rune) bool) [][]byte
-pkg bytes, func HasPrefix([]byte) bool
-pkg bytes, func HasSuffix([]byte) bool
-pkg bytes, func Index([]byte) int
-pkg bytes, func IndexAny([]byte, string) int
-pkg bytes, func IndexByte([]byte, byte) int
-pkg bytes, func IndexFunc([]byte, func(rune) bool) int
-pkg bytes, func IndexRune([]byte, rune) int
-pkg bytes, func Join([][]byte, []byte) []byte
-pkg bytes, func LastIndex([]byte) int
-pkg bytes, func LastIndexAny([]byte, string) int
-pkg bytes, func LastIndexFunc([]byte, func(rune) bool) int
-pkg bytes, func Map(func(rune) rune, []byte) []byte
-pkg bytes, func NewBuffer([]byte) *Buffer
+pkg bytes, func Compare([]uint8, []uint8) int
+pkg bytes, func Contains([]uint8, []uint8) bool
+pkg bytes, func Count([]uint8, []uint8) int
+pkg bytes, func Equal([]uint8, []uint8) bool
+pkg bytes, func EqualFold([]uint8, []uint8) bool
+pkg bytes, func Fields([]uint8) [][]uint8
+pkg bytes, func FieldsFunc([]uint8, func(int32) bool) [][]uint8
+pkg bytes, func HasPrefix([]uint8, []uint8) bool
+pkg bytes, func HasSuffix([]uint8, []uint8) bool
+pkg bytes, func Index([]uint8, []uint8) int
+pkg bytes, func IndexAny([]uint8, string) int
+pkg bytes, func IndexByte([]uint8, uint8) int
+pkg bytes, func IndexFunc([]uint8, func(int32) bool) int
+pkg bytes, func IndexRune([]uint8, int32) int
+pkg bytes, func Join([][]uint8, []uint8) []uint8
+pkg bytes, func LastIndex([]uint8, []uint8) int
+pkg bytes, func LastIndexAny([]uint8, string) int
+pkg bytes, func LastIndexFunc([]uint8, func(int32) bool) int
+pkg bytes, func Map(func(int32) int32, []uint8) []uint8
+pkg bytes, func NewBuffer([]uint8) *Buffer
 pkg bytes, func NewBufferString(string) *Buffer
-pkg bytes, func NewReader([]byte) *Reader
-pkg bytes, func Repeat([]byte, int) []byte
-pkg bytes, func Replace([]byte, int) []byte
-pkg bytes, func Runes([]byte) []rune
-pkg bytes, func Split([]byte) [][]byte
-pkg bytes, func SplitAfter([]byte) [][]byte
-pkg bytes, func SplitAfterN([]byte, int) [][]byte
-pkg bytes, func SplitN([]byte, int) [][]byte
-pkg bytes, func Title([]byte) []byte
-pkg bytes, func ToLower([]byte) []byte
-pkg bytes, func ToLowerSpecial(unicode.SpecialCase, []byte) []byte
-pkg bytes, func ToTitle([]byte) []byte
-pkg bytes, func ToTitleSpecial(unicode.SpecialCase, []byte) []byte
-pkg bytes, func ToUpper([]byte) []byte
-pkg bytes, func ToUpperSpecial(unicode.SpecialCase, []byte) []byte
-pkg bytes, func Trim([]byte, string) []byte
-pkg bytes, func TrimFunc([]byte, func(rune) bool) []byte
-pkg bytes, func TrimLeft([]byte, string) []byte
-pkg bytes, func TrimLeftFunc([]byte, func(rune) bool) []byte
-pkg bytes, func TrimRight([]byte, string) []byte
-pkg bytes, func TrimRightFunc([]byte, func(rune) bool) []byte
-pkg bytes, func TrimSpace([]byte) []byte
-pkg bytes, method (*Buffer) Bytes() []byte
+pkg bytes, func NewReader([]uint8) *Reader
+pkg bytes, func Repeat([]uint8, int) []uint8
+pkg bytes, func Replace([]uint8, []uint8, []uint8, int) []uint8
+pkg bytes, func Runes([]uint8) []int32
+pkg bytes, func Split([]uint8, []uint8) [][]uint8
+pkg bytes, func SplitAfter([]uint8, []uint8) [][]uint8
+pkg bytes, func SplitAfterN([]uint8, []uint8, int) [][]uint8
+pkg bytes, func SplitN([]uint8, []uint8, int) [][]uint8
+pkg bytes, func Title([]uint8) []uint8
+pkg bytes, func ToLower([]uint8) []uint8
+pkg bytes, func ToLowerSpecial(unicode.SpecialCase, []uint8) []uint8
+pkg bytes, func ToTitle([]uint8) []uint8
+pkg bytes, func ToTitleSpecial(unicode.SpecialCase, []uint8) []uint8
+pkg bytes, func ToUpper([]uint8) []uint8
+pkg bytes, func ToUpperSpecial(unicode.SpecialCase, []uint8) []uint8
+pkg bytes, func Trim([]uint8, string) []uint8
+pkg bytes, func TrimFunc([]uint8, func(int32) bool) []uint8
+pkg bytes, func TrimLeft([]uint8, string) []uint8
+pkg bytes, func TrimLeftFunc([]uint8, func(int32) bool) []uint8
+pkg bytes, func TrimRight([]uint8, string) []uint8
+pkg bytes, func TrimRightFunc([]uint8, func(int32) bool) []uint8
+pkg bytes, func TrimSpace([]uint8) []uint8
+pkg bytes, method (*Buffer) Bytes() []uint8
 pkg bytes, method (*Buffer) Len() int
-pkg bytes, method (*Buffer) Next(int) []byte
-pkg bytes, method (*Buffer) Read([]byte) (int, error)
-pkg bytes, method (*Buffer) ReadByte() (byte, error)
-pkg bytes, method (*Buffer) ReadBytes(byte) ([]byte, error)
+pkg bytes, method (*Buffer) Next(int) []uint8
+pkg bytes, method (*Buffer) Read([]uint8) (int, error)
+pkg bytes, method (*Buffer) ReadByte() (uint8, error)
+pkg bytes, method (*Buffer) ReadBytes(uint8) ([]uint8, error)
 pkg bytes, method (*Buffer) ReadFrom(io.Reader) (int64, error)
-pkg bytes, method (*Buffer) ReadRune() (rune, int, error)
-pkg bytes, method (*Buffer) ReadString(byte) (string, error)
+pkg bytes, method (*Buffer) ReadRune() (int32, int, error)
+pkg bytes, method (*Buffer) ReadString(uint8) (string, error)
 pkg bytes, method (*Buffer) Reset()
 pkg bytes, method (*Buffer) String() string
 pkg bytes, method (*Buffer) Truncate(int)
 pkg bytes, method (*Buffer) UnreadByte() error
 pkg bytes, method (*Buffer) UnreadRune() error
-pkg bytes, method (*Buffer) Write([]byte) (int, error)
-pkg bytes, method (*Buffer) WriteByte(byte) error
-pkg bytes, method (*Buffer) WriteRune(rune) (int, error)
+pkg bytes, method (*Buffer) Write([]uint8) (int, error)
+pkg bytes, method (*Buffer) WriteByte(uint8) error
+pkg bytes, method (*Buffer) WriteRune(int32) (int, error)
 pkg bytes, method (*Buffer) WriteString(string) (int, error)
 pkg bytes, method (*Buffer) WriteTo(io.Writer) (int64, error)
 pkg bytes, method (*Reader) Len() int
-pkg bytes, method (*Reader) Read([]byte) (int, error)
-pkg bytes, method (*Reader) ReadAt([]byte, int64) (int, error)
-pkg bytes, method (*Reader) ReadByte() (byte, error)
-pkg bytes, method (*Reader) ReadRune() (rune, int, error)
+pkg bytes, method (*Reader) Read([]uint8) (int, error)
+pkg bytes, method (*Reader) ReadAt([]uint8, int64) (int, error)
+pkg bytes, method (*Reader) ReadByte() (uint8, error)
+pkg bytes, method (*Reader) ReadRune() (int32, int, error)
 pkg bytes, method (*Reader) Seek(int64, int) (int64, error)
 pkg bytes, method (*Reader) UnreadByte() error
 pkg bytes, method (*Reader) UnreadRune() error
@@ -214,14 +214,14 @@ pkg compress/flate, const BestSpeed ideal-int
 pkg compress/flate, const DefaultCompression ideal-int
 pkg compress/flate, const NoCompression ideal-int
 pkg compress/flate, func NewReader(io.Reader) io.ReadCloser
-pkg compress/flate, func NewReaderDict(io.Reader, []byte) io.ReadCloser
+pkg compress/flate, func NewReaderDict(io.Reader, []uint8) io.ReadCloser
 pkg compress/flate, func NewWriter(io.Writer, int) (*Writer, error)
-pkg compress/flate, func NewWriterDict(io.Writer, int, []byte) (*Writer, error)
+pkg compress/flate, func NewWriterDict(io.Writer, int, []uint8) (*Writer, error)
 pkg compress/flate, method (*ReadError) Error() string
 pkg compress/flate, method (*WriteError) Error() string
 pkg compress/flate, method (*Writer) Close() error
 pkg compress/flate, method (*Writer) Flush() error
-pkg compress/flate, method (*Writer) Write([]byte) (int, error)
+pkg compress/flate, method (*Writer) Write([]uint8) (int, error)
 pkg compress/flate, method (CorruptInputError) Error() string
 pkg compress/flate, method (InternalError) Error() string
 pkg compress/flate, type CorruptInputError int64
@@ -230,8 +230,8 @@ pkg compress/flate, type ReadError struct
 pkg compress/flate, type ReadError struct, Err error
 pkg compress/flate, type ReadError struct, Offset int64
 pkg compress/flate, type Reader interface { Read, ReadByte }
-pkg compress/flate, type Reader interface, Read([]byte) (int, error)
-pkg compress/flate, type Reader interface, ReadByte() (byte, error)
+pkg compress/flate, type Reader interface, Read([]uint8) (int, error)
+pkg compress/flate, type Reader interface, ReadByte() (uint8, error)
 pkg compress/flate, type WriteError struct
 pkg compress/flate, type WriteError struct, Err error
 pkg compress/flate, type WriteError struct, Offset int64
@@ -244,15 +244,15 @@ pkg compress/gzip, func NewReader(io.Reader) (*Reader, error)
 pkg compress/gzip, func NewWriter(io.Writer) *Writer
 pkg compress/gzip, func NewWriterLevel(io.Writer, int) (*Writer, error)
 pkg compress/gzip, method (*Reader) Close() error
-pkg compress/gzip, method (*Reader) Read([]byte) (int, error)
+pkg compress/gzip, method (*Reader) Read([]uint8) (int, error)
 pkg compress/gzip, method (*Writer) Close() error
-pkg compress/gzip, method (*Writer) Write([]byte) (int, error)
+pkg compress/gzip, method (*Writer) Write([]uint8) (int, error)
 pkg compress/gzip, type Header struct
 pkg compress/gzip, type Header struct, Comment string
-pkg compress/gzip, type Header struct, Extra []byte
+pkg compress/gzip, type Header struct, Extra []uint8
 pkg compress/gzip, type Header struct, ModTime time.Time
 pkg compress/gzip, type Header struct, Name string
-pkg compress/gzip, type Header struct, OS byte
+pkg compress/gzip, type Header struct, OS uint8
 pkg compress/gzip, type Reader struct
 pkg compress/gzip, type Reader struct, embedded Header
 pkg compress/gzip, type Writer struct
@@ -269,13 +269,13 @@ pkg compress/zlib, const BestSpeed ideal-int
 pkg compress/zlib, const DefaultCompression ideal-int
 pkg compress/zlib, const NoCompression ideal-int
 pkg compress/zlib, func NewReader(io.Reader) (io.ReadCloser, error)
-pkg compress/zlib, func NewReaderDict(io.Reader, []byte) (io.ReadCloser, error)
+pkg compress/zlib, func NewReaderDict(io.Reader, []uint8) (io.ReadCloser, error)
 pkg compress/zlib, func NewWriter(io.Writer) *Writer
 pkg compress/zlib, func NewWriterLevel(io.Writer, int) (*Writer, error)
-pkg compress/zlib, func NewWriterLevelDict(io.Writer, int, []byte) (*Writer, error)
+pkg compress/zlib, func NewWriterLevelDict(io.Writer, int, []uint8) (*Writer, error)
 pkg compress/zlib, method (*Writer) Close() error
 pkg compress/zlib, method (*Writer) Flush() error
-pkg compress/zlib, method (*Writer) Write([]byte) (int, error)
+pkg compress/zlib, method (*Writer) Write([]uint8) (int, error)
 pkg compress/zlib, type Writer struct
 pkg compress/zlib, var ErrChecksum error
 pkg compress/zlib, var ErrDictionary error
@@ -286,10 +286,10 @@ pkg container/heap, func Push(Interface, interface{})
 pkg container/heap, func Remove(Interface, int) interface{}
 pkg container/heap, type Interface interface { Len, Less, Pop, Push, Swap }
 pkg container/heap, type Interface interface, Len() int
-pkg container/heap, type Interface interface, Less(int) bool
+pkg container/heap, type Interface interface, Less(int, int) bool
 pkg container/heap, type Interface interface, Pop() interface{}
 pkg container/heap, type Interface interface, Push(interface{})
-pkg container/heap, type Interface interface, Swap(int)
+pkg container/heap, type Interface interface, Swap(int, int)
 pkg container/list, func New() *List
 pkg container/list, method (*Element) Next() *Element
 pkg container/list, method (*Element) Prev() *Element
@@ -335,27 +335,27 @@ pkg crypto, method (Hash) Size() int
 pkg crypto, type Hash uint
 pkg crypto, type PrivateKey interface {}
 pkg crypto/aes, const BlockSize ideal-int
-pkg crypto/aes, func NewCipher([]byte) (cipher.Block, error)
+pkg crypto/aes, func NewCipher([]uint8) (cipher.Block, error)
 pkg crypto/aes, method (KeySizeError) Error() string
 pkg crypto/aes, type KeySizeError int
-pkg crypto/cipher, func NewCBCDecrypter(Block, []byte) BlockMode
-pkg crypto/cipher, func NewCBCEncrypter(Block, []byte) BlockMode
-pkg crypto/cipher, func NewCFBDecrypter(Block, []byte) Stream
-pkg crypto/cipher, func NewCFBEncrypter(Block, []byte) Stream
-pkg crypto/cipher, func NewCTR(Block, []byte) Stream
-pkg crypto/cipher, func NewOFB(Block, []byte) Stream
-pkg crypto/cipher, method (StreamReader) Read([]byte) (int, error)
+pkg crypto/cipher, func NewCBCDecrypter(Block, []uint8) BlockMode
+pkg crypto/cipher, func NewCBCEncrypter(Block, []uint8) BlockMode
+pkg crypto/cipher, func NewCFBDecrypter(Block, []uint8) Stream
+pkg crypto/cipher, func NewCFBEncrypter(Block, []uint8) Stream
+pkg crypto/cipher, func NewCTR(Block, []uint8) Stream
+pkg crypto/cipher, func NewOFB(Block, []uint8) Stream
+pkg crypto/cipher, method (StreamReader) Read([]uint8) (int, error)
 pkg crypto/cipher, method (StreamWriter) Close() error
-pkg crypto/cipher, method (StreamWriter) Write([]byte) (int, error)
+pkg crypto/cipher, method (StreamWriter) Write([]uint8) (int, error)
 pkg crypto/cipher, type Block interface { BlockSize, Decrypt, Encrypt }
 pkg crypto/cipher, type Block interface, BlockSize() int
-pkg crypto/cipher, type Block interface, Decrypt([]byte)
-pkg crypto/cipher, type Block interface, Encrypt([]byte)
+pkg crypto/cipher, type Block interface, Decrypt([]uint8, []uint8)
+pkg crypto/cipher, type Block interface, Encrypt([]uint8, []uint8)
 pkg crypto/cipher, type BlockMode interface { BlockSize, CryptBlocks }
 pkg crypto/cipher, type BlockMode interface, BlockSize() int
-pkg crypto/cipher, type BlockMode interface, CryptBlocks([]byte)
+pkg crypto/cipher, type BlockMode interface, CryptBlocks([]uint8, []uint8)
 pkg crypto/cipher, type Stream interface { XORKeyStream }
-pkg crypto/cipher, type Stream interface, XORKeyStream([]byte)
+pkg crypto/cipher, type Stream interface, XORKeyStream([]uint8, []uint8)
 pkg crypto/cipher, type StreamReader struct
 pkg crypto/cipher, type StreamReader struct, R io.Reader
 pkg crypto/cipher, type StreamReader struct, S Stream
@@ -364,8 +364,8 @@ pkg crypto/cipher, type StreamWriter struct, Err error
 pkg crypto/cipher, type StreamWriter struct, S Stream
 pkg crypto/cipher, type StreamWriter struct, W io.Writer
 pkg crypto/des, const BlockSize ideal-int
-pkg crypto/des, func NewCipher([]byte) (cipher.Block, error)
-pkg crypto/des, func NewTripleDESCipher([]byte) (cipher.Block, error)
+pkg crypto/des, func NewCipher([]uint8) (cipher.Block, error)
+pkg crypto/des, func NewTripleDESCipher([]uint8) (cipher.Block, error)
 pkg crypto/des, method (KeySizeError) Error() string
 pkg crypto/des, type KeySizeError int
 pkg crypto/dsa, const L1024N160 ParameterSizes
@@ -374,8 +374,8 @@ pkg crypto/dsa, const L2048N256 ParameterSizes
 pkg crypto/dsa, const L3072N256 ParameterSizes
 pkg crypto/dsa, func GenerateKey(*PrivateKey, io.Reader) error
 pkg crypto/dsa, func GenerateParameters(*Parameters, io.Reader, ParameterSizes) error
-pkg crypto/dsa, func Sign(io.Reader, *PrivateKey, []byte) (*big.Int, error)
-pkg crypto/dsa, func Verify(*PublicKey, []byte, *big.Int) bool
+pkg crypto/dsa, func Sign(io.Reader, *PrivateKey, []uint8) (*big.Int, *big.Int, error)
+pkg crypto/dsa, func Verify(*PublicKey, []uint8, *big.Int, *big.Int) bool
 pkg crypto/dsa, type ParameterSizes int
 pkg crypto/dsa, type Parameters struct
 pkg crypto/dsa, type Parameters struct, G *big.Int
@@ -389,8 +389,8 @@ pkg crypto/dsa, type PublicKey struct, Y *big.Int
 pkg crypto/dsa, type PublicKey struct, embedded Parameters
 pkg crypto/dsa, var ErrInvalidPublicKey error
 pkg crypto/ecdsa, func GenerateKey(elliptic.Curve, io.Reader) (*PrivateKey, error)
-pkg crypto/ecdsa, func Sign(io.Reader, *PrivateKey, []byte) (*big.Int, error)
-pkg crypto/ecdsa, func Verify(*PublicKey, []byte, *big.Int) bool
+pkg crypto/ecdsa, func Sign(io.Reader, *PrivateKey, []uint8) (*big.Int, *big.Int, error)
+pkg crypto/ecdsa, func Verify(*PublicKey, []uint8, *big.Int, *big.Int) bool
 pkg crypto/ecdsa, type PrivateKey struct
 pkg crypto/ecdsa, type PrivateKey struct, D *big.Int
 pkg crypto/ecdsa, type PrivateKey struct, embedded PublicKey
@@ -398,26 +398,26 @@ pkg crypto/ecdsa, type PublicKey struct
 pkg crypto/ecdsa, type PublicKey struct, X *big.Int
 pkg crypto/ecdsa, type PublicKey struct, Y *big.Int
 pkg crypto/ecdsa, type PublicKey struct, embedded elliptic.Curve
-pkg crypto/elliptic, func GenerateKey(Curve, io.Reader) ([]byte, *big.Int, error)
-pkg crypto/elliptic, func Marshal(Curve, *big.Int) []byte
+pkg crypto/elliptic, func GenerateKey(Curve, io.Reader) ([]uint8, *big.Int, *big.Int, error)
+pkg crypto/elliptic, func Marshal(Curve, *big.Int, *big.Int) []uint8
 pkg crypto/elliptic, func P224() Curve
 pkg crypto/elliptic, func P256() Curve
 pkg crypto/elliptic, func P384() Curve
 pkg crypto/elliptic, func P521() Curve
-pkg crypto/elliptic, func Unmarshal(Curve, []byte) *big.Int
-pkg crypto/elliptic, method (*CurveParams) Add(*big.Int) (*big.Int, *big.Int)
-pkg crypto/elliptic, method (*CurveParams) Double(*big.Int) (*big.Int, *big.Int)
-pkg crypto/elliptic, method (*CurveParams) IsOnCurve(*big.Int) bool
+pkg crypto/elliptic, func Unmarshal(Curve, []uint8) (*big.Int, *big.Int)
+pkg crypto/elliptic, method (*CurveParams) Add(*big.Int, *big.Int, *big.Int, *big.Int) (*big.Int, *big.Int)
+pkg crypto/elliptic, method (*CurveParams) Double(*big.Int, *big.Int) (*big.Int, *big.Int)
+pkg crypto/elliptic, method (*CurveParams) IsOnCurve(*big.Int, *big.Int) bool
 pkg crypto/elliptic, method (*CurveParams) Params() *CurveParams
-pkg crypto/elliptic, method (*CurveParams) ScalarBaseMult([]byte) (*big.Int, *big.Int)
-pkg crypto/elliptic, method (*CurveParams) ScalarMult(*big.Int, []byte) (*big.Int, *big.Int)
+pkg crypto/elliptic, method (*CurveParams) ScalarBaseMult([]uint8) (*big.Int, *big.Int)
+pkg crypto/elliptic, method (*CurveParams) ScalarMult(*big.Int, *big.Int, []uint8) (*big.Int, *big.Int)
 pkg crypto/elliptic, type Curve interface { Add, Double, IsOnCurve, Params, ScalarBaseMult, ScalarMult }
-pkg crypto/elliptic, type Curve interface, Add(*big.Int) *big.Int
-pkg crypto/elliptic, type Curve interface, Double(*big.Int) *big.Int
-pkg crypto/elliptic, type Curve interface, IsOnCurve(*big.Int) bool
+pkg crypto/elliptic, type Curve interface, Add(*big.Int, *big.Int, *big.Int, *big.Int) (*big.Int, *big.Int)
+pkg crypto/elliptic, type Curve interface, Double(*big.Int, *big.Int) (*big.Int, *big.Int)
+pkg crypto/elliptic, type Curve interface, IsOnCurve(*big.Int, *big.Int) bool
 pkg crypto/elliptic, type Curve interface, Params() *CurveParams
-pkg crypto/elliptic, type Curve interface, ScalarBaseMult([]byte) *big.Int
-pkg crypto/elliptic, type Curve interface, ScalarMult(*big.Int, []byte) *big.Int
+pkg crypto/elliptic, type Curve interface, ScalarBaseMult([]uint8) (*big.Int, *big.Int)
+pkg crypto/elliptic, type Curve interface, ScalarMult(*big.Int, *big.Int, []uint8) (*big.Int, *big.Int)
 pkg crypto/elliptic, type CurveParams struct
 pkg crypto/elliptic, type CurveParams struct, B *big.Int
 pkg crypto/elliptic, type CurveParams struct, BitSize int
@@ -425,29 +425,29 @@ pkg crypto/elliptic, type CurveParams struct, Gx *big.Int
 pkg crypto/elliptic, type CurveParams struct, Gy *big.Int
 pkg crypto/elliptic, type CurveParams struct, N *big.Int
 pkg crypto/elliptic, type CurveParams struct, P *big.Int
-pkg crypto/hmac, func New(func() hash.Hash, []byte) hash.Hash
+pkg crypto/hmac, func New(func() hash.Hash, []uint8) hash.Hash
 pkg crypto/md5, const BlockSize ideal-int
 pkg crypto/md5, const Size ideal-int
 pkg crypto/md5, func New() hash.Hash
 pkg crypto/rand, func Int(io.Reader, *big.Int) (*big.Int, error)
 pkg crypto/rand, func Prime(io.Reader, int) (*big.Int, error)
-pkg crypto/rand, func Read([]byte) (int, error)
+pkg crypto/rand, func Read([]uint8) (int, error)
 pkg crypto/rand, var Reader io.Reader
-pkg crypto/rc4, func NewCipher([]byte) (*Cipher, error)
+pkg crypto/rc4, func NewCipher([]uint8) (*Cipher, error)
 pkg crypto/rc4, method (*Cipher) Reset()
-pkg crypto/rc4, method (*Cipher) XORKeyStream([]byte)
+pkg crypto/rc4, method (*Cipher) XORKeyStream([]uint8, []uint8)
 pkg crypto/rc4, method (KeySizeError) Error() string
 pkg crypto/rc4, type Cipher struct
 pkg crypto/rc4, type KeySizeError int
-pkg crypto/rsa, func DecryptOAEP(hash.Hash, io.Reader, *PrivateKey, []byte, []byte) ([]byte, error)
-pkg crypto/rsa, func DecryptPKCS1v15(io.Reader, *PrivateKey, []byte) ([]byte, error)
-pkg crypto/rsa, func DecryptPKCS1v15SessionKey(io.Reader, *PrivateKey, []byte, []byte) error
-pkg crypto/rsa, func EncryptOAEP(hash.Hash, io.Reader, *PublicKey, []byte, []byte) ([]byte, error)
-pkg crypto/rsa, func EncryptPKCS1v15(io.Reader, *PublicKey, []byte) ([]byte, error)
+pkg crypto/rsa, func DecryptOAEP(hash.Hash, io.Reader, *PrivateKey, []uint8, []uint8) ([]uint8, error)
+pkg crypto/rsa, func DecryptPKCS1v15(io.Reader, *PrivateKey, []uint8) ([]uint8, error)
+pkg crypto/rsa, func DecryptPKCS1v15SessionKey(io.Reader, *PrivateKey, []uint8, []uint8) error
+pkg crypto/rsa, func EncryptOAEP(hash.Hash, io.Reader, *PublicKey, []uint8, []uint8) ([]uint8, error)
+pkg crypto/rsa, func EncryptPKCS1v15(io.Reader, *PublicKey, []uint8) ([]uint8, error)
 pkg crypto/rsa, func GenerateKey(io.Reader, int) (*PrivateKey, error)
 pkg crypto/rsa, func GenerateMultiPrimeKey(io.Reader, int, int) (*PrivateKey, error)
-pkg crypto/rsa, func SignPKCS1v15(io.Reader, *PrivateKey, crypto.Hash, []byte) ([]byte, error)
-pkg crypto/rsa, func VerifyPKCS1v15(*PublicKey, crypto.Hash, []byte, []byte) error
+pkg crypto/rsa, func SignPKCS1v15(io.Reader, *PrivateKey, crypto.Hash, []uint8) ([]uint8, error)
+pkg crypto/rsa, func VerifyPKCS1v15(*PublicKey, crypto.Hash, []uint8, []uint8) error
 pkg crypto/rsa, method (*PrivateKey) Precompute()
 pkg crypto/rsa, method (*PrivateKey) Validate() error
 pkg crypto/rsa, type CRTValue struct
@@ -483,11 +483,11 @@ pkg crypto/sha512, const Size ideal-int
 pkg crypto/sha512, const Size384 ideal-int
 pkg crypto/sha512, func New() hash.Hash
 pkg crypto/sha512, func New384() hash.Hash
-pkg crypto/subtle, func ConstantTimeByteEq(uint8) int
-pkg crypto/subtle, func ConstantTimeCompare([]byte) int
-pkg crypto/subtle, func ConstantTimeCopy(int, []byte)
-pkg crypto/subtle, func ConstantTimeEq(int32) int
-pkg crypto/subtle, func ConstantTimeSelect(int) int
+pkg crypto/subtle, func ConstantTimeByteEq(uint8, uint8) int
+pkg crypto/subtle, func ConstantTimeCompare([]uint8, []uint8) int
+pkg crypto/subtle, func ConstantTimeCopy(int, []uint8, []uint8)
+pkg crypto/subtle, func ConstantTimeEq(int32, int32) int
+pkg crypto/subtle, func ConstantTimeSelect(int, int, int) int
 pkg crypto/tls, const NoClientCert ClientAuthType
 pkg crypto/tls, const RequestClientCert ClientAuthType
 pkg crypto/tls, const RequireAndVerifyClientCert ClientAuthType
@@ -500,29 +500,29 @@ pkg crypto/tls, const TLS_RSA_WITH_AES_128_CBC_SHA uint16
 pkg crypto/tls, const TLS_RSA_WITH_RC4_128_SHA uint16
 pkg crypto/tls, const VerifyClientCertIfGiven ClientAuthType
 pkg crypto/tls, func Client(net.Conn, *Config) *Conn
-pkg crypto/tls, func Dial(string, *Config) (*Conn, error)
-pkg crypto/tls, func Listen(string, *Config) (net.Listener, error)
-pkg crypto/tls, func LoadX509KeyPair(string) (Certificate, error)
+pkg crypto/tls, func Dial(string, string, *Config) (*Conn, error)
+pkg crypto/tls, func Listen(string, string, *Config) (net.Listener, error)
+pkg crypto/tls, func LoadX509KeyPair(string, string) (Certificate, error)
 pkg crypto/tls, func NewListener(net.Listener, *Config) net.Listener
 pkg crypto/tls, func Server(net.Conn, *Config) *Conn
-pkg crypto/tls, func X509KeyPair([]byte) (Certificate, error)
+pkg crypto/tls, func X509KeyPair([]uint8, []uint8) (Certificate, error)
 pkg crypto/tls, method (*Config) BuildNameToCertificate()
 pkg crypto/tls, method (*Conn) Close() error
 pkg crypto/tls, method (*Conn) ConnectionState() ConnectionState
 pkg crypto/tls, method (*Conn) Handshake() error
 pkg crypto/tls, method (*Conn) LocalAddr() net.Addr
-pkg crypto/tls, method (*Conn) OCSPResponse() []byte
-pkg crypto/tls, method (*Conn) Read([]byte) (int, error)
+pkg crypto/tls, method (*Conn) OCSPResponse() []uint8
+pkg crypto/tls, method (*Conn) Read([]uint8) (int, error)
 pkg crypto/tls, method (*Conn) RemoteAddr() net.Addr
 pkg crypto/tls, method (*Conn) SetDeadline(time.Time) error
 pkg crypto/tls, method (*Conn) SetReadDeadline(time.Time) error
 pkg crypto/tls, method (*Conn) SetWriteDeadline(time.Time) error
 pkg crypto/tls, method (*Conn) VerifyHostname(string) error
-pkg crypto/tls, method (*Conn) Write([]byte) (int, error)
+pkg crypto/tls, method (*Conn) Write([]uint8) (int, error)
 pkg crypto/tls, type Certificate struct
-pkg crypto/tls, type Certificate struct, Certificate [][]byte
+pkg crypto/tls, type Certificate struct, Certificate [][]uint8
 pkg crypto/tls, type Certificate struct, Leaf *x509.Certificate
-pkg crypto/tls, type Certificate struct, OCSPStaple []byte
+pkg crypto/tls, type Certificate struct, OCSPStaple []uint8
 pkg crypto/tls, type Certificate struct, PrivateKey crypto.PrivateKey
 pkg crypto/tls, type ClientAuthType int
 pkg crypto/tls, type Config struct
@@ -578,24 +578,24 @@ pkg crypto/x509, const SHA512WithRSA SignatureAlgorithm
 pkg crypto/x509, const TooManyIntermediates InvalidReason
 pkg crypto/x509, const UnknownPublicKeyAlgorithm PublicKeyAlgorithm
 pkg crypto/x509, const UnknownSignatureAlgorithm SignatureAlgorithm
-pkg crypto/x509, func CreateCertificate(io.Reader, *Certificate, interface{}, interface{}) ([]byte, error)
-pkg crypto/x509, func MarshalPKCS1PrivateKey(*rsa.PrivateKey) []byte
-pkg crypto/x509, func MarshalPKIXPublicKey(interface{}) ([]byte, error)
+pkg crypto/x509, func CreateCertificate(io.Reader, *Certificate, *Certificate, interface{}, interface{}) ([]uint8, error)
+pkg crypto/x509, func MarshalPKCS1PrivateKey(*rsa.PrivateKey) []uint8
+pkg crypto/x509, func MarshalPKIXPublicKey(interface{}) ([]uint8, error)
 pkg crypto/x509, func NewCertPool() *CertPool
-pkg crypto/x509, func ParseCRL([]byte) (*pkix.CertificateList, error)
-pkg crypto/x509, func ParseCertificate([]byte) (*Certificate, error)
-pkg crypto/x509, func ParseCertificates([]byte) ([]*Certificate, error)
-pkg crypto/x509, func ParseDERCRL([]byte) (*pkix.CertificateList, error)
-pkg crypto/x509, func ParsePKCS1PrivateKey([]byte) (*rsa.PrivateKey, error)
-pkg crypto/x509, func ParsePKCS8PrivateKey([]byte) (interface{}, error)
-pkg crypto/x509, func ParsePKIXPublicKey([]byte) (interface{}, error)
+pkg crypto/x509, func ParseCRL([]uint8) (*pkix.CertificateList, error)
+pkg crypto/x509, func ParseCertificate([]uint8) (*Certificate, error)
+pkg crypto/x509, func ParseCertificates([]uint8) ([]*Certificate, error)
+pkg crypto/x509, func ParseDERCRL([]uint8) (*pkix.CertificateList, error)
+pkg crypto/x509, func ParsePKCS1PrivateKey([]uint8) (*rsa.PrivateKey, error)
+pkg crypto/x509, func ParsePKCS8PrivateKey([]uint8) (interface{}, error)
+pkg crypto/x509, func ParsePKIXPublicKey([]uint8) (interface{}, error)
 pkg crypto/x509, method (*CertPool) AddCert(*Certificate)
-pkg crypto/x509, method (*CertPool) AppendCertsFromPEM([]byte) bool
-pkg crypto/x509, method (*CertPool) Subjects() [][]byte
+pkg crypto/x509, method (*CertPool) AppendCertsFromPEM([]uint8) bool
+pkg crypto/x509, method (*CertPool) Subjects() [][]uint8
 pkg crypto/x509, method (*Certificate) CheckCRLSignature(*pkix.CertificateList) error
-pkg crypto/x509, method (*Certificate) CheckSignature(SignatureAlgorithm, []byte) error
+pkg crypto/x509, method (*Certificate) CheckSignature(SignatureAlgorithm, []uint8, []uint8) error
 pkg crypto/x509, method (*Certificate) CheckSignatureFrom(*Certificate) error
-pkg crypto/x509, method (*Certificate) CreateCRL(io.Reader, interface{}, []pkix.RevokedCertificate, time.Time) ([]byte, error)
+pkg crypto/x509, method (*Certificate) CreateCRL(io.Reader, interface{}, []pkix.RevokedCertificate, time.Time, time.Time) ([]uint8, error)
 pkg crypto/x509, method (*Certificate) Equal(*Certificate) bool
 pkg crypto/x509, method (*Certificate) Verify(VerifyOptions) ([][]*Certificate, error)
 pkg crypto/x509, method (*Certificate) VerifyHostname(string) error
@@ -606,7 +606,7 @@ pkg crypto/x509, method (UnhandledCriticalExtension) Error() string
 pkg crypto/x509, method (UnknownAuthorityError) Error() string
 pkg crypto/x509, type CertPool struct
 pkg crypto/x509, type Certificate struct
-pkg crypto/x509, type Certificate struct, AuthorityKeyId []byte
+pkg crypto/x509, type Certificate struct, AuthorityKeyId []uint8
 pkg crypto/x509, type Certificate struct, BasicConstraintsValid bool
 pkg crypto/x509, type Certificate struct, DNSNames []string
 pkg crypto/x509, type Certificate struct, EmailAddresses []string
@@ -622,16 +622,16 @@ pkg crypto/x509, type Certificate struct, PermittedDNSDomainsCritical bool
 pkg crypto/x509, type Certificate struct, PolicyIdentifiers []asn1.ObjectIdentifier
 pkg crypto/x509, type Certificate struct, PublicKey interface{}
 pkg crypto/x509, type Certificate struct, PublicKeyAlgorithm PublicKeyAlgorithm
-pkg crypto/x509, type Certificate struct, Raw []byte
-pkg crypto/x509, type Certificate struct, RawIssuer []byte
-pkg crypto/x509, type Certificate struct, RawSubject []byte
-pkg crypto/x509, type Certificate struct, RawSubjectPublicKeyInfo []byte
-pkg crypto/x509, type Certificate struct, RawTBSCertificate []byte
+pkg crypto/x509, type Certificate struct, Raw []uint8
+pkg crypto/x509, type Certificate struct, RawIssuer []uint8
+pkg crypto/x509, type Certificate struct, RawSubject []uint8
+pkg crypto/x509, type Certificate struct, RawSubjectPublicKeyInfo []uint8
+pkg crypto/x509, type Certificate struct, RawTBSCertificate []uint8
 pkg crypto/x509, type Certificate struct, SerialNumber *big.Int
-pkg crypto/x509, type Certificate struct, Signature []byte
+pkg crypto/x509, type Certificate struct, Signature []uint8
 pkg crypto/x509, type Certificate struct, SignatureAlgorithm SignatureAlgorithm
 pkg crypto/x509, type Certificate struct, Subject pkix.Name
-pkg crypto/x509, type Certificate struct, SubjectKeyId []byte
+pkg crypto/x509, type Certificate struct, SubjectKeyId []uint8
 pkg crypto/x509, type Certificate struct, UnknownExtKeyUsage []asn1.ObjectIdentifier
 pkg crypto/x509, type Certificate struct, Version int
 pkg crypto/x509, type CertificateInvalidError struct
@@ -670,7 +670,7 @@ pkg crypto/x509/pkix, type CertificateList struct, TBSCertList TBSCertificateLis
 pkg crypto/x509/pkix, type Extension struct
 pkg crypto/x509/pkix, type Extension struct, Critical bool
 pkg crypto/x509/pkix, type Extension struct, Id asn1.ObjectIdentifier
-pkg crypto/x509/pkix, type Extension struct, Value []byte
+pkg crypto/x509/pkix, type Extension struct, Value []uint8
 pkg crypto/x509/pkix, type Name struct
 pkg crypto/x509/pkix, type Name struct, CommonName string
 pkg crypto/x509/pkix, type Name struct, Country []string
@@ -697,7 +697,7 @@ pkg crypto/x509/pkix, type TBSCertificateList struct, RevokedCertificates []Revo
 pkg crypto/x509/pkix, type TBSCertificateList struct, Signature AlgorithmIdentifier
 pkg crypto/x509/pkix, type TBSCertificateList struct, ThisUpdate time.Time
 pkg crypto/x509/pkix, type TBSCertificateList struct, Version int
-pkg database/sql, func Open(string) (*DB, error)
+pkg database/sql, func Open(string, string) (*DB, error)
 pkg database/sql, func Register(string, driver.Driver)
 pkg database/sql, method (*DB) Begin() (*Tx, error)
 pkg database/sql, method (*DB) Close() error
@@ -744,7 +744,7 @@ pkg database/sql, type NullInt64 struct, Valid bool
 pkg database/sql, type NullString struct
 pkg database/sql, type NullString struct, String string
 pkg database/sql, type NullString struct, Valid bool
-pkg database/sql, type RawBytes []byte
+pkg database/sql, type RawBytes []uint8
 pkg database/sql, type Result interface { LastInsertId, RowsAffected }
 pkg database/sql, type Result interface, LastInsertId() (int64, error)
 pkg database/sql, type Result interface, RowsAffected() (int64, error)
@@ -932,7 +932,7 @@ pkg debug/dwarf, const TagVariant Tag
 pkg debug/dwarf, const TagVariantPart Tag
 pkg debug/dwarf, const TagVolatileType Tag
 pkg debug/dwarf, const TagWithStmt Tag
-pkg debug/dwarf, func New([]byte) (*Data, error)
+pkg debug/dwarf, func New([]uint8, []uint8, []uint8, []uint8, []uint8, []uint8, []uint8, []uint8) (*Data, error)
 pkg debug/dwarf, method (*AddrType) Basic() *BasicType
 pkg debug/dwarf, method (*AddrType) Common() *CommonType
 pkg debug/dwarf, method (*AddrType) Size() int64
@@ -1579,8 +1579,8 @@ pkg debug/elf, const Sym32Size ideal-int
 pkg debug/elf, const Sym64Size ideal-int
 pkg debug/elf, func NewFile(io.ReaderAt) (*File, error)
 pkg debug/elf, func Open(string) (*File, error)
-pkg debug/elf, func R_INFO(uint32) uint64
-pkg debug/elf, func R_INFO32(uint32) uint32
+pkg debug/elf, func R_INFO(uint32, uint32) uint64
+pkg debug/elf, func R_INFO32(uint32, uint32) uint32
 pkg debug/elf, func R_SYM32(uint32) uint32
 pkg debug/elf, func R_SYM64(uint64) uint32
 pkg debug/elf, func R_TYPE32(uint32) uint32
@@ -1598,7 +1598,7 @@ pkg debug/elf, method (*File) SectionByType(SectionType) *Section
 pkg debug/elf, method (*File) Symbols() ([]Symbol, error)
 pkg debug/elf, method (*FormatError) Error() string
 pkg debug/elf, method (*Prog) Open() io.ReadSeeker
-pkg debug/elf, method (*Section) Data() ([]byte, error)
+pkg debug/elf, method (*Section) Data() ([]uint8, error)
 pkg debug/elf, method (*Section) Open() io.ReadSeeker
 pkg debug/elf, method (Class) GoString() string
 pkg debug/elf, method (Class) String() string
@@ -1646,8 +1646,8 @@ pkg debug/elf, method (Type) GoString() string
 pkg debug/elf, method (Type) String() string
 pkg debug/elf, method (Version) GoString() string
 pkg debug/elf, method (Version) String() string
-pkg debug/elf, type Class byte
-pkg debug/elf, type Data byte
+pkg debug/elf, type Class uint8
+pkg debug/elf, type Data uint8
 pkg debug/elf, type Dyn32 struct
 pkg debug/elf, type Dyn32 struct, Tag int32
 pkg debug/elf, type Dyn32 struct, Val uint32
@@ -1674,7 +1674,7 @@ pkg debug/elf, type Header32 struct
 pkg debug/elf, type Header32 struct, Ehsize uint16
 pkg debug/elf, type Header32 struct, Entry uint32
 pkg debug/elf, type Header32 struct, Flags uint32
-pkg debug/elf, type Header32 struct, Ident [EI_NIDENT]byte
+pkg debug/elf, type Header32 struct, Ident [EI_NIDENT]uint8
 pkg debug/elf, type Header32 struct, Machine uint16
 pkg debug/elf, type Header32 struct, Phentsize uint16
 pkg debug/elf, type Header32 struct, Phnum uint16
@@ -1689,7 +1689,7 @@ pkg debug/elf, type Header64 struct
 pkg debug/elf, type Header64 struct, Ehsize uint16
 pkg debug/elf, type Header64 struct, Entry uint64
 pkg debug/elf, type Header64 struct, Flags uint32
-pkg debug/elf, type Header64 struct, Ident [EI_NIDENT]byte
+pkg debug/elf, type Header64 struct, Ident [EI_NIDENT]uint8
 pkg debug/elf, type Header64 struct, Machine uint16
 pkg debug/elf, type Header64 struct, Phentsize uint16
 pkg debug/elf, type Header64 struct, Phnum uint16
@@ -1706,7 +1706,7 @@ pkg debug/elf, type ImportedSymbol struct, Name string
 pkg debug/elf, type ImportedSymbol struct, Version string
 pkg debug/elf, type Machine uint16
 pkg debug/elf, type NType int
-pkg debug/elf, type OSABI byte
+pkg debug/elf, type OSABI uint8
 pkg debug/elf, type Prog struct
 pkg debug/elf, type Prog struct, embedded ProgHeader
 pkg debug/elf, type Prog struct, embedded io.ReaderAt
@@ -1816,16 +1816,16 @@ pkg debug/elf, type SymBind int
 pkg debug/elf, type SymType int
 pkg debug/elf, type SymVis int
 pkg debug/elf, type Symbol struct
-pkg debug/elf, type Symbol struct, Info byte
+pkg debug/elf, type Symbol struct, Info uint8
 pkg debug/elf, type Symbol struct, Name string
-pkg debug/elf, type Symbol struct, Other byte
+pkg debug/elf, type Symbol struct, Other uint8
 pkg debug/elf, type Symbol struct, Section SectionIndex
 pkg debug/elf, type Symbol struct, Size uint64
 pkg debug/elf, type Symbol struct, Value uint64
 pkg debug/elf, type Type uint16
-pkg debug/elf, type Version byte
-pkg debug/gosym, func NewLineTable([]byte, uint64) *LineTable
-pkg debug/gosym, func NewTable([]byte, *LineTable) (*Table, error)
+pkg debug/elf, type Version uint8
+pkg debug/gosym, func NewLineTable([]uint8, uint64) *LineTable
+pkg debug/gosym, func NewTable([]uint8, *LineTable) (*Table, error)
 pkg debug/gosym, method (*DecodingError) Error() string
 pkg debug/gosym, method (*LineTable) LineToPC(int, uint64) uint64
 pkg debug/gosym, method (*LineTable) PCToLine(uint64) int
@@ -1856,7 +1856,7 @@ pkg debug/gosym, type Func struct, Obj *Obj
 pkg debug/gosym, type Func struct, Params []*Sym
 pkg debug/gosym, type Func struct, embedded *Sym
 pkg debug/gosym, type LineTable struct
-pkg debug/gosym, type LineTable struct, Data []byte
+pkg debug/gosym, type LineTable struct, Data []uint8
 pkg debug/gosym, type LineTable struct, Line int
 pkg debug/gosym, type LineTable struct, PC uint64
 pkg debug/gosym, type Obj struct
@@ -1866,7 +1866,7 @@ pkg debug/gosym, type Sym struct
 pkg debug/gosym, type Sym struct, Func *Func
 pkg debug/gosym, type Sym struct, GoType uint64
 pkg debug/gosym, type Sym struct, Name string
-pkg debug/gosym, type Sym struct, Type byte
+pkg debug/gosym, type Sym struct, Type uint8
 pkg debug/gosym, type Sym struct, Value uint64
 pkg debug/gosym, type Table struct
 pkg debug/gosym, type Table struct, Files map[string]*Obj
@@ -1900,19 +1900,19 @@ pkg debug/macho, method (*File) ImportedSymbols() ([]string, error)
 pkg debug/macho, method (*File) Section(string) *Section
 pkg debug/macho, method (*File) Segment(string) *Segment
 pkg debug/macho, method (*FormatError) Error() string
-pkg debug/macho, method (*Section) Data() ([]byte, error)
+pkg debug/macho, method (*Section) Data() ([]uint8, error)
 pkg debug/macho, method (*Section) Open() io.ReadSeeker
-pkg debug/macho, method (*Segment) Data() ([]byte, error)
+pkg debug/macho, method (*Segment) Data() ([]uint8, error)
 pkg debug/macho, method (*Segment) Open() io.ReadSeeker
 pkg debug/macho, method (Cpu) GoString() string
 pkg debug/macho, method (Cpu) String() string
-pkg debug/macho, method (Dylib) Raw() []byte
-pkg debug/macho, method (Dysymtab) Raw() []byte
-pkg debug/macho, method (LoadBytes) Raw() []byte
+pkg debug/macho, method (Dylib) Raw() []uint8
+pkg debug/macho, method (Dysymtab) Raw() []uint8
+pkg debug/macho, method (LoadBytes) Raw() []uint8
 pkg debug/macho, method (LoadCmd) GoString() string
 pkg debug/macho, method (LoadCmd) String() string
-pkg debug/macho, method (Segment) Raw() []byte
-pkg debug/macho, method (Symtab) Raw() []byte
+pkg debug/macho, method (Segment) Raw() []uint8
+pkg debug/macho, method (Symtab) Raw() []uint8
 pkg debug/macho, type Cpu uint32
 pkg debug/macho, type Dylib struct
 pkg debug/macho, type Dylib struct, CompatVersion uint32
@@ -1969,8 +1969,8 @@ pkg debug/macho, type FileHeader struct, SubCpu uint32
 pkg debug/macho, type FileHeader struct, Type Type
 pkg debug/macho, type FormatError struct
 pkg debug/macho, type Load interface { Raw }
-pkg debug/macho, type Load interface, Raw() []byte
-pkg debug/macho, type LoadBytes []byte
+pkg debug/macho, type Load interface, Raw() []uint8
+pkg debug/macho, type LoadBytes []uint8
 pkg debug/macho, type LoadCmd uint32
 pkg debug/macho, type Nlist32 struct
 pkg debug/macho, type Nlist32 struct, Desc uint16
@@ -2030,26 +2030,26 @@ pkg debug/macho, type Section32 struct
 pkg debug/macho, type Section32 struct, Addr uint32
 pkg debug/macho, type Section32 struct, Align uint32
 pkg debug/macho, type Section32 struct, Flags uint32
-pkg debug/macho, type Section32 struct, Name [16]byte
+pkg debug/macho, type Section32 struct, Name [16]uint8
 pkg debug/macho, type Section32 struct, Nreloc uint32
 pkg debug/macho, type Section32 struct, Offset uint32
 pkg debug/macho, type Section32 struct, Reloff uint32
 pkg debug/macho, type Section32 struct, Reserve1 uint32
 pkg debug/macho, type Section32 struct, Reserve2 uint32
-pkg debug/macho, type Section32 struct, Seg [16]byte
+pkg debug/macho, type Section32 struct, Seg [16]uint8
 pkg debug/macho, type Section32 struct, Size uint32
 pkg debug/macho, type Section64 struct
 pkg debug/macho, type Section64 struct, Addr uint64
 pkg debug/macho, type Section64 struct, Align uint32
 pkg debug/macho, type Section64 struct, Flags uint32
-pkg debug/macho, type Section64 struct, Name [16]byte
+pkg debug/macho, type Section64 struct, Name [16]uint8
 pkg debug/macho, type Section64 struct, Nreloc uint32
 pkg debug/macho, type Section64 struct, Offset uint32
 pkg debug/macho, type Section64 struct, Reloff uint32
 pkg debug/macho, type Section64 struct, Reserve1 uint32
 pkg debug/macho, type Section64 struct, Reserve2 uint32
 pkg debug/macho, type Section64 struct, Reserve3 uint32
-pkg debug/macho, type Section64 struct, Seg [16]byte
+pkg debug/macho, type Section64 struct, Seg [16]uint8
 pkg debug/macho, type Section64 struct, Size uint64
 pkg debug/macho, type SectionHeader struct
 pkg debug/macho, type SectionHeader struct, Addr uint64
@@ -2073,7 +2073,7 @@ pkg debug/macho, type Segment32 struct, Flag uint32
 pkg debug/macho, type Segment32 struct, Len uint32
 pkg debug/macho, type Segment32 struct, Maxprot uint32
 pkg debug/macho, type Segment32 struct, Memsz uint32
-pkg debug/macho, type Segment32 struct, Name [16]byte
+pkg debug/macho, type Segment32 struct, Name [16]uint8
 pkg debug/macho, type Segment32 struct, Nsect uint32
 pkg debug/macho, type Segment32 struct, Offset uint32
 pkg debug/macho, type Segment32 struct, Prot uint32
@@ -2085,7 +2085,7 @@ pkg debug/macho, type Segment64 struct, Flag uint32
 pkg debug/macho, type Segment64 struct, Len uint32
 pkg debug/macho, type Segment64 struct, Maxprot uint32
 pkg debug/macho, type Segment64 struct, Memsz uint64
-pkg debug/macho, type Segment64 struct, Name [16]byte
+pkg debug/macho, type Segment64 struct, Name [16]uint8
 pkg debug/macho, type Segment64 struct, Nsect uint32
 pkg debug/macho, type Segment64 struct, Offset uint64
 pkg debug/macho, type Segment64 struct, Prot uint32
@@ -2152,7 +2152,7 @@ pkg debug/pe, method (*File) ImportedLibraries() ([]string, error)
 pkg debug/pe, method (*File) ImportedSymbols() ([]string, error)
 pkg debug/pe, method (*File) Section(string) *Section
 pkg debug/pe, method (*FormatError) Error() string
-pkg debug/pe, method (*Section) Data() ([]byte, error)
+pkg debug/pe, method (*Section) Data() ([]uint8, error)
 pkg debug/pe, method (*Section) Open() io.ReadSeeker
 pkg debug/pe, type File struct
 pkg debug/pe, type File struct, Sections []*Section
@@ -2197,32 +2197,32 @@ pkg debug/pe, type SectionHeader32 struct, PointerToRelocations uint32
 pkg debug/pe, type SectionHeader32 struct, SizeOfRawData uint32
 pkg debug/pe, type SectionHeader32 struct, VirtualAddress uint32
 pkg debug/pe, type SectionHeader32 struct, VirtualSize uint32
-pkg encoding/ascii85, func Decode([]byte, bool) (int, error)
-pkg encoding/ascii85, func Encode([]byte) int
+pkg encoding/ascii85, func Decode([]uint8, []uint8, bool) (int, int, error)
+pkg encoding/ascii85, func Encode([]uint8, []uint8) int
 pkg encoding/ascii85, func MaxEncodedLen(int) int
 pkg encoding/ascii85, func NewDecoder(io.Reader) io.Reader
 pkg encoding/ascii85, func NewEncoder(io.Writer) io.WriteCloser
 pkg encoding/ascii85, method (CorruptInputError) Error() string
 pkg encoding/ascii85, type CorruptInputError int64
-pkg encoding/asn1, func Marshal(interface{}) ([]byte, error)
-pkg encoding/asn1, func Unmarshal([]byte, interface{}) ([]byte, error)
-pkg encoding/asn1, func UnmarshalWithParams([]byte, interface{}, string) ([]byte, error)
+pkg encoding/asn1, func Marshal(interface{}) ([]uint8, error)
+pkg encoding/asn1, func Unmarshal([]uint8, interface{}) ([]uint8, error)
+pkg encoding/asn1, func UnmarshalWithParams([]uint8, interface{}, string) ([]uint8, error)
 pkg encoding/asn1, method (BitString) At(int) int
-pkg encoding/asn1, method (BitString) RightAlign() []byte
+pkg encoding/asn1, method (BitString) RightAlign() []uint8
 pkg encoding/asn1, method (ObjectIdentifier) Equal(ObjectIdentifier) bool
 pkg encoding/asn1, method (StructuralError) Error() string
 pkg encoding/asn1, method (SyntaxError) Error() string
 pkg encoding/asn1, type BitString struct
 pkg encoding/asn1, type BitString struct, BitLength int
-pkg encoding/asn1, type BitString struct, Bytes []byte
+pkg encoding/asn1, type BitString struct, Bytes []uint8
 pkg encoding/asn1, type Enumerated int
 pkg encoding/asn1, type Flag bool
 pkg encoding/asn1, type ObjectIdentifier []int
-pkg encoding/asn1, type RawContent []byte
+pkg encoding/asn1, type RawContent []uint8
 pkg encoding/asn1, type RawValue struct
-pkg encoding/asn1, type RawValue struct, Bytes []byte
+pkg encoding/asn1, type RawValue struct, Bytes []uint8
 pkg encoding/asn1, type RawValue struct, Class int
-pkg encoding/asn1, type RawValue struct, FullBytes []byte
+pkg encoding/asn1, type RawValue struct, FullBytes []uint8
 pkg encoding/asn1, type RawValue struct, IsCompound bool
 pkg encoding/asn1, type RawValue struct, Tag int
 pkg encoding/asn1, type StructuralError struct
@@ -2232,11 +2232,11 @@ pkg encoding/asn1, type SyntaxError struct, Msg string
 pkg encoding/base32, func NewDecoder(*Encoding, io.Reader) io.Reader
 pkg encoding/base32, func NewEncoder(*Encoding, io.Writer) io.WriteCloser
 pkg encoding/base32, func NewEncoding(string) *Encoding
-pkg encoding/base32, method (*Encoding) Decode([]byte) (int, error)
-pkg encoding/base32, method (*Encoding) DecodeString(string) ([]byte, error)
+pkg encoding/base32, method (*Encoding) Decode([]uint8, []uint8) (int, error)
+pkg encoding/base32, method (*Encoding) DecodeString(string) ([]uint8, error)
 pkg encoding/base32, method (*Encoding) DecodedLen(int) int
-pkg encoding/base32, method (*Encoding) Encode([]byte)
-pkg encoding/base32, method (*Encoding) EncodeToString([]byte) string
+pkg encoding/base32, method (*Encoding) Encode([]uint8, []uint8)
+pkg encoding/base32, method (*Encoding) EncodeToString([]uint8) string
 pkg encoding/base32, method (*Encoding) EncodedLen(int) int
 pkg encoding/base32, method (CorruptInputError) Error() string
 pkg encoding/base32, type CorruptInputError int64
@@ -2246,11 +2246,11 @@ pkg encoding/base32, var StdEncoding *Encoding
 pkg encoding/base64, func NewDecoder(*Encoding, io.Reader) io.Reader
 pkg encoding/base64, func NewEncoder(*Encoding, io.Writer) io.WriteCloser
 pkg encoding/base64, func NewEncoding(string) *Encoding
-pkg encoding/base64, method (*Encoding) Decode([]byte) (int, error)
-pkg encoding/base64, method (*Encoding) DecodeString(string) ([]byte, error)
+pkg encoding/base64, method (*Encoding) Decode([]uint8, []uint8) (int, error)
+pkg encoding/base64, method (*Encoding) DecodeString(string) ([]uint8, error)
 pkg encoding/base64, method (*Encoding) DecodedLen(int) int
-pkg encoding/base64, method (*Encoding) Encode([]byte)
-pkg encoding/base64, method (*Encoding) EncodeToString([]byte) string
+pkg encoding/base64, method (*Encoding) Encode([]uint8, []uint8)
+pkg encoding/base64, method (*Encoding) EncodeToString([]uint8) string
 pkg encoding/base64, method (*Encoding) EncodedLen(int) int
 pkg encoding/base64, method (CorruptInputError) Error() string
 pkg encoding/base64, type CorruptInputError int64
@@ -2260,23 +2260,23 @@ pkg encoding/base64, var URLEncoding *Encoding
 pkg encoding/binary, const MaxVarintLen16 ideal-int
 pkg encoding/binary, const MaxVarintLen32 ideal-int
 pkg encoding/binary, const MaxVarintLen64 ideal-int
-pkg encoding/binary, func PutUvarint([]byte, uint64) int
-pkg encoding/binary, func PutVarint([]byte, int64) int
+pkg encoding/binary, func PutUvarint([]uint8, uint64) int
+pkg encoding/binary, func PutVarint([]uint8, int64) int
 pkg encoding/binary, func Read(io.Reader, ByteOrder, interface{}) error
 pkg encoding/binary, func ReadUvarint(io.ByteReader) (uint64, error)
 pkg encoding/binary, func ReadVarint(io.ByteReader) (int64, error)
 pkg encoding/binary, func Size(interface{}) int
-pkg encoding/binary, func Uvarint([]byte) (uint64, int)
-pkg encoding/binary, func Varint([]byte) (int64, int)
+pkg encoding/binary, func Uvarint([]uint8) (uint64, int)
+pkg encoding/binary, func Varint([]uint8) (int64, int)
 pkg encoding/binary, func Write(io.Writer, ByteOrder, interface{}) error
 pkg encoding/binary, type ByteOrder interface { PutUint16, PutUint32, PutUint64, String, Uint16, Uint32, Uint64 }
-pkg encoding/binary, type ByteOrder interface, PutUint16([]byte, uint16)
-pkg encoding/binary, type ByteOrder interface, PutUint32([]byte, uint32)
-pkg encoding/binary, type ByteOrder interface, PutUint64([]byte, uint64)
+pkg encoding/binary, type ByteOrder interface, PutUint16([]uint8, uint16)
+pkg encoding/binary, type ByteOrder interface, PutUint32([]uint8, uint32)
+pkg encoding/binary, type ByteOrder interface, PutUint64([]uint8, uint64)
 pkg encoding/binary, type ByteOrder interface, String() string
-pkg encoding/binary, type ByteOrder interface, Uint16([]byte) uint16
-pkg encoding/binary, type ByteOrder interface, Uint32([]byte) uint32
-pkg encoding/binary, type ByteOrder interface, Uint64([]byte) uint64
+pkg encoding/binary, type ByteOrder interface, Uint16([]uint8) uint16
+pkg encoding/binary, type ByteOrder interface, Uint32([]uint8) uint32
+pkg encoding/binary, type ByteOrder interface, Uint64([]uint8) uint64
 pkg encoding/binary, var BigEndian bigEndian
 pkg encoding/binary, var LittleEndian littleEndian
 pkg encoding/csv, func NewReader(io.Reader) *Reader
@@ -2292,14 +2292,14 @@ pkg encoding/csv, type ParseError struct, Column int
 pkg encoding/csv, type ParseError struct, Err error
 pkg encoding/csv, type ParseError struct, Line int
 pkg encoding/csv, type Reader struct
-pkg encoding/csv, type Reader struct, Comma rune
-pkg encoding/csv, type Reader struct, Comment rune
+pkg encoding/csv, type Reader struct, Comma int32
+pkg encoding/csv, type Reader struct, Comment int32
 pkg encoding/csv, type Reader struct, FieldsPerRecord int
 pkg encoding/csv, type Reader struct, LazyQuotes bool
 pkg encoding/csv, type Reader struct, TrailingComma bool
 pkg encoding/csv, type Reader struct, TrimLeadingSpace bool
 pkg encoding/csv, type Writer struct
-pkg encoding/csv, type Writer struct, Comma rune
+pkg encoding/csv, type Writer struct, Comma int32
 pkg encoding/csv, type Writer struct, UseCRLF bool
 pkg encoding/csv, var ErrBareQuote error
 pkg encoding/csv, var ErrFieldCount error
@@ -2319,35 +2319,35 @@ pkg encoding/gob, type CommonType struct, Name string
 pkg encoding/gob, type Decoder struct
 pkg encoding/gob, type Encoder struct
 pkg encoding/gob, type GobDecoder interface { GobDecode }
-pkg encoding/gob, type GobDecoder interface, GobDecode([]byte) error
+pkg encoding/gob, type GobDecoder interface, GobDecode([]uint8) error
 pkg encoding/gob, type GobEncoder interface { GobEncode }
-pkg encoding/gob, type GobEncoder interface, GobEncode() ([]byte, error)
-pkg encoding/hex, func Decode([]byte) (int, error)
-pkg encoding/hex, func DecodeString(string) ([]byte, error)
+pkg encoding/gob, type GobEncoder interface, GobEncode() ([]uint8, error)
+pkg encoding/hex, func Decode([]uint8, []uint8) (int, error)
+pkg encoding/hex, func DecodeString(string) ([]uint8, error)
 pkg encoding/hex, func DecodedLen(int) int
-pkg encoding/hex, func Dump([]byte) string
+pkg encoding/hex, func Dump([]uint8) string
 pkg encoding/hex, func Dumper(io.Writer) io.WriteCloser
-pkg encoding/hex, func Encode([]byte) int
-pkg encoding/hex, func EncodeToString([]byte) string
+pkg encoding/hex, func Encode([]uint8, []uint8) int
+pkg encoding/hex, func EncodeToString([]uint8) string
 pkg encoding/hex, func EncodedLen(int) int
 pkg encoding/hex, method (InvalidByteError) Error() string
-pkg encoding/hex, type InvalidByteError byte
+pkg encoding/hex, type InvalidByteError uint8
 pkg encoding/hex, var ErrLength error
-pkg encoding/json, func Compact(*bytes.Buffer, []byte) error
-pkg encoding/json, func HTMLEscape(*bytes.Buffer, []byte)
-pkg encoding/json, func Indent(*bytes.Buffer, []byte, string) error
-pkg encoding/json, func Marshal(interface{}) ([]byte, error)
-pkg encoding/json, func MarshalIndent(interface{}, string) ([]byte, error)
+pkg encoding/json, func Compact(*bytes.Buffer, []uint8) error
+pkg encoding/json, func HTMLEscape(*bytes.Buffer, []uint8)
+pkg encoding/json, func Indent(*bytes.Buffer, []uint8, string, string) error
+pkg encoding/json, func Marshal(interface{}) ([]uint8, error)
+pkg encoding/json, func MarshalIndent(interface{}, string, string) ([]uint8, error)
 pkg encoding/json, func NewDecoder(io.Reader) *Decoder
 pkg encoding/json, func NewEncoder(io.Writer) *Encoder
-pkg encoding/json, func Unmarshal([]byte, interface{}) error
+pkg encoding/json, func Unmarshal([]uint8, interface{}) error
 pkg encoding/json, method (*Decoder) Decode(interface{}) error
 pkg encoding/json, method (*Encoder) Encode(interface{}) error
 pkg encoding/json, method (*InvalidUTF8Error) Error() string
 pkg encoding/json, method (*InvalidUnmarshalError) Error() string
 pkg encoding/json, method (*MarshalerError) Error() string
-pkg encoding/json, method (*RawMessage) MarshalJSON() ([]byte, error)
-pkg encoding/json, method (*RawMessage) UnmarshalJSON([]byte) error
+pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
+pkg encoding/json, method (*RawMessage) UnmarshalJSON([]uint8) error
 pkg encoding/json, method (*SyntaxError) Error() string
 pkg encoding/json, method (*UnmarshalFieldError) Error() string
 pkg encoding/json, method (*UnmarshalTypeError) Error() string
@@ -2360,11 +2360,11 @@ pkg encoding/json, type InvalidUTF8Error struct, S string
 pkg encoding/json, type InvalidUnmarshalError struct
 pkg encoding/json, type InvalidUnmarshalError struct, Type reflect.Type
 pkg encoding/json, type Marshaler interface { MarshalJSON }
-pkg encoding/json, type Marshaler interface, MarshalJSON() ([]byte, error)
+pkg encoding/json, type Marshaler interface, MarshalJSON() ([]uint8, error)
 pkg encoding/json, type MarshalerError struct
 pkg encoding/json, type MarshalerError struct, Err error
 pkg encoding/json, type MarshalerError struct, Type reflect.Type
-pkg encoding/json, type RawMessage []byte
+pkg encoding/json, type RawMessage []uint8
 pkg encoding/json, type SyntaxError struct
 pkg encoding/json, type SyntaxError struct, Offset int64
 pkg encoding/json, type UnmarshalFieldError struct
@@ -2375,27 +2375,27 @@ pkg encoding/json, type UnmarshalTypeError struct
 pkg encoding/json, type UnmarshalTypeError struct, Type reflect.Type
 pkg encoding/json, type UnmarshalTypeError struct, Value string
 pkg encoding/json, type Unmarshaler interface { UnmarshalJSON }
-pkg encoding/json, type Unmarshaler interface, UnmarshalJSON([]byte) error
+pkg encoding/json, type Unmarshaler interface, UnmarshalJSON([]uint8) error
 pkg encoding/json, type UnsupportedTypeError struct
 pkg encoding/json, type UnsupportedTypeError struct, Type reflect.Type
 pkg encoding/json, type UnsupportedValueError struct
 pkg encoding/json, type UnsupportedValueError struct, Str string
 pkg encoding/json, type UnsupportedValueError struct, Value reflect.Value
-pkg encoding/pem, func Decode([]byte) (*Block, []byte)
+pkg encoding/pem, func Decode([]uint8) (*Block, []uint8)
 pkg encoding/pem, func Encode(io.Writer, *Block) error
-pkg encoding/pem, func EncodeToMemory(*Block) []byte
+pkg encoding/pem, func EncodeToMemory(*Block) []uint8
 pkg encoding/pem, type Block struct
-pkg encoding/pem, type Block struct, Bytes []byte
+pkg encoding/pem, type Block struct, Bytes []uint8
 pkg encoding/pem, type Block struct, Headers map[string]string
 pkg encoding/pem, type Block struct, Type string
 pkg encoding/xml, const Header ideal-string
 pkg encoding/xml, func CopyToken(Token) Token
-pkg encoding/xml, func Escape(io.Writer, []byte)
-pkg encoding/xml, func Marshal(interface{}) ([]byte, error)
-pkg encoding/xml, func MarshalIndent(interface{}, string) ([]byte, error)
+pkg encoding/xml, func Escape(io.Writer, []uint8)
+pkg encoding/xml, func Marshal(interface{}) ([]uint8, error)
+pkg encoding/xml, func MarshalIndent(interface{}, string, string) ([]uint8, error)
 pkg encoding/xml, func NewDecoder(io.Reader) *Decoder
 pkg encoding/xml, func NewEncoder(io.Writer) *Encoder
-pkg encoding/xml, func Unmarshal([]byte, interface{}) error
+pkg encoding/xml, func Unmarshal([]uint8, interface{}) error
 pkg encoding/xml, method (*Decoder) Decode(interface{}) error
 pkg encoding/xml, method (*Decoder) DecodeElement(interface{}, *StartElement) error
 pkg encoding/xml, method (*Decoder) RawToken() (Token, error)
@@ -2414,14 +2414,14 @@ pkg encoding/xml, method (UnmarshalError) Error() string
 pkg encoding/xml, type Attr struct
 pkg encoding/xml, type Attr struct, Name Name
 pkg encoding/xml, type Attr struct, Value string
-pkg encoding/xml, type CharData []byte
-pkg encoding/xml, type Comment []byte
+pkg encoding/xml, type CharData []uint8
+pkg encoding/xml, type Comment []uint8
 pkg encoding/xml, type Decoder struct
 pkg encoding/xml, type Decoder struct, AutoClose []string
 pkg encoding/xml, type Decoder struct, CharsetReader func(string, io.Reader) (io.Reader, error)
 pkg encoding/xml, type Decoder struct, Entity map[string]string
 pkg encoding/xml, type Decoder struct, Strict bool
-pkg encoding/xml, type Directive []byte
+pkg encoding/xml, type Directive []uint8
 pkg encoding/xml, type Encoder struct
 pkg encoding/xml, type EndElement struct
 pkg encoding/xml, type EndElement struct, Name Name
@@ -2429,7 +2429,7 @@ pkg encoding/xml, type Name struct
 pkg encoding/xml, type Name struct, Local string
 pkg encoding/xml, type Name struct, Space string
 pkg encoding/xml, type ProcInst struct
-pkg encoding/xml, type ProcInst struct, Inst []byte
+pkg encoding/xml, type ProcInst struct, Inst []uint8
 pkg encoding/xml, type ProcInst struct, Target string
 pkg encoding/xml, type StartElement struct
 pkg encoding/xml, type StartElement struct, Attr []Attr
@@ -2505,7 +2505,7 @@ pkg flag, func NewFlagSet(string, ErrorHandling) *FlagSet
 pkg flag, func Parse()
 pkg flag, func Parsed() bool
 pkg flag, func PrintDefaults()
-pkg flag, func Set(string) error
+pkg flag, func Set(string, string) error
 pkg flag, func String(string, string, string) *string
 pkg flag, func StringVar(*string, string, string, string)
 pkg flag, func Uint(string, uint, string) *uint
@@ -2534,7 +2534,7 @@ pkg flag, method (*FlagSet) NFlag() int
 pkg flag, method (*FlagSet) Parse([]string) error
 pkg flag, method (*FlagSet) Parsed() bool
 pkg flag, method (*FlagSet) PrintDefaults()
-pkg flag, method (*FlagSet) Set(string) error
+pkg flag, method (*FlagSet) Set(string, string) error
 pkg flag, method (*FlagSet) SetOutput(io.Writer)
 pkg flag, method (*FlagSet) String(string, string, string) *string
 pkg flag, method (*FlagSet) StringVar(*string, string, string, string)
@@ -2578,23 +2578,23 @@ pkg fmt, func Sscan(string, ...interface{}) (int, error)
 pkg fmt, func Sscanf(string, string, ...interface{}) (int, error)
 pkg fmt, func Sscanln(string, ...interface{}) (int, error)
 pkg fmt, type Formatter interface { Format }
-pkg fmt, type Formatter interface, Format(State, rune)
+pkg fmt, type Formatter interface, Format(State, int32)
 pkg fmt, type GoStringer interface { GoString }
 pkg fmt, type GoStringer interface, GoString() string
 pkg fmt, type ScanState interface { Read, ReadRune, SkipSpace, Token, UnreadRune, Width }
-pkg fmt, type ScanState interface, Read([]byte) (int, error)
-pkg fmt, type ScanState interface, ReadRune() (rune, int, error)
+pkg fmt, type ScanState interface, Read([]uint8) (int, error)
+pkg fmt, type ScanState interface, ReadRune() (int32, int, error)
 pkg fmt, type ScanState interface, SkipSpace()
-pkg fmt, type ScanState interface, Token(bool, func(rune) bool) ([]byte, error)
+pkg fmt, type ScanState interface, Token(bool, func(int32) bool) ([]uint8, error)
 pkg fmt, type ScanState interface, UnreadRune() error
 pkg fmt, type ScanState interface, Width() (int, bool)
 pkg fmt, type Scanner interface { Scan }
-pkg fmt, type Scanner interface, Scan(ScanState, rune) error
+pkg fmt, type Scanner interface, Scan(ScanState, int32) error
 pkg fmt, type State interface { Flag, Precision, Width, Write }
 pkg fmt, type State interface, Flag(int) bool
 pkg fmt, type State interface, Precision() (int, bool)
 pkg fmt, type State interface, Width() (int, bool)
-pkg fmt, type State interface, Write([]byte) (int, error)
+pkg fmt, type State interface, Write([]uint8) (int, error)
 pkg fmt, type Stringer interface { String }
 pkg fmt, type Stringer interface, String() string
 pkg go/ast, const Bad ObjKind
@@ -2811,9 +2811,9 @@ pkg go/ast, type CompositeLit struct, Elts []Expr
 pkg go/ast, type CompositeLit struct, Lbrace token.Pos
 pkg go/ast, type CompositeLit struct, Rbrace token.Pos
 pkg go/ast, type CompositeLit struct, Type Expr
-pkg go/ast, type Decl interface { End, Pos }
 pkg go/ast, type Decl interface, End() token.Pos
 pkg go/ast, type Decl interface, Pos() token.Pos
+pkg go/ast, type Decl interface, unexported methods
 pkg go/ast, type DeclStmt struct
 pkg go/ast, type DeclStmt struct, Decl Decl
 pkg go/ast, type DeferStmt struct
@@ -2824,9 +2824,9 @@ pkg go/ast, type Ellipsis struct, Ellipsis token.Pos
 pkg go/ast, type Ellipsis struct, Elt Expr
 pkg go/ast, type EmptyStmt struct
 pkg go/ast, type EmptyStmt struct, Semicolon token.Pos
-pkg go/ast, type Expr interface { End, Pos }
 pkg go/ast, type Expr interface, End() token.Pos
 pkg go/ast, type Expr interface, Pos() token.Pos
+pkg go/ast, type Expr interface, unexported methods
 pkg go/ast, type ExprStmt struct
 pkg go/ast, type ExprStmt struct, X Expr
 pkg go/ast, type Field struct
@@ -2835,7 +2835,7 @@ pkg go/ast, type Field struct, Doc *CommentGroup
 pkg go/ast, type Field struct, Names []*Ident
 pkg go/ast, type Field struct, Tag *BasicLit
 pkg go/ast, type Field struct, Type Expr
-pkg go/ast, type FieldFilter func(name string, value reflect.Value) bool
+pkg go/ast, type FieldFilter func(string, reflect.Value) bool
 pkg go/ast, type FieldList struct
 pkg go/ast, type FieldList struct, Closing token.Pos
 pkg go/ast, type FieldList struct, List []*Field
@@ -2895,7 +2895,7 @@ pkg go/ast, type ImportSpec struct, Doc *CommentGroup
 pkg go/ast, type ImportSpec struct, EndPos token.Pos
 pkg go/ast, type ImportSpec struct, Name *Ident
 pkg go/ast, type ImportSpec struct, Path *BasicLit
-pkg go/ast, type Importer func(imports map[string]*Object, path string) (pkg *Object, err error)
+pkg go/ast, type Importer func(map[string]*Object, string) (*Object, error)
 pkg go/ast, type IncDecStmt struct
 pkg go/ast, type IncDecStmt struct, Tok token.Token
 pkg go/ast, type IncDecStmt struct, TokPos token.Pos
@@ -2971,15 +2971,15 @@ pkg go/ast, type SliceExpr struct, Lbrack token.Pos
 pkg go/ast, type SliceExpr struct, Low Expr
 pkg go/ast, type SliceExpr struct, Rbrack token.Pos
 pkg go/ast, type SliceExpr struct, X Expr
-pkg go/ast, type Spec interface { End, Pos }
 pkg go/ast, type Spec interface, End() token.Pos
 pkg go/ast, type Spec interface, Pos() token.Pos
+pkg go/ast, type Spec interface, unexported methods
 pkg go/ast, type StarExpr struct
 pkg go/ast, type StarExpr struct, Star token.Pos
 pkg go/ast, type StarExpr struct, X Expr
-pkg go/ast, type Stmt interface { End, Pos }
 pkg go/ast, type Stmt interface, End() token.Pos
 pkg go/ast, type Stmt interface, Pos() token.Pos
+pkg go/ast, type Stmt interface, unexported methods
 pkg go/ast, type StructType struct
 pkg go/ast, type StructType struct, Fields *FieldList
 pkg go/ast, type StructType struct, Incomplete bool
@@ -3017,7 +3017,7 @@ pkg go/ast, type Visitor interface, Visit(Node) Visitor
 pkg go/build, const AllowBinary ImportMode
 pkg go/build, const FindOnly ImportMode
 pkg go/build, func ArchChar(string) (string, error)
-pkg go/build, func Import(string, ImportMode) (*Package, error)
+pkg go/build, func Import(string, string, ImportMode) (*Package, error)
 pkg go/build, func ImportDir(string, ImportMode) (*Package, error)
 pkg go/build, func IsLocalImport(string) bool
 pkg go/build, method (*Context) Import(string, string, ImportMode) (*Package, error)
@@ -3033,7 +3033,7 @@ pkg go/build, type Context struct, GOARCH string
 pkg go/build, type Context struct, GOOS string
 pkg go/build, type Context struct, GOPATH string
 pkg go/build, type Context struct, GOROOT string
-pkg go/build, type Context struct, HasSubdir func(string) (string, bool)
+pkg go/build, type Context struct, HasSubdir func(string, string) (string, bool)
 pkg go/build, type Context struct, IsAbsPath func(string) bool
 pkg go/build, type Context struct, IsDir func(string) bool
 pkg go/build, type Context struct, JoinPath func(...string) string
@@ -3080,7 +3080,7 @@ pkg go/doc, func Examples(...*ast.File) []*Example
 pkg go/doc, func New(*ast.Package, string, Mode) *Package
 pkg go/doc, func Synopsis(string) string
 pkg go/doc, func ToHTML(io.Writer, string, map[string]string)
-pkg go/doc, func ToText(io.Writer, string, string, int)
+pkg go/doc, func ToText(io.Writer, string, string, string, int)
 pkg go/doc, method (*Package) Filter(Filter)
 pkg go/doc, type Example struct
 pkg go/doc, type Example struct, Code ast.Node
@@ -3148,19 +3148,19 @@ pkg go/scanner, func PrintError(io.Writer, error)
 pkg go/scanner, method (*ErrorList) Add(token.Position, string)
 pkg go/scanner, method (*ErrorList) RemoveMultiples()
 pkg go/scanner, method (*ErrorList) Reset()
-pkg go/scanner, method (*Scanner) Init(*token.File, []byte, ErrorHandler, Mode)
+pkg go/scanner, method (*Scanner) Init(*token.File, []uint8, ErrorHandler, Mode)
 pkg go/scanner, method (*Scanner) Scan() (token.Pos, token.Token, string)
 pkg go/scanner, method (Error) Error() string
 pkg go/scanner, method (ErrorList) Err() error
 pkg go/scanner, method (ErrorList) Error() string
 pkg go/scanner, method (ErrorList) Len() int
-pkg go/scanner, method (ErrorList) Less(int) bool
+pkg go/scanner, method (ErrorList) Less(int, int) bool
 pkg go/scanner, method (ErrorList) Sort()
-pkg go/scanner, method (ErrorList) Swap(int)
+pkg go/scanner, method (ErrorList) Swap(int, int)
 pkg go/scanner, type Error struct
 pkg go/scanner, type Error struct, Msg string
 pkg go/scanner, type Error struct, Pos token.Position
-pkg go/scanner, type ErrorHandler func(pos token.Position, msg string)
+pkg go/scanner, type ErrorHandler func(token.Position, string)
 pkg go/scanner, type ErrorList []*Error
 pkg go/scanner, type Mode uint
 pkg go/scanner, type Scanner struct
@@ -3262,9 +3262,9 @@ pkg go/token, method (*File) Offset(Pos) int
 pkg go/token, method (*File) Pos(int) Pos
 pkg go/token, method (*File) Position(Pos) Position
 pkg go/token, method (*File) SetLines([]int) bool
-pkg go/token, method (*File) SetLinesForContent([]byte)
+pkg go/token, method (*File) SetLinesForContent([]uint8)
 pkg go/token, method (*File) Size() int
-pkg go/token, method (*FileSet) AddFile(string, int) *File
+pkg go/token, method (*FileSet) AddFile(string, int, int) *File
 pkg go/token, method (*FileSet) Base() int
 pkg go/token, method (*FileSet) File(Pos) *File
 pkg go/token, method (*FileSet) Iterate(func(*File) bool)
@@ -3292,44 +3292,44 @@ pkg hash, type Hash interface { BlockSize, Reset, Size, Sum, Write }
 pkg hash, type Hash interface, BlockSize() int
 pkg hash, type Hash interface, Reset()
 pkg hash, type Hash interface, Size() int
-pkg hash, type Hash interface, Sum([]byte) []byte
-pkg hash, type Hash interface, Write([]byte) (int, error)
+pkg hash, type Hash interface, Sum([]uint8) []uint8
+pkg hash, type Hash interface, Write([]uint8) (int, error)
 pkg hash, type Hash32 interface { BlockSize, Reset, Size, Sum, Sum32, Write }
 pkg hash, type Hash32 interface, BlockSize() int
 pkg hash, type Hash32 interface, Reset()
 pkg hash, type Hash32 interface, Size() int
-pkg hash, type Hash32 interface, Sum([]byte) []byte
+pkg hash, type Hash32 interface, Sum([]uint8) []uint8
 pkg hash, type Hash32 interface, Sum32() uint32
-pkg hash, type Hash32 interface, Write([]byte) (int, error)
+pkg hash, type Hash32 interface, Write([]uint8) (int, error)
 pkg hash, type Hash64 interface { BlockSize, Reset, Size, Sum, Sum64, Write }
 pkg hash, type Hash64 interface, BlockSize() int
 pkg hash, type Hash64 interface, Reset()
 pkg hash, type Hash64 interface, Size() int
-pkg hash, type Hash64 interface, Sum([]byte) []byte
+pkg hash, type Hash64 interface, Sum([]uint8) []uint8
 pkg hash, type Hash64 interface, Sum64() uint64
-pkg hash, type Hash64 interface, Write([]byte) (int, error)
+pkg hash, type Hash64 interface, Write([]uint8) (int, error)
 pkg hash/adler32, const Size ideal-int
-pkg hash/adler32, func Checksum([]byte) uint32
+pkg hash/adler32, func Checksum([]uint8) uint32
 pkg hash/adler32, func New() hash.Hash32
 pkg hash/crc32, const Castagnoli ideal-int
 pkg hash/crc32, const IEEE ideal-int
 pkg hash/crc32, const Koopman ideal-int
 pkg hash/crc32, const Size ideal-int
-pkg hash/crc32, func Checksum([]byte, *Table) uint32
-pkg hash/crc32, func ChecksumIEEE([]byte) uint32
+pkg hash/crc32, func Checksum([]uint8, *Table) uint32
+pkg hash/crc32, func ChecksumIEEE([]uint8) uint32
 pkg hash/crc32, func MakeTable(uint32) *Table
 pkg hash/crc32, func New(*Table) hash.Hash32
 pkg hash/crc32, func NewIEEE() hash.Hash32
-pkg hash/crc32, func Update(uint32, *Table, []byte) uint32
+pkg hash/crc32, func Update(uint32, *Table, []uint8) uint32
 pkg hash/crc32, type Table [256]uint32
 pkg hash/crc32, var IEEETable *Table
 pkg hash/crc64, const ECMA ideal-int
 pkg hash/crc64, const ISO ideal-int
 pkg hash/crc64, const Size ideal-int
-pkg hash/crc64, func Checksum([]byte, *Table) uint64
+pkg hash/crc64, func Checksum([]uint8, *Table) uint64
 pkg hash/crc64, func MakeTable(uint64) *Table
 pkg hash/crc64, func New(*Table) hash.Hash64
-pkg hash/crc64, func Update(uint64, *Table, []byte) uint64
+pkg hash/crc64, func Update(uint64, *Table, []uint8) uint64
 pkg hash/crc64, type Table [256]uint64
 pkg hash/fnv, func New32() hash.Hash32
 pkg hash/fnv, func New32a() hash.Hash32
@@ -3348,10 +3348,10 @@ pkg html/template, const ErrPartialEscape ErrorCode
 pkg html/template, const ErrRangeLoopReentry ErrorCode
 pkg html/template, const ErrSlashAmbig ErrorCode
 pkg html/template, const OK ErrorCode
-pkg html/template, func HTMLEscape(io.Writer, []byte)
+pkg html/template, func HTMLEscape(io.Writer, []uint8)
 pkg html/template, func HTMLEscapeString(string) string
 pkg html/template, func HTMLEscaper(...interface{}) string
-pkg html/template, func JSEscape(io.Writer, []byte)
+pkg html/template, func JSEscape(io.Writer, []uint8)
 pkg html/template, func JSEscapeString(string) string
 pkg html/template, func JSEscaper(...interface{}) string
 pkg html/template, func Must(*Template, error) *Template
@@ -3362,7 +3362,7 @@ pkg html/template, func URLQueryEscaper(...interface{}) string
 pkg html/template, method (*Error) Error() string
 pkg html/template, method (*Template) AddParseTree(string, *parse.Tree) (*Template, error)
 pkg html/template, method (*Template) Clone() (*Template, error)
-pkg html/template, method (*Template) Delims(string) *Template
+pkg html/template, method (*Template) Delims(string, string) *Template
 pkg html/template, method (*Template) Execute(io.Writer, interface{}) error
 pkg html/template, method (*Template) ExecuteTemplate(io.Writer, string, interface{}) error
 pkg html/template, method (*Template) Funcs(FuncMap) *Template
@@ -3403,95 +3403,95 @@ pkg image, func NewRGBA(Rectangle) *RGBA
 pkg image, func NewRGBA64(Rectangle) *RGBA64
 pkg image, func NewUniform(color.Color) *Uniform
 pkg image, func NewYCbCr(Rectangle, YCbCrSubsampleRatio) *YCbCr
-pkg image, func Pt(int) Point
-pkg image, func Rect(int) Rectangle
-pkg image, func RegisterFormat(string, func(io.Reader) (Image, error), func(io.Reader) (Config, error))
-pkg image, method (*Alpha) At(int) color.Color
+pkg image, func Pt(int, int) Point
+pkg image, func Rect(int, int, int, int) Rectangle
+pkg image, func RegisterFormat(string, string, func(io.Reader) (Image, error), func(io.Reader) (Config, error))
+pkg image, method (*Alpha) At(int, int) color.Color
 pkg image, method (*Alpha) Bounds() Rectangle
 pkg image, method (*Alpha) ColorModel() color.Model
 pkg image, method (*Alpha) Opaque() bool
-pkg image, method (*Alpha) PixOffset(int) int
-pkg image, method (*Alpha) Set(int, color.Color)
-pkg image, method (*Alpha) SetAlpha(int, color.Alpha)
+pkg image, method (*Alpha) PixOffset(int, int) int
+pkg image, method (*Alpha) Set(int, int, color.Color)
+pkg image, method (*Alpha) SetAlpha(int, int, color.Alpha)
 pkg image, method (*Alpha) SubImage(Rectangle) Image
-pkg image, method (*Alpha16) At(int) color.Color
+pkg image, method (*Alpha16) At(int, int) color.Color
 pkg image, method (*Alpha16) Bounds() Rectangle
 pkg image, method (*Alpha16) ColorModel() color.Model
 pkg image, method (*Alpha16) Opaque() bool
-pkg image, method (*Alpha16) PixOffset(int) int
-pkg image, method (*Alpha16) Set(int, color.Color)
-pkg image, method (*Alpha16) SetAlpha16(int, color.Alpha16)
+pkg image, method (*Alpha16) PixOffset(int, int) int
+pkg image, method (*Alpha16) Set(int, int, color.Color)
+pkg image, method (*Alpha16) SetAlpha16(int, int, color.Alpha16)
 pkg image, method (*Alpha16) SubImage(Rectangle) Image
-pkg image, method (*Gray) At(int) color.Color
+pkg image, method (*Gray) At(int, int) color.Color
 pkg image, method (*Gray) Bounds() Rectangle
 pkg image, method (*Gray) ColorModel() color.Model
 pkg image, method (*Gray) Opaque() bool
-pkg image, method (*Gray) PixOffset(int) int
-pkg image, method (*Gray) Set(int, color.Color)
-pkg image, method (*Gray) SetGray(int, color.Gray)
+pkg image, method (*Gray) PixOffset(int, int) int
+pkg image, method (*Gray) Set(int, int, color.Color)
+pkg image, method (*Gray) SetGray(int, int, color.Gray)
 pkg image, method (*Gray) SubImage(Rectangle) Image
-pkg image, method (*Gray16) At(int) color.Color
+pkg image, method (*Gray16) At(int, int) color.Color
 pkg image, method (*Gray16) Bounds() Rectangle
 pkg image, method (*Gray16) ColorModel() color.Model
 pkg image, method (*Gray16) Opaque() bool
-pkg image, method (*Gray16) PixOffset(int) int
-pkg image, method (*Gray16) Set(int, color.Color)
-pkg image, method (*Gray16) SetGray16(int, color.Gray16)
+pkg image, method (*Gray16) PixOffset(int, int) int
+pkg image, method (*Gray16) Set(int, int, color.Color)
+pkg image, method (*Gray16) SetGray16(int, int, color.Gray16)
 pkg image, method (*Gray16) SubImage(Rectangle) Image
-pkg image, method (*NRGBA) At(int) color.Color
+pkg image, method (*NRGBA) At(int, int) color.Color
 pkg image, method (*NRGBA) Bounds() Rectangle
 pkg image, method (*NRGBA) ColorModel() color.Model
 pkg image, method (*NRGBA) Opaque() bool
-pkg image, method (*NRGBA) PixOffset(int) int
-pkg image, method (*NRGBA) Set(int, color.Color)
-pkg image, method (*NRGBA) SetNRGBA(int, color.NRGBA)
+pkg image, method (*NRGBA) PixOffset(int, int) int
+pkg image, method (*NRGBA) Set(int, int, color.Color)
+pkg image, method (*NRGBA) SetNRGBA(int, int, color.NRGBA)
 pkg image, method (*NRGBA) SubImage(Rectangle) Image
-pkg image, method (*NRGBA64) At(int) color.Color
+pkg image, method (*NRGBA64) At(int, int) color.Color
 pkg image, method (*NRGBA64) Bounds() Rectangle
 pkg image, method (*NRGBA64) ColorModel() color.Model
 pkg image, method (*NRGBA64) Opaque() bool
-pkg image, method (*NRGBA64) PixOffset(int) int
-pkg image, method (*NRGBA64) Set(int, color.Color)
-pkg image, method (*NRGBA64) SetNRGBA64(int, color.NRGBA64)
+pkg image, method (*NRGBA64) PixOffset(int, int) int
+pkg image, method (*NRGBA64) Set(int, int, color.Color)
+pkg image, method (*NRGBA64) SetNRGBA64(int, int, color.NRGBA64)
 pkg image, method (*NRGBA64) SubImage(Rectangle) Image
-pkg image, method (*Paletted) At(int) color.Color
+pkg image, method (*Paletted) At(int, int) color.Color
 pkg image, method (*Paletted) Bounds() Rectangle
-pkg image, method (*Paletted) ColorIndexAt(int) uint8
+pkg image, method (*Paletted) ColorIndexAt(int, int) uint8
 pkg image, method (*Paletted) ColorModel() color.Model
 pkg image, method (*Paletted) Opaque() bool
-pkg image, method (*Paletted) PixOffset(int) int
-pkg image, method (*Paletted) Set(int, color.Color)
-pkg image, method (*Paletted) SetColorIndex(int, uint8)
+pkg image, method (*Paletted) PixOffset(int, int) int
+pkg image, method (*Paletted) Set(int, int, color.Color)
+pkg image, method (*Paletted) SetColorIndex(int, int, uint8)
 pkg image, method (*Paletted) SubImage(Rectangle) Image
-pkg image, method (*RGBA) At(int) color.Color
+pkg image, method (*RGBA) At(int, int) color.Color
 pkg image, method (*RGBA) Bounds() Rectangle
 pkg image, method (*RGBA) ColorModel() color.Model
 pkg image, method (*RGBA) Opaque() bool
-pkg image, method (*RGBA) PixOffset(int) int
-pkg image, method (*RGBA) Set(int, color.Color)
-pkg image, method (*RGBA) SetRGBA(int, color.RGBA)
+pkg image, method (*RGBA) PixOffset(int, int) int
+pkg image, method (*RGBA) Set(int, int, color.Color)
+pkg image, method (*RGBA) SetRGBA(int, int, color.RGBA)
 pkg image, method (*RGBA) SubImage(Rectangle) Image
-pkg image, method (*RGBA64) At(int) color.Color
+pkg image, method (*RGBA64) At(int, int) color.Color
 pkg image, method (*RGBA64) Bounds() Rectangle
 pkg image, method (*RGBA64) ColorModel() color.Model
 pkg image, method (*RGBA64) Opaque() bool
-pkg image, method (*RGBA64) PixOffset(int) int
-pkg image, method (*RGBA64) Set(int, color.Color)
-pkg image, method (*RGBA64) SetRGBA64(int, color.RGBA64)
+pkg image, method (*RGBA64) PixOffset(int, int) int
+pkg image, method (*RGBA64) Set(int, int, color.Color)
+pkg image, method (*RGBA64) SetRGBA64(int, int, color.RGBA64)
 pkg image, method (*RGBA64) SubImage(Rectangle) Image
-pkg image, method (*Uniform) At(int) color.Color
+pkg image, method (*Uniform) At(int, int) color.Color
 pkg image, method (*Uniform) Bounds() Rectangle
 pkg image, method (*Uniform) ColorModel() color.Model
 pkg image, method (*Uniform) Convert(color.Color) color.Color
 pkg image, method (*Uniform) Opaque() bool
-pkg image, method (*Uniform) RGBA() uint32
-pkg image, method (*YCbCr) At(int) color.Color
+pkg image, method (*Uniform) RGBA() (uint32, uint32, uint32, uint32)
+pkg image, method (*YCbCr) At(int, int) color.Color
 pkg image, method (*YCbCr) Bounds() Rectangle
-pkg image, method (*YCbCr) COffset(int) int
+pkg image, method (*YCbCr) COffset(int, int) int
 pkg image, method (*YCbCr) ColorModel() color.Model
 pkg image, method (*YCbCr) Opaque() bool
 pkg image, method (*YCbCr) SubImage(Rectangle) Image
-pkg image, method (*YCbCr) YOffset(int) int
+pkg image, method (*YCbCr) YOffset(int, int) int
 pkg image, method (Point) Add(Point) Point
 pkg image, method (Point) Div(int) Point
 pkg image, method (Point) Eq(Point) bool
@@ -3536,7 +3536,7 @@ pkg image, type Gray16 struct, Pix []uint8
 pkg image, type Gray16 struct, Rect Rectangle
 pkg image, type Gray16 struct, Stride int
 pkg image, type Image interface { At, Bounds, ColorModel }
-pkg image, type Image interface, At(int) color.Color
+pkg image, type Image interface, At(int, int) color.Color
 pkg image, type Image interface, Bounds() Rectangle
 pkg image, type Image interface, ColorModel() color.Model
 pkg image, type NRGBA struct
@@ -3553,9 +3553,9 @@ pkg image, type Paletted struct, Pix []uint8
 pkg image, type Paletted struct, Rect Rectangle
 pkg image, type Paletted struct, Stride int
 pkg image, type PalettedImage interface { At, Bounds, ColorIndexAt, ColorModel }
-pkg image, type PalettedImage interface, At(int) color.Color
+pkg image, type PalettedImage interface, At(int, int) color.Color
 pkg image, type PalettedImage interface, Bounds() Rectangle
-pkg image, type PalettedImage interface, ColorIndexAt(int) uint8
+pkg image, type PalettedImage interface, ColorIndexAt(int, int) uint8
 pkg image, type PalettedImage interface, ColorModel() color.Model
 pkg image, type Point struct
 pkg image, type Point struct, X int
@@ -3590,25 +3590,25 @@ pkg image, var White *Uniform
 pkg image, var ZP Point
 pkg image, var ZR Rectangle
 pkg image/color, func ModelFunc(func(Color) Color) Model
-pkg image/color, func RGBToYCbCr(uint8) (uint8, uint8, uint8)
-pkg image/color, func YCbCrToRGB(uint8) (uint8, uint8, uint8)
-pkg image/color, method (Alpha) RGBA() uint32
-pkg image/color, method (Alpha16) RGBA() uint32
-pkg image/color, method (Gray) RGBA() uint32
-pkg image/color, method (Gray16) RGBA() uint32
-pkg image/color, method (NRGBA) RGBA() uint32
-pkg image/color, method (NRGBA64) RGBA() uint32
+pkg image/color, func RGBToYCbCr(uint8, uint8, uint8) (uint8, uint8, uint8)
+pkg image/color, func YCbCrToRGB(uint8, uint8, uint8) (uint8, uint8, uint8)
+pkg image/color, method (Alpha) RGBA() (uint32, uint32, uint32, uint32)
+pkg image/color, method (Alpha16) RGBA() (uint32, uint32, uint32, uint32)
+pkg image/color, method (Gray) RGBA() (uint32, uint32, uint32, uint32)
+pkg image/color, method (Gray16) RGBA() (uint32, uint32, uint32, uint32)
+pkg image/color, method (NRGBA) RGBA() (uint32, uint32, uint32, uint32)
+pkg image/color, method (NRGBA64) RGBA() (uint32, uint32, uint32, uint32)
 pkg image/color, method (Palette) Convert(Color) Color
 pkg image/color, method (Palette) Index(Color) int
-pkg image/color, method (RGBA) RGBA() uint32
-pkg image/color, method (RGBA64) RGBA() uint32
+pkg image/color, method (RGBA) RGBA() (uint32, uint32, uint32, uint32)
+pkg image/color, method (RGBA64) RGBA() (uint32, uint32, uint32, uint32)
 pkg image/color, method (YCbCr) RGBA() (uint32, uint32, uint32, uint32)
 pkg image/color, type Alpha struct
 pkg image/color, type Alpha struct, A uint8
 pkg image/color, type Alpha16 struct
 pkg image/color, type Alpha16 struct, A uint16
 pkg image/color, type Color interface { RGBA }
-pkg image/color, type Color interface, RGBA() uint32
+pkg image/color, type Color interface, RGBA() (uint32, uint32, uint32, uint32)
 pkg image/color, type Gray struct
 pkg image/color, type Gray struct, Y uint8
 pkg image/color, type Gray16 struct
@@ -3658,10 +3658,10 @@ pkg image/draw, const Src Op
 pkg image/draw, func Draw(Image, image.Rectangle, image.Image, image.Point, Op)
 pkg image/draw, func DrawMask(Image, image.Rectangle, image.Image, image.Point, image.Image, image.Point, Op)
 pkg image/draw, type Image interface { At, Bounds, ColorModel, Set }
-pkg image/draw, type Image interface, At(int) color.Color
+pkg image/draw, type Image interface, At(int, int) color.Color
 pkg image/draw, type Image interface, Bounds() Rectangle
 pkg image/draw, type Image interface, ColorModel() color.Model
-pkg image/draw, type Image interface, Set(int, color.Color)
+pkg image/draw, type Image interface, Set(int, int, color.Color)
 pkg image/draw, type Op int
 pkg image/gif, func Decode(io.Reader) (image.Image, error)
 pkg image/gif, func DecodeAll(io.Reader) (*GIF, error)
@@ -3680,8 +3680,8 @@ pkg image/jpeg, type FormatError string
 pkg image/jpeg, type Options struct
 pkg image/jpeg, type Options struct, Quality int
 pkg image/jpeg, type Reader interface { Read, ReadByte }
-pkg image/jpeg, type Reader interface, Read([]byte) (int, error)
-pkg image/jpeg, type Reader interface, ReadByte() (byte, error)
+pkg image/jpeg, type Reader interface, Read([]uint8) (int, error)
+pkg image/jpeg, type Reader interface, ReadByte() (uint8, error)
 pkg image/jpeg, type UnsupportedError string
 pkg image/png, func Decode(io.Reader) (image.Image, error)
 pkg image/png, func DecodeConfig(io.Reader) (image.Config, error)
@@ -3690,10 +3690,10 @@ pkg image/png, method (FormatError) Error() string
 pkg image/png, method (UnsupportedError) Error() string
 pkg image/png, type FormatError string
 pkg image/png, type UnsupportedError string
-pkg index/suffixarray, func New([]byte) *Index
-pkg index/suffixarray, method (*Index) Bytes() []byte
+pkg index/suffixarray, func New([]uint8) *Index
+pkg index/suffixarray, method (*Index) Bytes() []uint8
 pkg index/suffixarray, method (*Index) FindAllIndex(*regexp.Regexp, int) [][]int
-pkg index/suffixarray, method (*Index) Lookup([]byte, int) []int
+pkg index/suffixarray, method (*Index) Lookup([]uint8, int) []int
 pkg index/suffixarray, method (*Index) Read(io.Reader) error
 pkg index/suffixarray, method (*Index) Write(io.Writer) error
 pkg index/suffixarray, type Index struct
@@ -3704,25 +3704,25 @@ pkg io, func MultiReader(...Reader) Reader
 pkg io, func MultiWriter(...Writer) Writer
 pkg io, func NewSectionReader(ReaderAt, int64, int64) *SectionReader
 pkg io, func Pipe() (*PipeReader, *PipeWriter)
-pkg io, func ReadAtLeast(Reader, []byte, int) (int, error)
-pkg io, func ReadFull(Reader, []byte) (int, error)
+pkg io, func ReadAtLeast(Reader, []uint8, int) (int, error)
+pkg io, func ReadFull(Reader, []uint8) (int, error)
 pkg io, func TeeReader(Reader, Writer) Reader
 pkg io, func WriteString(Writer, string) (int, error)
-pkg io, method (*LimitedReader) Read([]byte) (int, error)
+pkg io, method (*LimitedReader) Read([]uint8) (int, error)
 pkg io, method (*PipeReader) Close() error
 pkg io, method (*PipeReader) CloseWithError(error) error
-pkg io, method (*PipeReader) Read([]byte) (int, error)
+pkg io, method (*PipeReader) Read([]uint8) (int, error)
 pkg io, method (*PipeWriter) Close() error
 pkg io, method (*PipeWriter) CloseWithError(error) error
-pkg io, method (*PipeWriter) Write([]byte) (int, error)
-pkg io, method (*SectionReader) Read([]byte) (int, error)
-pkg io, method (*SectionReader) ReadAt([]byte, int64) (int, error)
+pkg io, method (*PipeWriter) Write([]uint8) (int, error)
+pkg io, method (*SectionReader) Read([]uint8) (int, error)
+pkg io, method (*SectionReader) ReadAt([]uint8, int64) (int, error)
 pkg io, method (*SectionReader) Seek(int64, int) (int64, error)
 pkg io, method (*SectionReader) Size() int64
 pkg io, type ByteReader interface { ReadByte }
-pkg io, type ByteReader interface, ReadByte() (byte, error)
+pkg io, type ByteReader interface, ReadByte() (uint8, error)
 pkg io, type ByteScanner interface { ReadByte, UnreadByte }
-pkg io, type ByteScanner interface, ReadByte() (byte, error)
+pkg io, type ByteScanner interface, ReadByte() (uint8, error)
 pkg io, type ByteScanner interface, UnreadByte() error
 pkg io, type Closer interface { Close }
 pkg io, type Closer interface, Close() error
@@ -3733,45 +3733,45 @@ pkg io, type PipeReader struct
 pkg io, type PipeWriter struct
 pkg io, type ReadCloser interface { Close, Read }
 pkg io, type ReadCloser interface, Close() error
-pkg io, type ReadCloser interface, Read([]byte) (int, error)
+pkg io, type ReadCloser interface, Read([]uint8) (int, error)
 pkg io, type ReadSeeker interface { Read, Seek }
-pkg io, type ReadSeeker interface, Read([]byte) (int, error)
+pkg io, type ReadSeeker interface, Read([]uint8) (int, error)
 pkg io, type ReadSeeker interface, Seek(int64, int) (int64, error)
 pkg io, type ReadWriteCloser interface { Close, Read, Write }
 pkg io, type ReadWriteCloser interface, Close() error
-pkg io, type ReadWriteCloser interface, Read([]byte) (int, error)
-pkg io, type ReadWriteCloser interface, Write([]byte) (int, error)
+pkg io, type ReadWriteCloser interface, Read([]uint8) (int, error)
+pkg io, type ReadWriteCloser interface, Write([]uint8) (int, error)
 pkg io, type ReadWriteSeeker interface { Read, Seek, Write }
-pkg io, type ReadWriteSeeker interface, Read([]byte) (int, error)
+pkg io, type ReadWriteSeeker interface, Read([]uint8) (int, error)
 pkg io, type ReadWriteSeeker interface, Seek(int64, int) (int64, error)
-pkg io, type ReadWriteSeeker interface, Write([]byte) (int, error)
+pkg io, type ReadWriteSeeker interface, Write([]uint8) (int, error)
 pkg io, type ReadWriter interface { Read, Write }
-pkg io, type ReadWriter interface, Read([]byte) (int, error)
-pkg io, type ReadWriter interface, Write([]byte) (int, error)
+pkg io, type ReadWriter interface, Read([]uint8) (int, error)
+pkg io, type ReadWriter interface, Write([]uint8) (int, error)
 pkg io, type Reader interface { Read }
-pkg io, type Reader interface, Read([]byte) (int, error)
+pkg io, type Reader interface, Read([]uint8) (int, error)
 pkg io, type ReaderAt interface { ReadAt }
-pkg io, type ReaderAt interface, ReadAt([]byte, int64) (int, error)
+pkg io, type ReaderAt interface, ReadAt([]uint8, int64) (int, error)
 pkg io, type ReaderFrom interface { ReadFrom }
 pkg io, type ReaderFrom interface, ReadFrom(Reader) (int64, error)
 pkg io, type RuneReader interface { ReadRune }
-pkg io, type RuneReader interface, ReadRune() (rune, int, error)
+pkg io, type RuneReader interface, ReadRune() (int32, int, error)
 pkg io, type RuneScanner interface { ReadRune, UnreadRune }
-pkg io, type RuneScanner interface, ReadRune() (rune, int, error)
+pkg io, type RuneScanner interface, ReadRune() (int32, int, error)
 pkg io, type RuneScanner interface, UnreadRune() error
 pkg io, type SectionReader struct
 pkg io, type Seeker interface { Seek }
 pkg io, type Seeker interface, Seek(int64, int) (int64, error)
 pkg io, type WriteCloser interface { Close, Write }
 pkg io, type WriteCloser interface, Close() error
-pkg io, type WriteCloser interface, Write([]byte) (int, error)
+pkg io, type WriteCloser interface, Write([]uint8) (int, error)
 pkg io, type WriteSeeker interface { Seek, Write }
 pkg io, type WriteSeeker interface, Seek(int64, int) (int64, error)
-pkg io, type WriteSeeker interface, Write([]byte) (int, error)
+pkg io, type WriteSeeker interface, Write([]uint8) (int, error)
 pkg io, type Writer interface { Write }
-pkg io, type Writer interface, Write([]byte) (int, error)
+pkg io, type Writer interface, Write([]uint8) (int, error)
 pkg io, type WriterAt interface { WriteAt }
-pkg io, type WriterAt interface, WriteAt([]byte, int64) (int, error)
+pkg io, type WriterAt interface, WriteAt([]uint8, int64) (int, error)
 pkg io, type WriterTo interface { WriteTo }
 pkg io, type WriterTo interface, WriteTo(Writer) (int64, error)
 pkg io, var EOF error
@@ -3780,12 +3780,12 @@ pkg io, var ErrShortBuffer error
 pkg io, var ErrShortWrite error
 pkg io, var ErrUnexpectedEOF error
 pkg io/ioutil, func NopCloser(io.Reader) io.ReadCloser
-pkg io/ioutil, func ReadAll(io.Reader) ([]byte, error)
+pkg io/ioutil, func ReadAll(io.Reader) ([]uint8, error)
 pkg io/ioutil, func ReadDir(string) ([]os.FileInfo, error)
-pkg io/ioutil, func ReadFile(string) ([]byte, error)
-pkg io/ioutil, func TempDir(string) (string, error)
-pkg io/ioutil, func TempFile(string) (*os.File, error)
-pkg io/ioutil, func WriteFile(string, []byte, os.FileMode) error
+pkg io/ioutil, func ReadFile(string) ([]uint8, error)
+pkg io/ioutil, func TempDir(string, string) (string, error)
+pkg io/ioutil, func TempFile(string, string) (*os.File, error)
+pkg io/ioutil, func WriteFile(string, []uint8, os.FileMode) error
 pkg io/ioutil, var Discard io.Writer
 pkg log, const Ldate ideal-int
 pkg log, const Llongfile ideal-int
@@ -3831,7 +3831,7 @@ pkg log/syslog (darwin-386), const LOG_ERR Priority
 pkg log/syslog (darwin-386), const LOG_INFO Priority
 pkg log/syslog (darwin-386), const LOG_NOTICE Priority
 pkg log/syslog (darwin-386), const LOG_WARNING Priority
-pkg log/syslog (darwin-386), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (darwin-386), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (darwin-386), func New(Priority, string) (*Writer, error)
 pkg log/syslog (darwin-386), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (darwin-386), method (*Writer) Alert(string) error
@@ -3843,7 +3843,7 @@ pkg log/syslog (darwin-386), method (*Writer) Err(string) error
 pkg log/syslog (darwin-386), method (*Writer) Info(string) error
 pkg log/syslog (darwin-386), method (*Writer) Notice(string) error
 pkg log/syslog (darwin-386), method (*Writer) Warning(string) error
-pkg log/syslog (darwin-386), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (darwin-386), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (darwin-386), type Priority int
 pkg log/syslog (darwin-386), type Writer struct
 pkg log/syslog (darwin-386-cgo), const LOG_ALERT Priority
@@ -3854,7 +3854,7 @@ pkg log/syslog (darwin-386-cgo), const LOG_ERR Priority
 pkg log/syslog (darwin-386-cgo), const LOG_INFO Priority
 pkg log/syslog (darwin-386-cgo), const LOG_NOTICE Priority
 pkg log/syslog (darwin-386-cgo), const LOG_WARNING Priority
-pkg log/syslog (darwin-386-cgo), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (darwin-386-cgo), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (darwin-386-cgo), func New(Priority, string) (*Writer, error)
 pkg log/syslog (darwin-386-cgo), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (darwin-386-cgo), method (*Writer) Alert(string) error
@@ -3866,7 +3866,7 @@ pkg log/syslog (darwin-386-cgo), method (*Writer) Err(string) error
 pkg log/syslog (darwin-386-cgo), method (*Writer) Info(string) error
 pkg log/syslog (darwin-386-cgo), method (*Writer) Notice(string) error
 pkg log/syslog (darwin-386-cgo), method (*Writer) Warning(string) error
-pkg log/syslog (darwin-386-cgo), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (darwin-386-cgo), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (darwin-386-cgo), type Priority int
 pkg log/syslog (darwin-386-cgo), type Writer struct
 pkg log/syslog (darwin-amd64), const LOG_ALERT Priority
@@ -3877,7 +3877,7 @@ pkg log/syslog (darwin-amd64), const LOG_ERR Priority
 pkg log/syslog (darwin-amd64), const LOG_INFO Priority
 pkg log/syslog (darwin-amd64), const LOG_NOTICE Priority
 pkg log/syslog (darwin-amd64), const LOG_WARNING Priority
-pkg log/syslog (darwin-amd64), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (darwin-amd64), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (darwin-amd64), func New(Priority, string) (*Writer, error)
 pkg log/syslog (darwin-amd64), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (darwin-amd64), method (*Writer) Alert(string) error
@@ -3889,7 +3889,7 @@ pkg log/syslog (darwin-amd64), method (*Writer) Err(string) error
 pkg log/syslog (darwin-amd64), method (*Writer) Info(string) error
 pkg log/syslog (darwin-amd64), method (*Writer) Notice(string) error
 pkg log/syslog (darwin-amd64), method (*Writer) Warning(string) error
-pkg log/syslog (darwin-amd64), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (darwin-amd64), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (darwin-amd64), type Priority int
 pkg log/syslog (darwin-amd64), type Writer struct
 pkg log/syslog (darwin-amd64-cgo), const LOG_ALERT Priority
@@ -3900,7 +3900,7 @@ pkg log/syslog (darwin-amd64-cgo), const LOG_ERR Priority
 pkg log/syslog (darwin-amd64-cgo), const LOG_INFO Priority
 pkg log/syslog (darwin-amd64-cgo), const LOG_NOTICE Priority
 pkg log/syslog (darwin-amd64-cgo), const LOG_WARNING Priority
-pkg log/syslog (darwin-amd64-cgo), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (darwin-amd64-cgo), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (darwin-amd64-cgo), func New(Priority, string) (*Writer, error)
 pkg log/syslog (darwin-amd64-cgo), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (darwin-amd64-cgo), method (*Writer) Alert(string) error
@@ -3912,7 +3912,7 @@ pkg log/syslog (darwin-amd64-cgo), method (*Writer) Err(string) error
 pkg log/syslog (darwin-amd64-cgo), method (*Writer) Info(string) error
 pkg log/syslog (darwin-amd64-cgo), method (*Writer) Notice(string) error
 pkg log/syslog (darwin-amd64-cgo), method (*Writer) Warning(string) error
-pkg log/syslog (darwin-amd64-cgo), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (darwin-amd64-cgo), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (darwin-amd64-cgo), type Priority int
 pkg log/syslog (darwin-amd64-cgo), type Writer struct
 pkg log/syslog (freebsd-386), const LOG_ALERT Priority
@@ -3923,7 +3923,7 @@ pkg log/syslog (freebsd-386), const LOG_ERR Priority
 pkg log/syslog (freebsd-386), const LOG_INFO Priority
 pkg log/syslog (freebsd-386), const LOG_NOTICE Priority
 pkg log/syslog (freebsd-386), const LOG_WARNING Priority
-pkg log/syslog (freebsd-386), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (freebsd-386), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (freebsd-386), func New(Priority, string) (*Writer, error)
 pkg log/syslog (freebsd-386), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (freebsd-386), method (*Writer) Alert(string) error
@@ -3935,7 +3935,7 @@ pkg log/syslog (freebsd-386), method (*Writer) Err(string) error
 pkg log/syslog (freebsd-386), method (*Writer) Info(string) error
 pkg log/syslog (freebsd-386), method (*Writer) Notice(string) error
 pkg log/syslog (freebsd-386), method (*Writer) Warning(string) error
-pkg log/syslog (freebsd-386), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (freebsd-386), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (freebsd-386), type Priority int
 pkg log/syslog (freebsd-386), type Writer struct
 pkg log/syslog (freebsd-amd64), const LOG_ALERT Priority
@@ -3946,7 +3946,7 @@ pkg log/syslog (freebsd-amd64), const LOG_ERR Priority
 pkg log/syslog (freebsd-amd64), const LOG_INFO Priority
 pkg log/syslog (freebsd-amd64), const LOG_NOTICE Priority
 pkg log/syslog (freebsd-amd64), const LOG_WARNING Priority
-pkg log/syslog (freebsd-amd64), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (freebsd-amd64), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (freebsd-amd64), func New(Priority, string) (*Writer, error)
 pkg log/syslog (freebsd-amd64), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (freebsd-amd64), method (*Writer) Alert(string) error
@@ -3958,7 +3958,7 @@ pkg log/syslog (freebsd-amd64), method (*Writer) Err(string) error
 pkg log/syslog (freebsd-amd64), method (*Writer) Info(string) error
 pkg log/syslog (freebsd-amd64), method (*Writer) Notice(string) error
 pkg log/syslog (freebsd-amd64), method (*Writer) Warning(string) error
-pkg log/syslog (freebsd-amd64), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (freebsd-amd64), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (freebsd-amd64), type Priority int
 pkg log/syslog (freebsd-amd64), type Writer struct
 pkg log/syslog (linux-386), const LOG_ALERT Priority
@@ -3969,7 +3969,7 @@ pkg log/syslog (linux-386), const LOG_ERR Priority
 pkg log/syslog (linux-386), const LOG_INFO Priority
 pkg log/syslog (linux-386), const LOG_NOTICE Priority
 pkg log/syslog (linux-386), const LOG_WARNING Priority
-pkg log/syslog (linux-386), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (linux-386), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (linux-386), func New(Priority, string) (*Writer, error)
 pkg log/syslog (linux-386), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (linux-386), method (*Writer) Alert(string) error
@@ -3981,7 +3981,7 @@ pkg log/syslog (linux-386), method (*Writer) Err(string) error
 pkg log/syslog (linux-386), method (*Writer) Info(string) error
 pkg log/syslog (linux-386), method (*Writer) Notice(string) error
 pkg log/syslog (linux-386), method (*Writer) Warning(string) error
-pkg log/syslog (linux-386), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (linux-386), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (linux-386), type Priority int
 pkg log/syslog (linux-386), type Writer struct
 pkg log/syslog (linux-386-cgo), const LOG_ALERT Priority
@@ -3992,7 +3992,7 @@ pkg log/syslog (linux-386-cgo), const LOG_ERR Priority
 pkg log/syslog (linux-386-cgo), const LOG_INFO Priority
 pkg log/syslog (linux-386-cgo), const LOG_NOTICE Priority
 pkg log/syslog (linux-386-cgo), const LOG_WARNING Priority
-pkg log/syslog (linux-386-cgo), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (linux-386-cgo), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (linux-386-cgo), func New(Priority, string) (*Writer, error)
 pkg log/syslog (linux-386-cgo), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (linux-386-cgo), method (*Writer) Alert(string) error
@@ -4004,7 +4004,7 @@ pkg log/syslog (linux-386-cgo), method (*Writer) Err(string) error
 pkg log/syslog (linux-386-cgo), method (*Writer) Info(string) error
 pkg log/syslog (linux-386-cgo), method (*Writer) Notice(string) error
 pkg log/syslog (linux-386-cgo), method (*Writer) Warning(string) error
-pkg log/syslog (linux-386-cgo), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (linux-386-cgo), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (linux-386-cgo), type Priority int
 pkg log/syslog (linux-386-cgo), type Writer struct
 pkg log/syslog (linux-amd64), const LOG_ALERT Priority
@@ -4015,7 +4015,7 @@ pkg log/syslog (linux-amd64), const LOG_ERR Priority
 pkg log/syslog (linux-amd64), const LOG_INFO Priority
 pkg log/syslog (linux-amd64), const LOG_NOTICE Priority
 pkg log/syslog (linux-amd64), const LOG_WARNING Priority
-pkg log/syslog (linux-amd64), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (linux-amd64), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (linux-amd64), func New(Priority, string) (*Writer, error)
 pkg log/syslog (linux-amd64), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (linux-amd64), method (*Writer) Alert(string) error
@@ -4027,7 +4027,7 @@ pkg log/syslog (linux-amd64), method (*Writer) Err(string) error
 pkg log/syslog (linux-amd64), method (*Writer) Info(string) error
 pkg log/syslog (linux-amd64), method (*Writer) Notice(string) error
 pkg log/syslog (linux-amd64), method (*Writer) Warning(string) error
-pkg log/syslog (linux-amd64), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (linux-amd64), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (linux-amd64), type Priority int
 pkg log/syslog (linux-amd64), type Writer struct
 pkg log/syslog (linux-amd64-cgo), const LOG_ALERT Priority
@@ -4038,7 +4038,7 @@ pkg log/syslog (linux-amd64-cgo), const LOG_ERR Priority
 pkg log/syslog (linux-amd64-cgo), const LOG_INFO Priority
 pkg log/syslog (linux-amd64-cgo), const LOG_NOTICE Priority
 pkg log/syslog (linux-amd64-cgo), const LOG_WARNING Priority
-pkg log/syslog (linux-amd64-cgo), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (linux-amd64-cgo), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (linux-amd64-cgo), func New(Priority, string) (*Writer, error)
 pkg log/syslog (linux-amd64-cgo), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (linux-amd64-cgo), method (*Writer) Alert(string) error
@@ -4050,7 +4050,7 @@ pkg log/syslog (linux-amd64-cgo), method (*Writer) Err(string) error
 pkg log/syslog (linux-amd64-cgo), method (*Writer) Info(string) error
 pkg log/syslog (linux-amd64-cgo), method (*Writer) Notice(string) error
 pkg log/syslog (linux-amd64-cgo), method (*Writer) Warning(string) error
-pkg log/syslog (linux-amd64-cgo), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (linux-amd64-cgo), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (linux-amd64-cgo), type Priority int
 pkg log/syslog (linux-amd64-cgo), type Writer struct
 pkg log/syslog (linux-arm), const LOG_ALERT Priority
@@ -4061,7 +4061,7 @@ pkg log/syslog (linux-arm), const LOG_ERR Priority
 pkg log/syslog (linux-arm), const LOG_INFO Priority
 pkg log/syslog (linux-arm), const LOG_NOTICE Priority
 pkg log/syslog (linux-arm), const LOG_WARNING Priority
-pkg log/syslog (linux-arm), func Dial(string, Priority, string) (*Writer, error)
+pkg log/syslog (linux-arm), func Dial(string, string, Priority, string) (*Writer, error)
 pkg log/syslog (linux-arm), func New(Priority, string) (*Writer, error)
 pkg log/syslog (linux-arm), func NewLogger(Priority, int) (*log.Logger, error)
 pkg log/syslog (linux-arm), method (*Writer) Alert(string) error
@@ -4073,7 +4073,7 @@ pkg log/syslog (linux-arm), method (*Writer) Err(string) error
 pkg log/syslog (linux-arm), method (*Writer) Info(string) error
 pkg log/syslog (linux-arm), method (*Writer) Notice(string) error
 pkg log/syslog (linux-arm), method (*Writer) Warning(string) error
-pkg log/syslog (linux-arm), method (*Writer) Write([]byte) (int, error)
+pkg log/syslog (linux-arm), method (*Writer) Write([]uint8) (int, error)
 pkg log/syslog (linux-arm), type Priority int
 pkg log/syslog (linux-arm), type Writer struct
 pkg math, const E ideal-float
@@ -4109,14 +4109,14 @@ pkg math, func Acosh(float64) float64
 pkg math, func Asin(float64) float64
 pkg math, func Asinh(float64) float64
 pkg math, func Atan(float64) float64
-pkg math, func Atan2(float64) float64
+pkg math, func Atan2(float64, float64) float64
 pkg math, func Atanh(float64) float64
 pkg math, func Cbrt(float64) float64
 pkg math, func Ceil(float64) float64
-pkg math, func Copysign(float64) float64
+pkg math, func Copysign(float64, float64) float64
 pkg math, func Cos(float64) float64
 pkg math, func Cosh(float64) float64
-pkg math, func Dim(float64) float64
+pkg math, func Dim(float64, float64) float64
 pkg math, func Erf(float64) float64
 pkg math, func Erfc(float64) float64
 pkg math, func Exp(float64) float64
@@ -4129,7 +4129,7 @@ pkg math, func Float64frombits(uint64) float64
 pkg math, func Floor(float64) float64
 pkg math, func Frexp(float64) (float64, int)
 pkg math, func Gamma(float64) float64
-pkg math, func Hypot(float64) float64
+pkg math, func Hypot(float64, float64) float64
 pkg math, func Ilogb(float64) int
 pkg math, func Inf(int) float64
 pkg math, func IsInf(float64, int) bool
@@ -4144,18 +4144,18 @@ pkg math, func Log10(float64) float64
 pkg math, func Log1p(float64) float64
 pkg math, func Log2(float64) float64
 pkg math, func Logb(float64) float64
-pkg math, func Max(float64) float64
-pkg math, func Min(float64) float64
-pkg math, func Mod(float64) float64
+pkg math, func Max(float64, float64) float64
+pkg math, func Min(float64, float64) float64
+pkg math, func Mod(float64, float64) float64
 pkg math, func Modf(float64) (float64, float64)
 pkg math, func NaN() float64
-pkg math, func Nextafter(float64) float64
-pkg math, func Pow(float64) float64
+pkg math, func Nextafter(float64, float64) float64
+pkg math, func Pow(float64, float64) float64
 pkg math, func Pow10(int) float64
-pkg math, func Remainder(float64) float64
+pkg math, func Remainder(float64, float64) float64
 pkg math, func Signbit(float64) bool
 pkg math, func Sin(float64) float64
-pkg math, func Sincos(float64) float64
+pkg math, func Sincos(float64) (float64, float64)
 pkg math, func Sinh(float64) float64
 pkg math, func Sqrt(float64) float64
 pkg math, func Tan(float64) float64
@@ -4166,74 +4166,74 @@ pkg math, func Y1(float64) float64
 pkg math, func Yn(int, float64) float64
 pkg math/big, const MaxBase ideal-int
 pkg math/big, func NewInt(int64) *Int
-pkg math/big, func NewRat(int64) *Rat
+pkg math/big, func NewRat(int64, int64) *Rat
 pkg math/big, method (*Int) Abs(*Int) *Int
-pkg math/big, method (*Int) Add(*Int) *Int
-pkg math/big, method (*Int) And(*Int) *Int
-pkg math/big, method (*Int) AndNot(*Int) *Int
-pkg math/big, method (*Int) Binomial(int64) *Int
+pkg math/big, method (*Int) Add(*Int, *Int) *Int
+pkg math/big, method (*Int) And(*Int, *Int) *Int
+pkg math/big, method (*Int) AndNot(*Int, *Int) *Int
+pkg math/big, method (*Int) Binomial(int64, int64) *Int
 pkg math/big, method (*Int) Bit(int) uint
 pkg math/big, method (*Int) BitLen() int
 pkg math/big, method (*Int) Bits() []Word
-pkg math/big, method (*Int) Bytes() []byte
+pkg math/big, method (*Int) Bytes() []uint8
 pkg math/big, method (*Int) Cmp(*Int) int
-pkg math/big, method (*Int) Div(*Int) *Int
-pkg math/big, method (*Int) DivMod(*Int) (*Int, *Int)
-pkg math/big, method (*Int) Exp(*Int) *Int
-pkg math/big, method (*Int) Format(fmt.State, rune)
-pkg math/big, method (*Int) GCD(*Int) *Int
-pkg math/big, method (*Int) GobDecode([]byte) error
-pkg math/big, method (*Int) GobEncode() ([]byte, error)
+pkg math/big, method (*Int) Div(*Int, *Int) *Int
+pkg math/big, method (*Int) DivMod(*Int, *Int, *Int) (*Int, *Int)
+pkg math/big, method (*Int) Exp(*Int, *Int, *Int) *Int
+pkg math/big, method (*Int) Format(fmt.State, int32)
+pkg math/big, method (*Int) GCD(*Int, *Int, *Int, *Int) *Int
+pkg math/big, method (*Int) GobDecode([]uint8) error
+pkg math/big, method (*Int) GobEncode() ([]uint8, error)
 pkg math/big, method (*Int) Int64() int64
 pkg math/big, method (*Int) Lsh(*Int, uint) *Int
-pkg math/big, method (*Int) Mod(*Int) *Int
-pkg math/big, method (*Int) ModInverse(*Int) *Int
-pkg math/big, method (*Int) Mul(*Int) *Int
-pkg math/big, method (*Int) MulRange(int64) *Int
+pkg math/big, method (*Int) Mod(*Int, *Int) *Int
+pkg math/big, method (*Int) ModInverse(*Int, *Int) *Int
+pkg math/big, method (*Int) Mul(*Int, *Int) *Int
+pkg math/big, method (*Int) MulRange(int64, int64) *Int
 pkg math/big, method (*Int) Neg(*Int) *Int
 pkg math/big, method (*Int) Not(*Int) *Int
-pkg math/big, method (*Int) Or(*Int) *Int
+pkg math/big, method (*Int) Or(*Int, *Int) *Int
 pkg math/big, method (*Int) ProbablyPrime(int) bool
-pkg math/big, method (*Int) Quo(*Int) *Int
-pkg math/big, method (*Int) QuoRem(*Int) (*Int, *Int)
+pkg math/big, method (*Int) Quo(*Int, *Int) *Int
+pkg math/big, method (*Int) QuoRem(*Int, *Int, *Int) (*Int, *Int)
 pkg math/big, method (*Int) Rand(*rand.Rand, *Int) *Int
-pkg math/big, method (*Int) Rem(*Int) *Int
+pkg math/big, method (*Int) Rem(*Int, *Int) *Int
 pkg math/big, method (*Int) Rsh(*Int, uint) *Int
-pkg math/big, method (*Int) Scan(fmt.ScanState, rune) error
+pkg math/big, method (*Int) Scan(fmt.ScanState, int32) error
 pkg math/big, method (*Int) Set(*Int) *Int
 pkg math/big, method (*Int) SetBit(*Int, int, uint) *Int
 pkg math/big, method (*Int) SetBits([]Word) *Int
-pkg math/big, method (*Int) SetBytes([]byte) *Int
+pkg math/big, method (*Int) SetBytes([]uint8) *Int
 pkg math/big, method (*Int) SetInt64(int64) *Int
 pkg math/big, method (*Int) SetString(string, int) (*Int, bool)
 pkg math/big, method (*Int) Sign() int
 pkg math/big, method (*Int) String() string
-pkg math/big, method (*Int) Sub(*Int) *Int
-pkg math/big, method (*Int) Xor(*Int) *Int
+pkg math/big, method (*Int) Sub(*Int, *Int) *Int
+pkg math/big, method (*Int) Xor(*Int, *Int) *Int
 pkg math/big, method (*Rat) Abs(*Rat) *Rat
-pkg math/big, method (*Rat) Add(*Rat) *Rat
+pkg math/big, method (*Rat) Add(*Rat, *Rat) *Rat
 pkg math/big, method (*Rat) Cmp(*Rat) int
 pkg math/big, method (*Rat) Denom() *Int
 pkg math/big, method (*Rat) FloatString(int) string
-pkg math/big, method (*Rat) GobDecode([]byte) error
-pkg math/big, method (*Rat) GobEncode() ([]byte, error)
+pkg math/big, method (*Rat) GobDecode([]uint8) error
+pkg math/big, method (*Rat) GobEncode() ([]uint8, error)
 pkg math/big, method (*Rat) Inv(*Rat) *Rat
 pkg math/big, method (*Rat) IsInt() bool
-pkg math/big, method (*Rat) Mul(*Rat) *Rat
+pkg math/big, method (*Rat) Mul(*Rat, *Rat) *Rat
 pkg math/big, method (*Rat) Neg(*Rat) *Rat
 pkg math/big, method (*Rat) Num() *Int
-pkg math/big, method (*Rat) Quo(*Rat) *Rat
+pkg math/big, method (*Rat) Quo(*Rat, *Rat) *Rat
 pkg math/big, method (*Rat) RatString() string
-pkg math/big, method (*Rat) Scan(fmt.ScanState, rune) error
+pkg math/big, method (*Rat) Scan(fmt.ScanState, int32) error
 pkg math/big, method (*Rat) Set(*Rat) *Rat
-pkg math/big, method (*Rat) SetFrac(*Int) *Rat
-pkg math/big, method (*Rat) SetFrac64(int64) *Rat
+pkg math/big, method (*Rat) SetFrac(*Int, *Int) *Rat
+pkg math/big, method (*Rat) SetFrac64(int64, int64) *Rat
 pkg math/big, method (*Rat) SetInt(*Int) *Rat
 pkg math/big, method (*Rat) SetInt64(int64) *Rat
 pkg math/big, method (*Rat) SetString(string) (*Rat, bool)
 pkg math/big, method (*Rat) Sign() int
 pkg math/big, method (*Rat) String() string
-pkg math/big, method (*Rat) Sub(*Rat) *Rat
+pkg math/big, method (*Rat) Sub(*Rat, *Rat) *Rat
 pkg math/big, type Int struct
 pkg math/big, type Rat struct
 pkg math/big, type Word uintptr
@@ -4256,9 +4256,9 @@ pkg math/cmplx, func Log(complex128) complex128
 pkg math/cmplx, func Log10(complex128) complex128
 pkg math/cmplx, func NaN() complex128
 pkg math/cmplx, func Phase(complex128) float64
-pkg math/cmplx, func Polar(complex128) float64
-pkg math/cmplx, func Pow(complex128) complex128
-pkg math/cmplx, func Rect(float64) complex128
+pkg math/cmplx, func Polar(complex128) (float64, float64)
+pkg math/cmplx, func Pow(complex128, complex128) complex128
+pkg math/cmplx, func Rect(float64, float64) complex128
 pkg math/cmplx, func Sin(complex128) complex128
 pkg math/cmplx, func Sinh(complex128) complex128
 pkg math/cmplx, func Sqrt(complex128) complex128
@@ -4299,7 +4299,7 @@ pkg math/rand, type Source interface { Int63, Seed }
 pkg math/rand, type Source interface, Int63() int64
 pkg math/rand, type Source interface, Seed(int64)
 pkg math/rand, type Zipf struct
-pkg mime, func AddExtensionType(string) error
+pkg mime, func AddExtensionType(string, string) error
 pkg mime, func FormatMediaType(string, map[string]string) string
 pkg mime, func ParseMediaType(string) (string, map[string]string, error)
 pkg mime, func TypeByExtension(string) string
@@ -4310,20 +4310,20 @@ pkg mime/multipart, method (*Form) RemoveAll() error
 pkg mime/multipart, method (*Part) Close() error
 pkg mime/multipart, method (*Part) FileName() string
 pkg mime/multipart, method (*Part) FormName() string
-pkg mime/multipart, method (*Part) Read([]byte) (int, error)
+pkg mime/multipart, method (*Part) Read([]uint8) (int, error)
 pkg mime/multipart, method (*Reader) NextPart() (*Part, error)
 pkg mime/multipart, method (*Reader) ReadForm(int64) (*Form, error)
 pkg mime/multipart, method (*Writer) Boundary() string
 pkg mime/multipart, method (*Writer) Close() error
 pkg mime/multipart, method (*Writer) CreateFormField(string) (io.Writer, error)
-pkg mime/multipart, method (*Writer) CreateFormFile(string) (io.Writer, error)
+pkg mime/multipart, method (*Writer) CreateFormFile(string, string) (io.Writer, error)
 pkg mime/multipart, method (*Writer) CreatePart(textproto.MIMEHeader) (io.Writer, error)
 pkg mime/multipart, method (*Writer) FormDataContentType() string
-pkg mime/multipart, method (*Writer) WriteField(string) error
+pkg mime/multipart, method (*Writer) WriteField(string, string) error
 pkg mime/multipart, type File interface { Close, Read, ReadAt, Seek }
 pkg mime/multipart, type File interface, Close() error
-pkg mime/multipart, type File interface, Read([]byte) (int, error)
-pkg mime/multipart, type File interface, ReadAt([]byte, int64) (int, error)
+pkg mime/multipart, type File interface, Read([]uint8) (int, error)
+pkg mime/multipart, type File interface, ReadAt([]uint8, int64) (int, error)
 pkg mime/multipart, type File interface, Seek(int64, int) (int64, error)
 pkg mime/multipart, type FileHeader struct
 pkg mime/multipart, type FileHeader struct, Filename string
@@ -4342,27 +4342,27 @@ pkg net, const FlagPointToPoint Flags
 pkg net, const FlagUp Flags
 pkg net, const IPv4len ideal-int
 pkg net, const IPv6len ideal-int
-pkg net, func CIDRMask(int) IPMask
-pkg net, func Dial(string) (Conn, error)
-pkg net, func DialIP(string, *IPAddr) (*IPConn, error)
-pkg net, func DialTCP(string, *TCPAddr) (*TCPConn, error)
-pkg net, func DialTimeout(string, time.Duration) (Conn, error)
-pkg net, func DialUDP(string, *UDPAddr) (*UDPConn, error)
-pkg net, func DialUnix(string, *UnixAddr) (*UnixConn, error)
+pkg net, func CIDRMask(int, int) IPMask
+pkg net, func Dial(string, string) (Conn, error)
+pkg net, func DialIP(string, *IPAddr, *IPAddr) (*IPConn, error)
+pkg net, func DialTCP(string, *TCPAddr, *TCPAddr) (*TCPConn, error)
+pkg net, func DialTimeout(string, string, time.Duration) (Conn, error)
+pkg net, func DialUDP(string, *UDPAddr, *UDPAddr) (*UDPConn, error)
+pkg net, func DialUnix(string, *UnixAddr, *UnixAddr) (*UnixConn, error)
 pkg net, func FileConn(*os.File) (Conn, error)
 pkg net, func FileListener(*os.File) (Listener, error)
 pkg net, func FilePacketConn(*os.File) (PacketConn, error)
-pkg net, func IPv4(byte) IP
-pkg net, func IPv4Mask(byte) IPMask
+pkg net, func IPv4(uint8, uint8, uint8, uint8) IP
+pkg net, func IPv4Mask(uint8, uint8, uint8, uint8) IPMask
 pkg net, func InterfaceAddrs() ([]Addr, error)
 pkg net, func InterfaceByIndex(int) (*Interface, error)
 pkg net, func InterfaceByName(string) (*Interface, error)
 pkg net, func Interfaces() ([]Interface, error)
-pkg net, func JoinHostPort(string) string
-pkg net, func Listen(string) (Listener, error)
+pkg net, func JoinHostPort(string, string) string
+pkg net, func Listen(string, string) (Listener, error)
 pkg net, func ListenIP(string, *IPAddr) (*IPConn, error)
 pkg net, func ListenMulticastUDP(string, *Interface, *UDPAddr) (*UDPConn, error)
-pkg net, func ListenPacket(string) (PacketConn, error)
+pkg net, func ListenPacket(string, string) (PacketConn, error)
 pkg net, func ListenTCP(string, *TCPAddr) (*TCPListener, error)
 pkg net, func ListenUDP(string, *UDPAddr) (*UDPConn, error)
 pkg net, func ListenUnix(string, *UnixAddr) (*UnixListener, error)
@@ -4372,18 +4372,18 @@ pkg net, func LookupCNAME(string) (string, error)
 pkg net, func LookupHost(string) ([]string, error)
 pkg net, func LookupIP(string) ([]IP, error)
 pkg net, func LookupMX(string) ([]*MX, error)
-pkg net, func LookupPort(string) (int, error)
-pkg net, func LookupSRV(string) (string, []*SRV, error)
+pkg net, func LookupPort(string, string) (int, error)
+pkg net, func LookupSRV(string, string, string) (string, []*SRV, error)
 pkg net, func LookupTXT(string) ([]string, error)
 pkg net, func ParseCIDR(string) (IP, *IPNet, error)
 pkg net, func ParseIP(string) IP
 pkg net, func ParseMAC(string) (HardwareAddr, error)
 pkg net, func Pipe() (Conn, Conn)
-pkg net, func ResolveIPAddr(string) (*IPAddr, error)
-pkg net, func ResolveTCPAddr(string) (*TCPAddr, error)
-pkg net, func ResolveUDPAddr(string) (*UDPAddr, error)
-pkg net, func ResolveUnixAddr(string) (*UnixAddr, error)
-pkg net, func SplitHostPort(string) (string, error)
+pkg net, func ResolveIPAddr(string, string) (*IPAddr, error)
+pkg net, func ResolveTCPAddr(string, string) (*TCPAddr, error)
+pkg net, func ResolveUDPAddr(string, string) (*UDPAddr, error)
+pkg net, func ResolveUnixAddr(string, string) (*UnixAddr, error)
+pkg net, func SplitHostPort(string) (string, string, error)
 pkg net, method (*AddrError) Error() string
 pkg net, method (*AddrError) Temporary() bool
 pkg net, method (*AddrError) Timeout() bool
@@ -4398,18 +4398,18 @@ pkg net, method (*IPAddr) String() string
 pkg net, method (*IPConn) Close() error
 pkg net, method (*IPConn) File() (*os.File, error)
 pkg net, method (*IPConn) LocalAddr() Addr
-pkg net, method (*IPConn) Read([]byte) (int, error)
-pkg net, method (*IPConn) ReadFrom([]byte) (int, Addr, error)
-pkg net, method (*IPConn) ReadFromIP([]byte) (int, *IPAddr, error)
+pkg net, method (*IPConn) Read([]uint8) (int, error)
+pkg net, method (*IPConn) ReadFrom([]uint8) (int, Addr, error)
+pkg net, method (*IPConn) ReadFromIP([]uint8) (int, *IPAddr, error)
 pkg net, method (*IPConn) RemoteAddr() Addr
 pkg net, method (*IPConn) SetDeadline(time.Time) error
 pkg net, method (*IPConn) SetReadBuffer(int) error
 pkg net, method (*IPConn) SetReadDeadline(time.Time) error
 pkg net, method (*IPConn) SetWriteBuffer(int) error
 pkg net, method (*IPConn) SetWriteDeadline(time.Time) error
-pkg net, method (*IPConn) Write([]byte) (int, error)
-pkg net, method (*IPConn) WriteTo([]byte, Addr) (int, error)
-pkg net, method (*IPConn) WriteToIP([]byte, *IPAddr) (int, error)
+pkg net, method (*IPConn) Write([]uint8) (int, error)
+pkg net, method (*IPConn) WriteTo([]uint8, Addr) (int, error)
+pkg net, method (*IPConn) WriteToIP([]uint8, *IPAddr) (int, error)
 pkg net, method (*IPNet) Contains(IP) bool
 pkg net, method (*IPNet) Network() string
 pkg net, method (*IPNet) String() string
@@ -4426,7 +4426,7 @@ pkg net, method (*TCPConn) CloseRead() error
 pkg net, method (*TCPConn) CloseWrite() error
 pkg net, method (*TCPConn) File() (*os.File, error)
 pkg net, method (*TCPConn) LocalAddr() Addr
-pkg net, method (*TCPConn) Read([]byte) (int, error)
+pkg net, method (*TCPConn) Read([]uint8) (int, error)
 pkg net, method (*TCPConn) ReadFrom(io.Reader) (int64, error)
 pkg net, method (*TCPConn) RemoteAddr() Addr
 pkg net, method (*TCPConn) SetDeadline(time.Time) error
@@ -4437,7 +4437,7 @@ pkg net, method (*TCPConn) SetReadBuffer(int) error
 pkg net, method (*TCPConn) SetReadDeadline(time.Time) error
 pkg net, method (*TCPConn) SetWriteBuffer(int) error
 pkg net, method (*TCPConn) SetWriteDeadline(time.Time) error
-pkg net, method (*TCPConn) Write([]byte) (int, error)
+pkg net, method (*TCPConn) Write([]uint8) (int, error)
 pkg net, method (*TCPListener) Accept() (Conn, error)
 pkg net, method (*TCPListener) AcceptTCP() (*TCPConn, error)
 pkg net, method (*TCPListener) Addr() Addr
@@ -4449,37 +4449,37 @@ pkg net, method (*UDPAddr) String() string
 pkg net, method (*UDPConn) Close() error
 pkg net, method (*UDPConn) File() (*os.File, error)
 pkg net, method (*UDPConn) LocalAddr() Addr
-pkg net, method (*UDPConn) Read([]byte) (int, error)
-pkg net, method (*UDPConn) ReadFrom([]byte) (int, Addr, error)
-pkg net, method (*UDPConn) ReadFromUDP([]byte) (int, *UDPAddr, error)
+pkg net, method (*UDPConn) Read([]uint8) (int, error)
+pkg net, method (*UDPConn) ReadFrom([]uint8) (int, Addr, error)
+pkg net, method (*UDPConn) ReadFromUDP([]uint8) (int, *UDPAddr, error)
 pkg net, method (*UDPConn) RemoteAddr() Addr
 pkg net, method (*UDPConn) SetDeadline(time.Time) error
 pkg net, method (*UDPConn) SetReadBuffer(int) error
 pkg net, method (*UDPConn) SetReadDeadline(time.Time) error
 pkg net, method (*UDPConn) SetWriteBuffer(int) error
 pkg net, method (*UDPConn) SetWriteDeadline(time.Time) error
-pkg net, method (*UDPConn) Write([]byte) (int, error)
-pkg net, method (*UDPConn) WriteTo([]byte, Addr) (int, error)
-pkg net, method (*UDPConn) WriteToUDP([]byte, *UDPAddr) (int, error)
+pkg net, method (*UDPConn) Write([]uint8) (int, error)
+pkg net, method (*UDPConn) WriteTo([]uint8, Addr) (int, error)
+pkg net, method (*UDPConn) WriteToUDP([]uint8, *UDPAddr) (int, error)
 pkg net, method (*UnixAddr) Network() string
 pkg net, method (*UnixAddr) String() string
 pkg net, method (*UnixConn) Close() error
 pkg net, method (*UnixConn) File() (*os.File, error)
 pkg net, method (*UnixConn) LocalAddr() Addr
-pkg net, method (*UnixConn) Read([]byte) (int, error)
-pkg net, method (*UnixConn) ReadFrom([]byte) (int, Addr, error)
-pkg net, method (*UnixConn) ReadFromUnix([]byte) (int, *UnixAddr, error)
-pkg net, method (*UnixConn) ReadMsgUnix([]byte) (int, *UnixAddr, error)
+pkg net, method (*UnixConn) Read([]uint8) (int, error)
+pkg net, method (*UnixConn) ReadFrom([]uint8) (int, Addr, error)
+pkg net, method (*UnixConn) ReadFromUnix([]uint8) (int, *UnixAddr, error)
+pkg net, method (*UnixConn) ReadMsgUnix([]uint8, []uint8) (int, int, int, *UnixAddr, error)
 pkg net, method (*UnixConn) RemoteAddr() Addr
 pkg net, method (*UnixConn) SetDeadline(time.Time) error
 pkg net, method (*UnixConn) SetReadBuffer(int) error
 pkg net, method (*UnixConn) SetReadDeadline(time.Time) error
 pkg net, method (*UnixConn) SetWriteBuffer(int) error
 pkg net, method (*UnixConn) SetWriteDeadline(time.Time) error
-pkg net, method (*UnixConn) Write([]byte) (int, error)
-pkg net, method (*UnixConn) WriteMsgUnix([]byte, *UnixAddr) (int, error)
-pkg net, method (*UnixConn) WriteTo([]byte, Addr) (int, error)
-pkg net, method (*UnixConn) WriteToUnix([]byte, *UnixAddr) (int, error)
+pkg net, method (*UnixConn) Write([]uint8) (int, error)
+pkg net, method (*UnixConn) WriteMsgUnix([]uint8, []uint8, *UnixAddr) (int, int, error)
+pkg net, method (*UnixConn) WriteTo([]uint8, Addr) (int, error)
+pkg net, method (*UnixConn) WriteToUnix([]uint8, *UnixAddr) (int, error)
 pkg net, method (*UnixListener) Accept() (Conn, error)
 pkg net, method (*UnixListener) AcceptUnix() (*UnixConn, error)
 pkg net, method (*UnixListener) Addr() Addr
@@ -4501,7 +4501,7 @@ pkg net, method (IP) Mask(IPMask) IP
 pkg net, method (IP) String() string
 pkg net, method (IP) To16() IP
 pkg net, method (IP) To4() IP
-pkg net, method (IPMask) Size() int
+pkg net, method (IPMask) Size() (int, int)
 pkg net, method (IPMask) String() string
 pkg net, method (InvalidAddrError) Error() string
 pkg net, method (InvalidAddrError) Temporary() bool
@@ -4518,12 +4518,12 @@ pkg net, type AddrError struct, Err string
 pkg net, type Conn interface { Close, LocalAddr, Read, RemoteAddr, SetDeadline, SetReadDeadline, SetWriteDeadline, Write }
 pkg net, type Conn interface, Close() error
 pkg net, type Conn interface, LocalAddr() Addr
-pkg net, type Conn interface, Read([]byte) (int, error)
+pkg net, type Conn interface, Read([]uint8) (int, error)
 pkg net, type Conn interface, RemoteAddr() Addr
 pkg net, type Conn interface, SetDeadline(time.Time) error
 pkg net, type Conn interface, SetReadDeadline(time.Time) error
 pkg net, type Conn interface, SetWriteDeadline(time.Time) error
-pkg net, type Conn interface, Write([]byte) (int, error)
+pkg net, type Conn interface, Write([]uint8) (int, error)
 pkg net, type DNSConfigError struct
 pkg net, type DNSConfigError struct, Err error
 pkg net, type DNSError struct
@@ -4536,12 +4536,12 @@ pkg net, type Error interface, Error() string
 pkg net, type Error interface, Temporary() bool
 pkg net, type Error interface, Timeout() bool
 pkg net, type Flags uint
-pkg net, type HardwareAddr []byte
-pkg net, type IP []byte
+pkg net, type HardwareAddr []uint8
+pkg net, type IP []uint8
 pkg net, type IPAddr struct
 pkg net, type IPAddr struct, IP IP
 pkg net, type IPConn struct
-pkg net, type IPMask []byte
+pkg net, type IPMask []uint8
 pkg net, type IPNet struct
 pkg net, type IPNet struct, IP IP
 pkg net, type IPNet struct, Mask IPMask
@@ -4567,11 +4567,11 @@ pkg net, type OpError struct, Op string
 pkg net, type PacketConn interface { Close, LocalAddr, ReadFrom, SetDeadline, SetReadDeadline, SetWriteDeadline, WriteTo }
 pkg net, type PacketConn interface, Close() error
 pkg net, type PacketConn interface, LocalAddr() Addr
-pkg net, type PacketConn interface, ReadFrom([]byte) (int, Addr, error)
+pkg net, type PacketConn interface, ReadFrom([]uint8) (int, Addr, error)
 pkg net, type PacketConn interface, SetDeadline(time.Time) error
 pkg net, type PacketConn interface, SetReadDeadline(time.Time) error
 pkg net, type PacketConn interface, SetWriteDeadline(time.Time) error
-pkg net, type PacketConn interface, WriteTo([]byte, Addr) (int, error)
+pkg net, type PacketConn interface, WriteTo([]uint8, Addr) (int, error)
 pkg net, type ParseError struct
 pkg net, type ParseError struct, Text string
 pkg net, type ParseError struct, Type string
@@ -4651,7 +4651,7 @@ pkg net/http, const StatusUnsupportedMediaType ideal-int
 pkg net/http, const StatusUseProxy ideal-int
 pkg net/http, const TimeFormat ideal-string
 pkg net/http, func CanonicalHeaderKey(string) string
-pkg net/http, func DetectContentType([]byte) string
+pkg net/http, func DetectContentType([]uint8) string
 pkg net/http, func Error(ResponseWriter, string, int)
 pkg net/http, func FileServer(FileSystem) Handler
 pkg net/http, func Get(string) (*Response, error)
@@ -4662,11 +4662,11 @@ pkg net/http, func ListenAndServe(string, Handler) error
 pkg net/http, func ListenAndServeTLS(string, string, string, Handler) error
 pkg net/http, func MaxBytesReader(ResponseWriter, io.ReadCloser, int64) io.ReadCloser
 pkg net/http, func NewFileTransport(FileSystem) RoundTripper
-pkg net/http, func NewRequest(string, io.Reader) (*Request, error)
+pkg net/http, func NewRequest(string, string, io.Reader) (*Request, error)
 pkg net/http, func NewServeMux() *ServeMux
 pkg net/http, func NotFound(ResponseWriter, *Request)
 pkg net/http, func NotFoundHandler() Handler
-pkg net/http, func ParseHTTPVersion(string) (int, bool)
+pkg net/http, func ParseHTTPVersion(string) (int, int, bool)
 pkg net/http, func Post(string, string, io.Reader) (*Response, error)
 pkg net/http, func PostForm(string, url.Values) (*Response, error)
 pkg net/http, func ProxyFromEnvironment(*Request) (*url.URL, error)
@@ -4697,31 +4697,31 @@ pkg net/http, method (*Request) FormValue(string) string
 pkg net/http, method (*Request) MultipartReader() (*multipart.Reader, error)
 pkg net/http, method (*Request) ParseForm() error
 pkg net/http, method (*Request) ParseMultipartForm(int64) error
-pkg net/http, method (*Request) ProtoAtLeast(int) bool
+pkg net/http, method (*Request) ProtoAtLeast(int, int) bool
 pkg net/http, method (*Request) Referer() string
-pkg net/http, method (*Request) SetBasicAuth(string)
+pkg net/http, method (*Request) SetBasicAuth(string, string)
 pkg net/http, method (*Request) UserAgent() string
 pkg net/http, method (*Request) Write(io.Writer) error
 pkg net/http, method (*Request) WriteProxy(io.Writer) error
 pkg net/http, method (*Response) Cookies() []*Cookie
 pkg net/http, method (*Response) Location() (*url.URL, error)
-pkg net/http, method (*Response) ProtoAtLeast(int) bool
+pkg net/http, method (*Response) ProtoAtLeast(int, int) bool
 pkg net/http, method (*Response) Write(io.Writer) error
 pkg net/http, method (*ServeMux) Handle(string, Handler)
 pkg net/http, method (*ServeMux) HandleFunc(string, func(ResponseWriter, *Request))
 pkg net/http, method (*ServeMux) ServeHTTP(ResponseWriter, *Request)
 pkg net/http, method (*Server) ListenAndServe() error
-pkg net/http, method (*Server) ListenAndServeTLS(string) error
+pkg net/http, method (*Server) ListenAndServeTLS(string, string) error
 pkg net/http, method (*Server) Serve(net.Listener) error
 pkg net/http, method (*Transport) CloseIdleConnections()
 pkg net/http, method (*Transport) RegisterProtocol(string, RoundTripper)
 pkg net/http, method (*Transport) RoundTrip(*Request) (*Response, error)
 pkg net/http, method (Dir) Open(string) (File, error)
 pkg net/http, method (HandlerFunc) ServeHTTP(ResponseWriter, *Request)
-pkg net/http, method (Header) Add(string)
+pkg net/http, method (Header) Add(string, string)
 pkg net/http, method (Header) Del(string)
 pkg net/http, method (Header) Get(string) string
-pkg net/http, method (Header) Set(string)
+pkg net/http, method (Header) Set(string, string)
 pkg net/http, method (Header) Write(io.Writer) error
 pkg net/http, method (Header) WriteSubset(io.Writer, map[string]bool) error
 pkg net/http, type Client struct
@@ -4746,7 +4746,7 @@ pkg net/http, type CookieJar interface, SetCookies(*url.URL, []*Cookie)
 pkg net/http, type Dir string
 pkg net/http, type File interface { Close, Read, Readdir, Seek, Stat }
 pkg net/http, type File interface, Close() error
-pkg net/http, type File interface, Read([]byte) (int, error)
+pkg net/http, type File interface, Read([]uint8) (int, error)
 pkg net/http, type File interface, Readdir(int) ([]os.FileInfo, error)
 pkg net/http, type File interface, Seek(int64, int) (int64, error)
 pkg net/http, type File interface, Stat() (os.FileInfo, error)
@@ -4795,7 +4795,7 @@ pkg net/http, type Response struct, Trailer Header
 pkg net/http, type Response struct, TransferEncoding []string
 pkg net/http, type ResponseWriter interface { Header, Write, WriteHeader }
 pkg net/http, type ResponseWriter interface, Header() Header
-pkg net/http, type ResponseWriter interface, Write([]byte) (int, error)
+pkg net/http, type ResponseWriter interface, Write([]uint8) (int, error)
 pkg net/http, type ResponseWriter interface, WriteHeader(int)
 pkg net/http, type RoundTripper interface { RoundTrip }
 pkg net/http, type RoundTripper interface, RoundTrip(*Request) (*Response, error)
@@ -4808,7 +4808,7 @@ pkg net/http, type Server struct, ReadTimeout time.Duration
 pkg net/http, type Server struct, TLSConfig *tls.Config
 pkg net/http, type Server struct, WriteTimeout time.Duration
 pkg net/http, type Transport struct
-pkg net/http, type Transport struct, Dial func(string) (net.Conn, error)
+pkg net/http, type Transport struct, Dial func(string, string) (net.Conn, error)
 pkg net/http, type Transport struct, DisableCompression bool
 pkg net/http, type Transport struct, DisableKeepAlives bool
 pkg net/http, type Transport struct, MaxIdleConnsPerHost int
@@ -4855,7 +4855,7 @@ pkg net/http/httptest, func NewTLSServer(http.Handler) *Server
 pkg net/http/httptest, func NewUnstartedServer(http.Handler) *Server
 pkg net/http/httptest, method (*ResponseRecorder) Flush()
 pkg net/http/httptest, method (*ResponseRecorder) Header() http.Header
-pkg net/http/httptest, method (*ResponseRecorder) Write([]byte) (int, error)
+pkg net/http/httptest, method (*ResponseRecorder) Write([]uint8) (int, error)
 pkg net/http/httptest, method (*ResponseRecorder) WriteHeader(int)
 pkg net/http/httptest, method (*Server) Close()
 pkg net/http/httptest, method (*Server) CloseClientConnections()
@@ -4871,9 +4871,9 @@ pkg net/http/httptest, type Server struct, Config *http.Server
 pkg net/http/httptest, type Server struct, Listener net.Listener
 pkg net/http/httptest, type Server struct, TLS *tls.Config
 pkg net/http/httptest, type Server struct, URL string
-pkg net/http/httputil, func DumpRequest(*http.Request, bool) ([]byte, error)
-pkg net/http/httputil, func DumpRequestOut(*http.Request, bool) ([]byte, error)
-pkg net/http/httputil, func DumpResponse(*http.Response, bool) ([]byte, error)
+pkg net/http/httputil, func DumpRequest(*http.Request, bool) ([]uint8, error)
+pkg net/http/httputil, func DumpRequestOut(*http.Request, bool) ([]uint8, error)
+pkg net/http/httputil, func DumpResponse(*http.Response, bool) ([]uint8, error)
 pkg net/http/httputil, func NewChunkedReader(io.Reader) io.Reader
 pkg net/http/httputil, func NewChunkedWriter(io.Writer) io.WriteCloser
 pkg net/http/httputil, func NewClientConn(net.Conn, *bufio.Reader) *ClientConn
@@ -4923,9 +4923,9 @@ pkg net/mail, var ErrHeaderNotPresent error
 pkg net/rpc, const DefaultDebugPath ideal-string
 pkg net/rpc, const DefaultRPCPath ideal-string
 pkg net/rpc, func Accept(net.Listener)
-pkg net/rpc, func Dial(string) (*Client, error)
-pkg net/rpc, func DialHTTP(string) (*Client, error)
-pkg net/rpc, func DialHTTPPath(string) (*Client, error)
+pkg net/rpc, func Dial(string, string) (*Client, error)
+pkg net/rpc, func DialHTTP(string, string) (*Client, error)
+pkg net/rpc, func DialHTTPPath(string, string, string) (*Client, error)
 pkg net/rpc, func HandleHTTP()
 pkg net/rpc, func NewClient(io.ReadWriteCloser) *Client
 pkg net/rpc, func NewClientWithCodec(ClientCodec) *Client
@@ -4939,7 +4939,7 @@ pkg net/rpc, method (*Client) Call(string, interface{}, interface{}) error
 pkg net/rpc, method (*Client) Close() error
 pkg net/rpc, method (*Client) Go(string, interface{}, interface{}, chan *Call) *Call
 pkg net/rpc, method (*Server) Accept(net.Listener)
-pkg net/rpc, method (*Server) HandleHTTP(string)
+pkg net/rpc, method (*Server) HandleHTTP(string, string)
 pkg net/rpc, method (*Server) Register(interface{}) error
 pkg net/rpc, method (*Server) RegisterName(string, interface{}) error
 pkg net/rpc, method (*Server) ServeCodec(ServerCodec)
@@ -4975,16 +4975,16 @@ pkg net/rpc, type ServerCodec interface, WriteResponse(*Response, interface{}) e
 pkg net/rpc, type ServerError string
 pkg net/rpc, var DefaultServer *Server
 pkg net/rpc, var ErrShutdown error
-pkg net/rpc/jsonrpc, func Dial(string) (*rpc.Client, error)
+pkg net/rpc/jsonrpc, func Dial(string, string) (*rpc.Client, error)
 pkg net/rpc/jsonrpc, func NewClient(io.ReadWriteCloser) *rpc.Client
 pkg net/rpc/jsonrpc, func NewClientCodec(io.ReadWriteCloser) rpc.ClientCodec
 pkg net/rpc/jsonrpc, func NewServerCodec(io.ReadWriteCloser) rpc.ServerCodec
 pkg net/rpc/jsonrpc, func ServeConn(io.ReadWriteCloser)
-pkg net/smtp, func CRAMMD5Auth(string) Auth
+pkg net/smtp, func CRAMMD5Auth(string, string) Auth
 pkg net/smtp, func Dial(string) (*Client, error)
 pkg net/smtp, func NewClient(net.Conn, string) (*Client, error)
-pkg net/smtp, func PlainAuth(string) Auth
-pkg net/smtp, func SendMail(string, Auth, string, []string, []byte) error
+pkg net/smtp, func PlainAuth(string, string, string, string) Auth
+pkg net/smtp, func SendMail(string, Auth, string, []string, []uint8) error
 pkg net/smtp, method (*Client) Auth(Auth) error
 pkg net/smtp, method (*Client) Data() (io.WriteCloser, error)
 pkg net/smtp, method (*Client) Extension(string) (bool, string)
@@ -4995,8 +4995,8 @@ pkg net/smtp, method (*Client) Reset() error
 pkg net/smtp, method (*Client) StartTLS(*tls.Config) error
 pkg net/smtp, method (*Client) Verify(string) error
 pkg net/smtp, type Auth interface { Next, Start }
-pkg net/smtp, type Auth interface, Next([]byte, bool) ([]byte, error)
-pkg net/smtp, type Auth interface, Start(*ServerInfo) (string, []byte, error)
+pkg net/smtp, type Auth interface, Next([]uint8, bool) ([]uint8, error)
+pkg net/smtp, type Auth interface, Start(*ServerInfo) (string, []uint8, error)
 pkg net/smtp, type Client struct
 pkg net/smtp, type Client struct, Text *textproto.Conn
 pkg net/smtp, type ServerInfo struct
@@ -5004,7 +5004,7 @@ pkg net/smtp, type ServerInfo struct, Auth []string
 pkg net/smtp, type ServerInfo struct, Name string
 pkg net/smtp, type ServerInfo struct, TLS bool
 pkg net/textproto, func CanonicalMIMEHeaderKey(string) string
-pkg net/textproto, func Dial(string) (*Conn, error)
+pkg net/textproto, func Dial(string, string) (*Conn, error)
 pkg net/textproto, func NewConn(io.ReadWriteCloser) *Conn
 pkg net/textproto, func NewReader(*bufio.Reader) *Reader
 pkg net/textproto, func NewWriter(*bufio.Writer) *Writer
@@ -5018,11 +5018,11 @@ pkg net/textproto, method (*Conn) Next() uint
 pkg net/textproto, method (*Conn) PrintfLine(string, ...interface{}) error
 pkg net/textproto, method (*Conn) ReadCodeLine(int) (int, string, error)
 pkg net/textproto, method (*Conn) ReadContinuedLine() (string, error)
-pkg net/textproto, method (*Conn) ReadContinuedLineBytes() ([]byte, error)
-pkg net/textproto, method (*Conn) ReadDotBytes() ([]byte, error)
+pkg net/textproto, method (*Conn) ReadContinuedLineBytes() ([]uint8, error)
+pkg net/textproto, method (*Conn) ReadDotBytes() ([]uint8, error)
 pkg net/textproto, method (*Conn) ReadDotLines() ([]string, error)
 pkg net/textproto, method (*Conn) ReadLine() (string, error)
-pkg net/textproto, method (*Conn) ReadLineBytes() ([]byte, error)
+pkg net/textproto, method (*Conn) ReadLineBytes() ([]uint8, error)
 pkg net/textproto, method (*Conn) ReadMIMEHeader() (MIMEHeader, error)
 pkg net/textproto, method (*Conn) ReadResponse(int) (int, string, error)
 pkg net/textproto, method (*Conn) StartRequest(uint)
@@ -5036,19 +5036,19 @@ pkg net/textproto, method (*Pipeline) StartResponse(uint)
 pkg net/textproto, method (*Reader) DotReader() io.Reader
 pkg net/textproto, method (*Reader) ReadCodeLine(int) (int, string, error)
 pkg net/textproto, method (*Reader) ReadContinuedLine() (string, error)
-pkg net/textproto, method (*Reader) ReadContinuedLineBytes() ([]byte, error)
-pkg net/textproto, method (*Reader) ReadDotBytes() ([]byte, error)
+pkg net/textproto, method (*Reader) ReadContinuedLineBytes() ([]uint8, error)
+pkg net/textproto, method (*Reader) ReadDotBytes() ([]uint8, error)
 pkg net/textproto, method (*Reader) ReadDotLines() ([]string, error)
 pkg net/textproto, method (*Reader) ReadLine() (string, error)
-pkg net/textproto, method (*Reader) ReadLineBytes() ([]byte, error)
+pkg net/textproto, method (*Reader) ReadLineBytes() ([]uint8, error)
 pkg net/textproto, method (*Reader) ReadMIMEHeader() (MIMEHeader, error)
 pkg net/textproto, method (*Reader) ReadResponse(int) (int, string, error)
 pkg net/textproto, method (*Writer) DotWriter() io.WriteCloser
 pkg net/textproto, method (*Writer) PrintfLine(string, ...interface{}) error
-pkg net/textproto, method (MIMEHeader) Add(string)
+pkg net/textproto, method (MIMEHeader) Add(string, string)
 pkg net/textproto, method (MIMEHeader) Del(string)
 pkg net/textproto, method (MIMEHeader) Get(string) string
-pkg net/textproto, method (MIMEHeader) Set(string)
+pkg net/textproto, method (MIMEHeader) Set(string, string)
 pkg net/textproto, method (ProtocolError) Error() string
 pkg net/textproto, type Conn struct
 pkg net/textproto, type Conn struct, embedded Pipeline
@@ -5070,7 +5070,7 @@ pkg net/url, func ParseRequestURI(string) (*URL, error)
 pkg net/url, func QueryEscape(string) string
 pkg net/url, func QueryUnescape(string) (string, error)
 pkg net/url, func User(string) *Userinfo
-pkg net/url, func UserPassword(string) *Userinfo
+pkg net/url, func UserPassword(string, string) *Userinfo
 pkg net/url, method (*Error) Error() string
 pkg net/url, method (*URL) IsAbs() bool
 pkg net/url, method (*URL) Parse(string) (*URL, error)
@@ -5082,11 +5082,11 @@ pkg net/url, method (*Userinfo) Password() (string, bool)
 pkg net/url, method (*Userinfo) String() string
 pkg net/url, method (*Userinfo) Username() string
 pkg net/url, method (EscapeError) Error() string
-pkg net/url, method (Values) Add(string)
+pkg net/url, method (Values) Add(string, string)
 pkg net/url, method (Values) Del(string)
 pkg net/url, method (Values) Encode() string
 pkg net/url, method (Values) Get(string) string
-pkg net/url, method (Values) Set(string)
+pkg net/url, method (Values) Set(string, string)
 pkg net/url, type Error struct
 pkg net/url, type Error struct, Err error
 pkg net/url, type Error struct, Op string
@@ -5132,7 +5132,7 @@ pkg os, const SEEK_END int
 pkg os, const SEEK_SET int
 pkg os, func Chdir(string) error
 pkg os, func Chmod(string, FileMode) error
-pkg os, func Chown(string, int) error
+pkg os, func Chown(string, int, int) error
 pkg os, func Chtimes(string, time.Time, time.Time) error
 pkg os, func Clearenv()
 pkg os, func Create(string) (*File, error)
@@ -5156,8 +5156,8 @@ pkg os, func IsExist(error) bool
 pkg os, func IsNotExist(error) bool
 pkg os, func IsPathSeparator(uint8) bool
 pkg os, func IsPermission(error) bool
-pkg os, func Lchown(string, int) error
-pkg os, func Link(string) error
+pkg os, func Lchown(string, int, int) error
+pkg os, func Link(string, string) error
 pkg os, func Lstat(string) (FileInfo, error)
 pkg os, func Mkdir(string, FileMode) error
 pkg os, func MkdirAll(string, FileMode) error
@@ -5169,30 +5169,30 @@ pkg os, func Pipe() (*File, *File, error)
 pkg os, func Readlink(string) (string, error)
 pkg os, func Remove(string) error
 pkg os, func RemoveAll(string) error
-pkg os, func Rename(string) error
-pkg os, func SameFile(FileInfo) bool
-pkg os, func Setenv(string) error
+pkg os, func Rename(string, string) error
+pkg os, func SameFile(FileInfo, FileInfo) bool
+pkg os, func Setenv(string, string) error
 pkg os, func StartProcess(string, []string, *ProcAttr) (*Process, error)
 pkg os, func Stat(string) (FileInfo, error)
-pkg os, func Symlink(string) error
+pkg os, func Symlink(string, string) error
 pkg os, func TempDir() string
 pkg os, func Truncate(string, int64) error
 pkg os, method (*File) Chdir() error
 pkg os, method (*File) Chmod(FileMode) error
-pkg os, method (*File) Chown(int) error
+pkg os, method (*File) Chown(int, int) error
 pkg os, method (*File) Close() error
 pkg os, method (*File) Fd() uintptr
 pkg os, method (*File) Name() string
-pkg os, method (*File) Read([]byte) (int, error)
-pkg os, method (*File) ReadAt([]byte, int64) (int, error)
+pkg os, method (*File) Read([]uint8) (int, error)
+pkg os, method (*File) ReadAt([]uint8, int64) (int, error)
 pkg os, method (*File) Readdir(int) ([]FileInfo, error)
 pkg os, method (*File) Readdirnames(int) ([]string, error)
 pkg os, method (*File) Seek(int64, int) (int64, error)
 pkg os, method (*File) Stat() (FileInfo, error)
 pkg os, method (*File) Sync() error
 pkg os, method (*File) Truncate(int64) error
-pkg os, method (*File) Write([]byte) (int, error)
-pkg os, method (*File) WriteAt([]byte, int64) (int, error)
+pkg os, method (*File) Write([]uint8) (int, error)
+pkg os, method (*File) WriteAt([]uint8, int64) (int, error)
 pkg os, method (*File) WriteString(string) (int, error)
 pkg os, method (*LinkError) Error() string
 pkg os, method (*PathError) Error() string
@@ -5256,8 +5256,8 @@ pkg os, var Stdin *File
 pkg os, var Stdout *File
 pkg os/exec, func Command(string, ...string) *Cmd
 pkg os/exec, func LookPath(string) (string, error)
-pkg os/exec, method (*Cmd) CombinedOutput() ([]byte, error)
-pkg os/exec, method (*Cmd) Output() ([]byte, error)
+pkg os/exec, method (*Cmd) CombinedOutput() ([]uint8, error)
+pkg os/exec, method (*Cmd) Output() ([]uint8, error)
 pkg os/exec, method (*Cmd) Run() error
 pkg os/exec, method (*Cmd) Start() error
 pkg os/exec, method (*Cmd) StderrPipe() (io.ReadCloser, error)
@@ -5304,8 +5304,8 @@ pkg path, func Dir(string) string
 pkg path, func Ext(string) string
 pkg path, func IsAbs(string) bool
 pkg path, func Join(...string) string
-pkg path, func Match(string) (bool, error)
-pkg path, func Split(string) string
+pkg path, func Match(string, string) (bool, error)
+pkg path, func Split(string) (string, string)
 pkg path, var ErrBadPattern error
 pkg path/filepath, const ListSeparator ideal-char
 pkg path/filepath, const Separator ideal-char
@@ -5317,17 +5317,17 @@ pkg path/filepath, func EvalSymlinks(string) (string, error)
 pkg path/filepath, func Ext(string) string
 pkg path/filepath, func FromSlash(string) string
 pkg path/filepath, func Glob(string) ([]string, error)
-pkg path/filepath, func HasPrefix(string) bool
+pkg path/filepath, func HasPrefix(string, string) bool
 pkg path/filepath, func IsAbs(string) bool
 pkg path/filepath, func Join(...string) string
-pkg path/filepath, func Match(string) (bool, error)
-pkg path/filepath, func Rel(string) (string, error)
-pkg path/filepath, func Split(string) string
+pkg path/filepath, func Match(string, string) (bool, error)
+pkg path/filepath, func Rel(string, string) (string, error)
+pkg path/filepath, func Split(string) (string, string)
 pkg path/filepath, func SplitList(string) []string
 pkg path/filepath, func ToSlash(string) string
 pkg path/filepath, func VolumeName(string) string
 pkg path/filepath, func Walk(string, WalkFunc) error
-pkg path/filepath, type WalkFunc func(path string, info os.FileInfo, err error) error
+pkg path/filepath, type WalkFunc func(string, os.FileInfo, error) error
 pkg path/filepath, var ErrBadPattern error
 pkg path/filepath, var SkipDir error
 pkg reflect, const Array Kind
@@ -5361,13 +5361,13 @@ pkg reflect, const Uint8 Kind
 pkg reflect, const Uintptr Kind
 pkg reflect, const UnsafePointer Kind
 pkg reflect, func Append(Value, ...Value) Value
-pkg reflect, func AppendSlice(Value) Value
-pkg reflect, func Copy(Value) int
-pkg reflect, func DeepEqual(interface{}) bool
+pkg reflect, func AppendSlice(Value, Value) Value
+pkg reflect, func Copy(Value, Value) int
+pkg reflect, func DeepEqual(interface{}, interface{}) bool
 pkg reflect, func Indirect(Value) Value
 pkg reflect, func MakeChan(Type, int) Value
 pkg reflect, func MakeMap(Type) Value
-pkg reflect, func MakeSlice(Type, int) Value
+pkg reflect, func MakeSlice(Type, int, int) Value
 pkg reflect, func New(Type) Value
 pkg reflect, func NewAt(Type, unsafe.Pointer) Value
 pkg reflect, func PtrTo(Type) Type
@@ -5380,7 +5380,7 @@ pkg reflect, method (Kind) String() string
 pkg reflect, method (StructTag) Get(string) string
 pkg reflect, method (Value) Addr() Value
 pkg reflect, method (Value) Bool() bool
-pkg reflect, method (Value) Bytes() []byte
+pkg reflect, method (Value) Bytes() []uint8
 pkg reflect, method (Value) Call([]Value) []Value
 pkg reflect, method (Value) CallSlice([]Value) []Value
 pkg reflect, method (Value) CanAddr() bool
@@ -5418,16 +5418,16 @@ pkg reflect, method (Value) Recv() (Value, bool)
 pkg reflect, method (Value) Send(Value)
 pkg reflect, method (Value) Set(Value)
 pkg reflect, method (Value) SetBool(bool)
-pkg reflect, method (Value) SetBytes([]byte)
+pkg reflect, method (Value) SetBytes([]uint8)
 pkg reflect, method (Value) SetComplex(complex128)
 pkg reflect, method (Value) SetFloat(float64)
 pkg reflect, method (Value) SetInt(int64)
 pkg reflect, method (Value) SetLen(int)
-pkg reflect, method (Value) SetMapIndex(Value)
+pkg reflect, method (Value) SetMapIndex(Value, Value)
 pkg reflect, method (Value) SetPointer(unsafe.Pointer)
 pkg reflect, method (Value) SetString(string)
 pkg reflect, method (Value) SetUint(uint64)
-pkg reflect, method (Value) Slice(int) Value
+pkg reflect, method (Value) Slice(int, int) Value
 pkg reflect, method (Value) String() string
 pkg reflect, method (Value) TryRecv() (Value, bool)
 pkg reflect, method (Value) TrySend(Value) bool
@@ -5458,7 +5458,6 @@ pkg reflect, type StructField struct, PkgPath string
 pkg reflect, type StructField struct, Tag StructTag
 pkg reflect, type StructField struct, Type Type
 pkg reflect, type StructTag string
-pkg reflect, type Type interface { Align, AssignableTo, Bits, ChanDir, Elem, Field, FieldAlign, FieldByIndex, FieldByName, FieldByNameFunc, Implements, In, IsVariadic, Key, Kind, Len, Method, MethodByName, Name, NumField, NumIn, NumMethod, NumOut, Out, PkgPath, Size, String }
 pkg reflect, type Type interface, Align() int
 pkg reflect, type Type interface, AssignableTo(Type) bool
 pkg reflect, type Type interface, Bits() int
@@ -5486,48 +5485,49 @@ pkg reflect, type Type interface, Out(int) Type
 pkg reflect, type Type interface, PkgPath() string
 pkg reflect, type Type interface, Size() uintptr
 pkg reflect, type Type interface, String() string
+pkg reflect, type Type interface, unexported methods
 pkg reflect, type Value struct
 pkg reflect, type ValueError struct
 pkg reflect, type ValueError struct, Kind Kind
 pkg reflect, type ValueError struct, Method string
 pkg regexp, func Compile(string) (*Regexp, error)
 pkg regexp, func CompilePOSIX(string) (*Regexp, error)
-pkg regexp, func Match(string, []byte) (bool, error)
+pkg regexp, func Match(string, []uint8) (bool, error)
 pkg regexp, func MatchReader(string, io.RuneReader) (bool, error)
 pkg regexp, func MatchString(string, string) (bool, error)
 pkg regexp, func MustCompile(string) *Regexp
 pkg regexp, func MustCompilePOSIX(string) *Regexp
 pkg regexp, func QuoteMeta(string) string
-pkg regexp, method (*Regexp) Expand([]byte, []byte, []byte, []int) []byte
-pkg regexp, method (*Regexp) ExpandString([]byte, string, string, []int) []byte
-pkg regexp, method (*Regexp) Find([]byte) []byte
-pkg regexp, method (*Regexp) FindAll([]byte, int) [][]byte
-pkg regexp, method (*Regexp) FindAllIndex([]byte, int) [][]int
+pkg regexp, method (*Regexp) Expand([]uint8, []uint8, []uint8, []int) []uint8
+pkg regexp, method (*Regexp) ExpandString([]uint8, string, string, []int) []uint8
+pkg regexp, method (*Regexp) Find([]uint8) []uint8
+pkg regexp, method (*Regexp) FindAll([]uint8, int) [][]uint8
+pkg regexp, method (*Regexp) FindAllIndex([]uint8, int) [][]int
 pkg regexp, method (*Regexp) FindAllString(string, int) []string
 pkg regexp, method (*Regexp) FindAllStringIndex(string, int) [][]int
 pkg regexp, method (*Regexp) FindAllStringSubmatch(string, int) [][]string
 pkg regexp, method (*Regexp) FindAllStringSubmatchIndex(string, int) [][]int
-pkg regexp, method (*Regexp) FindAllSubmatch([]byte, int) [][][]byte
-pkg regexp, method (*Regexp) FindAllSubmatchIndex([]byte, int) [][]int
-pkg regexp, method (*Regexp) FindIndex([]byte) []int
+pkg regexp, method (*Regexp) FindAllSubmatch([]uint8, int) [][][]uint8
+pkg regexp, method (*Regexp) FindAllSubmatchIndex([]uint8, int) [][]int
+pkg regexp, method (*Regexp) FindIndex([]uint8) []int
 pkg regexp, method (*Regexp) FindReaderIndex(io.RuneReader) []int
 pkg regexp, method (*Regexp) FindReaderSubmatchIndex(io.RuneReader) []int
 pkg regexp, method (*Regexp) FindString(string) string
 pkg regexp, method (*Regexp) FindStringIndex(string) []int
 pkg regexp, method (*Regexp) FindStringSubmatch(string) []string
 pkg regexp, method (*Regexp) FindStringSubmatchIndex(string) []int
-pkg regexp, method (*Regexp) FindSubmatch([]byte) [][]byte
-pkg regexp, method (*Regexp) FindSubmatchIndex([]byte) []int
+pkg regexp, method (*Regexp) FindSubmatch([]uint8) [][]uint8
+pkg regexp, method (*Regexp) FindSubmatchIndex([]uint8) []int
 pkg regexp, method (*Regexp) LiteralPrefix() (string, bool)
-pkg regexp, method (*Regexp) Match([]byte) bool
+pkg regexp, method (*Regexp) Match([]uint8) bool
 pkg regexp, method (*Regexp) MatchReader(io.RuneReader) bool
 pkg regexp, method (*Regexp) MatchString(string) bool
 pkg regexp, method (*Regexp) NumSubexp() int
-pkg regexp, method (*Regexp) ReplaceAll([]byte) []byte
-pkg regexp, method (*Regexp) ReplaceAllFunc([]byte, func([]byte) []byte) []byte
-pkg regexp, method (*Regexp) ReplaceAllLiteral([]byte) []byte
-pkg regexp, method (*Regexp) ReplaceAllLiteralString(string) string
-pkg regexp, method (*Regexp) ReplaceAllString(string) string
+pkg regexp, method (*Regexp) ReplaceAll([]uint8, []uint8) []uint8
+pkg regexp, method (*Regexp) ReplaceAllFunc([]uint8, func([]uint8) []uint8) []uint8
+pkg regexp, method (*Regexp) ReplaceAllLiteral([]uint8, []uint8) []uint8
+pkg regexp, method (*Regexp) ReplaceAllLiteralString(string, string) string
+pkg regexp, method (*Regexp) ReplaceAllString(string, string) string
 pkg regexp, method (*Regexp) ReplaceAllStringFunc(string, func(string) string) string
 pkg regexp, method (*Regexp) String() string
 pkg regexp, method (*Regexp) SubexpNames() []string
@@ -5595,12 +5595,12 @@ pkg regexp/syntax, const Simple Flags
 pkg regexp/syntax, const UnicodeGroups Flags
 pkg regexp/syntax, const WasDollar Flags
 pkg regexp/syntax, func Compile(*Regexp) (*Prog, error)
-pkg regexp/syntax, func EmptyOpContext(rune) EmptyOp
-pkg regexp/syntax, func IsWordChar(rune) bool
+pkg regexp/syntax, func EmptyOpContext(int32, int32) EmptyOp
+pkg regexp/syntax, func IsWordChar(int32) bool
 pkg regexp/syntax, func Parse(string, Flags) (*Regexp, error)
 pkg regexp/syntax, method (*Error) Error() string
-pkg regexp/syntax, method (*Inst) MatchEmptyWidth(rune, rune) bool
-pkg regexp/syntax, method (*Inst) MatchRune(rune) bool
+pkg regexp/syntax, method (*Inst) MatchEmptyWidth(int32, int32) bool
+pkg regexp/syntax, method (*Inst) MatchRune(int32) bool
 pkg regexp/syntax, method (*Inst) String() string
 pkg regexp/syntax, method (*Prog) Prefix() (string, bool)
 pkg regexp/syntax, method (*Prog) StartCond() EmptyOp
@@ -5621,7 +5621,7 @@ pkg regexp/syntax, type Inst struct
 pkg regexp/syntax, type Inst struct, Arg uint32
 pkg regexp/syntax, type Inst struct, Op InstOp
 pkg regexp/syntax, type Inst struct, Out uint32
-pkg regexp/syntax, type Inst struct, Rune []rune
+pkg regexp/syntax, type Inst struct, Rune []int32
 pkg regexp/syntax, type InstOp uint8
 pkg regexp/syntax, type Op uint8
 pkg regexp/syntax, type Prog struct
@@ -5635,15 +5635,15 @@ pkg regexp/syntax, type Regexp struct, Max int
 pkg regexp/syntax, type Regexp struct, Min int
 pkg regexp/syntax, type Regexp struct, Name string
 pkg regexp/syntax, type Regexp struct, Op Op
-pkg regexp/syntax, type Regexp struct, Rune []rune
-pkg regexp/syntax, type Regexp struct, Rune0 [2]rune
+pkg regexp/syntax, type Regexp struct, Rune []int32
+pkg regexp/syntax, type Regexp struct, Rune0 [2]int32
 pkg regexp/syntax, type Regexp struct, Sub []*Regexp
 pkg regexp/syntax, type Regexp struct, Sub0 [1]*Regexp
 pkg runtime, const Compiler ideal-string
 pkg runtime, const GOARCH string
 pkg runtime, const GOOS string
 pkg runtime, func Breakpoint()
-pkg runtime, func CPUProfile() []byte
+pkg runtime, func CPUProfile() []uint8
 pkg runtime, func Caller(int) (uintptr, string, int, bool)
 pkg runtime, func Callers(int, []uintptr) int
 pkg runtime, func FuncForPC(uintptr) *Func
@@ -5660,8 +5660,8 @@ pkg runtime, func NumCgoCall() int64
 pkg runtime, func NumGoroutine() int
 pkg runtime, func ReadMemStats(*MemStats)
 pkg runtime, func SetCPUProfileRate(int)
-pkg runtime, func SetFinalizer(interface{})
-pkg runtime, func Stack([]byte, bool) int
+pkg runtime, func SetFinalizer(interface{}, interface{})
+pkg runtime, func Stack([]uint8, bool) int
 pkg runtime, func ThreadCreateProfile([]StackRecord) (int, bool)
 pkg runtime, func UnlockOSThread()
 pkg runtime, func Version() string
@@ -5716,7 +5716,7 @@ pkg runtime, type StackRecord struct, Stack0 [32]uintptr
 pkg runtime, type TypeAssertionError struct
 pkg runtime, var MemProfileRate int
 pkg runtime/debug, func PrintStack()
-pkg runtime/debug, func Stack() []byte
+pkg runtime/debug, func Stack() []uint8
 pkg runtime/pprof, func Lookup(string) *Profile
 pkg runtime/pprof, func NewProfile(string) *Profile
 pkg runtime/pprof, func Profiles() []*Profile
@@ -5742,54 +5742,54 @@ pkg sort, func Sort(Interface)
 pkg sort, func Strings([]string)
 pkg sort, func StringsAreSorted([]string) bool
 pkg sort, method (Float64Slice) Len() int
-pkg sort, method (Float64Slice) Less(int) bool
+pkg sort, method (Float64Slice) Less(int, int) bool
 pkg sort, method (Float64Slice) Search(float64) int
 pkg sort, method (Float64Slice) Sort()
-pkg sort, method (Float64Slice) Swap(int)
+pkg sort, method (Float64Slice) Swap(int, int)
 pkg sort, method (IntSlice) Len() int
-pkg sort, method (IntSlice) Less(int) bool
+pkg sort, method (IntSlice) Less(int, int) bool
 pkg sort, method (IntSlice) Search(int) int
 pkg sort, method (IntSlice) Sort()
-pkg sort, method (IntSlice) Swap(int)
+pkg sort, method (IntSlice) Swap(int, int)
 pkg sort, method (StringSlice) Len() int
-pkg sort, method (StringSlice) Less(int) bool
+pkg sort, method (StringSlice) Less(int, int) bool
 pkg sort, method (StringSlice) Search(string) int
 pkg sort, method (StringSlice) Sort()
-pkg sort, method (StringSlice) Swap(int)
+pkg sort, method (StringSlice) Swap(int, int)
 pkg sort, type Float64Slice []float64
 pkg sort, type IntSlice []int
 pkg sort, type Interface interface { Len, Less, Swap }
 pkg sort, type Interface interface, Len() int
-pkg sort, type Interface interface, Less(int) bool
-pkg sort, type Interface interface, Swap(int)
+pkg sort, type Interface interface, Less(int, int) bool
+pkg sort, type Interface interface, Swap(int, int)
 pkg sort, type StringSlice []string
 pkg strconv, const IntSize ideal-int
-pkg strconv, func AppendBool([]byte, bool) []byte
-pkg strconv, func AppendFloat([]byte, float64, byte, int, int) []byte
-pkg strconv, func AppendInt([]byte, int64, int) []byte
-pkg strconv, func AppendQuote([]byte, string) []byte
-pkg strconv, func AppendQuoteRune([]byte, rune) []byte
-pkg strconv, func AppendQuoteRuneToASCII([]byte, rune) []byte
-pkg strconv, func AppendQuoteToASCII([]byte, string) []byte
-pkg strconv, func AppendUint([]byte, uint64, int) []byte
+pkg strconv, func AppendBool([]uint8, bool) []uint8
+pkg strconv, func AppendFloat([]uint8, float64, uint8, int, int) []uint8
+pkg strconv, func AppendInt([]uint8, int64, int) []uint8
+pkg strconv, func AppendQuote([]uint8, string) []uint8
+pkg strconv, func AppendQuoteRune([]uint8, int32) []uint8
+pkg strconv, func AppendQuoteRuneToASCII([]uint8, int32) []uint8
+pkg strconv, func AppendQuoteToASCII([]uint8, string) []uint8
+pkg strconv, func AppendUint([]uint8, uint64, int) []uint8
 pkg strconv, func Atoi(string) (int, error)
 pkg strconv, func CanBackquote(string) bool
 pkg strconv, func FormatBool(bool) string
-pkg strconv, func FormatFloat(float64, byte, int) string
+pkg strconv, func FormatFloat(float64, uint8, int, int) string
 pkg strconv, func FormatInt(int64, int) string
 pkg strconv, func FormatUint(uint64, int) string
-pkg strconv, func IsPrint(rune) bool
+pkg strconv, func IsPrint(int32) bool
 pkg strconv, func Itoa(int) string
 pkg strconv, func ParseBool(string) (bool, error)
 pkg strconv, func ParseFloat(string, int) (float64, error)
 pkg strconv, func ParseInt(string, int, int) (int64, error)
 pkg strconv, func ParseUint(string, int, int) (uint64, error)
 pkg strconv, func Quote(string) string
-pkg strconv, func QuoteRune(rune) string
-pkg strconv, func QuoteRuneToASCII(rune) string
+pkg strconv, func QuoteRune(int32) string
+pkg strconv, func QuoteRuneToASCII(int32) string
 pkg strconv, func QuoteToASCII(string) string
 pkg strconv, func Unquote(string) (string, error)
-pkg strconv, func UnquoteChar(string, byte) (rune, bool, string, error)
+pkg strconv, func UnquoteChar(string, uint8) (int32, bool, string, error)
 pkg strconv, method (*NumError) Error() string
 pkg strconv, type NumError struct
 pkg strconv, type NumError struct, Err error
@@ -5797,32 +5797,32 @@ pkg strconv, type NumError struct, Func string
 pkg strconv, type NumError struct, Num string
 pkg strconv, var ErrRange error
 pkg strconv, var ErrSyntax error
-pkg strings, func Contains(string) bool
-pkg strings, func ContainsAny(string) bool
-pkg strings, func ContainsRune(string, rune) bool
-pkg strings, func Count(string) int
-pkg strings, func EqualFold(string) bool
+pkg strings, func Contains(string, string) bool
+pkg strings, func ContainsAny(string, string) bool
+pkg strings, func ContainsRune(string, int32) bool
+pkg strings, func Count(string, string) int
+pkg strings, func EqualFold(string, string) bool
 pkg strings, func Fields(string) []string
-pkg strings, func FieldsFunc(string, func(rune) bool) []string
-pkg strings, func HasPrefix(string) bool
-pkg strings, func HasSuffix(string) bool
-pkg strings, func Index(string) int
-pkg strings, func IndexAny(string) int
-pkg strings, func IndexFunc(string, func(rune) bool) int
-pkg strings, func IndexRune(string, rune) int
+pkg strings, func FieldsFunc(string, func(int32) bool) []string
+pkg strings, func HasPrefix(string, string) bool
+pkg strings, func HasSuffix(string, string) bool
+pkg strings, func Index(string, string) int
+pkg strings, func IndexAny(string, string) int
+pkg strings, func IndexFunc(string, func(int32) bool) int
+pkg strings, func IndexRune(string, int32) int
 pkg strings, func Join([]string, string) string
-pkg strings, func LastIndex(string) int
-pkg strings, func LastIndexAny(string) int
-pkg strings, func LastIndexFunc(string, func(rune) bool) int
-pkg strings, func Map(func(rune) rune, string) string
+pkg strings, func LastIndex(string, string) int
+pkg strings, func LastIndexAny(string, string) int
+pkg strings, func LastIndexFunc(string, func(int32) bool) int
+pkg strings, func Map(func(int32) int32, string) string
 pkg strings, func NewReader(string) *Reader
 pkg strings, func NewReplacer(...string) *Replacer
 pkg strings, func Repeat(string, int) string
-pkg strings, func Replace(string, int) string
-pkg strings, func Split(string) []string
-pkg strings, func SplitAfter(string) []string
-pkg strings, func SplitAfterN(string, int) []string
-pkg strings, func SplitN(string, int) []string
+pkg strings, func Replace(string, string, string, int) string
+pkg strings, func Split(string, string) []string
+pkg strings, func SplitAfter(string, string) []string
+pkg strings, func SplitAfterN(string, string, int) []string
+pkg strings, func SplitN(string, string, int) []string
 pkg strings, func Title(string) string
 pkg strings, func ToLower(string) string
 pkg strings, func ToLowerSpecial(unicode.SpecialCase, string) string
@@ -5831,17 +5831,17 @@ pkg strings, func ToTitleSpecial(unicode.SpecialCase, string) string
 pkg strings, func ToUpper(string) string
 pkg strings, func ToUpperSpecial(unicode.SpecialCase, string) string
 pkg strings, func Trim(string, string) string
-pkg strings, func TrimFunc(string, func(rune) bool) string
+pkg strings, func TrimFunc(string, func(int32) bool) string
 pkg strings, func TrimLeft(string, string) string
-pkg strings, func TrimLeftFunc(string, func(rune) bool) string
+pkg strings, func TrimLeftFunc(string, func(int32) bool) string
 pkg strings, func TrimRight(string, string) string
-pkg strings, func TrimRightFunc(string, func(rune) bool) string
+pkg strings, func TrimRightFunc(string, func(int32) bool) string
 pkg strings, func TrimSpace(string) string
 pkg strings, method (*Reader) Len() int
-pkg strings, method (*Reader) Read([]byte) (int, error)
-pkg strings, method (*Reader) ReadAt([]byte, int64) (int, error)
-pkg strings, method (*Reader) ReadByte() (byte, error)
-pkg strings, method (*Reader) ReadRune() (rune, int, error)
+pkg strings, method (*Reader) Read([]uint8) (int, error)
+pkg strings, method (*Reader) ReadAt([]uint8, int64) (int, error)
+pkg strings, method (*Reader) ReadByte() (uint8, error)
+pkg strings, method (*Reader) ReadRune() (int32, int, error)
 pkg strings, method (*Reader) Seek(int64, int) (int64, error)
 pkg strings, method (*Reader) UnreadByte() error
 pkg strings, method (*Reader) UnreadRune() error
@@ -5878,12 +5878,12 @@ pkg sync/atomic, func AddInt64(*int64, int64) int64
 pkg sync/atomic, func AddUint32(*uint32, uint32) uint32
 pkg sync/atomic, func AddUint64(*uint64, uint64) uint64
 pkg sync/atomic, func AddUintptr(*uintptr, uintptr) uintptr
-pkg sync/atomic, func CompareAndSwapInt32(*int32, int32) bool
-pkg sync/atomic, func CompareAndSwapInt64(*int64, int64) bool
-pkg sync/atomic, func CompareAndSwapPointer(*unsafe.Pointer, unsafe.Pointer) bool
-pkg sync/atomic, func CompareAndSwapUint32(*uint32, uint32) bool
-pkg sync/atomic, func CompareAndSwapUint64(*uint64, uint64) bool
-pkg sync/atomic, func CompareAndSwapUintptr(*uintptr, uintptr) bool
+pkg sync/atomic, func CompareAndSwapInt32(*int32, int32, int32) bool
+pkg sync/atomic, func CompareAndSwapInt64(*int64, int64, int64) bool
+pkg sync/atomic, func CompareAndSwapPointer(*unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) bool
+pkg sync/atomic, func CompareAndSwapUint32(*uint32, uint32, uint32) bool
+pkg sync/atomic, func CompareAndSwapUint64(*uint64, uint64, uint64) bool
+pkg sync/atomic, func CompareAndSwapUintptr(*uintptr, uintptr, uintptr) bool
 pkg sync/atomic, func LoadInt32(*int32) int32
 pkg sync/atomic, func LoadInt64(*int64) int64
 pkg sync/atomic, func LoadPointer(*unsafe.Pointer) unsafe.Pointer
@@ -7280,9 +7280,9 @@ pkg syscall (darwin-386), func BpfBuflen(int) (int, error)
 pkg syscall (darwin-386), func BpfDatalink(int) (int, error)
 pkg syscall (darwin-386), func BpfHeadercmpl(int) (int, error)
 pkg syscall (darwin-386), func BpfInterface(int, string) (string, error)
-pkg syscall (darwin-386), func BpfJump(int) *BpfInsn
+pkg syscall (darwin-386), func BpfJump(int, int, int, int) *BpfInsn
 pkg syscall (darwin-386), func BpfStats(int) (*BpfStat, error)
-pkg syscall (darwin-386), func BpfStmt(int) *BpfInsn
+pkg syscall (darwin-386), func BpfStmt(int, int) *BpfInsn
 pkg syscall (darwin-386), func BpfTimeout(int) (*Timeval, error)
 pkg syscall (darwin-386), func CheckBpfVersion(int) error
 pkg syscall (darwin-386), func Chflags(string, int) error
@@ -7308,7 +7308,7 @@ pkg syscall (darwin-386), func Fstatfs(int, *Statfs_t) error
 pkg syscall (darwin-386), func Fsync(int) error
 pkg syscall (darwin-386), func Ftruncate(int, int64) error
 pkg syscall (darwin-386), func Futimes(int, []Timeval) error
-pkg syscall (darwin-386), func Getdirentries(int, []byte, *uintptr) (int, error)
+pkg syscall (darwin-386), func Getdirentries(int, []uint8, *uintptr) (int, error)
 pkg syscall (darwin-386), func Getdtablesize() int
 pkg syscall (darwin-386), func Getfsstat([]Statfs_t, int) (int, error)
 pkg syscall (darwin-386), func Getpeername(int) (Sockaddr, error)
@@ -7319,58 +7319,56 @@ pkg syscall (darwin-386), func Getrlimit(int, *Rlimit) error
 pkg syscall (darwin-386), func Getrusage(int, *Rusage) error
 pkg syscall (darwin-386), func Getsid(int) (int, error)
 pkg syscall (darwin-386), func Getsockname(int) (Sockaddr, error)
-pkg syscall (darwin-386), func GetsockoptByte(int) (byte, error)
-pkg syscall (darwin-386), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (darwin-386), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (darwin-386), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (darwin-386), func GetsockoptInt(int) (int, error)
+pkg syscall (darwin-386), func GetsockoptByte(int, int, int) (uint8, error)
+pkg syscall (darwin-386), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (darwin-386), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (darwin-386), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (darwin-386), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (darwin-386), func Issetugid() bool
-pkg syscall (darwin-386), func Kevent(int, []Kevent_t, *Timespec) (int, error)
+pkg syscall (darwin-386), func Kevent(int, []Kevent_t, []Kevent_t, *Timespec) (int, error)
 pkg syscall (darwin-386), func Kill(int, Signal) error
 pkg syscall (darwin-386), func Kqueue() (int, error)
-pkg syscall (darwin-386), func Link(string, string) error
 pkg syscall (darwin-386), func Listen(int, int) error
 pkg syscall (darwin-386), func Lstat(string, *Stat_t) error
 pkg syscall (darwin-386), func Mkfifo(string, uint32) error
 pkg syscall (darwin-386), func Mknod(string, uint32, int) error
-pkg syscall (darwin-386), func Mmap(int, int64, int, int, int) ([]byte, error)
-pkg syscall (darwin-386), func Munmap([]byte) error
+pkg syscall (darwin-386), func Mmap(int, int64, int, int, int) ([]uint8, error)
+pkg syscall (darwin-386), func Munmap([]uint8) error
 pkg syscall (darwin-386), func NsecToTimespec(int64) Timespec
 pkg syscall (darwin-386), func Open(string, int, uint32) (int, error)
-pkg syscall (darwin-386), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (darwin-386), func ParseRoutingMessage([]byte) ([]RoutingMessage, error)
+pkg syscall (darwin-386), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (darwin-386), func ParseRoutingMessage([]uint8) ([]RoutingMessage, error)
 pkg syscall (darwin-386), func ParseRoutingSockaddr(RoutingMessage) ([]Sockaddr, error)
-pkg syscall (darwin-386), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (darwin-386), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (darwin-386), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (darwin-386), func Pathconf(string, int) (int, error)
 pkg syscall (darwin-386), func Pipe([]int) error
-pkg syscall (darwin-386), func Pread(int, []byte, int64) (int, error)
+pkg syscall (darwin-386), func Pread(int, []uint8, int64) (int, error)
 pkg syscall (darwin-386), func PtraceAttach(int) error
 pkg syscall (darwin-386), func PtraceDetach(int) error
-pkg syscall (darwin-386), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (darwin-386), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (darwin-386), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (darwin-386), func Read(int, []byte) (int, error)
-pkg syscall (darwin-386), func ReadDirent(int, []byte) (int, error)
-pkg syscall (darwin-386), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (darwin-386), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (darwin-386), func Rename(string, string) error
+pkg syscall (darwin-386), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (darwin-386), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-386), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-386), func Read(int, []uint8) (int, error)
+pkg syscall (darwin-386), func ReadDirent(int, []uint8) (int, error)
+pkg syscall (darwin-386), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (darwin-386), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (darwin-386), func Revoke(string) error
-pkg syscall (darwin-386), func RouteRIB(int) ([]byte, error)
+pkg syscall (darwin-386), func RouteRIB(int, int) ([]uint8, error)
 pkg syscall (darwin-386), func Seek(int, int64, int) (int64, error)
 pkg syscall (darwin-386), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) error
 pkg syscall (darwin-386), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (darwin-386), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (darwin-386), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (darwin-386), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (darwin-386), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (darwin-386), func SetBpf(int, []BpfInsn) error
-pkg syscall (darwin-386), func SetBpfBuflen(int) (int, error)
-pkg syscall (darwin-386), func SetBpfDatalink(int) (int, error)
-pkg syscall (darwin-386), func SetBpfHeadercmpl(int) error
-pkg syscall (darwin-386), func SetBpfImmediate(int) error
+pkg syscall (darwin-386), func SetBpfBuflen(int, int) (int, error)
+pkg syscall (darwin-386), func SetBpfDatalink(int, int) (int, error)
+pkg syscall (darwin-386), func SetBpfHeadercmpl(int, int) error
+pkg syscall (darwin-386), func SetBpfImmediate(int, int) error
 pkg syscall (darwin-386), func SetBpfInterface(int, string) error
-pkg syscall (darwin-386), func SetBpfPromisc(int) error
+pkg syscall (darwin-386), func SetBpfPromisc(int, int) error
 pkg syscall (darwin-386), func SetBpfTimeout(int, *Timeval) error
-pkg syscall (darwin-386), func SetKevent(*Kevent_t, int)
+pkg syscall (darwin-386), func SetKevent(*Kevent_t, int, int, int)
 pkg syscall (darwin-386), func SetNonblock(int, bool) error
 pkg syscall (darwin-386), func Setegid(int) error
 pkg syscall (darwin-386), func Seteuid(int) error
@@ -7384,25 +7382,26 @@ pkg syscall (darwin-386), func Setregid(int, int) error
 pkg syscall (darwin-386), func Setreuid(int, int) error
 pkg syscall (darwin-386), func Setrlimit(int, *Rlimit) error
 pkg syscall (darwin-386), func Setsid() (int, error)
-pkg syscall (darwin-386), func SetsockoptByte(int, byte) error
-pkg syscall (darwin-386), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (darwin-386), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (darwin-386), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (darwin-386), func SetsockoptInt(int, int) error
-pkg syscall (darwin-386), func SetsockoptLinger(int, *Linger) error
-pkg syscall (darwin-386), func SetsockoptString(int, string) error
-pkg syscall (darwin-386), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (darwin-386), func SetsockoptByte(int, int, int, uint8) error
+pkg syscall (darwin-386), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (darwin-386), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (darwin-386), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (darwin-386), func SetsockoptInt(int, int, int, int) error
+pkg syscall (darwin-386), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (darwin-386), func SetsockoptString(int, int, int, string) error
+pkg syscall (darwin-386), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (darwin-386), func Settimeofday(*Timeval) error
 pkg syscall (darwin-386), func Setuid(int) error
 pkg syscall (darwin-386), func Shutdown(int, int) error
-pkg syscall (darwin-386), func Socket(int) (int, error)
-pkg syscall (darwin-386), func Socketpair(int) ([2]int, error)
+pkg syscall (darwin-386), func Socket(int, int, int) (int, error)
+pkg syscall (darwin-386), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (darwin-386), func Stat(string, *Stat_t) error
 pkg syscall (darwin-386), func Statfs(string, *Statfs_t) error
-pkg syscall (darwin-386), func StringSlicePtr([]string) []*byte
-pkg syscall (darwin-386), func Symlink(string, string) error
+pkg syscall (darwin-386), func StringSlicePtr([]string) []*uint8
 pkg syscall (darwin-386), func Sync() error
-pkg syscall (darwin-386), func Syscall9(uintptr) (uintptr, Errno)
+pkg syscall (darwin-386), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-386), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-386), func Syscall9(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (darwin-386), func Sysctl(string) (string, error)
 pkg syscall (darwin-386), func SysctlUint32(string) (uint32, error)
 pkg syscall (darwin-386), func TimespecToNsec(Timespec) int64
@@ -7410,10 +7409,10 @@ pkg syscall (darwin-386), func TimevalToNsec(Timeval) int64
 pkg syscall (darwin-386), func Truncate(string, int64) error
 pkg syscall (darwin-386), func Umask(int) int
 pkg syscall (darwin-386), func Undelete(string) error
-pkg syscall (darwin-386), func UnixRights(...int) []byte
+pkg syscall (darwin-386), func UnixRights(...int) []uint8
 pkg syscall (darwin-386), func Unmount(string, int) error
 pkg syscall (darwin-386), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (darwin-386), func Write(int, []byte) (int, error)
+pkg syscall (darwin-386), func Write(int, []uint8) (int, error)
 pkg syscall (darwin-386), method (*Cmsghdr) SetLen(int)
 pkg syscall (darwin-386), method (*Iovec) SetLen(int)
 pkg syscall (darwin-386), method (*Msghdr) SetControllen(int)
@@ -7421,7 +7420,7 @@ pkg syscall (darwin-386), type BpfHdr struct
 pkg syscall (darwin-386), type BpfHdr struct, Caplen uint32
 pkg syscall (darwin-386), type BpfHdr struct, Datalen uint32
 pkg syscall (darwin-386), type BpfHdr struct, Hdrlen uint16
-pkg syscall (darwin-386), type BpfHdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386), type BpfHdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386), type BpfHdr struct, Tstamp Timeval
 pkg syscall (darwin-386), type BpfInsn struct
 pkg syscall (darwin-386), type BpfInsn struct, Code uint16
@@ -7449,12 +7448,12 @@ pkg syscall (darwin-386), type Dirent struct
 pkg syscall (darwin-386), type Dirent struct, Ino uint64
 pkg syscall (darwin-386), type Dirent struct, Name [1024]int8
 pkg syscall (darwin-386), type Dirent struct, Namlen uint16
-pkg syscall (darwin-386), type Dirent struct, Pad_cgo_0 [3]byte
+pkg syscall (darwin-386), type Dirent struct, Pad_cgo_0 [3]uint8
 pkg syscall (darwin-386), type Dirent struct, Reclen uint16
 pkg syscall (darwin-386), type Dirent struct, Seekoff uint64
 pkg syscall (darwin-386), type Dirent struct, Type uint8
 pkg syscall (darwin-386), type Fbootstraptransfer_t struct
-pkg syscall (darwin-386), type Fbootstraptransfer_t struct, Buffer *byte
+pkg syscall (darwin-386), type Fbootstraptransfer_t struct, Buffer *uint8
 pkg syscall (darwin-386), type Fbootstraptransfer_t struct, Length uint32
 pkg syscall (darwin-386), type Fbootstraptransfer_t struct, Offset int64
 pkg syscall (darwin-386), type FdSet struct
@@ -7509,7 +7508,7 @@ pkg syscall (darwin-386), type IfMsghdr struct, Data IfData
 pkg syscall (darwin-386), type IfMsghdr struct, Flags int32
 pkg syscall (darwin-386), type IfMsghdr struct, Index uint16
 pkg syscall (darwin-386), type IfMsghdr struct, Msglen uint16
-pkg syscall (darwin-386), type IfMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386), type IfMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386), type IfMsghdr struct, Type uint8
 pkg syscall (darwin-386), type IfMsghdr struct, Version uint8
 pkg syscall (darwin-386), type IfaMsghdr struct
@@ -7518,7 +7517,7 @@ pkg syscall (darwin-386), type IfaMsghdr struct, Flags int32
 pkg syscall (darwin-386), type IfaMsghdr struct, Index uint16
 pkg syscall (darwin-386), type IfaMsghdr struct, Metric int32
 pkg syscall (darwin-386), type IfaMsghdr struct, Msglen uint16
-pkg syscall (darwin-386), type IfaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386), type IfaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386), type IfaMsghdr struct, Type uint8
 pkg syscall (darwin-386), type IfaMsghdr struct, Version uint8
 pkg syscall (darwin-386), type IfmaMsghdr struct
@@ -7526,7 +7525,7 @@ pkg syscall (darwin-386), type IfmaMsghdr struct, Addrs int32
 pkg syscall (darwin-386), type IfmaMsghdr struct, Flags int32
 pkg syscall (darwin-386), type IfmaMsghdr struct, Index uint16
 pkg syscall (darwin-386), type IfmaMsghdr struct, Msglen uint16
-pkg syscall (darwin-386), type IfmaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386), type IfmaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386), type IfmaMsghdr struct, Type uint8
 pkg syscall (darwin-386), type IfmaMsghdr struct, Version uint8
 pkg syscall (darwin-386), type IfmaMsghdr2 struct
@@ -7534,24 +7533,24 @@ pkg syscall (darwin-386), type IfmaMsghdr2 struct, Addrs int32
 pkg syscall (darwin-386), type IfmaMsghdr2 struct, Flags int32
 pkg syscall (darwin-386), type IfmaMsghdr2 struct, Index uint16
 pkg syscall (darwin-386), type IfmaMsghdr2 struct, Msglen uint16
-pkg syscall (darwin-386), type IfmaMsghdr2 struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386), type IfmaMsghdr2 struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386), type IfmaMsghdr2 struct, Refcount int32
 pkg syscall (darwin-386), type IfmaMsghdr2 struct, Type uint8
 pkg syscall (darwin-386), type IfmaMsghdr2 struct, Version uint8
 pkg syscall (darwin-386), type Inet6Pktinfo struct
-pkg syscall (darwin-386), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (darwin-386), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (darwin-386), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (darwin-386), type InterfaceAddrMessage struct
-pkg syscall (darwin-386), type InterfaceAddrMessage struct, Data []byte
+pkg syscall (darwin-386), type InterfaceAddrMessage struct, Data []uint8
 pkg syscall (darwin-386), type InterfaceAddrMessage struct, Header IfaMsghdr
 pkg syscall (darwin-386), type InterfaceMessage struct
-pkg syscall (darwin-386), type InterfaceMessage struct, Data []byte
+pkg syscall (darwin-386), type InterfaceMessage struct, Data []uint8
 pkg syscall (darwin-386), type InterfaceMessage struct, Header IfMsghdr
 pkg syscall (darwin-386), type InterfaceMulticastAddrMessage struct
-pkg syscall (darwin-386), type InterfaceMulticastAddrMessage struct, Data []byte
+pkg syscall (darwin-386), type InterfaceMulticastAddrMessage struct, Data []uint8
 pkg syscall (darwin-386), type InterfaceMulticastAddrMessage struct, Header IfmaMsghdr2
 pkg syscall (darwin-386), type Iovec struct
-pkg syscall (darwin-386), type Iovec struct, Base *byte
+pkg syscall (darwin-386), type Iovec struct, Base *uint8
 pkg syscall (darwin-386), type Iovec struct, Len uint32
 pkg syscall (darwin-386), type Kevent_t struct
 pkg syscall (darwin-386), type Kevent_t struct, Data int32
@@ -7559,18 +7558,18 @@ pkg syscall (darwin-386), type Kevent_t struct, Fflags uint32
 pkg syscall (darwin-386), type Kevent_t struct, Filter int16
 pkg syscall (darwin-386), type Kevent_t struct, Flags uint16
 pkg syscall (darwin-386), type Kevent_t struct, Ident uint32
-pkg syscall (darwin-386), type Kevent_t struct, Udata *byte
+pkg syscall (darwin-386), type Kevent_t struct, Udata *uint8
 pkg syscall (darwin-386), type Log2phys_t struct
 pkg syscall (darwin-386), type Log2phys_t struct, Contigbytes int64
 pkg syscall (darwin-386), type Log2phys_t struct, Devoffset int64
 pkg syscall (darwin-386), type Log2phys_t struct, Flags uint32
 pkg syscall (darwin-386), type Msghdr struct
-pkg syscall (darwin-386), type Msghdr struct, Control *byte
+pkg syscall (darwin-386), type Msghdr struct, Control *uint8
 pkg syscall (darwin-386), type Msghdr struct, Controllen uint32
 pkg syscall (darwin-386), type Msghdr struct, Flags int32
 pkg syscall (darwin-386), type Msghdr struct, Iov *Iovec
 pkg syscall (darwin-386), type Msghdr struct, Iovlen int32
-pkg syscall (darwin-386), type Msghdr struct, Name *byte
+pkg syscall (darwin-386), type Msghdr struct, Name *uint8
 pkg syscall (darwin-386), type Msghdr struct, Namelen uint32
 pkg syscall (darwin-386), type Radvisory_t struct
 pkg syscall (darwin-386), type Radvisory_t struct, Count int32
@@ -7592,7 +7591,7 @@ pkg syscall (darwin-386), type RawSockaddrInet4 struct, Family uint8
 pkg syscall (darwin-386), type RawSockaddrInet4 struct, Len uint8
 pkg syscall (darwin-386), type RawSockaddrInet4 struct, Zero [8]int8
 pkg syscall (darwin-386), type RawSockaddrInet6 struct
-pkg syscall (darwin-386), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (darwin-386), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (darwin-386), type RawSockaddrInet6 struct, Family uint8
 pkg syscall (darwin-386), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (darwin-386), type RawSockaddrInet6 struct, Len uint8
@@ -7606,9 +7605,9 @@ pkg syscall (darwin-386), type Rlimit struct
 pkg syscall (darwin-386), type Rlimit struct, Cur uint64
 pkg syscall (darwin-386), type Rlimit struct, Max uint64
 pkg syscall (darwin-386), type RouteMessage struct
-pkg syscall (darwin-386), type RouteMessage struct, Data []byte
+pkg syscall (darwin-386), type RouteMessage struct, Data []uint8
 pkg syscall (darwin-386), type RouteMessage struct, Header RtMsghdr
-pkg syscall (darwin-386), type RoutingMessage interface {}
+pkg syscall (darwin-386), type RoutingMessage interface, unexported methods
 pkg syscall (darwin-386), type RtMetrics struct
 pkg syscall (darwin-386), type RtMetrics struct, Expire int32
 pkg syscall (darwin-386), type RtMetrics struct, Filler [4]uint32
@@ -7628,7 +7627,7 @@ pkg syscall (darwin-386), type RtMsghdr struct, Flags int32
 pkg syscall (darwin-386), type RtMsghdr struct, Index uint16
 pkg syscall (darwin-386), type RtMsghdr struct, Inits uint32
 pkg syscall (darwin-386), type RtMsghdr struct, Msglen uint16
-pkg syscall (darwin-386), type RtMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386), type RtMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386), type RtMsghdr struct, Pid int32
 pkg syscall (darwin-386), type RtMsghdr struct, Rmx RtMetrics
 pkg syscall (darwin-386), type RtMsghdr struct, Seq int32
@@ -7661,7 +7660,7 @@ pkg syscall (darwin-386), type SockaddrDatalink struct, Nlen uint8
 pkg syscall (darwin-386), type SockaddrDatalink struct, Slen uint8
 pkg syscall (darwin-386), type SockaddrDatalink struct, Type uint8
 pkg syscall (darwin-386), type SocketControlMessage struct
-pkg syscall (darwin-386), type SocketControlMessage struct, Data []byte
+pkg syscall (darwin-386), type SocketControlMessage struct, Data []uint8
 pkg syscall (darwin-386), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (darwin-386), type Stat_t struct
 pkg syscall (darwin-386), type Stat_t struct, Atimespec Timespec
@@ -7710,7 +7709,7 @@ pkg syscall (darwin-386), type Timespec struct, Nsec int32
 pkg syscall (darwin-386), type Timespec struct, Sec int32
 pkg syscall (darwin-386), type Timeval struct, Sec int32
 pkg syscall (darwin-386), type Timeval struct, Usec int32
-pkg syscall (darwin-386), type Timeval32 [0]byte
+pkg syscall (darwin-386), type Timeval32 [0]uint8
 pkg syscall (darwin-386), type WaitStatus uint32
 pkg syscall (darwin-386), var Stderr int
 pkg syscall (darwin-386), var Stdin int
@@ -9099,9 +9098,9 @@ pkg syscall (darwin-386-cgo), func BpfBuflen(int) (int, error)
 pkg syscall (darwin-386-cgo), func BpfDatalink(int) (int, error)
 pkg syscall (darwin-386-cgo), func BpfHeadercmpl(int) (int, error)
 pkg syscall (darwin-386-cgo), func BpfInterface(int, string) (string, error)
-pkg syscall (darwin-386-cgo), func BpfJump(int) *BpfInsn
+pkg syscall (darwin-386-cgo), func BpfJump(int, int, int, int) *BpfInsn
 pkg syscall (darwin-386-cgo), func BpfStats(int) (*BpfStat, error)
-pkg syscall (darwin-386-cgo), func BpfStmt(int) *BpfInsn
+pkg syscall (darwin-386-cgo), func BpfStmt(int, int) *BpfInsn
 pkg syscall (darwin-386-cgo), func BpfTimeout(int) (*Timeval, error)
 pkg syscall (darwin-386-cgo), func CheckBpfVersion(int) error
 pkg syscall (darwin-386-cgo), func Chflags(string, int) error
@@ -9127,7 +9126,7 @@ pkg syscall (darwin-386-cgo), func Fstatfs(int, *Statfs_t) error
 pkg syscall (darwin-386-cgo), func Fsync(int) error
 pkg syscall (darwin-386-cgo), func Ftruncate(int, int64) error
 pkg syscall (darwin-386-cgo), func Futimes(int, []Timeval) error
-pkg syscall (darwin-386-cgo), func Getdirentries(int, []byte, *uintptr) (int, error)
+pkg syscall (darwin-386-cgo), func Getdirentries(int, []uint8, *uintptr) (int, error)
 pkg syscall (darwin-386-cgo), func Getdtablesize() int
 pkg syscall (darwin-386-cgo), func Getfsstat([]Statfs_t, int) (int, error)
 pkg syscall (darwin-386-cgo), func Getpeername(int) (Sockaddr, error)
@@ -9138,58 +9137,56 @@ pkg syscall (darwin-386-cgo), func Getrlimit(int, *Rlimit) error
 pkg syscall (darwin-386-cgo), func Getrusage(int, *Rusage) error
 pkg syscall (darwin-386-cgo), func Getsid(int) (int, error)
 pkg syscall (darwin-386-cgo), func Getsockname(int) (Sockaddr, error)
-pkg syscall (darwin-386-cgo), func GetsockoptByte(int) (byte, error)
-pkg syscall (darwin-386-cgo), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (darwin-386-cgo), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (darwin-386-cgo), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (darwin-386-cgo), func GetsockoptInt(int) (int, error)
+pkg syscall (darwin-386-cgo), func GetsockoptByte(int, int, int) (uint8, error)
+pkg syscall (darwin-386-cgo), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (darwin-386-cgo), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (darwin-386-cgo), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (darwin-386-cgo), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (darwin-386-cgo), func Issetugid() bool
-pkg syscall (darwin-386-cgo), func Kevent(int, []Kevent_t, *Timespec) (int, error)
+pkg syscall (darwin-386-cgo), func Kevent(int, []Kevent_t, []Kevent_t, *Timespec) (int, error)
 pkg syscall (darwin-386-cgo), func Kill(int, Signal) error
 pkg syscall (darwin-386-cgo), func Kqueue() (int, error)
-pkg syscall (darwin-386-cgo), func Link(string, string) error
 pkg syscall (darwin-386-cgo), func Listen(int, int) error
 pkg syscall (darwin-386-cgo), func Lstat(string, *Stat_t) error
 pkg syscall (darwin-386-cgo), func Mkfifo(string, uint32) error
 pkg syscall (darwin-386-cgo), func Mknod(string, uint32, int) error
-pkg syscall (darwin-386-cgo), func Mmap(int, int64, int, int, int) ([]byte, error)
-pkg syscall (darwin-386-cgo), func Munmap([]byte) error
+pkg syscall (darwin-386-cgo), func Mmap(int, int64, int, int, int) ([]uint8, error)
+pkg syscall (darwin-386-cgo), func Munmap([]uint8) error
 pkg syscall (darwin-386-cgo), func NsecToTimespec(int64) Timespec
 pkg syscall (darwin-386-cgo), func Open(string, int, uint32) (int, error)
-pkg syscall (darwin-386-cgo), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (darwin-386-cgo), func ParseRoutingMessage([]byte) ([]RoutingMessage, error)
+pkg syscall (darwin-386-cgo), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (darwin-386-cgo), func ParseRoutingMessage([]uint8) ([]RoutingMessage, error)
 pkg syscall (darwin-386-cgo), func ParseRoutingSockaddr(RoutingMessage) ([]Sockaddr, error)
-pkg syscall (darwin-386-cgo), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (darwin-386-cgo), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (darwin-386-cgo), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (darwin-386-cgo), func Pathconf(string, int) (int, error)
 pkg syscall (darwin-386-cgo), func Pipe([]int) error
-pkg syscall (darwin-386-cgo), func Pread(int, []byte, int64) (int, error)
+pkg syscall (darwin-386-cgo), func Pread(int, []uint8, int64) (int, error)
 pkg syscall (darwin-386-cgo), func PtraceAttach(int) error
 pkg syscall (darwin-386-cgo), func PtraceDetach(int) error
-pkg syscall (darwin-386-cgo), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (darwin-386-cgo), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (darwin-386-cgo), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (darwin-386-cgo), func Read(int, []byte) (int, error)
-pkg syscall (darwin-386-cgo), func ReadDirent(int, []byte) (int, error)
-pkg syscall (darwin-386-cgo), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (darwin-386-cgo), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (darwin-386-cgo), func Rename(string, string) error
+pkg syscall (darwin-386-cgo), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (darwin-386-cgo), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-386-cgo), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-386-cgo), func Read(int, []uint8) (int, error)
+pkg syscall (darwin-386-cgo), func ReadDirent(int, []uint8) (int, error)
+pkg syscall (darwin-386-cgo), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (darwin-386-cgo), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (darwin-386-cgo), func Revoke(string) error
-pkg syscall (darwin-386-cgo), func RouteRIB(int) ([]byte, error)
+pkg syscall (darwin-386-cgo), func RouteRIB(int, int) ([]uint8, error)
 pkg syscall (darwin-386-cgo), func Seek(int, int64, int) (int64, error)
 pkg syscall (darwin-386-cgo), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) error
 pkg syscall (darwin-386-cgo), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (darwin-386-cgo), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (darwin-386-cgo), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (darwin-386-cgo), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (darwin-386-cgo), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (darwin-386-cgo), func SetBpf(int, []BpfInsn) error
-pkg syscall (darwin-386-cgo), func SetBpfBuflen(int) (int, error)
-pkg syscall (darwin-386-cgo), func SetBpfDatalink(int) (int, error)
-pkg syscall (darwin-386-cgo), func SetBpfHeadercmpl(int) error
-pkg syscall (darwin-386-cgo), func SetBpfImmediate(int) error
+pkg syscall (darwin-386-cgo), func SetBpfBuflen(int, int) (int, error)
+pkg syscall (darwin-386-cgo), func SetBpfDatalink(int, int) (int, error)
+pkg syscall (darwin-386-cgo), func SetBpfHeadercmpl(int, int) error
+pkg syscall (darwin-386-cgo), func SetBpfImmediate(int, int) error
 pkg syscall (darwin-386-cgo), func SetBpfInterface(int, string) error
-pkg syscall (darwin-386-cgo), func SetBpfPromisc(int) error
+pkg syscall (darwin-386-cgo), func SetBpfPromisc(int, int) error
 pkg syscall (darwin-386-cgo), func SetBpfTimeout(int, *Timeval) error
-pkg syscall (darwin-386-cgo), func SetKevent(*Kevent_t, int)
+pkg syscall (darwin-386-cgo), func SetKevent(*Kevent_t, int, int, int)
 pkg syscall (darwin-386-cgo), func SetNonblock(int, bool) error
 pkg syscall (darwin-386-cgo), func Setegid(int) error
 pkg syscall (darwin-386-cgo), func Seteuid(int) error
@@ -9203,25 +9200,26 @@ pkg syscall (darwin-386-cgo), func Setregid(int, int) error
 pkg syscall (darwin-386-cgo), func Setreuid(int, int) error
 pkg syscall (darwin-386-cgo), func Setrlimit(int, *Rlimit) error
 pkg syscall (darwin-386-cgo), func Setsid() (int, error)
-pkg syscall (darwin-386-cgo), func SetsockoptByte(int, byte) error
-pkg syscall (darwin-386-cgo), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (darwin-386-cgo), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (darwin-386-cgo), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (darwin-386-cgo), func SetsockoptInt(int, int) error
-pkg syscall (darwin-386-cgo), func SetsockoptLinger(int, *Linger) error
-pkg syscall (darwin-386-cgo), func SetsockoptString(int, string) error
-pkg syscall (darwin-386-cgo), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (darwin-386-cgo), func SetsockoptByte(int, int, int, uint8) error
+pkg syscall (darwin-386-cgo), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (darwin-386-cgo), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (darwin-386-cgo), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (darwin-386-cgo), func SetsockoptInt(int, int, int, int) error
+pkg syscall (darwin-386-cgo), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (darwin-386-cgo), func SetsockoptString(int, int, int, string) error
+pkg syscall (darwin-386-cgo), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (darwin-386-cgo), func Settimeofday(*Timeval) error
 pkg syscall (darwin-386-cgo), func Setuid(int) error
 pkg syscall (darwin-386-cgo), func Shutdown(int, int) error
-pkg syscall (darwin-386-cgo), func Socket(int) (int, error)
-pkg syscall (darwin-386-cgo), func Socketpair(int) ([2]int, error)
+pkg syscall (darwin-386-cgo), func Socket(int, int, int) (int, error)
+pkg syscall (darwin-386-cgo), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (darwin-386-cgo), func Stat(string, *Stat_t) error
 pkg syscall (darwin-386-cgo), func Statfs(string, *Statfs_t) error
-pkg syscall (darwin-386-cgo), func StringSlicePtr([]string) []*byte
-pkg syscall (darwin-386-cgo), func Symlink(string, string) error
+pkg syscall (darwin-386-cgo), func StringSlicePtr([]string) []*uint8
 pkg syscall (darwin-386-cgo), func Sync() error
-pkg syscall (darwin-386-cgo), func Syscall9(uintptr) (uintptr, Errno)
+pkg syscall (darwin-386-cgo), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-386-cgo), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-386-cgo), func Syscall9(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (darwin-386-cgo), func Sysctl(string) (string, error)
 pkg syscall (darwin-386-cgo), func SysctlUint32(string) (uint32, error)
 pkg syscall (darwin-386-cgo), func TimespecToNsec(Timespec) int64
@@ -9229,10 +9227,10 @@ pkg syscall (darwin-386-cgo), func TimevalToNsec(Timeval) int64
 pkg syscall (darwin-386-cgo), func Truncate(string, int64) error
 pkg syscall (darwin-386-cgo), func Umask(int) int
 pkg syscall (darwin-386-cgo), func Undelete(string) error
-pkg syscall (darwin-386-cgo), func UnixRights(...int) []byte
+pkg syscall (darwin-386-cgo), func UnixRights(...int) []uint8
 pkg syscall (darwin-386-cgo), func Unmount(string, int) error
 pkg syscall (darwin-386-cgo), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (darwin-386-cgo), func Write(int, []byte) (int, error)
+pkg syscall (darwin-386-cgo), func Write(int, []uint8) (int, error)
 pkg syscall (darwin-386-cgo), method (*Cmsghdr) SetLen(int)
 pkg syscall (darwin-386-cgo), method (*Iovec) SetLen(int)
 pkg syscall (darwin-386-cgo), method (*Msghdr) SetControllen(int)
@@ -9240,7 +9238,7 @@ pkg syscall (darwin-386-cgo), type BpfHdr struct
 pkg syscall (darwin-386-cgo), type BpfHdr struct, Caplen uint32
 pkg syscall (darwin-386-cgo), type BpfHdr struct, Datalen uint32
 pkg syscall (darwin-386-cgo), type BpfHdr struct, Hdrlen uint16
-pkg syscall (darwin-386-cgo), type BpfHdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386-cgo), type BpfHdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386-cgo), type BpfHdr struct, Tstamp Timeval
 pkg syscall (darwin-386-cgo), type BpfInsn struct
 pkg syscall (darwin-386-cgo), type BpfInsn struct, Code uint16
@@ -9268,12 +9266,12 @@ pkg syscall (darwin-386-cgo), type Dirent struct
 pkg syscall (darwin-386-cgo), type Dirent struct, Ino uint64
 pkg syscall (darwin-386-cgo), type Dirent struct, Name [1024]int8
 pkg syscall (darwin-386-cgo), type Dirent struct, Namlen uint16
-pkg syscall (darwin-386-cgo), type Dirent struct, Pad_cgo_0 [3]byte
+pkg syscall (darwin-386-cgo), type Dirent struct, Pad_cgo_0 [3]uint8
 pkg syscall (darwin-386-cgo), type Dirent struct, Reclen uint16
 pkg syscall (darwin-386-cgo), type Dirent struct, Seekoff uint64
 pkg syscall (darwin-386-cgo), type Dirent struct, Type uint8
 pkg syscall (darwin-386-cgo), type Fbootstraptransfer_t struct
-pkg syscall (darwin-386-cgo), type Fbootstraptransfer_t struct, Buffer *byte
+pkg syscall (darwin-386-cgo), type Fbootstraptransfer_t struct, Buffer *uint8
 pkg syscall (darwin-386-cgo), type Fbootstraptransfer_t struct, Length uint32
 pkg syscall (darwin-386-cgo), type Fbootstraptransfer_t struct, Offset int64
 pkg syscall (darwin-386-cgo), type FdSet struct
@@ -9328,7 +9326,7 @@ pkg syscall (darwin-386-cgo), type IfMsghdr struct, Data IfData
 pkg syscall (darwin-386-cgo), type IfMsghdr struct, Flags int32
 pkg syscall (darwin-386-cgo), type IfMsghdr struct, Index uint16
 pkg syscall (darwin-386-cgo), type IfMsghdr struct, Msglen uint16
-pkg syscall (darwin-386-cgo), type IfMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386-cgo), type IfMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386-cgo), type IfMsghdr struct, Type uint8
 pkg syscall (darwin-386-cgo), type IfMsghdr struct, Version uint8
 pkg syscall (darwin-386-cgo), type IfaMsghdr struct
@@ -9337,7 +9335,7 @@ pkg syscall (darwin-386-cgo), type IfaMsghdr struct, Flags int32
 pkg syscall (darwin-386-cgo), type IfaMsghdr struct, Index uint16
 pkg syscall (darwin-386-cgo), type IfaMsghdr struct, Metric int32
 pkg syscall (darwin-386-cgo), type IfaMsghdr struct, Msglen uint16
-pkg syscall (darwin-386-cgo), type IfaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386-cgo), type IfaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386-cgo), type IfaMsghdr struct, Type uint8
 pkg syscall (darwin-386-cgo), type IfaMsghdr struct, Version uint8
 pkg syscall (darwin-386-cgo), type IfmaMsghdr struct
@@ -9345,7 +9343,7 @@ pkg syscall (darwin-386-cgo), type IfmaMsghdr struct, Addrs int32
 pkg syscall (darwin-386-cgo), type IfmaMsghdr struct, Flags int32
 pkg syscall (darwin-386-cgo), type IfmaMsghdr struct, Index uint16
 pkg syscall (darwin-386-cgo), type IfmaMsghdr struct, Msglen uint16
-pkg syscall (darwin-386-cgo), type IfmaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386-cgo), type IfmaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386-cgo), type IfmaMsghdr struct, Type uint8
 pkg syscall (darwin-386-cgo), type IfmaMsghdr struct, Version uint8
 pkg syscall (darwin-386-cgo), type IfmaMsghdr2 struct
@@ -9353,24 +9351,24 @@ pkg syscall (darwin-386-cgo), type IfmaMsghdr2 struct, Addrs int32
 pkg syscall (darwin-386-cgo), type IfmaMsghdr2 struct, Flags int32
 pkg syscall (darwin-386-cgo), type IfmaMsghdr2 struct, Index uint16
 pkg syscall (darwin-386-cgo), type IfmaMsghdr2 struct, Msglen uint16
-pkg syscall (darwin-386-cgo), type IfmaMsghdr2 struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386-cgo), type IfmaMsghdr2 struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386-cgo), type IfmaMsghdr2 struct, Refcount int32
 pkg syscall (darwin-386-cgo), type IfmaMsghdr2 struct, Type uint8
 pkg syscall (darwin-386-cgo), type IfmaMsghdr2 struct, Version uint8
 pkg syscall (darwin-386-cgo), type Inet6Pktinfo struct
-pkg syscall (darwin-386-cgo), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (darwin-386-cgo), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (darwin-386-cgo), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (darwin-386-cgo), type InterfaceAddrMessage struct
-pkg syscall (darwin-386-cgo), type InterfaceAddrMessage struct, Data []byte
+pkg syscall (darwin-386-cgo), type InterfaceAddrMessage struct, Data []uint8
 pkg syscall (darwin-386-cgo), type InterfaceAddrMessage struct, Header IfaMsghdr
 pkg syscall (darwin-386-cgo), type InterfaceMessage struct
-pkg syscall (darwin-386-cgo), type InterfaceMessage struct, Data []byte
+pkg syscall (darwin-386-cgo), type InterfaceMessage struct, Data []uint8
 pkg syscall (darwin-386-cgo), type InterfaceMessage struct, Header IfMsghdr
 pkg syscall (darwin-386-cgo), type InterfaceMulticastAddrMessage struct
-pkg syscall (darwin-386-cgo), type InterfaceMulticastAddrMessage struct, Data []byte
+pkg syscall (darwin-386-cgo), type InterfaceMulticastAddrMessage struct, Data []uint8
 pkg syscall (darwin-386-cgo), type InterfaceMulticastAddrMessage struct, Header IfmaMsghdr2
 pkg syscall (darwin-386-cgo), type Iovec struct
-pkg syscall (darwin-386-cgo), type Iovec struct, Base *byte
+pkg syscall (darwin-386-cgo), type Iovec struct, Base *uint8
 pkg syscall (darwin-386-cgo), type Iovec struct, Len uint32
 pkg syscall (darwin-386-cgo), type Kevent_t struct
 pkg syscall (darwin-386-cgo), type Kevent_t struct, Data int32
@@ -9378,18 +9376,18 @@ pkg syscall (darwin-386-cgo), type Kevent_t struct, Fflags uint32
 pkg syscall (darwin-386-cgo), type Kevent_t struct, Filter int16
 pkg syscall (darwin-386-cgo), type Kevent_t struct, Flags uint16
 pkg syscall (darwin-386-cgo), type Kevent_t struct, Ident uint32
-pkg syscall (darwin-386-cgo), type Kevent_t struct, Udata *byte
+pkg syscall (darwin-386-cgo), type Kevent_t struct, Udata *uint8
 pkg syscall (darwin-386-cgo), type Log2phys_t struct
 pkg syscall (darwin-386-cgo), type Log2phys_t struct, Contigbytes int64
 pkg syscall (darwin-386-cgo), type Log2phys_t struct, Devoffset int64
 pkg syscall (darwin-386-cgo), type Log2phys_t struct, Flags uint32
 pkg syscall (darwin-386-cgo), type Msghdr struct
-pkg syscall (darwin-386-cgo), type Msghdr struct, Control *byte
+pkg syscall (darwin-386-cgo), type Msghdr struct, Control *uint8
 pkg syscall (darwin-386-cgo), type Msghdr struct, Controllen uint32
 pkg syscall (darwin-386-cgo), type Msghdr struct, Flags int32
 pkg syscall (darwin-386-cgo), type Msghdr struct, Iov *Iovec
 pkg syscall (darwin-386-cgo), type Msghdr struct, Iovlen int32
-pkg syscall (darwin-386-cgo), type Msghdr struct, Name *byte
+pkg syscall (darwin-386-cgo), type Msghdr struct, Name *uint8
 pkg syscall (darwin-386-cgo), type Msghdr struct, Namelen uint32
 pkg syscall (darwin-386-cgo), type Radvisory_t struct
 pkg syscall (darwin-386-cgo), type Radvisory_t struct, Count int32
@@ -9411,7 +9409,7 @@ pkg syscall (darwin-386-cgo), type RawSockaddrInet4 struct, Family uint8
 pkg syscall (darwin-386-cgo), type RawSockaddrInet4 struct, Len uint8
 pkg syscall (darwin-386-cgo), type RawSockaddrInet4 struct, Zero [8]int8
 pkg syscall (darwin-386-cgo), type RawSockaddrInet6 struct
-pkg syscall (darwin-386-cgo), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (darwin-386-cgo), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (darwin-386-cgo), type RawSockaddrInet6 struct, Family uint8
 pkg syscall (darwin-386-cgo), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (darwin-386-cgo), type RawSockaddrInet6 struct, Len uint8
@@ -9425,9 +9423,9 @@ pkg syscall (darwin-386-cgo), type Rlimit struct
 pkg syscall (darwin-386-cgo), type Rlimit struct, Cur uint64
 pkg syscall (darwin-386-cgo), type Rlimit struct, Max uint64
 pkg syscall (darwin-386-cgo), type RouteMessage struct
-pkg syscall (darwin-386-cgo), type RouteMessage struct, Data []byte
+pkg syscall (darwin-386-cgo), type RouteMessage struct, Data []uint8
 pkg syscall (darwin-386-cgo), type RouteMessage struct, Header RtMsghdr
-pkg syscall (darwin-386-cgo), type RoutingMessage interface {}
+pkg syscall (darwin-386-cgo), type RoutingMessage interface, unexported methods
 pkg syscall (darwin-386-cgo), type RtMetrics struct
 pkg syscall (darwin-386-cgo), type RtMetrics struct, Expire int32
 pkg syscall (darwin-386-cgo), type RtMetrics struct, Filler [4]uint32
@@ -9447,7 +9445,7 @@ pkg syscall (darwin-386-cgo), type RtMsghdr struct, Flags int32
 pkg syscall (darwin-386-cgo), type RtMsghdr struct, Index uint16
 pkg syscall (darwin-386-cgo), type RtMsghdr struct, Inits uint32
 pkg syscall (darwin-386-cgo), type RtMsghdr struct, Msglen uint16
-pkg syscall (darwin-386-cgo), type RtMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-386-cgo), type RtMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-386-cgo), type RtMsghdr struct, Pid int32
 pkg syscall (darwin-386-cgo), type RtMsghdr struct, Rmx RtMetrics
 pkg syscall (darwin-386-cgo), type RtMsghdr struct, Seq int32
@@ -9480,7 +9478,7 @@ pkg syscall (darwin-386-cgo), type SockaddrDatalink struct, Nlen uint8
 pkg syscall (darwin-386-cgo), type SockaddrDatalink struct, Slen uint8
 pkg syscall (darwin-386-cgo), type SockaddrDatalink struct, Type uint8
 pkg syscall (darwin-386-cgo), type SocketControlMessage struct
-pkg syscall (darwin-386-cgo), type SocketControlMessage struct, Data []byte
+pkg syscall (darwin-386-cgo), type SocketControlMessage struct, Data []uint8
 pkg syscall (darwin-386-cgo), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (darwin-386-cgo), type Stat_t struct
 pkg syscall (darwin-386-cgo), type Stat_t struct, Atimespec Timespec
@@ -9529,7 +9527,7 @@ pkg syscall (darwin-386-cgo), type Timespec struct, Nsec int32
 pkg syscall (darwin-386-cgo), type Timespec struct, Sec int32
 pkg syscall (darwin-386-cgo), type Timeval struct, Sec int32
 pkg syscall (darwin-386-cgo), type Timeval struct, Usec int32
-pkg syscall (darwin-386-cgo), type Timeval32 [0]byte
+pkg syscall (darwin-386-cgo), type Timeval32 [0]uint8
 pkg syscall (darwin-386-cgo), type WaitStatus uint32
 pkg syscall (darwin-386-cgo), var Stderr int
 pkg syscall (darwin-386-cgo), var Stdin int
@@ -10918,9 +10916,9 @@ pkg syscall (darwin-amd64), func BpfBuflen(int) (int, error)
 pkg syscall (darwin-amd64), func BpfDatalink(int) (int, error)
 pkg syscall (darwin-amd64), func BpfHeadercmpl(int) (int, error)
 pkg syscall (darwin-amd64), func BpfInterface(int, string) (string, error)
-pkg syscall (darwin-amd64), func BpfJump(int) *BpfInsn
+pkg syscall (darwin-amd64), func BpfJump(int, int, int, int) *BpfInsn
 pkg syscall (darwin-amd64), func BpfStats(int) (*BpfStat, error)
-pkg syscall (darwin-amd64), func BpfStmt(int) *BpfInsn
+pkg syscall (darwin-amd64), func BpfStmt(int, int) *BpfInsn
 pkg syscall (darwin-amd64), func BpfTimeout(int) (*Timeval, error)
 pkg syscall (darwin-amd64), func CheckBpfVersion(int) error
 pkg syscall (darwin-amd64), func Chflags(string, int) error
@@ -10946,7 +10944,7 @@ pkg syscall (darwin-amd64), func Fstatfs(int, *Statfs_t) error
 pkg syscall (darwin-amd64), func Fsync(int) error
 pkg syscall (darwin-amd64), func Ftruncate(int, int64) error
 pkg syscall (darwin-amd64), func Futimes(int, []Timeval) error
-pkg syscall (darwin-amd64), func Getdirentries(int, []byte, *uintptr) (int, error)
+pkg syscall (darwin-amd64), func Getdirentries(int, []uint8, *uintptr) (int, error)
 pkg syscall (darwin-amd64), func Getdtablesize() int
 pkg syscall (darwin-amd64), func Getfsstat([]Statfs_t, int) (int, error)
 pkg syscall (darwin-amd64), func Getpeername(int) (Sockaddr, error)
@@ -10957,58 +10955,56 @@ pkg syscall (darwin-amd64), func Getrlimit(int, *Rlimit) error
 pkg syscall (darwin-amd64), func Getrusage(int, *Rusage) error
 pkg syscall (darwin-amd64), func Getsid(int) (int, error)
 pkg syscall (darwin-amd64), func Getsockname(int) (Sockaddr, error)
-pkg syscall (darwin-amd64), func GetsockoptByte(int) (byte, error)
-pkg syscall (darwin-amd64), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (darwin-amd64), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (darwin-amd64), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (darwin-amd64), func GetsockoptInt(int) (int, error)
+pkg syscall (darwin-amd64), func GetsockoptByte(int, int, int) (uint8, error)
+pkg syscall (darwin-amd64), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (darwin-amd64), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (darwin-amd64), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (darwin-amd64), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (darwin-amd64), func Issetugid() bool
-pkg syscall (darwin-amd64), func Kevent(int, []Kevent_t, *Timespec) (int, error)
+pkg syscall (darwin-amd64), func Kevent(int, []Kevent_t, []Kevent_t, *Timespec) (int, error)
 pkg syscall (darwin-amd64), func Kill(int, Signal) error
 pkg syscall (darwin-amd64), func Kqueue() (int, error)
-pkg syscall (darwin-amd64), func Link(string, string) error
 pkg syscall (darwin-amd64), func Listen(int, int) error
 pkg syscall (darwin-amd64), func Lstat(string, *Stat_t) error
 pkg syscall (darwin-amd64), func Mkfifo(string, uint32) error
 pkg syscall (darwin-amd64), func Mknod(string, uint32, int) error
-pkg syscall (darwin-amd64), func Mmap(int, int64, int, int, int) ([]byte, error)
-pkg syscall (darwin-amd64), func Munmap([]byte) error
+pkg syscall (darwin-amd64), func Mmap(int, int64, int, int, int) ([]uint8, error)
+pkg syscall (darwin-amd64), func Munmap([]uint8) error
 pkg syscall (darwin-amd64), func NsecToTimespec(int64) Timespec
 pkg syscall (darwin-amd64), func Open(string, int, uint32) (int, error)
-pkg syscall (darwin-amd64), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (darwin-amd64), func ParseRoutingMessage([]byte) ([]RoutingMessage, error)
+pkg syscall (darwin-amd64), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (darwin-amd64), func ParseRoutingMessage([]uint8) ([]RoutingMessage, error)
 pkg syscall (darwin-amd64), func ParseRoutingSockaddr(RoutingMessage) ([]Sockaddr, error)
-pkg syscall (darwin-amd64), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (darwin-amd64), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (darwin-amd64), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (darwin-amd64), func Pathconf(string, int) (int, error)
 pkg syscall (darwin-amd64), func Pipe([]int) error
-pkg syscall (darwin-amd64), func Pread(int, []byte, int64) (int, error)
+pkg syscall (darwin-amd64), func Pread(int, []uint8, int64) (int, error)
 pkg syscall (darwin-amd64), func PtraceAttach(int) error
 pkg syscall (darwin-amd64), func PtraceDetach(int) error
-pkg syscall (darwin-amd64), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (darwin-amd64), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (darwin-amd64), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (darwin-amd64), func Read(int, []byte) (int, error)
-pkg syscall (darwin-amd64), func ReadDirent(int, []byte) (int, error)
-pkg syscall (darwin-amd64), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (darwin-amd64), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (darwin-amd64), func Rename(string, string) error
+pkg syscall (darwin-amd64), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (darwin-amd64), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-amd64), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-amd64), func Read(int, []uint8) (int, error)
+pkg syscall (darwin-amd64), func ReadDirent(int, []uint8) (int, error)
+pkg syscall (darwin-amd64), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (darwin-amd64), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (darwin-amd64), func Revoke(string) error
-pkg syscall (darwin-amd64), func RouteRIB(int) ([]byte, error)
+pkg syscall (darwin-amd64), func RouteRIB(int, int) ([]uint8, error)
 pkg syscall (darwin-amd64), func Seek(int, int64, int) (int64, error)
 pkg syscall (darwin-amd64), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) error
 pkg syscall (darwin-amd64), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (darwin-amd64), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (darwin-amd64), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (darwin-amd64), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (darwin-amd64), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (darwin-amd64), func SetBpf(int, []BpfInsn) error
-pkg syscall (darwin-amd64), func SetBpfBuflen(int) (int, error)
-pkg syscall (darwin-amd64), func SetBpfDatalink(int) (int, error)
-pkg syscall (darwin-amd64), func SetBpfHeadercmpl(int) error
-pkg syscall (darwin-amd64), func SetBpfImmediate(int) error
+pkg syscall (darwin-amd64), func SetBpfBuflen(int, int) (int, error)
+pkg syscall (darwin-amd64), func SetBpfDatalink(int, int) (int, error)
+pkg syscall (darwin-amd64), func SetBpfHeadercmpl(int, int) error
+pkg syscall (darwin-amd64), func SetBpfImmediate(int, int) error
 pkg syscall (darwin-amd64), func SetBpfInterface(int, string) error
-pkg syscall (darwin-amd64), func SetBpfPromisc(int) error
+pkg syscall (darwin-amd64), func SetBpfPromisc(int, int) error
 pkg syscall (darwin-amd64), func SetBpfTimeout(int, *Timeval) error
-pkg syscall (darwin-amd64), func SetKevent(*Kevent_t, int)
+pkg syscall (darwin-amd64), func SetKevent(*Kevent_t, int, int, int)
 pkg syscall (darwin-amd64), func SetNonblock(int, bool) error
 pkg syscall (darwin-amd64), func Setegid(int) error
 pkg syscall (darwin-amd64), func Seteuid(int) error
@@ -11022,24 +11018,25 @@ pkg syscall (darwin-amd64), func Setregid(int, int) error
 pkg syscall (darwin-amd64), func Setreuid(int, int) error
 pkg syscall (darwin-amd64), func Setrlimit(int, *Rlimit) error
 pkg syscall (darwin-amd64), func Setsid() (int, error)
-pkg syscall (darwin-amd64), func SetsockoptByte(int, byte) error
-pkg syscall (darwin-amd64), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (darwin-amd64), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (darwin-amd64), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (darwin-amd64), func SetsockoptInt(int, int) error
-pkg syscall (darwin-amd64), func SetsockoptLinger(int, *Linger) error
-pkg syscall (darwin-amd64), func SetsockoptString(int, string) error
-pkg syscall (darwin-amd64), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (darwin-amd64), func SetsockoptByte(int, int, int, uint8) error
+pkg syscall (darwin-amd64), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (darwin-amd64), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (darwin-amd64), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (darwin-amd64), func SetsockoptInt(int, int, int, int) error
+pkg syscall (darwin-amd64), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (darwin-amd64), func SetsockoptString(int, int, int, string) error
+pkg syscall (darwin-amd64), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (darwin-amd64), func Settimeofday(*Timeval) error
 pkg syscall (darwin-amd64), func Setuid(int) error
 pkg syscall (darwin-amd64), func Shutdown(int, int) error
-pkg syscall (darwin-amd64), func Socket(int) (int, error)
-pkg syscall (darwin-amd64), func Socketpair(int) ([2]int, error)
+pkg syscall (darwin-amd64), func Socket(int, int, int) (int, error)
+pkg syscall (darwin-amd64), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (darwin-amd64), func Stat(string, *Stat_t) error
 pkg syscall (darwin-amd64), func Statfs(string, *Statfs_t) error
-pkg syscall (darwin-amd64), func StringSlicePtr([]string) []*byte
-pkg syscall (darwin-amd64), func Symlink(string, string) error
+pkg syscall (darwin-amd64), func StringSlicePtr([]string) []*uint8
 pkg syscall (darwin-amd64), func Sync() error
+pkg syscall (darwin-amd64), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-amd64), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (darwin-amd64), func Sysctl(string) (string, error)
 pkg syscall (darwin-amd64), func SysctlUint32(string) (uint32, error)
 pkg syscall (darwin-amd64), func TimespecToNsec(Timespec) int64
@@ -11047,10 +11044,10 @@ pkg syscall (darwin-amd64), func TimevalToNsec(Timeval) int64
 pkg syscall (darwin-amd64), func Truncate(string, int64) error
 pkg syscall (darwin-amd64), func Umask(int) int
 pkg syscall (darwin-amd64), func Undelete(string) error
-pkg syscall (darwin-amd64), func UnixRights(...int) []byte
+pkg syscall (darwin-amd64), func UnixRights(...int) []uint8
 pkg syscall (darwin-amd64), func Unmount(string, int) error
 pkg syscall (darwin-amd64), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (darwin-amd64), func Write(int, []byte) (int, error)
+pkg syscall (darwin-amd64), func Write(int, []uint8) (int, error)
 pkg syscall (darwin-amd64), method (*Cmsghdr) SetLen(int)
 pkg syscall (darwin-amd64), method (*Iovec) SetLen(int)
 pkg syscall (darwin-amd64), method (*Msghdr) SetControllen(int)
@@ -11058,7 +11055,7 @@ pkg syscall (darwin-amd64), type BpfHdr struct
 pkg syscall (darwin-amd64), type BpfHdr struct, Caplen uint32
 pkg syscall (darwin-amd64), type BpfHdr struct, Datalen uint32
 pkg syscall (darwin-amd64), type BpfHdr struct, Hdrlen uint16
-pkg syscall (darwin-amd64), type BpfHdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64), type BpfHdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64), type BpfHdr struct, Tstamp Timeval32
 pkg syscall (darwin-amd64), type BpfInsn struct
 pkg syscall (darwin-amd64), type BpfInsn struct, Code uint16
@@ -11068,7 +11065,7 @@ pkg syscall (darwin-amd64), type BpfInsn struct, K uint32
 pkg syscall (darwin-amd64), type BpfProgram struct
 pkg syscall (darwin-amd64), type BpfProgram struct, Insns *BpfInsn
 pkg syscall (darwin-amd64), type BpfProgram struct, Len uint32
-pkg syscall (darwin-amd64), type BpfProgram struct, Pad_cgo_0 [4]byte
+pkg syscall (darwin-amd64), type BpfProgram struct, Pad_cgo_0 [4]uint8
 pkg syscall (darwin-amd64), type BpfStat struct
 pkg syscall (darwin-amd64), type BpfStat struct, Drop uint32
 pkg syscall (darwin-amd64), type BpfStat struct, Recv uint32
@@ -11087,12 +11084,12 @@ pkg syscall (darwin-amd64), type Dirent struct
 pkg syscall (darwin-amd64), type Dirent struct, Ino uint64
 pkg syscall (darwin-amd64), type Dirent struct, Name [1024]int8
 pkg syscall (darwin-amd64), type Dirent struct, Namlen uint16
-pkg syscall (darwin-amd64), type Dirent struct, Pad_cgo_0 [3]byte
+pkg syscall (darwin-amd64), type Dirent struct, Pad_cgo_0 [3]uint8
 pkg syscall (darwin-amd64), type Dirent struct, Reclen uint16
 pkg syscall (darwin-amd64), type Dirent struct, Seekoff uint64
 pkg syscall (darwin-amd64), type Dirent struct, Type uint8
 pkg syscall (darwin-amd64), type Fbootstraptransfer_t struct
-pkg syscall (darwin-amd64), type Fbootstraptransfer_t struct, Buffer *byte
+pkg syscall (darwin-amd64), type Fbootstraptransfer_t struct, Buffer *uint8
 pkg syscall (darwin-amd64), type Fbootstraptransfer_t struct, Length uint64
 pkg syscall (darwin-amd64), type Fbootstraptransfer_t struct, Offset int64
 pkg syscall (darwin-amd64), type FdSet struct
@@ -11147,7 +11144,7 @@ pkg syscall (darwin-amd64), type IfMsghdr struct, Data IfData
 pkg syscall (darwin-amd64), type IfMsghdr struct, Flags int32
 pkg syscall (darwin-amd64), type IfMsghdr struct, Index uint16
 pkg syscall (darwin-amd64), type IfMsghdr struct, Msglen uint16
-pkg syscall (darwin-amd64), type IfMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64), type IfMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64), type IfMsghdr struct, Type uint8
 pkg syscall (darwin-amd64), type IfMsghdr struct, Version uint8
 pkg syscall (darwin-amd64), type IfaMsghdr struct
@@ -11156,7 +11153,7 @@ pkg syscall (darwin-amd64), type IfaMsghdr struct, Flags int32
 pkg syscall (darwin-amd64), type IfaMsghdr struct, Index uint16
 pkg syscall (darwin-amd64), type IfaMsghdr struct, Metric int32
 pkg syscall (darwin-amd64), type IfaMsghdr struct, Msglen uint16
-pkg syscall (darwin-amd64), type IfaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64), type IfaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64), type IfaMsghdr struct, Type uint8
 pkg syscall (darwin-amd64), type IfaMsghdr struct, Version uint8
 pkg syscall (darwin-amd64), type IfmaMsghdr struct
@@ -11164,7 +11161,7 @@ pkg syscall (darwin-amd64), type IfmaMsghdr struct, Addrs int32
 pkg syscall (darwin-amd64), type IfmaMsghdr struct, Flags int32
 pkg syscall (darwin-amd64), type IfmaMsghdr struct, Index uint16
 pkg syscall (darwin-amd64), type IfmaMsghdr struct, Msglen uint16
-pkg syscall (darwin-amd64), type IfmaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64), type IfmaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64), type IfmaMsghdr struct, Type uint8
 pkg syscall (darwin-amd64), type IfmaMsghdr struct, Version uint8
 pkg syscall (darwin-amd64), type IfmaMsghdr2 struct
@@ -11172,24 +11169,24 @@ pkg syscall (darwin-amd64), type IfmaMsghdr2 struct, Addrs int32
 pkg syscall (darwin-amd64), type IfmaMsghdr2 struct, Flags int32
 pkg syscall (darwin-amd64), type IfmaMsghdr2 struct, Index uint16
 pkg syscall (darwin-amd64), type IfmaMsghdr2 struct, Msglen uint16
-pkg syscall (darwin-amd64), type IfmaMsghdr2 struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64), type IfmaMsghdr2 struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64), type IfmaMsghdr2 struct, Refcount int32
 pkg syscall (darwin-amd64), type IfmaMsghdr2 struct, Type uint8
 pkg syscall (darwin-amd64), type IfmaMsghdr2 struct, Version uint8
 pkg syscall (darwin-amd64), type Inet6Pktinfo struct
-pkg syscall (darwin-amd64), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (darwin-amd64), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (darwin-amd64), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (darwin-amd64), type InterfaceAddrMessage struct
-pkg syscall (darwin-amd64), type InterfaceAddrMessage struct, Data []byte
+pkg syscall (darwin-amd64), type InterfaceAddrMessage struct, Data []uint8
 pkg syscall (darwin-amd64), type InterfaceAddrMessage struct, Header IfaMsghdr
 pkg syscall (darwin-amd64), type InterfaceMessage struct
-pkg syscall (darwin-amd64), type InterfaceMessage struct, Data []byte
+pkg syscall (darwin-amd64), type InterfaceMessage struct, Data []uint8
 pkg syscall (darwin-amd64), type InterfaceMessage struct, Header IfMsghdr
 pkg syscall (darwin-amd64), type InterfaceMulticastAddrMessage struct
-pkg syscall (darwin-amd64), type InterfaceMulticastAddrMessage struct, Data []byte
+pkg syscall (darwin-amd64), type InterfaceMulticastAddrMessage struct, Data []uint8
 pkg syscall (darwin-amd64), type InterfaceMulticastAddrMessage struct, Header IfmaMsghdr2
 pkg syscall (darwin-amd64), type Iovec struct
-pkg syscall (darwin-amd64), type Iovec struct, Base *byte
+pkg syscall (darwin-amd64), type Iovec struct, Base *uint8
 pkg syscall (darwin-amd64), type Iovec struct, Len uint64
 pkg syscall (darwin-amd64), type Kevent_t struct
 pkg syscall (darwin-amd64), type Kevent_t struct, Data int64
@@ -11197,25 +11194,25 @@ pkg syscall (darwin-amd64), type Kevent_t struct, Fflags uint32
 pkg syscall (darwin-amd64), type Kevent_t struct, Filter int16
 pkg syscall (darwin-amd64), type Kevent_t struct, Flags uint16
 pkg syscall (darwin-amd64), type Kevent_t struct, Ident uint64
-pkg syscall (darwin-amd64), type Kevent_t struct, Udata *byte
+pkg syscall (darwin-amd64), type Kevent_t struct, Udata *uint8
 pkg syscall (darwin-amd64), type Log2phys_t struct
 pkg syscall (darwin-amd64), type Log2phys_t struct, Contigbytes int64
 pkg syscall (darwin-amd64), type Log2phys_t struct, Devoffset int64
 pkg syscall (darwin-amd64), type Log2phys_t struct, Flags uint32
 pkg syscall (darwin-amd64), type Msghdr struct
-pkg syscall (darwin-amd64), type Msghdr struct, Control *byte
+pkg syscall (darwin-amd64), type Msghdr struct, Control *uint8
 pkg syscall (darwin-amd64), type Msghdr struct, Controllen uint32
 pkg syscall (darwin-amd64), type Msghdr struct, Flags int32
 pkg syscall (darwin-amd64), type Msghdr struct, Iov *Iovec
 pkg syscall (darwin-amd64), type Msghdr struct, Iovlen int32
-pkg syscall (darwin-amd64), type Msghdr struct, Name *byte
+pkg syscall (darwin-amd64), type Msghdr struct, Name *uint8
 pkg syscall (darwin-amd64), type Msghdr struct, Namelen uint32
-pkg syscall (darwin-amd64), type Msghdr struct, Pad_cgo_0 [4]byte
-pkg syscall (darwin-amd64), type Msghdr struct, Pad_cgo_1 [4]byte
+pkg syscall (darwin-amd64), type Msghdr struct, Pad_cgo_0 [4]uint8
+pkg syscall (darwin-amd64), type Msghdr struct, Pad_cgo_1 [4]uint8
 pkg syscall (darwin-amd64), type Radvisory_t struct
 pkg syscall (darwin-amd64), type Radvisory_t struct, Count int32
 pkg syscall (darwin-amd64), type Radvisory_t struct, Offset int64
-pkg syscall (darwin-amd64), type Radvisory_t struct, Pad_cgo_0 [4]byte
+pkg syscall (darwin-amd64), type Radvisory_t struct, Pad_cgo_0 [4]uint8
 pkg syscall (darwin-amd64), type RawSockaddr struct, Data [14]int8
 pkg syscall (darwin-amd64), type RawSockaddr struct, Family uint8
 pkg syscall (darwin-amd64), type RawSockaddr struct, Len uint8
@@ -11233,7 +11230,7 @@ pkg syscall (darwin-amd64), type RawSockaddrInet4 struct, Family uint8
 pkg syscall (darwin-amd64), type RawSockaddrInet4 struct, Len uint8
 pkg syscall (darwin-amd64), type RawSockaddrInet4 struct, Zero [8]int8
 pkg syscall (darwin-amd64), type RawSockaddrInet6 struct
-pkg syscall (darwin-amd64), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (darwin-amd64), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (darwin-amd64), type RawSockaddrInet6 struct, Family uint8
 pkg syscall (darwin-amd64), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (darwin-amd64), type RawSockaddrInet6 struct, Len uint8
@@ -11247,9 +11244,9 @@ pkg syscall (darwin-amd64), type Rlimit struct
 pkg syscall (darwin-amd64), type Rlimit struct, Cur uint64
 pkg syscall (darwin-amd64), type Rlimit struct, Max uint64
 pkg syscall (darwin-amd64), type RouteMessage struct
-pkg syscall (darwin-amd64), type RouteMessage struct, Data []byte
+pkg syscall (darwin-amd64), type RouteMessage struct, Data []uint8
 pkg syscall (darwin-amd64), type RouteMessage struct, Header RtMsghdr
-pkg syscall (darwin-amd64), type RoutingMessage interface {}
+pkg syscall (darwin-amd64), type RoutingMessage interface, unexported methods
 pkg syscall (darwin-amd64), type RtMetrics struct
 pkg syscall (darwin-amd64), type RtMetrics struct, Expire int32
 pkg syscall (darwin-amd64), type RtMetrics struct, Filler [4]uint32
@@ -11269,7 +11266,7 @@ pkg syscall (darwin-amd64), type RtMsghdr struct, Flags int32
 pkg syscall (darwin-amd64), type RtMsghdr struct, Index uint16
 pkg syscall (darwin-amd64), type RtMsghdr struct, Inits uint32
 pkg syscall (darwin-amd64), type RtMsghdr struct, Msglen uint16
-pkg syscall (darwin-amd64), type RtMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64), type RtMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64), type RtMsghdr struct, Pid int32
 pkg syscall (darwin-amd64), type RtMsghdr struct, Rmx RtMetrics
 pkg syscall (darwin-amd64), type RtMsghdr struct, Seq int32
@@ -11302,7 +11299,7 @@ pkg syscall (darwin-amd64), type SockaddrDatalink struct, Nlen uint8
 pkg syscall (darwin-amd64), type SockaddrDatalink struct, Slen uint8
 pkg syscall (darwin-amd64), type SockaddrDatalink struct, Type uint8
 pkg syscall (darwin-amd64), type SocketControlMessage struct
-pkg syscall (darwin-amd64), type SocketControlMessage struct, Data []byte
+pkg syscall (darwin-amd64), type SocketControlMessage struct, Data []uint8
 pkg syscall (darwin-amd64), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (darwin-amd64), type Stat_t struct
 pkg syscall (darwin-amd64), type Stat_t struct, Atimespec Timespec
@@ -11319,7 +11316,7 @@ pkg syscall (darwin-amd64), type Stat_t struct, Lspare int32
 pkg syscall (darwin-amd64), type Stat_t struct, Mode uint16
 pkg syscall (darwin-amd64), type Stat_t struct, Mtimespec Timespec
 pkg syscall (darwin-amd64), type Stat_t struct, Nlink uint16
-pkg syscall (darwin-amd64), type Stat_t struct, Pad_cgo_0 [4]byte
+pkg syscall (darwin-amd64), type Stat_t struct, Pad_cgo_0 [4]uint8
 pkg syscall (darwin-amd64), type Stat_t struct, Qspare [2]int64
 pkg syscall (darwin-amd64), type Stat_t struct, Rdev int32
 pkg syscall (darwin-amd64), type Stat_t struct, Size int64
@@ -11350,7 +11347,7 @@ pkg syscall (darwin-amd64), type SysProcAttr struct, Setpgid bool
 pkg syscall (darwin-amd64), type SysProcAttr struct, Setsid bool
 pkg syscall (darwin-amd64), type Timespec struct, Nsec int64
 pkg syscall (darwin-amd64), type Timespec struct, Sec int64
-pkg syscall (darwin-amd64), type Timeval struct, Pad_cgo_0 [4]byte
+pkg syscall (darwin-amd64), type Timeval struct, Pad_cgo_0 [4]uint8
 pkg syscall (darwin-amd64), type Timeval struct, Sec int64
 pkg syscall (darwin-amd64), type Timeval struct, Usec int32
 pkg syscall (darwin-amd64), type Timeval32 struct
@@ -12744,9 +12741,9 @@ pkg syscall (darwin-amd64-cgo), func BpfBuflen(int) (int, error)
 pkg syscall (darwin-amd64-cgo), func BpfDatalink(int) (int, error)
 pkg syscall (darwin-amd64-cgo), func BpfHeadercmpl(int) (int, error)
 pkg syscall (darwin-amd64-cgo), func BpfInterface(int, string) (string, error)
-pkg syscall (darwin-amd64-cgo), func BpfJump(int) *BpfInsn
+pkg syscall (darwin-amd64-cgo), func BpfJump(int, int, int, int) *BpfInsn
 pkg syscall (darwin-amd64-cgo), func BpfStats(int) (*BpfStat, error)
-pkg syscall (darwin-amd64-cgo), func BpfStmt(int) *BpfInsn
+pkg syscall (darwin-amd64-cgo), func BpfStmt(int, int) *BpfInsn
 pkg syscall (darwin-amd64-cgo), func BpfTimeout(int) (*Timeval, error)
 pkg syscall (darwin-amd64-cgo), func CheckBpfVersion(int) error
 pkg syscall (darwin-amd64-cgo), func Chflags(string, int) error
@@ -12772,7 +12769,7 @@ pkg syscall (darwin-amd64-cgo), func Fstatfs(int, *Statfs_t) error
 pkg syscall (darwin-amd64-cgo), func Fsync(int) error
 pkg syscall (darwin-amd64-cgo), func Ftruncate(int, int64) error
 pkg syscall (darwin-amd64-cgo), func Futimes(int, []Timeval) error
-pkg syscall (darwin-amd64-cgo), func Getdirentries(int, []byte, *uintptr) (int, error)
+pkg syscall (darwin-amd64-cgo), func Getdirentries(int, []uint8, *uintptr) (int, error)
 pkg syscall (darwin-amd64-cgo), func Getdtablesize() int
 pkg syscall (darwin-amd64-cgo), func Getfsstat([]Statfs_t, int) (int, error)
 pkg syscall (darwin-amd64-cgo), func Getpeername(int) (Sockaddr, error)
@@ -12783,58 +12780,56 @@ pkg syscall (darwin-amd64-cgo), func Getrlimit(int, *Rlimit) error
 pkg syscall (darwin-amd64-cgo), func Getrusage(int, *Rusage) error
 pkg syscall (darwin-amd64-cgo), func Getsid(int) (int, error)
 pkg syscall (darwin-amd64-cgo), func Getsockname(int) (Sockaddr, error)
-pkg syscall (darwin-amd64-cgo), func GetsockoptByte(int) (byte, error)
-pkg syscall (darwin-amd64-cgo), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (darwin-amd64-cgo), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (darwin-amd64-cgo), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (darwin-amd64-cgo), func GetsockoptInt(int) (int, error)
+pkg syscall (darwin-amd64-cgo), func GetsockoptByte(int, int, int) (uint8, error)
+pkg syscall (darwin-amd64-cgo), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (darwin-amd64-cgo), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (darwin-amd64-cgo), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (darwin-amd64-cgo), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (darwin-amd64-cgo), func Issetugid() bool
-pkg syscall (darwin-amd64-cgo), func Kevent(int, []Kevent_t, *Timespec) (int, error)
+pkg syscall (darwin-amd64-cgo), func Kevent(int, []Kevent_t, []Kevent_t, *Timespec) (int, error)
 pkg syscall (darwin-amd64-cgo), func Kill(int, Signal) error
 pkg syscall (darwin-amd64-cgo), func Kqueue() (int, error)
-pkg syscall (darwin-amd64-cgo), func Link(string, string) error
 pkg syscall (darwin-amd64-cgo), func Listen(int, int) error
 pkg syscall (darwin-amd64-cgo), func Lstat(string, *Stat_t) error
 pkg syscall (darwin-amd64-cgo), func Mkfifo(string, uint32) error
 pkg syscall (darwin-amd64-cgo), func Mknod(string, uint32, int) error
-pkg syscall (darwin-amd64-cgo), func Mmap(int, int64, int, int, int) ([]byte, error)
-pkg syscall (darwin-amd64-cgo), func Munmap([]byte) error
+pkg syscall (darwin-amd64-cgo), func Mmap(int, int64, int, int, int) ([]uint8, error)
+pkg syscall (darwin-amd64-cgo), func Munmap([]uint8) error
 pkg syscall (darwin-amd64-cgo), func NsecToTimespec(int64) Timespec
 pkg syscall (darwin-amd64-cgo), func Open(string, int, uint32) (int, error)
-pkg syscall (darwin-amd64-cgo), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (darwin-amd64-cgo), func ParseRoutingMessage([]byte) ([]RoutingMessage, error)
+pkg syscall (darwin-amd64-cgo), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (darwin-amd64-cgo), func ParseRoutingMessage([]uint8) ([]RoutingMessage, error)
 pkg syscall (darwin-amd64-cgo), func ParseRoutingSockaddr(RoutingMessage) ([]Sockaddr, error)
-pkg syscall (darwin-amd64-cgo), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (darwin-amd64-cgo), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (darwin-amd64-cgo), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (darwin-amd64-cgo), func Pathconf(string, int) (int, error)
 pkg syscall (darwin-amd64-cgo), func Pipe([]int) error
-pkg syscall (darwin-amd64-cgo), func Pread(int, []byte, int64) (int, error)
+pkg syscall (darwin-amd64-cgo), func Pread(int, []uint8, int64) (int, error)
 pkg syscall (darwin-amd64-cgo), func PtraceAttach(int) error
 pkg syscall (darwin-amd64-cgo), func PtraceDetach(int) error
-pkg syscall (darwin-amd64-cgo), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (darwin-amd64-cgo), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (darwin-amd64-cgo), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (darwin-amd64-cgo), func Read(int, []byte) (int, error)
-pkg syscall (darwin-amd64-cgo), func ReadDirent(int, []byte) (int, error)
-pkg syscall (darwin-amd64-cgo), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (darwin-amd64-cgo), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (darwin-amd64-cgo), func Rename(string, string) error
+pkg syscall (darwin-amd64-cgo), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (darwin-amd64-cgo), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-amd64-cgo), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-amd64-cgo), func Read(int, []uint8) (int, error)
+pkg syscall (darwin-amd64-cgo), func ReadDirent(int, []uint8) (int, error)
+pkg syscall (darwin-amd64-cgo), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (darwin-amd64-cgo), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (darwin-amd64-cgo), func Revoke(string) error
-pkg syscall (darwin-amd64-cgo), func RouteRIB(int) ([]byte, error)
+pkg syscall (darwin-amd64-cgo), func RouteRIB(int, int) ([]uint8, error)
 pkg syscall (darwin-amd64-cgo), func Seek(int, int64, int) (int64, error)
 pkg syscall (darwin-amd64-cgo), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) error
 pkg syscall (darwin-amd64-cgo), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (darwin-amd64-cgo), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (darwin-amd64-cgo), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (darwin-amd64-cgo), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (darwin-amd64-cgo), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (darwin-amd64-cgo), func SetBpf(int, []BpfInsn) error
-pkg syscall (darwin-amd64-cgo), func SetBpfBuflen(int) (int, error)
-pkg syscall (darwin-amd64-cgo), func SetBpfDatalink(int) (int, error)
-pkg syscall (darwin-amd64-cgo), func SetBpfHeadercmpl(int) error
-pkg syscall (darwin-amd64-cgo), func SetBpfImmediate(int) error
+pkg syscall (darwin-amd64-cgo), func SetBpfBuflen(int, int) (int, error)
+pkg syscall (darwin-amd64-cgo), func SetBpfDatalink(int, int) (int, error)
+pkg syscall (darwin-amd64-cgo), func SetBpfHeadercmpl(int, int) error
+pkg syscall (darwin-amd64-cgo), func SetBpfImmediate(int, int) error
 pkg syscall (darwin-amd64-cgo), func SetBpfInterface(int, string) error
-pkg syscall (darwin-amd64-cgo), func SetBpfPromisc(int) error
+pkg syscall (darwin-amd64-cgo), func SetBpfPromisc(int, int) error
 pkg syscall (darwin-amd64-cgo), func SetBpfTimeout(int, *Timeval) error
-pkg syscall (darwin-amd64-cgo), func SetKevent(*Kevent_t, int)
+pkg syscall (darwin-amd64-cgo), func SetKevent(*Kevent_t, int, int, int)
 pkg syscall (darwin-amd64-cgo), func SetNonblock(int, bool) error
 pkg syscall (darwin-amd64-cgo), func Setegid(int) error
 pkg syscall (darwin-amd64-cgo), func Seteuid(int) error
@@ -12848,24 +12843,25 @@ pkg syscall (darwin-amd64-cgo), func Setregid(int, int) error
 pkg syscall (darwin-amd64-cgo), func Setreuid(int, int) error
 pkg syscall (darwin-amd64-cgo), func Setrlimit(int, *Rlimit) error
 pkg syscall (darwin-amd64-cgo), func Setsid() (int, error)
-pkg syscall (darwin-amd64-cgo), func SetsockoptByte(int, byte) error
-pkg syscall (darwin-amd64-cgo), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (darwin-amd64-cgo), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (darwin-amd64-cgo), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (darwin-amd64-cgo), func SetsockoptInt(int, int) error
-pkg syscall (darwin-amd64-cgo), func SetsockoptLinger(int, *Linger) error
-pkg syscall (darwin-amd64-cgo), func SetsockoptString(int, string) error
-pkg syscall (darwin-amd64-cgo), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (darwin-amd64-cgo), func SetsockoptByte(int, int, int, uint8) error
+pkg syscall (darwin-amd64-cgo), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (darwin-amd64-cgo), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (darwin-amd64-cgo), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (darwin-amd64-cgo), func SetsockoptInt(int, int, int, int) error
+pkg syscall (darwin-amd64-cgo), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (darwin-amd64-cgo), func SetsockoptString(int, int, int, string) error
+pkg syscall (darwin-amd64-cgo), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (darwin-amd64-cgo), func Settimeofday(*Timeval) error
 pkg syscall (darwin-amd64-cgo), func Setuid(int) error
 pkg syscall (darwin-amd64-cgo), func Shutdown(int, int) error
-pkg syscall (darwin-amd64-cgo), func Socket(int) (int, error)
-pkg syscall (darwin-amd64-cgo), func Socketpair(int) ([2]int, error)
+pkg syscall (darwin-amd64-cgo), func Socket(int, int, int) (int, error)
+pkg syscall (darwin-amd64-cgo), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (darwin-amd64-cgo), func Stat(string, *Stat_t) error
 pkg syscall (darwin-amd64-cgo), func Statfs(string, *Statfs_t) error
-pkg syscall (darwin-amd64-cgo), func StringSlicePtr([]string) []*byte
-pkg syscall (darwin-amd64-cgo), func Symlink(string, string) error
+pkg syscall (darwin-amd64-cgo), func StringSlicePtr([]string) []*uint8
 pkg syscall (darwin-amd64-cgo), func Sync() error
+pkg syscall (darwin-amd64-cgo), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (darwin-amd64-cgo), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (darwin-amd64-cgo), func Sysctl(string) (string, error)
 pkg syscall (darwin-amd64-cgo), func SysctlUint32(string) (uint32, error)
 pkg syscall (darwin-amd64-cgo), func TimespecToNsec(Timespec) int64
@@ -12873,10 +12869,10 @@ pkg syscall (darwin-amd64-cgo), func TimevalToNsec(Timeval) int64
 pkg syscall (darwin-amd64-cgo), func Truncate(string, int64) error
 pkg syscall (darwin-amd64-cgo), func Umask(int) int
 pkg syscall (darwin-amd64-cgo), func Undelete(string) error
-pkg syscall (darwin-amd64-cgo), func UnixRights(...int) []byte
+pkg syscall (darwin-amd64-cgo), func UnixRights(...int) []uint8
 pkg syscall (darwin-amd64-cgo), func Unmount(string, int) error
 pkg syscall (darwin-amd64-cgo), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (darwin-amd64-cgo), func Write(int, []byte) (int, error)
+pkg syscall (darwin-amd64-cgo), func Write(int, []uint8) (int, error)
 pkg syscall (darwin-amd64-cgo), method (*Cmsghdr) SetLen(int)
 pkg syscall (darwin-amd64-cgo), method (*Iovec) SetLen(int)
 pkg syscall (darwin-amd64-cgo), method (*Msghdr) SetControllen(int)
@@ -12884,7 +12880,7 @@ pkg syscall (darwin-amd64-cgo), type BpfHdr struct
 pkg syscall (darwin-amd64-cgo), type BpfHdr struct, Caplen uint32
 pkg syscall (darwin-amd64-cgo), type BpfHdr struct, Datalen uint32
 pkg syscall (darwin-amd64-cgo), type BpfHdr struct, Hdrlen uint16
-pkg syscall (darwin-amd64-cgo), type BpfHdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64-cgo), type BpfHdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64-cgo), type BpfHdr struct, Tstamp Timeval32
 pkg syscall (darwin-amd64-cgo), type BpfInsn struct
 pkg syscall (darwin-amd64-cgo), type BpfInsn struct, Code uint16
@@ -12894,7 +12890,7 @@ pkg syscall (darwin-amd64-cgo), type BpfInsn struct, K uint32
 pkg syscall (darwin-amd64-cgo), type BpfProgram struct
 pkg syscall (darwin-amd64-cgo), type BpfProgram struct, Insns *BpfInsn
 pkg syscall (darwin-amd64-cgo), type BpfProgram struct, Len uint32
-pkg syscall (darwin-amd64-cgo), type BpfProgram struct, Pad_cgo_0 [4]byte
+pkg syscall (darwin-amd64-cgo), type BpfProgram struct, Pad_cgo_0 [4]uint8
 pkg syscall (darwin-amd64-cgo), type BpfStat struct
 pkg syscall (darwin-amd64-cgo), type BpfStat struct, Drop uint32
 pkg syscall (darwin-amd64-cgo), type BpfStat struct, Recv uint32
@@ -12913,12 +12909,12 @@ pkg syscall (darwin-amd64-cgo), type Dirent struct
 pkg syscall (darwin-amd64-cgo), type Dirent struct, Ino uint64
 pkg syscall (darwin-amd64-cgo), type Dirent struct, Name [1024]int8
 pkg syscall (darwin-amd64-cgo), type Dirent struct, Namlen uint16
-pkg syscall (darwin-amd64-cgo), type Dirent struct, Pad_cgo_0 [3]byte
+pkg syscall (darwin-amd64-cgo), type Dirent struct, Pad_cgo_0 [3]uint8
 pkg syscall (darwin-amd64-cgo), type Dirent struct, Reclen uint16
 pkg syscall (darwin-amd64-cgo), type Dirent struct, Seekoff uint64
 pkg syscall (darwin-amd64-cgo), type Dirent struct, Type uint8
 pkg syscall (darwin-amd64-cgo), type Fbootstraptransfer_t struct
-pkg syscall (darwin-amd64-cgo), type Fbootstraptransfer_t struct, Buffer *byte
+pkg syscall (darwin-amd64-cgo), type Fbootstraptransfer_t struct, Buffer *uint8
 pkg syscall (darwin-amd64-cgo), type Fbootstraptransfer_t struct, Length uint64
 pkg syscall (darwin-amd64-cgo), type Fbootstraptransfer_t struct, Offset int64
 pkg syscall (darwin-amd64-cgo), type FdSet struct
@@ -12973,7 +12969,7 @@ pkg syscall (darwin-amd64-cgo), type IfMsghdr struct, Data IfData
 pkg syscall (darwin-amd64-cgo), type IfMsghdr struct, Flags int32
 pkg syscall (darwin-amd64-cgo), type IfMsghdr struct, Index uint16
 pkg syscall (darwin-amd64-cgo), type IfMsghdr struct, Msglen uint16
-pkg syscall (darwin-amd64-cgo), type IfMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64-cgo), type IfMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64-cgo), type IfMsghdr struct, Type uint8
 pkg syscall (darwin-amd64-cgo), type IfMsghdr struct, Version uint8
 pkg syscall (darwin-amd64-cgo), type IfaMsghdr struct
@@ -12982,7 +12978,7 @@ pkg syscall (darwin-amd64-cgo), type IfaMsghdr struct, Flags int32
 pkg syscall (darwin-amd64-cgo), type IfaMsghdr struct, Index uint16
 pkg syscall (darwin-amd64-cgo), type IfaMsghdr struct, Metric int32
 pkg syscall (darwin-amd64-cgo), type IfaMsghdr struct, Msglen uint16
-pkg syscall (darwin-amd64-cgo), type IfaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64-cgo), type IfaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64-cgo), type IfaMsghdr struct, Type uint8
 pkg syscall (darwin-amd64-cgo), type IfaMsghdr struct, Version uint8
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr struct
@@ -12990,7 +12986,7 @@ pkg syscall (darwin-amd64-cgo), type IfmaMsghdr struct, Addrs int32
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr struct, Flags int32
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr struct, Index uint16
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr struct, Msglen uint16
-pkg syscall (darwin-amd64-cgo), type IfmaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64-cgo), type IfmaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr struct, Type uint8
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr struct, Version uint8
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr2 struct
@@ -12998,24 +12994,24 @@ pkg syscall (darwin-amd64-cgo), type IfmaMsghdr2 struct, Addrs int32
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr2 struct, Flags int32
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr2 struct, Index uint16
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr2 struct, Msglen uint16
-pkg syscall (darwin-amd64-cgo), type IfmaMsghdr2 struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64-cgo), type IfmaMsghdr2 struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr2 struct, Refcount int32
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr2 struct, Type uint8
 pkg syscall (darwin-amd64-cgo), type IfmaMsghdr2 struct, Version uint8
 pkg syscall (darwin-amd64-cgo), type Inet6Pktinfo struct
-pkg syscall (darwin-amd64-cgo), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (darwin-amd64-cgo), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (darwin-amd64-cgo), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (darwin-amd64-cgo), type InterfaceAddrMessage struct
-pkg syscall (darwin-amd64-cgo), type InterfaceAddrMessage struct, Data []byte
+pkg syscall (darwin-amd64-cgo), type InterfaceAddrMessage struct, Data []uint8
 pkg syscall (darwin-amd64-cgo), type InterfaceAddrMessage struct, Header IfaMsghdr
 pkg syscall (darwin-amd64-cgo), type InterfaceMessage struct
-pkg syscall (darwin-amd64-cgo), type InterfaceMessage struct, Data []byte
+pkg syscall (darwin-amd64-cgo), type InterfaceMessage struct, Data []uint8
 pkg syscall (darwin-amd64-cgo), type InterfaceMessage struct, Header IfMsghdr
 pkg syscall (darwin-amd64-cgo), type InterfaceMulticastAddrMessage struct
-pkg syscall (darwin-amd64-cgo), type InterfaceMulticastAddrMessage struct, Data []byte
+pkg syscall (darwin-amd64-cgo), type InterfaceMulticastAddrMessage struct, Data []uint8
 pkg syscall (darwin-amd64-cgo), type InterfaceMulticastAddrMessage struct, Header IfmaMsghdr2
 pkg syscall (darwin-amd64-cgo), type Iovec struct
-pkg syscall (darwin-amd64-cgo), type Iovec struct, Base *byte
+pkg syscall (darwin-amd64-cgo), type Iovec struct, Base *uint8
 pkg syscall (darwin-amd64-cgo), type Iovec struct, Len uint64
 pkg syscall (darwin-amd64-cgo), type Kevent_t struct
 pkg syscall (darwin-amd64-cgo), type Kevent_t struct, Data int64
@@ -13023,25 +13019,25 @@ pkg syscall (darwin-amd64-cgo), type Kevent_t struct, Fflags uint32
 pkg syscall (darwin-amd64-cgo), type Kevent_t struct, Filter int16
 pkg syscall (darwin-amd64-cgo), type Kevent_t struct, Flags uint16
 pkg syscall (darwin-amd64-cgo), type Kevent_t struct, Ident uint64
-pkg syscall (darwin-amd64-cgo), type Kevent_t struct, Udata *byte
+pkg syscall (darwin-amd64-cgo), type Kevent_t struct, Udata *uint8
 pkg syscall (darwin-amd64-cgo), type Log2phys_t struct
 pkg syscall (darwin-amd64-cgo), type Log2phys_t struct, Contigbytes int64
 pkg syscall (darwin-amd64-cgo), type Log2phys_t struct, Devoffset int64
 pkg syscall (darwin-amd64-cgo), type Log2phys_t struct, Flags uint32
 pkg syscall (darwin-amd64-cgo), type Msghdr struct
-pkg syscall (darwin-amd64-cgo), type Msghdr struct, Control *byte
+pkg syscall (darwin-amd64-cgo), type Msghdr struct, Control *uint8
 pkg syscall (darwin-amd64-cgo), type Msghdr struct, Controllen uint32
 pkg syscall (darwin-amd64-cgo), type Msghdr struct, Flags int32
 pkg syscall (darwin-amd64-cgo), type Msghdr struct, Iov *Iovec
 pkg syscall (darwin-amd64-cgo), type Msghdr struct, Iovlen int32
-pkg syscall (darwin-amd64-cgo), type Msghdr struct, Name *byte
+pkg syscall (darwin-amd64-cgo), type Msghdr struct, Name *uint8
 pkg syscall (darwin-amd64-cgo), type Msghdr struct, Namelen uint32
-pkg syscall (darwin-amd64-cgo), type Msghdr struct, Pad_cgo_0 [4]byte
-pkg syscall (darwin-amd64-cgo), type Msghdr struct, Pad_cgo_1 [4]byte
+pkg syscall (darwin-amd64-cgo), type Msghdr struct, Pad_cgo_0 [4]uint8
+pkg syscall (darwin-amd64-cgo), type Msghdr struct, Pad_cgo_1 [4]uint8
 pkg syscall (darwin-amd64-cgo), type Radvisory_t struct
 pkg syscall (darwin-amd64-cgo), type Radvisory_t struct, Count int32
 pkg syscall (darwin-amd64-cgo), type Radvisory_t struct, Offset int64
-pkg syscall (darwin-amd64-cgo), type Radvisory_t struct, Pad_cgo_0 [4]byte
+pkg syscall (darwin-amd64-cgo), type Radvisory_t struct, Pad_cgo_0 [4]uint8
 pkg syscall (darwin-amd64-cgo), type RawSockaddr struct, Data [14]int8
 pkg syscall (darwin-amd64-cgo), type RawSockaddr struct, Family uint8
 pkg syscall (darwin-amd64-cgo), type RawSockaddr struct, Len uint8
@@ -13059,7 +13055,7 @@ pkg syscall (darwin-amd64-cgo), type RawSockaddrInet4 struct, Family uint8
 pkg syscall (darwin-amd64-cgo), type RawSockaddrInet4 struct, Len uint8
 pkg syscall (darwin-amd64-cgo), type RawSockaddrInet4 struct, Zero [8]int8
 pkg syscall (darwin-amd64-cgo), type RawSockaddrInet6 struct
-pkg syscall (darwin-amd64-cgo), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (darwin-amd64-cgo), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (darwin-amd64-cgo), type RawSockaddrInet6 struct, Family uint8
 pkg syscall (darwin-amd64-cgo), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (darwin-amd64-cgo), type RawSockaddrInet6 struct, Len uint8
@@ -13073,9 +13069,9 @@ pkg syscall (darwin-amd64-cgo), type Rlimit struct
 pkg syscall (darwin-amd64-cgo), type Rlimit struct, Cur uint64
 pkg syscall (darwin-amd64-cgo), type Rlimit struct, Max uint64
 pkg syscall (darwin-amd64-cgo), type RouteMessage struct
-pkg syscall (darwin-amd64-cgo), type RouteMessage struct, Data []byte
+pkg syscall (darwin-amd64-cgo), type RouteMessage struct, Data []uint8
 pkg syscall (darwin-amd64-cgo), type RouteMessage struct, Header RtMsghdr
-pkg syscall (darwin-amd64-cgo), type RoutingMessage interface {}
+pkg syscall (darwin-amd64-cgo), type RoutingMessage interface, unexported methods
 pkg syscall (darwin-amd64-cgo), type RtMetrics struct
 pkg syscall (darwin-amd64-cgo), type RtMetrics struct, Expire int32
 pkg syscall (darwin-amd64-cgo), type RtMetrics struct, Filler [4]uint32
@@ -13095,7 +13091,7 @@ pkg syscall (darwin-amd64-cgo), type RtMsghdr struct, Flags int32
 pkg syscall (darwin-amd64-cgo), type RtMsghdr struct, Index uint16
 pkg syscall (darwin-amd64-cgo), type RtMsghdr struct, Inits uint32
 pkg syscall (darwin-amd64-cgo), type RtMsghdr struct, Msglen uint16
-pkg syscall (darwin-amd64-cgo), type RtMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (darwin-amd64-cgo), type RtMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (darwin-amd64-cgo), type RtMsghdr struct, Pid int32
 pkg syscall (darwin-amd64-cgo), type RtMsghdr struct, Rmx RtMetrics
 pkg syscall (darwin-amd64-cgo), type RtMsghdr struct, Seq int32
@@ -13128,7 +13124,7 @@ pkg syscall (darwin-amd64-cgo), type SockaddrDatalink struct, Nlen uint8
 pkg syscall (darwin-amd64-cgo), type SockaddrDatalink struct, Slen uint8
 pkg syscall (darwin-amd64-cgo), type SockaddrDatalink struct, Type uint8
 pkg syscall (darwin-amd64-cgo), type SocketControlMessage struct
-pkg syscall (darwin-amd64-cgo), type SocketControlMessage struct, Data []byte
+pkg syscall (darwin-amd64-cgo), type SocketControlMessage struct, Data []uint8
 pkg syscall (darwin-amd64-cgo), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (darwin-amd64-cgo), type Stat_t struct
 pkg syscall (darwin-amd64-cgo), type Stat_t struct, Atimespec Timespec
@@ -13145,7 +13141,7 @@ pkg syscall (darwin-amd64-cgo), type Stat_t struct, Lspare int32
 pkg syscall (darwin-amd64-cgo), type Stat_t struct, Mode uint16
 pkg syscall (darwin-amd64-cgo), type Stat_t struct, Mtimespec Timespec
 pkg syscall (darwin-amd64-cgo), type Stat_t struct, Nlink uint16
-pkg syscall (darwin-amd64-cgo), type Stat_t struct, Pad_cgo_0 [4]byte
+pkg syscall (darwin-amd64-cgo), type Stat_t struct, Pad_cgo_0 [4]uint8
 pkg syscall (darwin-amd64-cgo), type Stat_t struct, Qspare [2]int64
 pkg syscall (darwin-amd64-cgo), type Stat_t struct, Rdev int32
 pkg syscall (darwin-amd64-cgo), type Stat_t struct, Size int64
@@ -13176,7 +13172,7 @@ pkg syscall (darwin-amd64-cgo), type SysProcAttr struct, Setpgid bool
 pkg syscall (darwin-amd64-cgo), type SysProcAttr struct, Setsid bool
 pkg syscall (darwin-amd64-cgo), type Timespec struct, Nsec int64
 pkg syscall (darwin-amd64-cgo), type Timespec struct, Sec int64
-pkg syscall (darwin-amd64-cgo), type Timeval struct, Pad_cgo_0 [4]byte
+pkg syscall (darwin-amd64-cgo), type Timeval struct, Pad_cgo_0 [4]uint8
 pkg syscall (darwin-amd64-cgo), type Timeval struct, Sec int64
 pkg syscall (darwin-amd64-cgo), type Timeval struct, Usec int32
 pkg syscall (darwin-amd64-cgo), type Timeval32 struct
@@ -14737,9 +14733,9 @@ pkg syscall (freebsd-386), func BpfBuflen(int) (int, error)
 pkg syscall (freebsd-386), func BpfDatalink(int) (int, error)
 pkg syscall (freebsd-386), func BpfHeadercmpl(int) (int, error)
 pkg syscall (freebsd-386), func BpfInterface(int, string) (string, error)
-pkg syscall (freebsd-386), func BpfJump(int) *BpfInsn
+pkg syscall (freebsd-386), func BpfJump(int, int, int, int) *BpfInsn
 pkg syscall (freebsd-386), func BpfStats(int) (*BpfStat, error)
-pkg syscall (freebsd-386), func BpfStmt(int) *BpfInsn
+pkg syscall (freebsd-386), func BpfStmt(int, int) *BpfInsn
 pkg syscall (freebsd-386), func BpfTimeout(int) (*Timeval, error)
 pkg syscall (freebsd-386), func CheckBpfVersion(int) error
 pkg syscall (freebsd-386), func Chflags(string, int) error
@@ -14764,7 +14760,7 @@ pkg syscall (freebsd-386), func Fstatfs(int, *Statfs_t) error
 pkg syscall (freebsd-386), func Fsync(int) error
 pkg syscall (freebsd-386), func Ftruncate(int, int64) error
 pkg syscall (freebsd-386), func Futimes(int, []Timeval) error
-pkg syscall (freebsd-386), func Getdirentries(int, []byte, *uintptr) (int, error)
+pkg syscall (freebsd-386), func Getdirentries(int, []uint8, *uintptr) (int, error)
 pkg syscall (freebsd-386), func Getdtablesize() int
 pkg syscall (freebsd-386), func Getfsstat([]Statfs_t, int) (int, error)
 pkg syscall (freebsd-386), func Getpeername(int) (Sockaddr, error)
@@ -14775,58 +14771,56 @@ pkg syscall (freebsd-386), func Getrlimit(int, *Rlimit) error
 pkg syscall (freebsd-386), func Getrusage(int, *Rusage) error
 pkg syscall (freebsd-386), func Getsid(int) (int, error)
 pkg syscall (freebsd-386), func Getsockname(int) (Sockaddr, error)
-pkg syscall (freebsd-386), func GetsockoptByte(int) (byte, error)
-pkg syscall (freebsd-386), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (freebsd-386), func GetsockoptIPMreqn(int) (*IPMreqn, error)
-pkg syscall (freebsd-386), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (freebsd-386), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (freebsd-386), func GetsockoptInt(int) (int, error)
+pkg syscall (freebsd-386), func GetsockoptByte(int, int, int) (uint8, error)
+pkg syscall (freebsd-386), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (freebsd-386), func GetsockoptIPMreqn(int, int, int) (*IPMreqn, error)
+pkg syscall (freebsd-386), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (freebsd-386), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (freebsd-386), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (freebsd-386), func Issetugid() bool
-pkg syscall (freebsd-386), func Kevent(int, []Kevent_t, *Timespec) (int, error)
+pkg syscall (freebsd-386), func Kevent(int, []Kevent_t, []Kevent_t, *Timespec) (int, error)
 pkg syscall (freebsd-386), func Kill(int, Signal) error
 pkg syscall (freebsd-386), func Kqueue() (int, error)
-pkg syscall (freebsd-386), func Link(string, string) error
 pkg syscall (freebsd-386), func Listen(int, int) error
 pkg syscall (freebsd-386), func Lstat(string, *Stat_t) error
 pkg syscall (freebsd-386), func Mkfifo(string, uint32) error
 pkg syscall (freebsd-386), func Mknod(string, uint32, int) error
-pkg syscall (freebsd-386), func Mmap(int, int64, int, int, int) ([]byte, error)
-pkg syscall (freebsd-386), func Munmap([]byte) error
+pkg syscall (freebsd-386), func Mmap(int, int64, int, int, int) ([]uint8, error)
+pkg syscall (freebsd-386), func Munmap([]uint8) error
 pkg syscall (freebsd-386), func Nanosleep(*Timespec, *Timespec) error
 pkg syscall (freebsd-386), func NsecToTimespec(int64) Timespec
 pkg syscall (freebsd-386), func Open(string, int, uint32) (int, error)
-pkg syscall (freebsd-386), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (freebsd-386), func ParseRoutingMessage([]byte) ([]RoutingMessage, error)
+pkg syscall (freebsd-386), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (freebsd-386), func ParseRoutingMessage([]uint8) ([]RoutingMessage, error)
 pkg syscall (freebsd-386), func ParseRoutingSockaddr(RoutingMessage) ([]Sockaddr, error)
-pkg syscall (freebsd-386), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (freebsd-386), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (freebsd-386), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (freebsd-386), func Pathconf(string, int) (int, error)
 pkg syscall (freebsd-386), func Pipe([]int) error
-pkg syscall (freebsd-386), func Pread(int, []byte, int64) (int, error)
-pkg syscall (freebsd-386), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (freebsd-386), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (freebsd-386), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (freebsd-386), func Read(int, []byte) (int, error)
-pkg syscall (freebsd-386), func ReadDirent(int, []byte) (int, error)
-pkg syscall (freebsd-386), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (freebsd-386), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (freebsd-386), func Rename(string, string) error
+pkg syscall (freebsd-386), func Pread(int, []uint8, int64) (int, error)
+pkg syscall (freebsd-386), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (freebsd-386), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (freebsd-386), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (freebsd-386), func Read(int, []uint8) (int, error)
+pkg syscall (freebsd-386), func ReadDirent(int, []uint8) (int, error)
+pkg syscall (freebsd-386), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (freebsd-386), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (freebsd-386), func Revoke(string) error
-pkg syscall (freebsd-386), func RouteRIB(int) ([]byte, error)
+pkg syscall (freebsd-386), func RouteRIB(int, int) ([]uint8, error)
 pkg syscall (freebsd-386), func Seek(int, int64, int) (int64, error)
 pkg syscall (freebsd-386), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) error
 pkg syscall (freebsd-386), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (freebsd-386), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (freebsd-386), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (freebsd-386), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (freebsd-386), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (freebsd-386), func SetBpf(int, []BpfInsn) error
-pkg syscall (freebsd-386), func SetBpfBuflen(int) (int, error)
-pkg syscall (freebsd-386), func SetBpfDatalink(int) (int, error)
-pkg syscall (freebsd-386), func SetBpfHeadercmpl(int) error
-pkg syscall (freebsd-386), func SetBpfImmediate(int) error
+pkg syscall (freebsd-386), func SetBpfBuflen(int, int) (int, error)
+pkg syscall (freebsd-386), func SetBpfDatalink(int, int) (int, error)
+pkg syscall (freebsd-386), func SetBpfHeadercmpl(int, int) error
+pkg syscall (freebsd-386), func SetBpfImmediate(int, int) error
 pkg syscall (freebsd-386), func SetBpfInterface(int, string) error
-pkg syscall (freebsd-386), func SetBpfPromisc(int) error
+pkg syscall (freebsd-386), func SetBpfPromisc(int, int) error
 pkg syscall (freebsd-386), func SetBpfTimeout(int, *Timeval) error
-pkg syscall (freebsd-386), func SetKevent(*Kevent_t, int)
+pkg syscall (freebsd-386), func SetKevent(*Kevent_t, int, int, int)
 pkg syscall (freebsd-386), func SetNonblock(int, bool) error
 pkg syscall (freebsd-386), func Setegid(int) error
 pkg syscall (freebsd-386), func Seteuid(int) error
@@ -14839,26 +14833,27 @@ pkg syscall (freebsd-386), func Setregid(int, int) error
 pkg syscall (freebsd-386), func Setreuid(int, int) error
 pkg syscall (freebsd-386), func Setrlimit(int, *Rlimit) error
 pkg syscall (freebsd-386), func Setsid() (int, error)
-pkg syscall (freebsd-386), func SetsockoptByte(int, byte) error
-pkg syscall (freebsd-386), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (freebsd-386), func SetsockoptIPMreqn(int, *IPMreqn) error
-pkg syscall (freebsd-386), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (freebsd-386), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (freebsd-386), func SetsockoptInt(int, int) error
-pkg syscall (freebsd-386), func SetsockoptLinger(int, *Linger) error
-pkg syscall (freebsd-386), func SetsockoptString(int, string) error
-pkg syscall (freebsd-386), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (freebsd-386), func SetsockoptByte(int, int, int, uint8) error
+pkg syscall (freebsd-386), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (freebsd-386), func SetsockoptIPMreqn(int, int, int, *IPMreqn) error
+pkg syscall (freebsd-386), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (freebsd-386), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (freebsd-386), func SetsockoptInt(int, int, int, int) error
+pkg syscall (freebsd-386), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (freebsd-386), func SetsockoptString(int, int, int, string) error
+pkg syscall (freebsd-386), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (freebsd-386), func Settimeofday(*Timeval) error
 pkg syscall (freebsd-386), func Setuid(int) error
 pkg syscall (freebsd-386), func Shutdown(int, int) error
-pkg syscall (freebsd-386), func Socket(int) (int, error)
-pkg syscall (freebsd-386), func Socketpair(int) ([2]int, error)
+pkg syscall (freebsd-386), func Socket(int, int, int) (int, error)
+pkg syscall (freebsd-386), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (freebsd-386), func Stat(string, *Stat_t) error
 pkg syscall (freebsd-386), func Statfs(string, *Statfs_t) error
-pkg syscall (freebsd-386), func StringSlicePtr([]string) []*byte
-pkg syscall (freebsd-386), func Symlink(string, string) error
+pkg syscall (freebsd-386), func StringSlicePtr([]string) []*uint8
 pkg syscall (freebsd-386), func Sync() error
-pkg syscall (freebsd-386), func Syscall9(uintptr) (uintptr, Errno)
+pkg syscall (freebsd-386), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (freebsd-386), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (freebsd-386), func Syscall9(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (freebsd-386), func Sysctl(string) (string, error)
 pkg syscall (freebsd-386), func SysctlUint32(string) (uint32, error)
 pkg syscall (freebsd-386), func TimespecToNsec(Timespec) int64
@@ -14866,10 +14861,10 @@ pkg syscall (freebsd-386), func TimevalToNsec(Timeval) int64
 pkg syscall (freebsd-386), func Truncate(string, int64) error
 pkg syscall (freebsd-386), func Umask(int) int
 pkg syscall (freebsd-386), func Undelete(string) error
-pkg syscall (freebsd-386), func UnixRights(...int) []byte
+pkg syscall (freebsd-386), func UnixRights(...int) []uint8
 pkg syscall (freebsd-386), func Unmount(string, int) error
 pkg syscall (freebsd-386), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (freebsd-386), func Write(int, []byte) (int, error)
+pkg syscall (freebsd-386), func Write(int, []uint8) (int, error)
 pkg syscall (freebsd-386), method (*Cmsghdr) SetLen(int)
 pkg syscall (freebsd-386), method (*Iovec) SetLen(int)
 pkg syscall (freebsd-386), method (*Msghdr) SetControllen(int)
@@ -14877,7 +14872,7 @@ pkg syscall (freebsd-386), type BpfHdr struct
 pkg syscall (freebsd-386), type BpfHdr struct, Caplen uint32
 pkg syscall (freebsd-386), type BpfHdr struct, Datalen uint32
 pkg syscall (freebsd-386), type BpfHdr struct, Hdrlen uint16
-pkg syscall (freebsd-386), type BpfHdr struct, Pad_cgo_0 [2]byte
+pkg syscall (freebsd-386), type BpfHdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (freebsd-386), type BpfHdr struct, Tstamp Timeval
 pkg syscall (freebsd-386), type BpfInsn struct
 pkg syscall (freebsd-386), type BpfInsn struct, Code uint16
@@ -14894,8 +14889,8 @@ pkg syscall (freebsd-386), type BpfVersion struct
 pkg syscall (freebsd-386), type BpfVersion struct, Major uint16
 pkg syscall (freebsd-386), type BpfVersion struct, Minor uint16
 pkg syscall (freebsd-386), type BpfZbuf struct
-pkg syscall (freebsd-386), type BpfZbuf struct, Bufa *byte
-pkg syscall (freebsd-386), type BpfZbuf struct, Bufb *byte
+pkg syscall (freebsd-386), type BpfZbuf struct, Bufa *uint8
+pkg syscall (freebsd-386), type BpfZbuf struct, Bufb *uint8
 pkg syscall (freebsd-386), type BpfZbuf struct, Buflen uint32
 pkg syscall (freebsd-386), type BpfZbufHeader struct
 pkg syscall (freebsd-386), type BpfZbufHeader struct, Kernel_gen uint32
@@ -14928,9 +14923,9 @@ pkg syscall (freebsd-386), type Flock_t struct, Whence int16
 pkg syscall (freebsd-386), type Fsid struct
 pkg syscall (freebsd-386), type Fsid struct, Val [2]int32
 pkg syscall (freebsd-386), type IPMreqn struct
-pkg syscall (freebsd-386), type IPMreqn struct, Address [4]byte
+pkg syscall (freebsd-386), type IPMreqn struct, Address [4]uint8
 pkg syscall (freebsd-386), type IPMreqn struct, Ifindex int32
-pkg syscall (freebsd-386), type IPMreqn struct, Multiaddr [4]byte
+pkg syscall (freebsd-386), type IPMreqn struct, Multiaddr [4]uint8
 pkg syscall (freebsd-386), type IfData struct
 pkg syscall (freebsd-386), type IfData struct, Addrlen uint8
 pkg syscall (freebsd-386), type IfData struct, Baudrate uint32
@@ -14963,7 +14958,7 @@ pkg syscall (freebsd-386), type IfMsghdr struct, Data IfData
 pkg syscall (freebsd-386), type IfMsghdr struct, Flags int32
 pkg syscall (freebsd-386), type IfMsghdr struct, Index uint16
 pkg syscall (freebsd-386), type IfMsghdr struct, Msglen uint16
-pkg syscall (freebsd-386), type IfMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (freebsd-386), type IfMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (freebsd-386), type IfMsghdr struct, Type uint8
 pkg syscall (freebsd-386), type IfMsghdr struct, Version uint8
 pkg syscall (freebsd-386), type IfaMsghdr struct
@@ -14972,7 +14967,7 @@ pkg syscall (freebsd-386), type IfaMsghdr struct, Flags int32
 pkg syscall (freebsd-386), type IfaMsghdr struct, Index uint16
 pkg syscall (freebsd-386), type IfaMsghdr struct, Metric int32
 pkg syscall (freebsd-386), type IfaMsghdr struct, Msglen uint16
-pkg syscall (freebsd-386), type IfaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (freebsd-386), type IfaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (freebsd-386), type IfaMsghdr struct, Type uint8
 pkg syscall (freebsd-386), type IfaMsghdr struct, Version uint8
 pkg syscall (freebsd-386), type IfmaMsghdr struct
@@ -14980,23 +14975,23 @@ pkg syscall (freebsd-386), type IfmaMsghdr struct, Addrs int32
 pkg syscall (freebsd-386), type IfmaMsghdr struct, Flags int32
 pkg syscall (freebsd-386), type IfmaMsghdr struct, Index uint16
 pkg syscall (freebsd-386), type IfmaMsghdr struct, Msglen uint16
-pkg syscall (freebsd-386), type IfmaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (freebsd-386), type IfmaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (freebsd-386), type IfmaMsghdr struct, Type uint8
 pkg syscall (freebsd-386), type IfmaMsghdr struct, Version uint8
 pkg syscall (freebsd-386), type Inet6Pktinfo struct
-pkg syscall (freebsd-386), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (freebsd-386), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (freebsd-386), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (freebsd-386), type InterfaceAddrMessage struct
-pkg syscall (freebsd-386), type InterfaceAddrMessage struct, Data []byte
+pkg syscall (freebsd-386), type InterfaceAddrMessage struct, Data []uint8
 pkg syscall (freebsd-386), type InterfaceAddrMessage struct, Header IfaMsghdr
 pkg syscall (freebsd-386), type InterfaceMessage struct
-pkg syscall (freebsd-386), type InterfaceMessage struct, Data []byte
+pkg syscall (freebsd-386), type InterfaceMessage struct, Data []uint8
 pkg syscall (freebsd-386), type InterfaceMessage struct, Header IfMsghdr
 pkg syscall (freebsd-386), type InterfaceMulticastAddrMessage struct
-pkg syscall (freebsd-386), type InterfaceMulticastAddrMessage struct, Data []byte
+pkg syscall (freebsd-386), type InterfaceMulticastAddrMessage struct, Data []uint8
 pkg syscall (freebsd-386), type InterfaceMulticastAddrMessage struct, Header IfmaMsghdr
 pkg syscall (freebsd-386), type Iovec struct
-pkg syscall (freebsd-386), type Iovec struct, Base *byte
+pkg syscall (freebsd-386), type Iovec struct, Base *uint8
 pkg syscall (freebsd-386), type Iovec struct, Len uint32
 pkg syscall (freebsd-386), type Kevent_t struct
 pkg syscall (freebsd-386), type Kevent_t struct, Data int32
@@ -15004,14 +14999,14 @@ pkg syscall (freebsd-386), type Kevent_t struct, Fflags uint32
 pkg syscall (freebsd-386), type Kevent_t struct, Filter int16
 pkg syscall (freebsd-386), type Kevent_t struct, Flags uint16
 pkg syscall (freebsd-386), type Kevent_t struct, Ident uint32
-pkg syscall (freebsd-386), type Kevent_t struct, Udata *byte
+pkg syscall (freebsd-386), type Kevent_t struct, Udata *uint8
 pkg syscall (freebsd-386), type Msghdr struct
-pkg syscall (freebsd-386), type Msghdr struct, Control *byte
+pkg syscall (freebsd-386), type Msghdr struct, Control *uint8
 pkg syscall (freebsd-386), type Msghdr struct, Controllen uint32
 pkg syscall (freebsd-386), type Msghdr struct, Flags int32
 pkg syscall (freebsd-386), type Msghdr struct, Iov *Iovec
 pkg syscall (freebsd-386), type Msghdr struct, Iovlen int32
-pkg syscall (freebsd-386), type Msghdr struct, Name *byte
+pkg syscall (freebsd-386), type Msghdr struct, Name *uint8
 pkg syscall (freebsd-386), type Msghdr struct, Namelen uint32
 pkg syscall (freebsd-386), type RawSockaddr struct, Data [14]int8
 pkg syscall (freebsd-386), type RawSockaddr struct, Family uint8
@@ -15030,7 +15025,7 @@ pkg syscall (freebsd-386), type RawSockaddrInet4 struct, Family uint8
 pkg syscall (freebsd-386), type RawSockaddrInet4 struct, Len uint8
 pkg syscall (freebsd-386), type RawSockaddrInet4 struct, Zero [8]int8
 pkg syscall (freebsd-386), type RawSockaddrInet6 struct
-pkg syscall (freebsd-386), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (freebsd-386), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (freebsd-386), type RawSockaddrInet6 struct, Family uint8
 pkg syscall (freebsd-386), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (freebsd-386), type RawSockaddrInet6 struct, Len uint8
@@ -15044,9 +15039,9 @@ pkg syscall (freebsd-386), type Rlimit struct
 pkg syscall (freebsd-386), type Rlimit struct, Cur int64
 pkg syscall (freebsd-386), type Rlimit struct, Max int64
 pkg syscall (freebsd-386), type RouteMessage struct
-pkg syscall (freebsd-386), type RouteMessage struct, Data []byte
+pkg syscall (freebsd-386), type RouteMessage struct, Data []uint8
 pkg syscall (freebsd-386), type RouteMessage struct, Header RtMsghdr
-pkg syscall (freebsd-386), type RoutingMessage interface {}
+pkg syscall (freebsd-386), type RoutingMessage interface, unexported methods
 pkg syscall (freebsd-386), type RtMetrics struct
 pkg syscall (freebsd-386), type RtMetrics struct, Expire uint32
 pkg syscall (freebsd-386), type RtMetrics struct, Filler [3]uint32
@@ -15068,7 +15063,7 @@ pkg syscall (freebsd-386), type RtMsghdr struct, Fmask int32
 pkg syscall (freebsd-386), type RtMsghdr struct, Index uint16
 pkg syscall (freebsd-386), type RtMsghdr struct, Inits uint32
 pkg syscall (freebsd-386), type RtMsghdr struct, Msglen uint16
-pkg syscall (freebsd-386), type RtMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (freebsd-386), type RtMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (freebsd-386), type RtMsghdr struct, Pid int32
 pkg syscall (freebsd-386), type RtMsghdr struct, Rmx RtMetrics
 pkg syscall (freebsd-386), type RtMsghdr struct, Seq int32
@@ -15100,7 +15095,7 @@ pkg syscall (freebsd-386), type SockaddrDatalink struct, Nlen uint8
 pkg syscall (freebsd-386), type SockaddrDatalink struct, Slen uint8
 pkg syscall (freebsd-386), type SockaddrDatalink struct, Type uint8
 pkg syscall (freebsd-386), type SocketControlMessage struct
-pkg syscall (freebsd-386), type SocketControlMessage struct, Data []byte
+pkg syscall (freebsd-386), type SocketControlMessage struct, Data []uint8
 pkg syscall (freebsd-386), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (freebsd-386), type Stat_t struct
 pkg syscall (freebsd-386), type Stat_t struct, Atimespec Timespec
@@ -15117,7 +15112,7 @@ pkg syscall (freebsd-386), type Stat_t struct, Lspare int32
 pkg syscall (freebsd-386), type Stat_t struct, Mode uint16
 pkg syscall (freebsd-386), type Stat_t struct, Mtimespec Timespec
 pkg syscall (freebsd-386), type Stat_t struct, Nlink uint16
-pkg syscall (freebsd-386), type Stat_t struct, Pad_cgo_0 [8]byte
+pkg syscall (freebsd-386), type Stat_t struct, Pad_cgo_0 [8]uint8
 pkg syscall (freebsd-386), type Stat_t struct, Rdev uint32
 pkg syscall (freebsd-386), type Stat_t struct, Size int64
 pkg syscall (freebsd-386), type Stat_t struct, Uid uint32
@@ -16710,9 +16705,9 @@ pkg syscall (freebsd-amd64), func BpfBuflen(int) (int, error)
 pkg syscall (freebsd-amd64), func BpfDatalink(int) (int, error)
 pkg syscall (freebsd-amd64), func BpfHeadercmpl(int) (int, error)
 pkg syscall (freebsd-amd64), func BpfInterface(int, string) (string, error)
-pkg syscall (freebsd-amd64), func BpfJump(int) *BpfInsn
+pkg syscall (freebsd-amd64), func BpfJump(int, int, int, int) *BpfInsn
 pkg syscall (freebsd-amd64), func BpfStats(int) (*BpfStat, error)
-pkg syscall (freebsd-amd64), func BpfStmt(int) *BpfInsn
+pkg syscall (freebsd-amd64), func BpfStmt(int, int) *BpfInsn
 pkg syscall (freebsd-amd64), func BpfTimeout(int) (*Timeval, error)
 pkg syscall (freebsd-amd64), func CheckBpfVersion(int) error
 pkg syscall (freebsd-amd64), func Chflags(string, int) error
@@ -16737,7 +16732,7 @@ pkg syscall (freebsd-amd64), func Fstatfs(int, *Statfs_t) error
 pkg syscall (freebsd-amd64), func Fsync(int) error
 pkg syscall (freebsd-amd64), func Ftruncate(int, int64) error
 pkg syscall (freebsd-amd64), func Futimes(int, []Timeval) error
-pkg syscall (freebsd-amd64), func Getdirentries(int, []byte, *uintptr) (int, error)
+pkg syscall (freebsd-amd64), func Getdirentries(int, []uint8, *uintptr) (int, error)
 pkg syscall (freebsd-amd64), func Getdtablesize() int
 pkg syscall (freebsd-amd64), func Getfsstat([]Statfs_t, int) (int, error)
 pkg syscall (freebsd-amd64), func Getpeername(int) (Sockaddr, error)
@@ -16748,58 +16743,56 @@ pkg syscall (freebsd-amd64), func Getrlimit(int, *Rlimit) error
 pkg syscall (freebsd-amd64), func Getrusage(int, *Rusage) error
 pkg syscall (freebsd-amd64), func Getsid(int) (int, error)
 pkg syscall (freebsd-amd64), func Getsockname(int) (Sockaddr, error)
-pkg syscall (freebsd-amd64), func GetsockoptByte(int) (byte, error)
-pkg syscall (freebsd-amd64), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (freebsd-amd64), func GetsockoptIPMreqn(int) (*IPMreqn, error)
-pkg syscall (freebsd-amd64), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (freebsd-amd64), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (freebsd-amd64), func GetsockoptInt(int) (int, error)
+pkg syscall (freebsd-amd64), func GetsockoptByte(int, int, int) (uint8, error)
+pkg syscall (freebsd-amd64), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (freebsd-amd64), func GetsockoptIPMreqn(int, int, int) (*IPMreqn, error)
+pkg syscall (freebsd-amd64), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (freebsd-amd64), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (freebsd-amd64), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (freebsd-amd64), func Issetugid() bool
-pkg syscall (freebsd-amd64), func Kevent(int, []Kevent_t, *Timespec) (int, error)
+pkg syscall (freebsd-amd64), func Kevent(int, []Kevent_t, []Kevent_t, *Timespec) (int, error)
 pkg syscall (freebsd-amd64), func Kill(int, Signal) error
 pkg syscall (freebsd-amd64), func Kqueue() (int, error)
-pkg syscall (freebsd-amd64), func Link(string, string) error
 pkg syscall (freebsd-amd64), func Listen(int, int) error
 pkg syscall (freebsd-amd64), func Lstat(string, *Stat_t) error
 pkg syscall (freebsd-amd64), func Mkfifo(string, uint32) error
 pkg syscall (freebsd-amd64), func Mknod(string, uint32, int) error
-pkg syscall (freebsd-amd64), func Mmap(int, int64, int, int, int) ([]byte, error)
-pkg syscall (freebsd-amd64), func Munmap([]byte) error
+pkg syscall (freebsd-amd64), func Mmap(int, int64, int, int, int) ([]uint8, error)
+pkg syscall (freebsd-amd64), func Munmap([]uint8) error
 pkg syscall (freebsd-amd64), func Nanosleep(*Timespec, *Timespec) error
 pkg syscall (freebsd-amd64), func NsecToTimespec(int64) Timespec
 pkg syscall (freebsd-amd64), func Open(string, int, uint32) (int, error)
-pkg syscall (freebsd-amd64), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (freebsd-amd64), func ParseRoutingMessage([]byte) ([]RoutingMessage, error)
+pkg syscall (freebsd-amd64), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (freebsd-amd64), func ParseRoutingMessage([]uint8) ([]RoutingMessage, error)
 pkg syscall (freebsd-amd64), func ParseRoutingSockaddr(RoutingMessage) ([]Sockaddr, error)
-pkg syscall (freebsd-amd64), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (freebsd-amd64), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (freebsd-amd64), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (freebsd-amd64), func Pathconf(string, int) (int, error)
 pkg syscall (freebsd-amd64), func Pipe([]int) error
-pkg syscall (freebsd-amd64), func Pread(int, []byte, int64) (int, error)
-pkg syscall (freebsd-amd64), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (freebsd-amd64), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (freebsd-amd64), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (freebsd-amd64), func Read(int, []byte) (int, error)
-pkg syscall (freebsd-amd64), func ReadDirent(int, []byte) (int, error)
-pkg syscall (freebsd-amd64), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (freebsd-amd64), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (freebsd-amd64), func Rename(string, string) error
+pkg syscall (freebsd-amd64), func Pread(int, []uint8, int64) (int, error)
+pkg syscall (freebsd-amd64), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (freebsd-amd64), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (freebsd-amd64), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (freebsd-amd64), func Read(int, []uint8) (int, error)
+pkg syscall (freebsd-amd64), func ReadDirent(int, []uint8) (int, error)
+pkg syscall (freebsd-amd64), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (freebsd-amd64), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (freebsd-amd64), func Revoke(string) error
-pkg syscall (freebsd-amd64), func RouteRIB(int) ([]byte, error)
+pkg syscall (freebsd-amd64), func RouteRIB(int, int) ([]uint8, error)
 pkg syscall (freebsd-amd64), func Seek(int, int64, int) (int64, error)
 pkg syscall (freebsd-amd64), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) error
 pkg syscall (freebsd-amd64), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (freebsd-amd64), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (freebsd-amd64), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (freebsd-amd64), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (freebsd-amd64), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (freebsd-amd64), func SetBpf(int, []BpfInsn) error
-pkg syscall (freebsd-amd64), func SetBpfBuflen(int) (int, error)
-pkg syscall (freebsd-amd64), func SetBpfDatalink(int) (int, error)
-pkg syscall (freebsd-amd64), func SetBpfHeadercmpl(int) error
-pkg syscall (freebsd-amd64), func SetBpfImmediate(int) error
+pkg syscall (freebsd-amd64), func SetBpfBuflen(int, int) (int, error)
+pkg syscall (freebsd-amd64), func SetBpfDatalink(int, int) (int, error)
+pkg syscall (freebsd-amd64), func SetBpfHeadercmpl(int, int) error
+pkg syscall (freebsd-amd64), func SetBpfImmediate(int, int) error
 pkg syscall (freebsd-amd64), func SetBpfInterface(int, string) error
-pkg syscall (freebsd-amd64), func SetBpfPromisc(int) error
+pkg syscall (freebsd-amd64), func SetBpfPromisc(int, int) error
 pkg syscall (freebsd-amd64), func SetBpfTimeout(int, *Timeval) error
-pkg syscall (freebsd-amd64), func SetKevent(*Kevent_t, int)
+pkg syscall (freebsd-amd64), func SetKevent(*Kevent_t, int, int, int)
 pkg syscall (freebsd-amd64), func SetNonblock(int, bool) error
 pkg syscall (freebsd-amd64), func Setegid(int) error
 pkg syscall (freebsd-amd64), func Seteuid(int) error
@@ -16812,25 +16805,26 @@ pkg syscall (freebsd-amd64), func Setregid(int, int) error
 pkg syscall (freebsd-amd64), func Setreuid(int, int) error
 pkg syscall (freebsd-amd64), func Setrlimit(int, *Rlimit) error
 pkg syscall (freebsd-amd64), func Setsid() (int, error)
-pkg syscall (freebsd-amd64), func SetsockoptByte(int, byte) error
-pkg syscall (freebsd-amd64), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (freebsd-amd64), func SetsockoptIPMreqn(int, *IPMreqn) error
-pkg syscall (freebsd-amd64), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (freebsd-amd64), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (freebsd-amd64), func SetsockoptInt(int, int) error
-pkg syscall (freebsd-amd64), func SetsockoptLinger(int, *Linger) error
-pkg syscall (freebsd-amd64), func SetsockoptString(int, string) error
-pkg syscall (freebsd-amd64), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (freebsd-amd64), func SetsockoptByte(int, int, int, uint8) error
+pkg syscall (freebsd-amd64), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (freebsd-amd64), func SetsockoptIPMreqn(int, int, int, *IPMreqn) error
+pkg syscall (freebsd-amd64), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (freebsd-amd64), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (freebsd-amd64), func SetsockoptInt(int, int, int, int) error
+pkg syscall (freebsd-amd64), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (freebsd-amd64), func SetsockoptString(int, int, int, string) error
+pkg syscall (freebsd-amd64), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (freebsd-amd64), func Settimeofday(*Timeval) error
 pkg syscall (freebsd-amd64), func Setuid(int) error
 pkg syscall (freebsd-amd64), func Shutdown(int, int) error
-pkg syscall (freebsd-amd64), func Socket(int) (int, error)
-pkg syscall (freebsd-amd64), func Socketpair(int) ([2]int, error)
+pkg syscall (freebsd-amd64), func Socket(int, int, int) (int, error)
+pkg syscall (freebsd-amd64), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (freebsd-amd64), func Stat(string, *Stat_t) error
 pkg syscall (freebsd-amd64), func Statfs(string, *Statfs_t) error
-pkg syscall (freebsd-amd64), func StringSlicePtr([]string) []*byte
-pkg syscall (freebsd-amd64), func Symlink(string, string) error
+pkg syscall (freebsd-amd64), func StringSlicePtr([]string) []*uint8
 pkg syscall (freebsd-amd64), func Sync() error
+pkg syscall (freebsd-amd64), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (freebsd-amd64), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (freebsd-amd64), func Sysctl(string) (string, error)
 pkg syscall (freebsd-amd64), func SysctlUint32(string) (uint32, error)
 pkg syscall (freebsd-amd64), func TimespecToNsec(Timespec) int64
@@ -16838,10 +16832,10 @@ pkg syscall (freebsd-amd64), func TimevalToNsec(Timeval) int64
 pkg syscall (freebsd-amd64), func Truncate(string, int64) error
 pkg syscall (freebsd-amd64), func Umask(int) int
 pkg syscall (freebsd-amd64), func Undelete(string) error
-pkg syscall (freebsd-amd64), func UnixRights(...int) []byte
+pkg syscall (freebsd-amd64), func UnixRights(...int) []uint8
 pkg syscall (freebsd-amd64), func Unmount(string, int) error
 pkg syscall (freebsd-amd64), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (freebsd-amd64), func Write(int, []byte) (int, error)
+pkg syscall (freebsd-amd64), func Write(int, []uint8) (int, error)
 pkg syscall (freebsd-amd64), method (*Cmsghdr) SetLen(int)
 pkg syscall (freebsd-amd64), method (*Iovec) SetLen(int)
 pkg syscall (freebsd-amd64), method (*Msghdr) SetControllen(int)
@@ -16849,7 +16843,7 @@ pkg syscall (freebsd-amd64), type BpfHdr struct
 pkg syscall (freebsd-amd64), type BpfHdr struct, Caplen uint32
 pkg syscall (freebsd-amd64), type BpfHdr struct, Datalen uint32
 pkg syscall (freebsd-amd64), type BpfHdr struct, Hdrlen uint16
-pkg syscall (freebsd-amd64), type BpfHdr struct, Pad_cgo_0 [6]byte
+pkg syscall (freebsd-amd64), type BpfHdr struct, Pad_cgo_0 [6]uint8
 pkg syscall (freebsd-amd64), type BpfHdr struct, Tstamp Timeval
 pkg syscall (freebsd-amd64), type BpfInsn struct
 pkg syscall (freebsd-amd64), type BpfInsn struct, Code uint16
@@ -16859,7 +16853,7 @@ pkg syscall (freebsd-amd64), type BpfInsn struct, K uint32
 pkg syscall (freebsd-amd64), type BpfProgram struct
 pkg syscall (freebsd-amd64), type BpfProgram struct, Insns *BpfInsn
 pkg syscall (freebsd-amd64), type BpfProgram struct, Len uint32
-pkg syscall (freebsd-amd64), type BpfProgram struct, Pad_cgo_0 [4]byte
+pkg syscall (freebsd-amd64), type BpfProgram struct, Pad_cgo_0 [4]uint8
 pkg syscall (freebsd-amd64), type BpfStat struct
 pkg syscall (freebsd-amd64), type BpfStat struct, Drop uint32
 pkg syscall (freebsd-amd64), type BpfStat struct, Recv uint32
@@ -16867,8 +16861,8 @@ pkg syscall (freebsd-amd64), type BpfVersion struct
 pkg syscall (freebsd-amd64), type BpfVersion struct, Major uint16
 pkg syscall (freebsd-amd64), type BpfVersion struct, Minor uint16
 pkg syscall (freebsd-amd64), type BpfZbuf struct
-pkg syscall (freebsd-amd64), type BpfZbuf struct, Bufa *byte
-pkg syscall (freebsd-amd64), type BpfZbuf struct, Bufb *byte
+pkg syscall (freebsd-amd64), type BpfZbuf struct, Bufa *uint8
+pkg syscall (freebsd-amd64), type BpfZbuf struct, Bufb *uint8
 pkg syscall (freebsd-amd64), type BpfZbuf struct, Buflen uint64
 pkg syscall (freebsd-amd64), type BpfZbufHeader struct
 pkg syscall (freebsd-amd64), type BpfZbufHeader struct, Kernel_gen uint32
@@ -16893,7 +16887,7 @@ pkg syscall (freebsd-amd64), type FdSet struct
 pkg syscall (freebsd-amd64), type FdSet struct, X__fds_bits [16]uint64
 pkg syscall (freebsd-amd64), type Flock_t struct
 pkg syscall (freebsd-amd64), type Flock_t struct, Len int64
-pkg syscall (freebsd-amd64), type Flock_t struct, Pad_cgo_0 [4]byte
+pkg syscall (freebsd-amd64), type Flock_t struct, Pad_cgo_0 [4]uint8
 pkg syscall (freebsd-amd64), type Flock_t struct, Pid int32
 pkg syscall (freebsd-amd64), type Flock_t struct, Start int64
 pkg syscall (freebsd-amd64), type Flock_t struct, Sysid int32
@@ -16902,9 +16896,9 @@ pkg syscall (freebsd-amd64), type Flock_t struct, Whence int16
 pkg syscall (freebsd-amd64), type Fsid struct
 pkg syscall (freebsd-amd64), type Fsid struct, Val [2]int32
 pkg syscall (freebsd-amd64), type IPMreqn struct
-pkg syscall (freebsd-amd64), type IPMreqn struct, Address [4]byte
+pkg syscall (freebsd-amd64), type IPMreqn struct, Address [4]uint8
 pkg syscall (freebsd-amd64), type IPMreqn struct, Ifindex int32
-pkg syscall (freebsd-amd64), type IPMreqn struct, Multiaddr [4]byte
+pkg syscall (freebsd-amd64), type IPMreqn struct, Multiaddr [4]uint8
 pkg syscall (freebsd-amd64), type IfData struct
 pkg syscall (freebsd-amd64), type IfData struct, Addrlen uint8
 pkg syscall (freebsd-amd64), type IfData struct, Baudrate uint64
@@ -16937,7 +16931,7 @@ pkg syscall (freebsd-amd64), type IfMsghdr struct, Data IfData
 pkg syscall (freebsd-amd64), type IfMsghdr struct, Flags int32
 pkg syscall (freebsd-amd64), type IfMsghdr struct, Index uint16
 pkg syscall (freebsd-amd64), type IfMsghdr struct, Msglen uint16
-pkg syscall (freebsd-amd64), type IfMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (freebsd-amd64), type IfMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (freebsd-amd64), type IfMsghdr struct, Type uint8
 pkg syscall (freebsd-amd64), type IfMsghdr struct, Version uint8
 pkg syscall (freebsd-amd64), type IfaMsghdr struct
@@ -16946,7 +16940,7 @@ pkg syscall (freebsd-amd64), type IfaMsghdr struct, Flags int32
 pkg syscall (freebsd-amd64), type IfaMsghdr struct, Index uint16
 pkg syscall (freebsd-amd64), type IfaMsghdr struct, Metric int32
 pkg syscall (freebsd-amd64), type IfaMsghdr struct, Msglen uint16
-pkg syscall (freebsd-amd64), type IfaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (freebsd-amd64), type IfaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (freebsd-amd64), type IfaMsghdr struct, Type uint8
 pkg syscall (freebsd-amd64), type IfaMsghdr struct, Version uint8
 pkg syscall (freebsd-amd64), type IfmaMsghdr struct
@@ -16954,23 +16948,23 @@ pkg syscall (freebsd-amd64), type IfmaMsghdr struct, Addrs int32
 pkg syscall (freebsd-amd64), type IfmaMsghdr struct, Flags int32
 pkg syscall (freebsd-amd64), type IfmaMsghdr struct, Index uint16
 pkg syscall (freebsd-amd64), type IfmaMsghdr struct, Msglen uint16
-pkg syscall (freebsd-amd64), type IfmaMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (freebsd-amd64), type IfmaMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (freebsd-amd64), type IfmaMsghdr struct, Type uint8
 pkg syscall (freebsd-amd64), type IfmaMsghdr struct, Version uint8
 pkg syscall (freebsd-amd64), type Inet6Pktinfo struct
-pkg syscall (freebsd-amd64), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (freebsd-amd64), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (freebsd-amd64), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (freebsd-amd64), type InterfaceAddrMessage struct
-pkg syscall (freebsd-amd64), type InterfaceAddrMessage struct, Data []byte
+pkg syscall (freebsd-amd64), type InterfaceAddrMessage struct, Data []uint8
 pkg syscall (freebsd-amd64), type InterfaceAddrMessage struct, Header IfaMsghdr
 pkg syscall (freebsd-amd64), type InterfaceMessage struct
-pkg syscall (freebsd-amd64), type InterfaceMessage struct, Data []byte
+pkg syscall (freebsd-amd64), type InterfaceMessage struct, Data []uint8
 pkg syscall (freebsd-amd64), type InterfaceMessage struct, Header IfMsghdr
 pkg syscall (freebsd-amd64), type InterfaceMulticastAddrMessage struct
-pkg syscall (freebsd-amd64), type InterfaceMulticastAddrMessage struct, Data []byte
+pkg syscall (freebsd-amd64), type InterfaceMulticastAddrMessage struct, Data []uint8
 pkg syscall (freebsd-amd64), type InterfaceMulticastAddrMessage struct, Header IfmaMsghdr
 pkg syscall (freebsd-amd64), type Iovec struct
-pkg syscall (freebsd-amd64), type Iovec struct, Base *byte
+pkg syscall (freebsd-amd64), type Iovec struct, Base *uint8
 pkg syscall (freebsd-amd64), type Iovec struct, Len uint64
 pkg syscall (freebsd-amd64), type Kevent_t struct
 pkg syscall (freebsd-amd64), type Kevent_t struct, Data int64
@@ -16978,17 +16972,17 @@ pkg syscall (freebsd-amd64), type Kevent_t struct, Fflags uint32
 pkg syscall (freebsd-amd64), type Kevent_t struct, Filter int16
 pkg syscall (freebsd-amd64), type Kevent_t struct, Flags uint16
 pkg syscall (freebsd-amd64), type Kevent_t struct, Ident uint64
-pkg syscall (freebsd-amd64), type Kevent_t struct, Udata *byte
+pkg syscall (freebsd-amd64), type Kevent_t struct, Udata *uint8
 pkg syscall (freebsd-amd64), type Msghdr struct
-pkg syscall (freebsd-amd64), type Msghdr struct, Control *byte
+pkg syscall (freebsd-amd64), type Msghdr struct, Control *uint8
 pkg syscall (freebsd-amd64), type Msghdr struct, Controllen uint32
 pkg syscall (freebsd-amd64), type Msghdr struct, Flags int32
 pkg syscall (freebsd-amd64), type Msghdr struct, Iov *Iovec
 pkg syscall (freebsd-amd64), type Msghdr struct, Iovlen int32
-pkg syscall (freebsd-amd64), type Msghdr struct, Name *byte
+pkg syscall (freebsd-amd64), type Msghdr struct, Name *uint8
 pkg syscall (freebsd-amd64), type Msghdr struct, Namelen uint32
-pkg syscall (freebsd-amd64), type Msghdr struct, Pad_cgo_0 [4]byte
-pkg syscall (freebsd-amd64), type Msghdr struct, Pad_cgo_1 [4]byte
+pkg syscall (freebsd-amd64), type Msghdr struct, Pad_cgo_0 [4]uint8
+pkg syscall (freebsd-amd64), type Msghdr struct, Pad_cgo_1 [4]uint8
 pkg syscall (freebsd-amd64), type RawSockaddr struct, Data [14]int8
 pkg syscall (freebsd-amd64), type RawSockaddr struct, Family uint8
 pkg syscall (freebsd-amd64), type RawSockaddr struct, Len uint8
@@ -17006,7 +17000,7 @@ pkg syscall (freebsd-amd64), type RawSockaddrInet4 struct, Family uint8
 pkg syscall (freebsd-amd64), type RawSockaddrInet4 struct, Len uint8
 pkg syscall (freebsd-amd64), type RawSockaddrInet4 struct, Zero [8]int8
 pkg syscall (freebsd-amd64), type RawSockaddrInet6 struct
-pkg syscall (freebsd-amd64), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (freebsd-amd64), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (freebsd-amd64), type RawSockaddrInet6 struct, Family uint8
 pkg syscall (freebsd-amd64), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (freebsd-amd64), type RawSockaddrInet6 struct, Len uint8
@@ -17020,9 +17014,9 @@ pkg syscall (freebsd-amd64), type Rlimit struct
 pkg syscall (freebsd-amd64), type Rlimit struct, Cur int64
 pkg syscall (freebsd-amd64), type Rlimit struct, Max int64
 pkg syscall (freebsd-amd64), type RouteMessage struct
-pkg syscall (freebsd-amd64), type RouteMessage struct, Data []byte
+pkg syscall (freebsd-amd64), type RouteMessage struct, Data []uint8
 pkg syscall (freebsd-amd64), type RouteMessage struct, Header RtMsghdr
-pkg syscall (freebsd-amd64), type RoutingMessage interface {}
+pkg syscall (freebsd-amd64), type RoutingMessage interface, unexported methods
 pkg syscall (freebsd-amd64), type RtMetrics struct
 pkg syscall (freebsd-amd64), type RtMetrics struct, Expire uint64
 pkg syscall (freebsd-amd64), type RtMetrics struct, Filler [3]uint64
@@ -17044,7 +17038,7 @@ pkg syscall (freebsd-amd64), type RtMsghdr struct, Fmask int32
 pkg syscall (freebsd-amd64), type RtMsghdr struct, Index uint16
 pkg syscall (freebsd-amd64), type RtMsghdr struct, Inits uint64
 pkg syscall (freebsd-amd64), type RtMsghdr struct, Msglen uint16
-pkg syscall (freebsd-amd64), type RtMsghdr struct, Pad_cgo_0 [2]byte
+pkg syscall (freebsd-amd64), type RtMsghdr struct, Pad_cgo_0 [2]uint8
 pkg syscall (freebsd-amd64), type RtMsghdr struct, Pid int32
 pkg syscall (freebsd-amd64), type RtMsghdr struct, Rmx RtMetrics
 pkg syscall (freebsd-amd64), type RtMsghdr struct, Seq int32
@@ -17076,7 +17070,7 @@ pkg syscall (freebsd-amd64), type SockaddrDatalink struct, Nlen uint8
 pkg syscall (freebsd-amd64), type SockaddrDatalink struct, Slen uint8
 pkg syscall (freebsd-amd64), type SockaddrDatalink struct, Type uint8
 pkg syscall (freebsd-amd64), type SocketControlMessage struct
-pkg syscall (freebsd-amd64), type SocketControlMessage struct, Data []byte
+pkg syscall (freebsd-amd64), type SocketControlMessage struct, Data []uint8
 pkg syscall (freebsd-amd64), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (freebsd-amd64), type Stat_t struct
 pkg syscall (freebsd-amd64), type Stat_t struct, Atimespec Timespec
@@ -18864,19 +18858,19 @@ pkg syscall (linux-386), func Fsync(int) error
 pkg syscall (linux-386), func Ftruncate(int, int64) error
 pkg syscall (linux-386), func Futimes(int, []Timeval) error
 pkg syscall (linux-386), func Futimesat(int, string, []Timeval) error
-pkg syscall (linux-386), func Getcwd([]byte) (int, error)
-pkg syscall (linux-386), func Getdents(int, []byte) (int, error)
+pkg syscall (linux-386), func Getcwd([]uint8) (int, error)
+pkg syscall (linux-386), func Getdents(int, []uint8) (int, error)
 pkg syscall (linux-386), func Getpeername(int) (Sockaddr, error)
 pkg syscall (linux-386), func Getpgid(int) (int, error)
 pkg syscall (linux-386), func Getpgrp() int
 pkg syscall (linux-386), func Getrlimit(int, *Rlimit) error
 pkg syscall (linux-386), func Getrusage(int, *Rusage) error
 pkg syscall (linux-386), func Getsockname(int) (Sockaddr, error)
-pkg syscall (linux-386), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (linux-386), func GetsockoptIPMreqn(int) (*IPMreqn, error)
-pkg syscall (linux-386), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (linux-386), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (linux-386), func GetsockoptInt(int) (int, error)
+pkg syscall (linux-386), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (linux-386), func GetsockoptIPMreqn(int, int, int) (*IPMreqn, error)
+pkg syscall (linux-386), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (linux-386), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (linux-386), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (linux-386), func Gettid() int
 pkg syscall (linux-386), func InotifyAddWatch(int, string, uint32) (int, error)
 pkg syscall (linux-386), func InotifyInit() (int, error)
@@ -18885,76 +18879,74 @@ pkg syscall (linux-386), func InotifyRmWatch(int, uint32) (int, error)
 pkg syscall (linux-386), func Ioperm(int, int, int) error
 pkg syscall (linux-386), func Iopl(int) error
 pkg syscall (linux-386), func Kill(int, Signal) error
-pkg syscall (linux-386), func Klogctl(int, []byte) (int, error)
-pkg syscall (linux-386), func Link(string, string) error
+pkg syscall (linux-386), func Klogctl(int, []uint8) (int, error)
 pkg syscall (linux-386), func Listen(int, int) error
-pkg syscall (linux-386), func LsfJump(int) *SockFilter
-pkg syscall (linux-386), func LsfSocket(int) (int, error)
-pkg syscall (linux-386), func LsfStmt(int) *SockFilter
+pkg syscall (linux-386), func LsfJump(int, int, int, int) *SockFilter
+pkg syscall (linux-386), func LsfSocket(int, int) (int, error)
+pkg syscall (linux-386), func LsfStmt(int, int) *SockFilter
 pkg syscall (linux-386), func Lstat(string, *Stat_t) error
-pkg syscall (linux-386), func Madvise([]byte, int) error
+pkg syscall (linux-386), func Madvise([]uint8, int) error
 pkg syscall (linux-386), func Mkdirat(int, string, uint32) error
 pkg syscall (linux-386), func Mkfifo(string, uint32) error
 pkg syscall (linux-386), func Mknod(string, uint32, int) error
 pkg syscall (linux-386), func Mknodat(int, string, uint32, int) error
-pkg syscall (linux-386), func Mlock([]byte) error
+pkg syscall (linux-386), func Mlock([]uint8) error
 pkg syscall (linux-386), func Mlockall(int) error
-pkg syscall (linux-386), func Mmap(int, int64, int, int, int) ([]byte, error)
+pkg syscall (linux-386), func Mmap(int, int64, int, int, int) ([]uint8, error)
 pkg syscall (linux-386), func Mount(string, string, string, uintptr, string) error
-pkg syscall (linux-386), func Mprotect([]byte, int) error
-pkg syscall (linux-386), func Munlock([]byte) error
+pkg syscall (linux-386), func Mprotect([]uint8, int) error
+pkg syscall (linux-386), func Munlock([]uint8) error
 pkg syscall (linux-386), func Munlockall() error
-pkg syscall (linux-386), func Munmap([]byte) error
+pkg syscall (linux-386), func Munmap([]uint8) error
 pkg syscall (linux-386), func Nanosleep(*Timespec, *Timespec) error
-pkg syscall (linux-386), func NetlinkRIB(int) ([]byte, error)
+pkg syscall (linux-386), func NetlinkRIB(int, int) ([]uint8, error)
 pkg syscall (linux-386), func NsecToTimespec(int64) Timespec
 pkg syscall (linux-386), func Open(string, int, uint32) (int, error)
 pkg syscall (linux-386), func Openat(int, string, int, uint32) (int, error)
-pkg syscall (linux-386), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (linux-386), func ParseNetlinkMessage([]byte) ([]NetlinkMessage, error)
+pkg syscall (linux-386), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (linux-386), func ParseNetlinkMessage([]uint8) ([]NetlinkMessage, error)
 pkg syscall (linux-386), func ParseNetlinkRouteAttr(*NetlinkMessage) ([]NetlinkRouteAttr, error)
-pkg syscall (linux-386), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (linux-386), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (linux-386), func ParseUnixCredentials(*SocketControlMessage) (*Ucred, error)
 pkg syscall (linux-386), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (linux-386), func Pause() error
 pkg syscall (linux-386), func Pipe([]int) error
 pkg syscall (linux-386), func PivotRoot(string, string) error
-pkg syscall (linux-386), func Pread(int, []byte, int64) (int, error)
+pkg syscall (linux-386), func Pread(int, []uint8, int64) (int, error)
 pkg syscall (linux-386), func PtraceAttach(int) error
 pkg syscall (linux-386), func PtraceCont(int, int) error
 pkg syscall (linux-386), func PtraceDetach(int) error
 pkg syscall (linux-386), func PtraceGetEventMsg(int) (uint, error)
 pkg syscall (linux-386), func PtraceGetRegs(int, *PtraceRegs) error
-pkg syscall (linux-386), func PtracePeekData(int, uintptr, []byte) (int, error)
-pkg syscall (linux-386), func PtracePeekText(int, uintptr, []byte) (int, error)
-pkg syscall (linux-386), func PtracePokeData(int, uintptr, []byte) (int, error)
-pkg syscall (linux-386), func PtracePokeText(int, uintptr, []byte) (int, error)
+pkg syscall (linux-386), func PtracePeekData(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-386), func PtracePeekText(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-386), func PtracePokeData(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-386), func PtracePokeText(int, uintptr, []uint8) (int, error)
 pkg syscall (linux-386), func PtraceSetOptions(int, int) error
 pkg syscall (linux-386), func PtraceSetRegs(int, *PtraceRegs) error
 pkg syscall (linux-386), func PtraceSingleStep(int) error
-pkg syscall (linux-386), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (linux-386), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (linux-386), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (linux-386), func Read(int, []byte) (int, error)
-pkg syscall (linux-386), func ReadDirent(int, []byte) (int, error)
+pkg syscall (linux-386), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (linux-386), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-386), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-386), func Read(int, []uint8) (int, error)
+pkg syscall (linux-386), func ReadDirent(int, []uint8) (int, error)
 pkg syscall (linux-386), func Reboot(int) error
-pkg syscall (linux-386), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (linux-386), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (linux-386), func Rename(string, string) error
+pkg syscall (linux-386), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (linux-386), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (linux-386), func Renameat(int, string, int, string) error
 pkg syscall (linux-386), func Seek(int, int64, int) (int64, error)
 pkg syscall (linux-386), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) (int, error)
 pkg syscall (linux-386), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (linux-386), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (linux-386), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (linux-386), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (linux-386), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (linux-386), func SetLsfPromisc(string, bool) error
 pkg syscall (linux-386), func SetNonblock(int, bool) error
-pkg syscall (linux-386), func Setdomainname([]byte) error
+pkg syscall (linux-386), func Setdomainname([]uint8) error
 pkg syscall (linux-386), func Setfsgid(int) error
 pkg syscall (linux-386), func Setfsuid(int) error
 pkg syscall (linux-386), func Setgid(int) error
 pkg syscall (linux-386), func Setgroups([]int) error
-pkg syscall (linux-386), func Sethostname([]byte) error
+pkg syscall (linux-386), func Sethostname([]uint8) error
 pkg syscall (linux-386), func Setpgid(int, int) error
 pkg syscall (linux-386), func Setregid(int, int) error
 pkg syscall (linux-386), func Setresgid(int, int, int) error
@@ -18962,26 +18954,27 @@ pkg syscall (linux-386), func Setresuid(int, int, int) error
 pkg syscall (linux-386), func Setreuid(int, int) error
 pkg syscall (linux-386), func Setrlimit(int, *Rlimit) error
 pkg syscall (linux-386), func Setsid() (int, error)
-pkg syscall (linux-386), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (linux-386), func SetsockoptIPMreqn(int, *IPMreqn) error
-pkg syscall (linux-386), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (linux-386), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (linux-386), func SetsockoptInt(int, int) error
-pkg syscall (linux-386), func SetsockoptLinger(int, *Linger) error
-pkg syscall (linux-386), func SetsockoptString(int, string) error
-pkg syscall (linux-386), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (linux-386), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (linux-386), func SetsockoptIPMreqn(int, int, int, *IPMreqn) error
+pkg syscall (linux-386), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (linux-386), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (linux-386), func SetsockoptInt(int, int, int, int) error
+pkg syscall (linux-386), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (linux-386), func SetsockoptString(int, int, int, string) error
+pkg syscall (linux-386), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (linux-386), func Settimeofday(*Timeval) error
 pkg syscall (linux-386), func Setuid(int) error
-pkg syscall (linux-386), func Shutdown(int) error
-pkg syscall (linux-386), func Socket(int) (int, error)
-pkg syscall (linux-386), func Socketpair(int) ([2]int, error)
+pkg syscall (linux-386), func Shutdown(int, int) error
+pkg syscall (linux-386), func Socket(int, int, int) (int, error)
+pkg syscall (linux-386), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (linux-386), func Splice(int, *int64, int, *int64, int, int) (int, error)
 pkg syscall (linux-386), func Stat(string, *Stat_t) error
 pkg syscall (linux-386), func Statfs(string, *Statfs_t) error
-pkg syscall (linux-386), func StringSlicePtr([]string) []*byte
-pkg syscall (linux-386), func Symlink(string, string) error
+pkg syscall (linux-386), func StringSlicePtr([]string) []*uint8
 pkg syscall (linux-386), func Sync()
 pkg syscall (linux-386), func SyncFileRange(int, int64, int64, int) error
+pkg syscall (linux-386), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-386), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (linux-386), func Sysinfo(*Sysinfo_t) error
 pkg syscall (linux-386), func Tee(int, int, int, int) (int64, error)
 pkg syscall (linux-386), func Tgkill(int, int, Signal) error
@@ -18992,15 +18985,15 @@ pkg syscall (linux-386), func TimevalToNsec(Timeval) int64
 pkg syscall (linux-386), func Truncate(string, int64) error
 pkg syscall (linux-386), func Umask(int) int
 pkg syscall (linux-386), func Uname(*Utsname) error
-pkg syscall (linux-386), func UnixCredentials(*Ucred) []byte
-pkg syscall (linux-386), func UnixRights(...int) []byte
+pkg syscall (linux-386), func UnixCredentials(*Ucred) []uint8
+pkg syscall (linux-386), func UnixRights(...int) []uint8
 pkg syscall (linux-386), func Unlinkat(int, string) error
 pkg syscall (linux-386), func Unmount(string, int) error
 pkg syscall (linux-386), func Unshare(int) error
 pkg syscall (linux-386), func Ustat(int, *Ustat_t) error
 pkg syscall (linux-386), func Utime(string, *Utimbuf) error
 pkg syscall (linux-386), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (linux-386), func Write(int, []byte) (int, error)
+pkg syscall (linux-386), func Write(int, []uint8) (int, error)
 pkg syscall (linux-386), method (*Cmsghdr) SetLen(int)
 pkg syscall (linux-386), method (*Iovec) SetLen(int)
 pkg syscall (linux-386), method (*Msghdr) SetControllen(int)
@@ -19010,7 +19003,7 @@ pkg syscall (linux-386), type Cmsghdr struct
 pkg syscall (linux-386), type Cmsghdr struct, Len uint32
 pkg syscall (linux-386), type Cmsghdr struct, Level int32
 pkg syscall (linux-386), type Cmsghdr struct, Type int32
-pkg syscall (linux-386), type Cmsghdr struct, X__cmsg_data [0]byte
+pkg syscall (linux-386), type Cmsghdr struct, X__cmsg_data [0]uint8
 pkg syscall (linux-386), type Credential struct
 pkg syscall (linux-386), type Credential struct, Gid uint32
 pkg syscall (linux-386), type Credential struct, Groups []uint32
@@ -19019,7 +19012,7 @@ pkg syscall (linux-386), type Dirent struct
 pkg syscall (linux-386), type Dirent struct, Ino uint64
 pkg syscall (linux-386), type Dirent struct, Name [256]int8
 pkg syscall (linux-386), type Dirent struct, Off int64
-pkg syscall (linux-386), type Dirent struct, Pad_cgo_0 [1]byte
+pkg syscall (linux-386), type Dirent struct, Pad_cgo_0 [1]uint8
 pkg syscall (linux-386), type Dirent struct, Reclen uint16
 pkg syscall (linux-386), type Dirent struct, Type uint8
 pkg syscall (linux-386), type EpollEvent struct
@@ -19031,9 +19024,9 @@ pkg syscall (linux-386), type FdSet struct, Bits [32]int32
 pkg syscall (linux-386), type Fsid struct
 pkg syscall (linux-386), type Fsid struct, X__val [2]int32
 pkg syscall (linux-386), type IPMreqn struct
-pkg syscall (linux-386), type IPMreqn struct, Address [4]byte
+pkg syscall (linux-386), type IPMreqn struct, Address [4]uint8
 pkg syscall (linux-386), type IPMreqn struct, Ifindex int32
-pkg syscall (linux-386), type IPMreqn struct, Multiaddr [4]byte
+pkg syscall (linux-386), type IPMreqn struct, Multiaddr [4]uint8
 pkg syscall (linux-386), type IfAddrmsg struct
 pkg syscall (linux-386), type IfAddrmsg struct, Family uint8
 pkg syscall (linux-386), type IfAddrmsg struct, Flags uint8
@@ -19048,35 +19041,35 @@ pkg syscall (linux-386), type IfInfomsg struct, Index int32
 pkg syscall (linux-386), type IfInfomsg struct, Type uint16
 pkg syscall (linux-386), type IfInfomsg struct, X__ifi_pad uint8
 pkg syscall (linux-386), type Inet4Pktinfo struct
-pkg syscall (linux-386), type Inet4Pktinfo struct, Addr [4]byte
+pkg syscall (linux-386), type Inet4Pktinfo struct, Addr [4]uint8
 pkg syscall (linux-386), type Inet4Pktinfo struct, Ifindex int32
-pkg syscall (linux-386), type Inet4Pktinfo struct, Spec_dst [4]byte
+pkg syscall (linux-386), type Inet4Pktinfo struct, Spec_dst [4]uint8
 pkg syscall (linux-386), type Inet6Pktinfo struct
-pkg syscall (linux-386), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (linux-386), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (linux-386), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (linux-386), type InotifyEvent struct
 pkg syscall (linux-386), type InotifyEvent struct, Cookie uint32
 pkg syscall (linux-386), type InotifyEvent struct, Len uint32
 pkg syscall (linux-386), type InotifyEvent struct, Mask uint32
-pkg syscall (linux-386), type InotifyEvent struct, Name [0]byte
+pkg syscall (linux-386), type InotifyEvent struct, Name [0]uint8
 pkg syscall (linux-386), type InotifyEvent struct, Wd int32
 pkg syscall (linux-386), type Iovec struct
-pkg syscall (linux-386), type Iovec struct, Base *byte
+pkg syscall (linux-386), type Iovec struct, Base *uint8
 pkg syscall (linux-386), type Iovec struct, Len uint32
 pkg syscall (linux-386), type Msghdr struct
-pkg syscall (linux-386), type Msghdr struct, Control *byte
+pkg syscall (linux-386), type Msghdr struct, Control *uint8
 pkg syscall (linux-386), type Msghdr struct, Controllen uint32
 pkg syscall (linux-386), type Msghdr struct, Flags int32
 pkg syscall (linux-386), type Msghdr struct, Iov *Iovec
 pkg syscall (linux-386), type Msghdr struct, Iovlen uint32
-pkg syscall (linux-386), type Msghdr struct, Name *byte
+pkg syscall (linux-386), type Msghdr struct, Name *uint8
 pkg syscall (linux-386), type Msghdr struct, Namelen uint32
 pkg syscall (linux-386), type NetlinkMessage struct
-pkg syscall (linux-386), type NetlinkMessage struct, Data []byte
+pkg syscall (linux-386), type NetlinkMessage struct, Data []uint8
 pkg syscall (linux-386), type NetlinkMessage struct, Header NlMsghdr
 pkg syscall (linux-386), type NetlinkRouteAttr struct
 pkg syscall (linux-386), type NetlinkRouteAttr struct, Attr RtAttr
-pkg syscall (linux-386), type NetlinkRouteAttr struct, Value []byte
+pkg syscall (linux-386), type NetlinkRouteAttr struct, Value []uint8
 pkg syscall (linux-386), type NetlinkRouteRequest struct
 pkg syscall (linux-386), type NetlinkRouteRequest struct, Data RtGenmsg
 pkg syscall (linux-386), type NetlinkRouteRequest struct, Header NlMsghdr
@@ -19116,7 +19109,7 @@ pkg syscall (linux-386), type RawSockaddrAny struct, Pad [96]int8
 pkg syscall (linux-386), type RawSockaddrInet4 struct, Family uint16
 pkg syscall (linux-386), type RawSockaddrInet4 struct, Zero [8]uint8
 pkg syscall (linux-386), type RawSockaddrInet6 struct
-pkg syscall (linux-386), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (linux-386), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (linux-386), type RawSockaddrInet6 struct, Family uint16
 pkg syscall (linux-386), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (linux-386), type RawSockaddrInet6 struct, Port uint16
@@ -19184,9 +19177,9 @@ pkg syscall (linux-386), type SockFilter struct, K uint32
 pkg syscall (linux-386), type SockFprog struct
 pkg syscall (linux-386), type SockFprog struct, Filter *SockFilter
 pkg syscall (linux-386), type SockFprog struct, Len uint16
-pkg syscall (linux-386), type SockFprog struct, Pad_cgo_0 [2]byte
+pkg syscall (linux-386), type SockFprog struct, Pad_cgo_0 [2]uint8
 pkg syscall (linux-386), type SockaddrLinklayer struct
-pkg syscall (linux-386), type SockaddrLinklayer struct, Addr [8]byte
+pkg syscall (linux-386), type SockaddrLinklayer struct, Addr [8]uint8
 pkg syscall (linux-386), type SockaddrLinklayer struct, Halen uint8
 pkg syscall (linux-386), type SockaddrLinklayer struct, Hatype uint16
 pkg syscall (linux-386), type SockaddrLinklayer struct, Ifindex int
@@ -19198,7 +19191,7 @@ pkg syscall (linux-386), type SockaddrNetlink struct, Groups uint32
 pkg syscall (linux-386), type SockaddrNetlink struct, Pad uint16
 pkg syscall (linux-386), type SockaddrNetlink struct, Pid uint32
 pkg syscall (linux-386), type SocketControlMessage struct
-pkg syscall (linux-386), type SocketControlMessage struct, Data []byte
+pkg syscall (linux-386), type SocketControlMessage struct, Data []uint8
 pkg syscall (linux-386), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (linux-386), type Stat_t struct
 pkg syscall (linux-386), type Stat_t struct, Atim Timespec
@@ -19211,8 +19204,8 @@ pkg syscall (linux-386), type Stat_t struct, Ino uint64
 pkg syscall (linux-386), type Stat_t struct, Mode uint32
 pkg syscall (linux-386), type Stat_t struct, Mtim Timespec
 pkg syscall (linux-386), type Stat_t struct, Nlink uint32
-pkg syscall (linux-386), type Stat_t struct, Pad_cgo_0 [2]byte
-pkg syscall (linux-386), type Stat_t struct, Pad_cgo_1 [2]byte
+pkg syscall (linux-386), type Stat_t struct, Pad_cgo_0 [2]uint8
+pkg syscall (linux-386), type Stat_t struct, Pad_cgo_1 [2]uint8
 pkg syscall (linux-386), type Stat_t struct, Rdev uint64
 pkg syscall (linux-386), type Stat_t struct, Size int64
 pkg syscall (linux-386), type Stat_t struct, Uid uint32
@@ -19264,7 +19257,7 @@ pkg syscall (linux-386), type Termios struct, Lflag uint32
 pkg syscall (linux-386), type Termios struct, Line uint8
 pkg syscall (linux-386), type Termios struct, Oflag uint32
 pkg syscall (linux-386), type Termios struct, Ospeed uint32
-pkg syscall (linux-386), type Termios struct, Pad_cgo_0 [3]byte
+pkg syscall (linux-386), type Termios struct, Pad_cgo_0 [3]uint8
 pkg syscall (linux-386), type Time_t int32
 pkg syscall (linux-386), type Timespec struct, Nsec int32
 pkg syscall (linux-386), type Timespec struct, Sec int32
@@ -19281,7 +19274,7 @@ pkg syscall (linux-386), type Timex struct, Jitter int32
 pkg syscall (linux-386), type Timex struct, Maxerror int32
 pkg syscall (linux-386), type Timex struct, Modes uint32
 pkg syscall (linux-386), type Timex struct, Offset int32
-pkg syscall (linux-386), type Timex struct, Pad_cgo_0 [44]byte
+pkg syscall (linux-386), type Timex struct, Pad_cgo_0 [44]uint8
 pkg syscall (linux-386), type Timex struct, Ppsfreq int32
 pkg syscall (linux-386), type Timex struct, Precision int32
 pkg syscall (linux-386), type Timex struct, Shift int32
@@ -21050,19 +21043,19 @@ pkg syscall (linux-386-cgo), func Fsync(int) error
 pkg syscall (linux-386-cgo), func Ftruncate(int, int64) error
 pkg syscall (linux-386-cgo), func Futimes(int, []Timeval) error
 pkg syscall (linux-386-cgo), func Futimesat(int, string, []Timeval) error
-pkg syscall (linux-386-cgo), func Getcwd([]byte) (int, error)
-pkg syscall (linux-386-cgo), func Getdents(int, []byte) (int, error)
+pkg syscall (linux-386-cgo), func Getcwd([]uint8) (int, error)
+pkg syscall (linux-386-cgo), func Getdents(int, []uint8) (int, error)
 pkg syscall (linux-386-cgo), func Getpeername(int) (Sockaddr, error)
 pkg syscall (linux-386-cgo), func Getpgid(int) (int, error)
 pkg syscall (linux-386-cgo), func Getpgrp() int
 pkg syscall (linux-386-cgo), func Getrlimit(int, *Rlimit) error
 pkg syscall (linux-386-cgo), func Getrusage(int, *Rusage) error
 pkg syscall (linux-386-cgo), func Getsockname(int) (Sockaddr, error)
-pkg syscall (linux-386-cgo), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (linux-386-cgo), func GetsockoptIPMreqn(int) (*IPMreqn, error)
-pkg syscall (linux-386-cgo), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (linux-386-cgo), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (linux-386-cgo), func GetsockoptInt(int) (int, error)
+pkg syscall (linux-386-cgo), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (linux-386-cgo), func GetsockoptIPMreqn(int, int, int) (*IPMreqn, error)
+pkg syscall (linux-386-cgo), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (linux-386-cgo), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (linux-386-cgo), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (linux-386-cgo), func Gettid() int
 pkg syscall (linux-386-cgo), func InotifyAddWatch(int, string, uint32) (int, error)
 pkg syscall (linux-386-cgo), func InotifyInit() (int, error)
@@ -21071,76 +21064,74 @@ pkg syscall (linux-386-cgo), func InotifyRmWatch(int, uint32) (int, error)
 pkg syscall (linux-386-cgo), func Ioperm(int, int, int) error
 pkg syscall (linux-386-cgo), func Iopl(int) error
 pkg syscall (linux-386-cgo), func Kill(int, Signal) error
-pkg syscall (linux-386-cgo), func Klogctl(int, []byte) (int, error)
-pkg syscall (linux-386-cgo), func Link(string, string) error
+pkg syscall (linux-386-cgo), func Klogctl(int, []uint8) (int, error)
 pkg syscall (linux-386-cgo), func Listen(int, int) error
-pkg syscall (linux-386-cgo), func LsfJump(int) *SockFilter
-pkg syscall (linux-386-cgo), func LsfSocket(int) (int, error)
-pkg syscall (linux-386-cgo), func LsfStmt(int) *SockFilter
+pkg syscall (linux-386-cgo), func LsfJump(int, int, int, int) *SockFilter
+pkg syscall (linux-386-cgo), func LsfSocket(int, int) (int, error)
+pkg syscall (linux-386-cgo), func LsfStmt(int, int) *SockFilter
 pkg syscall (linux-386-cgo), func Lstat(string, *Stat_t) error
-pkg syscall (linux-386-cgo), func Madvise([]byte, int) error
+pkg syscall (linux-386-cgo), func Madvise([]uint8, int) error
 pkg syscall (linux-386-cgo), func Mkdirat(int, string, uint32) error
 pkg syscall (linux-386-cgo), func Mkfifo(string, uint32) error
 pkg syscall (linux-386-cgo), func Mknod(string, uint32, int) error
 pkg syscall (linux-386-cgo), func Mknodat(int, string, uint32, int) error
-pkg syscall (linux-386-cgo), func Mlock([]byte) error
+pkg syscall (linux-386-cgo), func Mlock([]uint8) error
 pkg syscall (linux-386-cgo), func Mlockall(int) error
-pkg syscall (linux-386-cgo), func Mmap(int, int64, int, int, int) ([]byte, error)
+pkg syscall (linux-386-cgo), func Mmap(int, int64, int, int, int) ([]uint8, error)
 pkg syscall (linux-386-cgo), func Mount(string, string, string, uintptr, string) error
-pkg syscall (linux-386-cgo), func Mprotect([]byte, int) error
-pkg syscall (linux-386-cgo), func Munlock([]byte) error
+pkg syscall (linux-386-cgo), func Mprotect([]uint8, int) error
+pkg syscall (linux-386-cgo), func Munlock([]uint8) error
 pkg syscall (linux-386-cgo), func Munlockall() error
-pkg syscall (linux-386-cgo), func Munmap([]byte) error
+pkg syscall (linux-386-cgo), func Munmap([]uint8) error
 pkg syscall (linux-386-cgo), func Nanosleep(*Timespec, *Timespec) error
-pkg syscall (linux-386-cgo), func NetlinkRIB(int) ([]byte, error)
+pkg syscall (linux-386-cgo), func NetlinkRIB(int, int) ([]uint8, error)
 pkg syscall (linux-386-cgo), func NsecToTimespec(int64) Timespec
 pkg syscall (linux-386-cgo), func Open(string, int, uint32) (int, error)
 pkg syscall (linux-386-cgo), func Openat(int, string, int, uint32) (int, error)
-pkg syscall (linux-386-cgo), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (linux-386-cgo), func ParseNetlinkMessage([]byte) ([]NetlinkMessage, error)
+pkg syscall (linux-386-cgo), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (linux-386-cgo), func ParseNetlinkMessage([]uint8) ([]NetlinkMessage, error)
 pkg syscall (linux-386-cgo), func ParseNetlinkRouteAttr(*NetlinkMessage) ([]NetlinkRouteAttr, error)
-pkg syscall (linux-386-cgo), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (linux-386-cgo), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (linux-386-cgo), func ParseUnixCredentials(*SocketControlMessage) (*Ucred, error)
 pkg syscall (linux-386-cgo), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (linux-386-cgo), func Pause() error
 pkg syscall (linux-386-cgo), func Pipe([]int) error
 pkg syscall (linux-386-cgo), func PivotRoot(string, string) error
-pkg syscall (linux-386-cgo), func Pread(int, []byte, int64) (int, error)
+pkg syscall (linux-386-cgo), func Pread(int, []uint8, int64) (int, error)
 pkg syscall (linux-386-cgo), func PtraceAttach(int) error
 pkg syscall (linux-386-cgo), func PtraceCont(int, int) error
 pkg syscall (linux-386-cgo), func PtraceDetach(int) error
 pkg syscall (linux-386-cgo), func PtraceGetEventMsg(int) (uint, error)
 pkg syscall (linux-386-cgo), func PtraceGetRegs(int, *PtraceRegs) error
-pkg syscall (linux-386-cgo), func PtracePeekData(int, uintptr, []byte) (int, error)
-pkg syscall (linux-386-cgo), func PtracePeekText(int, uintptr, []byte) (int, error)
-pkg syscall (linux-386-cgo), func PtracePokeData(int, uintptr, []byte) (int, error)
-pkg syscall (linux-386-cgo), func PtracePokeText(int, uintptr, []byte) (int, error)
+pkg syscall (linux-386-cgo), func PtracePeekData(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-386-cgo), func PtracePeekText(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-386-cgo), func PtracePokeData(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-386-cgo), func PtracePokeText(int, uintptr, []uint8) (int, error)
 pkg syscall (linux-386-cgo), func PtraceSetOptions(int, int) error
 pkg syscall (linux-386-cgo), func PtraceSetRegs(int, *PtraceRegs) error
 pkg syscall (linux-386-cgo), func PtraceSingleStep(int) error
-pkg syscall (linux-386-cgo), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (linux-386-cgo), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (linux-386-cgo), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (linux-386-cgo), func Read(int, []byte) (int, error)
-pkg syscall (linux-386-cgo), func ReadDirent(int, []byte) (int, error)
+pkg syscall (linux-386-cgo), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (linux-386-cgo), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-386-cgo), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-386-cgo), func Read(int, []uint8) (int, error)
+pkg syscall (linux-386-cgo), func ReadDirent(int, []uint8) (int, error)
 pkg syscall (linux-386-cgo), func Reboot(int) error
-pkg syscall (linux-386-cgo), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (linux-386-cgo), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (linux-386-cgo), func Rename(string, string) error
+pkg syscall (linux-386-cgo), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (linux-386-cgo), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (linux-386-cgo), func Renameat(int, string, int, string) error
 pkg syscall (linux-386-cgo), func Seek(int, int64, int) (int64, error)
 pkg syscall (linux-386-cgo), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) (int, error)
 pkg syscall (linux-386-cgo), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (linux-386-cgo), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (linux-386-cgo), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (linux-386-cgo), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (linux-386-cgo), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (linux-386-cgo), func SetLsfPromisc(string, bool) error
 pkg syscall (linux-386-cgo), func SetNonblock(int, bool) error
-pkg syscall (linux-386-cgo), func Setdomainname([]byte) error
+pkg syscall (linux-386-cgo), func Setdomainname([]uint8) error
 pkg syscall (linux-386-cgo), func Setfsgid(int) error
 pkg syscall (linux-386-cgo), func Setfsuid(int) error
 pkg syscall (linux-386-cgo), func Setgid(int) error
 pkg syscall (linux-386-cgo), func Setgroups([]int) error
-pkg syscall (linux-386-cgo), func Sethostname([]byte) error
+pkg syscall (linux-386-cgo), func Sethostname([]uint8) error
 pkg syscall (linux-386-cgo), func Setpgid(int, int) error
 pkg syscall (linux-386-cgo), func Setregid(int, int) error
 pkg syscall (linux-386-cgo), func Setresgid(int, int, int) error
@@ -21148,26 +21139,27 @@ pkg syscall (linux-386-cgo), func Setresuid(int, int, int) error
 pkg syscall (linux-386-cgo), func Setreuid(int, int) error
 pkg syscall (linux-386-cgo), func Setrlimit(int, *Rlimit) error
 pkg syscall (linux-386-cgo), func Setsid() (int, error)
-pkg syscall (linux-386-cgo), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (linux-386-cgo), func SetsockoptIPMreqn(int, *IPMreqn) error
-pkg syscall (linux-386-cgo), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (linux-386-cgo), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (linux-386-cgo), func SetsockoptInt(int, int) error
-pkg syscall (linux-386-cgo), func SetsockoptLinger(int, *Linger) error
-pkg syscall (linux-386-cgo), func SetsockoptString(int, string) error
-pkg syscall (linux-386-cgo), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (linux-386-cgo), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (linux-386-cgo), func SetsockoptIPMreqn(int, int, int, *IPMreqn) error
+pkg syscall (linux-386-cgo), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (linux-386-cgo), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (linux-386-cgo), func SetsockoptInt(int, int, int, int) error
+pkg syscall (linux-386-cgo), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (linux-386-cgo), func SetsockoptString(int, int, int, string) error
+pkg syscall (linux-386-cgo), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (linux-386-cgo), func Settimeofday(*Timeval) error
 pkg syscall (linux-386-cgo), func Setuid(int) error
-pkg syscall (linux-386-cgo), func Shutdown(int) error
-pkg syscall (linux-386-cgo), func Socket(int) (int, error)
-pkg syscall (linux-386-cgo), func Socketpair(int) ([2]int, error)
+pkg syscall (linux-386-cgo), func Shutdown(int, int) error
+pkg syscall (linux-386-cgo), func Socket(int, int, int) (int, error)
+pkg syscall (linux-386-cgo), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (linux-386-cgo), func Splice(int, *int64, int, *int64, int, int) (int, error)
 pkg syscall (linux-386-cgo), func Stat(string, *Stat_t) error
 pkg syscall (linux-386-cgo), func Statfs(string, *Statfs_t) error
-pkg syscall (linux-386-cgo), func StringSlicePtr([]string) []*byte
-pkg syscall (linux-386-cgo), func Symlink(string, string) error
+pkg syscall (linux-386-cgo), func StringSlicePtr([]string) []*uint8
 pkg syscall (linux-386-cgo), func Sync()
 pkg syscall (linux-386-cgo), func SyncFileRange(int, int64, int64, int) error
+pkg syscall (linux-386-cgo), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-386-cgo), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (linux-386-cgo), func Sysinfo(*Sysinfo_t) error
 pkg syscall (linux-386-cgo), func Tee(int, int, int, int) (int64, error)
 pkg syscall (linux-386-cgo), func Tgkill(int, int, Signal) error
@@ -21178,15 +21170,15 @@ pkg syscall (linux-386-cgo), func TimevalToNsec(Timeval) int64
 pkg syscall (linux-386-cgo), func Truncate(string, int64) error
 pkg syscall (linux-386-cgo), func Umask(int) int
 pkg syscall (linux-386-cgo), func Uname(*Utsname) error
-pkg syscall (linux-386-cgo), func UnixCredentials(*Ucred) []byte
-pkg syscall (linux-386-cgo), func UnixRights(...int) []byte
+pkg syscall (linux-386-cgo), func UnixCredentials(*Ucred) []uint8
+pkg syscall (linux-386-cgo), func UnixRights(...int) []uint8
 pkg syscall (linux-386-cgo), func Unlinkat(int, string) error
 pkg syscall (linux-386-cgo), func Unmount(string, int) error
 pkg syscall (linux-386-cgo), func Unshare(int) error
 pkg syscall (linux-386-cgo), func Ustat(int, *Ustat_t) error
 pkg syscall (linux-386-cgo), func Utime(string, *Utimbuf) error
 pkg syscall (linux-386-cgo), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (linux-386-cgo), func Write(int, []byte) (int, error)
+pkg syscall (linux-386-cgo), func Write(int, []uint8) (int, error)
 pkg syscall (linux-386-cgo), method (*Cmsghdr) SetLen(int)
 pkg syscall (linux-386-cgo), method (*Iovec) SetLen(int)
 pkg syscall (linux-386-cgo), method (*Msghdr) SetControllen(int)
@@ -21196,7 +21188,7 @@ pkg syscall (linux-386-cgo), type Cmsghdr struct
 pkg syscall (linux-386-cgo), type Cmsghdr struct, Len uint32
 pkg syscall (linux-386-cgo), type Cmsghdr struct, Level int32
 pkg syscall (linux-386-cgo), type Cmsghdr struct, Type int32
-pkg syscall (linux-386-cgo), type Cmsghdr struct, X__cmsg_data [0]byte
+pkg syscall (linux-386-cgo), type Cmsghdr struct, X__cmsg_data [0]uint8
 pkg syscall (linux-386-cgo), type Credential struct
 pkg syscall (linux-386-cgo), type Credential struct, Gid uint32
 pkg syscall (linux-386-cgo), type Credential struct, Groups []uint32
@@ -21205,7 +21197,7 @@ pkg syscall (linux-386-cgo), type Dirent struct
 pkg syscall (linux-386-cgo), type Dirent struct, Ino uint64
 pkg syscall (linux-386-cgo), type Dirent struct, Name [256]int8
 pkg syscall (linux-386-cgo), type Dirent struct, Off int64
-pkg syscall (linux-386-cgo), type Dirent struct, Pad_cgo_0 [1]byte
+pkg syscall (linux-386-cgo), type Dirent struct, Pad_cgo_0 [1]uint8
 pkg syscall (linux-386-cgo), type Dirent struct, Reclen uint16
 pkg syscall (linux-386-cgo), type Dirent struct, Type uint8
 pkg syscall (linux-386-cgo), type EpollEvent struct
@@ -21217,9 +21209,9 @@ pkg syscall (linux-386-cgo), type FdSet struct, Bits [32]int32
 pkg syscall (linux-386-cgo), type Fsid struct
 pkg syscall (linux-386-cgo), type Fsid struct, X__val [2]int32
 pkg syscall (linux-386-cgo), type IPMreqn struct
-pkg syscall (linux-386-cgo), type IPMreqn struct, Address [4]byte
+pkg syscall (linux-386-cgo), type IPMreqn struct, Address [4]uint8
 pkg syscall (linux-386-cgo), type IPMreqn struct, Ifindex int32
-pkg syscall (linux-386-cgo), type IPMreqn struct, Multiaddr [4]byte
+pkg syscall (linux-386-cgo), type IPMreqn struct, Multiaddr [4]uint8
 pkg syscall (linux-386-cgo), type IfAddrmsg struct
 pkg syscall (linux-386-cgo), type IfAddrmsg struct, Family uint8
 pkg syscall (linux-386-cgo), type IfAddrmsg struct, Flags uint8
@@ -21234,35 +21226,35 @@ pkg syscall (linux-386-cgo), type IfInfomsg struct, Index int32
 pkg syscall (linux-386-cgo), type IfInfomsg struct, Type uint16
 pkg syscall (linux-386-cgo), type IfInfomsg struct, X__ifi_pad uint8
 pkg syscall (linux-386-cgo), type Inet4Pktinfo struct
-pkg syscall (linux-386-cgo), type Inet4Pktinfo struct, Addr [4]byte
+pkg syscall (linux-386-cgo), type Inet4Pktinfo struct, Addr [4]uint8
 pkg syscall (linux-386-cgo), type Inet4Pktinfo struct, Ifindex int32
-pkg syscall (linux-386-cgo), type Inet4Pktinfo struct, Spec_dst [4]byte
+pkg syscall (linux-386-cgo), type Inet4Pktinfo struct, Spec_dst [4]uint8
 pkg syscall (linux-386-cgo), type Inet6Pktinfo struct
-pkg syscall (linux-386-cgo), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (linux-386-cgo), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (linux-386-cgo), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (linux-386-cgo), type InotifyEvent struct
 pkg syscall (linux-386-cgo), type InotifyEvent struct, Cookie uint32
 pkg syscall (linux-386-cgo), type InotifyEvent struct, Len uint32
 pkg syscall (linux-386-cgo), type InotifyEvent struct, Mask uint32
-pkg syscall (linux-386-cgo), type InotifyEvent struct, Name [0]byte
+pkg syscall (linux-386-cgo), type InotifyEvent struct, Name [0]uint8
 pkg syscall (linux-386-cgo), type InotifyEvent struct, Wd int32
 pkg syscall (linux-386-cgo), type Iovec struct
-pkg syscall (linux-386-cgo), type Iovec struct, Base *byte
+pkg syscall (linux-386-cgo), type Iovec struct, Base *uint8
 pkg syscall (linux-386-cgo), type Iovec struct, Len uint32
 pkg syscall (linux-386-cgo), type Msghdr struct
-pkg syscall (linux-386-cgo), type Msghdr struct, Control *byte
+pkg syscall (linux-386-cgo), type Msghdr struct, Control *uint8
 pkg syscall (linux-386-cgo), type Msghdr struct, Controllen uint32
 pkg syscall (linux-386-cgo), type Msghdr struct, Flags int32
 pkg syscall (linux-386-cgo), type Msghdr struct, Iov *Iovec
 pkg syscall (linux-386-cgo), type Msghdr struct, Iovlen uint32
-pkg syscall (linux-386-cgo), type Msghdr struct, Name *byte
+pkg syscall (linux-386-cgo), type Msghdr struct, Name *uint8
 pkg syscall (linux-386-cgo), type Msghdr struct, Namelen uint32
 pkg syscall (linux-386-cgo), type NetlinkMessage struct
-pkg syscall (linux-386-cgo), type NetlinkMessage struct, Data []byte
+pkg syscall (linux-386-cgo), type NetlinkMessage struct, Data []uint8
 pkg syscall (linux-386-cgo), type NetlinkMessage struct, Header NlMsghdr
 pkg syscall (linux-386-cgo), type NetlinkRouteAttr struct
 pkg syscall (linux-386-cgo), type NetlinkRouteAttr struct, Attr RtAttr
-pkg syscall (linux-386-cgo), type NetlinkRouteAttr struct, Value []byte
+pkg syscall (linux-386-cgo), type NetlinkRouteAttr struct, Value []uint8
 pkg syscall (linux-386-cgo), type NetlinkRouteRequest struct
 pkg syscall (linux-386-cgo), type NetlinkRouteRequest struct, Data RtGenmsg
 pkg syscall (linux-386-cgo), type NetlinkRouteRequest struct, Header NlMsghdr
@@ -21302,7 +21294,7 @@ pkg syscall (linux-386-cgo), type RawSockaddrAny struct, Pad [96]int8
 pkg syscall (linux-386-cgo), type RawSockaddrInet4 struct, Family uint16
 pkg syscall (linux-386-cgo), type RawSockaddrInet4 struct, Zero [8]uint8
 pkg syscall (linux-386-cgo), type RawSockaddrInet6 struct
-pkg syscall (linux-386-cgo), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (linux-386-cgo), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (linux-386-cgo), type RawSockaddrInet6 struct, Family uint16
 pkg syscall (linux-386-cgo), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (linux-386-cgo), type RawSockaddrInet6 struct, Port uint16
@@ -21370,9 +21362,9 @@ pkg syscall (linux-386-cgo), type SockFilter struct, K uint32
 pkg syscall (linux-386-cgo), type SockFprog struct
 pkg syscall (linux-386-cgo), type SockFprog struct, Filter *SockFilter
 pkg syscall (linux-386-cgo), type SockFprog struct, Len uint16
-pkg syscall (linux-386-cgo), type SockFprog struct, Pad_cgo_0 [2]byte
+pkg syscall (linux-386-cgo), type SockFprog struct, Pad_cgo_0 [2]uint8
 pkg syscall (linux-386-cgo), type SockaddrLinklayer struct
-pkg syscall (linux-386-cgo), type SockaddrLinklayer struct, Addr [8]byte
+pkg syscall (linux-386-cgo), type SockaddrLinklayer struct, Addr [8]uint8
 pkg syscall (linux-386-cgo), type SockaddrLinklayer struct, Halen uint8
 pkg syscall (linux-386-cgo), type SockaddrLinklayer struct, Hatype uint16
 pkg syscall (linux-386-cgo), type SockaddrLinklayer struct, Ifindex int
@@ -21384,7 +21376,7 @@ pkg syscall (linux-386-cgo), type SockaddrNetlink struct, Groups uint32
 pkg syscall (linux-386-cgo), type SockaddrNetlink struct, Pad uint16
 pkg syscall (linux-386-cgo), type SockaddrNetlink struct, Pid uint32
 pkg syscall (linux-386-cgo), type SocketControlMessage struct
-pkg syscall (linux-386-cgo), type SocketControlMessage struct, Data []byte
+pkg syscall (linux-386-cgo), type SocketControlMessage struct, Data []uint8
 pkg syscall (linux-386-cgo), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (linux-386-cgo), type Stat_t struct
 pkg syscall (linux-386-cgo), type Stat_t struct, Atim Timespec
@@ -21397,8 +21389,8 @@ pkg syscall (linux-386-cgo), type Stat_t struct, Ino uint64
 pkg syscall (linux-386-cgo), type Stat_t struct, Mode uint32
 pkg syscall (linux-386-cgo), type Stat_t struct, Mtim Timespec
 pkg syscall (linux-386-cgo), type Stat_t struct, Nlink uint32
-pkg syscall (linux-386-cgo), type Stat_t struct, Pad_cgo_0 [2]byte
-pkg syscall (linux-386-cgo), type Stat_t struct, Pad_cgo_1 [2]byte
+pkg syscall (linux-386-cgo), type Stat_t struct, Pad_cgo_0 [2]uint8
+pkg syscall (linux-386-cgo), type Stat_t struct, Pad_cgo_1 [2]uint8
 pkg syscall (linux-386-cgo), type Stat_t struct, Rdev uint64
 pkg syscall (linux-386-cgo), type Stat_t struct, Size int64
 pkg syscall (linux-386-cgo), type Stat_t struct, Uid uint32
@@ -21450,7 +21442,7 @@ pkg syscall (linux-386-cgo), type Termios struct, Lflag uint32
 pkg syscall (linux-386-cgo), type Termios struct, Line uint8
 pkg syscall (linux-386-cgo), type Termios struct, Oflag uint32
 pkg syscall (linux-386-cgo), type Termios struct, Ospeed uint32
-pkg syscall (linux-386-cgo), type Termios struct, Pad_cgo_0 [3]byte
+pkg syscall (linux-386-cgo), type Termios struct, Pad_cgo_0 [3]uint8
 pkg syscall (linux-386-cgo), type Time_t int32
 pkg syscall (linux-386-cgo), type Timespec struct, Nsec int32
 pkg syscall (linux-386-cgo), type Timespec struct, Sec int32
@@ -21467,7 +21459,7 @@ pkg syscall (linux-386-cgo), type Timex struct, Jitter int32
 pkg syscall (linux-386-cgo), type Timex struct, Maxerror int32
 pkg syscall (linux-386-cgo), type Timex struct, Modes uint32
 pkg syscall (linux-386-cgo), type Timex struct, Offset int32
-pkg syscall (linux-386-cgo), type Timex struct, Pad_cgo_0 [44]byte
+pkg syscall (linux-386-cgo), type Timex struct, Pad_cgo_0 [44]uint8
 pkg syscall (linux-386-cgo), type Timex struct, Ppsfreq int32
 pkg syscall (linux-386-cgo), type Timex struct, Precision int32
 pkg syscall (linux-386-cgo), type Timex struct, Shift int32
@@ -23202,19 +23194,19 @@ pkg syscall (linux-amd64), func Fsync(int) error
 pkg syscall (linux-amd64), func Ftruncate(int, int64) error
 pkg syscall (linux-amd64), func Futimes(int, []Timeval) error
 pkg syscall (linux-amd64), func Futimesat(int, string, []Timeval) error
-pkg syscall (linux-amd64), func Getcwd([]byte) (int, error)
-pkg syscall (linux-amd64), func Getdents(int, []byte) (int, error)
+pkg syscall (linux-amd64), func Getcwd([]uint8) (int, error)
+pkg syscall (linux-amd64), func Getdents(int, []uint8) (int, error)
 pkg syscall (linux-amd64), func Getpeername(int) (Sockaddr, error)
 pkg syscall (linux-amd64), func Getpgid(int) (int, error)
 pkg syscall (linux-amd64), func Getpgrp() int
 pkg syscall (linux-amd64), func Getrlimit(int, *Rlimit) error
 pkg syscall (linux-amd64), func Getrusage(int, *Rusage) error
 pkg syscall (linux-amd64), func Getsockname(int) (Sockaddr, error)
-pkg syscall (linux-amd64), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (linux-amd64), func GetsockoptIPMreqn(int) (*IPMreqn, error)
-pkg syscall (linux-amd64), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (linux-amd64), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (linux-amd64), func GetsockoptInt(int) (int, error)
+pkg syscall (linux-amd64), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (linux-amd64), func GetsockoptIPMreqn(int, int, int) (*IPMreqn, error)
+pkg syscall (linux-amd64), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (linux-amd64), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (linux-amd64), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (linux-amd64), func Gettid() int
 pkg syscall (linux-amd64), func InotifyAddWatch(int, string, uint32) (int, error)
 pkg syscall (linux-amd64), func InotifyInit() (int, error)
@@ -23223,76 +23215,74 @@ pkg syscall (linux-amd64), func InotifyRmWatch(int, uint32) (int, error)
 pkg syscall (linux-amd64), func Ioperm(int, int, int) error
 pkg syscall (linux-amd64), func Iopl(int) error
 pkg syscall (linux-amd64), func Kill(int, Signal) error
-pkg syscall (linux-amd64), func Klogctl(int, []byte) (int, error)
-pkg syscall (linux-amd64), func Link(string, string) error
+pkg syscall (linux-amd64), func Klogctl(int, []uint8) (int, error)
 pkg syscall (linux-amd64), func Listen(int, int) error
-pkg syscall (linux-amd64), func LsfJump(int) *SockFilter
-pkg syscall (linux-amd64), func LsfSocket(int) (int, error)
-pkg syscall (linux-amd64), func LsfStmt(int) *SockFilter
+pkg syscall (linux-amd64), func LsfJump(int, int, int, int) *SockFilter
+pkg syscall (linux-amd64), func LsfSocket(int, int) (int, error)
+pkg syscall (linux-amd64), func LsfStmt(int, int) *SockFilter
 pkg syscall (linux-amd64), func Lstat(string, *Stat_t) error
-pkg syscall (linux-amd64), func Madvise([]byte, int) error
+pkg syscall (linux-amd64), func Madvise([]uint8, int) error
 pkg syscall (linux-amd64), func Mkdirat(int, string, uint32) error
 pkg syscall (linux-amd64), func Mkfifo(string, uint32) error
 pkg syscall (linux-amd64), func Mknod(string, uint32, int) error
 pkg syscall (linux-amd64), func Mknodat(int, string, uint32, int) error
-pkg syscall (linux-amd64), func Mlock([]byte) error
+pkg syscall (linux-amd64), func Mlock([]uint8) error
 pkg syscall (linux-amd64), func Mlockall(int) error
-pkg syscall (linux-amd64), func Mmap(int, int64, int, int, int) ([]byte, error)
+pkg syscall (linux-amd64), func Mmap(int, int64, int, int, int) ([]uint8, error)
 pkg syscall (linux-amd64), func Mount(string, string, string, uintptr, string) error
-pkg syscall (linux-amd64), func Mprotect([]byte, int) error
-pkg syscall (linux-amd64), func Munlock([]byte) error
+pkg syscall (linux-amd64), func Mprotect([]uint8, int) error
+pkg syscall (linux-amd64), func Munlock([]uint8) error
 pkg syscall (linux-amd64), func Munlockall() error
-pkg syscall (linux-amd64), func Munmap([]byte) error
+pkg syscall (linux-amd64), func Munmap([]uint8) error
 pkg syscall (linux-amd64), func Nanosleep(*Timespec, *Timespec) error
-pkg syscall (linux-amd64), func NetlinkRIB(int) ([]byte, error)
+pkg syscall (linux-amd64), func NetlinkRIB(int, int) ([]uint8, error)
 pkg syscall (linux-amd64), func NsecToTimespec(int64) Timespec
 pkg syscall (linux-amd64), func Open(string, int, uint32) (int, error)
 pkg syscall (linux-amd64), func Openat(int, string, int, uint32) (int, error)
-pkg syscall (linux-amd64), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (linux-amd64), func ParseNetlinkMessage([]byte) ([]NetlinkMessage, error)
+pkg syscall (linux-amd64), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (linux-amd64), func ParseNetlinkMessage([]uint8) ([]NetlinkMessage, error)
 pkg syscall (linux-amd64), func ParseNetlinkRouteAttr(*NetlinkMessage) ([]NetlinkRouteAttr, error)
-pkg syscall (linux-amd64), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (linux-amd64), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (linux-amd64), func ParseUnixCredentials(*SocketControlMessage) (*Ucred, error)
 pkg syscall (linux-amd64), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (linux-amd64), func Pause() error
 pkg syscall (linux-amd64), func Pipe([]int) error
 pkg syscall (linux-amd64), func PivotRoot(string, string) error
-pkg syscall (linux-amd64), func Pread(int, []byte, int64) (int, error)
+pkg syscall (linux-amd64), func Pread(int, []uint8, int64) (int, error)
 pkg syscall (linux-amd64), func PtraceAttach(int) error
 pkg syscall (linux-amd64), func PtraceCont(int, int) error
 pkg syscall (linux-amd64), func PtraceDetach(int) error
 pkg syscall (linux-amd64), func PtraceGetEventMsg(int) (uint, error)
 pkg syscall (linux-amd64), func PtraceGetRegs(int, *PtraceRegs) error
-pkg syscall (linux-amd64), func PtracePeekData(int, uintptr, []byte) (int, error)
-pkg syscall (linux-amd64), func PtracePeekText(int, uintptr, []byte) (int, error)
-pkg syscall (linux-amd64), func PtracePokeData(int, uintptr, []byte) (int, error)
-pkg syscall (linux-amd64), func PtracePokeText(int, uintptr, []byte) (int, error)
+pkg syscall (linux-amd64), func PtracePeekData(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-amd64), func PtracePeekText(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-amd64), func PtracePokeData(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-amd64), func PtracePokeText(int, uintptr, []uint8) (int, error)
 pkg syscall (linux-amd64), func PtraceSetOptions(int, int) error
 pkg syscall (linux-amd64), func PtraceSetRegs(int, *PtraceRegs) error
 pkg syscall (linux-amd64), func PtraceSingleStep(int) error
-pkg syscall (linux-amd64), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (linux-amd64), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (linux-amd64), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (linux-amd64), func Read(int, []byte) (int, error)
-pkg syscall (linux-amd64), func ReadDirent(int, []byte) (int, error)
+pkg syscall (linux-amd64), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (linux-amd64), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-amd64), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-amd64), func Read(int, []uint8) (int, error)
+pkg syscall (linux-amd64), func ReadDirent(int, []uint8) (int, error)
 pkg syscall (linux-amd64), func Reboot(int) error
-pkg syscall (linux-amd64), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (linux-amd64), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (linux-amd64), func Rename(string, string) error
+pkg syscall (linux-amd64), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (linux-amd64), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (linux-amd64), func Renameat(int, string, int, string) error
 pkg syscall (linux-amd64), func Seek(int, int64, int) (int64, error)
 pkg syscall (linux-amd64), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) (int, error)
 pkg syscall (linux-amd64), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (linux-amd64), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (linux-amd64), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (linux-amd64), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (linux-amd64), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (linux-amd64), func SetLsfPromisc(string, bool) error
 pkg syscall (linux-amd64), func SetNonblock(int, bool) error
-pkg syscall (linux-amd64), func Setdomainname([]byte) error
+pkg syscall (linux-amd64), func Setdomainname([]uint8) error
 pkg syscall (linux-amd64), func Setfsgid(int) error
 pkg syscall (linux-amd64), func Setfsuid(int) error
 pkg syscall (linux-amd64), func Setgid(int) error
 pkg syscall (linux-amd64), func Setgroups([]int) error
-pkg syscall (linux-amd64), func Sethostname([]byte) error
+pkg syscall (linux-amd64), func Sethostname([]uint8) error
 pkg syscall (linux-amd64), func Setpgid(int, int) error
 pkg syscall (linux-amd64), func Setregid(int, int) error
 pkg syscall (linux-amd64), func Setresgid(int, int, int) error
@@ -23300,26 +23290,27 @@ pkg syscall (linux-amd64), func Setresuid(int, int, int) error
 pkg syscall (linux-amd64), func Setreuid(int, int) error
 pkg syscall (linux-amd64), func Setrlimit(int, *Rlimit) error
 pkg syscall (linux-amd64), func Setsid() (int, error)
-pkg syscall (linux-amd64), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (linux-amd64), func SetsockoptIPMreqn(int, *IPMreqn) error
-pkg syscall (linux-amd64), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (linux-amd64), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (linux-amd64), func SetsockoptInt(int, int) error
-pkg syscall (linux-amd64), func SetsockoptLinger(int, *Linger) error
-pkg syscall (linux-amd64), func SetsockoptString(int, string) error
-pkg syscall (linux-amd64), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (linux-amd64), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (linux-amd64), func SetsockoptIPMreqn(int, int, int, *IPMreqn) error
+pkg syscall (linux-amd64), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (linux-amd64), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (linux-amd64), func SetsockoptInt(int, int, int, int) error
+pkg syscall (linux-amd64), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (linux-amd64), func SetsockoptString(int, int, int, string) error
+pkg syscall (linux-amd64), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (linux-amd64), func Settimeofday(*Timeval) error
 pkg syscall (linux-amd64), func Setuid(int) error
 pkg syscall (linux-amd64), func Shutdown(int, int) error
-pkg syscall (linux-amd64), func Socket(int) (int, error)
-pkg syscall (linux-amd64), func Socketpair(int) ([2]int, error)
+pkg syscall (linux-amd64), func Socket(int, int, int) (int, error)
+pkg syscall (linux-amd64), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (linux-amd64), func Splice(int, *int64, int, *int64, int, int) (int64, error)
 pkg syscall (linux-amd64), func Stat(string, *Stat_t) error
 pkg syscall (linux-amd64), func Statfs(string, *Statfs_t) error
-pkg syscall (linux-amd64), func StringSlicePtr([]string) []*byte
-pkg syscall (linux-amd64), func Symlink(string, string) error
+pkg syscall (linux-amd64), func StringSlicePtr([]string) []*uint8
 pkg syscall (linux-amd64), func Sync()
 pkg syscall (linux-amd64), func SyncFileRange(int, int64, int64, int) error
+pkg syscall (linux-amd64), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-amd64), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (linux-amd64), func Sysinfo(*Sysinfo_t) error
 pkg syscall (linux-amd64), func Tee(int, int, int, int) (int64, error)
 pkg syscall (linux-amd64), func Tgkill(int, int, Signal) error
@@ -23330,15 +23321,15 @@ pkg syscall (linux-amd64), func TimevalToNsec(Timeval) int64
 pkg syscall (linux-amd64), func Truncate(string, int64) error
 pkg syscall (linux-amd64), func Umask(int) int
 pkg syscall (linux-amd64), func Uname(*Utsname) error
-pkg syscall (linux-amd64), func UnixCredentials(*Ucred) []byte
-pkg syscall (linux-amd64), func UnixRights(...int) []byte
+pkg syscall (linux-amd64), func UnixCredentials(*Ucred) []uint8
+pkg syscall (linux-amd64), func UnixRights(...int) []uint8
 pkg syscall (linux-amd64), func Unlinkat(int, string) error
 pkg syscall (linux-amd64), func Unmount(string, int) error
 pkg syscall (linux-amd64), func Unshare(int) error
 pkg syscall (linux-amd64), func Ustat(int, *Ustat_t) error
 pkg syscall (linux-amd64), func Utime(string, *Utimbuf) error
 pkg syscall (linux-amd64), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (linux-amd64), func Write(int, []byte) (int, error)
+pkg syscall (linux-amd64), func Write(int, []uint8) (int, error)
 pkg syscall (linux-amd64), method (*Cmsghdr) SetLen(int)
 pkg syscall (linux-amd64), method (*Iovec) SetLen(int)
 pkg syscall (linux-amd64), method (*Msghdr) SetControllen(int)
@@ -23348,7 +23339,7 @@ pkg syscall (linux-amd64), type Cmsghdr struct
 pkg syscall (linux-amd64), type Cmsghdr struct, Len uint64
 pkg syscall (linux-amd64), type Cmsghdr struct, Level int32
 pkg syscall (linux-amd64), type Cmsghdr struct, Type int32
-pkg syscall (linux-amd64), type Cmsghdr struct, X__cmsg_data [0]byte
+pkg syscall (linux-amd64), type Cmsghdr struct, X__cmsg_data [0]uint8
 pkg syscall (linux-amd64), type Credential struct
 pkg syscall (linux-amd64), type Credential struct, Gid uint32
 pkg syscall (linux-amd64), type Credential struct, Groups []uint32
@@ -23357,7 +23348,7 @@ pkg syscall (linux-amd64), type Dirent struct
 pkg syscall (linux-amd64), type Dirent struct, Ino uint64
 pkg syscall (linux-amd64), type Dirent struct, Name [256]int8
 pkg syscall (linux-amd64), type Dirent struct, Off int64
-pkg syscall (linux-amd64), type Dirent struct, Pad_cgo_0 [5]byte
+pkg syscall (linux-amd64), type Dirent struct, Pad_cgo_0 [5]uint8
 pkg syscall (linux-amd64), type Dirent struct, Reclen uint16
 pkg syscall (linux-amd64), type Dirent struct, Type uint8
 pkg syscall (linux-amd64), type EpollEvent struct
@@ -23369,9 +23360,9 @@ pkg syscall (linux-amd64), type FdSet struct, Bits [16]int64
 pkg syscall (linux-amd64), type Fsid struct
 pkg syscall (linux-amd64), type Fsid struct, X__val [2]int32
 pkg syscall (linux-amd64), type IPMreqn struct
-pkg syscall (linux-amd64), type IPMreqn struct, Address [4]byte
+pkg syscall (linux-amd64), type IPMreqn struct, Address [4]uint8
 pkg syscall (linux-amd64), type IPMreqn struct, Ifindex int32
-pkg syscall (linux-amd64), type IPMreqn struct, Multiaddr [4]byte
+pkg syscall (linux-amd64), type IPMreqn struct, Multiaddr [4]uint8
 pkg syscall (linux-amd64), type IfAddrmsg struct
 pkg syscall (linux-amd64), type IfAddrmsg struct, Family uint8
 pkg syscall (linux-amd64), type IfAddrmsg struct, Flags uint8
@@ -23386,37 +23377,37 @@ pkg syscall (linux-amd64), type IfInfomsg struct, Index int32
 pkg syscall (linux-amd64), type IfInfomsg struct, Type uint16
 pkg syscall (linux-amd64), type IfInfomsg struct, X__ifi_pad uint8
 pkg syscall (linux-amd64), type Inet4Pktinfo struct
-pkg syscall (linux-amd64), type Inet4Pktinfo struct, Addr [4]byte
+pkg syscall (linux-amd64), type Inet4Pktinfo struct, Addr [4]uint8
 pkg syscall (linux-amd64), type Inet4Pktinfo struct, Ifindex int32
-pkg syscall (linux-amd64), type Inet4Pktinfo struct, Spec_dst [4]byte
+pkg syscall (linux-amd64), type Inet4Pktinfo struct, Spec_dst [4]uint8
 pkg syscall (linux-amd64), type Inet6Pktinfo struct
-pkg syscall (linux-amd64), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (linux-amd64), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (linux-amd64), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (linux-amd64), type InotifyEvent struct
 pkg syscall (linux-amd64), type InotifyEvent struct, Cookie uint32
 pkg syscall (linux-amd64), type InotifyEvent struct, Len uint32
 pkg syscall (linux-amd64), type InotifyEvent struct, Mask uint32
-pkg syscall (linux-amd64), type InotifyEvent struct, Name [0]byte
+pkg syscall (linux-amd64), type InotifyEvent struct, Name [0]uint8
 pkg syscall (linux-amd64), type InotifyEvent struct, Wd int32
 pkg syscall (linux-amd64), type Iovec struct
-pkg syscall (linux-amd64), type Iovec struct, Base *byte
+pkg syscall (linux-amd64), type Iovec struct, Base *uint8
 pkg syscall (linux-amd64), type Iovec struct, Len uint64
 pkg syscall (linux-amd64), type Msghdr struct
-pkg syscall (linux-amd64), type Msghdr struct, Control *byte
+pkg syscall (linux-amd64), type Msghdr struct, Control *uint8
 pkg syscall (linux-amd64), type Msghdr struct, Controllen uint64
 pkg syscall (linux-amd64), type Msghdr struct, Flags int32
 pkg syscall (linux-amd64), type Msghdr struct, Iov *Iovec
 pkg syscall (linux-amd64), type Msghdr struct, Iovlen uint64
-pkg syscall (linux-amd64), type Msghdr struct, Name *byte
+pkg syscall (linux-amd64), type Msghdr struct, Name *uint8
 pkg syscall (linux-amd64), type Msghdr struct, Namelen uint32
-pkg syscall (linux-amd64), type Msghdr struct, Pad_cgo_0 [4]byte
-pkg syscall (linux-amd64), type Msghdr struct, Pad_cgo_1 [4]byte
+pkg syscall (linux-amd64), type Msghdr struct, Pad_cgo_0 [4]uint8
+pkg syscall (linux-amd64), type Msghdr struct, Pad_cgo_1 [4]uint8
 pkg syscall (linux-amd64), type NetlinkMessage struct
-pkg syscall (linux-amd64), type NetlinkMessage struct, Data []byte
+pkg syscall (linux-amd64), type NetlinkMessage struct, Data []uint8
 pkg syscall (linux-amd64), type NetlinkMessage struct, Header NlMsghdr
 pkg syscall (linux-amd64), type NetlinkRouteAttr struct
 pkg syscall (linux-amd64), type NetlinkRouteAttr struct, Attr RtAttr
-pkg syscall (linux-amd64), type NetlinkRouteAttr struct, Value []byte
+pkg syscall (linux-amd64), type NetlinkRouteAttr struct, Value []uint8
 pkg syscall (linux-amd64), type NetlinkRouteRequest struct
 pkg syscall (linux-amd64), type NetlinkRouteRequest struct, Data RtGenmsg
 pkg syscall (linux-amd64), type NetlinkRouteRequest struct, Header NlMsghdr
@@ -23466,7 +23457,7 @@ pkg syscall (linux-amd64), type RawSockaddrAny struct, Pad [96]int8
 pkg syscall (linux-amd64), type RawSockaddrInet4 struct, Family uint16
 pkg syscall (linux-amd64), type RawSockaddrInet4 struct, Zero [8]uint8
 pkg syscall (linux-amd64), type RawSockaddrInet6 struct
-pkg syscall (linux-amd64), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (linux-amd64), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (linux-amd64), type RawSockaddrInet6 struct, Family uint16
 pkg syscall (linux-amd64), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (linux-amd64), type RawSockaddrInet6 struct, Port uint16
@@ -23534,9 +23525,9 @@ pkg syscall (linux-amd64), type SockFilter struct, K uint32
 pkg syscall (linux-amd64), type SockFprog struct
 pkg syscall (linux-amd64), type SockFprog struct, Filter *SockFilter
 pkg syscall (linux-amd64), type SockFprog struct, Len uint16
-pkg syscall (linux-amd64), type SockFprog struct, Pad_cgo_0 [6]byte
+pkg syscall (linux-amd64), type SockFprog struct, Pad_cgo_0 [6]uint8
 pkg syscall (linux-amd64), type SockaddrLinklayer struct
-pkg syscall (linux-amd64), type SockaddrLinklayer struct, Addr [8]byte
+pkg syscall (linux-amd64), type SockaddrLinklayer struct, Addr [8]uint8
 pkg syscall (linux-amd64), type SockaddrLinklayer struct, Halen uint8
 pkg syscall (linux-amd64), type SockaddrLinklayer struct, Hatype uint16
 pkg syscall (linux-amd64), type SockaddrLinklayer struct, Ifindex int
@@ -23548,7 +23539,7 @@ pkg syscall (linux-amd64), type SockaddrNetlink struct, Groups uint32
 pkg syscall (linux-amd64), type SockaddrNetlink struct, Pad uint16
 pkg syscall (linux-amd64), type SockaddrNetlink struct, Pid uint32
 pkg syscall (linux-amd64), type SocketControlMessage struct
-pkg syscall (linux-amd64), type SocketControlMessage struct, Data []byte
+pkg syscall (linux-amd64), type SocketControlMessage struct, Data []uint8
 pkg syscall (linux-amd64), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (linux-amd64), type Stat_t struct
 pkg syscall (linux-amd64), type Stat_t struct, Atim Timespec
@@ -23594,8 +23585,8 @@ pkg syscall (linux-amd64), type Sysinfo_t struct, Freeram uint64
 pkg syscall (linux-amd64), type Sysinfo_t struct, Freeswap uint64
 pkg syscall (linux-amd64), type Sysinfo_t struct, Loads [3]uint64
 pkg syscall (linux-amd64), type Sysinfo_t struct, Pad uint16
-pkg syscall (linux-amd64), type Sysinfo_t struct, Pad_cgo_0 [4]byte
-pkg syscall (linux-amd64), type Sysinfo_t struct, Pad_cgo_1 [4]byte
+pkg syscall (linux-amd64), type Sysinfo_t struct, Pad_cgo_0 [4]uint8
+pkg syscall (linux-amd64), type Sysinfo_t struct, Pad_cgo_1 [4]uint8
 pkg syscall (linux-amd64), type Sysinfo_t struct, Procs uint16
 pkg syscall (linux-amd64), type Sysinfo_t struct, Sharedram uint64
 pkg syscall (linux-amd64), type Sysinfo_t struct, Totalhigh uint64
@@ -23603,7 +23594,7 @@ pkg syscall (linux-amd64), type Sysinfo_t struct, Totalram uint64
 pkg syscall (linux-amd64), type Sysinfo_t struct, Totalswap uint64
 pkg syscall (linux-amd64), type Sysinfo_t struct, Unit uint32
 pkg syscall (linux-amd64), type Sysinfo_t struct, Uptime int64
-pkg syscall (linux-amd64), type Sysinfo_t struct, X_f [0]byte
+pkg syscall (linux-amd64), type Sysinfo_t struct, X_f [0]uint8
 pkg syscall (linux-amd64), type Termios struct
 pkg syscall (linux-amd64), type Termios struct, Cc [32]uint8
 pkg syscall (linux-amd64), type Termios struct, Cflag uint32
@@ -23613,7 +23604,7 @@ pkg syscall (linux-amd64), type Termios struct, Lflag uint32
 pkg syscall (linux-amd64), type Termios struct, Line uint8
 pkg syscall (linux-amd64), type Termios struct, Oflag uint32
 pkg syscall (linux-amd64), type Termios struct, Ospeed uint32
-pkg syscall (linux-amd64), type Termios struct, Pad_cgo_0 [3]byte
+pkg syscall (linux-amd64), type Termios struct, Pad_cgo_0 [3]uint8
 pkg syscall (linux-amd64), type Time_t int64
 pkg syscall (linux-amd64), type Timespec struct, Nsec int64
 pkg syscall (linux-amd64), type Timespec struct, Sec int64
@@ -23630,10 +23621,10 @@ pkg syscall (linux-amd64), type Timex struct, Jitter int64
 pkg syscall (linux-amd64), type Timex struct, Maxerror int64
 pkg syscall (linux-amd64), type Timex struct, Modes uint32
 pkg syscall (linux-amd64), type Timex struct, Offset int64
-pkg syscall (linux-amd64), type Timex struct, Pad_cgo_0 [4]byte
-pkg syscall (linux-amd64), type Timex struct, Pad_cgo_1 [4]byte
-pkg syscall (linux-amd64), type Timex struct, Pad_cgo_2 [4]byte
-pkg syscall (linux-amd64), type Timex struct, Pad_cgo_3 [44]byte
+pkg syscall (linux-amd64), type Timex struct, Pad_cgo_0 [4]uint8
+pkg syscall (linux-amd64), type Timex struct, Pad_cgo_1 [4]uint8
+pkg syscall (linux-amd64), type Timex struct, Pad_cgo_2 [4]uint8
+pkg syscall (linux-amd64), type Timex struct, Pad_cgo_3 [44]uint8
 pkg syscall (linux-amd64), type Timex struct, Ppsfreq int64
 pkg syscall (linux-amd64), type Timex struct, Precision int64
 pkg syscall (linux-amd64), type Timex struct, Shift int32
@@ -23656,8 +23647,8 @@ pkg syscall (linux-amd64), type Ucred struct, Uid uint32
 pkg syscall (linux-amd64), type Ustat_t struct
 pkg syscall (linux-amd64), type Ustat_t struct, Fname [6]int8
 pkg syscall (linux-amd64), type Ustat_t struct, Fpack [6]int8
-pkg syscall (linux-amd64), type Ustat_t struct, Pad_cgo_0 [4]byte
-pkg syscall (linux-amd64), type Ustat_t struct, Pad_cgo_1 [4]byte
+pkg syscall (linux-amd64), type Ustat_t struct, Pad_cgo_0 [4]uint8
+pkg syscall (linux-amd64), type Ustat_t struct, Pad_cgo_1 [4]uint8
 pkg syscall (linux-amd64), type Ustat_t struct, Tfree int32
 pkg syscall (linux-amd64), type Ustat_t struct, Tinode uint64
 pkg syscall (linux-amd64), type Utimbuf struct
@@ -25370,19 +25361,19 @@ pkg syscall (linux-amd64-cgo), func Fsync(int) error
 pkg syscall (linux-amd64-cgo), func Ftruncate(int, int64) error
 pkg syscall (linux-amd64-cgo), func Futimes(int, []Timeval) error
 pkg syscall (linux-amd64-cgo), func Futimesat(int, string, []Timeval) error
-pkg syscall (linux-amd64-cgo), func Getcwd([]byte) (int, error)
-pkg syscall (linux-amd64-cgo), func Getdents(int, []byte) (int, error)
+pkg syscall (linux-amd64-cgo), func Getcwd([]uint8) (int, error)
+pkg syscall (linux-amd64-cgo), func Getdents(int, []uint8) (int, error)
 pkg syscall (linux-amd64-cgo), func Getpeername(int) (Sockaddr, error)
 pkg syscall (linux-amd64-cgo), func Getpgid(int) (int, error)
 pkg syscall (linux-amd64-cgo), func Getpgrp() int
 pkg syscall (linux-amd64-cgo), func Getrlimit(int, *Rlimit) error
 pkg syscall (linux-amd64-cgo), func Getrusage(int, *Rusage) error
 pkg syscall (linux-amd64-cgo), func Getsockname(int) (Sockaddr, error)
-pkg syscall (linux-amd64-cgo), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (linux-amd64-cgo), func GetsockoptIPMreqn(int) (*IPMreqn, error)
-pkg syscall (linux-amd64-cgo), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (linux-amd64-cgo), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (linux-amd64-cgo), func GetsockoptInt(int) (int, error)
+pkg syscall (linux-amd64-cgo), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (linux-amd64-cgo), func GetsockoptIPMreqn(int, int, int) (*IPMreqn, error)
+pkg syscall (linux-amd64-cgo), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (linux-amd64-cgo), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (linux-amd64-cgo), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (linux-amd64-cgo), func Gettid() int
 pkg syscall (linux-amd64-cgo), func InotifyAddWatch(int, string, uint32) (int, error)
 pkg syscall (linux-amd64-cgo), func InotifyInit() (int, error)
@@ -25391,76 +25382,74 @@ pkg syscall (linux-amd64-cgo), func InotifyRmWatch(int, uint32) (int, error)
 pkg syscall (linux-amd64-cgo), func Ioperm(int, int, int) error
 pkg syscall (linux-amd64-cgo), func Iopl(int) error
 pkg syscall (linux-amd64-cgo), func Kill(int, Signal) error
-pkg syscall (linux-amd64-cgo), func Klogctl(int, []byte) (int, error)
-pkg syscall (linux-amd64-cgo), func Link(string, string) error
+pkg syscall (linux-amd64-cgo), func Klogctl(int, []uint8) (int, error)
 pkg syscall (linux-amd64-cgo), func Listen(int, int) error
-pkg syscall (linux-amd64-cgo), func LsfJump(int) *SockFilter
-pkg syscall (linux-amd64-cgo), func LsfSocket(int) (int, error)
-pkg syscall (linux-amd64-cgo), func LsfStmt(int) *SockFilter
+pkg syscall (linux-amd64-cgo), func LsfJump(int, int, int, int) *SockFilter
+pkg syscall (linux-amd64-cgo), func LsfSocket(int, int) (int, error)
+pkg syscall (linux-amd64-cgo), func LsfStmt(int, int) *SockFilter
 pkg syscall (linux-amd64-cgo), func Lstat(string, *Stat_t) error
-pkg syscall (linux-amd64-cgo), func Madvise([]byte, int) error
+pkg syscall (linux-amd64-cgo), func Madvise([]uint8, int) error
 pkg syscall (linux-amd64-cgo), func Mkdirat(int, string, uint32) error
 pkg syscall (linux-amd64-cgo), func Mkfifo(string, uint32) error
 pkg syscall (linux-amd64-cgo), func Mknod(string, uint32, int) error
 pkg syscall (linux-amd64-cgo), func Mknodat(int, string, uint32, int) error
-pkg syscall (linux-amd64-cgo), func Mlock([]byte) error
+pkg syscall (linux-amd64-cgo), func Mlock([]uint8) error
 pkg syscall (linux-amd64-cgo), func Mlockall(int) error
-pkg syscall (linux-amd64-cgo), func Mmap(int, int64, int, int, int) ([]byte, error)
+pkg syscall (linux-amd64-cgo), func Mmap(int, int64, int, int, int) ([]uint8, error)
 pkg syscall (linux-amd64-cgo), func Mount(string, string, string, uintptr, string) error
-pkg syscall (linux-amd64-cgo), func Mprotect([]byte, int) error
-pkg syscall (linux-amd64-cgo), func Munlock([]byte) error
+pkg syscall (linux-amd64-cgo), func Mprotect([]uint8, int) error
+pkg syscall (linux-amd64-cgo), func Munlock([]uint8) error
 pkg syscall (linux-amd64-cgo), func Munlockall() error
-pkg syscall (linux-amd64-cgo), func Munmap([]byte) error
+pkg syscall (linux-amd64-cgo), func Munmap([]uint8) error
 pkg syscall (linux-amd64-cgo), func Nanosleep(*Timespec, *Timespec) error
-pkg syscall (linux-amd64-cgo), func NetlinkRIB(int) ([]byte, error)
+pkg syscall (linux-amd64-cgo), func NetlinkRIB(int, int) ([]uint8, error)
 pkg syscall (linux-amd64-cgo), func NsecToTimespec(int64) Timespec
 pkg syscall (linux-amd64-cgo), func Open(string, int, uint32) (int, error)
 pkg syscall (linux-amd64-cgo), func Openat(int, string, int, uint32) (int, error)
-pkg syscall (linux-amd64-cgo), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (linux-amd64-cgo), func ParseNetlinkMessage([]byte) ([]NetlinkMessage, error)
+pkg syscall (linux-amd64-cgo), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (linux-amd64-cgo), func ParseNetlinkMessage([]uint8) ([]NetlinkMessage, error)
 pkg syscall (linux-amd64-cgo), func ParseNetlinkRouteAttr(*NetlinkMessage) ([]NetlinkRouteAttr, error)
-pkg syscall (linux-amd64-cgo), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (linux-amd64-cgo), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (linux-amd64-cgo), func ParseUnixCredentials(*SocketControlMessage) (*Ucred, error)
 pkg syscall (linux-amd64-cgo), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (linux-amd64-cgo), func Pause() error
 pkg syscall (linux-amd64-cgo), func Pipe([]int) error
 pkg syscall (linux-amd64-cgo), func PivotRoot(string, string) error
-pkg syscall (linux-amd64-cgo), func Pread(int, []byte, int64) (int, error)
+pkg syscall (linux-amd64-cgo), func Pread(int, []uint8, int64) (int, error)
 pkg syscall (linux-amd64-cgo), func PtraceAttach(int) error
 pkg syscall (linux-amd64-cgo), func PtraceCont(int, int) error
 pkg syscall (linux-amd64-cgo), func PtraceDetach(int) error
 pkg syscall (linux-amd64-cgo), func PtraceGetEventMsg(int) (uint, error)
 pkg syscall (linux-amd64-cgo), func PtraceGetRegs(int, *PtraceRegs) error
-pkg syscall (linux-amd64-cgo), func PtracePeekData(int, uintptr, []byte) (int, error)
-pkg syscall (linux-amd64-cgo), func PtracePeekText(int, uintptr, []byte) (int, error)
-pkg syscall (linux-amd64-cgo), func PtracePokeData(int, uintptr, []byte) (int, error)
-pkg syscall (linux-amd64-cgo), func PtracePokeText(int, uintptr, []byte) (int, error)
+pkg syscall (linux-amd64-cgo), func PtracePeekData(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-amd64-cgo), func PtracePeekText(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-amd64-cgo), func PtracePokeData(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-amd64-cgo), func PtracePokeText(int, uintptr, []uint8) (int, error)
 pkg syscall (linux-amd64-cgo), func PtraceSetOptions(int, int) error
 pkg syscall (linux-amd64-cgo), func PtraceSetRegs(int, *PtraceRegs) error
 pkg syscall (linux-amd64-cgo), func PtraceSingleStep(int) error
-pkg syscall (linux-amd64-cgo), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (linux-amd64-cgo), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (linux-amd64-cgo), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (linux-amd64-cgo), func Read(int, []byte) (int, error)
-pkg syscall (linux-amd64-cgo), func ReadDirent(int, []byte) (int, error)
+pkg syscall (linux-amd64-cgo), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (linux-amd64-cgo), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-amd64-cgo), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-amd64-cgo), func Read(int, []uint8) (int, error)
+pkg syscall (linux-amd64-cgo), func ReadDirent(int, []uint8) (int, error)
 pkg syscall (linux-amd64-cgo), func Reboot(int) error
-pkg syscall (linux-amd64-cgo), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (linux-amd64-cgo), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (linux-amd64-cgo), func Rename(string, string) error
+pkg syscall (linux-amd64-cgo), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (linux-amd64-cgo), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (linux-amd64-cgo), func Renameat(int, string, int, string) error
 pkg syscall (linux-amd64-cgo), func Seek(int, int64, int) (int64, error)
 pkg syscall (linux-amd64-cgo), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) (int, error)
 pkg syscall (linux-amd64-cgo), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (linux-amd64-cgo), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (linux-amd64-cgo), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (linux-amd64-cgo), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (linux-amd64-cgo), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (linux-amd64-cgo), func SetLsfPromisc(string, bool) error
 pkg syscall (linux-amd64-cgo), func SetNonblock(int, bool) error
-pkg syscall (linux-amd64-cgo), func Setdomainname([]byte) error
+pkg syscall (linux-amd64-cgo), func Setdomainname([]uint8) error
 pkg syscall (linux-amd64-cgo), func Setfsgid(int) error
 pkg syscall (linux-amd64-cgo), func Setfsuid(int) error
 pkg syscall (linux-amd64-cgo), func Setgid(int) error
 pkg syscall (linux-amd64-cgo), func Setgroups([]int) error
-pkg syscall (linux-amd64-cgo), func Sethostname([]byte) error
+pkg syscall (linux-amd64-cgo), func Sethostname([]uint8) error
 pkg syscall (linux-amd64-cgo), func Setpgid(int, int) error
 pkg syscall (linux-amd64-cgo), func Setregid(int, int) error
 pkg syscall (linux-amd64-cgo), func Setresgid(int, int, int) error
@@ -25468,26 +25457,27 @@ pkg syscall (linux-amd64-cgo), func Setresuid(int, int, int) error
 pkg syscall (linux-amd64-cgo), func Setreuid(int, int) error
 pkg syscall (linux-amd64-cgo), func Setrlimit(int, *Rlimit) error
 pkg syscall (linux-amd64-cgo), func Setsid() (int, error)
-pkg syscall (linux-amd64-cgo), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (linux-amd64-cgo), func SetsockoptIPMreqn(int, *IPMreqn) error
-pkg syscall (linux-amd64-cgo), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (linux-amd64-cgo), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (linux-amd64-cgo), func SetsockoptInt(int, int) error
-pkg syscall (linux-amd64-cgo), func SetsockoptLinger(int, *Linger) error
-pkg syscall (linux-amd64-cgo), func SetsockoptString(int, string) error
-pkg syscall (linux-amd64-cgo), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (linux-amd64-cgo), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (linux-amd64-cgo), func SetsockoptIPMreqn(int, int, int, *IPMreqn) error
+pkg syscall (linux-amd64-cgo), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (linux-amd64-cgo), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (linux-amd64-cgo), func SetsockoptInt(int, int, int, int) error
+pkg syscall (linux-amd64-cgo), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (linux-amd64-cgo), func SetsockoptString(int, int, int, string) error
+pkg syscall (linux-amd64-cgo), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (linux-amd64-cgo), func Settimeofday(*Timeval) error
 pkg syscall (linux-amd64-cgo), func Setuid(int) error
 pkg syscall (linux-amd64-cgo), func Shutdown(int, int) error
-pkg syscall (linux-amd64-cgo), func Socket(int) (int, error)
-pkg syscall (linux-amd64-cgo), func Socketpair(int) ([2]int, error)
+pkg syscall (linux-amd64-cgo), func Socket(int, int, int) (int, error)
+pkg syscall (linux-amd64-cgo), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (linux-amd64-cgo), func Splice(int, *int64, int, *int64, int, int) (int64, error)
 pkg syscall (linux-amd64-cgo), func Stat(string, *Stat_t) error
 pkg syscall (linux-amd64-cgo), func Statfs(string, *Statfs_t) error
-pkg syscall (linux-amd64-cgo), func StringSlicePtr([]string) []*byte
-pkg syscall (linux-amd64-cgo), func Symlink(string, string) error
+pkg syscall (linux-amd64-cgo), func StringSlicePtr([]string) []*uint8
 pkg syscall (linux-amd64-cgo), func Sync()
 pkg syscall (linux-amd64-cgo), func SyncFileRange(int, int64, int64, int) error
+pkg syscall (linux-amd64-cgo), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-amd64-cgo), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (linux-amd64-cgo), func Sysinfo(*Sysinfo_t) error
 pkg syscall (linux-amd64-cgo), func Tee(int, int, int, int) (int64, error)
 pkg syscall (linux-amd64-cgo), func Tgkill(int, int, Signal) error
@@ -25498,15 +25488,15 @@ pkg syscall (linux-amd64-cgo), func TimevalToNsec(Timeval) int64
 pkg syscall (linux-amd64-cgo), func Truncate(string, int64) error
 pkg syscall (linux-amd64-cgo), func Umask(int) int
 pkg syscall (linux-amd64-cgo), func Uname(*Utsname) error
-pkg syscall (linux-amd64-cgo), func UnixCredentials(*Ucred) []byte
-pkg syscall (linux-amd64-cgo), func UnixRights(...int) []byte
+pkg syscall (linux-amd64-cgo), func UnixCredentials(*Ucred) []uint8
+pkg syscall (linux-amd64-cgo), func UnixRights(...int) []uint8
 pkg syscall (linux-amd64-cgo), func Unlinkat(int, string) error
 pkg syscall (linux-amd64-cgo), func Unmount(string, int) error
 pkg syscall (linux-amd64-cgo), func Unshare(int) error
 pkg syscall (linux-amd64-cgo), func Ustat(int, *Ustat_t) error
 pkg syscall (linux-amd64-cgo), func Utime(string, *Utimbuf) error
 pkg syscall (linux-amd64-cgo), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (linux-amd64-cgo), func Write(int, []byte) (int, error)
+pkg syscall (linux-amd64-cgo), func Write(int, []uint8) (int, error)
 pkg syscall (linux-amd64-cgo), method (*Cmsghdr) SetLen(int)
 pkg syscall (linux-amd64-cgo), method (*Iovec) SetLen(int)
 pkg syscall (linux-amd64-cgo), method (*Msghdr) SetControllen(int)
@@ -25516,7 +25506,7 @@ pkg syscall (linux-amd64-cgo), type Cmsghdr struct
 pkg syscall (linux-amd64-cgo), type Cmsghdr struct, Len uint64
 pkg syscall (linux-amd64-cgo), type Cmsghdr struct, Level int32
 pkg syscall (linux-amd64-cgo), type Cmsghdr struct, Type int32
-pkg syscall (linux-amd64-cgo), type Cmsghdr struct, X__cmsg_data [0]byte
+pkg syscall (linux-amd64-cgo), type Cmsghdr struct, X__cmsg_data [0]uint8
 pkg syscall (linux-amd64-cgo), type Credential struct
 pkg syscall (linux-amd64-cgo), type Credential struct, Gid uint32
 pkg syscall (linux-amd64-cgo), type Credential struct, Groups []uint32
@@ -25525,7 +25515,7 @@ pkg syscall (linux-amd64-cgo), type Dirent struct
 pkg syscall (linux-amd64-cgo), type Dirent struct, Ino uint64
 pkg syscall (linux-amd64-cgo), type Dirent struct, Name [256]int8
 pkg syscall (linux-amd64-cgo), type Dirent struct, Off int64
-pkg syscall (linux-amd64-cgo), type Dirent struct, Pad_cgo_0 [5]byte
+pkg syscall (linux-amd64-cgo), type Dirent struct, Pad_cgo_0 [5]uint8
 pkg syscall (linux-amd64-cgo), type Dirent struct, Reclen uint16
 pkg syscall (linux-amd64-cgo), type Dirent struct, Type uint8
 pkg syscall (linux-amd64-cgo), type EpollEvent struct
@@ -25537,9 +25527,9 @@ pkg syscall (linux-amd64-cgo), type FdSet struct, Bits [16]int64
 pkg syscall (linux-amd64-cgo), type Fsid struct
 pkg syscall (linux-amd64-cgo), type Fsid struct, X__val [2]int32
 pkg syscall (linux-amd64-cgo), type IPMreqn struct
-pkg syscall (linux-amd64-cgo), type IPMreqn struct, Address [4]byte
+pkg syscall (linux-amd64-cgo), type IPMreqn struct, Address [4]uint8
 pkg syscall (linux-amd64-cgo), type IPMreqn struct, Ifindex int32
-pkg syscall (linux-amd64-cgo), type IPMreqn struct, Multiaddr [4]byte
+pkg syscall (linux-amd64-cgo), type IPMreqn struct, Multiaddr [4]uint8
 pkg syscall (linux-amd64-cgo), type IfAddrmsg struct
 pkg syscall (linux-amd64-cgo), type IfAddrmsg struct, Family uint8
 pkg syscall (linux-amd64-cgo), type IfAddrmsg struct, Flags uint8
@@ -25554,37 +25544,37 @@ pkg syscall (linux-amd64-cgo), type IfInfomsg struct, Index int32
 pkg syscall (linux-amd64-cgo), type IfInfomsg struct, Type uint16
 pkg syscall (linux-amd64-cgo), type IfInfomsg struct, X__ifi_pad uint8
 pkg syscall (linux-amd64-cgo), type Inet4Pktinfo struct
-pkg syscall (linux-amd64-cgo), type Inet4Pktinfo struct, Addr [4]byte
+pkg syscall (linux-amd64-cgo), type Inet4Pktinfo struct, Addr [4]uint8
 pkg syscall (linux-amd64-cgo), type Inet4Pktinfo struct, Ifindex int32
-pkg syscall (linux-amd64-cgo), type Inet4Pktinfo struct, Spec_dst [4]byte
+pkg syscall (linux-amd64-cgo), type Inet4Pktinfo struct, Spec_dst [4]uint8
 pkg syscall (linux-amd64-cgo), type Inet6Pktinfo struct
-pkg syscall (linux-amd64-cgo), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (linux-amd64-cgo), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (linux-amd64-cgo), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (linux-amd64-cgo), type InotifyEvent struct
 pkg syscall (linux-amd64-cgo), type InotifyEvent struct, Cookie uint32
 pkg syscall (linux-amd64-cgo), type InotifyEvent struct, Len uint32
 pkg syscall (linux-amd64-cgo), type InotifyEvent struct, Mask uint32
-pkg syscall (linux-amd64-cgo), type InotifyEvent struct, Name [0]byte
+pkg syscall (linux-amd64-cgo), type InotifyEvent struct, Name [0]uint8
 pkg syscall (linux-amd64-cgo), type InotifyEvent struct, Wd int32
 pkg syscall (linux-amd64-cgo), type Iovec struct
-pkg syscall (linux-amd64-cgo), type Iovec struct, Base *byte
+pkg syscall (linux-amd64-cgo), type Iovec struct, Base *uint8
 pkg syscall (linux-amd64-cgo), type Iovec struct, Len uint64
 pkg syscall (linux-amd64-cgo), type Msghdr struct
-pkg syscall (linux-amd64-cgo), type Msghdr struct, Control *byte
+pkg syscall (linux-amd64-cgo), type Msghdr struct, Control *uint8
 pkg syscall (linux-amd64-cgo), type Msghdr struct, Controllen uint64
 pkg syscall (linux-amd64-cgo), type Msghdr struct, Flags int32
 pkg syscall (linux-amd64-cgo), type Msghdr struct, Iov *Iovec
 pkg syscall (linux-amd64-cgo), type Msghdr struct, Iovlen uint64
-pkg syscall (linux-amd64-cgo), type Msghdr struct, Name *byte
+pkg syscall (linux-amd64-cgo), type Msghdr struct, Name *uint8
 pkg syscall (linux-amd64-cgo), type Msghdr struct, Namelen uint32
-pkg syscall (linux-amd64-cgo), type Msghdr struct, Pad_cgo_0 [4]byte
-pkg syscall (linux-amd64-cgo), type Msghdr struct, Pad_cgo_1 [4]byte
+pkg syscall (linux-amd64-cgo), type Msghdr struct, Pad_cgo_0 [4]uint8
+pkg syscall (linux-amd64-cgo), type Msghdr struct, Pad_cgo_1 [4]uint8
 pkg syscall (linux-amd64-cgo), type NetlinkMessage struct
-pkg syscall (linux-amd64-cgo), type NetlinkMessage struct, Data []byte
+pkg syscall (linux-amd64-cgo), type NetlinkMessage struct, Data []uint8
 pkg syscall (linux-amd64-cgo), type NetlinkMessage struct, Header NlMsghdr
 pkg syscall (linux-amd64-cgo), type NetlinkRouteAttr struct
 pkg syscall (linux-amd64-cgo), type NetlinkRouteAttr struct, Attr RtAttr
-pkg syscall (linux-amd64-cgo), type NetlinkRouteAttr struct, Value []byte
+pkg syscall (linux-amd64-cgo), type NetlinkRouteAttr struct, Value []uint8
 pkg syscall (linux-amd64-cgo), type NetlinkRouteRequest struct
 pkg syscall (linux-amd64-cgo), type NetlinkRouteRequest struct, Data RtGenmsg
 pkg syscall (linux-amd64-cgo), type NetlinkRouteRequest struct, Header NlMsghdr
@@ -25634,7 +25624,7 @@ pkg syscall (linux-amd64-cgo), type RawSockaddrAny struct, Pad [96]int8
 pkg syscall (linux-amd64-cgo), type RawSockaddrInet4 struct, Family uint16
 pkg syscall (linux-amd64-cgo), type RawSockaddrInet4 struct, Zero [8]uint8
 pkg syscall (linux-amd64-cgo), type RawSockaddrInet6 struct
-pkg syscall (linux-amd64-cgo), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (linux-amd64-cgo), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (linux-amd64-cgo), type RawSockaddrInet6 struct, Family uint16
 pkg syscall (linux-amd64-cgo), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (linux-amd64-cgo), type RawSockaddrInet6 struct, Port uint16
@@ -25702,9 +25692,9 @@ pkg syscall (linux-amd64-cgo), type SockFilter struct, K uint32
 pkg syscall (linux-amd64-cgo), type SockFprog struct
 pkg syscall (linux-amd64-cgo), type SockFprog struct, Filter *SockFilter
 pkg syscall (linux-amd64-cgo), type SockFprog struct, Len uint16
-pkg syscall (linux-amd64-cgo), type SockFprog struct, Pad_cgo_0 [6]byte
+pkg syscall (linux-amd64-cgo), type SockFprog struct, Pad_cgo_0 [6]uint8
 pkg syscall (linux-amd64-cgo), type SockaddrLinklayer struct
-pkg syscall (linux-amd64-cgo), type SockaddrLinklayer struct, Addr [8]byte
+pkg syscall (linux-amd64-cgo), type SockaddrLinklayer struct, Addr [8]uint8
 pkg syscall (linux-amd64-cgo), type SockaddrLinklayer struct, Halen uint8
 pkg syscall (linux-amd64-cgo), type SockaddrLinklayer struct, Hatype uint16
 pkg syscall (linux-amd64-cgo), type SockaddrLinklayer struct, Ifindex int
@@ -25716,7 +25706,7 @@ pkg syscall (linux-amd64-cgo), type SockaddrNetlink struct, Groups uint32
 pkg syscall (linux-amd64-cgo), type SockaddrNetlink struct, Pad uint16
 pkg syscall (linux-amd64-cgo), type SockaddrNetlink struct, Pid uint32
 pkg syscall (linux-amd64-cgo), type SocketControlMessage struct
-pkg syscall (linux-amd64-cgo), type SocketControlMessage struct, Data []byte
+pkg syscall (linux-amd64-cgo), type SocketControlMessage struct, Data []uint8
 pkg syscall (linux-amd64-cgo), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (linux-amd64-cgo), type Stat_t struct
 pkg syscall (linux-amd64-cgo), type Stat_t struct, Atim Timespec
@@ -25762,8 +25752,8 @@ pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Freeram uint64
 pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Freeswap uint64
 pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Loads [3]uint64
 pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Pad uint16
-pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Pad_cgo_0 [4]byte
-pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Pad_cgo_1 [4]byte
+pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Pad_cgo_0 [4]uint8
+pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Pad_cgo_1 [4]uint8
 pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Procs uint16
 pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Sharedram uint64
 pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Totalhigh uint64
@@ -25771,7 +25761,7 @@ pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Totalram uint64
 pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Totalswap uint64
 pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Unit uint32
 pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, Uptime int64
-pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, X_f [0]byte
+pkg syscall (linux-amd64-cgo), type Sysinfo_t struct, X_f [0]uint8
 pkg syscall (linux-amd64-cgo), type Termios struct
 pkg syscall (linux-amd64-cgo), type Termios struct, Cc [32]uint8
 pkg syscall (linux-amd64-cgo), type Termios struct, Cflag uint32
@@ -25781,7 +25771,7 @@ pkg syscall (linux-amd64-cgo), type Termios struct, Lflag uint32
 pkg syscall (linux-amd64-cgo), type Termios struct, Line uint8
 pkg syscall (linux-amd64-cgo), type Termios struct, Oflag uint32
 pkg syscall (linux-amd64-cgo), type Termios struct, Ospeed uint32
-pkg syscall (linux-amd64-cgo), type Termios struct, Pad_cgo_0 [3]byte
+pkg syscall (linux-amd64-cgo), type Termios struct, Pad_cgo_0 [3]uint8
 pkg syscall (linux-amd64-cgo), type Time_t int64
 pkg syscall (linux-amd64-cgo), type Timespec struct, Nsec int64
 pkg syscall (linux-amd64-cgo), type Timespec struct, Sec int64
@@ -25798,10 +25788,10 @@ pkg syscall (linux-amd64-cgo), type Timex struct, Jitter int64
 pkg syscall (linux-amd64-cgo), type Timex struct, Maxerror int64
 pkg syscall (linux-amd64-cgo), type Timex struct, Modes uint32
 pkg syscall (linux-amd64-cgo), type Timex struct, Offset int64
-pkg syscall (linux-amd64-cgo), type Timex struct, Pad_cgo_0 [4]byte
-pkg syscall (linux-amd64-cgo), type Timex struct, Pad_cgo_1 [4]byte
-pkg syscall (linux-amd64-cgo), type Timex struct, Pad_cgo_2 [4]byte
-pkg syscall (linux-amd64-cgo), type Timex struct, Pad_cgo_3 [44]byte
+pkg syscall (linux-amd64-cgo), type Timex struct, Pad_cgo_0 [4]uint8
+pkg syscall (linux-amd64-cgo), type Timex struct, Pad_cgo_1 [4]uint8
+pkg syscall (linux-amd64-cgo), type Timex struct, Pad_cgo_2 [4]uint8
+pkg syscall (linux-amd64-cgo), type Timex struct, Pad_cgo_3 [44]uint8
 pkg syscall (linux-amd64-cgo), type Timex struct, Ppsfreq int64
 pkg syscall (linux-amd64-cgo), type Timex struct, Precision int64
 pkg syscall (linux-amd64-cgo), type Timex struct, Shift int32
@@ -25824,8 +25814,8 @@ pkg syscall (linux-amd64-cgo), type Ucred struct, Uid uint32
 pkg syscall (linux-amd64-cgo), type Ustat_t struct
 pkg syscall (linux-amd64-cgo), type Ustat_t struct, Fname [6]int8
 pkg syscall (linux-amd64-cgo), type Ustat_t struct, Fpack [6]int8
-pkg syscall (linux-amd64-cgo), type Ustat_t struct, Pad_cgo_0 [4]byte
-pkg syscall (linux-amd64-cgo), type Ustat_t struct, Pad_cgo_1 [4]byte
+pkg syscall (linux-amd64-cgo), type Ustat_t struct, Pad_cgo_0 [4]uint8
+pkg syscall (linux-amd64-cgo), type Ustat_t struct, Pad_cgo_1 [4]uint8
 pkg syscall (linux-amd64-cgo), type Ustat_t struct, Tfree int32
 pkg syscall (linux-amd64-cgo), type Ustat_t struct, Tinode uint64
 pkg syscall (linux-amd64-cgo), type Utimbuf struct
@@ -27594,95 +27584,93 @@ pkg syscall (linux-arm), func Fsync(int) error
 pkg syscall (linux-arm), func Ftruncate(int, int64) error
 pkg syscall (linux-arm), func Futimes(int, []Timeval) error
 pkg syscall (linux-arm), func Futimesat(int, string, []Timeval) error
-pkg syscall (linux-arm), func Getcwd([]byte) (int, error)
-pkg syscall (linux-arm), func Getdents(int, []byte) (int, error)
+pkg syscall (linux-arm), func Getcwd([]uint8) (int, error)
+pkg syscall (linux-arm), func Getdents(int, []uint8) (int, error)
 pkg syscall (linux-arm), func Getpeername(int) (Sockaddr, error)
 pkg syscall (linux-arm), func Getpgid(int) (int, error)
 pkg syscall (linux-arm), func Getpgrp() int
 pkg syscall (linux-arm), func Getrlimit(int, *Rlimit) error
 pkg syscall (linux-arm), func Getrusage(int, *Rusage) error
 pkg syscall (linux-arm), func Getsockname(int) (Sockaddr, error)
-pkg syscall (linux-arm), func GetsockoptIPMreq(int) (*IPMreq, error)
-pkg syscall (linux-arm), func GetsockoptIPMreqn(int) (*IPMreqn, error)
-pkg syscall (linux-arm), func GetsockoptIPv6Mreq(int) (*IPv6Mreq, error)
-pkg syscall (linux-arm), func GetsockoptInet4Addr(int) ([4]byte, error)
-pkg syscall (linux-arm), func GetsockoptInt(int) (int, error)
+pkg syscall (linux-arm), func GetsockoptIPMreq(int, int, int) (*IPMreq, error)
+pkg syscall (linux-arm), func GetsockoptIPMreqn(int, int, int) (*IPMreqn, error)
+pkg syscall (linux-arm), func GetsockoptIPv6Mreq(int, int, int) (*IPv6Mreq, error)
+pkg syscall (linux-arm), func GetsockoptInet4Addr(int, int, int) ([4]uint8, error)
+pkg syscall (linux-arm), func GetsockoptInt(int, int, int) (int, error)
 pkg syscall (linux-arm), func Gettid() int
 pkg syscall (linux-arm), func InotifyAddWatch(int, string, uint32) (int, error)
 pkg syscall (linux-arm), func InotifyInit() (int, error)
 pkg syscall (linux-arm), func InotifyInit1(int) (int, error)
 pkg syscall (linux-arm), func InotifyRmWatch(int, uint32) (int, error)
 pkg syscall (linux-arm), func Kill(int, Signal) error
-pkg syscall (linux-arm), func Klogctl(int, []byte) (int, error)
-pkg syscall (linux-arm), func Link(string, string) error
+pkg syscall (linux-arm), func Klogctl(int, []uint8) (int, error)
 pkg syscall (linux-arm), func Listen(int, int) error
-pkg syscall (linux-arm), func LsfJump(int) *SockFilter
-pkg syscall (linux-arm), func LsfSocket(int) (int, error)
-pkg syscall (linux-arm), func LsfStmt(int) *SockFilter
+pkg syscall (linux-arm), func LsfJump(int, int, int, int) *SockFilter
+pkg syscall (linux-arm), func LsfSocket(int, int) (int, error)
+pkg syscall (linux-arm), func LsfStmt(int, int) *SockFilter
 pkg syscall (linux-arm), func Lstat(string, *Stat_t) error
-pkg syscall (linux-arm), func Madvise([]byte, int) error
+pkg syscall (linux-arm), func Madvise([]uint8, int) error
 pkg syscall (linux-arm), func Mkdirat(int, string, uint32) error
 pkg syscall (linux-arm), func Mkfifo(string, uint32) error
 pkg syscall (linux-arm), func Mknod(string, uint32, int) error
 pkg syscall (linux-arm), func Mknodat(int, string, uint32, int) error
-pkg syscall (linux-arm), func Mlock([]byte) error
+pkg syscall (linux-arm), func Mlock([]uint8) error
 pkg syscall (linux-arm), func Mlockall(int) error
-pkg syscall (linux-arm), func Mmap(int, int64, int, int, int) ([]byte, error)
+pkg syscall (linux-arm), func Mmap(int, int64, int, int, int) ([]uint8, error)
 pkg syscall (linux-arm), func Mount(string, string, string, uintptr, string) error
-pkg syscall (linux-arm), func Mprotect([]byte, int) error
-pkg syscall (linux-arm), func Munlock([]byte) error
+pkg syscall (linux-arm), func Mprotect([]uint8, int) error
+pkg syscall (linux-arm), func Munlock([]uint8) error
 pkg syscall (linux-arm), func Munlockall() error
-pkg syscall (linux-arm), func Munmap([]byte) error
+pkg syscall (linux-arm), func Munmap([]uint8) error
 pkg syscall (linux-arm), func Nanosleep(*Timespec, *Timespec) error
-pkg syscall (linux-arm), func NetlinkRIB(int) ([]byte, error)
+pkg syscall (linux-arm), func NetlinkRIB(int, int) ([]uint8, error)
 pkg syscall (linux-arm), func NsecToTimespec(int64) Timespec
 pkg syscall (linux-arm), func Open(string, int, uint32) (int, error)
 pkg syscall (linux-arm), func Openat(int, string, int, uint32) (int, error)
-pkg syscall (linux-arm), func ParseDirent([]byte, int, []string) (int, int, []string)
-pkg syscall (linux-arm), func ParseNetlinkMessage([]byte) ([]NetlinkMessage, error)
+pkg syscall (linux-arm), func ParseDirent([]uint8, int, []string) (int, int, []string)
+pkg syscall (linux-arm), func ParseNetlinkMessage([]uint8) ([]NetlinkMessage, error)
 pkg syscall (linux-arm), func ParseNetlinkRouteAttr(*NetlinkMessage) ([]NetlinkRouteAttr, error)
-pkg syscall (linux-arm), func ParseSocketControlMessage([]byte) ([]SocketControlMessage, error)
+pkg syscall (linux-arm), func ParseSocketControlMessage([]uint8) ([]SocketControlMessage, error)
 pkg syscall (linux-arm), func ParseUnixCredentials(*SocketControlMessage) (*Ucred, error)
 pkg syscall (linux-arm), func ParseUnixRights(*SocketControlMessage) ([]int, error)
 pkg syscall (linux-arm), func Pause() error
 pkg syscall (linux-arm), func Pipe([]int) error
 pkg syscall (linux-arm), func PivotRoot(string, string) error
-pkg syscall (linux-arm), func Pread(int, []byte, int64) (int, error)
+pkg syscall (linux-arm), func Pread(int, []uint8, int64) (int, error)
 pkg syscall (linux-arm), func PtraceAttach(int) error
 pkg syscall (linux-arm), func PtraceCont(int, int) error
 pkg syscall (linux-arm), func PtraceDetach(int) error
 pkg syscall (linux-arm), func PtraceGetEventMsg(int) (uint, error)
 pkg syscall (linux-arm), func PtraceGetRegs(int, *PtraceRegs) error
-pkg syscall (linux-arm), func PtracePeekData(int, uintptr, []byte) (int, error)
-pkg syscall (linux-arm), func PtracePeekText(int, uintptr, []byte) (int, error)
-pkg syscall (linux-arm), func PtracePokeData(int, uintptr, []byte) (int, error)
-pkg syscall (linux-arm), func PtracePokeText(int, uintptr, []byte) (int, error)
+pkg syscall (linux-arm), func PtracePeekData(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-arm), func PtracePeekText(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-arm), func PtracePokeData(int, uintptr, []uint8) (int, error)
+pkg syscall (linux-arm), func PtracePokeText(int, uintptr, []uint8) (int, error)
 pkg syscall (linux-arm), func PtraceSetOptions(int, int) error
 pkg syscall (linux-arm), func PtraceSetRegs(int, *PtraceRegs) error
 pkg syscall (linux-arm), func PtraceSingleStep(int) error
-pkg syscall (linux-arm), func Pwrite(int, []byte, int64) (int, error)
-pkg syscall (linux-arm), func RawSyscall(uintptr) (uintptr, Errno)
-pkg syscall (linux-arm), func RawSyscall6(uintptr) (uintptr, Errno)
-pkg syscall (linux-arm), func Read(int, []byte) (int, error)
-pkg syscall (linux-arm), func ReadDirent(int, []byte) (int, error)
+pkg syscall (linux-arm), func Pwrite(int, []uint8, int64) (int, error)
+pkg syscall (linux-arm), func RawSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-arm), func RawSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-arm), func Read(int, []uint8) (int, error)
+pkg syscall (linux-arm), func ReadDirent(int, []uint8) (int, error)
 pkg syscall (linux-arm), func Reboot(int) error
-pkg syscall (linux-arm), func Recvfrom(int, []byte, int) (int, Sockaddr, error)
-pkg syscall (linux-arm), func Recvmsg(int, []byte, int) (int, int, Sockaddr, error)
-pkg syscall (linux-arm), func Rename(string, string) error
+pkg syscall (linux-arm), func Recvfrom(int, []uint8, int) (int, Sockaddr, error)
+pkg syscall (linux-arm), func Recvmsg(int, []uint8, []uint8, int) (int, int, int, Sockaddr, error)
 pkg syscall (linux-arm), func Renameat(int, string, int, string) error
 pkg syscall (linux-arm), func Seek(int, int64, int) (int64, error)
 pkg syscall (linux-arm), func Select(int, *FdSet, *FdSet, *FdSet, *Timeval) (int, error)
 pkg syscall (linux-arm), func Sendfile(int, int, *int64, int) (int, error)
-pkg syscall (linux-arm), func Sendmsg(int, []byte, Sockaddr, int) error
-pkg syscall (linux-arm), func Sendto(int, []byte, int, Sockaddr) error
+pkg syscall (linux-arm), func Sendmsg(int, []uint8, []uint8, Sockaddr, int) error
+pkg syscall (linux-arm), func Sendto(int, []uint8, int, Sockaddr) error
 pkg syscall (linux-arm), func SetLsfPromisc(string, bool) error
 pkg syscall (linux-arm), func SetNonblock(int, bool) error
-pkg syscall (linux-arm), func Setdomainname([]byte) error
+pkg syscall (linux-arm), func Setdomainname([]uint8) error
 pkg syscall (linux-arm), func Setfsgid(int) error
 pkg syscall (linux-arm), func Setfsuid(int) error
 pkg syscall (linux-arm), func Setgid(int) error
 pkg syscall (linux-arm), func Setgroups([]int) error
-pkg syscall (linux-arm), func Sethostname([]byte) error
+pkg syscall (linux-arm), func Sethostname([]uint8) error
 pkg syscall (linux-arm), func Setpgid(int, int) error
 pkg syscall (linux-arm), func Setregid(int, int) error
 pkg syscall (linux-arm), func Setresgid(int, int, int) error
@@ -27690,25 +27678,26 @@ pkg syscall (linux-arm), func Setresuid(int, int, int) error
 pkg syscall (linux-arm), func Setreuid(int, int) error
 pkg syscall (linux-arm), func Setrlimit(int, *Rlimit) error
 pkg syscall (linux-arm), func Setsid() (int, error)
-pkg syscall (linux-arm), func SetsockoptIPMreq(int, *IPMreq) error
-pkg syscall (linux-arm), func SetsockoptIPMreqn(int, *IPMreqn) error
-pkg syscall (linux-arm), func SetsockoptIPv6Mreq(int, *IPv6Mreq) error
-pkg syscall (linux-arm), func SetsockoptInet4Addr(int, [4]byte) error
-pkg syscall (linux-arm), func SetsockoptInt(int, int) error
-pkg syscall (linux-arm), func SetsockoptLinger(int, *Linger) error
-pkg syscall (linux-arm), func SetsockoptString(int, string) error
-pkg syscall (linux-arm), func SetsockoptTimeval(int, *Timeval) error
+pkg syscall (linux-arm), func SetsockoptIPMreq(int, int, int, *IPMreq) error
+pkg syscall (linux-arm), func SetsockoptIPMreqn(int, int, int, *IPMreqn) error
+pkg syscall (linux-arm), func SetsockoptIPv6Mreq(int, int, int, *IPv6Mreq) error
+pkg syscall (linux-arm), func SetsockoptInet4Addr(int, int, int, [4]uint8) error
+pkg syscall (linux-arm), func SetsockoptInt(int, int, int, int) error
+pkg syscall (linux-arm), func SetsockoptLinger(int, int, int, *Linger) error
+pkg syscall (linux-arm), func SetsockoptString(int, int, int, string) error
+pkg syscall (linux-arm), func SetsockoptTimeval(int, int, int, *Timeval) error
 pkg syscall (linux-arm), func Settimeofday(*Timeval) error
 pkg syscall (linux-arm), func Setuid(int) error
 pkg syscall (linux-arm), func Shutdown(int, int) error
-pkg syscall (linux-arm), func Socket(int) (int, error)
-pkg syscall (linux-arm), func Socketpair(int) ([2]int, error)
+pkg syscall (linux-arm), func Socket(int, int, int) (int, error)
+pkg syscall (linux-arm), func Socketpair(int, int, int) ([2]int, error)
 pkg syscall (linux-arm), func Splice(int, *int64, int, *int64, int, int) (int, error)
 pkg syscall (linux-arm), func Stat(string, *Stat_t) error
 pkg syscall (linux-arm), func Statfs(string, *Statfs_t) error
-pkg syscall (linux-arm), func StringSlicePtr([]string) []*byte
-pkg syscall (linux-arm), func Symlink(string, string) error
+pkg syscall (linux-arm), func StringSlicePtr([]string) []*uint8
 pkg syscall (linux-arm), func Sync()
+pkg syscall (linux-arm), func Syscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (linux-arm), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (linux-arm), func Sysinfo(*Sysinfo_t) error
 pkg syscall (linux-arm), func Tee(int, int, int, int) (int64, error)
 pkg syscall (linux-arm), func Tgkill(int, int, Signal) error
@@ -27718,15 +27707,15 @@ pkg syscall (linux-arm), func TimespecToNsec(Timespec) int64
 pkg syscall (linux-arm), func Truncate(string, int64) error
 pkg syscall (linux-arm), func Umask(int) int
 pkg syscall (linux-arm), func Uname(*Utsname) error
-pkg syscall (linux-arm), func UnixCredentials(*Ucred) []byte
-pkg syscall (linux-arm), func UnixRights(...int) []byte
+pkg syscall (linux-arm), func UnixCredentials(*Ucred) []uint8
+pkg syscall (linux-arm), func UnixRights(...int) []uint8
 pkg syscall (linux-arm), func Unlinkat(int, string) error
 pkg syscall (linux-arm), func Unmount(string, int) error
 pkg syscall (linux-arm), func Unshare(int) error
 pkg syscall (linux-arm), func Ustat(int, *Ustat_t) error
 pkg syscall (linux-arm), func Utime(string, *Utimbuf) error
 pkg syscall (linux-arm), func Wait4(int, *WaitStatus, int, *Rusage) (int, error)
-pkg syscall (linux-arm), func Write(int, []byte) (int, error)
+pkg syscall (linux-arm), func Write(int, []uint8) (int, error)
 pkg syscall (linux-arm), method (*Cmsghdr) SetLen(int)
 pkg syscall (linux-arm), method (*Iovec) SetLen(int)
 pkg syscall (linux-arm), method (*Msghdr) SetControllen(int)
@@ -27745,7 +27734,7 @@ pkg syscall (linux-arm), type Dirent struct
 pkg syscall (linux-arm), type Dirent struct, Ino uint64
 pkg syscall (linux-arm), type Dirent struct, Name [256]uint8
 pkg syscall (linux-arm), type Dirent struct, Off int64
-pkg syscall (linux-arm), type Dirent struct, Pad_cgo_0 [5]byte
+pkg syscall (linux-arm), type Dirent struct, Pad_cgo_0 [5]uint8
 pkg syscall (linux-arm), type Dirent struct, Reclen uint16
 pkg syscall (linux-arm), type Dirent struct, Type uint8
 pkg syscall (linux-arm), type EpollEvent struct
@@ -27758,9 +27747,9 @@ pkg syscall (linux-arm), type FdSet struct, Bits [32]int32
 pkg syscall (linux-arm), type Fsid struct
 pkg syscall (linux-arm), type Fsid struct, X__val [2]int32
 pkg syscall (linux-arm), type IPMreqn struct
-pkg syscall (linux-arm), type IPMreqn struct, Address [4]byte
+pkg syscall (linux-arm), type IPMreqn struct, Address [4]uint8
 pkg syscall (linux-arm), type IPMreqn struct, Ifindex int32
-pkg syscall (linux-arm), type IPMreqn struct, Multiaddr [4]byte
+pkg syscall (linux-arm), type IPMreqn struct, Multiaddr [4]uint8
 pkg syscall (linux-arm), type IfAddrmsg struct
 pkg syscall (linux-arm), type IfAddrmsg struct, Family uint8
 pkg syscall (linux-arm), type IfAddrmsg struct, Flags uint8
@@ -27775,11 +27764,11 @@ pkg syscall (linux-arm), type IfInfomsg struct, Index int32
 pkg syscall (linux-arm), type IfInfomsg struct, Type uint16
 pkg syscall (linux-arm), type IfInfomsg struct, X__ifi_pad uint8
 pkg syscall (linux-arm), type Inet4Pktinfo struct
-pkg syscall (linux-arm), type Inet4Pktinfo struct, Addr [4]byte
+pkg syscall (linux-arm), type Inet4Pktinfo struct, Addr [4]uint8
 pkg syscall (linux-arm), type Inet4Pktinfo struct, Ifindex int32
-pkg syscall (linux-arm), type Inet4Pktinfo struct, Spec_dst [4]byte
+pkg syscall (linux-arm), type Inet4Pktinfo struct, Spec_dst [4]uint8
 pkg syscall (linux-arm), type Inet6Pktinfo struct
-pkg syscall (linux-arm), type Inet6Pktinfo struct, Addr [16]byte
+pkg syscall (linux-arm), type Inet6Pktinfo struct, Addr [16]uint8
 pkg syscall (linux-arm), type Inet6Pktinfo struct, Ifindex uint32
 pkg syscall (linux-arm), type InotifyEvent struct
 pkg syscall (linux-arm), type InotifyEvent struct, Cookie uint32
@@ -27788,22 +27777,22 @@ pkg syscall (linux-arm), type InotifyEvent struct, Mask uint32
 pkg syscall (linux-arm), type InotifyEvent struct, Name [0]uint8
 pkg syscall (linux-arm), type InotifyEvent struct, Wd int32
 pkg syscall (linux-arm), type Iovec struct
-pkg syscall (linux-arm), type Iovec struct, Base *byte
+pkg syscall (linux-arm), type Iovec struct, Base *uint8
 pkg syscall (linux-arm), type Iovec struct, Len uint32
 pkg syscall (linux-arm), type Msghdr struct
-pkg syscall (linux-arm), type Msghdr struct, Control *byte
+pkg syscall (linux-arm), type Msghdr struct, Control *uint8
 pkg syscall (linux-arm), type Msghdr struct, Controllen uint32
 pkg syscall (linux-arm), type Msghdr struct, Flags int32
 pkg syscall (linux-arm), type Msghdr struct, Iov *Iovec
 pkg syscall (linux-arm), type Msghdr struct, Iovlen uint32
-pkg syscall (linux-arm), type Msghdr struct, Name *byte
+pkg syscall (linux-arm), type Msghdr struct, Name *uint8
 pkg syscall (linux-arm), type Msghdr struct, Namelen uint32
 pkg syscall (linux-arm), type NetlinkMessage struct
-pkg syscall (linux-arm), type NetlinkMessage struct, Data []byte
+pkg syscall (linux-arm), type NetlinkMessage struct, Data []uint8
 pkg syscall (linux-arm), type NetlinkMessage struct, Header NlMsghdr
 pkg syscall (linux-arm), type NetlinkRouteAttr struct
 pkg syscall (linux-arm), type NetlinkRouteAttr struct, Attr RtAttr
-pkg syscall (linux-arm), type NetlinkRouteAttr struct, Value []byte
+pkg syscall (linux-arm), type NetlinkRouteAttr struct, Value []uint8
 pkg syscall (linux-arm), type NetlinkRouteRequest struct
 pkg syscall (linux-arm), type NetlinkRouteRequest struct, Data RtGenmsg
 pkg syscall (linux-arm), type NetlinkRouteRequest struct, Header NlMsghdr
@@ -27827,7 +27816,7 @@ pkg syscall (linux-arm), type RawSockaddrAny struct, Pad [96]uint8
 pkg syscall (linux-arm), type RawSockaddrInet4 struct, Family uint16
 pkg syscall (linux-arm), type RawSockaddrInet4 struct, Zero [8]uint8
 pkg syscall (linux-arm), type RawSockaddrInet6 struct
-pkg syscall (linux-arm), type RawSockaddrInet6 struct, Addr [16]byte
+pkg syscall (linux-arm), type RawSockaddrInet6 struct, Addr [16]uint8
 pkg syscall (linux-arm), type RawSockaddrInet6 struct, Family uint16
 pkg syscall (linux-arm), type RawSockaddrInet6 struct, Flowinfo uint32
 pkg syscall (linux-arm), type RawSockaddrInet6 struct, Port uint16
@@ -27895,9 +27884,9 @@ pkg syscall (linux-arm), type SockFilter struct, K uint32
 pkg syscall (linux-arm), type SockFprog struct
 pkg syscall (linux-arm), type SockFprog struct, Filter *SockFilter
 pkg syscall (linux-arm), type SockFprog struct, Len uint16
-pkg syscall (linux-arm), type SockFprog struct, Pad_cgo_0 [2]byte
+pkg syscall (linux-arm), type SockFprog struct, Pad_cgo_0 [2]uint8
 pkg syscall (linux-arm), type SockaddrLinklayer struct
-pkg syscall (linux-arm), type SockaddrLinklayer struct, Addr [8]byte
+pkg syscall (linux-arm), type SockaddrLinklayer struct, Addr [8]uint8
 pkg syscall (linux-arm), type SockaddrLinklayer struct, Halen uint8
 pkg syscall (linux-arm), type SockaddrLinklayer struct, Hatype uint16
 pkg syscall (linux-arm), type SockaddrLinklayer struct, Ifindex int
@@ -27909,7 +27898,7 @@ pkg syscall (linux-arm), type SockaddrNetlink struct, Groups uint32
 pkg syscall (linux-arm), type SockaddrNetlink struct, Pad uint16
 pkg syscall (linux-arm), type SockaddrNetlink struct, Pid uint32
 pkg syscall (linux-arm), type SocketControlMessage struct
-pkg syscall (linux-arm), type SocketControlMessage struct, Data []byte
+pkg syscall (linux-arm), type SocketControlMessage struct, Data []uint8
 pkg syscall (linux-arm), type SocketControlMessage struct, Header Cmsghdr
 pkg syscall (linux-arm), type Stat_t struct
 pkg syscall (linux-arm), type Stat_t struct, Atim Timespec
@@ -27922,9 +27911,9 @@ pkg syscall (linux-arm), type Stat_t struct, Ino uint64
 pkg syscall (linux-arm), type Stat_t struct, Mode uint32
 pkg syscall (linux-arm), type Stat_t struct, Mtim Timespec
 pkg syscall (linux-arm), type Stat_t struct, Nlink uint32
-pkg syscall (linux-arm), type Stat_t struct, Pad_cgo_0 [2]byte
-pkg syscall (linux-arm), type Stat_t struct, Pad_cgo_1 [6]byte
-pkg syscall (linux-arm), type Stat_t struct, Pad_cgo_2 [4]byte
+pkg syscall (linux-arm), type Stat_t struct, Pad_cgo_0 [2]uint8
+pkg syscall (linux-arm), type Stat_t struct, Pad_cgo_1 [6]uint8
+pkg syscall (linux-arm), type Stat_t struct, Pad_cgo_2 [4]uint8
 pkg syscall (linux-arm), type Stat_t struct, Rdev uint64
 pkg syscall (linux-arm), type Stat_t struct, Size int64
 pkg syscall (linux-arm), type Stat_t struct, Uid uint32
@@ -27942,7 +27931,7 @@ pkg syscall (linux-arm), type Statfs_t struct, Flags int32
 pkg syscall (linux-arm), type Statfs_t struct, Frsize int32
 pkg syscall (linux-arm), type Statfs_t struct, Fsid Fsid
 pkg syscall (linux-arm), type Statfs_t struct, Namelen int32
-pkg syscall (linux-arm), type Statfs_t struct, Pad_cgo_0 [4]byte
+pkg syscall (linux-arm), type Statfs_t struct, Pad_cgo_0 [4]uint8
 pkg syscall (linux-arm), type Statfs_t struct, Spare [4]int32
 pkg syscall (linux-arm), type Statfs_t struct, Type int32
 pkg syscall (linux-arm), type SysProcAttr struct, Chroot string
@@ -27977,7 +27966,7 @@ pkg syscall (linux-arm), type Termios struct, Lflag uint32
 pkg syscall (linux-arm), type Termios struct, Line uint8
 pkg syscall (linux-arm), type Termios struct, Oflag uint32
 pkg syscall (linux-arm), type Termios struct, Ospeed uint32
-pkg syscall (linux-arm), type Termios struct, Pad_cgo_0 [3]byte
+pkg syscall (linux-arm), type Termios struct, Pad_cgo_0 [3]uint8
 pkg syscall (linux-arm), type Time_t int32
 pkg syscall (linux-arm), type Timespec struct, Nsec int32
 pkg syscall (linux-arm), type Timespec struct, Sec int32
@@ -27994,7 +27983,7 @@ pkg syscall (linux-arm), type Timex struct, Jitter int32
 pkg syscall (linux-arm), type Timex struct, Maxerror int32
 pkg syscall (linux-arm), type Timex struct, Modes uint32
 pkg syscall (linux-arm), type Timex struct, Offset int32
-pkg syscall (linux-arm), type Timex struct, Pad_cgo_0 [44]byte
+pkg syscall (linux-arm), type Timex struct, Pad_cgo_0 [44]uint8
 pkg syscall (linux-arm), type Timex struct, Ppsfreq int32
 pkg syscall (linux-arm), type Timex struct, Precision int32
 pkg syscall (linux-arm), type Timex struct, Shift int32
@@ -28448,12 +28437,12 @@ pkg syscall (windows-386), const WSADESCRIPTION_LEN ideal-int
 pkg syscall (windows-386), const WSASYS_STATUS_LEN ideal-int
 pkg syscall (windows-386), const X509_ASN_ENCODING ideal-int
 pkg syscall (windows-386), func Accept(Handle) (Handle, Sockaddr, error)
-pkg syscall (windows-386), func AcceptEx(Handle, Handle, *byte, uint32, uint32, uint32, *uint32, *Overlapped) error
+pkg syscall (windows-386), func AcceptEx(Handle, Handle, *uint8, uint32, uint32, uint32, *uint32, *Overlapped) error
 pkg syscall (windows-386), func Bind(Handle, Sockaddr) error
 pkg syscall (windows-386), func CancelIo(Handle) error
 pkg syscall (windows-386), func CertAddCertificateContextToStore(Handle, *CertContext, uint32, **CertContext) error
 pkg syscall (windows-386), func CertCloseStore(Handle, uint32) error
-pkg syscall (windows-386), func CertCreateCertificateContext(uint32, *byte, uint32) (*CertContext, error)
+pkg syscall (windows-386), func CertCreateCertificateContext(uint32, *uint8, uint32) (*CertContext, error)
 pkg syscall (windows-386), func CertEnumCertificatesInStore(Handle, *CertContext) (*CertContext, error)
 pkg syscall (windows-386), func CertFreeCertificateChain(*CertChainContext)
 pkg syscall (windows-386), func CertFreeCertificateContext(*CertContext) error
@@ -28478,10 +28467,10 @@ pkg syscall (windows-386), func CreateIoCompletionPort(Handle, Handle, uint32, u
 pkg syscall (windows-386), func CreatePipe(*Handle, *Handle, *SecurityAttributes, uint32) error
 pkg syscall (windows-386), func CreateProcess(*uint16, *uint16, *SecurityAttributes, *SecurityAttributes, bool, uint32, *uint16, *uint16, *StartupInfo, *ProcessInformation) error
 pkg syscall (windows-386), func CryptAcquireContext(*Handle, *uint16, *uint16, uint32, uint32) error
-pkg syscall (windows-386), func CryptGenRandom(Handle, uint32, *byte) error
+pkg syscall (windows-386), func CryptGenRandom(Handle, uint32, *uint8) error
 pkg syscall (windows-386), func CryptReleaseContext(Handle, uint32) error
 pkg syscall (windows-386), func DeleteFile(*uint16) error
-pkg syscall (windows-386), func DnsQuery(string, uint16, uint32, *byte, **DNSRecord, *byte) error
+pkg syscall (windows-386), func DnsQuery(string, uint16, uint32, *uint8, **DNSRecord, *uint8) error
 pkg syscall (windows-386), func DnsRecordListFree(*DNSRecord, uint32)
 pkg syscall (windows-386), func DuplicateHandle(Handle, Handle, Handle, *Handle, uint32, bool, uint32) error
 pkg syscall (windows-386), func EscapeArg(string) string
@@ -28494,12 +28483,12 @@ pkg syscall (windows-386), func FindFirstFile(*uint16, *Win32finddata) (Handle,
 pkg syscall (windows-386), func FindNextFile(Handle, *Win32finddata) error
 pkg syscall (windows-386), func FlushFileBuffers(Handle) error
 pkg syscall (windows-386), func FlushViewOfFile(uintptr, uintptr) error
-pkg syscall (windows-386), func FormatMessage(uint32, uint32, uint32, uint32, []uint16, *byte) (uint32, error)
+pkg syscall (windows-386), func FormatMessage(uint32, uint32, uint32, uint32, []uint16, *uint8) (uint32, error)
 pkg syscall (windows-386), func FreeEnvironmentStrings(*uint16) error
 pkg syscall (windows-386), func FreeLibrary(Handle) error
 pkg syscall (windows-386), func Fsync(Handle) error
 pkg syscall (windows-386), func Ftruncate(Handle, int64) error
-pkg syscall (windows-386), func GetAcceptExSockaddrs(*byte, uint32, uint32, uint32, **RawSockaddrAny, *int32, **RawSockaddrAny, *int32)
+pkg syscall (windows-386), func GetAcceptExSockaddrs(*uint8, uint32, uint32, uint32, **RawSockaddrAny, *int32, **RawSockaddrAny, *int32)
 pkg syscall (windows-386), func GetAdaptersInfo(*IpAdapterInfo, *uint32) error
 pkg syscall (windows-386), func GetCommandLine() *uint16
 pkg syscall (windows-386), func GetComputerName(*uint16, *uint32) error
@@ -28509,7 +28498,7 @@ pkg syscall (windows-386), func GetEnvironmentStrings() (*uint16, error)
 pkg syscall (windows-386), func GetEnvironmentVariable(*uint16, *uint16, uint32) (uint32, error)
 pkg syscall (windows-386), func GetExitCodeProcess(Handle, *uint32) error
 pkg syscall (windows-386), func GetFileAttributes(*uint16) (uint32, error)
-pkg syscall (windows-386), func GetFileAttributesEx(*uint16, uint32, *byte) error
+pkg syscall (windows-386), func GetFileAttributesEx(*uint16, uint32, *uint8) error
 pkg syscall (windows-386), func GetFileInformationByHandle(Handle, *ByHandleFileInformation) error
 pkg syscall (windows-386), func GetFileType(Handle) (uint32, error)
 pkg syscall (windows-386), func GetFullPathName(*uint16, uint32, *uint16, **uint16) (uint32, error)
@@ -28529,26 +28518,25 @@ pkg syscall (windows-386), func GetStdHandle(int) (Handle, error)
 pkg syscall (windows-386), func GetSystemTimeAsFileTime(*Filetime)
 pkg syscall (windows-386), func GetTempPath(uint32, *uint16) (uint32, error)
 pkg syscall (windows-386), func GetTimeZoneInformation(*Timezoneinformation) (uint32, error)
-pkg syscall (windows-386), func GetTokenInformation(Token, uint32, *byte, uint32, *uint32) error
+pkg syscall (windows-386), func GetTokenInformation(Token, uint32, *uint8, uint32, *uint32) error
 pkg syscall (windows-386), func GetUserNameEx(uint32, *uint16, *uint32) error
 pkg syscall (windows-386), func GetUserProfileDirectory(Token, *uint16, *uint32) error
 pkg syscall (windows-386), func GetVersion() (uint32, error)
 pkg syscall (windows-386), func Getpeername(Handle) (Sockaddr, error)
 pkg syscall (windows-386), func Getsockname(Handle) (Sockaddr, error)
-pkg syscall (windows-386), func GetsockoptInt(Handle, int) (int, error)
-pkg syscall (windows-386), func Link(string) error
+pkg syscall (windows-386), func GetsockoptInt(Handle, int, int) (int, error)
 pkg syscall (windows-386), func Listen(Handle, int) error
 pkg syscall (windows-386), func LoadDLL(string) (*DLL, error)
 pkg syscall (windows-386), func LoadLibrary(string) (Handle, error)
 pkg syscall (windows-386), func LocalFree(Handle) (Handle, error)
 pkg syscall (windows-386), func LookupAccountName(*uint16, *uint16, *SID, *uint32, *uint16, *uint32, *uint32) error
 pkg syscall (windows-386), func LookupAccountSid(*uint16, *SID, *uint16, *uint32, *uint16, *uint32, *uint32) error
-pkg syscall (windows-386), func LookupSID(string) (*SID, string, uint32, error)
+pkg syscall (windows-386), func LookupSID(string, string) (*SID, string, uint32, error)
 pkg syscall (windows-386), func MapViewOfFile(Handle, uint32, uint32, uint32, uintptr) (uintptr, error)
 pkg syscall (windows-386), func MoveFile(*uint16, *uint16) error
 pkg syscall (windows-386), func MustLoadDLL(string) *DLL
-pkg syscall (windows-386), func NetApiBufferFree(*byte) error
-pkg syscall (windows-386), func NetUserGetInfo(*uint16, *uint16, uint32, **byte) error
+pkg syscall (windows-386), func NetApiBufferFree(*uint8) error
+pkg syscall (windows-386), func NetUserGetInfo(*uint16, *uint16, uint32, **uint8) error
 pkg syscall (windows-386), func NewCallback(interface{}) uintptr
 pkg syscall (windows-386), func NewLazyDLL(string) *LazyDLL
 pkg syscall (windows-386), func NsecToFiletime(int64) Filetime
@@ -28559,19 +28547,18 @@ pkg syscall (windows-386), func OpenProcess(uint32, bool, uint32) (Handle, error
 pkg syscall (windows-386), func OpenProcessToken(Handle, uint32, *Token) error
 pkg syscall (windows-386), func Pipe([]Handle) error
 pkg syscall (windows-386), func PostQueuedCompletionStatus(Handle, uint32, uint32, *Overlapped) error
-pkg syscall (windows-386), func Read(Handle, []byte) (int, error)
-pkg syscall (windows-386), func ReadDirectoryChanges(Handle, *byte, uint32, bool, uint32, *uint32, *Overlapped, uintptr) error
-pkg syscall (windows-386), func ReadFile(Handle, []byte, *uint32, *Overlapped) error
-pkg syscall (windows-386), func Recvfrom(Handle, []byte, int) (int, Sockaddr, error)
+pkg syscall (windows-386), func Read(Handle, []uint8) (int, error)
+pkg syscall (windows-386), func ReadDirectoryChanges(Handle, *uint8, uint32, bool, uint32, *uint32, *Overlapped, uintptr) error
+pkg syscall (windows-386), func ReadFile(Handle, []uint8, *uint32, *Overlapped) error
+pkg syscall (windows-386), func Recvfrom(Handle, []uint8, int) (int, Sockaddr, error)
 pkg syscall (windows-386), func RegCloseKey(Handle) error
 pkg syscall (windows-386), func RegEnumKeyEx(Handle, uint32, *uint16, *uint32, *uint32, *uint16, *uint32, *Filetime) error
 pkg syscall (windows-386), func RegOpenKeyEx(Handle, *uint16, uint32, uint32, *Handle) error
 pkg syscall (windows-386), func RegQueryInfoKey(Handle, *uint16, *uint32, *uint32, *uint32, *uint32, *uint32, *uint32, *uint32, *uint32, *uint32, *Filetime) error
-pkg syscall (windows-386), func RegQueryValueEx(Handle, *uint16, *uint32, *uint32, *byte, *uint32) error
+pkg syscall (windows-386), func RegQueryValueEx(Handle, *uint16, *uint32, *uint32, *uint8, *uint32) error
 pkg syscall (windows-386), func RemoveDirectory(*uint16) error
-pkg syscall (windows-386), func Rename(string) error
 pkg syscall (windows-386), func Seek(Handle, int64, int) (int64, error)
-pkg syscall (windows-386), func Sendto(Handle, []byte, int, Sockaddr) error
+pkg syscall (windows-386), func Sendto(Handle, []uint8, int, Sockaddr) error
 pkg syscall (windows-386), func SetCurrentDirectory(*uint16) error
 pkg syscall (windows-386), func SetEndOfFile(Handle) error
 pkg syscall (windows-386), func SetEnvironmentVariable(*uint16, *uint16) error
@@ -28580,24 +28567,25 @@ pkg syscall (windows-386), func SetFilePointer(Handle, int32, *int32, uint32) (u
 pkg syscall (windows-386), func SetFileTime(Handle, *Filetime, *Filetime, *Filetime) error
 pkg syscall (windows-386), func SetHandleInformation(Handle, uint32, uint32) error
 pkg syscall (windows-386), func SetNonblock(Handle, bool) error
-pkg syscall (windows-386), func Setsockopt(Handle, int32, int32, *byte, int32) error
-pkg syscall (windows-386), func SetsockoptIPMreq(Handle, int, *IPMreq) error
-pkg syscall (windows-386), func SetsockoptIPv6Mreq(Handle, int, *IPv6Mreq) error
-pkg syscall (windows-386), func SetsockoptInet4Addr(Handle, int, [4]byte) error
-pkg syscall (windows-386), func SetsockoptInt(Handle, int, int) error
-pkg syscall (windows-386), func SetsockoptLinger(Handle, int, *Linger) error
-pkg syscall (windows-386), func SetsockoptTimeval(Handle, int, *Timeval) error
+pkg syscall (windows-386), func Setsockopt(Handle, int32, int32, *uint8, int32) error
+pkg syscall (windows-386), func SetsockoptIPMreq(Handle, int, int, *IPMreq) error
+pkg syscall (windows-386), func SetsockoptIPv6Mreq(Handle, int, int, *IPv6Mreq) error
+pkg syscall (windows-386), func SetsockoptInet4Addr(Handle, int, int, [4]uint8) error
+pkg syscall (windows-386), func SetsockoptInt(Handle, int, int, int) error
+pkg syscall (windows-386), func SetsockoptLinger(Handle, int, int, *Linger) error
+pkg syscall (windows-386), func SetsockoptTimeval(Handle, int, int, *Timeval) error
 pkg syscall (windows-386), func Shutdown(Handle, int) error
-pkg syscall (windows-386), func Socket(int) (Handle, error)
+pkg syscall (windows-386), func Socket(int, int, int) (Handle, error)
 pkg syscall (windows-386), func StringToSid(string) (*SID, error)
 pkg syscall (windows-386), func StringToUTF16(string) []uint16
 pkg syscall (windows-386), func StringToUTF16Ptr(string) *uint16
-pkg syscall (windows-386), func Symlink(string) error
-pkg syscall (windows-386), func Syscall12(uintptr) (uintptr, Errno)
-pkg syscall (windows-386), func Syscall15(uintptr) (uintptr, Errno)
-pkg syscall (windows-386), func Syscall9(uintptr) (uintptr, Errno)
+pkg syscall (windows-386), func Syscall(uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (windows-386), func Syscall12(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (windows-386), func Syscall15(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (windows-386), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (windows-386), func Syscall9(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (windows-386), func TerminateProcess(Handle, uint32) error
-pkg syscall (windows-386), func TranslateAccountName(string, uint32, int) (string, error)
+pkg syscall (windows-386), func TranslateAccountName(string, uint32, uint32, int) (string, error)
 pkg syscall (windows-386), func TranslateName(*uint16, uint32, uint32, *uint16, *uint32) error
 pkg syscall (windows-386), func TransmitFile(Handle, Handle, uint32, uint32, *Overlapped, *TransmitFileBuffers, uint32) error
 pkg syscall (windows-386), func UTF16ToString([]uint16) string
@@ -28605,16 +28593,16 @@ pkg syscall (windows-386), func UnmapViewOfFile(uintptr) error
 pkg syscall (windows-386), func VirtualLock(uintptr, uintptr) error
 pkg syscall (windows-386), func VirtualUnlock(uintptr, uintptr) error
 pkg syscall (windows-386), func WSACleanup() error
-pkg syscall (windows-386), func WSAIoctl(Handle, uint32, *byte, uint32, *byte, uint32, *uint32, *Overlapped, uintptr) error
-pkg syscall (windows-386), func WSARecv(Handle, *WSABuf, uint32, *uint32, *uint32, *Overlapped, *byte) error
-pkg syscall (windows-386), func WSARecvFrom(Handle, *WSABuf, uint32, *uint32, *uint32, *RawSockaddrAny, *int32, *Overlapped, *byte) error
-pkg syscall (windows-386), func WSASend(Handle, *WSABuf, uint32, *uint32, uint32, *Overlapped, *byte) error
-pkg syscall (windows-386), func WSASendTo(Handle, *WSABuf, uint32, *uint32, uint32, *RawSockaddrAny, int32, *Overlapped, *byte) error
-pkg syscall (windows-386), func WSASendto(Handle, *WSABuf, uint32, *uint32, uint32, Sockaddr, *Overlapped, *byte) error
+pkg syscall (windows-386), func WSAIoctl(Handle, uint32, *uint8, uint32, *uint8, uint32, *uint32, *Overlapped, uintptr) error
+pkg syscall (windows-386), func WSARecv(Handle, *WSABuf, uint32, *uint32, *uint32, *Overlapped, *uint8) error
+pkg syscall (windows-386), func WSARecvFrom(Handle, *WSABuf, uint32, *uint32, *uint32, *RawSockaddrAny, *int32, *Overlapped, *uint8) error
+pkg syscall (windows-386), func WSASend(Handle, *WSABuf, uint32, *uint32, uint32, *Overlapped, *uint8) error
+pkg syscall (windows-386), func WSASendTo(Handle, *WSABuf, uint32, *uint32, uint32, *RawSockaddrAny, int32, *Overlapped, *uint8) error
+pkg syscall (windows-386), func WSASendto(Handle, *WSABuf, uint32, *uint32, uint32, Sockaddr, *Overlapped, *uint8) error
 pkg syscall (windows-386), func WSAStartup(uint32, *WSAData) error
 pkg syscall (windows-386), func WaitForSingleObject(Handle, uint32) (uint32, error)
-pkg syscall (windows-386), func Write(Handle, []byte) (int, error)
-pkg syscall (windows-386), func WriteFile(Handle, []byte, *uint32, *Overlapped) error
+pkg syscall (windows-386), func Write(Handle, []uint8) (int, error)
+pkg syscall (windows-386), func WriteFile(Handle, []uint8, *uint32, *Overlapped) error
 pkg syscall (windows-386), method (*DLL) FindProc(string) (*Proc, error)
 pkg syscall (windows-386), method (*DLL) MustFindProc(string) *Proc
 pkg syscall (windows-386), method (*DLL) Release() error
@@ -28624,14 +28612,14 @@ pkg syscall (windows-386), method (*LazyDLL) Handle() uintptr
 pkg syscall (windows-386), method (*LazyDLL) Load() error
 pkg syscall (windows-386), method (*LazyDLL) NewProc(string) *LazyProc
 pkg syscall (windows-386), method (*LazyProc) Addr() uintptr
-pkg syscall (windows-386), method (*LazyProc) Call(...uintptr) (uintptr, error)
+pkg syscall (windows-386), method (*LazyProc) Call(...uintptr) (uintptr, uintptr, error)
 pkg syscall (windows-386), method (*LazyProc) Find() error
 pkg syscall (windows-386), method (*Proc) Addr() uintptr
-pkg syscall (windows-386), method (*Proc) Call(...uintptr) (uintptr, error)
+pkg syscall (windows-386), method (*Proc) Call(...uintptr) (uintptr, uintptr, error)
 pkg syscall (windows-386), method (*RawSockaddrAny) Sockaddr() (Sockaddr, error)
 pkg syscall (windows-386), method (*SID) Copy() (*SID, error)
 pkg syscall (windows-386), method (*SID) Len() int
-pkg syscall (windows-386), method (*SID) LookupAccount(string) (string, uint32, error)
+pkg syscall (windows-386), method (*SID) LookupAccount(string) (string, string, uint32, error)
 pkg syscall (windows-386), method (*SID) String() (string, error)
 pkg syscall (windows-386), method (*Timeval) Nanoseconds() int64
 pkg syscall (windows-386), method (Token) Close() error
@@ -28686,19 +28674,19 @@ pkg syscall (windows-386), type CertChainPolicyStatus struct, ExtraPolicyStatus
 pkg syscall (windows-386), type CertChainPolicyStatus struct, Size uint32
 pkg syscall (windows-386), type CertContext struct
 pkg syscall (windows-386), type CertContext struct, CertInfo uintptr
-pkg syscall (windows-386), type CertContext struct, EncodedCert *byte
+pkg syscall (windows-386), type CertContext struct, EncodedCert *uint8
 pkg syscall (windows-386), type CertContext struct, EncodingType uint32
 pkg syscall (windows-386), type CertContext struct, Length uint32
 pkg syscall (windows-386), type CertContext struct, Store Handle
 pkg syscall (windows-386), type CertEnhKeyUsage struct
 pkg syscall (windows-386), type CertEnhKeyUsage struct, Length uint32
-pkg syscall (windows-386), type CertEnhKeyUsage struct, UsageIdentifiers **byte
+pkg syscall (windows-386), type CertEnhKeyUsage struct, UsageIdentifiers **uint8
 pkg syscall (windows-386), type CertRevocationInfo struct
 pkg syscall (windows-386), type CertRevocationInfo struct, CrlInfo uintptr
 pkg syscall (windows-386), type CertRevocationInfo struct, FreshnessTime uint32
 pkg syscall (windows-386), type CertRevocationInfo struct, HasFreshnessTime uint32
 pkg syscall (windows-386), type CertRevocationInfo struct, OidSpecificInfo uintptr
-pkg syscall (windows-386), type CertRevocationInfo struct, RevocationOid *byte
+pkg syscall (windows-386), type CertRevocationInfo struct, RevocationOid *uint8
 pkg syscall (windows-386), type CertRevocationInfo struct, RevocationResult uint32
 pkg syscall (windows-386), type CertRevocationInfo struct, Size uint32
 pkg syscall (windows-386), type CertSimpleChain struct
@@ -28729,7 +28717,7 @@ pkg syscall (windows-386), type DNSMXData struct, Preference uint16
 pkg syscall (windows-386), type DNSPTRData struct
 pkg syscall (windows-386), type DNSPTRData struct, Host *uint16
 pkg syscall (windows-386), type DNSRecord struct
-pkg syscall (windows-386), type DNSRecord struct, Data [40]byte
+pkg syscall (windows-386), type DNSRecord struct, Data [40]uint8
 pkg syscall (windows-386), type DNSRecord struct, Dw uint32
 pkg syscall (windows-386), type DNSRecord struct, Length uint16
 pkg syscall (windows-386), type DNSRecord struct, Name *uint16
@@ -28756,23 +28744,23 @@ pkg syscall (windows-386), type Filetime struct, HighDateTime uint32
 pkg syscall (windows-386), type Filetime struct, LowDateTime uint32
 pkg syscall (windows-386), type Handle uintptr
 pkg syscall (windows-386), type Hostent struct
-pkg syscall (windows-386), type Hostent struct, AddrList **byte
+pkg syscall (windows-386), type Hostent struct, AddrList **uint8
 pkg syscall (windows-386), type Hostent struct, AddrType uint16
-pkg syscall (windows-386), type Hostent struct, Aliases **byte
+pkg syscall (windows-386), type Hostent struct, Aliases **uint8
 pkg syscall (windows-386), type Hostent struct, Length uint16
-pkg syscall (windows-386), type Hostent struct, Name *byte
+pkg syscall (windows-386), type Hostent struct, Name *uint8
 pkg syscall (windows-386), type InterfaceInfo struct
 pkg syscall (windows-386), type InterfaceInfo struct, Address SockaddrGen
 pkg syscall (windows-386), type InterfaceInfo struct, BroadcastAddress SockaddrGen
 pkg syscall (windows-386), type InterfaceInfo struct, Flags uint32
 pkg syscall (windows-386), type InterfaceInfo struct, Netmask SockaddrGen
 pkg syscall (windows-386), type IpAdapterInfo struct
-pkg syscall (windows-386), type IpAdapterInfo struct, AdapterName [MAX_ADAPTER_NAME_LENGTH + 4]byte
-pkg syscall (windows-386), type IpAdapterInfo struct, Address [MAX_ADAPTER_ADDRESS_LENGTH]byte
+pkg syscall (windows-386), type IpAdapterInfo struct, AdapterName [MAX_ADAPTER_NAME_LENGTH + 4]uint8
+pkg syscall (windows-386), type IpAdapterInfo struct, Address [MAX_ADAPTER_ADDRESS_LENGTH]uint8
 pkg syscall (windows-386), type IpAdapterInfo struct, AddressLength uint32
 pkg syscall (windows-386), type IpAdapterInfo struct, ComboIndex uint32
 pkg syscall (windows-386), type IpAdapterInfo struct, CurrentIpAddress *IpAddrString
-pkg syscall (windows-386), type IpAdapterInfo struct, Description [MAX_ADAPTER_DESCRIPTION_LENGTH + 4]byte
+pkg syscall (windows-386), type IpAdapterInfo struct, Description [MAX_ADAPTER_DESCRIPTION_LENGTH + 4]uint8
 pkg syscall (windows-386), type IpAdapterInfo struct, DhcpEnabled uint32
 pkg syscall (windows-386), type IpAdapterInfo struct, DhcpServer IpAddrString
 pkg syscall (windows-386), type IpAdapterInfo struct, GatewayList IpAddrString
@@ -28791,7 +28779,7 @@ pkg syscall (windows-386), type IpAddrString struct, IpAddress IpAddressString
 pkg syscall (windows-386), type IpAddrString struct, IpMask IpMaskString
 pkg syscall (windows-386), type IpAddrString struct, Next *IpAddrString
 pkg syscall (windows-386), type IpAddressString struct
-pkg syscall (windows-386), type IpAddressString struct, String [16]byte
+pkg syscall (windows-386), type IpAddressString struct, String [16]uint8
 pkg syscall (windows-386), type IpMaskString IpAddressString
 pkg syscall (windows-386), type LazyDLL struct
 pkg syscall (windows-386), type LazyDLL struct, Name string
@@ -28799,7 +28787,7 @@ pkg syscall (windows-386), type LazyProc struct
 pkg syscall (windows-386), type LazyProc struct, Name string
 pkg syscall (windows-386), type MibIfRow struct
 pkg syscall (windows-386), type MibIfRow struct, AdminStatus uint32
-pkg syscall (windows-386), type MibIfRow struct, Descr [MAXLEN_IFDESCR]byte
+pkg syscall (windows-386), type MibIfRow struct, Descr [MAXLEN_IFDESCR]uint8
 pkg syscall (windows-386), type MibIfRow struct, DescrLen uint32
 pkg syscall (windows-386), type MibIfRow struct, InDiscards uint32
 pkg syscall (windows-386), type MibIfRow struct, InErrors uint32
@@ -28818,7 +28806,7 @@ pkg syscall (windows-386), type MibIfRow struct, OutNUcastPkts uint32
 pkg syscall (windows-386), type MibIfRow struct, OutOctets uint32
 pkg syscall (windows-386), type MibIfRow struct, OutQLen uint32
 pkg syscall (windows-386), type MibIfRow struct, OutUcastPkts uint32
-pkg syscall (windows-386), type MibIfRow struct, PhysAddr [MAXLEN_PHYSADDR]byte
+pkg syscall (windows-386), type MibIfRow struct, PhysAddr [MAXLEN_PHYSADDR]uint8
 pkg syscall (windows-386), type MibIfRow struct, PhysAddrLen uint32
 pkg syscall (windows-386), type MibIfRow struct, Speed uint32
 pkg syscall (windows-386), type MibIfRow struct, Type uint32
@@ -28837,8 +28825,8 @@ pkg syscall (windows-386), type ProcessInformation struct, ProcessId uint32
 pkg syscall (windows-386), type ProcessInformation struct, Thread Handle
 pkg syscall (windows-386), type ProcessInformation struct, ThreadId uint32
 pkg syscall (windows-386), type Protoent struct
-pkg syscall (windows-386), type Protoent struct, Aliases **byte
-pkg syscall (windows-386), type Protoent struct, Name *byte
+pkg syscall (windows-386), type Protoent struct, Aliases **uint8
+pkg syscall (windows-386), type Protoent struct, Name *uint8
 pkg syscall (windows-386), type Protoent struct, Proto uint16
 pkg syscall (windows-386), type RawSockaddr struct, Data [14]int8
 pkg syscall (windows-386), type RawSockaddr struct, Family uint16
@@ -28863,11 +28851,11 @@ pkg syscall (windows-386), type SecurityAttributes struct, InheritHandle uint32
 pkg syscall (windows-386), type SecurityAttributes struct, Length uint32
 pkg syscall (windows-386), type SecurityAttributes struct, SecurityDescriptor uintptr
 pkg syscall (windows-386), type Servent struct
-pkg syscall (windows-386), type Servent struct, Aliases **byte
-pkg syscall (windows-386), type Servent struct, Name *byte
+pkg syscall (windows-386), type Servent struct, Aliases **uint8
+pkg syscall (windows-386), type Servent struct, Name *uint8
 pkg syscall (windows-386), type Servent struct, Port uint16
-pkg syscall (windows-386), type Servent struct, Proto *byte
-pkg syscall (windows-386), type SockaddrGen [24]byte
+pkg syscall (windows-386), type Servent struct, Proto *uint8
+pkg syscall (windows-386), type SockaddrGen [24]uint8
 pkg syscall (windows-386), type StartupInfo struct
 pkg syscall (windows-386), type StartupInfo struct, Cb uint32
 pkg syscall (windows-386), type StartupInfo struct, Desktop *uint16
@@ -28923,15 +28911,15 @@ pkg syscall (windows-386), type UserInfo10 struct, FullName *uint16
 pkg syscall (windows-386), type UserInfo10 struct, Name *uint16
 pkg syscall (windows-386), type UserInfo10 struct, UsrComment *uint16
 pkg syscall (windows-386), type WSABuf struct
-pkg syscall (windows-386), type WSABuf struct, Buf *byte
+pkg syscall (windows-386), type WSABuf struct, Buf *uint8
 pkg syscall (windows-386), type WSABuf struct, Len uint32
 pkg syscall (windows-386), type WSAData struct
-pkg syscall (windows-386), type WSAData struct, Description [WSADESCRIPTION_LEN + 1]byte
+pkg syscall (windows-386), type WSAData struct, Description [WSADESCRIPTION_LEN + 1]uint8
 pkg syscall (windows-386), type WSAData struct, HighVersion uint16
 pkg syscall (windows-386), type WSAData struct, MaxSockets uint16
 pkg syscall (windows-386), type WSAData struct, MaxUdpDg uint16
-pkg syscall (windows-386), type WSAData struct, SystemStatus [WSASYS_STATUS_LEN + 1]byte
-pkg syscall (windows-386), type WSAData struct, VendorInfo *byte
+pkg syscall (windows-386), type WSAData struct, SystemStatus [WSASYS_STATUS_LEN + 1]uint8
+pkg syscall (windows-386), type WSAData struct, VendorInfo *uint8
 pkg syscall (windows-386), type WSAData struct, Version uint16
 pkg syscall (windows-386), type WaitStatus struct
 pkg syscall (windows-386), type WaitStatus struct, ExitCode uint32
@@ -28953,9 +28941,9 @@ pkg syscall (windows-386), type Win32finddata struct, LastAccessTime Filetime
 pkg syscall (windows-386), type Win32finddata struct, LastWriteTime Filetime
 pkg syscall (windows-386), type Win32finddata struct, Reserved0 uint32
 pkg syscall (windows-386), type Win32finddata struct, Reserved1 uint32
-pkg syscall (windows-386), var OID_PKIX_KP_SERVER_AUTH []byte
-pkg syscall (windows-386), var OID_SERVER_GATED_CRYPTO []byte
-pkg syscall (windows-386), var OID_SGC_NETSCAPE []byte
+pkg syscall (windows-386), var OID_PKIX_KP_SERVER_AUTH []uint8
+pkg syscall (windows-386), var OID_SERVER_GATED_CRYPTO []uint8
+pkg syscall (windows-386), var OID_SGC_NETSCAPE []uint8
 pkg syscall (windows-386), var Stderr Handle
 pkg syscall (windows-386), var Stdin Handle
 pkg syscall (windows-386), var Stdout Handle
@@ -29374,12 +29362,12 @@ pkg syscall (windows-amd64), const WSADESCRIPTION_LEN ideal-int
 pkg syscall (windows-amd64), const WSASYS_STATUS_LEN ideal-int
 pkg syscall (windows-amd64), const X509_ASN_ENCODING ideal-int
 pkg syscall (windows-amd64), func Accept(Handle) (Handle, Sockaddr, error)
-pkg syscall (windows-amd64), func AcceptEx(Handle, Handle, *byte, uint32, uint32, uint32, *uint32, *Overlapped) error
+pkg syscall (windows-amd64), func AcceptEx(Handle, Handle, *uint8, uint32, uint32, uint32, *uint32, *Overlapped) error
 pkg syscall (windows-amd64), func Bind(Handle, Sockaddr) error
 pkg syscall (windows-amd64), func CancelIo(Handle) error
 pkg syscall (windows-amd64), func CertAddCertificateContextToStore(Handle, *CertContext, uint32, **CertContext) error
 pkg syscall (windows-amd64), func CertCloseStore(Handle, uint32) error
-pkg syscall (windows-amd64), func CertCreateCertificateContext(uint32, *byte, uint32) (*CertContext, error)
+pkg syscall (windows-amd64), func CertCreateCertificateContext(uint32, *uint8, uint32) (*CertContext, error)
 pkg syscall (windows-amd64), func CertEnumCertificatesInStore(Handle, *CertContext) (*CertContext, error)
 pkg syscall (windows-amd64), func CertFreeCertificateChain(*CertChainContext)
 pkg syscall (windows-amd64), func CertFreeCertificateContext(*CertContext) error
@@ -29404,10 +29392,10 @@ pkg syscall (windows-amd64), func CreateIoCompletionPort(Handle, Handle, uint32,
 pkg syscall (windows-amd64), func CreatePipe(*Handle, *Handle, *SecurityAttributes, uint32) error
 pkg syscall (windows-amd64), func CreateProcess(*uint16, *uint16, *SecurityAttributes, *SecurityAttributes, bool, uint32, *uint16, *uint16, *StartupInfo, *ProcessInformation) error
 pkg syscall (windows-amd64), func CryptAcquireContext(*Handle, *uint16, *uint16, uint32, uint32) error
-pkg syscall (windows-amd64), func CryptGenRandom(Handle, uint32, *byte) error
+pkg syscall (windows-amd64), func CryptGenRandom(Handle, uint32, *uint8) error
 pkg syscall (windows-amd64), func CryptReleaseContext(Handle, uint32) error
 pkg syscall (windows-amd64), func DeleteFile(*uint16) error
-pkg syscall (windows-amd64), func DnsQuery(string, uint16, uint32, *byte, **DNSRecord, *byte) error
+pkg syscall (windows-amd64), func DnsQuery(string, uint16, uint32, *uint8, **DNSRecord, *uint8) error
 pkg syscall (windows-amd64), func DnsRecordListFree(*DNSRecord, uint32)
 pkg syscall (windows-amd64), func DuplicateHandle(Handle, Handle, Handle, *Handle, uint32, bool, uint32) error
 pkg syscall (windows-amd64), func EscapeArg(string) string
@@ -29420,12 +29408,12 @@ pkg syscall (windows-amd64), func FindFirstFile(*uint16, *Win32finddata) (Handle
 pkg syscall (windows-amd64), func FindNextFile(Handle, *Win32finddata) error
 pkg syscall (windows-amd64), func FlushFileBuffers(Handle) error
 pkg syscall (windows-amd64), func FlushViewOfFile(uintptr, uintptr) error
-pkg syscall (windows-amd64), func FormatMessage(uint32, uint32, uint32, uint32, []uint16, *byte) (uint32, error)
+pkg syscall (windows-amd64), func FormatMessage(uint32, uint32, uint32, uint32, []uint16, *uint8) (uint32, error)
 pkg syscall (windows-amd64), func FreeEnvironmentStrings(*uint16) error
 pkg syscall (windows-amd64), func FreeLibrary(Handle) error
 pkg syscall (windows-amd64), func Fsync(Handle) error
 pkg syscall (windows-amd64), func Ftruncate(Handle, int64) error
-pkg syscall (windows-amd64), func GetAcceptExSockaddrs(*byte, uint32, uint32, uint32, **RawSockaddrAny, *int32, **RawSockaddrAny, *int32)
+pkg syscall (windows-amd64), func GetAcceptExSockaddrs(*uint8, uint32, uint32, uint32, **RawSockaddrAny, *int32, **RawSockaddrAny, *int32)
 pkg syscall (windows-amd64), func GetAdaptersInfo(*IpAdapterInfo, *uint32) error
 pkg syscall (windows-amd64), func GetCommandLine() *uint16
 pkg syscall (windows-amd64), func GetComputerName(*uint16, *uint32) error
@@ -29435,7 +29423,7 @@ pkg syscall (windows-amd64), func GetEnvironmentStrings() (*uint16, error)
 pkg syscall (windows-amd64), func GetEnvironmentVariable(*uint16, *uint16, uint32) (uint32, error)
 pkg syscall (windows-amd64), func GetExitCodeProcess(Handle, *uint32) error
 pkg syscall (windows-amd64), func GetFileAttributes(*uint16) (uint32, error)
-pkg syscall (windows-amd64), func GetFileAttributesEx(*uint16, uint32, *byte) error
+pkg syscall (windows-amd64), func GetFileAttributesEx(*uint16, uint32, *uint8) error
 pkg syscall (windows-amd64), func GetFileInformationByHandle(Handle, *ByHandleFileInformation) error
 pkg syscall (windows-amd64), func GetFileType(Handle) (uint32, error)
 pkg syscall (windows-amd64), func GetFullPathName(*uint16, uint32, *uint16, **uint16) (uint32, error)
@@ -29455,26 +29443,25 @@ pkg syscall (windows-amd64), func GetStdHandle(int) (Handle, error)
 pkg syscall (windows-amd64), func GetSystemTimeAsFileTime(*Filetime)
 pkg syscall (windows-amd64), func GetTempPath(uint32, *uint16) (uint32, error)
 pkg syscall (windows-amd64), func GetTimeZoneInformation(*Timezoneinformation) (uint32, error)
-pkg syscall (windows-amd64), func GetTokenInformation(Token, uint32, *byte, uint32, *uint32) error
+pkg syscall (windows-amd64), func GetTokenInformation(Token, uint32, *uint8, uint32, *uint32) error
 pkg syscall (windows-amd64), func GetUserNameEx(uint32, *uint16, *uint32) error
 pkg syscall (windows-amd64), func GetUserProfileDirectory(Token, *uint16, *uint32) error
 pkg syscall (windows-amd64), func GetVersion() (uint32, error)
 pkg syscall (windows-amd64), func Getpeername(Handle) (Sockaddr, error)
 pkg syscall (windows-amd64), func Getsockname(Handle) (Sockaddr, error)
-pkg syscall (windows-amd64), func GetsockoptInt(Handle, int) (int, error)
-pkg syscall (windows-amd64), func Link(string) error
+pkg syscall (windows-amd64), func GetsockoptInt(Handle, int, int) (int, error)
 pkg syscall (windows-amd64), func Listen(Handle, int) error
 pkg syscall (windows-amd64), func LoadDLL(string) (*DLL, error)
 pkg syscall (windows-amd64), func LoadLibrary(string) (Handle, error)
 pkg syscall (windows-amd64), func LocalFree(Handle) (Handle, error)
 pkg syscall (windows-amd64), func LookupAccountName(*uint16, *uint16, *SID, *uint32, *uint16, *uint32, *uint32) error
 pkg syscall (windows-amd64), func LookupAccountSid(*uint16, *SID, *uint16, *uint32, *uint16, *uint32, *uint32) error
-pkg syscall (windows-amd64), func LookupSID(string) (*SID, string, uint32, error)
+pkg syscall (windows-amd64), func LookupSID(string, string) (*SID, string, uint32, error)
 pkg syscall (windows-amd64), func MapViewOfFile(Handle, uint32, uint32, uint32, uintptr) (uintptr, error)
 pkg syscall (windows-amd64), func MoveFile(*uint16, *uint16) error
 pkg syscall (windows-amd64), func MustLoadDLL(string) *DLL
-pkg syscall (windows-amd64), func NetApiBufferFree(*byte) error
-pkg syscall (windows-amd64), func NetUserGetInfo(*uint16, *uint16, uint32, **byte) error
+pkg syscall (windows-amd64), func NetApiBufferFree(*uint8) error
+pkg syscall (windows-amd64), func NetUserGetInfo(*uint16, *uint16, uint32, **uint8) error
 pkg syscall (windows-amd64), func NewCallback(interface{}) uintptr
 pkg syscall (windows-amd64), func NewLazyDLL(string) *LazyDLL
 pkg syscall (windows-amd64), func NsecToFiletime(int64) Filetime
@@ -29485,19 +29472,18 @@ pkg syscall (windows-amd64), func OpenProcess(uint32, bool, uint32) (Handle, err
 pkg syscall (windows-amd64), func OpenProcessToken(Handle, uint32, *Token) error
 pkg syscall (windows-amd64), func Pipe([]Handle) error
 pkg syscall (windows-amd64), func PostQueuedCompletionStatus(Handle, uint32, uint32, *Overlapped) error
-pkg syscall (windows-amd64), func Read(Handle, []byte) (int, error)
-pkg syscall (windows-amd64), func ReadDirectoryChanges(Handle, *byte, uint32, bool, uint32, *uint32, *Overlapped, uintptr) error
-pkg syscall (windows-amd64), func ReadFile(Handle, []byte, *uint32, *Overlapped) error
-pkg syscall (windows-amd64), func Recvfrom(Handle, []byte, int) (int, Sockaddr, error)
+pkg syscall (windows-amd64), func Read(Handle, []uint8) (int, error)
+pkg syscall (windows-amd64), func ReadDirectoryChanges(Handle, *uint8, uint32, bool, uint32, *uint32, *Overlapped, uintptr) error
+pkg syscall (windows-amd64), func ReadFile(Handle, []uint8, *uint32, *Overlapped) error
+pkg syscall (windows-amd64), func Recvfrom(Handle, []uint8, int) (int, Sockaddr, error)
 pkg syscall (windows-amd64), func RegCloseKey(Handle) error
 pkg syscall (windows-amd64), func RegEnumKeyEx(Handle, uint32, *uint16, *uint32, *uint32, *uint16, *uint32, *Filetime) error
 pkg syscall (windows-amd64), func RegOpenKeyEx(Handle, *uint16, uint32, uint32, *Handle) error
 pkg syscall (windows-amd64), func RegQueryInfoKey(Handle, *uint16, *uint32, *uint32, *uint32, *uint32, *uint32, *uint32, *uint32, *uint32, *uint32, *Filetime) error
-pkg syscall (windows-amd64), func RegQueryValueEx(Handle, *uint16, *uint32, *uint32, *byte, *uint32) error
+pkg syscall (windows-amd64), func RegQueryValueEx(Handle, *uint16, *uint32, *uint32, *uint8, *uint32) error
 pkg syscall (windows-amd64), func RemoveDirectory(*uint16) error
-pkg syscall (windows-amd64), func Rename(string) error
 pkg syscall (windows-amd64), func Seek(Handle, int64, int) (int64, error)
-pkg syscall (windows-amd64), func Sendto(Handle, []byte, int, Sockaddr) error
+pkg syscall (windows-amd64), func Sendto(Handle, []uint8, int, Sockaddr) error
 pkg syscall (windows-amd64), func SetCurrentDirectory(*uint16) error
 pkg syscall (windows-amd64), func SetEndOfFile(Handle) error
 pkg syscall (windows-amd64), func SetEnvironmentVariable(*uint16, *uint16) error
@@ -29506,24 +29492,25 @@ pkg syscall (windows-amd64), func SetFilePointer(Handle, int32, *int32, uint32)
 pkg syscall (windows-amd64), func SetFileTime(Handle, *Filetime, *Filetime, *Filetime) error
 pkg syscall (windows-amd64), func SetHandleInformation(Handle, uint32, uint32) error
 pkg syscall (windows-amd64), func SetNonblock(Handle, bool) error
-pkg syscall (windows-amd64), func Setsockopt(Handle, int32, int32, *byte, int32) error
-pkg syscall (windows-amd64), func SetsockoptIPMreq(Handle, int, *IPMreq) error
-pkg syscall (windows-amd64), func SetsockoptIPv6Mreq(Handle, int, *IPv6Mreq) error
-pkg syscall (windows-amd64), func SetsockoptInet4Addr(Handle, int, [4]byte) error
-pkg syscall (windows-amd64), func SetsockoptInt(Handle, int, int) error
-pkg syscall (windows-amd64), func SetsockoptLinger(Handle, int, *Linger) error
-pkg syscall (windows-amd64), func SetsockoptTimeval(Handle, int, *Timeval) error
+pkg syscall (windows-amd64), func Setsockopt(Handle, int32, int32, *uint8, int32) error
+pkg syscall (windows-amd64), func SetsockoptIPMreq(Handle, int, int, *IPMreq) error
+pkg syscall (windows-amd64), func SetsockoptIPv6Mreq(Handle, int, int, *IPv6Mreq) error
+pkg syscall (windows-amd64), func SetsockoptInet4Addr(Handle, int, int, [4]uint8) error
+pkg syscall (windows-amd64), func SetsockoptInt(Handle, int, int, int) error
+pkg syscall (windows-amd64), func SetsockoptLinger(Handle, int, int, *Linger) error
+pkg syscall (windows-amd64), func SetsockoptTimeval(Handle, int, int, *Timeval) error
 pkg syscall (windows-amd64), func Shutdown(Handle, int) error
-pkg syscall (windows-amd64), func Socket(int) (Handle, error)
+pkg syscall (windows-amd64), func Socket(int, int, int) (Handle, error)
 pkg syscall (windows-amd64), func StringToSid(string) (*SID, error)
 pkg syscall (windows-amd64), func StringToUTF16(string) []uint16
 pkg syscall (windows-amd64), func StringToUTF16Ptr(string) *uint16
-pkg syscall (windows-amd64), func Symlink(string) error
-pkg syscall (windows-amd64), func Syscall12(uintptr) (uintptr, Errno)
-pkg syscall (windows-amd64), func Syscall15(uintptr) (uintptr, Errno)
-pkg syscall (windows-amd64), func Syscall9(uintptr) (uintptr, Errno)
+pkg syscall (windows-amd64), func Syscall(uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (windows-amd64), func Syscall12(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (windows-amd64), func Syscall15(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (windows-amd64), func Syscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (windows-amd64), func Syscall9(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
 pkg syscall (windows-amd64), func TerminateProcess(Handle, uint32) error
-pkg syscall (windows-amd64), func TranslateAccountName(string, uint32, int) (string, error)
+pkg syscall (windows-amd64), func TranslateAccountName(string, uint32, uint32, int) (string, error)
 pkg syscall (windows-amd64), func TranslateName(*uint16, uint32, uint32, *uint16, *uint32) error
 pkg syscall (windows-amd64), func TransmitFile(Handle, Handle, uint32, uint32, *Overlapped, *TransmitFileBuffers, uint32) error
 pkg syscall (windows-amd64), func UTF16ToString([]uint16) string
@@ -29531,16 +29518,16 @@ pkg syscall (windows-amd64), func UnmapViewOfFile(uintptr) error
 pkg syscall (windows-amd64), func VirtualLock(uintptr, uintptr) error
 pkg syscall (windows-amd64), func VirtualUnlock(uintptr, uintptr) error
 pkg syscall (windows-amd64), func WSACleanup() error
-pkg syscall (windows-amd64), func WSAIoctl(Handle, uint32, *byte, uint32, *byte, uint32, *uint32, *Overlapped, uintptr) error
-pkg syscall (windows-amd64), func WSARecv(Handle, *WSABuf, uint32, *uint32, *uint32, *Overlapped, *byte) error
-pkg syscall (windows-amd64), func WSARecvFrom(Handle, *WSABuf, uint32, *uint32, *uint32, *RawSockaddrAny, *int32, *Overlapped, *byte) error
-pkg syscall (windows-amd64), func WSASend(Handle, *WSABuf, uint32, *uint32, uint32, *Overlapped, *byte) error
-pkg syscall (windows-amd64), func WSASendTo(Handle, *WSABuf, uint32, *uint32, uint32, *RawSockaddrAny, int32, *Overlapped, *byte) error
-pkg syscall (windows-amd64), func WSASendto(Handle, *WSABuf, uint32, *uint32, uint32, Sockaddr, *Overlapped, *byte) error
+pkg syscall (windows-amd64), func WSAIoctl(Handle, uint32, *uint8, uint32, *uint8, uint32, *uint32, *Overlapped, uintptr) error
+pkg syscall (windows-amd64), func WSARecv(Handle, *WSABuf, uint32, *uint32, *uint32, *Overlapped, *uint8) error
+pkg syscall (windows-amd64), func WSARecvFrom(Handle, *WSABuf, uint32, *uint32, *uint32, *RawSockaddrAny, *int32, *Overlapped, *uint8) error
+pkg syscall (windows-amd64), func WSASend(Handle, *WSABuf, uint32, *uint32, uint32, *Overlapped, *uint8) error
+pkg syscall (windows-amd64), func WSASendTo(Handle, *WSABuf, uint32, *uint32, uint32, *RawSockaddrAny, int32, *Overlapped, *uint8) error
+pkg syscall (windows-amd64), func WSASendto(Handle, *WSABuf, uint32, *uint32, uint32, Sockaddr, *Overlapped, *uint8) error
 pkg syscall (windows-amd64), func WSAStartup(uint32, *WSAData) error
 pkg syscall (windows-amd64), func WaitForSingleObject(Handle, uint32) (uint32, error)
-pkg syscall (windows-amd64), func Write(Handle, []byte) (int, error)
-pkg syscall (windows-amd64), func WriteFile(Handle, []byte, *uint32, *Overlapped) error
+pkg syscall (windows-amd64), func Write(Handle, []uint8) (int, error)
+pkg syscall (windows-amd64), func WriteFile(Handle, []uint8, *uint32, *Overlapped) error
 pkg syscall (windows-amd64), method (*DLL) FindProc(string) (*Proc, error)
 pkg syscall (windows-amd64), method (*DLL) MustFindProc(string) *Proc
 pkg syscall (windows-amd64), method (*DLL) Release() error
@@ -29550,14 +29537,14 @@ pkg syscall (windows-amd64), method (*LazyDLL) Handle() uintptr
 pkg syscall (windows-amd64), method (*LazyDLL) Load() error
 pkg syscall (windows-amd64), method (*LazyDLL) NewProc(string) *LazyProc
 pkg syscall (windows-amd64), method (*LazyProc) Addr() uintptr
-pkg syscall (windows-amd64), method (*LazyProc) Call(...uintptr) (uintptr, error)
+pkg syscall (windows-amd64), method (*LazyProc) Call(...uintptr) (uintptr, uintptr, error)
 pkg syscall (windows-amd64), method (*LazyProc) Find() error
 pkg syscall (windows-amd64), method (*Proc) Addr() uintptr
-pkg syscall (windows-amd64), method (*Proc) Call(...uintptr) (uintptr, error)
+pkg syscall (windows-amd64), method (*Proc) Call(...uintptr) (uintptr, uintptr, error)
 pkg syscall (windows-amd64), method (*RawSockaddrAny) Sockaddr() (Sockaddr, error)
 pkg syscall (windows-amd64), method (*SID) Copy() (*SID, error)
 pkg syscall (windows-amd64), method (*SID) Len() int
-pkg syscall (windows-amd64), method (*SID) LookupAccount(string) (string, uint32, error)
+pkg syscall (windows-amd64), method (*SID) LookupAccount(string) (string, string, uint32, error)
 pkg syscall (windows-amd64), method (*SID) String() (string, error)
 pkg syscall (windows-amd64), method (*Timeval) Nanoseconds() int64
 pkg syscall (windows-amd64), method (Token) Close() error
@@ -29612,19 +29599,19 @@ pkg syscall (windows-amd64), type CertChainPolicyStatus struct, ExtraPolicyStatu
 pkg syscall (windows-amd64), type CertChainPolicyStatus struct, Size uint32
 pkg syscall (windows-amd64), type CertContext struct
 pkg syscall (windows-amd64), type CertContext struct, CertInfo uintptr
-pkg syscall (windows-amd64), type CertContext struct, EncodedCert *byte
+pkg syscall (windows-amd64), type CertContext struct, EncodedCert *uint8
 pkg syscall (windows-amd64), type CertContext struct, EncodingType uint32
 pkg syscall (windows-amd64), type CertContext struct, Length uint32
 pkg syscall (windows-amd64), type CertContext struct, Store Handle
 pkg syscall (windows-amd64), type CertEnhKeyUsage struct
 pkg syscall (windows-amd64), type CertEnhKeyUsage struct, Length uint32
-pkg syscall (windows-amd64), type CertEnhKeyUsage struct, UsageIdentifiers **byte
+pkg syscall (windows-amd64), type CertEnhKeyUsage struct, UsageIdentifiers **uint8
 pkg syscall (windows-amd64), type CertRevocationInfo struct
 pkg syscall (windows-amd64), type CertRevocationInfo struct, CrlInfo uintptr
 pkg syscall (windows-amd64), type CertRevocationInfo struct, FreshnessTime uint32
 pkg syscall (windows-amd64), type CertRevocationInfo struct, HasFreshnessTime uint32
 pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uintptr
-pkg syscall (windows-amd64), type CertRevocationInfo struct, RevocationOid *byte
+pkg syscall (windows-amd64), type CertRevocationInfo struct, RevocationOid *uint8
 pkg syscall (windows-amd64), type CertRevocationInfo struct, RevocationResult uint32
 pkg syscall (windows-amd64), type CertRevocationInfo struct, Size uint32
 pkg syscall (windows-amd64), type CertSimpleChain struct
@@ -29655,7 +29642,7 @@ pkg syscall (windows-amd64), type DNSMXData struct, Preference uint16
 pkg syscall (windows-amd64), type DNSPTRData struct
 pkg syscall (windows-amd64), type DNSPTRData struct, Host *uint16
 pkg syscall (windows-amd64), type DNSRecord struct
-pkg syscall (windows-amd64), type DNSRecord struct, Data [40]byte
+pkg syscall (windows-amd64), type DNSRecord struct, Data [40]uint8
 pkg syscall (windows-amd64), type DNSRecord struct, Dw uint32
 pkg syscall (windows-amd64), type DNSRecord struct, Length uint16
 pkg syscall (windows-amd64), type DNSRecord struct, Name *uint16
@@ -29682,23 +29669,23 @@ pkg syscall (windows-amd64), type Filetime struct, HighDateTime uint32
 pkg syscall (windows-amd64), type Filetime struct, LowDateTime uint32
 pkg syscall (windows-amd64), type Handle uintptr
 pkg syscall (windows-amd64), type Hostent struct
-pkg syscall (windows-amd64), type Hostent struct, AddrList **byte
+pkg syscall (windows-amd64), type Hostent struct, AddrList **uint8
 pkg syscall (windows-amd64), type Hostent struct, AddrType uint16
-pkg syscall (windows-amd64), type Hostent struct, Aliases **byte
+pkg syscall (windows-amd64), type Hostent struct, Aliases **uint8
 pkg syscall (windows-amd64), type Hostent struct, Length uint16
-pkg syscall (windows-amd64), type Hostent struct, Name *byte
+pkg syscall (windows-amd64), type Hostent struct, Name *uint8
 pkg syscall (windows-amd64), type InterfaceInfo struct
 pkg syscall (windows-amd64), type InterfaceInfo struct, Address SockaddrGen
 pkg syscall (windows-amd64), type InterfaceInfo struct, BroadcastAddress SockaddrGen
 pkg syscall (windows-amd64), type InterfaceInfo struct, Flags uint32
 pkg syscall (windows-amd64), type InterfaceInfo struct, Netmask SockaddrGen
 pkg syscall (windows-amd64), type IpAdapterInfo struct
-pkg syscall (windows-amd64), type IpAdapterInfo struct, AdapterName [MAX_ADAPTER_NAME_LENGTH + 4]byte
-pkg syscall (windows-amd64), type IpAdapterInfo struct, Address [MAX_ADAPTER_ADDRESS_LENGTH]byte
+pkg syscall (windows-amd64), type IpAdapterInfo struct, AdapterName [MAX_ADAPTER_NAME_LENGTH + 4]uint8
+pkg syscall (windows-amd64), type IpAdapterInfo struct, Address [MAX_ADAPTER_ADDRESS_LENGTH]uint8
 pkg syscall (windows-amd64), type IpAdapterInfo struct, AddressLength uint32
 pkg syscall (windows-amd64), type IpAdapterInfo struct, ComboIndex uint32
 pkg syscall (windows-amd64), type IpAdapterInfo struct, CurrentIpAddress *IpAddrString
-pkg syscall (windows-amd64), type IpAdapterInfo struct, Description [MAX_ADAPTER_DESCRIPTION_LENGTH + 4]byte
+pkg syscall (windows-amd64), type IpAdapterInfo struct, Description [MAX_ADAPTER_DESCRIPTION_LENGTH + 4]uint8
 pkg syscall (windows-amd64), type IpAdapterInfo struct, DhcpEnabled uint32
 pkg syscall (windows-amd64), type IpAdapterInfo struct, DhcpServer IpAddrString
 pkg syscall (windows-amd64), type IpAdapterInfo struct, GatewayList IpAddrString
@@ -29717,7 +29704,7 @@ pkg syscall (windows-amd64), type IpAddrString struct, IpAddress IpAddressString
 pkg syscall (windows-amd64), type IpAddrString struct, IpMask IpMaskString
 pkg syscall (windows-amd64), type IpAddrString struct, Next *IpAddrString
 pkg syscall (windows-amd64), type IpAddressString struct
-pkg syscall (windows-amd64), type IpAddressString struct, String [16]byte
+pkg syscall (windows-amd64), type IpAddressString struct, String [16]uint8
 pkg syscall (windows-amd64), type IpMaskString IpAddressString
 pkg syscall (windows-amd64), type LazyDLL struct
 pkg syscall (windows-amd64), type LazyDLL struct, Name string
@@ -29725,7 +29712,7 @@ pkg syscall (windows-amd64), type LazyProc struct
 pkg syscall (windows-amd64), type LazyProc struct, Name string
 pkg syscall (windows-amd64), type MibIfRow struct
 pkg syscall (windows-amd64), type MibIfRow struct, AdminStatus uint32
-pkg syscall (windows-amd64), type MibIfRow struct, Descr [MAXLEN_IFDESCR]byte
+pkg syscall (windows-amd64), type MibIfRow struct, Descr [MAXLEN_IFDESCR]uint8
 pkg syscall (windows-amd64), type MibIfRow struct, DescrLen uint32
 pkg syscall (windows-amd64), type MibIfRow struct, InDiscards uint32
 pkg syscall (windows-amd64), type MibIfRow struct, InErrors uint32
@@ -29744,7 +29731,7 @@ pkg syscall (windows-amd64), type MibIfRow struct, OutNUcastPkts uint32
 pkg syscall (windows-amd64), type MibIfRow struct, OutOctets uint32
 pkg syscall (windows-amd64), type MibIfRow struct, OutQLen uint32
 pkg syscall (windows-amd64), type MibIfRow struct, OutUcastPkts uint32
-pkg syscall (windows-amd64), type MibIfRow struct, PhysAddr [MAXLEN_PHYSADDR]byte
+pkg syscall (windows-amd64), type MibIfRow struct, PhysAddr [MAXLEN_PHYSADDR]uint8
 pkg syscall (windows-amd64), type MibIfRow struct, PhysAddrLen uint32
 pkg syscall (windows-amd64), type MibIfRow struct, Speed uint32
 pkg syscall (windows-amd64), type MibIfRow struct, Type uint32
@@ -29763,8 +29750,8 @@ pkg syscall (windows-amd64), type ProcessInformation struct, ProcessId uint32
 pkg syscall (windows-amd64), type ProcessInformation struct, Thread Handle
 pkg syscall (windows-amd64), type ProcessInformation struct, ThreadId uint32
 pkg syscall (windows-amd64), type Protoent struct
-pkg syscall (windows-amd64), type Protoent struct, Aliases **byte
-pkg syscall (windows-amd64), type Protoent struct, Name *byte
+pkg syscall (windows-amd64), type Protoent struct, Aliases **uint8
+pkg syscall (windows-amd64), type Protoent struct, Name *uint8
 pkg syscall (windows-amd64), type Protoent struct, Proto uint16
 pkg syscall (windows-amd64), type RawSockaddr struct, Data [14]int8
 pkg syscall (windows-amd64), type RawSockaddr struct, Family uint16
@@ -29789,11 +29776,11 @@ pkg syscall (windows-amd64), type SecurityAttributes struct, InheritHandle uint3
 pkg syscall (windows-amd64), type SecurityAttributes struct, Length uint32
 pkg syscall (windows-amd64), type SecurityAttributes struct, SecurityDescriptor uintptr
 pkg syscall (windows-amd64), type Servent struct
-pkg syscall (windows-amd64), type Servent struct, Aliases **byte
-pkg syscall (windows-amd64), type Servent struct, Name *byte
+pkg syscall (windows-amd64), type Servent struct, Aliases **uint8
+pkg syscall (windows-amd64), type Servent struct, Name *uint8
 pkg syscall (windows-amd64), type Servent struct, Port uint16
-pkg syscall (windows-amd64), type Servent struct, Proto *byte
-pkg syscall (windows-amd64), type SockaddrGen [24]byte
+pkg syscall (windows-amd64), type Servent struct, Proto *uint8
+pkg syscall (windows-amd64), type SockaddrGen [24]uint8
 pkg syscall (windows-amd64), type StartupInfo struct
 pkg syscall (windows-amd64), type StartupInfo struct, Cb uint32
 pkg syscall (windows-amd64), type StartupInfo struct, Desktop *uint16
@@ -29849,15 +29836,15 @@ pkg syscall (windows-amd64), type UserInfo10 struct, FullName *uint16
 pkg syscall (windows-amd64), type UserInfo10 struct, Name *uint16
 pkg syscall (windows-amd64), type UserInfo10 struct, UsrComment *uint16
 pkg syscall (windows-amd64), type WSABuf struct
-pkg syscall (windows-amd64), type WSABuf struct, Buf *byte
+pkg syscall (windows-amd64), type WSABuf struct, Buf *uint8
 pkg syscall (windows-amd64), type WSABuf struct, Len uint32
 pkg syscall (windows-amd64), type WSAData struct
-pkg syscall (windows-amd64), type WSAData struct, Description [WSADESCRIPTION_LEN + 1]byte
+pkg syscall (windows-amd64), type WSAData struct, Description [WSADESCRIPTION_LEN + 1]uint8
 pkg syscall (windows-amd64), type WSAData struct, HighVersion uint16
 pkg syscall (windows-amd64), type WSAData struct, MaxSockets uint16
 pkg syscall (windows-amd64), type WSAData struct, MaxUdpDg uint16
-pkg syscall (windows-amd64), type WSAData struct, SystemStatus [WSASYS_STATUS_LEN + 1]byte
-pkg syscall (windows-amd64), type WSAData struct, VendorInfo *byte
+pkg syscall (windows-amd64), type WSAData struct, SystemStatus [WSASYS_STATUS_LEN + 1]uint8
+pkg syscall (windows-amd64), type WSAData struct, VendorInfo *uint8
 pkg syscall (windows-amd64), type WSAData struct, Version uint16
 pkg syscall (windows-amd64), type WaitStatus struct
 pkg syscall (windows-amd64), type WaitStatus struct, ExitCode uint32
@@ -29879,9 +29866,9 @@ pkg syscall (windows-amd64), type Win32finddata struct, LastAccessTime Filetime
 pkg syscall (windows-amd64), type Win32finddata struct, LastWriteTime Filetime
 pkg syscall (windows-amd64), type Win32finddata struct, Reserved0 uint32
 pkg syscall (windows-amd64), type Win32finddata struct, Reserved1 uint32
-pkg syscall (windows-amd64), var OID_PKIX_KP_SERVER_AUTH []byte
-pkg syscall (windows-amd64), var OID_SERVER_GATED_CRYPTO []byte
-pkg syscall (windows-amd64), var OID_SGC_NETSCAPE []byte
+pkg syscall (windows-amd64), var OID_PKIX_KP_SERVER_AUTH []uint8
+pkg syscall (windows-amd64), var OID_SERVER_GATED_CRYPTO []uint8
+pkg syscall (windows-amd64), var OID_SGC_NETSCAPE []uint8
 pkg syscall (windows-amd64), var Stderr Handle
 pkg syscall (windows-amd64), var Stdin Handle
 pkg syscall (windows-amd64), var Stdout Handle
@@ -30070,16 +30057,17 @@ pkg syscall, func Gettimeofday(*Timeval) error
 pkg syscall, func Getuid() int
 pkg syscall, func Getwd() (string, error)
 pkg syscall, func Lchown(string, int, int) error
+pkg syscall, func Link(string, string) error
 pkg syscall, func Mkdir(string, uint32) error
 pkg syscall, func NsecToTimeval(int64) Timeval
-pkg syscall, func Readlink(string, []byte) (int, error)
+pkg syscall, func Readlink(string, []uint8) (int, error)
+pkg syscall, func Rename(string, string) error
 pkg syscall, func Rmdir(string) error
-pkg syscall, func Setenv(string) error
+pkg syscall, func Setenv(string, string) error
 pkg syscall, func StartProcess(string, []string, *ProcAttr) (int, uintptr, error)
-pkg syscall, func StringBytePtr(string) *byte
-pkg syscall, func StringByteSlice(string) []byte
-pkg syscall, func Syscall(uintptr) (uintptr, Errno)
-pkg syscall, func Syscall6(uintptr) (uintptr, Errno)
+pkg syscall, func StringBytePtr(string) *uint8
+pkg syscall, func StringByteSlice(string) []uint8
+pkg syscall, func Symlink(string, string) error
 pkg syscall, func Unlink(string) error
 pkg syscall, func Utimes(string, []Timeval) error
 pkg syscall, method (*Timespec) Nano() int64
@@ -30102,11 +30090,11 @@ pkg syscall, method (WaitStatus) Stopped() bool
 pkg syscall, method (WaitStatus) TrapCause() int
 pkg syscall, type Errno uintptr
 pkg syscall, type IPMreq struct
-pkg syscall, type IPMreq struct, Interface [4]byte
-pkg syscall, type IPMreq struct, Multiaddr [4]byte
+pkg syscall, type IPMreq struct, Interface [4]uint8
+pkg syscall, type IPMreq struct, Multiaddr [4]uint8
 pkg syscall, type IPv6Mreq struct
 pkg syscall, type IPv6Mreq struct, Interface uint32
-pkg syscall, type IPv6Mreq struct, Multiaddr [16]byte
+pkg syscall, type IPv6Mreq struct, Multiaddr [16]uint8
 pkg syscall, type Linger struct
 pkg syscall, type Linger struct, Linger int32
 pkg syscall, type Linger struct, Onoff int32
@@ -30119,16 +30107,16 @@ pkg syscall, type RawSockaddr struct
 pkg syscall, type RawSockaddrAny struct
 pkg syscall, type RawSockaddrAny struct, Addr RawSockaddr
 pkg syscall, type RawSockaddrInet4 struct
-pkg syscall, type RawSockaddrInet4 struct, Addr [4]byte
+pkg syscall, type RawSockaddrInet4 struct, Addr [4]uint8
 pkg syscall, type RawSockaddrInet4 struct, Port uint16
 pkg syscall, type Rusage struct
 pkg syscall, type Signal int
-pkg syscall, type Sockaddr interface {}
+pkg syscall, type Sockaddr interface, unexported methods
 pkg syscall, type SockaddrInet4 struct
-pkg syscall, type SockaddrInet4 struct, Addr [4]byte
+pkg syscall, type SockaddrInet4 struct, Addr [4]uint8
 pkg syscall, type SockaddrInet4 struct, Port int
 pkg syscall, type SockaddrInet6 struct
-pkg syscall, type SockaddrInet6 struct, Addr [16]byte
+pkg syscall, type SockaddrInet6 struct, Addr [16]uint8
 pkg syscall, type SockaddrInet6 struct, Port int
 pkg syscall, type SockaddrInet6 struct, ZoneId uint32
 pkg syscall, type SockaddrUnix struct
@@ -30139,10 +30127,10 @@ pkg syscall, type Timeval struct
 pkg syscall, var ForkLock sync.RWMutex
 pkg syscall, var SocketDisableIPv6 bool
 pkg testing, func Benchmark(func(*B)) BenchmarkResult
-pkg testing, func Main(func(string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample)
-pkg testing, func RunBenchmarks(func(string) (bool, error), []InternalBenchmark)
-pkg testing, func RunExamples(func(string) (bool, error), []InternalExample) bool
-pkg testing, func RunTests(func(string) (bool, error), []InternalTest) bool
+pkg testing, func Main(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample)
+pkg testing, func RunBenchmarks(func(string, string) (bool, error), []InternalBenchmark)
+pkg testing, func RunExamples(func(string, string) (bool, error), []InternalExample) bool
+pkg testing, func RunTests(func(string, string) (bool, error), []InternalTest) bool
 pkg testing, func Short() bool
 pkg testing, method (*B) Error(...interface{})
 pkg testing, method (*B) Errorf(string, ...interface{})
@@ -30195,7 +30183,7 @@ pkg testing/iotest, func TimeoutReader(io.Reader) io.Reader
 pkg testing/iotest, func TruncateWriter(io.Writer, int64) io.Writer
 pkg testing/iotest, var ErrTimeout error
 pkg testing/quick, func Check(interface{}, *Config) error
-pkg testing/quick, func CheckEqual(interface{}, *Config) error
+pkg testing/quick, func CheckEqual(interface{}, interface{}, *Config) error
 pkg testing/quick, func Value(reflect.Type, *rand.Rand) (reflect.Value, bool)
 pkg testing/quick, method (*CheckEqualError) Error() string
 pkg testing/quick, method (*CheckError) Error() string
@@ -30233,14 +30221,14 @@ pkg text/scanner, const ScanRawStrings ideal-int
 pkg text/scanner, const ScanStrings ideal-int
 pkg text/scanner, const SkipComments ideal-int
 pkg text/scanner, const String ideal-int
-pkg text/scanner, func TokenString(rune) string
+pkg text/scanner, func TokenString(int32) string
 pkg text/scanner, method (*Position) IsValid() bool
 pkg text/scanner, method (*Scanner) Init(io.Reader) *Scanner
 pkg text/scanner, method (*Scanner) IsValid() bool
-pkg text/scanner, method (*Scanner) Next() rune
-pkg text/scanner, method (*Scanner) Peek() rune
+pkg text/scanner, method (*Scanner) Next() int32
+pkg text/scanner, method (*Scanner) Peek() int32
 pkg text/scanner, method (*Scanner) Pos() Position
-pkg text/scanner, method (*Scanner) Scan() rune
+pkg text/scanner, method (*Scanner) Scan() int32
 pkg text/scanner, method (*Scanner) TokenText() string
 pkg text/scanner, method (Position) String() string
 pkg text/scanner, method (Scanner) String() string
@@ -30262,15 +30250,15 @@ pkg text/tabwriter, const Escape ideal-char
 pkg text/tabwriter, const FilterHTML uint
 pkg text/tabwriter, const StripEscape uint
 pkg text/tabwriter, const TabIndent uint
-pkg text/tabwriter, func NewWriter(io.Writer, int, byte, uint) *Writer
+pkg text/tabwriter, func NewWriter(io.Writer, int, int, int, uint8, uint) *Writer
 pkg text/tabwriter, method (*Writer) Flush() error
-pkg text/tabwriter, method (*Writer) Init(io.Writer, int, byte, uint) *Writer
-pkg text/tabwriter, method (*Writer) Write([]byte) (int, error)
+pkg text/tabwriter, method (*Writer) Init(io.Writer, int, int, int, uint8, uint) *Writer
+pkg text/tabwriter, method (*Writer) Write([]uint8) (int, error)
 pkg text/tabwriter, type Writer struct
-pkg text/template, func HTMLEscape(io.Writer, []byte)
+pkg text/template, func HTMLEscape(io.Writer, []uint8)
 pkg text/template, func HTMLEscapeString(string) string
 pkg text/template, func HTMLEscaper(...interface{}) string
-pkg text/template, func JSEscape(io.Writer, []byte)
+pkg text/template, func JSEscape(io.Writer, []uint8)
 pkg text/template, func JSEscapeString(string) string
 pkg text/template, func JSEscaper(...interface{}) string
 pkg text/template, func Must(*Template, error) *Template
@@ -30280,7 +30268,7 @@ pkg text/template, func ParseGlob(string) (*Template, error)
 pkg text/template, func URLQueryEscaper(...interface{}) string
 pkg text/template, method (*Template) AddParseTree(string, *parse.Tree) (*Template, error)
 pkg text/template, method (*Template) Clone() (*Template, error)
-pkg text/template, method (*Template) Delims(string) *Template
+pkg text/template, method (*Template) Delims(string, string) *Template
 pkg text/template, method (*Template) Execute(io.Writer, interface{}) error
 pkg text/template, method (*Template) ExecuteTemplate(io.Writer, string, interface{}) error
 pkg text/template, method (*Template) Funcs(FuncMap) *Template
@@ -30313,7 +30301,7 @@ pkg text/template/parse, const NodeWith NodeType
 pkg text/template/parse, func IsEmptyTree(Node) bool
 pkg text/template/parse, func New(string, ...map[string]interface{}) *Tree
 pkg text/template/parse, func NewIdentifier(string) *IdentifierNode
-pkg text/template/parse, func Parse(string, ...map[string]interface{}) (map[string]*Tree, error)
+pkg text/template/parse, func Parse(string, string, string, string, ...map[string]interface{}) (map[string]*Tree, error)
 pkg text/template/parse, method (*ActionNode) Copy() Node
 pkg text/template/parse, method (*ActionNode) String() string
 pkg text/template/parse, method (*BoolNode) Copy() Node
@@ -30346,7 +30334,7 @@ pkg text/template/parse, method (*TemplateNode) Copy() Node
 pkg text/template/parse, method (*TemplateNode) String() string
 pkg text/template/parse, method (*TextNode) Copy() Node
 pkg text/template/parse, method (*TextNode) String() string
-pkg text/template/parse, method (*Tree) Parse(string, map[string]*Tree, ...map[string]interface{}) (*Tree, error)
+pkg text/template/parse, method (*Tree) Parse(string, string, string, map[string]*Tree, ...map[string]interface{}) (*Tree, error)
 pkg text/template/parse, method (*VariableNode) Copy() Node
 pkg text/template/parse, method (*VariableNode) String() string
 pkg text/template/parse, method (*WithNode) Copy() Node
@@ -30429,7 +30417,7 @@ pkg text/template/parse, type TemplateNode struct, Name string
 pkg text/template/parse, type TemplateNode struct, Pipe *PipeNode
 pkg text/template/parse, type TemplateNode struct, embedded NodeType
 pkg text/template/parse, type TextNode struct
-pkg text/template/parse, type TextNode struct, Text []byte
+pkg text/template/parse, type TextNode struct, Text []uint8
 pkg text/template/parse, type TextNode struct, embedded NodeType
 pkg text/template/parse, type Tree struct
 pkg text/template/parse, type Tree struct, Name string
@@ -30481,13 +30469,13 @@ pkg time, const UnixDate ideal-string
 pkg time, const Wednesday Weekday
 pkg time, func After(Duration) <-chan Time
 pkg time, func AfterFunc(Duration, func()) *Timer
-pkg time, func Date(int, Month, int, *Location) Time
+pkg time, func Date(int, Month, int, int, int, int, int, *Location) Time
 pkg time, func FixedZone(string, int) *Location
 pkg time, func LoadLocation(string) (*Location, error)
 pkg time, func NewTicker(Duration) *Ticker
 pkg time, func NewTimer(Duration) *Timer
 pkg time, func Now() Time
-pkg time, func Parse(string) (Time, error)
+pkg time, func Parse(string, string) (Time, error)
 pkg time, func ParseDuration(string) (Duration, error)
 pkg time, func Since(Time) Duration
 pkg time, func Sleep(Duration)
@@ -30496,8 +30484,8 @@ pkg time, func Unix(int64, int64) Time
 pkg time, method (*Location) String() string
 pkg time, method (*ParseError) Error() string
 pkg time, method (*Ticker) Stop()
-pkg time, method (*Time) GobDecode([]byte) error
-pkg time, method (*Time) UnmarshalJSON([]byte) error
+pkg time, method (*Time) GobDecode([]uint8) error
+pkg time, method (*Time) UnmarshalJSON([]uint8) error
 pkg time, method (*Timer) Stop() bool
 pkg time, method (Duration) Hours() float64
 pkg time, method (Duration) Minutes() float64
@@ -30509,19 +30497,19 @@ pkg time, method (Time) Add(Duration) Time
 pkg time, method (Time) AddDate(int, int, int) Time
 pkg time, method (Time) After(Time) bool
 pkg time, method (Time) Before(Time) bool
-pkg time, method (Time) Clock() int
+pkg time, method (Time) Clock() (int, int, int)
 pkg time, method (Time) Date() (int, Month, int)
 pkg time, method (Time) Day() int
 pkg time, method (Time) Equal(Time) bool
 pkg time, method (Time) Format(string) string
-pkg time, method (Time) GobEncode() ([]byte, error)
+pkg time, method (Time) GobEncode() ([]uint8, error)
 pkg time, method (Time) Hour() int
-pkg time, method (Time) ISOWeek() int
+pkg time, method (Time) ISOWeek() (int, int)
 pkg time, method (Time) In(*Location) Time
 pkg time, method (Time) IsZero() bool
 pkg time, method (Time) Local() Time
 pkg time, method (Time) Location() *Location
-pkg time, method (Time) MarshalJSON() ([]byte, error)
+pkg time, method (Time) MarshalJSON() ([]uint8, error)
 pkg time, method (Time) Minute() int
 pkg time, method (Time) Month() Month
 pkg time, method (Time) Nanosecond() int
@@ -30562,29 +30550,29 @@ pkg unicode, const TitleCase ideal-int
 pkg unicode, const UpperCase ideal-int
 pkg unicode, const UpperLower ideal-int
 pkg unicode, const Version ideal-string
-pkg unicode, func Is(*RangeTable, rune) bool
-pkg unicode, func IsControl(rune) bool
-pkg unicode, func IsDigit(rune) bool
-pkg unicode, func IsGraphic(rune) bool
-pkg unicode, func IsLetter(rune) bool
-pkg unicode, func IsLower(rune) bool
-pkg unicode, func IsMark(rune) bool
-pkg unicode, func IsNumber(rune) bool
-pkg unicode, func IsOneOf([]*RangeTable, rune) bool
-pkg unicode, func IsPrint(rune) bool
-pkg unicode, func IsPunct(rune) bool
-pkg unicode, func IsSpace(rune) bool
-pkg unicode, func IsSymbol(rune) bool
-pkg unicode, func IsTitle(rune) bool
-pkg unicode, func IsUpper(rune) bool
-pkg unicode, func SimpleFold(rune) rune
-pkg unicode, func To(int, rune) rune
-pkg unicode, func ToLower(rune) rune
-pkg unicode, func ToTitle(rune) rune
-pkg unicode, func ToUpper(rune) rune
-pkg unicode, method (SpecialCase) ToLower(rune) rune
-pkg unicode, method (SpecialCase) ToTitle(rune) rune
-pkg unicode, method (SpecialCase) ToUpper(rune) rune
+pkg unicode, func Is(*RangeTable, int32) bool
+pkg unicode, func IsControl(int32) bool
+pkg unicode, func IsDigit(int32) bool
+pkg unicode, func IsGraphic(int32) bool
+pkg unicode, func IsLetter(int32) bool
+pkg unicode, func IsLower(int32) bool
+pkg unicode, func IsMark(int32) bool
+pkg unicode, func IsNumber(int32) bool
+pkg unicode, func IsOneOf([]*RangeTable, int32) bool
+pkg unicode, func IsPrint(int32) bool
+pkg unicode, func IsPunct(int32) bool
+pkg unicode, func IsSpace(int32) bool
+pkg unicode, func IsSymbol(int32) bool
+pkg unicode, func IsTitle(int32) bool
+pkg unicode, func IsUpper(int32) bool
+pkg unicode, func SimpleFold(int32) int32
+pkg unicode, func To(int, int32) int32
+pkg unicode, func ToLower(int32) int32
+pkg unicode, func ToTitle(int32) int32
+pkg unicode, func ToUpper(int32) int32
+pkg unicode, method (SpecialCase) ToLower(int32) int32
+pkg unicode, method (SpecialCase) ToTitle(int32) int32
+pkg unicode, method (SpecialCase) ToUpper(int32) int32
 pkg unicode, type CaseRange struct
 pkg unicode, type CaseRange struct, Delta d
 pkg unicode, type CaseRange struct, Hi uint32
@@ -30785,27 +30773,27 @@ pkg unicode, var Z *RangeTable
 pkg unicode, var Zl *RangeTable
 pkg unicode, var Zp *RangeTable
 pkg unicode, var Zs *RangeTable
-pkg unicode/utf16, func Decode([]uint16) []rune
-pkg unicode/utf16, func DecodeRune(rune) rune
-pkg unicode/utf16, func Encode([]rune) []uint16
-pkg unicode/utf16, func EncodeRune(rune) rune
-pkg unicode/utf16, func IsSurrogate(rune) bool
+pkg unicode/utf16, func Decode([]uint16) []int32
+pkg unicode/utf16, func DecodeRune(int32, int32) int32
+pkg unicode/utf16, func Encode([]int32) []uint16
+pkg unicode/utf16, func EncodeRune(int32) (int32, int32)
+pkg unicode/utf16, func IsSurrogate(int32) bool
 pkg unicode/utf8, const MaxRune ideal-char
 pkg unicode/utf8, const RuneError ideal-char
 pkg unicode/utf8, const RuneSelf ideal-int
 pkg unicode/utf8, const UTFMax ideal-int
-pkg unicode/utf8, func DecodeLastRune([]byte) (rune, int)
-pkg unicode/utf8, func DecodeLastRuneInString(string) (rune, int)
-pkg unicode/utf8, func DecodeRune([]byte) (rune, int)
-pkg unicode/utf8, func DecodeRuneInString(string) (rune, int)
-pkg unicode/utf8, func EncodeRune([]byte, rune) int
-pkg unicode/utf8, func FullRune([]byte) bool
+pkg unicode/utf8, func DecodeLastRune([]uint8) (int32, int)
+pkg unicode/utf8, func DecodeLastRuneInString(string) (int32, int)
+pkg unicode/utf8, func DecodeRune([]uint8) (int32, int)
+pkg unicode/utf8, func DecodeRuneInString(string) (int32, int)
+pkg unicode/utf8, func EncodeRune([]uint8, int32) int
+pkg unicode/utf8, func FullRune([]uint8) bool
 pkg unicode/utf8, func FullRuneInString(string) bool
-pkg unicode/utf8, func RuneCount([]byte) int
+pkg unicode/utf8, func RuneCount([]uint8) int
 pkg unicode/utf8, func RuneCountInString(string) int
-pkg unicode/utf8, func RuneLen(rune) int
-pkg unicode/utf8, func RuneStart(byte) bool
-pkg unicode/utf8, func Valid([]byte) bool
+pkg unicode/utf8, func RuneLen(int32) int
+pkg unicode/utf8, func RuneStart(uint8) bool
+pkg unicode/utf8, func Valid([]uint8) bool
 pkg unicode/utf8, func ValidString(string) bool
 pkg unsafe, func Alignof(ArbitraryType) uintptr
 pkg unsafe, func Offsetof(ArbitraryType) uintptr
diff --git a/api/next.txt b/api/next.txt
index 506f088..b049cc3 100644
--- a/api/next.txt
+++ b/api/next.txt
@@ -1,15 +1,606 @@
+pkg archive/tar, const TypeGNULongLink ideal-char
+pkg archive/tar, const TypeGNULongName ideal-char
+pkg archive/tar, func FileInfoHeader(os.FileInfo, string) (*Header, error)
+pkg archive/tar, method (*Header) FileInfo() os.FileInfo
+pkg archive/zip, type FileHeader struct, CompressedSize64 uint64
+pkg archive/zip, type FileHeader struct, UncompressedSize64 uint64
+pkg bufio, const MaxScanTokenSize ideal-int
+pkg bufio, func NewScanner(io.Reader) *Scanner
+pkg bufio, func ScanBytes([]uint8, bool) (int, []uint8, error)
+pkg bufio, func ScanLines([]uint8, bool) (int, []uint8, error)
+pkg bufio, func ScanRunes([]uint8, bool) (int, []uint8, error)
+pkg bufio, func ScanWords([]uint8, bool) (int, []uint8, error)
+pkg bufio, method (*Reader) WriteTo(io.Writer) (int64, error)
+pkg bufio, method (*Scanner) Bytes() []uint8
+pkg bufio, method (*Scanner) Err() error
+pkg bufio, method (*Scanner) Scan() bool
+pkg bufio, method (*Scanner) Split(SplitFunc)
+pkg bufio, method (*Scanner) Text() string
+pkg bufio, method (*Writer) ReadFrom(io.Reader) (int64, error)
+pkg bufio, method (ReadWriter) ReadFrom(io.Reader) (int64, error)
+pkg bufio, method (ReadWriter) WriteTo(io.Writer) (int64, error)
+pkg bufio, type Scanner struct
+pkg bufio, type SplitFunc func([]uint8, bool) (int, []uint8, error)
+pkg bufio, var ErrAdvanceTooFar error
+pkg bufio, var ErrNegativeAdvance error
+pkg bufio, var ErrTooLong error
+pkg bytes, func TrimPrefix([]uint8, []uint8) []uint8
+pkg bytes, func TrimSuffix([]uint8, []uint8) []uint8
+pkg bytes, method (*Buffer) Grow(int)
+pkg bytes, method (*Reader) WriteTo(io.Writer) (int64, error)
+pkg crypto/hmac, func Equal([]uint8, []uint8) bool
 pkg crypto/tls, const TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16
 pkg crypto/tls, const TLS_RSA_WITH_AES_256_CBC_SHA uint16
+pkg crypto/tls, type Config struct, PreferServerCipherSuites bool
+pkg crypto/tls, type Config struct, SessionTicketKey [32]uint8
+pkg crypto/tls, type Config struct, SessionTicketsDisabled bool
+pkg crypto/tls, type ConnectionState struct, DidResume bool
 pkg crypto/x509, const ECDSA PublicKeyAlgorithm
 pkg crypto/x509, const ECDSAWithSHA1 SignatureAlgorithm
 pkg crypto/x509, const ECDSAWithSHA256 SignatureAlgorithm
 pkg crypto/x509, const ECDSAWithSHA384 SignatureAlgorithm
 pkg crypto/x509, const ECDSAWithSHA512 SignatureAlgorithm
+pkg crypto/x509, const ExtKeyUsageIPSECEndSystem ExtKeyUsage
+pkg crypto/x509, const ExtKeyUsageIPSECTunnel ExtKeyUsage
+pkg crypto/x509, const ExtKeyUsageIPSECUser ExtKeyUsage
+pkg crypto/x509, const ExtKeyUsageMicrosoftServerGatedCrypto ExtKeyUsage
+pkg crypto/x509, const ExtKeyUsageNetscapeServerGatedCrypto ExtKeyUsage
+pkg crypto/x509, const IncompatibleUsage InvalidReason
+pkg crypto/x509, const PEMCipher3DES PEMCipher
+pkg crypto/x509, const PEMCipherAES128 PEMCipher
+pkg crypto/x509, const PEMCipherAES192 PEMCipher
+pkg crypto/x509, const PEMCipherAES256 PEMCipher
+pkg crypto/x509, const PEMCipherDES PEMCipher
+pkg crypto/x509, func DecryptPEMBlock(*pem.Block, []uint8) ([]uint8, error)
+pkg crypto/x509, func EncryptPEMBlock(io.Reader, string, []uint8, []uint8, PEMCipher) (*pem.Block, error)
+pkg crypto/x509, func IsEncryptedPEMBlock(*pem.Block) bool
+pkg crypto/x509, func ParseECPrivateKey([]uint8) (*ecdsa.PrivateKey, error)
+pkg crypto/x509, method (SystemRootsError) Error() string
+pkg crypto/x509, type Certificate struct, IPAddresses []net.IP
+pkg crypto/x509, type PEMCipher int
+pkg crypto/x509, type SystemRootsError struct
+pkg crypto/x509, type VerifyOptions struct, KeyUsages []ExtKeyUsage
+pkg crypto/x509, var IncorrectPasswordError error
+pkg database/sql/driver, type Queryer interface { Query }
+pkg database/sql/driver, type Queryer interface, Query(string, []Value) (Rows, error)
+pkg debug/elf, method (*File) DynString(DynTag) ([]string, error)
 pkg debug/elf, type FileHeader struct, Entry uint64
+pkg debug/pe, const COFFSymbolSize ideal-int
+pkg debug/pe, type COFFSymbol struct
+pkg debug/pe, type COFFSymbol struct, Name [8]uint8
+pkg debug/pe, type COFFSymbol struct, NumberOfAuxSymbols uint8
+pkg debug/pe, type COFFSymbol struct, SectionNumber int16
+pkg debug/pe, type COFFSymbol struct, StorageClass uint8
+pkg debug/pe, type COFFSymbol struct, Type uint16
+pkg debug/pe, type COFFSymbol struct, Value uint32
+pkg debug/pe, type File struct, Symbols []*Symbol
+pkg debug/pe, type Symbol struct
+pkg debug/pe, type Symbol struct, Name string
+pkg debug/pe, type Symbol struct, SectionNumber int16
+pkg debug/pe, type Symbol struct, StorageClass uint8
+pkg debug/pe, type Symbol struct, Type uint16
+pkg debug/pe, type Symbol struct, Value uint32
+pkg encoding/csv, method (*Writer) Error() error
+pkg encoding/json, method (*Decoder) Buffered() io.Reader
+pkg encoding/json, method (*Decoder) UseNumber()
+pkg encoding/json, method (Number) Float64() (float64, error)
+pkg encoding/json, method (Number) Int64() (int64, error)
+pkg encoding/json, method (Number) String() string
+pkg encoding/json, type Number string
+pkg encoding/xml, func EscapeText(io.Writer, []uint8) error
+pkg encoding/xml, method (*Encoder) Indent(string, string)
+pkg go/ast, func NewCommentMap(*token.FileSet, Node, []*CommentGroup) CommentMap
+pkg go/ast, method (CommentMap) Comments() []*CommentGroup
+pkg go/ast, method (CommentMap) Filter(Node) CommentMap
+pkg go/ast, method (CommentMap) String() string
+pkg go/ast, method (CommentMap) Update(Node, Node) Node
+pkg go/ast, type ChanType struct, Arrow token.Pos
+pkg go/ast, type CommentMap map[Node][]*CommentGroup
+pkg go/build, type Context struct, InstallTag string
+pkg go/build, type Package struct, IgnoredGoFiles []string
+pkg go/build, type Package struct, SwigCXXFiles []string
+pkg go/build, type Package struct, SwigFiles []string
+pkg go/doc, type Example struct, EmptyOutput bool
+pkg go/doc, type Example struct, Order int
+pkg go/doc, type Example struct, Play *ast.File
+pkg go/doc, type Package struct, Notes map[string][]string
 pkg go/doc, var IllegalPrefixes []string
-pkg math/big, method (*Int) MarshalJSON() ([]byte, error)
-pkg math/big, method (*Int) UnmarshalJSON([]byte) error
+pkg go/format, func Node(io.Writer, *token.FileSet, interface{}) error
+pkg go/format, func Source([]uint8) ([]uint8, error)
+pkg go/parser, const AllErrors Mode
+pkg go/printer, type Config struct, Indent int
+pkg go/types, const Bool BasicKind
+pkg go/types, const Byte BasicKind
+pkg go/types, const Complex128 BasicKind
+pkg go/types, const Complex64 BasicKind
+pkg go/types, const DefaultMaxAlign ideal-int
+pkg go/types, const DefaultPtrSize ideal-int
+pkg go/types, const Float32 BasicKind
+pkg go/types, const Float64 BasicKind
+pkg go/types, const Int BasicKind
+pkg go/types, const Int16 BasicKind
+pkg go/types, const Int32 BasicKind
+pkg go/types, const Int64 BasicKind
+pkg go/types, const Int8 BasicKind
+pkg go/types, const Invalid BasicKind
+pkg go/types, const IsBoolean BasicInfo
+pkg go/types, const IsComplex BasicInfo
+pkg go/types, const IsConstType BasicInfo
+pkg go/types, const IsFloat BasicInfo
+pkg go/types, const IsInteger BasicInfo
+pkg go/types, const IsNumeric BasicInfo
+pkg go/types, const IsOrdered BasicInfo
+pkg go/types, const IsString BasicInfo
+pkg go/types, const IsUnsigned BasicInfo
+pkg go/types, const IsUntyped BasicInfo
+pkg go/types, const Rune BasicKind
+pkg go/types, const String BasicKind
+pkg go/types, const Uint BasicKind
+pkg go/types, const Uint16 BasicKind
+pkg go/types, const Uint32 BasicKind
+pkg go/types, const Uint64 BasicKind
+pkg go/types, const Uint8 BasicKind
+pkg go/types, const Uintptr BasicKind
+pkg go/types, const UnsafePointer BasicKind
+pkg go/types, const UntypedBool BasicKind
+pkg go/types, const UntypedComplex BasicKind
+pkg go/types, const UntypedFloat BasicKind
+pkg go/types, const UntypedInt BasicKind
+pkg go/types, const UntypedNil BasicKind
+pkg go/types, const UntypedRune BasicKind
+pkg go/types, const UntypedString BasicKind
+pkg go/types, func Check(*token.FileSet, []*ast.File) (*Package, error)
+pkg go/types, func DefaultAlignof(Type) int64
+pkg go/types, func DefaultOffsetsof([]*Field) []int64
+pkg go/types, func DefaultSizeof(Type) int64
+pkg go/types, func FindGcExportData(*bufio.Reader) error
+pkg go/types, func FindPkg(string, string) (string, string)
+pkg go/types, func GcImport(map[string]*Package, string) (*Package, error)
+pkg go/types, func GcImportData(map[string]*Package, string, string, *bufio.Reader) (*Package, error)
+pkg go/types, func IsIdentical(Type, Type) bool
+pkg go/types, method (*Array) String() string
+pkg go/types, method (*Basic) String() string
+pkg go/types, method (*Chan) String() string
+pkg go/types, method (*Const) GetName() string
+pkg go/types, method (*Const) GetPkg() *Package
+pkg go/types, method (*Const) GetPos() token.Pos
+pkg go/types, method (*Const) GetType() Type
+pkg go/types, method (*Context) Check(*token.FileSet, []*ast.File) (*Package, error)
+pkg go/types, method (*Func) GetName() string
+pkg go/types, method (*Func) GetPkg() *Package
+pkg go/types, method (*Func) GetPos() token.Pos
+pkg go/types, method (*Func) GetType() Type
+pkg go/types, method (*Interface) String() string
+pkg go/types, method (*Map) String() string
+pkg go/types, method (*NamedType) String() string
+pkg go/types, method (*Package) GetName() string
+pkg go/types, method (*Package) GetPkg() *Package
+pkg go/types, method (*Package) GetPos() token.Pos
+pkg go/types, method (*Package) GetType() Type
+pkg go/types, method (*Pointer) String() string
+pkg go/types, method (*Result) String() string
+pkg go/types, method (*Scope) Insert(Object) Object
+pkg go/types, method (*Scope) Lookup(string) Object
+pkg go/types, method (*Scope) String() string
+pkg go/types, method (*Signature) String() string
+pkg go/types, method (*Slice) String() string
+pkg go/types, method (*Struct) String() string
+pkg go/types, method (*TypeName) GetName() string
+pkg go/types, method (*TypeName) GetPkg() *Package
+pkg go/types, method (*TypeName) GetPos() token.Pos
+pkg go/types, method (*TypeName) GetType() Type
+pkg go/types, method (*Var) GetName() string
+pkg go/types, method (*Var) GetPkg() *Package
+pkg go/types, method (*Var) GetPos() token.Pos
+pkg go/types, method (*Var) GetType() Type
+pkg go/types, method (Complex) String() string
+pkg go/types, method (Field) IsSame(QualifiedName) bool
+pkg go/types, method (Method) IsSame(QualifiedName) bool
+pkg go/types, method (NilType) String() string
+pkg go/types, method (QualifiedName) IsSame(QualifiedName) bool
+pkg go/types, type Array struct
+pkg go/types, type Array struct, Elt Type
+pkg go/types, type Array struct, Len int64
+pkg go/types, type Basic struct
+pkg go/types, type Basic struct, Info BasicInfo
+pkg go/types, type Basic struct, Kind BasicKind
+pkg go/types, type Basic struct, Name string
+pkg go/types, type Basic struct, Size int64
+pkg go/types, type BasicInfo int
+pkg go/types, type BasicKind int
+pkg go/types, type Chan struct
+pkg go/types, type Chan struct, Dir ast.ChanDir
+pkg go/types, type Chan struct, Elt Type
+pkg go/types, type Complex struct
+pkg go/types, type Complex struct, Im *big.Rat
+pkg go/types, type Complex struct, Re *big.Rat
+pkg go/types, type Const struct
+pkg go/types, type Const struct, Name string
+pkg go/types, type Const struct, Pkg *Package
+pkg go/types, type Const struct, Type Type
+pkg go/types, type Const struct, Val interface{}
+pkg go/types, type Context struct
+pkg go/types, type Context struct, Alignof func(Type) int64
+pkg go/types, type Context struct, Error func(error)
+pkg go/types, type Context struct, Expr func(ast.Expr, Type, interface{})
+pkg go/types, type Context struct, Ident func(*ast.Ident, Object)
+pkg go/types, type Context struct, Import Importer
+pkg go/types, type Context struct, IntSize int64
+pkg go/types, type Context struct, Offsetsof func([]*Field) []int64
+pkg go/types, type Context struct, PtrSize int64
+pkg go/types, type Context struct, Sizeof func(Type) int64
+pkg go/types, type Field struct
+pkg go/types, type Field struct, IsAnonymous bool
+pkg go/types, type Field struct, Tag string
+pkg go/types, type Field struct, Type Type
+pkg go/types, type Field struct, embedded QualifiedName
+pkg go/types, type Func struct
+pkg go/types, type Func struct, Name string
+pkg go/types, type Func struct, Pkg *Package
+pkg go/types, type Func struct, Type Type
+pkg go/types, type Importer func(imports map[string]*Package, path string) (pkg *Package, err error)
+pkg go/types, type Importer func(map[string]*Package, string) (*Package, error)
+pkg go/types, type Interface struct
+pkg go/types, type Interface struct, Methods []*Method
+pkg go/types, type Map struct
+pkg go/types, type Map struct, Elt Type
+pkg go/types, type Map struct, Key Type
+pkg go/types, type Method struct
+pkg go/types, type Method struct, Type *Signature
+pkg go/types, type Method struct, embedded QualifiedName
+pkg go/types, type NamedType struct
+pkg go/types, type NamedType struct, Methods []*Method
+pkg go/types, type NamedType struct, Obj *TypeName
+pkg go/types, type NamedType struct, Underlying Type
+pkg go/types, type NilType struct
+pkg go/types, type Object interface, GetName() string
+pkg go/types, type Object interface, GetPkg() *Package
+pkg go/types, type Object interface, GetPos() token.Pos
+pkg go/types, type Object interface, GetType() Type
+pkg go/types, type Object interface, unexported methods
+pkg go/types, type Package struct
+pkg go/types, type Package struct, Complete bool
+pkg go/types, type Package struct, Imports map[string]*Package
+pkg go/types, type Package struct, Name string
+pkg go/types, type Package struct, Path string
+pkg go/types, type Package struct, Scope *Scope
+pkg go/types, type Pointer struct
+pkg go/types, type Pointer struct, Base Type
+pkg go/types, type QualifiedName struct
+pkg go/types, type QualifiedName struct, Name string
+pkg go/types, type QualifiedName struct, Pkg *Package
+pkg go/types, type Result struct
+pkg go/types, type Result struct, Values []*Var
+pkg go/types, type Scope struct
+pkg go/types, type Scope struct, Entries []Object
+pkg go/types, type Scope struct, Outer *Scope
+pkg go/types, type Signature struct
+pkg go/types, type Signature struct, IsVariadic bool
+pkg go/types, type Signature struct, Params []*Var
+pkg go/types, type Signature struct, Recv *Var
+pkg go/types, type Signature struct, Results []*Var
+pkg go/types, type Slice struct
+pkg go/types, type Slice struct, Elt Type
+pkg go/types, type Struct struct
+pkg go/types, type Struct struct, Fields []*Field
+pkg go/types, type Type interface, String() string
+pkg go/types, type Type interface, unexported methods
+pkg go/types, type TypeName struct
+pkg go/types, type TypeName struct, Name string
+pkg go/types, type TypeName struct, Pkg *Package
+pkg go/types, type TypeName struct, Type Type
+pkg go/types, type Var struct
+pkg go/types, type Var struct, Name string
+pkg go/types, type Var struct, Pkg *Package
+pkg go/types, type Var struct, Type Type
+pkg go/types, var Default Context
+pkg go/types, var Typ [...]*Basic
+pkg go/types, var Universe *Scope
+pkg go/types, var Unsafe *Package
+pkg image, const YCbCrSubsampleRatio440 YCbCrSubsampleRatio
+pkg io, type ByteWriter interface { WriteByte }
+pkg io, type ByteWriter interface, WriteByte(uint8) error
+pkg log/syslog (darwin-386), const LOG_AUTH Priority
+pkg log/syslog (darwin-386), const LOG_AUTHPRIV Priority
+pkg log/syslog (darwin-386), const LOG_CRON Priority
+pkg log/syslog (darwin-386), const LOG_DAEMON Priority
+pkg log/syslog (darwin-386), const LOG_FTP Priority
+pkg log/syslog (darwin-386), const LOG_KERN Priority
+pkg log/syslog (darwin-386), const LOG_LOCAL0 Priority
+pkg log/syslog (darwin-386), const LOG_LOCAL1 Priority
+pkg log/syslog (darwin-386), const LOG_LOCAL2 Priority
+pkg log/syslog (darwin-386), const LOG_LOCAL3 Priority
+pkg log/syslog (darwin-386), const LOG_LOCAL4 Priority
+pkg log/syslog (darwin-386), const LOG_LOCAL5 Priority
+pkg log/syslog (darwin-386), const LOG_LOCAL6 Priority
+pkg log/syslog (darwin-386), const LOG_LOCAL7 Priority
+pkg log/syslog (darwin-386), const LOG_LPR Priority
+pkg log/syslog (darwin-386), const LOG_MAIL Priority
+pkg log/syslog (darwin-386), const LOG_NEWS Priority
+pkg log/syslog (darwin-386), const LOG_SYSLOG Priority
+pkg log/syslog (darwin-386), const LOG_USER Priority
+pkg log/syslog (darwin-386), const LOG_UUCP Priority
+pkg log/syslog (darwin-386-cgo), const LOG_AUTH Priority
+pkg log/syslog (darwin-386-cgo), const LOG_AUTHPRIV Priority
+pkg log/syslog (darwin-386-cgo), const LOG_CRON Priority
+pkg log/syslog (darwin-386-cgo), const LOG_DAEMON Priority
+pkg log/syslog (darwin-386-cgo), const LOG_FTP Priority
+pkg log/syslog (darwin-386-cgo), const LOG_KERN Priority
+pkg log/syslog (darwin-386-cgo), const LOG_LOCAL0 Priority
+pkg log/syslog (darwin-386-cgo), const LOG_LOCAL1 Priority
+pkg log/syslog (darwin-386-cgo), const LOG_LOCAL2 Priority
+pkg log/syslog (darwin-386-cgo), const LOG_LOCAL3 Priority
+pkg log/syslog (darwin-386-cgo), const LOG_LOCAL4 Priority
+pkg log/syslog (darwin-386-cgo), const LOG_LOCAL5 Priority
+pkg log/syslog (darwin-386-cgo), const LOG_LOCAL6 Priority
+pkg log/syslog (darwin-386-cgo), const LOG_LOCAL7 Priority
+pkg log/syslog (darwin-386-cgo), const LOG_LPR Priority
+pkg log/syslog (darwin-386-cgo), const LOG_MAIL Priority
+pkg log/syslog (darwin-386-cgo), const LOG_NEWS Priority
+pkg log/syslog (darwin-386-cgo), const LOG_SYSLOG Priority
+pkg log/syslog (darwin-386-cgo), const LOG_USER Priority
+pkg log/syslog (darwin-386-cgo), const LOG_UUCP Priority
+pkg log/syslog (darwin-amd64), const LOG_AUTH Priority
+pkg log/syslog (darwin-amd64), const LOG_AUTHPRIV Priority
+pkg log/syslog (darwin-amd64), const LOG_CRON Priority
+pkg log/syslog (darwin-amd64), const LOG_DAEMON Priority
+pkg log/syslog (darwin-amd64), const LOG_FTP Priority
+pkg log/syslog (darwin-amd64), const LOG_KERN Priority
+pkg log/syslog (darwin-amd64), const LOG_LOCAL0 Priority
+pkg log/syslog (darwin-amd64), const LOG_LOCAL1 Priority
+pkg log/syslog (darwin-amd64), const LOG_LOCAL2 Priority
+pkg log/syslog (darwin-amd64), const LOG_LOCAL3 Priority
+pkg log/syslog (darwin-amd64), const LOG_LOCAL4 Priority
+pkg log/syslog (darwin-amd64), const LOG_LOCAL5 Priority
+pkg log/syslog (darwin-amd64), const LOG_LOCAL6 Priority
+pkg log/syslog (darwin-amd64), const LOG_LOCAL7 Priority
+pkg log/syslog (darwin-amd64), const LOG_LPR Priority
+pkg log/syslog (darwin-amd64), const LOG_MAIL Priority
+pkg log/syslog (darwin-amd64), const LOG_NEWS Priority
+pkg log/syslog (darwin-amd64), const LOG_SYSLOG Priority
+pkg log/syslog (darwin-amd64), const LOG_USER Priority
+pkg log/syslog (darwin-amd64), const LOG_UUCP Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_AUTH Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_AUTHPRIV Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_CRON Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_DAEMON Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_FTP Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_KERN Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_LOCAL0 Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_LOCAL1 Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_LOCAL2 Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_LOCAL3 Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_LOCAL4 Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_LOCAL5 Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_LOCAL6 Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_LOCAL7 Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_LPR Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_MAIL Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_NEWS Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_SYSLOG Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_USER Priority
+pkg log/syslog (darwin-amd64-cgo), const LOG_UUCP Priority
+pkg log/syslog (freebsd-386), const LOG_AUTH Priority
+pkg log/syslog (freebsd-386), const LOG_AUTHPRIV Priority
+pkg log/syslog (freebsd-386), const LOG_CRON Priority
+pkg log/syslog (freebsd-386), const LOG_DAEMON Priority
+pkg log/syslog (freebsd-386), const LOG_FTP Priority
+pkg log/syslog (freebsd-386), const LOG_KERN Priority
+pkg log/syslog (freebsd-386), const LOG_LOCAL0 Priority
+pkg log/syslog (freebsd-386), const LOG_LOCAL1 Priority
+pkg log/syslog (freebsd-386), const LOG_LOCAL2 Priority
+pkg log/syslog (freebsd-386), const LOG_LOCAL3 Priority
+pkg log/syslog (freebsd-386), const LOG_LOCAL4 Priority
+pkg log/syslog (freebsd-386), const LOG_LOCAL5 Priority
+pkg log/syslog (freebsd-386), const LOG_LOCAL6 Priority
+pkg log/syslog (freebsd-386), const LOG_LOCAL7 Priority
+pkg log/syslog (freebsd-386), const LOG_LPR Priority
+pkg log/syslog (freebsd-386), const LOG_MAIL Priority
+pkg log/syslog (freebsd-386), const LOG_NEWS Priority
+pkg log/syslog (freebsd-386), const LOG_SYSLOG Priority
+pkg log/syslog (freebsd-386), const LOG_USER Priority
+pkg log/syslog (freebsd-386), const LOG_UUCP Priority
+pkg log/syslog (freebsd-amd64), const LOG_AUTH Priority
+pkg log/syslog (freebsd-amd64), const LOG_AUTHPRIV Priority
+pkg log/syslog (freebsd-amd64), const LOG_CRON Priority
+pkg log/syslog (freebsd-amd64), const LOG_DAEMON Priority
+pkg log/syslog (freebsd-amd64), const LOG_FTP Priority
+pkg log/syslog (freebsd-amd64), const LOG_KERN Priority
+pkg log/syslog (freebsd-amd64), const LOG_LOCAL0 Priority
+pkg log/syslog (freebsd-amd64), const LOG_LOCAL1 Priority
+pkg log/syslog (freebsd-amd64), const LOG_LOCAL2 Priority
+pkg log/syslog (freebsd-amd64), const LOG_LOCAL3 Priority
+pkg log/syslog (freebsd-amd64), const LOG_LOCAL4 Priority
+pkg log/syslog (freebsd-amd64), const LOG_LOCAL5 Priority
+pkg log/syslog (freebsd-amd64), const LOG_LOCAL6 Priority
+pkg log/syslog (freebsd-amd64), const LOG_LOCAL7 Priority
+pkg log/syslog (freebsd-amd64), const LOG_LPR Priority
+pkg log/syslog (freebsd-amd64), const LOG_MAIL Priority
+pkg log/syslog (freebsd-amd64), const LOG_NEWS Priority
+pkg log/syslog (freebsd-amd64), const LOG_SYSLOG Priority
+pkg log/syslog (freebsd-amd64), const LOG_USER Priority
+pkg log/syslog (freebsd-amd64), const LOG_UUCP Priority
+pkg log/syslog (linux-386), const LOG_AUTH Priority
+pkg log/syslog (linux-386), const LOG_AUTHPRIV Priority
+pkg log/syslog (linux-386), const LOG_CRON Priority
+pkg log/syslog (linux-386), const LOG_DAEMON Priority
+pkg log/syslog (linux-386), const LOG_FTP Priority
+pkg log/syslog (linux-386), const LOG_KERN Priority
+pkg log/syslog (linux-386), const LOG_LOCAL0 Priority
+pkg log/syslog (linux-386), const LOG_LOCAL1 Priority
+pkg log/syslog (linux-386), const LOG_LOCAL2 Priority
+pkg log/syslog (linux-386), const LOG_LOCAL3 Priority
+pkg log/syslog (linux-386), const LOG_LOCAL4 Priority
+pkg log/syslog (linux-386), const LOG_LOCAL5 Priority
+pkg log/syslog (linux-386), const LOG_LOCAL6 Priority
+pkg log/syslog (linux-386), const LOG_LOCAL7 Priority
+pkg log/syslog (linux-386), const LOG_LPR Priority
+pkg log/syslog (linux-386), const LOG_MAIL Priority
+pkg log/syslog (linux-386), const LOG_NEWS Priority
+pkg log/syslog (linux-386), const LOG_SYSLOG Priority
+pkg log/syslog (linux-386), const LOG_USER Priority
+pkg log/syslog (linux-386), const LOG_UUCP Priority
+pkg log/syslog (linux-386-cgo), const LOG_AUTH Priority
+pkg log/syslog (linux-386-cgo), const LOG_AUTHPRIV Priority
+pkg log/syslog (linux-386-cgo), const LOG_CRON Priority
+pkg log/syslog (linux-386-cgo), const LOG_DAEMON Priority
+pkg log/syslog (linux-386-cgo), const LOG_FTP Priority
+pkg log/syslog (linux-386-cgo), const LOG_KERN Priority
+pkg log/syslog (linux-386-cgo), const LOG_LOCAL0 Priority
+pkg log/syslog (linux-386-cgo), const LOG_LOCAL1 Priority
+pkg log/syslog (linux-386-cgo), const LOG_LOCAL2 Priority
+pkg log/syslog (linux-386-cgo), const LOG_LOCAL3 Priority
+pkg log/syslog (linux-386-cgo), const LOG_LOCAL4 Priority
+pkg log/syslog (linux-386-cgo), const LOG_LOCAL5 Priority
+pkg log/syslog (linux-386-cgo), const LOG_LOCAL6 Priority
+pkg log/syslog (linux-386-cgo), const LOG_LOCAL7 Priority
+pkg log/syslog (linux-386-cgo), const LOG_LPR Priority
+pkg log/syslog (linux-386-cgo), const LOG_MAIL Priority
+pkg log/syslog (linux-386-cgo), const LOG_NEWS Priority
+pkg log/syslog (linux-386-cgo), const LOG_SYSLOG Priority
+pkg log/syslog (linux-386-cgo), const LOG_USER Priority
+pkg log/syslog (linux-386-cgo), const LOG_UUCP Priority
+pkg log/syslog (linux-amd64), const LOG_AUTH Priority
+pkg log/syslog (linux-amd64), const LOG_AUTHPRIV Priority
+pkg log/syslog (linux-amd64), const LOG_CRON Priority
+pkg log/syslog (linux-amd64), const LOG_DAEMON Priority
+pkg log/syslog (linux-amd64), const LOG_FTP Priority
+pkg log/syslog (linux-amd64), const LOG_KERN Priority
+pkg log/syslog (linux-amd64), const LOG_LOCAL0 Priority
+pkg log/syslog (linux-amd64), const LOG_LOCAL1 Priority
+pkg log/syslog (linux-amd64), const LOG_LOCAL2 Priority
+pkg log/syslog (linux-amd64), const LOG_LOCAL3 Priority
+pkg log/syslog (linux-amd64), const LOG_LOCAL4 Priority
+pkg log/syslog (linux-amd64), const LOG_LOCAL5 Priority
+pkg log/syslog (linux-amd64), const LOG_LOCAL6 Priority
+pkg log/syslog (linux-amd64), const LOG_LOCAL7 Priority
+pkg log/syslog (linux-amd64), const LOG_LPR Priority
+pkg log/syslog (linux-amd64), const LOG_MAIL Priority
+pkg log/syslog (linux-amd64), const LOG_NEWS Priority
+pkg log/syslog (linux-amd64), const LOG_SYSLOG Priority
+pkg log/syslog (linux-amd64), const LOG_USER Priority
+pkg log/syslog (linux-amd64), const LOG_UUCP Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_AUTH Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_AUTHPRIV Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_CRON Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_DAEMON Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_FTP Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_KERN Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_LOCAL0 Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_LOCAL1 Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_LOCAL2 Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_LOCAL3 Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_LOCAL4 Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_LOCAL5 Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_LOCAL6 Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_LOCAL7 Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_LPR Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_MAIL Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_NEWS Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_SYSLOG Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_USER Priority
+pkg log/syslog (linux-amd64-cgo), const LOG_UUCP Priority
+pkg log/syslog (linux-arm), const LOG_AUTH Priority
+pkg log/syslog (linux-arm), const LOG_AUTHPRIV Priority
+pkg log/syslog (linux-arm), const LOG_CRON Priority
+pkg log/syslog (linux-arm), const LOG_DAEMON Priority
+pkg log/syslog (linux-arm), const LOG_FTP Priority
+pkg log/syslog (linux-arm), const LOG_KERN Priority
+pkg log/syslog (linux-arm), const LOG_LOCAL0 Priority
+pkg log/syslog (linux-arm), const LOG_LOCAL1 Priority
+pkg log/syslog (linux-arm), const LOG_LOCAL2 Priority
+pkg log/syslog (linux-arm), const LOG_LOCAL3 Priority
+pkg log/syslog (linux-arm), const LOG_LOCAL4 Priority
+pkg log/syslog (linux-arm), const LOG_LOCAL5 Priority
+pkg log/syslog (linux-arm), const LOG_LOCAL6 Priority
+pkg log/syslog (linux-arm), const LOG_LOCAL7 Priority
+pkg log/syslog (linux-arm), const LOG_LPR Priority
+pkg log/syslog (linux-arm), const LOG_MAIL Priority
+pkg log/syslog (linux-arm), const LOG_NEWS Priority
+pkg log/syslog (linux-arm), const LOG_SYSLOG Priority
+pkg log/syslog (linux-arm), const LOG_USER Priority
+pkg log/syslog (linux-arm), const LOG_UUCP Priority
+pkg math/big, method (*Int) MarshalJSON() ([]uint8, error)
+pkg math/big, method (*Int) SetUint64(uint64) *Int
+pkg math/big, method (*Int) Uint64() uint64
+pkg math/big, method (*Int) UnmarshalJSON([]uint8) error
+pkg math/big, method (*Rat) Float64() (float64, bool)
+pkg math/big, method (*Rat) SetFloat64(float64) *Rat
+pkg mime/multipart, method (*Writer) SetBoundary(string) error
+pkg net, func Deadline(time.Time) DialOption
+pkg net, func DialOpt(string, ...DialOption) (Conn, error)
+pkg net, func ListenUnixgram(string, *UnixAddr) (*UnixConn, error)
+pkg net, func LocalAddress(Addr) DialOption
+pkg net, func LookupNS(string) ([]*NS, error)
+pkg net, func Network(string) DialOption
+pkg net, func Timeout(time.Duration) DialOption
+pkg net, method (*IPConn) ReadMsgIP([]uint8, []uint8) (int, int, int, *IPAddr, error)
+pkg net, method (*IPConn) WriteMsgIP([]uint8, []uint8, *IPAddr) (int, int, error)
+pkg net, method (*UDPConn) ReadMsgUDP([]uint8, []uint8) (int, int, int, *UDPAddr, error)
+pkg net, method (*UDPConn) WriteMsgUDP([]uint8, []uint8, *UDPAddr) (int, int, error)
+pkg net, method (*UnixConn) CloseRead() error
+pkg net, method (*UnixConn) CloseWrite() error
+pkg net, type DialOption interface, unexported methods
+pkg net, type IPAddr struct, Zone string
+pkg net, type IPNet struct, Zone string
+pkg net, type NS struct
+pkg net, type NS struct, Host string
+pkg net, type TCPAddr struct, Zone string
+pkg net, type UDPAddr struct, Zone string
+pkg net, var TCP DialOption
+pkg net, var UDP DialOption
+pkg net/http, func ParseTime(string) (time.Time, error)
+pkg net/http, method (*Request) PostFormValue(string) string
+pkg net/http, method (*ServeMux) Handler(*Request) (Handler, string)
+pkg net/http, type CloseNotifier interface { CloseNotify }
+pkg net/http, type CloseNotifier interface, CloseNotify() <-chan bool
+pkg net/http, type Request struct, PostForm url.Values
+pkg net/http, type Server struct, TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
+pkg net/http, type Transport struct, ResponseHeaderTimeout time.Duration
+pkg net/mail, func ParseAddress(string) (*Address, error)
+pkg net/mail, func ParseAddressList(string) ([]*Address, error)
+pkg net/smtp, method (*Client) Hello(string) error
+pkg net/textproto, func TrimBytes([]uint8) []uint8
+pkg net/textproto, func TrimString(string) string
+pkg os, method (FileMode) IsRegular() bool
+pkg reflect, const SelectDefault SelectDir
+pkg reflect, const SelectRecv SelectDir
+pkg reflect, const SelectSend SelectDir
+pkg reflect, func ChanOf(ChanDir, Type) Type
+pkg reflect, func MakeFunc(Type, func([]Value) []Value) Value
+pkg reflect, func MapOf(Type, Type) Type
+pkg reflect, func Select([]SelectCase) (int, Value, bool)
+pkg reflect, func SliceOf(Type) Type
+pkg reflect, method (Value) Convert(Type) Value
+pkg reflect, type SelectCase struct
+pkg reflect, type SelectCase struct, Chan Value
+pkg reflect, type SelectCase struct, Dir SelectDir
+pkg reflect, type SelectCase struct, Send Value
+pkg reflect, type SelectDir int
+pkg reflect, type Type interface, ConvertibleTo(Type) bool
+pkg regexp, method (*Regexp) Longest()
+pkg regexp, method (*Regexp) Split(string, int) []string
 pkg regexp/syntax, const ErrUnexpectedParen ErrorCode
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
+pkg runtime/debug, func FreeOSMemory()
+pkg runtime/debug, func ReadGCStats(*GCStats)
+pkg runtime/debug, func SetGCPercent(int) int
+pkg runtime/debug, type GCStats struct
+pkg runtime/debug, type GCStats struct, LastGC time.Time
+pkg runtime/debug, type GCStats struct, NumGC int64
+pkg runtime/debug, type GCStats struct, Pause []time.Duration
+pkg runtime/debug, type GCStats struct, PauseQuantiles []time.Duration
+pkg runtime/debug, type GCStats struct, PauseTotal time.Duration
+pkg sort, func Reverse(Interface) Interface
+pkg strings, func TrimPrefix(string, string) string
+pkg strings, func TrimSuffix(string, string) string
+pkg strings, method (*Reader) WriteTo(io.Writer) (int64, error)
 pkg syscall (darwin-386), const B0 ideal-int
 pkg syscall (darwin-386), const B110 ideal-int
 pkg syscall (darwin-386), const B115200 ideal-int
@@ -77,6 +668,7 @@ pkg syscall (darwin-386), const PARENB ideal-int
 pkg syscall (darwin-386), const PARMRK ideal-int
 pkg syscall (darwin-386), const PARODD ideal-int
 pkg syscall (darwin-386), const PENDIN ideal-int
+pkg syscall (darwin-386), const SizeofInet4Pktinfo ideal-int
 pkg syscall (darwin-386), const TCIFLUSH ideal-int
 pkg syscall (darwin-386), const TCIOFLUSH ideal-int
 pkg syscall (darwin-386), const TCOFLUSH ideal-int
@@ -103,6 +695,11 @@ pkg syscall (darwin-386), const VT1 ideal-int
 pkg syscall (darwin-386), const VTDLY ideal-int
 pkg syscall (darwin-386), const VTIME ideal-int
 pkg syscall (darwin-386), const VWERASE ideal-int
+pkg syscall (darwin-386), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (darwin-386), type Inet4Pktinfo struct
+pkg syscall (darwin-386), type Inet4Pktinfo struct, Addr [4]uint8
+pkg syscall (darwin-386), type Inet4Pktinfo struct, Ifindex uint32
+pkg syscall (darwin-386), type Inet4Pktinfo struct, Spec_dst [4]uint8
 pkg syscall (darwin-386), type Termios struct
 pkg syscall (darwin-386), type Termios struct, Cc [20]uint8
 pkg syscall (darwin-386), type Termios struct, Cflag uint32
@@ -178,6 +775,7 @@ pkg syscall (darwin-386-cgo), const PARENB ideal-int
 pkg syscall (darwin-386-cgo), const PARMRK ideal-int
 pkg syscall (darwin-386-cgo), const PARODD ideal-int
 pkg syscall (darwin-386-cgo), const PENDIN ideal-int
+pkg syscall (darwin-386-cgo), const SizeofInet4Pktinfo ideal-int
 pkg syscall (darwin-386-cgo), const TCIFLUSH ideal-int
 pkg syscall (darwin-386-cgo), const TCIOFLUSH ideal-int
 pkg syscall (darwin-386-cgo), const TCOFLUSH ideal-int
@@ -204,6 +802,11 @@ pkg syscall (darwin-386-cgo), const VT1 ideal-int
 pkg syscall (darwin-386-cgo), const VTDLY ideal-int
 pkg syscall (darwin-386-cgo), const VTIME ideal-int
 pkg syscall (darwin-386-cgo), const VWERASE ideal-int
+pkg syscall (darwin-386-cgo), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (darwin-386-cgo), type Inet4Pktinfo struct
+pkg syscall (darwin-386-cgo), type Inet4Pktinfo struct, Addr [4]uint8
+pkg syscall (darwin-386-cgo), type Inet4Pktinfo struct, Ifindex uint32
+pkg syscall (darwin-386-cgo), type Inet4Pktinfo struct, Spec_dst [4]uint8
 pkg syscall (darwin-386-cgo), type Termios struct
 pkg syscall (darwin-386-cgo), type Termios struct, Cc [20]uint8
 pkg syscall (darwin-386-cgo), type Termios struct, Cflag uint32
@@ -279,6 +882,7 @@ pkg syscall (darwin-amd64), const PARENB ideal-int
 pkg syscall (darwin-amd64), const PARMRK ideal-int
 pkg syscall (darwin-amd64), const PARODD ideal-int
 pkg syscall (darwin-amd64), const PENDIN ideal-int
+pkg syscall (darwin-amd64), const SizeofInet4Pktinfo ideal-int
 pkg syscall (darwin-amd64), const TCIFLUSH ideal-int
 pkg syscall (darwin-amd64), const TCIOFLUSH ideal-int
 pkg syscall (darwin-amd64), const TCOFLUSH ideal-int
@@ -305,6 +909,11 @@ pkg syscall (darwin-amd64), const VT1 ideal-int
 pkg syscall (darwin-amd64), const VTDLY ideal-int
 pkg syscall (darwin-amd64), const VTIME ideal-int
 pkg syscall (darwin-amd64), const VWERASE ideal-int
+pkg syscall (darwin-amd64), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (darwin-amd64), type Inet4Pktinfo struct
+pkg syscall (darwin-amd64), type Inet4Pktinfo struct, Addr [4]uint8
+pkg syscall (darwin-amd64), type Inet4Pktinfo struct, Ifindex uint32
+pkg syscall (darwin-amd64), type Inet4Pktinfo struct, Spec_dst [4]uint8
 pkg syscall (darwin-amd64), type Termios struct
 pkg syscall (darwin-amd64), type Termios struct, Cc [20]uint8
 pkg syscall (darwin-amd64), type Termios struct, Cflag uint64
@@ -313,7 +922,7 @@ pkg syscall (darwin-amd64), type Termios struct, Ispeed uint64
 pkg syscall (darwin-amd64), type Termios struct, Lflag uint64
 pkg syscall (darwin-amd64), type Termios struct, Oflag uint64
 pkg syscall (darwin-amd64), type Termios struct, Ospeed uint64
-pkg syscall (darwin-amd64), type Termios struct, Pad_cgo_0 [4]byte
+pkg syscall (darwin-amd64), type Termios struct, Pad_cgo_0 [4]uint8
 pkg syscall (darwin-amd64-cgo), const B0 ideal-int
 pkg syscall (darwin-amd64-cgo), const B110 ideal-int
 pkg syscall (darwin-amd64-cgo), const B115200 ideal-int
@@ -381,6 +990,7 @@ pkg syscall (darwin-amd64-cgo), const PARENB ideal-int
 pkg syscall (darwin-amd64-cgo), const PARMRK ideal-int
 pkg syscall (darwin-amd64-cgo), const PARODD ideal-int
 pkg syscall (darwin-amd64-cgo), const PENDIN ideal-int
+pkg syscall (darwin-amd64-cgo), const SizeofInet4Pktinfo ideal-int
 pkg syscall (darwin-amd64-cgo), const TCIFLUSH ideal-int
 pkg syscall (darwin-amd64-cgo), const TCIOFLUSH ideal-int
 pkg syscall (darwin-amd64-cgo), const TCOFLUSH ideal-int
@@ -407,6 +1017,11 @@ pkg syscall (darwin-amd64-cgo), const VT1 ideal-int
 pkg syscall (darwin-amd64-cgo), const VTDLY ideal-int
 pkg syscall (darwin-amd64-cgo), const VTIME ideal-int
 pkg syscall (darwin-amd64-cgo), const VWERASE ideal-int
+pkg syscall (darwin-amd64-cgo), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (darwin-amd64-cgo), type Inet4Pktinfo struct
+pkg syscall (darwin-amd64-cgo), type Inet4Pktinfo struct, Addr [4]uint8
+pkg syscall (darwin-amd64-cgo), type Inet4Pktinfo struct, Ifindex uint32
+pkg syscall (darwin-amd64-cgo), type Inet4Pktinfo struct, Spec_dst [4]uint8
 pkg syscall (darwin-amd64-cgo), type Termios struct
 pkg syscall (darwin-amd64-cgo), type Termios struct, Cc [20]uint8
 pkg syscall (darwin-amd64-cgo), type Termios struct, Cflag uint64
@@ -415,14 +1030,509 @@ pkg syscall (darwin-amd64-cgo), type Termios struct, Ispeed uint64
 pkg syscall (darwin-amd64-cgo), type Termios struct, Lflag uint64
 pkg syscall (darwin-amd64-cgo), type Termios struct, Oflag uint64
 pkg syscall (darwin-amd64-cgo), type Termios struct, Ospeed uint64
-pkg syscall (darwin-amd64-cgo), type Termios struct, Pad_cgo_0 [4]byte
+pkg syscall (darwin-amd64-cgo), type Termios struct, Pad_cgo_0 [4]uint8
+pkg syscall (freebsd-386), const IFAN_ARRIVAL ideal-int
+pkg syscall (freebsd-386), const IFAN_DEPARTURE ideal-int
+pkg syscall (freebsd-386), const SizeofIfAnnounceMsghdr ideal-int
+pkg syscall (freebsd-386), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (freebsd-386), type IfAnnounceMsghdr struct
+pkg syscall (freebsd-386), type IfAnnounceMsghdr struct, Index uint16
+pkg syscall (freebsd-386), type IfAnnounceMsghdr struct, Msglen uint16
+pkg syscall (freebsd-386), type IfAnnounceMsghdr struct, Name [16]int8
+pkg syscall (freebsd-386), type IfAnnounceMsghdr struct, Type uint8
+pkg syscall (freebsd-386), type IfAnnounceMsghdr struct, Version uint8
+pkg syscall (freebsd-386), type IfAnnounceMsghdr struct, What uint16
+pkg syscall (freebsd-386), type InterfaceAnnounceMessage struct
+pkg syscall (freebsd-386), type InterfaceAnnounceMessage struct, Header IfAnnounceMsghdr
+pkg syscall (freebsd-amd64), const IFAN_ARRIVAL ideal-int
+pkg syscall (freebsd-amd64), const IFAN_DEPARTURE ideal-int
+pkg syscall (freebsd-amd64), const SizeofIfAnnounceMsghdr ideal-int
+pkg syscall (freebsd-amd64), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (freebsd-amd64), func Syscall9(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
+pkg syscall (freebsd-amd64), type IfAnnounceMsghdr struct
+pkg syscall (freebsd-amd64), type IfAnnounceMsghdr struct, Index uint16
+pkg syscall (freebsd-amd64), type IfAnnounceMsghdr struct, Msglen uint16
+pkg syscall (freebsd-amd64), type IfAnnounceMsghdr struct, Name [16]int8
+pkg syscall (freebsd-amd64), type IfAnnounceMsghdr struct, Type uint8
+pkg syscall (freebsd-amd64), type IfAnnounceMsghdr struct, Version uint8
+pkg syscall (freebsd-amd64), type IfAnnounceMsghdr struct, What uint16
+pkg syscall (freebsd-amd64), type InterfaceAnnounceMessage struct
+pkg syscall (freebsd-amd64), type InterfaceAnnounceMessage struct, Header IfAnnounceMsghdr
+pkg syscall (linux-386), const RTNLGRP_IPV4_IFADDR ideal-int
+pkg syscall (linux-386), const RTNLGRP_IPV4_MROUTE ideal-int
+pkg syscall (linux-386), const RTNLGRP_IPV4_ROUTE ideal-int
+pkg syscall (linux-386), const RTNLGRP_IPV4_RULE ideal-int
+pkg syscall (linux-386), const RTNLGRP_IPV6_IFADDR ideal-int
+pkg syscall (linux-386), const RTNLGRP_IPV6_IFINFO ideal-int
+pkg syscall (linux-386), const RTNLGRP_IPV6_MROUTE ideal-int
+pkg syscall (linux-386), const RTNLGRP_IPV6_PREFIX ideal-int
+pkg syscall (linux-386), const RTNLGRP_IPV6_ROUTE ideal-int
+pkg syscall (linux-386), const RTNLGRP_IPV6_RULE ideal-int
+pkg syscall (linux-386), const RTNLGRP_LINK ideal-int
+pkg syscall (linux-386), const RTNLGRP_ND_USEROPT ideal-int
+pkg syscall (linux-386), const RTNLGRP_NEIGH ideal-int
+pkg syscall (linux-386), const RTNLGRP_NONE ideal-int
+pkg syscall (linux-386), const RTNLGRP_NOTIFY ideal-int
+pkg syscall (linux-386), const RTNLGRP_TC ideal-int
+pkg syscall (linux-386), const SizeofTCPInfo ideal-int
+pkg syscall (linux-386), func Accept4(int, int) (int, Sockaddr, error)
+pkg syscall (linux-386), func GetsockoptUcred(int, int, int) (*Ucred, error)
+pkg syscall (linux-386), func Getxattr(string, string, []uint8) (int, error)
+pkg syscall (linux-386), func Listxattr(string, []uint8) (int, error)
+pkg syscall (linux-386), func Pipe2([]int, int) error
+pkg syscall (linux-386), func PtraceSyscall(int, int) error
+pkg syscall (linux-386), func Removexattr(string, string) error
+pkg syscall (linux-386), func Setxattr(string, string, []uint8, int) error
+pkg syscall (linux-386), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (linux-386), type SysProcAttr struct, Ctty int
+pkg syscall (linux-386), type TCPInfo struct
+pkg syscall (linux-386), type TCPInfo struct, Advmss uint32
+pkg syscall (linux-386), type TCPInfo struct, Ato uint32
+pkg syscall (linux-386), type TCPInfo struct, Backoff uint8
+pkg syscall (linux-386), type TCPInfo struct, Ca_state uint8
+pkg syscall (linux-386), type TCPInfo struct, Fackets uint32
+pkg syscall (linux-386), type TCPInfo struct, Last_ack_recv uint32
+pkg syscall (linux-386), type TCPInfo struct, Last_ack_sent uint32
+pkg syscall (linux-386), type TCPInfo struct, Last_data_recv uint32
+pkg syscall (linux-386), type TCPInfo struct, Last_data_sent uint32
+pkg syscall (linux-386), type TCPInfo struct, Lost uint32
+pkg syscall (linux-386), type TCPInfo struct, Options uint8
+pkg syscall (linux-386), type TCPInfo struct, Pad_cgo_0 [2]uint8
+pkg syscall (linux-386), type TCPInfo struct, Pmtu uint32
+pkg syscall (linux-386), type TCPInfo struct, Probes uint8
+pkg syscall (linux-386), type TCPInfo struct, Rcv_mss uint32
+pkg syscall (linux-386), type TCPInfo struct, Rcv_rtt uint32
+pkg syscall (linux-386), type TCPInfo struct, Rcv_space uint32
+pkg syscall (linux-386), type TCPInfo struct, Rcv_ssthresh uint32
+pkg syscall (linux-386), type TCPInfo struct, Reordering uint32
+pkg syscall (linux-386), type TCPInfo struct, Retrans uint32
+pkg syscall (linux-386), type TCPInfo struct, Retransmits uint8
+pkg syscall (linux-386), type TCPInfo struct, Rto uint32
+pkg syscall (linux-386), type TCPInfo struct, Rtt uint32
+pkg syscall (linux-386), type TCPInfo struct, Rttvar uint32
+pkg syscall (linux-386), type TCPInfo struct, Sacked uint32
+pkg syscall (linux-386), type TCPInfo struct, Snd_cwnd uint32
+pkg syscall (linux-386), type TCPInfo struct, Snd_mss uint32
+pkg syscall (linux-386), type TCPInfo struct, Snd_ssthresh uint32
+pkg syscall (linux-386), type TCPInfo struct, State uint8
+pkg syscall (linux-386), type TCPInfo struct, Total_retrans uint32
+pkg syscall (linux-386), type TCPInfo struct, Unacked uint32
+pkg syscall (linux-386-cgo), const RTNLGRP_IPV4_IFADDR ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_IPV4_MROUTE ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_IPV4_ROUTE ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_IPV4_RULE ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_IPV6_IFADDR ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_IPV6_IFINFO ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_IPV6_MROUTE ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_IPV6_PREFIX ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_IPV6_ROUTE ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_IPV6_RULE ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_LINK ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_ND_USEROPT ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_NEIGH ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_NONE ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_NOTIFY ideal-int
+pkg syscall (linux-386-cgo), const RTNLGRP_TC ideal-int
+pkg syscall (linux-386-cgo), const SizeofTCPInfo ideal-int
+pkg syscall (linux-386-cgo), func Accept4(int, int) (int, Sockaddr, error)
+pkg syscall (linux-386-cgo), func GetsockoptUcred(int, int, int) (*Ucred, error)
+pkg syscall (linux-386-cgo), func Getxattr(string, string, []uint8) (int, error)
+pkg syscall (linux-386-cgo), func Listxattr(string, []uint8) (int, error)
+pkg syscall (linux-386-cgo), func Pipe2([]int, int) error
+pkg syscall (linux-386-cgo), func PtraceSyscall(int, int) error
+pkg syscall (linux-386-cgo), func Removexattr(string, string) error
+pkg syscall (linux-386-cgo), func Setxattr(string, string, []uint8, int) error
+pkg syscall (linux-386-cgo), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (linux-386-cgo), type SysProcAttr struct, Ctty int
+pkg syscall (linux-386-cgo), type TCPInfo struct
+pkg syscall (linux-386-cgo), type TCPInfo struct, Advmss uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Ato uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Backoff uint8
+pkg syscall (linux-386-cgo), type TCPInfo struct, Ca_state uint8
+pkg syscall (linux-386-cgo), type TCPInfo struct, Fackets uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Last_ack_recv uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Last_ack_sent uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Last_data_recv uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Last_data_sent uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Lost uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Options uint8
+pkg syscall (linux-386-cgo), type TCPInfo struct, Pad_cgo_0 [2]uint8
+pkg syscall (linux-386-cgo), type TCPInfo struct, Pmtu uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Probes uint8
+pkg syscall (linux-386-cgo), type TCPInfo struct, Rcv_mss uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Rcv_rtt uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Rcv_space uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Rcv_ssthresh uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Reordering uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Retrans uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Retransmits uint8
+pkg syscall (linux-386-cgo), type TCPInfo struct, Rto uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Rtt uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Rttvar uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Sacked uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Snd_cwnd uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Snd_mss uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Snd_ssthresh uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, State uint8
+pkg syscall (linux-386-cgo), type TCPInfo struct, Total_retrans uint32
+pkg syscall (linux-386-cgo), type TCPInfo struct, Unacked uint32
+pkg syscall (linux-amd64), const RTNLGRP_IPV4_IFADDR ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_IPV4_MROUTE ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_IPV4_ROUTE ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_IPV4_RULE ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_IPV6_IFADDR ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_IPV6_IFINFO ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_IPV6_MROUTE ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_IPV6_PREFIX ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_IPV6_ROUTE ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_IPV6_RULE ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_LINK ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_ND_USEROPT ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_NEIGH ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_NONE ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_NOTIFY ideal-int
+pkg syscall (linux-amd64), const RTNLGRP_TC ideal-int
+pkg syscall (linux-amd64), const SizeofTCPInfo ideal-int
+pkg syscall (linux-amd64), func Accept4(int, int) (int, Sockaddr, error)
+pkg syscall (linux-amd64), func GetsockoptUcred(int, int, int) (*Ucred, error)
+pkg syscall (linux-amd64), func Getxattr(string, string, []uint8) (int, error)
+pkg syscall (linux-amd64), func Listxattr(string, []uint8) (int, error)
+pkg syscall (linux-amd64), func Pipe2([]int, int) error
+pkg syscall (linux-amd64), func PtraceSyscall(int, int) error
+pkg syscall (linux-amd64), func Removexattr(string, string) error
+pkg syscall (linux-amd64), func Setxattr(string, string, []uint8, int) error
+pkg syscall (linux-amd64), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (linux-amd64), type SysProcAttr struct, Ctty int
+pkg syscall (linux-amd64), type TCPInfo struct
+pkg syscall (linux-amd64), type TCPInfo struct, Advmss uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Ato uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Backoff uint8
+pkg syscall (linux-amd64), type TCPInfo struct, Ca_state uint8
+pkg syscall (linux-amd64), type TCPInfo struct, Fackets uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Last_ack_recv uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Last_ack_sent uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Last_data_recv uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Last_data_sent uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Lost uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Options uint8
+pkg syscall (linux-amd64), type TCPInfo struct, Pad_cgo_0 [2]uint8
+pkg syscall (linux-amd64), type TCPInfo struct, Pmtu uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Probes uint8
+pkg syscall (linux-amd64), type TCPInfo struct, Rcv_mss uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Rcv_rtt uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Rcv_space uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Rcv_ssthresh uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Reordering uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Retrans uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Retransmits uint8
+pkg syscall (linux-amd64), type TCPInfo struct, Rto uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Rtt uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Rttvar uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Sacked uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Snd_cwnd uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Snd_mss uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Snd_ssthresh uint32
+pkg syscall (linux-amd64), type TCPInfo struct, State uint8
+pkg syscall (linux-amd64), type TCPInfo struct, Total_retrans uint32
+pkg syscall (linux-amd64), type TCPInfo struct, Unacked uint32
+pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV4_IFADDR ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV4_MROUTE ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV4_ROUTE ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV4_RULE ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV6_IFADDR ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV6_IFINFO ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV6_MROUTE ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV6_PREFIX ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV6_ROUTE ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV6_RULE ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_LINK ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_ND_USEROPT ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_NEIGH ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_NONE ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_NOTIFY ideal-int
+pkg syscall (linux-amd64-cgo), const RTNLGRP_TC ideal-int
+pkg syscall (linux-amd64-cgo), const SizeofTCPInfo ideal-int
+pkg syscall (linux-amd64-cgo), func Accept4(int, int) (int, Sockaddr, error)
+pkg syscall (linux-amd64-cgo), func GetsockoptUcred(int, int, int) (*Ucred, error)
+pkg syscall (linux-amd64-cgo), func Getxattr(string, string, []uint8) (int, error)
+pkg syscall (linux-amd64-cgo), func Listxattr(string, []uint8) (int, error)
+pkg syscall (linux-amd64-cgo), func Pipe2([]int, int) error
+pkg syscall (linux-amd64-cgo), func PtraceSyscall(int, int) error
+pkg syscall (linux-amd64-cgo), func Removexattr(string, string) error
+pkg syscall (linux-amd64-cgo), func Setxattr(string, string, []uint8, int) error
+pkg syscall (linux-amd64-cgo), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (linux-amd64-cgo), type SysProcAttr struct, Ctty int
+pkg syscall (linux-amd64-cgo), type TCPInfo struct
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Advmss uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Ato uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Backoff uint8
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Ca_state uint8
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Fackets uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Last_ack_recv uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Last_ack_sent uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Last_data_recv uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Last_data_sent uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Lost uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Options uint8
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Pad_cgo_0 [2]uint8
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Pmtu uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Probes uint8
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Rcv_mss uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Rcv_rtt uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Rcv_space uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Rcv_ssthresh uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Reordering uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Retrans uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Retransmits uint8
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Rto uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Rtt uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Rttvar uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Sacked uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Snd_cwnd uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Snd_mss uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Snd_ssthresh uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, State uint8
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Total_retrans uint32
+pkg syscall (linux-amd64-cgo), type TCPInfo struct, Unacked uint32
+pkg syscall (linux-arm), const RTNLGRP_IPV4_IFADDR ideal-int
+pkg syscall (linux-arm), const RTNLGRP_IPV4_MROUTE ideal-int
+pkg syscall (linux-arm), const RTNLGRP_IPV4_ROUTE ideal-int
+pkg syscall (linux-arm), const RTNLGRP_IPV4_RULE ideal-int
+pkg syscall (linux-arm), const RTNLGRP_IPV6_IFADDR ideal-int
+pkg syscall (linux-arm), const RTNLGRP_IPV6_IFINFO ideal-int
+pkg syscall (linux-arm), const RTNLGRP_IPV6_MROUTE ideal-int
+pkg syscall (linux-arm), const RTNLGRP_IPV6_PREFIX ideal-int
+pkg syscall (linux-arm), const RTNLGRP_IPV6_ROUTE ideal-int
+pkg syscall (linux-arm), const RTNLGRP_IPV6_RULE ideal-int
+pkg syscall (linux-arm), const RTNLGRP_LINK ideal-int
+pkg syscall (linux-arm), const RTNLGRP_ND_USEROPT ideal-int
+pkg syscall (linux-arm), const RTNLGRP_NEIGH ideal-int
+pkg syscall (linux-arm), const RTNLGRP_NONE ideal-int
+pkg syscall (linux-arm), const RTNLGRP_NOTIFY ideal-int
+pkg syscall (linux-arm), const RTNLGRP_TC ideal-int
+pkg syscall (linux-arm), const SizeofTCPInfo ideal-int
+pkg syscall (linux-arm), func Accept4(int, int) (int, Sockaddr, error)
+pkg syscall (linux-arm), func GetsockoptUcred(int, int, int) (*Ucred, error)
+pkg syscall (linux-arm), func Getxattr(string, string, []uint8) (int, error)
+pkg syscall (linux-arm), func Listxattr(string, []uint8) (int, error)
+pkg syscall (linux-arm), func Pipe2([]int, int) error
+pkg syscall (linux-arm), func PtraceSyscall(int, int) error
+pkg syscall (linux-arm), func Removexattr(string, string) error
+pkg syscall (linux-arm), func Setxattr(string, string, []uint8, int) error
+pkg syscall (linux-arm), func SlicePtrFromStrings([]string) ([]*uint8, error)
+pkg syscall (linux-arm), type SysProcAttr struct, Ctty int
+pkg syscall (linux-arm), type TCPInfo struct
+pkg syscall (linux-arm), type TCPInfo struct, Advmss uint32
+pkg syscall (linux-arm), type TCPInfo struct, Ato uint32
+pkg syscall (linux-arm), type TCPInfo struct, Backoff uint8
+pkg syscall (linux-arm), type TCPInfo struct, Ca_state uint8
+pkg syscall (linux-arm), type TCPInfo struct, Fackets uint32
+pkg syscall (linux-arm), type TCPInfo struct, Last_ack_recv uint32
+pkg syscall (linux-arm), type TCPInfo struct, Last_ack_sent uint32
+pkg syscall (linux-arm), type TCPInfo struct, Last_data_recv uint32
+pkg syscall (linux-arm), type TCPInfo struct, Last_data_sent uint32
+pkg syscall (linux-arm), type TCPInfo struct, Lost uint32
+pkg syscall (linux-arm), type TCPInfo struct, Options uint8
+pkg syscall (linux-arm), type TCPInfo struct, Pad_cgo_0 [2]uint8
+pkg syscall (linux-arm), type TCPInfo struct, Pmtu uint32
+pkg syscall (linux-arm), type TCPInfo struct, Probes uint8
+pkg syscall (linux-arm), type TCPInfo struct, Rcv_mss uint32
+pkg syscall (linux-arm), type TCPInfo struct, Rcv_rtt uint32
+pkg syscall (linux-arm), type TCPInfo struct, Rcv_space uint32
+pkg syscall (linux-arm), type TCPInfo struct, Rcv_ssthresh uint32
+pkg syscall (linux-arm), type TCPInfo struct, Reordering uint32
+pkg syscall (linux-arm), type TCPInfo struct, Retrans uint32
+pkg syscall (linux-arm), type TCPInfo struct, Retransmits uint8
+pkg syscall (linux-arm), type TCPInfo struct, Rto uint32
+pkg syscall (linux-arm), type TCPInfo struct, Rtt uint32
+pkg syscall (linux-arm), type TCPInfo struct, Rttvar uint32
+pkg syscall (linux-arm), type TCPInfo struct, Sacked uint32
+pkg syscall (linux-arm), type TCPInfo struct, Snd_cwnd uint32
+pkg syscall (linux-arm), type TCPInfo struct, Snd_mss uint32
+pkg syscall (linux-arm), type TCPInfo struct, Snd_ssthresh uint32
+pkg syscall (linux-arm), type TCPInfo struct, State uint8
+pkg syscall (linux-arm), type TCPInfo struct, Total_retrans uint32
+pkg syscall (linux-arm), type TCPInfo struct, Unacked uint32
+pkg syscall (windows-386), const AI_CANONNAME ideal-int
+pkg syscall (windows-386), const AI_NUMERICHOST ideal-int
+pkg syscall (windows-386), const AI_PASSIVE ideal-int
 pkg syscall (windows-386), const CREATE_NEW_PROCESS_GROUP ideal-int
 pkg syscall (windows-386), const CTRL_BREAK_EVENT ideal-int
 pkg syscall (windows-386), const CTRL_C_EVENT ideal-int
-pkg syscall (windows-386), func GetCurrentProcessId() uint32
+pkg syscall (windows-386), const ERROR_NOT_FOUND Errno
+pkg syscall (windows-386), const IOC_IN ideal-int
+pkg syscall (windows-386), const IOC_INOUT ideal-int
+pkg syscall (windows-386), const IOC_OUT ideal-int
+pkg syscall (windows-386), const IOC_WS2 ideal-int
+pkg syscall (windows-386), const SIO_GET_EXTENSION_FUNCTION_POINTER ideal-int
+pkg syscall (windows-386), const SO_UPDATE_CONNECT_CONTEXT ideal-int
+pkg syscall (windows-386), func CancelIoEx(Handle, *Overlapped) error
+pkg syscall (windows-386), func ConnectEx(Handle, Sockaddr, *uint8, uint32, *uint32, *Overlapped) error
+pkg syscall (windows-386), func FreeAddrInfoW(*AddrinfoW)
+pkg syscall (windows-386), func GetAddrInfoW(*uint16, *uint16, *AddrinfoW, **AddrinfoW) error
+pkg syscall (windows-386), func GetConsoleMode(Handle, *uint32) error
+pkg syscall (windows-386), func Getsockopt(Handle, int32, int32, *uint8, *int32) error
+pkg syscall (windows-386), func LoadCancelIoEx() error
+pkg syscall (windows-386), func LoadConnectEx() error
+pkg syscall (windows-386), func LoadGetAddrInfo() error
+pkg syscall (windows-386), func ReadConsole(Handle, *uint16, uint32, *uint32, *uint8) error
+pkg syscall (windows-386), func UTF16FromString(string) ([]uint16, error)
+pkg syscall (windows-386), func UTF16PtrFromString(string) (*uint16, error)
+pkg syscall (windows-386), func WriteConsole(Handle, *uint16, uint32, *uint32, *uint8) error
+pkg syscall (windows-386), type AddrinfoW struct
+pkg syscall (windows-386), type AddrinfoW struct, Addr uintptr
+pkg syscall (windows-386), type AddrinfoW struct, Addrlen uintptr
+pkg syscall (windows-386), type AddrinfoW struct, Canonname *uint16
+pkg syscall (windows-386), type AddrinfoW struct, Family int32
+pkg syscall (windows-386), type AddrinfoW struct, Flags int32
+pkg syscall (windows-386), type AddrinfoW struct, Next *AddrinfoW
+pkg syscall (windows-386), type AddrinfoW struct, Protocol int32
+pkg syscall (windows-386), type AddrinfoW struct, Socktype int32
+pkg syscall (windows-386), type GUID struct
+pkg syscall (windows-386), type GUID struct, Data1 uint32
+pkg syscall (windows-386), type GUID struct, Data2 uint16
+pkg syscall (windows-386), type GUID struct, Data3 uint16
+pkg syscall (windows-386), type GUID struct, Data4 [8]uint8
+pkg syscall (windows-386), type RawSockaddrInet6 struct, Family uint16
 pkg syscall (windows-386), type SysProcAttr struct, CreationFlags uint32
+pkg syscall (windows-386), var WSAID_CONNECTEX GUID
+pkg syscall (windows-amd64), const AI_CANONNAME ideal-int
+pkg syscall (windows-amd64), const AI_NUMERICHOST ideal-int
+pkg syscall (windows-amd64), const AI_PASSIVE ideal-int
 pkg syscall (windows-amd64), const CREATE_NEW_PROCESS_GROUP ideal-int
 pkg syscall (windows-amd64), const CTRL_BREAK_EVENT ideal-int
 pkg syscall (windows-amd64), const CTRL_C_EVENT ideal-int
-pkg syscall (windows-amd64), func GetCurrentProcessId() uint32
+pkg syscall (windows-amd64), const ERROR_NOT_FOUND Errno
+pkg syscall (windows-amd64), const IOC_IN ideal-int
+pkg syscall (windows-amd64), const IOC_INOUT ideal-int
+pkg syscall (windows-amd64), const IOC_OUT ideal-int
+pkg syscall (windows-amd64), const IOC_WS2 ideal-int
+pkg syscall (windows-amd64), const SIO_GET_EXTENSION_FUNCTION_POINTER ideal-int
+pkg syscall (windows-amd64), const SO_UPDATE_CONNECT_CONTEXT ideal-int
+pkg syscall (windows-amd64), func CancelIoEx(Handle, *Overlapped) error
+pkg syscall (windows-amd64), func ConnectEx(Handle, Sockaddr, *uint8, uint32, *uint32, *Overlapped) error
+pkg syscall (windows-amd64), func FreeAddrInfoW(*AddrinfoW)
+pkg syscall (windows-amd64), func GetAddrInfoW(*uint16, *uint16, *AddrinfoW, **AddrinfoW) error
+pkg syscall (windows-amd64), func GetConsoleMode(Handle, *uint32) error
+pkg syscall (windows-amd64), func Getsockopt(Handle, int32, int32, *uint8, *int32) error
+pkg syscall (windows-amd64), func LoadCancelIoEx() error
+pkg syscall (windows-amd64), func LoadConnectEx() error
+pkg syscall (windows-amd64), func LoadGetAddrInfo() error
+pkg syscall (windows-amd64), func ReadConsole(Handle, *uint16, uint32, *uint32, *uint8) error
+pkg syscall (windows-amd64), func UTF16FromString(string) ([]uint16, error)
+pkg syscall (windows-amd64), func UTF16PtrFromString(string) (*uint16, error)
+pkg syscall (windows-amd64), func WriteConsole(Handle, *uint16, uint32, *uint32, *uint8) error
+pkg syscall (windows-amd64), type AddrinfoW struct
+pkg syscall (windows-amd64), type AddrinfoW struct, Addr uintptr
+pkg syscall (windows-amd64), type AddrinfoW struct, Addrlen uintptr
+pkg syscall (windows-amd64), type AddrinfoW struct, Canonname *uint16
+pkg syscall (windows-amd64), type AddrinfoW struct, Family int32
+pkg syscall (windows-amd64), type AddrinfoW struct, Flags int32
+pkg syscall (windows-amd64), type AddrinfoW struct, Next *AddrinfoW
+pkg syscall (windows-amd64), type AddrinfoW struct, Protocol int32
+pkg syscall (windows-amd64), type AddrinfoW struct, Socktype int32
+pkg syscall (windows-amd64), type GUID struct
+pkg syscall (windows-amd64), type GUID struct, Data1 uint32
+pkg syscall (windows-amd64), type GUID struct, Data2 uint16
+pkg syscall (windows-amd64), type GUID struct, Data3 uint16
+pkg syscall (windows-amd64), type GUID struct, Data4 [8]uint8
+pkg syscall (windows-amd64), type RawSockaddrInet6 struct, Family uint16
 pkg syscall (windows-amd64), type SysProcAttr struct, CreationFlags uint32
+pkg syscall (windows-amd64), var WSAID_CONNECTEX GUID
+pkg syscall, func BytePtrFromString(string) (*uint8, error)
+pkg syscall, func ByteSliceFromString(string) ([]uint8, error)
+pkg syscall, func NsecToTimespec(int64) Timespec
+pkg syscall, func TimespecToNsec(Timespec) int64
+pkg syscall, func UtimesNano(string, []Timespec) error
+pkg syscall, type RawSockaddrInet6 struct
+pkg syscall, type RawSockaddrInet6 struct, Addr [16]uint8
+pkg syscall, type RawSockaddrInet6 struct, Flowinfo uint32
+pkg syscall, type RawSockaddrInet6 struct, Port uint16
+pkg syscall, type RawSockaddrInet6 struct, Scope_id uint32
+pkg testing, func AllocsPerRun(int, func()) float64
+pkg testing, func Verbose() bool
+pkg testing, method (*B) ReportAllocs()
+pkg testing, method (*B) Skip(...interface{})
+pkg testing, method (*B) SkipNow()
+pkg testing, method (*B) Skipf(string, ...interface{})
+pkg testing, method (*B) Skipped() bool
+pkg testing, method (*T) Skip(...interface{})
+pkg testing, method (*T) SkipNow()
+pkg testing, method (*T) Skipf(string, ...interface{})
+pkg testing, method (*T) Skipped() bool
+pkg testing, method (BenchmarkResult) AllocedBytesPerOp() int64
+pkg testing, method (BenchmarkResult) AllocsPerOp() int64
+pkg testing, method (BenchmarkResult) MemString() string
+pkg testing, type BenchmarkResult struct, MemAllocs uint64
+pkg testing, type BenchmarkResult struct, MemBytes uint64
+pkg text/template/parse, const NodeChain NodeType
+pkg text/template/parse, const NodeNil NodeType
+pkg text/template/parse, method (*ChainNode) Add(string)
+pkg text/template/parse, method (*ChainNode) Copy() Node
+pkg text/template/parse, method (*ChainNode) String() string
+pkg text/template/parse, method (*IdentifierNode) SetPos(Pos) *IdentifierNode
+pkg text/template/parse, method (*NilNode) Copy() Node
+pkg text/template/parse, method (*NilNode) String() string
+pkg text/template/parse, method (*NilNode) Type() NodeType
+pkg text/template/parse, method (*Tree) ErrorContext(Node) (string, string)
+pkg text/template/parse, method (ActionNode) Position() Pos
+pkg text/template/parse, method (BoolNode) Position() Pos
+pkg text/template/parse, method (BranchNode) Position() Pos
+pkg text/template/parse, method (ChainNode) Position() Pos
+pkg text/template/parse, method (ChainNode) Type() NodeType
+pkg text/template/parse, method (CommandNode) Position() Pos
+pkg text/template/parse, method (DotNode) Position() Pos
+pkg text/template/parse, method (FieldNode) Position() Pos
+pkg text/template/parse, method (IdentifierNode) Position() Pos
+pkg text/template/parse, method (IfNode) Position() Pos
+pkg text/template/parse, method (ListNode) Position() Pos
+pkg text/template/parse, method (NilNode) Position() Pos
+pkg text/template/parse, method (NumberNode) Position() Pos
+pkg text/template/parse, method (PipeNode) Position() Pos
+pkg text/template/parse, method (Pos) Position() Pos
+pkg text/template/parse, method (RangeNode) Position() Pos
+pkg text/template/parse, method (StringNode) Position() Pos
+pkg text/template/parse, method (TemplateNode) Position() Pos
+pkg text/template/parse, method (TextNode) Position() Pos
+pkg text/template/parse, method (VariableNode) Position() Pos
+pkg text/template/parse, method (WithNode) Position() Pos
+pkg text/template/parse, type ActionNode struct, embedded Pos
+pkg text/template/parse, type BoolNode struct, embedded Pos
+pkg text/template/parse, type BranchNode struct, embedded Pos
+pkg text/template/parse, type ChainNode struct
+pkg text/template/parse, type ChainNode struct, Field []string
+pkg text/template/parse, type ChainNode struct, Node Node
+pkg text/template/parse, type ChainNode struct, embedded NodeType
+pkg text/template/parse, type ChainNode struct, embedded Pos
+pkg text/template/parse, type CommandNode struct, embedded Pos
+pkg text/template/parse, type DotNode struct
+pkg text/template/parse, type DotNode struct, embedded Pos
+pkg text/template/parse, type FieldNode struct, embedded Pos
+pkg text/template/parse, type IdentifierNode struct, embedded Pos
+pkg text/template/parse, type ListNode struct, embedded Pos
+pkg text/template/parse, type NilNode struct
+pkg text/template/parse, type NilNode struct, embedded Pos
+pkg text/template/parse, type Node interface, Position() Pos
+pkg text/template/parse, type Node interface, unexported methods
+pkg text/template/parse, type NumberNode struct, embedded Pos
+pkg text/template/parse, type PipeNode struct, embedded Pos
+pkg text/template/parse, type Pos int
+pkg text/template/parse, type StringNode struct, embedded Pos
+pkg text/template/parse, type TemplateNode struct, embedded Pos
+pkg text/template/parse, type TextNode struct, embedded Pos
+pkg text/template/parse, type Tree struct, ParseName string
+pkg text/template/parse, type VariableNode struct, embedded Pos
+pkg time, func ParseInLocation(string, string, *Location) (Time, error)
+pkg time, method (*Timer) Reset(Duration) bool
+pkg time, method (Time) Round(Duration) Time
+pkg time, method (Time) Truncate(Duration) Time
+pkg time, method (Time) YearDay() int
+pkg unicode, type RangeTable struct, LatinOffset int
+pkg unicode, var Chakma *RangeTable
+pkg unicode, var Meroitic_Cursive *RangeTable
+pkg unicode, var Meroitic_Hieroglyphs *RangeTable
+pkg unicode, var Miao *RangeTable
+pkg unicode, var Sharada *RangeTable
+pkg unicode, var Sora_Sompeng *RangeTable
+pkg unicode, var Takri *RangeTable
+pkg unicode/utf8, func ValidRune(int32) bool
diff --git a/doc/ExpressivenessOfGo.pdf b/doc/ExpressivenessOfGo.pdf
deleted file mode 100644
index f1931d0..0000000
Binary files a/doc/ExpressivenessOfGo.pdf and /dev/null differ
diff --git a/doc/Makefile b/doc/Makefile
index b6e475b..23262da 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -25,3 +25,8 @@ all: $(RAWHTML)
 
 clean:
 	rm -f $(RAWHTML)
+
+compare:
+	for i in $(RAWHTML); do \
+		godoc -url /doc/$${i/.rawhtml/.html} | diff -u $$i -; \
+	done
diff --git a/doc/articles/c_go_cgo.html b/doc/articles/c_go_cgo.html
index ac6bb29..b37a6ba 100644
--- a/doc/articles/c_go_cgo.html
+++ b/doc/articles/c_go_cgo.html
@@ -149,9 +149,9 @@ is more complex than a single function call), as in this rewrite of
 </p>
 
 <p>
-To build cgo packages, just use <a href="/cmd/go/#Compile_packages_and_dependencies">"
+To build cgo packages, just use <a href="/cmd/go/#hdr-Compile_packages_and_dependencies">"
 <code>go build</code>"</a> or
-<a href="/cmd/go/#Compile_and_install_packages_and_dependencies">"<code>go install</code>
+<a href="/cmd/go/#hdr-Compile_and_install_packages_and_dependencies">"<code>go install</code>
 "</a> as usual. The go tool recognizes the special <code>"C"</code> import and automatically
 uses cgo for those files.
 </p>
@@ -169,9 +169,8 @@ in the Go tree demonstrate more advanced concepts.
 <p>
 For a simple, idiomatic example of a cgo-based package, see Russ Cox's <a
 href="http://code.google.com/p/gosqlite/source/browse/sqlite/sqlite.go">gosqlite</a>.
-Also, the Go Project Dashboard lists <a
-href="https://godashboard.appspot.com/project?tag=cgo">several other
-cgo packages</a>.
+Also, the <a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Community Wiki</a>
+lists many packages, some of which use cgo.
 </p>
 
 <p>
diff --git a/doc/articles/concurrency_patterns.html b/doc/articles/concurrency_patterns.html
index 63c8cd5..62168b8 100644
--- a/doc/articles/concurrency_patterns.html
+++ b/doc/articles/concurrency_patterns.html
@@ -17,7 +17,7 @@ and launching a goroutine that sleeps before sending on the channel:
 We can then use a <code>select</code> statement to receive from either
 <code>ch</code> or <code>timeout</code>. If nothing arrives on <code>ch</code>
 after one second, the timeout case is selected and the attempt to read from
-<cde>ch</cde> is abandoned.
+<code>ch</code> is abandoned.
 </p>
 
 {{code "/doc/progs/timeout1.go" `/select {/` `/STOP/`}}
@@ -64,7 +64,7 @@ could fail since no one is ready.
 </p>
 
 <p>
-This problem is a textbook of example of what is known as a
+This problem is a textbook example of what is known as a
 <a href="https://en.wikipedia.org/wiki/Race_condition">race condition</a>, but
 the fix is trivial. We just make sure to buffer the channel <code>ch</code> (by
 adding the buffer length as the second argument to <a href="/pkg/builtin/#make">make</a>),
diff --git a/doc/articles/error_handling.html b/doc/articles/error_handling.html
index 8f4fffb..6ba05ac 100644
--- a/doc/articles/error_handling.html
+++ b/doc/articles/error_handling.html
@@ -137,7 +137,7 @@ messages:
 
 <p>
 (This is a slightly simplified version of some
-<a href="http://camlistore.org/code/?p=camlistore.git;a=blob;f=lib/go/camli/jsonconfig/eval.go#l68">actual code</a>
+<a href="http://golang.org/s/camjsondecode">actual code</a>
 from the <a href="http://camlistore.org">Camlistore</a> project.)
 </p>
 
diff --git a/doc/articles/go_command.html b/doc/articles/go_command.html
index 1e9e70f..fddca41 100644
--- a/doc/articles/go_command.html
+++ b/doc/articles/go_command.html
@@ -48,9 +48,9 @@ had to be installed in certain places, under certain names, using certain build
 tools, in order to be used. That's understandable: that's the way it works in
 most other languages. Over the last few years we consistently reminded people
 about the <code>goinstall</code> command
-(now replaced by <a href="/cmd/go/#Download_and_install_packages_and_dependencies"><code>go get</code></a>)
+(now replaced by <a href="/cmd/go/#hdr-Download_and_install_packages_and_dependencies"><code>go get</code></a>)
 and its conventions: first, that the import path is derived in a known way from
-the URL of the source code; second, that that the place to store the sources in
+the URL of the source code; second, that the place to store the sources in
 the local file system is derived in a known way from the import path; third,
 that each directory in a source tree corresponds to a single package; and
 fourth, that the package is built using only information in the source code.
diff --git a/doc/articles/godoc_documenting_go_code.html b/doc/articles/godoc_documenting_go_code.html
index ca66076..18a3ee9 100644
--- a/doc/articles/godoc_documenting_go_code.html
+++ b/doc/articles/godoc_documenting_go_code.html
@@ -65,8 +65,8 @@ package's brief description:
 {{code "/src/pkg/sort/sort.go" `/Package sort provides/` `/package sort/`}}
 
 <p>
-They can also be detailed like the <a href="/pkg/encoding/gob/">gob package</a>'s
-overview. That package uses another convention for packages
+They can also be detailed like the <a href="/pkg/encoding/gob/"><code>gob</code></a>
+package's overview. That package uses another convention for packages
 that need large amounts of introductory documentation: the package comment is
 placed in its own file, <a href="/src/pkg/encoding/gob/doc.go">doc.go</a>, which
 contains only those comments and a package clause.
@@ -80,10 +80,10 @@ sentence will appear in godoc's <a href="/pkg/">package list</a>.
 <p>
 Comments that are not adjacent to a top-level declaration are omitted from
 godoc's output, with one notable exception. Top-level comments that begin with
-the word <code>"BUG(who)”</code> are recognized as known bugs, and included in
-the "Bugs” section of the package documentation. The "who” part should be the
+the word <code>"BUG(who)"</code> are recognized as known bugs, and included in
+the "Bugs" section of the package documentation. The "who" part should be the
 user name of someone who could provide more information. For example, this is a
-known issue from the <a href="/pkg/bytes/#bugs">bytes package</a>:
+known issue from the <a href="/pkg/bytes/#pkg-bugs"><code>bytes</code></a> package:
 </p>
 
 <pre>
@@ -93,7 +93,7 @@ known issue from the <a href="/pkg/bytes/#bugs">bytes package</a>:
 <p>
 Godoc treats executable commands somewhat differently. Instead of inspecting the
 command source code, it looks for a Go source file belonging to the special
-package "documentation”. The comment on the "package documentation” clause is
+package "documentation". The comment on the "package documentation" clause is
 used as the command's documentation. For example, see the
 <a href="/cmd/godoc/">godoc documentation</a> and its corresponding
 <a href="/src/cmd/godoc/doc.go">doc.go</a> file.
@@ -137,3 +137,9 @@ indexing via the <code>-path</code> flag or just by running <code>"godoc ."</cod
 in the source directory. See the <a href="/cmd/godoc/">godoc documentation</a>
 for more details.
 </p>
+
+<p>
+Godoc recognizes example functions written according to the
+<a href="/pkg/testing/#pkg-overview"><code>testing</code></a> package's naming
+conventions and presents them appropriately.
+</p>
diff --git a/doc/articles/image_package.html b/doc/articles/image_package.html
index a9d2f35..ebe92a1 100644
--- a/doc/articles/image_package.html
+++ b/doc/articles/image_package.html
@@ -45,7 +45,7 @@ classic algebra:
 dstr, dstg, dstb, dsta := dst.RGBA()
 srcr, srcg, srcb, srca := src.RGBA()
 _, _, _, m := mask.RGBA()
-const M = 1<<16 - 1
+const M = 1<<16 - 1
 // The resultant red value is a blend of dstr and srcr, and ranges in [0, M].
 // The calculation for green, blue and alpha is similar.
 dstr = (dstr*(M-m) + srcr*m) / M
@@ -130,7 +130,7 @@ much easier to type.
 A <code>Rectangle</code> is inclusive at the top-left and exclusive at the
 bottom-right. For a <code>Point p</code> and a <code>Rectangle r</code>,
 <code>p.In(r)</code> if and only if
-<code>r.Min.X <= p.X && p.X < r.Max.X</code>, and similarly for <code>Y</code>. This is analagous to how
+<code>r.Min.X <= p.X && p.X < r.Max.X</code>, and similarly for <code>Y</code>. This is analagous to how
 a slice <code>s[i0:i1]</code> is inclusive at the low end and exclusive at the
 high end. (Unlike arrays and slices, a <code>Rectangle</code> often has a
 non-zero origin.)
@@ -193,8 +193,8 @@ way to iterate over an <code>Image</code> m's pixels looks like:
 
 <pre>
 b := m.Bounds()
-for y := b.Min.Y; y < b.Max.Y; y++ {
-	for x := b.Min.X; y < b.Max.X; x++ {
+for y := b.Min.Y; y < b.Max.Y; y++ {
+	for x := b.Min.X; x < b.Max.X; x++ {
 		doStuffWith(m.At(x, y))
 	}
 }
diff --git a/doc/articles/json_and_go.html b/doc/articles/json_and_go.html
index af7776c..8c4ef33 100644
--- a/doc/articles/json_and_go.html
+++ b/doc/articles/json_and_go.html
@@ -43,7 +43,7 @@ and an instance of <code>Message</code>
 {{code "/doc/progs/json1.go" `/m :=/`}}
 
 <p>
-we can marshal a JSON-encoded version of m using <code>json.Marshal</code>:
+we can marshal a JSON-encoded version of <code>m</code> using <code>json.Marshal</code>:
 </p>
 
 {{code "/doc/progs/json1.go" `/b, err :=/`}}
@@ -82,8 +82,8 @@ is <code>nil</code>).
 
 <p>
 The json package only accesses the exported fields of struct types (those that
-begin with an uppercase letter). Therefore only the the exported fields of a
-struct will be present in the JSON output.
+begin with an uppercase letter). Therefore only the exported fields of a struct
+will be present in the JSON output.
 </p>
 
 <p>
@@ -130,7 +130,7 @@ preference):
 
 <ul>
 <li>
-An exported field with a tag of <code>"Foo"</code> (see the
+An exported field with a tag of <code>`json:"Foo"`</code> (see the
 <a href="/ref/spec#Struct_types">Go spec</a> for more on struct tags),
 </li>
 <li>
@@ -151,11 +151,11 @@ type?
 
 <p>
 <code>Unmarshal</code> will decode only the fields that it can find in the
-destination type.  In this case, only the Name field of m will be populated,
-and the Food field will be ignored. This behavior is particularly useful when
-you wish to pick only a few specific fields out of a large JSON blob. It also
-means that any unexported fields in the destination struct will be unaffected
-by <code>Unmarshal</code>.
+destination type.  In this case, only the <code>Name</code> field of m will be
+populated, and the <code>Food</code> field will be ignored. This behavior is
+particularly useful when you wish to pick only a few specific fields out of a
+large JSON blob. It also means that any unexported fields in the destination
+struct will be unaffected by <code>Unmarshal</code>.
 </p>
 
 <p>
@@ -163,7 +163,7 @@ But what if you don't know the structure of your JSON data beforehand?
 </p>
 
 <p>
-<b>Generic JSON with interface{}</b>
+<b>Generic JSON with <code>interface{}</code></b>
 </p>
 
 <p>
@@ -190,11 +190,12 @@ Or, if the underlying type is unknown, a type switch determines the type:
 
 {{code "/doc/progs/json2.go" `/switch v/` `/STOP/`}}
 
-
+<p>
 The json package uses <code>map[string]interface{}</code> and
 <code>[]interface{}</code> values to store arbitrary JSON objects and arrays;
 it will happily unmarshal any valid JSON blob into a plain
 <code>interface{}</code> value.  The default concrete Go types are:
+</p>
 
 <ul>
 <li>
diff --git a/doc/articles/json_rpc_tale_of_interfaces.html b/doc/articles/json_rpc_tale_of_interfaces.html
index a545f55..0db366f 100644
--- a/doc/articles/json_rpc_tale_of_interfaces.html
+++ b/doc/articles/json_rpc_tale_of_interfaces.html
@@ -57,7 +57,7 @@ original functionality. From there it is simple to build a
 After some similar changes to the client side, this was the full extent of the
 work we needed to do on the RPC package. This whole exercise took about 20
 minutes! After tidying up and testing the new code, the
-<a href="http://code.google.com/p/go/source/diff?spec=svn9daf796ebf1cae97b2fcf760a4ab682f1f063f29&r=9daf796ebf1cae97b2fcf760a4ab682f1f063f29&format=side&path=/src/pkg/rpc/server.go">final changeset</a>
+<a href="http://code.google.com/p/go/source/diff?spec=svn9daf796ebf1cae97b2fcf760a4ab682f1f063f29&r=9daf796ebf1cae97b2fcf760a4ab682f1f063f29&format=side&path=/src/pkg/rpc/server.go">final changeset</a>
 was submitted.
 </p>
 
diff --git a/doc/articles/laws_of_reflection.html b/doc/articles/laws_of_reflection.html
index 826a054..81f6697 100644
--- a/doc/articles/laws_of_reflection.html
+++ b/doc/articles/laws_of_reflection.html
@@ -213,7 +213,7 @@ type: float64
 You might be wondering where the interface is here, since the program looks
 like it's passing the <code>float64</code> variable <code>x</code>, not an
 interface value, to <code>reflect.TypeOf</code>. But it's there; as
-<a href="/pkg/reflect/#Type.TypeOf">godoc reports</a>, the signature of
+<a href="/pkg/reflect/#TypeOf">godoc reports</a>, the signature of
 <code>reflect.TypeOf</code> includes an empty interface:
 </p>
 
diff --git a/doc/articles/race_detector.html b/doc/articles/race_detector.html
new file mode 100644
index 0000000..400d96b
--- /dev/null
+++ b/doc/articles/race_detector.html
@@ -0,0 +1,369 @@
+<!--{
+	"Title": "Data Race Detector",
+	"Template": true
+}-->
+
+<h2 id="Introduction">Introduction</h2>
+
+<p>
+Data races are one of the most common and hardest to debug types of bugs in concurrent systems.  A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write.  See the <a href="/ref/mem/">The Go Memory Model</a> for details.
+</p>
+
+<p>
+Here is an example of a data race that can lead to crashes and memory corruption:
+</p>
+
+<pre>
+func main() {
+	c := make(chan bool)
+	m := make(map[string]string)
+	go func() {
+		m["1"] = "a" // First conflicting access.
+		c <- true
+	}()
+	m["2"] = "b" // Second conflicting access.
+	<-c
+	for k, v := range m {
+		fmt.Println(k, v)
+	}
+}
+</pre>
+
+<h2 id="Usage">Usage</h2>
+
+<p>
+Fortunately, Go includes a built-in data race detector.  To use it, add the <code>-race</code> flag to the go command:
+</p>
+
+<pre>
+$ go test -race mypkg    // to test the package
+$ go run -race mysrc.go  // to run the source file
+$ go build -race mycmd   // to build the command
+$ go install -race mypkg // to install the package
+</pre>
+
+<h2 id="Report_Format">Report Format</h2>
+
+<p>
+When the race detector finds a data race in the program, it prints a report.  The report contains stack traces for conflicting accesses, as well as stacks where the involved goroutines were created.  For example:
+</p>
+
+<pre>
+WARNING: DATA RACE
+Read by goroutine 185:
+  net.(*pollServer).AddFD()
+      src/pkg/net/fd_unix.go:89 +0x398
+  net.(*pollServer).WaitWrite()
+      src/pkg/net/fd_unix.go:247 +0x45
+  net.(*netFD).Write()
+      src/pkg/net/fd_unix.go:540 +0x4d4
+  net.(*conn).Write()
+      src/pkg/net/net.go:129 +0x101
+  net.func·060()
+      src/pkg/net/timeout_test.go:603 +0xaf
+
+Previous write by goroutine 184:
+  net.setWriteDeadline()
+      src/pkg/net/sockopt_posix.go:135 +0xdf
+  net.setDeadline()
+      src/pkg/net/sockopt_posix.go:144 +0x9c
+  net.(*conn).SetDeadline()
+      src/pkg/net/net.go:161 +0xe3
+  net.func·061()
+      src/pkg/net/timeout_test.go:616 +0x3ed
+
+Goroutine 185 (running) created at:
+  net.func·061()
+      src/pkg/net/timeout_test.go:609 +0x288
+
+Goroutine 184 (running) created at:
+  net.TestProlongTimeout()
+      src/pkg/net/timeout_test.go:618 +0x298
+  testing.tRunner()
+      src/pkg/testing/testing.go:301 +0xe8
+</pre>
+
+<h2 id="Options">Options</h2>
+
+<p>
+The <code>GORACE</code> environment variable sets race detector options.  The format is:
+</p>
+
+<pre>
+GORACE="option1=val1 option2=val2"
+</pre>
+
+<p>
+The options are:
+</p>
+
+<ul>
+<li>
+<code>log_path</code> (default <code>stderr</code>): The race detector writes
+its report to a file named log_path.pid.  The special names <code>stdout</code>
+and <code>stderr</code> cause reports to be written to standard output and
+standard error, respectively.
+</li>
+
+<li>
+<code>exitcode</code> (default <code>66</code>): The exit status to use when
+exiting after a detected race.
+</li>
+
+<li>
+<code>strip_path_prefix</code> (default <code>""</code>): Strip this prefix
+from all reported file paths, to make reports more concise.
+</li>
+
+<li>
+<code>history_size</code> (default <code>1</code>): The per-goroutine memory
+access history is <code>32K * 2**history_size elements</code>. Increasing this
+value can avoid a "failed to restore the stack" error in reports, but at the
+cost of increased memory usage.
+</li>
+</ul>
+
+<p>
+Example:
+</p>
+
+<pre>
+$ GORACE="log_path=/tmp/race/report strip_path_prefix=/my/go/sources/" go test -race
+</pre>
+
+<h2 id="Excluding_Tests">Excluding Tests</h2>
+
+<p>
+When you build with <code>-race</code> flag, go command defines additional
+<a href="/pkg/go/build/#Build_Constraints">build tag</a> <code>race</code>.
+You can use it to exclude some code/tests under the race detector. For example:
+</p>
+
+<pre>
+// +build !race
+
+package foo
+
+// The test contains a data race. See issue 123.
+func TestFoo(t *testing.T) {
+	// ...
+}
+
+// The test fails under the race detector due to timeouts.
+func TestBar(t *testing.T) {
+	// ...
+}
+
+// The test takes too long under the race detector.
+func TestBaz(t *testing.T) {
+	// ...
+}
+</pre>
+
+<h2 id="How_To_Use">How To Use</h2>
+
+<p>
+To start, run your tests using the race detector (<code>go test -race</code>).
+The race detector only finds races that happen at runtime, so it can't find
+races in code paths that are not executed. If your tests have incomplete coverage,
+you may find more races by running a binary built with <code>-race</code> under a realistic
+workload.
+</p>
+
+<h2 id="Typical_Data_Races">Typical Data Races</h2>
+
+<p>
+Here are some typical data races.  All of them can be detected with the race detector.
+</p>
+
+<h3 id="Race_on_loop_counter">Race on loop counter</h3>
+
+<pre>
+func main() {
+	var wg sync.WaitGroup
+	wg.Add(5)
+	for i := 0; i < 5; i++ {
+		go func() {
+			fmt.Println(i) // Not the 'i' you are looking for.
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+</pre>
+
+<p>
+The variable <code>i</code> in the function literal is the same variable used by the loop, so
+the read in the goroutine races with the loop increment. (This program typically
+prints 55555, not 01234.) The program can be fixed by making a copy of the
+variable:
+</p>
+
+<pre>
+func main() {
+	var wg sync.WaitGroup
+	wg.Add(5)
+	for i := 0; i < 5; i++ {
+		go func(j int) {
+			fmt.Println(j) // Good. Read local copy of the loop counter.
+			wg.Done()
+		}(i)
+	}
+	wg.Wait()
+}
+</pre>
+
+<h3 id="Accidentally_shared_variable">Accidentally shared variable</h3>
+
+<pre>
+// ParallelWrite writes data to file1 and file2, returns the errors.
+func ParallelWrite(data []byte) chan error {
+	res := make(chan error, 2)
+	f1, err := os.Create("file1")
+	if err != nil {
+		res <- err
+	} else {
+		go func() {
+			// This err is shared with the main goroutine,
+			// so the write races with the write below.
+			_, err = f1.Write(data)
+			res <- err
+			f1.Close()
+		}()
+	}
+	f2, err := os.Create("file2") // The second conflicting write to err.
+	if err != nil {
+		res <- err
+	} else {
+		go func() {
+			_, err = f2.Write(data)
+			res <- err
+			f2.Close()
+		}()
+	}
+	return res
+}
+</pre>
+
+<p>
+The fix is to introduce new variables in the goroutines (note <code>:=</code>):
+</p>
+
+<pre>
+			...
+			_, err := f1.Write(data)
+			...
+			_, err := f2.Write(data)
+			...
+</pre>
+
+<h3 id="Unprotected_global_variable">Unprotected global variable</h3>
+
+<p>
+If the following code is called from several goroutines, it leads to bad races on the <code>service</code> map.
+Concurrent reads and writes of a map are not safe:
+</p>
+
+<pre>
+var service map[string]net.Addr
+
+func RegisterService(name string, addr net.Addr) {
+	service[name] = addr
+}
+
+func LookupService(name string) net.Addr {
+	return service[name]
+}
+</pre>
+
+<p>
+To make the code safe, protect the accesses with a mutex:
+</p>
+
+<pre>
+var (
+	service   map[string]net.Addr
+	serviceMu sync.Mutex
+)
+
+func RegisterService(name string, addr net.Addr) {
+	serviceMu.Lock()
+	defer serviceMu.Unlock()
+	service[name] = addr
+}
+
+func LookupService(name string) net.Addr {
+	serviceMu.Lock()
+	defer serviceMu.Unlock()
+	return service[name]
+}
+</pre>
+
+<h3 id="Primitive_unprotected_variable">Primitive unprotected variable</h3>
+
+<p>
+Data races can happen on variables of primitive types as well (<code>bool</code>, <code>int</code>, <code>int64</code>, etc.), like in the following example:
+</p>
+
+<pre>
+type Watchdog struct{ last int64 }
+
+func (w *Watchdog) KeepAlive() {
+	w.last = time.Now().UnixNano() // First conflicting access.
+}
+
+func (w *Watchdog) Start() {
+	go func() {
+		for {
+			time.Sleep(time.Second)
+			// Second conflicting access.
+			if w.last < time.Now().Add(-10*time.Second).UnixNano() {
+				fmt.Println("No keepalives for 10 seconds. Dying.")
+				os.Exit(1)
+			}
+		}
+	}()
+}
+</pre>
+
+<p>
+Even such “innocent” data races can lead to hard to debug problems caused by (1) non-atomicity of the memory accesses, (2) interference with compiler optimizations and (3) processor memory access reordering issues.
+</p>
+
+<p>
+A typical fix for this race is to use a channel or a mutex.
+To preserve the lock-free behavior, one can also use the <a href="/pkg/sync/atomic/"><code>sync/atomic</code></a> package.
+</p>
+
+<pre>
+type Watchdog struct{ last int64 }
+
+func (w *Watchdog) KeepAlive() {
+	atomic.StoreInt64(&w.last, time.Now().UnixNano())
+}
+
+func (w *Watchdog) Start() {
+	go func() {
+		for {
+			time.Sleep(time.Second)
+			if atomic.LoadInt64(&w.last) < time.Now().Add(-10*time.Second).UnixNano() {
+				fmt.Println("No keepalives for 10 seconds. Dying.")
+				os.Exit(1)
+			}
+		}
+	}()
+}
+</pre>
+
+<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>.
+</p>
+
+<h2 id="Runtime_Overheads">Runtime Overhead</h2>
+
+<p>
+The cost of race detection varies by program, but for a typical program, memory
+usage may increase by 5-10x and execution time by 2-20x.
+</p>
diff --git a/doc/articles/slices_usage_and_internals.html b/doc/articles/slices_usage_and_internals.html
index 810b0a4..7eb751b 100644
--- a/doc/articles/slices_usage_and_internals.html
+++ b/doc/articles/slices_usage_and_internals.html
@@ -243,7 +243,7 @@ slice itself) of a re-slice modifies the elements of the original slice:
 d := []byte{'r', 'o', 'a', 'd'}
 e := d[2:] 
 // e == []byte{'a', 'd'}
-e[1] == 'm'
+e[1] = 'm'
 // e == []byte{'a', 'm'}
 // d == []byte{'r', 'o', 'a', 'm'}
 </pre>
diff --git a/doc/articles/wiki/get.go b/doc/articles/wiki/get.go
index c6e9bf2..b3e464b 100644
--- a/doc/articles/wiki/get.go
+++ b/doc/articles/wiki/get.go
@@ -13,11 +13,13 @@ import (
 	"net/http"
 	"os"
 	"strings"
+	"time"
 )
 
 var (
 	post = flag.String("post", "", "urlencoded form data to POST")
 	addr = flag.Bool("addr", false, "find open address and print to stdout")
+	wait = flag.Duration("wait_for_port", 0, "if non-zero, the amount of time to wait for the address to become available")
 )
 
 func main() {
@@ -37,11 +39,18 @@ func main() {
 	}
 	var r *http.Response
 	var err error
-	if *post != "" {
-		b := strings.NewReader(*post)
-		r, err = http.Post(url, "application/x-www-form-urlencoded", b)
-	} else {
-		r, err = http.Get(url)
+	loopUntil := time.Now().Add(*wait)
+	for {
+		if *post != "" {
+			b := strings.NewReader(*post)
+			r, err = http.Post(url, "application/x-www-form-urlencoded", b)
+		} else {
+			r, err = http.Get(url)
+		}
+		if err == nil || *wait == 0 || time.Now().After(loopUntil) {
+			break
+		}
+		time.Sleep(100 * time.Millisecond)
 	}
 	if err != nil {
 		log.Fatal(err)
diff --git a/doc/articles/wiki/index.html b/doc/articles/wiki/index.html
index 6c45d71..ea3507f 100644
--- a/doc/articles/wiki/index.html
+++ b/doc/articles/wiki/index.html
@@ -46,7 +46,7 @@ $ cd gowiki
 </pre>
 
 <p>
-Create a file named <code>wiki.go</code>, open it in your favorite editor, and 
+Create a file named <code>wiki.go</code>, open it in your favorite editor, and
 add the following lines:
 </p>
 
@@ -60,8 +60,8 @@ import (
 </pre>
 
 <p>
-We import the <code>fmt</code> and <code>ioutil</code> packages from the Go 
-standard library. Later, as we implement additional functionality, we will 
+We import the <code>fmt</code> and <code>ioutil</code> packages from the Go
+standard library. Later, as we implement additional functionality, we will
 add more packages to this <code>import</code> declaration.
 </p>
 
@@ -77,7 +77,7 @@ the title and body.
 {{code "doc/articles/wiki/part1.go" `/^type Page/` `/}/`}}
 
 <p>
-The type <code>[]byte</code> means "a <code>byte</code> slice". 
+The type <code>[]byte</code> means "a <code>byte</code> slice".
 (See <a href="/doc/articles/slices_usage_and_internals.html">Slices: usage and
 internals</a> for more on slices.)
 The <code>Body</code> element is a <code>[]byte</code> rather than
@@ -86,8 +86,8 @@ libraries we will use, as you'll see below.
 </p>
 
 <p>
-The <code>Page</code> struct describes how page data will be stored in memory. 
-But what about persistent storage? We can address that by creating a 
+The <code>Page</code> struct describes how page data will be stored in memory.
+But what about persistent storage? We can address that by creating a
 <code>save</code> method on <code>Page</code>:
 </p>
 
@@ -96,11 +96,11 @@ But what about persistent storage? We can address that by creating a
 <p>
 This method's signature reads: "This is a method named <code>save</code> that
 takes as its receiver <code>p</code>, a pointer to <code>Page</code> . It takes
-no parameters, and returns a value of type <code>error</code>." 
+no parameters, and returns a value of type <code>error</code>."
 </p>
 
 <p>
-This method will save the <code>Page</code>'s <code>Body</code> to a text 
+This method will save the <code>Page</code>'s <code>Body</code> to a text
 file. For simplicity, we will use the <code>Title</code> as the file name.
 </p>
 
@@ -110,35 +110,37 @@ that is the return type of <code>WriteFile</code> (a standard library function
 that writes a byte slice to a file).  The <code>save</code> method returns the
 error value, to let the application handle it should anything go wrong while
 writing the file.  If all goes well, <code>Page.save()</code> will return
-<code>nil</code> (the zero-value for pointers, interfaces, and some other 
+<code>nil</code> (the zero-value for pointers, interfaces, and some other
 types).
 </p>
 
 <p>
-The octal integer constant <code>0600</code>, passed as the third parameter to
+The octal integer literal <code>0600</code>, passed as the third parameter to
 <code>WriteFile</code>, indicates that the file should be created with
 read-write permissions for the current user only. (See the Unix man page
 <code>open(2)</code> for details.)
 </p>
 
 <p>
-We will want to load pages, too:
+In addition to saving pages, we will want to load pages, too:
 </p>
 
 {{code "doc/articles/wiki/part1-noerror.go" `/^func loadPage/` `/^}/`}}
 
 <p>
 The function <code>loadPage</code> constructs the file name from
-<code>Title</code>, reads the file's contents into a new
-<code>Page</code>, and returns a pointer to that new <code>page</code>.
+the title parameter, reads the file's contents into a new
+variable <code>body</code>, and returns two values: a pointer to a
+<code>Page</code> literal constructed with the proper title and body
+values and <code>nil</code> for the error value.
 </p>
 
 <p>
-Functions can return multiple values. The standard library function 
-<code>io.ReadFile</code> returns <code>[]byte</code> and <code>error</code>. 
+Functions can return multiple values. The standard library function
+<code>io.ReadFile</code> returns <code>[]byte</code> and <code>error</code>.
 In <code>loadPage</code>, error isn't being handled yet; the "blank identifier"
 represented by the underscore (<code>_</code>) symbol is used to throw away the
-error return value (in essence, assigning the value to nothing). 
+error return value (in essence, assigning the value to nothing).
 </p>
 
 <p>
@@ -152,7 +154,7 @@ function to return <code>*Page</code> and <code>error</code>.
 <p>
 Callers of this function can now check the second parameter; if it is
 <code>nil</code> then it has successfully loaded a Page. If not, it will be an
-<code>error</code> that can be handled by the caller (see the 
+<code>error</code> that can be handled by the caller (see the
 <a href="/ref/spec#Errors">language specification</a> for details).
 </p>
 
@@ -172,7 +174,7 @@ printed to the screen.
 </p>
 
 <p>
-You can compile and run the program like this: 
+You can compile and run the program like this:
 </p>
 
 <pre>
@@ -182,7 +184,7 @@ This is a sample page.
 </pre>
 
 <p>
-(If you're using Windows you must type "<code>wiki</code>" without the 
+(If you're using Windows you must type "<code>wiki</code>" without the
 "<code>./</code>" to run the program.)
 </p>
 
@@ -199,10 +201,10 @@ Here's a full working example of a simple web server:
 {{code "doc/articles/wiki/http-sample.go"}}
 
 <p>
-The <code>main</code> function begins with a call to 
-<code>http.HandleFunc</code>, which tells the <code>http</code> package to 
-handle all requests to the web root (<code>"/"</code>) with 
-<code>handler</code>. 
+The <code>main</code> function begins with a call to
+<code>http.HandleFunc</code>, which tells the <code>http</code> package to
+handle all requests to the web root (<code>"/"</code>) with
+<code>handler</code>.
 </p>
 
 <p>
@@ -219,20 +221,20 @@ its arguments.
 </p>
 
 <p>
-An <code>http.ResponseWriter</code> value assembles the HTTP server's response; by writing 
+An <code>http.ResponseWriter</code> value assembles the HTTP server's response; by writing
 to it, we send data to the HTTP client.
 </p>
 
 <p>
 An <code>http.Request</code> is a data structure that represents the client
-HTTP request.  The string <code>r.URL.Path</code> is the path component
-of the request URL.  The trailing <code>[1:]</code> means
-"create a sub-slice of <code>Path</code> from the 1st character to the end." 
+HTTP request. <code>r.URL.Path</code> is the path component
+of the request URL. The trailing <code>[1:]</code> means
+"create a sub-slice of <code>Path</code> from the 1st character to the end."
 This drops the leading "/" from the path name.
 </p>
 
 <p>
-If you run this program and access the URL: 
+If you run this program and access the URL:
 </p>
 <pre>http://localhost:8080/monkeys</pre>
 <p>
@@ -249,13 +251,14 @@ To use the <code>net/http</code> package, it must be imported:
 <pre>
 import (
 	"fmt"
-	<b>"net/http"</b>
 	"io/ioutil"
+	<b>"net/http"</b>
 )
 </pre>
 
 <p>
-Let's create a handler to view a wiki page: 
+Let's create a handler, <code>viewHandler</code> that will allow users to
+view a wiki page. It will handle URLs prefixed with "/view/".
 </p>
 
 {{code "doc/articles/wiki/part2.go" `/^const lenPath/`}}
@@ -264,28 +267,28 @@ Let's create a handler to view a wiki page:
 
 <p>
 First, this function extracts the page title from <code>r.URL.Path</code>,
-the path component of the request URL. The global constant 
+the path component of the request URL. The global constant
 <code>lenPath</code> is the length of the leading <code>"/view/"</code>
 component of the request path.
-The <code>Path</code> is re-sliced with <code>[lenPath:]</code> to drop the 
-first 6 characters of the string. This is because the path will invariably 
-begin with <code>"/view/"</code>, which is not part of the page title.
+The <code>Path</code> is re-sliced with <code>[lenPath:]</code> to drop the
+first 6 characters of the string. This is because the path will invariably
+begin with <code>"/view/"</code>, which is not part of the page's title.
 </p>
 
 <p>
-The function then loads the page data, formats the page with a string of simple 
-HTML, and writes it to <code>w</code>, the <code>http.ResponseWriter</code>. 
+The function then loads the page data, formats the page with a string of simple
+HTML, and writes it to <code>w</code>, the <code>http.ResponseWriter</code>.
 </p>
 
 <p>
-Again, note the use of <code>_</code> to ignore the <code>error</code> 
+Again, note the use of <code>_</code> to ignore the <code>error</code>
 return value from <code>loadPage</code>. This is done here for simplicity
 and generally considered bad practice. We will attend to this later.
 </p>
 
 <p>
-To use this handler, we create a <code>main</code> function that
-initializes <code>http</code> using the <code>viewHandler</code> to handle
+To use this handler, we rewrite our <code>main</code> function to
+initialize <code>http</code> using the <code>viewHandler</code> to handle
 any requests under the path <code>/view/</code>.
 </p>
 
@@ -311,6 +314,11 @@ $ ./wiki
 </pre>
 
 <p>
+(If you're using Windows you must type "<code>wiki</code>" without the
+"<code>./</code>" to run the program.)
+</p>
+
+<p>
 With this web server running, a visit to <code><a
 href="http://localhost:8080/view/test">http://localhost:8080/view/test</a></code>
 should show a page titled "test" containing the words "Hello world".
@@ -326,14 +334,14 @@ form.
 </p>
 
 <p>
-First, we add them to <code>main()</code>: 
+First, we add them to <code>main()</code>:
 </p>
 
 {{code "doc/articles/wiki/final-noclosure.go" `/^func main/` `/^}/`}}
 
 <p>
-The function <code>editHandler</code> loads the page 
-(or, if it doesn't exist, create an empty <code>Page</code> struct), 
+The function <code>editHandler</code> loads the page
+(or, if it doesn't exist, create an empty <code>Page</code> struct),
 and displays an HTML form.
 </p>
 
@@ -343,7 +351,7 @@ and displays an HTML form.
 This function will work fine, but all that hard-coded HTML is ugly.
 Of course, there is a better way.
 </p>
- 
+
 <h2>The <code>html/template</code> package</h2>
 
 <p>
@@ -354,20 +362,20 @@ underlying Go code.
 </p>
 
 <p>
-First, we must add <code>html/template</code> to the list of imports:
+First, we must add <code>html/template</code> to the list of imports. We
+also won't be using <code>fmt</code> anymore, so we have to remove that.
 </p>
 
 <pre>
 import (
 	<b>"html/template"</b>
-	"http"
 	"io/ioutil"
-	"os"
+	"net/http"
 )
 </pre>
 
 <p>
-Let's create a template file containing the HTML form. 
+Let's create a template file containing the HTML form.
 Open a new file named <code>edit.html</code>, and add the following lines:
 </p>
 
@@ -381,8 +389,8 @@ HTML:
 {{code "doc/articles/wiki/final-noerror.go" `/^func editHandler/` `/^}/`}}
 
 <p>
-The function <code>template.ParseFiles</code> will read the contents of 
-<code>edit.html</code> and return a <code>*template.Template</code>. 
+The function <code>template.ParseFiles</code> will read the contents of
+<code>edit.html</code> and return a <code>*template.Template</code>.
 </p>
 
 <p>
@@ -405,12 +413,7 @@ HTML.
 </p>
 
 <p>
-Now that we've removed the <code>fmt.Fprintf</code> statement, we can remove
-<code>"fmt"</code> from the <code>import</code> list.
-</p>
-
-<p>
-While we're working with templates, let's create a template for our
+Since we're working with templates now, let's create a template for our
 <code>viewHandler</code> called <code>view.html</code>:
 </p>
 
@@ -428,28 +431,31 @@ handlers. Let's remove this duplication by moving the templating code
 to its own function:
 </p>
 
+{{code "doc/articles/wiki/final-template.go" `/^func renderTemplate/` `/^}/`}}
 {{code "doc/articles/wiki/final-template.go" `/^func viewHandler/` `/^}/`}}
 {{code "doc/articles/wiki/final-template.go" `/^func editHandler/` `/^}/`}}
-{{code "doc/articles/wiki/final-template.go" `/^func renderTemplate/` `/^}/`}}
 
 <p>
-The handlers are now shorter and simpler. 
+If we comment out the registration of our unimplemented save handler in
+<code>main</code>, we can once again build and test our program.
+<a href="part3.go">Click here to view the code we've written so far.</a>
 </p>
 
 <h2>Handling non-existent pages</h2>
 
 <p>
 What if you visit <a href="http://localhost:8080/view/APageThatDoesntExist">
-<code>/view/APageThatDoesntExist</code></a>? The program will crash. This is 
-because it ignores the error return value from <code>loadPage</code>. Instead,
-if the requested Page doesn't exist, it should redirect the client to the edit
-Page so the content may be created:
+<code>/view/APageThatDoesntExist</code></a>? You'll see a page containing
+HTML. This is because it ignores the error return value from
+<code>loadPage</code> and continues to try and fill out the template
+with no data. Instead, if the requested Page doesn't exist, it should
+redirect the client to the edit Page so the content may be created:
 </p>
 
-{{code "doc/articles/wiki/final-noclosure.go" `/^func viewHandler/` `/^}/`}}
+{{code "doc/articles/wiki/part3-errorhandling.go" `/^func viewHandler/` `/^}/`}}
 
 <p>
-The <code>http.Redirect</code> function adds an HTTP status code of 
+The <code>http.Redirect</code> function adds an HTTP status code of
 <code>http.StatusFound</code> (302) and a <code>Location</code>
 header to the HTTP response.
 </p>
@@ -457,22 +463,24 @@ header to the HTTP response.
 <h2>Saving Pages</h2>
 
 <p>
-The function <code>saveHandler</code> will handle the form submission. 
+The function <code>saveHandler</code> will handle the submission of forms
+located on the edit pages. After uncommenting the related line in
+<code>main</code>, let's implement the the handler:
 </p>
 
 {{code "doc/articles/wiki/final-template.go" `/^func saveHandler/` `/^}/`}}
 
 <p>
-The page title (provided in the URL) and the form's only field, 
-<code>Body</code>, are stored in a new <code>Page</code>. 
+The page title (provided in the URL) and the form's only field,
+<code>Body</code>, are stored in a new <code>Page</code>.
 The <code>save()</code> method is then called to write the data to a file,
 and the client is redirected to the <code>/view/</code> page.
 </p>
 
 <p>
 The value returned by <code>FormValue</code> is of type <code>string</code>.
-We must convert that value to <code>[]byte</code> before it will fit into 
-the <code>Page</code> struct.  We use <code>[]byte(body)</code> to perform
+We must convert that value to <code>[]byte</code> before it will fit into
+the <code>Page</code> struct. We use <code>[]byte(body)</code> to perform
 the conversion.
 </p>
 
@@ -481,9 +489,9 @@ the conversion.
 <p>
 There are several places in our program where errors are being ignored.  This
 is bad practice, not least because when an error does occur the program will
-crash.  A better solution is to handle the errors and return an error message
-to the user. That way if something does go wrong, the server will continue to
-function and the user will be notified.
+have unintended behavior. A better solution is to handle the errors and return
+an error message to the user. That way if something does go wrong, the server
+will function exactly how we want and the user can be notified.
 </p>
 
 <p>
@@ -493,7 +501,7 @@ First, let's handle the errors in <code>renderTemplate</code>:
 {{code "doc/articles/wiki/final-parsetemplate.go" `/^func renderTemplate/` `/^}/`}}
 
 <p>
-The <code>http.Error</code> function sends a specified HTTP response code 
+The <code>http.Error</code> function sends a specified HTTP response code
 (in this case "Internal Server Error") and error message.
 Already the decision to put this in a separate function is paying off.
 </p>
@@ -502,18 +510,18 @@ Already the decision to put this in a separate function is paying off.
 Now let's fix up <code>saveHandler</code>:
 </p>
 
-{{code "doc/articles/wiki/final-noclosure.go" `/^func saveHandler/` `/^}/`}}
+{{code "doc/articles/wiki/part3-errorhandling.go" `/^func saveHandler/` `/^}/`}}
 
 <p>
-Any errors that occur during <code>p.save()</code> will be reported 
+Any errors that occur during <code>p.save()</code> will be reported
 to the user.
 </p>
 
 <h2>Template caching</h2>
 
 <p>
-There is an inefficiency in this code: <code>renderTemplate</code> calls 
-<code>ParseFiles</code> every time a page is rendered. 
+There is an inefficiency in this code: <code>renderTemplate</code> calls
+<code>ParseFiles</code> every time a page is rendered.
 A better approach would be to call <code>ParseFiles</code> once at program
 initialization, parsing all templates into a single <code>*Template</code>.
 Then we can use the
@@ -536,10 +544,11 @@ can't be loaded the only sensible thing to do is exit the program.
 </p>
 
 <p>
-A <code>for</code> loop is used with a <code>range</code> statement to iterate 
-over an array constant containing the names of the templates we want parsed.
-If we were to add more templates to our program, we would add their names to 
-that array.
+The <code>ParseFiles</code> function takes any number of string arguments that
+identify our template files, and parses those files into templates that are
+named after the base file name. If we were to add more templates to our
+program, we would add their names to the <code>ParseFiles</code> call's
+arguments.
 </p>
 
 <p>
@@ -571,25 +580,27 @@ Then we can create a global variable to store our validation regexp:
 {{code "doc/articles/wiki/final-noclosure.go" `/^var titleValidator/`}}
 
 <p>
-The function <code>regexp.MustCompile</code> will parse and compile the 
-regular expression, and return a <code>regexp.Regexp</code>. 
+The function <code>regexp.MustCompile</code> will parse and compile the
+regular expression, and return a <code>regexp.Regexp</code>.
 <code>MustCompile</code> is distinct from <code>Compile</code> in that it will
 panic if the expression compilation fails, while <code>Compile</code> returns
-an <code>error</code> as a second parameter. 
+an <code>error</code> as a second parameter.
 </p>
 
 <p>
-Now, let's write a function that extracts the title string from the request 
-URL, and tests it against our <code>TitleValidator</code> expression:
+Now, let's write a function, <code>getTitle</code>, that extracts the title
+string from the request URL, and tests it against our
+<code>TitleValidator</code> expression:
 </p>
 
 {{code "doc/articles/wiki/final-noclosure.go" `/func getTitle/` `/^}/`}}
 
 <p>
 If the title is valid, it will be returned along with a <code>nil</code>
-error value.  If the title is invalid, the function will write a 
-"404 Not Found" error to the HTTP connection, and return an error to the 
-handler. 
+error value. If the title is invalid, the function will write a
+"404 Not Found" error to the HTTP connection, and return an error to the
+handler. To create a new error, we have to import the <code>errors</code>
+package.
 </p>
 
 <p>
@@ -604,10 +615,10 @@ Let's put a call to <code>getTitle</code> in each of the handlers:
 
 <p>
 Catching the error condition in each handler introduces a lot of repeated code.
-What if we could wrap each of the handlers in a function that does this 
-validation and error checking? Go's 
-<a href="/ref/spec#Function_declarations">function 
-literals</a> provide a powerful means of abstracting functionality 
+What if we could wrap each of the handlers in a function that does this
+validation and error checking? Go's
+<a href="/ref/spec#Function_declarations">function
+literals</a> provide a powerful means of abstracting functionality
 that can help us here.
 </p>
 
@@ -654,19 +665,19 @@ Now we can take the code from <code>getTitle</code> and use it here
 <p>
 The closure returned by <code>makeHandler</code> is a function that takes
 an <code>http.ResponseWriter</code> and <code>http.Request</code> (in other
-words, an <code>http.HandlerFunc</code>). 
+words, an <code>http.HandlerFunc</code>).
 The closure extracts the <code>title</code> from the request path, and
 validates it with the <code>TitleValidator</code> regexp. If the
 <code>title</code> is invalid, an error will be written to the
-<code>ResponseWriter</code> using the <code>http.NotFound</code> function. 
+<code>ResponseWriter</code> using the <code>http.NotFound</code> function.
 If the <code>title</code> is valid, the enclosed handler function
 <code>fn</code> will be called with the <code>ResponseWriter</code>,
 <code>Request</code>, and <code>title</code> as arguments.
 </p>
 
 <p>
-Now we can wrap the handler functions with <code>makeHandler</code> in 
-<code>main</code>, before they are registered with the <code>http</code> 
+Now we can wrap the handler functions with <code>makeHandler</code> in
+<code>main</code>, before they are registered with the <code>http</code>
 package:
 </p>
 
@@ -698,7 +709,7 @@ $ ./wiki
 
 <p>
 Visiting <a href="http://localhost:8080/view/ANewPage">http://localhost:8080/view/ANewPage</a>
-should present you with the page edit form. You should then be able to 
+should present you with the page edit form. You should then be able to
 enter some text, click 'Save', and be redirected to the newly created page.
 </p>
 
@@ -710,11 +721,11 @@ Here are some simple tasks you might want to tackle on your own:
 
 <ul>
 <li>Store templates in <code>tmpl/</code> and page data in <code>data/</code>.
-<li>Add a handler to make the web root redirect to 
+<li>Add a handler to make the web root redirect to
 	<code>/view/FrontPage</code>.</li>
 <li>Spruce up the page templates by making them valid HTML and adding some
 	CSS rules.</li>
-<li>Implement inter-page linking by converting instances of 
+<li>Implement inter-page linking by converting instances of
 	<code>[PageName]</code> to <br>
 	<code><a href="/view/PageName">PageName</a></code>.
 	(hint: you could use <code>regexp.ReplaceAllFunc</code> to do this)
diff --git a/doc/articles/wiki/part3-errorhandling.go b/doc/articles/wiki/part3-errorhandling.go
new file mode 100644
index 0000000..945aa1e
--- /dev/null
+++ b/doc/articles/wiki/part3-errorhandling.go
@@ -0,0 +1,75 @@
+// 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 main
+
+import (
+	"html/template"
+	"io/ioutil"
+	"net/http"
+)
+
+type Page struct {
+	Title string
+	Body  []byte
+}
+
+func (p *Page) save() error {
+	filename := p.Title + ".txt"
+	return ioutil.WriteFile(filename, p.Body, 0600)
+}
+
+func loadPage(title string) (*Page, error) {
+	filename := title + ".txt"
+	body, err := ioutil.ReadFile(filename)
+	if err != nil {
+		return nil, err
+	}
+	return &Page{Title: title, Body: body}, nil
+}
+
+const lenPath = len("/view/")
+
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
+	t, _ := template.ParseFiles(tmpl + ".html")
+	t.Execute(w, p)
+}
+
+func viewHandler(w http.ResponseWriter, r *http.Request) {
+	title := r.URL.Path[lenPath:]
+	p, err := loadPage(title)
+	if err != nil {
+		http.Redirect(w, r, "/edit/"+title, http.StatusFound)
+		return
+	}
+	renderTemplate(w, "view", p)
+}
+
+func editHandler(w http.ResponseWriter, r *http.Request) {
+	title := r.URL.Path[lenPath:]
+	p, err := loadPage(title)
+	if err != nil {
+		p = &Page{Title: title}
+	}
+	renderTemplate(w, "edit", p)
+}
+
+func saveHandler(w http.ResponseWriter, r *http.Request) {
+	title := r.URL.Path[lenPath:]
+	body := r.FormValue("body")
+	p := &Page{Title: title, Body: []byte(body)}
+	err := p.save()
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	http.Redirect(w, r, "/view/"+title, http.StatusFound)
+}
+
+func main() {
+	http.HandleFunc("/view/", viewHandler)
+	http.HandleFunc("/edit/", editHandler)
+	http.HandleFunc("/save/", saveHandler)
+	http.ListenAndServe(":8080", nil)
+}
diff --git a/doc/articles/wiki/part3.go b/doc/articles/wiki/part3.go
new file mode 100644
index 0000000..7fe4351
--- /dev/null
+++ b/doc/articles/wiki/part3.go
@@ -0,0 +1,59 @@
+// 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 main
+
+import (
+	"html/template"
+	"io/ioutil"
+	"net/http"
+)
+
+type Page struct {
+	Title string
+	Body  []byte
+}
+
+func (p *Page) save() error {
+	filename := p.Title + ".txt"
+	return ioutil.WriteFile(filename, p.Body, 0600)
+}
+
+func loadPage(title string) (*Page, error) {
+	filename := title + ".txt"
+	body, err := ioutil.ReadFile(filename)
+	if err != nil {
+		return nil, err
+	}
+	return &Page{Title: title, Body: body}, nil
+}
+
+const lenPath = len("/view/")
+
+func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
+	t, _ := template.ParseFiles(tmpl + ".html")
+	t.Execute(w, p)
+}
+
+func viewHandler(w http.ResponseWriter, r *http.Request) {
+	title := r.URL.Path[lenPath:]
+	p, _ := loadPage(title)
+	renderTemplate(w, "view", p)
+}
+
+func editHandler(w http.ResponseWriter, r *http.Request) {
+	title := r.URL.Path[lenPath:]
+	p, err := loadPage(title)
+	if err != nil {
+		p = &Page{Title: title}
+	}
+	renderTemplate(w, "edit", p)
+}
+
+func main() {
+	http.HandleFunc("/view/", viewHandler)
+	http.HandleFunc("/edit/", editHandler)
+	//http.HandleFunc("/save/", saveHandler)
+	http.ListenAndServe(":8080", nil)
+}
diff --git a/doc/articles/wiki/test.bash b/doc/articles/wiki/test.bash
index 5c2cb60..02ed189 100755
--- a/doc/articles/wiki/test.bash
+++ b/doc/articles/wiki/test.bash
@@ -18,11 +18,10 @@ go build -o final-test.bin final-test.go
 (./final-test.bin) &
 wiki_pid=$!
 
-sleep 1
-
-./get.bin http://$addr/edit/Test > test_edit.out
+./get.bin --wait_for_port=5s http://$addr/edit/Test > test_edit.out
 diff -u test_edit.out test_edit.good
-./get.bin -post=body=some%20content http://$addr/save/Test
+./get.bin -post=body=some%20content http://$addr/save/Test > test_save.out
+diff -u test_save.out test_view.good # should be the same as viewing
 diff -u Test.txt test_Test.txt.good
 ./get.bin http://$addr/view/Test > test_view.out
 diff -u test_view.out test_view.good
diff --git a/doc/code.html b/doc/code.html
index efbe7ee..82b2118 100644
--- a/doc/code.html
+++ b/doc/code.html
@@ -10,6 +10,10 @@ introduces the <a href="/cmd/go/">go command</a>, the standard way to fetch,
 build, and install Go packages and commands.
 </p>
 
+<p>
+This content is also available as a <a href="http://www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>.
+</p>
+
 
 <h2 id="GOPATH">Code organization</h2>
 
@@ -182,7 +186,7 @@ func Sqrt(x float64) float64 {
         // This is a terrible implementation.
         // Real code should import "math" and use math.Sqrt.
         z := 0.0
-        for i := 0; i < 1000; i++ {
+        for i := 0; i < 1000; i++ {
                 z -= (z*z - x) / (2 * x)
         }
         return z
@@ -402,7 +406,7 @@ ok  	example/newmath 0.165s
 </pre>
 
 <p>
-Run <code><a href="/cmd/go/#Test_packages">go help test</a></code> and see the
+Run <code><a href="/cmd/go/#hdr-Test_packages">go help test</a></code> and see the
 <a href="/pkg/testing/">testing package documentation</a> for more detail.
 </p>
 
@@ -476,13 +480,13 @@ import "code.google.com/p/go.example/newmath"
 <p>
 This convention is the easiest way to make your Go packages available for
 others to use.
-The <a href="http://godashboard.appspot.com">Go Project Dashboard</a>
-is a list of external Go projects including programs and libraries.
+The <a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Community Wiki</a>
+has a list of external Go projects including programs and libraries.
 </p>
 
 <p>
 For more information on using remote repositories with the <code>go</code> command, see
-<code><a href="/cmd/go/#Remote_import_path_syntax">go help remote</a></code>.
+<code><a href="/cmd/go/#hdr-Remote_import_path_syntax">go help remote</a></code>.
 </p>
 
 
diff --git a/doc/codereview_with_mq.html b/doc/codereview_with_mq.html
deleted file mode 100644
index 38ecbda..0000000
--- a/doc/codereview_with_mq.html
+++ /dev/null
@@ -1,115 +0,0 @@
-<!--{
-	"Title": "Using Mercurial Queues with Codereview"
-}-->
-
-<h2 id="Introduction">Introduction</h2>
-
-<p>
-The Mercurial Queues extension (<code>mq</code>) provides a mechanism for
-managing patches on top of a Mercurial repository and is described in detail
-in Chapters
-<a href="http://hgbook.red-bean.com/read/managing-change-with-mercurial-queues.html">12</a>
-and <a href="http://hgbook.red-bean.com/read/advanced-uses-of-mercurial-queues.html">13</a>
-of <a href="http://hgbook.red-bean.com/read/">Mercurial: The Definitive Guide</a>.
-This document explains how to use <code>mq</code> in conjunction
-with the <code>codereview</code> Mercurial extension described in the
-instructions for <a href="contribute.html">contributing to the Go project</a>.
-It assumes you have read those instructions.
-</p>
-
-<h2>Configuration</h2>
-
-<p>
-To enable <code>mq</code> edit either <code>$HOME/.hgrc</code> (to enable it
-for all of your repositories) or <code>$GOROOT/.hg/hgrc</code> (to enable it for the
-repository at <code>$GOROOT</code>) to add:</p>
-
-<pre>
-[extensions]
-mq=
-</pre>
-
-<p>
-Since pulling, pushing, updating and committing while <code>mq</code> patches
-are applied can damage your repository or a remote one, add these lines to
-prevent that case: 
-</p>
-
-<pre>
-[hooks]
-# Prevent "hg pull" if MQ patches are applied.
-prechangegroup.mq-no-pull = ! hg qtop > /dev/null 2>&1
-# Prevent "hg push" if MQ patches are applied.
-preoutgoing.mq-no-push = ! hg qtop > /dev/null 2>&1
-# Prevent "hg update" if MQ patches are applied.
-preupdate.mq-no-update = ! hg qtop > /dev/null 2>&1
-</pre>
-
-<h2>Making a change</h2>
-
-<p>
-The entire checked-out tree is writable and you can use <code>mq</code>,
-as documented in Chapter
-<a href="http://hgbook.red-bean.com/read/managing-change-with-mercurial-queues.html">12</a>
-of "The Guide",
-to implement your change as a single patch or a series of patches.
-
-</p>
-
-<p>When you are ready to send a change out for review, run</p>
-
-<pre>
-$ hg change
-</pre>
-
-<p>from any directory in your Go repository with all of the <code>mq</code> patches relevant to your
-change applied and then proceed as instructed in <a href="contribute.html">contributing
-to the Go project</a>.
-</p>
-
-<p>
-The change number reported by <code>hg change</code>, preceded by a <code>+</code>,
-can be used as an <code>mq</code> patch guard to assist in controlling which patches
-are applied as described in Chapter
-<a href="http://hgbook.red-bean.com/read/advanced-uses-of-mercurial-queues.html">13</a>
-of "The Guide".
-For example, the command:
-</p>
-
-<pre>
-for p in $(hg qapplied); do hg qguard $p +99999; done
-</pre>
-
-<p>
-will apply the guard <code>+99999</code> guard to all currently applied <code>mq</code>
-patches.
-</p>
-
-<h2>Synchronizing your client</h2>
-
-<p>While you were working, others might have submitted changes
-to the repository and, as explained in <a href="contribute.html">contributing
-to the Go project</a>, it is necessary to synchronize your repository using
-<code>hg sync</code>before sending your change list for review.
-Because <code>hg sync</code> runs <code>hg pull -u</code>,
-you should not run <code>hg sync</code> while <code>mq</code> patches are
-applied. Instead
-pop all your patches before running <code>hg sync</code> and reapply them after
-it has completed.
-</p>
-
-<p>
-When reapplying the patches, you may need to resolve conflicts
-as described in <a href="contribute.html">contributing to the Go project</a>.
-</p>
-
-<h2>Mailing the change for review</h2>
-
-<p>
-You should have all of the <code>mq</code> patches relevant to your
-change applied when you run <code>hg mail</code>.
-
-<h2>Submitting the change after the review</h2>
-
-If you are a committer, you should have all of the <code>mq</code> patches relevant to your
-change applied when you run <code>hg commit</code>.
diff --git a/doc/codewalk/codewalk.js b/doc/codewalk/codewalk.js
index f780bc7..eb4667a 100644
--- a/doc/codewalk/codewalk.js
+++ b/doc/codewalk/codewalk.js
@@ -297,7 +297,7 @@ CodewalkViewer.prototype.updateHeight = function() {
 };
 
 jQuery(document).ready(function() {
-  var viewer = new CodewalkViewer(jQuery());
+  var viewer = new CodewalkViewer(jQuery('#codewalk-main'));
   viewer.selectFirstComment();
   viewer.targetCommentLinksAtBlank();
   viewer.installEventHandlers();
diff --git a/doc/codewalk/markov.xml b/doc/codewalk/markov.xml
index b7b7117..7f12818 100644
--- a/doc/codewalk/markov.xml
+++ b/doc/codewalk/markov.xml
@@ -58,7 +58,7 @@ Prefix               Map key
 	this data.
 </step>
 
-<step title="The NewChain constructor function" src="doc/codewalk/markov.go:/func New/,/}/">
+<step title="The NewChain constructor function" src="doc/codewalk/markov.go:/func New/,/\n}/">
 	The <code>Chain</code> struct has two unexported fields (those that
 	do not begin with an upper case character), and so we write a
 	<code>NewChain</code> constructor function that initializes the
diff --git a/doc/codewalk/pig.go b/doc/codewalk/pig.go
index 10963b4..941daae 100644
--- a/doc/codewalk/pig.go
+++ b/doc/codewalk/pig.go
@@ -23,7 +23,7 @@ type score struct {
 // An action transitions stochastically to a resulting score.
 type action func(current score) (result score, turnIsOver bool)
 
-// roll returns the (result, turnIsOver) outcome of simulating a die roll. 
+// roll returns the (result, turnIsOver) outcome of simulating a die roll.
 // If the roll value is 1, then thisTurn score is abandoned, and the players'
 // roles swap.  Otherwise, the roll value is added to thisTurn.
 func roll(s score) (score, bool) {
diff --git a/doc/contrib.html b/doc/contrib.html
index b4bd47e..a9f12f9 100644
--- a/doc/contrib.html
+++ b/doc/contrib.html
@@ -34,9 +34,6 @@ We encourage all Go users to subscribe to
 <h3 id="release"><a href="/doc/devel/release.html">Release History</a></h3>
 <p>A summary of the changes between Go releases.</p>
 
-<h3 id="weekly"><a href="/doc/devel/weekly.html">Weekly Snapshot History</a></h3>
-<p>A summary of the changes between weekly snapshots of Go.</p>
-
 <h3 id="golang-dev"><a href="http://groups.google.com/group/golang-dev">Developer Mailing List</a></h3>
 <p>The <a href="http://groups.google.com/group/golang-dev">golang-dev</a>
 mailing list is for discussing and reviewing code for the Go project.</p>
@@ -91,12 +88,15 @@ are particularly in need of outside help.
 <p>The <a href="http://groups.google.com/group/golang-nuts">golang-nuts</a> 
 mailing list is for general Go discussion.</p>
 
-<h3 id="projects"><a href="http://godashboard.appspot.com/project">Go Project Dashboard</a></h3>
+<h3 id="projects"><a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Wiki Projects Page</a></h3>
 <p>A list of external Go projects including programs and libraries.</p>
 
 <h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
 <p><b>#go-nuts</b> on <b>irc.freenode.net</b> is the official Go IRC channel.</p>
 
+<h3 id="pluscom"><a href="https://plus.google.com/communities/114112804251407510571">The Go+ community</a></h3>
+<p>The Google+ community for Go enthusiasts.</p>
+
 <h3 id="plus"><a href="https://plus.google.com/101406623878176903605/posts">The Go Programming Language at Google+</a></h3>
 <p>The Go project's Google+ page.</p>
 
diff --git a/doc/contribute.html b/doc/contribute.html
index e1f39ae..72c9364 100644
--- a/doc/contribute.html
+++ b/doc/contribute.html
@@ -7,7 +7,7 @@
 <p>
 This document explains how to contribute changes to the Go project.
 It assumes you have installed Go using the
-<a href="/doc/install">installation instructions</a> and
+<a href="/doc/install/source">installation instructions</a> and
 have <a href="code.html">written and tested your code</a>.
 (Note that the <code>gccgo</code> frontend lives elsewhere;
 see <a href="gccgo_contribute.html">Contributing to gccgo</a>.)
@@ -46,24 +46,13 @@ tree to make sure the changes don't break other packages or programs:
 
 <pre>
 cd $GOROOT/src
-./all.bash
+./all.bash    # On Windows, run all.bat
 </pre>
 
 <p>
-The final line printed by <code>make all</code> should be of the form:
+After running for a while, the command should print "<code>ALL TESTS PASSED</code>".
 </p>
 
-<pre>
-<i>N</i> known bugs; 0 unexpected bugs
-</pre>
-
-<p>
-The value of <i>N</i> varies over time, but the line must
-say “<code>0 unexpected bugs</code>” and must not
-add “<code>test output differs</code>.”
-</p>
-
-
 <h2 id="Code_review">Code review</h2>
 
 <p>
@@ -104,41 +93,44 @@ the code review extension disables the standard <code>hg commit</code>
 command.
 </p>
 
-<p>
-Mercurial power users: if you prefer to use the Mercurial Queues extension, see
-<a href="codereview_with_mq.html">Using Mercurial Queues with Codereview</a>.
-</p>
-
 <h3>Configure the extension</h3>
 
 <p>Edit <code>$GOROOT/.hg/hgrc</code> to add:</p>
 
 <pre>
 [extensions]
-codereview = YOUR_GO_ROOT/lib/codereview/codereview.py
+codereview = $GOROOT/lib/codereview/codereview.py
 
 [ui]
 username = Your Name <you at server.dom>
 </pre>
 
-<p>Replace YOUR_GO_ROOT with the value of <code>$GOROOT</code>.
-The Mercurial configuration file format does not allow environment variable substitution.
+<p>
 The <code>username</code> information will not be used unless
 you are a committer (see below), but Mercurial complains if it is missing.
 </p>
 
+<p>
+After adding the extension, <code>hg help codereview</code>
+will show documentation for its commands. As the codereview extension is only
+enabled for your checkout in <code>$GOROOT</code>, the remainder of this
+document assumes you are inside <code>$GOROOT</code> when issuing commands.
+</p>
+
 <h3>Log in to the code review site.</h3>
 
 <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&continue=http://www.google.com/">sign in at google.com</a>,
-you can use it to sign in to the code review server.
+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="http://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.
 </p>
 
 <pre>
@@ -163,6 +155,19 @@ 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 at golang.org</code>.
 </p>
 
+<h3>Switch to the default 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:
+</p>
+
+<pre>
+$ hg update default
+</pre>
+
 <h3>Make a change</h3>
 
 <p>
@@ -263,6 +268,8 @@ The special sentence “Fixes issue 159.” associates
 the change with issue 159 in the <a href="http://code.google.com/p/go/issues/list">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="http://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control">Google Project Hosting Issue Tracker documentation</a>.)
 </p>
 
 <p>
@@ -277,15 +284,37 @@ which <code>hg change</code> will print, something like:
 CL created: http://codereview.appspot.com/99999
 </pre>
 
+<h3>Adding or removing files from an existing change</h3>
+
 <p>
-If you need to re-edit the change description,
+If you need to re-edit the change description, or change the files included in the CL,
 run <code>hg change 99999</code>.
 </p>
 
 <p>
-You can see a list of your pending changes by running <code>hg pending</code> (<code>hg p</code> for short).
+Alternatively, you can use
 </p>
 
+<pre>
+$ hg file 99999 somefile
+</pre>
+
+<p>
+to add <code>somefile</code> to CL 99999, and
+</p>
+
+<pre>
+$ hg file -d 99999 somefile
+</pre>
+
+<p>
+to remove <code>somefile</code> from the CL.
+</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.
+</p>
 
 <h3>Synchronize your client</h3>
 
@@ -378,6 +407,12 @@ changes, but you may still need to run
 
 <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).
+</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>
 
@@ -399,6 +434,10 @@ $ hg mail -r golang-dev at googlegroups.com --cc math-nuts at swtch.com 99999
 
 <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.
+</p>
 
 <h3>Reviewing code</h3>
 
@@ -412,7 +451,18 @@ to send comments back.
 
 <h3>Revise and upload</h3>
 
-<p>You will probably revise your code in response to the reviewer comments.
+<p>
+You will probably revise your code in response to the reviewer comments. When
+you have done this, you can upload your change to the code review server
+without sending a notification by running <code>hg upload</code> using the change
+list number assigned during <code>hg change</code>
+</p>
+
+<pre>
+$ hg upload 99999
+</pre>
+
+<p>
 When you have revised the code and are ready for another round of review, run
 </p>
 
@@ -433,39 +483,59 @@ The reviewer approves the change by replying with a mail that says
 <code>LGTM</code>: looks good to me.
 </p>
 
-<h3>Submit the change after the review</h3>
+<p>
+You can see a list of your pending changes by running <code>hg pending</code> (<code>hg p</code> for short).
+</p>
+
+<h3>Reviewing code by others</h3>
 
 <p>
-After the code has been <code>LGTM</code>'ed, it is time to submit
-it to the Mercurial repository.
-If you are a committer, you can run:
+You can import a CL proposed by someone else into your local Mercurial client
+by using the <code>hg clpatch</code> command. Running
 </p>
 
 <pre>
-$ hg submit 99999
+$ hg clpatch 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.
+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>
-If your local copy of the repository is out of date,
-<code>hg submit</code>
-will refuse the change:
+To revert a CL you have applied locally, use the <code>hg revert</code>
+command. Running
 </p>
 
 <pre>
-$ hg submit 99999
-local repository out of date; must sync before submit
+$ hg revert @99999
 </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.
+</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>
+
+<p>
+After the code has been <code>LGTM</code>'ed, it is time to submit
+it to the Mercurial repository.
+</p>
+
+<p>
 If you are not a committer, you cannot submit the change directly.
-Instead, a committer, usually the reviewer who said <code>LGTM</code>,
+Instead a committer, usually the reviewer who said <code>LGTM</code>,
 will run:
 </p>
 
@@ -474,19 +544,39 @@ $ hg clpatch 99999
 $ hg submit 99999
 </pre>
 
-<p>The <code>clpatch</code> command imports your change 99999 into
-the committer's local Mercurial client, at which point the committer
-can check or test the code more.
-(Anyone can run <code>clpatch</code> to try a change that
-has been uploaded to the code review server.)
+<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>.
 </p>
 
+<p>
+If you are a committer, you can run:
+</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.
+</p>
 
-<h3 id="copyright">Copyright</h3>
+<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>
+
+<h2 id="copyright">Copyright</h2>
 
 <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.
@@ -497,7 +587,7 @@ and perhaps the <a href="/AUTHORS"><code>AUTHORS</code></a> file.
 
 <p>The <a href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file
 defines who the Go contributors—the people—are;
-the <a href="/AUTHORS"><code>AUTHORS</code></a> file, which defines
+the <a href="/AUTHORS"><code>AUTHORS</code></a> file defines
 who “The Go Authors”—the copyright holders—are.
 The Go developers at Google will update these files when submitting
 your first change.
@@ -525,7 +615,12 @@ This rigmarole needs to be done only for your first submission.
 <p>Code that you contribute should use the standard copyright header:</p>
 
 <pre>
-// Copyright 2012 The Go Authors. All rights reserved.
+// 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.
 </pre>
+
+<p>
+Files in the repository are copyright the year they are added. It is not
+necessary to update the copyright year on files that you change.
+</p>
diff --git a/doc/debugging_with_gdb.html b/doc/debugging_with_gdb.html
index b268391..b893f93 100644
--- a/doc/debugging_with_gdb.html
+++ b/doc/debugging_with_gdb.html
@@ -13,7 +13,7 @@ Besides this overview you might want to consult the
 
 <p>
 When you compile and link your Go programs with the <code>gc</code> toolchain
-on Linux, Mac OS X or FreeBSD, the resulting binaries contain DWARFv3
+on Linux, Mac OS X, FreeBSD or NetBSD, the resulting binaries contain DWARFv3
 debugging information that recent versions (>7.1) of the GDB debugger can
 use to inspect a live process or a core dump.
 </p>
@@ -23,13 +23,20 @@ Pass the <code>'-s'</code> flag to the linker to omit the debug information
 (for example, <code>go build -ldflags "-s" prog.go</code>).
 </p>
 
+<p>
+The code generated by the <code>gc</code> compiler includes inlining of
+function invocations and registerization of variables. These optimizations
+can sometimes make debugging with <code>gdb</code> harder. To disable them
+when debugging, pass the flags <code>-gcflags "-N -l"</code> to the
+<a href="/cmd/go"><code>go</code></a> command used to build the code being
+debugged.
+</p>
 
 <h3 id="Common_Operations">Common Operations</h3>
 
 <ul>
 <li>
-Show file and line number for code 
-, set breakpoints and disassemble:
+Show file and line number for code, set breakpoints and disassemble:
 <pre>(gdb) <b>list</b>
 (gdb) <b>list <i>line</i></b>
 (gdb) <b>list <i>file.go</i>:<i>line</i></b>
@@ -172,7 +179,7 @@ $ <b>gdb regexp.test -d $GOROOT</b>
 If for some reason GDB still can't find that directory or that script, you can load
 it by hand by telling gdb (assuming you have the go sources in
 <code>~/go/</code>):
-<p>
+</p>
 
 <pre>
 (gdb) <b>source ~/go/src/pkg/runtime/runtime-gdb.py</b>
diff --git a/doc/devel/release.html b/doc/devel/release.html
index 9863106..3340d1e 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -3,11 +3,8 @@
 }-->
 
 <p>This page summarizes the changes between official stable releases of Go.
-Between releases we issue less stable
-<a href="http://blog.golang.org/2011/03/go-becomes-more-stable.html">weekly snapshots</a>.
-The <a href="weekly.html">weekly snapshot history</a> contains more detail,
-and the <a href="http://code.google.com/p/go/source/list">Mercurial change log</a>
-has full details.</p>
+The <a href="http://code.google.com/p/go/source/list">Mercurial change log</a>
+has the full details.</p>
 
 <p>To update to a specific release, use:</p>
 
@@ -54,6 +51,10 @@ It also includes many minor code and documentation fixes.
 </p>
 
 <p>
+go1.0.3 (released 2012/09/21) includes minor code and documentation fixes.
+</p>
+
+<p>
 See the <a href="http://code.google.com/p/go/source/list?name=release-branch.go1">go1 release branch history</a> for the complete list of changes.
 </p>
 
diff --git a/doc/devel/weekly.html b/doc/devel/weekly.html
index 46efe41..f8d3ec6 100644
--- a/doc/devel/weekly.html
+++ b/doc/devel/weekly.html
@@ -3,18 +3,9 @@
 }-->
 
 <p>This page summarizes the changes between tagged weekly snapshots of Go.
-For full details, see the <a href="http://code.google.com/p/go/source/list">Mercurial change log</a>.</p>
+Such snapshots are no longer created. This page remains as a historical reference only.</p>
 
-<p>Weekly snapshots occur often and may not be stable.
-If stability of API and code is more important than having the
-latest features, use the <a href="release.html">official releases</a> instead.</p>
-
-<p>To update to a specific snapshot, use:</p>
-
-<pre>
-hg pull
-hg update weekly.<i>YYYY-MM-DD</i>
-</pre>
+<p>For recent information, see the <a href="http://code.google.com/p/go/source/list">Mercurial change log</a> and <a href="http://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 f88e930..3112381 100644
--- a/doc/docs.html
+++ b/doc/docs.html
@@ -45,8 +45,10 @@ learned. You can <a href="http://tour.golang.org/">take the tour online</a> or
 
 <h3 id="code"><a href="code.html">How to write Go code</a></h3>
 <p>
-How to use the <a href="/cmd/go/">go command</a> to fetch, build, and install
-packages, commands, and run tests.
+Also available as a
+<a href="http://www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>, this doc
+explains how to use the <a href="/cmd/go/">go command</a> to fetch, build, and
+install packages, commands, and run tests.
 </p>
 
 <h3 id="effective_go"><a href="effective_go.html">Effective Go</a></h3>
@@ -56,10 +58,13 @@ A must read for any new Go programmer. It augments the tour and
 the language specification, both of which should be read first.
 </p>
 
-<h3 id="appengine"><a href="http://code.google.com/appengine/docs/go/gettingstarted/">Getting Started with Go on App Engine</a></h3>
+<h3 id="ref"><a href="/ref/">Go References</a></h3>
+<p>Language specification, memory model, and detailed documentation for the commands and packages.</p>
+
+<h3 id="appengine"><a href="https://developers.google.com/appengine/docs/go/gettingstarted/">Getting Started with Go on App Engine</a></h3>
 <p>
 How to develop and deploy a simple Go project with
-<a href="http://code.google.com/appengine/">Google App Engine</a>.
+<a href="https://developers.google.com/appengine/">Google App Engine</a>.
 </p>
 
 <h3 id="go_faq"><a href="go_faq.html">Frequently Asked Questions (FAQ)</a></h3>
@@ -127,6 +132,7 @@ Guided tours of Go programs.
 <li><a href="/doc/gdb">Debugging Go Code with GDB</a></li>
 <li><a href="/doc/articles/godoc_documenting_go_code.html">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
 <li><a href="http://blog.golang.org/2011/06/profiling-go-programs.html">Profiling Go Programs</a></li>
+<li><a href="/doc/articles/race_detector.html">Data Race Detector</a> - testing Go programs for race conditions.</li>
 </ul>
 
 <h2 id="talks">Talks</h2>
@@ -139,27 +145,29 @@ before Go 1 and contain some examples that are no longer correct, but they are
 still of value.
 </p>
 
-<h3 id="writing_web_apps"><a href="http://www.youtube.com/watch?v=-i0hat7pdpk">Writing Web Apps in Go</a><font color="red">*</font></h3>
+<h3 id="video_tour_of_go"><a href="http://research.swtch.com/gotour">A Video Tour of Go</a></h3>
 <p>
-A talk by Rob Pike and Andrew Gerrand presented at Google I/O 2011.
-It walks through the construction and deployment of a simple web application
-and unveils the <a href="http://blog.golang.org/2011/05/go-and-google-app-engine.html">Go runtime for App Engine</a>.
-See the <a href="/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf">presentation slides</a>.
+Three things that make Go fast, fun, and productive:
+interfaces, reflection, and concurrency. Builds a toy web crawler to
+demonstrate these.
 </p>
 
-<h3 id="real_world_go"><a href="http://www.youtube.com/watch?v=7QDVRowyUQA">Real World Go</a><font color="red">*</font></h3>
+<h3 id="go_concurrency_patterns"><a href="http://www.youtube.com/watch?v=f6kdp27TYZs">Go Concurrency Patterns</a></h3>
 <p>
-A talk by Andrew Gerrand presented at Google I/O Bootcamp 2011.
-It gives a broad overview of Go's type system and concurrency model
-and provides four examples of Go programs that solve real problems.
-See the <a href="/doc/talks/io2011/Real_World_Go.pdf">presentation slides</a>.
+Concurrency is the key to designing high performance network services. Go's concurrency primitives (goroutines and channels) provide a simple and efficient means of expressing concurrent execution. In this talk we see how tricky concurrency problems can be solved gracefully with simple Go code.
 </p>
 
-<h3 id="integrated_apps"><a href="http://www.youtube.com/watch?v=Mo1YKpIF1PQ">Building Integrated Apps on Google's Cloud Platform</a></h3>
+<h3 id="meet_the_go_team"><a href="http://www.youtube.com/watch?v=sln-gJaURzk">Meet the Go team</a></h3>
 <p>
-A talk by Andrew Gerrand presented at Google Developer Day Japan 2011.
-It discusses the development of a web application that runs on Google
-App Engine and renders images that it stores on Google Cloud Storage.
+A panel discussion with David Symonds, Robert Griesemer, Rob Pike, Ken Thompson, Andrew Gerrand, and Brad Fitzpatrick.
+</p>
+
+<h3 id="writing_web_apps"><a href="http://www.youtube.com/watch?v=-i0hat7pdpk">Writing Web Apps in Go</a><font color="red">*</font></h3>
+<p>
+A talk by Rob Pike and Andrew Gerrand presented at Google I/O 2011.
+It walks through the construction and deployment of a simple web application
+and unveils the <a href="http://blog.golang.org/2011/05/go-and-google-app-engine.html">Go runtime for App Engine</a>.
+See the <a href="http://talks.golang.org/2011/Writing_Web_Apps_in_Go.pdf">presentation slides</a>.
 </p>
 
 <h3 id="go_programming"><a href="http://www.youtube.com/watch?v=jgVhBThJdXc">Go Programming</a><font color="red">*</font></h3>
@@ -170,14 +178,6 @@ examples demonstrating features particular to Go.  These include concurrency,
 embedded types, methods on any type, and program construction using interfaces.
 </p>
 
-<h3 id="practical_go_programming"><a href="http://www.youtube.com/watch?v=2-pPAvqyluI">Practical Go Programming</a><font color="red">*</font></h3>
-<p>
-This talk presents the development of a complete web application in Go.
-It looks at design, storage, concurrency, and scaling issues in detail, using
-the simple example of an URL shortening service.
-See the <a href="http://wh3rd.net/practical-go/">presentation slides</a>.
-</p>
-
 <h4 id="talks_more">More</h4>
 <p>
 See the <a href="http://code.google.com/p/go-wiki/wiki/GoTalks">GoTalks
@@ -201,7 +201,7 @@ documentation.
 <p>The <a href="http://groups.google.com/group/golang-nuts">golang-nuts</a>
 mailing list is for general Go discussion.</p>
 
-<h3 id="projects"><a href="http://godashboard.appspot.com/project">Go Project Dashboard</a></h3>
+<h3 id="projects"><a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Wiki Projects Page</a></h3>
 <p>A list of external Go projects including programs and libraries.</p>
 
 <h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
diff --git a/doc/effective_go.html b/doc/effective_go.html
index 6cacac6..e02694a 100644
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -41,8 +41,14 @@ The <a href="/src/pkg/">Go package sources</a>
 are intended to serve not
 only as the core library but also as examples of how to
 use the language.
+Moreover, many of the packages contain working, self-contained
+executable examples you can run directly from the
+<a href="http://golang.org">golang.org</a> web site, such as
+<a href="http://golang.org/pkg/strings/#example_Map">this one</a> (click
+on the word "Example" to open it up).
 If you have a question about how to approach a problem or how something
-might be implemented, they can provide answers, ideas and
+might be implemented, the documentation, code and examples in the
+library can provide answers, ideas and
 background.
 </p>
 
@@ -108,7 +114,7 @@ All Go code in the standard packages has been formatted with <code>gofmt</code>.
 
 
 <p>
-Some formatting details remain.  Very briefly,
+Some formatting details remain.  Very briefly:
 </p>
 
 <dl>
@@ -123,14 +129,14 @@ Some formatting details remain.  Very briefly,
     </dd>
     <dt>Parentheses</dt>
     <dd>
-    Go needs fewer parentheses: control structures (<code>if</code>,
+    Go needs fewer parentheses than C and Java: control structures (<code>if</code>,
     <code>for</code>, <code>switch</code>) do not have parentheses in
     their syntax.
     Also, the operator precedence hierarchy is shorter and clearer, so
 <pre>
 x<<8 + y<<16
 </pre>
-    means what the spacing implies.
+    means what the spacing implies, unlike in the other languages.
     </dd>
 </dl>
 
@@ -140,8 +146,8 @@ x<<8 + y<<16
 Go provides C-style <code>/* */</code> block comments
 and C++-style <code>//</code> line comments.
 Line comments are the norm;
-block comments appear mostly as package comments and
-are also useful to disable large swaths of code.
+block comments appear mostly as package comments, but
+are useful within an expression or to disable large swaths of code.
 </p>
 
 <p>
@@ -167,10 +173,9 @@ should set up the detailed documentation that follows.
 
 <pre>
 /*
-    Package regexp implements a simple library for
-    regular expressions.
+Package regexp implements a simple library for regular expressions.
 
-    The syntax of the regular expressions accepted is:
+The syntax of the regular expressions accepted is:
 
     regexp:
         concatenation { '|' concatenation }
@@ -206,6 +211,13 @@ takes care of that.
 The comments are uninterpreted plain text, so HTML and other
 annotations such as <code>_this_</code> will reproduce <i>verbatim</i> and should
 not be used.
+One adjustment <code>godoc</code> does do is to display indented
+text in a fixed-width font, suitable for program snippets.
+The package comment for the
+<a href="http://golang.org/pkg/fmt/"><code>fmt</code> package</a> uses this to good effect.
+</p>
+
+<p>
 Depending on the context, <code>godoc</code> might not even
 reformat comments, so make sure they look good straight up:
 use correct spelling, punctuation, and sentence structure,
@@ -233,6 +245,33 @@ func Compile(str string) (regexp *Regexp, err error) {
 </pre>
 
 <p>
+If the name always begins the comment, the output of <code>godoc</code>
+can usefully be run through <code>grep</code>.
+Imagine you couldn't remember the name "Compile" but were looking for
+the parsing function for regular expressions, so you ran
+the command,
+</p>
+
+<pre>
+$ godoc regexp | grep parse
+</pre>
+
+<p>
+If all the doc comments in the package began, "This function...", <code>grep</code>
+wouldn't help you remember the name. But because the package starts each
+doc comment with the name, you'd see something like this,
+which recalls the word you're looking for.
+</p>
+
+<pre>
+$ godoc regexp | grep parse
+    Compile parses a regular expression and returns, if successful, a Regexp
+    parsed. It simplifies safe initialization of global variables holding
+    cannot be parsed. It simplifies safe initialization of global variables
+$
+</pre>
+
+<p>
 Go's declaration syntax allows grouping of declarations.
 A single doc comment can introduce a group of related constants or variables.
 Since the whole declaration is presented, such a comment can often be perfunctory.
@@ -266,7 +305,7 @@ var (
 
 <p>
 Names are as important in Go as in any other language.
-In some cases they even have semantic effect: for instance,
+They even have semantic effect:
 the visibility of a name outside a package is determined by whether its
 first character is upper case.
 It's therefore worth spending a little time talking about naming conventions
@@ -311,11 +350,11 @@ not <code>encoding_base64</code> and not <code>encodingBase64</code>.
 </p>
 
 <p>
-The importer of a package will use the name to refer to its contents
-(the <code>import .</code> notation is intended mostly for tests and other
-unusual situations and should be avoided unless necessary),
+The importer of a package will use the name to refer to its contents.
 so exported names in the package can use that fact
 to avoid stutter.
+(Don't use the <code>import .</code> notation, which can simplify
+tests that must run outside the package they are testing, but should otherwise be avoided.)
 For instance, the buffered reader type in the <code>bufio</code> package is called <code>Reader</code>,
 not <code>BufReader</code>, because users see it as <code>bufio.Reader</code>,
 which is a clear, concise name.
@@ -336,9 +375,7 @@ Another short example is <code>once.Do</code>;
 <code>once.Do(setup)</code> reads well and would not be improved by
 writing <code>once.DoOrWaitUntilDone(setup)</code>.
 Long names don't automatically make things more readable.
-If the name represents something intricate or subtle, it's usually better
-to write a helpful doc comment than to attempt to put all the information
-into the name.
+A helpful doc comment can often be more valuable than an extra long name.
 </p>
 
 <h3 id="Getters">Getters</h3>
@@ -395,8 +432,8 @@ multiword names.
 <h2 id="semicolons">Semicolons</h2>
 
 <p>
-Like C, Go's formal grammar uses semicolons to terminate statements;
-unlike C, those semicolons do not appear in the source.
+Like C, Go's formal grammar uses semicolons to terminate statements,
+but unlike in C, those semicolons do not appear in the source.
 Instead the lexer uses a simple rule to insert semicolons automatically
 as it scans, so the input text is mostly free of them.
 </p>
@@ -432,7 +469,8 @@ statements on a line, should you write code that way.
 </p>
 
 <p>
-One caveat. You should never put the opening brace of a
+One consequence of the semicolon insertion rules
+is that you cannot put the opening brace of a
 control structure (<code>if</code>, <code>for</code>, <code>switch</code>,
 or <code>select</code>) on the next line.  If you do, a semicolon
 will be inserted before the brace, which could cause unwanted
@@ -541,7 +579,7 @@ codeUsing(f, d)
 </pre>
 
 
-<h3 id="redeclaration">Redeclaration</h3>
+<h3 id="redeclaration">Redeclaration and reassignment</h3>
 
 <p>
 An aside: The last example in the previous section demonstrates a detail of how the
@@ -578,7 +616,7 @@ if it has already been declared, provided:
 
 <ul>
 <li>this declaration is in the same scope as the existing declaration of <code>v</code>
-(if <code>v</code> is already declared in an outer scope, the declaration will create a new variable),</li>
+(if <code>v</code> is already declared in an outer scope, the declaration will create a new variable §),</li>
 <li>the corresponding value in the initialization is assignable to <code>v</code>, and</li>
 <li>there is at least one other variable in the declaration that is being declared anew.</li>
 </ul>
@@ -590,6 +628,12 @@ in a long <code>if-else</code> chain.
 You'll see it used often.
 </p>
 
+<p>
+§ It's worth noting here that in Go the scope of function parameters and return values
+is the same as the function body, even though they appear lexically outside the braces
+that enclose the body.
+</p>
+
 <h3 id="for">For</h3>
 
 <p>
@@ -635,7 +679,7 @@ If you only need the first item in the range (the key or index), drop the second
 </p>
 <pre>
 for key := range m {
-    if expired(key) {
+    if key.expired() {
         delete(m, key)
     }
 }
@@ -653,29 +697,30 @@ for _, value := range array {
 
 <p>
 For strings, the <code>range</code> does more work for you, breaking out individual
-Unicode characters by parsing the UTF-8.
+Unicode code points by parsing the UTF-8.
 Erroneous encodings consume one byte and produce the
 replacement rune U+FFFD. The loop
 </p>
 <pre>
-for pos, char := range "日本語" {
-    fmt.Printf("character %c starts at byte position %d\n", char, pos)
+for pos, char := range "日本\x80語" { // \x80 is an illegal UTF-8 encoding
+    fmt.Printf("character %#U starts at byte position %d\n", char, pos)
 }
 </pre>
 <p>
 prints
 </p>
 <pre>
-character 日 starts at byte position 0
-character 本 starts at byte position 3
-character 語 starts at byte position 6
+character U+65E5 '日' starts at byte position 0
+character U+672C '本' starts at byte position 3
+character U+FFFD '�' starts at byte position 6
+character U+8A9E '語' starts at byte position 7
 </pre>
 
 <p>
 Finally, Go has no comma operator and <code>++</code> and <code>--</code>
 are statements not expressions.
 Thus if you want to run multiple variables in a <code>for</code>
-you should use parallel assignment.
+you should use parallel assignment (although that precludes <code>++</code> and <code>--</code>).
 </p>
 <pre>
 // Reverse a
@@ -714,6 +759,7 @@ func unhex(c byte) byte {
 <p>
 There is no automatic fall through, but cases can be presented
 in comma-separated lists.
+</p>
 <pre>
 func shouldEscape(c byte) bool {
     switch c {
@@ -725,10 +771,11 @@ func shouldEscape(c byte) bool {
 </pre>
 
 <p>
-Here's a comparison routine for byte arrays that uses two
+Here's a comparison routine for byte slices that uses two
 <code>switch</code> statements:
+</p>
 <pre>
-// Compare returns an integer comparing the two byte arrays,
+// Compare returns an integer comparing the two byte slices,
 // lexicographically.
 // The result will be 0 if a == b, -1 if a < b, and +1 if a > b
 func Compare(a, b []byte) int {
@@ -756,19 +803,23 @@ variable.  Such a <em>type switch</em> uses the syntax of a type
 assertion with the keyword <code>type</code> inside the parentheses.
 If the switch declares a variable in the expression, the variable will
 have the corresponding type in each clause.
+It's also idiomatic to reuse the name in such cases, in effect declaring
+a new variable with the same name but a different type in each case.
 </p>
 <pre>
-switch t := interfaceValue.(type) {
+var t interface{}
+t = functionOfSomeType()
+switch t := t.(type) {
 default:
-    fmt.Printf("unexpected type %T", t)  // %T prints type
+    fmt.Printf("unexpected type %T", t)       // %T prints whatever type t has
 case bool:
-    fmt.Printf("boolean %t\n", t)
+    fmt.Printf("boolean %t\n", t)             // t has type bool
 case int:
-    fmt.Printf("integer %d\n", t)
+    fmt.Printf("integer %d\n", t)             // t has type int
 case *bool:
-    fmt.Printf("pointer to boolean %t\n", *t)
+    fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
 case *int:
-    fmt.Printf("pointer to integer %d\n", *t)
+    fmt.Printf("pointer to integer %d\n", *t) // t has type *int
 }
 </pre>
 
@@ -808,7 +859,7 @@ This is a common style; see the section on error handling for more examples.
 A similar approach obviates the need to pass a pointer to a return
 value to simulate a reference parameter.
 Here's a simple-minded function to
-grab a number from a position in a byte array, returning the number
+grab a number from a position in a byte slice, returning the number
 and the next position.
 </p>
 
@@ -825,12 +876,12 @@ func nextInt(b []byte, i int) (int, int) {
 </pre>
 
 <p>
-You could use it to scan the numbers in an input array <code>a</code> like this:
+You could use it to scan the numbers in an input slice <code>b</code> like this:
 </p>
 
 <pre>
-    for i := 0; i < len(a); {
-        x, i = nextInt(a, i)
+    for i := 0; i < len(b); {
+        x, i = nextInt(b, i)
         fmt.Println(x)
     }
 </pre>
@@ -1180,6 +1231,7 @@ structure with length 10 and a capacity of 100 pointing at the first
 for more information.)
 In contrast, <code>new([]int)</code> returns a pointer to a newly allocated, zeroed slice
 structure, that is, a pointer to a <code>nil</code> slice value.
+</p>
 
 <p>
 These examples illustrate the difference between <code>new</code> and
@@ -1330,6 +1382,8 @@ func Append(slice, data[]byte) []byte {
 We must return the slice afterwards because, although <code>Append</code>
 can modify the elements of <code>slice</code>, the slice itself (the run-time data
 structure holding the pointer, length, and capacity) is passed by value.
+</p>
+
 <p>
 The idea of appending to a slice is so useful it's captured by the
 <code>append</code> built-in function.  To understand that function's
@@ -1369,8 +1423,8 @@ var timeZone = map[string] int {
 </pre>
 <p>
 Assigning and fetching map values looks syntactically just like
-doing the same for arrays except that the index doesn't need to
-be an integer.
+doing the same for arrays and slices except that the index doesn't
+need to be an integer.
 </p>
 <pre>
 offset := timeZone["EST"]
@@ -1495,7 +1549,7 @@ prints
 If you just want the default conversion, such as decimal for integers, you can use
 the catchall format <code>%v</code> (for “value”); the result is exactly
 what <code>Print</code> and <code>Println</code> would produce.
-Moreover, that format can print <em>any</em> value, even arrays, structs, and
+Moreover, that format can print <em>any</em> value, even arrays, slices, structs, and
 maps.  Here is a print statement for the time zone map defined in the previous section.
 </p>
 <pre>
@@ -1539,12 +1593,13 @@ map[string] int{"CST":-21600, "PST":-28800, "EST":-18000, "UTC":0, "MST":-25200}
 That quoted string format is also available through <code>%q</code> when
 applied to a value of type <code>string</code> or <code>[]byte</code>;
 the alternate format <code>%#q</code> will use backquotes instead if possible.
-Also, <code>%x</code> works on strings and arrays of bytes as well as on integers,
-generating a long hexadecimal string, and with
+Also, <code>%x</code> works on strings, byte arrays and byte slices as well as
+on integers, generating a long hexadecimal string, and with
 a space in the format (<code>% x</code>) it puts spaces between the bytes.
 </p>
 <p>
 Another handy format is <code>%T</code>, which prints the <em>type</em> of a value.
+</p>
 <pre>
 fmt.Printf("%T\n", timeZone)
 </pre>
@@ -1606,6 +1661,7 @@ func Println(v ...interface{}) {
 We write <code>...</code> after <code>v</code> in the nested call to <code>Sprintln</code> to tell the
 compiler to treat <code>v</code> as a list of arguments; otherwise it would just pass
 <code>v</code> as a single slice argument.
+</p>
 <p>
 There's even more to printing than we've covered here.  See the <code>godoc</code> documentation
 for package <code>fmt</code> for the details.
@@ -1738,9 +1794,9 @@ initializer can be a general expression computed at run time.
 </p>
 <pre>
 var (
-    HOME = os.Getenv("HOME")
-    USER = os.Getenv("USER")
-    GOROOT = os.Getenv("GOROOT")
+    home   = os.Getenv("HOME")
+    user   = os.Getenv("USER")
+    goRoot = os.Getenv("GOROOT")
 )
 </pre>
 
@@ -1763,17 +1819,17 @@ correctness of the program state before real execution begins.
 
 <pre>
 func init() {
-    if USER == "" {
+    if user == "" {
         log.Fatal("$USER not set")
     }
-    if HOME == "" {
-        HOME = "/usr/" + USER
+    if home == "" {
+        home = "/home/" + user
     }
-    if GOROOT == "" {
-        GOROOT = HOME + "/go"
+    if goRoot == "" {
+        goRoot = home + "/go"
     }
-    // GOROOT may be overridden by --goroot flag on command line.
-    flag.StringVar(&GOROOT, "goroot", GOROOT, "Go root directory")
+    // goRoot may be overridden by --goroot flag on command line.
+    flag.StringVar(&goRoot, "goroot", goRoot, "Go root directory")
 }
 </pre>
 
@@ -1783,6 +1839,7 @@ func init() {
 <p>
 Methods can be defined for any named type that is not a pointer or an interface;
 the receiver does not have to be a struct.
+</p>
 <p>
 In the discussion of slices above, we wrote an <code>Append</code>
 function.  We can define it as a method on slices instead.  To do
@@ -2012,6 +2069,7 @@ Those methods include the standard <code>Write</code> method, so an
 can be used.
 <code>Request</code> is a struct containing a parsed representation
 of the request from the client.
+</p>
 <p>
 For brevity, let's ignore POSTs and assume HTTP requests are always
 GETs; that simplification does not affect the way the handlers are
@@ -2034,6 +2092,7 @@ func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 (Keeping with our theme, note how <code>Fprintf</code> can print to an
 <code>http.ResponseWriter</code>.)
 For reference, here's how to attach such a server to a node on the URL tree.
+</p>
 <pre>
 import "net/http"
 ...
@@ -2187,6 +2246,7 @@ what a <code>Reader</code> does <em>and</em> what a <code>Writer</code>
 does; it is a union of the embedded interfaces (which must be disjoint
 sets of methods).
 Only interfaces can be embedded within interfaces.
+</p>
 <p>
 The same basic idea applies to structs, but with more far-reaching
 implications.  The <code>bufio</code> package has two struct types,
@@ -2378,10 +2438,11 @@ exits, silently.  (The effect is similar to the Unix shell's
 background.)
 </p>
 <pre>
-go list.Sort()  // run list.Sort concurrently; don't wait for it. 
+go list.Sort()  // run list.Sort concurrently; don't wait for it.
 </pre>
 <p>
 A function literal can be handy in a goroutine invocation.
+</p>
 <pre>
 func Announce(message string, delay time.Duration) {
     go func() {
@@ -2393,6 +2454,7 @@ func Announce(message string, delay time.Duration) {
 <p>
 In Go, function literals are closures: the implementation makes
 sure the variables referred to by the function survive as long as they are active.
+</p>
 <p>
 These examples aren't too practical because the functions have no way of signaling
 completion.  For that, we need channels.
@@ -2425,7 +2487,7 @@ c := make(chan int)  // Allocate a channel.
 // Start the sort in a goroutine; when it completes, signal on the channel.
 go func() {
     list.Sort()
-    c <- 1  // Send a signal; value does not matter. 
+    c <- 1  // Send a signal; value does not matter.
 }()
 doSomethingForAWhile()
 <-c   // Wait for sort to finish; discard sent value.
@@ -2494,6 +2556,7 @@ One of the most important properties of Go is that
 a channel is a first-class value that can be allocated and passed
 around like any other.  A common use of this property is
 to implement safe, parallel demultiplexing.
+</p>
 <p>
 In the example in the previous section, <code>handle</code> was
 an idealized handler for a request but we didn't define the
@@ -2822,7 +2885,7 @@ func init() {
 
 <p>
 When <code>panic</code> is called, including implicitly for run-time
-errors such as indexing an array out of bounds or failing a type
+errors such as indexing a slice out of bounds or failing a type
 assertion, it immediately stops execution of the current function
 and begins unwinding the stack of the goroutine, running any deferred
 functions along the way.  If that unwinding reaches the top of the
@@ -2923,7 +2986,7 @@ that it has the local type <code>Error</code>.
 If it does not, the type assertion will fail, causing a run-time error
 that continues the stack unwinding as though nothing had interrupted
 it.  This check means that if something unexpected happens, such
-as an array index out of bounds, the code will fail even though we
+as an index out of bounds, the code will fail even though we
 are using <code>panic</code> and <code>recover</code> to handle
 user-triggered errors.
 </p>
@@ -2952,6 +3015,155 @@ filter unexpected problems and re-panic with the original error.
 That's left as an exercise for the reader.
 </p>
 
+<h2 id="blank">Blank identifier</h2>
+
+<p>
+Go defines a special identifier <code>_</code>, called the <i>blank identifier</i>.
+The blank identifier can be used in a declaration to avoid
+declaring a name, and it can be used in an assignment to discard a value.
+This definition makes it useful in a variety of contexts.
+</p>
+
+<h3 id="blank_assign">Multiple assignment</h3>
+
+<p>
+If an assignment requires multiple values on the left side,
+but one of the values will not be used by the program,
+using the blank identifier in the assignment avoids the need
+to create a dummy variable.
+We saw one example of this in the discussion of
+<a href="#for">for loops</a> above.
+</p>
+<pre>
+sum := 0
+for _, value := range array {
+    sum += value
+}
+</pre>
+
+<p>
+Another common use is when calling a function that returns
+a value and an error, but only the error is important.
+</p>
+<pre>
+if _, err := os.Stat(path); os.IsNotExist(err) {
+	fmt.Printf("%s does not exist\n", path)
+}
+</pre>
+
+<p>
+A final use that is more common than it should be is to 
+discard the error from a function that is not expected to fail.
+This is usually a mistake: when the function does fail, the code
+will continue on and probably panic dereferencing a nil pointer.
+</p>
+<pre>
+// Always check errors: this program crashes if path does not exist.
+fi, _ := os.Stat(path)
+fmt.Printf("%s is %d bytes\n", path, fi.Size())
+</pre>
+
+<h3 id="blank_unused">Unused imports and variables</h3>
+
+<p>
+Go defines that it is an error to import a package without using it,
+or to declare a variable without using its value.
+Unused imports bloat a program and lengthen compiles unnecessarily;
+a variable that is initialized but not used is at least
+a wasted computation and perhaps indicative of a
+larger bug.
+Of course, both of these situations also arise in programs
+that are under active development, as you test and refine
+your code. 
+</p>
+<p>
+For example, in this program, there are two unused imports
+(<code>fmt</code> and <code>io</code>)
+and an unused variable (<code>greeting</code>).
+</p>
+{{code "/doc/progs/unused1.go" `/package/` `$`}}
+<p>
+Top-level blank declarations referring to the packages
+will silence the unused import errors.
+By convention, these declarations should come immediately after
+the imports, as a reminder to clean things up later.
+Similarly, assigning <code>greeting</code> to a blank identifier
+will silence the unused variable error.
+</p>
+{{code "/doc/progs/unused2.go" `/package/` `$`}}
+
+<h3 id="blank_import">Import for side effect</h3>
+
+<p>
+An unused import like <code>fmt</code> or <code>io</code> in the last section
+should eventually be used or removed:
+blank assignments identify code as a work in progress.
+But sometimes it is useful to import a package only for its
+side effects, without any explicit use.
+For example, during its <code>init</code> function,
+the <code><a href="/pkg/net/http/pprof/">net/http/pprof</a></code>
+package registers HTTP handlers that provide useful
+debugging information. It has an exported API too, but
+most clients need only the handler registration.
+In this situation, it is conventional to rename the package
+to the blank identifier:
+</p>
+<pre>
+import _ "net/http/pprof"
+</pre>
+<p>
+This form of import makes clear that the package is being
+imported for its side effects, because there is no other possible
+use of the package: in this file, it doesn't have a name.
+</p>
+
+<h3 id="blank_implements">Interface checks</h3>
+
+<p>
+As we saw in the discussion of <a href="#interfaces_and_types">interfaces</a> above,
+Go does not require a type to declare explicitly that it implements an interface.
+It implements the interface by simply implementing the required methods.
+This makes Go programs more lightweight and flexible, and it can avoid
+unnecessary dependencies between packages. 
+Most interface conversions are static, visible to the compiler,
+and therefore checked at compile time.
+For example, passing an <code>*os.File</code> to a function
+expecting an <code>io.Reader</code> will not compile unless
+<code>*os.File</code> implements the <code>io.Reader</code> interface.
+</p>
+<p>
+However, some types that are used only to satisfy dynamic interface checks.
+For example, the <code><a href="/pkg/encoding/json/">encoding/json</a></code>
+package defines a <code><a href="/pkg/encoding/json/#Marshaler">Marshaler</a></code>
+interface. If the JSON encoder encounters a type implementing that interface,
+the encoder will let the type convert itself to JSON instead of using the standard
+conversion.
+This check is done only at runtime, with code like:
+</p>
+<pre>
+m, ok := val.(json.Marshaler)
+</pre>
+<p>
+If a type—for example,
+<code><a href="/pkg/encoding/json/#RawMessage">json.RawMessage</a></code>—intends
+to customize its JSON representation, it should implement
+<code>json.Marshaler</code>, but there are no static conversions that would
+cause the compiler to verify this automatically.
+A declaration can be used to add such a check:
+</p>
+<pre>
+var _ json.Marshaler = (*RawMessage)(nil)
+</pre>
+<p>
+As part of type-checking this static assignment of a
+<code>*RawMessage</code> to a <code>Marshaler</code>,
+the Go compiler will require that <code>*RawMessage</code> implements <code>Marshaler</code>.
+Using the blank identifier here indicates that
+the declaration exists only for the type checking,
+not to create a variable.
+Conventionally, such declarations are used only when there are
+no static conversions already present in the code.
+</p>
 
 <h2 id="web_server">A web server</h2>
 
@@ -2973,7 +3185,7 @@ for instance, a URL, saving you typing the URL into the phone's tiny keyboard.
 Here's the complete program.
 An explanation follows.
 </p>
-{{code "/doc/progs/eff_qr.go"}}
+{{code "/doc/progs/eff_qr.go" `/package/` `$`}}
 <p>
 The pieces up to <code>main</code> should be easy to follow.
 The one flag sets a default HTTP port for our server.  The template
@@ -2992,11 +3204,11 @@ server; it blocks while the server runs.
 executes the template on the data in the form value named <code>s</code>.
 </p>
 <p>
-The template package is powerful;
+The template package <code>html/template</code> is powerful;
 this program just touches on its capabilities.
-In essence, it rewrites a piece of text on the fly by substituting elements derived
+In essence, it rewrites a piece of HTML text on the fly by substituting elements derived
 from data items passed to <code>templ.Execute</code>, in this case the
-form value.  
+form value.
 Within the template text (<code>templateStr</code>),
 double-brace-delimited pieces denote template actions.
 The piece from <code>{{html "{{if .}}"}}</code>
@@ -3005,13 +3217,14 @@ is non-empty.
 That is, when the string is empty, this piece of the template is suppressed.
 </p>
 <p>
-The snippet <code>{{html "{{urlquery .}}"}}</code> says to process the data with the function
-<code>urlquery</code>, which sanitizes the query string
-for safe display on the web page.
+The two snippets <code>{{html "{{.}}"}}</code> say to show the data presented to
+the template—the query string—on the web page.
+The HTML template package automatically provides appropriate escaping so the
+text is safe to display.
 </p>
 <p>
 The rest of the template string is just the HTML to show when the page loads.
-If this is too quick an explanation, see the <a href="/pkg/text/template/">documentation</a>
+If this is too quick an explanation, see the <a href="/pkg/html/template/">documentation</a>
 for the template package for a more thorough discussion.
 </p>
 <p>
@@ -3025,7 +3238,7 @@ TODO
 <pre>
 verifying implementation
 type Color uint32
-    
+
 // Check that Color implements image.Color and image.Image
 var _ image.Color = Black
 var _ image.Image = Black
diff --git a/doc/gccgo_contribute.html b/doc/gccgo_contribute.html
index 8ca13e4..4d268e0 100644
--- a/doc/gccgo_contribute.html
+++ b/doc/gccgo_contribute.html
@@ -100,7 +100,9 @@ or <code>gcc/testsuite/go.dg</code> directories in the GCC repository.
 
 <p>
 Changes to the Go frontend should follow the same process as for the
-main Go repository, only for the <code>gofrontend</code> project
-rather than the <code>go</code> project.  Those changes will then be
-merged into the GCC sources.
+main Go repository, only for the <code>gofrontend</code> project and
+the<code>gofrontend-dev at googlegroups.com</code> mailing list 
+rather than the <code>go</code> project and the
+<code>golang-dev at googlegroups.com</code> mailing list.  Those changes
+will then be merged into the GCC sources.
 </p>
diff --git a/doc/go1.1.html b/doc/go1.1.html
new file mode 100644
index 0000000..ae0a099
--- /dev/null
+++ b/doc/go1.1.html
@@ -0,0 +1,207 @@
+<!--{
+	"Title": "Go 1.1 Release Notes",
+	"Path":  "/doc/go1.1",
+	"Template": true
+}-->
+
+<h2 id="introduction">Introduction to Go 1.1</h2>
+
+TODO
+ - overview
+ - link back to Go 1 and also Go 1 Compatibility docs.
+
+<h2 id="language">Changes to the language</h2>
+
+TODO
+
+<h3 id="divzero">Integer division by zero</h3>
+
+<p>
+In Go 1, integer division by a constant zero produced a runtime panic:
+</p>
+
+<pre>
+func f(x int) int {
+	return x/0
+}
+</pre>
+
+<p>
+In Go 1.1, an integer division by constant zero is not a legal program, so it is a compile-time error.
+</p>
+
+
+<h2 id="impl">Changes to the implementations and tools</h2>
+
+TODO: more
+
+<h3 id="gc-flag">Command-line flag parsing</h3>
+
+<p>
+In the gc toolchain, the compilers and linkers now use the
+same command-line flag parsing rules as the Go flag package, a departure
+from the traditional Unix flag parsing. This may affect scripts that invoke
+the tool directly.
+For example,
+<code>go tool 6c -Fw -Dfoo</code> must now be written
+<code>go tool 6c -F -w -D foo</code>. 
+</p>
+
+<h3 id="int">Size of int on 64-bit platforms</h3>
+
+<p>
+The language allows the implementation to choose whether the <code>int</code> type and <code>uint</code> types are 32 or 64 bits. Previous Go implementations made <code>int</code> and <code>uint</code> 32 bits on all systems. Both the gc and gccgo implementations (TODO: check that gccgo does) <a href="http://golang.org/issue/2188">now make <code>int</code> and <code>uint</code> 64 bits on 64-bit platforms such as AMD64/x86-64</a>.
+Among other things, this enables the allocation of slices with
+more than 2 billion elements on 64-bit platforms.
+</p>
+
+<p>
+<em>Updating</em>:
+Most programs will be unaffected by this change.
+Because Go does not allow implicit conversions between distinct
+<a href="/ref/spec#Numeric_types">numeric types</a>,
+no programs will stop compiling due to this change.
+However, programs that contain implicit assumptions
+that <code>int</code> is only 32 bits may change behavior.
+For example, this code prints a positive number on 64-bit systems and
+a negative one on 32-bit systems:
+
+<pre>
+x := ^uint32(0) // x is 0xffffffff
+i := int(x)     // i is -1 on 32-bit systems, 0xffffffff on 64-bit
+fmt.Println(i)
+</pre>
+
+<p>Portable code intending 32-bit sign extension (yielding -1 on all systems)
+would instead say:
+</p>
+
+<pre>
+i := int(int32(x))
+</pre>
+
+<h3 id="asm">Assembler</h3>
+
+<p>
+Due to the <a href="#int">int</a> and TODO: OTHER changes,
+the placement of function arguments on the stack has changed.
+Functions written in assembly will need to be revised at least
+to adjust frame pointer offsets.
+</p>
+
+<h3 id="gotool">Changes to the go tool</h3>
+
+<p>The <code>go</code> tool has acquired several improvements which are intended to improve the experience for new Go users.</p>
+
+<p>Firstly, when compiling, testing, or running Go code, the <code>go</code> tool will now give more detailed errors messages, including a list of paths searched, when a package cannot be located.
+</p>
+
+<pre>
+$ go build foo/quxx
+can't load package: package foo/quxx: cannot find package "foo/quxx" in any of:
+        /home/User/go/src/pkg/foo/quxx (from $GOROOT)
+        /home/User/src/foo/quxx (from $GOPATH) 
+</pre>
+
+<p>
+Secondly, the <code>go get</code> command no longer allows <code>$GOROOT</code> as the default destination when downloading package source. To use <code>go get</code> command, a valid <code>$GOPATH</code> is now required.
+</p>
+
+<pre>
+$ GOPATH= go get code.google.com/p/foo/quxx
+package code.google.com/p/foo/quxx: cannot download, $GOPATH not set. For more details see: go help gopath 
+</pre>
+
+<p>Finally, as a result of the previous change, the <code>go get</code> command will also fail when <code>$GOPATH</code> and <code>$GOROOT</code> are set to the same value. 
+</p>
+
+<pre>
+$ GOPATH=$GOROOT go get code.google.com/p/foo/quxx
+warning: GOPATH set to GOROOT (/home/User/go) has no effect
+package code.google.com/p/foo/quxx: cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath
+</pre>
+
+<h3 id="gofix">Changes to go fix</h3>
+
+<p>
+The <code>go fix</code> command no longer applies fixes to update code from
+before Go 1 to use Go 1 APIs. To update pre-Go 1 code to Go 1.1, use a Go 1.0 toolchain
+to convert the code to Go 1.0 first.
+</p>
+
+<h2 id="library">Changes to the standard library</h2>
+
+<h3 id="debug_elf">debug/elf</h3>
+<p>
+Previous versions of the debug/elf package intentionally skipped over the first
+symbol in the ELF symbol table, since it is always an empty symbol. This symbol
+is no longer skipped since indexes into the symbol table returned by debug/elf,
+will be different to indexes into the original ELF symbol table. Any code that
+calls the debug/elf functions Symbols or ImportedSymbols may need to be
+adjusted to account for the additional symbol and the change in symbol offsets.
+</p>
+
+<h3 id="html_template">html/template</h3>
+
+<p>
+Templates using the undocumented and only partially implemented
+"noescape" feature will break: that feature was removed.
+</p>
+
+<h3 id="net">net</h3>
+
+<p>
+The protocol-specific resolvers were formerly
+lax about the network name passed in. For example, although the documentation was clear
+that the only valid networks for <code>ResolveTCPAddr</code> are <code>"tcp"</code>,
+<code>"tcp4"</code>, and <code>"tcp6"</code>, the Go 1.0 implementation silently accepted
+any string. The Go 1.1 implementation returns an error if the network is not one of those strings.
+The same is true of the other protocol-specific resolvers <code>ResolveIPAddr</code>, <code>ResolveUDPAddr</code>, and
+<code>ResolveUnixAddr</code>.
+</p>
+
+<p>
+The previous <code>ListenUnixgram</code> returned <code>UDPConn</code> as
+arepresentation of the connection endpoint. The Go 1.1 implementation
+returns <code>UnixConn</code> to allow reading and writing
+with <code>ReadFrom</code> and <code>WriteTo</code> methods on
+the <code>UnixConn</code>.
+</p>
+
+<h3 id="time">time</h3>
+<p>
+On FreeBSD, Linux, NetBSD, OS X and OpenBSD, previous versions of the time package
+returned times with microsecond precision. The Go 1.1 implementation of time on these
+systems now returns times with nanosecond precision. Code may exist that expects to be
+able to store such a time in an external format with only microsecond precision,
+read it back, and recover exactly the same time instant.
+In Go 1.1 the same time will not be recovered, since the external storage
+will have discarded nanoseconds.
+To address this case, there are two new methods of time.Time, Round and Truncate,
+that can be used to remove precision from a time before passing it to
+external storage.
+</p>
+
+<h3 id="exp_old">Exp and old subtrees moved to go.exp subrepo</h3>
+
+<p>
+To make it easier for binary distributions to access them if desired, the <code>exp</code>
+and <code>old</code> source subtrees, which are not included in binary distributions,
+have been moved to the new <code>go.exp</code> subrepository at
+<code>code.google.com/p/go.exp</code>. To access the <code>ssa</code> package,
+for example, run
+</p>
+
+<pre>
+$ go get code.google.com/p/go.exp/ssa
+</pre>
+
+<p>
+and then in Go source,
+</p>
+
+<pre>
+import "code.google.com/p/go.exp/ssa"
+</pre>
+
+<h3 id="TODO">TODO</h3>
diff --git a/doc/go1.html b/doc/go1.html
index e1afe47..491fd7b 100644
--- a/doc/go1.html
+++ b/doc/go1.html
@@ -618,8 +618,6 @@ The packages in their new locations are:
 
 <ul>
 <li><code>old/netchan</code></li>
-<li><code>old/regexp</code></li>
-<li><code>old/template</code></li>
 </ul>
 
 <p>
@@ -639,6 +637,8 @@ Go 1 deletes several packages outright:
 <li><code>container/vector</code></li>
 <li><code>exp/datafmt</code></li>
 <li><code>go/typechecker</code></li>
+<li><code>old/regexp</code></li>
+<li><code>old/template</code></li>
 <li><code>try</code></li>
 </ul>
 
@@ -1676,7 +1676,7 @@ instead of a <code>Visitor</code> interface value.
 The <code>WalkFunc</code> function will be called even for files or directories that could not be opened;
 in such cases the error argument will describe the failure.
 If a directory's contents are to be skipped,
-the function should return the value <a href="/pkg/path/filepath/#variables"><code>filepath.SkipDir</code></a>
+the function should return the value <a href="/pkg/path/filepath/#pkg-variables"><code>filepath.SkipDir</code></a>
 </p>
 
 {{code "/doc/progs/go1.go" `/STARTWALK/` `/ENDWALK/`}}
@@ -1865,7 +1865,7 @@ made easier with the new structure of the packages.
 The imports will be updated by fix tool.
 Single-template uses will be otherwise be largely unaffected.
 Code that uses multiple templates in concert will need to be updated by hand.
-The <a href="/pkg/text/template/#examples">examples</a> in
+The <a href="/pkg/text/template/#pkg-examples">examples</a> in
 the documentation for <code>text/template</code> can provide guidance.
 </p>
 
diff --git a/doc/go_faq.html b/doc/go_faq.html
index b5b7cc6..5c68aa7 100644
--- a/doc/go_faq.html
+++ b/doc/go_faq.html
@@ -1,5 +1,6 @@
 <!--{
-	"Title": "FAQ"
+	"Title": "FAQ",
+	"Path": "/doc/faq"
 }-->
 
 <h2 id="Origins">Origins</h2>
@@ -54,6 +55,38 @@ By its design, Go proposes an approach for the construction of system
 software on multicore machines.
 </ul>
 
+<h3 id="What_is_the_status_of_the_project">
+What is the status of the project?</h3>
+
+<p>
+Go became a public open source project on November 10, 2009.
+After a couple of years of very active design and development, stability was called for and
+Go 1 was <a href="http://blog.golang.org/2012/03/go-version-1-is-released.html">released</a>
+on March 28, 2012.
+Go 1, which includes a <a href="/ref/spec">language specification</a>,
+<a href="/pkg/">standard libraries</a>,
+and <a href="/cmd/go/">custom tools</a>,
+provides a stable foundation for creating reliable products, projects, and publications.
+</p>
+
+<p>
+With that stability established, we are using Go to develop programs, products, and tools rather than
+actively changing the language and libraries.
+In fact, the purpose of Go 1 is to provide <a href="/doc/go1compat.html">long-term stability</a>.
+Backwards-incompatible changes will not be made to any Go 1 point release.
+We want to use what we have to learn how a future version of Go might look, rather than to play with
+the language underfoot.
+</p>
+
+<p>
+Of course, development will continue on Go itself, but the focus will be on performance, reliability,
+portability and the addition of new functionality such as improved support for internationalization.
+</p>
+
+<p>
+There may well be a Go 2 one day, but not for a few years and it will be influenced by what we learn using Go 1 as it is today.
+</p>
+
 <h3 id="What_is_the_origin_of_the_name">
 What is the origin of the name?</h3>
 
@@ -175,12 +208,12 @@ easier to understand what happens when things combine.
 <h3 id="Is_Google_using_go_internally"> Is Google using Go internally?</h3>
 
 <p>
-Yes. There are now several Go programs deployed in 
+Yes. There are now several Go programs deployed in
 production inside Google.  A public example is the server behind
 <a href="http://golang.org">http://golang.org</a>.
 It's just the <a href="/cmd/godoc"><code>godoc</code></a>
 document server running in a production configuration on
-<a href="http://code.google.com/appengine/">Google App Engine</a>.
+<a href="https://developers.google.com/appengine/">Google App Engine</a>.
 </p>
 
 <h3 id="Do_Go_programs_link_with_Cpp_programs">
@@ -191,14 +224,14 @@ There are two Go compiler implementations, <code>gc</code>
 (the <code>6g</code> program and friends) and <code>gccgo</code>.
 <code>Gc</code> uses a different calling convention and linker and can
 therefore only be linked with C programs using the same convention.
-There is such a C compiler but no C++ compiler. 
-<code>Gccgo</code> is a GCC front-end that can, with care, be linked with 
-GCC-compiled C or C++ programs. 
+There is such a C compiler but no C++ compiler.
+<code>Gccgo</code> is a GCC front-end that can, with care, be linked with
+GCC-compiled C or C++ programs.
 </p>
 
 <p>
-The <a href="/cmd/cgo/">cgo</a> program provides the mechanism for a 
-“foreign function interface” to allow safe calling of 
+The <a href="/cmd/cgo/">cgo</a> program provides the mechanism for a
+“foreign function interface” to allow safe calling of
 C libraries from Go code. SWIG extends this capability to C++ libraries.
 </p>
 
@@ -509,7 +542,7 @@ Why doesn't Go have "implements" declarations?</h3>
 <p>
 A Go type satisfies an interface by implementing the methods of that interface,
 nothing more.  This property allows interfaces to be defined and used without
-having to modify existing code.  It enables a kind of "duck typing" that
+having to modify existing code.  It enables a kind of structural typing that
 promotes separation of concerns and improves code re-use, and makes it easier
 to build on patterns that emerge as the code develops.
 The semantics of interfaces is one of the main reasons for Go's nimble,
@@ -564,7 +597,7 @@ func (b Bar) Foo() {}
 </pre>
 
 <p>
-Most code doesn't make use of such constraints, since they limit the utility of 
+Most code doesn't make use of such constraints, since they limit the utility of
 the interface idea. Sometimes, though, they're necessary to resolve ambiguities
 among similar interfaces.
 </p>
@@ -890,6 +923,32 @@ 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="http://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="http://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>
+
 <h2 id="Pointers">Pointers and Allocation</h2>
 
 <h3 id="pass_by_value">
@@ -912,7 +971,7 @@ slice value doesn't copy the data it points to.  Copying an interface value
 makes a copy of the thing stored in the interface value.  If the interface
 value holds a struct, copying the interface value makes a copy of the
 struct.  If the interface value holds a pointer, copying the interface value
-makes a copy of the pointer, but again not the data it points to. 
+makes a copy of the pointer, but again not the data it points to.
 </p>
 
 <h3 id="methods_on_values_or_pointers">
@@ -994,9 +1053,11 @@ Why is <code>int</code> 32 bits on 64 bit machines?</h3>
 <p>
 The sizes of <code>int</code> and <code>uint</code> are implementation-specific
 but the same as each other on a given platform.
-The 64 bit Go compilers (both gc and gccgo) use a 32 bit representation for
-<code>int</code>.  Code that relies on a particular
+For portability, code that relies on a particular
 size of value should use an explicitly sized type, like <code>int64</code>.
+Prior to Go 1.1, the 64-bit Go compilers (both gc and gccgo) used
+a 32-bit representation for <code>int</code>. As of Go 1.1 they use
+a 64-bit representation.
 On the other hand, floating-point scalars and complex
 numbers are always sized: <code>float32</code>, <code>complex64</code>,
 etc., because programmers should be aware of precision when using
@@ -1038,6 +1099,22 @@ analysis</em> recognizes some cases when such variables will not
 live past the return from the function and can reside on the stack.
 </p>
 
+<h3 id="Why_does_my_Go_process_use_so_much_virtual_memory">
+Why does my Go process use so much virtual memory?</h3>
+
+<p>
+The Go memory allocator reserves a large region of virtual memory as an arena
+for allocations. This virtual memory is local to the specific Go process; the
+reservation does not deprive other processes of memory.
+</p>
+
+<p>
+To find the amount of actual memory allocated to a Go process, use the Unix
+<code>top</code> command and consult the <code>RES</code> (Linux) or
+<code>RSIZE</code> (Mac OS X) columns.
+<!-- TODO(adg): find out how this works on Windows -->
+</p>
+
 <h2 id="Concurrency">Concurrency</h2>
 
 <h3 id="What_operations_are_atomic_What_about_mutexes">
@@ -1071,7 +1148,7 @@ Why doesn't my multi-goroutine program use multiple CPUs?</h3>
 You must set the <code>GOMAXPROCS</code> shell environment variable
 or use the similarly-named <a href="/pkg/runtime/#GOMAXPROCS"><code>function</code></a>
 of the runtime package to allow the
-run-time support to utilize more than one OS thread. 
+run-time support to utilize more than one OS thread.
 </p>
 
 <p>
@@ -1084,7 +1161,7 @@ Why does using <code>GOMAXPROCS</code> > 1 sometimes make my program
 slower?</h3>
 
 <p>
-It depends on the nature of your program. 
+It depends on the nature of your program.
 Problems that are intrinsically sequential cannot be sped up by adding
 more goroutines.
 Concurrency only becomes parallelism when the problem is
@@ -1173,23 +1250,26 @@ func main() {
 
     // wait for all goroutines to complete before exiting
     for _ = range values {
-        <-done 
+        <-done
     }
 }
 </pre>
 
 <p>
-One might mistakenly expect to see <code>a, b, c</code> as the output. 
-What you'll probably see instead is <code>c, c, c</code>.  This is because 
+One might mistakenly expect to see <code>a, b, c</code> as the output.
+What you'll probably see instead is <code>c, c, c</code>.  This is because
 each iteration of the loop uses the same instance of the variable <code>v</code>, so
-each closure shares that single variable. When the closure runs, it prints the 
+each closure shares that single variable. When the closure runs, it prints the
 value of <code>v</code> at the time <code>fmt.Println</code> is executed,
-but <code>v</code> may have been modified since the goroutine was launched. 
+but <code>v</code> may have been modified since the goroutine was launched.
+To help detect this and other problems before they happen, run
+<a href="http://golang.org/cmd/go/#hdr-Run_go_tool_vet_on_packages"><code>go vet</code></a>.
 </p>
 
 <p>
-To bind the value of <code>v</code> to each closure as they are launched, one
-could modify the inner loop to read:
+To bind the current value of <code>v</code> to each closure as it is launched, one
+must modify the inner loop to create a new variable each iteration.
+One way is to pass the variable as an argument to the closure:
 </p>
 
 <pre>
@@ -1202,11 +1282,26 @@ could modify the inner loop to read:
 </pre>
 
 <p>
-In this example, the value of <code>v</code> is passed as an argument to the 
+In this example, the value of <code>v</code> is passed as an argument to the
 anonymous function. That value is then accessible inside the function as
 the variable <code>u</code>.
 </p>
 
+<p>
+Even easier is just to create a new variable, using a declaration style that may
+seem odd but works fine in Go:
+</p>
+
+<pre>
+    for _, v := range values {
+        <b>v := v</b> // create a new 'v'.
+        go func() {
+            fmt.Println(<b>v</b>)
+            done <- true
+        }()
+    }
+</pre>
+
 <h2 id="Control_flow">Control flow</h2>
 
 <h3 id="Does_Go_have_a_ternary_form">
@@ -1264,7 +1359,7 @@ builds a test binary, and runs it.
 
 <p>See the <a href="/doc/code.html">How to Write Go Code</a> document,
 the <a href="/pkg/testing/"><code>testing</code></a> package
-and the <a href="/cmd/go/#Test_packages"><code>go test</code></a> subcommand for more details.
+and the <a href="/cmd/go/#hdr-Test_packages"><code>go test</code></a> subcommand for more details.
 </p>
 
 <h3 id="testing_framework">
@@ -1383,7 +1478,7 @@ For these reasons, Go allows neither.
 <p>
 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.  
+program will compile.
 </p>
 
 <p>
@@ -1430,13 +1525,13 @@ Why does Go perform badly on benchmark X?</h3>
 
 <p>
 One of Go's design goals is to approach the performance of C for comparable
-programs, yet on some benchmarks it does quite poorly, including several 
-in <a href="/test/bench/shootout/">test/bench/shootout</a>. The slowest depend on libraries 
-for which versions of comparable performance are not available in Go. 
+programs, yet on some benchmarks it does quite poorly, including several
+in <a href="/test/bench/shootout/">test/bench/shootout</a>. The slowest depend on libraries
+for which versions of comparable performance are not available in Go.
 For instance, <a href="/test/bench/shootout/pidigits.go">pidigits.go</a>
 depends on a multi-precision math package, and the C
 versions, unlike Go's, use <a href="http://gmplib.org/">GMP</a> (which is
-written in optimized assembler). 
+written in optimized assembler).
 Benchmarks that depend on regular expressions
 (<a href="/test/bench/shootout/regex-dna.go">regex-dna.go</a>, for instance) are
 essentially comparing Go's native <a href="/pkg/regexp">regexp package</a> to
@@ -1455,7 +1550,7 @@ indicate.
 <p>
 Still, there is room for improvement. The compilers are good but could be
 better, many libraries need major performance work, and the garbage collector
-isn't fast enough yet. (Even if it were, taking care not to generate unnecessary 
+isn't fast enough yet. (Even if it were, taking care not to generate unnecessary
 garbage can have a huge effect.)
 </p>
 
diff --git a/doc/go_mem.html b/doc/go_mem.html
index ece2306..0b73e43 100644
--- a/doc/go_mem.html
+++ b/doc/go_mem.html
@@ -270,8 +270,8 @@ before the <code>print</code>.
 <p>
 If the channel were buffered (e.g., <code>c = make(chan int, 1)</code>)
 then the program would not be guaranteed to print
-<code>"hello, world"</code>.  (It might print the empty string;
-it cannot print <code>"goodbye, universe"</code>, nor can it crash.)
+<code>"hello, world"</code>.  (It might print the empty string,
+crash, or do something else.)
 </p>
 
 <h3>Locks</h3>
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 90acc17..0cb9f54 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
 <!--{
 	"Title": "The Go Programming Language Specification",
-	"Subtitle": "Version of June 4, 2012",
+	"Subtitle": "Version of March 1, 2013",
 	"Path": "/ref/spec"
 }-->
 
@@ -15,7 +15,6 @@ TODO
 [ ] need explicit language about the result type of operations
 [ ] should probably write something about evaluation order of statements even
 	though obvious
-[ ] review language on implicit dereferencing
 -->
 
 
@@ -89,7 +88,8 @@ Source code is Unicode text encoded in
 canonicalized, so a single accented code point is distinct from the
 same character constructed from combining an accent and a letter;
 those are treated as two code points.  For simplicity, this document
-will use the term <i>character</i> to refer to a Unicode code point.
+will use the unqualified term <i>character</i> to refer to a Unicode code point
+in the source text.
 </p>
 <p>
 Each code point is distinct; for instance, upper and lower case letters
@@ -99,6 +99,11 @@ are different characters.
 Implementation restriction: For compatibility with other tools, a
 compiler may disallow the NUL character (U+0000) in the source text.
 </p>
+<p>
+Implementation restriction: For compatibility with other tools, a
+compiler may ignore a UTF-8-encoded byte order mark
+(U+FEFF) if it is the first Unicode code point in the source text.
+</p>
 
 <h3 id="Characters">Characters</h3>
 
@@ -113,7 +118,7 @@ unicode_digit  = /* a Unicode code point classified as "Decimal Digit" */ .
 </pre>
 
 <p>
-In <a href="http://www.unicode.org/versions/Unicode6.0.0/">The Unicode Standard 6.0</a>,
+In <a href="http://www.unicode.org/versions/Unicode6.2.0/">The Unicode Standard 6.2</a>,
 Section 4.5 "General Category"
 defines a set of character categories.  Go treats
 those characters in category Lu, Ll, Lt, Lm, or Lo as Unicode letters,
@@ -198,7 +203,7 @@ token is
 	    <a href="#Integer_literals">integer</a>,
 	    <a href="#Floating-point_literals">floating-point</a>,
 	    <a href="#Imaginary_literals">imaginary</a>,
-	    <a href="#Character_literals">character</a>, or
+	    <a href="#Rune_literals">rune</a>, or
 	    <a href="#String_literals">string</a> literal
 	</li>
 
@@ -360,13 +365,15 @@ imaginary_lit = (decimals | float_lit) "i" .
 </pre>
 
 
-<h3 id="Character_literals">Character literals</h3>
+<h3 id="Rune_literals">Rune literals</h3>
 
 <p>
-A character literal represents a <a href="#Constants">character constant</a>,
-typically a Unicode code point, as one or more characters enclosed in single
-quotes.  Within the quotes, any character may appear except single
-quote and newline. A single quoted character represents itself,
+A rune literal represents a <a href="#Constants">rune constant</a>,
+an integer value identifying a Unicode code point.
+A rune literal is expressed as one or more characters enclosed in single quotes.
+Within the quotes, any character may appear except single
+quote and newline. A single quoted character represents the Unicode value
+of the character itself,
 while multi-character sequences beginning with a backslash encode
 values in various formats.
 </p>
@@ -380,8 +387,8 @@ a literal <code>a</code>, Unicode U+0061, value <code>0x61</code>, while
 a literal <code>a</code>-dieresis, U+00E4, value <code>0xe4</code>.
 </p>
 <p>
-Several backslash escapes allow arbitrary values to be represented
-as ASCII text.  There are four ways to represent the integer value
+Several backslash escapes allow arbitrary values to be encoded as
+ASCII text.  There are four ways to represent the integer value
 as a numeric constant: <code>\x</code> followed by exactly two hexadecimal
 digits; <code>\u</code> followed by exactly four hexadecimal digits;
 <code>\U</code> followed by exactly eight hexadecimal digits, and a
@@ -409,14 +416,14 @@ After a backslash, certain single-character escapes represent special values:
 \t   U+0009 horizontal tab
 \v   U+000b vertical tab
 \\   U+005c backslash
-\'   U+0027 single quote  (valid escape only within character literals)
+\'   U+0027 single quote  (valid escape only within rune literals)
 \"   U+0022 double quote  (valid escape only within string literals)
 </pre>
 <p>
-All other sequences starting with a backslash are illegal inside character literals.
+All other sequences starting with a backslash are illegal inside rune literals.
 </p>
 <pre class="ebnf">
-char_lit         = "'" ( unicode_value | byte_value ) "'" .
+rune_lit         = "'" ( unicode_value | byte_value ) "'" .
 unicode_value    = unicode_char | little_u_value | big_u_value | escaped_char .
 byte_value       = octal_byte_value | hex_byte_value .
 octal_byte_value = `\` octal_digit octal_digit octal_digit .
@@ -439,6 +446,11 @@ escaped_char     = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `
 '\xff'
 '\u12e4'
 '\U00101234'
+'aa'         // illegal: too many characters
+'\xa'        // illegal: too few hexadecimal digits
+'\0'         // illegal: too few octal digits
+'\uDFFF'     // illegal: surrogate half
+'\U00110000' // illegal: invalid Unicode code point
 </pre>
 
 
@@ -453,7 +465,8 @@ raw string literals and interpreted string literals.
 Raw string literals are character sequences between back quotes
 <code>``</code>.  Within the quotes, any character is legal except
 back quote. The value of a raw string literal is the
-string composed of the uninterpreted characters between the quotes;
+string composed of the uninterpreted (implicitly UTF-8-encoded) characters
+between the quotes;
 in particular, backslashes have no special meaning and the string may
 contain newlines.
 Carriage returns inside raw string literals
@@ -464,8 +477,9 @@ Interpreted string literals are character sequences between double
 quotes <code>""</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 character literals (except that <code>\'</code> is illegal and
-<code>\"</code> is legal).  The three-digit octal (<code>\</code><i>nnn</i>)
+are in rune literals (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
 <i>bytes</i> of the resulting string; all other escapes represent
 the (possibly multi-byte) UTF-8 encoding of individual <i>characters</i>.
@@ -492,6 +506,8 @@ interpreted_string_lit = `"` { unicode_value | byte_value } `"` .
 "日本語"
 "\u65e5本\U00008a9e"
 "\xff\u00FF"
+"\uD800"       // illegal: surrogate half
+"\U00110000"   // illegal: invalid Unicode code point
 </pre>
 
 <p>
@@ -501,15 +517,15 @@ These examples all represent the same string:
 <pre>
 "日本語"                                 // UTF-8 input text
 `日本語`                                 // UTF-8 input text as a raw literal
-"\u65e5\u672c\u8a9e"                    // The explicit Unicode code points
-"\U000065e5\U0000672c\U00008a9e"        // The explicit Unicode code points
-"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"  // The explicit UTF-8 bytes
+"\u65e5\u672c\u8a9e"                    // the explicit Unicode code points
+"\U000065e5\U0000672c\U00008a9e"        // the explicit Unicode code points
+"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"  // the explicit UTF-8 bytes
 </pre>
 
 <p>
 If the source code represents a character as two code points, such as
 a combining form involving an accent and a letter, the result will be
-an error if placed in a character literal (it is not a single code
+an error if placed in a rune literal (it is not a single code
 point), and will appear as two code points if placed in a string
 literal.
 </p>
@@ -518,7 +534,7 @@ literal.
 <h2 id="Constants">Constants</h2>
 
 <p>There are <i>boolean constants</i>,
-<i>character constants</i>,
+<i>rune constants</i>,
 <i>integer constants</i>,
 <i>floating-point constants</i>, <i>complex constants</i>,
 and <i>string constants</i>. Character, integer, floating-point,
@@ -528,7 +544,7 @@ collectively called <i>numeric constants</i>.
 
 <p>
 A constant value is represented by a
-<a href="#Character_literals">character</a>,
+<a href="#Rune_literals">rune</a>,
 <a href="#Integer_literals">integer</a>,
 <a href="#Floating-point_literals">floating-point</a>,
 <a href="#Imaginary_literals">imaginary</a>,
@@ -622,14 +638,15 @@ expressions</a>.
 
 <p>
 A type determines the set of values and operations specific to values of that
-type.  A type may be specified by a (possibly qualified) <i>type name</i>
-(§<a href="#Qualified_identifiers">Qualified identifier</a>, §<a href="#Type_declarations">Type declarations</a>) or a <i>type literal</i>,
+type.  A type may be specified by a
+(possibly <a href="#Qualified_identifiers">qualified</a>) <i>type name</i>
+(§<a href="#Type_declarations">Type declarations</a>) or a <i>type literal</i>,
 which composes a new type from previously declared types.
 </p>
 
 <pre class="ebnf">
 Type      = TypeName | TypeLit | "(" Type ")" .
-TypeName  = QualifiedIdent .
+TypeName  = identifier | QualifiedIdent .
 TypeLit   = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
 	    SliceType | MapType | ChannelType .
 </pre>
@@ -646,7 +663,7 @@ type literals.
 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.
+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
@@ -764,19 +781,21 @@ particular architecture.
 
 <p>
 A <i>string type</i> represents the set of string values.
-Strings behave like slices of bytes but are immutable: once created,
+A string value is a (possibly empty) sequence of bytes.
+Strings are immutable: once created,
 it is impossible to change the contents of a string.
 The predeclared string type is <code>string</code>.
+</p>
 
 <p>
-The elements of strings have type <code>byte</code> and may be
-accessed using the usual <a href="#Indexes">indexing operations</a>.  It is
-illegal to take the address of such an element; if
-<code>s[i]</code> is the <i>i</i>th byte of a
-string, <code>&s[i]</code> is invalid.  The length of string
-<code>s</code> can be discovered using the built-in function
-<code>len</code>. The length is a compile-time constant if <code>s</code>
-is a string literal.
+The length of a string <code>s</code> (its size in bytes) can be discovered using
+the built-in function <a href="#Length_and_capacity"><code>len</code></a>.
+The length is a compile-time constant if the string is a constant.
+A string's bytes can be accessed by integer <a href="#Index_expressions">indices</a>
+0 through <code>len(s)-1</code>.
+It is illegal to take the address of such an element; if
+<code>s[i]</code> is the <code>i</code>'th byte of a
+string, <code>&s[i]</code> is invalid.
 </p>
 
 
@@ -796,12 +815,13 @@ ElementType = Type .
 </pre>
 
 <p>
-The length is part of the array's type and must be a
-<a href="#Constant_expressions">constant expression</a> that evaluates to a non-negative
-integer value.  The length of array <code>a</code> can be discovered
-using the built-in function <a href="#Length_and_capacity"><code>len(a)</code></a>.
-The elements can be indexed by integer
-indices 0 through <code>len(a)-1</code> (§<a href="#Indexes">Indexes</a>).
+The length is part of the array's type; it must evaluate to a non-
+negative <a href="#Constants">constant</a> representable by a value
+of type <code>int</code>.
+The length of array <code>a</code> can be discovered
+using the built-in function <a href="#Length_and_capacity"><code>len</code></a>.
+The elements can be addressed by integer <a href="#Index_expressions">indices</a>
+0 through <code>len(a)-1</code>.
 Array types are always one-dimensional but may be composed to form
 multi-dimensional types.
 </p>
@@ -830,9 +850,9 @@ SliceType = "[" "]" ElementType .
 <p>
 Like arrays, slices are indexable and have a length.  The length of a
 slice <code>s</code> can be discovered by the built-in function
-<a href="#Length_and_capacity"><code>len(s)</code></a>; unlike with arrays it may change during
-execution.  The elements can be addressed by integer indices 0
-through <code>len(s)-1</code> (§<a href="#Indexes">Indexes</a>).  The slice index of a
+<a href="#Length_and_capacity"><code>len</code></a>; unlike with arrays it may change during
+execution.  The elements can be addressed by integer <a href="#Index_expressions">indices</a>
+0 through <code>len(s)-1</code>.  The slice index of a
 given element may be less than the index of the same element in the
 underlying array.
 </p>
@@ -981,7 +1001,7 @@ promoted methods are included in the method set of the struct as follows:
 	<code>T</code>. The method set of <code>*S</code> also
 	includes promoted methods with receiver <code>*T</code>.
 	</li>
-	
+
 	<li>
 	If <code>S</code> contains an anonymous field <code>*T</code>,
 	the method sets of <code>S</code> and <code>*S</code> both
@@ -994,7 +1014,7 @@ promoted methods are included in the method set of the struct as follows:
 A field declaration may be followed by an optional string literal <i>tag</i>,
 which becomes an attribute for all the fields in the corresponding
 field declaration. The tags are made
-visible through a <a href="#Package_unsafe">reflection interface</a>
+visible through a <a href="/pkg/reflect/#StructTag">reflection interface</a>
 but are otherwise ignored.
 </p>
 
@@ -1046,8 +1066,11 @@ ParameterDecl  = [ IdentifierList ] [ "..." ] Type .
 <p>
 Within a list of parameters or results, the names (IdentifierList)
 must either all be present or all be absent. If present, each name
-stands for one item (parameter or result) of the specified type; if absent, each
-type stands for one item of that type.  Parameter and result
+stands for one item (parameter or result) of the specified type and
+all non-<a href="#Blank_identifier">blank</a> names in the signature
+must be <a href="#Uniqueness_of_identifiers">unique</a>.
+If absent, each type stands for one item of that type.
+Parameter and result
 lists are always parenthesized except that if there is exactly
 one unnamed result it may be written as an unparenthesized type.
 </p>
@@ -1232,10 +1255,10 @@ map[string]interface{}
 <p>
 The number of map elements is called its length.
 For a map <code>m</code>, it can be discovered using the
-built-in function <a href="#Length_and_capacity"><code>len(m)</code></a>
+built-in function <a href="#Length_and_capacity"><code>len</code></a>
 and may change during execution. Elements may be added during execution
 using <a href="#Assignments">assignments</a> and retrieved with
-<a href="#Indexes">index</a> expressions; they may be removed with the
+<a href="#Index_expressions">index expressions</a>; they may be removed with the
 <a href="#Deletion_of_map_elements"><code>delete</code></a> built-in function.
 </p>
 <p>
@@ -1510,11 +1533,11 @@ Go is lexically scoped using blocks:
 	    or function (but not method) declared at top level (outside any
 	    function) is the package block.</li>
 
-	<li>The scope of an imported package identifier is the file block
+	<li>The scope of the package name of an imported package is the file block
 	    of the file containing the import declaration.</li>
 
-	<li>The scope of an identifier denoting a function parameter or
-	    result variable is the function body.</li>
+	<li>The scope of an identifier denoting a method receiver, function parameter,
+	    or result variable is the function body.</li>
 
 	<li>The scope of a constant or variable identifier declared
 	    inside a function begins at the end of the ConstSpec or VarSpec
@@ -1897,7 +1920,7 @@ _, y, _ := coord(p)  // coord() returns three values; only interested in y coord
 
 <p>
 Unlike regular variable declarations, a short variable declaration may redeclare variables provided they
-were originally declared in the same block with the same type, and at
+were originally declared earlier in the same block with the same type, and at
 least one of the non-<a href="#Blank_identifier">blank</a> variables is new.  As a consequence, redeclaration
 can only appear in a multi-variable short declaration.
 Redeclaration does not introduce a new
@@ -1907,6 +1930,7 @@ variable; it just assigns a new value to the original.
 <pre>
 field1, offset := nextField(str, 0)
 field2, offset := nextField(str, offset)  // redeclares offset
+a, a := 1, 2                              // illegal: double declaration of a or no new variable if a was declared elsewhere
 </pre>
 
 <p>
@@ -1969,8 +1993,15 @@ is visible only within selectors for that type.
 </p>
 
 <p>
-For a base type, the non-<a href="#Blank_identifier">blank</a> names of
-methods bound to it must be <a href="#Uniqueness_of_identifiers">unique</a>.
+A non-<a href="#Blank_identifier">blank</a> receiver identifier must be
+<a href="#Uniqueness_of_identifiers">unique</a> in the method signature.
+If the receiver's value is not referenced inside the body of the method,
+its identifier may be omitted in the declaration. The same applies in
+general to parameters of functions and methods.
+</p>
+
+<p>
+For a base type, the non-blank names of methods bound to it must be unique.
 If the base type is a <a href="#Struct_types">struct type</a>,
 the non-blank method and field names must be distinct.
 </p>
@@ -1997,12 +2028,6 @@ to the base type <code>Point</code>.
 </p>
 
 <p>
-If the receiver's value is not referenced inside the body of the method,
-its identifier may be omitted in the declaration. The same applies in
-general to parameters of functions and methods.
-</p>
-
-<p>
 The type of a method is the type of a function with the receiver as first
 argument.  For instance, the method <code>Scale</code> has type
 </p>
@@ -2026,25 +2051,33 @@ operators and functions to operands.
 <h3 id="Operands">Operands</h3>
 
 <p>
-Operands denote the elementary values in an expression.
+Operands denote the elementary values in an expression. An operand may be a
+literal, a (possibly <a href="#Qualified_identifiers">qualified</a>) identifier
+denoting a
+<a href="#Constant_declarations">constant</a>,
+<a href="#Variable_declarations">variable</a>, or
+<a href="#Function_declarations">function</a>,
+a <a href="#Method_expressions">method expression</a> yielding a function,
+or a parenthesized expression.
 </p>
 
 <pre class="ebnf">
-Operand    = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" .
+Operand    = Literal | OperandName | MethodExpr | "(" Expression ")" .
 Literal    = BasicLit | CompositeLit | FunctionLit .
-BasicLit   = int_lit | float_lit | imaginary_lit | char_lit | string_lit .
+BasicLit   = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
+OperandName = identifier | QualifiedIdent.
 </pre>
 
-
 <h3 id="Qualified_identifiers">Qualified identifiers</h3>
 
 <p>
-A qualified identifier is a non-<a href="#Blank_identifier">blank</a> identifier
-qualified by a package name prefix.
+A qualified identifier is an identifier qualified with a package name prefix.
+Both the package name and the identifier must not be
+<a href="#Blank_identifier">blank</a>.
 </p>
 
 <pre class="ebnf">
-QualifiedIdent = [ PackageName "." ] identifier .
+QualifiedIdent = PackageName "." identifier .
 </pre>
 
 <p>
@@ -2089,7 +2122,7 @@ The types of the expressions must be <a href="#Assignability">assignable</a>
 to the respective field, element, and key types of the LiteralType;
 there is no additional conversion.
 The key is interpreted as a field name for struct literals,
-an index expression for array and slice literals, and a key for map literals.
+an index for array and slice literals, and a key for map literals.
 For map literals, all elements must have a key. It is an error
 to specify multiple elements with the same field name or
 constant key value.
@@ -2101,18 +2134,18 @@ For struct literals the following rules apply:
 <ul>
 	<li>A key must be a field name declared in the LiteralType.
 	</li>
-	<li>A literal that does not contain any keys must
+	<li>An element list that does not contain any keys must
 	    list an element for each struct field in the
 	    order in which the fields are declared.
 	</li>
 	<li>If any element has a key, every element must have a key.
 	</li>
-	<li>A literal that contains keys does not need to
+	<li>An element list that contains keys does not need to
 	    have an element for each struct field. Omitted fields
 	    get the zero value for that field.
 	</li>
 	<li>A literal may omit the element list; such a literal evaluates
-		to the zero value for its type.
+	    to the zero value for its type.
 	</li>
 	<li>It is an error to specify an element for a non-exported
 	    field of a struct belonging to a different package.
@@ -2198,7 +2231,7 @@ Within a composite literal of array, slice, or map type <code>T</code>,
 elements that are themselves composite literals may elide the respective
 literal type if it is identical to the element type of <code>T</code>.
 Similarly, elements that are addresses of composite literals may elide
-the <code>&T</code> when the the element type is <code>*T</code>.
+the <code>&T</code> when the element type is <code>*T</code>.
 </p>
 
 
@@ -2315,7 +2348,6 @@ Point{1, 2}
 m["foo"]
 s[i : j + 1]
 obj.color
-math.Sin
 f.p[i].x()
 </pre>
 
@@ -2323,7 +2355,9 @@ f.p[i].x()
 <h3 id="Selectors">Selectors</h3>
 
 <p>
-A primary expression of the form
+For a <a href="#Primary_expressions">primary expression</a> <code>x</code>
+that is not a <a href="#Package_clause">package name</a>, the
+<i>selector expression</i>
 </p>
 
 <pre>
@@ -2331,17 +2365,20 @@ x.f
 </pre>
 
 <p>
-denotes the field or method <code>f</code> of the value denoted by <code>x</code>
-(or sometimes <code>*x</code>; see below). The identifier <code>f</code>
-is called the (field or method)
-<i>selector</i>; it must not be the <a href="#Blank_identifier">blank identifier</a>.
-The type of the expression is the type of <code>f</code>.
+denotes the field or method <code>f</code> of the value <code>x</code>
+(or sometimes <code>*x</code>; see below).
+The identifier <code>f</code> is called the (field or method) <i>selector</i>;
+it must not be the <a href="#Blank_identifier">blank identifier</a>.
+The type of the selector expression is the type of <code>f</code>.
+If <code>x</code> is a package name, see the section on
+<a href="#Qualified_identifiers">qualified identifiers</a>.
 </p>
+
 <p>
 A selector <code>f</code> may denote a field or method <code>f</code> of
 a type <code>T</code>, or it may refer
-to a field or method <code>f</code> of a nested anonymous field of
-<code>T</code>.
+to a field or method <code>f</code> of a nested
+<a href="#Struct_types">anonymous field</a> of <code>T</code>.
 The number of anonymous fields traversed
 to reach <code>f</code> is called its <i>depth</i> in <code>T</code>.
 The depth of a field or method <code>f</code>
@@ -2350,9 +2387,11 @@ The depth of a field or method <code>f</code> declared in
 an anonymous field <code>A</code> in <code>T</code> is the
 depth of <code>f</code> in <code>A</code> plus one.
 </p>
+
 <p>
 The following rules apply to selectors:
 </p>
+
 <ol>
 <li>
 For a value <code>x</code> of type <code>T</code> or <code>*T</code>
@@ -2364,18 +2403,26 @@ If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code><
 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> 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> if there is such a method.
-If no value or <code>nil</code> was assigned to <code>x</code>, <code>x.f</code> is illegal.
+For a variable <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>.
+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>
 In all other cases, <code>x.f</code> is illegal.
 </li>
+<li>
+If <code>x</code> is of pointer or interface type and has the value
+<code>nil</code>, assigning to, evaluating, or calling <code>x.f</code>
+causes a <a href="#Run_time_panics">run-time panic</a>.
+</li>
 </ol>
+
 <p>
-Selectors automatically dereference pointers to structs.
+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
@@ -2384,6 +2431,7 @@ 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 a shortcut for <code>(*x.A).f</code>.
 </p>
+
 <p>
 For example, given the declarations:
 </p>
@@ -2421,9 +2469,9 @@ p.z   // (*p).z
 p.y   // ((*p).T1).y
 p.x   // (*(*p).T0).x
 
-p.M2  // (*p).M2
-p.M1  // ((*p).T1).M1
-p.M0  // ((*p).T0).M0
+p.M2()  // (*p).M2()
+p.M1()  // ((*p).T1).M1()
+p.M0()  // ((*p).T0).M0()
 </pre>
 
 
@@ -2434,7 +2482,7 @@ TODO: Specify what happens to receivers.
 -->
 
 
-<h3 id="Indexes">Indexes</h3>
+<h3 id="Index_expressions">Index expressions</h3>
 
 <p>
 A primary expression of the form
@@ -2452,16 +2500,35 @@ rules apply:
 </p>
 
 <p>
+If <code>a</code> is not a map:
+</p>
+<ul>
+	<li>the index <code>x</code> must be an integer value; it is <i>in range</i> if <code>0 <= x < len(a)</code>,
+	    otherwise it is <i>out of range</i></li>
+	<li>a <a href="#Constants">constant</a> index must be non-negative
+	    and representable by a value of type <code>int</code>
+</ul>
+
+<p>
 For <code>a</code> of type <code>A</code> or <code>*A</code>
-where <code>A</code> is an <a href="#Array_types">array type</a>,
-or for <code>a</code> of type <code>S</code> where <code>S</code> is a <a href="#Slice_types">slice type</a>:
+where <code>A</code> is an <a href="#Array_types">array type</a>:
 </p>
 <ul>
-	<li><code>x</code> must be an integer value and <code>0 <= x < len(a)</code></li>
+	<li>a <a href="#Constants">constant</a> index must be in range</li>
+	<li>if <code>a</code> is <code>nil</code> or if <code>x</code> is out of range at run time,
+	    a <a href="#Run_time_panics">run-time panic</a> occurs</li>
 	<li><code>a[x]</code> is the array element at index <code>x</code> and the type of
-	  <code>a[x]</code> is the element type of <code>A</code></li>
-	<li>if <code>a</code> is <code>nil</code> or if the index <code>x</code> is out of range,
-	a <a href="#Run_time_panics">run-time panic</a> occurs</li>
+	    <code>a[x]</code> is the element type of <code>A</code></li>
+</ul>
+
+<p>
+For <code>a</code> of type <code>S</code> where <code>S</code> is a <a href="#Slice_types">slice type</a>:
+</p>
+<ul>
+	<li>if the slice is <code>nil</code> or if <code>x</code> is out of range at run time,
+	    a <a href="#Run_time_panics">run-time panic</a> occurs</li>
+	<li><code>a[x]</code> is the slice element at index <code>x</code> and the type of
+	    <code>a[x]</code> is the element type of <code>S</code></li>
 </ul>
 
 <p>
@@ -2469,12 +2536,13 @@ For <code>a</code> of type <code>T</code>
 where <code>T</code> is a <a href="#String_types">string type</a>:
 </p>
 <ul>
-	<li><code>x</code> must be an integer value and <code>0 <= x < len(a)</code></li>
+	<li>a <a href="#Constants">constant</a> index must be in range
+	    if the string <code>a</code> is also constant</li>
+	<li>if <code>x</code> is out of range at run time,
+	    a <a href="#Run_time_panics">run-time panic</a> occurs</li>
 	<li><code>a[x]</code> is the byte at index <code>x</code> and the type of
-	  <code>a[x]</code> is <code>byte</code></li>
+	    <code>a[x]</code> is <code>byte</code></li>
 	<li><code>a[x]</code> may not be assigned to</li>
-	<li>if the index <code>x</code> is out of range,
-	a <a href="#Run_time_panics">run-time panic</a> occurs</li>
 </ul>
 
 <p>
@@ -2483,14 +2551,14 @@ where <code>M</code> is a <a href="#Map_types">map type</a>:
 </p>
 <ul>
 	<li><code>x</code>'s type must be
-	<a href="#Assignability">assignable</a>
-	to the key type of <code>M</code></li>
+	    <a href="#Assignability">assignable</a>
+	    to the key type of <code>M</code></li>
 	<li>if the map contains an entry with key <code>x</code>,
-	  <code>a[x]</code> is the map value with key <code>x</code>
-	  and the type of <code>a[x]</code> is the value type of <code>M</code></li>
+	    <code>a[x]</code> is the map value with key <code>x</code>
+	    and the type of <code>a[x]</code> is the value type of <code>M</code></li>
 	<li>if the map is <code>nil</code> or does not contain such an entry,
-	  <code>a[x]</code> is the <a href="#The_zero_value">zero value</a>
-	  for the value type of <code>M</code></li>
+	    <code>a[x]</code> is the <a href="#The_zero_value">zero value</a>
+	    for the value type of <code>M</code></li>
 </ul>
 
 <p>
@@ -2533,9 +2601,9 @@ a[low : high]
 </pre>
 
 <p>
-constructs a substring or slice. The index expressions <code>low</code> and
+constructs a substring or slice. The indices <code>low</code> and
 <code>high</code> select which elements appear in the result. The result has
-indexes starting at 0 and length equal to
+indices starting at 0 and length equal to
 <code>high</code> - <code>low</code>.
 After slicing the array <code>a</code>
 </p>
@@ -2556,7 +2624,7 @@ s[2] == 4
 </pre>
 
 <p>
-For convenience, any of the index expressions may be omitted. A missing <code>low</code>
+For convenience, any of the indices may be omitted. A missing <code>low</code>
 index defaults to zero; a missing <code>high</code> index defaults to the length of the
 sliced operand:
 </p>
@@ -2568,9 +2636,15 @@ a[:]   // same as a[0 : len(a)]
 </pre>
 
 <p>
-For arrays or strings, the indexes <code>low</code> and <code>high</code> must
-satisfy 0 <= <code>low</code> <= <code>high</code> <= length; for
-slices, the upper bound is the capacity rather than the length.
+For arrays or strings, the indices <code>low</code> and <code>high</code> are
+<i>in range</i> if <code>0</code> <= <code>low</code> <= <code>high</code> <= <code>len(a)</code>,
+otherwise they are <i>out of range</i>.
+For slices, the upper index bound is the slice capacity <code>cap(a)</code> rather than the length.
+A <a href="#Constants">constant</a> index must be non-negative and representable by a value of type
+<code>int</code>.
+If both indices
+are constant, they must satisfy <code>low <= high</code>. If <code>a</code> is <code>nil</code>
+or if the indices are out of range at run time, a <a href="#Run_time_panics">run-time panic</a> occurs.
 </p>
 
 <p>
@@ -2601,19 +2675,33 @@ The notation <code>x.(T)</code> is called a <i>type assertion</i>.
 More precisely, if <code>T</code> is not an interface type, <code>x.(T)</code> asserts
 that the dynamic type of <code>x</code> is <a href="#Type_identity">identical</a>
 to the type <code>T</code>.
+In this case, <code>T</code> must <a href="#Method_sets">implement</a> the (interface) type of <code>x</code>;
+otherwise the type assertion is invalid since it is not possible for <code>x</code>
+to store a value of type <code>T</code>.
 If <code>T</code> is an interface type, <code>x.(T)</code> asserts that the dynamic type
-of <code>x</code> implements the interface <code>T</code> (§<a href="#Interface_types">Interface types</a>).
+of <code>x</code> implements the interface <code>T</code>.
 </p>
 <p>
 If the type assertion holds, the value of the expression is the value
 stored in <code>x</code> and its type is <code>T</code>. If the type assertion is false,
 a <a href="#Run_time_panics">run-time panic</a> occurs.
 In other words, even though the dynamic type of <code>x</code>
-is known only at run-time, the type of <code>x.(T)</code> is
+is known only at run time, the type of <code>x.(T)</code> is
 known to be <code>T</code> in a correct program.
 </p>
+
+<pre>
+var x interface{} = 7  // x has dynamic type int and value 7
+i := x.(int)           // i has type int and value 7
+
+type I interface { m() }
+var y I
+s := y.(string)        // illegal: string does not implement I (missing method m)
+r := y.(io.Reader)     // r has type io.Reader and y must implement both I and io.Reader
+</pre>
+
 <p>
-If a type assertion is used in an assignment or initialization of the form
+If a type assertion is used in an <a href="#Assignments">assignment</a> or initialization of the form
 </p>
 
 <pre>
@@ -2629,7 +2717,7 @@ 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>.
 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.  (§<a href="#Assignments">Assignments</a>)
+returning a value and a boolean indicating success.
 </p>
 
 
@@ -2677,13 +2765,14 @@ causes a <a href="#Run_time_panics">run-time panic</a>.
 </p>
 
 <p>
-As a special case, if the return parameters of a function or method
+As a special case, if the return values of a function or method
 <code>g</code> are equal in number and individually
 assignable to the parameters of another function or method
 <code>f</code>, then the call <code>f(g(<i>parameters_of_g</i>))</code>
 will invoke <code>f</code> after binding the return values of
 <code>g</code> to the parameters of <code>f</code> in order.  The call
-of <code>f</code> must contain no parameters other than the call of <code>g</code>.
+of <code>f</code> must contain no parameters other than the call of <code>g</code>,
+and <code>g</code> must have at least one return value.
 If <code>f</code> has a final <code>...</code> parameter, it is
 assigned the return values of <code>g</code> that remain after
 assignment of regular parameters.
@@ -2834,8 +2923,8 @@ As a consequence, statement <code>*p++</code> is the same as <code>(*p)++</code>
 <p>
 There are five precedence levels for binary operators.
 Multiplication operators bind strongest, followed by addition
-operators, comparison operators, <code>&&</code> (logical and),
-and finally <code>||</code> (logical or):
+operators, comparison operators, <code>&&</code> (logical AND),
+and finally <code>||</code> (logical OR):
 </p>
 
 <pre class="grammar">
@@ -2878,10 +2967,10 @@ to strings. All other arithmetic operators apply to integers only.
 /    quotient               integers, floats, complex values
 %    remainder              integers
 
-&    bitwise and            integers
-|    bitwise or             integers
-^    bitwise xor            integers
-&^   bit clear (and not)    integers
+&    bitwise AND            integers
+|    bitwise OR             integers
+^    bitwise XOR            integers
+&^   bit clear (AND NOT)    integers
 
 <<   left shift             integer << unsigned integer
 >>   right shift            integer >> unsigned integer
@@ -2938,10 +3027,11 @@ int64    -9223372036854775808
 </pre>
 
 <p>
-If the divisor is zero, a <a href="#Run_time_panics">run-time panic</a> occurs.
-If the dividend is positive and the divisor is a constant power of 2,
+If the divisor is a <a href="#Constants">constant</a>, it must not be zero.
+If the divisor is zero at run time, a <a href="#Run_time_panics">run-time panic</a> occurs.
+If the dividend is non-negative and the divisor is a constant power of 2,
 the division may be replaced by a right shift, and computing the remainder may
-be replaced by a bitwise "and" operation:
+be replaced by a bitwise AND operation:
 </p>
 
 <pre>
@@ -2976,10 +3066,10 @@ follows:
 </pre>
 
 <p>
-For floating-point numbers,
+For floating-point and complex numbers,
 <code>+x</code> is the same as <code>x</code>,
 while <code>-x</code> is the negation of <code>x</code>.
-The result of a floating-point division by zero is not specified beyond the
+The result of a floating-point or complex division by zero is not specified beyond the
 IEEE-754 standard; whether a <a href="#Run_time_panics">run-time panic</a>
 occurs is implementation-specific.
 </p>
@@ -3142,9 +3232,9 @@ The right operand is evaluated conditionally.
 </p>
 
 <pre class="grammar">
-&&    conditional and    p && q  is  "if p then q else false"
-||    conditional or     p || q  is  "if p then true else q"
-!     not                !p      is  "not p"
+&&    conditional AND    p && q  is  "if p then q else false"
+||    conditional OR     p || q  is  "if p then true else q"
+!     NOT                !p      is  "not p"
 </pre>
 
 
@@ -3158,6 +3248,7 @@ that is, either a variable, pointer indirection, or slice indexing
 operation; or a field selector of an addressable struct operand;
 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>.
 </p>
 <p>
@@ -3171,6 +3262,7 @@ will cause a <a href="#Run_time_panics">run-time panic</a>.
 <pre>
 &x
 &a[f(2)]
+&Point{2, 3}
 *p
 *pf(x)
 </pre>
@@ -3181,9 +3273,13 @@ will cause a <a href="#Run_time_panics">run-time panic</a>.
 <p>
 For an operand <code>ch</code> of <a href="#Channel_types">channel type</a>,
 the value of the receive operation <code><-ch</code> is the value received
-from the channel <code>ch</code>. The type of the value is the element type of
-the channel. The expression blocks until a value is available.
+from the channel <code>ch</code>. The channel direction must permit receive operations,
+and the type of the receive operation is the element type of the channel.
+The expression blocks until a value is available.
 Receiving from a <code>nil</code> channel blocks forever.
+Receiving from a <a href="#Close">closed</a> channel always succeeds,
+immediately returning the element type's <a href="#The_zero_value">zero
+value</a>.
 </p>
 
 <pre>
@@ -3204,11 +3300,11 @@ var x, ok = <-ch
 </pre>
 
 <p>
-yields an additional result.
-The boolean variable <code>ok</code> indicates whether
-the received value was sent on the channel (<code>true</code>)
-or is a <a href="#The_zero_value">zero value</a> returned
-because the channel is closed and empty (<code>false</code>).
+yields an additional result of type <code>bool</code> 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
+channel is closed and empty.
 </p>
 
 <!--
@@ -3230,7 +3326,7 @@ argument that is the receiver of the method.
 
 <pre class="ebnf">
 MethodExpr    = ReceiverType "." MethodName .
-ReceiverType  = TypeName | "(" "*" TypeName ")" .
+ReceiverType  = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
 </pre>
 
 <p>
@@ -3267,13 +3363,15 @@ func(tv T, a int) int
 
 <p>
 That function may be called normally with an explicit receiver, so
-these three invocations are equivalent:
+these five invocations are equivalent:
 </p>
 
 <pre>
 t.Mv(7)
 T.Mv(t, 7)
-f := T.Mv; f(t, 7)
+(T).Mv(t, 7)
+f1 := T.Mv; f1(t, 7)
+f2 := (T).Mv; f2(t, 7)
 </pre>
 
 <p>
@@ -3345,18 +3443,25 @@ that can be converted to type <code>T</code>.
 </p>
 
 <pre class="ebnf">
-Conversion = Type "(" Expression ")" .
+Conversion = Type "(" Expression [ "," ] ")" .
 </pre>
 
 <p>
-If the type starts with an operator it must be parenthesized:
+If the type starts with the operator <code>*</code> or <code><-</code>,
+or if the type starts with the keyword <code>func</code>
+and has no result list, it must be parenthesized when
+necessary to avoid ambiguity:
 </p>
 
 <pre>
 *Point(p)        // same as *(Point(p))
-(*Point)(p)      // p is converted to (*Point)
+(*Point)(p)      // p is converted to *Point
 <-chan int(c)    // same as <-(chan int(c))
-(<-chan int)(c)  // c is converted to (<-chan int)
+(<-chan int)(c)  // c is converted to <-chan int
+func()(x)        // function signature func() x
+(func())(x)      // x is converted to func()
+(func() int)(x)  // x is converted to func() int
+func() int(x)    // x is converted to func() int (unambiguous)
 </pre>
 
 <p>
@@ -3369,6 +3474,14 @@ type <code>T</code> in any of these cases:
 	<code>x</code> is representable by a value of type <code>T</code>.
 	</li>
 	<li>
+	<code>x</code> is a floating-point constant,
+	<code>T</code> is a floating-point type,
+	and <code>x</code> is representable by a value
+	of type <code>T</code> after rounding using
+	IEEE 754 round-to-even rules.
+	The constant <code>T(x)</code> is the rounded value.
+	</li>
+	<li>
 	<code>x</code> is an integer constant and <code>T</code> is a
 	<a href="#String_types">string type</a>.
 	The same rule as for non-constant <code>x</code> applies in this case
@@ -3384,6 +3497,7 @@ Converting a constant yields a typed constant as result.
 uint(iota)               // iota value of type uint
 float32(2.718281828)     // 2.718281828 of type float32
 complex128(1)            // 1.0 + 0.0i of type complex128
+float32(0.49999999)      // 0.5 of type float32
 string('x')              // "x" of type string
 string(0x266c)           // "♬" of type string
 MyString("foo" + "bar")  // "foobar" of type MyString
@@ -3419,12 +3533,11 @@ in any of these cases:
 	<code>x</code>'s type and <code>T</code> are both complex types.
 	</li>
 	<li>
-	<code>x</code> is an integer or has type <code>[]byte</code> or
-	<code>[]rune</code> and <code>T</code> is a string type.
+	<code>x</code> is an integer or a slice of bytes or runes
+	and <code>T</code> is a string type.
 	</li>
 	<li>
-	<code>x</code> is a string and <code>T</code> is <code>[]byte</code> or
-	<code>[]rune</code>.
+	<code>x</code> is a string and <code>T</code> is a slice of bytes or runes.
 	</li>
 </ul>
 
@@ -3490,7 +3603,7 @@ the range of valid Unicode code points are converted to <code>"\uFFFD"</code>.
 
 <pre>
 string('a')       // "a"
-string(-1)        // "\ufffd" == "\xef\xbf\xbd "
+string(-1)        // "\ufffd" == "\xef\xbf\xbd"
 string(0xf8)      // "\u00f8" == "ø" == "\xc3\xb8"
 type MyString string
 MyString(0x65e5)  // "\u65e5" == "日" == "\xe6\x97\xa5"
@@ -3551,7 +3664,7 @@ MyRunes("白鵬翔")           // []rune{0x767d, 0x9d6c, 0x7fd4}
 
 <p>
 Constant expressions may contain only <a href="#Constants">constant</a>
-operands and are evaluated at compile-time.
+operands and are evaluated at compile time.
 </p>
 
 <p>
@@ -3560,7 +3673,7 @@ wherever it is legal to use an operand of boolean, numeric, or string type,
 respectively.
 Except for shift operations, if the operands of a binary operation are
 different kinds of untyped constants, the operation and, for non-boolean operations, the result use
-the kind that appears later in this list: integer, character, floating-point, complex.
+the kind that appears later in this list: integer, rune, floating-point, complex.
 For example, an untyped integer constant divided by an
 untyped complex constant yields an untyped complex constant.
 </p>
@@ -3581,14 +3694,15 @@ complex, or string constant).
 const a = 2 + 3.0          // a == 5.0   (untyped floating-point constant)
 const b = 15 / 4           // b == 3     (untyped integer constant)
 const c = 15 / 4.0         // c == 3.75  (untyped floating-point constant)
-const Θ float64 = 3/2      // Θ == 1.5   (type float64)
+const Θ float64 = 3/2      // Θ == 1.0   (type float64, 3/2 is integer division)
+const Π float64 = 3/2.     // Π == 1.5   (type float64, 3/2. is float division)
 const d = 1 << 3.0         // d == 8     (untyped integer constant)
 const e = 1.0 << 3         // e == 8     (untyped integer constant)
 const f = int32(1) << 33   // f == 0     (type int32)
 const g = float64(2) >> 1  // illegal    (float64(2) is a typed floating-point constant)
 const h = "foo" > "bar"    // h == true  (untyped boolean constant)
 const j = true             // j == true  (untyped boolean constant)
-const k = 'w' + 1          // k == 'x'   (untyped character constant)
+const k = 'w' + 1          // k == 'x'   (untyped rune constant)
 const l = "hi"             // l == "hi"  (untyped string constant)
 const m = string(k)        // m == "x"   (type string)
 const Σ = 1 - 0.707i       //            (untyped complex constant)
@@ -3598,13 +3712,13 @@ const Φ = iota*1i - 1/1i   //            (untyped complex constant)
 
 <p>
 Applying the built-in function <code>complex</code> to untyped
-integer, character, or floating-point constants yields
+integer, rune, or floating-point constants yields
 an untyped complex constant.
 </p>
 
 <pre>
-const ic = complex(0, c)   // ic == 3.75i (untyped complex constant)
-const iΘ = complex(0, Θ)   // iΘ == 1.5i  (type complex128)
+const ic = complex(0, c)   // ic == 3.75i  (untyped complex constant)
+const iΘ = complex(0, Θ)   // iΘ == 1.5i   (type complex128)
 </pre>
 
 <p>
@@ -3614,8 +3728,16 @@ by any predeclared type in the language. The following are legal declarations:
 </p>
 
 <pre>
-const Huge = 1 << 100
-const Four int8 = Huge >> 98
+const Huge = 1 << 100         // Huge == 1267650600228229401496703205376  (untyped integer constant)
+const Four int8 = Huge >> 98  // Four == 4                                (type int8)
+</pre>
+
+<p>
+The divisor of a constant division or remainder operation must not be zero:
+</p>
+
+<pre>
+3.14 / 0.0   // illegal: division by zero
 </pre>
 
 <p>
@@ -3626,9 +3748,9 @@ of the constant type. The following constant expressions are illegal:
 <pre>
 uint(-1)     // -1 cannot be represented as a uint
 int(3.14)    // 3.14 cannot be represented as an int
-int64(Huge)  // 1<<100 cannot be represented as an int64
-Four * 300   // 300 cannot be represented as an int8
-Four * 100   // 400 cannot be represented as an int8
+int64(Huge)  // 1267650600228229401496703205376 cannot be represented as an int64
+Four * 300   // operand 300 cannot be represented as an int8 (type of Four)
+Four * 100   // product 400 cannot be represented as an int8 (type of Four)
 </pre>
 
 <p>
@@ -3639,7 +3761,7 @@ and -1 for signed and untyped constants.
 
 <pre>
 ^1         // untyped integer constant, equal to -2
-uint8(^1)  // error, same as uint8(-2), out of range
+uint8(^1)  // illegal: same as uint8(-2), -2 cannot be represented as a uint8
 ^uint8(1)  // typed uint8 constant, same as 0xFF ^ uint8(1) = uint8(0xFE)
 int8(^1)   // same as int8(-2)
 ^int8(1)   // same as -1 ^ int8(1) = -2
@@ -3668,8 +3790,10 @@ overflow etc. errors being caught.
 <h3 id="Order_of_evaluation">Order of evaluation</h3>
 
 <p>
-When evaluating the elements of an assignment or expression,
-all function calls, method calls and
+When evaluating the <a href="#Operands">operands</a> of an expression,
+<a href="#Assignments">assignment</a>, or
+<a href="#Return_statements">return statement</a>,
+all function calls, method calls, and
 communication operations are evaluated in lexical left-to-right
 order.
 </p>
@@ -3689,6 +3813,12 @@ and indexing of <code>x</code> and the evaluation
 of <code>y</code> is not specified.
 </p>
 
+<pre>
+a := 1
+f := func() int { a = 2; return 3 }
+x := []int{a, f()}  // x may be [1, 3] or [2, 3]: evaluation order between a and f() is not specified
+</pre>
+
 <p>
 Floating-point operations within a single expression are evaluated according to
 the associativity of the operators.  Explicit parentheses affect the evaluation
@@ -3745,7 +3875,9 @@ Error: log.Panic("error encountered")
 <h3 id="Expression_statements">Expression statements</h3>
 
 <p>
-Function calls, method calls, and receive operations
+With the exception of specific built-in functions,
+function and method <a href="#Calls">calls</a> and
+<a href="#Receive_operator">receive operations</a>
 can appear in statement context. Such statements may be parenthesized.
 </p>
 
@@ -3753,11 +3885,21 @@ can appear in statement context. Such statements may be parenthesized.
 ExpressionStmt = Expression .
 </pre>
 
+<p>
+The following built-in functions are not permitted in statement context:
+</p>
+
+<pre>
+append cap complex imag len make new real
+unsafe.Alignof unsafe.Offsetof unsafe.Sizeof
+</pre>
+
 <pre>
 h(x+y)
 f.Close()
 <-ch
 (<-ch)
+len("foo")  // illegal if len is the built-in function
 </pre>
 
 
@@ -3765,8 +3907,9 @@ f.Close()
 
 <p>
 A send statement sends a value on a channel.
-The channel expression must be of <a href="#Channel_types">channel type</a>
-and the type of the value must be <a href="#Assignability">assignable</a>
+The channel expression must be of <a href="#Channel_types">channel type</a>,
+the channel direction must permit send operations,
+and the type of the value to be sent must be <a href="#Assignability">assignable</a>
 to the channel's element type.
 </p>
 
@@ -3884,7 +4027,7 @@ operand on the left.
 
 <p>
 The assignment proceeds in two phases.
-First, the operands of <a href="#Indexes">index expressions</a>
+First, the operands of <a href="#Index_expressions">index expressions</a>
 and <a href="#Address_operators">pointer indirections</a>
 (including implicit pointer indirections in <a href="#Selectors">selectors</a>)
 on the left and the expressions on the right are all
@@ -3926,7 +4069,7 @@ is assigned to a variable of interface type, the constant is <a href="#Conversio
 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, character, integer, floating-point, complex, or string constant.
+boolean, rune, integer, floating-point, complex, or string constant.
 </p>
 
 
@@ -4011,12 +4154,14 @@ ExprSwitchCase = "case" ExpressionList | "default" .
 </pre>
 
 <p>
-In a case or default clause,
-the last statement only may be a "fallthrough" statement
-(§<a href="#Fallthrough_statements">Fallthrough statement</a>) to
+In a case or default clause, the last non-empty statement
+may be a (possibly <a href="#Labeled_statements">labeled</a>)
+<a href="#Fallthrough_statements">"fallthrough" statement</a> to
 indicate that control should flow from the end of this clause to
 the first statement of the next clause.
 Otherwise control flows to the end of the "switch" statement.
+A "fallthrough" statement may appear as the last statement of all
+but the last clause of an expression switch.
 </p>
 
 <p>
@@ -4049,9 +4194,20 @@ case x == 4: f3()
 A type switch compares types rather than values. It is otherwise similar
 to an expression switch. It is marked by a special switch expression that
 has the form of a <a href="#Type_assertions">type assertion</a>
-using the reserved word <code>type</code> rather than an actual type.
-Cases then match literal types against the dynamic type of the expression
-in the type assertion.
+using the reserved word <code>type</code> rather than an actual type:
+</p>
+
+<pre>
+switch x.(type) {
+// cases
+}
+</pre>
+
+<p>
+Cases then match actual types <code>T</code> against the dynamic type of the
+expression <code>x</code>. As with type assertions, <code>x</code> must be of
+<a href="#Interface_types">interface type</a>, and each non-interface type
+<code>T</code> listed in a case must implement the type of <code>x</code>.
 </p>
 
 <pre class="ebnf">
@@ -4087,17 +4243,17 @@ the following type switch:
 <pre>
 switch i := x.(type) {
 case nil:
-	printString("x is nil")
+	printString("x is nil")                // type of i is type of x (interface{})
 case int:
-	printInt(i)  // i is an int
+	printInt(i)                            // type of i is int
 case float64:
-	printFloat64(i)  // i is a float64
+	printFloat64(i)                        // type of i is float64
 case func(int) float64:
-	printFunction(i)  // i is a function
+	printFunction(i)                       // type of i is func(int) float64
 case bool, string:
-	printString("type is bool or string")  // i is an interface{}
+	printString("type is bool or string")  // type of i is type of x (interface{})
 default:
-	printString("don't know the type")
+	printString("don't know the type")     // type of i is type of x (interface{})
 }
 </pre>
 
@@ -4108,22 +4264,23 @@ could be rewritten:
 <pre>
 v := x  // x is evaluated exactly once
 if v == nil {
+	i := v                                 // type of i is type of x (interface{})
 	printString("x is nil")
 } else if i, isInt := v.(int); isInt {
-	printInt(i)  // i is an int
+	printInt(i)                            // type of i is int
 } else if i, isFloat64 := v.(float64); isFloat64 {
-	printFloat64(i)  // i is a float64
+	printFloat64(i)                        // type of i is float64
 } else if i, isFunc := v.(func(int) float64); isFunc {
-	printFunction(i)  // i is a function
+	printFunction(i)                       // type of i is func(int) float64
 } else {
-	i1, isBool := v.(bool)
-	i2, isString := v.(string)
+	_, isBool := v.(bool)
+	_, isString := v.(string)
 	if isBool || isString {
-		i := v
-		printString("type is bool or string")  // i is an interface{}
+		i := v                         // type of i is type of x (interface{})
+		printString("type is bool or string")
 	} else {
-		i := v
-		printString("don't know the type")  // i is an interface{}
+		i := v                         // type of i is type of x (interface{})
+		printString("don't know the type")
 	}
 }
 </pre>
@@ -4206,24 +4363,31 @@ to corresponding <i>iteration variables</i> and then executes the block.
 </p>
 
 <pre class="ebnf">
-RangeClause = Expression [ "," Expression ] ( "=" | ":=" ) "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.
+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
 <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.
-If the second iteration variable is the <a href="#Blank_identifier">blank identifier</a>,
+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.
 </p>
 
 <p>
-The range expression is evaluated once before beginning the loop
-except if the expression is an array, in which case, depending on
-the expression, it might not be evaluated (see below).
+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 by definition
+(see §<a href="#Length_and_capacity">Length and capacity</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:
 </p>
@@ -4234,14 +4398,14 @@ Range expression                          1st value          2nd value (if 2nd v
 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
 map             m  map[K]V                key      k  K      m[k]       V
-channel         c  chan E                 element  e  E
+channel         c  chan E, <-chan E       element  e  E
 </pre>
 
 <ol>
 <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. As a special
-case, if only the first iteration variable is present, the range loop produces
+values are produced in increasing order, starting at element index 0.
+If only the first iteration variable is present, the range loop produces
 iteration values from 0 up to <code>len(a)</code> and does not index into the array
 or slice itself. For a <code>nil</code> slice, the number of iterations is 0.
 </li>
@@ -4260,11 +4424,12 @@ a single byte in the string.
 <li>
 The iteration order over maps is not specified
 and is not guaranteed to be the same from one iteration to the next.
-If map entries that have not yet been reached are deleted during iteration,
+If map entries that have not yet been reached are removed during iteration,
 the corresponding iteration values will not be produced. If map entries are
-inserted during iteration, the behavior is implementation-dependent, but the
-iteration values for each entry will be produced at most once. If the map
-is <code>nil</code>, the number of iterations is 0.
+created during iteration, that entry may be produced during the iteration or
+may be skipped. The choice may vary for each entry created and from one
+iteration to the next.
+If the map is <code>nil</code>, the number of iterations is 0.
 </li>
 
 <li>
@@ -4327,7 +4492,7 @@ for w := range ch {
 <h3 id="Go_statements">Go statements</h3>
 
 <p>
-A "go" statement starts the execution of a function or method call
+A "go" statement starts the execution of a function call
 as an independent concurrent thread of control, or <i>goroutine</i>,
 within the same address space.
 </p>
@@ -4337,7 +4502,12 @@ GoStmt = "go" Expression .
 </pre>
 
 <p>
-The expression must be a call.
+The expression must be a function or method call; it cannot be parenthesized.
+Calls of built-in functions are restricted as for
+<a href="#Expression_statements">expression statements</a>.
+</p>
+
+<p>
 The function value and parameters are
 <a href="#Calls">evaluated as usual</a>
 in the calling goroutine, but
@@ -4368,7 +4538,7 @@ cases all referring to communication operations.
 SelectStmt = "select" "{" { CommClause } "}" .
 CommClause = CommCase ":" { Statement ";" } .
 CommCase   = "case" ( SendStmt | RecvStmt ) | "default" .
-RecvStmt   = [ Expression [ "," Expression ] ( "=" | ":=" ) ] RecvExpr .
+RecvStmt   = [ ExpressionList "=" | IdentifierList ":=" ] RecvExpr .
 RecvExpr   = Expression .
 </pre>
 
@@ -4385,7 +4555,8 @@ If any of the resulting operations can proceed, one of those is
 chosen and the corresponding communication and statements are
 evaluated.  Otherwise, if there is a default case, that executes;
 if there is no default case, the statement blocks until one of the communications can
-complete.
+complete. There can be at most one default case and it may appear anywhere in the
+"select" statement.
 If there are no cases with non-<code>nil</code> channels,
 the statement blocks forever.
 Even if the statement blocks,
@@ -4437,8 +4608,10 @@ select {}  // block forever
 <h3 id="Return_statements">Return statements</h3>
 
 <p>
-A "return" statement terminates execution of the containing function
-and optionally provides a result value or values to the caller.
+A "return" statement in a function <code>F</code> terminates the execution
+of <code>F</code>, and optionally provides one or more result values.
+Any functions <a href="#Defer_statements">deferred</a> by <code>F</code>
+are executed before <code>F</code> returns to its caller.
 </p>
 
 <pre class="ebnf">
@@ -4488,7 +4661,7 @@ func complexF2() (re float64, im float64) {
 </pre>
 	</li>
 	<li>The expression list may be empty if the function's result
-		type specifies names for its result parameters (§<a href="#Function_types">Function Types</a>).
+		type specifies names for its result parameters (§<a href="#Function_types">Function types</a>).
 		The result parameters act as ordinary local variables
 		and the function may assign values to them as necessary.
 		The "return" statement returns the values of these variables.
@@ -4508,7 +4681,10 @@ func (devnull) Write(p []byte) (n int, _ error) {
 </ol>
 
 <p>
-Regardless of how they are declared, all the result values are initialized to the zero values for their type (§<a href="#The_zero_value">The zero value</a>) upon entry to the function.
+Regardless of how they are declared, all the result values are initialized to the zero
+values for their type (§<a href="#The_zero_value">The zero value</a>) upon entry to the
+function. A "return" statement that specifies results sets the result parameters before
+any deferred functions are executed.
 </p>
 
 <!--
@@ -4534,7 +4710,8 @@ BreakStmt = "break" [ Label ] .
 If there is a label, it must be that of an enclosing
 "for", "switch" or "select" statement, and that is the one whose execution
 terminates
-(§<a href="#For_statements">For statements</a>, §<a href="#Switch_statements">Switch statements</a>, §<a href="#Select_statements">Select statements</a>).
+(§<a href="#For_statements">For statements</a>, §<a href="#Switch_statements">Switch statements</a>,
+§<a href="#Select_statements">Select statements</a>).
 </p>
 
 <pre>
@@ -4623,9 +4800,8 @@ the "for" statement's block but the <code>goto</code> is not.
 
 <p>
 A "fallthrough" statement transfers control to the first statement of the
-next case clause in a expression "switch" statement (§<a href="#Expression_switches">Expression switches</a>). It may
-be used only as the final non-empty statement in a case or default clause in an
-expression "switch" statement.
+next case clause in a <a href="#Expression_switches">expression "switch" statement</a>.
+It may be used only as the final non-empty statement in such a clause.
 </p>
 
 <pre class="ebnf">
@@ -4636,8 +4812,11 @@ FallthroughStmt = "fallthrough" .
 <h3 id="Defer_statements">Defer statements</h3>
 
 <p>
-A "defer" statement invokes a function whose execution is deferred to the moment
-the surrounding function returns.
+A "defer" statement invokes a function whose execution is deferred
+to the moment the surrounding function returns, either because the
+surrounding function executed a <a href="#Return_statements">return statement</a>,
+reached the end of its <a href="#Function_declarations">function body</a>,
+or because the corresponding goroutine is <a href="#Handling_panics">panicking</a>.
 </p>
 
 <pre class="ebnf">
@@ -4645,22 +4824,30 @@ DeferStmt = "defer" Expression .
 </pre>
 
 <p>
-The expression must be a function or method call.
+The expression must be a function or method call; it cannot be parenthesized.
+Calls of built-in functions are restricted as for
+<a href="#Expression_statements">expression statements</a>.
+</p>
+
+<p>
 Each time the "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 is not invoked.
-Instead, deferred calls are executed in LIFO order
-immediately before the surrounding function returns,
-after the return values, if any, have been evaluated, but before they
-are returned to the caller. For instance, if the deferred function is
+and saved anew but the actual function body is not executed.
+Instead, deferred functions are executed immediately before
+the surrounding function returns, in the reverse order
+they were deferred.
+</p>
+
+<p>
+For instance, if the deferred function is
 a <a href="#Function_literals">function literal</a> and the surrounding
 function has <a href="#Function_types">named result parameters</a> that
 are in scope within the literal, the deferred function may access and modify
 the result parameters before they are returned.
 If the deferred function has any return values, they are discarded when
 the function completes.
+(See also the section on <a href="#Handling_panics">handling panics</a>.)
 </p>
 
 <pre>
@@ -4698,7 +4885,7 @@ they cannot be used as function values.
 
 <pre class="ebnf">
 BuiltinCall = identifier "(" [ BuiltinArgs [ "," ] ] ")" .
-BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList .
+BuiltinArgs = Type [ "," ArgumentList ] | ArgumentList .
 </pre>
 
 <h3 id="Close">Close</h3>
@@ -4750,7 +4937,8 @@ At any time the following relationship holds:
 </pre>
 
 <p>
-The length and capacity of a <code>nil</code> slice, map, or channel are 0.
+The length of a <code>nil</code> slice, map or channel is 0.
+The capacity of a <code>nil</code> slice and channel is 0.
 </p>
 
 <p>
@@ -4822,15 +5010,20 @@ make(T, n)       channel    asynchronous channel of type T, buffer size n
 
 
 <p>
-The arguments <code>n</code> and <code>m</code> must be of integer type.
-A <a href="#Run_time_panics">run-time panic</a> occurs if <code>n</code>
-is negative or larger than <code>m</code>, or if <code>n</code> or
-<code>m</code> cannot be represented by an <code>int</code>.
+The size arguments <code>n</code> and <code>m</code> must be integer values.
+A <a href="#Constants">constant</a> size argument must be non-negative and
+representable by a value of type <code>int</code>.
+If both <code>n</code> and <code>m</code> are provided and are constant, then
+<code>n</code> must be no larger than <code>m</code>.
+If <code>n</code> is negative or larger than <code>m</code> at run time,
+a <a href="#Run_time_panics">run-time panic</a> occurs.
 </p>
 
 <pre>
 s := make([]int, 10, 100)       // slice with len(s) == 10, cap(s) == 100
-s := make([]int, 10)            // slice with len(s) == cap(s) == 10
+s := make([]int, 1e3)           // slice with len(s) == cap(s) == 1000
+s := make([]int, 1<<63)         // illegal: len(s) is not representable by a value of type int
+s := make([]int, 10, 0)         // illegal: len(s) > cap(s)
 c := make(chan int, 10)         // channel with a buffer size of 10
 m := make(map[string]int, 100)  // map with initial space for 100 elements
 </pre>
@@ -4839,7 +5032,10 @@ m := make(map[string]int, 100)  // map with initial space for 100 elements
 <h3 id="Appending_and_copying_slices">Appending to and copying slices</h3>
 
 <p>
-Two built-in functions assist in common slice operations.
+The built-in functions <code>append</code> and <code>copy</code> assist in
+common slice operations.
+For both functions, the result is independent of whether the memory referenced
+by the arguments overlaps.
 </p>
 
 <p>
@@ -4870,21 +5066,22 @@ slice may refer to a different underlying array.
 
 <pre>
 s0 := []int{0, 0}
-s1 := append(s0, 2)        // append a single element     s1 == []int{0, 0, 2}
-s2 := append(s1, 3, 5, 7)  // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
-s3 := append(s2, s0...)    // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}
+s1 := append(s0, 2)                // append a single element     s1 == []int{0, 0, 2}
+s2 := append(s1, 3, 5, 7)          // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
+s3 := append(s2, s0...)            // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}
+s4 := append(s3[3:6], s3[2:]...)   // append overlapping slice    s4 == []int{3, 5, 7, 2, 3, 5, 7, 0, 0}
 
 var t []interface{}
-t = append(t, 42, 3.1415, "foo")                          t == []interface{}{42, 3.1415, "foo"}
+t = append(t, 42, 3.1415, "foo")                                  t == []interface{}{42, 3.1415, "foo"}
 
 var b []byte
-b = append(b, "bar"...)  // append string contents      b == []byte{'b', 'a', 'r' }
+b = append(b, "bar"...)            // append string contents      b == []byte{'b', 'a', 'r' }
 </pre>
 
 <p>
 The function <code>copy</code> copies slice elements from
 a source <code>src</code> to a destination <code>dst</code> and returns the
-number of elements copied. Source and destination may overlap.
+number of elements copied.
 Both arguments must have <a href="#Type_identity">identical</a> element type <code>T</code> and must be
 <a href="#Assignability">assignable</a> to a slice of type <code>[]T</code>.
 The number of elements copied is the minimum of
@@ -4927,9 +5124,8 @@ delete(m, k)  // remove element m[k] from map m
 </pre>
 
 <p>
-If the element <code>m[k]</code> does not exist, <code>delete</code> is
-a no-op. Calling <code>delete</code> with a nil map causes a
-<a href="#Run_time_panics">run-time panic</a>.
+If the map <code>m</code> is <code>nil</code> or the element <code>m[k]</code>
+does not exist, <code>delete</code> is a no-op.
 </p>
 
 
@@ -4988,18 +5184,16 @@ func recover() interface{}
 </pre>
 
 <p>
-When a function <code>F</code> calls <code>panic</code>, normal
-execution of <code>F</code> stops immediately.  Any functions whose
-execution was <a href="#Defer_statements">deferred</a> by the
-invocation of <code>F</code> are run in the usual way, and then
-<code>F</code> returns to its caller.  To the caller, <code>F</code>
-then behaves like a call to <code>panic</code>, terminating its own
-execution and running deferred functions.  This continues until all
-functions in the goroutine have ceased execution, in reverse order.
-At that point, the program is
-terminated and the error condition is reported, including the value of
-the argument to <code>panic</code>.  This termination sequence is
-called <i>panicking</i>.
+A <code>panic</code> call in a function <code>F</code> terminates the execution
+of <code>F</code>.
+Any functions <a href="#Defer_statements">deferred</a> by <code>F</code>
+are executed before <code>F</code> returns to its caller. To the caller,
+the call of <code>F</code> then behaves itself like a call to <code>panic</code>,
+terminating its own execution and running deferred functions in the same manner.
+This continues until all functions in the goroutine have ceased execution,
+in reverse order. At that point, the program is terminated and the error
+condition is reported, including the value of the argument to <code>panic</code>.
+This termination sequence is called <i>panicking</i>.
 </p>
 
 <pre>
@@ -5112,7 +5306,7 @@ An implementation may require that all source files for a package inhabit the sa
 An import declaration states that the source file containing the declaration
 depends on functionality of the <i>imported</i> package
 (<a href="#Program_initialization_and_execution">§Program initialization and execution</a>)
-and it enables access to <a href="#Exported_identifiers">exported</a> identifiers
+and enables access to <a href="#Exported_identifiers">exported</a> identifiers
 of that package.
 The import names an identifier (PackageName) to be used for access and an ImportPath
 that specifies the package to be imported.
@@ -5145,7 +5339,7 @@ package and may be relative to a repository of installed packages.
 <p>
 Implementation restriction: A compiler may restrict ImportPaths to
 non-empty strings using only characters belonging to
-<a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode's</a>
+<a href="http://www.unicode.org/versions/Unicode6.2.0/">Unicode's</a>
 L, M, N, P, and S general categories (the Graphic characters without
 spaces) and may also exclude the characters
 <code>!"#$%&'()*,:;<=>?[\]^`{|}</code>
@@ -5166,7 +5360,7 @@ various types of import declaration.
 Import declaration          Local name of Sin
 
 import   "lib/math"         math.Sin
-import M "lib/math"         M.Sin
+import m "lib/math"         m.Sin
 import . "lib/math"         Sin
 </pre>
 
@@ -5292,8 +5486,10 @@ func init()
 </pre>
 <p>
 defined in its source.
-A package may contain multiple
-<code>init</code> functions, even
+A package-scope or file-scope identifier
+with name <code>init</code> may only be
+declared to be a function with this signature.
+Multiple such functions may be defined, even
 within a single source file; they execute
 in unspecified order.
 </p>
@@ -5430,16 +5626,26 @@ func Sizeof(variable ArbitraryType) uintptr
 </pre>
 
 <p>
-Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted into
-a <code>Pointer</code> and vice versa.
+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.
 </p>
+
+<pre>
+var f float64
+bits = *(*uint64)(unsafe.Pointer(&f))
+
+type ptr unsafe.Pointer
+bits = *(*uint64)(ptr(&f))
+</pre>
+
 <p>
-The function <code>Sizeof</code> takes an expression denoting a
-variable of any type and returns the size of the variable in bytes.
+The functions <code>Alignof</code> and <code>Sizeof</code> take an expression <code>x</code>
+of any type and return the alignment or size, respectively, of a hypothetical variable <code>v</code>
+as if <code>v</code> was declared via <code>var v = x</code>.
 </p>
 <p>
-The function <code>Offsetof</code> takes a selector (§<a href="#Selectors">Selectors</a>) denoting a struct
-field of any type and returns the field offset in bytes relative to the
+The function <code>Offsetof</code> takes a (possibly parenthesized) <a href="#Selectors">selector</a>
+denoting a struct field of any type and returns the field offset in bytes relative to the
 struct's address.
 For a struct <code>s</code> with field <code>f</code>:
 </p>
@@ -5465,7 +5671,6 @@ uintptr(unsafe.Pointer(&x)) % unsafe.Alignof(x) == 0
 Calls to <code>Alignof</code>, <code>Offsetof</code>, and
 <code>Sizeof</code> are compile-time constant expressions of type <code>uintptr</code>.
 </p>
-<p>
 
 <h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3>
 
diff --git a/doc/godocs.js b/doc/godocs.js
index 8fd32fe..5d12da1 100644
--- a/doc/godocs.js
+++ b/doc/godocs.js
@@ -1,213 +1,195 @@
-// Except as noted, this content is licensed under Creative Commons
-// Attribution 3.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.
 
 /* A little code to ease navigation of these documents.
  *
  * On window load we:
- *  + Generate a table of contents (godocs_generateTOC)
- *  + Add links up to the top of the doc from each section (godocs_addTopLinks)
+ *  + Bind search box hint placeholder show/hide events (bindSearchEvents)
+ *  + Generate a table of contents (generateTOC)
+ *  + Bind foldable sections (bindToggles)
+ *  + Bind links to foldable sections (bindToggleLinks)
  */
 
-/* We want to do some stuff on page load (after the HTML is rendered).
-   So listen for that:
- */
-function bindEvent(el, e, fn) {
-  if (el.addEventListener){
-    el.addEventListener(e, fn, false);
-  } else if (el.attachEvent){
-    el.attachEvent('on'+e, fn);
-  }
-}
+(function() {
+'use strict';
 
-function godocs_bindSearchEvents() {
-  var search = document.getElementById('search');
-  if (!search) {
-    // no search box (index disabled)
-    return;
+function bindSearchEvents() {
+
+  var search = $('#search');
+  if (search.length === 0) {
+    return; // no search box
   }
+
   function clearInactive() {
-    if (search.className == "inactive") {
-      search.value = "";
-      search.className = "";
+    if (search.is('.inactive')) {
+      search.val('');
+      search.removeClass('inactive');
     }
   }
+
   function restoreInactive() {
-    if (search.value !== "") {
+    if (search.val() !== '') {
       return;
     }
-    if (search.type != "search") {
-      search.value = search.getAttribute("placeholder");
-    }
-    search.className = "inactive";
+    search.val(search.attr('placeholder'));
+    search.addClass('inactive');
   }
+
+  search.on('focus', clearInactive);
+  search.on('blur', restoreInactive);
+
   restoreInactive();
-  bindEvent(search, 'focus', clearInactive);
-  bindEvent(search, 'blur', restoreInactive);
 }
 
-/* Returns the "This sweet header" from <h2>This <i>sweet</i> header</h2>.
- * Takes a node, returns a string.
+/* Generates a table of contents: looks for h2 and h3 elements and generates
+ * links. "Decorates" the element with id=="nav" with this table of contents.
  */
-function godocs_nodeToText(node) {
-  var TEXT_NODE = 3; // Defined in Mozilla but not MSIE :(
-
-  var text = '';
-  for (var j = 0; j != node.childNodes.length; j++) {
-    var child = node.childNodes[j];
-    if (child.nodeType == TEXT_NODE) {
-      if (child.nodeValue != '[Top]') { //ok, that's a hack, but it works.
-        text = text + child.nodeValue;
-      }
-    } else {
-      text = text + godocs_nodeToText(child);
-    }
+function generateTOC() {
+  if ($('#manual-nav').length > 0) {
+    return;
   }
-  return text;
-}
 
-/* Generates a table of contents: looks for h2 and h3 elements and generates
- * links.  "Decorates" the element with id=="nav" with this table of contents.
- */
-function godocs_generateTOC() {
-  if (document.getElementById('manual-nav')) { return; }
-  var navbar = document.getElementById('nav');
-  if (!navbar) { return; }
+  var nav = $('#nav');
+  if (nav.length === 0) {
+    return;
+  }
 
   var toc_items = [];
-
-  var i;
-  var seenNav = false;
-  for (i = 0; i < navbar.parentNode.childNodes.length; i++) {
-    var node = navbar.parentNode.childNodes[i];
-    if (!seenNav) { 
-      if (node.id == 'nav') {
-        seenNav = true;
-      }
-      continue;
-    }
-    if ((node.tagName != 'h2') && (node.tagName != 'H2') &&
-        (node.tagName != 'h3') && (node.tagName != 'H3')) {
-      continue;
-    }
-    if (!node.id) {
-      node.id = 'tmp_' + i;
-    }
-    var text = godocs_nodeToText(node);
-    if (!text) { continue; }
-
-    var textNode = document.createTextNode(text);
-
-    var link = document.createElement('a');
-    link.href = '#' + node.id;
-    link.appendChild(textNode);
-
-    // Then create the item itself
+  $(nav).nextAll('h2, h3').each(function() {
+    var node = this;
+    if (node.id == '')
+      node.id = 'tmp_' + toc_items.length;
+    var link = $('<a/>').attr('href', '#' + node.id).text($(node).text());
     var item;
-    if ((node.tagName == 'h2') || (node.tagName == 'H2')) {
-      item = document.createElement('dt');
+    if ($(node).is('h2')) {
+      item = $('<dt/>');
     } else { // h3
-      item = document.createElement('dd');
+      item = $('<dd/>');
     }
-
-    item.appendChild(link);
+    item.append(link);
     toc_items.push(item);
+  });
+  if (toc_items.length <= 1) {
+    return;
   }
 
-  if (toc_items.length <= 1) { return; }
-
-  var dl1 = document.createElement('dl');
-  var dl2 = document.createElement('dl');
+  var dl1 = $('<dl/>');
+  var dl2 = $('<dl/>');
 
   var split_index = (toc_items.length / 2) + 1;
   if (split_index < 8) {
     split_index = toc_items.length;
   }
-
-  for (i = 0; i < split_index; i++) {
-    dl1.appendChild(toc_items[i]);
+  for (var i = 0; i < split_index; i++) {
+    dl1.append(toc_items[i]);
   }
   for (/* keep using i */; i < toc_items.length; i++) {
-    dl2.appendChild(toc_items[i]);
+    dl2.append(toc_items[i]);
   }
 
-  var tocTable = document.createElement('table');
-  navbar.appendChild(tocTable);
-  tocTable.className = 'unruled';
-  var tocBody = document.createElement('tbody');
-  tocTable.appendChild(tocBody);
-
-  var tocRow = document.createElement('tr');
-  tocBody.appendChild(tocRow);
+  var tocTable = $('<table class="unruled"/>').appendTo(nav);
+  var tocBody = $('<tbody/>').appendTo(tocTable);
+  var tocRow = $('<tr/>').appendTo(tocBody);
 
   // 1st column
-  var tocCell = document.createElement('td');
-  tocCell.className = 'first';
-  tocRow.appendChild(tocCell);
-  tocCell.appendChild(dl1);
-
+  $('<td class="first"/>').appendTo(tocRow).append(dl1);
   // 2nd column
-  tocCell = document.createElement('td');
-  tocRow.appendChild(tocCell);
-  tocCell.appendChild(dl2);
-}
-
-function getElementsByClassName(base, clazz) {
-  if (base.getElementsByClassName) {
-    return base.getElementsByClassName(clazz);
-  }
-  var elements = base.getElementsByTagName('*'), foundElements = [];
-  for (var n in elements) {
-    if (clazz == elements[n].className) {
-      foundElements.push(elements[n]);
-    }
-  }
-  return foundElements;
+  $('<td/>').appendTo(tocRow).append(dl2);
 }
 
-function godocs_bindToggle(el) {
-  var button = getElementsByClassName(el, "toggleButton");
-  var callback = function() {
-    if (el.className == "toggle") {
-      el.className = "toggleVisible";
+function bindToggle(el) {
+  $('.toggleButton', el).click(function() {
+    if ($(el).is('.toggle')) {
+      $(el).addClass('toggleVisible').removeClass('toggle');
     } else {
-      el.className = "toggle";
+      $(el).addClass('toggle').removeClass('toggleVisible');
     }
-  };
-  for (var i = 0; i < button.length; i++) {
-    bindEvent(button[i], "click", callback);
-  }
+  });
 }
-function godocs_bindToggles(className) {
-  var els = getElementsByClassName(document, className);
-  for (var i = 0; i < els.length; i++) {
-    godocs_bindToggle(els[i]);
-  }
+function bindToggles(selector) {
+  $(selector).each(function(i, el) {
+    bindToggle(el);
+  });
 }
-function godocs_bindToggleLink(l, prefix) {
-  bindEvent(l, "click", function() {
-    var i = l.href.indexOf("#"+prefix);
+
+function bindToggleLink(el, prefix) {
+  $(el).click(function() {
+    var href = $(el).attr('href');
+    var i = href.indexOf('#'+prefix);
     if (i < 0) {
       return;
     }
-    var id = prefix + l.href.slice(i+1+prefix.length);
-    var eg = document.getElementById(id);
-    eg.className = "toggleVisible";
+    var id = '#' + prefix + href.slice(i+1+prefix.length);
+    if ($(id).is('.toggle')) {
+      $(id).find('.toggleButton').first().click();
+    }
   });
 }
-function godocs_bindToggleLinks(className, prefix) {
-  var links = getElementsByClassName(document, className);
-  for (i = 0; i < links.length; i++) {
-    godocs_bindToggleLink(links[i], prefix);
+function bindToggleLinks(selector, prefix) {
+  $(selector).each(function(i, el) {
+    bindToggleLink(el, prefix);
+  });
+}
+
+function setupDropdownPlayground() {
+  if (!$('#page').is('.wide')) {
+    return; // don't show on front page
   }
+  var button = $('#playgroundButton');
+  var div = $('#playground');
+  var setup = false;
+  button.toggle(function() {
+    button.addClass('active');
+    div.show();
+    if (setup) {
+      return;
+    }
+    setup = true;
+    playground({
+      'codeEl': $('.code', div),
+      'outputEl': $('.output', div),
+      'runEl': $('.run', div),
+      'fmtEl': $('.fmt', div),
+      'shareEl': $('.share', div),
+      'shareRedirect': 'http://play.golang.org/p/'
+    });
+  },
+  function() {
+    button.removeClass('active');
+    div.hide();
+  });
+  button.show();
+  $('#menu').css('min-width', '+=60');
 }
 
-function godocs_onload() {
-  godocs_bindSearchEvents();
-  godocs_generateTOC();
-  godocs_bindToggles("toggle");
-  godocs_bindToggles("toggleVisible");
-  godocs_bindToggleLinks("exampleLink", "example_");
-  godocs_bindToggleLinks("overviewLink", "");
+// fixFocus tries to put focus to div#page so that keyboard navigation works.
+function fixFocus() {
+  var page = $('div#page');
+  var topbar = $('div#topbar');
+  page.css('outline', 0); // disable outline when focused
+  page.attr('tabindex', -1); // and set tabindex so that it is focusable
+  $(window).resize(function (evt) {
+    // only focus page when the topbar is at fixed position (that is, it's in
+    // front of page, and keyboard event will go to the former by default.)
+    // by focusing page, keyboard event will go to page so that up/down arrow,
+    // space, etc. will work as expected.
+    if (topbar.css('position') == "fixed")
+      page.focus();
+  }).resize();
 }
 
-bindEvent(window, 'load', godocs_onload);
+$(document).ready(function() {
+  bindSearchEvents();
+  generateTOC();
+  bindToggles(".toggle");
+  bindToggles(".toggleVisible");
+  bindToggleLinks(".exampleLink", "example_");
+  bindToggleLinks(".overviewLink", "");
+  bindToggleLinks(".examplesLink", "");
+  bindToggleLinks(".indexLink", "");
+  setupDropdownPlayground();
+  fixFocus();
+});
+
+})();
diff --git a/doc/gopher/pencil/gopherhat.jpg b/doc/gopher/pencil/gopherhat.jpg
new file mode 100644
index 0000000..f34d7b3
Binary files /dev/null and b/doc/gopher/pencil/gopherhat.jpg differ
diff --git a/doc/gopher/pencil/gopherhelmet.jpg b/doc/gopher/pencil/gopherhelmet.jpg
new file mode 100644
index 0000000..c7b6c61
Binary files /dev/null and b/doc/gopher/pencil/gopherhelmet.jpg differ
diff --git a/doc/gopher/pencil/gophermega.jpg b/doc/gopher/pencil/gophermega.jpg
new file mode 100644
index 0000000..779fb07
Binary files /dev/null and b/doc/gopher/pencil/gophermega.jpg differ
diff --git a/doc/gopher/pencil/gopherrunning.jpg b/doc/gopher/pencil/gopherrunning.jpg
new file mode 100644
index 0000000..eeeddf1
Binary files /dev/null and b/doc/gopher/pencil/gopherrunning.jpg differ
diff --git a/doc/gopher/pencil/gopherswim.jpg b/doc/gopher/pencil/gopherswim.jpg
new file mode 100644
index 0000000..2f32877
Binary files /dev/null and b/doc/gopher/pencil/gopherswim.jpg differ
diff --git a/doc/gopher/pencil/gopherswrench.jpg b/doc/gopher/pencil/gopherswrench.jpg
new file mode 100644
index 0000000..93005f4
Binary files /dev/null and b/doc/gopher/pencil/gopherswrench.jpg differ
diff --git a/doc/help.html b/doc/help.html
index fadf80a..3478b9e 100644
--- a/doc/help.html
+++ b/doc/help.html
@@ -28,11 +28,17 @@ archives and consult the <a href="/doc/go_faq.html">FAQ</a> and
 <p>Get live support at <b>#go-nuts</b> on <b>irc.freenode.net</b>, the official
 Go IRC channel.</p>
 
+<h3 id="pluscom"><a href="https://plus.google.com/communities/114112804251407510571">The Go+ community</a></h3>
+<p>The Google+ community for Go enthusiasts.</p>
+
+<h3 id="plus"><a href="https://plus.google.com/101406623878176903605/posts">The Go Programming Language at Google+</a></h3>
+<p>The Go project's Google+ page.</p>
+
 <h3 id="twitter"><a href="http://twitter.com/go_nuts">@go_nuts at Twitter</a></h3>
 <p>The Go project's official Twitter account.</p>
 <p>Tweeting your about problem with the <code>#golang</code> hashtag usually
 generates some helpful responses.</p>
 
-<h3 id="plus"><a href="https://plus.google.com/101406623878176903605/posts">The Go Programming Language at Google+</a></h3>
-<p>The Go project's Google+ page.</p>
-
+<h3 id="blog"><a href="http://blog.golang.org/">The Go Blog</a></h3>
+<p>The official blog of the Go project, featuring news and in-depth articles by
+the Go team and guests.</p>
diff --git a/doc/install-source.html b/doc/install-source.html
index 87c187b..ee7b39b 100644
--- a/doc/install-source.html
+++ b/doc/install-source.html
@@ -57,8 +57,7 @@ architectures.
 	<code>arm</code> (a.k.a. <code>ARM</code>); <code>5g,5l,5c,5a</code>
 </dt>
 <dd>
-	Supports only Linux binaries. Less widely used than the other ports and therefore
-	not as thoroughly tested.
+	Supports only Linux binaries. Less widely used than the other ports and therefore not as thoroughly tested.
 </dd>
 </dl>
 
@@ -81,25 +80,9 @@ The full set of supported combinations is listed in the discussion of
 <h2 id="ctools">Install C tools, if needed</h2>
 
 <p>
-The Go tool chain is written in C.
-To build it, you need a C compiler installed.
-</p>
-
-<p>
-On OS X, a C compiler can be installed as part of
-<a href="http://developer.apple.com/Xcode/">Xcode</a>. 
-</p>
-
-<p>
-On Ubuntu/Debian, use <code>sudo apt-get install gcc libc6-dev</code>.
-If you want to build 32-bit binaries on a 64-bit system you'll also need the
-<code>libc6-dev-i386</code> package.
-</p>
-
-<p>
-On Windows, install <code>gcc</code> with
-<a href="http://www.mingw.org/">MinGW</a>.
-(Make sure you add its <code>bin</code> subdirectory to your <code>PATH</code>.)
+The Go tool chain is written in C. To build it, you need a C compiler installed. 
+Please refer to the <a href="http://code.google.com/p/go-wiki/wiki/InstallFromSource#Install_C_tools">InstallFromSource</a>
+page on the Go community Wiki for operating system specific instructions.
 </p>
 
 <h2 id="mercurial">Install Mercurial, if needed</h2>
@@ -144,6 +127,18 @@ Then check out the repository:</p>
 $ hg clone -u release https://code.google.com/p/go
 </pre>
 
+<h2 id="head">(Optional) Switch to the default branch</h2>
+
+<p>If you intend to modify the go source code, and
+<a href="/doc/contribute.html">contribute your changes</a>
+to the project, then move your repository
+off the release branch, and onto the default (development) branch.
+Otherwise, skip this step.</p>
+
+<pre>
+$ hg update default
+</pre>
+
 <h2 id="install">Install Go</h2>
 
 <p>
@@ -218,6 +213,12 @@ hello, world
 If you see the "hello, world" message then Go is installed correctly.
 </p>
 
+<h2 id="gopath">Set up your work environment</h2>
+
+<p>
+The document <a href="/doc/code.html">How to Write Go Code</a> explains how to
+set up a work environment in which to build and test Go code.
+</p>
 
 <h2 id="community">Community resources</h2>
 
@@ -241,8 +242,8 @@ Bugs can be reported using the <a href="http://code.google.com/p/go/issues/list"
 <h2 id="releases">Keeping up with releases</h2>
 
 <p>
-The Go project maintains two stable tags in its Mercurial repository:
-<code>release</code> and <code>weekly</code>.
+The Go project maintains a stable tag in its Mercurial repository:
+<code>release</code>.
 </p>
 
 <p>
@@ -263,12 +264,6 @@ $ hg update release
 $ ./all.bash
 </pre>
 
-<p>
-The <code>weekly</code> tag is updated about once a week, and should be used 
-only by those who are actively working on the Go core.
-To use the <code>weekly</code> tag run <code>hg update weekly</code> instead.
-</p>
-
 
 <h2 id="environment">Optional environment variables</h2>
 
diff --git a/doc/install.html b/doc/install.html
index b856836..03b13c0 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -40,14 +40,20 @@ proceeding. If your OS or architecture is not on the list, it's possible that
 <th align="middle">Notes</th>
 </tr>
 <tr><td colspan="3"><hr></td></tr>
-<tr><td>FreeBSD 7 or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
-<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; no binary distribution for ARM yet</tr>
-<tr><td>Mac OS X 10.6/10.7</td> <td>amd64, 386</td> <td>use the gcc<sup>†</sup> that comes with Xcode</td></tr>
+<tr><td>FreeBSD 7 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/10.7</td> <td>amd64, 386</td> <td>use the gcc<sup>†</sup> that comes with Xcode<sup>‡</sup></td></tr>
 <tr><td>Windows 2000 or later</td> <td>amd64, 386</td> <td>use mingw gcc<sup>†</sup>; cygwin or msys is not needed</td></tr>
+<tr><td>NetBSD 6 or later</td> <td>amd64, 386</td> <td></td></tr>
 </table>
 
 <p>
-<sup>†</sup><code>gcc</code> is required only if you plan to use <a href="/cmd/cgo">cgo</a>.
+<sup>†</sup><code>gcc</code> is required only if you plan to use
+<a href="/cmd/cgo">cgo</a>.<br/>
+<sup>‡</sup>You only need to install the command line tools for
+<a href="http://developer.apple.com/Xcode/">Xcode</a>. If you have already
+installed Xcode 4.3+, you can install it from the Components tab of the
+Downloads preferences panel.
 </p>
 
 <h2 id="download">Download the Go tools</h2>
@@ -61,7 +67,7 @@ your operating system and processor architecture.
 
 <p>
 Official binary distributions are available
-for the FreeBSD, Linux, Mac OS X (Snow Leopard/Lion), and Windows operating systems
+for the FreeBSD, Linux, Mac OS X (Snow Leopard/Lion), NetBSD, and Windows operating systems
 and the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>)
 x86 processor architectures.
 </p>
@@ -98,10 +104,10 @@ Windows users should read the section about <a href="#windows_env">setting
 environment variables under Windows</a>.
 </p>
 
-<h3 id="freebsd_linux">FreeBSD and Linux</h3>
+<h3 id="bsd_linux">FreeBSD, Linux, Mac OS X and NetBSD tarballs</h3>
 
 <p>
-On FreeBSD and Linux, if you are upgrading from an older version of Go you must
+If you are upgrading from an older version of Go you must
 first remove the existing version from <code>/usr/local/go</code>:
 </p>
 
@@ -110,15 +116,21 @@ rm -r /usr/local/go
 </pre>
 
 <p>
-Extract <a href="http://code.google.com/p/go/downloads/list?q=OpSys-FreeBSD+OR+OpSys-Linux">the archive</a>
-into <code>/usr/local</code>, creating a Go tree in <code>/usr/local/go</code>:
+Extract <a href="http://code.google.com/p/go/downloads/list?q=OpSys-FreeBSD+OR+OpSys-Linux+OR+OpSys-OSX+OR+OpSys-NetBSD+Type-Archive">the archive</a>
+into <code>/usr/local</code>, creating a Go tree in <code>/usr/local/go</code>.
+For example:
 </p>
 
 <pre>
-tar -C /usr/local -xzf go.release.go1.tar.gz
+tar -C /usr/local -xzf go1.0.3.linux-amd64.tar.gz
 </pre>
 
 <p>
+The name of the archive may differ, depending on the version of Go you are
+installing and your system's operating system and processor architecture.
+</p>
+
+<p>
 (Typically these commands must be run as root or through <code>sudo</code>.)
 </p>
 
@@ -132,10 +144,10 @@ variable. You can do this by adding this line to your <code>/etc/profile</code>
 export PATH=$PATH:/usr/local/go/bin
 </pre>
 
-<h3 id="osx">Mac OS X</h3>
+<h3 id="osx">Mac OS X package installer</h3>
 
 <p>
-Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Darwin">package file</a>
+Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-OSX+Type-Installer">package file</a>
 and follow the prompts to install the Go tools.
 The package installs the Go distribution to <code>/usr/local/go</code>.
 </p>
@@ -155,7 +167,7 @@ a zip archive that requires you to set some environment variables and an
 experimental MSI installer that configures your installation automatically.
 </p>
 
-<h4 id="windows_zip">Zip archive</h3>
+<h4 id="windows_zip">Zip archive</h4>
 
 <p>
 Extract the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Windows+Type%3DArchive">zip file</a>
@@ -171,7 +183,7 @@ the <code>GOROOT</code> environment variable to your chosen path.
 Add the <code>bin</code> subdirectory of your Go root (for example, <code>c:\Go\bin</code>) to to your <code>PATH</code> environment variable.
 </p>
 
-<h4 id="windows_msi">MSI installer (experimental)</h3>
+<h4 id="windows_msi">MSI installer (experimental)</h4>
 
 <p>
 Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Windows+Type%3DInstaller">MSI file</a>
@@ -227,15 +239,17 @@ hello, world
 If you see the "hello, world" message then your Go installation is working.
 </p>
 
-<h2 id="next">What's next</h2>
+<h2 id="gopath">Set up your work environment</h2>
 
 <p>
-Start by taking <a href="http://code.google.com/p/go-tour/">A Tour of Go</a>.
+The document <a href="/doc/code.html">How to Write Go Code</a> explains how to
+set up a work environment in which to build and test Go code.
 </p>
 
+<h2 id="next">What's next</h2>
+
 <p>
-For more detail about the process of building and testing Go programs
-read <a href="/doc/code.html">How to Write Go Code</a>.
+Start by taking <a href="http://code.google.com/p/go-tour/">A Tour of Go</a>.
 </p>
 
 <p>
diff --git a/doc/jquery.js b/doc/jquery.js
new file mode 100644
index 0000000..bc3fbc8
--- /dev/null
+++ b/doc/jquery.js
@@ -0,0 +1,2 @@
+/*! jQuery v1.8.2 jquery.com | jquery.org/license */
+(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(" ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);
\ No newline at end of file
diff --git a/doc/play/fib.go b/doc/play/fib.go
index 42da9ce..19e4721 100644
--- a/doc/play/fib.go
+++ b/doc/play/fib.go
@@ -1,5 +1,7 @@
 package main
 
+import "fmt"
+
 // fib returns a function that returns
 // successive Fibonacci numbers.
 func fib() func() int {
@@ -13,5 +15,5 @@ func fib() func() int {
 func main() {
 	f := fib()
 	// Function calls are evaluated left-to-right.
-	println(f(), f(), f(), f(), f())
+	fmt.Println(f(), f(), f(), f(), f())
 }
diff --git a/doc/play/playground.js b/doc/play/playground.js
index d7cc58d..7091366 100644
--- a/doc/play/playground.js
+++ b/doc/play/playground.js
@@ -3,23 +3,19 @@
 // license that can be found in the LICENSE file.
 
 // opts is an object with these keys
-// 	codeEl - code editor element 
-// 	outputEl - program output element
-// 	runEl - run button element
-// 	fmtEl - fmt button element (optional)
-// 	shareEl - share button element (optional)
-// 	shareURLEl - share URL text input element (optional)
-// 	shareRedirect - base URL to redirect to on share (optional)
-// 	preCompile - callback to mutate request data before compiling (optional)
-// 	postCompile - callback to read response data after compiling (optional)
-// 	simple - use plain textarea instead of CodeMirror. (optional)
-// 	toysEl - select element with a list of toys. (optional)
+//	codeEl - code editor element
+//	outputEl - program output element
+//	runEl - run button element
+//	fmtEl - fmt button element (optional)
+//	shareEl - share button element (optional)
+//	shareURLEl - share URL text input element (optional)
+//	shareRedirect - base URL to redirect to on share (optional)
+//	toysEl - toys select element (optional)
+//	enableHistory - enable using HTML5 history API (optional)
 function playground(opts) {
-	var simple = opts['simple'];
 	var code = $(opts['codeEl']);
-	var editor;
 
-	// autoindent helpers for simple mode.
+	// autoindent helpers.
 	function insertTabs(n) {
 		// find the selection start and end
 		var start = code[0].selectionStart;
@@ -49,12 +45,12 @@ function playground(opts) {
 			}
 		}
 		setTimeout(function() {
-			insertTabs(tabs, 1);
+			insertTabs(tabs);
 		}, 1);
 	}
 
 	function keyHandler(e) {
-		if (simple && e.keyCode == 9) { // tab
+		if (e.keyCode == 9) { // tab
 			insertTabs(1);
 			e.preventDefault();
 			return false;
@@ -64,58 +60,19 @@ function playground(opts) {
 				run();
 				e.preventDefault();
 				return false;
-			} else if (simple) {
+			} else {
 				autoindent(e.target);
 			}
 		}
 		return true;
 	}
-	if (simple) {
-		code.unbind('keydown').bind('keydown', keyHandler);
-	} else {
-		editor = CodeMirror.fromTextArea(
-			code[0],
-			{
-				lineNumbers: true,
-				indentUnit: 8,
-				indentWithTabs: true,
-				onKeyEvent: function(editor, e) { keyHandler(e); }
-			}
-		);
-	}
+	code.unbind('keydown').bind('keydown', keyHandler);
 	var output = $(opts['outputEl']);
 
-	function clearErrors() {
-		if (!editor) {
-			return;
-		}
-		var lines = editor.lineCount();
-		for (var i = 0; i < lines; i++) {
-			editor.setLineClass(i, null);
-		}
-	}
-	function highlightErrors(text) {
-		if (!editor) {
-			return;
-		}
-		var errorRe = /[a-z]+\.go:([0-9]+):/g;
-		var result;
-		while ((result = errorRe.exec(text)) != null) {
-			var line = result[1]*1-1;
-			editor.setLineClass(line, "errLine")
-		}
-	}
 	function body() {
-		if (editor) {
-			return editor.getValue();
-		}
 		return $(opts['codeEl']).val();
 	}
 	function setBody(text) {
-		if (editor) {
-			editor.setValue(text);
-			return;
-		}
 		$(opts['codeEl']).val(text);
 	}
 	function origin(href) {
@@ -126,24 +83,116 @@ function playground(opts) {
 			'<div class="loading">Waiting for remote server...</div>'
 		);
 	}
-	function setOutput(text, error) {
+	var playbackTimeout;
+	function playback(pre, events) {
+		function show(msg) {
+			// ^L clears the screen.
+			var msgs = msg.split("\x0c");
+			if (msgs.length == 1) {
+				pre.text(pre.text() + msg);
+				return;
+			}
+			pre.text(msgs.pop());
+		}
+		function next() {
+			if (events.length == 0) {
+				var exit = $('<span class="exit"/>');
+				exit.text("\nProgram exited.");
+				exit.appendTo(pre);
+				return;
+			}
+			var e = events.shift();
+			if (e.Delay == 0) {
+				show(e.Message);
+				next();
+			} else {
+				playbackTimeout = setTimeout(function() {
+					show(e.Message);
+					next();
+				}, e.Delay / 1000000);
+			}
+		}
+		next();
+	}
+	function stopPlayback() {
+		clearTimeout(playbackTimeout);
+	}
+	function setOutput(events, error) {
+		stopPlayback();
 		output.empty();
+		$(".lineerror").removeClass("lineerror");
+
+		// Display errors.
 		if (error) {
 			output.addClass("error");
+			var regex = /prog.go:([0-9]+)/g;
+			var r;
+			while (r = regex.exec(error)) {
+				$(".lines div").eq(r[1]-1).addClass("lineerror");
+			}
+			$("<pre/>").text(error).appendTo(output);
+			return;
+		}
+
+		// Display image output.
+		if (events.length > 0 && events[0].Message.indexOf("IMAGE:") == 0) {
+			var out = "";
+			for (var i = 0; i < events.length; i++) {
+				out += events[i].Message;
+			}
+			var url = "data:image/png;base64," + out.substr(6);
+			$("<img/>").attr("src", url).appendTo(output);
+			return;
+		}
+
+		// Play back events.
+		if (events !== null) {
+			var pre = $("<pre/>").appendTo(output);
+			playback(pre, events);
+		}
+	}
+
+	var pushedEmpty = (window.location.pathname == "/");
+	function inputChanged() {
+		if (pushedEmpty) {
+			return;
 		}
-		$("<pre/>").text(text).appendTo(output);
+		pushedEmpty = true;
+
+		$(opts['shareURLEl']).hide();
+		window.history.pushState(null, "", "/");
+	}
+
+	function popState(e) {
+		if (e == null) {
+			return;
+		}
+
+		if (e && e.state && e.state.code) {
+			setBody(e.state.code);
+		}
+	}
+
+	var rewriteHistory = false;
+
+	if (window.history &&
+		window.history.pushState &&
+		window.addEventListener &&
+		opts['enableHistory']) {
+		rewriteHistory = true;
+		code[0].addEventListener('input', inputChanged);
+		window.addEventListener('popstate', popState)
 	}
 
 	var seq = 0;
 	function run() {
-		clearErrors();
 		loading();
 		seq++;
 		var cur = seq;
-		var data = {"body": body()};
-		if (opts['preCompile']) {
-			opts['preCompile'](data);
-		}
+		var data = {
+			"version": 2,
+			"body": body()
+		};
 		$.ajax("/compile", {
 			data: data,
 			type: "POST",
@@ -152,34 +201,19 @@ function playground(opts) {
 				if (seq != cur) {
 					return;
 				}
-				if (opts['postCompile']) {
-					opts['postCompile'](data);
-				}
 				if (!data) {
 					return;
 				}
-				if (data.compile_errors != "") {
-					setOutput(data.compile_errors, true);
-					highlightErrors(data.compile_errors);
-					return;
-				}
-				var out = ""+data.output;
-				if (out.indexOf("IMAGE:") == 0) {
-					var img = $("<img/>");
-					var url = "data:image/png;base64,";
-					url += out.substr(6)
-					img.attr("src", url);
-					output.empty().append(img);
+				if (data.Errors) {
+					setOutput(null, data.Errors);
 					return;
 				}
-				setOutput(out, false);
+				setOutput(data.Events, false);
 			},
-			error: function(xhr) {
-				var text = "Error communicating with remote server.";
-				if (xhr.status == 501) {
-					text = xhr.responseText;
-				}
-				output.addClass("error").text(text);
+			error: function() {
+				output.addClass("error").text(
+					"Error communicating with remote server."
+				);
 			}
 		});
 	}
@@ -193,29 +227,11 @@ function playground(opts) {
 			dataType: "json",
 			success: function(data) {
 				if (data.Error) {
-					setOutput(data.Error, true);
-					highlightErrors(data.Error);
+					setOutput(null, data.Error);
 					return;
 				}
 				setBody(data.Body);
-				setOutput("", false);
-			}
-		});
-	});
-
-	$(opts['toysEl']).bind('change', function() {
-		var toy = $(this).val();
-		loading();
-		$.ajax("/doc/play/"+toy, {
-			processData: false,
-			type: "GET",
-			complete: function(xhr) {
-				if (xhr.status != 200) {
-					setOutput("Server error; try again.", true);
-					return;
-				}
-				setBody(xhr.responseText);
-				setOutput("", false);
+				setOutput(null);
 			}
 		});
 	});
@@ -229,16 +245,13 @@ function playground(opts) {
 		$(opts['shareEl']).click(function() {
 			if (sharing) return;
 			sharing = true;
+			var sharingData = body();
 			$.ajax("/share", {
 				processData: false,
-				data: body(),
+				data: sharingData,
 				type: "POST",
 				complete: function(xhr) {
 					sharing = false;
-					if (xhr.status == 501) {
-						alert(xhr.responseText);
-						return;
-					}
 					if (xhr.status != 200) {
 						alert("Server error; try again.");
 						return;
@@ -247,13 +260,37 @@ function playground(opts) {
 						window.location = opts['shareRedirect'] + xhr.responseText;
 					}
 					if (shareURL) {
-						var url = origin(window.location) + "/p/" + xhr.responseText;
+						var path = "/p/" + xhr.responseText
+						var url = origin(window.location) + path;
 						shareURL.show().val(url).focus().select();
+
+						if (rewriteHistory) {
+							var historyData = {
+								"code": sharingData,
+							};
+							window.history.pushState(historyData, "", path);
+							pushedEmpty = false;
+						}
 					}
 				}
 			});
 		});
 	}
 
-	return editor;
+	if (opts['toysEl'] != null) {
+		$(opts['toysEl']).bind('change', function() {
+			var toy = $(this).val();
+			$.ajax("/doc/play/"+toy, {
+				processData: false,
+				type: "GET",
+				complete: function(xhr) {
+					if (xhr.status != 200) {
+						alert("Server error; try again.")
+						return;
+					}
+					setBody(xhr.responseText);
+				}
+			});
+		});
+	}
 }
diff --git a/doc/play/sieve.go b/doc/play/sieve.go
index 585507a..5190934 100644
--- a/doc/play/sieve.go
+++ b/doc/play/sieve.go
@@ -2,6 +2,8 @@
 
 package main
 
+import "fmt"
+
 // Send the sequence 2, 3, 4, ... to channel 'ch'.
 func Generate(ch chan<- int) {
 	for i := 2; ; i++ {
@@ -26,7 +28,7 @@ func main() {
 	go Generate(ch)      // Launch Generate goroutine.
 	for i := 0; i < 10; i++ {
 		prime := <-ch
-		print(prime, "\n")
+		fmt.Println(prime)
 		ch1 := make(chan int)
 		go Filter(ch, ch1, prime)
 		ch = ch1
diff --git a/doc/play/solitaire.go b/doc/play/solitaire.go
index 759d542..15022aa 100644
--- a/doc/play/solitaire.go
+++ b/doc/play/solitaire.go
@@ -28,7 +28,7 @@ var board = []rune(
 ...........
 `)
 
-// center is the position of the center hole if 
+// center is the position of the center hole if
 // there is a single one; otherwise it is -1.
 var center int
 
@@ -47,7 +47,7 @@ func init() {
 
 var moves int // number of times move is called
 
-// move tests if there is a peg at position pos that 
+// move tests if there is a peg at position pos that
 // can jump over another peg in direction dir. If the
 // move is valid, it is executed and move returns true.
 // Otherwise, move returns false.
@@ -69,11 +69,11 @@ func unmove(pos, dir int) {
 	board[pos+2*dir] = '○'
 }
 
-// solve tries to find a sequence of moves such that 
-// there is only one peg left at the end; if center is 
+// solve tries to find a sequence of moves such that
+// there is only one peg left at the end; if center is
 // >= 0, that last peg must be in the center position.
 // If a solution is found, solve prints the board after
-// each move in a backward fashion (i.e., the last 
+// each move in a backward fashion (i.e., the last
 // board position is printed first, all the way back to
 // the starting board position).
 func solve() bool {
@@ -89,7 +89,7 @@ func solve() bool {
 					// see if this new board has a solution
 					if solve() {
 						unmove(pos, dir)
-						println(string(board))
+						fmt.Println(string(board))
 						return true
 					}
 					unmove(pos, dir)
@@ -102,7 +102,7 @@ func solve() bool {
 	// tried each possible move
 	if n == 1 && (center < 0 || last == center) {
 		// there's only one peg left
-		println(string(board))
+		fmt.Println(string(board))
 		return true
 	}
 	// no solution found for this board
diff --git a/doc/play/tree.go b/doc/play/tree.go
index 5bcbf05..3790e6c 100644
--- a/doc/play/tree.go
+++ b/doc/play/tree.go
@@ -2,7 +2,7 @@
 // express concurrent concepts, such as
 // this binary tree comparison.
 //
-// Trees may be of different shapes, 
+// Trees may be of different shapes,
 // but have the same contents. For example:
 //
 //        4               6
@@ -29,7 +29,7 @@ type Tree struct {
 	Right *Tree
 }
 
-// Walk traverses a tree depth-first, 
+// Walk traverses a tree depth-first,
 // sending each Value on a channel.
 func Walk(t *Tree, ch chan int) {
 	if t == nil {
diff --git a/doc/popups.js b/doc/popups.js
deleted file mode 100644
index 23ccc8c..0000000
--- a/doc/popups.js
+++ /dev/null
@@ -1,24 +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.
-
-function godocs_bindPopups(data) {
-
-  $('#content span').bind('mouseenter', function() {
-    var id = $(this).attr('id');
-    //var txt = $(this).text();
-    if (typeof data[id] == 'undefined')
-	return;
-    var content = data[id];
-
-    var $el = $('.popup', this);
-    if (!$el.length) { // create it
-      $el = $('<div class="popup"></div>');
-      $el.prependTo(this).css($(this).offset()).text(content);
-    }
-  });
-  $('#content span').bind('mouseleave', function() {
-    $('.popup', this).remove();
-  });
-
-}
diff --git a/doc/progs/cgo1.go b/doc/progs/cgo1.go
index b79ee36..1a2dc6c 100644
--- a/doc/progs/cgo1.go
+++ b/doc/progs/cgo1.go
@@ -1,3 +1,5 @@
+// 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.
diff --git a/doc/progs/cgo2.go b/doc/progs/cgo2.go
index f38473b..9999af3 100644
--- a/doc/progs/cgo2.go
+++ b/doc/progs/cgo2.go
@@ -1,3 +1,5 @@
+// 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.
diff --git a/doc/progs/cgo3.go b/doc/progs/cgo3.go
index 435fd04..c4f4791 100644
--- a/doc/progs/cgo3.go
+++ b/doc/progs/cgo3.go
@@ -1,3 +1,5 @@
+// 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.
diff --git a/doc/progs/cgo4.go b/doc/progs/cgo4.go
index 3808d62..30b8935 100644
--- a/doc/progs/cgo4.go
+++ b/doc/progs/cgo4.go
@@ -1,3 +1,5 @@
+// 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.
diff --git a/doc/progs/defer.go b/doc/progs/defer.go
index 2e11020..006a474 100644
--- a/doc/progs/defer.go
+++ b/doc/progs/defer.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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/doc/progs/defer.out b/doc/progs/defer.out
new file mode 100644
index 0000000..0cdf53a
--- /dev/null
+++ b/doc/progs/defer.out
@@ -0,0 +1,3 @@
+0
+3210
+2
diff --git a/doc/progs/defer2.go b/doc/progs/defer2.go
index cad66b0..ff7eaf9 100644
--- a/doc/progs/defer2.go
+++ b/doc/progs/defer2.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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/doc/progs/defer2.out b/doc/progs/defer2.out
new file mode 100644
index 0000000..6110685
--- /dev/null
+++ b/doc/progs/defer2.out
@@ -0,0 +1,12 @@
+Calling g.
+Printing in g 0
+Printing in g 1
+Printing in g 2
+Printing in g 3
+Panicking!
+Defer in g 3
+Defer in g 2
+Defer in g 1
+Defer in g 0
+Recovered in f 4
+Returned normally from f.
diff --git a/doc/progs/eff_bytesize.go b/doc/progs/eff_bytesize.go
index b459611..a0c3d50 100644
--- a/doc/progs/eff_bytesize.go
+++ b/doc/progs/eff_bytesize.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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.
diff --git a/doc/progs/eff_bytesize.out b/doc/progs/eff_bytesize.out
new file mode 100644
index 0000000..df763f3
--- /dev/null
+++ b/doc/progs/eff_bytesize.out
@@ -0,0 +1 @@
+1.00YB 9.09TB
diff --git a/doc/progs/eff_qr.go b/doc/progs/eff_qr.go
index de96a02..861131d 100644
--- a/doc/progs/eff_qr.go
+++ b/doc/progs/eff_qr.go
@@ -1,10 +1,16 @@
+// compile
+
+// 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 main
 
 import (
 	"flag"
+	"html/template"
 	"log"
 	"net/http"
-	"text/template"
 )
 
 var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
@@ -31,9 +37,9 @@ const templateStr = `
 </head>
 <body>
 {{if .}}
-<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={{urlquery .}}" />
+<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={{.}}" />
 <br>
-{{html .}}
+{{.}}
 <br>
 <br>
 {{end}}
diff --git a/doc/progs/eff_sequence.go b/doc/progs/eff_sequence.go
index 11c885a..c9b18ba 100644
--- a/doc/progs/eff_sequence.go
+++ b/doc/progs/eff_sequence.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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.
diff --git a/doc/progs/eff_sequence.out b/doc/progs/eff_sequence.out
new file mode 100644
index 0000000..fd01a7d
--- /dev/null
+++ b/doc/progs/eff_sequence.out
@@ -0,0 +1 @@
+[-1 2 6 16 44]
diff --git a/doc/progs/error.go b/doc/progs/error.go
index f85a527..57854c5 100644
--- a/doc/progs/error.go
+++ b/doc/progs/error.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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.
@@ -18,7 +20,11 @@ import (
 
 type File struct{}
 
-func Open(name string) (file *File, err error)
+func Open(name string) (file *File, err error) {
+	// OMIT
+	panic(1)
+	// STOP OMIT
+}
 
 func openFile() { // OMIT
 	f, err := os.Open("filename.ext")
diff --git a/doc/progs/error2.go b/doc/progs/error2.go
index 2b0e0c3..aad1dc8 100644
--- a/doc/progs/error2.go
+++ b/doc/progs/error2.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/error3.go b/doc/progs/error3.go
index e4e57e0..9f1b300 100644
--- a/doc/progs/error3.go
+++ b/doc/progs/error3.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/error4.go b/doc/progs/error4.go
index 8f35cf7..d40fc6e 100644
--- a/doc/progs/error4.go
+++ b/doc/progs/error4.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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.
@@ -22,7 +24,7 @@ type appError struct {
 type appHandler func(http.ResponseWriter, *http.Request) *appError
 
 func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	if e := fn(w, r); e != nil { // e is *appError, not os.Error.
+	if e := fn(w, r); e != nil { // e is *appError, not error.
 		c := appengine.NewContext(r)
 		c.Errorf("%v", e.Error)
 		http.Error(w, e.Message, e.Code)
diff --git a/doc/progs/go1.go b/doc/progs/go1.go
index 50fd934..a4dc64d 100644
--- a/doc/progs/go1.go
+++ b/doc/progs/go1.go
@@ -1,3 +1,6 @@
+// compile
+// this file will output a list of filenames in cwd, not suitable for cmpout
+
 // 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/doc/progs/gobs1.go b/doc/progs/gobs1.go
index 7077ca1..d95f765 100644
--- a/doc/progs/gobs1.go
+++ b/doc/progs/gobs1.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/gobs2.go b/doc/progs/gobs2.go
index 85bb41c..acd1838 100644
--- a/doc/progs/gobs2.go
+++ b/doc/progs/gobs2.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/image_draw.go b/doc/progs/image_draw.go
index bb73c8a..0a1f7ac 100644
--- a/doc/progs/image_draw.go
+++ b/doc/progs/image_draw.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/image_package1.go b/doc/progs/image_package1.go
index c4c401e..d331834 100644
--- a/doc/progs/image_package1.go
+++ b/doc/progs/image_package1.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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/doc/progs/image_package1.out b/doc/progs/image_package1.out
new file mode 100644
index 0000000..809b31b
--- /dev/null
+++ b/doc/progs/image_package1.out
@@ -0,0 +1 @@
+X is 2 Y is 1
diff --git a/doc/progs/image_package2.go b/doc/progs/image_package2.go
index fcb5d9f..e5b78b4 100644
--- a/doc/progs/image_package2.go
+++ b/doc/progs/image_package2.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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/doc/progs/image_package2.out b/doc/progs/image_package2.out
new file mode 100644
index 0000000..616d307
--- /dev/null
+++ b/doc/progs/image_package2.out
@@ -0,0 +1 @@
+3 4 false
diff --git a/doc/progs/image_package3.go b/doc/progs/image_package3.go
index 13d0f08..95d72a0 100644
--- a/doc/progs/image_package3.go
+++ b/doc/progs/image_package3.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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/doc/progs/image_package3.out b/doc/progs/image_package3.out
new file mode 100644
index 0000000..3fe35de
--- /dev/null
+++ b/doc/progs/image_package3.out
@@ -0,0 +1 @@
+3 4 true
diff --git a/doc/progs/image_package4.go b/doc/progs/image_package4.go
index c46fddf..ec0e461 100644
--- a/doc/progs/image_package4.go
+++ b/doc/progs/image_package4.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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/doc/progs/image_package4.out b/doc/progs/image_package4.out
new file mode 100644
index 0000000..cb1b777
--- /dev/null
+++ b/doc/progs/image_package4.out
@@ -0,0 +1 @@
+image.Point{X:2, Y:1}
diff --git a/doc/progs/image_package5.go b/doc/progs/image_package5.go
index 0bb5c76..b9e27d6 100644
--- a/doc/progs/image_package5.go
+++ b/doc/progs/image_package5.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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/doc/progs/image_package5.out b/doc/progs/image_package5.out
new file mode 100644
index 0000000..2da80c1
--- /dev/null
+++ b/doc/progs/image_package5.out
@@ -0,0 +1 @@
+{255 0 0 255}
diff --git a/doc/progs/image_package6.go b/doc/progs/image_package6.go
index 62eeecd..5e6eefa 100644
--- a/doc/progs/image_package6.go
+++ b/doc/progs/image_package6.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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/doc/progs/image_package6.out b/doc/progs/image_package6.out
new file mode 100644
index 0000000..fcd13c0
--- /dev/null
+++ b/doc/progs/image_package6.out
@@ -0,0 +1,2 @@
+8 4
+true
diff --git a/doc/progs/interface.go b/doc/progs/interface.go
index c2925d5..6972b72 100644
--- a/doc/progs/interface.go
+++ b/doc/progs/interface.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/interface2.go b/doc/progs/interface2.go
index a541d94..85e7d51 100644
--- a/doc/progs/interface2.go
+++ b/doc/progs/interface2.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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/doc/progs/interface2.out b/doc/progs/interface2.out
new file mode 100644
index 0000000..085bd01
--- /dev/null
+++ b/doc/progs/interface2.out
@@ -0,0 +1 @@
+type: float64
diff --git a/doc/progs/json1.go b/doc/progs/json1.go
index 9e10f47..887d7d1 100644
--- a/doc/progs/json1.go
+++ b/doc/progs/json1.go
@@ -1,3 +1,5 @@
+// run
+
 // 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/doc/progs/json2.go b/doc/progs/json2.go
index 6089ae6..f358fea 100644
--- a/doc/progs/json2.go
+++ b/doc/progs/json2.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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/doc/progs/json2.out b/doc/progs/json2.out
new file mode 100644
index 0000000..8f2dea5
--- /dev/null
+++ b/doc/progs/json2.out
@@ -0,0 +1,2 @@
+the circle's area 24.227111172875365
+the reciprocal of i is 0.3601008282319049
diff --git a/doc/progs/json3.go b/doc/progs/json3.go
index a04fdfa..41eb373 100644
--- a/doc/progs/json3.go
+++ b/doc/progs/json3.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/json4.go b/doc/progs/json4.go
index 4926302..ee38f31 100644
--- a/doc/progs/json4.go
+++ b/doc/progs/json4.go
@@ -1,3 +1,5 @@
+// run
+
 // 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/doc/progs/json5.go b/doc/progs/json5.go
index 6d7a4ca..9ab972d 100644
--- a/doc/progs/json5.go
+++ b/doc/progs/json5.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/run b/doc/progs/run
index 92c8da5..da777f3 100755
--- a/doc/progs/run
+++ b/doc/progs/run
@@ -40,6 +40,15 @@ c_go_cgo="
 if [ "$goos" == "freebsd" ]; then
 	c_go_cgo="cgo3 cgo4"
 fi
+# cgo1 and cgo2 don't run on netbsd, srandom has a different signature
+# cgo3 and cgo4 don't run on netbsd, since cgo cannot handle stdout correctly
+if [ "$goos" == "netbsd" ]; then
+	c_go_cgo=""
+fi
+# cgo3 and cgo4 don't run on openbsd, since cgo cannot handle stdout correctly
+if [ "$goos" == "openbsd" ]; then
+	c_go_cgo="cgo1 cgo2"
+fi
 
 timeout="
 	timeout1
diff --git a/doc/progs/slices.go b/doc/progs/slices.go
index 8e44010..0461684 100644
--- a/doc/progs/slices.go
+++ b/doc/progs/slices.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/timeout1.go b/doc/progs/timeout1.go
index 5221770..fbc39ca 100644
--- a/doc/progs/timeout1.go
+++ b/doc/progs/timeout1.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/timeout2.go b/doc/progs/timeout2.go
index 7145bc9..a12bc2a 100644
--- a/doc/progs/timeout2.go
+++ b/doc/progs/timeout2.go
@@ -1,3 +1,5 @@
+// compile
+
 // 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/doc/progs/unused1.go b/doc/progs/unused1.go
new file mode 100644
index 0000000..96a6d98
--- /dev/null
+++ b/doc/progs/unused1.go
@@ -0,0 +1,12 @@
+// skip
+
+package main
+
+import (
+	"fmt"
+	"io"
+)
+
+func main() {
+	greeting := "hello, world"
+}
diff --git a/doc/progs/unused2.go b/doc/progs/unused2.go
new file mode 100644
index 0000000..5c5f9d7
--- /dev/null
+++ b/doc/progs/unused2.go
@@ -0,0 +1,16 @@
+// compile
+
+package main
+
+import (
+	"fmt"
+	"io"
+)
+
+var _ = fmt.Printf
+var _ io.Reader
+
+func main() {
+	greeting := "hello, world"
+	_ = greeting
+}
diff --git a/doc/progs/update.bash b/doc/progs/update.bash
new file mode 100755
index 0000000..d4ecfbe
--- /dev/null
+++ b/doc/progs/update.bash
@@ -0,0 +1,15 @@
+#!/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.
+
+set -e
+
+rm -f *.out *.rej *.orig [568].out
+
+for i in *.go; do
+	if grep -q '^// cmpout$' $i; then
+		echo $i
+		go run $i &> ${i/.go/.out}
+	fi
+done
diff --git a/doc/reference.html b/doc/reference.html
index beaac43..795c5e0 100644
--- a/doc/reference.html
+++ b/doc/reference.html
@@ -21,13 +21,13 @@ The documentation for the Go tools.
 
 <h3 id="spec"><a href="/ref/spec">Language Specification</a></h3>
 <p>
-The official Go Language specification. 
+The official Go Language specification.
 </p>
 
-<h3 id="appengine"><a href="http://code.google.com/appengine/docs/go/">App Engine Go Runtime Documentation</a></h3>
+<h3 id="appengine"><a href="https://developers.google.com/appengine/docs/go/">App Engine Go Runtime Documentation</a></h3>
 <p>
 The documentation for
-<a href="http://code.google.com/appengine/">Google App Engine</a>'s Go runtime.
+<a href="https://developers.google.com/appengine/">Google App Engine</a>'s Go runtime.
 </p>
 
 <h3 id="go_mem"><a href="/ref/mem">The Go Memory Model</a></h3>
@@ -47,25 +47,14 @@ Install them with "<code><a href="/cmd/go/#Download_and_install_packages_and_dep
 </p>
 
 <ul>
-<li><a href="http://code.google.com/p/go/source/browse?repo=codereview"><code>code.google.com/p/go.codereview</code></a> [<a href="http://gopkgdoc.appspot.com/pkg/code.google.com/p/go.codereview">docs</a>]
-<li><a href="http://code.google.com/p/go/source/browse?repo=crypto"><code>code.google.com/p/go.crypto</code></a> [<a href="http://gopkgdoc.appspot.com/pkg/code.google.com/p/go.crypto">docs</a>]
-<li><a href="http://code.google.com/p/go/source/browse?repo=image"><code>code.google.com/p/go.image</code></a> [<a href="http://gopkgdoc.appspot.com/pkg/code.google.com/p/go.image">docs</a>]
-<li><a href="http://code.google.com/p/go/source/browse?repo=net"><code>code.google.com/p/go.net</code></a> [<a href="http://gopkgdoc.appspot.com/pkg/code.google.com/p/go.net">docs</a>]
-</ul>
-
-<h4 id="articles">Articles</h4>
-
-<ul>
-<li><a href="/doc/articles/c_go_cgo.html">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
-<li><a href="/doc/gdb">Debugging Go Code with GDB</a></li>
-<li><a href="/doc/articles/defer_panic_recover.html">Defer, Panic, and Recover</a></li>
-<li><a href="/doc/articles/slices_usage_and_internals.html">Go Slices: usage and internals</a></li>
-<li><a href="/doc/articles/godoc_documenting_go_code.html">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
-<li><a href="http://blog.golang.org/2011/06/profiling-go-programs.html">Profiling Go Programs</a></li>
+<li><a href="http://code.google.com/p/go/source/browse?repo=codereview"><code>code.google.com/p/go.codereview</code></a> [<a href="http://godoc.org/code.google.com/p/go.codereview">docs</a>]
+<li><a href="http://code.google.com/p/go/source/browse?repo=crypto"><code>code.google.com/p/go.crypto</code></a> [<a href="http://godoc.org/code.google.com/p/go.crypto">docs</a>]
+<li><a href="http://code.google.com/p/go/source/browse?repo=image"><code>code.google.com/p/go.image</code></a> [<a href="http://godoc.org/code.google.com/p/go.image">docs</a>]
+<li><a href="http://code.google.com/p/go/source/browse?repo=net"><code>code.google.com/p/go.net</code></a> [<a href="http://godoc.org/code.google.com/p/go.net">docs</a>]
 </ul>
 
 <p>
-See the <a href="/doc/#articles">documentation page</a> for more articles.
+See the <a href="/doc/">documents page</a> for more documentation.
 </p>
 
 </div>
diff --git a/doc/root.html b/doc/root.html
index 3b92229..34915c0 100644
--- a/doc/root.html
+++ b/doc/root.html
@@ -53,11 +53,11 @@ simple, reliable, and efficient software.
 <div id="gopher"></div>
 
 <a href="/doc/install" id="start">
-<div class="big">Download Go</div>
-<div class="desc">
+<span class="big">Download Go</span>
+<span class="desc">
 Binary distributions available for<br>
 Linux, Mac OS X, Windows, and more.
-</div>
+</span>
 </a>
 
 </div>
@@ -68,8 +68,7 @@ Linux, Mac OS X, Windows, and more.
 
 <div id="video">
 <div class="rootHeading">Featured video</div>
-<a class="title" href="http://www.youtube.com/watch?v=Mo1YKpIF1PQ">Building integrated apps on Google's cloud platform with Go</a>
-<iframe width="415" height="241" src="http://www.youtube.com/embed/Mo1YKpIF1PQ" frameborder="0" allowfullscreen></iframe>
+<iframe width="415" height="241" src="http://www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe>
 </div>
 
 </div>
@@ -86,10 +85,8 @@ Linux, Mac OS X, Windows, and more.
 <div style="clear: both;"></div>
 
 <script type="text/javascript" src="https://www.google.com/jsapi"></script>
-<script type="text/javascript" src="/doc/play/playground.js"></script>
 <script type="text/javascript">
 google.load("feeds", "1");
-google.load("jquery", "1.7.1");
 
 function feedLoaded(result) {
 	if (result.error) {
@@ -124,7 +121,6 @@ function init() {
 
 	// Set up playground.
 	playground({
-		"simple":        true,
 		"codeEl":        "#learn .code",
 		"outputEl":      "#learn .output",
 		"runEl":         "#learn .run",
diff --git a/doc/style.css b/doc/style.css
index a0c6320..3d881b0 100644
--- a/doc/style.css
+++ b/doc/style.css
@@ -130,22 +130,25 @@ div#heading a {
 div#topbar {
 	background: #E0EBF5;
 	height: 64px;
+	overflow: hidden;
 }
 
 body {
 	text-align: center;
 }
-div#page,
+div#page {
+	width: 100%;
+}
+div#page > .container,
 div#topbar > .container {
-	clear: both;
 	text-align: left;
 	margin-left: auto;
 	margin-right: auto;
 	padding: 0 20px;
 	width: 900px;
 }
-div#page.wide,
-div#topbar > .wide {
+div#page.wide > .container,
+div#topbar.wide > .container {
 	width: auto;
 }
 div#plusone {
@@ -153,6 +156,7 @@ div#plusone {
 }
 
 div#footer {
+	text-align: center;
 	color: #666;
 	font-size: 14px;
 	margin: 40px 0;
@@ -161,6 +165,7 @@ div#footer {
 div#menu > a,
 div#menu > input,
 div#learn .buttons a,
+div.play .buttons a,
 div#blog .read a {
 	padding: 10px;
 
@@ -171,16 +176,23 @@ div#blog .read a {
 	-moz-border-radius: 5px;
 	border-radius: 5px;
 }
+div#playground .buttons a,
 div#menu > a,
 div#menu > input {
 	border: 1px solid #375EAB;
 }
+div#playground .buttons a,
 div#menu > a {
 	color: white;
 	background: #375EAB;
 }
+#playgroundButton.active {
+	background: white;
+	color: #375EAB;
+}
 a#start,
 div#learn .buttons a,
+div.play .buttons a,
 div#blog .read a {
 	color: #222;
 	border: 1px solid #375EAB;
@@ -212,9 +224,11 @@ div#menu > input.inactive {
 
 div.left {
 	float: left;
+	clear: left;
 }
 div.right {
 	float: right;
+	clear: right;
 }
 div.left,
 div.right {
@@ -253,10 +267,12 @@ a#start {
 	border-radius: 5px;
 }
 a#start .big {
+	display: block;
 	font-weight: bold;
 	font-size: 20px;
 }
 a#start .desc {
+	display: block;
 	font-size: 14px;
 	font-weight: normal;
 	margin-top: 5px;
@@ -340,6 +356,9 @@ div#learn .toys select {
 	border: 1px solid #375EAB;
 	margin: 0;
 }
+div#learn .output .exit {
+	display: none;
+}
 
 div#blog,
 div#video {
@@ -391,3 +410,120 @@ img.gopher {
 	margin-bottom: -120px;
 }
 h2 { clear: right; }
+
+/* example and drop-down playground */
+div.play {
+	padding: 0 20px 40px 20px;
+}
+div.play pre,
+div.play textarea,
+div.play .lines {
+	padding: 0;
+	margin: 0;
+	font-family: Menlo, monospace;
+	font-size: 14px;
+}
+div.play .input {
+	padding: 10px;
+	margin-top: 10px;
+
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-top-right-radius: 5px;
+	-moz-border-radius-topleft: 5px;
+	-moz-border-radius-topright: 5px;
+	border-top-left-radius: 5px;
+	border-top-right-radius: 5px;
+
+	overflow: hidden;
+}
+div.play .input textarea {
+	width: 100%;
+	height: 100%;
+	border: none;
+	outline: none;
+	resize: none;
+
+	overflow: hidden;
+}
+div#playground .input textarea {
+	overflow: auto;
+	resize: auto;
+}
+div.play .output {
+	border-top: none !important;
+
+	padding: 10px;
+	max-height: 200px;
+	overflow: auto;
+
+	-webkit-border-bottom-right-radius: 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-moz-border-radius-bottomright: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	border-bottom-right-radius: 5px;
+	border-bottom-left-radius: 5px;
+}
+div.play .output pre {
+	padding: 0;
+
+	-webkit-border-radius: 0;
+	-moz-border-radius: 0;
+	border-radius: 0;
+}
+div.play .input,
+div.play .input textarea,
+div.play .output,
+div.play .output pre {
+	background: #FFFFD8;
+}
+div.play .input,
+div.play .output {
+	border: 1px solid #375EAB;
+}
+div.play .buttons {
+	float: right;
+	padding: 20px 0 10px 0;
+	text-align: right;
+}
+div.play .buttons a {
+	height: 16px;
+	margin-left: 5px;
+	padding: 10px;
+	cursor: pointer;
+}
+div.play .output .exit {
+	color: #999;
+}
+
+/* drop-down playground */
+#playgroundButton,
+div#playground {
+	/* start hidden; revealed by javascript */
+	display: none;
+}
+div#playground {
+	position: absolute;
+	top: 63px;
+	right: 20px;
+	padding: 0 10px 10px 10px;
+	z-index: 1;
+	text-align: left;
+	background: #E0EBF5;
+
+	border: 1px solid #B0BBC5;
+	border-top: none;
+
+	-webkit-border-bottom-left-radius: 5px;
+	-webkit-border-bottom-right-radius: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	-moz-border-radius-bottomright: 5px;
+	border-bottom-left-radius: 5px;
+	border-bottom-right-radius: 5px;
+}
+div#playground .code {
+	width: 520px;
+	height: 200px;
+}
+div#playground .output {
+	height: 100px;
+}
diff --git a/doc/talks/go_talk-20091030.pdf b/doc/talks/go_talk-20091030.pdf
deleted file mode 100644
index 5139ff2..0000000
Binary files a/doc/talks/go_talk-20091030.pdf and /dev/null differ
diff --git a/doc/talks/go_talk-20100112.html b/doc/talks/go_talk-20100112.html
deleted file mode 100644
index 2e36435..0000000
--- a/doc/talks/go_talk-20100112.html
+++ /dev/null
@@ -1,411 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<title>Go (January 12, 2010)</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="font-size-adjustment" content="-1" />
-<link rel="stylesheet" href="slidy.css"
-  type="text/css" media="screen, projection, print" />
-<script src="slidy.js" type="text/javascript">
-</script>
-</head>
-<body>
-<!-- this defines the slide background -->
-
-<div class="background">
-
-  <div class="header">
-  <!-- sized and colored via CSS -->
-  </div>
-
-  <div class="footer"></div>
-  </div>
-
-<div class="slide titlepage">
-<div style="height: 135px; width: 480px; overflow: hidden; position: fixed; top: auto; bottom: 10px; left: auto; right: 0;  ">
-<img src="../gordon/bumper480x270.png" style="margin: -135px 0 0 0;"/>
-</div>
-<!-- <img src="google.png" style="position: fixed; top: auto; bottom: 30px; left: 20px; right: auto;"/> -->
-<br/>
-<img src="../go-logo-white.png">
-<br/>
-<br/>
-<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
-<div style="color: #ffcc00;">
-<h2>Russ Cox</h2>
-<!-- <h3><i>rsc at google.com</i></h3> -->
-<br/>
-<h3>Stanford University<br/><br/>January 12, 2010</h3>
-</div>
-</div>
-
-<div class="slide">
-	<h1>Go</h1>
-
-	<h2>New</h2>
-	<h2>Experimental</h2>
-	<h2>Concurrent</h2>
-	<h2>Garbage-collected</h2>
-	<h2>Systems</h2>
-	<h2>Language</h2>
-</div>
-
-<div class="slide">
-	<h1>Hello, world</h1>
-<pre>
-package main
-
-import "fmt"
-
-func main() {
-	fmt.Printf("Hello, 世界\n")
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>History</h1>
-	
-	<h2>Design started in late 2007.</h2>
-	<h2>Implementation starting to work mid-2008.</h2>
-	<h2>Released as an open source project in November 2009.</h2>
-	<h2>Work continues.<h2>
-	<h2>Robert Griesemer, Ken Thompson, Rob Pike, Ian Lance Taylor, Russ Cox, many others</h2>
-</div>
-
-<div class="slide">
-	<h1>Why?</h1>
-	
-	<h2>Go fast!</h2>
-	<h2>Make programming fun again.</h2>
-</div>
-
-<div class="slide">
-	<h1>Why isn't programming fun?</h1>
-	
-	<div class="incremental">
-	<h2>Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:</h2>
-	
-	<ul>
-		<li>verbose, lots of repetition</li>
-		<li>too much focus on type hierarchy</li>
-		<li>types get in the way as much as they help</li>
-		<li>compiles take far too long</li>
-	</ul>
-	</div>
-	
-	<div class="incremental">
-	<h2>Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:</h2>
-	
-	<ul>
-		<li>errors at run time that should be caught statically</li>
-		<li>no compilation means slow code</li>
-	</ul>
-	</div>
-	
-	<h2 class="incremental">Can we combine the best of both?</h2>
-</div>
-
-<div class="slide">
-	<h1>Go</h1>
-	
-	<h2>Make the language fast.</h2>
-	<h2>Make the tools fast.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Static Types</h1>
-	
-	<h2>Static types, but declarations can infer type from expression:</h2>
-	
-<pre>
-var one, hi = 1, "hello"
-
-var double = func(x int) int { return x*2 }
-</pre>
-
-	<h2>Not full Hindley-Milner type inference.</h2>
-</div>
-
-
-<div class="slide">
-	<h1>Go Approach: Methods</h1>
-	
-	<h2>Methods can be defined on any type.</h2>
-
-<pre>
-type Point struct {
-	X, Y float64
-}
-
-func (p Point) Abs() float64 {
-	return math.Sqrt(p.X*p.X + p.Y*p.Y)
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Methods</h1>
-	
-	<h2>Methods can be defined on any type.</h2>
-
-<pre>
-type MyFloat float64
-
-func (f MyFloat) Abs() float64 {
-	v := float64(f)
-	if v < 0 {
-		v = -v
-	}
-	return v
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Abstract Types</h1>
-	
-	<h2>An interface type lists a set of methods. Any value with those methods satisfies the interface.</h2>
-
-<pre>
-type Abser interface {
-	Abs() float64
-}
-
-func AbsPrinter(a Abser)
-</pre>
-
-	<h2>Can use Point or MyFloat (or ...):</h2>
-
-<pre>
-p := Point{3, 4}
-AbsPrinter(p)
-
-f := MyFloat(-10)
-AbsPrinter(f)
-</pre>
-
-	<h2>Notice that Point never declared that it implements Abser. It just does.  Same with MyFloat.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Packages</h1>
-
-	<h2>A Go program comprises one or more packages.</h2>
-	<h2>Each package is one or more source files compiled and imported as a unit.</h2>
-<pre>
-package draw
-
-type Point struct {
-	X, Y int
-}
-</pre>
-
-<pre>
-package main
-
-import "draw"
-
-var p draw.Point
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Visibility</h1>
-	
-	<h2>Inside a package, all locally defined names are visible in all source files.</h2>
-	
-	<h2>When imported, only the upper case names are visible.</h2>
-
-<pre>
-package draw
-
-type <span style="color: black;">Point</span> struct {
-	<span style="color: black;">X</span>, <span style="color: black;">Y</span> int
-	dist float64
-}
-
-type cache map[Point] float64
-</pre>
-
-<h2>Clients that <code>import "draw"</code> can use the black names only.</h2>
-
-<h2>“Shift is the new <code>public</code>.”</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Concurrency</h1>
-	
-	<h2>Cheap to create a new flow of control (goroutine):</h2>
-	
-<pre>
-func main() {
-	go expensiveComputation(x, y, z)
-	anotherExpensiveComputation(a, b, c)
-}
-</pre>
-
-	<h2>Two expensive computations in parallel.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Approach: Synchronization</h1>
-	
-	<h2>Use explicit messages to communicate and synchronize.</h2>
-	
-<pre>
-func computeAndSend(ch chan int, x, y, z int) {
-	ch <- expensiveComputation(x, y, z)
-}
-
-func main() {
-	ch := make(chan int)
-	go computeAndSend(ch, x, y, z)
-	v2 := anotherExpensiveComputation(a, b, c)
-	v1 := <-ch
-	fmt.Println(v1, v2)
-}
-</pre>
-	<h2>Notice communication of result in addition to synchronization.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Fast: Language</h1>
-	
-	<h2 class="incremental">Static types: enough to compile well, but inferred much of the time.</h2>
-	
-	<h2 class="incremental">Methods: on any type, orthogonal to type system.</h2>
-	
-	<h2 class="incremental">Abstract types: interface values, relations inferred statically.</h2>
-	
-	<h2 class="incremental">Visibility: inferred from case of name.</h2>
-	
-	<h2 class="incremental">Concurrency: lightweight way to start new thread of control.</h2>
-	
-	<h2 class="incremental">Synchronization: explicit, easy message passing.</h2>
-
-	<br/>
-	
-	<h2 class="incremental">Lightweight feel of a scripting language but compiled.</h2>
-</div>
-
-<div class="slide">
-	<h1>Compile fast</h1>
-
-	<div class="incremental">
-	<h2>Observation: much of the compile time for a source file is spent processing
-	other, often unrelated files.</h2>
-
-	<h2>In C: <code>a.c</code> includes <code>b.h</code>, which includes <code>c.h</code>, which includes <code>d.h</code>.
-	</h2>
-	
-	<h2>Except that it's more often a tree instead of a chain.</h2>
-	
-	<h2>On my Mac (OS X 10.5.8, gcc 4.0.1):</h2>
-	<ul>
-	<li>C: <code>#include <stdio.h></code> reads 360 lines from 9 files.
-	<li>C++: <code>#include <iostream></code> reads 25,326 lines from 131 files.
-	<li>Objective C: <code>#include <Carbon/Carbon.h></code> reads 124,730 lines from 689 files.
-	</ul>
-	
-	<h2>And we haven't done any real work yet!</h2>
-	
-	<h2>Same story in Java, Python, but reading binaries instead of source files.</h2>
-	</div>
-</div>
-
-<div class="slide">
-	<h1>Implementation: Summarize Dependencies</h1>
-	
-<pre>
-package gui
-
-import "draw"
-
-type Mouse struct {
-	Loc draw.Point
-	Buttons uint
-}
-</pre>
-	<h2>Compiled form of <code>gui</code> summarizes the necessary part of <code>draw</code> (just <code>Point</code>).</h2>
-
-</div>
-
-<div class="slide">
-	<h1>Implementation: Summarize Dependencies</h1>
-
-	<h2>Compiled form of <code>gui</code> summarizes the necessary part of <code>draw</code> (just <code>Point</code>).  Pseudo-object:</h2>
-
-<pre>
-package gui
-type draw.Point struct {
-	X, Y int
-}
-type gui.Mouse struct {
-	Loc draw.Point
-	Buttons uint
-}
-</pre>
-
-	<h2>A file that imports <code>gui</code> compiles without consulting <code>draw</code> or its dependencies.</h2>
-	
-	<h2>In Go: <code>import "fmt"</code> reads <i>one</i> file: 184 lines summarizing types from 7 packages.</h2>
-
-	<h2>Tiny effect in this program but can be exponential in large programs.</h2>
-</div>
-
-<div class="slide">
-	<h1>Compilation Demo</h1>
-	
-	<h2>Build all standard Go packages: ~120,000 lines of code.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go Status</h1>
-	
-	<div class="incremental">
-	<div>
-	<h2>Open source:</h2>
-	<ul>
-	<li>released on November 10, 2009
-	<li>regular releases (~ weekly)
-	<li>all development done in public Mercurial repository
-	<li>outside contributions welcome
-	</ul>
-	</div>
-	
-	<div>
-	<h2>Portable:</h2>
-	<ul>
-	<li>FreeBSD, Linux, OS X (x86, x86-64)
-	<li>(in progress) Linux arm, Native Client x86, Windows x86.
-	</ul>
-	</div>
-	
-	<div>
-	<h2>Still in progress, experimental.  Yet to come:</h2>
-	<ul>
-	<li>mature garbage collector
-	<li>generics?
-	<li>exceptions?
-	<li>unions or sum types?
-	</ul>
-	</div>
-	</div>
-
-</div>
-
-<div class="slide titlepage">
-	<h1>Questions?</h1>
-	<br><br>
-	<center>
-	<img src="../gordon/bumper640x360.png">
-	</center>
-	<br><br>
-	<div style="color: #ffcc00;">
-	<!-- <h3><i>rsc at google.com</i></h3> -->
-	</div>
-</div>
-
-</body></html>
diff --git a/doc/talks/go_talk-20100121.html b/doc/talks/go_talk-20100121.html
deleted file mode 100644
index d5e4bc6..0000000
--- a/doc/talks/go_talk-20100121.html
+++ /dev/null
@@ -1,453 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<title>Go, Networked (January 21, 2010)</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="font-size-adjustment" content="-1" />
-<link rel="stylesheet" href="slidy.css"
-  type="text/css" media="screen, projection, print" />
-<script src="slidy.js" type="text/javascript">
-</script>
-</head>
-<body>
-<!-- this defines the slide background -->
-
-<div class="background">
-
-  <div class="header">
-  <!-- sized and colored via CSS -->
-  </div>
-
-  <div class="footer"></div>
-  </div>
-
-<div class="slide titlepage">
-<div style="height: 135px; width: 480px; overflow: hidden; position: fixed; top: auto; bottom: 10px; left: auto; right: 0;  ">
-<img src="../gordon/bumper480x270.png" style="margin: -135px 0 0 0;"/>
-</div>
-<!-- <img src="../google.png" style="position: fixed; top: auto; bottom: 30px; left: 20px; right: auto;"/> -->
-<br/>
-<img src="../go-logo-white.png">
-<br/>
-<br/>
-<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
-<div style="color: #ffcc00;">
-<h2>Russ Cox</h2>
-<!-- <h3><i>rsc at google.com</i></h3> -->
-<br/>
-<h3>CNS Winter Research Review<br/><br/>January 21, 2010</h3>
-<br/>
-<br/>
-<!--
-<h4><i>click to start; then left/right arrow to change slides</i></h4> -->
-</div>
-</div>
-
-<div class="slide">
-	<h1>Go</h1>
-
-	<h2>New</h2>
-	<h2>Experimental</h2>
-	<h2>Concurrent</h2>
-	<h2>Garbage-collected</h2>
-	<h2>Systems</h2>
-	<h2>Language</h2>
-</div>
-
-<div class="slide">
-	<h1>Hello, world</h1>
-<pre>
-package main
-
-import "fmt"
-
-func main() {
-	fmt.Printf("Hello, 世界\n")
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>History</h1>
-	
-	<h2>Design started in late 2007.</h2>
-	<h2>Implementation starting to work mid-2008.</h2>
-	<h2>Released as an open source project in November 2009.</h2>
-	<h2>Work continues.<h2>
-	<h2>Robert Griesemer, Ken Thompson, Rob Pike, Ian Lance Taylor, Russ Cox, many others</h2>
-</div>
-
-<div class="slide">
-	<h1>Goals and Motivation</h1>
-	
-	<h2>Go fast!</h2>
-	<h2>Make programming fun again.</h2>
-	<h2>Targeted at systems software, broadly.</h2>
-</div>
-
-<div class="slide">
-	<h1>Why isn't programming fun?</h1>
-	
-	<div class="incremental">
-	<h2>Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:</h2>
-	
-	<ul>
-		<li>verbose, lots of repetition</li>
-		<li>too much focus on type hierarchy</li>
-		<li>types get in the way as much as they help</li>
-		<li>compiles take far too long</li>
-	</ul>
-	</div>
-	
-	<div class="incremental">
-	<h2>Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:</h2>
-	
-	<ul>
-		<li>errors at run time that should be caught statically</li>
-		<li>no compilation means slow code</li>
-	</ul>
-	</div>
-	
-	<h2 class="incremental">Can we combine the best of both?</h2>
-</div>
-
-<div class="slide">
-	<h1>Why a new language?</h1>
-	
-	<div class="incremental">
-	<h2>No new systems language in 10+ years.</h2>
-	<h2>Current languages designed before ...</h2>
-	<h3>... rise of large-scale, networked and multicore computing</h3>
-	<h3>... rise of Internet-scale distributed development (many libraries)</h3>
-	</div>
-</div>
-	
-<div class="slide">
-	<h1>Go</h1>
-	
-	<h2>Make the language fast.</h2>
-	<h2>Make the tools fast.</h2>
-</div>
-
-<div class="slide">
-	<h1>Compilation Demo</h1>
-	
-	<h2>Build all standard Go packages: ~120,000 lines of code.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go in one slide</h1>
-	
-	<h2 class="incremental">Lightweight syntax.</h2>
-	
-	<h2 class="incremental">Static types: enough to compile well, but inferred much of the time.</h2>
-	
-	<h2 class="incremental">Methods: on any type, orthogonal to type system.</h2>
-	
-	<h2 class="incremental">Abstract types: interface values, relations inferred statically.</h2>
-	
-	<h2 class="incremental">Visibility: inferred from case of name.</h2>
-
-	<h2 class="incremental">First-class functions.</h2>
-	
-	<h2 class="incremental">Garbage collection.</h2>
-
-	<br/>
-	
-	<h2 class="incremental">Lightweight feel of a scripting language but compiled.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go, concurrently</h1>
-	
-	<h2>Cheap to create a new flow of control (goroutine):</h2>
-	
-<pre>
-func main() {
-	go expensiveComputation(x, y, z)
-	anotherExpensiveComputation(a, b, c)
-}
-</pre>
-
-	<h2>Two expensive computations in parallel.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go, concurrently</h1>
-	
-	<h2>Cheap to create a new flow of control (goroutine):</h2>
-	
-<pre>
-	for {
-		rw := l.Accept()
-		conn := newConn(rw, handler)
-		go conn.serve()
-	}
-</pre>
-
-	<h2>Concurrent web server.</h2>
-	<h2>Network connections multiplexed onto epoll.</h2>
-		<ul>
-		<li>many blocked Read calls != many blocked OS threads</li>
-		</ul>
-
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>Use explicit messages to communicate and synchronize.</h2>
-	
-<pre>
-func computeAndSend(ch chan int, x, y, z int) {
-	ch <- expensiveComputation(x, y, z)
-}
-
-func main() {
-	ch := make(chan int)
-	go computeAndSend(ch, x, y, z)
-	v2 := anotherExpensiveComputation(a, b, c)
-	v1 := <-ch
-	fmt.Println(v1, v2)
-}
-</pre>
-	<h2>Notice communication of result in addition to synchronization.</h2>
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client</h2>
-
-<pre>
-func (client *Client) Call(method string, args, reply interface{}) os.Error {
-    // Send RPC message.
-    call := client.Go(method, args, reply, nil)
-	
-    // Read reply from Done channel.
-    <-call.Done
-
-    return call.Error
-}
-</pre>	
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		resp := client.readResponse()
-		client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()
-		if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)
-		c.Done <- c
-	}
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		<font style="color: black;">resp := client.readResponse()</font>
-		client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()
-		if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)
-		c.Done <- c
-	}
-}
-</pre>
-<h2>Read response from network.</h2
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		resp := client.readResponse()
-		<font style="color: black;">client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()</font>
-		if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)
-		c.Done <- c
-	}
-}
-</pre>
-<h2>Look up request by sequence number.</h2
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		resp := client.readResponse()
-		client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()
-		<font style="color: black;">if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)</font>
-		c.Done <- c
-	}
-}
-</pre>
-<h2>Decode response fields from payload.</h2
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		resp := client.readResponse()
-		client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()
-		if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)
-		<font style="color: black;">c.Done <- c</font>
-	}
-}
-</pre>
-<h2>Tell client that it finished.</h2
-</div>
-
-<div class="slide">
-	<h1>Go, synchronized</h1>
-	
-	<h2>RPC client demux</h2>
-
-<pre>
-func (client *Client) input() {
-	for {
-		resp := client.readResponse()
-		client.mutex.Lock()
-		c := client.pending[resp.Seq]
-		client.pending[resp.Seq] = c, false
-		client.mutex.Unlock()
-		if resp.Error != "" {
-			c.Error = os.ErrorString(resp.error)
-		}
-		resp.Decode(c.Reply)
-		c.Done <- c
-	}
-}
-</pre>
-
-<h2>Can create multiple Calls with same Done channel
-and distinguish which finished by inspecting value sent on channel.
-</h2>
-
-</div>
-
-<div class="slide">
-	<h1>Goroutine demo</h1>
-	
-	<h2>Chain together 100,000 goroutines connected by 100,001 channels.</h2>
-	
-	<h2>Send a value to one end of the chain.</h2>
-	
-	<h2>Each passes it along, increments.</h2>
-	
-	<h2>Receive value out the other end of the chain.</h2>
-</div>
-	
-
-<div class="slide">
-	<h1>Go Status</h1>
-</div>
-
-<div class="slide">
-	<h1>Go Status</h1>
-	
-	<h2>Open source:</h2>
-	<ul>
-	<li>released on November 10, 2009
-	<li>regular releases (~ weekly)
-	<li>all development done in public Mercurial repository
-	<li>outside contributions welcome
-	<li>two independent compiler implementations
-	<li>XML, JSON, HTTP, TLS/SSL, native RPC, (network channels,) ...
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Go Status</h1>
-	
-	<h2>Open source</h2>
-
-	<h2>Portable:</h2>
-	<ul>
-	<li>FreeBSD, Linux, OS X (x86, x86-64)
-	<li>(in progress) Linux arm, Native Client x86, Windows x86.
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Go Status</h1>
-	
-	<h2>Open source</h2>
-	<h2>Portable</h2>
-
-	<h2>Still in progress, experimental.  Yet to come:</h2>
-	<ul>
-	<li>production garbage collector
-	<li>generics?
-	<li>exceptions?
-	<li>unions or sum types?
-	</ul>
-</div>
-
-<div class="slide titlepage">
-	<h1>Questions?</h1>
-	<br><br>
-	<center>
-	<img src="../gordon/bumper640x360.png">
-	</center>
-	<br><br>
-	<div style="color: #ffcc00;">
-	<!-- <h3><i>rsc at google.com</i></h3> -->
-	</div>
-</div>
-
-</body></html>
diff --git a/doc/talks/go_talk-20100323.html b/doc/talks/go_talk-20100323.html
deleted file mode 100644
index 7330dd2..0000000
--- a/doc/talks/go_talk-20100323.html
+++ /dev/null
@@ -1,395 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<title>Go Tech Talk</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="font-size-adjustment" content="-1" />
-<link rel="stylesheet" href="slidy.css"
-  type="text/css" media="screen, projection, print" />
-<script src="slidy.js" type="text/javascript">
-</script>
-</head>
-<body>
-<!-- this defines the slide background -->
-
-<div class="background">
-
-  <div class="header">
-  <!-- sized and colored via CSS -->
-  </div>
-
-  <div class="footer"></div>
-  </div>
-
-<div class="slide titlepage">
-<br/>
-<br/>
-<img src="../go-logo-white.png" width="588px" height="217px">
-<br/>
-<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
-<div style="color: #ffcc00;">
-<br/>
-<h3>Sydney University<br/><br/>March 23, 2010</h3>
-</div>
-</div>
-
-<div class="slide">
-	<h1>Go</h1>
-
-	<h2>New</h2>
-	<h2>Experimental</h2>
-	<h2>Concurrent</h2>
-	<h2>Garbage Collected</h2>
-	<h2>Systems Language</h2>
-</div>
-
-<div class="slide">
-	<h1>Hello, world</h1>
-<pre>
-package main
-
-import "fmt"
-
-func main() {
-	fmt.Printf("Hello, 世界\n")
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Hello, world 2.0</h1>
-
-	<h2>Serving <a href="http://localhost:8080/world">http://localhost:8080/world</a></h2>
-<pre>
-package main
-
-import (
-	"fmt"
-	"http"
-)
-
-func handler(c *http.Conn, r *http.Request) { 
-	fmt.Fprintf(c, "Hello, %s.", r.URL.Path[1:]) 
-}
-
-func main() {
-	http.ListenAndServe(":8080",
-			http.HandlerFunc(handler))
-}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>New</h1>
-	
-	<h2>It's about two years old:</h2>
-	<ul>
-		<li>Design started in late 2007</li>
-		<li>Implementation starting to work mid-2008</li>
-		<li>Released as an open source project in November 2009</li>
-		<li>Development continues with an active community</li>
-	</ul>
-
-	<h2>Why invent a new language? Older languages weren't designed for concurrency, but modern software needs it:</h2>
-	<ul>
-		<li>Large scale, networked computing, such as Google web search</li>
-		<li>Multi-core hardware</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>New</h1>
-	
-	<h2>Older languages are also frustrating on a day-to-day basis</h2>
-	<h2>Statically-typed languages (C, C++, Java) have issues:</h2>
-	<ul>
-		<li>Edit-Compile-Run cycle takes far too long</li>
-		<li>Type hierarchy can hurt as much as it helps</li>
-	</ul>
-<div style="text-align:center">
-<img src="java-typing.png" width="800px" height="90px"><br>
-</div>
-	
-	<h2>Dynamic languages (Python, JavaScript) fix some issues but introduce others:</h2>
-	<ul>
-		<li>No compilation means slow code</li>
-		<li>Runtime errors that should be caught statically</li>
-	</ul>
-
-	<h2>Go has the lighter feel of a scripting language but is compiled</h2>
-</div>
-
-<div class="slide">
-	<h1>New</h1>
-
-	<h2>Large C++ programs (e.g. Firefox, OpenOffice, Chromium) have enormous build times:</h2>
-	<ul>
-		<li>XKCD's #1 Programmer Excuse for Legitimately Slacking Off: "<a href="http://xkcd.com/303/">My Code's Compiling</a>"</li>
-	</ul>
-
-	<h2>On a Mac (OS X 10.5.8, gcc 4.0.1):</h2>
-	<ul>
-		<li>C: <code>#include <stdio.h></code> reads 360 lines from 9 files</li>
-		<li>C++: <code>#include <iostream></code> reads 25,326 lines from 131 files</li>
-		<li>Objective-C: <code>#include <Carbon/Carbon.h></code> reads 124,730 lines from 689 files</li>
-		<li>We haven't done any real work yet!</li>
-	</ul>
-				
-	<h2>In Go: <code>import "fmt"</code> reads <i>one</i> file: 184 lines summarizing 7 packages</h2>
-</div>
-
-<div class="slide">
-	<h1>New</h1>
-
-	<h2>Compilation demo</h2>
-</div>
-
-<div class="slide">
-	<h1>Experimental</h1>
-	
-	<h2>Go is still unproven</h2>
-	<h2>Language is still evolving</h2>
-	<h2>Package library is incomplete</h2>
-	<h2>Concurrent garbage collection is an active research problem</h2>
-	<h2>Reviving forgotten concepts:</h2>
-	<ul>
-		<li>Go's concurrency is strongly influenced by <i>Communicating Sequential Processes</i> (Hoare, 1978)</li>
-		<li>Go has types and interfaces, but no inheritance. It is arguably more object-oriented than previously mentioned languages, being closer to the original Smalltalk meaning (1970s)</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>Unix philosophy: write <i>programs</i> that do one thing and do it well</h2>
-	<h2>Connect them with <i>pipes</i>:</h2>
-	<ul>
-		<li>How many lines of test code are there in the Go standard library?</li>
-		<li><code>find ~/go/src/pkg | grep _test.go$ | xargs wc -l</code></li>
-	</ul>
-
-	<h2>Unlike other languages, Go makes it easy to:</h2>
-	<ul>
-		<li>Launch <i>goroutines</i></li>
-		<li>Connect them with <i>channels</i></li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>Start a new flow of control with the <code>go</code> keyword</h2>
-	<h2>Parallel computation is easy:</h2>
-<pre>
-func main() {
-	go expensiveComputation(x, y, z)
-	anotherExpensiveComputation(a, b, c)
-}
-</pre>
-
-	<h2>Roughly speaking, a goroutine is like a thread, but lighter weight:</h2>
-	<ul>
-		<li>Goroutines have segmented stacks, and typically smaller stacks</li>
-		<li>This requires compiler support. Goroutines can't just be a C++ library on top of a thread library</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>Consider web servers ("the C10k problem"):</h2>
-	<ul>
-		<li>"Thread per connection" approach is conceptually neat, but doesn't scale well in practice</li>
-		<li>What does scale well (event-driven callbacks, asynchronous APIs) are harder to understand, maintain, and debug</li>
-		<li>We think "goroutine per connection" can scale well, and is conceptually neat</li>
-	</ul>
-<pre>
-	for {
-		rw := socket.Accept()
-		conn := newConn(rw, handler)
-		go conn.serve()
-	}
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>Let's look again at our simple parallel computation:</h2>
-<pre>
-func main() {
-	go expensiveComputation(x, y, z)
-	anotherExpensiveComputation(a, b, c)
-}
-</pre>
-
-	<h2>This story is incomplete:</h2>
-	<ul>
-		<li>How do we know when the two computations are done?</li>
-		<li>What are their values?</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>Goroutines communicate with other goroutines via channels</h2>
-<pre>
-func computeAndSend(ch chan int, x, y, z int) {
-	ch <- expensiveComputation(x, y, z)
-}
-
-func main() {
-	ch := make(chan int)
-	go computeAndSend(ch, x, y, z)
-	v2 := anotherExpensiveComputation(a, b, c)
-	v1 := <-ch
-	fmt.Println(v1, v2)
-}
-</pre>
-
-</div>
-
-<div class="slide">
-	<h1>Concurrent</h1>
-	
-	<h2>In traditional concurrent programs, you <i>communicate by sharing memory</i>. In Go, you <i>share memory by communicating</i>:</h2>
-	<ul>
-		<li>Communication (the <code><-</code> operator) is sharing and synchronization</li>
-	</ul>
-
-	<h2>Threads and locks are concurrency primitives; CSP is a concurrency model:</h2>
-	<ul>
-		<li>Analogy: "Go To Statement Considered Harmful" (Dijsktra, 1968)</li>
-		<li><code>goto</code> is a control flow primitive; structured programming (<code>if</code> statements, <code>for</code> loops, function calls) is a control flow model</li>
-	</ul>
-
-	<h2>Learning CSP changes the way you think about concurrent programming:</h2>
-	<ul>
-		<li>Every language has its grain. If your Go program uses mutexes, you're probably working against the grain</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Garbage Collected</h1>
-	
-	<h2>Automatic memory management makes writing (and maintaining) programs easier</h2>
-	<h2>Especially in a concurrent world:</h2>
-	<ul>
-		<li>Who "owns" a shared piece of memory, and is responsible for destroying it?</li>
-	</ul>
-
-	<h2>Large C++ programs usually end up with semi-automatic memory management anyway, via "smart pointers"</h2>
-	<h2>Mixing the two models can be problematic:</h2>
-	<ul>
-		<li>Browsers can leak memory easily; DOM elements are C++ objects, but JavaScript is garbage collected</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Garbage Collected</h1>
-
-	<h2>Go is also a safer language:</h2>
-	<ul>
-		<li>Pointers but no pointer arithmetic</li>
-		<li>No dangling pointers</li>
-		<li>Variables are zero-initialized</li>
-		<li>Array access is bounds-checked</li>
-	</ul>
-
-	<h2>No buffer overflow exploits</h2>
-</div>
-
-<div class="slide">
-	<h1>Systems Language</h1>
-
-	<h2>This just means you could write decently large programs in Go:</h2>
-	<ul>
-		<li>Web servers</li>
-		<li>Web browsers</li>
-		<li>Web crawlers</li>
-		<li>Search indexers</li>
-		<li>Databases</li>
-		<li>Word processors</li>
-		<li>Integrated Development Environments (IDEs)</li>
-		<li>Operating systems</li>
-		<li>...</li>
-	</ul>
-</div>
-
-<div class="slide">
-	<h1>Systems Language</h1>
-
-	<h2>Garbage collection has a reputation for being "slower"</h2>
-	<h2>We're expecting Go to be slightly slower than optimized C, but faster than Java, depending on the task. Nonetheless:</h2>
-	<ul>
-		<li>Fast and buggy is worse than almost-as-fast and correct</li>
-		<li>It is easier to optimize a correct program than to correct an optimized program</li>
-		<li>Fundamentally, it's simply a trade-off we're willing to make</li>
-	</ul>
-
-	<h2>Memory layout can drastically affect performance. These two designs are equivalent in Go, but significantly different in Java:</h2>
-<pre>
-type Point struct { X, Y int }
-type Rect struct { P0, P1 Point }
-
-// or ...
-
-type Rect struct { X0, Y0, X1, Y1 int }
-</pre>
-</div>
-
-<div class="slide">
-	<h1>Systems Language</h1>
-	
-	<h2>Quote from http://loadcode.blogspot.com/2009/12/go-vs-java.html</h2>
-
-<h2>
-"[Git] is known to be very fast. It is written in C. A Java version
-JGit was made. It was considerably slower. Handling of memory and lack
-of unsigned types was some of the important reasons.
-</h2>
-
-<h2>Shawn O. Pearce wrote on the git mailinglist:</h2>
-<ul><li>"JGit struggles with not
-having an efficient way to represent a SHA-1. C can just say "unsigned
-char[20]" and have it inline into the container's memory allocation. A
-byte[20] in Java will cost an *additional* 16 bytes of memory, and be
-slower to access because the bytes themselves are in a different area
-of memory from the container object. We try to work around it by
-converting from a byte[20] to 5 ints, but that costs us machine
-instructions"
-</li></ul>
-
-<h2>
-Like C, Go does allow unsigned types and defining data structures
-containing other data structures as continuous blocks of memory."
-</h2>
-</div>
-
-<div class="slide">
-	<h1>Go</h1>
-
-	<h2>New</h2>
-	<h2>Experimental</h2>
-	<h2>Concurrent</h2>
-	<h2>Garbage Collected</h2>
-	<h2>Systems Language</h2>
-
-	<h2>And more:</h2>
-	<ul>
-		<li>I haven't talked about the type system, interfaces, slices, closures, selects, ...</li>
-		<li>Documentation, mailing list, source code all online</li>
-	</ul>
-</div>
-
-<div class="slide titlepage">
-	<h1>Questions?</h1>
-	<br><br>
-	<center>
-	<img src="../gordon/bumper640x360.png" width="640px" height="360px">
-	</center>
-</div>
-
-</body></html>
diff --git a/doc/talks/gofrontend-gcc-summit-2010.pdf b/doc/talks/gofrontend-gcc-summit-2010.pdf
deleted file mode 100644
index 157fd76..0000000
Binary files a/doc/talks/gofrontend-gcc-summit-2010.pdf and /dev/null differ
diff --git a/doc/talks/io2010/balance.go b/doc/talks/io2010/balance.go
deleted file mode 100644
index a3825cb..0000000
--- a/doc/talks/io2010/balance.go
+++ /dev/null
@@ -1,168 +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 main
-
-import (
-	"container/heap"
-	"flag"
-	"fmt"
-	"math/rand"
-	"time"
-)
-
-const nRequester = 100
-const nWorker = 10
-
-var roundRobin = flag.Bool("r", false, "use round-robin scheduling")
-
-// Simulation of some work: just sleep for a while and report how long.
-func op() int {
-	n := rand.Int63n(1e9)
-	time.Sleep(nWorker * n)
-	return int(n)
-}
-
-type Request struct {
-	fn func() int
-	c  chan int
-}
-
-func requester(work chan Request) {
-	c := make(chan int)
-	for {
-		time.Sleep(rand.Int63n(nWorker * 2e9))
-		work <- Request{op, c}
-		<-c
-	}
-}
-
-type Worker struct {
-	i        int
-	requests chan Request
-	pending  int
-}
-
-func (w *Worker) work(done chan *Worker) {
-	for {
-		req := <-w.requests
-		req.c <- req.fn()
-		done <- w
-	}
-}
-
-type Pool []*Worker
-
-func (p Pool) Len() int { return len(p) }
-
-func (p Pool) Less(i, j int) bool {
-	return p[i].pending < p[j].pending
-}
-
-func (p *Pool) Swap(i, j int) {
-	a := *p
-	a[i], a[j] = a[j], a[i]
-	a[i].i = i
-	a[j].i = j
-}
-
-func (p *Pool) Push(x interface{}) {
-	a := *p
-	n := len(a)
-	a = a[0 : n+1]
-	w := x.(*Worker)
-	a[n] = w
-	w.i = n
-	*p = a
-}
-
-func (p *Pool) Pop() interface{} {
-	a := *p
-	*p = a[0 : len(a)-1]
-	w := a[len(a)-1]
-	w.i = -1 // for safety
-	return w
-}
-
-type Balancer struct {
-	pool Pool
-	done chan *Worker
-	i    int
-}
-
-func NewBalancer() *Balancer {
-	done := make(chan *Worker, nWorker)
-	b := &Balancer{make(Pool, 0, nWorker), done, 0}
-	for i := 0; i < nWorker; i++ {
-		w := &Worker{requests: make(chan Request, nRequester)}
-		heap.Push(&b.pool, w)
-		go w.work(b.done)
-	}
-	return b
-}
-
-func (b *Balancer) balance(work chan Request) {
-	for {
-		select {
-		case req := <-work:
-			b.dispatch(req)
-		case w := <-b.done:
-			b.completed(w)
-		}
-		b.print()
-	}
-}
-
-func (b *Balancer) print() {
-	sum := 0
-	sumsq := 0
-	for _, w := range b.pool {
-		fmt.Printf("%d ", w.pending)
-		sum += w.pending
-		sumsq += w.pending * w.pending
-	}
-	avg := float64(sum) / float64(len(b.pool))
-	variance := float64(sumsq)/float64(len(b.pool)) - avg*avg
-	fmt.Printf(" %.2f %.2f\n", avg, variance)
-}
-
-func (b *Balancer) dispatch(req Request) {
-	if *roundRobin {
-		w := b.pool[b.i]
-		w.requests <- req
-		w.pending++
-		b.i++
-		if b.i >= len(b.pool) {
-			b.i = 0
-		}
-		return
-	}
-
-	w := heap.Pop(&b.pool).(*Worker)
-	w.requests <- req
-	w.pending++
-	//	fmt.Printf("started %p; now %d\n", w, w.pending)
-	heap.Push(&b.pool, w)
-}
-
-func (b *Balancer) completed(w *Worker) {
-	if *roundRobin {
-		w.pending--
-		return
-	}
-
-	w.pending--
-	//	fmt.Printf("finished %p; now %d\n", w, w.pending)
-	heap.Remove(&b.pool, w.i)
-	heap.Push(&b.pool, w)
-}
-
-func main() {
-	flag.Parse()
-	work := make(chan Request)
-	for i := 0; i < nRequester; i++ {
-		go requester(work)
-	}
-	NewBalancer().balance(work)
-}
diff --git a/doc/talks/io2010/decrypt.go b/doc/talks/io2010/decrypt.go
deleted file mode 100644
index e63418b..0000000
--- a/doc/talks/io2010/decrypt.go
+++ /dev/null
@@ -1,85 +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.
-
-// This code differs from the slides in that it handles errors.
-
-package main
-
-import (
-	"crypto/aes"
-	"crypto/cipher"
-	"compress/gzip"
-	"io"
-	"log"
-	"os"
-)
-
-func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) error {
-	r, err := os.Open(srcfile)
-	if err != nil {
-		return err
-	}
-	var w io.Writer
-	w, err = os.Create(dstfile)
-	if err != nil {
-		return err
-	}
-	c, err := aes.NewCipher(key)
-	if err != nil {
-		return err
-	}
-	w = cipher.StreamWriter{S: cipher.NewOFB(c, iv), W: w}
-	w2, err := gzip.NewWriter(w)
-	if err != nil {
-		return err
-	}
-	defer w2.Close()
-	_, err = io.Copy(w2, r)
-	return err
-}
-
-func DecryptAndGunzip(dstfile, srcfile string, key, iv []byte) error {
-	f, err := os.Open(srcfile)
-	if err != nil {
-		return err
-	}
-	defer f.Close()
-	c, err := aes.NewCipher(key)
-	if err != nil {
-		return err
-	}
-	r := cipher.StreamReader{S: cipher.NewOFB(c, iv), R: f}
-	r2, err := gzip.NewReader(r)
-	if err != nil {
-		return err
-	}
-	w, err := os.Create(dstfile)
-	if err != nil {
-		return err
-	}
-	defer w.Close()
-	_, err = io.Copy(w, r2)
-	return err
-}
-
-func main() {
-	err := EncryptAndGzip(
-		"/tmp/passwd.gz",
-		"/etc/passwd",
-		make([]byte, 16),
-		make([]byte, 16),
-	)
-	if err != nil {
-		log.Fatal(err)
-	}
-	err = DecryptAndGunzip(
-		"/dev/stdout",
-		"/tmp/passwd.gz",
-		make([]byte, 16),
-		make([]byte, 16),
-	)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/doc/talks/io2010/encrypt.go b/doc/talks/io2010/encrypt.go
deleted file mode 100644
index 57c888c..0000000
--- a/doc/talks/io2010/encrypt.go
+++ /dev/null
@@ -1,52 +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.
-
-// This code differs from the slides in that it handles errors.
-
-package main
-
-import (
-	"crypto/aes"
-	"crypto/cipher"
-	"compress/gzip"
-	"io"
-	"log"
-	"os"
-)
-
-func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) error {
-	r, err := os.Open(srcfile)
-	if err != nil {
-		return err
-	}
-	var w io.WriteCloser
-	w, err = os.Create(dstfile)
-	if err != nil {
-		return err
-	}
-	defer w.Close()
-	w, err = gzip.NewWriter(w)
-	if err != nil {
-		return err
-	}
-	defer w.Close()
-	c, err := aes.NewCipher(key)
-	if err != nil {
-		return err
-	}
-	_, err = io.Copy(cipher.StreamWriter{S: cipher.NewOFB(c, iv), W: w}, r)
-	return err
-}
-
-func main() {
-	err := EncryptAndGzip(
-		"/tmp/passwd.gz",
-		"/etc/passwd",
-		make([]byte, 16),
-		make([]byte, 16),
-	)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
diff --git a/doc/talks/io2010/eval1.go b/doc/talks/io2010/eval1.go
deleted file mode 100644
index 582f43e..0000000
--- a/doc/talks/io2010/eval1.go
+++ /dev/null
@@ -1,227 +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 main
-
-import (
-	"bufio"
-	"fmt"
-	"os"
-	"strconv"
-	"strings"
-)
-
-// Generic expression parser/evaluator
-
-type Value interface {
-	String() string
-	BinaryOp(op string, y Value) Value
-}
-
-type Parser struct {
-	precTab map[string]int
-	newVal  func(string) Value
-	src     string
-	pos     int
-	tok     string
-}
-
-const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-
-func (p *Parser) stop(c uint8) bool {
-	switch {
-	case p.pos >= len(p.src):
-		return true
-	case c == '"':
-		if p.src[p.pos] == '"' {
-			p.pos++
-			return true
-		}
-		return false
-	case strings.IndexRune(alphanum, int(c)) >= 0:
-		return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0
-	}
-	return true
-}
-
-func (p *Parser) next() {
-	// skip blanks
-	for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ {
-	}
-	if p.pos >= len(p.src) {
-		p.tok = ""
-		return
-	}
-	start := p.pos
-	c := p.src[p.pos]
-	for p.pos < len(p.src) {
-		p.pos++
-		if p.stop(c) {
-			break
-		}
-	}
-	p.tok = p.src[start:p.pos]
-}
-
-func (p *Parser) binaryExpr(prec1 int) Value {
-	x := p.newVal(p.tok)
-	p.next()
-	for prec := p.precTab[p.tok]; prec >= prec1; prec-- {
-		for p.precTab[p.tok] == prec {
-			op := p.tok
-			p.next()
-			y := p.binaryExpr(prec + 1)
-			x = x.BinaryOp(op, y)
-		}
-	}
-	return x
-}
-
-func Eval(precTab map[string]int, newVal func(string) Value, src string) Value {
-	var p Parser
-	p.precTab = precTab
-	p.newVal = newVal
-	p.src = src
-	p.next()
-	return p.binaryExpr(1)
-}
-
-// Command-line expression evaluator
-
-func main() {
-	r := bufio.NewReader(os.Stdin)
-	for {
-		fmt.Printf("> ")
-		line, err := r.ReadString('\n')
-		if err != nil {
-			break
-		}
-		fmt.Printf("%s\n", Eval(precTab, trace(newVal), line))
-	}
-}
-
-// Custom grammar and values
-
-var precTab = map[string]int{
-	"&&": 1,
-	"||": 2,
-	"==": 3,
-	"!=": 3,
-	"<":  3,
-	"<=": 3,
-	">":  3,
-	">=": 3,
-	"+":  4,
-	"-":  4,
-	"*":  5,
-	"/":  5,
-	"%":  5,
-}
-
-func newVal(lit string) Value {
-	x, err := strconv.Atoi(lit)
-	if err == nil {
-		return Int(x)
-	}
-	b, err := strconv.ParseBool(lit)
-	if err == nil {
-		return Bool(b)
-	}
-	return Error(fmt.Sprintf("illegal literal '%s'", lit))
-}
-
-type Error string
-
-func (e Error) String() string                    { return string(e) }
-func (e Error) BinaryOp(op string, y Value) Value { return e }
-
-type Int int
-
-func (x Int) String() string { return strconv.Itoa(int(x)) }
-func (x Int) BinaryOp(op string, y Value) Value {
-	switch y := y.(type) {
-	case Error:
-		return y
-	case Int:
-		switch op {
-		case "+":
-			return x + y
-		case "-":
-			return x - y
-		case "*":
-			return x * y
-		case "/":
-			return x / y
-		case "%":
-			return x % y
-		case "==":
-			return Bool(x == y)
-		case "!=":
-			return Bool(x != y)
-		case "<":
-			return Bool(x < y)
-		case "<=":
-			return Bool(x <= y)
-		case ">":
-			return Bool(x > y)
-		case ">=":
-			return Bool(x >= y)
-		}
-	}
-	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
-}
-
-type Bool bool
-
-func (x Bool) String() string { return strconv.FormatBool(bool(x)) }
-func (x Bool) BinaryOp(op string, y Value) Value {
-	switch y := y.(type) {
-	case Error:
-		return y
-	case Bool:
-		switch op {
-		case "&&":
-			return Bool(x && y)
-		case "||":
-			return Bool(x || y)
-		case "==":
-			return Bool(x == y)
-		case "!=":
-			return Bool(x != y)
-		}
-	}
-	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
-}
-
-func trace(newVal func(string) Value) func(string) Value {
-	return func(s string) Value {
-		v := newVal(s)
-		fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v))
-		return &traceValue{v}
-	}
-}
-
-type traceValue struct {
-	Value
-}
-
-func (x *traceValue) BinaryOp(op string, y Value) Value {
-	z := x.Value.BinaryOp(op, y.(*traceValue).Value)
-	fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z))
-	return &traceValue{z}
-}
-
-func (x *traceValue) String() string {
-	s := x.Value.String()
-	fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s)
-	return s
-}
-
-func fmtv(v Value) string {
-	t := fmt.Sprintf("%T", v)
-	if i := strings.LastIndex(t, "."); i >= 0 { // strip package
-		t = t[i+1:]
-	}
-	return fmt.Sprintf("%s(%#v)", t, v)
-}
diff --git a/doc/talks/io2010/eval2.go b/doc/talks/io2010/eval2.go
deleted file mode 100644
index 6f826e1..0000000
--- a/doc/talks/io2010/eval2.go
+++ /dev/null
@@ -1,259 +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 main
-
-import (
-	"bufio"
-	"fmt"
-	"os"
-	"strconv"
-	"strings"
-)
-
-// Generic expression parser/evaluator
-
-type Value interface {
-	String() string
-	BinaryOp(op string, y Value) Value
-}
-
-type Parser struct {
-	precTab map[string]int
-	newVal  func(string) Value
-	src     string
-	pos     int
-	tok     string
-}
-
-const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-
-func (p *Parser) stop(c uint8) bool {
-	switch {
-	case p.pos >= len(p.src):
-		return true
-	case c == '"':
-		if p.src[p.pos] == '"' {
-			p.pos++
-			return true
-		}
-		return false
-	case strings.IndexRune(alphanum, int(c)) >= 0:
-		return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0
-	}
-	return true
-}
-
-func (p *Parser) next() {
-	// skip blanks
-	for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ {
-	}
-	if p.pos >= len(p.src) {
-		p.tok = ""
-		return
-	}
-	start := p.pos
-	c := p.src[p.pos]
-	for p.pos < len(p.src) {
-		p.pos++
-		if p.stop(c) {
-			break
-		}
-	}
-	p.tok = p.src[start:p.pos]
-}
-
-func (p *Parser) binaryExpr(prec1 int) Value {
-	x := p.newVal(p.tok)
-	p.next()
-	for prec := p.precTab[p.tok]; prec >= prec1; prec-- {
-		for p.precTab[p.tok] == prec {
-			op := p.tok
-			p.next()
-			y := p.binaryExpr(prec + 1)
-			x = x.BinaryOp(op, y)
-		}
-	}
-	return x
-}
-
-func Eval(precTab map[string]int, newVal func(string) Value, src string) Value {
-	var p Parser
-	p.precTab = precTab
-	p.newVal = newVal
-	p.src = src
-	p.next()
-	return p.binaryExpr(1)
-}
-
-// Command-line expression evaluator
-
-func main() {
-	r := bufio.NewReader(os.Stdin)
-	for {
-		fmt.Printf("> ")
-		line, err := r.ReadString('\n')
-		if err != nil {
-			break
-		}
-		fmt.Printf("%s\n", Eval(precTab, trace(newVal), line))
-	}
-}
-
-// Custom grammar and values
-
-var precTab = map[string]int{
-	"&&": 1,
-	"||": 2,
-	"==": 3,
-	"!=": 3,
-	"<":  3,
-	"<=": 3,
-	">":  3,
-	">=": 3,
-	"+":  4,
-	"-":  4,
-	"*":  5,
-	"/":  5,
-	"%":  5,
-}
-
-func newVal(lit string) Value {
-	x, err := strconv.Atoi(lit)
-	if err == nil {
-		return Int(x)
-	}
-	b, err := strconv.ParseBool(lit)
-	if err == nil {
-		return Bool(b)
-	}
-	s, err := strconv.Unquote(lit)
-	if err == nil {
-		return String(s)
-	}
-	return Error(fmt.Sprintf("illegal literal '%s'", lit))
-}
-
-type Error string
-
-func (e Error) String() string                    { return string(e) }
-func (e Error) BinaryOp(op string, y Value) Value { return e }
-
-type Int int
-
-func (x Int) String() string { return strconv.Itoa(int(x)) }
-func (x Int) BinaryOp(op string, y Value) Value {
-	switch y := y.(type) {
-	case Error:
-		return y
-	case String:
-		switch op {
-		case "*":
-			return String(strings.Repeat(string(y), int(x)))
-		}
-	case Int:
-		switch op {
-		case "+":
-			return x + y
-		case "-":
-			return x - y
-		case "*":
-			return x * y
-		case "/":
-			return x / y
-		case "%":
-			return x % y
-		case "==":
-			return Bool(x == y)
-		case "!=":
-			return Bool(x != y)
-		case "<":
-			return Bool(x < y)
-		case "<=":
-			return Bool(x <= y)
-		case ">":
-			return Bool(x > y)
-		case ">=":
-			return Bool(x >= y)
-		}
-	}
-	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
-}
-
-type Bool bool
-
-func (x Bool) String() string { return strconv.FormatBool(bool(x)) }
-func (x Bool) BinaryOp(op string, y Value) Value {
-	switch y := y.(type) {
-	case Error:
-		return y
-	case Bool:
-		switch op {
-		case "&&":
-			return Bool(x && y)
-		case "||":
-			return Bool(x || y)
-		case "==":
-			return Bool(x == y)
-		case "!=":
-			return Bool(x != y)
-		}
-	}
-	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
-}
-
-type String string
-
-func (x String) String() string { return strconv.Quote(string(x)) }
-func (x String) BinaryOp(op string, y Value) Value {
-	switch y := y.(type) {
-	case Error:
-		return y
-	case Int:
-		switch op {
-		case "*":
-			return String(strings.Repeat(string(x), int(y)))
-		}
-	case String:
-		switch op {
-		case "+":
-			return x + y
-		case "<":
-			return Bool(x < y)
-		}
-	}
-	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
-}
-
-func trace(newVal func(string) Value) func(string) Value {
-	return func(s string) Value {
-		v := newVal(s)
-		fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v))
-		return &traceValue{v}
-	}
-}
-
-type traceValue struct {
-	Value
-}
-
-func (x *traceValue) BinaryOp(op string, y Value) Value {
-	z := x.Value.BinaryOp(op, y.(*traceValue).Value)
-	fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z))
-	return &traceValue{z}
-}
-
-func (x *traceValue) String() string {
-	s := x.Value.String()
-	fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s)
-	return s
-}
-
-func fmtv(v Value) string {
-	t := fmt.Sprintf("%T", v)
-	if i := strings.LastIndex(t, "."); i >= 0 { // strip package
-		t = t[i+1:]
-	}
-	return fmt.Sprintf("%s(%#v)", t, v)
-}
diff --git a/doc/talks/io2010/talk.pdf b/doc/talks/io2010/talk.pdf
deleted file mode 100644
index aff42c2..0000000
Binary files a/doc/talks/io2010/talk.pdf and /dev/null differ
diff --git a/doc/talks/io2011/Real_World_Go.pdf b/doc/talks/io2011/Real_World_Go.pdf
deleted file mode 100644
index 2a18711..0000000
Binary files a/doc/talks/io2011/Real_World_Go.pdf and /dev/null differ
diff --git a/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf b/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf
deleted file mode 100644
index ca4702e..0000000
Binary files a/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf and /dev/null differ
diff --git a/doc/talks/java-typing.png b/doc/talks/java-typing.png
deleted file mode 100644
index 54abf01..0000000
Binary files a/doc/talks/java-typing.png and /dev/null differ
diff --git a/doc/talks/slidy.css b/doc/talks/slidy.css
deleted file mode 100644
index e9ff532..0000000
--- a/doc/talks/slidy.css
+++ /dev/null
@@ -1,277 +0,0 @@
-/* http://www.w3.org/Talks/Tools/Slidy/slidy.css
-
-   Copyright (c) 2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
-   W3C liability, trademark, document use and software licensing
-   rules apply, see:
-
-   http://www.w3.org/Consortium/Legal/copyright-documents
-   http://www.w3.org/Consortium/Legal/copyright-software
-*/
-body
-{
-  margin: 0 0 0 0;
-  padding: 0 0 0 0;
-  width: 100%;
-  height: 100%;
-  color: black;
-  background-color: white;
-  font-family: "Lucida Sans", "Lucida Grande", Lucida, sans-serif;
-  font-size: 14pt;
-}
-
-.hidden { display: none; visibility: hidden }
-
-div.toolbar {
-  position: fixed; z-index: 200;
-  top: auto; bottom: 0; left: 0; right: 0;
-  height: 1.2em; text-align: right;
-  padding-left: 1em;
-  padding-right: 1em; 
-  font-size: 60%;
-  color: red; background: rgb(240,240,240);
-}
-
-div.background {
-  display: none;
-}
-
-div.handout {
-  margin-left: 20px;
-  margin-right: 20px;
-}
-
-div.slide.titlepage {
-  color: white;
-  background: black;
-  text-align: center;
-}
-
-div.slide {
-  z-index: 20;
-  margin: 0 0 0 0;
-  padding-top: 0;
-  padding-bottom: 0;
-  padding-left: 20px;
-  padding-right: 20px;
-  border-width: 0;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  line-height: 120%;
-  background-color: transparent;
-}
-
-/* this rule is hidden from IE 6 and below which don't support + selector */
-div.slide + div[class].slide { page-break-before: always;}
-
-div.slide h1 {
-  padding-left: 20px;
-  padding-right: 20px;
-  padding-top: 10px;
-  padding-bottom: 10px;
-  margin-top: 0;
-  margin-left: 0;
-  margin-right: 0;
-  margin-bottom: 0.5em;
-  border-bottom: 4px solid #36c;
-  display: block; 
-  font-size: 160%;
-  line-height: 1.2em;
-}
-
-div.slide h2 {
-  font-size:120%;
-  line-height: 1.2em;
-}
-
-div.toc {
-  position: absolute;
-  top: auto;
-  bottom: 4em;
-  left: 4em;
-  right: auto;
-  width: 60%;
-  max-width: 30em;
-  height: 30em;
-  border: solid thin black;
-  padding: 1em;
-  background: rgb(240,240,240);
-  color: black;
-  z-index: 300;
-  overflow: auto;
-  display: block;
-  visibility: visible;
-}
-
-div.toc-heading {
-  width: 100%;
-  border-bottom: solid 1px rgb(180,180,180);
-  margin-bottom: 1em;
-  text-align: center;
-}
-
-pre {
- font-size: 120%;
- font-weight: bold;
- line-height: 140%;
- padding-top: 0.2em;
- padding-bottom: 0.2em;
- padding-left: 1em;
- padding-right: 1em;
-/*
- border-style: solid;
- border-left-width: 1em;
- border-top-width: thin;
- border-right-width: thin;
- border-bottom-width: thin;
- border-color: #95ABD0;
-*/
- color: #0F398D;
- background-color: #fff8f8;
-}
-
- at media print {
-  div.slide {
-     display: block;
-     visibility: visible;
-     position: relative;
-     border-top-style: solid;
-     border-top-width: thin;
-     border-top-color: black;
-  }
-  div.slide pre { font-size: 60%; padding-left: 0.5em; }
-  div.handout { display: block; visibility: visible; }
-}
-
-blockquote { font-style: italic }
-
-img { background-color: transparent }
-
-p.copyright { font-size: smaller }
-
-.center { text-align: center }
-.footnote { font-size: smaller; margin-left: 2em; }
-
-a img { border-width: 0; border-style: none }
-
-a:visited { color: navy }
-a:link { color: navy }
-a:hover { color: red; text-decoration: underline }
-a:active { color: red; text-decoration: underline }
-
-a {text-decoration: none}
-.navbar a:link {color: white}
-.navbar a:visited {color: yellow}
-.navbar a:active {color: red}
-.navbar a:hover {color: red}
-
-ul { list-style-type: square; }
-ul ul { list-style-type: disc; }
-ul ul ul { list-style-type: circle; }
-ul ul ul ul { list-style-type: disc; }
-li { margin-left: 2em; margin-top: 0.5em; }
-li li { font-size: 85%; font-style: italic }
-li li li { font-size: 85%; font-style: normal }
-
-div dt
-{
-  margin-left: 0;
-  margin-top: 1em;
-  margin-bottom: 0.5em;
-  font-weight: bold;
-}
-div dd
-{
-  margin-left: 2em;
-  margin-bottom: 0.5em;
-}
-
-
-p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
-  margin-left: 1em;
-  margin-right: 1em;
-}
-
-p.subhead { font-weight: bold; margin-top: 2em; }
-
-p.smaller { font-size: smaller }
-
-td,th { padding: 0.2em }
-
-ul {
-  margin: 0.5em 1.5em 0.5em 1.5em;
-  padding: 0;
-}
-
-ol {
-  margin: 0.5em 1.5em 0.5em 1.5em;
-  padding: 0;
-}
-
-ul { list-style-type: square; }
-ul ul { list-style-type: disc; }
-ul ul ul { list-style-type: circle; }
-ul ul ul ul { list-style-type: disc; }
-
-ul li { 
-  list-style: square;
-  //margin: 0.1em 0em 0.6em 0;
-  padding: 0 0 0 0;
-  line-height: 140%;
-}
-
-ol li { 
-  margin: 0.1em 0em 0.6em 1.5em;
-  padding: 0 0 0 0px;
-  line-height: 140%;
-  list-style-type: decimal;
-}
-
-li ul li { 
-  font-size: 85%; 
-  font-style: italic;
-  list-style-type: disc;
-  background: transparent;
-  padding: 0 0 0 0;
-}
-li li ul li { 
-  font-size: 85%; 
-  font-style: normal;
-  list-style-type: circle;
-  background: transparent;
-  padding: 0 0 0 0;
-}
-li li li ul li {
-  list-style-type: disc;
-  background: transparent;
-  padding: 0 0 0 0;
-}
-
-li ol li {
-  list-style-type: decimal;
-}
-
-
-li li ol li {
-  list-style-type: decimal;
-}
-
-/*
- setting class="outline on ol or ul makes it behave as an
- ouline list where blocklevel content in li elements is
- hidden by default and can be expanded or collapsed with
- mouse click. Set class="expand" on li to override default
-*/
-
-ol.outline li:hover { cursor: pointer }
-ol.outline li.nofold:hover { cursor: default }
-
-ul.outline li:hover { cursor: pointer }
-ul.outline li.nofold:hover { cursor: default }
-
-ol.outline { list-style:decimal; }
-ol.outline ol { list-style-type:lower-alpha }
-
-/* for slides with class "title" in table of contents */
-a.titleslide { font-weight: bold; font-style: italic }
diff --git a/doc/talks/slidy.js b/doc/talks/slidy.js
deleted file mode 100644
index 6a5561a..0000000
--- a/doc/talks/slidy.js
+++ /dev/null
@@ -1,2772 +0,0 @@
-/* http://www.w3.org/Talks/Tools/Slidy/slidy.js
-
-   Copyright (c) 2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
-   W3C liability, trademark, document use and software licensing
-   rules apply, see:
-
-   http://www.w3.org/Consortium/Legal/copyright-documents
-   http://www.w3.org/Consortium/Legal/copyright-software
-*/
-
-var ns_pos = (typeof window.pageYOffset!='undefined');
-var khtml = ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false);
-var opera = ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false);
-var ie7 = (!ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1);
-
-window.onload = startup; // equivalent to onload on body element
-
-// IE only event handlers to ensure all slides are printed
-// I don't yet know how to emulate these for other browsers
-window.onbeforeprint = beforePrint;
-window.onafterprint = afterPrint;
-
-// hack to hide slides while loading
-setTimeout(hideAll, 50);
-
-function hideAll()
-{
-  if (document.body)
-    document.body.style.visibility = "hidden";
-  else
-    setTimeout(hideAll, 50);
-}
-
-var slidenum = 0;     // integer slide count: 0, 1, 2, ...
-var slides;           // set to array of slide div's
-var slideNumElement;  // element containing slide number
-var notes;            // set to array of handout div's
-var backgrounds;      // set to array of background div's
-var toolbar;          // element containing toolbar
-var title;            // document title
-var lastShown = null; // last incrementally shown item
-var eos = null;       // span element for end of slide indicator
-var toc = null;       // table of contents
-var outline = null;   // outline element with the focus
-var selectedTextLen;  // length of drag selection on document
-
-var viewAll = 0;      // 1 to view all slides + handouts
-var wantToolbar = 1;   // 0 if toolbar isn't wanted
-var mouseClickEnabled = true;  // enables left click for next slide
-var scrollhack = 0;   // IE work around for position: fixed
-
-var helpAnchor;  // used for keyboard focus hack in showToolbar()
-var helpPage = "http://www.w3.org/Talks/Tools/Slidy/help.html";
-var helpText = "Navigate with mouse click, space bar, Cursor Left/Right, " +
-               "or Pg Up and Pg Dn. Use S and B to change font size.";
-
-var sizeIndex = 0;
-var sizeAdjustment = 0;
-var sizes = new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt",
-                      "22pt", "24pt", "26pt", "28pt", "30pt", "32pt");
-
-var okayForIncremental = incrementalElementList();
-
-// needed for efficient resizing
-var lastWidth = 0;
-var lastHeight = 0;
-
-// Needed for cross browser support for relative width/height on
-// object elements. The work around is to save width/height attributes
-// and then to recompute absolute width/height dimensions on resizing
-var objects;
-
-// updated to language specified by html file
-var lang = "en";
-
-//var localize = {};
-
-// for each language there is an associative array
-var strings_es = {
-  "slide":"pág.",
-  "help?":"Ayuda",
-  "contents?":"Índice",
-  "table of contents":"tabla de contenidos",
-  "Table of Contents":"Tabla de Contenidos",
-  "restart presentation":"Reiniciar presentación",
-  "restart?":"Inicio"
-   };
-
-strings_es[helpText] =
-    "Utilice el ratón, barra espaciadora, teclas Izda/Dhca, " +
-    "o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente.";
-
-var strings_nl = {
-  "slide":"pagina",
-  "help?":"Help?",
-  "contents?":"Inhoud?",
-  "table of contents":"inhoudsopgave",
-  "Table of Contents":"Inhoudsopgave",
-  "restart presentation":"herstart presentatie",
-  "restart?":"Herstart?"
-   };
-
-strings_nl[helpText] =
-    "Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " +
-    "of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.";
-
-var strings_de = {
-  "slide":"Seite",
-  "help?":"Hilfe",
-  "contents?":"Übersicht",
-  "table of contents":"Inhaltsverzeichnis",
-  "Table of Contents":"Inhaltsverzeichnis",
-  "restart presentation":"Präsentation neu starten",
-  "restart?":"Neustart"
-   };
-
-strings_de[helpText] =
-    "Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts" +
-    "oder Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse.";
-
-var strings_pl = {
-  "slide":"slajd",
-  "help?":"pomoc?",
-  "contents?":"spis treści?",
-  "table of contents":"spis treści",
-  "Table of Contents":"Spis Treści",
-  "restart presentation":"Restartuj prezentację",
-  "restart?":"restart?"
-   };
-
-strings_pl[helpText] =
-    "Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" +
-    "lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.";
-
-var strings_fr = {
-  "slide":"page",
-  "help?":"Aide",
-  "contents?":"Index",
-  "table of contents":"table des matières",
-  "Table of Contents":"Table des matières",
-  "restart presentation":"Recommencer l'exposé",
-  "restart?":"Début"
-  };
-
-strings_fr[helpText] =
-    "Naviguez avec la souris, la barre d'espace, les flèches" +
-    "gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " +
-    "les touches S et B pour modifier la taille de la police.";
-
-var strings_hu = {
-  "slide":"oldal",
-  "help?":"segítség",
-  "contents?":"tartalom",
-  "table of contents":"tartalomjegyzék",
-  "Table of Contents":"Tartalomjegyzék",
-  "restart presentation":"bemutató újraindítása",
-  "restart?":"újraindítás"
-   };
-
-strings_hu[helpText] =
-    "Az oldalak közti lépkedéshez kattintson az egérrel, vagy használja a szóköz, a bal, vagy a jobb nyíl, " +
-    "illetve a Page Down, Page Up billentyűket. Az S és a B billentyűkkel változtathatja a szöveg méretét.";
-
-var strings_it = {
-  "slide":"pag.",
-  "help?":"Aiuto",
-  "contents?":"Indice",
-  "table of contents":"indice",
-  "Table of Contents":"Indice",
-  "restart presentation":"Ricominciare la presentazione",
-  "restart?":"Inizio"
-   };
-
-strings_it[helpText] =
-    "Navigare con mouse, barra spazio, frecce sinistra/destra o " +
-    "PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.";
-
-var strings_el = {
-  "slide":"σελίδα",
-  "help?":"βοήθεια;",
-  "contents?":"περιεχόμενα;",
-  "table of contents":"πίνακας περιεχομένων",
-  "Table of Contents":"Πίνακας Περιεχομένων",
-  "restart presentation":"επανεκκίνηση παρουσίασης",
-  "restart?":"επανεκκίνηση;"
-   };
-
-strings_el[helpText] =
-  "Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " +
-  "ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " +
-  "το μέγεθος της γραμματοσειράς.";
-
-var strings_ja = {
-  "slide":"スライド",
-  "help?":"ヘルプ",
-  "contents?":"目次",
-  "table of contents":"目次を表示",
-  "Table of Contents":"目次",
-  "restart presentation":"最初から再生",
-  "restart?":"最初から"
-};
-
-strings_ja[helpText] =
-    "マウス左クリック ・ スペース ・ 左右キー " +
-    "または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更";
-
-
-// each such language array is declared in the localize array
-// used indirectly as in help.innerHTML = "help".localize();
-var localize = {
-     "es":strings_es,
-     "nl":strings_nl,
-     "de":strings_de,
-     "pl":strings_pl,
-     "fr":strings_fr,
-     "hu":strings_hu,
-     "it":strings_it,
-     "el":strings_el,
-     "jp":strings_ja
-   };
-
-/* general initialization */
-function startup()
-{
-   // find human language from html element
-   // for use in localizing strings
-   lang = document.body.parentNode.getAttribute("lang");
-
-   if (!lang)
-     lang = document.body.parentNode.getAttribute("xml:lang");
-
-   if (!lang)
-     lang = "en";
-
-   document.body.style.visibility = "visible";
-   title = document.title;
-   toolbar = addToolbar();
-   wrapImplicitSlides();
-   slides = collectSlides();
-   notes = collectNotes();
-   objects = document.body.getElementsByTagName("object");
-   backgrounds = collectBackgrounds();
-   patchAnchors();
-
-   slidenum = findSlideNumber(location.href);
-   window.offscreenbuffering = true;
-   sizeAdjustment = findSizeAdjust();
-   hideImageToolbar();  // suppress IE image toolbar popup
-   initOutliner();  // activate fold/unfold support
-
-   if (slides.length > 0)
-   {
-      var slide = slides[slidenum];
-      slide.style.position = "absolute";
-   
-      if (slidenum > 0)
-      {
-         setVisibilityAllIncremental("visible");
-         lastShown = previousIncrementalItem(null);
-         setEosStatus(true);
-      }
-      else
-      {
-         lastShown = null;
-         setVisibilityAllIncremental("hidden");
-         setEosStatus(!nextIncrementalItem(lastShown));
-      }
-
-      setLocation();
-   }
-
-   toc = tableOfContents();
-   hideTableOfContents();
-
-   // bind event handlers
-   document.onclick = mouseButtonClick;
-   document.onmouseup = mouseButtonUp;
-   document.onkeydown = keyDown;
-   window.onresize  = resized;
-   window.onscroll = scrolled;
-   singleSlideView();
-
-   setLocation();
-   resized();
-
-   if (ie7)
-     setTimeout("ieHack()", 100);
-
-   showToolbar();
-}
-
-// add localize method to all strings for use
-// as in help.innerHTML = "help".localize();
-String.prototype.localize = function()
-{
-  if (this == "")
-    return this;
-
-  // try full language code, e.g. en-US
-  var s, lookup = localize[lang];
-
-  if (lookup)
-  {
-    s = lookup[this];
-
-    if (s)
-      return s;
-  }
-
-  // try en if undefined for en-US
-  var lg = lang.split("-");
-
-  if (lg.length > 1)
-  {
-    lookup = localize[lg[0]];
-
-    if (lookup)
-    {
-      s = lookup[this];
-
-      if (s)
-        return s;
-    }
-  }
-
-  // otherwise string as is
-  return this;
-}
-
-// suppress IE's image toolbar pop up
-function hideImageToolbar()
-{
-  if (!ns_pos)
-  {
-    var images = document.getElementsByTagName("IMG");
-
-    for (var i = 0; i < images.length; ++i)
-      images[i].setAttribute("galleryimg", "no");
-  }
-}
-
-// hack to persuade IE to compute correct document height
-// as needed for simulating fixed positioning of toolbar
-function ieHack()
-{
-   window.resizeBy(0,-1);
-   window.resizeBy(0, 1);
-}
-
-// Firefox reload SVG bug work around
-function reload(e)
-{
-   if (!e)
-      var e = window.event;
-
-   hideBackgrounds();
-   setTimeout("document.reload();", 100);
-
-   stopPropagation(e);
-   e.cancel = true;
-   e.returnValue = false;
-
-   return false;
-}
-
-// Safari and Konqueror don't yet support getComputedStyle()
-// and they always reload page when location.href is updated
-function isKHTML()
-{
-   var agent = navigator.userAgent;
-   return (agent.indexOf("KHTML") >= 0 ? true : false);
-}
-
-function resized()
-{
-   var width = 0;
-
-   if ( typeof( window.innerWidth ) == 'number' )
-      width = window.innerWidth;  // Non IE browser
-   else if (document.documentElement && document.documentElement.clientWidth)
-      width = document.documentElement.clientWidth;  // IE6
-   else if (document.body && document.body.clientWidth)
-      width = document.body.clientWidth; // IE4
-
-   var height = 0;
-
-   if ( typeof( window.innerHeight ) == 'number' )
-      height = window.innerHeight;  // Non IE browser
-   else if (document.documentElement && document.documentElement.clientHeight)
-      height = document.documentElement.clientHeight;  // IE6
-   else if (document.body && document.body.clientHeight)
-      height = document.body.clientHeight; // IE4
-
-   if (height && (width/height > 1.05*1024/768))
-   {
-     width = height * 1024.0/768;
-   }
-
-   // IE fires onresize even when only font size is changed!
-   // so we do a check to avoid blocking < and > actions
-   if (width != lastWidth || height != lastHeight)
-   {
-      if (width >= 1100)
-         sizeIndex = 5;    // 4
-      else if (width >= 1000)
-         sizeIndex = 4;    // 3
-      else if (width >= 800)
-         sizeIndex = 3;    // 2
-      else if (width >= 600)
-         sizeIndex = 2;    // 1
-      else if (width)
-         sizeIndex = 0;
-
-      // add in font size adjustment from meta element e.g.
-      // <meta name="font-size-adjustment" content="-2" />
-      // useful when slides have too much content ;-)
-
-      if (0 <= sizeIndex + sizeAdjustment &&
-             sizeIndex + sizeAdjustment < sizes.length)
-        sizeIndex = sizeIndex + sizeAdjustment;
-
-      // enables cross browser use of relative width/height
-      // on object elements for use with SVG and Flash media
-      adjustObjectDimensions(width, height);
-
-      document.body.style.fontSize = sizes[sizeIndex];
-
-      lastWidth = width;
-      lastHeight = height;
-
-      // force reflow to work around Mozilla bug
-      //if (ns_pos)
-      {
-         var slide = slides[slidenum];
-         hideSlide(slide);
-         showSlide(slide);
-      }
-
-      // force correct positioning of toolbar
-      refreshToolbar(200);
-   }
-}
-
-function scrolled()
-{
-   if (toolbar && !ns_pos && !ie7)
-   {
-      hackoffset = scrollXOffset();
-      // hide toolbar
-      toolbar.style.display = "none";
-
-      // make it reappear later
-      if (scrollhack == 0 && !viewAll)
-      {
-         setTimeout(showToolbar, 1000);
-         scrollhack = 1;
-      }
-   }
-}
-
-// used to ensure IE refreshes toolbar in correct position
-function refreshToolbar(interval)
-{
-   if (!ns_pos && !ie7)
-   {
-     hideToolbar();
-     setTimeout(showToolbar, interval);
-   }
-}
-
-// restores toolbar after short delay
-function showToolbar()
-{
-   if (wantToolbar)
-   {
-      if (!ns_pos)
-      {
-         // adjust position to allow for scrolling
-         var xoffset = scrollXOffset();
-         toolbar.style.left = xoffset;
-         toolbar.style.right = xoffset;
-
-         // determine vertical scroll offset
-         //var yoffset = scrollYOffset();
-
-         // bottom is doc height - window height - scroll offset
-         //var bottom = documentHeight() - lastHeight - yoffset
-
-         //if (yoffset > 0 || documentHeight() > lastHeight)
-         //   bottom += 16;  // allow for height of scrollbar
-
-         toolbar.style.bottom = 0; //bottom;
-      }
-
-      toolbar.style.display = "block";
-      toolbar.style.visibility = "visible";
-   }
-
-   scrollhack = 0;
-
-
-   // set the keyboard focus to the help link on the
-   // toolbar to ensure that document has the focus
-   // IE doesn't always work with window.focus()
-   // and this hack has benefit of Enter for help
-
-   try
-   {
-     if (!opera)
-       helpAnchor.focus();
-   }
-   catch (e)
-   {
-   }
-}
-
-function test()
-{
-   var s = "docH: " + documentHeight() +
-       " winH: " + lastHeight +
-       " yoffset: " + scrollYOffset() +
-       " toolbot: " + (documentHeight() - lastHeight - scrollYOffset());
-
-   //alert(s);
-
-   var slide = slides[slidenum];
-   // IE getAttribute requires "class" to be "className"
-   var name = ns_pos ? "class" : "className";
-   var style = (slide.currentStyle ? slide.currentStyle["backgroundColor"] :
-       document.defaultView.getComputedStyle(slide, '').getPropertyValue("background-color"));
-   alert("class='" + slide.getAttribute(name) + "' backgroundColor: " + style);
-}
-
-function hideToolbar()
-{
-   toolbar.style.display = "none";
-   toolbar.style.visibility = "hidden";
-   window.focus();
-}
-
-// invoked via F key
-function toggleToolbar()
-{
-   if (!viewAll)
-   {
-      if (toolbar.style.display == "none")
-      {
-         toolbar.style.display = "block";
-         toolbar.style.visibility = "visible";
-         wantToolbar = 1;
-      }
-      else
-      {
-         toolbar.style.display = "none";
-         toolbar.style.visibility = "hidden";
-         wantToolbar = 0;
-      }
-   }
-}
-
-function scrollXOffset()
-{
-   if (window.pageXOffset)
-      return self.pageXOffset;
-
-   if (document.documentElement && 
-             document.documentElement.scrollLeft)
-      return document.documentElement.scrollLeft;
-
-   if (document.body)
-      return document.body.scrollLeft;
-
-    return 0;
-}
-
-
-function scrollYOffset()
-{
-   if (window.pageYOffset)
-      return self.pageYOffset;
-
-   if (document.documentElement && 
-             document.documentElement.scrollTop)
-      return document.documentElement.scrollTop;
-
-   if (document.body)
-      return document.body.scrollTop;
-
-    return 0;
-}
-
-// looking for a way to determine height of slide content
-// the slide itself is set to the height of the window
-function optimizeFontSize()
-{
-   var slide = slides[slidenum];
-
-   //var dh = documentHeight(); //getDocHeight(document);
-   var dh = slide.scrollHeight;
-   var wh = getWindowHeight();
-   var u = 100 * dh / wh;
-
-   alert("window utilization = " + u + "% (doc "
-      + dh + " win " + wh + ")");
-}
-
-function getDocHeight(doc) // from document object
-{
-  if (!doc)
-    doc = document;
-
-  if (doc && doc.body && doc.body.offsetHeight)
-    return doc.body.offsetHeight;  // ns/gecko syntax
-
-  if (doc && doc.body && doc.body.scrollHeight)
-    return doc.body.scrollHeight;
-
-  alert("couldn't determine document height");
-}
-
-function getWindowHeight()
-{
-  if ( typeof( window.innerHeight ) == 'number' )
-    return window.innerHeight;  // Non IE browser
-
-  if (document.documentElement && document.documentElement.clientHeight)
-    return document.documentElement.clientHeight;  // IE6
-
-  if (document.body && document.body.clientHeight)
-    return document.body.clientHeight; // IE4
-}
-
-
-
-function documentHeight()
-{
-   var sh, oh;
-
-   sh = document.body.scrollHeight;
-   oh = document.body.offsetHeight;
-
-   if (sh && oh)
-   {
-      return (sh > oh ? sh : oh);
-   }
-
-   // no idea!
-   return 0;
-}
-
-function smaller()
-{
-   if (sizeIndex > 0)
-   {
-      --sizeIndex;
-   }
-
-   toolbar.style.display = "none";
-   document.body.style.fontSize = sizes[sizeIndex];
-   var slide = slides[slidenum];
-   hideSlide(slide);
-   showSlide(slide);
-   setTimeout(showToolbar, 300);
-}
-
-function bigger()
-{
-   if (sizeIndex < sizes.length - 1)
-   {
-      ++sizeIndex;
-   }
-
-   toolbar.style.display = "none";
-   document.body.style.fontSize = sizes[sizeIndex];
-   var slide = slides[slidenum];
-   hideSlide(slide);
-   showSlide(slide);
-   setTimeout(showToolbar, 300);
-}
-
-// enables cross browser use of relative width/height
-// on object elements for use with SVG and Flash media
-// with thanks to Ivan Herman for the suggestion
-function adjustObjectDimensions(width, height)
-{
-   for( var i = 0; i < objects.length; i++ )
-   {
-      var obj = objects[i];
-      var mimeType = obj.getAttribute("type");
-
-      if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash")
-      {
-         if ( !obj.initialWidth ) 
-            obj.initialWidth = obj.getAttribute("width");
-
-         if ( !obj.initialHeight ) 
-            obj.initialHeight = obj.getAttribute("height");
-
-         if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" )
-         {
-            var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1));
-            var newW = width * (w/100.0);
-            obj.setAttribute("width",newW);
-         }
-
-         if ( obj.initialHeight && obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" )
-         {
-            var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1));
-            var newH = height * (h/100.0);
-            obj.setAttribute("height", newH);
-         }
-      }
-   }
-}
-
-function cancel(event)
-{
-  if (event)
-  {
-     event.cancel = true;
-     event.returnValue = false;
-
-    if (event.preventDefault)
-      event.preventDefault();
-  }
-
-  return false;
-}
-
-//  See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes
-function keyDown(event)
-{
-    var key;
-
-    if (!event)
-      var event = window.event;
-
-    // kludge around NS/IE differences 
-    if (window.event)
-       key = window.event.keyCode;
-    else if (event.which)
-       key = event.which;
-    else
-       return true; // Yikes! unknown browser
-
-    // ignore event if key value is zero
-    // as for alt on Opera and Konqueror
-    if (!key)
-       return true;
-
-    // check for concurrent control/command/alt key
-    // but are these only present on mouse events?
-
-    if (event.ctrlKey || event.altKey || event.metaKey)
-       return true;
-
-    // dismiss table of contents if visible
-    if (isShownToc() && key != 9 && key != 16 && key != 38 && key != 40)
-    {
-      hideTableOfContents();
-
-      if (key == 27 || key == 84 || key == 67)
-        return cancel(event);
-    }
-
-    if (key == 34) // Page Down
-    {
-       nextSlide(false);
-       return cancel(event);
-    }
-    else if (key == 33) // Page Up
-    {
-       previousSlide(false);
-       return cancel(event);
-    }
-    else if (key == 32) // space bar
-    {
-       nextSlide(true);
-       return cancel(event);
-    }
-    else if (key == 37 || key == 38) // Left arrow || Up arrow
-    {
-       previousSlide(!event.shiftKey);
-       return cancel(event);
-    }
-    else if (key == 36) // Home
-    {
-       firstSlide();
-       return cancel(event);
-    }
-    else if (key == 35) // End
-    {
-       lastSlide();
-       return cancel(event);
-    }
-    else if (key == 39 || key == 40) // Right arrow || Down arrow
-    {
-       nextSlide(!event.shiftKey);
-       return cancel(event);
-    }
-    else if (key == 13) // Enter
-    {
-       if (outline)
-       {
-          if (outline.visible)
-            fold(outline);
-          else
-            unfold(outline);
-          
-         return cancel(event);
-       }
-    }
-    else if (key == 188)  // < for smaller fonts
-    {
-       smaller();
-       return cancel(event);
-    }
-    else if (key == 190)  // > for larger fonts
-    {
-       bigger();
-       return cancel(event);
-    }
-    else if (key == 189 || key == 109)  // - for smaller fonts
-    {
-       smaller();
-       return cancel(event);
-    }
-    else if (key == 187 || key == 191 || key == 107)  // = +  for larger fonts
-    {
-       bigger();
-       return cancel(event);
-    }
-    else if (key == 83)  // S for smaller fonts
-    {
-       smaller();
-       return cancel(event);
-    }
-    else if (key == 66)  // B for larger fonts
-    {
-       bigger();
-       return cancel(event);
-    }
-    else if (key == 90)  // Z for last slide
-    {
-       lastSlide();
-       return cancel(event);
-    }
-    else if (key == 70)  // F for toggle toolbar
-    {
-       toggleToolbar();
-       return cancel(event);
-    }
-    else if (key == 65)  // A for toggle view single/all slides
-    {
-       toggleView();
-       return cancel(event);
-    }
-    else if (key == 75)  // toggle action of left click for next page
-    {
-       mouseClickEnabled = !mouseClickEnabled;
-       alert((mouseClickEnabled ? "enabled" : "disabled") +  " mouse click advance");
-       return cancel(event);
-    }
-    else if (key == 84 || key == 67)  // T or C for table of contents
-    {
-       if (toc)
-         showTableOfContents();
-
-       return cancel(event);
-    }
-    else if (key == 72) // H for help
-    {
-       window.location = helpPage;
-       return cancel(event);
-    }
-
-    //else if (key == 93) // Windows menu key
-      //alert("lastShown is " + lastShown);
-    //else alert("key code is "+ key);
-
-
-    return true;
-}
-
-// make note of length of selected text
-// as this evaluates to zero in click event
-function mouseButtonUp(e)
-{
-  selectedTextLen = getSelectedText().length;
-}
-
-// right mouse button click is reserved for context menus
-// it is more reliable to detect rightclick than leftclick
-function mouseButtonClick(e)
-{
-   var rightclick = false;
-   var leftclick = false;
-   var middleclick = false;
-   var target;
-
-   if (!e)
-      var e = window.event;
-
-   if (e.target)
-      target = e.target;
-   else if (e.srcElement)
-      target = e.srcElement;
-
-   // work around Safari bug
-   if (target.nodeType == 3)
-      target = target.parentNode;
-
-   if (e.which) // all browsers except IE
-   {
-      leftclick = (e.which == 1);
-      middleclick = (e.which == 2);
-      rightclick = (e.which == 3);
-   }
-   else if (e.button)
-   {
-      // Konqueror gives 1 for left, 4 for middle
-      // IE6 gives 0 for left and not 1 as I expected
-
-      if (e.button == 4)
-        middleclick = true;
-
-      // all browsers agree on 2 for right button
-      rightclick = (e.button == 2);
-   }
-   else leftclick = true;
-
-   // dismiss table of contents
-   hideTableOfContents();
-
-   if (selectedTextLen > 0)
-   {
-      stopPropagation(e);
-      e.cancel = true;
-      e.returnValue = false;
-      return false;
-   }
-
-   // check if target is something that probably want's clicks
-   // e.g. embed, object, input, textarea, select, option
-
-   if (mouseClickEnabled && leftclick &&
-        target.nodeName != "EMBED" &&
-        target.nodeName != "OBJECT" &&
-        target.nodeName != "INPUT" &&
-        target.nodeName != "TEXTAREA" &&
-        target.nodeName != "SELECT" &&
-        target.nodeName != "OPTION")
-   {
-      nextSlide(true);
-      stopPropagation(e);
-      e.cancel = true;
-      e.returnValue = false;
-   }
-}
-
-function previousSlide(incremental)
-{
-   if (!viewAll)
-   {
-      var slide;
-
-      if ((incremental || slidenum == 0) && lastShown != null)
-      {
-         lastShown = hidePreviousItem(lastShown);
-         setEosStatus(false);
-      }
-      else if (slidenum > 0)
-      {
-         slide = slides[slidenum];
-         hideSlide(slide);
-
-         slidenum = slidenum - 1;
-         slide = slides[slidenum];
-         setVisibilityAllIncremental("visible");
-         lastShown = previousIncrementalItem(null);
-         setEosStatus(true);
-         showSlide(slide);
-      }
-
-      setLocation();
-
-      if (!ns_pos)
-         refreshToolbar(200);
-   }
-}
-
-function nextSlide(incremental)
-{
-   if (!viewAll)
-   {
-      var slide, last = lastShown;
-
-      if (incremental || slidenum == slides.length - 1)
-         lastShown = revealNextItem(lastShown);
-
-      if ((!incremental || lastShown == null) && slidenum < slides.length - 1)
-      {
-         slide = slides[slidenum];
-         hideSlide(slide);
-
-         slidenum = slidenum + 1;
-         slide = slides[slidenum];
-         lastShown = null;
-         setVisibilityAllIncremental("hidden");
-         showSlide(slide);
-      }
-      else if (!lastShown)
-      {
-         if (last && incremental)
-           lastShown = last;
-      }
-
-      setLocation();
-
-      setEosStatus(!nextIncrementalItem(lastShown));
-
-      if (!ns_pos)
-         refreshToolbar(200);
-   }
-}
-
-// to first slide with nothing revealed
-// i.e. state at start of presentation
-function firstSlide()
-{
-   if (!viewAll)
-   {
-      var slide;
-
-      if (slidenum != 0)
-      {
-         slide = slides[slidenum];
-         hideSlide(slide);
-
-         slidenum = 0;
-         slide = slides[slidenum];
-         lastShown = null;
-         setVisibilityAllIncremental("hidden");
-         showSlide(slide);
-      }
-
-      setEosStatus(!nextIncrementalItem(lastShown));
-      setLocation();
-   }
-}
-
-
-// to last slide with everything revealed
-// i.e. state at end of presentation
-function lastSlide()
-{
-   if (!viewAll)
-   {
-      var slide;
-
-      lastShown = null; //revealNextItem(lastShown);
-
-      if (lastShown == null && slidenum < slides.length - 1)
-      {
-         slide = slides[slidenum];
-         hideSlide(slide);
-         slidenum = slides.length - 1;
-         slide = slides[slidenum];
-         setVisibilityAllIncremental("visible");
-         lastShown = previousIncrementalItem(null);
-
-         showSlide(slide);
-      }
-      else
-      {
-         setVisibilityAllIncremental("visible");
-         lastShown = previousIncrementalItem(null);
-      }
-
-      setEosStatus(true);
-      setLocation();
-   }
-}
-
-function setEosStatus(state)
-{
-   if (eos)
-      eos.style.color = (state ? "rgb(240,240,240)" : "red");
-}
-
-function showSlide(slide)
-{
-   syncBackground(slide);
-   window.scrollTo(0,0);
-   slide.style.visibility = "visible";
-   slide.style.display = "block";
-}
-
-function hideSlide(slide)
-{
-   slide.style.visibility = "hidden";
-   slide.style.display = "none";
-}
-
-function beforePrint()
-{
-   showAllSlides();
-   hideToolbar();
-}
-
-function afterPrint()
-{
-   if (!viewAll)
-   {
-      singleSlideView();
-      showToolbar();
-   }
-}
-
-function printSlides()
-{
-  beforePrint();
-  window.print();
-  afterPrint();
-}
-
-function toggleView()
-{
-   if (viewAll)
-   {
-      singleSlideView();
-      showToolbar();
-      viewAll = 0;
-   }
-   else
-   {
-      showAllSlides();
-      hideToolbar();
-      viewAll = 1;
-   }
-}
-
-// prepare for printing
-function showAllSlides()
-{
-   var slide;
-
-   for (var i = 0; i < slides.length; ++i)
-   {
-      slide = slides[i];
-
-      slide.style.position = "relative";
-      slide.style.borderTopStyle = "solid";
-      slide.style.borderTopWidth = "thin";
-      slide.style.borderTopColor = "black";
-
-      try {
-        if (i == 0)
-          slide.style.pageBreakBefore = "avoid";
-        else
-          slide.style.pageBreakBefore = "always";
-      }
-      catch (e)
-      {
-        //do nothing
-      }
-
-      setVisibilityAllIncremental("visible");
-      showSlide(slide);
-   }
-
-   var note;
-
-   for (var i = 0; i < notes.length; ++i)
-   {
-      showSlide(notes[i]);
-   }
-
-   // no easy way to render background under each slide
-   // without duplicating the background divs for each slide
-   // therefore hide backgrounds to avoid messing up slides
-   hideBackgrounds();
-}
-
-// restore after printing
-function singleSlideView()
-{
-   var slide;
-
-   for (var i = 0; i < slides.length; ++i)
-   {
-      slide = slides[i];
-
-      slide.style.position = "absolute";
-
-      if (i == slidenum)
-      {
-         slide.style.borderStyle = "none";
-         showSlide(slide);
-      }
-      else
-      {
-         slide.style.borderStyle = "none";
-         hideSlide(slide);
-      }
-   }
-
-   setVisibilityAllIncremental("visible");
-   lastShown = previousIncrementalItem(null);
-
-   var note;
-
-   for (var i = 0; i < notes.length; ++i)
-   {
-      hideSlide(notes[i]);
-   }
-}
-
-// the string str is a whitespace separated list of tokens
-// test if str contains a particular token, e.g. "slide"
-function hasToken(str, token)
-{
-   if (str)
-   {
-      // define pattern as regular expression
-      var pattern = /\w+/g;
-
-      // check for matches
-      // place result in array
-      var result = str.match(pattern);
-
-      // now check if desired token is present
-      for (var i = 0; i < result.length; i++)
-      {
-         if (result[i] == token)
-            return true;
-      }
-   }
-
-   return false;
-}
-
-function getClassList(element)
-{
-  if (typeof window.pageYOffset =='undefined')
-    return element.getAttribute("className");
-
-  return element.getAttribute("class");
-}
-
-function hasClass(element, name)
-{
-  var regexp = new RegExp("(^| )" + name + "\W*");
-
-  if (regexp.test(getClassList(element)))
-    return true;
-
-  return false;
-
-}
-
-function removeClass(element, name)
-{
-  // IE getAttribute requires "class" to be "className"
-  var clsname = ns_pos ? "class" : "className";
-  var clsval = element.getAttribute(clsname);
-
-  var regexp = new RegExp("(^| )" + name + "\W*");
-
-  if (clsval)
-  {
-    clsval = clsval.replace(regexp, "");
-    element.setAttribute(clsname, clsval);
-  }
-}
-
-function addClass(element, name)
-{
-  if (!hasClass(element, name))
-  {
-    // IE getAttribute requires "class" to be "className"
-    var clsname = ns_pos ? "class" : "className";
-    var clsval = element.getAttribute(clsname);
-    element.setAttribute(clsname, (clsval ? clsval + " " + name : name));
-  }
-}
-
-// wysiwyg editors make it hard to use div elements
-// e.g. amaya loses the div when you copy and paste
-// this function wraps div elements around implicit
-// slides which start with an h1 element and continue
-// up to the next heading or div element
-function wrapImplicitSlides()
-{
-   var i, heading, node, next, div;
-   var headings = document.getElementsByTagName("h1");
-
-   if (!headings)
-     return;
-
-   for (i = 0; i < headings.length; ++i)
-   {
-      heading = headings[i];
-
-      if (heading.parentNode != document.body)
-         continue;
-
-      node = heading.nextSibling;
-
-      div = document.createElement("div");
-      div.setAttribute((ns_pos ? "class" : "className"), "slide");
-      document.body.replaceChild(div, heading);
-      div.appendChild(heading);
-
-      while (node)
-      {
-         if (node.nodeType == 1 &&    // an element
-                  (node.nodeName == "H1" ||
-                   node.nodeName == "h1" ||
-                   node.nodeName == "DIV" ||
-                   node.nodeName == "div"))
-            break;
-
-         next = node.nextSibling;
-         node = document.body.removeChild(node);
-         div.appendChild(node);
-         node = next;
-      } 
-   }
-}
-
-// return new array of all slides
-function collectSlides()
-{
-   var slides = new Array();
-   var divs = document.body.getElementsByTagName("div");
-
-   for (var i = 0; i < divs.length; ++i)
-   {
-      div = divs.item(i);
-
-      if (hasClass(div, "slide"))
-      {
-         // add slide to collection
-         slides[slides.length] = div;
-
-         // hide each slide as it is found
-         div.style.display = "none";
-         div.style.visibility = "hidden";
-
-         // add dummy <br/> at end for scrolling hack
-         var node1 = document.createElement("br");
-         div.appendChild(node1);
-         var node2 = document.createElement("br");
-         div.appendChild(node2);
-      }
-      else if (hasClass(div, "background"))
-      {  // work around for Firefox SVG reload bug
-         // which otherwise replaces 1st SVG graphic with 2nd
-         div.style.display = "block";
-      }
-   }
-
-   return slides;
-}
-
-// return new array of all <div class="handout">
-function collectNotes()
-{
-   var notes = new Array();
-   var divs = document.body.getElementsByTagName("div");
-
-   for (var i = 0; i < divs.length; ++i)
-   {
-      div = divs.item(i);
-
-      if (hasClass(div, "handout"))
-      {
-         // add slide to collection
-         notes[notes.length] = div;
-
-         // hide handout notes as they are found
-         div.style.display = "none";
-         div.style.visibility = "hidden";
-      }
-   }
-
-   return notes;
-}
-
-// return new array of all <div class="background">
-// including named backgrounds e.g. class="background titlepage"
-function collectBackgrounds()
-{
-   var backgrounds = new Array();
-   var divs = document.body.getElementsByTagName("div");
-
-   for (var i = 0; i < divs.length; ++i)
-   {
-      div = divs.item(i);
-
-      if (hasClass(div, "background"))
-      {
-         // add slide to collection
-         backgrounds[backgrounds.length] = div;
-
-         // hide named backgrounds as they are found
-         // e.g. class="background epilog"
-         if (getClassList(div) != "background")
-         {
-            div.style.display = "none";
-            div.style.visibility = "hidden";
-         }
-      }
-   }
-
-   return backgrounds;
-}
-
-// show just the backgrounds pertinent to this slide
-function syncBackground(slide)
-{
-   var background;
-   var bgColor;
-
-   if (slide.currentStyle)
-      bgColor = slide.currentStyle["backgroundColor"];
-   else if (document.defaultView)
-   {
-      var styles = document.defaultView.getComputedStyle(slide,null);
-
-      if (styles)
-          bgColor = styles.getPropertyValue("background-color");
-      else // broken implementation probably due Safari or Konqueror
-      {
-          //alert("defective implementation of getComputedStyle()");
-          bgColor = "transparent";
-      }
-   }
-   else
-      bgColor == "transparent";
-
-   if (bgColor == "transparent")
-   {
-      var slideClass = getClassList(slide);
-
-      for (var i = 0; i < backgrounds.length; i++)
-      {
-         background = backgrounds[i];
-
-         var bgClass = getClassList(background);
-
-         if (matchingBackground(slideClass, bgClass))
-         {
-            background.style.display = "block";
-            background.style.visibility = "visible";
-         }
-         else
-         {
-            background.style.display = "none";
-            background.style.visibility = "hidden";
-         }
-      }
-   }
-   else // forcibly hide all backgrounds
-      hideBackgrounds();
-}
-
-function hideBackgrounds()
-{
-   for (var i = 0; i < backgrounds.length; i++)
-   {
-      background = backgrounds[i];
-      background.style.display = "none";
-      background.style.visibility = "hidden";
-   }
-}
-
-// compare classes for slide and background
-function matchingBackground(slideClass, bgClass)
-{
-   if (bgClass == "background")
-      return true;
-
-   // define pattern as regular expression
-   var pattern = /\w+/g;
-
-   // check for matches and place result in array
-   var result = slideClass.match(pattern);
-
-   // now check if desired name is present for background
-   for (var i = 0; i < result.length; i++)
-   {
-      if (hasToken(bgClass, result[i]))
-         return true;
-   }
-
-   return false;
-}
-
-// left to right traversal of root's content
-function nextNode(root, node)
-{
-   if (node == null)
-      return root.firstChild;
-
-   if (node.firstChild)
-      return node.firstChild;
-
-   if (node.nextSibling)
-      return node.nextSibling;
-
-   for (;;)
-   {
-      node = node.parentNode;
-
-      if (!node || node == root)
-         break;
-
-      if (node && node.nextSibling)
-         return node.nextSibling;
-   }
-
-   return null;
-}
-
-// right to left traversal of root's content
-function previousNode(root, node)
-{
-   if (node == null)
-   {
-      node = root.lastChild;
-
-      if (node)
-      {
-         while (node.lastChild)
-            node = node.lastChild;
-      }
-
-      return node;
-   }
-
-   if (node.previousSibling)
-   {
-      node = node.previousSibling;
-
-      while (node.lastChild)
-         node = node.lastChild;
-
-      return node;
-   }
-
-   if (node.parentNode != root)
-      return node.parentNode;
-
-   return null;
-}
-
-// HTML elements that can be used with class="incremental"
-// note that you can also put the class on containers like
-// up, ol, dl, and div to make their contents appear
-// incrementally. Upper case is used since this is what
-// browsers report for HTML node names (text/html).
-function incrementalElementList()
-{
-   var inclist = new Array();
-   inclist["P"] = true;
-   inclist["PRE"] = true;
-   inclist["LI"] = true;
-   inclist["BLOCKQUOTE"] = true;
-   inclist["DT"] = true;
-   inclist["DD"] = true;
-   inclist["H2"] = true;
-   inclist["H3"] = true;
-   inclist["H4"] = true;
-   inclist["H5"] = true;
-   inclist["H6"] = true;
-   inclist["SPAN"] = true;
-   inclist["ADDRESS"] = true;
-   inclist["TABLE"] = true;
-   inclist["TR"] = true;
-   inclist["TH"] = true;
-   inclist["TD"] = true;
-   inclist["IMG"] = true;
-   inclist["OBJECT"] = true;
-   return inclist;
-}
-
-function nextIncrementalItem(node)
-{
-   var slide = slides[slidenum];
-
-   for (;;)
-   {
-      node = nextNode(slide, node);
-
-      if (node == null || node.parentNode == null)
-         break;
-
-      if (node.nodeType == 1)  // ELEMENT
-      {
-         if (node.nodeName == "BR")
-           continue;
-
-         if (hasClass(node, "incremental")
-             && okayForIncremental[node.nodeName])
-            return node;
-
-         if (hasClass(node.parentNode, "incremental")
-             && !hasClass(node, "non-incremental"))
-            return node;
-      }
-   }
-
-   return node;
-}
-
-function previousIncrementalItem(node)
-{
-   var slide = slides[slidenum];
-
-   for (;;)
-   {
-      node = previousNode(slide, node);
-
-      if (node == null || node.parentNode == null)
-         break;
-
-      if (node.nodeType == 1)
-      {
-         if (node.nodeName == "BR")
-           continue;
-
-         if (hasClass(node, "incremental")
-             && okayForIncremental[node.nodeName])
-            return node;
-
-         if (hasClass(node.parentNode, "incremental")
-             && !hasClass(node, "non-incremental"))
-            return node;
-      }
-   }
-
-   return node;
-}
-
-// set visibility for all elements on current slide with
-// a parent element with attribute class="incremental"
-function setVisibilityAllIncremental(value)
-{
-   var node = nextIncrementalItem(null);
-
-   while (node)
-   {
-      node.style.visibility = value;
-      node = nextIncrementalItem(node);
-   }
-}
-
-// reveal the next hidden item on the slide
-// node is null or the node that was last revealed
-function revealNextItem(node)
-{
-   node = nextIncrementalItem(node);
-
-   if (node && node.nodeType == 1)  // an element
-      node.style.visibility = "visible";
-
-   return node;
-}
-
-
-// exact inverse of revealNextItem(node)
-function hidePreviousItem(node)
-{
-   if (node && node.nodeType == 1)  // an element
-      node.style.visibility = "hidden";
-
-   return previousIncrementalItem(node);
-}
-
-
-/* set click handlers on all anchors */
-function patchAnchors()
-{
-   var anchors = document.body.getElementsByTagName("a");
-
-   for (var i = 0; i < anchors.length; ++i)
-   {
-      anchors[i].onclick = clickedAnchor;
-   }
-}
-
-function clickedAnchor(e)
-{
-   if (!e)
-      var e = window.event;
-
-   // compare this.href with location.href
-   // for link to another slide in this doc
-
-   if (pageAddress(this.href) == pageAddress(location.href))
-   {
-      // yes, so find new slide number
-      var newslidenum = findSlideNumber(this.href);
-
-      if (newslidenum != slidenum)
-      {
-         slide = slides[slidenum];
-         hideSlide(slide);
-         slidenum = newslidenum;
-         slide = slides[slidenum];
-         showSlide(slide);
-         setLocation();
-      }
-   }
-   else if (this.target == null)
-      location.href = this.href;
-
-   this.blur();
-   stopPropagation(e);
-}
-
-function pageAddress(uri)
-{
-   var i = uri.indexOf("#");
-
-   // check if anchor is entire page
-
-   if (i < 0)
-      return uri;  // yes
-
-   return uri.substr(0, i);
-}
-
-function showSlideNumber()
-{
-   slideNumElement.innerHTML = "slide".localize() + " " +
-           (slidenum + 1) + "/" + slides.length;
-}
-
-function setLocation()
-{
-   var uri = pageAddress(location.href);
-
-   //if (slidenum > 0)
-      uri = uri + "#(" + (slidenum+1) + ")";
-
-   if (uri != location.href && !khtml)
-      location.href = uri;
-
-   document.title = title + " (" + (slidenum+1) + ")";
-   //document.title = (slidenum+1) + ") " + slideName(slidenum);
-
-   showSlideNumber();
-}
-
-// find current slide based upon location
-// first find target anchor and then look
-// for associated div element enclosing it
-// finally map that to slide number
-function findSlideNumber(uri)
-{
-   // first get anchor from page location
-
-   var i = uri.indexOf("#");
-
-   // check if anchor is entire page
-
-   if (i < 0)
-      return 0;  // yes
-
-   var anchor = unescape(uri.substr(i+1));
-
-   // now use anchor as XML ID to find target
-   var target = document.getElementById(anchor);
-
-   if (!target)
-   {
-      // does anchor look like "(2)" for slide 2 ??
-      // where first slide is (1)
-      var re = /\((\d)+\)/;
-
-      if (anchor.match(re))
-      {
-         var num = parseInt(anchor.substring(1, anchor.length-1));
-
-         if (num > slides.length)
-            num = 1;
-
-         if (--num < 0)
-            num = 0;
-
-         return num;
-      }
-
-      // accept [2] for backwards compatibility
-      re = /\[(\d)+\]/;
-
-      if (anchor.match(re))
-      {
-         var num = parseInt(anchor.substring(1, anchor.length-1));
-
-         if (num > slides.length)
-            num = 1;
-
-         if (--num < 0)
-            num = 0;
-
-         return num;
-      }
-
-      // oh dear unknown anchor
-      return 0;
-   }
-
-   // search for enclosing slide
-
-   while (true)
-   {
-      // browser coerces html elements to uppercase!
-      if (target.nodeName.toLowerCase() == "div" &&
-            hasClass(target, "slide"))
-      {
-         // found the slide element
-         break;
-      }
-
-      // otherwise try parent element if any
-
-      target = target.parentNode;
-
-      if (!target)
-      {
-         return 0;   // no luck!
-      }
-   };
-
-   for (i = 0; i < slides.length; ++i)
-   {
-      if (slides[i] == target)
-         return i;  // success
-   }
-
-   // oh dear still no luck
-   return 0;
-}
-
-// find slide name from first h1 element
-// default to document title + slide number
-function slideName(index)
-{
-   var name = null;
-   var slide = slides[index];
-
-   var heading = findHeading(slide);
-
-   if (heading)
-     name = extractText(heading);
-
-   if (!name)
-     name = title + "(" + (index + 1) + ")";
-
-   name.replace(/\&/g, "&");
-   name.replace(/\</g, "<");
-   name.replace(/\>/g, ">");
-
-   return name;
-}
-
-// find first h1 element in DOM tree
-function findHeading(node)
-{
-  if (!node || node.nodeType != 1)
-    return null;
-
-  if (node.nodeName == "H1" || node.nodeName == "h1")
-    return node;
-
-  var child = node.firstChild;
-
-  while (child)
-  {
-    node = findHeading(child);
-
-    if (node)
-      return node;
-
-    child = child.nextSibling;
-  }
-
-  return null;
-}
-
-// recursively extract text from DOM tree
-function extractText(node)
-{
-  if (!node)
-    return "";
-
-  // text nodes
-  if (node.nodeType == 3)
-    return node.nodeValue;
-
-  // elements
-  if (node.nodeType == 1)
-  {
-    node = node.firstChild;
-    var text = "";
-
-    while (node)
-    {
-      text = text + extractText(node);
-      node = node.nextSibling;
-    }
-
-    return text;
-  }
-
-  return "";
-}
-
-
-// find copyright text from meta element
-function findCopyright()
-{
-   var name, content;
-   var meta = document.getElementsByTagName("meta");
-
-   for (var i = 0; i < meta.length; ++i)
-   {
-      name = meta[i].getAttribute("name");
-      content = meta[i].getAttribute("content");
-
-      if (name == "copyright")
-         return content;
-   }
-
-   return null;
-}
-
-function findSizeAdjust()
-{
-   var name, content, offset;
-   var meta = document.getElementsByTagName("meta");
-
-   for (var i = 0; i < meta.length; ++i)
-   {
-      name = meta[i].getAttribute("name");
-      content = meta[i].getAttribute("content");
-
-      if (name == "font-size-adjustment")
-         return 1 * content;
-   }
-
-   return 0;
-}
-
-function addToolbar()
-{
-   var slideCounter, page;
-
-   var toolbar = createElement("div");
-   toolbar.setAttribute("class", "toolbar");
-
-   if (ns_pos) // a reasonably behaved browser
-   {
-      var right = document.createElement("div");
-      right.setAttribute("style", "float: right; text-align: right");
-
-      slideCounter = document.createElement("div")
-      slideCounter.innerHTML = "slide".localize() + " n/m";
-      right.appendChild(slideCounter);
-      toolbar.appendChild(right);
-
-      var left = document.createElement("div");
-      left.setAttribute("style", "text-align: left");
-
-      // global end of slide indicator
-      eos = document.createElement("span");
-      eos.innerHTML = "* ";
-      left.appendChild(eos);
-
-      var help = document.createElement("a");
-      help.setAttribute("href", helpPage);
-      help.setAttribute("title", helpText.localize());
-      help.innerHTML = "help?".localize();
-      left.appendChild(help);
-      helpAnchor = help;  // save for focus hack
-
-      var gap1 = document.createTextNode(" ");
-      left.appendChild(gap1);
-
-      var contents = document.createElement("a");
-      contents.setAttribute("href", "javascript:toggleTableOfContents()");
-      contents.setAttribute("title", "table of contents".localize());
-      contents.innerHTML = "contents?".localize();
-      left.appendChild(contents);
-
-      var gap2 = document.createTextNode(" ");
-      left.appendChild(gap2);
-
-      var i = location.href.indexOf("#");
-
-      // check if anchor is entire page
-
-      if (i > 0)
-         page = location.href.substr(0, i);
-      else
-         page = location.href;
-
-      var start = document.createElement("a");
-      start.setAttribute("href", page);
-      start.setAttribute("title", "restart presentation".localize());
-      start.innerHTML = "restart?".localize();
-//    start.setAttribute("href", "javascript:printSlides()");
-//    start.setAttribute("title", "print all slides".localize());
-//    start.innerHTML = "print!".localize();
-      left.appendChild(start);
-
-      var copyright = findCopyright();
-
-      if (copyright)
-      {
-         var span = document.createElement("span");
-         span.innerHTML = copyright;
-         span.style.color = "black";
-         span.style.marginLeft = "4em";
-         left.appendChild(span);
-      }
-
-      toolbar.appendChild(left);
-   }
-   else // IE so need to work around its poor CSS support
-   {
-      toolbar.style.position = (ie7 ? "fixed" : "absolute");
-      toolbar.style.zIndex = "200";
-      toolbar.style.width = "99.9%";
-      toolbar.style.height = "1.2em";
-      toolbar.style.top = "auto";
-      toolbar.style.bottom = "0";
-      toolbar.style.left = "0";
-      toolbar.style.right = "0";
-      toolbar.style.textAlign = "left";
-      toolbar.style.fontSize = "60%";
-      toolbar.style.color = "red";
-      toolbar.borderWidth = 0;
-      toolbar.style.background = "rgb(240,240,240)";
-
-      // would like to have help text left aligned
-      // and page counter right aligned, floating
-      // div's don't work, so instead use nested
-      // absolutely positioned div's.
-
-      var sp = document.createElement("span");
-      sp.innerHTML = "  * ";
-      toolbar.appendChild(sp);
-      eos = sp;  // end of slide indicator
-
-      var help = document.createElement("a");
-      help.setAttribute("href", helpPage);
-      help.setAttribute("title", helpText.localize());
-      help.innerHTML = "help?".localize();
-      toolbar.appendChild(help);
-      helpAnchor = help;  // save for focus hack
-
-      var gap1 = document.createTextNode(" ");
-      toolbar.appendChild(gap1);
-
-      var contents = document.createElement("a");
-      contents.setAttribute("href", "javascript:toggleTableOfContents()");
-      contents.setAttribute("title", "table of contents".localize());
-      contents.innerHTML = "contents?".localize();
-      toolbar.appendChild(contents);
-
-      var gap2 = document.createTextNode(" ");
-      toolbar.appendChild(gap2);
-
-      var i = location.href.indexOf("#");
-
-      // check if anchor is entire page
-
-      if (i > 0)
-         page = location.href.substr(0, i);
-      else
-         page = location.href;
-
-      var start = document.createElement("a");
-      start.setAttribute("href", page);
-      start.setAttribute("title", "restart presentation".localize());
-      start.innerHTML = "restart?".localize();
-//    start.setAttribute("href", "javascript:printSlides()");
-//    start.setAttribute("title", "print all slides".localize());
-//    start.innerHTML = "print!".localize();
-      toolbar.appendChild(start);
-
-      var copyright = findCopyright();
-
-      if (copyright)
-      {
-         var span = document.createElement("span");
-         span.innerHTML = copyright;
-         span.style.color = "black";
-         span.style.marginLeft = "2em";
-         toolbar.appendChild(span);
-      }
-
-      slideCounter = document.createElement("div")
-      slideCounter.style.position = "absolute";
-      slideCounter.style.width = "auto"; //"20%";
-      slideCounter.style.height = "1.2em";
-      slideCounter.style.top = "auto";
-      slideCounter.style.bottom = 0;
-      slideCounter.style.right = "0";
-      slideCounter.style.textAlign = "right";
-      slideCounter.style.color = "red";
-      slideCounter.style.background = "rgb(240,240,240)";
-
-      slideCounter.innerHTML = "slide".localize() + " n/m";
-      toolbar.appendChild(slideCounter);
-   }
-
-   // ensure that click isn't passed through to the page
-   toolbar.onclick = stopPropagation;
-   document.body.appendChild(toolbar);
-   slideNumElement = slideCounter;
-   setEosStatus(false);
-
-   return toolbar;
-}
-
-function isShownToc()
-{
-  if (toc && toc.style.visible == "visible")
-    return true;
-
-  return false;
-}
-
-function showTableOfContents()
-{
-  if (toc)
-  {
-    if (toc.style.visibility != "visible")
-    {
-      toc.style.visibility = "visible";
-      toc.style.display = "block";
-      toc.focus();
-
-      if (ie7 && slidenum == 0)
-        setTimeout("ieHack()", 100);
-    }
-    else
-      hideTableOfContents();
-  }
-}
-
-function hideTableOfContents()
-{
-  if (toc && toc.style.visibility != "hidden")
-  {
-    toc.style.visibility = "hidden";
-    toc.style.display = "none";
-
-    try
-    {
-       if (!opera)
-         helpAnchor.focus();
-    }
-    catch (e)
-    {
-    }
-  }
-}
-
-function toggleTableOfContents()
-{
-  if (toc)
-  {
-     if (toc.style.visible != "visible")
-       showTableOfContents();
-     else
-       hideTableOfContents();
-  }
-}
-
-// called on clicking toc entry
-function gotoEntry(e)
-{
-   var target;
-
-   if (!e)
-      var e = window.event;
-
-   if (e.target)
-      target = e.target;
-   else if (e.srcElement)
-      target = e.srcElement;
-
-   // work around Safari bug
-   if (target.nodeType == 3)
-      target = target.parentNode;
-
-   if (target && target.nodeType == 1)
-   {
-     var uri = target.getAttribute("href");
-
-     if (uri)
-     {
-        //alert("going to " + uri);
-        var slide = slides[slidenum];
-        hideSlide(slide);
-        slidenum = findSlideNumber(uri);
-        slide = slides[slidenum];
-        lastShown = null;
-        setLocation();
-        setVisibilityAllIncremental("hidden");
-        setEosStatus(!nextIncrementalItem(lastShown));
-        showSlide(slide);
-        //target.focus();
-
-        try
-        {
-           if (!opera)
-             helpAnchor.focus();
-        }
-        catch (e)
-        {
-        }
-     }
-   }
-
-   hideTableOfContents(e);
-   if (ie7) ieHack();
-   stopPropagation(e);
-   return cancel(e);
-}
-
-// called onkeydown for toc entry
-function gotoTocEntry(event)
-{
-  var key;
-
-  if (!event)
-    var event = window.event;
-
-  // kludge around NS/IE differences 
-  if (window.event)
-    key = window.event.keyCode;
-  else if (event.which)
-    key = event.which;
-  else
-    return true; // Yikes! unknown browser
-
-  // ignore event if key value is zero
-  // as for alt on Opera and Konqueror
-  if (!key)
-     return true;
-
-  // check for concurrent control/command/alt key
-  // but are these only present on mouse events?
-
-  if (event.ctrlKey || event.altKey)
-     return true;
-
-  if (key == 13)
-  {
-    var uri = this.getAttribute("href");
-
-    if (uri)
-    {
-      //alert("going to " + uri);
-      var slide = slides[slidenum];
-      hideSlide(slide);
-      slidenum = findSlideNumber(uri);
-      slide = slides[slidenum];
-      lastShown = null;
-      setLocation();
-      setVisibilityAllIncremental("hidden");
-      setEosStatus(!nextIncrementalItem(lastShown));
-      showSlide(slide);
-      //target.focus();
-
-      try
-      {
-         if (!opera)
-           helpAnchor.focus();
-      }
-      catch (e)
-      {
-      }
-    }
-
-    hideTableOfContents();
-    if (ie7) ieHack();
-    return cancel(event);
-  }
-
-  if (key == 40 && this.next)
-  {
-    this.next.focus();
-    return cancel(event);
-  }
-
-  if (key == 38 && this.previous)
-  {
-    this.previous.focus();
-    return cancel(event);
-  }
-
-  return true;
-}
-
-function isTitleSlide(slide)
-{
-   return hasClass(slide, "title");
-}
-
-// create div element with links to each slide
-function tableOfContents()
-{
-  var toc = document.createElement("div");
-  addClass(toc, "toc");
-  //toc.setAttribute("tabindex", "0");
-
-  var heading = document.createElement("div");
-  addClass(heading, "toc-heading");
-  heading.innerHTML = "Table of Contents".localize();
-
-  heading.style.textAlign = "center";
-  heading.style.width = "100%";
-  heading.style.margin = "0";
-  heading.style.marginBottom = "1em";
-  heading.style.borderBottomStyle = "solid";
-  heading.style.borderBottomColor = "rgb(180,180,180)";
-  heading.style.borderBottomWidth = "1px";
-
-  toc.appendChild(heading);
-  var previous = null;
-
-  for (var i = 0; i < slides.length; ++i)
-  {
-    var title = hasClass(slides[i], "title");
-    var num = document.createTextNode((i + 1) + ". ");
-
-    toc.appendChild(num);
-
-    var a = document.createElement("a");
-    a.setAttribute("href", "#(" + (i+1) + ")");
-
-    if (title)
-      addClass(a, "titleslide");
-
-    var name = document.createTextNode(slideName(i));
-    a.appendChild(name);
-    a.onclick = gotoEntry;
-    a.onkeydown = gotoTocEntry;
-    a.previous = previous;
-
-    if (previous)
-      previous.next = a;
-
-    toc.appendChild(a);
-
-    if (i == 0)
-      toc.first = a;
-
-    if (i < slides.length - 1)
-    {
-      var br = document.createElement("br");
-      toc.appendChild(br);
-    }
-
-    previous = a;
-  }
-
-  toc.focus = function () {
-    if (this.first)
-      this.first.focus();
-  }
-
-  toc.onclick = function (e) {
-    e||(e=window.event);
-    hideTableOfContents();
-    stopPropagation(e);
-    
-    if (e.cancel != undefined)
-      e.cancel = true;
-      
-    if (e.returnValue != undefined)
-      e.returnValue = false;
-      
-    return false;
-  };
-
-  toc.style.position = "absolute";
-  toc.style.zIndex = "300";
-  toc.style.width = "60%";
-  toc.style.maxWidth = "30em";
-  toc.style.height = "30em";
-  toc.style.overflow = "auto";
-  toc.style.top = "auto";
-  toc.style.right = "auto";
-  toc.style.left = "4em";
-  toc.style.bottom = "4em";
-  toc.style.padding = "1em";
-  toc.style.background = "rgb(240,240,240)";
-  toc.style.borderStyle = "solid";
-  toc.style.borderWidth = "2px";
-  toc.style.fontSize = "60%";
-
-  document.body.insertBefore(toc, document.body.firstChild);
-  return toc;
-}
-
-function replaceByNonBreakingSpace(str)
-{
-   for (var i = 0; i < str.length; ++i)
-      str[i] = 160;
-}
-
-
-function initOutliner()
-{
-  var items = document.getElementsByTagName("LI");
-
-  for (var i = 0; i < items.length; ++i)
-  {
-     var target = items[i];
-
-     if (!hasClass(target.parentNode, "outline"))
-        continue;
-
-     target.onclick = outlineClick;
-
-     if (!ns_pos)
-     {
-        target.onmouseover = hoverOutline;
-        target.onmouseout = unhoverOutline;
-     }
-
-     if (foldable(target))
-     {
-       target.foldable = true;
-       target.onfocus = function () {outline = this;};
-       target.onblur = function () {outline = null;};
-
-       if (!target.getAttribute("tabindex"))
-         target.setAttribute("tabindex", "0");
-
-       if (hasClass(target, "expand"))
-         unfold(target);
-       else
-         fold(target);
-     }
-     else
-     {
-       addClass(target, "nofold");
-       target.visible = true;
-       target.foldable = false;
-     }
-  }
-}
-
-function foldable(item)
-{
-   if (!item || item.nodeType != 1)
-      return false;
-
-   var node = item.firstChild;
-
-   while (node)
-   {
-     if (node.nodeType == 1 && isBlock(node))
-       return true;
-
-      node = node.nextSibling;
-   }
-
-   return false;
-}
-
-function fold(item)
-{
-  if (item)
-  {
-    removeClass(item, "unfolded");
-    addClass(item, "folded");
-  }
-
-  var node = item ? item.firstChild : null;
-
-  while (node)
-  {
-    if (node.nodeType == 1 && isBlock(node)) // element
-    {
-      // note that getElementStyle won't work for Safari 1.3
-      node.display = getElementStyle(node, "display", "display");
-      node.style.display = "none";
-      node.style.visibility = "hidden";
-    }
-
-    node = node.nextSibling;
-  }
-
-  item.visible = false;
-}
-
-function unfold(item)
-{
-   if (item)
-   {
-     addClass(item, "unfolded");
-     removeClass(item, "folded");
-   }
-
-  var node = item ? item.firstChild : null;
-
-  while (node)
-  {
-    if (node.nodeType == 1 && isBlock(node)) // element
-    {
-      // with fallback for Safari, see above
-      node.style.display = (node.display ? node.display : "block");
-      node.style.visibility = "visible";
-    }
-
-    node = node.nextSibling;
-  }
-
-  item.visible = true;
-}
-
-function outlineClick(e)
-{
-   var rightclick = false;
-   var target;
-
-   if (!e)
-      var e = window.event;
-
-   if (e.target)
-      target = e.target;
-   else if (e.srcElement)
-      target = e.srcElement;
-
-   // work around Safari bug
-   if (target.nodeType == 3)
-      target = target.parentNode;
-
-   while (target && target.visible == undefined)
-      target = target.parentNode;
-
-   if (!target)
-      return true;
-
-   if (e.which)
-      rightclick = (e.which == 3);
-   else if (e.button)
-      rightclick = (e.button == 2);
-
-   if (!rightclick && target.visible != undefined)
-   {
-      if (target.foldable)
-      {
-         if (target.visible)
-           fold(target);
-         else
-           unfold(target);
-      }
-
-      stopPropagation(e);
-      e.cancel = true;
-      e.returnValue = false;
-   }
-
-   return false;
-}
-
-function hoverOutline(e)
-{
-   var target;
-
-   if (!e)
-      var e = window.event;
-
-   if (e.target)
-      target = e.target;
-   else if (e.srcElement)
-      target = e.srcElement;
-
-   // work around Safari bug
-   if (target.nodeType == 3)
-      target = target.parentNode;
-
-   while (target && target.visible == undefined)
-      target = target.parentNode;
-
-   if (target && target.foldable)
-      target.style.cursor = "pointer";
-
-   return true;
-}
-
-function unhoverOutline(e)
-{
-   var target;
-
-   if (!e)
-      var e = window.event;
-
-   if (e.target)
-      target = e.target;
-   else if (e.srcElement)
-      target = e.srcElement;
-
-   // work around Safari bug
-   if (target.nodeType == 3)
-      target = target.parentNode;
-
-   while (target && target.visible == undefined)
-      target = target.parentNode;
-
-   if (target)
-     target.style.cursor = "default";
-
-   return true;
-}
-
-
-function stopPropagation(e)
-{
-   if (window.event)
-   {
-      window.event.cancelBubble = true;
-      //window.event.returnValue = false;
-   }
-   else if (e)
-   {
-      e.cancelBubble = true;
-      e.stopPropagation();
-      //e.preventDefault();
-   }
-}
-
-/* can't rely on display since we set that to none to hide things */
-function isBlock(elem)
-{
-   var tag = elem.nodeName;
-
-   return tag == "OL" || tag == "UL" || tag == "P" ||
-          tag == "LI" || tag == "TABLE" || tag == "PRE" ||
-          tag == "H1" || tag == "H2" || tag == "H3" ||
-          tag == "H4" || tag == "H5" || tag == "H6" ||
-          tag == "BLOCKQUOTE" || tag == "ADDRESS"; 
-}
-
-function getElementStyle(elem, IEStyleProp, CSSStyleProp)
-{
-   if (elem.currentStyle)
-   {
-      return elem.currentStyle[IEStyleProp];
-   }
-   else if (window.getComputedStyle)
-   {
-      var compStyle = window.getComputedStyle(elem, "");
-      return compStyle.getPropertyValue(CSSStyleProp);
-   }
-   return "";
-}
-
-// works with text/html and text/xhtml+xml with thanks to Simon Willison
-function createElement(element)
-{
-   if (typeof document.createElementNS != 'undefined')
-   {
-      return document.createElementNS('http://www.w3.org/1999/xhtml', element);
-   }
-
-   if (typeof document.createElement != 'undefined')
-   {
-      return document.createElement(element);
-   }
-
-   return false;
-}
-
-// designed to work with both text/html and text/xhtml+xml
-function getElementsByTagName(name)
-{
-   if (typeof document.getElementsByTagNameNS != 'undefined')
-   {
-      return document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', name);
-   }
-
-   if (typeof document.getElementsByTagName != 'undefined')
-   {
-      return document.getElementsByTagName(name);
-   }
-
-   return null;
-}
-
-/*
-// clean alternative to innerHTML method, but on IE6
-// it doesn't work with named entities like  
-// which need to be replaced by numeric entities
-function insertText(element, text)
-{
-   try
-   {
-     element.textContent = text;  // DOM3 only
-   }
-   catch (e)
-   {
-      if (element.firstChild)
-      {
-         // remove current children
-         while (element.firstChild)
-            element.removeChild(element.firstChild);
-      }
-
-      element.appendChild(document.createTextNode(text));
-   }
-}
-
-// as above, but as method of all element nodes
-// doesn't work in IE6 which doesn't allow you to
-// add methods to the HTMLElement prototype
-if (HTMLElement != undefined)
-{
-  HTMLElement.prototype.insertText = function(text) {
-    var element = this;
-
-    try
-    {
-      element.textContent = text;  // DOM3 only
-    }
-    catch (e)
-    {
-      if (element.firstChild)
-      {
-         // remove current children
-         while (element.firstChild)
-           element.removeChild(element.firstChild);
-      }
-
-      element.appendChild(document.createTextNode(text));
-    }
-  };
-}
-*/
-
-function getSelectedText()
-{
-  try
-  {
-    if (window.getSelection)
-      return window.getSelection().toString();
-
-    if (document.getSelection)
-      return document.getSelection().toString();
-
-    if (document.selection)
-      return document.selection.createRange().text;
-  }
-  catch (e)
-  {
-    return "";
-  }
-  return "";
-}
diff --git a/favicon.ico b/favicon.ico
index 48854ff..d287722 100644
Binary files a/favicon.ico and b/favicon.ico differ
diff --git a/include/libc.h b/include/libc.h
index b464cb4..1440209 100644
--- a/include/libc.h
+++ b/include/libc.h
@@ -85,16 +85,12 @@ extern	char*	p9getenv(char*);
 extern	int	p9putenv(char*, char*);
 extern	int	getfields(char*, char**, int, int, char*);
 extern	int	gettokens(char *, char **, int, char *);
-extern	char*	getuser(void);
 extern	char*	p9getwd(char*, int);
 extern	void	p9longjmp(p9jmp_buf, int);
-extern	char*	mktemp(char*);
-extern	int		opentemp(char*);
 extern	void	p9notejmp(void*, p9jmp_buf, int);
 extern	void	perror(const char*);
 extern	int	postnote(int, int, char *);
 extern	double	p9pow10(int);
-extern	char*	searchpath(char*);
 extern	char*	p9ctime(long);
 #define p9setjmp(b)	sigsetjmp((void*)(b), 1)
 
@@ -293,6 +289,18 @@ extern	char*	getgoos(void);
 extern	char*	getgoarch(void);
 extern	char*	getgoroot(void);
 extern	char*	getgoversion(void);
+extern	char*	getgoarm(void);
+extern	char*	getgo386(void);
+
+extern	void	flagcount(char*, char*, int*);
+extern	void	flagint32(char*, char*, int32*);
+extern	void	flagint64(char*, char*, int64*);
+extern	void	flagstr(char*, char*, char**);
+extern	void	flagparse(int*, char***, void (*usage)(void));
+extern	void	flagfn0(char*, char*, void(*fn)(void));
+extern	void	flagfn1(char*, char*, void(*fn)(char*));
+extern	void	flagfn2(char*, char*, void(*fn)(char*, char*));
+extern	void	flagprint(int);
 
 #ifdef _WIN32
 
@@ -366,7 +374,7 @@ extern	char*	unsharp(char*);
 /* command line */
 extern char	*argv0;
 extern void __fixargv0(void);
-#define	ARGBEGIN	for((argv0?0:(argv0=(__fixargv0(),*argv))),argv++,argc--;\
+#define	ARGBEGIN	for((void)(argv0?0:(argv0=(__fixargv0(),*argv))),argv++,argc--;\
 			    argv[0] && argv[0][0]=='-' && argv[0][1];\
 			    argc--, argv++) {\
 				char *_args, *_argt;\
diff --git a/include/plan9/amd64/u.h b/include/plan9/amd64/u.h
new file mode 100644
index 0000000..f2430b5
--- /dev/null
+++ b/include/plan9/amd64/u.h
@@ -0,0 +1,14 @@
+// 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 "/amd64/include/u.h"
+
+typedef char   int8;
+typedef uchar  uint8;
+typedef short  int16;
+typedef ushort uint16;
+typedef int    int32;
+typedef uint   uint32;
+typedef vlong  int64;
+typedef uvlong uint64;
diff --git a/include/plan9/arm/u.h b/include/plan9/arm/u.h
new file mode 100644
index 0000000..c387ae7
--- /dev/null
+++ b/include/plan9/arm/u.h
@@ -0,0 +1,14 @@
+// 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 "/arm/include/u.h"
+
+typedef char   int8;
+typedef uchar  uint8;
+typedef short  int16;
+typedef ushort uint16;
+typedef int    int32;
+typedef uint   uint32;
+typedef vlong  int64;
+typedef uvlong uint64;
diff --git a/include/plan9/libc.h b/include/plan9/libc.h
index d13ddbc..e6f9839 100644
--- a/include/plan9/libc.h
+++ b/include/plan9/libc.h
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+#define Runemax Plan9Runemax
 #include "/sys/include/libc.h"
+#undef Runemax
 #include "/sys/include/ctype.h"
 
 enum
@@ -14,3 +16,15 @@ char*	getgoos(void);
 char*	getgoarch(void);
 char*	getgoroot(void);
 char*	getgoversion(void);
+char*	getgoarm(void);
+char*	getgo386(void);
+
+void	flagcount(char*, char*, int*);
+void	flagint32(char*, char*, int32*);
+void	flagint64(char*, char*, int64*);
+void	flagstr(char*, char*, char**);
+void	flagparse(int*, char***, void (*usage)(void));
+void	flagfn0(char*, char*, void(*fn)(void));
+void	flagfn1(char*, char*, void(*fn)(char*));
+void	flagfn2(char*, char*, void(*fn)(char*, char*));
+void	flagprint(int);
diff --git a/lib/codereview/codereview.cfg b/lib/codereview/codereview.cfg
new file mode 100644
index 0000000..93b55c0
--- /dev/null
+++ b/lib/codereview/codereview.cfg
@@ -0,0 +1 @@
+defaultcc: golang-dev at googlegroups.com
diff --git a/lib/codereview/codereview.py b/lib/codereview/codereview.py
new file mode 100644
index 0000000..4b60145
--- /dev/null
+++ b/lib/codereview/codereview.py
@@ -0,0 +1,3550 @@
+# coding=utf-8
+# (The line above is necessary so that I can use 世界 in the
+# *comment* below without Python getting all bent out of shape.)
+
+# Copyright 2007-2009 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#	http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+'''Mercurial interface to codereview.appspot.com.
+
+To configure, set the following options in
+your repository's .hg/hgrc file.
+
+	[extensions]
+	codereview = /path/to/codereview.py
+
+	[codereview]
+	server = codereview.appspot.com
+
+The server should be running Rietveld; see http://code.google.com/p/rietveld/.
+
+In addition to the new commands, this extension introduces
+the file pattern syntax @nnnnnn, where nnnnnn is a change list
+number, to mean the files included in that change list, which
+must be associated with the current client.
+
+For example, if change 123456 contains the files x.go and y.go,
+"hg diff @123456" is equivalent to"hg diff x.go y.go".
+'''
+
+import sys
+
+if __name__ == "__main__":
+	print >>sys.stderr, "This is a Mercurial extension and should not be invoked directly."
+	sys.exit(2)
+
+# We require Python 2.6 for the json package.
+if sys.version < '2.6':
+	print >>sys.stderr, "The codereview extension requires Python 2.6 or newer."
+	print >>sys.stderr, "You are running Python " + sys.version
+	sys.exit(2)
+
+import json
+import os
+import re
+import stat
+import subprocess
+import threading
+import time
+
+from mercurial import commands as hg_commands
+from mercurial import util as hg_util
+
+defaultcc = None
+codereview_disabled = None
+real_rollback = None
+releaseBranch = None
+server = "codereview.appspot.com"
+server_url_base = None
+
+#######################################################################
+# Normally I would split this into multiple files, but it simplifies
+# import path headaches to keep it all in one file.  Sorry.
+# The different parts of the file are separated by banners like this one.
+
+#######################################################################
+# Helpers
+
+def RelativePath(path, cwd):
+	n = len(cwd)
+	if path.startswith(cwd) and path[n] == '/':
+		return path[n+1:]
+	return path
+
+def Sub(l1, l2):
+	return [l for l in l1 if l not in l2]
+
+def Add(l1, l2):
+	l = l1 + Sub(l2, l1)
+	l.sort()
+	return l
+
+def Intersect(l1, l2):
+	return [l for l in l1 if l in l2]
+
+#######################################################################
+# RE: UNICODE STRING HANDLING
+#
+# Python distinguishes between the str (string of bytes)
+# and unicode (string of code points) types.  Most operations
+# work on either one just fine, but some (like regexp matching)
+# require unicode, and others (like write) require str.
+#
+# As befits the language, Python hides the distinction between
+# unicode and str by converting between them silently, but
+# *only* if all the bytes/code points involved are 7-bit ASCII.
+# This means that if you're not careful, your program works
+# fine on "hello, world" and fails on "hello, 世界".  And of course,
+# the obvious way to be careful - use static types - is unavailable.
+# So the only way is trial and error to find where to put explicit
+# conversions.
+#
+# Because more functions do implicit conversion to str (string of bytes)
+# than do implicit conversion to unicode (string of code points),
+# the convention in this module is to represent all text as str,
+# converting to unicode only when calling a unicode-only function
+# and then converting back to str as soon as possible.
+
+def typecheck(s, t):
+	if type(s) != t:
+		raise hg_util.Abort("type check failed: %s has type %s != %s" % (repr(s), type(s), t))
+
+# If we have to pass unicode instead of str, ustr does that conversion clearly.
+def ustr(s):
+	typecheck(s, str)
+	return s.decode("utf-8")
+
+# Even with those, Mercurial still sometimes turns unicode into str
+# and then tries to use it as ascii.  Change Mercurial's default.
+def set_mercurial_encoding_to_utf8():
+	from mercurial import encoding
+	encoding.encoding = 'utf-8'
+
+set_mercurial_encoding_to_utf8()
+
+# Even with those we still run into problems.
+# I tried to do things by the book but could not convince
+# Mercurial to let me check in a change with UTF-8 in the
+# CL description or author field, no matter how many conversions
+# between str and unicode I inserted and despite changing the
+# default encoding.  I'm tired of this game, so set the default
+# encoding for all of Python to 'utf-8', not 'ascii'.
+def default_to_utf8():
+	import sys
+	stdout, __stdout__ = sys.stdout, sys.__stdout__
+	reload(sys)  # site.py deleted setdefaultencoding; get it back
+	sys.stdout, sys.__stdout__ = stdout, __stdout__
+	sys.setdefaultencoding('utf-8')
+
+default_to_utf8()
+
+#######################################################################
+# Status printer for long-running commands
+
+global_status = None
+
+def set_status(s):
+	# print >>sys.stderr, "\t", time.asctime(), s
+	global global_status
+	global_status = s
+
+class StatusThread(threading.Thread):
+	def __init__(self):
+		threading.Thread.__init__(self)
+	def run(self):
+		# pause a reasonable amount of time before
+		# starting to display status messages, so that
+		# most hg commands won't ever see them.
+		time.sleep(30)
+
+		# now show status every 15 seconds
+		while True:
+			time.sleep(15 - time.time() % 15)
+			s = global_status
+			if s is None:
+				continue
+			if s == "":
+				s = "(unknown status)"
+			print >>sys.stderr, time.asctime(), s
+
+def start_status_thread():
+	t = StatusThread()
+	t.setDaemon(True)  # allowed to exit if t is still running
+	t.start()
+
+#######################################################################
+# Change list parsing.
+#
+# Change lists are stored in .hg/codereview/cl.nnnnnn
+# where nnnnnn is the number assigned by the code review server.
+# Most data about a change list is stored on the code review server
+# too: the description, reviewer, and cc list are all stored there.
+# The only thing in the cl.nnnnnn file is the list of relevant files.
+# Also, the existence of the cl.nnnnnn file marks this repository
+# as the one where the change list lives.
+
+emptydiff = """Index: ~rietveld~placeholder~
+===================================================================
+diff --git a/~rietveld~placeholder~ b/~rietveld~placeholder~
+new file mode 100644
+"""
+
+class CL(object):
+	def __init__(self, name):
+		typecheck(name, str)
+		self.name = name
+		self.desc = ''
+		self.files = []
+		self.reviewer = []
+		self.cc = []
+		self.url = ''
+		self.local = False
+		self.web = False
+		self.copied_from = None	# None means current user
+		self.mailed = False
+		self.private = False
+		self.lgtm = []
+
+	def DiskText(self):
+		cl = self
+		s = ""
+		if cl.copied_from:
+			s += "Author: " + cl.copied_from + "\n\n"
+		if cl.private:
+			s += "Private: " + str(self.private) + "\n"
+		s += "Mailed: " + str(self.mailed) + "\n"
+		s += "Description:\n"
+		s += Indent(cl.desc, "\t")
+		s += "Files:\n"
+		for f in cl.files:
+			s += "\t" + f + "\n"
+		typecheck(s, str)
+		return s
+
+	def EditorText(self):
+		cl = self
+		s = _change_prolog
+		s += "\n"
+		if cl.copied_from:
+			s += "Author: " + cl.copied_from + "\n"
+		if cl.url != '':
+			s += 'URL: ' + cl.url + '	# cannot edit\n\n'
+		if cl.private:
+			s += "Private: True\n"
+		s += "Reviewer: " + JoinComma(cl.reviewer) + "\n"
+		s += "CC: " + JoinComma(cl.cc) + "\n"
+		s += "\n"
+		s += "Description:\n"
+		if cl.desc == '':
+			s += "\t<enter description here>\n"
+		else:
+			s += Indent(cl.desc, "\t")
+		s += "\n"
+		if cl.local or cl.name == "new":
+			s += "Files:\n"
+			for f in cl.files:
+				s += "\t" + f + "\n"
+			s += "\n"
+		typecheck(s, str)
+		return s
+
+	def PendingText(self, quick=False):
+		cl = self
+		s = cl.name + ":" + "\n"
+		s += Indent(cl.desc, "\t")
+		s += "\n"
+		if cl.copied_from:
+			s += "\tAuthor: " + cl.copied_from + "\n"
+		if not quick:
+			s += "\tReviewer: " + JoinComma(cl.reviewer) + "\n"
+			for (who, line) in cl.lgtm:
+				s += "\t\t" + who + ": " + line + "\n"
+			s += "\tCC: " + JoinComma(cl.cc) + "\n"
+		s += "\tFiles:\n"
+		for f in cl.files:
+			s += "\t\t" + f + "\n"
+		typecheck(s, str)
+		return s
+
+	def Flush(self, ui, repo):
+		if self.name == "new":
+			self.Upload(ui, repo, gofmt_just_warn=True, creating=True)
+		dir = CodeReviewDir(ui, repo)
+		path = dir + '/cl.' + self.name
+		f = open(path+'!', "w")
+		f.write(self.DiskText())
+		f.close()
+		if sys.platform == "win32" and os.path.isfile(path):
+			os.remove(path)
+		os.rename(path+'!', path)
+		if self.web and not self.copied_from:
+			EditDesc(self.name, desc=self.desc,
+				reviewers=JoinComma(self.reviewer), cc=JoinComma(self.cc),
+				private=self.private)
+
+	def Delete(self, ui, repo):
+		dir = CodeReviewDir(ui, repo)
+		os.unlink(dir + "/cl." + self.name)
+
+	def Subject(self):
+		s = line1(self.desc)
+		if len(s) > 60:
+			s = s[0:55] + "..."
+		if self.name != "new":
+			s = "code review %s: %s" % (self.name, s)
+		typecheck(s, str)
+		return s
+
+	def Upload(self, ui, repo, send_mail=False, gofmt=True, gofmt_just_warn=False, creating=False, quiet=False):
+		if not self.files and not creating:
+			ui.warn("no files in change list\n")
+		if ui.configbool("codereview", "force_gofmt", True) and gofmt:
+			CheckFormat(ui, repo, self.files, just_warn=gofmt_just_warn)
+		set_status("uploading CL metadata + diffs")
+		os.chdir(repo.root)
+		form_fields = [
+			("content_upload", "1"),
+			("reviewers", JoinComma(self.reviewer)),
+			("cc", JoinComma(self.cc)),
+			("description", self.desc),
+			("base_hashes", ""),
+		]
+
+		if self.name != "new":
+			form_fields.append(("issue", self.name))
+		vcs = None
+		# We do not include files when creating the issue,
+		# because we want the patch sets to record the repository
+		# and base revision they are diffs against.  We use the patch
+		# set message for that purpose, but there is no message with
+		# the first patch set.  Instead the message gets used as the
+		# new CL's overall subject.  So omit the diffs when creating
+		# and then we'll run an immediate upload.
+		# This has the effect that every CL begins with an empty "Patch set 1".
+		if self.files and not creating:
+			vcs = MercurialVCS(upload_options, ui, repo)
+			data = vcs.GenerateDiff(self.files)
+			files = vcs.GetBaseFiles(data)
+			if len(data) > MAX_UPLOAD_SIZE:
+				uploaded_diff_file = []
+				form_fields.append(("separate_patches", "1"))
+			else:
+				uploaded_diff_file = [("data", "data.diff", data)]
+		else:
+			uploaded_diff_file = [("data", "data.diff", emptydiff)]
+		
+		if vcs and self.name != "new":
+			form_fields.append(("subject", "diff -r " + vcs.base_rev + " " + ui.expandpath("default")))
+		else:
+			# First upload sets the subject for the CL itself.
+			form_fields.append(("subject", self.Subject()))
+		ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file)
+		response_body = MySend("/upload", body, content_type=ctype)
+		patchset = None
+		msg = response_body
+		lines = msg.splitlines()
+		if len(lines) >= 2:
+			msg = lines[0]
+			patchset = lines[1].strip()
+			patches = [x.split(" ", 1) for x in lines[2:]]
+		if response_body.startswith("Issue updated.") and quiet:
+			pass
+		else:
+			ui.status(msg + "\n")
+		set_status("uploaded CL metadata + diffs")
+		if not response_body.startswith("Issue created.") and not response_body.startswith("Issue updated."):
+			raise hg_util.Abort("failed to update issue: " + response_body)
+		issue = msg[msg.rfind("/")+1:]
+		self.name = issue
+		if not self.url:
+			self.url = server_url_base + self.name
+		if not uploaded_diff_file:
+			set_status("uploading patches")
+			patches = UploadSeparatePatches(issue, rpc, patchset, data, upload_options)
+		if vcs:
+			set_status("uploading base files")
+			vcs.UploadBaseFiles(issue, rpc, patches, patchset, upload_options, files)
+		if send_mail:
+			set_status("sending mail")
+			MySend("/" + issue + "/mail", payload="")
+		self.web = True
+		set_status("flushing changes to disk")
+		self.Flush(ui, repo)
+		return
+
+	def Mail(self, ui, repo):
+		pmsg = "Hello " + JoinComma(self.reviewer)
+		if self.cc:
+			pmsg += " (cc: %s)" % (', '.join(self.cc),)
+		pmsg += ",\n"
+		pmsg += "\n"
+		repourl = ui.expandpath("default")
+		if not self.mailed:
+			pmsg += "I'd like you to review this change to\n" + repourl + "\n"
+		else:
+			pmsg += "Please take another look.\n"
+		typecheck(pmsg, str)
+		PostMessage(ui, self.name, pmsg, subject=self.Subject())
+		self.mailed = True
+		self.Flush(ui, repo)
+
+def GoodCLName(name):
+	typecheck(name, str)
+	return re.match("^[0-9]+$", name)
+
+def ParseCL(text, name):
+	typecheck(text, str)
+	typecheck(name, str)
+	sname = None
+	lineno = 0
+	sections = {
+		'Author': '',
+		'Description': '',
+		'Files': '',
+		'URL': '',
+		'Reviewer': '',
+		'CC': '',
+		'Mailed': '',
+		'Private': '',
+	}
+	for line in text.split('\n'):
+		lineno += 1
+		line = line.rstrip()
+		if line != '' and line[0] == '#':
+			continue
+		if line == '' or line[0] == ' ' or line[0] == '\t':
+			if sname == None and line != '':
+				return None, lineno, 'text outside section'
+			if sname != None:
+				sections[sname] += line + '\n'
+			continue
+		p = line.find(':')
+		if p >= 0:
+			s, val = line[:p].strip(), line[p+1:].strip()
+			if s in sections:
+				sname = s
+				if val != '':
+					sections[sname] += val + '\n'
+				continue
+		return None, lineno, 'malformed section header'
+
+	for k in sections:
+		sections[k] = StripCommon(sections[k]).rstrip()
+
+	cl = CL(name)
+	if sections['Author']:
+		cl.copied_from = sections['Author']
+	cl.desc = sections['Description']
+	for line in sections['Files'].split('\n'):
+		i = line.find('#')
+		if i >= 0:
+			line = line[0:i].rstrip()
+		line = line.strip()
+		if line == '':
+			continue
+		cl.files.append(line)
+	cl.reviewer = SplitCommaSpace(sections['Reviewer'])
+	cl.cc = SplitCommaSpace(sections['CC'])
+	cl.url = sections['URL']
+	if sections['Mailed'] != 'False':
+		# Odd default, but avoids spurious mailings when
+		# reading old CLs that do not have a Mailed: line.
+		# CLs created with this update will always have 
+		# Mailed: False on disk.
+		cl.mailed = True
+	if sections['Private'] in ('True', 'true', 'Yes', 'yes'):
+		cl.private = True
+	if cl.desc == '<enter description here>':
+		cl.desc = ''
+	return cl, 0, ''
+
+def SplitCommaSpace(s):
+	typecheck(s, str)
+	s = s.strip()
+	if s == "":
+		return []
+	return re.split(", *", s)
+
+def CutDomain(s):
+	typecheck(s, str)
+	i = s.find('@')
+	if i >= 0:
+		s = s[0:i]
+	return s
+
+def JoinComma(l):
+	for s in l:
+		typecheck(s, str)
+	return ", ".join(l)
+
+def ExceptionDetail():
+	s = str(sys.exc_info()[0])
+	if s.startswith("<type '") and s.endswith("'>"):
+		s = s[7:-2]
+	elif s.startswith("<class '") and s.endswith("'>"):
+		s = s[8:-2]
+	arg = str(sys.exc_info()[1])
+	if len(arg) > 0:
+		s += ": " + arg
+	return s
+
+def IsLocalCL(ui, repo, name):
+	return GoodCLName(name) and os.access(CodeReviewDir(ui, repo) + "/cl." + name, 0)
+
+# Load CL from disk and/or the web.
+def LoadCL(ui, repo, name, web=True):
+	typecheck(name, str)
+	set_status("loading CL " + name)
+	if not GoodCLName(name):
+		return None, "invalid CL name"
+	dir = CodeReviewDir(ui, repo)
+	path = dir + "cl." + name
+	if os.access(path, 0):
+		ff = open(path)
+		text = ff.read()
+		ff.close()
+		cl, lineno, err = ParseCL(text, name)
+		if err != "":
+			return None, "malformed CL data: "+err
+		cl.local = True
+	else:
+		cl = CL(name)
+	if web:
+		set_status("getting issue metadata from web")
+		d = JSONGet(ui, "/api/" + name + "?messages=true")
+		set_status(None)
+		if d is None:
+			return None, "cannot load CL %s from server" % (name,)
+		if 'owner_email' not in d or 'issue' not in d or str(d['issue']) != name:
+			return None, "malformed response loading CL data from code review server"
+		cl.dict = d
+		cl.reviewer = d.get('reviewers', [])
+		cl.cc = d.get('cc', [])
+		if cl.local and cl.copied_from and cl.desc:
+			# local copy of CL written by someone else
+			# and we saved a description.  use that one,
+			# so that committers can edit the description
+			# before doing hg submit.
+			pass
+		else:
+			cl.desc = d.get('description', "")
+		cl.url = server_url_base + name
+		cl.web = True
+		cl.private = d.get('private', False) != False
+		cl.lgtm = []
+		for m in d.get('messages', []):
+			if m.get('approval', False) == True or m.get('disapproval', False) == True:
+				who = re.sub('@.*', '', m.get('sender', ''))
+				text = re.sub("\n(.|\n)*", '', m.get('text', ''))
+				cl.lgtm.append((who, text))
+
+	set_status("loaded CL " + name)
+	return cl, ''
+
+class LoadCLThread(threading.Thread):
+	def __init__(self, ui, repo, dir, f, web):
+		threading.Thread.__init__(self)
+		self.ui = ui
+		self.repo = repo
+		self.dir = dir
+		self.f = f
+		self.web = web
+		self.cl = None
+	def run(self):
+		cl, err = LoadCL(self.ui, self.repo, self.f[3:], web=self.web)
+		if err != '':
+			self.ui.warn("loading "+self.dir+self.f+": " + err + "\n")
+			return
+		self.cl = cl
+
+# Load all the CLs from this repository.
+def LoadAllCL(ui, repo, web=True):
+	dir = CodeReviewDir(ui, repo)
+	m = {}
+	files = [f for f in os.listdir(dir) if f.startswith('cl.')]
+	if not files:
+		return m
+	active = []
+	first = True
+	for f in files:
+		t = LoadCLThread(ui, repo, dir, f, web)
+		t.start()
+		if web and first:
+			# first request: wait in case it needs to authenticate
+			# otherwise we get lots of user/password prompts
+			# running in parallel.
+			t.join()
+			if t.cl:
+				m[t.cl.name] = t.cl
+			first = False
+		else:
+			active.append(t)
+	for t in active:
+		t.join()
+		if t.cl:
+			m[t.cl.name] = t.cl
+	return m
+
+# Find repository root.  On error, ui.warn and return None
+def RepoDir(ui, repo):
+	url = repo.url();
+	if not url.startswith('file:'):
+		ui.warn("repository %s is not in local file system\n" % (url,))
+		return None
+	url = url[5:]
+	if url.endswith('/'):
+		url = url[:-1]
+	typecheck(url, str)
+	return url
+
+# Find (or make) code review directory.  On error, ui.warn and return None
+def CodeReviewDir(ui, repo):
+	dir = RepoDir(ui, repo)
+	if dir == None:
+		return None
+	dir += '/.hg/codereview/'
+	if not os.path.isdir(dir):
+		try:
+			os.mkdir(dir, 0700)
+		except:
+			ui.warn('cannot mkdir %s: %s\n' % (dir, ExceptionDetail()))
+			return None
+	typecheck(dir, str)
+	return dir
+
+# Turn leading tabs into spaces, so that the common white space
+# prefix doesn't get confused when people's editors write out 
+# some lines with spaces, some with tabs.  Only a heuristic
+# (some editors don't use 8 spaces either) but a useful one.
+def TabsToSpaces(line):
+	i = 0
+	while i < len(line) and line[i] == '\t':
+		i += 1
+	return ' '*(8*i) + line[i:]
+
+# Strip maximal common leading white space prefix from text
+def StripCommon(text):
+	typecheck(text, str)
+	ws = None
+	for line in text.split('\n'):
+		line = line.rstrip()
+		if line == '':
+			continue
+		line = TabsToSpaces(line)
+		white = line[:len(line)-len(line.lstrip())]
+		if ws == None:
+			ws = white
+		else:
+			common = ''
+			for i in range(min(len(white), len(ws))+1):
+				if white[0:i] == ws[0:i]:
+					common = white[0:i]
+			ws = common
+		if ws == '':
+			break
+	if ws == None:
+		return text
+	t = ''
+	for line in text.split('\n'):
+		line = line.rstrip()
+		line = TabsToSpaces(line)
+		if line.startswith(ws):
+			line = line[len(ws):]
+		if line == '' and t == '':
+			continue
+		t += line + '\n'
+	while len(t) >= 2 and t[-2:] == '\n\n':
+		t = t[:-1]
+	typecheck(t, str)
+	return t
+
+# Indent text with indent.
+def Indent(text, indent):
+	typecheck(text, str)
+	typecheck(indent, str)
+	t = ''
+	for line in text.split('\n'):
+		t += indent + line + '\n'
+	typecheck(t, str)
+	return t
+
+# Return the first line of l
+def line1(text):
+	typecheck(text, str)
+	return text.split('\n')[0]
+
+_change_prolog = """# Change list.
+# Lines beginning with # are ignored.
+# Multi-line values should be indented.
+"""
+
+desc_re = '^(.+: |(tag )?(release|weekly)\.|fix build|undo CL)'
+
+desc_msg = '''Your CL description appears not to use the standard form.
+
+The first line of your 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.
+
+Examples:
+
+	encoding/rot13: new package
+
+	math: add IsInf, IsNaN
+	
+	net: fix cname in LookupHost
+
+	unicode: update to Unicode 5.0.2
+
+'''
+
+def promptyesno(ui, msg):
+	return ui.promptchoice(msg, ["&yes", "&no"], 0) == 0
+
+def promptremove(ui, repo, f):
+	if promptyesno(ui, "hg remove %s (y/n)?" % (f,)):
+		if hg_commands.remove(ui, repo, 'path:'+f) != 0:
+			ui.warn("error removing %s" % (f,))
+
+def promptadd(ui, repo, f):
+	if promptyesno(ui, "hg add %s (y/n)?" % (f,)):
+		if hg_commands.add(ui, repo, 'path:'+f) != 0:
+			ui.warn("error adding %s" % (f,))
+
+def EditCL(ui, repo, cl):
+	set_status(None)	# do not show status
+	s = cl.EditorText()
+	while True:
+		s = ui.edit(s, ui.username())
+		
+		# We can't trust Mercurial + Python not to die before making the change,
+		# so, by popular demand, just scribble the most recent CL edit into
+		# $(hg root)/last-change so that if Mercurial does die, people
+		# can look there for their work.
+		try:
+			f = open(repo.root+"/last-change", "w")
+			f.write(s)
+			f.close()
+		except:
+			pass
+
+		clx, line, err = ParseCL(s, cl.name)
+		if err != '':
+			if not promptyesno(ui, "error parsing change list: line %d: %s\nre-edit (y/n)?" % (line, err)):
+				return "change list not modified"
+			continue
+		
+		# Check description.
+		if clx.desc == '':
+			if promptyesno(ui, "change list should have a description\nre-edit (y/n)?"):
+				continue
+		elif re.search('<enter reason for undo>', clx.desc):
+			if promptyesno(ui, "change list description omits reason for undo\nre-edit (y/n)?"):
+				continue
+		elif not re.match(desc_re, clx.desc.split('\n')[0]):
+			if promptyesno(ui, desc_msg + "re-edit (y/n)?"):
+				continue
+
+		# Check file list for files that need to be hg added or hg removed
+		# or simply aren't understood.
+		pats = ['path:'+f for f in clx.files]
+		changed = hg_matchPattern(ui, repo, *pats, modified=True, added=True, removed=True)
+		deleted = hg_matchPattern(ui, repo, *pats, deleted=True)
+		unknown = hg_matchPattern(ui, repo, *pats, unknown=True)
+		ignored = hg_matchPattern(ui, repo, *pats, ignored=True)
+		clean = hg_matchPattern(ui, repo, *pats, clean=True)
+		files = []
+		for f in clx.files:
+			if f in changed:
+				files.append(f)
+				continue
+			if f in deleted:
+				promptremove(ui, repo, f)
+				files.append(f)
+				continue
+			if f in unknown:
+				promptadd(ui, repo, f)
+				files.append(f)
+				continue
+			if f in ignored:
+				ui.warn("error: %s is excluded by .hgignore; omitting\n" % (f,))
+				continue
+			if f in clean:
+				ui.warn("warning: %s is listed in the CL but unchanged\n" % (f,))
+				files.append(f)
+				continue
+			p = repo.root + '/' + f
+			if os.path.isfile(p):
+				ui.warn("warning: %s is a file but not known to hg\n" % (f,))
+				files.append(f)
+				continue
+			if os.path.isdir(p):
+				ui.warn("error: %s is a directory, not a file; omitting\n" % (f,))
+				continue
+			ui.warn("error: %s does not exist; omitting\n" % (f,))
+		clx.files = files
+
+		cl.desc = clx.desc
+		cl.reviewer = clx.reviewer
+		cl.cc = clx.cc
+		cl.files = clx.files
+		cl.private = clx.private
+		break
+	return ""
+
+# For use by submit, etc. (NOT by change)
+# Get change list number or list of files from command line.
+# If files are given, make a new change list.
+def CommandLineCL(ui, repo, pats, opts, op="verb", defaultcc=None):
+	if len(pats) > 0 and GoodCLName(pats[0]):
+		if len(pats) != 1:
+			return None, "cannot specify change number and file names"
+		if opts.get('message'):
+			return None, "cannot use -m with existing CL"
+		cl, err = LoadCL(ui, repo, pats[0], web=True)
+		if err != "":
+			return None, err
+	else:
+		cl = CL("new")
+		cl.local = True
+		cl.files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
+		if not cl.files:
+			return None, "no files changed (use hg %s <number> to use existing CL)" % op
+	if opts.get('reviewer'):
+		cl.reviewer = Add(cl.reviewer, SplitCommaSpace(opts.get('reviewer')))
+	if opts.get('cc'):
+		cl.cc = Add(cl.cc, SplitCommaSpace(opts.get('cc')))
+	if defaultcc:
+		cl.cc = Add(cl.cc, defaultcc)
+	if cl.name == "new":
+		if opts.get('message'):
+			cl.desc = opts.get('message')
+		else:
+			err = EditCL(ui, repo, cl)
+			if err != '':
+				return None, err
+	return cl, ""
+
+#######################################################################
+# Change list file management
+
+# Return list of changed files in repository that match pats.
+# The patterns came from the command line, so we warn
+# if they have no effect or cannot be understood.
+def ChangedFiles(ui, repo, pats, taken=None):
+	taken = taken or {}
+	# Run each pattern separately so that we can warn about
+	# patterns that didn't do anything useful.
+	for p in pats:
+		for f in hg_matchPattern(ui, repo, p, unknown=True):
+			promptadd(ui, repo, f)
+		for f in hg_matchPattern(ui, repo, p, removed=True):
+			promptremove(ui, repo, f)
+		files = hg_matchPattern(ui, repo, p, modified=True, added=True, removed=True)
+		for f in files:
+			if f in taken:
+				ui.warn("warning: %s already in CL %s\n" % (f, taken[f].name))
+		if not files:
+			ui.warn("warning: %s did not match any modified files\n" % (p,))
+
+	# Again, all at once (eliminates duplicates)
+	l = hg_matchPattern(ui, repo, *pats, modified=True, added=True, removed=True)
+	l.sort()
+	if taken:
+		l = Sub(l, taken.keys())
+	return l
+
+# Return list of changed files in repository that match pats and still exist.
+def ChangedExistingFiles(ui, repo, pats, opts):
+	l = hg_matchPattern(ui, repo, *pats, modified=True, added=True)
+	l.sort()
+	return l
+
+# Return list of files claimed by existing CLs
+def Taken(ui, repo):
+	all = LoadAllCL(ui, repo, web=False)
+	taken = {}
+	for _, cl in all.items():
+		for f in cl.files:
+			taken[f] = cl
+	return taken
+
+# Return list of changed files that are not claimed by other CLs
+def DefaultFiles(ui, repo, pats):
+	return ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
+
+#######################################################################
+# File format checking.
+
+def CheckFormat(ui, repo, files, just_warn=False):
+	set_status("running gofmt")
+	CheckGofmt(ui, repo, files, just_warn)
+	CheckTabfmt(ui, repo, files, just_warn)
+
+# Check that gofmt run on the list of files does not change them
+def CheckGofmt(ui, repo, files, just_warn):
+	files = gofmt_required(files)
+	if not files:
+		return
+	cwd = os.getcwd()
+	files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
+	files = [f for f in files if os.access(f, 0)]
+	if not files:
+		return
+	try:
+		cmd = subprocess.Popen(["gofmt", "-l"] + files, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=sys.platform != "win32")
+		cmd.stdin.close()
+	except:
+		raise hg_util.Abort("gofmt: " + ExceptionDetail())
+	data = cmd.stdout.read()
+	errors = cmd.stderr.read()
+	cmd.wait()
+	set_status("done with gofmt")
+	if len(errors) > 0:
+		ui.warn("gofmt errors:\n" + errors.rstrip() + "\n")
+		return
+	if len(data) > 0:
+		msg = "gofmt needs to format these files (run hg gofmt):\n" + Indent(data, "\t").rstrip()
+		if just_warn:
+			ui.warn("warning: " + msg + "\n")
+		else:
+			raise hg_util.Abort(msg)
+	return
+
+# Check that *.[chys] files indent using tabs.
+def CheckTabfmt(ui, repo, files, just_warn):
+	files = [f for f in files if f.startswith('src/') and re.search(r"\.[chys]$", f) and not re.search(r"\.tab\.[ch]$", f)]
+	if not files:
+		return
+	cwd = os.getcwd()
+	files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
+	files = [f for f in files if os.access(f, 0)]
+	badfiles = []
+	for f in files:
+		try:
+			for line in open(f, 'r'):
+				# Four leading spaces is enough to complain about,
+				# except that some Plan 9 code uses four spaces as the label indent,
+				# so allow that.
+				if line.startswith('    ') and not re.match('    [A-Za-z0-9_]+:', line):
+					badfiles.append(f)
+					break
+		except:
+			# ignore cannot open file, etc.
+			pass
+	if len(badfiles) > 0:
+		msg = "these files use spaces for indentation (use tabs instead):\n\t" + "\n\t".join(badfiles)
+		if just_warn:
+			ui.warn("warning: " + msg + "\n")
+		else:
+			raise hg_util.Abort(msg)
+	return
+
+#######################################################################
+# CONTRIBUTORS file parsing
+
+contributorsCache = None
+contributorsURL = None
+
+def ReadContributors(ui, repo):
+	global contributorsCache
+	if contributorsCache is not None:
+		return contributorsCache
+
+	try:
+		if contributorsURL is not None:
+			opening = contributorsURL
+			f = urllib2.urlopen(contributorsURL)
+		else:
+			opening = repo.root + '/CONTRIBUTORS'
+			f = open(repo.root + '/CONTRIBUTORS', 'r')
+	except:
+		ui.write("warning: cannot open %s: %s\n" % (opening, ExceptionDetail()))
+		return
+
+	contributors = {}
+	for line in f:
+		# CONTRIBUTORS is a list of lines like:
+		#	Person <email>
+		#	Person <email> <alt-email>
+		# The first email address is the one used in commit logs.
+		if line.startswith('#'):
+			continue
+		m = re.match(r"([^<>]+\S)\s+(<[^<>\s]+>)((\s+<[^<>\s]+>)*)\s*$", line)
+		if m:
+			name = m.group(1)
+			email = m.group(2)[1:-1]
+			contributors[email.lower()] = (name, email)
+			for extra in m.group(3).split():
+				contributors[extra[1:-1].lower()] = (name, email)
+
+	contributorsCache = contributors
+	return contributors
+
+def CheckContributor(ui, repo, user=None):
+	set_status("checking CONTRIBUTORS file")
+	user, userline = FindContributor(ui, repo, user, warn=False)
+	if not userline:
+		raise hg_util.Abort("cannot find %s in CONTRIBUTORS" % (user,))
+	return userline
+
+def FindContributor(ui, repo, user=None, warn=True):
+	if not user:
+		user = ui.config("ui", "username")
+		if not user:
+			raise hg_util.Abort("[ui] username is not configured in .hgrc")
+	user = user.lower()
+	m = re.match(r".*<(.*)>", user)
+	if m:
+		user = m.group(1)
+
+	contributors = ReadContributors(ui, repo)
+	if user not in contributors:
+		if warn:
+			ui.warn("warning: cannot find %s in CONTRIBUTORS\n" % (user,))
+		return user, None
+	
+	user, email = contributors[user]
+	return email, "%s <%s>" % (user, email)
+
+#######################################################################
+# Mercurial helper functions.
+# Read http://mercurial.selenic.com/wiki/MercurialApi before writing any of these.
+# We use the ui.pushbuffer/ui.popbuffer + hg_commands.xxx tricks for all interaction
+# with Mercurial.  It has proved the most stable as they make changes.
+
+hgversion = hg_util.version()
+
+# We require Mercurial 1.9 and suggest Mercurial 2.0.
+# The details of the scmutil package changed then,
+# so allowing earlier versions would require extra band-aids below.
+# Ubuntu 11.10 ships with Mercurial 1.9.1 as the default version.
+hg_required = "1.9"
+hg_suggested = "2.0"
+
+old_message = """
+
+The code review extension requires Mercurial """+hg_required+""" or newer.
+You are using Mercurial """+hgversion+""".
+
+To install a new Mercurial, visit http://mercurial.selenic.com/downloads/.
+"""
+
+linux_message = """
+You may need to clear your current Mercurial installation by running:
+
+	sudo apt-get remove mercurial mercurial-common
+	sudo rm -rf /etc/mercurial
+"""
+
+if hgversion < hg_required:
+	msg = old_message
+	if os.access("/etc/mercurial", 0):
+		msg += linux_message
+	raise hg_util.Abort(msg)
+
+from mercurial.hg import clean as hg_clean
+from mercurial import cmdutil as hg_cmdutil
+from mercurial import error as hg_error
+from mercurial import match as hg_match
+from mercurial import node as hg_node
+
+class uiwrap(object):
+	def __init__(self, ui):
+		self.ui = ui
+		ui.pushbuffer()
+		self.oldQuiet = ui.quiet
+		ui.quiet = True
+		self.oldVerbose = ui.verbose
+		ui.verbose = False
+	def output(self):
+		ui = self.ui
+		ui.quiet = self.oldQuiet
+		ui.verbose = self.oldVerbose
+		return ui.popbuffer()
+
+def to_slash(path):
+	if sys.platform == "win32":
+		return path.replace('\\', '/')
+	return path
+
+def hg_matchPattern(ui, repo, *pats, **opts):
+	w = uiwrap(ui)
+	hg_commands.status(ui, repo, *pats, **opts)
+	text = w.output()
+	ret = []
+	prefix = to_slash(os.path.realpath(repo.root))+'/'
+	for line in text.split('\n'):
+		f = line.split()
+		if len(f) > 1:
+			if len(pats) > 0:
+				# Given patterns, Mercurial shows relative to cwd
+				p = to_slash(os.path.realpath(f[1]))
+				if not p.startswith(prefix):
+					print >>sys.stderr, "File %s not in repo root %s.\n" % (p, prefix)
+				else:
+					ret.append(p[len(prefix):])
+			else:
+				# Without patterns, Mercurial shows relative to root (what we want)
+				ret.append(to_slash(f[1]))
+	return ret
+
+def hg_heads(ui, repo):
+	w = uiwrap(ui)
+	hg_commands.heads(ui, repo)
+	return w.output()
+
+noise = [
+	"",
+	"resolving manifests",
+	"searching for changes",
+	"couldn't find merge tool hgmerge",
+	"adding changesets",
+	"adding manifests",
+	"adding file changes",
+	"all local heads known remotely",
+]
+
+def isNoise(line):
+	line = str(line)
+	for x in noise:
+		if line == x:
+			return True
+	return False
+
+def hg_incoming(ui, repo):
+	w = uiwrap(ui)
+	ret = hg_commands.incoming(ui, repo, force=False, bundle="")
+	if ret and ret != 1:
+		raise hg_util.Abort(ret)
+	return w.output()
+
+def hg_log(ui, repo, **opts):
+	for k in ['date', 'keyword', 'rev', 'user']:
+		if not opts.has_key(k):
+			opts[k] = ""
+	w = uiwrap(ui)
+	ret = hg_commands.log(ui, repo, **opts)
+	if ret:
+		raise hg_util.Abort(ret)
+	return w.output()
+
+def hg_outgoing(ui, repo, **opts):
+	w = uiwrap(ui)
+	ret = hg_commands.outgoing(ui, repo, **opts)
+	if ret and ret != 1:
+		raise hg_util.Abort(ret)
+	return w.output()
+
+def hg_pull(ui, repo, **opts):
+	w = uiwrap(ui)
+	ui.quiet = False
+	ui.verbose = True  # for file list
+	err = hg_commands.pull(ui, repo, **opts)
+	for line in w.output().split('\n'):
+		if isNoise(line):
+			continue
+		if line.startswith('moving '):
+			line = 'mv ' + line[len('moving '):]
+		if line.startswith('getting ') and line.find(' to ') >= 0:
+			line = 'mv ' + line[len('getting '):]
+		if line.startswith('getting '):
+			line = '+ ' + line[len('getting '):]
+		if line.startswith('removing '):
+			line = '- ' + line[len('removing '):]
+		ui.write(line + '\n')
+	return err
+
+def hg_push(ui, repo, **opts):
+	w = uiwrap(ui)
+	ui.quiet = False
+	ui.verbose = True
+	err = hg_commands.push(ui, repo, **opts)
+	for line in w.output().split('\n'):
+		if not isNoise(line):
+			ui.write(line + '\n')
+	return err
+
+def hg_commit(ui, repo, *pats, **opts):
+	return hg_commands.commit(ui, repo, *pats, **opts)
+
+#######################################################################
+# Mercurial precommit hook to disable commit except through this interface.
+
+commit_okay = False
+
+def precommithook(ui, repo, **opts):
+	if commit_okay:
+		return False  # False means okay.
+	ui.write("\ncodereview extension enabled; use mail, upload, or submit instead of commit\n\n")
+	return True
+
+#######################################################################
+# @clnumber file pattern support
+
+# We replace scmutil.match with the MatchAt wrapper to add the @clnumber pattern.
+
+match_repo = None
+match_ui = None
+match_orig = None
+
+def InstallMatch(ui, repo):
+	global match_repo
+	global match_ui
+	global match_orig
+
+	match_ui = ui
+	match_repo = repo
+
+	from mercurial import scmutil
+	match_orig = scmutil.match
+	scmutil.match = MatchAt
+
+def MatchAt(ctx, pats=None, opts=None, globbed=False, default='relpath'):
+	taken = []
+	files = []
+	pats = pats or []
+	opts = opts or {}
+	
+	for p in pats:
+		if p.startswith('@'):
+			taken.append(p)
+			clname = p[1:]
+			if clname == "default":
+				files = DefaultFiles(match_ui, match_repo, [])
+			else:
+				if not GoodCLName(clname):
+					raise hg_util.Abort("invalid CL name " + clname)
+				cl, err = LoadCL(match_repo.ui, match_repo, clname, web=False)
+				if err != '':
+					raise hg_util.Abort("loading CL " + clname + ": " + err)
+				if not cl.files:
+					raise hg_util.Abort("no files in CL " + clname)
+				files = Add(files, cl.files)
+	pats = Sub(pats, taken) + ['path:'+f for f in files]
+
+	# work-around for http://selenic.com/hg/rev/785bbc8634f8
+	if not hasattr(ctx, 'match'):
+		ctx = ctx[None]
+	return match_orig(ctx, pats=pats, opts=opts, globbed=globbed, default=default)
+
+#######################################################################
+# Commands added by code review extension.
+
+def hgcommand(f):
+	return f
+
+#######################################################################
+# hg change
+
+ at hgcommand
+def change(ui, repo, *pats, **opts):
+	"""create, edit or delete a change list
+
+	Create, edit or delete a change list.
+	A change list is a group of files to be reviewed and submitted together,
+	plus a textual description of the change.
+	Change lists are referred to by simple alphanumeric names.
+
+	Changes must be reviewed before they can be submitted.
+
+	In the absence of options, the change command opens the
+	change list for editing in the default editor.
+
+	Deleting a change with the -d or -D flag does not affect
+	the contents of the files listed in that change.  To revert
+	the files listed in a change, use
+
+		hg revert @123456
+
+	before running hg change -d 123456.
+	"""
+
+	if codereview_disabled:
+		raise hg_util.Abort(codereview_disabled)
+	
+	dirty = {}
+	if len(pats) > 0 and GoodCLName(pats[0]):
+		name = pats[0]
+		if len(pats) != 1:
+			raise hg_util.Abort("cannot specify CL name and file patterns")
+		pats = pats[1:]
+		cl, err = LoadCL(ui, repo, name, web=True)
+		if err != '':
+			raise hg_util.Abort(err)
+		if not cl.local and (opts["stdin"] or not opts["stdout"]):
+			raise hg_util.Abort("cannot change non-local CL " + name)
+	else:
+		name = "new"
+		cl = CL("new")
+		if repo[None].branch() != "default":
+			raise hg_util.Abort("cannot create CL outside default branch; switch with 'hg update default'")
+		dirty[cl] = True
+		files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
+
+	if opts["delete"] or opts["deletelocal"]:
+		if opts["delete"] and opts["deletelocal"]:
+			raise hg_util.Abort("cannot use -d and -D together")
+		flag = "-d"
+		if opts["deletelocal"]:
+			flag = "-D"
+		if name == "new":
+			raise hg_util.Abort("cannot use "+flag+" with file patterns")
+		if opts["stdin"] or opts["stdout"]:
+			raise hg_util.Abort("cannot use "+flag+" with -i or -o")
+		if not cl.local:
+			raise hg_util.Abort("cannot change non-local CL " + name)
+		if opts["delete"]:
+			if cl.copied_from:
+				raise hg_util.Abort("original author must delete CL; hg change -D will remove locally")
+			PostMessage(ui, cl.name, "*** Abandoned ***", send_mail=cl.mailed)
+			EditDesc(cl.name, closed=True, private=cl.private)
+		cl.Delete(ui, repo)
+		return
+
+	if opts["stdin"]:
+		s = sys.stdin.read()
+		clx, line, err = ParseCL(s, name)
+		if err != '':
+			raise hg_util.Abort("error parsing change list: line %d: %s" % (line, err))
+		if clx.desc is not None:
+			cl.desc = clx.desc;
+			dirty[cl] = True
+		if clx.reviewer is not None:
+			cl.reviewer = clx.reviewer
+			dirty[cl] = True
+		if clx.cc is not None:
+			cl.cc = clx.cc
+			dirty[cl] = True
+		if clx.files is not None:
+			cl.files = clx.files
+			dirty[cl] = True
+		if clx.private != cl.private:
+			cl.private = clx.private
+			dirty[cl] = True
+
+	if not opts["stdin"] and not opts["stdout"]:
+		if name == "new":
+			cl.files = files
+		err = EditCL(ui, repo, cl)
+		if err != "":
+			raise hg_util.Abort(err)
+		dirty[cl] = True
+
+	for d, _ in dirty.items():
+		name = d.name
+		d.Flush(ui, repo)
+		if name == "new":
+			d.Upload(ui, repo, quiet=True)
+
+	if opts["stdout"]:
+		ui.write(cl.EditorText())
+	elif opts["pending"]:
+		ui.write(cl.PendingText())
+	elif name == "new":
+		if ui.quiet:
+			ui.write(cl.name)
+		else:
+			ui.write("CL created: " + cl.url + "\n")
+	return
+
+#######################################################################
+# hg code-login (broken?)
+
+ at hgcommand
+def code_login(ui, repo, **opts):
+	"""log in to code review server
+
+	Logs in to the code review server, saving a cookie in
+	a file in your home directory.
+	"""
+	if codereview_disabled:
+		raise hg_util.Abort(codereview_disabled)
+
+	MySend(None)
+
+#######################################################################
+# hg clpatch / undo / release-apply / download
+# All concerned with applying or unapplying patches to the repository.
+
+ at hgcommand
+def clpatch(ui, repo, clname, **opts):
+	"""import a patch from the code review server
+
+	Imports a patch from the code review server into the local client.
+	If the local client has already modified any of the files that the
+	patch modifies, this command will refuse to apply the patch.
+
+	Submitting an imported patch will keep the original author's
+	name as the Author: line but add your own name to a Committer: line.
+	"""
+	if repo[None].branch() != "default":
+		raise hg_util.Abort("cannot run hg clpatch outside default branch")
+	err = clpatch_or_undo(ui, repo, clname, opts, mode="clpatch")
+	if err:
+		raise hg_util.Abort(err)
+
+ at hgcommand
+def undo(ui, repo, clname, **opts):
+	"""undo the effect of a CL
+	
+	Creates a new CL that undoes an earlier CL.
+	After creating the CL, opens the CL text for editing so that
+	you can add the reason for the undo to the description.
+	"""
+	if repo[None].branch() != "default":
+		raise hg_util.Abort("cannot run hg undo outside default branch")
+	err = clpatch_or_undo(ui, repo, clname, opts, mode="undo")
+	if err:
+		raise hg_util.Abort(err)
+
+ at hgcommand
+def release_apply(ui, repo, clname, **opts):
+	"""apply a CL to the release branch
+
+	Creates a new CL copying a previously committed change
+	from the main branch to the release branch.
+	The current client must either be clean or already be in
+	the release branch.
+	
+	The release branch must be created by starting with a
+	clean client, disabling the code review plugin, and running:
+	
+		hg update weekly.YYYY-MM-DD
+		hg branch release-branch.rNN
+		hg commit -m 'create release-branch.rNN'
+		hg push --new-branch
+	
+	Then re-enable the code review plugin.
+	
+	People can test the release branch by running
+	
+		hg update release-branch.rNN
+	
+	in a clean client.  To return to the normal tree,
+	
+		hg update default
+	
+	Move changes since the weekly into the release branch 
+	using hg release-apply followed by the usual code review
+	process and hg submit.
+
+	When it comes time to tag the release, record the
+	final long-form tag of the release-branch.rNN
+	in the *default* branch's .hgtags file.  That is, run
+	
+		hg update default
+	
+	and then edit .hgtags as you would for a weekly.
+		
+	"""
+	c = repo[None]
+	if not releaseBranch:
+		raise hg_util.Abort("no active release branches")
+	if c.branch() != releaseBranch:
+		if c.modified() or c.added() or c.removed():
+			raise hg_util.Abort("uncommitted local changes - cannot switch branches")
+		err = hg_clean(repo, releaseBranch)
+		if err:
+			raise hg_util.Abort(err)
+	try:
+		err = clpatch_or_undo(ui, repo, clname, opts, mode="backport")
+		if err:
+			raise hg_util.Abort(err)
+	except Exception, e:
+		hg_clean(repo, "default")
+		raise e
+
+def rev2clname(rev):
+	# Extract CL name from revision description.
+	# The last line in the description that is a codereview URL is the real one.
+	# Earlier lines might be part of the user-written description.
+	all = re.findall('(?m)^https?://codereview.appspot.com/([0-9]+)$', rev.description())
+	if len(all) > 0:
+		return all[-1]
+	return ""
+
+undoHeader = """undo CL %s / %s
+
+<enter reason for undo>
+
+««« original CL description
+"""
+
+undoFooter = """
+»»»
+"""
+
+backportHeader = """[%s] %s
+
+««« CL %s / %s
+"""
+
+backportFooter = """
+»»»
+"""
+
+# Implementation of clpatch/undo.
+def clpatch_or_undo(ui, repo, clname, opts, mode):
+	if codereview_disabled:
+		return codereview_disabled
+
+	if mode == "undo" or mode == "backport":
+		# Find revision in Mercurial repository.
+		# Assume CL number is 7+ decimal digits.
+		# Otherwise is either change log sequence number (fewer decimal digits),
+		# hexadecimal hash, or tag name.
+		# Mercurial will fall over long before the change log
+		# sequence numbers get to be 7 digits long.
+		if re.match('^[0-9]{7,}$', clname):
+			found = False
+			for r in hg_log(ui, repo, keyword="codereview.appspot.com/"+clname, limit=100, template="{node}\n").split():
+				rev = repo[r]
+				# Last line with a code review URL is the actual review URL.
+				# Earlier ones might be part of the CL description.
+				n = rev2clname(rev)
+				if n == clname:
+					found = True
+					break
+			if not found:
+				return "cannot find CL %s in local repository" % clname
+		else:
+			rev = repo[clname]
+			if not rev:
+				return "unknown revision %s" % clname
+			clname = rev2clname(rev)
+			if clname == "":
+				return "cannot find CL name in revision description"
+		
+		# Create fresh CL and start with patch that would reverse the change.
+		vers = hg_node.short(rev.node())
+		cl = CL("new")
+		desc = str(rev.description())
+		if mode == "undo":
+			cl.desc = (undoHeader % (clname, vers)) + desc + undoFooter
+		else:
+			cl.desc = (backportHeader % (releaseBranch, line1(desc), clname, vers)) + desc + undoFooter
+		v1 = vers
+		v0 = hg_node.short(rev.parents()[0].node())
+		if mode == "undo":
+			arg = v1 + ":" + v0
+		else:
+			vers = v0
+			arg = v0 + ":" + v1
+		patch = RunShell(["hg", "diff", "--git", "-r", arg])
+
+	else:  # clpatch
+		cl, vers, patch, err = DownloadCL(ui, repo, clname)
+		if err != "":
+			return err
+		if patch == emptydiff:
+			return "codereview issue %s has no diff" % clname
+
+	# find current hg version (hg identify)
+	ctx = repo[None]
+	parents = ctx.parents()
+	id = '+'.join([hg_node.short(p.node()) for p in parents])
+
+	# if version does not match the patch version,
+	# try to update the patch line numbers.
+	if vers != "" and id != vers:
+		# "vers in repo" gives the wrong answer
+		# on some versions of Mercurial.  Instead, do the actual
+		# lookup and catch the exception.
+		try:
+			repo[vers].description()
+		except:
+			return "local repository is out of date; sync to get %s" % (vers)
+		patch1, err = portPatch(repo, patch, vers, id)
+		if err != "":
+			if not opts["ignore_hgapplydiff_failure"]:
+				return "codereview issue %s is out of date: %s (%s->%s)" % (clname, err, vers, id)
+		else:
+			patch = patch1
+	argv = ["hgapplydiff"]
+	if opts["no_incoming"] or mode == "backport":
+		argv += ["--checksync=false"]
+	try:
+		cmd = subprocess.Popen(argv, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None, close_fds=sys.platform != "win32")
+	except:
+		return "hgapplydiff: " + ExceptionDetail() + "\nInstall hgapplydiff with:\n$ go get code.google.com/p/go.codereview/cmd/hgapplydiff\n"
+
+	out, err = cmd.communicate(patch)
+	if cmd.returncode != 0 and not opts["ignore_hgapplydiff_failure"]:
+		return "hgapplydiff failed"
+	cl.local = True
+	cl.files = out.strip().split()
+	if not cl.files and not opts["ignore_hgapplydiff_failure"]:
+		return "codereview issue %s has no changed files" % clname
+	files = ChangedFiles(ui, repo, [])
+	extra = Sub(cl.files, files)
+	if extra:
+		ui.warn("warning: these files were listed in the patch but not changed:\n\t" + "\n\t".join(extra) + "\n")
+	cl.Flush(ui, repo)
+	if mode == "undo":
+		err = EditCL(ui, repo, cl)
+		if err != "":
+			return "CL created, but error editing: " + err
+		cl.Flush(ui, repo)
+	else:
+		ui.write(cl.PendingText() + "\n")
+
+# portPatch rewrites patch from being a patch against
+# oldver to being a patch against newver.
+def portPatch(repo, patch, oldver, newver):
+	lines = patch.splitlines(True) # True = keep \n
+	delta = None
+	for i in range(len(lines)):
+		line = lines[i]
+		if line.startswith('--- a/'):
+			file = line[6:-1]
+			delta = fileDeltas(repo, file, oldver, newver)
+		if not delta or not line.startswith('@@ '):
+			continue
+		# @@ -x,y +z,w @@ means the patch chunk replaces
+		# the original file's line numbers x up to x+y with the
+		# line numbers z up to z+w in the new file.
+		# Find the delta from x in the original to the same
+		# line in the current version and add that delta to both
+		# x and z.
+		m = re.match('@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@', line)
+		if not m:
+			return None, "error parsing patch line numbers"
+		n1, len1, n2, len2 = int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4))
+		d, err = lineDelta(delta, n1, len1)
+		if err != "":
+			return "", err
+		n1 += d
+		n2 += d
+		lines[i] = "@@ -%d,%d +%d,%d @@\n" % (n1, len1, n2, len2)
+		
+	newpatch = ''.join(lines)
+	return newpatch, ""
+
+# fileDelta returns the line number deltas for the given file's
+# changes from oldver to newver.
+# The deltas are a list of (n, len, newdelta) triples that say
+# lines [n, n+len) were modified, and after that range the
+# line numbers are +newdelta from what they were before.
+def fileDeltas(repo, file, oldver, newver):
+	cmd = ["hg", "diff", "--git", "-r", oldver + ":" + newver, "path:" + file]
+	data = RunShell(cmd, silent_ok=True)
+	deltas = []
+	for line in data.splitlines():
+		m = re.match('@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@', line)
+		if not m:
+			continue
+		n1, len1, n2, len2 = int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4))
+		deltas.append((n1, len1, n2+len2-(n1+len1)))
+	return deltas
+
+# lineDelta finds the appropriate line number delta to apply to the lines [n, n+len).
+# It returns an error if those lines were rewritten by the patch.
+def lineDelta(deltas, n, len):
+	d = 0
+	for (old, oldlen, newdelta) in deltas:
+		if old >= n+len:
+			break
+		if old+len > n:
+			return 0, "patch and recent changes conflict"
+		d = newdelta
+	return d, ""
+
+ at hgcommand
+def download(ui, repo, clname, **opts):
+	"""download a change from the code review server
+
+	Download prints a description of the given change list
+	followed by its diff, downloaded from the code review server.
+	"""
+	if codereview_disabled:
+		raise hg_util.Abort(codereview_disabled)
+
+	cl, vers, patch, err = DownloadCL(ui, repo, clname)
+	if err != "":
+		return err
+	ui.write(cl.EditorText() + "\n")
+	ui.write(patch + "\n")
+	return
+
+#######################################################################
+# hg file
+
+ at hgcommand
+def file(ui, repo, clname, pat, *pats, **opts):
+	"""assign files to or remove files from a change list
+
+	Assign files to or (with -d) remove files from a change list.
+
+	The -d option only removes files from the change list.
+	It does not edit them or remove them from the repository.
+	"""
+	if codereview_disabled:
+		raise hg_util.Abort(codereview_disabled)
+
+	pats = tuple([pat] + list(pats))
+	if not GoodCLName(clname):
+		return "invalid CL name " + clname
+
+	dirty = {}
+	cl, err = LoadCL(ui, repo, clname, web=False)
+	if err != '':
+		return err
+	if not cl.local:
+		return "cannot change non-local CL " + clname
+
+	files = ChangedFiles(ui, repo, pats)
+
+	if opts["delete"]:
+		oldfiles = Intersect(files, cl.files)
+		if oldfiles:
+			if not ui.quiet:
+				ui.status("# Removing files from CL.  To undo:\n")
+				ui.status("#	cd %s\n" % (repo.root))
+				for f in oldfiles:
+					ui.status("#	hg file %s %s\n" % (cl.name, f))
+			cl.files = Sub(cl.files, oldfiles)
+			cl.Flush(ui, repo)
+		else:
+			ui.status("no such files in CL")
+		return
+
+	if not files:
+		return "no such modified files"
+
+	files = Sub(files, cl.files)
+	taken = Taken(ui, repo)
+	warned = False
+	for f in files:
+		if f in taken:
+			if not warned and not ui.quiet:
+				ui.status("# Taking files from other CLs.  To undo:\n")
+				ui.status("#	cd %s\n" % (repo.root))
+				warned = True
+			ocl = taken[f]
+			if not ui.quiet:
+				ui.status("#	hg file %s %s\n" % (ocl.name, f))
+			if ocl not in dirty:
+				ocl.files = Sub(ocl.files, files)
+				dirty[ocl] = True
+	cl.files = Add(cl.files, files)
+	dirty[cl] = True
+	for d, _ in dirty.items():
+		d.Flush(ui, repo)
+	return
+
+#######################################################################
+# hg gofmt
+
+ at hgcommand
+def gofmt(ui, repo, *pats, **opts):
+	"""apply gofmt to modified files
+
+	Applies gofmt to the modified files in the repository that match
+	the given patterns.
+	"""
+	if codereview_disabled:
+		raise hg_util.Abort(codereview_disabled)
+
+	files = ChangedExistingFiles(ui, repo, pats, opts)
+	files = gofmt_required(files)
+	if not files:
+		return "no modified go files"
+	cwd = os.getcwd()
+	files = [RelativePath(repo.root + '/' + f, cwd) for f in files]
+	try:
+		cmd = ["gofmt", "-l"]
+		if not opts["list"]:
+			cmd += ["-w"]
+		if subprocess.call(cmd + files) != 0:
+			raise hg_util.Abort("gofmt did not exit cleanly")
+	except hg_error.Abort, e:
+		raise
+	except:
+		raise hg_util.Abort("gofmt: " + ExceptionDetail())
+	return
+
+def gofmt_required(files):
+	return [f for f in files if (not f.startswith('test/') or f.startswith('test/bench/')) and f.endswith('.go')]
+
+#######################################################################
+# hg mail
+
+ at hgcommand
+def mail(ui, repo, *pats, **opts):
+	"""mail a change for review
+
+	Uploads a patch to the code review server and then sends mail
+	to the reviewer and CC list asking for a review.
+	"""
+	if codereview_disabled:
+		raise hg_util.Abort(codereview_disabled)
+
+	cl, err = CommandLineCL(ui, repo, pats, opts, op="mail", defaultcc=defaultcc)
+	if err != "":
+		raise hg_util.Abort(err)
+	cl.Upload(ui, repo, gofmt_just_warn=True)
+	if not cl.reviewer:
+		# If no reviewer is listed, assign the review to defaultcc.
+		# This makes sure that it appears in the 
+		# codereview.appspot.com/user/defaultcc
+		# page, so that it doesn't get dropped on the floor.
+		if not defaultcc:
+			raise hg_util.Abort("no reviewers listed in CL")
+		cl.cc = Sub(cl.cc, defaultcc)
+		cl.reviewer = defaultcc
+		cl.Flush(ui, repo)
+
+	if cl.files == []:
+			raise hg_util.Abort("no changed files, not sending mail")
+
+	cl.Mail(ui, repo)
+
+#######################################################################
+# hg p / hg pq / hg ps / hg pending
+
+ at hgcommand
+def ps(ui, repo, *pats, **opts):
+	"""alias for hg p --short
+	"""
+	opts['short'] = True
+	return pending(ui, repo, *pats, **opts)
+
+ at hgcommand
+def pq(ui, repo, *pats, **opts):
+	"""alias for hg p --quick
+	"""
+	opts['quick'] = True
+	return pending(ui, repo, *pats, **opts)
+
+ at hgcommand
+def pending(ui, repo, *pats, **opts):
+	"""show pending changes
+
+	Lists pending changes followed by a list of unassigned but modified files.
+	"""
+	if codereview_disabled:
+		raise hg_util.Abort(codereview_disabled)
+
+	quick = opts.get('quick', False)
+	short = opts.get('short', False)
+	m = LoadAllCL(ui, repo, web=not quick and not short)
+	names = m.keys()
+	names.sort()
+	for name in names:
+		cl = m[name]
+		if short:
+			ui.write(name + "\t" + line1(cl.desc) + "\n")
+		else:
+			ui.write(cl.PendingText(quick=quick) + "\n")
+
+	if short:
+		return 0
+	files = DefaultFiles(ui, repo, [])
+	if len(files) > 0:
+		s = "Changed files not in any CL:\n"
+		for f in files:
+			s += "\t" + f + "\n"
+		ui.write(s)
+
+#######################################################################
+# hg submit
+
+def need_sync():
+	raise hg_util.Abort("local repository out of date; must sync before submit")
+
+ at hgcommand
+def submit(ui, repo, *pats, **opts):
+	"""submit change to remote repository
+
+	Submits change to remote repository.
+	Bails out if the local repository is not in sync with the remote one.
+	"""
+	if codereview_disabled:
+		raise hg_util.Abort(codereview_disabled)
+
+	# We already called this on startup but sometimes Mercurial forgets.
+	set_mercurial_encoding_to_utf8()
+
+	if not opts["no_incoming"] and hg_incoming(ui, repo):
+		need_sync()
+
+	cl, err = CommandLineCL(ui, repo, pats, opts, op="submit", defaultcc=defaultcc)
+	if err != "":
+		raise hg_util.Abort(err)
+
+	user = None
+	if cl.copied_from:
+		user = cl.copied_from
+	userline = CheckContributor(ui, repo, user)
+	typecheck(userline, str)
+
+	about = ""
+	if cl.reviewer:
+		about += "R=" + JoinComma([CutDomain(s) for s in cl.reviewer]) + "\n"
+	if opts.get('tbr'):
+		tbr = SplitCommaSpace(opts.get('tbr'))
+		cl.reviewer = Add(cl.reviewer, tbr)
+		about += "TBR=" + JoinComma([CutDomain(s) for s in tbr]) + "\n"
+	if cl.cc:
+		about += "CC=" + JoinComma([CutDomain(s) for s in cl.cc]) + "\n"
+
+	if not cl.reviewer:
+		raise hg_util.Abort("no reviewers listed in CL")
+
+	if not cl.local:
+		raise hg_util.Abort("cannot submit non-local CL")
+
+	# upload, to sync current patch and also get change number if CL is new.
+	if not cl.copied_from:
+		cl.Upload(ui, repo, gofmt_just_warn=True)
+
+	# check gofmt for real; allowed upload to warn in order to save CL.
+	cl.Flush(ui, repo)
+	CheckFormat(ui, repo, cl.files)
+
+	about += "%s%s\n" % (server_url_base, cl.name)
+
+	if cl.copied_from:
+		about += "\nCommitter: " + CheckContributor(ui, repo, None) + "\n"
+	typecheck(about, str)
+
+	if not cl.mailed and not cl.copied_from:		# in case this is TBR
+		cl.Mail(ui, repo)
+
+	# submit changes locally
+	message = cl.desc.rstrip() + "\n\n" + about
+	typecheck(message, str)
+
+	set_status("pushing " + cl.name + " to remote server")
+
+	if hg_outgoing(ui, repo):
+		raise hg_util.Abort("local repository corrupt or out-of-phase with remote: found outgoing changes")
+	
+	old_heads = len(hg_heads(ui, repo).split())
+
+	global commit_okay
+	commit_okay = True
+	ret = hg_commit(ui, repo, *['path:'+f for f in cl.files], message=message, user=userline)
+	commit_okay = False
+	if ret:
+		raise hg_util.Abort("nothing changed")
+	node = repo["-1"].node()
+	# push to remote; if it fails for any reason, roll back
+	try:
+		new_heads = len(hg_heads(ui, repo).split())
+		if old_heads != new_heads and not (old_heads == 0 and new_heads == 1):
+			# Created new head, so we weren't up to date.
+			need_sync()
+
+		# Push changes to remote.  If it works, we're committed.  If not, roll back.
+		try:
+			if hg_push(ui, repo):
+				raise hg_util.Abort("push error")
+		except hg_error.Abort, e:
+			if e.message.find("push creates new heads") >= 0:
+				# Remote repository had changes we missed.
+				need_sync()
+			raise
+	except:
+		real_rollback()
+		raise
+
+	# We're committed. Upload final patch, close review, add commit message.
+	changeURL = hg_node.short(node)
+	url = ui.expandpath("default")
+	m = re.match("(^https?://([^@/]+@)?([^.]+)\.googlecode\.com/hg/?)" + "|" +
+		"(^https?://([^@/]+@)?code\.google\.com/p/([^/.]+)(\.[^./]+)?/?)", url)
+	if m:
+		if m.group(1): # prj.googlecode.com/hg/ case
+			changeURL = "https://code.google.com/p/%s/source/detail?r=%s" % (m.group(3), changeURL)
+		elif m.group(4) and m.group(7): # code.google.com/p/prj.subrepo/ case
+			changeURL = "https://code.google.com/p/%s/source/detail?r=%s&repo=%s" % (m.group(6), changeURL, m.group(7)[1:])
+		elif m.group(4): # code.google.com/p/prj/ case
+			changeURL = "https://code.google.com/p/%s/source/detail?r=%s" % (m.group(6), changeURL)
+		else:
+			print >>sys.stderr, "URL: ", url
+	else:
+		print >>sys.stderr, "URL: ", url
+	pmsg = "*** Submitted as " + changeURL + " ***\n\n" + message
+
+	# When posting, move reviewers to CC line,
+	# so that the issue stops showing up in their "My Issues" page.
+	PostMessage(ui, cl.name, pmsg, reviewers="", cc=JoinComma(cl.reviewer+cl.cc))
+
+	if not cl.copied_from:
+		EditDesc(cl.name, closed=True, private=cl.private)
+	cl.Delete(ui, repo)
+
+	c = repo[None]
+	if c.branch() == releaseBranch and not c.modified() and not c.added() and not c.removed():
+		ui.write("switching from %s to default branch.\n" % releaseBranch)
+		err = hg_clean(repo, "default")
+		if err:
+			return err
+	return 0
+
+#######################################################################
+# hg sync
+
+ at hgcommand
+def sync(ui, repo, **opts):
+	"""synchronize with remote repository
+
+	Incorporates recent changes from the remote repository
+	into the local repository.
+	"""
+	if codereview_disabled:
+		raise hg_util.Abort(codereview_disabled)
+
+	if not opts["local"]:
+		err = hg_pull(ui, repo, update=True)
+		if err:
+			return err
+	sync_changes(ui, repo)
+
+def sync_changes(ui, repo):
+	# Look through recent change log descriptions to find
+	# potential references to http://.*/our-CL-number.
+	# Double-check them by looking at the Rietveld log.
+	for rev in hg_log(ui, repo, limit=100, template="{node}\n").split():
+		desc = repo[rev].description().strip()
+		for clname in re.findall('(?m)^https?://(?:[^\n]+)/([0-9]+)$', desc):
+			if IsLocalCL(ui, repo, clname) and IsRietveldSubmitted(ui, clname, repo[rev].hex()):
+				ui.warn("CL %s submitted as %s; closing\n" % (clname, repo[rev]))
+				cl, err = LoadCL(ui, repo, clname, web=False)
+				if err != "":
+					ui.warn("loading CL %s: %s\n" % (clname, err))
+					continue
+				if not cl.copied_from:
+					EditDesc(cl.name, closed=True, private=cl.private)
+				cl.Delete(ui, repo)
+
+	# Remove files that are not modified from the CLs in which they appear.
+	all = LoadAllCL(ui, repo, web=False)
+	changed = ChangedFiles(ui, repo, [])
+	for cl in all.values():
+		extra = Sub(cl.files, changed)
+		if extra:
+			ui.warn("Removing unmodified files from CL %s:\n" % (cl.name,))
+			for f in extra:
+				ui.warn("\t%s\n" % (f,))
+			cl.files = Sub(cl.files, extra)
+			cl.Flush(ui, repo)
+		if not cl.files:
+			if not cl.copied_from:
+				ui.warn("CL %s has no files; delete (abandon) with hg change -d %s\n" % (cl.name, cl.name))
+			else:
+				ui.warn("CL %s has no files; delete locally with hg change -D %s\n" % (cl.name, cl.name))
+	return 0
+
+#######################################################################
+# hg upload
+
+ at hgcommand
+def upload(ui, repo, name, **opts):
+	"""upload diffs to the code review server
+
+	Uploads the current modifications for a given change to the server.
+	"""
+	if codereview_disabled:
+		raise hg_util.Abort(codereview_disabled)
+
+	repo.ui.quiet = True
+	cl, err = LoadCL(ui, repo, name, web=True)
+	if err != "":
+		raise hg_util.Abort(err)
+	if not cl.local:
+		raise hg_util.Abort("cannot upload non-local change")
+	cl.Upload(ui, repo)
+	print "%s%s\n" % (server_url_base, cl.name)
+	return 0
+
+#######################################################################
+# Table of commands, supplied to Mercurial for installation.
+
+review_opts = [
+	('r', 'reviewer', '', 'add reviewer'),
+	('', 'cc', '', 'add cc'),
+	('', 'tbr', '', 'add future reviewer'),
+	('m', 'message', '', 'change description (for new change)'),
+]
+
+cmdtable = {
+	# The ^ means to show this command in the help text that
+	# is printed when running hg with no arguments.
+	"^change": (
+		change,
+		[
+			('d', 'delete', None, 'delete existing change list'),
+			('D', 'deletelocal', None, 'delete locally, but do not change CL on server'),
+			('i', 'stdin', None, 'read change list from standard input'),
+			('o', 'stdout', None, 'print change list to standard output'),
+			('p', 'pending', None, 'print pending summary to standard output'),
+		],
+		"[-d | -D] [-i] [-o] change# or FILE ..."
+	),
+	"^clpatch": (
+		clpatch,
+		[
+			('', 'ignore_hgapplydiff_failure', None, 'create CL metadata even if hgapplydiff fails'),
+			('', 'no_incoming', None, 'disable check for incoming changes'),
+		],
+		"change#"
+	),
+	# Would prefer to call this codereview-login, but then
+	# hg help codereview prints the help for this command
+	# instead of the help for the extension.
+	"code-login": (
+		code_login,
+		[],
+		"",
+	),
+	"^download": (
+		download,
+		[],
+		"change#"
+	),
+	"^file": (
+		file,
+		[
+			('d', 'delete', None, 'delete files from change list (but not repository)'),
+		],
+		"[-d] change# FILE ..."
+	),
+	"^gofmt": (
+		gofmt,
+		[
+			('l', 'list', None, 'list files that would change, but do not edit them'),
+		],
+		"FILE ..."
+	),
+	"^pending|p": (
+		pending,
+		[
+			('s', 'short', False, 'show short result form'),
+			('', 'quick', False, 'do not consult codereview server'),
+		],
+		"[FILE ...]"
+	),
+	"^ps": (
+		ps,
+		[],
+		"[FILE ...]"
+	),
+	"^pq": (
+		pq,
+		[],
+		"[FILE ...]"
+	),
+	"^mail": (
+		mail,
+		review_opts + [
+		] + hg_commands.walkopts,
+		"[-r reviewer] [--cc cc] [change# | file ...]"
+	),
+	"^release-apply": (
+		release_apply,
+		[
+			('', 'ignore_hgapplydiff_failure', None, 'create CL metadata even if hgapplydiff fails'),
+			('', 'no_incoming', None, 'disable check for incoming changes'),
+		],
+		"change#"
+	),
+	# TODO: release-start, release-tag, weekly-tag
+	"^submit": (
+		submit,
+		review_opts + [
+			('', 'no_incoming', None, 'disable initial incoming check (for testing)'),
+		] + hg_commands.walkopts + hg_commands.commitopts + hg_commands.commitopts2,
+		"[-r reviewer] [--cc cc] [change# | file ...]"
+	),
+	"^sync": (
+		sync,
+		[
+			('', 'local', None, 'do not pull changes from remote repository')
+		],
+		"[--local]",
+	),
+	"^undo": (
+		undo,
+		[
+			('', 'ignore_hgapplydiff_failure', None, 'create CL metadata even if hgapplydiff fails'),
+			('', 'no_incoming', None, 'disable check for incoming changes'),
+		],
+		"change#"
+	),
+	"^upload": (
+		upload,
+		[],
+		"change#"
+	),
+}
+
+#######################################################################
+# Mercurial extension initialization
+
+def norollback(*pats, **opts):
+	"""(disabled when using this extension)"""
+	raise hg_util.Abort("codereview extension enabled; use undo instead of rollback")
+
+codereview_init = False
+
+def reposetup(ui, repo):
+	global codereview_disabled
+	global defaultcc
+	
+	# reposetup gets called both for the local repository
+	# and also for any repository we are pulling or pushing to.
+	# Only initialize the first time.
+	global codereview_init
+	if codereview_init:
+		return
+	codereview_init = True
+
+	# Read repository-specific options from lib/codereview/codereview.cfg or codereview.cfg.
+	root = ''
+	try:
+		root = repo.root
+	except:
+		# Yes, repo might not have root; see issue 959.
+		codereview_disabled = 'codereview disabled: repository has no root'
+		return
+	
+	repo_config_path = ''
+	p1 = root + '/lib/codereview/codereview.cfg'
+	p2 = root + '/codereview.cfg'
+	if os.access(p1, os.F_OK):
+		repo_config_path = p1
+	else:
+		repo_config_path = p2
+	try:
+		f = open(repo_config_path)
+		for line in f:
+			if line.startswith('defaultcc:'):
+				defaultcc = SplitCommaSpace(line[len('defaultcc:'):])
+			if line.startswith('contributors:'):
+				global contributorsURL
+				contributorsURL = line[len('contributors:'):].strip()
+	except:
+		codereview_disabled = 'codereview disabled: cannot open ' + repo_config_path
+		return
+
+	remote = ui.config("paths", "default", "")
+	if remote.find("://") < 0:
+		raise hg_util.Abort("codereview: default path '%s' is not a URL" % (remote,))
+
+	InstallMatch(ui, repo)
+	RietveldSetup(ui, repo)
+
+	# Disable the Mercurial commands that might change the repository.
+	# Only commands in this extension are supposed to do that.
+	ui.setconfig("hooks", "precommit.codereview", precommithook)
+
+	# Rollback removes an existing commit.  Don't do that either.
+	global real_rollback
+	real_rollback = repo.rollback
+	repo.rollback = norollback
+	
+
+#######################################################################
+# Wrappers around upload.py for interacting with Rietveld
+
+from HTMLParser import HTMLParser
+
+# HTML form parser
+class FormParser(HTMLParser):
+	def __init__(self):
+		self.map = {}
+		self.curtag = None
+		self.curdata = None
+		HTMLParser.__init__(self)
+	def handle_starttag(self, tag, attrs):
+		if tag == "input":
+			key = None
+			value = ''
+			for a in attrs:
+				if a[0] == 'name':
+					key = a[1]
+				if a[0] == 'value':
+					value = a[1]
+			if key is not None:
+				self.map[key] = value
+		if tag == "textarea":
+			key = None
+			for a in attrs:
+				if a[0] == 'name':
+					key = a[1]
+			if key is not None:
+				self.curtag = key
+				self.curdata = ''
+	def handle_endtag(self, tag):
+		if tag == "textarea" and self.curtag is not None:
+			self.map[self.curtag] = self.curdata
+			self.curtag = None
+			self.curdata = None
+	def handle_charref(self, name):
+		self.handle_data(unichr(int(name)))
+	def handle_entityref(self, name):
+		import htmlentitydefs
+		if name in htmlentitydefs.entitydefs:
+			self.handle_data(htmlentitydefs.entitydefs[name])
+		else:
+			self.handle_data("&" + name + ";")
+	def handle_data(self, data):
+		if self.curdata is not None:
+			self.curdata += data
+
+def JSONGet(ui, path):
+	try:
+		data = MySend(path, force_auth=False)
+		typecheck(data, str)
+		d = fix_json(json.loads(data))
+	except:
+		ui.warn("JSONGet %s: %s\n" % (path, ExceptionDetail()))
+		return None
+	return d
+
+# Clean up json parser output to match our expectations:
+#   * all strings are UTF-8-encoded str, not unicode.
+#   * missing fields are missing, not None,
+#     so that d.get("foo", defaultvalue) works.
+def fix_json(x):
+	if type(x) in [str, int, float, bool, type(None)]:
+		pass
+	elif type(x) is unicode:
+		x = x.encode("utf-8")
+	elif type(x) is list:
+		for i in range(len(x)):
+			x[i] = fix_json(x[i])
+	elif type(x) is dict:
+		todel = []
+		for k in x:
+			if x[k] is None:
+				todel.append(k)
+			else:
+				x[k] = fix_json(x[k])
+		for k in todel:
+			del x[k]
+	else:
+		raise hg_util.Abort("unknown type " + str(type(x)) + " in fix_json")
+	if type(x) is str:
+		x = x.replace('\r\n', '\n')
+	return x
+
+def IsRietveldSubmitted(ui, clname, hex):
+	dict = JSONGet(ui, "/api/" + clname + "?messages=true")
+	if dict is None:
+		return False
+	for msg in dict.get("messages", []):
+		text = msg.get("text", "")
+		m = re.match('\*\*\* Submitted as [^*]*?([0-9a-f]+) \*\*\*', text)
+		if m is not None and len(m.group(1)) >= 8 and hex.startswith(m.group(1)):
+			return True
+	return False
+
+def IsRietveldMailed(cl):
+	for msg in cl.dict.get("messages", []):
+		if msg.get("text", "").find("I'd like you to review this change") >= 0:
+			return True
+	return False
+
+def DownloadCL(ui, repo, clname):
+	set_status("downloading CL " + clname)
+	cl, err = LoadCL(ui, repo, clname, web=True)
+	if err != "":
+		return None, None, None, "error loading CL %s: %s" % (clname, err)
+
+	# Find most recent diff
+	diffs = cl.dict.get("patchsets", [])
+	if not diffs:
+		return None, None, None, "CL has no patch sets"
+	patchid = diffs[-1]
+
+	patchset = JSONGet(ui, "/api/" + clname + "/" + str(patchid))
+	if patchset is None:
+		return None, None, None, "error loading CL patchset %s/%d" % (clname, patchid)
+	if patchset.get("patchset", 0) != patchid:
+		return None, None, None, "malformed patchset information"
+	
+	vers = ""
+	msg = patchset.get("message", "").split()
+	if len(msg) >= 3 and msg[0] == "diff" and msg[1] == "-r":
+		vers = msg[2]
+	diff = "/download/issue" + clname + "_" + str(patchid) + ".diff"
+
+	diffdata = MySend(diff, force_auth=False)
+	
+	# Print warning if email is not in CONTRIBUTORS file.
+	email = cl.dict.get("owner_email", "")
+	if not email:
+		return None, None, None, "cannot find owner for %s" % (clname)
+	him = FindContributor(ui, repo, email)
+	me = FindContributor(ui, repo, None)
+	if him == me:
+		cl.mailed = IsRietveldMailed(cl)
+	else:
+		cl.copied_from = email
+
+	return cl, vers, diffdata, ""
+
+def MySend(request_path, payload=None,
+		content_type="application/octet-stream",
+		timeout=None, force_auth=True,
+		**kwargs):
+	"""Run MySend1 maybe twice, because Rietveld is unreliable."""
+	try:
+		return MySend1(request_path, payload, content_type, timeout, force_auth, **kwargs)
+	except Exception, e:
+		if type(e) != urllib2.HTTPError or e.code != 500:	# only retry on HTTP 500 error
+			raise
+		print >>sys.stderr, "Loading "+request_path+": "+ExceptionDetail()+"; trying again in 2 seconds."
+		time.sleep(2)
+		return MySend1(request_path, payload, content_type, timeout, force_auth, **kwargs)
+
+# Like upload.py Send but only authenticates when the
+# redirect is to www.google.com/accounts.  This keeps
+# unnecessary redirects from happening during testing.
+def MySend1(request_path, payload=None,
+				content_type="application/octet-stream",
+				timeout=None, force_auth=True,
+				**kwargs):
+	"""Sends an RPC and returns the response.
+
+	Args:
+		request_path: The path to send the request to, eg /api/appversion/create.
+		payload: The body of the request, or None to send an empty request.
+		content_type: The Content-Type header to use.
+		timeout: timeout in seconds; default None i.e. no timeout.
+			(Note: for large requests on OS X, the timeout doesn't work right.)
+		kwargs: Any keyword arguments are converted into query string parameters.
+
+	Returns:
+		The response body, as a string.
+	"""
+	# TODO: Don't require authentication.  Let the server say
+	# whether it is necessary.
+	global rpc
+	if rpc == None:
+		rpc = GetRpcServer(upload_options)
+	self = rpc
+	if not self.authenticated and force_auth:
+		self._Authenticate()
+	if request_path is None:
+		return
+	if timeout is None:
+		timeout = 30 # seconds
+
+	old_timeout = socket.getdefaulttimeout()
+	socket.setdefaulttimeout(timeout)
+	try:
+		tries = 0
+		while True:
+			tries += 1
+			args = dict(kwargs)
+			url = "https://%s%s" % (self.host, request_path)
+			if args:
+				url += "?" + urllib.urlencode(args)
+			req = self._CreateRequest(url=url, data=payload)
+			req.add_header("Content-Type", content_type)
+			try:
+				f = self.opener.open(req)
+				response = f.read()
+				f.close()
+				# Translate \r\n into \n, because Rietveld doesn't.
+				response = response.replace('\r\n', '\n')
+				# who knows what urllib will give us
+				if type(response) == unicode:
+					response = response.encode("utf-8")
+				typecheck(response, str)
+				return response
+			except urllib2.HTTPError, e:
+				if tries > 3:
+					raise
+				elif e.code == 401:
+					self._Authenticate()
+				elif e.code == 302:
+					loc = e.info()["location"]
+					if not loc.startswith('https://www.google.com/a') or loc.find('/ServiceLogin') < 0:
+						return ''
+					self._Authenticate()
+				else:
+					raise
+	finally:
+		socket.setdefaulttimeout(old_timeout)
+
+def GetForm(url):
+	f = FormParser()
+	f.feed(ustr(MySend(url)))	# f.feed wants unicode
+	f.close()
+	# convert back to utf-8 to restore sanity
+	m = {}
+	for k,v in f.map.items():
+		m[k.encode("utf-8")] = v.replace("\r\n", "\n").encode("utf-8")
+	return m
+
+def EditDesc(issue, subject=None, desc=None, reviewers=None, cc=None, closed=False, private=False):
+	set_status("uploading change to description")
+	form_fields = GetForm("/" + issue + "/edit")
+	if subject is not None:
+		form_fields['subject'] = subject
+	if desc is not None:
+		form_fields['description'] = desc
+	if reviewers is not None:
+		form_fields['reviewers'] = reviewers
+	if cc is not None:
+		form_fields['cc'] = cc
+	if closed:
+		form_fields['closed'] = "checked"
+	if private:
+		form_fields['private'] = "checked"
+	ctype, body = EncodeMultipartFormData(form_fields.items(), [])
+	response = MySend("/" + issue + "/edit", body, content_type=ctype)
+	if response != "":
+		print >>sys.stderr, "Error editing description:\n" + "Sent form: \n", form_fields, "\n", response
+		sys.exit(2)
+
+def PostMessage(ui, issue, message, reviewers=None, cc=None, send_mail=True, subject=None):
+	set_status("uploading message")
+	form_fields = GetForm("/" + issue + "/publish")
+	if reviewers is not None:
+		form_fields['reviewers'] = reviewers
+	if cc is not None:
+		form_fields['cc'] = cc
+	if send_mail:
+		form_fields['send_mail'] = "checked"
+	else:
+		del form_fields['send_mail']
+	if subject is not None:
+		form_fields['subject'] = subject
+	form_fields['message'] = message
+	
+	form_fields['message_only'] = '1'	# Don't include draft comments
+	if reviewers is not None or cc is not None:
+		form_fields['message_only'] = ''	# Must set '' in order to override cc/reviewer
+	ctype = "applications/x-www-form-urlencoded"
+	body = urllib.urlencode(form_fields)
+	response = MySend("/" + issue + "/publish", body, content_type=ctype)
+	if response != "":
+		print response
+		sys.exit(2)
+
+class opt(object):
+	pass
+
+def RietveldSetup(ui, repo):
+	global force_google_account
+	global rpc
+	global server
+	global server_url_base
+	global upload_options
+	global verbosity
+
+	if not ui.verbose:
+		verbosity = 0
+
+	# Config options.
+	x = ui.config("codereview", "server")
+	if x is not None:
+		server = x
+
+	# TODO(rsc): Take from ui.username?
+	email = None
+	x = ui.config("codereview", "email")
+	if x is not None:
+		email = x
+
+	server_url_base = "https://" + server + "/"
+
+	testing = ui.config("codereview", "testing")
+	force_google_account = ui.configbool("codereview", "force_google_account", False)
+
+	upload_options = opt()
+	upload_options.email = email
+	upload_options.host = None
+	upload_options.verbose = 0
+	upload_options.description = None
+	upload_options.description_file = None
+	upload_options.reviewers = None
+	upload_options.cc = None
+	upload_options.message = None
+	upload_options.issue = None
+	upload_options.download_base = False
+	upload_options.revision = None
+	upload_options.send_mail = False
+	upload_options.vcs = None
+	upload_options.server = server
+	upload_options.save_cookies = True
+
+	if testing:
+		upload_options.save_cookies = False
+		upload_options.email = "test at example.com"
+
+	rpc = None
+	
+	global releaseBranch
+	tags = repo.branchtags().keys()
+	if 'release-branch.go10' in tags:
+		# NOTE(rsc): This tags.sort is going to get the wrong
+		# answer when comparing release-branch.go9 with
+		# release-branch.go10.  It will be a while before we care.
+		raise hg_util.Abort('tags.sort needs to be fixed for release-branch.go10')
+	tags.sort()
+	for t in tags:
+		if t.startswith('release-branch.go'):
+			releaseBranch = t			
+
+#######################################################################
+# http://codereview.appspot.com/static/upload.py, heavily edited.
+
+#!/usr/bin/env python
+#
+# Copyright 2007 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#	http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Tool for uploading diffs from a version control system to the codereview app.
+
+Usage summary: upload.py [options] [-- diff_options]
+
+Diff options are passed to the diff command of the underlying system.
+
+Supported version control systems:
+	Git
+	Mercurial
+	Subversion
+
+It is important for Git/Mercurial users to specify a tree/node/branch to diff
+against by using the '--rev' option.
+"""
+# This code is derived from appcfg.py in the App Engine SDK (open source),
+# and from ASPN recipe #146306.
+
+import cookielib
+import getpass
+import logging
+import mimetypes
+import optparse
+import os
+import re
+import socket
+import subprocess
+import sys
+import urllib
+import urllib2
+import urlparse
+
+# The md5 module was deprecated in Python 2.5.
+try:
+	from hashlib import md5
+except ImportError:
+	from md5 import md5
+
+try:
+	import readline
+except ImportError:
+	pass
+
+# The logging verbosity:
+#  0: Errors only.
+#  1: Status messages.
+#  2: Info logs.
+#  3: Debug logs.
+verbosity = 1
+
+# Max size of patch or base file.
+MAX_UPLOAD_SIZE = 900 * 1024
+
+# whitelist for non-binary filetypes which do not start with "text/"
+# .mm (Objective-C) shows up as application/x-freemind on my Linux box.
+TEXT_MIMETYPES = [
+	'application/javascript',
+	'application/x-javascript',
+	'application/x-freemind'
+]
+
+def GetEmail(prompt):
+	"""Prompts the user for their email address and returns it.
+
+	The last used email address is saved to a file and offered up as a suggestion
+	to the user. If the user presses enter without typing in anything the last
+	used email address is used. If the user enters a new address, it is saved
+	for next time we prompt.
+
+	"""
+	last_email_file_name = os.path.expanduser("~/.last_codereview_email_address")
+	last_email = ""
+	if os.path.exists(last_email_file_name):
+		try:
+			last_email_file = open(last_email_file_name, "r")
+			last_email = last_email_file.readline().strip("\n")
+			last_email_file.close()
+			prompt += " [%s]" % last_email
+		except IOError, e:
+			pass
+	email = raw_input(prompt + ": ").strip()
+	if email:
+		try:
+			last_email_file = open(last_email_file_name, "w")
+			last_email_file.write(email)
+			last_email_file.close()
+		except IOError, e:
+			pass
+	else:
+		email = last_email
+	return email
+
+
+def StatusUpdate(msg):
+	"""Print a status message to stdout.
+
+	If 'verbosity' is greater than 0, print the message.
+
+	Args:
+		msg: The string to print.
+	"""
+	if verbosity > 0:
+		print msg
+
+
+def ErrorExit(msg):
+	"""Print an error message to stderr and exit."""
+	print >>sys.stderr, msg
+	sys.exit(1)
+
+
+class ClientLoginError(urllib2.HTTPError):
+	"""Raised to indicate there was an error authenticating with ClientLogin."""
+
+	def __init__(self, url, code, msg, headers, args):
+		urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
+		self.args = args
+		# .reason is now a read-only property based on .msg
+		# this means we ignore 'msg', but that seems to work fine.
+		self.msg = args["Error"] 
+
+
+class AbstractRpcServer(object):
+	"""Provides a common interface for a simple RPC server."""
+
+	def __init__(self, host, auth_function, host_override=None, extra_headers={}, save_cookies=False):
+		"""Creates a new HttpRpcServer.
+
+		Args:
+			host: The host to send requests to.
+			auth_function: A function that takes no arguments and returns an
+				(email, password) tuple when called. Will be called if authentication
+				is required.
+			host_override: The host header to send to the server (defaults to host).
+			extra_headers: A dict of extra headers to append to every request.
+			save_cookies: If True, save the authentication cookies to local disk.
+				If False, use an in-memory cookiejar instead.  Subclasses must
+				implement this functionality.  Defaults to False.
+		"""
+		self.host = host
+		self.host_override = host_override
+		self.auth_function = auth_function
+		self.authenticated = False
+		self.extra_headers = extra_headers
+		self.save_cookies = save_cookies
+		self.opener = self._GetOpener()
+		if self.host_override:
+			logging.info("Server: %s; Host: %s", self.host, self.host_override)
+		else:
+			logging.info("Server: %s", self.host)
+
+	def _GetOpener(self):
+		"""Returns an OpenerDirector for making HTTP requests.
+
+		Returns:
+			A urllib2.OpenerDirector object.
+		"""
+		raise NotImplementedError()
+
+	def _CreateRequest(self, url, data=None):
+		"""Creates a new urllib request."""
+		logging.debug("Creating request for: '%s' with payload:\n%s", url, data)
+		req = urllib2.Request(url, data=data)
+		if self.host_override:
+			req.add_header("Host", self.host_override)
+		for key, value in self.extra_headers.iteritems():
+			req.add_header(key, value)
+		return req
+
+	def _GetAuthToken(self, email, password):
+		"""Uses ClientLogin to authenticate the user, returning an auth token.
+
+		Args:
+			email:    The user's email address
+			password: The user's password
+
+		Raises:
+			ClientLoginError: If there was an error authenticating with ClientLogin.
+			HTTPError: If there was some other form of HTTP error.
+
+		Returns:
+			The authentication token returned by ClientLogin.
+		"""
+		account_type = "GOOGLE"
+		if self.host.endswith(".google.com") and not force_google_account:
+			# Needed for use inside Google.
+			account_type = "HOSTED"
+		req = self._CreateRequest(
+				url="https://www.google.com/accounts/ClientLogin",
+				data=urllib.urlencode({
+						"Email": email,
+						"Passwd": password,
+						"service": "ah",
+						"source": "rietveld-codereview-upload",
+						"accountType": account_type,
+				}),
+		)
+		try:
+			response = self.opener.open(req)
+			response_body = response.read()
+			response_dict = dict(x.split("=") for x in response_body.split("\n") if x)
+			return response_dict["Auth"]
+		except urllib2.HTTPError, e:
+			if e.code == 403:
+				body = e.read()
+				response_dict = dict(x.split("=", 1) for x in body.split("\n") if x)
+				raise ClientLoginError(req.get_full_url(), e.code, e.msg, e.headers, response_dict)
+			else:
+				raise
+
+	def _GetAuthCookie(self, auth_token):
+		"""Fetches authentication cookies for an authentication token.
+
+		Args:
+			auth_token: The authentication token returned by ClientLogin.
+
+		Raises:
+			HTTPError: If there was an error fetching the authentication cookies.
+		"""
+		# This is a dummy value to allow us to identify when we're successful.
+		continue_location = "http://localhost/"
+		args = {"continue": continue_location, "auth": auth_token}
+		req = self._CreateRequest("https://%s/_ah/login?%s" % (self.host, urllib.urlencode(args)))
+		try:
+			response = self.opener.open(req)
+		except urllib2.HTTPError, e:
+			response = e
+		if (response.code != 302 or
+				response.info()["location"] != continue_location):
+			raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg, response.headers, response.fp)
+		self.authenticated = True
+
+	def _Authenticate(self):
+		"""Authenticates the user.
+
+		The authentication process works as follows:
+		1) We get a username and password from the user
+		2) We use ClientLogin to obtain an AUTH token for the user
+				(see http://code.google.com/apis/accounts/AuthForInstalledApps.html).
+		3) We pass the auth token to /_ah/login on the server to obtain an
+				authentication cookie. If login was successful, it tries to redirect
+				us to the URL we provided.
+
+		If we attempt to access the upload API without first obtaining an
+		authentication cookie, it returns a 401 response (or a 302) and
+		directs us to authenticate ourselves with ClientLogin.
+		"""
+		for i in range(3):
+			credentials = self.auth_function()
+			try:
+				auth_token = self._GetAuthToken(credentials[0], credentials[1])
+			except ClientLoginError, e:
+				if e.msg == "BadAuthentication":
+					print >>sys.stderr, "Invalid username or password."
+					continue
+				if e.msg == "CaptchaRequired":
+					print >>sys.stderr, (
+						"Please go to\n"
+						"https://www.google.com/accounts/DisplayUnlockCaptcha\n"
+						"and verify you are a human.  Then try again.")
+					break
+				if e.msg == "NotVerified":
+					print >>sys.stderr, "Account not verified."
+					break
+				if e.msg == "TermsNotAgreed":
+					print >>sys.stderr, "User has not agreed to TOS."
+					break
+				if e.msg == "AccountDeleted":
+					print >>sys.stderr, "The user account has been deleted."
+					break
+				if e.msg == "AccountDisabled":
+					print >>sys.stderr, "The user account has been disabled."
+					break
+				if e.msg == "ServiceDisabled":
+					print >>sys.stderr, "The user's access to the service has been disabled."
+					break
+				if e.msg == "ServiceUnavailable":
+					print >>sys.stderr, "The service is not available; try again later."
+					break
+				raise
+			self._GetAuthCookie(auth_token)
+			return
+
+	def Send(self, request_path, payload=None,
+					content_type="application/octet-stream",
+					timeout=None,
+					**kwargs):
+		"""Sends an RPC and returns the response.
+
+		Args:
+			request_path: The path to send the request to, eg /api/appversion/create.
+			payload: The body of the request, or None to send an empty request.
+			content_type: The Content-Type header to use.
+			timeout: timeout in seconds; default None i.e. no timeout.
+				(Note: for large requests on OS X, the timeout doesn't work right.)
+			kwargs: Any keyword arguments are converted into query string parameters.
+
+		Returns:
+			The response body, as a string.
+		"""
+		# TODO: Don't require authentication.  Let the server say
+		# whether it is necessary.
+		if not self.authenticated:
+			self._Authenticate()
+
+		old_timeout = socket.getdefaulttimeout()
+		socket.setdefaulttimeout(timeout)
+		try:
+			tries = 0
+			while True:
+				tries += 1
+				args = dict(kwargs)
+				url = "https://%s%s" % (self.host, request_path)
+				if args:
+					url += "?" + urllib.urlencode(args)
+				req = self._CreateRequest(url=url, data=payload)
+				req.add_header("Content-Type", content_type)
+				try:
+					f = self.opener.open(req)
+					response = f.read()
+					f.close()
+					return response
+				except urllib2.HTTPError, e:
+					if tries > 3:
+						raise
+					elif e.code == 401 or e.code == 302:
+						self._Authenticate()
+					else:
+						raise
+		finally:
+			socket.setdefaulttimeout(old_timeout)
+
+
+class HttpRpcServer(AbstractRpcServer):
+	"""Provides a simplified RPC-style interface for HTTP requests."""
+
+	def _Authenticate(self):
+		"""Save the cookie jar after authentication."""
+		super(HttpRpcServer, self)._Authenticate()
+		if self.save_cookies:
+			StatusUpdate("Saving authentication cookies to %s" % self.cookie_file)
+			self.cookie_jar.save()
+
+	def _GetOpener(self):
+		"""Returns an OpenerDirector that supports cookies and ignores redirects.
+
+		Returns:
+			A urllib2.OpenerDirector object.
+		"""
+		opener = urllib2.OpenerDirector()
+		opener.add_handler(urllib2.ProxyHandler())
+		opener.add_handler(urllib2.UnknownHandler())
+		opener.add_handler(urllib2.HTTPHandler())
+		opener.add_handler(urllib2.HTTPDefaultErrorHandler())
+		opener.add_handler(urllib2.HTTPSHandler())
+		opener.add_handler(urllib2.HTTPErrorProcessor())
+		if self.save_cookies:
+			self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies_" + server)
+			self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file)
+			if os.path.exists(self.cookie_file):
+				try:
+					self.cookie_jar.load()
+					self.authenticated = True
+					StatusUpdate("Loaded authentication cookies from %s" % self.cookie_file)
+				except (cookielib.LoadError, IOError):
+					# Failed to load cookies - just ignore them.
+					pass
+			else:
+				# Create an empty cookie file with mode 600
+				fd = os.open(self.cookie_file, os.O_CREAT, 0600)
+				os.close(fd)
+			# Always chmod the cookie file
+			os.chmod(self.cookie_file, 0600)
+		else:
+			# Don't save cookies across runs of update.py.
+			self.cookie_jar = cookielib.CookieJar()
+		opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar))
+		return opener
+
+
+def GetRpcServer(options):
+	"""Returns an instance of an AbstractRpcServer.
+
+	Returns:
+		A new AbstractRpcServer, on which RPC calls can be made.
+	"""
+
+	rpc_server_class = HttpRpcServer
+
+	def GetUserCredentials():
+		"""Prompts the user for a username and password."""
+		# Disable status prints so they don't obscure the password prompt.
+		global global_status
+		st = global_status
+		global_status = None
+
+		email = options.email
+		if email is None:
+			email = GetEmail("Email (login for uploading to %s)" % options.server)
+		password = getpass.getpass("Password for %s: " % email)
+
+		# Put status back.
+		global_status = st
+		return (email, password)
+
+	# If this is the dev_appserver, use fake authentication.
+	host = (options.host or options.server).lower()
+	if host == "localhost" or host.startswith("localhost:"):
+		email = options.email
+		if email is None:
+			email = "test at example.com"
+			logging.info("Using debug user %s.  Override with --email" % email)
+		server = rpc_server_class(
+				options.server,
+				lambda: (email, "password"),
+				host_override=options.host,
+				extra_headers={"Cookie": 'dev_appserver_login="%s:False"' % email},
+				save_cookies=options.save_cookies)
+		# Don't try to talk to ClientLogin.
+		server.authenticated = True
+		return server
+
+	return rpc_server_class(options.server, GetUserCredentials,
+		host_override=options.host, save_cookies=options.save_cookies)
+
+
+def EncodeMultipartFormData(fields, files):
+	"""Encode form fields for multipart/form-data.
+
+	Args:
+		fields: A sequence of (name, value) elements for regular form fields.
+		files: A sequence of (name, filename, value) elements for data to be
+					uploaded as files.
+	Returns:
+		(content_type, body) ready for httplib.HTTP instance.
+
+	Source:
+		http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
+	"""
+	BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
+	CRLF = '\r\n'
+	lines = []
+	for (key, value) in fields:
+		typecheck(key, str)
+		typecheck(value, str)
+		lines.append('--' + BOUNDARY)
+		lines.append('Content-Disposition: form-data; name="%s"' % key)
+		lines.append('')
+		lines.append(value)
+	for (key, filename, value) in files:
+		typecheck(key, str)
+		typecheck(filename, str)
+		typecheck(value, str)
+		lines.append('--' + BOUNDARY)
+		lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
+		lines.append('Content-Type: %s' % GetContentType(filename))
+		lines.append('')
+		lines.append(value)
+	lines.append('--' + BOUNDARY + '--')
+	lines.append('')
+	body = CRLF.join(lines)
+	content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
+	return content_type, body
+
+
+def GetContentType(filename):
+	"""Helper to guess the content-type from the filename."""
+	return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
+
+
+# Use a shell for subcommands on Windows to get a PATH search.
+use_shell = sys.platform.startswith("win")
+
+def RunShellWithReturnCode(command, print_output=False,
+		universal_newlines=True, env=os.environ):
+	"""Executes a command and returns the output from stdout and the return code.
+
+	Args:
+		command: Command to execute.
+		print_output: If True, the output is printed to stdout.
+			If False, both stdout and stderr are ignored.
+		universal_newlines: Use universal_newlines flag (default: True).
+
+	Returns:
+		Tuple (output, return code)
+	"""
+	logging.info("Running %s", command)
+	p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+		shell=use_shell, universal_newlines=universal_newlines, env=env)
+	if print_output:
+		output_array = []
+		while True:
+			line = p.stdout.readline()
+			if not line:
+				break
+			print line.strip("\n")
+			output_array.append(line)
+		output = "".join(output_array)
+	else:
+		output = p.stdout.read()
+	p.wait()
+	errout = p.stderr.read()
+	if print_output and errout:
+		print >>sys.stderr, errout
+	p.stdout.close()
+	p.stderr.close()
+	return output, p.returncode
+
+
+def RunShell(command, silent_ok=False, universal_newlines=True,
+		print_output=False, env=os.environ):
+	data, retcode = RunShellWithReturnCode(command, print_output, universal_newlines, env)
+	if retcode:
+		ErrorExit("Got error status from %s:\n%s" % (command, data))
+	if not silent_ok and not data:
+		ErrorExit("No output from %s" % command)
+	return data
+
+
+class VersionControlSystem(object):
+	"""Abstract base class providing an interface to the VCS."""
+
+	def __init__(self, options):
+		"""Constructor.
+
+		Args:
+			options: Command line options.
+		"""
+		self.options = options
+
+	def GenerateDiff(self, args):
+		"""Return the current diff as a string.
+
+		Args:
+			args: Extra arguments to pass to the diff command.
+		"""
+		raise NotImplementedError(
+				"abstract method -- subclass %s must override" % self.__class__)
+
+	def GetUnknownFiles(self):
+		"""Return a list of files unknown to the VCS."""
+		raise NotImplementedError(
+				"abstract method -- subclass %s must override" % self.__class__)
+
+	def CheckForUnknownFiles(self):
+		"""Show an "are you sure?" prompt if there are unknown files."""
+		unknown_files = self.GetUnknownFiles()
+		if unknown_files:
+			print "The following files are not added to version control:"
+			for line in unknown_files:
+				print line
+			prompt = "Are you sure to continue?(y/N) "
+			answer = raw_input(prompt).strip()
+			if answer != "y":
+				ErrorExit("User aborted")
+
+	def GetBaseFile(self, filename):
+		"""Get the content of the upstream version of a file.
+
+		Returns:
+			A tuple (base_content, new_content, is_binary, status)
+				base_content: The contents of the base file.
+				new_content: For text files, this is empty.  For binary files, this is
+					the contents of the new file, since the diff output won't contain
+					information to reconstruct the current file.
+				is_binary: True iff the file is binary.
+				status: The status of the file.
+		"""
+
+		raise NotImplementedError(
+				"abstract method -- subclass %s must override" % self.__class__)
+
+
+	def GetBaseFiles(self, diff):
+		"""Helper that calls GetBase file for each file in the patch.
+
+		Returns:
+			A dictionary that maps from filename to GetBaseFile's tuple.  Filenames
+			are retrieved based on lines that start with "Index:" or
+			"Property changes on:".
+		"""
+		files = {}
+		for line in diff.splitlines(True):
+			if line.startswith('Index:') or line.startswith('Property changes on:'):
+				unused, filename = line.split(':', 1)
+				# On Windows if a file has property changes its filename uses '\'
+				# instead of '/'.
+				filename = to_slash(filename.strip())
+				files[filename] = self.GetBaseFile(filename)
+		return files
+
+
+	def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options,
+											files):
+		"""Uploads the base files (and if necessary, the current ones as well)."""
+
+		def UploadFile(filename, file_id, content, is_binary, status, is_base):
+			"""Uploads a file to the server."""
+			set_status("uploading " + filename)
+			file_too_large = False
+			if is_base:
+				type = "base"
+			else:
+				type = "current"
+			if len(content) > MAX_UPLOAD_SIZE:
+				print ("Not uploading the %s file for %s because it's too large." %
+							(type, filename))
+				file_too_large = True
+				content = ""
+			checksum = md5(content).hexdigest()
+			if options.verbose > 0 and not file_too_large:
+				print "Uploading %s file for %s" % (type, filename)
+			url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id)
+			form_fields = [
+				("filename", filename),
+				("status", status),
+				("checksum", checksum),
+				("is_binary", str(is_binary)),
+				("is_current", str(not is_base)),
+			]
+			if file_too_large:
+				form_fields.append(("file_too_large", "1"))
+			if options.email:
+				form_fields.append(("user", options.email))
+			ctype, body = EncodeMultipartFormData(form_fields, [("data", filename, content)])
+			response_body = rpc_server.Send(url, body, content_type=ctype)
+			if not response_body.startswith("OK"):
+				StatusUpdate("  --> %s" % response_body)
+				sys.exit(1)
+
+		# Don't want to spawn too many threads, nor do we want to
+		# hit Rietveld too hard, or it will start serving 500 errors.
+		# When 8 works, it's no better than 4, and sometimes 8 is
+		# too many for Rietveld to handle.
+		MAX_PARALLEL_UPLOADS = 4
+
+		sema = threading.BoundedSemaphore(MAX_PARALLEL_UPLOADS)
+		upload_threads = []
+		finished_upload_threads = []
+		
+		class UploadFileThread(threading.Thread):
+			def __init__(self, args):
+				threading.Thread.__init__(self)
+				self.args = args
+			def run(self):
+				UploadFile(*self.args)
+				finished_upload_threads.append(self)
+				sema.release()
+
+		def StartUploadFile(*args):
+			sema.acquire()
+			while len(finished_upload_threads) > 0:
+				t = finished_upload_threads.pop()
+				upload_threads.remove(t)
+				t.join()
+			t = UploadFileThread(args)
+			upload_threads.append(t)
+			t.start()
+
+		def WaitForUploads():			
+			for t in upload_threads:
+				t.join()
+
+		patches = dict()
+		[patches.setdefault(v, k) for k, v in patch_list]
+		for filename in patches.keys():
+			base_content, new_content, is_binary, status = files[filename]
+			file_id_str = patches.get(filename)
+			if file_id_str.find("nobase") != -1:
+				base_content = None
+				file_id_str = file_id_str[file_id_str.rfind("_") + 1:]
+			file_id = int(file_id_str)
+			if base_content != None:
+				StartUploadFile(filename, file_id, base_content, is_binary, status, True)
+			if new_content != None:
+				StartUploadFile(filename, file_id, new_content, is_binary, status, False)
+		WaitForUploads()
+
+	def IsImage(self, filename):
+		"""Returns true if the filename has an image extension."""
+		mimetype =  mimetypes.guess_type(filename)[0]
+		if not mimetype:
+			return False
+		return mimetype.startswith("image/")
+
+	def IsBinary(self, filename):
+		"""Returns true if the guessed mimetyped isnt't in text group."""
+		mimetype = mimetypes.guess_type(filename)[0]
+		if not mimetype:
+			return False  # e.g. README, "real" binaries usually have an extension
+		# special case for text files which don't start with text/
+		if mimetype in TEXT_MIMETYPES:
+			return False
+		return not mimetype.startswith("text/")
+
+
+class FakeMercurialUI(object):
+	def __init__(self):
+		self.quiet = True
+		self.output = ''
+	
+	def write(self, *args, **opts):
+		self.output += ' '.join(args)
+	def copy(self):
+		return self
+	def status(self, *args, **opts):
+		pass
+
+	def formatter(self, topic, opts):
+		from mercurial.formatter import plainformatter
+		return plainformatter(self, topic, opts)
+	
+	def readconfig(self, *args, **opts):
+		pass
+	def expandpath(self, *args, **opts):
+		return global_ui.expandpath(*args, **opts)
+	def configitems(self, *args, **opts):
+		return global_ui.configitems(*args, **opts)
+	def config(self, *args, **opts):
+		return global_ui.config(*args, **opts)
+
+use_hg_shell = False	# set to True to shell out to hg always; slower
+
+class MercurialVCS(VersionControlSystem):
+	"""Implementation of the VersionControlSystem interface for Mercurial."""
+
+	def __init__(self, options, ui, repo):
+		super(MercurialVCS, self).__init__(options)
+		self.ui = ui
+		self.repo = repo
+		self.status = None
+		# Absolute path to repository (we can be in a subdir)
+		self.repo_dir = os.path.normpath(repo.root)
+		# Compute the subdir
+		cwd = os.path.normpath(os.getcwd())
+		assert cwd.startswith(self.repo_dir)
+		self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/")
+		if self.options.revision:
+			self.base_rev = self.options.revision
+		else:
+			mqparent, err = RunShellWithReturnCode(['hg', 'log', '--rev', 'qparent', '--template={node}'])
+			if not err and mqparent != "":
+				self.base_rev = mqparent
+			else:
+				out = RunShell(["hg", "parents", "-q"], silent_ok=True).strip()
+				if not out:
+					# No revisions; use 0 to mean a repository with nothing.
+					out = "0:0"
+				self.base_rev = out.split(':')[1].strip()
+	def _GetRelPath(self, filename):
+		"""Get relative path of a file according to the current directory,
+		given its logical path in the repo."""
+		assert filename.startswith(self.subdir), (filename, self.subdir)
+		return filename[len(self.subdir):].lstrip(r"\/")
+
+	def GenerateDiff(self, extra_args):
+		# If no file specified, restrict to the current subdir
+		extra_args = extra_args or ["."]
+		cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args
+		data = RunShell(cmd, silent_ok=True)
+		svndiff = []
+		filecount = 0
+		for line in data.splitlines():
+			m = re.match("diff --git a/(\S+) b/(\S+)", line)
+			if m:
+				# Modify line to make it look like as it comes from svn diff.
+				# With this modification no changes on the server side are required
+				# to make upload.py work with Mercurial repos.
+				# NOTE: for proper handling of moved/copied files, we have to use
+				# the second filename.
+				filename = m.group(2)
+				svndiff.append("Index: %s" % filename)
+				svndiff.append("=" * 67)
+				filecount += 1
+				logging.info(line)
+			else:
+				svndiff.append(line)
+		if not filecount:
+			ErrorExit("No valid patches found in output from hg diff")
+		return "\n".join(svndiff) + "\n"
+
+	def GetUnknownFiles(self):
+		"""Return a list of files unknown to the VCS."""
+		args = []
+		status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."],
+				silent_ok=True)
+		unknown_files = []
+		for line in status.splitlines():
+			st, fn = line.split(" ", 1)
+			if st == "?":
+				unknown_files.append(fn)
+		return unknown_files
+
+	def get_hg_status(self, rev, path):
+		# We'd like to use 'hg status -C path', but that is buggy
+		# (see http://mercurial.selenic.com/bts/issue3023).
+		# Instead, run 'hg status -C' without a path
+		# and skim the output for the path we want.
+		if self.status is None:
+			if use_hg_shell:
+				out = RunShell(["hg", "status", "-C", "--rev", rev])
+			else:
+				fui = FakeMercurialUI()
+				ret = hg_commands.status(fui, self.repo, *[], **{'rev': [rev], 'copies': True})
+				if ret:
+					raise hg_util.Abort(ret)
+				out = fui.output
+			self.status = out.splitlines()
+		for i in range(len(self.status)):
+			# line is
+			#	A path
+			#	M path
+			# etc
+			line = to_slash(self.status[i])
+			if line[2:] == path:
+				if i+1 < len(self.status) and self.status[i+1][:2] == '  ':
+					return self.status[i:i+2]
+				return self.status[i:i+1]
+		raise hg_util.Abort("no status for " + path)
+	
+	def GetBaseFile(self, filename):
+		set_status("inspecting " + filename)
+		# "hg status" and "hg cat" both take a path relative to the current subdir
+		# rather than to the repo root, but "hg diff" has given us the full path
+		# to the repo root.
+		base_content = ""
+		new_content = None
+		is_binary = False
+		oldrelpath = relpath = self._GetRelPath(filename)
+		out = self.get_hg_status(self.base_rev, relpath)
+		status, what = out[0].split(' ', 1)
+		if len(out) > 1 and status == "A" and what == relpath:
+			oldrelpath = out[1].strip()
+			status = "M"
+		if ":" in self.base_rev:
+			base_rev = self.base_rev.split(":", 1)[0]
+		else:
+			base_rev = self.base_rev
+		if status != "A":
+			if use_hg_shell:
+				base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], silent_ok=True)
+			else:
+				base_content = str(self.repo[base_rev][oldrelpath].data())
+			is_binary = "\0" in base_content  # Mercurial's heuristic
+		if status != "R":
+			new_content = open(relpath, "rb").read()
+			is_binary = is_binary or "\0" in new_content
+		if is_binary and base_content and use_hg_shell:
+			# Fetch again without converting newlines
+			base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath],
+				silent_ok=True, universal_newlines=False)
+		if not is_binary or not self.IsImage(relpath):
+			new_content = None
+		return base_content, new_content, is_binary, status
+
+
+# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync.
+def SplitPatch(data):
+	"""Splits a patch into separate pieces for each file.
+
+	Args:
+		data: A string containing the output of svn diff.
+
+	Returns:
+		A list of 2-tuple (filename, text) where text is the svn diff output
+			pertaining to filename.
+	"""
+	patches = []
+	filename = None
+	diff = []
+	for line in data.splitlines(True):
+		new_filename = None
+		if line.startswith('Index:'):
+			unused, new_filename = line.split(':', 1)
+			new_filename = new_filename.strip()
+		elif line.startswith('Property changes on:'):
+			unused, temp_filename = line.split(':', 1)
+			# When a file is modified, paths use '/' between directories, however
+			# when a property is modified '\' is used on Windows.  Make them the same
+			# otherwise the file shows up twice.
+			temp_filename = to_slash(temp_filename.strip())
+			if temp_filename != filename:
+				# File has property changes but no modifications, create a new diff.
+				new_filename = temp_filename
+		if new_filename:
+			if filename and diff:
+				patches.append((filename, ''.join(diff)))
+			filename = new_filename
+			diff = [line]
+			continue
+		if diff is not None:
+			diff.append(line)
+	if filename and diff:
+		patches.append((filename, ''.join(diff)))
+	return patches
+
+
+def UploadSeparatePatches(issue, rpc_server, patchset, data, options):
+	"""Uploads a separate patch for each file in the diff output.
+
+	Returns a list of [patch_key, filename] for each file.
+	"""
+	patches = SplitPatch(data)
+	rv = []
+	for patch in patches:
+		set_status("uploading patch for " + patch[0])
+		if len(patch[1]) > MAX_UPLOAD_SIZE:
+			print ("Not uploading the patch for " + patch[0] +
+				" because the file is too large.")
+			continue
+		form_fields = [("filename", patch[0])]
+		if not options.download_base:
+			form_fields.append(("content_upload", "1"))
+		files = [("data", "data.diff", patch[1])]
+		ctype, body = EncodeMultipartFormData(form_fields, files)
+		url = "/%d/upload_patch/%d" % (int(issue), int(patchset))
+		print "Uploading patch for " + patch[0]
+		response_body = rpc_server.Send(url, body, content_type=ctype)
+		lines = response_body.splitlines()
+		if not lines or lines[0] != "OK":
+			StatusUpdate("  --> %s" % response_body)
+			sys.exit(1)
+		rv.append([lines[1], patch[0]])
+	return rv
diff --git a/lib/codereview/test.sh b/lib/codereview/test.sh
new file mode 100755
index 0000000..13f2b9c
--- /dev/null
+++ b/lib/codereview/test.sh
@@ -0,0 +1,198 @@
+#!/bin/bash
+# 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.
+
+# Test the code review plugin.
+# Assumes a local Rietveld is running using the App Engine SDK
+# at http://localhost:7777/
+#
+# dev_appserver.py -p 7777 $HOME/pub/rietveld
+
+codereview_script=$(pwd)/codereview.py
+server=localhost:7777
+master=/tmp/go.test
+clone1=/tmp/go.test1
+clone2=/tmp/go.test2
+export HGEDITOR=true
+
+must() {
+	if ! "$@"; then
+		echo "$@" failed >&2
+		exit 1
+	fi
+}
+
+not() {
+	if "$@"; then
+		false
+	else
+		true
+	fi
+}
+
+status() {
+	echo '+++' "$@" >&2
+}
+
+firstcl() {
+	hg pending | sed 1q | tr -d ':'
+}
+
+# Initial setup.
+status Create repositories.
+rm -rf $master $clone1 $clone2
+mkdir $master
+cd $master
+must hg init .
+echo Initial state >file
+must hg add file
+must hg ci -m 'first commit' file
+must hg clone $master $clone1
+must hg clone $master $clone2
+
+echo "
+[ui]
+username=Grace R Emlin <gre at golang.org>
+[extensions]
+codereview=$codereview_script
+[codereview]
+server=$server
+" >>$clone1/.hg/hgrc
+cp $clone1/.hg/hgrc $clone2/.hg/hgrc
+
+status Codereview should be disabled.
+cd $clone1
+must hg status
+must not hg pending
+
+status Enabling code review.
+must mkdir lib lib/codereview
+must touch lib/codereview/codereview.cfg
+
+status Code review should work even without CONTRIBUTORS.
+must hg pending
+
+status Add CONTRIBUTORS.
+echo 'Grace R Emlin <gre at golang.org>' >CONTRIBUTORS
+must hg add lib/codereview/codereview.cfg CONTRIBUTORS
+
+status First submit.
+must hg submit -r gre at golang.org -m codereview \
+	lib/codereview/codereview.cfg CONTRIBUTORS
+
+status Should see change in other client.
+cd $clone2
+must hg pull -u
+must test -f lib/codereview/codereview.cfg
+must test -f CONTRIBUTORS
+
+test_clpatch() {
+	# The email address must be test at example.com to match
+	# the test code review server's default user.
+	# Clpatch will check.
+	
+	cd $clone1
+	# Tried to use UTF-8 here to test that, but dev_appserver.py crashes.  Ha ha.
+	if false; then
+		status Using UTF-8.
+		name="Grácè T Emlïn <test at example.com>"
+	else
+		status Using ASCII.
+		name="Grace T Emlin <test at example.com>"
+	fi
+	echo "$name" >>CONTRIBUTORS
+	cat .hg/hgrc | sed "s/Grace.*/$name/" >/tmp/x && mv /tmp/x .hg/hgrc
+	echo '
+Reviewer: gre at golang.org
+Description:
+	CONTRIBUTORS: add $name
+Files:
+	CONTRIBUTORS
+'	| must hg change -i
+	num=$(hg pending | sed 1q | tr -d :)
+	
+	status Patch CL.
+	cd $clone2
+	must hg clpatch $num
+	must [ "$num" = "$(firstcl)" ]
+	must hg submit $num
+	
+	status Issue should be open with no reviewers.
+	must curl http://$server/api/$num >/tmp/x
+	must not grep '"closed":true' /tmp/x
+	must grep '"reviewers":\[\]' /tmp/x
+	
+	status Sync should close issue.
+	cd $clone1
+	must hg sync
+	must curl http://$server/api/$num >/tmp/x
+	must grep '"closed":true' /tmp/x
+	must grep '"reviewers":\[\]' /tmp/x
+	must [ "$(firstcl)" = "" ]
+}
+
+test_reviewer() {
+	status Submit without reviewer should fail.
+	cd $clone1
+	echo dummy >dummy
+	must hg add dummy
+	echo '
+Description:
+	no reviewer
+Files:
+	dummy
+'	| must hg change -i
+	num=$(firstcl)
+	must not hg submit $num
+	must hg revert dummy
+	must rm dummy
+	must hg change -d $num
+}
+
+test_linearity() {
+	status Linearity of changes.
+	cd $clone1
+	echo file1 >file1
+	must hg add file1
+	echo '
+Reviewer: gre at golang.org
+Description: file1
+Files: file1
+	' | must hg change -i
+	must hg submit $(firstcl)
+	
+	cd $clone2
+	echo file2 >file2
+	must hg add file2
+	echo '
+Reviewer: gre at golang.org
+Description: file2
+Files: file2
+	' | must hg change -i
+	must not hg submit $(firstcl)
+	must hg sync
+	must hg submit $(firstcl)
+}
+
+test_restrict() {
+	status Cannot use hg ci.
+	cd $clone1
+	echo file1a >file1a
+	hg add file1a
+	must not hg ci -m commit file1a
+	must rm file1a
+	must hg revert file1a
+	
+	status Cannot use hg rollback.
+	must not hg rollback
+	
+	status Cannot use hg backout
+	must not hg backout -r -1
+}
+
+test_reviewer
+test_clpatch
+test_linearity
+test_restrict
+status ALL TESTS PASSED.
diff --git a/lib/godoc/codewalk.html b/lib/godoc/codewalk.html
index 2835c6e..313f1f6 100644
--- a/lib/godoc/codewalk.html
+++ b/lib/godoc/codewalk.html
@@ -4,8 +4,6 @@
 	license that can be found in the LICENSE file.
 -->
 
-<script src="http://www.google.com/jsapi"></script>
-<script>google.load("jquery", "1.3.2");</script>
 <style type='text/css'>@import "/doc/codewalk/codewalk.css";</style>
 <script type="text/javascript" src="/doc/codewalk/codewalk.js"></script>
 
diff --git a/lib/godoc/example.html b/lib/godoc/example.html
index ede31d6..cda2a84 100644
--- a/lib/godoc/example.html
+++ b/lib/godoc/example.html
@@ -5,11 +5,24 @@
 	<div class="expanded">
 		<p class="exampleHeading toggleButton">▾ <span class="text">Example{{example_suffix .Name}}</span></p>
 		{{with .Doc}}<p>{{html .}}</p>{{end}}
-		<p>Code:</p>
-		<pre class="code">{{.Code}}</pre>
-		{{with .Output}}
-		<p>Output:</p>
-		<pre class="output">{{html .}}</pre>
+		{{$output := .Output}}
+		{{with .Play}}
+			<div class="play">
+				<div class="input"><textarea class="code">{{html .}}</textarea></div>
+				<div class="output"><pre>{{html $output}}</pre></div>
+				<div class="buttons">
+					<a class="run" title="Run this code [shift-enter]">Run</a>
+					<a class="fmt" title="Format this code">Format</a>
+					<a class="share" title="Share this code">Share</a>
+				</div>
+			</div>
+		{{else}}
+			<p>Code:</p>
+			<pre class="code">{{.Code}}</pre>
+			{{with .Output}}
+			<p>Output:</p>
+			<pre class="output">{{html .}}</pre>
+			{{end}}
 		{{end}}
 	</div>
 </div>
diff --git a/lib/godoc/godoc.html b/lib/godoc/godoc.html
index fd60329..b7a772c 100644
--- a/lib/godoc/godoc.html
+++ b/lib/godoc/godoc.html
@@ -8,6 +8,11 @@
   <title>The Go Programming Language</title>
 {{end}}
 <link type="text/css" rel="stylesheet" href="/doc/style.css">
+<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
+<script type="text/javascript">window.jQuery || document.write(unescape("%3Cscript src='/doc/jquery.js' type='text/javascript'%3E%3C/script%3E"));</script>
+{{if .Playground}}
+<script type="text/javascript" src="/doc/play/playground.js"></script>
+{{end}}
 <script type="text/javascript" src="/doc/godocs.js"></script>
 {{if .SearchBox}}
 <link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
@@ -15,7 +20,7 @@
 </head>
 <body>
 
-<div id="topbar"><div class="container{{if .Title}} wide{{end}}">
+<div id="topbar"{{if .Title}} class="wide"{{end}}><div class="container">
 
 <form method="GET" action="/search">
 <div id="menu">
@@ -24,14 +29,36 @@
 <a href="/pkg/">Packages</a>
 <a href="/project/">The Project</a>
 <a href="/help/">Help</a>
-<input type="text" id="search" name="q" class="inactive" value="Search">
+{{if .Playground}}
+<a id="playgroundButton" href="http://play.golang.org/" title="Show Go Playground">Play</a>
+{{end}}
+<input type="text" id="search" name="q" class="inactive" value="Search" placeholder="Search">
 </div>
 <div id="heading"><a href="/">The Go Programming Language</a></div>
 </form>
 
 </div></div>
 
+{{if .Playground}}
+<div id="playground" class="play">
+	<div class="input"><textarea class="code">package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, 世界")
+}</textarea></div>
+	<div class="output"></div>
+	<div class="buttons">
+		<a class="run" title="Run this code [shift-enter]">Run</a>
+		<a class="fmt" title="Format this code">Format</a>
+		<a class="share" title="Share this code">Share</a>
+	</div>
+</div>
+{{end}}
+
 <div id="page"{{if .Title}} class="wide"{{end}}>
+<div class="container">
 
 {{with .Title}}
   <div id="plusone"><g:plusone size="small" annotation="none"></g:plusone></div>
@@ -45,10 +72,8 @@
      Do not delete this <div>. */}}
 <div id="nav"></div>
 
-{{/* Content is HTML-escaped elsewhere */}}
-{{printf "%s" .Content}}
-
-</div>
+{{/* Body is HTML-escaped elsewhere */}}
+{{printf "%s" .Body}}
 
 <div id="footer">
 Build version {{html .Version}}.<br>
@@ -57,9 +82,12 @@ the content of this page is licensed under the
 Creative Commons Attribution 3.0 License,
 and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
 <a href="/doc/tos.html">Terms of Service</a> | 
-<a href="http://www.google.com/intl/en/privacy/privacy-policy.html">Privacy Policy</a>
+<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
 </div>
 
+</div><!-- .container -->
+</div><!-- #page -->
+
 </body>
 <script type="text/javascript">
   (function() {
diff --git a/lib/godoc/package.html b/lib/godoc/package.html
index 5b7fce8..1df1f91 100644
--- a/lib/godoc/package.html
+++ b/lib/godoc/package.html
@@ -3,25 +3,31 @@
 	Use of this source code is governed by a BSD-style
 	license that can be found in the LICENSE file.
 -->
+<!--
+	Note: Static (i.e., not template-generated) href and id
+	attributes start with "pkg-" to make it impossible for
+	them to conflict with generated attributes (some of which
+	correspond to Go identifiers).
+-->
 {{with .PDoc}}
-	{{if $.IsPkg}}
+	{{if not $.IsMain}}
 		<div id="short-nav">
 			<dl>
 			<dd><code>import "{{html .ImportPath}}"</code></dd>
 			</dl>
 			<dl>
-			<dd><a href="#overview" class="overviewLink">Overview</a></dd>
-			<dd><a href="#index">Index</a></dd>
+			<dd><a href="#pkg-overview" class="overviewLink">Overview</a></dd>
+			<dd><a href="#pkg-index" class="indexLink">Index</a></dd>
 			{{if $.Examples}}
-				<dd><a href="#examples">Examples</a></dd>
+				<dd><a href="#pkg-examples" class="examplesLink">Examples</a></dd>
 			{{end}}
 			{{if $.Dirs}}
-				<dd><a href="#subdirectories">Subdirectories</a></dd>
+				<dd><a href="#pkg-subdirectories">Subdirectories</a></dd>
 			{{end}}
 			</dl>
 		</div>
 		<!-- The package's Name is printed as title by the top-level template -->
-		<div id="overview" class="toggleVisible">
+		<div id="pkg-overview" class="toggleVisible">
 			<div class="collapsed">
 				<h2 class="toggleButton" title="Click to show Overview section">Overview ▹</h2>
 			</div>
@@ -31,16 +37,22 @@
 			</div>
 		</div>
 		{{example_html "" $.Examples $.FSet}}
-	
-		<h2 id="index">Index</h2>
+
+		<div id="pkg-index" class="toggleVisible">
+		<div class="collapsed">
+			<h2 class="toggleButton" title="Click to show Index section">Index ▹</h2>
+		</div>
+		<div class="expanded">
+			<h2 class="toggleButton" title="Click to hide Index section">Index ▾</h2>
+
 		<!-- Table of contents for API; must be named manual-nav to turn off auto nav. -->
-		<div id="manual-nav">
+			<div id="manual-nav">
 			<dl>
 			{{if .Consts}}
-				<dd><a href="#constants">Constants</a></dd>
+				<dd><a href="#pkg-constants">Constants</a></dd>
 			{{end}}
 			{{if .Vars}}
-				<dd><a href="#variables">Variables</a></dd>
+				<dd><a href="#pkg-variables">Variables</a></dd>
 			{{end}}
 			{{range .Funcs}}
 				{{$name_html := html .Name}}
@@ -58,20 +70,25 @@
 					<dd>    <a href="#{{$tname_html}}.{{$name_html}}">{{node_html .Decl $.FSet}}</a></dd>
 				{{end}}
 			{{end}}
-			{{if .Bugs}}
-				<dd><a href="#bugs">Bugs</a></dd>
+			{{if $.Notes}}
+                                {{range $marker, $item := $.Notes}}
+				<dd><a href="#pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</a></dd>
+                                {{end}}
 			{{end}}
-		</dl>
+			</dl>
+			</div><!-- #manual-nav -->
 
 		{{if $.Examples}}
-			<h4 id="examples">Examples</h4>
+		<div id="pkg-examples">
+			<h4>Examples</h4>
 			<dl>
 			{{range $.Examples}}
 			<dd><a class="exampleLink" href="#example_{{.Name}}">{{example_name .Name}}</a></dd>
 			{{end}}
 			</dl>
+		</div>
 		{{end}}
-
+	
 		{{with .Filenames}}
 			<h4>Package files</h4>
 			<p>
@@ -82,16 +99,18 @@
 			</span>
 			</p>
 		{{end}}
+		</div><!-- .expanded -->
+		</div><!-- #pkg-index -->
 	
 		{{with .Consts}}
-			<h2 id="constants">Constants</h2>
+			<h2 id="pkg-constants">Constants</h2>
 			{{range .}}
 				<pre>{{node_html .Decl $.FSet}}</pre>
 				{{comment_html .Doc}}
 			{{end}}
 		{{end}}
 		{{with .Vars}}
-			<h2 id="variables">Variables</h2>
+			<h2 id="pkg-variables">Variables</h2>
 			{{range .}}
 				<pre>{{node_html .Decl $.FSet}}</pre>
 				{{comment_html .Doc}}
@@ -141,15 +160,16 @@
 				{{example_html $name $.Examples $.FSet}}
 			{{end}}
 		{{end}}
-		</div>
 	{{else}}  {{/* not a package; is a command */}}
 		{{comment_html .Doc}}
 	{{end}}
 
-	{{with .Bugs}}
-		<h2 id="bugs">Bugs</h2>
-		{{range .}}
-		{{comment_html .}}
+	{{with $.Notes}}
+                {{range $marker, $content := .}}
+		    <h2 id="pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</h2>
+		    {{range .}}
+		    {{comment_html .}}
+                    {{end}}
 		{{end}}
 	{{end}}
 {{end}}
@@ -158,20 +178,10 @@
 	<pre>{{node_html . $.FSet}}</pre>
 {{end}}
 
-{{with .PList}}
-	<h2>Other packages</h2>
-	<p>
-	{{/* PList entries are strings - no need for FSet */}}
-	{{range .}}
-	<a href="?p={{urlquery .}}">{{html .}}</a><br />
-	{{end}}
-	</p>
-{{end}}
-
 {{with .Dirs}}
 	{{/* DirList entries are numbers and strings - no need for FSet */}}
 	{{if $.PDoc}}
-		<h2 id="subdirectories">Subdirectories</h2>
+		<h2 id="pkg-subdirectories">Subdirectories</h2>
 	{{else}}
 		<div class="pkgGopher">
 			<img class="gopher" src="/doc/gopher/pkg.png"/>
@@ -192,14 +202,14 @@
 		{{if $.DirFlat}}
 			{{if .HasPkg}}
 				<tr>
-				<td class="name"><a href="{{html .Path}}">{{html .Path}}</a></td>
+				<td class="name"><a href="{{html .Path}}/">{{html .Path}}</a></td>
 				<td>    </td>
 				<td style="width: auto">{{html .Synopsis}}</td>
 				</tr>
 			{{end}}
 		{{else}}
 			<tr>
-			<td class="name">{{repeat `     ` .Depth}}<a href="{{html .Path}}">{{html .Name}}</a></td>
+			<td class="name">{{repeat `     ` .Depth}}<a href="{{html .Path}}/">{{html .Name}}</a></td>
 			<td>    </td>
 			<td style="width: auto">{{html .Synopsis}}</td>
 			</tr>
@@ -207,6 +217,47 @@
 	{{end}}
 	</table>
 	{{if $.PDoc}}{{else}}
-	<p>Need more packages? Take a look at the <a href="http://godashboard.appspot.com/">Go Project Dashboard</a>.</p>
+	<p>Need more packages? Take a look at the <a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Projects wiki page</a>.</p>
 	{{end}}
 {{end}}
+
+{{if $.Examples}}
+<script>
+$(document).ready(function() {
+	'use strict';
+	// Set up playground when each element is toggled.
+	$('div.play').each(function (i, el) {
+		var built = false;
+		$(el).closest('.toggle').click(function() {
+			// Only set up playground once.
+			if (built) {
+				return;
+			}
+			built = true;
+
+			// Set up playground.
+			var code = $('.code', el);
+			playground({
+				'codeEl':   code,
+				'outputEl': $('.output', el),
+				'runEl':    $('.run', el),
+				'fmtEl':    $('.fmt', el),
+				'shareEl':  $('.share', el),
+				'shareRedirect': 'http://play.golang.org/p/'
+			});
+
+			// Make the code textarea resize to fit content.
+			var resize = function() {
+				code.height(0);
+				var h = code[0].scrollHeight;
+				code.height(h+20); // minimize bouncing
+				code.closest('.input').height(h);
+			};
+			code.on('keydown', resize);
+			code.on('keyup', resize);
+			code.keyup(); // resize now.
+		});
+	});
+});
+</script>
+{{end}}
diff --git a/lib/godoc/package.txt b/lib/godoc/package.txt
index 3f3c396..94239ca 100644
--- a/lib/godoc/package.txt
+++ b/lib/godoc/package.txt
@@ -2,14 +2,15 @@
 
 ---------------------------------------
 
-*/}}{{with .PDoc}}{{if $.IsPkg}}PACKAGE
+*/}}{{with .PDoc}}{{if not $.IsMain}}PACKAGE
 
 package {{.Name}}
     import "{{.ImportPath}}"
 
 {{else}}COMMAND DOCUMENTATION
 
-{{end}}{{comment_text .Doc "    " "\t"}}{{/*
+{{end}}{{comment_text .Doc "    " "\t"}}
+{{example_text "" $.Examples $.FSet "    "}}{{/*
 
 ---------------------------------------
 
@@ -36,6 +37,7 @@ FUNCTIONS
 
 {{range .}}{{node .Decl $.FSet}}
 {{comment_text .Doc "    " "\t"}}
+{{example_text .Name $.Examples $.FSet "    "}}
 {{end}}{{end}}{{/*
 
 ---------------------------------------
@@ -43,34 +45,29 @@ FUNCTIONS
 */}}{{with .Types}}
 TYPES
 
-{{range .}}{{node .Decl $.FSet}}
+{{range .}}{{$tname := .Name}}{{node .Decl $.FSet}}
 {{comment_text .Doc "    " "\t"}}
 {{range .Consts}}{{node .Decl $.FSet}}
 {{comment_text .Doc "    " "\t"}}
 {{end}}{{range .Vars}}{{node .Decl $.FSet}}
 {{comment_text .Doc "    " "\t"}}
-{{end}}{{range .Funcs}}{{node .Decl $.FSet}}
+{{end}}{{example_text .Name $.Examples $.FSet "    "}}
+{{range .Funcs}}{{node .Decl $.FSet}}
 {{comment_text .Doc "    " "\t"}}
+{{example_text .Name $.Examples $.FSet "    "}}
 {{end}}{{range .Methods}}{{node .Decl $.FSet}}
 {{comment_text .Doc "    " "\t"}}
+{{$name := printf "%s_%s" $tname .Name}}{{example_text $name $.Examples $.FSet "    "}}
 {{end}}{{end}}{{end}}{{/*
 
 ---------------------------------------
 
-*/}}{{with .Bugs}}
-BUGS
-
-{{range .}}{{comment_text . "    " "\t"}}
-{{end}}{{end}}{{end}}{{/*
+*/}}{{with $.Notes}}
+{{range $marker, $content := .}}
+{{noteTitle $marker}}s
 
----------------------------------------
-
-*/}}{{with .PList}}
-OTHER PACKAGES
-
-{{range .}}
-{{.}}{{end}}
-{{end}}{{/*
+{{range $content}}{{comment_text . "    " "\t"}}
+{{end}}{{end}}{{end}}{{end}}{{/*
 
 ---------------------------------------
 
diff --git a/misc/benchcmp b/misc/benchcmp
index 015e7d2..3180f57 100755
--- a/misc/benchcmp
+++ b/misc/benchcmp
@@ -7,8 +7,13 @@ case "$1" in
 -*)	
 	echo 'usage: benchcmp old.txt new.txt' >&2
 	echo >&2
-	echo 'Each input file should be go test -test.run=NONE -test.bench=. > [old,new].txt' >&2
+	echo 'Each input file should be from:' >&2
+	echo '	go test -test.run=NONE -test.bench=. > [old,new].txt' >&2
+	echo >&2
 	echo 'Benchcmp compares the first and last for each benchmark.' >&2
+	echo >&2
+	echo 'If -test.benchmem=true is added to the "go test" command' >&2
+	echo 'benchcmp will also compare memory allocations.' >&2
 	exit 2
 esac
 
@@ -27,10 +32,31 @@ $1 ~ /Benchmark/ && $4 == "ns/op" {
 		new[$1] = $3
 		if($6 == "MB/s")
 			newmb[$1] = $5
+
+		# allocs/op might be at $8 or $10 depending on if
+		# SetBytes was used or not.
+		# B/op might be at $6 or $8, it should be immediately
+		# followed by allocs/op
+		if($8 == "allocs/op") {
+			newbytes[$1] = $5
+			newalloc[$1] = $7
+		}
+		if($10 == "allocs/op") {
+			newbytes[$1] = $7
+			newalloc[$1] = $9
+		}
 	} else {
 		old[$1] = $3
-		if($6 = "MB/s")
+		if($6 == "MB/s")
 			oldmb[$1] = $5
+		if($8 == "allocs/op") {
+			oldbytes[$1] = $5
+			oldalloc[$1] = $7
+		}
+		if($10 == "allocs/op") {
+			oldbytes[$1] = $7
+			oldalloc[$1] = $9
+		}
 	}
 }
 
@@ -62,5 +88,37 @@ END {
 			sprintf("%.2f", newmb[what]),
 			sprintf("%.2f", newmb[what]/oldmb[what]))
 	}
+
+	# print allocs
+	anyalloc = 0
+	for(i=0; i<n; i++) {
+		what = name[i]
+		if(!(what in newalloc))
+			continue
+		if(anyalloc++ == 0)
+			printf("\n%-*s %12s %12s  %7s\n", len, "benchmark", "old allocs", "new allocs", "delta")
+		if(oldalloc[what] == 0)
+			delta="n/a"
+		else
+			delta=sprintf("%.2f", 100*newalloc[what]/oldalloc[what]-100)
+		printf("%-*s %12d %12d  %6s%%\n", len, what,
+			oldalloc[what], newalloc[what], delta)
+	}
+
+	# print alloc bytes
+	anybytes = 0
+	for(i=0; i<n; i++) {
+		what = name[i]
+		if(!(what in newbytes))
+			continue
+		if(anybytes++ == 0)
+			printf("\n%-*s %12s %12s  %7s\n", len, "benchmark", "old bytes", "new bytes", "delta")
+		if(oldbytes[what] == 0)
+			delta="n/a"
+		else
+			delta=sprintf("%.2f", 100*newbytes[what]/oldbytes[what]-100)
+		printf("%-*s %12d %12d  %6s%%\n", len, what,
+			oldbytes[what], newbytes[what], delta)
+	}
 }
 ' "$@"
diff --git a/misc/cgo/life/golden.out b/misc/cgo/life/golden.out
deleted file mode 100644
index 539d210..0000000
--- a/misc/cgo/life/golden.out
+++ /dev/null
@@ -1,17 +0,0 @@
-* life
-                
-                
-  XXX     XXX   
-                
-                
-                
-                
-                
-                
-                
-  XXX     XXX   
-                
-                
-                
-                
-                
diff --git a/misc/cgo/life/life.go b/misc/cgo/life/life.go
index ec000ce..fda5495 100644
--- a/misc/cgo/life/life.go
+++ b/misc/cgo/life/life.go
@@ -1,3 +1,5 @@
+// skip
+
 // 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.
@@ -9,8 +11,8 @@ import "C"
 
 import "unsafe"
 
-func Run(gen, x, y int, a []int) {
-	n := make([]int, x*y)
+func Run(gen, x, y int, a []int32) {
+	n := make([]int32, x*y)
 	for i := 0; i < gen; i++ {
 		C.Step(C.int(x), C.int(y), (*C.int)(unsafe.Pointer(&a[0])), (*C.int)(unsafe.Pointer(&n[0])))
 		copy(a, n)
diff --git a/misc/cgo/life/main.go b/misc/cgo/life/main.go
index 47ae0e1..725e10f 100644
--- a/misc/cgo/life/main.go
+++ b/misc/cgo/life/main.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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.
@@ -22,7 +24,7 @@ var gen = flag.Int("gen", 10, "generations")
 func main() {
 	flag.Parse()
 
-	var a [MAXDIM * MAXDIM]int
+	var a [MAXDIM * MAXDIM]int32
 	for i := 2; i < *dim; i += 8 {
 		for j := 2; j < *dim-3; j += 8 {
 			for y := 0; y < 3; y++ {
diff --git a/misc/cgo/life/main.out b/misc/cgo/life/main.out
new file mode 100644
index 0000000..26fc9c6
--- /dev/null
+++ b/misc/cgo/life/main.out
@@ -0,0 +1,16 @@
+                
+                
+  XXX     XXX   
+                
+                
+                
+                
+                
+                
+                
+  XXX     XXX   
+                
+                
+                
+                
+                
diff --git a/misc/cgo/life/test.bash b/misc/cgo/life/test.bash
deleted file mode 100755
index bb48352..0000000
--- a/misc/cgo/life/test.bash
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-# 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.
-
-set -e
-go build -o life main.go
-
-echo '*' life >run.out
-./life >>run.out
-diff run.out golden.out
-
-rm -f life
-
diff --git a/misc/cgo/stdio/chain.go b/misc/cgo/stdio/chain.go
index 1cf0b1f..a55cefa 100644
--- a/misc/cgo/stdio/chain.go
+++ b/misc/cgo/stdio/chain.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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.
diff --git a/misc/cgo/stdio/chain.out b/misc/cgo/stdio/chain.out
new file mode 100644
index 0000000..963cf9b
--- /dev/null
+++ b/misc/cgo/stdio/chain.out
@@ -0,0 +1,55 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
diff --git a/misc/cgo/stdio/fib.go b/misc/cgo/stdio/fib.go
index 6d3ccfd..981ffeb 100644
--- a/misc/cgo/stdio/fib.go
+++ b/misc/cgo/stdio/fib.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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.
diff --git a/misc/cgo/stdio/fib.out b/misc/cgo/stdio/fib.out
new file mode 100644
index 0000000..17ff503
--- /dev/null
+++ b/misc/cgo/stdio/fib.out
@@ -0,0 +1,91 @@
+0
+1
+1
+2
+3
+5
+8
+13
+21
+34
+55
+89
+144
+233
+377
+610
+987
+1597
+2584
+4181
+6765
+10946
+17711
+28657
+46368
+75025
+121393
+196418
+317811
+514229
+832040
+1346269
+2178309
+3524578
+5702887
+9227465
+14930352
+24157817
+39088169
+63245986
+102334155
+165580141
+267914296
+433494437
+701408733
+1134903170
+1836311903
+2971215073
+4807526976
+7778742049
+12586269025
+20365011074
+32951280099
+53316291173
+86267571272
+139583862445
+225851433717
+365435296162
+591286729879
+956722026041
+1548008755920
+2504730781961
+4052739537881
+6557470319842
+10610209857723
+17167680177565
+27777890035288
+44945570212853
+72723460248141
+117669030460994
+190392490709135
+308061521170129
+498454011879264
+806515533049393
+1304969544928657
+2111485077978050
+3416454622906707
+5527939700884757
+8944394323791464
+14472334024676221
+23416728348467685
+37889062373143906
+61305790721611591
+99194853094755497
+160500643816367088
+259695496911122585
+420196140727489673
+679891637638612258
+1100087778366101931
+1779979416004714189
+2880067194370816120
diff --git a/misc/cgo/stdio/file.go b/misc/cgo/stdio/file.go
index 6e7d479..e7bb906 100644
--- a/misc/cgo/stdio/file.go
+++ b/misc/cgo/stdio/file.go
@@ -1,3 +1,5 @@
+// skip
+
 // 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.
@@ -23,9 +25,6 @@ import "unsafe"
 
 type File C.FILE
 
-var Stdout = (*File)(C.stdout)
-var Stderr = (*File)(C.stderr)
-
 // Test reference to library symbol.
 // Stdout and stderr are too special to be a reliable test.
 //var  = C.environ
diff --git a/misc/cgo/stdio/hello.go b/misc/cgo/stdio/hello.go
index 4ab3c74..9cfeefb 100644
--- a/misc/cgo/stdio/hello.go
+++ b/misc/cgo/stdio/hello.go
@@ -1,3 +1,5 @@
+// cmpout
+
 // 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.
diff --git a/test/helloworld.out b/misc/cgo/stdio/hello.out
similarity index 100%
copy from test/helloworld.out
copy to misc/cgo/stdio/hello.out
diff --git a/misc/cgo/stdio/golden.out b/misc/cgo/stdio/run.out
similarity index 100%
rename from misc/cgo/stdio/golden.out
rename to misc/cgo/stdio/run.out
diff --git a/misc/cgo/stdio/stdio.go b/misc/cgo/stdio/stdio.go
new file mode 100644
index 0000000..76cb8ad
--- /dev/null
+++ b/misc/cgo/stdio/stdio.go
@@ -0,0 +1,22 @@
+// skip
+
+// 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 stdio
+
+/*
+#include <stdio.h>
+
+// on mingw, stderr and stdout are defined as &_iob[FILENO]
+// on netbsd, they are defined as &__sF[FILENO]
+// and cgo doesn't recognize them, so write a function to get them,
+// instead of depending on internals of libc implementation.
+FILE *getStdout(void) { return stdout; }
+FILE *getStderr(void) { return stderr; }
+*/
+import "C"
+
+var Stdout = (*File)(C.getStdout())
+var Stderr = (*File)(C.getStderr())
diff --git a/misc/cgo/stdio/test.bash b/misc/cgo/stdio/test.bash
deleted file mode 100755
index 21829fa..0000000
--- a/misc/cgo/stdio/test.bash
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-# Copyright 2009 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-set -e
-go build hello.go
-go build fib.go
-go build chain.go
-
-echo '*' hello >run.out
-./hello >>run.out
-echo '*' fib >>run.out
-./fib >>run.out
-echo '*' chain >>run.out
-./chain >>run.out
-diff run.out golden.out
-
-rm -f hello fib chain
-
diff --git a/misc/cgo/test/Makefile b/misc/cgo/test/Makefile
deleted file mode 100644
index 2b7187a..0000000
--- a/misc/cgo/test/Makefile
+++ /dev/null
@@ -1,48 +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 ../../../src/Make.inc
-
-TARG=runtime/cgotest
-
-CGOFILES=\
-	align.go\
-	basic.go\
-	callback.go\
-	env.go\
-	exports.go\
-	helpers.go\
-	issue1222.go\
-	issue1328.go\
-	issue1560.go\
-	issue2462.go\
-	duplicate_symbol.go\
-
-CGO_OFILES=\
-	callback_c.o\
-
-OFILES=\
-	runtime.$O\
-
-ifeq ($(GOOS),windows)
-GCCVERSION=$(shell gcc -dumpversion)
-ifeq ($(GOARCH),386)
-GCCLIBDIR=/mingw/lib/gcc/mingw32/$(GCCVERSION)
-CHKSTK=_chkstk.o
-else
-GCCLIBDIR=/mingw/lib/gcc/x86_64-w64-mingw32/$(GCCVERSION)
-CHKSTK=_chkstk_ms.o
-endif
-
-CGOFILES+=sleep_windows.go
-CGO_OFILES+=$(CHKSTK)
-
-$(CHKSTK):
-	ar -x "$(GCCLIBDIR)/libgcc.a" $@
-endif
-
-include ../../../src/Make.pkg
-
-test:
-	echo cgo: tests disabled. gotest is gone. TODO
\ No newline at end of file
diff --git a/misc/cgo/test/backdoor/runtime.c b/misc/cgo/test/backdoor/runtime.c
index 54e6a1e..194a9c8 100644
--- a/misc/cgo/test/backdoor/runtime.c
+++ b/misc/cgo/test/backdoor/runtime.c
@@ -6,6 +6,8 @@
 // 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);
diff --git a/misc/cgo/test/backdoor/runtime_gccgo.c b/misc/cgo/test/backdoor/runtime_gccgo.c
new file mode 100644
index 0000000..218b2c3
--- /dev/null
+++ b/misc/cgo/test/backdoor/runtime_gccgo.c
@@ -0,0 +1,18 @@
+// 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.
+
+// Expose some runtime functions for testing.
+// This is the gccgo version of runtime.c.
+
+// +build gccgo
+
+_Bool runtime_lockedOSThread(void);
+
+_Bool LockedOSThread(void) asm(GOPKGPATH ".LockedOSThread");
+
+_Bool
+LockedOSThread(void)
+{
+	return runtime_lockedOSThread();
+}
diff --git a/misc/cgo/test/basic.go b/misc/cgo/test/basic.go
index 70ec5e4..79cbf2b 100644
--- a/misc/cgo/test/basic.go
+++ b/misc/cgo/test/basic.go
@@ -14,15 +14,16 @@ package cgotest
 
 #define SHIFT(x, y)  ((x)<<(y))
 #define KILO SHIFT(1, 10)
+#define UINT32VAL 0xc008427bU
 
 enum E {
 	Enum1 = 1,
 	Enum2 = 2,
 };
 
-typedef unsigned char uuid_t[20];
+typedef unsigned char cgo_uuid_t[20];
 
-void uuid_generate(uuid_t x) {
+void uuid_generate(cgo_uuid_t x) {
 	x[0] = 0;
 }
 
@@ -55,6 +56,7 @@ int add(int x, int y) {
 */
 import "C"
 import (
+	"runtime"
 	"syscall"
 	"testing"
 	"unsafe"
@@ -65,7 +67,7 @@ const EINVAL = C.EINVAL /* test #define */
 var KILO = C.KILO
 
 func uuidgen() {
-	var uuid C.uuid_t
+	var uuid C.cgo_uuid_t
 	C.uuid_generate(&uuid[0])
 }
 
@@ -118,7 +120,12 @@ func testErrno(t *testing.T) {
 func testMultipleAssign(t *testing.T) {
 	p := C.CString("234")
 	n, m := C.strtol(p, nil, 345), C.strtol(p, nil, 10)
-	if n != 0 || m != 234 {
+	if runtime.GOOS == "openbsd" {
+		// Bug in OpenBSD strtol(3) - base > 36 succeeds.
+		if (n != 0 && n != 239089) || m != 234 {
+			t.Fatal("Strtol x2: ", n, m)
+		}
+	} else if n != 0 || m != 234 {
 		t.Fatal("Strtol x2: ", n, m)
 	}
 	C.free(unsafe.Pointer(p))
@@ -141,3 +148,12 @@ func benchCgoCall(b *testing.B) {
 		C.add(x, y)
 	}
 }
+
+// Issue 2470.
+func testUnsignedInt(t *testing.T) {
+	a := (int64)(C.UINT32VAL)
+	b := (int64)(0xc008427b)
+	if a != b {
+		t.Errorf("Incorrect unsigned int - got %x, want %x", a, b)
+	}
+}
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go
index e6a1462..4f5d3f8 100644
--- a/misc/cgo/test/callback.go
+++ b/misc/cgo/test/callback.go
@@ -110,7 +110,7 @@ func testZeroArgCallback(t *testing.T) {
 func goFoo() {
 	x := 1
 	for i := 0; i < 10000; i++ {
-		// variadic call mallocs + writes to 
+		// variadic call mallocs + writes to
 		variadic(x, x, x)
 		if x != 1 {
 			panic("bad x")
diff --git a/misc/cgo/test/cgo_linux_test.go b/misc/cgo/test/cgo_linux_test.go
new file mode 100644
index 0000000..056d67c
--- /dev/null
+++ b/misc/cgo/test/cgo_linux_test.go
@@ -0,0 +1,9 @@
+// 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 cgotest
+
+import "testing"
+
+func TestSetgid(t *testing.T) { testSetgid(t) }
diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go
index 34beee6..536fa50 100644
--- a/misc/cgo/test/cgo_test.go
+++ b/misc/cgo/test/cgo_test.go
@@ -6,7 +6,7 @@ package cgotest
 
 import "testing"
 
-// The actual test functions are in non-_test.go files 
+// The actual test functions are in non-_test.go files
 // so that they can use cgo (import "C").
 // These wrappers are here for gotest to find.
 
@@ -16,6 +16,7 @@ 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) }
@@ -27,5 +28,13 @@ 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 BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/misc/cgo/test/cthread.go b/misc/cgo/test/cthread.go
new file mode 100644
index 0000000..d918d03
--- /dev/null
+++ b/misc/cgo/test/cthread.go
@@ -0,0 +1,44 @@
+// 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 cgotest
+
+// extern void doAdd(int, int);
+import "C"
+
+import (
+	"runtime"
+	"sync"
+	"testing"
+)
+
+var sum struct {
+	sync.Mutex
+	i int
+}
+
+//export Add
+func Add(x int) {
+	defer func() {
+		recover()
+	}()
+	sum.Lock()
+	sum.i += x
+	sum.Unlock()
+	var p *int
+	*p = 2
+}
+
+func testCthread(t *testing.T) {
+	if runtime.GOARCH == "arm" {
+		t.Skip("testCthread disabled on arm")
+	}
+
+	C.doAdd(10, 6)
+
+	want := 10 * (10 - 1) / 2 * 6
+	if sum.i != want {
+		t.Fatalf("sum=%d, want %d", sum.i, want)
+	}
+}
diff --git a/misc/cgo/test/cthread_unix.c b/misc/cgo/test/cthread_unix.c
new file mode 100644
index 0000000..998bc00
--- /dev/null
+++ b/misc/cgo/test/cthread_unix.c
@@ -0,0 +1,34 @@
+// 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 freebsd linux netbsd openbsd
+
+#include <pthread.h>
+#include "_cgo_export.h"
+
+static void*
+addThread(void *p)
+{
+	int i, max;
+	
+	max = *(int*)p;
+	for(i=0; i<max; i++)
+		Add(i);
+	return 0;
+}
+
+void
+doAdd(int max, int nthread)
+{
+	enum { MaxThread = 20 };
+	int i;
+	pthread_t thread_id[MaxThread];
+	
+	if(nthread > MaxThread)
+		nthread = MaxThread;
+	for(i=0; i<nthread; i++)
+		pthread_create(&thread_id[i], 0, addThread, &max);
+	for(i=0; i<nthread; i++)
+		pthread_join(thread_id[i], 0);		
+}
diff --git a/misc/cgo/test/cthread_windows.c b/misc/cgo/test/cthread_windows.c
new file mode 100644
index 0000000..5f370a8
--- /dev/null
+++ b/misc/cgo/test/cthread_windows.c
@@ -0,0 +1,37 @@
+// 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.
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+#include "_cgo_export.h"
+
+__stdcall
+static unsigned int
+addThread(void *p)
+{
+	int i, max;
+	
+	max = *(int*)p;
+	for(i=0; i<max; i++)
+		Add(i);
+	return 0;
+}
+
+void
+doAdd(int max, int nthread)
+{
+	enum { MaxThread = 20 };
+	int i;
+	uintptr_t thread_id[MaxThread];
+	
+	if(nthread > MaxThread)
+		nthread = MaxThread;
+	for(i=0; i<nthread; i++)
+		thread_id[i] = _beginthreadex(0, 0, addThread, &max, 0, 0);
+	for(i=0; i<nthread; i++) {
+		WaitForSingleObject((HANDLE)thread_id[i], INFINITE);
+		CloseHandle((HANDLE)thread_id[i]);
+	}
+}
diff --git a/misc/cgo/test/issue1560.go b/misc/cgo/test/issue1560.go
index 3faa966..147ce94 100644
--- a/misc/cgo/test/issue1560.go
+++ b/misc/cgo/test/issue1560.go
@@ -15,6 +15,7 @@ void twoSleep(int);
 import "C"
 
 import (
+	"runtime"
 	"testing"
 	"time"
 )
@@ -27,19 +28,48 @@ func parallelSleep(n int) {
 }
 
 //export BackgroundSleep
-func BackgroundSleep(n int) {
+func BackgroundSleep(n int32) {
 	go func() {
 		C.sleep(C.uint(n))
 		sleepDone <- true
 	}()
 }
 
+// wasteCPU starts a background goroutine to waste CPU
+// to cause the power management to raise the CPU frequency.
+// On ARM this has the side effect of making sleep more accurate.
+func wasteCPU() chan struct{} {
+	done := make(chan struct{})
+	go func() {
+		for {
+			select {
+			case <-done:
+				return
+			default:
+			}
+		}
+	}()
+	// pause for a short amount of time to allow the
+	// power management to recognise load has risen.
+	<-time.After(300 * time.Millisecond)
+	return done
+}
+
 func testParallelSleep(t *testing.T) {
+	if runtime.GOARCH == "arm" {
+		// on ARM, the 1.3s deadline is frequently missed,
+		// and burning cpu seems to help
+		defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+		defer close(wasteCPU())
+	}
+
+	sleepSec := 1
 	start := time.Now()
-	parallelSleep(1)
-	dt := time.Now().Sub(start)
-	// bug used to run sleeps in serial, producing a 2-second delay.
-	if dt >= 1300*time.Millisecond {
-		t.Fatalf("parallel 1-second sleeps slept for %f seconds", dt.Seconds())
+	parallelSleep(sleepSec)
+	dt := time.Since(start)
+	t.Logf("sleep(%d) slept for %v", sleepSec, dt)
+	// bug used to run sleeps in serial, producing a 2*sleepSec-second delay.
+	if dt >= time.Duration(sleepSec)*1300*time.Millisecond {
+		t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds())
 	}
 }
diff --git a/misc/cgo/test/issue1635.go b/misc/cgo/test/issue1635.go
new file mode 100644
index 0000000..6bfe110
--- /dev/null
+++ b/misc/cgo/test/issue1635.go
@@ -0,0 +1,33 @@
+// 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 cgotest
+
+/*
+// Mac OS X's gcc will generate scattered relocation 2/1 for
+// this function on Darwin/386, and 8l couldn't handle it.
+// this example is in issue 1635
+#include <stdio.h>
+void scatter() {
+	void *p = scatter;
+	printf("scatter = %p\n", p);
+}
+
+// this example is in issue 3253
+int hola = 0;
+int testHola() { return hola; }
+*/
+import "C"
+
+import "testing"
+
+func test1635(t *testing.T) {
+	C.scatter()
+	if v := C.hola; v != 0 {
+		t.Fatalf("C.hola is %d, should be 0", v)
+	}
+	if v := C.testHola(); v != 0 {
+		t.Fatalf("C.testHola() is %d, should be 0", v)
+	}
+}
diff --git a/misc/cgo/test/issue3261.go b/misc/cgo/test/issue3261.go
new file mode 100644
index 0000000..0411be8
--- /dev/null
+++ b/misc/cgo/test/issue3261.go
@@ -0,0 +1,43 @@
+// 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 cgotest
+
+/*
+// libgcc on ARM might be compiled as thumb code, but our 5l
+// can't handle that, so we have to disable this test on arm.
+#ifdef __ARMEL__
+#include <stdio.h>
+int vabs(int x) {
+	puts("testLibgcc is disabled on ARM because 5l cannot handle thumb library.");
+	return (x < 0) ? -x : x;
+}
+#else
+int __absvsi2(int); // dummy prototype for libgcc function
+// we shouldn't name the function abs, as gcc might use
+// the builtin one.
+int vabs(int x) { return __absvsi2(x); }
+#endif
+*/
+import "C"
+
+import "testing"
+
+func testLibgcc(t *testing.T) {
+	var table = []struct {
+		in, out C.int
+	}{
+		{0, 0},
+		{1, 1},
+		{-42, 42},
+		{1000300, 1000300},
+		{1 - 1<<31, 1<<31 - 1},
+	}
+	for _, v := range table {
+		if o := C.vabs(v.in); o != v.out {
+			t.Fatalf("abs(%d) got %d, should be %d", v.in, o, v.out)
+			return
+		}
+	}
+}
diff --git a/misc/cgo/test/issue3729.go b/misc/cgo/test/issue3729.go
new file mode 100644
index 0000000..1bea38b
--- /dev/null
+++ b/misc/cgo/test/issue3729.go
@@ -0,0 +1,47 @@
+// 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.
+
+// Issue 3729:	cmd/cgo: access errno from void C function
+// void f(void) returns [0]byte, error in Go world.
+
+// +build !windows
+
+package cgotest
+
+/*
+#include <errno.h>
+
+void g(void) {
+	errno = E2BIG;
+}
+
+// try to pass some non-trivial arguments to function g2
+const char _expA = 0x42;
+const float _expB = 3.14159;
+const short _expC = 0x55aa;
+const int _expD = 0xdeadbeef;
+void g2(int x, char a, float b, short c, int d) {
+	if (a == _expA && b == _expB && c == _expC && d == _expD)
+		errno = x;
+	else
+		errno = -1;
+}
+*/
+import "C"
+
+import (
+	"syscall"
+	"testing"
+)
+
+func test3729(t *testing.T) {
+	_, e := C.g()
+	if e != syscall.E2BIG {
+		t.Errorf("got %q, expect %q", e, syscall.E2BIG)
+	}
+	_, e = C.g2(C.EINVAL, C._expA, C._expB, C._expC, C._expD)
+	if e != syscall.EINVAL {
+		t.Errorf("got %q, expect %q", e, syscall.EINVAL)
+	}
+}
diff --git a/misc/cgo/test/issue3729w.go b/misc/cgo/test/issue3729w.go
new file mode 100644
index 0000000..702115b
--- /dev/null
+++ b/misc/cgo/test/issue3729w.go
@@ -0,0 +1,16 @@
+// 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.
+
+// Issue 3729:	cmd/cgo: access errno from void C function
+// void f(void) returns [0]byte, error in Go world.
+
+// +build windows
+
+package cgotest
+
+import "testing"
+
+func test3729(t *testing.T) {
+	t.Log("skip errno test on Windows")
+}
diff --git a/misc/cgo/test/issue3741.go b/misc/cgo/test/issue3741.go
new file mode 100644
index 0000000..3d3bbf9
--- /dev/null
+++ b/misc/cgo/test/issue3741.go
@@ -0,0 +1,22 @@
+// 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 cgotest
+
+import "C"
+
+//export exportSliceIn
+func exportSliceIn(s []byte) bool {
+	return len(s) == cap(s)
+}
+
+//export exportSliceOut
+func exportSliceOut() []byte {
+	return []byte{1}
+}
+
+//export exportSliceInOut
+func exportSliceInOut(s []byte) []byte {
+	return s
+}
diff --git a/misc/cgo/test/issue3775.go b/misc/cgo/test/issue3775.go
new file mode 100644
index 0000000..c05a5d4
--- /dev/null
+++ b/misc/cgo/test/issue3775.go
@@ -0,0 +1,29 @@
+package cgotest
+
+/*
+void lockOSThreadCallback(void);
+inline static void lockOSThreadC(void)
+{
+        lockOSThreadCallback();
+}
+int usleep(unsigned usec);
+*/
+import "C"
+
+import (
+	"runtime"
+	"testing"
+)
+
+func test3775(t *testing.T) {
+	// Used to panic because of the UnlockOSThread below.
+	C.lockOSThreadC()
+}
+
+//export lockOSThreadCallback
+func lockOSThreadCallback() {
+	runtime.LockOSThread()
+	runtime.UnlockOSThread()
+	go C.usleep(10000)
+	runtime.Gosched()
+}
diff --git a/misc/cgo/test/issue3945.go b/misc/cgo/test/issue3945.go
new file mode 100644
index 0000000..331cd0b
--- /dev/null
+++ b/misc/cgo/test/issue3945.go
@@ -0,0 +1,22 @@
+// 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 cgotest
+
+// Test that cgo reserves enough stack space during cgo call.
+// See http://golang.org/issue/3945 for details.
+
+// #include <stdio.h>
+//
+// void say() {
+//    printf("%s from C\n", "hello");
+// }
+//
+import "C"
+
+import "testing"
+
+func testPrintf(t *testing.T) {
+	C.say()
+}
diff --git a/misc/cgo/test/issue4029.go b/misc/cgo/test/issue4029.go
new file mode 100644
index 0000000..7495d38
--- /dev/null
+++ b/misc/cgo/test/issue4029.go
@@ -0,0 +1,60 @@
+// 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 !windows
+
+package cgotest
+
+/*
+#include <dlfcn.h>
+#cgo linux LDFLAGS: -ldl
+*/
+import "C"
+
+import (
+	"fmt"
+	"testing"
+)
+
+//export IMPIsOpaque
+func IMPIsOpaque() {
+	fmt.Println("isOpaque")
+}
+
+//export IMPInitWithFrame
+func IMPInitWithFrame() {
+	fmt.Println("IInitWithFrame")
+}
+
+//export IMPDrawRect
+func IMPDrawRect() {
+	fmt.Println("drawRect:")
+}
+
+//export IMPWindowResize
+func IMPWindowResize() {
+	fmt.Println("windowDidResize:")
+}
+
+func test4029(t *testing.T) {
+	loadThySelf(t, "IMPWindowResize")
+	loadThySelf(t, "IMPDrawRect")
+	loadThySelf(t, "IMPInitWithFrame")
+	loadThySelf(t, "IMPIsOpaque")
+}
+
+func loadThySelf(t *testing.T, symbol string) {
+	this_process := C.dlopen(nil, C.RTLD_NOW)
+	if this_process == nil {
+		t.Fatal("dlopen:", C.GoString(C.dlerror()))
+	}
+	defer C.dlclose(this_process)
+
+	symbol_address := C.dlsym(this_process, C.CString(symbol))
+	if symbol_address == nil {
+		t.Fatal("dlsym:", C.GoString(C.dlerror()))
+	} else {
+		t.Log(symbol, symbol_address)
+	}
+}
diff --git a/misc/cgo/test/issue4029w.go b/misc/cgo/test/issue4029w.go
new file mode 100644
index 0000000..1cf43df
--- /dev/null
+++ b/misc/cgo/test/issue4029w.go
@@ -0,0 +1,12 @@
+// 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 windows
+
+package cgotest
+
+import "testing"
+
+func test4029(t *testing.T) {
+}
diff --git a/misc/cgo/test/issue4054a.go b/misc/cgo/test/issue4054a.go
new file mode 100644
index 0000000..2abdac5
--- /dev/null
+++ b/misc/cgo/test/issue4054a.go
@@ -0,0 +1,23 @@
+// 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 cgotest
+
+/*
+typedef enum {
+	A = 0,
+	B,
+	C,
+	D,
+	E,
+	F,
+	G,
+	H,
+	I,
+	J,
+} issue4054a;
+*/
+import "C"
+
+var issue4054a = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J}
diff --git a/misc/cgo/test/issue4054b.go b/misc/cgo/test/issue4054b.go
new file mode 100644
index 0000000..048964c
--- /dev/null
+++ b/misc/cgo/test/issue4054b.go
@@ -0,0 +1,23 @@
+// 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 cgotest
+
+/*
+typedef enum {
+	A = 0,
+	B,
+	C,
+	D,
+	E,
+	F,
+	G,
+	H,
+	I,
+	J,
+} issue4054b;
+*/
+import "C"
+
+var issue4054b = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J}
diff --git a/misc/cgo/test/issue4273.c b/misc/cgo/test/issue4273.c
new file mode 100644
index 0000000..a3fcf3b
--- /dev/null
+++ b/misc/cgo/test/issue4273.c
@@ -0,0 +1,10 @@
+// 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.
+
+#ifdef __ELF__
+__attribute__((weak))
+__attribute__((visibility("hidden")))
+void _compilerrt_abort_impl(const char *file, int line, const char *func) {
+}
+#endif
diff --git a/misc/cgo/test/issue4273b.c b/misc/cgo/test/issue4273b.c
new file mode 100644
index 0000000..93e2f4f
--- /dev/null
+++ b/misc/cgo/test/issue4273b.c
@@ -0,0 +1,11 @@
+// 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.
+
+#ifdef __ELF__
+extern void _compilerrt_abort_impl(const char *file, int line, const char *func);
+
+void __my_abort(const char *file, int line, const char *func) {
+	_compilerrt_abort_impl(file, line, func);
+}
+#endif
diff --git a/misc/cgo/test/issue4417.go b/misc/cgo/test/issue4417.go
new file mode 100644
index 0000000..0b48071
--- /dev/null
+++ b/misc/cgo/test/issue4417.go
@@ -0,0 +1,42 @@
+// 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.
+
+// Issue 4417:	cmd/cgo: bool alignment/padding issue.
+// bool alignment is wrong and causing wrong arguments when calling functions.
+//
+
+package cgotest
+
+/*
+#include <stdbool.h>
+
+static int c_bool(bool a, bool b, int c, bool d, bool e)  {
+   return c;
+}
+*/
+import "C"
+import "testing"
+
+func testBoolAlign(t *testing.T) {
+	b := C.c_bool(true, true, 10, true, false)
+	if b != 10 {
+		t.Fatalf("found %d expected 10\n", b)
+	}
+	b = C.c_bool(true, true, 5, true, true)
+	if b != 5 {
+		t.Fatalf("found %d expected 5\n", b)
+	}
+	b = C.c_bool(true, true, 3, true, false)
+	if b != 3 {
+		t.Fatalf("found %d expected 3\n", b)
+	}
+	b = C.c_bool(false, false, 1, true, false)
+	if b != 1 {
+		t.Fatalf("found %d expected 1\n", b)
+	}
+	b = C.c_bool(false, true, 200, true, false)
+	if b != 200 {
+		t.Fatalf("found %d expected 200\n", b)
+	}
+}
diff --git a/misc/cgo/test/setgid_linux.go b/misc/cgo/test/setgid_linux.go
new file mode 100644
index 0000000..829afce
--- /dev/null
+++ b/misc/cgo/test/setgid_linux.go
@@ -0,0 +1,32 @@
+// 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 that setgid does not hang on GNU/Linux.
+// See http://code.google.com/p/go/issues/detail?id=3871 for details.
+
+package cgotest
+
+/*
+#include <sys/types.h>
+#include <unistd.h>
+*/
+import "C"
+
+import (
+	"testing"
+	"time"
+)
+
+func testSetgid(t *testing.T) {
+	c := make(chan bool)
+	go func() {
+		C.setgid(0)
+		c <- true
+	}()
+	select {
+	case <-c:
+	case <-time.After(5 * time.Second):
+		t.Error("setgid hung")
+	}
+}
diff --git a/misc/cgo/test/sleep_windows.go b/misc/cgo/test/sleep_windows.go
deleted file mode 100644
index 007a1bb..0000000
--- a/misc/cgo/test/sleep_windows.go
+++ /dev/null
@@ -1,16 +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 cgotest
-
-/*
-#include <windows.h>
-
-unsigned int sleep(unsigned int seconds) {
-	Sleep(1000 * seconds);
-	return 0;
-}
-
-*/
-import "C"
diff --git a/misc/cgo/test/sleep_windows_386.go b/misc/cgo/test/sleep_windows_386.go
new file mode 100644
index 0000000..75687d7
--- /dev/null
+++ b/misc/cgo/test/sleep_windows_386.go
@@ -0,0 +1,20 @@
+// 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 cgotest
+
+/*
+// mingw32 on windows/386 provides usleep() but not sleep(),
+// as we don't want to require all other OSes to provide usleep,
+// we emulate sleep(int s) using win32 API Sleep(int ms).
+
+#include <windows.h>
+
+unsigned int sleep(unsigned int seconds) {
+	Sleep(1000 * seconds);
+	return 0;
+}
+
+*/
+import "C"
diff --git a/misc/cgo/testso/test.bash b/misc/cgo/testso/test.bash
index ecef873..5f113d2 100755
--- a/misc/cgo/testso/test.bash
+++ b/misc/cgo/testso/test.bash
@@ -4,7 +4,7 @@
 # license that can be found in the LICENSE file.
 
 set -e
-gcc $(go env GOGCCFLAGS) -shared -o libcgosotest.so cgoso_c.c
+$(go env CC) $(go env GOGCCFLAGS) -shared -o libcgosotest.so cgoso_c.c
 go build main.go
 LD_LIBRARY_PATH=. ./main
 rm -f libcgosotest.so main
diff --git a/misc/chrome/gophertool/background.html b/misc/chrome/gophertool/background.html
index 058c181..06daa98 100644
--- a/misc/chrome/gophertool/background.html
+++ b/misc/chrome/gophertool/background.html
@@ -6,19 +6,7 @@
 -->
 <head>
 <script src="gopher.js"></script>
-<script>
-    
-chrome.omnibox.onInputEntered.addListener(function(t) {
-  var url = urlForInput(t);
-  if (url) {
-    chrome.tabs.getSelected(null, function(tab) {
-      if (!tab) return;
-      chrome.tabs.update(tab.id, { "url": url, "selected": true });
-    });
-  }
-});
-
-</script>
+<script src="background.js"></script>
 </head>
 </html>
 
diff --git a/misc/chrome/gophertool/background.js b/misc/chrome/gophertool/background.js
new file mode 100644
index 0000000..d18faa9
--- /dev/null
+++ b/misc/chrome/gophertool/background.js
@@ -0,0 +1,9 @@
+chrome.omnibox.onInputEntered.addListener(function(t) {
+  var url = urlForInput(t);
+  if (url) {
+    chrome.tabs.getSelected(null, function(tab) {
+      if (!tab) return;
+      chrome.tabs.update(tab.id, { "url": url, "selected": true });
+    });
+  }
+});
diff --git a/misc/chrome/gophertool/gopher.js b/misc/chrome/gophertool/gopher.js
index 847c1c7..3238f0f 100644
--- a/misc/chrome/gophertool/gopher.js
+++ b/misc/chrome/gophertool/gopher.js
@@ -12,7 +12,7 @@ function urlForInput(t) {
     }
 
     if (numericRE.test(t)) {
-        if (t < 1000000) {
+        if (t < 150000) {
             return "http://code.google.com/p/go/issues/detail?id=" + t;
         }
         return "http://codereview.appspot.com/" + t + "/";
diff --git a/misc/chrome/gophertool/manifest.json b/misc/chrome/gophertool/manifest.json
index 3a2540a..0438659 100644
--- a/misc/chrome/gophertool/manifest.json
+++ b/misc/chrome/gophertool/manifest.json
@@ -1,11 +1,14 @@
 {
   "name": "Hacking Gopher",
   "version": "1.0",
+  "manifest_version": 2,
   "description": "Go Hacking utility",
-  "background_page": "background.html",
+  "background": {
+    "page": "background.html"
+  },
   "browser_action": {
     "default_icon": "gopher.png",
-    "popup": "popup.html"
+    "default_popup": "popup.html"
   },
   "omnibox": { "keyword": "golang" },
   "icons": {
diff --git a/misc/chrome/gophertool/popup.html b/misc/chrome/gophertool/popup.html
index 4816c39..8bb7795 100644
--- a/misc/chrome/gophertool/popup.html
+++ b/misc/chrome/gophertool/popup.html
@@ -6,49 +6,14 @@
 -->
 <head>
 <script src="gopher.js"></script>
-<script>
-    
-function focusinput() {
-  document.getElementById("inputbox").focus();
-}
-
-function navigate() {
-  var box = document.getElementById("inputbox");
-  box.focus();
-
-  var t = box.value;
-  if (t == "") {
-    return false;
-  }
-
-  var success = function(url) {
-    console.log("matched " + t + " to: " + url)
-    box.value = "";
-    openURL(url);
-    return false;  // cancel form submission
-  };
-
-  var url = urlForInput(t);
-  if (url) {
-    return success(url);
-  }
-
-  console.log("no match for text: " + t)
-  return false;
-}
-
-function openURL(url) {
-  chrome.tabs.create({ "url": url })
-}
-
-</script>
+<script src="popup.js"></script>
 </head>
-<body onload="focusinput()" style='margin: 0.5em; font-family: sans;'>
-<small><a href="#" onclick="openURL('http://code.google.com/p/go/issues/list')">issue</a>,
-<a href="#" onclick="openURL('http://codereview.appspot.com/')">codereview</a>,
-<a href="#" onclick="openURL('http://code.google.com/p/go/source/list')">commit</a>, or
-<a href="#" onclick="openURL('http://golang.org/pkg/')">pkg</a> id/name:</small>
-<form style='margin: 0' onsubmit="return navigate();"><nobr><input id="inputbox" size=10 /><input type="submit" value="go" /></nobr></form>
-<small>Also: <a href="#" onclick="openURL('http://build.golang.org/')">buildbots</small>
+<body style='margin: 0.5em; font-family: sans;'>
+<small><a href="#" url="http://code.google.com/p/go/issues/list">issue</a>,
+<a href="#" url="http://codereview.appspot.com/">codereview</a>,
+<a href="#" url="http://code.google.com/p/go/source/list">commit</a>, or
+<a href="#" url="http://golang.org/pkg/">pkg</a> id/name:</small>
+<form style='margin: 0' id='navform'><nobr><input id="inputbox" size=10 tabindex=1 /><input type="submit" value="go" /></nobr></form>
+<small>Also: <a href="#" url="http://build.golang.org">buildbots</a></small>
 </body>
 </html>
diff --git a/misc/chrome/gophertool/popup.js b/misc/chrome/gophertool/popup.js
new file mode 100644
index 0000000..410d651
--- /dev/null
+++ b/misc/chrome/gophertool/popup.js
@@ -0,0 +1,46 @@
+function openURL(url) {
+  chrome.tabs.create({ "url": url })
+}
+
+function addLinks() {
+  var links = document.getElementsByTagName("a");
+  for (var i = 0; i < links.length; i++) {
+    var url = links[i].getAttribute("url");
+    if (url)
+      links[i].addEventListener("click", function () {
+        openURL(this.getAttribute("url"));
+      });
+  }
+}
+
+window.addEventListener("load", function () {
+  addLinks();
+  console.log("hacking gopher pop-up loaded.");
+  document.getElementById("inputbox").focus();
+});
+
+window.addEventListener("submit", function () {
+  console.log("submitting form");
+  var box = document.getElementById("inputbox");
+  box.focus();
+
+  var t = box.value;
+  if (t == "") {
+    return false;
+  }
+
+  var success = function(url) {
+    console.log("matched " + t + " to: " + url)
+    box.value = "";
+    openURL(url);
+    return false;  // cancel form submission
+  };
+
+  var url = urlForInput(t);
+  if (url) {
+    return success(url);
+  }
+
+  console.log("no match for text: " + t)
+  return false;
+});
diff --git a/misc/dashboard/app/app.yaml b/misc/dashboard/app/app.yaml
index 6e19db0..c5a1f6c 100644
--- a/misc/dashboard/app/app.yaml
+++ b/misc/dashboard/app/app.yaml
@@ -6,7 +6,7 @@
 application: golang-org
 version: build
 runtime: go
-api_version: go1beta
+api_version: go1
 
 handlers:
 - url: /static
diff --git a/misc/dashboard/app/build/build.go b/misc/dashboard/app/build/build.go
index c49fa8b..e0c0f00 100644
--- a/misc/dashboard/app/build/build.go
+++ b/misc/dashboard/app/build/build.go
@@ -49,6 +49,10 @@ func (p *Package) LastCommit(c appengine.Context) (*Commit, error) {
 		Order("-Time").
 		Limit(1).
 		GetAll(c, &commits)
+	if _, ok := err.(*datastore.ErrFieldMismatch); ok {
+		// Some fields have been removed, so it's okay to ignore this error.
+		err = nil
+	}
 	if err != nil {
 		return nil, err
 	}
@@ -65,6 +69,10 @@ func GetPackage(c appengine.Context, path string) (*Package, error) {
 	if err == datastore.ErrNoSuchEntity {
 		return nil, fmt.Errorf("package %q not found", path)
 	}
+	if _, ok := err.(*datastore.ErrFieldMismatch); ok {
+		// Some fields have been removed, so it's okay to ignore this error.
+		err = nil
+	}
 	return p, err
 }
 
@@ -111,19 +119,35 @@ func (c *Commit) Valid() error {
 	return nil
 }
 
+// each result line is approx 105 bytes. This constant is a tradeoff between
+// build history and the AppEngine datastore limit of 1mb.
+const maxResults = 1000
+
 // AddResult adds the denormalized Reuslt data to the Commit's Result field.
 // It must be called from inside a datastore transaction.
 func (com *Commit) AddResult(c appengine.Context, r *Result) error {
 	if err := datastore.Get(c, com.Key(c), com); err != nil {
 		return fmt.Errorf("getting Commit: %v", err)
 	}
-	com.ResultData = append(com.ResultData, r.Data())
+	com.ResultData = trim(append(com.ResultData, r.Data()), maxResults)
 	if _, err := datastore.Put(c, com.Key(c), com); err != nil {
 		return fmt.Errorf("putting Commit: %v", err)
 	}
 	return nil
 }
 
+func trim(s []string, n int) []string {
+	l := min(len(s), n)
+	return s[len(s)-l:]
+}
+
+func min(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}
+
 // Result returns the build Result for this Commit for the given builder/goHash.
 func (c *Commit) Result(builder, goHash string) *Result {
 	for _, r := range c.ResultData {
@@ -160,20 +184,11 @@ func partsToHash(c *Commit, p []string) *Result {
 	}
 }
 
-// OK returns the Commit's build state for a specific builder and goHash.
-func (c *Commit) OK(builder, goHash string) (ok, present bool) {
-	r := c.Result(builder, goHash)
-	if r == nil {
-		return false, false
-	}
-	return r.OK, true
-}
-
 // A Result describes a build result for a Commit on an OS/architecture.
 //
 // Each Result entity is a descendant of its associated Commit entity.
 type Result struct {
-	Builder     string // "arch-os[-note]"
+	Builder     string // "os-arch[-note]"
 	Hash        string
 	PackagePath string // (empty for Go commits)
 
@@ -184,7 +199,7 @@ type Result struct {
 	Log     string `datastore:"-"`        // for JSON unmarshaling only
 	LogHash string `datastore:",noindex"` // Key to the Log record.
 
-	RunTime int64 // time to build+test in nanoseconds 
+	RunTime int64 // time to build+test in nanoseconds
 }
 
 func (r *Result) Key(c appengine.Context) *datastore.Key {
@@ -297,7 +312,12 @@ func Packages(c appengine.Context, kind string) ([]*Package, error) {
 	q := datastore.NewQuery("Package").Filter("Kind=", kind)
 	for t := q.Run(c); ; {
 		pkg := new(Package)
-		if _, err := t.Next(pkg); err == datastore.Done {
+		_, err := t.Next(pkg)
+		if _, ok := err.(*datastore.ErrFieldMismatch); ok {
+			// Some fields have been removed, so it's okay to ignore this error.
+			err = nil
+		}
+		if err == datastore.Done {
 			break
 		} else if err != nil {
 			return nil, err
diff --git a/misc/dashboard/app/build/handler.go b/misc/dashboard/app/build/handler.go
index 5d1e309..1a11186 100644
--- a/misc/dashboard/app/build/handler.go
+++ b/misc/dashboard/app/build/handler.go
@@ -322,7 +322,7 @@ func resultHandler(r *http.Request) (interface{}, error) {
 // logHandler displays log text for a given hash.
 // It handles paths like "/log/hash".
 func logHandler(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-type", "text/plain")
+	w.Header().Set("Content-type", "text/plain; charset=utf-8")
 	c := appengine.NewContext(r)
 	hash := r.URL.Path[len("/log/"):]
 	key := datastore.NewKey(c, "Log", hash, 0, nil)
diff --git a/misc/dashboard/app/build/init.go b/misc/dashboard/app/build/init.go
index 5311688..85a766b 100644
--- a/misc/dashboard/app/build/init.go
+++ b/misc/dashboard/app/build/init.go
@@ -24,6 +24,8 @@ var subRepos = []string{
 	"crypto",
 	"image",
 	"net",
+	"talks",
+	"exp",
 }
 
 // Put subRepos into defaultPackages.
@@ -42,7 +44,12 @@ func initHandler(w http.ResponseWriter, r *http.Request) {
 	c := appengine.NewContext(r)
 	defer cache.Tick(c)
 	for _, p := range defaultPackages {
-		if err := datastore.Get(c, p.Key(c), new(Package)); err == nil {
+		err := datastore.Get(c, p.Key(c), new(Package))
+		if _, ok := err.(*datastore.ErrFieldMismatch); ok {
+			// Some fields have been removed, so it's okay to ignore this error.
+			err = nil
+		}
+		if err == nil {
 			continue
 		} else if err != datastore.ErrNoSuchEntity {
 			logErr(w, r, err)
diff --git a/misc/dashboard/app/build/notify.go b/misc/dashboard/app/build/notify.go
index e02344c..52b91f6 100644
--- a/misc/dashboard/app/build/notify.go
+++ b/misc/dashboard/app/build/notify.go
@@ -21,6 +21,13 @@ const (
 	domain     = "build.golang.org"
 )
 
+// failIgnore is a set of builders that we don't email about because
+// they're too flaky.
+var failIgnore = map[string]bool{
+	"netbsd-386-bsiegert":   true,
+	"netbsd-amd64-bsiegert": true,
+}
+
 // notifyOnFailure checks whether the supplied Commit or the subsequent
 // Commit (if present) breaks the build for this builder.
 // If either of those commits break the build an email notification is sent
@@ -30,6 +37,10 @@ const (
 // This must be run in a datastore transaction, and the provided *Commit must
 // have been retrieved from the datastore within that transaction.
 func notifyOnFailure(c appengine.Context, com *Commit, builder string) error {
+	if failIgnore[builder] {
+		return nil
+	}
+
 	// TODO(adg): implement notifications for packages
 	if com.PackagePath != "" {
 		return nil
@@ -37,15 +48,15 @@ func notifyOnFailure(c appengine.Context, com *Commit, builder string) error {
 
 	p := &Package{Path: com.PackagePath}
 	var broken *Commit
-	ok, present := com.OK(builder, "")
-	if !present {
+	cr := com.Result(builder, "")
+	if cr == nil {
 		return fmt.Errorf("no result for %s/%s", com.Hash, builder)
 	}
 	q := datastore.NewQuery("Commit").Ancestor(p.Key(c))
-	if ok {
+	if cr.OK {
 		// This commit is OK. Notify if next Commit is broken.
 		next := new(Commit)
-		q.Filter("ParentHash=", com.Hash)
+		q = q.Filter("ParentHash=", com.Hash)
 		if err := firstMatch(c, q, next); err != nil {
 			if err == datastore.ErrNoSuchEntity {
 				// OK at tip, no notification necessary.
@@ -53,13 +64,15 @@ func notifyOnFailure(c appengine.Context, com *Commit, builder string) error {
 			}
 			return err
 		}
-		if ok, present := next.OK(builder, ""); present && !ok {
+		if nr := next.Result(builder, ""); nr != nil && !nr.OK {
+			c.Debugf("commit ok: %#v\nresult: %#v", com, cr)
+			c.Debugf("next commit broken: %#v\nnext result:%#v", next, nr)
 			broken = next
 		}
 	} else {
 		// This commit is broken. Notify if the previous Commit is OK.
 		prev := new(Commit)
-		q.Filter("Hash=", com.ParentHash)
+		q = q.Filter("Hash=", com.ParentHash)
 		if err := firstMatch(c, q, prev); err != nil {
 			if err == datastore.ErrNoSuchEntity {
 				// No previous result, let the backfill of
@@ -68,7 +81,9 @@ func notifyOnFailure(c appengine.Context, com *Commit, builder string) error {
 			}
 			return err
 		}
-		if ok, present := prev.OK(builder, ""); present && ok {
+		if pr := prev.Result(builder, ""); pr != nil && pr.OK {
+			c.Debugf("commit broken: %#v\nresult: %#v", com, cr)
+			c.Debugf("previous commit ok: %#v\nprevious result:%#v", prev, pr)
 			broken = com
 		}
 	}
diff --git a/misc/dashboard/app/build/test.go b/misc/dashboard/app/build/test.go
index d8470fe..7e55392 100644
--- a/misc/dashboard/app/build/test.go
+++ b/misc/dashboard/app/build/test.go
@@ -43,14 +43,15 @@ var testPackages = []*Package{
 
 var tCommitTime = time.Now().Add(-time.Hour * 24 * 7)
 
-func tCommit(hash, parentHash string) *Commit {
+func tCommit(hash, parentHash, path string) *Commit {
 	tCommitTime.Add(time.Hour) // each commit should have a different time
 	return &Commit{
-		Hash:       hash,
-		ParentHash: parentHash,
-		Time:       tCommitTime,
-		User:       "adg",
-		Desc:       "change description",
+		PackagePath: path,
+		Hash:        hash,
+		ParentHash:  parentHash,
+		Time:        tCommitTime,
+		User:        "adg",
+		Desc:        "change description " + hash,
 	}
 }
 
@@ -64,9 +65,9 @@ var testRequests = []struct {
 	{"/packages?kind=subrepo", nil, nil, []*Package{testPackage}},
 
 	// Go repo
-	{"/commit", nil, tCommit("0001", "0000"), nil},
-	{"/commit", nil, tCommit("0002", "0001"), nil},
-	{"/commit", nil, tCommit("0003", "0002"), nil},
+	{"/commit", nil, tCommit("0001", "0000", ""), nil},
+	{"/commit", nil, tCommit("0002", "0001", ""), nil},
+	{"/commit", nil, tCommit("0003", "0002", ""), nil},
 	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
 	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
 	{"/result", nil, &Result{Builder: "linux-386", Hash: "0001", OK: true}, nil},
@@ -81,12 +82,12 @@ var testRequests = []struct {
 	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0002"}}},
 
 	// branches
-	{"/commit", nil, tCommit("0004", "0003"), nil},
-	{"/commit", nil, tCommit("0005", "0002"), nil},
+	{"/commit", nil, tCommit("0004", "0003", ""), nil},
+	{"/commit", nil, tCommit("0005", "0002", ""), nil},
 	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0005"}}},
 	{"/result", nil, &Result{Builder: "linux-386", Hash: "0005", OK: true}, nil},
 	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0004"}}},
-	{"/result", nil, &Result{Builder: "linux-386", Hash: "0004", OK: true}, nil},
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0004", OK: false}, nil},
 	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
 
 	// logs
@@ -98,9 +99,9 @@ var testRequests = []struct {
 	{"/result", nil, &Result{Builder: "linux-386", Hash: "0003", OK: false, Log: "test"}, nil},
 
 	// non-Go repos
-	{"/commit", nil, &Commit{PackagePath: testPkg, Hash: "1001", ParentHash: "1000"}, nil},
-	{"/commit", nil, &Commit{PackagePath: testPkg, Hash: "1002", ParentHash: "1001"}, nil},
-	{"/commit", nil, &Commit{PackagePath: testPkg, Hash: "1003", ParentHash: "1002"}, nil},
+	{"/commit", nil, tCommit("1001", "1000", testPkg), nil},
+	{"/commit", nil, tCommit("1002", "1001", testPkg), nil},
+	{"/commit", nil, tCommit("1003", "1002", testPkg), nil},
 	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1003"}}},
 	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1003", GoHash: "0001", OK: true}, nil},
 	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1002"}}},
@@ -230,7 +231,7 @@ func testHandler(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 	}
-	fmt.Fprint(w, "PASS")
+	fmt.Fprint(w, "PASS\nYou should see only one mail notification (for 0003/linux-386) in the dev_appserver logs.")
 }
 
 func nukeEntities(c appengine.Context, kinds []string) error {
diff --git a/misc/dashboard/app/build/ui.go b/misc/dashboard/app/build/ui.go
index 0337aa3..cc3629a 100644
--- a/misc/dashboard/app/build/ui.go
+++ b/misc/dashboard/app/build/ui.go
@@ -97,7 +97,7 @@ type Pagination struct {
 func goCommits(c appengine.Context, page int) ([]*Commit, error) {
 	q := datastore.NewQuery("Commit").
 		Ancestor((&Package{}).Key(c)).
-		Order("-Time").
+		Order("-Num").
 		Limit(commitsPerPage).
 		Offset(page * commitsPerPage)
 	var commits []*Commit
@@ -211,6 +211,9 @@ func builderArch(s string) string {
 
 // builderArchShort returns a short arch tag for a builder string
 func builderArchShort(s string) string {
+	if s == "linux-amd64-race" {
+		return "race"
+	}
 	arch := builderArch(s)
 	switch arch {
 	case "amd64":
diff --git a/misc/dashboard/builder/Makefile b/misc/dashboard/builder/Makefile
index abf3755..4e4d408 100644
--- a/misc/dashboard/builder/Makefile
+++ b/misc/dashboard/builder/Makefile
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-gobuilder: $(shell ls *.go)
+builder: $(shell ls *.go)
 	go build -o $@ $^
 
 clean:
-	rm -f gobuilder
+	rm -f builder
diff --git a/misc/dashboard/builder/doc.go b/misc/dashboard/builder/doc.go
index 30d8fe9..5192861 100644
--- a/misc/dashboard/builder/doc.go
+++ b/misc/dashboard/builder/doc.go
@@ -4,15 +4,15 @@
 
 /*
 
-Go Builder is a continuous build client for the Go project. 
+Go Builder is a continuous build client for the Go project.
 It integrates with the Go Dashboard AppEngine application.
 
 Go Builder is intended to run continuously as a background process.
 
-It periodically pulls updates from the Go Mercurial repository. 
+It periodically pulls updates from the Go Mercurial repository.
 
 When a newer revision is found, Go Builder creates a clone of the repository,
-runs all.bash, and reports build success or failure to the Go Dashboard. 
+runs all.bash, and reports build success or failure to the Go Dashboard.
 
 For a release revision (a change description that matches "release.YYYY-MM-DD"),
 Go Builder will create a tar.gz archive of the GOROOT and deliver it to the
@@ -22,7 +22,7 @@ Usage:
 
   gobuilder goos-goarch...
 
-  Several goos-goarch combinations can be provided, and the builder will 
+  Several goos-goarch combinations can be provided, and the builder will
   build them in serial.
 
 Optional flags:
@@ -55,4 +55,4 @@ If the Google Code credentials are not provided the archival step
 will be skipped.
 
 */
-package documentation
+package main
diff --git a/misc/dashboard/builder/exec.go b/misc/dashboard/builder/exec.go
index 802d5f0..a4aabd2 100644
--- a/misc/dashboard/builder/exec.go
+++ b/misc/dashboard/builder/exec.go
@@ -6,14 +6,16 @@ package main
 
 import (
 	"bytes"
+	"fmt"
 	"io"
 	"log"
 	"os"
 	"os/exec"
+	"time"
 )
 
 // run is a simple wrapper for exec.Run/Close
-func run(envv []string, dir string, argv ...string) error {
+func run(timeout time.Duration, envv []string, dir string, argv ...string) error {
 	if *verbose {
 		log.Println("run", argv)
 	}
@@ -21,43 +23,57 @@ func run(envv []string, dir string, argv ...string) error {
 	cmd.Dir = dir
 	cmd.Env = envv
 	cmd.Stderr = os.Stderr
-	return cmd.Run()
+	if err := cmd.Start(); err != nil {
+		return err
+	}
+	return waitWithTimeout(timeout, cmd)
 }
 
-// runLog runs a process and returns the combined stdout/stderr, 
-// as well as writing it to logfile (if specified). It returns
-// process combined stdout and stderr output, exit status and error.
-// The error returned is nil, if process is started successfully,
-// even if exit status is not successful.
-func runLog(envv []string, logfile, dir string, argv ...string) (string, int, error) {
-	if *verbose {
-		log.Println("runLog", argv)
-	}
+// runLog runs a process and returns the combined stdout/stderr. It returns
+// process combined stdout and stderr output, exit status and error. The
+// error returned is nil, if process is started successfully, even if exit
+// status is not successful.
+func runLog(timeout time.Duration, envv []string, dir string, argv ...string) (string, bool, error) {
+	var b bytes.Buffer
+	ok, err := runOutput(timeout, envv, &b, dir, argv...)
+	return b.String(), ok, err
+}
 
-	b := new(bytes.Buffer)
-	var w io.Writer = b
-	if logfile != "" {
-		f, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
-		if err != nil {
-			return "", 0, err
-		}
-		defer f.Close()
-		w = io.MultiWriter(f, b)
+// runOutput runs a process and directs any output to the supplied writer.
+// It returns exit status and error. The error returned is nil, if process
+// is started successfully, even if exit status is not successful.
+func runOutput(timeout time.Duration, envv []string, out io.Writer, dir string, argv ...string) (bool, error) {
+	if *verbose {
+		log.Println("runOutput", argv)
 	}
 
 	cmd := exec.Command(argv[0], argv[1:]...)
 	cmd.Dir = dir
 	cmd.Env = envv
-	cmd.Stdout = w
-	cmd.Stderr = w
+	cmd.Stdout = out
+	cmd.Stderr = out
 
 	startErr := cmd.Start()
 	if startErr != nil {
-		return "", 1, startErr
+		return false, startErr
+	}
+	if err := waitWithTimeout(timeout, cmd); err != nil {
+		return false, err
 	}
-	exitStatus := 0
-	if err := cmd.Wait(); err != nil {
-		exitStatus = 1 // TODO(bradfitz): this is fake. no callers care, so just return a bool instead.
+	return true, nil
+}
+
+func waitWithTimeout(timeout time.Duration, cmd *exec.Cmd) error {
+	errc := make(chan error, 1)
+	go func() {
+		errc <- cmd.Wait()
+	}()
+	var err error
+	select {
+	case <-time.After(timeout):
+		cmd.Process.Kill()
+		err = fmt.Errorf("timed out after %v", timeout)
+	case err = <-errc:
 	}
-	return b.String(), exitStatus, nil
+	return err
 }
diff --git a/misc/dashboard/builder/http.go b/misc/dashboard/builder/http.go
index e50ae57..b50e845 100644
--- a/misc/dashboard/builder/http.go
+++ b/misc/dashboard/builder/http.go
@@ -56,8 +56,10 @@ func dash(meth, cmd string, args url.Values, req, resp interface{}) error {
 	if err != nil {
 		return err
 	}
-
 	defer r.Body.Close()
+	if r.StatusCode != http.StatusOK {
+		return fmt.Errorf("bad http response: %v", r.Status)
+	}
 	body := new(bytes.Buffer)
 	if _, err := body.ReadFrom(r.Body); err != nil {
 		return err
diff --git a/misc/dashboard/builder/main.go b/misc/dashboard/builder/main.go
index 85bb7ad..b2b8f43 100644
--- a/misc/dashboard/builder/main.go
+++ b/misc/dashboard/builder/main.go
@@ -6,16 +6,15 @@ package main
 
 import (
 	"bytes"
-	"encoding/xml"
 	"flag"
 	"fmt"
+	"io"
 	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
 	"regexp"
 	"runtime"
-	"strconv"
 	"strings"
 	"time"
 )
@@ -32,6 +31,7 @@ const (
 // These variables are copied from the gobuilder's environment
 // to the envv of its subprocesses.
 var extraEnv = []string{
+	"CC",
 	"GOARM",
 	"GOHOSTARCH",
 	"GOHOSTOS",
@@ -40,25 +40,27 @@ var extraEnv = []string{
 }
 
 type Builder struct {
+	goroot       *Repo
 	name         string
 	goos, goarch string
 	key          string
 }
 
 var (
-	buildroot     = flag.String("buildroot", filepath.Join(os.TempDir(), "gobuilder"), "Directory under which to build")
-	commitFlag    = flag.Bool("commit", false, "upload information about new commits")
-	dashboard     = flag.String("dashboard", "build.golang.org", "Go Dashboard Host")
-	buildRelease  = flag.Bool("release", false, "Build and upload binary release archives")
-	buildRevision = flag.String("rev", "", "Build specified revision and exit")
-	buildCmd      = flag.String("cmd", filepath.Join(".", allCmd), "Build command (specify relative to go/src/)")
-	failAll       = flag.Bool("fail", false, "fail all builds")
-	parallel      = flag.Bool("parallel", false, "Build multiple targets in parallel")
-	verbose       = flag.Bool("v", false, "verbose")
+	buildroot      = flag.String("buildroot", defaultBuildRoot(), "Directory under which to build")
+	dashboard      = flag.String("dashboard", "build.golang.org", "Go Dashboard Host")
+	buildRelease   = flag.Bool("release", false, "Build and upload binary release archives")
+	buildRevision  = flag.String("rev", "", "Build specified revision and exit")
+	buildCmd       = flag.String("cmd", filepath.Join(".", allCmd), "Build command (specify relative to go/src/)")
+	failAll        = flag.Bool("fail", false, "fail all builds")
+	parallel       = flag.Bool("parallel", false, "Build multiple targets in parallel")
+	buildTimeout   = flag.Duration("buildTimeout", 60*time.Minute, "Maximum time to wait for builds and tests")
+	cmdTimeout     = flag.Duration("cmdTimeout", 5*time.Minute, "Maximum time to wait for an external command")
+	commitInterval = flag.Duration("commitInterval", 1*time.Minute, "Time to wait between polling for new commits (0 disables commit poller)")
+	verbose        = flag.Bool("v", false, "verbose")
 )
 
 var (
-	goroot      string
 	binaryTagRe = regexp.MustCompile(`^(release\.r|weekly\.)[0-9\-.]+`)
 	releaseRe   = regexp.MustCompile(`^release\.r[0-9\-.]+`)
 	allCmd      = "all" + suffix
@@ -73,26 +75,15 @@ func main() {
 		os.Exit(2)
 	}
 	flag.Parse()
-	if len(flag.Args()) == 0 && !*commitFlag {
+	if len(flag.Args()) == 0 {
 		flag.Usage()
 	}
-	goroot = filepath.Join(*buildroot, "goroot")
-	builders := make([]*Builder, len(flag.Args()))
-	for i, builder := range flag.Args() {
-		b, err := NewBuilder(builder)
-		if err != nil {
-			log.Fatal(err)
-		}
-		builders[i] = b
-	}
-
-	if *failAll {
-		failMode(builders)
-		return
+	goroot := &Repo{
+		Path: filepath.Join(*buildroot, "goroot"),
 	}
 
 	// set up work environment, use existing enviroment if possible
-	if hgRepoExists(goroot) {
+	if goroot.Exists() || *failAll {
 		log.Print("Found old workspace, will use it")
 	} else {
 		if err := os.RemoveAll(*buildroot); err != nil {
@@ -101,22 +92,31 @@ func main() {
 		if err := os.Mkdir(*buildroot, mkdirPerm); err != nil {
 			log.Fatalf("Error making build root (%s): %s", *buildroot, err)
 		}
-		if err := hgClone(hgUrl, goroot); err != nil {
+		var err error
+		goroot, err = RemoteRepo(hgUrl).Clone(goroot.Path, "tip")
+		if err != nil {
 			log.Fatal("Error cloning repository:", err)
 		}
 	}
 
-	if *commitFlag {
-		if len(flag.Args()) == 0 {
-			commitWatcher()
-			return
+	// set up builders
+	builders := make([]*Builder, len(flag.Args()))
+	for i, name := range flag.Args() {
+		b, err := NewBuilder(goroot, name)
+		if err != nil {
+			log.Fatal(err)
 		}
-		go commitWatcher()
+		builders[i] = b
+	}
+
+	if *failAll {
+		failMode(builders)
+		return
 	}
 
 	// if specified, build revision and return
 	if *buildRevision != "" {
-		hash, err := fullHash(goroot, *buildRevision)
+		hash, err := goroot.FullHash(*buildRevision)
 		if err != nil {
 			log.Fatal("Error finding revision: ", err)
 		}
@@ -128,7 +128,10 @@ func main() {
 		return
 	}
 
-	// go continuous build mode (default)
+	// Start commit watcher
+	go commitWatcher(goroot)
+
+	// go continuous build mode
 	// check for new commits and build them
 	for {
 		built := false
@@ -175,15 +178,18 @@ func failMode(builders []*Builder) {
 	}
 }
 
-func NewBuilder(builder string) (*Builder, error) {
-	b := &Builder{name: builder}
+func NewBuilder(goroot *Repo, name string) (*Builder, error) {
+	b := &Builder{
+		goroot: goroot,
+		name:   name,
+	}
 
 	// get goos/goarch from builder string
-	s := strings.SplitN(builder, "-", 3)
+	s := strings.SplitN(b.name, "-", 3)
 	if len(s) >= 2 {
 		b.goos, b.goarch = s[0], s[1]
 	} else {
-		return nil, fmt.Errorf("unsupported builder form: %s", builder)
+		return nil, fmt.Errorf("unsupported builder form: %s", name)
 	}
 
 	// read keys from keyfile
@@ -206,7 +212,7 @@ func NewBuilder(builder string) (*Builder, error) {
 }
 
 // build checks for a new commit for this builder
-// and builds it if one is found. 
+// and builds it if one is found.
 // It returns true if a build was attempted.
 func (b *Builder) build() bool {
 	hash, err := b.todo("build-go-commit", "", "")
@@ -217,16 +223,8 @@ func (b *Builder) build() bool {
 	if hash == "" {
 		return false
 	}
-	// Look for hash locally before running hg pull.
-	if _, err := fullHash(goroot, hash[:12]); err != nil {
-		// Don't have hash, so run hg pull.
-		if err := run(nil, goroot, "hg", "pull"); err != nil {
-			log.Println("hg pull failed:", err)
-			return false
-		}
-	}
-	err = b.buildHash(hash)
-	if err != nil {
+
+	if err := b.buildHash(hash); err != nil {
 		log.Println(err)
 	}
 	return true
@@ -242,34 +240,49 @@ func (b *Builder) buildHash(hash string) error {
 	}
 	defer os.RemoveAll(workpath)
 
-	// clone repo
-	if err := run(nil, workpath, "hg", "clone", goroot, "go"); err != nil {
+	// pull before cloning to ensure we have the revision
+	if err := b.goroot.Pull(); err != nil {
 		return err
 	}
 
-	// update to specified revision
-	if err := run(nil, filepath.Join(workpath, "go"), "hg", "update", hash); err != nil {
+	// clone repo at specified revision
+	if _, err := b.goroot.Clone(filepath.Join(workpath, "go"), hash); err != nil {
 		return err
 	}
 
 	srcDir := filepath.Join(workpath, "go", "src")
 
 	// build
+	var buildlog bytes.Buffer
 	logfile := filepath.Join(workpath, "build.log")
+	f, err := os.Create(logfile)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+	w := io.MultiWriter(f, &buildlog)
+
 	cmd := *buildCmd
 	if !filepath.IsAbs(cmd) {
 		cmd = filepath.Join(srcDir, cmd)
 	}
 	startTime := time.Now()
-	buildLog, status, err := runLog(b.envv(), logfile, srcDir, cmd)
+	ok, err := runOutput(*buildTimeout, b.envv(), w, srcDir, cmd)
 	runTime := time.Now().Sub(startTime)
-	if err != nil {
-		return fmt.Errorf("%s: %s", *buildCmd, err)
+	errf := func() string {
+		if err != nil {
+			return fmt.Sprintf("error: %v", err)
+		}
+		if !ok {
+			return "failed"
+		}
+		return "success"
 	}
+	fmt.Fprintf(w, "Build complete, duration %v. Result: %v\n", runTime, errf())
 
-	if status != 0 {
+	if err != nil || !ok {
 		// record failure
-		return b.recordResult(false, "", hash, "", buildLog, runTime)
+		return b.recordResult(false, "", hash, "", buildlog.String(), runTime)
 	}
 
 	// record success
@@ -278,13 +291,15 @@ func (b *Builder) buildHash(hash string) error {
 	}
 
 	// build Go sub-repositories
-	b.buildSubrepos(filepath.Join(workpath, "go"), hash)
+	goRoot := filepath.Join(workpath, "go")
+	goPath := workpath
+	b.buildSubrepos(goRoot, goPath, hash)
 
 	return nil
 }
 
 // failBuild checks for a new commit for this builder
-// and fails it if one is found. 
+// and fails it if one is found.
 // It returns true if a build was "attempted".
 func (b *Builder) failBuild() bool {
 	hash, err := b.todo("build-go-commit", "", "")
@@ -304,7 +319,7 @@ func (b *Builder) failBuild() bool {
 	return true
 }
 
-func (b *Builder) buildSubrepos(goRoot, goHash string) {
+func (b *Builder) buildSubrepos(goRoot, goPath, goHash string) {
 	for _, pkg := range dashboardPackages("subrepo") {
 		// get the latest todo for this package
 		hash, err := b.todo("build-package", pkg, goHash)
@@ -320,7 +335,7 @@ func (b *Builder) buildSubrepos(goRoot, goHash string) {
 		if *verbose {
 			log.Printf("buildSubrepos %s: building %q", pkg, hash)
 		}
-		buildLog, err := b.buildSubrepo(goRoot, pkg, hash)
+		buildLog, err := b.buildSubrepo(goRoot, goPath, pkg, hash)
 		if err != nil {
 			if buildLog == "" {
 				buildLog = err.Error()
@@ -338,45 +353,39 @@ func (b *Builder) buildSubrepos(goRoot, goHash string) {
 
 // buildSubrepo fetches the given package, updates it to the specified hash,
 // and runs 'go test -short pkg/...'. It returns the build log and any error.
-func (b *Builder) buildSubrepo(goRoot, pkg, hash string) (string, error) {
-	goBin := filepath.Join(goRoot, "bin")
-	goTool := filepath.Join(goBin, "go")
-	env := append(b.envv(), "GOROOT="+goRoot)
+func (b *Builder) buildSubrepo(goRoot, goPath, pkg, hash string) (string, error) {
+	goTool := filepath.Join(goRoot, "bin", "go")
+	env := append(b.envv(), "GOROOT="+goRoot, "GOPATH="+goPath)
 
-	// add goBin to PATH
+	// add $GOROOT/bin and $GOPATH/bin to PATH
 	for i, e := range env {
 		const p = "PATH="
 		if !strings.HasPrefix(e, p) {
 			continue
 		}
-		env[i] = p + goBin + string(os.PathListSeparator) + e[len(p):]
+		sep := string(os.PathListSeparator)
+		env[i] = p + filepath.Join(goRoot, "bin") + sep + filepath.Join(goPath, "bin") + sep + e[len(p):]
 	}
 
 	// fetch package and dependencies
-	log, status, err := runLog(env, "", goRoot, goTool, "get", "-d", pkg)
-	if err == nil && status != 0 {
-		err = fmt.Errorf("go exited with status %d", status)
+	log, ok, err := runLog(*cmdTimeout, env, goPath, goTool, "get", "-d", pkg+"/...")
+	if err == nil && !ok {
+		err = fmt.Errorf("go exited with status 1")
 	}
 	if err != nil {
-		// 'go get -d' will fail for a subrepo because its top-level
-		// directory does not contain a go package. No matter, just
-		// check whether an hg directory exists and proceed.
-		hgDir := filepath.Join(goRoot, "src/pkg", pkg, ".hg")
-		if fi, e := os.Stat(hgDir); e != nil || !fi.IsDir() {
-			return log, err
-		}
+		return log, err
 	}
 
 	// hg update to the specified hash
-	pkgPath := filepath.Join(goRoot, "src/pkg", pkg)
-	if err := run(nil, pkgPath, "hg", "update", hash); err != nil {
+	repo := Repo{Path: filepath.Join(goPath, "src", pkg)}
+	if err := repo.UpdateTo(hash); err != nil {
 		return "", err
 	}
 
 	// test the package
-	log, status, err = runLog(env, "", goRoot, goTool, "test", "-short", pkg+"/...")
-	if err == nil && status != 0 {
-		err = fmt.Errorf("go exited with status %d", status)
+	log, ok, err = runLog(*buildTimeout, env, goPath, goTool, "test", "-short", pkg+"/...")
+	if err == nil && !ok {
+		err = fmt.Errorf("go exited with status 1")
 	}
 	return log, err
 }
@@ -449,9 +458,13 @@ func isFile(name string) bool {
 }
 
 // commitWatcher polls hg for new commits and tells the dashboard about them.
-func commitWatcher() {
+func commitWatcher(goroot *Repo) {
+	if *commitInterval == 0 {
+		log.Printf("commitInterval is %s, disabling commitWatcher", *commitInterval)
+		return
+	}
 	// Create builder just to get master key.
-	b, err := NewBuilder("mercurial-commit")
+	b, err := NewBuilder(goroot, "mercurial-commit")
 	if err != nil {
 		log.Fatal(err)
 	}
@@ -462,104 +475,46 @@ func commitWatcher() {
 			log.Printf("poll...")
 		}
 		// Main Go repository.
-		commitPoll(key, "")
+		commitPoll(goroot, "", key)
 		// Go sub-repositories.
 		for _, pkg := range dashboardPackages("subrepo") {
-			commitPoll(key, pkg)
+			pkgroot := &Repo{
+				Path: filepath.Join(*buildroot, pkg),
+			}
+			commitPoll(pkgroot, pkg, key)
 		}
 		if *verbose {
 			log.Printf("sleep...")
 		}
-		time.Sleep(60e9)
-	}
-}
-
-func hgClone(url, path string) error {
-	return run(nil, *buildroot, "hg", "clone", url, path)
-}
-
-func hgRepoExists(path string) bool {
-	fi, err := os.Stat(filepath.Join(path, ".hg"))
-	if err != nil {
-		return false
+		time.Sleep(*commitInterval)
 	}
-	return fi.IsDir()
-}
-
-// HgLog represents a single Mercurial revision.
-type HgLog struct {
-	Hash   string
-	Author string
-	Date   string
-	Desc   string
-	Parent string
-
-	// Internal metadata
-	added bool
 }
 
 // logByHash is a cache of all Mercurial revisions we know about,
 // indexed by full hash.
 var logByHash = map[string]*HgLog{}
 
-// xmlLogTemplate is a template to pass to Mercurial to make
-// hg log print the log in valid XML for parsing with xml.Unmarshal.
-const xmlLogTemplate = `
-	<Log>
-	<Hash>{node|escape}</Hash>
-	<Parent>{parent|escape}</Parent>
-	<Author>{author|escape}</Author>
-	<Date>{date|rfc3339date}</Date>
-	<Desc>{desc|escape}</Desc>
-	</Log>
-`
-
 // commitPoll pulls any new revisions from the hg server
 // and tells the server about them.
-func commitPoll(key, pkg string) {
-	pkgRoot := goroot
-
-	if pkg != "" {
-		pkgRoot = filepath.Join(*buildroot, pkg)
-		if !hgRepoExists(pkgRoot) {
-			if err := hgClone(repoURL(pkg), pkgRoot); err != nil {
-				log.Printf("%s: hg clone failed: %v", pkg, err)
-				if err := os.RemoveAll(pkgRoot); err != nil {
-					log.Printf("%s: %v", pkg, err)
-				}
-				return
+func commitPoll(repo *Repo, pkg, key string) {
+	if !repo.Exists() {
+		var err error
+		repo, err = RemoteRepo(repoURL(pkg)).Clone(repo.Path, "tip")
+		if err != nil {
+			log.Printf("%s: hg clone failed: %v", pkg, err)
+			if err := os.RemoveAll(repo.Path); err != nil {
+				log.Printf("%s: %v", pkg, err)
 			}
 		}
-	}
-
-	if err := run(nil, pkgRoot, "hg", "pull"); err != nil {
-		log.Printf("hg pull: %v", err)
 		return
 	}
 
-	const N = 50 // how many revisions to grab
-
-	data, _, err := runLog(nil, "", pkgRoot, "hg", "log",
-		"--encoding=utf-8",
-		"--limit="+strconv.Itoa(N),
-		"--template="+xmlLogTemplate,
-	)
+	logs, err := repo.Log() // repo.Log calls repo.Pull internally
 	if err != nil {
 		log.Printf("hg log: %v", err)
 		return
 	}
 
-	var logStruct struct {
-		Log []HgLog
-	}
-	err = xml.Unmarshal([]byte("<Top>"+data+"</Top>"), &logStruct)
-	if err != nil {
-		log.Printf("unmarshal hg log: %v", err)
-		return
-	}
-
-	logs := logStruct.Log
-
 	// Pass 1.  Fill in parents and add new log entries to logsByHash.
 	// Empty parent means take parent from next log entry.
 	// Non-empty parent has form 1234:hashhashhash; we want full hash.
@@ -568,7 +523,7 @@ func commitPoll(key, pkg string) {
 		if l.Parent == "" && i+1 < len(logs) {
 			l.Parent = logs[i+1].Hash
 		} else if l.Parent != "" {
-			l.Parent, _ = fullHash(pkgRoot, l.Parent)
+			l.Parent, _ = repo.FullHash(l.Parent)
 		}
 		if *verbose {
 			log.Printf("hg log %s: %s < %s\n", pkg, l.Hash, l.Parent)
@@ -580,8 +535,7 @@ func commitPoll(key, pkg string) {
 		}
 	}
 
-	for i := range logs {
-		l := &logs[i]
+	for _, l := range logs {
 		addCommit(pkg, l.Hash, key)
 	}
 }
@@ -625,28 +579,6 @@ func addCommit(pkg, hash, key string) bool {
 	return true
 }
 
-// fullHash returns the full hash for the given Mercurial revision.
-func fullHash(root, rev string) (string, error) {
-	s, _, err := runLog(nil, "", root,
-		"hg", "log",
-		"--encoding=utf-8",
-		"--rev="+rev,
-		"--limit=1",
-		"--template={node}",
-	)
-	if err != nil {
-		return "", nil
-	}
-	s = strings.TrimSpace(s)
-	if s == "" {
-		return "", fmt.Errorf("cannot find revision")
-	}
-	if len(s) != 40 {
-		return "", fmt.Errorf("hg returned invalid hash " + s)
-	}
-	return s, nil
-}
-
 var repoRe = regexp.MustCompile(`^code\.google\.com/p/([a-z0-9\-]+(\.[a-z0-9\-]+)?)(/[a-z0-9A-Z_.\-/]+)?$`)
 
 // repoURL returns the repository URL for the supplied import path.
@@ -668,6 +600,19 @@ func defaultSuffix() string {
 	return ".bash"
 }
 
+// defaultBuildRoot returns default buildroot directory.
+func defaultBuildRoot() string {
+	var d string
+	if runtime.GOOS == "windows" {
+		// will use c:\, otherwise absolute paths become too long
+		// during builder run, see http://golang.org/issue/3358.
+		d = `c:\`
+	} else {
+		d = os.TempDir()
+	}
+	return filepath.Join(d, "gobuilder")
+}
+
 func getenvOk(k string) (v string, ok bool) {
 	v = os.Getenv(k)
 	if v != "" {
diff --git a/misc/dashboard/builder/vcs.go b/misc/dashboard/builder/vcs.go
new file mode 100644
index 0000000..63198a3
--- /dev/null
+++ b/misc/dashboard/builder/vcs.go
@@ -0,0 +1,148 @@
+// 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 main
+
+import (
+	"encoding/xml"
+	"fmt"
+	"log"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"sync"
+)
+
+// Repo represents a mercurial repository.
+type Repo struct {
+	Path string
+	sync.Mutex
+}
+
+// RemoteRepo constructs a *Repo representing a remote repository.
+func RemoteRepo(url string) *Repo {
+	return &Repo{
+		Path: url,
+	}
+}
+
+// Clone clones the current Repo to a new destination
+// returning a new *Repo if successful.
+func (r *Repo) Clone(path, rev string) (*Repo, error) {
+	r.Lock()
+	defer r.Unlock()
+	if err := run(*cmdTimeout, nil, *buildroot, r.hgCmd("clone", "-r", rev, r.Path, path)...); err != nil {
+		return nil, err
+	}
+	return &Repo{
+		Path: path,
+	}, nil
+}
+
+// UpdateTo updates the working copy of this Repo to the
+// supplied revision.
+func (r *Repo) UpdateTo(hash string) error {
+	r.Lock()
+	defer r.Unlock()
+	return run(*cmdTimeout, nil, r.Path, r.hgCmd("update", hash)...)
+}
+
+// Exists reports whether this Repo represents a valid Mecurial repository.
+func (r *Repo) Exists() bool {
+	fi, err := os.Stat(filepath.Join(r.Path, ".hg"))
+	if err != nil {
+		return false
+	}
+	return fi.IsDir()
+}
+
+// Pull pulls changes from the default path, that is, the path
+// this Repo was cloned from.
+func (r *Repo) Pull() error {
+	r.Lock()
+	defer r.Unlock()
+	return run(*cmdTimeout, nil, r.Path, r.hgCmd("pull")...)
+}
+
+// Log returns the changelog for this repository.
+func (r *Repo) Log() ([]HgLog, error) {
+	if err := r.Pull(); err != nil {
+		return nil, err
+	}
+	const N = 50 // how many revisions to grab
+
+	r.Lock()
+	defer r.Unlock()
+	data, _, err := runLog(*cmdTimeout, nil, r.Path, r.hgCmd("log",
+		"--encoding=utf-8",
+		"--limit="+strconv.Itoa(N),
+		"--template="+xmlLogTemplate)...,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	var logStruct struct {
+		Log []HgLog
+	}
+	err = xml.Unmarshal([]byte("<Top>"+data+"</Top>"), &logStruct)
+	if err != nil {
+		log.Printf("unmarshal hg log: %v", err)
+		return nil, err
+	}
+	return logStruct.Log, nil
+}
+
+// FullHash returns the full hash for the given Mercurial revision.
+func (r *Repo) FullHash(rev string) (string, error) {
+	r.Lock()
+	defer r.Unlock()
+	s, _, err := runLog(*cmdTimeout, nil, r.Path,
+		r.hgCmd("log",
+			"--encoding=utf-8",
+			"--rev="+rev,
+			"--limit=1",
+			"--template={node}")...,
+	)
+	if err != nil {
+		return "", nil
+	}
+	s = strings.TrimSpace(s)
+	if s == "" {
+		return "", fmt.Errorf("cannot find revision")
+	}
+	if len(s) != 40 {
+		return "", fmt.Errorf("hg returned invalid hash " + s)
+	}
+	return s, nil
+}
+
+func (r *Repo) hgCmd(args ...string) []string {
+	return append([]string{"hg", "--config", "extensions.codereview=!"}, args...)
+}
+
+// HgLog represents a single Mercurial revision.
+type HgLog struct {
+	Hash   string
+	Author string
+	Date   string
+	Desc   string
+	Parent string
+
+	// Internal metadata
+	added bool
+}
+
+// xmlLogTemplate is a template to pass to Mercurial to make
+// hg log print the log in valid XML for parsing with xml.Unmarshal.
+const xmlLogTemplate = `
+        <Log>
+        <Hash>{node|escape}</Hash>
+        <Parent>{parent|escape}</Parent>
+        <Author>{author|escape}</Author>
+        <Date>{date|rfc3339date}</Date>
+        <Desc>{desc|escape}</Desc>
+        </Log>
+`
diff --git a/misc/dashboard/codereview/app.yaml b/misc/dashboard/codereview/app.yaml
new file mode 100644
index 0000000..372eca5
--- /dev/null
+++ b/misc/dashboard/codereview/app.yaml
@@ -0,0 +1,24 @@
+application: gocodereview
+version: 1
+runtime: go
+api_version: go1
+
+inbound_services:
+- mail
+
+handlers:
+- url: /static/(.*)
+  static_files: static/\1
+  upload: static/.*
+- url: /_ah/mail/.*
+  script: _go_app
+  login: admin
+- url: /_ah/queue/go/delay
+  script: _go_app
+  login: admin
+- url: /(gc|update-cl)
+  script: _go_app
+  login: admin
+- url: /.*
+  script: _go_app
+  login: required
diff --git a/misc/dashboard/codereview/cron.yaml b/misc/dashboard/codereview/cron.yaml
new file mode 100644
index 0000000..3d33d32
--- /dev/null
+++ b/misc/dashboard/codereview/cron.yaml
@@ -0,0 +1,4 @@
+cron:
+- description: GC
+  url: /gc
+  schedule: every 6 hours
diff --git a/misc/dashboard/codereview/dashboard/cl.go b/misc/dashboard/codereview/dashboard/cl.go
new file mode 100644
index 0000000..e150ea1
--- /dev/null
+++ b/misc/dashboard/codereview/dashboard/cl.go
@@ -0,0 +1,481 @@
+// 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 dashboard
+
+// This file handles operations on the CL entity kind.
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"html/template"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"regexp"
+	"sort"
+	"strings"
+	"time"
+
+	"appengine"
+	"appengine/datastore"
+	"appengine/taskqueue"
+	"appengine/urlfetch"
+	"appengine/user"
+)
+
+func init() {
+	http.HandleFunc("/assign", handleAssign)
+	http.HandleFunc("/update-cl", handleUpdateCL)
+}
+
+const codereviewBase = "http://codereview.appspot.com"
+const gobotBase = "http://research.swtch.com/gobot_codereview"
+
+var clRegexp = regexp.MustCompile(`\d+`)
+
+// CL represents a code review.
+type CL struct {
+	Number string // e.g. "5903061"
+	Closed bool
+	Owner  string // email address
+
+	Created, Modified time.Time
+
+	Description  []byte `datastore:",noindex"`
+	FirstLine    string `datastore:",noindex"`
+	LGTMs        []string
+	NotLGTMs     []string
+	LastUpdateBy string // author of most recent review message
+	LastUpdate   string `datastore:",noindex"` // first line of most recent review message
+
+	// Mail information.
+	Subject       string   `datastore:",noindex"`
+	Recipients    []string `datastore:",noindex"`
+	LastMessageID string   `datastore:",noindex"`
+
+	// These are person IDs (e.g. "rsc"); they may be empty
+	Author   string
+	Reviewer string
+}
+
+// Reviewed reports whether the reviewer has replied to the CL.
+// The heuristic is that the CL has been replied to if it is LGTMed
+// or if the last CL message was from the reviewer.
+func (cl *CL) Reviewed() bool {
+	if cl.LastUpdateBy == cl.Reviewer {
+		return true
+	}
+	if person := emailToPerson[cl.LastUpdateBy]; person != "" && person == cl.Reviewer {
+		return true
+	}
+	for _, who := range cl.LGTMs {
+		if who == cl.Reviewer {
+			return true
+		}
+	}
+	return false
+}
+
+// DisplayOwner returns the CL's owner, either as their email address
+// or the person ID if it's a reviewer. It is for display only.
+func (cl *CL) DisplayOwner() string {
+	if p, ok := emailToPerson[cl.Owner]; ok {
+		return p
+	}
+	return cl.Owner
+}
+
+func (cl *CL) FirstLineHTML() template.HTML {
+	s := template.HTMLEscapeString(cl.FirstLine)
+	// Embolden the package name.
+	if i := strings.Index(s, ":"); i >= 0 {
+		s = "<b>" + s[:i] + "</b>" + s[i:]
+	}
+	return template.HTML(s)
+}
+
+func formatEmails(e []string) template.HTML {
+	x := make([]string, len(e))
+	for i, s := range e {
+		s = template.HTMLEscapeString(s)
+		if !strings.Contains(s, "@") {
+			s = "<b>" + s + "</b>"
+		}
+		s = `<span class="email">` + s + "</span>"
+		x[i] = s
+	}
+	return template.HTML(strings.Join(x, ", "))
+}
+
+func (cl *CL) LGTMHTML() template.HTML {
+	return formatEmails(cl.LGTMs)
+}
+
+func (cl *CL) NotLGTMHTML() template.HTML {
+	return formatEmails(cl.NotLGTMs)
+}
+
+func (cl *CL) ModifiedAgo() string {
+	// Just the first non-zero unit.
+	units := [...]struct {
+		suffix string
+		unit   time.Duration
+	}{
+		{"d", 24 * time.Hour},
+		{"h", time.Hour},
+		{"m", time.Minute},
+		{"s", time.Second},
+	}
+	d := time.Now().Sub(cl.Modified)
+	for _, u := range units {
+		if d > u.unit {
+			return fmt.Sprintf("%d%s", d/u.unit, u.suffix)
+		}
+	}
+	return "just now"
+}
+
+func handleAssign(w http.ResponseWriter, r *http.Request) {
+	c := appengine.NewContext(r)
+
+	if r.Method != "POST" {
+		http.Error(w, "Bad method "+r.Method, 400)
+		return
+	}
+
+	u := user.Current(c)
+	person, ok := emailToPerson[u.Email]
+	if !ok {
+		http.Error(w, "Not allowed", http.StatusUnauthorized)
+		return
+	}
+
+	n, rev := r.FormValue("cl"), r.FormValue("r")
+	if !clRegexp.MatchString(n) {
+		c.Errorf("Bad CL %q", n)
+		http.Error(w, "Bad CL", 400)
+		return
+	}
+	if _, ok := preferredEmail[rev]; !ok && rev != "" {
+		c.Errorf("Unknown reviewer %q", rev)
+		http.Error(w, "Unknown reviewer", 400)
+		return
+	}
+
+	key := datastore.NewKey(c, "CL", n, 0, nil)
+
+	if rev != "" {
+		// Make sure the reviewer is listed in Rietveld as a reviewer.
+		url := codereviewBase + "/" + n + "/fields"
+		resp, err := urlfetch.Client(c).Get(url + "?field=reviewers")
+		if err != nil {
+			c.Errorf("Retrieving CL reviewer list failed: %v", err)
+			http.Error(w, err.Error(), 500)
+			return
+		}
+		defer resp.Body.Close()
+		if resp.StatusCode != 200 {
+			c.Errorf("Retrieving CL reviewer list failed: got HTTP response %d", resp.StatusCode)
+			http.Error(w, "Failed contacting Rietveld", 500)
+			return
+		}
+
+		var apiResp struct {
+			Reviewers []string `json:"reviewers"`
+		}
+		if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
+			// probably can't be retried
+			msg := fmt.Sprintf("Malformed JSON from %v: %v", url, err)
+			c.Errorf("%s", msg)
+			http.Error(w, msg, 500)
+			return
+		}
+		found := false
+		for _, r := range apiResp.Reviewers {
+			if emailToPerson[r] == rev {
+				found = true
+				break
+			}
+		}
+		if !found {
+			c.Infof("Adding %v as a reviewer of CL %v", rev, n)
+
+			url := fmt.Sprintf("%s?cl=%s&r=%s&obo=%s", gobotBase, n, rev, person)
+			resp, err := urlfetch.Client(c).Get(url)
+			if err != nil {
+				c.Errorf("Gobot GET failed: %v", err)
+				http.Error(w, err.Error(), 500)
+				return
+			}
+			defer resp.Body.Close()
+			if resp.StatusCode != 200 {
+				c.Errorf("Gobot GET failed: got HTTP response %d", resp.StatusCode)
+				http.Error(w, "Failed contacting Gobot", 500)
+				return
+			}
+
+			c.Infof("Gobot said %q", resp.Status)
+		}
+	}
+
+	// Update our own record.
+	err := datastore.RunInTransaction(c, func(c appengine.Context) error {
+		cl := new(CL)
+		err := datastore.Get(c, key, cl)
+		if err != nil {
+			return err
+		}
+		cl.Reviewer = rev
+		_, err = datastore.Put(c, key, cl)
+		return err
+	}, nil)
+	if err != nil {
+		msg := fmt.Sprintf("Assignment failed: %v", err)
+		c.Errorf("%s", msg)
+		http.Error(w, msg, 500)
+		return
+	}
+	c.Infof("Assigned CL %v to %v", n, rev)
+}
+
+func UpdateCLLater(c appengine.Context, n string, delay time.Duration) {
+	t := taskqueue.NewPOSTTask("/update-cl", url.Values{
+		"cl": []string{n},
+	})
+	t.Delay = delay
+	if _, err := taskqueue.Add(c, t, "update-cl"); err != nil {
+		c.Errorf("Failed adding task: %v", err)
+	}
+}
+
+func handleUpdateCL(w http.ResponseWriter, r *http.Request) {
+	c := appengine.NewContext(r)
+
+	n := r.FormValue("cl")
+	if !clRegexp.MatchString(n) {
+		c.Errorf("Bad CL %q", n)
+		http.Error(w, "Bad CL", 400)
+		return
+	}
+
+	if err := updateCL(c, n); err != nil {
+		c.Errorf("Failed updating CL %v: %v", n, err)
+		http.Error(w, "Failed update", 500)
+		return
+	}
+
+	io.WriteString(w, "OK")
+}
+
+// apiMessage describes the JSON sent back by Rietveld in the CL messages list.
+type apiMessage struct {
+	Date       string   `json:"date"`
+	Text       string   `json:"text"`
+	Sender     string   `json:"sender"`
+	Recipients []string `json:"recipients"`
+	Approval   bool     `json:"approval"`
+}
+
+// byDate implements sort.Interface to order the messages by date, earliest first.
+// The dates are sent in RFC 3339 format, so string comparison matches time value comparison.
+type byDate []*apiMessage
+
+func (x byDate) Len() int           { return len(x) }
+func (x byDate) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byDate) Less(i, j int) bool { return x[i].Date < x[j].Date }
+
+// updateCL updates a single CL. If a retryable failure occurs, an error is returned.
+func updateCL(c appengine.Context, n string) error {
+	c.Debugf("Updating CL %v", n)
+	key := datastore.NewKey(c, "CL", n, 0, nil)
+
+	url := codereviewBase + "/api/" + n + "?messages=true"
+	resp, err := urlfetch.Client(c).Get(url)
+	if err != nil {
+		return err
+	}
+	defer resp.Body.Close()
+
+	raw, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return fmt.Errorf("Failed reading HTTP body: %v", err)
+	}
+
+	// Special case for abandoned CLs.
+	if resp.StatusCode == 404 && bytes.Contains(raw, []byte("No issue exists with that id")) {
+		// Don't bother checking for errors. The CL might never have been saved, for instance.
+		datastore.Delete(c, key)
+		c.Infof("Deleted abandoned CL %v", n)
+		return nil
+	}
+
+	if resp.StatusCode != 200 {
+		return fmt.Errorf("Update: got HTTP response %d", resp.StatusCode)
+	}
+
+	var apiResp struct {
+		Description string        `json:"description"`
+		Reviewers   []string      `json:"reviewers"`
+		Created     string        `json:"created"`
+		OwnerEmail  string        `json:"owner_email"`
+		Modified    string        `json:"modified"`
+		Closed      bool          `json:"closed"`
+		Subject     string        `json:"subject"`
+		Messages    []*apiMessage `json:"messages"`
+	}
+	if err := json.Unmarshal(raw, &apiResp); err != nil {
+		// probably can't be retried
+		c.Errorf("Malformed JSON from %v: %v", url, err)
+		return nil
+	}
+	//c.Infof("RAW: %+v", apiResp)
+	sort.Sort(byDate(apiResp.Messages))
+
+	cl := &CL{
+		Number:      n,
+		Closed:      apiResp.Closed,
+		Owner:       apiResp.OwnerEmail,
+		Description: []byte(apiResp.Description),
+		FirstLine:   apiResp.Description,
+		Subject:     apiResp.Subject,
+		Author:      emailToPerson[apiResp.OwnerEmail],
+	}
+	cl.Created, err = time.Parse("2006-01-02 15:04:05.000000", apiResp.Created)
+	if err != nil {
+		c.Errorf("Bad creation time %q: %v", apiResp.Created, err)
+	}
+	cl.Modified, err = time.Parse("2006-01-02 15:04:05.000000", apiResp.Modified)
+	if err != nil {
+		c.Errorf("Bad modification time %q: %v", apiResp.Modified, err)
+	}
+	if i := strings.Index(cl.FirstLine, "\n"); i >= 0 {
+		cl.FirstLine = cl.FirstLine[:i]
+	}
+	// Treat zero reviewers as a signal that the CL is completed.
+	// This could be after the CL has been submitted, but before the CL author has synced,
+	// but it could also be a CL manually edited to remove reviewers.
+	if len(apiResp.Reviewers) == 0 {
+		cl.Closed = true
+	}
+
+	lgtm := make(map[string]bool)
+	notLGTM := make(map[string]bool)
+	rcpt := make(map[string]bool)
+	for _, msg := range apiResp.Messages {
+		s, rev := msg.Sender, false
+		if p, ok := emailToPerson[s]; ok {
+			s, rev = p, true
+		}
+
+		line := firstLine(msg.Text)
+		if line != "" {
+			cl.LastUpdateBy = msg.Sender
+			cl.LastUpdate = line
+		}
+
+		// CLs submitted by someone other than the CL owner do not immediately
+		// transition to "closed". Let's simulate the intention by treating
+		// messages starting with "*** Submitted as " from a reviewer as a
+		// signal that the CL is now closed.
+		if rev && strings.HasPrefix(msg.Text, "*** Submitted as ") {
+			cl.Closed = true
+		}
+
+		if msg.Approval {
+			lgtm[s] = true
+			delete(notLGTM, s) // "LGTM" overrules previous "NOT LGTM"
+		}
+		if strings.Contains(line, "NOT LGTM") {
+			notLGTM[s] = true
+			delete(lgtm, s) // "NOT LGTM" overrules previous "LGTM"
+		}
+
+		for _, r := range msg.Recipients {
+			rcpt[r] = true
+		}
+	}
+	for l := range lgtm {
+		cl.LGTMs = append(cl.LGTMs, l)
+	}
+	for l := range notLGTM {
+		cl.NotLGTMs = append(cl.NotLGTMs, l)
+	}
+	for r := range rcpt {
+		cl.Recipients = append(cl.Recipients, r)
+	}
+	sort.Strings(cl.LGTMs)
+	sort.Strings(cl.NotLGTMs)
+	sort.Strings(cl.Recipients)
+
+	err = datastore.RunInTransaction(c, func(c appengine.Context) error {
+		ocl := new(CL)
+		err := datastore.Get(c, key, ocl)
+		if err != nil && err != datastore.ErrNoSuchEntity {
+			return err
+		} else if err == nil {
+			// LastMessageID and Reviewer need preserving.
+			cl.LastMessageID = ocl.LastMessageID
+			cl.Reviewer = ocl.Reviewer
+		}
+		_, err = datastore.Put(c, key, cl)
+		return err
+	}, nil)
+	if err != nil {
+		return err
+	}
+	c.Infof("Updated CL %v", n)
+	return nil
+}
+
+// trailingSpaceRE matches trailing spaces.
+var trailingSpaceRE = regexp.MustCompile(`(?m)[ \t\r]+$`)
+
+// removeRE is the list of patterns to skip over at the beginning of a
+// message when looking for message text.
+var removeRE = regexp.MustCompile(`(?m-s)\A(` +
+	// Skip leading "Hello so-and-so," generated by codereview plugin.
+	`(Hello(.|\n)*?\n\n)` +
+
+	// Skip quoted text.
+	`|((On.*|.* writes|.* wrote):\n)` +
+	`|((>.*\n)+)` +
+
+	// Skip lines with no letters.
+	`|(([^A-Za-z]*\n)+)` +
+
+	// Skip links to comments and file info.
+	`|(http://codereview.*\n([^ ]+:[0-9]+:.*\n)?)` +
+	`|(File .*:\n)` +
+
+	`)`,
+)
+
+// firstLine returns the first interesting line of the message text.
+func firstLine(text string) string {
+	// Cut trailing spaces.
+	text = trailingSpaceRE.ReplaceAllString(text, "")
+
+	// Skip uninteresting lines.
+	for {
+		text = strings.TrimSpace(text)
+		m := removeRE.FindStringIndex(text)
+		if m == nil || m[0] != 0 {
+			break
+		}
+		text = text[m[1]:]
+	}
+
+	// Chop line at newline or else at 74 bytes.
+	i := strings.Index(text, "\n")
+	if i >= 0 {
+		text = text[:i]
+	}
+	if len(text) > 74 {
+		text = text[:70] + "..."
+	}
+	return text
+}
diff --git a/misc/dashboard/codereview/dashboard/front.go b/misc/dashboard/codereview/dashboard/front.go
new file mode 100644
index 0000000..c7b0f0f
--- /dev/null
+++ b/misc/dashboard/codereview/dashboard/front.go
@@ -0,0 +1,299 @@
+// 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 dashboard
+
+// This file handles the front page.
+
+import (
+	"bytes"
+	"html/template"
+	"io"
+	"net/http"
+	"strings"
+	"sync"
+	"time"
+
+	"appengine"
+	"appengine/datastore"
+	"appengine/user"
+)
+
+func init() {
+	http.HandleFunc("/", handleFront)
+	http.HandleFunc("/favicon.ico", http.NotFound)
+}
+
+// maximum number of active CLs to show in person-specific tables.
+const maxCLs = 100
+
+func handleFront(w http.ResponseWriter, r *http.Request) {
+	c := appengine.NewContext(r)
+
+	data := &frontPageData{
+		Reviewers: personList,
+		User:      user.Current(c).Email,
+		IsAdmin:   user.IsAdmin(c),
+	}
+	var currentPerson string
+	u := data.User
+	you := "you"
+	if e := r.FormValue("user"); e != "" {
+		u = e
+		you = e
+	}
+	currentPerson, data.UserIsReviewer = emailToPerson[u]
+	if !data.UserIsReviewer {
+		currentPerson = u
+	}
+
+	var wg sync.WaitGroup
+	errc := make(chan error, 10)
+	activeCLs := datastore.NewQuery("CL").
+		Filter("Closed =", false).
+		Order("-Modified")
+
+	tableFetch := func(index int, f func(tbl *clTable) error) {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			start := time.Now()
+			if err := f(&data.Tables[index]); err != nil {
+				errc <- err
+			}
+			data.Timing[index] = time.Now().Sub(start)
+		}()
+	}
+
+	data.Tables[0].Title = "CLs assigned to " + you + " for review"
+	if data.UserIsReviewer {
+		tableFetch(0, func(tbl *clTable) error {
+			q := activeCLs.Filter("Reviewer =", currentPerson).Limit(maxCLs)
+			tbl.Assignable = true
+			_, err := q.GetAll(c, &tbl.CLs)
+			return err
+		})
+	}
+
+	tableFetch(1, func(tbl *clTable) error {
+		q := activeCLs
+		if data.UserIsReviewer {
+			q = q.Filter("Author =", currentPerson)
+		} else {
+			q = q.Filter("Owner =", currentPerson)
+		}
+		q = q.Limit(maxCLs)
+		tbl.Title = "CLs sent by " + you
+		tbl.Assignable = true
+		_, err := q.GetAll(c, &tbl.CLs)
+		return err
+	})
+
+	tableFetch(2, func(tbl *clTable) error {
+		q := activeCLs.Limit(50)
+		tbl.Title = "Other active CLs"
+		tbl.Assignable = true
+		if _, err := q.GetAll(c, &tbl.CLs); err != nil {
+			return err
+		}
+		// filter
+		for i := len(tbl.CLs) - 1; i >= 0; i-- {
+			cl := tbl.CLs[i]
+			if cl.Owner == currentPerson || cl.Author == currentPerson || cl.Reviewer == currentPerson {
+				// Preserve order.
+				copy(tbl.CLs[i:], tbl.CLs[i+1:])
+				tbl.CLs = tbl.CLs[:len(tbl.CLs)-1]
+			}
+		}
+		return nil
+	})
+
+	tableFetch(3, func(tbl *clTable) error {
+		q := datastore.NewQuery("CL").
+			Filter("Closed =", true).
+			Order("-Modified").
+			Limit(10)
+		tbl.Title = "Recently closed CLs"
+		tbl.Assignable = false
+		_, err := q.GetAll(c, &tbl.CLs)
+		return err
+	})
+
+	// Not really a table fetch.
+	tableFetch(0, func(_ *clTable) error {
+		var err error
+		data.LogoutURL, err = user.LogoutURL(c, "/")
+		return err
+	})
+
+	wg.Wait()
+
+	select {
+	case err := <-errc:
+		c.Errorf("%v", err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	default:
+	}
+
+	var b bytes.Buffer
+	if err := frontPage.ExecuteTemplate(&b, "front", &data); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	io.Copy(w, &b)
+}
+
+type frontPageData struct {
+	Tables [4]clTable
+	Timing [4]time.Duration
+
+	Reviewers      []string
+	UserIsReviewer bool
+
+	User, LogoutURL string // actual logged in user
+	IsAdmin         bool
+}
+
+type clTable struct {
+	Title      string
+	Assignable bool
+	CLs        []*CL
+}
+
+var frontPage = template.Must(template.New("front").Funcs(template.FuncMap{
+	"selected": func(a, b string) string {
+		if a == b {
+			return "selected"
+		}
+		return ""
+	},
+	"shortemail": func(s string) string {
+		if i := strings.Index(s, "@"); i >= 0 {
+			s = s[:i]
+		}
+		return s
+	},
+}).Parse(`
+<!doctype html>
+<html>
+  <head>
+    <title>Go code reviews</title>
+    <link rel="icon" type="image/png" href="/static/icon.png" />
+    <style type="text/css">
+      body {
+        font-family: Helvetica, sans-serif;
+      }
+      img#gopherstamp {
+        float: right;
+	height: auto;
+	width: 250px;
+      }
+      h1, h2, h3 {
+        color: #777;
+	margin-bottom: 0;
+      }
+      table {
+        border-spacing: 0;
+      }
+      td {
+        vertical-align: top;
+        padding: 2px 5px;
+      }
+      tr.unreplied td.email {
+        border-left: 2px solid blue;
+      }
+      tr.pending td {
+        background: #fc8;
+      }
+      tr.failed td {
+        background: #f88;
+      }
+      tr.saved td {
+        background: #8f8;
+      }
+      .cls {
+        margin-top: 0;
+      }
+      a {
+        color: blue;
+	text-decoration: none;  /* no link underline */
+      }
+      address {
+        font-size: 10px;
+	text-align: right;
+      }
+      .email {
+        font-family: monospace;
+      }
+    </style>
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
+  <head>
+  <body>
+
+<img id="gopherstamp" src="/static/gopherstamp.jpg" />
+<h1>Go code reviews</h1>
+
+<table class="cls">
+{{range $i, $tbl := .Tables}}
+<tr><td colspan="5"><h3>{{$tbl.Title}}</h3></td></tr>
+{{if .CLs}}
+{{range $cl := .CLs}}
+  <tr id="cl-{{$cl.Number}}" class="{{if not $i}}{{if not .Reviewed}}unreplied{{end}}{{end}}">
+    <td class="email">{{$cl.DisplayOwner}}</td>
+    <td>
+    {{if $tbl.Assignable}}
+    <select id="cl-rev-{{$cl.Number}}" {{if not $.UserIsReviewer}}disabled{{end}}>
+      <option></option>
+      {{range $.Reviewers}}
+      <option {{selected . $cl.Reviewer}}>{{.}}</option>
+      {{end}}
+    </select>
+    <script type="text/javascript">
+    $(function() {
+      $('#cl-rev-{{$cl.Number}}').change(function() {
+        var r = $(this).val();
+        var row = $('tr#cl-{{$cl.Number}}');
+        row.addClass('pending');
+        $.post('/assign', {
+          'cl': '{{$cl.Number}}',
+          'r': r
+        }).success(function() {
+          row.removeClass('pending');
+          row.addClass('saved');
+        }).error(function() {
+          row.removeClass('pending');
+          row.addClass('failed');
+        });
+      });
+    });
+    </script>
+    {{end}}
+    </td>
+    <td>
+      <a href="http://codereview.appspot.com/{{.Number}}/" title="{{ printf "%s" .Description}}">{{.Number}}: {{.FirstLineHTML}}</a>
+      {{if and .LGTMs $tbl.Assignable}}<br /><span style="font-size: smaller;">LGTMs: {{.LGTMHTML}}</span>{{end}}
+      {{if and .NotLGTMs $tbl.Assignable}}<br /><span style="font-size: smaller; color: #f74545;">NOT LGTMs: {{.NotLGTMHTML}}</span>{{end}}
+      {{if .LastUpdateBy}}<br /><span style="font-size: smaller; color: #777777;">(<span title="{{.LastUpdateBy}}">{{.LastUpdateBy | shortemail}}</span>) {{.LastUpdate}}</span>{{end}}
+    </td>
+    <td title="Last modified">{{.ModifiedAgo}}</td>
+    <td>{{if $.IsAdmin}}<a href="/update-cl?cl={{.Number}}" title="Update this CL">&#x27f3;</a>{{end}}</td>
+  </tr>
+{{end}}
+{{else}}
+<tr><td colspan="5"><em>none</em></td></tr>
+{{end}}
+{{end}}
+</table>
+
+<hr />
+<address>
+You are <span class="email">{{.User}}</span> · <a href="{{.LogoutURL}}">logout</a><br />
+datastore timing: {{range .Timing}} {{.}}{{end}}
+</address>
+
+  </body>
+</html>
+`))
diff --git a/misc/dashboard/codereview/dashboard/gc.go b/misc/dashboard/codereview/dashboard/gc.go
new file mode 100644
index 0000000..a80b375
--- /dev/null
+++ b/misc/dashboard/codereview/dashboard/gc.go
@@ -0,0 +1,47 @@
+// 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 dashboard
+
+// This file handles garbage collection of old CLs.
+
+import (
+	"net/http"
+	"time"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+func init() {
+	http.HandleFunc("/gc", handleGC)
+}
+
+func handleGC(w http.ResponseWriter, r *http.Request) {
+	c := appengine.NewContext(r)
+
+	// Delete closed CLs that haven't been modified in 168 hours (7 days).
+	cutoff := time.Now().Add(-168 * time.Hour)
+	q := datastore.NewQuery("CL").
+		Filter("Closed =", true).
+		Filter("Modified <", cutoff).
+		Limit(100).
+		KeysOnly()
+	keys, err := q.GetAll(c, nil)
+	if err != nil {
+		c.Errorf("GetAll failed for old CLs: %v", err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	if len(keys) == 0 {
+		return
+	}
+
+	if err := datastore.DeleteMulti(c, keys); err != nil {
+		c.Errorf("DeleteMulti failed for old CLs: %v", err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	c.Infof("Deleted %d old CLs", len(keys))
+}
diff --git a/misc/dashboard/codereview/dashboard/mail.go b/misc/dashboard/codereview/dashboard/mail.go
new file mode 100644
index 0000000..838d082
--- /dev/null
+++ b/misc/dashboard/codereview/dashboard/mail.go
@@ -0,0 +1,68 @@
+// 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 dashboard
+
+// This file handles receiving mail.
+
+import (
+	"net/http"
+	"net/mail"
+	"regexp"
+	"time"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+func init() {
+	http.HandleFunc("/_ah/mail/", handleMail)
+}
+
+var subjectRegexp = regexp.MustCompile(`.*code review (\d+):.*`)
+
+func handleMail(w http.ResponseWriter, r *http.Request) {
+	c := appengine.NewContext(r)
+
+	defer r.Body.Close()
+	msg, err := mail.ReadMessage(r.Body)
+	if err != nil {
+		c.Errorf("mail.ReadMessage: %v", err)
+		return
+	}
+
+	subj := msg.Header.Get("Subject")
+	m := subjectRegexp.FindStringSubmatch(subj)
+	if len(m) != 2 {
+		c.Debugf("Subject %q did not match /%v/", subj, subjectRegexp)
+		return
+	}
+
+	c.Infof("Found issue %q", m[1])
+
+	// Track the MessageID.
+	key := datastore.NewKey(c, "CL", m[1], 0, nil)
+	err = datastore.RunInTransaction(c, func(c appengine.Context) error {
+		cl := new(CL)
+		err := datastore.Get(c, key, cl)
+		if err != nil && err != datastore.ErrNoSuchEntity {
+			return err
+		}
+		if err == datastore.ErrNoSuchEntity {
+			// Must set sentinel values for time.Time fields
+			// if this is a new entity.
+			cl.Created = time.Unix(0, 0)
+			cl.Modified = time.Unix(0, 0)
+		}
+		cl.LastMessageID = msg.Header.Get("Message-ID")
+		_, err = datastore.Put(c, key, cl)
+		return err
+	}, nil)
+	if err != nil {
+		c.Errorf("datastore transaction failed: %v", err)
+	}
+
+	// Update the CL after a delay to give Rietveld a chance to catch up.
+	UpdateCLLater(c, m[1], 10*time.Second)
+}
diff --git a/misc/dashboard/codereview/dashboard/people.go b/misc/dashboard/codereview/dashboard/people.go
new file mode 100644
index 0000000..facda7b
--- /dev/null
+++ b/misc/dashboard/codereview/dashboard/people.go
@@ -0,0 +1,42 @@
+// 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 dashboard
+
+// This file handles identities of people.
+
+import (
+	"sort"
+)
+
+var (
+	emailToPerson  = make(map[string]string) // email => person
+	preferredEmail = make(map[string]string) // person => email
+	personList     []string
+)
+
+func init() {
+	// People we assume have golang.org and google.com accounts,
+	// and prefer to use their golang.org address for code review.
+	gophers := [...]string{
+		"adg",
+		"bradfitz",
+		"campoy",
+		"dsymonds",
+		"gri",
+		"iant",
+		"nigeltao",
+		"r",
+		"rsc",
+		"sameer",
+	}
+	for _, p := range gophers {
+		personList = append(personList, p)
+		emailToPerson[p+"@golang.org"] = p
+		emailToPerson[p+"@google.com"] = p
+		preferredEmail[p] = p + "@golang.org"
+	}
+
+	sort.Strings(personList)
+}
diff --git a/misc/dashboard/codereview/index.yaml b/misc/dashboard/codereview/index.yaml
new file mode 100644
index 0000000..a87073c
--- /dev/null
+++ b/misc/dashboard/codereview/index.yaml
@@ -0,0 +1,25 @@
+indexes:
+
+- kind: CL
+  properties:
+  - name: Author
+  - name: Modified
+    direction: desc
+
+- kind: CL
+  properties:
+  - name: Owner
+  - name: Modified
+    direction: desc
+
+- kind: CL
+  properties:
+  - name: Closed
+  - name: Modified
+    direction: desc
+
+- kind: CL
+  properties:
+  - name: Reviewer
+  - name: Modified
+    direction: desc
diff --git a/misc/dashboard/codereview/queue.yaml b/misc/dashboard/codereview/queue.yaml
new file mode 100644
index 0000000..1a35fac
--- /dev/null
+++ b/misc/dashboard/codereview/queue.yaml
@@ -0,0 +1,4 @@
+queue:
+- name: update-cl
+  rate: 12/m
+  bucket_size: 1
diff --git a/misc/dashboard/codereview/static/gopherstamp.jpg b/misc/dashboard/codereview/static/gopherstamp.jpg
new file mode 100644
index 0000000..b17f3c8
Binary files /dev/null and b/misc/dashboard/codereview/static/gopherstamp.jpg differ
diff --git a/misc/dashboard/codereview/static/icon.png b/misc/dashboard/codereview/static/icon.png
new file mode 100644
index 0000000..c929ac8
Binary files /dev/null and b/misc/dashboard/codereview/static/icon.png differ
diff --git a/misc/dist/bindist.go b/misc/dist/bindist.go
index 16193bd..29454c7 100644
--- a/misc/dist/bindist.go
+++ b/misc/dist/bindist.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // This is a tool for packaging binary releases.
-// It supports FreeBSD, Linux, OS X, and Windows.
+// It supports FreeBSD, Linux, NetBSD, OS X, and Windows.
 package main
 
 import (
@@ -13,7 +13,6 @@ import (
 	"bytes"
 	"compress/gzip"
 	"encoding/base64"
-	"errors"
 	"flag"
 	"fmt"
 	"io"
@@ -30,8 +29,9 @@ import (
 )
 
 var (
-	tag      = flag.String("tag", "weekly", "mercurial tag to check out")
+	tag      = flag.String("tag", "release", "mercurial tag to check out")
 	repo     = flag.String("repo", "https://code.google.com/p/go", "repo URL")
+	tourPath = flag.String("tour", "code.google.com/p/go-tour", "Go tour repo import path")
 	verbose  = flag.Bool("v", false, "verbose output")
 	upload   = flag.Bool("upload", true, "upload resulting files to Google Code")
 	wxsFile  = flag.String("wxs", "", "path to custom installer.wxs")
@@ -41,8 +41,7 @@ var (
 )
 
 const (
-	packageMaker = "/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker"
-	uploadURL    = "https://go.googlecode.com/files"
+	uploadURL = "https://go.googlecode.com/files"
 )
 
 var preBuildCleanFiles = []string{
@@ -66,6 +65,20 @@ var sourceCleanFiles = []string{
 	"pkg",
 }
 
+var tourPackages = []string{
+	"pic",
+	"tree",
+	"wc",
+}
+
+var tourContent = []string{
+	"prog",
+	"solutions",
+	"static",
+	"template",
+	"tour.article",
+}
+
 var fileRe = regexp.MustCompile(`^go\.([a-z0-9-.]+)\.(src|([a-z0-9]+)-([a-z0-9]+))\.`)
 
 func main() {
@@ -129,6 +142,7 @@ type Build struct {
 	OS     string
 	Arch   string
 	root   string
+	gopath string
 }
 
 func (b *Build) Do() error {
@@ -138,6 +152,7 @@ func (b *Build) Do() error {
 	}
 	defer os.RemoveAll(work)
 	b.root = filepath.Join(work, "go")
+	b.gopath = work
 
 	// Clone Go distribution and update to tag.
 	_, err = b.run(work, "hg", "clone", "-q", *repo, b.root)
@@ -173,6 +188,10 @@ func (b *Build) Do() error {
 		return err
 	}
 
+	if err := b.tour(); err != nil {
+		return err
+	}
+
 	// Get version strings.
 	var (
 		version     string // "weekly.2012-03-04"
@@ -211,19 +230,31 @@ func (b *Build) Do() error {
 	}
 
 	// Create packages.
-	base := fmt.Sprintf("go.%s.%s-%s", version, b.OS, b.Arch)
+	base := fmt.Sprintf("%s.%s-%s", version, b.OS, b.Arch)
+	if !strings.HasPrefix(base, "go") {
+		base = "go." + base
+	}
 	var targs []string
 	switch b.OS {
-	case "linux", "freebsd", "":
+	case "linux", "freebsd", "netbsd", "":
 		// build tarball
 		targ := base
 		if b.Source {
-			targ = fmt.Sprintf("go.%s.src", version)
+			targ = fmt.Sprintf("%s.src", version)
+			if !strings.HasPrefix(targ, "go") {
+				targ = "go." + targ
+			}
 		}
 		targ += ".tar.gz"
 		err = makeTar(targ, work)
 		targs = append(targs, targ)
 	case "darwin":
+		// build tarball
+		targ := base + ".tar.gz"
+		err = makeTar(targ, work)
+		targs = append(targs, targ)
+
+		// build pkg
 		// arrange work so it's laid out as the dest filesystem
 		etc := filepath.Join(b.root, "misc/dist/darwin/etc")
 		_, err = b.run(work, "cp", "-r", etc, ".")
@@ -231,7 +262,7 @@ func (b *Build) Do() error {
 			return err
 		}
 		localDir := filepath.Join(work, "usr/local")
-		err = os.MkdirAll(localDir, 0744)
+		err = os.MkdirAll(localDir, 0755)
 		if err != nil {
 			return err
 		}
@@ -240,23 +271,30 @@ func (b *Build) Do() error {
 			return err
 		}
 		// build package
-		pm := packageMaker
-		if !exists(pm) {
-			pm = "/Developer" + pm
-			if !exists(pm) {
-				return errors.New("couldn't find PackageMaker")
-			}
+		pkgdest, err := ioutil.TempDir("", "pkgdest")
+		if err != nil {
+			return err
 		}
-		targ := base + ".pkg"
-		scripts := filepath.Join(work, "usr/local/go/misc/dist/darwin/scripts")
-		_, err = b.run("", pm, "-v",
-			"-r", work,
-			"-o", targ,
-			"--scripts", scripts,
-			"--id", "com.googlecode.go",
-			"--title", "Go",
+		defer os.RemoveAll(pkgdest)
+		dist := filepath.Join(runtime.GOROOT(), "misc/dist")
+		_, err = b.run("", "pkgbuild",
+			"--identifier", "com.googlecode.go",
 			"--version", "1.0",
-			"--target", "10.6")
+			"--scripts", filepath.Join(dist, "darwin/scripts"),
+			"--root", work,
+			filepath.Join(pkgdest, "com.googlecode.go.pkg"))
+		if err != nil {
+			return err
+		}
+		targ = base + ".pkg"
+		_, err = b.run("", "productbuild",
+			"--distribution", filepath.Join(dist, "darwin/Distribution"),
+			"--resources", filepath.Join(dist, "darwin/Resources"),
+			"--package-path", pkgdest,
+			targ)
+		if err != nil {
+			return err
+		}
 		targs = append(targs, targ)
 	case "windows":
 		// Create ZIP file.
@@ -327,6 +365,33 @@ func (b *Build) Do() error {
 	return err
 }
 
+func (b *Build) tour() error {
+	// go get the gotour package.
+	_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"), "get", *tourPath+"/gotour")
+	if err != nil {
+		return err
+	}
+
+	// Copy all the tour content to $GOROOT/misc/tour.
+	importPath := filepath.FromSlash(*tourPath)
+	tourSrc := filepath.Join(b.gopath, "src", importPath)
+	contentDir := filepath.Join(b.root, "misc", "tour")
+	if err = cpAllDir(contentDir, tourSrc, tourContent...); err != nil {
+		return err
+	}
+
+	// Copy the tour source code so it's accessible with $GOPATH pointing to $GOROOT/misc/tour.
+	if err = cpAllDir(filepath.Join(contentDir, "src", importPath), tourSrc, tourPackages...); err != nil {
+		return err
+	}
+
+	// Copy gotour binary to tool directory as "tour"; invoked as "go tool tour".
+	return cp(
+		filepath.Join(b.root, "pkg", "tool", b.OS+"_"+b.Arch, "tour"),
+		filepath.Join(b.gopath, "bin", "gotour"),
+	)
+}
+
 func (b *Build) run(dir, name string, args ...string) ([]byte, error) {
 	buf := new(bytes.Buffer)
 	absName, err := lookPath(name)
@@ -358,6 +423,7 @@ var cleanEnv = []string{
 	"GOOS",
 	"GOROOT",
 	"GOROOT_FINAL",
+	"GOPATH",
 }
 
 func (b *Build) env() []string {
@@ -380,6 +446,7 @@ func (b *Build) env() []string {
 		"GOOS="+b.OS,
 		"GOROOT="+b.root,
 		"GOROOT_FINAL="+final,
+		"GOPATH="+b.gopath,
 	)
 	return env
 }
@@ -390,42 +457,51 @@ func (b *Build) Upload(version string, filename string) error {
 	os_, arch := b.OS, b.Arch
 	switch b.Arch {
 	case "386":
-		arch = "32-bit"
+		arch = "x86 32-bit"
 	case "amd64":
-		arch = "64-bit"
+		arch = "x86 64-bit"
 	}
 	if arch != "" {
 		labels = append(labels, "Arch-"+b.Arch)
 	}
+	var opsys, ftype string // labels
 	switch b.OS {
 	case "linux":
 		os_ = "Linux"
-		labels = append(labels, "Type-Archive", "OpSys-Linux")
+		opsys = "Linux"
 	case "freebsd":
 		os_ = "FreeBSD"
-		labels = append(labels, "Type-Archive", "OpSys-FreeBSD")
+		opsys = "FreeBSD"
 	case "darwin":
 		os_ = "Mac OS X"
-		labels = append(labels, "Type-Installer", "OpSys-OSX")
+		opsys = "OSX"
+	case "netbsd":
+		os_ = "NetBSD"
+		opsys = "NetBSD"
 	case "windows":
 		os_ = "Windows"
-		labels = append(labels, "OpSys-Windows")
+		opsys = "Windows"
 	}
 	summary := fmt.Sprintf("%s %s (%s)", version, os_, arch)
-	if b.OS == "windows" {
-		switch {
-		case strings.HasSuffix(filename, ".msi"):
-			labels = append(labels, "Type-Installer")
-			summary += " MSI installer"
-		case strings.HasSuffix(filename, ".zip"):
-			labels = append(labels, "Type-Archive")
-			summary += " ZIP archive"
-		}
+	switch {
+	case strings.HasSuffix(filename, ".msi"):
+		ftype = "Installer"
+		summary += " MSI installer"
+	case strings.HasSuffix(filename, ".pkg"):
+		ftype = "Installer"
+		summary += " PKG installer"
+	case strings.HasSuffix(filename, ".zip"):
+		ftype = "Archive"
+		summary += " ZIP archive"
+	case strings.HasSuffix(filename, ".tar.gz"):
+		ftype = "Archive"
+		summary += " tarball"
 	}
 	if b.Source {
-		labels = append(labels, "Type-Source")
+		ftype = "Source"
 		summary = fmt.Sprintf("%s (source only)", version)
 	}
+	labels = append(labels, "OpSys-"+opsys, "Type-"+ftype)
 	if *addLabel != "" {
 		labels = append(labels, *addLabel)
 	}
@@ -535,15 +611,45 @@ func cp(dst, src string) error {
 		return err
 	}
 	defer sf.Close()
+	fi, err := sf.Stat()
+	if err != nil {
+		return err
+	}
 	df, err := os.Create(dst)
 	if err != nil {
 		return err
 	}
 	defer df.Close()
+	if err := df.Chmod(fi.Mode()); err != nil {
+		return err
+	}
 	_, err = io.Copy(df, sf)
 	return err
 }
 
+func cpDir(dst, src string) error {
+	walk := func(srcPath string, info os.FileInfo, err error) error {
+		if err != nil {
+			return err
+		}
+		dstPath := filepath.Join(dst, srcPath[len(src):])
+		if info.IsDir() {
+			return os.MkdirAll(dstPath, 0755)
+		}
+		return cp(dstPath, srcPath)
+	}
+	return filepath.Walk(src, walk)
+}
+
+func cpAllDir(dst, basePath string, dirs ...string) error {
+	for _, dir := range dirs {
+		if err := cpDir(filepath.Join(dst, dir), filepath.Join(basePath, dir)); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
 func makeTar(targ, workdir string) error {
 	f, err := os.Create(targ)
 	if err != nil {
@@ -552,7 +658,7 @@ func makeTar(targ, workdir string) error {
 	zout := gzip.NewWriter(f)
 	tw := tar.NewWriter(zout)
 
-	filepath.Walk(workdir, filepath.WalkFunc(func(path string, fi os.FileInfo, err error) error {
+	err = filepath.Walk(workdir, func(path string, fi os.FileInfo, err error) error {
 		if !strings.HasPrefix(path, workdir) {
 			log.Panicf("walked filename %q doesn't begin with workdir %q", path, workdir)
 		}
@@ -570,10 +676,8 @@ func makeTar(targ, workdir string) error {
 		if *verbose {
 			log.Printf("adding to tar: %s", name)
 		}
-		if fi.IsDir() {
-			return nil
-		}
-		hdr, err := tarFileInfoHeader(fi, path)
+		target, _ := os.Readlink(path)
+		hdr, err := tar.FileInfoHeader(fi, target)
 		if err != nil {
 			return err
 		}
@@ -594,6 +698,9 @@ func makeTar(targ, workdir string) error {
 		if err != nil {
 			return fmt.Errorf("Error writing file %q: %v", name, err)
 		}
+		if fi.IsDir() {
+			return nil
+		}
 		r, err := os.Open(path)
 		if err != nil {
 			return err
@@ -601,8 +708,10 @@ func makeTar(targ, workdir string) error {
 		defer r.Close()
 		_, err = io.Copy(tw, r)
 		return err
-	}))
-
+	})
+	if err != nil {
+		return err
+	}
 	if err := tw.Close(); err != nil {
 		return err
 	}
@@ -619,10 +728,7 @@ func makeZip(targ, workdir string) error {
 	}
 	zw := zip.NewWriter(f)
 
-	filepath.Walk(workdir, filepath.WalkFunc(func(path string, fi os.FileInfo, err error) error {
-		if fi.IsDir() {
-			return nil
-		}
+	err = filepath.Walk(workdir, func(path string, fi os.FileInfo, err error) error {
 		if !strings.HasPrefix(path, workdir) {
 			log.Panicf("walked filename %q doesn't begin with workdir %q", path, workdir)
 		}
@@ -649,10 +755,17 @@ func makeZip(targ, workdir string) error {
 		}
 		fh.Name = name
 		fh.Method = zip.Deflate
+		if fi.IsDir() {
+			fh.Name += "/"        // append trailing slash
+			fh.Method = zip.Store // no need to deflate 0 byte files
+		}
 		w, err := zw.CreateHeader(fh)
 		if err != nil {
 			return err
 		}
+		if fi.IsDir() {
+			return nil
+		}
 		r, err := os.Open(path)
 		if err != nil {
 			return err
@@ -660,8 +773,10 @@ func makeZip(targ, workdir string) error {
 		defer r.Close()
 		_, err = io.Copy(w, r)
 		return err
-	}))
-
+	})
+	if err != nil {
+		return err
+	}
 	if err := zw.Close(); err != nil {
 		return err
 	}
@@ -733,64 +848,3 @@ func lookPath(prog string) (absPath string, err error) {
 	}
 	return
 }
-
-// sysStat, if non-nil, populates h from system-dependent fields of fi.
-var sysStat func(fi os.FileInfo, h *tar.Header) error
-
-// Mode constants from the tar spec.
-const (
-	c_ISDIR  = 040000
-	c_ISFIFO = 010000
-	c_ISREG  = 0100000
-	c_ISLNK  = 0120000
-	c_ISBLK  = 060000
-	c_ISCHR  = 020000
-	c_ISSOCK = 0140000
-)
-
-// tarFileInfoHeader creates a partially-populated Header from an os.FileInfo.
-// The filename parameter is used only in the case of symlinks, to call os.Readlink.
-// If fi is a symlink but filename is empty, an error is returned.
-func tarFileInfoHeader(fi os.FileInfo, filename string) (*tar.Header, error) {
-	h := &tar.Header{
-		Name:    fi.Name(),
-		ModTime: fi.ModTime(),
-		Mode:    int64(fi.Mode().Perm()), // or'd with c_IS* constants later
-	}
-	switch {
-	case fi.Mode()&os.ModeType == 0:
-		h.Mode |= c_ISREG
-		h.Typeflag = tar.TypeReg
-		h.Size = fi.Size()
-	case fi.IsDir():
-		h.Typeflag = tar.TypeDir
-		h.Mode |= c_ISDIR
-	case fi.Mode()&os.ModeSymlink != 0:
-		h.Typeflag = tar.TypeSymlink
-		h.Mode |= c_ISLNK
-		if filename == "" {
-			return h, fmt.Errorf("archive/tar: unable to populate Header.Linkname of symlinks")
-		}
-		targ, err := os.Readlink(filename)
-		if err != nil {
-			return h, err
-		}
-		h.Linkname = targ
-	case fi.Mode()&os.ModeDevice != 0:
-		if fi.Mode()&os.ModeCharDevice != 0 {
-			h.Mode |= c_ISCHR
-			h.Typeflag = tar.TypeChar
-		} else {
-			h.Mode |= c_ISBLK
-			h.Typeflag = tar.TypeBlock
-		}
-	case fi.Mode()&os.ModeSocket != 0:
-		h.Mode |= c_ISSOCK
-	default:
-		return nil, fmt.Errorf("archive/tar: unknown file mode %v", fi.Mode())
-	}
-	if sysStat != nil {
-		return h, sysStat(fi, h)
-	}
-	return h, nil
-}
diff --git a/misc/dist/darwin/Distribution b/misc/dist/darwin/Distribution
new file mode 100644
index 0000000..8b764b6
--- /dev/null
+++ b/misc/dist/darwin/Distribution
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<installer-script minSpecVersion="1.000000">
+    <title>Go</title>
+    <background mime-type="image/png" file="bg.png"/>
+    <options customize="never" allow-external-scripts="no"/>
+    <domains enable_localSystem="true" />
+    <installation-check script="installCheck();"/>
+    <script>
+function installCheck() {
+    if(!(system.compareVersions(system.version.ProductVersion, '10.6.0') >= 0)) {
+        my.result.title = 'Unable to install';
+        my.result.message = 'Go requires Mac OS X 10.6 or later.';
+        my.result.type = 'Fatal';
+        return false;
+    }
+    if(system.files.fileExistsAtPath('/usr/local/go/bin/go')) {
+	    my.result.title = 'Previous Installation Detected';
+	    my.result.message = 'A previous installation of Go exists at /usr/local/go. This installer will remove the previous installation prior to installing. Please back up any data before proceeding.';
+	    my.result.type = 'Warning';
+	    return false;
+	}
+    return true;    
+}
+    </script>
+    <choices-outline>
+        <line choice="com.googlecode.go.choice"/>
+    </choices-outline>
+    <choice id="com.googlecode.go.choice" title="Go">
+        <pkg-ref id="com.googlecode.go.pkg"/>
+    </choice>
+    <pkg-ref id="com.googlecode.go.pkg" auth="Root">com.googlecode.go.pkg</pkg-ref>
+</installer-script>
diff --git a/misc/dist/darwin/Resources/bg.png b/misc/dist/darwin/Resources/bg.png
new file mode 100644
index 0000000..c3d8ea9
Binary files /dev/null and b/misc/dist/darwin/Resources/bg.png differ
diff --git a/misc/dist/darwin/scripts/postinstall b/misc/dist/darwin/scripts/postinstall
old mode 100644
new mode 100755
index 3748721..4410a30
--- a/misc/dist/darwin/scripts/postinstall
+++ b/misc/dist/darwin/scripts/postinstall
@@ -9,14 +9,9 @@ find bin -exec chmod ugo+rx \{\} \;
 find . -type d -exec chmod ugo+rx \{\} \;
 chmod o-w .
 
-echo "Fixing debuggers via sudo.bash"
-# setgrp procmod the debuggers (sudo.bash)
-cd $GOROOT/src
-./sudo.bash
-
 echo "Installing miscellaneous files:"
 XCODE_MISC_DIR="/Library/Application Support/Developer/Shared/Xcode/Specifications/"
-if [ -f $XCODE_MISC_DIR ]; then
+if [ -d "$XCODE_MISC_DIR" ]; then
 	echo "  XCode"
 	cp $GOROOT/misc/xcode/* $XCODE_MISC_DIR
 fi
diff --git a/misc/dist/darwin/scripts/preinstall b/misc/dist/darwin/scripts/preinstall
new file mode 100644
index 0000000..4cdaaa4
--- /dev/null
+++ b/misc/dist/darwin/scripts/preinstall
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+GOROOT=/usr/local/go
+
+echo "Removing previous installation"
+if [ -d $GOROOT ]; then
+	rm -r $GOROOT
+fi
diff --git a/misc/dist/stat_darwin.go b/misc/dist/stat_darwin.go
deleted file mode 100644
index eb3f76a..0000000
--- a/misc/dist/stat_darwin.go
+++ /dev/null
@@ -1,32 +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
-
-package main
-
-import (
-	"archive/tar"
-	"os"
-	"syscall"
-	"time"
-)
-
-func init() {
-	sysStat = func(fi os.FileInfo, h *tar.Header) error {
-		sys, ok := fi.Sys().(*syscall.Stat_t)
-		if !ok {
-			return nil
-		}
-		h.Uid = int(sys.Uid)
-		h.Gid = int(sys.Gid)
-		// TODO(bradfitz): populate username & group.  os/user
-		// doesn't cache LookupId lookups, and lacks group
-		// lookup functions.
-		h.AccessTime = time.Unix(sys.Atimespec.Unix())
-		h.ChangeTime = time.Unix(sys.Ctimespec.Unix())
-		// TODO(bradfitz): major/minor device numbers?
-		return nil
-	}
-}
diff --git a/misc/dist/stat_linux.go b/misc/dist/stat_linux.go
deleted file mode 100644
index 0ddb8a3..0000000
--- a/misc/dist/stat_linux.go
+++ /dev/null
@@ -1,32 +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 linux
-
-package main
-
-import (
-	"archive/tar"
-	"os"
-	"syscall"
-	"time"
-)
-
-func init() {
-	sysStat = func(fi os.FileInfo, h *tar.Header) error {
-		sys, ok := fi.Sys().(*syscall.Stat_t)
-		if !ok {
-			return nil
-		}
-		h.Uid = int(sys.Uid)
-		h.Gid = int(sys.Gid)
-		// TODO(bradfitz): populate username & group.  os/user
-		// doesn't cache LookupId lookups, and lacks group
-		// lookup functions.
-		h.AccessTime = time.Unix(sys.Atim.Unix())
-		h.ChangeTime = time.Unix(sys.Ctim.Unix())
-		// TODO(bradfitz): major/minor device numbers?
-		return nil
-	}
-}
diff --git a/misc/emacs/go-mode-load.el b/misc/emacs/go-mode-load.el
index d453166..3fc35c1 100644
--- a/misc/emacs/go-mode-load.el
+++ b/misc/emacs/go-mode-load.el
@@ -1,50 +1,96 @@
-;;; go-mode-load.el --- Major mode for the Go programming language
-
+;;; 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.
-
-;;; Code:
-
+;;
 ;; To update this file, evaluate the following form
 ;;   (let ((generated-autoload-file buffer-file-name)) (update-file-autoloads "go-mode.el"))
 
+;;; Code:
+
 
-;;;### (autoloads (gofmt-before-save gofmt go-mode) "go-mode" "go-mode.el"
-;;;;;;  (19917 17808))
+;;;### (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 provides basic syntax highlighting for keywords, built-ins,
-functions, and some types.  It also provides indentation that is
-\(almost) identical to gofmt.
+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 "go-mode" "\
-Pipe the current buffer through the external tool `gofmt`.
-Replace the current buffer on success; display errors on failure.
-
-\(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)
+ (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
index 214c196..8a16d8a 100644
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -1,40 +1,54 @@
 ;;; go-mode.el --- Major mode for the Go programming language
 
-;;; Commentary:
+;; 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.
 
-;; For installation instructions, see go-mode-load.el
+(require 'cl)
+(require 'diff-mode)
+(require 'ffap)
+(require 'find-lisp)
+(require 'url)
 
-;;; To do:
+(defconst go-dangling-operators-regexp "[^-]-\\|[^+]\\+\\|[/*&><.=|^]")
+(defconst gofmt-stdin-tag "<standard input>")
+(defconst go-identifier-regexp "[[:word:][:multibyte:]_]+")
+(defconst go-label-regexp go-identifier-regexp)
+(defconst go-type-regexp "[[:word:][:multibyte:]_*]+")
+(defconst go-func-regexp (concat "\\<func\\>\\s *\\(" go-identifier-regexp "\\)"))
+(defconst go-func-meth-regexp (concat "\\<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.")
 
-;; * Indentation is *almost* identical to gofmt
-;; ** We think struct literal keys are labels and outdent them
-;; ** We disagree on the indentation of function literals in arguments
-;; ** There are bugs with the close brace of struct literals
-;; * Highlight identifiers according to their syntactic context: type,
-;;   variable, function call, or tag
-;; * Command for adding an import
-;; ** Check if it's already there
-;; ** Factor/unfactor the import line
-;; ** Alphabetize
-;; * Remove unused imports
-;; ** This is hard, since I have to be aware of shadowing to do it
-;;    right
-;; * Format region using gofmt
+(defconst go-constants '("nil" "true" "false" "iota"))
+(defconst go-type-name-regexp (concat "\\(?:[*(]\\)*\\(?:" go-identifier-regexp "\\.\\)?\\(" go-identifier-regexp "\\)"))
 
-;;; Code:
+(defvar go-dangling-cache)
 
-(eval-when-compile (require 'cl))
+(defgroup go nil
+  "Major mode for editing Go code"
+  :group 'languages)
+
+(defcustom go-fontify-function-calls t
+  "Fontify function and method calls if this is non-nil."
+  :type 'boolean
+  :group 'go)
 
 (defvar go-mode-syntax-table
   (let ((st (make-syntax-table)))
-    ;; Add _ to :word: character class
-    (modify-syntax-entry ?_  "w" st)
-
-    ;; Operators (punctuation)
     (modify-syntax-entry ?+  "." st)
     (modify-syntax-entry ?-  "." st)
-    (modify-syntax-entry ?*  ". 23" st)                                    ; also part of comments
-    (modify-syntax-entry ?/ (if (featurep 'xemacs) ". 1456" ". 124b") st)  ; ditto
     (modify-syntax-entry ?%  "." st)
     (modify-syntax-entry ?&  "." st)
     (modify-syntax-entry ?|  "." st)
@@ -43,80 +57,56 @@
     (modify-syntax-entry ?=  "." st)
     (modify-syntax-entry ?<  "." st)
     (modify-syntax-entry ?>  "." st)
-
-    ;; Strings and comments are font-locked separately.
-    (modify-syntax-entry ?\" "." st)
-    (modify-syntax-entry ?\' "." st)
-    (modify-syntax-entry ?`  "." st)
-    (modify-syntax-entry ?\\ "." st)
-
-    ;; Newline is a comment-ender.
+    (modify-syntax-entry ?/  ". 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)
+    (modify-syntax-entry ?_  "_" st)
 
     st)
   "Syntax table for Go mode.")
 
-(defvar 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 and
-some syntax analysis.")
-
-(defvar go-mode-font-lock-keywords
-  (let ((builtins '("append" "cap" "close" "complex" "copy" "delete" "imag" "len"
-                    "make" "new" "panic" "print" "println" "real" "recover"))
-        (constants '("nil" "true" "false" "iota"))
-        (type-name "\\s *\\(?:[*(]\\s *\\)*\\(?:\\w+\\s *\\.\\s *\\)?\\(\\w+\\)")
-        )
-    `((go-mode-font-lock-cs-comment 0 font-lock-comment-face t)
-      (go-mode-font-lock-cs-string 0 font-lock-string-face t)
-      (,(regexp-opt go-mode-keywords 'words) . font-lock-keyword-face)
-      (,(regexp-opt builtins 'words) . font-lock-builtin-face)
-      (,(regexp-opt constants 'words) . font-lock-constant-face)
-      ;; Function names in declarations
-      ("\\<func\\>\\s *\\(\\w+\\)" 1 font-lock-function-name-face)
-      ;; Function names in methods are handled by function call pattern
-      ;; Function names in calls
-      ;; XXX Doesn't match if function name is surrounded by parens
-      ("\\(\\w+\\)\\s *(" 1 font-lock-function-name-face)
-      ;; Type names
-      ("\\<type\\>\\s *\\(\\w+\\)" 1 font-lock-type-face)
-      (,(concat "\\<type\\>\\s *\\w+\\s *" type-name) 1 font-lock-type-face)
-      ;; Arrays/slices/map value type
-      ;; XXX Wrong.  Marks 0 in expression "foo[0] * x"
-      ;;      (,(concat "]" type-name) 1 font-lock-type-face)
-      ;; Map key type
-      (,(concat "\\<map\\s *\\[" type-name) 1 font-lock-type-face)
-      ;; Channel value type
-      (,(concat "\\<chan\\>\\s *\\(?:<-\\)?" type-name) 1 font-lock-type-face)
-      ;; new/make type
-      (,(concat "\\<\\(?:new\\|make\\)\\>\\(?:\\s \\|)\\)*(" type-name) 1 font-lock-type-face)
-      ;; Type conversion
-      (,(concat "\\.\\s *(" type-name) 1 font-lock-type-face)
-      ;; Method receiver type
-      (,(concat "\\<func\\>\\s *(\\w+\\s +" type-name) 1 font-lock-type-face)
-      ;; Labels
-      ;; XXX Not quite right.  Also marks compound literal fields.
-      ("^\\s *\\(\\w+\\)\\s *:\\(\\S.\\|$\\)" 1 font-lock-constant-face)
-      ("\\<\\(goto\\|break\\|continue\\)\\>\\s *\\(\\w+\\)" 2 font-lock-constant-face)))
-  "Basic font lock keywords for Go mode.  Highlights keywords,
-built-ins, functions, and some types.")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Key map
-;;
+(defun go--build-font-lock-keywords ()
+  (append
+   `((,(regexp-opt go-mode-keywords 'symbols) . font-lock-keyword-face)
+     (,(regexp-opt go-builtins 'symbols) . font-lock-builtin-face)
+     (,(regexp-opt go-constants 'symbols) . 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 "(\\(" go-identifier-regexp "\\))[[:space:]]*(") 1 font-lock-function-name-face)) ;; bracketed function call
+     `((,go-func-meth-regexp 1 font-lock-function-name-face))) ;; method name
+
+   `(
+     ("\\<type\\>[[:space:]]*\\([^[:space:]]+\\)" 1 font-lock-type-face) ;; types
+     (,(concat "\\<type\\>[[:space:]]*" go-identifier-regexp "[[:space:]]*" go-type-name-regexp) 1 font-lock-type-face) ;; types
+     (,(concat "\\(?:[[:space:]]+\\|\\]\\)\\[\\([[:digit:]]+\\|\\.\\.\\.\\)?\\]" go-type-name-regexp) 2 font-lock-type-face) ;; Arrays/slices
+     (,(concat "map\\[[^]]+\\]" go-type-name-regexp) 1 font-lock-type-face) ;; map value type
+     (,(concat "\\(" go-identifier-regexp "\\)" "{") 1 font-lock-type-face)
+     (,(concat "\\<map\\[" go-type-name-regexp) 1 font-lock-type-face) ;; map key type
+     (,(concat "\\<chan\\>[[:space:]]*\\(?:<-\\)?" go-type-name-regexp) 1 font-lock-type-face) ;; channel type
+     (,(concat "\\<\\(?: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 "\\<func\\>[[:space:]]+(" go-identifier-regexp "[[:space:]]+" go-type-name-regexp ")") 1 font-lock-type-face) ;; Method receiver
+     ;; 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 "\\<\\(goto\\|break\\|continue\\)\\>[[:space:]]*\\(" go-label-regexp "\\)") 2 font-lock-constant-face)))) ;; labels in goto/break/continue
 
 (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-delayed-electric)
-    ;; In case we get : indentation wrong, correct ourselves
-    (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 "=" 'go-mode-insert-and-indent)
+    (define-key m (kbd "C-c C-a") 'go-import-add)
     m)
   "Keymap used by Go mode to implement electric keys.")
 
@@ -127,606 +117,229 @@ built-ins, functions, and some types.")
   (call-interactively (lookup-key (current-global-map) key))
   (indent-according-to-mode))
 
-(defvar go-mode-delayed-point nil
-  "The point following the previous insertion if the insertion
-was a delayed electric key.  Used to communicate between
-`go-mode-delayed-electric' and `go-mode-delayed-electric-hook'.")
-(make-variable-buffer-local 'go-mode-delayed-point)
-
-(defun go-mode-delayed-electric (p)
-  "Perform electric insertion, but delayed by one event.
-
-This inserts P into the buffer, as usual, then waits for another key.
-If that second key causes a buffer modification starting at the
-point after the insertion of P, reindents the line containing P."
-
-  (interactive "p")
-  (self-insert-command p)
-  (setq go-mode-delayed-point (point)))
-
-(defun go-mode-delayed-electric-hook (b e l)
-  "An after-change-function that implements `go-mode-delayed-electric'."
-
-  (when (and go-mode-delayed-point
-             (= go-mode-delayed-point b))
-    (save-excursion
-      (save-match-data
-        (goto-char go-mode-delayed-point)
-        (indent-according-to-mode))))
-  (setq go-mode-delayed-point nil))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Parser
-;;
-
-(defvar go-mode-mark-cs-end 1
-  "The point at which the comment/string cache ends.  The buffer
-will be marked from the beginning up to this point (that is, up
-to and including character (1- go-mode-mark-cs-end)).")
-(make-variable-buffer-local 'go-mode-mark-cs-end)
-
-(defvar go-mode-mark-string-end 1
-  "The point at which the string cache ends.  The buffer
-will be marked from the beginning up to this point (that is, up
-to and including character (1- go-mode-mark-string-end)).")
-(make-variable-buffer-local 'go-mode-mark-string-end)
-
-(defvar go-mode-mark-comment-end 1
-  "The point at which the comment cache ends.  The buffer
-will be marked from the beginning up to this point (that is, up
-to and including character (1- go-mode-mark-comment-end)).")
-(make-variable-buffer-local 'go-mode-mark-comment-end)
-
-(defvar go-mode-mark-nesting-end 1
-  "The point at which the nesting cache ends.  The buffer will be
-marked from the beginning up to this point.")
-(make-variable-buffer-local 'go-mode-mark-nesting-end)
-
-(defun go-mode-mark-clear-cs (b e l)
-  "An after-change-function that removes the go-mode-cs text property"
-  (remove-text-properties b e '(go-mode-cs)))
-
-(defun go-mode-mark-clear-cache (b e)
-  "A before-change-function that clears the comment/string and
-nesting caches from the modified point on."
-
-  (save-restriction
-    (widen)
-    (when (<= b go-mode-mark-cs-end)
-      ;; Remove the property adjacent to the change position.
-      ;; It may contain positions pointing beyond the new end mark.
-      (let ((b (let ((cs (get-text-property (max 1 (1- b)) 'go-mode-cs)))
-		 (if cs (car cs) b))))
-	(remove-text-properties
-	 b (min go-mode-mark-cs-end (point-max)) '(go-mode-cs nil))
-	(setq go-mode-mark-cs-end b)))
-
-    (when (<= b go-mode-mark-string-end)
-      ;; Remove the property adjacent to the change position.
-      ;; It may contain positions pointing beyond the new end mark.
-      (let ((b (let ((cs (get-text-property (max 1 (1- b)) 'go-mode-string)))
-		 (if cs (car cs) b))))
-	(remove-text-properties
-	 b (min go-mode-mark-string-end (point-max)) '(go-mode-string nil))
-	(setq go-mode-mark-string-end b)))
-    (when (<= b go-mode-mark-comment-end)
-      ;; Remove the property adjacent to the change position.
-      ;; It may contain positions pointing beyond the new end mark.
-      (let ((b (let ((cs (get-text-property (max 1 (1- b)) 'go-mode-comment)))
-		 (if cs (car cs) b))))
-	(remove-text-properties
-	 b (min go-mode-mark-string-end (point-max)) '(go-mode-comment nil))
-	(setq go-mode-mark-comment-end b)))
-    
-    (when (< b go-mode-mark-nesting-end)
-      (remove-text-properties b (min go-mode-mark-nesting-end (point-max)) '(go-mode-nesting nil))
-      (setq go-mode-mark-nesting-end b))))
-
-(defmacro go-mode-parser (&rest body)
-  "Evaluate BODY in an environment set up for parsers that use
-text properties to mark text.  This inhibits changes to the undo
-list or the buffer's modification status and inhibits calls to
-the modification hooks.  It also saves the excursion and
-restriction and widens the buffer, since most parsers are
-context-sensitive."
-
-  (let ((modified-var (make-symbol "modified")))
-    `(let ((buffer-undo-list t)
-           (,modified-var (buffer-modified-p))
-           (inhibit-modification-hooks t)
-           (inhibit-read-only t))
-       (save-excursion
-         (save-restriction
-           (widen)
-           (unwind-protect
-               (progn , at body)
-             (set-buffer-modified-p ,modified-var)))))))
-
-(defun go-mode-cs (&optional pos)
-  "Return the comment/string state at point POS.  If point is
-inside a comment or string (including the delimiters), this
-returns a pair (START . END) indicating the extents of the
-comment or string."
-
-  (unless pos
-    (setq pos (point)))
-  (when (>= pos go-mode-mark-cs-end)
-    (go-mode-mark-cs (1+ pos)))
-  (get-text-property pos 'go-mode-cs))
-
-(defun go-mode-mark-cs (end)
-  "Mark comments and strings up to point END.  Don't call this
-directly; use `go-mode-cs'."
-  (setq end (min end (point-max)))
-  (go-mode-parser
-   (save-match-data
-     (let ((pos
-	    ;; Back up to the last known state.
-	    (let ((last-cs
-		   (and (> go-mode-mark-cs-end 1)
-			(get-text-property (1- go-mode-mark-cs-end) 
-					   'go-mode-cs))))
-	      (if last-cs
-		  (car last-cs)
-		(max 1 (1- go-mode-mark-cs-end))))))
-       (while (< pos end)
-	 (goto-char pos)
-	 (let ((cs-end			; end of the text property
-		(cond
-		 ((looking-at "//")
-		  (end-of-line)
-		  (1+ (point)))
-		 ((looking-at "/\\*")
-		  (goto-char (+ pos 2))
-		  (if (search-forward "*/" (1+ end) t)
-		      (point)
-		    end))
-		 ((looking-at "\"")
-		  (goto-char (1+ pos))
-		  (if (looking-at "[^\"\n\\\\]*\\(\\\\.[^\"\n\\\\]*\\)*\"")
-		      (match-end 0)
-		    (end-of-line)
-		    (point)))
-		 ((looking-at "'")
-		  (goto-char (1+ pos))
-		  (if (looking-at "[^'\n\\\\]*\\(\\\\.[^'\n\\\\]*\\)*'")
-		      (match-end 0)
-		    (end-of-line)
-		    (point)))
-		 ((looking-at "`")
-		  (goto-char (1+ pos))
-		  (while (if (search-forward "`" end t)
-			     (if (eq (char-after) ?`)
-				 (goto-char (1+ (point))))
-			   (goto-char end)
-			   nil))
-		  (point)))))
-	   (cond
-	    (cs-end
-	     (put-text-property pos cs-end 'go-mode-cs (cons pos cs-end))
-	     (setq pos cs-end))
-	    ((re-search-forward "[\"'`]\\|/[/*]" end t)
-	     (setq pos (match-beginning 0)))
-	    (t
-	     (setq pos end)))))
-       (setq go-mode-mark-cs-end pos)))))
-
-(defun go-mode-in-comment (&optional pos)
-  "Return the comment/string state at point POS.  If point is
-inside a comment (including the delimiters), this
-returns a pair (START . END) indicating the extents of the
-comment or string."
-
-  (unless pos
-    (setq pos (point)))
-  (when (> pos go-mode-mark-comment-end)
-    (go-mode-mark-comment pos))
-  (get-text-property pos 'go-mode-comment))
-
-(defun go-mode-mark-comment (end)
-  "Mark comments up to point END.  Don't call this directly; use `go-mode-in-comment'."
-  (setq end (min end (point-max)))
-  (go-mode-parser
-   (save-match-data
-     (let ((pos
-	    ;; Back up to the last known state.
-	    (let ((last-comment
-		   (and (> go-mode-mark-comment-end 1)
-			(get-text-property (1- go-mode-mark-comment-end) 
-					   'go-mode-comment))))
-	      (if last-comment
-		  (car last-comment)
-		(max 1 (1- go-mode-mark-comment-end))))))
-       (while (< pos end)
-	 (goto-char pos)
-	 (let ((comment-end			; end of the text property
-		(cond
-		 ((looking-at "//")
-		  (end-of-line)
-		  (1+ (point)))
-		 ((looking-at "/\\*")
-		  (goto-char (+ pos 2))
-		  (if (search-forward "*/" (1+ end) t)
-		      (point)
-		    end)))))
-	   (cond
-	    (comment-end
-	     (put-text-property pos comment-end 'go-mode-comment (cons pos comment-end))
-	     (setq pos comment-end))
-	    ((re-search-forward "/[/*]" end t)
-	     (setq pos (match-beginning 0)))
-	    (t
-	     (setq pos end)))))
-       (setq go-mode-mark-comment-end pos)))))
-
-(defun go-mode-in-string (&optional pos)
-  "Return the string state at point POS.  If point is
-inside a string (including the delimiters), this
-returns a pair (START . END) indicating the extents of the
-comment or string."
-
-  (unless pos
-    (setq pos (point)))
-  (when (> pos go-mode-mark-string-end)
-    (go-mode-mark-string pos))
-  (get-text-property pos 'go-mode-string))
-
-(defun go-mode-mark-string (end)
-  "Mark strings up to point END.  Don't call this
-directly; use `go-mode-in-string'."
-  (setq end (min end (point-max)))
-  (go-mode-parser
-   (save-match-data
-     (let ((pos
-	    ;; Back up to the last known state.
-	    (let ((last-cs
-		   (and (> go-mode-mark-string-end 1)
-			(get-text-property (1- go-mode-mark-string-end) 
-					   'go-mode-string))))
-	      (if last-cs
-		  (car last-cs)
-		(max 1 (1- go-mode-mark-string-end))))))
-       (while (< pos end)
-	 (goto-char pos)
-	 (let ((cs-end			; end of the text property
-		(cond 
-		 ((looking-at "\"")
-		  (goto-char (1+ pos))
-		  (if (looking-at "[^\"\n\\\\]*\\(\\\\.[^\"\n\\\\]*\\)*\"")
-		      (match-end 0)
-		    (end-of-line)
-		    (point)))
-		 ((looking-at "'")
-		  (goto-char (1+ pos))
-		  (if (looking-at "[^'\n\\\\]*\\(\\\\.[^'\n\\\\]*\\)*'")
-		      (match-end 0)
-		    (end-of-line)
-		    (point)))
-		 ((looking-at "`")
-		  (goto-char (1+ pos))
-		  (while (if (search-forward "`" end t)
-			     (if (eq (char-after) ?`)
-				 (goto-char (1+ (point))))
-			   (goto-char end)
-			   nil))
-		  (point)))))
-	   (cond
-	    (cs-end
-	     (put-text-property pos cs-end 'go-mode-string (cons pos cs-end))
-	     (setq pos cs-end))
-	    ((re-search-forward "[\"'`]" end t)
-	     (setq pos (match-beginning 0)))
-	    (t
-	     (setq pos end)))))
-       (setq go-mode-mark-string-end pos)))))
-
-(defun go-mode-font-lock-cs (limit comment)
-  "Helper function for highlighting comment/strings.  If COMMENT is t,
-set match data to the next comment after point, and advance point
-after it.  If COMMENT is nil, use the next string.  Returns nil
-if no further tokens of the type exist."
-  ;; Ensures that `next-single-property-change' below will work properly.
-  (go-mode-cs limit)
-  (let (cs next (result 'scan))
-    (while (eq result 'scan)
-      (if (or (>= (point) limit) (eobp))
-	  (setq result nil)
-	(setq cs (go-mode-cs))
-	(if cs
-	    (if (eq (= (char-after (car cs)) ?/) comment)
-		;; If inside the expected comment/string, highlight it.
-		(progn
-		  ;; If the match includes a "\n", we have a
-		  ;; multi-line construct.  Mark it as such.
-		  (goto-char (car cs))
-		  (when (search-forward "\n" (cdr cs) t)
-		    (put-text-property
-		     (car cs) (cdr cs) 'font-lock-multline t))
-		  (set-match-data (list (car cs) (copy-marker (cdr cs))))
-		  (goto-char (cdr cs))
-		  (setq result t))
-	      ;; Wrong type.  Look for next comment/string after this one.
-	      (goto-char (cdr cs)))
-	  ;; Not inside comment/string.  Search for next comment/string.
-	  (setq next (next-single-property-change
-		      (point) 'go-mode-cs nil limit))
-	  (if (and next (< next limit))
-	      (goto-char next)
-	    (setq result nil)))))
-    result))
-
-(defun go-mode-font-lock-cs-string (limit)
-  "Font-lock iterator for strings."
-  (go-mode-font-lock-cs limit nil))
-
-(defun go-mode-font-lock-cs-comment (limit)
-  "Font-lock iterator for comments."
-  (go-mode-font-lock-cs limit t))
-
-(defsubst go-mode-nesting (&optional pos)
-  "Return the nesting at point POS.  The nesting is a list
-of (START . END) pairs for all braces, parens, and brackets
-surrounding POS, starting at the inner-most nesting.  START is
-the location of the open character.  END is the location of the
-close character or nil if the nesting scanner has not yet
-encountered the close character."
-
-  (unless pos
-    (setq pos (point)))
-  (if (= pos 1)
-      '()
-    (when (> pos go-mode-mark-nesting-end)
-      (go-mode-mark-nesting pos))
-    (get-text-property (- pos 1) 'go-mode-nesting)))
-
-(defun go-mode-mark-nesting (pos)
-  "Mark nesting up to point END.  Don't call this directly; use
-`go-mode-nesting'."
-
-  (go-mode-cs pos)
-  (go-mode-parser
-   ;; Mark depth
-   (goto-char go-mode-mark-nesting-end)
-   (let ((nesting (go-mode-nesting))
-         (last (point)))
-     (while (< last pos)
-       ;; Find the next depth-changing character
-       (skip-chars-forward "^(){}[]" pos)
-       ;; Mark everything up to this character with the current
-       ;; nesting
-       (put-text-property last (point) 'go-mode-nesting nesting)
-       (when nil
-         (let ((depth (length nesting)))
-           (put-text-property last (point) 'face
-                              `((:background
-                                 ,(format "gray%d" (* depth 10)))))))
-       (setq last (point))
-       ;; Update nesting
-       (unless (eobp)
-         (let ((ch (unless (go-mode-cs) (char-after))))
-           (forward-char 1)
-           (case ch
-             ((?\( ?\{ ?\[)
-              (setq nesting (cons (cons (- (point) 1) nil)
-                                  nesting)))
-             ((?\) ?\} ?\])
-              (when nesting
-                (setcdr (car nesting) (- (point) 1))
-                (setq nesting (cdr nesting))))))))
-     ;; Update state
-     (setq go-mode-mark-nesting-end last))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Indentation
-;;
-
-(defvar go-mode-non-terminating-keywords-regexp
-  (let* ((kws go-mode-keywords)
-         (kws (remove "break" kws))
-         (kws (remove "continue" kws))
-         (kws (remove "fallthrough" kws))
-         (kws (remove "return" kws)))
-    (regexp-opt kws 'words))
-  "Regular expression matching all Go keywords that *do not*
-implicitly terminate a statement.")
-
-(defun go-mode-semicolon-p ()
-  "True iff point immediately follows either an explicit or
-implicit semicolon.  Point should immediately follow the last
-token on the line."
-
-  ;; #Semicolons
-  (case (char-before)
-    ((?\;) t)
-    ;; String literal
-    ((?' ?\" ?`) t)
-    ;; One of the operators and delimiters ++, --, ), ], or }
-    ((?+) (eq (char-before (1- (point))) ?+))
-    ((?-) (eq (char-before (1- (point))) ?-))
-    ((?\) ?\] ?\}) t)
-    ;; An identifier or one of the keywords break, continue,
-    ;; fallthrough, or return or a numeric literal
-    (otherwise
-     (save-excursion
-       (when (/= (skip-chars-backward "[:word:]_") 0)
-         (not (looking-at go-mode-non-terminating-keywords-regexp)))))))
-
-(defun go-mode-whitespace-p (char)
-  "Is newline, or char whitespace in the syntax table for go."
-  (or (eq char ?\n)
-      (= (char-syntax char) ?\ )))
-
-(defun go-mode-backward-skip-comments ()
-  "Skip backward over comments and whitespace."
-  ;; only proceed if point is in a comment or white space
-  (if (or (go-mode-in-comment)
-	  (go-mode-whitespace-p (char-after (point))))
-      (let ((loop-guard t))
-	(while (and
-		loop-guard
-		(not (bobp)))
-
-	  (cond ((go-mode-whitespace-p (char-after (point)))
-		 ;; moves point back over any whitespace
-		 (re-search-backward "[^[:space:]]"))
-
-		((go-mode-in-comment)
-		 ;; move point to char preceeding current comment
-		 (goto-char (1- (car (go-mode-in-comment)))))
-		
-		;; not in a comment or whitespace? we must be done.
-		(t (setq loop-guard nil)
-		   (forward-char 1)))))))
-
-(defun go-mode-indentation ()
-  "Compute the ideal indentation level of the current line.
-
-To the first order, this is the brace depth of the current line,
-plus parens that follow certain keywords.  case, default, and
-labels are outdented one level, and continuation lines are
-indented one level."
-
+(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[:blank:]")
+    (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-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-goto-opening-parenthesis (&optional char)
+  (let ((start-nesting (go-paren-level)))
+    (while (and (not (bobp))
+                (>= (go-paren-level) start-nesting))
+      (if (zerop (skip-chars-backward
+                  (if char
+                      (case char (?\] "^[") (?\} "^{") (?\) "^("))
+                    "^[{(")))
+          (if (go-in-string-or-comment-p)
+              (go-goto-beginning-of-string-or-comment)
+            (backward-char))))))
+
+(defun go-indentation-at-point ()
   (save-excursion
-    (back-to-indentation)
-    (let ((cs (go-mode-cs)))
-      ;; Treat comments and strings differently only if the beginning
-      ;; of the line is contained within them
-      (when (and cs (= (point) (car cs)))
-        (setq cs nil))
-      ;; What type of context am I in?
+    (let (start-nesting (outindent 0))
+      (back-to-indentation)
+      (setq start-nesting (go-paren-level))
+
       (cond
-       ((and cs (save-excursion
-                  (goto-char (car cs))
-                  (looking-at "`")))
-        ;; Inside a multi-line string.  Don't mess with indentation.
-        nil)
-       (cs
-        ;; Inside a general comment
-        (goto-char (car cs))
-        (forward-char 1)
-        (current-column))
+       ((go-in-string-p)
+        (current-indentation))
+       ((looking-at "[])}]")
+        (go-goto-opening-parenthesis (char-after))
+        (if (go-previous-line-has-dangling-op-p)
+            (- (current-indentation) tab-width)
+          (current-indentation)))
+       ((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)
+          (+ (current-indentation) tab-width)))
        (t
-        ;; Not in a multi-line string or comment
-        (let ((indent 0)
-              (inside-indenting-paren nil))
-          ;; Count every enclosing brace, plus parens that follow
-          ;; import, const, var, or type and indent according to
-          ;; depth.  This simple rule does quite well, but also has a
-          ;; very large extent.  It would be better if we could mimic
-          ;; some nearby indentation.
-          (save-excursion
-            (skip-chars-forward "})")
-            (let ((first t))
-              (dolist (nest (go-mode-nesting))
-                (case (char-after (car nest))
-                  ((?\{)
-                   (incf indent tab-width))
-                  ((?\()
-                   (goto-char (car nest))
-                   (go-mode-backward-skip-comments)
-                   (backward-char)
-                   ;; Really just want the token before
-                   (when (looking-back "\\<import\\|const\\|var\\|type\\|package"
-                                       (max (- (point) 7) (point-min)))
-                     (incf indent tab-width)
-                     (when first
-                       (setq inside-indenting-paren t)))))
-                (setq first nil))))
-
-          ;; case, default, and labels are outdented 1 level
-          (when (looking-at "\\<case\\>\\|\\<default\\>\\|\\w+\\s *:\\(\\S.\\|$\\)")
-            (decf indent tab-width))
-
-	  (when (looking-at "\\w+\\s *:.+,\\s *$")
-	    (incf indent tab-width))
-
-          ;; Continuation lines are indented 1 level
-          (beginning-of-line)		; back up to end of previous line
-	  (backward-char)
-          (go-mode-backward-skip-comments) ; back up past any comments
-          (when (case (char-before)
-                  ((nil ?\{ ?:)
-                   ;; At the beginning of a block or the statement
-                   ;; following a label.
-                   nil)
-                  ((?\()
-                   ;; Usually a continuation line in an expression,
-                   ;; unless this paren is part of a factored
-                   ;; declaration.
-                   (not inside-indenting-paren))
-                  ((?,)
-                   ;; Could be inside a literal.  We're a little
-                   ;; conservative here and consider any comma within
-                   ;; curly braces (as opposed to parens) to be a
-                   ;; literal separator.  This will fail to recognize
-                   ;; line-breaks in parallel assignments as
-                   ;; continuation lines.
-                   (let ((depth (go-mode-nesting)))
-                     (and depth
-                          (not (eq (char-after (caar depth)) ?\{)))))
-                  (t
-                   ;; We're in the middle of a block.  Did the
-                   ;; previous line end with an implicit or explicit
-                   ;; semicolon?
-                   (not (go-mode-semicolon-p))))
-            (incf indent tab-width))
-
-          (max indent 0)))))))
+        (current-indentation))))))
 
 (defun go-mode-indent-line ()
-  "Indent the current line according to `go-mode-indentation'."
   (interactive)
-
-  ;; turn off case folding to distinguish keywords from identifiers
-  ;; e.g. "default" is a keyword; "Default" can be a variable name.
-  (let ((case-fold-search nil))
-    (let ((col (go-mode-indentation)))
-      (when col
-	(let ((offset (- (current-column) (current-indentation))))
-	  (indent-line-to col)
-	  (when (> offset 0)
-	    (forward-char offset)))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Go mode
-;;
+  (let (indent
+        shift-amt
+        end
+        (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)
+  (unless count (setq 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 nil "Go"
+(define-derived-mode go-mode fundamental-mode "Go"
   "Major mode for editing Go source text.
 
-This provides basic syntax highlighting for keywords, built-ins,
-functions, and some types.  It also provides indentation that is
-\(almost) identical to gofmt."
+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'
+
+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 that you look at goflymake
+\(https://github.com/dougm/goflymake), gocode
+\(https://github.com/nsf/gocode) and yasnippet-go
+\(https://github.com/dominikh/yasnippet-go)"
 
   ;; Font lock
   (set (make-local-variable 'font-lock-defaults)
-       '(go-mode-font-lock-keywords nil nil nil nil))
-
-  ;; Remove stale text properties
-  (save-restriction
-    (widen)
-    (let ((modified (buffer-modified-p)))
-      (remove-text-properties 1 (point-max)
-                              '(go-mode-cs nil go-mode-nesting nil))
-      ;; remove-text-properties marks the buffer modified. undo that if it
-      ;; wasn't originally marked modified.
-      (set-buffer-modified-p modified)))
-
-  ;; Reset the syntax mark caches
-  (setq go-mode-mark-cs-end      1
-        go-mode-mark-nesting-end 1)
-  (add-hook 'before-change-functions #'go-mode-mark-clear-cache nil t)
-  (add-hook 'after-change-functions #'go-mode-mark-clear-cs nil t)
+       '(go--build-font-lock-keywords))
 
   ;; Indentation
-  (set (make-local-variable 'indent-line-function)
-       #'go-mode-indent-line)
-  (add-hook 'after-change-functions #'go-mode-delayed-electric-hook nil t)
+  (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 '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)
+
+
+  (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)
@@ -739,24 +352,14 @@ functions, and some types.  It also provides indentation that is
   ;; 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)))
+             (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-mode-reload ()
-  "Reload go-mode.el and put the current buffer into Go mode.
-Useful for development work."
+(add-to-list 'auto-mode-alist (cons "\\.go\\'" 'go-mode))
 
-  (interactive)
-  (unload-feature 'go-mode)
-  (require 'go-mode)
-  (go-mode))
-
-;;;###autoload
 (defun gofmt ()
   "Pipe the current buffer through the external tool `gofmt`.
 Replace the current buffer on success; display errors on failure."
@@ -768,84 +371,103 @@ Replace the current buffer on success; display errors on failure."
           (patchbuf (get-buffer-create "*Gofmt patch*")))
       (with-current-buffer patchbuf
         (let ((errbuf (get-buffer-create "*Gofmt Errors*"))
-              (coding-system-for-read 'utf-8)    ;; use utf-8 with subprocesses
+              ;; use utf-8 with subprocesses
+              (coding-system-for-read 'utf-8)
               (coding-system-for-write 'utf-8))
           (with-current-buffer errbuf
-            (toggle-read-only 0)
+            (setq buffer-read-only nil)
             (erase-buffer))
           (with-current-buffer srcbuf
             (save-restriction
               (let (deactivate-mark)
                 (widen)
-                ; If this is a new file, diff-mode can't apply a
-                ; patch to a non-exisiting file, so replace the buffer
-                ; completely with the output of 'gofmt'.
-                ; If the file exists, patch it to keep the 'undo' list happy.
+                ;; If this is a new file, diff-mode can't apply a
+                ;; patch to a non-exisiting file, so replace the buffer
+                ;; completely with the output of 'gofmt'.
+                ;; If the file exists, patch it to keep the 'undo' list happy.
                 (let* ((newfile (not (file-exists-p filename)))
-                      (flag (if newfile "" " -d")))
-                  (if (= 0 (shell-command-on-region (point-min) (point-max)
-                                                    (concat "gofmt" flag)
-                                                    patchbuf nil errbuf))
-                      ; gofmt succeeded: replace buffer or apply patch hunks.
+                       (flag (if newfile "" " -d")))
+
+                  ;; diff-mode doesn't work too well with missing
+                  ;; end-of-file newline, so add one
+                  (if (/= (char-after (1- (point-max))) ?\n)
+                      (save-excursion
+                        (goto-char (point-max))
+                        (insert ?\n)))
+
+                  (if (zerop (shell-command-on-region (point-min) (point-max)
+                                                      (concat "gofmt" flag)
+                                                      patchbuf nil errbuf))
+                      ;; gofmt succeeded: replace buffer or apply patch hunks.
                       (let ((old-point (point))
                             (old-mark (mark t)))
                         (kill-buffer errbuf)
                         (if newfile
-                            ; New file, replace it (diff-mode won't work)
-                            (gofmt-replace-buffer srcbuf patchbuf)
-                          ; Existing file, patch it
-                          (gofmt-apply-patch filename srcbuf patchbuf))
+                            ;; New file, replace it (diff-mode won't work)
+                            (gofmt--replace-buffer srcbuf patchbuf)
+                          ;; Existing file, patch it
+                          (gofmt--apply-patch filename srcbuf patchbuf))
                         (goto-char (min old-point (point-max)))
                         ;; Restore the mark and point
                         (if old-mark (push-mark (min old-mark (point-max)) t))
                         (set-window-configuration currconf))
 
-                  ;; gofmt failed: display the errors
-                  (gofmt-process-errors filename errbuf))))))
+                    ;; gofmt failed: display the errors
+                    (message "Could not apply gofmt. Check errors for details")
+                    (gofmt--process-errors filename errbuf))))))
 
           ;; Collapse any window opened on outbuf if shell-command-on-region
           ;; displayed it.
           (delete-windows-on patchbuf)))
       (kill-buffer patchbuf))))
 
-(defun gofmt-replace-buffer (srcbuf patchbuf)
+(defun gofmt--replace-buffer (srcbuf patchbuf)
   (with-current-buffer srcbuf
     (erase-buffer)
-    (insert-buffer-substring patchbuf)))
+    (insert-buffer-substring patchbuf))
+  (message "Applied gofmt"))
 
-(defconst gofmt-stdin-tag "<standard input>")
-
-(defun gofmt-apply-patch (filename srcbuf patchbuf)
-  (require 'diff-mode)
+(defun gofmt--apply-patch (filename srcbuf patchbuf)
   ;; apply all the patch hunks
-  (with-current-buffer patchbuf
-    (replace-regexp "^--- /tmp/gofmt[0-9]*" (concat "--- " filename)
-                      nil (point-min) (point-max))
-    (condition-case nil
-        (while t
-          (diff-hunk-next)
-          (diff-apply-hunk))
-      ;; When there's no more hunks, diff-hunk-next signals an error, ignore it
-      (error nil))))
-
-(defun gofmt-process-errors (filename errbuf)
+  (let (changed)
+    (with-current-buffer patchbuf
+      (goto-char (point-min))
+      ;; The .* is for TMPDIR, but to avoid dealing with TMPDIR
+      ;; having a trailing / or not, it's easier to just search for .*
+      ;; especially as we're only replacing the first instance.
+      (if (re-search-forward "^--- \\(.*/gofmt[0-9]*\\)" nil t)
+          (replace-match filename nil nil nil 1))
+      (condition-case nil
+          (while t
+            (diff-hunk-next)
+            (diff-apply-hunk)
+            (setq changed t))
+        ;; When there's no more hunks, diff-hunk-next signals an error, ignore it
+        (error nil)))
+    (if changed (message "Applied gofmt") (message "Buffer was already gofmted"))))
+
+(defun gofmt--process-errors (filename errbuf)
   ;; Convert the gofmt stderr to something understood by the compilation mode.
   (with-current-buffer errbuf
-    (beginning-of-buffer)
+    (goto-char (point-min))
     (insert "gofmt errors:\n")
-    (replace-string gofmt-stdin-tag (file-name-nondirectory filename) nil (point-min) (point-max))
+    (if (search-forward gofmt-stdin-tag nil t)
+        (replace-match (file-name-nondirectory filename) nil t))
     (display-buffer errbuf)
     (compilation-mode)))
 
 ;;;###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)"
+ (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 ()
+(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
@@ -859,7 +481,7 @@ Replace the current buffer on success; display errors on failure."
                    "godoc: ")
                  nil nil symbol)))
 
-(defun godoc-get-buffer (query)
+(defun godoc--get-buffer (query)
   "Get an empty buffer for a godoc query."
   (let* ((buffer-name (concat "*godoc " query "*"))
          (buffer (get-buffer buffer-name)))
@@ -867,13 +489,14 @@ Replace the current buffer on success; display errors on failure."
     (when buffer (kill-buffer buffer))
     (get-buffer-create buffer-name)))
 
-(defun godoc-buffer-sentinel (proc event)
+(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))
-           (display-buffer (current-buffer) 'not-this-window))
-          ((not (= (process-exit-status proc) 0))  ;; Error exit.
+           (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)))))))
@@ -881,12 +504,217 @@ Replace the current buffer on success; display errors on failure."
 ;;;###autoload
 (defun godoc (query)
   "Show go documentation for a query, much like M-x man."
-  (interactive (list (godoc-read-query)))
+  (interactive (list (godoc--read-query)))
   (unless (string= query "")
     (set-process-sentinel
-     (start-process-shell-command "godoc" (godoc-get-buffer query)
+     (start-process-shell-command "godoc" (godoc--get-buffer query)
                                   (concat "godoc " query))
-     'godoc-buffer-sentinel)
+     '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 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 (buffer-substring-no-properties start end))
+         (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))))))
+
+;; ;; Commented until we actually make use of this function
+;; (defun go--common-prefix (sequences)
+;;   ;; mismatch and reduce are cl
+;;   (assert sequences)
+;;   (flet ((common-prefix (s1 s2)
+;;                         (let ((diff-pos (mismatch s1 s2)))
+;;                           (if diff-pos (subseq s1 0 diff-pos) s1))))
+;;     (reduce #'common-prefix sequences)))
+
+(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-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
+              (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 (process-lines "go" "env" "GOROOT" "GOPATH"))
+         (root (car output))
+         (paths (split-string (car (cdr output)) ":")))
+    (append (list root) paths)))
+
+(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 (string-prefix-p "obj/" sub) (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)
+                     (find-lisp-find-files-internal pkgdir 'find-lisp-file-predicate-is-directory 'find-lisp-default-directory-predicate)))))
+     (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
+                                   (if (string-match "_test\.go$" buffer-file-truename)
+                                       "go test -c"
+                                     "go 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)
+          (goto-char (point-min))
+          (forward-line (1- import))
+          (beginning-of-line)
+          (if arg
+              (comment-region (line-beginning-position) (line-end-position))
+            (let ((kill-whole-line t))
+              (kill-line))))
+        (message "Removed %d imports" (length lines)))
+      (if flymake-state (flymake-mode-on)))))
+
 (provide 'go-mode)
diff --git a/misc/git/pre-commit b/misc/git/pre-commit
new file mode 100755
index 0000000..18b7f83
--- /dev/null
+++ b/misc/git/pre-commit
@@ -0,0 +1,26 @@
+#!/bin/sh
+# 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.
+
+# git gofmt pre-commit hook
+#
+# To use, store as .git/hooks/pre-commit inside your repository and make sure
+# it has execute permissions.
+#
+# This script does not handle file names that contain spaces.
+
+gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '.go$')
+[ -z "$gofiles" ] && exit 0
+
+unformatted=$(gofmt -l $gofiles)
+[ -z "$unformatted" ] && exit 0
+
+# Some files are not gofmt'd. Print message and fail.
+
+echo >&2 "Go files must be formatted with gofmt. Please run:"
+for fn in $unformatted; do
+	echo >&2 "  gofmt -w $PWD/$fn"
+done
+
+exit 1
diff --git a/misc/goplay/doc.go b/misc/goplay/doc.go
index fd4a28e..61e74a0 100644
--- a/misc/goplay/doc.go
+++ b/misc/goplay/doc.go
@@ -4,20 +4,20 @@
 
 // Goplay is a web interface for experimenting with Go code.
 // It is similar to the Go Playground: http://golang.org/doc/play/
-// 
+//
 // To use goplay:
 //   $ cd $GOROOT/misc/goplay
 //   $ go run goplay.go
 // and load http://localhost:3999/ in a web browser.
-// 
+//
 // You should see a Hello World program, which you can compile and run by
 // pressing shift-enter. There is also a "compile-on-keypress" feature that can
 // be enabled by checking a checkbox.
-// 
+//
 // WARNING! CUIDADO! ACHTUNG! ATTENZIONE!
 // A note on security: anyone with access to the goplay web interface can run
 // arbitrary code on your computer. Goplay is not a sandbox, and has no other
-// security mechanisms. Do not deploy it in untrusted environments. 
-// By default, goplay listens only on localhost. This can be overridden with 
+// security mechanisms. Do not deploy it in untrusted environments.
+// By default, goplay listens only on localhost. This can be overridden with
 // the -http parameter. Do so at your own risk.
-package documentation
+package main
diff --git a/misc/goplay/goplay.go b/misc/goplay/goplay.go
index 9ce4f89..94d0413 100644
--- a/misc/goplay/goplay.go
+++ b/misc/goplay/goplay.go
@@ -44,7 +44,7 @@ func main() {
 	log.Fatal(http.ListenAndServe(*httpListen, nil))
 }
 
-// FrontPage is an HTTP handler that renders the goplay interface. 
+// FrontPage is an HTTP handler that renders the goplay interface.
 // If a filename is supplied in the path component of the URI,
 // its contents will be put in the interface's text area.
 // Otherwise, the default "hello, world" program is displayed.
diff --git a/misc/osx/README b/misc/osx/README
deleted file mode 100644
index 2408dc4..0000000
--- a/misc/osx/README
+++ /dev/null
@@ -1,3 +0,0 @@
-Use package.bash to construct a package file (Go.pkg) for installation on OS X.
-
-This script depends on PackageMaker (Developer Tools).
diff --git a/misc/osx/etc/paths.d/go b/misc/osx/etc/paths.d/go
deleted file mode 100644
index 532e5f9..0000000
--- a/misc/osx/etc/paths.d/go
+++ /dev/null
@@ -1 +0,0 @@
-/usr/local/go/bin
diff --git a/misc/osx/package.bash b/misc/osx/package.bash
deleted file mode 100755
index d4ee5f4..0000000
--- a/misc/osx/package.bash
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/bash
-# 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.
-
-set -e
-
-if ! test -f ../../src/all.bash; then
-	echo >&2 "package.bash must be run from $GOROOT/misc/osx"
-	exit 1
-fi
-
-echo >&2 "Locating PackageMaker..."
-PM=/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker
-if [ ! -x $PM ]; then
-	PM=/Developer$PM
-	if [ ! -x $PM ]; then
-		echo >&2 "could not find PackageMaker; aborting"
-		exit 1
-	fi
-fi
-echo >&2 "  Found: $PM"
-
-BUILD=/tmp/go.build.tmp
-ROOT=`hg root`
-export GOROOT=$BUILD/root/usr/local/go
-export GOROOT_FINAL=/usr/local/go
-
-echo >&2 "Removing old images"
-rm -f *.pkg *.dmg
-
-echo >&2 "Preparing temporary directory"
-rm -rf $BUILD
-mkdir -p $BUILD
-trap "rm -rf $BUILD" 0
-
-echo >&2 "Copying go source distribution"
-mkdir -p $BUILD/root/usr/local
-cp -r $ROOT $GOROOT
-cp -r etc $BUILD/root/etc
-
-pushd $GOROOT > /dev/null
-
-echo >&2 "Detecting version..."
-pushd src > /dev/null
-./make.bash --dist-tool > /dev/null
-../bin/tool/dist version > /dev/null
-popd > /dev/null
-mv VERSION.cache VERSION
-VERSION="$(cat VERSION | awk '{ print $1 }')"
-echo >&2 "  Version: $VERSION"
-
-echo >&2 "Pruning Mercurial metadata"
-rm -rf .hg .hgignore .hgtags
-
-echo >&2 "Building Go"
-pushd src
-./all.bash 2>&1 | sed "s/^/  /" >&2
-popd > /dev/null
-
-popd > /dev/null
-
-echo >&2 "Building package"
-$PM -v -r $BUILD/root -o "go.darwin.$VERSION.pkg" \
-	--scripts scripts \
-	--id com.googlecode.go \
-	--title Go \
-	--version "0.1" \
-	--target "10.5"
diff --git a/misc/osx/scripts/postinstall b/misc/osx/scripts/postinstall
deleted file mode 100644
index 3748721..0000000
--- a/misc/osx/scripts/postinstall
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-
-GOROOT=/usr/local/go
-
-echo "Fixing permissions"
-cd $GOROOT
-find . -exec chmod ugo+r \{\} \;
-find bin -exec chmod ugo+rx \{\} \;
-find . -type d -exec chmod ugo+rx \{\} \;
-chmod o-w .
-
-echo "Fixing debuggers via sudo.bash"
-# setgrp procmod the debuggers (sudo.bash)
-cd $GOROOT/src
-./sudo.bash
-
-echo "Installing miscellaneous files:"
-XCODE_MISC_DIR="/Library/Application Support/Developer/Shared/Xcode/Specifications/"
-if [ -f $XCODE_MISC_DIR ]; then
-	echo "  XCode"
-	cp $GOROOT/misc/xcode/* $XCODE_MISC_DIR
-fi
-
diff --git a/misc/pprof b/misc/pprof
index 2fe5650..7c379ac 100755
--- a/misc/pprof
+++ b/misc/pprof
@@ -634,7 +634,7 @@ sub Main() {
       # (only matters when --heapcheck is given but we must be
       # compatible with old branches that did not pass --heapcheck always):
       if ($total != 0) {
-        printf("Total: %s %s\n", Unparse($total), Units());
+        Infof("Total: %s %s\n", Unparse($total), Units());
       }
       PrintText($symbols, $flat, $cumulative, $total, -1);
     } elsif ($main::opt_raw) {
@@ -726,10 +726,8 @@ sub RunWeb {
     "firefox",
   );
   foreach my $b (@alt) {
-    if (-f $b) {
-      if (system($b, $fname) == 0) {
-        return;
-      }
+    if (system($b, $fname) == 0) {
+      return;
     }
   }
 
@@ -931,7 +929,7 @@ sub ProcessProfile {
   if ($focus ne '') {
     $profile = FocusProfile($symbols, $profile, $focus);
     my $focus_count = TotalProfile($profile);
-    printf("After focusing on '%s': %s %s of %s (%0.1f%%)\n",
+    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);
@@ -939,7 +937,7 @@ sub ProcessProfile {
   if ($ignore ne '') {
     $profile = IgnoreProfile($symbols, $profile, $ignore);
     my $ignore_count = TotalProfile($profile);
-    printf("After ignoring '%s': %s %s of %s (%0.1f%%)\n",
+    Infof("After ignoring '%s': %s %s of %s (%0.1f%%)\n",
            $ignore,
            Unparse($ignore_count), Units(),
            Unparse($total_count),
@@ -1115,6 +1113,15 @@ sub PrintSymbolizedProfile {
   }
 }
 
+# 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;
@@ -2638,6 +2645,8 @@ sub RemoveUninterestingFrames {
                       'runtime.makemap_c',
                       'runtime.makeslice',
                       'runtime.mal',
+                      'runtime.settype',
+                      'runtime.settype_flush',
                       'runtime.slicebytetostring',
                       'runtime.sliceinttostring',
                       'runtime.stringtoslicebyte',
@@ -2971,32 +2980,32 @@ print STDERR "Read $url\n";
 
 sub IsProfileURL {
   my $profile_name = shift;
-  my ($host, $port, $prefix, $path) = ParseProfileURL($profile_name);
+  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,^(http://|)([^/:]+):(\d+)(|\@\d+)(|/|(.*?)($PROFILE_PAGE|$PMUPROFILE_PAGE|$HEAP_PAGE|$GROWTH_PAGE|$THREAD_PAGE|$CONTENTION_PAGE|$WALL_PAGE|$FILTEREDPROFILE_PAGE))$,o) {
+      $profile_name =~ m,^(?:(https?)://|)([^/:]+):(\d+)(|\@\d+)(|/|(.*?)($PROFILE_PAGE|$PMUPROFILE_PAGE|$HEAP_PAGE|$GROWTH_PAGE|$THREAD_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 ($2, $3, $6, $7 || $5);
+    return ($1 || "http", $2, $3, $6, $7 || $5);
   }
   return ();
 }
 
 # We fetch symbols from the first profile argument.
 sub SymbolPageURL {
-  my ($host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]);
-  return "http://$host:$port$prefix$SYMBOL_PAGE";
+  my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]);
+  return "$scheme://$host:$port$prefix$SYMBOL_PAGE";
 }
 
 sub FetchProgramName() {
-  my ($host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]);
-  my $url = "http://$host:$port$prefix$PROGRAM_NAME_PAGE";
+  my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]);
+  my $url = "$scheme://$host:$port$prefix$PROGRAM_NAME_PAGE";
   my $command_line = "$CURL -s '$url'";
   open(CMDLINE, "$command_line |") or error($command_line);
   my $cmdline = <CMDLINE>;
@@ -3128,7 +3137,7 @@ sub BaseName {
 
 sub MakeProfileBaseName {
   my ($binary_name, $profile_name) = @_;
-  my ($host, $port, $prefix, $path) = ParseProfileURL($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);
@@ -3143,7 +3152,7 @@ sub FetchDynamicProfile {
   if (!IsProfileURL($profile_name)) {
     return $profile_name;
   } else {
-    my ($host, $port, $prefix, $path) = ParseProfileURL($profile_name);
+    my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($profile_name);
     if ($path eq "" || $path eq "/") {
       # Missing type specifier defaults to cpu-profile
       $path = $PROFILE_PAGE;
@@ -3155,7 +3164,7 @@ sub FetchDynamicProfile {
     my $curl_timeout;
     if (($path =~ m/$PROFILE_PAGE/) || ($path =~ m/$PMUPROFILE_PAGE/)) {
       if ($path =~ m/$PROFILE_PAGE/) {
-        $url = sprintf("http://$host:$port$prefix$path?seconds=%d",
+        $url = sprintf("$scheme://$host:$port$prefix$path?seconds=%d",
             $main::opt_seconds);
       } else {
         if ($profile_name =~ m/[?]/) {
@@ -3163,7 +3172,7 @@ sub FetchDynamicProfile {
         } else {
           $profile_name .= "?"
         }
-        $url = sprintf("http://$profile_name" . "seconds=%d",
+        $url = sprintf("$scheme://$profile_name" . "seconds=%d",
             $main::opt_seconds);
       }
       $curl_timeout = sprintf("--max-time %d",
@@ -3174,7 +3183,7 @@ sub FetchDynamicProfile {
       my $suffix = $path;
       $suffix =~ s,/,.,g;
       $profile_file .= "$suffix";
-      $url = "http://$host:$port$prefix$path";
+      $url = "$scheme://$host:$port$prefix$path";
       $curl_timeout = "";
     }
 
@@ -3201,6 +3210,10 @@ sub FetchDynamicProfile {
     }
 
     (system($cmd) == 0) || error("Failed to get profile: $cmd: $!\n");
+    open(TMPPROF, "$tmp_profile") || error("Cannot open $tmp_profile: $!\n");
+    my $line = <TMPPROF>;
+    close(TMPPROF);
+    $line !~ /^Could not enable CPU profiling/ || error($line);
     (system("mv $tmp_profile $real_profile") == 0) || error("Unable to rename profile\n");
     print STDERR "Wrote profile to $real_profile\n";
     $main::collected_profile = $real_profile;
@@ -3753,15 +3766,19 @@ sub ReadHeapProfile {
         } else {
           # Remote-heap version 1
           my $ratio;
-          $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
-          if ($ratio < 1) {
-            $n1 /= $ratio;
-            $s1 /= $ratio;
+          if ($n1 > 0) {
+            $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
+            if ($ratio < 1) {
+                $n1 /= $ratio;
+                $s1 /= $ratio;
+            }
           }
-          $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
-          if ($ratio < 1) {
-            $n2 /= $ratio;
-            $s2 /= $ratio;
+          if ($n2 > 0) {
+            $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
+            if ($ratio < 1) {
+                $n2 /= $ratio;
+                $s2 /= $ratio;
+            }
           }
         }
       }
@@ -4595,6 +4612,7 @@ sub ConfigureObjTools {
     # in the same directory as pprof.
     $obj_tool_map{"nm_pdb"} = "nm-pdb";
     $obj_tool_map{"addr2line_pdb"} = "addr2line-pdb";
+    $obj_tool_map{"is_windows"} = "true";
   }
 
   if ($file_type =~ /Mach-O/) {
@@ -4802,16 +4820,13 @@ sub GetProcedureBoundaries {
                      " $image 2>/dev/null $cppfilt_flag",
                      "$nm -D -n $flatten_flag $demangle_flag" .
                      " $image 2>/dev/null $cppfilt_flag",
-                     # 6nm is for Go binaries
-                     "6nm $image 2>/dev/null | sort");
-
-  # If the executable is an MS Windows PDB-format executable, we'll
-  # have set up obj_tool_map("nm_pdb").  In this case, we actually
-  # want to use both unix nm and windows-specific nm_pdb, since
-  # PDB-format executables can apparently include dwarf .o files.
-  if (exists $obj_tool_map{"nm_pdb"}) {
-    my $nm_pdb = $obj_tool_map{"nm_pdb"};
-    push(@nm_commands, "$nm_pdb --demangle $image 2>/dev/null");
+                     # go tool nm is for Go binaries
+                     "go tool nm $image 2>/dev/null | sort");
+
+  # If the executable is an MS Windows Go executable, we'll
+  # have set up obj_tool_map("is_windows").
+  if (exists $obj_tool_map{"is_windows"}) {
+    @nm_commands = ("go tool nm $image 2>/dev/null | sort");
   }
 
   foreach my $nm_command (@nm_commands) {
diff --git a/misc/swig/callback/Makefile b/misc/swig/callback/Makefile
deleted file mode 100644
index 0ca33ef..0000000
--- a/misc/swig/callback/Makefile
+++ /dev/null
@@ -1,17 +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 ../../../src/Make.inc
-
-TARG=swig/callback
-SWIGFILES=\
-	callback.swigcxx
-
-CLEANFILES+=run
-
-include ../../../src/Make.pkg
-
-%: install %.go
-	$(GC) $(GCFLAGS) $(GCIMPORTS) $*.go
-	$(LD) $(SWIG_RPATH) -o $@ $*.$O
diff --git a/misc/swig/callback/callback.go b/misc/swig/callback/callback.go
new file mode 100644
index 0000000..39c1719
--- /dev/null
+++ b/misc/swig/callback/callback.go
@@ -0,0 +1,11 @@
+// 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 callback
+
+type GoCallback struct{}
+
+func (p *GoCallback) Run() string {
+	return "GoCallback.Run"
+}
diff --git a/misc/swig/callback/callback_test.go b/misc/swig/callback/callback_test.go
new file mode 100644
index 0000000..cf008fb
--- /dev/null
+++ b/misc/swig/callback/callback_test.go
@@ -0,0 +1,34 @@
+// 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 callback_test
+
+import (
+	"../callback"
+	"testing"
+)
+
+func TestCall(t *testing.T) {
+	c := callback.NewCaller()
+	cb := callback.NewCallback()
+
+	c.SetCallback(cb)
+	s := c.Call()
+	if s != "Callback::run" {
+		t.Errorf("unexpected string from Call: %q", s)
+	}
+	c.DelCallback()
+}
+
+func TestCallback(t *testing.T) {
+	c := callback.NewCaller()
+	cb := callback.NewDirectorCallback(&callback.GoCallback{})
+	c.SetCallback(cb)
+	s := c.Call()
+	if s != "GoCallback.Run" {
+		t.Errorf("unexpected string from Call with callback: %q", s)
+	}
+	c.DelCallback()
+	callback.DeleteDirectorCallback(cb)
+}
diff --git a/misc/swig/callback/run.go b/misc/swig/callback/run.go
deleted file mode 100644
index b3f13ad..0000000
--- a/misc/swig/callback/run.go
+++ /dev/null
@@ -1,39 +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 main
-
-import (
-	"fmt"
-	"swig/callback"
-)
-
-type GoCallback struct{}
-
-func (p *GoCallback) Run() string {
-	return "GoCallback.Run"
-}
-
-func main() {
-	c := callback.NewCaller()
-	cb := callback.NewCallback()
-
-	c.SetCallback(cb)
-	s := c.Call()
-	fmt.Println(s)
-	if s != "Callback::run" {
-		panic(s)
-	}
-	c.DelCallback()
-
-	cb = callback.NewDirectorCallback(&GoCallback{})
-	c.SetCallback(cb)
-	s = c.Call()
-	fmt.Println(s)
-	if s != "GoCallback.Run" {
-		panic(s)
-	}
-	c.DelCallback()
-	callback.DeleteDirectorCallback(cb)
-}
diff --git a/misc/swig/stdio/file.swig b/misc/swig/stdio/file.swig
index 57c623f..8ba341d 100644
--- a/misc/swig/stdio/file.swig
+++ b/misc/swig/stdio/file.swig
@@ -6,6 +6,19 @@
 
 %{
 #include <stdio.h>
+#include <stdlib.h>
 %}
 
-int puts(const char *);
+%typemap(gotype) const char * "string"
+%typemap(in) const char * %{
+	$1 = malloc($input.n + 1);
+	memcpy($1, $input.p, $input.n);
+	$1[$input.n] = '\0';
+%}
+%typemap(freearg) const char * %{
+	free($1);
+%}
+
+FILE *fopen(const char *name, const char *mode);
+int fclose(FILE *);
+int fgetc(FILE *);
diff --git a/misc/swig/stdio/file_test.go b/misc/swig/stdio/file_test.go
new file mode 100644
index 0000000..6478a7c
--- /dev/null
+++ b/misc/swig/stdio/file_test.go
@@ -0,0 +1,22 @@
+// 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 file
+
+import "testing"
+
+// Open this file itself and verify that the first few characters are
+// as expected.
+func TestRead(t *testing.T) {
+	f := Fopen("file_test.go", "r")
+	if f == nil {
+		t.Fatal("fopen failed")
+	}
+	if Fgetc(f) != '/' || Fgetc(f) != '/' || Fgetc(f) != ' ' || Fgetc(f) != 'C' {
+		t.Error("read unexpected characters")
+	}
+	if Fclose(f) != 0 {
+		t.Error("fclose failed")
+	}
+}
diff --git a/misc/swig/stdio/hello.go b/misc/swig/stdio/hello.go
deleted file mode 100644
index eec2942..0000000
--- a/misc/swig/stdio/hello.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2011 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "swig/file"
-
-func main() {
-	file.Puts("Hello, world")
-}
diff --git a/misc/vim/autoload/go/complete.vim b/misc/vim/autoload/go/complete.vim
index d4ae3b9..cc1013b 100644
--- a/misc/vim/autoload/go/complete.vim
+++ b/misc/vim/autoload/go/complete.vim
@@ -29,21 +29,43 @@ if len(s:goarch) == 0
 endif
 
 function! go#complete#Package(ArgLead, CmdLine, CursorPos)
-  let goroot = $GOROOT
-  if len(goroot) == 0
-    " should not occur.
-    return []
+  let dirs = []
+
+  if executable('go')
+      let goroot = substitute(system('go env GOROOT'), '\n', '', 'g')
+      if v:shell_error
+          echo '\'go env GOROOT\' failed'
+      endif
+  else
+      let goroot = $GOROOT
   endif
+
+  if len(goroot) != 0 && isdirectory(goroot)
+    let dirs += [ goroot ]
+  endif
+
+  let workspaces = split($GOPATH, ':')
+  if workspaces != []
+      let dirs += workspaces
+  endif
+
+  if len(dirs) == 0
+      " should not happen
+      return []
+  endif
+
   let ret = {}
-  let root = expand(goroot.'/pkg/'.s:goos.'_'.s:goarch)
-  for i in split(globpath(root, a:ArgLead.'*'), "\n")
-    if isdirectory(i)
-      let i .= '/'
-    elseif i !~ '\.a$'
-      continue
-    endif
-    let i = substitute(substitute(i[len(root)+1:], '[\\]', '/', 'g'), '\.a$', '', 'g')
-    let ret[i] = i
+  for dir in dirs
+    let root = expand(dir . '/pkg/' . s:goos . '_' . s:goarch)
+    for i in split(globpath(root, a:ArgLead.'*'), "\n")
+      if isdirectory(i)
+        let i .= '/'
+      elseif i !~ '\.a$'
+        continue
+      endif
+      let i = substitute(substitute(i[len(root)+1:], '[\\]', '/', 'g'), '\.a$', '', 'g')
+      let ret[i] = i
+    endfor
   endfor
   return sort(keys(ret))
 endfunction
diff --git a/misc/vim/ftplugin/go/fmt.vim b/misc/vim/ftplugin/go/fmt.vim
index 0ee44cd..30814fd 100644
--- a/misc/vim/ftplugin/go/fmt.vim
+++ b/misc/vim/ftplugin/go/fmt.vim
@@ -12,6 +12,9 @@
 "       It tries to preserve cursor position and avoids
 "       replacing the buffer with stderr output.
 "
+if exists("b:did_ftplugin_go_fmt")
+    finish
+endif
 
 command! -buffer Fmt call s:GoFormat()
 
@@ -41,4 +44,6 @@ function! s:GoFormat()
     call winrestview(view)
 endfunction
 
+let b:did_ftplugin_go_fmt = 1
+
 " vim:ts=4:sw=4:et
diff --git a/misc/vim/ftplugin/go/godoc.vim b/misc/vim/ftplugin/go/godoc.vim
deleted file mode 100644
index 55195a6..0000000
--- a/misc/vim/ftplugin/go/godoc.vim
+++ /dev/null
@@ -1,13 +0,0 @@
-" Copyright 2011 The Go Authors. All rights reserved.
-" Use of this source code is governed by a BSD-style
-" license that can be found in the LICENSE file.
-"
-" godoc.vim: Vim command to see godoc.
-
-if exists("b:did_ftplugin")
-    finish
-endif
-
-silent! nmap <buffer> <silent> K <Plug>(godoc-keyword)
-
-" vim:ts=4:sw=4:et
diff --git a/misc/vim/ftplugin/go/import.vim b/misc/vim/ftplugin/go/import.vim
index 6705a47..1d969e4 100644
--- a/misc/vim/ftplugin/go/import.vim
+++ b/misc/vim/ftplugin/go/import.vim
@@ -12,7 +12,7 @@
 "       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.
@@ -32,7 +32,7 @@
 " The backslash is the default maplocalleader, so it is possible that
 " your vim is set to use a different character (:help maplocalleader).
 "
-if exists("b:did_ftplugin")
+if exists("b:did_ftplugin_go_import")
     finish
 endif
 
@@ -58,6 +58,12 @@ function! s:SwitchImport(enabled, localname, path)
         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
@@ -83,16 +89,31 @@ function! s:SwitchImport(enabled, localname, path)
             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
@@ -103,7 +124,16 @@ function! s:SwitchImport(enabled, localname, path)
                     let deleteline = line
                     break
                 elseif m[4] < path
-                    let appendline = line
+                    " 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
@@ -198,4 +228,6 @@ 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
new file mode 100755
index 0000000..a6e31d8
--- /dev/null
+++ b/misc/vim/ftplugin/go/test.sh
@@ -0,0 +1,78 @@
+#!/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 ! grep -P -q "(?s)$2" test.go; 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/plugin/godoc.vim b/misc/vim/plugin/godoc.vim
index fdb4966..a9abb7a 100644
--- a/misc/vim/plugin/godoc.vim
+++ b/misc/vim/plugin/godoc.vim
@@ -72,7 +72,7 @@ function! s:Godoc(...)
   if !len(word)
     let word = expand('<cword>')
   endif
-  let word = substitute(word, '[^a-zA-Z0-9\/]', '', 'g')
+  let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g')
   if !len(word)
     return
   endif
diff --git a/misc/vim/readme.txt b/misc/vim/readme.txt
index fe15da9..cb3a520 100644
--- a/misc/vim/readme.txt
+++ b/misc/vim/readme.txt
@@ -1,9 +1,13 @@
 Vim plugins for Go (http://golang.org)
 ======================================
 
-To use all the Vim plugins, add these lines to your vimrc.
+To use all the Vim plugins, add these lines to your $HOME/.vimrc.
 
-  set rtp+=$GOROOT/misc/vim
+  " Some Linux distributions set filetype in /etc/vimrc.
+  " Clear filetype flags before changing runtimepath to force Vim to reload them.
+  filetype off
+  filetype plugin indent off
+  set runtimepath+=$GOROOT/misc/vim
   filetype plugin indent on
   syntax on
 
@@ -72,5 +76,4 @@ 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,
-     ftplugin/go/godoc.vim to $HOME/.vim/ftplugin/go/godoc.vim.
      and autoload/go/complete.vim to $HOME/.vim/autoload/go/complete.vim.
diff --git a/misc/zsh/go b/misc/zsh/go
index 23afa96..dce2554 100644
--- a/misc/zsh/go
+++ b/misc/zsh/go
@@ -88,7 +88,7 @@ __go_tool_complete() {
         "-cpu[values of GOMAXPROCS to use]:number list" \
         "-run[run tests and examples matching regexp]:regexp" \
         "-bench[run benchmarks matching regexp]:regexp" \
-        "-benchtime[run each benchmark during n seconds]:duration" \
+        "-benchtime[run each benchmark until taking this long]:duration" \
         "-timeout[kill test after that duration]:duration" \
         "-cpuprofile[write CPU profile to file]:file:_files" \
         "-memprofile[write heap profile to file]:file:_files" \
diff --git a/src/all.bat b/src/all.bat
index 8edfd7f..8929f77 100644
--- a/src/all.bat
+++ b/src/all.bat
@@ -16,8 +16,11 @@ call make.bat --no-banner --no-local
 if %GOBUILDFAIL%==1 goto end
 call run.bat --no-rebuild --no-local
 if %GOBUILDFAIL%==1 goto end
+:: we must restore %PATH% before running "dist banner" so that the latter
+:: can get the original %PATH% and give suggestion to add %GOROOT%/bin
+:: to %PATH% if necessary.
 set PATH=%OLDPATH%
-go tool dist banner
+%GOTOOLDIR%/dist banner
 
 :end
 if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
diff --git a/src/all.rc b/src/all.rc
new file mode 100755
index 0000000..14e2f55
--- /dev/null
+++ b/src/all.rc
@@ -0,0 +1,16 @@
+#!/bin/rc -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.
+
+rfork n
+
+if(! test -f make.rc){
+	echo 'all.rc must be run from $GOROOT/src' >[1=2]
+	exit wrongdir
+}
+
+. ./make.rc --no-banner
+bind -b $GOROOT/bin /bin
+./run.rc --no-rebuild
+$GOTOOLDIR/dist banner  # print build info
diff --git a/src/clean.rc b/src/clean.rc
new file mode 100755
index 0000000..41cab61
--- /dev/null
+++ b/src/clean.rc
@@ -0,0 +1,14 @@
+#!/bin/rc -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.
+
+eval `{go tool dist env -9}
+
+if(! test -x $GOTOOLDIR/dist){
+	echo 'cannot find $GOTOOLDIR/dist; nothing to clean' >[1=2]
+	exit noclean
+}
+
+$GOBIN/go clean -i std
+$GOTOOLDIR/dist clean
diff --git a/src/cmd/5a/a.y b/src/cmd/5a/a.y
index 512fb5a..c9fdf05 100644
--- a/src/cmd/5a/a.y
+++ b/src/cmd/5a/a.y
@@ -52,7 +52,7 @@
 %token	<lval>	LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
 %token	<lval>	LTYPEB LTYPEC LTYPED LTYPEE LTYPEF
 %token	<lval>	LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
-%token	<lval>	LTYPEL LTYPEM LTYPEN LTYPEBX
+%token	<lval>	LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
 %token	<lval>	LCONST LSP LSB LFP LPC
 %token	<lval>	LTYPEX LR LREG LF LFREG LC LCREG LPSR LFCR
 %token	<lval>	LCOND LS LAT
@@ -286,22 +286,30 @@ inst:
 		outcode(AWORD, Always, &nullgen, NREG, &g);
 	}
 /*
- * MULL hi,lo,r1,r2
+ * MULL r1,r2,(hi,lo)
  */
 |	LTYPEM cond reg ',' reg ',' regreg
 	{
 		outcode($1, $2, &$3, $5.reg, &$7);
 	}
 /*
- * MULA hi,lo,r1,r2
+ * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff -> r4
+ * MULAW{T,B} r1,r2,r3,r4
  */
 |	LTYPEN cond reg ',' reg ',' reg ',' spreg
 	{
-		$7.type = D_REGREG;
+		$7.type = D_REGREG2;
 		$7.offset = $9;
 		outcode($1, $2, &$3, $5.reg, &$7);
 	}
 /*
+ * PLD
+ */
+|	LTYPEPLD oreg
+	{
+		outcode($1, Always, &$2, NREG, &nullgen);
+	}
+/*
  * END
  */
 |	LTYPEE comma
diff --git a/src/cmd/5a/doc.go b/src/cmd/5a/doc.go
index a0d2c4c..29725db 100644
--- a/src/cmd/5a/doc.go
+++ b/src/cmd/5a/doc.go
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build ignore
+
 /*
 
 5a is a version of the Plan 9 assembler.  The original is documented at
 
-	http://plan9.bell-labs.com/magic/man2html/1/2a
+	http://plan9.bell-labs.com/magic/man2html/1/8a
 
 Its target architecture is the ARM, referred to by these tools as arm.
 
 */
-package documentation
+package main
diff --git a/src/cmd/5a/lex.c b/src/cmd/5a/lex.c
index 4bef021..a77e305 100644
--- a/src/cmd/5a/lex.c
+++ b/src/cmd/5a/lex.c
@@ -329,8 +329,6 @@ struct
 	"STREXD",		LTYPE9, ASTREXD,
 
 /*
-	"ABSF",		LTYPEI, AABSF,
-	"ABSD",		LTYPEI, AABSD,
 	"NEGF",		LTYPEI, ANEGF,
 	"NEGD",		LTYPEI, ANEGD,
 	"SQTF",		LTYPEI,	ASQTF,
@@ -343,6 +341,8 @@ struct
 	"NRMD",		LTYPEI,	ANRMD,
 */
 
+	"ABSF",		LTYPEI, AABSF,
+	"ABSD",		LTYPEI, AABSD,
 	"SQRTF",	LTYPEI, ASQRTF,
 	"SQRTD",	LTYPEI, ASQRTD,
 	"CMPF",		LTYPEL, ACMPF,
@@ -403,6 +403,18 @@ struct
 
 	"MCR",		LTYPEJ, 0,
 	"MRC",		LTYPEJ, 1,
+
+	"PLD",		LTYPEPLD, APLD,
+	"UNDEF",	LTYPEE,	AUNDEF,
+	"CLZ",		LTYPE2, ACLZ,
+
+	"MULWT",	LTYPE1, AMULWT,
+	"MULWB",	LTYPE1, AMULWB,
+	"MULAWT",	LTYPEN, AMULAWT,
+	"MULAWB",	LTYPEN, AMULAWB,
+
+	"USEFIELD",	LTYPEN, AUSEFIELD,
+
 	0
 };
 
@@ -493,6 +505,7 @@ zaddr(Gen *a, int s)
 	Bputc(&obuf, a->reg);
 	Bputc(&obuf, s);
 	Bputc(&obuf, a->name);
+	Bputc(&obuf, 0);
 	switch(a->type) {
 	default:
 		print("unknown type %d\n", a->type);
@@ -506,6 +519,7 @@ zaddr(Gen *a, int s)
 		break;
 
 	case D_REGREG:
+	case D_REGREG2:
 		Bputc(&obuf, a->offset);
 		break;
 
@@ -641,11 +655,37 @@ outhist(void)
 	Hist *h;
 	char *p, *q, *op, c;
 	int n;
-
+ 	char *tofree;
+ 	static int first = 1;
+ 	static char *goroot, *goroot_final;
+ 
+ 	if(first) {
+ 		// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
+ 		first = 0;
+ 		goroot = getenv("GOROOT");
+ 		goroot_final = getenv("GOROOT_FINAL");
+ 		if(goroot == nil)
+ 			goroot = "";
+ 		if(goroot_final == nil)
+ 			goroot_final = goroot;
+ 		if(strcmp(goroot, goroot_final) == 0) {
+ 			goroot = nil;
+ 			goroot_final = nil;
+ 		}
+ 	}
+ 
+ 	tofree = nil;
 	g = nullgen;
 	c = '/';
 	for(h = hist; h != H; h = h->link) {
 		p = h->name;
+ 		if(p != nil && goroot != nil) {
+ 			n = strlen(goroot);
+ 			if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
+ 				tofree = smprint("%s%s", goroot_final, p+n);
+ 				p = tofree;
+ 			}
+ 		}
 		op = 0;
 		if(systemtype(Windows) && p && p[1] == ':'){
 			c = p[2];
@@ -697,6 +737,11 @@ outhist(void)
 		Bputc(&obuf, h->line>>24);
 		zaddr(&nullgen, 0);
 		zaddr(&g, 0);
+
+		if(tofree) {
+			free(tofree);
+			tofree = nil;
+		}
 	}
 }
 
diff --git a/src/cmd/5a/y.tab.c b/src/cmd/5a/y.tab.c
index a2fba60..ce97ee3 100644
--- a/src/cmd/5a/y.tab.c
+++ b/src/cmd/5a/y.tab.c
@@ -128,28 +128,29 @@
      LTYPEM = 279,
      LTYPEN = 280,
      LTYPEBX = 281,
-     LCONST = 282,
-     LSP = 283,
-     LSB = 284,
-     LFP = 285,
-     LPC = 286,
-     LTYPEX = 287,
-     LR = 288,
-     LREG = 289,
-     LF = 290,
-     LFREG = 291,
-     LC = 292,
-     LCREG = 293,
-     LPSR = 294,
-     LFCR = 295,
-     LCOND = 296,
-     LS = 297,
-     LAT = 298,
-     LFCONST = 299,
-     LSCONST = 300,
-     LNAME = 301,
-     LLAB = 302,
-     LVAR = 303
+     LTYPEPLD = 282,
+     LCONST = 283,
+     LSP = 284,
+     LSB = 285,
+     LFP = 286,
+     LPC = 287,
+     LTYPEX = 288,
+     LR = 289,
+     LREG = 290,
+     LF = 291,
+     LFREG = 292,
+     LC = 293,
+     LCREG = 294,
+     LPSR = 295,
+     LFCR = 296,
+     LCOND = 297,
+     LS = 298,
+     LAT = 299,
+     LFCONST = 300,
+     LSCONST = 301,
+     LNAME = 302,
+     LLAB = 303,
+     LVAR = 304
    };
 #endif
 /* Tokens.  */
@@ -177,28 +178,29 @@
 #define LTYPEM 279
 #define LTYPEN 280
 #define LTYPEBX 281
-#define LCONST 282
-#define LSP 283
-#define LSB 284
-#define LFP 285
-#define LPC 286
-#define LTYPEX 287
-#define LR 288
-#define LREG 289
-#define LF 290
-#define LFREG 291
-#define LC 292
-#define LCREG 293
-#define LPSR 294
-#define LFCR 295
-#define LCOND 296
-#define LS 297
-#define LAT 298
-#define LFCONST 299
-#define LSCONST 300
-#define LNAME 301
-#define LLAB 302
-#define LVAR 303
+#define LTYPEPLD 282
+#define LCONST 283
+#define LSP 284
+#define LSB 285
+#define LFP 286
+#define LPC 287
+#define LTYPEX 288
+#define LR 289
+#define LREG 290
+#define LF 291
+#define LFREG 292
+#define LC 293
+#define LCREG 294
+#define LPSR 295
+#define LFCR 296
+#define LCOND 297
+#define LS 298
+#define LAT 299
+#define LFCONST 300
+#define LSCONST 301
+#define LNAME 302
+#define LLAB 303
+#define LVAR 304
 
 
 
@@ -219,7 +221,7 @@ typedef union YYSTYPE
 
 
 /* Line 214 of yacc.c  */
-#line 223 "y.tab.c"
+#line 225 "y.tab.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -231,7 +233,7 @@ typedef union YYSTYPE
 
 
 /* Line 264 of yacc.c  */
-#line 235 "y.tab.c"
+#line 237 "y.tab.c"
 
 #ifdef short
 # undef short
@@ -446,20 +448,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   643
+#define YYLAST   603
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  69
+#define YYNTOKENS  70
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  35
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  129
+#define YYNRULES  130
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  327
+#define YYNSTATES  329
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   303
+#define YYMAXUTOK   304
 
 #define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -470,16 +472,16 @@ static const yytype_uint8 yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,    67,    12,     5,     2,
-      65,    66,    10,     8,    62,     9,     2,    11,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    59,    61,
-       6,    60,     7,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,    68,    12,     5,     2,
+      66,    67,    10,     8,    63,     9,     2,    11,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    60,    62,
+       6,    61,     7,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    63,     2,    64,     4,     2,     2,     2,     2,     2,
+       2,    64,     2,    65,     4,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     3,     2,    68,     2,     2,     2,
+       2,     2,     2,     2,     3,     2,    69,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -497,7 +499,7 @@ static const yytype_uint8 yytranslate[] =
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
       35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
       45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58
+      55,    56,    57,    58,    59
 };
 
 #if YYDEBUG
@@ -509,71 +511,72 @@ static const yytype_uint16 yyprhs[] =
       26,    31,    33,    36,    39,    47,    54,    60,    66,    72,
       77,    82,    86,    90,    95,   102,   110,   118,   126,   133,
      140,   144,   149,   156,   163,   168,   172,   178,   184,   192,
-     199,   212,   220,   230,   233,   234,   237,   240,   241,   244,
-     249,   252,   255,   258,   261,   266,   269,   271,   274,   278,
-     280,   284,   288,   290,   292,   294,   299,   301,   303,   305,
-     307,   309,   311,   313,   317,   319,   324,   326,   331,   333,
-     335,   337,   339,   342,   344,   350,   355,   360,   365,   370,
-     372,   374,   376,   378,   383,   385,   387,   389,   394,   396,
-     398,   400,   405,   410,   416,   424,   425,   428,   431,   433,
-     435,   437,   439,   441,   444,   447,   450,   454,   455,   458,
-     460,   464,   468,   472,   476,   480,   485,   490,   494,   498
+     199,   212,   220,   230,   233,   236,   237,   240,   243,   244,
+     247,   252,   255,   258,   261,   264,   269,   272,   274,   277,
+     281,   283,   287,   291,   293,   295,   297,   302,   304,   306,
+     308,   310,   312,   314,   316,   320,   322,   327,   329,   334,
+     336,   338,   340,   342,   345,   347,   353,   358,   363,   368,
+     373,   375,   377,   379,   381,   386,   388,   390,   392,   397,
+     399,   401,   403,   408,   413,   419,   427,   428,   431,   434,
+     436,   438,   440,   442,   444,   447,   450,   453,   457,   458,
+     461,   463,   467,   471,   475,   479,   483,   488,   493,   497,
+     501
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      70,     0,    -1,    -1,    -1,    70,    71,    72,    -1,    -1,
-      57,    59,    73,    72,    -1,    -1,    56,    59,    74,    72,
-      -1,    56,    60,   103,    61,    -1,    58,    60,   103,    61,
-      -1,    61,    -1,    75,    61,    -1,     1,    61,    -1,    13,
-      76,    87,    62,    94,    62,    89,    -1,    13,    76,    87,
-      62,    94,    62,    -1,    13,    76,    87,    62,    89,    -1,
-      14,    76,    87,    62,    89,    -1,    15,    76,    82,    62,
-      82,    -1,    16,    76,    77,    78,    -1,    16,    76,    77,
-      83,    -1,    36,    77,    84,    -1,    17,    77,    78,    -1,
-      18,    76,    77,    82,    -1,    19,    76,    87,    62,    94,
-      77,    -1,    20,    76,    85,    62,    63,    81,    64,    -1,
-      20,    76,    63,    81,    64,    62,    85,    -1,    21,    76,
-      89,    62,    84,    62,    89,    -1,    21,    76,    89,    62,
-      84,    77,    -1,    21,    76,    77,    84,    62,    89,    -1,
-      22,    76,    77,    -1,    23,    98,    62,    88,    -1,    23,
-      98,    62,   101,    62,    88,    -1,    24,    98,    11,   101,
-      62,    79,    -1,    25,    76,    89,    77,    -1,    29,    77,
-      79,    -1,    30,    76,    97,    62,    97,    -1,    32,    76,
-      96,    62,    97,    -1,    32,    76,    96,    62,    46,    62,
-      97,    -1,    33,    76,    97,    62,    97,    77,    -1,    31,
-      76,   101,    62,   103,    62,    94,    62,    95,    62,    95,
-     102,    -1,    34,    76,    89,    62,    89,    62,    90,    -1,
-      35,    76,    89,    62,    89,    62,    89,    62,    94,    -1,
-      26,    77,    -1,    -1,    76,    51,    -1,    76,    52,    -1,
-      -1,    62,    77,    -1,   101,    65,    41,    66,    -1,    56,
-      99,    -1,    57,    99,    -1,    67,   101,    -1,    67,    86,
-      -1,    67,    10,    67,    86,    -1,    67,    55,    -1,    80,
-      -1,    67,    54,    -1,    67,     9,    54,    -1,    94,    -1,
-      94,     9,    94,    -1,    94,    77,    81,    -1,    89,    -1,
-      79,    -1,    91,    -1,    91,    65,    94,    66,    -1,    49,
-      -1,    50,    -1,   101,    -1,    86,    -1,    97,    -1,    84,
-      -1,    98,    -1,    65,    94,    66,    -1,    84,    -1,   101,
-      65,    93,    66,    -1,    98,    -1,    98,    65,    93,    66,
-      -1,    85,    -1,    89,    -1,    88,    -1,    91,    -1,    67,
-     101,    -1,    94,    -1,    65,    94,    62,    94,    66,    -1,
-      94,     6,     6,    92,    -1,    94,     7,     7,    92,    -1,
-      94,     9,     7,    92,    -1,    94,    53,     7,    92,    -1,
-      94,    -1,   101,    -1,    44,    -1,    41,    -1,    43,    65,
-     103,    66,    -1,    93,    -1,    38,    -1,    48,    -1,    47,
-      65,   103,    66,    -1,    97,    -1,    80,    -1,    46,    -1,
-      45,    65,   101,    66,    -1,   101,    65,   100,    66,    -1,
-      56,    99,    65,   100,    66,    -1,    56,     6,     7,    99,
-      65,    39,    66,    -1,    -1,     8,   101,    -1,     9,   101,
-      -1,    39,    -1,    38,    -1,    40,    -1,    37,    -1,    58,
-      -1,     9,   101,    -1,     8,   101,    -1,    68,   101,    -1,
-      65,   103,    66,    -1,    -1,    62,   103,    -1,   101,    -1,
-     103,     8,   103,    -1,   103,     9,   103,    -1,   103,    10,
-     103,    -1,   103,    11,   103,    -1,   103,    12,   103,    -1,
-     103,     6,     6,   103,    -1,   103,     7,     7,   103,    -1,
-     103,     5,   103,    -1,   103,     4,   103,    -1,   103,     3,
-     103,    -1
+      71,     0,    -1,    -1,    -1,    71,    72,    73,    -1,    -1,
+      58,    60,    74,    73,    -1,    -1,    57,    60,    75,    73,
+      -1,    57,    61,   104,    62,    -1,    59,    61,   104,    62,
+      -1,    62,    -1,    76,    62,    -1,     1,    62,    -1,    13,
+      77,    88,    63,    95,    63,    90,    -1,    13,    77,    88,
+      63,    95,    63,    -1,    13,    77,    88,    63,    90,    -1,
+      14,    77,    88,    63,    90,    -1,    15,    77,    83,    63,
+      83,    -1,    16,    77,    78,    79,    -1,    16,    77,    78,
+      84,    -1,    36,    78,    85,    -1,    17,    78,    79,    -1,
+      18,    77,    78,    83,    -1,    19,    77,    88,    63,    95,
+      78,    -1,    20,    77,    86,    63,    64,    82,    65,    -1,
+      20,    77,    64,    82,    65,    63,    86,    -1,    21,    77,
+      90,    63,    85,    63,    90,    -1,    21,    77,    90,    63,
+      85,    78,    -1,    21,    77,    78,    85,    63,    90,    -1,
+      22,    77,    78,    -1,    23,    99,    63,    89,    -1,    23,
+      99,    63,   102,    63,    89,    -1,    24,    99,    11,   102,
+      63,    80,    -1,    25,    77,    90,    78,    -1,    29,    78,
+      80,    -1,    30,    77,    98,    63,    98,    -1,    32,    77,
+      97,    63,    98,    -1,    32,    77,    97,    63,    47,    63,
+      98,    -1,    33,    77,    98,    63,    98,    78,    -1,    31,
+      77,   102,    63,   104,    63,    95,    63,    96,    63,    96,
+     103,    -1,    34,    77,    90,    63,    90,    63,    91,    -1,
+      35,    77,    90,    63,    90,    63,    90,    63,    95,    -1,
+      37,    87,    -1,    26,    78,    -1,    -1,    77,    52,    -1,
+      77,    53,    -1,    -1,    63,    78,    -1,   102,    66,    42,
+      67,    -1,    57,   100,    -1,    58,   100,    -1,    68,   102,
+      -1,    68,    87,    -1,    68,    10,    68,    87,    -1,    68,
+      56,    -1,    81,    -1,    68,    55,    -1,    68,     9,    55,
+      -1,    95,    -1,    95,     9,    95,    -1,    95,    78,    82,
+      -1,    90,    -1,    80,    -1,    92,    -1,    92,    66,    95,
+      67,    -1,    50,    -1,    51,    -1,   102,    -1,    87,    -1,
+      98,    -1,    85,    -1,    99,    -1,    66,    95,    67,    -1,
+      85,    -1,   102,    66,    94,    67,    -1,    99,    -1,    99,
+      66,    94,    67,    -1,    86,    -1,    90,    -1,    89,    -1,
+      92,    -1,    68,   102,    -1,    95,    -1,    66,    95,    63,
+      95,    67,    -1,    95,     6,     6,    93,    -1,    95,     7,
+       7,    93,    -1,    95,     9,     7,    93,    -1,    95,    54,
+       7,    93,    -1,    95,    -1,   102,    -1,    45,    -1,    42,
+      -1,    44,    66,   104,    67,    -1,    94,    -1,    39,    -1,
+      49,    -1,    48,    66,   104,    67,    -1,    98,    -1,    81,
+      -1,    47,    -1,    46,    66,   102,    67,    -1,   102,    66,
+     101,    67,    -1,    57,   100,    66,   101,    67,    -1,    57,
+       6,     7,   100,    66,    40,    67,    -1,    -1,     8,   102,
+      -1,     9,   102,    -1,    40,    -1,    39,    -1,    41,    -1,
+      38,    -1,    59,    -1,     9,   102,    -1,     8,   102,    -1,
+      69,   102,    -1,    66,   104,    67,    -1,    -1,    63,   104,
+      -1,   102,    -1,   104,     8,   104,    -1,   104,     9,   104,
+      -1,   104,    10,   104,    -1,   104,    11,   104,    -1,   104,
+      12,   104,    -1,   104,     6,     6,   104,    -1,   104,     7,
+       7,   104,    -1,   104,     5,   104,    -1,   104,     4,   104,
+      -1,   104,     3,   104,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
@@ -583,15 +586,16 @@ static const yytype_uint16 yyrline[] =
       93,    99,   100,   101,   107,   111,   115,   122,   129,   136,
      140,   147,   154,   161,   168,   175,   184,   196,   200,   204,
      211,   218,   222,   229,   236,   243,   250,   254,   258,   262,
-     269,   291,   298,   307,   313,   316,   320,   325,   326,   329,
-     335,   344,   352,   358,   363,   368,   374,   377,   383,   391,
-     395,   404,   410,   411,   412,   413,   418,   424,   430,   436,
-     437,   440,   441,   449,   458,   459,   468,   469,   475,   478,
-     479,   480,   482,   490,   498,   507,   513,   519,   525,   533,
-     539,   547,   548,   552,   560,   561,   567,   568,   576,   577,
-     580,   586,   594,   602,   610,   620,   623,   627,   633,   634,
-     635,   638,   639,   643,   647,   651,   655,   661,   664,   670,
-     671,   675,   679,   683,   687,   691,   695,   699,   703,   707
+     269,   291,   299,   308,   315,   321,   324,   328,   333,   334,
+     337,   343,   352,   360,   366,   371,   376,   382,   385,   391,
+     399,   403,   412,   418,   419,   420,   421,   426,   432,   438,
+     444,   445,   448,   449,   457,   466,   467,   476,   477,   483,
+     486,   487,   488,   490,   498,   506,   515,   521,   527,   533,
+     541,   547,   555,   556,   560,   568,   569,   575,   576,   584,
+     585,   588,   594,   602,   610,   618,   628,   631,   635,   641,
+     642,   643,   646,   647,   651,   655,   659,   663,   669,   672,
+     678,   679,   683,   687,   691,   695,   699,   703,   707,   711,
+     715
 };
 #endif
 
@@ -604,13 +608,13 @@ static const char *const yytname[] =
   "'-'", "'*'", "'/'", "'%'", "LTYPE1", "LTYPE2", "LTYPE3", "LTYPE4",
   "LTYPE5", "LTYPE6", "LTYPE7", "LTYPE8", "LTYPE9", "LTYPEA", "LTYPEB",
   "LTYPEC", "LTYPED", "LTYPEE", "LTYPEF", "LTYPEG", "LTYPEH", "LTYPEI",
-  "LTYPEJ", "LTYPEK", "LTYPEL", "LTYPEM", "LTYPEN", "LTYPEBX", "LCONST",
-  "LSP", "LSB", "LFP", "LPC", "LTYPEX", "LR", "LREG", "LF", "LFREG", "LC",
-  "LCREG", "LPSR", "LFCR", "LCOND", "LS", "LAT", "LFCONST", "LSCONST",
-  "LNAME", "LLAB", "LVAR", "':'", "'='", "';'", "','", "'['", "']'", "'('",
-  "')'", "'$'", "'~'", "$accept", "prog", "$@1", "line", "$@2", "$@3",
-  "inst", "cond", "comma", "rel", "ximm", "fcon", "reglist", "gen",
-  "nireg", "ireg", "ioreg", "oreg", "imsr", "imm", "reg", "regreg",
+  "LTYPEJ", "LTYPEK", "LTYPEL", "LTYPEM", "LTYPEN", "LTYPEBX", "LTYPEPLD",
+  "LCONST", "LSP", "LSB", "LFP", "LPC", "LTYPEX", "LR", "LREG", "LF",
+  "LFREG", "LC", "LCREG", "LPSR", "LFCR", "LCOND", "LS", "LAT", "LFCONST",
+  "LSCONST", "LNAME", "LLAB", "LVAR", "':'", "'='", "';'", "','", "'['",
+  "']'", "'('", "')'", "'$'", "'~'", "$accept", "prog", "$@1", "line",
+  "$@2", "$@3", "inst", "cond", "comma", "rel", "ximm", "fcon", "reglist",
+  "gen", "nireg", "ireg", "ioreg", "oreg", "imsr", "imm", "reg", "regreg",
   "shift", "rcon", "sreg", "spreg", "creg", "frcon", "freg", "name",
   "offset", "pointer", "con", "oexpr", "expr", 0
 };
@@ -626,27 +630,28 @@ static const yytype_uint16 yytoknum[] =
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
      285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,   298,   299,   300,   301,   302,   303,    58,
-      61,    59,    44,    91,    93,    40,    41,    36,   126
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+      58,    61,    59,    44,    91,    93,    40,    41,    36,   126
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    69,    70,    71,    70,    73,    72,    74,    72,    72,
-      72,    72,    72,    72,    75,    75,    75,    75,    75,    75,
-      75,    75,    75,    75,    75,    75,    75,    75,    75,    75,
-      75,    75,    75,    75,    75,    75,    75,    75,    75,    75,
-      75,    75,    75,    75,    76,    76,    76,    77,    77,    78,
-      78,    78,    79,    79,    79,    79,    79,    80,    80,    81,
-      81,    81,    82,    82,    82,    82,    82,    82,    82,    82,
-      82,    83,    83,    84,    85,    85,    86,    86,    86,    87,
-      87,    87,    88,    89,    90,    91,    91,    91,    91,    92,
-      92,    93,    93,    93,    94,    94,    95,    95,    96,    96,
-      97,    97,    98,    98,    98,    99,    99,    99,   100,   100,
-     100,   101,   101,   101,   101,   101,   101,   102,   102,   103,
-     103,   103,   103,   103,   103,   103,   103,   103,   103,   103
+       0,    70,    71,    72,    71,    74,    73,    75,    73,    73,
+      73,    73,    73,    73,    76,    76,    76,    76,    76,    76,
+      76,    76,    76,    76,    76,    76,    76,    76,    76,    76,
+      76,    76,    76,    76,    76,    76,    76,    76,    76,    76,
+      76,    76,    76,    76,    76,    77,    77,    77,    78,    78,
+      79,    79,    79,    80,    80,    80,    80,    80,    81,    81,
+      82,    82,    82,    83,    83,    83,    83,    83,    83,    83,
+      83,    83,    84,    84,    85,    86,    86,    87,    87,    87,
+      88,    88,    88,    89,    90,    91,    92,    92,    92,    92,
+      93,    93,    94,    94,    94,    95,    95,    96,    96,    97,
+      97,    98,    98,    99,    99,    99,   100,   100,   100,   101,
+     101,   101,   102,   102,   102,   102,   102,   102,   103,   103,
+     104,   104,   104,   104,   104,   104,   104,   104,   104,   104,
+     104
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -656,15 +661,16 @@ static const yytype_uint8 yyr2[] =
        4,     1,     2,     2,     7,     6,     5,     5,     5,     4,
        4,     3,     3,     4,     6,     7,     7,     7,     6,     6,
        3,     4,     6,     6,     4,     3,     5,     5,     7,     6,
-      12,     7,     9,     2,     0,     2,     2,     0,     2,     4,
-       2,     2,     2,     2,     4,     2,     1,     2,     3,     1,
-       3,     3,     1,     1,     1,     4,     1,     1,     1,     1,
-       1,     1,     1,     3,     1,     4,     1,     4,     1,     1,
-       1,     1,     2,     1,     5,     4,     4,     4,     4,     1,
-       1,     1,     1,     4,     1,     1,     1,     4,     1,     1,
-       1,     4,     4,     5,     7,     0,     2,     2,     1,     1,
-       1,     1,     1,     2,     2,     2,     3,     0,     2,     1,
-       3,     3,     3,     3,     3,     4,     4,     3,     3,     3
+      12,     7,     9,     2,     2,     0,     2,     2,     0,     2,
+       4,     2,     2,     2,     2,     4,     2,     1,     2,     3,
+       1,     3,     3,     1,     1,     1,     4,     1,     1,     1,
+       1,     1,     1,     1,     3,     1,     4,     1,     4,     1,
+       1,     1,     1,     2,     1,     5,     4,     4,     4,     4,
+       1,     1,     1,     1,     4,     1,     1,     1,     4,     1,
+       1,     1,     4,     4,     5,     7,     0,     2,     2,     1,
+       1,     1,     1,     1,     2,     2,     2,     3,     0,     2,
+       1,     3,     3,     3,     3,     3,     4,     4,     3,     3,
+       3
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -672,279 +678,271 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       2,     3,     1,     0,     0,    44,    44,    44,    44,    47,
-      44,    44,    44,    44,    44,     0,     0,    44,    47,    47,
-      44,    44,    44,    44,    44,    44,    47,     0,     0,     0,
-      11,     4,     0,    13,     0,     0,     0,    47,    47,     0,
-      47,     0,     0,    47,    47,     0,     0,   111,   105,   112,
-       0,     0,     0,     0,     0,     0,    43,     0,     0,     0,
-       0,     0,     0,     0,     0,     7,     0,     5,     0,    12,
-      95,    92,     0,    91,    45,    46,     0,     0,    80,    79,
-      81,    94,    83,     0,     0,   100,    66,    67,     0,     0,
-      63,    56,     0,    74,    78,    69,    62,    64,    70,    76,
-      68,     0,    48,   105,   105,    22,     0,     0,     0,     0,
-       0,     0,     0,     0,    83,    30,   114,   113,     0,     0,
-       0,     0,   119,     0,   115,     0,     0,     0,    47,    35,
-       0,     0,     0,    99,     0,    98,     0,     0,     0,     0,
-      21,     0,     0,     0,     0,     0,    82,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    57,    55,    53,
-      52,     0,     0,     0,     0,   105,    19,    20,    71,    72,
-       0,    50,    51,     0,    23,     0,     0,    47,     0,     0,
-       0,     0,   105,   106,   107,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   116,    31,     0,   109,
-     108,   110,     0,     0,    34,     0,     0,     0,     0,     0,
-       0,     0,     8,     9,     6,    10,     0,    16,    83,     0,
-       0,     0,     0,    17,     0,    73,    58,     0,    18,     0,
-       0,     0,    50,     0,     0,    47,     0,     0,     0,     0,
-       0,    47,     0,     0,   129,   128,   127,     0,     0,   120,
-     121,   122,   123,   124,     0,   102,     0,    36,     0,   100,
-      37,    47,     0,     0,    93,    15,    85,    89,    90,    86,
-      87,    88,   101,    54,     0,    65,    77,    75,    49,    24,
-       0,    60,    61,     0,    29,    47,    28,     0,   103,   125,
-     126,    32,    33,     0,     0,    39,     0,     0,    14,    26,
-      25,    27,     0,     0,    38,     0,    41,     0,   104,     0,
-       0,     0,     0,    96,     0,     0,    42,     0,     0,     0,
-       0,   117,    84,    97,     0,    40,   118
+       2,     3,     1,     0,     0,    45,    45,    45,    45,    48,
+      45,    45,    45,    45,    45,     0,     0,    45,    48,    48,
+      45,    45,    45,    45,    45,    45,    48,     0,     0,     0,
+       0,    11,     4,     0,    13,     0,     0,     0,    48,    48,
+       0,    48,     0,     0,    48,    48,     0,     0,   112,   106,
+     113,     0,     0,     0,     0,     0,     0,    44,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    75,    79,    43,
+      77,     0,     7,     0,     5,     0,    12,    96,    93,     0,
+      92,    46,    47,     0,     0,    81,    80,    82,    95,    84,
+       0,     0,   101,    67,    68,     0,    64,    57,     0,    70,
+      63,    65,    71,    69,     0,    49,   106,   106,    22,     0,
+       0,     0,     0,     0,     0,     0,     0,    84,    30,   115,
+     114,     0,     0,     0,     0,   120,     0,   116,     0,     0,
+       0,    48,    35,     0,     0,     0,   100,     0,    99,     0,
+       0,     0,     0,    21,     0,     0,     0,     0,     0,     0,
+       0,     0,    83,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    58,    56,    54,    53,     0,     0,   106,    19,
+      20,    72,    73,     0,    51,    52,     0,    23,     0,     0,
+      48,     0,     0,     0,     0,   106,   107,   108,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   117,
+      31,     0,   110,   109,   111,     0,     0,    34,     0,     0,
+       0,     0,     0,     0,     0,    74,     0,     0,     8,     9,
+       6,    10,     0,    16,    84,     0,     0,     0,     0,    17,
+       0,    59,     0,    18,     0,    51,     0,     0,    48,     0,
+       0,     0,     0,     0,    48,     0,     0,   130,   129,   128,
+       0,     0,   121,   122,   123,   124,   125,     0,   103,     0,
+      36,     0,   101,    37,    48,     0,     0,    78,    76,    94,
+      15,    86,    90,    91,    87,    88,    89,   102,    55,    66,
+      50,    24,     0,    61,    62,     0,    29,    48,    28,     0,
+     104,   126,   127,    32,    33,     0,     0,    39,     0,     0,
+      14,    26,    25,    27,     0,     0,    38,     0,    41,     0,
+     105,     0,     0,     0,     0,    97,     0,     0,    42,     0,
+       0,     0,     0,   118,    85,    98,     0,    40,   119
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     3,    31,   143,   141,    32,    34,   102,   105,
-      90,    91,   176,    92,   167,    93,    94,    95,    77,    78,
-      79,   306,    80,   266,    81,   114,   314,   134,    98,    99,
-     121,   202,   122,   325,   123
+      -1,     1,     3,    32,   149,   147,    33,    35,   105,   108,
+      96,    97,   179,    98,   170,    67,    68,    99,    84,    85,
+      86,   308,    87,   271,    88,   117,   316,   137,   102,    70,
+     124,   205,   125,   327,   126
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -147
+#define YYPACT_NINF -114
 static const yytype_int16 yypact[] =
 {
-    -147,    19,  -147,   305,   -37,  -147,  -147,  -147,  -147,   -40,
-    -147,  -147,  -147,  -147,  -147,   448,   448,  -147,   -40,   -40,
-    -147,  -147,  -147,  -147,  -147,  -147,   -40,    -8,   -22,   -21,
-    -147,  -147,   -20,  -147,   102,   102,   334,   108,   -40,   416,
-     108,   102,   397,    48,   108,   482,   482,  -147,    95,  -147,
-     482,   482,   -19,    18,    34,   223,  -147,     5,   174,   424,
-     132,   174,   223,   223,    20,  -147,   482,  -147,   482,  -147,
-    -147,  -147,    30,  -147,  -147,  -147,   482,    35,  -147,  -147,
-    -147,  -147,    49,    76,    84,  -147,  -147,  -147,   205,   339,
-    -147,  -147,    93,  -147,  -147,  -147,  -147,   110,  -147,   124,
-     125,   442,  -147,    98,    98,  -147,   128,   373,   134,    36,
-     144,   147,    20,   153,  -147,  -147,  -147,  -147,    60,   482,
-     482,   175,  -147,   114,  -147,   249,    21,   482,   -40,  -147,
-     182,   183,    12,  -147,   185,  -147,   188,   189,   198,    36,
-    -147,   305,   562,   305,   572,   482,  -147,    36,   256,   258,
-     261,   269,    36,   482,   212,   460,   216,  -147,  -147,  -147,
-     125,   373,    36,   138,   586,    95,  -147,  -147,  -147,  -147,
-     217,  -147,  -147,   247,  -147,    36,   226,     7,   229,   138,
-     227,    20,    98,  -147,  -147,    21,   482,   482,   482,   287,
-     301,   482,   482,   482,   482,   482,  -147,  -147,   248,  -147,
-    -147,  -147,   243,   250,  -147,    66,   482,   257,   106,    66,
-      36,    36,  -147,  -147,  -147,  -147,   225,  -147,   251,   205,
-     205,   205,   205,  -147,   266,  -147,  -147,   478,  -147,   267,
-     278,   279,   175,   215,   280,   -40,   253,    36,    36,    36,
-      36,   297,   295,   298,   601,   345,   609,   482,   482,   190,
-     190,  -147,  -147,  -147,   300,  -147,     5,  -147,   552,   303,
-    -147,   -40,   306,   307,  -147,    36,  -147,  -147,  -147,  -147,
-    -147,  -147,  -147,  -147,   125,  -147,  -147,  -147,  -147,  -147,
-     486,  -147,  -147,   309,  -147,   130,  -147,   331,  -147,   121,
-     121,  -147,  -147,    36,    66,  -147,   322,    36,  -147,  -147,
-    -147,  -147,   308,   326,  -147,    36,  -147,   327,  -147,   119,
-     329,    36,   333,  -147,   338,    36,  -147,   482,   119,   330,
-     292,   341,  -147,  -147,   482,  -147,   631
+    -114,    19,  -114,   311,   -20,  -114,  -114,  -114,  -114,   -36,
+    -114,  -114,  -114,  -114,  -114,   413,   413,  -114,   -36,   -36,
+    -114,  -114,  -114,  -114,  -114,  -114,   -36,   427,   -22,    -9,
+      -7,  -114,  -114,    11,  -114,   480,   480,   341,    45,   -36,
+     229,    45,   480,   210,   436,    45,   435,   435,  -114,   152,
+    -114,   435,   435,    25,    15,    79,   517,  -114,    24,   134,
+     393,   197,   134,   517,   517,    28,    71,  -114,  -114,  -114,
+      35,    58,  -114,   435,  -114,   435,  -114,  -114,  -114,    69,
+    -114,  -114,  -114,   435,    51,  -114,  -114,  -114,  -114,    46,
+      57,    75,  -114,  -114,  -114,   119,  -114,  -114,    82,  -114,
+    -114,    88,  -114,    58,   368,  -114,   159,   159,  -114,   113,
+     373,   114,   411,   120,   123,    28,   145,  -114,  -114,  -114,
+    -114,   193,   435,   435,   173,  -114,    54,  -114,   395,   111,
+     435,   -36,  -114,   178,   182,    21,  -114,   198,  -114,   201,
+     207,   212,   411,  -114,   206,   168,   558,   311,   310,   311,
+     506,   435,  -114,   411,   271,   274,   285,   286,   411,   435,
+      87,   228,  -114,  -114,  -114,    58,   373,   411,   152,  -114,
+    -114,  -114,  -114,   231,  -114,  -114,   257,  -114,   411,   235,
+       5,   259,   168,   275,    28,   159,  -114,  -114,   111,   435,
+     435,   435,   333,   344,   435,   435,   435,   435,   435,  -114,
+    -114,   289,  -114,  -114,  -114,   300,   308,  -114,   151,   435,
+     319,   176,   151,   411,   411,  -114,   317,   322,  -114,  -114,
+    -114,  -114,   224,  -114,   312,    71,    71,    71,    71,  -114,
+     323,  -114,   427,  -114,   328,   173,    64,   329,   -36,   315,
+     411,   411,   411,   411,   334,   339,   332,   577,   247,   584,
+     435,   435,   273,   273,  -114,  -114,  -114,   340,  -114,    24,
+    -114,   350,   351,  -114,   -36,   353,   365,  -114,  -114,  -114,
+     411,  -114,  -114,  -114,  -114,  -114,  -114,  -114,  -114,  -114,
+    -114,  -114,   439,  -114,  -114,   364,  -114,   157,  -114,   398,
+    -114,   518,   518,  -114,  -114,   411,   151,  -114,   374,   411,
+    -114,  -114,  -114,  -114,   382,   394,  -114,   411,  -114,   397,
+    -114,   155,   403,   411,   392,  -114,   404,   411,  -114,   435,
+     155,   401,   299,   406,  -114,  -114,   435,  -114,   568
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -147,  -147,  -147,  -114,  -147,  -147,  -147,   579,    44,   311,
-     -49,   348,     0,   -97,  -147,   -44,   -39,   -80,    -9,  -119,
-     -13,  -147,   -25,     2,  -146,   -34,    91,  -147,   -14,    -3,
-     -89,   228,   -11,  -147,   -30
+    -114,  -114,  -114,   -78,  -114,  -114,  -114,   529,     2,   367,
+     -50,   415,    48,   -88,  -114,   -48,   -40,   -21,    47,  -113,
+     -19,  -114,   -28,   137,   -59,   -35,   154,  -114,   -49,    18,
+     -83,   295,   -11,  -114,   -25
 };
 
 /* 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 -60
+#define YYTABLE_NINF -61
 static const yytype_int16 yytable[] =
 {
-      82,    82,    82,   110,    53,    53,   197,    82,   129,   159,
-     174,    97,    52,    54,   171,   172,   237,   230,   231,     2,
-     140,   207,    38,    96,    33,   100,    83,   212,   106,   214,
-     113,   111,   108,   231,   116,   117,   142,    67,   144,    68,
-     124,    69,   128,   125,   130,   127,   135,   136,   131,   137,
-     138,    65,    66,    39,   154,   148,   149,   168,   150,   199,
-     200,   201,    56,    57,   228,   146,   157,   182,   180,    38,
-      64,   -59,    89,    82,    70,   177,   232,    71,   160,    72,
-      73,   101,    97,   126,   107,   139,    70,   112,   115,    71,
-     170,    72,    73,   242,    96,   145,   100,   147,   169,    74,
-      75,   118,   151,   119,   120,   154,   119,   120,   183,   184,
-      38,    84,    85,   218,   198,   216,   203,   186,   187,   188,
-     189,   190,   191,   192,   193,   194,   195,    82,   229,   191,
-     192,   193,   194,   195,   217,   291,    97,   241,   152,   223,
-      70,   235,   224,    71,   117,    72,    73,   273,    96,   153,
-     100,    84,   259,    74,    75,   161,   244,   245,   246,    74,
-      75,   249,   250,   251,   252,   253,   312,   313,    70,    76,
-      38,    71,   204,    72,    73,   162,   258,    84,    85,    71,
-     196,    72,    73,    74,    75,   267,   267,   267,   267,   163,
-     164,   257,    38,   173,   260,   261,   175,   262,   263,   132,
-     193,   194,   195,   281,   177,   177,   178,   292,   268,   268,
-     268,   268,   179,    45,    46,   181,   274,   289,   290,    84,
-      85,   238,   269,   270,   271,    74,    75,   284,   186,   187,
-     188,   189,   190,   191,   192,   193,   194,   195,   282,   283,
-     185,   299,    47,    70,   205,   206,    71,   208,    72,    73,
-     209,   210,   298,   199,   200,   201,   234,    45,    46,   303,
-     211,    70,   219,    49,    71,   220,    72,    73,   221,   111,
-      50,   310,   301,    51,    74,    75,   222,   316,   225,   279,
-     304,   319,   233,   227,   307,   286,    47,   320,   234,   240,
-     236,   264,   239,   247,   326,   186,   187,   188,   189,   190,
-     191,   192,   193,   194,   195,   295,     4,    49,   248,   255,
-     254,   226,   256,   265,    50,   280,    76,    51,     5,     6,
-       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,   272,   275,    19,    20,    21,    22,    23,    24,
-      25,    26,    45,    46,   276,   277,   278,    45,   155,   156,
-     188,   189,   190,   191,   192,   193,   194,   195,   323,   285,
-     287,    27,    28,    29,   288,   294,    30,    76,   296,   297,
-     302,    47,    70,   300,   308,    71,    47,    72,    73,    84,
-      85,    45,    46,    86,    87,    74,    75,   305,   309,   311,
-      48,   315,    49,   157,   158,    48,   322,    49,   317,    88,
-     318,    89,    51,   324,    88,    45,    46,    51,   133,   321,
-      47,    70,   166,   243,    71,     0,    72,    73,    84,    85,
-       0,     0,    86,    87,    45,    46,     0,     0,     0,    48,
-       0,    49,    45,    46,    47,     0,     0,     0,    88,     0,
-      89,    51,     0,     0,     0,     0,     0,     0,    74,    75,
-      45,    46,     0,    47,     0,    49,    45,    46,     0,     0,
-     109,    47,    88,     0,     0,    51,     0,     0,    45,    46,
-       0,     0,   103,   104,    49,    74,    75,     0,     0,    47,
-       0,    50,    49,     0,    51,    47,    45,    46,     0,    50,
-      45,    46,    51,     0,    45,    46,     0,    47,   165,   104,
-      49,     0,     0,     0,    48,     0,    49,    88,     0,     0,
-      51,     0,     0,    50,   226,    47,    51,     0,    49,    47,
-       0,     0,     0,    47,     0,    50,     0,     0,    51,     0,
-       0,     0,     0,     0,    48,     0,    49,     0,     0,     0,
-      49,     0,     0,    88,    49,     0,    51,    50,     0,     0,
-      51,    88,     0,     0,    51,   186,   187,   188,   189,   190,
-     191,   192,   193,   194,   195,   186,   187,   188,   189,   190,
-     191,   192,   193,   194,   195,   186,   187,   188,   189,   190,
-     191,   192,   193,   194,   195,    35,    36,    37,     0,    40,
-      41,    42,    43,    44,     0,     0,    55,     0,     0,    58,
-      59,    60,    61,    62,    63,   187,   188,   189,   190,   191,
-     192,   193,   194,   195,   293,   189,   190,   191,   192,   193,
-     194,   195,     0,   213,   199,   200,   201,    71,     0,    72,
-      73,     0,     0,   215,   186,   187,   188,   189,   190,   191,
-     192,   193,   194,   195
+      89,    89,    89,   113,    54,    54,    69,    89,   132,   101,
+     133,    40,   138,   139,   240,   200,    71,   143,   100,     2,
+      57,    58,   177,   174,   175,   116,   103,    39,    65,   109,
+     210,   144,   114,    53,    55,   119,   120,   131,    72,    73,
+     104,   127,    34,   110,   140,   141,   115,   118,   148,   134,
+     150,    74,   154,   155,    75,   156,   171,   189,   190,   191,
+     192,   193,   194,   195,   196,   197,   198,   183,    39,   218,
+     -60,   220,   152,    76,   164,    89,   162,   180,   233,    46,
+      47,   129,   101,    90,   165,   235,   216,   217,   128,   111,
+     130,   100,    95,   173,   142,    46,    47,    81,    82,   103,
+     157,   145,   245,   202,   203,   204,   237,   144,    39,    48,
+      77,   186,   187,    78,   153,    79,    80,   201,   224,   206,
+     158,   199,   172,   217,   146,    48,   222,    46,   160,   161,
+      50,    89,   234,   207,   223,   151,   244,    51,   101,   229,
+      52,   159,   231,   238,   293,   166,    50,   100,   230,   120,
+     202,   203,   204,    51,   167,   103,    52,    48,   121,   260,
+     122,   123,   263,   264,   247,   248,   249,   122,   123,   252,
+     253,   254,   255,   256,   162,   163,    49,   178,    50,   176,
+      91,    92,   241,   181,   261,    66,    81,    82,    52,   182,
+     272,   272,   272,   272,   265,   266,    77,    91,    92,    78,
+     185,    79,    80,   314,   315,   283,   180,   180,   184,   294,
+      78,   278,    79,    80,   273,   273,   273,   273,    46,    47,
+      39,    71,    91,   262,   286,   291,   292,   189,   190,   191,
+     192,   193,   194,   195,   196,   197,   198,    46,    47,   188,
+     281,   208,   301,    91,    92,   209,   288,   306,    48,    81,
+      82,   300,   191,   192,   193,   194,   195,   196,   197,   198,
+     305,   211,    81,    82,   212,   135,   297,    48,   303,    50,
+     213,   114,   312,   215,   112,   214,    66,   225,   318,    52,
+     309,   226,   321,   196,   197,   198,   106,   107,    50,   284,
+     285,   269,   227,   228,   322,    51,   232,   236,    52,   237,
+     239,   328,   189,   190,   191,   192,   193,   194,   195,   196,
+     197,   198,     4,   189,   190,   191,   192,   193,   194,   195,
+     196,   197,   198,   242,     5,     6,     7,     8,     9,    10,
+      11,    12,    13,    14,    15,    16,    17,    18,   243,   250,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    46,
+      47,   251,   257,   189,   190,   191,   192,   193,   194,   195,
+     196,   197,   198,   274,   275,   276,   325,   258,    28,    29,
+      30,   259,   219,    31,   231,   270,    46,    47,   282,    48,
+      77,    46,    47,    78,   267,    79,    80,    91,    92,   268,
+     277,    93,    94,    81,    82,   279,   280,   287,    49,   290,
+      50,    46,    47,    46,    47,   289,    48,    66,    83,    95,
+      52,    48,    77,   295,   296,    78,   298,    79,    80,    91,
+      92,    46,    47,    93,    94,   168,   107,    50,   299,   302,
+      49,    48,    50,    48,    66,    46,    47,    52,   304,    66,
+     307,    95,    52,    46,    47,    81,    82,    46,    47,   310,
+      77,    48,    50,    78,    50,    79,    80,   311,   319,    51,
+     313,    51,    52,    83,    52,    48,   317,   320,   324,   326,
+      49,   169,    50,    48,   323,    77,   136,    48,    78,    51,
+      79,    80,    52,   246,    49,     0,    50,     0,    81,    82,
+       0,     0,     0,    66,    50,     0,    52,     0,    50,    39,
+       0,    51,     0,     0,    52,    66,     0,     0,    52,   189,
+     190,   191,   192,   193,   194,   195,   196,   197,   198,    77,
+       0,     0,    78,     0,    79,    80,   194,   195,   196,   197,
+     198,     0,    81,    82,     0,    36,    37,    38,     0,    41,
+      42,    43,    44,    45,     0,     0,    56,     0,    83,    59,
+      60,    61,    62,    63,    64,     0,    77,     0,     0,    78,
+       0,    79,    80,     0,     0,     0,     0,     0,   221,    81,
+      82,   189,   190,   191,   192,   193,   194,   195,   196,   197,
+     198,   190,   191,   192,   193,   194,   195,   196,   197,   198,
+     192,   193,   194,   195,   196,   197,   198,   202,   203,   204,
+      78,     0,    79,    80
 };
 
 static const yytype_int16 yycheck[] =
 {
-      34,    35,    36,    42,    15,    16,   125,    41,    57,    89,
-     107,    36,    15,    16,   103,   104,     9,   163,   164,     0,
-      64,     9,    62,    36,    61,    36,    35,   141,    39,   143,
-      43,    42,    41,   179,    45,    46,    66,    59,    68,    60,
-      51,    61,    55,    62,    58,    11,    60,    61,    59,    62,
-      63,    59,    60,     9,    88,     6,     7,   101,     9,    38,
-      39,    40,    18,    19,   161,    76,    54,     7,   112,    62,
-      26,    64,    67,   107,    38,   109,   165,    41,    89,    43,
-      44,    37,   107,    65,    40,    65,    38,    43,    44,    41,
-     101,    43,    44,   182,   107,    65,   107,    62,   101,    51,
-      52,     6,    53,     8,     9,   139,     8,     9,   119,   120,
-      62,    45,    46,   147,   125,   145,   127,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,   161,   162,     8,
-       9,    10,    11,    12,   147,   254,   161,   181,    62,   152,
-      38,   175,   153,    41,   155,    43,    44,   227,   161,    65,
-     161,    45,    46,    51,    52,    62,   186,   187,   188,    51,
-      52,   191,   192,   193,   194,   195,    47,    48,    38,    67,
-      62,    41,   128,    43,    44,    65,   206,    45,    46,    41,
-      66,    43,    44,    51,    52,   219,   220,   221,   222,    65,
-      65,   205,    62,    65,   208,   209,    62,   210,   211,    67,
-      10,    11,    12,   237,   238,   239,    62,   256,   219,   220,
-     221,   222,    65,     8,     9,    62,   227,   247,   248,    45,
-      46,   177,   220,   221,   222,    51,    52,   240,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,   238,   239,
-      65,   280,    37,    38,    62,    62,    41,    62,    43,    44,
-      62,    62,   265,    38,    39,    40,    41,     8,     9,   293,
-      62,    38,     6,    58,    41,     7,    43,    44,     7,   280,
-      65,   305,   285,    68,    51,    52,     7,   311,    66,   235,
-     294,   315,    65,    67,   297,   241,    37,   317,    41,    62,
-      64,    66,    63,     6,   324,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,   261,     1,    58,     7,    66,
-      62,    54,    62,    62,    65,    62,    67,    68,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    66,    66,    29,    30,    31,    32,    33,    34,
-      35,    36,     8,     9,    66,    66,    66,     8,     9,    10,
-       5,     6,     7,     8,     9,    10,    11,    12,    66,    62,
-      65,    56,    57,    58,    66,    62,    61,    67,    62,    62,
-      39,    37,    38,    64,    66,    41,    37,    43,    44,    45,
-      46,     8,     9,    49,    50,    51,    52,    65,    62,    62,
-      56,    62,    58,    54,    55,    56,    66,    58,    65,    65,
-      62,    67,    68,    62,    65,     8,     9,    68,    60,   318,
-      37,    38,   101,   185,    41,    -1,    43,    44,    45,    46,
-      -1,    -1,    49,    50,     8,     9,    -1,    -1,    -1,    56,
-      -1,    58,     8,     9,    37,    -1,    -1,    -1,    65,    -1,
-      67,    68,    -1,    -1,    -1,    -1,    -1,    -1,    51,    52,
-       8,     9,    -1,    37,    -1,    58,     8,     9,    -1,    -1,
-      63,    37,    65,    -1,    -1,    68,    -1,    -1,     8,     9,
-      -1,    -1,    56,    57,    58,    51,    52,    -1,    -1,    37,
-      -1,    65,    58,    -1,    68,    37,     8,     9,    -1,    65,
-       8,     9,    68,    -1,     8,     9,    -1,    37,    56,    57,
-      58,    -1,    -1,    -1,    56,    -1,    58,    65,    -1,    -1,
-      68,    -1,    -1,    65,    54,    37,    68,    -1,    58,    37,
-      -1,    -1,    -1,    37,    -1,    65,    -1,    -1,    68,    -1,
-      -1,    -1,    -1,    -1,    56,    -1,    58,    -1,    -1,    -1,
-      58,    -1,    -1,    65,    58,    -1,    68,    65,    -1,    -1,
-      68,    65,    -1,    -1,    68,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,     6,     7,     8,    -1,    10,
-      11,    12,    13,    14,    -1,    -1,    17,    -1,    -1,    20,
-      21,    22,    23,    24,    25,     4,     5,     6,     7,     8,
-       9,    10,    11,    12,    62,     6,     7,     8,     9,    10,
-      11,    12,    -1,    61,    38,    39,    40,    41,    -1,    43,
-      44,    -1,    -1,    61,     3,     4,     5,     6,     7,     8,
-       9,    10,    11,    12
+      35,    36,    37,    43,    15,    16,    27,    42,    58,    37,
+      59,     9,    61,    62,     9,   128,    27,    65,    37,     0,
+      18,    19,   110,   106,   107,    44,    37,    63,    26,    40,
+       9,    66,    43,    15,    16,    46,    47,    56,    60,    61,
+      38,    52,    62,    41,    63,    64,    44,    45,    73,    60,
+      75,    60,     6,     7,    61,     9,   104,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,   115,    63,   147,
+      65,   149,    83,    62,    95,   110,    55,   112,   166,     8,
+       9,    66,   110,    36,    95,   168,   145,   146,    63,    42,
+      11,   110,    68,   104,    66,     8,     9,    52,    53,   110,
+      54,    66,   185,    39,    40,    41,    42,   142,    63,    38,
+      39,   122,   123,    42,    63,    44,    45,   128,   153,   130,
+      63,    67,   104,   182,    66,    38,   151,     8,     9,    10,
+      59,   166,   167,   131,   153,    66,   184,    66,   166,   158,
+      69,    66,    55,   178,   257,    63,    59,   166,   159,   160,
+      39,    40,    41,    66,    66,   166,    69,    38,     6,   208,
+       8,     9,   211,   212,   189,   190,   191,     8,     9,   194,
+     195,   196,   197,   198,    55,    56,    57,    63,    59,    66,
+      46,    47,   180,    63,   209,    66,    52,    53,    69,    66,
+     225,   226,   227,   228,   213,   214,    39,    46,    47,    42,
+       7,    44,    45,    48,    49,   240,   241,   242,    63,   259,
+      42,   232,    44,    45,   225,   226,   227,   228,     8,     9,
+      63,   232,    46,    47,   243,   250,   251,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,     8,     9,    66,
+     238,    63,   282,    46,    47,    63,   244,   296,    38,    52,
+      53,   270,     5,     6,     7,     8,     9,    10,    11,    12,
+     295,    63,    52,    53,    63,    68,   264,    38,   287,    59,
+      63,   282,   307,    67,    64,    63,    66,     6,   313,    69,
+     299,     7,   317,    10,    11,    12,    57,    58,    59,   241,
+     242,    67,     7,     7,   319,    66,    68,    66,    69,    42,
+      65,   326,     3,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,     1,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,    64,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    63,     6,
+      29,    30,    31,    32,    33,    34,    35,    36,    37,     8,
+       9,     7,    63,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,   226,   227,   228,    67,    67,    57,    58,
+      59,    63,    62,    62,    55,    63,     8,     9,    63,    38,
+      39,     8,     9,    42,    67,    44,    45,    46,    47,    67,
+      67,    50,    51,    52,    53,    67,    67,    63,    57,    67,
+      59,     8,     9,     8,     9,    66,    38,    66,    68,    68,
+      69,    38,    39,    63,    63,    42,    63,    44,    45,    46,
+      47,     8,     9,    50,    51,    57,    58,    59,    63,    65,
+      57,    38,    59,    38,    66,     8,     9,    69,    40,    66,
+      66,    68,    69,     8,     9,    52,    53,     8,     9,    67,
+      39,    38,    59,    42,    59,    44,    45,    63,    66,    66,
+      63,    66,    69,    68,    69,    38,    63,    63,    67,    63,
+      57,   104,    59,    38,   320,    39,    61,    38,    42,    66,
+      44,    45,    69,   188,    57,    -1,    59,    -1,    52,    53,
+      -1,    -1,    -1,    66,    59,    -1,    69,    -1,    59,    63,
+      -1,    66,    -1,    -1,    69,    66,    -1,    -1,    69,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    39,
+      -1,    -1,    42,    -1,    44,    45,     8,     9,    10,    11,
+      12,    -1,    52,    53,    -1,     6,     7,     8,    -1,    10,
+      11,    12,    13,    14,    -1,    -1,    17,    -1,    68,    20,
+      21,    22,    23,    24,    25,    -1,    39,    -1,    -1,    42,
+      -1,    44,    45,    -1,    -1,    -1,    -1,    -1,    62,    52,
+      53,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+       6,     7,     8,     9,    10,    11,    12,    39,    40,    41,
+      42,    -1,    44,    45
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    70,     0,    71,     1,    13,    14,    15,    16,    17,
+       0,    71,     0,    72,     1,    13,    14,    15,    16,    17,
       18,    19,    20,    21,    22,    23,    24,    25,    26,    29,
-      30,    31,    32,    33,    34,    35,    36,    56,    57,    58,
-      61,    72,    75,    61,    76,    76,    76,    76,    62,    77,
-      76,    76,    76,    76,    76,     8,     9,    37,    56,    58,
-      65,    68,    98,   101,    98,    76,    77,    77,    76,    76,
-      76,    76,    76,    76,    77,    59,    60,    59,    60,    61,
-      38,    41,    43,    44,    51,    52,    67,    87,    88,    89,
-      91,    93,    94,    87,    45,    46,    49,    50,    65,    67,
-      79,    80,    82,    84,    85,    86,    89,    91,    97,    98,
-     101,    77,    77,    56,    57,    78,   101,    77,    87,    63,
-      85,   101,    77,    89,    94,    77,   101,   101,     6,     8,
-       9,    99,   101,   103,   101,    62,    65,    11,    89,    79,
-      97,   101,    67,    80,    96,    97,    97,    89,    89,    65,
-      84,    74,   103,    73,   103,    65,   101,    62,     6,     7,
-       9,    53,    62,    65,    94,     9,    10,    54,    55,    86,
-     101,    62,    65,    65,    65,    56,    78,    83,    84,    98,
-     101,    99,    99,    65,    82,    62,    81,    94,    62,    65,
-      84,    62,     7,   101,   101,    65,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    66,    88,   101,    38,
-      39,    40,   100,   101,    77,    62,    62,     9,    62,    62,
-      62,    62,    72,    61,    72,    61,   103,    89,    94,     6,
-       7,     7,     7,    89,   101,    66,    54,    67,    82,    94,
-      93,    93,    99,    65,    41,    94,    64,     9,    77,    63,
-      62,    84,    99,   100,   103,   103,   103,     6,     7,   103,
-     103,   103,   103,   103,    62,    66,    62,    97,   103,    46,
-      97,    97,    89,    89,    66,    62,    92,    94,   101,    92,
-      92,    92,    66,    86,   101,    66,    66,    66,    66,    77,
-      62,    94,    81,    81,    89,    62,    77,    65,    66,   103,
-     103,    88,    79,    62,    62,    77,    62,    62,    89,    85,
-      64,    89,    39,    94,    97,    65,    90,    89,    66,    62,
-      94,    62,    47,    48,    95,    62,    94,    65,    62,    94,
-     103,    95,    66,    66,    62,   102,   103
+      30,    31,    32,    33,    34,    35,    36,    37,    57,    58,
+      59,    62,    73,    76,    62,    77,    77,    77,    77,    63,
+      78,    77,    77,    77,    77,    77,     8,     9,    38,    57,
+      59,    66,    69,    99,   102,    99,    77,    78,    78,    77,
+      77,    77,    77,    77,    77,    78,    66,    85,    86,    87,
+      99,   102,    60,    61,    60,    61,    62,    39,    42,    44,
+      45,    52,    53,    68,    88,    89,    90,    92,    94,    95,
+      88,    46,    47,    50,    51,    68,    80,    81,    83,    87,
+      90,    92,    98,   102,    78,    78,    57,    58,    79,   102,
+      78,    88,    64,    86,   102,    78,    90,    95,    78,   102,
+     102,     6,     8,     9,   100,   102,   104,   102,    63,    66,
+      11,    90,    80,    98,   102,    68,    81,    97,    98,    98,
+      90,    90,    66,    85,    95,    66,    66,    75,   104,    74,
+     104,    66,   102,    63,     6,     7,     9,    54,    63,    66,
+       9,    10,    55,    56,    87,   102,    63,    66,    57,    79,
+      84,    85,    99,   102,   100,   100,    66,    83,    63,    82,
+      95,    63,    66,    85,    63,     7,   102,   102,    66,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    67,
+      89,   102,    39,    40,    41,   101,   102,    78,    63,    63,
+       9,    63,    63,    63,    63,    67,    94,    94,    73,    62,
+      73,    62,   104,    90,    95,     6,     7,     7,     7,    90,
+     102,    55,    68,    83,    95,   100,    66,    42,    95,    65,
+       9,    78,    64,    63,    85,   100,   101,   104,   104,   104,
+       6,     7,   104,   104,   104,   104,   104,    63,    67,    63,
+      98,   104,    47,    98,    98,    90,    90,    67,    67,    67,
+      63,    93,    95,   102,    93,    93,    93,    67,    87,    67,
+      67,    78,    63,    95,    82,    82,    90,    63,    78,    66,
+      67,   104,   104,    89,    80,    63,    63,    78,    63,    63,
+      90,    86,    65,    90,    40,    95,    98,    66,    91,    90,
+      67,    63,    95,    63,    48,    49,    96,    63,    95,    66,
+      63,    95,   104,    96,    67,    67,    63,   103,   104
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -1974,7 +1972,7 @@ yyreduce:
 /* Line 1455 of yacc.c  */
 #line 219 "a.y"
     {
-		outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].gen), NREG, &(yyvsp[(4) - (4)].gen));
+		outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].gen), 0, &(yyvsp[(4) - (4)].gen));
 	}
     break;
 
@@ -2086,9 +2084,9 @@ yyreduce:
   case 42:
 
 /* Line 1455 of yacc.c  */
-#line 299 "a.y"
+#line 300 "a.y"
     {
-		(yyvsp[(7) - (9)].gen).type = D_REGREG;
+		(yyvsp[(7) - (9)].gen).type = D_REGREG2;
 		(yyvsp[(7) - (9)].gen).offset = (yyvsp[(9) - (9)].lval);
 		outcode((yyvsp[(1) - (9)].lval), (yyvsp[(2) - (9)].lval), &(yyvsp[(3) - (9)].gen), (yyvsp[(5) - (9)].gen).reg, &(yyvsp[(7) - (9)].gen));
 	}
@@ -2097,43 +2095,52 @@ yyreduce:
   case 43:
 
 /* Line 1455 of yacc.c  */
-#line 308 "a.y"
+#line 309 "a.y"
     {
-		outcode((yyvsp[(1) - (2)].lval), Always, &nullgen, NREG, &nullgen);
+		outcode((yyvsp[(1) - (2)].lval), Always, &(yyvsp[(2) - (2)].gen), NREG, &nullgen);
 	}
     break;
 
   case 44:
 
 /* Line 1455 of yacc.c  */
-#line 313 "a.y"
+#line 316 "a.y"
     {
-		(yyval.lval) = Always;
+		outcode((yyvsp[(1) - (2)].lval), Always, &nullgen, NREG, &nullgen);
 	}
     break;
 
   case 45:
 
 /* Line 1455 of yacc.c  */
-#line 317 "a.y"
+#line 321 "a.y"
     {
-		(yyval.lval) = ((yyvsp[(1) - (2)].lval) & ~C_SCOND) | (yyvsp[(2) - (2)].lval);
+		(yyval.lval) = Always;
 	}
     break;
 
   case 46:
 
 /* Line 1455 of yacc.c  */
-#line 321 "a.y"
+#line 325 "a.y"
+    {
+		(yyval.lval) = ((yyvsp[(1) - (2)].lval) & ~C_SCOND) | (yyvsp[(2) - (2)].lval);
+	}
+    break;
+
+  case 47:
+
+/* Line 1455 of yacc.c  */
+#line 329 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (2)].lval) | (yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 49:
+  case 50:
 
 /* Line 1455 of yacc.c  */
-#line 330 "a.y"
+#line 338 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_BRANCH;
@@ -2141,10 +2148,10 @@ yyreduce:
 	}
     break;
 
-  case 50:
+  case 51:
 
 /* Line 1455 of yacc.c  */
-#line 336 "a.y"
+#line 344 "a.y"
     {
 		(yyval.gen) = nullgen;
 		if(pass == 2)
@@ -2155,10 +2162,10 @@ yyreduce:
 	}
     break;
 
-  case 51:
+  case 52:
 
 /* Line 1455 of yacc.c  */
-#line 345 "a.y"
+#line 353 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_BRANCH;
@@ -2167,10 +2174,10 @@ yyreduce:
 	}
     break;
 
-  case 52:
+  case 53:
 
 /* Line 1455 of yacc.c  */
-#line 353 "a.y"
+#line 361 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_CONST;
@@ -2178,30 +2185,30 @@ yyreduce:
 	}
     break;
 
-  case 53:
+  case 54:
 
 /* Line 1455 of yacc.c  */
-#line 359 "a.y"
+#line 367 "a.y"
     {
 		(yyval.gen) = (yyvsp[(2) - (2)].gen);
 		(yyval.gen).type = D_CONST;
 	}
     break;
 
-  case 54:
+  case 55:
 
 /* Line 1455 of yacc.c  */
-#line 364 "a.y"
+#line 372 "a.y"
     {
 		(yyval.gen) = (yyvsp[(4) - (4)].gen);
 		(yyval.gen).type = D_OCONST;
 	}
     break;
 
-  case 55:
+  case 56:
 
 /* Line 1455 of yacc.c  */
-#line 369 "a.y"
+#line 377 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_SCONST;
@@ -2209,10 +2216,10 @@ yyreduce:
 	}
     break;
 
-  case 57:
+  case 58:
 
 /* Line 1455 of yacc.c  */
-#line 378 "a.y"
+#line 386 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FCONST;
@@ -2220,10 +2227,10 @@ yyreduce:
 	}
     break;
 
-  case 58:
+  case 59:
 
 /* Line 1455 of yacc.c  */
-#line 384 "a.y"
+#line 392 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FCONST;
@@ -2231,19 +2238,19 @@ yyreduce:
 	}
     break;
 
-  case 59:
+  case 60:
 
 /* Line 1455 of yacc.c  */
-#line 392 "a.y"
+#line 400 "a.y"
     {
 		(yyval.lval) = 1 << (yyvsp[(1) - (1)].lval);
 	}
     break;
 
-  case 60:
+  case 61:
 
 /* Line 1455 of yacc.c  */
-#line 396 "a.y"
+#line 404 "a.y"
     {
 		int i;
 		(yyval.lval)=0;
@@ -2254,29 +2261,29 @@ yyreduce:
 	}
     break;
 
-  case 61:
+  case 62:
 
 /* Line 1455 of yacc.c  */
-#line 405 "a.y"
+#line 413 "a.y"
     {
 		(yyval.lval) = (1<<(yyvsp[(1) - (3)].lval)) | (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 65:
+  case 66:
 
 /* Line 1455 of yacc.c  */
-#line 414 "a.y"
+#line 422 "a.y"
     {
 		(yyval.gen) = (yyvsp[(1) - (4)].gen);
 		(yyval.gen).reg = (yyvsp[(3) - (4)].lval);
 	}
     break;
 
-  case 66:
+  case 67:
 
 /* Line 1455 of yacc.c  */
-#line 419 "a.y"
+#line 427 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_PSR;
@@ -2284,10 +2291,10 @@ yyreduce:
 	}
     break;
 
-  case 67:
+  case 68:
 
 /* Line 1455 of yacc.c  */
-#line 425 "a.y"
+#line 433 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FPCR;
@@ -2295,10 +2302,10 @@ yyreduce:
 	}
     break;
 
-  case 68:
+  case 69:
 
 /* Line 1455 of yacc.c  */
-#line 431 "a.y"
+#line 439 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_OREG;
@@ -2306,10 +2313,10 @@ yyreduce:
 	}
     break;
 
-  case 72:
+  case 73:
 
 /* Line 1455 of yacc.c  */
-#line 442 "a.y"
+#line 450 "a.y"
     {
 		(yyval.gen) = (yyvsp[(1) - (1)].gen);
 		if((yyvsp[(1) - (1)].gen).name != D_EXTERN && (yyvsp[(1) - (1)].gen).name != D_STATIC) {
@@ -2317,10 +2324,10 @@ yyreduce:
 	}
     break;
 
-  case 73:
+  case 74:
 
 /* Line 1455 of yacc.c  */
-#line 450 "a.y"
+#line 458 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_OREG;
@@ -2329,10 +2336,10 @@ yyreduce:
 	}
     break;
 
-  case 75:
+  case 76:
 
 /* Line 1455 of yacc.c  */
-#line 460 "a.y"
+#line 468 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_OREG;
@@ -2341,10 +2348,10 @@ yyreduce:
 	}
     break;
 
-  case 77:
+  case 78:
 
 /* Line 1455 of yacc.c  */
-#line 470 "a.y"
+#line 478 "a.y"
     {
 		(yyval.gen) = (yyvsp[(1) - (4)].gen);
 		(yyval.gen).type = D_OREG;
@@ -2352,10 +2359,10 @@ yyreduce:
 	}
     break;
 
-  case 82:
+  case 83:
 
 /* Line 1455 of yacc.c  */
-#line 483 "a.y"
+#line 491 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_CONST;
@@ -2363,10 +2370,10 @@ yyreduce:
 	}
     break;
 
-  case 83:
+  case 84:
 
 /* Line 1455 of yacc.c  */
-#line 491 "a.y"
+#line 499 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_REG;
@@ -2374,10 +2381,10 @@ yyreduce:
 	}
     break;
 
-  case 84:
+  case 85:
 
 /* Line 1455 of yacc.c  */
-#line 499 "a.y"
+#line 507 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_REGREG;
@@ -2386,10 +2393,10 @@ yyreduce:
 	}
     break;
 
-  case 85:
+  case 86:
 
 /* Line 1455 of yacc.c  */
-#line 508 "a.y"
+#line 516 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_SHIFT;
@@ -2397,10 +2404,10 @@ yyreduce:
 	}
     break;
 
-  case 86:
+  case 87:
 
 /* Line 1455 of yacc.c  */
-#line 514 "a.y"
+#line 522 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_SHIFT;
@@ -2408,10 +2415,10 @@ yyreduce:
 	}
     break;
 
-  case 87:
+  case 88:
 
 /* Line 1455 of yacc.c  */
-#line 520 "a.y"
+#line 528 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_SHIFT;
@@ -2419,10 +2426,10 @@ yyreduce:
 	}
     break;
 
-  case 88:
+  case 89:
 
 /* Line 1455 of yacc.c  */
-#line 526 "a.y"
+#line 534 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_SHIFT;
@@ -2430,10 +2437,10 @@ yyreduce:
 	}
     break;
 
-  case 89:
+  case 90:
 
 /* Line 1455 of yacc.c  */
-#line 534 "a.y"
+#line 542 "a.y"
     {
 		if((yyval.lval) < 0 || (yyval.lval) >= 16)
 			print("register value out of range\n");
@@ -2441,10 +2448,10 @@ yyreduce:
 	}
     break;
 
-  case 90:
+  case 91:
 
 /* Line 1455 of yacc.c  */
-#line 540 "a.y"
+#line 548 "a.y"
     {
 		if((yyval.lval) < 0 || (yyval.lval) >= 32)
 			print("shift value out of range\n");
@@ -2452,19 +2459,19 @@ yyreduce:
 	}
     break;
 
-  case 92:
+  case 93:
 
 /* Line 1455 of yacc.c  */
-#line 549 "a.y"
+#line 557 "a.y"
     {
 		(yyval.lval) = REGPC;
 	}
     break;
 
-  case 93:
+  case 94:
 
 /* Line 1455 of yacc.c  */
-#line 553 "a.y"
+#line 561 "a.y"
     {
 		if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= NREG)
 			print("register value out of range\n");
@@ -2472,19 +2479,19 @@ yyreduce:
 	}
     break;
 
-  case 95:
+  case 96:
 
 /* Line 1455 of yacc.c  */
-#line 562 "a.y"
+#line 570 "a.y"
     {
 		(yyval.lval) = REGSP;
 	}
     break;
 
-  case 97:
+  case 98:
 
 /* Line 1455 of yacc.c  */
-#line 569 "a.y"
+#line 577 "a.y"
     {
 		if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= NREG)
 			print("register value out of range\n");
@@ -2492,10 +2499,10 @@ yyreduce:
 	}
     break;
 
-  case 100:
+  case 101:
 
 /* Line 1455 of yacc.c  */
-#line 581 "a.y"
+#line 589 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FREG;
@@ -2503,10 +2510,10 @@ yyreduce:
 	}
     break;
 
-  case 101:
+  case 102:
 
 /* Line 1455 of yacc.c  */
-#line 587 "a.y"
+#line 595 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FREG;
@@ -2514,10 +2521,10 @@ yyreduce:
 	}
     break;
 
-  case 102:
+  case 103:
 
 /* Line 1455 of yacc.c  */
-#line 595 "a.y"
+#line 603 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_OREG;
@@ -2527,10 +2534,10 @@ yyreduce:
 	}
     break;
 
-  case 103:
+  case 104:
 
 /* Line 1455 of yacc.c  */
-#line 603 "a.y"
+#line 611 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_OREG;
@@ -2540,10 +2547,10 @@ yyreduce:
 	}
     break;
 
-  case 104:
+  case 105:
 
 /* Line 1455 of yacc.c  */
-#line 611 "a.y"
+#line 619 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_OREG;
@@ -2553,181 +2560,181 @@ yyreduce:
 	}
     break;
 
-  case 105:
+  case 106:
 
 /* Line 1455 of yacc.c  */
-#line 620 "a.y"
+#line 628 "a.y"
     {
 		(yyval.lval) = 0;
 	}
     break;
 
-  case 106:
+  case 107:
 
 /* Line 1455 of yacc.c  */
-#line 624 "a.y"
+#line 632 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 107:
+  case 108:
 
 /* Line 1455 of yacc.c  */
-#line 628 "a.y"
+#line 636 "a.y"
     {
 		(yyval.lval) = -(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 112:
+  case 113:
 
 /* Line 1455 of yacc.c  */
-#line 640 "a.y"
+#line 648 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
 	}
     break;
 
-  case 113:
+  case 114:
 
 /* Line 1455 of yacc.c  */
-#line 644 "a.y"
+#line 652 "a.y"
     {
 		(yyval.lval) = -(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 114:
+  case 115:
 
 /* Line 1455 of yacc.c  */
-#line 648 "a.y"
+#line 656 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 115:
+  case 116:
 
 /* Line 1455 of yacc.c  */
-#line 652 "a.y"
+#line 660 "a.y"
     {
 		(yyval.lval) = ~(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 116:
+  case 117:
 
 /* Line 1455 of yacc.c  */
-#line 656 "a.y"
+#line 664 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (3)].lval);
 	}
     break;
 
-  case 117:
+  case 118:
 
 /* Line 1455 of yacc.c  */
-#line 661 "a.y"
+#line 669 "a.y"
     {
 		(yyval.lval) = 0;
 	}
     break;
 
-  case 118:
+  case 119:
 
 /* Line 1455 of yacc.c  */
-#line 665 "a.y"
+#line 673 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 120:
+  case 121:
 
 /* Line 1455 of yacc.c  */
-#line 672 "a.y"
+#line 680 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 121:
+  case 122:
 
 /* Line 1455 of yacc.c  */
-#line 676 "a.y"
+#line 684 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 122:
+  case 123:
 
 /* Line 1455 of yacc.c  */
-#line 680 "a.y"
+#line 688 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 123:
+  case 124:
 
 /* Line 1455 of yacc.c  */
-#line 684 "a.y"
+#line 692 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 124:
+  case 125:
 
 /* Line 1455 of yacc.c  */
-#line 688 "a.y"
+#line 696 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 125:
+  case 126:
 
 /* Line 1455 of yacc.c  */
-#line 692 "a.y"
+#line 700 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
 	}
     break;
 
-  case 126:
+  case 127:
 
 /* Line 1455 of yacc.c  */
-#line 696 "a.y"
+#line 704 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
 	}
     break;
 
-  case 127:
+  case 128:
 
 /* Line 1455 of yacc.c  */
-#line 700 "a.y"
+#line 708 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 128:
+  case 129:
 
 /* Line 1455 of yacc.c  */
-#line 704 "a.y"
+#line 712 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 129:
+  case 130:
 
 /* Line 1455 of yacc.c  */
-#line 708 "a.y"
+#line 716 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
 	}
@@ -2736,7 +2743,7 @@ yyreduce:
 
 
 /* Line 1455 of yacc.c  */
-#line 2740 "y.tab.c"
+#line 2747 "y.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
diff --git a/src/cmd/5a/y.tab.h b/src/cmd/5a/y.tab.h
index 2803999..1dd0cb0 100644
--- a/src/cmd/5a/y.tab.h
+++ b/src/cmd/5a/y.tab.h
@@ -63,28 +63,29 @@
      LTYPEM = 279,
      LTYPEN = 280,
      LTYPEBX = 281,
-     LCONST = 282,
-     LSP = 283,
-     LSB = 284,
-     LFP = 285,
-     LPC = 286,
-     LTYPEX = 287,
-     LR = 288,
-     LREG = 289,
-     LF = 290,
-     LFREG = 291,
-     LC = 292,
-     LCREG = 293,
-     LPSR = 294,
-     LFCR = 295,
-     LCOND = 296,
-     LS = 297,
-     LAT = 298,
-     LFCONST = 299,
-     LSCONST = 300,
-     LNAME = 301,
-     LLAB = 302,
-     LVAR = 303
+     LTYPEPLD = 282,
+     LCONST = 283,
+     LSP = 284,
+     LSB = 285,
+     LFP = 286,
+     LPC = 287,
+     LTYPEX = 288,
+     LR = 289,
+     LREG = 290,
+     LF = 291,
+     LFREG = 292,
+     LC = 293,
+     LCREG = 294,
+     LPSR = 295,
+     LFCR = 296,
+     LCOND = 297,
+     LS = 298,
+     LAT = 299,
+     LFCONST = 300,
+     LSCONST = 301,
+     LNAME = 302,
+     LLAB = 303,
+     LVAR = 304
    };
 #endif
 /* Tokens.  */
@@ -112,28 +113,29 @@
 #define LTYPEM 279
 #define LTYPEN 280
 #define LTYPEBX 281
-#define LCONST 282
-#define LSP 283
-#define LSB 284
-#define LFP 285
-#define LPC 286
-#define LTYPEX 287
-#define LR 288
-#define LREG 289
-#define LF 290
-#define LFREG 291
-#define LC 292
-#define LCREG 293
-#define LPSR 294
-#define LFCR 295
-#define LCOND 296
-#define LS 297
-#define LAT 298
-#define LFCONST 299
-#define LSCONST 300
-#define LNAME 301
-#define LLAB 302
-#define LVAR 303
+#define LTYPEPLD 282
+#define LCONST 283
+#define LSP 284
+#define LSB 285
+#define LFP 286
+#define LPC 287
+#define LTYPEX 288
+#define LR 289
+#define LREG 290
+#define LF 291
+#define LFREG 292
+#define LC 293
+#define LCREG 294
+#define LPSR 295
+#define LFCR 296
+#define LCOND 297
+#define LS 298
+#define LAT 299
+#define LFCONST 300
+#define LSCONST 301
+#define LNAME 302
+#define LLAB 303
+#define LVAR 304
 
 
 
@@ -154,7 +156,7 @@ typedef union YYSTYPE
 
 
 /* Line 1676 of yacc.c  */
-#line 158 "y.tab.h"
+#line 160 "y.tab.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
diff --git a/src/cmd/5c/cgen.c b/src/cmd/5c/cgen.c
index 9e74f51..5ff4f63 100644
--- a/src/cmd/5c/cgen.c
+++ b/src/cmd/5c/cgen.c
@@ -950,9 +950,9 @@ sugen(Node *n, Node *nn, int32 w)
 
 	case OSTRUCT:
 		/*
-		 * rewrite so lhs has no fn call
+		 * rewrite so lhs has no side effect.
 		 */
-		if(nn != Z && nn->complex >= FNX) {
+		if(nn != Z && side(nn)) {
 			nod1 = *n;
 			nod1.type = typ(TIND, n->type);
 			regret(&nod2, &nod1);
diff --git a/src/cmd/5c/doc.go b/src/cmd/5c/doc.go
index 0874293..7291d45 100644
--- a/src/cmd/5c/doc.go
+++ b/src/cmd/5c/doc.go
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build ignore
+
 /*
 
 5c is a version of the Plan 9 C compiler.  The original is documented at
 
-	http://plan9.bell-labs.com/magic/man2html/1/2c
+	http://plan9.bell-labs.com/magic/man2html/1/8c
 
 Its target architecture is the ARM, referred to by these tools as arm.
 
 */
-package documentation
+package main
diff --git a/src/cmd/5c/gc.h b/src/cmd/5c/gc.h
index 2065268..a0fc63c 100644
--- a/src/cmd/5c/gc.h
+++ b/src/cmd/5c/gc.h
@@ -297,6 +297,7 @@ void	patch(Prog*, int32);
 int	sconst(Node*);
 int	sval(int32);
 void	gpseudo(int, Sym*, Node*);
+void	gprefetch(Node*);
 
 /*
  * swt.c
diff --git a/src/cmd/5c/peep.c b/src/cmd/5c/peep.c
index 3a905f0..2f902e0 100644
--- a/src/cmd/5c/peep.c
+++ b/src/cmd/5c/peep.c
@@ -824,7 +824,7 @@ xtramodes(Reg *r, Adr *a)
 	Adr v;
 
 	p = r->prog;
-	if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG)	/* byte load */
+	if(p->as == AMOVB && p->from.type == D_OREG)	/* byte load */
 		return 0;
 	v = *a;
 	v.type = D_REG;
@@ -1067,6 +1067,7 @@ copyu(Prog *p, Adr *v, Adr *s)
 	case ABLT:
 	case ABGT:
 	case ABLE:
+	case APLD:
 		if(s != A) {
 			if(copysub(&p->from, v, s, 1))
 				return 1;
diff --git a/src/cmd/5c/reg.c b/src/cmd/5c/reg.c
index 1ccf74a..42c5193 100644
--- a/src/cmd/5c/reg.c
+++ b/src/cmd/5c/reg.c
@@ -66,12 +66,6 @@ rcmp(const void *a1, const void *a2)
 void
 regopt(Prog *p)
 {
-	USED(p);
-	// TODO(kaib): optimizer disabled because it smashes R8 when running out of registers
-	// the disable is unconventionally here because the call is in common code shared by 5c/6c/8c
-	return;
-
-#ifdef	NOTDEF
 	Reg *r, *r1, *r2;
 	Prog *p1;
 	int i, z;
@@ -191,6 +185,14 @@ regopt(Prog *p)
 			break;
 
 		/*
+		 * right side read
+		 */
+		case APLD:
+			for(z=0; z<BITS; z++)
+				r->use2.b[z] |= bit.b[z];
+			break;
+
+		/*
 		 * funny
 		 */
 		case ABL:
@@ -492,7 +494,6 @@ brk:
 		r1->link = freer;
 		freer = firstr;
 	}
-#endif
 }
 
 void
@@ -1149,12 +1150,13 @@ addreg(Adr *a, int rn)
  *	1	R1
  *	...	...
  *	10	R10
+ *	12  R12
  */
 int32
 RtoB(int r)
 {
 
-	if(r < 2 || r >= REGTMP-2)	// excluded R9 and R10 for m and g
+	if(r < 2 || (r >= REGTMP-2 && r != 12))	// excluded R9 and R10 for m and g, but not R12
 		return 0;
 	return 1L << r;
 }
@@ -1162,7 +1164,7 @@ RtoB(int r)
 int
 BtoR(int32 b)
 {
-	b &= 0x01fcL;	// excluded R9 and R10 for m and g
+	b &= 0x11fcL;	// excluded R9 and R10 for m and g, but not R12
 	if(b == 0)
 		return 0;
 	return bitno(b);
@@ -1173,7 +1175,7 @@ BtoR(int32 b)
  *	18	F2
  *	19	F3
  *	...	...
- *	23	F7
+ *	31	F15
  */
 int32
 FtoB(int f)
@@ -1188,7 +1190,7 @@ int
 BtoF(int32 b)
 {
 
-	b &= 0xfc0000L;
+	b &= 0xfffc0000L;
 	if(b == 0)
 		return 0;
 	return bitno(b) - 16;
diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c
index 7268f9a..87b7751 100644
--- a/src/cmd/5c/swt.c
+++ b/src/cmd/5c/swt.c
@@ -393,18 +393,12 @@ outcode(void)
 	}
 
 	Bprint(&outbuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
-	if(ndynimp > 0 || ndynexp > 0) {
-		int i;
-
+	if(pragcgobuf.to > pragcgobuf.start) {
 		Bprint(&outbuf, "\n");
 		Bprint(&outbuf, "$$  // exports\n\n");
 		Bprint(&outbuf, "$$  // local types\n\n");
-		Bprint(&outbuf, "$$  // dynimport\n");
-		for(i=0; i<ndynimp; i++)
-			Bprint(&outbuf, "dynimport %s %s %s\n", dynimp[i].local, dynimp[i].remote, dynimp[i].path);
-		Bprint(&outbuf, "\n$$  // dynexport\n");
-		for(i=0; i<ndynexp; i++)
-			Bprint(&outbuf, "dynexport %s %s\n", dynexp[i].local, dynexp[i].remote);
+		Bprint(&outbuf, "$$  // cgo\n");
+		Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf));
 		Bprint(&outbuf, "\n$$\n\n");
 	}
 	Bprint(&outbuf, "!\n");
@@ -472,12 +466,38 @@ outhist(Biobuf *b)
 	char *p, *q, *op, c;
 	Prog pg;
 	int n;
+	char *tofree;
+	static int first = 1;
+	static char *goroot, *goroot_final;
+
+	if(first) {
+		// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
+		first = 0;
+		goroot = getenv("GOROOT");
+		goroot_final = getenv("GOROOT_FINAL");
+		if(goroot == nil)
+			goroot = "";
+		if(goroot_final == nil)
+			goroot_final = goroot;
+		if(strcmp(goroot, goroot_final) == 0) {
+			goroot = nil;
+			goroot_final = nil;
+		}
+	}
 
+	tofree = nil;
 	pg = zprog;
 	pg.as = AHISTORY;
 	c = pathchar();
 	for(h = hist; h != H; h = h->link) {
 		p = h->name;
+		if(p != nil && goroot != nil) {
+			n = strlen(goroot);
+			if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
+				tofree = smprint("%s%s", goroot_final, p+n);
+				p = tofree;
+			}
+		}
 		op = 0;
 		if(systemtype(Windows) && p && p[1] == ':'){
 			c = p[2];
@@ -525,6 +545,11 @@ outhist(Biobuf *b)
 			pg.to.type = D_CONST;
 
 		zwrite(b, &pg, 0, 0);
+
+ 		if(tofree) {
+ 			free(tofree);
+ 			tofree = nil;
+ 		}
 	}
 }
 
@@ -566,7 +591,8 @@ zaddr(char *bp, Adr *a, int s)
 	bp[1] = a->reg;
 	bp[2] = s;
 	bp[3] = a->name;
-	bp += 4;
+	bp[4] = 0;
+	bp += 5;
 	switch(a->type) {
 	default:
 		diag(Z, "unknown type %d in zaddr", a->type);
diff --git a/src/cmd/5c/txt.c b/src/cmd/5c/txt.c
index 1a189e3..b8675fe 100644
--- a/src/cmd/5c/txt.c
+++ b/src/cmd/5c/txt.c
@@ -1176,17 +1176,15 @@ patch(Prog *op, int32 pc)
 void
 gpseudo(int a, Sym *s, Node *n)
 {
-
 	nextpc();
 	p->as = a;
 	p->from.type = D_OREG;
 	p->from.sym = s;
 	p->from.name = D_EXTERN;
-	if(a == ATEXT) {
+	if(a == ATEXT || a == AGLOBL) {
 		p->reg = textflag;
 		textflag = 0;
-	} else if(a == AGLOBL)
-		p->reg = 0;
+	}
 	if(s->class == CSTATIC)
 		p->from.name = D_STATIC;
 	naddr(n, &p->to);
@@ -1194,6 +1192,18 @@ gpseudo(int a, Sym *s, Node *n)
 		pc--;
 }
 
+void
+gprefetch(Node *n)
+{
+	Node n1;
+
+	regalloc(&n1, n, Z);
+	gmove(n, &n1);
+	n1.op = OINDREG;
+	gins(APLD, &n1, Z);
+	regfree(&n1);
+}
+
 int
 sconst(Node *n)
 {
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index cccef94..9e35f95 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -15,8 +15,8 @@ void
 cgen(Node *n, Node *res)
 {
 	Node *nl, *nr, *r;
-	Node n1, n2, n3, f0, f1;
-	int a, w;
+	Node n1, n2, f0, f1;
+	int a, w, rg;
 	Prog *p1, *p2, *p3;
 	Addr addr;
 
@@ -30,6 +30,27 @@ cgen(Node *n, Node *res)
 	if(res == N || res->type == T)
 		fatal("cgen: res nil");
 
+	switch(n->op) {
+	case OSLICE:
+	case OSLICEARR:
+	case OSLICESTR:
+		if (res->op != ONAME || !res->addable) {
+			tempname(&n1, n->type);
+			cgen_slice(n, &n1);
+			cgen(&n1, res);
+		} else
+			cgen_slice(n, res);
+		return;
+	case OEFACE:
+		if (res->op != ONAME || !res->addable) {
+			tempname(&n1, n->type);
+			cgen_eface(n, &n1);
+			cgen(&n1, res);
+		} else
+			cgen_eface(n, res);
+		return;
+	}
+
 	while(n->op == OCONVNOP)
 		n = n->left;
 
@@ -156,6 +177,7 @@ cgen(Node *n, Node *res)
 		case OADD:
 		case OSUB:
 		case OMUL:
+		case OLROT:
 		case OLSH:
 		case ORSH:
 		case OAND:
@@ -171,7 +193,7 @@ cgen(Node *n, Node *res)
 	switch(n->op) {
 	default:
 		dump("cgen", n);
-		fatal("cgen: unknown op %N", n);
+		fatal("cgen: unknown op %+hN", n);
 		break;
 
 	case OREAL:
@@ -190,12 +212,12 @@ cgen(Node *n, Node *res)
 	case OGE:
 	case OGT:
 	case ONOT:
-		p1 = gbranch(AB, T);
+		p1 = gbranch(AB, T, 0);
 		p2 = pc;
 		gmove(nodbool(1), res);
-		p3 = gbranch(AB, T);
+		p3 = gbranch(AB, T, 0);
 		patch(p1, pc);
-		bgen(n, 1, p2);
+		bgen(n, 1, 0, p2);
 		gmove(nodbool(0), res);
 		patch(p3, pc);
 		goto ret;
@@ -218,13 +240,10 @@ cgen(Node *n, Node *res)
 	case OMINUS:
 		regalloc(&n1, nl->type, N);
 		cgen(nl, &n1);
-		nodconst(&n3, nl->type, 0);
-		regalloc(&n2, nl->type, res);
-		gmove(&n3, &n2);
-		gins(optoas(OSUB, nl->type), &n1, &n2);
-		gmove(&n2, res);
+		nodconst(&n2, nl->type, 0);
+		gins(optoas(OMINUS, nl->type), &n2, &n1);
+		gmove(&n1, res);
 		regfree(&n1);
-		regfree(&n2);
 		goto ret;
 
 	// symmetric binary
@@ -241,9 +260,14 @@ cgen(Node *n, Node *res)
 		a = optoas(n->op, nl->type);
 		goto abop;
 
+	case OHMUL:
+		cgen_hmul(nl, nr, res);
+		break;
+
+	case OLROT:
 	case OLSH:
 	case ORSH:
-		cgen_shift(n->op, nl, nr, res);
+		cgen_shift(n->op, n->bounded, nl, nr, res);
 		break;
 
 	case OCONV:
@@ -284,17 +308,11 @@ cgen(Node *n, Node *res)
 		break;
 
 	case OITAB:
-		// itable of interface value
+		// interface table is first word of interface value
 		igen(nl, &n1, res);
-		n1.op = OREGISTER;	// was OINDREG
-		regalloc(&n2, n->type, &n1);
-		n1.op = OINDREG;
 		n1.type = n->type;
-		n1.xoffset = 0;
-		gmove(&n1, &n2);
-		gmove(&n2, res);
+		gmove(&n1, res);
 		regfree(&n1);
-		regfree(&n2);
 		break;
 
 	case OLEN:
@@ -305,11 +323,8 @@ cgen(Node *n, Node *res)
 			cgen(nl, &n1);
 
 			nodconst(&n2, types[tptr], 0);
-			regalloc(&n3, n2.type, N);
-			gmove(&n2, &n3);
-			gcmp(optoas(OCMP, types[tptr]), &n1, &n3);
-			regfree(&n3);
-			p1 = gbranch(optoas(OEQ, types[tptr]), T);
+			gcmp(optoas(OCMP, types[tptr]), &n1, &n2);
+			p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
 
 			n2 = n1;
 			n2.op = OINDREG;
@@ -325,15 +340,10 @@ cgen(Node *n, Node *res)
 		if(istype(nl->type, TSTRING) || isslice(nl->type)) {
 			// both slice and string have len one pointer into the struct.
 			igen(nl, &n1, res);
-			n1.op = OREGISTER;	// was OINDREG
-			regalloc(&n2, types[TUINT32], &n1);
-			n1.op = OINDREG;
 			n1.type = types[TUINT32];
-			n1.xoffset = Array_nel;
-			gmove(&n1, &n2);
-			gmove(&n2, res);
+			n1.xoffset += Array_nel;
+			gmove(&n1, res);
 			regfree(&n1);
-			regfree(&n2);
 			break;
 		}
 		fatal("cgen: OLEN: unknown type %lT", nl->type);
@@ -347,11 +357,8 @@ cgen(Node *n, Node *res)
 			cgen(nl, &n1);
 
 			nodconst(&n2, types[tptr], 0);
-			regalloc(&n3, n2.type, N);
-			gmove(&n2, &n3);
-			gcmp(optoas(OCMP, types[tptr]), &n1, &n3);
-			regfree(&n3);
-			p1 = gbranch(optoas(OEQ, types[tptr]), T);
+			gcmp(optoas(OCMP, types[tptr]), &n1, &n2);
+			p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
 
 			n2 = n1;
 			n2.op = OINDREG;
@@ -366,11 +373,9 @@ cgen(Node *n, Node *res)
 			break;
 		}
 		if(isslice(nl->type)) {
-			regalloc(&n1, types[tptr], res);
-			agen(nl, &n1);
-			n1.op = OINDREG;
+			igen(nl, &n1, res);
 			n1.type = types[TUINT32];
-			n1.xoffset = Array_cap;
+			n1.xoffset += Array_cap;
 			gmove(&n1, res);
 			regfree(&n1);
 			break;
@@ -383,7 +388,22 @@ cgen(Node *n, Node *res)
 		break;
 
 	case OCALLMETH:
-		cgen_callmeth(n, 0);
+	case OCALLFUNC:
+		// Release res so that it is available for cgen_call.
+		// Pick it up again after the call.
+		rg = -1;
+		if(n->ullman >= UINF) {
+			if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
+				rg = res->val.u.reg;
+				reg[rg]--;
+			}
+		}
+		if(n->op == OCALLMETH)
+			cgen_callmeth(n, 0);
+		else
+			cgen_call(n, 0);
+		if(rg >= 0)
+			reg[rg]++;
 		cgen_callret(n, res);
 		break;
 
@@ -392,11 +412,6 @@ cgen(Node *n, Node *res)
 		cgen_callret(n, res);
 		break;
 
-	case OCALLFUNC:
-		cgen_call(n, 0);
-		cgen_callret(n, res);
-		break;
-
 	case OMOD:
 	case ODIV:
 		a = optoas(n->op, nl->type);
@@ -416,18 +431,43 @@ abop:	// asymmetric binary
 	if(nl->ullman >= nr->ullman) {
 		regalloc(&n1, nl->type, res);
 		cgen(nl, &n1);
-		regalloc(&n2, nr->type, N);
-		cgen(nr, &n2);
+		switch(n->op) {
+		case OADD:
+		case OSUB:
+		case OAND:
+		case OOR:
+		case OXOR:
+			if(smallintconst(nr)) {
+				n2 = *nr;
+				break;
+			}
+		default:
+			regalloc(&n2, nr->type, N);
+			cgen(nr, &n2);
+		}
 	} else {
-		regalloc(&n2, nr->type, res);
-		cgen(nr, &n2);
+		switch(n->op) {
+		case OADD:
+		case OSUB:
+		case OAND:
+		case OOR:
+		case OXOR:
+			if(smallintconst(nr)) {
+				n2 = *nr;
+				break;
+			}
+		default:
+			regalloc(&n2, nr->type, res);
+			cgen(nr, &n2);
+		}
 		regalloc(&n1, nl->type, N);
 		cgen(nl, &n1);
 	}
 	gins(a, &n2, &n1);
 	gmove(&n1, res);
 	regfree(&n1);
-	regfree(&n2);
+	if(n2.op != OLITERAL)
+		regfree(&n2);
 	goto ret;
 
 flt:	// floating-point.
@@ -478,7 +518,7 @@ ret:
  * returns Prog* to patch to panic call.
  */
 Prog*
-cgenindex(Node *n, Node *res)
+cgenindex(Node *n, Node *res, int bounded)
 {
 	Node tmp, lo, hi, zero, n1, n2;
 
@@ -491,7 +531,7 @@ cgenindex(Node *n, Node *res)
 	cgen(n, &tmp);
 	split64(&tmp, &lo, &hi);
 	gmove(&lo, res);
-	if(debug['B']) {
+	if(bounded) {
 		splitclean();
 		return nil;
 	}
@@ -504,7 +544,7 @@ cgenindex(Node *n, Node *res)
 	regfree(&n2);
 	regfree(&n1);
 	splitclean();
-	return gbranch(ABNE, T);
+	return gbranch(ABNE, T, -1);
 }
 
 /*
@@ -514,11 +554,8 @@ cgenindex(Node *n, Node *res)
 void
 agen(Node *n, Node *res)
 {
-	Node *nl, *nr;
-	Node n1, n2, n3, n4, n5, tmp;
-	Prog *p1, *p2;
-	uint32 w;
-	uint64 v;
+	Node *nl;
+	Node n1, n2, n3;
 	int r;
 
 	if(debug['g']) {
@@ -531,6 +568,21 @@ agen(Node *n, Node *res)
 	while(n->op == OCONVNOP)
 		n = n->left;
 
+	if(isconst(n, CTNIL) && n->type->width > widthptr) {
+		// Use of a nil interface or nil slice.
+		// Create a temporary we can take the address of and read.
+		// The generated code is just going to panic, so it need not
+		// be terribly efficient. See issue 3670.
+		tempname(&n1, n->type);
+		clearfat(&n1);
+		regalloc(&n2, types[tptr], res);
+		gins(AMOVW, &n1, &n2);
+		gmove(&n2, res);
+		regfree(&n2);
+		goto ret;
+	}
+		
+
 	if(n->addable) {
 		memset(&n1, 0, sizeof n1);
 		n1.op = OADDR;
@@ -543,11 +595,10 @@ agen(Node *n, Node *res)
 	}
 
 	nl = n->left;
-	nr = n->right;
 
 	switch(n->op) {
 	default:
-		fatal("agen: unknown op %N", n);
+		fatal("agen: unknown op %+hN", n);
 		break;
 
 	case OCALLMETH:
@@ -575,16 +626,305 @@ agen(Node *n, Node *res)
 		cgen_aret(n, res);
 		break;
 
+	case OSLICE:
+	case OSLICEARR:
+	case OSLICESTR:
+		tempname(&n1, n->type);
+		cgen_slice(n, &n1);
+		agen(&n1, res);
+		break;
+
+	case OEFACE:
+		tempname(&n1, n->type);
+		cgen_eface(n, &n1);
+		agen(&n1, res);
+		break;
+
+	case OINDEX:
+		agenr(n, &n1, res);
+		gmove(&n1, res);
+		regfree(&n1);
+		break;
+
+	case ONAME:
+		// should only get here with names in this func.
+		if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
+			dump("bad agen", n);
+			fatal("agen: bad ONAME funcdepth %d != %d",
+				n->funcdepth, funcdepth);
+		}
+
+		// should only get here for heap vars or paramref
+		if(!(n->class & PHEAP) && n->class != PPARAMREF) {
+			dump("bad agen", n);
+			fatal("agen: bad ONAME class %#x", n->class);
+		}
+		cgen(n->heapaddr, res);
+		if(n->xoffset != 0) {
+			nodconst(&n1, types[TINT32], n->xoffset);
+			regalloc(&n2, n1.type, N);
+			regalloc(&n3, types[TINT32], N);
+			gmove(&n1, &n2);
+			gmove(res, &n3);
+			gins(optoas(OADD, types[tptr]), &n2, &n3);
+			gmove(&n3, res);
+			regfree(&n2);
+			regfree(&n3);
+		}
+		break;
+
+	case OIND:
+		cgen(nl, res);
+		break;
+
+	case ODOT:
+		agen(nl, res);
+		if(n->xoffset != 0) {
+			nodconst(&n1, types[TINT32], n->xoffset);
+			regalloc(&n2, n1.type, N);
+			regalloc(&n3, types[TINT32], N);
+			gmove(&n1, &n2);
+			gmove(res, &n3);
+			gins(optoas(OADD, types[tptr]), &n2, &n3);
+			gmove(&n3, res);
+			regfree(&n2);
+			regfree(&n3);
+		}
+		break;
+
+	case ODOTPTR:
+		cgen(nl, res);
+		if(n->xoffset != 0) {
+			// explicit check for nil if struct is large enough
+			// that we might derive too big a pointer.
+			if(nl->type->type->width >= unmappedzero) {
+				regalloc(&n1, types[tptr], N);
+				gmove(res, &n1);
+				regalloc(&n2, types[TUINT8], &n1);
+				n1.op = OINDREG;
+				n1.type = types[TUINT8];
+				n1.xoffset = 0;
+				gmove(&n1, &n2);
+				regfree(&n1);
+				regfree(&n2);
+			}
+			nodconst(&n1, types[TINT32], n->xoffset);
+			regalloc(&n2, n1.type, N);
+			regalloc(&n3, types[tptr], N);
+			gmove(&n1, &n2);
+			gmove(res, &n3);
+			gins(optoas(OADD, types[tptr]), &n2, &n3);
+			gmove(&n3, res);
+			regfree(&n2);
+			regfree(&n3);
+		}
+		break;
+	}
+
+ret:
+	;
+}
+
+/*
+ * generate:
+ *	newreg = &n;
+ *	res = newreg
+ *
+ * on exit, a has been changed to be *newreg.
+ * caller must regfree(a).
+ */
+void
+igen(Node *n, Node *a, Node *res)
+{
+	Node n1, n2;
+	int r;
+
+	if(debug['g']) {
+		dump("\nigen-n", n);
+	}
+	switch(n->op) {
+	case ONAME:
+		if((n->class&PHEAP) || n->class == PPARAMREF)
+			break;
+		*a = *n;
+		return;
+
+	case OINDREG:
+		// Increase the refcount of the register so that igen's caller
+		// has to call regfree.
+		if(n->val.u.reg != REGSP)
+			reg[n->val.u.reg]++;
+		*a = *n;
+		return;
+
+	case ODOT:
+		igen(n->left, a, res);
+		a->xoffset += n->xoffset;
+		a->type = n->type;
+		return;
+
+	case ODOTPTR:
+		if(n->left->addable
+			|| n->left->op == OCALLFUNC
+			|| n->left->op == OCALLMETH
+			|| n->left->op == OCALLINTER) {
+			// igen-able nodes.
+			igen(n->left, &n1, res);
+			regalloc(a, types[tptr], &n1);
+			gmove(&n1, a);
+			regfree(&n1);
+		} else {
+			regalloc(a, types[tptr], res);
+			cgen(n->left, a);
+		}
+		if(n->xoffset != 0) {
+			// explicit check for nil if struct is large enough
+			// that we might derive too big a pointer.
+			if(n->left->type->type->width >= unmappedzero) {
+				regalloc(&n1, types[tptr], N);
+				gmove(a, &n1);
+				regalloc(&n2, types[TUINT8], &n1);
+				n1.op = OINDREG;
+				n1.type = types[TUINT8];
+				n1.xoffset = 0;
+				gmove(&n1, &n2);
+				regfree(&n1);
+				regfree(&n2);
+			}
+		}
+		a->op = OINDREG;
+		a->xoffset = n->xoffset;
+		a->type = n->type;
+		return;
+
+	case OCALLMETH:
+	case OCALLFUNC:
+	case OCALLINTER:
+		// Release res so that it is available for cgen_call.
+		// Pick it up again after the call.
+		r = -1;
+		if(n->ullman >= UINF) {
+			if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
+				r = res->val.u.reg;
+				reg[r]--;
+			}
+		}
+		switch(n->op) {
+		case OCALLMETH:
+			cgen_callmeth(n, 0);
+			break;
+		case OCALLFUNC:
+			cgen_call(n, 0);
+			break;
+		case OCALLINTER:
+			cgen_callinter(n, N, 0);
+			break;
+		}
+		if(r >= 0)
+			reg[r]++;
+		regalloc(a, types[tptr], res);
+		cgen_aret(n, a);
+		a->op = OINDREG;
+		a->type = n->type;
+		return;
+	}
+
+	agenr(n, a, res);
+	a->op = OINDREG;
+	a->type = n->type;
+}
+
+/*
+ * allocate a register in res and generate
+ *  newreg = &n
+ * The caller must call regfree(a).
+ */
+void
+cgenr(Node *n, Node *a, Node *res)
+{
+	Node n1;
+
+	if(debug['g'])
+		dump("cgenr-n", n);
+
+	if(isfat(n->type))
+		fatal("cgenr on fat node");
+
+	if(n->addable) {
+		regalloc(a, types[tptr], res);
+		gmove(n, a);
+		return;
+	}
+
+	switch(n->op) {
+	case ONAME:
+	case ODOT:
+	case ODOTPTR:
+	case OINDEX:
+	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		igen(n, &n1, res);
+		regalloc(a, types[tptr], &n1);
+		gmove(&n1, a);
+		regfree(&n1);
+		break;
+	default:
+		regalloc(a, n->type, res);
+		cgen(n, a);
+		break;
+	}
+}
+
+/*
+ * generate:
+ *	newreg = &n;
+ *
+ * caller must regfree(a).
+ */
+void
+agenr(Node *n, Node *a, Node *res)
+{
+	Node *nl, *nr;
+	Node n1, n2, n3, n4, tmp;
+	Prog *p1, *p2;
+	uint32 w;
+	uint64 v;
+	int bounded;
+
+	if(debug['g'])
+		dump("agenr-n", n);
+
+	nl = n->left;
+	nr = n->right;
+
+	switch(n->op) {
+	case ODOT:
+	case ODOTPTR:
+	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		igen(n, &n1, res);
+		regalloc(a, types[tptr], &n1);
+		agen(&n1, a);
+		regfree(&n1);
+		break;
+
+	case OIND:
+		cgenr(n->left, a, res);
+		break;
+
 	case OINDEX:
 		p2 = nil;  // to be patched to panicindex.
 		w = n->type->width;
+		bounded = debug['B'] || n->bounded;
 		if(nr->addable) {
 			if(!isconst(nr, CTINT))
 				tempname(&tmp, types[TINT32]);
 			if(!isconst(nl, CTSTR))
 				agenr(nl, &n3, res);
 			if(!isconst(nr, CTINT)) {
-				p2 = cgenindex(nr, &tmp);
+				p2 = cgenindex(nr, &tmp, bounded);
 				regalloc(&n1, tmp.type, N);
 				gmove(&tmp, &n1);
 			}
@@ -592,17 +932,16 @@ agen(Node *n, Node *res)
 		if(nl->addable) {
 			if(!isconst(nr, CTINT)) {
 				tempname(&tmp, types[TINT32]);
-				p2 = cgenindex(nr, &tmp);
+				p2 = cgenindex(nr, &tmp, bounded);
 				regalloc(&n1, tmp.type, N);
 				gmove(&tmp, &n1);
 			}
 			if(!isconst(nl, CTSTR)) {
-				regalloc(&n3, types[tptr], res);
-				agen(nl, &n3);
+				agenr(nl, &n3, res);
 			}
 		} else {
 			tempname(&tmp, types[TINT32]);
-			p2 = cgenindex(nr, &tmp);
+			p2 = cgenindex(nr, &tmp, bounded);
 			nr = &tmp;
 			if(!isconst(nl, CTSTR))
 				agenr(nl, &n3, res);
@@ -614,26 +953,37 @@ agen(Node *n, Node *res)
 		// i is in &n1 (if not constant)
 		// w is width
 
+		// explicit check for nil if array is large enough
+		// that we might derive too big a pointer.
+		if(isfixedarray(nl->type) && nl->type->width >= unmappedzero) {
+			regalloc(&n4, types[tptr], N);
+			gmove(&n3, &n4);
+			regalloc(&tmp, types[TUINT8], &n4);
+			n4.op = OINDREG;
+			n4.type = types[TUINT8];
+			n4.xoffset = 0;
+			gmove(&n4, &tmp);
+			regfree(&n4);
+			regfree(&tmp);
+		}
+
 		// constant index
 		if(isconst(nr, CTINT)) {
 			if(isconst(nl, CTSTR))
 				fatal("constant string constant index");
 			v = mpgetfix(nr->val.u.xval);
 			if(isslice(nl->type) || nl->type->etype == TSTRING) {
-				if(!debug['B'] && !n->etype) {
+				if(!debug['B'] && !n->bounded) {
 					n1 = n3;
 					n1.op = OINDREG;
 					n1.type = types[tptr];
 					n1.xoffset = Array_nel;
 					regalloc(&n4, n1.type, N);
-					cgen(&n1, &n4);
+					gmove(&n1, &n4);
 					nodconst(&n2, types[TUINT32], v);
-					regalloc(&n5, n2.type, N);
-					gmove(&n2, &n5);
-					gcmp(optoas(OCMP, types[TUINT32]), &n4, &n5);
+					gcmp(optoas(OCMP, types[TUINT32]), &n4, &n2);
 					regfree(&n4);
-					regfree(&n5);
-					p1 = gbranch(optoas(OGT, types[TUINT32]), T);
+					p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
 					ginscall(panicindex, 0);
 					patch(p1, pc);
 				}
@@ -646,13 +996,8 @@ agen(Node *n, Node *res)
 			}
 
 			nodconst(&n2, types[tptr], v*w);
-			regalloc(&n4, n2.type, N);
-			gmove(&n2, &n4);
-			gins(optoas(OADD, types[tptr]), &n4, &n3);
-			regfree(&n4);
-
-			gmove(&n3, res);
-			regfree(&n3);
+			gins(optoas(OADD, types[tptr]), &n2, &n3);
+			*a = n3;
 			break;
 		}
 
@@ -660,25 +1005,24 @@ agen(Node *n, Node *res)
 		gmove(&n1, &n2);
 		regfree(&n1);
 
-		if(!debug['B'] && !n->etype) {
+		if(!debug['B'] && !n->bounded) {
 			// check bounds
-			regalloc(&n4, types[TUINT32], N);
 			if(isconst(nl, CTSTR)) {
-				nodconst(&n1, types[TUINT32], nl->val.u.sval->len);
-				gmove(&n1, &n4);
+				nodconst(&n4, types[TUINT32], nl->val.u.sval->len);
 			} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
 				n1 = n3;
 				n1.op = OINDREG;
 				n1.type = types[tptr];
 				n1.xoffset = Array_nel;
-				cgen(&n1, &n4);
-			} else {
-				nodconst(&n1, types[TUINT32], nl->type->bound);
+				regalloc(&n4, types[TUINT32], N);
 				gmove(&n1, &n4);
+			} else {
+				nodconst(&n4, types[TUINT32], nl->type->bound);
 			}
 			gcmp(optoas(OCMP, types[TUINT32]), &n2, &n4);
-			regfree(&n4);
-			p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+			if(n4.op == OREGISTER)
+				regfree(&n4);
+			p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
 			if(p2)
 				patch(p2, pc);
 			ginscall(panicindex, 0);
@@ -713,7 +1057,7 @@ agen(Node *n, Node *res)
 			else if(w == 4)
 				gshift(AADD, &n2, SHIFT_LL, 2, &n3);
 			else if(w == 8)
-				gshift(AADD, &n2, SHIFT_LL, 3, &n3);	
+				gshift(AADD, &n2, SHIFT_LL, 3, &n3);
 		} else {
 			regalloc(&n4, types[TUINT32], N);
 			nodconst(&n1, types[TUINT32], w);
@@ -721,122 +1065,21 @@ agen(Node *n, Node *res)
 			gins(optoas(OMUL, types[TUINT32]), &n4, &n2);
 			gins(optoas(OADD, types[tptr]), &n2, &n3);
 			regfree(&n4);
-			gmove(&n3, res);
 		}
 
-		gmove(&n3, res);
+		*a = n3;
 		regfree(&n2);
-		regfree(&n3);
 		break;
 
-	case ONAME:
-		// should only get here with names in this func.
-		if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
-			dump("bad agen", n);
-			fatal("agen: bad ONAME funcdepth %d != %d",
-				n->funcdepth, funcdepth);
-		}
-
-		// should only get here for heap vars or paramref
-		if(!(n->class & PHEAP) && n->class != PPARAMREF) {
-			dump("bad agen", n);
-			fatal("agen: bad ONAME class %#x", n->class);
-		}
-		cgen(n->heapaddr, res);
-		if(n->xoffset != 0) {
-			nodconst(&n1, types[TINT32], n->xoffset);
-			regalloc(&n2, n1.type, N);
-			regalloc(&n3, types[TINT32], N);
-			gmove(&n1, &n2);
-			gmove(res, &n3);
-			gins(optoas(OADD, types[tptr]), &n2, &n3);
-			gmove(&n3, res);
-			regfree(&n2);
-			regfree(&n3);
-		}
-		break;
-
-	case OIND:
-		cgen(nl, res);
-		break;
-
-	case ODOT:
-		agen(nl, res);
-		if(n->xoffset != 0) {
-			nodconst(&n1, types[TINT32], n->xoffset);
-			regalloc(&n2, n1.type, N);
-			regalloc(&n3, types[TINT32], N);
-			gmove(&n1, &n2);
-			gmove(res, &n3);
-			gins(optoas(OADD, types[tptr]), &n2, &n3);
-			gmove(&n3, res);
-			regfree(&n2);
-			regfree(&n3);
-		}
-		break;
-
-	case ODOTPTR:
-		cgen(nl, res);
-		if(n->xoffset != 0) {
-			// explicit check for nil if struct is large enough
-			// that we might derive too big a pointer.
-			if(nl->type->type->width >= unmappedzero) {
-				regalloc(&n1, types[tptr], N);
-				gmove(res, &n1);
-				p1 = gins(AMOVW, &n1, &n1);
-				p1->from.type = D_OREG;
-				p1->from.offset = 0;
-				regfree(&n1);
-			}
-			nodconst(&n1, types[TINT32], n->xoffset);
-			regalloc(&n2, n1.type, N);
-			regalloc(&n3, types[tptr], N);
-			gmove(&n1, &n2);
-			gmove(res, &n3);
-			gins(optoas(OADD, types[tptr]), &n2, &n3);
-			gmove(&n3, res);
-			regfree(&n2);
-			regfree(&n3);
-		}
+	default:
+		regalloc(a, types[tptr], res);
+		agen(n, a);
 		break;
 	}
-
-ret:
-	;
 }
 
-/*
- * generate:
- *	newreg = &n;
- *	res = newreg
- *
- * on exit, a has been changed to be *newreg.
- * caller must regfree(a).
- */
 void
-igen(Node *n, Node *a, Node *res)
-{
-	regalloc(a, types[tptr], res);
-	agen(n, a);
-	a->op = OINDREG;
-	a->type = n->type;
-}
-
-/*
- * generate:
- *	newreg = &n;
- *
- * caller must regfree(a).
- */
-void
-agenr(Node *n, Node *a, Node *res)
-{
-	regalloc(a, types[tptr], res);
-	agen(n, a);
-}
-
-void
-gencmp0(Node *n, Type *t, int o, Prog *to)
+gencmp0(Node *n, Type *t, int o, int likely, Prog *to)
 {
 	Node n1, n2, n3;
 	int a;
@@ -853,7 +1096,7 @@ gencmp0(Node *n, Type *t, int o, Prog *to)
 	} else
 		gins(ATST, &n1, N);
 	a = optoas(o, t);
-	patch(gbranch(a, t), to);
+	patch(gbranch(a, t, likely), to);
 	regfree(&n1);
 }
 
@@ -862,7 +1105,7 @@ gencmp0(Node *n, Type *t, int o, Prog *to)
  *	if(n == true) goto to;
  */
 void
-bgen(Node *n, int true, Prog *to)
+bgen(Node *n, int true, int likely, Prog *to)
 {
 	int et, a;
 	Node *nl, *nr, *r;
@@ -900,13 +1143,13 @@ bgen(Node *n, int true, Prog *to)
 		a = ONE;
 		if(!true)
 			a = OEQ;
-		gencmp0(n, n->type, a, to);
+		gencmp0(n, n->type, a, likely, to);
 		goto ret;
 
 	case OLITERAL:
 		// need to ask if it is bool?
 		if(!true == !n->val.u.bval)
-			patch(gbranch(AB, T), to);
+			patch(gbranch(AB, T, 0), to);
 		goto ret;
 
 	case OANDAND:
@@ -914,12 +1157,12 @@ bgen(Node *n, int true, Prog *to)
 			goto caseor;
 
 	caseand:
-		p1 = gbranch(AB, T);
-		p2 = gbranch(AB, T);
+		p1 = gbranch(AB, T, 0);
+		p2 = gbranch(AB, T, 0);
 		patch(p1, pc);
-		bgen(n->left, !true, p2);
-		bgen(n->right, !true, p2);
-		p1 = gbranch(AB, T);
+		bgen(n->left, !true, -likely, p2);
+		bgen(n->right, !true, -likely, p2);
+		p1 = gbranch(AB, T, 0);
 		patch(p1, to);
 		patch(p2, pc);
 		goto ret;
@@ -929,8 +1172,8 @@ bgen(Node *n, int true, Prog *to)
 			goto caseand;
 
 	caseor:
-		bgen(n->left, true, to);
-		bgen(n->right, true, to);
+		bgen(n->left, true, likely, to);
+		bgen(n->right, true, likely, to);
 		goto ret;
 
 	case OEQ:
@@ -952,7 +1195,7 @@ bgen(Node *n, int true, Prog *to)
 	switch(n->op) {
 
 	case ONOT:
-		bgen(nl, !true, to);
+		bgen(nl, !true, likely, to);
 		goto ret;
 
 	case OEQ:
@@ -965,14 +1208,14 @@ bgen(Node *n, int true, Prog *to)
 		if(!true) {
 			if(isfloat[nl->type->etype]) {
 				// brcom is not valid on floats when NaN is involved.
-				p1 = gbranch(AB, T);
-				p2 = gbranch(AB, T);
+				p1 = gbranch(AB, T, 0);
+				p2 = gbranch(AB, T, 0);
 				patch(p1, pc);
 				ll = n->ninit;
 				n->ninit = nil;
-				bgen(n, 1, p2);
+				bgen(n, 1, -likely, p2);
 				n->ninit = ll;
-				patch(gbranch(AB, T), to);
+				patch(gbranch(AB, T, 0), to);
 				patch(p2, pc);
 				goto ret;
 			}				
@@ -995,34 +1238,12 @@ bgen(Node *n, int true, Prog *to)
 				break;
 			}
 
-			regalloc(&n1, types[tptr], N);
-			agen(nl, &n1);
-			n2 = n1;
-			n2.op = OINDREG;
-			n2.xoffset = Array_array;
-			gencmp0(&n2, types[tptr], a, to);
-			regfree(&n1);
-			break;
-
-#ifdef	NOTDEF
-			a = optoas(a, types[tptr]);
-			regalloc(&n1, types[tptr], N);
-			regalloc(&n3, types[tptr], N);
-			regalloc(&n4, types[tptr], N);
-			agen(nl, &n1);
-			n2 = n1;
-			n2.op = OINDREG;
-			n2.xoffset = Array_array;
-			gmove(&n2, &n4);
-			nodconst(&tmp, types[tptr], 0);
-			gmove(&tmp, &n3);
-			gcmp(optoas(OCMP, types[tptr]), &n4, &n3);
-			patch(gbranch(a, types[tptr]), to);
-			regfree(&n4);
-			regfree(&n3);
+			igen(nl, &n1, N);
+			n1.xoffset += Array_array;
+			n1.type = types[tptr];
+			gencmp0(&n1, types[tptr], a, likely, to);
 			regfree(&n1);
 			break;
-#endif
 		}
 
 		if(isinter(nl->type)) {
@@ -1032,38 +1253,16 @@ bgen(Node *n, int true, Prog *to)
 				break;
 			}
 
-			regalloc(&n1, types[tptr], N);
-			agen(nl, &n1);
-			n2 = n1;
-			n2.op = OINDREG;
-			n2.xoffset = 0;
-			gencmp0(&n2, types[tptr], a, to);
-			regfree(&n1);
-			break;
-
-#ifdef	NOTDEF
-			a = optoas(a, types[tptr]);
-			regalloc(&n1, types[tptr], N);
-			regalloc(&n3, types[tptr], N);
-			regalloc(&n4, types[tptr], N);
-			agen(nl, &n1);
-			n2 = n1;
-			n2.op = OINDREG;
-			n2.xoffset = 0;
-			gmove(&n2, &n4);
-			nodconst(&tmp, types[tptr], 0);
-			gmove(&tmp, &n3);
-			gcmp(optoas(OCMP, types[tptr]), &n4, &n3);
-			patch(gbranch(a, types[tptr]), to);
+			igen(nl, &n1, N);
+			n1.type = types[tptr];
+			n1.xoffset += 0;
+			gencmp0(&n1, types[tptr], a, likely, to);
 			regfree(&n1);
-			regfree(&n3);
-			regfree(&n4);
 			break;
-#endif
 		}
 
 		if(iscomplex[nl->type->etype]) {
-			complexbool(a, nl, nr, true, to);
+			complexbool(a, nl, nr, true, likely, to);
 			break;
 		}
 
@@ -1078,17 +1277,17 @@ bgen(Node *n, int true, Prog *to)
 				cgen(nr, &n2);
 				nr = &n2;
 			}
-			cmp64(nl, nr, a, to);
+			cmp64(nl, nr, a, likely, to);
 			break;
 		}
 
 		if(nr->op == OLITERAL) {
 			if(isconst(nr, CTINT) &&  mpgetfix(nr->val.u.xval) == 0) {
-				gencmp0(nl, nl->type, a, to);
+				gencmp0(nl, nl->type, a, likely, to);
 				break;
 			}
 			if(nr->val.ctype == CTNIL) {
-				gencmp0(nl, nl->type, a, to);
+				gencmp0(nl, nl->type, a, likely, to);
 				break;
 			}
 		}
@@ -1110,7 +1309,7 @@ bgen(Node *n, int true, Prog *to)
 			cgen(&tmp, &n1);
 
 			gcmp(optoas(OCMP, nr->type), &n1, &n2);
-			patch(gbranch(a, nr->type), to);
+			patch(gbranch(a, nr->type, likely), to);
 
 			regfree(&n1);
 			regfree(&n2);
@@ -1131,14 +1330,17 @@ bgen(Node *n, int true, Prog *to)
 
 		gcmp(optoas(OCMP, nr->type), &n1, &n2);
 		if(isfloat[nl->type->etype]) {
-			p1 = gbranch(ABVS, nr->type);
-			patch(gbranch(a, nr->type), to);
-			if(n->op == ONE)
+			if(n->op == ONE) {
+				p1 = gbranch(ABVS, nr->type, likely);
+				patch(gbranch(a, nr->type, likely), to);
 				patch(p1, to);
-			else
+			} else {
+				p1 = gbranch(ABVS, nr->type, -likely);
+				patch(gbranch(a, nr->type, likely), to);
 				patch(p1, pc);
+			}
 		} else {
-			patch(gbranch(a, nr->type), to);
+			patch(gbranch(a, nr->type, likely), to);
 		}
 		regfree(&n1);
 		regfree(&n2);
@@ -1241,6 +1443,10 @@ sgen(Node *n, Node *res, int64 w)
 		return;
 	}
 
+	// Avoid taking the address for simple enough types.
+	if(componentgen(n, res))
+		return;
+	
 	// determine alignment.
 	// want to avoid unaligned access, so have to use
 	// smaller operations for less aligned types.
@@ -1284,16 +1490,14 @@ sgen(Node *n, Node *res, int64 w)
 	if(osrc < odst && odst < osrc+w)
 		dir = -dir;
 
-	regalloc(&dst, types[tptr], res);
 	if(n->ullman >= res->ullman) {
-		agen(n, &dst);	// temporarily use dst
+		agenr(n, &dst, res);	// temporarily use dst
 		regalloc(&src, types[tptr], N);
 		gins(AMOVW, &dst, &src);
 		agen(res, &dst);
 	} else {
-		agen(res, &dst);
-		regalloc(&src, types[tptr], N);
-		agen(n, &src);
+		agenr(res, &dst, res);
+		agenr(n, &src, N);
 	}
 
 	regalloc(&tmp, types[TUINT32], N);
@@ -1338,7 +1542,7 @@ sgen(Node *n, Node *res, int64 w)
 		p = gins(ACMP, &src, N);
 		raddr(&nend, p);
 
-		patch(gbranch(ABNE, T), ploop);
+		patch(gbranch(ABNE, T, 0), ploop);
  		regfree(&nend);
 	} else {
 		while(c-- > 0) {
@@ -1358,3 +1562,157 @@ sgen(Node *n, Node *res, int64 w)
 	regfree(&src);
 	regfree(&tmp);
 }
+
+static int
+cadable(Node *n)
+{
+	if(!n->addable) {
+		// dont know how it happens,
+		// but it does
+		return 0;
+	}
+
+	switch(n->op) {
+	case ONAME:
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * copy a composite value by moving its individual components.
+ * Slices, strings and interfaces are supported.
+ * nr is N when assigning a zero value.
+ * return 1 if can do, 0 if cant.
+ */
+int
+componentgen(Node *nr, Node *nl)
+{
+	Node nodl, nodr, tmp;
+	int freel, freer;
+
+	freel = 0;
+	freer = 0;
+
+	switch(nl->type->etype) {
+	default:
+		goto no;
+
+	case TARRAY:
+		if(!isslice(nl->type))
+			goto no;
+	case TSTRING:
+	case TINTER:
+		break;
+	}
+
+	nodl = *nl;
+	if(!cadable(nl)) {
+		if(nr == N || !cadable(nr))
+			goto no;
+		igen(nl, &nodl, N);
+		freel = 1;
+	}
+
+	if(nr != N) {
+		nodr = *nr;
+		if(!cadable(nr)) {
+			igen(nr, &nodr, N);
+			freer = 1;
+		}
+	} else {
+		// When zeroing, prepare a register containing zero.
+		nodconst(&tmp, nl->type, 0);
+		regalloc(&nodr, types[TUINT], N);
+		gmove(&tmp, &nodr);
+		freer = 1;
+	}
+
+	switch(nl->type->etype) {
+	case TARRAY:
+		nodl.xoffset += Array_array;
+		nodl.type = ptrto(nl->type->type);
+
+		if(nr != N) {
+			nodr.xoffset += Array_array;
+			nodr.type = nodl.type;
+		}
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_nel-Array_array;
+		nodl.type = types[simtype[TUINT]];
+
+		if(nr != N) {
+			nodr.xoffset += Array_nel-Array_array;
+			nodr.type = nodl.type;
+		}
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_cap-Array_nel;
+		nodl.type = types[simtype[TUINT]];
+
+		if(nr != N) {
+			nodr.xoffset += Array_cap-Array_nel;
+			nodr.type = nodl.type;
+		}
+		gmove(&nodr, &nodl);
+
+		goto yes;
+
+	case TSTRING:
+		nodl.xoffset += Array_array;
+		nodl.type = ptrto(types[TUINT8]);
+
+		if(nr != N) {
+			nodr.xoffset += Array_array;
+			nodr.type = nodl.type;
+		}
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_nel-Array_array;
+		nodl.type = types[simtype[TUINT]];
+
+		if(nr != N) {
+			nodr.xoffset += Array_nel-Array_array;
+			nodr.type = nodl.type;
+		}
+		gmove(&nodr, &nodl);
+
+		goto yes;
+
+	case TINTER:
+		nodl.xoffset += Array_array;
+		nodl.type = ptrto(types[TUINT8]);
+
+		if(nr != N) {
+			nodr.xoffset += Array_array;
+			nodr.type = nodl.type;
+		}
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_nel-Array_array;
+		nodl.type = ptrto(types[TUINT8]);
+
+		if(nr != N) {
+			nodr.xoffset += Array_nel-Array_array;
+			nodr.type = nodl.type;
+		}
+		gmove(&nodr, &nodl);
+
+		goto yes;
+	}
+
+no:
+	if(freer)
+		regfree(&nodr);
+	if(freel)
+		regfree(&nodl);
+	return 0;
+
+yes:
+	if(freer)
+		regfree(&nodr);
+	if(freel)
+		regfree(&nodl);
+	return 1;
+}
diff --git a/src/cmd/5g/cgen64.c b/src/cmd/5g/cgen64.c
index 1235d1a..ef11e2a 100644
--- a/src/cmd/5g/cgen64.c
+++ b/src/cmd/5g/cgen64.c
@@ -94,6 +94,7 @@ cgen64(Node *n, Node *res)
 	case OAND:
 	case OOR:
 	case OXOR:
+	case OLROT:
 		// binary operators.
 		// common setup below.
 		break;
@@ -175,7 +176,7 @@ cgen64(Node *n, Node *res)
 		p1->from.type = D_REG;
 		p1->from.reg = bl.val.u.reg;
 		p1->reg = ch.val.u.reg;
-		p1->to.type = D_REGREG;
+		p1->to.type = D_REGREG2;
 		p1->to.reg = ah.val.u.reg;
 		p1->to.offset = ah.val.u.reg;
 //print("%P\n", p1);
@@ -185,7 +186,7 @@ cgen64(Node *n, Node *res)
 		p1->from.type = D_REG;
 		p1->from.reg = bh.val.u.reg;
 		p1->reg = cl.val.u.reg;
-		p1->to.type = D_REGREG;
+		p1->to.type = D_REGREG2;
 		p1->to.reg = ah.val.u.reg;
 		p1->to.offset = ah.val.u.reg;
 //print("%P\n", p1);
@@ -197,6 +198,47 @@ cgen64(Node *n, Node *res)
 
 		break;
 
+	case OLROT:
+		// We only rotate by a constant c in [0,64).
+		// if c >= 32:
+		//	lo, hi = hi, lo
+		//	c -= 32
+		// if c == 0:
+		//	no-op
+		// else:
+		//	t = hi
+		//	shld hi:lo, c
+		//	shld lo:t, c
+		v = mpgetfix(r->val.u.xval);
+		regalloc(&bl, lo1.type, N);
+		regalloc(&bh, hi1.type, N);
+		if(v >= 32) {
+			// reverse during load to do the first 32 bits of rotate
+			v -= 32;
+			gins(AMOVW, &hi1, &bl);
+			gins(AMOVW, &lo1, &bh);
+		} else {
+			gins(AMOVW, &hi1, &bh);
+			gins(AMOVW, &lo1, &bl);
+		}
+		if(v == 0) {
+			gins(AMOVW, &bh, &ah);
+			gins(AMOVW, &bl, &al);
+		} else {
+			// rotate by 1 <= v <= 31
+			//	MOVW	bl<<v, al
+			//	MOVW	bh<<v, ah
+			//	OR		bl>>(32-v), ah
+			//	OR		bh>>(32-v), al
+			gshift(AMOVW, &bl, SHIFT_LL, v, &al);
+			gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
+			gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
+			gshift(AORR, &bh, SHIFT_LR, 32-v, &al);
+		}
+		regfree(&bl);
+		regfree(&bh);
+		break;
+
 	case OLSH:
 		regalloc(&bl, lo1.type, N);
 		regalloc(&bh, hi1.type, N);
@@ -243,7 +285,7 @@ cgen64(Node *n, Node *res)
 			split64(r, &cl, &ch);
 			gmove(&ch, &s);
 			gins(ATST, &s, N);
-			p6 = gbranch(ABNE, T);
+			p6 = gbranch(ABNE, T, 0);
 			gmove(&cl, &s);
 			splitclean();
 		} else {
@@ -257,7 +299,7 @@ cgen64(Node *n, Node *res)
 		p1->scond = C_SCOND_EQ;
 		p1 = gins(AMOVW, &bh, &ah);
 		p1->scond = C_SCOND_EQ;
-		p2 = gbranch(ABEQ, T);
+		p2 = gbranch(ABEQ, T, 0);
 
 		// shift is < 32
 		nodconst(&n1, types[TUINT32], 32);
@@ -281,14 +323,14 @@ cgen64(Node *n, Node *res)
 		p1->scond = C_SCOND_LO;
 
 		//	BLO	end
-		p3 = gbranch(ABLO, T);
+		p3 = gbranch(ABLO, T, 0);
 
 		// shift == 32
 		p1 = gins(AEOR, &al, &al);
 		p1->scond = C_SCOND_EQ;
 		p1 = gins(AMOVW, &bl, &ah);
 		p1->scond = C_SCOND_EQ;
-		p4 = gbranch(ABEQ, T);
+		p4 = gbranch(ABEQ, T, 0);
 
 		// shift is < 64
 		nodconst(&n1, types[TUINT32], 64);
@@ -311,7 +353,7 @@ cgen64(Node *n, Node *res)
 		p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
 		p1->scond = C_SCOND_LO;
 
-		p5 = gbranch(ABLO, T);
+		p5 = gbranch(ABLO, T, 0);
 
 		// shift >= 64
 		if (p6 != P) patch(p6, pc);
@@ -406,7 +448,7 @@ olsh_break:
 			else
 				p1 = gins(AEOR, &ah, &ah);
 			p1->scond = C_SCOND_NE;
-			p6 = gbranch(ABNE, T);
+			p6 = gbranch(ABNE, T, 0);
 			gmove(&cl, &s);
 			splitclean();
 		} else {
@@ -420,7 +462,7 @@ olsh_break:
 		p1->scond = C_SCOND_EQ;
 		p1 = gins(AMOVW, &bh, &ah);
 		p1->scond = C_SCOND_EQ;
-		p2 = gbranch(ABEQ, T);
+		p2 = gbranch(ABEQ, T, 0);
 
 		// check if shift is < 32
 		nodconst(&n1, types[TUINT32], 32);
@@ -449,7 +491,7 @@ olsh_break:
 		p1->scond = C_SCOND_LO;
 
 		//	BLO	end
-		p3 = gbranch(ABLO, T);
+		p3 = gbranch(ABLO, T, 0);
 
 		// shift == 32
 		p1 = gins(AMOVW, &bh, &al);
@@ -458,7 +500,7 @@ olsh_break:
 			gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
 		else
 			gins(AEOR, &ah, &ah);
-		p4 = gbranch(ABEQ, T);
+		p4 = gbranch(ABEQ, T, 0);
 
 		// check if shift is < 64
 		nodconst(&n1, types[TUINT32], 64);
@@ -484,7 +526,7 @@ olsh_break:
 		}
 
 		//	BLO	end
-		p5 = gbranch(ABLO, T);
+		p5 = gbranch(ABLO, T, 0);
 
 		// s >= 64
 		if(p6 != P)
@@ -633,7 +675,7 @@ orsh_break:
  * nl is memory; nr is constant or memory.
  */
 void
-cmp64(Node *nl, Node *nr, int op, Prog *to)
+cmp64(Node *nl, Node *nr, int op, int likely, Prog *to)
 {
 	Node lo1, hi1, lo2, hi2, r1, r2;
 	Prog *br;
@@ -663,14 +705,14 @@ cmp64(Node *nl, Node *nr, int op, Prog *to)
 		// cmp lo
 		// beq to
 		// L:
-		br = gbranch(ABNE, T);
+		br = gbranch(ABNE, T, -likely);
 		break;
 	case ONE:
 		// cmp hi
 		// bne to
 		// cmp lo
 		// bne to
-		patch(gbranch(ABNE, T), to);
+		patch(gbranch(ABNE, T, likely), to);
 		break;
 	case OGE:
 	case OGT:
@@ -680,8 +722,8 @@ cmp64(Node *nl, Node *nr, int op, Prog *to)
 		// cmp lo
 		// bge to (or bgt to)
 		// L:
-		patch(gbranch(optoas(OGT, t), T), to);
-		br = gbranch(optoas(OLT, t), T);
+		patch(gbranch(optoas(OGT, t), T, likely), to);
+		br = gbranch(optoas(OLT, t), T, -likely);
 		break;
 	case OLE:
 	case OLT:
@@ -691,8 +733,8 @@ cmp64(Node *nl, Node *nr, int op, Prog *to)
 		// cmp lo
 		// ble to (or jlt to)
 		// L:
-		patch(gbranch(optoas(OLT, t), T), to);
-		br = gbranch(optoas(OGT, t), T);
+		patch(gbranch(optoas(OLT, t), T, likely), to);
+		br = gbranch(optoas(OGT, t), T, -likely);
 		break;
 	}
 
@@ -707,7 +749,7 @@ cmp64(Node *nl, Node *nr, int op, Prog *to)
 	regfree(&r2);
 
 	// jump again
-	patch(gbranch(optoas(op, t), T), to);
+	patch(gbranch(optoas(op, t), T, likely), to);
 
 	// point first branch down here if appropriate
 	if(br != P)
diff --git a/src/cmd/5g/doc.go b/src/cmd/5g/doc.go
index 5a4a772..aebdcab 100644
--- a/src/cmd/5g/doc.go
+++ b/src/cmd/5g/doc.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 ignore
+
 /*
 
 5g is the version of the gc compiler for the ARM.
@@ -10,4 +12,4 @@ The $GOARCH for these tools is arm.
 It reads .go files and outputs .5 files. The flags are documented in ../gc/doc.go.
 
 */
-package documentation
+package main
diff --git a/src/cmd/5g/galign.c b/src/cmd/5g/galign.c
index 0708042..1fbf633 100644
--- a/src/cmd/5g/galign.c
+++ b/src/cmd/5g/galign.c
@@ -27,6 +27,7 @@ void
 betypeinit(void)
 {
 	widthptr = 4;
+	widthint = 4;
 
 	zprog.link = P;
 	zprog.as = AGOK;
diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h
index 7dbf3be..45a9a88 100644
--- a/src/cmd/5g/gg.h
+++ b/src/cmd/5g/gg.h
@@ -15,32 +15,36 @@ struct	Addr
 {
 	int32	offset;
 	int32	offset2;
-	double	dval;
-	Prog*	branch;
-	char	sval[NSNAME];
+
+	union {
+		double	dval;
+		vlong	vval;
+		Prog*	branch;
+		char	sval[NSNAME];
+	} u;
 
 	Sym*	sym;
+	Sym*	gotype;
 	Node*	node;
 	int	width;
 	uchar	type;
 	char	name;
 	uchar	reg;
-	char pun;
 	uchar	etype;
 };
 #define	A	((Addr*)0)
 
 struct	Prog
 {
-	short	as;		// opcode
 	uint32	loc;		// pc offset in this func
 	uint32	lineno;		// source line that generated this
-	Addr	from;		// src address
-	Addr	to;		// dst address
 	Prog*	link;		// next instruction in this func
 	void*	regp;		// points to enclosing Reg struct
+	short	as;		// opcode
 	uchar	reg;		// doubles as width in DATA op
 	uchar	scond;
+	Addr	from;		// src address
+	Addr	to;		// dst address
 };
 
 #define TEXTFLAG reg
@@ -78,22 +82,20 @@ void	cgen_callinter(Node*, Node*, int);
 void	cgen_proc(Node*, int);
 void	cgen_callret(Node*, Node*);
 void	cgen_dcl(Node*);
-int	cgen_inline(Node*, Node*);
 int	needconvert(Type*, Type*);
 void	genconv(Type*, Type*);
 void	allocparams(void);
-void	checklabels();
+void	checklabels(void);
 void	ginscall(Node*, int);
 
 /*
  * cgen
  */
 void	agen(Node*, Node*);
-Prog* cgenindex(Node *, Node *);
+Prog* cgenindex(Node *, Node *, int);
 void	igen(Node*, Node*, Node*);
 void agenr(Node *n, Node *a, Node *res);
 vlong	fieldoffset(Type*, Node*);
-void	bgen(Node*, int, Prog*);
 void	sgen(Node*, Node*, int64);
 void	gmove(Node*, Node*);
 Prog*	gins(int, Node*, Node*);
@@ -104,12 +106,14 @@ Prog*	gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs);
 Prog *	gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs);
 void	naddr(Node*, Addr*, int);
 void	cgen_aret(Node*, Node*);
-void	cgen_shift(int, Node*, Node*, Node*);
+void	cgen_hmul(Node*, Node*, Node*);
+void	cgen_shift(int, int, Node*, Node*, Node*);
+int	componentgen(Node*, Node*);
 
 /*
  * cgen64.c
  */
-void	cmp64(Node*, Node*, int, Prog*);
+void	cmp64(Node*, Node*, int, int, Prog*);
 void	cgen64(Node*, Node*);
 
 /*
@@ -117,16 +121,13 @@ void	cgen64(Node*, Node*);
  */
 void	clearp(Prog*);
 void	proglist(void);
-Prog*	gbranch(int, Type*);
+Prog*	gbranch(int, Type*, int);
 Prog*	prog(int);
-void	gaddoffset(Node*);
 void	gconv(int, int);
 int	conv2pt(Type*);
 vlong	convvtox(vlong, int);
 void	fnparam(Type*, int, int);
 Prog*	gop(int, Node*, Node*, Node*);
-void	setconst(Addr*, vlong);
-void	setaddr(Addr*, Node*);
 int	optoas(int, Type*);
 void	ginit(void);
 void	gclean(void);
@@ -141,11 +142,12 @@ int	isfat(Type*);
 int	dotaddable(Node*, Node*);
 void	sudoclean(void);
 int	sudoaddable(int, Node*, Addr*, int*);
-void	afunclit(Addr*);
+void	afunclit(Addr*, Node*);
 void	datagostring(Strlit*, Addr*);
 void	split64(Node*, Node*, Node*);
 void	splitclean(void);
 Node*	ncon(uint32 i);
+void	gtrack(Sym*);
 
 /*
  * obj.c
@@ -164,7 +166,7 @@ int	Rconv(Fmt*);
 int	Yconv(Fmt*);
 void	listinit(void);
 
-void	zaddr(Biobuf*, Addr*, int);
+void	zaddr(Biobuf*, Addr*, int, int);
 
 #pragma	varargck	type	"D"	Addr*
 #pragma	varargck	type	"M"	Addr*
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index de10062..de1671b 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -28,6 +28,9 @@ void
 markautoused(Prog* p)
 {
 	for (; p; p = p->link) {
+		if (p->as == ATYPE)
+			continue;
+
 		if (p->from.name == D_AUTO && p->from.node)
 			p->from.node->used = 1;
 
@@ -40,27 +43,38 @@ markautoused(Prog* p)
 void
 fixautoused(Prog* p)
 {
-	for (; p; p = p->link) {
+	Prog **lp;
+
+	for (lp=&p; (p=*lp) != P; ) {
+		if (p->as == ATYPE && p->from.node && p->from.name == D_AUTO && !p->from.node->used) {
+			*lp = p->link;
+			continue;
+		}
+
 		if (p->from.name == D_AUTO && p->from.node)
 			p->from.offset += p->from.node->stkdelta;
 
 		if (p->to.name == D_AUTO && p->to.node)
 			p->to.offset += p->to.node->stkdelta;
+
+		lp = &p->link;
 	}
 }
 
 /*
  * generate:
  *	call f
+ *	proc=-1	normal call but no return
  *	proc=0	normal call
  *	proc=1	goroutine run in new proc
  *	proc=2	defer call save away stack
+  *	proc=3	normal call to C pointer (not Go func value)
  */
 void
 ginscall(Node *f, int proc)
 {
 	Prog *p;
-	Node n1, r, con;
+	Node n1, r, r1, con;
 
 	switch(proc) {
 	default:
@@ -68,8 +82,26 @@ ginscall(Node *f, int proc)
 		break;
 
 	case 0:	// normal call
-		p = gins(ABL, N, f);
-		afunclit(&p->to);
+	case -1:	// normal call but no return
+		if(f->op == ONAME && f->class == PFUNC) {
+			p = gins(ABL, N, f);
+			afunclit(&p->to, f);
+			if(proc == -1 || noreturn(p))
+				gins(AUNDEF, N, N);
+			break;
+		}
+		nodreg(&r, types[tptr], 7);
+		nodreg(&r1, types[tptr], 1);
+		gmove(f, &r);
+		r.op = OINDREG;
+		gmove(&r, &r1);
+		r.op = OREGISTER;
+		r1.op = OINDREG;
+		gins(ABL, &r, &r1);
+		break;
+
+	case 3:	// normal call of c function pointer
+		gins(ABL, N, f);
 		break;
 
 	case 1:	// call in new proc (go)
@@ -120,7 +152,7 @@ ginscall(Node *f, int proc)
 			nodconst(&con, types[TINT32], 0);
 			p = gins(ACMP, &con, N);
 			p->reg = 0;
-			patch(gbranch(ABNE, T), retpc);
+			patch(gbranch(ABNE, T, -1), retpc);
 		}
 		break;
 	}
@@ -136,6 +168,7 @@ cgen_callinter(Node *n, Node *res, int proc)
 	int r;
 	Node *i, *f;
 	Node tmpi, nodo, nodr, nodsp;
+	Prog *p;
 
 	i = n->left;
 	if(i->op != ODOTINTER)
@@ -180,7 +213,17 @@ cgen_callinter(Node *n, Node *res, int proc)
 	cgen(&nodo, &nodr);	// REG = 0(REG) -- i.tab
 
 	nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
-	cgen(&nodo, &nodr);	// REG = 20+offset(REG) -- i.tab->fun[f]
+	
+	if(proc == 0) {
+		// plain call: use direct c function pointer - more efficient
+		cgen(&nodo, &nodr);	// REG = 20+offset(REG) -- i.tab->fun[f]
+		nodr.op = OINDREG;
+		proc = 3;
+	} else {
+		// go/defer. generate go func value.
+		p = gins(AMOVW, &nodo, &nodr);
+		p->from.type = D_CONST;	// REG = &(20+offset(REG)) -- i.tab->fun[f]
+	}
 
 	// BOTCH nodr.type = fntype;
 	nodr.type = n->left->type;
@@ -368,14 +411,19 @@ cgen_asop(Node *n)
 	case OOR:
 		a = optoas(n->etype, nl->type);
 		if(nl->addable) {
-			regalloc(&n3, nr->type, N);
-			cgen(nr, &n3);
+			if(smallintconst(nr))
+				n3 = *nr;
+			else {
+				regalloc(&n3, nr->type, N);
+				cgen(nr, &n3);
+			}
 			regalloc(&n2, nl->type, N);
 			cgen(nl, &n2);
 			gins(a, &n3, &n2);
 			cgen(&n2, nl);
 			regfree(&n2);
-			regfree(&n3);
+			if(n3.op != OLITERAL)
+				regfree(&n3);
 			goto ret;
 		}
 		if(nr->ullman < UINF)
@@ -399,7 +447,9 @@ cgen_asop(Node *n)
 hard:
 	n2.op = 0;
 	n1.op = 0;
-	if(nr->ullman >= nl->ullman || nl->addable) {
+	if(nr->op == OLITERAL) {
+		// don't allocate a register for literals.
+	} else if(nr->ullman >= nl->ullman || nl->addable) {
 		regalloc(&n2, nr->type, N);
 		cgen(nr, &n2);
 		nr = &n2;
@@ -464,24 +514,99 @@ samereg(Node *a, Node *b)
 }
 
 /*
+ * generate high multiply
+ *  res = (nl * nr) >> wordsize
+ */
+void
+cgen_hmul(Node *nl, Node *nr, Node *res)
+{
+	int w;
+	Node n1, n2, *tmp;
+	Type *t;
+	Prog *p;
+
+	if(nl->ullman < nr->ullman) {
+		tmp = nl;
+		nl = nr;
+		nr = tmp;
+	}
+	t = nl->type;
+	w = t->width * 8;
+	regalloc(&n1, t, res);
+	cgen(nl, &n1);
+	regalloc(&n2, t, N);
+	cgen(nr, &n2);
+	switch(simtype[t->etype]) {
+	case TINT8:
+	case TINT16:
+		gins(optoas(OMUL, t), &n2, &n1);
+		gshift(AMOVW, &n1, SHIFT_AR, w, &n1);
+		break;
+	case TUINT8:
+	case TUINT16:
+		gins(optoas(OMUL, t), &n2, &n1);
+		gshift(AMOVW, &n1, SHIFT_LR, w, &n1);
+		break;
+	case TINT32:
+	case TUINT32:
+		// perform a long multiplication.
+		if(issigned[t->etype])
+			p = gins(AMULL, &n2, N);
+		else
+			p = gins(AMULLU, &n2, N);
+		// n2 * n1 -> (n1 n2)
+		p->reg = n1.val.u.reg;
+		p->to.type = D_REGREG;
+		p->to.reg = n1.val.u.reg;
+		p->to.offset = n2.val.u.reg;
+		break;
+	default:
+		fatal("cgen_hmul %T", t);
+		break;
+	}
+	cgen(&n1, res);
+	regfree(&n1);
+	regfree(&n2);
+}
+
+/*
  * generate shift according to op, one of:
  *	res = nl << nr
  *	res = nl >> nr
  */
 void
-cgen_shift(int op, Node *nl, Node *nr, Node *res)
+cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
 {
 	Node n1, n2, n3, nt, t, lo, hi;
-	int w;
+	int w, v;
 	Prog *p1, *p2, *p3;
 	Type *tr;
 	uvlong sc;
 
+	USED(bounded);
 	if(nl->type->width > 4)
 		fatal("cgen_shift %T", nl->type);
 
 	w = nl->type->width * 8;
 
+	if(op == OLROT) {
+		v = mpgetfix(nr->val.u.xval);
+		regalloc(&n1, nl->type, res);
+		if(w == 32) {
+			cgen(nl, &n1);
+			gshift(AMOVW, &n1, SHIFT_RR, w-v, &n1);
+		} else {
+			regalloc(&n2, nl->type, N);
+			cgen(nl, &n2);
+			gshift(AMOVW, &n2, SHIFT_LL, v, &n1);
+			gshift(AORR, &n2, SHIFT_LR, w-v, &n1);
+			regfree(&n2);
+		}
+		gmove(&n1, res);
+		regfree(&n1);
+		return;
+	}
+
 	if(nr->op == OLITERAL) {
 		regalloc(&n1, nl->type, res);
 		cgen(nl, &n1);
@@ -524,6 +649,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
 		regalloc(&n3, types[TUINT32], N);
 		gmove(&lo, &n1);
 		gmove(&hi, &n3);
+		splitclean();
 		gins(ATST, &n3, N);
 		nodconst(&t, types[TUINT32], w);
 		p1 = gins(AMOVW, &t, &n1);
@@ -546,9 +672,10 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
 
 	// test for shift being 0
 	gins(ATST, &n1, N);
-	p3 = gbranch(ABEQ, T);
+	p3 = gbranch(ABEQ, T, -1);
 
 	// test and fix up large shifts
+	// TODO: if(!bounded), don't emit some of this.
 	regalloc(&n3, tr, N);
 	nodconst(&t, types[TUINT32], w);
 	gmove(&t, &n3);
@@ -589,7 +716,12 @@ clearfat(Node *nl)
 	if(debug['g'])
 		dump("\nclearfat", nl);
 
+
 	w = nl->type->width;
+	// Avoid taking the address for simple enough types.
+	if(componentgen(N, nl))
+		return;
+
 	c = w % 4;	// bytes
 	q = w / 4;	// quads
 
@@ -613,7 +745,7 @@ clearfat(Node *nl)
 
 		p = gins(ACMP, &dst, N);
 		raddr(&end, p);
-		patch(gbranch(ABNE, T), pl);
+		patch(gbranch(ABNE, T, 0), pl);
 
 		regfree(&end);
 	} else
@@ -637,395 +769,3 @@ clearfat(Node *nl)
 	regfree(&dst);
 	regfree(&nz);
 }
-
-static int
-regcmp(const void *va, const void *vb)
-{
-	Node *ra, *rb;
-
-	ra = (Node*)va;
-	rb = (Node*)vb;
-	return ra->local - rb->local;
-}
-
-static	Prog*	throwpc;
-
-// We're only going to bother inlining if we can
-// convert all the arguments to 32 bits safely.  Can we?
-static int
-fix64(NodeList *nn, int n)
-{
-	NodeList *l;
-	Node *r;
-	int i;
-	
-	l = nn;
-	for(i=0; i<n; i++) {
-		r = l->n->right;
-		if(is64(r->type) && !smallintconst(r)) {
-			if(r->op == OCONV)
-				r = r->left;
-			if(is64(r->type))
-				return 0;
-		}
-		l = l->next;
-	}
-	return 1;
-}
-
-void
-getargs(NodeList *nn, Node *reg, int n)
-{
-	NodeList *l;
-	int i;
-
-	throwpc = nil;
-
-	l = nn;
-	for(i=0; i<n; i++) {
-		if(!smallintconst(l->n->right) && !isslice(l->n->right->type)) {
-			regalloc(reg+i, l->n->right->type, N);
-			cgen(l->n->right, reg+i);
-		} else
-			reg[i] = *l->n->right;
-		if(reg[i].local != 0)
-			yyerror("local used");
-		reg[i].local = l->n->left->xoffset;
-		l = l->next;
-	}
-	qsort((void*)reg, n, sizeof(*reg), regcmp);
-	for(i=0; i<n; i++)
-		reg[i].local = 0;
-}
-
-void
-cmpandthrow(Node *nl, Node *nr)
-{
-	vlong cl;
-	Prog *p1;
-	int op;
-	Node *c, n1, n2;
-
-	op = OLE;
-	if(smallintconst(nl)) {
-		cl = mpgetfix(nl->val.u.xval);
-		if(cl == 0)
-			return;
-		if(smallintconst(nr))
-			return;
-
-		// put the constant on the right
-		op = brrev(op);
-		c = nl;
-		nl = nr;
-		nr = c;
-	}
-
-	n1.op = OXXX;
-	if(nr->op != OREGISTER) {
-		regalloc(&n1, types[TUINT32], N);
-		gmove(nr, &n1);
-		nr = &n1;
-	}
-	n2.op = OXXX;
-	if(nl->op != OREGISTER) {
-		regalloc(&n2, types[TUINT32], N);
-		gmove(nl, &n2);
-		nl = &n2;
-	}
-	gcmp(optoas(OCMP, types[TUINT32]), nl, nr);
-	if(nr == &n1)
-		regfree(&n1);
-	if(nl == &n2)
-		regfree(&n2);
-	if(throwpc == nil) {
-		p1 = gbranch(optoas(op, types[TUINT32]), T);
-		throwpc = pc;
-		ginscall(panicslice, 0);
-		patch(p1, pc);
-	} else {
-		op = brcom(op);
-		p1 = gbranch(optoas(op, types[TUINT32]), T);
-		patch(p1, throwpc);
-	}
-}
-
-int
-sleasy(Node *n)
-{
-	if(n->op != ONAME)
-		return 0;
-	if(!n->addable)
-		return 0;
-	return 1;
-}
-
-// generate inline code for
-//	slicearray
-//	sliceslice
-//	arraytoslice
-int
-cgen_inline(Node *n, Node *res)
-{
-	Node nodes[5];
-	Node n1, n2, n3, nres, ntemp;
-	vlong v;
-	int i, narg;
-
-	if(n->op != OCALLFUNC)
-		goto no;
-	if(!n->left->addable)
-		goto no;
-	if(n->left->sym == S)
-		goto no;
-	if(n->left->sym->pkg != runtimepkg)
-		goto no;
-	if(strcmp(n->left->sym->name, "slicearray") == 0)
-		goto slicearray;
-	if(strcmp(n->left->sym->name, "sliceslice") == 0) {
-		narg = 4;
-		goto sliceslice;
-	}
-	if(strcmp(n->left->sym->name, "sliceslice1") == 0) {
-		narg = 3;
-		goto sliceslice;
-	}
-	goto no;
-
-slicearray:
-	if(!sleasy(res))
-		goto no;
-	if(!fix64(n->list, 5))
-		goto no;
-	getargs(n->list, nodes, 5);
-
-	// if(hb[3] > nel[1]) goto throw
-	cmpandthrow(&nodes[3], &nodes[1]);
-
-	// if(lb[2] > hb[3]) goto throw
-	cmpandthrow(&nodes[2], &nodes[3]);
-
-	// len = hb[3] - lb[2] (destroys hb)
-	n2 = *res;
-	n2.type = types[TUINT32];
-	n2.xoffset += Array_nel;
-
-	if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) {
-		v = mpgetfix(nodes[3].val.u.xval) -
-			mpgetfix(nodes[2].val.u.xval);
-		nodconst(&n1, types[TUINT32], v);
-		gmove(&n1, &n2);
-	} else {
-		regalloc(&n1, types[TUINT32], &nodes[3]);
-		gmove(&nodes[3], &n1);
-		if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
-			gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
-		gmove(&n1, &n2);
-		regfree(&n1);
-	}
-
-	// cap = nel[1] - lb[2] (destroys nel)
-	n2 = *res;
-	n2.type = types[TUINT32];
-	n2.xoffset += Array_cap;
-
-	if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) {
-		v = mpgetfix(nodes[1].val.u.xval) -
-			mpgetfix(nodes[2].val.u.xval);
-		nodconst(&n1, types[TUINT32], v);
-		gmove(&n1, &n2);
-	} else {
-		regalloc(&n1, types[TUINT32], &nodes[1]);
-		gmove(&nodes[1], &n1);
-		if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
-			gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
-		gmove(&n1, &n2);
-		regfree(&n1);
-	}
-
-	// if slice could be too big, dereference to
-	// catch nil array pointer.
-	if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
-		n2 = nodes[0];
-		n2.xoffset = 0;
-		n2.op = OINDREG;
-		n2.type = types[TUINT8];
-		regalloc(&n1, types[TUINT32], N);
-		gins(AMOVB, &n2, &n1);
-		regfree(&n1);
-	}
-
-	// ary = old[0] + (lb[2] * width[4]) (destroys old)
-	n2 = *res;
-	n2.type = types[tptr];
-	n2.xoffset += Array_array;
-
-	if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) {
-		v = mpgetfix(nodes[2].val.u.xval) *
-			mpgetfix(nodes[4].val.u.xval);
-		if(v != 0) {
-			nodconst(&n1, types[tptr], v);
-			gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
-		}
-	} else {
-		regalloc(&n1, types[tptr], &nodes[2]);
-		gmove(&nodes[2], &n1);
-		if(!smallintconst(&nodes[4]) || mpgetfix(nodes[4].val.u.xval) != 1) {
-			regalloc(&n3, types[tptr], N);
-			gmove(&nodes[4], &n3);
-			gins(optoas(OMUL, types[tptr]), &n3, &n1);
-			regfree(&n3);
-		}
-		gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
-		regfree(&n1);
-	}
-	gmove(&nodes[0], &n2);
-
-	for(i=0; i<5; i++) {
-		if(nodes[i].op == OREGISTER)
-			regfree(&nodes[i]);
-	}
-	return 1;
-
-sliceslice:
-	if(!fix64(n->list, narg))
-		goto no;
-	ntemp.op = OXXX;
-	if(!sleasy(n->list->n->right)) {
-		Node *n0;
-		
-		n0 = n->list->n->right;
-		tempname(&ntemp, res->type);
-		cgen(n0, &ntemp);
-		n->list->n->right = &ntemp;
-		getargs(n->list, nodes, narg);
-		n->list->n->right = n0;
-	} else
-		getargs(n->list, nodes, narg);
-
-	nres = *res;		// result
-	if(!sleasy(res)) {
-		if(ntemp.op == OXXX)
-			tempname(&ntemp, res->type);
-		nres = ntemp;
-	}
-
-	if(narg == 3) {	// old[lb:]
-		// move width to where it would be for old[lb:hb]
-		nodes[3] = nodes[2];
-		nodes[2].op = OXXX;
-		
-		// if(lb[1] > old.nel[0]) goto throw;
-		n2 = nodes[0];
-		n2.xoffset += Array_nel;
-		n2.type = types[TUINT32];
-		cmpandthrow(&nodes[1], &n2);
-
-		// ret.nel = old.nel[0]-lb[1];
-		n2 = nodes[0];
-		n2.type = types[TUINT32];
-		n2.xoffset += Array_nel;
-	
-		regalloc(&n1, types[TUINT32], N);
-		gmove(&n2, &n1);
-		if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
-			gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
-	
-		n2 = nres;
-		n2.type = types[TUINT32];
-		n2.xoffset += Array_nel;
-		gmove(&n1, &n2);
-		regfree(&n1);
-	} else {	// old[lb:hb]
-		// if(hb[2] > old.cap[0]) goto throw;
-		n2 = nodes[0];
-		n2.xoffset += Array_cap;
-		n2.type = types[TUINT32];
-		cmpandthrow(&nodes[2], &n2);
-
-		// if(lb[1] > hb[2]) goto throw;
-		cmpandthrow(&nodes[1], &nodes[2]);
-
-		// ret.len = hb[2]-lb[1]; (destroys hb[2])
-		n2 = nres;
-		n2.type = types[TUINT32];
-		n2.xoffset += Array_nel;
-	
-		if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) {
-			v = mpgetfix(nodes[2].val.u.xval) -
-				mpgetfix(nodes[1].val.u.xval);
-			nodconst(&n1, types[TUINT32], v);
-			gmove(&n1, &n2);
-		} else {
-			regalloc(&n1, types[TUINT32], &nodes[2]);
-			gmove(&nodes[2], &n1);
-			if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
-				gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
-			gmove(&n1, &n2);
-			regfree(&n1);
-		}
-	}
-
-	// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
-	n2 = nodes[0];
-	n2.type = types[TUINT32];
-	n2.xoffset += Array_cap;
-
-	regalloc(&n1, types[TUINT32], &nodes[2]);
-	gmove(&n2, &n1);
-	if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
-		gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
-
-	n2 = nres;
-	n2.type = types[TUINT32];
-	n2.xoffset += Array_cap;
-	gmove(&n1, &n2);
-	regfree(&n1);
-
-	// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
-	n2 = nodes[0];
-	n2.type = types[tptr];
-	n2.xoffset += Array_array;
-	regalloc(&n3, types[tptr], N);
-	gmove(&n2, &n3);
-
-	regalloc(&n1, types[tptr], &nodes[1]);
-	if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) {
-		gmove(&n2, &n1);
-		v = mpgetfix(nodes[1].val.u.xval) *
-			mpgetfix(nodes[3].val.u.xval);
-		if(v != 0) {
-			nodconst(&n2, types[tptr], v);
-			gins(optoas(OADD, types[tptr]), &n3, &n1);
-		}
-	} else {
-		gmove(&nodes[1], &n1);
-		if(!smallintconst(&nodes[3]) || mpgetfix(nodes[3].val.u.xval) != 1) {
-			regalloc(&n2, types[tptr], N);
-			gmove(&nodes[3], &n2);
-			gins(optoas(OMUL, types[tptr]), &n2, &n1);
-			regfree(&n2);
-		}
-		gins(optoas(OADD, types[tptr]), &n3, &n1);
-	}
-	regfree(&n3);
-
-	n2 = nres;
-	n2.type = types[tptr];
-	n2.xoffset += Array_array;
-	gmove(&n1, &n2);
-	regfree(&n1);
-
-	for(i=0; i<4; i++) {
-		if(nodes[i].op == OREGISTER)
-			regfree(&nodes[i]);
-	}
-
-	if(!sleasy(res)) {
-		cgen(&nres, res);
-	}
-	return 1;
-
-no:
-	return 0;
-}
diff --git a/src/cmd/5g/gobj.c b/src/cmd/5g/gobj.c
index 2763e7b..9c5fb2a 100644
--- a/src/cmd/5g/gobj.c
+++ b/src/cmd/5g/gobj.c
@@ -65,17 +65,17 @@ zhist(Biobuf *b, int line, vlong offset)
 	Bputc(b, line>>8);
 	Bputc(b, line>>16);
 	Bputc(b, line>>24);
-	zaddr(b, &zprog.from, 0);
+	zaddr(b, &zprog.from, 0, 0);
 	a = zprog.to;
 	if(offset != 0) {
 		a.offset = offset;
 		a.type = D_CONST;
 	}
-	zaddr(b, &a, 0);
+	zaddr(b, &a, 0, 0);
 }
 
 void
-zaddr(Biobuf *b, Addr *a, int s)
+zaddr(Biobuf *b, Addr *a, int s, int gotype)
 {
 	int32 l;
 	uint64 e;
@@ -95,6 +95,7 @@ zaddr(Biobuf *b, Addr *a, int s)
 		Bputc(b, a->reg);
 		Bputc(b, s);
 		Bputc(b, a->name);
+		Bputc(b, gotype);
 	}
 
 	switch(a->type) {
@@ -128,9 +129,9 @@ zaddr(Biobuf *b, Addr *a, int s)
 		break;
 
 	case D_BRANCH:
-		if(a->branch == nil)
+		if(a->u.branch == nil)
 			fatal("unpatched branch");
-		a->offset = a->branch->loc;
+		a->offset = a->u.branch->loc;
 		l = a->offset;
 		Bputc(b, l);
 		Bputc(b, l>>8);
@@ -139,7 +140,7 @@ zaddr(Biobuf *b, Addr *a, int s)
 		break;
 
 	case D_SCONST:
-		n = a->sval;
+		n = a->u.sval;
 		for(i=0; i<NSNAME; i++) {
 			Bputc(b, *n);
 			n++;
@@ -147,11 +148,12 @@ zaddr(Biobuf *b, Addr *a, int s)
 		break;
 
 	case D_REGREG:
+	case D_REGREG2:
 		Bputc(b, a->offset);
 		break;
 
 	case D_FCONST:
-		ieeedtod(&e, a->dval);
+		ieeedtod(&e, a->u.dval);
 		l = e;
 		Bputc(b, l);
 		Bputc(b, l>>8);
@@ -166,20 +168,66 @@ zaddr(Biobuf *b, Addr *a, int s)
 	}
 }
 
+static struct {
+	struct { Sym *sym; short type; } h[NSYM];
+	int sym;
+} z;
+
+static void
+zsymreset(void)
+{
+	for(z.sym=0; z.sym<NSYM; z.sym++) {
+		z.h[z.sym].sym = S;
+		z.h[z.sym].type = 0;
+	}
+	z.sym = 1;
+}
+
+static int
+zsym(Sym *s, int t, int *new)
+{
+	int i;
+
+	*new = 0;
+	if(s == S)
+		return 0;
+
+	i = s->sym;
+	if(i < 0 || i >= NSYM)
+		i = 0;
+	if(z.h[i].type == t && z.h[i].sym == s)
+		return i;
+	i = z.sym;
+	s->sym = i;
+	zname(bout, s, t);
+	z.h[i].sym = s;
+	z.h[i].type = t;
+	if(++z.sym >= NSYM)
+		z.sym = 1;
+	*new = 1;
+	return i;
+}
+
+static int
+zsymaddr(Addr *a, int *new)
+{
+	int t;
+
+	t = a->name;
+	if(t == D_ADDR)
+		t = a->name;
+	return zsym(a->sym, t, new);
+}
+
 void
 dumpfuncs(void)
 {
 	Plist *pl;
-	int sf, st, t, sym;
-	struct { Sym *sym; short type; } h[NSYM];
+	int sf, st, gf, gt, new;
 	Sym *s;
 	Prog *p;
 
-	for(sym=0; sym<NSYM; sym++) {
-		h[sym].sym = S;
-		h[sym].type = 0;
-	}
-	sym = 1;
+	zsymreset();
 
 	// fix up pc
 	pcloc = 0;
@@ -209,53 +257,20 @@ dumpfuncs(void)
 		}
 
 		for(p=pl->firstpc; p!=P; p=p->link) {
-		jackpot:
-			sf = 0;
-			s = p->from.sym;
-			while(s != S) {
-				sf = s->sym;
-				if(sf < 0 || sf >= NSYM)
-					sf = 0;
-				t = p->from.name;
-				if(t == D_ADDR)
-					t = p->from.name;
-				if(h[sf].type == t)
-				if(h[sf].sym == s)
-					break;
-				s->sym = sym;
-				zname(bout, s, t);
-				h[sym].sym = s;
-				h[sym].type = t;
-				sf = sym;
-				sym++;
-				if(sym >= NSYM)
-					sym = 1;
-				break;
-			}
-			st = 0;
-			s = p->to.sym;
-			while(s != S) {
-				st = s->sym;
-				if(st < 0 || st >= NSYM)
-					st = 0;
-				t = p->to.name;
-				if(t == D_ADDR)
-					t = p->to.name;
-				if(h[st].type == t)
-				if(h[st].sym == s)
-					break;
-				s->sym = sym;
-				zname(bout, s, t);
-				h[sym].sym = s;
-				h[sym].type = t;
-				st = sym;
-				sym++;
-				if(sym >= NSYM)
-					sym = 1;
-				if(st == sf)
-					goto jackpot;
+			for(;;) {
+				sf = zsymaddr(&p->from, &new);
+				gf = zsym(p->from.gotype, D_EXTERN, &new);
+				if(new && sf == gf)
+					continue;
+				st = zsymaddr(&p->to, &new);
+				if(new && (st == sf || st == gf))
+					continue;
+				gt = zsym(p->to.gotype, D_EXTERN, &new);
+				if(new && (gt == sf || gt == gf || gt == st))
+					continue;
 				break;
 			}
+
 			Bputc(bout, p->as);
 			Bputc(bout, p->scond);
  			Bputc(bout, p->reg);
@@ -263,8 +278,8 @@ dumpfuncs(void)
 			Bputc(bout, p->lineno>>8);
 			Bputc(bout, p->lineno>>16);
 			Bputc(bout, p->lineno>>24);
-			zaddr(bout, &p->from, sf);
-			zaddr(bout, &p->to, st);
+			zaddr(bout, &p->from, sf, gf);
+			zaddr(bout, &p->to, st, gt);
 		}
 	}
 }
@@ -288,7 +303,7 @@ dsname(Sym *sym, int off, char *t, int n)
 	p->to.name = D_NONE;
 	p->to.reg = NREG;
 	p->to.offset = 0;
-	memmove(p->to.sval, t, n);
+	memmove(p->to.u.sval, t, n);
 	return off + n;
 }
 
@@ -372,13 +387,13 @@ gdatacomplex(Node *nam, Mpcplx *cval)
 	p = gins(ADATA, nam, N);
 	p->reg = w;
 	p->to.type = D_FCONST;
-	p->to.dval = mpgetflt(&cval->real);
+	p->to.u.dval = mpgetflt(&cval->real);
 
 	p = gins(ADATA, nam, N);
 	p->reg = w;
 	p->from.offset += w;
 	p->to.type = D_FCONST;
-	p->to.dval = mpgetflt(&cval->imag);
+	p->to.u.dval = mpgetflt(&cval->imag);
 }
 
 void
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index 9acf936..191c755 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -108,17 +108,22 @@ dumpdata(void)
 /*
  * generate a branch.
  * t is ignored.
+ * likely values are for branch prediction:
+ *	-1 unlikely
+ *	0 no opinion
+ *	+1 likely
  */
 Prog*
-gbranch(int as, Type *t)
+gbranch(int as, Type *t, int likely)
 {
 	Prog *p;
 
 	USED(t);
+	USED(likely);  // TODO: record this for linker
 
 	p = prog(as);
 	p->to.type = D_BRANCH;
-	p->to.branch = P;
+	p->to.u.branch = P;
 	return p;
 }
 
@@ -130,7 +135,7 @@ patch(Prog *p, Prog *to)
 {
 	if(p->to.type != D_BRANCH)
 		fatal("patch: not a branch");
-	p->to.branch = to;
+	p->to.u.branch = to;
 	p->to.offset = to->loc;
 }
 
@@ -141,8 +146,8 @@ unpatch(Prog *p)
 
 	if(p->to.type != D_BRANCH)
 		fatal("unpatch: not a branch");
-	q = p->to.branch;
-	p->to.branch = P;
+	q = p->to.u.branch;
+	p->to.u.branch = P;
 	p->to.offset = 0;
 	return q;
 }
@@ -170,64 +175,6 @@ newplist(void)
 }
 
 void
-clearstk(void)
-{
-	Plist *pl;
-	Prog *p, *p1, *p2, *p3;
-	Node dst, end, zero, con;
-
-	if(plast->firstpc->to.offset <= 0)
-		return;
-
-	// reestablish context for inserting code
-	// at beginning of function.
-	pl = plast;
-	p1 = pl->firstpc;
-	p2 = p1->link;
-	pc = mal(sizeof(*pc));
-	clearp(pc);
-	p1->link = pc;
-	
-	// zero stack frame
-
-	// MOVW $4(SP), R1
-	nodreg(&dst, types[tptr], 1);
-	p = gins(AMOVW, N, &dst);
-	p->from.type = D_CONST;
-	p->from.reg = REGSP;
-	p->from.offset = 4;
-
-	// MOVW $n(R1), R2
-	nodreg(&end, types[tptr], 2);
-	p = gins(AMOVW, N, &end);
-	p->from.type = D_CONST;
-	p->from.reg = 1;
-	p->from.offset = p1->to.offset;
-	
-	// MOVW $0, R3
-	nodreg(&zero, types[TUINT32], 3);
-	nodconst(&con, types[TUINT32], 0);
-	gmove(&con, &zero);
-
-	// L:
-	//	MOVW.P R3, 0(R1) +4
-	//	CMP R1, R2
-	//	BNE L
-	p = gins(AMOVW, &zero, &dst);
-	p->to.type = D_OREG;
-	p->to.offset = 4;
-	p->scond |= C_PBIT;
-	p3 = p;
-	p = gins(ACMP, &dst, N);
-	raddr(&end, p);
-	patch(gbranch(ABNE, T), p3);
-
-	// continue with original code.
-	gins(ANOP, N, N)->link = p2;
-	pc = P;
-}	
-
-void
 gused(Node *n)
 {
 	gins(ANOP, n, N);	// used
@@ -238,22 +185,23 @@ gjmp(Prog *to)
 {
 	Prog *p;
 
-	p = gbranch(AB, T);
+	p = gbranch(AB, T, 0);
 	if(to != P)
 		patch(p, to);
 	return p;
 }
 
 void
-ggloblnod(Node *nam, int32 width)
+ggloblnod(Node *nam)
 {
 	Prog *p;
 
 	p = gins(AGLOBL, nam, N);
 	p->lineno = nam->lineno;
+	p->from.gotype = ngotype(nam);
 	p->to.sym = S;
 	p->to.type = D_CONST;
-	p->to.offset = width;
+	p->to.offset = nam->type->width;
 	if(nam->readonly)
 		p->reg = RODATA;
 	if(nam->type != T && !haspointers(nam->type))
@@ -261,7 +209,7 @@ ggloblnod(Node *nam, int32 width)
 }
 
 void
-ggloblsym(Sym *s, int32 width, int dupok)
+ggloblsym(Sym *s, int32 width, int dupok, int rodata)
 {
 	Prog *p;
 
@@ -273,8 +221,20 @@ ggloblsym(Sym *s, int32 width, int dupok)
 	p->to.name = D_NONE;
 	p->to.offset = width;
 	if(dupok)
-		p->reg = DUPOK;
-	p->reg |= RODATA;
+		p->reg |= DUPOK;
+	if(rodata)
+		p->reg |= RODATA;
+}
+
+void
+gtrack(Sym *s)
+{
+	Prog *p;
+	
+	p = gins(AUSEFIELD, N, N);
+	p->from.type = D_OREG;
+	p->from.name = D_EXTERN;
+	p->from.sym = s;
 }
 
 int
@@ -298,17 +258,20 @@ isfat(Type *t)
  * also fix up direct register references to be D_OREG.
  */
 void
-afunclit(Addr *a)
+afunclit(Addr *a, Node *n)
 {
 	if(a->type == D_CONST && a->name == D_EXTERN || a->type == D_REG) {
 		a->type = D_OREG;
+		if(n->op == ONAME)
+			a->sym = n->sym;
 	}
 }
 
 static	int	resvd[] =
 {
-	9,	// reserved for m
-	10,	// reserved for g
+	9,     // reserved for m
+	10,    // reserved for g
+	REGSP, // reserved for SP
 };
 
 void
@@ -401,6 +364,7 @@ regalloc(Node *n, Type *t, Node *o)
 				regpc[i] = (uintptr)getcallerpc(&n);
 				goto out;
 			}
+		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");
@@ -452,15 +416,17 @@ regfree(Node *n)
 		print("regalloc fix %d float %d\n", fixfree, floatfree);
 	}
 
-	if(n->op == ONAME && iscomplex[n->type->etype])
+	if(n->op == ONAME)
 		return;
 	if(n->op != OREGISTER && n->op != OINDREG)
 		fatal("regfree: not a register");
 	i = n->val.u.reg;
+	if(i == REGSP)
+		return;
 	if(i < 0 || i >= nelem(reg) || i >= nelem(regpc))
 		fatal("regfree: reg out of range");
 	if(reg[i] <= 0)
-		fatal("regfree: reg not allocated");
+		fatal("regfree: reg %R not allocated", i);
 	reg[i]--;
 	if(reg[i] == 0)
 		regpc[i] = 0;
@@ -597,9 +563,9 @@ split64(Node *n, Node *lo, Node *hi)
 	if(!is64(n->type))
 		fatal("split64 %T", n->type);
 
-	sclean[nsclean].op = OEMPTY;
 	if(nsclean >= nelem(sclean))
 		fatal("split64 clean");
+	sclean[nsclean].op = OEMPTY;
 	nsclean++;
 	switch(n->op) {
 	default:
@@ -1155,7 +1121,7 @@ gcmp(int as, Node *lhs, Node *rhs)
 {
 	Prog *p;
 
-	if(lhs->op != OREGISTER || rhs->op != OREGISTER)
+	if(lhs->op != OREGISTER)
 		fatal("bad operands to gcmp: %O %O", lhs->op, rhs->op);
 
 	p = gins(as, rhs, N);
@@ -1194,6 +1160,27 @@ gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs)
 	return p;
 }
 
+// Generate an instruction referencing *n
+// to force segv on nil pointer dereference.
+void
+checkref(Node *n)
+{
+	Node m1, m2;
+
+	if(n->type->type->width < unmappedzero)
+		return;
+
+	regalloc(&m1, types[TUINTPTR], n);
+	regalloc(&m2, types[TUINT8], n);
+	cgen(n, &m1);
+	m1.xoffset = 0;
+	m1.op = OINDREG;
+	m1.type = types[TUINT8];
+	gins(AMOVBU, &m1, &m2);
+	regfree(&m2);
+	regfree(&m1);
+}
+
 static void
 checkoffset(Addr *a, int canemitcode)
 {
@@ -1209,7 +1196,7 @@ checkoffset(Addr *a, int canemitcode)
 	// reference with large offset.  instead, emit explicit
 	// test of 0(reg).
 	regalloc(&n1, types[TUINTPTR], N);
-	p = gins(AMOVW, N, &n1);
+	p = gins(AMOVB, N, &n1);
 	p->from = *a;
 	p->from.offset = 0;
 	regfree(&n1);
@@ -1222,14 +1209,22 @@ checkoffset(Addr *a, int canemitcode)
 void
 naddr(Node *n, Addr *a, int canemitcode)
 {
+	Prog *p;
+
 	a->type = D_NONE;
 	a->name = D_NONE;
 	a->reg = NREG;
+	a->gotype = S;
 	a->node = N;
 	a->etype = 0;
 	if(n == N)
 		return;
 
+	if(n->type != T && n->type->etype != TIDEAL) {
+		dowidth(n->type);
+		a->width = n->type->width;
+	}
+
 	switch(n->op) {
 	default:
 		fatal("naddr: bad %O %D", n->op, a);
@@ -1286,6 +1281,25 @@ naddr(Node *n, Addr *a, int canemitcode)
 		a->name = D_PARAM;
 		a->node = n->left->orig;
 		break;
+	
+	case OCLOSUREVAR:
+		if(!canemitcode)
+			fatal("naddr OCLOSUREVAR cannot emit code");
+		p = gins(AMOVW, N, N);
+		p->from.type = D_OREG;
+		p->from.reg = 7;
+		p->from.offset = n->xoffset;
+		p->to.type = D_REG;
+		p->to.reg = 1;
+		a->type = D_REG;
+		a->reg = 1;
+		a->sym = S;
+		break;		
+
+	case OCFUNC:
+		naddr(n->left, a, canemitcode);
+		a->sym = n->left->sym;
+		break;
 
 	case ONAME:
 		a->etype = 0;
@@ -1326,6 +1340,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 		case PFUNC:
 			a->name = D_EXTERN;
 			a->type = D_CONST;
+			a->sym = funcsym(a->sym);
 			break;
 		}
 		break;
@@ -1337,7 +1352,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 			break;
 		case CTFLT:
 			a->type = D_FCONST;
-			a->dval = mpgetflt(n->val.u.fval);
+			a->u.dval = mpgetflt(n->val.u.fval);
 			break;
 		case CTINT:
 		case CTRUNE:
@@ -1409,6 +1424,9 @@ naddr(Node *n, Addr *a, int canemitcode)
 			fatal("naddr: OADDR %d\n", a->type);
 		}
 	}
+	
+	if(a->width < 0)
+		fatal("naddr: bad width for %N -> %D", n, a);
 }
 
 /*
@@ -1619,6 +1637,16 @@ optoas(int op, Type *t)
 		a = ASUBD;
 		break;
 
+	case CASE(OMINUS, TINT8):
+	case CASE(OMINUS, TUINT8):
+	case CASE(OMINUS, TINT16):
+	case CASE(OMINUS, TUINT16):
+	case CASE(OMINUS, TINT32):
+	case CASE(OMINUS, TUINT32):
+	case CASE(OMINUS, TPTR32):
+		a = ARSB;
+		break;
+
 	case CASE(OAND, TINT8):
 	case CASE(OAND, TUINT8):
 	case CASE(OAND, TINT16):
@@ -1825,6 +1853,9 @@ sudoaddable(int as, Node *n, Addr *a, int *w)
 		goto odot;
 
 	case OINDEX:
+		return 0;
+		// disabled: OINDEX case is now covered by agenr
+		// for a more suitable register allocation pattern.
 		if(n->left->type->etype == TSTRING)
 			return 0;
 		cleani += 2;
@@ -1942,7 +1973,7 @@ oindex:
 		t = types[TINT32];
 	regalloc(reg1, t, N);
 	regalloc(&n3, types[TINT32], reg1);
-	p2 = cgenindex(r, &n3);
+	p2 = cgenindex(r, &n3, debug['B'] || n->bounded);
 	gmove(&n3, reg1);
 	regfree(&n3);
 
@@ -1982,7 +2013,7 @@ oindex:
 		cgen(&n2, &n3);
 		gcmp(optoas(OCMP, types[TUINT32]), reg1, &n3);
 		regfree(&n3);
-		p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+		p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
 		if(p2)
 			patch(p2, pc);
 		ginscall(panicindex, 0);
@@ -2032,7 +2063,7 @@ oindex_const:
 	v = mpgetfix(r->val.u.xval);
 	if(o & ODynam) {
 
-		if(!debug['B'] && !n->etype) {
+		if(!debug['B'] && !n->bounded) {
 			n1 = *reg;
 			n1.op = OINDREG;
 			n1.type = types[tptr];
@@ -2045,7 +2076,7 @@ oindex_const:
 			gcmp(optoas(OCMP, types[TUINT32]), &n4, &n3);
 			regfree(&n4);
 			regfree(&n3);
-			p1 = gbranch(optoas(OGT, types[TUINT32]), T);
+			p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
 			ginscall(panicindex, 0);
 			patch(p1, pc);
 		}
diff --git a/src/cmd/5g/list.c b/src/cmd/5g/list.c
index f0da247..6c3f1d7 100644
--- a/src/cmd/5g/list.c
+++ b/src/cmd/5g/list.c
@@ -153,6 +153,12 @@ Dconv(Fmt *fp)
 			sprint(str, "%M(R%d)(REG)", a, a->reg);
 		break;
 
+	case D_REGREG2:
+		sprint(str, "R%d,R%d", a->reg, (int)a->offset);
+		if(a->name != D_NONE || a->sym != S)
+			sprint(str, "%M(R%d)(REG)", a, a->reg);
+		break;
+
 	case D_FREG:
 		sprint(str, "F%d", a->reg);
 		if(a->name != D_NONE || a->sym != S)
@@ -160,24 +166,24 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_BRANCH:
-		if(a->branch == P || a->branch->loc == 0) {
+		if(a->u.branch == P || a->u.branch->loc == 0) {
 			if(a->sym != S)
 				sprint(str, "%s+%d(APC)", a->sym->name, a->offset);
 			else
 				sprint(str, "%d(APC)", a->offset);
 		} else
 			if(a->sym != S)
-				sprint(str, "%s+%d(APC)", a->sym->name, a->branch->loc);
+				sprint(str, "%s+%d(APC)", a->sym->name, a->u.branch->loc);
 			else
-				sprint(str, "%d(APC)", a->branch->loc);
+				sprint(str, "%d(APC)", a->u.branch->loc);
 		break;
 
 	case D_FCONST:
-		snprint(str, sizeof(str), "$(%.17e)", a->dval);
+		snprint(str, sizeof(str), "$(%.17e)", a->u.dval);
 		break;
 
 	case D_SCONST:
-		snprint(str, sizeof(str), "$\"%Y\"", a->sval);
+		snprint(str, sizeof(str), "$\"%Y\"", a->u.sval);
 		break;
 
 		// TODO(kaib): Add back
@@ -190,7 +196,10 @@ Dconv(Fmt *fp)
 //		goto conv;
 	}
 conv:
-	return fmtstrcpy(fp, str);
+	fmtstrcpy(fp, str);
+	if(a->gotype)
+		fmtprint(fp, "{%s}", a->gotype->name);
+	return 0;
 }
 
 int
diff --git a/src/cmd/5g/opt.h b/src/cmd/5g/opt.h
index 7a0070f..af7d654 100644
--- a/src/cmd/5g/opt.h
+++ b/src/cmd/5g/opt.h
@@ -34,8 +34,6 @@
 #define	D_HI	D_NONE
 #define	D_LO	D_NONE
 
-#define	isregtype(t)	((t)>= D_AX && (t)<=D_R15)
-
 #define	BLOAD(r)	band(bnot(r->refbehind), r->refahead)
 #define	BSTORE(r)	band(bnot(r->calbehind), r->calahead)
 #define	LOAD(r)		(~r->refbehind.b[z] & r->refahead.b[z])
@@ -49,12 +47,16 @@
 typedef	struct	Reg	Reg;
 typedef	struct	Rgn	Rgn;
 
+// 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.
+// r->prog->regp points back to r.
 struct	Reg
 {
 
-	Bits	set;
-	Bits	use1;
-	Bits	use2;
+	Bits	set;  		// variables written by this instruction.
+	Bits	use1; 		// variables read by prog->from.
+	Bits	use2; 		// variables read by prog->to.
 
 	Bits	refbehind;
 	Bits	refahead;
@@ -70,13 +72,13 @@ struct	Reg
 	uint16	loop;		// x5 for every loop
 	uchar	refset;		// diagnostic generated
 
-	Reg*	p1;
-	Reg*	p2;
+	Reg*	p1;     	// predecessors of this instruction: p1,
+	Reg*	p2;     	// and then p2 linked though p2link.
 	Reg*	p2link;
-	Reg*	s1;
+	Reg*	s1;     	// successors of this instruction (at most two: s1 and s2).
 	Reg*	s2;
-	Reg*	link;
-	Prog*	prog;
+	Reg*	link;   	// next instruction in function code
+	Prog*	prog;   	// actual instruction
 };
 #define	R	((Reg*)0)
 
diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c
index e87f5d6..b6202a8 100644
--- a/src/cmd/5g/peep.c
+++ b/src/cmd/5g/peep.c
@@ -1,5 +1,5 @@
 // Inferno utils/5c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5g/peep.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5c/peep.c
 //
 //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
 //	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
@@ -49,7 +49,6 @@ peep(void)
 	int t;
 
 	p1 = nil;
-	USED(p1);		// ... in unreachable code...
 /*
  * complete R structure
  */
@@ -77,6 +76,8 @@ peep(void)
 		case AGLOBL:
 		case ANAME:
 		case ASIGNAME:
+		case ALOCALS:
+		case ATYPE:
 			p = p->link;
 		}
 	}
@@ -120,7 +121,7 @@ loop1:
 			}
 			break;
 
-#ifdef	NOTDEF
+#ifdef NOTDEF
 			if(p->scond == C_SCOND_NONE)
 			if(regtyp(&p->to))
 			if(isdconst(&p->from)) {
@@ -133,26 +134,24 @@ loop1:
 	if(t)
 		goto loop1;
 
-return;
 
-#ifdef	NOTDEF
 	for(r=firstr; r!=R; r=r->link) {
 		p = r->prog;
 		switch(p->as) {
-//		case AEOR:
-//			/*
-//			 * EOR -1,x,y => MVN x,y
-//			 */
-//			if(isdconst(&p->from) && p->from.offset == -1) {
-//				p->as = AMVN;
-//				p->from.type = D_REG;
-//				if(p->reg != NREG)
-//					p->from.reg = p->reg;
-//				else
-//					p->from.reg = p->to.reg;
-//				p->reg = NREG;
-//			}
-//			break;
+		case AEOR:
+			/*
+			 * EOR -1,x,y => MVN x,y
+			 */
+			if(isdconst(&p->from) && p->from.offset == -1) {
+				p->as = AMVN;
+				p->from.type = D_REG;
+				if(p->reg != NREG)
+					p->from.reg = p->reg;
+				else
+					p->from.reg = p->to.reg;
+				p->reg = NREG;
+			}
+			break;
 
 		case AMOVH:
 		case AMOVHU:
@@ -161,6 +160,7 @@ return;
 			/*
 			 * look for MOVB x,R; MOVB R,R
 			 */
+			r1 = r->link;
 			if(p->to.type != D_REG)
 				break;
 			if(r1 == R)
@@ -175,23 +175,22 @@ return;
 			excise(r1);
 			break;
 		}
-		r1 = r->link;
 	}
 
-//	for(r=firstr; r!=R; r=r->link) {
-//		p = r->prog;
-//		switch(p->as) {
-//		case AMOVW:
-//		case AMOVB:
-//		case AMOVBU:
-//			if(p->from.type == D_OREG && p->from.offset == 0)
-//				xtramodes(r, &p->from);
-//			else
-//			if(p->to.type == D_OREG && p->to.offset == 0)
-//				xtramodes(r, &p->to);
-//			else
-//				continue;
-//			break;
+	for(r=firstr; r!=R; r=r->link) {
+		p = r->prog;
+		switch(p->as) {
+		case AMOVW:
+		case AMOVB:
+		case AMOVBU:
+			if(p->from.type == D_OREG && p->from.offset == 0)
+				xtramodes(r, &p->from);
+			else
+			if(p->to.type == D_OREG && p->to.offset == 0)
+				xtramodes(r, &p->to);
+			else
+				continue;
+			break;
 //		case ACMP:
 //			/*
 //			 * elide CMP $0,x if calculation of x can set condition codes
@@ -259,13 +258,17 @@ return;
 //			r2->prog->as = t;
 //			excise(r);
 //			continue;
-//		}
-//	}
+		}
+	}
 
-	predicate();
-#endif
+//	predicate();
 }
 
+/*
+ * uniqp returns a "unique" predecessor to instruction r.
+ * If the instruction is the first one or has multiple
+ * predecessors due to jump, R is returned.
+ */
 Reg*
 uniqp(Reg *r)
 {
@@ -738,6 +741,11 @@ shiftprop(Reg *r)
 	return 1;
 }
 
+/*
+ * findpre returns the last instruction mentioning v
+ * before r. It must be a set, and there must be
+ * a unique path from that instruction to r.
+ */
 Reg*
 findpre(Reg *r, Adr *v)
 {
@@ -758,6 +766,10 @@ findpre(Reg *r, Adr *v)
 	return R;
 }
 
+/*
+ * findinc finds ADD instructions with a constant
+ * argument which falls within the immed_12 range.
+ */
 Reg*
 findinc(Reg *r, Reg *r2, Adr *v)
 {
@@ -848,6 +860,19 @@ finduse(Reg *r, Adr *v)
 	return findu1(r, v);
 }
 
+/*
+ * xtramodes enables the ARM post increment and
+ * shift offset addressing modes to transform
+ *   MOVW   0(R3),R1
+ *   ADD    $4,R3,R3
+ * into
+ *   MOVW.P 4(R3),R1
+ * and 
+ *   ADD    R0,R1
+ *   MOVBU  0(R1),R0
+ * into 
+ *   MOVBU  R0<<0(R1),R0
+ */
 int
 xtramodes(Reg *r, Adr *a)
 {
@@ -856,8 +881,6 @@ xtramodes(Reg *r, Adr *a)
 	Adr v;
 
 	p = r->prog;
-	if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG)	/* byte load */
-		return 0;
 	v = *a;
 	v.type = D_REG;
 	r1 = findpre(r, &v);
@@ -866,6 +889,9 @@ xtramodes(Reg *r, Adr *a)
 		if(p1->to.type == D_REG && p1->to.reg == v.reg)
 		switch(p1->as) {
 		case AADD:
+			if(p1->scond & C_SBIT)
+				// avoid altering ADD.S/ADC sequences.
+				break;
 			if(p1->from.type == D_REG ||
 			   (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
 			    (p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
@@ -1032,6 +1058,7 @@ copyu(Prog *p, Adr *v, Adr *s)
 		return 0;
 
 	case AMULLU:	/* read, read, write, write */
+	case AMULL:
 	case AMULA:
 	case AMVN:
 		return 2;
@@ -1135,12 +1162,9 @@ copyu(Prog *p, Adr *v, Adr *s)
 		return 0;
 
 	case ARET:	/* funny */
-		if(v->type == D_REG)
-		if(v->reg == REGRET)
-			return 2;
-		if(v->type == D_FREG)
-		if(v->reg == FREGRET)
-			return 2;
+		if(s != A)
+			return 1;
+		return 3;
 
 	case ABL:	/* funny */
 		if(v->type == D_REG) {
@@ -1152,6 +1176,8 @@ copyu(Prog *p, Adr *v, Adr *s)
 		if(v->type == D_FREG)
 			if(v->reg <= FREGEXT && v->reg > exfregoffset)
 				return 2;
+		if(p->from.type == D_REG && v->type == D_REG && p->from.reg == v->reg)
+			return 2;
 
 		if(s != A) {
 			if(copysub(&p->to, v, s, 1))
@@ -1167,6 +1193,9 @@ copyu(Prog *p, Adr *v, Adr *s)
 			if(v->reg == (uchar)REGARG)
 				return 3;
 		return 0;
+
+	case ALOCALS:	/* funny */
+		return 0;
 	}
 }
 
@@ -1213,7 +1242,7 @@ copyau(Adr *a, Adr *v)
 			if(a->reg == v->reg)
 				return 1;
 		} else
-		if(a->type == D_REGREG) {
+		if(a->type == D_REGREG || a->type == D_REGREG2) {
 			if(a->reg == v->reg)
 				return 1;
 			if(a->offset == v->reg)
@@ -1276,7 +1305,7 @@ copysub(Adr *a, Adr *v, Adr *s, int f)
 			if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
 				a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
 		} else
-		if(a->type == D_REGREG) {
+		if(a->type == D_REGREG || a->type == D_REGREG2) {
 			if(a->offset == v->reg)
 				a->offset = s->reg;
 			if(a->reg == v->reg)
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 3932669..eaaaf9b 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -1,5 +1,5 @@
 // Inferno utils/5c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5g/reg.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5c/reg.c
 //
 //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
 //	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
@@ -34,8 +34,8 @@
 #include "gg.h"
 #include "opt.h"
 
-#define	NREGVAR	24
-#define	REGBITS	((uint32)0xffffff)
+#define	NREGVAR	32
+#define	REGBITS	((uint32)0xffffffff)
 #define	P2R(p)	(Reg*)(p->reg)
 
 	void	addsplits(void);
@@ -95,7 +95,7 @@ setoutvar(void)
 			ovar.b[z] |= bit.b[z];
 		t = structnext(&save);
 	}
-//if(bany(ovar))
+//if(bany(&ovar))
 //print("ovar = %Q\n", ovar);
 }
 
@@ -160,8 +160,18 @@ static char* regname[] = {
 	".F5",
 	".F6",
 	".F7",
+	".F8",
+	".F9",
+	".F10",
+	".F11",
+	".F12",
+	".F13",
+	".F14",
+	".F15",
 };
 
+static Node* regnodes[NREGVAR];
+
 void
 regopt(Prog *firstp)
 {
@@ -197,7 +207,6 @@ regopt(Prog *firstp)
 		return;
 	}
 
-	r1 = R;
 	firstr = R;
 	lastr = R;
 
@@ -208,8 +217,11 @@ regopt(Prog *firstp)
 	 */
 	nvar = NREGVAR;
 	memset(var, 0, NREGVAR*sizeof var[0]);
-	for(i=0; i<NREGVAR; i++)
-		var[i].node = newname(lookup(regname[i]));
+	for(i=0; i<NREGVAR; i++) {
+		if(regnodes[i] == N)
+			regnodes[i] = newname(lookup(regname[i]));
+		var[i].node = regnodes[i];
+	}
 
 	regbits = RtoB(REGSP)|RtoB(REGLINK)|RtoB(REGPC);
 	for(z=0; z<BITS; z++) {
@@ -236,6 +248,8 @@ regopt(Prog *firstp)
 		case AGLOBL:
 		case ANAME:
 		case ASIGNAME:
+		case ALOCALS:
+		case ATYPE:
 			continue;
 		}
 		r = rega();
@@ -263,6 +277,10 @@ regopt(Prog *firstp)
 			}
 		}
 
+		// Avoid making variables for direct-called functions.
+		if(p->as == ABL && p->to.type == D_EXTERN)
+			continue;
+
 		/*
 		 * left side always read
 		 */
@@ -408,10 +426,14 @@ regopt(Prog *firstp)
 				addrs.b[z] |= bit.b[z];
 		}
 
-//		print("bit=%2d addr=%d et=%-6E w=%-2d s=%S + %lld\n",
-//			i, v->addr, v->etype, v->width, v->sym, v->offset);
+		if(debug['R'] && debug['v'])
+			print("bit=%2d addr=%d et=%-6E w=%-2d s=%N + %lld\n",
+				i, v->addr, v->etype, v->width, v->node, v->offset);
 	}
 
+	if(debug['R'] && debug['v'])
+		dumpit("pass1", firstr);
+
 	/*
 	 * pass 2
 	 * turn branch references to pointers
@@ -420,9 +442,9 @@ regopt(Prog *firstp)
 	for(r=firstr; r!=R; r=r->link) {
 		p = r->prog;
 		if(p->to.type == D_BRANCH) {
-			if(p->to.branch == P)
+			if(p->to.u.branch == P)
 				fatal("pnil %P", p);
-			r1 = p->to.branch->regp;
+			r1 = p->to.u.branch->regp;
 			if(r1 == R)
 				fatal("rnil %P", p);
 			if(r1 == r) {
@@ -440,6 +462,9 @@ regopt(Prog *firstp)
 		print("	addr = %Q\n", addrs);
 	}
 
+	if(debug['R'] && debug['v'])
+		dumpit("pass2", firstr);
+
 	/*
 	 * pass 2.5
 	 * find looping structure
@@ -449,6 +474,9 @@ regopt(Prog *firstp)
 	change = 0;
 	loopit(firstr, nr);
 
+	if(debug['R'] && debug['v'])
+		dumpit("pass2.5", firstr);
+
 	/*
 	 * pass 3
 	 * iterate propagating usage
@@ -476,6 +504,9 @@ loop11:
 	if(change)
 		goto loop1;
 
+	if(debug['R'] && debug['v'])
+		dumpit("pass3", firstr);
+
 
 	/*
 	 * pass 4
@@ -492,6 +523,9 @@ loop2:
 
 	addsplits();
 
+	if(debug['R'] && debug['v'])
+		dumpit("pass4", firstr);
+
 	if(debug['R'] > 1) {
 		print("\nprop structure:\n");
 		for(r = firstr; r != R; r = r->link) {
@@ -543,6 +577,9 @@ loop2:
 		r->act.b[0] &= ~REGBITS;
 	}
 
+	if(debug['R'] && debug['v'])
+		dumpit("pass4.5", firstr);
+
 	/*
 	 * pass 5
 	 * isolate regions
@@ -605,6 +642,9 @@ loop2:
 brk:
 	qsort(region, nregion, sizeof(region[0]), rcmp);
 
+	if(debug['R'] && debug['v'])
+		dumpit("pass5", firstr);
+
 	/*
 	 * pass 6
 	 * determine used registers (paint2)
@@ -633,6 +673,10 @@ brk:
 			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
 		rgp++;
 	}
+
+	if(debug['R'] && debug['v'])
+		dumpit("pass6", firstr);
+
 	/*
 	 * pass 7
 	 * peep-hole on basic block
@@ -641,6 +685,9 @@ brk:
 		peep();
 	}
 
+	if(debug['R'] && debug['v'])
+		dumpit("pass7", firstr);
+
 	/*
 	 * last pass
 	 * eliminate nops
@@ -662,8 +709,8 @@ brk:
 		while(p->link != P && p->link->as == ANOP)
 			p->link = p->link->link;
 		if(p->to.type == D_BRANCH)
-			while(p->to.branch != P && p->to.branch->as == ANOP)
-				p->to.branch = p->to.branch->link;
+			while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
+				p->to.u.branch = p->to.u.branch->link;
 		if(p->as == AMOVW && p->to.reg == 13) {
 			if(p->scond & C_WBIT) {
 				vreg = -p->to.offset;		// in adjust region
@@ -866,6 +913,7 @@ mkvar(Reg *r, Adr *a)
 		goto onereg;
 
 	case D_REGREG:
+	case D_REGREG2:
 		bit = zbits;
 		if(a->offset != NREG)
 			bit.b[0] |= RtoB(a->offset);
@@ -926,6 +974,8 @@ mkvar(Reg *r, Adr *a)
 	et = a->etype;
 	o = a->offset;
 	w = a->width;
+	if(w < 0)
+		fatal("bad width %d for %D", w, a);
 
 	for(i=0; i<nvar; i++) {
 		v = var+i;
@@ -947,8 +997,6 @@ mkvar(Reg *r, Adr *a)
 	switch(et) {
 	case 0:
 	case TFUNC:
-	case TARRAY:
-	case TSTRING:
 		goto none;
 	}
 
@@ -964,14 +1012,13 @@ mkvar(Reg *r, Adr *a)
 	v = var+i;
 	v->offset = o;
 	v->name = n;
-//	v->gotype = a->gotype;
 	v->etype = et;
 	v->width = w;
 	v->addr = flag;		// funny punning
 	v->node = node;
 	
 	if(debug['R'])
-		print("bit=%2d et=%2d w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
+		print("bit=%2d et=%2E w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
 
 	bit = blsh(i);
 	if(n == D_EXTERN || n == D_STATIC)
@@ -1033,8 +1080,12 @@ prop(Reg *r, Bits ref, Bits cal)
 		default:
 			// Work around for issue 1304:
 			// flush modified globals before each instruction.
-			for(z=0; z<BITS; z++)
+			for(z=0; z<BITS; z++) {
 				cal.b[z] |= externs.b[z];
+				// issue 4066: flush modified return variables in case of panic
+				if(hasdefer)
+					cal.b[z] |= ovar.b[z];
+			}
 			break;
 		}
 		for(z=0; z<BITS; z++) {
@@ -1486,11 +1537,12 @@ addreg(Adr *a, int rn)
  *	1	R1
  *	...	...
  *	10	R10
+ *	12  R12
  */
 int32
 RtoB(int r)
 {
-	if(r >= REGTMP-2)	// excluded R9 and R10 for m and g
+	if(r >= REGTMP-2 && r != 12)	// excluded R9 and R10 for m and g, but not R12
 		return 0;
 	return 1L << r;
 }
@@ -1498,7 +1550,7 @@ RtoB(int r)
 int
 BtoR(int32 b)
 {
-	b &= 0x01fcL;	// excluded R9 and R10 for m and g
+	b &= 0x11fcL;	// excluded R9 and R10 for m and g, but not R12
 	if(b == 0)
 		return 0;
 	return bitno(b);
@@ -1509,7 +1561,7 @@ BtoR(int32 b)
  *	18	F2
  *	19	F3
  *	...	...
- *	23	F7
+ *	31	F15
  */
 int32
 FtoB(int f)
@@ -1524,7 +1576,7 @@ int
 BtoF(int32 b)
 {
 
-	b &= 0xfc0000L;
+	b &= 0xfffc0000L;
 	if(b == 0)
 		return 0;
 	return bitno(b) - 16;
@@ -1643,7 +1695,7 @@ chasejmp(Prog *p, int *jmploop)
 			*jmploop = 1;
 			break;
 		}
-		p = p->to.branch;
+		p = p->to.u.branch;
 	}
 	return p;
 }
@@ -1665,8 +1717,8 @@ mark(Prog *firstp)
 		if(p->regp != dead)
 			break;
 		p->regp = alive;
-		if(p->as != ABL && p->to.type == D_BRANCH && p->to.branch)
-			mark(p->to.branch);
+		if(p->as != ABL && p->to.type == D_BRANCH && p->to.u.branch)
+			mark(p->to.u.branch);
 		if(p->as == AB || p->as == ARET || (p->as == ABL && noreturn(p)))
 			break;
 	}
@@ -1686,8 +1738,8 @@ fixjmp(Prog *firstp)
 	for(p=firstp; p; p=p->link) {
 		if(debug['R'] && debug['v'])
 			print("%P\n", p);
-		if(p->as != ABL && p->to.type == D_BRANCH && p->to.branch && p->to.branch->as == AB) {
-			p->to.branch = chasejmp(p->to.branch, &jmploop);
+		if(p->as != ABL && p->to.type == D_BRANCH && p->to.u.branch && p->to.u.branch->as == AB) {
+			p->to.u.branch = chasejmp(p->to.u.branch, &jmploop);
 			if(debug['R'] && debug['v'])
 				print("->%P\n", p);
 		}
@@ -1695,7 +1747,7 @@ fixjmp(Prog *firstp)
 	}
 	if(debug['R'] && debug['v'])
 		print("\n");
-
+	
 	// pass 2: mark all reachable code alive
 	mark(firstp);
 	
@@ -1723,7 +1775,7 @@ fixjmp(Prog *firstp)
 	if(!jmploop) {
 		last = nil;
 		for(p=firstp; p; p=p->link) {
-			if(p->as == AB && p->to.type == D_BRANCH && p->to.branch == p->link) {
+			if(p->as == AB && p->to.type == D_BRANCH && p->to.u.branch == p->link) {
 				if(debug['R'] && debug['v'])
 					print("del %P\n", p);
 				continue;
diff --git a/src/cmd/5l/5.out.h b/src/cmd/5l/5.out.h
index 569536e..4aef8a2 100644
--- a/src/cmd/5l/5.out.h
+++ b/src/cmd/5l/5.out.h
@@ -49,12 +49,11 @@
 #define REGM        (REGEXT-1)
 /* compiler allocates external registers R10 down */
 #define	REGTMP		11
-#define	REGSB		12
 #define	REGSP		13
 #define	REGLINK		14
 #define	REGPC		15
 
-#define	NFREG		8
+#define	NFREG		16
 #define	FREGRET		0
 #define	FREGEXT		7
 #define	FREGTMP		15
@@ -127,6 +126,8 @@ enum	as
 	ADIVD,
 	ASQRTF,
 	ASQRTD,
+	AABSF,
+	AABSD,
 
 	ASRL,
 	ASRA,
@@ -184,6 +185,21 @@ enum	as
 	ALDREXD,
 	ASTREXD,
 
+	APLD,
+
+	AUNDEF,
+
+	ACLZ,
+
+	AMULWT,
+	AMULWB,
+	AMULAWT,
+	AMULAWB,
+	
+	AUSEFIELD,
+	ALOCALS,
+	ATYPE,
+
 	ALAST,
 };
 
@@ -237,12 +253,14 @@ enum	as
 
 #define	D_SHIFT		(D_NONE+19)
 #define	D_FPCR		(D_NONE+20)
-#define	D_REGREG	(D_NONE+21)
+#define	D_REGREG	(D_NONE+21) // (reg, reg)
 #define	D_ADDR		(D_NONE+22)
 
 #define	D_SBIG		(D_NONE+23)
 #define	D_CONST2	(D_NONE+24)
 
+#define	D_REGREG2	(D_NONE+25) // reg, reg
+
 /* name */
 #define	D_EXTERN	(D_NONE+3)
 #define	D_STATIC	(D_NONE+4)
@@ -252,11 +270,16 @@ enum	as
 /* internal only */
 #define	D_SIZE		(D_NONE+40)
 #define	D_PCREL		(D_NONE+41)
+#define	D_GOTOFF	(D_NONE+42) // R_ARM_GOTOFF
+#define	D_PLT0		(D_NONE+43) // R_ARM_PLT32, 1st inst: add ip, pc, #0xNN00000
+#define	D_PLT1		(D_NONE+44) // R_ARM_PLT32, 2nd inst: add ip, ip, #0xNN000
+#define	D_PLT2		(D_NONE+45) // R_ARM_PLT32, 3rd inst: ldr pc, [ip, #0xNNN]!
+#define	D_CALL		(D_NONE+46) // R_ARM_PLT32/R_ARM_CALL/R_ARM_JUMP24, bl xxxxx or b yyyyy
 
 /*
  * this is the ranlib header
  */
-#define	SYMDEF	"__.SYMDEF"
+#define	SYMDEF	"__.GOSYMDEF"
 
 /*
  * this is the simulated IEEE floating point
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index b36a982..04f2a9c 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -33,10 +33,14 @@
 #include	"l.h"
 #include	"../ld/lib.h"
 #include	"../ld/elf.h"
+#include	"../ld/dwarf.h"
 
 static Prog *PP;
 
-char linuxdynld[] = "/lib/ld-linux.so.2";
+char linuxdynld[] = "/lib/ld-linux.so.3"; // 2 for OABI, 3 for EABI
+char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
+char openbsddynld[] = "XXX";
+char netbsddynld[] = "/libexec/ld.elf_so";
 
 int32
 entryvalue(void)
@@ -55,32 +59,6 @@ entryvalue(void)
 	return s->value;
 }
 
-enum {
-	ElfStrEmpty,
-	ElfStrInterp,
-	ElfStrHash,
-	ElfStrGot,
-	ElfStrGotPlt,
-	ElfStrDynamic,
-	ElfStrDynsym,
-	ElfStrDynstr,
-	ElfStrRel,
-	ElfStrText,
-	ElfStrData,
-	ElfStrBss,
-	ElfStrSymtab,
-	ElfStrStrtab,
-	ElfStrShstrtab,
-	ElfStrRelPlt,
-	ElfStrPlt,
-	ElfStrNoteNetbsdIdent,
-	ElfStrNoPtrData,
-	ElfStrNoPtrBss,
-	NElfStr
-};
-
-vlong elfstr[NElfStr];
-
 static int
 needlib(char *name)
 {
@@ -103,164 +81,437 @@ needlib(char *name)
 
 int	nelfsym = 1;
 
+static void	addpltsym(Sym*);
+static void	addgotsym(Sym*);
+static void	addgotsyminternal(Sym*);
+
+// Preserve highest 8 bits of a, and do addition to lower 24-bit
+// of a and b; used to adjust ARM branch intruction's target
+static int32
+braddoff(int32 a, int32 b)
+{
+	return (((uint32)a) & 0xff000000U) | (0x00ffffffU & (uint32)(a + b));
+}
+
+Sym *
+lookuprel(void)
+{
+	return lookup(".rel", 0);
+}
+
 void
-adddynrel(Sym *s, Reloc *r)
+adddynrela(Sym *rel, Sym *s, Reloc *r)
 {
-	USED(s);
-	USED(r);
-	diag("adddynrel: unsupported binary format");
+	addaddrplus(rel, s, r->off);
+	adduint32(rel, R_ARM_RELATIVE);
 }
 
 void
-adddynsym(Sym *s)
+adddynrel(Sym *s, Reloc *r)
 {
-	USED(s);
-	diag("adddynsym: not implemented");
+	Sym *targ, *rel;
+
+	targ = r->sym;
+	cursym = s;
+
+	switch(r->type) {
+	default:
+		if(r->type >= 256) {
+			diag("unexpected relocation type %d", r->type);
+			return;
+		}
+		break;
+
+	// Handle relocations found in ELF object files.
+	case 256 + R_ARM_PLT32:
+		r->type = D_CALL;
+		if(targ->dynimpname != nil && !targ->dynexport) {
+			addpltsym(targ);
+			r->sym = lookup(".plt", 0);
+			r->add = braddoff(r->add, targ->plt / 4);
+		}
+		return;
+
+	case 256 + R_ARM_THM_PC22: // R_ARM_THM_CALL
+		diag("R_ARM_THM_CALL, are you using -marm?");
+		errorexit();
+		return;
+
+	case 256 + R_ARM_GOT32: // R_ARM_GOT_BREL
+		if(targ->dynimpname == nil || targ->dynexport) {
+			addgotsyminternal(targ);
+		} else {
+			addgotsym(targ);
+		}
+		r->type = D_CONST;	// write r->add during relocsym
+		r->sym = S;
+		r->add += targ->got;
+		return;
+
+	case 256 + R_ARM_GOT_PREL: // GOT(S) + A - P
+		if(targ->dynimpname == nil || targ->dynexport) {
+			addgotsyminternal(targ);
+		} else {
+			addgotsym(targ);
+		}
+		r->type = D_PCREL;
+		r->sym = lookup(".got", 0);
+		r->add += targ->got + 4;
+		return;
+
+	case 256 + R_ARM_GOTOFF: // R_ARM_GOTOFF32
+		r->type = D_GOTOFF;
+		return;
+
+	case 256 + R_ARM_GOTPC: // R_ARM_BASE_PREL
+		r->type = D_PCREL;
+		r->sym = lookup(".got", 0);
+		r->add += 4;
+		return;
+
+	case 256 + R_ARM_CALL:
+		r->type = D_CALL;
+		if(targ->dynimpname != nil && !targ->dynexport) {
+			addpltsym(targ);
+			r->sym = lookup(".plt", 0);
+			r->add = braddoff(r->add, targ->plt / 4);
+		}
+		return;
+
+	case 256 + R_ARM_REL32: // R_ARM_REL32
+		r->type = D_PCREL;
+		r->add += 4;
+		return;
+
+	case 256 + R_ARM_ABS32: 
+		if(targ->dynimpname != nil && !targ->dynexport)
+			diag("unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ->name);
+		r->type = D_ADDR;
+		return;
+
+	case 256 + R_ARM_V4BX:
+		// we can just ignore this, because we are targeting ARM V5+ anyway
+		if(r->sym) {
+			// R_ARM_V4BX is ABS relocation, so this symbol is a dummy symbol, ignore it
+			r->sym->type = 0;
+		}
+		r->sym = S;
+		return;
+
+	case 256 + R_ARM_PC24:
+	case 256 + R_ARM_JUMP24:
+		r->type = D_CALL;
+		if(targ->dynimpname != nil && !targ->dynexport) {
+			addpltsym(targ);
+			r->sym = lookup(".plt", 0);
+			r->add = braddoff(r->add, targ->plt / 4);
+		}
+		return;
+	}
+	
+	// Handle references to ELF symbols from our own object files.
+	if(targ->dynimpname == nil || targ->dynexport)
+		return;
+
+	switch(r->type) {
+	case D_PCREL:
+		addpltsym(targ);
+		r->sym = lookup(".plt", 0);
+		r->add = targ->plt;
+		return;
+	
+	case D_ADDR:
+		if(s->type != SDATA)
+			break;
+		if(iself) {
+			adddynsym(targ);
+			rel = lookup(".rel", 0);
+			addaddrplus(rel, s, r->off);
+			adduint32(rel, ELF32_R_INFO(targ->dynid, R_ARM_GLOB_DAT)); // we need a S + A dynmic reloc
+			r->type = D_CONST;	// write r->add during relocsym
+			r->sym = S;
+			return;
+		}
+		break;
+	}
+
+	cursym = s;
+	diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
 }
 
-static void
+int
+elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+{
+	USED(add);	// written to obj file by ../ld/data.c's reloc
+
+	LPUT(off);
+
+	switch(r->type) {
+	default:
+		return -1;
+
+	case D_ADDR:
+		if(r->siz == 4)
+			LPUT(R_ARM_ABS32 | elfsym<<8);
+		else
+			return -1;
+		break;
+
+	case D_PCREL:
+		if(r->siz == 4)
+			LPUT(R_ARM_REL32 | elfsym<<8);
+		else
+			return -1;
+		break;
+	}
+
+	return 0;
+}
+
+void
 elfsetupplt(void)
 {
-	// TODO
+	Sym *plt, *got;
+	
+	plt = lookup(".plt", 0);
+	got = lookup(".got.plt", 0);
+	if(plt->size == 0) {
+		// str lr, [sp, #-4]!
+		adduint32(plt, 0xe52de004);
+		// ldr lr, [pc, #4]
+		adduint32(plt, 0xe59fe004);
+		// add lr, pc, lr
+		adduint32(plt, 0xe08fe00e);
+		// ldr pc, [lr, #8]!
+		adduint32(plt, 0xe5bef008);
+		// .word &GLOBAL_OFFSET_TABLE[0] - .
+		addpcrelplus(plt, got, 4);
+
+		// the first .plt entry requires 3 .plt.got entries
+		adduint32(got, 0);
+		adduint32(got, 0);
+		adduint32(got, 0);
+	}
 }
 
 int
 archreloc(Reloc *r, Sym *s, vlong *val)
 {
-	USED(r);
-	USED(s);
-	USED(val);
-	return -1;
+	switch(r->type) {
+	case D_CONST:
+		*val = r->add;
+		return 0;
+	case D_GOTOFF:
+		*val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0));
+		return 0;
+	// The following three arch specific relocations are only for generation of 
+	// Linux/ARM ELF's PLT entry (3 assembler instruction)
+	case D_PLT0: // add ip, pc, #0xXX00000
+		if (symaddr(lookup(".got.plt", 0)) < symaddr(lookup(".plt", 0)))
+			diag(".got.plt should be placed after .plt section.");
+		*val = 0xe28fc600U +
+			(0xff & ((uint32)(symaddr(r->sym) - (symaddr(lookup(".plt", 0)) + r->off) + r->add) >> 20));
+		return 0;
+	case D_PLT1: // add ip, ip, #0xYY000
+		*val = 0xe28cca00U +
+			(0xff & ((uint32)(symaddr(r->sym) - (symaddr(lookup(".plt", 0)) + r->off) + r->add + 4) >> 12));
+		return 0;
+	case D_PLT2: // ldr pc, [ip, #0xZZZ]!
+		*val = 0xe5bcf000U +
+			(0xfff & (uint32)(symaddr(r->sym) - (symaddr(lookup(".plt", 0)) + r->off) + r->add + 8));
+		return 0;
+	case D_CALL: // bl XXXXXX or b YYYYYY
+		*val = braddoff((0xff000000U & (uint32)r->add), 
+		                (0xffffff & (uint32)
+		                   ((symaddr(r->sym) + ((uint32)r->add) * 4 - (s->value + r->off)) / 4)));
+	return 0;
+}
+return -1;
 }
 
-void
-adddynlib(char *lib)
+static Reloc *
+addpltreloc(Sym *plt, Sym *got, Sym *sym, int typ)
 {
-	Sym *s;
+Reloc *r;
+	r = addrel(plt);
+	r->sym = got;
+	r->off = plt->size;
+	r->siz = 4;
+	r->type = typ;
+	r->add = sym->got - 8;
+
+	plt->reachable = 1;
+	plt->size += 4;
+	symgrow(plt, plt->size);
+
+	return r;
+}
+
+static void
+addpltsym(Sym *s)
+{
+	Sym *plt, *got, *rel;
 	
-	if(!needlib(lib))
+	if(s->plt >= 0)
 		return;
+
+	adddynsym(s);
 	
 	if(iself) {
-		s = lookup(".dynstr", 0);
-		if(s->size == 0)
-			addstring(s, "");
-		elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, lib));
+		plt = lookup(".plt", 0);
+		got = lookup(".got.plt", 0);
+		rel = lookup(".rel.plt", 0);
+		if(plt->size == 0)
+			elfsetupplt();
+		
+		// .got entry
+		s->got = got->size;
+		// In theory, all GOT should point to the first PLT entry,
+		// Linux/ARM's dynamic linker will do that for us, but FreeBSD/ARM's
+		// dynamic linker won't, so we'd better do it ourselves.
+		addaddrplus(got, plt, 0);
+
+		// .plt entry, this depends on the .got entry
+		s->plt = plt->size;
+		addpltreloc(plt, got, s, D_PLT0); // add lr, pc, #0xXX00000
+		addpltreloc(plt, got, s, D_PLT1); // add lr, lr, #0xYY000
+		addpltreloc(plt, got, s, D_PLT2); // ldr pc, [lr, #0xZZZ]!
+
+		// rel
+		addaddrplus(rel, got, s->got);
+		adduint32(rel, ELF32_R_INFO(s->dynid, R_ARM_JUMP_SLOT));
 	} else {
-		diag("adddynlib: unsupported binary format");
+		diag("addpltsym: unsupported binary format");
+	}
+}
+
+static void
+addgotsyminternal(Sym *s)
+{
+	Sym *got;
+	
+	if(s->got >= 0)
+		return;
+
+	got = lookup(".got", 0);
+	s->got = got->size;
+
+	addaddrplus(got, s, 0);
+
+	if(iself) {
+		;
+	} else {
+		diag("addgotsyminternal: unsupported binary format");
+	}
+}
+
+static void
+addgotsym(Sym *s)
+{
+	Sym *got, *rel;
+	
+	if(s->got >= 0)
+		return;
+	
+	adddynsym(s);
+	got = lookup(".got", 0);
+	s->got = got->size;
+	adduint32(got, 0);
+	
+	if(iself) {
+		rel = lookup(".rel", 0);
+		addaddrplus(rel, got, s->got);
+		adduint32(rel, ELF32_R_INFO(s->dynid, R_ARM_GLOB_DAT));
+	} else {
+		diag("addgotsym: unsupported binary format");
 	}
 }
 
 void
-doelf(void)
+adddynsym(Sym *s)
 {
-	Sym *s, *shstrtab, *dynstr;
+	Sym *d;
+	int t;
+	char *name;
 
-	if(!iself)
+	if(s->dynid >= 0)
 		return;
 
-	/* predefine strings we need for section headers */
-	shstrtab = lookup(".shstrtab", 0);
-	shstrtab->type = SELFROSECT;
-	shstrtab->reachable = 1;
-
-	elfstr[ElfStrEmpty] = addstring(shstrtab, "");
-	elfstr[ElfStrText] = addstring(shstrtab, ".text");
-	elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata");
-	elfstr[ElfStrData] = addstring(shstrtab, ".data");
-	elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
-	elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
-	if(HEADTYPE == Hnetbsd)
-		elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
-	addstring(shstrtab, ".rodata");
-	addstring(shstrtab, ".gosymtab");
-	addstring(shstrtab, ".gopclntab");
-	if(!debug['s']) {	
-		elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
-		elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
+	if(s->dynimpname == nil) {
+		s->dynimpname = s->name;
+		//diag("adddynsym: no dynamic name for %s", s->name);
 	}
-	elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
-
-	if(!debug['d']) {	/* -d suppresses dynamic loader format */
-		elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
-		elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
-		elfstr[ElfStrGot] = addstring(shstrtab, ".got");
-		elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
-		elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
-		elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
-		elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
-		elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
-		elfstr[ElfStrRelPlt] = addstring(shstrtab, ".rel.plt");
-		elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
-
-		/* dynamic symbol table - first entry all zeros */
-		s = lookup(".dynsym", 0);
-		s->type = SELFROSECT;
-		s->reachable = 1;
-		s->value += ELF32SYMSIZE;
-
-		/* dynamic string table */
-		s = lookup(".dynstr", 0);
-		s->type = SELFROSECT;
-		s->reachable = 1;
-		if(s->size == 0)
-			addstring(s, "");
-		dynstr = s;
 
-		/* relocation table */
-		s = lookup(".rel", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
+	if(iself) {
+		s->dynid = nelfsym++;
 
-		/* global offset table */
-		s = lookup(".got", 0);
-		s->reachable = 1;
-		s->type = SELFSECT; // writable
-		
-		/* hash */
-		s = lookup(".hash", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-
-		/* got.plt */
-		s = lookup(".got.plt", 0);
-		s->reachable = 1;
-		s->type = SELFSECT; // writable
-		
-		s = lookup(".plt", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
+		d = lookup(".dynsym", 0);
 
-		s = lookup(".rel.plt", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-		
-		elfsetupplt();
-
-		/* define dynamic elf table */
-		s = lookup(".dynamic", 0);
-		s->reachable = 1;
-		s->type = SELFSECT; // writable
-
-		/*
-		 * .dynamic table
-		 */
-		elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
-		elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
-		elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
-		elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
-		elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
-		elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
-		elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
-		elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
-		if(rpath)
-			elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
-		elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
-		elfwritedynent(s, DT_PLTREL, DT_REL);
-		elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
-		elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
-		elfwritedynent(s, DT_DEBUG, 0);
-		elfwritedynent(s, DT_NULL, 0);
+		/* name */
+		name = s->dynimpname;
+		if(name == nil)
+			name = s->name;
+		adduint32(d, addstring(lookup(".dynstr", 0), name));
+
+		/* value */
+		if(s->type == SDYNIMPORT)
+			adduint32(d, 0);
+		else
+			addaddr(d, s);
+
+		/* size */
+		adduint32(d, 0);
+
+		/* type */
+		t = STB_GLOBAL << 4;
+		if(s->dynexport && (s->type&SMASK) == STEXT)
+			t |= STT_FUNC;
+		else
+			t |= STT_OBJECT;
+		adduint8(d, t);
+		adduint8(d, 0);
+
+		/* shndx */
+		if(!s->dynexport && s->dynimpname != nil)
+			adduint16(d, SHN_UNDEF);
+		else {
+			switch(s->type) {
+			default:
+			case STEXT:
+				t = 11;
+				break;
+			case SRODATA:
+				t = 12;
+				break;
+			case SDATA:
+				t = 13;
+				break;
+			case SBSS:
+				t = 14;
+				break;
+			}
+			adduint16(d, t);
+		}
+	} else {
+		diag("adddynsym: unsupported binary format");
+	}
+}
+
+void
+adddynlib(char *lib)
+{
+	Sym *s;
+	
+	if(!needlib(lib))
+		return;
+	
+	if(iself) {
+		s = lookup(".dynstr", 0);
+		if(s->size == 0)
+			addstring(s, "");
+		elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, lib));
+	} else {
+		diag("adddynlib: unsupported binary format");
 	}
 }
 
@@ -276,48 +527,26 @@ datoff(vlong addr)
 }
 
 void
-shsym(Elf64_Shdr *sh, Sym *s)
-{
-	vlong addr;
-	addr = symaddr(s);
-	if(sh->flags&SHF_ALLOC)
-		sh->addr = addr;
-	sh->off = datoff(addr);
-	sh->size = s->size;
-}
-
-void
-phsh(Elf64_Phdr *ph, Elf64_Shdr *sh)
-{
-	ph->vaddr = sh->addr;
-	ph->paddr = ph->vaddr;
-	ph->off = sh->off;
-	ph->filesz = sh->size;
-	ph->memsz = sh->size;
-	ph->align = sh->addralign;
-}
-
-void
 asmb(void)
 {
 	int32 t;
-	int a, dynsym;
-	uint32 fo, symo, startva, resoff;
-	ElfEhdr *eh;
-	ElfPhdr *ph, *pph;
-	ElfShdr *sh;
+	uint32 symo;
 	Section *sect;
-	int o;
+	Sym *sym;
+	int i;
 
 	if(debug['v'])
 		Bprint(&bso, "%5.2f asmb\n", cputime());
 	Bflush(&bso);
 
+	if(iself)
+		asmbelfsetup();
+
 	sect = segtext.sect;
 	cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
 	codeblk(sect->vaddr, sect->len);
 
-	/* output read-only data in text segment (rodata, gosymtab and pclntab) */
+	/* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
 	for(sect = sect->next; sect != nil; sect = sect->next) {
 		cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
 		datblk(sect->vaddr, sect->len);
@@ -330,19 +559,6 @@ asmb(void)
 	cseek(segdata.fileoff);
 	datblk(segdata.vaddr, segdata.filelen);
 
-	if(iself) {
-		/* index of elf text section; needed by asmelfsym, double-checked below */
-		/* !debug['d'] causes extra sections before the .text section */
-		elftextsh = 2;
-		if(!debug['d']) {
-			elftextsh += 10;
-			if(elfverneed)
-				elftextsh += 2;
-		}
-		if(HEADTYPE == Hnetbsd)
-			elftextsh += 1;
-	}
-
 	/* output symbol table */
 	symsize = 0;
 	lcsize = 0;
@@ -365,28 +581,43 @@ asmb(void)
 		case Hplan9x32:
 			symo = HEADR+segtext.len+segdata.filelen;
 			break;
-		case Hnetbsd:
-			symo = rnd(segdata.filelen, 4096);
-			break;
 		ElfSym:
 			symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
 			symo = rnd(symo, INITRND);
 			break;
 		}
 		cseek(symo);
-		if(iself) {
-			if(debug['v'])
-				Bprint(&bso, "%5.2f elfsym\n", cputime());
-			asmelfsym();
+		switch(HEADTYPE) {
+		default:
+			if(iself) {
+				if(debug['v'])
+					Bprint(&bso, "%5.2f elfsym\n", cputime());
+				asmelfsym();
+				cflush();
+				cwrite(elfstrdat, elfstrsize);
+	
+				if(debug['v'])
+					Bprint(&bso, "%5.2f dwarf\n", cputime());
+				dwarfemitdebugsections();
+				
+				if(isobj)
+					elfemitreloc();
+			}
+			break;
+		case Hplan9x32:
+			asmplan9sym();
 			cflush();
-			cwrite(elfstrdat, elfstrsize);
 
-			// if(debug['v'])
-			// 	Bprint(&bso, "%5.2f dwarf\n", cputime());
-			// dwarfemitdebugsections();
+			sym = lookup("pclntab", 0);
+			if(sym != nil) {
+				lcsize = sym->np;
+				for(i=0; i < lcsize; i++)
+					cput(sym->p[i]);
+
+				cflush();
+			}
+			break;
 		}
-		cflush();
-		
 	}
 
 	cursym = nil;
@@ -395,6 +626,7 @@ asmb(void)
 	Bflush(&bso);
 	cseek(0L);
 	switch(HEADTYPE) {
+	default:
 	case Hnoheader:	/* no header */
 		break;
 	case Hrisc:	/* aif for risc os */
@@ -409,7 +641,7 @@ asmb(void)
 			 - 8) / 4);		/* BL - entry code */
 
 		lputl(0xef000011);		/* SWI - exit code */
-		lputl(textsize+HEADR);		/* text size */
+		lputl(segtext.filelen+HEADR);		/* text size */
 		lputl(segdata.filelen);			/* data size */
 		lputl(0);			/* sym size */
 
@@ -429,7 +661,7 @@ asmb(void)
 		break;
 	case Hplan9x32:	/* plan 9 */
 		lput(0x647);			/* magic */
-		lput(textsize);			/* sizes */
+		lput(segtext.filelen);			/* sizes */
 		lput(segdata.filelen);
 		lput(segdata.len - segdata.filelen);
 		lput(symsize);			/* nsyms */
@@ -437,16 +669,6 @@ asmb(void)
 		lput(0L);
 		lput(lcsize);
 		break;
-	case Hnetbsd:	/* boot for NetBSD */
-		lput((143<<16)|0413);		/* magic */
-		lputl(rnd(HEADR+textsize, 4096));
-		lputl(rnd(segdata.filelen, 4096));
-		lputl(segdata.len - segdata.filelen);
-		lputl(symsize);			/* nsyms */
-		lputl(entryvalue());		/* va of entry */
-		lputl(0L);
-		lputl(0L);
-		break;
 	case Hixp1200: /* boot for IXP1200 */
 		break;
 	case Hipaq: /* boot for ipaq */
@@ -456,216 +678,20 @@ asmb(void)
 		lputl(0xe3300000);		/* nop */
 		break;
 	case Hlinux:
-		/* elf arm */
-		eh = getElfEhdr();
-		fo = HEADR;
-		startva = INITTEXT - fo;	/* va of byte 0 of file */
-		resoff = ELFRESERVE;
-		
-		/* This null SHdr must appear before all others */
-		newElfShdr(elfstr[ElfStrEmpty]);
-
-		/* program header info */
-		pph = newElfPhdr();
-		pph->type = PT_PHDR;
-		pph->flags = PF_R + PF_X;
-		pph->off = eh->ehsize;
-		pph->vaddr = INITTEXT - HEADR + pph->off;
-		pph->paddr = INITTEXT - HEADR + pph->off;
-		pph->align = INITRND;
-
-		/*
-		 * PHDR must be in a loaded segment. Adjust the text
-		 * segment boundaries downwards to include it.
-		 */
-		o = segtext.vaddr - pph->vaddr;
-		segtext.vaddr -= o;
-		segtext.len += o;
-		o = segtext.fileoff - pph->off;
-		segtext.fileoff -= o;
-		segtext.filelen += o;
-
-		if(!debug['d']) {
-			/* interpreter for dynamic linking */
-			sh = newElfShdr(elfstr[ElfStrInterp]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC;
-			sh->addralign = 1;
-			if(interpreter == nil)
-				interpreter = linuxdynld;
-			resoff -= elfinterp(sh, startva, resoff, interpreter);
-
-			ph = newElfPhdr();
-			ph->type = PT_INTERP;
-			ph->flags = PF_R;
-			phsh(ph, sh);
-		}
-
-		if(HEADTYPE == Hnetbsd) {
-			sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
-			sh->type = SHT_NOTE;
-			sh->flags = SHF_ALLOC;
-			sh->addralign = 4;
-			resoff -= elfnetbsdsig(sh, startva, resoff);
-
-			ph = newElfPhdr();
-			ph->type = PT_NOTE;
-			ph->flags = PF_R;
-			phsh(ph, sh);
-		}
-
-		elfphload(&segtext);
-		elfphload(&segdata);
-
-		/* Dynamic linking sections */
-		if(!debug['d']) {	/* -d suppresses dynamic loader format */
-			/* S headers for dynamic linking */
-			sh = newElfShdr(elfstr[ElfStrGot]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC+SHF_WRITE;
-			sh->entsize = 4;
-			sh->addralign = 4;
-			shsym(sh, lookup(".got", 0));
-
-			sh = newElfShdr(elfstr[ElfStrGotPlt]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC+SHF_WRITE;
-			sh->entsize = 4;
-			sh->addralign = 4;
-			shsym(sh, lookup(".got.plt", 0));
-
-			dynsym = eh->shnum;
-			sh = newElfShdr(elfstr[ElfStrDynsym]);
-			sh->type = SHT_DYNSYM;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = ELF32SYMSIZE;
-			sh->addralign = 4;
-			sh->link = dynsym+1;	// dynstr
-			// sh->info = index of first non-local symbol (number of local symbols)
-			shsym(sh, lookup(".dynsym", 0));
-
-			sh = newElfShdr(elfstr[ElfStrDynstr]);
-			sh->type = SHT_STRTAB;
-			sh->flags = SHF_ALLOC;
-			sh->addralign = 1;
-			shsym(sh, lookup(".dynstr", 0));
-
-			sh = newElfShdr(elfstr[ElfStrHash]);
-			sh->type = SHT_HASH;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = 4;
-			sh->addralign = 4;
-			sh->link = dynsym;
-			shsym(sh, lookup(".hash", 0));
-
-			sh = newElfShdr(elfstr[ElfStrRel]);
-			sh->type = SHT_REL;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = ELF32RELSIZE;
-			sh->addralign = 4;
-			sh->link = dynsym;
-			shsym(sh, lookup(".rel", 0));
-
-			/* sh and PT_DYNAMIC for .dynamic section */
-			sh = newElfShdr(elfstr[ElfStrDynamic]);
-			sh->type = SHT_DYNAMIC;
-			sh->flags = SHF_ALLOC+SHF_WRITE;
-			sh->entsize = 8;
-			sh->addralign = 4;
-			sh->link = dynsym+1;	// dynstr
-			shsym(sh, lookup(".dynamic", 0));
-
-			ph = newElfPhdr();
-			ph->type = PT_DYNAMIC;
-			ph->flags = PF_R + PF_W;
-			phsh(ph, sh);
-
-			/*
-			 * Thread-local storage segment (really just size).
-			if(tlsoffset != 0) {
-				ph = newElfPhdr();
-				ph->type = PT_TLS;
-				ph->flags = PF_R;
-				ph->memsz = -tlsoffset;
-				ph->align = 4;
-			}
-			 */
-		}
-
-		ph = newElfPhdr();
-		ph->type = PT_GNU_STACK;
-		ph->flags = PF_W+PF_R;
-		ph->align = 4;
-
-		sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
-		sh->type = SHT_STRTAB;
-		sh->addralign = 1;
-		shsym(sh, lookup(".shstrtab", 0));
-
-		if(elftextsh != eh->shnum)
-			diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
-		for(sect=segtext.sect; sect!=nil; sect=sect->next)
-			elfshbits(sect);
-		for(sect=segdata.sect; sect!=nil; sect=sect->next)
-			elfshbits(sect);
-
-		if(!debug['s']) {
-			sh = newElfShdr(elfstr[ElfStrSymtab]);
-			sh->type = SHT_SYMTAB;
-			sh->off = symo;
-			sh->size = symsize;
-			sh->addralign = 4;
-			sh->entsize = 16;
-			sh->link = eh->shnum;	// link to strtab
-
-			sh = newElfShdr(elfstr[ElfStrStrtab]);
-			sh->type = SHT_STRTAB;
-			sh->off = symo+symsize;
-			sh->size = elfstrsize;
-			sh->addralign = 1;
-
-			// dwarfaddelfheaders();
-		}
-
-		/* Main header */
-		eh->ident[EI_MAG0] = '\177';
-		eh->ident[EI_MAG1] = 'E';
-		eh->ident[EI_MAG2] = 'L';
-		eh->ident[EI_MAG3] = 'F';
-		eh->ident[EI_CLASS] = ELFCLASS32;
-		eh->ident[EI_DATA] = ELFDATA2LSB;
-		eh->ident[EI_VERSION] = EV_CURRENT;
-
-		eh->type = ET_EXEC;
-		eh->machine = EM_ARM;
-		eh->version = EV_CURRENT;
-		eh->entry = entryvalue();
-
-		if(pph != nil) {
-			pph->filesz = eh->phnum * eh->phentsize;
-			pph->memsz = pph->filesz;
-		}
-
-		cseek(0);
-		a = 0;
-		a += elfwritehdr();
-		a += elfwritephdrs();
-		a += elfwriteshdrs();
-		a += elfwriteinterp(elfstr[ElfStrInterp]);
-		if(HEADTYPE == Hnetbsd)
-			a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
-		if(a > ELFRESERVE)	
-			diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
+	case Hfreebsd:
+	case Hnetbsd:
+	case Hopenbsd:
+		asmbelf(symo);
 		break;
 	}
 	cflush();
 	if(debug['c']){
-		print("textsize=%d\n", textsize);
+		print("textsize=%ulld\n", segtext.filelen);
 		print("datsize=%ulld\n", segdata.filelen);
 		print("bsssize=%ulld\n", segdata.len - segdata.filelen);
 		print("symsize=%d\n", symsize);
 		print("lcsize=%d\n", lcsize);
-		print("total=%lld\n", textsize+segdata.len+symsize+lcsize);
+		print("total=%lld\n", segtext.filelen+segdata.len+symsize+lcsize);
 	}
 }
 
@@ -812,6 +838,7 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
 
 	case 5:		/* bra s */
 		v = -8;
+		// TODO: Use addrel.
 		if(p->cond != P)
 			v = (p->cond->pc - pc) - 8;
 		o1 = opbra(p->as, p->scond);
@@ -875,15 +902,22 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
 			rel = addrel(cursym);
 			rel->off = pc - cursym->value;
 			rel->siz = 4;
-			rel->type = D_ADDR;
 			rel->sym = p->to.sym;
 			rel->add = p->to.offset;
+			if(flag_shared) {
+				rel->type = D_PCREL;
+				rel->add += pc - p->pcrel->pc - 8;
+			} else
+				rel->type = D_ADDR;
 			o1 = 0;
 		}
 		break;
 
 	case 12:	/* movw $lcon, reg */
 		o1 = omvl(p, &p->from, p->to.reg);
+		if(o->flag & LPCREL) {
+			o2 = oprrr(AADD, p->scond) | p->to.reg | REGPC << 16 | p->to.reg << 12;
+		}
 		break;
 
 	case 13:	/* op $lcon, [R], R */
@@ -1128,7 +1162,7 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
 		r = p->reg;
 		if(r == NREG) {
 			r = rt;
-			if(p->as == AMOVF || p->as == AMOVD || p->as == ASQRTF || p->as == ASQRTD)
+			if(p->as == AMOVF || p->as == AMOVD || p->as == ASQRTF || p->as == ASQRTD || p->as == AABSF || p->as == AABSD)
 				r = 0;
 		}
 		o1 |= rf | (r<<16) | (rt<<12);
@@ -1188,13 +1222,23 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
 		break;
 
 	case 62:	/* case R -> movw	R<<2(PC),PC */
-		o1 = olrr(p->from.reg, REGPC, REGPC, p->scond);
-		o1 |= 2<<7;
+		if(o->flag & LPCREL) {
+			o1 = oprrr(AADD, p->scond) | immrot(1) | p->from.reg << 16 | REGTMP << 12;
+			o2 = olrr(REGTMP, REGPC, REGTMP, p->scond);
+			o2 |= 2<<7;
+			o3 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGPC << 12;
+		} else {
+			o1 = olrr(p->from.reg, REGPC, REGPC, p->scond);
+			o1 |= 2<<7;
+		}
 		break;
 
 	case 63:	/* bcase */
-		if(p->cond != P)
+		if(p->cond != P) {
 			o1 = p->cond->pc;
+			if(flag_shared)
+				o1 = o1 - p->pcrel->pc - 16;
+		}
 		break;
 
 	/* reloc ops */
@@ -1203,6 +1247,10 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
 		if(!o1)
 			break;
 		o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
+		if(o->flag & LPCREL) {
+			o3 = o2;
+			o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+		}
 		break;
 
 	case 65:	/* mov/movbu addr,R */
@@ -1212,6 +1260,10 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
 		o2 = olr(0, REGTMP, p->to.reg, p->scond);
 		if(p->as == AMOVBU || p->as == AMOVB)
 			o2 |= 1<<22;
+		if(o->flag & LPCREL) {
+			o3 = o2;
+			o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+		}
 		break;
 
 	case 68:	/* floating point store -> ADDR */
@@ -1219,6 +1271,10 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
 		if(!o1)
 			break;
 		o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p);
+		if(o->flag & LPCREL) {
+			o3 = o2;
+			o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+		}
 		break;
 
 	case 69:	/* floating point load <- ADDR */
@@ -1226,6 +1282,10 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
 		if(!o1)
 			break;
 		o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
+		if(o->flag & LPCREL) {
+			o3 = o2;
+			o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+		}
 		break;
 
 	/* ArmV4 ops: */
@@ -1422,12 +1482,57 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
 			o2 ^= (1<<5)|(1<<6);
 		else if(p->as == AMOVH)
 			o2 ^= (1<<6);
+		if(o->flag & LPCREL) {
+			o3 = o2;
+			o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+		}
 		break;
 	case 94:	/* movh/movhu R,addr -> strh */
 		o1 = omvl(p, &p->to, REGTMP);
 		if(!o1)
 			break;
 		o2 = oshr(p->from.reg, 0, REGTMP, p->scond);
+		if(o->flag & LPCREL) {
+			o3 = o2;
+			o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+		}
+		break;
+	case 95:	/* PLD off(reg) */
+		o1 = 0xf5d0f000;
+		o1 |= p->from.reg << 16;
+		if(p->from.offset < 0) {
+			o1 &= ~(1 << 23);
+			o1 |= (-p->from.offset) & 0xfff;
+		} else
+			o1 |= p->from.offset & 0xfff;
+		break;
+	case 96:	/* UNDEF */
+		// This is supposed to be something that stops execution.
+		// It's not supposed to be reached, ever, but if it is, we'd
+		// like to be able to tell how we got there.  Assemble as
+		//	BL $0
+		// TODO: Use addrel.
+		v = (0 - pc) - 8;
+		o1 = opbra(ABL, C_SCOND_NONE);
+		o1 |= (v >> 2) & 0xffffff;
+		break;
+	case 97:	/* CLZ Rm, Rd */
+ 		o1 = oprrr(p->as, p->scond);
+ 		o1 |= p->to.reg << 12;
+ 		o1 |= p->from.reg;
+		break;
+	case 98:	/* MULW{T,B} Rs, Rm, Rd */
+		o1 = oprrr(p->as, p->scond);
+		o1 |= p->to.reg << 16;
+		o1 |= p->from.reg << 8;
+		o1 |= p->reg;
+		break;
+	case 99:	/* MULAW{T,B} Rs, Rm, Rn, Rd */
+		o1 = oprrr(p->as, p->scond);
+		o1 |= p->to.reg << 12;
+		o1 |= p->from.reg << 8;
+		o1 |= p->reg;
+		o1 |= p->to.offset << 16;
 		break;
 	}
 	
@@ -1547,6 +1652,8 @@ oprrr(int a, int sc)
 	case ADIVF:	return o | (0xe<<24) | (0x8<<20) | (0xa<<8) | (0<<4);
 	case ASQRTD:	return o | (0xe<<24) | (0xb<<20) | (1<<16) | (0xb<<8) | (0xc<<4);
 	case ASQRTF:	return o | (0xe<<24) | (0xb<<20) | (1<<16) | (0xa<<8) | (0xc<<4);
+	case AABSD:	return o | (0xe<<24) | (0xb<<20) | (0<<16) | (0xb<<8) | (0xc<<4);
+	case AABSF:	return o | (0xe<<24) | (0xb<<20) | (0<<16) | (0xa<<8) | (0xc<<4);
 	case ACMPD:	return o | (0xe<<24) | (0xb<<20) | (4<<16) | (0xb<<8) | (0xc<<4);
 	case ACMPF:	return o | (0xe<<24) | (0xb<<20) | (4<<16) | (0xa<<8) | (0xc<<4);
 
@@ -1586,6 +1693,19 @@ oprrr(int a, int sc)
 		return o | (0xe<<24) | (0x1<<20) | (0xb<<8) | (1<<4);
 	case ACMP+AEND:	// cmp imm
 		return o | (0x3<<24) | (0x5<<20);
+
+	case ACLZ:
+		// CLZ doesn't support .S
+		return (o & (0xf<<28)) | (0x16f<<16) | (0xf1<<4);
+
+	case AMULWT:
+		return (o & (0xf<<28)) | (0x12 << 20) | (0xe<<4);
+	case AMULWB:
+		return (o & (0xf<<28)) | (0x12 << 20) | (0xa<<4);
+	case AMULAWT:
+		return (o & (0xf<<28)) | (0x12 << 20) | (0xc<<4);
+	case AMULAWB:
+		return (o & (0xf<<28)) | (0x12 << 20) | (0x8<<4);
 	}
 	diag("bad rrr %d", a);
 	prasm(curp);
@@ -1789,7 +1909,8 @@ omvl(Prog *p, Adr *a, int dr)
 int
 chipzero(Ieee *e)
 {
-	if(e->l != 0 || e->h != 0)
+	// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
+	if(goarm < 7 || e->l != 0 || e->h != 0)
 		return -1;
 	return 0;
 }
@@ -1800,6 +1921,10 @@ chipfloat(Ieee *e)
 	int n;
 	ulong h;
 
+	// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
+	if(goarm < 7)
+		goto no;
+
 	if(e->l != 0 || (e->h&0xffff) != 0)
 		goto no;
 	h = e->h & 0x7fc00000;
@@ -1824,83 +1949,3 @@ chipfloat(Ieee *e)
 no:
 	return -1;
 }
-
-
-void
-genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
-{
-	Auto *a;
-	Sym *s;
-	int h;
-
-	s = lookup("etext", 0);
-	if(s->type == STEXT)
-		put(s, s->name, 'T', s->value, s->size, s->version, 0);
-
-	for(h=0; h<NHASH; h++) {
-		for(s=hash[h]; s!=S; s=s->hash) {
-			if(s->hide)
-				continue;
-			switch(s->type) {
-			case SCONST:
-			case SRODATA:
-			case SDATA:
-			case SELFROSECT:
-			case STYPE:
-			case SSTRING:
-			case SGOSTRING:
-			case SNOPTRDATA:
-			case SSYMTAB:
-			case SPCLNTAB:
-				if(!s->reachable)
-					continue;
-				put(s, s->name, 'D', s->value, s->size, s->version, s->gotype);
-				continue;
-
-			case SBSS:
-			case SNOPTRBSS:
-				if(!s->reachable)
-					continue;
-				if(s->np > 0)
-					diag("%s should not be bss (size=%d type=%d special=%d)", s->name, (int)s->np, s->type, s->special);
-				put(s, s->name, 'B', s->value, s->size, s->version, s->gotype);
-				continue;
-
-			case SFILE:
-				put(nil, s->name, 'f', s->value, 0, s->version, 0);
-				continue;
-			}
-		}
-	}
-
-	for(s = textp; s != nil; s = s->next) {
-		/* filenames first */
-		for(a=s->autom; a; a=a->link)
-			if(a->type == D_FILE)
-				put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0);
-			else
-			if(a->type == D_FILE1)
-				put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
-
-		put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
-
-		/* frame, auto and param after */
-		put(nil, ".frame", 'm', s->text->to.offset+4, 0, 0, 0);
-
-		for(a=s->autom; a; a=a->link)
-			if(a->type == D_AUTO)
-				put(nil, a->asym->name, 'a', -a->aoffset, 0, 0, a->gotype);
-			else
-			if(a->type == D_PARAM)
-				put(nil, a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
-	}
-	if(debug['v'] || debug['n'])
-		Bprint(&bso, "symsize = %ud\n", symsize);
-	Bflush(&bso);
-}
-
-void
-setpersrc(Sym *s)
-{
-	USED(s);
-}
diff --git a/src/cmd/5l/doc.go b/src/cmd/5l/doc.go
index 969f502..a054a22 100644
--- a/src/cmd/5l/doc.go
+++ b/src/cmd/5l/doc.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 ignore
+
 /*
 
 5l is the linker for the ARM.
@@ -10,4 +12,4 @@ The $GOARCH for these tools is arm.
 The flags are documented in ../ld/doc.go.
 
 */
-package documentation
+package main
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index b1a48de..62dd894 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -36,7 +36,9 @@
 enum
 {
 	thechar = '5',
-	PtrSize = 4
+	PtrSize = 4,
+	IntSize = 4,
+	FuncAlign = 4  // single-instruction alignment
 };
 
 #ifndef	EXTERN
@@ -66,22 +68,24 @@ struct	Adr
 {
 	union
 	{
-		int32	u0offset;
+		struct {
+			int32	u0offset;
+			int32	u0offset2; // argsize
+		} u0off;
 		char*	u0sval;
 		Ieee	u0ieee;
 		char*	u0sbig;
 	} u0;
 	Sym*	sym;
+	Sym*	gotype;
 	char	type;
-	uchar	index; // not used on arm, required by ld/go.c
 	char	reg;
 	char	name;
-	int32	offset2; // argsize
 	char	class;
-	Sym*	gotype;
 };
 
-#define	offset	u0.u0offset
+#define	offset	u0.u0off.u0offset
+#define	offset2	u0.u0off.u0offset2
 #define	sval	u0.u0sval
 #define	scon	sval
 #define	ieee	u0.u0ieee
@@ -107,7 +111,7 @@ struct	Prog
 	} u0;
 	Prog*	cond;
 	Prog*	link;
-	Prog*	dlink;
+	Prog*	pcrel;
 	int32	pc;
 	int32	line;
 	int32	spadj;
@@ -116,7 +120,7 @@ struct	Prog
 	uchar	as;
 	uchar	scond;
 	uchar	reg;
-	uchar	align;
+	uchar	align;	// unused
 };
 
 #define	regused	u0.u0regused
@@ -135,8 +139,6 @@ struct	Sym
 	uchar	reachable;
 	uchar	dynexport;
 	uchar	leaf;
-	uchar	stkcheck;
-	uchar	hide;
 	int32	dynid;
 	int32	plt;
 	int32	got;
@@ -144,18 +146,26 @@ struct	Sym
 	int32	sig;
 	int32	size;
 	int32	align;	// if non-zero, required alignment in bytes
+	int32	elfsym;
+	int32	locals;	// size of stack frame locals area
+	int32	args;	// size of stack frame incoming arguments area
 	uchar	special;
 	uchar	fnptr;	// used as fn ptr
+	uchar	stkcheck;
+	uchar	hide;
 	Sym*	hash;	// in hash table
 	Sym*	allsym;	// in all symbol list
 	Sym*	next;	// in text or data list
 	Sym*	sub;	// in SSUB list
 	Sym*	outer;	// container of sub
 	Sym*	gotype;
+	Sym*	reachparent;
+	Sym*	queue;
 	char*	file;
 	char*	dynimpname;
 	char*	dynimplib;
 	char*	dynimpvers;
+	struct Section*	sect;
 	
 	// STEXT
 	Auto*	autom;
@@ -168,6 +178,7 @@ struct	Sym
 	Reloc*	r;
 	int32	nr;
 	int32	maxr;
+	int 	rel_ro;
 };
 
 #define SIGNINTERN	(1729*325*1729)
@@ -190,6 +201,7 @@ struct	Optab
 	char	size;
 	char	param;
 	char	flag;
+	uchar	pcrelsiz;
 };
 struct	Oprang
 {
@@ -207,10 +219,12 @@ enum
 	LFROM		= 1<<0,
 	LTO		= 1<<1,
 	LPOOL		= 1<<2,
+	LPCREL		= 1<<3,
 
 	C_NONE		= 0,
 	C_REG,
 	C_REGREG,
+	C_REGREG2,
 	C_SHIFT,
 	C_FREG,
 	C_PSR,
@@ -220,6 +234,7 @@ enum
 	C_NCON,		/* ~RCON */
 	C_SCON,		/* 0xffff */
 	C_LCON,
+	C_LCONADDR,
 	C_ZFCON,
 	C_SFCON,
 	C_LFCON,
@@ -273,6 +288,7 @@ EXTERN	int32	INITDAT;		/* data location */
 EXTERN	int32	INITRND;		/* data round above text location */
 EXTERN	int32	INITTEXT;		/* text location */
 EXTERN	char*	INITENTRY;		/* entry point */
+EXTERN	char*	LIBINITENTRY;		/* shared library entry point */
 EXTERN	int32	autosize;
 EXTERN	Auto*	curauto;
 EXTERN	Auto*	curhist;
@@ -280,7 +296,7 @@ EXTERN	Prog*	curp;
 EXTERN	Sym*	cursym;
 EXTERN	Sym*	datap;
 EXTERN	int32 	elfdatsize;
-EXTERN	char	debug[128];
+EXTERN	int	debug[128];
 EXTERN	Sym*	etextp;
 EXTERN	char*	noname;
 EXTERN	Prog*	lastp;
@@ -298,12 +314,15 @@ EXTERN	char*	rpath;
 EXTERN	uint32	stroffset;
 EXTERN	int32	symsize;
 EXTERN	Sym*	textp;
-EXTERN	int32	textsize;
 EXTERN	int	version;
 EXTERN	char	xcmp[C_GOK+1][C_GOK+1];
 EXTERN	Prog	zprg;
 EXTERN	int	dtype;
+EXTERN	int	tlsoffset;
 EXTERN	int	armsize;
+EXTERN	int	goarm;
+EXTERN	Sym*	adrgotype;	// type symbol on last Adr read
+EXTERN	Sym*	fromgotype;	// type symbol on last p->from read
 
 extern	char*	anames[];
 extern	Optab	optab[];
@@ -312,6 +331,8 @@ void	addpool(Prog*, Adr*);
 EXTERN	Prog*	blitrl;
 EXTERN	Prog*	elitrl;
 
+EXTERN	int	goarm;
+
 void	initdiv(void);
 EXTERN	Prog*	prog_div;
 EXTERN	Prog*	prog_divu;
@@ -398,6 +419,9 @@ void	span(void);
 void	strnput(char*, int);
 int32	symaddr(Sym*);
 void	undef(void);
+void	vputb(uint64);
+void	vputl(uint64);
+void	wputb(uint16);
 void	wput(int32);
 void    wputl(ushort w);
 void	xdefine(char*, int, int32);
@@ -407,8 +431,9 @@ int32	immaddr(int32);
 int32	opbra(int, int);
 int	brextra(Prog*);
 int	isbranch(Prog*);
-void fnptrs(void);
+void	fnptrs(void);
 void	doelf(void);
+void	dozerostk(void); // used by -Z
 
 vlong		addaddr(Sym *s, Sym *t);
 vlong		addsize(Sym *s, Sym *t);
@@ -425,3 +450,9 @@ vlong		adduintxx(Sym *s, uint64 v, int wid);
 #define	VPUT(a)	abort()
 
 #endif
+
+/* Used by ../ld/dwarf.c */
+enum
+{
+	DWARFREGSP = 13
+};
diff --git a/src/cmd/5l/list.c b/src/cmd/5l/list.c
index 293fee3..a051774 100644
--- a/src/cmd/5l/list.c
+++ b/src/cmd/5l/list.c
@@ -225,6 +225,12 @@ Dconv(Fmt *fp)
 			snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg);
 		break;
 
+	case D_REGREG2:
+		snprint(str, sizeof str, "R%d,R%d", a->reg, (int)a->offset);
+		if(a->name != D_NONE || a->sym != S)
+			snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg);
+		break;
+
 	case D_FREG:
 		snprint(str, sizeof str, "F%d", a->reg);
 		if(a->name != D_NONE || a->sym != S)
@@ -429,6 +435,7 @@ cnames[] =
 	[C_LAUTO]	= "C_LAUTO",
 	[C_LBRA]	= "C_LBRA",
 	[C_LCON]	= "C_LCON",
+	[C_LCONADDR]	= "C_LCONADDR",
 	[C_LOREG]	= "C_LOREG",
 	[C_NCON]	= "C_NCON",
 	[C_NONE]	= "C_NONE",
@@ -438,6 +445,7 @@ cnames[] =
 	[C_RCON]	= "C_RCON",
 	[C_REG]		= "C_REG",
 	[C_REGREG]	= "C_REGREG",
+	[C_REGREG2]	= "C_REGREG2",
 	[C_ROREG]	= "C_ROREG",
 	[C_SAUTO]	= "C_SAUTO",
 	[C_SBRA]	= "C_SBRA",
diff --git a/src/cmd/5l/noop.c b/src/cmd/5l/noop.c
index 004f9f2..99a096a 100644
--- a/src/cmd/5l/noop.c
+++ b/src/cmd/5l/noop.c
@@ -45,6 +45,20 @@ static	Sym*	sym_divu;
 static	Sym*	sym_mod;
 static	Sym*	sym_modu;
 
+static void
+linkcase(Prog *casep)
+{
+	Prog *p;
+
+	for(p = casep; p != P; p = p->link){
+		if(p->as == ABCASE) {
+			for(; p != P && p->as == ABCASE; p = p->link)
+				p->pcrel = casep;
+			break;
+		}
+	}
+}
+
 void
 noops(void)
 {
@@ -76,6 +90,11 @@ noops(void)
 	for(cursym = textp; cursym != nil; cursym = cursym->next) {
 		for(p = cursym->text; p != P; p = p->link) {
 			switch(p->as) {
+			case ACASE:
+				if(flag_shared)
+					linkcase(p);
+				break;
+
 			case ATEXT:
 				p->mark |= LEAF;
 				break;
@@ -365,11 +384,7 @@ noops(void)
 				q1 = p;
 	
 				/* MOV a,4(SP) */
-				q = prg();
-				q->link = p->link;
-				p->link = q;
-				p = q;
-	
+				p = appendp(p);
 				p->as = AMOVW;
 				p->line = q1->line;
 				p->from.type = D_REG;
@@ -379,11 +394,7 @@ noops(void)
 				p->to.offset = 4;
 	
 				/* MOV b,REGTMP */
-				q = prg();
-				q->link = p->link;
-				p->link = q;
-				p = q;
-	
+				p = appendp(p);
 				p->as = AMOVW;
 				p->line = q1->line;
 				p->from.type = D_REG;
@@ -395,11 +406,7 @@ noops(void)
 				p->to.offset = 0;
 	
 				/* CALL appropriate */
-				q = prg();
-				q->link = p->link;
-				p->link = q;
-				p = q;
-	
+				p = appendp(p);
 				p->as = ABL;
 				p->line = q1->line;
 				p->to.type = D_BRANCH;
@@ -424,11 +431,7 @@ noops(void)
 				}
 	
 				/* MOV REGTMP, b */
-				q = prg();
-				q->link = p->link;
-				p->link = q;
-				p = q;
-	
+				p = appendp(p);
 				p->as = AMOVW;
 				p->line = q1->line;
 				p->from.type = D_REG;
@@ -438,12 +441,9 @@ noops(void)
 				p->to.reg = q1->to.reg;
 	
 				/* ADD $8,SP */
-				q = prg();
-				q->link = p->link;
-				p->link = q;
-				p = q;
-	
+				p = appendp(p);
 				p->as = AADD;
+				p->line = q1->line;
 				p->from.type = D_CONST;
 				p->from.reg = NREG;
 				p->from.offset = 8;
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index a3f8161..6aa7fdd 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -34,6 +34,7 @@
 #include	"l.h"
 #include	"../ld/lib.h"
 #include	"../ld/elf.h"
+#include	"../ld/dwarf.h"
 #include	<ar.h>
 
 #ifndef	DEFAULT
@@ -47,41 +48,29 @@ Header headers[] = {
    "noheader", Hnoheader,
    "risc", Hrisc,
    "plan9", Hplan9x32,
-   "netbsd", Hnetbsd,
    "ixp1200", Hixp1200,
    "ipaq", Hipaq,
    "linux", Hlinux,
+   "freebsd", Hfreebsd,
+   "netbsd", Hnetbsd,
    0, 0
 };
 
 /*
  *	-Hrisc -T0x10005000 -R4		is aif for risc os
  *	-Hplan9 -T4128 -R4096		is plan9 format
- *	-Hnetbsd -T0xF0000020 -R4	is NetBSD format
  *	-Hixp1200			is IXP1200 (raw)
  *	-Hipaq -T0xC0008010 -R1024	is ipaq
  *	-Hlinux -Tx -Rx			is linux elf
+ *	-Hfreebsd			is freebsd elf
+ *	-Hnetbsd			is netbsd elf
  */
 
-static char*
-linkername[] =
-{
-	"runtime.softfloat",
-	"math.sqrtGoC",
-};
-
-void
-usage(void)
-{
-	fprint(2, "usage: 5l [-E entry] [-H head] [-I interpreter] [-L dir] [-T text] [-D data] [-R rnd] [-r path] [-o out] main.5\n");
-	errorexit();
-}
-
 void
 main(int argc, char *argv[])
 {
-	int c, i;
-	char *p, *name, *val;
+	char *p;
+	Sym *s;
 
 	Binit(&bso, 1, OWRITE);
 	listinit();
@@ -92,59 +81,53 @@ main(int argc, char *argv[])
 	INITDAT = -1;
 	INITRND = -1;
 	INITENTRY = 0;
+	LIBINITENTRY = 0;
 	nuxiinit();
 	
-	p = getenv("GOARM");
-	if(p != nil && strcmp(p, "5") == 0)
+	p = getgoarm();
+	if(p != nil)
+		goarm = atoi(p);
+	else
+		goarm = 6;
+	if(goarm == 5)
 		debug['F'] = 1;
 
-	ARGBEGIN {
-	default:
-		c = ARGC();
-		if(c == 'l')
-			usage();
- 		if(c >= 0 && c < sizeof(debug))
-			debug[c]++;
-		break;
-	case 'o':
-		outfile = EARGF(usage());
-		break;
-	case 'E':
-		INITENTRY = EARGF(usage());
-		break;
-	case 'I':
-		interpreter = EARGF(usage());
-		break;
-	case 'L':
-		Lflag(EARGF(usage()));
-		break;
-	case 'T':
-		INITTEXT = atolwhex(EARGF(usage()));
-		break;
-	case 'D':
-		INITDAT = atolwhex(EARGF(usage()));
-		break;
-	case 'R':
-		INITRND = atolwhex(EARGF(usage()));
-		break;
-	case 'r':
-		rpath = EARGF(usage());
-		break;
-	case 'H':
-		HEADTYPE = headtype(EARGF(usage()));
-		/* do something about setting INITTEXT */
-		break;
-	case 'V':
-		print("%cl version %s\n", thechar, getgoversion());
-		errorexit();
-	case 'X':
-		name = EARGF(usage());
-		val = EARGF(usage());
-		addstrdata(name, val);
-		break;
-	} ARGEND
-
-	USED(argc);
+	flagcount("1", "use alternate profiling code", &debug['1']);
+	flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo);
+	flagstr("E", "sym: entry symbol", &INITENTRY);
+	flagint32("D", "addr: data address", &INITDAT);
+	flagcount("G", "debug pseudo-ops", &debug['G']);
+	flagfn1("I", "interp: set ELF interp", setinterp);
+	flagfn1("L", "dir: add dir to library path", Lflag);
+	flagfn1("H", "head: header type", setheadtype);
+	flagcount("K", "add stack underflow checks", &debug['K']);
+	flagcount("M", "disable software div/mod", &debug['M']);
+	flagcount("O", "print pc-line tables", &debug['O']);
+	flagcount("P", "debug code generation", &debug['P']);
+	flagint32("R", "rnd: address rounding", &INITRND);
+	flagint32("T", "addr: text address", &INITTEXT);
+	flagfn0("V", "print version and exit", doversion);
+	flagcount("W", "disassemble input", &debug['W']);
+	flagfn2("X", "name value: define string data", addstrdata);
+	flagcount("Z", "clear stack frame on entry", &debug['Z']);
+	flagcount("a", "disassemble output", &debug['a']);
+	flagcount("c", "dump call graph", &debug['c']);
+	flagcount("d", "disable dynamic executable", &debug['d']);
+	flagcount("f", "ignore version mismatch", &debug['f']);
+	flagcount("g", "disable go package data checks", &debug['g']);
+	flagstr("k", "sym: set field tracking symbol", &tracksym);
+	flagcount("n", "dump symbol table", &debug['n']);
+	flagstr("o", "outfile: set output file", &outfile);
+	flagcount("p", "insert profiling code", &debug['p']);
+	flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
+	flagcount("race", "enable race detector", &flag_race);
+	flagcount("s", "disable symbol table", &debug['s']);
+	flagcount("u", "reject unsafe packages", &debug['u']);
+	flagcount("v", "print link trace", &debug['v']);
+	flagcount("w", "disable DWARF generation", &debug['w']);
+	flagcount("shared", "generate shared object", &flag_shared);
+	
+	flagparse(&argc, &argv, usage);
 
 	if(argc != 1)
 		usage();
@@ -152,7 +135,7 @@ main(int argc, char *argv[])
 	libinit();
 
 	if(HEADTYPE == -1)
-		HEADTYPE = Hlinux;
+		HEADTYPE = headtype(goos);
 	switch(HEADTYPE) {
 	default:
 		diag("unknown -H option");
@@ -184,15 +167,6 @@ main(int argc, char *argv[])
 		if(INITRND == -1)
 			INITRND = 4096;
 		break;
-	case Hnetbsd:	/* boot for NetBSD */
-		HEADR = 32L;
-		if(INITTEXT == -1)
-			INITTEXT = 0xF0000020L;
-		if(INITDAT == -1)
-			INITDAT = 0;
-		if(INITRND == -1)
-			INITRND = 4096;
-		break;
 	case Hixp1200: /* boot for IXP1200 */
 		HEADR = 0L;
 		if(INITTEXT == -1)
@@ -212,7 +186,11 @@ main(int argc, char *argv[])
 			INITRND = 1024;
 		break;
 	case Hlinux:	/* arm elf */
-		debug['d'] = 1;	// no dynamic linking
+	case Hfreebsd:
+	case Hnetbsd:
+		debug['d'] = 0;	// with dynamic linking
+		tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then 4-byte word for m
+		                // this number is known to ../../pkg/runtime/cgo/gcc_linux_arm.c
 		elfinit();
 		HEADR = ELFRESERVE;
 		if(INITTEXT == -1)
@@ -246,13 +224,17 @@ main(int argc, char *argv[])
 	cbp = buf.cbuf;
 	cbc = sizeof(buf.cbuf);
 
+	// embed goarm to runtime.goarm
+	s = lookup("runtime.goarm", 0);
+	s->dupok = 1;
+	adduint8(s, goarm);
+
 	addlibpath("command line", "command line", argv[0], "main");
 	loadlib();
 
 	// mark some functions that are only referenced after linker code editing
-	// TODO(kaib): this doesn't work, the prog can't be found in runtime
-	for(i=0; i<nelem(linkername); i++)
-		mark(lookup(linkername[i], 0));
+	if(debug['F'])
+		mark(rlookup("_sfloat", 0));
 	deadcode();
 	if(textp == nil) {
 		diag("no code");
@@ -268,9 +250,16 @@ main(int argc, char *argv[])
 	doelf();
 	follow();
 	softfloat();
-	noops();
+	// 5l -Z means zero the stack frame on entry.
+	// This slows down function calls but can help avoid
+	// false positives in garbage collection.
+	if(debug['Z'])
+		dozerostk();
+	noops(); // generate stack split prolog, handle div/mod, etc.
 	dostkcheck();
 	span();
+	addexport();
+	// textaddress() functionality is handled in span()
 	pclntab();
 	symtab();
 	dodata();
@@ -291,24 +280,38 @@ main(int argc, char *argv[])
 	errorexit();
 }
 
+static Sym*
+zsym(char *pn, Biobuf *f, Sym *h[])
+{	
+	int o;
+	
+	o = BGETC(f);
+	if(o == 0)
+		return S;
+	if(o < 0 || o >= NSYM || h[o] == nil)
+		mangle(pn);
+	return h[o];
+}
+
 static void
-zaddr(Biobuf *f, Adr *a, Sym *h[])
+zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
 {
 	int i, c;
 	int32 l;
 	Sym *s;
 	Auto *u;
 
-	a->type = Bgetc(f);
-	a->reg = Bgetc(f);
-	c = Bgetc(f);
+	a->type = BGETC(f);
+	a->reg = BGETC(f);
+	c = BGETC(f);
 	if(c < 0 || c > NSYM){
 		print("sym out of range: %d\n", c);
 		Bputc(f, ALAST+1);
 		return;
 	}
 	a->sym = h[c];
-	a->name = Bgetc(f);
+	a->name = BGETC(f);
+	adrgotype = zsym(pn, f, h);
 
 	if((schar)a->reg < 0 || a->reg > NREG) {
 		print("register out of range %d\n", a->reg);
@@ -341,7 +344,8 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
 		break;
 
 	case D_REGREG:
-		a->offset = Bgetc(f);
+	case D_REGREG2:
+		a->offset = BGETC(f);
 		break;
 
 	case D_CONST2:
@@ -368,8 +372,11 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
 	if(s == S)
 		return;
 	i = a->name;
-	if(i != D_AUTO && i != D_PARAM)
+	if(i != D_AUTO && i != D_PARAM) {
+		if(s && adrgotype)
+			s->gotype = adrgotype;
 		return;
+	}
 
 	l = a->offset;
 	for(u=curauto; u; u=u->link)
@@ -377,6 +384,8 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
 		if(u->type == i) {
 			if(u->aoffset > l)
 				u->aoffset = l;
+			if(adrgotype)
+				u->gotype = adrgotype;
 			return;
 		}
 
@@ -386,6 +395,7 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
 	u->asym = s;
 	u->aoffset = l;
 	u->type = i;
+	u->gotype = adrgotype;
 }
 
 void
@@ -425,7 +435,7 @@ newloop:
 loop:
 	if(f->state == Bracteof || Boffset(f) >= eof)
 		goto eof;
-	o = Bgetc(f);
+	o = BGETC(f);
 	if(o == Beof)
 		goto eof;
 
@@ -438,8 +448,8 @@ loop:
 		sig = 0;
 		if(o == ASIGNAME)
 			sig = Bget4(f);
-		v = Bgetc(f); /* type */
-		o = Bgetc(f); /* sym */
+		v = BGETC(f); /* type */
+		o = BGETC(f); /* sym */
 		r = 0;
 		if(v == D_STATIC)
 			r = version;
@@ -483,18 +493,20 @@ loop:
 				histfrogp++;
 			} else
 				collapsefrog(s);
+			dwarfaddfrag(s->value, s->name);
 		}
 		goto loop;
 	}
 
 	p = mal(sizeof(Prog));
 	p->as = o;
-	p->scond = Bgetc(f);
-	p->reg = Bgetc(f);
+	p->scond = BGETC(f);
+	p->reg = BGETC(f);
 	p->line = Bget4(f);
 
-	zaddr(f, &p->from, h);
-	zaddr(f, &p->to, h);
+	zaddr(pn, f, &p->from, h);
+	fromgotype = adrgotype;
+	zaddr(pn, f, &p->to, h);
 
 	if(p->as != ATEXT && p->as != AGLOBL && p->reg > NREG)
 		diag("register out of range %A %d", p->as, p->reg);
@@ -582,6 +594,15 @@ loop:
 		pc++;
 		break;
 
+	case ALOCALS:
+		cursym->locals = p->to.offset;
+		pc++;
+		break;
+
+	case ATYPE:
+		pc++;
+		goto loop;
+
 	case ATEXT:
 		if(cursym != nil && cursym->text) {
 			histtoauto();
@@ -611,6 +632,11 @@ loop:
 			etextp->next = s;
 		else
 			textp = s;
+		if(fromgotype) {
+			if(s->gotype && s->gotype != fromgotype)
+				diag("%s: type mismatch for %s", pn, s->name);
+			s->gotype = fromgotype;
+		}
 		etextp = s;
 		p->align = 4;
 		autosize = (p->to.offset+3L) & ~3L;
@@ -619,6 +645,7 @@ loop:
 		s->type = STEXT;
 		s->text = p;
 		s->value = pc;
+		s->args = p->to.offset2;
 		lastp = p;
 		p->pc = pc;
 		pc++;
@@ -672,7 +699,7 @@ loop:
 			sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
 			s = lookup(literal, 0);
 			if(s->type == 0) {
-				s->type = SBSS;
+				s->type = SRODATA;
 				adduint32(s, ieeedtof(&p->from.ieee));
 				s->reachable = 0;
 			}
@@ -694,7 +721,7 @@ loop:
 				p->from.ieee.l, p->from.ieee.h);
 			s = lookup(literal, 0);
 			if(s->type == 0) {
-				s->type = SBSS;
+				s->type = SRODATA;
 				adduint32(s, p->from.ieee.l);
 				adduint32(s, p->from.ieee.h);
 				s->reachable = 0;
diff --git a/src/cmd/5l/optab.c b/src/cmd/5l/optab.c
index 514786f..231071f 100644
--- a/src/cmd/5l/optab.c
+++ b/src/cmd/5l/optab.c
@@ -63,6 +63,7 @@ Optab	optab[] =
 
 	{ AB,		C_NONE,	C_NONE,	C_ROREG,	 6, 4, 0,	LPOOL },
 	{ ABL,		C_NONE,	C_NONE,	C_ROREG,	 7, 8, 0 },
+	{ ABL,		C_REG,	C_NONE,	C_ROREG,	 7, 8, 0 },
 	{ ABX,		C_NONE,	C_NONE,	C_ROREG,	 75, 12, 0 },
 	{ ABXRET,	C_NONE,	C_NONE,	C_ROREG,	 76, 4, 0 },
 
@@ -77,10 +78,12 @@ Optab	optab[] =
 	{ ASWI,		C_NONE,	C_NONE,	C_LCON,		10, 4, 0 },
 
 	{ AWORD,	C_NONE,	C_NONE,	C_LCON,		11, 4, 0 },
+	{ AWORD,	C_NONE,	C_NONE,	C_LCONADDR,	11, 4, 0 },
 	{ AWORD,	C_NONE,	C_NONE,	C_ADDR,		11, 4, 0 },
 
 	{ AMOVW,	C_NCON,	C_NONE,	C_REG,		12, 4, 0 },
 	{ AMOVW,	C_LCON,	C_NONE,	C_REG,		12, 4, 0,	LFROM },
+	{ AMOVW,	C_LCONADDR,	C_NONE,	C_REG,	12, 4, 0,	LFROM | LPCREL, 4},
 
 	{ AADD,		C_NCON,	C_REG,	C_REG,		13, 8, 0 },
 	{ AADD,		C_NCON,	C_NONE,	C_REG,		13, 8, 0 },
@@ -103,6 +106,7 @@ Optab	optab[] =
 	{ ADIV,		C_REG,	C_NONE,	C_REG,		16, 4, 0 },
 
 	{ AMULL,	C_REG,	C_REG,	C_REGREG,	17, 4, 0 },
+	{ AMULA,	C_REG,	C_REG,	C_REGREG2,	17, 4, 0 },
 
 	{ AMOVW,	C_REG,	C_NONE,	C_SAUTO,	20, 4, REGSP },
 	{ AMOVW,	C_REG,	C_NONE,	C_SOREG,	20, 4, 0 },
@@ -118,20 +122,20 @@ Optab	optab[] =
 
 	{ AMOVW,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
 	{ AMOVW,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
-	{ AMOVW,	C_REG,	C_NONE,	C_ADDR,		64, 8, 0,	LTO },
+	{ AMOVW,	C_REG,	C_NONE,	C_ADDR,		64, 8, 0,	LTO | LPCREL, 4 },
 	{ AMOVB,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
 	{ AMOVB,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
-	{ AMOVB,	C_REG,	C_NONE,	C_ADDR,		64, 8, 0,	LTO },
+	{ AMOVB,	C_REG,	C_NONE,	C_ADDR,		64, 8, 0,	LTO | LPCREL, 4 },
 	{ AMOVBU,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
 	{ AMOVBU,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
-	{ AMOVBU,	C_REG,	C_NONE,	C_ADDR,		64, 8, 0,	LTO },
+	{ AMOVBU,	C_REG,	C_NONE,	C_ADDR,		64, 8, 0,	LTO | LPCREL, 4 },
 
 	{ AMOVW,	C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM },
 	{ AMOVW,	C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM },
-	{ AMOVW,	C_ADDR,	C_NONE,	C_REG,		65, 8, 0,	LFROM },
+	{ AMOVW,	C_ADDR,	C_NONE,	C_REG,		65, 8, 0,	LFROM | LPCREL, 4 },
 	{ AMOVBU,	C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM },
 	{ AMOVBU,	C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM },
-	{ AMOVBU,	C_ADDR,	C_NONE,	C_REG,		65, 8, 0,	LFROM },
+	{ AMOVBU,	C_ADDR,	C_NONE,	C_REG,		65, 8, 0,	LFROM | LPCREL, 4 },
 
 	{ AMOVW,	C_LACON,C_NONE,	C_REG,		34, 8, REGSP,	LFROM },
 
@@ -158,8 +162,8 @@ Optab	optab[] =
 	{ AMOVF,	C_LAUTO,C_NONE,	C_FREG,		53, 12, REGSP,	LFROM },
 	{ AMOVF,	C_LOREG,C_NONE,	C_FREG,		53, 12, 0,	LFROM },
 
-	{ AMOVF,	C_FREG,	C_NONE,	C_ADDR,		68, 8, 0,	LTO },
-	{ AMOVF,	C_ADDR,	C_NONE,	C_FREG,		69, 8, 0,	LFROM },
+	{ AMOVF,	C_FREG,	C_NONE,	C_ADDR,		68, 8, 0,	LTO | LPCREL, 4 },
+	{ AMOVF,	C_ADDR,	C_NONE,	C_FREG,		69, 8, 0,	LFROM | LPCREL, 4},
 
 	{ AADDF,	C_FREG,	C_NONE,	C_FREG,		54, 4, 0 },
 	{ AADDF,	C_FREG,	C_REG,	C_FREG,		54, 4, 0 },
@@ -177,7 +181,7 @@ Optab	optab[] =
 	{ AMOVB,	C_REG,	C_NONE,	C_SHIFT,	61, 4, 0 },
 	{ AMOVBU,	C_REG,	C_NONE,	C_SHIFT,	61, 4, 0 },
 
-	{ ACASE,	C_REG,	C_NONE,	C_NONE,		62, 4, 0 },
+	{ ACASE,	C_REG,	C_NONE,	C_NONE,		62, 4, 0, LPCREL, 8 },
 	{ ABCASE,	C_NONE, C_NONE, C_SBRA,		63, 4, 0 },
 
 	{ AMOVH,	C_REG,	C_NONE, C_HAUTO,	70, 4, REGSP,	0 },
@@ -194,20 +198,20 @@ Optab	optab[] =
 
 	{ AMOVH,	C_REG,	C_NONE, C_LAUTO,	72, 8, REGSP,	LTO },
 	{ AMOVH,	C_REG,	C_NONE,	C_LOREG,	72, 8, 0,	LTO },
-	{ AMOVH,	C_REG,	C_NONE,	C_ADDR,	94, 8, 0,	LTO },
+	{ AMOVH,	C_REG,	C_NONE,	C_ADDR,	94, 8, 0,	LTO | LPCREL, 4 },
 	{ AMOVHU,	C_REG,	C_NONE, C_LAUTO,	72, 8, REGSP,	LTO },
 	{ AMOVHU,	C_REG,	C_NONE,	C_LOREG,	72, 8, 0,	LTO },
-	{ AMOVHU,	C_REG,	C_NONE,	C_ADDR,	94, 8, 0,	LTO },
+	{ AMOVHU,	C_REG,	C_NONE,	C_ADDR,	94, 8, 0,	LTO | LPCREL, 4 },
 
 	{ AMOVB,	C_LAUTO,C_NONE,	C_REG,		73, 8, REGSP,	LFROM },
 	{ AMOVB,	C_LOREG,C_NONE,	C_REG,		73, 8, 0,	LFROM },
-	{ AMOVB,	C_ADDR,	C_NONE,	C_REG,		93, 8, 0,	LFROM },
+	{ AMOVB,	C_ADDR,	C_NONE,	C_REG,		93, 8, 0,	LFROM | LPCREL, 4 },
 	{ AMOVH,	C_LAUTO,C_NONE, C_REG,		73, 8, REGSP,	LFROM },
 	{ AMOVH,	C_LOREG,C_NONE,	C_REG,		73, 8, 0,	LFROM },
-	{ AMOVH,	C_ADDR,	C_NONE,	C_REG,		93, 8, 0,	LFROM },
+	{ AMOVH,	C_ADDR,	C_NONE,	C_REG,		93, 8, 0,	LFROM | LPCREL, 4 },
 	{ AMOVHU,	C_LAUTO,C_NONE, C_REG,		73, 8, REGSP,	LFROM },
 	{ AMOVHU,	C_LOREG,C_NONE,	C_REG,		73, 8, 0,	LFROM },
-	{ AMOVHU,	C_ADDR,	C_NONE,	C_REG,		93, 8, 0,	LFROM },
+	{ AMOVHU,	C_ADDR,	C_NONE,	C_REG,		93, 8, 0,	LFROM | LPCREL, 4 },
 
 	{ ALDREX,	C_SOREG,C_NONE,	C_REG,		77, 4, 0 },
 	{ ASTREX,	C_SOREG,C_REG,	C_REG,		78, 4, 0 },
@@ -232,5 +236,16 @@ Optab	optab[] =
 	{ ALDREXD,	C_SOREG,C_NONE,	C_REG,		91, 4, 0 },
 	{ ASTREXD,	C_SOREG,C_REG,	C_REG,		92, 4, 0 },
 
+	{ APLD,		C_SOREG,C_NONE,	C_NONE,		95, 4, 0 },
+	
+	{ AUNDEF,		C_NONE,	C_NONE,	C_NONE,		96, 4, 0 },
+
+	{ ACLZ,		C_REG,	C_NONE,	C_REG,		97, 4, 0 },
+
+	{ AMULWT,	C_REG,	C_REG,	C_REG,		98, 4, 0 },
+	{ AMULAWT,	C_REG,	C_REG,	C_REGREG2,		99, 4, 0 },
+
+	{ AUSEFIELD,	C_ADDR,	C_NONE,	C_NONE, 	 0, 0, 0 },
+
 	{ AXXX,		C_NONE,	C_NONE,	C_NONE,		 0, 4, 0 },
 };
diff --git a/src/cmd/5l/pass.c b/src/cmd/5l/pass.c
index 0f2afbd..c22b860 100644
--- a/src/cmd/5l/pass.c
+++ b/src/cmd/5l/pass.c
@@ -119,7 +119,7 @@ loop:
 				i--;
 				continue;
 			}
-			if(a == AB || (a == ARET && q->scond == 14) || a == ARFE)
+			if(a == AB || (a == ARET && q->scond == 14) || a == ARFE || a == AUNDEF)
 				goto copy;
 			if(q->cond == P || (q->cond->mark&FOLL))
 				continue;
@@ -140,7 +140,7 @@ loop:
 				}
 				(*last)->link = r;
 				*last = r;
-				if(a == AB || (a == ARET && q->scond == 14) || a == ARFE)
+				if(a == AB || (a == ARET && q->scond == 14) || a == ARFE || a == AUNDEF)
 					return;
 				r->as = ABNE;
 				if(a == ABNE)
@@ -166,7 +166,7 @@ loop:
 	p->mark |= FOLL;
 	(*last)->link = p;
 	*last = p;
-	if(a == AB || (a == ARET && p->scond == 14) || a == ARFE){
+	if(a == AB || (a == ARET && p->scond == 14) || a == ARFE || a == AUNDEF){
 		return;
 	}
 	if(p->cond != P)
@@ -215,7 +215,7 @@ patch(void)
 				s = p->to.sym;
 				if(s->text == nil)
 					continue;
-				switch(s->type) {
+				switch(s->type&SMASK) {
 				default:
 					diag("undefined: %s", s->name);
 					s->type = STEXT;
@@ -231,7 +231,7 @@ patch(void)
 			if(p->to.type != D_BRANCH)
 				continue;
 			c = p->to.offset;
-			for(q = textp->text; q != P;) {
+			for(q = cursym->text; q != P;) {
 				if(c == q->pc)
 					break;
 				if(q->forwd != P && c >= q->forwd->pc)
@@ -333,3 +333,70 @@ rnd(int32 v, int32 r)
 	v -= c;
 	return v;
 }
+
+void
+dozerostk(void)
+{
+	Prog *p, *pl;
+	int32 autoffset;
+
+	for(cursym = textp; cursym != nil; cursym = cursym->next) {
+		if(cursym->text == nil || cursym->text->link == nil)
+			continue;				
+		p = cursym->text;
+		autoffset = p->to.offset;
+		if(autoffset < 0)
+			autoffset = 0;
+		if(autoffset && !(p->reg&NOSPLIT)) {
+			// MOVW $4(R13), R1
+			p = appendp(p);
+			p->as = AMOVW;
+			p->from.type = D_CONST;
+			p->from.reg = 13;
+			p->from.offset = 4;
+			p->to.type = D_REG;
+			p->to.reg = 1;
+
+			// MOVW $n(R13), R2
+			p = appendp(p);
+			p->as = AMOVW;
+			p->from.type = D_CONST;
+			p->from.reg = 13;
+			p->from.offset = 4 + autoffset;
+			p->to.type = D_REG;
+			p->to.reg = 2;
+
+			// MOVW $0, R3
+			p = appendp(p);
+			p->as = AMOVW;
+			p->from.type = D_CONST;
+			p->from.offset = 0;
+			p->to.type = D_REG;
+			p->to.reg = 3;
+
+			// L:
+			//	MOVW.P R3, 0(R1) +4
+			//	CMP R1, R2
+			//	BNE L
+			p = pl = appendp(p);
+			p->as = AMOVW;
+			p->from.type = D_REG;
+			p->from.reg = 3;
+			p->to.type = D_OREG;
+			p->to.reg = 1;
+			p->to.offset = 4;
+			p->scond |= C_PBIT;
+
+			p = appendp(p);
+			p->as = ACMP;
+			p->from.type = D_REG;
+			p->from.reg = 1;
+			p->reg = 2;
+
+			p = appendp(p);
+			p->as = ABNE;
+			p->to.type = D_BRANCH;
+			p->cond = pl;
+		}
+	}
+}
diff --git a/src/cmd/5l/softfloat.c b/src/cmd/5l/softfloat.c
index 4011071..de6481c 100644
--- a/src/cmd/5l/softfloat.c
+++ b/src/cmd/5l/softfloat.c
@@ -55,6 +55,8 @@ softfloat(void)
 			case ADIVD:
 			case ASQRTF:
 			case ASQRTD:
+			case AABSF:
+			case AABSD:
 				goto soft;
 
 			default:
@@ -74,6 +76,7 @@ softfloat(void)
 	 				p->to.type = D_BRANCH;
 					p->to.sym = symsfloat;
 					p->cond = psfloat;
+					p->line = next->line;
 	
 					p = next;
 					wasfloat = 1;
diff --git a/src/cmd/5l/span.c b/src/cmd/5l/span.c
index 13e1848..a5afa02 100644
--- a/src/cmd/5l/span.c
+++ b/src/cmd/5l/span.c
@@ -90,16 +90,36 @@ span(void)
 	int32 c, otxt, out[6];
 	Section *sect;
 	uchar *bp;
+	Sym *sub;
 
 	if(debug['v'])
 		Bprint(&bso, "%5.2f span\n", cputime());
 	Bflush(&bso);
 
+	sect = addsection(&segtext, ".text", 05);
+	lookup("text", 0)->sect = sect;
+	lookup("etext", 0)->sect = sect;
+
 	bflag = 0;
 	c = INITTEXT;
 	otxt = c;
 	for(cursym = textp; cursym != nil; cursym = cursym->next) {
+		cursym->sect = sect;
 		p = cursym->text;
+		if(p == P || p->link == P) { // handle external functions and ELF section symbols
+			if(cursym->type & SSUB)
+				continue;
+			if(cursym->align != 0)
+				c = rnd(c, cursym->align);
+			cursym->value = 0;
+			for(sub = cursym; sub != S; sub = sub->sub) {
+				sub->value += c;
+				for(p = sub->text; p != P; p = p->link)
+					p->pc += sub->value;
+			}
+			c += cursym->size;
+			continue;
+		}
 		p->pc = c;
 		cursym->value = c;
 
@@ -160,6 +180,8 @@ span(void)
 		bflag = 0;
 		c = INITTEXT;
 		for(cursym = textp; cursym != nil; cursym = cursym->next) {
+			if(!cursym->text || !cursym->text->link)
+				continue;
 			cursym->value = c;
 			for(p = cursym->text; p != P; p = p->link) {
 				curp = p;
@@ -217,6 +239,8 @@ span(void)
 	 */
 	for(cursym = textp; cursym != nil; cursym = cursym->next) {
 		p = cursym->text;
+		if(p == P || p->link == P)
+		       continue;
 		autosize = p->to.offset + 4;
 		symgrow(cursym, cursym->size);
 	
@@ -235,7 +259,6 @@ span(void)
 			}
 		}
 	}
-	sect = addsection(&segtext, ".text", 05);
 	sect->vaddr = INITTEXT;
 	sect->len = c - INITTEXT;
 }
@@ -269,12 +292,20 @@ flushpool(Prog *p, int skip, int force)
 			q->to.type = D_BRANCH;
 			q->cond = p->link;
 			q->link = blitrl;
+			q->line = p->line;
 			blitrl = q;
 		}
 		else if(!force && (p->pc+pool.size-pool.start < 2048))
 			return 0;
 		elitrl->link = p->link;
 		p->link = blitrl;
+		// BUG(minux): how to correctly handle line number for constant pool entries?
+		// for now, we set line number to the last instruction preceding them at least
+		// this won't bloat the .debug_line tables
+		while(blitrl) {
+			blitrl->line = p->line;
+			blitrl = blitrl->link;
+		}
 		blitrl = 0;	/* BUG: should refer back to values until out-of-range */
 		elitrl = 0;
 		pool.size = 0;
@@ -299,9 +330,11 @@ addpool(Prog *p, Adr *a)
 	switch(c) {
 	default:
 		t.to = *a;
+		if(flag_shared && t.to.sym != S)
+			t.pcrel = p;
 		break;
 
-	case	C_SROREG:
+	case C_SROREG:
 	case C_LOREG:
 	case C_ROREG:
 	case C_FOREG:
@@ -316,11 +349,13 @@ addpool(Prog *p, Adr *a)
 		break;
 	}
 
-	for(q = blitrl; q != P; q = q->link)	/* could hash on t.t0.offset */
-		if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) {
-			p->cond = q;
-			return;
-		}
+	if(t.pcrel == P) {
+		for(q = blitrl; q != P; q = q->link)	/* could hash on t.t0.offset */
+			if(q->pcrel == P && memcmp(&q->to, &t.to, sizeof(t.to)) == 0) {
+				p->cond = q;
+				return;
+			}
+	}
 
 	q = prg();
 	*q = t;
@@ -407,25 +442,9 @@ immhalf(int32 v)
 int32
 symaddr(Sym *s)
 {
-	int32 v;
-
-	v = s->value;
-	switch(s->type) {
-	default:
-		diag("unexpected type %d in symaddr(%s)", s->type, s->name);
-		return 0;
-	
-	case STEXT:
-	case SELFROSECT:
-	case SRODATA:
-	case SDATA:
-	case SBSS:
-	case SCONST:
-	case SNOPTRDATA:
-	case SNOPTRBSS:
-		break;
-	}
-	return v;
+	if(!s->reachable)
+		diag("unreachable symbol in symaddr - %s", s->name);
+	return s->value;
 }
 
 int
@@ -444,6 +463,9 @@ aclass(Adr *a)
 	case D_REGREG:
 		return C_REGREG;
 
+	case D_REGREG2:
+		return C_REGREG2;
+
 	case D_SHIFT:
 		return C_SHIFT;
 
@@ -552,7 +574,10 @@ aclass(Adr *a)
 			if(s == S)
 				break;
 			instoffset = 0;	// s.b. unused but just in case
-			return C_LCON;
+			if(flag_shared)
+				return C_LCONADDR;
+			else
+				return C_LCON;
 
 		case D_AUTO:
 			instoffset = autosize + a->offset;
@@ -718,8 +743,14 @@ buildop(void)
 	for(i=0; i<C_GOK; i++)
 		for(n=0; n<C_GOK; n++)
 			xcmp[i][n] = cmp(n, i);
-	for(n=0; optab[n].as != AXXX; n++)
-		;
+	for(n=0; optab[n].as != AXXX; n++) {
+		if((optab[n].flag & LPCREL) != 0) {
+			if(flag_shared)
+				optab[n].size += optab[n].pcrelsiz;
+			else
+				optab[n].flag &= ~LPCREL;
+		}
+	}
 	qsort(optab, n, sizeof(optab[0]), ocmp);
 	for(i=0; i<n; i++) {
 		r = optab[i].as;
@@ -798,8 +829,11 @@ buildop(void)
 		case AMOVM:
 		case ARFE:
 		case ATEXT:
+		case AUSEFIELD:
+		case ALOCALS:
 		case ACASE:
 		case ABCASE:
+		case ATYPE:
 			break;
 		case AADDF:
 			oprange[AADDD] = oprange[r];
@@ -813,6 +847,8 @@ buildop(void)
 			oprange[ASQRTD] = oprange[r];
 			oprange[AMOVFD] = oprange[r];
 			oprange[AMOVDF] = oprange[r];
+			oprange[AABSF] = oprange[r];
+			oprange[AABSD] = oprange[r];
 			break;
 
 		case ACMPF:
@@ -832,17 +868,28 @@ buildop(void)
 			break;
 
 		case AMULL:
-			oprange[AMULA] = oprange[r];
 			oprange[AMULAL] = oprange[r];
 			oprange[AMULLU] = oprange[r];
 			oprange[AMULALU] = oprange[r];
 			break;
 
+		case AMULWT:
+			oprange[AMULWB] = oprange[r];
+			break;
+
+		case AMULAWT:
+			oprange[AMULAWB] = oprange[r];
+			break;
+
+		case AMULA:
 		case ALDREX:
 		case ASTREX:
 		case ALDREXD:
 		case ASTREXD:
 		case ATST:
+		case APLD:
+		case AUNDEF:
+		case ACLZ:
 			break;
 		}
 	}
diff --git a/src/cmd/6a/a.y b/src/cmd/6a/a.y
index 8459ff3..42af65e 100644
--- a/src/cmd/6a/a.y
+++ b/src/cmd/6a/a.y
@@ -176,6 +176,11 @@ nonrel:
 		$$.from = nullgen;
 		$$.to = $1;
 	}
+|	imm ',' rel
+	{
+		$$.from = $1;
+		$$.to = $3;
+	}
 
 spec1:	/* DATA */
 	nam '/' con ',' imm
diff --git a/src/cmd/6a/doc.go b/src/cmd/6a/doc.go
index 92fb74d..a5f3f87 100644
--- a/src/cmd/6a/doc.go
+++ b/src/cmd/6a/doc.go
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build ignore
+
 /*
 
 6a is a version of the Plan 9 assembler.  The original is documented at
 
-	http://plan9.bell-labs.com/magic/man2html/1/2a
+	http://plan9.bell-labs.com/magic/man2html/1/8a
 
 Its target architecture is the x86-64, referred to by these tools as amd64.
 
 */
-package documentation
+package main
diff --git a/src/cmd/6a/lex.c b/src/cmd/6a/lex.c
index e013bec..d65802a 100644
--- a/src/cmd/6a/lex.c
+++ b/src/cmd/6a/lex.c
@@ -340,6 +340,8 @@ struct
 	"BSRL",		LTYPE3,	ABSRL,
 	"BSRQ",		LTYPE3,	ABSRQ,
 	"BSRW",		LTYPE3,	ABSRW,
+	"BSWAPL",	LTYPE1,	ABSWAPL,
+	"BSWAPQ",	LTYPE1,	ABSWAPQ,
 	"BTCL",		LTYPE3,	ABTCL,
 	"BTCQ",		LTYPE3,	ABTCQ,
 	"BTCW",		LTYPE3,	ABTCW,
@@ -1001,6 +1003,19 @@ struct
 	"XORPS",	LTYPE3,	AXORPS,
 	"CRC32B",	LTYPE4, ACRC32B,
 	"CRC32Q",	LTYPE4, ACRC32Q,
+	"PREFETCHT0",		LTYPE2,	APREFETCHT0,
+	"PREFETCHT1",		LTYPE2,	APREFETCHT1,
+	"PREFETCHT2",		LTYPE2,	APREFETCHT2,
+	"PREFETCHNTA",		LTYPE2,	APREFETCHNTA,
+	"UNDEF",	LTYPE0,	AUNDEF,
+	"AESENC",	LTYPE3,	AAESENC,
+	"AESENCLAST",	LTYPE3, AAESENCLAST,
+	"AESDEC",	LTYPE3, AAESDEC,
+	"AESDECLAST",	LTYPE3, AAESDECLAST,
+	"AESIMC",	LTYPE3, AAESIMC,
+	"AESKEYGENASSIST", LTYPEX, AAESKEYGENASSIST,
+	"PSHUFD",	LTYPEX, APSHUFD,
+	"USEFIELD",	LTYPEN, AUSEFIELD,
 
 	0
 };
@@ -1250,11 +1265,38 @@ outhist(void)
 	Hist *h;
 	char *p, *q, *op, c;
 	int n;
+	char *tofree;
+	static int first = 1;
+	static char *goroot, *goroot_final;
+
+	if(first) {
+		// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
+		first = 0;
+		goroot = getenv("GOROOT");
+		goroot_final = getenv("GOROOT_FINAL");
+		if(goroot == nil)
+			goroot = "";
+		if(goroot_final == nil)
+			goroot_final = goroot;
+		if(strcmp(goroot, goroot_final) == 0) {
+			goroot = nil;
+			goroot_final = nil;
+		}
+	}
+
+	tofree = nil;
 
 	g = nullgen;
 	c = pathchar();
 	for(h = hist; h != H; h = h->link) {
 		p = h->name;
+		if(p != nil && goroot != nil) {
+			n = strlen(goroot);
+			if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
+				tofree = smprint("%s%s", goroot_final, p+n);
+				p = tofree;
+			}
+		}
 		op = 0;
 		if(systemtype(Windows) && p && p[1] == ':'){
 			c = p[2];
@@ -1306,21 +1348,12 @@ outhist(void)
 		Bputc(&obuf, h->line>>24);
 		zaddr(&nullgen, 0);
 		zaddr(&g, 0);
-	}
-}
 
-void
-pragbldicks(void)
-{
-	while(getnsc() != '\n')
-		;
-}
-
-void
-praghjdicks(void)
-{
-	while(getnsc() != '\n')
-		;
+		if(tofree) {
+			free(tofree);
+			tofree = nil;
+		}
+	}
 }
 
 #include "../cc/lexbody"
diff --git a/src/cmd/6a/y.tab.c b/src/cmd/6a/y.tab.c
index 2da8a1f..75c4ad5 100644
--- a/src/cmd/6a/y.tab.c
+++ b/src/cmd/6a/y.tab.c
@@ -406,16 +406,16 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   548
+#define YYLAST   554
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  54
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  40
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  131
+#define YYNRULES  132
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  260
+#define YYNSTATES  263
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -468,16 +468,16 @@ static const yytype_uint16 yyprhs[] =
       23,    26,    29,    33,    37,    40,    43,    46,    49,    52,
       55,    58,    61,    64,    67,    70,    73,    76,    79,    82,
       85,    88,    89,    91,    95,    99,   102,   104,   107,   109,
-     112,   114,   120,   124,   130,   133,   135,   137,   139,   143,
-     149,   153,   159,   162,   164,   168,   174,   180,   181,   183,
-     187,   193,   195,   197,   199,   201,   204,   207,   209,   211,
-     213,   215,   220,   223,   226,   228,   230,   232,   234,   236,
-     238,   240,   243,   246,   249,   252,   255,   260,   266,   270,
-     272,   274,   276,   281,   286,   291,   298,   308,   312,   316,
-     322,   331,   333,   340,   346,   354,   355,   358,   361,   363,
-     365,   367,   369,   371,   374,   377,   380,   384,   386,   389,
-     393,   398,   400,   404,   408,   412,   416,   420,   425,   430,
-     434,   438
+     112,   114,   118,   124,   128,   134,   137,   139,   141,   143,
+     147,   153,   157,   163,   166,   168,   172,   178,   184,   185,
+     187,   191,   197,   199,   201,   203,   205,   208,   211,   213,
+     215,   217,   219,   224,   227,   230,   232,   234,   236,   238,
+     240,   242,   244,   247,   250,   253,   256,   259,   264,   270,
+     274,   276,   278,   280,   285,   290,   295,   302,   312,   316,
+     320,   326,   335,   337,   344,   350,   358,   359,   362,   365,
+     367,   369,   371,   373,   375,   378,   381,   384,   388,   390,
+     393,   397,   402,   404,   408,   412,   416,   420,   424,   429,
+     434,   438,   442
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
@@ -494,40 +494,40 @@ static const yytype_int8 yyrhs[] =
       75,    -1,    29,    76,    -1,    23,    77,    -1,    -1,    49,
       -1,    80,    49,    78,    -1,    78,    49,    80,    -1,    80,
       49,    -1,    80,    -1,    49,    78,    -1,    78,    -1,    49,
-      81,    -1,    81,    -1,    88,    11,    91,    49,    84,    -1,
-      85,    49,    83,    -1,    85,    49,    91,    49,    83,    -1,
-      49,    79,    -1,    79,    -1,    61,    -1,    65,    -1,    80,
-      49,    78,    -1,    80,    49,    78,    46,    35,    -1,    80,
-      49,    78,    -1,    80,    49,    78,    46,    36,    -1,    80,
-      49,    -1,    80,    -1,    80,    49,    78,    -1,    82,    49,
-      78,    49,    91,    -1,    84,    49,    78,    49,    82,    -1,
-      -1,    84,    -1,    85,    49,    84,    -1,    85,    49,    91,
-      49,    84,    -1,    82,    -1,    85,    -1,    81,    -1,    87,
-      -1,    10,    82,    -1,    10,    86,    -1,    82,    -1,    86,
-      -1,    78,    -1,    84,    -1,    91,    50,    32,    51,    -1,
-      43,    89,    -1,    44,    89,    -1,    34,    -1,    37,    -1,
-      35,    -1,    38,    -1,    42,    -1,    36,    -1,    39,    -1,
-      52,    92,    -1,    52,    91,    -1,    52,    88,    -1,    52,
-      41,    -1,    52,    40,    -1,    52,    50,    40,    51,    -1,
-      52,    50,     9,    40,    51,    -1,    52,     9,    40,    -1,
-      86,    -1,    87,    -1,    91,    -1,    91,    50,    35,    51,
-      -1,    91,    50,    42,    51,    -1,    91,    50,    36,    51,
-      -1,    91,    50,    35,    10,    91,    51,    -1,    91,    50,
-      35,    51,    50,    35,    10,    91,    51,    -1,    50,    35,
-      51,    -1,    50,    42,    51,    -1,    50,    35,    10,    91,
-      51,    -1,    50,    35,    51,    50,    35,    10,    91,    51,
-      -1,    88,    -1,    88,    50,    35,    10,    91,    51,    -1,
-      43,    89,    50,    90,    51,    -1,    43,     6,     7,    89,
-      50,    33,    51,    -1,    -1,     8,    91,    -1,     9,    91,
-      -1,    33,    -1,    42,    -1,    31,    -1,    30,    -1,    45,
-      -1,     9,    91,    -1,     8,    91,    -1,    53,    91,    -1,
-      50,    93,    51,    -1,    30,    -1,     9,    30,    -1,    30,
-       9,    30,    -1,     9,    30,     9,    30,    -1,    91,    -1,
-      93,     8,    93,    -1,    93,     9,    93,    -1,    93,    10,
-      93,    -1,    93,    11,    93,    -1,    93,    12,    93,    -1,
-      93,     6,     6,    93,    -1,    93,     7,     7,    93,    -1,
-      93,     5,    93,    -1,    93,     4,    93,    -1,    93,     3,
-      93,    -1
+      81,    -1,    81,    -1,    84,    49,    81,    -1,    88,    11,
+      91,    49,    84,    -1,    85,    49,    83,    -1,    85,    49,
+      91,    49,    83,    -1,    49,    79,    -1,    79,    -1,    61,
+      -1,    65,    -1,    80,    49,    78,    -1,    80,    49,    78,
+      46,    35,    -1,    80,    49,    78,    -1,    80,    49,    78,
+      46,    36,    -1,    80,    49,    -1,    80,    -1,    80,    49,
+      78,    -1,    82,    49,    78,    49,    91,    -1,    84,    49,
+      78,    49,    82,    -1,    -1,    84,    -1,    85,    49,    84,
+      -1,    85,    49,    91,    49,    84,    -1,    82,    -1,    85,
+      -1,    81,    -1,    87,    -1,    10,    82,    -1,    10,    86,
+      -1,    82,    -1,    86,    -1,    78,    -1,    84,    -1,    91,
+      50,    32,    51,    -1,    43,    89,    -1,    44,    89,    -1,
+      34,    -1,    37,    -1,    35,    -1,    38,    -1,    42,    -1,
+      36,    -1,    39,    -1,    52,    92,    -1,    52,    91,    -1,
+      52,    88,    -1,    52,    41,    -1,    52,    40,    -1,    52,
+      50,    40,    51,    -1,    52,    50,     9,    40,    51,    -1,
+      52,     9,    40,    -1,    86,    -1,    87,    -1,    91,    -1,
+      91,    50,    35,    51,    -1,    91,    50,    42,    51,    -1,
+      91,    50,    36,    51,    -1,    91,    50,    35,    10,    91,
+      51,    -1,    91,    50,    35,    51,    50,    35,    10,    91,
+      51,    -1,    50,    35,    51,    -1,    50,    42,    51,    -1,
+      50,    35,    10,    91,    51,    -1,    50,    35,    51,    50,
+      35,    10,    91,    51,    -1,    88,    -1,    88,    50,    35,
+      10,    91,    51,    -1,    43,    89,    50,    90,    51,    -1,
+      43,     6,     7,    89,    50,    33,    51,    -1,    -1,     8,
+      91,    -1,     9,    91,    -1,    33,    -1,    42,    -1,    31,
+      -1,    30,    -1,    45,    -1,     9,    91,    -1,     8,    91,
+      -1,    53,    91,    -1,    50,    93,    51,    -1,    30,    -1,
+       9,    30,    -1,    30,     9,    30,    -1,     9,    30,     9,
+      30,    -1,    91,    -1,    93,     8,    93,    -1,    93,     9,
+      93,    -1,    93,    10,    93,    -1,    93,    11,    93,    -1,
+      93,    12,    93,    -1,    93,     6,     6,    93,    -1,    93,
+       7,     7,    93,    -1,    93,     5,    93,    -1,    93,     4,
+      93,    -1,    93,     3,    93,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
@@ -537,16 +537,16 @@ static const yytype_uint16 yyrline[] =
       86,    87,    90,    95,   101,   102,   103,   104,   105,   106,
      107,   108,   109,   110,   111,   112,   113,   114,   115,   116,
      117,   120,   124,   131,   138,   145,   150,   157,   162,   169,
-     174,   181,   189,   194,   202,   207,   214,   215,   218,   223,
-     233,   238,   248,   253,   258,   265,   273,   283,   287,   294,
-     299,   307,   308,   311,   312,   313,   317,   321,   322,   325,
-     326,   329,   335,   344,   353,   358,   363,   368,   373,   378,
-     383,   389,   397,   403,   414,   420,   426,   432,   438,   446,
-     447,   450,   456,   462,   468,   474,   483,   492,   497,   502,
-     510,   520,   524,   533,   540,   549,   552,   556,   562,   563,
-     567,   570,   571,   575,   579,   583,   587,   593,   597,   601,
-     606,   613,   614,   618,   622,   626,   630,   634,   638,   642,
-     646,   650
+     174,   179,   186,   194,   199,   207,   212,   219,   220,   223,
+     228,   238,   243,   253,   258,   263,   270,   278,   288,   292,
+     299,   304,   312,   313,   316,   317,   318,   322,   326,   327,
+     330,   331,   334,   340,   349,   358,   363,   368,   373,   378,
+     383,   388,   394,   402,   408,   419,   425,   431,   437,   443,
+     451,   452,   455,   461,   467,   473,   479,   488,   497,   502,
+     507,   515,   525,   529,   538,   545,   554,   557,   561,   567,
+     568,   572,   575,   576,   580,   584,   588,   592,   598,   602,
+     606,   611,   618,   619,   623,   627,   631,   635,   639,   643,
+     647,   651,   655
 };
 #endif
 
@@ -591,16 +591,16 @@ static const yytype_uint8 yyr1[] =
       57,    57,    60,    60,    60,    60,    60,    60,    60,    60,
       60,    60,    60,    60,    60,    60,    60,    60,    60,    60,
       60,    61,    61,    62,    63,    64,    64,    65,    65,    66,
-      66,    67,    68,    68,    69,    69,    70,    70,    71,    71,
-      72,    72,    73,    73,    73,    74,    75,    76,    76,    77,
-      77,    78,    78,    79,    79,    79,    79,    79,    79,    80,
-      80,    81,    81,    81,    82,    82,    82,    82,    82,    82,
-      82,    83,    84,    84,    84,    84,    84,    84,    84,    85,
-      85,    86,    86,    86,    86,    86,    86,    86,    86,    86,
-      86,    87,    87,    88,    88,    89,    89,    89,    90,    90,
-      90,    91,    91,    91,    91,    91,    91,    92,    92,    92,
-      92,    93,    93,    93,    93,    93,    93,    93,    93,    93,
-      93,    93
+      66,    66,    67,    68,    68,    69,    69,    70,    70,    71,
+      71,    72,    72,    73,    73,    73,    74,    75,    76,    76,
+      77,    77,    78,    78,    79,    79,    79,    79,    79,    79,
+      80,    80,    81,    81,    81,    82,    82,    82,    82,    82,
+      82,    82,    83,    84,    84,    84,    84,    84,    84,    84,
+      85,    85,    86,    86,    86,    86,    86,    86,    86,    86,
+      86,    86,    87,    87,    88,    88,    89,    89,    89,    90,
+      90,    90,    91,    91,    91,    91,    91,    91,    92,    92,
+      92,    92,    93,    93,    93,    93,    93,    93,    93,    93,
+      93,    93,    93
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -610,16 +610,16 @@ static const yytype_uint8 yyr2[] =
        2,     2,     3,     3,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     0,     1,     3,     3,     2,     1,     2,     1,     2,
-       1,     5,     3,     5,     2,     1,     1,     1,     3,     5,
-       3,     5,     2,     1,     3,     5,     5,     0,     1,     3,
-       5,     1,     1,     1,     1,     2,     2,     1,     1,     1,
-       1,     4,     2,     2,     1,     1,     1,     1,     1,     1,
-       1,     2,     2,     2,     2,     2,     4,     5,     3,     1,
-       1,     1,     4,     4,     4,     6,     9,     3,     3,     5,
-       8,     1,     6,     5,     7,     0,     2,     2,     1,     1,
-       1,     1,     1,     2,     2,     2,     3,     1,     2,     3,
-       4,     1,     3,     3,     3,     3,     3,     4,     4,     3,
-       3,     3
+       1,     3,     5,     3,     5,     2,     1,     1,     1,     3,
+       5,     3,     5,     2,     1,     3,     5,     5,     0,     1,
+       3,     5,     1,     1,     1,     1,     2,     2,     1,     1,
+       1,     1,     4,     2,     2,     1,     1,     1,     1,     1,
+       1,     1,     2,     2,     2,     2,     2,     4,     5,     3,
+       1,     1,     1,     4,     4,     4,     6,     9,     3,     3,
+       5,     8,     1,     6,     5,     7,     0,     2,     2,     1,
+       1,     1,     1,     1,     2,     2,     2,     3,     1,     2,
+       3,     4,     1,     3,     3,     3,     3,     3,     4,     4,
+       3,     3,     3
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -629,39 +629,40 @@ static const yytype_uint8 yydefact[] =
 {
        2,     3,     1,     0,     0,    31,     0,     0,     0,     0,
        0,     0,    31,     0,     0,     0,     0,     0,     0,     0,
-       0,    57,     0,     0,     0,     9,     4,     0,    11,    32,
-      14,     0,     0,   111,    74,    76,    79,    75,    77,    80,
-      78,   105,   112,     0,     0,     0,    15,    38,    61,    62,
-      89,    90,   101,    91,     0,    16,    69,    36,    70,    17,
-       0,    18,     0,     0,   105,   105,     0,    22,    45,    63,
-      67,    68,    64,    91,    20,     0,    32,    46,    47,    23,
-     105,     0,     0,    19,    40,     0,    21,     0,    30,     0,
-      24,     0,    25,     0,    26,    53,    27,     0,    28,     0,
-      29,    58,     7,     0,     5,     0,    10,   114,   113,     0,
-       0,     0,     0,    37,     0,     0,   121,     0,   115,     0,
-       0,     0,    85,    84,     0,    83,    82,    35,     0,     0,
-      65,    66,    72,    73,    44,     0,     0,    72,    39,     0,
-       0,     0,     0,     0,    52,     0,     0,     0,    12,     0,
-      13,   105,   106,   107,     0,     0,    97,    98,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   116,     0,
-       0,     0,     0,    88,     0,     0,    33,    34,     0,     0,
-       0,    42,     0,    59,     0,    48,    50,    54,     0,     0,
-       8,     6,     0,   110,   108,   109,     0,     0,     0,   131,
-     130,   129,     0,     0,   122,   123,   124,   125,   126,     0,
-       0,    92,    94,    93,     0,    86,    71,     0,     0,   117,
-      81,     0,     0,     0,     0,     0,     0,     0,   103,    99,
-       0,   127,   128,     0,     0,     0,    87,    41,   118,     0,
-      43,    60,    49,    51,    55,    56,     0,     0,   102,    95,
-       0,     0,   119,   104,     0,     0,   120,   100,     0,    96
+       0,    58,     0,     0,     0,     9,     4,     0,    11,    32,
+      14,     0,     0,   112,    75,    77,    80,    76,    78,    81,
+      79,   106,   113,     0,     0,     0,    15,    38,    62,    63,
+      90,    91,   102,    92,     0,    16,    70,    36,    71,    17,
+       0,    18,     0,     0,   106,   106,     0,    22,    46,    64,
+      68,    69,    65,    92,    20,     0,    32,    47,    48,    23,
+     106,     0,     0,    19,    40,     0,     0,    21,     0,    30,
+       0,    24,     0,    25,     0,    26,    54,    27,     0,    28,
+       0,    29,    59,     7,     0,     5,     0,    10,   115,   114,
+       0,     0,     0,     0,    37,     0,     0,   122,     0,   116,
+       0,     0,     0,    86,    85,     0,    84,    83,    35,     0,
+       0,    66,    67,    73,    74,    45,     0,     0,    73,    39,
+       0,     0,     0,     0,     0,     0,    53,     0,     0,     0,
+      12,     0,    13,   106,   107,   108,     0,     0,    98,    99,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     117,     0,     0,     0,     0,    89,     0,     0,    33,    34,
+       0,     0,    41,     0,    43,     0,    60,     0,    49,    51,
+      55,     0,     0,     8,     6,     0,   111,   109,   110,     0,
+       0,     0,   132,   131,   130,     0,     0,   123,   124,   125,
+     126,   127,     0,     0,    93,    95,    94,     0,    87,    72,
+       0,     0,   118,    82,     0,     0,     0,     0,     0,     0,
+       0,   104,   100,     0,   128,   129,     0,     0,     0,    88,
+      42,   119,     0,    44,    61,    50,    52,    56,    57,     0,
+       0,   103,    96,     0,     0,   120,   105,     0,     0,   121,
+     101,     0,    97
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     3,    26,   149,   147,    27,    30,    59,    61,
-      55,    46,    83,    74,    86,    67,    79,    90,    92,    94,
-      96,    98,   100,    88,    56,    68,    57,    69,    48,   181,
-      58,    49,    50,    51,    52,   112,   196,    53,   220,   117
+      -1,     1,     3,    26,   151,   149,    27,    30,    59,    61,
+      55,    46,    83,    74,    87,    67,    79,    91,    93,    95,
+      97,    99,   101,    89,    56,    68,    57,    69,    48,   184,
+      58,    49,    50,    51,    52,   113,   199,    53,   223,   118
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
@@ -669,41 +670,42 @@ static const yytype_int16 yydefgoto[] =
 #define YYPACT_NINF -97
 static const yytype_int16 yypact[] =
 {
-     -97,    29,   -97,   206,   -39,   -36,   254,   278,   278,   326,
-     230,    15,   302,    59,   412,   412,   278,   278,   278,    82,
-     -20,   -20,   -22,    -6,     2,   -97,   -97,    12,   -97,   -97,
-     -97,   476,   476,   -97,   -97,   -97,   -97,   -97,   -97,   -97,
-     -97,    88,   -97,   326,   366,   476,   -97,   -97,   -97,   -97,
-     -97,   -97,    14,    16,   364,   -97,   -97,    33,   -97,   -97,
-      39,   -97,    41,   350,    88,    11,   152,   -97,   -97,   -97,
-     -97,   -97,   -97,    31,   -97,    51,   326,   -97,   -97,   -97,
-      11,   382,   476,   -97,   -97,    42,   -97,    50,   -97,    56,
-     -97,    58,   -97,    61,   -97,    64,   -97,    66,   -97,    79,
-     -97,   -97,   -97,   476,   -97,   476,   -97,   -97,   -97,    84,
-     476,   476,    92,   -97,    18,    78,   -97,   129,   -97,   108,
-      -5,   414,   -97,   -97,   421,   -97,   -97,   -97,   326,   278,
-     -97,   -97,    92,   -97,   -97,    13,   476,   -97,   -97,   112,
-     428,   438,   326,   326,   326,   326,   326,   206,   527,   206,
-     527,    11,   -97,   -97,    10,   476,    96,   -97,   476,   476,
-     476,   141,   144,   476,   476,   476,   476,   476,   -97,   142,
-      23,   126,   127,   -97,   467,   128,   -97,   -97,   130,   110,
-       8,   -97,   114,   -97,   134,   138,   139,   -97,   149,   154,
-     -97,   -97,   163,   -97,   -97,   -97,   153,   165,   179,   536,
-     493,   159,   476,   476,    65,    65,   -97,   -97,   -97,   476,
-     476,   168,   -97,   -97,   185,   -97,   -97,   -20,   211,   233,
-     -97,   191,   -20,   209,   210,   476,    82,   214,   -97,   -97,
-     238,   200,   200,   201,   203,   220,   -97,   -97,   247,   227,
-     -97,   -97,   -97,   -97,   -97,   -97,   207,   476,   -97,   -97,
-     249,   231,   -97,   -97,   219,   476,   -97,   -97,   225,   -97
+     -97,    40,   -97,   208,     5,    -4,   140,   295,   295,   343,
+     233,    15,   319,   381,    91,    91,   295,   295,   295,   222,
+      24,    24,   -15,    22,    14,   -97,   -97,    30,   -97,   -97,
+     -97,   486,   486,   -97,   -97,   -97,   -97,   -97,   -97,   -97,
+     -97,    42,   -97,   343,   406,   486,   -97,   -97,   -97,   -97,
+     -97,   -97,    45,    48,   399,   -97,   -97,    20,   -97,   -97,
+      67,   -97,    68,   367,    42,    19,   271,   -97,   -97,   -97,
+     -97,   -97,   -97,    87,   -97,   127,   343,   -97,   -97,   -97,
+      19,   437,   486,   -97,   -97,    90,    92,   -97,    94,   -97,
+      96,   -97,   104,   -97,   105,   -97,   111,   -97,   118,   -97,
+     119,   -97,   -97,   -97,   486,   -97,   486,   -97,   -97,   -97,
+     133,   486,   486,   121,   -97,     8,   122,   -97,    80,   -97,
+     134,    78,   413,   -97,   -97,   446,   -97,   -97,   -97,   343,
+     295,   -97,   -97,   121,   -97,   -97,     7,   486,   -97,   -97,
+     437,   148,   453,   462,   343,   343,   343,   343,   343,   208,
+     284,   208,   284,    19,   -97,   -97,    -1,   486,   131,   -97,
+     486,   486,   486,   166,   177,   486,   486,   486,   486,   486,
+     -97,   176,    10,   136,   137,   -97,   480,   141,   -97,   -97,
+     143,   142,   -97,    16,   -97,   149,   -97,   150,   151,   154,
+     -97,   152,   155,   -97,   -97,   156,   -97,   -97,   -97,   157,
+     159,   170,    99,   535,   542,   486,   486,    26,    26,   -97,
+     -97,   -97,   486,   486,   161,   -97,   -97,   162,   -97,   -97,
+      24,   184,   198,   -97,   163,    24,   181,   183,   486,   222,
+     205,   -97,   -97,   229,   114,   114,   193,   194,   211,   -97,
+     -97,   238,   219,   -97,   -97,   -97,   -97,   -97,   -97,   199,
+     486,   -97,   -97,   244,   232,   -97,   -97,   214,   486,   -97,
+     -97,   215,   -97
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-     -97,   -97,   -97,   -96,   -97,   -97,   -97,   259,   -97,   -97,
-     -97,   265,   -97,   -97,   -97,   -97,   -97,   -97,   -97,   -97,
-     -97,   -97,   -97,   -97,    30,   212,    -2,   -11,    -9,    60,
-     -16,    32,    -3,    -1,     7,   -53,   -97,   -10,   -97,   -80
+     -97,   -97,   -97,   -96,   -97,   -97,   -97,   261,   -97,   -97,
+     -97,   262,   -97,   -97,   -97,   -97,   -97,   -97,   -97,   -97,
+     -97,   -97,   -97,   -97,    17,   218,    -2,   -11,    -9,    61,
+      -8,    51,     1,    -3,    -7,   -56,   -97,   -10,   -97,   -87
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -713,120 +715,122 @@ static const yytype_int16 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint16 yytable[] =
 {
-      73,    70,    84,    85,    99,   101,    60,    71,    28,    72,
-      97,   132,   133,    29,    91,    93,    95,   218,    75,   110,
-     111,   107,   108,   148,   102,   150,   103,   137,   155,     2,
-     170,   171,    54,   210,   116,   118,    47,   172,   219,    62,
-     104,   193,    47,   194,   126,   178,    87,    89,   170,   171,
-     105,   190,   195,   191,   130,   172,    73,    70,    41,   106,
-     131,   125,   136,    71,   119,    72,   120,    31,    32,   156,
-     138,    85,   116,   113,   211,   165,   166,   167,   199,   200,
-     201,   135,   127,   204,   205,   206,   207,   208,   128,    33,
-     129,   151,   139,   116,   109,   116,   110,   111,   192,   140,
-     152,   153,    80,    65,    42,   141,   113,   142,    81,    82,
-     143,   108,    45,   144,   116,   145,    34,    35,    36,    37,
-      38,    39,   231,   232,    40,   183,   179,   177,   146,   157,
-     182,   184,   158,   159,   160,   161,   162,   163,   164,   165,
-     166,   167,   154,   169,   178,   197,   198,   202,   116,   116,
-     116,   203,   209,   116,   116,   116,   116,   116,   176,   217,
-      31,    32,    63,   221,   108,   161,   162,   163,   164,   165,
-     166,   167,   185,   186,   187,   188,   189,   212,   213,   215,
-     168,   216,    33,   222,   223,   224,    34,    35,    36,    37,
-      38,    39,   116,   116,    40,    64,    65,    42,   225,   233,
-     234,   237,    44,   226,   228,    45,   241,     4,   163,   164,
-     165,   166,   167,   227,   230,   244,   229,   245,   235,     5,
-       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,   236,   254,    31,    32,
-      63,   238,   239,   180,   242,   258,   243,   246,   247,    22,
-      23,    24,   248,    25,   249,   250,   251,   252,   253,   255,
-      33,   256,    31,    32,    34,    35,    36,    37,    38,    39,
-     257,    77,    40,    64,    65,    42,   259,    78,   134,    66,
-      44,   240,     0,    45,    33,     0,    31,    32,    34,    35,
-      36,    37,    38,    39,     0,     0,    40,    41,     0,    42,
-       0,     0,     0,    43,    44,     0,     0,    45,    33,     0,
-      31,    32,    34,    35,    36,    37,    38,    39,     0,     0,
-      40,    41,     0,    42,     0,     0,     0,     0,    44,     0,
-      54,    45,    33,     0,    31,    32,    34,    35,    36,    37,
-      38,    39,     0,     0,    40,    41,     0,    42,     0,     0,
-       0,    76,    44,     0,     0,    45,    33,     0,    31,    32,
-      34,    35,    36,    37,    38,    39,     0,     0,    40,    41,
-       0,    42,    31,   121,    31,    32,    44,     0,     0,    45,
-      33,     0,     0,     0,    34,    35,    36,    37,    38,    39,
-      31,    32,    40,     0,    33,    42,    33,     0,     0,     0,
-      44,   114,     0,    45,   122,   123,     0,    41,   115,    42,
-       0,    42,    33,     0,   124,     0,    82,    45,     0,    45,
-      31,    32,    31,    32,     0,    80,    65,    42,     0,    31,
-     174,     0,    82,     0,     0,    45,    31,    32,     0,     0,
-       0,     0,    33,     0,    33,     0,    31,    32,     0,     0,
-       0,    33,     0,     0,   173,    41,     0,    42,    33,    42,
-       0,   175,    44,     0,    82,    45,    42,    45,    33,     0,
-       0,    82,     0,    42,    45,    31,    32,     0,    82,     0,
-     180,    45,     0,    42,    31,    32,     0,     0,    82,     0,
-      54,    45,     0,     0,     0,     0,     0,    33,   160,   161,
-     162,   163,   164,   165,   166,   167,    33,   214,     0,     0,
-       0,     0,    42,     0,     0,     0,     0,    82,     0,     0,
-      45,    42,     0,     0,     0,     0,    82,     0,     0,    45,
-     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
-     159,   160,   161,   162,   163,   164,   165,   166,   167
+      73,    70,    84,    86,    75,    85,    60,    72,   133,   134,
+      98,    71,   100,   102,    92,    94,    96,   150,   157,   152,
+     213,   108,   109,    47,   138,   221,    62,   111,   112,    47,
+     196,   103,   197,   104,   117,   119,   167,   168,   169,   180,
+       2,   198,   172,   173,   127,    29,   222,   126,   110,   174,
+     111,   112,    28,   193,   131,   194,    73,    70,    41,   158,
+     114,   214,   106,    72,   132,    88,    90,    71,   105,   128,
+     139,    86,   117,   202,   203,   204,    54,   107,   207,   208,
+     209,   210,   211,   160,   161,   162,   163,   164,   165,   166,
+     167,   168,   169,   114,   117,   120,   117,   195,   121,    31,
+      32,   154,   155,   161,   162,   163,   164,   165,   166,   167,
+     168,   169,   109,   172,   173,   117,   129,   130,   234,   235,
+     174,    33,   165,   166,   167,   168,   169,   181,   179,   182,
+      86,   170,   185,   187,    41,   186,    42,   136,   137,   140,
+     153,    44,   141,   142,    45,   143,   178,   200,    31,    32,
+     117,   117,   117,   144,   145,   117,   117,   117,   117,   117,
+     146,   188,   189,   190,   191,   192,   109,   147,   148,   171,
+      33,   156,   205,   159,    34,    35,    36,    37,    38,    39,
+     180,   201,    40,    41,   206,    42,   212,   215,   216,    43,
+      44,   220,   218,    45,   219,   117,   117,   226,   224,   225,
+     227,   228,   236,   237,   229,   233,   230,   242,   231,     4,
+     232,   238,   240,   239,   241,   183,   245,   244,   247,   246,
+     248,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,   249,   250,
+     257,    31,    32,    63,   251,   252,   253,   254,   261,   255,
+     256,    22,    23,    24,   258,    25,    34,    35,    36,    37,
+      38,    39,   259,    33,    40,   260,   262,    34,    35,    36,
+      37,    38,    39,    77,    78,    40,    64,    65,    42,    31,
+      32,    63,    66,    44,   135,   243,    45,   160,   161,   162,
+     163,   164,   165,   166,   167,   168,   169,     0,     0,     0,
+       0,    33,     0,    31,    32,    34,    35,    36,    37,    38,
+      39,     0,     0,    40,    64,    65,    42,     0,     0,     0,
+       0,    44,     0,     0,    45,    33,     0,    31,    32,    34,
+      35,    36,    37,    38,    39,     0,     0,    40,    41,     0,
+      42,     0,     0,     0,     0,    44,     0,    54,    45,    33,
+       0,    31,    32,    34,    35,    36,    37,    38,    39,     0,
+       0,    40,    41,     0,    42,     0,     0,     0,    76,    44,
+       0,     0,    45,    33,     0,    31,    32,    34,    35,    36,
+      37,    38,    39,     0,     0,    40,    41,     0,    42,    31,
+      32,     0,     0,    44,     0,     0,    45,    33,     0,     0,
+       0,    34,    35,    36,    37,    38,    39,    31,   122,    40,
+       0,    33,    42,     0,    31,    32,     0,    44,     0,     0,
+      45,    31,    32,     0,    80,    65,    42,     0,     0,    33,
+      81,    82,     0,    54,    45,     0,    33,     0,     0,   123,
+     124,   115,    41,    33,    42,    31,    32,     0,   116,   125,
+       0,    42,    45,   175,    31,   176,    82,     0,    42,    45,
+       0,    31,    32,    82,     0,     0,    45,    33,     0,     0,
+      31,    32,     0,     0,     0,     0,    33,     0,     0,     0,
+      80,    65,    42,    33,     0,     0,   177,    82,    31,    32,
+      45,    42,    33,     0,    31,    32,    82,     0,    42,    45,
+       0,     0,     0,    82,     0,   183,    45,    42,     0,     0,
+      33,     0,    82,     0,    54,    45,    33,     0,     0,     0,
+     217,     0,     0,     0,     0,    42,     0,     0,     0,     0,
+      82,    42,     0,    45,     0,     0,    82,     0,     0,    45,
+     162,   163,   164,   165,   166,   167,   168,   169,   163,   164,
+     165,   166,   167,   168,   169
 };
 
 static const yytype_int16 yycheck[] =
 {
-      10,    10,    13,    13,    20,    21,     8,    10,    47,    10,
-      19,    64,    65,    49,    16,    17,    18,     9,    11,     8,
-       9,    31,    32,   103,    46,   105,    48,    80,    10,     0,
-      35,    36,    52,    10,    44,    45,     6,    42,    30,     9,
-      46,    31,    12,    33,    54,    32,    14,    15,    35,    36,
-      48,   147,    42,   149,    63,    42,    66,    66,    43,    47,
-      63,    54,    11,    66,    50,    66,    50,     8,     9,    51,
-      81,    81,    82,    43,    51,    10,    11,    12,   158,   159,
-     160,    50,    49,   163,   164,   165,   166,   167,    49,    30,
-      49,     7,    50,   103,     6,   105,     8,     9,   151,    49,
-     110,   111,    43,    44,    45,    49,    76,    49,    49,    50,
-      49,   121,    53,    49,   124,    49,    34,    35,    36,    37,
-      38,    39,   202,   203,    42,   141,   136,   129,    49,    51,
-     140,   141,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    50,    35,    32,   155,    50,     6,   158,   159,
-     160,     7,    10,   163,   164,   165,   166,   167,   128,    49,
-       8,     9,    10,    49,   174,     6,     7,     8,     9,    10,
-      11,    12,   142,   143,   144,   145,   146,    51,    51,    51,
-      51,    51,    30,    49,    46,    46,    34,    35,    36,    37,
-      38,    39,   202,   203,    42,    43,    44,    45,    49,   209,
-     210,   217,    50,    49,    51,    53,   222,     1,     8,     9,
-      10,    11,    12,    50,    35,   225,    51,   226,    50,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    51,   247,     8,     9,
-      10,    30,     9,    52,    35,   255,    36,    33,    10,    43,
-      44,    45,    51,    47,    51,    35,     9,    30,    51,    10,
-      30,    30,     8,     9,    34,    35,    36,    37,    38,    39,
-      51,    12,    42,    43,    44,    45,    51,    12,    66,    49,
-      50,   221,    -1,    53,    30,    -1,     8,     9,    34,    35,
-      36,    37,    38,    39,    -1,    -1,    42,    43,    -1,    45,
-      -1,    -1,    -1,    49,    50,    -1,    -1,    53,    30,    -1,
-       8,     9,    34,    35,    36,    37,    38,    39,    -1,    -1,
-      42,    43,    -1,    45,    -1,    -1,    -1,    -1,    50,    -1,
-      52,    53,    30,    -1,     8,     9,    34,    35,    36,    37,
-      38,    39,    -1,    -1,    42,    43,    -1,    45,    -1,    -1,
-      -1,    49,    50,    -1,    -1,    53,    30,    -1,     8,     9,
-      34,    35,    36,    37,    38,    39,    -1,    -1,    42,    43,
-      -1,    45,     8,     9,     8,     9,    50,    -1,    -1,    53,
-      30,    -1,    -1,    -1,    34,    35,    36,    37,    38,    39,
-       8,     9,    42,    -1,    30,    45,    30,    -1,    -1,    -1,
-      50,    35,    -1,    53,    40,    41,    -1,    43,    42,    45,
-      -1,    45,    30,    -1,    50,    -1,    50,    53,    -1,    53,
-       8,     9,     8,     9,    -1,    43,    44,    45,    -1,     8,
-       9,    -1,    50,    -1,    -1,    53,     8,     9,    -1,    -1,
-      -1,    -1,    30,    -1,    30,    -1,     8,     9,    -1,    -1,
-      -1,    30,    -1,    -1,    40,    43,    -1,    45,    30,    45,
-      -1,    40,    50,    -1,    50,    53,    45,    53,    30,    -1,
-      -1,    50,    -1,    45,    53,     8,     9,    -1,    50,    -1,
-      52,    53,    -1,    45,     8,     9,    -1,    -1,    50,    -1,
-      52,    53,    -1,    -1,    -1,    -1,    -1,    30,     5,     6,
-       7,     8,     9,    10,    11,    12,    30,    40,    -1,    -1,
-      -1,    -1,    45,    -1,    -1,    -1,    -1,    50,    -1,    -1,
-      53,    45,    -1,    -1,    -1,    -1,    50,    -1,    -1,    53,
-       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-       4,     5,     6,     7,     8,     9,    10,    11,    12
+      10,    10,    13,    13,    11,    13,     8,    10,    64,    65,
+      19,    10,    20,    21,    16,    17,    18,   104,    10,   106,
+      10,    31,    32,     6,    80,     9,     9,     8,     9,    12,
+      31,    46,    33,    48,    44,    45,    10,    11,    12,    32,
+       0,    42,    35,    36,    54,    49,    30,    54,     6,    42,
+       8,     9,    47,   149,    63,   151,    66,    66,    43,    51,
+      43,    51,    48,    66,    63,    14,    15,    66,    46,    49,
+      81,    81,    82,   160,   161,   162,    52,    47,   165,   166,
+     167,   168,   169,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,    76,   104,    50,   106,   153,    50,     8,
+       9,   111,   112,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,   122,    35,    36,   125,    49,    49,   205,   206,
+      42,    30,     8,     9,    10,    11,    12,   137,   130,   140,
+     140,    51,   142,   143,    43,   143,    45,    50,    11,    49,
+       7,    50,    50,    49,    53,    49,   129,   157,     8,     9,
+     160,   161,   162,    49,    49,   165,   166,   167,   168,   169,
+      49,   144,   145,   146,   147,   148,   176,    49,    49,    35,
+      30,    50,     6,    51,    34,    35,    36,    37,    38,    39,
+      32,    50,    42,    43,     7,    45,    10,    51,    51,    49,
+      50,    49,    51,    53,    51,   205,   206,    46,    49,    49,
+      46,    49,   212,   213,    49,    35,    50,     9,    51,     1,
+      51,    50,   220,    51,    30,    52,    35,   225,   228,    36,
+     229,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    33,    10,
+     250,     8,     9,    10,    51,    51,    35,     9,   258,    30,
+      51,    43,    44,    45,    10,    47,    34,    35,    36,    37,
+      38,    39,    30,    30,    42,    51,    51,    34,    35,    36,
+      37,    38,    39,    12,    12,    42,    43,    44,    45,     8,
+       9,    10,    49,    50,    66,   224,    53,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    -1,    -1,    -1,
+      -1,    30,    -1,     8,     9,    34,    35,    36,    37,    38,
+      39,    -1,    -1,    42,    43,    44,    45,    -1,    -1,    -1,
+      -1,    50,    -1,    -1,    53,    30,    -1,     8,     9,    34,
+      35,    36,    37,    38,    39,    -1,    -1,    42,    43,    -1,
+      45,    -1,    -1,    -1,    -1,    50,    -1,    52,    53,    30,
+      -1,     8,     9,    34,    35,    36,    37,    38,    39,    -1,
+      -1,    42,    43,    -1,    45,    -1,    -1,    -1,    49,    50,
+      -1,    -1,    53,    30,    -1,     8,     9,    34,    35,    36,
+      37,    38,    39,    -1,    -1,    42,    43,    -1,    45,     8,
+       9,    -1,    -1,    50,    -1,    -1,    53,    30,    -1,    -1,
+      -1,    34,    35,    36,    37,    38,    39,     8,     9,    42,
+      -1,    30,    45,    -1,     8,     9,    -1,    50,    -1,    -1,
+      53,     8,     9,    -1,    43,    44,    45,    -1,    -1,    30,
+      49,    50,    -1,    52,    53,    -1,    30,    -1,    -1,    40,
+      41,    35,    43,    30,    45,     8,     9,    -1,    42,    50,
+      -1,    45,    53,    40,     8,     9,    50,    -1,    45,    53,
+      -1,     8,     9,    50,    -1,    -1,    53,    30,    -1,    -1,
+       8,     9,    -1,    -1,    -1,    -1,    30,    -1,    -1,    -1,
+      43,    44,    45,    30,    -1,    -1,    40,    50,     8,     9,
+      53,    45,    30,    -1,     8,     9,    50,    -1,    45,    53,
+      -1,    -1,    -1,    50,    -1,    52,    53,    45,    -1,    -1,
+      30,    -1,    50,    -1,    52,    53,    30,    -1,    -1,    -1,
+      40,    -1,    -1,    -1,    -1,    45,    -1,    -1,    -1,    -1,
+      50,    45,    -1,    53,    -1,    -1,    50,    -1,    -1,    53,
+       5,     6,     7,     8,     9,    10,    11,    12,     6,     7,
+       8,     9,    10,    11,    12
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -841,24 +845,25 @@ static const yytype_uint8 yystos[] =
       86,    87,    88,    91,    52,    64,    78,    80,    84,    62,
       80,    63,    78,    10,    43,    44,    49,    69,    79,    81,
       82,    86,    87,    91,    67,    88,    49,    61,    65,    70,
-      43,    49,    50,    66,    81,    91,    68,    85,    77,    85,
-      71,    80,    72,    80,    73,    80,    74,    82,    75,    84,
-      76,    84,    46,    48,    46,    48,    47,    91,    91,     6,
-       8,     9,    89,    78,    35,    42,    91,    93,    91,    50,
-      50,     9,    40,    41,    50,    88,    91,    49,    49,    49,
-      82,    86,    89,    89,    79,    50,    11,    89,    81,    50,
-      49,    49,    49,    49,    49,    49,    49,    59,    93,    58,
-      93,     7,    91,    91,    50,    10,    51,    51,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    51,    35,
-      35,    36,    42,    40,     9,    40,    78,    80,    32,    91,
-      52,    83,    91,    84,    91,    78,    78,    78,    78,    78,
-      57,    57,    89,    31,    33,    42,    90,    91,    50,    93,
-      93,    93,     6,     7,    93,    93,    93,    93,    93,    10,
-      10,    51,    51,    51,    40,    51,    51,    49,     9,    30,
-      92,    49,    49,    46,    46,    49,    49,    50,    51,    51,
-      35,    93,    93,    91,    91,    50,    51,    84,    30,     9,
-      83,    84,    35,    36,    91,    82,    33,    10,    51,    51,
-      35,     9,    30,    51,    91,    10,    30,    51,    91,    51
+      43,    49,    50,    66,    81,    84,    91,    68,    85,    77,
+      85,    71,    80,    72,    80,    73,    80,    74,    82,    75,
+      84,    76,    84,    46,    48,    46,    48,    47,    91,    91,
+       6,     8,     9,    89,    78,    35,    42,    91,    93,    91,
+      50,    50,     9,    40,    41,    50,    88,    91,    49,    49,
+      49,    82,    86,    89,    89,    79,    50,    11,    89,    81,
+      49,    50,    49,    49,    49,    49,    49,    49,    49,    59,
+      93,    58,    93,     7,    91,    91,    50,    10,    51,    51,
+       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      51,    35,    35,    36,    42,    40,     9,    40,    78,    80,
+      32,    91,    81,    52,    83,    91,    84,    91,    78,    78,
+      78,    78,    78,    57,    57,    89,    31,    33,    42,    90,
+      91,    50,    93,    93,    93,     6,     7,    93,    93,    93,
+      93,    93,    10,    10,    51,    51,    51,    40,    51,    51,
+      49,     9,    30,    92,    49,    49,    46,    46,    49,    49,
+      50,    51,    51,    35,    93,    93,    91,    91,    50,    51,
+      84,    30,     9,    83,    84,    35,    36,    91,    82,    33,
+      10,    51,    51,    35,     9,    30,    51,    91,    10,    30,
+      51,    91,    51
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -1879,7 +1884,15 @@ yyreduce:
     break;
 
   case 41:
-#line 182 "a.y"
+#line 180 "a.y"
+    {
+		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
+		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
+	}
+    break;
+
+  case 42:
+#line 187 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -1887,16 +1900,16 @@ yyreduce:
 	}
     break;
 
-  case 42:
-#line 190 "a.y"
+  case 43:
+#line 195 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 43:
-#line 195 "a.y"
+  case 44:
+#line 200 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -1904,32 +1917,32 @@ yyreduce:
 	}
     break;
 
-  case 44:
-#line 203 "a.y"
+  case 45:
+#line 208 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
 	}
     break;
 
-  case 45:
-#line 208 "a.y"
+  case 46:
+#line 213 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = (yyvsp[(1) - (1)].gen);
 	}
     break;
 
-  case 48:
-#line 219 "a.y"
+  case 49:
+#line 224 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 49:
-#line 224 "a.y"
+  case 50:
+#line 229 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -1939,16 +1952,16 @@ yyreduce:
 	}
     break;
 
-  case 50:
-#line 234 "a.y"
+  case 51:
+#line 239 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 51:
-#line 239 "a.y"
+  case 52:
+#line 244 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -1958,32 +1971,32 @@ yyreduce:
 	}
     break;
 
-  case 52:
-#line 249 "a.y"
+  case 53:
+#line 254 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (2)].gen);
 		(yyval.gen2).to = nullgen;
 	}
     break;
 
-  case 53:
-#line 254 "a.y"
+  case 54:
+#line 259 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (1)].gen);
 		(yyval.gen2).to = nullgen;
 	}
     break;
 
-  case 54:
-#line 259 "a.y"
+  case 55:
+#line 264 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 55:
-#line 266 "a.y"
+  case 56:
+#line 271 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -1991,8 +2004,8 @@ yyreduce:
 	}
     break;
 
-  case 56:
-#line 274 "a.y"
+  case 57:
+#line 279 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(3) - (5)].gen);
 		(yyval.gen2).to = (yyvsp[(5) - (5)].gen);
@@ -2002,32 +2015,32 @@ yyreduce:
 	}
     break;
 
-  case 57:
-#line 283 "a.y"
+  case 58:
+#line 288 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = nullgen;
 	}
     break;
 
-  case 58:
-#line 288 "a.y"
+  case 59:
+#line 293 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (1)].gen);
 		(yyval.gen2).to = nullgen;
 	}
     break;
 
-  case 59:
-#line 295 "a.y"
+  case 60:
+#line 300 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 60:
-#line 300 "a.y"
+  case 61:
+#line 305 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -2035,22 +2048,22 @@ yyreduce:
 	}
     break;
 
-  case 65:
-#line 314 "a.y"
+  case 66:
+#line 319 "a.y"
     {
 		(yyval.gen) = (yyvsp[(2) - (2)].gen);
 	}
     break;
 
-  case 66:
-#line 318 "a.y"
+  case 67:
+#line 323 "a.y"
     {
 		(yyval.gen) = (yyvsp[(2) - (2)].gen);
 	}
     break;
 
-  case 71:
-#line 330 "a.y"
+  case 72:
+#line 335 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_BRANCH;
@@ -2058,8 +2071,8 @@ yyreduce:
 	}
     break;
 
-  case 72:
-#line 336 "a.y"
+  case 73:
+#line 341 "a.y"
     {
 		(yyval.gen) = nullgen;
 		if(pass == 2)
@@ -2070,8 +2083,8 @@ yyreduce:
 	}
     break;
 
-  case 73:
-#line 345 "a.y"
+  case 74:
+#line 350 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_BRANCH;
@@ -2080,14 +2093,6 @@ yyreduce:
 	}
     break;
 
-  case 74:
-#line 354 "a.y"
-    {
-		(yyval.gen) = nullgen;
-		(yyval.gen).type = (yyvsp[(1) - (1)].lval);
-	}
-    break;
-
   case 75:
 #line 359 "a.y"
     {
@@ -2116,7 +2121,7 @@ yyreduce:
 #line 374 "a.y"
     {
 		(yyval.gen) = nullgen;
-		(yyval.gen).type = D_SP;
+		(yyval.gen).type = (yyvsp[(1) - (1)].lval);
 	}
     break;
 
@@ -2124,7 +2129,7 @@ yyreduce:
 #line 379 "a.y"
     {
 		(yyval.gen) = nullgen;
-		(yyval.gen).type = (yyvsp[(1) - (1)].lval);
+		(yyval.gen).type = D_SP;
 	}
     break;
 
@@ -2137,16 +2142,15 @@ yyreduce:
     break;
 
   case 81:
-#line 390 "a.y"
+#line 389 "a.y"
     {
 		(yyval.gen) = nullgen;
-		(yyval.gen).type = D_CONST;
-		(yyval.gen).offset = (yyvsp[(2) - (2)].lval);
+		(yyval.gen).type = (yyvsp[(1) - (1)].lval);
 	}
     break;
 
   case 82:
-#line 398 "a.y"
+#line 395 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_CONST;
@@ -2155,7 +2159,16 @@ yyreduce:
     break;
 
   case 83:
-#line 404 "a.y"
+#line 403 "a.y"
+    {
+		(yyval.gen) = nullgen;
+		(yyval.gen).type = D_CONST;
+		(yyval.gen).offset = (yyvsp[(2) - (2)].lval);
+	}
+    break;
+
+  case 84:
+#line 409 "a.y"
     {
 		(yyval.gen) = (yyvsp[(2) - (2)].gen);
 		(yyval.gen).index = (yyvsp[(2) - (2)].gen).type;
@@ -2168,8 +2181,8 @@ yyreduce:
 	}
     break;
 
-  case 84:
-#line 415 "a.y"
+  case 85:
+#line 420 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_SCONST;
@@ -2177,8 +2190,8 @@ yyreduce:
 	}
     break;
 
-  case 85:
-#line 421 "a.y"
+  case 86:
+#line 426 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FCONST;
@@ -2186,8 +2199,8 @@ yyreduce:
 	}
     break;
 
-  case 86:
-#line 427 "a.y"
+  case 87:
+#line 432 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FCONST;
@@ -2195,8 +2208,8 @@ yyreduce:
 	}
     break;
 
-  case 87:
-#line 433 "a.y"
+  case 88:
+#line 438 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FCONST;
@@ -2204,8 +2217,8 @@ yyreduce:
 	}
     break;
 
-  case 88:
-#line 439 "a.y"
+  case 89:
+#line 444 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FCONST;
@@ -2213,8 +2226,8 @@ yyreduce:
 	}
     break;
 
-  case 91:
-#line 451 "a.y"
+  case 92:
+#line 456 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_NONE;
@@ -2222,8 +2235,8 @@ yyreduce:
 	}
     break;
 
-  case 92:
-#line 457 "a.y"
+  case 93:
+#line 462 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2231,8 +2244,8 @@ yyreduce:
 	}
     break;
 
-  case 93:
-#line 463 "a.y"
+  case 94:
+#line 468 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_SP;
@@ -2240,8 +2253,8 @@ yyreduce:
 	}
     break;
 
-  case 94:
-#line 469 "a.y"
+  case 95:
+#line 474 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2249,8 +2262,8 @@ yyreduce:
 	}
     break;
 
-  case 95:
-#line 475 "a.y"
+  case 96:
+#line 480 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_NONE;
@@ -2261,8 +2274,8 @@ yyreduce:
 	}
     break;
 
-  case 96:
-#line 484 "a.y"
+  case 97:
+#line 489 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(3) - (9)].lval);
@@ -2273,24 +2286,24 @@ yyreduce:
 	}
     break;
 
-  case 97:
-#line 493 "a.y"
+  case 98:
+#line 498 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(2) - (3)].lval);
 	}
     break;
 
-  case 98:
-#line 498 "a.y"
+  case 99:
+#line 503 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_SP;
 	}
     break;
 
-  case 99:
-#line 503 "a.y"
+  case 100:
+#line 508 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_NONE;
@@ -2300,8 +2313,8 @@ yyreduce:
 	}
     break;
 
-  case 100:
-#line 511 "a.y"
+  case 101:
+#line 516 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(2) - (8)].lval);
@@ -2311,15 +2324,15 @@ yyreduce:
 	}
     break;
 
-  case 101:
-#line 521 "a.y"
+  case 102:
+#line 526 "a.y"
     {
 		(yyval.gen) = (yyvsp[(1) - (1)].gen);
 	}
     break;
 
-  case 102:
-#line 525 "a.y"
+  case 103:
+#line 530 "a.y"
     {
 		(yyval.gen) = (yyvsp[(1) - (6)].gen);
 		(yyval.gen).index = (yyvsp[(3) - (6)].lval);
@@ -2328,8 +2341,8 @@ yyreduce:
 	}
     break;
 
-  case 103:
-#line 534 "a.y"
+  case 104:
+#line 539 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = (yyvsp[(4) - (5)].lval);
@@ -2338,8 +2351,8 @@ yyreduce:
 	}
     break;
 
-  case 104:
-#line 541 "a.y"
+  case 105:
+#line 546 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_STATIC;
@@ -2348,164 +2361,164 @@ yyreduce:
 	}
     break;
 
-  case 105:
-#line 549 "a.y"
+  case 106:
+#line 554 "a.y"
     {
 		(yyval.lval) = 0;
 	}
     break;
 
-  case 106:
-#line 553 "a.y"
+  case 107:
+#line 558 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 107:
-#line 557 "a.y"
+  case 108:
+#line 562 "a.y"
     {
 		(yyval.lval) = -(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 109:
-#line 564 "a.y"
+  case 110:
+#line 569 "a.y"
     {
 		(yyval.lval) = D_AUTO;
 	}
     break;
 
-  case 112:
-#line 572 "a.y"
+  case 113:
+#line 577 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
 	}
     break;
 
-  case 113:
-#line 576 "a.y"
+  case 114:
+#line 581 "a.y"
     {
 		(yyval.lval) = -(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 114:
-#line 580 "a.y"
+  case 115:
+#line 585 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 115:
-#line 584 "a.y"
+  case 116:
+#line 589 "a.y"
     {
 		(yyval.lval) = ~(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 116:
-#line 588 "a.y"
+  case 117:
+#line 593 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (3)].lval);
 	}
     break;
 
-  case 117:
-#line 594 "a.y"
+  case 118:
+#line 599 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (1)].lval) & 0xffffffffLL;
 	}
     break;
 
-  case 118:
-#line 598 "a.y"
+  case 119:
+#line 603 "a.y"
     {
 		(yyval.lval) = -(yyvsp[(2) - (2)].lval) & 0xffffffffLL;
 	}
     break;
 
-  case 119:
-#line 602 "a.y"
+  case 120:
+#line 607 "a.y"
     {
 		(yyval.lval) = ((yyvsp[(1) - (3)].lval) & 0xffffffffLL) +
 			(((yyvsp[(3) - (3)].lval) & 0xffffLL) << 32);
 	}
     break;
 
-  case 120:
-#line 607 "a.y"
+  case 121:
+#line 612 "a.y"
     {
 		(yyval.lval) = (-(yyvsp[(2) - (4)].lval) & 0xffffffffLL) +
 			(((yyvsp[(4) - (4)].lval) & 0xffffLL) << 32);
 	}
     break;
 
-  case 122:
-#line 615 "a.y"
+  case 123:
+#line 620 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 123:
-#line 619 "a.y"
+  case 124:
+#line 624 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 124:
-#line 623 "a.y"
+  case 125:
+#line 628 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 125:
-#line 627 "a.y"
+  case 126:
+#line 632 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 126:
-#line 631 "a.y"
+  case 127:
+#line 636 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 127:
-#line 635 "a.y"
+  case 128:
+#line 640 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
 	}
     break;
 
-  case 128:
-#line 639 "a.y"
+  case 129:
+#line 644 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
 	}
     break;
 
-  case 129:
-#line 643 "a.y"
+  case 130:
+#line 648 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 130:
-#line 647 "a.y"
+  case 131:
+#line 652 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 131:
-#line 651 "a.y"
+  case 132:
+#line 656 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
 	}
@@ -2513,7 +2526,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 2517 "y.tab.c"
+#line 2530 "y.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c
index 7182258..95400c4 100644
--- a/src/cmd/6c/cgen.c
+++ b/src/cmd/6c/cgen.c
@@ -265,6 +265,18 @@ cgen(Node *n, Node *nn)
 				break;
 			}
 		}
+		if(n->op == OOR && l->op == OASHL && r->op == OLSHR
+		&& l->right->op == OCONST && r->right->op == OCONST
+		&& l->left->op == ONAME && r->left->op == ONAME
+		&& l->left->sym == r->left->sym
+		&& l->right->vconst + r->right->vconst == 8 * l->left->type->width) {
+			regalloc(&nod, l->left, nn);
+			cgen(l->left, &nod);
+			gopcode(OROTL, n->type, l->right, &nod);
+			gmove(&nod, nn);
+			regfree(&nod);
+			break;
+		}
 		if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
 		&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
 			c = l->right->vconst;
@@ -1672,7 +1684,7 @@ copy:
 		regsalloc(&nod2, nn);
 		nn->type = t;
 
-		gins(AMOVL, &nod1, &nod2);
+		gins(AMOVQ, &nod1, &nod2);
 		regfree(&nod1);
 
 		nod2.type = typ(TIND, t);
diff --git a/src/cmd/6c/doc.go b/src/cmd/6c/doc.go
index 249a8ed..e0a22e7 100644
--- a/src/cmd/6c/doc.go
+++ b/src/cmd/6c/doc.go
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build ignore
+
 /*
 
 6c is a version of the Plan 9 C compiler.  The original is documented at
 
-	http://plan9.bell-labs.com/magic/man2html/1/2c
+	http://plan9.bell-labs.com/magic/man2html/1/8c
 
 Its target architecture is the x86-64, referred to by these tools as amd64.
 
 */
-package documentation
+package main
diff --git a/src/cmd/6c/gc.h b/src/cmd/6c/gc.h
index b0081ab..d1133ee 100644
--- a/src/cmd/6c/gc.h
+++ b/src/cmd/6c/gc.h
@@ -292,6 +292,7 @@ void	gbranch(int);
 void	patch(Prog*, int32);
 int	sconst(Node*);
 void	gpseudo(int, Sym*, Node*);
+void	gprefetch(Node*);
 
 /*
  * swt.c
@@ -366,8 +367,6 @@ int	BtoF(int32);
 #define	D_HI	D_NONE
 #define	D_LO	D_NONE
 
-#define	isregtype(t)	((t)>= D_AX && (t)<=D_R15)
-
 /*
  * bound
  */
diff --git a/src/cmd/6c/list.c b/src/cmd/6c/list.c
index 4293203..b5a60ac 100644
--- a/src/cmd/6c/list.c
+++ b/src/cmd/6c/list.c
@@ -93,7 +93,7 @@ Pconv(Fmt *fp)
 		break;
 
 	default:
-		sprint(str, "(%L)	%A	%D,%lD",
+		sprint(str, "(%L)	%A	%D,%D",
 			p->lineno, p->as, &p->from, &p->to);
 		break;
 	}
@@ -120,13 +120,12 @@ Dconv(Fmt *fp)
 	i = a->type;
 
 	if(fp->flags & FmtLong) {
-		if(i != D_CONST) {
+		if(i == D_CONST)
+			sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
+		else {
 			// ATEXT dst is not constant
 			sprint(str, "!!%D", a);
-			goto brk;
 		}
-		sprint(str, "$%lld-%lld", a->offset&0xffffffffLL,
-			(a->offset>>32)&0xffffffffLL);
 		goto brk;
 	}
 
@@ -138,7 +137,6 @@ Dconv(Fmt *fp)
 		goto brk;
 	}
 	switch(i) {
-
 	default:
 		if(a->offset)
 			sprint(str, "$%lld,%R", a->offset, i);
@@ -151,7 +149,7 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_BRANCH:
-		sprint(str, "%lld(PC)", a->offset-pc);
+		sprint(str, "%lld", a->offset);
 		break;
 
 	case D_EXTERN:
@@ -159,24 +157,21 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_STATIC:
-		sprint(str, "%s<>+%lld(SB)", a->sym->name,
-			a->offset);
+		sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
 		break;
 
 	case D_AUTO:
-		if(a->sym) {
+		if(a->sym)
 			sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
-			break;
-		}
-		sprint(str, "%lld(SP)", a->offset);
+		else
+			sprint(str, "%lld(SP)", a->offset);
 		break;
 
 	case D_PARAM:
-		if(a->sym) {
+		if(a->sym)
 			sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
-			break;
-		}
-		sprint(str, "%lld(FP)", a->offset);
+		else
+			sprint(str, "%lld(FP)", a->offset);
 		break;
 
 	case D_CONST:
@@ -210,7 +205,7 @@ conv:
 
 char*	regstr[] =
 {
-	"AL",		/* [D_AL] */
+	"AL",	/* [D_AL] */
 	"CL",
 	"DL",
 	"BL",
@@ -227,7 +222,7 @@ char*	regstr[] =
 	"R14B",
 	"R15B",
 
-	"AX",		/* [D_AX] */
+	"AX",	/* [D_AX] */
 	"CX",
 	"DX",
 	"BX",
@@ -249,7 +244,7 @@ char*	regstr[] =
 	"DH",
 	"BH",
 
-	"F0",		/* [D_F0] */
+	"F0",	/* [D_F0] */
 	"F1",
 	"F2",
 	"F3",
@@ -284,20 +279,20 @@ char*	regstr[] =
 	"X14",
 	"X15",
 
-	"CS",		/* [D_CS] */
+	"CS",	/* [D_CS] */
 	"SS",
 	"DS",
 	"ES",
 	"FS",
 	"GS",
 
-	"GDTR",		/* [D_GDTR] */
-	"IDTR",		/* [D_IDTR] */
-	"LDTR",		/* [D_LDTR] */
-	"MSW",		/* [D_MSW] */
-	"TASK",		/* [D_TASK] */
+	"GDTR",	/* [D_GDTR] */
+	"IDTR",	/* [D_IDTR] */
+	"LDTR",	/* [D_LDTR] */
+	"MSW",	/* [D_MSW] */
+	"TASK",	/* [D_TASK] */
 
-	"CR0",		/* [D_CR] */
+	"CR0",	/* [D_CR] */
 	"CR1",
 	"CR2",
 	"CR3",
@@ -314,7 +309,7 @@ char*	regstr[] =
 	"CR14",
 	"CR15",
 
-	"DR0",		/* [D_DR] */
+	"DR0",	/* [D_DR] */
 	"DR1",
 	"DR2",
 	"DR3",
@@ -323,7 +318,7 @@ char*	regstr[] =
 	"DR6",
 	"DR7",
 
-	"TR0",		/* [D_TR] */
+	"TR0",	/* [D_TR] */
 	"TR1",
 	"TR2",
 	"TR3",
@@ -332,7 +327,7 @@ char*	regstr[] =
 	"TR6",
 	"TR7",
 
-	"NONE",		/* [D_NONE] */
+	"NONE",	/* [D_NONE] */
 };
 
 int
diff --git a/src/cmd/6c/mul.c b/src/cmd/6c/mul.c
index ab6883e..510edc0 100644
--- a/src/cmd/6c/mul.c
+++ b/src/cmd/6c/mul.c
@@ -35,17 +35,17 @@ typedef struct	Mparam	Mparam;
 
 struct	Malg
 {
-	char	vals[10];
+	schar	vals[10];
 };
 
 struct	Mparam
 {
 	uint32	value;
-	char	alg;
+	schar	alg;
 	char	neg;
 	char	shift;
 	char	arg;
-	char	off;
+	schar	off;
 };
 
 static	Mparam	multab[32];
@@ -101,7 +101,7 @@ mulparam(uint32 m, Mparam *mp)
 {
 	int c, i, j, n, o, q, s;
 	int bc, bi, bn, bo, bq, bs, bt;
-	char *p;
+	schar *p;
 	int32 u;
 	uint32 t;
 
diff --git a/src/cmd/6c/peep.c b/src/cmd/6c/peep.c
index 8b82adb..c648d8c 100644
--- a/src/cmd/6c/peep.c
+++ b/src/cmd/6c/peep.c
@@ -330,20 +330,7 @@ subprop(Reg *r0)
 		case AIMULW:
 			if(p->to.type != D_NONE)
 				break;
-
-		case ADIVB:
-		case ADIVL:
-		case ADIVQ:
-		case ADIVW:
-		case AIDIVB:
-		case AIDIVL:
-		case AIDIVQ:
-		case AIDIVW:
-		case AIMULB:
-		case AMULB:
-		case AMULL:
-		case AMULQ:
-		case AMULW:
+			goto giveup;
 
 		case AROLB:
 		case AROLL:
@@ -369,6 +356,23 @@ subprop(Reg *r0)
 		case ASHRL:
 		case ASHRQ:
 		case ASHRW:
+			if(p->from.type == D_CONST)
+				break;
+			goto giveup;
+
+		case ADIVB:
+		case ADIVL:
+		case ADIVQ:
+		case ADIVW:
+		case AIDIVB:
+		case AIDIVL:
+		case AIDIVQ:
+		case AIDIVW:
+		case AIMULB:
+		case AMULB:
+		case AMULL:
+		case AMULQ:
+		case AMULW:
 
 		case AREP:
 		case AREPN:
@@ -383,6 +387,8 @@ subprop(Reg *r0)
 		case AMOVSB:
 		case AMOVSL:
 		case AMOVSQ:
+		case AMOVQL:
+		giveup:
 			return 0;
 
 		case AMOVL:
@@ -581,6 +587,7 @@ copyu(Prog *p, Adr *v, Adr *s)
 	case AMOVWLZX:
 	case AMOVWQSX:
 	case AMOVWQZX:
+	case AMOVQL:
 
 	case AMOVSS:
 	case AMOVSD:
@@ -695,6 +702,11 @@ copyu(Prog *p, Adr *v, Adr *s)
 	case ACMPB:
 	case ACMPQ:
 
+	case APREFETCHT0:
+	case APREFETCHT1:
+	case APREFETCHT2:
+	case APREFETCHNTA:
+
 	case ACOMISD:
 	case ACOMISS:
 	case AUCOMISD:
diff --git a/src/cmd/6c/reg.c b/src/cmd/6c/reg.c
index 996128f..e40e6c8 100644
--- a/src/cmd/6c/reg.c
+++ b/src/cmd/6c/reg.c
@@ -30,6 +30,8 @@
 
 #include "gc.h"
 
+static	void	fixjmp(Reg*);
+
 Reg*
 rega(void)
 {
@@ -185,6 +187,10 @@ regopt(Prog *p)
 		case ACMPL:
 		case ACMPQ:
 		case ACMPW:
+		case APREFETCHT0:
+		case APREFETCHT1:
+		case APREFETCHT2:
+		case APREFETCHNTA:
 		case ACOMISS:
 		case ACOMISD:
 		case AUCOMISS:
@@ -211,6 +217,7 @@ regopt(Prog *p)
 		case AMOVWLZX:
 		case AMOVWQSX:
 		case AMOVWQZX:
+		case AMOVQL:
 
 		case AMOVSS:
 		case AMOVSD:
@@ -438,6 +445,12 @@ regopt(Prog *p)
 	}
 
 	/*
+	 * pass 2.1
+	 * fix jumps
+	 */
+	fixjmp(firstr);
+
+	/*
 	 * pass 2.5
 	 * find looping structure
 	 */
@@ -1384,3 +1397,126 @@ BtoF(int32 b)
 		return 0;
 	return bitno(b) - 16 + FREGMIN;
 }
+
+/* what instruction does a JMP to p eventually land on? */
+static Reg*
+chasejmp(Reg *r, int *jmploop)
+{
+	int n;
+
+	n = 0;
+	for(; r; r=r->s2) {
+		if(r->prog->as != AJMP || r->prog->to.type != D_BRANCH)
+			break;
+		if(++n > 10) {
+			*jmploop = 1;
+			break;
+		}
+	}
+	return r;
+}
+
+/* mark all code reachable from firstp as alive */
+static void
+mark(Reg *firstr)
+{
+	Reg *r;
+	Prog *p;
+
+	for(r=firstr; r; r=r->link) {
+		if(r->active)
+			break;
+		r->active = 1;
+		p = r->prog;
+		if(p->as != ACALL && p->to.type == D_BRANCH)
+			mark(r->s2);
+		if(p->as == AJMP || p->as == ARET || p->as == AUNDEF)
+			break;
+	}
+}
+
+/*
+ * the code generator depends on being able to write out JMP
+ * instructions that it can jump to now but fill in later.
+ * the linker will resolve them nicely, but they make the code
+ * longer and more difficult to follow during debugging.
+ * remove them.
+ */
+static void
+fixjmp(Reg *firstr)
+{
+	int jmploop;
+	Reg *r;
+	Prog *p;
+
+	if(debug['R'] && debug['v'])
+		print("\nfixjmp\n");
+
+	// pass 1: resolve jump to AJMP, mark all code as dead.
+	jmploop = 0;
+	for(r=firstr; r; r=r->link) {
+		p = r->prog;
+		if(debug['R'] && debug['v'])
+			print("%04d %P\n", r->pc, p);
+		if(p->as != ACALL && p->to.type == D_BRANCH && r->s2 && r->s2->prog->as == AJMP) {
+			r->s2 = chasejmp(r->s2, &jmploop);
+			p->to.offset = r->s2->pc;
+			if(debug['R'] && debug['v'])
+				print("->%P\n", p);
+		}
+		r->active = 0;
+	}
+	if(debug['R'] && debug['v'])
+		print("\n");
+
+	// pass 2: mark all reachable code alive
+	mark(firstr);
+
+	// pass 3: delete dead code (mostly JMPs).
+	for(r=firstr; r; r=r->link) {
+		if(!r->active) {
+			p = r->prog;
+			if(p->link == P && p->as == ARET && r->p1 && r->p1->prog->as != ARET) {
+				// This is the final ARET, and the code so far doesn't have one.
+				// Let it stay.
+			} else {
+				if(debug['R'] && debug['v'])
+					print("del %04d %P\n", r->pc, p);
+				p->as = ANOP;
+			}
+		}
+	}
+
+	// pass 4: elide JMP to next instruction.
+	// only safe if there are no jumps to JMPs anymore.
+	if(!jmploop) {
+		for(r=firstr; r; r=r->link) {
+			p = r->prog;
+			if(p->as == AJMP && p->to.type == D_BRANCH && r->s2 == r->link) {
+				if(debug['R'] && debug['v'])
+					print("del %04d %P\n", r->pc, p);
+				p->as = ANOP;
+			}
+		}
+	}
+
+	// fix back pointers.
+	for(r=firstr; r; r=r->link) {
+		r->p2 = R;
+		r->p2link = R;
+	}
+	for(r=firstr; r; r=r->link) {
+		if(r->s2) {
+			r->p2link = r->s2->p2;
+			r->s2->p2 = r;
+		}
+	}
+
+	if(debug['R'] && debug['v']) {
+		print("\n");
+		for(r=firstr; r; r=r->link)
+			print("%04d %P\n", r->pc, r->prog);
+		print("\n");
+	}
+}
+
diff --git a/src/cmd/6c/sgen.c b/src/cmd/6c/sgen.c
index 42045f8..2402a02 100644
--- a/src/cmd/6c/sgen.c
+++ b/src/cmd/6c/sgen.c
@@ -126,7 +126,10 @@ xcom(Node *n)
 		break;
 
 	case ONAME:
-		n->addable = 10;
+		if(flag_largemodel)
+			n->addable = 9;
+		else
+			n->addable = 10;
 		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 f16d0f7..58d6d51 100644
--- a/src/cmd/6c/swt.c
+++ b/src/cmd/6c/swt.c
@@ -247,18 +247,12 @@ outcode(void)
 	Binit(&b, f, OWRITE);
 
 	Bprint(&b, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
-	if(ndynimp > 0 || ndynexp > 0) {
-		int i;
-
+	if(pragcgobuf.to > pragcgobuf.start) {
 		Bprint(&b, "\n");
 		Bprint(&b, "$$  // exports\n\n");
 		Bprint(&b, "$$  // local types\n\n");
-		Bprint(&b, "$$  // dynimport\n");
-		for(i=0; i<ndynimp; i++)
-			Bprint(&b, "dynimport %s %s %s\n", dynimp[i].local, dynimp[i].remote, dynimp[i].path);
-		Bprint(&b, "\n$$  // dynexport\n");
-		for(i=0; i<ndynexp; i++)
-			Bprint(&b, "dynexport %s %s\n", dynexp[i].local, dynexp[i].remote);
+		Bprint(&b, "$$  // cgo\n");
+		Bprint(&b, "%s", fmtstrflush(&pragcgobuf));
 		Bprint(&b, "\n$$\n\n");
 	}
 	Bprint(&b, "!\n");
@@ -339,12 +333,38 @@ outhist(Biobuf *b)
 	char *p, *q, *op, c;
 	Prog pg;
 	int n;
+	char *tofree;
+	static int first = 1;
+	static char *goroot, *goroot_final;
+
+	if(first) {
+		// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
+		first = 0;
+		goroot = getenv("GOROOT");
+		goroot_final = getenv("GOROOT_FINAL");
+		if(goroot == nil)
+			goroot = "";
+		if(goroot_final == nil)
+			goroot_final = goroot;
+		if(strcmp(goroot, goroot_final) == 0) {
+			goroot = nil;
+			goroot_final = nil;
+		}
+	}
 
+	tofree = nil;
 	pg = zprog;
 	pg.as = AHISTORY;
 	c = pathchar();
 	for(h = hist; h != H; h = h->link) {
 		p = h->name;
+		if(p != nil && goroot != nil) {
+			n = strlen(goroot);
+			if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
+				tofree = smprint("%s%s", goroot_final, p+n);
+				p = tofree;
+			}
+		}
 		op = 0;
 		if(systemtype(Windows) && p && p[1] == ':'){
 			c = p[2];
@@ -400,6 +420,11 @@ outhist(Biobuf *b)
 		Bputc(b, pg.lineno>>24);
 		zaddr(b, &pg.from, 0);
 		zaddr(b, &pg.to, 0);
+
+		if(tofree) {
+			free(tofree);
+			tofree = nil;
+		}
 	}
 }
 
@@ -591,8 +616,8 @@ align(int32 i, Type *t, int op, int32 *maxalign)
 int32
 maxround(int32 max, int32 v)
 {
-	v += SZ_VLONG-1;
+	v = xround(v, SZ_VLONG);
 	if(v > max)
-		max = xround(v, SZ_VLONG);
+		return v;
 	return max;
 }
diff --git a/src/cmd/6c/txt.c b/src/cmd/6c/txt.c
index 2cb8c15..364b189 100644
--- a/src/cmd/6c/txt.c
+++ b/src/cmd/6c/txt.c
@@ -809,7 +809,6 @@ gmove(Node *f, Node *t)
 	case CASE(	TUINT,	TCHAR):
 	case CASE(	TLONG,	TCHAR):
 	case CASE(	TULONG,	TCHAR):
-	case CASE(	TIND,	TCHAR):
 
 	case CASE(	TCHAR,	TUCHAR):
 	case CASE(	TUCHAR,	TUCHAR):
@@ -819,7 +818,6 @@ gmove(Node *f, Node *t)
 	case CASE(	TUINT,	TUCHAR):
 	case CASE(	TLONG,	TUCHAR):
 	case CASE(	TULONG,	TUCHAR):
-	case CASE(	TIND,	TUCHAR):
 
 	case CASE(	TSHORT,	TSHORT):
 	case CASE(	TUSHORT,TSHORT):
@@ -827,7 +825,6 @@ gmove(Node *f, Node *t)
 	case CASE(	TUINT,	TSHORT):
 	case CASE(	TLONG,	TSHORT):
 	case CASE(	TULONG,	TSHORT):
-	case CASE(	TIND,	TSHORT):
 
 	case CASE(	TSHORT,	TUSHORT):
 	case CASE(	TUSHORT,TUSHORT):
@@ -835,42 +832,26 @@ gmove(Node *f, Node *t)
 	case CASE(	TUINT,	TUSHORT):
 	case CASE(	TLONG,	TUSHORT):
 	case CASE(	TULONG,	TUSHORT):
-	case CASE(	TIND,	TUSHORT):
 
 	case CASE(	TINT,	TINT):
 	case CASE(	TUINT,	TINT):
 	case CASE(	TLONG,	TINT):
 	case CASE(	TULONG,	TINT):
-	case CASE(	TIND,	TINT):
 
 	case CASE(	TINT,	TUINT):
 	case CASE(	TUINT,	TUINT):
 	case CASE(	TLONG,	TUINT):
 	case CASE(	TULONG,	TUINT):
-	case CASE(	TIND,	TUINT):
-
-	case CASE(	TUINT,	TIND):
-	case CASE(	TVLONG,	TUINT):
-	case CASE(	TVLONG,	TULONG):
-	case CASE(	TUVLONG, TUINT):
-	case CASE(	TUVLONG, TULONG):
  *****/
 		a = AMOVL;
 		break;
 
-	case CASE(	TVLONG,	TCHAR):
-	case	CASE(	TVLONG,	TSHORT):
-	case CASE(	TVLONG,	TINT):
-	case CASE(	TVLONG,	TLONG):
-	case CASE(	TUVLONG, TCHAR):
-	case	CASE(	TUVLONG, TSHORT):
-	case CASE(	TUVLONG, TINT):
-	case CASE(	TUVLONG, TLONG):
+	case CASE(	TINT,	TIND):
 	case CASE(	TINT,	TVLONG):
 	case CASE(	TINT,	TUVLONG):
-	case CASE(	TLONG,	TVLONG):
-	case CASE(	TINT,	TIND):
 	case CASE(	TLONG,	TIND):
+	case CASE(	TLONG,	TVLONG):
+	case CASE(	TLONG,	TUVLONG):
 		a = AMOVLQSX;
 		if(f->op == OCONST) {
 			f->vconst &= (uvlong)0xffffffffU;
@@ -886,22 +867,53 @@ gmove(Node *f, Node *t)
 	case CASE(	TULONG,	TVLONG):
 	case CASE(	TULONG,	TUVLONG):
 	case CASE(	TULONG,	TIND):
-		a = AMOVL;	/* same effect as AMOVLQZX */
+		a = AMOVLQZX;
 		if(f->op == OCONST) {
 			f->vconst &= (uvlong)0xffffffffU;
 			a = AMOVQ;
 		}
 		break;
+	
+	case CASE(	TIND,	TCHAR):
+	case CASE(	TIND,	TUCHAR):
+	case CASE(	TIND,	TSHORT):
+	case CASE(	TIND,	TUSHORT):
+	case CASE(	TIND,	TINT):
+	case CASE(	TIND,	TUINT):
+	case CASE(	TIND,	TLONG):
+	case CASE(	TIND,	TULONG):
+	case CASE(	TVLONG,	TCHAR):
+	case CASE(	TVLONG,	TUCHAR):
+	case CASE(	TVLONG,	TSHORT):
+	case CASE(	TVLONG,	TUSHORT):
+	case CASE(	TVLONG,	TINT):
+	case CASE(	TVLONG,	TUINT):
+	case CASE(	TVLONG,	TLONG):
+	case CASE(	TVLONG,	TULONG):
+	case CASE(	TUVLONG,	TCHAR):
+	case CASE(	TUVLONG,	TUCHAR):
+	case CASE(	TUVLONG,	TSHORT):
+	case CASE(	TUVLONG,	TUSHORT):
+	case CASE(	TUVLONG,	TINT):
+	case CASE(	TUVLONG,	TUINT):
+	case CASE(	TUVLONG,	TLONG):
+	case CASE(	TUVLONG,	TULONG):
+		a = AMOVQL;
+		if(f->op == OCONST) {
+			f->vconst &= (int)0xffffffffU;
+			a = AMOVL;
+		}
+		break;	
 
+	case CASE(	TIND,	TIND):
 	case CASE(	TIND,	TVLONG):
-	case CASE(	TVLONG,	TVLONG):
-	case CASE(	TUVLONG,	TVLONG):
-	case CASE(	TVLONG,	TUVLONG):
-	case CASE(	TUVLONG,	TUVLONG):
 	case CASE(	TIND,	TUVLONG):
 	case CASE(	TVLONG,	TIND):
+	case CASE(	TVLONG,	TVLONG):
+	case CASE(	TVLONG,	TUVLONG):
 	case CASE(	TUVLONG,	TIND):
-	case CASE(	TIND,	TIND):
+	case CASE(	TUVLONG,	TVLONG):
+	case CASE(	TUVLONG,	TUVLONG):
 		a = AMOVQ;
 		break;
 
@@ -1348,6 +1360,16 @@ gopcode(int o, Type *ty, Node *f, Node *t)
 			a = ASALQ;
 		break;
 
+	case OROTL:
+		a = AROLL;
+		if(et == TCHAR || et == TUCHAR)
+			a = AROLB;
+		if(et == TSHORT || et == TUSHORT)
+			a = AROLW;
+		if(et == TVLONG || et == TUVLONG || et == TIND)
+			a = AROLQ;
+		break;
+
 	case OFUNC:
 		a = ACALL;
 		break;
@@ -1490,6 +1512,18 @@ gpseudo(int a, Sym *s, Node *n)
 		pc--;
 }
 
+void
+gprefetch(Node *n)
+{
+	Node n1;
+	
+	regalloc(&n1, n, Z);
+	gmove(n, &n1);
+	n1.op = OINDREG;
+	gins(APREFETCHNTA, &n1, Z);
+	regfree(&n1);
+}
+
 int
 sconst(Node *n)
 {
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
index 00334e7..a51c0ca 100644
--- a/src/cmd/6g/cgen.c
+++ b/src/cmd/6g/cgen.c
@@ -33,9 +33,26 @@ cgen(Node *n, Node *res)
 	while(n->op == OCONVNOP)
 		n = n->left;
 
-	// inline slices
-	if(cgen_inline(n, res))
+	switch(n->op) {
+	case OSLICE:
+	case OSLICEARR:
+	case OSLICESTR:
+		if (res->op != ONAME || !res->addable) {
+			tempname(&n1, n->type);
+			cgen_slice(n, &n1);
+			cgen(&n1, res);
+		} else
+			cgen_slice(n, res);
 		goto ret;
+	case OEFACE:
+		if (res->op != ONAME || !res->addable) {
+			tempname(&n1, n->type);
+			cgen_eface(n, &n1);
+			cgen(&n1, res);
+		} else
+			cgen_eface(n, res);
+		goto ret;
+	}
 
 	if(n->ullman >= UINF) {
 		if(n->op == OINDREG)
@@ -174,7 +191,7 @@ cgen(Node *n, Node *res)
 	switch(n->op) {
 	default:
 		dump("cgen", n);
-		fatal("cgen: unknown op %N", n);
+		fatal("cgen: unknown op %+hN", n);
 		break;
 
 	// these call bgen to get a bool value
@@ -187,12 +204,12 @@ cgen(Node *n, Node *res)
 	case OGE:
 	case OGT:
 	case ONOT:
-		p1 = gbranch(AJMP, T);
+		p1 = gbranch(AJMP, T, 0);
 		p2 = pc;
 		gmove(nodbool(1), res);
-		p3 = gbranch(AJMP, T);
+		p3 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
-		bgen(n, 1, p2);
+		bgen(n, 1, 0, p2);
 		gmove(nodbool(0), res);
 		patch(p3, pc);
 		goto ret;
@@ -229,17 +246,41 @@ cgen(Node *n, Node *res)
 	case OADD:
 	case OMUL:
 		a = optoas(n->op, nl->type);
-		if(a != AIMULB)
-			goto sbop;
-		cgen_bmul(n->op, nl, nr, res);
-		break;
+		if(a == AIMULB) {
+			cgen_bmul(n->op, nl, nr, res);
+			break;
+		}
+		goto sbop;
 
 	// asymmetric binary
 	case OSUB:
 		a = optoas(n->op, nl->type);
 		goto abop;
 
+	case OHMUL:
+		cgen_hmul(nl, nr, res);
+		break;
+
 	case OCONV:
+		if(n->type->width > nl->type->width) {
+			// If loading from memory, do conversion during load,
+			// so as to avoid use of 8-bit register in, say, int(*byteptr).
+			switch(nl->op) {
+			case ODOT:
+			case ODOTPTR:
+			case OINDEX:
+			case OIND:
+			case ONAME:
+				igen(nl, &n1, res);
+				regalloc(&n2, n->type, res);
+				gmove(&n1, &n2);
+				gmove(&n2, res);
+				regfree(&n2);
+				regfree(&n1);
+				goto ret;
+			}
+		}
+
 		regalloc(&n1, nl->type, res);
 		regalloc(&n2, n->type, &n1);
 		cgen(nl, &n1);
@@ -273,18 +314,18 @@ cgen(Node *n, Node *res)
 
 	case OLEN:
 		if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
-			// map and chan have len in the first 32-bit word.
+			// map and chan have len in the first int-sized word.
 			// a zero pointer means zero length
 			regalloc(&n1, types[tptr], res);
 			cgen(nl, &n1);
 
 			nodconst(&n2, types[tptr], 0);
 			gins(optoas(OCMP, types[tptr]), &n1, &n2);
-			p1 = gbranch(optoas(OEQ, types[tptr]), T);
+			p1 = gbranch(optoas(OEQ, types[tptr]), T, 0);
 
 			n2 = n1;
 			n2.op = OINDREG;
-			n2.type = types[TINT32];
+			n2.type = types[simtype[TINT]];
 			gmove(&n2, &n1);
 
 			patch(p1, pc);
@@ -297,7 +338,7 @@ cgen(Node *n, Node *res)
 			// both slice and string have len one pointer into the struct.
 			// a zero pointer means zero length
 			igen(nl, &n1, res);
-			n1.type = types[TUINT32];
+			n1.type = types[simtype[TUINT]];
 			n1.xoffset += Array_nel;
 			gmove(&n1, res);
 			regfree(&n1);
@@ -308,19 +349,19 @@ cgen(Node *n, Node *res)
 
 	case OCAP:
 		if(istype(nl->type, TCHAN)) {
-			// chan has cap in the second 32-bit word.
+			// chan has cap in the second int-sized word.
 			// a zero pointer means zero length
 			regalloc(&n1, types[tptr], res);
 			cgen(nl, &n1);
 
 			nodconst(&n2, types[tptr], 0);
 			gins(optoas(OCMP, types[tptr]), &n1, &n2);
-			p1 = gbranch(optoas(OEQ, types[tptr]), T);
+			p1 = gbranch(optoas(OEQ, types[tptr]), T, 0);
 
 			n2 = n1;
 			n2.op = OINDREG;
-			n2.xoffset = 4;
-			n2.type = types[TINT32];
+			n2.xoffset = widthint;
+			n2.type = types[simtype[TINT]];
 			gmove(&n2, &n1);
 
 			patch(p1, pc);
@@ -331,7 +372,7 @@ cgen(Node *n, Node *res)
 		}
 		if(isslice(nl->type)) {
 			igen(nl, &n1, res);
-			n1.type = types[TUINT32];
+			n1.type = types[simtype[TUINT]];
 			n1.xoffset += Array_cap;
 			gmove(&n1, res);
 			regfree(&n1);
@@ -365,18 +406,53 @@ cgen(Node *n, Node *res)
 			a = optoas(n->op, nl->type);
 			goto abop;
 		}
-		cgen_div(n->op, nl, nr, res);
+
+		if(nl->ullman >= nr->ullman) {
+			regalloc(&n1, nl->type, res);
+			cgen(nl, &n1);
+			cgen_div(n->op, &n1, nr, res);
+			regfree(&n1);
+		} else {
+			if(!smallintconst(nr)) {
+				regalloc(&n2, nr->type, res);
+				cgen(nr, &n2);
+			} else {
+				n2 = *nr;
+			}
+			cgen_div(n->op, nl, &n2, res);
+			if(n2.op != OLITERAL)
+				regfree(&n2);
+		}
 		break;
 
 	case OLSH:
 	case ORSH:
-		cgen_shift(n->op, nl, nr, res);
+	case OLROT:
+		cgen_shift(n->op, n->bounded, nl, nr, res);
 		break;
 	}
 	goto ret;
 
 sbop:	// symmetric binary
-	if(nl->ullman < nr->ullman) {
+	/*
+	 * put simplest on right - we'll generate into left
+	 * and then adjust it using the computation of right.
+	 * constants and variables have the same ullman
+	 * count, so look for constants specially.
+	 *
+	 * an integer constant we can use as an immediate
+	 * is simpler than a variable - we can use the immediate
+	 * in the adjustment instruction directly - so it goes
+	 * on the right.
+	 *
+	 * other constants, like big integers or floating point
+	 * constants, require a mov into a register, so those
+	 * might as well go on the left, so we can reuse that
+	 * register for the computation.
+	 */
+	if(nl->ullman < nr->ullman ||
+	   (nl->ullman == nr->ullman &&
+	    (smallintconst(nl) || (nr->op == OLITERAL && !smallintconst(nr))))) {
 		r = nl;
 		nl = nr;
 		nr = r;
@@ -386,7 +462,13 @@ abop:	// asymmetric binary
 	if(nl->ullman >= nr->ullman) {
 		regalloc(&n1, nl->type, res);
 		cgen(nl, &n1);
-
+	/*
+	 * This generates smaller code - it avoids a MOV - but it's
+	 * easily 10% slower due to not being able to
+	 * optimize/manipulate the move.
+	 * To see, run: go test -bench . crypto/md5
+	 * with and without.
+	 *
 		if(sudoaddable(a, nr, &addr)) {
 			p1 = gins(a, N, &n1);
 			p1->from = addr;
@@ -395,18 +477,30 @@ abop:	// asymmetric binary
 			regfree(&n1);
 			goto ret;
 		}
-		regalloc(&n2, nr->type, N);
-		cgen(nr, &n2);
+	 *
+	 */
+
+		if(smallintconst(nr))
+			n2 = *nr;
+		else {
+			regalloc(&n2, nr->type, N);
+			cgen(nr, &n2);
+		}
 	} else {
-		regalloc(&n2, nr->type, res);
-		cgen(nr, &n2);
+		if(smallintconst(nr))
+			n2 = *nr;
+		else {
+			regalloc(&n2, nr->type, res);
+			cgen(nr, &n2);
+		}
 		regalloc(&n1, nl->type, N);
 		cgen(nl, &n1);
 	}
 	gins(a, &n2, &n1);
 	gmove(&n1, res);
 	regfree(&n1);
-	regfree(&n2);
+	if(n2.op != OLITERAL)
+		regfree(&n2);
 	goto ret;
 
 uop:	// unary
@@ -422,93 +516,142 @@ ret:
 }
 
 /*
- * generate:
- *	res = &n;
+ * allocate a register in res and generate
+ *  newreg = &n
+ * The caller must call regfree(a).
  */
 void
-agen(Node *n, Node *res)
+cgenr(Node *n, Node *a, Node *res)
+{
+	Node n1;
+
+	if(debug['g'])
+		dump("cgenr-n", n);
+
+	if(isfat(n->type))
+		fatal("cgenr on fat node");
+
+	if(n->addable) {
+		regalloc(a, n->type, res);
+		gmove(n, a);
+		return;
+	}
+
+	switch(n->op) {
+	case ONAME:
+	case ODOT:
+	case ODOTPTR:
+	case OINDEX:
+	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		igen(n, &n1, res);
+		regalloc(a, types[tptr], &n1);
+		gmove(&n1, a);
+		regfree(&n1);
+		break;
+	default:
+		regalloc(a, n->type, res);
+		cgen(n, a);
+		break;
+	}
+}
+
+/*
+ * allocate a register in res and generate
+ * res = &n
+ */
+void
+agenr(Node *n, Node *a, Node *res)
 {
 	Node *nl, *nr;
-	Node n1, n2, n3, tmp, n4, n5;
+	Node n1, n2, n3, n4, n5, tmp, tmp2, nlen;
 	Prog *p1;
+	Type *t;
 	uint32 w;
 	uint64 v;
-	Type *t;
+	int freelen;
 
 	if(debug['g']) {
-		dump("\nagen-res", res);
-		dump("agen-r", n);
-	}
-	if(n == N || n->type == T)
-		return;
-
-	while(n->op == OCONVNOP)
-		n = n->left;
-
-	if(n->addable) {
-		regalloc(&n1, types[tptr], res);
-		gins(ALEAQ, n, &n1);
-		gmove(&n1, res);
-		regfree(&n1);
-		goto ret;
+		dump("\nagenr-n", n);
 	}
 
 	nl = n->left;
 	nr = n->right;
 
 	switch(n->op) {
-	default:
-		fatal("agen: unknown op %N", n);
-		break;
-
+	case ODOT:
+	case ODOTPTR:
+	case OCALLFUNC:
 	case OCALLMETH:
-		cgen_callmeth(n, 0);
-		cgen_aret(n, res);
-		break;
-
 	case OCALLINTER:
-		cgen_callinter(n, res, 0);
-		cgen_aret(n, res);
+		igen(n, &n1, res);
+		regalloc(a, types[tptr], &n1);
+		agen(&n1, a);
+		regfree(&n1);
 		break;
 
-	case OCALLFUNC:
-		cgen_call(n, 0);
-		cgen_aret(n, res);
+	case OIND:
+		cgenr(n->left, a, res);
 		break;
 
 	case OINDEX:
+		freelen = 0;
 		w = n->type->width;
+		// Generate the non-addressable child first.
 		if(nr->addable)
 			goto irad;
 		if(nl->addable) {
-			if(!isconst(nr, CTINT)) {
-				regalloc(&n1, nr->type, N);
-				cgen(nr, &n1);
-			}
+			cgenr(nr, &n1, N);
 			if(!isconst(nl, CTSTR)) {
-				regalloc(&n3, types[tptr], res);
-				agen(nl, &n3);
+				if(isfixedarray(nl->type)) {
+					agenr(nl, &n3, res);
+				} else {
+					igen(nl, &nlen, res);
+					freelen = 1;
+					nlen.type = types[tptr];
+					nlen.xoffset += Array_array;
+					regalloc(&n3, types[tptr], res);
+					gmove(&nlen, &n3);
+					nlen.type = types[simtype[TUINT]];
+					nlen.xoffset += Array_nel-Array_array;
+				}
 			}
 			goto index;
 		}
 		tempname(&tmp, nr->type);
 		cgen(nr, &tmp);
 		nr = &tmp;
-
 	irad:
 		if(!isconst(nl, CTSTR)) {
-			regalloc(&n3, types[tptr], res);
-			agen(nl, &n3);
+			if(isfixedarray(nl->type)) {
+				agenr(nl, &n3, res);
+			} else {
+				if(!nl->addable) {
+					// igen will need an addressable node.
+					tempname(&tmp2, nl->type);
+					cgen(nl, &tmp2);
+					nl = &tmp2;
+				}
+				igen(nl, &nlen, res);
+				freelen = 1;
+				nlen.type = types[tptr];
+				nlen.xoffset += Array_array;
+				regalloc(&n3, types[tptr], res);
+				gmove(&nlen, &n3);
+				nlen.type = types[simtype[TUINT]];
+				nlen.xoffset += Array_nel-Array_array;
+			}
 		}
 		if(!isconst(nr, CTINT)) {
-			regalloc(&n1, nr->type, N);
-			cgen(nr, &n1);
+			cgenr(nr, &n1, N);
 		}
 		goto index;
 
 	index:
 		// &a is in &n3 (allocated in res)
 		// i is in &n1 (if not constant)
+		// len(a) is in nlen (if needed)
 		// w is width
 
 		// explicit check for nil if array is large enough
@@ -529,29 +672,26 @@ agen(Node *n, Node *res)
 				fatal("constant string constant index");	// front end should handle
 			v = mpgetfix(nr->val.u.xval);
 			if(isslice(nl->type) || nl->type->etype == TSTRING) {
-				if(!debug['B'] && !n->etype) {
-					n1 = n3;
-					n1.op = OINDREG;
-					n1.type = types[tptr];
-					n1.xoffset = Array_nel;
-					nodconst(&n2, types[TUINT32], v);
-					gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
-					p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-					ginscall(panicindex, 0);
+				if(!debug['B'] && !n->bounded) {
+					nodconst(&n2, types[simtype[TUINT]], v);
+					if(smallintconst(nr)) {
+						gins(optoas(OCMP, types[simtype[TUINT]]), &nlen, &n2);
+					} else {
+						regalloc(&tmp, types[simtype[TUINT]], N);
+						gmove(&n2, &tmp);
+						gins(optoas(OCMP, types[simtype[TUINT]]), &nlen, &tmp);
+						regfree(&tmp);
+					}
+					p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1);
+					ginscall(panicindex, -1);
 					patch(p1, pc);
 				}
-
-				n1 = n3;
-				n1.op = OINDREG;
-				n1.type = types[tptr];
-				n1.xoffset = Array_array;
-				gmove(&n1, &n3);
+				regfree(&nlen);
 			}
 
 			if (v*w != 0)
 				ginscon(optoas(OADD, types[tptr]), v*w, &n3);
-			gmove(&n3, res);
-			regfree(&n3);
+			*a = n3;
 			break;
 		}
 
@@ -564,32 +704,32 @@ agen(Node *n, Node *res)
 		gmove(&n1, &n2);
 		regfree(&n1);
 
-		if(!debug['B'] && !n->etype) {
+		if(!debug['B'] && !n->bounded) {
 			// check bounds
-			n5.op = OXXX;
-			t = types[TUINT32];
+			t = types[simtype[TUINT]];
 			if(is64(nr->type))
 				t = types[TUINT64];
 			if(isconst(nl, CTSTR)) {
-				nodconst(&n1, t, nl->val.u.sval->len);
+				nodconst(&nlen, t, nl->val.u.sval->len);
 			} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
-				n1 = n3;
-				n1.op = OINDREG;
-				n1.type = types[TUINT32];
-				n1.xoffset = Array_nel;
 				if(is64(nr->type)) {
 					regalloc(&n5, t, N);
-					gmove(&n1, &n5);
-					n1 = n5;
+					gmove(&nlen, &n5);
+					regfree(&nlen);
+					nlen = n5;
 				}
 			} else {
-				nodconst(&n1, t, nl->type->bound);
+				nodconst(&nlen, t, nl->type->bound);
+				if(!smallintconst(&nlen)) {
+					regalloc(&n5, t, N);
+					gmove(&nlen, &n5);
+					nlen = n5;
+					freelen = 1;
+				}
 			}
-			gins(optoas(OCMP, t), &n2, &n1);
-			p1 = gbranch(optoas(OLT, t), T);
-			if(n5.op != OXXX)
-				regfree(&n5);
-			ginscall(panicindex, 0);
+			gins(optoas(OCMP, t), &n2, &nlen);
+			p1 = gbranch(optoas(OLT, t), T, +1);
+			ginscall(panicindex, -1);
 			patch(p1, pc);
 		}
 
@@ -597,19 +737,15 @@ agen(Node *n, 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);
-			p1->from.scale = 1;
-			p1->from.index = n2.val.u.reg;
+			if(flag_largemodel) {
+				gins(AADDQ, &n2, &n3);
+			} else {
+				p1->from.scale = 1;
+				p1->from.index = n2.val.u.reg;
+			}
 			goto indexdone;
 		}
 
-		if(isslice(nl->type) || nl->type->etype == TSTRING) {
-			n1 = n3;
-			n1.op = OINDREG;
-			n1.type = types[tptr];
-			n1.xoffset = Array_array;
-			gmove(&n1, &n3);
-		}
-
 		if(w == 0) {
 			// nothing to do
 		} else if(w == 1 || w == 2 || w == 4 || w == 8) {
@@ -623,9 +759,103 @@ agen(Node *n, Node *res)
 		}
 
 	indexdone:
-		gmove(&n3, res);
+		*a = n3;
 		regfree(&n2);
-		regfree(&n3);
+		if(freelen)
+			regfree(&nlen);
+		break;
+
+	default:
+		regalloc(a, types[tptr], res);
+		agen(n, a);
+		break;
+	}
+}
+
+/*
+ * generate:
+ *	res = &n;
+ */
+void
+agen(Node *n, Node *res)
+{
+	Node *nl, *nr;
+	Node n1, n2;
+
+	if(debug['g']) {
+		dump("\nagen-res", res);
+		dump("agen-r", n);
+	}
+	if(n == N || n->type == T)
+		return;
+
+	while(n->op == OCONVNOP)
+		n = n->left;
+
+	if(isconst(n, CTNIL) && n->type->width > widthptr) {
+		// Use of a nil interface or nil slice.
+		// Create a temporary we can take the address of and read.
+		// The generated code is just going to panic, so it need not
+		// be terribly efficient. See issue 3670.
+		tempname(&n1, n->type);
+		clearfat(&n1);
+		regalloc(&n2, types[tptr], res);
+		gins(ALEAQ, &n1, &n2);
+		gmove(&n2, res);
+		regfree(&n2);
+		goto ret;
+	}
+		
+	if(n->addable) {
+		regalloc(&n1, types[tptr], res);
+		gins(ALEAQ, n, &n1);
+		gmove(&n1, res);
+		regfree(&n1);
+		goto ret;
+	}
+
+	nl = n->left;
+	nr = n->right;
+	USED(nr);
+
+	switch(n->op) {
+	default:
+		fatal("agen: unknown op %+hN", n);
+		break;
+
+	case OCALLMETH:
+		cgen_callmeth(n, 0);
+		cgen_aret(n, res);
+		break;
+
+	case OCALLINTER:
+		cgen_callinter(n, res, 0);
+		cgen_aret(n, res);
+		break;
+
+	case OCALLFUNC:
+		cgen_call(n, 0);
+		cgen_aret(n, res);
+		break;
+
+	case OSLICE:
+	case OSLICEARR:
+	case OSLICESTR:
+		tempname(&n1, n->type);
+		cgen_slice(n, &n1);
+		agen(&n1, res);
+		break;
+
+	case OEFACE:
+		tempname(&n1, n->type);
+		cgen_eface(n, &n1);
+		agen(&n1, res);
+		break;
+
+	case OINDEX:
+		agenr(n, &n1, res);
+		gmove(&n1, res);
+		regfree(&n1);
 		break;
 
 	case ONAME:
@@ -692,7 +922,11 @@ igen(Node *n, Node *a, Node *res)
 {
 	Type *fp;
 	Iter flist;
- 
+	Node n1;
+
+	if(debug['g']) {
+		dump("\nigen-n", n);
+	}
 	switch(n->op) {
 	case ONAME:
 		if((n->class&PHEAP) || n->class == PPARAMREF)
@@ -700,9 +934,53 @@ igen(Node *n, Node *a, Node *res)
 		*a = *n;
 		return;
 
+	case OINDREG:
+		// Increase the refcount of the register so that igen's caller
+		// has to call regfree.
+		if(n->val.u.reg != D_SP)
+			reg[n->val.u.reg]++;
+		*a = *n;
+		return;
+
+	case ODOT:
+		igen(n->left, a, res);
+		a->xoffset += n->xoffset;
+		a->type = n->type;
+		return;
+
+	case ODOTPTR:
+		cgenr(n->left, a, res);
+		if(n->xoffset != 0) {
+			// explicit check for nil if struct is large enough
+			// that we might derive too big a pointer.
+			if(n->left->type->type->width >= unmappedzero) {
+				n1 = *a;
+				n1.op = OINDREG;
+				n1.type = types[TUINT8];
+				n1.xoffset = 0;
+				gins(ATESTB, nodintconst(0), &n1);
+			}
+		}
+		a->op = OINDREG;
+		a->xoffset += n->xoffset;
+		a->type = n->type;
+		return;
+
 	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		switch(n->op) {
+		case OCALLFUNC:
+			cgen_call(n, 0);
+			break;
+		case OCALLMETH:
+			cgen_callmeth(n, 0);
+			break;
+		case OCALLINTER:
+			cgen_callinter(n, N, 0);
+			break;
+		}
 		fp = structfirst(&flist, getoutarg(n->left->type));
-		cgen_call(n, 0);
 		memset(a, 0, sizeof *a);
 		a->op = OINDREG;
 		a->val.u.reg = D_SP;
@@ -710,10 +988,34 @@ igen(Node *n, Node *a, Node *res)
 		a->xoffset = fp->width;
 		a->type = n->type;
 		return;
+
+	case OINDEX:
+		// Index of fixed-size array by constant can
+		// put the offset in the addressing.
+		// Could do the same for slice except that we need
+		// to use the real index for the bounds checking.
+		if(isfixedarray(n->left->type) ||
+		   (isptr[n->left->type->etype] && isfixedarray(n->left->left->type)))
+		if(isconst(n->right, CTINT)) {
+			// Compute &a.
+			if(!isptr[n->left->type->etype])
+				igen(n->left, a, res);
+			else {
+				igen(n->left, &n1, res);
+				regalloc(a, types[tptr], res);
+				gmove(&n1, a);
+				regfree(&n1);
+				a->op = OINDREG;
+			}
+
+			// Compute &a[i] as &a + i*width.
+			a->type = n->type;
+			a->xoffset += mpgetfix(n->right->val.u.xval)*n->type->width;
+			return;
+		}
 	}
- 
-	regalloc(a, types[tptr], res);
-	agen(n, a);
+
+	agenr(n, a, res);
 	a->op = OINDREG;
 	a->type = n->type;
 }
@@ -723,7 +1025,7 @@ igen(Node *n, Node *a, Node *res)
  *	if(n == true) goto to;
  */
 void
-bgen(Node *n, int true, Prog *to)
+bgen(Node *n, int true, int likely, Prog *to)
 {
 	int et, a;
 	Node *nl, *nr, *l, *r;
@@ -765,14 +1067,14 @@ bgen(Node *n, int true, Prog *to)
 		a = AJNE;
 		if(!true)
 			a = AJEQ;
-		patch(gbranch(a, n->type), to);
+		patch(gbranch(a, n->type, likely), to);
 		regfree(&n1);
 		goto ret;
 
 	case OLITERAL:
 		// need to ask if it is bool?
 		if(!true == !n->val.u.bval)
-			patch(gbranch(AJMP, T), to);
+			patch(gbranch(AJMP, T, likely), to);
 		goto ret;
 
 	case ONAME:
@@ -783,7 +1085,7 @@ bgen(Node *n, int true, Prog *to)
 		a = AJNE;
 		if(!true)
 			a = AJEQ;
-		patch(gbranch(a, n->type), to);
+		patch(gbranch(a, n->type, likely), to);
 		goto ret;
 
 	case OANDAND:
@@ -791,12 +1093,12 @@ bgen(Node *n, int true, Prog *to)
 			goto caseor;
 
 	caseand:
-		p1 = gbranch(AJMP, T);
-		p2 = gbranch(AJMP, T);
+		p1 = gbranch(AJMP, T, 0);
+		p2 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
-		bgen(n->left, !true, p2);
-		bgen(n->right, !true, p2);
-		p1 = gbranch(AJMP, T);
+		bgen(n->left, !true, -likely, p2);
+		bgen(n->right, !true, -likely, p2);
+		p1 = gbranch(AJMP, T, 0);
 		patch(p1, to);
 		patch(p2, pc);
 		goto ret;
@@ -806,8 +1108,8 @@ bgen(Node *n, int true, Prog *to)
 			goto caseand;
 
 	caseor:
-		bgen(n->left, true, to);
-		bgen(n->right, true, to);
+		bgen(n->left, true, likely, to);
+		bgen(n->right, true, likely, to);
 		goto ret;
 
 	case OEQ:
@@ -830,7 +1132,7 @@ bgen(Node *n, int true, Prog *to)
 	switch(n->op) {
 
 	case ONOT:
-		bgen(nl, !true, to);
+		bgen(nl, !true, likely, to);
 		goto ret;
 
 	case OEQ:
@@ -843,14 +1145,14 @@ bgen(Node *n, int true, Prog *to)
 		if(!true) {
 			if(isfloat[nr->type->etype]) {
 				// brcom is not valid on floats when NaN is involved.
-				p1 = gbranch(AJMP, T);
-				p2 = gbranch(AJMP, T);
+				p1 = gbranch(AJMP, T, 0);
+				p2 = gbranch(AJMP, T, 0);
 				patch(p1, pc);
 				ll = n->ninit;   // avoid re-genning ninit
 				n->ninit = nil;
-				bgen(n, 1, p2);
+				bgen(n, 1, -likely, p2);
 				n->ninit = ll;
-				patch(gbranch(AJMP, T), to);
+				patch(gbranch(AJMP, T, 0), to);
 				patch(p2, pc);
 				goto ret;
 			}				
@@ -865,47 +1167,41 @@ bgen(Node *n, int true, Prog *to)
 			nl = nr;
 			nr = r;
 		}
-		
+
 		if(isslice(nl->type)) {
-			// only valid to cmp darray to literal nil
+			// front end should only leave cmp to literal nil
 			if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-				yyerror("illegal array comparison");
+				yyerror("illegal slice comparison");
 				break;
 			}
 			a = optoas(a, types[tptr]);
-			regalloc(&n1, types[tptr], N);
-			agen(nl, &n1);
-			n2 = n1;
-			n2.op = OINDREG;
-			n2.xoffset = Array_array;
-			n2.type = types[tptr];
+			igen(nl, &n1, N);
+			n1.xoffset += Array_array;
+			n1.type = types[tptr];
 			nodconst(&tmp, types[tptr], 0);
-			gins(optoas(OCMP, types[tptr]), &n2, &tmp);
-			patch(gbranch(a, types[tptr]), to);
+			gins(optoas(OCMP, types[tptr]), &n1, &tmp);
+			patch(gbranch(a, types[tptr], likely), to);
 			regfree(&n1);
 			break;
 		}
 
 		if(isinter(nl->type)) {
-			// front end shold only leave cmp to literal nil
+			// front end should only leave cmp to literal nil
 			if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
 				yyerror("illegal interface comparison");
 				break;
 			}
 			a = optoas(a, types[tptr]);
-			regalloc(&n1, types[tptr], N);
-			agen(nl, &n1);
-			n2 = n1;
-			n2.op = OINDREG;
-			n2.xoffset = 0;
+			igen(nl, &n1, N);
+			n1.type = types[tptr];
 			nodconst(&tmp, types[tptr], 0);
-			gins(optoas(OCMP, types[tptr]), &n2, &tmp);
-			patch(gbranch(a, types[tptr]), to);
+			gins(optoas(OCMP, types[tptr]), &n1, &tmp);
+			patch(gbranch(a, types[tptr], likely), to);
 			regfree(&n1);
 			break;
 		}
 		if(iscomplex[nl->type->etype]) {
-			complexbool(a, nl, nr, true, to);
+			complexbool(a, nl, nr, true, likely, to);
 			break;
 		}
 
@@ -931,7 +1227,7 @@ bgen(Node *n, int true, Prog *to)
 
 		if(smallintconst(nr)) {
 			gins(optoas(OCMP, nr->type), &n1, nr);
-			patch(gbranch(optoas(a, nr->type), nr->type), to);
+			patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
 			regfree(&n1);
 			break;
 		}
@@ -953,18 +1249,18 @@ bgen(Node *n, int true, Prog *to)
 		if(isfloat[nr->type->etype] && (n->op == OEQ || n->op == ONE)) {
 			if(n->op == OEQ) {
 				// neither NE nor P
-				p1 = gbranch(AJNE, T);
-				p2 = gbranch(AJPS, T);
-				patch(gbranch(AJMP, T), to);
+				p1 = gbranch(AJNE, T, -likely);
+				p2 = gbranch(AJPS, T, -likely);
+				patch(gbranch(AJMP, T, 0), to);
 				patch(p1, pc);
 				patch(p2, pc);
 			} else {
 				// either NE or P
-				patch(gbranch(AJNE, T), to);
-				patch(gbranch(AJPS, T), to);
+				patch(gbranch(AJNE, T, likely), to);
+				patch(gbranch(AJPS, T, likely), to);
 			}
 		} else
-			patch(gbranch(optoas(a, nr->type), nr->type), to);
+			patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
 		regfree(&n1);
 		regfree(&n2);
 		break;
@@ -1036,8 +1332,8 @@ stkof(Node *n)
 void
 sgen(Node *n, Node *ns, int64 w)
 {
-	Node nodl, nodr, oldl, oldr, cx, oldcx, tmp;
-	int32 c, q, odst, osrc;
+	Node nodl, nodr, nodsi, noddi, cx, oldcx, tmp;
+	vlong c, q, odst, osrc;
 
 	if(debug['g']) {
 		print("\nsgen w=%lld\n", w);
@@ -1051,9 +1347,9 @@ sgen(Node *n, Node *ns, int64 w)
 	if(w < 0)
 		fatal("sgen copy %lld", w);
 
-	if(w == 16)
-		if(componentgen(n, ns))
-			return;
+	// Avoid taking the address for simple enough types.
+	if(componentgen(n, ns))
+		return;
 	
 	if(w == 0) {
 		// evaluate side effects only
@@ -1080,22 +1376,18 @@ sgen(Node *n, Node *ns, int64 w)
 	}
 
 	if(n->ullman >= ns->ullman) {
-		savex(D_SI, &nodr, &oldr, N, types[tptr]);
-		agen(n, &nodr);
-
-		regalloc(&nodr, types[tptr], &nodr);	// mark nodr as live
-		savex(D_DI, &nodl, &oldl, N, types[tptr]);
-		agen(ns, &nodl);
-		regfree(&nodr);
+		agenr(n, &nodr, N);
+		agenr(ns, &nodl, N);
 	} else {
-		savex(D_DI, &nodl, &oldl, N, types[tptr]);
-		agen(ns, &nodl);
-
-		regalloc(&nodl, types[tptr], &nodl);	// mark nodl as live
-		savex(D_SI, &nodr, &oldr, N, types[tptr]);
-		agen(n, &nodr);
-		regfree(&nodl);
+		agenr(ns, &nodl, N);
+		agenr(n, &nodr, N);
 	}
+	nodreg(&noddi, types[tptr], D_DI);
+	nodreg(&nodsi, types[tptr], D_SI);
+	gmove(&nodl, &noddi);
+	gmove(&nodr, &nodsi);
+	regfree(&nodl);
+	regfree(&nodr);
 
 	c = w % 8;	// bytes
 	q = w / 8;	// quads
@@ -1152,9 +1444,6 @@ sgen(Node *n, Node *ns, int64 w)
 		}
 	}
 
-
-	restx(&nodl, &oldl);
-	restx(&nodr, &oldr);
 	restx(&cx, &oldcx);
 }
 
@@ -1175,15 +1464,21 @@ cadable(Node *n)
 }
 
 /*
- * copy a structure component by component
+ * copy a composite value by moving its individual components.
+ * Slices, strings and interfaces are supported.
+ * Small structs or arrays with elements of basic type are
+ * also supported.
+ * nr is N when assigning a zero value.
  * return 1 if can do, 0 if cant.
- * nr is N for copy zero
  */
 int
 componentgen(Node *nr, Node *nl)
 {
 	Node nodl, nodr;
+	Type *t;
 	int freel, freer;
+	vlong fldcount;
+	vlong loffset, roffset;
 
 	freel = 0;
 	freer = 0;
@@ -1193,8 +1488,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 > 3)
 			goto no;
+
+		break;
+
 	case TSTRING:
 	case TINTER:
 		break;
@@ -1218,9 +1538,23 @@ componentgen(Node *nr, Node *nl)
 
 	switch(nl->type->etype) {
 	case TARRAY:
-		if(!isslice(nl->type))
-			goto no;
+		// componentgen for arrays.
+		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);
 
@@ -1232,7 +1566,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;
@@ -1242,7 +1576,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;
@@ -1265,7 +1599,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;
@@ -1300,7 +1634,27 @@ componentgen(Node *nr, Node *nl)
 		goto yes;
 
 	case TSTRUCT:
-		goto no;
+		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/6g/doc.go b/src/cmd/6g/doc.go
index 64f1d2b..07b2818 100644
--- a/src/cmd/6g/doc.go
+++ b/src/cmd/6g/doc.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 ignore
+
 /*
 
 6g is the version of the gc compiler for the x86-64.
@@ -10,4 +12,4 @@ The $GOARCH for these tools is amd64.
 It reads .go files and outputs .6 files. The flags are documented in ../gc/doc.go.
 
 */
-package documentation
+package main
diff --git a/src/cmd/6g/galign.c b/src/cmd/6g/galign.c
index b03ac1e..526c04c 100644
--- a/src/cmd/6g/galign.c
+++ b/src/cmd/6g/galign.c
@@ -17,8 +17,8 @@ vlong MAXWIDTH = 1LL<<50;
  */
 Typedef	typedefs[] =
 {
-	"int",		TINT,		TINT32,
-	"uint",		TUINT,		TUINT32,
+	"int",		TINT,		TINT64,
+	"uint",		TUINT,		TUINT64,
 	"uintptr",	TUINTPTR,	TUINT64,
 	0
 };
@@ -27,6 +27,7 @@ void
 betypeinit(void)
 {
 	widthptr = 8;
+	widthint = 8;
 
 	zprog.link = P;
 	zprog.as = AGOK;
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
index 47a5400..ceb6a2c 100644
--- a/src/cmd/6g/gg.h
+++ b/src/cmd/6g/gg.h
@@ -14,19 +14,22 @@ typedef	struct	Addr	Addr;
 struct	Addr
 {
 	vlong	offset;
-	double	dval;
-	Prog*	branch;
-	char	sval[NSNAME];
+	
+	union {
+		double	dval;
+		vlong	vval;
+		Prog*	branch;
+		char	sval[NSNAME];
+	} u;
 
 	Sym*	gotype;
 	Sym*	sym;
 	Node*	node;
-	int	width;
+	int64	width;
 	uchar	type;
 	uchar	index;
 	uchar	etype;
 	uchar	scale;	/* doubles as width in DATA op */
-	uchar	pun;	/* dont register variable */
 };
 #define	A	((Addr*)0)
 
@@ -58,7 +61,7 @@ EXTERN	Node*	throwreturn;
 extern	vlong	unmappedzero;
 
 /*
- * gen.c
+ * ggen.c
  */
 void	compile(Node*);
 void	proglist(void);
@@ -71,29 +74,31 @@ void	cgen_proc(Node*, int);
 void	cgen_callret(Node*, Node*);
 void	cgen_div(int, Node*, Node*, Node*);
 void	cgen_bmul(int, Node*, Node*, Node*);
-void	cgen_shift(int, Node*, Node*, Node*);
+void	cgen_hmul(Node*, Node*, Node*);
+void	cgen_shift(int, int, Node*, Node*, Node*);
 void	cgen_dcl(Node*);
 int	needconvert(Type*, Type*);
 void	genconv(Type*, Type*);
 void	allocparams(void);
-void	checklabels();
+void	checklabels(void);
 void	ginscall(Node*, int);
 int	gen_as_init(Node*);
+void	clearslim(Node*);
 
 /*
- * cgen
+ * cgen.c
  */
 void	agen(Node*, Node*);
+void	agenr(Node*, Node*, Node*);
+void	cgenr(Node*, Node*, Node*);
 void	igen(Node*, Node*, Node*);
 vlong	fieldoffset(Type*, Node*);
-void	bgen(Node*, int, Prog*);
 void	sgen(Node*, Node*, int64);
 void	gmove(Node*, Node*);
 Prog*	gins(int, Node*, Node*);
 int	samaddr(Node*, Node*);
 void	naddr(Node*, Addr*, int);
 void	cgen_aret(Node*, Node*);
-int	cgen_inline(Node*, Node*);
 void	restx(Node*, Node*);
 void	savex(int, Node*, Node*, Node*, Type*);
 int	componentgen(Node*, Node*);
@@ -103,9 +108,8 @@ int	componentgen(Node*, Node*);
  */
 void	clearp(Prog*);
 void	proglist(void);
-Prog*	gbranch(int, Type*);
+Prog*	gbranch(int, Type*, int);
 Prog*	prog(int);
-void	gaddoffset(Node*);
 void	gconv(int, int);
 int	conv2pt(Type*);
 vlong	convvtox(vlong, int);
@@ -126,9 +130,9 @@ Plist*	newplist(void);
 int	isfat(Type*);
 void	sudoclean(void);
 int	sudoaddable(int, Node*, Addr*);
-void	afunclit(Addr*);
-void	datagostring(Strlit*, Addr*);
+void	afunclit(Addr*, Node*);
 void	nodfconst(Node*, Type*, Mpflt*);
+void	gtrack(Sym*);
 
 /*
  * cplx.c
@@ -136,12 +140,12 @@ void	nodfconst(Node*, Type*, Mpflt*);
 int	complexop(Node*, Node*);
 void	complexmove(Node*, Node*);
 void	complexgen(Node*, Node*);
-void	complexbool(int, Node*, Node*, int, Prog*);
 
 /*
  * gobj.c
  */
 void	datastring(char*, int, Addr*);
+void	datagostring(Strlit*, Addr*);
 
 /*
  * list.c
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index 02e67d6..23bb509 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -25,6 +25,9 @@ void
 markautoused(Prog* p)
 {
 	for (; p; p = p->link) {
+		if (p->as == ATYPE)
+			continue;
+
 		if (p->from.type == D_AUTO && p->from.node)
 			p->from.node->used = 1;
 
@@ -35,14 +38,22 @@ markautoused(Prog* p)
 
 // Fixup instructions after compactframe has moved all autos around.
 void
-fixautoused(Prog* p)
+fixautoused(Prog *p)
 {
-	for (; p; p = p->link) {
+	Prog **lp;
+
+	for (lp=&p; (p=*lp) != P; ) {
+		if (p->as == ATYPE && p->from.node && p->from.type == D_AUTO && !p->from.node->used) {
+			*lp = p->link;
+			continue;
+		}
 		if (p->from.type == D_AUTO && p->from.node)
 			p->from.offset += p->from.node->stkdelta;
 
 		if (p->to.type == D_AUTO && p->to.node)
 			p->to.offset += p->to.node->stkdelta;
+
+		lp = &p->link;
 	}
 }
 
@@ -50,15 +61,18 @@ fixautoused(Prog* p)
 /*
  * generate:
  *	call f
+ *	proc=-1	normal call but no return
  *	proc=0	normal call
  *	proc=1	goroutine run in new proc
  *	proc=2	defer call save away stack
+  *	proc=3	normal call to C pointer (not Go func value)
  */
 void
 ginscall(Node *f, int proc)
 {
 	Prog *p;
 	Node reg, con;
+	Node r1;
 
 	switch(proc) {
 	default:
@@ -66,14 +80,38 @@ ginscall(Node *f, int proc)
 		break;
 
 	case 0:	// normal call
-		p = gins(ACALL, N, f);
-		afunclit(&p->to);
+	case -1:	// normal call but no return
+		if(f->op == ONAME && f->class == PFUNC) {
+			p = gins(ACALL, N, f);
+			afunclit(&p->to, f);
+			if(proc == -1 || noreturn(p))
+				gins(AUNDEF, N, N);
+			break;
+		}
+		nodreg(&reg, types[tptr], D_DX);
+		nodreg(&r1, types[tptr], D_BX);
+		gmove(f, &reg);
+		reg.op = OINDREG;
+		gmove(&reg, &r1);
+		reg.op = OREGISTER;
+		gins(ACALL, &reg, &r1);
+		break;
+	
+	case 3:	// normal call of c function pointer
+		gins(ACALL, N, f);
 		break;
 
 	case 1:	// call in new proc (go)
 	case 2:	// deferred call (defer)
 		nodreg(&reg, types[TINT64], D_CX);
-		gins(APUSHQ, f, N);
+		if(flag_largemodel) {
+			regalloc(&r1, f->type, f);
+			gmove(f, &r1);
+			gins(APUSHQ, &r1, N);
+			regfree(&r1);
+		} else {
+			gins(APUSHQ, f, N);
+		}
 		nodconst(&con, types[TINT32], argsize(f->type));
 		gins(APUSHQ, &con, N);
 		if(proc == 1)
@@ -88,7 +126,7 @@ ginscall(Node *f, int proc)
 		if(proc == 2) {
 			nodreg(&reg, types[TINT64], D_AX);
 			gins(ATESTQ, &reg, &reg);
-			patch(gbranch(AJNE, T), retpc);
+			patch(gbranch(AJNE, T, -1), retpc);
 		}
 		break;
 	}
@@ -102,7 +140,7 @@ void
 cgen_callinter(Node *n, Node *res, int proc)
 {
 	Node *i, *f;
-	Node tmpi, nodo, nodr, nodsp;
+	Node tmpi, nodi, nodo, nodr, nodsp;
 
 	i = n->left;
 	if(i->op != ODOTINTER)
@@ -122,21 +160,34 @@ cgen_callinter(Node *n, Node *res, int proc)
 
 	genlist(n->list);		// assign the args
 
-	regalloc(&nodr, types[tptr], res);
-	regalloc(&nodo, types[tptr], &nodr);
-	nodo.op = OINDREG;
-
-	agen(i, &nodr);         // REG = &inter
+	// i is now addable, prepare an indirected
+	// register to hold its address.
+	igen(i, &nodi, res);		// REG = &inter
 
 	nodindreg(&nodsp, types[tptr], D_SP);
-	nodo.xoffset += widthptr;
-	cgen(&nodo, &nodsp);	// 0(SP) = 8(REG) -- i.data
-
-	nodo.xoffset -= widthptr;
-	cgen(&nodo, &nodr);	// REG = 0(REG) -- i.tab
-
+	nodi.type = types[tptr];
+	nodi.xoffset += widthptr;
+	cgen(&nodi, &nodsp);	// 0(SP) = 8(REG) -- i.data
+
+	regalloc(&nodo, types[tptr], res);
+	nodi.type = types[tptr];
+	nodi.xoffset -= widthptr;
+	cgen(&nodi, &nodo);	// REG = 0(REG) -- i.tab
+	regfree(&nodi);
+
+	regalloc(&nodr, types[tptr], &nodo);
+	if(n->left->xoffset == BADWIDTH)
+		fatal("cgen_callinter: badwidth");
+	nodo.op = OINDREG;
 	nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
-	cgen(&nodo, &nodr);	// REG = 32+offset(REG) -- i.tab->fun[f]
+	if(proc == 0) {
+		// plain call: use direct c function pointer - more efficient
+		cgen(&nodo, &nodr);	// REG = 32+offset(REG) -- i.tab->fun[f]
+		proc = 3;
+	} else {
+		// go/defer. generate go func value.
+		gins(ALEAQ, &nodo, &nodr);	// REG = &(32+offset(REG)) -- i.tab->fun[f]
+	}
 
 	// BOTCH nodr.type = fntype;
 	nodr.type = n->left->type;
@@ -182,7 +233,7 @@ cgen_call(Node *n, int proc)
 		nod.type = t;
 		ginscall(&nod, proc);
 		regfree(&nod);
-		goto ret;
+		return;
 	}
 
 	// call pointer
@@ -192,16 +243,12 @@ cgen_call(Node *n, int proc)
 		nod.type = t;
 		ginscall(&nod, proc);
 		regfree(&nod);
-		goto ret;
+		return;
 	}
 
 	// call direct
 	n->left->method = 1;
 	ginscall(n->left, proc);
-
-
-ret:
-	;
 }
 
 /*
@@ -389,7 +436,9 @@ cgen_asop(Node *n)
 hard:
 	n2.op = 0;
 	n1.op = 0;
-	if(nr->ullman >= nl->ullman || nl->addable) {
+	if(nr->op == OLITERAL) {
+		// don't allocate a register for literals.
+	} else if(nr->ullman >= nl->ullman || nl->addable) {
 		regalloc(&n2, nr->type, N);
 		cgen(nr, &n2);
 		nr = &n2;
@@ -447,10 +496,10 @@ void
 dodiv(int op, Node *nl, Node *nr, Node *res)
 {
 	int a, check;
-	Node n3, n4, n5;
+	Node n3, n4;
 	Type *t, *t0;
 	Node ax, dx, ax1, n31, oldax, olddx;
-	Prog *p1, *p2, *p3;
+	Prog *p1, *p2;
 
 	// Have to be careful about handling
 	// most negative int divided by -1 correctly.
@@ -501,30 +550,22 @@ dodiv(int op, Node *nl, Node *nr, Node *res)
 		gmove(&n31, &n3);
 	}
 
-	p3 = P;
+	p2 = P;
 	if(check) {
 		nodconst(&n4, t, -1);
 		gins(optoas(OCMP, t), &n3, &n4);
-		p1 = gbranch(optoas(ONE, t), T);
-		nodconst(&n4, t, -1LL<<(t->width*8-1));
-		if(t->width == 8) {
-			n5 = n4;
-			regalloc(&n4, t, N);
-			gins(AMOVQ, &n5, &n4);
-		}
-		gins(optoas(OCMP, t), &ax, &n4);
-		p2 = gbranch(optoas(ONE, t), T);
-		if(op == ODIV)
-			gmove(&n4, res);
-		if(t->width == 8)
-			regfree(&n4);
-		if(op == OMOD) {
+		p1 = gbranch(optoas(ONE, t), T, +1);
+		if(op == ODIV) {
+			// a / (-1) is -a.
+			gins(optoas(OMINUS, t), N, &ax);
+			gmove(&ax, res);
+		} else {
+			// a % (-1) is 0.
 			nodconst(&n4, t, 0);
 			gmove(&n4, res);
 		}
-		p3 = gbranch(AJMP, T);
+		p2 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
-		patch(p2, pc);
 	}
 	savex(D_DX, &dx, &olddx, res, t);
 	if(!issigned[t->etype]) {
@@ -540,7 +581,7 @@ dodiv(int op, Node *nl, Node *nr, Node *res)
 		gmove(&dx, res);
 	restx(&dx, &olddx);
 	if(check)
-		patch(p3, pc);
+		patch(p2, pc);
 	restx(&ax, &oldax);
 }
 
@@ -594,134 +635,21 @@ restx(Node *x, Node *oldx)
 void
 cgen_div(int op, Node *nl, Node *nr, Node *res)
 {
-	Node n1, n2, n3, savl, savr;
-	Node ax, dx, oldax, olddx;
-	int n, w, s, a;
+	Node n1, n2, n3;
+	int w, a;
 	Magic m;
 
-	if(nl->ullman >= UINF) {
-		tempname(&savl, nl->type);
-		cgen(nl, &savl);
-		nl = &savl;
-	}
-	if(nr->ullman >= UINF) {
-		tempname(&savr, nr->type);
-		cgen(nr, &savr);
-		nr = &savr;
-	}
-
 	if(nr->op != OLITERAL)
 		goto longdiv;
-
-	// special cases of mod/div
-	// by a constant
 	w = nl->type->width*8;
-	s = 0;
-	n = powtwo(nr);
-	if(n >= 1000) {
-		// negative power of 2
-		s = 1;
-		n -= 1000;
-	}
-
-	if(n+1 >= w) {
-		// just sign bit
-		goto longdiv;
-	}
 
-	if(n < 0)
-		goto divbymul;
-	switch(n) {
-	case 0:
-		// divide by 1
-		regalloc(&n1, nl->type, res);
-		cgen(nl, &n1);
-		if(op == OMOD) {
-			gins(optoas(OXOR, nl->type), &n1, &n1);
-		} else
-		if(s)
-			gins(optoas(OMINUS, nl->type), N, &n1);
-		gmove(&n1, res);
-		regfree(&n1);
-		return;
-	case 1:
-		// divide by 2
-		if(op == OMOD) {
-			if(issigned[nl->type->etype])
-				goto longmod;
-			regalloc(&n1, nl->type, res);
-			cgen(nl, &n1);
-			nodconst(&n2, nl->type, 1);
-			gins(optoas(OAND, nl->type), &n2, &n1);
-			gmove(&n1, res);
-			regfree(&n1);
-			return;
-		}
-		regalloc(&n1, nl->type, res);
-		cgen(nl, &n1);
-		if(!issigned[nl->type->etype])
-			break;
-
-		// develop -1 iff nl is negative
-		regalloc(&n2, nl->type, N);
-		gmove(&n1, &n2);
-		nodconst(&n3, nl->type, w-1);
-		gins(optoas(ORSH, nl->type), &n3, &n2);
-		gins(optoas(OSUB, nl->type), &n2, &n1);
-		regfree(&n2);
-		break;
-	default:
-		if(op == OMOD) {
-			if(issigned[nl->type->etype])
-				goto longmod;
-			regalloc(&n1, nl->type, res);
-			cgen(nl, &n1);
-			nodconst(&n2, nl->type, mpgetfix(nr->val.u.xval)-1);
-			if(!smallintconst(&n2)) {
-				regalloc(&n3, nl->type, N);
-				gmove(&n2, &n3);
-				gins(optoas(OAND, nl->type), &n3, &n1);
-				regfree(&n3);
-			} else
-				gins(optoas(OAND, nl->type), &n2, &n1);
-			gmove(&n1, res);
-			regfree(&n1);
-			return;
-		}
-		regalloc(&n1, nl->type, res);
-		cgen(nl, &n1);
-		if(!issigned[nl->type->etype])
-			break;
-
-		// develop (2^k)-1 iff nl is negative
-		regalloc(&n2, nl->type, N);
-		gmove(&n1, &n2);
-		nodconst(&n3, nl->type, w-1);
-		gins(optoas(ORSH, nl->type), &n3, &n2);
-		nodconst(&n3, nl->type, w-n);
-		gins(optoas(ORSH, tounsigned(nl->type)), &n3, &n2);
-		gins(optoas(OADD, nl->type), &n2, &n1);
-		regfree(&n2);
-		break;
-	}
-	nodconst(&n2, nl->type, n);
-	gins(optoas(ORSH, nl->type), &n2, &n1);
-	if(s)
-		gins(optoas(OMINUS, nl->type), N, &n1);
-	gmove(&n1, res);
-	regfree(&n1);
-	return;
-
-divbymul:
+	// Front end handled 32-bit division. We only need to handle 64-bit.
 	// try to do division by multiply by (2^w)/d
 	// see hacker's delight chapter 10
 	switch(simtype[nl->type->etype]) {
 	default:
 		goto longdiv;
 
-	case TUINT8:
-	case TUINT16:
-	case TUINT32:
 	case TUINT64:
 		m.w = w;
 		m.ud = mpgetfix(nr->val.u.xval);
@@ -731,47 +659,28 @@ divbymul:
 		if(op == OMOD)
 			goto longmod;
 
-		regalloc(&n1, nl->type, N);
-		cgen(nl, &n1);				// num -> reg(n1)
-
-		savex(D_AX, &ax, &oldax, res, nl->type);
-		savex(D_DX, &dx, &olddx, res, nl->type);
-
+		cgenr(nl, &n1, N);
 		nodconst(&n2, nl->type, m.um);
-		gmove(&n2, &ax);			// const->ax
-
-		gins(optoas(OHMUL, nl->type), &n1, N);	// imul reg
-		if(w == 8) {
-			// fix up 8-bit multiply
-			Node ah, dl;
-			nodreg(&ah, types[TUINT8], D_AH);
-			nodreg(&dl, types[TUINT8], D_DL);
-			gins(AMOVB, &ah, &dl);
-		}
+		regalloc(&n3, nl->type, res);
+		cgen_hmul(&n1, &n2, &n3);
 
 		if(m.ua) {
 			// need to add numerator accounting for overflow
-			gins(optoas(OADD, nl->type), &n1, &dx);
+			gins(optoas(OADD, nl->type), &n1, &n3);
 			nodconst(&n2, nl->type, 1);
-			gins(optoas(ORRC, nl->type), &n2, &dx);
+			gins(optoas(ORROTC, nl->type), &n2, &n3);
 			nodconst(&n2, nl->type, m.s-1);
-			gins(optoas(ORSH, nl->type), &n2, &dx);
+			gins(optoas(ORSH, nl->type), &n2, &n3);
 		} else {
 			nodconst(&n2, nl->type, m.s);
-			gins(optoas(ORSH, nl->type), &n2, &dx);	// shift dx
+			gins(optoas(ORSH, nl->type), &n2, &n3);	// shift dx
 		}
 
-
+		gmove(&n3, res);
 		regfree(&n1);
-		gmove(&dx, res);
-
-		restx(&ax, &oldax);
-		restx(&dx, &olddx);
+		regfree(&n3);
 		return;
 
-	case TINT8:
-	case TINT16:
-	case TINT32:
 	case TINT64:
 		m.w = w;
 		m.sd = mpgetfix(nr->val.u.xval);
@@ -781,47 +690,32 @@ divbymul:
 		if(op == OMOD)
 			goto longmod;
 
-		regalloc(&n1, nl->type, N);
-		cgen(nl, &n1);				// num -> reg(n1)
-
-		savex(D_AX, &ax, &oldax, res, nl->type);
-		savex(D_DX, &dx, &olddx, res, nl->type);
-
+		cgenr(nl, &n1, res);
 		nodconst(&n2, nl->type, m.sm);
-		gmove(&n2, &ax);			// const->ax
-
-		gins(optoas(OHMUL, nl->type), &n1, N);	// imul reg
-		if(w == 8) {
-			// fix up 8-bit multiply
-			Node ah, dl;
-			nodreg(&ah, types[TUINT8], D_AH);
-			nodreg(&dl, types[TUINT8], D_DL);
-			gins(AMOVB, &ah, &dl);
-		}
+		regalloc(&n3, nl->type, N);
+		cgen_hmul(&n1, &n2, &n3);
 
 		if(m.sm < 0) {
 			// need to add numerator
-			gins(optoas(OADD, nl->type), &n1, &dx);
+			gins(optoas(OADD, nl->type), &n1, &n3);
 		}
 
 		nodconst(&n2, nl->type, m.s);
-		gins(optoas(ORSH, nl->type), &n2, &dx);	// shift dx
+		gins(optoas(ORSH, nl->type), &n2, &n3);	// shift n3
 
 		nodconst(&n2, nl->type, w-1);
 		gins(optoas(ORSH, nl->type), &n2, &n1);	// -1 iff num is neg
-		gins(optoas(OSUB, nl->type), &n1, &dx);	// added
+		gins(optoas(OSUB, nl->type), &n1, &n3);	// added
 
 		if(m.sd < 0) {
 			// this could probably be removed
 			// by factoring it into the multiplier
-			gins(optoas(OMINUS, nl->type), N, &dx);
+			gins(optoas(OMINUS, nl->type), N, &n3);
 		}
 
+		gmove(&n3, res);
 		regfree(&n1);
-		gmove(&dx, res);
-
-		restx(&ax, &oldax);
-		restx(&dx, &olddx);
+		regfree(&n3);
 		return;
 	}
 	goto longdiv;
@@ -858,12 +752,48 @@ longmod:
 }
 
 /*
+ * generate high multiply:
+ *   res = (nl*nr) >> width
+ */
+void
+cgen_hmul(Node *nl, Node *nr, Node *res)
+{
+	Type *t;
+	int a;
+	Node n1, n2, ax, dx, *tmp;
+
+	t = nl->type;
+	a = optoas(OHMUL, t);
+	if(nl->ullman < nr->ullman) {
+		tmp = nl;
+		nl = nr;
+		nr = tmp;
+	}
+	cgenr(nl, &n1, res);
+	cgenr(nr, &n2, N);
+	nodreg(&ax, t, D_AX);
+	gmove(&n1, &ax);
+	gins(a, &n2, N);
+	regfree(&n2);
+	regfree(&n1);
+
+	if(t->width == 1) {
+		// byte multiply behaves differently.
+		nodreg(&ax, t, D_AH);
+		nodreg(&dx, t, D_DL);
+		gmove(&ax, &dx);
+	}
+	nodreg(&dx, t, D_DX);
+	gmove(&dx, res);
+}
+
+/*
  * generate shift according to op, one of:
  *	res = nl << nr
  *	res = nl >> nr
  */
 void
-cgen_shift(int op, Node *nl, Node *nr, Node *res)
+cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
 {
 	Node n1, n2, n3, n4, n5, cx, oldcx;
 	int a, rcx;
@@ -878,7 +808,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
 		cgen(nl, &n1);
 		sc = mpgetfix(nr->val.u.xval);
 		if(sc >= nl->type->width*8) {
-			// large shift gets 2 shifts by width
+			// large shift gets 2 shifts by width-1
 			nodconst(&n3, types[TUINT32], nl->type->width*8-1);
 			gins(a, &n3, &n1);
 			gins(a, &n3, &n1);
@@ -937,17 +867,20 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
 	regfree(&n3);
 
 	// test and fix up large shifts
-	nodconst(&n3, tcount, nl->type->width*8);
-	gins(optoas(OCMP, tcount), &n1, &n3);
-	p1 = gbranch(optoas(OLT, tcount), T);
-	if(op == ORSH && issigned[nl->type->etype]) {
-		nodconst(&n3, types[TUINT32], nl->type->width*8-1);
-		gins(a, &n3, &n2);
-	} else {
-		nodconst(&n3, nl->type, 0);
-		gmove(&n3, &n2);
+	if(!bounded) {
+		nodconst(&n3, tcount, nl->type->width*8);
+		gins(optoas(OCMP, tcount), &n1, &n3);
+		p1 = gbranch(optoas(OLT, tcount), T, +1);
+		if(op == ORSH && issigned[nl->type->etype]) {
+			nodconst(&n3, types[TUINT32], nl->type->width*8-1);
+			gins(a, &n3, &n2);
+		} else {
+			nodconst(&n3, nl->type, 0);
+			gmove(&n3, &n2);
+		}
+		patch(p1, pc);
 	}
-	patch(p1, pc);
+
 	gins(a, &n1, &n2);
 
 	if(oldcx.op != 0) {
@@ -968,46 +901,40 @@ ret:
 /*
  * generate byte multiply:
  *	res = nl * nr
- * no 2-operand byte multiply instruction so have to do
- * 16-bit multiply and take bottom half.
+ * there is no 2-operand byte multiply instruction so
+ * we do a full-width multiplication and truncate afterwards.
  */
 void
 cgen_bmul(int op, Node *nl, Node *nr, Node *res)
 {
-	Node n1b, n2b, n1w, n2w;
+	Node n1, n2, n1b, n2b, *tmp;
 	Type *t;
 	int a;
 
-	if(nl->ullman >= nr->ullman) {
-		regalloc(&n1b, nl->type, res);
-		cgen(nl, &n1b);
-		regalloc(&n2b, nr->type, N);
-		cgen(nr, &n2b);
-	} else {
-		regalloc(&n2b, nr->type, N);
-		cgen(nr, &n2b);
-		regalloc(&n1b, nl->type, res);
-		cgen(nl, &n1b);
+	// largest ullman on left.
+	if(nl->ullman < nr->ullman) {
+		tmp = nl;
+		nl = nr;
+		nr = tmp;
 	}
 
-	// copy from byte to short registers
-	t = types[TUINT16];
-	if(issigned[nl->type->etype])
-		t = types[TINT16];
-
-	regalloc(&n2w, t, &n2b);
-	cgen(&n2b, &n2w);
-
-	regalloc(&n1w, t, &n1b);
-	cgen(&n1b, &n1w);
+	// generate operands in "8-bit" registers.
+	regalloc(&n1b, nl->type, res);
+	cgen(nl, &n1b);
+	regalloc(&n2b, nr->type, N);
+	cgen(nr, &n2b);
 
+	// perform full-width multiplication.
+	t = types[TUINT64];
+	if(issigned[nl->type->etype])
+		t = types[TINT64];
+	nodreg(&n1, t, n1b.val.u.reg);
+	nodreg(&n2, t, n2b.val.u.reg);
 	a = optoas(op, t);
-	gins(a, &n2w, &n1w);
-	cgen(&n1w, &n1b);
-	cgen(&n1b, res);
+	gins(a, &n2, &n1);
 
-	regfree(&n1w);
-	regfree(&n2w);
+	// truncate.
+	gmove(&n1, res);
 	regfree(&n1b);
 	regfree(&n2b);
 }
@@ -1024,9 +951,9 @@ clearfat(Node *nl)
 
 
 	w = nl->type->width;
-	if(w == 16)
-		if(componentgen(N, nl))
-			return;
+	// Avoid taking the address for simple enough types.
+	if(componentgen(N, nl))
+		return;
 
 	c = w % 8;	// bytes
 	q = w / 8;	// quads
@@ -1060,366 +987,3 @@ clearfat(Node *nl)
 	restx(&n1, &oldn1);
 	restx(&ax, &oldax);
 }
-
-static int
-regcmp(const void *va, const void *vb)
-{
-	Node *ra, *rb;
-
-	ra = (Node*)va;
-	rb = (Node*)vb;
-	return ra->local - rb->local;
-}
-
-static	Prog*	throwpc;
-
-void
-getargs(NodeList *nn, Node *reg, int n)
-{
-	NodeList *l;
-	int i;
-
-	throwpc = nil;
-
-	l = nn;
-	for(i=0; i<n; i++) {
-		if(!smallintconst(l->n->right) && !isslice(l->n->right->type)) {
-			regalloc(reg+i, l->n->right->type, N);
-			cgen(l->n->right, reg+i);
-		} else
-			reg[i] = *l->n->right;
-		if(reg[i].local != 0)
-			yyerror("local used");
-		reg[i].local = l->n->left->xoffset;
-		l = l->next;
-	}
-	qsort((void*)reg, n, sizeof(*reg), regcmp);
-	for(i=0; i<n; i++)
-		reg[i].local = 0;
-}
-
-void
-cmpandthrow(Node *nl, Node *nr)
-{
-	vlong cl;
-	Prog *p1;
-	int op;
-	Node *c;
-	Type *t;
-	Node n1;
-	
-	if(nl->op == OCONV && is64(nl->type))
-		nl = nl->left;
-	if(nr->op == OCONV && is64(nr->type))
-		nr = nr->left;
-
-	op = OLE;
-	if(smallintconst(nl)) {
-		cl = mpgetfix(nl->val.u.xval);
-		if(cl == 0)
-			return;
-		if(smallintconst(nr))
-			return;
-		// put the constant on the right
-		op = brrev(op);
-		c = nl;
-		nl = nr;
-		nr = c;
-	}
-	if(is64(nr->type) && smallintconst(nr))
-		nr->type = types[TUINT32];
-
-	n1.op = OXXX;
-	t = types[TUINT32];
-	if(nl->type->width != t->width || nr->type->width != t->width) {
-		if((is64(nl->type) && nl->op != OLITERAL) || (is64(nr->type) && nr->op != OLITERAL))
-			t = types[TUINT64];
-
-		// Check if we need to use a temporary.
-		// At least one of the arguments is 32 bits
-		// (the len or cap) so one temporary suffices.
-		if(nl->type->width != t->width && nl->op != OLITERAL) {
-			regalloc(&n1, t, nl);
-			gmove(nl, &n1);
-			nl = &n1;
-		} else if(nr->type->width != t->width && nr->op != OLITERAL) {
-			regalloc(&n1, t, nr);
-			gmove(nr, &n1);
-			nr = &n1;
-		}
-	}
-	gins(optoas(OCMP, t), nl, nr);
-	if(n1.op != OXXX)
-		regfree(&n1);
-	if(throwpc == nil) {
-		p1 = gbranch(optoas(op, t), T);
-		throwpc = pc;
-		ginscall(panicslice, 0);
-		patch(p1, pc);
-	} else {
-		op = brcom(op);
-		p1 = gbranch(optoas(op, t), T);
-		patch(p1, throwpc);
-	}
-}
-
-int
-sleasy(Node *n)
-{
-	if(n->op != ONAME)
-		return 0;
-	if(!n->addable)
-		return 0;
-	return 1;
-}
-
-// generate inline code for
-//	slicearray
-//	sliceslice
-//	arraytoslice
-int
-cgen_inline(Node *n, Node *res)
-{
-	Node nodes[5];
-	Node n1, n2, nres, ntemp;
-	vlong v;
-	int i, narg, nochk;
-
-	if(n->op != OCALLFUNC)
-		goto no;
-	if(!n->left->addable)
-		goto no;
-	if(n->left->sym == S)
-		goto no;
-	if(n->left->sym->pkg != runtimepkg)
-		goto no;
-	if(strcmp(n->left->sym->name, "slicearray") == 0)
-		goto slicearray;
-	if(strcmp(n->left->sym->name, "sliceslice") == 0) {
-		narg = 4;
-		goto sliceslice;
-	}
-	if(strcmp(n->left->sym->name, "sliceslice1") == 0) {
-		narg = 3;
-		goto sliceslice;
-	}
-	goto no;
-
-slicearray:
-	if(!sleasy(res))
-		goto no;
-	getargs(n->list, nodes, 5);
-
-	// if(hb[3] > nel[1]) goto throw
-	cmpandthrow(&nodes[3], &nodes[1]);
-
-	// if(lb[2] > hb[3]) goto throw
-	cmpandthrow(&nodes[2], &nodes[3]);
-
-	// len = hb[3] - lb[2] (destroys hb)
-	n2 = *res;
-	n2.xoffset += Array_nel;
-	n2.type = types[TUINT32];
-
-	if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) {
-		v = mpgetfix(nodes[3].val.u.xval) -
-			mpgetfix(nodes[2].val.u.xval);
-		nodconst(&n1, types[TUINT32], v);
-		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-	} else {
-		regalloc(&n1, types[TUINT32], &nodes[3]);
-		gmove(&nodes[3], &n1);
-		if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
-			gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
-		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-		regfree(&n1);
-	}
-
-	// cap = nel[1] - lb[2] (destroys nel)
-	n2 = *res;
-	n2.xoffset += Array_cap;
-	n2.type = types[TUINT32];
-
-	if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) {
-		v = mpgetfix(nodes[1].val.u.xval) -
-			mpgetfix(nodes[2].val.u.xval);
-		nodconst(&n1, types[TUINT32], v);
-		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-	} else {
-		regalloc(&n1, types[TUINT32], &nodes[1]);
-		gmove(&nodes[1], &n1);
-		if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
-			gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
-		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-		regfree(&n1);
-	}
-
-	// if slice could be too big, dereference to
-	// catch nil array pointer.
-	if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
-		n2 = nodes[0];
-		n2.xoffset = 0;
-		n2.op = OINDREG;
-		n2.type = types[TUINT8];
-		gins(ATESTB, nodintconst(0), &n2);
-	}
-
-	// ary = old[0] + (lb[2] * width[4]) (destroys old)
-	n2 = *res;
-	n2.xoffset += Array_array;
-	n2.type = types[tptr];
-
-	if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) {
-		v = mpgetfix(nodes[2].val.u.xval) *
-			mpgetfix(nodes[4].val.u.xval);
-		if(v != 0)
-			ginscon(optoas(OADD, types[tptr]), v, &nodes[0]);
-	} else {
-		regalloc(&n1, types[tptr], &nodes[2]);
-		gmove(&nodes[2], &n1);
-		if(!smallintconst(&nodes[4]) || mpgetfix(nodes[4].val.u.xval) != 1)
-			gins(optoas(OMUL, types[tptr]), &nodes[4], &n1);
-		gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
-		regfree(&n1);
-	}
-	gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
-
-	for(i=0; i<5; i++) {
-		if(nodes[i].op == OREGISTER)
-			regfree(&nodes[i]);
-	}
-	return 1;
-
-sliceslice:
-	nochk = n->etype;  // skip bounds checking
-	ntemp.op = OXXX;
-	if(!sleasy(n->list->n->right)) {
-		Node *n0;
-		
-		n0 = n->list->n->right;
-		tempname(&ntemp, res->type);
-		cgen(n0, &ntemp);
-		n->list->n->right = &ntemp;
-		getargs(n->list, nodes, narg);
-		n->list->n->right = n0;
-	} else
-		getargs(n->list, nodes, narg);
-
-	nres = *res;		// result
-	if(!sleasy(res)) {
-		if(ntemp.op == OXXX)
-			tempname(&ntemp, res->type);
-		nres = ntemp;
-	}
-
-	if(narg == 3) {	// old[lb:]
-		// move width to where it would be for old[lb:hb]
-		nodes[3] = nodes[2];
-		nodes[2].op = OXXX;
-		
-		// if(lb[1] > old.nel[0]) goto throw;
-		n2 = nodes[0];
-		n2.xoffset += Array_nel;
-		n2.type = types[TUINT32];
-		if(!nochk)
-			cmpandthrow(&nodes[1], &n2);
-
-		// ret.nel = old.nel[0]-lb[1];
-		n2 = nodes[0];
-		n2.xoffset += Array_nel;
-		n2.type = types[TUINT32];
-	
-		regalloc(&n1, types[TUINT32], N);
-		gins(optoas(OAS, types[TUINT32]), &n2, &n1);
-		if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
-			gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
-	
-		n2 = nres;
-		n2.xoffset += Array_nel;
-		n2.type = types[TUINT32];
-		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-		regfree(&n1);
-	} else {	// old[lb:hb]
-		n2 = nodes[0];
-		n2.xoffset += Array_cap;
-		n2.type = types[TUINT32];
-		if(!nochk) {
-			// if(hb[2] > old.cap[0]) goto throw;
-			cmpandthrow(&nodes[2], &n2);
-			// if(lb[1] > hb[2]) goto throw;
-			cmpandthrow(&nodes[1], &nodes[2]);
-		}
-		// ret.len = hb[2]-lb[1]; (destroys hb[2])
-		n2 = nres;
-		n2.xoffset += Array_nel;
-		n2.type = types[TUINT32];
-
-		if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) {
-			v = mpgetfix(nodes[2].val.u.xval) -
-				mpgetfix(nodes[1].val.u.xval);
-			nodconst(&n1, types[TUINT32], v);
-			gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-		} else {
-			regalloc(&n1, types[TUINT32], &nodes[2]);
-			gmove(&nodes[2], &n1);
-			if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
-				gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
-			gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-			regfree(&n1);
-		}
-	}
-
-	// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
-	n2 = nodes[0];
-	n2.xoffset += Array_cap;
-	n2.type = types[TUINT32];
-
-	regalloc(&n1, types[TUINT32], &nodes[2]);
-	gins(optoas(OAS, types[TUINT32]), &n2, &n1);
-	if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
-		gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
-
-	n2 = nres;
-	n2.xoffset += Array_cap;
-	n2.type = types[TUINT32];
-
-	gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-	regfree(&n1);
-
-	// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
-	n2 = nodes[0];
-	n2.xoffset += Array_array;
-	n2.type = types[tptr];
-	regalloc(&n1, types[tptr], &nodes[1]);
-	if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) {
-		gins(optoas(OAS, types[tptr]), &n2, &n1);
-		v = mpgetfix(nodes[1].val.u.xval) *
-			mpgetfix(nodes[3].val.u.xval);
-		if(v != 0)
-			ginscon(optoas(OADD, types[tptr]), v, &n1);
-	} else {
-		gmove(&nodes[1], &n1);
-		if(!smallintconst(&nodes[3]) || mpgetfix(nodes[3].val.u.xval) != 1)
-			gins(optoas(OMUL, types[tptr]), &nodes[3], &n1);
-		gins(optoas(OADD, types[tptr]), &n2, &n1);
-	}
-
-	n2 = nres;
-	n2.xoffset += Array_array;
-	n2.type = types[tptr];
-	gins(optoas(OAS, types[tptr]), &n1, &n2);
-	regfree(&n1);
-
-	for(i=0; i<4; i++) {
-		if(nodes[i].op == OREGISTER)
-			regfree(&nodes[i]);
-	}
-
-	if(!sleasy(res)) {
-		cgen(&nres, res);
-	}
-	return 1;
-
-no:
-	return 0;
-}
diff --git a/src/cmd/6g/gobj.c b/src/cmd/6g/gobj.c
index 8c92083..508a354 100644
--- a/src/cmd/6g/gobj.c
+++ b/src/cmd/6g/gobj.c
@@ -94,9 +94,9 @@ zaddr(Biobuf *b, Addr *a, int s, int gotype)
 	switch(a->type) {
 
 	case D_BRANCH:
-		if(a->branch == nil)
+		if(a->u.branch == nil)
 			fatal("unpatched branch");
-		a->offset = a->branch->loc;
+		a->offset = a->u.branch->loc;
 
 	default:
 		t |= T_TYPE;
@@ -139,7 +139,7 @@ zaddr(Biobuf *b, Addr *a, int s, int gotype)
 	if(t & T_SYM)		/* implies sym */
 		Bputc(b, s);
 	if(t & T_FCONST) {
-		ieeedtod(&e, a->dval);
+		ieeedtod(&e, a->u.dval);
 		l = e;
 		Bputc(b, l);
 		Bputc(b, l>>8);
@@ -153,7 +153,7 @@ zaddr(Biobuf *b, Addr *a, int s, int gotype)
 		return;
 	}
 	if(t & T_SCONST) {
-		n = a->sval;
+		n = a->u.sval;
 		for(i=0; i<NSNAME; i++) {
 			Bputc(b, *n);
 			n++;
@@ -295,7 +295,7 @@ dsname(Sym *s, int off, char *t, int n)
 	
 	p->to.type = D_SCONST;
 	p->to.index = D_NONE;
-	memmove(p->to.sval, t, n);
+	memmove(p->to.u.sval, t, n);
 	return off + n;
 }
 
@@ -312,8 +312,8 @@ datastring(char *s, int len, Addr *a)
 	a->type = D_EXTERN;
 	a->sym = sym;
 	a->node = sym->def;
-	a->offset = widthptr+4;  // skip header
-	a->etype = TINT32;
+	a->offset = widthptr+widthint;  // skip header
+	a->etype = simtype[TINT];
 }
 
 /*
@@ -324,7 +324,7 @@ void
 datagostring(Strlit *sval, Addr *a)
 {
 	Sym *sym;
-	
+
 	sym = stringsym(sval->s, sval->len);
 	a->type = D_EXTERN;
 	a->sym = sym;
@@ -364,13 +364,13 @@ gdatacomplex(Node *nam, Mpcplx *cval)
 	p = gins(ADATA, nam, N);
 	p->from.scale = w;
 	p->to.type = D_FCONST;
-	p->to.dval = mpgetflt(&cval->real);
+	p->to.u.dval = mpgetflt(&cval->real);
 
 	p = gins(ADATA, nam, N);
 	p->from.scale = w;
 	p->from.offset += w;
 	p->to.type = D_FCONST;
-	p->to.dval = mpgetflt(&cval->imag);
+	p->to.u.dval = mpgetflt(&cval->imag);
 }
 
 void
@@ -386,10 +386,10 @@ gdatastring(Node *nam, Strlit *sval)
 	p->to.type = D_ADDR;
 //print("%P\n", p);
 
-	nodconst(&nod1, types[TINT32], sval->len);
+	nodconst(&nod1, types[TINT], sval->len);
 	p = gins(ADATA, nam, &nod1);
-	p->from.scale = types[TINT32]->width;
-	p->from.offset += types[tptr]->width;
+	p->from.scale = widthint;
+	p->from.offset += widthptr;
 }
 
 int
@@ -408,7 +408,7 @@ dstringptr(Sym *s, int off, char *str)
 	datastring(str, strlen(str)+1, &p->to);
 	p->to.index = p->to.type;
 	p->to.type = D_ADDR;
-	p->to.etype = TINT32;
+	p->to.etype = simtype[TINT];
 	off += widthptr;
 
 	return off;
@@ -432,7 +432,7 @@ dgostrlitptr(Sym *s, int off, Strlit *lit)
 	datagostring(lit, &p->to);
 	p->to.index = p->to.type;
 	p->to.type = D_ADDR;
-	p->to.etype = TINT32;
+	p->to.etype = simtype[TINT];
 	off += widthptr;
 
 	return off;
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index ededcf6..fc5407a 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -103,9 +103,13 @@ dumpdata(void)
 /*
  * generate a branch.
  * t is ignored.
+ * likely values are for branch prediction:
+ *	-1 unlikely
+ *	0 no opinion
+ *	+1 likely
  */
 Prog*
-gbranch(int as, Type *t)
+gbranch(int as, Type *t, int likely)
 {
 	Prog *p;
 	
@@ -113,7 +117,11 @@ gbranch(int as, Type *t)
 
 	p = prog(as);
 	p->to.type = D_BRANCH;
-	p->to.branch = P;
+	p->to.u.branch = P;
+	if(as != AJMP && likely != 0) {
+		p->from.type = D_CONST;
+		p->from.offset = likely > 0;
+	}
 	return p;
 }
 
@@ -125,7 +133,7 @@ patch(Prog *p, Prog *to)
 {
 	if(p->to.type != D_BRANCH)
 		fatal("patch: not a branch");
-	p->to.branch = to;
+	p->to.u.branch = to;
 	p->to.offset = to->loc;
 }
 
@@ -136,8 +144,8 @@ unpatch(Prog *p)
 
 	if(p->to.type != D_BRANCH)
 		fatal("unpatch: not a branch");
-	q = p->to.branch;
-	p->to.branch = P;
+	q = p->to.u.branch;
+	p->to.u.branch = P;
 	p->to.offset = 0;
 	return q;
 }
@@ -165,44 +173,6 @@ newplist(void)
 }
 
 void
-clearstk(void)
-{
-	Plist *pl;
-	Prog *p1, *p2;
-	Node sp, di, cx, con, ax;
-
-	if((uint32)plast->firstpc->to.offset <= 0)
-		return;
-
-	// reestablish context for inserting code
-	// at beginning of function.
-	pl = plast;
-	p1 = pl->firstpc;
-	p2 = p1->link;
-	pc = mal(sizeof(*pc));
-	clearp(pc);
-	p1->link = pc;
-	
-	// zero stack frame
-	nodreg(&sp, types[tptr], D_SP);
-	nodreg(&di, types[tptr], D_DI);
-	nodreg(&cx, types[TUINT64], D_CX);
-	nodconst(&con, types[TUINT64], (uint32)p1->to.offset / widthptr);
-	gins(ACLD, N, N);
-	gins(AMOVQ, &sp, &di);
-	gins(AMOVQ, &con, &cx);
-	nodconst(&con, types[TUINT64], 0);
-	nodreg(&ax, types[TUINT64], D_AX);
-	gins(AMOVQ, &con, &ax);
-	gins(AREP, N, N);
-	gins(ASTOSQ, N, N);
-
-	// continue with original code.
-	gins(ANOP, N, N)->link = p2;
-	pc = P;
-}	
-
-void
 gused(Node *n)
 {
 	gins(ANOP, n, N);	// used
@@ -213,22 +183,23 @@ gjmp(Prog *to)
 {
 	Prog *p;
 
-	p = gbranch(AJMP, T);
+	p = gbranch(AJMP, T, 0);
 	if(to != P)
 		patch(p, to);
 	return p;
 }
 
 void
-ggloblnod(Node *nam, int32 width)
+ggloblnod(Node *nam)
 {
 	Prog *p;
 
 	p = gins(AGLOBL, nam, N);
 	p->lineno = nam->lineno;
+	p->from.gotype = ngotype(nam);
 	p->to.sym = S;
 	p->to.type = D_CONST;
-	p->to.offset = width;
+	p->to.offset = nam->type->width;
 	if(nam->readonly)
 		p->from.scale = RODATA;
 	if(nam->type != T && !haspointers(nam->type))
@@ -236,7 +207,18 @@ ggloblnod(Node *nam, int32 width)
 }
 
 void
-ggloblsym(Sym *s, int32 width, int dupok)
+gtrack(Sym *s)
+{
+	Prog *p;
+	
+	p = gins(AUSEFIELD, N, N);
+	p->from.type = D_EXTERN;
+	p->from.index = D_NONE;
+	p->from.sym = s;
+}
+
+void
+ggloblsym(Sym *s, int32 width, int dupok, int rodata)
 {
 	Prog *p;
 
@@ -248,8 +230,9 @@ ggloblsym(Sym *s, int32 width, int dupok)
 	p->to.index = D_NONE;
 	p->to.offset = width;
 	if(dupok)
-		p->from.scale = DUPOK;
-	p->from.scale |= RODATA;
+		p->from.scale |= DUPOK;
+	if(rodata)
+		p->from.scale |= RODATA;
 }
 
 int
@@ -272,11 +255,12 @@ isfat(Type *t)
  * call afunclit to fix up the argument.
  */
 void
-afunclit(Addr *a)
+afunclit(Addr *a, Node *n)
 {
 	if(a->type == D_ADDR && a->index == D_EXTERN) {
 		a->type = D_EXTERN;
 		a->index = D_NONE;
+		a->sym = n->sym;
 	}
 }
 
@@ -300,7 +284,7 @@ ginit(void)
 		reg[i] = 1;
 	for(i=D_AX; i<=D_R15; i++)
 		reg[i] = 0;
-	for(i=D_X0; i<=D_X7; i++)
+	for(i=D_X0; i<=D_X15; i++)
 		reg[i] = 0;
 
 	for(i=0; i<nelem(resvd); i++)
@@ -318,7 +302,7 @@ gclean(void)
 	for(i=D_AX; i<=D_R15; i++)
 		if(reg[i])
 			yyerror("reg %R left allocated\n", i);
-	for(i=D_X0; i<=D_X7; i++)
+	for(i=D_X0; i<=D_X15; i++)
 		if(reg[i])
 			yyerror("reg %R left allocated\n", i);
 }
@@ -388,10 +372,10 @@ regalloc(Node *n, Type *t, Node *o)
 	case TFLOAT64:
 		if(o != N && o->op == OREGISTER) {
 			i = o->val.u.reg;
-			if(i >= D_X0 && i <= D_X7)
+			if(i >= D_X0 && i <= D_X15)
 				goto out;
 		}
-		for(i=D_X0; i<=D_X7; i++)
+		for(i=D_X0; i<=D_X15; i++)
 			if(reg[i] == 0)
 				goto out;
 		fatal("out of floating registers");
@@ -572,6 +556,10 @@ ismem(Node *n)
 	case ONAME:
 	case OPARAM:
 		return 1;
+	case OADDR:
+		if(flag_largemodel)
+			return 1;
+		break;
 	}
 	return 0;
 }
@@ -616,7 +604,7 @@ gmove(Node *f, Node *t)
 	Prog *p1, *p2;
 
 	if(debug['M'])
-		print("gmove %N -> %N\n", f, t);
+		print("gmove %lN -> %lN\n", f, t);
 
 	ft = simsimtype(f->type);
 	tt = simsimtype(t->type);
@@ -706,11 +694,14 @@ gmove(Node *f, Node *t)
 	case CASE(TINT32, TUINT32):
 	case CASE(TUINT32, TINT32):
 	case CASE(TUINT32, TUINT32):
+		a = AMOVL;
+		break;
+
 	case CASE(TINT64, TINT32):	// truncate
 	case CASE(TUINT64, TINT32):
 	case CASE(TINT64, TUINT32):
 	case CASE(TUINT64, TUINT32):
-		a = AMOVL;
+		a = AMOVQL;
 		break;
 
 	case CASE(TINT64, TINT64):	// same size
@@ -822,9 +813,9 @@ gmove(Node *f, Node *t)
 		// algorithm is:
 		//	if small enough, use native float64 -> int64 conversion.
 		//	otherwise, subtract 2^63, convert, and add it back.
-		a = ACVTSS2SQ;
+		a = ACVTTSS2SQ;
 		if(ft == TFLOAT64)
-			a = ACVTSD2SQ;
+			a = ACVTTSD2SQ;
 		bignodes();
 		regalloc(&r1, types[ft], N);
 		regalloc(&r2, types[tt], t);
@@ -832,9 +823,9 @@ gmove(Node *f, Node *t)
 		regalloc(&r4, types[tt], N);
 		gins(optoas(OAS, f->type), f, &r1);
 		gins(optoas(OCMP, f->type), &bigf, &r1);
-		p1 = gbranch(optoas(OLE, f->type), T);
+		p1 = gbranch(optoas(OLE, f->type), T, +1);
 		gins(a, &r1, &r2);
-		p2 = gbranch(AJMP, T);
+		p2 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
 		gins(optoas(OAS, f->type), &bigf, &r3);
 		gins(optoas(OSUB, f->type), &r3, &r1);
@@ -903,9 +894,9 @@ gmove(Node *f, Node *t)
 		regalloc(&r4, f->type, N);
 		gmove(f, &r1);
 		gins(ACMPQ, &r1, &zero);
-		p1 = gbranch(AJLT, T);
+		p1 = gbranch(AJLT, T, +1);
 		gins(a, &r1, &r2);
-		p2 = gbranch(AJMP, T);
+		p2 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
 		gmove(&r1, &r3);
 		gins(ASHRQ, &one, &r3);
@@ -1016,6 +1007,13 @@ gins(int as, Node *f, Node *t)
 	case AMOVSD:
 		if(f != N && t != N && samaddr(f, t))
 			return nil;
+		break;
+	
+	case ALEAQ:
+		if(f != N && isconst(f, CTNIL)) {
+			fatal("gins LEAQ nil %T", f->type);
+		}
+		break;
 	}
 
 	memset(&af, 0, sizeof af);
@@ -1047,13 +1045,34 @@ gins(int as, Node *f, Node *t)
 		w = 8;
 		break;
 	}
-	if(w != 0 && f != N && (af.width > w || at.width > w)) {
+	if(w != 0 && ((f != N && af.width < w) || (t != N && at.width > w))) {
+		dump("f", f);
+		dump("t", t);
 		fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
 	}
 
 	return p;
 }
 
+// Generate an instruction referencing *n
+// to force segv on nil pointer dereference.
+void
+checkref(Node *n)
+{
+	Node m;
+
+	if(n->type->type->width < unmappedzero)
+		return;
+
+	regalloc(&m, types[TUINTPTR], n);
+	cgen(n, &m);
+	m.xoffset = 0;
+	m.op = OINDREG;
+	m.type = types[TUINT8];
+	gins(ATESTB, nodintconst(0), &m);
+	regfree(&m);
+}
+
 static void
 checkoffset(Addr *a, int canemitcode)
 {
@@ -1079,14 +1098,22 @@ checkoffset(Addr *a, int canemitcode)
 void
 naddr(Node *n, Addr *a, int canemitcode)
 {
+	Prog *p;
+
 	a->scale = 0;
 	a->index = D_NONE;
 	a->type = D_NONE;
 	a->gotype = S;
 	a->node = N;
+	a->width = 0;
 	if(n == N)
 		return;
 
+	if(n->type != T && n->type->etype != TIDEAL) {
+		dowidth(n->type);
+		a->width = n->type->width;
+	}
+
 	switch(n->op) {
 	default:
 		fatal("naddr: bad %O %D", n->op, a);
@@ -1134,15 +1161,27 @@ naddr(Node *n, Addr *a, int canemitcode)
 		a->type = D_PARAM;
 		a->node = n->left->orig;
 		break;
+	
+	case OCLOSUREVAR:
+		if(!canemitcode)
+			fatal("naddr OCLOSUREVAR cannot emit code");
+		p = gins(AMOVQ, N, N);
+		p->from.type = D_DX+D_INDIR;
+		p->from.offset = n->xoffset;
+		p->to.type = D_BX;
+		a->type = D_BX;
+		a->sym = S;
+		break;
+	
+	case OCFUNC:
+		naddr(n->left, a, canemitcode);
+		a->sym = n->left->sym;
+		break;
 
 	case ONAME:
 		a->etype = 0;
-		a->width = 0;
-		if(n->type != T) {
+		if(n->type != T)
 			a->etype = simtype[n->type->etype];
-			a->width = n->type->width;
-			a->gotype = ngotype(n);
-		}
 		a->offset = n->xoffset;
 		a->sym = n->sym;
 		a->node = n->orig;
@@ -1173,6 +1212,8 @@ naddr(Node *n, Addr *a, int canemitcode)
 		case PFUNC:
 			a->index = D_EXTERN;
 			a->type = D_ADDR;
+			a->width = widthptr;
+			a->sym = funcsym(a->sym);
 			break;
 		}
 		break;
@@ -1184,7 +1225,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 			break;
 		case CTFLT:
 			a->type = D_FCONST;
-			a->dval = mpgetflt(n->val.u.fval);
+			a->u.dval = mpgetflt(n->val.u.fval);
 			break;
 		case CTINT:
 		case CTRUNE:
@@ -1210,6 +1251,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 
 	case OADDR:
 		naddr(n->left, a, canemitcode);
+		a->width = widthptr;
 		if(a->type >= D_INDIR) {
 			a->type -= D_INDIR;
 			break;
@@ -1239,9 +1281,9 @@ naddr(Node *n, Addr *a, int canemitcode)
 		naddr(n->left, a, canemitcode);
 		if(a->type == D_CONST && a->offset == 0)
 			break;	// len(nil)
-		a->etype = TUINT32;
+		a->etype = simtype[TUINT];
 		a->offset += Array_nel;
-		a->width = 4;
+		a->width = widthint;
 		if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero)
 			checkoffset(a, canemitcode);
 		break;
@@ -1251,9 +1293,9 @@ naddr(Node *n, Addr *a, int canemitcode)
 		naddr(n->left, a, canemitcode);
 		if(a->type == D_CONST && a->offset == 0)
 			break;	// cap(nil)
-		a->etype = TUINT32;
+		a->etype = simtype[TUINT];
 		a->offset += Array_cap;
-		a->width = 4;
+		a->width = widthint;
 		if(a->offset >= unmappedzero && a->offset-Array_cap < unmappedzero)
 			checkoffset(a, canemitcode);
 		break;
@@ -1645,6 +1687,28 @@ optoas(int op, Type *t)
 		a = AXORQ;
 		break;
 
+	case CASE(OLROT, TINT8):
+	case CASE(OLROT, TUINT8):
+		a = AROLB;
+		break;
+
+	case CASE(OLROT, TINT16):
+	case CASE(OLROT, TUINT16):
+		a = AROLW;
+		break;
+
+	case CASE(OLROT, TINT32):
+	case CASE(OLROT, TUINT32):
+	case CASE(OLROT, TPTR32):
+		a = AROLL;
+		break;
+
+	case CASE(OLROT, TINT64):
+	case CASE(OLROT, TUINT64):
+	case CASE(OLROT, TPTR64):
+		a = AROLQ;
+		break;
+
 	case CASE(OLSH, TINT8):
 	case CASE(OLSH, TUINT8):
 		a = ASHLB;
@@ -1701,23 +1765,23 @@ optoas(int op, Type *t)
 		a = ASARQ;
 		break;
 
-	case CASE(ORRC, TINT8):
-	case CASE(ORRC, TUINT8):
+	case CASE(ORROTC, TINT8):
+	case CASE(ORROTC, TUINT8):
 		a = ARCRB;
 		break;
 
-	case CASE(ORRC, TINT16):
-	case CASE(ORRC, TUINT16):
+	case CASE(ORROTC, TINT16):
+	case CASE(ORROTC, TUINT16):
 		a = ARCRW;
 		break;
 
-	case CASE(ORRC, TINT32):
-	case CASE(ORRC, TUINT32):
+	case CASE(ORROTC, TINT32):
+	case CASE(ORROTC, TUINT32):
 		a = ARCRL;
 		break;
 
-	case CASE(ORRC, TINT64):
-	case CASE(ORRC, TUINT64):
+	case CASE(ORROTC, TINT64):
+	case CASE(ORROTC, TUINT64):
 		a = ARCRQ;
 		break;
 
@@ -1919,6 +1983,9 @@ sudoaddable(int as, Node *n, Addr *a)
 		goto odot;
 
 	case OINDEX:
+		return 0;
+		// disabled: OINDEX case is now covered by agenr
+		// for a more suitable register allocation pattern.
 		if(n->left->type->etype == TSTRING)
 			return 0;
 		goto oindex;
@@ -2053,32 +2120,20 @@ oindex:
 	}
 
 	// check bounds
-	if(!debug['B'] && !n->etype) {
+	if(!debug['B'] && !n->bounded) {
 		// check bounds
 		n4.op = OXXX;
-		t = types[TUINT32];
+		t = types[simtype[TUINT]];
 		if(o & ODynam) {
 			if(o & OAddable) {
 				n2 = *l;
 				n2.xoffset += Array_nel;
-				n2.type = types[TUINT32];
-				if(is64(r->type)) {
-					t = types[TUINT64];
-					regalloc(&n4, t, N);
-					gmove(&n2, &n4);
-					n2 = n4;
-				}
+				n2.type = types[simtype[TUINT]];
 			} else {
 				n2 = *reg;
 				n2.xoffset = Array_nel;
 				n2.op = OINDREG;
-				n2.type = types[TUINT32];
-				if(is64(r->type)) {
-					t = types[TUINT64];
-					regalloc(&n4, t, N);
-					gmove(&n2, &n4);
-					n2 = n4;
-				}
+				n2.type = types[simtype[TUINT]];
 			}
 		} else {
 			if(is64(r->type))
@@ -2086,10 +2141,10 @@ oindex:
 			nodconst(&n2, types[TUINT64], l->type->bound);
 		}
 		gins(optoas(OCMP, t), reg1, &n2);
-		p1 = gbranch(optoas(OLT, t), T);
+		p1 = gbranch(optoas(OLT, t), T, +1);
 		if(n4.op != OXXX)
 			regfree(&n4);
-		ginscall(panicindex, 0);
+		ginscall(panicindex, -1);
 		patch(p1, pc);
 	}
 
@@ -2140,19 +2195,19 @@ oindex_const:
 	reg->op = OEMPTY;
 	reg1->op = OEMPTY;
 
-	regalloc(reg, types[tptr], N);
-	agen(l, reg);
-
 	if(o & ODynam) {
-		if(!debug['B'] && !n->etype) {
+		regalloc(reg, types[tptr], N);
+		agen(l, reg);
+	
+		if(!debug['B'] && !n->bounded) {
 			n1 = *reg;
 			n1.op = OINDREG;
 			n1.type = types[tptr];
 			n1.xoffset = Array_nel;
 			nodconst(&n2, types[TUINT64], v);
-			gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
-			p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-			ginscall(panicindex, 0);
+			gins(optoas(OCMP, types[simtype[TUINT]]), &n1, &n2);
+			p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1);
+			ginscall(panicindex, -1);
 			patch(p1, pc);
 		}
 
@@ -2162,14 +2217,24 @@ oindex_const:
 		n1.xoffset = Array_array;
 		gmove(&n1, reg);
 
+		n2 = *reg;
+		n2.op = OINDREG;
+		n2.xoffset = v*w;
+		a->type = D_NONE;
+		a->index = D_NONE;
+		naddr(&n2, a, 1);
+		goto yes;
 	}
-
-	n2 = *reg;
-	n2.op = OINDREG;
-	n2.xoffset = v*w;
+	
+	igen(l, &n1, N);
+	if(n1.op == OINDREG) {
+		*reg = n1;
+		reg->op = OREGISTER;
+	}
+	n1.xoffset += v*w;
 	a->type = D_NONE;
-	a->index = D_NONE;
-	naddr(&n2, a, 1);
+	a->index= D_NONE;
+	naddr(&n1, a, 1);
 	goto yes;
 
 oindex_const_sudo:
@@ -2180,13 +2245,13 @@ oindex_const_sudo:
 	}
 
 	// slice indexed by a constant
-	if(!debug['B'] && !n->etype) {
+	if(!debug['B'] && !n->bounded) {
 		a->offset += Array_nel;
 		nodconst(&n2, types[TUINT64], v);
-		p1 = gins(optoas(OCMP, types[TUINT32]), N, &n2);
+		p1 = gins(optoas(OCMP, types[simtype[TUINT]]), N, &n2);
 		p1->from = *a;
-		p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-		ginscall(panicindex, 0);
+		p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1);
+		ginscall(panicindex, -1);
 		patch(p1, pc);
 		a->offset -= Array_nel;
 	}
diff --git a/src/cmd/6g/list.c b/src/cmd/6g/list.c
index ad63f7d..9d27a6a 100644
--- a/src/cmd/6g/list.c
+++ b/src/cmd/6g/list.c
@@ -107,10 +107,10 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_BRANCH:
-		if(a->branch == nil)
+		if(a->u.branch == nil)
 			snprint(str, sizeof(str), "<nil>");
 		else
-			snprint(str, sizeof(str), "%d", a->branch->loc);
+			snprint(str, sizeof(str), "%d", a->u.branch->loc);
 		break;
 
 	case D_EXTERN:
@@ -140,11 +140,11 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_FCONST:
-		snprint(str, sizeof(str), "$(%.17e)", a->dval);
+		snprint(str, sizeof(str), "$(%.17e)", a->u.dval);
 		break;
 
 	case D_SCONST:
-		snprint(str, sizeof(str), "$\"%Y\"", a->sval);
+		snprint(str, sizeof(str), "$\"%Y\"", a->u.sval);
 		break;
 
 	case D_ADDR:
@@ -161,7 +161,10 @@ brk:
 		strcat(str, s);
 	}
 conv:
-	return fmtstrcpy(fp, str);
+	fmtstrcpy(fp, str);
+	if(a->gotype)
+		fmtprint(fp, "{%s}", a->gotype->name);
+	return 0;
 }
 
 static	char*	regstr[] =
diff --git a/src/cmd/6g/opt.h b/src/cmd/6g/opt.h
index 9a8866b..9b0ea1b 100644
--- a/src/cmd/6g/opt.h
+++ b/src/cmd/6g/opt.h
@@ -34,8 +34,6 @@
 #define	D_HI	D_NONE
 #define	D_LO	D_NONE
 
-#define	isregtype(t)	((t)>= D_AX && (t)<=D_R15)
-
 #define	BLOAD(r)	band(bnot(r->refbehind), r->refahead)
 #define	BSTORE(r)	band(bnot(r->calbehind), r->calahead)
 #define	LOAD(r)		(~r->refbehind.b[z] & r->refahead.b[z])
@@ -49,12 +47,16 @@
 typedef	struct	Reg	Reg;
 typedef	struct	Rgn	Rgn;
 
+// 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.
+// r->prog->regp points back to r.
 struct	Reg
 {
 
-	Bits	set;
-	Bits	use1;
-	Bits	use2;
+	Bits	set;  		// variables written by this instruction.
+	Bits	use1; 		// variables read by prog->from.
+	Bits	use2; 		// variables read by prog->to.
 
 	Bits	refbehind;
 	Bits	refahead;
@@ -70,13 +72,13 @@ struct	Reg
 	uint16	loop;		// x5 for every loop
 	uchar	refset;		// diagnostic generated
 
-	Reg*	p1;
-	Reg*	p2;
+	Reg*	p1;     	// predecessors of this instruction: p1,
+	Reg*	p2;     	// and then p2 linked though p2link.
 	Reg*	p2link;
-	Reg*	s1;
+	Reg*	s1;     	// successors of this instruction (at most two: s1 and s2).
 	Reg*	s2;
-	Reg*	link;
-	Prog*	prog;
+	Reg*	link;   	// next instruction in function code
+	Prog*	prog;   	// actual instruction
 };
 #define	R	((Reg*)0)
 
diff --git a/src/cmd/6g/peep.c b/src/cmd/6g/peep.c
index 3710033..5696557 100644
--- a/src/cmd/6g/peep.c
+++ b/src/cmd/6g/peep.c
@@ -34,6 +34,10 @@
 #include "opt.h"
 
 static void	conprop(Reg *r);
+static void elimshortmov(Reg *r);
+static int prevl(Reg *r, int reg);
+static void pushback(Reg *r);
+static int regconsttyp(Adr*);
 
 // do we need the carry bit
 static int
@@ -45,11 +49,17 @@ needc(Prog *p)
 		case AADCQ:
 		case ASBBL:
 		case ASBBQ:
+		case ARCRB:
+		case ARCRW:
 		case ARCRL:
 		case ARCRQ:
 			return 1;
+		case AADDB:
+		case AADDW:
 		case AADDL:
 		case AADDQ:
+		case ASUBB:
+		case ASUBW:
 		case ASUBL:
 		case ASUBQ:
 		case AJMP:
@@ -122,9 +132,14 @@ peep(void)
 		case AGLOBL:
 		case ANAME:
 		case ASIGNAME:
+		case ALOCALS:
+		case ATYPE:
 			p = p->link;
 		}
 	}
+	
+	// byte, word arithmetic elimination.
+	elimshortmov(r);
 
 	// constant propagation
 	// find MOV $con,R followed by
@@ -200,6 +215,7 @@ loop1:
 		case AMOVWQZX:
 		case AMOVLQSX:
 		case AMOVLQZX:
+		case AMOVQL:
 			if(regtyp(&p->to)) {
 				r1 = rnops(uniqs(r));
 				if(r1 != R) {
@@ -272,6 +288,115 @@ loop1:
 	}
 	if(t)
 		goto loop1;
+
+	// MOVLQZX removal.
+	// The MOVLQZX exists to avoid being confused for a
+	// MOVL that is just copying 32-bit data around during
+	// copyprop.  Now that copyprop is done, remov MOVLQZX R1, R2
+	// if it is dominated by an earlier ADDL/MOVL/etc into R1 that
+	// will have already cleared the high bits.
+	//
+	// MOVSD removal.
+	// We never use packed registers, so a MOVSD between registers
+	// can be replaced by MOVAPD, which moves the pair of float64s
+	// instead of just the lower one.  We only use the lower one, but
+	// the processor can do better if we do moves using both.
+	for(r=firstr; r!=R; r=r->link) {
+		p = r->prog;
+		if(p->as == AMOVLQZX)
+		if(regtyp(&p->from))
+		if(p->from.type == p->to.type)
+		if(prevl(r, p->from.type))
+			excise(r);
+		
+		if(p->as == AMOVSD)
+		if(regtyp(&p->from))
+		if(regtyp(&p->to))
+			p->as = AMOVAPD;
+	}
+
+	// load pipelining
+	// push any load from memory as early as possible
+	// to give it time to complete before use.
+	for(r=firstr; r!=R; r=r->link) {
+		p = r->prog;
+		switch(p->as) {
+		case AMOVB:
+		case AMOVW:
+		case AMOVL:
+		case AMOVQ:
+		case AMOVLQZX:
+			if(regtyp(&p->to) && !regconsttyp(&p->from))
+				pushback(r);
+		}
+	}
+}
+
+static void
+pushback(Reg *r0)
+{
+	Reg *r, *b;
+	Prog *p0, *p, t;
+	
+	b = R;
+	p0 = r0->prog;
+	for(r=uniqp(r0); r!=R && uniqs(r)!=R; r=uniqp(r)) {
+		p = r->prog;
+		if(p->as != ANOP) {
+			if(!regconsttyp(&p->from) || !regtyp(&p->to))
+				break;
+			if(copyu(p, &p0->to, A) || copyu(p0, &p->to, A))
+				break;
+		}
+		if(p->as == ACALL)
+			break;
+		b = r;
+	}
+	
+	if(b == R) {
+		if(debug['v']) {
+			print("no pushback: %P\n", r0->prog);
+			if(r)
+				print("\t%P [%d]\n", r->prog, uniqs(r)!=R);
+		}
+		return;
+	}
+
+	if(debug['v']) {
+		print("pushback\n");
+		for(r=b;; r=r->link) {
+			print("\t%P\n", r->prog);
+			if(r == r0)
+				break;
+		}
+	}
+
+	t = *r0->prog;
+	for(r=uniqp(r0);; r=uniqp(r)) {
+		p0 = r->link->prog;
+		p = r->prog;
+		p0->as = p->as;
+		p0->lineno = p->lineno;
+		p0->from = p->from;
+		p0->to = p->to;
+
+		if(r == b)
+			break;
+	}
+	p0 = r->prog;
+	p0->as = t.as;
+	p0->lineno = t.lineno;
+	p0->from = t.from;
+	p0->to = t.to;
+
+	if(debug['v']) {
+		print("\tafter\n");
+		for(r=b;; r=r->link) {
+			print("\t%P\n", r->prog);
+			if(r == r0)
+				break;
+		}
+	}
 }
 
 void
@@ -335,6 +460,155 @@ regtyp(Adr *a)
 	return 0;
 }
 
+// movb elimination.
+// movb is simulated by the linker
+// when a register other than ax, bx, cx, dx
+// is used, so rewrite to other instructions
+// when possible.  a movb into a register
+// can smash the entire 32-bit register without
+// causing any trouble.
+static void
+elimshortmov(Reg *r)
+{
+	Prog *p;
+
+	for(r=firstr; r!=R; r=r->link) {
+		p = r->prog;
+		if(regtyp(&p->to)) {
+			switch(p->as) {
+			case AINCB:
+			case AINCW:
+				p->as = AINCQ;
+				break;
+			case ADECB:
+			case ADECW:
+				p->as = ADECQ;
+				break;
+			case ANEGB:
+			case ANEGW:
+				p->as = ANEGQ;
+				break;
+			case ANOTB:
+			case ANOTW:
+				p->as = ANOTQ;
+				break;
+			}
+			if(regtyp(&p->from) || p->from.type == D_CONST) {
+				// move or artihmetic into partial register.
+				// from another register or constant can be movl.
+				// we don't switch to 64-bit arithmetic if it can
+				// change how the carry bit is set (and the carry bit is needed).
+				switch(p->as) {
+				case AMOVB:
+				case AMOVW:
+					p->as = AMOVQ;
+					break;
+				case AADDB:
+				case AADDW:
+					if(!needc(p->link))
+						p->as = AADDQ;
+					break;
+				case ASUBB:
+				case ASUBW:
+					if(!needc(p->link))
+						p->as = ASUBQ;
+					break;
+				case AMULB:
+				case AMULW:
+					p->as = AMULQ;
+					break;
+				case AIMULB:
+				case AIMULW:
+					p->as = AIMULQ;
+					break;
+				case AANDB:
+				case AANDW:
+					p->as = AANDQ;
+					break;
+				case AORB:
+				case AORW:
+					p->as = AORQ;
+					break;
+				case AXORB:
+				case AXORW:
+					p->as = AXORQ;
+					break;
+				case ASHLB:
+				case ASHLW:
+					p->as = ASHLQ;
+					break;
+				}
+			} else if(p->from.type >= D_NONE) {
+				// explicit zero extension, but don't
+				// do that if source is a byte register
+				// (only AH can occur and it's forbidden).
+				switch(p->as) {
+				case AMOVB:
+					p->as = AMOVBQZX;
+					break;
+				case AMOVW:
+					p->as = AMOVWQZX;
+					break;
+				}
+			}
+		}
+	}
+}
+
+int
+regconsttyp(Adr *a)
+{
+	if(regtyp(a))
+		return 1;
+	switch(a->type) {
+	case D_CONST:
+	case D_FCONST:
+	case D_SCONST:
+	case D_ADDR:
+		return 1;
+	}
+	return 0;
+}
+
+// is reg guaranteed to be truncated by a previous L instruction?
+static int
+prevl(Reg *r0, int reg)
+{
+	Prog *p;
+	Reg *r;
+
+	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
+		p = r->prog;
+		if(p->to.type == reg) {
+			switch(p->as) {
+			case AADDL:
+			case AANDL:
+			case ADECL:
+			case ADIVL:
+			case AIDIVL:
+			case AIMULL:
+			case AINCL:
+			case AMOVL:
+			case AMULL:
+			case AORL:
+			case ARCLL:
+			case ARCRL:
+			case AROLL:
+			case ARORL:
+			case ASALL:
+			case ASARL:
+			case ASHLL:
+			case ASHRL:
+			case ASUBL:
+			case AXORL:
+				return 1;
+			}
+			return 0;
+		}
+	}
+	return 0;
+}
+
 /*
  * the idea is to substitute
  * one register for another
@@ -357,19 +631,34 @@ subprop(Reg *r0)
 	Reg *r;
 	int t;
 
+	if(debug['P'] && debug['v'])
+		print("subprop %P\n", r0->prog);
 	p = r0->prog;
 	v1 = &p->from;
-	if(!regtyp(v1))
+	if(!regtyp(v1)) {
+		if(debug['P'] && debug['v'])
+			print("\tnot regtype %D; return 0\n", v1);
 		return 0;
+	}
 	v2 = &p->to;
-	if(!regtyp(v2))
+	if(!regtyp(v2)) {
+		if(debug['P'] && debug['v'])
+			print("\tnot regtype %D; return 0\n", v2);
 		return 0;
+	}
 	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
-		if(uniqs(r) == R)
+		if(debug['P'] && debug['v'])
+			print("\t? %P\n", r->prog);
+		if(uniqs(r) == R) {
+			if(debug['P'] && debug['v'])
+				print("\tno unique successor\n");
 			break;
+		}
 		p = r->prog;
 		switch(p->as) {
 		case ACALL:
+			if(debug['P'] && debug['v'])
+				print("\tfound %P; return 0\n", p);
 			return 0;
 
 		case AIMULL:
@@ -377,20 +666,7 @@ subprop(Reg *r0)
 		case AIMULW:
 			if(p->to.type != D_NONE)
 				break;
-
-		case ADIVB:
-		case ADIVL:
-		case ADIVQ:
-		case ADIVW:
-		case AIDIVB:
-		case AIDIVL:
-		case AIDIVQ:
-		case AIDIVW:
-		case AIMULB:
-		case AMULB:
-		case AMULL:
-		case AMULQ:
-		case AMULW:
+			goto giveup;
 
 		case ARCLB:
 		case ARCLL:
@@ -424,6 +700,23 @@ subprop(Reg *r0)
 		case ASHRL:
 		case ASHRQ:
 		case ASHRW:
+			if(p->from.type == D_CONST)
+				break;
+			goto giveup;
+
+		case ADIVB:
+		case ADIVL:
+		case ADIVQ:
+		case ADIVW:
+		case AIDIVB:
+		case AIDIVL:
+		case AIDIVQ:
+		case AIDIVW:
+		case AIMULB:
+		case AMULB:
+		case AMULL:
+		case AMULQ:
+		case AMULW:
 
 		case AREP:
 		case AREPN:
@@ -438,21 +731,34 @@ subprop(Reg *r0)
 		case AMOVSB:
 		case AMOVSL:
 		case AMOVSQ:
+		giveup:
+			if(debug['P'] && debug['v'])
+				print("\tfound %P; return 0\n", p);
 			return 0;
 
 		case AMOVL:
 		case AMOVQ:
+		case AMOVSS:
+		case AMOVSD:
 			if(p->to.type == v1->type)
 				goto gotit;
 			break;
 		}
 		if(copyau(&p->from, v2) ||
-		   copyau(&p->to, v2))
+		   copyau(&p->to, v2)) {
+		   	if(debug['P'] && debug['v'])
+		   		print("\tcopyau %D failed\n", v2);
 			break;
+		}
 		if(copysub(&p->from, v1, v2, 0) ||
-		   copysub(&p->to, v1, v2, 0))
+		   copysub(&p->to, v1, v2, 0)) {
+		   	if(debug['P'] && debug['v'])
+		   		print("\tcopysub failed\n");
 			break;
+		}
 	}
+	if(debug['P'] && debug['v'])
+		print("\tran off end; return 0\n", p);
 	return 0;
 
 gotit:
@@ -497,6 +803,8 @@ copyprop(Reg *r0)
 	Adr *v1, *v2;
 	Reg *r;
 
+	if(debug['P'] && debug['v'])
+		print("copyprop %P\n", r0->prog);
 	p = r0->prog;
 	v1 = &p->from;
 	v2 = &p->to;
@@ -636,6 +944,7 @@ copyu(Prog *p, Adr *v, Adr *s)
 	case AMOVWLZX:
 	case AMOVWQSX:
 	case AMOVWQZX:
+	case AMOVQL:
 
 	case AMOVSS:
 	case AMOVSD:
@@ -853,8 +1162,6 @@ copyu(Prog *p, Adr *v, Adr *s)
 		return 0;
 
 	case ARET:	/* funny */
-		if(v->type == REGRET || v->type == FREGRET)
-			return 2;
 		if(s != A)
 			return 1;
 		return 3;
@@ -864,6 +1171,8 @@ copyu(Prog *p, Adr *v, Adr *s)
 			return 2;
 		if(REGARG >= 0 && v->type == (uchar)REGARG)
 			return 2;
+		if(v->type == p->from.type)
+			return 2;
 
 		if(s != A) {
 			if(copysub(&p->to, v, s, 1))
@@ -907,13 +1216,22 @@ int
 copyau(Adr *a, Adr *v)
 {
 
-	if(copyas(a, v))
+	if(copyas(a, v)) {
+		if(debug['P'] && debug['v'])
+			print("\tcopyau: copyas returned 1\n");
 		return 1;
+	}
 	if(regtyp(v)) {
-		if(a->type-D_INDIR == v->type)
+		if(a->type-D_INDIR == v->type) {
+			if(debug['P'] && debug['v'])
+				print("\tcopyau: found indir use - return 1\n");
 			return 1;
-		if(a->index == v->type)
+		}
+		if(a->index == v->type) {
+			if(debug['P'] && debug['v'])
+				print("\tcopyau: found index use - return 1\n");
 			return 1;
+		}
 	}
 	return 0;
 }
@@ -990,7 +1308,7 @@ loop:
 		if(p->from.node == p0->from.node)
 		if(p->from.offset == p0->from.offset)
 		if(p->from.scale == p0->from.scale)
-		if(p->from.dval == p0->from.dval)
+		if(p->from.u.vval == p0->from.u.vval)
 		if(p->from.index == p0->from.index) {
 			excise(r);
 			goto loop;
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index 049c63f..c56d716 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -151,6 +151,8 @@ static char* regname[] = {
 	".X15",
 };
 
+static Node* regnodes[NREGVAR];
+
 static void fixjmp(Prog*);
 
 void
@@ -164,7 +166,7 @@ regopt(Prog *firstp)
 
 	if(first) {
 		fmtinstall('Q', Qconv);
-		exregoffset = D_R13;	// R14,R15 are external
+		exregoffset = D_R15;
 		first = 0;
 	}
 
@@ -191,8 +193,11 @@ regopt(Prog *firstp)
 	 */
 	nvar = NREGVAR;
 	memset(var, 0, NREGVAR*sizeof var[0]);
-	for(i=0; i<NREGVAR; i++)
-		var[i].node = newname(lookup(regname[i]));
+	for(i=0; i<NREGVAR; i++) {
+		if(regnodes[i] == N)
+			regnodes[i] = newname(lookup(regname[i]));
+		var[i].node = regnodes[i];
+	}
 
 	regbits = RtoB(D_SP);
 	for(z=0; z<BITS; z++) {
@@ -219,6 +224,8 @@ regopt(Prog *firstp)
 		case AGLOBL:
 		case ANAME:
 		case ASIGNAME:
+		case ALOCALS:
+		case ATYPE:
 			continue;
 		}
 		r = rega();
@@ -247,6 +254,20 @@ regopt(Prog *firstp)
 			}
 		}
 
+		// Avoid making variables for direct-called functions.
+		if(p->as == ACALL && p->to.type == D_EXTERN)
+			continue;
+
+		// Addressing makes some registers used.
+		if(p->from.type >= D_INDIR)
+			r->use1.b[0] |= RtoB(p->from.type-D_INDIR);
+		if(p->from.index != D_NONE)
+			r->use1.b[0] |= RtoB(p->from.index);
+		if(p->to.type >= D_INDIR)
+			r->use2.b[0] |= RtoB(p->to.type-D_INDIR);
+		if(p->to.index != D_NONE)
+			r->use2.b[0] |= RtoB(p->to.index);
+
 		bit = mkvar(r, &p->from);
 		if(bany(&bit))
 		switch(p->as) {
@@ -326,6 +347,7 @@ regopt(Prog *firstp)
 		case AMOVWLZX:
 		case AMOVWQSX:
 		case AMOVWQZX:
+		case AMOVQL:
 		case APOPQ:
 
 		case AMOVSS:
@@ -578,8 +600,9 @@ regopt(Prog *firstp)
 				addrs.b[z] |= bit.b[z];
 		}
 
-//		print("bit=%2d addr=%d et=%-6E w=%-2d s=%S + %lld\n",
-//			i, v->addr, v->etype, v->width, v->sym, v->offset);
+		if(debug['R'] && debug['v'])
+			print("bit=%2d addr=%d et=%-6E w=%-2d s=%N + %lld\n",
+				i, v->addr, v->etype, v->width, v->node, v->offset);
 	}
 
 	if(debug['R'] && debug['v'])
@@ -593,9 +616,9 @@ regopt(Prog *firstp)
 	for(r=firstr; r!=R; r=r->link) {
 		p = r->prog;
 		if(p->to.type == D_BRANCH) {
-			if(p->to.branch == P)
+			if(p->to.u.branch == P)
 				fatal("pnil %P", p);
-			r1 = p->to.branch->reg;
+			r1 = p->to.u.branch->reg;
 			if(r1 == R)
 				fatal("rnil %P", p);
 			if(r1 == r) {
@@ -742,6 +765,9 @@ loop2:
 brk:
 	qsort(region, nregion, sizeof(region[0]), rcmp);
 
+	if(debug['R'] && debug['v'])
+		dumpit("pass5", firstr);
+
 	/*
 	 * pass 6
 	 * determine used registers (paint2)
@@ -752,8 +778,16 @@ brk:
 		bit = blsh(rgp->varno);
 		vreg = paint2(rgp->enter, rgp->varno);
 		vreg = allreg(vreg, rgp);
-		if(rgp->regno != 0)
+		if(rgp->regno != 0) {
+			if(debug['R'] && debug['v']) {
+				Var *v;
+
+				v = var + rgp->varno;
+				print("registerize %N+%d (bit=%2d et=%2E) in %R\n",
+						v->node, v->offset, rgp->varno, v->etype, rgp->regno);
+			}
 			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
+		}
 		rgp++;
 	}
 
@@ -776,8 +810,8 @@ brk:
 		while(p->link != P && p->link->as == ANOP)
 			p->link = p->link->link;
 		if(p->to.type == D_BRANCH)
-			while(p->to.branch != P && p->to.branch->as == ANOP)
-				p->to.branch = p->to.branch->link;
+			while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
+				p->to.u.branch = p->to.u.branch->link;
 	}
 
 	if(lastr != R) {
@@ -838,7 +872,6 @@ addmove(Reg *r, int bn, int rn, int f)
 	a->offset = v->offset;
 	a->etype = v->etype;
 	a->type = v->name;
-	a->gotype = v->gotype;
 	a->node = v->node;
 	a->sym = v->node->sym;
 
@@ -847,7 +880,7 @@ addmove(Reg *r, int bn, int rn, int f)
 	p1->as = AMOVL;
 	switch(v->etype) {
 	default:
-		fatal("unknown type\n");
+		fatal("unknown type %E", v->etype);
 	case TINT8:
 	case TUINT8:
 	case TBOOL:
@@ -932,7 +965,8 @@ Bits
 mkvar(Reg *r, Adr *a)
 {
 	Var *v;
-	int i, t, n, et, z, w, flag;
+	int i, t, n, et, z, flag;
+	int64 w;
 	uint32 regu;
 	int32 o;
 	Bits bit;
@@ -984,6 +1018,8 @@ mkvar(Reg *r, Adr *a)
 	et = a->etype;
 	o = a->offset;
 	w = a->width;
+	if(w < 0)
+		fatal("bad width %lld for %D", w, a);
 
 	flag = 0;
 	for(i=0; i<nvar; i++) {
@@ -1019,14 +1055,14 @@ mkvar(Reg *r, Adr *a)
 	v = var+i;
 	v->offset = o;
 	v->name = n;
-	v->gotype = a->gotype;
 	v->etype = et;
 	v->width = w;
 	v->addr = flag;		// funny punning
 	v->node = node;
 
 	if(debug['R'])
-		print("bit=%2d et=%2d w=%d %#N %D\n", i, et, w, node, a);
+		print("bit=%2d et=%2E w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
+
 	ostats.nvar++;
 
 	bit = blsh(i);
@@ -1089,8 +1125,12 @@ prop(Reg *r, Bits ref, Bits cal)
 		default:
 			// Work around for issue 1304:
 			// flush modified globals before each instruction.
-			for(z=0; z<BITS; z++)
+			for(z=0; z<BITS; z++) {
 				cal.b[z] |= externs.b[z];
+				// issue 4066: flush modified return variables in case of panic
+				if(hasdefer)
+					cal.b[z] |= ovar.b[z];
+			}
 			break;
 		}
 		for(z=0; z<BITS; z++) {
@@ -1576,7 +1616,7 @@ RtoB(int r)
 int
 BtoR(int32 b)
 {
-	b &= 0x3fffL;		// no R14 or R15
+	b &= 0xffffL;
 	if(b == 0)
 		return 0;
 	return bitno(b) + D_AX;
@@ -1584,26 +1624,26 @@ BtoR(int32 b)
 
 /*
  *	bit	reg
- *	16	X5 (FREGMIN)
+ *	16	X0
  *	...
- *	26	X15 (FREGEXT)
+ *	31	X15
  */
 int32
 FtoB(int f)
 {
-	if(f < FREGMIN || f > FREGEXT)
+	if(f < D_X0 || f > D_X15)
 		return 0;
-	return 1L << (f - FREGMIN + 16);
+	return 1L << (f - D_X0 + 16);
 }
 
 int
 BtoF(int32 b)
 {
 
-	b &= 0xFF0000L;
+	b &= 0xFFFF0000L;
 	if(b == 0)
 		return 0;
-	return bitno(b) - 16 + FREGMIN;
+	return bitno(b) - 16 + D_X0;
 }
 
 void
@@ -1719,7 +1759,7 @@ chasejmp(Prog *p, int *jmploop)
 			*jmploop = 1;
 			break;
 		}
-		p = p->to.branch;
+		p = p->to.u.branch;
 	}
 	return p;
 }
@@ -1741,9 +1781,9 @@ mark(Prog *firstp)
 		if(p->reg != dead)
 			break;
 		p->reg = alive;
-		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.branch)
-			mark(p->to.branch);
-		if(p->as == AJMP || p->as == ARET || (p->as == ACALL && noreturn(p)))
+		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.u.branch)
+			mark(p->to.u.branch);
+		if(p->as == AJMP || p->as == ARET || p->as == AUNDEF)
 			break;
 	}
 }
@@ -1762,8 +1802,8 @@ fixjmp(Prog *firstp)
 	for(p=firstp; p; p=p->link) {
 		if(debug['R'] && debug['v'])
 			print("%P\n", p);
-		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.branch && p->to.branch->as == AJMP) {
-			p->to.branch = chasejmp(p->to.branch, &jmploop);
+		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.u.branch && p->to.u.branch->as == AJMP) {
+			p->to.u.branch = chasejmp(p->to.u.branch, &jmploop);
 			if(debug['R'] && debug['v'])
 				print("->%P\n", p);
 		}
@@ -1799,7 +1839,7 @@ fixjmp(Prog *firstp)
 	if(!jmploop) {
 		last = nil;
 		for(p=firstp; p; p=p->link) {
-			if(p->as == AJMP && p->to.type == D_BRANCH && p->to.branch == p->link) {
+			if(p->as == AJMP && p->to.type == D_BRANCH && p->to.u.branch == p->link) {
 				if(debug['R'] && debug['v'])
 					print("del %P\n", p);
 				continue;
diff --git a/src/cmd/6l/6.out.h b/src/cmd/6l/6.out.h
index 8499159..805b3fc 100644
--- a/src/cmd/6l/6.out.h
+++ b/src/cmd/6l/6.out.h
@@ -736,6 +736,30 @@ enum	as
 	ACRC32B,
 	ACRC32Q,
 	AIMUL3Q,
+	
+	APREFETCHT0,
+	APREFETCHT1,
+	APREFETCHT2,
+	APREFETCHNTA,
+	
+	AMOVQL,
+	ABSWAPL,
+	ABSWAPQ,
+	
+	AUNDEF,
+
+	AAESENC,
+	AAESENCLAST,
+	AAESDEC,
+	AAESDECLAST,
+	AAESIMC,
+	AAESKEYGENASSIST,
+
+	APSHUFD,
+	
+	AUSEFIELD,
+	ALOCALS,
+	ATYPE,
 
 	ALAST
 };
@@ -794,6 +818,14 @@ enum
 	D_X5,
 	D_X6,
 	D_X7,
+	D_X8,
+	D_X9,
+	D_X10,
+	D_X11,
+	D_X12,
+	D_X13,
+	D_X14,
+	D_X15,
 
 	D_CS		= 68,
 	D_SS,
@@ -854,7 +886,7 @@ enum
 /*
  * this is the ranlib header
  */
-#define	SYMDEF	"__.SYMDEF"
+#define	SYMDEF	"__.GOSYMDEF"
 
 /*
  * this is the simulated IEEE floating point
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index ee31a05..5fb75ba 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -74,34 +74,6 @@ datoff(vlong addr)
 	return 0;
 }
 
-enum {
-	ElfStrEmpty,
-	ElfStrInterp,
-	ElfStrHash,
-	ElfStrGot,
-	ElfStrGotPlt,
-	ElfStrDynamic,
-	ElfStrDynsym,
-	ElfStrDynstr,
-	ElfStrRela,
-	ElfStrText,
-	ElfStrData,
-	ElfStrBss,
-	ElfStrShstrtab,
-	ElfStrSymtab,
-	ElfStrStrtab,
-	ElfStrRelaPlt,
-	ElfStrPlt,
-	ElfStrGnuVersion,
-	ElfStrGnuVersionR,
-	ElfStrNoteNetbsdIdent,
-	ElfStrNoPtrData,
-	ElfStrNoPtrBss,
-	NElfStr
-};
-
-vlong elfstr[NElfStr];
-
 static int
 needlib(char *name)
 {
@@ -127,6 +99,20 @@ int nelfsym = 1;
 static void addpltsym(Sym*);
 static void addgotsym(Sym*);
 
+Sym *
+lookuprel(void)
+{
+	return lookup(".rela", 0);
+}
+
+void
+adddynrela(Sym *rela, Sym *s, Reloc *r)
+{
+	addaddrplus(rela, s, r->off);
+	adduint64(rela, R_X86_64_RELATIVE);
+	addaddrplus(rela, r->sym, r->add); // Addend
+}
+
 void
 adddynrel(Sym *s, Reloc *r)
 {
@@ -299,6 +285,37 @@ adddynrel(Sym *s, Reloc *r)
 }
 
 int
+elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+{
+	VPUT(off);
+
+	switch(r->type) {
+	default:
+		return -1;
+
+	case D_ADDR:
+		if(r->siz == 4)
+			VPUT(R_X86_64_32 | (uint64)elfsym<<32);
+		else if(r->siz == 8)
+			VPUT(R_X86_64_64 | (uint64)elfsym<<32);
+		else
+			return -1;
+		break;
+
+	case D_PCREL:
+		if(r->siz == 4)
+			VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
+		else
+			return -1;
+		add -= r->siz;
+		break;
+	}
+
+	VPUT(add);
+	return 0;
+}
+
+int
 archreloc(Reloc *r, Sym *s, vlong *val)
 {
 	USED(r);
@@ -307,7 +324,7 @@ archreloc(Reloc *r, Sym *s, vlong *val)
 	return -1;
 }
 
-static void
+void
 elfsetupplt(void)
 {
 	Sym *plt, *got;
@@ -434,6 +451,7 @@ adddynsym(Sym *s)
 	Sym *d, *str;
 	int t;
 	char *name;
+	vlong off;
 
 	if(s->dynid >= 0)
 		return;
@@ -452,7 +470,7 @@ adddynsym(Sym *s)
 		adduint32(d, addstring(lookup(".dynstr", 0), name));
 		/* type */
 		t = STB_GLOBAL << 4;
-		if(s->dynexport && s->type == STEXT)
+		if(s->dynexport && (s->type&SMASK) == STEXT)
 			t |= STT_FUNC;
 		else
 			t |= STT_OBJECT;
@@ -490,7 +508,7 @@ adddynsym(Sym *s)
 			addaddr(d, s);
 	
 		/* size of object */
-		adduint64(d, 0);
+		adduint64(d, s->size);
 	
 		if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) {
 			elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
@@ -502,35 +520,51 @@ adddynsym(Sym *s)
 		name = s->dynimpname;
 		if(name == nil)
 			name = s->name;
-		s->dynid = d->size/16;
+		if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps
+			symgrow(d, ndynexp*16);
+		}
+		if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp()
+			s->dynid = -s->dynid-100;
+			off = s->dynid*16;
+		} else {
+			off = d->size;
+			s->dynid = off/16;
+		}
 		// darwin still puts _ prefixes on all C symbols
 		str = lookup(".dynstr", 0);
-		adduint32(d, str->size);
+		setuint32(d, off, str->size);
+		off += 4;
 		adduint8(str, '_');
 		addstring(str, name);
 		if(s->type == SDYNIMPORT) {
-			adduint8(d, 0x01);	// type - N_EXT - external symbol
-			adduint8(d, 0);	// section
+			setuint8(d, off, 0x01); // type - N_EXT - external symbol
+			off++;
+			setuint8(d, off, 0); // section
+			off++;
 		} else {
-			adduint8(d, 0x0f);
+			setuint8(d, off, 0x0f);
+			off++;
 			switch(s->type) {
 			default:
 			case STEXT:
-				adduint8(d, 1);
+				setuint8(d, off, 1);
 				break;
 			case SDATA:
-				adduint8(d, 2);
+				setuint8(d, off, 2);
 				break;
 			case SBSS:
-				adduint8(d, 4);
+				setuint8(d, off, 4);
 				break;
 			}
+			off++;
 		}
-		adduint16(d, 0);	// desc
+		setuint16(d, off, 0); // desc
+		off += 2;
 		if(s->type == SDYNIMPORT)
-			adduint64(d, 0);	// value
+			setuint64(d, off, 0); // value
 		else
-			addaddr(d, s);
+			setaddr(d, off, s);
+		off += 8;
 	} else if(HEADTYPE != Hwindows) {
 		diag("adddynsym: unsupported binary format");
 	}
@@ -557,181 +591,30 @@ adddynlib(char *lib)
 }
 
 void
-doelf(void)
-{
-	Sym *s, *shstrtab, *dynstr;
-
-	if(HEADTYPE != Hlinux && HEADTYPE != Hfreebsd && HEADTYPE != Hopenbsd && HEADTYPE != Hnetbsd)
-		return;
-
-	/* predefine strings we need for section headers */
-	shstrtab = lookup(".shstrtab", 0);
-	shstrtab->type = SELFROSECT;
-	shstrtab->reachable = 1;
-
-	elfstr[ElfStrEmpty] = addstring(shstrtab, "");
-	elfstr[ElfStrText] = addstring(shstrtab, ".text");
-	elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata");
-	elfstr[ElfStrData] = addstring(shstrtab, ".data");
-	elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
-	elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
-	if(HEADTYPE == Hnetbsd)
-		elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
-	addstring(shstrtab, ".elfdata");
-	addstring(shstrtab, ".rodata");
-	addstring(shstrtab, ".gosymtab");
-	addstring(shstrtab, ".gopclntab");
-	if(!debug['s']) {
-		elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
-		elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
-		dwarfaddshstrings(shstrtab);
-	}
-	elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
-
-	if(!debug['d']) {	/* -d suppresses dynamic loader format */
-		elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
-		elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
-		elfstr[ElfStrGot] = addstring(shstrtab, ".got");
-		elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
-		elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
-		elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
-		elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
-		elfstr[ElfStrRela] = addstring(shstrtab, ".rela");
-		elfstr[ElfStrRelaPlt] = addstring(shstrtab, ".rela.plt");
-		elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
-		elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
-		elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
-
-		/* dynamic symbol table - first entry all zeros */
-		s = lookup(".dynsym", 0);
-		s->type = SELFROSECT;
-		s->reachable = 1;
-		s->size += ELF64SYMSIZE;
-
-		/* dynamic string table */
-		s = lookup(".dynstr", 0);
-		s->type = SELFROSECT;
-		s->reachable = 1;
-		if(s->size == 0)
-			addstring(s, "");
-		dynstr = s;
-
-		/* relocation table */
-		s = lookup(".rela", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-
-		/* global offset table */
-		s = lookup(".got", 0);
-		s->reachable = 1;
-		s->type = SELFSECT; // writable
-
-		/* hash */
-		s = lookup(".hash", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-
-		s = lookup(".got.plt", 0);
-		s->reachable = 1;
-		s->type = SELFSECT; // writable
-
-		s = lookup(".plt", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-		
-		elfsetupplt();
-		
-		s = lookup(".rela.plt", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-		
-		s = lookup(".gnu.version", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-		
-		s = lookup(".gnu.version_r", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-
-		/* define dynamic elf table */
-		s = lookup(".dynamic", 0);
-		s->reachable = 1;
-		s->type = SELFSECT; // writable
-
-		/*
-		 * .dynamic table
-		 */
-		elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
-		elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
-		elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
-		elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
-		elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
-		elfwritedynentsym(s, DT_RELA, lookup(".rela", 0));
-		elfwritedynentsymsize(s, DT_RELASZ, lookup(".rela", 0));
-		elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
-		if(rpath)
-			elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
-		
-		elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
-		elfwritedynent(s, DT_PLTREL, DT_RELA);
-		elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0));
-		elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0));
-		
-		elfwritedynent(s, DT_DEBUG, 0);
-
-		// Do not write DT_NULL.  elfdynhash will finish it.
-	}
-}
-
-void
-shsym(ElfShdr *sh, Sym *s)
-{
-	vlong addr;
-	addr = symaddr(s);
-	if(sh->flags&SHF_ALLOC)
-		sh->addr = addr;
-	sh->off = datoff(addr);
-	sh->size = s->size;
-}
-
-void
-phsh(ElfPhdr *ph, ElfShdr *sh)
-{
-	ph->vaddr = sh->addr;
-	ph->paddr = ph->vaddr;
-	ph->off = sh->off;
-	ph->filesz = sh->size;
-	ph->memsz = sh->size;
-	ph->align = sh->addralign;
-}
-
-void
 asmb(void)
 {
 	int32 magic;
-	int a, dynsym;
-	vlong vl, startva, symo, dwarfoff, machlink, resoff;
-	ElfEhdr *eh;
-	ElfPhdr *ph, *pph;
-	ElfShdr *sh;
+	int i;
+	vlong vl, symo, dwarfoff, machlink;
 	Section *sect;
-	int o;
+	Sym *sym;
 
 	if(debug['v'])
 		Bprint(&bso, "%5.2f asmb\n", cputime());
 	Bflush(&bso);
 
-	elftextsh = 0;
-	
 	if(debug['v'])
 		Bprint(&bso, "%5.2f codeblk\n", cputime());
 	Bflush(&bso);
 
+	if(iself)
+		asmbelfsetup();
+
 	sect = segtext.sect;
 	cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
 	codeblk(sect->vaddr, sect->len);
 
-	/* output read-only data in text segment (rodata, gosymtab and pclntab) */
+	/* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
 	for(sect = sect->next; sect != nil; sect = sect->next) {
 		cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
 		datblk(sect->vaddr, sect->len);
@@ -763,6 +646,7 @@ asmb(void)
 	default:
 		diag("unknown header type %d", HEADTYPE);
 	case Hplan9x32:
+	case Hplan9x64:
 	case Helf:
 		break;
 	case Hdarwin:
@@ -773,16 +657,6 @@ asmb(void)
 	case Hnetbsd:
 	case Hopenbsd:
 		debug['8'] = 1;	/* 64-bit addresses */
-		/* index of elf text section; needed by asmelfsym, double-checked below */
-		/* !debug['d'] causes extra sections before the .text section */
-		elftextsh = 2;
-		if(!debug['d']) {
-			elftextsh += 10;
-			if(elfverneed)
-				elftextsh += 2;
-		}
-		if(HEADTYPE == Hnetbsd)
-			elftextsh += 1;
 		break;
 	case Hwindows:
 		break;
@@ -798,7 +672,7 @@ asmb(void)
 		Bflush(&bso);
 		switch(HEADTYPE) {
 		default:
-		case Hplan9x32:
+		case Hplan9x64:
 		case Helf:
 			debug['s'] = 1;
 			symo = HEADR+segtext.len+segdata.filelen;
@@ -831,6 +705,22 @@ asmb(void)
 				       Bprint(&bso, "%5.2f dwarf\n", cputime());
 
 				dwarfemitdebugsections();
+				
+				if(isobj)
+					elfemitreloc();
+			}
+			break;
+		case Hplan9x64:
+			asmplan9sym();
+			cflush();
+
+			sym = lookup("pclntab", 0);
+			if(sym != nil) {
+				lcsize = sym->np;
+				for(i=0; i < lcsize; i++)
+					cput(sym->p[i]);
+				
+				cflush();
 			}
 			break;
 		case Hwindows:
@@ -848,7 +738,7 @@ asmb(void)
 	cseek(0L);
 	switch(HEADTYPE) {
 	default:
-	case Hplan9x32:	/* plan9 */
+	case Hplan9x64:	/* plan9 */
 		magic = 4*26*26+7;
 		magic |= 0x00008000;		/* fat header */
 		lputb(magic);			/* magic */
@@ -862,7 +752,7 @@ asmb(void)
 		lputb(lcsize);			/* line offsets */
 		vputb(vl);			/* va of entry */
 		break;
-	case Hplan9x64:	/* plan9 */
+	case Hplan9x32:	/* plan9 */
 		magic = 4*26*26+7;
 		lputb(magic);			/* magic */
 		lputb(segtext.filelen);		/* sizes */
@@ -880,257 +770,7 @@ asmb(void)
 	case Hfreebsd:
 	case Hnetbsd:
 	case Hopenbsd:
-		/* elf amd-64 */
-
-		eh = getElfEhdr();
-		startva = INITTEXT - HEADR;
-		resoff = ELFRESERVE;
-
-		/* This null SHdr must appear before all others */
-		newElfShdr(elfstr[ElfStrEmpty]);
-
-		/* program header info */
-		pph = newElfPhdr();
-		pph->type = PT_PHDR;
-		pph->flags = PF_R + PF_X;
-		pph->off = eh->ehsize;
-		pph->vaddr = INITTEXT - HEADR + pph->off;
-		pph->paddr = INITTEXT - HEADR + pph->off;
-		pph->align = INITRND;
-
-		/*
-		 * PHDR must be in a loaded segment. Adjust the text
-		 * segment boundaries downwards to include it.
-		 */
-		o = segtext.vaddr - pph->vaddr;
-		segtext.vaddr -= o;
-		segtext.len += o;
-		o = segtext.fileoff - pph->off;
-		segtext.fileoff -= o;
-		segtext.filelen += o;
-
-		if(!debug['d']) {
-			/* interpreter */
-			sh = newElfShdr(elfstr[ElfStrInterp]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC;
-			sh->addralign = 1;
-			if(interpreter == nil) {
-				switch(HEADTYPE) {
-				case Hlinux:
-					interpreter = linuxdynld;
-					break;
-				case Hfreebsd:
-					interpreter = freebsddynld;
-					break;
-				case Hnetbsd:
-					interpreter = netbsddynld;
-					break;
-				case Hopenbsd:
-					interpreter = openbsddynld;
-					break;
-				}
-			}
-			resoff -= elfinterp(sh, startva, resoff, interpreter);
-
-			ph = newElfPhdr();
-			ph->type = PT_INTERP;
-			ph->flags = PF_R;
-			phsh(ph, sh);
-		}
-
-		if(HEADTYPE == Hnetbsd) {
-			sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
-			sh->type = SHT_NOTE;
-			sh->flags = SHF_ALLOC;
-			sh->addralign = 4;
-			resoff -= elfnetbsdsig(sh, startva, resoff);
-
-			ph = newElfPhdr();
-			ph->type = PT_NOTE;
-			ph->flags = PF_R;
-			phsh(ph, sh);
-		}
-
-		elfphload(&segtext);
-		elfphload(&segdata);
-
-		/* Dynamic linking sections */
-		if(!debug['d']) {	/* -d suppresses dynamic loader format */
-			/* S headers for dynamic linking */
-			sh = newElfShdr(elfstr[ElfStrGot]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC+SHF_WRITE;
-			sh->entsize = 8;
-			sh->addralign = 8;
-			shsym(sh, lookup(".got", 0));
-
-			sh = newElfShdr(elfstr[ElfStrGotPlt]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC+SHF_WRITE;
-			sh->entsize = 8;
-			sh->addralign = 8;
-			shsym(sh, lookup(".got.plt", 0));
-			
-			dynsym = eh->shnum;
-			sh = newElfShdr(elfstr[ElfStrDynsym]);
-			sh->type = SHT_DYNSYM;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = ELF64SYMSIZE;
-			sh->addralign = 8;
-			sh->link = dynsym+1;	// dynstr
-			// sh->info = index of first non-local symbol (number of local symbols)
-			shsym(sh, lookup(".dynsym", 0));
-
-			sh = newElfShdr(elfstr[ElfStrDynstr]);
-			sh->type = SHT_STRTAB;
-			sh->flags = SHF_ALLOC;
-			sh->addralign = 1;
-			shsym(sh, lookup(".dynstr", 0));
-
-			if(elfverneed) {
-				sh = newElfShdr(elfstr[ElfStrGnuVersion]);
-				sh->type = SHT_GNU_VERSYM;
-				sh->flags = SHF_ALLOC;
-				sh->addralign = 2;
-				sh->link = dynsym;
-				sh->entsize = 2;
-				shsym(sh, lookup(".gnu.version", 0));
-				
-				sh = newElfShdr(elfstr[ElfStrGnuVersionR]);
-				sh->type = SHT_GNU_VERNEED;
-				sh->flags = SHF_ALLOC;
-				sh->addralign = 8;
-				sh->info = elfverneed;
-				sh->link = dynsym+1;  // dynstr
-				shsym(sh, lookup(".gnu.version_r", 0));
-			}
-
-			sh = newElfShdr(elfstr[ElfStrRelaPlt]);
-			sh->type = SHT_RELA;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = ELF64RELASIZE;
-			sh->addralign = 8;
-			sh->link = dynsym;
-			sh->info = eh->shnum;	// .plt
-			shsym(sh, lookup(".rela.plt", 0));
-
-			sh = newElfShdr(elfstr[ElfStrPlt]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC+SHF_EXECINSTR;
-			sh->entsize = 16;
-			sh->addralign = 4;
-			shsym(sh, lookup(".plt", 0));
-
-			sh = newElfShdr(elfstr[ElfStrHash]);
-			sh->type = SHT_HASH;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = 4;
-			sh->addralign = 8;
-			sh->link = dynsym;
-			shsym(sh, lookup(".hash", 0));
-
-			sh = newElfShdr(elfstr[ElfStrRela]);
-			sh->type = SHT_RELA;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = ELF64RELASIZE;
-			sh->addralign = 8;
-			sh->link = dynsym;
-			shsym(sh, lookup(".rela", 0));
-
-			/* sh and PT_DYNAMIC for .dynamic section */
-			sh = newElfShdr(elfstr[ElfStrDynamic]);
-			sh->type = SHT_DYNAMIC;
-			sh->flags = SHF_ALLOC+SHF_WRITE;
-			sh->entsize = 16;
-			sh->addralign = 8;
-			sh->link = dynsym+1;	// dynstr
-			shsym(sh, lookup(".dynamic", 0));
-			ph = newElfPhdr();
-			ph->type = PT_DYNAMIC;
-			ph->flags = PF_R + PF_W;
-			phsh(ph, sh);
-			
-			/*
-			 * Thread-local storage segment (really just size).
-			 */
-			if(tlsoffset != 0) {
-				ph = newElfPhdr();
-				ph->type = PT_TLS;
-				ph->flags = PF_R;
-				ph->memsz = -tlsoffset;
-				ph->align = 8;
-			}
-		}
-
-		ph = newElfPhdr();
-		ph->type = PT_GNU_STACK;
-		ph->flags = PF_W+PF_R;
-		ph->align = 8;
-
-		sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
-		sh->type = SHT_STRTAB;
-		sh->addralign = 1;
-		shsym(sh, lookup(".shstrtab", 0));
-
-		if(elftextsh != eh->shnum)
-			diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
-		for(sect=segtext.sect; sect!=nil; sect=sect->next)
-			elfshbits(sect);
-		for(sect=segdata.sect; sect!=nil; sect=sect->next)
-			elfshbits(sect);
-
-		if(!debug['s']) {
-			sh = newElfShdr(elfstr[ElfStrSymtab]);
-			sh->type = SHT_SYMTAB;
-			sh->off = symo;
-			sh->size = symsize;
-			sh->addralign = 8;
-			sh->entsize = 24;
-			sh->link = eh->shnum;	// link to strtab
-
-			sh = newElfShdr(elfstr[ElfStrStrtab]);
-			sh->type = SHT_STRTAB;
-			sh->off = symo+symsize;
-			sh->size = elfstrsize;
-			sh->addralign = 1;
-
-			dwarfaddelfheaders();
-		}
-
-		/* Main header */
-		eh->ident[EI_MAG0] = '\177';
-		eh->ident[EI_MAG1] = 'E';
-		eh->ident[EI_MAG2] = 'L';
-		eh->ident[EI_MAG3] = 'F';
-		if(HEADTYPE == Hfreebsd)
-			eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
-		else if(HEADTYPE == Hnetbsd)
-			eh->ident[EI_OSABI] = ELFOSABI_NETBSD;
-		else if(HEADTYPE == Hopenbsd)
-			eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
-		eh->ident[EI_CLASS] = ELFCLASS64;
-		eh->ident[EI_DATA] = ELFDATA2LSB;
-		eh->ident[EI_VERSION] = EV_CURRENT;
-
-		eh->type = ET_EXEC;
-		eh->machine = EM_X86_64;
-		eh->version = EV_CURRENT;
-		eh->entry = entryvalue();
-
-		pph->filesz = eh->phnum * eh->phentsize;
-		pph->memsz = pph->filesz;
-
-		cseek(0);
-		a = 0;
-		a += elfwritehdr();
-		a += elfwritephdrs();
-		a += elfwriteshdrs();
-		a += elfwriteinterp(elfstr[ElfStrInterp]);
-		if(HEADTYPE == Hnetbsd)
-			a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
-		if(a > ELFRESERVE)	
-			diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
+		asmbelf(symo);
 		break;
 	case Hwindows:
 		asmbpe();
@@ -1153,78 +793,3 @@ rnd(vlong v, vlong r)
 	v -= c;
 	return v;
 }
-
-void
-genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
-{
-	Auto *a;
-	Sym *s;
-
-	s = lookup("etext", 0);
-	if(s->type == STEXT)
-		put(s, s->name, 'T', s->value, s->size, s->version, 0);
-
-	for(s=allsym; s!=S; s=s->allsym) {
-		if(s->hide)
-			continue;
-		switch(s->type&~SSUB) {
-		case SCONST:
-		case SRODATA:
-		case SSYMTAB:
-		case SPCLNTAB:
-		case SDATA:
-		case SNOPTRDATA:
-		case SELFROSECT:
-		case SMACHOGOT:
-		case STYPE:
-		case SSTRING:
-		case SGOSTRING:
-		case SWINDOWS:
-			if(!s->reachable)
-				continue;
-			put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
-			continue;
-
-		case SBSS:
-		case SNOPTRBSS:
-			if(!s->reachable)
-				continue;
-			if(s->np > 0)
-				diag("%s should not be bss (size=%d type=%d special=%d)", s->name, (int)s->np, s->type, s->special);
-			put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
-			continue;
-
-		case SFILE:
-			put(nil, s->name, 'f', s->value, 0, s->version, 0);
-			continue;
-		}
-	}
-
-	for(s = textp; s != nil; s = s->next) {
-		if(s->text == nil)
-			continue;
-
-		/* filenames first */
-		for(a=s->autom; a; a=a->link)
-			if(a->type == D_FILE)
-				put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0);
-			else
-			if(a->type == D_FILE1)
-				put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
-
-		put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
-
-		/* frame, auto and param after */
-		put(nil, ".frame", 'm', s->text->to.offset+8, 0, 0, 0);
-
-		for(a=s->autom; a; a=a->link)
-			if(a->type == D_AUTO)
-				put(nil, a->asym->name, 'a', -a->aoffset, 0, 0, a->gotype);
-			else
-			if(a->type == D_PARAM)
-				put(nil, a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
-	}
-	if(debug['v'] || debug['n'])
-		Bprint(&bso, "symsize = %ud\n", symsize);
-	Bflush(&bso);
-}
diff --git a/src/cmd/6l/doc.go b/src/cmd/6l/doc.go
index 4d94b20..6287dd9 100644
--- a/src/cmd/6l/doc.go
+++ b/src/cmd/6l/doc.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 ignore
+
 /*
 
 6l is the linker for the x86-64.
@@ -10,4 +12,4 @@ The $GOARCH for these tools is amd64.
 The flags are documented in ../ld/doc.go.
 
 */
-package documentation
+package main
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index 5f62239..ffb8a45 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -40,7 +40,26 @@
 enum
 {
 	thechar = '6',
-	PtrSize = 8
+	PtrSize = 8,
+	IntSize = 8,
+	
+	// Loop alignment constants:
+	// want to align loop entry to LoopAlign-byte boundary,
+	// and willing to insert at most MaxLoopPad bytes of NOP to do so.
+	// We define a loop entry as the target of a backward jump.
+	//
+	// gcc uses MaxLoopPad = 10 for its 'generic x86-64' config,
+	// and it aligns all jump targets, not just backward jump targets.
+	//
+	// As of 6/1/2012, the effect of setting MaxLoopPad = 10 here
+	// is very slight but negative, so the alignment is disabled by
+	// setting MaxLoopPad = 0. The code is here for reference and
+	// for future experiments.
+	// 
+	LoopAlign = 16,
+	MaxLoopPad = 0,
+
+	FuncAlign = 16
 };
 
 #define	P		((Prog*)0)
@@ -134,11 +153,16 @@ struct	Sym
 	int32	plt;
 	int32	got;
 	int32	align;	// if non-zero, required alignment in bytes
+	int32	elfsym;
+	int32	locals;	// size of stack frame locals area
+	int32	args;	// size of stack frame incoming arguments area
 	Sym*	hash;	// in hash table
 	Sym*	allsym;	// in all symbol list
 	Sym*	next;	// in text or data list
 	Sym*	sub;	// in SSUB list
 	Sym*	outer;	// container of sub
+	Sym*	reachparent;
+	Sym*	queue;
 	vlong	value;
 	vlong	size;
 	Sym*	gotype;
@@ -146,6 +170,7 @@ struct	Sym
 	char*	dynimpname;
 	char*	dynimplib;
 	char*	dynimpvers;
+	struct Section*	sect;
 	
 	// STEXT
 	Auto*	autom;
@@ -158,6 +183,7 @@ struct	Sym
 	Reloc*	r;
 	int32	nr;
 	int32	maxr;
+	int 	rel_ro;
 };
 struct	Optab
 {
@@ -294,9 +320,10 @@ enum
 EXTERN	int32	HEADR;
 EXTERN	int32	HEADTYPE;
 EXTERN	int32	INITRND;
-EXTERN	vlong	INITTEXT;
-EXTERN	vlong	INITDAT;
+EXTERN	int64	INITTEXT;
+EXTERN	int64	INITDAT;
 EXTERN	char*	INITENTRY;		/* entry point */
+EXTERN	char*	LIBINITENTRY;		/* shared library entry point */
 EXTERN	char*	pcstr;
 EXTERN	Auto*	curauto;
 EXTERN	Auto*	curhist;
@@ -304,7 +331,7 @@ EXTERN	Prog*	curp;
 EXTERN	Sym*	cursym;
 EXTERN	Sym*	datap;
 EXTERN	vlong	elfdatsize;
-EXTERN	char	debug[128];
+EXTERN	int	debug[128];
 EXTERN	char	literal[32];
 EXTERN	Sym*	textp;
 EXTERN	Sym*	etextp;
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 692cab7..10e4a98 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -58,8 +58,8 @@ Header headers[] = {
 };
 
 /*
- *	-Hplan9x32 -T4136 -R4096	is plan9 64-bit format
- *	-Hplan9 -T4128 -R4096		is plan9 32-bit format
+ *	-Hplan9x32 -T4128 -R4096	is plan9 32-bit format
+ *	-Hplan9 -T0x200028 -R0x200000	is plan9 64-bit format
  *	-Helf -T0x80110000 -R4096	is ELF32
  *	-Hdarwin -Tx -Rx		is apple MH-exec
  *	-Hlinux -Tx -Rx			is linux elf-exec
@@ -67,23 +67,11 @@ Header headers[] = {
  *	-Hnetbsd -Tx -Rx		is NetBSD elf-exec
  *	-Hopenbsd -Tx -Rx		is OpenBSD elf-exec
  *	-Hwindows -Tx -Rx		is MS Windows PE32+
- *
- *	options used: 189BLQSWabcjlnpsvz
  */
 
 void
-usage(void)
-{
-	fprint(2, "usage: 6l [-options] [-E entry] [-H head] [-I interpreter] [-L dir] [-T text] [-R rnd] [-r path] [-o out] main.6\n");
-	exits("usage");
-}
-
-void
 main(int argc, char *argv[])
 {
-	int c;
-	char *name, *val;
-
 	Binit(&bso, 1, OWRITE);
 	listinit();
 	memset(debug, 0, sizeof(debug));
@@ -94,52 +82,46 @@ main(int argc, char *argv[])
 	INITDAT = -1;
 	INITRND = -1;
 	INITENTRY = 0;
+	LIBINITENTRY = 0;
 	nuxiinit();
 
-	ARGBEGIN {
-	default:
-		c = ARGC();
-		if(c == 'l')
-			usage();
- 		if(c >= 0 && c < sizeof(debug))
-			debug[c]++;
-		break;
-	case 'o': /* output to (next arg) */
-		outfile = EARGF(usage());
-		break;
-	case 'E':
-		INITENTRY = EARGF(usage());
-		break;
-	case 'H':
-		HEADTYPE = headtype(EARGF(usage()));
-		break;
-	case 'I':
-		interpreter = EARGF(usage());
-		break;
-	case 'L':
-		Lflag(EARGF(usage()));
-		break;
-	case 'T':
-		INITTEXT = atolwhex(EARGF(usage()));
-		break;
-	case 'D':
-		INITDAT = atolwhex(EARGF(usage()));
-		break;
-	case 'R':
-		INITRND = atolwhex(EARGF(usage()));
-		break;
-	case 'r':
-		rpath = EARGF(usage());
-		break;
-	case 'V':
-		print("%cl version %s\n", thechar, getgoversion());
-		errorexit();
-	case 'X':
-		name = EARGF(usage());
-		val = EARGF(usage());
-		addstrdata(name, val);
-		break;
-	} ARGEND
+	flagcount("1", "use alternate profiling code", &debug['1']);
+	flagcount("8", "assume 64-bit addresses", &debug['8']);
+	flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo);
+	flagint64("D", "addr: data address", &INITDAT);
+	flagstr("E", "sym: entry symbol", &INITENTRY);
+	flagfn1("I", "interp: set ELF interp", setinterp);
+	flagfn1("L", "dir: add dir to library path", Lflag);
+	flagfn1("H", "head: header type", setheadtype);
+	flagcount("K", "add stack underflow checks", &debug['K']);
+	flagcount("O", "print pc-line tables", &debug['O']);
+	flagcount("Q", "debug byte-register code gen", &debug['Q']);
+	flagint32("R", "rnd: address rounding", &INITRND);
+	flagcount("S", "check type signatures", &debug['S']);
+	flagint64("T", "addr: text address", &INITTEXT);
+	flagfn0("V", "print version and exit", doversion);
+	flagcount("W", "disassemble input", &debug['W']);
+	flagfn2("X", "name value: define string data", addstrdata);
+	flagcount("Z", "clear stack frame on entry", &debug['Z']);
+	flagcount("a", "disassemble output", &debug['a']);
+	flagcount("c", "dump call graph", &debug['c']);
+	flagcount("d", "disable dynamic executable", &debug['d']);
+	flagcount("f", "ignore version mismatch", &debug['f']);
+	flagcount("g", "disable go package data checks", &debug['g']);
+	flagcount("hostobj", "generate host object file", &isobj);
+	flagstr("k", "sym: set field tracking symbol", &tracksym);
+	flagcount("n", "dump symbol table", &debug['n']);
+	flagstr("o", "outfile: set output file", &outfile);
+	flagcount("p", "insert profiling code", &debug['p']);
+	flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
+	flagcount("race", "enable race detector", &flag_race);
+	flagcount("s", "disable symbol table", &debug['s']);
+	flagcount("u", "reject unsafe packages", &debug['u']);
+	flagcount("v", "print link trace", &debug['v']);
+	flagcount("w", "disable DWARF generation", &debug['w']);
+	flagcount("shared", "generate shared object", &flag_shared);
+	
+	flagparse(&argc, &argv, usage);
 
 	if(argc != 1)
 		usage();
@@ -149,6 +131,15 @@ main(int argc, char *argv[])
 	if(HEADTYPE == -1)
 		HEADTYPE = headtype(goos);
 
+	if(isobj) {
+		switch(HEADTYPE) {
+		default:
+			sysfatal("cannot use -hostobj with -H %s", headstr(HEADTYPE));
+		case Hlinux:
+			break;
+		}
+	}
+
 	if(outfile == nil) {
 		if(HEADTYPE == Hwindows)
 			outfile = "6.out.exe";
@@ -163,7 +154,7 @@ main(int argc, char *argv[])
 		diag("unknown -H option");
 		errorexit();
 	case Hplan9x32:	/* plan 9 */
-		HEADR = 32L+8L;
+		HEADR = 32L;
 		if(INITTEXT == -1)
 			INITTEXT = 4096+HEADR;
 		if(INITDAT == -1)
@@ -172,13 +163,13 @@ main(int argc, char *argv[])
 			INITRND = 4096;
 		break;
 	case Hplan9x64:	/* plan 9 */
-		HEADR = 32L;
+		HEADR = 32L + 8L;
 		if(INITTEXT == -1)
-			INITTEXT = 4096+32;
+			INITTEXT = 0x200000+HEADR;
 		if(INITDAT == -1)
 			INITDAT = 0;
 		if(INITRND == -1)
-			INITRND = 4096;
+			INITRND = 0x200000;
 		break;
 	case Helf:	/* elf32 executable */
 		HEADR = rnd(52L+3*32L, 16);
@@ -506,8 +497,6 @@ loop:
 	p->line = Bget4(f);
 	p->back = 2;
 	p->mode = mode;
-	p->ft = 0;
-	p->tt = 0;
 	zaddr(pn, f, &p->from, h);
 	fromgotype = adrgotype;
 	zaddr(pn, f, &p->to, h);
@@ -597,6 +586,15 @@ loop:
 		pc++;
 		goto loop;
 
+	case ALOCALS:
+		cursym->locals = p->to.offset;
+		pc++;
+		goto loop;
+	
+	case ATYPE:
+		pc++;
+		goto loop;
+
 	case ATEXT:
 		s = p->from.sym;
 		if(s->text != nil) {
@@ -640,6 +638,7 @@ loop:
 		}
 		s->type = STEXT;
 		s->value = pc;
+		s->args = p->to.offset >> 32;
 		lastp = p;
 		p->pc = pc++;
 		goto loop;
@@ -677,7 +676,7 @@ loop:
 			sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
 			s = lookup(literal, 0);
 			if(s->type == 0) {
-				s->type = SDATA;
+				s->type = SRODATA;
 				adduint32(s, ieeedtof(&p->from.ieee));
 				s->reachable = 0;
 			}
@@ -711,7 +710,7 @@ loop:
 				p->from.ieee.l, p->from.ieee.h);
 			s = lookup(literal, 0);
 			if(s->type == 0) {
-				s->type = SDATA;
+				s->type = SRODATA;
 				adduint32(s, p->from.ieee.l);
 				adduint32(s, p->from.ieee.h);
 				s->reachable = 0;
diff --git a/src/cmd/6l/optab.c b/src/cmd/6l/optab.c
index 5746ded..a163e6f 100644
--- a/src/cmd/6l/optab.c
+++ b/src/cmd/6l/optab.c
@@ -269,7 +269,7 @@ uchar	yimul[] =
 };
 uchar	yimul3[] =
 {
-	Yml,	Yrl,	Zibm_r,	1,
+	Yml,	Yrl,	Zibm_r,	2,
 	0
 };
 uchar	ybyte[] =
@@ -302,6 +302,11 @@ uchar	ypopl[] =
 	Ynone,	Ym,	Zo_m,	2,
 	0
 };
+uchar	ybswap[] =
+{
+	Ynone,	Yrl,	Z_rp,	2,
+	0,
+};
 uchar	yscond[] =
 {
 	Ynone,	Ymb,	Zo_m,	2,
@@ -309,7 +314,9 @@ uchar	yscond[] =
 };
 uchar	yjcond[] =
 {
-	Ynone,	Ybr,	Zbr,	1,
+	Ynone,	Ybr,	Zbr,	0,
+	Yi0,	Ybr,	Zbr,	0,
+	Yi1,	Ybr,	Zbr,	1,
 	0
 };
 uchar	yloop[] =
@@ -319,7 +326,8 @@ uchar	yloop[] =
 };
 uchar	ycall[] =
 {
-	Ynone,	Yml,	Zo_m64,	2,
+	Ynone,	Yml,	Zo_m64,	0,
+	Yrx,	Yrx,	Zo_m64,	2,
 	Ynone,	Ybr,	Zcall,	1,
 	0
 };
@@ -511,17 +519,17 @@ uchar	ymrxr[] =
 };
 uchar	ymshuf[] =
 {
-	Ymm,	Ymr,	Zibm_r,	1,
+	Ymm,	Ymr,	Zibm_r,	2,
 	0
 };
 uchar	yxshuf[] =
 {
-	Yxm,	Yxr,	Zibm_r,	1,
+	Yxm,	Yxr,	Zibm_r,	2,
 	0
 };
 uchar	yextrw[] =
 {
-	Yxr,	Yrl,	Zibm_r,	1,
+	Yxr,	Yrl,	Zibm_r,	2,
 	0
 };
 uchar	ypsdq[] =
@@ -539,6 +547,21 @@ uchar	ycrc32l[] =
 {
 	Yml,	Yrl,	Zlitm_r,	0,
 };
+uchar	yprefetch[] =
+{
+	Ym,	Ynone,	Zm_o,	2,
+	0,
+};
+uchar	yaes[] =
+{
+	Yxm,	Yxr,	Zlitm_r,	2,
+	0
+};
+uchar	yaes2[] =
+{
+	Yxm,	Yxr,	Zibm_r,	2,
+	0
+};
 
 /*
  * You are doasm, holding in your hand a Prog* with p->as set to, say, ACRC32,
@@ -636,6 +659,8 @@ Optab optab[] =
 	{ 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 },
@@ -777,7 +802,7 @@ Optab optab[] =
 	{ 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 },
+	{ AIMUL3Q,	yimul3,	Pw, 0x6b,(00) },
 	{ AINB,		yin,	Pb, 0xe4,0xec },
 	{ AINCB,	yincb,	Pb, 0xfe,(00) },
 	{ AINCL,	yincl,	Px, 0xff,(00) },
@@ -936,7 +961,7 @@ Optab optab[] =
 	{ APCMPGTB,	ymm,	Py, 0x64,Pe,0x64 },
 	{ APCMPGTL,	ymm,	Py, 0x66,Pe,0x66 },
 	{ APCMPGTW,	ymm,	Py, 0x65,Pe,0x65 },
-	{ APEXTRW,	yextrw,	Pq, 0xc5 },
+	{ APEXTRW,	yextrw,	Pq, 0xc5,(00) },
 	{ APF2IL,	ymfp,	Px, 0x1d },
 	{ APF2IW,	ymfp,	Px, 0x1c },
 	{ API2FL,	ymfp,	Px, 0x0d },
@@ -957,7 +982,7 @@ Optab optab[] =
 	{ APFRSQRT,	ymfp,	Px, 0x97 },
 	{ APFSUB,	ymfp,	Px, 0x9a },
 	{ APFSUBR,	ymfp,	Px, 0xaa },
-	{ APINSRW,	yextrw,	Pq, 0xc4 },
+	{ APINSRW,	yextrw,	Pq, 0xc4,(00) },
 	{ APMADDWL,	ymm,	Py, 0xf5,Pe,0xf5 },
 	{ APMAXSW,	yxm,	Pe, 0xee },
 	{ APMAXUB,	yxm,	Pe, 0xde },
@@ -979,10 +1004,10 @@ Optab optab[] =
 	{ APOPW,	ypopl,	Pe, 0x58,0x8f,(00) },
 	{ APOR,		ymm,	Py, 0xeb,Pe,0xeb },
 	{ APSADBW,	yxm,	Pq, 0xf6 },
-	{ APSHUFHW,	yxshuf,	Pf3, 0x70 },
-	{ APSHUFL,	yxshuf,	Pq, 0x70 },
-	{ APSHUFLW,	yxshuf,	Pf2, 0x70 },
-	{ APSHUFW,	ymshuf,	Pm, 0x70 },
+	{ APSHUFHW,	yxshuf,	Pf3, 0x70,(00) },
+	{ APSHUFL,	yxshuf,	Pq, 0x70,(00) },
+	{ APSHUFLW,	yxshuf,	Pf2, 0x70,(00) },
+	{ APSHUFW,	ymshuf,	Pm, 0x70,(00) },
 	{ 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) },
@@ -1087,8 +1112,8 @@ Optab optab[] =
 	{ 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 },
-	{ ASHUFPS,	yxshuf,	Pm, 0xc6 },
+	{ ASHUFPD,	yxshuf,	Pq, 0xc6,(00) },
+	{ ASHUFPS,	yxshuf,	Pm, 0xc6,(00) },
 	{ ASQRTPD,	yxm,	Pe, 0x51 },
 	{ ASQRTPS,	yxm,	Pm, 0x51 },
 	{ ASQRTSD,	yxm,	Pf2, 0x51 },
@@ -1270,8 +1295,30 @@ Optab optab[] =
 	{ 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},
+	{ 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) },
+	
+	{ AMOVQL,	yrl_ml,	Px, 0x89 },
+
+	{ 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) },
+
+	{ APSHUFD,	yaes2,	Pq,	0x70,(0) },
+
+	{ AUSEFIELD,	ynop,	Px, 0,0 },
+	{ ALOCALS },
+	{ ATYPE },
 
 	{ AEND },
 	0
diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c
index c9b4776..0054b32 100644
--- a/src/cmd/6l/pass.c
+++ b/src/cmd/6l/pass.c
@@ -79,6 +79,7 @@ nofollow(int a)
 	case ARETFL:
 	case ARETFQ:
 	case ARETFW:
+	case AUNDEF:
 		return 1;
 	}
 	return 0;
@@ -192,20 +193,34 @@ loop:
 		 * recurse to follow one path.
 		 * continue loop on the other.
 		 */
-		q = brchain(p->link);
-		if(q != P && q->mark)
-		if(a != ALOOP) {
-			p->as = relinv(a);
-			p->link = p->pcond;
+		if((q = brchain(p->pcond)) != P)
 			p->pcond = q;
+		if((q = brchain(p->link)) != P)
+			p->link = q;
+		if(p->from.type == D_CONST) {
+			if(p->from.offset == 1) {
+				/*
+				 * expect conditional jump to be taken.
+				 * rewrite so that's the fall-through case.
+				 */
+				p->as = relinv(a);
+				q = p->link;
+				p->link = p->pcond;
+				p->pcond = q;
+			}
+		} else {			
+			q = p->link;
+			if(q->mark)
+			if(a != ALOOP) {
+				p->as = relinv(a);
+				p->link = p->pcond;
+				p->pcond = q;
+			}
 		}
 		xfol(p->link, last);
-		q = brchain(p->pcond);
-		if(q->mark) {
-			p->pcond = q;
+		if(p->pcond->mark)
 			return;
-		}
-		p = q;
+		p = p->pcond;
 		goto loop;
 	}
 	p = p->link;
@@ -295,7 +310,8 @@ patch(void)
 			}
 		}
 		if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
-		|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd) {
+		|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd
+		|| HEADTYPE == Hplan9x64) {
 			// ELF uses FS instead of GS.
 			if(p->from.type == D_INDIR+D_GS)
 				p->from.type = D_INDIR+D_FS;
@@ -307,7 +323,7 @@ patch(void)
 			if(s) {
 				if(debug['c'])
 					Bprint(&bso, "%s calls %s\n", TNAME, s->name);
-				if((s->type&~SSUB) != STEXT) {
+				if((s->type&SMASK) != STEXT) {
 					/* diag prints TNAME first */
 					diag("undefined: %s", s->name);
 					s->type = STEXT;
@@ -405,7 +421,7 @@ dostkoff(void)
 
 	for(cursym = textp; cursym != nil; cursym = cursym->next) {
 		if(cursym->text == nil || cursym->text->link == nil)
-			continue;
+			continue;				
 
 		p = cursym->text;
 		parsetextconst(p->to.offset);
@@ -413,6 +429,14 @@ dostkoff(void)
 		if(autoffset < 0)
 			autoffset = 0;
 
+		if(autoffset < StackSmall && !(p->from.scale & NOSPLIT)) {
+			for(q = p; q != P; q = q->link)
+				if(q->as == ACALL)
+					goto noleaf;
+			p->from.scale |= NOSPLIT;
+		noleaf:;
+		}
+
 		q = P;
 		if((p->from.scale & NOSPLIT) && autoffset >= StackSmall)
 			diag("nosplit func likely to overflow stack");
@@ -421,7 +445,8 @@ dostkoff(void)
 			p = appendp(p);	// load g into CX
 			p->as = AMOVQ;
 			if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
-			|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd)	// ELF uses FS
+			|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd
+			|| HEADTYPE == Hplan9x64)	// ELF uses FS
 				p->from.type = D_INDIR+D_FS;
 			else
 				p->from.type = D_INDIR+D_GS;
@@ -579,6 +604,16 @@ dostkoff(void)
 			p->spadj = autoffset;
 			if(q != P)
 				q->pcond = p;
+		} else {
+			// zero-byte stack adjustment.
+			// Insert a fake non-zero adjustment so that stkcheck can
+			// recognize the end of the stack-splitting prolog.
+			p = appendp(p);
+			p->as = ANOP;
+			p->spadj = -PtrSize;
+			p = appendp(p);
+			p->as = ANOP;
+			p->spadj = PtrSize;
 		}
 		deltasp = autoffset;
 
@@ -618,6 +653,34 @@ dostkoff(void)
 			q1->pcond = p;
 		}
 		
+		if(debug['Z'] && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
+			// 6l -Z means zero the stack frame on entry.
+			// This slows down function calls but can help avoid
+			// false positives in garbage collection.
+			p = appendp(p);
+			p->as = AMOVQ;
+			p->from.type = D_SP;
+			p->to.type = D_DI;
+			
+			p = appendp(p);
+			p->as = AMOVQ;
+			p->from.type = D_CONST;
+			p->from.offset = autoffset/8;
+			p->to.type = D_CX;
+			
+			p = appendp(p);
+			p->as = AMOVQ;
+			p->from.type = D_CONST;
+			p->from.offset = 0;
+			p->to.type = D_AX;
+			
+			p = appendp(p);
+			p->as = AREP;
+			
+			p = appendp(p);
+			p->as = ASTOSQ;
+		}
+		
 		for(; p != P; p = p->link) {
 			pcsize = p->mode/8;
 			a = p->from.type;
diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c
index 28eb38f..283a0e3 100644
--- a/src/cmd/6l/span.c
+++ b/src/cmd/6l/span.c
@@ -37,6 +37,37 @@ static int	rexflag;
 static int	asmode;
 static vlong	vaddr(Adr*, Reloc*);
 
+// 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.
+static uchar nop[][16] = {
+	{0x90},
+	{0x66, 0x90},
+	{0x0F, 0x1F, 0x00},
+	{0x0F, 0x1F, 0x40, 0x00},
+	{0x0F, 0x1F, 0x44, 0x00, 0x00},
+	{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
+	{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+};
+
+static void
+fillnop(uchar *p, int n)
+{
+	int m;
+
+	while(n > 0) {
+		m = n;
+		if(m > nelem(nop))
+			m = nelem(nop);
+		memmove(p, nop[m-1], m);
+		p += m;
+		n -= m;
+	}
+}
+
 void
 span1(Sym *s)
 {
@@ -52,8 +83,10 @@ span1(Sym *s)
 
 	for(p = s->text; p != P; p = p->link) {
 		p->back = 2;	// use short branches first time through
-		if((q = p->pcond) != P && (q->back & 2))
+		if((q = p->pcond) != P && (q->back & 2)) {
 			p->back |= 1;	// backward jump
+			q->back |= 4;   // loop head
+		}
 
 		if(p->as == AADJSP) {
 			p->to.type = D_SP;
@@ -78,6 +111,16 @@ span1(Sym *s)
 		s->np = 0;
 		c = 0;
 		for(p = s->text; p != P; p = p->link) {
+			if((p->back & 4) && (c&(LoopAlign-1)) != 0) {
+				// pad with NOPs
+				v = -c&(LoopAlign-1);
+				if(v <= MaxLoopPad) {
+					symgrow(s, c+v);
+					fillnop(s->p+c, v);
+					c += v;
+				}
+			}
+
 			p->pc = c;
 
 			// process forward jumps to p
@@ -329,7 +372,10 @@ oclass(Adr *a)
 				switch(a->index) {
 				case D_EXTERN:
 				case D_STATIC:
-					return Yi32;	/* TO DO: Yi64 */
+					if(flag_shared)
+						return Yiauto;
+					else
+						return Yi32;	/* TO DO: Yi64 */
 				case D_AUTO:
 				case D_PARAM:
 					return Yiauto;
@@ -688,7 +734,10 @@ vaddr(Adr *a, Reloc *r)
 			diag("need reloc for %D", a);
 			errorexit();
 		}
-		r->type = D_ADDR;
+		if(flag_shared)
+			r->type = D_PCREL;
+		else
+			r->type = D_ADDR;
 		r->siz = 4;	// TODO: 8 for external symbols
 		r->off = -1;	// caller must fill in
 		r->sym = s;
@@ -717,6 +766,8 @@ asmandsz(Adr *a, int r, int rex, int m64)
 				goto bad;
 			case D_STATIC:
 			case D_EXTERN:
+				if(flag_shared)
+					goto bad;
 				t = D_NONE;
 				v = vaddr(a, &rel);
 				break;
@@ -777,7 +828,7 @@ asmandsz(Adr *a, int r, int rex, int m64)
 
 	rexflag |= (regrex[t] & Rxb) | rex;
 	if(t == D_NONE || (D_CS <= t && t <= D_GS)) {
-		if(asmode != 64){
+		if(flag_shared && t == D_NONE && (a->type == D_STATIC || a->type == D_EXTERN) || asmode != 64) {
 			*andptr++ = (0 << 6) | (5 << 0) | (r << 3);
 			goto putrelv;
 		}
@@ -1204,7 +1255,8 @@ found:
 		break;
 
 	case Zibm_r:
-		*andptr++ = op;
+		while ((op = o->op[z++]) != 0)
+			*andptr++ = op;
 		asmand(&p->from, &p->to);
 		*andptr++ = p->to.offset;
 		break;
@@ -1574,7 +1626,9 @@ bad:
 		pp = *p;
 		z = p->from.type;
 		if(z >= D_BP && z <= D_DI) {
-			if(isax(&p->to)) {
+			if(isax(&p->to) || p->to.type == D_NONE) {
+				// We certainly don't want to exchange
+				// with AX if the op is MUL or DIV.
 				*andptr++ = 0x87;			/* xchg lhs,bx */
 				asmando(&p->from, reg[D_BX]);
 				subreg(&pp, z, D_BX);
@@ -1730,13 +1784,17 @@ asmins(Prog *p)
 			if(c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26)
 				break;
 		}
-		for(r=cursym->r+cursym->nr; r-- > cursym->r; ) {
-			if(r->off < p->pc)
-				break;
-			r->off++;
-		}
 		memmove(and+np+1, and+np, n-np);
 		and[np] = 0x40 | rexflag;
 		andptr++;
 	}
+	n = andptr - and;
+	for(r=cursym->r+cursym->nr; r-- > cursym->r; ) {
+		if(r->off < p->pc)
+			break;
+		if(rexflag)
+			r->off++;
+		if(r->type == D_PCREL)
+			r->add -= p->pc + n - (r->off + r->siz);
+	}
 }
diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y
index f188180..60707d1 100644
--- a/src/cmd/8a/a.y
+++ b/src/cmd/8a/a.y
@@ -53,9 +53,9 @@
 %left	'+' '-'
 %left	'*' '/' '%'
 %token	<lval>	LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
-%token	<lval>	LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG
+%token	<lval>	LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG LTYPEXC
 %token	<lval>	LCONST LFP LPC LSB
-%token	<lval>	LBREG LLREG LSREG LFREG
+%token	<lval>	LBREG LLREG LSREG LFREG LXREG
 %token	<dval>	LFCONST
 %token	<sval>	LSCONST LSP
 %token	<sym>	LNAME LLAB LVAR
@@ -63,7 +63,7 @@
 %type	<con2>	con2
 %type	<gen>	mem imm imm2 reg nam rel rem rim rom omem nmem
 %type	<gen2>	nonnon nonrel nonrem rimnon rimrem remrim
-%type	<gen2>	spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8
+%type	<gen2>	spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9
 %%
 prog:
 |	prog
@@ -116,6 +116,7 @@ inst:
 |	LTYPEM spec6	{ outcode($1, &$2); }
 |	LTYPEI spec7	{ outcode($1, &$2); }
 |	LTYPEG spec8	{ outcode($1, &$2); }
+|	LTYPEXC spec9	{ outcode($1, &$2); }
 
 nonnon:
 	{
@@ -177,6 +178,11 @@ nonrel:
 		$$.from = nullgen;
 		$$.to = $1;
 	}
+|	imm ',' rel
+	{
+		$$.from = $1;
+		$$.to = $3;
+	}
 
 spec1:	/* DATA */
 	nam '/' con ',' imm
@@ -282,6 +288,14 @@ spec8:	/* GLOBL */
 		$$.to = $5;
 	}
 
+spec9:	/* CMPPS/CMPPD */
+	reg ',' rem ',' con
+	{
+		$$.from = $1;
+		$$.to = $3;
+		$$.to.offset = $5;
+	}
+
 rem:
 	reg
 |	mem
@@ -345,6 +359,11 @@ reg:
 		$$ = nullgen;
 		$$.type = $1;
 	}
+|	LXREG
+	{
+		$$ = nullgen;
+		$$.type = $1;
+	}
 |	LSP
 	{
 		$$ = nullgen;
diff --git a/src/cmd/8a/doc.go b/src/cmd/8a/doc.go
index a43b446..737c56f 100644
--- a/src/cmd/8a/doc.go
+++ b/src/cmd/8a/doc.go
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build ignore
+
 /*
 
 8a is a version of the Plan 9 assembler.  The original is documented at
 
-	http://plan9.bell-labs.com/magic/man2html/1/2a
+	http://plan9.bell-labs.com/magic/man2html/1/8a
 
 Its target architecture is the x86, referred to by these tools for historical reasons as 386.
 
 */
-package documentation
+package main
diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c
index 1cc6e59..770ca5a 100644
--- a/src/cmd/8a/lex.c
+++ b/src/cmd/8a/lex.c
@@ -210,6 +210,15 @@ struct
 	"F6",		LFREG,	D_F0+6,
 	"F7",		LFREG,	D_F0+7,
 
+	"X0",		LXREG,	D_X0+0,
+	"X1",		LXREG,	D_X0+1,
+	"X2",		LXREG,	D_X0+2,
+	"X3",		LXREG,	D_X0+3,
+	"X4",		LXREG,	D_X0+4,
+	"X5",		LXREG,	D_X0+5,
+	"X6",		LXREG,	D_X0+6,
+	"X7",		LXREG,	D_X0+7,
+
 	"CS",		LSREG,	D_CS,
 	"SS",		LSREG,	D_SS,
 	"DS",		LSREG,	D_DS,
@@ -271,6 +280,7 @@ struct
 	"BSFW",		LTYPE3,	ABSFW,
 	"BSRL",		LTYPE3,	ABSRL,
 	"BSRW",		LTYPE3,	ABSRW,
+	"BSWAPL",	LTYPE1,	ABSWAPL,
 	"BTCL",		LTYPE3,	ABTCL,
 	"BTCW",		LTYPE3,	ABTCW,
 	"BTL",		LTYPE3,	ABTL,
@@ -667,6 +677,120 @@ struct
 	"MFENCE",	LTYPE0, AMFENCE,
 	"SFENCE",	LTYPE0, ASFENCE,
 	"EMMS",		LTYPE0, AEMMS,
+	"PREFETCHT0",		LTYPE2,	APREFETCHT0,
+	"PREFETCHT1",		LTYPE2,	APREFETCHT1,
+	"PREFETCHT2",		LTYPE2,	APREFETCHT2,
+	"PREFETCHNTA",		LTYPE2,	APREFETCHNTA,
+	"UNDEF",	LTYPE0,	AUNDEF,
+
+	"ADDPD",	LTYPE3,	AADDPD,
+	"ADDPS",	LTYPE3,	AADDPS,
+	"ADDSD",	LTYPE3,	AADDSD,
+	"ADDSS",	LTYPE3,	AADDSS,
+	"ANDNPD",	LTYPE3,	AANDNPD,
+	"ANDNPS",	LTYPE3,	AANDNPS,
+	"ANDPD",	LTYPE3,	AANDPD,
+	"ANDPS",	LTYPE3,	AANDPS,
+	"CMPPD",	LTYPEXC,ACMPPD,
+	"CMPPS",	LTYPEXC,ACMPPS,
+	"CMPSD",	LTYPEXC,ACMPSD,
+	"CMPSS",	LTYPEXC,ACMPSS,
+	"COMISD",	LTYPE3,	ACOMISD,
+	"COMISS",	LTYPE3,	ACOMISS,
+	"CVTPL2PD",	LTYPE3,	ACVTPL2PD,
+	"CVTPL2PS",	LTYPE3,	ACVTPL2PS,
+	"CVTPD2PL",	LTYPE3,	ACVTPD2PL,
+	"CVTPD2PS",	LTYPE3,	ACVTPD2PS,
+	"CVTPS2PL",	LTYPE3,	ACVTPS2PL,
+	"CVTPS2PD",	LTYPE3,	ACVTPS2PD,
+	"CVTSD2SL",	LTYPE3,	ACVTSD2SL,
+	"CVTSD2SS",	LTYPE3,	ACVTSD2SS,
+	"CVTSL2SD",	LTYPE3,	ACVTSL2SD,
+	"CVTSL2SS",	LTYPE3,	ACVTSL2SS,
+	"CVTSS2SD",	LTYPE3,	ACVTSS2SD,
+	"CVTSS2SL",	LTYPE3,	ACVTSS2SL,
+	"CVTTPD2PL",	LTYPE3,	ACVTTPD2PL,
+	"CVTTPS2PL",	LTYPE3,	ACVTTPS2PL,
+	"CVTTSD2SL",	LTYPE3,	ACVTTSD2SL,
+	"CVTTSS2SL",	LTYPE3,	ACVTTSS2SL,
+	"DIVPD",	LTYPE3,	ADIVPD,
+	"DIVPS",	LTYPE3,	ADIVPS,
+	"DIVSD",	LTYPE3,	ADIVSD,
+	"DIVSS",	LTYPE3,	ADIVSS,
+	"MASKMOVOU",	LTYPE3,	AMASKMOVOU,
+	"MASKMOVDQU",	LTYPE3,	AMASKMOVOU,	/* syn */
+	"MAXPD",	LTYPE3,	AMAXPD,
+	"MAXPS",	LTYPE3,	AMAXPS,
+	"MAXSD",	LTYPE3,	AMAXSD,
+	"MAXSS",	LTYPE3,	AMAXSS,
+	"MINPD",	LTYPE3,	AMINPD,
+	"MINPS",	LTYPE3,	AMINPS,
+	"MINSD",	LTYPE3,	AMINSD,
+	"MINSS",	LTYPE3,	AMINSS,
+	"MOVAPD",	LTYPE3,	AMOVAPD,
+	"MOVAPS",	LTYPE3,	AMOVAPS,
+	"MOVO",		LTYPE3,	AMOVO,
+	"MOVOA",	LTYPE3,	AMOVO,	/* syn */
+	"MOVOU",	LTYPE3,	AMOVOU,
+	"MOVHLPS",	LTYPE3,	AMOVHLPS,
+	"MOVHPD",	LTYPE3,	AMOVHPD,
+	"MOVHPS",	LTYPE3,	AMOVHPS,
+	"MOVLHPS",	LTYPE3,	AMOVLHPS,
+	"MOVLPD",	LTYPE3,	AMOVLPD,
+	"MOVLPS",	LTYPE3,	AMOVLPS,
+	"MOVMSKPD",	LTYPE3,	AMOVMSKPD,
+	"MOVMSKPS",	LTYPE3,	AMOVMSKPS,
+	"MOVNTO",	LTYPE3,	AMOVNTO,
+	"MOVNTDQ",	LTYPE3,	AMOVNTO,	/* syn */
+	"MOVNTPD",	LTYPE3,	AMOVNTPD,
+	"MOVNTPS",	LTYPE3,	AMOVNTPS,
+	"MOVSD",	LTYPE3,	AMOVSD,
+	"MOVSS",	LTYPE3,	AMOVSS,
+	"MOVUPD",	LTYPE3,	AMOVUPD,
+	"MOVUPS",	LTYPE3,	AMOVUPS,
+	"MULPD",	LTYPE3,	AMULPD,
+	"MULPS",	LTYPE3,	AMULPS,
+	"MULSD",	LTYPE3,	AMULSD,
+	"MULSS",	LTYPE3,	AMULSS,
+	"ORPD",		LTYPE3,	AORPD,
+	"ORPS",		LTYPE3,	AORPS,
+	"PADDQ",	LTYPE3,	APADDQ,
+	"PMAXSW",	LTYPE3,	APMAXSW,
+	"PMAXUB",	LTYPE3,	APMAXUB,
+	"PMINSW",	LTYPE3,	APMINSW,
+	"PMINUB",	LTYPE3,	APMINUB,
+	"PSADBW",	LTYPE3,	APSADBW,
+	"PSUBB",	LTYPE3,	APSUBB,
+	"PSUBL",	LTYPE3,	APSUBL,
+	"PSUBQ",	LTYPE3,	APSUBQ,
+	"PSUBSB",	LTYPE3,	APSUBSB,
+	"PSUBSW",	LTYPE3,	APSUBSW,
+	"PSUBUSB",	LTYPE3,	APSUBUSB,
+	"PSUBUSW",	LTYPE3,	APSUBUSW,
+	"PSUBW",	LTYPE3,	APSUBW,
+	"PUNPCKHQDQ",	LTYPE3,	APUNPCKHQDQ,
+	"PUNPCKLQDQ",	LTYPE3,	APUNPCKLQDQ,
+	"RCPPS",	LTYPE3,	ARCPPS,
+	"RCPSS",	LTYPE3,	ARCPSS,
+	"RSQRTPS",	LTYPE3,	ARSQRTPS,
+	"RSQRTSS",	LTYPE3,	ARSQRTSS,
+	"SQRTPD",	LTYPE3,	ASQRTPD,
+	"SQRTPS",	LTYPE3,	ASQRTPS,
+	"SQRTSD",	LTYPE3,	ASQRTSD,
+	"SQRTSS",	LTYPE3,	ASQRTSS,
+	"SUBPD",	LTYPE3,	ASUBPD,
+	"SUBPS",	LTYPE3,	ASUBPS,
+	"SUBSD",	LTYPE3,	ASUBSD,
+	"SUBSS",	LTYPE3,	ASUBSS,
+	"UCOMISD",	LTYPE3,	AUCOMISD,
+	"UCOMISS",	LTYPE3,	AUCOMISS,
+	"UNPCKHPD",	LTYPE3,	AUNPCKHPD,
+	"UNPCKHPS",	LTYPE3,	AUNPCKHPS,
+	"UNPCKLPD",	LTYPE3,	AUNPCKLPD,
+	"UNPCKLPS",	LTYPE3,	AUNPCKLPS,
+	"XORPD",	LTYPE3,	AXORPD,
+	"XORPS",	LTYPE3,	AXORPS,
+	"USEFIELD",	LTYPEN, AUSEFIELD,
 
 	0
 };
@@ -915,11 +1039,38 @@ outhist(void)
 	Hist *h;
 	char *p, *q, *op, c;
 	int n;
+	char *tofree;
+	static int first = 1;
+	static char *goroot, *goroot_final;
+
+	if(first) {
+		// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
+		first = 0;
+		goroot = getenv("GOROOT");
+		goroot_final = getenv("GOROOT_FINAL");
+		if(goroot == nil)
+			goroot = "";
+		if(goroot_final == nil)
+			goroot_final = goroot;
+		if(strcmp(goroot, goroot_final) == 0) {
+			goroot = nil;
+			goroot_final = nil;
+		}
+	}
+
+	tofree = nil;
 
 	g = nullgen;
 	c = pathchar();
 	for(h = hist; h != H; h = h->link) {
 		p = h->name;
+		if(p != nil && goroot != nil) {
+			n = strlen(goroot);
+			if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
+				tofree = smprint("%s%s", goroot_final, p+n);
+				p = tofree;
+			}
+		}
 		op = 0;
 		if(systemtype(Windows) && p && p[1] == ':'){
 			c = p[2];
@@ -971,6 +1122,11 @@ outhist(void)
 		Bputc(&obuf, h->line>>24);
 		zaddr(&nullgen, 0);
 		zaddr(&g, 0);
+
+		if(tofree) {
+			free(tofree);
+			tofree = nil;
+		}
 	}
 }
 
diff --git a/src/cmd/8a/y.tab.c b/src/cmd/8a/y.tab.c
index ccd3a25..38f2de5 100644
--- a/src/cmd/8a/y.tab.c
+++ b/src/cmd/8a/y.tab.c
@@ -1,10 +1,8 @@
+/* A Bison parser, made by GNU Bison 2.6.5.  */
 
-/* A Bison parser, made by GNU Bison 2.4.1.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
+/* Bison implementation for Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989-1990, 2000-2012 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
@@ -46,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.1"
+#define YYBISON_VERSION "2.6.5"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -60,14 +58,11 @@
 /* Pull parsers.  */
 #define YYPULL 1
 
-/* Using locations.  */
-#define YYLSP_NEEDED 0
 
 
 
 /* Copy the first part of user declarations.  */
-
-/* Line 189 of yacc.c  */
+/* Line 360 of yacc.c  */
 #line 31 "a.y"
 
 #include <u.h>
@@ -75,14 +70,16 @@
 #include <libc.h>
 #include "a.h"
 
+/* Line 360 of yacc.c  */
+#line 75 "y.tab.c"
 
-/* Line 189 of yacc.c  */
-#line 81 "y.tab.c"
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
+# 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
@@ -92,11 +89,17 @@
 # define YYERROR_VERBOSE 0
 #endif
 
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
+/* 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
@@ -118,20 +121,22 @@
      LTYPEM = 269,
      LTYPEI = 270,
      LTYPEG = 271,
-     LCONST = 272,
-     LFP = 273,
-     LPC = 274,
-     LSB = 275,
-     LBREG = 276,
-     LLREG = 277,
-     LSREG = 278,
-     LFREG = 279,
-     LFCONST = 280,
-     LSCONST = 281,
-     LSP = 282,
-     LNAME = 283,
-     LLAB = 284,
-     LVAR = 285
+     LTYPEXC = 272,
+     LCONST = 273,
+     LFP = 274,
+     LPC = 275,
+     LSB = 276,
+     LBREG = 277,
+     LLREG = 278,
+     LSREG = 279,
+     LFREG = 280,
+     LXREG = 281,
+     LFCONST = 282,
+     LSCONST = 283,
+     LSP = 284,
+     LNAME = 285,
+     LLAB = 286,
+     LVAR = 287
    };
 #endif
 /* Tokens.  */
@@ -149,29 +154,29 @@
 #define LTYPEM 269
 #define LTYPEI 270
 #define LTYPEG 271
-#define LCONST 272
-#define LFP 273
-#define LPC 274
-#define LSB 275
-#define LBREG 276
-#define LLREG 277
-#define LSREG 278
-#define LFREG 279
-#define LFCONST 280
-#define LSCONST 281
-#define LSP 282
-#define LNAME 283
-#define LLAB 284
-#define LVAR 285
-
+#define LTYPEXC 272
+#define LCONST 273
+#define LFP 274
+#define LPC 275
+#define LSB 276
+#define LBREG 277
+#define LLREG 278
+#define LSREG 279
+#define LFREG 280
+#define LXREG 281
+#define LFCONST 282
+#define LSCONST 283
+#define LSP 284
+#define LNAME 285
+#define LLAB 286
+#define LVAR 287
 
 
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 {
-
-/* Line 214 of yacc.c  */
+/* Line 376 of yacc.c  */
 #line 37 "a.y"
 
 	Sym	*sym;
@@ -186,21 +191,36 @@ typedef union YYSTYPE
 	Gen2	gen2;
 
 
-
-/* Line 214 of yacc.c  */
-#line 192 "y.tab.c"
+/* Line 376 of yacc.c  */
+#line 196 "y.tab.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
+extern YYSTYPE yylval;
 
-/* Copy the second part of user declarations.  */
+#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 264 of yacc.c  */
-#line 204 "y.tab.c"
+/* Line 379 of yacc.c  */
+#line 224 "y.tab.c"
 
 #ifdef short
 # undef short
@@ -250,27 +270,27 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# 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
+#  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)
@@ -303,11 +323,12 @@ YYID (yyi)
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
 #     endif
 #    endif
 #   endif
@@ -330,24 +351,24 @@ YYID (yyi)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
 #  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
        && ! ((defined YYMALLOC || defined malloc) \
 	     && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
 #   endif
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+#   if ! defined malloc && ! defined EXIT_SUCCESS && (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 _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
@@ -376,23 +397,7 @@ union yyalloc
      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
       + YYSTACK_GAP_MAXIMUM)
 
-/* 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
+# define YYCOPY_NEEDED 1
 
 /* Relocate STACK from its old location to the new one.  The
    local variables YYSIZE and YYSTACKSIZE give the old and new number of
@@ -412,23 +417,43 @@ 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.  */
-#define YYLAST   483
+#define YYLAST   544
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  49
+#define YYNTOKENS  51
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  37
+#define YYNNTS  38
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  124
+#define YYNRULES  128
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  244
+#define YYNSTATES  255
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   285
+#define YYMAXUTOK   287
 
 #define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -439,16 +464,16 @@ static const yytype_uint8 yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,    47,    12,     5,     2,
-      45,    46,    10,     8,    44,     9,     2,    11,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    41,    42,
-       6,    43,     7,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,    49,    12,     5,     2,
+      47,    48,    10,     8,    46,     9,     2,    11,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    43,    44,
+       6,    45,     7,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     4,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     3,     2,    48,     2,     2,     2,
+       2,     2,     2,     2,     3,     2,    50,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -464,7 +489,7 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     1,     2,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40
+      35,    36,    37,    38,    39,    40,    41,    42
 };
 
 #if YYDEBUG
@@ -474,64 +499,66 @@ static const yytype_uint16 yyprhs[] =
 {
        0,     0,     3,     4,     5,     9,    10,    15,    16,    21,
       23,    26,    29,    33,    37,    40,    43,    46,    49,    52,
-      55,    58,    61,    64,    67,    70,    73,    76,    79,    80,
-      82,    86,    90,    93,    95,    98,   100,   103,   105,   111,
-     115,   121,   124,   126,   129,   131,   133,   137,   143,   147,
-     153,   156,   158,   162,   166,   172,   174,   176,   178,   180,
-     183,   186,   188,   190,   192,   194,   196,   201,   204,   207,
-     209,   211,   213,   215,   217,   220,   223,   226,   229,   234,
-     240,   244,   247,   249,   252,   256,   261,   263,   265,   267,
-     272,   277,   284,   294,   298,   302,   307,   313,   322,   324,
-     331,   337,   345,   346,   349,   352,   354,   356,   358,   360,
-     362,   365,   368,   371,   375,   377,   381,   385,   389,   393,
-     397,   402,   407,   411,   415
+      55,    58,    61,    64,    67,    70,    73,    76,    79,    82,
+      83,    85,    89,    93,    96,    98,   101,   103,   106,   108,
+     112,   118,   122,   128,   131,   133,   136,   138,   140,   144,
+     150,   154,   160,   163,   165,   169,   173,   179,   185,   187,
+     189,   191,   193,   196,   199,   201,   203,   205,   207,   209,
+     214,   217,   220,   222,   224,   226,   228,   230,   232,   235,
+     238,   241,   244,   249,   255,   259,   262,   264,   267,   271,
+     276,   278,   280,   282,   287,   292,   299,   309,   313,   317,
+     322,   328,   337,   339,   346,   352,   360,   361,   364,   367,
+     369,   371,   373,   375,   377,   380,   383,   386,   390,   392,
+     396,   400,   404,   408,   412,   417,   422,   426,   430
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      50,     0,    -1,    -1,    -1,    50,    51,    52,    -1,    -1,
-      39,    41,    53,    52,    -1,    -1,    38,    41,    54,    52,
-      -1,    42,    -1,    55,    42,    -1,     1,    42,    -1,    38,
-      43,    85,    -1,    40,    43,    85,    -1,    13,    56,    -1,
-      14,    60,    -1,    15,    59,    -1,    16,    57,    -1,    17,
-      58,    -1,    21,    61,    -1,    19,    62,    -1,    22,    63,
-      -1,    18,    64,    -1,    20,    65,    -1,    23,    66,    -1,
-      24,    67,    -1,    25,    68,    -1,    26,    69,    -1,    -1,
-      44,    -1,    72,    44,    70,    -1,    70,    44,    72,    -1,
-      72,    44,    -1,    72,    -1,    44,    70,    -1,    70,    -1,
-      44,    73,    -1,    73,    -1,    81,    11,    84,    44,    75,
-      -1,    78,    44,    76,    -1,    78,    44,    84,    44,    76,
-      -1,    44,    71,    -1,    71,    -1,    10,    81,    -1,    56,
-      -1,    60,    -1,    72,    44,    70,    -1,    72,    44,    70,
-      41,    32,    -1,    72,    44,    70,    -1,    72,    44,    70,
-      41,    33,    -1,    72,    44,    -1,    72,    -1,    72,    44,
-      70,    -1,    78,    44,    75,    -1,    78,    44,    84,    44,
-      75,    -1,    74,    -1,    78,    -1,    73,    -1,    80,    -1,
-      10,    74,    -1,    10,    79,    -1,    74,    -1,    79,    -1,
-      75,    -1,    70,    -1,    75,    -1,    84,    45,    29,    46,
-      -1,    38,    82,    -1,    39,    82,    -1,    31,    -1,    34,
-      -1,    32,    -1,    37,    -1,    33,    -1,    47,    84,    -1,
-      47,    81,    -1,    47,    36,    -1,    47,    35,    -1,    47,
-      45,    35,    46,    -1,    47,    45,     9,    35,    46,    -1,
-      47,     9,    35,    -1,    47,    77,    -1,    27,    -1,     9,
-      27,    -1,    27,     9,    27,    -1,     9,    27,     9,    27,
-      -1,    79,    -1,    80,    -1,    84,    -1,    84,    45,    32,
-      46,    -1,    84,    45,    37,    46,    -1,    84,    45,    32,
-      10,    84,    46,    -1,    84,    45,    32,    46,    45,    32,
-      10,    84,    46,    -1,    45,    32,    46,    -1,    45,    37,
-      46,    -1,    84,    45,    33,    46,    -1,    45,    32,    10,
-      84,    46,    -1,    45,    32,    46,    45,    32,    10,    84,
-      46,    -1,    81,    -1,    81,    45,    32,    10,    84,    46,
-      -1,    38,    82,    45,    83,    46,    -1,    38,     6,     7,
-      82,    45,    30,    46,    -1,    -1,     8,    84,    -1,     9,
-      84,    -1,    30,    -1,    37,    -1,    28,    -1,    27,    -1,
-      40,    -1,     9,    84,    -1,     8,    84,    -1,    48,    84,
-      -1,    45,    85,    46,    -1,    84,    -1,    85,     8,    85,
-      -1,    85,     9,    85,    -1,    85,    10,    85,    -1,    85,
-      11,    85,    -1,    85,    12,    85,    -1,    85,     6,     6,
-      85,    -1,    85,     7,     7,    85,    -1,    85,     5,    85,
-      -1,    85,     4,    85,    -1,    85,     3,    85,    -1
+      52,     0,    -1,    -1,    -1,    52,    53,    54,    -1,    -1,
+      41,    43,    55,    54,    -1,    -1,    40,    43,    56,    54,
+      -1,    44,    -1,    57,    44,    -1,     1,    44,    -1,    40,
+      45,    88,    -1,    42,    45,    88,    -1,    13,    58,    -1,
+      14,    62,    -1,    15,    61,    -1,    16,    59,    -1,    17,
+      60,    -1,    21,    63,    -1,    19,    64,    -1,    22,    65,
+      -1,    18,    66,    -1,    20,    67,    -1,    23,    68,    -1,
+      24,    69,    -1,    25,    70,    -1,    26,    71,    -1,    27,
+      72,    -1,    -1,    46,    -1,    75,    46,    73,    -1,    73,
+      46,    75,    -1,    75,    46,    -1,    75,    -1,    46,    73,
+      -1,    73,    -1,    46,    76,    -1,    76,    -1,    78,    46,
+      76,    -1,    84,    11,    87,    46,    78,    -1,    81,    46,
+      79,    -1,    81,    46,    87,    46,    79,    -1,    46,    74,
+      -1,    74,    -1,    10,    84,    -1,    58,    -1,    62,    -1,
+      75,    46,    73,    -1,    75,    46,    73,    43,    33,    -1,
+      75,    46,    73,    -1,    75,    46,    73,    43,    34,    -1,
+      75,    46,    -1,    75,    -1,    75,    46,    73,    -1,    81,
+      46,    78,    -1,    81,    46,    87,    46,    78,    -1,    77,
+      46,    73,    46,    87,    -1,    77,    -1,    81,    -1,    76,
+      -1,    83,    -1,    10,    77,    -1,    10,    82,    -1,    77,
+      -1,    82,    -1,    78,    -1,    73,    -1,    78,    -1,    87,
+      47,    30,    48,    -1,    40,    85,    -1,    41,    85,    -1,
+      32,    -1,    35,    -1,    33,    -1,    36,    -1,    39,    -1,
+      34,    -1,    49,    87,    -1,    49,    84,    -1,    49,    38,
+      -1,    49,    37,    -1,    49,    47,    37,    48,    -1,    49,
+      47,     9,    37,    48,    -1,    49,     9,    37,    -1,    49,
+      80,    -1,    28,    -1,     9,    28,    -1,    28,     9,    28,
+      -1,     9,    28,     9,    28,    -1,    82,    -1,    83,    -1,
+      87,    -1,    87,    47,    33,    48,    -1,    87,    47,    39,
+      48,    -1,    87,    47,    33,    10,    87,    48,    -1,    87,
+      47,    33,    48,    47,    33,    10,    87,    48,    -1,    47,
+      33,    48,    -1,    47,    39,    48,    -1,    87,    47,    34,
+      48,    -1,    47,    33,    10,    87,    48,    -1,    47,    33,
+      48,    47,    33,    10,    87,    48,    -1,    84,    -1,    84,
+      47,    33,    10,    87,    48,    -1,    40,    85,    47,    86,
+      48,    -1,    40,     6,     7,    85,    47,    31,    48,    -1,
+      -1,     8,    87,    -1,     9,    87,    -1,    31,    -1,    39,
+      -1,    29,    -1,    28,    -1,    42,    -1,     9,    87,    -1,
+       8,    87,    -1,    50,    87,    -1,    47,    88,    48,    -1,
+      87,    -1,    88,     8,    88,    -1,    88,     9,    88,    -1,
+      88,    10,    88,    -1,    88,    11,    88,    -1,    88,    12,
+      88,    -1,    88,     6,     6,    88,    -1,    88,     7,     7,
+      88,    -1,    88,     5,    88,    -1,    88,     4,    88,    -1,
+      88,     3,    88,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
@@ -539,21 +566,21 @@ static const yytype_uint16 yyrline[] =
 {
        0,    68,    68,    70,    69,    77,    76,    84,    83,    89,
       90,    91,    94,    99,   105,   106,   107,   108,   109,   110,
-     111,   112,   113,   114,   115,   116,   117,   118,   121,   125,
-     132,   139,   146,   151,   158,   163,   170,   175,   182,   190,
-     195,   203,   208,   213,   222,   223,   226,   231,   241,   246,
-     256,   261,   266,   273,   278,   286,   287,   290,   291,   292,
-     296,   300,   301,   302,   305,   306,   309,   315,   324,   333,
-     338,   343,   348,   353,   360,   366,   377,   383,   389,   395,
-     401,   409,   418,   423,   428,   433,   440,   441,   444,   450,
-     456,   462,   471,   480,   485,   490,   496,   504,   514,   518,
-     527,   534,   543,   546,   550,   556,   557,   561,   564,   565,
-     569,   573,   577,   581,   587,   588,   592,   596,   600,   604,
-     608,   612,   616,   620,   624
+     111,   112,   113,   114,   115,   116,   117,   118,   119,   122,
+     126,   133,   140,   147,   152,   159,   164,   171,   176,   181,
+     188,   196,   201,   209,   214,   219,   228,   229,   232,   237,
+     247,   252,   262,   267,   272,   279,   284,   292,   300,   301,
+     304,   305,   306,   310,   314,   315,   316,   319,   320,   323,
+     329,   338,   347,   352,   357,   362,   367,   372,   379,   385,
+     396,   402,   408,   414,   420,   428,   437,   442,   447,   452,
+     459,   460,   463,   469,   475,   481,   490,   499,   504,   509,
+     515,   523,   533,   537,   546,   553,   562,   565,   569,   575,
+     576,   580,   583,   584,   588,   592,   596,   600,   606,   607,
+     611,   615,   619,   623,   627,   631,   635,   639,   643
 };
 #endif
 
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+#if YYDEBUG || YYERROR_VERBOSE || 0
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
@@ -561,14 +588,14 @@ static const char *const yytname[] =
   "$end", "error", "$undefined", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'",
   "'-'", "'*'", "'/'", "'%'", "LTYPE0", "LTYPE1", "LTYPE2", "LTYPE3",
   "LTYPE4", "LTYPEC", "LTYPED", "LTYPEN", "LTYPER", "LTYPET", "LTYPES",
-  "LTYPEM", "LTYPEI", "LTYPEG", "LCONST", "LFP", "LPC", "LSB", "LBREG",
-  "LLREG", "LSREG", "LFREG", "LFCONST", "LSCONST", "LSP", "LNAME", "LLAB",
-  "LVAR", "':'", "';'", "'='", "','", "'('", "')'", "'$'", "'~'",
-  "$accept", "prog", "$@1", "line", "$@2", "$@3", "inst", "nonnon",
+  "LTYPEM", "LTYPEI", "LTYPEG", "LTYPEXC", "LCONST", "LFP", "LPC", "LSB",
+  "LBREG", "LLREG", "LSREG", "LFREG", "LXREG", "LFCONST", "LSCONST", "LSP",
+  "LNAME", "LLAB", "LVAR", "':'", "';'", "'='", "','", "'('", "')'", "'$'",
+  "'~'", "$accept", "prog", "$@1", "line", "$@2", "$@3", "inst", "nonnon",
   "rimrem", "remrim", "rimnon", "nonrem", "nonrel", "spec1", "spec2",
-  "spec3", "spec4", "spec5", "spec6", "spec7", "spec8", "rem", "rom",
-  "rim", "rel", "reg", "imm", "imm2", "con2", "mem", "omem", "nmem", "nam",
-  "offset", "pointer", "con", "expr", 0
+  "spec3", "spec4", "spec5", "spec6", "spec7", "spec8", "spec9", "rem",
+  "rom", "rim", "rel", "reg", "imm", "imm2", "con2", "mem", "omem", "nmem",
+  "nam", "offset", "pointer", "con", "expr", YY_NULL
 };
 #endif
 
@@ -581,26 +608,27 @@ static const yytype_uint16 yytoknum[] =
       42,    47,    37,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,    58,    59,    61,    44,    40,    41,    36,   126
+     285,   286,   287,    58,    59,    61,    44,    40,    41,    36,
+     126
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    49,    50,    51,    50,    53,    52,    54,    52,    52,
-      52,    52,    55,    55,    55,    55,    55,    55,    55,    55,
-      55,    55,    55,    55,    55,    55,    55,    55,    56,    56,
-      57,    58,    59,    59,    60,    60,    61,    61,    62,    63,
-      63,    64,    64,    64,    65,    65,    66,    66,    67,    67,
-      68,    68,    68,    69,    69,    70,    70,    71,    71,    71,
-      71,    71,    71,    71,    72,    72,    73,    73,    73,    74,
-      74,    74,    74,    74,    75,    75,    75,    75,    75,    75,
-      75,    76,    77,    77,    77,    77,    78,    78,    79,    79,
-      79,    79,    79,    79,    79,    79,    79,    79,    80,    80,
-      81,    81,    82,    82,    82,    83,    83,    83,    84,    84,
-      84,    84,    84,    84,    85,    85,    85,    85,    85,    85,
-      85,    85,    85,    85,    85
+       0,    51,    52,    53,    52,    55,    54,    56,    54,    54,
+      54,    54,    57,    57,    57,    57,    57,    57,    57,    57,
+      57,    57,    57,    57,    57,    57,    57,    57,    57,    58,
+      58,    59,    60,    61,    61,    62,    62,    63,    63,    63,
+      64,    65,    65,    66,    66,    66,    67,    67,    68,    68,
+      69,    69,    70,    70,    70,    71,    71,    72,    73,    73,
+      74,    74,    74,    74,    74,    74,    74,    75,    75,    76,
+      76,    76,    77,    77,    77,    77,    77,    77,    78,    78,
+      78,    78,    78,    78,    78,    79,    80,    80,    80,    80,
+      81,    81,    82,    82,    82,    82,    82,    82,    82,    82,
+      82,    82,    83,    83,    84,    84,    85,    85,    85,    86,
+      86,    86,    87,    87,    87,    87,    87,    87,    88,    88,
+      88,    88,    88,    88,    88,    88,    88,    88,    88
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -608,241 +636,261 @@ static const yytype_uint8 yyr2[] =
 {
        0,     2,     0,     0,     3,     0,     4,     0,     4,     1,
        2,     2,     3,     3,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     0,     1,
-       3,     3,     2,     1,     2,     1,     2,     1,     5,     3,
-       5,     2,     1,     2,     1,     1,     3,     5,     3,     5,
-       2,     1,     3,     3,     5,     1,     1,     1,     1,     2,
-       2,     1,     1,     1,     1,     1,     4,     2,     2,     1,
-       1,     1,     1,     1,     2,     2,     2,     2,     4,     5,
-       3,     2,     1,     2,     3,     4,     1,     1,     1,     4,
-       4,     6,     9,     3,     3,     4,     5,     8,     1,     6,
-       5,     7,     0,     2,     2,     1,     1,     1,     1,     1,
-       2,     2,     2,     3,     1,     3,     3,     3,     3,     3,
-       4,     4,     3,     3,     3
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     0,
+       1,     3,     3,     2,     1,     2,     1,     2,     1,     3,
+       5,     3,     5,     2,     1,     2,     1,     1,     3,     5,
+       3,     5,     2,     1,     3,     3,     5,     5,     1,     1,
+       1,     1,     2,     2,     1,     1,     1,     1,     1,     4,
+       2,     2,     1,     1,     1,     1,     1,     1,     2,     2,
+       2,     2,     4,     5,     3,     2,     1,     2,     3,     4,
+       1,     1,     1,     4,     4,     6,     9,     3,     3,     4,
+       5,     8,     1,     6,     5,     7,     0,     2,     2,     1,
+       1,     1,     1,     1,     2,     2,     2,     3,     1,     3,
+       3,     3,     3,     3,     4,     4,     3,     3,     3
 };
 
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
+   Performed when YYTABLE doesn't specify something else to do.  Zero
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       2,     3,     1,     0,     0,    28,     0,     0,     0,     0,
-       0,     0,    28,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     9,     4,     0,    11,    29,    14,     0,     0,
-     108,    69,    71,    73,    70,    72,   102,   109,     0,     0,
-       0,    15,    35,    55,    56,    86,    87,    98,    88,     0,
-      16,    64,    33,    65,    17,     0,    18,     0,     0,   102,
-     102,     0,    22,    42,    57,    61,    63,    62,    58,    88,
-      20,     0,    29,    44,    45,    23,   102,     0,     0,    19,
-      37,     0,    21,     0,    24,     0,    25,     0,    26,    51,
-      27,     0,     7,     0,     5,     0,    10,   111,   110,     0,
-       0,     0,     0,    34,     0,     0,   114,     0,   112,     0,
-       0,     0,    77,    76,     0,    75,    74,    32,     0,     0,
-      59,    60,    43,    67,    68,     0,    41,     0,     0,    67,
-      36,     0,     0,     0,     0,    50,     0,     0,    12,     0,
-      13,   102,   103,   104,     0,     0,    93,    94,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   113,     0,
-       0,     0,     0,    80,     0,     0,    30,    31,     0,     0,
-       0,    39,     0,    46,    48,    52,    53,     0,     8,     6,
-       0,   107,   105,   106,     0,     0,     0,   124,   123,   122,
-       0,     0,   115,   116,   117,   118,   119,     0,     0,    89,
-      95,    90,     0,    78,    66,     0,     0,    82,    81,     0,
-       0,     0,     0,     0,   100,    96,     0,   120,   121,     0,
-       0,     0,    79,    38,    83,     0,    40,    47,    49,    54,
-       0,     0,    99,    91,     0,     0,    84,   101,     0,     0,
-      85,    97,     0,    92
+       2,     3,     1,     0,     0,    29,     0,     0,     0,     0,
+       0,     0,    29,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     9,     4,     0,    11,    30,    14,     0,
+       0,   112,    72,    74,    77,    73,    75,    76,   106,   113,
+       0,     0,     0,    15,    36,    58,    59,    90,    91,   102,
+      92,     0,    16,    67,    34,    68,    17,     0,    18,     0,
+       0,   106,   106,     0,    22,    44,    60,    64,    66,    65,
+      61,    92,    20,     0,    30,    46,    47,    23,   106,     0,
+       0,    19,    38,     0,     0,    21,     0,    24,     0,    25,
+       0,    26,    53,    27,     0,    28,     0,     7,     0,     5,
+       0,    10,   115,   114,     0,     0,     0,     0,    35,     0,
+       0,   118,     0,   116,     0,     0,     0,    81,    80,     0,
+      79,    78,    33,     0,     0,    62,    63,    45,    70,    71,
+       0,    43,     0,     0,    70,    37,     0,     0,     0,     0,
+       0,    52,     0,     0,     0,    12,     0,    13,   106,   107,
+     108,     0,     0,    97,    98,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   117,     0,     0,     0,     0,
+      84,     0,     0,    31,    32,     0,     0,    39,     0,    41,
+       0,    48,    50,    54,    55,     0,     0,     8,     6,     0,
+     111,   109,   110,     0,     0,     0,   128,   127,   126,     0,
+       0,   119,   120,   121,   122,   123,     0,     0,    93,    99,
+      94,     0,    82,    69,     0,     0,    86,    85,     0,     0,
+       0,     0,     0,     0,   104,   100,     0,   124,   125,     0,
+       0,     0,    83,    40,    87,     0,    42,    49,    51,    56,
+      57,     0,     0,   103,    95,     0,     0,    88,   105,     0,
+       0,    89,   101,     0,    96
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     3,    23,   139,   137,    24,    27,    54,    56,
-      50,    41,    79,    70,    82,    62,    75,    84,    86,    88,
-      90,    51,    63,    52,    64,    43,    53,   171,   208,    44,
-      45,    46,    47,   102,   184,    48,   107
+      -1,     1,     3,    24,   146,   144,    25,    28,    56,    58,
+      52,    43,    81,    72,    85,    64,    77,    87,    89,    91,
+      93,    95,    53,    65,    54,    66,    45,    55,   179,   217,
+      46,    47,    48,    49,   107,   193,    50,   112
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -107
+#define YYPACT_NINF -96
 static const yytype_int16 yypact[] =
 {
-    -107,     9,  -107,   151,   -28,   -19,   235,   255,   255,   302,
-     175,     6,   282,    34,   363,   255,   255,   255,   363,    -3,
-      -6,     5,  -107,  -107,     4,  -107,  -107,  -107,   373,   373,
-    -107,  -107,  -107,  -107,  -107,  -107,   128,  -107,   302,   343,
-     373,  -107,  -107,  -107,  -107,  -107,  -107,    17,    19,   115,
-    -107,  -107,    15,  -107,  -107,    27,  -107,    42,   302,   128,
-      72,   208,  -107,  -107,  -107,  -107,  -107,  -107,  -107,    52,
-    -107,    44,   302,  -107,  -107,  -107,    72,   359,   373,  -107,
-    -107,    55,  -107,    71,  -107,    76,  -107,    81,  -107,    84,
-    -107,    97,  -107,   373,  -107,   373,  -107,  -107,  -107,   142,
-     373,   373,   114,  -107,     1,   116,  -107,   102,  -107,   129,
-      66,   385,  -107,  -107,   387,  -107,  -107,  -107,   302,   255,
-    -107,  -107,  -107,   114,  -107,   329,  -107,   168,   373,  -107,
-    -107,   149,    18,   302,   302,   302,   397,   151,   447,   151,
-     447,    72,  -107,  -107,    47,   373,   134,  -107,   373,   373,
-     373,   176,   179,   373,   373,   373,   373,   373,  -107,   182,
-       3,   148,   152,  -107,   401,   153,  -107,  -107,   158,   166,
-      14,  -107,   167,   154,   189,  -107,  -107,   187,  -107,  -107,
-     188,  -107,  -107,  -107,   186,   190,   202,   456,   464,   471,
-     373,   373,   146,   146,  -107,  -107,  -107,   373,   373,   192,
-    -107,  -107,   203,  -107,  -107,   191,   223,   242,  -107,   205,
-     222,   224,   191,   228,  -107,  -107,   249,   216,   216,   214,
-     215,   233,  -107,  -107,   261,   244,  -107,  -107,  -107,  -107,
-     230,   373,  -107,  -107,   264,   250,  -107,  -107,   232,   373,
-    -107,  -107,   238,  -107
+     -96,    34,   -96,   158,   -38,   -30,   267,   288,   288,   338,
+     195,    20,   317,   210,   428,   288,   288,   288,   428,    68,
+      -6,     2,    42,   -96,   -96,    45,   -96,   -96,   -96,   449,
+     449,   -96,   -96,   -96,   -96,   -96,   -96,   -96,   127,   -96,
+     338,   388,   449,   -96,   -96,   -96,   -96,   -96,   -96,    46,
+      47,   382,   -96,   -96,    52,   -96,   -96,    59,   -96,    62,
+     338,   127,    19,   238,   -96,   -96,   -96,   -96,   -96,   -96,
+     -96,    63,   -96,   103,   338,   -96,   -96,   -96,    19,   403,
+     449,   -96,   -96,    69,    78,   -96,    81,   -96,    94,   -96,
+      97,   -96,    98,   -96,   102,   -96,   111,   -96,   449,   -96,
+     449,   -96,   -96,   -96,   142,   449,   449,   113,   -96,    23,
+     110,   -96,    74,   -96,   137,    58,   432,   -96,   -96,   439,
+     -96,   -96,   -96,   338,   288,   -96,   -96,   -96,   113,   -96,
+     367,   -96,    13,   449,   -96,   -96,   403,   156,    16,   338,
+     338,   338,   443,   338,   158,   523,   158,   523,    19,   -96,
+     -96,    11,   449,   140,   -96,   449,   449,   449,   182,   194,
+     449,   449,   449,   449,   449,   -96,   197,    25,   160,   161,
+     -96,   475,   162,   -96,   -96,   163,   168,   -96,     8,   -96,
+     169,   173,   174,   -96,   -96,   175,   176,   -96,   -96,   177,
+     -96,   -96,   -96,   172,   178,   192,   532,   157,   498,   449,
+     449,    64,    64,   -96,   -96,   -96,   449,   449,   186,   -96,
+     -96,   191,   -96,   -96,   200,   215,   244,   -96,   205,   222,
+     224,   200,   449,   230,   -96,   -96,   252,   183,   183,   216,
+     217,   234,   -96,   -96,   254,   240,   -96,   -96,   -96,   -96,
+     -96,   221,   449,   -96,   -96,   271,   255,   -96,   -96,   236,
+     449,   -96,   -96,   241,   -96
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -107,  -107,  -107,  -106,  -107,  -107,  -107,   269,  -107,  -107,
-    -107,   273,  -107,  -107,  -107,  -107,  -107,  -107,  -107,  -107,
-    -107,    -2,   236,     0,    -1,    -8,    -9,    85,  -107,    10,
-      -4,    -5,    11,   -39,  -107,   -10,   -61
+     -96,   -96,   -96,   -95,   -96,   -96,   -96,   270,   -96,   -96,
+     -96,   274,   -96,   -96,   -96,   -96,   -96,   -96,   -96,   -96,
+     -96,   -96,    -2,   227,     6,   -12,    -1,    -8,    73,   -96,
+      12,     1,     5,    -3,   -49,   -96,   -10,   -44
 };
 
 /* 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.  */
+   number is the opposite.  If YYTABLE_NINF, syntax error.  */
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      69,    66,    65,    81,    42,    68,    67,    57,    55,     2,
-      42,   145,    80,   198,    25,    85,    87,    89,    97,    98,
-     123,   124,    71,   206,    83,    26,    28,    29,    91,   106,
-     108,   178,   138,   179,   140,    94,   103,   129,    92,   116,
-      93,   207,    28,    29,    36,    30,    96,   146,    95,   199,
-     120,    69,    66,    65,   121,   128,    68,    67,    37,   117,
-     115,    30,   109,    78,   110,   170,    40,    81,   106,   122,
-     103,   118,    76,    60,    37,   181,   130,   182,    77,    78,
-     100,   101,    40,   106,   183,   106,   119,   187,   188,   189,
-     142,   143,   192,   193,   194,   195,   196,   127,   160,   161,
-     131,    98,   180,   162,   106,   148,   149,   150,   151,   152,
-     153,   154,   155,   156,   157,   132,   166,   120,   169,   167,
-     133,   121,   172,    28,   111,   134,   177,   176,   135,   217,
-     218,   173,   174,   175,    99,   185,   100,   101,   106,   106,
-     106,   136,    30,   106,   106,   106,   106,   106,   158,   141,
-     112,   113,     4,    36,    98,    37,   155,   156,   157,   144,
-     114,   159,   147,    40,     5,     6,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    16,    17,    18,   168,   186,
-     106,   106,   190,    28,    29,    58,   191,   219,   220,    19,
-      20,    21,   197,    22,   200,   210,   223,   168,   201,   203,
-     160,   161,    30,   229,   204,   162,    31,    32,    33,    34,
-     205,   209,    35,    59,    60,    37,    28,    29,   125,    61,
-      39,   238,    49,    40,   153,   154,   155,   156,   157,   242,
-     211,   212,   214,   213,   216,    30,   215,   221,    49,    31,
-      32,    33,    34,    28,    29,    35,    59,    60,    37,   222,
-     224,   225,   170,    39,   227,    49,    40,   228,   230,   231,
-     232,   233,    30,    28,    29,   234,    31,    32,    33,    34,
-     235,   236,    35,    36,   239,    37,   237,   240,   241,    38,
-      39,    73,    30,    40,   243,    74,    31,    32,    33,    34,
-      28,    29,    35,    36,   226,    37,     0,   126,     0,     0,
-      39,     0,    49,    40,     0,     0,     0,     0,     0,    30,
-      28,    29,     0,    31,    32,    33,    34,     0,     0,    35,
-      36,     0,    37,     0,     0,     0,    72,    39,     0,    30,
-      40,     0,     0,    31,    32,    33,    34,    28,    29,    35,
-      36,     0,    37,     0,     0,     0,     0,    39,     0,     0,
-      40,    28,    29,     0,     0,     0,    30,     0,     0,     0,
-      31,    32,    33,    34,     0,     0,    35,    28,    29,    37,
-      30,    28,    29,     0,    39,   104,     0,    40,     0,     0,
-     105,    28,    29,    37,     0,     0,    30,     0,    78,     0,
-      30,    40,     0,    28,    29,    28,   164,    76,    60,    37,
-      30,    36,     0,    37,    78,    28,    29,    40,    39,    28,
-      29,    40,    30,    37,    30,     0,     0,     0,    78,     0,
-     163,    40,   165,     0,    30,    37,     0,    37,    30,     0,
-      78,     0,    78,    40,     0,    40,   202,    37,     0,     0,
-       0,    37,    78,     0,    49,    40,    78,     0,     0,    40,
-     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
-     149,   150,   151,   152,   153,   154,   155,   156,   157,   150,
-     151,   152,   153,   154,   155,   156,   157,   151,   152,   153,
-     154,   155,   156,   157
+      71,    82,    68,    84,    44,    83,    26,    59,    73,    67,
+      44,    69,   128,   129,    57,    70,    27,   215,    96,   102,
+     103,    88,    90,    92,    29,    30,    86,   105,   106,   134,
+      94,   111,   113,   152,     2,   207,   216,    97,   108,    98,
+     190,   121,   191,   175,    31,    99,   167,   168,   120,   187,
+     192,   188,   169,    71,   145,    68,   147,   127,    39,   125,
+      38,   126,    67,    80,    69,   178,    42,   135,    70,    84,
+     111,   153,   108,   208,   162,   163,   164,   155,   156,   157,
+     158,   159,   160,   161,   162,   163,   164,   100,   111,   101,
+     111,   167,   168,   114,   115,   149,   150,   169,   122,   189,
+      32,    33,    34,    35,    36,   123,   103,    37,   124,   111,
+     132,   196,   197,   198,   133,   136,   201,   202,   203,   204,
+     205,   173,   165,   176,   177,   137,    84,   138,   180,   125,
+     174,   126,   185,   104,   184,   105,   106,   181,   182,   183,
+     139,   186,   194,   140,   141,   111,   111,   111,   142,   148,
+     111,   111,   111,   111,   111,   227,   228,   143,   154,     4,
+     151,   103,   157,   158,   159,   160,   161,   162,   163,   164,
+     166,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,   175,   195,   199,   111,
+     111,   160,   161,   162,   163,   164,   229,   230,    20,    21,
+      22,   200,    23,    29,    30,    60,   233,   206,   209,   210,
+     212,   213,   240,   239,   214,   218,   219,   220,    29,    30,
+     224,   221,   222,    31,   223,   226,   225,    32,    33,    34,
+      35,    36,   249,   231,    37,    61,    62,    39,    31,   232,
+     253,    63,    41,   234,    51,    42,    29,    30,   130,    51,
+      78,    62,    39,   235,   178,   237,    79,    80,   238,    51,
+      42,   241,   242,   246,   243,   244,    31,   245,   247,   248,
+      32,    33,    34,    35,    36,    29,    30,    37,    61,    62,
+      39,   250,    75,   251,   252,    41,    76,    51,    42,   254,
+     131,   236,     0,     0,     0,    31,    29,    30,     0,    32,
+      33,    34,    35,    36,     0,     0,    37,    38,     0,    39,
+       0,     0,     0,    40,    41,     0,    31,    42,     0,     0,
+      32,    33,    34,    35,    36,    29,    30,    37,    38,     0,
+      39,     0,     0,     0,     0,    41,     0,    51,    42,     0,
+       0,     0,     0,     0,     0,    31,    29,    30,     0,    32,
+      33,    34,    35,    36,     0,     0,    37,    38,     0,    39,
+       0,     0,     0,    74,    41,     0,    31,    42,     0,     0,
+      32,    33,    34,    35,    36,    29,    30,    37,    38,     0,
+      39,     0,     0,     0,     0,    41,     0,     0,    42,     0,
+      29,   116,     0,     0,     0,    31,    29,    30,     0,    32,
+      33,    34,    35,    36,     0,     0,    37,     0,     0,    39,
+      31,    29,    30,     0,    41,     0,    31,    42,     0,   117,
+     118,   109,    38,     0,    39,     0,     0,   110,     0,   119,
+      39,    31,    42,     0,     0,    80,    29,    30,    42,     0,
+      29,    30,     0,    78,    62,    39,     0,    29,   171,     0,
+      80,    29,    30,    42,     0,     0,    31,    29,    30,     0,
+      31,     0,     0,     0,     0,     0,     0,    31,    38,   170,
+      39,    31,     0,     0,    39,    41,   172,    31,    42,    80,
+       0,    39,    42,    29,    30,    39,    80,     0,     0,    42,
+      80,    39,    51,    42,     0,     0,    80,     0,     0,    42,
+       0,     0,     0,    31,   158,   159,   160,   161,   162,   163,
+     164,     0,   211,     0,     0,     0,     0,    39,     0,     0,
+       0,     0,    80,     0,     0,    42,   155,   156,   157,   158,
+     159,   160,   161,   162,   163,   164,   156,   157,   158,   159,
+     160,   161,   162,   163,   164
 };
 
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-96)))
+
+#define yytable_value_is_error(Yytable_value) \
+  YYID (0)
+
 static const yytype_int16 yycheck[] =
 {
-      10,    10,    10,    13,     6,    10,    10,     9,     8,     0,
-      12,    10,    13,    10,    42,    15,    16,    17,    28,    29,
-      59,    60,    11,     9,    14,    44,     8,     9,    18,    39,
-      40,   137,    93,   139,    95,    41,    38,    76,    41,    49,
-      43,    27,     8,     9,    38,    27,    42,    46,    43,    46,
-      58,    61,    61,    61,    58,    11,    61,    61,    40,    44,
-      49,    27,    45,    45,    45,    47,    48,    77,    78,    58,
-      72,    44,    38,    39,    40,    28,    77,    30,    44,    45,
-       8,     9,    48,    93,    37,    95,    44,   148,   149,   150,
-     100,   101,   153,   154,   155,   156,   157,    45,    32,    33,
-      45,   111,   141,    37,   114,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    44,   118,   125,   128,   119,
-      44,   125,   132,     8,     9,    44,   136,   136,    44,   190,
-     191,   133,   134,   135,     6,   145,     8,     9,   148,   149,
-     150,    44,    27,   153,   154,   155,   156,   157,    46,     7,
-      35,    36,     1,    38,   164,    40,    10,    11,    12,    45,
-      45,    32,    46,    48,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    29,    45,
-     190,   191,     6,     8,     9,    10,     7,   197,   198,    38,
-      39,    40,    10,    42,    46,    41,   205,    29,    46,    46,
-      32,    33,    27,   212,    46,    37,    31,    32,    33,    34,
-      44,    44,    37,    38,    39,    40,     8,     9,    10,    44,
-      45,   231,    47,    48,     8,     9,    10,    11,    12,   239,
-      41,    44,    46,    45,    32,    27,    46,    45,    47,    31,
-      32,    33,    34,     8,     9,    37,    38,    39,    40,    46,
-      27,     9,    47,    45,    32,    47,    48,    33,    30,    10,
-      46,    46,    27,     8,     9,    32,    31,    32,    33,    34,
-       9,    27,    37,    38,    10,    40,    46,    27,    46,    44,
-      45,    12,    27,    48,    46,    12,    31,    32,    33,    34,
-       8,     9,    37,    38,   209,    40,    -1,    61,    -1,    -1,
-      45,    -1,    47,    48,    -1,    -1,    -1,    -1,    -1,    27,
-       8,     9,    -1,    31,    32,    33,    34,    -1,    -1,    37,
-      38,    -1,    40,    -1,    -1,    -1,    44,    45,    -1,    27,
-      48,    -1,    -1,    31,    32,    33,    34,     8,     9,    37,
-      38,    -1,    40,    -1,    -1,    -1,    -1,    45,    -1,    -1,
-      48,     8,     9,    -1,    -1,    -1,    27,    -1,    -1,    -1,
-      31,    32,    33,    34,    -1,    -1,    37,     8,     9,    40,
-      27,     8,     9,    -1,    45,    32,    -1,    48,    -1,    -1,
-      37,     8,     9,    40,    -1,    -1,    27,    -1,    45,    -1,
-      27,    48,    -1,     8,     9,     8,     9,    38,    39,    40,
-      27,    38,    -1,    40,    45,     8,     9,    48,    45,     8,
-       9,    48,    27,    40,    27,    -1,    -1,    -1,    45,    -1,
-      35,    48,    35,    -1,    27,    40,    -1,    40,    27,    -1,
-      45,    -1,    45,    48,    -1,    48,    35,    40,    -1,    -1,
-      -1,    40,    45,    -1,    47,    48,    45,    -1,    -1,    48,
-       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-       4,     5,     6,     7,     8,     9,    10,    11,    12,     5,
-       6,     7,     8,     9,    10,    11,    12,     6,     7,     8,
-       9,    10,    11,    12
+      10,    13,    10,    13,     6,    13,    44,     9,    11,    10,
+      12,    10,    61,    62,     8,    10,    46,     9,    19,    29,
+      30,    15,    16,    17,     8,     9,    14,     8,     9,    78,
+      18,    41,    42,    10,     0,    10,    28,    43,    40,    45,
+      29,    51,    31,    30,    28,    43,    33,    34,    51,   144,
+      39,   146,    39,    63,    98,    63,   100,    60,    42,    60,
+      40,    60,    63,    47,    63,    49,    50,    79,    63,    79,
+      80,    48,    74,    48,    10,    11,    12,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    45,    98,    44,
+     100,    33,    34,    47,    47,   105,   106,    39,    46,   148,
+      32,    33,    34,    35,    36,    46,   116,    39,    46,   119,
+      47,   155,   156,   157,    11,    46,   160,   161,   162,   163,
+     164,   123,    48,   133,   136,    47,   136,    46,   138,   130,
+     124,   130,   142,     6,   142,     8,     9,   139,   140,   141,
+      46,   143,   152,    46,    46,   155,   156,   157,    46,     7,
+     160,   161,   162,   163,   164,   199,   200,    46,    48,     1,
+      47,   171,     5,     6,     7,     8,     9,    10,    11,    12,
+      33,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    30,    47,     6,   199,
+     200,     8,     9,    10,    11,    12,   206,   207,    40,    41,
+      42,     7,    44,     8,     9,    10,   214,    10,    48,    48,
+      48,    48,   222,   221,    46,    46,    43,    43,     8,     9,
+      48,    46,    46,    28,    47,    33,    48,    32,    33,    34,
+      35,    36,   242,    47,    39,    40,    41,    42,    28,    48,
+     250,    46,    47,    28,    49,    50,     8,     9,    10,    49,
+      40,    41,    42,     9,    49,    33,    46,    47,    34,    49,
+      50,    31,    10,     9,    48,    48,    28,    33,    28,    48,
+      32,    33,    34,    35,    36,     8,     9,    39,    40,    41,
+      42,    10,    12,    28,    48,    47,    12,    49,    50,    48,
+      63,   218,    -1,    -1,    -1,    28,     8,     9,    -1,    32,
+      33,    34,    35,    36,    -1,    -1,    39,    40,    -1,    42,
+      -1,    -1,    -1,    46,    47,    -1,    28,    50,    -1,    -1,
+      32,    33,    34,    35,    36,     8,     9,    39,    40,    -1,
+      42,    -1,    -1,    -1,    -1,    47,    -1,    49,    50,    -1,
+      -1,    -1,    -1,    -1,    -1,    28,     8,     9,    -1,    32,
+      33,    34,    35,    36,    -1,    -1,    39,    40,    -1,    42,
+      -1,    -1,    -1,    46,    47,    -1,    28,    50,    -1,    -1,
+      32,    33,    34,    35,    36,     8,     9,    39,    40,    -1,
+      42,    -1,    -1,    -1,    -1,    47,    -1,    -1,    50,    -1,
+       8,     9,    -1,    -1,    -1,    28,     8,     9,    -1,    32,
+      33,    34,    35,    36,    -1,    -1,    39,    -1,    -1,    42,
+      28,     8,     9,    -1,    47,    -1,    28,    50,    -1,    37,
+      38,    33,    40,    -1,    42,    -1,    -1,    39,    -1,    47,
+      42,    28,    50,    -1,    -1,    47,     8,     9,    50,    -1,
+       8,     9,    -1,    40,    41,    42,    -1,     8,     9,    -1,
+      47,     8,     9,    50,    -1,    -1,    28,     8,     9,    -1,
+      28,    -1,    -1,    -1,    -1,    -1,    -1,    28,    40,    37,
+      42,    28,    -1,    -1,    42,    47,    37,    28,    50,    47,
+      -1,    42,    50,     8,     9,    42,    47,    -1,    -1,    50,
+      47,    42,    49,    50,    -1,    -1,    47,    -1,    -1,    50,
+      -1,    -1,    -1,    28,     6,     7,     8,     9,    10,    11,
+      12,    -1,    37,    -1,    -1,    -1,    -1,    42,    -1,    -1,
+      -1,    -1,    47,    -1,    -1,    50,     3,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,     4,     5,     6,     7,
+       8,     9,    10,    11,    12
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    50,     0,    51,     1,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    38,
-      39,    40,    42,    52,    55,    42,    44,    56,     8,     9,
-      27,    31,    32,    33,    34,    37,    38,    40,    44,    45,
-      48,    60,    70,    74,    78,    79,    80,    81,    84,    47,
-      59,    70,    72,    75,    57,    72,    58,    70,    10,    38,
-      39,    44,    64,    71,    73,    74,    75,    79,    80,    84,
-      62,    81,    44,    56,    60,    65,    38,    44,    45,    61,
-      73,    84,    63,    78,    66,    72,    67,    72,    68,    72,
-      69,    78,    41,    43,    41,    43,    42,    84,    84,     6,
-       8,     9,    82,    70,    32,    37,    84,    85,    84,    45,
-      45,     9,    35,    36,    45,    81,    84,    44,    44,    44,
-      74,    79,    81,    82,    82,    10,    71,    45,    11,    82,
-      73,    45,    44,    44,    44,    44,    44,    54,    85,    53,
-      85,     7,    84,    84,    45,    10,    46,    46,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    46,    32,
-      32,    33,    37,    35,     9,    35,    70,    72,    29,    84,
-      47,    76,    84,    70,    70,    70,    75,    84,    52,    52,
-      82,    28,    30,    37,    83,    84,    45,    85,    85,    85,
-       6,     7,    85,    85,    85,    85,    85,    10,    10,    46,
-      46,    46,    35,    46,    46,    44,     9,    27,    77,    44,
-      41,    41,    44,    45,    46,    46,    32,    85,    85,    84,
-      84,    45,    46,    75,    27,     9,    76,    32,    33,    75,
-      30,    10,    46,    46,    32,     9,    27,    46,    84,    10,
-      27,    46,    84,    46
+       0,    52,     0,    53,     1,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      40,    41,    42,    44,    54,    57,    44,    46,    58,     8,
+       9,    28,    32,    33,    34,    35,    36,    39,    40,    42,
+      46,    47,    50,    62,    73,    77,    81,    82,    83,    84,
+      87,    49,    61,    73,    75,    78,    59,    75,    60,    73,
+      10,    40,    41,    46,    66,    74,    76,    77,    78,    82,
+      83,    87,    64,    84,    46,    58,    62,    67,    40,    46,
+      47,    63,    76,    78,    87,    65,    81,    68,    75,    69,
+      75,    70,    75,    71,    81,    72,    77,    43,    45,    43,
+      45,    44,    87,    87,     6,     8,     9,    85,    73,    33,
+      39,    87,    88,    87,    47,    47,     9,    37,    38,    47,
+      84,    87,    46,    46,    46,    77,    82,    84,    85,    85,
+      10,    74,    47,    11,    85,    76,    46,    47,    46,    46,
+      46,    46,    46,    46,    56,    88,    55,    88,     7,    87,
+      87,    47,    10,    48,    48,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    48,    33,    33,    34,    39,
+      37,     9,    37,    73,    75,    30,    87,    76,    49,    79,
+      87,    73,    73,    73,    78,    87,    73,    54,    54,    85,
+      29,    31,    39,    86,    87,    47,    88,    88,    88,     6,
+       7,    88,    88,    88,    88,    88,    10,    10,    48,    48,
+      48,    37,    48,    48,    46,     9,    28,    80,    46,    43,
+      43,    46,    46,    47,    48,    48,    33,    88,    88,    87,
+      87,    47,    48,    78,    28,     9,    79,    33,    34,    78,
+      87,    31,    10,    48,    48,    33,     9,    28,    48,    87,
+      10,    28,    48,    87,    48
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -857,78 +905,50 @@ 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.  */
+   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.  */
 
 #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 && yylen == 1)				\
-    {								\
-      yychar = (Token);						\
-      yylval = (Value);						\
-      yytoken = YYTRANSLATE (yychar);				\
-      YYPOPSTACK (1);						\
-      goto yybackup;						\
-    }								\
-  else								\
-    {								\
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
       yyerror (YY_("syntax error: cannot back up")); \
       YYERROR;							\
     }								\
 while (YYID (0))
 
-
+/* Error token number */
 #define YYTERROR	1
 #define YYERRCODE	256
 
 
-/* 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.  */
-
+/* This macro is provided for backward compatibility. */
 #ifndef YY_LOCATION_PRINT
-# if 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
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
 #endif
 
 
 /* YYLEX -- calling `yylex' with the right arguments.  */
-
 #ifdef YYLEX_PARAM
 # define YYLEX yylex (YYLEX_PARAM)
 #else
@@ -978,6 +998,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
     YYSTYPE const * const yyvaluep;
 #endif
 {
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
   if (!yyvaluep)
     return;
 # ifdef YYPRINT
@@ -1115,7 +1137,6 @@ int yydebug;
 # define YYMAXDEPTH 10000
 #endif
 
-
 
 #if YYERROR_VERBOSE
 
@@ -1218,115 +1239,142 @@ yytnamerr (char *yyres, const char *yystr)
 }
 # endif
 
-/* 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)
-{
-  int yyn = yypact[yystate];
+/* 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.
 
-  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;
-	  }
+   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)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  YYSIZE_T yysize1;
+  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];
+                yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+                if (! (yysize <= yysize1
+                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                  return 2;
+                yysize = yysize1;
+              }
+        }
+    }
 
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
+  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 (yysize_overflow)
-	return YYSIZE_MAXIMUM;
+  yysize1 = yysize + yystrlen (yyformat);
+  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+    return 2;
+  yysize = yysize1;
 
-      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;
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
     }
+
+  /* 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;
 }
 #endif /* YYERROR_VERBOSE */
-
 
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
@@ -1359,36 +1407,31 @@ yydestruct (yymsg, yytype, yyvaluep)
     }
 }
 
-/* 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 semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
+YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
 
 /* Number of syntax errors so far.  */
 int yynerrs;
 
 
-
-/*-------------------------.
-| yyparse or yypush_parse.  |
-`-------------------------*/
+/*----------.
+| yyparse.  |
+`----------*/
 
 #ifdef YYPARSE_PARAM
 #if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1412,8 +1455,6 @@ yyparse ()
 #endif
 #endif
 {
-
-
     int yystate;
     /* Number of tokens to shift before error messages enabled.  */
     int yyerrstatus;
@@ -1422,7 +1463,7 @@ yyparse ()
        `yyss': related to states.
        `yyvs': related to semantic values.
 
-       Refer to the stacks thru separate pointers, to allow yyoverflow
+       Refer to the stacks through separate pointers, to allow yyoverflow
        to reallocate them elsewhere.  */
 
     /* The state stack.  */
@@ -1440,7 +1481,7 @@ yyparse ()
   int yyn;
   int yyresult;
   /* Lookahead token as an internal (translated) token number.  */
-  int yytoken;
+  int yytoken = 0;
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
@@ -1458,9 +1499,8 @@ yyparse ()
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
-  yytoken = 0;
-  yyss = yyssa;
-  yyvs = yyvsa;
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
   yystacksize = YYINITDEPTH;
 
   YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1469,14 +1509,6 @@ yyparse ()
   yyerrstatus = 0;
   yynerrs = 0;
   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;
 
 /*------------------------------------------------------------.
@@ -1568,7 +1600,7 @@ yybackup:
 
   /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
+  if (yypact_value_is_default (yyn))
     goto yydefault;
 
   /* Not known => get a lookahead token if don't already have one.  */
@@ -1599,8 +1631,8 @@ yybackup:
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-	goto yyerrlab;
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
       yyn = -yyn;
       goto yyreduce;
     }
@@ -1617,7 +1649,9 @@ yybackup:
   yychar = YYEMPTY;
 
   yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
   goto yynewstate;
 
@@ -1654,8 +1688,7 @@ yyreduce:
   switch (yyn)
     {
         case 3:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 70 "a.y"
     {
 		stmtline = lineno;
@@ -1663,8 +1696,7 @@ yyreduce:
     break;
 
   case 5:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 77 "a.y"
     {
 		if((yyvsp[(1) - (2)].sym)->value != pc)
@@ -1674,8 +1706,7 @@ yyreduce:
     break;
 
   case 7:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 84 "a.y"
     {
 		(yyvsp[(1) - (2)].sym)->type = LLAB;
@@ -1684,8 +1715,7 @@ yyreduce:
     break;
 
   case 12:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 95 "a.y"
     {
 		(yyvsp[(1) - (3)].sym)->type = LVAR;
@@ -1694,8 +1724,7 @@ yyreduce:
     break;
 
   case 13:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 100 "a.y"
     {
 		if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval))
@@ -1705,207 +1734,197 @@ yyreduce:
     break;
 
   case 14:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 105 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 15:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 106 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 16:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 107 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 17:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 108 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 18:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 109 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 19:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 110 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 20:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 111 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 21:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 112 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 22:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 113 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 23:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 114 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 24:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 115 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 25:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 116 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 26:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 117 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 27:
-
-/* Line 1455 of yacc.c  */
+/* Line 1778 of yacc.c  */
 #line 118 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
     break;
 
   case 28:
+/* Line 1778 of yacc.c  */
+#line 119 "a.y"
+    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
+    break;
 
-/* Line 1455 of yacc.c  */
-#line 121 "a.y"
+  case 29:
+/* Line 1778 of yacc.c  */
+#line 122 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = nullgen;
 	}
     break;
 
-  case 29:
-
-/* Line 1455 of yacc.c  */
-#line 126 "a.y"
+  case 30:
+/* Line 1778 of yacc.c  */
+#line 127 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = nullgen;
 	}
     break;
 
-  case 30:
-
-/* Line 1455 of yacc.c  */
-#line 133 "a.y"
+  case 31:
+/* Line 1778 of yacc.c  */
+#line 134 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 31:
-
-/* Line 1455 of yacc.c  */
-#line 140 "a.y"
+  case 32:
+/* Line 1778 of yacc.c  */
+#line 141 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 32:
-
-/* Line 1455 of yacc.c  */
-#line 147 "a.y"
+  case 33:
+/* Line 1778 of yacc.c  */
+#line 148 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (2)].gen);
 		(yyval.gen2).to = nullgen;
 	}
     break;
 
-  case 33:
-
-/* Line 1455 of yacc.c  */
-#line 152 "a.y"
+  case 34:
+/* Line 1778 of yacc.c  */
+#line 153 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (1)].gen);
 		(yyval.gen2).to = nullgen;
 	}
     break;
 
-  case 34:
-
-/* Line 1455 of yacc.c  */
-#line 159 "a.y"
+  case 35:
+/* Line 1778 of yacc.c  */
+#line 160 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
 	}
     break;
 
-  case 35:
-
-/* Line 1455 of yacc.c  */
-#line 164 "a.y"
+  case 36:
+/* Line 1778 of yacc.c  */
+#line 165 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = (yyvsp[(1) - (1)].gen);
 	}
     break;
 
-  case 36:
-
-/* Line 1455 of yacc.c  */
-#line 171 "a.y"
+  case 37:
+/* Line 1778 of yacc.c  */
+#line 172 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
 	}
     break;
 
-  case 37:
-
-/* Line 1455 of yacc.c  */
-#line 176 "a.y"
+  case 38:
+/* Line 1778 of yacc.c  */
+#line 177 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = (yyvsp[(1) - (1)].gen);
 	}
     break;
 
-  case 38:
+  case 39:
+/* Line 1778 of yacc.c  */
+#line 182 "a.y"
+    {
+		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
+		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
+	}
+    break;
 
-/* Line 1455 of yacc.c  */
-#line 183 "a.y"
+  case 40:
+/* Line 1778 of yacc.c  */
+#line 189 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -1913,20 +1932,18 @@ yyreduce:
 	}
     break;
 
-  case 39:
-
-/* Line 1455 of yacc.c  */
-#line 191 "a.y"
+  case 41:
+/* Line 1778 of yacc.c  */
+#line 197 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 40:
-
-/* Line 1455 of yacc.c  */
-#line 196 "a.y"
+  case 42:
+/* Line 1778 of yacc.c  */
+#line 202 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -1934,30 +1951,27 @@ yyreduce:
 	}
     break;
 
-  case 41:
-
-/* Line 1455 of yacc.c  */
-#line 204 "a.y"
+  case 43:
+/* Line 1778 of yacc.c  */
+#line 210 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
 	}
     break;
 
-  case 42:
-
-/* Line 1455 of yacc.c  */
-#line 209 "a.y"
+  case 44:
+/* Line 1778 of yacc.c  */
+#line 215 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = (yyvsp[(1) - (1)].gen);
 	}
     break;
 
-  case 43:
-
-/* Line 1455 of yacc.c  */
-#line 214 "a.y"
+  case 45:
+/* Line 1778 of yacc.c  */
+#line 220 "a.y"
     {
 		(yyval.gen2).from = nullgen;
 		(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
@@ -1966,20 +1980,18 @@ yyreduce:
 	}
     break;
 
-  case 46:
-
-/* Line 1455 of yacc.c  */
-#line 227 "a.y"
+  case 48:
+/* Line 1778 of yacc.c  */
+#line 233 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 47:
-
-/* Line 1455 of yacc.c  */
-#line 232 "a.y"
+  case 49:
+/* Line 1778 of yacc.c  */
+#line 238 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -1989,20 +2001,18 @@ yyreduce:
 	}
     break;
 
-  case 48:
-
-/* Line 1455 of yacc.c  */
-#line 242 "a.y"
+  case 50:
+/* Line 1778 of yacc.c  */
+#line 248 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 49:
-
-/* Line 1455 of yacc.c  */
-#line 247 "a.y"
+  case 51:
+/* Line 1778 of yacc.c  */
+#line 253 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -2012,50 +2022,45 @@ yyreduce:
 	}
     break;
 
-  case 50:
-
-/* Line 1455 of yacc.c  */
-#line 257 "a.y"
+  case 52:
+/* Line 1778 of yacc.c  */
+#line 263 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (2)].gen);
 		(yyval.gen2).to = nullgen;
 	}
     break;
 
-  case 51:
-
-/* Line 1455 of yacc.c  */
-#line 262 "a.y"
+  case 53:
+/* Line 1778 of yacc.c  */
+#line 268 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (1)].gen);
 		(yyval.gen2).to = nullgen;
 	}
     break;
 
-  case 52:
-
-/* Line 1455 of yacc.c  */
-#line 267 "a.y"
+  case 54:
+/* Line 1778 of yacc.c  */
+#line 273 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 53:
-
-/* Line 1455 of yacc.c  */
-#line 274 "a.y"
+  case 55:
+/* Line 1778 of yacc.c  */
+#line 280 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
 		(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
 	}
     break;
 
-  case 54:
-
-/* Line 1455 of yacc.c  */
-#line 279 "a.y"
+  case 56:
+/* Line 1778 of yacc.c  */
+#line 285 "a.y"
     {
 		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
 		(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -2063,28 +2068,35 @@ yyreduce:
 	}
     break;
 
-  case 59:
-
-/* Line 1455 of yacc.c  */
+  case 57:
+/* Line 1778 of yacc.c  */
 #line 293 "a.y"
     {
-		(yyval.gen) = (yyvsp[(2) - (2)].gen);
+		(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
+		(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
+		(yyval.gen2).to.offset = (yyvsp[(5) - (5)].lval);
 	}
     break;
 
-  case 60:
-
-/* Line 1455 of yacc.c  */
-#line 297 "a.y"
+  case 62:
+/* Line 1778 of yacc.c  */
+#line 307 "a.y"
     {
 		(yyval.gen) = (yyvsp[(2) - (2)].gen);
 	}
     break;
 
-  case 66:
+  case 63:
+/* Line 1778 of yacc.c  */
+#line 311 "a.y"
+    {
+		(yyval.gen) = (yyvsp[(2) - (2)].gen);
+	}
+    break;
 
-/* Line 1455 of yacc.c  */
-#line 310 "a.y"
+  case 69:
+/* Line 1778 of yacc.c  */
+#line 324 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_BRANCH;
@@ -2092,10 +2104,9 @@ yyreduce:
 	}
     break;
 
-  case 67:
-
-/* Line 1455 of yacc.c  */
-#line 316 "a.y"
+  case 70:
+/* Line 1778 of yacc.c  */
+#line 330 "a.y"
     {
 		(yyval.gen) = nullgen;
 		if(pass == 2)
@@ -2106,10 +2117,9 @@ yyreduce:
 	}
     break;
 
-  case 68:
-
-/* Line 1455 of yacc.c  */
-#line 325 "a.y"
+  case 71:
+/* Line 1778 of yacc.c  */
+#line 339 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_BRANCH;
@@ -2118,60 +2128,63 @@ yyreduce:
 	}
     break;
 
-  case 69:
-
-/* Line 1455 of yacc.c  */
-#line 334 "a.y"
+  case 72:
+/* Line 1778 of yacc.c  */
+#line 348 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = (yyvsp[(1) - (1)].lval);
 	}
     break;
 
-  case 70:
-
-/* Line 1455 of yacc.c  */
-#line 339 "a.y"
+  case 73:
+/* Line 1778 of yacc.c  */
+#line 353 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = (yyvsp[(1) - (1)].lval);
 	}
     break;
 
-  case 71:
-
-/* Line 1455 of yacc.c  */
-#line 344 "a.y"
+  case 74:
+/* Line 1778 of yacc.c  */
+#line 358 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = (yyvsp[(1) - (1)].lval);
 	}
     break;
 
-  case 72:
+  case 75:
+/* Line 1778 of yacc.c  */
+#line 363 "a.y"
+    {
+		(yyval.gen) = nullgen;
+		(yyval.gen).type = (yyvsp[(1) - (1)].lval);
+	}
+    break;
 
-/* Line 1455 of yacc.c  */
-#line 349 "a.y"
+  case 76:
+/* Line 1778 of yacc.c  */
+#line 368 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_SP;
 	}
     break;
 
-  case 73:
-
-/* Line 1455 of yacc.c  */
-#line 354 "a.y"
+  case 77:
+/* Line 1778 of yacc.c  */
+#line 373 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = (yyvsp[(1) - (1)].lval);
 	}
     break;
 
-  case 74:
-
-/* Line 1455 of yacc.c  */
-#line 361 "a.y"
+  case 78:
+/* Line 1778 of yacc.c  */
+#line 380 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_CONST;
@@ -2179,10 +2192,9 @@ yyreduce:
 	}
     break;
 
-  case 75:
-
-/* Line 1455 of yacc.c  */
-#line 367 "a.y"
+  case 79:
+/* Line 1778 of yacc.c  */
+#line 386 "a.y"
     {
 		(yyval.gen) = (yyvsp[(2) - (2)].gen);
 		(yyval.gen).index = (yyvsp[(2) - (2)].gen).type;
@@ -2195,10 +2207,9 @@ yyreduce:
 	}
     break;
 
-  case 76:
-
-/* Line 1455 of yacc.c  */
-#line 378 "a.y"
+  case 80:
+/* Line 1778 of yacc.c  */
+#line 397 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_SCONST;
@@ -2206,10 +2217,9 @@ yyreduce:
 	}
     break;
 
-  case 77:
-
-/* Line 1455 of yacc.c  */
-#line 384 "a.y"
+  case 81:
+/* Line 1778 of yacc.c  */
+#line 403 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FCONST;
@@ -2217,10 +2227,9 @@ yyreduce:
 	}
     break;
 
-  case 78:
-
-/* Line 1455 of yacc.c  */
-#line 390 "a.y"
+  case 82:
+/* Line 1778 of yacc.c  */
+#line 409 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FCONST;
@@ -2228,10 +2237,9 @@ yyreduce:
 	}
     break;
 
-  case 79:
-
-/* Line 1455 of yacc.c  */
-#line 396 "a.y"
+  case 83:
+/* Line 1778 of yacc.c  */
+#line 415 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FCONST;
@@ -2239,10 +2247,9 @@ yyreduce:
 	}
     break;
 
-  case 80:
-
-/* Line 1455 of yacc.c  */
-#line 402 "a.y"
+  case 84:
+/* Line 1778 of yacc.c  */
+#line 421 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_FCONST;
@@ -2250,10 +2257,9 @@ yyreduce:
 	}
     break;
 
-  case 81:
-
-/* Line 1455 of yacc.c  */
-#line 410 "a.y"
+  case 85:
+/* Line 1778 of yacc.c  */
+#line 429 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_CONST2;
@@ -2262,50 +2268,45 @@ yyreduce:
 	}
     break;
 
-  case 82:
-
-/* Line 1455 of yacc.c  */
-#line 419 "a.y"
+  case 86:
+/* Line 1778 of yacc.c  */
+#line 438 "a.y"
     {
 		(yyval.con2).v1 = (yyvsp[(1) - (1)].lval);
 		(yyval.con2).v2 = 0;
 	}
     break;
 
-  case 83:
-
-/* Line 1455 of yacc.c  */
-#line 424 "a.y"
+  case 87:
+/* Line 1778 of yacc.c  */
+#line 443 "a.y"
     {
 		(yyval.con2).v1 = -(yyvsp[(2) - (2)].lval);
 		(yyval.con2).v2 = 0;
 	}
     break;
 
-  case 84:
-
-/* Line 1455 of yacc.c  */
-#line 429 "a.y"
+  case 88:
+/* Line 1778 of yacc.c  */
+#line 448 "a.y"
     {
 		(yyval.con2).v1 = (yyvsp[(1) - (3)].lval);
 		(yyval.con2).v2 = (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 85:
-
-/* Line 1455 of yacc.c  */
-#line 434 "a.y"
+  case 89:
+/* Line 1778 of yacc.c  */
+#line 453 "a.y"
     {
 		(yyval.con2).v1 = -(yyvsp[(2) - (4)].lval);
 		(yyval.con2).v2 = (yyvsp[(4) - (4)].lval);
 	}
     break;
 
-  case 88:
-
-/* Line 1455 of yacc.c  */
-#line 445 "a.y"
+  case 92:
+/* Line 1778 of yacc.c  */
+#line 464 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_NONE;
@@ -2313,10 +2314,9 @@ yyreduce:
 	}
     break;
 
-  case 89:
-
-/* Line 1455 of yacc.c  */
-#line 451 "a.y"
+  case 93:
+/* Line 1778 of yacc.c  */
+#line 470 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2324,10 +2324,9 @@ yyreduce:
 	}
     break;
 
-  case 90:
-
-/* Line 1455 of yacc.c  */
-#line 457 "a.y"
+  case 94:
+/* Line 1778 of yacc.c  */
+#line 476 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_SP;
@@ -2335,10 +2334,9 @@ yyreduce:
 	}
     break;
 
-  case 91:
-
-/* Line 1455 of yacc.c  */
-#line 463 "a.y"
+  case 95:
+/* Line 1778 of yacc.c  */
+#line 482 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_NONE;
@@ -2349,10 +2347,9 @@ yyreduce:
 	}
     break;
 
-  case 92:
-
-/* Line 1455 of yacc.c  */
-#line 472 "a.y"
+  case 96:
+/* Line 1778 of yacc.c  */
+#line 491 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(3) - (9)].lval);
@@ -2363,30 +2360,27 @@ yyreduce:
 	}
     break;
 
-  case 93:
-
-/* Line 1455 of yacc.c  */
-#line 481 "a.y"
+  case 97:
+/* Line 1778 of yacc.c  */
+#line 500 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(2) - (3)].lval);
 	}
     break;
 
-  case 94:
-
-/* Line 1455 of yacc.c  */
-#line 486 "a.y"
+  case 98:
+/* Line 1778 of yacc.c  */
+#line 505 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_SP;
 	}
     break;
 
-  case 95:
-
-/* Line 1455 of yacc.c  */
-#line 491 "a.y"
+  case 99:
+/* Line 1778 of yacc.c  */
+#line 510 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2394,10 +2388,9 @@ yyreduce:
 	}
     break;
 
-  case 96:
-
-/* Line 1455 of yacc.c  */
-#line 497 "a.y"
+  case 100:
+/* Line 1778 of yacc.c  */
+#line 516 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+D_NONE;
@@ -2407,10 +2400,9 @@ yyreduce:
 	}
     break;
 
-  case 97:
-
-/* Line 1455 of yacc.c  */
-#line 505 "a.y"
+  case 101:
+/* Line 1778 of yacc.c  */
+#line 524 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_INDIR+(yyvsp[(2) - (8)].lval);
@@ -2420,19 +2412,17 @@ yyreduce:
 	}
     break;
 
-  case 98:
-
-/* Line 1455 of yacc.c  */
-#line 515 "a.y"
+  case 102:
+/* Line 1778 of yacc.c  */
+#line 534 "a.y"
     {
 		(yyval.gen) = (yyvsp[(1) - (1)].gen);
 	}
     break;
 
-  case 99:
-
-/* Line 1455 of yacc.c  */
-#line 519 "a.y"
+  case 103:
+/* Line 1778 of yacc.c  */
+#line 538 "a.y"
     {
 		(yyval.gen) = (yyvsp[(1) - (6)].gen);
 		(yyval.gen).index = (yyvsp[(3) - (6)].lval);
@@ -2441,10 +2431,9 @@ yyreduce:
 	}
     break;
 
-  case 100:
-
-/* Line 1455 of yacc.c  */
-#line 528 "a.y"
+  case 104:
+/* Line 1778 of yacc.c  */
+#line 547 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = (yyvsp[(4) - (5)].lval);
@@ -2453,10 +2442,9 @@ yyreduce:
 	}
     break;
 
-  case 101:
-
-/* Line 1455 of yacc.c  */
-#line 535 "a.y"
+  case 105:
+/* Line 1778 of yacc.c  */
+#line 554 "a.y"
     {
 		(yyval.gen) = nullgen;
 		(yyval.gen).type = D_STATIC;
@@ -2465,183 +2453,174 @@ yyreduce:
 	}
     break;
 
-  case 102:
-
-/* Line 1455 of yacc.c  */
-#line 543 "a.y"
+  case 106:
+/* Line 1778 of yacc.c  */
+#line 562 "a.y"
     {
 		(yyval.lval) = 0;
 	}
     break;
 
-  case 103:
-
-/* Line 1455 of yacc.c  */
-#line 547 "a.y"
+  case 107:
+/* Line 1778 of yacc.c  */
+#line 566 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 104:
-
-/* Line 1455 of yacc.c  */
-#line 551 "a.y"
+  case 108:
+/* Line 1778 of yacc.c  */
+#line 570 "a.y"
     {
 		(yyval.lval) = -(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 106:
-
-/* Line 1455 of yacc.c  */
-#line 558 "a.y"
+  case 110:
+/* Line 1778 of yacc.c  */
+#line 577 "a.y"
     {
 		(yyval.lval) = D_AUTO;
 	}
     break;
 
-  case 109:
-
-/* Line 1455 of yacc.c  */
-#line 566 "a.y"
+  case 113:
+/* Line 1778 of yacc.c  */
+#line 585 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
 	}
     break;
 
-  case 110:
-
-/* Line 1455 of yacc.c  */
-#line 570 "a.y"
+  case 114:
+/* Line 1778 of yacc.c  */
+#line 589 "a.y"
     {
 		(yyval.lval) = -(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 111:
-
-/* Line 1455 of yacc.c  */
-#line 574 "a.y"
+  case 115:
+/* Line 1778 of yacc.c  */
+#line 593 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 112:
-
-/* Line 1455 of yacc.c  */
-#line 578 "a.y"
+  case 116:
+/* Line 1778 of yacc.c  */
+#line 597 "a.y"
     {
 		(yyval.lval) = ~(yyvsp[(2) - (2)].lval);
 	}
     break;
 
-  case 113:
-
-/* Line 1455 of yacc.c  */
-#line 582 "a.y"
+  case 117:
+/* Line 1778 of yacc.c  */
+#line 601 "a.y"
     {
 		(yyval.lval) = (yyvsp[(2) - (3)].lval);
 	}
     break;
 
-  case 115:
-
-/* Line 1455 of yacc.c  */
-#line 589 "a.y"
+  case 119:
+/* Line 1778 of yacc.c  */
+#line 608 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 116:
-
-/* Line 1455 of yacc.c  */
-#line 593 "a.y"
+  case 120:
+/* Line 1778 of yacc.c  */
+#line 612 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 117:
-
-/* Line 1455 of yacc.c  */
-#line 597 "a.y"
+  case 121:
+/* Line 1778 of yacc.c  */
+#line 616 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 118:
-
-/* Line 1455 of yacc.c  */
-#line 601 "a.y"
+  case 122:
+/* Line 1778 of yacc.c  */
+#line 620 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 119:
-
-/* Line 1455 of yacc.c  */
-#line 605 "a.y"
+  case 123:
+/* Line 1778 of yacc.c  */
+#line 624 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 120:
-
-/* Line 1455 of yacc.c  */
-#line 609 "a.y"
+  case 124:
+/* Line 1778 of yacc.c  */
+#line 628 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
 	}
     break;
 
-  case 121:
-
-/* Line 1455 of yacc.c  */
-#line 613 "a.y"
+  case 125:
+/* Line 1778 of yacc.c  */
+#line 632 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
 	}
     break;
 
-  case 122:
-
-/* Line 1455 of yacc.c  */
-#line 617 "a.y"
+  case 126:
+/* Line 1778 of yacc.c  */
+#line 636 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 123:
-
-/* Line 1455 of yacc.c  */
-#line 621 "a.y"
+  case 127:
+/* Line 1778 of yacc.c  */
+#line 640 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
 	}
     break;
 
-  case 124:
-
-/* Line 1455 of yacc.c  */
-#line 625 "a.y"
+  case 128:
+/* Line 1778 of yacc.c  */
+#line 644 "a.y"
     {
 		(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
 	}
     break;
 
 
-
-/* Line 1455 of yacc.c  */
-#line 2643 "y.tab.c"
+/* Line 1778 of yacc.c  */
+#line 2611 "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);
@@ -2669,6 +2648,10 @@ 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)
     {
@@ -2676,37 +2659,36 @@ yyerrlab:
 #if ! YYERROR_VERBOSE
       yyerror (YY_("syntax error"));
 #else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
       {
-	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;
-	  }
+        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;
       }
+# undef YYSYNTAX_ERROR
 #endif
     }
 
@@ -2765,7 +2747,7 @@ yyerrlab1:
   for (;;)
     {
       yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
+      if (!yypact_value_is_default (yyn))
 	{
 	  yyn += YYTERROR;
 	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
@@ -2788,7 +2770,9 @@ yyerrlab1:
       YY_STACK_PRINT (yyss, yyssp);
     }
 
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
 
   /* Shift the error token.  */
@@ -2812,7 +2796,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#if !defined(yyoverflow) || YYERROR_VERBOSE
+#if !defined yyoverflow || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -2824,8 +2808,13 @@ yyexhaustedlab:
 
 yyreturn:
   if (yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-		 yytoken, &yylval);
+    {
+      /* 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);
+    }
   /* Do not reclaim the symbols of the rule which action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
@@ -2849,4 +2838,3 @@ yyreturn:
 }
 
 
-
diff --git a/src/cmd/8a/y.tab.h b/src/cmd/8a/y.tab.h
index 69a966a..621aba7 100644
--- a/src/cmd/8a/y.tab.h
+++ b/src/cmd/8a/y.tab.h
@@ -1,10 +1,8 @@
+/* A Bison parser, made by GNU Bison 2.6.5.  */
 
-/* A Bison parser, made by GNU Bison 2.4.1.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* Bison interface for Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989-1990, 2000-2012 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
@@ -32,6 +30,15 @@
    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
@@ -53,20 +60,22 @@
      LTYPEM = 269,
      LTYPEI = 270,
      LTYPEG = 271,
-     LCONST = 272,
-     LFP = 273,
-     LPC = 274,
-     LSB = 275,
-     LBREG = 276,
-     LLREG = 277,
-     LSREG = 278,
-     LFREG = 279,
-     LFCONST = 280,
-     LSCONST = 281,
-     LSP = 282,
-     LNAME = 283,
-     LLAB = 284,
-     LVAR = 285
+     LTYPEXC = 272,
+     LCONST = 273,
+     LFP = 274,
+     LPC = 275,
+     LSB = 276,
+     LBREG = 277,
+     LLREG = 278,
+     LSREG = 279,
+     LFREG = 280,
+     LXREG = 281,
+     LFCONST = 282,
+     LSCONST = 283,
+     LSP = 284,
+     LNAME = 285,
+     LLAB = 286,
+     LVAR = 287
    };
 #endif
 /* Tokens.  */
@@ -84,29 +93,29 @@
 #define LTYPEM 269
 #define LTYPEI 270
 #define LTYPEG 271
-#define LCONST 272
-#define LFP 273
-#define LPC 274
-#define LSB 275
-#define LBREG 276
-#define LLREG 277
-#define LSREG 278
-#define LFREG 279
-#define LFCONST 280
-#define LSCONST 281
-#define LSP 282
-#define LNAME 283
-#define LLAB 284
-#define LVAR 285
-
+#define LTYPEXC 272
+#define LCONST 273
+#define LFP 274
+#define LPC 275
+#define LSB 276
+#define LBREG 277
+#define LLREG 278
+#define LSREG 279
+#define LFREG 280
+#define LXREG 281
+#define LFCONST 282
+#define LSCONST 283
+#define LSP 284
+#define LNAME 285
+#define LLAB 286
+#define LVAR 287
 
 
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 {
-
-/* Line 1676 of yacc.c  */
+/* Line 2042 of yacc.c  */
 #line 37 "a.y"
 
 	Sym	*sym;
@@ -121,9 +130,8 @@ typedef union YYSTYPE
 	Gen2	gen2;
 
 
-
-/* Line 1676 of yacc.c  */
-#line 127 "y.tab.h"
+/* Line 2042 of yacc.c  */
+#line 135 "y.tab.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -132,4 +140,18 @@ typedef union YYSTYPE
 
 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/8c/cgen.c b/src/cmd/8c/cgen.c
index 869d31a..78eb7ec 100644
--- a/src/cmd/8c/cgen.c
+++ b/src/cmd/8c/cgen.c
@@ -277,6 +277,18 @@ cgen(Node *n, Node *nn)
 				break;
 			}
 		}
+		if(n->op == OOR && l->op == OASHL && r->op == OLSHR
+		&& l->right->op == OCONST && r->right->op == OCONST
+		&& l->left->op == ONAME && r->left->op == ONAME
+		&& l->left->sym == r->left->sym
+		&& l->right->vconst + r->right->vconst == 8 * l->left->type->width) {
+			regalloc(&nod, l->left, nn);
+			cgen(l->left, &nod);
+			gopcode(OROTL, n->type, l->right, &nod);
+			gmove(&nod, nn);
+			regfree(&nod);
+			break;
+		}
 		if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
 		&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
 			c = l->right->vconst;
@@ -1703,6 +1715,7 @@ copy:
 		}
 	}
 
+	v = w == 8;
 	if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
 		t = nn->type;
 		nn->type = types[TLONG];
@@ -1728,8 +1741,28 @@ copy:
 	}
 
 	x = 0;
-	v = w == 8;
 	if(v) {
+		if(nn != nil && nn->complex >= FNX) {
+			t = nn->type;
+			nn->type = types[TLONG];
+			regialloc(&nod2, nn, Z);
+			lcgen(nn, &nod2);
+			nn->type = t;
+			
+			nod2.type = typ(TIND, t);
+	
+			nod1 = nod2;
+			nod1.op = OIND;
+			nod1.left = &nod2;
+			nod1.right = Z;
+			nod1.complex = 1;
+			nod1.type = t;
+	
+			sugen(n, &nod1, w);
+			regfree(&nod2);
+			return;
+		}
+			
 		c = cursafe;
 		if(n->left != Z && n->left->complex >= FNX
 		&& n->right != Z && n->right->complex >= FNX) {
diff --git a/src/cmd/8c/doc.go b/src/cmd/8c/doc.go
index e3aae85..0d07db1 100644
--- a/src/cmd/8c/doc.go
+++ b/src/cmd/8c/doc.go
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build ignore
+
 /*
 
 8c is a version of the Plan 9 C compiler.  The original is documented at
 
-	http://plan9.bell-labs.com/magic/man2html/1/2c
+	http://plan9.bell-labs.com/magic/man2html/1/8c
 
 Its target architecture is the x86, referred to by these tools for historical reasons as 386.
 
 */
-package documentation
+package main
diff --git a/src/cmd/8c/gc.h b/src/cmd/8c/gc.h
index 4a57f5d..bdf981b 100644
--- a/src/cmd/8c/gc.h
+++ b/src/cmd/8c/gc.h
@@ -297,6 +297,7 @@ void	gbranch(int);
 void	patch(Prog*, int32);
 int	sconst(Node*);
 void	gpseudo(int, Sym*, Node*);
+void	gprefetch(Node*);
 
 /*
  * swt.c
diff --git a/src/cmd/8c/list.c b/src/cmd/8c/list.c
index c422905..8506e08 100644
--- a/src/cmd/8c/list.c
+++ b/src/cmd/8c/list.c
@@ -93,7 +93,7 @@ Pconv(Fmt *fp)
 		break;
 
 	default:
-		sprint(str, "(%L)	%A	%D,%lD",
+		sprint(str, "(%L)	%A	%D,%D",
 			p->lineno, p->as, &p->from, &p->to);
 		break;
 	}
@@ -118,6 +118,17 @@ Dconv(Fmt *fp)
 
 	a = va_arg(fp->args, Adr*);
 	i = a->type;
+
+	if(fp->flags & FmtLong) {
+		if(i == D_CONST2)
+			sprint(str, "$%d-%d", a->offset, a->offset2);
+		else {
+			// ATEXT dst is not constant
+			sprint(str, "!!%D", a);
+		}
+		goto brk;
+	}
+
 	if(i >= D_INDIR) {
 		if(a->offset)
 			sprint(str, "%d(%R)", a->offset, i-D_INDIR);
@@ -126,7 +137,6 @@ Dconv(Fmt *fp)
 		goto brk;
 	}
 	switch(i) {
-
 	default:
 		if(a->offset)
 			sprint(str, "$%d,%R", a->offset, i);
@@ -139,7 +149,7 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_BRANCH:
-		sprint(str, "%d(PC)", a->offset-pc);
+		sprint(str, "%d", a->offset);
 		break;
 
 	case D_EXTERN:
@@ -147,12 +157,14 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_STATIC:
-		sprint(str, "%s<>+%d(SB)", a->sym->name,
-			a->offset);
+		sprint(str, "%s<>+%d(SB)", a->sym->name, a->offset);
 		break;
 
 	case D_AUTO:
-		sprint(str, "%s+%d(SP)", a->sym->name, a->offset);
+		if(a->sym)
+			sprint(str, "%s+%d(SP)", a->sym->name, a->offset);
+		else
+			sprint(str, "%d(SP)", a->offset);
 		break;
 
 	case D_PARAM:
@@ -167,7 +179,10 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_CONST2:
-		sprint(str, "$%d-%d", a->offset, a->offset2);
+		if(!(fp->flags & FmtLong)) {
+			// D_CONST2 outside of ATEXT should not happen
+			sprint(str, "!!$%d-%d", a->offset, a->offset2);
+		}
 		break;
 
 	case D_FCONST:
@@ -197,7 +212,7 @@ conv:
 
 char*	regstr[] =
 {
-	"AL",	/*[D_AL]*/
+	"AL",	/* [D_AL] */
 	"CL",
 	"DL",
 	"BL",
@@ -206,7 +221,7 @@ char*	regstr[] =
 	"DH",
 	"BH",
 
-	"AX",	/*[D_AX]*/
+	"AX",	/* [D_AX] */
 	"CX",
 	"DX",
 	"BX",
@@ -215,7 +230,7 @@ char*	regstr[] =
 	"SI",
 	"DI",
 
-	"F0",	/*[D_F0]*/
+	"F0",	/* [D_F0] */
 	"F1",
 	"F2",
 	"F3",
@@ -224,20 +239,20 @@ char*	regstr[] =
 	"F6",
 	"F7",
 
-	"CS",	/*[D_CS]*/
+	"CS",	/* [D_CS] */
 	"SS",
 	"DS",
 	"ES",
 	"FS",
 	"GS",
 
-	"GDTR",	/*[D_GDTR]*/
-	"IDTR",	/*[D_IDTR]*/
-	"LDTR",	/*[D_LDTR]*/
-	"MSW",	/*[D_MSW] */
-	"TASK",	/*[D_TASK]*/
+	"GDTR",	/* [D_GDTR] */
+	"IDTR",	/* [D_IDTR] */
+	"LDTR",	/* [D_LDTR] */
+	"MSW",	/* [D_MSW] */
+	"TASK",	/* [D_TASK] */
 
-	"CR0",	/*[D_CR]*/
+	"CR0",	/* [D_CR] */
 	"CR1",
 	"CR2",
 	"CR3",
@@ -246,7 +261,7 @@ char*	regstr[] =
 	"CR6",
 	"CR7",
 
-	"DR0",	/*[D_DR]*/
+	"DR0",	/* [D_DR] */
 	"DR1",
 	"DR2",
 	"DR3",
@@ -255,7 +270,7 @@ char*	regstr[] =
 	"DR6",
 	"DR7",
 
-	"TR0",	/*[D_TR]*/
+	"TR0",	/* [D_TR] */
 	"TR1",
 	"TR2",
 	"TR3",
@@ -264,7 +279,16 @@ char*	regstr[] =
 	"TR6",
 	"TR7",
 
-	"NONE",	/*[D_NONE]*/
+	"X0",	/* [D_X0] */
+	"X1",
+	"X2",
+	"X3",
+	"X4",
+	"X5",
+	"X6",
+	"X7",
+
+	"NONE",	/* [D_NONE] */
 };
 
 int
diff --git a/src/cmd/8c/mul.c b/src/cmd/8c/mul.c
index a074280..9955e76 100644
--- a/src/cmd/8c/mul.c
+++ b/src/cmd/8c/mul.c
@@ -35,17 +35,17 @@ typedef struct	Mparam	Mparam;
 
 struct	Malg
 {
-	char	vals[10];
+	schar	vals[10];
 };
 
 struct	Mparam
 {
 	uint32	value;
-	char	alg;
+	schar	alg;
 	char	neg;
 	char	shift;
 	char	arg;
-	char	off;
+	schar	off;
 };
 
 static	Mparam	multab[32];
@@ -101,7 +101,7 @@ mulparam(uint32 m, Mparam *mp)
 {
 	int c, i, j, n, o, q, s;
 	int bc, bi, bn, bo, bq, bs, bt;
-	char *p;
+	schar *p;
 	int32 u;
 	uint32 t;
 
diff --git a/src/cmd/8c/peep.c b/src/cmd/8c/peep.c
index 9511a55..9c3e9a5 100644
--- a/src/cmd/8c/peep.c
+++ b/src/cmd/8c/peep.c
@@ -602,6 +602,12 @@ copyu(Prog *p, Adr *v, Adr *s)
 	case ACMPL:	/* read only */
 	case ACMPW:
 	case ACMPB:
+	
+	case APREFETCHT0:
+	case APREFETCHT1:
+	case APREFETCHT2:
+	case APREFETCHNTA:
+
 
 	case AFCOMB:
 	case AFCOMBP:
diff --git a/src/cmd/8c/reg.c b/src/cmd/8c/reg.c
index 6ba07be..6c87d70 100644
--- a/src/cmd/8c/reg.c
+++ b/src/cmd/8c/reg.c
@@ -30,6 +30,8 @@
 
 #include "gc.h"
 
+static	void	fixjmp(Reg*);
+
 Reg*
 rega(void)
 {
@@ -148,7 +150,6 @@ regopt(Prog *p)
 			r->p1 = R;
 			r1->s1 = R;
 		}
-
 		bit = mkvar(r, &p->from);
 		if(bany(&bit))
 		switch(p->as) {
@@ -182,6 +183,10 @@ regopt(Prog *p)
 		case ACMPB:
 		case ACMPL:
 		case ACMPW:
+		case APREFETCHT0:
+		case APREFETCHT1:
+		case APREFETCHT2:
+		case APREFETCHNTA:
 			for(z=0; z<BITS; z++)
 				r->use2.b[z] |= bit.b[z];
 			break;
@@ -372,6 +377,12 @@ regopt(Prog *p)
 	}
 
 	/*
+	 * pass 2.1
+	 * fix jumps
+	 */
+	fixjmp(firstr);
+
+	/*
 	 * pass 2.5
 	 * find looping structure
 	 */
@@ -543,6 +554,13 @@ brk:
 	if(!debug['R'] || debug['P'])
 		peep();
 
+	if(debug['R'] && debug['v']) {
+		print("after pass 7 (peep)\n");
+		for(r=firstr; r; r=r->link)
+			print("%04d %P\n", r->pc, r->prog);
+		print("\n");
+	}
+
 	/*
 	 * pass 8
 	 * recalculate pc
@@ -596,6 +614,14 @@ brk:
 		while(p->link && p->link->as == ANOP)
 			p->link = p->link->link;
 	}
+
+	if(debug['R'] && debug['v']) {
+		print("after pass 8 (fixup pc)\n");
+		for(p1=firstr->prog; p1!=P; p1=p1->link)
+			print("%P\n", p1);
+		print("\n");
+	}
+
 	if(r1 != R) {
 		r1->link = freer;
 		freer = firstr;
@@ -1285,3 +1311,126 @@ BtoR(int32 b)
 		return 0;
 	return bitno(b) + D_AX;
 }
+
+/* what instruction does a JMP to p eventually land on? */
+static Reg*
+chasejmp(Reg *r, int *jmploop)
+{
+	int n;
+
+	n = 0;
+	for(; r; r=r->s2) {
+		if(r->prog->as != AJMP || r->prog->to.type != D_BRANCH)
+			break;
+		if(++n > 10) {
+			*jmploop = 1;
+			break;
+		}
+	}
+	return r;
+}
+
+/* mark all code reachable from firstp as alive */
+static void
+mark(Reg *firstr)
+{
+	Reg *r;
+	Prog *p;
+
+	for(r=firstr; r; r=r->link) {
+		if(r->active)
+			break;
+		r->active = 1;
+		p = r->prog;
+		if(p->as != ACALL && p->to.type == D_BRANCH)
+			mark(r->s2);
+		if(p->as == AJMP || p->as == ARET || p->as == AUNDEF)
+			break;
+	}
+}
+
+/*
+ * the code generator depends on being able to write out JMP
+ * instructions that it can jump to now but fill in later.
+ * the linker will resolve them nicely, but they make the code
+ * longer and more difficult to follow during debugging.
+ * remove them.
+ */
+static void
+fixjmp(Reg *firstr)
+{
+	int jmploop;
+	Reg *r;
+	Prog *p;
+
+	if(debug['R'] && debug['v'])
+		print("\nfixjmp\n");
+
+	// pass 1: resolve jump to AJMP, mark all code as dead.
+	jmploop = 0;
+	for(r=firstr; r; r=r->link) {
+		p = r->prog;
+		if(debug['R'] && debug['v'])
+			print("%04d %P\n", r->pc, p);
+		if(p->as != ACALL && p->to.type == D_BRANCH && r->s2 && r->s2->prog->as == AJMP) {
+			r->s2 = chasejmp(r->s2, &jmploop);
+			p->to.offset = r->s2->pc;
+			if(debug['R'] && debug['v'])
+				print("->%P\n", p);
+		}
+		r->active = 0;
+	}
+	if(debug['R'] && debug['v'])
+		print("\n");
+
+	// pass 2: mark all reachable code alive
+	mark(firstr);
+
+	// pass 3: delete dead code (mostly JMPs).
+	for(r=firstr; r; r=r->link) {
+		if(!r->active) {
+			p = r->prog;
+			if(p->link == P && p->as == ARET && r->p1 && r->p1->prog->as != ARET) {
+				// This is the final ARET, and the code so far doesn't have one.
+				// Let it stay.
+			} else {
+				if(debug['R'] && debug['v'])
+					print("del %04d %P\n", r->pc, p);
+				p->as = ANOP;
+			}
+		}
+	}
+
+	// pass 4: elide JMP to next instruction.
+	// only safe if there are no jumps to JMPs anymore.
+	if(!jmploop) {
+		for(r=firstr; r; r=r->link) {
+			p = r->prog;
+			if(p->as == AJMP && p->to.type == D_BRANCH && r->s2 == r->link) {
+				if(debug['R'] && debug['v'])
+					print("del %04d %P\n", r->pc, p);
+				p->as = ANOP;
+			}
+		}
+	}
+
+	// fix back pointers.
+	for(r=firstr; r; r=r->link) {
+		r->p2 = R;
+		r->p2link = R;
+	}
+	for(r=firstr; r; r=r->link) {
+		if(r->s2) {
+			r->p2link = r->s2->p2;
+			r->s2->p2 = r;
+		}
+	}
+
+	if(debug['R'] && debug['v']) {
+		print("\n");
+		for(r=firstr; r; r=r->link)
+			print("%04d %P\n", r->pc, r->prog);
+		print("\n");
+	}
+}
+
diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c
index f1ca4c2..d331eee 100644
--- a/src/cmd/8c/swt.c
+++ b/src/cmd/8c/swt.c
@@ -251,18 +251,12 @@ outcode(void)
 	Binit(&b, f, OWRITE);
 
 	Bprint(&b, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
-	if(ndynimp > 0 || ndynexp > 0) {
-		int i;
-
+	if(pragcgobuf.to > pragcgobuf.start) {
 		Bprint(&b, "\n");
 		Bprint(&b, "$$  // exports\n\n");
 		Bprint(&b, "$$  // local types\n\n");
-		Bprint(&b, "$$  // dynimport\n");
-		for(i=0; i<ndynimp; i++)
-			Bprint(&b, "dynimport %s %s %s\n", dynimp[i].local, dynimp[i].remote, dynimp[i].path);
-		Bprint(&b, "\n$$  // dynexport\n");
-		for(i=0; i<ndynexp; i++)
-			Bprint(&b, "dynexport %s %s\n", dynexp[i].local, dynexp[i].remote);
+		Bprint(&b, "$$  // cgo\n");
+		Bprint(&b, "%s", fmtstrflush(&pragcgobuf));
 		Bprint(&b, "\n$$\n\n");
 	}
 	Bprint(&b, "!\n");
@@ -343,12 +337,38 @@ outhist(Biobuf *b)
 	char *p, *q, *op, c;
 	Prog pg;
 	int n;
+	char *tofree;
+	static int first = 1;
+	static char *goroot, *goroot_final;
+
+	if(first) {
+		// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
+		first = 0;
+		goroot = getenv("GOROOT");
+		goroot_final = getenv("GOROOT_FINAL");
+		if(goroot == nil)
+			goroot = "";
+		if(goroot_final == nil)
+			goroot_final = goroot;
+		if(strcmp(goroot, goroot_final) == 0) {
+			goroot = nil;
+			goroot_final = nil;
+		}
+	}
 
+	tofree = nil;
 	pg = zprog;
 	pg.as = AHISTORY;
 	c = pathchar();
 	for(h = hist; h != H; h = h->link) {
 		p = h->name;
+		if(p != nil && goroot != nil) {
+			n = strlen(goroot);
+			if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
+				tofree = smprint("%s%s", goroot_final, p+n);
+				p = tofree;
+			}
+		}
 		op = 0;
 		if(systemtype(Windows) && p && p[1] == ':'){
 			c = p[2];
@@ -404,6 +424,11 @@ outhist(Biobuf *b)
 		Bputc(b, pg.lineno>>24);
 		zaddr(b, &pg.from, 0);
 		zaddr(b, &pg.to, 0);
+
+		if(tofree) {
+			free(tofree);
+			tofree = nil;
+		}
 	}
 }
 
@@ -597,8 +622,8 @@ align(int32 i, Type *t, int op, int32 *maxalign)
 int32
 maxround(int32 max, int32 v)
 {
-	v += SZ_LONG-1;
+	v = xround(v, SZ_LONG);
 	if(v > max)
-		max = xround(v, SZ_LONG);
+		return v;
 	return max;
 }
diff --git a/src/cmd/8c/txt.c b/src/cmd/8c/txt.c
index 3a08da7..1b7617b 100644
--- a/src/cmd/8c/txt.c
+++ b/src/cmd/8c/txt.c
@@ -1253,6 +1253,14 @@ gopcode(int o, Type *ty, Node *f, Node *t)
 			a = ASALW;
 		break;
 
+	case OROTL:
+		a = AROLL;
+		if(et == TCHAR || et == TUCHAR)
+			a = AROLB;
+		if(et == TSHORT || et == TUSHORT)
+			a = AROLW;
+		break;
+
 	case OFUNC:
 		a = ACALL;
 		break;
@@ -1383,6 +1391,21 @@ gpseudo(int a, Sym *s, Node *n)
 		pc--;
 }
 
+void
+gprefetch(Node *n)
+{
+	Node n1;
+	
+	if(strcmp(getgo386(), "sse2") != 0) // assume no prefetch on old machines
+		return;
+
+	regalloc(&n1, n, Z);
+	gmove(n, &n1);
+	n1.op = OINDREG;
+	gins(APREFETCHNTA, &n1, Z);
+	regfree(&n1);
+}
+
 int
 sconst(Node *n)
 {
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index 48619ac..0b2f2b7 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -49,7 +49,7 @@ mfree(Node *n)
 void
 cgen(Node *n, Node *res)
 {
-	Node *nl, *nr, *r, n1, n2, nt, f0, f1;
+	Node *nl, *nr, *r, n1, n2, nt;
 	Prog *p1, *p2, *p3;
 	int a;
 
@@ -63,9 +63,26 @@ cgen(Node *n, Node *res)
 	if(res == N || res->type == T)
 		fatal("cgen: res nil");
 
-	// inline slices
-	if(cgen_inline(n, res))
+	switch(n->op) {
+	case OSLICE:
+	case OSLICEARR:
+	case OSLICESTR:
+		if (res->op != ONAME || !res->addable) {
+			tempname(&n1, n->type);
+			cgen_slice(n, &n1);
+			cgen(&n1, res);
+		} else
+			cgen_slice(n, res);
+		return;
+	case OEFACE:
+		if (res->op != ONAME || !res->addable) {
+			tempname(&n1, n->type);
+			cgen_eface(n, &n1);
+			cgen(&n1, res);
+		} else
+			cgen_eface(n, res);
 		return;
+	}
 
 	while(n->op == OCONVNOP)
 		n = n->left;
@@ -160,6 +177,7 @@ cgen(Node *n, Node *res)
 		case OADD:
 		case OSUB:
 		case OMUL:
+		case OLROT:
 		case OLSH:
 		case ORSH:
 		case OAND:
@@ -170,8 +188,10 @@ cgen(Node *n, Node *res)
 		}
 	}
 
-	if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype])
-		goto flt;
+	if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype]) {
+		cgen_float(n, res);
+		return;
+	}
 
 	switch(n->op) {
 	default:
@@ -195,12 +215,12 @@ cgen(Node *n, Node *res)
 	case OGE:
 	case OGT:
 	case ONOT:
-		p1 = gbranch(AJMP, T);
+		p1 = gbranch(AJMP, T, 0);
 		p2 = pc;
 		gmove(nodbool(1), res);
-		p3 = gbranch(AJMP, T);
+		p3 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
-		bgen(n, 1, p2);
+		bgen(n, 1, 0, p2);
 		gmove(nodbool(0), res);
 		patch(p3, pc);
 		return;
@@ -232,6 +252,10 @@ cgen(Node *n, Node *res)
 		a = optoas(n->op, nl->type);
 		goto abop;
 
+	case OHMUL:
+		cgen_hmul(nl, nr, res);
+		break;
+
 	case OCONV:
 		if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
 			cgen(nl, res);
@@ -274,7 +298,7 @@ cgen(Node *n, Node *res)
 
 			nodconst(&n2, types[tptr], 0);
 			gins(optoas(OCMP, types[tptr]), &n1, &n2);
-			p1 = gbranch(optoas(OEQ, types[tptr]), T);
+			p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
 
 			n2 = n1;
 			n2.op = OINDREG;
@@ -308,7 +332,7 @@ cgen(Node *n, Node *res)
 
 			nodconst(&n2, types[tptr], 0);
 			gins(optoas(OCMP, types[tptr]), &n1, &n2);
-			p1 = gbranch(optoas(OEQ, types[tptr]), T);
+			p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
 
 			n2 = n1;
 			n2.op = OINDREG;
@@ -324,9 +348,8 @@ cgen(Node *n, Node *res)
 		}
 		if(isslice(nl->type)) {
 			igen(nl, &n1, res);
-			n1.op = OINDREG;
 			n1.type = types[TUINT32];
-			n1.xoffset = Array_cap;
+			n1.xoffset += Array_cap;
 			gmove(&n1, res);
 			regfree(&n1);
 			break;
@@ -360,20 +383,29 @@ cgen(Node *n, Node *res)
 
 	case OLSH:
 	case ORSH:
-		cgen_shift(n->op, nl, nr, res);
+	case OLROT:
+		cgen_shift(n->op, n->bounded, nl, nr, res);
 		break;
 	}
 	return;
 
 sbop:	// symmetric binary
-	if(nl->ullman < nr->ullman) {
+	if(nl->ullman < nr->ullman || nl->op == OLITERAL) {
 		r = nl;
 		nl = nr;
 		nr = r;
 	}
 
 abop:	// asymmetric binary
-	if(nl->ullman >= nr->ullman) {
+	if(smallintconst(nr)) {
+		mgen(nl, &n1, res);
+		regalloc(&n2, nl->type, &n1);
+		gmove(&n1, &n2);
+		gins(a, nr, &n2);
+		gmove(&n2, res);
+		regfree(&n2);
+		mfree(&n1);
+	} else if(nl->ullman >= nr->ullman) {
 		tempname(&nt, nl->type);
 		cgen(nl, &nt);
 		mgen(nr, &n2, N);
@@ -401,69 +433,42 @@ uop:	// unary
 	gins(a, N, &n1);
 	gmove(&n1, res);
 	return;
-
-flt:	// floating-point.  387 (not SSE2) to interoperate with 8c
-	nodreg(&f0, nl->type, D_F0);
-	nodreg(&f1, n->type, D_F0+1);
-	if(nr != N)
-		goto flt2;
-
-	// unary
-	cgen(nl, &f0);
-	if(n->op != OCONV && n->op != OPLUS)
-		gins(foptoas(n->op, n->type, 0), N, N);
-	gmove(&f0, res);
-	return;
-
-flt2:	// binary
-	if(nl->ullman >= nr->ullman) {
-		cgen(nl, &f0);
-		if(nr->addable)
-			gins(foptoas(n->op, n->type, 0), nr, &f0);
-		else {
-			cgen(nr, &f0);
-			gins(foptoas(n->op, n->type, Fpop), &f0, &f1);
-		}
-	} else {
-		cgen(nr, &f0);
-		if(nl->addable)
-			gins(foptoas(n->op, n->type, Frev), nl, &f0);
-		else {
-			cgen(nl, &f0);
-			gins(foptoas(n->op, n->type, Frev|Fpop), &f0, &f1);
-		}
-	}
-	gmove(&f0, res);
-	return;
 }
 
 /*
- * generate array index into res.
- * n might be any size; res is 32-bit.
+ * generate an addressable node in res, containing the value of n.
+ * n is an array index, and might be any size; res width is <= 32-bit.
  * returns Prog* to patch to panic call.
  */
-Prog*
-cgenindex(Node *n, Node *res)
+static Prog*
+igenindex(Node *n, Node *res, int bounded)
 {
 	Node tmp, lo, hi, zero;
 
 	if(!is64(n->type)) {
-		cgen(n, res);
+		if(n->addable) {
+			// nothing to do.
+			*res = *n;
+		} else {
+			tempname(res, types[TUINT32]);
+			cgen(n, res);
+		}
 		return nil;
 	}
 
 	tempname(&tmp, types[TINT64]);
 	cgen(n, &tmp);
 	split64(&tmp, &lo, &hi);
+	tempname(res, types[TUINT32]);
 	gmove(&lo, res);
-	if(debug['B']) {
+	if(bounded) {
 		splitclean();
 		return nil;
 	}
 	nodconst(&zero, types[TINT32], 0);
 	gins(ACMPL, &hi, &zero);
 	splitclean();
-	return gbranch(AJNE, T);
+	return gbranch(AJNE, T, +1);
 }
 		
 /*
@@ -474,11 +479,12 @@ void
 agen(Node *n, Node *res)
 {
 	Node *nl, *nr;
-	Node n1, n2, n3, n4, tmp;
+	Node n1, n2, n3, n4, tmp, nlen;
 	Type *t;
 	uint32 w;
 	uint64 v;
 	Prog *p1, *p2;
+	int bounded;
 
 	if(debug['g']) {
 		dump("\nagen-res", res);
@@ -490,6 +496,20 @@ agen(Node *n, Node *res)
 	while(n->op == OCONVNOP)
 		n = n->left;
 
+	if(isconst(n, CTNIL) && n->type->width > widthptr) {
+		// Use of a nil interface or nil slice.
+		// Create a temporary we can take the address of and read.
+		// The generated code is just going to panic, so it need not
+		// be terribly efficient. See issue 3670.
+		tempname(&n1, n->type);
+		clearfat(&n1);
+		regalloc(&n2, types[tptr], res);
+		gins(ALEAL, &n1, &n2);
+		gmove(&n2, res);
+		regfree(&n2);
+		return;
+	}
+		
 	// addressable var is easy
 	if(n->addable) {
 		if(n->op == OREGISTER)
@@ -524,113 +544,136 @@ agen(Node *n, Node *res)
 		cgen_aret(n, res);
 		break;
 
+	case OSLICE:
+	case OSLICEARR:
+	case OSLICESTR:
+		tempname(&n1, n->type);
+		cgen_slice(n, &n1);
+		agen(&n1, res);
+		break;
+
+	case OEFACE:
+		tempname(&n1, n->type);
+		cgen_eface(n, &n1);
+		agen(&n1, res);
+		break;
+
 	case OINDEX:
 		p2 = nil;  // to be patched to panicindex.
 		w = n->type->width;
+		bounded = debug['B'] || n->bounded;
 		if(nr->addable) {
-			if(!isconst(nr, CTINT))
-				tempname(&tmp, types[TINT32]);
+			// Generate &nl first, and move nr into register.
 			if(!isconst(nl, CTSTR))
-				agenr(nl, &n3, res);
+				igen(nl, &n3, res);
 			if(!isconst(nr, CTINT)) {
-				p2 = cgenindex(nr, &tmp);
+				p2 = igenindex(nr, &tmp, bounded);
 				regalloc(&n1, tmp.type, N);
 				gmove(&tmp, &n1);
 			}
 		} else if(nl->addable) {
+			// Generate nr first, and move &nl into register.
 			if(!isconst(nr, CTINT)) {
-				tempname(&tmp, types[TINT32]);
-				p2 = cgenindex(nr, &tmp);
+				p2 = igenindex(nr, &tmp, bounded);
 				regalloc(&n1, tmp.type, N);
 				gmove(&tmp, &n1);
 			}
-			if(!isconst(nl, CTSTR)) {
-				regalloc(&n3, types[tptr], res);
-				agen(nl, &n3);
-			}
+			if(!isconst(nl, CTSTR))
+				igen(nl, &n3, res);
 		} else {
-			tempname(&tmp, types[TINT32]);
-			p2 = cgenindex(nr, &tmp);
+			p2 = igenindex(nr, &tmp, bounded);
 			nr = &tmp;
 			if(!isconst(nl, CTSTR))
-				agenr(nl, &n3, res);
+				igen(nl, &n3, res);
 			regalloc(&n1, tmp.type, N);
 			gins(optoas(OAS, tmp.type), &tmp, &n1);
 		}
 
-		// &a is in &n3 (allocated in res)
-		// i is in &n1 (if not constant)
+		// For fixed array we really want the pointer in n3.
+		if(isfixedarray(nl->type)) {
+			regalloc(&n2, types[tptr], &n3);
+			agen(&n3, &n2);
+			regfree(&n3);
+			n3 = n2;
+		}
+
+		// &a[0] is in n3 (allocated in res)
+		// i is in n1 (if not constant)
+		// len(a) is in nlen (if needed)
 		// w is width
 
 		// explicit check for nil if array is large enough
 		// that we might derive too big a pointer.
 		if(isfixedarray(nl->type) && nl->type->width >= unmappedzero) {
-			regalloc(&n4, types[tptr], &n3);
-			gmove(&n3, &n4);
+			n4 = n3;
 			n4.op = OINDREG;
 			n4.type = types[TUINT8];
 			n4.xoffset = 0;
 			gins(ATESTB, nodintconst(0), &n4);
-			regfree(&n4);
 		}
 
 		// constant index
 		if(isconst(nr, CTINT)) {
 			if(isconst(nl, CTSTR))
-				fatal("constant string constant index");
+				fatal("constant string constant index");  // front end should handle
 			v = mpgetfix(nr->val.u.xval);
 			if(isslice(nl->type) || nl->type->etype == TSTRING) {
-				if(!debug['B'] && !n->etype) {
-					n1 = n3;
-					n1.op = OINDREG;
-					n1.type = types[tptr];
-					n1.xoffset = Array_nel;
+				if(!debug['B'] && !n->bounded) {
+					nlen = n3;
+					nlen.type = types[TUINT32];
+					nlen.xoffset += Array_nel;
 					nodconst(&n2, types[TUINT32], v);
-					gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
-					p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-					ginscall(panicindex, 0);
+					gins(optoas(OCMP, types[TUINT32]), &nlen, &n2);
+					p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
+					ginscall(panicindex, -1);
 					patch(p1, pc);
 				}
-
-				n1 = n3;
-				n1.op = OINDREG;
-				n1.type = types[tptr];
-				n1.xoffset = Array_array;
-				gmove(&n1, &n3);
 			}
 
+			// Load base pointer in n2 = n3.
+			regalloc(&n2, types[tptr], &n3);
+			n3.type = types[tptr];
+			n3.xoffset += Array_array;
+			gmove(&n3, &n2);
+			regfree(&n3);
 			if (v*w != 0) {
-				nodconst(&n2, types[tptr], v*w);
-				gins(optoas(OADD, types[tptr]), &n2, &n3);
+				nodconst(&n1, types[tptr], v*w);
+				gins(optoas(OADD, types[tptr]), &n1, &n2);
 			}
-			gmove(&n3, res);
-			regfree(&n3);
+			gmove(&n2, res);
+			regfree(&n2);
 			break;
 		}
 
-		regalloc(&n2, types[TINT32], &n1);			// i
+		// i is in register n1, extend to 32 bits.
+		t = types[TUINT32];
+		if(issigned[n1.type->etype])
+			t = types[TINT32];
+
+		regalloc(&n2, t, &n1);			// i
 		gmove(&n1, &n2);
 		regfree(&n1);
 
-		if(!debug['B'] && !n->etype) {
+		if(!debug['B'] && !n->bounded) {
 			// check bounds
-			if(isconst(nl, CTSTR))
-				nodconst(&n1, types[TUINT32], nl->val.u.sval->len);
-			else if(isslice(nl->type) || nl->type->etype == TSTRING) {
-				n1 = n3;
-				n1.op = OINDREG;
-				n1.type = types[tptr];
-				n1.xoffset = Array_nel;
-			} else
-				nodconst(&n1, types[TUINT32], nl->type->bound);
-			gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
-			p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+			t = types[TUINT32];
+			if(isconst(nl, CTSTR)) {
+				nodconst(&nlen, t, nl->val.u.sval->len);
+			} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
+				nlen = n3;
+				nlen.type = t;
+				nlen.xoffset += Array_nel;
+			} else {
+				nodconst(&nlen, t, nl->type->bound);
+			}
+			gins(optoas(OCMP, t), &n2, &nlen);
+			p1 = gbranch(optoas(OLT, t), T, +1);
 			if(p2)
 				patch(p2, pc);
-			ginscall(panicindex, 0);
+			ginscall(panicindex, -1);
 			patch(p1, pc);
 		}
-		
+
 		if(isconst(nl, CTSTR)) {
 			regalloc(&n3, types[tptr], res);
 			p1 = gins(ALEAL, N, &n3);
@@ -640,24 +683,27 @@ agen(Node *n, Node *res)
 			goto indexdone;
 		}
 
+		// Load base pointer in n3.
+		regalloc(&tmp, types[tptr], &n3);
 		if(isslice(nl->type) || nl->type->etype == TSTRING) {
-			n1 = n3;
-			n1.op = OINDREG;
-			n1.type = types[tptr];
-			n1.xoffset = Array_array;
-			gmove(&n1, &n3);
+			n3.type = types[tptr];
+			n3.xoffset += Array_array;
+			gmove(&n3, &tmp);
 		}
+		regfree(&n3);
+		n3 = tmp;
 
 		if(w == 0) {
 			// nothing to do
 		} else if(w == 1 || w == 2 || w == 4 || w == 8) {
+			// LEAL (n3)(n2*w), n3
 			p1 = gins(ALEAL, &n2, &n3);
 			p1->from.scale = w;
 			p1->from.index = p1->from.type;
 			p1->from.type = p1->to.type + D_INDIR;
 		} else {
-			nodconst(&n1, types[TUINT32], w);
-			gins(optoas(OMUL, types[TUINT32]), &n1, &n2);
+			nodconst(&tmp, types[TUINT32], w);
+			gins(optoas(OMUL, types[TUINT32]), &tmp, &n2);
 			gins(optoas(OADD, types[tptr]), &n2, &n3);
 		}
 
@@ -734,20 +780,82 @@ agen(Node *n, Node *res)
 void
 igen(Node *n, Node *a, Node *res)
 {
-	Node n1;
 	Type *fp;
 	Iter flist;
-  
+	Node n1;
+
+	if(debug['g']) {
+		dump("\nigen-n", n);
+	}
 	switch(n->op) {
 	case ONAME:
 		if((n->class&PHEAP) || n->class == PPARAMREF)
 			break;
 		*a = *n;
 		return;
- 
+
+	case OINDREG:
+		// Increase the refcount of the register so that igen's caller
+		// has to call regfree.
+		if(n->val.u.reg != D_SP)
+			reg[n->val.u.reg]++;
+		*a = *n;
+		return;
+
+	case ODOT:
+		igen(n->left, a, res);
+		a->xoffset += n->xoffset;
+		a->type = n->type;
+		return;
+
+	case ODOTPTR:
+		switch(n->left->op) {
+		case ODOT:
+		case ODOTPTR:
+		case OCALLFUNC:
+		case OCALLMETH:
+		case OCALLINTER:
+			// igen-able nodes.
+			igen(n->left, &n1, res);
+			regalloc(a, types[tptr], &n1);
+			gmove(&n1, a);
+			regfree(&n1);
+			break;
+		default:
+			regalloc(a, types[tptr], res);
+			cgen(n->left, a);
+		}
+		if(n->xoffset != 0) {
+			// explicit check for nil if struct is large enough
+			// that we might derive too big a pointer.
+			if(n->left->type->type->width >= unmappedzero) {
+				n1 = *a;
+				n1.op = OINDREG;
+				n1.type = types[TUINT8];
+				n1.xoffset = 0;
+				gins(ATESTB, nodintconst(0), &n1);
+			}
+		}
+		a->op = OINDREG;
+		a->xoffset += n->xoffset;
+		a->type = n->type;
+		return;
+
 	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		switch(n->op) {
+		case OCALLFUNC:
+			cgen_call(n, 0);
+			break;
+		case OCALLMETH:
+			cgen_callmeth(n, 0);
+			break;
+		case OCALLINTER:
+			cgen_callinter(n, N, 0);
+			break;
+		}
 		fp = structfirst(&flist, getoutarg(n->left->type));
-		cgen_call(n, 0);
 		memset(a, 0, sizeof *a);
 		a->op = OINDREG;
 		a->val.u.reg = D_SP;
@@ -771,33 +879,15 @@ igen(Node *n, Node *a, Node *res)
 }
 
 /*
- * generate:
- *	newreg = &n;
- *
- * caller must regfree(a).
- */
-void
-agenr(Node *n, Node *a, Node *res)
-{
-	Node n1;
-
-	tempname(&n1, types[tptr]);
-	agen(n, &n1);
-	regalloc(a, types[tptr], res);
-	gmove(&n1, a);
-}
-
-/*
  * branch gen
  *	if(n == true) goto to;
  */
 void
-bgen(Node *n, int true, Prog *to)
+bgen(Node *n, int true, int likely, Prog *to)
 {
 	int et, a;
 	Node *nl, *nr, *r;
-	Node n1, n2, tmp, t1, t2, ax;
-	NodeList *ll;
+	Node n1, n2, tmp;
 	Prog *p1, *p2;
 
 	if(debug['g']) {
@@ -822,8 +912,14 @@ bgen(Node *n, int true, Prog *to)
 		patch(gins(AEND, N, N), to);
 		return;
 	}
+	nl = n->left;
 	nr = N;
 
+	if(nl != N && isfloat[nl->type->etype]) {
+		bgen_float(n, true, likely, to);
+		return;
+	}
+
 	switch(n->op) {
 	default:
 	def:
@@ -834,14 +930,14 @@ bgen(Node *n, int true, Prog *to)
 		a = AJNE;
 		if(!true)
 			a = AJEQ;
-		patch(gbranch(a, n->type), to);
+		patch(gbranch(a, n->type, likely), to);
 		regfree(&n1);
 		return;
 
 	case OLITERAL:
 		// need to ask if it is bool?
 		if(!true == !n->val.u.bval)
-			patch(gbranch(AJMP, T), to);
+			patch(gbranch(AJMP, T, 0), to);
 		return;
 
 	case ONAME:
@@ -852,7 +948,7 @@ bgen(Node *n, int true, Prog *to)
 		a = AJNE;
 		if(!true)
 			a = AJEQ;
-		patch(gbranch(a, n->type), to);
+		patch(gbranch(a, n->type, likely), to);
 		return;
 
 	case OANDAND:
@@ -860,12 +956,12 @@ bgen(Node *n, int true, Prog *to)
 			goto caseor;
 
 	caseand:
-		p1 = gbranch(AJMP, T);
-		p2 = gbranch(AJMP, T);
+		p1 = gbranch(AJMP, T, 0);
+		p2 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
-		bgen(n->left, !true, p2);
-		bgen(n->right, !true, p2);
-		p1 = gbranch(AJMP, T);
+		bgen(n->left, !true, -likely, p2);
+		bgen(n->right, !true, -likely, p2);
+		p1 = gbranch(AJMP, T, 0);
 		patch(p1, to);
 		patch(p2, pc);
 		return;
@@ -875,8 +971,8 @@ bgen(Node *n, int true, Prog *to)
 			goto caseand;
 
 	caseor:
-		bgen(n->left, true, to);
-		bgen(n->right, true, to);
+		bgen(n->left, true, likely, to);
+		bgen(n->right, true, likely, to);
 		return;
 
 	case OEQ:
@@ -897,7 +993,7 @@ bgen(Node *n, int true, Prog *to)
 
 	switch(n->op) {
 	case ONOT:
-		bgen(nl, !true, to);
+		bgen(nl, !true, likely, to);
 		break;
 
 	case OEQ:
@@ -908,19 +1004,6 @@ bgen(Node *n, int true, Prog *to)
 	case OGE:
 		a = n->op;
 		if(!true) {
-			if(isfloat[nl->type->etype]) {
-				// brcom is not valid on floats when NaN is involved.
-				p1 = gbranch(AJMP, T);
-				p2 = gbranch(AJMP, T);
-				patch(p1, pc);
-				ll = n->ninit;  // avoid re-genning ninit
-				n->ninit = nil;
-				bgen(n, 1, p2);
-				n->ninit = ll;
-				patch(gbranch(AJMP, T), to);
-				patch(p2, pc);
-				break;
-			}				
 			a = brcom(a);
 			true = !true;
 		}
@@ -936,19 +1019,16 @@ bgen(Node *n, int true, Prog *to)
 		if(isslice(nl->type)) {
 			// front end should only leave cmp to literal nil
 			if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-				yyerror("illegal array comparison");
+				yyerror("illegal slice comparison");
 				break;
 			}
 			a = optoas(a, types[tptr]);
-			regalloc(&n1, types[tptr], N);
-			agen(nl, &n1);
-			n2 = n1;
-			n2.op = OINDREG;
-			n2.xoffset = Array_array;
-			n2.type = types[tptr];
+			igen(nl, &n1, N);
+			n1.xoffset += Array_array;
+			n1.type = types[tptr];
 			nodconst(&tmp, types[tptr], 0);
-			gins(optoas(OCMP, types[tptr]), &n2, &tmp);
-			patch(gbranch(a, types[tptr]), to);
+			gins(optoas(OCMP, types[tptr]), &n1, &tmp);
+			patch(gbranch(a, types[tptr], likely), to);
 			regfree(&n1);
 			break;
 		}
@@ -960,75 +1040,17 @@ bgen(Node *n, int true, Prog *to)
 				break;
 			}
 			a = optoas(a, types[tptr]);
-			regalloc(&n1, types[tptr], N);
-			agen(nl, &n1);
-			n2 = n1;
-			n2.op = OINDREG;
-			n2.xoffset = 0;
+			igen(nl, &n1, N);
+			n1.type = types[tptr];
 			nodconst(&tmp, types[tptr], 0);
-			gins(optoas(OCMP, types[tptr]), &n2, &tmp);
-			patch(gbranch(a, types[tptr]), to);
+			gins(optoas(OCMP, types[tptr]), &n1, &tmp);
+			patch(gbranch(a, types[tptr], likely), to);
 			regfree(&n1);
 			break;
 		}
 
-		if(isfloat[nr->type->etype]) {
-			a = brrev(a);	// because the args are stacked
-			if(a == OGE || a == OGT) {
-				// only < and <= work right with NaN; reverse if needed
-				r = nr;
-				nr = nl;
-				nl = r;
-				a = brrev(a);
-			}
-			nodreg(&tmp, nr->type, D_F0);
-			nodreg(&n2, nr->type, D_F0 + 1);
-			nodreg(&ax, types[TUINT16], D_AX);
-			et = simsimtype(nr->type);
-			if(et == TFLOAT64) {
-				if(nl->ullman > nr->ullman) {
-					cgen(nl, &tmp);
-					cgen(nr, &tmp);
-					gins(AFXCHD, &tmp, &n2);
-				} else {
-					cgen(nr, &tmp);
-					cgen(nl, &tmp);
-				}
-				gins(AFUCOMIP, &tmp, &n2);
-				gins(AFMOVDP, &tmp, &tmp);	// annoying pop but still better than STSW+SAHF
-			} else {
-				// TODO(rsc): The moves back and forth to memory
-				// here are for truncating the value to 32 bits.
-				// This handles 32-bit comparison but presumably
-				// all the other ops have the same problem.
-				// We need to figure out what the right general
-				// solution is, besides telling people to use float64.
-				tempname(&t1, types[TFLOAT32]);
-				tempname(&t2, types[TFLOAT32]);
-				cgen(nr, &t1);
-				cgen(nl, &t2);
-				gmove(&t2, &tmp);
-				gins(AFCOMFP, &t1, &tmp);
-				gins(AFSTSW, N, &ax);
-				gins(ASAHF, N, N);
-			}
-			if(a == OEQ) {
-				// neither NE nor P
-				p1 = gbranch(AJNE, T);
-				p2 = gbranch(AJPS, T);
-				patch(gbranch(AJMP, T), to);
-				patch(p1, pc);
-				patch(p2, pc);
-			} else if(a == ONE) {
-				// either NE or P
-				patch(gbranch(AJNE, T), to);
-				patch(gbranch(AJPS, T), to);
-			} else
-				patch(gbranch(optoas(a, nr->type), T), to);
-			break;
-		}
 		if(iscomplex[nl->type->etype]) {
-			complexbool(a, nl, nr, true, to);
+			complexbool(a, nl, nr, true, likely, to);
 			break;
 		}
 
@@ -1043,40 +1065,55 @@ bgen(Node *n, int true, Prog *to)
 				cgen(nr, &n2);
 				nr = &n2;
 			}
-			cmp64(nl, nr, a, to);
+			cmp64(nl, nr, a, likely, to);
 			break;
 		}
 
-		a = optoas(a, nr->type);
-
 		if(nr->ullman >= UINF) {
-			tempname(&n1, nl->type);
-			tempname(&tmp, nr->type);
-			cgen(nl, &n1);
-			cgen(nr, &tmp);
+			if(!nl->addable) {
+				tempname(&n1, nl->type);
+				cgen(nl, &n1);
+				nl = &n1;
+			}
+			if(!nr->addable) {
+				tempname(&tmp, nr->type);
+				cgen(nr, &tmp);
+				nr = &tmp;
+			}
 			regalloc(&n2, nr->type, N);
-			cgen(&tmp, &n2);
+			cgen(nr, &n2);
+			nr = &n2;
 			goto cmp;
 		}
 
-		tempname(&n1, nl->type);
-		cgen(nl, &n1);
+		if(!nl->addable) {
+			tempname(&n1, nl->type);
+			cgen(nl, &n1);
+			nl = &n1;
+		}
 
 		if(smallintconst(nr)) {
-			gins(optoas(OCMP, nr->type), &n1, nr);
-			patch(gbranch(a, nr->type), to);
+			gins(optoas(OCMP, nr->type), nl, nr);
+			patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
 			break;
 		}
 
-		tempname(&tmp, nr->type);
-		cgen(nr, &tmp);
+		if(!nr->addable) {
+			tempname(&tmp, nr->type);
+			cgen(nr, &tmp);
+			nr = &tmp;
+		}
 		regalloc(&n2, nr->type, N);
-		gmove(&tmp, &n2);
+		gmove(nr, &n2);
+		nr = &n2;
 
 cmp:
-		gins(optoas(OCMP, nr->type), &n1, &n2);
-		patch(gbranch(a, nr->type), to);
-		regfree(&n2);
+		gins(optoas(OCMP, nr->type), nl, nr);
+		patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
+
+		if(nl->op == OREGISTER)
+			regfree(nl);
+		regfree(nr);
 		break;
 	}
 }
@@ -1164,6 +1201,10 @@ sgen(Node *n, Node *res, int64 w)
 		return;
 	}
 
+	// Avoid taking the address for simple enough types.
+	if(componentgen(n, res))
+		return;
+
 	// offset on the stack
 	osrc = stkof(n);
 	odst = stkof(res);
@@ -1247,3 +1288,157 @@ sgen(Node *n, Node *res, int64 w)
 	}
 }
 
+static int
+cadable(Node *n)
+{
+	if(!n->addable) {
+		// dont know how it happens,
+		// but it does
+		return 0;
+	}
+
+	switch(n->op) {
+	case ONAME:
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * copy a composite value by moving its individual components.
+ * Slices, strings and interfaces are supported.
+ * nr is N when assigning a zero value.
+ * return 1 if can do, 0 if cant.
+ */
+int
+componentgen(Node *nr, Node *nl)
+{
+	Node nodl, nodr;
+	int freel, freer;
+
+	freel = 0;
+	freer = 0;
+
+	switch(nl->type->etype) {
+	default:
+		goto no;
+
+	case TARRAY:
+		if(!isslice(nl->type))
+			goto no;
+	case TSTRING:
+	case TINTER:
+		break;
+	}
+
+	nodl = *nl;
+	if(!cadable(nl)) {
+		if(nr == N || !cadable(nr))
+			goto no;
+		igen(nl, &nodl, N);
+		freel = 1;
+	}
+
+	if(nr != N) {
+		nodr = *nr;
+		if(!cadable(nr)) {
+			igen(nr, &nodr, N);
+			freer = 1;
+		}
+	}
+
+	switch(nl->type->etype) {
+	case TARRAY:
+		nodl.xoffset += Array_array;
+		nodl.type = ptrto(nl->type->type);
+
+		if(nr != N) {
+			nodr.xoffset += Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_nel-Array_array;
+		nodl.type = types[TUINT32];
+
+		if(nr != N) {
+			nodr.xoffset += Array_nel-Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_cap-Array_nel;
+		nodl.type = types[TUINT32];
+
+		if(nr != N) {
+			nodr.xoffset += Array_cap-Array_nel;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		goto yes;
+
+	case TSTRING:
+		nodl.xoffset += Array_array;
+		nodl.type = ptrto(types[TUINT8]);
+
+		if(nr != N) {
+			nodr.xoffset += Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_nel-Array_array;
+		nodl.type = types[TUINT32];
+
+		if(nr != N) {
+			nodr.xoffset += Array_nel-Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		goto yes;
+
+	case TINTER:
+		nodl.xoffset += Array_array;
+		nodl.type = ptrto(types[TUINT8]);
+
+		if(nr != N) {
+			nodr.xoffset += Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_nel-Array_array;
+		nodl.type = ptrto(types[TUINT8]);
+
+		if(nr != N) {
+			nodr.xoffset += Array_nel-Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		goto yes;
+	}
+
+no:
+	if(freer)
+		regfree(&nodr);
+	if(freel)
+		regfree(&nodl);
+	return 0;
+
+yes:
+	if(freer)
+		regfree(&nodr);
+	if(freel)
+		regfree(&nodl);
+	return 1;
+}
diff --git a/src/cmd/8g/cgen64.c b/src/cmd/8g/cgen64.c
index 8e568a0..dc50a40 100644
--- a/src/cmd/8g/cgen64.c
+++ b/src/cmd/8g/cgen64.c
@@ -49,6 +49,7 @@ cgen64(Node *n, Node *res)
 	case OADD:
 	case OSUB:
 	case OMUL:
+	case OLROT:
 	case OLSH:
 	case ORSH:
 	case OAND:
@@ -113,9 +114,9 @@ cgen64(Node *n, Node *res)
 		// if DX and EX are zero, use 32 x 32 -> 64 unsigned multiply.
 		gins(AMOVL, &dx, &fx);
 		gins(AORL, &ex, &fx);
-		p1 = gbranch(AJNE, T);
+		p1 = gbranch(AJNE, T, 0);
 		gins(AMULL, &cx, N);	// implicit &ax
-		p2 = gbranch(AJMP, T);
+		p2 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
 
 		// full 64x64 -> 64, from 32x32 -> 64.
@@ -131,6 +132,40 @@ cgen64(Node *n, Node *res)
 		regfree(&ex);
 		regfree(&fx);
 		break;
+	
+	case OLROT:
+		// We only rotate by a constant c in [0,64).
+		// if c >= 32:
+		//	lo, hi = hi, lo
+		//	c -= 32
+		// if c == 0:
+		//	no-op
+		// else:
+		//	t = hi
+		//	shld hi:lo, c
+		//	shld lo:t, c
+		v = mpgetfix(r->val.u.xval);
+		if(v >= 32) {
+			// reverse during load to do the first 32 bits of rotate
+			v -= 32;
+			gins(AMOVL, &lo1, &dx);
+			gins(AMOVL, &hi1, &ax);
+		} else {
+			gins(AMOVL, &lo1, &ax);
+			gins(AMOVL, &hi1, &dx);
+		}
+		if(v == 0) {
+			// done
+		} else {
+			gins(AMOVL, &dx, &cx);
+			p1 = gins(ASHLL, ncon(v), &dx);
+			p1->from.index = D_AX;	// double-width shift
+			p1->from.scale = 0;
+			p1 = gins(ASHLL, ncon(v), &ax);
+			p1->from.index = D_CX;	// double-width shift
+			p1->from.scale = 0;
+		}
+		break;
 
 	case OLSH:
 		if(r->op == OLITERAL) {
@@ -178,7 +213,7 @@ cgen64(Node *n, Node *res)
 		p1 = P;
 		if(is64(r->type)) {
 			gins(ACMPL, &hi2, ncon(0));
-			p1 = gbranch(AJNE, T);
+			p1 = gbranch(AJNE, T, +1);
 			gins(AMOVL, &lo2, &cx);
 		} else {
 			cx.type = types[TUINT32];
@@ -187,7 +222,7 @@ cgen64(Node *n, Node *res)
 
 		// if shift count is >=64, zero value
 		gins(ACMPL, &cx, ncon(64));
-		p2 = gbranch(optoas(OLT, types[TUINT32]), T);
+		p2 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
 		if(p1 != P)
 			patch(p1, pc);
 		gins(AXORL, &dx, &dx);
@@ -196,11 +231,11 @@ cgen64(Node *n, Node *res)
 
 		// if shift count is >= 32, zero low.
 		gins(ACMPL, &cx, ncon(32));
-		p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+		p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
 		gins(AMOVL, &ax, &dx);
 		gins(ASHLL, &cx, &dx);	// SHLL only uses bottom 5 bits of count
 		gins(AXORL, &ax, &ax);
-		p2 = gbranch(AJMP, T);
+		p2 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
 
 		// general shift
@@ -267,7 +302,7 @@ cgen64(Node *n, Node *res)
 		p1 = P;
 		if(is64(r->type)) {
 			gins(ACMPL, &hi2, ncon(0));
-			p1 = gbranch(AJNE, T);
+			p1 = gbranch(AJNE, T, +1);
 			gins(AMOVL, &lo2, &cx);
 		} else {
 			cx.type = types[TUINT32];
@@ -276,7 +311,7 @@ cgen64(Node *n, Node *res)
 
 		// if shift count is >=64, zero or sign-extend value
 		gins(ACMPL, &cx, ncon(64));
-		p2 = gbranch(optoas(OLT, types[TUINT32]), T);
+		p2 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
 		if(p1 != P)
 			patch(p1, pc);
 		if(hi1.type->etype == TINT32) {
@@ -290,7 +325,7 @@ cgen64(Node *n, Node *res)
 
 		// if shift count is >= 32, sign-extend hi.
 		gins(ACMPL, &cx, ncon(32));
-		p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+		p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
 		gins(AMOVL, &dx, &ax);
 		if(hi1.type->etype == TINT32) {
 			gins(ASARL, &cx, &ax);	// SARL only uses bottom 5 bits of count
@@ -299,7 +334,7 @@ cgen64(Node *n, Node *res)
 			gins(ASHRL, &cx, &ax);
 			gins(AXORL, &dx, &dx);
 		}
-		p2 = gbranch(AJMP, T);
+		p2 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
 
 		// general shift
@@ -427,7 +462,7 @@ out:;
  * nl is memory; nr is constant or memory.
  */
 void
-cmp64(Node *nl, Node *nr, int op, Prog *to)
+cmp64(Node *nl, Node *nr, int op, int likely, Prog *to)
 {
 	Node lo1, hi1, lo2, hi2, rr;
 	Prog *br;
@@ -457,14 +492,14 @@ cmp64(Node *nl, Node *nr, int op, Prog *to)
 		// cmp lo
 		// jeq to
 		// L:
-		br = gbranch(AJNE, T);
+		br = gbranch(AJNE, T, -likely);
 		break;
 	case ONE:
 		// cmp hi
 		// jne to
 		// cmp lo
 		// jne to
-		patch(gbranch(AJNE, T), to);
+		patch(gbranch(AJNE, T, likely), to);
 		break;
 	case OGE:
 	case OGT:
@@ -474,8 +509,8 @@ cmp64(Node *nl, Node *nr, int op, Prog *to)
 		// cmp lo
 		// jge to (or jgt to)
 		// L:
-		patch(gbranch(optoas(OGT, t), T), to);
-		br = gbranch(optoas(OLT, t), T);
+		patch(gbranch(optoas(OGT, t), T, likely), to);
+		br = gbranch(optoas(OLT, t), T, -likely);
 		break;
 	case OLE:
 	case OLT:
@@ -485,8 +520,8 @@ cmp64(Node *nl, Node *nr, int op, Prog *to)
 		// cmp lo
 		// jle to (or jlt to)
 		// L:
-		patch(gbranch(optoas(OLT, t), T), to);
-		br = gbranch(optoas(OGT, t), T);
+		patch(gbranch(optoas(OLT, t), T, likely), to);
+		br = gbranch(optoas(OGT, t), T, -likely);
 		break;
 	}
 
@@ -502,7 +537,7 @@ cmp64(Node *nl, Node *nr, int op, Prog *to)
 	}
 
 	// jump again
-	patch(gbranch(optoas(op, t), T), to);
+	patch(gbranch(optoas(op, t), T, likely), to);
 
 	// point first branch down here if appropriate
 	if(br != P)
diff --git a/src/cmd/8g/doc.go b/src/cmd/8g/doc.go
index 6d678ea..9e46dca 100644
--- a/src/cmd/8g/doc.go
+++ b/src/cmd/8g/doc.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 ignore
+
 /*
 
 8g is the version of the gc compiler for the x86.
@@ -10,4 +12,4 @@ The $GOARCH for these tools is 386.
 It reads .go files and outputs .8 files. The flags are documented in ../gc/doc.go.
 
 */
-package documentation
+package main
diff --git a/src/cmd/8g/galign.c b/src/cmd/8g/galign.c
index 4526a2e..2c8aaa0 100644
--- a/src/cmd/8g/galign.c
+++ b/src/cmd/8g/galign.c
@@ -27,6 +27,7 @@ void
 betypeinit(void)
 {
 	widthptr = 4;
+	widthint = 4;
 
 	zprog.link = P;
 	zprog.as = AGOK;
diff --git a/src/cmd/8g/gg.h b/src/cmd/8g/gg.h
index 0a4f0ad..03c206a 100644
--- a/src/cmd/8g/gg.h
+++ b/src/cmd/8g/gg.h
@@ -16,9 +16,12 @@ struct	Addr
 	int32	offset;
 	int32	offset2;
 
-	double	dval;
-	Prog*	branch;
-	char	sval[NSNAME];
+	union {
+		double	dval;
+		vlong	vval;
+		Prog*	branch;
+		char	sval[NSNAME];
+	} u;
 
 	Sym*	gotype;
 	Sym*	sym;
@@ -28,7 +31,6 @@ struct	Addr
 	uchar	index;
 	uchar	etype;
 	uchar	scale;	/* doubles as width in DATA op */
-	uchar	pun;	/* dont register variable */
 };
 #define	A	((Addr*)0)
 
@@ -83,37 +85,38 @@ void	cgen_proc(Node*, int);
 void	cgen_callret(Node*, Node*);
 void	cgen_div(int, Node*, Node*, Node*);
 void	cgen_bmul(int, Node*, Node*, Node*);
-void	cgen_shift(int, Node*, Node*, Node*);
+void	cgen_hmul(Node*, Node*, Node*);
+void	cgen_shift(int, int, Node*, Node*, Node*);
+void	cgen_float(Node*, Node*);
+void	bgen_float(Node *n, int true, int likely, Prog *to);
 void	cgen_dcl(Node*);
 int	needconvert(Type*, Type*);
 void	genconv(Type*, Type*);
 void	allocparams(void);
-void	checklabels();
+void	checklabels(void);
 void	ginscall(Node*, int);
 
 /*
  * cgen.c
  */
 void	agen(Node*, Node*);
-void	agenr(Node *n, Node *a, Node *res);
 void	igen(Node*, Node*, Node*);
 vlong	fieldoffset(Type*, Node*);
-void	bgen(Node*, int, Prog*);
 void	sgen(Node*, Node*, int64);
 void	gmove(Node*, Node*);
 Prog*	gins(int, Node*, Node*);
 int	samaddr(Node*, Node*);
 void	naddr(Node*, Addr*, int);
 void	cgen_aret(Node*, Node*);
-int	cgen_inline(Node*, Node*);
 Node*	ncon(uint32);
 void	mgen(Node*, Node*, Node*);
 void	mfree(Node*);
+int	componentgen(Node*, Node*);
 
 /*
  * cgen64.c
  */
-void	cmp64(Node*, Node*, int, Prog*);
+void	cmp64(Node*, Node*, int, int, Prog*);
 void	cgen64(Node*, Node*);
 
 /*
@@ -121,16 +124,13 @@ void	cgen64(Node*, Node*);
  */
 void	clearp(Prog*);
 void	proglist(void);
-Prog*	gbranch(int, Type*);
+Prog*	gbranch(int, Type*, int);
 Prog*	prog(int);
-void	gaddoffset(Node*);
 void	gconv(int, int);
 int	conv2pt(Type*);
 vlong	convvtox(vlong, int);
 void	fnparam(Type*, int, int);
 Prog*	gop(int, Node*, Node*, Node*);
-void	setconst(Addr*, vlong);
-void	setaddr(Addr*, Node*);
 int	optoas(int, Type*);
 int	foptoas(int, Type*, int);
 void	ginit(void);
@@ -142,18 +142,17 @@ void	nodreg(Node*, Type*, int);
 void	nodindreg(Node*, Type*, int);
 void	nodconst(Node*, Type*, int64);
 void	gconreg(int, vlong, int);
-void	datagostring(Strlit*, Addr*);
-void	datastring(char*, int, Addr*);
 void	buildtxt(void);
 Plist*	newplist(void);
 int	isfat(Type*);
 void	sudoclean(void);
 int	sudoaddable(int, Node*, Addr*);
 int	dotaddable(Node*, Node*);
-void	afunclit(Addr*);
+void	afunclit(Addr*, Node*);
 void	split64(Node*, Node*, Node*);
 void	splitclean(void);
 void	nswap(Node*, Node*);
+void	gtrack(Sym*);
 
 /*
  * cplx.c
@@ -161,7 +160,12 @@ void	nswap(Node*, Node*);
 int	complexop(Node*, Node*);
 void	complexmove(Node*, Node*);
 void	complexgen(Node*, Node*);
-void	complexbool(int, Node*, Node*, int, Prog*);
+
+/*
+ * gobj.c
+ */
+void	datastring(char*, int, Addr*);
+void	datagostring(Strlit*, Addr*);
 
 /*
  * list.c
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 6a45701..7014810 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -27,6 +27,9 @@ void
 markautoused(Prog* p)
 {
 	for (; p; p = p->link) {
+		if (p->as == ATYPE)
+			continue;
+
 		if (p->from.type == D_AUTO && p->from.node)
 			p->from.node->used = 1;
 
@@ -39,12 +42,21 @@ markautoused(Prog* p)
 void
 fixautoused(Prog* p)
 {
-	for (; p; p = p->link) {
+	Prog **lp;
+
+	for (lp=&p; (p=*lp) != P; ) {
+		if (p->as == ATYPE && p->from.node && p->from.type == D_AUTO && !p->from.node->used) {
+			*lp = p->link;
+			continue;
+		}
+
 		if (p->from.type == D_AUTO && p->from.node)
 			p->from.offset += p->from.node->stkdelta;
 
 		if (p->to.type == D_AUTO && p->to.node)
 			p->to.offset += p->to.node->stkdelta;
+
+		lp = &p->link;
 	}
 }
 
@@ -59,6 +71,10 @@ clearfat(Node *nl)
 		dump("\nclearfat", nl);
 
 	w = nl->type->width;
+	// Avoid taking the address for simple enough types.
+	if(componentgen(N, nl))
+		return;
+
 	c = w % 4;	// bytes
 	q = w / 4;	// quads
 
@@ -90,15 +106,17 @@ clearfat(Node *nl)
 /*
  * generate:
  *	call f
+ *	proc=-1	normal call but no return
  *	proc=0	normal call
  *	proc=1	goroutine run in new proc
  *	proc=2	defer call save away stack
+  *	proc=3	normal call to C pointer (not Go func value)
  */
 void
 ginscall(Node *f, int proc)
 {
 	Prog *p;
-	Node reg, con;
+	Node reg, r1, con;
 
 	switch(proc) {
 	default:
@@ -106,8 +124,25 @@ ginscall(Node *f, int proc)
 		break;
 
 	case 0:	// normal call
-		p = gins(ACALL, N, f);
-		afunclit(&p->to);
+	case -1:	// normal call but no return
+		if(f->op == ONAME && f->class == PFUNC) {
+			p = gins(ACALL, N, f);
+			afunclit(&p->to, f);
+			if(proc == -1 || noreturn(p))
+				gins(AUNDEF, N, N);
+			break;
+		}
+		nodreg(&reg, types[tptr], D_DX);
+		nodreg(&r1, types[tptr], D_BX);
+		gmove(f, &reg);
+		reg.op = OINDREG;
+		gmove(&reg, &r1);
+		reg.op = OREGISTER;
+		gins(ACALL, &reg, &r1);
+		break;
+	
+	case 3:	// normal call of c function pointer
+		gins(ACALL, N, f);
 		break;
 
 	case 1:	// call in new proc (go)
@@ -125,7 +160,7 @@ ginscall(Node *f, int proc)
 		if(proc == 2) {
 			nodreg(&reg, types[TINT64], D_AX);
 			gins(ATESTL, &reg, &reg);
-			patch(gbranch(AJNE, T), retpc);
+			patch(gbranch(AJNE, T, -1), retpc);
 		}
 		break;
 	}
@@ -139,7 +174,7 @@ void
 cgen_callinter(Node *n, Node *res, int proc)
 {
 	Node *i, *f;
-	Node tmpi, nodo, nodr, nodsp;
+	Node tmpi, nodi, nodo, nodr, nodsp;
 
 	i = n->left;
 	if(i->op != ODOTINTER)
@@ -159,25 +194,35 @@ cgen_callinter(Node *n, Node *res, int proc)
 
 	genlist(n->list);		// assign the args
 
-	// Can regalloc now; i is known to be addable,
-	// so the agen will be easy.
-	regalloc(&nodr, types[tptr], res);
-	regalloc(&nodo, types[tptr], &nodr);
-	nodo.op = OINDREG;
-
-	agen(i, &nodr);		// REG = &inter
+	// i is now addable, prepare an indirected
+	// register to hold its address.
+	igen(i, &nodi, res);		// REG = &inter
 
 	nodindreg(&nodsp, types[tptr], D_SP);
-	nodo.xoffset += widthptr;
-	cgen(&nodo, &nodsp);	// 0(SP) = 4(REG) -- i.data
+	nodi.type = types[tptr];
+	nodi.xoffset += widthptr;
+	cgen(&nodi, &nodsp);	// 0(SP) = 4(REG) -- i.data
 
-	nodo.xoffset -= widthptr;
-	cgen(&nodo, &nodr);	// REG = 0(REG) -- i.tab
+	regalloc(&nodo, types[tptr], res);
+	nodi.type = types[tptr];
+	nodi.xoffset -= widthptr;
+	cgen(&nodi, &nodo);	// REG = 0(REG) -- i.tab
+	regfree(&nodi);
 
+	regalloc(&nodr, types[tptr], &nodo);
 	if(n->left->xoffset == BADWIDTH)
 		fatal("cgen_callinter: badwidth");
+	nodo.op = OINDREG;
 	nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
-	cgen(&nodo, &nodr);	// REG = 20+offset(REG) -- i.tab->fun[f]
+	
+	if(proc == 0) {
+		// plain call: use direct c function pointer - more efficient
+		cgen(&nodo, &nodr);	// REG = 20+offset(REG) -- i.tab->fun[f]
+		proc = 3;
+	} else {
+		// go/defer. generate go func value.
+		gins(ALEAL, &nodo, &nodr);	// REG = &(20+offset(REG)) -- i.tab->fun[f]
+	}
 
 	// BOTCH nodr.type = fntype;
 	nodr.type = n->left->type;
@@ -486,7 +531,7 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
 	int check;
 	Node n1, t1, t2, t3, t4, n4, nz;
 	Type *t, *t0;
-	Prog *p1, *p2, *p3;
+	Prog *p1, *p2;
 
 	// Have to be careful about handling
 	// most negative int divided by -1 correctly.
@@ -535,23 +580,22 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
 		regalloc(&n1, t, N);
 	gmove(&t2, &n1);
 	gmove(&t1, ax);
-	p3 = P;
+	p2 = P;
 	if(check) {
 		nodconst(&n4, t, -1);
 		gins(optoas(OCMP, t), &n1, &n4);
-		p1 = gbranch(optoas(ONE, t), T);
-		nodconst(&n4, t, -1LL<<(t->width*8-1));
-		gins(optoas(OCMP, t), ax, &n4);
-		p2 = gbranch(optoas(ONE, t), T);
-		if(op == ODIV)
-			gmove(&n4, res);
-		if(op == OMOD) {
+		p1 = gbranch(optoas(ONE, t), T, +1);
+		if(op == ODIV) {
+			// a / (-1) is -a.
+			gins(optoas(OMINUS, t), N, ax);
+			gmove(ax, res);
+		} else {
+			// a % (-1) is 0.
 			nodconst(&n4, t, 0);
 			gmove(&n4, res);
 		}
-		p3 = gbranch(AJMP, T);
+		p2 = gbranch(AJMP, T, 0);
 		patch(p1, pc);
-		patch(p2, pc);
 	}
 	if(!issigned[t->etype]) {
 		nodconst(&nz, t, 0);
@@ -566,7 +610,7 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
 	else
 		gmove(dx, res);
 	if(check)
-		patch(p3, pc);
+		patch(p2, pc);
 }
 
 static void
@@ -630,7 +674,7 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
  *	res = nl >> nr
  */
 void
-cgen_shift(int op, Node *nl, Node *nr, Node *res)
+cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
 {
 	Node n1, n2, nt, cx, oldcx, hi, lo;
 	int a, w;
@@ -651,7 +695,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
 		gmove(&n2, &n1);
 		sc = mpgetfix(nr->val.u.xval);
 		if(sc >= nl->type->width*8) {
-			// large shift gets 2 shifts by width
+			// large shift gets 2 shifts by width-1
 			gins(a, ncon(w-1), &n1);
 			gins(a, ncon(w-1), &n1);
 		} else
@@ -689,27 +733,39 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
 	}
 
 	// test and fix up large shifts
-	if(nr->type->width > 4) {
-		// delayed reg alloc
-		nodreg(&n1, types[TUINT32], D_CX);
-		regalloc(&n1, types[TUINT32], &n1);		// to hold the shift type in CX
-		split64(&nt, &lo, &hi);
-		gmove(&lo, &n1);
-		gins(optoas(OCMP, types[TUINT32]), &hi, ncon(0));
-		p2 = gbranch(optoas(ONE, types[TUINT32]), T);
-		gins(optoas(OCMP, types[TUINT32]), &n1, ncon(w));
-		p1 = gbranch(optoas(OLT, types[TUINT32]), T);
-		patch(p2, pc);
-	} else {
-		gins(optoas(OCMP, nr->type), &n1, ncon(w));
-		p1 = gbranch(optoas(OLT, types[TUINT32]), T);
-	}
-	if(op == ORSH && issigned[nl->type->etype]) {
-		gins(a, ncon(w-1), &n2);
+	if(bounded) {
+		if(nr->type->width > 4) {
+			// delayed reg alloc
+			nodreg(&n1, types[TUINT32], D_CX);
+			regalloc(&n1, types[TUINT32], &n1);		// to hold the shift type in CX
+			split64(&nt, &lo, &hi);
+			gmove(&lo, &n1);
+			splitclean();
+		}
 	} else {
-		gmove(ncon(0), &n2);
+		if(nr->type->width > 4) {
+			// delayed reg alloc
+			nodreg(&n1, types[TUINT32], D_CX);
+			regalloc(&n1, types[TUINT32], &n1);		// to hold the shift type in CX
+			split64(&nt, &lo, &hi);
+			gmove(&lo, &n1);
+			gins(optoas(OCMP, types[TUINT32]), &hi, ncon(0));
+			p2 = gbranch(optoas(ONE, types[TUINT32]), T, +1);
+			gins(optoas(OCMP, types[TUINT32]), &n1, ncon(w));
+			p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
+			splitclean();
+			patch(p2, pc);
+		} else {
+			gins(optoas(OCMP, nr->type), &n1, ncon(w));
+			p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
+		}
+		if(op == ORSH && issigned[nl->type->etype]) {
+			gins(a, ncon(w-1), &n2);
+		} else {
+			gmove(ncon(0), &n2);
+		}
+		patch(p1, pc);
 	}
-	patch(p1, pc);
 	gins(a, &n1, &n2);
 
 	if(oldcx.op != 0)
@@ -724,444 +780,361 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
 /*
  * generate byte multiply:
  *	res = nl * nr
- * no byte multiply instruction so have to do
- * 16-bit multiply and take bottom half.
+ * there is no 2-operand byte multiply instruction so
+ * we do a full-width multiplication and truncate afterwards.
  */
 void
 cgen_bmul(int op, Node *nl, Node *nr, Node *res)
 {
-	Node n1b, n2b, n1w, n2w;
+	Node n1, n2, nt, *tmp;
 	Type *t;
 	int a;
 
-	if(nl->ullman >= nr->ullman) {
-		regalloc(&n1b, nl->type, res);
-		cgen(nl, &n1b);
-		regalloc(&n2b, nr->type, N);
-		cgen(nr, &n2b);
-	} else {
-		regalloc(&n2b, nr->type, N);
-		cgen(nr, &n2b);
-		regalloc(&n1b, nl->type, res);
-		cgen(nl, &n1b);
-	}
-
-	// copy from byte to short registers
-	t = types[TUINT16];
+	// copy from byte to full registers
+	t = types[TUINT32];
 	if(issigned[nl->type->etype])
-		t = types[TINT16];
-
-	regalloc(&n2w, t, &n2b);
-	cgen(&n2b, &n2w);
+		t = types[TINT32];
 
-	regalloc(&n1w, t, &n1b);
-	cgen(&n1b, &n1w);
+	// largest ullman on left.
+	if(nl->ullman < nr->ullman) {
+		tmp = nl;
+		nl = nr;
+		nr = tmp;
+	}
 
+	tempname(&nt, nl->type);
+	cgen(nl, &nt);
+	regalloc(&n1, t, res);
+	cgen(nr, &n1);
+	regalloc(&n2, t, N);
+	gmove(&nt, &n2);
 	a = optoas(op, t);
-	gins(a, &n2w, &n1w);
-	cgen(&n1w, &n1b);
-	cgen(&n1b, res);
-
-	regfree(&n1w);
-	regfree(&n2w);
-	regfree(&n1b);
-	regfree(&n2b);
+	gins(a, &n2, &n1);
+	regfree(&n2);
+	gmove(&n1, res);
+	regfree(&n1);
 }
 
-static int
-regcmp(const void *va, const void *vb)
+/*
+ * generate high multiply:
+ *   res = (nl*nr) >> width
+ */
+void
+cgen_hmul(Node *nl, Node *nr, Node *res)
 {
-	Node *ra, *rb;
-
-	ra = (Node*)va;
-	rb = (Node*)vb;
-	return ra->local - rb->local;
-}
+	Type *t;
+	int a;
+	Node n1, n2, ax, dx;
 
-static	Prog*	throwpc;
+	t = nl->type;
+	a = optoas(OHMUL, t);
+	// gen nl in n1.
+	tempname(&n1, t);
+	cgen(nl, &n1);
+	// gen nr in n2.
+	regalloc(&n2, t, res);
+	cgen(nr, &n2);
+
+	// multiply.
+	nodreg(&ax, t, D_AX);
+	gmove(&n2, &ax);
+	gins(a, &n1, N);
+	regfree(&n2);
 
-// We're only going to bother inlining if we can
-// convert all the arguments to 32 bits safely.  Can we?
-static int
-fix64(NodeList *nn, int n)
-{
-	NodeList *l;
-	Node *r;
-	int i;
-	
-	l = nn;
-	for(i=0; i<n; i++) {
-		r = l->n->right;
-		if(is64(r->type) && !smallintconst(r)) {
-			if(r->op == OCONV)
-				r = r->left;
-			if(is64(r->type))
-				return 0;
-		}
-		l = l->next;
+	if(t->width == 1) {
+		// byte multiply behaves differently.
+		nodreg(&ax, t, D_AH);
+		nodreg(&dx, t, D_DL);
+		gmove(&ax, &dx);
 	}
-	return 1;
+	nodreg(&dx, t, D_DX);
+	gmove(&dx, res);
 }
 
+static void cgen_float387(Node *n, Node *res);
+static void cgen_floatsse(Node *n, Node *res);
+
+/*
+ * generate floating-point operation.
+ */
 void
-getargs(NodeList *nn, Node *reg, int n)
+cgen_float(Node *n, Node *res)
 {
-	NodeList *l;
-	Node *r;
-	int i;
-
-	throwpc = nil;
-
-	l = nn;
-	for(i=0; i<n; i++) {
-		r = l->n->right;
-		if(is64(r->type)) {
-			if(r->op == OCONV)
-				r = r->left;
-			else if(smallintconst(r))
-				r->type = types[TUINT32];
-			if(is64(r->type))
-				fatal("getargs");
+	Node *nl;
+	Node n1, n2;
+	Prog *p1, *p2, *p3;
+
+	nl = n->left;
+	switch(n->op) {
+	case OEQ:
+	case ONE:
+	case OLT:
+	case OLE:
+	case OGE:
+		p1 = gbranch(AJMP, T, 0);
+		p2 = pc;
+		gmove(nodbool(1), res);
+		p3 = gbranch(AJMP, T, 0);
+		patch(p1, pc);
+		bgen(n, 1, 0, p2);
+		gmove(nodbool(0), res);
+		patch(p3, pc);
+		return;
+
+	case OPLUS:
+		cgen(nl, res);
+		return;
+
+	case OCONV:
+		if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
+			cgen(nl, res);
+			return;
 		}
-		if(!smallintconst(r) && !isslice(r->type)) {
-			if(i < 3)	// AX CX DX
-				nodreg(reg+i, r->type, D_AX+i);
-			else
-				reg[i].op = OXXX;
-			regalloc(reg+i, r->type, reg+i);
-			cgen(r, reg+i);
-		} else
-			reg[i] = *r;
-		if(reg[i].local != 0)
-			yyerror("local used");
-		reg[i].local = l->n->left->xoffset;
-		l = l->next;
+
+		tempname(&n2, n->type);
+		mgen(nl, &n1, res);
+		gmove(&n1, &n2);
+		gmove(&n2, res);
+		mfree(&n1);
+		return;
 	}
-	qsort((void*)reg, n, sizeof(*reg), regcmp);
-	for(i=0; i<n; i++)
-		reg[i].local = 0;
+
+	if(use_sse)
+		cgen_floatsse(n, res);
+	else
+		cgen_float387(n, res);
 }
 
-void
-cmpandthrow(Node *nl, Node *nr)
+// floating-point.  387 (not SSE2)
+static void
+cgen_float387(Node *n, Node *res)
 {
-	vlong cl;
-	Prog *p1;
-	int op;
-	Node *c, n1;
-	Type *t;
+	Node f0, f1;
+	Node *nl, *nr;
 
-	op = OLE;
-	if(smallintconst(nl)) {
-		cl = mpgetfix(nl->val.u.xval);
-		if(cl == 0)
-			return;
-		if(smallintconst(nr))
-			return;
-		// put the constant on the right
-		op = brrev(op);
-		c = nl;
-		nl = nr;
-		nr = c;
-	}
-	
-	// Arguments are known not to be 64-bit,
-	// but they might be smaller than 32 bits.
-	// Check if we need to use a temporary.
-	// At least one of the arguments is 32 bits
-	// (the len or cap) so one temporary suffices.
-	n1.op = OXXX;
-	t = types[TUINT32];
-	if(nl->type->width != t->width) {
-		regalloc(&n1, t, nl);
-		gmove(nl, &n1);
-		nl = &n1;
-	} else if(nr->type->width != t->width) {
-		regalloc(&n1, t, nr);
-		gmove(nr, &n1);
-		nr = &n1;
-	}
-	gins(optoas(OCMP, t), nl, nr);
-	if(n1.op != OXXX)
-		regfree(&n1);
-	if(throwpc == nil) {
-		p1 = gbranch(optoas(op, t), T);
-		throwpc = pc;
-		ginscall(panicslice, 0);
-		patch(p1, pc);
+	nl = n->left;
+	nr = n->right;
+	nodreg(&f0, nl->type, D_F0);
+	nodreg(&f1, n->type, D_F0+1);
+	if(nr != N)
+		goto flt2;
+
+	// unary
+	cgen(nl, &f0);
+	if(n->op != OCONV && n->op != OPLUS)
+		gins(foptoas(n->op, n->type, 0), N, N);
+	gmove(&f0, res);
+	return;
+
+flt2:	// binary
+	if(nl->ullman >= nr->ullman) {
+		cgen(nl, &f0);
+		if(nr->addable)
+			gins(foptoas(n->op, n->type, 0), nr, &f0);
+		else {
+			cgen(nr, &f0);
+			gins(foptoas(n->op, n->type, Fpop), &f0, &f1);
+		}
 	} else {
-		op = brcom(op);
-		p1 = gbranch(optoas(op, t), T);
-		patch(p1, throwpc);
+		cgen(nr, &f0);
+		if(nl->addable)
+			gins(foptoas(n->op, n->type, Frev), nl, &f0);
+		else {
+			cgen(nl, &f0);
+			gins(foptoas(n->op, n->type, Frev|Fpop), &f0, &f1);
+		}
 	}
-}
+	gmove(&f0, res);
+	return;
 
-int
-sleasy(Node *n)
-{
-	if(n->op != ONAME)
-		return 0;
-	if(!n->addable)
-		return 0;
-	return 1;
 }
 
-// generate inline code for
-//	slicearray
-//	sliceslice
-//	arraytoslice
-int
-cgen_inline(Node *n, Node *res)
+static void
+cgen_floatsse(Node *n, Node *res)
 {
-	Node nodes[5];
-	Node n1, n2, nres, ntemp;
-	vlong v;
-	int i, narg, nochk;
-
-	if(n->op != OCALLFUNC)
-		goto no;
-	if(!n->left->addable)
-		goto no;
-	if(n->left->sym == S)
-		goto no;
-	if(n->left->sym->pkg != runtimepkg)
-		goto no;
-	if(strcmp(n->left->sym->name, "slicearray") == 0)
-		goto slicearray;
-	if(strcmp(n->left->sym->name, "sliceslice") == 0) {
-		narg = 4;
-		goto sliceslice;
-	}
-	if(strcmp(n->left->sym->name, "sliceslice1") == 0) {
-		narg = 3;
-		goto sliceslice;
-	}
-	goto no;
-
-slicearray:
-	if(!sleasy(res))
-		goto no;
-	if(!fix64(n->list, 5))
-		goto no;
-	getargs(n->list, nodes, 5);
-
-	// if(hb[3] > nel[1]) goto throw
-	cmpandthrow(&nodes[3], &nodes[1]);
-
-	// if(lb[2] > hb[3]) goto throw
-	cmpandthrow(&nodes[2], &nodes[3]);
-
-	// len = hb[3] - lb[2] (destroys hb)
-	n2 = *res;
-	n2.xoffset += Array_nel;
-	n2.type = types[TUINT32];
-
-	if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) {
-		v = mpgetfix(nodes[3].val.u.xval) -
-			mpgetfix(nodes[2].val.u.xval);
-		nodconst(&n1, types[TUINT32], v);
-		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-	} else {
-		regalloc(&n1, types[TUINT32], &nodes[3]);
-		gmove(&nodes[3], &n1);
-		if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
-			gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
-		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-		regfree(&n1);
-	}
+	Node *nl, *nr, *r;
+	Node n1, n2, nt;
+	int a;
 
-	// cap = nel[1] - lb[2] (destroys nel)
-	n2 = *res;
-	n2.xoffset += Array_cap;
-	n2.type = types[TUINT32];
+	nl = n->left;
+	nr = n->right;
+	switch(n->op) {
+	default:
+		dump("cgen_floatsse", n);
+		fatal("cgen_floatsse %O", n->op);
+		return;
 
-	if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) {
-		v = mpgetfix(nodes[1].val.u.xval) -
-			mpgetfix(nodes[2].val.u.xval);
-		nodconst(&n1, types[TUINT32], v);
-		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-	} else {
-		regalloc(&n1, types[TUINT32], &nodes[1]);
-		gmove(&nodes[1], &n1);
-		if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
-			gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
-		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-		regfree(&n1);
+	case OMINUS:
+	case OCOM:
+		nr = nodintconst(-1);
+		convlit(&nr, n->type);
+		a = foptoas(OMUL, nl->type, 0);
+		goto sbop;
+
+	// symmetric binary
+	case OADD:
+	case OMUL:
+		a = foptoas(n->op, nl->type, 0);
+		goto sbop;
+
+	// asymmetric binary
+	case OSUB:
+	case OMOD:
+	case ODIV:
+		a = foptoas(n->op, nl->type, 0);
+		goto abop;
 	}
 
-	// if slice could be too big, dereference to
-	// catch nil array pointer.
-	if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
-		n2 = nodes[0];
-		n2.xoffset = 0;
-		n2.op = OINDREG;
-		n2.type = types[TUINT8];
-		gins(ATESTB, nodintconst(0), &n2);
+sbop:	// symmetric binary
+	if(nl->ullman < nr->ullman || nl->op == OLITERAL) {
+		r = nl;
+		nl = nr;
+		nr = r;
 	}
 
-	// ary = old[0] + (lb[2] * width[4]) (destroys old)
-	n2 = *res;
-	n2.xoffset += Array_array;
-	n2.type = types[tptr];
-
-	if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) {
-		v = mpgetfix(nodes[2].val.u.xval) *
-			mpgetfix(nodes[4].val.u.xval);
-		if(v != 0) {
-			nodconst(&n1, types[tptr], v);
-			gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
-		}
+abop:	// asymmetric binary
+	if(nl->ullman >= nr->ullman) {
+		tempname(&nt, nl->type);
+		cgen(nl, &nt);
+		mgen(nr, &n2, N);
+		regalloc(&n1, nl->type, res);
+		gmove(&nt, &n1);
+		gins(a, &n2, &n1);
+		gmove(&n1, res);
+		regfree(&n1);
+		mfree(&n2);
 	} else {
-		regalloc(&n1, types[tptr], &nodes[2]);
-		gmove(&nodes[2], &n1);
-		if(!smallintconst(&nodes[4]) || mpgetfix(nodes[4].val.u.xval) != 1)
-			gins(optoas(OMUL, types[tptr]), &nodes[4], &n1);
-		gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
+		regalloc(&n2, nr->type, res);
+		cgen(nr, &n2);
+		regalloc(&n1, nl->type, N);
+		cgen(nl, &n1);
+		gins(a, &n2, &n1);
+		regfree(&n2);
+		gmove(&n1, res);
 		regfree(&n1);
 	}
-	gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
-
-	for(i=0; i<5; i++) {
-		if(nodes[i].op == OREGISTER)
-			regfree(&nodes[i]);
-	}
-	return 1;
+	return;
+}
 
-sliceslice:
-	if(!fix64(n->list, narg))
-		goto no;
-	nochk = n->etype;  // skip bounds checking
-	ntemp.op = OXXX;
-	if(!sleasy(n->list->n->right)) {
-		Node *n0;
-		
-		n0 = n->list->n->right;
-		tempname(&ntemp, res->type);
-		cgen(n0, &ntemp);
-		n->list->n->right = &ntemp;
-		getargs(n->list, nodes, narg);
-		n->list->n->right = n0;
-	} else
-		getargs(n->list, nodes, narg);
+void
+bgen_float(Node *n, int true, int likely, Prog *to)
+{
+	int et, a;
+	Node *nl, *nr, *r;
+	Node n1, n2, n3, tmp, t1, t2, ax;
+	Prog *p1, *p2;
 
-	nres = *res;		// result
-	if(!sleasy(res)) {
-		if(ntemp.op == OXXX)
-			tempname(&ntemp, res->type);
-		nres = ntemp;
+	nl = n->left;
+	nr = n->right;
+	a = n->op;
+	if(!true) {
+		// brcom is not valid on floats when NaN is involved.
+		p1 = gbranch(AJMP, T, 0);
+		p2 = gbranch(AJMP, T, 0);
+		patch(p1, pc);
+		// No need to avoid re-genning ninit.
+		bgen_float(n, 1, -likely, p2);
+		patch(gbranch(AJMP, T, 0), to);
+		patch(p2, pc);
+		return;
 	}
 
-	if(narg == 3) {	// old[lb:]
-		// move width to where it would be for old[lb:hb]
-		nodes[3] = nodes[2];
-		nodes[2].op = OXXX;
-		
-		// if(lb[1] > old.nel[0]) goto throw;
-		n2 = nodes[0];
-		n2.xoffset += Array_nel;
-		n2.type = types[TUINT32];
-		if(!nochk)
-			cmpandthrow(&nodes[1], &n2);
-
-		// ret.nel = old.nel[0]-lb[1];
-		n2 = nodes[0];
-		n2.xoffset += Array_nel;
-		n2.type = types[TUINT32];
-	
-		regalloc(&n1, types[TUINT32], N);
-		gins(optoas(OAS, types[TUINT32]), &n2, &n1);
-		if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
-			gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
-	
-		n2 = nres;
-		n2.xoffset += Array_nel;
-		n2.type = types[TUINT32];
-		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-		regfree(&n1);
-	} else {	// old[lb:hb]
-		n2 = nodes[0];
-		n2.xoffset += Array_cap;
-		n2.type = types[TUINT32];
-		if (!nochk) {
-			// if(hb[2] > old.cap[0]) goto throw;
-			cmpandthrow(&nodes[2], &n2);
-			// if(lb[1] > hb[2]) goto throw;
-			cmpandthrow(&nodes[1], &nodes[2]);
-		}
-
-		// ret.len = hb[2]-lb[1]; (destroys hb[2])
-		n2 = nres;
-		n2.xoffset += Array_nel;
-		n2.type = types[TUINT32];
-
-		if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) {
-			v = mpgetfix(nodes[2].val.u.xval) -
-				mpgetfix(nodes[1].val.u.xval);
-			nodconst(&n1, types[TUINT32], v);
-			gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-		} else {
-			regalloc(&n1, types[TUINT32], &nodes[2]);
-			gmove(&nodes[2], &n1);
-			if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
-				gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
-			gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-			regfree(&n1);
-		}
+	if(use_sse)
+		goto sse;
+	else
+		goto x87;
+
+x87:
+	a = brrev(a);	// because the args are stacked
+	if(a == OGE || a == OGT) {
+		// only < and <= work right with NaN; reverse if needed
+		r = nr;
+		nr = nl;
+		nl = r;
+		a = brrev(a);
 	}
 
-	// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
-	n2 = nodes[0];
-	n2.xoffset += Array_cap;
-	n2.type = types[TUINT32];
-
-	regalloc(&n1, types[TUINT32], &nodes[2]);
-	gins(optoas(OAS, types[TUINT32]), &n2, &n1);
-	if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
-		gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
-
-	n2 = nres;
-	n2.xoffset += Array_cap;
-	n2.type = types[TUINT32];
-	gins(optoas(OAS, types[TUINT32]), &n1, &n2);
-	regfree(&n1);
-
-	// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
-	n2 = nodes[0];
-	n2.xoffset += Array_array;
-	n2.type = types[tptr];
-
-	regalloc(&n1, types[tptr], &nodes[1]);
-	if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) {
-		gins(optoas(OAS, types[tptr]), &n2, &n1);
-		v = mpgetfix(nodes[1].val.u.xval) *
-			mpgetfix(nodes[3].val.u.xval);
-		if(v != 0) {
-			nodconst(&n2, types[tptr], v);
-			gins(optoas(OADD, types[tptr]), &n2, &n1);
+	nodreg(&tmp, nr->type, D_F0);
+	nodreg(&n2, nr->type, D_F0 + 1);
+	nodreg(&ax, types[TUINT16], D_AX);
+	et = simsimtype(nr->type);
+	if(et == TFLOAT64) {
+		if(nl->ullman > nr->ullman) {
+			cgen(nl, &tmp);
+			cgen(nr, &tmp);
+			gins(AFXCHD, &tmp, &n2);
+		} else {
+			cgen(nr, &tmp);
+			cgen(nl, &tmp);
 		}
+		gins(AFUCOMIP, &tmp, &n2);
+		gins(AFMOVDP, &tmp, &tmp);	// annoying pop but still better than STSW+SAHF
 	} else {
-		gmove(&nodes[1], &n1);
-		if(!smallintconst(&nodes[3]) || mpgetfix(nodes[3].val.u.xval) != 1)
-			gins(optoas(OMUL, types[tptr]), &nodes[3], &n1);
-		gins(optoas(OADD, types[tptr]), &n2, &n1);
+		// TODO(rsc): The moves back and forth to memory
+		// here are for truncating the value to 32 bits.
+		// This handles 32-bit comparison but presumably
+		// all the other ops have the same problem.
+		// We need to figure out what the right general
+		// solution is, besides telling people to use float64.
+		tempname(&t1, types[TFLOAT32]);
+		tempname(&t2, types[TFLOAT32]);
+		cgen(nr, &t1);
+		cgen(nl, &t2);
+		gmove(&t2, &tmp);
+		gins(AFCOMFP, &t1, &tmp);
+		gins(AFSTSW, N, &ax);
+		gins(ASAHF, N, N);
 	}
 
-	n2 = nres;
-	n2.xoffset += Array_array;
-	n2.type = types[tptr];
-	gins(optoas(OAS, types[tptr]), &n1, &n2);
-	regfree(&n1);
+	goto ret;
 
-	for(i=0; i<4; i++) {
-		if(nodes[i].op == OREGISTER)
-			regfree(&nodes[i]);
+sse:
+	if(!nl->addable) {
+		tempname(&n1, nl->type);
+		cgen(nl, &n1);
+		nl = &n1;
+	}
+	if(!nr->addable) {
+		tempname(&tmp, nr->type);
+		cgen(nr, &tmp);
+		nr = &tmp;
+	}
+	regalloc(&n2, nr->type, N);
+	gmove(nr, &n2);
+	nr = &n2;
+
+	if(nl->op != OREGISTER) {
+		regalloc(&n3, nl->type, N);
+		gmove(nl, &n3);
+		nl = &n3;
 	}
 
-	if(!sleasy(res)) {
-		cgen(&nres, res);
+	if(a == OGE || a == OGT) {
+		// only < and <= work right with NaN; reverse if needed
+		r = nr;
+		nr = nl;
+		nl = r;
+		a = brrev(a);
 	}
-	return 1;
 
-no:
-	return 0;
+	gins(foptoas(OCMP, nr->type, 0), nl, nr);
+	if(nl->op == OREGISTER)
+		regfree(nl);
+	regfree(nr);
+
+ret:
+	if(a == OEQ) {
+		// neither NE nor P
+		p1 = gbranch(AJNE, T, -likely);
+		p2 = gbranch(AJPS, T, -likely);
+		patch(gbranch(AJMP, T, 0), to);
+		patch(p1, pc);
+		patch(p2, pc);
+	} else if(a == ONE) {
+		// either NE or P
+		patch(gbranch(AJNE, T, likely), to);
+		patch(gbranch(AJPS, T, likely), to);
+	} else
+		patch(gbranch(optoas(a, nr->type), T, likely), to);
+
 }
diff --git a/src/cmd/8g/gobj.c b/src/cmd/8g/gobj.c
index da0055c..39717d5 100644
--- a/src/cmd/8g/gobj.c
+++ b/src/cmd/8g/gobj.c
@@ -94,9 +94,9 @@ zaddr(Biobuf *b, Addr *a, int s, int gotype)
 	switch(a->type) {
 
 	case D_BRANCH:
-		if(a->branch == nil)
+		if(a->u.branch == nil)
 			fatal("unpatched branch");
-		a->offset = a->branch->loc;
+		a->offset = a->u.branch->loc;
 
 	default:
 		t |= T_TYPE;
@@ -137,7 +137,7 @@ zaddr(Biobuf *b, Addr *a, int s, int gotype)
 	if(t & T_SYM)		/* implies sym */
 		Bputc(b, s);
 	if(t & T_FCONST) {
-		ieeedtod(&e, a->dval);
+		ieeedtod(&e, a->u.dval);
 		l = e;
 		Bputc(b, l);
 		Bputc(b, l>>8);
@@ -151,7 +151,7 @@ zaddr(Biobuf *b, Addr *a, int s, int gotype)
 		return;
 	}
 	if(t & T_SCONST) {
-		n = a->sval;
+		n = a->u.sval;
 		for(i=0; i<NSNAME; i++) {
 			Bputc(b, *n);
 			n++;
@@ -293,7 +293,7 @@ dsname(Sym *s, int off, char *t, int n)
 	
 	p->to.type = D_SCONST;
 	p->to.index = D_NONE;
-	memmove(p->to.sval, t, n);
+	memmove(p->to.u.sval, t, n);
 	return off + n;
 }
 
@@ -373,13 +373,13 @@ gdatacomplex(Node *nam, Mpcplx *cval)
 	p = gins(ADATA, nam, N);
 	p->from.scale = w;
 	p->to.type = D_FCONST;
-	p->to.dval = mpgetflt(&cval->real);
+	p->to.u.dval = mpgetflt(&cval->real);
 
 	p = gins(ADATA, nam, N);
 	p->from.scale = w;
 	p->from.offset += w;
 	p->to.type = D_FCONST;
-	p->to.dval = mpgetflt(&cval->imag);
+	p->to.u.dval = mpgetflt(&cval->imag);
 }
 
 void
diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c
index 5e89af0..c4c184b 100644
--- a/src/cmd/8g/gsubr.c
+++ b/src/cmd/8g/gsubr.c
@@ -105,16 +105,24 @@ dumpdata(void)
 /*
  * generate a branch.
  * t is ignored.
+ * likely values are for branch prediction:
+ *	-1 unlikely
+ *	0 no opinion
+ *	+1 likely
  */
 Prog*
-gbranch(int as, Type *t)
+gbranch(int as, Type *t, int likely)
 {
 	Prog *p;
 
 	USED(t);
 	p = prog(as);
 	p->to.type = D_BRANCH;
-	p->to.branch = P;
+	p->to.u.branch = P;
+	if(likely != 0) {
+		p->from.type = D_CONST;
+		p->from.offset = likely > 0;
+	}
 	return p;
 }
 
@@ -126,7 +134,7 @@ patch(Prog *p, Prog *to)
 {
 	if(p->to.type != D_BRANCH)
 		fatal("patch: not a branch");
-	p->to.branch = to;
+	p->to.u.branch = to;
 	p->to.offset = to->loc;
 }
 
@@ -137,8 +145,8 @@ unpatch(Prog *p)
 
 	if(p->to.type != D_BRANCH)
 		fatal("unpatch: not a branch");
-	q = p->to.branch;
-	p->to.branch = P;
+	q = p->to.u.branch;
+	p->to.u.branch = P;
 	p->to.offset = 0;
 	return q;
 }
@@ -166,44 +174,6 @@ newplist(void)
 }
 
 void
-clearstk(void)
-{
-	Plist *pl;
-	Prog *p1, *p2;
-	Node sp, di, cx, con, ax;
-
-	if(plast->firstpc->to.offset <= 0)
-		return;
-
-	// reestablish context for inserting code
-	// at beginning of function.
-	pl = plast;
-	p1 = pl->firstpc;
-	p2 = p1->link;
-	pc = mal(sizeof(*pc));
-	clearp(pc);
-	p1->link = pc;
-	
-	// zero stack frame
-	nodreg(&sp, types[tptr], D_SP);
-	nodreg(&di, types[tptr], D_DI);
-	nodreg(&cx, types[TUINT32], D_CX);
-	nodconst(&con, types[TUINT32], p1->to.offset / widthptr);
-	gins(ACLD, N, N);
-	gins(AMOVL, &sp, &di);
-	gins(AMOVL, &con, &cx);
-	nodconst(&con, types[TUINT32], 0);
-	nodreg(&ax, types[TUINT32], D_AX);
-	gins(AMOVL, &con, &ax);
-	gins(AREP, N, N);
-	gins(ASTOSL, N, N);
-
-	// continue with original code.
-	gins(ANOP, N, N)->link = p2;
-	pc = P;
-}	
-
-void
 gused(Node *n)
 {
 	gins(ANOP, n, N);	// used
@@ -214,22 +184,23 @@ gjmp(Prog *to)
 {
 	Prog *p;
 
-	p = gbranch(AJMP, T);
+	p = gbranch(AJMP, T, 0);
 	if(to != P)
 		patch(p, to);
 	return p;
 }
 
 void
-ggloblnod(Node *nam, int32 width)
+ggloblnod(Node *nam)
 {
 	Prog *p;
 
 	p = gins(AGLOBL, nam, N);
 	p->lineno = nam->lineno;
+	p->from.gotype = ngotype(nam);
 	p->to.sym = S;
 	p->to.type = D_CONST;
-	p->to.offset = width;
+	p->to.offset = nam->type->width;
 	if(nam->readonly)
 		p->from.scale = RODATA;
 	if(nam->type != T && !haspointers(nam->type))
@@ -237,7 +208,7 @@ ggloblnod(Node *nam, int32 width)
 }
 
 void
-ggloblsym(Sym *s, int32 width, int dupok)
+ggloblsym(Sym *s, int32 width, int dupok, int rodata)
 {
 	Prog *p;
 
@@ -249,8 +220,20 @@ ggloblsym(Sym *s, int32 width, int dupok)
 	p->to.index = D_NONE;
 	p->to.offset = width;
 	if(dupok)
-		p->from.scale = DUPOK;
-	p->from.scale |= RODATA;
+		p->from.scale |= DUPOK;
+	if(rodata)
+		p->from.scale |= RODATA;
+}
+
+void
+gtrack(Sym *s)
+{
+	Prog *p;
+	
+	p = gins(AUSEFIELD, N, N);
+	p->from.type = D_EXTERN;
+	p->from.index = D_NONE;
+	p->from.sym = s;
 }
 
 int
@@ -273,11 +256,12 @@ isfat(Type *t)
  * call afunclit to fix up the argument.
  */
 void
-afunclit(Addr *a)
+afunclit(Addr *a, Node *n)
 {
 	if(a->type == D_ADDR && a->index == D_EXTERN) {
 		a->type = D_EXTERN;
 		a->index = D_NONE;
+		a->sym = n->sym;
 	}
 }
 
@@ -572,6 +556,22 @@ optoas(int op, Type *t)
 		a = AXORL;
 		break;
 
+	case CASE(OLROT, TINT8):
+	case CASE(OLROT, TUINT8):
+		a = AROLB;
+		break;
+
+	case CASE(OLROT, TINT16):
+	case CASE(OLROT, TUINT16):
+		a = AROLW;
+		break;
+
+	case CASE(OLROT, TINT32):
+	case CASE(OLROT, TUINT32):
+	case CASE(OLROT, TPTR32):
+		a = AROLL;
+		break;
+
 	case CASE(OLSH, TINT8):
 	case CASE(OLSH, TUINT8):
 		a = ASHLB;
@@ -613,22 +613,38 @@ optoas(int op, Type *t)
 		a = ASARL;
 		break;
 
+	case CASE(OHMUL, TINT8):
 	case CASE(OMUL, TINT8):
 	case CASE(OMUL, TUINT8):
 		a = AIMULB;
 		break;
 
+	case CASE(OHMUL, TINT16):
 	case CASE(OMUL, TINT16):
 	case CASE(OMUL, TUINT16):
 		a = AIMULW;
 		break;
 
+	case CASE(OHMUL, TINT32):
 	case CASE(OMUL, TINT32):
 	case CASE(OMUL, TUINT32):
 	case CASE(OMUL, TPTR32):
 		a = AIMULL;
 		break;
 
+	case CASE(OHMUL, TUINT8):
+		a = AMULB;
+		break;
+
+	case CASE(OHMUL, TUINT16):
+		a = AMULW;
+		break;
+
+	case CASE(OHMUL, TUINT32):
+	case CASE(OHMUL, TPTR32):
+		a = AMULL;
+		break;
+
 	case CASE(ODIV, TINT8):
 	case CASE(OMOD, TINT8):
 		a = AIDIVB;
@@ -676,10 +692,14 @@ optoas(int op, Type *t)
 int
 foptoas(int op, Type *t, int flg)
 {
-	int et;
+	int et, a;
 
+	a = AGOK;
 	et = simtype[t->etype];
 
+	if(use_sse)
+		goto sse;
+
 	// If we need Fpop, it means we're working on
 	// two different floating-point registers, not memory.
 	// There the instruction only has a float64 form.
@@ -756,8 +776,65 @@ foptoas(int op, Type *t, int flg)
 
 	fatal("foptoas %O %T %#x", op, t, flg);
 	return 0;
+
+sse:
+	switch(CASE(op, et)) {
+	default:
+		fatal("foptoas-sse: no entry %O-%T", op, t);
+		break;
+
+	case CASE(OCMP, TFLOAT32):
+		a = AUCOMISS;
+		break;
+
+	case CASE(OCMP, TFLOAT64):
+		a = AUCOMISD;
+		break;
+
+	case CASE(OAS, TFLOAT32):
+		a = AMOVSS;
+		break;
+
+	case CASE(OAS, TFLOAT64):
+		a = AMOVSD;
+		break;
+
+	case CASE(OADD, TFLOAT32):
+		a = AADDSS;
+		break;
+
+	case CASE(OADD, TFLOAT64):
+		a = AADDSD;
+		break;
+
+	case CASE(OSUB, TFLOAT32):
+		a = ASUBSS;
+		break;
+
+	case CASE(OSUB, TFLOAT64):
+		a = ASUBSD;
+		break;
+
+	case CASE(OMUL, TFLOAT32):
+		a = AMULSS;
+		break;
+
+	case CASE(OMUL, TFLOAT64):
+		a = AMULSD;
+		break;
+
+	case CASE(ODIV, TFLOAT32):
+		a = ADIVSS;
+		break;
+
+	case CASE(ODIV, TFLOAT64):
+		a = ADIVSD;
+		break;
+	}
+	return a;
 }
 
+
 static	int	resvd[] =
 {
 //	D_DI,	// for movstring
@@ -779,7 +856,9 @@ ginit(void)
 
 	for(i=0; i<nelem(reg); i++)
 		reg[i] = 1;
-	for(i=D_AL; i<=D_DI; i++)
+	for(i=D_AX; i<=D_DI; i++)
+		reg[i] = 0;
+	for(i=D_X0; i<=D_X7; i++)
 		reg[i] = 0;
 	for(i=0; i<nelem(resvd); i++)
 		reg[resvd[i]]++;
@@ -795,9 +874,12 @@ gclean(void)
 	for(i=0; i<nelem(resvd); i++)
 		reg[resvd[i]]--;
 
-	for(i=D_AL; i<=D_DI; i++)
+	for(i=D_AX; i<=D_DI; i++)
 		if(reg[i])
 			yyerror("reg %R left allocated at %ux", i, regpc[i]);
+	for(i=D_X0; i<=D_X7; i++)
+		if(reg[i])
+			yyerror("reg %R left allocated\n", i);
 }
 
 int32
@@ -805,7 +887,7 @@ anyregalloc(void)
 {
 	int i, j;
 
-	for(i=D_AL; i<=D_DI; i++) {
+	for(i=D_AX; i<=D_DI; i++) {
 		if(reg[i] == 0)
 			goto ok;
 		for(j=0; j<nelem(resvd); j++)
@@ -814,6 +896,9 @@ anyregalloc(void)
 		return 1;
 	ok:;
 	}
+	for(i=D_X0; i<=D_X7; i++)
+		if(reg[i])
+			return 1;
 	return 0;
 }
 
@@ -832,14 +917,16 @@ regalloc(Node *n, Type *t, Node *o)
 	et = simtype[t->etype];
 
 	switch(et) {
+	case TINT64:
+	case TUINT64:
+		fatal("regalloc64");
+
 	case TINT8:
 	case TUINT8:
 	case TINT16:
 	case TUINT16:
 	case TINT32:
 	case TUINT32:
-	case TINT64:
-	case TUINT64:
 	case TPTR32:
 	case TPTR64:
 	case TBOOL:
@@ -860,8 +947,22 @@ regalloc(Node *n, Type *t, Node *o)
 
 	case TFLOAT32:
 	case TFLOAT64:
-		i = D_F0;
-		goto out;
+		if(!use_sse) {
+			i = D_F0;
+			goto out;
+		}
+		if(o != N && o->op == OREGISTER) {
+			i = o->val.u.reg;
+			if(i >= D_X0 && i <= D_X7)
+				goto out;
+		}
+		for(i=D_X0; i<=D_X7; i++)
+			if(reg[i] == 0)
+				goto out;
+		fprint(2, "registers allocated at\n");
+		for(i=D_X0; i<=D_X7; i++)
+			fprint(2, "\t%R\t%#lux\n", i, regpc[i]);
+		fatal("out of floating registers");
 	}
 	yyerror("regalloc: unknown type %T", t);
 
@@ -1069,9 +1170,9 @@ split64(Node *n, Node *lo, Node *hi)
 	if(!is64(n->type))
 		fatal("split64 %T", n->type);
 
-	sclean[nsclean].op = OEMPTY;
 	if(nsclean >= nelem(sclean))
 		fatal("split64 clean");
+	sclean[nsclean].op = OEMPTY;
 	nsclean++;
 	switch(n->op) {
 	default:
@@ -1165,13 +1266,16 @@ memname(Node *n, Type *t)
 	n->orig->sym = n->sym;
 }
 
+static void floatmove(Node *f, Node *t);
+static void floatmove_387(Node *f, Node *t);
+static void floatmove_sse(Node *f, Node *t);
+
 void
 gmove(Node *f, Node *t)
 {
 	int a, ft, tt;
 	Type *cvt;
-	Node r1, r2, t1, t2, flo, fhi, tlo, thi, con, f0, f1, ax, dx, cx;
-	Prog *p1, *p2, *p3;
+	Node r1, r2, flo, fhi, tlo, thi, con;
 
 	if(debug['M'])
 		print("gmove %N -> %N\n", f, t);
@@ -1179,11 +1283,15 @@ gmove(Node *f, Node *t)
 	ft = simsimtype(f->type);
 	tt = simsimtype(t->type);
 	cvt = t->type;
-
+	
 	if(iscomplex[ft] || iscomplex[tt]) {
 		complexmove(f, t);
 		return;
 	}
+	if(isfloat[ft] || isfloat[tt]) {
+		floatmove(f, t);
+		return;
+	}
 
 	// cannot have two integer memory operands;
 	// except 64-bit, which always copies via registers anyway.
@@ -1192,19 +1300,9 @@ gmove(Node *f, Node *t)
 
 	// convert constant to desired type
 	if(f->op == OLITERAL) {
-		if(tt == TFLOAT32)
-			convconst(&con, types[TFLOAT64], &f->val);
-		else
-			convconst(&con, t->type, &f->val);
+		convconst(&con, t->type, &f->val);
 		f = &con;
 		ft = simsimtype(con.type);
-
-		// some constants can't move directly to memory.
-		if(ismem(t)) {
-			// float constants come from memory.
-			if(isfloat[tt])
-				goto hard;
-		}
 	}
 
 	// value -> value copy, only one memory operand.
@@ -1380,25 +1478,97 @@ gmove(Node *f, Node *t)
 		gins(AMOVL, ncon(0), &thi);
 		splitclean();
 		return;
+	}
 
-	/*
-	* float to integer
-	*/
-	case CASE(TFLOAT32, TINT16):
-	case CASE(TFLOAT32, TINT32):
+	gins(a, f, t);
+	return;
+
+rsrc:
+	// requires register source
+	regalloc(&r1, f->type, t);
+	gmove(f, &r1);
+	gins(a, &r1, t);
+	regfree(&r1);
+	return;
+
+rdst:
+	// requires register destination
+	regalloc(&r1, t->type, t);
+	gins(a, f, &r1);
+	gmove(&r1, t);
+	regfree(&r1);
+	return;
+
+hard:
+	// requires register intermediate
+	regalloc(&r1, cvt, t);
+	gmove(f, &r1);
+	gmove(&r1, t);
+	regfree(&r1);
+	return;
+
+fatal:
+	// should not happen
+	fatal("gmove %N -> %N", f, t);
+}
+
+static void
+floatmove(Node *f, Node *t)
+{
+	Node r1, r2, t1, t2, tlo, thi, con, f0, f1, ax, dx, cx;
+	Type *cvt;
+	int ft, tt;
+	Prog *p1, *p2, *p3;
+
+	ft = simsimtype(f->type);
+	tt = simsimtype(t->type);
+	cvt = t->type;
+
+	// cannot have two floating point memory operands.
+	if(isfloat[ft] && isfloat[tt] && ismem(f) && ismem(t))
+		goto hard;
+
+	// convert constant to desired type
+	if(f->op == OLITERAL) {
+		convconst(&con, t->type, &f->val);
+		f = &con;
+		ft = simsimtype(con.type);
+
+		// some constants can't move directly to memory.
+		if(ismem(t)) {
+			// float constants come from memory.
+			if(isfloat[tt])
+				goto hard;
+		}
+	}
+
+	// value -> value copy, only one memory operand.
+	// figure out the instruction to use.
+	// break out of switch for one-instruction gins.
+	// goto rdst for "destination must be register".
+	// goto hard for "convert to cvt type first".
+	// otherwise handle and return.
+
+	switch(CASE(ft, tt)) {
+	default:
+		if(use_sse)
+			floatmove_sse(f, t);
+		else
+			floatmove_387(f, t);
+		return;
+
+	// float to very long integer.
 	case CASE(TFLOAT32, TINT64):
-	case CASE(TFLOAT64, TINT16):
-	case CASE(TFLOAT64, TINT32):
 	case CASE(TFLOAT64, TINT64):
-		if(t->op == OREGISTER)
+		if(f->op == OREGISTER) {
+			cvt = f->type;
 			goto hardmem;
-		nodreg(&r1, types[ft], D_F0);
-		if(f->op != OREGISTER) {
-			if(ft == TFLOAT32)
-				gins(AFMOVF, f, &r1);
-			else
-				gins(AFMOVD, f, &r1);
 		}
+		nodreg(&r1, types[ft], D_F0);
+		if(ft == TFLOAT32)
+			gins(AFMOVF, f, &r1);
+		else
+			gins(AFMOVD, f, &r1);
 
 		// set round to zero mode during conversion
 		memname(&t1, types[TUINT16]);
@@ -1415,85 +1585,37 @@ gmove(Node *f, Node *t)
 		gins(AFLDCW, &t1, N);
 		return;
 
-	case CASE(TFLOAT32, TINT8):
-	case CASE(TFLOAT32, TUINT16):
-	case CASE(TFLOAT32, TUINT8):
-	case CASE(TFLOAT64, TINT8):
-	case CASE(TFLOAT64, TUINT16):
-	case CASE(TFLOAT64, TUINT8):
-		// convert via int32.
-		tempname(&t1, types[TINT32]);
-		gmove(f, &t1);
-		switch(tt) {
-		default:
-			fatal("gmove %T", t);
-		case TINT8:
-			gins(ACMPL, &t1, ncon(-0x80));
-			p1 = gbranch(optoas(OLT, types[TINT32]), T);
-			gins(ACMPL, &t1, ncon(0x7f));
-			p2 = gbranch(optoas(OGT, types[TINT32]), T);
-			p3 = gbranch(AJMP, T);
-			patch(p1, pc);
-			patch(p2, pc);
-			gmove(ncon(-0x80), &t1);
-			patch(p3, pc);
-			gmove(&t1, t);
-			break;
-		case TUINT8:
-			gins(ATESTL, ncon(0xffffff00), &t1);
-			p1 = gbranch(AJEQ, T);
-			gins(AMOVL, ncon(0), &t1);
-			patch(p1, pc);
-			gmove(&t1, t);
-			break;
-		case TUINT16:
-			gins(ATESTL, ncon(0xffff0000), &t1);
-			p1 = gbranch(AJEQ, T);
-			gins(AMOVL, ncon(0), &t1);
-			patch(p1, pc);
-			gmove(&t1, t);
-			break;
-		}
-		return;
-
-	case CASE(TFLOAT32, TUINT32):
-	case CASE(TFLOAT64, TUINT32):
-		// convert via int64.
-		tempname(&t1, types[TINT64]);
-		gmove(f, &t1);
-		split64(&t1, &tlo, &thi);
-		gins(ACMPL, &thi, ncon(0));
-		p1 = gbranch(AJEQ, T);
-		gins(AMOVL, ncon(0), &tlo);
-		patch(p1, pc);
-		gmove(&tlo, t);
-		splitclean();
-		return;
-
 	case CASE(TFLOAT32, TUINT64):
 	case CASE(TFLOAT64, TUINT64):
+		if(!ismem(f)) {
+			cvt = f->type;
+			goto hardmem;
+		}
 		bignodes();
 		nodreg(&f0, types[ft], D_F0);
 		nodreg(&f1, types[ft], D_F0 + 1);
 		nodreg(&ax, types[TUINT16], D_AX);
 
-		gmove(f, &f0);
+		if(ft == TFLOAT32)
+			gins(AFMOVF, f, &f0);
+		else
+			gins(AFMOVD, f, &f0);
 
 		// if 0 > v { answer = 0 }
-		gmove(&zerof, &f0);
+		gins(AFMOVD, &zerof, &f0);
 		gins(AFUCOMIP, &f0, &f1);
-		p1 = gbranch(optoas(OGT, types[tt]), T);
+		p1 = gbranch(optoas(OGT, types[tt]), T, 0);
 		// if 1<<64 <= v { answer = 0 too }
-		gmove(&two64f, &f0);
+		gins(AFMOVD, &two64f, &f0);
 		gins(AFUCOMIP, &f0, &f1);
-		p2 = gbranch(optoas(OGT, types[tt]), T);
+		p2 = gbranch(optoas(OGT, types[tt]), T, 0);
 		patch(p1, pc);
 		gins(AFMOVVP, &f0, t);	// don't care about t, but will pop the stack
 		split64(t, &tlo, &thi);
 		gins(AMOVL, ncon(0), &tlo);
 		gins(AMOVL, ncon(0), &thi);
 		splitclean();
-		p1 = gbranch(AJMP, T);
+		p1 = gbranch(AJMP, T, 0);
 		patch(p2, pc);
 
 		// in range; algorithm is:
@@ -1508,13 +1630,13 @@ gmove(Node *f, Node *t)
 		gins(AFLDCW, &t2, N);
 
 		// actual work
-		gmove(&two63f, &f0);
+		gins(AFMOVD, &two63f, &f0);
 		gins(AFUCOMIP, &f0, &f1);
-		p2 = gbranch(optoas(OLE, types[tt]), T);
+		p2 = gbranch(optoas(OLE, types[tt]), T, 0);
 		gins(AFMOVVP, &f0, t);
-		p3 = gbranch(AJMP, T);
+		p3 = gbranch(AJMP, T, 0);
 		patch(p2, pc);
-		gmove(&two63f, &f0);
+		gins(AFMOVD, &two63f, &f0);
 		gins(AFSUBDP, &f0, &f1);
 		gins(AFMOVVP, &f0, t);
 		split64(t, &tlo, &thi);
@@ -1530,51 +1652,22 @@ gmove(Node *f, Node *t)
 	/*
 	 * integer to float
 	 */
-	case CASE(TINT16, TFLOAT32):
-	case CASE(TINT16, TFLOAT64):
-	case CASE(TINT32, TFLOAT32):
-	case CASE(TINT32, TFLOAT64):
 	case CASE(TINT64, TFLOAT32):
 	case CASE(TINT64, TFLOAT64):
-		if(t->op != OREGISTER)
-			goto hard;
-		if(f->op == OREGISTER) {
-			cvt = f->type;
+		if(t->op == OREGISTER)
 			goto hardmem;
-		}
-		switch(ft) {
-		case TINT16:
-			a = AFMOVW;
-			break;
-		case TINT32:
-			a = AFMOVL;
-			break;
-		default:
-			a = AFMOVV;
-			break;
-		}
-		break;
-
-	case CASE(TINT8, TFLOAT32):
-	case CASE(TINT8, TFLOAT64):
-	case CASE(TUINT16, TFLOAT32):
-	case CASE(TUINT16, TFLOAT64):
-	case CASE(TUINT8, TFLOAT32):
-	case CASE(TUINT8, TFLOAT64):
-		// convert via int32 memory
-		cvt = types[TINT32];
-		goto hardmem;
-
-	case CASE(TUINT32, TFLOAT32):
-	case CASE(TUINT32, TFLOAT64):
-		// convert via int64 memory
-		cvt = types[TINT64];
-		goto hardmem;
+		nodreg(&f0, t->type, D_F0);
+		gins(AFMOVV, f, &f0);
+		if(tt == TFLOAT32)
+			gins(AFMOVFP, &f0, t);
+		else
+			gins(AFMOVDP, &f0, t);
+		return;
 
 	case CASE(TUINT64, TFLOAT32):
 	case CASE(TUINT64, TFLOAT64):
 		// algorithm is:
-		//	if small enough, use native int64 -> uint64 conversion.
+		//	if small enough, use native int64 -> float64 conversion.
 		//	otherwise, halve (rounding to odd?), convert, and double.
 		nodreg(&ax, types[TUINT32], D_AX);
 		nodreg(&dx, types[TUINT32], D_DX);
@@ -1583,11 +1676,16 @@ gmove(Node *f, Node *t)
 		split64(&t1, &tlo, &thi);
 		gmove(f, &t1);
 		gins(ACMPL, &thi, ncon(0));
-		p1 = gbranch(AJLT, T);
+		p1 = gbranch(AJLT, T, 0);
 		// native
 		t1.type = types[TINT64];
-		gmove(&t1, t);
-		p2 = gbranch(AJMP, T);
+		nodreg(&r1, types[tt], D_F0);
+		gins(AFMOVV, &t1, &r1);
+		if(tt == TFLOAT32)
+			gins(AFMOVFP, &r1, t);
+		else
+			gins(AFMOVDP, &r1, t);
+		p2 = gbranch(AJMP, T, 0);
 		// simulated
 		patch(p1, pc);
 		gmove(&tlo, &ax);
@@ -1595,20 +1693,182 @@ gmove(Node *f, Node *t)
 		p1 = gins(ASHRL, ncon(1), &ax);
 		p1->from.index = D_DX;	// double-width shift DX -> AX
 		p1->from.scale = 0;
+		gins(AMOVL, ncon(0), &cx);
 		gins(ASETCC, N, &cx);
-		gins(AORB, &cx, &ax);
+		gins(AORL, &cx, &ax);
 		gins(ASHRL, ncon(1), &dx);
 		gmove(&dx, &thi);
 		gmove(&ax, &tlo);
 		nodreg(&r1, types[tt], D_F0);
 		nodreg(&r2, types[tt], D_F0 + 1);
-		gmove(&t1, &r1);	// t1.type is TINT64 now, set above
+		gins(AFMOVV, &t1, &r1);
 		gins(AFMOVD, &r1, &r1);
 		gins(AFADDDP, &r1, &r2);
-		gmove(&r1, t);
+		if(tt == TFLOAT32)
+			gins(AFMOVFP, &r1, t);
+		else
+			gins(AFMOVDP, &r1, t);
 		patch(p2, pc);
 		splitclean();
 		return;
+	}
+
+hard:
+	// requires register intermediate
+	regalloc(&r1, cvt, t);
+	gmove(f, &r1);
+	gmove(&r1, t);
+	regfree(&r1);
+	return;
+
+hardmem:
+	// requires memory intermediate
+	tempname(&r1, cvt);
+	gmove(f, &r1);
+	gmove(&r1, t);
+	return;
+}
+
+static void
+floatmove_387(Node *f, Node *t)
+{
+	Node r1, t1, t2;
+	Type *cvt;
+	Prog *p1, *p2, *p3;
+	int a, ft, tt;
+
+	ft = simsimtype(f->type);
+	tt = simsimtype(t->type);
+	cvt = t->type;
+
+	switch(CASE(ft, tt)) {
+	default:
+		goto fatal;
+
+	/*
+	* float to integer
+	*/
+	case CASE(TFLOAT32, TINT16):
+	case CASE(TFLOAT32, TINT32):
+	case CASE(TFLOAT32, TINT64):
+	case CASE(TFLOAT64, TINT16):
+	case CASE(TFLOAT64, TINT32):
+	case CASE(TFLOAT64, TINT64):
+		if(t->op == OREGISTER)
+			goto hardmem;
+		nodreg(&r1, types[ft], D_F0);
+		if(f->op != OREGISTER) {
+			if(ft == TFLOAT32)
+				gins(AFMOVF, f, &r1);
+			else
+				gins(AFMOVD, f, &r1);
+		}
+
+		// set round to zero mode during conversion
+		memname(&t1, types[TUINT16]);
+		memname(&t2, types[TUINT16]);
+		gins(AFSTCW, N, &t1);
+		gins(AMOVW, ncon(0xf7f), &t2);
+		gins(AFLDCW, &t2, N);
+		if(tt == TINT16)
+			gins(AFMOVWP, &r1, t);
+		else if(tt == TINT32)
+			gins(AFMOVLP, &r1, t);
+		else
+			gins(AFMOVVP, &r1, t);
+		gins(AFLDCW, &t1, N);
+		return;
+
+	case CASE(TFLOAT32, TINT8):
+	case CASE(TFLOAT32, TUINT16):
+	case CASE(TFLOAT32, TUINT8):
+	case CASE(TFLOAT64, TINT8):
+	case CASE(TFLOAT64, TUINT16):
+	case CASE(TFLOAT64, TUINT8):
+		// convert via int32.
+		tempname(&t1, types[TINT32]);
+		gmove(f, &t1);
+		switch(tt) {
+		default:
+			fatal("gmove %T", t);
+		case TINT8:
+			gins(ACMPL, &t1, ncon(-0x80));
+			p1 = gbranch(optoas(OLT, types[TINT32]), T, -1);
+			gins(ACMPL, &t1, ncon(0x7f));
+			p2 = gbranch(optoas(OGT, types[TINT32]), T, -1);
+			p3 = gbranch(AJMP, T, 0);
+			patch(p1, pc);
+			patch(p2, pc);
+			gmove(ncon(-0x80), &t1);
+			patch(p3, pc);
+			gmove(&t1, t);
+			break;
+		case TUINT8:
+			gins(ATESTL, ncon(0xffffff00), &t1);
+			p1 = gbranch(AJEQ, T, +1);
+			gins(AMOVL, ncon(0), &t1);
+			patch(p1, pc);
+			gmove(&t1, t);
+			break;
+		case TUINT16:
+			gins(ATESTL, ncon(0xffff0000), &t1);
+			p1 = gbranch(AJEQ, T, +1);
+			gins(AMOVL, ncon(0), &t1);
+			patch(p1, pc);
+			gmove(&t1, t);
+			break;
+		}
+		return;
+
+	case CASE(TFLOAT32, TUINT32):
+	case CASE(TFLOAT64, TUINT32):
+		// convert via int64.
+		cvt = types[TINT64];
+		goto hardmem;
+
+	/*
+	 * integer to float
+	 */
+	case CASE(TINT16, TFLOAT32):
+	case CASE(TINT16, TFLOAT64):
+	case CASE(TINT32, TFLOAT32):
+	case CASE(TINT32, TFLOAT64):
+	case CASE(TINT64, TFLOAT32):
+	case CASE(TINT64, TFLOAT64):
+		if(t->op != OREGISTER)
+			goto hard;
+		if(f->op == OREGISTER) {
+			cvt = f->type;
+			goto hardmem;
+		}
+		switch(ft) {
+		case TINT16:
+			a = AFMOVW;
+			break;
+		case TINT32:
+			a = AFMOVL;
+			break;
+		default:
+			a = AFMOVV;
+			break;
+		}
+		break;
+
+	case CASE(TINT8, TFLOAT32):
+	case CASE(TINT8, TFLOAT64):
+	case CASE(TUINT16, TFLOAT32):
+	case CASE(TUINT16, TFLOAT64):
+	case CASE(TUINT8, TFLOAT32):
+	case CASE(TUINT8, TFLOAT64):
+		// convert via int32 memory
+		cvt = types[TINT32];
+		goto hardmem;
+
+	case CASE(TUINT32, TFLOAT32):
+	case CASE(TUINT32, TFLOAT64):
+		// convert via int64 memory
+		cvt = types[TINT64];
+		goto hardmem;
 
 	/*
 	 * float to float
@@ -1673,20 +1933,121 @@ gmove(Node *f, Node *t)
 	gins(a, f, t);
 	return;
 
-rsrc:
-	// requires register source
-	regalloc(&r1, f->type, t);
+hard:
+	// requires register intermediate
+	regalloc(&r1, cvt, t);
 	gmove(f, &r1);
-	gins(a, &r1, t);
+	gmove(&r1, t);
 	regfree(&r1);
 	return;
 
-rdst:
-	// requires register destination
-	regalloc(&r1, t->type, t);
-	gins(a, f, &r1);
+hardmem:
+	// requires memory intermediate
+	tempname(&r1, cvt);
+	gmove(f, &r1);
 	gmove(&r1, t);
-	regfree(&r1);
+	return;
+
+fatal:
+	// should not happen
+	fatal("gmove %lN -> %lN", f, t);
+	return;
+}
+
+static void
+floatmove_sse(Node *f, Node *t)
+{
+	Node r1;
+	Type *cvt;
+	int a, ft, tt;
+
+	ft = simsimtype(f->type);
+	tt = simsimtype(t->type);
+
+	switch(CASE(ft, tt)) {
+	default:
+		// should not happen
+		fatal("gmove %N -> %N", f, t);
+		return;
+	/*
+	* float to integer
+	*/
+	case CASE(TFLOAT32, TINT16):
+	case CASE(TFLOAT32, TINT8):
+	case CASE(TFLOAT32, TUINT16):
+	case CASE(TFLOAT32, TUINT8):
+	case CASE(TFLOAT64, TINT16):
+	case CASE(TFLOAT64, TINT8):
+	case CASE(TFLOAT64, TUINT16):
+	case CASE(TFLOAT64, TUINT8):
+		// convert via int32.
+		cvt = types[TINT32];
+		goto hard;
+
+	case CASE(TFLOAT32, TUINT32):
+	case CASE(TFLOAT64, TUINT32):
+		// convert via int64.
+		cvt = types[TINT64];
+		goto hardmem;
+
+	case CASE(TFLOAT32, TINT32):
+		a = ACVTTSS2SL;
+		goto rdst;
+
+	case CASE(TFLOAT64, TINT32):
+		a = ACVTTSD2SL;
+		goto rdst;
+
+	/*
+	 * integer to float
+	 */
+	case CASE(TINT8, TFLOAT32):
+	case CASE(TINT8, TFLOAT64):
+	case CASE(TINT16, TFLOAT32):
+	case CASE(TINT16, TFLOAT64):
+	case CASE(TUINT16, TFLOAT32):
+	case CASE(TUINT16, TFLOAT64):
+	case CASE(TUINT8, TFLOAT32):
+	case CASE(TUINT8, TFLOAT64):
+		// convert via int32 memory
+		cvt = types[TINT32];
+		goto hard;
+
+	case CASE(TUINT32, TFLOAT32):
+	case CASE(TUINT32, TFLOAT64):
+		// convert via int64 memory
+		cvt = types[TINT64];
+		goto hardmem;
+
+	case CASE(TINT32, TFLOAT32):
+		a = ACVTSL2SS;
+		goto rdst;
+
+	case CASE(TINT32, TFLOAT64):
+		a = ACVTSL2SD;
+		goto rdst;
+
+	/*
+	 * float to float
+	 */
+	case CASE(TFLOAT32, TFLOAT32):
+		a = AMOVSS;
+		break;
+
+	case CASE(TFLOAT64, TFLOAT64):
+		a = AMOVSD;
+		break;
+
+	case CASE(TFLOAT32, TFLOAT64):
+		a = ACVTSS2SD;
+		goto rdst;
+
+	case CASE(TFLOAT64, TFLOAT32):
+		a = ACVTSD2SS;
+		goto rdst;
+	}
+
+	gins(a, f, t);
 	return;
 
 hard:
@@ -1704,9 +2065,13 @@ hardmem:
 	gmove(&r1, t);
 	return;
 
-fatal:
-	// should not happen
-	fatal("gmove %N -> %N", f, t);
+rdst:
+	// requires register destination
+	regalloc(&r1, t->type, t);
+	gins(a, f, &r1);
+	gmove(&r1, t);
+	regfree(&r1);
+	return;
 }
 
 int
@@ -1737,6 +2102,10 @@ gins(int as, Node *f, Node *t)
 
 	if(as == AFMOVF && f && f->op == OREGISTER && t && t->op == OREGISTER)
 		fatal("gins MOVF reg, reg");
+	if(as == ACVTSD2SS && f && f->op == OLITERAL)
+		fatal("gins CVTSD2SS const");
+	if(as == AMOVSD && t && t->op == OREGISTER && t->val.u.reg == D_F0)
+		fatal("gins MOVSD into F0");
 
 	switch(as) {
 	case AMOVB:
@@ -1744,6 +2113,12 @@ gins(int as, Node *f, Node *t)
 	case AMOVL:
 		if(f != N && t != N && samaddr(f, t))
 			return nil;
+		break;
+	
+	case ALEAL:
+		if(f != N && isconst(f, CTNIL))
+			fatal("gins LEAL nil %T", f->type);
+		break;
 	}
 
 	memset(&af, 0, sizeof af);
@@ -1782,6 +2157,25 @@ gins(int as, Node *f, Node *t)
 	return p;
 }
 
+// Generate an instruction referencing *n
+// to force segv on nil pointer dereference.
+void
+checkref(Node *n)
+{
+	Node m;
+
+	if(n->type->type->width < unmappedzero)
+		return;
+
+	regalloc(&m, types[TUINTPTR], n);
+	cgen(n, &m);
+	m.xoffset = 0;
+	m.op = OINDREG;
+	m.type = types[TUINT8];
+	gins(ATESTB, nodintconst(0), &m);
+	regfree(&m);
+}
+
 static void
 checkoffset(Addr *a, int canemitcode)
 {
@@ -1807,6 +2201,8 @@ checkoffset(Addr *a, int canemitcode)
 void
 naddr(Node *n, Addr *a, int canemitcode)
 {
+	Prog *p;
+
 	a->scale = 0;
 	a->index = D_NONE;
 	a->type = D_NONE;
@@ -1842,13 +2238,29 @@ naddr(Node *n, Addr *a, int canemitcode)
 		a->node = n->left->orig;
 		break;
 
+	case OCLOSUREVAR:
+		if(!canemitcode)
+			fatal("naddr OCLOSUREVAR cannot emit code");
+		p = gins(AMOVL, N, N);
+		p->from.type = D_DX+D_INDIR;
+		p->from.offset = n->xoffset;
+		p->to.type = D_BX;
+		a->type = D_BX;
+		a->sym = S;
+		break;
+
+	case OCFUNC:
+		naddr(n->left, a, canemitcode);
+		a->sym = n->left->sym;
+		break;
+
 	case ONAME:
 		a->etype = 0;
 		a->width = 0;
 		if(n->type != T) {
 			a->etype = simtype[n->type->etype];
+			dowidth(n->type);
 			a->width = n->type->width;
-			a->gotype = ngotype(n);
 		}
 		a->offset = n->xoffset;
 		a->sym = n->sym;
@@ -1880,6 +2292,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 		case PFUNC:
 			a->index = D_EXTERN;
 			a->type = D_ADDR;
+			a->sym = funcsym(a->sym);
 			break;
 		}
 		break;
@@ -1891,7 +2304,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 			break;
 		case CTFLT:
 			a->type = D_FCONST;
-			a->dval = mpgetflt(n->val.u.fval);
+			a->u.dval = mpgetflt(n->val.u.fval);
 			break;
 		case CTINT:
 		case CTRUNE:
diff --git a/src/cmd/8g/list.c b/src/cmd/8g/list.c
index 88d3d5f..ec02ba5 100644
--- a/src/cmd/8g/list.c
+++ b/src/cmd/8g/list.c
@@ -107,7 +107,7 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_BRANCH:
-		snprint(str, sizeof(str), "%d", a->branch->loc);
+		snprint(str, sizeof(str), "%d", a->u.branch->loc);
 		break;
 
 	case D_EXTERN:
@@ -137,11 +137,11 @@ Dconv(Fmt *fp)
 		break;
 
 	case D_FCONST:
-		snprint(str, sizeof(str), "$(%.17e)", a->dval);
+		snprint(str, sizeof(str), "$(%.17e)", a->u.dval);
 		break;
 
 	case D_SCONST:
-		snprint(str, sizeof(str), "$\"%Y\"", a->sval);
+		snprint(str, sizeof(str), "$\"%Y\"", a->u.sval);
 		break;
 
 	case D_ADDR:
@@ -158,7 +158,10 @@ brk:
 		strcat(str, s);
 	}
 conv:
-	return fmtstrcpy(fp, str);
+	fmtstrcpy(fp, str);
+	if(a->gotype)
+		fmtprint(fp, "{%s}", a->gotype->name);
+	return 0;
 }
 
 static	char*	regstr[] =
@@ -231,6 +234,15 @@ static	char*	regstr[] =
 	"TR6",
 	"TR7",
 
+	"X0",		/* [D_X0] */
+	"X1",
+	"X2",
+	"X3",
+	"X4",
+	"X5",
+	"X6",
+	"X7",
+
 	"NONE",		/* [D_NONE] */
 };
 
diff --git a/src/cmd/8g/opt.h b/src/cmd/8g/opt.h
index ed6eb15..b80043e 100644
--- a/src/cmd/8g/opt.h
+++ b/src/cmd/8g/opt.h
@@ -47,12 +47,16 @@
 typedef	struct	Reg	Reg;
 typedef	struct	Rgn	Rgn;
 
+// 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.
+// r->prog->regp points back to r.
 struct	Reg
 {
 
-	Bits	set;
-	Bits	use1;
-	Bits	use2;
+	Bits	set;  		// variables written by this instruction.
+	Bits	use1; 		// variables read by prog->from.
+	Bits	use2; 		// variables read by prog->to.
 
 	Bits	refbehind;
 	Bits	refahead;
@@ -68,13 +72,13 @@ struct	Reg
 	uint16	loop;		// x5 for every loop
 	uchar	refset;		// diagnostic generated
 
-	Reg*	p1;
-	Reg*	p2;
+	Reg*	p1;     	// predecessors of this instruction: p1,
+	Reg*	p2;     	// and then p2 linked though p2link.
 	Reg*	p2link;
-	Reg*	s1;
+	Reg*	s1;     	// successors of this instruction (at most two: s1 and s2).
 	Reg*	s2;
-	Reg*	link;
-	Prog*	prog;
+	Reg*	link;   	// next instruction in function code
+	Prog*	prog;   	// actual instruction
 };
 #define	R	((Reg*)0)
 
diff --git a/src/cmd/8g/peep.c b/src/cmd/8g/peep.c
index b8a2825..e5a3149 100644
--- a/src/cmd/8g/peep.c
+++ b/src/cmd/8g/peep.c
@@ -36,6 +36,7 @@
 #define	REGEXT	0
 
 static void	conprop(Reg *r);
+static void elimshortmov(Reg *r);
 
 // do we need the carry bit
 static int
@@ -45,9 +46,15 @@ needc(Prog *p)
 		switch(p->as) {
 		case AADCL:
 		case ASBBL:
+		case ARCRB:
+		case ARCRW:
 		case ARCRL:
 			return 1;
+		case AADDB:
+		case AADDW:
 		case AADDL:
+		case ASUBB:
+		case ASUBW:
 		case ASUBL:
 		case AJMP:
 		case ARET:
@@ -119,28 +126,14 @@ peep(void)
 		case AGLOBL:
 		case ANAME:
 		case ASIGNAME:
+		case ALOCALS:
+		case ATYPE:
 			p = p->link;
 		}
 	}
-	
-	// movb elimination.
-	// movb is simulated by the linker
-	// when a register other than ax, bx, cx, dx
-	// is used, so rewrite to other instructions
-	// when possible.  a movb into a register
-	// can smash the entire 32-bit register without
-	// causing any trouble.
-	for(r=firstr; r!=R; r=r->link) {
-		p = r->prog;
-		if(p->as == AMOVB && regtyp(&p->to)) {
-			// movb into register.
-			// from another register or constant can be movl.
-			if(regtyp(&p->from) || p->from.type == D_CONST)
-				p->as = AMOVL;
-			else
-				p->as = AMOVBLZX;
-		}
-	}
+
+	// byte, word arithmetic elimination.
+	elimshortmov(r);
 
 	// constant propagation
 	// find MOV $con,R followed by
@@ -158,6 +151,8 @@ peep(void)
 		case AMOVB:
 		case AMOVW:
 		case AMOVL:
+		case AMOVSS:
+		case AMOVSD:
 			if(regtyp(&p->to))
 			if(p->from.type == D_CONST)
 				conprop(r);
@@ -173,9 +168,9 @@ loop1:
 	for(r=firstr; r!=R; r=r->link) {
 		p = r->prog;
 		switch(p->as) {
-		case AMOVB:
-		case AMOVW:
 		case AMOVL:
+		case AMOVSS:
+		case AMOVSD:
 			if(regtyp(&p->to))
 			if(regtyp(&p->from)) {
 				if(copyprop(r)) {
@@ -205,7 +200,6 @@ loop1:
 			}
 			break;
 
-		case AADDB:
 		case AADDL:
 		case AADDW:
 			if(p->from.type != D_CONST || needc(p->link))
@@ -228,7 +222,6 @@ loop1:
 			}
 			break;
 
-		case ASUBB:
 		case ASUBL:
 		case ASUBW:
 			if(p->from.type != D_CONST || needc(p->link))
@@ -254,6 +247,19 @@ loop1:
 	}
 	if(t)
 		goto loop1;
+
+	// MOVSD removal.
+	// We never use packed registers, so a MOVSD between registers
+	// can be replaced by MOVAPD, which moves the pair of float64s
+	// instead of just the lower one.  We only use the lower one, but
+	// the processor can do better if we do moves using both.
+	for(r=firstr; r!=R; r=r->link) {
+		p = r->prog;
+		if(p->as == AMOVSD)
+		if(regtyp(&p->from))
+		if(regtyp(&p->to))
+			p->as = AMOVAPD;
+	}
 }
 
 void
@@ -312,9 +318,104 @@ regtyp(Adr *a)
 	t = a->type;
 	if(t >= D_AX && t <= D_DI)
 		return 1;
+	if(t >= D_X0 && t <= D_X7)
+		return 1;
 	return 0;
 }
 
+// movb elimination.
+// movb is simulated by the linker
+// when a register other than ax, bx, cx, dx
+// is used, so rewrite to other instructions
+// when possible.  a movb into a register
+// can smash the entire 64-bit register without
+// causing any trouble.
+static void
+elimshortmov(Reg *r)
+{
+	Prog *p;
+
+	for(r=firstr; r!=R; r=r->link) {
+		p = r->prog;
+		if(regtyp(&p->to)) {
+			switch(p->as) {
+			case AINCB:
+			case AINCW:
+				p->as = AINCL;
+				break;
+			case ADECB:
+			case ADECW:
+				p->as = ADECL;
+				break;
+			case ANEGB:
+			case ANEGW:
+				p->as = ANEGL;
+				break;
+			case ANOTB:
+			case ANOTW:
+				p->as = ANOTL;
+				break;
+			}
+			if(regtyp(&p->from) || p->from.type == D_CONST) {
+				// move or artihmetic into partial register.
+				// from another register or constant can be movl.
+				// we don't switch to 32-bit arithmetic if it can
+				// change how the carry bit is set (and the carry bit is needed).
+				switch(p->as) {
+				case AMOVB:
+				case AMOVW:
+					p->as = AMOVL;
+					break;
+				case AADDB:
+				case AADDW:
+					if(!needc(p->link))
+						p->as = AADDL;
+					break;
+				case ASUBB:
+				case ASUBW:
+					if(!needc(p->link))
+						p->as = ASUBL;
+					break;
+				case AMULB:
+				case AMULW:
+					p->as = AMULL;
+					break;
+				case AIMULB:
+				case AIMULW:
+					p->as = AIMULL;
+					break;
+				case AANDB:
+				case AANDW:
+					p->as = AANDL;
+					break;
+				case AORB:
+				case AORW:
+					p->as = AORL;
+					break;
+				case AXORB:
+				case AXORW:
+					p->as = AXORL;
+					break;
+				case ASHLB:
+				case ASHLW:
+					p->as = ASHLL;
+					break;
+				}
+			} else {
+				// explicit zero extension
+				switch(p->as) {
+				case AMOVB:
+					p->as = AMOVBLZX;
+					break;
+				case AMOVW:
+					p->as = AMOVWLZX;
+					break;
+				}
+			}
+		}
+	}
+}
+
 /*
  * the idea is to substitute
  * one register for another
@@ -357,17 +458,6 @@ subprop(Reg *r0)
 			if(p->to.type != D_NONE)
 				break;
 
-		case ADIVB:
-		case ADIVL:
-		case ADIVW:
-		case AIDIVB:
-		case AIDIVL:
-		case AIDIVW:
-		case AIMULB:
-		case AMULB:
-		case AMULL:
-		case AMULW:
-
 		case ARCLB:
 		case ARCLL:
 		case ARCLW:
@@ -392,6 +482,19 @@ subprop(Reg *r0)
 		case ASHRB:
 		case ASHRL:
 		case ASHRW:
+			if(p->from.type == D_CONST)
+				break;
+
+		case ADIVB:
+		case ADIVL:
+		case ADIVW:
+		case AIDIVB:
+		case AIDIVL:
+		case AIDIVW:
+		case AIMULB:
+		case AMULB:
+		case AMULL:
+		case AMULW:
 
 		case AREP:
 		case AREPN:
@@ -403,11 +506,16 @@ subprop(Reg *r0)
 		case ASTOSL:
 		case AMOVSB:
 		case AMOVSL:
+
+		case AFMOVF:
+		case AFMOVD:
+		case AFMOVFP:
+		case AFMOVDP:
 			return 0;
 
-		case AMOVB:
-		case AMOVW:
 		case AMOVL:
+		case AMOVSS:
+		case AMOVSD:
 			if(p->to.type == v1->type)
 				goto gotit;
 			break;
@@ -587,13 +695,22 @@ copyu(Prog *p, Adr *v, Adr *s)
 
 
 	case ANOP:	/* rhs store */
-	case AMOVB:
-	case AMOVW:
 	case AMOVL:
 	case AMOVBLSX:
 	case AMOVBLZX:
 	case AMOVWLSX:
 	case AMOVWLZX:
+	
+	case AMOVSS:
+	case AMOVSD:
+	case ACVTSD2SL:
+	case ACVTSD2SS:
+	case ACVTSL2SD:
+	case ACVTSL2SS:
+	case ACVTSS2SD:
+	case ACVTSS2SL:
+	case ACVTTSD2SL:
+	case ACVTTSS2SL:
 		if(copyas(&p->to, v)) {
 			if(s != A)
 				return copysub(&p->from, v, s, 1);
@@ -653,6 +770,28 @@ copyu(Prog *p, Adr *v, Adr *s)
 	case AXORB:
 	case AXORL:
 	case AXORW:
+	case AMOVB:
+	case AMOVW:
+
+	case AADDSD:
+	case AADDSS:
+	case ACMPSD:
+	case ACMPSS:
+	case ADIVSD:
+	case ADIVSS:
+	case AMAXSD:
+	case AMAXSS:
+	case AMINSD:
+	case AMINSS:
+	case AMULSD:
+	case AMULSS:
+	case ARCPSS:
+	case ARSQRTSS:
+	case ASQRTSD:
+	case ASQRTSS:
+	case ASUBSD:
+	case ASUBSS:
+	case AXORPD:
 		if(copyas(&p->to, v))
 			return 2;
 		goto caseread;
@@ -660,6 +799,11 @@ copyu(Prog *p, Adr *v, Adr *s)
 	case ACMPL:	/* read only */
 	case ACMPW:
 	case ACMPB:
+
+	case ACOMISD:
+	case ACOMISS:
+	case AUCOMISD:
+	case AUCOMISS:
 	caseread:
 		if(s != A) {
 			if(copysub(&p->from, v, s, 1))
@@ -744,8 +888,6 @@ copyu(Prog *p, Adr *v, Adr *s)
 		return 0;
 
 	case ARET:	/* funny */
-		if(v->type == REGRET || v->type == FREGRET)
-			return 2;
 		if(s != A)
 			return 1;
 		return 3;
@@ -755,6 +897,8 @@ copyu(Prog *p, Adr *v, Adr *s)
 			return 2;
 		if(REGARG >= 0 && v->type == (uchar)REGARG)
 			return 2;
+		if(v->type == p->from.type)
+			return 2;
 
 		if(s != A) {
 			if(copysub(&p->to, v, s, 1))
@@ -820,7 +964,7 @@ copysub(Adr *a, Adr *v, Adr *s, int f)
 
 	if(copyas(a, v)) {
 		t = s->type;
-		if(t >= D_AX && t <= D_DI) {
+		if(t >= D_AX && t <= D_DI || t >= D_X0 && t <= D_X7) {
 			if(f)
 				a->type = t;
 		}
@@ -881,7 +1025,7 @@ loop:
 		if(p->from.node == p0->from.node)
 		if(p->from.offset == p0->from.offset)
 		if(p->from.scale == p0->from.scale)
-		if(p->from.dval == p0->from.dval)
+		if(p->from.u.vval == p0->from.u.vval)
 		if(p->from.index == p0->from.index) {
 			excise(r);
 			goto loop;
diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c
index 45ffdf9..985f6cc 100644
--- a/src/cmd/8g/reg.c
+++ b/src/cmd/8g/reg.c
@@ -33,13 +33,14 @@
 #include "gg.h"
 #include "opt.h"
 
-#define	NREGVAR	8
-#define	REGBITS	((uint32)0xff)
+#define	NREGVAR	16	/* 8 integer + 8 floating */
+#define	REGBITS	((uint32)0xffff)
 #define	P2R(p)	(Reg*)(p->reg)
 
 static	int	first	= 1;
 
 static	void	fixjmp(Prog*);
+static	void	fixtemp(Prog*);
 
 Reg*
 rega(void)
@@ -118,7 +119,12 @@ setaddrs(Bits bit)
 	}
 }
 
-static char* regname[] = { ".ax", ".cx", ".dx", ".bx", ".sp", ".bp", ".si", ".di" };
+static char* regname[] = {
+	".ax", ".cx", ".dx", ".bx", ".sp", ".bp", ".si", ".di",
+	".x0", ".x1", ".x2", ".x3", ".x4", ".x5", ".x6", ".x7",
+};
+
+static Node* regnodes[NREGVAR];
 
 void
 regopt(Prog *firstp)
@@ -135,6 +141,7 @@ regopt(Prog *firstp)
 		first = 0;
 	}
 	
+	fixtemp(firstp);
 	fixjmp(firstp);
 
 	// count instructions
@@ -147,7 +154,6 @@ regopt(Prog *firstp)
 		return;
 	}
 
-	r1 = R;
 	firstr = R;
 	lastr = R;
 	
@@ -158,8 +164,11 @@ regopt(Prog *firstp)
 	 */
 	nvar = NREGVAR;
 	memset(var, 0, NREGVAR*sizeof var[0]);
-	for(i=0; i<NREGVAR; i++)
-		var[i].node = newname(lookup(regname[i]));
+	for(i=0; i<NREGVAR; i++) {
+		if(regnodes[i] == N)
+			regnodes[i] = newname(lookup(regname[i]));
+		var[i].node = regnodes[i];
+	}
 
 	regbits = RtoB(D_SP);
 	for(z=0; z<BITS; z++) {
@@ -186,6 +195,8 @@ regopt(Prog *firstp)
 		case AGLOBL:
 		case ANAME:
 		case ASIGNAME:
+		case ALOCALS:
+		case ATYPE:
 			continue;
 		}
 		r = rega();
@@ -213,6 +224,20 @@ regopt(Prog *firstp)
 			}
 		}
 
+		// Avoid making variables for direct-called functions.
+		if(p->as == ACALL && p->to.type == D_EXTERN)
+			continue;
+
+		// Addressing makes some registers used.
+		if(p->from.type >= D_INDIR)
+			r->use1.b[0] |= RtoB(p->from.type-D_INDIR);
+		if(p->from.index != D_NONE)
+			r->use1.b[0] |= RtoB(p->from.index);
+		if(p->to.type >= D_INDIR)
+			r->use2.b[0] |= RtoB(p->to.type-D_INDIR);
+		if(p->to.index != D_NONE)
+			r->use2.b[0] |= RtoB(p->to.index);
+
 		bit = mkvar(r, &p->from);
 		if(bany(&bit))
 		switch(p->as) {
@@ -220,6 +245,8 @@ regopt(Prog *firstp)
 		 * funny
 		 */
 		case ALEAL:
+		case AFMOVD:
+		case AFMOVF:
 		case AFMOVL: 
 		case AFMOVW:
 		case AFMOVV:
@@ -260,6 +287,10 @@ regopt(Prog *firstp)
 		case ACMPB:
 		case ACMPL:
 		case ACMPW:
+		case ACOMISS:
+		case ACOMISD:
+		case AUCOMISS:
+		case AUCOMISD:
 		case ATESTB:
 		case ATESTL:
 		case ATESTW:
@@ -283,6 +314,17 @@ regopt(Prog *firstp)
 		case AMOVWLSX:
 		case AMOVWLZX:
 		case APOPL:
+
+		case AMOVSS:
+		case AMOVSD:
+		case ACVTSD2SL:
+		case ACVTSD2SS:
+		case ACVTSL2SD:
+		case ACVTSL2SS:
+		case ACVTSS2SD:
+		case ACVTSS2SL:
+		case ACVTTSD2SL:
+		case ACVTTSS2SL:
 			for(z=0; z<BITS; z++)
 				r->set.b[z] |= bit.b[z];
 			break;
@@ -367,6 +409,26 @@ regopt(Prog *firstp)
 		case AXCHGB:
 		case AXCHGW:
 		case AXCHGL:
+
+		case AADDSD:
+		case AADDSS:
+		case ACMPSD:
+		case ACMPSS:
+		case ADIVSD:
+		case ADIVSS:
+		case AMAXSD:
+		case AMAXSS:
+		case AMINSD:
+		case AMINSS:
+		case AMULSD:
+		case AMULSS:
+		case ARCPSS:
+		case ARSQRTSS:
+		case ASQRTSD:
+		case ASQRTSS:
+		case ASUBSD:
+		case ASUBSS:
+		case AXORPD:
 			for(z=0; z<BITS; z++) {
 				r->set.b[z] |= bit.b[z];
 				r->use2.b[z] |= bit.b[z];
@@ -475,8 +537,9 @@ regopt(Prog *firstp)
 				addrs.b[z] |= bit.b[z];
 		}
 
-//		print("bit=%2d addr=%d et=%-6E w=%-2d s=%S + %lld\n",
-//			i, v->addr, v->etype, v->width, v->sym, v->offset);
+		if(debug['R'] && debug['v'])
+			print("bit=%2d addr=%d et=%-6E w=%-2d s=%N + %lld\n",
+				i, v->addr, v->etype, v->width, v->node, v->offset);
 	}
 
 	if(debug['R'] && debug['v'])
@@ -490,9 +553,9 @@ regopt(Prog *firstp)
 	for(r=firstr; r!=R; r=r->link) {
 		p = r->prog;
 		if(p->to.type == D_BRANCH) {
-			if(p->to.branch == P)
+			if(p->to.u.branch == P)
 				fatal("pnil %P", p);
-			r1 = p->to.branch->reg;
+			r1 = p->to.u.branch->reg;
 			if(r1 == R)
 				fatal("rnil %P", p);
 			if(r1 == r) {
@@ -673,8 +736,16 @@ brk:
 		while(p->link != P && p->link->as == ANOP)
 			p->link = p->link->link;
 		if(p->to.type == D_BRANCH)
-			while(p->to.branch != P && p->to.branch->as == ANOP)
-				p->to.branch = p->to.branch->link;
+			while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
+				p->to.u.branch = p->to.u.branch->link;
+	}
+
+	if(!use_sse)
+	for(p=firstp; p!=P; p=p->link) {
+		if(p->from.type >= D_X0 && p->from.type <= D_X7)
+			fatal("invalid use of %R with GO386=387: %P", p->from.type, p);
+		if(p->to.type >= D_X0 && p->to.type <= D_X7)
+			fatal("invalid use of %R with GO386=387: %P", p->to.type, p);
 	}
 
 	if(lastr != R) {
@@ -735,7 +806,6 @@ addmove(Reg *r, int bn, int rn, int f)
 	a->offset = v->offset;
 	a->etype = v->etype;
 	a->type = v->name;
-	a->gotype = v->gotype;
 	a->node = v->node;
 	a->sym = v->node->sym;
 
@@ -754,6 +824,12 @@ addmove(Reg *r, int bn, int rn, int f)
 	case TUINT16:
 		p1->as = AMOVW;
 		break;
+	case TFLOAT32:
+		p1->as = AMOVSS;
+		break;
+	case TFLOAT64:
+		p1->as = AMOVSD;
+		break;
 	case TINT:
 	case TUINT:
 	case TINT32:
@@ -793,6 +869,9 @@ doregbits(int r)
 	else
 	if(r >= D_AH && r <= D_BH)
 		b |= RtoB(r-D_AH+D_AX);
+	else
+	if(r >= D_X0 && r <= D_X0+7)
+		b |= FtoB(r);
 	return b;
 }
 
@@ -865,6 +944,8 @@ mkvar(Reg *r, Adr *a)
 	et = a->etype;
 	o = a->offset;
 	w = a->width;
+	if(w < 0)
+		fatal("bad width %d for %D", w, a);
 
 	flag = 0;
 	for(i=0; i<nvar; i++) {
@@ -902,14 +983,13 @@ mkvar(Reg *r, Adr *a)
 	v = var+i;
 	v->offset = o;
 	v->name = n;
-	v->gotype = a->gotype;
 	v->etype = et;
 	v->width = w;
 	v->addr = flag;		// funny punning
 	v->node = node;
 
 	if(debug['R'])
-		print("bit=%2d et=%2d w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
+		print("bit=%2d et=%2E w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
 	ostats.nvar++;
 
 	bit = blsh(i);
@@ -972,8 +1052,12 @@ prop(Reg *r, Bits ref, Bits cal)
 		default:
 			// Work around for issue 1304:
 			// flush modified globals before each instruction.
-			for(z=0; z<BITS; z++)
+			for(z=0; z<BITS; z++) {
 				cal.b[z] |= externs.b[z];
+				// issue 4066: flush modified return variables in case of panic
+				if(hasdefer)
+					cal.b[z] |= ovar.b[z];
+			}
 			break;
 		}
 		for(z=0; z<BITS; z++) {
@@ -1190,6 +1274,13 @@ allreg(uint32 b, Rgn *r)
 
 	case TFLOAT32:
 	case TFLOAT64:
+		if(!use_sse)
+			break;
+		i = BtoF(~b);
+		if(i && r->cost > 0) {
+			r->regno = i;
+			return FtoB(i);
+		}
 		break;
 	}
 	return 0;
@@ -1279,7 +1370,7 @@ regset(Reg *r, uint32 bb)
 	set = 0;
 	v = zprog.from;
 	while(b = bb & ~(bb-1)) {
-		v.type = BtoR(b);
+		v.type = b & 0xFF ? BtoR(b): BtoF(b);
 		c = copyu(r->prog, &v, A);
 		if(c == 3)
 			set |= b;
@@ -1298,7 +1389,7 @@ reguse(Reg *r, uint32 bb)
 	set = 0;
 	v = zprog.from;
 	while(b = bb & ~(bb-1)) {
-		v.type = BtoR(b);
+		v.type = b & 0xFF ? BtoR(b): BtoF(b);
 		c = copyu(r->prog, &v, A);
 		if(c == 1 || c == 2 || c == 4)
 			set |= b;
@@ -1468,6 +1559,23 @@ BtoR(int32 b)
 	return bitno(b) + D_AX;
 }
 
+int32
+FtoB(int f)
+{
+	if(f < D_X0 || f > D_X7)
+		return 0;
+	return 1L << (f - D_X0 + 8);
+}
+
+int
+BtoF(int32 b)
+{
+	b &= 0xFF00L;
+	if(b == 0)
+		return 0;
+	return bitno(b) - 8 + D_X0;
+}
+
 void
 dumpone(Reg *r)
 {
@@ -1581,7 +1689,7 @@ chasejmp(Prog *p, int *jmploop)
 			*jmploop = 1;
 			break;
 		}
-		p = p->to.branch;
+		p = p->to.u.branch;
 	}
 	return p;
 }
@@ -1603,9 +1711,9 @@ mark(Prog *firstp)
 		if(p->reg != dead)
 			break;
 		p->reg = alive;
-		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.branch)
-			mark(p->to.branch);
-		if(p->as == AJMP || p->as == ARET || (p->as == ACALL && noreturn(p)))
+		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.u.branch)
+			mark(p->to.u.branch);
+		if(p->as == AJMP || p->as == ARET || p->as == AUNDEF)
 			break;
 	}
 }
@@ -1624,8 +1732,8 @@ fixjmp(Prog *firstp)
 	for(p=firstp; p; p=p->link) {
 		if(debug['R'] && debug['v'])
 			print("%P\n", p);
-		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.branch && p->to.branch->as == AJMP) {
-			p->to.branch = chasejmp(p->to.branch, &jmploop);
+		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.u.branch && p->to.u.branch->as == AJMP) {
+			p->to.u.branch = chasejmp(p->to.u.branch, &jmploop);
 			if(debug['R'] && debug['v'])
 				print("->%P\n", p);
 		}
@@ -1661,7 +1769,7 @@ fixjmp(Prog *firstp)
 	if(!jmploop) {
 		last = nil;
 		for(p=firstp; p; p=p->link) {
-			if(p->as == AJMP && p->to.type == D_BRANCH && p->to.branch == p->link) {
+			if(p->as == AJMP && p->to.type == D_BRANCH && p->to.u.branch == p->link) {
 				if(debug['R'] && debug['v'])
 					print("del %P\n", p);
 				continue;
@@ -1680,3 +1788,131 @@ fixjmp(Prog *firstp)
 		print("\n");
 	}
 }
+
+static uint32
+fnv1(Sym *sym)
+{
+	uint32 h;
+	char *s;
+
+	h = 2166136261U;
+	for(s=sym->name;*s;s++) {
+		h = (16777619 * h) ^ (uint32)(uint8)(*s);
+	}
+	return h;
+}
+
+static uint16
+hash32to16(uint32 h)
+{
+	return (h & 0xffff) ^ (h >> 16);
+}
+
+/*
+ * fixtemp eliminates sequences like:
+ *   MOV reg1, mem
+ *   OP mem, reg2
+ * when mem is a stack variable which is not mentioned
+ * anywhere else. The instructions are replaced by
+ *   OP reg1, reg2
+ * this reduces the number of variables that the register optimizer
+ * sees, which lets it do a better job and makes it less likely to turn
+ * itself off.
+ */
+static void
+fixtemp(Prog *firstp)
+{
+	static uint8 counts[1<<16]; // A hash table to count variable occurences.
+	int i;
+	Prog *p, *p2;
+	uint32 h;
+
+	if(debug['R'] && debug['v'])
+		print("\nfixtemp\n");
+
+	// Count variable references. We actually use a hashtable so this
+	// is only approximate.
+	for(i=0; i<nelem(counts); i++)
+		counts[i] = 0;
+	for(p=firstp; p!=P; p=p->link) {
+		if(p->from.type == D_AUTO) {
+			h = hash32to16(fnv1(p->from.sym));
+			//print("seen %S hash %d\n", p->from.sym, hash32to16(h));
+			if(counts[h] < 10)
+				counts[h]++;
+		}
+		if(p->to.type == D_AUTO) {
+			h = hash32to16(fnv1(p->to.sym));
+			//print("seen %S hash %d\n", p->to.sym, hash32to16(h));
+			if(counts[h] < 10)
+				counts[h]++;
+		}
+	}
+
+	// Eliminate single-write, single-read stack variables.
+	for(p=firstp; p!=P; p=p->link) {
+		if(debug['R'] && debug['v'])
+			print("%P\n", p);
+		if(p->link == P || p->to.type != D_AUTO)
+			continue;
+		if(isfloat[p->to.etype] && FtoB(p->from.type)) {
+			switch(p->as) {
+			case AMOVSS:
+			case AMOVSD:
+				break;
+			default:
+				continue;
+			}
+		} else if(!isfloat[p->to.etype] && RtoB(p->from.type)) {
+			switch(p->as) {
+			case AMOVB:
+				if(p->to.width == 1)
+					break;
+			case AMOVW:
+				if(p->to.width == 2)
+					break;
+			case AMOVL:
+				if(p->to.width == 4)
+					break;
+			default:
+				continue;
+			}
+		} else
+			continue;
+		// p is a MOV reg, mem.
+		p2 = p->link;
+		h = hash32to16(fnv1(p->to.sym));
+		if(counts[h] != 2) {
+			continue;
+		}
+		switch(p2->as) {
+		case ALEAL:
+		case AFMOVD:
+		case AFMOVF:
+		case AFMOVL:
+		case AFMOVW:
+		case AFMOVV:
+			// funny
+			continue;
+		}
+		// p2 is OP mem, reg2
+		// and OP is not a funny instruction.
+		if(p2->from.sym == p->to.sym
+			&& p2->from.offset == p->to.offset
+			&& p2->from.type == p->to.type) {
+			if(debug['R'] && debug['v']) {
+				print(" ===elide== %D\n", &p->to);
+				print("%P", p2);
+			}
+			// p2 is OP mem, reg2.
+			// change to OP reg, reg2 and
+			// eliminate the mov.
+			p2->from = p->from;
+			*p = *p2;
+			p->link = p2->link;
+			if(debug['R'] && debug['v']) {
+				print(" ===change== %P\n", p);
+			}
+		}
+	}
+}
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index 9d2751c..3868899 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -451,6 +451,125 @@ enum	as
 	ASFENCE,
 
 	AEMMS,
+	
+	APREFETCHT0,
+	APREFETCHT1,
+	APREFETCHT2,
+	APREFETCHNTA,
+	
+	ABSWAPL,
+	
+	AUNDEF,
+
+	// SSE2
+	AADDPD,
+	AADDPS,
+	AADDSD,
+	AADDSS,
+	AANDNPD,
+	AANDNPS,
+	AANDPD,
+	AANDPS,
+	ACMPPD,
+	ACMPPS,
+	ACMPSD,
+	ACMPSS,
+	ACOMISD,
+	ACOMISS,
+	ACVTPL2PD,
+	ACVTPL2PS,
+	ACVTPD2PL,
+	ACVTPD2PS,
+	ACVTPS2PL,
+	ACVTPS2PD,
+	ACVTSD2SL,
+	ACVTSD2SS,
+	ACVTSL2SD,
+	ACVTSL2SS,
+	ACVTSS2SD,
+	ACVTSS2SL,
+	ACVTTPD2PL,
+	ACVTTPS2PL,
+	ACVTTSD2SL,
+	ACVTTSS2SL,
+	ADIVPD,
+	ADIVPS,
+	ADIVSD,
+	ADIVSS,
+	AMASKMOVOU,
+	AMAXPD,
+	AMAXPS,
+	AMAXSD,
+	AMAXSS,
+	AMINPD,
+	AMINPS,
+	AMINSD,
+	AMINSS,
+	AMOVAPD,
+	AMOVAPS,
+	AMOVO,
+	AMOVOU,
+	AMOVHLPS,
+	AMOVHPD,
+	AMOVHPS,
+	AMOVLHPS,
+	AMOVLPD,
+	AMOVLPS,
+	AMOVMSKPD,
+	AMOVMSKPS,
+	AMOVNTO,
+	AMOVNTPD,
+	AMOVNTPS,
+	AMOVSD,
+	AMOVSS,
+	AMOVUPD,
+	AMOVUPS,
+	AMULPD,
+	AMULPS,
+	AMULSD,
+	AMULSS,
+	AORPD,
+	AORPS,
+	APADDQ,
+	APMAXSW,
+	APMAXUB,
+	APMINSW,
+	APMINUB,
+	APSADBW,
+	APSUBB,
+	APSUBL,
+	APSUBQ,
+	APSUBSB,
+	APSUBSW,
+	APSUBUSB,
+	APSUBUSW,
+	APSUBW,
+	APUNPCKHQDQ,
+	APUNPCKLQDQ,
+	ARCPPS,
+	ARCPSS,
+	ARSQRTPS,
+	ARSQRTSS,
+	ASQRTPD,
+	ASQRTPS,
+	ASQRTSD,
+	ASQRTSS,
+	ASUBPD,
+	ASUBPS,
+	ASUBSD,
+	ASUBSS,
+	AUCOMISD,
+	AUCOMISS,
+	AUNPCKHPD,
+	AUNPCKHPS,
+	AUNPCKLPD,
+	AUNPCKLPS,
+	AXORPD,
+	AXORPS,
+	
+	AUSEFIELD,
+	ALOCALS,
+	ATYPE,
 
 	ALAST
 };
@@ -496,17 +615,26 @@ enum
 	D_DR		= 43,
 	D_TR		= 51,
 
-	D_NONE		= 59,
-
-	D_BRANCH	= 60,
-	D_EXTERN	= 61,
-	D_STATIC	= 62,
-	D_AUTO		= 63,
-	D_PARAM		= 64,
-	D_CONST		= 65,
-	D_FCONST	= 66,
-	D_SCONST	= 67,
-	D_ADDR		= 68,
+	D_X0		= 59,
+	D_X1,
+	D_X2,
+	D_X3,
+	D_X4,
+	D_X5,
+	D_X6,
+	D_X7,
+
+	D_NONE		= 67,
+
+	D_BRANCH	= 68,
+	D_EXTERN	= 69,
+	D_STATIC	= 70,
+	D_AUTO		= 71,
+	D_PARAM		= 72,
+	D_CONST		= 73,
+	D_FCONST	= 74,
+	D_SCONST	= 75,
+	D_ADDR		= 76,
 
 	D_FILE,
 	D_FILE1,
@@ -538,7 +666,7 @@ enum
 /*
  * this is the ranlib header
  */
-#define	SYMDEF	"__.SYMDEF"
+#define	SYMDEF	"__.GOSYMDEF"
 
 /*
  * this is the simulated IEEE floating point
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 25ffc78..a00174c 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -70,34 +70,6 @@ datoff(vlong addr)
 	return 0;
 }
 
-enum {
-	ElfStrEmpty,
-	ElfStrInterp,
-	ElfStrHash,
-	ElfStrGot,
-	ElfStrGotPlt,
-	ElfStrDynamic,
-	ElfStrDynsym,
-	ElfStrDynstr,
-	ElfStrRel,
-	ElfStrText,
-	ElfStrData,
-	ElfStrBss,
-	ElfStrShstrtab,
-	ElfStrSymtab,
-	ElfStrStrtab,
-	ElfStrRelPlt,
-	ElfStrPlt,
-	ElfStrGnuVersion,
-	ElfStrGnuVersionR,
-	ElfStrNoteNetbsdIdent,
-	ElfStrNoPtrData,
-	ElfStrNoPtrBss,
-	NElfStr
-};
-
-vlong elfstr[NElfStr];
-
 static int
 needlib(char *name)
 {
@@ -123,6 +95,21 @@ int	nelfsym = 1;
 static void	addpltsym(Sym*);
 static void	addgotsym(Sym*);
 
+Sym *
+lookuprel(void)
+{
+	return lookup(".rel", 0);
+}
+
+void
+adddynrela(Sym *rela, Sym *s, Reloc *r)
+{
+	USED(rela);
+	USED(s);
+	USED(r);
+	sysfatal("adddynrela not implemented");
+}
+
 void
 adddynrel(Sym *s, Reloc *r)
 {
@@ -282,7 +269,36 @@ adddynrel(Sym *s, Reloc *r)
 	diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
 }
 
-static void
+int
+elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+{
+	USED(add);	// written to obj file by ../ld/data.c's reloc
+
+	LPUT(off);
+
+	switch(r->type) {
+	default:
+		return -1;
+
+	case D_ADDR:
+		if(r->siz == 4)
+			LPUT(R_386_32 | elfsym<<8);
+		else
+			return -1;
+		break;
+
+	case D_PCREL:
+		if(r->siz == 4)
+			LPUT(R_386_PC32 | elfsym<<8);
+		else
+			return -1;
+		break;
+	}
+
+	return 0;
+}
+
+void
 elfsetupplt(void)
 {
 	Sym *plt, *got;
@@ -415,6 +431,7 @@ adddynsym(Sym *s)
 	Sym *d, *str;
 	int t;
 	char *name;
+	vlong off;
 	
 	if(s->dynid >= 0)
 		return;
@@ -444,7 +461,7 @@ adddynsym(Sym *s)
 	
 		/* type */
 		t = STB_GLOBAL << 4;
-		if(s->dynexport && s->type == STEXT)
+		if(s->dynexport && (s->type&SMASK) == STEXT)
 			t |= STT_FUNC;
 		else
 			t |= STT_OBJECT;
@@ -478,16 +495,51 @@ adddynsym(Sym *s)
 		name = s->dynimpname;
 		if(name == nil)
 			name = s->name;
-		s->dynid = d->size/12;
+		if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps
+			symgrow(d, ndynexp*12);
+		}
+		if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp()
+			s->dynid = -s->dynid-100;
+			off = s->dynid*12;
+		} else {
+			off = d->size;
+			s->dynid = off/12;
+		}
 		// darwin still puts _ prefixes on all C symbols
 		str = lookup(".dynstr", 0);
-		adduint32(d, str->size);
+		setuint32(d, off, str->size);
+		off += 4;
 		adduint8(str, '_');
 		addstring(str, name);
-		adduint8(d, 0x01);	// type - N_EXT - external symbol
-		adduint8(d, 0);	// section
-		adduint16(d, 0);	// desc
-		adduint32(d, 0);	// value
+		if(s->type == SDYNIMPORT) {
+			setuint8(d, off, 0x01); // type - N_EXT - external symbol
+			off++;
+			setuint8(d, off, 0); // section
+			off++;
+		} else {
+			setuint8(d, off, 0x0f);
+			off++;
+			switch(s->type) {
+			default:
+			case STEXT:
+				setuint8(d, off, 1);
+				break;
+			case SDATA:
+				setuint8(d, off, 2);
+				break;
+			case SBSS:
+				setuint8(d, off, 4);
+				break;
+			}
+			off++;
+		}
+		setuint16(d, off, 0); // desc
+		off += 2;
+		if(s->type == SDYNIMPORT)
+			setuint32(d, off, 0); // value
+		else
+			setaddr(d, off, s);
+		off += 4;
 	} else if(HEADTYPE != Hwindows) {
 		diag("adddynsym: unsupported binary format");
 	}
@@ -514,177 +566,26 @@ adddynlib(char *lib)
 }
 
 void
-doelf(void)
-{
-	Sym *s, *shstrtab, *dynstr;
-
-	if(!iself)
-		return;
-
-	/* predefine strings we need for section headers */
-	shstrtab = lookup(".shstrtab", 0);
-	shstrtab->type = SELFROSECT;
-	shstrtab->reachable = 1;
-
-	elfstr[ElfStrEmpty] = addstring(shstrtab, "");
-	elfstr[ElfStrText] = addstring(shstrtab, ".text");
-	elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata");
-	elfstr[ElfStrData] = addstring(shstrtab, ".data");
-	elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
-	elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
-	if(HEADTYPE == Hnetbsd)
-		elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
-	addstring(shstrtab, ".elfdata");
-	addstring(shstrtab, ".rodata");
-	addstring(shstrtab, ".gosymtab");
-	addstring(shstrtab, ".gopclntab");
-	if(!debug['s']) {
-		elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
-		elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
-		dwarfaddshstrings(shstrtab);
-	}
-	elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
-
-	if(!debug['d']) {	/* -d suppresses dynamic loader format */
-		elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
-		elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
-		elfstr[ElfStrGot] = addstring(shstrtab, ".got");
-		elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
-		elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
-		elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
-		elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
-		elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
-		elfstr[ElfStrRelPlt] = addstring(shstrtab, ".rel.plt");
-		elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
-		elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
-		elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
-
-		/* dynamic symbol table - first entry all zeros */
-		s = lookup(".dynsym", 0);
-		s->type = SELFROSECT;
-		s->reachable = 1;
-		s->size += ELF32SYMSIZE;
-
-		/* dynamic string table */
-		s = lookup(".dynstr", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-		if(s->size == 0)
-			addstring(s, "");
-		dynstr = s;
-
-		/* relocation table */
-		s = lookup(".rel", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-
-		/* global offset table */
-		s = lookup(".got", 0);
-		s->reachable = 1;
-		s->type = SELFSECT; // writable
-		
-		/* hash */
-		s = lookup(".hash", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-
-		/* got.plt */
-		s = lookup(".got.plt", 0);
-		s->reachable = 1;
-		s->type = SELFSECT; // writable
-		
-		s = lookup(".plt", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-
-		s = lookup(".rel.plt", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-		
-		s = lookup(".gnu.version", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-		
-		s = lookup(".gnu.version_r", 0);
-		s->reachable = 1;
-		s->type = SELFROSECT;
-
-		elfsetupplt();
-
-		/* define dynamic elf table */
-		s = lookup(".dynamic", 0);
-		s->reachable = 1;
-		s->type = SELFSECT; // writable
-
-		/*
-		 * .dynamic table
-		 */
-		elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
-		elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
-		elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
-		elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
-		elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
-		elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
-		elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
-		elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
-		if(rpath)
-			elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
-		elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
-		elfwritedynent(s, DT_PLTREL, DT_REL);
-		elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
-		elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
-
-		elfwritedynent(s, DT_DEBUG, 0);
-
-		// Do not write DT_NULL.  elfdynhash will finish it.
-	}
-}
-
-void
-shsym(Elf64_Shdr *sh, Sym *s)
-{
-	vlong addr;
-	addr = symaddr(s);
-	if(sh->flags&SHF_ALLOC)
-		sh->addr = addr;
-	sh->off = datoff(addr);
-	sh->size = s->size;
-}
-
-void
-phsh(Elf64_Phdr *ph, Elf64_Shdr *sh)
-{
-	ph->vaddr = sh->addr;
-	ph->paddr = ph->vaddr;
-	ph->off = sh->off;
-	ph->filesz = sh->size;
-	ph->memsz = sh->size;
-	ph->align = sh->addralign;
-}
-
-void
 asmb(void)
 {
 	int32 v, magic;
-	int a, dynsym;
-	uint32 symo, startva, dwarfoff, machlink, resoff;
-	ElfEhdr *eh;
-	ElfPhdr *ph, *pph;
-	ElfShdr *sh;
+	uint32 symo, dwarfoff, machlink;
 	Section *sect;
 	Sym *sym;
-	int o;
 	int i;
 
 	if(debug['v'])
 		Bprint(&bso, "%5.2f asmb\n", cputime());
 	Bflush(&bso);
 
+	if(iself)
+		asmbelfsetup();
+
 	sect = segtext.sect;
 	cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
 	codeblk(sect->vaddr, sect->len);
 
-	/* output read-only data in text segment (rodata, gosymtab and pclntab) */
+	/* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
 	for(sect = sect->next; sect != nil; sect = sect->next) {
 		cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
 		datblk(sect->vaddr, sect->len);
@@ -712,19 +613,6 @@ asmb(void)
 		machlink = domacholink();
 	}
 
-	if(iself) {
-		/* index of elf text section; needed by asmelfsym, double-checked below */
-		/* !debug['d'] causes extra sections before the .text section */
-		elftextsh = 2;
-		if(!debug['d']) {
-			elftextsh += 10;
-			if(elfverneed)
-				elftextsh += 2;
-		}
-		if(HEADTYPE == Hnetbsd)
-			elftextsh += 1;
-	}
-
 	symsize = 0;
 	spsize = 0;
 	lcsize = 0;
@@ -777,6 +665,9 @@ asmb(void)
 				if(debug['v'])
 					Bprint(&bso, "%5.2f dwarf\n", cputime());
 				dwarfemitdebugsections();
+				
+				if(isobj)
+					elfemitreloc();
 			}
 			break;
 		case Hplan9x32:
@@ -805,8 +696,6 @@ asmb(void)
 	cseek(0L);
 	switch(HEADTYPE) {
 	default:
-		if(iself)
-			goto Elfput;
 	case Hgarbunix:	/* garbage */
 		lputb(0x160L<<16);		/* magic and sections */
 		lputb(0L);			/* time and date */
@@ -932,273 +821,15 @@ asmb(void)
 		wputl(0x003E);			/* reloc table offset */
 		wputl(0x0000);			/* overlay number */
 		break;
-
 	case Hdarwin:
 		asmbmacho();
 		break;
-
-	Elfput:
-		eh = getElfEhdr();
-		startva = INITTEXT - HEADR;
-		resoff = ELFRESERVE;
-
-		/* This null SHdr must appear before all others */
-		newElfShdr(elfstr[ElfStrEmpty]);
-
-		/* program header info */
-		pph = newElfPhdr();
-		pph->type = PT_PHDR;
-		pph->flags = PF_R + PF_X;
-		pph->off = eh->ehsize;
-		pph->vaddr = INITTEXT - HEADR + pph->off;
-		pph->paddr = INITTEXT - HEADR + pph->off;
-		pph->align = INITRND;
-
-		/*
-		 * PHDR must be in a loaded segment. Adjust the text
-		 * segment boundaries downwards to include it.
-		 */
-		o = segtext.vaddr - pph->vaddr;
-		segtext.vaddr -= o;
-		segtext.len += o;
-		o = segtext.fileoff - pph->off;
-		segtext.fileoff -= o;
-		segtext.filelen += o;
-
-		if(!debug['d']) {
-			/* interpreter */
-			sh = newElfShdr(elfstr[ElfStrInterp]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC;
-			sh->addralign = 1;
-			if(interpreter == nil) {
-				switch(HEADTYPE) {
-				case Hlinux:
-					interpreter = linuxdynld;
-					break;
-				case Hfreebsd:
-					interpreter = freebsddynld;
-					break;
-				case Hnetbsd:
-					interpreter = netbsddynld;
-					break;
-				case Hopenbsd:
-					interpreter = openbsddynld;
-					break;
-				}
-			}
-			resoff -= elfinterp(sh, startva, resoff, interpreter);
-
-			ph = newElfPhdr();
-			ph->type = PT_INTERP;
-			ph->flags = PF_R;
-			phsh(ph, sh);
-		}
-
-		if(HEADTYPE == Hnetbsd) {
-			sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
-			sh->type = SHT_NOTE;
-			sh->flags = SHF_ALLOC;
-			sh->addralign = 4;
-			resoff -= elfnetbsdsig(sh, startva, resoff);
-
-			ph = newElfPhdr();
-			ph->type = PT_NOTE;
-			ph->flags = PF_R;
-			phsh(ph, sh);
-		}
-
-		// Additions to the reserved area must be above this line.
-		USED(resoff);
-
-		elfphload(&segtext);
-		elfphload(&segdata);
-
-		/* Dynamic linking sections */
-		if(!debug['d']) {	/* -d suppresses dynamic loader format */
-			/* S headers for dynamic linking */
-			sh = newElfShdr(elfstr[ElfStrGot]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC+SHF_WRITE;
-			sh->entsize = 4;
-			sh->addralign = 4;
-			shsym(sh, lookup(".got", 0));
-
-			sh = newElfShdr(elfstr[ElfStrGotPlt]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC+SHF_WRITE;
-			sh->entsize = 4;
-			sh->addralign = 4;
-			shsym(sh, lookup(".got.plt", 0));
-
-			dynsym = eh->shnum;
-			sh = newElfShdr(elfstr[ElfStrDynsym]);
-			sh->type = SHT_DYNSYM;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = ELF32SYMSIZE;
-			sh->addralign = 4;
-			sh->link = dynsym+1;	// dynstr
-			// sh->info = index of first non-local symbol (number of local symbols)
-			shsym(sh, lookup(".dynsym", 0));
-
-			sh = newElfShdr(elfstr[ElfStrDynstr]);
-			sh->type = SHT_STRTAB;
-			sh->flags = SHF_ALLOC;
-			sh->addralign = 1;
-			shsym(sh, lookup(".dynstr", 0));
-			
-			if(elfverneed) {
-				sh = newElfShdr(elfstr[ElfStrGnuVersion]);
-				sh->type = SHT_GNU_VERSYM;
-				sh->flags = SHF_ALLOC;
-				sh->addralign = 2;
-				sh->link = dynsym;
-				sh->entsize = 2;
-				shsym(sh, lookup(".gnu.version", 0));
-
-				sh = newElfShdr(elfstr[ElfStrGnuVersionR]);
-				sh->type = SHT_GNU_VERNEED;
-				sh->flags = SHF_ALLOC;
-				sh->addralign = 4;
-				sh->info = elfverneed;
-				sh->link = dynsym+1;  // dynstr
-				shsym(sh, lookup(".gnu.version_r", 0));
-			}
-
-			sh = newElfShdr(elfstr[ElfStrRelPlt]);
-			sh->type = SHT_REL;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = ELF32RELSIZE;
-			sh->addralign = 4;
-			sh->link = dynsym;
-			sh->info = eh->shnum;	// .plt
-			shsym(sh, lookup(".rel.plt", 0));
-			
-			sh = newElfShdr(elfstr[ElfStrPlt]);
-			sh->type = SHT_PROGBITS;
-			sh->flags = SHF_ALLOC+SHF_EXECINSTR;
-			sh->entsize = 4;
-			sh->addralign = 4;
-			shsym(sh, lookup(".plt", 0));
-
-			sh = newElfShdr(elfstr[ElfStrHash]);
-			sh->type = SHT_HASH;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = 4;
-			sh->addralign = 4;
-			sh->link = dynsym;
-			shsym(sh, lookup(".hash", 0));
-
-			sh = newElfShdr(elfstr[ElfStrRel]);
-			sh->type = SHT_REL;
-			sh->flags = SHF_ALLOC;
-			sh->entsize = ELF32RELSIZE;
-			sh->addralign = 4;
-			sh->link = dynsym;
-			shsym(sh, lookup(".rel", 0));
-
-			/* sh and PT_DYNAMIC for .dynamic section */
-			sh = newElfShdr(elfstr[ElfStrDynamic]);
-			sh->type = SHT_DYNAMIC;
-			sh->flags = SHF_ALLOC+SHF_WRITE;
-			sh->entsize = 8;
-			sh->addralign = 4;
-			sh->link = dynsym+1;	// dynstr
-			shsym(sh, lookup(".dynamic", 0));
-			ph = newElfPhdr();
-			ph->type = PT_DYNAMIC;
-			ph->flags = PF_R + PF_W;
-			phsh(ph, sh);
-
-			/*
-			 * Thread-local storage segment (really just size).
-			 */
-			if(tlsoffset != 0) {
-				ph = newElfPhdr();
-				ph->type = PT_TLS;
-				ph->flags = PF_R;
-				ph->memsz = -tlsoffset;
-				ph->align = 4;
-			}
-		}
-
-		ph = newElfPhdr();
-		ph->type = PT_GNU_STACK;
-		ph->flags = PF_W+PF_R;
-		ph->align = 4;
-
-		sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
-		sh->type = SHT_STRTAB;
-		sh->addralign = 1;
-		shsym(sh, lookup(".shstrtab", 0));
-
-		if(elftextsh != eh->shnum)
-			diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
-		for(sect=segtext.sect; sect!=nil; sect=sect->next)
-			elfshbits(sect);
-		for(sect=segdata.sect; sect!=nil; sect=sect->next)
-			elfshbits(sect);
-
-		if(!debug['s']) {
-			sh = newElfShdr(elfstr[ElfStrSymtab]);
-			sh->type = SHT_SYMTAB;
-			sh->off = symo;
-			sh->size = symsize;
-			sh->addralign = 4;
-			sh->entsize = 16;
-			sh->link = eh->shnum;	// link to strtab
-
-			sh = newElfShdr(elfstr[ElfStrStrtab]);
-			sh->type = SHT_STRTAB;
-			sh->off = symo+symsize;
-			sh->size = elfstrsize;
-			sh->addralign = 1;
-
-			dwarfaddelfheaders();
-		}
-
-		/* Main header */
-		eh->ident[EI_MAG0] = '\177';
-		eh->ident[EI_MAG1] = 'E';
-		eh->ident[EI_MAG2] = 'L';
-		eh->ident[EI_MAG3] = 'F';
-		eh->ident[EI_CLASS] = ELFCLASS32;
-		eh->ident[EI_DATA] = ELFDATA2LSB;
-		eh->ident[EI_VERSION] = EV_CURRENT;
-		switch(HEADTYPE) {
-		case Hfreebsd:
-			eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
-			break;
-		case Hnetbsd:
-			eh->ident[EI_OSABI] = ELFOSABI_NETBSD;
-			break;
-		case Hopenbsd:
-			eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
-			break;
-		}
-
-		eh->type = ET_EXEC;
-		eh->machine = EM_386;
-		eh->version = EV_CURRENT;
-		eh->entry = entryvalue();
-
-		if(pph != nil) {
-			pph->filesz = eh->phnum * eh->phentsize;
-			pph->memsz = pph->filesz;
-		}
-
-		cseek(0);
-		a = 0;
-		a += elfwritehdr();
-		a += elfwritephdrs();
-		a += elfwriteshdrs();
-		a += elfwriteinterp(elfstr[ElfStrInterp]);
-		if(HEADTYPE == Hnetbsd)
-			a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
-		if(a > ELFRESERVE)	
-			diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
+	case Hlinux:
+	case Hfreebsd:
+	case Hnetbsd:
+	case Hopenbsd:
+		asmbelf(symo);
 		break;
-
 	case Hwindows:
 		asmbpe();
 		break;
@@ -1231,80 +862,3 @@ rnd(int32 v, int32 r)
 	v -= c;
 	return v;
 }
-
-void
-genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
-{
-	Auto *a;
-	Sym *s;
-	int h;
-
-	s = lookup("etext", 0);
-	if(s->type == STEXT)
-		put(s, s->name, 'T', s->value, s->size, s->version, 0);
-
-	for(h=0; h<NHASH; h++) {
-		for(s=hash[h]; s!=S; s=s->hash) {
-			if(s->hide)
-				continue;
-			switch(s->type&~SSUB) {
-			case SCONST:
-			case SRODATA:
-			case SDATA:
-			case SELFROSECT:
-			case SMACHO:
-			case SMACHOGOT:
-			case STYPE:
-			case SSTRING:
-			case SGOSTRING:
-			case SWINDOWS:
-			case SNOPTRDATA:
-			case SSYMTAB:
-			case SPCLNTAB:
-				if(!s->reachable)
-					continue;
-				put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
-				continue;
-
-			case SBSS:
-			case SNOPTRBSS:
-				if(!s->reachable)
-					continue;
-				put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
-				continue;
-
-			case SFILE:
-				put(nil, s->name, 'f', s->value, 0, s->version, 0);
-				continue;
-			}
-		}
-	}
-
-	for(s = textp; s != nil; s = s->next) {
-		if(s->text == nil)
-			continue;
-
-		/* filenames first */
-		for(a=s->autom; a; a=a->link)
-			if(a->type == D_FILE)
-				put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0);
-			else
-			if(a->type == D_FILE1)
-				put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
-
-		put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
-
-		/* frame, auto and param after */
-		put(nil, ".frame", 'm', s->text->to.offset+4, 0, 0, 0);
-
-		for(a=s->autom; a; a=a->link)
-			if(a->type == D_AUTO)
-				put(nil, a->asym->name, 'a', -a->aoffset, 0, 0, a->gotype);
-			else
-			if(a->type == D_PARAM)
-				put(nil, a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
-	}
-	if(debug['v'] || debug['n'])
-		Bprint(&bso, "symsize = %d\n", symsize);
-	Bflush(&bso);
-}
diff --git a/src/cmd/8l/doc.go b/src/cmd/8l/doc.go
index 12301d4..ff06bc3 100644
--- a/src/cmd/8l/doc.go
+++ b/src/cmd/8l/doc.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 ignore
+
 /*
 
 8l is the linker for the 32-bit x86.
@@ -10,4 +12,4 @@ The $GOARCH for these tools is 386.
 The flags are documented in ../ld/doc.go.
 
 */
-package documentation
+package main
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index b974f46..f88f058 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -40,7 +40,9 @@
 enum
 {
 	thechar = '8',
-	PtrSize = 4
+	PtrSize = 4,
+	IntSize = 4,
+	FuncAlign = 16
 };
 
 #define	P		((Prog*)0)
@@ -135,16 +137,22 @@ struct	Sym
 	int32	plt;
 	int32	got;
 	int32	align;	// if non-zero, required alignment in bytes
+	int32	elfsym;
+	int32	locals;	// size of stack frame locals area
+	int32	args;	// size of stack frame incoming arguments area
 	Sym*	hash;	// in hash table
 	Sym*	allsym;	// in all symbol list
 	Sym*	next;	// in text or data list
 	Sym*	sub;	// in sub list
 	Sym*	outer;	// container of sub
 	Sym*	gotype;
+	Sym*	reachparent;
+	Sym*	queue;
 	char*	file;
 	char*	dynimpname;
 	char*	dynimplib;
 	char*	dynimpvers;
+	struct Section*	sect;
 	
 	// STEXT
 	Auto*	autom;
@@ -157,6 +165,7 @@ struct	Sym
 	Reloc*	r;
 	int32	nr;
 	int32	maxr;
+	int 	rel_ro;
 };
 struct	Optab
 {
@@ -201,6 +210,8 @@ enum
 	Ycr0,	Ycr1,	Ycr2,	Ycr3,	Ycr4,	Ycr5,	Ycr6,	Ycr7,
 	Ydr0,	Ydr1,	Ydr2,	Ydr3,	Ydr4,	Ydr5,	Ydr6,	Ydr7,
 	Ytr0,	Ytr1,	Ytr2,	Ytr3,	Ytr4,	Ytr5,	Ytr6,	Ytr7,
+	Ymr, Ymm,
+	Yxr, Yxm,
 	Ymax,
 
 	Zxxx		= 0,
@@ -222,10 +233,14 @@ enum
 	Zloop,
 	Zm_o,
 	Zm_r,
+	Zm_r_xm,
+	Zm_r_i_xm,
 	Zaut_r,
 	Zo_m,
 	Zpseudo,
 	Zr_m,
+	Zr_m_xm,
+	Zr_m_i_xm,
 	Zrp_,
 	Z_ib,
 	Z_il,
@@ -243,6 +258,8 @@ enum
 	Pm		= 0x0f,	/* 2byte opcode escape */
 	Pq		= 0xff,	/* both escape */
 	Pb		= 0xfe,	/* byte operands */
+	Pf2		= 0xf2,	/* xmm escape 1 */
+	Pf3		= 0xf3,	/* xmm escape 2 */
 };
 
 #pragma	varargck	type	"A"	int
@@ -261,6 +278,7 @@ EXTERN	int32	INITRND;
 EXTERN	int32	INITTEXT;
 EXTERN	int32	INITDAT;
 EXTERN	char*	INITENTRY;		/* entry point */
+EXTERN	char*	LIBINITENTRY;		/* shared library entry point */
 EXTERN	int32	casepc;
 EXTERN	char*	pcstr;
 EXTERN	Auto*	curauto;
@@ -269,7 +287,7 @@ EXTERN	Prog*	curp;
 EXTERN	Sym*	cursym;
 EXTERN	Sym*	datap;
 EXTERN	int32	elfdatsize;
-EXTERN	char	debug[128];
+EXTERN	int	debug[128];
 EXTERN	char	literal[32];
 EXTERN	Sym*	etextp;
 EXTERN	Prog*	firstp;
@@ -282,7 +300,6 @@ EXTERN	int	maxop;
 EXTERN	int	nerrors;
 EXTERN	char*	noname;
 EXTERN	int32	pc;
-EXTERN	char*	interpreter;
 EXTERN	char*	rpath;
 EXTERN	int32	spsize;
 EXTERN	Sym*	symlist;
diff --git a/src/cmd/8l/list.c b/src/cmd/8l/list.c
index 31ae023..0b544fb 100644
--- a/src/cmd/8l/list.c
+++ b/src/cmd/8l/list.c
@@ -254,6 +254,15 @@ char*	regstr[] =
 	"TR5",
 	"TR6",
 	"TR7",
+	
+	"X0",
+	"X1",
+	"X2",
+	"X3",
+	"X4",
+	"X5",
+	"X6",
+	"X7",
 
 	"NONE",		/* [D_NONE] */
 };
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index af4bc84..dcb8390 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -77,18 +77,8 @@ Header headers[] = {
  */
 
 void
-usage(void)
-{
-	fprint(2, "usage: 8l [-options] [-E entry] [-H head] [-I interpreter] [-L dir] [-T text] [-R rnd] [-r path] [-o out] main.8\n");
-	exits("usage");
-}
-
-void
 main(int argc, char *argv[])
 {
-	int c;
-	char *name, *val;
-
 	Binit(&bso, 1, OWRITE);
 	listinit();
 	memset(debug, 0, sizeof(debug));
@@ -99,52 +89,44 @@ main(int argc, char *argv[])
 	INITDAT = -1;
 	INITRND = -1;
 	INITENTRY = 0;
+	LIBINITENTRY = 0;
 	nuxiinit();
 
-	ARGBEGIN {
-	default:
-		c = ARGC();
-		if(c == 'l')
-			usage();
- 		if(c >= 0 && c < sizeof(debug))
-			debug[c]++;
-		break;
-	case 'o': /* output to (next arg) */
-		outfile = EARGF(usage());
-		break;
-	case 'E':
-		INITENTRY = EARGF(usage());
-		break;
-	case 'H':
-		HEADTYPE = headtype(EARGF(usage()));
-		break;
-	case 'I':
-		interpreter = EARGF(usage());
-		break;
-	case 'L':
-		Lflag(EARGF(usage()));
-		break;
-	case 'T':
-		INITTEXT = atolwhex(EARGF(usage()));
-		break;
-	case 'D':
-		INITDAT = atolwhex(EARGF(usage()));
-		break;
-	case 'R':
-		INITRND = atolwhex(EARGF(usage()));
-		break;
-	case 'r':
-		rpath = EARGF(usage());
-		break;
-	case 'V':
-		print("%cl version %s\n", thechar, getgoversion());
-		errorexit();
-	case 'X':
-		name = EARGF(usage());
-		val = EARGF(usage());
-		addstrdata(name, val);
-		break;
-	} ARGEND
+	flagcount("1", "use alternate profiling code", &debug['1']);
+	flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo);
+	flagstr("E", "sym: entry symbol", &INITENTRY);
+	flagint32("D", "addr: data address", &INITDAT);
+	flagfn1("I", "interp: set ELF interp", setinterp);
+	flagfn1("L", "dir: add dir to library path", Lflag);
+	flagfn1("H", "head: header type", setheadtype);
+	flagcount("K", "add stack underflow checks", &debug['K']);
+	flagcount("O", "print pc-line tables", &debug['O']);
+	flagcount("Q", "debug byte-register code gen", &debug['Q']);
+	flagint32("R", "rnd: address rounding", &INITRND);
+	flagcount("S", "check type signatures", &debug['S']);
+	flagint32("T", "addr: text address", &INITTEXT);
+	flagfn0("V", "print version and exit", doversion);
+	flagcount("W", "disassemble input", &debug['W']);
+	flagfn2("X", "name value: define string data", addstrdata);
+	flagcount("Z", "clear stack frame on entry", &debug['Z']);
+	flagcount("a", "disassemble output", &debug['a']);
+	flagcount("c", "dump call graph", &debug['c']);
+	flagcount("d", "disable dynamic executable", &debug['d']);
+	flagcount("f", "ignore version mismatch", &debug['f']);
+	flagcount("g", "disable go package data checks", &debug['g']);
+	flagcount("hostobj", "generate host object file", &isobj);
+	flagstr("k", "sym: set field tracking symbol", &tracksym);
+	flagstr("o", "outfile: set output file", &outfile);
+	flagcount("p", "insert profiling code", &debug['p']);
+	flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
+	flagcount("race", "enable race detector", &flag_race);
+	flagcount("s", "disable symbol table", &debug['s']);
+	flagcount("n", "dump symbol table", &debug['n']);
+	flagcount("u", "reject unsafe packages", &debug['u']);
+	flagcount("v", "print link trace", &debug['v']);
+	flagcount("w", "disable DWARF generation", &debug['w']);
+	
+	flagparse(&argc, &argv, usage);
 
 	if(argc != 1)
 		usage();
@@ -154,6 +136,15 @@ main(int argc, char *argv[])
 	if(HEADTYPE == -1)
 		HEADTYPE = headtype(goos);
 
+	if(isobj) {
+		switch(HEADTYPE) {
+		default:
+			sysfatal("cannot use -hostobj with -H %s", headstr(HEADTYPE));
+		case Hlinux:
+			break;
+		}
+	}
+
 	if(outfile == nil) {
 		if(HEADTYPE == Hwindows)
 			outfile = "8.out.exe";
@@ -300,6 +291,7 @@ main(int argc, char *argv[])
 	if(HEADTYPE == Hwindows)
 		dope();
 	dostkoff();
+	dostkcheck();
 	if(debug['p'])
 		if(debug['1'])
 			doprof1();
@@ -332,7 +324,7 @@ zsym(char *pn, Biobuf *f, Sym *h[])
 {	
 	int o;
 	
-	o = Bgetc(f);
+	o = BGETC(f);
 	if(o < 0 || o >= NSYM || h[o] == nil)
 		mangle(pn);
 	return h[o];
@@ -346,12 +338,12 @@ zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
 	Sym *s;
 	Auto *u;
 
-	t = Bgetc(f);
+	t = BGETC(f);
 	a->index = D_NONE;
 	a->scale = 0;
 	if(t & T_INDEX) {
-		a->index = Bgetc(f);
-		a->scale = Bgetc(f);
+		a->index = BGETC(f);
+		a->scale = BGETC(f);
 	}
 	a->type = D_NONE;
 	a->offset = 0;
@@ -375,7 +367,7 @@ zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
 		a->type = D_SCONST;
 	}
 	if(t & T_TYPE)
-		a->type = Bgetc(f);
+		a->type = BGETC(f);
 	adrgotype = S;
 	if(t & T_GOTYPE)
 		adrgotype = zsym(pn, f, h);
@@ -451,10 +443,10 @@ newloop:
 loop:
 	if(f->state == Bracteof || Boffset(f) >= eof)
 		goto eof;
-	o = Bgetc(f);
+	o = BGETC(f);
 	if(o == Beof)
 		goto eof;
-	o |= Bgetc(f) << 8;
+	o |= BGETC(f) << 8;
 	if(o <= AXXX || o >= ALAST) {
 		if(o < 0)
 			goto eof;
@@ -467,8 +459,8 @@ loop:
 		sig = 0;
 		if(o == ASIGNAME)
 			sig = Bget4(f);
-		v = Bgetc(f);	/* type */
-		o = Bgetc(f);	/* sym */
+		v = BGETC(f);	/* type */
+		o = BGETC(f);	/* sym */
 		r = 0;
 		if(v == D_STATIC)
 			r = version;
@@ -523,8 +515,6 @@ loop:
 	p->as = o;
 	p->line = Bget4(f);
 	p->back = 2;
-	p->ft = 0;
-	p->tt = 0;
 	zaddr(pn, f, &p->from, h);
 	fromgotype = adrgotype;
 	zaddr(pn, f, &p->to, h);
@@ -605,6 +595,15 @@ loop:
 		pc++;
 		goto loop;
 
+	case ALOCALS:
+		cursym->locals = p->to.offset;
+		pc++;
+		goto loop;
+
+	case ATYPE:
+		pc++;
+		goto loop;
+
 	case ATEXT:
 		s = p->from.sym;
 		if(s->text != nil) {
@@ -643,6 +642,7 @@ loop:
 		}
 		s->type = STEXT;
 		s->value = pc;
+		s->args = p->to.offset2;
 		lastp = p;
 		p->pc = pc++;
 		goto loop;
@@ -656,6 +656,13 @@ loop:
 	case AFDIVRF:
 	case AFCOMF:
 	case AFCOMFP:
+	case AMOVSS:
+	case AADDSS:
+	case ASUBSS:
+	case AMULSS:
+	case ADIVSS:
+	case ACOMISS:
+	case AUCOMISS:
 		if(skip)
 			goto casdef;
 		if(p->from.type == D_FCONST) {
@@ -663,7 +670,7 @@ loop:
 			sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
 			s = lookup(literal, 0);
 			if(s->type == 0) {
-				s->type = SDATA;
+				s->type = SRODATA;
 				adduint32(s, ieeedtof(&p->from.ieee));
 				s->reachable = 0;
 			}
@@ -682,6 +689,13 @@ loop:
 	case AFDIVRD:
 	case AFCOMD:
 	case AFCOMDP:
+	case AMOVSD:
+	case AADDSD:
+	case ASUBSD:
+	case AMULSD:
+	case ADIVSD:
+	case ACOMISD:
+	case AUCOMISD:
 		if(skip)
 			goto casdef;
 		if(p->from.type == D_FCONST) {
@@ -690,7 +704,7 @@ loop:
 				p->from.ieee.l, p->from.ieee.h);
 			s = lookup(literal, 0);
 			if(s->type == 0) {
-				s->type = SDATA;
+				s->type = SRODATA;
 				adduint32(s, p->from.ieee.l);
 				adduint32(s, p->from.ieee.h);
 				s->reachable = 0;
diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c
index 8564822..79d7b39 100644
--- a/src/cmd/8l/optab.c
+++ b/src/cmd/8l/optab.c
@@ -242,6 +242,11 @@ uchar	ypopl[] =
 	Ynone,	Ym,	Zo_m,	2,
 	0
 };
+uchar	ybswap[] =
+{
+	Ynone,	Yrl,	Z_rp,	1,
+	0,
+};
 uchar	yscond[] =
 {
 	Ynone,	Ymb,	Zo_m,	2,
@@ -249,7 +254,9 @@ uchar	yscond[] =
 };
 uchar	yjcond[] =
 {
-	Ynone,	Ybr,	Zbr,	1,
+	Ynone,	Ybr,	Zbr,	0,
+	Yi0,	Ybr,	Zbr,	0,
+	Yi1,	Ybr,	Zbr,	1,
 	0
 };
 uchar	yloop[] =
@@ -259,7 +266,8 @@ uchar	yloop[] =
 };
 uchar	ycall[] =
 {
-	Ynone,	Yml,	Zo_m,	2,
+	Ynone,	Yml,	Zo_m,	0,
+	Yrx,	Yrx,	Zo_m,	2,
 	Ynone,	Ycol,	Zcallind,	2,
 	Ynone,	Ybr,	Zcall,	0,
 	Ynone,	Yi32,	Zcallcon,	1,
@@ -349,6 +357,84 @@ uchar	ysvrs[] =
 	Ym,	Ynone,	Zm_o,	2,
 	0
 };
+uchar	yxm[] = 
+{
+	Yxm,	Yxr,	Zm_r_xm,	1,
+	0
+};
+uchar	yxcvm1[] = 
+{
+	Yxm,	Yxr,	Zm_r_xm,	2,
+	Yxm,	Ymr,	Zm_r_xm,	2,
+	0
+};
+uchar	yxcvm2[] =
+{
+	Yxm,	Yxr,	Zm_r_xm,	2,
+	Ymm,	Yxr,	Zm_r_xm,	2,
+	0
+};
+uchar	yxmq[] = 
+{
+	Yxm,	Yxr,	Zm_r_xm,	2,
+	0
+};
+uchar	yxr[] = 
+{
+	Yxr,	Yxr,	Zm_r_xm,	1,
+	0
+};
+uchar	yxr_ml[] =
+{
+	Yxr,	Yml,	Zr_m_xm,	1,
+	0
+};
+uchar	yxcmp[] =
+{
+	Yxm,	Yxr, Zm_r_xm,	1,
+	0
+};
+uchar	yxcmpi[] =
+{
+	Yxm,	Yxr, Zm_r_i_xm,	2,
+	0
+};
+uchar	yxmov[] =
+{
+	Yxm,	Yxr,	Zm_r_xm,	1,
+	Yxr,	Yxm,	Zr_m_xm,	1,
+	0
+};
+uchar	yxcvfl[] = 
+{
+	Yxm,	Yrl,	Zm_r_xm,	1,
+	0
+};
+uchar	yxcvlf[] =
+{
+	Yml,	Yxr,	Zm_r_xm,	1,
+	0
+};
+uchar	yxcvfq[] = 
+{
+	Yxm,	Yrl,	Zm_r_xm,	2,
+	0
+};
+uchar	yxcvqf[] =
+{
+	Yml,	Yxr,	Zm_r_xm,	2,
+	0
+};
+uchar	yxrrl[] =
+{
+	Yxr,	Yrl,	Zm_r,	1,
+	0
+};
+uchar	yprefetch[] =
+{
+	Ym,	Ynone,	Zm_o,	2,
+	0,
+};
 
 Optab optab[] =
 /*	as, ytab, andproto, opcode */
@@ -761,5 +847,123 @@ Optab optab[] =
 
 	{ 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 },
+	{ APMAXSW,	yxm,	Pe, 0xee },
+	{ APMAXUB,	yxm,	Pe, 0xde },
+	{ APMINSW,	yxm,	Pe, 0xea },
+	{ APMINUB,	yxm,	Pe, 0xda },
+	{ 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 },
+	{ 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 },
+
+	{ AUSEFIELD,	ynop,	Px, 0,0 },
+	{ ALOCALS },
+	{ ATYPE },
+
 	0
 };
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
index 9034fdf..14dd3e0 100644
--- a/src/cmd/8l/pass.c
+++ b/src/cmd/8l/pass.c
@@ -75,6 +75,7 @@ nofollow(int a)
 	case ARET:
 	case AIRETL:
 	case AIRETW:
+	case AUNDEF:
 		return 1;
 	}
 	return 0;
@@ -184,20 +185,34 @@ loop:
 		 * recurse to follow one path.
 		 * continue loop on the other.
 		 */
-		q = brchain(p->link);
-		if(q != P && q->mark)
-		if(a != ALOOP) {
-			p->as = relinv(a);
-			p->link = p->pcond;
+		if((q = brchain(p->pcond)) != P)
 			p->pcond = q;
+		if((q = brchain(p->link)) != P)
+			p->link = q;
+		if(p->from.type == D_CONST) {
+			if(p->from.offset == 1) {
+				/*
+				 * expect conditional jump to be taken.
+				 * rewrite so that's the fall-through case.
+				 */
+				p->as = relinv(a);
+				q = p->link;
+				p->link = p->pcond;
+				p->pcond = q;
+			}
+		} else {
+			q = p->link;
+			if(q->mark)
+			if(a != ALOOP) {
+				p->as = relinv(a);
+				p->link = p->pcond;
+				p->pcond = q;
+			}
 		}
 		xfol(p->link, last);
-		q = brchain(p->pcond);
-		if(q->mark) {
-			p->pcond = q;
+		if(p->pcond->mark)
 			return;
-		}
-		p = q;
+		p = p->pcond;
 		goto loop;
 	}
 	p = p->link;
@@ -315,7 +330,7 @@ patch(void)
 				} else if(s) {
 					if(debug['c'])
 						Bprint(&bso, "%s calls %s\n", TNAME, s->name);
-					if((s->type&~SSUB) != STEXT) {
+					if((s->type&SMASK) != STEXT) {
 						/* diag prints TNAME first */
 						diag("undefined: %s", s->name);
 						s->type = STEXT;
@@ -524,9 +539,9 @@ dostkoff(void)
 				q = p;
 			}
 
-			p = appendp(p);	// save frame size in DX
+			p = appendp(p);	// save frame size in DI
 			p->as = AMOVL;
-			p->to.type = D_DX;
+			p->to.type = D_DI;
 			p->from.type = D_CONST;
 
 			// If we ask for more stack, we'll get a minimum of StackMin bytes.
@@ -565,9 +580,47 @@ dostkoff(void)
 			p->spadj = autoffset;
 			if(q != P)
 				q->pcond = p;
+		} else {
+			// zero-byte stack adjustment.
+			// Insert a fake non-zero adjustment so that stkcheck can
+			// recognize the end of the stack-splitting prolog.
+			p = appendp(p);
+			p->as = ANOP;
+			p->spadj = -PtrSize;
+			p = appendp(p);
+			p->as = ANOP;
+			p->spadj = PtrSize;
 		}
 		deltasp = autoffset;
 		
+		if(debug['Z'] && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
+			// 8l -Z means zero the stack frame on entry.
+			// This slows down function calls but can help avoid
+			// false positives in garbage collection.
+			p = appendp(p);
+			p->as = AMOVL;
+			p->from.type = D_SP;
+			p->to.type = D_DI;
+			
+			p = appendp(p);
+			p->as = AMOVL;
+			p->from.type = D_CONST;
+			p->from.offset = autoffset/4;
+			p->to.type = D_CX;
+			
+			p = appendp(p);
+			p->as = AMOVL;
+			p->from.type = D_CONST;
+			p->from.offset = 0;
+			p->to.type = D_AX;
+			
+			p = appendp(p);
+			p->as = AREP;
+			
+			p = appendp(p);
+			p->as = ASTOSL;
+		}
+		
 		for(; p != P; p = p->link) {
 			a = p->from.type;
 			if(a == D_AUTO)
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index 81c1d37..b828d86 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -194,7 +194,7 @@ instinit(void)
 
 	for(i=1; optab[i].as; i++)
 		if(i != optab[i].as) {
-			diag("phase error in optab: %d", i);
+			diag("phase error in optab: at %A found %A", i, optab[i].as);
 			errorexit();
 		}
 	maxop = i;
@@ -238,6 +238,16 @@ instinit(void)
 	ycover[Yrl*Ymax + Yml] = 1;
 	ycover[Ym*Ymax + Yml] = 1;
 
+	ycover[Yax*Ymax + Ymm] = 1;
+	ycover[Ycx*Ymax + Ymm] = 1;
+	ycover[Yrx*Ymax + Ymm] = 1;
+	ycover[Yrl*Ymax + Ymm] = 1;
+	ycover[Ym*Ymax + Ymm] = 1;
+	ycover[Ymr*Ymax + Ymm] = 1;
+
+	ycover[Ym*Ymax + Yxm] = 1;
+	ycover[Yxr*Ymax + Yxm] = 1;
+
 	for(i=0; i<D_NONE; i++) {
 		reg[i] = -1;
 		if(i >= D_AL && i <= D_BH)
@@ -246,6 +256,8 @@ instinit(void)
 			reg[i] = (i-D_AX) & 7;
 		if(i >= D_F0 && i <= D_F0+7)
 			reg[i] = (i-D_F0) & 7;
+		if(i >= D_X0 && i <= D_X0+7)
+			reg[i] = (i-D_X0) & 7;
 	}
 }
 
@@ -333,6 +345,16 @@ oclass(Adr *a)
 	case D_F0+7:
 		return	Yrf;
 
+	case D_X0+0:
+	case D_X0+1:
+	case D_X0+2:
+	case D_X0+3:
+	case D_X0+4:
+	case D_X0+5:
+	case D_X0+6:
+	case D_X0+7:
+		return	Yxr;
+
 	case D_NONE:
 		return Ynone;
 
@@ -585,7 +607,7 @@ asmand(Adr *a, int r)
 		asmidx(a->scale, a->index, t);
 		goto putrelv;
 	}
-	if(t >= D_AL && t <= D_F0+7) {
+	if(t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7) {
 		if(v)
 			goto bad;
 		*andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
@@ -772,19 +794,71 @@ uchar	ymovtab[] =
 	0
 };
 
+// byteswapreg returns a byte-addressable register (AX, BX, CX, DX)
+// which is not referenced in a->type.
+// If a is empty, it returns BX to account for MULB-like instructions
+// that might use DX and AX.
 int
-isax(Adr *a)
+byteswapreg(Adr *a)
 {
+	int cana, canb, canc, cand;
+
+	cana = canb = canc = cand = 1;
 
 	switch(a->type) {
+	case D_NONE:
+		cana = cand = 0;
+		break;
 	case D_AX:
 	case D_AL:
 	case D_AH:
 	case D_INDIR+D_AX:
-		return 1;
+		cana = 0;
+		break;
+	case D_BX:
+	case D_BL:
+	case D_BH:
+	case D_INDIR+D_BX:
+		canb = 0;
+		break;
+	case D_CX:
+	case D_CL:
+	case D_CH:
+	case D_INDIR+D_CX:
+		canc = 0;
+		break;
+	case D_DX:
+	case D_DL:
+	case D_DH:
+	case D_INDIR+D_DX:
+		cand = 0;
+		break;
+	}
+	switch(a->index) {
+	case D_AX:
+		cana = 0;
+		break;
+	case D_BX:
+		canb = 0;
+		break;
+	case D_CX:
+		canc = 0;
+		break;
+	case D_DX:
+		cand = 0;
+		break;
 	}
-	if(a->index == D_AX)
-		return 1;
+	if(cana)
+		return D_AX;
+	if(canb)
+		return D_BX;
+	if(canc)
+		return D_CX;
+	if(cand)
+		return D_DX;
+
+	diag("impossible byte register");
+	errorexit();
 	return 0;
 }
 
@@ -827,13 +901,37 @@ subreg(Prog *p, int from, int to)
 		print("%P\n", p);
 }
 
+static int
+mediaop(Optab *o, int op, int osize, int z)
+{
+	switch(op){
+	case Pm:
+	case Pe:
+	case Pf2:
+	case Pf3:
+		if(osize != 1){
+			if(op != Pm)
+				*andptr++ = op;
+			*andptr++ = Pm;
+			op = o->op[++z];
+			break;
+		}
+	default:
+		if(andptr == and || andptr[-1] != Pm)
+			*andptr++ = Pm;
+		break;
+	}
+	*andptr++ = op;
+	return z;
+}
+
 void
 doasm(Prog *p)
 {
 	Optab *o;
 	Prog *q, pp;
 	uchar *t;
-	int z, op, ft, tt;
+	int z, op, ft, tt, breg;
 	int32 v, pre;
 	Reloc rel, *r;
 	Adr *a;
@@ -873,6 +971,12 @@ found:
 		*andptr++ = Pm;
 		break;
 
+	case Pf2:	/* xmm opcode escape */
+	case Pf3:
+		*andptr++ = o->prefix;
+		*andptr++ = Pm;
+		break;
+
 	case Pm:	/* opcode escape */
 		*andptr++ = Pm;
 		break;
@@ -904,6 +1008,17 @@ found:
 		asmand(&p->from, reg[p->to.type]);
 		break;
 
+	case Zm_r_xm:
+		mediaop(o, op, t[3], z);
+		asmand(&p->from, reg[p->to.type]);
+		break;
+
+	case Zm_r_i_xm:
+		mediaop(o, op, t[3], z);
+		asmand(&p->from, reg[p->to.type]);
+		*andptr++ = p->to.offset;
+		break;
+
 	case Zaut_r:
 		*andptr++ = 0x8d;	/* leal */
 		if(p->from.type != D_ADDR)
@@ -927,6 +1042,17 @@ found:
 		asmand(&p->to, reg[p->from.type]);
 		break;
 
+	case Zr_m_xm:
+		mediaop(o, op, t[3], z);
+		asmand(&p->to, reg[p->from.type]);
+		break;
+
+	case Zr_m_i_xm:
+		mediaop(o, op, t[3], z);
+		asmand(&p->to, reg[p->from.type]);
+		*andptr++ = p->from.offset;
+		break;
+
 	case Zo_m:
 		*andptr++ = op;
 		asmand(&p->to, o->op[z+1]);
@@ -1198,13 +1324,13 @@ bad:
 	pp = *p;
 	z = p->from.type;
 	if(z >= D_BP && z <= D_DI) {
-		if(isax(&p->to)) {
+		if((breg = byteswapreg(&p->to)) != D_AX) {
 			*andptr++ = 0x87;			/* xchg lhs,bx */
-			asmand(&p->from, reg[D_BX]);
-			subreg(&pp, z, D_BX);
+			asmand(&p->from, reg[breg]);
+			subreg(&pp, z, breg);
 			doasm(&pp);
 			*andptr++ = 0x87;			/* xchg lhs,bx */
-			asmand(&p->from, reg[D_BX]);
+			asmand(&p->from, reg[breg]);
 		} else {
 			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
 			subreg(&pp, z, D_AX);
@@ -1215,13 +1341,13 @@ bad:
 	}
 	z = p->to.type;
 	if(z >= D_BP && z <= D_DI) {
-		if(isax(&p->from)) {
+		if((breg = byteswapreg(&p->from)) != D_AX) {
 			*andptr++ = 0x87;			/* xchg rhs,bx */
-			asmand(&p->to, reg[D_BX]);
-			subreg(&pp, z, D_BX);
+			asmand(&p->to, reg[breg]);
+			subreg(&pp, z, breg);
 			doasm(&pp);
 			*andptr++ = 0x87;			/* xchg rhs,bx */
-			asmand(&p->to, reg[D_BX]);
+			asmand(&p->to, reg[breg]);
 		} else {
 			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
 			subreg(&pp, z, D_AX);
diff --git a/src/cmd/api/clone.go b/src/cmd/api/clone.go
new file mode 100644
index 0000000..180215f
--- /dev/null
+++ b/src/cmd/api/clone.go
@@ -0,0 +1,251 @@
+// 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 main
+
+import (
+	"fmt"
+	"go/ast"
+	"log"
+	"reflect"
+)
+
+const debugClone = false
+
+// TODO(bradfitz): delete this function (and whole file) once
+// http://golang.org/issue/4380 is fixed.
+func clone(i interface{}) (cloned interface{}) {
+	if debugClone {
+		defer func() {
+			if !reflect.DeepEqual(i, cloned) {
+				log.Printf("cloned %T doesn't match: in=%#v out=%#v", i, i, cloned)
+			}
+		}()
+	}
+	switch v := i.(type) {
+	case nil:
+		return nil
+	case *ast.File:
+		o := &ast.File{
+			Doc:      v.Doc, // shallow
+			Package:  v.Package,
+			Comments: v.Comments, // shallow
+			Name:     v.Name,
+			Scope:    v.Scope,
+		}
+		for _, x := range v.Decls {
+			o.Decls = append(o.Decls, clone(x).(ast.Decl))
+		}
+		for _, x := range v.Imports {
+			o.Imports = append(o.Imports, clone(x).(*ast.ImportSpec))
+		}
+		for _, x := range v.Unresolved {
+			o.Unresolved = append(o.Unresolved, x)
+		}
+		return o
+	case *ast.GenDecl:
+		o := new(ast.GenDecl)
+		*o = *v
+		o.Specs = nil
+		for _, x := range v.Specs {
+			o.Specs = append(o.Specs, clone(x).(ast.Spec))
+		}
+		return o
+	case *ast.TypeSpec:
+		o := new(ast.TypeSpec)
+		*o = *v
+		o.Type = cloneExpr(v.Type)
+		return o
+	case *ast.InterfaceType:
+		o := new(ast.InterfaceType)
+		*o = *v
+		o.Methods = clone(v.Methods).(*ast.FieldList)
+		return o
+	case *ast.FieldList:
+		if v == nil {
+			return v
+		}
+		o := new(ast.FieldList)
+		*o = *v
+		o.List = nil
+		for _, x := range v.List {
+			o.List = append(o.List, clone(x).(*ast.Field))
+		}
+		return o
+	case *ast.Field:
+		o := &ast.Field{
+			Doc:     v.Doc, // shallow
+			Type:    cloneExpr(v.Type),
+			Tag:     clone(v.Tag).(*ast.BasicLit),
+			Comment: v.Comment, // shallow
+		}
+		for _, x := range v.Names {
+			o.Names = append(o.Names, clone(x).(*ast.Ident))
+		}
+		return o
+	case *ast.FuncType:
+		if v == nil {
+			return v
+		}
+		return &ast.FuncType{
+			Func:    v.Func,
+			Params:  clone(v.Params).(*ast.FieldList),
+			Results: clone(v.Results).(*ast.FieldList),
+		}
+	case *ast.FuncDecl:
+		if v == nil {
+			return v
+		}
+		return &ast.FuncDecl{
+			Recv: clone(v.Recv).(*ast.FieldList),
+			Name: v.Name,
+			Type: clone(v.Type).(*ast.FuncType),
+			Body: v.Body, // shallow
+		}
+	case *ast.ValueSpec:
+		if v == nil {
+			return v
+		}
+		o := &ast.ValueSpec{
+			Type: cloneExpr(v.Type),
+		}
+		for _, x := range v.Names {
+			o.Names = append(o.Names, x)
+		}
+		for _, x := range v.Values {
+			o.Values = append(o.Values, cloneExpr(x))
+		}
+		return o
+	case *ast.CallExpr:
+		if v == nil {
+			return v
+		}
+		o := &ast.CallExpr{}
+		*o = *v
+		o.Args = cloneExprs(v.Args)
+		o.Fun = cloneExpr(v.Fun)
+		return o
+	case *ast.SelectorExpr:
+		if v == nil {
+			return nil
+		}
+		return &ast.SelectorExpr{
+			X:   cloneExpr(v.X),
+			Sel: v.Sel,
+		}
+	case *ast.ArrayType:
+		return &ast.ArrayType{
+			Lbrack: v.Lbrack,
+			Len:    cloneExpr(v.Len),
+			Elt:    cloneExpr(v.Elt),
+		}
+	case *ast.StructType:
+		return &ast.StructType{
+			Struct:     v.Struct,
+			Fields:     clone(v.Fields).(*ast.FieldList),
+			Incomplete: v.Incomplete,
+		}
+	case *ast.StarExpr:
+		return &ast.StarExpr{
+			Star: v.Star,
+			X:    cloneExpr(v.X),
+		}
+	case *ast.CompositeLit:
+		return &ast.CompositeLit{
+			Type:   cloneExpr(v.Type),
+			Lbrace: v.Lbrace,
+			Elts:   cloneExprs(v.Elts),
+			Rbrace: v.Rbrace,
+		}
+	case *ast.UnaryExpr:
+		return &ast.UnaryExpr{
+			OpPos: v.OpPos,
+			Op:    v.Op,
+			X:     cloneExpr(v.X),
+		}
+	case *ast.BinaryExpr:
+		return &ast.BinaryExpr{
+			OpPos: v.OpPos,
+			Op:    v.Op,
+			X:     cloneExpr(v.X),
+			Y:     cloneExpr(v.Y),
+		}
+	case *ast.Ellipsis:
+		return &ast.Ellipsis{
+			Ellipsis: v.Ellipsis,
+			Elt:      cloneExpr(v.Elt),
+		}
+	case *ast.KeyValueExpr:
+		return &ast.KeyValueExpr{
+			Key:   cloneExpr(v.Key),
+			Colon: v.Colon,
+			Value: cloneExpr(v.Value),
+		}
+	case *ast.FuncLit:
+		return &ast.FuncLit{
+			Type: clone(v.Type).(*ast.FuncType),
+			Body: v.Body, // shallow
+		}
+	case *ast.MapType:
+		return &ast.MapType{
+			Map:   v.Map,
+			Key:   cloneExpr(v.Key),
+			Value: cloneExpr(v.Value),
+		}
+	case *ast.ParenExpr:
+		return &ast.ParenExpr{
+			Lparen: v.Lparen,
+			X:      cloneExpr(v.X),
+			Rparen: v.Rparen,
+		}
+	case *ast.Ident, *ast.BasicLit:
+		return v
+	case *ast.ImportSpec:
+		return &ast.ImportSpec{
+			Doc:     v.Doc, // shallow
+			Name:    v.Name,
+			Path:    clone(v.Path).(*ast.BasicLit),
+			Comment: v.Comment, // shallow
+			EndPos:  v.EndPos,
+		}
+	case *ast.ChanType:
+		return &ast.ChanType{
+			Begin: v.Begin,
+			Arrow: v.Arrow,
+			Dir:   v.Dir,
+			Value: cloneExpr(v.Value),
+		}
+	case *ast.TypeAssertExpr:
+		return &ast.TypeAssertExpr{
+			X:    cloneExpr(v.X),
+			Type: cloneExpr(v.Type),
+		}
+	case *ast.IndexExpr:
+		return &ast.IndexExpr{
+			X:      cloneExpr(v.X),
+			Index:  cloneExpr(v.Index),
+			Lbrack: v.Lbrack,
+			Rbrack: v.Rbrack,
+		}
+	}
+	panic(fmt.Sprintf("Uncloneable type %T", i))
+}
+
+func cloneExpr(x ast.Expr) ast.Expr {
+	if x == nil {
+		return nil
+	}
+	return clone(x).(ast.Expr)
+}
+
+func cloneExprs(x []ast.Expr) []ast.Expr {
+	if x == nil {
+		return nil
+	}
+	o := make([]ast.Expr, len(x))
+	for i, x := range x {
+		o[i] = cloneExpr(x)
+	}
+	return o
+}
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index ad1c6bb..0d76b0c 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -22,12 +22,14 @@ import (
 	"go/parser"
 	"go/printer"
 	"go/token"
+	"io"
 	"io/ioutil"
 	"log"
 	"os"
 	"os/exec"
 	"path"
 	"path/filepath"
+	"regexp"
 	"runtime"
 	"sort"
 	"strconv"
@@ -38,11 +40,12 @@ import (
 var (
 	// TODO(bradfitz): once Go 1.1 comes out, allow the -c flag to take a comma-separated
 	// list of files, rather than just one.
-	checkFile = flag.String("c", "", "optional filename to check API against")
-	allowNew  = flag.Bool("allow_new", true, "allow API additions")
-	nextFile  = flag.String("next", "", "optional filename of tentative upcoming API features for the next release. This file can be lazily maintained. It only affects the delta warnings from the -c file printed on success.")
-	verbose   = flag.Bool("v", false, "verbose debugging")
-	forceCtx  = flag.String("contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.")
+	checkFile  = flag.String("c", "", "optional filename to check API against")
+	allowNew   = flag.Bool("allow_new", true, "allow API additions")
+	exceptFile = flag.String("except", "", "optional filename of packages that are allowed to change without triggering a failure in the tool")
+	nextFile   = flag.String("next", "", "optional filename of tentative upcoming API features for the next release. This file can be lazily maintained. It only affects the delta warnings from the -c file printed on success.")
+	verbose    = flag.Bool("v", false, "verbose debugging")
+	forceCtx   = flag.String("contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.")
 )
 
 // contexts are the default contexts which are scanned, unless
@@ -100,7 +103,7 @@ func setContexts() {
 func main() {
 	flag.Parse()
 
-	if !strings.Contains(runtime.Version(), "weekly") {
+	if !strings.Contains(runtime.Version(), "weekly") && !strings.Contains(runtime.Version(), "devel") {
 		if *nextFile != "" {
 			fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFile)
 			*nextFile = ""
@@ -166,7 +169,6 @@ func main() {
 			features = append(features, f2)
 		}
 	}
-	sort.Strings(features)
 
 	fail := false
 	defer func() {
@@ -179,24 +181,45 @@ func main() {
 	defer bw.Flush()
 
 	if *checkFile == "" {
+		sort.Strings(features)
 		for _, f := range features {
 			fmt.Fprintf(bw, "%s\n", f)
 		}
 		return
 	}
 
-	var required []string
-	for _, filename := range []string{*checkFile} {
-		required = append(required, fileFeatures(filename)...)
+	required := fileFeatures(*checkFile)
+	optional := fileFeatures(*nextFile)
+	exception := fileFeatures(*exceptFile)
+	fail = !compareAPI(bw, features, required, optional, exception)
+}
+
+func set(items []string) map[string]bool {
+	s := make(map[string]bool)
+	for _, v := range items {
+		s[v] = true
 	}
-	sort.Strings(required)
+	return s
+}
 
-	var optional = make(map[string]bool) // feature => true
-	if *nextFile != "" {
-		for _, feature := range fileFeatures(*nextFile) {
-			optional[feature] = true
-		}
+var spaceParensRx = regexp.MustCompile(` \(\S+?\)`)
+
+func featureWithoutContext(f string) string {
+	if !strings.Contains(f, "(") {
+		return f
 	}
+	return spaceParensRx.ReplaceAllString(f, "")
+}
+
+func compareAPI(w io.Writer, features, required, optional, exception []string) (ok bool) {
+	ok = true
+
+	optionalSet := set(optional)
+	exceptionSet := set(exception)
+	featureSet := set(features)
+
+	sort.Strings(features)
+	sort.Strings(required)
 
 	take := func(sl *[]string) string {
 		s := (*sl)[0]
@@ -206,20 +229,27 @@ func main() {
 
 	for len(required) > 0 || len(features) > 0 {
 		switch {
-		case len(features) == 0 || required[0] < features[0]:
-			fmt.Fprintf(bw, "-%s\n", take(&required))
-			fail = true // broke compatibility
-		case len(required) == 0 || required[0] > features[0]:
+		case len(features) == 0 || (len(required) > 0 && required[0] < features[0]):
+			feature := take(&required)
+			if exceptionSet[feature] {
+				fmt.Fprintf(w, "~%s\n", feature)
+			} else if featureSet[featureWithoutContext(feature)] {
+				// okay.
+			} else {
+				fmt.Fprintf(w, "-%s\n", feature)
+				ok = false // broke compatibility
+			}
+		case len(required) == 0 || (len(features) > 0 && required[0] > features[0]):
 			newFeature := take(&features)
-			if optional[newFeature] {
+			if optionalSet[newFeature] {
 				// Known added feature to the upcoming release.
 				// Delete it from the map so we can detect any upcoming features
 				// which were never seen.  (so we can clean up the nextFile)
-				delete(optional, newFeature)
+				delete(optionalSet, newFeature)
 			} else {
-				fmt.Fprintf(bw, "+%s\n", newFeature)
+				fmt.Fprintf(w, "+%s\n", newFeature)
 				if !*allowNew {
-					fail = true // we're in lock-down mode for next release
+					ok = false // we're in lock-down mode for next release
 				}
 			}
 		default:
@@ -228,17 +258,22 @@ func main() {
 		}
 	}
 
+	// In next file, but not in API.
 	var missing []string
-	for feature := range optional {
+	for feature := range optionalSet {
 		missing = append(missing, feature)
 	}
 	sort.Strings(missing)
 	for _, feature := range missing {
-		fmt.Fprintf(bw, "(in next file, but not in API) -%s\n", feature)
+		fmt.Fprintf(w, "±%s\n", feature)
 	}
+	return
 }
 
 func fileFeatures(filename string) []string {
+	if filename == "" {
+		return nil
+	}
 	bs, err := ioutil.ReadFile(filename)
 	if err != nil {
 		log.Fatalf("Error reading file %s: %v", filename, err)
@@ -256,10 +291,11 @@ type pkgSymbol struct {
 	symbol string // "RoundTripper"
 }
 
+var fset = token.NewFileSet()
+
 type Walker struct {
 	context         *build.Context
 	root            string
-	fset            *token.FileSet
 	scope           []string
 	features        map[string]bool // set
 	lastConstType   string
@@ -276,7 +312,6 @@ type Walker struct {
 
 func NewWalker() *Walker {
 	return &Walker{
-		fset:            token.NewFileSet(),
 		features:        make(map[string]bool),
 		packageState:    make(map[string]loadState),
 		interfaces:      make(map[pkgSymbol]*ast.InterfaceType),
@@ -297,20 +332,6 @@ const (
 	loaded
 )
 
-// hardCodedConstantType is a hack until the type checker is sufficient for our needs.
-// Rather than litter the code with unnecessary type annotations, we'll hard-code
-// the cases we can't handle yet.
-func (w *Walker) hardCodedConstantType(name string) (typ string, ok bool) {
-	switch w.scope[0] {
-	case "pkg syscall":
-		switch name {
-		case "darwinAMD64":
-			return "bool", true
-		}
-	}
-	return "", false
-}
-
 func (w *Walker) Features() (fs []string) {
 	for f := range w.features {
 		fs = append(fs, f)
@@ -333,6 +354,21 @@ func fileDeps(f *ast.File) (pkgs []string) {
 	return
 }
 
+var parsedFileCache = make(map[string]*ast.File)
+
+func parseFile(filename string) (*ast.File, error) {
+	f, ok := parsedFileCache[filename]
+	if !ok {
+		var err error
+		f, err = parser.ParseFile(fset, filename, nil, 0)
+		if err != nil {
+			return nil, err
+		}
+		parsedFileCache[filename] = f
+	}
+	return clone(f).(*ast.File), nil
+}
+
 // WalkPackage walks all files in package `name'.
 // WalkPackage does nothing if the package has already been loaded.
 func (w *Walker) WalkPackage(name string) {
@@ -366,7 +402,7 @@ func (w *Walker) WalkPackage(name string) {
 
 	files := append(append([]string{}, info.GoFiles...), info.CgoFiles...)
 	for _, file := range files {
-		f, err := parser.ParseFile(w.fset, filepath.Join(dir, file), nil, 0)
+		f, err := parseFile(filepath.Join(dir, file))
 		if err != nil {
 			log.Fatalf("error parsing package %s, file %s: %v", name, file, err)
 		}
@@ -501,7 +537,7 @@ func (w *Walker) walkFile(file *ast.File) {
 			// Ignore. Handled in subsequent pass, by go/doc.
 		default:
 			log.Printf("unhandled %T, %#v\n", di, di)
-			printer.Fprint(os.Stderr, w.fset, di)
+			printer.Fprint(os.Stderr, fset, di)
 			os.Stderr.Write([]byte("\n"))
 		}
 	}
@@ -562,6 +598,10 @@ func (w *Walker) constValueType(vi interface{}) (string, error) {
 		}
 		return constDepPrefix + v.Name, nil
 	case *ast.BinaryExpr:
+		switch v.Op {
+		case token.EQL, token.LSS, token.GTR, token.NOT, token.NEQ, token.LEQ, token.GEQ:
+			return "bool", nil
+		}
 		left, err := w.constValueType(v.X)
 		if err != nil {
 			return "", err
@@ -734,17 +774,11 @@ func (w *Walker) walkConst(vs *ast.ValueSpec) {
 				var err error
 				litType, err = w.constValueType(vs.Values[0])
 				if err != nil {
-					if t, ok := w.hardCodedConstantType(ident.Name); ok {
-						litType = t
-						err = nil
-					} else {
-						log.Fatalf("unknown kind in const %q (%T): %v", ident.Name, vs.Values[0], err)
-					}
+					log.Fatalf("unknown kind in const %q (%T): %v", ident.Name, vs.Values[0], err)
 				}
 			}
 		}
-		if strings.HasPrefix(litType, constDepPrefix) {
-			dep := litType[len(constDepPrefix):]
+		if dep := strings.TrimPrefix(litType, constDepPrefix); dep != litType {
 			w.constDep[ident.Name] = dep
 			continue
 		}
@@ -816,7 +850,7 @@ func (w *Walker) nodeString(node interface{}) string {
 		return ""
 	}
 	var b bytes.Buffer
-	printer.Fprint(&b, w.fset, node)
+	printer.Fprint(&b, fset, node)
 	return b.String()
 }
 
@@ -825,7 +859,7 @@ func (w *Walker) nodeDebug(node interface{}) string {
 		return ""
 	}
 	var b bytes.Buffer
-	ast.Fprint(&b, w.fset, node, nil)
+	ast.Fprint(&b, fset, node, nil)
 	return b.String()
 }
 
@@ -844,7 +878,7 @@ func (w *Walker) walkTypeSpec(ts *ast.TypeSpec) {
 	case *ast.InterfaceType:
 		w.walkInterfaceType(name, t)
 	default:
-		w.emitFeature(fmt.Sprintf("type %s %s", name, w.nodeString(ts.Type)))
+		w.emitFeature(fmt.Sprintf("type %s %s", name, w.nodeString(w.namelessType(ts.Type))))
 	}
 }
 
@@ -892,15 +926,18 @@ type method struct {
 	sig  string // "([]byte) (int, error)", from funcSigString
 }
 
-// interfaceMethods returns the expanded list of methods for an interface.
+// interfaceMethods returns the expanded list of exported methods for an interface.
+// The boolean complete reports whether the list contains all methods (that is, the
+// interface has no unexported methods).
 // pkg is the complete package name ("net/http")
 // iname is the interface name.
-func (w *Walker) interfaceMethods(pkg, iname string) (methods []method) {
+func (w *Walker) interfaceMethods(pkg, iname string) (methods []method, complete bool) {
 	t, ok := w.interfaces[pkgSymbol{pkg, iname}]
 	if !ok {
 		log.Fatalf("failed to find interface %s.%s", pkg, iname)
 	}
 
+	complete = true
 	for _, f := range t.Methods.List {
 		typ := f.Type
 		switch tv := typ.(type) {
@@ -912,6 +949,8 @@ func (w *Walker) interfaceMethods(pkg, iname string) (methods []method) {
 						name: mname.Name,
 						sig:  w.funcSigString(ft),
 					})
+				} else {
+					complete = false
 				}
 			}
 		case *ast.Ident:
@@ -927,7 +966,9 @@ func (w *Walker) interfaceMethods(pkg, iname string) (methods []method) {
 				log.Fatalf("unexported embedded interface %q in exported interface %s.%s; confused",
 					embedded, pkg, iname)
 			}
-			methods = append(methods, w.interfaceMethods(pkg, embedded)...)
+			m, c := w.interfaceMethods(pkg, embedded)
+			methods = append(methods, m...)
+			complete = complete && c
 		case *ast.SelectorExpr:
 			lhs := w.nodeString(tv.X)
 			rhs := w.nodeString(tv.Sel)
@@ -935,7 +976,9 @@ func (w *Walker) interfaceMethods(pkg, iname string) (methods []method) {
 			if !ok {
 				log.Fatalf("can't resolve selector %q in interface %s.%s", lhs, pkg, iname)
 			}
-			methods = append(methods, w.interfaceMethods(fpkg, rhs)...)
+			m, c := w.interfaceMethods(fpkg, rhs)
+			methods = append(methods, m...)
+			complete = complete && c
 		default:
 			log.Fatalf("unknown type %T in interface field", typ)
 		}
@@ -945,14 +988,28 @@ func (w *Walker) interfaceMethods(pkg, iname string) (methods []method) {
 
 func (w *Walker) walkInterfaceType(name string, t *ast.InterfaceType) {
 	methNames := []string{}
-
 	pop := w.pushScope("type " + name + " interface")
-	for _, m := range w.interfaceMethods(w.curPackageName, name) {
+	methods, complete := w.interfaceMethods(w.curPackageName, name)
+	for _, m := range methods {
 		methNames = append(methNames, m.name)
 		w.emitFeature(fmt.Sprintf("%s%s", m.name, m.sig))
 	}
+	if !complete {
+		// The method set has unexported methods, so all the
+		// implementations are provided by the same package,
+		// so the method set can be extended. Instead of recording
+		// the full set of names (below), record only that there were
+		// unexported methods. (If the interface shrinks, we will notice
+		// because a method signature emitted during the last loop,
+		// will disappear.)
+		w.emitFeature("unexported methods")
+	}
 	pop()
 
+	if !complete {
+		return
+	}
+
 	sort.Strings(methNames)
 	if len(methNames) == 0 {
 		w.emitFeature(fmt.Sprintf("type %s interface {}", name))
@@ -994,18 +1051,38 @@ func (w *Walker) walkFuncDecl(f *ast.FuncDecl) {
 
 func (w *Walker) funcSigString(ft *ast.FuncType) string {
 	var b bytes.Buffer
+	writeField := func(b *bytes.Buffer, f *ast.Field) {
+		if n := len(f.Names); n > 1 {
+			for i := 0; i < n; i++ {
+				if i > 0 {
+					b.WriteString(", ")
+				}
+				b.WriteString(w.nodeString(w.namelessType(f.Type)))
+			}
+		} else {
+			b.WriteString(w.nodeString(w.namelessType(f.Type)))
+		}
+	}
 	b.WriteByte('(')
 	if ft.Params != nil {
 		for i, f := range ft.Params.List {
 			if i > 0 {
 				b.WriteString(", ")
 			}
-			b.WriteString(w.nodeString(w.namelessType(f.Type)))
+			writeField(&b, f)
 		}
 	}
 	b.WriteByte(')')
 	if ft.Results != nil {
-		if nr := len(ft.Results.List); nr > 0 {
+		nr := 0
+		for _, f := range ft.Results.List {
+			if n := len(f.Names); n > 1 {
+				nr += n
+			} else {
+				nr++
+			}
+		}
+		if nr > 0 {
 			b.WriteByte(' ')
 			if nr > 1 {
 				b.WriteByte('(')
@@ -1014,7 +1091,7 @@ func (w *Walker) funcSigString(ft *ast.FuncType) string {
 				if i > 0 {
 					b.WriteString(", ")
 				}
-				b.WriteString(w.nodeString(w.namelessType(f.Type)))
+				writeField(&b, f)
 			}
 			if nr > 1 {
 				b.WriteByte(')')
@@ -1042,7 +1119,13 @@ func (w *Walker) namelessFieldList(fl *ast.FieldList) *ast.FieldList {
 	fl2 := &ast.FieldList{}
 	if fl != nil {
 		for _, f := range fl.List {
-			fl2.List = append(fl2.List, w.namelessField(f))
+			repeats := 1
+			if len(f.Names) > 1 {
+				repeats = len(f.Names)
+			}
+			for i := 0; i < repeats; i++ {
+				fl2.List = append(fl2.List, w.namelessField(f))
+			}
 		}
 	}
 	return fl2
@@ -1056,10 +1139,21 @@ func (w *Walker) namelessField(f *ast.Field) *ast.Field {
 	}
 }
 
+var (
+	byteRx = regexp.MustCompile(`\bbyte\b`)
+	runeRx = regexp.MustCompile(`\brune\b`)
+)
+
 func (w *Walker) emitFeature(feature string) {
 	if !w.wantedPkg[w.curPackageName] {
 		return
 	}
+	if strings.Contains(feature, "byte") {
+		feature = byteRx.ReplaceAllString(feature, "uint8")
+	}
+	if strings.Contains(feature, "rune") {
+		feature = runeRx.ReplaceAllString(feature, "int32")
+	}
 	f := strings.Join(w.scope, ", ") + ", " + feature
 	if _, dup := w.features[f]; dup {
 		panic("duplicate feature inserted: " + f)
@@ -1075,6 +1169,7 @@ func (w *Walker) emitFeature(feature string) {
 		}
 		panic("feature contains newlines: " + f)
 	}
+
 	w.features[f] = true
 	if *verbose {
 		log.Printf("feature: %s", f)
diff --git a/src/cmd/api/goapi_test.go b/src/cmd/api/goapi_test.go
index c7cc601..1a86c0e 100644
--- a/src/cmd/api/goapi_test.go
+++ b/src/cmd/api/goapi_test.go
@@ -5,6 +5,7 @@
 package main
 
 import (
+	"bytes"
 	"flag"
 	"fmt"
 	"io/ioutil"
@@ -73,3 +74,68 @@ func TestGolden(t *testing.T) {
 		}
 	}
 }
+
+func TestCompareAPI(t *testing.T) {
+	tests := []struct {
+		name                                    string
+		features, required, optional, exception []string
+		ok                                      bool   // want
+		out                                     string // want
+	}{
+		{
+			name:     "feature added",
+			features: []string{"A", "B", "C", "D", "E", "F"},
+			required: []string{"B", "D"},
+			ok:       true,
+			out:      "+A\n+C\n+E\n+F\n",
+		},
+		{
+			name:     "feature removed",
+			features: []string{"C", "A"},
+			required: []string{"A", "B", "C"},
+			ok:       false,
+			out:      "-B\n",
+		},
+		{
+			name:     "feature added then removed",
+			features: []string{"A", "C"},
+			optional: []string{"B"},
+			required: []string{"A", "C"},
+			ok:       true,
+			out:      "±B\n",
+		},
+		{
+			name:      "exception removal",
+			required:  []string{"A", "B", "C"},
+			features:  []string{"A", "C"},
+			exception: []string{"B"},
+			ok:        true,
+			out:       "~B\n",
+		},
+		{
+			// http://golang.org/issue/4303
+			name: "contexts reconverging",
+			required: []string{
+				"A",
+				"pkg syscall (darwin-386), type RawSockaddrInet6 struct",
+				"pkg syscall (darwin-amd64), type RawSockaddrInet6 struct",
+			},
+			features: []string{
+				"A",
+				"pkg syscall, type RawSockaddrInet6 struct",
+			},
+			ok:  true,
+			out: "+pkg syscall, type RawSockaddrInet6 struct\n",
+		},
+	}
+	for _, tt := range tests {
+		buf := new(bytes.Buffer)
+		gotok := compareAPI(buf, tt.features, tt.required, tt.optional, tt.exception)
+		if gotok != tt.ok {
+			t.Errorf("%s: ok = %v; want %v", tt.name, gotok, tt.ok)
+		}
+		if got := buf.String(); got != tt.out {
+			t.Errorf("%s: output differs\nGOT:\n%s\nWANT:\n%s", tt.name, got, tt.out)
+		}
+	}
+}
diff --git a/src/cmd/api/testdata/src/pkg/p1/golden.txt b/src/cmd/api/testdata/src/pkg/p1/golden.txt
index e334e57..abcc0ce 100644
--- a/src/cmd/api/testdata/src/pkg/p1/golden.txt
+++ b/src/cmd/api/testdata/src/pkg/p1/golden.txt
@@ -10,6 +10,7 @@ pkg p1, func Bar(int8, int16, int64)
 pkg p1, func Bar1(int8, int16, int64) uint64
 pkg p1, func Bar2(int8, int16, int64) (uint8, uint64)
 pkg p1, func BarE() Error
+pkg p1, func PlainFunc(int, int, string) (*B, error)
 pkg p1, func TakesFunc(func(int) int)
 pkg p1, method (*B) JustOnB()
 pkg p1, method (*B) OnBothTandBPtr()
@@ -27,6 +28,9 @@ pkg p1, method (TPtrExported) OnEmbedded()
 pkg p1, method (TPtrUnexported) OnBothTandBPtr()
 pkg p1, method (TPtrUnexported) OnBothTandBVal()
 pkg p1, type B struct
+pkg p1, type ByteStruct struct
+pkg p1, type ByteStruct struct, B uint8
+pkg p1, type ByteStruct struct, R int32
 pkg p1, type Codec struct
 pkg p1, type Codec struct, Func func(int, int) int
 pkg p1, type EmbedSelector struct
@@ -37,15 +41,21 @@ pkg p1, type Embedded struct
 pkg p1, type Error interface { Error, Temporary }
 pkg p1, type Error interface, Error() string
 pkg p1, type Error interface, Temporary() bool
-pkg p1, type I interface { Get, GetNamed, Name, PackageTwoMeth, Set }
+pkg p1, type FuncType func(int, int, string) (*B, error)
 pkg p1, type I interface, Get(string) int64
 pkg p1, type I interface, GetNamed(string) int64
 pkg p1, type I interface, Name() string
 pkg p1, type I interface, PackageTwoMeth()
 pkg p1, type I interface, Set(string, int64)
+pkg p1, type I interface, unexported methods
 pkg p1, type MyInt int
 pkg p1, type Namer interface { Name }
 pkg p1, type Namer interface, Name() string
+pkg p1, type Private interface, X()
+pkg p1, type Private interface, unexported methods
+pkg p1, type Public interface { X, Y }
+pkg p1, type Public interface, X()
+pkg p1, type Public interface, Y()
 pkg p1, type S struct
 pkg p1, type S struct, Public *int
 pkg p1, type S struct, PublicTime time.Time
@@ -58,7 +68,9 @@ pkg p1, type T struct
 pkg p1, type TPtrExported struct
 pkg p1, type TPtrExported struct, embedded *Embedded
 pkg p1, type TPtrUnexported struct
-pkg p1, var ByteConv []byte
+pkg p1, var Byte uint8
+pkg p1, var ByteConv []uint8
+pkg p1, var ByteFunc func(uint8) int32
 pkg p1, var ChecksumError error
 pkg p1, var SIPtr *SI
 pkg p1, var SIPtr2 *SI
diff --git a/src/cmd/api/testdata/src/pkg/p1/p1.go b/src/cmd/api/testdata/src/pkg/p1/p1.go
index d965bb7..f94c9ce 100644
--- a/src/cmd/api/testdata/src/pkg/p1/p1.go
+++ b/src/cmd/api/testdata/src/pkg/p1/p1.go
@@ -78,6 +78,16 @@ type I interface {
 	private()
 }
 
+type Public interface {
+	X()
+	Y()
+}
+
+type Private interface {
+	X()
+	y()
+}
+
 type Error interface {
 	error
 	Temporary() bool
@@ -139,8 +149,12 @@ type TPtrExported struct {
 	*Embedded
 }
 
+type FuncType func(x, y int, s string) (b *B, err error)
+
 type Embedded struct{}
 
+func PlainFunc(x, y int, s string) (b *B, err error)
+
 func (*Embedded) OnEmbedded() {}
 
 func (*T) JustOnT()             {}
@@ -151,3 +165,39 @@ func (common) OnBothTandBVal()  {}
 type EmbedSelector struct {
 	time.Time
 }
+
+const (
+	foo          = "foo"
+	foo2  string = "foo2"
+	truth        = foo == "foo" || foo2 == "foo2"
+)
+
+func ellipsis(...string) {}
+
+var x = &S{
+	Public:     nil,
+	private:    nil,
+	publicTime: time.Now(),
+}
+
+var parenExpr = (1 + 5)
+
+var funcLit = func() {}
+
+var m map[string]int
+
+var chanVar chan int
+
+var ifaceVar interface{} = 5
+
+var assertVar = ifaceVar.(int)
+
+var indexVar = m["foo"]
+
+var Byte byte
+var ByteFunc func(byte) rune
+
+type ByteStruct struct {
+	B byte
+	R rune
+}
diff --git a/src/cmd/api/testdata/src/pkg/p3/golden.txt b/src/cmd/api/testdata/src/pkg/p3/golden.txt
new file mode 100644
index 0000000..a7dcccd
--- /dev/null
+++ b/src/cmd/api/testdata/src/pkg/p3/golden.txt
@@ -0,0 +1,3 @@
+pkg p3, func BadHop(int, int, int) (bool, bool, *ThirdBase, *ThirdBase, error)
+pkg p3, method (*ThirdBase) GoodPlayer() (int, int, int)
+pkg p3, type ThirdBase struct
diff --git a/src/cmd/api/testdata/src/pkg/p3/p3.go b/src/cmd/api/testdata/src/pkg/p3/p3.go
new file mode 100644
index 0000000..1b2b1a4
--- /dev/null
+++ b/src/cmd/api/testdata/src/pkg/p3/p3.go
@@ -0,0 +1,6 @@
+package p3
+
+type ThirdBase struct{}
+
+func (tb *ThirdBase) GoodPlayer() (i, j, k int)
+func BadHop(i, j, k int) (l, m bool, n, o *ThirdBase, err error)
diff --git a/src/cmd/cc/Makefile b/src/cmd/cc/Makefile
index 1095782..34df31d 100644
--- a/src/cmd/cc/Makefile
+++ b/src/cmd/cc/Makefile
@@ -7,4 +7,4 @@ include ../../Make.dist
 install: y.tab.h
 
 y.tab.h: cc.y
-	LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y
+	LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y cc.y
diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h
index 4c527a2..866aeb0 100644
--- a/src/cmd/cc/cc.h
+++ b/src/cmd/cc/cc.h
@@ -300,6 +300,7 @@ enum
 	OPOSTINC,
 	OPREDEC,
 	OPREINC,
+	OPREFETCH,
 	OPROTO,
 	OREGISTER,
 	ORETURN,
@@ -324,6 +325,7 @@ enum
 	OINDEX,
 	OFAS,
 	OREGPAIR,
+	OROTL,
 
 	OEND
 };
@@ -442,25 +444,6 @@ struct	Funct
 	Sym*	castfr[NTYPE];
 };
 
-struct	Dynimp
-{
-	char*	local;
-	char*	remote;
-	char*	path;
-};
-
-EXTERN	Dynimp	*dynimp;
-EXTERN	int	ndynimp;
-
-struct	Dynexp
-{
-	char*	local;
-	char*	remote;
-};
-
-EXTERN	Dynexp	*dynexp;
-EXTERN	int	ndynexp;
-
 EXTERN struct
 {
 	Type*	tenum;		/* type of entire enum */
@@ -473,7 +456,7 @@ EXTERN	int	autobn;
 EXTERN	int32	autoffset;
 EXTERN	int	blockno;
 EXTERN	Decl*	dclstack;
-EXTERN	char	debug[256];
+EXTERN	int	debug[256];
 EXTERN	Hist*	ehist;
 EXTERN	int32	firstbit;
 EXTERN	Sym*	firstarg;
@@ -526,10 +509,12 @@ EXTERN	int	packflg;
 EXTERN	int	fproundflg;
 EXTERN	int	textflag;
 EXTERN	int	dataflag;
+EXTERN	int	flag_largemodel;
 EXTERN	int	ncontin;
 EXTERN	int	canreach;
 EXTERN	int	warnreach;
 EXTERN	Bits	zbits;
+EXTERN	Fmt	pragcgobuf;
 
 extern	char	*onames[], *tnames[], *gnames[];
 extern	char	*cnames[], *qnames[], *bnames[];
@@ -771,8 +756,7 @@ void	pragfpround(void);
 void	pragdataflag(void);
 void	pragtextflag(void);
 void	pragincomplete(void);
-void	pragdynimport(void);
-void	pragdynexport(void);
+void	pragcgo(char*);
 
 /*
  * calls to machine depend part
diff --git a/src/cmd/cc/cc.y b/src/cmd/cc/cc.y
index 515a803..830dd21 100644
--- a/src/cmd/cc/cc.y
+++ b/src/cmd/cc/cc.y
@@ -93,7 +93,7 @@
 %token	<sval>	LSTRING LLSTRING
 %token		LAUTO LBREAK LCASE LCHAR LCONTINUE LDEFAULT LDO
 %token		LDOUBLE LELSE LEXTERN LFLOAT LFOR LGOTO
-%token	LIF LINT LLONG LREGISTER LRETURN LSHORT LSIZEOF LUSED
+%token	LIF LINT LLONG LPREFETCH LREGISTER LRETURN LSHORT LSIZEOF LUSED
 %token	LSTATIC LSTRUCT LSWITCH LTYPEDEF LTYPESTR LUNION LUNSIGNED
 %token	LWHILE LVOID LENUM LSIGNED LCONSTNT LVOLATILE LSET LSIGNOF
 %token	LRESTRICT LINLINE
@@ -535,6 +535,10 @@ ulstmnt:
 	{
 		$$ = new(OUSED, $3, Z);
 	}
+|	LPREFETCH '(' zelist ')' ';'
+	{
+		$$ = new(OPREFETCH, $3, Z);
+	}
 |	LSET '(' zelist ')' ';'
 	{
 		$$ = new(OSET, $3, Z);
diff --git a/src/cmd/cc/dcl.c b/src/cmd/cc/dcl.c
index a3ed977..edfc7e7 100644
--- a/src/cmd/cc/dcl.c
+++ b/src/cmd/cc/dcl.c
@@ -1058,6 +1058,10 @@ sigind(Type *t, Typetab *tt)
 			return p-a;
 	if((n&15) == 0){
 		na = malloc((n+16)*sizeof(Type*));
+		if(na == nil) {
+			print("%s: out of memory", argv0);
+			errorexit();
+		}
 		memmove(na, a, n*sizeof(Type*));
 		free(a);
 		a = tt->a = na;
diff --git a/src/cmd/cc/doc.go b/src/cmd/cc/doc.go
index 51aa8b1..10901b4 100644
--- a/src/cmd/cc/doc.go
+++ b/src/cmd/cc/doc.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.
 
+// +build ignore
+
 /*
 
 This directory contains the portable section of the Plan 9 C compilers.
 See ../6c, ../8c, and ../5c for more information.
 
 */
-package documentation
+package main
diff --git a/src/cmd/cc/dpchk.c b/src/cmd/cc/dpchk.c
index c579e20..2f038f5 100644
--- a/src/cmd/cc/dpchk.c
+++ b/src/cmd/cc/dpchk.c
@@ -662,65 +662,93 @@ getimpsym(void)
 	return lookup();
 }
 
-void
-pragdynimport(void)
+static int
+more(void)
 {
-	Sym *local, *remote;
-	char *path;
-	Dynimp *f;
-
-	local = getimpsym();
-	if(local == nil)
-		goto err;
-
-	remote = getimpsym();
-	if(remote == nil)
-		goto err;
-
-	path = getquoted();
-	if(path == nil)
-		goto err;
-
-	if(ndynimp%32 == 0)
-		dynimp = realloc(dynimp, (ndynimp+32)*sizeof dynimp[0]);
-	f = &dynimp[ndynimp++];
-	f->local = local->name;
-	f->remote = remote->name;
-	f->path = path;
-	goto out;
-
-err:
-	yyerror("usage: #pragma dynimport local remote \"path\"");
-
-out:
-	while(getnsc() != '\n')
-		;
+	int c;
+	
+	do
+		c = getnsc();
+	while(c == ' ' || c == '\t');
+	unget(c);
+	return c != '\n';
 }
 
 void
-pragdynexport(void)
+pragcgo(char *verb)
 {
 	Sym *local, *remote;
-	Dynexp *f;
-
-	local = getsym();
-	if(local == nil)
-		goto err;
-
-	remote = getsym();
-	if(remote == nil)
-		goto err;
+	char *p;
 
-	if(ndynexp%32 == 0)
-		dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
-	f = &dynexp[ndynexp++];
-	f->local = local->name;
-	f->remote = remote->name;
-	goto out;
-
-err:
-	yyerror("usage: #pragma dynexport local remote");
+	if(strcmp(verb, "cgo_dynamic_linker") == 0 || strcmp(verb, "dynlinker") == 0) {
+		p = getquoted();
+		if(p == nil)
+			goto err1;
+		fmtprint(&pragcgobuf, "cgo_dynamic_linker %q\n", p);
+		goto out;
+	
+	err1:
+		yyerror("usage: #pragma cgo_dynamic_linker \"path\"");
+		goto out;
+	}	
+	
+	if(strcmp(verb, "cgo_export") == 0 || strcmp(verb, "dynexport") == 0) {
+		local = getimpsym();
+		if(local == nil)
+			goto err2;
+		if(!more()) {
+			fmtprint(&pragcgobuf, "cgo_export %q\n", local->name);
+			goto out;
+		}
+		remote = getimpsym();
+		if(remote == nil)
+			goto err2;
+		fmtprint(&pragcgobuf, "cgo_export %q %q\n", local->name, remote->name);
+		goto out;
+	
+	err2:
+		yyerror("usage: #pragma cgo_export local [remote]");
+		goto out;
+	}
+	
+	if(strcmp(verb, "cgo_import_dynamic") == 0 || strcmp(verb, "dynimport") == 0) {
+		local = getimpsym();
+		if(local == nil)
+			goto err3;
+		if(!more()) {
+			fmtprint(&pragcgobuf, "cgo_import_dynamic %q\n", local->name);
+			goto out;
+		}
+		remote = getimpsym();
+		if(remote == nil)
+			goto err3;
+		if(!more()) {
+			fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q\n", local->name, remote->name);
+			goto out;
+		}
+		p = getquoted();
+		if(p == nil)	
+			goto err3;
+		fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q %q\n", local->name, remote->name, p);
+		goto out;
+	
+	err3:
+		yyerror("usage: #pragma cgo_import_dynamic local [remote [\"library\"]]");
+		goto out;
+	}
+	
+	if(strcmp(verb, "cgo_import_static") == 0) {
+		local = getimpsym();
+		if(local == nil)
+			goto err4;
+		fmtprint(&pragcgobuf, "cgo_import_static %q\n", local->name);
+		goto out;
 
+	err4:
+		yyerror("usage: #pragma cgo_import_static local [remote]");
+		goto out;
+	}
+	
 out:
 	while(getnsc() != '\n')
 		;
diff --git a/src/cmd/cc/godefs.c b/src/cmd/cc/godefs.c
index 4274c56..7457bd0 100644
--- a/src/cmd/cc/godefs.c
+++ b/src/cmd/cc/godefs.c
@@ -188,10 +188,10 @@ printtypename(Type *t)
 
 	switch(t->etype) {
 	case TINT:
-		Bprint(&outbuf, "int");
+		Bprint(&outbuf, "int32");
 		break;
 	case TUINT:
-		Bprint(&outbuf, "uint");
+		Bprint(&outbuf, "uint32");
 		break;
 	case TCHAR:
 		Bprint(&outbuf, "int8");
diff --git a/src/cmd/cc/lex.c b/src/cmd/cc/lex.c
index 8aeb1a3..4fb0be9 100644
--- a/src/cmd/cc/lex.c
+++ b/src/cmd/cc/lex.c
@@ -86,10 +86,37 @@ pathchar(void)
  */
 
 void
+usage(void)
+{
+	print("usage: %cc [options] file.c...\n", thechar);
+	flagprint(1);
+	errorexit();
+}
+
+void
+dospim(void)
+{
+	thechar = '0';
+	thestring = "spim";
+}
+
+char **defs;
+int ndef;
+
+void
+dodef(char *p)
+{
+	if(ndef%8 == 0)
+		defs = allocn(defs, ndef*sizeof(char *),
+			8*sizeof(char *));
+	defs[ndef++] = p;
+	dodefine(p);
+}
+
+void
 main(int argc, char *argv[])
 {
-	char **defs, *p;
-	int c, ndef;
+	int c;
 
 	ensuresymb(NSYMB);
 	memset(debug, 0, sizeof(debug));
@@ -97,52 +124,67 @@ main(int argc, char *argv[])
 	cinit();
 	ginit();
 	arginit();
+	
+	fmtstrinit(&pragcgobuf);
+	quotefmtinstall();
 
 	tufield = simplet((1L<<tfield->etype) | BUNSIGNED);
 	ndef = 0;
 	defs = nil;
 	outfile = 0;
 	setinclude(".");
-	ARGBEGIN {
-	default:
-		c = ARGC();
-		if(c >= 0 && c < sizeof(debug))
-			debug[c]++;
-		break;
-
-	case 'l':			/* for little-endian mips */
-		if(thechar != 'v'){
-			print("can only use -l with vc\n");
-			errorexit();
-		}
-		thechar = '0';
-		thestring = "spim";
-		break;
-
-	case 'o':
-		outfile = ARGF();
-		break;
 
-	case 'D':
-		p = ARGF();
-		if(p) {
-			if(ndef%8 == 0)
-				defs = allocn(defs, ndef*sizeof(char *),
-					8*sizeof(char *));
-			defs[ndef++] = p;
-			dodefine(p);
-		}
-		break;
+	flagcount("+", "pass -+ to preprocessor", &debug['+']);	
+	flagcount(".", "pass -. to preprocessor", &debug['.']);	
+	flagcount("<", "debug shift", &debug['<']);
+	flagcount("A", "debug alignment", &debug['A']);
+	flagcount("B", "allow pre-ANSI code", &debug['B']);
+	if(thechar == '5')
+		flagcount("C", "debug constant propagation", &debug['C']);
+	flagfn1("D", "name[=value]: add #define", dodef);
+	flagcount("F", "enable print format checks", &debug['F']);
+	if(thechar == '5')
+		flagcount("H", "debug shift propagation", &debug['H']);
+	flagfn1("I", "dir: add dir to include path", setinclude);
+	flagcount("L", "debug lexer", &debug['L']);
+	flagcount("M", "debug move generation", &debug['M']);
+	flagcount("N", "disable optimizations", &debug['N']);
+	flagcount("P", "debug peephole optimizer", &debug['P']);
+	flagcount("Q", "print exported Go definitions", &debug['Q']);
+	flagcount("R", "debug register optimizer", &debug['R']);
+	flagcount("S", "print assembly", &debug['S']);
+	flagcount("T", "enable type signatures", &debug['T']);
+	flagcount("V", "enable pointer type checks", &debug['V']);
+	flagcount("W", "debug switch generation", &debug['W']);
+	flagcount("X", "abort on error", &debug['X']);
+	flagcount("Y", "debug index generation", &debug['Y']);
+	flagcount("Z", "skip code generation", &debug['Z']);
+	flagcount("a", "print acid definitions", &debug['a']);
+	flagcount("c", "debug constant evaluation", &debug['c']);
+	flagcount("d", "debug declarations", &debug['d']);
+	flagcount("e", "debug macro expansion", &debug['e']);
+	flagcount("f", "debug pragmas", &debug['f']);
+	flagcount("g", "debug code generation", &debug['g']);
+	flagcount("i", "debug initialization", &debug['i']);
+	if(thechar == 'v')
+		flagfn0("l", "little-endian mips mode", dospim);
+	flagcount("m", "debug multiplication", &debug['m']);
+	flagcount("n", "print acid/Go to file, not stdout", &debug['n']);
+	flagstr("o", "file: set output file", &outfile);
+	flagcount("p", "invoke C preprocessor", &debug['p']);	
+	flagcount("q", "print Go definitions", &debug['q']);
+	flagcount("s", "print #define assembly offsets", &debug['s']);
+	flagcount("t", "debug code generation", &debug['t']);
+	flagcount("w", "enable warnings", &debug['w']);
+	flagcount("v", "increase debug verbosity", &debug['v']);	
+	if(thechar == '6')
+		flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel);
+	
+	flagparse(&argc, &argv, usage);
+
+	if(argc < 1 && outfile == 0)
+		usage();
 
-	case 'I':
-		p = ARGF();
-		setinclude(p);
-		break;
-	} ARGEND
-	if(argc < 1 && outfile == 0) {
-		print("usage: %cc [-options] files\n", thechar);
-		errorexit();
-	}
 	if(argc > 1){
 		print("can't compile multiple files\n");
 		errorexit();
@@ -377,11 +419,16 @@ lookup(void)
 		symb[1] = '"';
 	}
 
-	// turn · into .
 	for(r=w=symb; *r; r++) {
+		// turn · (U+00B7) into .
+		// turn ∕ (U+2215) into /
 		if((uchar)*r == 0xc2 && (uchar)*(r+1) == 0xb7) {
 			*w++ = '.';
 			r++;
+		}else if((uchar)*r == 0xe2 && (uchar)*(r+1) == 0x88 && (uchar)*(r+2) == 0x95) {
+			*w++ = '/';
+			r++;
+			r++;
 		}else
 			*w++ = *r;
 	}
@@ -1174,6 +1221,7 @@ struct
 	"inline",	LINLINE,	0,
 	"int",		LINT,		TINT,
 	"long",		LLONG,		TLONG,
+	"PREFETCH",	LPREFETCH,	0,
 	"register",	LREGISTER,	0,
 	"restrict",	LRESTRICT,	0,
 	"return",	LRETURN,	0,
diff --git a/src/cmd/cc/lexbody b/src/cmd/cc/lexbody
index d339cf9..5fa9802 100644
--- a/src/cmd/cc/lexbody
+++ b/src/cmd/cc/lexbody
@@ -47,15 +47,9 @@ pragvararg(void)
 }
 
 void
-pragdynimport(void)
-{
-	while(getnsc() != '\n')
-		;
-}
-
-void
-pragdynexport(void)
+pragcgo(char *name)
 {
+	USED(name);
 	while(getnsc() != '\n')
 		;
 }
@@ -244,11 +238,16 @@ lookup(void)
 		symb[1] = '"';
 	}
 
-	// turn · into .
 	for(r=w=symb; *r; r++) {
+		// turn · (U+00B7) into .
+		// turn ∕ (U+2215) into /
 		if((uchar)*r == 0xc2 && (uchar)*(r+1) == 0xb7) {
 			*w++ = '.';
 			r++;
+		}else if((uchar)*r == 0xe2 && (uchar)*(r+1) == 0x88 && (uchar)*(r+2) == 0x95) {
+			*w++ = '/';
+			r++;
+			r++;
 		}else
 			*w++ = *r;
 	}
diff --git a/src/cmd/cc/macbody b/src/cmd/cc/macbody
index 874e82d..f0a5076 100644
--- a/src/cmd/cc/macbody
+++ b/src/cmd/cc/macbody
@@ -743,12 +743,8 @@ macprag(void)
 		pragincomplete();
 		return;
 	}
-	if(s && strcmp(s->name, "dynimport") == 0) {
-		pragdynimport();
-		return;
-	}
-	if(s && strcmp(s->name, "dynexport") == 0) {
-		pragdynexport();
+	if(s && (strncmp(s->name, "cgo_", 4) == 0 || strncmp(s->name, "dyn", 3) == 0)) {
+		pragcgo(s->name);
 		return;
 	}
 	while(getnsc() != '\n')
diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c
index 3a68610..b06aa99 100644
--- a/src/cmd/cc/pgen.c
+++ b/src/cmd/cc/pgen.c
@@ -528,6 +528,7 @@ loop:
 
 	case OSET:
 	case OUSED:
+	case OPREFETCH:
 		usedset(n->left, o);
 		break;
 	}
@@ -542,6 +543,10 @@ usedset(Node *n, int o)
 		return;
 	}
 	complex(n);
+	if(o == OPREFETCH) {
+		gprefetch(n);
+		return;
+	}
 	switch(n->op) {
 	case OADDR:	/* volatile */
 		gins(ANOP, n, Z);
diff --git a/src/cmd/cc/sub.c b/src/cmd/cc/sub.c
index 72d671b..3a55763 100644
--- a/src/cmd/cc/sub.c
+++ b/src/cmd/cc/sub.c
@@ -847,12 +847,6 @@ simplifyshift(Node *n)
 	c2 = n->left->left->right->vconst;
 	c3 = n->left->right->vconst;
 
-/*
-	if(debug['h'])
-		print("%.3o %d %d %d #%.ux\n",
-			(s1<<3)|s2, c1, c2, topbit(c3), c3);
-*/
-
 	o = n->op;
 	switch((s1<<3)|s2) {
 	case 000:	/* (((e <<u c2) & c3) <<u c1) */
@@ -1497,6 +1491,7 @@ Init	onamesinit[] =
 	OPOSTINC,	0,	"POSTINC",
 	OPREDEC,	0,	"PREDEC",
 	OPREINC,	0,	"PREINC",
+	OPREFETCH,		0,	"PREFETCH",
 	OPROTO,		0,	"PROTO",
 	OREGISTER,	0,	"REGISTER",
 	ORETURN,	0,	"RETURN",
@@ -1520,6 +1515,7 @@ Init	onamesinit[] =
 	OINDEX,		0,	"INDEX",
 	OFAS,		0,	"FAS",
 	OREGPAIR,	0,	"REGPAIR",
+	OROTL,		0,	"ROTL",
 	OEND,		0,	"END",
 	-1,		0,	0,
 };
diff --git a/src/cmd/cc/y.tab.c b/src/cmd/cc/y.tab.c
index af8328a..10938c1 100644
--- a/src/cmd/cc/y.tab.c
+++ b/src/cmd/cc/y.tab.c
@@ -115,28 +115,29 @@
      LIF = 304,
      LINT = 305,
      LLONG = 306,
-     LREGISTER = 307,
-     LRETURN = 308,
-     LSHORT = 309,
-     LSIZEOF = 310,
-     LUSED = 311,
-     LSTATIC = 312,
-     LSTRUCT = 313,
-     LSWITCH = 314,
-     LTYPEDEF = 315,
-     LTYPESTR = 316,
-     LUNION = 317,
-     LUNSIGNED = 318,
-     LWHILE = 319,
-     LVOID = 320,
-     LENUM = 321,
-     LSIGNED = 322,
-     LCONSTNT = 323,
-     LVOLATILE = 324,
-     LSET = 325,
-     LSIGNOF = 326,
-     LRESTRICT = 327,
-     LINLINE = 328
+     LPREFETCH = 307,
+     LREGISTER = 308,
+     LRETURN = 309,
+     LSHORT = 310,
+     LSIZEOF = 311,
+     LUSED = 312,
+     LSTATIC = 313,
+     LSTRUCT = 314,
+     LSWITCH = 315,
+     LTYPEDEF = 316,
+     LTYPESTR = 317,
+     LUNION = 318,
+     LUNSIGNED = 319,
+     LWHILE = 320,
+     LVOID = 321,
+     LENUM = 322,
+     LSIGNED = 323,
+     LCONSTNT = 324,
+     LVOLATILE = 325,
+     LSET = 326,
+     LSIGNOF = 327,
+     LRESTRICT = 328,
+     LINLINE = 329
    };
 #endif
 /* Tokens.  */
@@ -189,28 +190,29 @@
 #define LIF 304
 #define LINT 305
 #define LLONG 306
-#define LREGISTER 307
-#define LRETURN 308
-#define LSHORT 309
-#define LSIZEOF 310
-#define LUSED 311
-#define LSTATIC 312
-#define LSTRUCT 313
-#define LSWITCH 314
-#define LTYPEDEF 315
-#define LTYPESTR 316
-#define LUNION 317
-#define LUNSIGNED 318
-#define LWHILE 319
-#define LVOID 320
-#define LENUM 321
-#define LSIGNED 322
-#define LCONSTNT 323
-#define LVOLATILE 324
-#define LSET 325
-#define LSIGNOF 326
-#define LRESTRICT 327
-#define LINLINE 328
+#define LPREFETCH 307
+#define LREGISTER 308
+#define LRETURN 309
+#define LSHORT 310
+#define LSIZEOF 311
+#define LUSED 312
+#define LSTATIC 313
+#define LSTRUCT 314
+#define LSWITCH 315
+#define LTYPEDEF 316
+#define LTYPESTR 317
+#define LUNION 318
+#define LUNSIGNED 319
+#define LWHILE 320
+#define LVOID 321
+#define LENUM 322
+#define LSIGNED 323
+#define LCONSTNT 324
+#define LVOLATILE 325
+#define LSET 326
+#define LSIGNOF 327
+#define LRESTRICT 328
+#define LINLINE 329
 
 
 
@@ -270,7 +272,7 @@ typedef union YYSTYPE
 	vlong	vval;
 }
 /* Line 193 of yacc.c.  */
-#line 274 "y.tab.c"
+#line 276 "y.tab.c"
 	YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -283,7 +285,7 @@ typedef union YYSTYPE
 
 
 /* Line 216 of yacc.c.  */
-#line 287 "y.tab.c"
+#line 289 "y.tab.c"
 
 #ifdef short
 # undef short
@@ -501,17 +503,17 @@ union yyalloc
 #define YYLAST   1188
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  98
+#define YYNTOKENS  99
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  75
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  246
+#define YYNRULES  247
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  412
+#define YYNSTATES  417
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   328
+#define YYMAXUTOK   329
 
 #define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -522,16 +524,16 @@ static const yytype_uint8 yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    96,     2,     2,     2,    35,    22,     2,
-      38,    92,    33,    31,     4,    32,    36,    34,     2,     2,
+       2,     2,     2,    97,     2,     2,     2,    35,    22,     2,
+      38,    93,    33,    31,     4,    32,    36,    34,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,    17,     3,
       25,     5,    26,    16,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    37,     2,    93,    21,     2,     2,     2,     2,     2,
+       2,    37,     2,    94,    21,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    94,    20,    95,    97,     2,     2,     2,
+       2,     2,     2,    95,    20,    96,    98,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -551,7 +553,7 @@ static const yytype_uint8 yytranslate[] =
       53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
       63,    64,    65,    66,    67,    68,    69,    70,    71,    72,
       73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
-      83,    84,    85,    86,    87,    88,    89,    90,    91
+      83,    84,    85,    86,    87,    88,    89,    90,    91,    92
 };
 
 #if YYDEBUG
@@ -569,102 +571,103 @@ static const yytype_uint16 yyprhs[] =
      208,   212,   213,   216,   219,   221,   224,   228,   231,   234,
      237,   239,   242,   244,   247,   250,   251,   254,   260,   268,
      269,   280,   286,   294,   298,   304,   307,   310,   314,   320,
-     326,   327,   329,   330,   332,   334,   336,   340,   342,   346,
-     350,   354,   358,   362,   366,   370,   374,   378,   382,   386,
-     390,   394,   398,   402,   406,   410,   414,   420,   424,   428,
-     432,   436,   440,   444,   448,   452,   456,   460,   464,   466,
-     472,   480,   482,   485,   488,   491,   494,   497,   500,   503,
-     506,   509,   512,   516,   522,   528,   533,   538,   542,   546,
-     549,   552,   554,   556,   558,   560,   562,   564,   566,   568,
-     570,   572,   574,   576,   579,   581,   584,   585,   587,   589,
-     593,   594,   599,   600,   602,   604,   606,   608,   611,   614,
-     618,   621,   625,   627,   629,   632,   633,   638,   641,   644,
-     645,   650,   653,   656,   657,   658,   666,   667,   673,   675,
-     677,   680,   681,   684,   686,   688,   690,   692,   695,   697,
-     699,   701,   705,   708,   712,   714,   716,   718,   720,   722,
-     724,   726,   728,   730,   732,   734,   736,   738,   740,   742,
-     744,   746,   748,   750,   752,   754,   756
+     326,   332,   333,   335,   336,   338,   340,   342,   346,   348,
+     352,   356,   360,   364,   368,   372,   376,   380,   384,   388,
+     392,   396,   400,   404,   408,   412,   416,   420,   426,   430,
+     434,   438,   442,   446,   450,   454,   458,   462,   466,   470,
+     472,   478,   486,   488,   491,   494,   497,   500,   503,   506,
+     509,   512,   515,   518,   522,   528,   534,   539,   544,   548,
+     552,   555,   558,   560,   562,   564,   566,   568,   570,   572,
+     574,   576,   578,   580,   582,   585,   587,   590,   591,   593,
+     595,   599,   600,   605,   606,   608,   610,   612,   614,   617,
+     620,   624,   627,   631,   633,   635,   638,   639,   644,   647,
+     650,   651,   656,   659,   662,   663,   664,   672,   673,   679,
+     681,   683,   686,   687,   690,   692,   694,   696,   698,   701,
+     703,   705,   707,   711,   714,   718,   720,   722,   724,   726,
+     728,   730,   732,   734,   736,   738,   740,   742,   744,   746,
+     748,   750,   752,   754,   756,   758,   760,   762
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int16 yyrhs[] =
 {
-      99,     0,    -1,    -1,    99,   100,    -1,   151,     3,    -1,
-     151,   103,     3,    -1,    -1,    -1,   151,   105,   101,   110,
-     102,   128,    -1,   105,    -1,    -1,   105,   104,     5,   122,
-      -1,   103,     4,   103,    -1,   106,    -1,    33,   162,   105,
-      -1,   171,    -1,    38,   105,    92,    -1,   106,    38,   126,
-      92,    -1,   106,    37,   138,    93,    -1,   154,     3,    -1,
-     154,   108,     3,    -1,   105,    -1,    -1,   105,   109,     5,
-     122,    -1,   108,     4,   108,    -1,    -1,   110,   154,   111,
-       3,    -1,   105,    -1,   111,     4,   111,    -1,    -1,   153,
-     113,   115,     3,    -1,    -1,   112,   153,   114,   115,     3,
-      -1,    -1,   116,    -1,   117,    -1,   116,     4,   116,    -1,
-     105,    -1,   171,    17,   139,    -1,    17,   139,    -1,    -1,
-     119,    -1,    33,   162,    -1,    33,   162,   119,    -1,   120,
-      -1,   121,    -1,   120,    38,   126,    92,    -1,   120,    37,
-     138,    93,    -1,    38,    92,    -1,    37,   138,    93,    -1,
-      38,   119,    92,    -1,   141,    -1,    94,   125,    95,    -1,
-      37,   139,    93,    -1,    36,   172,    -1,   123,     5,    -1,
-     122,     4,    -1,   124,   122,     4,    -1,   123,    -1,   124,
-     123,    -1,   124,    -1,   122,    -1,   124,   122,    -1,    -1,
-     127,    -1,   170,    -1,   153,   118,    -1,   153,   105,    -1,
-      36,    36,    36,    -1,   127,     4,   127,    -1,    94,   129,
-      95,    -1,    -1,   129,   107,    -1,   129,   132,    -1,   131,
-      -1,   130,   131,    -1,    56,   141,    17,    -1,    59,    17,
-      -1,    42,    17,    -1,     1,     3,    -1,   134,    -1,   130,
-     134,    -1,   137,    -1,   154,   108,    -1,   137,     3,    -1,
-      -1,   135,   128,    -1,    67,    38,   140,    92,   132,    -1,
-      67,    38,   140,    92,   132,    62,   132,    -1,    -1,   136,
-      65,    38,   133,     3,   137,     3,   137,    92,   132,    -1,
-      82,    38,   140,    92,   132,    -1,    60,   132,    82,    38,
-     140,    92,     3,    -1,    71,   137,     3,    -1,    77,    38,
-     140,    92,   132,    -1,    55,     3,    -1,    58,     3,    -1,
-      66,   172,     3,    -1,    74,    38,   147,    92,     3,    -1,
-      88,    38,   147,    92,     3,    -1,    -1,   140,    -1,    -1,
-     139,    -1,   141,    -1,   141,    -1,   140,     4,   140,    -1,
-     142,    -1,   141,    33,   141,    -1,   141,    34,   141,    -1,
-     141,    35,   141,    -1,   141,    31,   141,    -1,   141,    32,
-     141,    -1,   141,    29,   141,    -1,   141,    30,   141,    -1,
-     141,    25,   141,    -1,   141,    26,   141,    -1,   141,    28,
-     141,    -1,   141,    27,   141,    -1,   141,    24,   141,    -1,
-     141,    23,   141,    -1,   141,    22,   141,    -1,   141,    21,
-     141,    -1,   141,    20,   141,    -1,   141,    19,   141,    -1,
-     141,    18,   141,    -1,   141,    16,   140,    17,   141,    -1,
-     141,     5,   141,    -1,   141,    15,   141,    -1,   141,    14,
-     141,    -1,   141,    13,   141,    -1,   141,    12,   141,    -1,
-     141,    11,   141,    -1,   141,     9,   141,    -1,   141,    10,
-     141,    -1,   141,     8,   141,    -1,   141,     7,   141,    -1,
-     141,     6,   141,    -1,   143,    -1,    38,   153,   118,    92,
-     142,    -1,    38,   153,   118,    92,    94,   125,    95,    -1,
-     144,    -1,    33,   142,    -1,    22,   142,    -1,    31,   142,
-      -1,    32,   142,    -1,    96,   142,    -1,    97,   142,    -1,
-      40,   142,    -1,    41,   142,    -1,    73,   143,    -1,    89,
-     143,    -1,    38,   140,    92,    -1,    73,    38,   153,   118,
-      92,    -1,    89,    38,   153,   118,    92,    -1,   144,    38,
-     147,    92,    -1,   144,    37,   140,    93,    -1,   144,    39,
-     172,    -1,   144,    36,   172,    -1,   144,    40,    -1,   144,
-      41,    -1,   170,    -1,    46,    -1,    47,    -1,    48,    -1,
-      49,    -1,    45,    -1,    44,    -1,    50,    -1,    51,    -1,
-     145,    -1,   146,    -1,    52,    -1,   145,    52,    -1,    53,
-      -1,   146,    53,    -1,    -1,   148,    -1,   141,    -1,   148,
-       4,   148,    -1,    -1,    94,   150,   112,    95,    -1,    -1,
-     154,    -1,   155,    -1,   167,    -1,   164,    -1,   155,   161,
-      -1,   167,   161,    -1,   164,   155,   162,    -1,   164,   167,
-      -1,   164,   167,   161,    -1,   152,    -1,   152,    -1,    76,
-     172,    -1,    -1,    76,   172,   156,   149,    -1,    76,   149,
-      -1,    80,   172,    -1,    -1,    80,   172,   157,   149,    -1,
-      80,   149,    -1,    84,   172,    -1,    -1,    -1,    84,   172,
-     158,    94,   159,   166,    95,    -1,    -1,    84,    94,   160,
-     166,    95,    -1,    43,    -1,   163,    -1,   161,   163,    -1,
-      -1,   162,   169,    -1,   167,    -1,   169,    -1,   168,    -1,
-     165,    -1,   164,   165,    -1,   169,    -1,   168,    -1,    42,
-      -1,    42,     5,   141,    -1,   166,     4,    -1,   166,     4,
-     166,    -1,    57,    -1,    72,    -1,    68,    -1,    69,    -1,
-      85,    -1,    81,    -1,    64,    -1,    61,    -1,    83,    -1,
-      54,    -1,    75,    -1,    63,    -1,    78,    -1,    79,    -1,
-      70,    -1,    91,    -1,    86,    -1,    87,    -1,    90,    -1,
-      42,    -1,   172,    -1,    42,    -1,    43,    -1
+     100,     0,    -1,    -1,   100,   101,    -1,   152,     3,    -1,
+     152,   104,     3,    -1,    -1,    -1,   152,   106,   102,   111,
+     103,   129,    -1,   106,    -1,    -1,   106,   105,     5,   123,
+      -1,   104,     4,   104,    -1,   107,    -1,    33,   163,   106,
+      -1,   172,    -1,    38,   106,    93,    -1,   107,    38,   127,
+      93,    -1,   107,    37,   139,    94,    -1,   155,     3,    -1,
+     155,   109,     3,    -1,   106,    -1,    -1,   106,   110,     5,
+     123,    -1,   109,     4,   109,    -1,    -1,   111,   155,   112,
+       3,    -1,   106,    -1,   112,     4,   112,    -1,    -1,   154,
+     114,   116,     3,    -1,    -1,   113,   154,   115,   116,     3,
+      -1,    -1,   117,    -1,   118,    -1,   117,     4,   117,    -1,
+     106,    -1,   172,    17,   140,    -1,    17,   140,    -1,    -1,
+     120,    -1,    33,   163,    -1,    33,   163,   120,    -1,   121,
+      -1,   122,    -1,   121,    38,   127,    93,    -1,   121,    37,
+     139,    94,    -1,    38,    93,    -1,    37,   139,    94,    -1,
+      38,   120,    93,    -1,   142,    -1,    95,   126,    96,    -1,
+      37,   140,    94,    -1,    36,   173,    -1,   124,     5,    -1,
+     123,     4,    -1,   125,   123,     4,    -1,   124,    -1,   125,
+     124,    -1,   125,    -1,   123,    -1,   125,   123,    -1,    -1,
+     128,    -1,   171,    -1,   154,   119,    -1,   154,   106,    -1,
+      36,    36,    36,    -1,   128,     4,   128,    -1,    95,   130,
+      96,    -1,    -1,   130,   108,    -1,   130,   133,    -1,   132,
+      -1,   131,   132,    -1,    56,   142,    17,    -1,    59,    17,
+      -1,    42,    17,    -1,     1,     3,    -1,   135,    -1,   131,
+     135,    -1,   138,    -1,   155,   109,    -1,   138,     3,    -1,
+      -1,   136,   129,    -1,    67,    38,   141,    93,   133,    -1,
+      67,    38,   141,    93,   133,    62,   133,    -1,    -1,   137,
+      65,    38,   134,     3,   138,     3,   138,    93,   133,    -1,
+      83,    38,   141,    93,   133,    -1,    60,   133,    83,    38,
+     141,    93,     3,    -1,    72,   138,     3,    -1,    78,    38,
+     141,    93,   133,    -1,    55,     3,    -1,    58,     3,    -1,
+      66,   173,     3,    -1,    75,    38,   148,    93,     3,    -1,
+      70,    38,   148,    93,     3,    -1,    89,    38,   148,    93,
+       3,    -1,    -1,   141,    -1,    -1,   140,    -1,   142,    -1,
+     142,    -1,   141,     4,   141,    -1,   143,    -1,   142,    33,
+     142,    -1,   142,    34,   142,    -1,   142,    35,   142,    -1,
+     142,    31,   142,    -1,   142,    32,   142,    -1,   142,    29,
+     142,    -1,   142,    30,   142,    -1,   142,    25,   142,    -1,
+     142,    26,   142,    -1,   142,    28,   142,    -1,   142,    27,
+     142,    -1,   142,    24,   142,    -1,   142,    23,   142,    -1,
+     142,    22,   142,    -1,   142,    21,   142,    -1,   142,    20,
+     142,    -1,   142,    19,   142,    -1,   142,    18,   142,    -1,
+     142,    16,   141,    17,   142,    -1,   142,     5,   142,    -1,
+     142,    15,   142,    -1,   142,    14,   142,    -1,   142,    13,
+     142,    -1,   142,    12,   142,    -1,   142,    11,   142,    -1,
+     142,     9,   142,    -1,   142,    10,   142,    -1,   142,     8,
+     142,    -1,   142,     7,   142,    -1,   142,     6,   142,    -1,
+     144,    -1,    38,   154,   119,    93,   143,    -1,    38,   154,
+     119,    93,    95,   126,    96,    -1,   145,    -1,    33,   143,
+      -1,    22,   143,    -1,    31,   143,    -1,    32,   143,    -1,
+      97,   143,    -1,    98,   143,    -1,    40,   143,    -1,    41,
+     143,    -1,    74,   144,    -1,    90,   144,    -1,    38,   141,
+      93,    -1,    74,    38,   154,   119,    93,    -1,    90,    38,
+     154,   119,    93,    -1,   145,    38,   148,    93,    -1,   145,
+      37,   141,    94,    -1,   145,    39,   173,    -1,   145,    36,
+     173,    -1,   145,    40,    -1,   145,    41,    -1,   171,    -1,
+      46,    -1,    47,    -1,    48,    -1,    49,    -1,    45,    -1,
+      44,    -1,    50,    -1,    51,    -1,   146,    -1,   147,    -1,
+      52,    -1,   146,    52,    -1,    53,    -1,   147,    53,    -1,
+      -1,   149,    -1,   142,    -1,   149,     4,   149,    -1,    -1,
+      95,   151,   113,    96,    -1,    -1,   155,    -1,   156,    -1,
+     168,    -1,   165,    -1,   156,   162,    -1,   168,   162,    -1,
+     165,   156,   163,    -1,   165,   168,    -1,   165,   168,   162,
+      -1,   153,    -1,   153,    -1,    77,   173,    -1,    -1,    77,
+     173,   157,   150,    -1,    77,   150,    -1,    81,   173,    -1,
+      -1,    81,   173,   158,   150,    -1,    81,   150,    -1,    85,
+     173,    -1,    -1,    -1,    85,   173,   159,    95,   160,   167,
+      96,    -1,    -1,    85,    95,   161,   167,    96,    -1,    43,
+      -1,   164,    -1,   162,   164,    -1,    -1,   163,   170,    -1,
+     168,    -1,   170,    -1,   169,    -1,   166,    -1,   165,   166,
+      -1,   170,    -1,   169,    -1,    42,    -1,    42,     5,   142,
+      -1,   167,     4,    -1,   167,     4,   167,    -1,    57,    -1,
+      73,    -1,    68,    -1,    69,    -1,    86,    -1,    82,    -1,
+      64,    -1,    61,    -1,    84,    -1,    54,    -1,    76,    -1,
+      63,    -1,    79,    -1,    80,    -1,    71,    -1,    92,    -1,
+      87,    -1,    88,    -1,    91,    -1,    42,    -1,   173,    -1,
+      42,    -1,    43,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
@@ -680,21 +683,21 @@ static const yytype_uint16 yyrline[] =
      396,   406,   409,   413,   419,   420,   426,   430,   434,   440,
      444,   445,   451,   452,   458,   459,   459,   470,   476,   484,
      484,   495,   499,   503,   508,   522,   526,   530,   534,   538,
-     544,   547,   550,   553,   556,   563,   564,   570,   571,   575,
+     542,   548,   551,   554,   557,   560,   567,   568,   574,   575,
      579,   583,   587,   591,   595,   599,   603,   607,   611,   615,
      619,   623,   627,   631,   635,   639,   643,   647,   651,   655,
-     659,   663,   667,   671,   675,   679,   683,   687,   693,   694,
-     701,   709,   710,   714,   718,   722,   726,   730,   734,   738,
-     742,   746,   752,   756,   762,   768,   776,   780,   785,   790,
-     794,   798,   799,   806,   813,   820,   827,   834,   841,   848,
-     855,   856,   859,   869,   887,   897,   915,   918,   921,   922,
-     929,   928,   951,   955,   958,   963,   968,   974,   982,   988,
-     994,  1000,  1008,  1016,  1023,  1029,  1028,  1040,  1048,  1054,
-    1053,  1065,  1073,  1082,  1086,  1081,  1103,  1102,  1111,  1117,
-    1118,  1124,  1127,  1133,  1134,  1135,  1138,  1139,  1145,  1146,
-    1149,  1153,  1157,  1158,  1161,  1162,  1163,  1164,  1165,  1166,
-    1167,  1168,  1169,  1172,  1173,  1174,  1175,  1176,  1177,  1178,
-    1181,  1182,  1183,  1186,  1201,  1213,  1214
+     659,   663,   667,   671,   675,   679,   683,   687,   691,   697,
+     698,   705,   713,   714,   718,   722,   726,   730,   734,   738,
+     742,   746,   750,   756,   760,   766,   772,   780,   784,   789,
+     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
 };
 #endif
 
@@ -711,8 +714,8 @@ static const char *const yytname[] =
   "LDCONST", "LCONST", "LLCONST", "LUCONST", "LULCONST", "LVLCONST",
   "LUVLCONST", "LSTRING", "LLSTRING", "LAUTO", "LBREAK", "LCASE", "LCHAR",
   "LCONTINUE", "LDEFAULT", "LDO", "LDOUBLE", "LELSE", "LEXTERN", "LFLOAT",
-  "LFOR", "LGOTO", "LIF", "LINT", "LLONG", "LREGISTER", "LRETURN",
-  "LSHORT", "LSIZEOF", "LUSED", "LSTATIC", "LSTRUCT", "LSWITCH",
+  "LFOR", "LGOTO", "LIF", "LINT", "LLONG", "LPREFETCH", "LREGISTER",
+  "LRETURN", "LSHORT", "LSIZEOF", "LUSED", "LSTATIC", "LSTRUCT", "LSWITCH",
   "LTYPEDEF", "LTYPESTR", "LUNION", "LUNSIGNED", "LWHILE", "LVOID",
   "LENUM", "LSIGNED", "LCONSTNT", "LVOLATILE", "LSET", "LSIGNOF",
   "LRESTRICT", "LINLINE", "')'", "']'", "'{'", "'}'", "'!'", "'~'",
@@ -743,38 +746,38 @@ static const yytype_uint16 yytoknum[] =
      297,   298,   299,   300,   301,   302,   303,   304,   305,   306,
      307,   308,   309,   310,   311,   312,   313,   314,   315,   316,
      317,   318,   319,   320,   321,   322,   323,   324,   325,   326,
-     327,   328,    41,    93,   123,   125,    33,   126
+     327,   328,   329,    41,    93,   123,   125,    33,   126
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    98,    99,    99,   100,   100,   101,   102,   100,   103,
-     104,   103,   103,   105,   105,   106,   106,   106,   106,   107,
-     107,   108,   109,   108,   108,   110,   110,   111,   111,   113,
-     112,   114,   112,   115,   115,   116,   116,   117,   117,   117,
-     118,   118,   119,   119,   119,   120,   120,   120,   121,   121,
-     121,   122,   122,   123,   123,   123,   124,   124,   124,   124,
-     125,   125,   125,   126,   126,   127,   127,   127,   127,   127,
-     128,   129,   129,   129,   130,   130,   131,   131,   131,   132,
-     132,   132,   133,   133,   134,   135,   134,   134,   134,   136,
-     134,   134,   134,   134,   134,   134,   134,   134,   134,   134,
-     137,   137,   138,   138,   139,   140,   140,   141,   141,   141,
-     141,   141,   141,   141,   141,   141,   141,   141,   141,   141,
-     141,   141,   141,   141,   141,   141,   141,   141,   141,   141,
-     141,   141,   141,   141,   141,   141,   141,   141,   142,   142,
-     142,   143,   143,   143,   143,   143,   143,   143,   143,   143,
+       0,    99,   100,   100,   101,   101,   102,   103,   101,   104,
+     105,   104,   104,   106,   106,   107,   107,   107,   107,   108,
+     108,   109,   110,   109,   109,   111,   111,   112,   112,   114,
+     113,   115,   113,   116,   116,   117,   117,   118,   118,   118,
+     119,   119,   120,   120,   120,   121,   121,   121,   122,   122,
+     122,   123,   123,   124,   124,   124,   125,   125,   125,   125,
+     126,   126,   126,   127,   127,   128,   128,   128,   128,   128,
+     129,   130,   130,   130,   131,   131,   132,   132,   132,   133,
+     133,   133,   134,   134,   135,   136,   135,   135,   135,   137,
+     135,   135,   135,   135,   135,   135,   135,   135,   135,   135,
+     135,   138,   138,   139,   139,   140,   141,   141,   142,   142,
+     142,   142,   142,   142,   142,   142,   142,   142,   142,   142,
+     142,   142,   142,   142,   142,   142,   142,   142,   142,   142,
+     142,   142,   142,   142,   142,   142,   142,   142,   142,   143,
      143,   143,   144,   144,   144,   144,   144,   144,   144,   144,
-     144,   144,   144,   144,   144,   144,   144,   144,   144,   144,
-     144,   144,   145,   145,   146,   146,   147,   147,   148,   148,
-     150,   149,   151,   151,   152,   152,   152,   152,   152,   152,
-     152,   152,   153,   154,   155,   156,   155,   155,   155,   157,
-     155,   155,   155,   158,   159,   155,   160,   155,   155,   161,
-     161,   162,   162,   163,   163,   163,   164,   164,   165,   165,
-     166,   166,   166,   166,   167,   167,   167,   167,   167,   167,
-     167,   167,   167,   168,   168,   168,   168,   168,   168,   168,
-     169,   169,   169,   170,   171,   172,   172
+     144,   144,   144,   145,   145,   145,   145,   145,   145,   145,
+     145,   145,   145,   145,   145,   145,   145,   145,   145,   145,
+     145,   145,   145,   146,   146,   147,   147,   148,   148,   149,
+     149,   151,   150,   152,   152,   153,   153,   153,   153,   153,
+     153,   153,   153,   154,   155,   156,   157,   156,   156,   156,
+     158,   156,   156,   156,   159,   160,   156,   161,   156,   156,
+     162,   162,   163,   163,   164,   164,   164,   165,   165,   166,
+     166,   167,   167,   167,   167,   168,   168,   168,   168,   168,
+     168,   168,   168,   168,   169,   169,   169,   169,   169,   169,
+     169,   170,   170,   170,   171,   172,   173,   173
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -790,21 +793,21 @@ static const yytype_uint8 yyr2[] =
        3,     0,     2,     2,     1,     2,     3,     2,     2,     2,
        1,     2,     1,     2,     2,     0,     2,     5,     7,     0,
       10,     5,     7,     3,     5,     2,     2,     3,     5,     5,
-       0,     1,     0,     1,     1,     1,     3,     1,     3,     3,
+       5,     0,     1,     0,     1,     1,     1,     3,     1,     3,
        3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
-       3,     3,     3,     3,     3,     3,     5,     3,     3,     3,
-       3,     3,     3,     3,     3,     3,     3,     3,     1,     5,
-       7,     1,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     3,     5,     5,     4,     4,     3,     3,     2,
-       2,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     2,     1,     2,     0,     1,     1,     3,
-       0,     4,     0,     1,     1,     1,     1,     2,     2,     3,
-       2,     3,     1,     1,     2,     0,     4,     2,     2,     0,
-       4,     2,     2,     0,     0,     7,     0,     5,     1,     1,
-       2,     0,     2,     1,     1,     1,     1,     2,     1,     1,
-       1,     3,     2,     3,     1,     1,     1,     1,     1,     1,
+       3,     3,     3,     3,     3,     3,     3,     5,     3,     3,
+       3,     3,     3,     3,     3,     3,     3,     3,     3,     1,
+       5,     7,     1,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     3,     5,     5,     4,     4,     3,     3,
+       2,     2,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     2,     1,     2,     0,     1,     1,
+       3,     0,     4,     0,     1,     1,     1,     1,     2,     2,
+       3,     2,     3,     1,     1,     2,     0,     4,     2,     2,
+       0,     4,     2,     2,     0,     0,     7,     0,     5,     1,
+       1,     2,     0,     2,     1,     1,     1,     1,     2,     1,
+       1,     1,     3,     2,     3,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1
+       1,     1,     1,     1,     1,     1,     1,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -812,58 +815,58 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       2,   182,     1,   208,   233,   224,   231,   235,   230,   226,
-     227,   238,   225,   234,     0,   236,   237,     0,   229,   232,
-       0,   228,   240,   241,   242,   239,     3,     0,   193,   183,
-     184,   186,   216,   185,   219,   218,   245,   246,   180,   197,
-     194,   201,   198,   206,   202,     4,   211,     0,     0,     6,
-      13,    15,   244,   187,   209,   213,   215,   214,   211,   217,
-     190,   188,     0,     0,     0,     0,     0,     0,     0,     5,
-       0,    25,     0,   102,    63,   210,   189,   191,     0,   192,
-      29,   196,   200,   220,     0,   204,    14,   212,    16,    12,
+       2,   183,     1,   209,   234,   225,   232,   236,   231,   227,
+     228,   239,   226,   235,     0,   237,   238,     0,   230,   233,
+       0,   229,   241,   242,   243,   240,     3,     0,   194,   184,
+     185,   187,   217,   186,   220,   219,   246,   247,   181,   198,
+     195,   202,   199,   207,   203,     4,   212,     0,     0,     6,
+      13,    15,   245,   188,   210,   214,   216,   215,   212,   218,
+     191,   189,     0,     0,     0,     0,     0,     0,     0,     5,
+       0,    25,     0,   103,    63,   211,   190,   192,     0,   193,
+      29,   197,   201,   221,     0,   205,    14,   213,    16,    12,
        9,     7,     0,     0,     0,     0,     0,     0,     0,     0,
-     243,   167,   166,   162,   163,   164,   165,   168,   169,   172,
-     174,     0,     0,     0,     0,     0,   103,   104,   107,   138,
-     141,   170,   171,   161,     0,     0,    64,    40,    65,   181,
-      31,    33,     0,   222,   207,     0,     0,     0,     0,    11,
-      51,   143,   144,   145,   142,     0,   105,    40,   148,   149,
-       0,   150,     0,   151,   146,   147,    18,     0,     0,     0,
+     244,   168,   167,   163,   164,   165,   166,   169,   170,   173,
+     175,     0,     0,     0,     0,     0,   104,   105,   108,   139,
+     142,   171,   172,   162,     0,     0,    64,    40,    65,   182,
+      31,    33,     0,   223,   208,     0,     0,     0,     0,    11,
+      51,   144,   145,   146,   143,     0,   106,    40,   149,   150,
+       0,   151,     0,   152,   147,   148,    18,     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,     0,   176,
-       0,   159,   160,   173,   175,     0,    17,     0,   211,   102,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   177,
+       0,   160,   161,   174,   176,     0,    17,     0,   212,   103,
        0,    67,    66,    41,    44,    45,    33,     0,    37,     0,
-      34,    35,    15,   221,   223,     0,    71,     8,    27,     0,
-       0,     0,    61,    58,    60,     0,     0,   152,   211,     0,
-       0,    40,    40,   127,   137,   136,   135,   133,   134,   132,
-     131,   130,   129,   128,     0,   125,   124,   123,   122,   121,
-     120,   119,   115,   116,   118,   117,   113,   114,   111,   112,
-     108,   109,   110,   158,     0,   178,     0,   177,   157,    68,
-      69,    42,     0,    48,     0,   102,    63,     0,    39,    30,
-       0,     0,   205,     0,    26,     0,    54,     0,    56,    55,
-      62,    59,    52,   106,    42,     0,     0,     0,     0,   156,
-     155,     0,    43,    49,    50,     0,     0,    32,    36,    38,
-       0,   243,     0,     0,     0,     0,     0,     0,     0,   100,
-       0,     0,     0,     0,    70,    72,    85,    74,    73,    80,
-       0,     0,     0,   101,     0,    28,    53,    57,     0,   139,
-     153,   154,   126,   179,    47,    46,    79,    78,    95,     0,
-      96,    77,     0,     0,     0,     0,   176,     0,     0,   176,
-      75,    81,    86,     0,    84,    19,    21,     0,     0,    76,
-       0,    97,     0,    93,     0,     0,     0,     0,   100,     0,
-      20,     0,   140,     0,     0,     0,     0,     0,     0,     0,
-      82,     0,     0,    24,     0,    87,    98,    94,    91,    99,
-     100,    83,    23,     0,     0,     0,    92,    88,   100,     0,
-       0,    90
+      34,    35,    15,   222,   224,     0,    71,     8,    27,     0,
+       0,     0,    61,    58,    60,     0,     0,   153,   212,     0,
+       0,    40,    40,   128,   138,   137,   136,   134,   135,   133,
+     132,   131,   130,   129,     0,   126,   125,   124,   123,   122,
+     121,   120,   116,   117,   119,   118,   114,   115,   112,   113,
+     109,   110,   111,   159,     0,   179,     0,   178,   158,    68,
+      69,    42,     0,    48,     0,   103,    63,     0,    39,    30,
+       0,     0,   206,     0,    26,     0,    54,     0,    56,    55,
+      62,    59,    52,   107,    42,     0,     0,     0,     0,   157,
+     156,     0,    43,    49,    50,     0,     0,    32,    36,    38,
+       0,   244,     0,     0,     0,     0,     0,     0,     0,     0,
+     101,     0,     0,     0,     0,    70,    72,    85,    74,    73,
+      80,     0,     0,     0,   102,     0,    28,    53,    57,     0,
+     140,   154,   155,   127,   180,    47,    46,    79,    78,    95,
+       0,    96,    77,     0,     0,     0,   177,     0,   177,     0,
+       0,   177,    75,    81,    86,     0,    84,    19,    21,     0,
+       0,    76,     0,    97,     0,     0,    93,     0,     0,     0,
+       0,   101,     0,    20,     0,   141,     0,     0,     0,     0,
+       0,     0,     0,     0,    82,     0,     0,    24,     0,    87,
+      99,    98,    94,    91,   100,   101,    83,    23,     0,     0,
+       0,    92,    88,   101,     0,     0,    90
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,    26,    71,   136,    48,    72,   208,    50,   325,
-     367,   379,    91,   219,    78,   131,   206,   209,   210,   211,
+      -1,     1,    26,    71,   136,    48,    72,   208,    50,   326,
+     369,   382,    91,   219,    78,   131,   206,   209,   210,   211,
      202,   203,   204,   205,   222,   223,   224,   225,   125,   126,
-     217,   283,   326,   327,   328,   389,   329,   330,   331,   332,
-     115,   116,   333,   146,   118,   119,   120,   121,   122,   266,
+     217,   283,   327,   328,   329,   393,   330,   331,   332,   333,
+     115,   116,   334,   146,   118,   119,   120,   121,   122,   266,
      267,    39,    62,    27,    79,   127,    29,    30,    63,    64,
       66,   135,    65,    53,    67,    54,    31,    32,    84,    33,
       34,    35,   123,    51,    52
@@ -871,184 +874,184 @@ static const yytype_int16 yydefgoto[] =
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -366
+#define YYPACT_NINF -331
 static const yytype_int16 yypact[] =
 {
-    -366,   541,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,
-    -366,  -366,  -366,  -366,    -3,  -366,  -366,    -3,  -366,  -366,
-     140,  -366,  -366,  -366,  -366,  -366,  -366,   161,  -366,  -366,
-     949,   914,  -366,   949,  -366,  -366,  -366,  -366,  -366,  -366,
-     -64,  -366,   -60,  -366,   -17,  -366,  -366,    21,    70,   316,
-      51,  -366,  -366,   949,  -366,  -366,  -366,  -366,  -366,  -366,
-     949,   949,   914,   -13,   -13,    57,     9,   154,    54,  -366,
-      21,  -366,   164,   745,   836,  -366,   -41,   949,   875,  -366,
-    -366,  -366,  -366,   167,     7,  -366,  -366,  -366,  -366,  -366,
-     181,   914,   677,   745,   745,   745,   745,   607,   745,   745,
-    -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,
-    -366,   779,   813,   745,   745,    95,  -366,  1067,  -366,  -366,
-     422,   141,   145,  -366,   176,   139,   225,   128,  -366,  -366,
-    -366,   289,   745,    57,  -366,    57,   149,    21,   169,  -366,
-    1067,  -366,  -366,  -366,  -366,    31,  1067,   130,  -366,  -366,
-     607,  -366,   607,  -366,  -366,  -366,  -366,   745,   745,   745,
-     745,   745,   745,   745,   745,   745,   745,   745,   745,   745,
-     745,   745,   745,   745,   745,   745,   745,   745,   745,   745,
-     745,   745,   745,   745,   745,   745,   745,    53,   745,   745,
-      53,  -366,  -366,  -366,  -366,   199,  -366,   836,  -366,   745,
-     147,  -366,  -366,  -366,   111,  -366,   289,   745,  -366,   243,
-     247,  -366,   235,  1067,  -366,    13,  -366,  -366,  -366,   222,
-      53,   745,   260,   255,   169,   172,   745,  -366,  -366,    -6,
-     180,   130,   130,  1067,  1067,  1067,  1067,  1067,  1067,  1067,
-    1067,  1067,  1067,  1067,    16,  1084,  1100,  1115,  1129,  1142,
-    1153,  1153,   319,   319,   319,   319,   303,   303,   295,   295,
-    -366,  -366,  -366,  -366,    11,  1067,   186,   269,  -366,  -366,
-    -366,   190,   188,  -366,   187,   745,   836,   280,  -366,  -366,
-     289,   745,  -366,   338,  -366,    21,  -366,   191,  -366,  -366,
-     284,   255,  -366,  -366,   217,   711,   202,   204,   745,  -366,
-    -366,   745,  -366,  -366,  -366,   198,   207,  -366,  -366,  -366,
-     309,   296,   312,   745,   320,   307,   435,    53,   302,   745,
-     305,   306,   308,   318,  -366,  -366,   504,  -366,  -366,  -366,
-     149,   292,   342,   354,   259,  -366,  -366,  -366,   169,  -366,
-    -366,  -366,   421,  -366,  -366,  -366,  -366,  -366,  -366,  1036,
-    -366,  -366,   277,   358,   745,   359,   745,   745,   745,   745,
-    -366,  -366,  -366,   325,  -366,  -366,   361,   234,   272,  -366,
-     326,  -366,    64,  -366,   276,    66,    67,   281,   607,   367,
-    -366,    21,  -366,   745,   435,   371,   435,   435,   372,   397,
-    -366,    21,   677,  -366,    68,   368,  -366,  -366,  -366,  -366,
-     745,   427,  -366,   461,   435,   462,  -366,  -366,   745,   377,
-     435,  -366
+    -331,   548,  -331,  -331,  -331,  -331,  -331,  -331,  -331,  -331,
+    -331,  -331,  -331,  -331,    -3,  -331,  -331,    -3,  -331,  -331,
+     149,  -331,  -331,  -331,  -331,  -331,  -331,   264,  -331,  -331,
+     965,   929,  -331,   965,  -331,  -331,  -331,  -331,  -331,  -331,
+     -75,  -331,   -72,  -331,   -60,  -331,  -331,   307,    60,   270,
+     156,  -331,  -331,   965,  -331,  -331,  -331,  -331,  -331,  -331,
+     965,   965,   929,   -44,   -44,    29,   -15,   199,   -10,  -331,
+     307,  -331,    83,   756,   849,  -331,   140,   965,   889,  -331,
+    -331,  -331,  -331,    86,    12,  -331,  -331,  -331,  -331,  -331,
+      90,   929,   686,   756,   756,   756,   756,   615,   756,   756,
+    -331,  -331,  -331,  -331,  -331,  -331,  -331,  -331,  -331,  -331,
+    -331,   791,   826,   756,   756,     9,  -331,  1084,  -331,  -331,
+     708,    54,    57,  -331,   110,    56,   152,   310,  -331,  -331,
+    -331,   279,   756,    29,  -331,    29,    63,   307,   165,  -331,
+    1084,  -331,  -331,  -331,  -331,    30,  1084,    44,  -331,  -331,
+     615,  -331,   615,  -331,  -331,  -331,  -331,   756,   756,   756,
+     756,   756,   756,   756,   756,   756,   756,   756,   756,   756,
+     756,   756,   756,   756,   756,   756,   756,   756,   756,   756,
+     756,   756,   756,   756,   756,   756,   756,   157,   756,   756,
+     157,  -331,  -331,  -331,  -331,   115,  -331,   849,  -331,   756,
+     128,  -331,  -331,  -331,   182,  -331,   279,   756,  -331,   164,
+     200,  -331,   208,  1084,  -331,    13,  -331,  -331,  -331,   262,
+     157,   756,   225,   228,   165,    73,   756,  -331,  -331,    -7,
+     150,    44,    44,  1084,  1084,  1084,  1084,  1084,  1084,  1084,
+    1084,  1084,  1084,  1084,    28,   304,  1100,  1115,  1129,  1142,
+    1153,  1153,   433,   433,   433,   433,   333,   333,   265,   265,
+    -331,  -331,  -331,  -331,     8,  1084,   153,   236,  -331,  -331,
+    -331,   147,   158,  -331,   161,   756,   849,   247,  -331,  -331,
+     279,   756,  -331,   341,  -331,   307,  -331,   175,  -331,  -331,
+     254,   228,  -331,  -331,   135,   721,   188,   190,   756,  -331,
+    -331,   756,  -331,  -331,  -331,   191,   211,  -331,  -331,  -331,
+     298,   301,   338,   756,   343,   339,   439,   157,   319,   321,
+     756,   322,   323,   324,   332,  -331,  -331,   509,  -331,  -331,
+    -331,    63,   306,   372,   373,   277,  -331,  -331,  -331,   165,
+    -331,  -331,  -331,   425,  -331,  -331,  -331,  -331,  -331,  -331,
+    1053,  -331,  -331,   293,   375,   756,   756,   400,   756,   756,
+     756,   756,  -331,  -331,  -331,   396,  -331,  -331,   430,   285,
+     377,  -331,   431,  -331,    55,   381,  -331,   382,    62,    64,
+     383,   615,   473,  -331,   307,  -331,   756,   439,   479,   490,
+     439,   439,   493,   497,  -331,   307,   686,  -331,    66,   440,
+    -331,  -331,  -331,  -331,  -331,   756,   499,  -331,   498,   439,
+     504,  -331,  -331,   756,   415,   439,  -331
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -366,  -366,  -366,  -366,  -366,   400,  -366,   -26,  -366,  -366,
-    -365,  -366,  -366,   189,  -366,  -366,  -366,   266,   209,  -366,
-    -122,  -187,  -366,  -366,   -82,   254,  -366,   133,   216,   299,
-     168,  -366,  -366,   171,  -304,  -366,   173,  -366,  -366,  -227,
-    -181,  -183,   -83,   -45,   -38,   137,  -366,  -366,  -366,  -308,
-     203,     2,  -366,  -366,    -1,     0,   -88,   472,  -366,  -366,
-    -366,  -366,  -366,   -10,   -51,   208,  -366,   474,    22,   256,
-     265,   -24,   -52,  -127,   -12
+    -331,  -331,  -331,  -331,  -331,   445,  -331,   -26,  -331,  -331,
+    -330,  -331,  -331,   233,  -331,  -331,  -331,   313,   230,  -331,
+    -132,  -187,  -331,  -331,   -82,   292,  -331,   181,   245,   326,
+     193,  -331,  -331,   198,  -227,  -331,   203,  -331,  -331,  -309,
+    -181,  -183,   -83,   -45,   -38,   243,  -331,  -331,  -331,  -175,
+     226,    10,  -331,  -331,    -1,     0,   -88,   495,  -331,  -331,
+    -331,  -331,  -331,   -14,   -51,   -28,  -331,   501,   -85,   218,
+     231,   -24,   -52,  -127,   -12
 };
 
 /* 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 -204
+#define YYTABLE_NINF -205
 static const yytype_int16 yytable[] =
 {
       28,    49,    40,   137,   212,    42,    57,    76,    44,    57,
-     139,   133,   352,   274,   145,   226,   393,   133,   272,    41,
-     226,    68,   128,    61,   278,   230,   401,   228,   117,    57,
-    -195,   199,   229,   298,  -199,   226,    57,    57,   287,    36,
-      37,    86,   274,    87,    90,    22,    23,   140,   374,    24,
-      77,   377,    87,    57,    46,   141,   142,   143,   144,    47,
-     148,   149,    80,    36,    37,    81,    82,   145,   226,   145,
-     226,   226,   226,    69,    70,   154,   155,  -203,   130,   212,
-     395,    38,   397,   398,   302,   244,   273,   213,    73,    74,
-      28,    38,   355,   140,   305,    36,    37,   147,   309,    83,
-     407,   201,   134,    85,   299,   264,   411,   302,   282,   296,
-     297,   218,   233,   234,   235,   236,   237,   238,   239,   240,
+     139,   357,   226,   274,   145,   230,   133,   133,   272,    61,
+    -196,    68,   128,  -200,   278,    75,   228,    41,   117,    57,
+     199,   229,   226,    75,   226,  -204,    57,    57,   287,    36,
+      37,    86,   274,    87,    90,   298,    77,   140,   214,    75,
+     215,    38,    87,    57,   397,   141,   142,   143,   144,   226,
+     148,   149,    80,    69,    70,   406,   226,   145,   226,   145,
+     226,    83,   394,    81,    82,   154,   155,   228,   130,   212,
+      85,   199,   229,    88,   302,   244,   273,   213,    92,   353,
+      28,   132,    38,   140,   305,   -10,   410,   147,   309,   296,
+     297,   201,   299,   156,   414,   264,   193,   302,   134,   282,
+     194,   218,   233,   234,   235,   236,   237,   238,   239,   240,
      241,   242,   243,   227,   245,   246,   247,   248,   249,   250,
      251,   252,   253,   254,   255,   256,   257,   258,   259,   260,
-     261,   262,   290,   293,   265,   128,    88,   271,   275,   276,
-     231,   390,   232,   212,   117,   214,   384,   215,   386,   387,
-     403,   198,   117,   228,    45,   199,   200,   199,   229,    92,
-      36,    37,   132,   405,    68,   263,   117,   294,   268,   140,
-     198,   409,    36,    37,   199,   200,   -10,    46,   156,    36,
-      37,    93,    47,   193,    46,   334,    36,    37,   194,    47,
-      94,    95,    96,    36,    37,   220,   221,    97,   286,    98,
-      99,   100,   195,   101,   102,   103,   104,   105,   106,   107,
-     108,   109,   110,   198,   128,   284,   285,   199,   200,   197,
-     117,   196,    36,    37,    43,   269,   117,   380,   381,   273,
-      22,    23,   111,   216,    24,    86,   279,    87,   151,   153,
-     228,   280,   281,   342,   199,   229,   265,   339,   112,   218,
-     289,    75,   365,   138,   288,   113,   114,   292,   349,    75,
-      87,   372,   295,   301,   375,   376,    22,    23,   300,   304,
-      24,   303,    28,   307,   336,    75,    55,    60,   337,    55,
-     391,   344,    46,   140,   340,    56,   341,    47,    56,   345,
-     394,    36,    37,    22,    23,   353,   207,    24,   366,    55,
-     402,   265,   346,   347,   265,   348,    55,    55,    56,    -9,
-      -9,   -10,    46,   350,   351,    56,    56,    47,   184,   185,
-     186,    36,    37,    55,   182,   183,   184,   185,   186,   310,
-     354,  -100,    56,   356,   357,   364,   358,   140,   180,   181,
-     182,   183,   184,   185,   186,   366,   359,   363,   226,   370,
-      93,   371,   373,   378,   383,   366,   -22,   382,   385,    94,
-      95,    96,   392,   388,   396,   399,    97,    28,    98,    99,
-     311,     3,   101,   102,   103,   104,   105,   106,   107,   108,
-     109,   110,     4,   312,   313,     5,   314,   315,   316,     6,
-     400,     7,     8,   -89,   317,   318,     9,    10,    11,   319,
-      12,   111,   320,    13,    14,   321,    15,    16,    17,    18,
-     322,    19,    20,    21,    22,    23,   323,   112,    24,    25,
-     404,   381,   -85,   324,   113,   114,   310,   168,  -100,   169,
-     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
-     180,   181,   182,   183,   184,   185,   186,    93,   187,   188,
-     189,   190,   191,   192,   406,   408,    94,    95,    96,   410,
-      89,   368,   277,    97,   335,    98,    99,   311,   291,   101,
-     102,   103,   104,   105,   106,   107,   108,   109,   110,   308,
-     312,   313,   306,   314,   315,   316,   270,   360,   362,   361,
-     -89,   317,   318,    58,   343,    59,   319,  -100,   111,   320,
-       0,     0,   321,     0,     0,     0,     0,   322,     0,     0,
-       0,     0,     0,   323,   112,     0,    93,     0,     0,   -85,
-       0,   113,   114,     0,     0,    94,    95,    96,     0,     0,
-       0,     2,    97,     0,    98,    99,   311,     0,   101,   102,
-     103,   104,   105,   106,   107,   108,   109,   110,     0,   312,
-     313,     0,   314,   315,   316,     0,     0,     0,     0,   -89,
-     317,   318,     0,     0,     0,   319,     0,   111,   320,     0,
-       0,   321,     0,     0,     3,     0,   322,     0,     0,     0,
-       0,     0,   323,   112,     0,     4,     0,     0,     5,     0,
-     113,   114,     6,     0,     7,     8,     0,     0,     0,     9,
-      10,    11,     0,    12,     0,     0,    13,    14,     0,    15,
-      16,    17,    18,     0,    19,    20,    21,    22,    23,    93,
-       0,    24,    25,     0,     0,     0,     0,     0,    94,    95,
-      96,     0,     0,     0,     0,    97,     0,    98,    99,   100,
-       3,   101,   102,   103,   104,   105,   106,   107,   108,   109,
-     110,     4,     0,     0,     5,     0,     0,     0,     6,     0,
-       7,     8,     0,     0,     0,     9,    10,    11,     0,    12,
-     111,     0,    13,    14,     0,    15,    16,    17,    18,     0,
-      19,    20,    21,    22,    23,     0,   112,    24,    25,    93,
-       0,     0,     0,   113,   114,     0,     0,     0,    94,    95,
-      96,     0,     0,     0,     0,    97,     0,    98,    99,   100,
-       0,   101,   102,   103,   104,   105,   106,   107,   108,   109,
-     110,     0,     0,    93,     0,     0,     0,     0,     0,     0,
+     261,   262,   290,   293,   265,   128,   195,   271,   387,   196,
+     231,   269,   232,   212,   117,   390,   197,   391,   216,   408,
+     399,   198,   117,   402,   403,   199,   200,   279,   228,   292,
+      36,    37,   199,   229,    68,   263,   117,   294,   268,   140,
+     198,   375,   412,   377,   199,   200,   380,    93,   416,    36,
+      37,    36,    37,    73,    74,   335,    94,    95,    96,    36,
+      37,   220,   221,    97,   280,    98,    99,   100,   286,   101,
+     102,   103,   104,   105,   106,   107,   108,   109,   110,   275,
+     276,   273,    22,    23,   128,   281,    24,    22,    23,   288,
+     117,    24,    46,   289,    22,    23,   117,    47,    24,   111,
+     301,    36,    37,   295,    43,    86,   300,    87,    55,    60,
+     307,    55,   303,   343,   304,   112,   265,   340,   338,   218,
+     138,    56,   113,   114,    56,   284,   285,    45,   350,   337,
+      87,    55,   374,    -9,    -9,   -10,   378,   379,    55,    55,
+     367,   341,    28,   342,    56,   345,    22,    23,   383,   384,
+      24,    56,    56,   395,   140,    55,   207,    46,   184,   185,
+     186,   347,    47,   398,   346,   354,    36,    37,    56,   368,
+      46,   265,    46,   265,   407,    47,   265,    47,   348,    36,
+      37,    36,    37,   170,   171,   172,   173,   174,   175,   176,
+     177,   178,   179,   180,   181,   182,   183,   184,   185,   186,
+      46,   349,   310,   198,  -101,    47,   351,   199,   200,    36,
+      37,   140,    36,    37,   151,   153,   352,   355,   368,   356,
+     358,   359,   360,    93,   182,   183,   184,   185,   186,   368,
+     361,   365,    94,    95,    96,   366,   372,   226,   373,    97,
+      28,    98,    99,   311,     3,   101,   102,   103,   104,   105,
+     106,   107,   108,   109,   110,     4,   312,   313,     5,   314,
+     315,   316,     6,   376,     7,     8,   -89,   317,   318,     9,
+      10,   319,    11,   320,    12,   111,   321,    13,    14,   322,
+      15,    16,    17,    18,   323,    19,    20,    21,    22,    23,
+     324,   112,    24,    25,   381,   -22,   -85,   325,   113,   114,
+     310,   168,  -101,   169,   170,   171,   172,   173,   174,   175,
+     176,   177,   178,   179,   180,   181,   182,   183,   184,   185,
+     186,    93,   180,   181,   182,   183,   184,   185,   186,   386,
+      94,    95,    96,   385,   388,   389,   392,    97,   396,    98,
+      99,   311,   400,   101,   102,   103,   104,   105,   106,   107,
+     108,   109,   110,   401,   312,   313,   404,   314,   315,   316,
+     405,   411,   409,   384,   -89,   317,   318,   413,   415,   319,
+     308,   320,  -101,   111,   321,    89,   291,   322,   336,   277,
+     370,   306,   323,   270,   364,   362,    58,   344,   324,   112,
+     363,    93,    59,     0,   -85,     0,   113,   114,     0,     0,
+      94,    95,    96,     0,     0,     0,     0,    97,     2,    98,
+      99,   311,     0,   101,   102,   103,   104,   105,   106,   107,
+     108,   109,   110,     0,   312,   313,     0,   314,   315,   316,
+       0,     0,     0,     0,   -89,   317,   318,     0,     0,   319,
+       0,   320,     0,   111,   321,     0,     0,   322,     0,     0,
+       0,     3,   323,     0,     0,     0,     0,     0,   324,   112,
+       0,     0,     4,     0,     0,     5,   113,   114,     0,     6,
+       0,     7,     8,     0,     0,     0,     9,    10,     0,    11,
+       0,    12,     0,     0,    13,    14,     0,    15,    16,    17,
+      18,     0,    19,    20,    21,    22,    23,    93,     0,    24,
+      25,     0,     0,     0,     0,     0,    94,    95,    96,     0,
+       0,     0,     0,    97,     0,    98,    99,   100,     3,   101,
+     102,   103,   104,   105,   106,   107,   108,   109,   110,     4,
+       0,     0,     5,     0,     0,     0,     6,     0,     7,     8,
+       0,     0,     0,     9,    10,     0,    11,     0,    12,   111,
+       0,    13,    14,     0,    15,    16,    17,    18,     0,    19,
+      20,    21,    22,    23,     0,   112,    24,    25,    93,     0,
+       0,     0,   113,   114,     0,     0,     0,    94,    95,    96,
+       0,     0,     0,     0,    97,     0,    98,    99,   100,     0,
+     101,   102,   103,   104,   105,   106,   107,   108,   109,   110,
+       0,     0,     0,    93,   187,   188,   189,   190,   191,   192,
        0,     0,    94,    95,    96,     0,     0,     0,     0,    97,
      111,    98,    99,   100,     0,   101,   102,   103,   104,   105,
-     106,   107,   108,   109,   110,     0,   112,    93,     0,     0,
-       0,   138,     0,   113,   114,     0,    94,    95,    96,     0,
-       0,     0,     0,    97,   111,    98,    99,   100,     0,   101,
-     102,   103,   104,   105,   106,   107,   108,   109,   110,     0,
-     112,    93,     0,     0,     0,   338,     0,   113,   114,     0,
-      94,    95,    96,     0,     0,     0,     0,   150,   111,    98,
-      99,   100,     0,   101,   102,   103,   104,   105,   106,   107,
-     108,   109,   110,     0,   112,    93,     0,     0,     0,     0,
-       0,   113,   114,     0,    94,    95,    96,     0,     0,     0,
-       0,   152,   111,    98,    99,   100,     0,   101,   102,   103,
-     104,   105,   106,   107,   108,   109,   110,     0,   112,     0,
-       0,     0,   124,     0,     0,   113,   114,     0,   100,     3,
-       0,     0,     0,     0,     0,     0,   111,     0,     0,     0,
-       4,     0,     0,     5,     0,     0,     0,     6,     0,     7,
-       8,     0,   112,     0,     9,    10,    11,     0,    12,   113,
-     114,    13,    14,     0,    15,    16,    17,    18,     3,    19,
-      20,    21,    22,    23,     0,     0,    24,    25,     0,     4,
-       0,     0,     5,     0,     0,     0,     6,     0,     7,     8,
-       0,     0,     0,     9,    10,    11,     0,    12,     0,     0,
-      13,    14,     0,    15,    16,    17,    18,     3,    19,    20,
-      21,    22,    23,     0,     0,    24,    25,     0,     4,     0,
-     129,     5,     0,     0,     0,     6,     0,     7,     8,     0,
-       0,     0,     9,    10,    11,     0,    12,     0,     0,    13,
-      14,     0,    15,    16,    17,    18,     0,    19,    20,    21,
-      22,    23,     0,     4,    24,    25,     5,     0,     0,     0,
-       6,     0,     7,     8,     0,     0,     0,     9,    10,    11,
-       0,    12,     0,     0,    13,     0,     0,    15,    16,     0,
-      18,     0,    19,     0,    21,    22,    23,     0,     0,    24,
-      25,   157,   158,   159,   160,   161,   162,   163,   164,   165,
-     166,   167,   168,   369,   169,   170,   171,   172,   173,   174,
-     175,   176,   177,   178,   179,   180,   181,   182,   183,   184,
-     185,   186,   157,   158,   159,   160,   161,   162,   163,   164,
-     165,   166,   167,   168,     0,   169,   170,   171,   172,   173,
-     174,   175,   176,   177,   178,   179,   180,   181,   182,   183,
-     184,   185,   186,   170,   171,   172,   173,   174,   175,   176,
+     106,   107,   108,   109,   110,     0,   112,     0,    93,     0,
+       0,   138,     0,   113,   114,     0,     0,    94,    95,    96,
+       0,     0,     0,     0,    97,   111,    98,    99,   100,     0,
+     101,   102,   103,   104,   105,   106,   107,   108,   109,   110,
+       0,   112,     0,    93,     0,     0,   339,     0,   113,   114,
+       0,     0,    94,    95,    96,     0,     0,     0,     0,   150,
+     111,    98,    99,   100,     0,   101,   102,   103,   104,   105,
+     106,   107,   108,   109,   110,     0,   112,     0,    93,     0,
+       0,     0,     0,   113,   114,     0,     0,    94,    95,    96,
+       0,     0,     0,     0,   152,   111,    98,    99,   100,     0,
+     101,   102,   103,   104,   105,   106,   107,   108,   109,   110,
+       0,   112,     0,     0,     0,   124,     0,     0,   113,   114,
+       0,   100,     3,     0,     0,     0,     0,     0,     0,     0,
+     111,     0,     0,     4,     0,     0,     5,     0,     0,     0,
+       6,     0,     7,     8,     0,     0,   112,     9,    10,     0,
+      11,     0,    12,   113,   114,    13,    14,     0,    15,    16,
+      17,    18,     3,    19,    20,    21,    22,    23,     0,     0,
+      24,    25,     0,     4,     0,     0,     5,     0,     0,     0,
+       6,     0,     7,     8,     0,     0,     0,     9,    10,     0,
+      11,     0,    12,     0,     0,    13,    14,     0,    15,    16,
+      17,    18,     3,    19,    20,    21,    22,    23,     0,     0,
+      24,    25,     0,     4,     0,   129,     5,     0,     0,     0,
+       6,     0,     7,     8,     0,     0,     0,     9,    10,     0,
+      11,     0,    12,     0,     0,    13,    14,     0,    15,    16,
+      17,    18,     0,    19,    20,    21,    22,    23,     0,     4,
+      24,    25,     5,     0,     0,     0,     6,     0,     7,     8,
+       0,     0,     0,     9,    10,     0,    11,     0,    12,     0,
+       0,    13,     0,     0,    15,    16,     0,    18,     0,    19,
+       0,    21,    22,    23,     0,     0,    24,    25,   157,   158,
+     159,   160,   161,   162,   163,   164,   165,   166,   167,   168,
+     371,   169,   170,   171,   172,   173,   174,   175,   176,   177,
+     178,   179,   180,   181,   182,   183,   184,   185,   186,   157,
+     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
+     168,     0,   169,   170,   171,   172,   173,   174,   175,   176,
      177,   178,   179,   180,   181,   182,   183,   184,   185,   186,
      171,   172,   173,   174,   175,   176,   177,   178,   179,   180,
      181,   182,   183,   184,   185,   186,   172,   173,   174,   175,
@@ -1062,116 +1065,116 @@ static const yytype_int16 yytable[] =
 static const yytype_int16 yycheck[] =
 {
        1,    27,    14,    91,   131,    17,    30,    58,    20,    33,
-      92,     4,   316,   200,    97,     4,   381,     4,   199,    17,
-       4,    47,    74,    33,   207,   147,   391,    33,    73,    53,
-      94,    37,    38,    17,    94,     4,    60,    61,   221,    42,
-      43,    67,   229,    67,    70,    86,    87,    92,   356,    90,
-      60,   359,    76,    77,    33,    93,    94,    95,    96,    38,
-      98,    99,    62,    42,    43,    63,    64,   150,     4,   152,
-       4,     4,     4,     3,     4,   113,   114,    94,    78,   206,
-     384,    94,   386,   387,   271,   168,    92,   132,    37,    38,
-      91,    94,   319,   138,   275,    42,    43,    97,   281,    42,
-     404,   127,    95,    94,    93,   188,   410,   294,    95,   231,
-     232,   137,   157,   158,   159,   160,   161,   162,   163,   164,
-     165,   166,   167,    92,   169,   170,   171,   172,   173,   174,
+      92,   320,     4,   200,    97,   147,     4,     4,   199,    33,
+      95,    47,    74,    95,   207,    53,    33,    17,    73,    53,
+      37,    38,     4,    61,     4,    95,    60,    61,   221,    42,
+      43,    67,   229,    67,    70,    17,    60,    92,   133,    77,
+     135,    95,    76,    77,   384,    93,    94,    95,    96,     4,
+      98,    99,    62,     3,     4,   395,     4,   150,     4,   152,
+       4,    42,   381,    63,    64,   113,   114,    33,    78,   206,
+      95,    37,    38,    93,   271,   168,    93,   132,     5,   316,
+      91,     5,    95,   138,   275,     5,   405,    97,   281,   231,
+     232,   127,    94,    94,   413,   188,    52,   294,    96,    96,
+      53,   137,   157,   158,   159,   160,   161,   162,   163,   164,
+     165,   166,   167,    93,   169,   170,   171,   172,   173,   174,
      175,   176,   177,   178,   179,   180,   181,   182,   183,   184,
-     185,   186,   224,   226,   189,   197,    92,   198,    37,    38,
-     150,   378,   152,   280,   199,   133,    92,   135,    92,    92,
-      92,    33,   207,    33,     3,    37,    38,    37,    38,     5,
-      42,    43,     5,   400,   200,   187,   221,   228,   190,   224,
-      33,   408,    42,    43,    37,    38,     5,    33,    93,    42,
-      43,    22,    38,    52,    33,   283,    42,    43,    53,    38,
-      31,    32,    33,    42,    43,    36,    37,    38,   220,    40,
-      41,    42,    36,    44,    45,    46,    47,    48,    49,    50,
-      51,    52,    53,    33,   276,     3,     4,    37,    38,     4,
-     275,    92,    42,    43,    94,    36,   281,     3,     4,    92,
-      86,    87,    73,    94,    90,   271,     3,   271,   111,   112,
-      33,     4,    17,   298,    37,    38,   301,   295,    89,   285,
-       5,    53,     3,    94,     4,    96,    97,    95,   313,    61,
-     294,   354,    92,     4,   357,   358,    86,    87,    92,    92,
-      90,    93,   283,     3,    93,    77,    30,    31,     4,    33,
-     378,    93,    33,   338,    92,    30,    92,    38,    33,    92,
-     383,    42,    43,    86,    87,   317,    17,    90,   334,    53,
-     392,   356,     3,    17,   359,     3,    60,    61,    53,     3,
-       4,     5,    33,     3,    17,    60,    61,    38,    33,    34,
-      35,    42,    43,    77,    31,    32,    33,    34,    35,     1,
-      38,     3,    77,    38,    38,     3,    38,   392,    29,    30,
-      31,    32,    33,    34,    35,   381,    38,    65,     4,    82,
-      22,     3,     3,    38,    38,   391,     5,    95,    92,    31,
-      32,    33,     5,    92,     3,     3,    38,   378,    40,    41,
-      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
-      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
-       3,    63,    64,    65,    66,    67,    68,    69,    70,    71,
-      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
-      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
-      62,     4,    94,    95,    96,    97,     1,    16,     3,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    33,    34,    35,    22,    36,    37,
-      38,    39,    40,    41,     3,     3,    31,    32,    33,    92,
-      70,   338,   206,    38,   285,    40,    41,    42,   224,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,   280,
-      55,    56,   276,    58,    59,    60,   197,   326,   330,   326,
-      65,    66,    67,    31,   301,    31,    71,     3,    73,    74,
-      -1,    -1,    77,    -1,    -1,    -1,    -1,    82,    -1,    -1,
-      -1,    -1,    -1,    88,    89,    -1,    22,    -1,    -1,    94,
-      -1,    96,    97,    -1,    -1,    31,    32,    33,    -1,    -1,
-      -1,     0,    38,    -1,    40,    41,    42,    -1,    44,    45,
-      46,    47,    48,    49,    50,    51,    52,    53,    -1,    55,
-      56,    -1,    58,    59,    60,    -1,    -1,    -1,    -1,    65,
-      66,    67,    -1,    -1,    -1,    71,    -1,    73,    74,    -1,
-      -1,    77,    -1,    -1,    43,    -1,    82,    -1,    -1,    -1,
-      -1,    -1,    88,    89,    -1,    54,    -1,    -1,    57,    -1,
-      96,    97,    61,    -1,    63,    64,    -1,    -1,    -1,    68,
-      69,    70,    -1,    72,    -1,    -1,    75,    76,    -1,    78,
-      79,    80,    81,    -1,    83,    84,    85,    86,    87,    22,
-      -1,    90,    91,    -1,    -1,    -1,    -1,    -1,    31,    32,
-      33,    -1,    -1,    -1,    -1,    38,    -1,    40,    41,    42,
-      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
-      53,    54,    -1,    -1,    57,    -1,    -1,    -1,    61,    -1,
-      63,    64,    -1,    -1,    -1,    68,    69,    70,    -1,    72,
-      73,    -1,    75,    76,    -1,    78,    79,    80,    81,    -1,
-      83,    84,    85,    86,    87,    -1,    89,    90,    91,    22,
-      -1,    -1,    -1,    96,    97,    -1,    -1,    -1,    31,    32,
-      33,    -1,    -1,    -1,    -1,    38,    -1,    40,    41,    42,
-      -1,    44,    45,    46,    47,    48,    49,    50,    51,    52,
-      53,    -1,    -1,    22,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    31,    32,    33,    -1,    -1,    -1,    -1,    38,
-      73,    40,    41,    42,    -1,    44,    45,    46,    47,    48,
-      49,    50,    51,    52,    53,    -1,    89,    22,    -1,    -1,
-      -1,    94,    -1,    96,    97,    -1,    31,    32,    33,    -1,
-      -1,    -1,    -1,    38,    73,    40,    41,    42,    -1,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    -1,
-      89,    22,    -1,    -1,    -1,    94,    -1,    96,    97,    -1,
-      31,    32,    33,    -1,    -1,    -1,    -1,    38,    73,    40,
+     185,   186,   224,   226,   189,   197,    36,   198,    93,    93,
+     150,    36,   152,   280,   199,    93,     4,    93,    95,    93,
+     387,    33,   207,   390,   391,    37,    38,     3,    33,    96,
+      42,    43,    37,    38,   200,   187,   221,   228,   190,   224,
+      33,   356,   409,   358,    37,    38,   361,    22,   415,    42,
+      43,    42,    43,    37,    38,   283,    31,    32,    33,    42,
+      43,    36,    37,    38,     4,    40,    41,    42,   220,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    37,
+      38,    93,    87,    88,   276,    17,    91,    87,    88,     4,
+     275,    91,    33,     5,    87,    88,   281,    38,    91,    74,
+       4,    42,    43,    93,    95,   271,    93,   271,    30,    31,
+       3,    33,    94,   298,    93,    90,   301,   295,     4,   285,
+      95,    30,    97,    98,    33,     3,     4,     3,   313,    94,
+     294,    53,   355,     3,     4,     5,   359,   360,    60,    61,
+       3,    93,   283,    93,    53,    94,    87,    88,     3,     4,
+      91,    60,    61,   381,   339,    77,    17,    33,    33,    34,
+      35,     3,    38,   386,    93,   317,    42,    43,    77,   335,
+      33,   356,    33,   358,   396,    38,   361,    38,    17,    42,
+      43,    42,    43,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+      33,     3,     1,    33,     3,    38,     3,    37,    38,    42,
+      43,   396,    42,    43,   111,   112,    17,    38,   384,    38,
+      38,    38,    38,    22,    31,    32,    33,    34,    35,   395,
+      38,    65,    31,    32,    33,     3,    83,     4,     3,    38,
+     381,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    60,    61,     3,    63,    64,    65,    66,    67,    68,
+      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
+      79,    80,    81,    82,    83,    84,    85,    86,    87,    88,
+      89,    90,    91,    92,    38,     5,    95,    96,    97,    98,
+       1,    16,     3,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    22,    29,    30,    31,    32,    33,    34,    35,    38,
+      31,    32,    33,    96,    93,    93,    93,    38,     5,    40,
+      41,    42,     3,    44,    45,    46,    47,    48,    49,    50,
+      51,    52,    53,     3,    55,    56,     3,    58,    59,    60,
+       3,     3,    62,     4,    65,    66,    67,     3,    93,    70,
+     280,    72,     3,    74,    75,    70,   224,    78,   285,   206,
+     339,   276,    83,   197,   331,   327,    31,   301,    89,    90,
+     327,    22,    31,    -1,    95,    -1,    97,    98,    -1,    -1,
+      31,    32,    33,    -1,    -1,    -1,    -1,    38,     0,    40,
       41,    42,    -1,    44,    45,    46,    47,    48,    49,    50,
-      51,    52,    53,    -1,    89,    22,    -1,    -1,    -1,    -1,
-      -1,    96,    97,    -1,    31,    32,    33,    -1,    -1,    -1,
-      -1,    38,    73,    40,    41,    42,    -1,    44,    45,    46,
-      47,    48,    49,    50,    51,    52,    53,    -1,    89,    -1,
-      -1,    -1,    36,    -1,    -1,    96,    97,    -1,    42,    43,
-      -1,    -1,    -1,    -1,    -1,    -1,    73,    -1,    -1,    -1,
-      54,    -1,    -1,    57,    -1,    -1,    -1,    61,    -1,    63,
-      64,    -1,    89,    -1,    68,    69,    70,    -1,    72,    96,
-      97,    75,    76,    -1,    78,    79,    80,    81,    43,    83,
-      84,    85,    86,    87,    -1,    -1,    90,    91,    -1,    54,
+      51,    52,    53,    -1,    55,    56,    -1,    58,    59,    60,
+      -1,    -1,    -1,    -1,    65,    66,    67,    -1,    -1,    70,
+      -1,    72,    -1,    74,    75,    -1,    -1,    78,    -1,    -1,
+      -1,    43,    83,    -1,    -1,    -1,    -1,    -1,    89,    90,
+      -1,    -1,    54,    -1,    -1,    57,    97,    98,    -1,    61,
+      -1,    63,    64,    -1,    -1,    -1,    68,    69,    -1,    71,
+      -1,    73,    -1,    -1,    76,    77,    -1,    79,    80,    81,
+      82,    -1,    84,    85,    86,    87,    88,    22,    -1,    91,
+      92,    -1,    -1,    -1,    -1,    -1,    31,    32,    33,    -1,
+      -1,    -1,    -1,    38,    -1,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
       -1,    -1,    57,    -1,    -1,    -1,    61,    -1,    63,    64,
-      -1,    -1,    -1,    68,    69,    70,    -1,    72,    -1,    -1,
-      75,    76,    -1,    78,    79,    80,    81,    43,    83,    84,
-      85,    86,    87,    -1,    -1,    90,    91,    -1,    54,    -1,
-      95,    57,    -1,    -1,    -1,    61,    -1,    63,    64,    -1,
-      -1,    -1,    68,    69,    70,    -1,    72,    -1,    -1,    75,
-      76,    -1,    78,    79,    80,    81,    -1,    83,    84,    85,
-      86,    87,    -1,    54,    90,    91,    57,    -1,    -1,    -1,
-      61,    -1,    63,    64,    -1,    -1,    -1,    68,    69,    70,
-      -1,    72,    -1,    -1,    75,    -1,    -1,    78,    79,    -1,
-      81,    -1,    83,    -1,    85,    86,    87,    -1,    -1,    90,
-      91,     5,     6,     7,     8,     9,    10,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
-      34,    35,     5,     6,     7,     8,     9,    10,    11,    12,
-      13,    14,    15,    16,    -1,    18,    19,    20,    21,    22,
-      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
-      33,    34,    35,    19,    20,    21,    22,    23,    24,    25,
+      -1,    -1,    -1,    68,    69,    -1,    71,    -1,    73,    74,
+      -1,    76,    77,    -1,    79,    80,    81,    82,    -1,    84,
+      85,    86,    87,    88,    -1,    90,    91,    92,    22,    -1,
+      -1,    -1,    97,    98,    -1,    -1,    -1,    31,    32,    33,
+      -1,    -1,    -1,    -1,    38,    -1,    40,    41,    42,    -1,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      -1,    -1,    -1,    22,    36,    37,    38,    39,    40,    41,
+      -1,    -1,    31,    32,    33,    -1,    -1,    -1,    -1,    38,
+      74,    40,    41,    42,    -1,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    -1,    90,    -1,    22,    -1,
+      -1,    95,    -1,    97,    98,    -1,    -1,    31,    32,    33,
+      -1,    -1,    -1,    -1,    38,    74,    40,    41,    42,    -1,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      -1,    90,    -1,    22,    -1,    -1,    95,    -1,    97,    98,
+      -1,    -1,    31,    32,    33,    -1,    -1,    -1,    -1,    38,
+      74,    40,    41,    42,    -1,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    -1,    90,    -1,    22,    -1,
+      -1,    -1,    -1,    97,    98,    -1,    -1,    31,    32,    33,
+      -1,    -1,    -1,    -1,    38,    74,    40,    41,    42,    -1,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      -1,    90,    -1,    -1,    -1,    36,    -1,    -1,    97,    98,
+      -1,    42,    43,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      74,    -1,    -1,    54,    -1,    -1,    57,    -1,    -1,    -1,
+      61,    -1,    63,    64,    -1,    -1,    90,    68,    69,    -1,
+      71,    -1,    73,    97,    98,    76,    77,    -1,    79,    80,
+      81,    82,    43,    84,    85,    86,    87,    88,    -1,    -1,
+      91,    92,    -1,    54,    -1,    -1,    57,    -1,    -1,    -1,
+      61,    -1,    63,    64,    -1,    -1,    -1,    68,    69,    -1,
+      71,    -1,    73,    -1,    -1,    76,    77,    -1,    79,    80,
+      81,    82,    43,    84,    85,    86,    87,    88,    -1,    -1,
+      91,    92,    -1,    54,    -1,    96,    57,    -1,    -1,    -1,
+      61,    -1,    63,    64,    -1,    -1,    -1,    68,    69,    -1,
+      71,    -1,    73,    -1,    -1,    76,    77,    -1,    79,    80,
+      81,    82,    -1,    84,    85,    86,    87,    88,    -1,    54,
+      91,    92,    57,    -1,    -1,    -1,    61,    -1,    63,    64,
+      -1,    -1,    -1,    68,    69,    -1,    71,    -1,    73,    -1,
+      -1,    76,    -1,    -1,    79,    80,    -1,    82,    -1,    84,
+      -1,    86,    87,    88,    -1,    -1,    91,    92,     5,     6,
+       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    33,    34,    35,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    -1,    18,    19,    20,    21,    22,    23,    24,    25,
       26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
       20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
       30,    31,    32,    33,    34,    35,    21,    22,    23,    24,
@@ -1186,48 +1189,48 @@ static const yytype_int16 yycheck[] =
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    99,     0,    43,    54,    57,    61,    63,    64,    68,
-      69,    70,    72,    75,    76,    78,    79,    80,    81,    83,
-      84,    85,    86,    87,    90,    91,   100,   151,   152,   154,
-     155,   164,   165,   167,   168,   169,    42,    43,    94,   149,
-     172,   149,   172,    94,   172,     3,    33,    38,   103,   105,
-     106,   171,   172,   161,   163,   167,   168,   169,   155,   165,
-     167,   161,   150,   156,   157,   160,   158,   162,   105,     3,
-       4,   101,   104,    37,    38,   163,   162,   161,   112,   152,
-     153,   149,   149,    42,   166,    94,   105,   169,    92,   103,
-     105,   110,     5,    22,    31,    32,    33,    38,    40,    41,
+       0,   100,     0,    43,    54,    57,    61,    63,    64,    68,
+      69,    71,    73,    76,    77,    79,    80,    81,    82,    84,
+      85,    86,    87,    88,    91,    92,   101,   152,   153,   155,
+     156,   165,   166,   168,   169,   170,    42,    43,    95,   150,
+     173,   150,   173,    95,   173,     3,    33,    38,   104,   106,
+     107,   172,   173,   162,   164,   168,   169,   170,   156,   166,
+     168,   162,   151,   157,   158,   161,   159,   163,   106,     3,
+       4,   102,   105,    37,    38,   164,   163,   162,   113,   153,
+     154,   150,   150,    42,   167,    95,   106,   170,    93,   104,
+     106,   111,     5,    22,    31,    32,    33,    38,    40,    41,
       42,    44,    45,    46,    47,    48,    49,    50,    51,    52,
-      53,    73,    89,    96,    97,   138,   139,   141,   142,   143,
-     144,   145,   146,   170,    36,   126,   127,   153,   170,    95,
-     153,   113,     5,     4,    95,   159,   102,   154,    94,   122,
-     141,   142,   142,   142,   142,   140,   141,   153,   142,   142,
-      38,   143,    38,   143,   142,   142,    93,     5,     6,     7,
+      53,    74,    90,    97,    98,   139,   140,   142,   143,   144,
+     145,   146,   147,   171,    36,   127,   128,   154,   171,    96,
+     154,   114,     5,     4,    96,   160,   103,   155,    95,   123,
+     142,   143,   143,   143,   143,   141,   142,   154,   143,   143,
+      38,   144,    38,   144,   143,   143,    94,     5,     6,     7,
        8,     9,    10,    11,    12,    13,    14,    15,    16,    18,
       19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
       29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
-      39,    40,    41,    52,    53,    36,    92,     4,    33,    37,
-      38,   105,   118,   119,   120,   121,   114,    17,   105,   115,
-     116,   117,   171,   141,   166,   166,    94,   128,   105,   111,
-      36,    37,   122,   123,   124,   125,     4,    92,    33,    38,
-     118,   153,   153,   141,   141,   141,   141,   141,   141,   141,
-     141,   141,   141,   141,   140,   141,   141,   141,   141,   141,
-     141,   141,   141,   141,   141,   141,   141,   141,   141,   141,
-     141,   141,   141,   172,   140,   141,   147,   148,   172,    36,
-     127,   162,   138,    92,   119,    37,    38,   115,   139,     3,
-       4,    17,    95,   129,     3,     4,   172,   139,     4,     5,
-     122,   123,    95,   140,   162,    92,   118,   118,    17,    93,
-      92,     4,   119,    93,    92,   138,   126,     3,   116,   139,
-       1,    42,    55,    56,    58,    59,    60,    66,    67,    71,
-      74,    77,    82,    88,    95,   107,   130,   131,   132,   134,
-     135,   136,   137,   140,   154,   111,    93,     4,    94,   142,
-      92,    92,   141,   148,    93,    92,     3,    17,     3,   141,
-       3,    17,   132,   172,    38,   137,    38,    38,    38,    38,
-     131,   134,   128,    65,     3,     3,   105,   108,   125,    17,
-      82,     3,   140,     3,   147,   140,   140,   147,    38,   109,
-       3,     4,    95,    38,    92,    92,    92,    92,    92,   133,
-     137,   154,     5,   108,   140,   132,     3,   132,   132,     3,
-       3,   108,   122,    92,    62,   137,     3,   132,     3,   137,
-      92,   132
+      39,    40,    41,    52,    53,    36,    93,     4,    33,    37,
+      38,   106,   119,   120,   121,   122,   115,    17,   106,   116,
+     117,   118,   172,   142,   167,   167,    95,   129,   106,   112,
+      36,    37,   123,   124,   125,   126,     4,    93,    33,    38,
+     119,   154,   154,   142,   142,   142,   142,   142,   142,   142,
+     142,   142,   142,   142,   141,   142,   142,   142,   142,   142,
+     142,   142,   142,   142,   142,   142,   142,   142,   142,   142,
+     142,   142,   142,   173,   141,   142,   148,   149,   173,    36,
+     128,   163,   139,    93,   120,    37,    38,   116,   140,     3,
+       4,    17,    96,   130,     3,     4,   173,   140,     4,     5,
+     123,   124,    96,   141,   163,    93,   119,   119,    17,    94,
+      93,     4,   120,    94,    93,   139,   127,     3,   117,   140,
+       1,    42,    55,    56,    58,    59,    60,    66,    67,    70,
+      72,    75,    78,    83,    89,    96,   108,   131,   132,   133,
+     135,   136,   137,   138,   141,   155,   112,    94,     4,    95,
+     143,    93,    93,   142,   149,    94,    93,     3,    17,     3,
+     142,     3,    17,   133,   173,    38,    38,   138,    38,    38,
+      38,    38,   132,   135,   129,    65,     3,     3,   106,   109,
+     126,    17,    83,     3,   141,   148,     3,   148,   141,   141,
+     148,    38,   110,     3,     4,    96,    38,    93,    93,    93,
+      93,    93,    93,   134,   138,   155,     5,   109,   141,   133,
+       3,     3,   133,   133,     3,     3,   109,   123,    93,    62,
+     138,     3,   133,     3,   138,    93,   133
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -2598,251 +2601,258 @@ yyreduce:
   case 99:
 #line 539 "cc.y"
     {
-		(yyval.node) = new(OSET, (yyvsp[(3) - (5)].node), Z);
+		(yyval.node) = new(OPREFETCH, (yyvsp[(3) - (5)].node), Z);
 	}
     break;
 
   case 100:
-#line 544 "cc.y"
+#line 543 "cc.y"
     {
-		(yyval.node) = Z;
+		(yyval.node) = new(OSET, (yyvsp[(3) - (5)].node), Z);
 	}
     break;
 
-  case 102:
-#line 550 "cc.y"
+  case 101:
+#line 548 "cc.y"
     {
 		(yyval.node) = Z;
 	}
     break;
 
-  case 104:
-#line 557 "cc.y"
+  case 103:
+#line 554 "cc.y"
     {
-		(yyval.node) = new(OCAST, (yyvsp[(1) - (1)].node), Z);
-		(yyval.node)->type = types[TLONG];
+		(yyval.node) = Z;
 	}
     break;
 
-  case 106:
-#line 565 "cc.y"
+  case 105:
+#line 561 "cc.y"
     {
-		(yyval.node) = new(OCOMMA, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OCAST, (yyvsp[(1) - (1)].node), Z);
+		(yyval.node)->type = types[TLONG];
 	}
     break;
 
-  case 108:
-#line 572 "cc.y"
+  case 107:
+#line 569 "cc.y"
     {
-		(yyval.node) = new(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OCOMMA, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 109:
 #line 576 "cc.y"
     {
-		(yyval.node) = new(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 110:
 #line 580 "cc.y"
     {
-		(yyval.node) = new(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 111:
 #line 584 "cc.y"
     {
-		(yyval.node) = new(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 112:
 #line 588 "cc.y"
     {
-		(yyval.node) = new(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 113:
 #line 592 "cc.y"
     {
-		(yyval.node) = new(OASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 114:
 #line 596 "cc.y"
     {
-		(yyval.node) = new(OASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 115:
 #line 600 "cc.y"
     {
-		(yyval.node) = new(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 116:
 #line 604 "cc.y"
     {
-		(yyval.node) = new(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 117:
 #line 608 "cc.y"
     {
-		(yyval.node) = new(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 118:
 #line 612 "cc.y"
     {
-		(yyval.node) = new(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 119:
 #line 616 "cc.y"
     {
-		(yyval.node) = new(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 120:
 #line 620 "cc.y"
     {
-		(yyval.node) = new(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 121:
 #line 624 "cc.y"
     {
-		(yyval.node) = new(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 122:
 #line 628 "cc.y"
     {
-		(yyval.node) = new(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 123:
 #line 632 "cc.y"
     {
-		(yyval.node) = new(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 124:
 #line 636 "cc.y"
     {
-		(yyval.node) = new(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 125:
 #line 640 "cc.y"
     {
-		(yyval.node) = new(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 126:
 #line 644 "cc.y"
     {
-		(yyval.node) = new(OCOND, (yyvsp[(1) - (5)].node), new(OLIST, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)));
+		(yyval.node) = new(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 127:
 #line 648 "cc.y"
     {
-		(yyval.node) = new(OAS, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OCOND, (yyvsp[(1) - (5)].node), new(OLIST, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)));
 	}
     break;
 
   case 128:
 #line 652 "cc.y"
     {
-		(yyval.node) = new(OASADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OAS, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 129:
 #line 656 "cc.y"
     {
-		(yyval.node) = new(OASSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OASADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 130:
 #line 660 "cc.y"
     {
-		(yyval.node) = new(OASMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OASSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 131:
 #line 664 "cc.y"
     {
-		(yyval.node) = new(OASDIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OASMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 132:
 #line 668 "cc.y"
     {
-		(yyval.node) = new(OASMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OASDIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 133:
 #line 672 "cc.y"
     {
-		(yyval.node) = new(OASASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OASMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 134:
 #line 676 "cc.y"
     {
-		(yyval.node) = new(OASASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OASASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 135:
 #line 680 "cc.y"
     {
-		(yyval.node) = new(OASAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OASASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 136:
 #line 684 "cc.y"
     {
-		(yyval.node) = new(OASXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+		(yyval.node) = new(OASAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 137:
 #line 688 "cc.y"
     {
+		(yyval.node) = new(OASXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+	}
+    break;
+
+  case 138:
+#line 692 "cc.y"
+    {
 		(yyval.node) = new(OASOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 139:
-#line 695 "cc.y"
+  case 140:
+#line 699 "cc.y"
     {
 		(yyval.node) = new(OCAST, (yyvsp[(5) - (5)].node), Z);
 		dodecl(NODECL, CXXX, (yyvsp[(2) - (5)].type), (yyvsp[(3) - (5)].node));
@@ -2851,8 +2861,8 @@ yyreduce:
 	}
     break;
 
-  case 140:
-#line 702 "cc.y"
+  case 141:
+#line 706 "cc.y"
     {
 		(yyval.node) = new(OSTRUCT, (yyvsp[(6) - (7)].node), Z);
 		dodecl(NODECL, CXXX, (yyvsp[(2) - (7)].type), (yyvsp[(3) - (7)].node));
@@ -2860,94 +2870,94 @@ yyreduce:
 	}
     break;
 
-  case 142:
-#line 711 "cc.y"
-    {
-		(yyval.node) = new(OIND, (yyvsp[(2) - (2)].node), Z);
-	}
-    break;
-
   case 143:
 #line 715 "cc.y"
     {
-		(yyval.node) = new(OADDR, (yyvsp[(2) - (2)].node), Z);
+		(yyval.node) = new(OIND, (yyvsp[(2) - (2)].node), Z);
 	}
     break;
 
   case 144:
 #line 719 "cc.y"
     {
-		(yyval.node) = new(OPOS, (yyvsp[(2) - (2)].node), Z);
+		(yyval.node) = new(OADDR, (yyvsp[(2) - (2)].node), Z);
 	}
     break;
 
   case 145:
 #line 723 "cc.y"
     {
-		(yyval.node) = new(ONEG, (yyvsp[(2) - (2)].node), Z);
+		(yyval.node) = new(OPOS, (yyvsp[(2) - (2)].node), Z);
 	}
     break;
 
   case 146:
 #line 727 "cc.y"
     {
-		(yyval.node) = new(ONOT, (yyvsp[(2) - (2)].node), Z);
+		(yyval.node) = new(ONEG, (yyvsp[(2) - (2)].node), Z);
 	}
     break;
 
   case 147:
 #line 731 "cc.y"
     {
-		(yyval.node) = new(OCOM, (yyvsp[(2) - (2)].node), Z);
+		(yyval.node) = new(ONOT, (yyvsp[(2) - (2)].node), Z);
 	}
     break;
 
   case 148:
 #line 735 "cc.y"
     {
-		(yyval.node) = new(OPREINC, (yyvsp[(2) - (2)].node), Z);
+		(yyval.node) = new(OCOM, (yyvsp[(2) - (2)].node), Z);
 	}
     break;
 
   case 149:
 #line 739 "cc.y"
     {
-		(yyval.node) = new(OPREDEC, (yyvsp[(2) - (2)].node), Z);
+		(yyval.node) = new(OPREINC, (yyvsp[(2) - (2)].node), Z);
 	}
     break;
 
   case 150:
 #line 743 "cc.y"
     {
-		(yyval.node) = new(OSIZE, (yyvsp[(2) - (2)].node), Z);
+		(yyval.node) = new(OPREDEC, (yyvsp[(2) - (2)].node), Z);
 	}
     break;
 
   case 151:
 #line 747 "cc.y"
     {
-		(yyval.node) = new(OSIGN, (yyvsp[(2) - (2)].node), Z);
+		(yyval.node) = new(OSIZE, (yyvsp[(2) - (2)].node), Z);
 	}
     break;
 
   case 152:
-#line 753 "cc.y"
+#line 751 "cc.y"
     {
-		(yyval.node) = (yyvsp[(2) - (3)].node);
+		(yyval.node) = new(OSIGN, (yyvsp[(2) - (2)].node), Z);
 	}
     break;
 
   case 153:
 #line 757 "cc.y"
     {
+		(yyval.node) = (yyvsp[(2) - (3)].node);
+	}
+    break;
+
+  case 154:
+#line 761 "cc.y"
+    {
 		(yyval.node) = new(OSIZE, Z, Z);
 		dodecl(NODECL, CXXX, (yyvsp[(3) - (5)].type), (yyvsp[(4) - (5)].node));
 		(yyval.node)->type = lastdcl;
 	}
     break;
 
-  case 154:
-#line 763 "cc.y"
+  case 155:
+#line 767 "cc.y"
     {
 		(yyval.node) = new(OSIGN, Z, Z);
 		dodecl(NODECL, CXXX, (yyvsp[(3) - (5)].type), (yyvsp[(4) - (5)].node));
@@ -2955,8 +2965,8 @@ yyreduce:
 	}
     break;
 
-  case 155:
-#line 769 "cc.y"
+  case 156:
+#line 773 "cc.y"
     {
 		(yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), Z);
 		if((yyvsp[(1) - (4)].node)->op == ONAME)
@@ -2966,45 +2976,45 @@ yyreduce:
 	}
     break;
 
-  case 156:
-#line 777 "cc.y"
+  case 157:
+#line 781 "cc.y"
     {
 		(yyval.node) = new(OIND, new(OADD, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)), Z);
 	}
     break;
 
-  case 157:
-#line 781 "cc.y"
+  case 158:
+#line 785 "cc.y"
     {
 		(yyval.node) = new(ODOT, new(OIND, (yyvsp[(1) - (3)].node), Z), Z);
 		(yyval.node)->sym = (yyvsp[(3) - (3)].sym);
 	}
     break;
 
-  case 158:
-#line 786 "cc.y"
+  case 159:
+#line 790 "cc.y"
     {
 		(yyval.node) = new(ODOT, (yyvsp[(1) - (3)].node), Z);
 		(yyval.node)->sym = (yyvsp[(3) - (3)].sym);
 	}
     break;
 
-  case 159:
-#line 791 "cc.y"
+  case 160:
+#line 795 "cc.y"
     {
 		(yyval.node) = new(OPOSTINC, (yyvsp[(1) - (2)].node), Z);
 	}
     break;
 
-  case 160:
-#line 795 "cc.y"
+  case 161:
+#line 799 "cc.y"
     {
 		(yyval.node) = new(OPOSTDEC, (yyvsp[(1) - (2)].node), Z);
 	}
     break;
 
-  case 162:
-#line 800 "cc.y"
+  case 163:
+#line 804 "cc.y"
     {
 		(yyval.node) = new(OCONST, Z, Z);
 		(yyval.node)->type = types[TINT];
@@ -3013,8 +3023,8 @@ yyreduce:
 	}
     break;
 
-  case 163:
-#line 807 "cc.y"
+  case 164:
+#line 811 "cc.y"
     {
 		(yyval.node) = new(OCONST, Z, Z);
 		(yyval.node)->type = types[TLONG];
@@ -3023,8 +3033,8 @@ yyreduce:
 	}
     break;
 
-  case 164:
-#line 814 "cc.y"
+  case 165:
+#line 818 "cc.y"
     {
 		(yyval.node) = new(OCONST, Z, Z);
 		(yyval.node)->type = types[TUINT];
@@ -3033,8 +3043,8 @@ yyreduce:
 	}
     break;
 
-  case 165:
-#line 821 "cc.y"
+  case 166:
+#line 825 "cc.y"
     {
 		(yyval.node) = new(OCONST, Z, Z);
 		(yyval.node)->type = types[TULONG];
@@ -3043,8 +3053,8 @@ yyreduce:
 	}
     break;
 
-  case 166:
-#line 828 "cc.y"
+  case 167:
+#line 832 "cc.y"
     {
 		(yyval.node) = new(OCONST, Z, Z);
 		(yyval.node)->type = types[TDOUBLE];
@@ -3053,8 +3063,8 @@ yyreduce:
 	}
     break;
 
-  case 167:
-#line 835 "cc.y"
+  case 168:
+#line 839 "cc.y"
     {
 		(yyval.node) = new(OCONST, Z, Z);
 		(yyval.node)->type = types[TFLOAT];
@@ -3063,8 +3073,8 @@ yyreduce:
 	}
     break;
 
-  case 168:
-#line 842 "cc.y"
+  case 169:
+#line 846 "cc.y"
     {
 		(yyval.node) = new(OCONST, Z, Z);
 		(yyval.node)->type = types[TVLONG];
@@ -3073,8 +3083,8 @@ yyreduce:
 	}
     break;
 
-  case 169:
-#line 849 "cc.y"
+  case 170:
+#line 853 "cc.y"
     {
 		(yyval.node) = new(OCONST, Z, Z);
 		(yyval.node)->type = types[TUVLONG];
@@ -3083,8 +3093,8 @@ yyreduce:
 	}
     break;
 
-  case 172:
-#line 860 "cc.y"
+  case 173:
+#line 864 "cc.y"
     {
 		(yyval.node) = new(OSTRING, Z, Z);
 		(yyval.node)->type = typ(TARRAY, types[TCHAR]);
@@ -3096,8 +3106,8 @@ yyreduce:
 	}
     break;
 
-  case 173:
-#line 870 "cc.y"
+  case 174:
+#line 874 "cc.y"
     {
 		char *s;
 		int n;
@@ -3115,8 +3125,8 @@ yyreduce:
 	}
     break;
 
-  case 174:
-#line 888 "cc.y"
+  case 175:
+#line 892 "cc.y"
     {
 		(yyval.node) = new(OLSTRING, Z, Z);
 		(yyval.node)->type = typ(TARRAY, types[TUSHORT]);
@@ -3128,8 +3138,8 @@ yyreduce:
 	}
     break;
 
-  case 175:
-#line 898 "cc.y"
+  case 176:
+#line 902 "cc.y"
     {
 		char *s;
 		int n;
@@ -3147,22 +3157,22 @@ yyreduce:
 	}
     break;
 
-  case 176:
-#line 915 "cc.y"
+  case 177:
+#line 919 "cc.y"
     {
 		(yyval.node) = Z;
 	}
     break;
 
-  case 179:
-#line 923 "cc.y"
+  case 180:
+#line 927 "cc.y"
     {
 		(yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 180:
-#line 929 "cc.y"
+  case 181:
+#line 933 "cc.y"
     {
 		(yyval.tyty).t1 = strf;
 		(yyval.tyty).t2 = strl;
@@ -3177,8 +3187,8 @@ yyreduce:
 	}
     break;
 
-  case 181:
-#line 942 "cc.y"
+  case 182:
+#line 946 "cc.y"
     {
 		(yyval.type) = strf;
 		strf = (yyvsp[(2) - (4)].tyty).t1;
@@ -3188,32 +3198,32 @@ yyreduce:
 	}
     break;
 
-  case 182:
-#line 951 "cc.y"
+  case 183:
+#line 955 "cc.y"
     {
 		lastclass = CXXX;
 		lasttype = types[TINT];
 	}
     break;
 
-  case 184:
-#line 959 "cc.y"
+  case 185:
+#line 963 "cc.y"
     {
 		(yyval.tycl).t = (yyvsp[(1) - (1)].type);
 		(yyval.tycl).c = CXXX;
 	}
     break;
 
-  case 185:
-#line 964 "cc.y"
+  case 186:
+#line 968 "cc.y"
     {
 		(yyval.tycl).t = simplet((yyvsp[(1) - (1)].lval));
 		(yyval.tycl).c = CXXX;
 	}
     break;
 
-  case 186:
-#line 969 "cc.y"
+  case 187:
+#line 973 "cc.y"
     {
 		(yyval.tycl).t = simplet((yyvsp[(1) - (1)].lval));
 		(yyval.tycl).c = simplec((yyvsp[(1) - (1)].lval));
@@ -3221,8 +3231,8 @@ yyreduce:
 	}
     break;
 
-  case 187:
-#line 975 "cc.y"
+  case 188:
+#line 979 "cc.y"
     {
 		(yyval.tycl).t = (yyvsp[(1) - (2)].type);
 		(yyval.tycl).c = simplec((yyvsp[(2) - (2)].lval));
@@ -3232,8 +3242,8 @@ yyreduce:
 	}
     break;
 
-  case 188:
-#line 983 "cc.y"
+  case 189:
+#line 987 "cc.y"
     {
 		(yyval.tycl).t = simplet(typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval)));
 		(yyval.tycl).c = simplec((yyvsp[(2) - (2)].lval));
@@ -3241,8 +3251,8 @@ yyreduce:
 	}
     break;
 
-  case 189:
-#line 989 "cc.y"
+  case 190:
+#line 993 "cc.y"
     {
 		(yyval.tycl).t = (yyvsp[(2) - (3)].type);
 		(yyval.tycl).c = simplec((yyvsp[(1) - (3)].lval));
@@ -3250,8 +3260,8 @@ yyreduce:
 	}
     break;
 
-  case 190:
-#line 995 "cc.y"
+  case 191:
+#line 999 "cc.y"
     {
 		(yyval.tycl).t = simplet((yyvsp[(2) - (2)].lval));
 		(yyval.tycl).c = simplec((yyvsp[(1) - (2)].lval));
@@ -3259,8 +3269,8 @@ yyreduce:
 	}
     break;
 
-  case 191:
-#line 1001 "cc.y"
+  case 192:
+#line 1005 "cc.y"
     {
 		(yyval.tycl).t = simplet(typebitor((yyvsp[(2) - (3)].lval), (yyvsp[(3) - (3)].lval)));
 		(yyval.tycl).c = simplec((yyvsp[(1) - (3)].lval)|(yyvsp[(3) - (3)].lval));
@@ -3268,8 +3278,8 @@ yyreduce:
 	}
     break;
 
-  case 192:
-#line 1009 "cc.y"
+  case 193:
+#line 1013 "cc.y"
     {
 		(yyval.type) = (yyvsp[(1) - (1)].tycl).t;
 		if((yyvsp[(1) - (1)].tycl).c != CXXX)
@@ -3277,31 +3287,31 @@ yyreduce:
 	}
     break;
 
-  case 193:
-#line 1017 "cc.y"
+  case 194:
+#line 1021 "cc.y"
     {
 		lasttype = (yyvsp[(1) - (1)].tycl).t;
 		lastclass = (yyvsp[(1) - (1)].tycl).c;
 	}
     break;
 
-  case 194:
-#line 1024 "cc.y"
+  case 195:
+#line 1028 "cc.y"
     {
 		dotag((yyvsp[(2) - (2)].sym), TSTRUCT, 0);
 		(yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
 	}
     break;
 
-  case 195:
-#line 1029 "cc.y"
+  case 196:
+#line 1033 "cc.y"
     {
 		dotag((yyvsp[(2) - (2)].sym), TSTRUCT, autobn);
 	}
     break;
 
-  case 196:
-#line 1033 "cc.y"
+  case 197:
+#line 1037 "cc.y"
     {
 		(yyval.type) = (yyvsp[(2) - (4)].sym)->suetag;
 		if((yyval.type)->link != T)
@@ -3311,8 +3321,8 @@ yyreduce:
 	}
     break;
 
-  case 197:
-#line 1041 "cc.y"
+  case 198:
+#line 1045 "cc.y"
     {
 		taggen++;
 		sprint(symb, "_%d_", taggen);
@@ -3322,23 +3332,23 @@ yyreduce:
 	}
     break;
 
-  case 198:
-#line 1049 "cc.y"
+  case 199:
+#line 1053 "cc.y"
     {
 		dotag((yyvsp[(2) - (2)].sym), TUNION, 0);
 		(yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
 	}
     break;
 
-  case 199:
-#line 1054 "cc.y"
+  case 200:
+#line 1058 "cc.y"
     {
 		dotag((yyvsp[(2) - (2)].sym), TUNION, autobn);
 	}
     break;
 
-  case 200:
-#line 1058 "cc.y"
+  case 201:
+#line 1062 "cc.y"
     {
 		(yyval.type) = (yyvsp[(2) - (4)].sym)->suetag;
 		if((yyval.type)->link != T)
@@ -3348,8 +3358,8 @@ yyreduce:
 	}
     break;
 
-  case 201:
-#line 1066 "cc.y"
+  case 202:
+#line 1070 "cc.y"
     {
 		taggen++;
 		sprint(symb, "_%d_", taggen);
@@ -3359,8 +3369,8 @@ yyreduce:
 	}
     break;
 
-  case 202:
-#line 1074 "cc.y"
+  case 203:
+#line 1078 "cc.y"
     {
 		dotag((yyvsp[(2) - (2)].sym), TENUM, 0);
 		(yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
@@ -3370,23 +3380,23 @@ yyreduce:
 	}
     break;
 
-  case 203:
-#line 1082 "cc.y"
+  case 204:
+#line 1086 "cc.y"
     {
 		dotag((yyvsp[(2) - (2)].sym), TENUM, autobn);
 	}
     break;
 
-  case 204:
-#line 1086 "cc.y"
+  case 205:
+#line 1090 "cc.y"
     {
 		en.tenum = T;
 		en.cenum = T;
 	}
     break;
 
-  case 205:
-#line 1091 "cc.y"
+  case 206:
+#line 1095 "cc.y"
     {
 		(yyval.type) = (yyvsp[(2) - (7)].sym)->suetag;
 		if((yyval.type)->link != T)
@@ -3400,167 +3410,167 @@ yyreduce:
 	}
     break;
 
-  case 206:
-#line 1103 "cc.y"
+  case 207:
+#line 1107 "cc.y"
     {
 		en.tenum = T;
 		en.cenum = T;
 	}
     break;
 
-  case 207:
-#line 1108 "cc.y"
+  case 208:
+#line 1112 "cc.y"
     {
 		(yyval.type) = en.tenum;
 	}
     break;
 
-  case 208:
-#line 1112 "cc.y"
+  case 209:
+#line 1116 "cc.y"
     {
 		(yyval.type) = tcopy((yyvsp[(1) - (1)].sym)->type);
 	}
     break;
 
-  case 210:
-#line 1119 "cc.y"
+  case 211:
+#line 1123 "cc.y"
     {
 		(yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
 	}
     break;
 
-  case 211:
-#line 1124 "cc.y"
+  case 212:
+#line 1128 "cc.y"
     {
 		(yyval.lval) = 0;
 	}
     break;
 
-  case 212:
-#line 1128 "cc.y"
+  case 213:
+#line 1132 "cc.y"
     {
 		(yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
 	}
     break;
 
-  case 217:
-#line 1140 "cc.y"
+  case 218:
+#line 1144 "cc.y"
     {
 		(yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
 	}
     break;
 
-  case 220:
-#line 1150 "cc.y"
+  case 221:
+#line 1154 "cc.y"
     {
 		doenum((yyvsp[(1) - (1)].sym), Z);
 	}
     break;
 
-  case 221:
-#line 1154 "cc.y"
+  case 222:
+#line 1158 "cc.y"
     {
 		doenum((yyvsp[(1) - (3)].sym), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 224:
-#line 1161 "cc.y"
+  case 225:
+#line 1165 "cc.y"
     { (yyval.lval) = BCHAR; }
     break;
 
-  case 225:
-#line 1162 "cc.y"
+  case 226:
+#line 1166 "cc.y"
     { (yyval.lval) = BSHORT; }
     break;
 
-  case 226:
-#line 1163 "cc.y"
+  case 227:
+#line 1167 "cc.y"
     { (yyval.lval) = BINT; }
     break;
 
-  case 227:
-#line 1164 "cc.y"
+  case 228:
+#line 1168 "cc.y"
     { (yyval.lval) = BLONG; }
     break;
 
-  case 228:
-#line 1165 "cc.y"
+  case 229:
+#line 1169 "cc.y"
     { (yyval.lval) = BSIGNED; }
     break;
 
-  case 229:
-#line 1166 "cc.y"
+  case 230:
+#line 1170 "cc.y"
     { (yyval.lval) = BUNSIGNED; }
     break;
 
-  case 230:
-#line 1167 "cc.y"
+  case 231:
+#line 1171 "cc.y"
     { (yyval.lval) = BFLOAT; }
     break;
 
-  case 231:
-#line 1168 "cc.y"
+  case 232:
+#line 1172 "cc.y"
     { (yyval.lval) = BDOUBLE; }
     break;
 
-  case 232:
-#line 1169 "cc.y"
+  case 233:
+#line 1173 "cc.y"
     { (yyval.lval) = BVOID; }
     break;
 
-  case 233:
-#line 1172 "cc.y"
+  case 234:
+#line 1176 "cc.y"
     { (yyval.lval) = BAUTO; }
     break;
 
-  case 234:
-#line 1173 "cc.y"
+  case 235:
+#line 1177 "cc.y"
     { (yyval.lval) = BSTATIC; }
     break;
 
-  case 235:
-#line 1174 "cc.y"
+  case 236:
+#line 1178 "cc.y"
     { (yyval.lval) = BEXTERN; }
     break;
 
-  case 236:
-#line 1175 "cc.y"
+  case 237:
+#line 1179 "cc.y"
     { (yyval.lval) = BTYPEDEF; }
     break;
 
-  case 237:
-#line 1176 "cc.y"
+  case 238:
+#line 1180 "cc.y"
     { (yyval.lval) = BTYPESTR; }
     break;
 
-  case 238:
-#line 1177 "cc.y"
+  case 239:
+#line 1181 "cc.y"
     { (yyval.lval) = BREGISTER; }
     break;
 
-  case 239:
-#line 1178 "cc.y"
+  case 240:
+#line 1182 "cc.y"
     { (yyval.lval) = 0; }
     break;
 
-  case 240:
-#line 1181 "cc.y"
+  case 241:
+#line 1185 "cc.y"
     { (yyval.lval) = BCONSTNT; }
     break;
 
-  case 241:
-#line 1182 "cc.y"
+  case 242:
+#line 1186 "cc.y"
     { (yyval.lval) = BVOLATILE; }
     break;
 
-  case 242:
-#line 1183 "cc.y"
+  case 243:
+#line 1187 "cc.y"
     { (yyval.lval) = 0; }
     break;
 
-  case 243:
-#line 1187 "cc.y"
+  case 244:
+#line 1191 "cc.y"
     {
 		(yyval.node) = new(ONAME, Z, Z);
 		if((yyvsp[(1) - (1)].sym)->class == CLOCAL)
@@ -3576,8 +3586,8 @@ yyreduce:
 	}
     break;
 
-  case 244:
-#line 1202 "cc.y"
+  case 245:
+#line 1206 "cc.y"
     {
 		(yyval.node) = new(ONAME, Z, Z);
 		(yyval.node)->sym = (yyvsp[(1) - (1)].sym);
@@ -3592,7 +3602,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 3596 "y.tab.c"
+#line 3606 "y.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -3806,6 +3816,6 @@ yyreturn:
 }
 
 
-#line 1215 "cc.y"
+#line 1219 "cc.y"
 
 
diff --git a/src/cmd/cc/y.tab.h b/src/cmd/cc/y.tab.h
index c56a1d8..32daca9 100644
--- a/src/cmd/cc/y.tab.h
+++ b/src/cmd/cc/y.tab.h
@@ -88,28 +88,29 @@
      LIF = 304,
      LINT = 305,
      LLONG = 306,
-     LREGISTER = 307,
-     LRETURN = 308,
-     LSHORT = 309,
-     LSIZEOF = 310,
-     LUSED = 311,
-     LSTATIC = 312,
-     LSTRUCT = 313,
-     LSWITCH = 314,
-     LTYPEDEF = 315,
-     LTYPESTR = 316,
-     LUNION = 317,
-     LUNSIGNED = 318,
-     LWHILE = 319,
-     LVOID = 320,
-     LENUM = 321,
-     LSIGNED = 322,
-     LCONSTNT = 323,
-     LVOLATILE = 324,
-     LSET = 325,
-     LSIGNOF = 326,
-     LRESTRICT = 327,
-     LINLINE = 328
+     LPREFETCH = 307,
+     LREGISTER = 308,
+     LRETURN = 309,
+     LSHORT = 310,
+     LSIZEOF = 311,
+     LUSED = 312,
+     LSTATIC = 313,
+     LSTRUCT = 314,
+     LSWITCH = 315,
+     LTYPEDEF = 316,
+     LTYPESTR = 317,
+     LUNION = 318,
+     LUNSIGNED = 319,
+     LWHILE = 320,
+     LVOID = 321,
+     LENUM = 322,
+     LSIGNED = 323,
+     LCONSTNT = 324,
+     LVOLATILE = 325,
+     LSET = 326,
+     LSIGNOF = 327,
+     LRESTRICT = 328,
+     LINLINE = 329
    };
 #endif
 /* Tokens.  */
@@ -162,28 +163,29 @@
 #define LIF 304
 #define LINT 305
 #define LLONG 306
-#define LREGISTER 307
-#define LRETURN 308
-#define LSHORT 309
-#define LSIZEOF 310
-#define LUSED 311
-#define LSTATIC 312
-#define LSTRUCT 313
-#define LSWITCH 314
-#define LTYPEDEF 315
-#define LTYPESTR 316
-#define LUNION 317
-#define LUNSIGNED 318
-#define LWHILE 319
-#define LVOID 320
-#define LENUM 321
-#define LSIGNED 322
-#define LCONSTNT 323
-#define LVOLATILE 324
-#define LSET 325
-#define LSIGNOF 326
-#define LRESTRICT 327
-#define LINLINE 328
+#define LPREFETCH 307
+#define LREGISTER 308
+#define LRETURN 309
+#define LSHORT 310
+#define LSIZEOF 311
+#define LUSED 312
+#define LSTATIC 313
+#define LSTRUCT 314
+#define LSWITCH 315
+#define LTYPEDEF 316
+#define LTYPESTR 317
+#define LUNION 318
+#define LUNSIGNED 319
+#define LWHILE 320
+#define LVOID 321
+#define LENUM 322
+#define LSIGNED 323
+#define LCONSTNT 324
+#define LVOLATILE 325
+#define LSET 326
+#define LSIGNOF 327
+#define LRESTRICT 328
+#define LINLINE 329
 
 
 
@@ -217,7 +219,7 @@ typedef union YYSTYPE
 	vlong	vval;
 }
 /* Line 1529 of yacc.c.  */
-#line 221 "y.tab.h"
+#line 223 "y.tab.h"
 	YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go
index 381e606..dbae3b7 100644
--- a/src/cmd/cgo/ast.go
+++ b/src/cmd/cgo/ast.go
@@ -78,7 +78,7 @@ func (f *File) ReadGo(name string) {
 			}
 			if cg != nil {
 				f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), name)
-				f.Preamble += cg.Text() + "\n"
+				f.Preamble += commentText(cg) + "\n"
 			}
 		}
 	}
@@ -131,6 +131,30 @@ func (f *File) ReadGo(name string) {
 	f.AST = ast2
 }
 
+// Like ast.CommentGroup's Text method but preserves
+// leading blank lines, so that line numbers line up.
+func commentText(g *ast.CommentGroup) string {
+	if g == nil {
+		return ""
+	}
+	var pieces []string
+	for _, com := range g.List {
+		c := string(com.Text)
+		// Remove comment markers.
+		// The parser has given us exactly the comment text.
+		switch c[1] {
+		case '/':
+			//-style comment (no newline at the end)
+			c = c[2:] + "\n"
+		case '*':
+			/*-style comment */
+			c = c[2 : len(c)-2]
+		}
+		pieces = append(pieces, c)
+	}
+	return strings.Join(pieces, "")
+}
+
 // Save references to C.xxx for later processing.
 func (f *File) saveRef(x interface{}, context string) {
 	n, ok := x.(*ast.Expr)
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index 1bb48f4..955b7c4 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -65,11 +65,13 @@ struct_, union_, or enum_, as in C.struct_stat.
 
 Go structs cannot embed fields with C types.
 
-Any C function that returns a value may be called in a multiple
-assignment context to retrieve both the return value and the
-C errno variable as an error.  For example:
+Any C function (even void functions) may be called in a multiple
+assignment context to retrieve both the return value (if any) and the
+C errno variable as an error (use _ to skip the result value if the
+function returns void).  For example:
 
 	n, err := C.atoi("abc")
+	_, err := C.voidFunc()
 
 In C, a function argument written as a fixed size array
 actually requires a pointer to the first element of the array.
@@ -83,7 +85,8 @@ by making copies of the data.  In pseudo-Go definitions:
 	// Go string to C string
 	// The C string is allocated in the C heap using malloc.
 	// It is the caller's responsibility to arrange for it to be
-	// freed, such as by calling C.free.
+	// freed, such as by calling C.free (be sure to include stdlib.h
+	// if C.free is needed).
 	func C.CString(string) *C.char
 
 	// C string to Go string
@@ -113,6 +116,11 @@ copied from the cgo input files. Functions with multiple
 return values are mapped to functions returning a struct.
 Not all Go types can be mapped to C types in a useful way.
 
+Using //export in a file places a restriction on the preamble:
+since it is copied into two different C output files, it must not
+contain any definitions, only declarations. Definitions must be
+placed in preambles in other files, or in C source files.
+
 Cgo transforms the input file into four output files: two Go source
 files, a C file for 6c (or 8c or 5c), and a C file for gcc.
 
@@ -125,4 +133,492 @@ Cgo does not yet work with gccgo.
 See "C? Go? Cgo!" for an introduction to using cgo:
 http://golang.org/doc/articles/c_go_cgo.html
 */
-package documentation
+package main
+
+/*
+Implementation details.
+
+Cgo provides a way for Go programs to call C code linked into the same
+address space. This comment explains the operation of cgo.
+
+Cgo reads a set of Go source files and looks for statements saying
+import "C". If the import has a doc comment, that comment is
+taken as literal C code to be used as a preamble to any C code
+generated by cgo. A typical preamble #includes necessary definitions:
+
+	// #include <stdio.h>
+	import "C"
+
+For more details about the usage of cgo, see the documentation
+comment at the top of this file.
+
+Understanding C
+
+Cgo scans the Go source files that import "C" for uses of that
+package, such as C.puts. It collects all such identifiers. The next
+step is to determine each kind of name. In C.xxx the xxx might refer
+to a type, a function, a constant, or a global variable. Cgo must
+decide which.
+
+The obvious thing for cgo to do is to process the preamble, expanding
+#includes and processing the corresponding C code. That would require
+a full C parser and type checker that was also aware of any extensions
+known to the system compiler (for example, all the GNU C extensions) as
+well as the system-specific header locations and system-specific
+pre-#defined macros. This is certainly possible to do, but it is an
+enormous amount of work.
+
+Cgo takes a different approach. It determines the meaning of C
+identifiers not by parsing C code but by feeding carefully constructed
+programs into the system C compiler and interpreting the generated
+error messages, debug information, and object files. In practice,
+parsing these is significantly less work and more robust than parsing
+C source.
+
+Cgo first invokes gcc -E -dM on the preamble, in order to find out
+about simple #defines for constants and the like. These are recorded
+for later use.
+
+Next, cgo needs to identify the kinds for each identifier. For the
+identifiers C.foo and C.bar, cgo generates this C program:
+
+	<preamble>
+	void __cgo__f__(void) {
+	#line 1 "cgo-test"
+		foo;
+		enum { _cgo_enum_0 = foo };
+		bar;
+		enum { _cgo_enum_1 = bar };
+	}
+
+This program will not compile, but cgo can look at the error messages
+to infer the kind of each identifier. The line number given in the
+error tells cgo which identifier is involved.
+
+An error like "unexpected type name" or "useless type name in empty
+declaration" or "declaration does not declare anything" tells cgo that
+the identifier is a type.
+
+An error like "statement with no effect" or "expression result unused"
+tells cgo that the identifier is not a type, but not whether it is a
+constant, function, or global variable.
+
+An error like "not an integer constant" tells cgo that the identifier
+is not a constant. If it is also not a type, it must be a function or
+global variable. For now, those can be treated the same.
+
+Next, cgo must learn the details of each type, variable, function, or
+constant. It can do this by reading object files. If cgo has decided
+that t1 is a type, v2 and v3 are variables or functions, and c4, c5,
+and c6 are constants, it generates:
+
+	<preamble>
+	typeof(t1) *__cgo__1;
+	typeof(v2) *__cgo__2;
+	typeof(v3) *__cgo__3;
+	typeof(c4) *__cgo__4;
+	enum { __cgo_enum__4 = c4 };
+	typeof(c5) *__cgo__5;
+	enum { __cgo_enum__5 = c5 };
+	typeof(c6) *__cgo__6;
+	enum { __cgo_enum__6 = c6 };
+
+	long long __cgo_debug_data[] = {
+		0, // t1
+		0, // v2
+		0, // v3
+		c4,
+		c5,
+		c6,
+		1
+	};
+
+and again invokes the system C compiler, to produce an object file
+containing debug information. Cgo parses the DWARF debug information
+for __cgo__N to learn the type of each identifier. (The types also
+distinguish functions from global variables.) If using a standard gcc,
+cgo can parse the DWARF debug information for the __cgo_enum__N to
+learn the identifier's value. The LLVM-based gcc on OS X emits
+incomplete DWARF information for enums; in that case cgo reads the
+constant values from the __cgo_debug_data from the object file's data
+segment.
+
+At this point cgo knows the meaning of each C.xxx well enough to start
+the translation process.
+
+Translating Go
+
+[The rest of this comment refers to 6g and 6c, the Go and C compilers
+that are part of the amd64 port of the gc Go toolchain. Everything here
+applies to another architecture's compilers as well.]
+
+Given the input Go files x.go and y.go, cgo generates these source
+files:
+
+	x.cgo1.go       # for 6g
+	y.cgo1.go       # for 6g
+	_cgo_gotypes.go # for 6g
+	_cgo_defun.c    # for 6c
+	x.cgo2.c        # for gcc
+	y.cgo2.c        # for gcc
+	_cgo_export.c   # for gcc
+	_cgo_main.c     # for gcc
+
+The file x.cgo1.go is a copy of x.go with the import "C" removed and
+references to C.xxx replaced with names like _Cfunc_xxx or _Ctype_xxx.
+The definitions of those identifiers, written as Go functions, types,
+or variables, are provided in _cgo_gotypes.go.
+
+Here is a _cgo_gotypes.go containing definitions for C.flush (provided
+in the preamble) and C.puts (from stdio):
+
+	type _Ctype_char int8
+	type _Ctype_int int32
+	type _Ctype_void [0]byte
+
+	func _Cfunc_CString(string) *_Ctype_char
+	func _Cfunc_flush() _Ctype_void
+	func _Cfunc_puts(*_Ctype_char) _Ctype_int
+
+For functions, cgo only writes an external declaration in the Go
+output. The implementation is in a combination of C for 6c (meaning
+any gc-toolchain compiler) and C for gcc.
+
+The 6c file contains the definitions of the functions. They all have
+similar bodies that invoke runtime·cgocall to make a switch from the
+Go runtime world to the system C (GCC-based) world.
+
+For example, here is the definition of _Cfunc_puts:
+
+	void _cgo_be59f0f25121_Cfunc_puts(void*);
+
+	void
+	·_Cfunc_puts(struct{uint8 x[1];}p)
+	{
+		runtime·cgocall(_cgo_be59f0f25121_Cfunc_puts, &p);
+	}
+
+The hexadecimal number is a hash of cgo's input, chosen to be
+deterministic yet unlikely to collide with other uses. The actual
+function _cgo_be59f0f25121_Cfunc_puts is implemented in a C source
+file compiled by gcc, the file x.cgo2.c:
+
+	void
+	_cgo_be59f0f25121_Cfunc_puts(void *v)
+	{
+		struct {
+			char* p0;
+			int r;
+			char __pad12[4];
+		} __attribute__((__packed__)) *a = v;
+		a->r = puts((void*)a->p0);
+	}
+
+It extracts the arguments from the pointer to _Cfunc_puts's argument
+frame, invokes the system C function (in this case, puts), stores the
+result in the frame, and returns.
+
+Linking
+
+Once the _cgo_export.c and *.cgo2.c files have been compiled with gcc,
+they need to be linked into the final binary, along with the libraries
+they might depend on (in the case of puts, stdio). 6l has been
+extended to understand basic ELF files, but it does not understand ELF
+in the full complexity that modern C libraries embrace, so it cannot
+in general generate direct references to the system libraries.
+
+Instead, the build process generates an object file using dynamic
+linkage to the desired libraries. The main function is provided by
+_cgo_main.c:
+
+	int main() { return 0; }
+	void crosscall2(void(*fn)(void*, int), void *a, int c) { }
+	void _cgo_allocate(void *a, int c) { }
+	void _cgo_panic(void *a, int c) { }
+
+The extra functions here are stubs to satisfy the references in the C
+code generated for gcc. The build process links this stub, along with
+_cgo_export.c and *.cgo2.c, into a dynamic executable and then lets
+cgo examine the executable. Cgo records the list of shared library
+references and resolved names and writes them into a new file
+_cgo_import.c, which looks like:
+
+	#pragma cgo_dynamic_linker "/lib64/ld-linux-x86-64.so.2"
+	#pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
+	#pragma cgo_import_dynamic __libc_start_main __libc_start_main#GLIBC_2.2.5 "libc.so.6"
+	#pragma cgo_import_dynamic stdout stdout#GLIBC_2.2.5 "libc.so.6"
+	#pragma cgo_import_dynamic fflush fflush#GLIBC_2.2.5 "libc.so.6"
+	#pragma cgo_import_dynamic _ _ "libpthread.so.0"
+	#pragma cgo_import_dynamic _ _ "libc.so.6"
+
+In the end, the compiled Go package, which will eventually be
+presented to 6l as part of a larger program, contains:
+
+	_go_.6        # 6g-compiled object for _cgo_gotypes.go *.cgo1.go
+	_cgo_defun.6  # 6c-compiled object for _cgo_defun.c
+	_all.o        # gcc-compiled object for _cgo_export.c, *.cgo2.c
+	_cgo_import.6 # 6c-compiled object for _cgo_import.c
+
+The final program will be a dynamic executable, so that 6l can avoid
+needing to process arbitrary .o files. It only needs to process the .o
+files generated from C files that cgo writes, and those are much more
+limited in the ELF or other features that they use.
+
+In essence, the _cgo_import.6 file includes the extra linking
+directives that 6l is not sophisticated enough to derive from _all.o
+on its own. Similarly, the _all.o uses dynamic references to real
+system object code because 6l is not sophisticated enough to process
+the real code.
+
+The main benefits of this system are that 6l remains relatively simple
+(it does not need to implement a complete ELF and Mach-O linker) and
+that gcc is not needed after the package is compiled. For example,
+package net uses cgo for access to name resolution functions provided
+by libc. Although gcc is needed to compile package net, gcc is not
+needed to link programs that import package net.
+
+Runtime
+
+When using cgo, Go must not assume that it owns all details of the
+process. In particular it needs to coordinate with C in the use of
+threads and thread-local storage. The runtime package, in its own
+(6c-compiled) C code, declares a few uninitialized (default bss)
+variables:
+
+	bool	runtime·iscgo;
+	void	(*libcgo_thread_start)(void*);
+	void	(*initcgo)(G*);
+
+Any package using cgo imports "runtime/cgo", which provides
+initializations for these variables. It sets iscgo to 1, initcgo to a
+gcc-compiled function that can be called early during program startup,
+and libcgo_thread_start to a gcc-compiled function that can be used to
+create a new thread, in place of the runtime's usual direct system
+calls.
+
+[NOTE: From here down is planned but not yet implemented.]
+
+Internal and External Linking
+
+The text above describes "internal" linking, in which 6l parses and
+links host object files (ELF, Mach-O, PE, and so on) into the final
+executable itself. Keeping 6l simple means we cannot possibly
+implement the full semantics of the host linker, so the kinds of
+objects that can be linked directly into the binary is limited (other
+code can only be used as a dynamic library). On the other hand, when
+using internal linking, 6l can generate Go binaries by itself.
+
+In order to allow linking arbitrary object files without requiring
+dynamic libraries, cgo will soon support an "external" linking mode
+too. In external linking mode, 6l does not process any host object
+files. Instead, it collects all the Go code and writes a single go.o
+object file containing it. Then it invokes the host linker (usually
+gcc) to combine the go.o object file and any supporting non-Go code
+into a final executable. External linking avoids the dynamic library
+requirement but introduces a requirement that the host linker be
+present to create such a binary.
+
+Most builds both compile source code and invoke the linker to create a
+binary. When cgo is involved, the compile step already requires gcc, so
+it is not problematic for the link step to require gcc too.
+
+An important exception is builds using a pre-compiled copy of the
+standard library. In particular, package net uses cgo on most systems,
+and we want to preserve the ability to compile pure Go code that
+imports net without requiring gcc to be present at link time. (In this
+case, the dynamic library requirement is less significant, because the
+only library involved is libc.so, which can usually be assumed
+present.)
+
+This conflict between functionality and the gcc requirement means we
+must support both internal and external linking, depending on the
+circumstances: if net is the only cgo-using package, then internal
+linking is probably fine, but if other packages are involved, so that there
+are dependencies on libraries beyond libc, external linking is likely
+to work better. The compilation of a package records the relevant
+information to support both linking modes, leaving the decision
+to be made when linking the final binary.
+
+Linking Directives
+
+In either linking mode, package-specific directives must be passed
+through to 6l. These are communicated by writing #pragma directives
+in a C source file compiled by 6c. The directives are copied into the .6 object file
+and then processed by the linker.
+
+The directives are:
+
+#pragma cgo_import_dynamic <local> [<remote> ["<library>"]]
+
+	In internal linking mode, allow an unresolved reference to
+	<local>, assuming it will be resolved by a dynamic library
+	symbol. The optional <remote> specifies the symbol's name and
+	possibly version in the dynamic library, and the optional "<library>"
+	names the specific library where the symbol should be found.
+
+	In the <remote>, # or @ can be used to introduce a symbol version.
+
+	Examples:
+	#pragma cgo_import_dynamic puts
+	#pragma cgo_import_dynamic puts puts#GLIBC_2.2.5
+	#pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
+
+	A side effect of the cgo_dynamic_import directive with a
+	library is to make the final binary depend on that dynamic
+	library. To get the dependency without importing any specific
+	symbols, use _ for local and remote.
+
+	Example:
+	#pragma cgo_import_dynamic _ _ "libc.so.6"
+
+	For compatibility with current versions of SWIG,
+	#pragma dynimport is an alias for #pragma cgo_dynamic_import.
+
+#pragma cgo_dynamic_linker "<path>"
+
+	In internal linking mode, use "<path>" as the dynamic linker
+	in the final binary. This directive is only needed from one
+	package when constructing a binary; by convention it is
+	supplied by runtime/cgo.
+
+	Example:
+	#pragma cgo_dynamic_linker "/lib/ld-linux.so.2"
+
+#pragma cgo_export <local> <remote>
+
+	In both internal and external linking modes, put the Go symbol
+	named <local> into the program's exported symbol table as
+	<remote>, so that C code can refer to it by that name. This
+	mechanism makes it possible for C code to call back into Go or
+	to share Go's data.
+
+	For compatibility with current versions of SWIG,
+	#pragma dynexport is an alias for #pragma cgo_export.
+
+#pragma cgo_import_static <local>
+
+	In external linking mode, allow unresolved references to
+	<local> in the go.o object file prepared for the host linker,
+	under the assumption that <local> will be supplied by the
+	other object files that will be linked with go.o.
+
+	Example:
+	#pragma cgo_import_static puts_wrapper
+
+#pragma cgo_ldflag "<arg>"
+
+	In external linking mode, invoke the host linker (usually gcc)
+	with "<arg>" as a command-line argument following the .o files.
+	Note that the arguments are for "gcc", not "ld".
+
+	Example:
+	#pragma cgo_ldflag "-lpthread"
+	#pragma cgo_ldflag "-L/usr/local/sqlite3/lib"
+
+A package compiled with cgo will include directives for both
+internal and external linking; the linker will select the appropriate
+subset for the chosen linking mode.
+
+Example
+
+As a simple example, consider a package that uses cgo to call C.sin.
+The following code will be generated by cgo:
+
+	// compiled by 6g
+
+	type _Ctype_double float64
+	func _Cfunc_sin(_Ctype_double) _Ctype_double
+
+	// compiled by 6c
+
+	#pragma cgo_import_dynamic sin sin#GLIBC_2.2.5 "libm.so.6"
+
+	#pragma cgo_import_static _cgo_gcc_Cfunc_sin
+	#pragma cgo_ldflag "-lm"
+
+	void _cgo_gcc_Cfunc_sin(void*);
+
+	void
+	·_Cfunc_sin(struct{uint8 x[16];}p)
+	{
+		runtime·cgocall(_cgo_gcc_Cfunc_sin, &p);
+	}
+
+	// compiled by gcc, into foo.cgo2.o
+
+	void
+	_cgo_gcc_Cfunc_sin(void *v)
+	{
+		struct {
+			double p0;
+			double r;
+		} __attribute__((__packed__)) *a = v;
+		a->r = sin(a->p0);
+	}
+
+What happens at link time depends on whether the final binary is linked
+using the internal or external mode. If other packages are compiled in
+"external only" mode, then the final link will be an external one.
+Otherwise the link will be an internal one.
+
+The directives in the 6c-compiled file are used according to the kind
+of final link used.
+
+In internal mode, 6l itself processes all the host object files, in
+particular foo.cgo2.o. To do so, it uses the cgo_dynamic_import and
+cgo_dynamic_linker directives to learn that the otherwise undefined
+reference to sin in foo.cgo2.o should be rewritten to refer to the
+symbol sin with version GLIBC_2.2.5 from the dynamic library
+"libm.so.6", and the binary should request "/lib/ld-linux.so.2" as its
+runtime dynamic linker.
+
+In external mode, 6l does not process any host object files, in
+particular foo.cgo2.o. It links together the 6g- and 6c-generated
+object files, along with any other Go code, into a go.o file. While
+doing that, 6l will discover that there is no definition for
+_cgo_gcc_Cfunc_sin, referred to by the 6c-compiled source file. This
+is okay, because 6l also processes the cgo_import_static directive and
+knows that _cgo_gcc_Cfunc_sin is expected to be supplied by a host
+object file, so 6l does not treat the missing symbol as an error when
+creating go.o. Indeed, the definition for _cgo_gcc_Cfunc_sin will be
+provided to the host linker by foo2.cgo.o, which in turn will need the
+symbol 'sin'. 6l also processes the cgo_ldflag directives, so that it
+knows that the eventual host link command must include the -lm
+argument, so that the host linker will be able to find 'sin' in the
+math library.
+
+6l Command Line Interface
+
+The go command and any other Go-aware build systems invoke 6l
+to link a collection of packages into a single binary. By default, 6l will
+present the same interface it does today:
+
+	6l main.a
+
+produces a file named 6.out, even if 6l does so by invoking the host
+linker in external linking mode.
+
+By default, 6l will decide the linking mode as follows: if the only
+packages using cgo are those on a whitelist of standard library
+packages (net, os/user, runtime/cgo), 6l will use internal linking
+mode. Otherwise, there are non-standard cgo packages involved, and 6l
+will use external linking mode. The first rule means that a build of
+the godoc binary, which uses net but no other cgo, can run without
+needing gcc available. The second rule means that a build of a
+cgo-wrapped library like sqlite3 can generate a standalone executable
+instead of needing to refer to a dynamic library. The specific choice
+can be overridden using a command line flag: 6l -cgolink=internal or
+6l -cgolink=external.
+
+In an external link, 6l will create a temporary directory, write any
+host object files found in package archives to that directory (renamed
+to avoid conflicts), write the go.o file to that directory, and invoke
+the host linker. The default value for the host linker is $CC, split
+into fields, or else "gcc". The specific host linker command line can
+be overridden using a command line flag: 6l -hostld='gcc -ggdb'
+
+These defaults mean that Go-aware build systems can ignore the linking
+changes and keep running plain '6l' and get reasonable results, but
+they can also control the linking details if desired.
+
+*/
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index 98a847e..4b0a521 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -391,9 +391,9 @@ func (p *Package) guessKinds(f *File) []*Name {
 	b.WriteString(builtinProlog)
 	b.WriteString(f.Preamble)
 	b.WriteString("void __cgo__f__(void) {\n")
-	b.WriteString("#line 0 \"cgo-test\"\n")
+	b.WriteString("#line 1 \"cgo-test\"\n")
 	for i, n := range toSniff {
-		fmt.Fprintf(&b, "%s; enum { _cgo_enum_%d = %s }; /* cgo-test:%d */\n", n.C, i, n.C, i)
+		fmt.Fprintf(&b, "%s; /* #%d */\nenum { _cgo_enum_%d = %s }; /* #%d */\n", n.C, i, i, n.C, i)
 	}
 	b.WriteString("}\n")
 	stderr := p.gccErrors(b.Bytes())
@@ -423,14 +423,18 @@ func (p *Package) guessKinds(f *File) []*Name {
 		if err != nil {
 			continue
 		}
+		i = (i - 1) / 2
 		what := ""
 		switch {
 		default:
 			continue
-		case strings.Contains(line, ": useless type name in empty declaration"):
+		case strings.Contains(line, ": useless type name in empty declaration"),
+			strings.Contains(line, ": declaration does not declare anything"),
+			strings.Contains(line, ": unexpected type name"):
 			what = "type"
 			isConst[i] = false
-		case strings.Contains(line, ": statement with no effect"):
+		case strings.Contains(line, ": statement with no effect"),
+			strings.Contains(line, ": expression result unused"):
 			what = "not-type" // const or func or var
 		case strings.Contains(line, "undeclared"):
 			error_(token.NoPos, "%s", strings.TrimSpace(line[colon+1:]))
@@ -508,7 +512,12 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
 			fmt.Fprintf(&b, "\t0,\n")
 		}
 	}
-	fmt.Fprintf(&b, "\t0\n")
+	// for the last entry, we can not use 0, otherwise
+	// in case all __cgodebug_data is zero initialized,
+	// LLVM-based gcc will place the it in the __DATA.__common
+	// zero-filled section (our debug/macho doesn't support
+	// this)
+	fmt.Fprintf(&b, "\t1\n")
 	fmt.Fprintf(&b, "};\n")
 
 	d, bo, debugData := p.gccDebug(b.Bytes())
@@ -596,7 +605,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
 
 	// Record types and typedef information.
 	var conv typeConv
-	conv.Init(p.PtrSize)
+	conv.Init(p.PtrSize, p.IntSize)
 	for i, n := range names {
 		if types[i] == nil {
 			continue
@@ -618,7 +627,9 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
 				// Remove injected enum to ensure the value will deep-compare
 				// equally in future loads of the same constant.
 				delete(n.Type.EnumValues, k)
-			} else if n.Kind == "const" && i < len(enumVal) {
+			}
+			// Prefer debug data over DWARF debug output, if we have it.
+			if n.Kind == "const" && i < len(enumVal) {
 				n.Const = fmt.Sprintf("%#x", enumVal[i])
 			}
 		}
@@ -637,7 +648,14 @@ func (p *Package) rewriteRef(f *File) {
 			n.Kind = "var"
 		}
 		if n.Mangle == "" {
-			n.Mangle = "_C" + n.Kind + "_" + n.Go
+			// When using gccgo variables have to be
+			// exported so that they become global symbols
+			// that the C code can refer to.
+			prefix := "_C"
+			if *gccgo && n.Kind == "var" {
+				prefix = "C"
+			}
+			n.Mangle = prefix + n.Kind + "_" + n.Go
 		}
 	}
 
@@ -662,9 +680,6 @@ func (p *Package) rewriteRef(f *File) {
 				break
 			}
 			if r.Context == "call2" {
-				if r.Name.FuncType.Result == nil {
-					error_(r.Pos(), "assignment count mismatch: 2 = 0")
-				}
 				// Invent new Name for the two-result function.
 				n := f.Name["2"+r.Name.Go]
 				if n == nil {
@@ -720,23 +735,30 @@ func (p *Package) rewriteRef(f *File) {
 	}
 }
 
-// gccName returns the name of the compiler to run.  Use $GCC if set in
+// gccName returns the name of the compiler to run.  Use $CC if set in
 // the environment, otherwise just "gcc".
 
-func (p *Package) gccName() (ret string) {
-	if ret = os.Getenv("GCC"); ret == "" {
-		ret = "gcc"
+func (p *Package) gccName() string {
+	// Use $CC if set, since that's what the build uses.
+	if ret := os.Getenv("CC"); ret != "" {
+		return ret
 	}
-	return
+	// Fall back to $GCC if set, since that's what we used to use.
+	if ret := os.Getenv("GCC"); ret != "" {
+		return ret
+	}
+	return "gcc"
 }
 
-// gccMachine returns the gcc -m flag to use, either "-m32" or "-m64".
+// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
 func (p *Package) gccMachine() []string {
 	switch goarch {
 	case "amd64":
 		return []string{"-m64"}
 	case "386":
 		return []string{"-m32"}
+	case "arm":
+		return []string{"-marm"} // not thumb
 	}
 	return nil
 }
@@ -755,9 +777,22 @@ func (p *Package) gccCmd() []string {
 		"-o" + gccTmp(),                     // write object to tmp
 		"-gdwarf-2",                         // generate DWARF v2 debugging symbols
 		"-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped enum otherwise
-		"-c",                                // do not link
-		"-xc",                               // input language is C
+		"-c",  // do not link
+		"-xc", // input language is C
+	}
+	if strings.Contains(p.gccName(), "clang") {
+		c = append(c,
+			"-ferror-limit=0",
+			// Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
+			// doesn't have -Wno-unneeded-internal-declaration, so we need yet another
+			// flag to disable the warning. Yes, really good diagnostics, clang.
+			"-Wno-unknown-warning-option",
+			"-Wno-unneeded-internal-declaration",
+			"-Wno-unused-function",
+			"-Qunused-arguments",
+		)
 	}
+
 	c = append(c, p.GccOptions...)
 	c = append(c, p.gccMachine()...)
 	c = append(c, "-") //read input from standard input
@@ -795,15 +830,30 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
 		return d, f.ByteOrder, data
 	}
 
-	// Can skip debug data block in ELF and PE for now.
-	// The DWARF information is complete.
-
 	if f, err := elf.Open(gccTmp()); err == nil {
 		d, err := f.DWARF()
 		if err != nil {
 			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
 		}
-		return d, f.ByteOrder, nil
+		var data []byte
+		symtab, err := f.Symbols()
+		if err == nil {
+			for i := range symtab {
+				s := &symtab[i]
+				if s.Name == "__cgodebug_data" {
+					// Found it.  Now find data section.
+					if i := int(s.Section); 0 <= i && i < len(f.Sections) {
+						sect := f.Sections[i]
+						if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+							if sdat, err := sect.Data(); err == nil {
+								data = sdat[s.Value-sect.Addr:]
+							}
+						}
+					}
+				}
+			}
+		}
+		return d, f.ByteOrder, data
 	}
 
 	if f, err := pe.Open(gccTmp()); err == nil {
@@ -811,7 +861,20 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
 		if err != nil {
 			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
 		}
-		return d, binary.LittleEndian, nil
+		var data []byte
+		for _, s := range f.Symbols {
+			if s.Name == "_"+"__cgodebug_data" {
+				if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
+					sect := f.Sections[i]
+					if s.Value < sect.Size {
+						if sdat, err := sect.Data(); err == nil {
+							data = sdat[s.Value:]
+						}
+					}
+				}
+			}
+		}
+		return d, binary.LittleEndian, data
 	}
 
 	fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
@@ -889,16 +952,19 @@ type typeConv struct {
 	void                                   ast.Expr
 	unsafePointer                          ast.Expr
 	string                                 ast.Expr
+	goVoid                                 ast.Expr // _Ctype_void, denotes C's void
 
 	ptrSize int64
+	intSize int64
 }
 
 var tagGen int
 var typedef = make(map[string]*Type)
 var goIdent = make(map[string]*ast.Ident)
 
-func (c *typeConv) Init(ptrSize int64) {
+func (c *typeConv) Init(ptrSize, intSize int64) {
 	c.ptrSize = ptrSize
+	c.intSize = intSize
 	c.m = make(map[dwarf.Type]*Type)
 	c.bool = c.Ident("bool")
 	c.byte = c.Ident("byte")
@@ -918,6 +984,7 @@ func (c *typeConv) Init(ptrSize int64) {
 	c.unsafePointer = c.Ident("unsafe.Pointer")
 	c.void = c.Ident("void")
 	c.string = c.Ident("string")
+	c.goVoid = c.Ident("_Ctype_void")
 }
 
 // base strips away qualifiers and typedefs to get the underlying type
@@ -988,6 +1055,12 @@ 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()
 	t.Align = -1
@@ -1032,7 +1105,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
 
 	case *dwarf.BoolType:
 		t.Go = c.bool
-		t.Align = c.ptrSize
+		t.Align = 1
 
 	case *dwarf.CharType:
 		if t.Size != 1 {
@@ -1163,11 +1236,12 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
 		t.Go = name // publish before recursive calls
 		goIdent[name.Name] = name
 		switch dt.Kind {
-		case "union", "class":
+		case "class", "union":
 			t.Go = c.Opaque(t.Size)
 			if t.C.Empty() {
 				t.C.Set("typeof(unsigned char[%d])", t.Size)
 			}
+			t.Align = 1 // TODO: should probably base this on field alignment.
 			typedef[name.Name] = t
 		case "struct":
 			g, csyntax, align := c.Struct(dt, pos)
@@ -1245,8 +1319,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
 		}
 
 	case *dwarf.VoidType:
-		t.Go = c.void
+		t.Go = c.goVoid
 		t.C.Set("void")
+		t.Align = 1
 	}
 
 	switch dtype.(type) {
@@ -1334,7 +1409,9 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
 	}
 	var r *Type
 	var gr []*ast.Field
-	if _, ok := dtype.ReturnType.(*dwarf.VoidType); !ok && dtype.ReturnType != nil {
+	if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok {
+		gr = []*ast.Field{{Type: c.goVoid}}
+	} else if dtype.ReturnType != nil {
 		r = c.Type(dtype.ReturnType, pos)
 		gr = []*ast.Field{{Type: r.Go}}
 	}
@@ -1493,8 +1570,8 @@ func godefsFields(fld []*ast.Field) {
 	npad := 0
 	for _, f := range fld {
 		for _, n := range f.Names {
-			if strings.HasPrefix(n.Name, prefix) && n.Name != prefix {
-				n.Name = n.Name[len(prefix):]
+			if n.Name != prefix {
+				n.Name = strings.TrimPrefix(n.Name, prefix)
 			}
 			if n.Name == "_" {
 				// Use exported name instead.
@@ -1522,7 +1599,7 @@ func godefsFields(fld []*ast.Field) {
 }
 
 // fieldPrefix returns the prefix that should be removed from all the
-// field names when generating the C or Go code.  For generated 
+// field names when generating the C or Go code.  For generated
 // C, we leave the names as is (tv_sec, tv_usec), since that's what
 // people are used to seeing in C.  For generated Go code, such as
 // package syscall's data structures, we drop a common prefix
@@ -1539,7 +1616,7 @@ func fieldPrefix(fld []*ast.Field) string {
 			// named, say, _pad in an otherwise prefixed header.
 			// If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
 			// still want to remove the tv_ prefix.
-			// The check for "orig_" here handles orig_eax in the 
+			// The check for "orig_" here handles orig_eax in the
 			// x86 ptrace register sets, which otherwise have all fields
 			// with reg_ prefixes.
 			if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
diff --git a/src/cmd/cgo/godefs.go b/src/cmd/cgo/godefs.go
index fec70a3..2037617 100644
--- a/src/cmd/cgo/godefs.go
+++ b/src/cmd/cgo/godefs.go
@@ -180,7 +180,7 @@ func (p *Package) cdefs(f *File, srcfile string) string {
 			for _, line := range lines {
 				line = strings.TrimSpace(line)
 				if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
-					s := line[len("type ") : len(line)-len(" struct {")]
+					s := strings.TrimSuffix(strings.TrimPrefix(line, "type "), " struct {")
 					printf("typedef struct %s %s;\n", s, s)
 				}
 			}
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 6016596..7adc795 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -31,6 +31,7 @@ type Package struct {
 	PackageName string // name of package
 	PackagePath string
 	PtrSize     int64
+	IntSize     int64
 	GccOptions  []string
 	CgoFlags    map[string]string // #cgo flags (CFLAGS, LDFLAGS)
 	Written     map[string]bool
@@ -129,12 +130,19 @@ var ptrSizeMap = map[string]int64{
 	"arm":   4,
 }
 
+var intSizeMap = map[string]int64{
+	"386":   4,
+	"amd64": 8,
+	"arm":   4,
+}
+
 var cPrefix string
 
 var fset = token.NewFileSet()
 
 var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file")
 var dynout = flag.String("dynout", "", "write -dynobj output to this file")
+var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in dynimport mode")
 
 // These flags are for bootstrapping a new Go implementation,
 // to generate Go and C headers that match the data layout and
@@ -144,8 +152,10 @@ var cdefs = flag.Bool("cdefs", false, "for bootstrap: write C definitions for C
 var objDir = flag.String("objdir", "", "object directory")
 
 var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
-var gccgoprefix = flag.String("gccgoprefix", "go", "prefix of symbols generated by gccgo")
+var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo")
+var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used with gccgo")
 var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code")
+var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code")
 var goarch, goos string
 
 func main() {
@@ -287,7 +297,11 @@ func newPackage(args []string) *Package {
 	}
 	ptrSize := ptrSizeMap[goarch]
 	if ptrSize == 0 {
-		fatalf("unknown $GOARCH %q", goarch)
+		fatalf("unknown ptrSize for $GOARCH %q", goarch)
+	}
+	intSize := intSizeMap[goarch]
+	if intSize == 0 {
+		fatalf("unknown intSize for $GOARCH %q", goarch)
 	}
 
 	// Reset locale variables so gcc emits English errors [sic].
@@ -296,6 +310,7 @@ func newPackage(args []string) *Package {
 
 	p := &Package{
 		PtrSize:    ptrSize,
+		IntSize:    intSize,
 		GccOptions: gccOptions,
 		CgoFlags:   make(map[string]string),
 		Written:    make(map[string]bool),
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 5dfc16a..a126cf1 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -14,6 +14,7 @@ import (
 	"go/printer"
 	"go/token"
 	"os"
+	"sort"
 	"strings"
 )
 
@@ -26,6 +27,8 @@ func (p *Package) writeDefs() {
 	fc := creat(*objDir + "_cgo_defun.c")
 	fm := creat(*objDir + "_cgo_main.c")
 
+	var gccgoInit bytes.Buffer
+
 	fflg := creat(*objDir + "_cgo_flags")
 	for k, v := range p.CgoFlags {
 		fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, v)
@@ -50,19 +53,33 @@ 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")
-	fmt.Fprintf(fgo2, "import \"syscall\"\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")
-	fmt.Fprintf(fgo2, "func _Cerrno(dst *error, x int) { *dst = syscall.Errno(x) }\n")
+	if *importSyscall {
+		fmt.Fprintf(fgo2, "func _Cerrno(dst *error, x int32) { *dst = syscall.Errno(x) }\n")
+	}
 
-	for name, def := range typedef {
+	typedefNames := make([]string, 0, len(typedef))
+	for name := range typedef {
+		typedefNames = append(typedefNames, name)
+	}
+	sort.Strings(typedefNames)
+	for _, name := range typedefNames {
+		def := typedef[name]
 		fmt.Fprintf(fgo2, "type %s ", name)
 		conf.Fprint(fgo2, fset, def.Go)
 		fmt.Fprintf(fgo2, "\n\n")
 	}
-	fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n")
+	if *gccgo {
+		fmt.Fprintf(fgo2, "type _Ctype_void byte\n")
+	} else {
+		fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n")
+	}
 
 	if *gccgo {
 		fmt.Fprintf(fc, cPrologGccgo)
@@ -70,6 +87,8 @@ func (p *Package) writeDefs() {
 		fmt.Fprintf(fc, cProlog)
 	}
 
+	gccgoSymbolPrefix := p.gccgoSymbolPrefix()
+
 	cVars := make(map[string]bool)
 	for _, key := range nameKeys(p.Name) {
 		n := p.Name[key]
@@ -86,7 +105,12 @@ func (p *Package) writeDefs() {
 			cVars[n.C] = true
 		}
 
-		fmt.Fprintf(fc, "void *·%s = &%s;\n", n.Mangle, n.C)
+		if *gccgo {
+			fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
+			fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
+		} else {
+			fmt.Fprintf(fc, "void *·%s = &%s;\n", n.Mangle, n.C)
+		}
 		fmt.Fprintf(fc, "\n")
 
 		fmt.Fprintf(fgo2, "var %s ", n.Mangle)
@@ -116,6 +140,14 @@ func (p *Package) writeDefs() {
 		p.writeExports(fgo2, fc, fm)
 	}
 
+	init := gccgoInit.String()
+	if init != "" {
+		fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));")
+		fmt.Fprintln(fc, "static void init(void) {")
+		fmt.Fprint(fc, init)
+		fmt.Fprintln(fc, "}")
+	}
+
 	fgo2.Close()
 	fc.Close()
 }
@@ -131,6 +163,15 @@ func dynimport(obj string) {
 	}
 
 	if f, err := elf.Open(obj); err == nil {
+		if *dynlinker {
+			// Emit the cgo_dynamic_linker line.
+			if sec := f.Section(".interp"); sec != nil {
+				if data, err := sec.Data(); err == nil && len(data) > 1 {
+					// skip trailing \0 in data
+					fmt.Fprintf(stdout, "#pragma cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
+				}
+			}
+		}
 		sym, err := f.ImportedSymbols()
 		if err != nil {
 			fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
@@ -138,16 +179,16 @@ func dynimport(obj string) {
 		for _, s := range sym {
 			targ := s.Name
 			if s.Version != "" {
-				targ += "@" + s.Version
+				targ += "#" + s.Version
 			}
-			fmt.Fprintf(stdout, "#pragma dynimport %s %s %q\n", s.Name, targ, s.Library)
+			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
 		}
 		lib, err := f.ImportedLibraries()
 		if err != nil {
 			fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
 		}
 		for _, l := range lib {
-			fmt.Fprintf(stdout, "#pragma dynimport _ _ %q\n", l)
+			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
 		}
 		return
 	}
@@ -161,14 +202,14 @@ func dynimport(obj string) {
 			if len(s) > 0 && s[0] == '_' {
 				s = s[1:]
 			}
-			fmt.Fprintf(stdout, "#pragma dynimport %s %s %q\n", s, s, "")
+			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "")
 		}
 		lib, err := f.ImportedLibraries()
 		if err != nil {
 			fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
 		}
 		for _, l := range lib {
-			fmt.Fprintf(stdout, "#pragma dynimport _ _ %q\n", l)
+			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
 		}
 		return
 	}
@@ -180,7 +221,8 @@ func dynimport(obj string) {
 		}
 		for _, s := range sym {
 			ss := strings.Split(s, ":")
-			fmt.Fprintf(stdout, "#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1]))
+			name := strings.Split(ss[0], "@")[0]
+			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
 		}
 		return
 	}
@@ -247,6 +289,7 @@ func (p *Package) structType(n *Name) (string, int64) {
 func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
 	name := n.Go
 	gtype := n.FuncType.Go
+	void := gtype.Results == nil || len(gtype.Results.List) == 0
 	if n.AddError {
 		// Add "error" to return type list.
 		// Type list is known to be 0 or 1 element - it's a C function.
@@ -271,38 +314,58 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
 
 	if *gccgo {
 		// Gccgo style hooks.
-		// we hook directly into C. gccgo goes not support cgocall yet.
-		if !n.AddError {
-			fmt.Fprintf(fgo2, "//extern %s\n", n.C)
-			conf.Fprint(fgo2, fset, d)
-			fmt.Fprint(fgo2, "\n")
-		} else {
-			// write a small wrapper to retrieve errno.
-			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)
+		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")
+		fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
+		fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
+		if n.AddError {
+			fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
+		}
+		fmt.Fprint(fgo2, "\t")
+		if !void {
+			fmt.Fprint(fgo2, "r := ")
+		}
+		fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", "))
+
+		if n.AddError {
+			fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n")
+			fmt.Fprint(fgo2, "\tif e != 0 {\n")
+			fmt.Fprint(fgo2, "\t\treturn ")
+			if !void {
+				fmt.Fprint(fgo2, "r, ")
 			}
-			conf.Fprint(fgo2, fset, d)
-			fmt.Fprintf(fgo2, "{\n")
-			fmt.Fprintf(fgo2, "\tsyscall.SetErrno(0)\n")
-			fmt.Fprintf(fgo2, "\tr := %s(%s)\n", cname, strings.Join(paramnames, ", "))
-			fmt.Fprintf(fgo2, "\te := syscall.GetErrno()\n")
-			fmt.Fprintf(fgo2, "\tif e != 0 {\n")
-			fmt.Fprintf(fgo2, "\t\treturn r, e\n")
-			fmt.Fprintf(fgo2, "\t}\n")
-			fmt.Fprintf(fgo2, "\treturn r, nil\n")
-			fmt.Fprintf(fgo2, "}\n")
-			// declare the C function.
-			fmt.Fprintf(fgo2, "//extern %s\n", n.C)
-			d.Name = ast.NewIdent(cname)
+			fmt.Fprint(fgo2, "e\n")
+			fmt.Fprint(fgo2, "\t}\n")
+			fmt.Fprint(fgo2, "\treturn ")
+			if !void {
+				fmt.Fprint(fgo2, "r, ")
+			}
+			fmt.Fprint(fgo2, "nil\n")
+		} else if !void {
+			fmt.Fprint(fgo2, "\treturn r\n")
+		}
+
+		fmt.Fprint(fgo2, "}\n")
+
+		// declare the C function.
+		fmt.Fprintf(fgo2, "//extern %s\n", n.C)
+		d.Name = ast.NewIdent(cname)
+		if n.AddError {
 			l := d.Type.Results.List
 			d.Type.Results.List = l[:len(l)-1]
-			conf.Fprint(fgo2, fset, d)
-			fmt.Fprint(fgo2, "\n")
 		}
+		conf.Fprint(fgo2, fset, d)
+		fmt.Fprint(fgo2, "\n")
+
 		return
 	}
 	conf.Fprint(fgo2, fset, d)
@@ -317,6 +380,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
 	_, 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")
@@ -456,11 +520,13 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
 
 	fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
 	fmt.Fprintf(fgcch, "%s\n", p.Preamble)
-	fmt.Fprintf(fgcch, "%s\n", gccExportHeaderProlog)
+	fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
 
 	fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
 	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
 
+	fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n")
+
 	for _, exp := range p.ExpFunc {
 		fn := exp.Func
 
@@ -552,7 +618,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
 		s += ")"
 		fmt.Fprintf(fgcch, "\nextern %s;\n", s)
 
-		fmt.Fprintf(fgcc, "extern _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
+		fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
 		fmt.Fprintf(fgcc, "\n%s\n", s)
 		fmt.Fprintf(fgcc, "{\n")
 		fmt.Fprintf(fgcc, "\t%s __attribute__((packed)) a;\n", ctype)
@@ -585,7 +651,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
 		if fn.Recv != nil {
 			goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
 		}
-		fmt.Fprintf(fc, "#pragma dynexport %s %s\n", goname, goname)
+		fmt.Fprintf(fc, "#pragma cgo_export %s\n", goname)
 		fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
 		fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
 		fmt.Fprintf(fc, "void\n")
@@ -641,32 +707,22 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
 func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
 	fgcc := creat(*objDir + "_cgo_export.c")
 	fgcch := creat(*objDir + "_cgo_export.h")
-	_ = fgcc
+
+	gccgoSymbolPrefix := p.gccgoSymbolPrefix()
 
 	fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
 	fmt.Fprintf(fgcch, "%s\n", p.Preamble)
-	fmt.Fprintf(fgcch, "%s\n", gccExportHeaderProlog)
-	fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n")
+	fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
 
-	clean := func(r rune) rune {
-		switch {
-		case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
-			'0' <= r && r <= '9':
-			return r
-		}
-		return '_'
-	}
-	gccgoSymbolPrefix := strings.Map(clean, *gccgoprefix)
+	fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
+	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
+
+	fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n")
 
 	for _, exp := range p.ExpFunc {
-		// TODO: support functions with receivers.
 		fn := exp.Func
 		fntype := fn.Type
 
-		if !ast.IsExported(fn.Name.Name) {
-			fatalf("cannot export unexported function %s with gccgo", fn.Name)
-		}
-
 		cdeclBuf := new(bytes.Buffer)
 		resultCount := 0
 		forFieldList(fntype.Results,
@@ -692,28 +748,135 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
 			fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName)
 		}
 
-		// The function name.
-		fmt.Fprintf(cdeclBuf, " "+exp.ExpName)
-		gccgoSymbol := fmt.Sprintf("%s.%s.%s", gccgoSymbolPrefix, p.PackageName, exp.Func.Name)
-		fmt.Fprintf(cdeclBuf, " (")
+		cRet := cdeclBuf.String()
+
+		cdeclBuf = new(bytes.Buffer)
+		fmt.Fprintf(cdeclBuf, "(")
+		if fn.Recv != nil {
+			fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String())
+		}
 		// Function parameters.
 		forFieldList(fntype.Params,
 			func(i int, atype ast.Expr) {
-				if i > 0 {
+				if i > 0 || fn.Recv != nil {
 					fmt.Fprintf(cdeclBuf, ", ")
 				}
 				t := p.cgoType(atype)
 				fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i)
 			})
 		fmt.Fprintf(cdeclBuf, ")")
-		cdecl := cdeclBuf.String()
+		cParams := cdeclBuf.String()
+
+		goName := "Cgoexp_" + exp.ExpName
+		fmt.Fprintf(fgcch, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
+		fmt.Fprint(fgcch, "\n")
+
+		fmt.Fprint(fgcc, "\n")
+		fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
+		fmt.Fprint(fgcc, "\t")
+		if resultCount > 0 {
+			fmt.Fprint(fgcc, "return ")
+		}
+		fmt.Fprintf(fgcc, "%s(", goName)
+		if fn.Recv != nil {
+			fmt.Fprint(fgcc, "recv")
+		}
+		forFieldList(fntype.Params,
+			func(i int, atype ast.Expr) {
+				if i > 0 || fn.Recv != nil {
+					fmt.Fprintf(fgcc, ", ")
+				}
+				fmt.Fprintf(fgcc, "p%d", i)
+			})
+		fmt.Fprint(fgcc, ");\n")
+		fmt.Fprint(fgcc, "}\n")
 
-		fmt.Fprintf(fgcch, "extern %s __asm__(\"%s\");\n", cdecl, gccgoSymbol)
 		// Dummy declaration for _cgo_main.c
-		fmt.Fprintf(fm, "%s {}\n", cdecl)
+		fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams)
+
+		// For gccgo we use a wrapper function in Go, in order
+		// to call CgocallBack and CgocallBackDone.
+
+		// This code uses printer.Fprint, not conf.Fprint,
+		// because we don't want //line comments in the middle
+		// of the function types.
+		fmt.Fprint(fgo2, "\n")
+		fmt.Fprintf(fgo2, "func %s(", goName)
+		if fn.Recv != nil {
+			fmt.Fprint(fgo2, "recv ")
+			printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
+		}
+		forFieldList(fntype.Params,
+			func(i int, atype ast.Expr) {
+				if i > 0 || fn.Recv != nil {
+					fmt.Fprintf(fgo2, ", ")
+				}
+				fmt.Fprintf(fgo2, "p%d ", i)
+				printer.Fprint(fgo2, fset, atype)
+			})
+		fmt.Fprintf(fgo2, ")")
+		if resultCount > 0 {
+			fmt.Fprintf(fgo2, " (")
+			forFieldList(fntype.Results,
+				func(i int, atype ast.Expr) {
+					if i > 0 {
+						fmt.Fprint(fgo2, ", ")
+					}
+					printer.Fprint(fgo2, fset, atype)
+				})
+			fmt.Fprint(fgo2, ")")
+		}
+		fmt.Fprint(fgo2, " {\n")
+		fmt.Fprint(fgo2, "\tsyscall.CgocallBack()\n")
+		fmt.Fprint(fgo2, "\tdefer syscall.CgocallBackDone()\n")
+		fmt.Fprint(fgo2, "\t")
+		if resultCount > 0 {
+			fmt.Fprint(fgo2, "return ")
+		}
+		if fn.Recv != nil {
+			fmt.Fprint(fgo2, "recv.")
+		}
+		fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
+		forFieldList(fntype.Params,
+			func(i int, atype ast.Expr) {
+				if i > 0 {
+					fmt.Fprint(fgo2, ", ")
+				}
+				fmt.Fprintf(fgo2, "p%d", i)
+			})
+		fmt.Fprint(fgo2, ")\n")
+		fmt.Fprint(fgo2, "}\n")
 	}
 }
 
+// Return the package prefix when using gccgo.
+func (p *Package) gccgoSymbolPrefix() string {
+	if !*gccgo {
+		return ""
+	}
+
+	clean := func(r rune) rune {
+		switch {
+		case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
+			'0' <= r && r <= '9':
+			return r
+		}
+		return '_'
+	}
+
+	if *gccgopkgpath != "" {
+		return strings.Map(clean, *gccgopkgpath)
+	}
+	if *gccgoprefix == "" && p.PackageName == "main" {
+		return "main"
+	}
+	prefix := strings.Map(clean, *gccgoprefix)
+	if prefix == "" {
+		prefix = "go"
+	}
+	return prefix + "." + p.PackageName
+}
+
 // Call a function for each entry in an ast.FieldList, passing the
 // index into the list and the type.
 func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
@@ -742,8 +905,8 @@ func c(repr string, args ...interface{}) *TypeRepr {
 var goTypes = map[string]*Type{
 	"bool":       {Size: 1, Align: 1, C: c("GoUint8")},
 	"byte":       {Size: 1, Align: 1, C: c("GoUint8")},
-	"int":        {Size: 4, Align: 4, C: c("GoInt")},
-	"uint":       {Size: 4, Align: 4, C: c("GoUint")},
+	"int":        {Size: 0, Align: 0, C: c("GoInt")},
+	"uint":       {Size: 0, Align: 0, C: c("GoUint")},
 	"rune":       {Size: 4, Align: 4, C: c("GoInt32")},
 	"int8":       {Size: 1, Align: 1, C: c("GoInt8")},
 	"uint8":      {Size: 1, Align: 1, C: c("GoUint8")},
@@ -804,12 +967,21 @@ func (p *Package) cgoType(e ast.Expr) *Type {
 			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")}
 		}
 		if t.Name == "string" {
-			return &Type{Size: p.PtrSize + 4, Align: p.PtrSize, C: c("GoString")}
+			// The string data is 1 pointer + 1 int, but this always
+			// rounds to 2 pointers due to alignment.
+			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")}
 		}
 		if t.Name == "error" {
 			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
 		}
 		if r, ok := goTypes[t.Name]; ok {
+			if r.Size == 0 { // int or uint
+				rr := new(Type)
+				*rr = *r
+				rr.Size = p.IntSize
+				rr.Align = p.IntSize
+				r = rr
+			}
 			if r.Align > p.PtrSize {
 				r.Align = p.PtrSize
 			}
@@ -898,18 +1070,21 @@ const cPrologGccgo = `
 #include <stdint.h>
 #include <string.h>
 
+typedef unsigned char byte;
+typedef intptr_t intgo;
+
 struct __go_string {
 	const unsigned char *__data;
-	int __length;
+	intgo __length;
 };
 
 typedef struct __go_open_array {
 	void* __values;
-	int __count;
-	int __capacity;
+	intgo __count;
+	intgo __capacity;
 } Slice;
 
-struct __go_string __go_byte_array_to_string(const void* p, int len);
+struct __go_string __go_byte_array_to_string(const void* p, intgo len);
 struct __go_open_array __go_string_to_byte_array (struct __go_string str);
 
 const char *CString(struct __go_string s) {
@@ -917,23 +1092,25 @@ const char *CString(struct __go_string s) {
 }
 
 struct __go_string GoString(char *p) {
-	int len = (p != NULL) ? strlen(p) : 0;
+	intgo len = (p != NULL) ? strlen(p) : 0;
 	return __go_byte_array_to_string(p, len);
 }
 
-struct __go_string GoStringN(char *p, int n) {
+struct __go_string GoStringN(char *p, intgo n) {
 	return __go_byte_array_to_string(p, n);
 }
 
-Slice GoBytes(char *p, int n) {
+Slice GoBytes(char *p, intgo n) {
 	struct __go_string s = { (const unsigned char *)p, n };
 	return __go_string_to_byte_array(s);
 }
 `
 
+func (p *Package) gccExportHeaderProlog() string {
+	return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1)
+}
+
 const gccExportHeaderProlog = `
-typedef int GoInt;
-typedef unsigned int GoUint;
 typedef signed char GoInt8;
 typedef unsigned char GoUint8;
 typedef short GoInt16;
@@ -942,6 +1119,8 @@ typedef int GoInt32;
 typedef unsigned int GoUint32;
 typedef long long GoInt64;
 typedef unsigned long long GoUint64;
+typedef GoIntGOINTBITS GoInt;
+typedef GoUintGOINTBITS GoUint;
 typedef __SIZE_TYPE__ GoUintptr;
 typedef float GoFloat32;
 typedef double GoFloat64;
@@ -952,4 +1131,5 @@ typedef struct { char *p; int n; } GoString;
 typedef void *GoMap;
 typedef void *GoChan;
 typedef struct { void *t; void *v; } GoInterface;
+typedef struct { void *data; int len; int cap; } GoSlice;
 `
diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go
index a0f2166..4e7800d 100644
--- a/src/cmd/cgo/util.go
+++ b/src/cmd/cgo/util.go
@@ -5,9 +5,9 @@
 package main
 
 import (
+	"bytes"
 	"fmt"
 	"go/token"
-	"io/ioutil"
 	"os"
 	"os/exec"
 )
@@ -16,50 +16,17 @@ import (
 // It returns the output to standard output and standard error.
 // ok indicates whether the command exited successfully.
 func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
-	cmd, err := exec.LookPath(argv[0])
-	if err != nil {
-		fatalf("exec %s: %s", argv[0], err)
-	}
-	r0, w0, err := os.Pipe()
-	if err != nil {
-		fatalf("%s", err)
-	}
-	r1, w1, err := os.Pipe()
-	if err != nil {
-		fatalf("%s", err)
-	}
-	r2, w2, err := os.Pipe()
-	if err != nil {
-		fatalf("%s", err)
-	}
-	p, err := os.StartProcess(cmd, argv, &os.ProcAttr{Files: []*os.File{r0, w1, w2}})
-	if err != nil {
-		fatalf("%s", err)
-	}
-	r0.Close()
-	w1.Close()
-	w2.Close()
-	c := make(chan bool)
-	go func() {
-		w0.Write(stdin)
-		w0.Close()
-		c <- true
-	}()
-	go func() {
-		stdout, _ = ioutil.ReadAll(r1)
-		r1.Close()
-		c <- true
-	}()
-	stderr, _ = ioutil.ReadAll(r2)
-	r2.Close()
-	<-c
-	<-c
-
-	state, err := p.Wait()
-	if err != nil {
+	p := exec.Command(argv[0], argv[1:]...)
+	p.Stdin = bytes.NewReader(stdin)
+	var bout, berr bytes.Buffer
+	p.Stdout = &bout
+	p.Stderr = &berr
+	err := p.Run()
+	if _, ok := err.(*exec.ExitError); err != nil && !ok {
 		fatalf("%s", err)
 	}
-	ok = state.Success()
+	ok = p.ProcessState.Success()
+	stdout, stderr = bout.Bytes(), berr.Bytes()
 	return
 }
 
diff --git a/src/cmd/5c/Makefile b/src/cmd/cov/Makefile
similarity index 100%
copy from src/cmd/5c/Makefile
copy to src/cmd/cov/Makefile
diff --git a/src/cmd/cov/doc.go b/src/cmd/cov/doc.go
new file mode 100644
index 0000000..ab5d122
--- /dev/null
+++ b/src/cmd/cov/doc.go
@@ -0,0 +1,36 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+
+Cov is a rudimentary code coverage tool.
+
+Usage:
+	go tool cov [-lsv] [-g substring] [-m minlines] [6.out args]
+
+Given a command to run, it runs the command while tracking which
+sections of code have been executed.  When the command finishes,
+cov prints the line numbers of sections of code in the binary that
+were not executed.   With no arguments it assumes the command "6.out".
+
+
+The options are:
+
+	-l
+		print full path names instead of paths relative to the current directory
+	-s
+		show the source code that didn't execute, in addition to the line numbers.
+	-v
+		print debugging information during the run.
+	-g substring
+		restrict the coverage analysis to functions or files whose names contain substring
+	-m minlines
+		only report uncovered sections of code larger than minlines lines
+
+The program is the same for all architectures: 386, amd64, and arm.
+
+*/
+package main
diff --git a/src/cmd/cov/main.c b/src/cmd/cov/main.c
new file mode 100644
index 0000000..33ef49e
--- /dev/null
+++ b/src/cmd/cov/main.c
@@ -0,0 +1,484 @@
+// 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.
+
+/*
+ * code coverage
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "tree.h"
+
+#include <ureg_amd64.h>
+#include <mach.h>
+typedef struct Ureg Ureg;
+
+void
+usage(void)
+{
+	fprint(2, "usage: cov [-lsv] [-g substring] [-m minlines] [6.out args...]\n");
+	fprint(2, "-g specifies pattern of interesting functions or files\n");
+	exits("usage");
+}
+
+typedef struct Range Range;
+struct Range
+{
+	uvlong pc;
+	uvlong epc;
+};
+
+int chatty;
+int fd;
+int longnames;
+int pid;
+int doshowsrc;
+Map *mem;
+Map *text;
+Fhdr fhdr;
+char *substring;
+char cwd[1000];
+int ncwd;
+int minlines = -1000;
+
+Tree breakpoints;	// code ranges not run
+
+/*
+ * comparison for Range structures
+ * they are "equal" if they overlap, so
+ * that a search for [pc, pc+1) finds the
+ * Range containing pc.
+ */
+int
+rangecmp(void *va, void *vb)
+{
+	Range *a = va, *b = vb;
+	if(a->epc <= b->pc)
+		return 1;
+	if(b->epc <= a->pc)
+		return -1;
+	return 0;
+}
+
+/*
+ * remember that we ran the section of code [pc, epc).
+ */
+void
+ran(uvlong pc, uvlong epc)
+{
+	Range key;
+	Range *r;
+	uvlong oldepc;
+
+	if(chatty)
+		print("run %#llux-%#llux\n", pc, epc);
+
+	key.pc = pc;
+	key.epc = pc+1;
+	r = treeget(&breakpoints, &key);
+	if(r == nil)
+		sysfatal("unchecked breakpoint at %#llux+%d", pc, (int)(epc-pc));
+
+	// Might be that the tail of the sequence
+	// was run already, so r->epc is before the end.
+	// Adjust len.
+	if(epc > r->epc)
+		epc = r->epc;
+
+	if(r->pc == pc) {
+		r->pc = epc;
+	} else {
+		// Chop r to before pc;
+		// add new entry for after if needed.
+		// Changing r->epc does not affect r's position in the tree.
+		oldepc = r->epc;
+		r->epc = pc;
+		if(epc < oldepc) {
+			Range *n;
+			n = malloc(sizeof *n);
+			if(n == nil)
+				sysfatal("out of memory");
+			n->pc = epc;
+			n->epc = oldepc;
+			treeput(&breakpoints, n, n);
+		}
+	}
+}
+
+void
+showsrc(char *file, int line1, int line2)
+{
+	Biobuf *b;
+	char *p;
+	int n, stop;
+
+	if((b = Bopen(file, OREAD)) == nil) {
+		print("\topen %s: %r\n", file);
+		return;
+	}
+
+	for(n=1; n<line1 && (p = Brdstr(b, '\n', 1)) != nil; n++)
+		free(p);
+
+	// print up to five lines (this one and 4 more).
+	// if there are more than five lines, print 4 and "..."
+	stop = n+4;
+	if(stop > line2)
+		stop = line2;
+	if(stop < line2)
+		stop--;
+	for(; n<=stop && (p = Brdstr(b, '\n', 1)) != nil; n++) {
+		print("  %d %s\n", n, p);
+		free(p);
+	}
+	if(n < line2)
+		print("  ...\n");
+	Bterm(b);
+}
+
+/*
+ * if s is in the current directory or below,
+ * return the relative path.
+ */
+char*
+shortname(char *s)
+{
+	if(!longnames && strlen(s) > ncwd && memcmp(s, cwd, ncwd) == 0 && s[ncwd] == '/')
+		return s+ncwd+1;
+	return s;
+}
+
+/*
+ * we've decided that [pc, epc) did not run.
+ * do something about it.
+ */
+void
+missing(uvlong pc, uvlong epc)
+{
+	char file[1000];
+	int line1, line2;
+	char buf[100];
+	Symbol s;
+	char *p;
+	uvlong uv;
+
+	if(!findsym(pc, CTEXT, &s) || !fileline(file, sizeof file, pc)) {
+	notfound:
+		print("%#llux-%#llux\n", pc, epc);
+		return;
+	}
+	p = strrchr(file, ':');
+	*p++ = 0;
+	line1 = atoi(p);
+	for(uv=pc; uv<epc; ) {
+		if(!fileline(file, sizeof file, epc-2))
+			goto notfound;
+		uv += machdata->instsize(text, uv);
+	}
+	p = strrchr(file, ':');
+	*p++ = 0;
+	line2 = atoi(p);
+
+	if(line2+1-line2 < minlines)
+		return;
+
+	if(pc == s.value) {
+		// never entered function
+		print("%s:%d %s never called (%#llux-%#llux)\n", shortname(file), line1, s.name, pc, epc);
+		return;
+	}
+	if(pc <= s.value+13) {
+		// probably stub for stack growth.
+		// check whether last instruction is call to morestack.
+		// the -5 below is the length of
+		//	CALL sys.morestack.
+		buf[0] = 0;
+		machdata->das(text, epc-5, 0, buf, sizeof buf);
+		if(strstr(buf, "morestack"))
+			return;
+	}
+
+	if(epc - pc == 5) {
+		// check for CALL sys.panicindex
+		buf[0] = 0;
+		machdata->das(text, pc, 0, buf, sizeof buf);
+		if(strstr(buf, "panicindex"))
+			return;
+	}
+
+	if(epc - pc == 2 || epc -pc == 3) {
+		// check for XORL inside shift.
+		// (on x86 have to implement large left or unsigned right shift with explicit zeroing).
+		//	f+90 0x00002c9f	CMPL	CX,$20
+		//	f+93 0x00002ca2	JCS	f+97(SB)
+		//	f+95 0x00002ca4	XORL	AX,AX <<<
+		//	f+97 0x00002ca6	SHLL	CL,AX
+		//	f+99 0x00002ca8	MOVL	$1,CX
+		//
+		//	f+c8 0x00002cd7	CMPL	CX,$40
+		//	f+cb 0x00002cda	JCS	f+d0(SB)
+		//	f+cd 0x00002cdc	XORQ	AX,AX <<<
+		//	f+d0 0x00002cdf	SHLQ	CL,AX
+		//	f+d3 0x00002ce2	MOVQ	$1,CX
+		buf[0] = 0;
+		machdata->das(text, pc, 0, buf, sizeof buf);
+		if(strncmp(buf, "XOR", 3) == 0) {
+			machdata->das(text, epc, 0, buf, sizeof buf);
+			if(strncmp(buf, "SHL", 3) == 0 || strncmp(buf, "SHR", 3) == 0)
+				return;
+		}
+	}
+
+	if(epc - pc == 3) {
+		// check for SAR inside shift.
+		// (on x86 have to implement large signed right shift as >>31).
+		//	f+36 0x00016216	CMPL	CX,$20
+		//	f+39 0x00016219	JCS	f+3e(SB)
+		//	f+3b 0x0001621b	SARL	$1f,AX <<<
+		//	f+3e 0x0001621e	SARL	CL,AX
+		//	f+40 0x00016220	XORL	CX,CX
+		//	f+42 0x00016222	CMPL	CX,AX
+		buf[0] = 0;
+		machdata->das(text, pc, 0, buf, sizeof buf);
+		if(strncmp(buf, "SAR", 3) == 0) {
+			machdata->das(text, epc, 0, buf, sizeof buf);
+			if(strncmp(buf, "SAR", 3) == 0)
+				return;
+		}
+	}
+
+	// show first instruction to make clear where we were.
+	machdata->das(text, pc, 0, buf, sizeof buf);
+
+	if(line1 != line2)
+		print("%s:%d,%d %#llux-%#llux %s\n",
+			shortname(file), line1, line2, pc, epc, buf);
+	else
+		print("%s:%d %#llux-%#llux %s\n",
+			shortname(file), line1, pc, epc, buf);
+	if(doshowsrc)
+		showsrc(file, line1, line2);
+}
+
+/*
+ * walk the tree, calling missing for each non-empty
+ * section of missing code.
+ */
+void
+walktree(TreeNode *t)
+{
+	Range *n;
+
+	if(t == nil)
+		return;
+	walktree(t->left);
+	n = t->key;
+	if(n->pc < n->epc)
+		missing(n->pc, n->epc);
+	walktree(t->right);
+}
+
+/*
+ * set a breakpoint all over [pc, epc)
+ * and remember that we did.
+ */
+void
+breakpoint(uvlong pc, uvlong epc)
+{
+	Range *r;
+
+	r = malloc(sizeof *r);
+	if(r == nil)
+		sysfatal("out of memory");
+	r->pc = pc;
+	r->epc = epc;
+	treeput(&breakpoints, r, r);
+
+	for(; pc < epc; pc+=machdata->bpsize)
+		put1(mem, pc, machdata->bpinst, machdata->bpsize);
+}
+
+/*
+ * install breakpoints over all text symbols
+ * that match the pattern.
+ */
+void
+cover(void)
+{
+	Symbol s;
+	char *lastfn;
+	uvlong lastpc;
+	int i;
+	char buf[200];
+
+	lastfn = nil;
+	lastpc = 0;
+	for(i=0; textsym(&s, i); i++) {
+		switch(s.type) {
+		case 'T':
+		case 't':
+			if(lastpc != 0) {
+				breakpoint(lastpc, s.value);
+				lastpc = 0;
+			}
+			// Ignore second entry for a given name;
+			// that's the debugging blob.
+			if(lastfn && strcmp(s.name, lastfn) == 0)
+				break;
+			lastfn = s.name;
+			buf[0] = 0;
+			fileline(buf, sizeof buf, s.value);
+			if(substring == nil || strstr(buf, substring) || strstr(s.name, substring))
+				lastpc = s.value;
+		}
+	}
+}
+
+uvlong
+rgetzero(Map *map, char *reg)
+{
+	USED(map);
+	USED(reg);
+
+	return 0;
+}
+
+/*
+ * remove the breakpoints at pc and successive instructions,
+ * up to and including the first jump or other control flow transfer.
+ */
+void
+uncover(uvlong pc)
+{
+	uchar buf[1000];
+	int n, n1, n2;
+	uvlong foll[2];
+
+	// Double-check that we stopped at a breakpoint.
+	if(get1(mem, pc, buf, machdata->bpsize) < 0)
+		sysfatal("read mem inst at %#llux: %r", pc);
+	if(memcmp(buf, machdata->bpinst, machdata->bpsize) != 0)
+		sysfatal("stopped at %#llux; not at breakpoint %d", pc, machdata->bpsize);
+
+	// Figure out how many bytes of straight-line code
+	// there are in the text starting at pc.
+	n = 0;
+	while(n < sizeof buf) {
+		n1 = machdata->instsize(text, pc+n);
+		if(n+n1 > sizeof buf)
+			break;
+		n2 = machdata->foll(text, pc+n, rgetzero, foll);
+		n += n1;
+		if(n2 != 1 || foll[0] != pc+n)
+			break;
+	}
+
+	// Record that this section of code ran.
+	ran(pc, pc+n);
+
+	// Put original instructions back.
+	if(get1(text, pc, buf, n) < 0)
+		sysfatal("get1: %r");
+	if(put1(mem, pc, buf, n) < 0)
+		sysfatal("put1: %r");
+}
+
+int
+startprocess(char **argv)
+{
+	int pid;
+
+	if((pid = fork()) < 0)
+		sysfatal("fork: %r");
+	if(pid == 0) {
+		pid = getpid();
+		if(ctlproc(pid, "hang") < 0)
+			sysfatal("ctlproc hang: %r");
+		exec(argv[0], argv);
+		sysfatal("exec %s: %r", argv[0]);
+	}
+	if(ctlproc(pid, "attached") < 0 || ctlproc(pid, "waitstop") < 0)
+		sysfatal("attach %d %s: %r", pid, argv[0]);
+	return pid;
+}
+
+int
+go(void)
+{
+	uvlong pc;
+	char buf[100];
+	int n;
+
+	for(n = 0;; n++) {
+		ctlproc(pid, "startstop");
+		if(get8(mem, offsetof(Ureg, ip), &pc) < 0) {
+			rerrstr(buf, sizeof buf);
+			if(strstr(buf, "exited") || strstr(buf, "No such process"))
+				return n;
+			sysfatal("cannot read pc: %r");
+		}
+		pc--;
+		if(put8(mem, offsetof(Ureg, ip), pc) < 0)
+			sysfatal("cannot write pc: %r");
+		uncover(pc);
+	}
+}
+
+void
+main(int argc, char **argv)
+{
+	int n;
+
+	ARGBEGIN{
+	case 'g':
+		substring = EARGF(usage());
+		break;
+	case 'l':
+		longnames++;
+		break;
+	case 'n':
+		minlines = atoi(EARGF(usage()));
+		break;
+	case 's':
+		doshowsrc = 1;
+		break;
+	case 'v':
+		chatty++;
+		break;
+	default:
+		usage();
+	}ARGEND
+
+	getwd(cwd, sizeof cwd);
+	ncwd = strlen(cwd);
+
+	if(argc == 0) {
+		*--argv = "6.out";
+	}
+	fd = open(argv[0], OREAD);
+	if(fd < 0)
+		sysfatal("open %s: %r", argv[0]);
+	if(crackhdr(fd, &fhdr) <= 0)
+		sysfatal("crackhdr: %r");
+	machbytype(fhdr.type);
+	if(syminit(fd, &fhdr) <= 0)
+		sysfatal("syminit: %r");
+	text = loadmap(nil, fd, &fhdr);
+	if(text == nil)
+		sysfatal("loadmap: %r");
+	pid = startprocess(argv);
+	mem = attachproc(pid, &fhdr);
+	if(mem == nil)
+		sysfatal("attachproc: %r");
+	breakpoints.cmp = rangecmp;
+	cover();
+	n = go();
+	walktree(breakpoints.root);
+	if(chatty)
+		print("%d breakpoints\n", n);
+	detachproc(mem);
+	exits(0);
+}
+
diff --git a/src/cmd/cov/tree.c b/src/cmd/cov/tree.c
new file mode 100644
index 0000000..366a47e
--- /dev/null
+++ b/src/cmd/cov/tree.c
@@ -0,0 +1,245 @@
+// Renamed from Map to Tree to avoid conflict with libmach.
+
+/*
+Copyright (c) 2003-2007 Russ Cox, Tom Bergan, Austin Clements,
+	Massachusetts Institute of Technology
+Portions Copyright (c) 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.
+*/
+
+// Mutable map structure, but still based on
+// Okasaki, Red Black Trees in a Functional Setting, JFP 1999,
+// which is a lot easier than the traditional red-black
+// and plenty fast enough for me.  (Also I could copy
+// and edit fmap.c.)
+
+#include <u.h>
+#include <libc.h>
+#include "tree.h"
+
+enum
+{
+	Red = 0,
+	Black = 1
+};
+
+
+// Red-black trees are binary trees with this property:
+//	1. No red node has a red parent.
+//	2. Every path from the root to a leaf contains the
+//		same number of black nodes.
+
+static TreeNode*
+rwTreeNode(TreeNode *p, int color, TreeNode *left, void *key, void *value, TreeNode *right)
+{
+	if(p == nil)
+		p = malloc(sizeof *p);
+	if(p == nil)
+		sysfatal("out of memory");
+	p->color = color;
+	p->left = left;
+	p->key = key;
+	p->value = value;
+	p->right = right;
+	return p;
+}
+
+static TreeNode*
+balance(TreeNode *m0)
+{
+	void *xk, *xv, *yk, *yv, *zk, *zv;
+	TreeNode *a, *b, *c, *d;
+	TreeNode *m1, *m2;
+	int color;
+	TreeNode *left, *right;
+	void *key, *value;
+
+	color = m0->color;
+	left = m0->left;
+	key = m0->key;
+	value = m0->value;
+	right = m0->right;
+
+	// Okasaki notation: (T is mkTreeNode, B is Black, R is Red, x, y, z are key-value.
+	//
+	// balance B (T R (T R a x b) y c) z d
+	// balance B (T R a x (T R b y c)) z d
+	// balance B a x (T R (T R b y c) z d)
+	// balance B a x (T R b y (T R c z d))
+	//
+	//     = T R (T B a x b) y (T B c z d)
+
+	if(color == Black){
+		if(left && left->color == Red){
+			if(left->left && left->left->color == Red){
+				a = left->left->left;
+				xk = left->left->key;
+				xv = left->left->value;
+				b = left->left->right;
+				yk = left->key;
+				yv = left->value;
+				c = left->right;
+				zk = key;
+				zv = value;
+				d = right;
+				m1 = left;
+				m2 = left->left;
+				goto hard;
+			}else if(left->right && left->right->color == Red){
+				a = left->left;
+				xk = left->key;
+				xv = left->value;
+				b = left->right->left;
+				yk = left->right->key;
+				yv = left->right->value;
+				c = left->right->right;
+				zk = key;
+				zv = value;
+				d = right;
+				m1 = left;
+				m2 = left->right;
+				goto hard;
+			}
+		}else if(right && right->color == Red){
+			if(right->left && right->left->color == Red){
+				a = left;
+				xk = key;
+				xv = value;
+				b = right->left->left;
+				yk = right->left->key;
+				yv = right->left->value;
+				c = right->left->right;
+				zk = right->key;
+				zv = right->value;
+				d = right->right;
+				m1 = right;
+				m2 = right->left;
+				goto hard;
+			}else if(right->right && right->right->color == Red){
+				a = left;
+				xk = key;
+				xv = value;
+				b = right->left;
+				yk = right->key;
+				yv = right->value;
+				c = right->right->left;
+				zk = right->right->key;
+				zv = right->right->value;
+				d = right->right->right;
+				m1 = right;
+				m2 = right->right;
+				goto hard;
+			}
+		}
+	}
+	return rwTreeNode(m0, color, left, key, value, right);
+
+hard:
+	return rwTreeNode(m0, Red, rwTreeNode(m1, Black, a, xk, xv, b),
+		yk, yv, rwTreeNode(m2, Black, c, zk, zv, d));
+}
+
+static TreeNode*
+ins0(TreeNode *p, void *k, void *v, TreeNode *rw)
+{
+	if(p == nil)
+		return rwTreeNode(rw, Red, nil, k, v, nil);
+	if(p->key == k){
+		if(rw)
+			return rwTreeNode(rw, p->color, p->left, k, v, p->right);
+		p->value = v;
+		return p;
+	}
+	if(p->key < k)
+		p->left = ins0(p->left, k, v, rw);
+	else
+		p->right = ins0(p->right, k, v, rw);
+	return balance(p);
+}
+
+static TreeNode*
+ins1(Tree *m, TreeNode *p, void *k, void *v, TreeNode *rw)
+{
+	int i;
+
+	if(p == nil)
+		return rwTreeNode(rw, Red, nil, k, v, nil);
+	i = m->cmp(p->key, k);
+	if(i == 0){
+		if(rw)
+			return rwTreeNode(rw, p->color, p->left, k, v, p->right);
+		p->value = v;
+		return p;
+	}
+	if(i < 0)
+		p->left = ins1(m, p->left, k, v, rw);
+	else
+		p->right = ins1(m, p->right, k, v, rw);
+	return balance(p);
+}
+
+void
+treeputelem(Tree *m, void *key, void *val, TreeNode *rw)
+{
+	if(m->cmp)
+		m->root = ins1(m, m->root, key, val, rw);
+	else
+		m->root = ins0(m->root, key, val, rw);
+}
+
+void
+treeput(Tree *m, void *key, void *val)
+{
+	treeputelem(m, key, val, nil);
+}
+
+void*
+treeget(Tree *m, void *key)
+{
+	int i;
+	TreeNode *p;
+
+	p = m->root;
+	if(m->cmp){
+		for(;;){
+			if(p == nil)
+				return nil;
+			i = m->cmp(p->key, key);
+			if(i < 0)
+				p = p->left;
+			else if(i > 0)
+				p = p->right;
+			else
+				return p->value;
+		}
+	}else{
+		for(;;){
+			if(p == nil)
+				return nil;
+			if(p->key == key)
+				return p->value;
+			if(p->key < key)
+				p = p->left;
+			else
+				p = p->right;
+		}
+	}
+}
diff --git a/src/cmd/cov/tree.h b/src/cmd/cov/tree.h
new file mode 100644
index 0000000..a716d83
--- /dev/null
+++ b/src/cmd/cov/tree.h
@@ -0,0 +1,47 @@
+// Renamed from Map to Tree to avoid conflict with libmach.
+
+/*
+Copyright (c) 2003-2007 Russ Cox, Tom Bergan, Austin Clements,
+                        Massachusetts Institute of Technology
+Portions Copyright (c) 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.
+*/
+
+typedef struct Tree Tree;
+typedef struct TreeNode TreeNode;
+struct Tree
+{
+        int (*cmp)(void*, void*);
+        TreeNode *root;
+};
+
+struct TreeNode
+{
+        int color;
+        TreeNode *left;
+        void *key;
+        void *value;
+        TreeNode *right;
+};
+
+void *treeget(Tree*, void*);
+void treeput(Tree*, void*, void*);
+void treeputelem(Tree*, void*, void*, TreeNode*);
diff --git a/src/cmd/dist/README b/src/cmd/dist/README
index cf194fa..e6d08cf 100644
--- a/src/cmd/dist/README
+++ b/src/cmd/dist/README
@@ -31,8 +31,8 @@ Bufs or Vecs on the stack should be
 		... main code ...
 		bprintf(&b1, "hello, world");
 		vadd(&v1, bstr(&b1));  // v1 takes a copy of its argument
-		bprintf(&b1, "another string");
-		vadd(&v1, bstr(&b1));  // v1 now has two strings
+		bprintf(&b2, "another string");
+		vadd(&v1, bstr(&b2));  // v1 now has two strings
 		
 		bfree(&b1);
 		bfree(&b2);
diff --git a/src/cmd/dist/a.h b/src/cmd/dist/a.h
index c19b1f4..fcd81cc 100644
--- a/src/cmd/dist/a.h
+++ b/src/cmd/dist/a.h
@@ -10,7 +10,9 @@ typedef long long Time;
 
 #define nil ((void*)0)
 #define nelem(x) (sizeof(x)/sizeof((x)[0]))
+#ifndef PLAN9
 #define USED(x) ((void)(x))
+#endif
 
 // A Buf is a byte buffer, like Go's []byte.
 typedef struct Buf Buf;
@@ -106,6 +108,7 @@ void	xmain(int argc, char **argv);
 
 // portability layer (plan9.c, unix.c, windows.c)
 bool	contains(char *p, char *sep);
+void	errprintf(char*, ...);
 void	fatal(char *msg, ...);
 bool	hasprefix(char *p, char *prefix);
 bool	hassuffix(char *p, char *suffix);
@@ -120,6 +123,7 @@ void	runv(Buf *b, char *dir, int mode, Vec *argv);
 void	bgrunv(char *dir, int mode, Vec *argv);
 void	bgwait(void);
 bool	streq(char*, char*);
+bool	cansse2(void);
 void	writefile(Buf*, char*, int);
 void	xatexit(void (*f)(void));
 void	xexit(int);
@@ -147,3 +151,6 @@ int	xstrlen(char*);
 char*	xstrrchr(char*, int);
 char*	xstrstr(char*, char*);
 char*	xworkdir(void);
+int	xsamefile(char*, char*);
+char*	xgetgoarm(void);
+int	xtryexecfunc(void (*)(void));
diff --git a/src/cmd/dist/arg.h b/src/cmd/dist/arg.h
index 6eef035..9819765 100644
--- a/src/cmd/dist/arg.h
+++ b/src/cmd/dist/arg.h
@@ -28,7 +28,7 @@ THE SOFTWARE.
 
 /* command line */
 extern char	*argv0;
-#define	ARGBEGIN	for((argv0?0:(argv0=(*argv))),argv++,argc--;\
+#define	ARGBEGIN	for((argv0=(argv0?argv0:*argv)),argv++,argc--;\
 			    argv[0] && argv[0][0]=='-' && argv[0][1];\
 			    argc--, argv++) {\
 				char *_args, *_argt;\
@@ -37,7 +37,6 @@ extern char	*argv0;
 				if(_args[0]=='-' && _args[1]==0){\
 					argc--; argv++; break;\
 				}\
-				_argc = 0;\
 				while((_argc = *_args++) != 0)\
 				switch(_argc)
 #define	ARGEND		_argt=0;USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
diff --git a/src/cmd/dist/arm.c b/src/cmd/dist/arm.c
new file mode 100644
index 0000000..dafc5c1
--- /dev/null
+++ b/src/cmd/dist/arm.c
@@ -0,0 +1,79 @@
+// 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 "a.h"
+
+#ifndef __ARMEL__
+char *
+xgetgoarm(void)
+{
+	return "6";
+}
+#else
+static void useVFPv3(void);
+static void useVFPv1(void);
+
+char *
+xgetgoarm(void)
+{
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+	// NetBSD has buggy support for VFPv2 (incorrect inexact, 
+	// denormial, and NaN handling). When GOARM=6, some of our
+	// math tests fails on Raspberry Pi.
+	// Thus we return "5" here for safety, the user is free
+	// to override.
+	// Note: using GOARM=6 with cgo can trigger a kernel assertion
+	// failure and crash NetBSD/evbarm kernel.
+	// FreeBSD also have broken VFP support, so disable VFP also
+	// on FreeBSD.
+	return "5";
+#endif
+	if(xtryexecfunc(useVFPv3))
+		return "7";
+	else if(xtryexecfunc(useVFPv1))
+		return "6";
+	return "5";
+}
+
+static void
+useVFPv3(void)
+{
+	// try to run VFPv3-only "vmov.f64 d0, #112" instruction
+	// we can't use that instruction directly, because we
+	// might be compiling with a soft-float only toolchain.
+	//
+	// some newer toolchains are configured to use thumb
+	// by default, so we need to do some mode changing magic
+	// here.
+	// We can use "bx pc; nop" here, but GNU as(1) insists
+	// on warning us
+	// "use of r15 in bx in ARM mode is not really useful"
+	// so we workaround that by using "bx r0"
+	__asm__ __volatile__ ("mov r0, pc");
+	__asm__ __volatile__ ("bx r0");
+	__asm__ __volatile__ (".word 0xeeb70b00"); // vmov.f64 d0, #112
+	__asm__ __volatile__ (".word 0xe12fff1e"); // bx lr
+}
+
+static void
+useVFPv1(void)
+{
+	// try to run "vmov.f64 d0, d0" instruction
+	// we can't use that instruction directly, because we
+	// might be compiling with a soft-float only toolchain
+	//
+	// some newer toolchains are configured to use thumb
+	// by default, so we need to do some mode changing magic
+	// here.
+	// We can use "bx pc; nop" here, but GNU as(1) insists
+	// on warning us
+	// "use of r15 in bx in ARM mode is not really useful"
+	// so we workaround that by using "bx r0"
+	__asm__ __volatile__ ("mov r0, pc");
+	__asm__ __volatile__ ("bx r0");
+	__asm__ __volatile__ (".word 0xeeb00b40"); // vomv.f64 d0, d0
+	__asm__ __volatile__ (".word 0xe12fff1e"); // bx lr
+}
+
+#endif
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index 7f9aa7b..dda45ca 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -16,6 +16,8 @@ char *gohostarch;
 char *gohostchar;
 char *gohostos;
 char *goos;
+char *goarm;
+char *go386;
 char *goroot = GOROOT_FINAL;
 char *goroot_final = GOROOT_FINAL;
 char *workdir;
@@ -96,6 +98,20 @@ init(void)
 	if(find(goos, okgoos, nelem(okgoos)) < 0)
 		fatal("unknown $GOOS %s", goos);
 
+	xgetenv(&b, "GOARM");
+	if(b.len == 0)
+		bwritestr(&b, xgetgoarm());
+	goarm = btake(&b);
+
+	xgetenv(&b, "GO386");
+	if(b.len == 0) {
+		if(cansse2())
+			bwritestr(&b, "sse2");
+		else
+			bwritestr(&b, "387");
+	}
+	go386 = btake(&b);
+
 	p = bpathf(&b, "%s/include/u.h", goroot);
 	if(!isfile(p)) {
 		fatal("$GOROOT is not set correctly or not exported\n"
@@ -126,6 +142,8 @@ init(void)
 	xsetenv("GOROOT", goroot);
 	xsetenv("GOARCH", goarch);
 	xsetenv("GOOS", goos);
+	xsetenv("GOARM", goarm);
+	xsetenv("GO386", go386);
 
 	// Make the environment more predictable.
 	xsetenv("LANG", "C");
@@ -147,7 +165,7 @@ static void
 rmworkdir(void)
 {
 	if(vflag > 1)
-		xprintf("rm -rf %s\n", workdir);
+		errprintf("rm -rf %s\n", workdir);
 	xremoveall(workdir);
 }
 
@@ -207,7 +225,7 @@ findgoversion(void)
 	chomp(&branch);
 
 	// What are the tags along the current branch?
-	tag = "";
+	tag = "devel";
 	rev = ".";
 	run(&b, goroot, CheckExit, "hg", "log", "-b", bstr(&branch), "-r", ".:0", "--template", "{tags} + ", nil);
 	splitfields(&tags, bstr(&b));
@@ -216,7 +234,9 @@ findgoversion(void)
 		p = tags.p[i];
 		if(streq(p, "+"))
 			nrev++;
-		if(hasprefix(p, "release.") || hasprefix(p, "weekly.") || hasprefix(p, "go")) {
+		// NOTE: Can reenable the /* */ code when we want to
+		// start reporting versions named 'weekly' again.
+		if(/*hasprefix(p, "weekly.") ||*/ hasprefix(p, "go")) {
 			tag = xstrdup(p);
 			// If this tag matches the current checkout
 			// exactly (no "+" yet), don't show extra
@@ -236,7 +256,7 @@ findgoversion(void)
 	if(rev[0]) {
 		// Tag is before the revision we're building.
 		// Add extra information.
-		run(&bmore, goroot, CheckExit, "hg", "log", "--template", " +{node|short}", "-r", rev, nil);
+		run(&bmore, goroot, CheckExit, "hg", "log", "--template", " +{node|short} {date|date}", "-r", rev, nil);
 		chomp(&bmore);
 	}
 
@@ -378,6 +398,9 @@ setup(void)
 // gccargs is the gcc command line to use for compiling a single C file.
 static char *proto_gccargs[] = {
 	"-Wall",
+	// native Plan 9 compilers don't like non-standard prototypes
+	// so let gcc catch them.
+	"-Wstrict-prototypes",
 	"-Wno-sign-compare",
 	"-Wno-missing-braces",
 	"-Wno-parentheses",
@@ -387,7 +410,14 @@ static char *proto_gccargs[] = {
 	"-Werror",
 	"-fno-common",
 	"-ggdb",
+	"-pipe",
+#if defined(__NetBSD__) && defined(__arm__)
+	// GCC 4.5.4 (NetBSD nb1 20120916) on ARM is known to mis-optimize gc/mparith3.c
+	// Fix available at http://patchwork.ozlabs.org/patch/64562/.
+	"-O1",
+#else
 	"-O2",
+#endif
 };
 
 static Vec gccargs;
@@ -474,14 +504,7 @@ static struct {
 		"$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a",
 	}},
 	{"cmd/5l", {
-		"../ld/data.c",
-		"../ld/elf.c",
-		"../ld/go.c",
-		"../ld/ldelf.c",
-		"../ld/ldmacho.c",
-		"../ld/ldpe.c",
-		"../ld/lib.c",
-		"../ld/symtab.c",
+		"../ld/*",
 		"enam.c",
 	}},
 	{"cmd/6l", {
@@ -535,17 +558,17 @@ static void
 install(char *dir)
 {
 	char *name, *p, *elem, *prefix, *exe;
-	bool islib, ispkg, isgo, stale;
+	bool islib, ispkg, isgo, stale, clang;
 	Buf b, b1, path;
 	Vec compile, files, link, go, missing, clean, lib, extra;
 	Time ttarg, t;
-	int i, j, k, n, doclean, targ;
+	int i, j, k, n, doclean, targ, usecpp;
 
 	if(vflag) {
 		if(!streq(goos, gohostos) || !streq(goarch, gohostarch))
-			xprintf("%s (%s/%s)\n", dir, goos, goarch);
+			errprintf("%s (%s/%s)\n", dir, goos, goarch);
 		else
-			xprintf("%s\n", dir);
+			errprintf("%s\n", dir);
 	}
 
 	binit(&b);
@@ -560,6 +583,7 @@ install(char *dir)
 	vinit(&lib);
 	vinit(&extra);
 
+
 	// path = full path to dir.
 	bpathf(&path, "%s/src/%s", goroot, dir);
 	name = lastelem(dir);
@@ -574,7 +598,7 @@ install(char *dir)
 	// For release, cmd/prof and cmd/cov are not included.
 	if((streq(dir, "cmd/cov") || streq(dir, "cmd/prof")) && !isdir(bstr(&path))) {
 		if(vflag > 1)
-			xprintf("skipping %s - does not exist\n", dir);
+			errprintf("skipping %s - does not exist\n", dir);
 		goto out;
 	}
 
@@ -583,12 +607,13 @@ install(char *dir)
 		xgetenv(&b, "CC");
 		if(b.len == 0)
 			bprintf(&b, "gcc");
+		clang = contains(bstr(&b), "clang");
 		splitfields(&gccargs, bstr(&b));
 		for(i=0; i<nelem(proto_gccargs); i++)
 			vadd(&gccargs, proto_gccargs[i]);
-		if(xstrstr(bstr(&b), "clang") != nil) {
-			vadd(&gccargs, "-Wno-dangling-else");
-			vadd(&gccargs, "-Wno-unused-value");
+		if(clang) {
+			// clang is too smart about unused command-line arguments
+			vadd(&gccargs, "-Qunused-arguments");
 		}
 	}
 
@@ -605,7 +630,10 @@ install(char *dir)
 	if(islib) {
 		// C library.
 		vadd(&link, "ar");
-		vadd(&link, "rsc");
+		if(streq(gohostos, "plan9"))
+			vadd(&link, "rc");
+		else
+			vadd(&link, "rsc");
 		prefix = "";
 		if(!hasprefix(name, "lib"))
 			prefix = "lib";
@@ -631,14 +659,21 @@ install(char *dir)
 		vadd(&link, bpathf(&b, "%s/%s%s", tooldir, elem, exe));
 	} else {
 		// C command. Use gccargs.
-		vcopy(&link, gccargs.p, gccargs.len);
-		vadd(&link, "-o");
-		targ = link.len;
-		vadd(&link, bpathf(&b, "%s/%s%s", tooldir, name, exe));
-		if(streq(gohostarch, "amd64"))
-			vadd(&link, "-m64");
-		else if(streq(gohostarch, "386"))
-			vadd(&link, "-m32");
+		if(streq(gohostos, "plan9")) {
+			vadd(&link, bprintf(&b, "%sl", gohostchar));
+			vadd(&link, "-o");
+			targ = link.len;
+			vadd(&link, bpathf(&b, "%s/%s", tooldir, name));
+		} else {
+			vcopy(&link, gccargs.p, gccargs.len);
+			vadd(&link, "-o");
+			targ = link.len;
+			vadd(&link, bpathf(&b, "%s/%s%s", tooldir, name, exe));
+			if(streq(gohostarch, "amd64"))
+				vadd(&link, "-m64");
+			else if(streq(gohostarch, "386"))
+				vadd(&link, "-m32");
+		}
 	}
 	ttarg = mtime(link.p[targ]);
 
@@ -672,6 +707,8 @@ install(char *dir)
 				bsubst(&b1, "$GOARCH", goarch);
 				p = bstr(&b1);
 				if(hassuffix(p, ".a")) {
+					if(streq(gohostos, "plan9") && hassuffix(p, "libbio.a"))
+						continue;
 					vadd(&lib, bpathf(&b, "%s", p));
 					continue;
 				}
@@ -741,6 +778,10 @@ install(char *dir)
 	}
 	files.len = n;
 
+	// If there are no files to compile, we're done.
+	if(files.len == 0)
+		goto out;
+	
 	for(i=0; i<lib.len && !stale; i++)
 		if(mtime(lib.p[i]) > ttarg)
 			stale = 1;
@@ -767,7 +808,7 @@ install(char *dir)
 		for(j=0; j<nelem(gentab); j++) {
 			if(hasprefix(elem, gentab[j].nameprefix)) {
 				if(vflag > 1)
-					xprintf("generate %s\n", p);
+					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
@@ -799,10 +840,10 @@ install(char *dir)
 			p = files.p[i];
 			if(!hassuffix(p, ".goc"))
 				continue;
-			// b = path/zp but with _goarch.c instead of .goc
+			// 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.c", goarch);
+			bwritef(&b, "_%s_%s.c", goos, goarch);
 			goc2c(p, bstr(&b));
 			vadd(&files, bstr(&b));
 		}
@@ -812,10 +853,24 @@ install(char *dir)
 	if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
 		// We've generated the right files; the go command can do the build.
 		if(vflag > 1)
-			xprintf("skip build for cross-compile %s\n", dir);
+			errprintf("skip build for cross-compile %s\n", dir);
 		goto nobuild;
 	}
 
+	// The files generated by GNU Bison use macros that aren't
+	// supported by the Plan 9 compilers so we have to use the
+	// external preprocessor when compiling.
+	usecpp = 0;
+	if(streq(gohostos, "plan9")) {
+		for(i=0; i<files.len; i++) {
+			p = files.p[i];
+			if(hassuffix(p, "y.tab.c") || hassuffix(p, "y.tab.h")){
+				usecpp = 1;
+				break;
+			}
+		}
+	}
+
 	// Compile the files.
 	for(i=0; i<files.len; i++) {
 		if(!hassuffix(files.p[i], ".c") && !hassuffix(files.p[i], ".s"))
@@ -825,35 +880,53 @@ install(char *dir)
 		vreset(&compile);
 		if(!isgo) {
 			// C library or tool.
-			vcopy(&compile, gccargs.p, gccargs.len);
-			vadd(&compile, "-c");
-			if(streq(gohostarch, "amd64"))
-				vadd(&compile, "-m64");
-			else if(streq(gohostarch, "386"))
-				vadd(&compile, "-m32");
-			if(streq(dir, "lib9"))
-				vadd(&compile, "-DPLAN9PORT");
-
-			vadd(&compile, "-I");
-			vadd(&compile, bpathf(&b, "%s/include", goroot));
+			if(streq(gohostos, "plan9")) {
+				vadd(&compile, bprintf(&b, "%sc", gohostchar));
+				vadd(&compile, "-FTVw");
+				if(usecpp)
+					vadd(&compile, "-Bp+");
+				vadd(&compile, bpathf(&b, "-I%s/include/plan9", goroot));
+				vadd(&compile, bpathf(&b, "-I%s/include/plan9/%s", goroot, gohostarch));
+			} else {
+				vcopy(&compile, gccargs.p, gccargs.len);
+				vadd(&compile, "-c");
+				if(streq(gohostarch, "amd64"))
+					vadd(&compile, "-m64");
+				else if(streq(gohostarch, "386"))
+					vadd(&compile, "-m32");
+				if(streq(dir, "lib9"))
+					vadd(&compile, "-DPLAN9PORT");
+	
+				vadd(&compile, "-I");
+				vadd(&compile, bpathf(&b, "%s/include", goroot));
+			}
 
 			vadd(&compile, "-I");
 			vadd(&compile, bstr(&path));
 
 			// lib9/goos.c gets the default constants hard-coded.
 			if(streq(name, "goos.c")) {
-				vadd(&compile, bprintf(&b, "-DGOOS=\"%s\"", goos));
-				vadd(&compile, bprintf(&b, "-DGOARCH=\"%s\"", goarch));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GOOS=\"%s\"", goos));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GOARCH=\"%s\"", goarch));
 				bprintf(&b1, "%s", goroot_final);
 				bsubst(&b1, "\\", "\\\\");  // turn into C string
-				vadd(&compile, bprintf(&b, "-DGOROOT=\"%s\"", bstr(&b1)));
-				vadd(&compile, bprintf(&b, "-DGOVERSION=\"%s\"", goversion));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GOROOT=\"%s\"", bstr(&b1)));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GOVERSION=\"%s\"", goversion));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GOARM=\"%s\"", goarm));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GO386=\"%s\"", go386));
 			}
 
 			// gc/lex.c records the GOEXPERIMENT setting used during the build.
 			if(streq(name, "lex.c")) {
 				xgetenv(&b, "GOEXPERIMENT");
-				vadd(&compile, bprintf(&b1, "-DGOEXPERIMENT=\"%s\"", bstr(&b)));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b1, "GOEXPERIMENT=\"%s\"", bstr(&b)));
 			}
 		} else {
 			// Supporting files for a Go package.
@@ -861,12 +934,16 @@ install(char *dir)
 				vadd(&compile, bpathf(&b, "%s/%sa", tooldir, gochar));
 			else {
 				vadd(&compile, bpathf(&b, "%s/%sc", tooldir, gochar));
-				vadd(&compile, "-FVw");
+				vadd(&compile, "-F");
+				vadd(&compile, "-V");
+				vadd(&compile, "-w");
 			}
 			vadd(&compile, "-I");
 			vadd(&compile, workdir);
-			vadd(&compile, bprintf(&b, "-DGOOS_%s", goos));
-			vadd(&compile, bprintf(&b, "-DGOARCH_%s", goarch));
+			vadd(&compile, "-D");
+			vadd(&compile, bprintf(&b, "GOOS_%s", goos));
+			vadd(&compile, "-D");
+			vadd(&compile, bprintf(&b, "GOARCH_%s", goarch));
 		}
 
 		bpathf(&b, "%s/%s", workdir, lastelem(files.p[i]));
@@ -882,7 +959,11 @@ install(char *dir)
 			doclean = 0;
 		}
 
-		b.p[b.len-1] = 'o';  // was c or s
+		// Change the last character of the output file (which was c or s).
+		if(streq(gohostos, "plan9"))
+			b.p[b.len-1] = gohostchar[0];
+		else
+			b.p[b.len-1] = 'o';
 		vadd(&compile, "-o");
 		vadd(&compile, bstr(&b));
 		vadd(&compile, files.p[i]);
@@ -923,7 +1004,8 @@ install(char *dir)
 	if(!islib && !isgo) {
 		// C binaries need the libraries explicitly, and -lm.
 		vcopy(&link, lib.p, lib.len);
-		vadd(&link, "-lm");
+		if(!streq(gohostos, "plan9"))
+			vadd(&link, "-lm");
 	}
 
 	// Remove target before writing it.
@@ -981,6 +1063,20 @@ shouldbuild(char *file, char *dir)
 	Buf b;
 	Vec lines, fields;
 
+	// On Plan 9, most of the libraries are already present.
+	// The main exception is libmach which has been modified
+	// in various places to support Go object files.
+	if(streq(gohostos, "plan9")) {
+		if(streq(dir, "lib9")) {
+			name = lastelem(file);
+			if(streq(name, "goos.c") || streq(name, "flag.c"))
+				return 1;
+			return 0;
+		}
+		if(streq(dir, "libbio"))
+			return 0;
+	}
+	
 	// Check file name for GOOS or GOARCH.
 	name = lastelem(file);
 	for(i=0; i<nelem(okgoos); i++)
@@ -1057,7 +1153,7 @@ copy(char *dst, char *src, int exec)
 	Buf b;
 
 	if(vflag > 1)
-		xprintf("cp %s %s\n", src, dst);
+		errprintf("cp %s %s\n", src, dst);
 
 	binit(&b);
 	readfile(&b, src);
@@ -1125,6 +1221,7 @@ static char *buildorder[] = {
 	"pkg/go/ast",
 	"pkg/go/parser",
 	"pkg/os/exec",
+	"pkg/os/signal",
 	"pkg/net/url",
 	"pkg/text/template/parse",
 	"pkg/text/template",
@@ -1294,6 +1391,9 @@ cmdenv(int argc, char **argv)
 	format = "%s=\"%s\"\n";
 	pflag = 0;
 	ARGBEGIN{
+	case '9':
+		format = "%s='%s'\n";
+		break;
 	case 'p':
 		pflag = 1;
 		break;
@@ -1301,7 +1401,7 @@ cmdenv(int argc, char **argv)
 		vflag++;
 		break;
 	case 'w':
-		format = "set %s=%s\n";
+		format = "set %s=%s\r\n";
 		break;
 	default:
 		usage();
@@ -1318,6 +1418,10 @@ cmdenv(int argc, char **argv)
 	xprintf(format, "GOHOSTOS", gohostos);
 	xprintf(format, "GOTOOLDIR", tooldir);
 	xprintf(format, "GOCHAR", gochar);
+	if(streq(goarch, "arm"))
+		xprintf(format, "GOARM", goarm);
+	if(streq(goarch, "386"))
+		xprintf(format, "GO386", go386);
 
 	if(pflag) {
 		sep = ":";
@@ -1511,7 +1615,7 @@ cmdbanner(int argc, char **argv)
 				"Read and run ./sudo.bash to install the debuggers.\n");
 	}
 
-	if(!streq(goroot_final, goroot)) {
+	if(!xsamefile(goroot_final, goroot)) {
 		xprintf("\n"
 			"The binaries expect %s to be copied or moved to %s\n",
 			goroot, goroot_final);
diff --git a/src/cmd/dist/buildgc.c b/src/cmd/dist/buildgc.c
index da38760..03a797f 100644
--- a/src/cmd/dist/buildgc.c
+++ b/src/cmd/dist/buildgc.c
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 #include "a.h"
-#include <stdio.h>
 
 /*
  * Helpers for building cmd/gc.
diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c
index a0c6201..f46f72d 100644
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 #include "a.h"
-#include <stdio.h>
 
 /*
  * Helpers for building pkg/runtime.
@@ -20,6 +19,8 @@ mkzversion(char *dir, char *file)
 {
 	Buf b, out;
 	
+	USED(dir);
+
 	binit(&b);
 	binit(&out);
 	
@@ -46,6 +47,8 @@ void
 mkzgoarch(char *dir, char *file)
 {
 	Buf b, out;
+
+	USED(dir);
 	
 	binit(&b);
 	binit(&out);
@@ -72,6 +75,8 @@ void
 mkzgoos(char *dir, char *file)
 {
 	Buf b, out;
+
+	USED(dir);
 	
 	binit(&b);
 	binit(&out);
@@ -100,9 +105,15 @@ static struct {
 		"#define	m(r)	4(r)\n"
 	},
 	{"386", "plan9",
+		"// Plan 9 does not have per-process segment descriptors with\n"
+		"// which to do thread-local storage. Instead, we will use a\n"
+		"// fixed offset from the per-process TOS struct address for\n"
+		"// the local storage. Since the process ID is contained in the\n"
+		"// TOS struct, we specify an offset for that here as well.\n"
 		"#define	get_tls(r)	MOVL _tos(SB), r \n"
 		"#define	g(r)	-8(r)\n"
 		"#define	m(r)	-4(r)\n"
+		"#define	procid(r)	48(r)\n"
 	},
 	{"386", "linux",
 		"// On Linux systems, what we call 0(GS) and 4(GS) for g and m\n"
@@ -140,6 +151,12 @@ static struct {
 		"#define	g(r) 0(r)\n"
 		"#define	m(r) 8(r)\n"
 	},
+	{"amd64", "plan9",
+		"#define	get_tls(r)\n"
+		"#define	g(r) 0(GS)\n"
+		"#define	m(r) 8(GS)\n"
+		"#define	procid(r) 16(GS)\n"
+	},
 	{"amd64", "",
 		"// The offsets 0 and 8 are known to:\n"
 		"//	../../cmd/6l/pass.c:/D_GS\n"
@@ -188,16 +205,23 @@ mkzasm(char *dir, char *file)
 	fatal("unknown $GOOS/$GOARCH in mkzasm");
 ok:
 
-	// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -a proc.c
+	// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -a -n -o workdir/proc.acid proc.c
 	// to get acid [sic] output.
 	vreset(&argv);
 	vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
-	vadd(&argv, bprintf(&b, "-DGOOS_%s", goos));
-	vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
-	vadd(&argv, bprintf(&b, "-I%s", workdir));
+	vadd(&argv, "-D");
+	vadd(&argv, bprintf(&b, "GOOS_%s", goos));
+	vadd(&argv, "-D");
+	vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
+	vadd(&argv, "-I");
+	vadd(&argv, bprintf(&b, "%s", workdir));
 	vadd(&argv, "-a");
+	vadd(&argv, "-n");
+	vadd(&argv, "-o");
+	vadd(&argv, bpathf(&b, "%s/proc.acid", workdir));
 	vadd(&argv, "proc.c");
-	runv(&in, dir, CheckExit, &argv);
+	runv(nil, dir, CheckExit, &argv);
+	readfile(&in, bpathf(&b, "%s/proc.acid", workdir));
 	
 	// Convert input like
 	//	aggr G
@@ -222,6 +246,8 @@ ok:
 				aggr = "gobuf";
 			else if(streq(fields.p[1], "WinCall"))
 				aggr = "wincall";
+			else if(streq(fields.p[1], "SEH"))
+				aggr = "seh";
 		}
 		if(hasprefix(lines.p[i], "}"))
 			aggr = nil;
@@ -251,6 +277,7 @@ static char *runtimedefs[] = {
 	"iface.c",
 	"hashmap.c",
 	"chan.c",
+	"parfor.c",
 };
 
 // mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h,
@@ -265,11 +292,12 @@ mkzruntimedefs(char *dir, char *file)
 {
 	int i, skip;
 	char *p;
-	Buf in, b, out;
+	Buf in, b, b1, out;
 	Vec argv, lines, fields, seen;
 	
 	binit(&in);
 	binit(&b);
+	binit(&b1);
 	binit(&out);
 	vinit(&argv);
 	vinit(&lines);
@@ -285,18 +313,25 @@ mkzruntimedefs(char *dir, char *file)
 	);
 
 	
-	// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -q
+	// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -q -n -o workdir/runtimedefs
 	// on each of the runtimedefs C files.
 	vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
-	vadd(&argv, bprintf(&b, "-DGOOS_%s", goos));
-	vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
-	vadd(&argv, bprintf(&b, "-I%s", workdir));
+	vadd(&argv, "-D");
+	vadd(&argv, bprintf(&b, "GOOS_%s", goos));
+	vadd(&argv, "-D");
+	vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
+	vadd(&argv, "-I");
+	vadd(&argv, bprintf(&b, "%s", workdir));
 	vadd(&argv, "-q");
+	vadd(&argv, "-n");
+	vadd(&argv, "-o");
+	vadd(&argv, bpathf(&b, "%s/runtimedefs", workdir));
 	vadd(&argv, "");
 	p = argv.p[argv.len-1];
 	for(i=0; i<nelem(runtimedefs); i++) {
 		argv.p[argv.len-1] = runtimedefs[i];
-		runv(&b, dir, CheckExit, &argv);
+		runv(nil, dir, CheckExit, &argv);
+		readfile(&b, bpathf(&b1, "%s/runtimedefs", workdir));
 		bwriteb(&in, &b);
 	}
 	argv.p[argv.len-1] = p;
@@ -338,6 +373,7 @@ mkzruntimedefs(char *dir, char *file)
 
 	bfree(&in);
 	bfree(&b);
+	bfree(&b1);
 	bfree(&out);
 	vfree(&argv);
 	vfree(&lines);
diff --git a/src/cmd/dist/goc2c.c b/src/cmd/dist/goc2c.c
index 22f72f8..a103bce 100644
--- a/src/cmd/dist/goc2c.c
+++ b/src/cmd/dist/goc2c.c
@@ -26,6 +26,11 @@ static char *input;
 static Buf *output;
 #define EOF -1
 
+enum
+{
+	use64bitint = 1,
+};
+
 static int
 xgetchar(void)
 {
@@ -86,13 +91,16 @@ static struct {
 	char *name;
 	int size;
 } type_table[] = {
-	/* variable sized first, for easy replacement */
-	/* order matches enum above */
-	/* default is 32-bit architecture sizes */
-	{"bool",		1},
+	/* 
+	 * 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},
-	{"int",		4},
-	{"uint",		4},
+	{"intgo",		4},
+	{"uintgo",	4},
 	{"uintptr",	4},
 	{"String",	8},
 	{"Slice",	12},
@@ -101,17 +109,18 @@ static struct {
 	/* fixed size */
 	{"float32",	4},
 	{"float64",	8},
-	{"byte",		1},
-	{"int8",		1},
+	{"byte",	1},
+	{"int8",	1},
 	{"uint8",	1},
 	{"int16",	2},
 	{"uint16",	2},
 	{"int32",	4},
+	{"rune",	4},
 	{"uint32",	4},
 	{"int64",	8},
 	{"uint64",	8},
 
-	{nil},
+	{nil, 0},
 };
 
 /* Fixed structure alignment (non-gcc only) */
@@ -328,7 +337,7 @@ read_type(void)
 	unsigned int len;
 
 	p = read_token_no_eof();
-	if (*p != '*')
+	if (*p != '*' && !streq(p, "int") && !streq(p, "uint"))
 		return p;
 	op = p;
 	pointer_count = 0;
@@ -337,13 +346,18 @@ read_type(void)
 		++p;
 	}
 	len = xstrlen(p);
-	q = xmalloc(len + pointer_count + 1);
+	q = xmalloc(len + 2 + pointer_count + 1);
 	xmemmove(q, p, len);
-	while (pointer_count > 0) {
-		q[len] = '*';
-		++len;
-		--pointer_count;
+
+	// 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;
@@ -570,8 +584,9 @@ write_gcc_func_header(char *package, char *name, struct params *params,
 static void
 write_gcc_func_trailer(char *package, char *name, struct params *rets)
 {
-	if (rets == nil)
-		;
+	if (rets == nil) {
+		// nothing to do
+	}
 	else if (rets->next == nil)
 		bwritef(output, "return %s;\n", rets->name);
 	else {
@@ -712,15 +727,25 @@ goc2c(char *goc, char *c)
 	if(!gcc) {
 		if(streq(goarch, "amd64")) {
 			type_table[Uintptr].size = 8;
-			type_table[String].size = 16;
-			type_table[Slice].size = 8+4+4;
 			type_table[Eface].size = 8+8;
+			type_table[String].size = 16;
+			if(use64bitint) {
+				type_table[Int].size = 8;
+				type_table[Uint].size = 8;
+			}
+			type_table[Slice].size = 8+2*type_table[Int].size;
 			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[String].size = 8;
 			type_table[Slice].size = 16;
 			type_table[Eface].size = 4+4;
+			type_table[Int].size = 4;
+			type_table[Uint].size = 4;
 			structround = 4;
 		}
 	}
diff --git a/src/cmd/dist/plan9.c b/src/cmd/dist/plan9.c
new file mode 100644
index 0000000..8a7c0ab
--- /dev/null
+++ b/src/cmd/dist/plan9.c
@@ -0,0 +1,764 @@
+// 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.
+
+// These #ifdefs are being used as a substitute for
+// build configuration, so that on any system, this
+// tool can be built with the local equivalent of
+//	cc *.c
+//
+#ifdef PLAN9
+
+#include <u.h>
+#include <libc.h>
+#include <stdio.h>
+#undef nil
+#undef nelem
+#include "a.h"
+
+// bprintf replaces the buffer with the result of the printf formatting
+// and returns a pointer to the NUL-terminated buffer contents.
+char*
+bprintf(Buf *b, char *fmt, ...)
+{
+	va_list arg;
+	char buf[4096];
+	
+	breset(b);
+	va_start(arg, fmt);
+	vsnprintf(buf, sizeof buf, fmt, arg);
+	va_end(arg);
+	bwritestr(b, buf);
+	return bstr(b);
+}
+
+// bpathf is the same as bprintf (on windows it turns / into \ after the printf).
+// It returns a pointer to the NUL-terminated buffer contents.
+char*
+bpathf(Buf *b, char *fmt, ...)
+{
+	va_list arg;
+	char buf[4096];
+	
+	breset(b);
+	va_start(arg, fmt);
+	vsnprintf(buf, sizeof buf, fmt, arg);
+	va_end(arg);
+	bwritestr(b, buf);
+	return bstr(b);
+}
+
+// bwritef is like bprintf but does not reset the buffer
+// and does not return the NUL-terminated string.
+void
+bwritef(Buf *b, char *fmt, ...)
+{
+	va_list arg;
+	char buf[4096];
+	
+	va_start(arg, fmt);
+	vsnprintf(buf, sizeof buf, fmt, arg);
+	va_end(arg);
+	bwritestr(b, buf);
+}
+
+// breadfrom appends to b all the data that can be read from fd.
+static void
+breadfrom(Buf *b, int fd)
+{
+	int n;
+
+	for(;;) {
+		bgrow(b, 4096);
+		n = read(fd, b->p+b->len, 4096);
+		if(n < 0)
+			fatal("read");
+		if(n == 0)
+			break;
+		b->len += n;
+	}
+}
+
+// xgetenv replaces b with the value of the named environment variable.
+void
+xgetenv(Buf *b, char *name)
+{
+	char *p;
+	
+	breset(b);
+	p = getenv(name);
+	if(p != nil)
+		bwritestr(b, p);
+}
+
+static void genrun(Buf *b, char *dir, int mode, Vec *argv, int bg);
+
+// run runs the command named by cmd.
+// If b is not nil, run replaces b with the output of the command.
+// If dir is not nil, run runs the command in that directory.
+// If mode is CheckExit, run calls fatal if the command is not successful.
+void
+run(Buf *b, char *dir, int mode, char *cmd, ...)
+{
+	va_list arg;
+	Vec argv;
+	char *p;
+	
+	vinit(&argv);
+	vadd(&argv, cmd);
+	va_start(arg, cmd);
+	while((p = va_arg(arg, char*)) != nil)
+		vadd(&argv, p);
+	va_end(arg);
+	
+	runv(b, dir, mode, &argv);
+	
+	vfree(&argv);
+}
+
+// runv is like run but takes a vector.
+void
+runv(Buf *b, char *dir, int mode, Vec *argv)
+{
+	genrun(b, dir, mode, argv, 1);
+}
+
+// bgrunv is like run but runs the command in the background.
+// bgwait waits for pending bgrunv to finish.
+void
+bgrunv(char *dir, int mode, Vec *argv)
+{
+	genrun(nil, dir, mode, argv, 0);
+}
+
+#define MAXBG 4 /* maximum number of jobs to run at once */
+
+static struct {
+	int pid;
+	int mode;
+	char *cmd;
+	Buf *b;
+} bg[MAXBG];
+static int nbg;
+static int maxnbg = nelem(bg);
+
+static void bgwait1(void);
+
+// genrun is the generic run implementation.
+static void
+genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
+{
+	int i, p[2], pid;
+	Buf b1, cmd;
+	char *q;
+
+	while(nbg >= maxnbg)
+		bgwait1();
+
+	binit(&b1);
+	binit(&cmd);
+
+	if(!isabs(argv->p[0])) {
+		bpathf(&b1, "/bin/%s", argv->p[0]);
+		free(argv->p[0]);
+		argv->p[0] = xstrdup(bstr(&b1));
+	}
+
+	// Generate a copy of the command to show in a log.
+	// Substitute $WORK for the work directory.
+	for(i=0; i<argv->len; i++) {
+		if(i > 0)
+			bwritestr(&cmd, " ");
+		q = argv->p[i];
+		if(workdir != nil && hasprefix(q, workdir)) {
+			bwritestr(&cmd, "$WORK");
+			q += strlen(workdir);
+		}
+		bwritestr(&cmd, q);
+	}
+	if(vflag > 1)
+		errprintf("%s\n", bstr(&cmd));
+
+	if(b != nil) {
+		breset(b);
+		if(pipe(p) < 0)
+			fatal("pipe");
+	}
+
+	switch(pid = fork()) {
+	case -1:
+		fatal("fork");
+	case 0:
+		if(b != nil) {
+			close(0);
+			close(p[0]);
+			dup(p[1], 1);
+			dup(p[1], 2);
+			if(p[1] > 2)
+				close(p[1]);
+		}
+		if(dir != nil) {
+			if(chdir(dir) < 0) {
+				fprint(2, "chdir: %r\n");
+				_exits("chdir");
+			}
+		}
+		vadd(argv, nil);
+		exec(argv->p[0], argv->p);
+		fprint(2, "%s\n", bstr(&cmd));
+		fprint(2, "exec: %r\n");
+		_exits("exec");
+	}
+	if(b != nil) {
+		close(p[1]);
+		breadfrom(b, p[0]);
+		close(p[0]);
+	}
+
+	if(nbg < 0)
+		fatal("bad bookkeeping");
+	bg[nbg].pid = pid;
+	bg[nbg].mode = mode;
+	bg[nbg].cmd = btake(&cmd);
+	bg[nbg].b = b;
+	nbg++;
+	
+	if(wait)
+		bgwait();
+
+	bfree(&cmd);
+	bfree(&b1);
+}
+
+// bgwait1 waits for a single background job.
+static void
+bgwait1(void)
+{
+	Waitmsg *w;
+	int i, mode;
+	char *cmd;
+	Buf *b;
+
+	w = wait();
+	if(w == nil)
+		fatal("wait");
+		
+	for(i=0; i<nbg; i++)
+		if(bg[i].pid == w->pid)
+			goto ok;
+	fatal("wait: unexpected pid");
+
+ok:
+	cmd = bg[i].cmd;
+	mode = bg[i].mode;
+	bg[i].pid = 0;
+	b = bg[i].b;
+	bg[i].b = nil;
+	bg[i] = bg[--nbg];
+	
+	if(mode == CheckExit && w->msg[0]) {
+		if(b != nil)
+			xprintf("%s\n", bstr(b));
+		fatal("FAILED: %s", cmd);
+	}
+	xfree(cmd);
+}
+
+// bgwait waits for all the background jobs.
+void
+bgwait(void)
+{
+	while(nbg > 0)
+		bgwait1();
+}
+
+// xgetwd replaces b with the current directory.
+void
+xgetwd(Buf *b)
+{
+	char buf[4096];
+	
+	breset(b);
+	if(getwd(buf, sizeof buf) == nil)
+		fatal("getwd");
+	bwritestr(b, buf);
+}
+
+// xrealwd replaces b with the 'real' name for the given path.
+// real is defined as what getcwd returns in that directory.
+void
+xrealwd(Buf *b, char *path)
+{
+	char buf[4096];
+	int fd;
+
+	fd = open(path, OREAD);
+	if(fd2path(fd, buf, sizeof buf) < 0)
+		fatal("fd2path");
+	close(fd);
+	breset(b);
+	bwritestr(b, buf);
+}
+
+// isdir reports whether p names an existing directory.
+bool
+isdir(char *p)
+{
+	Dir *d;
+	ulong mode;
+
+	d = dirstat(p);
+	if(d == nil)
+		return 0;
+	mode = d->mode;
+	free(d);
+	return (mode & DMDIR) == DMDIR;
+}
+
+// isfile reports whether p names an existing file.
+bool
+isfile(char *p)
+{
+	Dir *d;
+	ulong mode;
+
+	d = dirstat(p);
+	if(d == nil)
+		return 0;
+	mode = d->mode;
+	free(d);
+	return (mode & DMDIR) == 0;
+}
+
+// mtime returns the modification time of the file p.
+Time
+mtime(char *p)
+{
+	Dir *d;
+	ulong t;
+
+	d = dirstat(p);
+	if(d == nil)
+		return 0;
+	t = d->mtime;
+	free(d);
+	return (Time)t;
+}
+
+// isabs reports whether p is an absolute path.
+bool
+isabs(char *p)
+{
+	return hasprefix(p, "/");
+}
+
+// readfile replaces b with the content of the named file.
+void
+readfile(Buf *b, char *file)
+{
+	int fd;
+
+	breset(b);
+	fd = open(file, OREAD);
+	if(fd < 0)
+		fatal("open %s", file);
+	breadfrom(b, fd);
+	close(fd);
+}
+
+// writefile writes b to the named file, creating it if needed.
+void
+writefile(Buf *b, char *file, int exec)
+{
+	int fd;
+	Dir d;
+	
+	fd = create(file, ORDWR, 0666);
+	if(fd < 0)
+		fatal("create %s", file);
+	if(write(fd, b->p, b->len) != b->len)
+		fatal("short write");
+	if(exec) {
+		nulldir(&d);
+		d.mode = 0755;
+		dirfwstat(fd, &d);
+	}
+	close(fd);
+}
+
+// xmkdir creates the directory p.
+void
+xmkdir(char *p)
+{
+	int fd;
+
+	if(isdir(p))
+		return;
+	fd = create(p, OREAD, 0777|DMDIR);
+	close(fd);
+	if(fd < 0)
+		fatal("mkdir %s", p);
+}
+
+// xmkdirall creates the directory p and its parents, as needed.
+void
+xmkdirall(char *p)
+{
+	char *q;
+
+	if(isdir(p))
+		return;
+	q = strrchr(p, '/');
+	if(q != nil) {
+		*q = '\0';
+		xmkdirall(p);
+		*q = '/';
+	}
+	xmkdir(p);
+}
+
+// xremove removes the file p.
+void
+xremove(char *p)
+{
+	if(vflag > 2)
+		errprintf("rm %s\n", p);
+	remove(p);
+}
+
+// xremoveall removes the file or directory tree rooted at p.
+void
+xremoveall(char *p)
+{
+	int i;
+	Buf b;
+	Vec dir;
+
+	binit(&b);
+	vinit(&dir);
+
+	if(isdir(p)) {
+		xreaddir(&dir, p);
+		for(i=0; i<dir.len; i++) {
+			bprintf(&b, "%s/%s", p, dir.p[i]);
+			xremoveall(bstr(&b));
+		}
+	}
+	if(vflag > 2)
+		errprintf("rm %s\n", p);
+	remove(p);
+	
+	bfree(&b);
+	vfree(&dir);	
+}
+
+// xreaddir replaces dst with a list of the names of the files in dir.
+// The names are relative to dir; they are not full paths.
+void
+xreaddir(Vec *dst, char *dir)
+{
+	Dir *d;
+	int fd, i, n;
+
+	vreset(dst);
+
+	fd = open(dir, OREAD);
+	if(fd < 0)
+		fatal("open %s", dir);
+	n = dirreadall(fd, &d);
+	for(i=0; i<n; i++)
+		vadd(dst, d[i].name);
+	free(d);
+	close(fd);
+}
+
+// xworkdir creates a new temporary directory to hold object files
+// and returns the name of that directory.
+char*
+xworkdir(void)
+{
+	Buf b;
+	char *p;
+	int fd, tries;
+
+	binit(&b);
+
+	fd = 0;
+	for(tries=0; tries<1000; tries++) {
+		bprintf(&b, "/tmp/go-cbuild-%06x", nrand((1<<24)-1));
+		fd = create(bstr(&b), OREAD|OEXCL, 0700|DMDIR);
+		if(fd >= 0)
+			goto done;
+	}
+	fatal("xworkdir create");
+
+done:
+	close(fd);
+	p = btake(&b);
+
+	bfree(&b);
+	return p;
+}
+
+// fatal prints an error message to standard error and exits.
+void
+fatal(char *msg, ...)
+{
+	char buf[ERRMAX];
+	va_list arg;
+	
+	rerrstr(buf, sizeof buf);
+
+	fflush(stdout);
+	fprintf(stderr, "go tool dist: ");
+	va_start(arg, msg);
+	vfprintf(stderr, msg, arg);
+	va_end(arg);
+
+	if(buf[0])
+		fprintf(stderr, ": %s", buf);
+	fprintf(stderr, "\n");
+
+	bgwait();
+	exits(msg);
+}
+
+// xmalloc returns a newly allocated zeroed block of n bytes of memory.
+// It calls fatal if it runs out of memory.
+void*
+xmalloc(int n)
+{
+	void *p;
+	
+	p = malloc(n);
+	if(p == nil)
+		fatal("out of memory");
+	memset(p, 0, n);
+	return p;
+}
+
+// xstrdup returns a newly allocated copy of p.
+// It calls fatal if it runs out of memory.
+char*
+xstrdup(char *p)
+{
+	p = strdup(p);
+	if(p == nil)
+		fatal("out of memory");
+	return p;
+}
+
+// xrealloc grows the allocation p to n bytes and
+// returns the new (possibly moved) pointer.
+// It calls fatal if it runs out of memory.
+void*
+xrealloc(void *p, int n)
+{
+	p = realloc(p, n);
+	if(p == nil)
+		fatal("out of memory");
+	return p;
+}
+
+// xfree frees the result returned by xmalloc, xstrdup, or xrealloc.
+void
+xfree(void *p)
+{
+	free(p);
+}
+
+// hassuffix reports whether p ends with suffix.
+bool
+hassuffix(char *p, char *suffix)
+{
+	int np, ns;
+	
+	np = strlen(p);
+	ns = strlen(suffix);
+	return np >= ns && strcmp(p+np-ns, suffix) == 0;
+}
+
+// hasprefix reports whether p begins wtih prefix.
+bool
+hasprefix(char *p, char *prefix)
+{
+	return strncmp(p, prefix, strlen(prefix)) == 0;
+}
+
+// contains reports whether sep appears in p.
+bool
+contains(char *p, char *sep)
+{
+	return strstr(p, sep) != nil;
+}
+
+// streq reports whether p and q are the same string.
+bool
+streq(char *p, char *q)
+{
+	return strcmp(p, q) == 0;
+}
+
+// lastelem returns the final path element in p.
+char*
+lastelem(char *p)
+{
+	char *out;
+
+	out = p;
+	for(; *p; p++)
+		if(*p == '/')
+			out = p+1;
+	return out;
+}
+
+// xmemmove copies n bytes from src to dst.
+void
+xmemmove(void *dst, void *src, int n)
+{
+	memmove(dst, src, n);
+}
+
+// xmemcmp compares the n-byte regions starting at a and at b.
+int
+xmemcmp(void *a, void *b, int n)
+{
+	return memcmp(a, b, n);
+}
+
+// xstrlen returns the length of the NUL-terminated string at p.
+int
+xstrlen(char *p)
+{
+	return strlen(p);
+}
+
+// xexit exits the process with return code n.
+void
+xexit(int n)
+{
+	char buf[32];
+
+	snprintf(buf, sizeof buf, "%d", n);
+	exits(buf);
+}
+
+// xatexit schedules the exit-handler f to be run when the program exits.
+void
+xatexit(void (*f)(void))
+{
+	atexit(f);
+}
+
+// xprintf prints a message to standard output.
+void
+xprintf(char *fmt, ...)
+{
+	va_list arg;
+	
+	va_start(arg, fmt);
+	vprintf(fmt, arg);
+	va_end(arg);
+}
+
+// errprintf prints a message to standard output.
+void
+errprintf(char *fmt, ...)
+{
+	va_list arg;
+	
+	va_start(arg, fmt);
+	vfprintf(stderr, fmt, arg);
+	va_end(arg);
+}
+
+// xsetenv sets the environment variable $name to the given value.
+void
+xsetenv(char *name, char *value)
+{
+	putenv(name, value);
+}
+
+// main takes care of OS-specific startup and dispatches to xmain.
+void
+main(int argc, char **argv)
+{
+	Buf b;
+
+	setvbuf(stdout, nil, _IOLBF, BUFSIZ);
+	setvbuf(stderr, nil, _IOLBF, BUFSIZ);
+
+	binit(&b);
+
+	rfork(RFENVG);
+
+	slash = "/";
+	gohostos = "plan9";
+
+	xgetenv(&b, "objtype");
+	if(b.len == 0)
+		fatal("$objtype is unset");
+	gohostarch = btake(&b);
+
+	srand(time(0)+getpid());
+	init();
+	xmain(argc, argv);
+
+	bfree(&b);
+	exits(nil);
+}
+
+// xqsort is a wrapper for the C standard qsort.
+void
+xqsort(void *data, int n, int elemsize, int (*cmp)(const void*, const void*))
+{
+	qsort(data, n, elemsize, cmp);
+}
+
+// xstrcmp compares the NUL-terminated strings a and b.
+int
+xstrcmp(char *a, char *b)
+{
+	return strcmp(a, b);
+}
+
+// xstrstr returns a pointer to the first occurrence of b in a.
+char*
+xstrstr(char *a, char *b)
+{
+	return strstr(a, b);
+}
+
+// xstrrchr returns a pointer to the final occurrence of c in p.
+char*
+xstrrchr(char *p, int c)
+{
+	return strrchr(p, c);
+}
+
+// xsamefile returns whether f1 and f2 are the same file (or dir)
+int
+xsamefile(char *f1, char *f2)
+{
+	return streq(f1, f2); // suffice for now
+}
+
+// xtryexecfunc tries to execute function f, if any illegal instruction
+// signal received in the course of executing that function, it will
+// return 0, otherwise it will return 1.
+int
+xtryexecfunc(void (*f)(void))
+{
+	USED(f);
+	return 0; // suffice for now
+}
+
+bool
+cansse2(void)
+{
+	// if we had access to cpuid, could answer this question
+	// less conservatively.
+	return 0;
+}
+
+#endif // PLAN9
diff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c
index e6d82e1..e4e2dcc 100644
--- a/src/cmd/dist/unix.c
+++ b/src/cmd/dist/unix.c
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <stdarg.h>
+#include <setjmp.h>
 
 // bprintf replaces the buffer with the result of the printf formatting
 // and returns a pointer to the NUL-terminated buffer contents.
@@ -177,7 +178,7 @@ genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
 		bwritestr(&cmd, q);
 	}
 	if(vflag > 1)
-		xprintf("%s\n", bstr(&cmd));
+		errprintf("%s\n", bstr(&cmd));
 
 	if(b != nil) {
 		breset(b);
@@ -398,7 +399,7 @@ void
 xremove(char *p)
 {
 	if(vflag > 2)
-		xprintf("rm %s\n", p);
+		errprintf("rm %s\n", p);
 	unlink(p);
 }
 
@@ -420,11 +421,11 @@ xremoveall(char *p)
 			xremoveall(bstr(&b));
 		}
 		if(vflag > 2)
-			xprintf("rm %s\n", p);
+			errprintf("rm %s\n", p);
 		rmdir(p);
 	} else {
 		if(vflag > 2)
-			xprintf("rm %s\n", p);
+			errprintf("rm %s\n", p);
 		unlink(p);
 	}
 	
@@ -627,6 +628,17 @@ xprintf(char *fmt, ...)
 	va_end(arg);
 }
 
+// errprintf prints a message to standard output.
+void
+errprintf(char *fmt, ...)
+{
+	va_list arg;
+	
+	va_start(arg, fmt);
+	vfprintf(stderr, fmt, arg);
+	va_end(arg);
+}
+
 // xsetenv sets the environment variable $name to the given value.
 void
 xsetenv(char *name, char *value)
@@ -658,6 +670,10 @@ main(int argc, char **argv)
 	gohostos = "linux";
 #elif defined(__FreeBSD__)
 	gohostos = "freebsd";
+#elif defined(__FreeBSD_kernel__)
+	// detect debian/kFreeBSD. 
+	// http://wiki.debian.org/Debian_GNU/kFreeBSD_FAQ#Q._How_do_I_detect_kfreebsd_with_preprocessor_directives_in_a_C_program.3F
+	gohostos = "freebsd";	
 #elif defined(__OpenBSD__)
 	gohostos = "openbsd";
 #elif defined(__NetBSD__)
@@ -716,5 +732,76 @@ xstrrchr(char *p, int c)
 	return strrchr(p, c);
 }
 
+// xsamefile returns whether f1 and f2 are the same file (or dir)
+int
+xsamefile(char *f1, char *f2)
+{
+	return streq(f1, f2); // suffice for now
+}
+
+sigjmp_buf sigill_jmpbuf;
+static void sigillhand(int);
+
+// xtryexecfunc tries to execute function f, if any illegal instruction
+// signal received in the course of executing that function, it will
+// return 0, otherwise it will return 1.
+// Some systems (notably NetBSD) will spin and spin when executing VFPv3
+// instructions on VFPv2 system (e.g. Raspberry Pi) without ever triggering
+// SIGILL, so we set a 1-second alarm to catch that case.
+int
+xtryexecfunc(void (*f)(void))
+{
+	int r;
+	r = 0;
+	signal(SIGILL, sigillhand);
+	signal(SIGALRM, sigillhand);
+	alarm(1);
+	if(sigsetjmp(sigill_jmpbuf, 1) == 0) {
+		f();
+		r = 1;
+	}
+	signal(SIGILL, SIG_DFL);
+	alarm(0);
+	signal(SIGALRM, SIG_DFL);
+	return r;
+}
+
+// SIGILL handler helper
+static void
+sigillhand(int signum)
+{
+	USED(signum);
+	siglongjmp(sigill_jmpbuf, 1);
+}
+
+static void
+__cpuid(int dst[4], int ax)
+{
+#ifdef __i386__
+	// we need to avoid ebx on i386 (esp. when -fPIC).
+	asm volatile(
+		"mov %%ebx, %%edi\n\t"
+		"cpuid\n\t"
+		"xchgl %%ebx, %%edi"
+		: "=a" (dst[0]), "=D" (dst[1]), "=c" (dst[2]), "=d" (dst[3])
+		: "0" (ax));
+#elif defined(__x86_64__)
+	asm volatile("cpuid"
+		: "=a" (dst[0]), "=b" (dst[1]), "=c" (dst[2]), "=d" (dst[3])
+		: "0" (ax));
+#else
+	dst[0] = dst[1] = dst[2] = dst[3] = 0;
+#endif
+}
+
+bool
+cansse2(void)
+{
+	int info[4];
+	
+	__cpuid(info, 1);
+	return (info[3] & (1<<26)) != 0;	// SSE2
+}
+
 #endif // PLAN9
 #endif // __WINDOWS__
diff --git a/src/cmd/dist/windows.c b/src/cmd/dist/windows.c
index 557e4b0..7bcda45 100644
--- a/src/cmd/dist/windows.c
+++ b/src/cmd/dist/windows.c
@@ -115,7 +115,7 @@ errstr(void)
 	binit(&b);
 	code = GetLastError();
 	r = nil;
-	FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+	FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
 		nil, code, 0, (Rune*)&r, 0, nil);
 	toutf(&b, r);
 	return bstr(&b);  // leak but we're dying anyway
@@ -285,9 +285,11 @@ genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
 	binit(&cmd);
 
 	for(i=0; i<argv->len; i++) {
+		q = argv->p[i];
+		if(i == 0 && streq(q, "hg"))
+			bwritestr(&cmd, "cmd.exe /c ");
 		if(i > 0)
 			bwritestr(&cmd, " ");
-		q = argv->p[i];
 		if(contains(q, " ") || contains(q, "\t") || contains(q, "\"") || contains(q, "\\\\") || hassuffix(q, "\\")) {
 			bwritestr(&cmd, "\"");
 			nslash = 0;
@@ -314,7 +316,7 @@ genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
 		}
 	}
 	if(vflag > 1)
-		xprintf("%s\n", bstr(&cmd));
+		errprintf("%s\n", bstr(&cmd));
 
 	torune(&rcmd, bstr(&cmd));
 	rexe = nil;
@@ -528,8 +530,9 @@ readfile(Buf *b, char *file)
 	HANDLE h;
 	Rune *r;
 
+	breset(b);
 	if(vflag > 2)
-		xprintf("read %s\n", file);
+		errprintf("read %s\n", file);
 	torune(&r, file);
 	h = CreateFileW(r, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
 	if(h == INVALID_HANDLE_VALUE)
@@ -548,7 +551,7 @@ writefile(Buf *b, char *file, int exec)
 	USED(exec);
 
 	if(vflag > 2)
-		xprintf("write %s\n", file);
+		errprintf("write %s\n", file);
 	torune(&r, file);
 	h = CreateFileW(r, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, nil, CREATE_ALWAYS, 0, 0);
 	if(h == INVALID_HANDLE_VALUE)
@@ -707,7 +710,7 @@ fatal(char *msg, ...)
 	vsnprintf(buf1, sizeof buf1, msg, arg);
 	va_end(arg);
 
-	xprintf("go tool dist: %s\n", buf1);
+	errprintf("go tool dist: %s\n", buf1);
 	
 	bgwait();
 	ExitProcess(1);
@@ -848,6 +851,23 @@ xprintf(char *fmt, ...)
 	xfree(p);
 }
 
+void
+errprintf(char *fmt, ...)
+{
+	va_list arg;
+	char *p;
+	DWORD n, w;
+
+	va_start(arg, fmt);
+	n = vsnprintf(NULL, 0, fmt, arg);
+	p = xmalloc(n+1);
+	vsnprintf(p, n+1, fmt, arg);
+	va_end(arg);
+	w = 0;
+	WriteFile(GetStdHandle(STD_ERROR_HANDLE), p, n, &w, 0);
+	xfree(p);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -907,4 +927,75 @@ xstrrchr(char *p, int c)
 	return nil;
 }
 
+// xsamefile returns whether f1 and f2 are the same file (or dir)
+int
+xsamefile(char *f1, char *f2)
+{
+	Rune *ru;
+	HANDLE fd1, fd2;
+	BY_HANDLE_FILE_INFORMATION fi1, fi2;
+	int r;
+
+	// trivial case
+	if(streq(f1, f2))
+		return 1;
+	
+	torune(&ru, f1);
+	// refer to ../../pkg/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)
+		return 0;
+	torune(&ru, f2);
+	fd2 = CreateFileW(ru, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
+	xfree(ru);
+	if(fd2 == INVALID_HANDLE_VALUE) {
+		CloseHandle(fd1);
+		return 0;
+	}
+	r = GetFileInformationByHandle(fd1, &fi1) != 0 && GetFileInformationByHandle(fd2, &fi2) != 0;
+	CloseHandle(fd2);
+	CloseHandle(fd1);
+	if(r != 0 &&
+	   fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber &&
+	   fi1.nFileIndexHigh == fi2.nFileIndexHigh &&
+	   fi1.nFileIndexLow == fi2.nFileIndexLow)
+	   	return 1;
+	return 0;
+}
+
+// xtryexecfunc tries to execute function f, if any illegal instruction
+// signal received in the course of executing that function, it will
+// return 0, otherwise it will return 1.
+int
+xtryexecfunc(void (*f)(void))
+{
+	return 0; // suffice for now
+}
+
+static void
+cpuid(int dst[4], int ax)
+{
+	// NOTE: This asm statement is for mingw.
+	// If we ever support MSVC, use __cpuid(dst, ax)
+	// to use the built-in.
+#if defined(__i386__) || defined(__x86_64__)
+	asm volatile("cpuid"
+		: "=a" (dst[0]), "=b" (dst[1]), "=c" (dst[2]), "=d" (dst[3])
+		: "0" (ax));
+#else
+	dst[0] = dst[1] = dst[2] = dst[3] = 0;
+#endif
+}
+
+bool
+cansse2(void)
+{
+	int info[4];
+	
+	cpuid(info, 1);
+	return (info[3] & (1<<26)) != 0;	// SSE2
+}
+
+
 #endif // __WINDOWS__
diff --git a/src/cmd/fix/doc.go b/src/cmd/fix/doc.go
index a92e0fc..5de3e08 100644
--- a/src/cmd/fix/doc.go
+++ b/src/cmd/fix/doc.go
@@ -33,4 +33,4 @@ Fix does not make backup copies of the files that it edits.
 Instead, use a version control system's ``diff'' functionality to inspect
 the changes that fix makes before committing them.
 */
-package documentation
+package main
diff --git a/src/cmd/fix/error.go b/src/cmd/fix/error.go
deleted file mode 100644
index 5561321..0000000
--- a/src/cmd/fix/error.go
+++ /dev/null
@@ -1,353 +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 main
-
-import (
-	"go/ast"
-	"regexp"
-	"strings"
-)
-
-func init() {
-	register(errorFix)
-}
-
-var errorFix = fix{
-	"error",
-	"2011-11-02",
-	errorFn,
-	`Use error instead of os.Error.
-
-This fix rewrites code using os.Error to use error:
-
-	os.Error -> error
-	os.NewError -> errors.New
-	os.EOF -> io.EOF
-
-Seeing the old names above (os.Error and so on) triggers the following
-heuristic rewrites.  The heuristics can be forced using the -force=error flag.
-
-A top-level function, variable, or constant named error is renamed error_.
-
-Error implementations—those types used as os.Error or named
-XxxError—have their String methods renamed to Error.  Any existing
-Error field or method is renamed to Err.
-
-Error values—those with type os.Error or named e, err, error, err1,
-and so on—have method calls and field references rewritten just
-as the types do (String to Error, Error to Err).  Also, a type assertion
-of the form err.(*os.Waitmsg) becomes err.(*exec.ExitError).
-
-http://codereview.appspot.com/5305066
-`,
-}
-
-// At minimum, this fix applies the following rewrites:
-//
-//	os.Error -> error
-//	os.NewError -> errors.New
-//	os.EOF -> io.EOF
-//
-// However, if can apply any of those rewrites, it assumes that the
-// file predates the error type and tries to update the code to use
-// the new definition for error - an Error method, not a String method.
-// This more heuristic procedure may not be 100% accurate, so it is
-// only run when the file needs updating anyway.  The heuristic can
-// be forced to run using -force=error.
-//
-// First, we must identify the implementations of os.Error.
-// These include the type of any value returned as or assigned to an os.Error.
-// To that set we add any type whose name contains "Error" or "error".
-// The heuristic helps for implementations that are not used as os.Error
-// in the file in which they are defined.
-//
-// In any implementation of os.Error, we rename an existing struct field
-// or method named Error to Err and rename the String method to Error.
-//
-// Second, we must identify the values of type os.Error.
-// These include any value that obviously has type os.Error.
-// To that set we add any variable whose name is e or err or error
-// possibly followed by _ or a numeric or capitalized suffix.
-// The heuristic helps for variables that are initialized using calls
-// to functions in other packages.  The type checker does not have
-// information about those packages available, and in general cannot
-// (because the packages may themselves not compile).
-//
-// For any value of type os.Error, we replace a call to String with a call to Error.
-// We also replace type assertion err.(*os.Waitmsg) with err.(*exec.ExitError).
-
-// Variables matching this regexp are assumed to have type os.Error.
-var errVar = regexp.MustCompile(`^(e|err|error)_?([A-Z0-9].*)?$`)
-
-// Types matching this regexp are assumed to be implementations of os.Error.
-var errType = regexp.MustCompile(`^\*?([Ee]rror|.*Error)$`)
-
-// Type-checking configuration: tell the type-checker this basic
-// information about types, functions, and variables in external packages.
-var errorTypeConfig = &TypeConfig{
-	Type: map[string]*Type{
-		"os.Error": {},
-	},
-	Func: map[string]string{
-		"fmt.Errorf":  "os.Error",
-		"os.NewError": "os.Error",
-	},
-	Var: map[string]string{
-		"os.EPERM":        "os.Error",
-		"os.ENOENT":       "os.Error",
-		"os.ESRCH":        "os.Error",
-		"os.EINTR":        "os.Error",
-		"os.EIO":          "os.Error",
-		"os.ENXIO":        "os.Error",
-		"os.E2BIG":        "os.Error",
-		"os.ENOEXEC":      "os.Error",
-		"os.EBADF":        "os.Error",
-		"os.ECHILD":       "os.Error",
-		"os.EDEADLK":      "os.Error",
-		"os.ENOMEM":       "os.Error",
-		"os.EACCES":       "os.Error",
-		"os.EFAULT":       "os.Error",
-		"os.EBUSY":        "os.Error",
-		"os.EEXIST":       "os.Error",
-		"os.EXDEV":        "os.Error",
-		"os.ENODEV":       "os.Error",
-		"os.ENOTDIR":      "os.Error",
-		"os.EISDIR":       "os.Error",
-		"os.EINVAL":       "os.Error",
-		"os.ENFILE":       "os.Error",
-		"os.EMFILE":       "os.Error",
-		"os.ENOTTY":       "os.Error",
-		"os.EFBIG":        "os.Error",
-		"os.ENOSPC":       "os.Error",
-		"os.ESPIPE":       "os.Error",
-		"os.EROFS":        "os.Error",
-		"os.EMLINK":       "os.Error",
-		"os.EPIPE":        "os.Error",
-		"os.EAGAIN":       "os.Error",
-		"os.EDOM":         "os.Error",
-		"os.ERANGE":       "os.Error",
-		"os.EADDRINUSE":   "os.Error",
-		"os.ECONNREFUSED": "os.Error",
-		"os.ENAMETOOLONG": "os.Error",
-		"os.EAFNOSUPPORT": "os.Error",
-		"os.ETIMEDOUT":    "os.Error",
-		"os.ENOTCONN":     "os.Error",
-	},
-}
-
-func errorFn(f *ast.File) bool {
-	if !imports(f, "os") && !force["error"] {
-		return false
-	}
-
-	// Fix gets called once to run the heuristics described above
-	// when we notice that this file definitely needs fixing
-	// (it mentions os.Error or something similar).
-	var fixed bool
-	var didHeuristic bool
-	heuristic := func() {
-		if didHeuristic {
-			return
-		}
-		didHeuristic = true
-
-		// We have identified a necessary fix (like os.Error -> error)
-		// but have not applied it or any others yet.  Prepare the file
-		// for fixing and apply heuristic fixes.
-
-		// Rename error to error_ to make room for error.
-		fixed = renameTop(f, "error", "error_") || fixed
-
-		// Use type checker to build list of error implementations.
-		typeof, assign := typecheck(errorTypeConfig, f)
-
-		isError := map[string]bool{}
-		for _, val := range assign["os.Error"] {
-			t := typeof[val]
-			if strings.HasPrefix(t, "*") {
-				t = t[1:]
-			}
-			if t != "" && !strings.HasPrefix(t, "func(") {
-				isError[t] = true
-			}
-		}
-
-		// We use both the type check results and the "Error" name heuristic
-		// to identify implementations of os.Error.
-		isErrorImpl := func(typ string) bool {
-			return isError[typ] || errType.MatchString(typ)
-		}
-
-		isErrorVar := func(x ast.Expr) bool {
-			if typ := typeof[x]; typ != "" {
-				return isErrorImpl(typ) || typ == "os.Error"
-			}
-			if sel, ok := x.(*ast.SelectorExpr); ok {
-				return sel.Sel.Name == "Error" || sel.Sel.Name == "Err"
-			}
-			if id, ok := x.(*ast.Ident); ok {
-				return errVar.MatchString(id.Name)
-			}
-			return false
-		}
-
-		walk(f, func(n interface{}) {
-			// In method declaration on error implementation type,
-			// rename String() to Error() and Error() to Err().
-			fn, ok := n.(*ast.FuncDecl)
-			if ok &&
-				fn.Recv != nil &&
-				len(fn.Recv.List) == 1 &&
-				isErrorImpl(typeName(fn.Recv.List[0].Type)) {
-				// Rename.
-				switch fn.Name.Name {
-				case "String":
-					fn.Name.Name = "Error"
-					fixed = true
-				case "Error":
-					fn.Name.Name = "Err"
-					fixed = true
-				}
-				return
-			}
-
-			// In type definition of an error implementation type,
-			// rename Error field to Err to make room for method.
-			// Given type XxxError struct { ... Error T } rename field to Err.
-			d, ok := n.(*ast.GenDecl)
-			if ok {
-				for _, s := range d.Specs {
-					switch s := s.(type) {
-					case *ast.TypeSpec:
-						if isErrorImpl(typeName(s.Name)) {
-							st, ok := s.Type.(*ast.StructType)
-							if ok {
-								for _, f := range st.Fields.List {
-									for _, n := range f.Names {
-										if n.Name == "Error" {
-											n.Name = "Err"
-											fixed = true
-										}
-									}
-								}
-							}
-						}
-					}
-				}
-			}
-
-			// For values that are an error implementation type,
-			// rename .Error to .Err and .String to .Error
-			sel, selok := n.(*ast.SelectorExpr)
-			if selok && isErrorImpl(typeof[sel.X]) {
-				switch sel.Sel.Name {
-				case "Error":
-					sel.Sel.Name = "Err"
-					fixed = true
-				case "String":
-					sel.Sel.Name = "Error"
-					fixed = true
-				}
-			}
-
-			// Assume x.Err is an error value and rename .String to .Error
-			// Children have been processed so the rewrite from Error to Err
-			// has already happened there.
-			if selok {
-				if subsel, ok := sel.X.(*ast.SelectorExpr); ok && subsel.Sel.Name == "Err" && sel.Sel.Name == "String" {
-					sel.Sel.Name = "Error"
-					fixed = true
-				}
-			}
-
-			// For values that are an error variable, rename .String to .Error.
-			if selok && isErrorVar(sel.X) && sel.Sel.Name == "String" {
-				sel.Sel.Name = "Error"
-				fixed = true
-			}
-
-			// Rewrite composite literal of error type to turn Error: into Err:.
-			lit, ok := n.(*ast.CompositeLit)
-			if ok && isErrorImpl(typeof[lit]) {
-				for _, e := range lit.Elts {
-					if kv, ok := e.(*ast.KeyValueExpr); ok && isName(kv.Key, "Error") {
-						kv.Key.(*ast.Ident).Name = "Err"
-						fixed = true
-					}
-				}
-			}
-
-			// Rename os.Waitmsg to exec.ExitError
-			// when used in a type assertion on an error.
-			ta, ok := n.(*ast.TypeAssertExpr)
-			if ok && isErrorVar(ta.X) && isPtrPkgDot(ta.Type, "os", "Waitmsg") {
-				addImport(f, "exec")
-				sel := ta.Type.(*ast.StarExpr).X.(*ast.SelectorExpr)
-				sel.X.(*ast.Ident).Name = "exec"
-				sel.Sel.Name = "ExitError"
-				fixed = true
-			}
-
-		})
-	}
-
-	fix := func() {
-		if fixed {
-			return
-		}
-		fixed = true
-		heuristic()
-	}
-
-	if force["error"] {
-		heuristic()
-	}
-
-	walk(f, func(n interface{}) {
-		p, ok := n.(*ast.Expr)
-		if !ok {
-			return
-		}
-		sel, ok := (*p).(*ast.SelectorExpr)
-		if !ok {
-			return
-		}
-		switch {
-		case isPkgDot(sel, "os", "Error"):
-			fix()
-			*p = &ast.Ident{NamePos: sel.Pos(), Name: "error"}
-		case isPkgDot(sel, "os", "NewError"):
-			fix()
-			addImport(f, "errors")
-			sel.X.(*ast.Ident).Name = "errors"
-			sel.Sel.Name = "New"
-		case isPkgDot(sel, "os", "EOF"):
-			fix()
-			addImport(f, "io")
-			sel.X.(*ast.Ident).Name = "io"
-		}
-	})
-
-	if fixed && !usesImport(f, "os") {
-		deleteImport(f, "os")
-	}
-
-	return fixed
-}
-
-func typeName(typ ast.Expr) string {
-	if p, ok := typ.(*ast.StarExpr); ok {
-		typ = p.X
-	}
-	id, ok := typ.(*ast.Ident)
-	if ok {
-		return id.Name
-	}
-	sel, ok := typ.(*ast.SelectorExpr)
-	if ok {
-		return typeName(sel.X) + "." + sel.Sel.Name
-	}
-	return ""
-}
diff --git a/src/cmd/fix/error_test.go b/src/cmd/fix/error_test.go
deleted file mode 100644
index 027eed2..0000000
--- a/src/cmd/fix/error_test.go
+++ /dev/null
@@ -1,240 +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 main
-
-func init() {
-	addTestCases(errorTests, errorFn)
-}
-
-var errorTests = []testCase{
-	{
-		Name: "error.0",
-		In: `package main
-
-func error() {}
-
-var error int
-`,
-		Out: `package main
-
-func error() {}
-
-var error int
-`,
-	},
-	{
-		Name: "error.1",
-		In: `package main
-
-import "os"
-
-func f() os.Error {
-	return os.EOF
-}
-
-func error() {}
-
-var error int
-
-func g() {
-	error := 1
-	_ = error
-}
-
-func h(os.Error) {}
-
-func i(...os.Error) {}
-`,
-		Out: `package main
-
-import "io"
-
-func f() error {
-	return io.EOF
-}
-
-func error_() {}
-
-var error_ int
-
-func g() {
-	error := 1
-	_ = error
-}
-
-func h(error) {}
-
-func i(...error) {}
-`,
-	},
-	{
-		Name: "error.2",
-		In: `package main
-
-import "os"
-
-func f() os.Error {
-	return os.EOF
-}
-
-func g() string {
-	// these all convert because f is known
-	if err := f(); err != nil {
-		return err.String()
-	}
-	if err1 := f(); err1 != nil {
-		return err1.String()
-	}
-	if e := f(); e != nil {
-		return e.String()
-	}
-	if x := f(); x != nil {
-		return x.String()
-	}
-
-	// only the error names (err, err1, e) convert; u is not known
-	if err := u(); err != nil {
-		return err.String()
-	}
-	if err1 := u(); err1 != nil {
-		return err1.String()
-	}
-	if e := u(); e != nil {
-		return e.String()
-	}
-	if x := u(); x != nil {
-		return x.String()
-	}
-	return ""
-}
-
-type T int
-
-func (t T) String() string { return "t" }
-
-type PT int
-
-func (p *PT) String() string { return "pt" }
-
-type MyError int
-
-func (t MyError) String() string { return "myerror" }
-
-type PMyError int
-
-func (p *PMyError) String() string { return "pmyerror" }
-
-func error() {}
-
-var error int
-`,
-		Out: `package main
-
-import "io"
-
-func f() error {
-	return io.EOF
-}
-
-func g() string {
-	// these all convert because f is known
-	if err := f(); err != nil {
-		return err.Error()
-	}
-	if err1 := f(); err1 != nil {
-		return err1.Error()
-	}
-	if e := f(); e != nil {
-		return e.Error()
-	}
-	if x := f(); x != nil {
-		return x.Error()
-	}
-
-	// only the error names (err, err1, e) convert; u is not known
-	if err := u(); err != nil {
-		return err.Error()
-	}
-	if err1 := u(); err1 != nil {
-		return err1.Error()
-	}
-	if e := u(); e != nil {
-		return e.Error()
-	}
-	if x := u(); x != nil {
-		return x.String()
-	}
-	return ""
-}
-
-type T int
-
-func (t T) String() string { return "t" }
-
-type PT int
-
-func (p *PT) String() string { return "pt" }
-
-type MyError int
-
-func (t MyError) Error() string { return "myerror" }
-
-type PMyError int
-
-func (p *PMyError) Error() string { return "pmyerror" }
-
-func error_() {}
-
-var error_ int
-`,
-	},
-	{
-		Name: "error.3",
-		In: `package main
-
-import "os"
-
-func f() os.Error {
-	return os.EOF
-}
-
-type PathError struct {
-	Name  string
-	Error os.Error
-}
-
-func (p *PathError) String() string {
-	return p.Name + ": " + p.Error.String()
-}
-
-func (p *PathError) Error1() string {
-	p = &PathError{Error: nil}
-	return fmt.Sprint(p.Name, ": ", p.Error)
-}
-`,
-		Out: `package main
-
-import "io"
-
-func f() error {
-	return io.EOF
-}
-
-type PathError struct {
-	Name string
-	Err  error
-}
-
-func (p *PathError) Error() string {
-	return p.Name + ": " + p.Err.Error()
-}
-
-func (p *PathError) Error1() string {
-	p = &PathError{Err: nil}
-	return fmt.Sprint(p.Name, ": ", p.Err)
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/filepath.go b/src/cmd/fix/filepath.go
deleted file mode 100644
index f312260..0000000
--- a/src/cmd/fix/filepath.go
+++ /dev/null
@@ -1,56 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(filepathFix)
-}
-
-var filepathFix = fix{
-	"filepath",
-	"2011-06-26",
-	filepathFunc,
-	`Adapt code from filepath.[List]SeparatorString to string(filepath.[List]Separator).
-
-http://codereview.appspot.com/4527090
-`,
-}
-
-func filepathFunc(f *ast.File) (fixed bool) {
-	if !imports(f, "path/filepath") {
-		return
-	}
-
-	walk(f, func(n interface{}) {
-		e, ok := n.(*ast.Expr)
-		if !ok {
-			return
-		}
-
-		var ident string
-		switch {
-		case isPkgDot(*e, "filepath", "SeparatorString"):
-			ident = "filepath.Separator"
-		case isPkgDot(*e, "filepath", "ListSeparatorString"):
-			ident = "filepath.ListSeparator"
-		default:
-			return
-		}
-
-		// string(filepath.[List]Separator)
-		*e = &ast.CallExpr{
-			Fun:  ast.NewIdent("string"),
-			Args: []ast.Expr{ast.NewIdent(ident)},
-		}
-
-		fixed = true
-	})
-
-	return
-}
diff --git a/src/cmd/fix/filepath_test.go b/src/cmd/fix/filepath_test.go
deleted file mode 100644
index 37a2f5d..0000000
--- a/src/cmd/fix/filepath_test.go
+++ /dev/null
@@ -1,33 +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 main
-
-func init() {
-	addTestCases(filepathTests, filepathFunc)
-}
-
-var filepathTests = []testCase{
-	{
-		Name: "filepath.0",
-		In: `package main
-
-import (
-	"path/filepath"
-)
-
-var _ = filepath.SeparatorString
-var _ = filepath.ListSeparatorString
-`,
-		Out: `package main
-
-import (
-	"path/filepath"
-)
-
-var _ = string(filepath.Separator)
-var _ = string(filepath.ListSeparator)
-`,
-	},
-}
diff --git a/src/cmd/fix/go1pkgrename.go b/src/cmd/fix/go1pkgrename.go
deleted file mode 100644
index f701f62..0000000
--- a/src/cmd/fix/go1pkgrename.go
+++ /dev/null
@@ -1,146 +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 main
-
-import (
-	"go/ast"
-	"strings"
-)
-
-func init() {
-	register(go1pkgrenameFix)
-}
-
-var go1pkgrenameFix = fix{
-	"go1rename",
-	"2011-11-08",
-	go1pkgrename,
-	`Rewrite imports for packages moved during transition to Go 1.
-
-http://codereview.appspot.com/5316078
-`,
-}
-
-var go1PackageRenames = []struct{ old, new string }{
-	{"asn1", "encoding/asn1"},
-	{"big", "math/big"},
-	{"cmath", "math/cmplx"},
-	{"csv", "encoding/csv"},
-	{"exec", "os/exec"},
-	{"exp/template/html", "html/template"},
-	{"gob", "encoding/gob"},
-	{"http", "net/http"},
-	{"http/cgi", "net/http/cgi"},
-	{"http/fcgi", "net/http/fcgi"},
-	{"http/httptest", "net/http/httptest"},
-	{"http/pprof", "net/http/pprof"},
-	{"json", "encoding/json"},
-	{"mail", "net/mail"},
-	{"rpc", "net/rpc"},
-	{"rpc/jsonrpc", "net/rpc/jsonrpc"},
-	{"scanner", "text/scanner"},
-	{"smtp", "net/smtp"},
-	{"syslog", "log/syslog"},
-	{"tabwriter", "text/tabwriter"},
-	{"template", "text/template"},
-	{"template/parse", "text/template/parse"},
-	{"rand", "math/rand"},
-	{"url", "net/url"},
-	{"utf16", "unicode/utf16"},
-	{"utf8", "unicode/utf8"},
-	{"xml", "encoding/xml"},
-
-	// go.crypto sub-repository
-	{"crypto/bcrypt", "code.google.com/p/go.crypto/bcrypt"},
-	{"crypto/blowfish", "code.google.com/p/go.crypto/blowfish"},
-	{"crypto/cast5", "code.google.com/p/go.crypto/cast5"},
-	{"crypto/md4", "code.google.com/p/go.crypto/md4"},
-	{"crypto/ocsp", "code.google.com/p/go.crypto/ocsp"},
-	{"crypto/openpgp", "code.google.com/p/go.crypto/openpgp"},
-	{"crypto/openpgp/armor", "code.google.com/p/go.crypto/openpgp/armor"},
-	{"crypto/openpgp/elgamal", "code.google.com/p/go.crypto/openpgp/elgamal"},
-	{"crypto/openpgp/errors", "code.google.com/p/go.crypto/openpgp/errors"},
-	{"crypto/openpgp/packet", "code.google.com/p/go.crypto/openpgp/packet"},
-	{"crypto/openpgp/s2k", "code.google.com/p/go.crypto/openpgp/s2k"},
-	{"crypto/ripemd160", "code.google.com/p/go.crypto/ripemd160"},
-	{"crypto/twofish", "code.google.com/p/go.crypto/twofish"},
-	{"crypto/xtea", "code.google.com/p/go.crypto/xtea"},
-	{"exp/ssh", "code.google.com/p/go.crypto/ssh"},
-
-	// go.image sub-repository
-	{"image/bmp", "code.google.com/p/go.image/bmp"},
-	{"image/tiff", "code.google.com/p/go.image/tiff"},
-
-	// go.net sub-repository
-	{"net/dict", "code.google.com/p/go.net/dict"},
-	{"net/websocket", "code.google.com/p/go.net/websocket"},
-	{"exp/spdy", "code.google.com/p/go.net/spdy"},
-	{"http/spdy", "code.google.com/p/go.net/spdy"},
-
-	// go.codereview sub-repository
-	{"encoding/git85", "code.google.com/p/go.codereview/git85"},
-	{"patch", "code.google.com/p/go.codereview/patch"},
-
-	// exp
-	{"ebnf", "exp/ebnf"},
-	{"go/types", "exp/types"},
-
-	// deleted
-	{"container/vector", ""},
-	{"exp/datafmt", ""},
-	{"go/typechecker", ""},
-	{"old/netchan", ""},
-	{"old/regexp", ""},
-	{"old/template", ""},
-	{"try", ""},
-}
-
-var go1PackageNameRenames = []struct{ newPath, old, new string }{
-	{"html/template", "html", "template"},
-	{"math/cmplx", "cmath", "cmplx"},
-}
-
-func go1pkgrename(f *ast.File) bool {
-	fixed := false
-
-	// First update the imports.
-	for _, rename := range go1PackageRenames {
-		spec := importSpec(f, rename.old)
-		if spec == nil {
-			continue
-		}
-		if rename.new == "" {
-			warn(spec.Pos(), "package %q has been deleted in Go 1", rename.old)
-			continue
-		}
-		if rewriteImport(f, rename.old, rename.new) {
-			fixed = true
-		}
-		if strings.HasPrefix(rename.new, "exp/") {
-			warn(spec.Pos(), "package %q is not part of Go 1", rename.new)
-		}
-	}
-	if !fixed {
-		return false
-	}
-
-	// Now update the package names used by importers.
-	for _, rename := range go1PackageNameRenames {
-		// These are rare packages, so do the import test before walking.
-		if imports(f, rename.newPath) {
-			walk(f, func(n interface{}) {
-				if sel, ok := n.(*ast.SelectorExpr); ok {
-					if isTopName(sel.X, rename.old) {
-						// We know Sel.X is an Ident.
-						sel.X.(*ast.Ident).Name = rename.new
-						return
-					}
-				}
-			})
-		}
-	}
-
-	return fixed
-}
diff --git a/src/cmd/fix/go1pkgrename_test.go b/src/cmd/fix/go1pkgrename_test.go
deleted file mode 100644
index 840e443..0000000
--- a/src/cmd/fix/go1pkgrename_test.go
+++ /dev/null
@@ -1,139 +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 main
-
-func init() {
-	addTestCases(go1pkgrenameTests, go1pkgrename)
-}
-
-var go1pkgrenameTests = []testCase{
-	{
-		Name: "go1rename.0",
-		In: `package main
-
-import (
-	"asn1"
-	"big"
-	"cmath"
-	"csv"
-	"exec"
-	"exp/template/html"
-	"gob"
-	"http"
-	"http/cgi"
-	"http/fcgi"
-	"http/httptest"
-	"http/pprof"
-	"json"
-	"mail"
-	"rand"
-	"rpc"
-	"rpc/jsonrpc"
-	"scanner"
-	"smtp"
-	"syslog"
-	"tabwriter"
-	"template"
-	"template/parse"
-	"url"
-	"utf16"
-	"utf8"
-	"xml"
-
-	"crypto/bcrypt"
-)
-`,
-		Out: `package main
-
-import (
-	"encoding/asn1"
-	"encoding/csv"
-	"encoding/gob"
-	"encoding/json"
-	"encoding/xml"
-	"html/template"
-	"log/syslog"
-	"math/big"
-	"math/cmplx"
-	"math/rand"
-	"net/http"
-	"net/http/cgi"
-	"net/http/fcgi"
-	"net/http/httptest"
-	"net/http/pprof"
-	"net/mail"
-	"net/rpc"
-	"net/rpc/jsonrpc"
-	"net/smtp"
-	"net/url"
-	"os/exec"
-	"text/scanner"
-	"text/tabwriter"
-	"text/template"
-	"text/template/parse"
-	"unicode/utf16"
-	"unicode/utf8"
-
-	"code.google.com/p/go.crypto/bcrypt"
-)
-`,
-	},
-	{
-		Name: "go1rename.1",
-		In: `package main
-
-import "cmath"
-import poot "exp/template/html"
-
-import (
-	"ebnf"
-	"old/regexp"
-)
-
-var _ = cmath.Sin
-var _ = poot.Poot
-`,
-		Out: `package main
-
-import "math/cmplx"
-import poot "html/template"
-
-import (
-	"exp/ebnf"
-	"old/regexp"
-)
-
-var _ = cmplx.Sin
-var _ = poot.Poot
-`,
-	},
-	{
-		Name: "go1rename.2",
-		In: `package foo
-
-import (
-	"fmt"
-	"http"
-	"url"
-
-	"google/secret/project/go"
-)
-
-func main() {}
-`,
-		Out: `package foo
-
-import (
-	"fmt"
-	"net/http"
-	"net/url"
-
-	"google/secret/project/go"
-)
-
-func main() {}
-`,
-	},
-}
diff --git a/src/cmd/fix/go1rename.go b/src/cmd/fix/go1rename.go
deleted file mode 100644
index 9266c74..0000000
--- a/src/cmd/fix/go1rename.go
+++ /dev/null
@@ -1,167 +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 main
-
-func init() {
-	register(go1renameFix)
-}
-
-var go1renameFix = fix{
-	"go1rename",
-	"2012-02-12",
-	renameFix(go1renameReplace),
-	`Rewrite package-level names that have been renamed in Go 1.
-
-http://codereview.appspot.com/5625045/
-http://codereview.appspot.com/5672072/
-`,
-}
-
-var go1renameReplace = []rename{
-	{
-		OldImport: "crypto/aes",
-		NewImport: "crypto/cipher",
-		Old:       "*aes.Cipher",
-		New:       "cipher.Block",
-	},
-	{
-		OldImport: "crypto/des",
-		NewImport: "crypto/cipher",
-		Old:       "*des.Cipher",
-		New:       "cipher.Block",
-	},
-	{
-		OldImport: "crypto/des",
-		NewImport: "crypto/cipher",
-		Old:       "*des.TripleDESCipher",
-		New:       "cipher.Block",
-	},
-	{
-		OldImport: "encoding/json",
-		NewImport: "",
-		Old:       "json.MarshalForHTML",
-		New:       "json.Marshal",
-	},
-	{
-		OldImport: "net/url",
-		NewImport: "",
-		Old:       "url.ParseWithReference",
-		New:       "url.Parse",
-	},
-	{
-		OldImport: "net/url",
-		NewImport: "",
-		Old:       "url.ParseRequest",
-		New:       "url.ParseRequestURI",
-	},
-	{
-		OldImport: "os",
-		NewImport: "syscall",
-		Old:       "os.Exec",
-		New:       "syscall.Exec",
-	},
-	{
-		OldImport: "runtime",
-		NewImport: "",
-		Old:       "runtime.Cgocalls",
-		New:       "runtime.NumCgoCall",
-	},
-	{
-		OldImport: "runtime",
-		NewImport: "",
-		Old:       "runtime.Goroutines",
-		New:       "runtime.NumGoroutine",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.ErrPersistEOF",
-		New:       "httputil.ErrPersistEOF",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.ErrPipeline",
-		New:       "httputil.ErrPipeline",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.ErrClosed",
-		New:       "httputil.ErrClosed",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.ServerConn",
-		New:       "httputil.ServerConn",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.ClientConn",
-		New:       "httputil.ClientConn",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.NewChunkedReader",
-		New:       "httputil.NewChunkedReader",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.NewChunkedWriter",
-		New:       "httputil.NewChunkedWriter",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.ReverseProxy",
-		New:       "httputil.ReverseProxy",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.NewSingleHostReverseProxy",
-		New:       "httputil.NewSingleHostReverseProxy",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.DumpRequest",
-		New:       "httputil.DumpRequest",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.DumpRequestOut",
-		New:       "httputil.DumpRequestOut",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.DumpResponse",
-		New:       "httputil.DumpResponse",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.NewClientConn",
-		New:       "httputil.NewClientConn",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.NewServerConn",
-		New:       "httputil.NewServerConn",
-	},
-	{
-		OldImport: "net/http",
-		NewImport: "net/http/httputil",
-		Old:       "http.NewProxyClientConn",
-		New:       "httputil.NewProxyClientConn",
-	},
-}
diff --git a/src/cmd/fix/go1rename_test.go b/src/cmd/fix/go1rename_test.go
deleted file mode 100644
index 90219ba..0000000
--- a/src/cmd/fix/go1rename_test.go
+++ /dev/null
@@ -1,195 +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 main
-
-func init() {
-	addTestCases(go1renameTests, go1renameFix.f)
-}
-
-var go1renameTests = []testCase{
-	{
-		Name: "go1rename.0",
-		In: `package main
-
-import (
-	"crypto/aes"
-	"crypto/des"
-	"encoding/json"
-	"net/http"
-	"net/url"
-	"os"
-	"runtime"
-)
-
-var (
-	_ *aes.Cipher
-	_ *des.Cipher
-	_ *des.TripleDESCipher
-	_ = json.MarshalForHTML
-	_ = aes.New()
-	_ = url.Parse
-	_ = url.ParseWithReference
-	_ = url.ParseRequest
-	_ = os.Exec
-	_ = runtime.Cgocalls
-	_ = runtime.Goroutines
-	_ = http.ErrPersistEOF
-	_ = http.ErrPipeline
-	_ = http.ErrClosed
-	_ = http.NewSingleHostReverseProxy
-	_ = http.NewChunkedReader
-	_ = http.NewChunkedWriter
-	_ *http.ReverseProxy
-	_ *http.ClientConn
-	_ *http.ServerConn
-)
-`,
-		Out: `package main
-
-import (
-	"crypto/aes"
-	"crypto/cipher"
-	"encoding/json"
-	"net/http/httputil"
-	"net/url"
-	"runtime"
-	"syscall"
-)
-
-var (
-	_ cipher.Block
-	_ cipher.Block
-	_ cipher.Block
-	_ = json.Marshal
-	_ = aes.New()
-	_ = url.Parse
-	_ = url.Parse
-	_ = url.ParseRequestURI
-	_ = syscall.Exec
-	_ = runtime.NumCgoCall
-	_ = runtime.NumGoroutine
-	_ = httputil.ErrPersistEOF
-	_ = httputil.ErrPipeline
-	_ = httputil.ErrClosed
-	_ = httputil.NewSingleHostReverseProxy
-	_ = httputil.NewChunkedReader
-	_ = httputil.NewChunkedWriter
-	_ *httputil.ReverseProxy
-	_ *httputil.ClientConn
-	_ *httputil.ServerConn
-)
-`,
-	},
-	{
-		Name: "httputil.0",
-		In: `package main
-
-import "net/http"
-
-func f() {
-	http.DumpRequest(nil, false)
-	http.DumpRequestOut(nil, false)
-	http.DumpResponse(nil, false)
-	http.NewChunkedReader(nil)
-	http.NewChunkedWriter(nil)
-	http.NewClientConn(nil, nil)
-	http.NewProxyClientConn(nil, nil)
-	http.NewServerConn(nil, nil)
-	http.NewSingleHostReverseProxy(nil)
-}
-`,
-		Out: `package main
-
-import "net/http/httputil"
-
-func f() {
-	httputil.DumpRequest(nil, false)
-	httputil.DumpRequestOut(nil, false)
-	httputil.DumpResponse(nil, false)
-	httputil.NewChunkedReader(nil)
-	httputil.NewChunkedWriter(nil)
-	httputil.NewClientConn(nil, nil)
-	httputil.NewProxyClientConn(nil, nil)
-	httputil.NewServerConn(nil, nil)
-	httputil.NewSingleHostReverseProxy(nil)
-}
-`,
-	},
-	{
-		Name: "httputil.1",
-		In: `package main
-
-import "net/http"
-
-func f() {
-	http.DumpRequest(nil, false)
-	http.DumpRequestOut(nil, false)
-	http.DumpResponse(nil, false)
-	http.NewChunkedReader(nil)
-	http.NewChunkedWriter(nil)
-	http.NewClientConn(nil, nil)
-	http.NewProxyClientConn(nil, nil)
-	http.NewServerConn(nil, nil)
-	http.NewSingleHostReverseProxy(nil)
-}
-`,
-		Out: `package main
-
-import "net/http/httputil"
-
-func f() {
-	httputil.DumpRequest(nil, false)
-	httputil.DumpRequestOut(nil, false)
-	httputil.DumpResponse(nil, false)
-	httputil.NewChunkedReader(nil)
-	httputil.NewChunkedWriter(nil)
-	httputil.NewClientConn(nil, nil)
-	httputil.NewProxyClientConn(nil, nil)
-	httputil.NewServerConn(nil, nil)
-	httputil.NewSingleHostReverseProxy(nil)
-}
-`,
-	},
-	{
-		Name: "httputil.2",
-		In: `package main
-
-import "net/http"
-
-func f() {
-	http.DumpRequest(nil, false)
-	http.DumpRequestOut(nil, false)
-	http.DumpResponse(nil, false)
-	http.NewChunkedReader(nil)
-	http.NewChunkedWriter(nil)
-	http.NewClientConn(nil, nil)
-	http.NewProxyClientConn(nil, nil)
-	http.NewServerConn(nil, nil)
-	http.NewSingleHostReverseProxy(nil)
-	http.Get("")
-}
-`,
-		Out: `package main
-
-import (
-	"net/http"
-	"net/http/httputil"
-)
-
-func f() {
-	httputil.DumpRequest(nil, false)
-	httputil.DumpRequestOut(nil, false)
-	httputil.DumpResponse(nil, false)
-	httputil.NewChunkedReader(nil)
-	httputil.NewChunkedWriter(nil)
-	httputil.NewClientConn(nil, nil)
-	httputil.NewProxyClientConn(nil, nil)
-	httputil.NewServerConn(nil, nil)
-	httputil.NewSingleHostReverseProxy(nil)
-	http.Get("")
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/googlecode.go b/src/cmd/fix/googlecode.go
deleted file mode 100644
index 143781a..0000000
--- a/src/cmd/fix/googlecode.go
+++ /dev/null
@@ -1,41 +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 main
-
-import (
-	"go/ast"
-	"regexp"
-)
-
-func init() {
-	register(googlecodeFix)
-}
-
-var googlecodeFix = fix{
-	"googlecode",
-	"2011-11-21",
-	googlecode,
-	`Rewrite Google Code imports from the deprecated form
-"foo.googlecode.com/vcs/path" to "code.google.com/p/foo/path".
-`,
-}
-
-var googlecodeRe = regexp.MustCompile(`^([a-z0-9\-]+)\.googlecode\.com/(svn|git|hg)(/[a-z0-9A-Z_.\-/]+)?$`)
-
-func googlecode(f *ast.File) bool {
-	fixed := false
-
-	for _, s := range f.Imports {
-		old := importPath(s)
-		if m := googlecodeRe.FindStringSubmatch(old); m != nil {
-			new := "code.google.com/p/" + m[1] + m[3]
-			if rewriteImport(f, old, new) {
-				fixed = true
-			}
-		}
-	}
-
-	return fixed
-}
diff --git a/src/cmd/fix/googlecode_test.go b/src/cmd/fix/googlecode_test.go
deleted file mode 100644
index c62ee4f..0000000
--- a/src/cmd/fix/googlecode_test.go
+++ /dev/null
@@ -1,31 +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 main
-
-func init() {
-	addTestCases(googlecodeTests, googlecode)
-}
-
-var googlecodeTests = []testCase{
-	{
-		Name: "googlecode.0",
-		In: `package main
-
-import (
-	"foo.googlecode.com/hg/bar"
-	"go-qux-23.googlecode.com/svn"
-	"zap.googlecode.com/git/some/path"
-)
-`,
-		Out: `package main
-
-import (
-	"code.google.com/p/foo/bar"
-	"code.google.com/p/go-qux-23"
-	"code.google.com/p/zap/some/path"
-)
-`,
-	},
-}
diff --git a/src/cmd/fix/hashsum.go b/src/cmd/fix/hashsum.go
deleted file mode 100644
index 0df6ad7..0000000
--- a/src/cmd/fix/hashsum.go
+++ /dev/null
@@ -1,94 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(hashSumFix)
-}
-
-var hashSumFix = fix{
-	"hashsum",
-	"2011-11-30",
-	hashSumFn,
-	`Pass a nil argument to calls to hash.Sum
-
-This fix rewrites code so that it passes a nil argument to hash.Sum.
-The additional argument will allow callers to avoid an
-allocation in the future.
-
-http://codereview.appspot.com/5448065
-`,
-}
-
-// Type-checking configuration: tell the type-checker this basic
-// information about types, functions, and variables in external packages.
-var hashSumTypeConfig = &TypeConfig{
-	Var: map[string]string{
-		"crypto.MD4":       "crypto.Hash",
-		"crypto.MD5":       "crypto.Hash",
-		"crypto.SHA1":      "crypto.Hash",
-		"crypto.SHA224":    "crypto.Hash",
-		"crypto.SHA256":    "crypto.Hash",
-		"crypto.SHA384":    "crypto.Hash",
-		"crypto.SHA512":    "crypto.Hash",
-		"crypto.MD5SHA1":   "crypto.Hash",
-		"crypto.RIPEMD160": "crypto.Hash",
-	},
-
-	Func: map[string]string{
-		"adler32.New":    "hash.Hash",
-		"crc32.New":      "hash.Hash",
-		"crc32.NewIEEE":  "hash.Hash",
-		"crc64.New":      "hash.Hash",
-		"fnv.New32a":     "hash.Hash",
-		"fnv.New32":      "hash.Hash",
-		"fnv.New64a":     "hash.Hash",
-		"fnv.New64":      "hash.Hash",
-		"hmac.New":       "hash.Hash",
-		"hmac.NewMD5":    "hash.Hash",
-		"hmac.NewSHA1":   "hash.Hash",
-		"hmac.NewSHA256": "hash.Hash",
-		"md4.New":        "hash.Hash",
-		"md5.New":        "hash.Hash",
-		"ripemd160.New":  "hash.Hash",
-		"sha1.New224":    "hash.Hash",
-		"sha1.New":       "hash.Hash",
-		"sha256.New224":  "hash.Hash",
-		"sha256.New":     "hash.Hash",
-		"sha512.New384":  "hash.Hash",
-		"sha512.New":     "hash.Hash",
-	},
-
-	Type: map[string]*Type{
-		"crypto.Hash": {
-			Method: map[string]string{
-				"New": "func() hash.Hash",
-			},
-		},
-	},
-}
-
-func hashSumFn(f *ast.File) bool {
-	typeof, _ := typecheck(hashSumTypeConfig, f)
-
-	fixed := false
-
-	walk(f, func(n interface{}) {
-		call, ok := n.(*ast.CallExpr)
-		if ok && len(call.Args) == 0 {
-			sel, ok := call.Fun.(*ast.SelectorExpr)
-			if ok && sel.Sel.Name == "Sum" && typeof[sel.X] == "hash.Hash" {
-				call.Args = append(call.Args, ast.NewIdent("nil"))
-				fixed = true
-			}
-		}
-	})
-
-	return fixed
-}
diff --git a/src/cmd/fix/hashsum_test.go b/src/cmd/fix/hashsum_test.go
deleted file mode 100644
index 241af20..0000000
--- a/src/cmd/fix/hashsum_test.go
+++ /dev/null
@@ -1,99 +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 main
-
-func init() {
-	addTestCases(hashSumTests, hashSumFn)
-}
-
-var hashSumTests = []testCase{
-	{
-		Name: "hashsum.0",
-		In: `package main
-
-import "crypto/sha256"
-
-func f() []byte {
-	h := sha256.New()
-	return h.Sum()
-}
-`,
-		Out: `package main
-
-import "crypto/sha256"
-
-func f() []byte {
-	h := sha256.New()
-	return h.Sum(nil)
-}
-`,
-	},
-
-	{
-		Name: "hashsum.1",
-		In: `package main
-
-func f(h hash.Hash) []byte {
-	return h.Sum()
-}
-`,
-		Out: `package main
-
-func f(h hash.Hash) []byte {
-	return h.Sum(nil)
-}
-`,
-	},
-
-	{
-		Name: "hashsum.0",
-		In: `package main
-
-import "crypto/sha256"
-
-func f() []byte {
-	h := sha256.New()
-	h.Write([]byte("foo"))
-	digest := h.Sum()
-}
-`,
-		Out: `package main
-
-import "crypto/sha256"
-
-func f() []byte {
-	h := sha256.New()
-	h.Write([]byte("foo"))
-	digest := h.Sum(nil)
-}
-`,
-	},
-
-	{
-		Name: "hashsum.0",
-		In: `package main
-
-import _ "crypto/sha256"
-import "crypto"
-
-func f() []byte {
-	hashType := crypto.SHA256
-	h := hashType.New()
-	digest := h.Sum()
-}
-`,
-		Out: `package main
-
-import _ "crypto/sha256"
-import "crypto"
-
-func f() []byte {
-	hashType := crypto.SHA256
-	h := hashType.New()
-	digest := h.Sum(nil)
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/hmacnew.go b/src/cmd/fix/hmacnew.go
deleted file mode 100644
index c0c44ef..0000000
--- a/src/cmd/fix/hmacnew.go
+++ /dev/null
@@ -1,61 +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 main
-
-import "go/ast"
-
-func init() {
-	register(hmacNewFix)
-}
-
-var hmacNewFix = fix{
-	"hmacnew",
-	"2012-01-19",
-	hmacnew,
-	`Deprecate hmac.NewMD5, hmac.NewSHA1 and hmac.NewSHA256.
-
-This fix rewrites code using hmac.NewMD5, hmac.NewSHA1 and hmac.NewSHA256 to
-use hmac.New:
-
-	hmac.NewMD5(key) -> hmac.New(md5.New, key)
-	hmac.NewSHA1(key) -> hmac.New(sha1.New, key)
-	hmac.NewSHA256(key) -> hmac.New(sha256.New, key)
-
-`,
-}
-
-func hmacnew(f *ast.File) (fixed bool) {
-	if !imports(f, "crypto/hmac") {
-		return
-	}
-
-	walk(f, func(n interface{}) {
-		ce, ok := n.(*ast.CallExpr)
-		if !ok {
-			return
-		}
-
-		var pkg string
-		switch {
-		case isPkgDot(ce.Fun, "hmac", "NewMD5"):
-			pkg = "md5"
-		case isPkgDot(ce.Fun, "hmac", "NewSHA1"):
-			pkg = "sha1"
-		case isPkgDot(ce.Fun, "hmac", "NewSHA256"):
-			pkg = "sha256"
-		default:
-			return
-		}
-
-		addImport(f, "crypto/"+pkg)
-
-		ce.Fun = ast.NewIdent("hmac.New")
-		ce.Args = append([]ast.Expr{ast.NewIdent(pkg + ".New")}, ce.Args...)
-
-		fixed = true
-	})
-
-	return
-}
diff --git a/src/cmd/fix/hmacnew_test.go b/src/cmd/fix/hmacnew_test.go
deleted file mode 100644
index 5aeee85..0000000
--- a/src/cmd/fix/hmacnew_test.go
+++ /dev/null
@@ -1,107 +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 main
-
-func init() {
-	addTestCases(hmacNewTests, hmacnew)
-}
-
-var hmacNewTests = []testCase{
-	{
-		Name: "hmacnew.0",
-		In: `package main
-
-import "crypto/hmac"
-
-var f = hmac.NewSHA1([]byte("some key"))
-`,
-		Out: `package main
-
-import (
-	"crypto/hmac"
-	"crypto/sha1"
-)
-
-var f = hmac.New(sha1.New, []byte("some key"))
-`,
-	},
-	{
-		Name: "hmacnew.1",
-		In: `package main
-
-import "crypto/hmac"
-
-var key = make([]byte, 8)
-var f = hmac.NewSHA1(key)
-`,
-		Out: `package main
-
-import (
-	"crypto/hmac"
-	"crypto/sha1"
-)
-
-var key = make([]byte, 8)
-var f = hmac.New(sha1.New, key)
-`,
-	},
-	{
-		Name: "hmacnew.2",
-		In: `package main
-
-import "crypto/hmac"
-
-var f = hmac.NewMD5([]byte("some key"))
-`,
-		Out: `package main
-
-import (
-	"crypto/hmac"
-	"crypto/md5"
-)
-
-var f = hmac.New(md5.New, []byte("some key"))
-`,
-	},
-	{
-		Name: "hmacnew.3",
-		In: `package main
-
-import "crypto/hmac"
-
-var f = hmac.NewSHA256([]byte("some key"))
-`,
-		Out: `package main
-
-import (
-	"crypto/hmac"
-	"crypto/sha256"
-)
-
-var f = hmac.New(sha256.New, []byte("some key"))
-`,
-	},
-	{
-		Name: "hmacnew.4",
-		In: `package main
-
-import (
-	"crypto/hmac"
-	"crypto/sha1"
-)
-
-var f = hmac.New(sha1.New, []byte("some key"))
-`,
-		Out: `package main
-
-import (
-	"crypto/hmac"
-	"crypto/sha1"
-)
-
-var f = hmac.New(sha1.New, []byte("some key"))
-`,
-	},
-}
diff --git a/src/cmd/fix/htmlerr.go b/src/cmd/fix/htmlerr.go
deleted file mode 100644
index b5105c8..0000000
--- a/src/cmd/fix/htmlerr.go
+++ /dev/null
@@ -1,47 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(htmlerrFix)
-}
-
-var htmlerrFix = fix{
-	"htmlerr",
-	"2011-11-04",
-	htmlerr,
-	`Rename html's Tokenizer.Error method to Err.
-
-http://codereview.appspot.com/5327064/
-`,
-}
-
-var htmlerrTypeConfig = &TypeConfig{
-	Func: map[string]string{
-		"html.NewTokenizer": "html.Tokenizer",
-	},
-}
-
-func htmlerr(f *ast.File) bool {
-	if !imports(f, "html") {
-		return false
-	}
-
-	typeof, _ := typecheck(htmlerrTypeConfig, f)
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		s, ok := n.(*ast.SelectorExpr)
-		if ok && typeof[s.X] == "html.Tokenizer" && s.Sel.Name == "Error" {
-			s.Sel.Name = "Err"
-			fixed = true
-		}
-	})
-	return fixed
-}
diff --git a/src/cmd/fix/htmlerr_test.go b/src/cmd/fix/htmlerr_test.go
deleted file mode 100644
index 043abc4..0000000
--- a/src/cmd/fix/htmlerr_test.go
+++ /dev/null
@@ -1,39 +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 main
-
-func init() {
-	addTestCases(htmlerrTests, htmlerr)
-}
-
-var htmlerrTests = []testCase{
-	{
-		Name: "htmlerr.0",
-		In: `package main
-
-import (
-	"html"
-)
-
-func f() {
-	e := errors.New("")
-	t := html.NewTokenizer(r)
-	_, _ = e.Error(), t.Error()
-}
-`,
-		Out: `package main
-
-import (
-	"html"
-)
-
-func f() {
-	e := errors.New("")
-	t := html.NewTokenizer(r)
-	_, _ = e.Error(), t.Err()
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/httpfinalurl.go b/src/cmd/fix/httpfinalurl.go
deleted file mode 100644
index 49b9f1c..0000000
--- a/src/cmd/fix/httpfinalurl.go
+++ /dev/null
@@ -1,57 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(httpFinalURLFix)
-}
-
-var httpFinalURLFix = fix{
-	"httpfinalurl",
-	"2011-05-13",
-	httpfinalurl,
-	`Adapt http Get calls to not have a finalURL result parameter.
-
-http://codereview.appspot.com/4535056/
-`,
-}
-
-func httpfinalurl(f *ast.File) bool {
-	if !imports(f, "http") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		// Fix up calls to http.Get.
-		//
-		// If they have blank identifiers, remove them:
-		//    resp, _, err := http.Get(url)
-		// -> resp, err := http.Get(url)
-		//
-		// But if they're using the finalURL parameter, warn:
-		//    resp, finalURL, err := http.Get(url)
-		as, ok := n.(*ast.AssignStmt)
-		if !ok || len(as.Lhs) != 3 || len(as.Rhs) != 1 {
-			return
-		}
-
-		if !isCall(as.Rhs[0], "http", "Get") {
-			return
-		}
-
-		if isBlank(as.Lhs[1]) {
-			as.Lhs = []ast.Expr{as.Lhs[0], as.Lhs[2]}
-			fixed = true
-		} else {
-			warn(as.Pos(), "call to http.Get records final URL")
-		}
-	})
-	return fixed
-}
diff --git a/src/cmd/fix/httpfinalurl_test.go b/src/cmd/fix/httpfinalurl_test.go
deleted file mode 100644
index 9249f7e..0000000
--- a/src/cmd/fix/httpfinalurl_test.go
+++ /dev/null
@@ -1,37 +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 main
-
-func init() {
-	addTestCases(httpfinalurlTests, httpfinalurl)
-}
-
-var httpfinalurlTests = []testCase{
-	{
-		Name: "finalurl.0",
-		In: `package main
-
-import (
-	"http"
-)
-
-func f() {
-	resp, _, err := http.Get("http://www.google.com/")
-	_, _ = resp, err
-}
-`,
-		Out: `package main
-
-import (
-	"http"
-)
-
-func f() {
-	resp, err := http.Get("http://www.google.com/")
-	_, _ = resp, err
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/httpfs.go b/src/cmd/fix/httpfs.go
deleted file mode 100644
index d87b30f..0000000
--- a/src/cmd/fix/httpfs.go
+++ /dev/null
@@ -1,70 +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 main
-
-import (
-	"go/ast"
-	"go/token"
-)
-
-func init() {
-	register(httpFileSystemFix)
-}
-
-var httpFileSystemFix = fix{
-	"httpfs",
-	"2011-06-27",
-	httpfs,
-	`Adapt http FileServer to take a FileSystem.
-
-http://codereview.appspot.com/4629047  http FileSystem interface
-`,
-}
-
-func httpfs(f *ast.File) bool {
-	if !imports(f, "http") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		call, ok := n.(*ast.CallExpr)
-		if !ok || !isPkgDot(call.Fun, "http", "FileServer") {
-			return
-		}
-		if len(call.Args) != 2 {
-			return
-		}
-		dir, prefix := call.Args[0], call.Args[1]
-		call.Args = []ast.Expr{&ast.CallExpr{
-			Fun: &ast.SelectorExpr{
-				X:   ast.NewIdent("http"),
-				Sel: ast.NewIdent("Dir"),
-			},
-			Args: []ast.Expr{dir},
-		}}
-		wrapInStripHandler := true
-		if prefixLit, ok := prefix.(*ast.BasicLit); ok {
-			if prefixLit.Kind == token.STRING && (prefixLit.Value == `"/"` || prefixLit.Value == `""`) {
-				wrapInStripHandler = false
-			}
-		}
-		if wrapInStripHandler {
-			call.Fun.(*ast.SelectorExpr).Sel = ast.NewIdent("StripPrefix")
-			call.Args = []ast.Expr{
-				prefix,
-				&ast.CallExpr{
-					Fun: &ast.SelectorExpr{
-						X:   ast.NewIdent("http"),
-						Sel: ast.NewIdent("FileServer"),
-					},
-					Args: call.Args,
-				},
-			}
-		}
-		fixed = true
-	})
-	return fixed
-}
diff --git a/src/cmd/fix/httpfs_test.go b/src/cmd/fix/httpfs_test.go
deleted file mode 100644
index dd8ef2c..0000000
--- a/src/cmd/fix/httpfs_test.go
+++ /dev/null
@@ -1,47 +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 main
-
-func init() {
-	addTestCases(httpFileSystemTests, httpfs)
-}
-
-var httpFileSystemTests = []testCase{
-	{
-		Name: "httpfs.0",
-		In: `package httpfs
-
-import (
-	"http"
-)
-
-func f() {
-	_ = http.FileServer("/var/www/foo", "/")
-	_ = http.FileServer("/var/www/foo", "")
-	_ = http.FileServer("/var/www/foo/bar", "/bar")
-	s := "/foo"
-	_ = http.FileServer(s, "/")
-	prefix := "/p"
-	_ = http.FileServer(s, prefix)
-}
-`,
-		Out: `package httpfs
-
-import (
-	"http"
-)
-
-func f() {
-	_ = http.FileServer(http.Dir("/var/www/foo"))
-	_ = http.FileServer(http.Dir("/var/www/foo"))
-	_ = http.StripPrefix("/bar", http.FileServer(http.Dir("/var/www/foo/bar")))
-	s := "/foo"
-	_ = http.FileServer(http.Dir(s))
-	prefix := "/p"
-	_ = http.StripPrefix(prefix, http.FileServer(http.Dir(s)))
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/httpheaders.go b/src/cmd/fix/httpheaders.go
deleted file mode 100644
index 15c21ac..0000000
--- a/src/cmd/fix/httpheaders.go
+++ /dev/null
@@ -1,67 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(httpHeadersFix)
-}
-
-var httpHeadersFix = fix{
-	"httpheaders",
-	"2011-06-16",
-	httpheaders,
-	`Rename http Referer, UserAgent, Cookie, SetCookie, which are now methods.
-
-http://codereview.appspot.com/4620049/
-`,
-}
-
-func httpheaders(f *ast.File) bool {
-	if !imports(f, "http") {
-		return false
-	}
-
-	called := make(map[ast.Node]bool)
-	walk(f, func(ni interface{}) {
-		switch n := ni.(type) {
-		case *ast.CallExpr:
-			called[n.Fun] = true
-		}
-	})
-
-	fixed := false
-	typeof, _ := typecheck(headerTypeConfig, f)
-	walk(f, func(ni interface{}) {
-		switch n := ni.(type) {
-		case *ast.SelectorExpr:
-			if called[n] {
-				break
-			}
-			if t := typeof[n.X]; t != "*http.Request" && t != "*http.Response" {
-				break
-			}
-			switch n.Sel.Name {
-			case "Referer", "UserAgent":
-				n.Sel.Name += "()"
-				fixed = true
-			case "Cookie":
-				n.Sel.Name = "Cookies()"
-				fixed = true
-			}
-		}
-	})
-	return fixed
-}
-
-var headerTypeConfig = &TypeConfig{
-	Type: map[string]*Type{
-		"*http.Request":  {},
-		"*http.Response": {},
-	},
-}
diff --git a/src/cmd/fix/httpheaders_test.go b/src/cmd/fix/httpheaders_test.go
deleted file mode 100644
index 37506b8..0000000
--- a/src/cmd/fix/httpheaders_test.go
+++ /dev/null
@@ -1,73 +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 main
-
-func init() {
-	addTestCases(httpHeadersTests, httpheaders)
-}
-
-var httpHeadersTests = []testCase{
-	{
-		Name: "httpheaders.0",
-		In: `package headertest
-
-import (
-	"http"
-)
-
-type Other struct {
-	Referer   string
-	UserAgent string
-	Cookie    []*http.Cookie
-}
-
-func f(req *http.Request, res *http.Response, other *Other) {
-	_ = req.Referer
-	_ = req.UserAgent
-	_ = req.Cookie
-
-	_ = res.Cookie
-
-	_ = other.Referer
-	_ = other.UserAgent
-	_ = other.Cookie
-
-	_ = req.Referer()
-	_ = req.UserAgent()
-	_ = req.Cookies()
-	_ = res.Cookies()
-}
-`,
-		Out: `package headertest
-
-import (
-	"http"
-)
-
-type Other struct {
-	Referer   string
-	UserAgent string
-	Cookie    []*http.Cookie
-}
-
-func f(req *http.Request, res *http.Response, other *Other) {
-	_ = req.Referer()
-	_ = req.UserAgent()
-	_ = req.Cookies()
-
-	_ = res.Cookies()
-
-	_ = other.Referer
-	_ = other.UserAgent
-	_ = other.Cookie
-
-	_ = req.Referer()
-	_ = req.UserAgent()
-	_ = req.Cookies()
-	_ = res.Cookies()
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/httpserver.go b/src/cmd/fix/httpserver.go
deleted file mode 100644
index 7aa6517..0000000
--- a/src/cmd/fix/httpserver.go
+++ /dev/null
@@ -1,141 +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 main
-
-import (
-	"go/ast"
-	"go/token"
-)
-
-func init() {
-	register(httpserverFix)
-}
-
-var httpserverFix = fix{
-	"httpserver",
-	"2011-03-15",
-	httpserver,
-	`Adapt http server methods and functions to changes
-made to the http ResponseWriter interface.
-
-http://codereview.appspot.com/4245064  Hijacker
-http://codereview.appspot.com/4239076  Header
-http://codereview.appspot.com/4239077  Flusher
-http://codereview.appspot.com/4248075  RemoteAddr, UsingTLS
-`,
-}
-
-func httpserver(f *ast.File) bool {
-	if !imports(f, "http") {
-		return false
-	}
-
-	fixed := false
-	for _, decl := range f.Decls {
-		fn, ok := decl.(*ast.FuncDecl)
-		if !ok {
-			continue
-		}
-		w, req, ok := isServeHTTP(fn)
-		if !ok {
-			continue
-		}
-		walk(fn.Body, func(n interface{}) {
-			// Want to replace expression sometimes,
-			// so record pointer to it for updating below.
-			ptr, ok := n.(*ast.Expr)
-			if ok {
-				n = *ptr
-			}
-
-			// Look for w.UsingTLS() and w.Remoteaddr().
-			call, ok := n.(*ast.CallExpr)
-			if !ok || (len(call.Args) != 0 && len(call.Args) != 2) {
-				return
-			}
-			sel, ok := call.Fun.(*ast.SelectorExpr)
-			if !ok {
-				return
-			}
-			if !refersTo(sel.X, w) {
-				return
-			}
-			switch sel.Sel.String() {
-			case "Hijack":
-				// replace w with w.(http.Hijacker)
-				sel.X = &ast.TypeAssertExpr{
-					X:    sel.X,
-					Type: ast.NewIdent("http.Hijacker"),
-				}
-				fixed = true
-			case "Flush":
-				// replace w with w.(http.Flusher)
-				sel.X = &ast.TypeAssertExpr{
-					X:    sel.X,
-					Type: ast.NewIdent("http.Flusher"),
-				}
-				fixed = true
-			case "UsingTLS":
-				if ptr == nil {
-					// can only replace expression if we have pointer to it
-					break
-				}
-				// replace with req.TLS != nil
-				*ptr = &ast.BinaryExpr{
-					X: &ast.SelectorExpr{
-						X:   ast.NewIdent(req.String()),
-						Sel: ast.NewIdent("TLS"),
-					},
-					Op: token.NEQ,
-					Y:  ast.NewIdent("nil"),
-				}
-				fixed = true
-			case "RemoteAddr":
-				if ptr == nil {
-					// can only replace expression if we have pointer to it
-					break
-				}
-				// replace with req.RemoteAddr
-				*ptr = &ast.SelectorExpr{
-					X:   ast.NewIdent(req.String()),
-					Sel: ast.NewIdent("RemoteAddr"),
-				}
-				fixed = true
-			case "SetHeader":
-				// replace w.SetHeader with w.Header().Set
-				// or w.Header().Del if second argument is ""
-				sel.X = &ast.CallExpr{
-					Fun: &ast.SelectorExpr{
-						X:   ast.NewIdent(w.String()),
-						Sel: ast.NewIdent("Header"),
-					},
-				}
-				sel.Sel = ast.NewIdent("Set")
-				if len(call.Args) == 2 && isEmptyString(call.Args[1]) {
-					sel.Sel = ast.NewIdent("Del")
-					call.Args = call.Args[:1]
-				}
-				fixed = true
-			}
-		})
-	}
-	return fixed
-}
-
-func isServeHTTP(fn *ast.FuncDecl) (w, req *ast.Ident, ok bool) {
-	for _, field := range fn.Type.Params.List {
-		if isPkgDot(field.Type, "http", "ResponseWriter") {
-			w = field.Names[0]
-			continue
-		}
-		if isPtrPkgDot(field.Type, "http", "Request") {
-			req = field.Names[0]
-			continue
-		}
-	}
-
-	ok = w != nil && req != nil
-	return
-}
diff --git a/src/cmd/fix/httpserver_test.go b/src/cmd/fix/httpserver_test.go
deleted file mode 100644
index b6ddff2..0000000
--- a/src/cmd/fix/httpserver_test.go
+++ /dev/null
@@ -1,53 +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 main
-
-func init() {
-	addTestCases(httpserverTests, httpserver)
-}
-
-var httpserverTests = []testCase{
-	{
-		Name: "httpserver.0",
-		In: `package main
-
-import "http"
-
-func f(xyz http.ResponseWriter, abc *http.Request, b string) {
-	xyz.SetHeader("foo", "bar")
-	xyz.SetHeader("baz", "")
-	xyz.Hijack()
-	xyz.Flush()
-	go xyz.Hijack()
-	defer xyz.Flush()
-	_ = xyz.UsingTLS()
-	_ = true == xyz.UsingTLS()
-	_ = xyz.RemoteAddr()
-	_ = xyz.RemoteAddr() == "hello"
-	if xyz.UsingTLS() {
-	}
-}
-`,
-		Out: `package main
-
-import "http"
-
-func f(xyz http.ResponseWriter, abc *http.Request, b string) {
-	xyz.Header().Set("foo", "bar")
-	xyz.Header().Del("baz")
-	xyz.(http.Hijacker).Hijack()
-	xyz.(http.Flusher).Flush()
-	go xyz.(http.Hijacker).Hijack()
-	defer xyz.(http.Flusher).Flush()
-	_ = abc.TLS != nil
-	_ = true == (abc.TLS != nil)
-	_ = abc.RemoteAddr
-	_ = abc.RemoteAddr == "hello"
-	if abc.TLS != nil {
-	}
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/imagecolor.go b/src/cmd/fix/imagecolor.go
deleted file mode 100644
index 1aac40a..0000000
--- a/src/cmd/fix/imagecolor.go
+++ /dev/null
@@ -1,85 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(imagecolorFix)
-}
-
-var imagecolorFix = fix{
-	"imagecolor",
-	"2011-10-04",
-	imagecolor,
-	`Adapt code to types moved from image to color.
-
-http://codereview.appspot.com/5132048
-`,
-}
-
-var colorRenames = []struct{ in, out string }{
-	{"Color", "Color"},
-	{"ColorModel", "Model"},
-	{"ColorModelFunc", "ModelFunc"},
-	{"PalettedColorModel", "Palette"},
-
-	{"RGBAColor", "RGBA"},
-	{"RGBA64Color", "RGBA64"},
-	{"NRGBAColor", "NRGBA"},
-	{"NRGBA64Color", "NRGBA64"},
-	{"AlphaColor", "Alpha"},
-	{"Alpha16Color", "Alpha16"},
-	{"GrayColor", "Gray"},
-	{"Gray16Color", "Gray16"},
-
-	{"RGBAColorModel", "RGBAModel"},
-	{"RGBA64ColorModel", "RGBA64Model"},
-	{"NRGBAColorModel", "NRGBAModel"},
-	{"NRGBA64ColorModel", "NRGBA64Model"},
-	{"AlphaColorModel", "AlphaModel"},
-	{"Alpha16ColorModel", "Alpha16Model"},
-	{"GrayColorModel", "GrayModel"},
-	{"Gray16ColorModel", "Gray16Model"},
-}
-
-func imagecolor(f *ast.File) (fixed bool) {
-	if !imports(f, "image") {
-		return
-	}
-
-	walk(f, func(n interface{}) {
-		s, ok := n.(*ast.SelectorExpr)
-
-		if !ok || !isTopName(s.X, "image") {
-			return
-		}
-
-		switch sel := s.Sel.String(); {
-		case sel == "ColorImage":
-			s.Sel = &ast.Ident{Name: "Uniform"}
-			fixed = true
-		case sel == "NewColorImage":
-			s.Sel = &ast.Ident{Name: "NewUniform"}
-			fixed = true
-		default:
-			for _, rename := range colorRenames {
-				if sel == rename.in {
-					addImport(f, "image/color")
-					s.X.(*ast.Ident).Name = "color"
-					s.Sel.Name = rename.out
-					fixed = true
-				}
-			}
-		}
-	})
-
-	if fixed && !usesImport(f, "image") {
-		deleteImport(f, "image")
-	}
-	return
-}
diff --git a/src/cmd/fix/imagecolor_test.go b/src/cmd/fix/imagecolor_test.go
deleted file mode 100644
index c623654..0000000
--- a/src/cmd/fix/imagecolor_test.go
+++ /dev/null
@@ -1,126 +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 main
-
-func init() {
-	addTestCases(colorTests, imagecolor)
-}
-
-var colorTests = []testCase{
-	{
-		Name: "color.0",
-		In: `package main
-
-import (
-	"image"
-)
-
-var (
-	_ image.Image
-	_ image.RGBA
-	_ image.Black
-	_ image.Color
-	_ image.ColorModel
-	_ image.ColorModelFunc
-	_ image.PalettedColorModel
-	_ image.RGBAColor
-	_ image.RGBA64Color
-	_ image.NRGBAColor
-	_ image.NRGBA64Color
-	_ image.AlphaColor
-	_ image.Alpha16Color
-	_ image.GrayColor
-	_ image.Gray16Color
-)
-
-func f() {
-	_ = image.RGBAColorModel
-	_ = image.RGBA64ColorModel
-	_ = image.NRGBAColorModel
-	_ = image.NRGBA64ColorModel
-	_ = image.AlphaColorModel
-	_ = image.Alpha16ColorModel
-	_ = image.GrayColorModel
-	_ = image.Gray16ColorModel
-}
-`,
-		Out: `package main
-
-import (
-	"image"
-	"image/color"
-)
-
-var (
-	_ image.Image
-	_ image.RGBA
-	_ image.Black
-	_ color.Color
-	_ color.Model
-	_ color.ModelFunc
-	_ color.Palette
-	_ color.RGBA
-	_ color.RGBA64
-	_ color.NRGBA
-	_ color.NRGBA64
-	_ color.Alpha
-	_ color.Alpha16
-	_ color.Gray
-	_ color.Gray16
-)
-
-func f() {
-	_ = color.RGBAModel
-	_ = color.RGBA64Model
-	_ = color.NRGBAModel
-	_ = color.NRGBA64Model
-	_ = color.AlphaModel
-	_ = color.Alpha16Model
-	_ = color.GrayModel
-	_ = color.Gray16Model
-}
-`,
-	},
-	{
-		Name: "color.1",
-		In: `package main
-
-import (
-	"fmt"
-	"image"
-)
-
-func f() {
-	fmt.Println(image.RGBAColor{1, 2, 3, 4}.RGBA())
-}
-`,
-		Out: `package main
-
-import (
-	"fmt"
-	"image/color"
-)
-
-func f() {
-	fmt.Println(color.RGBA{1, 2, 3, 4}.RGBA())
-}
-`,
-	},
-	{
-		Name: "color.2",
-		In: `package main
-
-import "image"
-
-var c *image.ColorImage = image.NewColorImage(nil)
-`,
-		Out: `package main
-
-import "image"
-
-var c *image.Uniform = image.NewUniform(nil)
-`,
-	},
-}
diff --git a/src/cmd/fix/imagenew.go b/src/cmd/fix/imagenew.go
deleted file mode 100644
index b4e36d4..0000000
--- a/src/cmd/fix/imagenew.go
+++ /dev/null
@@ -1,83 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(imagenewFix)
-}
-
-var imagenewFix = fix{
-	"imagenew",
-	"2011-09-14",
-	imagenew,
-	`Adapt image.NewXxx calls to pass an image.Rectangle instead of (w, h int).
-
-http://codereview.appspot.com/4964073
-`,
-}
-
-var imagenewFuncs = map[string]bool{
-	"NewRGBA":    true,
-	"NewRGBA64":  true,
-	"NewNRGBA":   true,
-	"NewNRGBA64": true,
-	"NewAlpha":   true,
-	"NewAlpha16": true,
-	"NewGray":    true,
-	"NewGray16":  true,
-}
-
-func imagenew(f *ast.File) bool {
-	if !imports(f, "image") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		call, ok := n.(*ast.CallExpr)
-		if !ok {
-			return
-		}
-		isNewFunc := false
-		for newFunc := range imagenewFuncs {
-			if len(call.Args) == 2 && isPkgDot(call.Fun, "image", newFunc) {
-				isNewFunc = true
-				break
-			}
-		}
-		if len(call.Args) == 3 && isPkgDot(call.Fun, "image", "NewPaletted") {
-			isNewFunc = true
-		}
-		if !isNewFunc {
-			return
-		}
-		// Replace image.NewXxx(w, h) with image.NewXxx(image.Rect(0, 0, w, h)).
-		rectArgs := []ast.Expr{
-			&ast.BasicLit{Value: "0"},
-			&ast.BasicLit{Value: "0"},
-		}
-		rectArgs = append(rectArgs, call.Args[:2]...)
-		rect := []ast.Expr{
-			&ast.CallExpr{
-				Fun: &ast.SelectorExpr{
-					X: &ast.Ident{
-						Name: "image",
-					},
-					Sel: &ast.Ident{
-						Name: "Rect",
-					},
-				},
-				Args: rectArgs,
-			},
-		}
-		call.Args = append(rect, call.Args[2:]...)
-		fixed = true
-	})
-	return fixed
-}
diff --git a/src/cmd/fix/imagenew_test.go b/src/cmd/fix/imagenew_test.go
deleted file mode 100644
index 30abed2..0000000
--- a/src/cmd/fix/imagenew_test.go
+++ /dev/null
@@ -1,51 +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 main
-
-func init() {
-	addTestCases(imagenewTests, imagenew)
-}
-
-var imagenewTests = []testCase{
-	{
-		Name: "imagenew.0",
-		In: `package main
-
-import (
-	"image"
-)
-
-func f() {
-	image.NewRGBA(1, 2)
-	image.NewRGBA64(1, 2)
-	image.NewNRGBA(1, 2)
-	image.NewNRGBA64(1, 2)
-	image.NewAlpha(1, 2)
-	image.NewAlpha16(1, 2)
-	image.NewGray(1, 2)
-	image.NewGray16(1, 2)
-	image.NewPaletted(1, 2, nil)
-}
-`,
-		Out: `package main
-
-import (
-	"image"
-)
-
-func f() {
-	image.NewRGBA(image.Rect(0, 0, 1, 2))
-	image.NewRGBA64(image.Rect(0, 0, 1, 2))
-	image.NewNRGBA(image.Rect(0, 0, 1, 2))
-	image.NewNRGBA64(image.Rect(0, 0, 1, 2))
-	image.NewAlpha(image.Rect(0, 0, 1, 2))
-	image.NewAlpha16(image.Rect(0, 0, 1, 2))
-	image.NewGray(image.Rect(0, 0, 1, 2))
-	image.NewGray16(image.Rect(0, 0, 1, 2))
-	image.NewPaletted(image.Rect(0, 0, 1, 2), nil)
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/imageycbcr.go b/src/cmd/fix/imageycbcr.go
deleted file mode 100644
index 41b96d1..0000000
--- a/src/cmd/fix/imageycbcr.go
+++ /dev/null
@@ -1,64 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(imageycbcrFix)
-}
-
-var imageycbcrFix = fix{
-	"imageycbcr",
-	"2011-12-20",
-	imageycbcr,
-	`Adapt code to types moved from image/ycbcr to image and image/color.
-
-http://codereview.appspot.com/5493084
-`,
-}
-
-func imageycbcr(f *ast.File) (fixed bool) {
-	if !imports(f, "image/ycbcr") {
-		return
-	}
-
-	walk(f, func(n interface{}) {
-		s, ok := n.(*ast.SelectorExpr)
-
-		if !ok || !isTopName(s.X, "ycbcr") {
-			return
-		}
-
-		switch s.Sel.String() {
-		case "RGBToYCbCr", "YCbCrToRGB":
-			addImport(f, "image/color")
-			s.X.(*ast.Ident).Name = "color"
-		case "YCbCrColor":
-			addImport(f, "image/color")
-			s.X.(*ast.Ident).Name = "color"
-			s.Sel.Name = "YCbCr"
-		case "YCbCrColorModel":
-			addImport(f, "image/color")
-			s.X.(*ast.Ident).Name = "color"
-			s.Sel.Name = "YCbCrModel"
-		case "SubsampleRatio", "SubsampleRatio444", "SubsampleRatio422", "SubsampleRatio420":
-			addImport(f, "image")
-			s.X.(*ast.Ident).Name = "image"
-			s.Sel.Name = "YCbCr" + s.Sel.Name
-		case "YCbCr":
-			addImport(f, "image")
-			s.X.(*ast.Ident).Name = "image"
-		default:
-			return
-		}
-		fixed = true
-	})
-
-	deleteImport(f, "image/ycbcr")
-	return
-}
diff --git a/src/cmd/fix/imageycbcr_test.go b/src/cmd/fix/imageycbcr_test.go
deleted file mode 100644
index 23b599d..0000000
--- a/src/cmd/fix/imageycbcr_test.go
+++ /dev/null
@@ -1,54 +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 main
-
-func init() {
-	addTestCases(ycbcrTests, imageycbcr)
-}
-
-var ycbcrTests = []testCase{
-	{
-		Name: "ycbcr.0",
-		In: `package main
-
-import (
-	"image/ycbcr"
-)
-
-func f() {
-	_ = ycbcr.RGBToYCbCr
-	_ = ycbcr.YCbCrToRGB
-	_ = ycbcr.YCbCrColorModel
-	var _ ycbcr.YCbCrColor
-	var _ ycbcr.YCbCr
-	var (
-		_ ycbcr.SubsampleRatio = ycbcr.SubsampleRatio444
-		_ ycbcr.SubsampleRatio = ycbcr.SubsampleRatio422
-		_ ycbcr.SubsampleRatio = ycbcr.SubsampleRatio420
-	)
-}
-`,
-		Out: `package main
-
-import (
-	"image"
-	"image/color"
-)
-
-func f() {
-	_ = color.RGBToYCbCr
-	_ = color.YCbCrToRGB
-	_ = color.YCbCrModel
-	var _ color.YCbCr
-	var _ image.YCbCr
-	var (
-		_ image.YCbCrSubsampleRatio = image.YCbCrSubsampleRatio444
-		_ image.YCbCrSubsampleRatio = image.YCbCrSubsampleRatio422
-		_ image.YCbCrSubsampleRatio = image.YCbCrSubsampleRatio420
-	)
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/iocopyn.go b/src/cmd/fix/iocopyn.go
deleted file mode 100644
index 720f3c6..0000000
--- a/src/cmd/fix/iocopyn.go
+++ /dev/null
@@ -1,41 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(ioCopyNFix)
-}
-
-var ioCopyNFix = fix{
-	"iocopyn",
-	"2011-09-30",
-	ioCopyN,
-	`Rename io.Copyn to io.CopyN.
-
-http://codereview.appspot.com/5157045
-`,
-}
-
-func ioCopyN(f *ast.File) bool {
-	if !imports(f, "io") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		if expr, ok := n.(ast.Expr); ok {
-			if isPkgDot(expr, "io", "Copyn") {
-				expr.(*ast.SelectorExpr).Sel.Name = "CopyN"
-				fixed = true
-				return
-			}
-		}
-	})
-	return fixed
-}
diff --git a/src/cmd/fix/iocopyn_test.go b/src/cmd/fix/iocopyn_test.go
deleted file mode 100644
index f86fad7..0000000
--- a/src/cmd/fix/iocopyn_test.go
+++ /dev/null
@@ -1,37 +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 main
-
-func init() {
-	addTestCases(ioCopyNTests, ioCopyN)
-}
-
-var ioCopyNTests = []testCase{
-	{
-		Name: "io.CopyN.0",
-		In: `package main
-
-import (
-	"io"
-)
-
-func f() {
-	io.Copyn(dst, src)
-	foo.Copyn(dst, src)
-}
-`,
-		Out: `package main
-
-import (
-	"io"
-)
-
-func f() {
-	io.CopyN(dst, src)
-	foo.Copyn(dst, src)
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go
index b151408..dc10d6b 100644
--- a/src/cmd/fix/main.go
+++ b/src/cmd/fix/main.go
@@ -9,8 +9,8 @@ import (
 	"flag"
 	"fmt"
 	"go/ast"
+	"go/format"
 	"go/parser"
-	"go/printer"
 	"go/scanner"
 	"go/token"
 	"io/ioutil"
@@ -97,23 +97,11 @@ func main() {
 	os.Exit(exitCode)
 }
 
-const (
-	tabWidth    = 8
-	parserMode  = parser.ParseComments
-	printerMode = printer.TabIndent | printer.UseSpaces
-)
-
-var printConfig = &printer.Config{
-	Mode:     printerMode,
-	Tabwidth: tabWidth,
-}
+const parserMode = parser.ParseComments
 
 func gofmtFile(f *ast.File) ([]byte, error) {
 	var buf bytes.Buffer
-
-	ast.SortImports(fset, f)
-	err := printConfig.Fprint(&buf, fset, f)
-	if err != nil {
+	if err := format.Node(&buf, fset, f); err != nil {
 		return nil, err
 	}
 	return buf.Bytes(), nil
@@ -211,8 +199,7 @@ var gofmtBuf bytes.Buffer
 
 func gofmt(n interface{}) string {
 	gofmtBuf.Reset()
-	err := printConfig.Fprint(&gofmtBuf, fset, n)
-	if err != nil {
+	if err := format.Node(&gofmtBuf, fset, n); err != nil {
 		return "<" + err.Error() + ">"
 	}
 	return gofmtBuf.String()
diff --git a/src/cmd/fix/mapdelete.go b/src/cmd/fix/mapdelete.go
deleted file mode 100644
index db89c7b..0000000
--- a/src/cmd/fix/mapdelete.go
+++ /dev/null
@@ -1,89 +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 main
-
-import "go/ast"
-
-func init() {
-	register(mapdeleteFix)
-}
-
-var mapdeleteFix = fix{
-	"mapdelete",
-	"2011-10-18",
-	mapdelete,
-	`Use delete(m, k) instead of m[k] = 0, false.
-
-http://codereview.appspot.com/5272045
-`,
-}
-
-func mapdelete(f *ast.File) bool {
-	fixed := false
-	walk(f, func(n interface{}) {
-		stmt, ok := n.(*ast.Stmt)
-		if !ok {
-			return
-		}
-		as, ok := (*stmt).(*ast.AssignStmt)
-		if !ok || len(as.Lhs) != 1 || len(as.Rhs) != 2 {
-			return
-		}
-		ix, ok := as.Lhs[0].(*ast.IndexExpr)
-		if !ok {
-			return
-		}
-		if !isTopName(as.Rhs[1], "false") {
-			warn(as.Pos(), "two-element map assignment with non-false second value")
-			return
-		}
-		if !canDrop(as.Rhs[0]) {
-			warn(as.Pos(), "two-element map assignment with non-trivial first value")
-			return
-		}
-		*stmt = &ast.ExprStmt{
-			X: &ast.CallExpr{
-				Fun: &ast.Ident{
-					NamePos: as.Pos(),
-					Name:    "delete",
-				},
-				Args: []ast.Expr{ix.X, ix.Index},
-			},
-		}
-		fixed = true
-	})
-	return fixed
-}
-
-// canDrop reports whether it is safe to drop the
-// evaluation of n from the program.
-// It is very conservative.
-func canDrop(n ast.Expr) bool {
-	switch n := n.(type) {
-	case *ast.Ident, *ast.BasicLit:
-		return true
-	case *ast.ParenExpr:
-		return canDrop(n.X)
-	case *ast.SelectorExpr:
-		return canDrop(n.X)
-	case *ast.CompositeLit:
-		if !canDrop(n.Type) {
-			return false
-		}
-		for _, e := range n.Elts {
-			if !canDrop(e) {
-				return false
-			}
-		}
-		return true
-	case *ast.StarExpr:
-		// Dropping *x is questionable,
-		// but we have to be able to drop (*T)(nil).
-		return canDrop(n.X)
-	case *ast.ArrayType, *ast.ChanType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.StructType:
-		return true
-	}
-	return false
-}
diff --git a/src/cmd/fix/mapdelete_test.go b/src/cmd/fix/mapdelete_test.go
deleted file mode 100644
index 8ed5032..0000000
--- a/src/cmd/fix/mapdelete_test.go
+++ /dev/null
@@ -1,43 +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 main
-
-func init() {
-	addTestCases(mapdeleteTests, mapdelete)
-}
-
-var mapdeleteTests = []testCase{
-	{
-		Name: "mapdelete.0",
-		In: `package main
-
-func f() {
-	m[x] = 0, false
-	m[x] = g(), false
-	m[x] = 1
-	delete(m, x)
-	m[x] = 0, b
-}
-
-func g(false bool) {
-	m[x] = 0, false
-}
-`,
-		Out: `package main
-
-func f() {
-	delete(m, x)
-	m[x] = g(), false
-	m[x] = 1
-	delete(m, x)
-	m[x] = 0, b
-}
-
-func g(false bool) {
-	m[x] = 0, false
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/math.go b/src/cmd/fix/math.go
deleted file mode 100644
index 2ec837e..0000000
--- a/src/cmd/fix/math.go
+++ /dev/null
@@ -1,51 +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 main
-
-import "go/ast"
-
-func init() {
-	register(mathFix)
-}
-
-var mathFix = fix{
-	"math",
-	"2011-09-29",
-	math,
-	`Remove the leading F from math functions such as Fabs.
-
-http://codereview.appspot.com/5158043
-`,
-}
-
-var mathRenames = []struct{ in, out string }{
-	{"Fabs", "Abs"},
-	{"Fdim", "Dim"},
-	{"Fmax", "Max"},
-	{"Fmin", "Min"},
-	{"Fmod", "Mod"},
-}
-
-func math(f *ast.File) bool {
-	if !imports(f, "math") {
-		return false
-	}
-
-	fixed := false
-
-	walk(f, func(n interface{}) {
-		// Rename functions.
-		if expr, ok := n.(ast.Expr); ok {
-			for _, s := range mathRenames {
-				if isPkgDot(expr, "math", s.in) {
-					expr.(*ast.SelectorExpr).Sel.Name = s.out
-					fixed = true
-					return
-				}
-			}
-		}
-	})
-	return fixed
-}
diff --git a/src/cmd/fix/math_test.go b/src/cmd/fix/math_test.go
deleted file mode 100644
index b8d69d2..0000000
--- a/src/cmd/fix/math_test.go
+++ /dev/null
@@ -1,47 +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 main
-
-func init() {
-	addTestCases(mathTests, math)
-}
-
-var mathTests = []testCase{
-	{
-		Name: "math.0",
-		In: `package main
-
-import (
-	"math"
-)
-
-func f() {
-	math.Fabs(1)
-	math.Fdim(1)
-	math.Fmax(1)
-	math.Fmin(1)
-	math.Fmod(1)
-	math.Abs(1)
-	foo.Fabs(1)
-}
-`,
-		Out: `package main
-
-import (
-	"math"
-)
-
-func f() {
-	math.Abs(1)
-	math.Dim(1)
-	math.Max(1)
-	math.Min(1)
-	math.Mod(1)
-	math.Abs(1)
-	foo.Fabs(1)
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/netdial.go b/src/cmd/fix/netdial.go
deleted file mode 100644
index 2de994c..0000000
--- a/src/cmd/fix/netdial.go
+++ /dev/null
@@ -1,117 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(netdialFix)
-	register(tlsdialFix)
-	register(netlookupFix)
-}
-
-var netdialFix = fix{
-	"netdial",
-	"2011-03-28",
-	netdial,
-	`Adapt 3-argument calls of net.Dial to use 2-argument form.
-
-http://codereview.appspot.com/4244055
-`,
-}
-
-var tlsdialFix = fix{
-	"tlsdial",
-	"2011-03-28",
-	tlsdial,
-	`Adapt 4-argument calls of tls.Dial to use 3-argument form.
-
-http://codereview.appspot.com/4244055
-`,
-}
-
-var netlookupFix = fix{
-	"netlookup",
-	"2011-03-28",
-	netlookup,
-	`Adapt 3-result calls to net.LookupHost to use 2-result form.
-
-http://codereview.appspot.com/4244055
-`,
-}
-
-func netdial(f *ast.File) bool {
-	if !imports(f, "net") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		call, ok := n.(*ast.CallExpr)
-		if !ok || !isPkgDot(call.Fun, "net", "Dial") || len(call.Args) != 3 {
-			return
-		}
-		// net.Dial(a, "", b) -> net.Dial(a, b)
-		if !isEmptyString(call.Args[1]) {
-			warn(call.Pos(), "call to net.Dial with non-empty second argument")
-			return
-		}
-		call.Args[1] = call.Args[2]
-		call.Args = call.Args[:2]
-		fixed = true
-	})
-	return fixed
-}
-
-func tlsdial(f *ast.File) bool {
-	if !imports(f, "crypto/tls") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		call, ok := n.(*ast.CallExpr)
-		if !ok || !isPkgDot(call.Fun, "tls", "Dial") || len(call.Args) != 4 {
-			return
-		}
-		// tls.Dial(a, "", b, c) -> tls.Dial(a, b, c)
-		if !isEmptyString(call.Args[1]) {
-			warn(call.Pos(), "call to tls.Dial with non-empty second argument")
-			return
-		}
-		call.Args[1] = call.Args[2]
-		call.Args[2] = call.Args[3]
-		call.Args = call.Args[:3]
-		fixed = true
-	})
-	return fixed
-}
-
-func netlookup(f *ast.File) bool {
-	if !imports(f, "net") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		as, ok := n.(*ast.AssignStmt)
-		if !ok || len(as.Lhs) != 3 || len(as.Rhs) != 1 {
-			return
-		}
-		call, ok := as.Rhs[0].(*ast.CallExpr)
-		if !ok || !isPkgDot(call.Fun, "net", "LookupHost") {
-			return
-		}
-		if !isBlank(as.Lhs[2]) {
-			warn(as.Pos(), "call to net.LookupHost expecting cname; use net.LookupCNAME")
-			return
-		}
-		as.Lhs = as.Lhs[:2]
-		fixed = true
-	})
-	return fixed
-}
diff --git a/src/cmd/fix/netdial_test.go b/src/cmd/fix/netdial_test.go
deleted file mode 100644
index fff00b4..0000000
--- a/src/cmd/fix/netdial_test.go
+++ /dev/null
@@ -1,57 +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 main
-
-func init() {
-	addTestCases(netdialTests, nil)
-}
-
-var netdialTests = []testCase{
-	{
-		Name: "netdial.0",
-		Fn:   netdial,
-		In: `package main
-
-import "net"
-
-func f() {
-	c, err := net.Dial(net, "", addr)
-	c, err = net.Dial(net, "", addr)
-}
-`,
-		Out: `package main
-
-import "net"
-
-func f() {
-	c, err := net.Dial(net, addr)
-	c, err = net.Dial(net, addr)
-}
-`,
-	},
-
-	{
-		Name: "netlookup.0",
-		Fn:   netlookup,
-		In: `package main
-
-import "net"
-
-func f() {
-	foo, bar, _ := net.LookupHost(host)
-	foo, bar, _ = net.LookupHost(host)
-}
-`,
-		Out: `package main
-
-import "net"
-
-func f() {
-	foo, bar := net.LookupHost(host)
-	foo, bar = net.LookupHost(host)
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/netipv6zone.go b/src/cmd/fix/netipv6zone.go
new file mode 100644
index 0000000..587b9ff
--- /dev/null
+++ b/src/cmd/fix/netipv6zone.go
@@ -0,0 +1,71 @@
+// 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 main
+
+import "go/ast"
+
+func init() {
+	register(netipv6zoneFix)
+}
+
+var netipv6zoneFix = fix{
+	"netipv6zone",
+	"2012-11-26",
+	netipv6zone,
+	`Adapt element key to IPNet, IPAddr, UDPAddr or TCPAddr composite literals.
+
+https://codereview.appspot.com/6849045/
+`,
+}
+
+func netipv6zone(f *ast.File) bool {
+	if !imports(f, "net") {
+		return false
+	}
+
+	fixed := false
+	walk(f, func(n interface{}) {
+		cl, ok := n.(*ast.CompositeLit)
+		if !ok {
+			return
+		}
+		se, ok := cl.Type.(*ast.SelectorExpr)
+		if !ok {
+			return
+		}
+		if !isTopName(se.X, "net") || se.Sel == nil {
+			return
+		}
+		switch ss := se.Sel.String(); ss {
+		case "IPNet", "IPAddr", "UDPAddr", "TCPAddr":
+			for i, e := range cl.Elts {
+				if _, ok := e.(*ast.KeyValueExpr); ok {
+					break
+				}
+				switch i {
+				case 0:
+					cl.Elts[i] = &ast.KeyValueExpr{
+						Key:   ast.NewIdent("IP"),
+						Value: e,
+					}
+				case 1:
+					if ss == "IPNet" {
+						cl.Elts[i] = &ast.KeyValueExpr{
+							Key:   ast.NewIdent("Mask"),
+							Value: e,
+						}
+					} else {
+						cl.Elts[i] = &ast.KeyValueExpr{
+							Key:   ast.NewIdent("Port"),
+							Value: e,
+						}
+					}
+				}
+				fixed = true
+			}
+		}
+	})
+	return fixed
+}
diff --git a/src/cmd/fix/netipv6zone_test.go b/src/cmd/fix/netipv6zone_test.go
new file mode 100644
index 0000000..229daa3
--- /dev/null
+++ b/src/cmd/fix/netipv6zone_test.go
@@ -0,0 +1,51 @@
+// 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 main
+
+func init() {
+	addTestCases(netipv6zoneTests, netipv6zone)
+}
+
+var netipv6zoneTests = []testCase{
+	{
+		Name: "netipv6zone.0",
+		In: `package main
+
+import "net"
+
+var a = []struct {
+	*net.IPNet
+}{
+	&net.IPNet{net.ParseIP("2001:DB8::"), net.IPMask(net.ParseIP("ffff:ffff:ffff::"))},
+}
+
+func f() net.Addr {
+	b := net.IPNet{net.IPv4(127, 0, 0, 1), net.IPv4Mask(255, 0, 0, 0)}
+	c := &net.IPAddr{ip1}
+	sub(&net.UDPAddr{ip2, 12345})
+	d := &net.TCPAddr{IP: ip3, Port: 54321}
+	return &net.TCPAddr{ip4}, nil
+}
+`,
+		Out: `package main
+
+import "net"
+
+var a = []struct {
+	*net.IPNet
+}{
+	&net.IPNet{IP: net.ParseIP("2001:DB8::"), Mask: net.IPMask(net.ParseIP("ffff:ffff:ffff::"))},
+}
+
+func f() net.Addr {
+	b := net.IPNet{IP: net.IPv4(127, 0, 0, 1), Mask: net.IPv4Mask(255, 0, 0, 0)}
+	c := &net.IPAddr{IP: ip1}
+	sub(&net.UDPAddr{IP: ip2, Port: 12345})
+	d := &net.TCPAddr{IP: ip3, Port: 54321}
+	return &net.TCPAddr{IP: ip4}, nil
+}
+`,
+	},
+}
diff --git a/src/cmd/fix/netudpgroup.go b/src/cmd/fix/netudpgroup.go
deleted file mode 100644
index b54beb0..0000000
--- a/src/cmd/fix/netudpgroup.go
+++ /dev/null
@@ -1,58 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(netudpgroupFix)
-}
-
-var netudpgroupFix = fix{
-	"netudpgroup",
-	"2011-08-18",
-	netudpgroup,
-	`Adapt 1-argument calls of net.(*UDPConn).JoinGroup, LeaveGroup to use 2-argument form.
-
-http://codereview.appspot.com/4815074
-`,
-}
-
-func netudpgroup(f *ast.File) bool {
-	if !imports(f, "net") {
-		return false
-	}
-
-	fixed := false
-	for _, d := range f.Decls {
-		fd, ok := d.(*ast.FuncDecl)
-		if !ok || fd.Body == nil {
-			continue
-		}
-		walk(fd.Body, func(n interface{}) {
-			ce, ok := n.(*ast.CallExpr)
-			if !ok {
-				return
-			}
-			se, ok := ce.Fun.(*ast.SelectorExpr)
-			if !ok || len(ce.Args) != 1 {
-				return
-			}
-			switch se.Sel.String() {
-			case "JoinGroup", "LeaveGroup":
-				// c.JoinGroup(a) -> c.JoinGroup(nil, a)
-				// c.LeaveGroup(a) -> c.LeaveGroup(nil, a)
-				arg := ce.Args[0]
-				ce.Args = make([]ast.Expr, 2)
-				ce.Args[0] = ast.NewIdent("nil")
-				ce.Args[1] = arg
-				fixed = true
-			}
-		})
-	}
-	return fixed
-}
diff --git a/src/cmd/fix/netudpgroup_test.go b/src/cmd/fix/netudpgroup_test.go
deleted file mode 100644
index 88c0e09..0000000
--- a/src/cmd/fix/netudpgroup_test.go
+++ /dev/null
@@ -1,53 +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 main
-
-func init() {
-	addTestCases(netudpgroupTests, netudpgroup)
-}
-
-var netudpgroupTests = []testCase{
-	{
-		Name: "netudpgroup.0",
-		In: `package main
-
-import "net"
-
-func f() {
-	err := x.JoinGroup(gaddr)
-	err = y.LeaveGroup(gaddr)
-}
-`,
-		Out: `package main
-
-import "net"
-
-func f() {
-	err := x.JoinGroup(nil, gaddr)
-	err = y.LeaveGroup(nil, gaddr)
-}
-`,
-	},
-	// Innocent function with no body.
-	{
-		Name: "netudpgroup.1",
-		In: `package main
-
-import "net"
-
-func f()
-
-var _ net.IP
-`,
-		Out: `package main
-
-import "net"
-
-func f()
-
-var _ net.IP
-`,
-	},
-}
diff --git a/src/cmd/fix/newwriter.go b/src/cmd/fix/newwriter.go
deleted file mode 100644
index 4befe24..0000000
--- a/src/cmd/fix/newwriter.go
+++ /dev/null
@@ -1,90 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(newWriterFix)
-}
-
-var newWriterFix = fix{
-	"newWriter",
-	"2012-02-14",
-	newWriter,
-	`Adapt bufio, gzip and zlib NewWriterXxx calls for whether they return errors.
-
-Also rename gzip.Compressor and gzip.Decompressor to gzip.Writer and gzip.Reader.
-
-http://codereview.appspot.com/5639057 and
-http://codereview.appspot.com/5642054
-`,
-}
-
-func newWriter(f *ast.File) bool {
-	if !imports(f, "bufio") && !imports(f, "compress/gzip") && !imports(f, "compress/zlib") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		switch n := n.(type) {
-		case *ast.SelectorExpr:
-			if isTopName(n.X, "gzip") {
-				switch n.Sel.String() {
-				case "Compressor":
-					n.Sel = &ast.Ident{Name: "Writer"}
-					fixed = true
-				case "Decompressor":
-					n.Sel = &ast.Ident{Name: "Reader"}
-					fixed = true
-				}
-			} else if isTopName(n.X, "zlib") {
-				if n.Sel.String() == "NewWriterDict" {
-					n.Sel = &ast.Ident{Name: "NewWriterLevelDict"}
-					fixed = true
-				}
-			}
-
-		case *ast.AssignStmt:
-			// Drop the ", _" in assignments of the form:
-			//	w0, _ = gzip.NewWriter(w1)
-			if len(n.Lhs) != 2 || len(n.Rhs) != 1 {
-				return
-			}
-			i, ok := n.Lhs[1].(*ast.Ident)
-			if !ok {
-				return
-			}
-			if i.String() != "_" {
-				return
-			}
-			c, ok := n.Rhs[0].(*ast.CallExpr)
-			if !ok {
-				return
-			}
-			s, ok := c.Fun.(*ast.SelectorExpr)
-			if !ok {
-				return
-			}
-			sel := s.Sel.String()
-			switch {
-			case isTopName(s.X, "bufio") && (sel == "NewReaderSize" || sel == "NewWriterSize"):
-				// No-op.
-			case isTopName(s.X, "gzip") && sel == "NewWriter":
-				// No-op.
-			case isTopName(s.X, "zlib") && sel == "NewWriter":
-				// No-op.
-			default:
-				return
-			}
-			n.Lhs = n.Lhs[:1]
-			fixed = true
-		}
-	})
-	return fixed
-}
diff --git a/src/cmd/fix/newwriter_test.go b/src/cmd/fix/newwriter_test.go
deleted file mode 100644
index 1f59628..0000000
--- a/src/cmd/fix/newwriter_test.go
+++ /dev/null
@@ -1,83 +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 main
-
-func init() {
-	addTestCases(newWriterTests, newWriter)
-}
-
-var newWriterTests = []testCase{
-	{
-		Name: "newWriter.0",
-		In: `package main
-
-import (
-	"bufio"
-	"compress/gzip"
-	"compress/zlib"
-	"io"
-
-	"foo"
-)
-
-func f() *gzip.Compressor {
-	var (
-		_ gzip.Compressor
-		_ *gzip.Decompressor
-		_ struct {
-			W *gzip.Compressor
-			R gzip.Decompressor
-		}
-	)
-
-	var w io.Writer
-	br := bufio.NewReader(nil)
-	br, _ = bufio.NewReaderSize(nil, 256)
-	bw, err := bufio.NewWriterSize(w, 256) // Unfixable, as it declares an err variable.
-	bw, _ = bufio.NewWriterSize(w, 256)
-	fw, _ := foo.NewWriter(w)
-	gw, _ := gzip.NewWriter(w)
-	gw, _ = gzip.NewWriter(w)
-	zw, _ := zlib.NewWriter(w)
-	_ = zlib.NewWriterDict(zw, 0, nil)
-	return gw
-}
-`,
-		Out: `package main
-
-import (
-	"bufio"
-	"compress/gzip"
-	"compress/zlib"
-	"io"
-
-	"foo"
-)
-
-func f() *gzip.Writer {
-	var (
-		_ gzip.Writer
-		_ *gzip.Reader
-		_ struct {
-			W *gzip.Writer
-			R gzip.Reader
-		}
-	)
-
-	var w io.Writer
-	br := bufio.NewReader(nil)
-	br = bufio.NewReaderSize(nil, 256)
-	bw, err := bufio.NewWriterSize(w, 256) // Unfixable, as it declares an err variable.
-	bw = bufio.NewWriterSize(w, 256)
-	fw, _ := foo.NewWriter(w)
-	gw := gzip.NewWriter(w)
-	gw = gzip.NewWriter(w)
-	zw := zlib.NewWriter(w)
-	_ = zlib.NewWriterLevelDict(zw, 0, nil)
-	return gw
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/oserrorstring.go b/src/cmd/fix/oserrorstring.go
deleted file mode 100644
index a75a2c1..0000000
--- a/src/cmd/fix/oserrorstring.go
+++ /dev/null
@@ -1,75 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(oserrorstringFix)
-}
-
-var oserrorstringFix = fix{
-	"oserrorstring",
-	"2011-06-22",
-	oserrorstring,
-	`Replace os.ErrorString() conversions with calls to os.NewError().
-
-http://codereview.appspot.com/4607052
-`,
-}
-
-func oserrorstring(f *ast.File) bool {
-	if !imports(f, "os") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		// The conversion os.ErrorString(x) looks like a call
-		// of os.ErrorString with one argument.
-		if call := callExpr(n, "os", "ErrorString"); call != nil {
-			// os.ErrorString(args) -> os.NewError(args)
-			call.Fun.(*ast.SelectorExpr).Sel.Name = "NewError"
-			// os.ErrorString(args) -> os.NewError(args)
-			call.Fun.(*ast.SelectorExpr).Sel.Name = "NewError"
-			fixed = true
-			return
-		}
-
-		// Remove os.Error type from variable declarations initialized
-		// with an os.NewError.
-		// (An *ast.ValueSpec may also be used in a const declaration
-		// but those won't be initialized with a call to os.NewError.)
-		if spec, ok := n.(*ast.ValueSpec); ok &&
-			len(spec.Names) == 1 &&
-			isPkgDot(spec.Type, "os", "Error") &&
-			len(spec.Values) == 1 &&
-			callExpr(spec.Values[0], "os", "NewError") != nil {
-			// var name os.Error = os.NewError(x) ->
-			// var name          = os.NewError(x)
-			spec.Type = nil
-			fixed = true
-			return
-		}
-
-		// Other occurrences of os.ErrorString are not fixed
-		// but they are rare.
-
-	})
-	return fixed
-}
-
-// callExpr returns the call expression if x is a call to pkg.name with one argument;
-// otherwise it returns nil.
-func callExpr(x interface{}, pkg, name string) *ast.CallExpr {
-	if call, ok := x.(*ast.CallExpr); ok &&
-		len(call.Args) == 1 &&
-		isPkgDot(call.Fun, pkg, name) {
-		return call
-	}
-	return nil
-}
diff --git a/src/cmd/fix/oserrorstring_test.go b/src/cmd/fix/oserrorstring_test.go
deleted file mode 100644
index 7555148..0000000
--- a/src/cmd/fix/oserrorstring_test.go
+++ /dev/null
@@ -1,57 +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 main
-
-func init() {
-	addTestCases(oserrorstringTests, oserrorstring)
-}
-
-var oserrorstringTests = []testCase{
-	{
-		Name: "oserrorstring.0",
-		In: `package main
-
-import "os"
-
-var _ = os.ErrorString("foo")
-var _ os.Error = os.ErrorString("bar1")
-var _ os.Error = os.NewError("bar2")
-var _ os.Error = MyError("bal") // don't rewrite this one
-
-var (
-	_          = os.ErrorString("foo")
-	_ os.Error = os.ErrorString("bar1")
-	_ os.Error = os.NewError("bar2")
-	_ os.Error = MyError("bal") // don't rewrite this one
-)
-
-func _() (err os.Error) {
-	err = os.ErrorString("foo")
-	return os.ErrorString("foo")
-}
-`,
-		Out: `package main
-
-import "os"
-
-var _ = os.NewError("foo")
-var _ = os.NewError("bar1")
-var _ = os.NewError("bar2")
-var _ os.Error = MyError("bal") // don't rewrite this one
-
-var (
-	_          = os.NewError("foo")
-	_          = os.NewError("bar1")
-	_          = os.NewError("bar2")
-	_ os.Error = MyError("bal") // don't rewrite this one
-)
-
-func _() (err os.Error) {
-	err = os.NewError("foo")
-	return os.NewError("foo")
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/osopen.go b/src/cmd/fix/osopen.go
deleted file mode 100644
index af2796a..0000000
--- a/src/cmd/fix/osopen.go
+++ /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.
-
-package main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(osopenFix)
-}
-
-var osopenFix = fix{
-	"osopen",
-	"2011-04-04",
-	osopen,
-	`Adapt os.Open calls to new, easier API and rename O_CREAT O_CREATE.
-
-http://codereview.appspot.com/4357052
-`,
-}
-
-func osopen(f *ast.File) bool {
-	if !imports(f, "os") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		// Rename O_CREAT to O_CREATE.
-		if expr, ok := n.(ast.Expr); ok && isPkgDot(expr, "os", "O_CREAT") {
-			expr.(*ast.SelectorExpr).Sel.Name = "O_CREATE"
-			fixed = true
-			return
-		}
-
-		// Fix up calls to Open.
-		call, ok := n.(*ast.CallExpr)
-		if !ok || len(call.Args) != 3 {
-			return
-		}
-		if !isPkgDot(call.Fun, "os", "Open") {
-			return
-		}
-		sel := call.Fun.(*ast.SelectorExpr)
-		args := call.Args
-		// os.Open(a, os.O_RDONLY, c) -> os.Open(a)
-		if isPkgDot(args[1], "os", "O_RDONLY") || isPkgDot(args[1], "syscall", "O_RDONLY") {
-			call.Args = call.Args[0:1]
-			fixed = true
-			return
-		}
-		// os.Open(a, createlike_flags, c) -> os.Create(a, c)
-		if isCreateFlag(args[1]) {
-			sel.Sel.Name = "Create"
-			if !isSimplePerm(args[2]) {
-				warn(sel.Pos(), "rewrote os.Open to os.Create with permission not 0666")
-			}
-			call.Args = args[0:1]
-			fixed = true
-			return
-		}
-		// Fallback: os.Open(a, b, c) -> os.OpenFile(a, b, c)
-		sel.Sel.Name = "OpenFile"
-		fixed = true
-	})
-	return fixed
-}
-
-func isCreateFlag(flag ast.Expr) bool {
-	foundCreate := false
-	foundTrunc := false
-	// OR'ing of flags: is O_CREATE on?  + or | would be fine; we just look for os.O_CREATE
-	// and don't worry about the actual operator.
-	p := flag.Pos()
-	for {
-		lhs := flag
-		expr, isBinary := flag.(*ast.BinaryExpr)
-		if isBinary {
-			lhs = expr.Y
-		}
-		sel, ok := lhs.(*ast.SelectorExpr)
-		if !ok || !isTopName(sel.X, "os") {
-			return false
-		}
-		switch sel.Sel.Name {
-		case "O_CREATE":
-			foundCreate = true
-		case "O_TRUNC":
-			foundTrunc = true
-		case "O_RDONLY", "O_WRONLY", "O_RDWR":
-			// okay 
-		default:
-			// Unexpected flag, like O_APPEND or O_EXCL.
-			// Be conservative and do not rewrite.
-			return false
-		}
-		if !isBinary {
-			break
-		}
-		flag = expr.X
-	}
-	if !foundCreate {
-		return false
-	}
-	if !foundTrunc {
-		warn(p, "rewrote os.Open with O_CREATE but not O_TRUNC to os.Create")
-	}
-	return foundCreate
-}
-
-func isSimplePerm(perm ast.Expr) bool {
-	basicLit, ok := perm.(*ast.BasicLit)
-	if !ok {
-		return false
-	}
-	switch basicLit.Value {
-	case "0666":
-		return true
-	}
-	return false
-}
diff --git a/src/cmd/fix/osopen_test.go b/src/cmd/fix/osopen_test.go
deleted file mode 100644
index 5797adb..0000000
--- a/src/cmd/fix/osopen_test.go
+++ /dev/null
@@ -1,82 +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 main
-
-func init() {
-	addTestCases(osopenTests, osopen)
-}
-
-var osopenTests = []testCase{
-	{
-		Name: "osopen.0",
-		In: `package main
-
-import (
-	"os"
-)
-
-func f() {
-	os.OpenFile(a, b, c)
-	os.Open(a, os.O_RDONLY, 0)
-	os.Open(a, os.O_RDONLY, 0666)
-	os.Open(a, os.O_RDWR, 0)
-	os.Open(a, os.O_CREAT, 0666)
-	os.Open(a, os.O_CREAT|os.O_TRUNC, 0664)
-	os.Open(a, os.O_CREATE, 0666)
-	os.Open(a, os.O_CREATE|os.O_TRUNC, 0664)
-	os.Open(a, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
-	os.Open(a, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
-	os.Open(a, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
-	os.Open(a, os.O_SURPRISE|os.O_CREATE, 0666)
-	_ = os.O_CREAT
-}
-`,
-		Out: `package main
-
-import (
-	"os"
-)
-
-func f() {
-	os.OpenFile(a, b, c)
-	os.Open(a)
-	os.Open(a)
-	os.OpenFile(a, os.O_RDWR, 0)
-	os.Create(a)
-	os.Create(a)
-	os.Create(a)
-	os.Create(a)
-	os.Create(a)
-	os.OpenFile(a, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
-	os.OpenFile(a, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
-	os.OpenFile(a, os.O_SURPRISE|os.O_CREATE, 0666)
-	_ = os.O_CREATE
-}
-`,
-	},
-	{
-		Name: "osopen.1",
-		In: `package main
-
-import (
-	"os"
-)
-
-func f() {
-	_ = os.O_CREAT
-}
-`,
-		Out: `package main
-
-import (
-	"os"
-)
-
-func f() {
-	_ = os.O_CREATE
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/printerconfig.go b/src/cmd/fix/printerconfig.go
new file mode 100644
index 0000000..432e18b
--- /dev/null
+++ b/src/cmd/fix/printerconfig.go
@@ -0,0 +1,61 @@
+// 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 main
+
+import "go/ast"
+
+func init() {
+	register(printerconfigFix)
+}
+
+var printerconfigFix = fix{
+	"printerconfig",
+	"2012-12-11",
+	printerconfig,
+	`Add element keys to Config composite literals.`,
+}
+
+func printerconfig(f *ast.File) bool {
+	if !imports(f, "go/printer") {
+		return false
+	}
+
+	fixed := false
+	walk(f, func(n interface{}) {
+		cl, ok := n.(*ast.CompositeLit)
+		if !ok {
+			return
+		}
+		se, ok := cl.Type.(*ast.SelectorExpr)
+		if !ok {
+			return
+		}
+		if !isTopName(se.X, "printer") || se.Sel == nil {
+			return
+		}
+
+		if ss := se.Sel.String(); ss == "Config" {
+			for i, e := range cl.Elts {
+				if _, ok := e.(*ast.KeyValueExpr); ok {
+					break
+				}
+				switch i {
+				case 0:
+					cl.Elts[i] = &ast.KeyValueExpr{
+						Key:   ast.NewIdent("Mode"),
+						Value: e,
+					}
+				case 1:
+					cl.Elts[i] = &ast.KeyValueExpr{
+						Key:   ast.NewIdent("Tabwidth"),
+						Value: e,
+					}
+				}
+				fixed = true
+			}
+		}
+	})
+	return fixed
+}
diff --git a/src/cmd/fix/printerconfig_test.go b/src/cmd/fix/printerconfig_test.go
new file mode 100644
index 0000000..72e2bdc
--- /dev/null
+++ b/src/cmd/fix/printerconfig_test.go
@@ -0,0 +1,37 @@
+// 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 main
+
+func init() {
+	addTestCases(printerconfigTests, printerconfig)
+}
+
+var printerconfigTests = []testCase{
+	{
+		Name: "printerconfig.0",
+		In: `package main
+
+import "go/printer"
+
+func f() printer.Config {
+	b := printer.Config{0, 8}
+	c := &printer.Config{0}
+	d := &printer.Config{Tabwidth: 8, Mode: 0}
+	return printer.Config{0, 8}
+}
+`,
+		Out: `package main
+
+import "go/printer"
+
+func f() printer.Config {
+	b := printer.Config{Mode: 0, Tabwidth: 8}
+	c := &printer.Config{Mode: 0}
+	d := &printer.Config{Tabwidth: 8, Mode: 0}
+	return printer.Config{Mode: 0, Tabwidth: 8}
+}
+`,
+	},
+}
diff --git a/src/cmd/fix/procattr.go b/src/cmd/fix/procattr.go
deleted file mode 100644
index ea375ec..0000000
--- a/src/cmd/fix/procattr.go
+++ /dev/null
@@ -1,62 +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 main
-
-import (
-	"go/ast"
-	"go/token"
-)
-
-func init() {
-	register(procattrFix)
-}
-
-var procattrFix = fix{
-	"procattr",
-	"2011-03-15",
-	procattr,
-	`Adapt calls to os.StartProcess to use new ProcAttr type.
-
-http://codereview.appspot.com/4253052
-`,
-}
-
-func procattr(f *ast.File) bool {
-	if !imports(f, "os") && !imports(f, "syscall") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		call, ok := n.(*ast.CallExpr)
-		if !ok || len(call.Args) != 5 {
-			return
-		}
-		var pkg string
-		if isPkgDot(call.Fun, "os", "StartProcess") {
-			pkg = "os"
-		} else if isPkgDot(call.Fun, "syscall", "StartProcess") {
-			pkg = "syscall"
-		} else {
-			return
-		}
-		// os.StartProcess(a, b, c, d, e) -> os.StartProcess(a, b, &os.ProcAttr{Env: c, Dir: d, Files: e})
-		lit := &ast.CompositeLit{Type: ast.NewIdent(pkg + ".ProcAttr")}
-		env, dir, files := call.Args[2], call.Args[3], call.Args[4]
-		if !isName(env, "nil") && !isCall(env, "os", "Environ") {
-			lit.Elts = append(lit.Elts, &ast.KeyValueExpr{Key: ast.NewIdent("Env"), Value: env})
-		}
-		if !isEmptyString(dir) {
-			lit.Elts = append(lit.Elts, &ast.KeyValueExpr{Key: ast.NewIdent("Dir"), Value: dir})
-		}
-		if !isName(files, "nil") {
-			lit.Elts = append(lit.Elts, &ast.KeyValueExpr{Key: ast.NewIdent("Files"), Value: files})
-		}
-		call.Args[2] = &ast.UnaryExpr{Op: token.AND, X: lit}
-		call.Args = call.Args[:3]
-		fixed = true
-	})
-	return fixed
-}
diff --git a/src/cmd/fix/procattr_test.go b/src/cmd/fix/procattr_test.go
deleted file mode 100644
index 9e2b86e..0000000
--- a/src/cmd/fix/procattr_test.go
+++ /dev/null
@@ -1,74 +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 main
-
-func init() {
-	addTestCases(procattrTests, procattr)
-}
-
-var procattrTests = []testCase{
-	{
-		Name: "procattr.0",
-		In: `package main
-
-import (
-	"os"
-	"syscall"
-)
-
-func f() {
-	os.StartProcess(a, b, c, d, e)
-	os.StartProcess(a, b, os.Environ(), d, e)
-	os.StartProcess(a, b, nil, d, e)
-	os.StartProcess(a, b, c, "", e)
-	os.StartProcess(a, b, c, d, nil)
-	os.StartProcess(a, b, nil, "", nil)
-
-	os.StartProcess(
-		a,
-		b,
-		c,
-		d,
-		e,
-	)
-
-	syscall.StartProcess(a, b, c, d, e)
-	syscall.StartProcess(a, b, os.Environ(), d, e)
-	syscall.StartProcess(a, b, nil, d, e)
-	syscall.StartProcess(a, b, c, "", e)
-	syscall.StartProcess(a, b, c, d, nil)
-	syscall.StartProcess(a, b, nil, "", nil)
-}
-`,
-		Out: `package main
-
-import (
-	"os"
-	"syscall"
-)
-
-func f() {
-	os.StartProcess(a, b, &os.ProcAttr{Env: c, Dir: d, Files: e})
-	os.StartProcess(a, b, &os.ProcAttr{Dir: d, Files: e})
-	os.StartProcess(a, b, &os.ProcAttr{Dir: d, Files: e})
-	os.StartProcess(a, b, &os.ProcAttr{Env: c, Files: e})
-	os.StartProcess(a, b, &os.ProcAttr{Env: c, Dir: d})
-	os.StartProcess(a, b, &os.ProcAttr{})
-
-	os.StartProcess(
-		a,
-		b, &os.ProcAttr{Env: c, Dir: d, Files: e},
-	)
-
-	syscall.StartProcess(a, b, &syscall.ProcAttr{Env: c, Dir: d, Files: e})
-	syscall.StartProcess(a, b, &syscall.ProcAttr{Dir: d, Files: e})
-	syscall.StartProcess(a, b, &syscall.ProcAttr{Dir: d, Files: e})
-	syscall.StartProcess(a, b, &syscall.ProcAttr{Env: c, Files: e})
-	syscall.StartProcess(a, b, &syscall.ProcAttr{Env: c, Dir: d})
-	syscall.StartProcess(a, b, &syscall.ProcAttr{})
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/reflect.go b/src/cmd/fix/reflect.go
deleted file mode 100644
index 151da56..0000000
--- a/src/cmd/fix/reflect.go
+++ /dev/null
@@ -1,862 +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.
-
-// TODO(rsc): Once there is better support for writing
-// multi-package commands, this should really be in
-// its own package, and then we can drop all the "reflect"
-// prefixes on the global variables and functions.
-
-package main
-
-import (
-	"go/ast"
-	"go/token"
-	"strings"
-)
-
-func init() {
-	register(reflectFix)
-}
-
-var reflectFix = fix{
-	"reflect",
-	"2011-04-08",
-	reflectFn,
-	`Adapt code to new reflect API.
-
-http://codereview.appspot.com/4281055
-http://codereview.appspot.com/4433066
-`,
-}
-
-// The reflect API change dropped the concrete types *reflect.ArrayType etc.
-// Any type assertions prior to method calls can be deleted:
-//	x.(*reflect.ArrayType).Len() -> x.Len()
-//
-// Any type checks can be replaced by assignment and check of Kind:
-//	x, y := z.(*reflect.ArrayType)
-// ->
-//	x := z
-//	y := x.Kind() == reflect.Array
-//
-// If z is an ordinary variable name and x is not subsequently assigned to,
-// references to x can be replaced by z and the assignment deleted.
-// We only bother if x and z are the same name.  
-// If y is not subsequently assigned to and neither is x, references to
-// y can be replaced by its expression.  We only bother when there is
-// just one use or when the use appears in an if clause.
-//
-// Not all type checks result in a single Kind check.  The rewrite of the type check for
-// reflect.ArrayOrSliceType checks x.Kind() against reflect.Array and reflect.Slice.
-// The rewrite for *reflect.IntType checks against Int, Int8, Int16, Int32, Int64.
-// The rewrite for *reflect.UintType adds Uintptr.
-//
-// A type switch turns into an assignment and a switch on Kind:
-//	switch x := y.(type) {
-//	case reflect.ArrayOrSliceType:
-//		...
-//	case *reflect.ChanType:
-//		...
-//	case *reflect.IntType:
-//		...
-//	}
-// ->
-//	switch x := y; x.Kind() {
-//	case reflect.Array, reflect.Slice:
-//		...
-//	case reflect.Chan:
-//		...
-//	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-//		...
-//	}
-//
-// The same simplification applies: we drop x := x if x is not assigned
-// to in the switch cases.
-//
-// Because the type check assignment includes a type assertion in its
-// syntax and the rewrite traversal is bottom up, we must do a pass to
-// rewrite the type check assignments and then a separate pass to 
-// rewrite the type assertions.
-//
-// The same process applies to the API changes for reflect.Value.
-//
-// For both cases, but especially Value, the code needs to be aware
-// of the type of a receiver when rewriting a method call.   For example,
-// x.(*reflect.ArrayValue).Elem(i) becomes x.Index(i) while 
-// x.(*reflect.MapValue).Elem(v) becomes x.MapIndex(v).
-// In general, reflectFn needs to know the type of the receiver expression.
-// In most cases (and in all the cases in the Go source tree), the toy
-// type checker in typecheck.go provides enough information for fix
-// to make the rewrite.  If fix misses a rewrite, the code that is left over
-// will not compile, so it will be noticed immediately.
-
-func reflectFn(f *ast.File) bool {
-	if !imports(f, "reflect") {
-		return false
-	}
-
-	fixed := false
-
-	// Rewrite names in method calls.
-	// Needs basic type information (see above).
-	typeof, _ := typecheck(reflectTypeConfig, f)
-	walk(f, func(n interface{}) {
-		switch n := n.(type) {
-		case *ast.SelectorExpr:
-			typ := typeof[n.X]
-			if m := reflectRewriteMethod[typ]; m != nil {
-				if replace := m[n.Sel.Name]; replace != "" {
-					n.Sel.Name = replace
-					fixed = true
-					return
-				}
-			}
-
-			// For all reflect Values, replace SetValue with Set.
-			if isReflectValue[typ] && n.Sel.Name == "SetValue" {
-				n.Sel.Name = "Set"
-				fixed = true
-				return
-			}
-
-			// Replace reflect.MakeZero with reflect.Zero.
-			if isPkgDot(n, "reflect", "MakeZero") {
-				n.Sel.Name = "Zero"
-				fixed = true
-				return
-			}
-		}
-	})
-
-	// Replace PtrValue's PointTo(x) with Set(x.Addr()).
-	walk(f, func(n interface{}) {
-		call, ok := n.(*ast.CallExpr)
-		if !ok || len(call.Args) != 1 {
-			return
-		}
-		sel, ok := call.Fun.(*ast.SelectorExpr)
-		if !ok || sel.Sel.Name != "PointTo" {
-			return
-		}
-		typ := typeof[sel.X]
-		if typ != "*reflect.PtrValue" {
-			return
-		}
-		sel.Sel.Name = "Set"
-		if !isTopName(call.Args[0], "nil") {
-			call.Args[0] = &ast.SelectorExpr{
-				X:   call.Args[0],
-				Sel: ast.NewIdent("Addr()"),
-			}
-		}
-		fixed = true
-	})
-
-	// Fix type switches.
-	walk(f, func(n interface{}) {
-		if reflectFixSwitch(n) {
-			fixed = true
-		}
-	})
-
-	// Fix type assertion checks (multiple assignment statements).
-	// Have to work on the statement context (statement list or if statement)
-	// so that we can insert an extra statement occasionally.
-	// Ignoring for and switch because they don't come up in
-	// typical code.
-	walk(f, func(n interface{}) {
-		switch n := n.(type) {
-		case *[]ast.Stmt:
-			// v is the replacement statement list.
-			var v []ast.Stmt
-			insert := func(x ast.Stmt) {
-				v = append(v, x)
-			}
-			for i, x := range *n {
-				// Tentatively append to v; if we rewrite x
-				// we'll have to update the entry, so remember
-				// the index.
-				j := len(v)
-				v = append(v, x)
-				if reflectFixTypecheck(&x, insert, (*n)[i+1:]) {
-					// reflectFixTypecheck may have overwritten x.
-					// Update the entry we appended just before the call.
-					v[j] = x
-					fixed = true
-				}
-			}
-			*n = v
-		case *ast.IfStmt:
-			x := &ast.ExprStmt{X: n.Cond}
-			if reflectFixTypecheck(&n.Init, nil, []ast.Stmt{x, n.Body, n.Else}) {
-				n.Cond = x.X
-				fixed = true
-			}
-		}
-	})
-
-	// Warn about any typecheck statements that we missed.
-	walk(f, reflectWarnTypecheckStmt)
-
-	// Now that those are gone, fix remaining type assertions.
-	// Delayed because the type checks have
-	// type assertions as part of their syntax.
-	walk(f, func(n interface{}) {
-		if reflectFixAssert(n) {
-			fixed = true
-		}
-	})
-
-	// Now that the type assertions are gone, rewrite remaining
-	// references to specific reflect types to use the general ones.
-	walk(f, func(n interface{}) {
-		ptr, ok := n.(*ast.Expr)
-		if !ok {
-			return
-		}
-		nn := *ptr
-		typ := reflectType(nn)
-		if typ == "" {
-			return
-		}
-		if strings.HasSuffix(typ, "Type") {
-			*ptr = newPkgDot(nn.Pos(), "reflect", "Type")
-		} else {
-			*ptr = newPkgDot(nn.Pos(), "reflect", "Value")
-		}
-		fixed = true
-	})
-
-	// Rewrite v.Set(nil) to v.Set(reflect.MakeZero(v.Type())).
-	walk(f, func(n interface{}) {
-		call, ok := n.(*ast.CallExpr)
-		if !ok || len(call.Args) != 1 || !isTopName(call.Args[0], "nil") {
-			return
-		}
-		sel, ok := call.Fun.(*ast.SelectorExpr)
-		if !ok || !isReflectValue[typeof[sel.X]] || sel.Sel.Name != "Set" {
-			return
-		}
-		call.Args[0] = &ast.CallExpr{
-			Fun: newPkgDot(call.Args[0].Pos(), "reflect", "Zero"),
-			Args: []ast.Expr{
-				&ast.CallExpr{
-					Fun: &ast.SelectorExpr{
-						X:   sel.X,
-						Sel: &ast.Ident{Name: "Type"},
-					},
-				},
-			},
-		}
-		fixed = true
-	})
-
-	// Rewrite v != nil to v.IsValid().
-	// Rewrite nil used as reflect.Value (in function argument or return) to reflect.Value{}.
-	walk(f, func(n interface{}) {
-		ptr, ok := n.(*ast.Expr)
-		if !ok {
-			return
-		}
-		if isTopName(*ptr, "nil") && isReflectValue[typeof[*ptr]] {
-			*ptr = ast.NewIdent("reflect.Value{}")
-			fixed = true
-			return
-		}
-		nn, ok := (*ptr).(*ast.BinaryExpr)
-		if !ok || (nn.Op != token.EQL && nn.Op != token.NEQ) || !isTopName(nn.Y, "nil") || !isReflectValue[typeof[nn.X]] {
-			return
-		}
-		var call ast.Expr = &ast.CallExpr{
-			Fun: &ast.SelectorExpr{
-				X:   nn.X,
-				Sel: &ast.Ident{Name: "IsValid"},
-			},
-		}
-		if nn.Op == token.EQL {
-			call = &ast.UnaryExpr{Op: token.NOT, X: call}
-		}
-		*ptr = call
-		fixed = true
-	})
-
-	// Rewrite
-	//	reflect.Typeof -> reflect.TypeOf,
-	walk(f, func(n interface{}) {
-		sel, ok := n.(*ast.SelectorExpr)
-		if !ok {
-			return
-		}
-		if isTopName(sel.X, "reflect") && sel.Sel.Name == "Typeof" {
-			sel.Sel.Name = "TypeOf"
-			fixed = true
-		}
-		if isTopName(sel.X, "reflect") && sel.Sel.Name == "NewValue" {
-			sel.Sel.Name = "ValueOf"
-			fixed = true
-		}
-	})
-
-	return fixed
-}
-
-// reflectFixSwitch rewrites *n (if n is an *ast.Stmt) corresponding
-// to a type switch.
-func reflectFixSwitch(n interface{}) bool {
-	ptr, ok := n.(*ast.Stmt)
-	if !ok {
-		return false
-	}
-	n = *ptr
-
-	ts, ok := n.(*ast.TypeSwitchStmt)
-	if !ok {
-		return false
-	}
-
-	// Are any switch cases referring to reflect types?
-	// (That is, is this an old reflect type switch?)
-	for _, cas := range ts.Body.List {
-		for _, typ := range cas.(*ast.CaseClause).List {
-			if reflectType(typ) != "" {
-				goto haveReflect
-			}
-		}
-	}
-	return false
-
-haveReflect:
-	// Now we know it's an old reflect type switch.  Prepare the new version,
-	// but don't replace or edit the original until we're sure of success.
-
-	// Figure out the initializer statement, if any, and the receiver for the Kind call.
-	var init ast.Stmt
-	var rcvr ast.Expr
-
-	init = ts.Init
-	switch n := ts.Assign.(type) {
-	default:
-		warn(ts.Pos(), "unexpected form in type switch")
-		return false
-
-	case *ast.AssignStmt:
-		as := n
-		ta := as.Rhs[0].(*ast.TypeAssertExpr)
-		x := isIdent(as.Lhs[0])
-		z := isIdent(ta.X)
-
-		if isBlank(x) || x != nil && z != nil && x.Name == z.Name && !assignsTo(x, ts.Body.List) {
-			// Can drop the variable creation.
-			rcvr = ta.X
-		} else {
-			// Need to use initialization statement.
-			if init != nil {
-				warn(ts.Pos(), "cannot rewrite reflect type switch with initializing statement")
-				return false
-			}
-			init = &ast.AssignStmt{
-				Lhs:    []ast.Expr{as.Lhs[0]},
-				TokPos: as.TokPos,
-				Tok:    token.DEFINE,
-				Rhs:    []ast.Expr{ta.X},
-			}
-			rcvr = as.Lhs[0]
-		}
-
-	case *ast.ExprStmt:
-		rcvr = n.X.(*ast.TypeAssertExpr).X
-	}
-
-	// Prepare rewritten type switch (see large comment above for form).
-	sw := &ast.SwitchStmt{
-		Switch: ts.Switch,
-		Init:   init,
-		Tag: &ast.CallExpr{
-			Fun: &ast.SelectorExpr{
-				X: rcvr,
-				Sel: &ast.Ident{
-					NamePos: rcvr.End(),
-					Name:    "Kind",
-					Obj:     nil,
-				},
-			},
-			Lparen: rcvr.End(),
-			Rparen: rcvr.End(),
-		},
-		Body: &ast.BlockStmt{
-			Lbrace: ts.Body.Lbrace,
-			List:   nil, // to be filled in
-			Rbrace: ts.Body.Rbrace,
-		},
-	}
-
-	// Translate cases.
-	for _, tcas := range ts.Body.List {
-		tcas := tcas.(*ast.CaseClause)
-		cas := &ast.CaseClause{
-			Case:  tcas.Case,
-			Colon: tcas.Colon,
-			Body:  tcas.Body,
-		}
-		for _, t := range tcas.List {
-			if isTopName(t, "nil") {
-				cas.List = append(cas.List, newPkgDot(t.Pos(), "reflect", "Invalid"))
-				continue
-			}
-
-			typ := reflectType(t)
-			if typ == "" {
-				warn(t.Pos(), "cannot rewrite reflect type switch case with non-reflect type %s", gofmt(t))
-				cas.List = append(cas.List, t)
-				continue
-			}
-
-			for _, k := range reflectKind[typ] {
-				cas.List = append(cas.List, newPkgDot(t.Pos(), "reflect", k))
-			}
-		}
-		sw.Body.List = append(sw.Body.List, cas)
-	}
-
-	// Everything worked.  Rewrite AST.
-	*ptr = sw
-	return true
-}
-
-// Rewrite x, y = z.(T) into
-//	x = z
-//	y = x.Kind() == K
-// as described in the long comment above.
-//
-// If insert != nil, it can be called to insert a statement after *ptr in its block.
-// If insert == nil, insertion is not possible.
-// At most one call to insert is allowed.
-//
-// Scope gives the statements for which a declaration
-// in *ptr would be in scope.
-//
-// The result is true of the statement was rewritten.
-//
-func reflectFixTypecheck(ptr *ast.Stmt, insert func(ast.Stmt), scope []ast.Stmt) bool {
-	st := *ptr
-	as, ok := st.(*ast.AssignStmt)
-	if !ok || len(as.Lhs) != 2 || len(as.Rhs) != 1 {
-		return false
-	}
-
-	ta, ok := as.Rhs[0].(*ast.TypeAssertExpr)
-	if !ok {
-		return false
-	}
-	typ := reflectType(ta.Type)
-	if typ == "" {
-		return false
-	}
-
-	// Have x, y := z.(t).
-	x := isIdent(as.Lhs[0])
-	y := isIdent(as.Lhs[1])
-	z := isIdent(ta.X)
-
-	// First step is x := z, unless it's x := x and the resulting x is never reassigned.
-	// rcvr is the x in x.Kind().
-	var rcvr ast.Expr
-	if isBlank(x) ||
-		as.Tok == token.DEFINE && x != nil && z != nil && x.Name == z.Name && !assignsTo(x, scope) {
-		// Can drop the statement.
-		// If we need to insert a statement later, now we have a slot.
-		*ptr = &ast.EmptyStmt{}
-		insert = func(x ast.Stmt) { *ptr = x }
-		rcvr = ta.X
-	} else {
-		*ptr = &ast.AssignStmt{
-			Lhs:    []ast.Expr{as.Lhs[0]},
-			TokPos: as.TokPos,
-			Tok:    as.Tok,
-			Rhs:    []ast.Expr{ta.X},
-		}
-		rcvr = as.Lhs[0]
-	}
-
-	// Prepare x.Kind() == T expression appropriate to t.
-	// If x is not a simple identifier, warn that we might be
-	// reevaluating x.
-	if x == nil {
-		warn(as.Pos(), "rewrite reevaluates expr with possible side effects: %s", gofmt(as.Lhs[0]))
-	}
-	yExpr, yNotExpr := reflectKindEq(rcvr, reflectKind[typ])
-
-	// Second step is y := x.Kind() == T, unless it's only used once
-	// or we have no way to insert that statement.
-	var yStmt *ast.AssignStmt
-	if as.Tok == token.DEFINE && countUses(y, scope) <= 1 || insert == nil {
-		// Can drop the statement and use the expression directly.
-		rewriteUses(y,
-			func(token.Pos) ast.Expr { return yExpr },
-			func(token.Pos) ast.Expr { return yNotExpr },
-			scope)
-	} else {
-		yStmt = &ast.AssignStmt{
-			Lhs:    []ast.Expr{as.Lhs[1]},
-			TokPos: as.End(),
-			Tok:    as.Tok,
-			Rhs:    []ast.Expr{yExpr},
-		}
-		insert(yStmt)
-	}
-	return true
-}
-
-// reflectKindEq returns the expression z.Kind() == kinds[0] || z.Kind() == kinds[1] || ...
-// and its negation.
-// The qualifier "reflect." is inserted before each kinds[i] expression.
-func reflectKindEq(z ast.Expr, kinds []string) (ast.Expr, ast.Expr) {
-	n := len(kinds)
-	if n == 1 {
-		y := &ast.BinaryExpr{
-			X: &ast.CallExpr{
-				Fun: &ast.SelectorExpr{
-					X:   z,
-					Sel: ast.NewIdent("Kind"),
-				},
-			},
-			Op: token.EQL,
-			Y:  newPkgDot(token.NoPos, "reflect", kinds[0]),
-		}
-		ynot := &ast.BinaryExpr{
-			X: &ast.CallExpr{
-				Fun: &ast.SelectorExpr{
-					X:   z,
-					Sel: ast.NewIdent("Kind"),
-				},
-			},
-			Op: token.NEQ,
-			Y:  newPkgDot(token.NoPos, "reflect", kinds[0]),
-		}
-		return y, ynot
-	}
-
-	x, xnot := reflectKindEq(z, kinds[0:n-1])
-	y, ynot := reflectKindEq(z, kinds[n-1:])
-
-	or := &ast.BinaryExpr{
-		X:  x,
-		Op: token.LOR,
-		Y:  y,
-	}
-	andnot := &ast.BinaryExpr{
-		X:  xnot,
-		Op: token.LAND,
-		Y:  ynot,
-	}
-	return or, andnot
-}
-
-// if x represents a known old reflect type/value like *reflect.PtrType or reflect.ArrayOrSliceValue,
-// reflectType returns the string form of that type.
-func reflectType(x ast.Expr) string {
-	ptr, ok := x.(*ast.StarExpr)
-	if ok {
-		x = ptr.X
-	}
-
-	sel, ok := x.(*ast.SelectorExpr)
-	if !ok || !isName(sel.X, "reflect") {
-		return ""
-	}
-
-	var s = "reflect."
-	if ptr != nil {
-		s = "*reflect."
-	}
-	s += sel.Sel.Name
-
-	if reflectKind[s] != nil {
-		return s
-	}
-	return ""
-}
-
-// reflectWarnTypecheckStmt warns about statements
-// of the form x, y = z.(T) for any old reflect type T.
-// The last pass should have gotten them all, and if it didn't,
-// the next pass is going to turn them into x, y = z.
-func reflectWarnTypecheckStmt(n interface{}) {
-	as, ok := n.(*ast.AssignStmt)
-	if !ok || len(as.Lhs) != 2 || len(as.Rhs) != 1 {
-		return
-	}
-	ta, ok := as.Rhs[0].(*ast.TypeAssertExpr)
-	if !ok || reflectType(ta.Type) == "" {
-		return
-	}
-	warn(n.(ast.Node).Pos(), "unfixed reflect type check")
-}
-
-// reflectFixAssert rewrites x.(T) to x for any old reflect type T.
-func reflectFixAssert(n interface{}) bool {
-	ptr, ok := n.(*ast.Expr)
-	if ok {
-		ta, ok := (*ptr).(*ast.TypeAssertExpr)
-		if ok && reflectType(ta.Type) != "" {
-			*ptr = ta.X
-			return true
-		}
-	}
-	return false
-}
-
-// Tables describing the transformations.
-
-// Description of old reflect API for partial type checking.
-// We pretend the Elem method is on Type and Value instead
-// of enumerating all the types it is actually on.
-// Also, we pretend that ArrayType etc embeds Type for the
-// purposes of describing the API.  (In fact they embed commonType,
-// which implements Type.)
-var reflectTypeConfig = &TypeConfig{
-	Type: map[string]*Type{
-		"reflect.ArrayOrSliceType":  {Embed: []string{"reflect.Type"}},
-		"reflect.ArrayOrSliceValue": {Embed: []string{"reflect.Value"}},
-		"reflect.ArrayType":         {Embed: []string{"reflect.Type"}},
-		"reflect.ArrayValue":        {Embed: []string{"reflect.Value"}},
-		"reflect.BoolType":          {Embed: []string{"reflect.Type"}},
-		"reflect.BoolValue":         {Embed: []string{"reflect.Value"}},
-		"reflect.ChanType":          {Embed: []string{"reflect.Type"}},
-		"reflect.ChanValue": {
-			Method: map[string]string{
-				"Recv":    "func() (reflect.Value, bool)",
-				"TryRecv": "func() (reflect.Value, bool)",
-			},
-			Embed: []string{"reflect.Value"},
-		},
-		"reflect.ComplexType":  {Embed: []string{"reflect.Type"}},
-		"reflect.ComplexValue": {Embed: []string{"reflect.Value"}},
-		"reflect.FloatType":    {Embed: []string{"reflect.Type"}},
-		"reflect.FloatValue":   {Embed: []string{"reflect.Value"}},
-		"reflect.FuncType": {
-			Method: map[string]string{
-				"In":  "func(int) reflect.Type",
-				"Out": "func(int) reflect.Type",
-			},
-			Embed: []string{"reflect.Type"},
-		},
-		"reflect.FuncValue": {
-			Method: map[string]string{
-				"Call": "func([]reflect.Value) []reflect.Value",
-			},
-		},
-		"reflect.IntType":        {Embed: []string{"reflect.Type"}},
-		"reflect.IntValue":       {Embed: []string{"reflect.Value"}},
-		"reflect.InterfaceType":  {Embed: []string{"reflect.Type"}},
-		"reflect.InterfaceValue": {Embed: []string{"reflect.Value"}},
-		"reflect.MapType": {
-			Method: map[string]string{
-				"Key": "func() reflect.Type",
-			},
-			Embed: []string{"reflect.Type"},
-		},
-		"reflect.MapValue": {
-			Method: map[string]string{
-				"Keys": "func() []reflect.Value",
-			},
-			Embed: []string{"reflect.Value"},
-		},
-		"reflect.Method": {
-			Field: map[string]string{
-				"Type": "*reflect.FuncType",
-				"Func": "*reflect.FuncValue",
-			},
-		},
-		"reflect.PtrType":   {Embed: []string{"reflect.Type"}},
-		"reflect.PtrValue":  {Embed: []string{"reflect.Value"}},
-		"reflect.SliceType": {Embed: []string{"reflect.Type"}},
-		"reflect.SliceValue": {
-			Method: map[string]string{
-				"Slice": "func(int, int) *reflect.SliceValue",
-			},
-			Embed: []string{"reflect.Value"},
-		},
-		"reflect.StringType":  {Embed: []string{"reflect.Type"}},
-		"reflect.StringValue": {Embed: []string{"reflect.Value"}},
-		"reflect.StructField": {
-			Field: map[string]string{
-				"Type": "reflect.Type",
-			},
-		},
-		"reflect.StructType": {
-			Method: map[string]string{
-				"Field":           "func() reflect.StructField",
-				"FieldByIndex":    "func() reflect.StructField",
-				"FieldByName":     "func() reflect.StructField,bool",
-				"FieldByNameFunc": "func() reflect.StructField,bool",
-			},
-			Embed: []string{"reflect.Type"},
-		},
-		"reflect.StructValue": {
-			Method: map[string]string{
-				"Field":           "func() reflect.Value",
-				"FieldByIndex":    "func() reflect.Value",
-				"FieldByName":     "func() reflect.Value",
-				"FieldByNameFunc": "func() reflect.Value",
-			},
-			Embed: []string{"reflect.Value"},
-		},
-		"reflect.Type": {
-			Method: map[string]string{
-				"Elem":   "func() reflect.Type",
-				"Method": "func() reflect.Method",
-			},
-		},
-		"reflect.UintType":           {Embed: []string{"reflect.Type"}},
-		"reflect.UintValue":          {Embed: []string{"reflect.Value"}},
-		"reflect.UnsafePointerType":  {Embed: []string{"reflect.Type"}},
-		"reflect.UnsafePointerValue": {Embed: []string{"reflect.Value"}},
-		"reflect.Value": {
-			Method: map[string]string{
-				"Addr":     "func() *reflect.PtrValue",
-				"Elem":     "func() reflect.Value",
-				"Method":   "func() *reflect.FuncValue",
-				"SetValue": "func(reflect.Value)",
-			},
-		},
-	},
-	Func: map[string]string{
-		"reflect.Append":      "*reflect.SliceValue",
-		"reflect.AppendSlice": "*reflect.SliceValue",
-		"reflect.Indirect":    "reflect.Value",
-		"reflect.MakeSlice":   "*reflect.SliceValue",
-		"reflect.MakeChan":    "*reflect.ChanValue",
-		"reflect.MakeMap":     "*reflect.MapValue",
-		"reflect.MakeZero":    "reflect.Value",
-		"reflect.NewValue":    "reflect.Value",
-		"reflect.PtrTo":       "*reflect.PtrType",
-		"reflect.Typeof":      "reflect.Type",
-	},
-}
-
-var reflectRewriteMethod = map[string]map[string]string{
-	// The type API didn't change much.
-	"*reflect.ChanType": {"Dir": "ChanDir"},
-	"*reflect.FuncType": {"DotDotDot": "IsVariadic"},
-
-	// The value API has longer names to disambiguate
-	// methods with different signatures.
-	"reflect.ArrayOrSliceValue": { // interface, not pointer
-		"Elem": "Index",
-	},
-	"*reflect.ArrayValue": {
-		"Elem": "Index",
-	},
-	"*reflect.BoolValue": {
-		"Get": "Bool",
-		"Set": "SetBool",
-	},
-	"*reflect.ChanValue": {
-		"Get": "Pointer",
-	},
-	"*reflect.ComplexValue": {
-		"Get":      "Complex",
-		"Set":      "SetComplex",
-		"Overflow": "OverflowComplex",
-	},
-	"*reflect.FloatValue": {
-		"Get":      "Float",
-		"Set":      "SetFloat",
-		"Overflow": "OverflowFloat",
-	},
-	"*reflect.FuncValue": {
-		"Get": "Pointer",
-	},
-	"*reflect.IntValue": {
-		"Get":      "Int",
-		"Set":      "SetInt",
-		"Overflow": "OverflowInt",
-	},
-	"*reflect.InterfaceValue": {
-		"Get": "InterfaceData",
-	},
-	"*reflect.MapValue": {
-		"Elem":    "MapIndex",
-		"Get":     "Pointer",
-		"Keys":    "MapKeys",
-		"SetElem": "SetMapIndex",
-	},
-	"*reflect.PtrValue": {
-		"Get": "Pointer",
-	},
-	"*reflect.SliceValue": {
-		"Elem": "Index",
-		"Get":  "Pointer",
-	},
-	"*reflect.StringValue": {
-		"Get": "String",
-		"Set": "SetString",
-	},
-	"*reflect.UintValue": {
-		"Get":      "Uint",
-		"Set":      "SetUint",
-		"Overflow": "OverflowUint",
-	},
-	"*reflect.UnsafePointerValue": {
-		"Get": "Pointer",
-		"Set": "SetPointer",
-	},
-}
-
-var reflectKind = map[string][]string{
-	"reflect.ArrayOrSliceType":   {"Array", "Slice"}, // interface, not pointer
-	"*reflect.ArrayType":         {"Array"},
-	"*reflect.BoolType":          {"Bool"},
-	"*reflect.ChanType":          {"Chan"},
-	"*reflect.ComplexType":       {"Complex64", "Complex128"},
-	"*reflect.FloatType":         {"Float32", "Float64"},
-	"*reflect.FuncType":          {"Func"},
-	"*reflect.IntType":           {"Int", "Int8", "Int16", "Int32", "Int64"},
-	"*reflect.InterfaceType":     {"Interface"},
-	"*reflect.MapType":           {"Map"},
-	"*reflect.PtrType":           {"Ptr"},
-	"*reflect.SliceType":         {"Slice"},
-	"*reflect.StringType":        {"String"},
-	"*reflect.StructType":        {"Struct"},
-	"*reflect.UintType":          {"Uint", "Uint8", "Uint16", "Uint32", "Uint64", "Uintptr"},
-	"*reflect.UnsafePointerType": {"UnsafePointer"},
-
-	"reflect.ArrayOrSliceValue":   {"Array", "Slice"}, // interface, not pointer
-	"*reflect.ArrayValue":         {"Array"},
-	"*reflect.BoolValue":          {"Bool"},
-	"*reflect.ChanValue":          {"Chan"},
-	"*reflect.ComplexValue":       {"Complex64", "Complex128"},
-	"*reflect.FloatValue":         {"Float32", "Float64"},
-	"*reflect.FuncValue":          {"Func"},
-	"*reflect.IntValue":           {"Int", "Int8", "Int16", "Int32", "Int64"},
-	"*reflect.InterfaceValue":     {"Interface"},
-	"*reflect.MapValue":           {"Map"},
-	"*reflect.PtrValue":           {"Ptr"},
-	"*reflect.SliceValue":         {"Slice"},
-	"*reflect.StringValue":        {"String"},
-	"*reflect.StructValue":        {"Struct"},
-	"*reflect.UintValue":          {"Uint", "Uint8", "Uint16", "Uint32", "Uint64", "Uintptr"},
-	"*reflect.UnsafePointerValue": {"UnsafePointer"},
-}
-
-var isReflectValue = map[string]bool{
-	"reflect.ArrayOrSliceValue":   true, // interface, not pointer
-	"*reflect.ArrayValue":         true,
-	"*reflect.BoolValue":          true,
-	"*reflect.ChanValue":          true,
-	"*reflect.ComplexValue":       true,
-	"*reflect.FloatValue":         true,
-	"*reflect.FuncValue":          true,
-	"*reflect.IntValue":           true,
-	"*reflect.InterfaceValue":     true,
-	"*reflect.MapValue":           true,
-	"*reflect.PtrValue":           true,
-	"*reflect.SliceValue":         true,
-	"*reflect.StringValue":        true,
-	"*reflect.StructValue":        true,
-	"*reflect.UintValue":          true,
-	"*reflect.UnsafePointerValue": true,
-	"reflect.Value":               true, // interface, not pointer
-}
diff --git a/src/cmd/fix/reflect_test.go b/src/cmd/fix/reflect_test.go
deleted file mode 100644
index 032cbc7..0000000
--- a/src/cmd/fix/reflect_test.go
+++ /dev/null
@@ -1,35 +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 main
-
-import (
-	"io/ioutil"
-	"log"
-	"path/filepath"
-)
-
-func init() {
-	addTestCases(reflectTests(), reflectFn)
-}
-
-func reflectTests() []testCase {
-	var tests []testCase
-
-	names, _ := filepath.Glob("testdata/reflect.*.in")
-	for _, in := range names {
-		out := in[:len(in)-len(".in")] + ".out"
-		inb, err := ioutil.ReadFile(in)
-		if err != nil {
-			log.Fatal(err)
-		}
-		outb, err := ioutil.ReadFile(out)
-		if err != nil {
-			log.Fatal(err)
-		}
-		tests = append(tests, testCase{Name: in, In: string(inb), Out: string(outb)})
-	}
-
-	return tests
-}
diff --git a/src/cmd/fix/signal.go b/src/cmd/fix/signal.go
deleted file mode 100644
index 5a583d4..0000000
--- a/src/cmd/fix/signal.go
+++ /dev/null
@@ -1,50 +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 main
-
-import (
-	"go/ast"
-	"strings"
-)
-
-func init() {
-	register(signalFix)
-}
-
-var signalFix = fix{
-	"signal",
-	"2011-06-29",
-	signal,
-	`Adapt code to types moved from os/signal to signal.
-
-http://codereview.appspot.com/4437091
-`,
-}
-
-func signal(f *ast.File) (fixed bool) {
-	if !imports(f, "os/signal") {
-		return
-	}
-
-	walk(f, func(n interface{}) {
-		s, ok := n.(*ast.SelectorExpr)
-
-		if !ok || !isTopName(s.X, "signal") {
-			return
-		}
-
-		sel := s.Sel.String()
-		if sel == "Signal" || sel == "UnixSignal" || strings.HasPrefix(sel, "SIG") {
-			addImport(f, "os")
-			s.X = &ast.Ident{Name: "os"}
-			fixed = true
-		}
-	})
-
-	if fixed && !usesImport(f, "os/signal") {
-		deleteImport(f, "os/signal")
-	}
-	return
-}
diff --git a/src/cmd/fix/signal_test.go b/src/cmd/fix/signal_test.go
deleted file mode 100644
index 7bca7d5..0000000
--- a/src/cmd/fix/signal_test.go
+++ /dev/null
@@ -1,94 +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 main
-
-func init() {
-	addTestCases(signalTests, signal)
-}
-
-var signalTests = []testCase{
-	{
-		Name: "signal.0",
-		In: `package main
-
-import (
-	_ "a"
-	"os/signal"
-	_ "z"
-)
-
-type T1 signal.UnixSignal
-type T2 signal.Signal
-
-func f() {
-	_ = signal.SIGHUP
-	_ = signal.Incoming
-}
-`,
-		Out: `package main
-
-import (
-	_ "a"
-	"os"
-	"os/signal"
-	_ "z"
-)
-
-type T1 os.UnixSignal
-type T2 os.Signal
-
-func f() {
-	_ = os.SIGHUP
-	_ = signal.Incoming
-}
-`,
-	},
-	{
-		Name: "signal.1",
-		In: `package main
-
-import (
-	"os"
-	"os/signal"
-)
-
-func f() {
-	var _ os.Error
-	_ = signal.SIGHUP
-}
-`,
-		Out: `package main
-
-import "os"
-
-func f() {
-	var _ os.Error
-	_ = os.SIGHUP
-}
-`,
-	},
-	{
-		Name: "signal.2",
-		In: `package main
-
-import "os"
-import "os/signal"
-
-func f() {
-	var _ os.Error
-	_ = signal.SIGHUP
-}
-`,
-		Out: `package main
-
-import "os"
-
-func f() {
-	var _ os.Error
-	_ = os.SIGHUP
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/sorthelpers.go b/src/cmd/fix/sorthelpers.go
deleted file mode 100644
index fa54931..0000000
--- a/src/cmd/fix/sorthelpers.go
+++ /dev/null
@@ -1,49 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(sorthelpersFix)
-}
-
-var sorthelpersFix = fix{
-	"sorthelpers",
-	"2011-07-08",
-	sorthelpers,
-	`Adapt code from sort.Sort[Ints|Float64s|Strings] to sort.[Ints|Float64s|Strings].
-`,
-}
-
-func sorthelpers(f *ast.File) (fixed bool) {
-	if !imports(f, "sort") {
-		return
-	}
-
-	walk(f, func(n interface{}) {
-		s, ok := n.(*ast.SelectorExpr)
-		if !ok || !isTopName(s.X, "sort") {
-			return
-		}
-
-		switch s.Sel.String() {
-		case "SortFloat64s":
-			s.Sel.Name = "Float64s"
-		case "SortInts":
-			s.Sel.Name = "Ints"
-		case "SortStrings":
-			s.Sel.Name = "Strings"
-		default:
-			return
-		}
-
-		fixed = true
-	})
-
-	return
-}
diff --git a/src/cmd/fix/sorthelpers_test.go b/src/cmd/fix/sorthelpers_test.go
deleted file mode 100644
index dd6b58e..0000000
--- a/src/cmd/fix/sorthelpers_test.go
+++ /dev/null
@@ -1,45 +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 main
-
-func init() {
-	addTestCases(sorthelpersTests, sorthelpers)
-}
-
-var sorthelpersTests = []testCase{
-	{
-		Name: "sortslice.0",
-		In: `package main
-
-import (
-	"sort"
-)
-
-func main() {
-	var s []string
-	sort.SortStrings(s)
-	var i []ints
-	sort.SortInts(i)
-	var f []float64
-	sort.SortFloat64s(f)
-}
-`,
-		Out: `package main
-
-import (
-	"sort"
-)
-
-func main() {
-	var s []string
-	sort.Strings(s)
-	var i []ints
-	sort.Ints(i)
-	var f []float64
-	sort.Float64s(f)
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/sortslice.go b/src/cmd/fix/sortslice.go
deleted file mode 100644
index 89267b8..0000000
--- a/src/cmd/fix/sortslice.go
+++ /dev/null
@@ -1,52 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(sortsliceFix)
-}
-
-var sortsliceFix = fix{
-	"sortslice",
-	"2011-06-26",
-	sortslice,
-	`Adapt code from sort.[Float64|Int|String]Array to  sort.[Float64|Int|String]Slice.
-		
-http://codereview.appspot.com/4602054
-http://codereview.appspot.com/4639041
-`,
-}
-
-func sortslice(f *ast.File) (fixed bool) {
-	if !imports(f, "sort") {
-		return
-	}
-
-	walk(f, func(n interface{}) {
-		s, ok := n.(*ast.SelectorExpr)
-		if !ok || !isTopName(s.X, "sort") {
-			return
-		}
-
-		switch s.Sel.String() {
-		case "Float64Array":
-			s.Sel.Name = "Float64Slice"
-		case "IntArray":
-			s.Sel.Name = "IntSlice"
-		case "StringArray":
-			s.Sel.Name = "StringSlice"
-		default:
-			return
-		}
-
-		fixed = true
-	})
-
-	return
-}
diff --git a/src/cmd/fix/sortslice_test.go b/src/cmd/fix/sortslice_test.go
deleted file mode 100644
index 7b745a2..0000000
--- a/src/cmd/fix/sortslice_test.go
+++ /dev/null
@@ -1,35 +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 main
-
-func init() {
-	addTestCases(sortsliceTests, sortslice)
-}
-
-var sortsliceTests = []testCase{
-	{
-		Name: "sortslice.0",
-		In: `package main
-
-import (
-	"sort"
-)
-
-var _ = sort.Float64Array
-var _ = sort.IntArray
-var _ = sort.StringArray
-`,
-		Out: `package main
-
-import (
-	"sort"
-)
-
-var _ = sort.Float64Slice
-var _ = sort.IntSlice
-var _ = sort.StringSlice
-`,
-	},
-}
diff --git a/src/cmd/fix/strconv.go b/src/cmd/fix/strconv.go
deleted file mode 100644
index 6cd6902..0000000
--- a/src/cmd/fix/strconv.go
+++ /dev/null
@@ -1,127 +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 main
-
-import "go/ast"
-
-func init() {
-	register(strconvFix)
-}
-
-var strconvFix = fix{
-	"strconv",
-	"2011-12-01",
-	strconvFn,
-	`Convert to new strconv API.
-
-http://codereview.appspot.com/5434095
-http://codereview.appspot.com/5434069
-`,
-}
-
-func strconvFn(f *ast.File) bool {
-	if !imports(f, "strconv") {
-		return false
-	}
-
-	fixed := false
-
-	walk(f, func(n interface{}) {
-		// Rename functions.
-		call, ok := n.(*ast.CallExpr)
-		if !ok || len(call.Args) < 1 {
-			return
-		}
-		sel, ok := call.Fun.(*ast.SelectorExpr)
-		if !ok || !isTopName(sel.X, "strconv") {
-			return
-		}
-		change := func(name string) {
-			fixed = true
-			sel.Sel.Name = name
-		}
-		add := func(s string) {
-			call.Args = append(call.Args, expr(s))
-		}
-		switch sel.Sel.Name {
-		case "Atob":
-			change("ParseBool")
-		case "Atof32":
-			change("ParseFloat")
-			add("32") // bitSize
-			warn(call.Pos(), "rewrote strconv.Atof32(_) to strconv.ParseFloat(_, 32) but return value must be converted to float32")
-		case "Atof64":
-			change("ParseFloat")
-			add("64") // bitSize
-		case "AtofN":
-			change("ParseFloat")
-		case "Atoi":
-			// Atoi stayed as a convenience wrapper.
-		case "Atoi64":
-			change("ParseInt")
-			add("10") // base
-			add("64") // bitSize
-		case "Atoui":
-			change("ParseUint")
-			add("10") // base
-			add("0")  // bitSize
-			warn(call.Pos(), "rewrote strconv.Atoui(_) to strconv.ParseUint(_, 10, 0) but return value must be converted to uint")
-		case "Atoui64":
-			change("ParseUint")
-			add("10") // base
-			add("64") // bitSize
-		case "Btoa":
-			change("FormatBool")
-		case "Btoi64":
-			change("ParseInt")
-			add("64") // bitSize
-		case "Btoui64":
-			change("ParseUint")
-			add("64") // bitSize
-		case "Ftoa32":
-			change("FormatFloat")
-			call.Args[0] = strconvRewrite("float32", "float64", call.Args[0])
-			add("32") // bitSize
-		case "Ftoa64":
-			change("FormatFloat")
-			add("64") // bitSize
-		case "FtoaN":
-			change("FormatFloat")
-		case "Itoa":
-			// Itoa stayed as a convenience wrapper.
-		case "Itoa64":
-			change("FormatInt")
-			add("10") // base
-		case "Itob":
-			change("FormatInt")
-			call.Args[0] = strconvRewrite("int", "int64", call.Args[0])
-		case "Itob64":
-			change("FormatInt")
-		case "Uitoa":
-			change("FormatUint")
-			call.Args[0] = strconvRewrite("uint", "uint64", call.Args[0])
-			add("10") // base
-		case "Uitoa64":
-			change("FormatUint")
-			add("10") // base
-		case "Uitob":
-			change("FormatUint")
-			call.Args[0] = strconvRewrite("uint", "uint64", call.Args[0])
-		case "Uitob64":
-			change("FormatUint")
-		}
-	})
-	return fixed
-}
-
-// rewrite from type t1 to type t2
-// If the expression x is of the form t1(_), use t2(_).  Otherwise use t2(x).
-func strconvRewrite(t1, t2 string, x ast.Expr) ast.Expr {
-	if call, ok := x.(*ast.CallExpr); ok && isTopName(call.Fun, t1) {
-		call.Fun.(*ast.Ident).Name = t2
-		return x
-	}
-	return &ast.CallExpr{Fun: ast.NewIdent(t2), Args: []ast.Expr{x}}
-}
diff --git a/src/cmd/fix/strconv_test.go b/src/cmd/fix/strconv_test.go
deleted file mode 100644
index 7fbd4e4..0000000
--- a/src/cmd/fix/strconv_test.go
+++ /dev/null
@@ -1,93 +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 main
-
-func init() {
-	addTestCases(strconvTests, strconvFn)
-}
-
-var strconvTests = []testCase{
-	{
-		Name: "strconv.0",
-		In: `package main
-
-import "strconv"
-
-func f() {
-	foo.Atob("abc")
-
-	strconv.Atob("true")
-	strconv.Btoa(false)
-
-	strconv.Atof32("1.2")
-	strconv.Atof64("1.2")
-	strconv.AtofN("1.2", 64)
-	strconv.Ftoa32(1.2, 'g', 17)
-	strconv.Ftoa64(1.2, 'g', 17)
-	strconv.FtoaN(1.2, 'g', 17, 64)
-
-	strconv.Atoi("3")
-	strconv.Atoi64("3")
-	strconv.Btoi64("1234", 5)
-
-	strconv.Atoui("3")
-	strconv.Atoui64("3")
-	strconv.Btoui64("1234", 5)
-
-	strconv.Itoa(123)
-	strconv.Itoa64(1234)
-	strconv.Itob(123, 5)
-	strconv.Itob64(1234, 5)
-
-	strconv.Uitoa(123)
-	strconv.Uitoa64(1234)
-	strconv.Uitob(123, 5)
-	strconv.Uitob64(1234, 5)
-
-	strconv.Uitoa(uint(x))
-	strconv.Uitoa(f(x))
-}
-`,
-		Out: `package main
-
-import "strconv"
-
-func f() {
-	foo.Atob("abc")
-
-	strconv.ParseBool("true")
-	strconv.FormatBool(false)
-
-	strconv.ParseFloat("1.2", 32)
-	strconv.ParseFloat("1.2", 64)
-	strconv.ParseFloat("1.2", 64)
-	strconv.FormatFloat(float64(1.2), 'g', 17, 32)
-	strconv.FormatFloat(1.2, 'g', 17, 64)
-	strconv.FormatFloat(1.2, 'g', 17, 64)
-
-	strconv.Atoi("3")
-	strconv.ParseInt("3", 10, 64)
-	strconv.ParseInt("1234", 5, 64)
-
-	strconv.ParseUint("3", 10, 0)
-	strconv.ParseUint("3", 10, 64)
-	strconv.ParseUint("1234", 5, 64)
-
-	strconv.Itoa(123)
-	strconv.FormatInt(1234, 10)
-	strconv.FormatInt(int64(123), 5)
-	strconv.FormatInt(1234, 5)
-
-	strconv.FormatUint(uint64(123), 10)
-	strconv.FormatUint(1234, 10)
-	strconv.FormatUint(uint64(123), 5)
-	strconv.FormatUint(1234, 5)
-
-	strconv.FormatUint(uint64(x), 10)
-	strconv.FormatUint(uint64(f(x)), 10)
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/stringssplit.go b/src/cmd/fix/stringssplit.go
deleted file mode 100644
index d89ecf0..0000000
--- a/src/cmd/fix/stringssplit.go
+++ /dev/null
@@ -1,72 +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 main
-
-import (
-	"go/ast"
-	"go/token"
-)
-
-func init() {
-	register(stringssplitFix)
-}
-
-var stringssplitFix = fix{
-	"stringssplit",
-	"2011-06-28",
-	stringssplit,
-	`Restore strings.Split to its original meaning and add strings.SplitN. Bytes too.
-
-http://codereview.appspot.com/4661051
-`,
-}
-
-func stringssplit(f *ast.File) bool {
-	if !imports(f, "bytes") && !imports(f, "strings") {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		call, ok := n.(*ast.CallExpr)
-		// func Split(s, sep string, n int) []string
-		// func SplitAfter(s, sep string, n int) []string
-		if !ok || len(call.Args) != 3 {
-			return
-		}
-		// Is this our function?
-		switch {
-		case isPkgDot(call.Fun, "bytes", "Split"):
-		case isPkgDot(call.Fun, "bytes", "SplitAfter"):
-		case isPkgDot(call.Fun, "strings", "Split"):
-		case isPkgDot(call.Fun, "strings", "SplitAfter"):
-		default:
-			return
-		}
-
-		sel := call.Fun.(*ast.SelectorExpr)
-		args := call.Args
-		fixed = true // We're committed.
-
-		// Is the last argument -1? If so, drop the arg.
-		// (Actually we just look for a negative integer literal.)
-		// Otherwise, Split->SplitN and keep the arg.
-		final := args[2]
-		if unary, ok := final.(*ast.UnaryExpr); ok && unary.Op == token.SUB {
-			if lit, ok := unary.X.(*ast.BasicLit); ok {
-				// Is it an integer? If so, it's a negative integer and that's what we're after.
-				if lit.Kind == token.INT {
-					// drop the last arg.
-					call.Args = args[0:2]
-					return
-				}
-			}
-		}
-
-		// If not, rename and keep the argument list.
-		sel.Sel.Name += "N"
-	})
-	return fixed
-}
diff --git a/src/cmd/fix/stringssplit_test.go b/src/cmd/fix/stringssplit_test.go
deleted file mode 100644
index fa42b1b..0000000
--- a/src/cmd/fix/stringssplit_test.go
+++ /dev/null
@@ -1,51 +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 main
-
-func init() {
-	addTestCases(stringssplitTests, stringssplit)
-}
-
-var stringssplitTests = []testCase{
-	{
-		Name: "stringssplit.0",
-		In: `package main
-
-import (
-	"bytes"
-	"strings"
-)
-
-func f() {
-	bytes.Split(a, b, c)
-	bytes.Split(a, b, -1)
-	bytes.SplitAfter(a, b, c)
-	bytes.SplitAfter(a, b, -1)
-	strings.Split(a, b, c)
-	strings.Split(a, b, -1)
-	strings.SplitAfter(a, b, c)
-	strings.SplitAfter(a, b, -1)
-}
-`,
-		Out: `package main
-
-import (
-	"bytes"
-	"strings"
-)
-
-func f() {
-	bytes.SplitN(a, b, c)
-	bytes.Split(a, b)
-	bytes.SplitAfterN(a, b, c)
-	bytes.SplitAfter(a, b)
-	strings.SplitN(a, b, c)
-	strings.Split(a, b)
-	strings.SplitAfterN(a, b, c)
-	strings.SplitAfter(a, b)
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/template.go b/src/cmd/fix/template.go
deleted file mode 100644
index a3dd144..0000000
--- a/src/cmd/fix/template.go
+++ /dev/null
@@ -1,111 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(templateFix)
-}
-
-var templateFix = fix{
-	"template",
-	"2011-11-22",
-	template,
-	`Rewrite calls to template.ParseFile to template.ParseFiles
-
-http://codereview.appspot.com/5433048
-`,
-}
-
-var templateSetGlobals = []string{
-	"ParseSetFiles",
-	"ParseSetGlob",
-	"ParseTemplateFiles",
-	"ParseTemplateGlob",
-	"Set",
-	"SetMust",
-}
-
-var templateSetMethods = []string{
-	"ParseSetFiles",
-	"ParseSetGlob",
-	"ParseTemplateFiles",
-	"ParseTemplateGlob",
-}
-
-var templateTypeConfig = &TypeConfig{
-	Type: map[string]*Type{
-		"template.Template": {
-			Method: map[string]string{
-				"Funcs":      "func() *template.Template",
-				"Delims":     "func() *template.Template",
-				"Parse":      "func() (*template.Template, error)",
-				"ParseFile":  "func() (*template.Template, error)",
-				"ParseInSet": "func() (*template.Template, error)",
-			},
-		},
-		"template.Set": {
-			Method: map[string]string{
-				"ParseSetFiles":      "func() (*template.Set, error)",
-				"ParseSetGlob":       "func() (*template.Set, error)",
-				"ParseTemplateFiles": "func() (*template.Set, error)",
-				"ParseTemplateGlob":  "func() (*template.Set, error)",
-			},
-		},
-	},
-
-	Func: map[string]string{
-		"template.New":     "*template.Template",
-		"template.Must":    "(*template.Template, error)",
-		"template.SetMust": "(*template.Set, error)",
-	},
-}
-
-func template(f *ast.File) bool {
-	if !imports(f, "text/template") && !imports(f, "html/template") {
-		return false
-	}
-
-	fixed := false
-
-	typeof, _ := typecheck(templateTypeConfig, f)
-
-	// Now update the names used by importers.
-	walk(f, func(n interface{}) {
-		if sel, ok := n.(*ast.SelectorExpr); ok {
-			// Reference to top-level function ParseFile.
-			if isPkgDot(sel, "template", "ParseFile") {
-				sel.Sel.Name = "ParseFiles"
-				fixed = true
-				return
-			}
-			// Reference to ParseFiles method.
-			if typeof[sel.X] == "*template.Template" && sel.Sel.Name == "ParseFile" {
-				sel.Sel.Name = "ParseFiles"
-				fixed = true
-				return
-			}
-			// The Set type and its functions are now gone.
-			for _, name := range templateSetGlobals {
-				if isPkgDot(sel, "template", name) {
-					warn(sel.Pos(), "reference to template.%s must be fixed manually", name)
-					return
-				}
-			}
-			// The methods of Set are now gone.
-			for _, name := range templateSetMethods {
-				if typeof[sel.X] == "*template.Set" && sel.Sel.Name == name {
-					warn(sel.Pos(), "reference to template.*Set.%s must be fixed manually", name)
-					return
-				}
-			}
-		}
-	})
-
-	return fixed
-}
diff --git a/src/cmd/fix/template_test.go b/src/cmd/fix/template_test.go
deleted file mode 100644
index f713a29..0000000
--- a/src/cmd/fix/template_test.go
+++ /dev/null
@@ -1,55 +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 main
-
-func init() {
-	addTestCases(templateTests, template)
-}
-
-var templateTests = []testCase{
-	{
-		Name: "template.0",
-		In: `package main
-
-import (
-	"text/template"
-)
-
-func f() {
-	template.ParseFile(a)
-	var t template.Template
-	x, y := template.ParseFile()
-	template.New("x").Funcs(m).ParseFile(a) // chained method
-	// Output should complain about these as functions or methods.
-	var s *template.Set
-	s.ParseSetFiles(a)
-	template.ParseSetGlob(a)
-	s.ParseTemplateFiles(a)
-	template.ParseTemplateGlob(a)
-	x := template.SetMust(a())
-}
-`,
-		Out: `package main
-
-import (
-	"text/template"
-)
-
-func f() {
-	template.ParseFiles(a)
-	var t template.Template
-	x, y := template.ParseFiles()
-	template.New("x").Funcs(m).ParseFiles(a) // chained method
-	// Output should complain about these as functions or methods.
-	var s *template.Set
-	s.ParseSetFiles(a)
-	template.ParseSetGlob(a)
-	s.ParseTemplateFiles(a)
-	template.ParseTemplateGlob(a)
-	x := template.SetMust(a())
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/testdata/reflect.encoder.go.in b/src/cmd/fix/testdata/reflect.encoder.go.in
index 0202d79..702f6dc 100644
--- a/src/cmd/fix/testdata/reflect.encoder.go.in
+++ b/src/cmd/fix/testdata/reflect.encoder.go.in
@@ -120,7 +120,7 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
 	return true
 }
 
-// sendType sends the type info to the other side, if necessary. 
+// sendType sends the type info to the other side, if necessary.
 func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) {
 	ut := userType(origt)
 	if ut.isGobEncoder {
diff --git a/src/cmd/fix/testdata/reflect.encoder.go.out b/src/cmd/fix/testdata/reflect.encoder.go.out
index 925d393..f1a7b98 100644
--- a/src/cmd/fix/testdata/reflect.encoder.go.out
+++ b/src/cmd/fix/testdata/reflect.encoder.go.out
@@ -120,7 +120,7 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
 	return true
 }
 
-// sendType sends the type info to the other side, if necessary. 
+// sendType sends the type info to the other side, if necessary.
 func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) {
 	ut := userType(origt)
 	if ut.isGobEncoder {
diff --git a/src/cmd/fix/testdata/reflect.export.go.in b/src/cmd/fix/testdata/reflect.export.go.in
index ce7940b..722387a 100644
--- a/src/cmd/fix/testdata/reflect.export.go.in
+++ b/src/cmd/fix/testdata/reflect.export.go.in
@@ -162,7 +162,7 @@ func (client *expClient) run() {
 				// all messages <=N have been seen by the recipient.  We check anyway.
 				expLog("sequence out of order:", client.ackNum, hdr.SeqNum)
 			}
-			if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count. 
+			if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count.
 				client.ackNum = hdr.SeqNum
 			}
 			client.mu.Unlock()
diff --git a/src/cmd/fix/testdata/reflect.export.go.out b/src/cmd/fix/testdata/reflect.export.go.out
index 7bd73c5..d1324f3 100644
--- a/src/cmd/fix/testdata/reflect.export.go.out
+++ b/src/cmd/fix/testdata/reflect.export.go.out
@@ -162,7 +162,7 @@ func (client *expClient) run() {
 				// all messages <=N have been seen by the recipient.  We check anyway.
 				expLog("sequence out of order:", client.ackNum, hdr.SeqNum)
 			}
-			if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count. 
+			if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count.
 				client.ackNum = hdr.SeqNum
 			}
 			client.mu.Unlock()
diff --git a/src/cmd/fix/testdata/reflect.print.go.in b/src/cmd/fix/testdata/reflect.print.go.in
index 6c9b8e4..14cf2b2 100644
--- a/src/cmd/fix/testdata/reflect.print.go.in
+++ b/src/cmd/fix/testdata/reflect.print.go.in
@@ -182,7 +182,7 @@ func Sprintf(format string, a ...interface{}) string {
 	return s
 }
 
-// Errorf formats according to a format specifier and returns the string 
+// Errorf formats according to a format specifier and returns the string
 // converted to an os.ErrorString, which satisfies the os.Error interface.
 func Errorf(format string, a ...interface{}) os.Error {
 	return os.NewError(Sprintf(format, a...))
diff --git a/src/cmd/fix/testdata/reflect.print.go.out b/src/cmd/fix/testdata/reflect.print.go.out
index b475a2a..e4e4c73 100644
--- a/src/cmd/fix/testdata/reflect.print.go.out
+++ b/src/cmd/fix/testdata/reflect.print.go.out
@@ -182,7 +182,7 @@ func Sprintf(format string, a ...interface{}) string {
 	return s
 }
 
-// Errorf formats according to a format specifier and returns the string 
+// Errorf formats according to a format specifier and returns the string
 // converted to an os.ErrorString, which satisfies the os.Error interface.
 func Errorf(format string, a ...interface{}) os.Error {
 	return os.NewError(Sprintf(format, a...))
diff --git a/src/cmd/fix/timefileinfo.go b/src/cmd/fix/timefileinfo.go
deleted file mode 100644
index b2ea23d..0000000
--- a/src/cmd/fix/timefileinfo.go
+++ /dev/null
@@ -1,298 +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 main
-
-import (
-	"go/ast"
-	"go/token"
-	"strings"
-)
-
-func init() {
-	register(timefileinfoFix)
-}
-
-var timefileinfoFix = fix{
-	"time+fileinfo",
-	"2011-11-29",
-	timefileinfo,
-	`Rewrite for new time and os.FileInfo APIs.
-
-This fix applies some of the more mechanical changes,
-but most code will still need manual cleanup.
-
-http://codereview.appspot.com/5392041
-http://codereview.appspot.com/5416060
-`,
-}
-
-var timefileinfoTypeConfig = &TypeConfig{
-	Type: map[string]*Type{
-		"os.File": {
-			Method: map[string]string{
-				"Readdir": "func() []*os.FileInfo",
-				"Stat":    "func() (*os.FileInfo, error)",
-			},
-		},
-		"time.Time": {
-			Method: map[string]string{
-				"Seconds":     "time.raw",
-				"Nanoseconds": "time.raw",
-			},
-		},
-	},
-	Func: map[string]string{
-		"ioutil.ReadDir":              "([]*os.FileInfo, error)",
-		"os.Stat":                     "(*os.FileInfo, error)",
-		"os.Lstat":                    "(*os.FileInfo, error)",
-		"time.LocalTime":              "*time.Time",
-		"time.UTC":                    "*time.Time",
-		"time.SecondsToLocalTime":     "*time.Time",
-		"time.SecondsToUTC":           "*time.Time",
-		"time.NanosecondsToLocalTime": "*time.Time",
-		"time.NanosecondsToUTC":       "*time.Time",
-		"time.Parse":                  "(*time.Time, error)",
-		"time.Nanoseconds":            "time.raw",
-		"time.Seconds":                "time.raw",
-	},
-}
-
-// timefileinfoIsOld reports whether f has evidence of being
-// "old code", from before the API changes.  Evidence means:
-//
-//	a mention of *os.FileInfo (the pointer)
-//	a mention of *time.Time (the pointer)
-//	a mention of old functions from package time
-//	an attempt to call time.UTC
-//
-func timefileinfoIsOld(f *ast.File, typeof map[interface{}]string) bool {
-	old := false
-
-	// called records the expressions that appear as
-	// the function part of a function call, so that
-	// we can distinguish a ref to the possibly new time.UTC
-	// from the definitely old time.UTC() function call.
-	called := make(map[interface{}]bool)
-
-	before := func(n interface{}) {
-		if old {
-			return
-		}
-		if star, ok := n.(*ast.StarExpr); ok {
-			if isPkgDot(star.X, "os", "FileInfo") || isPkgDot(star.X, "time", "Time") {
-				old = true
-				return
-			}
-		}
-		if sel, ok := n.(*ast.SelectorExpr); ok {
-			if isTopName(sel.X, "time") {
-				if timefileinfoOldTimeFunc[sel.Sel.Name] {
-					old = true
-					return
-				}
-			}
-			if typeof[sel.X] == "os.FileInfo" || typeof[sel.X] == "*os.FileInfo" {
-				switch sel.Sel.Name {
-				case "Mtime_ns", "IsDirectory", "IsRegular":
-					old = true
-					return
-				case "Name", "Mode", "Size":
-					if !called[sel] {
-						old = true
-						return
-					}
-				}
-			}
-		}
-		call, ok := n.(*ast.CallExpr)
-		if ok && isPkgDot(call.Fun, "time", "UTC") {
-			old = true
-			return
-		}
-		if ok {
-			called[call.Fun] = true
-		}
-	}
-	walkBeforeAfter(f, before, nop)
-	return old
-}
-
-var timefileinfoOldTimeFunc = map[string]bool{
-	"LocalTime":              true,
-	"SecondsToLocalTime":     true,
-	"SecondsToUTC":           true,
-	"NanosecondsToLocalTime": true,
-	"NanosecondsToUTC":       true,
-	"Seconds":                true,
-	"Nanoseconds":            true,
-}
-
-var isTimeNow = map[string]bool{
-	"LocalTime":   true,
-	"UTC":         true,
-	"Seconds":     true,
-	"Nanoseconds": true,
-}
-
-func timefileinfo(f *ast.File) bool {
-	if !imports(f, "os") && !imports(f, "time") && !imports(f, "io/ioutil") {
-		return false
-	}
-
-	typeof, _ := typecheck(timefileinfoTypeConfig, f)
-
-	if !timefileinfoIsOld(f, typeof) {
-		return false
-	}
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		p, ok := n.(*ast.Expr)
-		if !ok {
-			return
-		}
-		nn := *p
-
-		// Rewrite *os.FileInfo and *time.Time to drop the pointer.
-		if star, ok := nn.(*ast.StarExpr); ok {
-			if isPkgDot(star.X, "os", "FileInfo") || isPkgDot(star.X, "time", "Time") {
-				fixed = true
-				*p = star.X
-				return
-			}
-		}
-
-		// Rewrite old time API calls to new calls.
-		// The code will still not compile after this edit,
-		// but the compiler will catch that, and the replacement
-		// code will be the correct functions to use in the new API.
-		if sel, ok := nn.(*ast.SelectorExpr); ok && isTopName(sel.X, "time") {
-			fn := sel.Sel.Name
-			if fn == "LocalTime" || fn == "Seconds" || fn == "Nanoseconds" {
-				fixed = true
-				sel.Sel.Name = "Now"
-				return
-			}
-		}
-
-		if call, ok := nn.(*ast.CallExpr); ok {
-			if sel, ok := call.Fun.(*ast.SelectorExpr); ok {
-				// Rewrite time.UTC but only when called (there's a new time.UTC var now).
-				if isPkgDot(sel, "time", "UTC") {
-					fixed = true
-					sel.Sel.Name = "Now"
-					// rewrite time.Now() into time.Now().UTC()
-					*p = &ast.CallExpr{
-						Fun: &ast.SelectorExpr{
-							X:   call,
-							Sel: ast.NewIdent("UTC"),
-						},
-					}
-					return
-				}
-
-				// Rewrite conversions.
-				if ok && isTopName(sel.X, "time") && len(call.Args) == 1 {
-					fn := sel.Sel.Name
-					switch fn {
-					case "SecondsToLocalTime", "SecondsToUTC",
-						"NanosecondsToLocalTime", "NanosecondsToUTC":
-						fixed = true
-						sel.Sel.Name = "Unix"
-						call.Args = append(call.Args, nil)
-						if strings.HasPrefix(fn, "Seconds") {
-							// Unix(sec, 0)
-							call.Args[1] = ast.NewIdent("0")
-						} else {
-							// Unix(0, nsec)
-							call.Args[1] = call.Args[0]
-							call.Args[0] = ast.NewIdent("0")
-						}
-						if strings.HasSuffix(fn, "ToUTC") {
-							// rewrite call into call.UTC()
-							*p = &ast.CallExpr{
-								Fun: &ast.SelectorExpr{
-									X:   call,
-									Sel: ast.NewIdent("UTC"),
-								},
-							}
-						}
-						return
-					}
-				}
-
-				// Rewrite method calls.
-				switch typeof[sel.X] {
-				case "*time.Time", "time.Time":
-					switch sel.Sel.Name {
-					case "Seconds":
-						fixed = true
-						sel.Sel.Name = "Unix"
-						return
-					case "Nanoseconds":
-						fixed = true
-						sel.Sel.Name = "UnixNano"
-						return
-					}
-
-				case "*os.FileInfo", "os.FileInfo":
-					switch sel.Sel.Name {
-					case "IsDirectory":
-						fixed = true
-						sel.Sel.Name = "IsDir"
-						return
-					case "IsRegular":
-						fixed = true
-						sel.Sel.Name = "IsDir"
-						*p = &ast.UnaryExpr{
-							Op: token.NOT,
-							X:  call,
-						}
-						return
-					}
-				}
-			}
-		}
-
-		// Rewrite subtraction of two times.
-		// Cannot handle +=/-=.
-		if bin, ok := nn.(*ast.BinaryExpr); ok &&
-			bin.Op == token.SUB &&
-			(typeof[bin.X] == "time.raw" || typeof[bin.Y] == "time.raw") {
-			fixed = true
-			*p = &ast.CallExpr{
-				Fun: &ast.SelectorExpr{
-					X:   bin.X,
-					Sel: ast.NewIdent("Sub"),
-				},
-				Args: []ast.Expr{bin.Y},
-			}
-		}
-
-		// Rewrite field references for os.FileInfo.
-		if sel, ok := nn.(*ast.SelectorExpr); ok {
-			if typ := typeof[sel.X]; typ == "*os.FileInfo" || typ == "os.FileInfo" {
-				addCall := false
-				switch sel.Sel.Name {
-				case "Name", "Size", "Mode":
-					fixed = true
-					addCall = true
-				case "Mtime_ns":
-					fixed = true
-					sel.Sel.Name = "ModTime"
-					addCall = true
-				}
-				if addCall {
-					*p = &ast.CallExpr{
-						Fun: sel,
-					}
-					return
-				}
-			}
-		}
-	})
-
-	return true
-}
diff --git a/src/cmd/fix/timefileinfo_test.go b/src/cmd/fix/timefileinfo_test.go
deleted file mode 100644
index 6573b85..0000000
--- a/src/cmd/fix/timefileinfo_test.go
+++ /dev/null
@@ -1,187 +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 main
-
-func init() {
-	addTestCases(timefileinfoTests, timefileinfo)
-}
-
-var timefileinfoTests = []testCase{
-	{
-		Name: "timefileinfo.0",
-		In: `package main
-
-import "os"
-
-func main() {
-	st, _ := os.Stat("/etc/passwd")
-	_ = st.Name
-}
-`,
-		Out: `package main
-
-import "os"
-
-func main() {
-	st, _ := os.Stat("/etc/passwd")
-	_ = st.Name()
-}
-`,
-	},
-	{
-		Name: "timefileinfo.1",
-		In: `package main
-
-import "os"
-
-func main() {
-	st, _ := os.Stat("/etc/passwd")
-	_ = st.Size
-	_ = st.Mode
-	_ = st.Mtime_ns
-	_ = st.IsDirectory()
-	_ = st.IsRegular()
-}
-`,
-		Out: `package main
-
-import "os"
-
-func main() {
-	st, _ := os.Stat("/etc/passwd")
-	_ = st.Size()
-	_ = st.Mode()
-	_ = st.ModTime()
-	_ = st.IsDir()
-	_ = !st.IsDir()
-}
-`,
-	},
-	{
-		Name: "timefileinfo.2",
-		In: `package main
-
-import "os"
-
-func f(st *os.FileInfo) {
-	_ = st.Name
-	_ = st.Size
-	_ = st.Mode
-	_ = st.Mtime_ns
-	_ = st.IsDirectory()
-	_ = st.IsRegular()
-}
-`,
-		Out: `package main
-
-import "os"
-
-func f(st os.FileInfo) {
-	_ = st.Name()
-	_ = st.Size()
-	_ = st.Mode()
-	_ = st.ModTime()
-	_ = st.IsDir()
-	_ = !st.IsDir()
-}
-`,
-	},
-	{
-		Name: "timefileinfo.3",
-		In: `package main
-
-import "time"
-
-func main() {
-	_ = time.Seconds()
-	_ = time.Nanoseconds()
-	_ = time.LocalTime()
-	_ = time.UTC()
-	_ = time.SecondsToLocalTime(sec)
-	_ = time.SecondsToUTC(sec)
-	_ = time.NanosecondsToLocalTime(nsec)
-	_ = time.NanosecondsToUTC(nsec)
-}
-`,
-		Out: `package main
-
-import "time"
-
-func main() {
-	_ = time.Now()
-	_ = time.Now()
-	_ = time.Now()
-	_ = time.Now().UTC()
-	_ = time.Unix(sec, 0)
-	_ = time.Unix(sec, 0).UTC()
-	_ = time.Unix(0, nsec)
-	_ = time.Unix(0, nsec).UTC()
-}
-`,
-	},
-	{
-		Name: "timefileinfo.4",
-		In: `package main
-
-import "time"
-
-func f(*time.Time)
-
-func main() {
-	t := time.LocalTime()
-	_ = t.Seconds()
-	_ = t.Nanoseconds()
-
-	t1 := time.Nanoseconds()
-	f(nil)
-	t2 := time.Nanoseconds()
-	dt := t2 - t1
-}
-`,
-		Out: `package main
-
-import "time"
-
-func f(time.Time)
-
-func main() {
-	t := time.Now()
-	_ = t.Unix()
-	_ = t.UnixNano()
-
-	t1 := time.Now()
-	f(nil)
-	t2 := time.Now()
-	dt := t2.Sub(t1)
-}
-`,
-	},
-	{
-		Name: "timefileinfo.5", // test for issues 1505, 2636
-		In: `package main
-
-import (
-	"fmt"
-	"time"
-)
-
-func main() {
-	fmt.Println(time.SecondsToUTC(now)) // this comment must not introduce an illegal linebreak
-}
-`,
-		Out: `package main
-
-import (
-	"fmt"
-	"time"
-)
-
-func main() {
-	fmt.Println(time.Unix(now, 0).UTC( // this comment must not introduce an illegal linebreak
-	))
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/typecheck.go b/src/cmd/fix/typecheck.go
index 8e54314..d33b69f 100644
--- a/src/cmd/fix/typecheck.go
+++ b/src/cmd/fix/typecheck.go
@@ -17,7 +17,7 @@ import (
 //
 // The fact that it is partial is very important: the input is
 // an AST and a description of some type information to
-// assume about one or more packages, but not all the 
+// assume about one or more packages, but not all the
 // packages that the program imports.  The checker is
 // expected to do as much as it can with what it has been
 // given.  There is not enough information supplied to do
@@ -395,9 +395,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a
 			// Field or method.
 			name := n.Sel.Name
 			if t := typeof[n.X]; t != "" {
-				if strings.HasPrefix(t, "*") {
-					t = t[1:] // implicit *
-				}
+				t = strings.TrimPrefix(t, "*") // implicit *
 				if typ := cfg.Type[t]; typ != nil {
 					if t := typ.dot(cfg, name); t != "" {
 						typeof[n] = t
diff --git a/src/cmd/fix/url.go b/src/cmd/fix/url.go
deleted file mode 100644
index 49aac73..0000000
--- a/src/cmd/fix/url.go
+++ /dev/null
@@ -1,101 +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 main
-
-import "go/ast"
-
-func init() {
-	register(urlFix)
-}
-
-var urlFix = fix{
-	"url",
-	"2011-08-17",
-	url,
-	`Move the URL pieces of package http into a new package, url.
-
-http://codereview.appspot.com/4893043
-`,
-}
-
-var urlRenames = []struct{ in, out string }{
-	{"URL", "URL"},
-	{"ParseURL", "Parse"},
-	{"ParseURLReference", "ParseWithReference"},
-	{"ParseQuery", "ParseQuery"},
-	{"Values", "Values"},
-	{"URLEscape", "QueryEscape"},
-	{"URLUnescape", "QueryUnescape"},
-	{"URLError", "Error"},
-	{"URLEscapeError", "EscapeError"},
-}
-
-func url(f *ast.File) bool {
-	if imports(f, "url") || !imports(f, "http") {
-		return false
-	}
-
-	fixed := false
-
-	// Update URL code.
-	urlWalk := func(n interface{}) {
-		// Is it an identifier?
-		if ident, ok := n.(*ast.Ident); ok && ident.Name == "url" {
-			ident.Name = "url_"
-			return
-		}
-		// Parameter and result names.
-		if fn, ok := n.(*ast.FuncType); ok {
-			fixed = urlDoFields(fn.Params) || fixed
-			fixed = urlDoFields(fn.Results) || fixed
-		}
-	}
-
-	// Fix up URL code and add import, at most once.
-	fix := func() {
-		if fixed {
-			return
-		}
-		addImport(f, "url")
-		walkBeforeAfter(f, urlWalk, nop)
-		fixed = true
-	}
-
-	walk(f, func(n interface{}) {
-		// Rename functions and methods.
-		if expr, ok := n.(ast.Expr); ok {
-			for _, s := range urlRenames {
-				if isPkgDot(expr, "http", s.in) {
-					fix()
-					expr.(*ast.SelectorExpr).X.(*ast.Ident).Name = "url"
-					expr.(*ast.SelectorExpr).Sel.Name = s.out
-					return
-				}
-			}
-		}
-	})
-
-	// Remove the http import if no longer needed.
-	if fixed && !usesImport(f, "http") {
-		deleteImport(f, "http")
-	}
-
-	return fixed
-}
-
-func urlDoFields(list *ast.FieldList) (fixed bool) {
-	if list == nil {
-		return
-	}
-	for _, field := range list.List {
-		for _, ident := range field.Names {
-			if ident.Name == "url" {
-				fixed = true
-				ident.Name = "url_"
-			}
-		}
-	}
-	return
-}
diff --git a/src/cmd/fix/url2.go b/src/cmd/fix/url2.go
deleted file mode 100644
index 5fd05ad..0000000
--- a/src/cmd/fix/url2.go
+++ /dev/null
@@ -1,46 +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 main
-
-import "go/ast"
-
-func init() {
-	register(url2Fix)
-}
-
-var url2Fix = fix{
-	"url2",
-	"2012-02-16",
-	url2,
-	`Rename some functions in net/url.
-
-http://codereview.appspot.com/5671061
-`,
-}
-
-func url2(f *ast.File) bool {
-	if !imports(f, "net/url") {
-		return false
-	}
-
-	fixed := false
-
-	walk(f, func(n interface{}) {
-		// Rename functions and methods.
-		sel, ok := n.(*ast.SelectorExpr)
-		if !ok {
-			return
-		}
-		if !isTopName(sel.X, "url") {
-			return
-		}
-		if sel.Sel.Name == "ParseWithReference" {
-			sel.Sel.Name = "ParseWithFragment"
-			fixed = true
-		}
-	})
-
-	return fixed
-}
diff --git a/src/cmd/fix/url2_test.go b/src/cmd/fix/url2_test.go
deleted file mode 100644
index c68dd88..0000000
--- a/src/cmd/fix/url2_test.go
+++ /dev/null
@@ -1,31 +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 main
-
-func init() {
-	addTestCases(url2Tests, url2)
-}
-
-var url2Tests = []testCase{
-	{
-		Name: "url2.0",
-		In: `package main
-
-import "net/url"
-
-func f() {
-	url.ParseWithReference("foo")
-}
-`,
-		Out: `package main
-
-import "net/url"
-
-func f() {
-	url.ParseWithFragment("foo")
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/url_test.go b/src/cmd/fix/url_test.go
deleted file mode 100644
index 39827f7..0000000
--- a/src/cmd/fix/url_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.
-
-package main
-
-func init() {
-	addTestCases(urlTests, url)
-}
-
-var urlTests = []testCase{
-	{
-		Name: "url.0",
-		In: `package main
-
-import (
-	"http"
-)
-
-func f() {
-	var _ http.URL
-	http.ParseURL(a)
-	http.ParseURLReference(a)
-	http.ParseQuery(a)
-	m := http.Values{a: b}
-	http.URLEscape(a)
-	http.URLUnescape(a)
-	var x http.URLError
-	var y http.URLEscapeError
-}
-`,
-		Out: `package main
-
-import "url"
-
-func f() {
-	var _ url.URL
-	url.Parse(a)
-	url.ParseWithReference(a)
-	url.ParseQuery(a)
-	m := url.Values{a: b}
-	url.QueryEscape(a)
-	url.QueryUnescape(a)
-	var x url.Error
-	var y url.EscapeError
-}
-`,
-	},
-	{
-		Name: "url.1",
-		In: `package main
-
-import (
-	"http"
-)
-
-func f() {
-	http.ParseURL(a)
-	var x http.Request
-}
-`,
-		Out: `package main
-
-import (
-	"http"
-	"url"
-)
-
-func f() {
-	url.Parse(a)
-	var x http.Request
-}
-`,
-	},
-	{
-		Name: "url.2",
-		In: `package main
-
-import (
-	"http"
-)
-
-type U struct{ url int }
-type M map[int]int
-
-func f() {
-	http.ParseURL(a)
-	var url = 23
-	url, x := 45, y
-	_ = U{url: url}
-	_ = M{url + 1: url}
-}
-
-func g(url string) string {
-	return url
-}
-
-func h() (url string) {
-	return url
-}
-`,
-		Out: `package main
-
-import "url"
-
-type U struct{ url_ int }
-type M map[int]int
-
-func f() {
-	url.Parse(a)
-	var url_ = 23
-	url_, x := 45, y
-	_ = U{url_: url_}
-	_ = M{url_ + 1: url_}
-}
-
-func g(url_ string) string {
-	return url_
-}
-
-func h() (url_ string) {
-	return url_
-}
-`,
-	},
-	{
-		Name: "url.3",
-		In: `package main
-
-import "http"
-
-type U struct{ url string }
-
-func f() {
-	var u U
-	u.url = "x"
-}
-
-func (url *T) m() string {
-	return url
-}
-`,
-		Out: `package main
-
-import "http"
-
-type U struct{ url string }
-
-func f() {
-	var u U
-	u.url = "x"
-}
-
-func (url *T) m() string {
-	return url
-}
-`,
-	},
-}
diff --git a/src/cmd/fix/xmlapi.go b/src/cmd/fix/xmlapi.go
deleted file mode 100644
index e744259..0000000
--- a/src/cmd/fix/xmlapi.go
+++ /dev/null
@@ -1,111 +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 main
-
-import (
-	"go/ast"
-)
-
-func init() {
-	register(xmlapiFix)
-}
-
-var xmlapiFix = fix{
-	"xmlapi",
-	"2012-01-23",
-	xmlapi,
-	`
-	Make encoding/xml's API look more like the rest of the encoding packages.
-
-http://codereview.appspot.com/5574053
-`,
-}
-
-var xmlapiTypeConfig = &TypeConfig{
-	Func: map[string]string{
-		"xml.NewParser":         "*xml.Parser",
-		"os.Open":               "*os.File",
-		"os.OpenFile":           "*os.File",
-		"bytes.NewBuffer":       "*bytes.Buffer",
-		"bytes.NewBufferString": "*bytes.Buffer",
-		"bufio.NewReader":       "*bufio.Reader",
-		"bufio.NewReadWriter":   "*bufio.ReadWriter",
-	},
-}
-
-var isReader = map[string]bool{
-	"*os.File":          true,
-	"*bytes.Buffer":     true,
-	"*bufio.Reader":     true,
-	"*bufio.ReadWriter": true,
-	"io.Reader":         true,
-}
-
-func xmlapi(f *ast.File) bool {
-	if !imports(f, "encoding/xml") {
-		return false
-	}
-
-	typeof, _ := typecheck(xmlapiTypeConfig, f)
-
-	fixed := false
-	walk(f, func(n interface{}) {
-		s, ok := n.(*ast.SelectorExpr)
-		if ok && typeof[s.X] == "*xml.Parser" && s.Sel.Name == "Unmarshal" {
-			s.Sel.Name = "DecodeElement"
-			fixed = true
-			return
-		}
-		if ok && isPkgDot(s, "xml", "Parser") {
-			s.Sel.Name = "Decoder"
-			fixed = true
-			return
-		}
-
-		call, ok := n.(*ast.CallExpr)
-		if !ok {
-			return
-		}
-		switch {
-		case len(call.Args) == 2 && isPkgDot(call.Fun, "xml", "Marshal"):
-			*call = xmlMarshal(call.Args)
-			fixed = true
-		case len(call.Args) == 2 && isPkgDot(call.Fun, "xml", "Unmarshal"):
-			if isReader[typeof[call.Args[0]]] {
-				*call = xmlUnmarshal(call.Args)
-				fixed = true
-			}
-		case len(call.Args) == 1 && isPkgDot(call.Fun, "xml", "NewParser"):
-			sel := call.Fun.(*ast.SelectorExpr).Sel
-			sel.Name = "NewDecoder"
-			fixed = true
-		}
-	})
-	return fixed
-}
-
-func xmlMarshal(args []ast.Expr) ast.CallExpr {
-	return xmlCallChain("NewEncoder", "Encode", args)
-}
-
-func xmlUnmarshal(args []ast.Expr) ast.CallExpr {
-	return xmlCallChain("NewDecoder", "Decode", args)
-}
-
-func xmlCallChain(first, second string, args []ast.Expr) ast.CallExpr {
-	return ast.CallExpr{
-		Fun: &ast.SelectorExpr{
-			X: &ast.CallExpr{
-				Fun: &ast.SelectorExpr{
-					X:   ast.NewIdent("xml"),
-					Sel: ast.NewIdent(first),
-				},
-				Args: args[:1],
-			},
-			Sel: ast.NewIdent(second),
-		},
-		Args: args[1:2],
-	}
-}
diff --git a/src/cmd/fix/xmlapi_test.go b/src/cmd/fix/xmlapi_test.go
deleted file mode 100644
index 6486c81..0000000
--- a/src/cmd/fix/xmlapi_test.go
+++ /dev/null
@@ -1,85 +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 main
-
-func init() {
-	addTestCases(xmlapiTests, xmlapi)
-}
-
-var xmlapiTests = []testCase{
-	{
-		Name: "xmlapi.0",
-		In: `package main
-
-import "encoding/xml"
-
-func f() {
-	xml.Marshal(a, b)
-	xml.Unmarshal(a, b)
-
-	var buf1 bytes.Buffer
-	buf2 := &bytes.Buffer{}
-	buf3 := bytes.NewBuffer(data)
-	buf4 := bytes.NewBufferString(data)
-	buf5 := bufio.NewReader(r)
-	xml.Unmarshal(&buf1, v)
-	xml.Unmarshal(buf2, v)
-	xml.Unmarshal(buf3, v)
-	xml.Unmarshal(buf4, v)
-	xml.Unmarshal(buf5, v)
-
-	f := os.Open("foo.xml")
-	xml.Unmarshal(f, v)
-
-	p1 := xml.NewParser(stream)
-	p1.Unmarshal(v, start)
-
-	var p2 *xml.Parser
-	p2.Unmarshal(v, start)
-}
-
-func g(r io.Reader, f *os.File, b []byte) {
-	xml.Unmarshal(r, v)
-	xml.Unmarshal(f, v)
-	xml.Unmarshal(b, v)
-}
-`,
-		Out: `package main
-
-import "encoding/xml"
-
-func f() {
-	xml.NewEncoder(a).Encode(b)
-	xml.Unmarshal(a, b)
-
-	var buf1 bytes.Buffer
-	buf2 := &bytes.Buffer{}
-	buf3 := bytes.NewBuffer(data)
-	buf4 := bytes.NewBufferString(data)
-	buf5 := bufio.NewReader(r)
-	xml.NewDecoder(&buf1).Decode(v)
-	xml.NewDecoder(buf2).Decode(v)
-	xml.NewDecoder(buf3).Decode(v)
-	xml.NewDecoder(buf4).Decode(v)
-	xml.NewDecoder(buf5).Decode(v)
-
-	f := os.Open("foo.xml")
-	xml.NewDecoder(f).Decode(v)
-
-	p1 := xml.NewDecoder(stream)
-	p1.DecodeElement(v, start)
-
-	var p2 *xml.Decoder
-	p2.DecodeElement(v, start)
-}
-
-func g(r io.Reader, f *os.File, b []byte) {
-	xml.NewDecoder(r).Decode(v)
-	xml.NewDecoder(f).Decode(v)
-	xml.Unmarshal(b, v)
-}
-`,
-	},
-}
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index 6982bbe..be9f552 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -15,8 +15,8 @@
 
 static int defercalc;
 
-uint32
-rnd(uint32 o, uint32 r)
+vlong
+rnd(vlong o, vlong r)
 {
 	if(r < 1 || r > 8 || (r&(r-1)) != 0)
 		fatal("rnd");
@@ -54,6 +54,11 @@ widstruct(Type *errtype, Type *t, vlong o, int flag)
 	for(f=t->type; f!=T; f=f->down) {
 		if(f->etype != TFIELD)
 			fatal("widstruct: not TFIELD: %lT", f);
+		if(f->type == T) {
+			// broken field, just skip it so that other valid fields
+			// get a width.
+			continue;
+		}
 		dowidth(f->type);
 		if(f->type->align > maxalign)
 			maxalign = f->type->align;
@@ -248,8 +253,12 @@ dowidth(Type *t)
 			checkwidth(t->type);
 			t->align = widthptr;
 		}
-		else if(t->bound == -100)
-			yyerror("use of [...] array outside of array literal");
+		else if(t->bound == -100) {
+			if(!t->broke) {
+				yyerror("use of [...] array outside of array literal");
+				t->broke = 1;
+			}
+		}
 		else
 			fatal("dowidth %T", t);	// probably [...]T
 		break;
@@ -607,7 +616,7 @@ typeinit(void)
 			fatal("typeinit: %s already defined", s->name);
 
 		t = typ(etype);
-		t->sym = s;
+		t->sym = s1;
 
 		dowidth(t);
 		types[etype] = t;
@@ -615,12 +624,12 @@ typeinit(void)
 	}
 
 	Array_array = rnd(0, widthptr);
-	Array_nel = rnd(Array_array+widthptr, types[TUINT32]->width);
-	Array_cap = rnd(Array_nel+types[TUINT32]->width, types[TUINT32]->width);
-	sizeof_Array = rnd(Array_cap+types[TUINT32]->width, widthptr);
+	Array_nel = rnd(Array_array+widthptr, widthint);
+	Array_cap = rnd(Array_nel+widthint, widthint);
+	sizeof_Array = rnd(Array_cap+widthint, widthptr);
 
 	// string is same as slice wo the cap
-	sizeof_String = rnd(Array_nel+types[TUINT32]->width, widthptr);
+	sizeof_String = rnd(Array_nel+widthint, widthptr);
 
 	dowidth(types[TSTRING]);
 	dowidth(idealstring);
diff --git a/src/cmd/gc/bisonerrors b/src/cmd/gc/bisonerrors
index 0f865d0..8886a8e 100755
--- a/src/cmd/gc/bisonerrors
+++ b/src/cmd/gc/bisonerrors
@@ -41,9 +41,9 @@ grammar && NF>0 {
 }
 
 # In state dumps, record shift/reduce actions.
-bison && /^state 0/ { grammar = 0; states = 1 }
+bison && /^[Ss]tate 0/ { grammar = 0; states = 1 }
 
-states && /^state / { state = $2 }
+states && /^[Ss]tate / { state = $2 }
 states { statetext[state] = statetext[state] $0 "\n" }
 
 states && / shift/ {
diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c
index ca3d667..7de448d 100644
--- a/src/cmd/gc/builtin.c
+++ b/src/cmd/gc/builtin.c
@@ -1,118 +1,119 @@
 char *runtimeimport =
 	"package runtime\n"
 	"import runtime \"runtime\"\n"
-	"func @\"\".new(@\"\".typ *byte) (? *any)\n"
-	"func @\"\".panicindex()\n"
-	"func @\"\".panicslice()\n"
-	"func @\"\".throwreturn()\n"
-	"func @\"\".throwinit()\n"
-	"func @\"\".panicwrap(? string, ? string, ? string)\n"
-	"func @\"\".panic(? interface {})\n"
-	"func @\"\".recover(? *int32) (? interface {})\n"
-	"func @\"\".printbool(? bool)\n"
-	"func @\"\".printfloat(? float64)\n"
-	"func @\"\".printint(? int64)\n"
-	"func @\"\".printuint(? uint64)\n"
-	"func @\"\".printcomplex(? complex128)\n"
-	"func @\"\".printstring(? string)\n"
-	"func @\"\".printpointer(? any)\n"
-	"func @\"\".printiface(? any)\n"
-	"func @\"\".printeface(? any)\n"
-	"func @\"\".printslice(? any)\n"
-	"func @\"\".printnl()\n"
-	"func @\"\".printsp()\n"
-	"func @\"\".goprintf()\n"
-	"func @\"\".concatstring()\n"
-	"func @\"\".append()\n"
-	"func @\"\".appendslice(@\"\".typ *byte, @\"\".x any, @\"\".y []any) (? any)\n"
-	"func @\"\".appendstr(@\"\".typ *byte, @\"\".x []byte, @\"\".y string) (? []byte)\n"
-	"func @\"\".cmpstring(? string, ? string) (? int)\n"
-	"func @\"\".slicestring(? string, ? int, ? int) (? string)\n"
-	"func @\"\".slicestring1(? string, ? int) (? string)\n"
-	"func @\"\".intstring(? int64) (? string)\n"
-	"func @\"\".slicebytetostring(? []byte) (? string)\n"
-	"func @\"\".slicerunetostring(? []rune) (? string)\n"
-	"func @\"\".stringtoslicebyte(? string) (? []byte)\n"
-	"func @\"\".stringtoslicerune(? string) (? []rune)\n"
-	"func @\"\".stringiter(? string, ? int) (? int)\n"
-	"func @\"\".stringiter2(? string, ? int) (@\"\".retk int, @\"\".retv rune)\n"
-	"func @\"\".copy(@\"\".to any, @\"\".fr any, @\"\".wid uint32) (? int)\n"
-	"func @\"\".slicestringcopy(@\"\".to any, @\"\".fr any) (? int)\n"
-	"func @\"\".convI2E(@\"\".elem any) (@\"\".ret any)\n"
-	"func @\"\".convI2I(@\"\".typ *byte, @\"\".elem any) (@\"\".ret any)\n"
-	"func @\"\".convT2E(@\"\".typ *byte, @\"\".elem any) (@\"\".ret any)\n"
-	"func @\"\".convT2I(@\"\".typ *byte, @\"\".typ2 *byte, @\"\".elem any) (@\"\".ret any)\n"
-	"func @\"\".assertE2E(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
-	"func @\"\".assertE2E2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
-	"func @\"\".assertE2I(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
-	"func @\"\".assertE2I2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
-	"func @\"\".assertE2T(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
-	"func @\"\".assertE2T2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
-	"func @\"\".assertI2E(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
-	"func @\"\".assertI2E2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
-	"func @\"\".assertI2I(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
-	"func @\"\".assertI2I2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
-	"func @\"\".assertI2T(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
-	"func @\"\".assertI2T2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
-	"func @\"\".ifaceeq(@\"\".i1 any, @\"\".i2 any) (@\"\".ret bool)\n"
-	"func @\"\".efaceeq(@\"\".i1 any, @\"\".i2 any) (@\"\".ret bool)\n"
-	"func @\"\".ifacethash(@\"\".i1 any) (@\"\".ret uint32)\n"
-	"func @\"\".efacethash(@\"\".i1 any) (@\"\".ret uint32)\n"
-	"func @\"\".equal(@\"\".typ *byte, @\"\".x1 any, @\"\".x2 any) (@\"\".ret bool)\n"
-	"func @\"\".makemap(@\"\".mapType *byte, @\"\".hint int64) (@\"\".hmap map[any]any)\n"
-	"func @\"\".mapaccess1(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".key any) (@\"\".val any)\n"
-	"func @\"\".mapaccess2(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".key any) (@\"\".val any, @\"\".pres bool)\n"
-	"func @\"\".mapassign1(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".key any, @\"\".val any)\n"
-	"func @\"\".mapassign2(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".key any, @\"\".val any, @\"\".pres bool)\n"
-	"func @\"\".mapiterinit(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".hiter *any)\n"
-	"func @\"\".mapdelete(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".key any)\n"
-	"func @\"\".mapiternext(@\"\".hiter *any)\n"
-	"func @\"\".mapiter1(@\"\".hiter *any) (@\"\".key any)\n"
-	"func @\"\".mapiter2(@\"\".hiter *any) (@\"\".key any, @\"\".val any)\n"
-	"func @\"\".makechan(@\"\".chanType *byte, @\"\".hint int64) (@\"\".hchan chan any)\n"
-	"func @\"\".chanrecv1(@\"\".chanType *byte, @\"\".hchan <-chan any) (@\"\".elem any)\n"
-	"func @\"\".chanrecv2(@\"\".chanType *byte, @\"\".hchan <-chan any) (@\"\".elem any, @\"\".received bool)\n"
-	"func @\"\".chansend1(@\"\".chanType *byte, @\"\".hchan chan<- any, @\"\".elem any)\n"
-	"func @\"\".closechan(@\"\".hchan any)\n"
-	"func @\"\".selectnbsend(@\"\".chanType *byte, @\"\".hchan chan<- any, @\"\".elem any) (? bool)\n"
-	"func @\"\".selectnbrecv(@\"\".chanType *byte, @\"\".elem *any, @\"\".hchan <-chan any) (? bool)\n"
-	"func @\"\".selectnbrecv2(@\"\".chanType *byte, @\"\".elem *any, @\"\".received *bool, @\"\".hchan <-chan any) (? bool)\n"
-	"func @\"\".newselect(@\"\".size int) (@\"\".sel *byte)\n"
-	"func @\"\".selectsend(@\"\".sel *byte, @\"\".hchan chan<- any, @\"\".elem *any) (@\"\".selected bool)\n"
-	"func @\"\".selectrecv(@\"\".sel *byte, @\"\".hchan <-chan any, @\"\".elem *any) (@\"\".selected bool)\n"
-	"func @\"\".selectrecv2(@\"\".sel *byte, @\"\".hchan <-chan any, @\"\".elem *any, @\"\".received *bool) (@\"\".selected bool)\n"
-	"func @\"\".selectdefault(@\"\".sel *byte) (@\"\".selected bool)\n"
-	"func @\"\".selectgo(@\"\".sel *byte)\n"
-	"func @\"\".block()\n"
-	"func @\"\".makeslice(@\"\".typ *byte, @\"\".nel int64, @\"\".cap int64) (@\"\".ary []any)\n"
-	"func @\"\".growslice(@\"\".typ *byte, @\"\".old []any, @\"\".n int64) (@\"\".ary []any)\n"
-	"func @\"\".sliceslice1(@\"\".old []any, @\"\".lb uint64, @\"\".width uint64) (@\"\".ary []any)\n"
-	"func @\"\".sliceslice(@\"\".old []any, @\"\".lb uint64, @\"\".hb uint64, @\"\".width uint64) (@\"\".ary []any)\n"
-	"func @\"\".slicearray(@\"\".old *any, @\"\".nel uint64, @\"\".lb uint64, @\"\".hb uint64, @\"\".width uint64) (@\"\".ary []any)\n"
-	"func @\"\".closure()\n"
-	"func @\"\".memequal(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
-	"func @\"\".memequal8(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
-	"func @\"\".memequal16(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
-	"func @\"\".memequal32(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
-	"func @\"\".memequal64(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
-	"func @\"\".memequal128(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
-	"func @\"\".int64div(? int64, ? int64) (? int64)\n"
-	"func @\"\".uint64div(? uint64, ? uint64) (? uint64)\n"
-	"func @\"\".int64mod(? int64, ? int64) (? int64)\n"
-	"func @\"\".uint64mod(? uint64, ? uint64) (? uint64)\n"
-	"func @\"\".float64toint64(? float64) (? int64)\n"
-	"func @\"\".float64touint64(? float64) (? uint64)\n"
-	"func @\"\".int64tofloat64(? int64) (? float64)\n"
-	"func @\"\".uint64tofloat64(? uint64) (? float64)\n"
-	"func @\"\".complex128div(@\"\".num complex128, @\"\".den complex128) (@\"\".quo complex128)\n"
+	"func @\"\".new (@\"\".typ·2 *byte) (? *any)\n"
+	"func @\"\".panicindex ()\n"
+	"func @\"\".panicslice ()\n"
+	"func @\"\".throwreturn ()\n"
+	"func @\"\".throwinit ()\n"
+	"func @\"\".panicwrap (? string, ? string, ? string)\n"
+	"func @\"\".panic (? interface {})\n"
+	"func @\"\".recover (? *int32) (? interface {})\n"
+	"func @\"\".printbool (? bool)\n"
+	"func @\"\".printfloat (? float64)\n"
+	"func @\"\".printint (? int64)\n"
+	"func @\"\".printuint (? uint64)\n"
+	"func @\"\".printcomplex (? complex128)\n"
+	"func @\"\".printstring (? string)\n"
+	"func @\"\".printpointer (? any)\n"
+	"func @\"\".printiface (? any)\n"
+	"func @\"\".printeface (? any)\n"
+	"func @\"\".printslice (? any)\n"
+	"func @\"\".printnl ()\n"
+	"func @\"\".printsp ()\n"
+	"func @\"\".goprintf ()\n"
+	"func @\"\".concatstring ()\n"
+	"func @\"\".append ()\n"
+	"func @\"\".appendslice (@\"\".typ·2 *byte, @\"\".x·3 any, @\"\".y·4 []any) (? any)\n"
+	"func @\"\".appendstr (@\"\".typ·2 *byte, @\"\".x·3 []byte, @\"\".y·4 string) (? []byte)\n"
+	"func @\"\".cmpstring (? string, ? string) (? int)\n"
+	"func @\"\".eqstring (? string, ? string) (? bool)\n"
+	"func @\"\".intstring (? int64) (? string)\n"
+	"func @\"\".slicebytetostring (? []byte) (? string)\n"
+	"func @\"\".slicerunetostring (? []rune) (? string)\n"
+	"func @\"\".stringtoslicebyte (? string) (? []byte)\n"
+	"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 @\"\".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"
+	"func @\"\".convI2I (@\"\".typ·2 *byte, @\"\".elem·3 any) (@\"\".ret·1 any)\n"
+	"func @\"\".convT2E (@\"\".typ·2 *byte, @\"\".elem·3 any) (@\"\".ret·1 any)\n"
+	"func @\"\".convT2I (@\"\".typ·2 *byte, @\"\".typ2·3 *byte, @\"\".cache·4 **byte, @\"\".elem·5 any) (@\"\".ret·1 any)\n"
+	"func @\"\".assertE2E (@\"\".typ·2 *byte, @\"\".iface·3 any) (@\"\".ret·1 any)\n"
+	"func @\"\".assertE2E2 (@\"\".typ·3 *byte, @\"\".iface·4 any) (@\"\".ret·1 any, @\"\".ok·2 bool)\n"
+	"func @\"\".assertE2I (@\"\".typ·2 *byte, @\"\".iface·3 any) (@\"\".ret·1 any)\n"
+	"func @\"\".assertE2I2 (@\"\".typ·3 *byte, @\"\".iface·4 any) (@\"\".ret·1 any, @\"\".ok·2 bool)\n"
+	"func @\"\".assertE2T (@\"\".typ·2 *byte, @\"\".iface·3 any) (@\"\".ret·1 any)\n"
+	"func @\"\".assertE2T2 (@\"\".typ·3 *byte, @\"\".iface·4 any) (@\"\".ret·1 any, @\"\".ok·2 bool)\n"
+	"func @\"\".assertI2E (@\"\".typ·2 *byte, @\"\".iface·3 any) (@\"\".ret·1 any)\n"
+	"func @\"\".assertI2E2 (@\"\".typ·3 *byte, @\"\".iface·4 any) (@\"\".ret·1 any, @\"\".ok·2 bool)\n"
+	"func @\"\".assertI2I (@\"\".typ·2 *byte, @\"\".iface·3 any) (@\"\".ret·1 any)\n"
+	"func @\"\".assertI2I2 (@\"\".typ·3 *byte, @\"\".iface·4 any) (@\"\".ret·1 any, @\"\".ok·2 bool)\n"
+	"func @\"\".assertI2T (@\"\".typ·2 *byte, @\"\".iface·3 any) (@\"\".ret·1 any)\n"
+	"func @\"\".assertI2T2 (@\"\".typ·3 *byte, @\"\".iface·4 any) (@\"\".ret·1 any, @\"\".ok·2 bool)\n"
+	"func @\"\".assertI2TOK (@\"\".typ·2 *byte, @\"\".iface·3 any) (@\"\".ok·1 bool)\n"
+	"func @\"\".assertE2TOK (@\"\".typ·2 *byte, @\"\".iface·3 any) (@\"\".ok·1 bool)\n"
+	"func @\"\".ifaceeq (@\"\".i1·2 any, @\"\".i2·3 any) (@\"\".ret·1 bool)\n"
+	"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 @\"\".mapaccess2 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 any, @\"\".pres·2 bool)\n"
+	"func @\"\".mapassign1 (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 any, @\"\".val·4 any)\n"
+	"func @\"\".mapiterinit (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".hiter·3 *any)\n"
+	"func @\"\".mapdelete (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 any)\n"
+	"func @\"\".mapiternext (@\"\".hiter·1 *any)\n"
+	"func @\"\".mapiter1 (@\"\".hiter·2 *any) (@\"\".key·1 any)\n"
+	"func @\"\".mapiter2 (@\"\".hiter·3 *any) (@\"\".key·1 any, @\"\".val·2 any)\n"
+	"func @\"\".makechan (@\"\".chanType·2 *byte, @\"\".hint·3 int64) (@\"\".hchan·1 chan any)\n"
+	"func @\"\".chanrecv1 (@\"\".chanType·2 *byte, @\"\".hchan·3 <-chan any) (@\"\".elem·1 any)\n"
+	"func @\"\".chanrecv2 (@\"\".chanType·3 *byte, @\"\".hchan·4 <-chan any) (@\"\".elem·1 any, @\"\".received·2 bool)\n"
+	"func @\"\".chansend1 (@\"\".chanType·1 *byte, @\"\".hchan·2 chan<- any, @\"\".elem·3 any)\n"
+	"func @\"\".closechan (@\"\".hchan·1 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 @\"\".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"
+	"func @\"\".selectdefault (@\"\".sel·2 *byte) (@\"\".selected·1 bool)\n"
+	"func @\"\".selectgo (@\"\".sel·1 *byte)\n"
+	"func @\"\".block ()\n"
+	"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 @\"\".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 @\"\".int64div (? int64, ? int64) (? int64)\n"
+	"func @\"\".uint64div (? uint64, ? uint64) (? uint64)\n"
+	"func @\"\".int64mod (? int64, ? int64) (? int64)\n"
+	"func @\"\".uint64mod (? uint64, ? uint64) (? uint64)\n"
+	"func @\"\".float64toint64 (? float64) (? int64)\n"
+	"func @\"\".float64touint64 (? float64) (? uint64)\n"
+	"func @\"\".int64tofloat64 (? int64) (? float64)\n"
+	"func @\"\".uint64tofloat64 (? uint64) (? float64)\n"
+	"func @\"\".complex128div (@\"\".num·2 complex128, @\"\".den·3 complex128) (@\"\".quo·1 complex128)\n"
+	"func @\"\".racefuncenter (? uintptr)\n"
+	"func @\"\".racefuncexit ()\n"
+	"func @\"\".raceread (? uintptr)\n"
+	"func @\"\".racewrite (? uintptr)\n"
 	"\n"
 	"$$\n";
 char *unsafeimport =
 	"package unsafe\n"
 	"import runtime \"runtime\"\n"
 	"type @\"\".Pointer uintptr\n"
-	"func @\"\".Offsetof(? any) (? uintptr)\n"
-	"func @\"\".Sizeof(? any) (? uintptr)\n"
-	"func @\"\".Alignof(? any) (? uintptr)\n"
+	"func @\"\".Offsetof (? any) (? uintptr)\n"
+	"func @\"\".Sizeof (? any) (? uintptr)\n"
+	"func @\"\".Alignof (? any) (? uintptr)\n"
 	"\n"
 	"$$\n";
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index fa44e40..4e029ef 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -75,6 +75,8 @@ closurebody(NodeList *body)
 	return func;
 }
 
+static Node* makeclosure(Node *func, int nowrap);
+
 void
 typecheckclosure(Node *func, int top)
 {
@@ -85,12 +87,12 @@ typecheckclosure(Node *func, int top)
 	oldfn = curfn;
 	typecheck(&func->ntype, Etype);
 	func->type = func->ntype->type;
-	if(curfn == nil) {
-		xtop = list(xtop, func);
-		return;
-	}
-
-	if(func->type != T) {
+	
+	// Type check the body now, but only if we're inside a function.
+	// At top level (in a variable initialization: curfn==nil) we're not
+	// ready to type check code yet; we'll check it later, because the
+	// underlying closure function we create is added to xtop.
+	if(curfn && func->type != T) {
 		curfn = func;
 		typechecklist(func->nbody, Etop);
 		curfn = oldfn;
@@ -120,26 +122,43 @@ typecheckclosure(Node *func, int top)
 		func->enter = list(func->enter, v->heapaddr);
 		v->heapaddr = N;
 	}
+
+	// Create top-level function 
+	xtop = list(xtop, makeclosure(func, func->cvars==nil || (top&Ecall)));
 }
 
 static Node*
-makeclosure(Node *func, NodeList **init, int nowrap)
+makeclosure(Node *func, int nowrap)
 {
-	Node *xtype, *v, *addr, *xfunc;
-	NodeList *l;
+	Node *xtype, *v, *addr, *xfunc, *cv;
+	NodeList *l, *body;
 	static int closgen;
 	char *p;
-
-	USED(init);
+	int offset;
 
 	/*
 	 * wrap body in external function
-	 * with extra closure parameters.
+	 * that begins by reading closure parameters.
 	 */
 	xtype = nod(OTFUNC, N, N);
+	xtype->list = func->list;
+	xtype->rlist = func->rlist;
 
-	// each closure variable has a corresponding
-	// address parameter.
+	// create the function
+	xfunc = nod(ODCLFUNC, N, N);
+	snprint(namebuf, sizeof namebuf, "func·%.3d", ++closgen);
+	xfunc->nname = newname(lookup(namebuf));
+	xfunc->nname->sym->flags |= SymExported; // disable export
+	xfunc->nname->ntype = xtype;
+	xfunc->nname->defn = xfunc;
+	declare(xfunc->nname, PFUNC);
+	xfunc->nname->funcdepth = func->funcdepth;
+	xfunc->funcdepth = func->funcdepth;
+	
+	// declare variables holding addresses taken from closure
+	// and initialize in entry prologue.
+	body = nil;
+	offset = widthptr;
 	for(l=func->cvars; l; l=l->next) {
 		v = l->n;
 		if(v->op == 0)
@@ -149,38 +168,35 @@ makeclosure(Node *func, NodeList **init, int nowrap)
 		addr->sym = lookup(p);
 		free(p);
 		addr->ntype = nod(OIND, typenod(v->type), N);
-		addr->class = PPARAM;
+		addr->class = PAUTO;
 		addr->addable = 1;
 		addr->ullman = 1;
-
+		addr->used = 1;
+		addr->curfn = xfunc;
+		xfunc->dcl = list(xfunc->dcl, addr);
 		v->heapaddr = addr;
-
-		xtype->list = list(xtype->list, nod(ODCLFIELD, addr, addr->ntype));
+		cv = nod(OCLOSUREVAR, N, N);
+		cv->type = ptrto(v->type);
+		cv->xoffset = offset;
+		body = list(body, nod(OAS, addr, cv));
+		offset += widthptr;
 	}
+	typechecklist(body, Etop);
+	walkstmtlist(body);
+	xfunc->enter = body;
 
-	// then a dummy arg where the closure's caller pc sits
-	if (!nowrap)
-		xtype->list = list(xtype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
-
-	// then the function arguments
-	xtype->list = concat(xtype->list, func->list);
-	xtype->rlist = concat(xtype->rlist, func->rlist);
-
-	// create the function
-	xfunc = nod(ODCLFUNC, N, N);
-	snprint(namebuf, sizeof namebuf, "_func_%.3d", ++closgen);
-	xfunc->nname = newname(lookup(namebuf));
-	xfunc->nname->ntype = xtype;
-	xfunc->nname->defn = xfunc;
-	declare(xfunc->nname, PFUNC);
-	xfunc->nname->funcdepth = func->funcdepth;
-	xfunc->funcdepth = func->funcdepth;
 	xfunc->nbody = func->nbody;
-	xfunc->dcl = func->dcl;
+	xfunc->dcl = concat(func->dcl, xfunc->dcl);
 	if(xfunc->nbody == nil)
 		fatal("empty body - won't generate any code");
 	typecheck(&xfunc, Etop);
-	closures = list(closures, xfunc);
+
+	xfunc->closure = func;
+	func->closure = xfunc;
+	
+	func->nbody = nil;
+	func->list = nil;
+	func->rlist = nil;
 
 	return xfunc;
 }
@@ -188,51 +204,55 @@ makeclosure(Node *func, NodeList **init, int nowrap)
 Node*
 walkclosure(Node *func, NodeList **init)
 {
+	Node *clos, *typ;
+	NodeList *l;
+	char buf[20];
 	int narg;
-	Node *xtype, *xfunc, *call, *clos;
-	NodeList *l, *in;
 
-	// no closure vars, don't bother wrapping
+	// If no closure vars, don't bother wrapping.
 	if(func->cvars == nil)
-		return makeclosure(func, init, 1)->nname;
+		return func->closure->nname;
+
+	// Create closure in the form of a composite literal.
+	// supposing the closure captures an int i and a string s
+	// and has one float64 argument and no results,
+	// the generated code looks like:
+	//
+	//	clos = &struct{F uintptr; A0 *int; A1 *string}{func·001, &i, &s}
+	//
+	// The use of the struct provides type information to the garbage
+	// collector so that it can walk the closure. We could use (in this case)
+	// [3]unsafe.Pointer instead, but that would leave the gc in the dark.
+	// The information appears in the binary in the form of type descriptors;
+	// the struct is unnamed so that closures in multiple packages with the
+	// same struct type can share the descriptor.
 
-	/*
-	 * wrap body in external function
-	 * with extra closure parameters.
-	 */
-
-	// create the function
-	xfunc = makeclosure(func, init, 0);
-	xtype = xfunc->nname->ntype;
-
-	// prepare call of sys.closure that turns external func into func literal value.
-	clos = syslook("closure", 1);
-	clos->type = T;
-	clos->ntype = nod(OTFUNC, N, N);
-	in = list1(nod(ODCLFIELD, N, typenod(types[TINT])));	// siz
-	in = list(in, nod(ODCLFIELD, N, xtype));
 	narg = 0;
+	typ = nod(OTSTRUCT, N, N);
+	typ->list = list1(nod(ODCLFIELD, newname(lookup("F")), typenod(types[TUINTPTR])));
 	for(l=func->cvars; l; l=l->next) {
 		if(l->n->op == 0)
 			continue;
-		narg++;
-		in = list(in, nod(ODCLFIELD, N, l->n->heapaddr->ntype));
+		snprint(buf, sizeof buf, "A%d", narg++);
+		typ->list = list(typ->list, nod(ODCLFIELD, newname(lookup(buf)), l->n->heapaddr->ntype));
 	}
-	clos->ntype->list = in;
-	clos->ntype->rlist = list1(nod(ODCLFIELD, N, typenod(func->type)));
+
+	clos = nod(OCOMPLIT, N, nod(OIND, typ, N));
+	clos->esc = func->esc;
+	clos->right->implicit = 1;
+	clos->list = concat(list1(nod(OCFUNC, func->closure->nname, N)), func->enter);
+
+	// Force type conversion from *struct to the func type.
+	clos = nod(OCONVNOP, clos, N);
+	clos->type = func->type;
+
 	typecheck(&clos, Erv);
+	// typecheck will insert a PTRLIT node under CONVNOP,
+	// tag it with escape analysis result.
+	clos->left->esc = func->esc;
+	walkexpr(&clos, init);
 
-	call = nod(OCALL, clos, N);
-	if(narg*widthptr > 100)
-		yyerror("closure needs too many variables; runtime will reject it");
-	in = list1(nodintconst(narg*widthptr));
-	in = list(in, xfunc->nname);
-	in = concat(in, func->enter);
-	call->list = in;
-
-	typecheck(&call, Erv);
-	walkexpr(&call, init);
-	return call;
+	return clos;
 }
 
 // Special case for closures that get called in place.
@@ -242,6 +262,7 @@ walkclosure(Node *func, NodeList **init)
 void
 walkcallclosure(Node *n, NodeList **init)
 {
+	USED(init);
 	if (n->op != OCALLFUNC || n->left->op != OCLOSURE) {
 		dump("walkcallclosure", n);
 		fatal("abuse of walkcallclosure");
@@ -250,7 +271,7 @@ walkcallclosure(Node *n, NodeList **init)
 	// New arg list for n. First the closure-args
 	// and then the original parameter list.
 	n->list = concat(n->left->enter, n->list);
-	n->left = makeclosure(n->left, init, 1)->nname;
+	n->left = n->left->closure->nname;
 	dowidth(n->left->type);
 	n->type = getoutargx(n->left->type);
 	// for a single valued function, pull the field type out of the struct
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index e27c883..4f1ff67 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -87,8 +87,12 @@ convlit1(Node **np, Type *t, int explicit)
 
 	switch(n->op) {
 	default:
-		if(n->type == idealbool)
-			n->type = types[TBOOL];
+		if(n->type == idealbool) {
+			if(t->etype == TBOOL)
+				n->type = t;
+			else
+				n->type = types[TBOOL];
+		}
 		if(n->type->etype == TIDEAL) {
 			convlit(&n->left, t);
 			convlit(&n->right, t);
@@ -162,6 +166,16 @@ convlit1(Node **np, Type *t, int explicit)
 		case TFUNC:
 		case TUNSAFEPTR:
 			break;
+
+		case TUINTPTR:
+			// A nil literal may be converted to uintptr
+			// if it is an unsafe.Pointer
+			if(n->type->etype == TUNSAFEPTR) {
+				n->val.u.xval = mal(sizeof(*n->val.u.xval));
+				mpmovecfix(n->val.u.xval, 0);
+				n->val.ctype = CTINT;
+			} else
+				goto bad;
 		}
 		break;
 
@@ -230,7 +244,8 @@ convlit1(Node **np, Type *t, int explicit)
 
 bad:
 	if(!n->diag) {
-		yyerror("cannot convert %N to type %T", n, t);
+		if(!t->broke)
+			yyerror("cannot convert %N to type %T", n, t);
 		n->diag = 1;
 	}
 	if(isideal(n->type)) {
@@ -348,13 +363,9 @@ toint(Val v)
 	return v;
 }
 
-void
-overflow(Val v, Type *t)
+int
+doesoverflow(Val v, Type *t)
 {
-	// v has already been converted
-	// to appropriate form for t.
-	if(t == T || t->etype == TIDEAL)
-		return;
 	switch(v.ctype) {
 	case CTINT:
 	case CTRUNE:
@@ -362,14 +373,14 @@ overflow(Val v, Type *t)
 			fatal("overflow: %T integer constant", t);
 		if(mpcmpfixfix(v.u.xval, minintval[t->etype]) < 0 ||
 		   mpcmpfixfix(v.u.xval, maxintval[t->etype]) > 0)
-			yyerror("constant %B overflows %T", v.u.xval, t);
+			return 1;
 		break;
 	case CTFLT:
 		if(!isfloat[t->etype])
 			fatal("overflow: %T floating-point constant", t);
 		if(mpcmpfltflt(v.u.fval, minfltval[t->etype]) <= 0 ||
 		   mpcmpfltflt(v.u.fval, maxfltval[t->etype]) >= 0)
-			yyerror("constant %#F overflows %T", v.u.fval, t);
+			return 1;
 		break;
 	case CTCPLX:
 		if(!iscomplex[t->etype])
@@ -378,7 +389,33 @@ overflow(Val v, Type *t)
 		   mpcmpfltflt(&v.u.cval->real, maxfltval[t->etype]) >= 0 ||
 		   mpcmpfltflt(&v.u.cval->imag, minfltval[t->etype]) <= 0 ||
 		   mpcmpfltflt(&v.u.cval->imag, maxfltval[t->etype]) >= 0)
-			yyerror("constant %#F overflows %T", v.u.fval, t);
+			return 1;
+		break;
+	}
+	return 0;
+}
+
+void
+overflow(Val v, Type *t)
+{
+	// v has already been converted
+	// to appropriate form for t.
+	if(t == T || t->etype == TIDEAL)
+		return;
+
+	if(!doesoverflow(v, t))
+		return;
+
+	switch(v.ctype) {
+	case CTINT:
+	case CTRUNE:
+		yyerror("constant %B overflows %T", v.u.xval, t);
+		break;
+	case CTFLT:
+		yyerror("constant %#F overflows %T", v.u.fval, t);
+		break;
+	case CTCPLX:
+		yyerror("constant %#F overflows %T", v.u.fval, t);
 		break;
 	}
 }
@@ -437,6 +474,20 @@ isconst(Node *n, int ct)
 	return t == ct || (ct == CTINT && t == CTRUNE);
 }
 
+static Node*
+saveorig(Node *n)
+{
+	Node *n1;
+
+	if(n == n->orig) {
+		// duplicate node for n->orig.
+		n1 = nod(OLITERAL, N, N);
+		n->orig = n1;
+		*n1 = *n;
+	}
+	return n->orig;
+}
+
 /*
  * if n is constant, rewrite as OLITERAL node.
  */
@@ -902,12 +953,7 @@ unary:
 	}
 
 ret:
-	if(n == n->orig) {
-		// duplicate node for n->orig.
-		norig = nod(OLITERAL, N, N);
-		*norig = *n;
-	} else
-		norig = n->orig;
+	norig = saveorig(n);
 	*n = *nl;
 	// restore value of n->orig.
 	n->orig = norig;
@@ -924,11 +970,15 @@ ret:
 	return;
 
 settrue:
+	norig = saveorig(n);
 	*n = *nodbool(1);
+	n->orig = norig;
 	return;
 
 setfalse:
+	norig = saveorig(n);
 	*n = *nodbool(0);
+	n->orig = norig;
 	return;
 }
 
@@ -984,79 +1034,88 @@ nodcplxlit(Val r, Val i)
 	return n;
 }
 
-// TODO(rsc): combine with convlit
+// idealkind returns a constant kind like consttype
+// but for an arbitrary "ideal" expression.
+static int
+idealkind(Node *n)
+{
+	int k1, k2;
+
+	if(n == N || !isideal(n->type))
+		return CTxxx;
+
+	switch(n->op) {
+	default:
+		return CTxxx;
+	case OLITERAL:
+		return n->val.ctype;
+	case OADD:
+	case OAND:
+	case OANDNOT:
+	case OCOM:
+	case ODIV:
+	case OMINUS:
+	case OMOD:
+	case OMUL:
+	case OSUB:
+	case OXOR:
+	case OOR:
+	case OPLUS:
+		// numeric kinds.
+		k1 = idealkind(n->left);
+		k2 = idealkind(n->right);
+		if(k1 > k2)
+			return k1;
+		else
+			return k2;
+	case OADDSTR:
+		return CTSTR;
+	case OANDAND:
+	case OEQ:
+	case OGE:
+	case OGT:
+	case OLE:
+	case OLT:
+	case ONE:
+	case ONOT:
+	case OOROR:
+	case OCMPSTR:
+	case OCMPIFACE:
+		return CTBOOL;
+	case OLSH:
+	case ORSH:
+		// shifts (beware!).
+		return idealkind(n->left);
+	}
+}
+
 void
 defaultlit(Node **np, Type *t)
 {
 	int lno;
+	int ctype;
 	Node *n, *nn;
+	Type *t1;
 
 	n = *np;
 	if(n == N || !isideal(n->type))
 		return;
 
-	switch(n->op) {
-	case OLITERAL:
+	if(n->op == OLITERAL) {
 		nn = nod(OXXX, N, N);
 		*nn = *n;
 		n = nn;
 		*np = n;
-		break;
-	case OLSH:
-	case ORSH:
-		defaultlit(&n->left, t);
-		t = n->left->type;
-		if(t != T && !isint[t->etype]) {
-			yyerror("invalid operation: %N (shift of type %T)", n, t);
-			t = T;
-		}
-		n->type = t;
-		return;
-	case ONOT:
-		defaultlit(&n->left, t);
-		n->type = n->left->type;
-		return;
-	default:
-		if(n->left == N) {
-			dump("defaultlit", n);
-			fatal("defaultlit");
-		}
-		// n is ideal, so left and right must both be ideal.
-		// n has not been computed as a constant value,
-		// so either left or right must not be constant.
-		// The only 'ideal' non-constant expressions are shifts.  Ugh.
-		// If one of these is a shift and the other is not, use that type.
-		// When compiling x := 1<<i + 3.14, this means we try to push
-		// the float64 down into the 1<<i, producing the correct error
-		// (cannot shift float64).
-		if(t == T && (n->right->op == OLSH || n->right->op == ORSH)) {
-			defaultlit(&n->left, T);
-			defaultlit(&n->right, n->left->type);
-		} else if(t == T && (n->left->op == OLSH || n->left->op == ORSH)) {
-			defaultlit(&n->right, T);
-			defaultlit(&n->left, n->right->type);
-		} else if(iscmp[n->op]) {
-			defaultlit2(&n->left, &n->right, 1);
-		} else {
-			defaultlit(&n->left, t);
-			defaultlit(&n->right, t);
-		}
-		if(n->type == idealbool || n->type == idealstring) {
-			if(t != T && t->etype == n->type->etype)
-				n->type = t;
-			else
-				n->type = types[n->type->etype];
-		} else
-			n->type = n->left->type;
-		return;
 	}
 
 	lno = setlineno(n);
-	switch(n->val.ctype) {
+	ctype = idealkind(n);
+	t1 = T;
+	switch(ctype) {
 	default:
 		if(t != T) {
 			convlit(np, t);
-			break;
+			return;
 		}
 		if(n->val.ctype == CTNIL) {
 			lineno = lno;
@@ -1065,46 +1124,52 @@ defaultlit(Node **np, Type *t)
 			break;
 		}
 		if(n->val.ctype == CTSTR) {
-			n->type = types[TSTRING];
+			t1 = types[TSTRING];
+			convlit(np, t1);
 			break;
 		}
 		yyerror("defaultlit: unknown literal: %N", n);
 		break;
+	case CTxxx:
+		fatal("defaultlit: idealkind is CTxxx: %+N", n);
+		break;
 	case CTBOOL:
-		n->type = types[TBOOL];
+		t1 = types[TBOOL];
 		if(t != T && t->etype == TBOOL)
-			n->type = t;
+			t1 = t;
+		convlit(np, t1);
 		break;
 	case CTINT:
-		n->type = types[TINT];
+		t1 = types[TINT];
 		goto num;
 	case CTRUNE:
-		n->type = runetype;
+		t1 = runetype;
 		goto num;
 	case CTFLT:
-		n->type = types[TFLOAT64];
+		t1 = types[TFLOAT64];
 		goto num;
 	case CTCPLX:
-		n->type = types[TCOMPLEX128];
+		t1 = types[TCOMPLEX128];
 		goto num;
 	num:
 		if(t != T) {
 			if(isint[t->etype]) {
-				n->type = t;
+				t1 = t;
 				n->val = toint(n->val);
 			}
 			else
 			if(isfloat[t->etype]) {
-				n->type = t;
+				t1 = t;
 				n->val = toflt(n->val);
 			}
 			else
 			if(iscomplex[t->etype]) {
-				n->type = t;
+				t1 = t;
 				n->val = tocplx(n->val);
 			}
 		}
-		overflow(n->val, n->type);
+		overflow(n->val, t1);
+		convlit(np, t1);
 		break;
 	}
 	lineno = lno;
@@ -1206,6 +1271,7 @@ smallintconst(Node *n)
 	case TIDEAL:
 	case TINT64:
 	case TUINT64:
+	case TPTR64:
 		if(mpcmpfixfix(n->val.u.xval, minintval[TINT32]) < 0
 		|| mpcmpfixfix(n->val.u.xval, maxintval[TINT32]) > 0)
 			break;
@@ -1392,3 +1458,132 @@ cmplxdiv(Mpcplx *v, Mpcplx *rv)
 	mpsubfltflt(&v->imag, &ad);		// bc-ad
 	mpdivfltflt(&v->imag, &cc_plus_dd);	// (bc+ad)/(cc+dd)
 }
+
+static int hascallchan(Node*);
+
+// Is n a Go language constant (as opposed to a compile-time constant)?
+// Expressions derived from nil, like string([]byte(nil)), while they
+// may be known at compile time, are not Go language constants.
+// Only called for expressions known to evaluated to compile-time
+// constants.
+int
+isgoconst(Node *n)
+{
+	Node *l;
+	Type *t;
+
+	if(n->orig != N)
+		n = n->orig;
+
+	switch(n->op) {
+	case OADD:
+	case OADDSTR:
+	case OAND:
+	case OANDAND:
+	case OANDNOT:
+	case OCOM:
+	case ODIV:
+	case OEQ:
+	case OGE:
+	case OGT:
+	case OLE:
+	case OLSH:
+	case OLT:
+	case OMINUS:
+	case OMOD:
+	case OMUL:
+	case ONE:
+	case ONOT:
+	case OOR:
+	case OOROR:
+	case OPLUS:
+	case ORSH:
+	case OSUB:
+	case OXOR:
+	case OCONV:
+	case OIOTA:
+	case OCOMPLEX:
+	case OREAL:
+	case OIMAG:
+		if(isgoconst(n->left) && (n->right == N || isgoconst(n->right)))
+			return 1;
+		break;
+	
+	case OLEN:
+	case OCAP:
+		l = n->left;
+		if(isgoconst(l))
+			return 1;
+		// Special case: len/cap is constant when applied to array or
+		// pointer to array when the expression does not contain
+		// function calls or channel receive operations.
+		t = l->type;
+		if(t != T && isptr[t->etype])
+			t = t->type;
+		if(isfixedarray(t) && !hascallchan(l))
+			return 1;
+		break;
+
+	case OLITERAL:
+		if(n->val.ctype != CTNIL)
+			return 1;
+		break;
+
+	case ONAME:
+		l = n->sym->def;
+		if(l->op == OLITERAL && n->val.ctype != CTNIL)
+			return 1;
+		break;
+	
+	case ONONAME:
+		if(n->sym->def != N && n->sym->def->op == OIOTA)
+			return 1;
+		break;
+	
+	case OCALL:
+		// Only constant calls are unsafe.Alignof, Offsetof, and Sizeof.
+		l = n->left;
+		while(l->op == OPAREN)
+			l = l->left;
+		if(l->op != ONAME || l->sym->pkg != unsafepkg)
+			break;
+		if(strcmp(l->sym->name, "Alignof") == 0 ||
+		   strcmp(l->sym->name, "Offsetof") == 0 ||
+		   strcmp(l->sym->name, "Sizeof") == 0)
+			return 1;
+		break;		
+	}
+
+	//dump("nonconst", n);
+	return 0;
+}
+
+static int
+hascallchan(Node *n)
+{
+	NodeList *l;
+
+	if(n == N)
+		return 0;
+	switch(n->op) {
+	case OCALL:
+	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+	case ORECV:
+		return 1;
+	}
+	
+	if(hascallchan(n->left) ||
+	   hascallchan(n->right))
+		return 1;
+	
+	for(l=n->list; l; l=l->next)
+		if(hascallchan(l->n))
+			return 1;
+	for(l=n->rlist; l; l=l->next)
+		if(hascallchan(l->n))
+			return 1;
+
+	return 0;
+}
diff --git a/src/cmd/gc/cplx.c b/src/cmd/gc/cplx.c
index dea7bc3..e0127fc 100644
--- a/src/cmd/gc/cplx.c
+++ b/src/cmd/gc/cplx.c
@@ -271,7 +271,7 @@ complexgen(Node *n, Node *res)
 }
 
 void
-complexbool(int op, Node *nl, Node *nr, int true, Prog *to)
+complexbool(int op, Node *nl, Node *nr, int true, int likely, Prog *to)
 {
 	Node tnl, tnr;
 	Node n1, n2, n3, n4;
@@ -323,7 +323,7 @@ complexbool(int op, Node *nl, Node *nr, int true, Prog *to)
 	if(op == ONE)
 		true = !true;
 
-	bgen(&na, true, to);
+	bgen(&na, true, likely, to);
 }
 
 void
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 32f334b..aa2489d 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -150,16 +150,35 @@ testdclstack(void)
 void
 redeclare(Sym *s, char *where)
 {
-	if(s->lastlineno == 0)
-		yyerror("%S redeclared %s\n"
-			"\tprevious declaration during import",
-			s, where);
-	else
+	Strlit *pkgstr;
+	int line1, line2;
+
+	if(s->lastlineno == 0) {
+		pkgstr = s->origpkg ? s->origpkg->path : s->pkg->path;
 		yyerror("%S redeclared %s\n"
+			"\tprevious declaration during import \"%Z\"",
+			s, where, pkgstr);
+	} else {
+		line1 = parserline();
+		line2 = s->lastlineno;
+		
+		// When an import and a declaration collide in separate files,
+		// present the import as the "redeclared", because the declaration
+		// is visible where the import is, but not vice versa.
+		// See issue 4510.
+		if(s->def == N) {
+			line2 = line1;
+			line1 = s->lastlineno;
+		}
+
+		yyerrorl(line1, "%S redeclared %s\n"
 			"\tprevious declaration at %L",
-			s, where, s->lastlineno);
+			s, where, line2);
+	}
 }
 
+static int vargen;
+
 /*
  * declare individual names - var, typ, const
  */
@@ -168,7 +187,10 @@ declare(Node *n, int ctxt)
 {
 	Sym *s;
 	int gen;
-	static int typegen, vargen;
+	static int typegen;
+	
+	if(ctxt == PDISCARD)
+		return;
 
 	if(isblank(n))
 		return;
@@ -180,6 +202,9 @@ declare(Node *n, int ctxt)
 	if(importpkg == nil && !typecheckok && s->pkg != localpkg)
 		yyerror("cannot declare name %S", s);
 
+	if(ctxt == PEXTERN && strcmp(s->name, "init") == 0)
+		yyerror("cannot declare init - must be func", s);
+
 	gen = 0;
 	if(ctxt == PEXTERN) {
 		externdcl = list(externdcl, n);
@@ -192,7 +217,7 @@ declare(Node *n, int ctxt)
 			curfn->dcl = list(curfn->dcl, n);
 		if(n->op == OTYPE)
 			gen = ++typegen;
-		else if(n->op == ONAME)
+		else if(n->op == ONAME && ctxt == PAUTO && strstr(s->name, "·") == nil)
 			gen = ++vargen;
 		pushdcl(s);
 		n->curfn = curfn;
@@ -237,7 +262,7 @@ variter(NodeList *vl, Node *t, NodeList *el)
 
 	init = nil;
 	doexpr = el != nil;
-	
+
 	if(count(el) == 1 && count(vl) > 1) {
 		e = el->n;
 		as2 = nod(OAS2, N, N);
@@ -464,7 +489,7 @@ colasdefn(NodeList *left, Node *defn)
 		if(isblank(n))
 			continue;
 		if(!colasname(n)) {
-			yyerror("non-name %N on left side of :=", n);
+			yyerrorl(defn->lineno, "non-name %N on left side of :=", n);
 			nerr++;
 			continue;
 		}
@@ -479,11 +504,11 @@ colasdefn(NodeList *left, Node *defn)
 		l->n = n;
 	}
 	if(nnew == 0 && nerr == 0)
-		yyerror("no new variables on left side of :=");
+		yyerrorl(defn->lineno, "no new variables on left side of :=");
 }
 
 Node*
-colas(NodeList *left, NodeList *right)
+colas(NodeList *left, NodeList *right, int32 lno)
 {
 	Node *as;
 
@@ -491,6 +516,7 @@ colas(NodeList *left, NodeList *right)
 	as->list = left;
 	as->rlist = right;
 	as->colas = 1;
+	as->lineno = lno;
 	colasdefn(left, as);
 
 	// make the tree prettier; not necessary
@@ -515,7 +541,7 @@ ifacedcl(Node *n)
 	if(n->op != ODCLFIELD || n->right == N)
 		fatal("ifacedcl");
 
-	dclcontext = PAUTO;
+	dclcontext = PPARAM;
 	markdcl();
 	funcdepth++;
 	n->outer = curfn;
@@ -526,6 +552,7 @@ ifacedcl(Node *n)
 	// seen the body of a function but since an interface
 	// field declaration does not have a body, we must
 	// call it now to pop the current declaration context.
+	dclcontext = PAUTO;
 	funcbody(n);
 }
 
@@ -567,6 +594,11 @@ funcargs(Node *nt)
 	if(nt->op != OTFUNC)
 		fatal("funcargs %O", nt->op);
 
+	// re-start the variable generation number
+	// we want to use small numbers for the return variables,
+	// so let them have the chunk starting at 1.
+	vargen = count(nt->rlist);
+
 	// declare the receiver and in arguments.
 	// no n->defn because type checking of func header
 	// will not fill in the types until later
@@ -578,6 +610,8 @@ funcargs(Node *nt)
 			n->left->op = ONAME;
 			n->left->ntype = n->right;
 			declare(n->left, PPARAM);
+			if(dclcontext == PAUTO)
+				n->left->vargen = ++vargen;
 		}
 	}
 	for(l=nt->list; l; l=l->next) {
@@ -588,29 +622,44 @@ funcargs(Node *nt)
 			n->left->op = ONAME;
 			n->left->ntype = n->right;
 			declare(n->left, PPARAM);
+			if(dclcontext == PAUTO)
+				n->left->vargen = ++vargen;
 		}
 	}
 
 	// declare the out arguments.
-	gen = 0;
+	gen = count(nt->list);
+	int i = 0;
 	for(l=nt->rlist; l; l=l->next) {
 		n = l->n;
+
 		if(n->op != ODCLFIELD)
 			fatal("funcargs out %O", n->op);
-		if(n->left != N) {
-			n->left->op = ONAME;
-			n->left->ntype = n->right;
-			if(isblank(n->left)) {
-				// Give it a name so we can assign to it during return.
-				// preserve the original in ->orig
-				nn = nod(OXXX, N, N);
-				*nn = *n->left;
-				n->left = nn;
-				snprint(namebuf, sizeof(namebuf), ".anon%d", gen++);
-				n->left->sym = lookup(namebuf);
-			}
-			declare(n->left, PPARAMOUT);
+
+		if(n->left == N) {
+			// give it a name so escape analysis has nodes to work with
+			snprint(namebuf, sizeof(namebuf), "~anon%d", gen++);
+			n->left = newname(lookup(namebuf));
+			// TODO: n->left->missing = 1;
+		} 
+
+		n->left->op = ONAME;
+
+		if(isblank(n->left)) {
+			// Give it a name so we can assign to it during return.
+			// preserve the original in ->orig
+			nn = nod(OXXX, N, N);
+			*nn = *n->left;
+			n->left = nn;
+			
+			snprint(namebuf, sizeof(namebuf), "~anon%d", gen++);
+			n->left->sym = lookup(namebuf);
 		}
+
+		n->left->ntype = n->right;
+		declare(n->left, PPARAMOUT);
+		if(dclcontext == PAUTO)
+			n->left->vargen = ++i;
 	}
 }
 
@@ -978,8 +1027,11 @@ embedded(Sym *s)
 		*utfrune(name, CenterDot) = 0;
 	}
 
-	if(exportname(name) || s->pkg == builtinpkg)  // old behaviour, tests pass, but is it correct?
+	if(exportname(name))
 		n = newname(lookup(name));
+	else if(s->pkg == builtinpkg && importpkg != nil)
+		// The name of embedded builtins during imports belongs to importpkg.
+		n = newname(pkglookup(name, importpkg));
 	else
 		n = newname(pkglookup(name, s->pkg));
 	n = nod(ODCLFIELD, n, oldname(s));
@@ -1124,6 +1176,7 @@ functype(Node *this, NodeList *in, NodeList *out)
 {
 	Type *t;
 	NodeList *rcvr;
+	Sym *s;
 
 	t = typ(TFUNC);
 
@@ -1141,7 +1194,12 @@ functype(Node *this, NodeList *in, NodeList *out)
 		t->thistuple = 1;
 	t->outtuple = count(out);
 	t->intuple = count(in);
-	t->outnamed = t->outtuple > 0 && out->n->left != N;
+	t->outnamed = 0;
+	if(t->outtuple > 0 && out->n->left != N && out->n->left->orig != N) {
+		s = out->n->left->orig->sym;
+		if(s != S && s->name[0] != '~')
+			t->outnamed = 1;
+	}
 
 	return t;
 }
@@ -1249,7 +1307,7 @@ methodname1(Node *n, Node *t)
  * n is fieldname, pa is base type, t is function type
  */
 void
-addmethod(Sym *sf, Type *t, int local)
+addmethod(Sym *sf, Type *t, int local, int nointerface)
 {
 	Type *f, *d, *pa;
 	Node *n;
@@ -1332,6 +1390,7 @@ addmethod(Sym *sf, Type *t, int local)
 	}
 
 	f = structfield(n);
+	f->nointerface = nointerface;
 
 	// during import unexported method names should be in the type's package
 	if(importpkg && f->sym && !exportname(f->sym->name) && f->sym->pkg != structpkg)
@@ -1382,3 +1441,20 @@ funccompile(Node *n, int isclosure)
 	funcdepth = 0;
 	dclcontext = PEXTERN;
 }
+
+Sym*
+funcsym(Sym *s)
+{
+	char *p;
+	Sym *s1;
+	
+	p = smprint("%s·f", s->name);
+	s1 = pkglookup(p, s->pkg);
+	free(p);
+	if(s1->def == N) {
+		s1->def = newname(s1);
+		s1->def->shortname = newname(s);
+		funcsyms = list(funcsyms, s1->def);
+	}
+	return s1;
+}
diff --git a/src/cmd/gc/doc.go b/src/cmd/gc/doc.go
index 8d8f896..7919677 100644
--- a/src/cmd/gc/doc.go
+++ b/src/cmd/gc/doc.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 ignore
+
 /*
 
 Gc is the generic label for the family of Go compilers
@@ -25,6 +27,8 @@ other packages. It is therefore not necessary when compiling client C of
 package P to read the files of P's dependencies, only the compiled output
 of P.
 
+Command Line
+
 Usage:
 	go tool 6g [flags] file...
 The specified files must be Go source files and all part of the same package.
@@ -48,15 +52,40 @@ Flags:
 		disable optimizations
 	-S
 		write assembly language text to standard output (code only)
-	-SS
+	-S -S
 		write assembly language text to standard output (code and data)
 	-u
 		disallow importing packages not marked as safe
 	-V
 		print the compiler version
+	-race
+		compile with race detection enabled
 
 There are also a number of debugging flags; run the command with no arguments
 to get a usage message.
 
+Compiler Directives
+
+The compiler accepts two compiler directives in the form of // comments at the
+beginning of a line. To distinguish them from non-directive comments, the directives
+require no space between the slashes and the name of the directive. However, since
+they are comments, tools unaware of the directive convention or of a particular
+directive can skip over a directive like any other comment.
+
+    //line path/to/file:linenumber
+
+The //line directive specifies that the source line that follows should be recorded
+as having come from the given file path and line number. Successive lines are
+recorded using increasing line numbers, until the next directive. This directive
+typically appears in machine-generated code, so that compilers and debuggers
+will show lines in the original input to the generator.
+
+    //go:noescape
+
+The //go:noescape directive specifies that the next declaration in the file, which
+must be a func without a body (meaning that it has an implementation not written
+in Go) does not allow any of the pointers passed as arguments to escape into the
+heap or into the values returned from the function. This information can be used as
+during the compiler's escape analysis of Go code calling the function.
 */
-package documentation
+package main
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
index 8a265ce..46c06d1 100644
--- a/src/cmd/gc/esc.c
+++ b/src/cmd/gc/esc.c
@@ -1,8 +1,162 @@
 // 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.
-//
+
 // Escape analysis.
+
+#include <u.h>
+#include <libc.h>
+#include "go.h"
+
+// Run analysis on minimal sets of mutually recursive functions
+// or single non-recursive functions, bottom up.
+//
+// Finding these sets is finding strongly connected components
+// in the static call graph.  The algorithm for doing that is taken
+// from Sedgewick, Algorithms, Second Edition, p. 482, with two
+// adaptations.
+//
+// First, a hidden closure function (n->curfn != N) cannot be the
+// root of a connected component. Refusing to use it as a root
+// forces it into the component of the function in which it appears.
+// The analysis assumes that closures and the functions in which they
+// appear are analyzed together, so that the aliasing between their
+// variables can be modeled more precisely.
+//
+// Second, each function becomes two virtual nodes in the graph,
+// with numbers n and n+1. We record the function's node number as n
+// but search from node n+1. If the search tells us that the component
+// number (min) is n+1, we know that this is a trivial component: one function
+// plus its closures. If the search tells us that the component number is
+// n, then there was a path from node n+1 back to node n, meaning that
+// the function set is mutually recursive. The escape analysis can be
+// more precise when analyzing a single non-recursive function than
+// when analyzing a set of mutually recursive functions.
+
+static NodeList *stack;
+static uint32 visitgen;
+static uint32 visit(Node*);
+static uint32 visitcode(Node*, uint32);
+static uint32 visitcodelist(NodeList*, uint32);
+
+static void analyze(NodeList*, int);
+
+enum
+{
+	EscFuncUnknown = 0,
+	EscFuncPlanned,
+	EscFuncStarted,
+	EscFuncTagged,
+};
+
+void
+escapes(NodeList *all)
+{
+	NodeList *l;
+
+	for(l=all; l; l=l->next)
+		l->n->walkgen = 0;
+
+	visitgen = 0;
+	for(l=all; l; l=l->next)
+		if(l->n->op == ODCLFUNC && l->n->curfn == N)
+			visit(l->n);
+
+	for(l=all; l; l=l->next)
+		l->n->walkgen = 0;
+}
+
+static uint32
+visit(Node *n)
+{
+	uint32 min, recursive;
+	NodeList *l, *block;
+
+	if(n->walkgen > 0) {
+		// already visited
+		return n->walkgen;
+	}
+	
+	visitgen++;
+	n->walkgen = visitgen;
+	visitgen++;
+	min = visitgen;
+
+	l = mal(sizeof *l);
+	l->next = stack;
+	l->n = n;
+	stack = l;
+	min = visitcodelist(n->nbody, min);
+	if((min == n->walkgen || min == n->walkgen+1) && n->curfn == N) {
+		// This node is the root of a strongly connected component.
+
+		// The original min passed to visitcodelist was n->walkgen+1.
+		// If visitcodelist found its way back to n->walkgen, then this
+		// block is a set of mutually recursive functions.
+		// Otherwise it's just a lone function that does not recurse.
+		recursive = min == n->walkgen;
+
+		// Remove connected component from stack.
+		// Mark walkgen so that future visits return a large number
+		// so as not to affect the caller's min.
+		block = stack;
+		for(l=stack; l->n != n; l=l->next)
+			l->n->walkgen = (uint32)~0U;
+		n->walkgen = (uint32)~0U;
+		stack = l->next;
+		l->next = nil;
+
+		// Run escape analysis on this set of functions.
+		analyze(block, recursive);
+	}
+
+	return min;
+}
+
+static uint32
+visitcodelist(NodeList *l, uint32 min)
+{
+	for(; l; l=l->next)
+		min = visitcode(l->n, min);
+	return min;
+}
+
+static uint32
+visitcode(Node *n, uint32 min)
+{
+	Node *fn;
+	uint32 m;
+
+	if(n == N)
+		return min;
+
+	min = visitcodelist(n->ninit, min);
+	min = visitcode(n->left, min);
+	min = visitcode(n->right, min);
+	min = visitcodelist(n->list, min);
+	min = visitcode(n->ntest, min);
+	min = visitcode(n->nincr, min);
+	min = visitcodelist(n->nbody, min);
+	min = visitcodelist(n->nelse, min);
+	min = visitcodelist(n->rlist, min);
+	
+	if(n->op == OCALLFUNC || n->op == OCALLMETH) {
+		fn = n->left;
+		if(n->op == OCALLMETH)
+			fn = n->left->right->sym->def;
+		if(fn && fn->op == ONAME && fn->class == PFUNC && fn->defn && fn->defn->nbody)
+			if((m = visit(fn->defn)) < min)
+				min = m;
+	}
+	
+	if(n->op == OCLOSURE)
+		if((m = visit(n->closure)) < min)
+			min = m;
+
+	return min;
+}
+
+// An escape analysis pass for a set of functions.
 //
 // First escfunc, esc and escassign recurse over the ast of each
 // function to dig out flow(dst,src) edges between any
@@ -22,75 +176,123 @@
 // not escape, then new(T) can be rewritten into a stack allocation.
 // The same is true of slice literals.
 //
-// If escape analysis is disabled (-s), this code is not used.
+// If optimizations are disabled (-N), this code is not used.
 // Instead, the compiler assumes that any value whose address
 // is taken without being immediately dereferenced
 // needs to be moved to the heap, and new(T) and slice
 // literals are always real allocations.
 
-#include <u.h>
-#include <libc.h>
-#include "go.h"
+typedef struct EscState EscState;
+
+static void escfunc(EscState*, Node *func);
+static void esclist(EscState*, NodeList *l);
+static void esc(EscState*, Node *n);
+static void escloopdepthlist(EscState*, NodeList *l);
+static void escloopdepth(EscState*, Node *n);
+static void escassign(EscState*, Node *dst, Node *src);
+static void esccall(EscState*, Node*);
+static void escflows(EscState*, Node *dst, Node *src);
+static void escflood(EscState*, Node *dst);
+static void escwalk(EscState*, int level, Node *dst, Node *src);
+static void esctag(EscState*, Node *func);
+
+struct EscState {
+	// Fake node that all
+	//   - return values and output variables
+	//   - parameters on imported functions not marked 'safe'
+	//   - assignments to global variables
+	// flow to.
+	Node	theSink;
+	
+	NodeList*	dsts;		// all dst nodes
+	int	loopdepth;	// for detecting nested loop scopes
+	int	pdepth;		// for debug printing in recursions.
+	int	dstcount, edgecount;	// diagnostic
+	NodeList*	noesc;	// list of possible non-escaping nodes, for printing
+	int	recursive;	// recursive function or group of mutually recursive functions.
+};
+
+static Strlit *tags[16];
+
+static Strlit*
+mktag(int mask)
+{
+	Strlit *s;
+	char buf[40];
+
+	switch(mask&EscMask) {
+	case EscNone:
+	case EscReturn:
+		break;
+	default:
+		fatal("escape mktag");
+	}
 
-static void escfunc(Node *func);
-static void esclist(NodeList *l);
-static void esc(Node *n);
-static void escloopdepthlist(NodeList *l);
-static void escloopdepth(Node *n);
-static void escassign(Node *dst, Node *src);
-static void esccall(Node*);
-static void escflows(Node *dst, Node *src);
-static void escflood(Node *dst);
-static void escwalk(int level, Node *dst, Node *src);
-static void esctag(Node *func);
-
-// Fake node that all
-//   - return values and output variables
-//   - parameters on imported functions not marked 'safe'
-//   - assignments to global variables
-// flow to.
-static Node	theSink;
-
-static NodeList*	dsts;		// all dst nodes
-static int	loopdepth;	// for detecting nested loop scopes
-static int	pdepth;		// for debug printing in recursions.
-static Strlit*	safetag;	// gets slapped on safe parameters' field types for export
-static int	dstcount, edgecount;	// diagnostic
-static NodeList*	noesc;	// list of possible non-escaping nodes, for printing
+	mask >>= EscBits;
 
-void
-escapes(NodeList *all)
+	if(mask < nelem(tags) && tags[mask] != nil)
+		return tags[mask];
+
+	snprint(buf, sizeof buf, "esc:0x%x", mask);
+	s = strlit(buf);
+	if(mask < nelem(tags))
+		tags[mask] = s;
+	return s;
+}
+
+static int
+parsetag(Strlit *note)
 {
-	NodeList *l;
+	int em;
+
+	if(note == nil)
+		return EscUnknown;
+	if(strncmp(note->s, "esc:", 4) != 0)
+		return EscUnknown;
+	em = atoi(note->s + 4);
+	if (em == 0)
+		return EscNone;
+	return EscReturn | (em << EscBits);
+}
 
-	theSink.op = ONAME;
-	theSink.orig = &theSink;
-	theSink.class = PEXTERN;
-	theSink.sym = lookup(".sink");
-	theSink.escloopdepth = -1;
+static void
+analyze(NodeList *all, int recursive)
+{
+	NodeList *l;
+	EscState es, *e;
+	
+	memset(&es, 0, sizeof es);
+	e = &es;
+	e->theSink.op = ONAME;
+	e->theSink.orig = &e->theSink;
+	e->theSink.class = PEXTERN;
+	e->theSink.sym = lookup(".sink");
+	e->theSink.escloopdepth = -1;
+	e->recursive = recursive;
 
-	safetag = strlit("noescape");
-	noesc = nil;
+	for(l=all; l; l=l->next)
+		if(l->n->op == ODCLFUNC)
+			l->n->esc = EscFuncPlanned;
 
 	// flow-analyze functions
 	for(l=all; l; l=l->next)
-		if(l->n->op == ODCLFUNC || l->n->op == OCLOSURE)
-			escfunc(l->n);
+		if(l->n->op == ODCLFUNC)
+			escfunc(e, l->n);
 
-	// print("escapes: %d dsts, %d edges\n", dstcount, edgecount);
+	// print("escapes: %d e->dsts, %d edges\n", e->dstcount, e->edgecount);
 
-	// visit the updstream of each dst, mark address nodes with
+	// visit the upstream of each dst, mark address nodes with
 	// addrescapes, mark parameters unsafe
-	for(l = dsts; l; l=l->next)
-		escflood(l->n);
+	for(l = e->dsts; l; l=l->next)
+		escflood(e, l->n);
 
 	// for all top level functions, tag the typenodes corresponding to the param nodes
 	for(l=all; l; l=l->next)
 		if(l->n->op == ODCLFUNC)
-			esctag(l->n);
+			esctag(e, l->n);
 
 	if(debug['m']) {
-		for(l=noesc; l; l=l->next)
+		for(l=e->noesc; l; l=l->next)
 			if(l->n->esc == EscNone)
 				warnl(l->n->lineno, "%S %hN does not escape",
 					(l->n->curfn && l->n->curfn->nname) ? l->n->curfn->nname->sym : S,
@@ -100,14 +302,20 @@ escapes(NodeList *all)
 
 
 static void
-escfunc(Node *func)
+escfunc(EscState *e, Node *func)
 {
-	Node *savefn, *n;
+	Node *savefn;
 	NodeList *ll;
 	int saveld;
 
-	saveld = loopdepth;
-	loopdepth = 1;
+//	print("escfunc %N %s\n", func->nname, e->recursive?"(recursive)":"");
+
+	if(func->esc != 1)
+		fatal("repeat escfunc %N", func->nname);
+	func->esc = EscFuncStarted;
+
+	saveld = e->loopdepth;
+	e->loopdepth = 1;
 	savefn = curfn;
 	curfn = func;
 
@@ -116,63 +324,54 @@ escfunc(Node *func)
 			continue;
 		switch (ll->n->class) {
 		case PPARAMOUT:
-			// output parameters flow to the sink
-			escflows(&theSink, ll->n);
-			ll->n->escloopdepth = loopdepth;
+			// out params are in a loopdepth between the sink and all local variables
+			ll->n->escloopdepth = 0;
 			break;
 		case PPARAM:
 			if(ll->n->type && !haspointers(ll->n->type))
 				break;
-			ll->n->esc = EscNone;	// prime for escflood later
-			noesc = list(noesc, ll->n);
-			ll->n->escloopdepth = loopdepth;
+			if(curfn->nbody == nil && !curfn->noescape)
+				ll->n->esc = EscHeap;
+			else
+				ll->n->esc = EscNone;	// prime for escflood later
+			e->noesc = list(e->noesc, ll->n);
+			ll->n->escloopdepth = 1; 
 			break;
 		}
 	}
 
-	// walk will take the address of cvar->closure later and assign it to cvar.
-	// linking a fake oaddr node directly to the closure handles the case
-	// of the closure itself leaking.  Following the flow of the value to th
-	// paramref is done in escflow, because if we did that here, it would look
-	// like the original is assigned out of its loop depth, whereas it's just
-	// assigned to something in an inner function.  A paramref itself is never
-	// moved to the heap, only its original.
-	for(ll=curfn->cvars; ll; ll=ll->next) {
-		if(ll->n->op == OXXX)  // see dcl.c:398
-			continue;
-
-		n = nod(OADDR, ll->n->closure, N);
-		n->lineno = ll->n->lineno;
-		typecheck(&n, Erv);
-		escassign(curfn, n);
-	}
+	// in a mutually recursive group we lose track of the return values
+	if(e->recursive)
+		for(ll=curfn->dcl; ll; ll=ll->next)
+			if(ll->n->op == ONAME && ll->n->class == PPARAMOUT)
+				escflows(e, &e->theSink, ll->n);
 
-	escloopdepthlist(curfn->nbody);
-	esclist(curfn->nbody);
+	escloopdepthlist(e, curfn->nbody);
+	esclist(e, curfn->nbody);
 	curfn = savefn;
-	loopdepth = saveld;
+	e->loopdepth = saveld;
 }
 
-// Mark labels that have no backjumps to them as not increasing loopdepth.
+// Mark labels that have no backjumps to them as not increasing e->loopdepth.
 // Walk hasn't generated (goto|label)->left->sym->label yet, so we'll cheat
 // and set it to one of the following two.  Then in esc we'll clear it again.
 static Label looping;
 static Label nonlooping;
 
 static void
-escloopdepthlist(NodeList *l)
+escloopdepthlist(EscState *e, NodeList *l)
 {
 	for(; l; l=l->next)
-		escloopdepth(l->n);
+		escloopdepth(e, l->n);
 }
 
 static void
-escloopdepth(Node *n)
+escloopdepth(EscState *e, Node *n)
 {
 	if(n == N)
 		return;
 
-	escloopdepthlist(n->ninit);
+	escloopdepthlist(e, n->ninit);
 
 	switch(n->op) {
 	case OLABEL:
@@ -194,29 +393,30 @@ escloopdepth(Node *n)
 		break;
 	}
 
-	escloopdepth(n->left);
-	escloopdepth(n->right);
-	escloopdepthlist(n->list);
-	escloopdepth(n->ntest);
-	escloopdepth(n->nincr);
-	escloopdepthlist(n->nbody);
-	escloopdepthlist(n->nelse);
-	escloopdepthlist(n->rlist);
+	escloopdepth(e, n->left);
+	escloopdepth(e, n->right);
+	escloopdepthlist(e, n->list);
+	escloopdepth(e, n->ntest);
+	escloopdepth(e, n->nincr);
+	escloopdepthlist(e, n->nbody);
+	escloopdepthlist(e, n->nelse);
+	escloopdepthlist(e, n->rlist);
 
 }
 
 static void
-esclist(NodeList *l)
+esclist(EscState *e, NodeList *l)
 {
 	for(; l; l=l->next)
-		esc(l->n);
+		esc(e, l->n);
 }
 
 static void
-esc(Node *n)
+esc(EscState *e, Node *n)
 {
 	int lno;
 	NodeList *ll, *lr;
+	Node *a;
 
 	if(n == N)
 		return;
@@ -224,33 +424,30 @@ esc(Node *n)
 	lno = setlineno(n);
 
 	if(n->op == OFOR || n->op == ORANGE)
-		loopdepth++;
-
-	if(n->op == OCLOSURE) {
-		escfunc(n);
-	} else {
-		esc(n->left);
-		esc(n->right);
-		esc(n->ntest);
-		esc(n->nincr);
-		esclist(n->ninit);
-		esclist(n->nbody);
-		esclist(n->nelse);
-		esclist(n->list);
-		esclist(n->rlist);
-	}
+		e->loopdepth++;
+
+	esc(e, n->left);
+	esc(e, n->right);
+	esc(e, n->ntest);
+	esc(e, n->nincr);
+	esclist(e, n->ninit);
+	esclist(e, n->nbody);
+	esclist(e, n->nelse);
+	esclist(e, n->list);
+	esclist(e, n->rlist);
+
 	if(n->op == OFOR || n->op == ORANGE)
-		loopdepth--;
+		e->loopdepth--;
 
 	if(debug['m'] > 1)
-		print("%L:[%d] %S esc: %N\n", lineno, loopdepth,
+		print("%L:[%d] %S esc: %N\n", lineno, e->loopdepth,
 		      (curfn && curfn->nname) ? curfn->nname->sym : S, n);
 
 	switch(n->op) {
 	case ODCL:
 		// Record loop depth at declaration.
 		if(n->left)
-			n->left->escloopdepth = loopdepth;
+			n->left->escloopdepth = e->loopdepth;
 		break;
 
 	case OLABEL:
@@ -260,18 +457,19 @@ esc(Node *n)
 		} else if(n->left->sym->label == &looping) {
 			if(debug['m'] > 1)
 				print("%L: %N looping label\n", lineno, n);
-			loopdepth++;
+			e->loopdepth++;
 		}
 		// See case OLABEL in escloopdepth above
 		// else if(n->left->sym->label == nil)
-		//	fatal("escape anaylysis missed or messed up a label: %+N", n);
+		//	fatal("escape analysis missed or messed up a label: %+N", n);
 
 		n->left->sym->label = nil;
+		break;
 
 	case ORANGE:
 		// Everything but fixed array is a dereference.
 		if(isfixedarray(n->type) && n->list->next)
-			escassign(n->list->next->n, n->right);
+			escassign(e, n->list->next->n, n->right);
 		break;
 
 	case OSWITCH:
@@ -279,123 +477,157 @@ esc(Node *n)
 			for(ll=n->list; ll; ll=ll->next) {  // cases
 				// ntest->right is the argument of the .(type),
 				// ll->n->nname is the variable per case
-				escassign(ll->n->nname, n->ntest->right);
+				escassign(e, ll->n->nname, n->ntest->right);
 			}
 		}
 		break;
 
 	case OAS:
 	case OASOP:
-		escassign(n->left, n->right);
+		escassign(e, n->left, n->right);
 		break;
 
 	case OAS2:	// x,y = a,b
 		if(count(n->list) == count(n->rlist))
 			for(ll=n->list, lr=n->rlist; ll; ll=ll->next, lr=lr->next)
-				escassign(ll->n, lr->n);
+				escassign(e, ll->n, lr->n);
 		break;
 
 	case OAS2RECV:		// v, ok = <-ch
 	case OAS2MAPR:		// v, ok = m[k]
 	case OAS2DOTTYPE:	// v, ok = x.(type)
-		escassign(n->list->n, n->rlist->n);
+		escassign(e, n->list->n, n->rlist->n);
 		break;
 
 	case OSEND:		// ch <- x
-		escassign(&theSink, n->right);
+		escassign(e, &e->theSink, n->right);
 		break;
 
 	case ODEFER:
-		if(loopdepth == 1)  // top level
+		if(e->loopdepth == 1)  // top level
 			break;
 		// arguments leak out of scope
 		// TODO: leak to a dummy node instead
 		// fallthrough
 	case OPROC:
 		// go f(x) - f and x escape
-		escassign(&theSink, n->left->left);
-		escassign(&theSink, n->left->right);  // ODDDARG for call
+		escassign(e, &e->theSink, n->left->left);
+		escassign(e, &e->theSink, n->left->right);  // ODDDARG for call
 		for(ll=n->left->list; ll; ll=ll->next)
-			escassign(&theSink, ll->n);
+			escassign(e, &e->theSink, ll->n);
+		break;
+
+	case OCALLMETH:
+	case OCALLFUNC:
+	case OCALLINTER:
+		esccall(e, n);
+		break;
+
+	case OAS2FUNC:	// x,y = f()
+		// esccall already done on n->rlist->n. tie it's escretval to n->list
+		lr=n->rlist->n->escretval;
+		for(ll=n->list; lr && ll; lr=lr->next, ll=ll->next)
+			escassign(e, ll->n, lr->n);
+		if(lr || ll)
+			fatal("esc oas2func");
 		break;
 
 	case ORETURN:
-		for(ll=n->list; ll; ll=ll->next)
-			escassign(&theSink, ll->n);
+		ll=n->list;
+		if(count(n->list) == 1 && curfn->type->outtuple > 1) {
+			// OAS2FUNC in disguise
+			// esccall already done on n->list->n
+			// tie n->list->n->escretval to curfn->dcl PPARAMOUT's
+			ll = n->list->n->escretval;
+		}
+
+		for(lr = curfn->dcl; lr && ll; lr=lr->next) {
+			if (lr->n->op != ONAME || lr->n->class != PPARAMOUT)
+				continue;
+			escassign(e, lr->n, ll->n);
+			ll = ll->next;
+		}
+		if (ll != nil)
+			fatal("esc return list");
 		break;
 
 	case OPANIC:
 		// Argument could leak through recover.
-		escassign(&theSink, n->left);
+		escassign(e, &e->theSink, n->left);
 		break;
 
 	case OAPPEND:
 		if(!n->isddd)
 			for(ll=n->list->next; ll; ll=ll->next)
-				escassign(&theSink, ll->n);  // lose track of assign to dereference
-		break;
-
-	case OCALLMETH:
-	case OCALLFUNC:
-	case OCALLINTER:
-		esccall(n);
+				escassign(e, &e->theSink, ll->n);  // lose track of assign to dereference
 		break;
 
 	case OCONV:
 	case OCONVNOP:
 	case OCONVIFACE:
-		escassign(n, n->left);
+		escassign(e, n, n->left);
 		break;
 
 	case OARRAYLIT:
 		if(isslice(n->type)) {
 			n->esc = EscNone;  // until proven otherwise
-			noesc = list(noesc, n);
-			n->escloopdepth = loopdepth;
+			e->noesc = list(e->noesc, n);
+			n->escloopdepth = e->loopdepth;
 			// Values make it to memory, lose track.
 			for(ll=n->list; ll; ll=ll->next)
-				escassign(&theSink, ll->n->right);
+				escassign(e, &e->theSink, ll->n->right);
 		} else {
 			// Link values to array.
 			for(ll=n->list; ll; ll=ll->next)
-				escassign(n, ll->n->right);
+				escassign(e, n, ll->n->right);
 		}
 		break;
 
 	case OSTRUCTLIT:
 		// Link values to struct.
 		for(ll=n->list; ll; ll=ll->next)
-			escassign(n, ll->n->right);
+			escassign(e, n, ll->n->right);
 		break;
 	
 	case OPTRLIT:
 		n->esc = EscNone;  // until proven otherwise
-		noesc = list(noesc, n);
-		n->escloopdepth = loopdepth;
+		e->noesc = list(e->noesc, n);
+		n->escloopdepth = e->loopdepth;
 		// Contents make it to memory, lose track.
-		escassign(&theSink, n->left);
+		escassign(e, &e->theSink, n->left);
 		break;
 
 	case OMAPLIT:
 		n->esc = EscNone;  // until proven otherwise
-		noesc = list(noesc, n);
-		n->escloopdepth = loopdepth;
+		e->noesc = list(e->noesc, n);
+		n->escloopdepth = e->loopdepth;
 		// Keys and values make it to memory, lose track.
 		for(ll=n->list; ll; ll=ll->next) {
-			escassign(&theSink, ll->n->left);
-			escassign(&theSink, ll->n->right);
+			escassign(e, &e->theSink, ll->n->left);
+			escassign(e, &e->theSink, ll->n->right);
 		}
 		break;
 	
 	case OCLOSURE:
+		// Link addresses of captured variables to closure.
+		for(ll=n->cvars; ll; ll=ll->next) {
+			if(ll->n->op == OXXX)  // unnamed out argument; see dcl.c:/^funcargs
+				continue;
+			a = nod(OADDR, ll->n->closure, N);
+			a->lineno = ll->n->lineno;
+			a->escloopdepth = e->loopdepth;
+			typecheck(&a, Erv);
+			escassign(e, n, a);
+		}
+		// fallthrough
 	case OADDR:
 	case OMAKECHAN:
 	case OMAKEMAP:
 	case OMAKESLICE:
 	case ONEW:
-		n->escloopdepth = loopdepth;
+		n->escloopdepth = e->loopdepth;
 		n->esc = EscNone;  // until proven otherwise
-		noesc = list(noesc, n);
+		e->noesc = list(e->noesc, n);
 		break;
 	}
 
@@ -407,21 +639,22 @@ esc(Node *n)
 // evaluated in curfn.	For expr==nil, dst must still be examined for
 // evaluations inside it (e.g *f(x) = y)
 static void
-escassign(Node *dst, Node *src)
+escassign(EscState *e, Node *dst, Node *src)
 {
 	int lno;
+	NodeList *ll;
 
 	if(isblank(dst) || dst == N || src == N || src->op == ONONAME || src->op == OXXX)
 		return;
 
 	if(debug['m'] > 1)
-		print("%L:[%d] %S escassign: %hN(%hJ) = %hN(%hJ)\n", lineno, loopdepth,
+		print("%L:[%d] %S escassign: %hN(%hJ) = %hN(%hJ)\n", lineno, e->loopdepth,
 		      (curfn && curfn->nname) ? curfn->nname->sym : S, dst, dst, src, src);
 
 	setlineno(dst);
 	
 	// Analyze lhs of assignment.
-	// Replace dst with theSink if we can't track it.
+	// Replace dst with e->theSink if we can't track it.
 	switch(dst->op) {
 	default:
 		dump("dst", dst);
@@ -438,31 +671,31 @@ escassign(Node *dst, Node *src)
 
 	case ONAME:
 		if(dst->class == PEXTERN)
-			dst = &theSink;
+			dst = &e->theSink;
 		break;
 	case ODOT:	      // treat "dst.x  = src" as "dst = src"
-		escassign(dst->left, src);
+		escassign(e, dst->left, src);
 		return;
 	case OINDEX:
 		if(isfixedarray(dst->left->type)) {
-			escassign(dst->left, src);
+			escassign(e, dst->left, src);
 			return;
 		}
-		dst = &theSink;  // lose track of dereference
+		dst = &e->theSink;  // lose track of dereference
 		break;
 	case OIND:
 	case ODOTPTR:
-		dst = &theSink;  // lose track of dereference
+		dst = &e->theSink;  // lose track of dereference
 		break;
 	case OINDEXMAP:
 		// lose track of key and value
-		escassign(&theSink, dst->right);
-		dst = &theSink;
+		escassign(e, &e->theSink, dst->right);
+		dst = &e->theSink;
 		break;
 	}
 
 	lno = setlineno(src);
-	pdepth++;
+	e->pdepth++;
 
 	switch(src->op) {
 	case OADDR:	// dst = &x
@@ -480,7 +713,16 @@ escassign(Node *dst, Node *src)
 	case OMAKESLICE:
 	case ONEW:
 	case OCLOSURE:
-		escflows(dst, src);
+		escflows(e, dst, src);
+		break;
+
+	case OCALLMETH:
+	case OCALLFUNC:
+	case OCALLINTER:
+		// Flowing multiple returns to a single dst happens when
+		// analyzing "go f(g())": here g() flows to sink (issue 4529).
+		for(ll=src->escretval; ll; ll=ll->next)
+			escflows(e, dst, ll->n);
 		break;
 
 	case ODOT:
@@ -498,18 +740,18 @@ escassign(Node *dst, Node *src)
 	case OSLICE:
 	case OSLICEARR:
 		// Conversions, field access, slice all preserve the input value.
-		escassign(dst, src->left);
+		escassign(e, dst, src->left);
 		break;
 
 	case OAPPEND:
 		// Append returns first argument.
-		escassign(dst, src->list->n);
+		escassign(e, dst, src->list->n);
 		break;
 	
 	case OINDEX:
 		// Index of array preserves input value.
 		if(isfixedarray(src->left->type))
-			escassign(dst, src->left);
+			escassign(e, dst, src->left);
 		break;
 
 	case OADD:
@@ -529,29 +771,49 @@ escassign(Node *dst, Node *src)
 		// Might be pointer arithmetic, in which case
 		// the operands flow into the result.
 		// TODO(rsc): Decide what the story is here.  This is unsettling.
-		escassign(dst, src->left);
-		escassign(dst, src->right);
+		escassign(e, dst, src->left);
+		escassign(e, dst, src->right);
 		break;
-
 	}
 
-	pdepth--;
+	e->pdepth--;
 	lineno = lno;
 }
 
+static void
+escassignfromtag(EscState *e, Strlit *note, NodeList *dsts, Node *src)
+{
+	int em;
+	
+	em = parsetag(note);
+	
+	if(em == EscUnknown) {
+		escassign(e, &e->theSink, src);
+		return;
+	}
+		
+	for(em >>= EscBits; em && dsts; em >>= 1, dsts=dsts->next)
+		if(em & 1)
+			escassign(e, dsts->n, src);
+
+	if (em != 0 && dsts == nil)
+		fatal("corrupt esc tag %Z or messed up escretval list\n", note);
+}
 
-// This is a bit messier than fortunate, pulled out of escassign's big
+// This is a bit messier than fortunate, pulled out of esc's big
 // switch for clarity.	We either have the paramnodes, which may be
-// connected to other things throug flows or we have the parameter type
+// connected to other things through flows or we have the parameter type
 // nodes, which may be marked "noescape". Navigating the ast is slightly
 // different for methods vs plain functions and for imported vs
 // this-package
 static void
-esccall(Node *n)
+esccall(EscState *e, Node *n)
 {
 	NodeList *ll, *lr;
 	Node *a, *fn, *src;
 	Type *t, *fntype;
+	char buf[40];
+	int i;
 
 	fn = N;
 	switch(n->op) {
@@ -579,74 +841,96 @@ esccall(Node *n)
 	ll = n->list;
 	if(n->list != nil && n->list->next == nil) {
 		a = n->list->n;
-		if(a->type->etype == TSTRUCT && a->type->funarg) {
-			// f(g()).
-			// Since f's arguments are g's results and
-			// all function results escape, we're done.
-			ll = nil;
-		}
+		if(a->type->etype == TSTRUCT && a->type->funarg) // f(g()).
+			ll = a->escretval;
 	}
 			
-	if(fn && fn->op == ONAME && fn->class == PFUNC && fn->defn && fn->defn->nbody && fn->ntype) {
-		// Local function.  Incorporate into flow graph.
+	if(fn && fn->op == ONAME && fn->class == PFUNC && fn->defn && fn->defn->nbody && fn->ntype && fn->defn->esc < EscFuncTagged) {
+		// function in same mutually recursive group.  Incorporate into flow graph.
+//		print("esc local fn: %N\n", fn->ntype);
+		if(fn->defn->esc == EscFuncUnknown || n->escretval != nil)
+			fatal("graph inconsistency");
+
+		// set up out list on this call node
+		for(lr=fn->ntype->rlist; lr; lr=lr->next)
+			n->escretval = list(n->escretval, lr->n->left);  // type.rlist ->  dclfield -> ONAME (PPARAMOUT)
 
 		// Receiver.
 		if(n->op != OCALLFUNC)
-			escassign(fn->ntype->left->left, n->left->left);
+			escassign(e, fn->ntype->left->left, n->left->left);
 
 		for(lr=fn->ntype->list; ll && lr; ll=ll->next, lr=lr->next) {
 			src = ll->n;
 			if(lr->n->isddd && !n->isddd) {
 				// Introduce ODDDARG node to represent ... allocation.
 				src = nod(ODDDARG, N, N);
-				src->escloopdepth = loopdepth;
+				src->escloopdepth = e->loopdepth;
 				src->lineno = n->lineno;
 				src->esc = EscNone;  // until we find otherwise
-				noesc = list(noesc, src);
+				e->noesc = list(e->noesc, src);
 				n->right = src;
 			}
 			if(lr->n->left != N)
-				escassign(lr->n->left, src);
+				escassign(e, lr->n->left, src);
 			if(src != ll->n)
 				break;
 		}
 		// "..." arguments are untracked
 		for(; ll; ll=ll->next)
-			escassign(&theSink, ll->n);
+			escassign(e, &e->theSink, ll->n);
+
 		return;
 	}
 
-	// Imported function.  Use the escape tags.
-	if(n->op != OCALLFUNC) {
-		t = getthisx(fntype)->type;
-		if(!t->note || strcmp(t->note->s, safetag->s) != 0)
-			escassign(&theSink, n->left->left);
+	// Imported or completely analyzed function.  Use the escape tags.
+	if(n->escretval != nil)
+		fatal("esc already decorated call %+N\n", n);
+
+	// set up out list on this call node with dummy auto ONAMES in the current (calling) function.
+	i = 0;
+	for(t=getoutargx(fntype)->type; t; t=t->down) {
+		src = nod(ONAME, N, N);
+		snprint(buf, sizeof buf, ".dum%d", i++);
+		src->sym = lookup(buf);
+		src->type = t->type;
+		src->class = PAUTO;
+		src->curfn = curfn;
+		src->escloopdepth = e->loopdepth;
+		src->used = 1;
+		src->lineno = n->lineno;
+		n->escretval = list(n->escretval, src); 
 	}
+
+//	print("esc analyzed fn: %#N (%+T) returning (%+H)\n", fn, fntype, n->escretval);
+
+	// Receiver.
+	if(n->op != OCALLFUNC)
+		escassignfromtag(e, getthisx(fntype)->type->note, n->escretval, n->left->left);
+	
 	for(t=getinargx(fntype)->type; ll; ll=ll->next) {
 		src = ll->n;
 		if(t->isddd && !n->isddd) {
 			// Introduce ODDDARG node to represent ... allocation.
 			src = nod(ODDDARG, N, N);
-			src->escloopdepth = loopdepth;
+			src->escloopdepth = e->loopdepth;
 			src->lineno = n->lineno;
 			src->esc = EscNone;  // until we find otherwise
-			noesc = list(noesc, src);
+			e->noesc = list(e->noesc, src);
 			n->right = src;
 		}
-		if(!t->note || strcmp(t->note->s, safetag->s) != 0)
-			escassign(&theSink, src);
+		escassignfromtag(e, t->note, n->escretval, src);
 		if(src != ll->n)
 			break;
 		t = t->down;
 	}
 	// "..." arguments are untracked
 	for(; ll; ll=ll->next)
-		escassign(&theSink, ll->n);
+		escassign(e, &e->theSink, ll->n);
 }
 
 // Store the link src->dst in dst, throwing out some quick wins.
 static void
-escflows(Node *dst, Node *src)
+escflows(EscState *e, Node *dst, Node *src)
 {
 	if(dst == nil || src == nil || dst == src)
 		return;
@@ -659,10 +943,10 @@ escflows(Node *dst, Node *src)
 		print("%L::flows:: %hN <- %hN\n", lineno, dst, src);
 
 	if(dst->escflowsrc == nil) {
-		dsts = list(dsts, dst);
-		dstcount++;
+		e->dsts = list(e->dsts, dst);
+		e->dstcount++;
 	}
-	edgecount++;
+	e->edgecount++;
 
 	dst->escflowsrc = list(dst->escflowsrc, src);
 }
@@ -673,11 +957,11 @@ escflows(Node *dst, Node *src)
 // so this address doesn't leak (yet).
 // If level == 0, it means the /value/ of this node can reach the root of this flood.
 // so if this node is an OADDR, it's argument should be marked as escaping iff
-// it's currfn/loopdepth are different from the flood's root.
+// it's currfn/e->loopdepth are different from the flood's root.
 // Once an object has been moved to the heap, all of it's upstream should be considered
 // escaping to the global scope.
 static void
-escflood(Node *dst)
+escflood(EscState *e, Node *dst)
 {
 	NodeList *l;
 
@@ -696,45 +980,71 @@ escflood(Node *dst)
 
 	for(l = dst->escflowsrc; l; l=l->next) {
 		walkgen++;
-		escwalk(0, dst, l->n);
+		escwalk(e, 0, dst, l->n);
 	}
 }
 
+// There appear to be some loops in the escape graph, causing
+// arbitrary recursion into deeper and deeper levels.
+// Cut this off safely by making minLevel sticky: once you
+// get that deep, you cannot go down any further but you also
+// cannot go up any further. This is a conservative fix.
+// Making minLevel smaller (more negative) would handle more
+// complex chains of indirections followed by address-of operations,
+// at the cost of repeating the traversal once for each additional
+// allowed level when a loop is encountered. Using -2 suffices to
+// 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)
+
 static void
-escwalk(int level, Node *dst, Node *src)
+escwalk(EscState *e, int level, Node *dst, Node *src)
 {
 	NodeList *ll;
-	int leaks;
+	int leaks, newlevel;
 
-	if(src->walkgen == walkgen)
+	if(src->walkgen == walkgen && src->esclevel <= level)
 		return;
 	src->walkgen = walkgen;
+	src->esclevel = level;
 
 	if(debug['m']>1)
 		print("escwalk: level:%d depth:%d %.*s %hN(%hJ) scope:%S[%d]\n",
-		      level, pdepth, pdepth, "\t\t\t\t\t\t\t\t\t\t", src, src,
+		      level, e->pdepth, e->pdepth, "\t\t\t\t\t\t\t\t\t\t", src, src,
 		      (src->curfn && src->curfn->nname) ? src->curfn->nname->sym : S, src->escloopdepth);
 
-	pdepth++;
+	e->pdepth++;
+
+	// Input parameter flowing to output parameter?
+	if(dst->op == ONAME && dst->class == PPARAMOUT && dst->vargen <= 20) {
+		if(src->op == ONAME && src->class == PPARAM && level == 0 && src->curfn == dst->curfn) {
+			if(src->esc != EscScope && src->esc != EscHeap) {
+				if(debug['m'])
+					warnl(src->lineno, "leaking param: %hN to result %S", src, dst->sym);
+				if((src->esc&EscMask) != EscReturn)
+					src->esc = EscReturn;
+				src->esc |= 1<<((dst->vargen-1) + EscBits);
+				goto recurse;
+			}
+		}
+	}
 
 	leaks = (level <= 0) && (dst->escloopdepth < src->escloopdepth);
 
 	switch(src->op) {
 	case ONAME:
-		if(src->class == PPARAM && leaks && src->esc == EscNone) {
+		if(src->class == PPARAM && leaks && src->esc != EscHeap) {
 			src->esc = EscScope;
 			if(debug['m'])
 				warnl(src->lineno, "leaking param: %hN", src);
 		}
-		// handle the missing flow ref <- orig
-		// a paramref is automagically dereferenced, and taking its
-		// address produces the address of the original, so all we have to do here
-		// is keep track of the value flow, so level is unchanged.
-		// alternatively, we could have substituted PPARAMREFs with their ->closure in esc/escassign/flow,
+
+		// Treat a PPARAMREF closure variable as equivalent to the
+		// original variable.
 		if(src->class == PPARAMREF) {
 			if(leaks && debug['m'])
 				warnl(src->lineno, "leaking closure reference %hN", src);
-			escwalk(level, dst, src->closure);
+			escwalk(e, level, dst, src->closure);
 		}
 		break;
 
@@ -746,7 +1056,10 @@ escwalk(int level, Node *dst, Node *src)
 			if(debug['m'])
 				warnl(src->lineno, "%hN escapes to heap", src);
 		}
-		escwalk(level-1, dst, src->left);
+		newlevel = level;
+		if(level > MinLevel)
+			newlevel--;
+		escwalk(e, newlevel, dst, src->left);
 		break;
 
 	case OARRAYLIT:
@@ -767,32 +1080,53 @@ escwalk(int level, Node *dst, Node *src)
 		}
 		break;
 
+	case ODOT:
+		escwalk(e, level, dst, src->left);
+		break;
+
 	case OINDEX:
-		if(isfixedarray(src->type))
+		if(isfixedarray(src->left->type)) {
+			escwalk(e, level, dst, src->left);
 			break;
+		}
 		// fall through
 	case OSLICE:
 	case ODOTPTR:
 	case OINDEXMAP:
 	case OIND:
-		escwalk(level+1, dst, src->left);
+		newlevel = level;
+		if(level > MinLevel)
+			newlevel++;
+		escwalk(e, newlevel, dst, src->left);
 	}
 
+recurse:
 	for(ll=src->escflowsrc; ll; ll=ll->next)
-		escwalk(level, dst, ll->n);
+		escwalk(e, level, dst, ll->n);
 
-	pdepth--;
+	e->pdepth--;
 }
 
 static void
-esctag(Node *func)
+esctag(EscState *e, Node *func)
 {
 	Node *savefn;
 	NodeList *ll;
+	Type *t;
+
+	USED(e);
+	func->esc = EscFuncTagged;
 	
-	// External functions must be assumed unsafe.
-	if(func->nbody == nil)
+	// External functions are assumed unsafe,
+	// unless //go:noescape is given before the declaration.
+	if(func->nbody == nil) {
+		if(func->noescape) {
+			for(t=getinargx(func->type)->type; t; t=t->down)
+				if(haspointers(t->type))
+					t->note = mktag(EscNone);
+		}
 		return;
+	}
 
 	savefn = curfn;
 	curfn = func;
@@ -801,10 +1135,12 @@ esctag(Node *func)
 		if(ll->n->op != ONAME || ll->n->class != PPARAM)
 			continue;
 
-		switch (ll->n->esc) {
+		switch (ll->n->esc&EscMask) {
 		case EscNone:	// not touched by escflood
+		case EscReturn:	
 			if(haspointers(ll->n->type)) // don't bother tagging for scalars
-				ll->n->paramfld->note = safetag;
+				ll->n->paramfld->note = mktag(ll->n->esc);
+			break;
 		case EscHeap:	// touched by escflood, moved to heap
 		case EscScope:	// touched by escflood, value leaves scope
 			break;
diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c
index bbed8ae..b731166 100644
--- a/src/cmd/gc/export.c
+++ b/src/cmd/gc/export.c
@@ -22,22 +22,8 @@ exportsym(Node *n)
 	}
 	n->sym->flags |= SymExport;
 
-	exportlist = list(exportlist, n);
-}
-
-// Mark n's symbol as package-local
-static void
-packagesym(Node *n)
-{
-	if(n == N || n->sym == S)
-		return;
-	if(n->sym->flags & (SymExport|SymPackage)) {
-		if(n->sym->flags & SymExport)
-			yyerror("export/package mismatch: %S", n->sym);
-		return;
-	}
-	n->sym->flags |= SymPackage;
-
+	if(debug['E'])
+		print("export symbol %S\n", n->sym);
 	exportlist = list(exportlist, n);
 }
 
@@ -58,6 +44,18 @@ initname(char *s)
 	return strcmp(s, "init") == 0;
 }
 
+// exportedsym returns whether a symbol will be visible
+// to files that import our package.
+static int
+exportedsym(Sym *sym)
+{
+	// Builtins are visible everywhere.
+	if(sym->pkg == builtinpkg || sym->origpkg == builtinpkg)
+		return 1;
+
+	return sym->pkg == localpkg && exportname(sym->name);
+}
+
 void
 autoexport(Node *n, int ctxt)
 {
@@ -67,10 +65,9 @@ autoexport(Node *n, int ctxt)
 		return;
 	if(n->ntype && n->ntype->op == OTFUNC && n->ntype->left)	// method
 		return;
-	if(exportname(n->sym->name) || initname(n->sym->name))
+	// -A is for cmd/gc/mkbuiltin script, so export everything
+	if(debug['A'] || exportname(n->sym->name) || initname(n->sym->name))
 		exportsym(n);
-	else
-		packagesym(n);
 }
 
 static void
@@ -104,36 +101,60 @@ reexportdep(Node *n)
 	if(!n)
 		return;
 
-//	print("reexportdep %+hN\n", n);
+	//print("reexportdep %+hN\n", n);
 	switch(n->op) {
 	case ONAME:
 		switch(n->class&~PHEAP) {
 		case PFUNC:
 			// methods will be printed along with their type
+			// nodes for T.Method expressions
+			if(n->left && n->left->op == OTYPE)
+				break;
+			// nodes for method calls.
 			if(!n->type || n->type->thistuple > 0)
 				break;
 			// fallthrough
 		case PEXTERN:
-			if (n->sym && n->sym->pkg != localpkg && n->sym->pkg != builtinpkg)
+			if(n->sym && !exportedsym(n->sym)) {
+				if(debug['E'])
+					print("reexport name %S\n", n->sym);
 				exportlist = list(exportlist, n);
+			}
 		}
 		break;
 
+	case ODCL:
+		// Local variables in the bodies need their type.
+		t = n->left->type;
+		if(t != types[t->etype] && t != idealbool && t != idealstring) {
+			if(isptr[t->etype])
+				t = t->type;
+			if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
+				if(debug['E'])
+					print("reexport type %S from declaration\n", t->sym);
+				exportlist = list(exportlist, t->sym->def);
+			}
+		}
+		break;
 
 	case OLITERAL:
 		t = n->type;
 		if(t != types[n->type->etype] && t != idealbool && t != idealstring) {
 			if(isptr[t->etype])
 				t = t->type;
-			if (t && t->sym && t->sym->def && t->sym->pkg != localpkg  && t->sym->pkg != builtinpkg) {
-//				print("reexport literal type %+hN\n", t->sym->def);
+			if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
+				if(debug['E'])
+					print("reexport literal type %S\n", t->sym);
 				exportlist = list(exportlist, t->sym->def);
 			}
 		}
 		// fallthrough
 	case OTYPE:
-		if (n->sym && n->sym->pkg != localpkg && n->sym->pkg != builtinpkg)
+		if(n->sym && !exportedsym(n->sym)) {
+			if(debug['E'])
+				print("reexport literal/type %S\n", n->sym);
 			exportlist = list(exportlist, n);
+		}
 		break;
 
 	// for operations that need a type when rendered, put the type on the export list.
@@ -141,13 +162,15 @@ reexportdep(Node *n)
 	case OCONVIFACE:
 	case OCONVNOP:
 	case ODOTTYPE:
+	case ODOTTYPE2:
 	case OSTRUCTLIT:
 	case OPTRLIT:
 		t = n->type;
 		if(!t->sym && t->type)
 			t = t->type;
-		if (t && t->sym && t->sym->def && t->sym->pkg != localpkg  && t->sym->pkg != builtinpkg) {
-//			print("reexport convnop %+hN\n", t->sym->def);
+		if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
+			if(debug['E'])
+				print("reexport type for convnop %S\n", t->sym);
 			exportlist = list(exportlist, t->sym->def);
 		}
 		break;
@@ -207,10 +230,11 @@ dumpexportvar(Sym *s)
 			// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
 			if(debug['l'] < 2)
 				typecheckinl(n);
-			Bprint(bout, "\tfunc %#S%#hT { %#H }\n", s, t, n->inl);
+			// NOTE: The space after %#S here is necessary for ld's export data parser.
+			Bprint(bout, "\tfunc %#S %#hT { %#H }\n", s, t, n->inl);
 			reexportdeplist(n->inl);
 		} else
-			Bprint(bout, "\tfunc %#S%#hT\n", s, t);
+			Bprint(bout, "\tfunc %#S %#hT\n", s, t);
 	} else
 		Bprint(bout, "\tvar %#S %#T\n", s, t);
 }
@@ -262,15 +286,17 @@ dumpexporttype(Type *t)
 	Bprint(bout, "\ttype %#S %#lT\n", t->sym, t);
 	for(i=0; i<n; i++) {
 		f = m[i];
+		if(f->nointerface)
+			Bprint(bout, "\t//go:nointerface\n");
 		if (f->type->nname && f->type->nname->inl) { // nname was set by caninl
 			// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
 			// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
 			if(debug['l'] < 2)
 				typecheckinl(f->type->nname);
-			Bprint(bout, "\tfunc (%#T) %#hhS%#hT { %#H }\n", getthisx(f->type)->type, f->sym, f->type, f->type->nname->inl);
+			Bprint(bout, "\tfunc (%#T) %#hhS %#hT { %#H }\n", getthisx(f->type)->type, f->sym, f->type, f->type->nname->inl);
 			reexportdeplist(f->type->nname->inl);
 		} else
-			Bprint(bout, "\tfunc (%#T) %#hhS%#hT\n", getthisx(f->type)->type, f->sym, f->type);
+			Bprint(bout, "\tfunc (%#T) %#hhS %#hT\n", getthisx(f->type)->type, f->sym, f->type);
 	}
 }
 
@@ -349,8 +375,12 @@ dumpexport(void)
 Sym*
 importsym(Sym *s, int op)
 {
-	if(s->def != N && s->def->op != op)
-		redeclare(s, "during import");
+	char *pkgstr;
+
+	if(s->def != N && s->def->op != op) {
+		pkgstr = smprint("during import \"%Z\"", importpkg->path);
+		redeclare(s, pkgstr);
+	}
 
 	// mark the symbol so it is not reexported
 	if(s->def == N) {
@@ -389,6 +419,8 @@ importimport(Sym *s, Strlit *z)
 	// human-readable messages.
 	Pkg *p;
 
+	if(isbadimport(z))
+		errorexit();
 	p = mkpkg(z);
 	if(p->name == nil) {
 		p->name = s->name;
diff --git a/src/cmd/gc/fmt.c b/src/cmd/gc/fmt.c
index 5672c00..ab81e6c 100644
--- a/src/cmd/gc/fmt.c
+++ b/src/cmd/gc/fmt.c
@@ -228,6 +228,7 @@ goopnames[] =
 	[ORANGE]	= "range",
 	[OREAL]		= "real",
 	[ORECV]		= "<-",
+	[ORECOVER]	= "recover",
 	[ORETURN]	= "return",
 	[ORSH]		= ">>",
 	[OSELECT]	= "select",
@@ -289,7 +290,7 @@ Jconv(Fmt *fp)
 		fmtprint(fp, " l(%d)", n->lineno);
 
 	if(!c && n->xoffset != BADWIDTH)
-		fmtprint(fp, " x(%lld%+d)", n->xoffset, n->stkdelta);
+		fmtprint(fp, " x(%lld%+lld)", n->xoffset, n->stkdelta);
 
 	if(n->class != 0) {
 		s = "";
@@ -361,6 +362,8 @@ Vconv(Fmt *fp)
 
 	switch(v->ctype) {
 	case CTINT:
+		if((fp->flags & FmtSharp) || fmtmode == FExp)
+			return fmtprint(fp, "%#B", v->u.xval);
 		return fmtprint(fp, "%B", v->u.xval);
 	case CTRUNE:
 		x = mpgetfix(v->u.xval);
@@ -377,8 +380,14 @@ Vconv(Fmt *fp)
 		return fmtprint(fp, "%#F", v->u.fval);
 	case CTCPLX:
 		if((fp->flags & FmtSharp) || fmtmode == FExp)
-			return fmtprint(fp, "(%F+%F)", &v->u.cval->real, &v->u.cval->imag);
-		return fmtprint(fp, "(%#F + %#Fi)", &v->u.cval->real, &v->u.cval->imag);
+			return fmtprint(fp, "(%F+%Fi)", &v->u.cval->real, &v->u.cval->imag);
+		if(mpcmpfltc(&v->u.cval->real, 0) == 0)
+			return fmtprint(fp, "%#Fi", &v->u.cval->imag);
+		if(mpcmpfltc(&v->u.cval->imag, 0) == 0)
+			return fmtprint(fp, "%#F", &v->u.cval->real);
+		if(mpcmpfltc(&v->u.cval->imag, 0) < 0)
+			return fmtprint(fp, "(%#F%#Fi)", &v->u.cval->real, &v->u.cval->imag);
+		return fmtprint(fp, "(%#F+%#Fi)", &v->u.cval->real, &v->u.cval->imag);
 	case CTSTR:
 		return fmtprint(fp, "\"%Z\"", v->u.sval);
 	case CTBOOL:
@@ -388,7 +397,7 @@ Vconv(Fmt *fp)
 	case CTNIL:
 		return fmtstrcpy(fp, "nil");
 	}
-	return fmtprint(fp, "<%d>", v->ctype);
+	return fmtprint(fp, "<ctype=%d>", v->ctype);
 }
 
 // Fmt "%Z": escaped string literals
@@ -516,6 +525,8 @@ symfmt(Fmt *fp, Sym *s)
 				return fmtprint(fp, "%s.%s", s->pkg->name, s->name);	// dcommontype, typehash
 			return fmtprint(fp, "%s.%s", s->pkg->prefix, s->name);	// (methodsym), typesym, weaksym
 		case FExp:
+			if(s->name && s->name[0] == '.')
+				fatal("exporting synthetic symbol %s", s->name);
 			if(s->pkg != builtinpkg)
 				return fmtprint(fp, "@\"%Z\".%s", s->pkg->path, s->name);
 		}
@@ -711,12 +722,21 @@ typefmt(Fmt *fp, Type *t)
 	case TFIELD:
 		if(!(fp->flags&FmtShort)) {
 			s = t->sym;
-			// Take the name from the original, lest we substituted it with .anon%d
-			if (t->nname && (fmtmode == FErr || fmtmode == FExp))
-				s = t->nname->orig->sym;
+
+			// Take the name from the original, lest we substituted it with ~anon%d
+			if ((fmtmode == FErr || fmtmode == FExp) && t->nname != N) {
+				if(t->nname->orig != N) {
+					s = t->nname->orig->sym;
+					if(s != S && s->name[0] == '~')
+						s = S;
+				} else 
+					s = S;
+			}
 			
 			if(s != S && !t->embedded) {
-				if(fp->flags&FmtLong)
+				if(t->funarg)
+					fmtprint(fp, "%N ", t->nname);
+				else if(fp->flags&FmtLong)
 					fmtprint(fp, "%hhS ", s);  // qualify non-exported names (used on structs, not on funarg)
 				else 
 					fmtprint(fp, "%S ", s);
@@ -794,6 +814,15 @@ stmtfmt(Fmt *f, Node *n)
 
 	switch(n->op){
 	case ODCL:
+		if(fmtmode == FExp) {
+			switch(n->left->class&~PHEAP) {
+			case PPARAM:
+			case PPARAMOUT:
+			case PAUTO:
+				fmtprint(f, "var %N %T", n->left, n->left->type);
+				goto ret;
+			}
+		}			
 		fmtprint(f, "var %S %T", n->left->sym, n->left->type);
 		break;
 
@@ -805,6 +834,12 @@ stmtfmt(Fmt *f, Node *n)
 		break;
 
 	case OAS:
+		// Don't export "v = <N>" initializing statements, hope they're always 
+		// preceded by the DCL which will be re-parsed and typecheck to reproduce
+		// the "v = <N>" again.
+		if(fmtmode == FExp && n->right == N)
+			break;
+
 		if(n->colas && !complexinit)
 			fmtprint(f, "%N := %N", n->left, n->right);
 		else
@@ -925,6 +960,7 @@ stmtfmt(Fmt *f, Node *n)
 		break;
 	  
 	}
+ret:
 
 	if(extrablock)
 		fmtstrcpy(f, "}");
@@ -962,7 +998,6 @@ static int opprec[] = {
 	[OPAREN] = 8,
 	[OPRINTN] = 8,
 	[OPRINT] = 8,
-	[ORECV] = 8,
 	[ORUNESTR] = 8,
 	[OSTRARRAYBYTE] = 8,
 	[OSTRARRAYRUNE] = 8,
@@ -994,6 +1029,7 @@ static int opprec[] = {
 	[OMINUS] = 7,
 	[OADDR] = 7,
 	[OIND] = 7,
+	[ORECV] = 7,
 
 	[OMUL] = 6,
 	[ODIV] = 6,
@@ -1055,8 +1091,8 @@ static int
 exprfmt(Fmt *f, Node *n, int prec)
 {
 	int nprec;
+	int ptrlit;
 	NodeList *l;
-	Type *t;
 
 	while(n && n->implicit && (n->op == OIND || n->op == OADDR))
 		n = n->left;
@@ -1084,9 +1120,9 @@ exprfmt(Fmt *f, Node *n, int prec)
 	case OLITERAL:  // this is a bit of a mess
 		if(fmtmode == FErr && n->sym != S)
 			return fmtprint(f, "%S", n->sym);
-		if(n->val.ctype == CTNIL)
-			n = n->orig; // if this node was a nil decorated with at type, print the original naked nil
-		if(n->type != types[n->type->etype] && n->type != idealbool && n->type != idealstring) {
+		if(n->val.ctype == CTNIL && n->orig != N && n->orig != n)
+			return exprfmt(f, n->orig, prec);
+		if(n->type != T && n->type != types[n->type->etype] && n->type != idealbool && n->type != idealstring) {
 			// Need parens when type begins with what might
 			// be misinterpreted as a unary operator: * or <-.
 			if(isptr[n->type->etype] || (n->type->etype == TCHAN && n->type->chan == Crecv))
@@ -1097,6 +1133,15 @@ exprfmt(Fmt *f, Node *n, int prec)
 		return fmtprint(f, "%V", &n->val);
 
 	case ONAME:
+		// Special case: name used as local variable in export.
+		switch(n->class&~PHEAP){
+		case PAUTO:
+		case PPARAM:
+		case PPARAMOUT:
+			if(fmtmode == FExp && n->sym && !isblanksym(n->sym) && 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.
 		// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
@@ -1152,12 +1197,25 @@ exprfmt(Fmt *f, Node *n, int prec)
 	case OCLOSURE:
 		if(fmtmode == FErr)
 			return fmtstrcpy(f, "func literal");
-		return fmtprint(f, "%T { %H }", n->type, n->nbody);
+		if(n->nbody)
+			return fmtprint(f, "%T { %H }", n->type, n->nbody);
+		return fmtprint(f, "%T { %H }", n->type, n->closure->nbody);
 
 	case OCOMPLIT:
-		if(fmtmode == FErr)
+		ptrlit = n->right != N && n->right->implicit && n->right->type && isptr[n->right->type->etype];
+		if(fmtmode == FErr) {
+			if(n->right != N && n->right->type != T && !n->implicit) {
+				if(ptrlit)
+					return fmtprint(f, "&%T literal", n->right->type->type);
+				else
+					return fmtprint(f, "%T literal", n->right->type);
+			}
 			return fmtstrcpy(f, "composite literal");
-		return fmtprint(f, "%N{ %,H }", n->right, n->list);
+		}
+		if(fmtmode == FExp && ptrlit)
+			// typecheck has overwritten OIND by OTYPE with pointer type.
+			return fmtprint(f, "&%T{ %,H }", n->right->type->type, n->list);
+		return fmtprint(f, "(%N{ %,H })", n->right, n->list);
 
 	case OPTRLIT:
 		if(fmtmode == FExp && n->left->implicit)
@@ -1168,24 +1226,18 @@ exprfmt(Fmt *f, Node *n, int prec)
 		if(fmtmode == FExp) {   // requires special handling of field names
 			if(n->implicit)
 				fmtstrcpy(f, "{");
-			else 
-				fmtprint(f, "%T{", n->type);
+			else
+				fmtprint(f, "(%T{", n->type);
 			for(l=n->list; l; l=l->next) {
-				// another special case: if n->left is an embedded field of builtin type,
-				// it needs to be non-qualified.  Can't figure that out in %S, so do it here
-				if(l->n->left->type->embedded) {
-					t = l->n->left->type->type;
-					if(t->sym == S)
-						t = t->type;
-					fmtprint(f, " %T:%N", t, l->n->right);
-				} else
-					fmtprint(f, " %hhS:%N", l->n->left->sym, l->n->right);
+				fmtprint(f, " %hhS:%N", l->n->left->sym, l->n->right);
 
 				if(l->next)
 					fmtstrcpy(f, ",");
 				else
 					fmtstrcpy(f, " ");
 			}
+			if(!n->implicit)
+				return fmtstrcpy(f, "})");
 			return fmtstrcpy(f, "}");
 		}
 		// fallthrough
@@ -1196,11 +1248,16 @@ exprfmt(Fmt *f, Node *n, int prec)
 			return fmtprint(f, "%T literal", n->type);
 		if(fmtmode == FExp && n->implicit)
 			return fmtprint(f, "{ %,H }", n->list);
-		return fmtprint(f, "%T{ %,H }", n->type, n->list);
+		return fmtprint(f, "(%T{ %,H })", n->type, n->list);
 
 	case OKEY:
-		if(n->left && n->right)
-			return fmtprint(f, "%N:%N", n->left, n->right);
+		if(n->left && n->right) {
+			if(fmtmode == FExp && n->left->type && n->left->type->etype == TFIELD) {
+				// requires special handling of field names
+				return fmtprint(f, "%hhS:%N", n->left->sym, n->right);
+			} else
+				return fmtprint(f, "%N:%N", n->left, n->right);
+		}
 		if(!n->left && n->right)
 			return fmtprint(f, ":%N", n->right);
 		if(n->left && !n->right)
@@ -1260,6 +1317,7 @@ exprfmt(Fmt *f, Node *n, int prec)
 	case OMAKE:
 	case ONEW:
 	case OPANIC:
+	case ORECOVER:
 	case OPRINT:
 	case OPRINTN:
 		if(n->left)
@@ -1408,6 +1466,7 @@ nodedump(Fmt *fp, Node *n)
 		fmtprint(fp, "%O%J", n->op, n);
 		break;
 	case OREGISTER:
+	case OINDREG:
 		fmtprint(fp, "%O-%R%J", n->op, n->val.u.reg, n);
 		break;
 	case OLITERAL:
@@ -1419,6 +1478,10 @@ nodedump(Fmt *fp, Node *n)
 			fmtprint(fp, "%O-%S%J", n->op, n->sym, n);
 		else
 			fmtprint(fp, "%O%J", n->op, n);
+		if(recur && n->type == T && n->ntype) {
+			indent(fp);
+			fmtprint(fp, "%O-ntype%N", n->op, n->ntype);
+		}
 		break;
 	case OASOP:
 		fmtprint(fp, "%O-%O%J", n->op, n->etype, n);
@@ -1629,11 +1692,11 @@ fmtinstallgo(void)
 void
 dumplist(char *s, NodeList *l)
 {
-	print("%s\n%+H\n", s, l);
+	print("%s%+H\n", s, l);
 }
 
 void
 dump(char *s, Node *n)
 {
-	print("%s [%p]\n%+N\n", s, n, n);
+	print("%s [%p]%+N\n", s, n, n);
 }
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 96e7b52..5f03d94 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -266,6 +266,8 @@ gen(Node *n)
 	Label *lab;
 	int32 wasregalloc;
 
+//dump("gen", n);
+
 	lno = setlineno(n);
 	wasregalloc = anyregalloc();
 
@@ -279,7 +281,7 @@ gen(Node *n)
 
 	switch(n->op) {
 	default:
-		fatal("gen: unknown op %N", n);
+		fatal("gen: unknown op %+hN", n);
 		break;
 
 	case OCASE:
@@ -394,7 +396,7 @@ gen(Node *n)
 		}
 		gen(n->nincr);				// contin:	incr
 		patch(p1, pc);				// test:
-		bgen(n->ntest, 0, breakpc);		//		if(!test) goto break
+		bgen(n->ntest, 0, -1, breakpc);		//		if(!test) goto break
 		genlist(n->nbody);				//		body
 		gjmp(continpc);
 		patch(breakpc, pc);			// done:
@@ -410,7 +412,7 @@ gen(Node *n)
 		p1 = gjmp(P);			//		goto test
 		p2 = gjmp(P);			// p2:		goto else
 		patch(p1, pc);				// test:
-		bgen(n->ntest, 0, p2);			//		if(!test) goto p2
+		bgen(n->ntest, 0, -n->likely, p2);		//		if(!test) goto p2
 		genlist(n->nbody);				//		then
 		p3 = gjmp(P);			//		goto done
 		patch(p2, pc);				// else:
@@ -509,22 +511,24 @@ ret:
 void
 cgen_callmeth(Node *n, int proc)
 {
+	Node n2;
 	Node *l;
 
-	// generate a rewrite for method call
+	// generate a rewrite in n2 for the method call
 	// (p.f)(...) goes to (f)(p,...)
 
 	l = n->left;
 	if(l->op != ODOTMETH)
 		fatal("cgen_callmeth: not dotmethod: %N");
 
-	n->op = OCALLFUNC;
-	n->left = n->left->right;
-	n->left->type = l->type;
+	n2 = *n;
+	n2.op = OCALLFUNC;
+	n2.left = l->right;
+	n2.left->type = l->type;
 
-	if(n->left->op == ONAME)
-		n->left->class = PFUNC;
-	cgen_call(n, proc);
+	if(n2.left->op == ONAME)
+		n2.left->class = PFUNC;
+	cgen_call(&n2, proc);
 }
 
 /*
@@ -631,6 +635,67 @@ cgen_discard(Node *nr)
 }
 
 /*
+ * clearslim generates code to zero a slim node.
+ */
+void
+clearslim(Node *n)
+{
+	Node z;
+	Mpflt zero;
+
+	memset(&z, 0, sizeof(z));
+	z.op = OLITERAL;
+	z.type = n->type;
+	z.addable = 1;
+
+	switch(simtype[n->type->etype]) {
+	case TCOMPLEX64:
+	case TCOMPLEX128:
+		z.val.u.cval = mal(sizeof(*z.val.u.cval));
+		mpmovecflt(&z.val.u.cval->real, 0.0);
+		mpmovecflt(&z.val.u.cval->imag, 0.0);
+		break;
+
+	case TFLOAT32:
+	case TFLOAT64:
+		mpmovecflt(&zero, 0.0);
+		z.val.ctype = CTFLT;
+		z.val.u.fval = &zero;
+		break;
+
+	case TPTR32:
+	case TPTR64:
+	case TCHAN:
+	case TMAP:
+		z.val.ctype = CTNIL;
+		break;
+
+	case TBOOL:
+		z.val.ctype = CTBOOL;
+		break;
+
+	case TINT8:
+	case TINT16:
+	case TINT32:
+	case TINT64:
+	case TUINT8:
+	case TUINT16:
+	case TUINT32:
+	case TUINT64:
+		z.val.ctype = CTINT;
+		z.val.u.xval = mal(sizeof(*z.val.u.xval));
+		mpmovecfix(z.val.u.xval, 0);
+		break;
+
+	default:
+		fatal("clearslim called on type %T", n->type);
+	}
+
+	ullmancalc(&z);
+	cgen(&z, n);
+}
+
+/*
  * generate assignment:
  *	nl = nr
  * nr == N means zero nl.
@@ -638,9 +703,7 @@ cgen_discard(Node *nr)
 void
 cgen_as(Node *nl, Node *nr)
 {
-	Node nc;
 	Type *tl;
-	int iszer;
 
 	if(debug['g']) {
 		dump("cgen_as", nl);
@@ -655,7 +718,6 @@ cgen_as(Node *nl, Node *nr)
 		return;
 	}
 
-	iszer = 0;
 	if(nr == N || isnil(nr)) {
 		// externals and heaps should already be clear
 		if(nr == N) {
@@ -670,59 +732,10 @@ cgen_as(Node *nl, Node *nr)
 			return;
 		if(isfat(tl)) {
 			clearfat(nl);
-			goto ret;
-		}
-
-		/* invent a "zero" for the rhs */
-		iszer = 1;
-		nr = &nc;
-		memset(nr, 0, sizeof(*nr));
-		switch(simtype[tl->etype]) {
-		default:
-			fatal("cgen_as: tl %T", tl);
-			break;
-
-		case TINT8:
-		case TUINT8:
-		case TINT16:
-		case TUINT16:
-		case TINT32:
-		case TUINT32:
-		case TINT64:
-		case TUINT64:
-			nr->val.u.xval = mal(sizeof(*nr->val.u.xval));
-			mpmovecfix(nr->val.u.xval, 0);
-			nr->val.ctype = CTINT;
-			break;
-
-		case TFLOAT32:
-		case TFLOAT64:
-			nr->val.u.fval = mal(sizeof(*nr->val.u.fval));
-			mpmovecflt(nr->val.u.fval, 0.0);
-			nr->val.ctype = CTFLT;
-			break;
-
-		case TBOOL:
-			nr->val.u.bval = 0;
-			nr->val.ctype = CTBOOL;
-			break;
-
-		case TPTR32:
-		case TPTR64:
-			nr->val.ctype = CTNIL;
-			break;
-
-		case TCOMPLEX64:
-		case TCOMPLEX128:
-			nr->val.u.cval = mal(sizeof(*nr->val.u.cval));
-			mpmovecflt(&nr->val.u.cval->real, 0.0);
-			mpmovecflt(&nr->val.u.cval->imag, 0.0);
-			break;
+			return;
 		}
-		nr->op = OLITERAL;
-		nr->type = tl;
-		nr->addable = 1;
-		ullmancalc(nr);
+		clearslim(nl);
+		return;
 	}
 
 	tl = nl->type;
@@ -730,11 +743,88 @@ cgen_as(Node *nl, Node *nr)
 		return;
 
 	cgen(nr, nl);
-	if(iszer && nl->addable)
-		gused(nl);
+}
 
-ret:
-	;
+/*
+ * generate:
+ *	res = iface{typ, data}
+ * n->left is typ
+ * n->right is data
+ */
+void
+cgen_eface(Node *n, Node *res)
+{
+	/* 
+	 * the right node of an eface may contain function calls that uses res as an argument,
+	 * so it's important that it is done first
+	 */
+	Node dst;
+	dst = *res;
+	dst.type = types[tptr];
+	dst.xoffset += widthptr;
+	cgen(n->right, &dst);
+	dst.xoffset -= widthptr;
+	cgen(n->left, &dst);
+}
+
+/*
+ * generate:
+ *	res = s[lo, hi];
+ * n->left is s
+ * n->list is (cap(s)-lo(TUINT), hi-lo(TUINT)[, lo*width(TUINTPTR)])
+ * caller (cgen) guarantees res is an addable ONAME.
+ */
+void
+cgen_slice(Node *n, Node *res)
+{
+	Node src, dst, *cap, *len, *offs, *add;
+
+	cap = n->list->n;
+	len = n->list->next->n;
+	offs = N;
+	if(n->list->next->next)
+		offs = n->list->next->next->n;
+
+	// dst.len = hi [ - lo ]
+	dst = *res;
+	dst.xoffset += Array_nel;
+	dst.type = types[simtype[TUINT]];
+	cgen(len, &dst);
+
+	if(n->op != OSLICESTR) {
+		// dst.cap = cap [ - lo ]
+		dst = *res;
+		dst.xoffset += Array_cap;
+		dst.type = types[simtype[TUINT]];
+		cgen(cap, &dst);
+	}
+
+	// dst.array = src.array  [ + lo *width ]
+	dst = *res;
+	dst.xoffset += Array_array;
+	dst.type = types[TUINTPTR];
+
+	if(n->op == OSLICEARR) {
+		if(!isptr[n->left->type->etype])
+			fatal("slicearr is supposed to work on pointer: %+N\n", n);
+		checkref(n->left);
+	}
+
+	if(isnil(n->left)) {
+		tempname(&src, n->left->type);
+		cgen(n->left, &src);
+	} else
+		src = *n->left;
+	src.xoffset += Array_array;
+	src.type = types[TUINTPTR];
+
+	if(offs == N) {
+		cgen(&src, &dst);
+	} else {
+		add = nod(OADD, &src, offs);
+		typecheck(&add, Erv);
+		cgen(add, &dst);
+	}
 }
 
 /*
diff --git a/src/cmd/gc/go.errors b/src/cmd/gc/go.errors
index e29cfff..68a5e5a 100644
--- a/src/cmd/gc/go.errors
+++ b/src/cmd/gc/go.errors
@@ -65,6 +65,9 @@ static struct {
 	% loadsys package imports LVAR LNAME '=' LNAME '{' LNAME ';'
 	"need trailing comma before newline in composite literal",
 	
+	% loadsys package imports LVAR LNAME '=' comptype '{' LNAME ';'
+	"need trailing comma before newline in composite literal",
+	
 	% loadsys package imports LFUNC LNAME '(' ')' '{' LFUNC LNAME
 	"nested func not allowed",
 
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 43bd687..f86c152 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -137,6 +137,7 @@ typedef	struct	Label	Label;
 struct	Type
 {
 	uchar	etype;
+	uchar	nointerface;
 	uchar	chan;
 	uchar	trecur;		// to detect loops
 	uchar	printed;
@@ -146,7 +147,7 @@ struct	Type
 	uchar	copyany;
 	uchar	local;		// created in this file
 	uchar	deferwidth;
-	uchar	broke;
+	uchar	broke;  	// broken type definition.
 	uchar	isddd;		// TFIELD is ... argument
 	uchar	align;
 
@@ -170,21 +171,25 @@ struct	Type
 	vlong	argwid;
 
 	// most nodes
-	Type*	type;
-	vlong	width;		// offset in TFIELD, width in all others
+	Type*	type;   	// actual type for TFIELD, element type for TARRAY, TCHAN, TMAP, TPTRxx
+	vlong	width;  	// offset in TFIELD, width in all others
 
 	// TFIELD
-	Type*	down;		// also used in TMAP
+	Type*	down;		// next struct field, also key type in TMAP
+	Type*	outer;		// outer struct
 	Strlit*	note;		// literal string annotation
 
 	// TARRAY
-	int32	bound;		// negative is dynamic array
+	vlong	bound;		// negative is dynamic array
 
 	int32	maplineno;	// first use of TFORW as map key
 	int32	embedlineno;	// first use of TFORW as embedded type
 	
 	// for TFORW, where to copy the eventual value to
 	NodeList	*copyto;
+	
+	// for usefield
+	Node	*lastfn;
 };
 #define	T	((Type*)0)
 
@@ -215,7 +220,10 @@ enum
 	EscHeap,
 	EscScope,
 	EscNone,
+	EscReturn,
 	EscNever,
+	EscBits = 4,
+	EscMask = (1<<EscBits) - 1,
 };
 
 struct	Node
@@ -233,16 +241,19 @@ struct	Node
 	NodeList*	rlist;
 
 	uchar	op;
+	uchar	nointerface;
 	uchar	ullman;		// sethi/ullman number
 	uchar	addable;	// type of addressability - 0 is not addressable
 	uchar	trecur;		// to detect loops
 	uchar	etype;		// op for OASOP, etype for OTYPE, exclam for export
+	uchar	bounded;	// bounds check unnecessary
 	uchar	class;		// PPARAM, PAUTO, PEXTERN, etc
 	uchar	method;		// OCALLMETH name
 	uchar	embedded;	// ODCLFIELD embedded type
 	uchar	colas;		// OAS resulting from :=
 	uchar	diag;		// already printed error about this
 	uchar	esc;		// EscXXX
+	uchar	noescape;	// func arguments do not escape
 	uchar	funcdepth;
 	uchar	builtin;	// built-in name, like len or close
 	uchar	walkdef;
@@ -256,10 +267,10 @@ struct	Node
 	uchar	implicit;
 	uchar	addrtaken;	// address taken, even if not moved to heap
 	uchar	dupok;	// duplicate definitions ok (for func)
+	schar	likely; // likeliness of if statement
 
 	// most nodes
 	Type*	type;
-	Type*	realtype;	// as determined by typecheck
 	Node*	orig;		// original form, for printing, and tracking copies of ONAMEs
 
 	// func
@@ -279,7 +290,7 @@ struct	Node
 	Node*	defn;	// ONAME: initializing assignment; OLABEL: labeled statement
 	Node*	pack;	// real package for import . names
 	Node*	curfn;	// function for local variables
-	Type*	paramfld; // TFIELD for this PPARAM
+	Type*	paramfld; // TFIELD for this PPARAM; also for ODOT, curfn
 
 	// ONAME func param with PHEAP
 	Node*	heapaddr;	// temp holding heap address of param
@@ -301,17 +312,19 @@ struct	Node
 
 	// Escape analysis.
 	NodeList* escflowsrc;	// flow(this, src)
-	int	escloopdepth;	// -1: global, 0: not set, function top level:1, increased inside function for every loop or label to mark scopes
+	NodeList* escretval;	// on OCALLxxx, list of dummy return values
+	int	escloopdepth;	// -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
 
 	Sym*	sym;		// various
 	int32	vargen;		// unique name for OTYPE/ONAME
 	int32	lineno;
 	int32	endlineno;
 	vlong	xoffset;
-	int32	stkdelta;	// offset added by stack frame compaction phase.
+	vlong	stkdelta;	// offset added by stack frame compaction phase.
 	int32	ostk;
 	int32	iota;
 	uint32	walkgen;
+	int32	esclevel;
 };
 #define	N	((Node*)0)
 
@@ -345,6 +358,7 @@ enum
 	SymExported	= 1<<2,	// already written out by export
 	SymUniq		= 1<<3,
 	SymSiggen	= 1<<4,
+	SymGcgen	= 1<<5,
 };
 
 struct	Sym
@@ -362,6 +376,7 @@ struct	Sym
 	Label*	label;	// corresponding label (ephemeral)
 	int32	block;		// blocknumber to catch redeclaration
 	int32	lastlineno;	// last declaration for diagnostic
+	Pkg*	origpkg;	// original package for . import
 };
 #define	S	((Sym*)0)
 
@@ -374,6 +389,7 @@ struct	Pkg
 	Sym*	pathsym;
 	char*	prefix;		// escaped path for use in symbol table
 	Pkg*	link;
+	uchar	imported;	// export data of this package was parsed
 	char	exported;	// import line written in export data
 	char	direct;	// imported directly
 };
@@ -398,102 +414,171 @@ struct	Hist
 };
 #define	H	((Hist*)0)
 
+// Node ops.
 enum
 {
 	OXXX,
 
 	// names
-	ONAME,
-	ONONAME,
-	OTYPE,
-	OPACK,
-	OLITERAL,
-
-	// exprs
-	OADD, OSUB, OOR, OXOR, OADDSTR,
-	OADDR,
-	OANDAND,
-	OAPPEND,
-	OARRAYBYTESTR, OARRAYRUNESTR,
-	OSTRARRAYBYTE, OSTRARRAYRUNE,
-	OAS, OAS2, OAS2FUNC, OAS2RECV, OAS2MAPR, OAS2DOTTYPE,
-	OASOP,
-	OBAD,
-	OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
-	OCAP,
-	OCLOSE,
-	OCLOSURE,
-	OCMPIFACE, OCMPSTR,
-	OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT, OPTRLIT,
-	OCONV, OCONVIFACE, OCONVNOP,
-	OCOPY,
-	ODCL, ODCLFUNC, ODCLFIELD, ODCLCONST, ODCLTYPE,
-	ODELETE,
-	ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
-	ODOTTYPE,
-	ODOTTYPE2,
-	OEQ, ONE, OLT, OLE, OGE, OGT,
-	OIND,
-	OINDEX, OINDEXMAP,
-	OKEY, OPARAM,
-	OLEN,
-	OMAKE, OMAKECHAN, OMAKEMAP, OMAKESLICE,
-	OHMUL, ORRC, OLRC,	// high-mul and rotate-carry
-	OMUL, ODIV, OMOD, OLSH, ORSH, OAND, OANDNOT,
-	ONEW,
-	ONOT, OCOM, OPLUS, OMINUS,
-	OOROR,
-	OPANIC, OPRINT, OPRINTN,
-	OPAREN,
-	OSEND,
-	OSLICE, OSLICEARR, OSLICESTR,
-	ORECOVER,
-	ORECV,
-	ORUNESTR,
-	OSELRECV,
-	OSELRECV2,
-	OIOTA,
-	OREAL, OIMAG, OCOMPLEX,
-
-	// stmts
-	OBLOCK,
-	OBREAK,
-	OCASE, OXCASE,
-	OCONTINUE,
-	ODEFER,
-	OEMPTY,
-	OFALL, OXFALL,
-	OFOR,
-	OGOTO,
-	OIF,
-	OLABEL,
-	OPROC,
-	ORANGE,
-	ORETURN,
-	OSELECT,
-	OSWITCH,
-	OTYPESW,	// l = r.(type)
+	ONAME,	// var, const or func name
+	ONONAME,	// unnamed arg or return value: f(int, string) (int, error) { etc }
+	OTYPE,	// type name
+	OPACK,	// import
+	OLITERAL, // literal
+
+	// expressions
+	OADD,	// x + y
+	OSUB,	// x - y
+	OOR,	// x | y
+	OXOR,	// x ^ y
+	OADDSTR,	// s + "foo"
+	OADDR,	// &x
+	OANDAND,	// b0 && b1
+	OAPPEND,	// append
+	OARRAYBYTESTR,	// string(bytes)
+	OARRAYRUNESTR,	// string(runes)
+	OSTRARRAYBYTE,	// []byte(s)
+	OSTRARRAYRUNE,	// []rune(s)
+	OAS,	// x = y or x := y
+	OAS2,	// x, y, z = xx, yy, zz
+	OAS2FUNC,	// x, y = f()
+	OAS2RECV,	// x, ok = <-c
+	OAS2MAPR,	// x, ok = m["foo"]
+	OAS2DOTTYPE,	// x, ok = I.(int)
+	OASOP,	// x += y
+	OCALL,	// function call, method call or type conversion, possibly preceded by defer or go.
+	OCALLFUNC,	// f()
+	OCALLMETH,	// t.Method()
+	OCALLINTER,	// err.Error()
+	OCAP,	// cap
+	OCLOSE,	// close
+	OCLOSURE,	// f = func() { etc }
+	OCMPIFACE,	// err1 == err2
+	OCMPSTR,	// s1 == s2
+	OCOMPLIT,	// composite literal, typechecking may convert to a more specific OXXXLIT.
+	OMAPLIT,	// M{"foo":3, "bar":4}
+	OSTRUCTLIT,	// T{x:3, y:4}
+	OARRAYLIT,	// [2]int{3, 4}
+	OPTRLIT,	// &T{x:3, y:4}
+	OCONV,	// var i int; var u uint; i = int(u)
+	OCONVIFACE,	// I(t)
+	OCONVNOP,	// type Int int; var i int; var j Int; i = int(j)
+	OCOPY,	// copy
+	ODCL,	// var x int
+	ODCLFUNC,	// func f() or func (r) f()
+	ODCLFIELD,	// struct field, interface field, or func/method argument/return value.
+	ODCLCONST,	// const pi = 3.14
+	ODCLTYPE,	// type Int int
+	ODELETE,	// delete
+	ODOT,	// t.x
+	ODOTPTR,	// p.x that is implicitly (*p).x
+	ODOTMETH,	// t.Method
+	ODOTINTER,	// err.Error
+	OXDOT,	// t.x, typechecking may convert to a more specific ODOTXXX.
+	ODOTTYPE,	// e = err.(MyErr)
+	ODOTTYPE2,	// e, ok = err.(MyErr)
+	OEQ,	// x == y
+	ONE,	// x != y
+	OLT,	// x < y
+	OLE,	// x <= y
+	OGE,	// x >= y
+	OGT,	// x > y
+	OIND,	// *p
+	OINDEX,	// a[i]
+	OINDEXMAP,	// m[s]
+	OKEY,	// The x:3 in t{x:3, y:4}, the 1:2 in a[1:2], the 2:20 in [3]int{2:20}, etc.
+	OPARAM,	// The on-stack copy of a parameter or return value that escapes.
+	OLEN,	// len
+	OMAKE,	// make, typechecking may convert to a more specfic OMAKEXXX.
+	OMAKECHAN,	// make(chan int)
+	OMAKEMAP,	// make(map[string]int)
+	OMAKESLICE,	// make([]int, 0)
+	OMUL,	// x * y
+	ODIV,	// x / y
+	OMOD,	// x % y
+	OLSH,	// x << u
+	ORSH,	// x >> u
+	OAND,	// x & y
+	OANDNOT,	// x &^ y
+	ONEW,	// new
+	ONOT,	// !b
+	OCOM,	// ^x
+	OPLUS,	// +x
+	OMINUS,	// -y
+	OOROR,	// b1 || b2
+	OPANIC,	// panic
+	OPRINT,	// print
+	OPRINTN,	// println
+	OPAREN,	// (x)
+	OSEND,	// c <- x
+	OSLICE,	// v[1:2], typechecking may convert to a more specfic OSLICEXXX.
+	OSLICEARR,	// a[1:2]
+	OSLICESTR,	// s[1:2]
+	ORECOVER,	// recover
+	ORECV,	// <-c
+	ORUNESTR,	// string(i)
+	OSELRECV,	// case x = <-c:
+	OSELRECV2,	// case x, ok = <-c:
+	OIOTA,	// iota
+	OREAL,	// real
+	OIMAG,	// imag
+	OCOMPLEX,	// complex
+
+	// statements
+	OBLOCK,	// block of code
+	OBREAK,	// break
+	OCASE,	// case, after being verified by swt.c's casebody.
+	OXCASE,	// case, before verification.
+	OCONTINUE,	// continue
+	ODEFER,	// defer
+	OEMPTY,	// no-op
+	OFALL,	// fallthrough, after being verified by swt.c's casebody.
+	OXFALL,	// fallthrough, before verification.
+	OFOR,	// for
+	OGOTO,	// goto
+	OIF,	// if
+	OLABEL,	// label:
+	OPROC,	// go
+	ORANGE,	// range
+	ORETURN,	// return
+	OSELECT,	// select
+	OSWITCH,	// switch x
+	OTYPESW,	// switch err.(type)
 
 	// types
-	OTCHAN,
-	OTMAP,
-	OTSTRUCT,
-	OTINTER,
-	OTFUNC,
-	OTARRAY,
-	OTPAREN,
+	OTCHAN,	// chan int
+	OTMAP,	// map[string]int
+	OTSTRUCT,	// struct{}
+	OTINTER,	// interface{}
+	OTFUNC,	// func()
+	OTARRAY,	// []int, [8]int, [N]int or [...]int
+	OTPAREN,	// (T)
 
 	// misc
-	ODDD,
-	ODDDARG,
-	OINLCALL,	// intermediary representation of an inlined call
-	OITAB,	// itable word of interface value
-
-	// for back ends
-	OCMP, ODEC, OEXTEND, OINC, OREGISTER, OINDREG,
+	ODDD,	// func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}.
+	ODDDARG,	// func f(args ...int), introduced by escape analysis.
+	OINLCALL,	// intermediary representation of an inlined call.
+	OEFACE,	// itable and data words of an empty-interface value.
+	OITAB,	// itable word of an interface value.
+	OCLOSUREVAR, // variable reference at beginning of closure function
+	OCFUNC,	// reference to c function pointer (not go func value)
+
+	// arch-specific registers
+	OREGISTER,	// a register, such as AX.
+	OINDREG,	// offset plus indirect of a register, such as 8(SP).
+
+	// 386/amd64-specific opcodes
+	OCMP,	// compare: ACMP.
+	ODEC,	// decrement: ADEC.
+	OINC,	// increment: AINC.
+	OEXTEND,	// extend: ACWD/ACDQ/ACQO.
+	OHMUL, // high mul: AMUL/AIMUL for unsigned/signed (OMUL uses AIMUL for both).
+	OLROT,	// left rotate: AROL.
+	ORROTC, // right rotate-carry: ARCR.
 
 	OEND,
 };
+
 enum
 {
 	Txxx,			// 0
@@ -539,6 +624,7 @@ enum
 
 	NTYPE,
 };
+
 enum
 {
 	CTxxx,
@@ -562,18 +648,21 @@ enum
 	Cboth = Crecv | Csend,
 };
 
+// declaration context
 enum
 {
 	Pxxx,
 
-	PEXTERN,	// declaration context
-	PAUTO,
-	PPARAM,
-	PPARAMOUT,
-	PPARAMREF,	// param passed by reference
-	PFUNC,
+	PEXTERN,	// global variable
+	PAUTO,		// local variables
+	PPARAM,		// input arguments
+	PPARAMOUT,	// output results
+	PPARAMREF,	// closure variable reference
+	PFUNC,		// global function
 
-	PHEAP = 1<<7,
+	PDISCARD,	// discard during parse of duplicate import
+
+	PHEAP = 1<<7,	// an extra bit to identify an escaped variable
 };
 
 enum
@@ -606,7 +695,6 @@ typedef	struct	Var	Var;
 struct	Var
 {
 	vlong	offset;
-	Sym*	gotype;
 	Node*	node;
 	int	width;
 	char	name;
@@ -756,7 +844,7 @@ EXTERN	int	safemode;
 EXTERN	char	namebuf[NSYMB];
 EXTERN	char	lexbuf[NSYMB];
 EXTERN	char	litbuf[NSYMB];
-EXTERN	char	debug[256];
+EXTERN	int	debug[256];
 EXTERN	Sym*	hash[NHASH];
 EXTERN	Sym*	importmyname;	// my name for package
 EXTERN	Pkg*	localpkg;	// package being compiled
@@ -764,11 +852,15 @@ EXTERN	Pkg*	importpkg;	// package being imported
 EXTERN	Pkg*	structpkg;	// package that declared struct, during import
 EXTERN	Pkg*	builtinpkg;	// fake package for builtins
 EXTERN	Pkg*	gostringpkg;	// fake pkg for Go strings
+EXTERN	Pkg*	itabpkg;	// fake pkg for itab cache
 EXTERN	Pkg*	runtimepkg;	// package runtime
+EXTERN	Pkg*	racepkg;	// package runtime/race
 EXTERN	Pkg*	stringpkg;	// fake package for C strings
-EXTERN	Pkg*	typepkg;	// fake package for runtime type info
+EXTERN	Pkg*	typepkg;	// fake package for runtime type info (headers)
+EXTERN	Pkg*	typelinkpkg;	// fake package for runtime type info (data)
 EXTERN	Pkg*	weaktypepkg;	// weak references to runtime type info
 EXTERN	Pkg*	unsafepkg;	// package unsafe
+EXTERN	Pkg*	trackpkg;	// fake package for field tracking
 EXTERN	Pkg*	phash[128];
 EXTERN	int	tptr;		// either TPTR32 or TPTR64
 extern	char*	runtimeimport;
@@ -815,6 +907,7 @@ EXTERN	NodeList*	externdcl;
 EXTERN	NodeList*	closures;
 EXTERN	NodeList*	exportlist;
 EXTERN	NodeList*	importlist;	// imported functions and methods with inlinable bodies
+EXTERN	NodeList*	funcsyms;
 EXTERN	int	dclcontext;		// PEXTERN/PAUTO
 EXTERN	int	incannedimport;
 EXTERN	int	statuniqgen;		// name generator for static temps
@@ -823,8 +916,8 @@ EXTERN	int	loophack;
 EXTERN	int32	iota;
 EXTERN	NodeList*	lastconst;
 EXTERN	Node*	lasttype;
-EXTERN	int32	maxarg;
-EXTERN	int32	stksize;		// stack size for current frame
+EXTERN	vlong	maxarg;
+EXTERN	vlong	stksize;		// stack size for current frame
 EXTERN	int32	blockgen;		// max block number
 EXTERN	int32	block;			// current block number
 EXTERN	int	hasdefer;		// flag that curfn has defer statetment
@@ -832,12 +925,14 @@ EXTERN	int	hasdefer;		// flag that curfn has defer statetment
 EXTERN	Node*	curfn;
 
 EXTERN	int	widthptr;
+EXTERN	int	widthint;
 
 EXTERN	Node*	typesw;
 EXTERN	Node*	nblank;
 
 extern	int	thechar;
 extern	char*	thestring;
+EXTERN	int  	use_sse;
 
 EXTERN	char*	hunk;
 EXTERN	int32	nhunk;
@@ -846,6 +941,14 @@ EXTERN	int32	thunk;
 EXTERN	int	funcdepth;
 EXTERN	int	typecheckok;
 EXTERN	int	compiling_runtime;
+EXTERN	int	compiling_wrappers;
+EXTERN	int	pure_go;
+EXTERN	int	flag_race;
+EXTERN	int	flag_largemodel;
+EXTERN	int	noescape;
+
+EXTERN	int	nointerface;
+EXTERN	int	fieldtrack_enabled;
 
 /*
  *	y.tab.c
@@ -860,7 +963,7 @@ void	checkwidth(Type *t);
 void	defercheckwidth(void);
 void	dowidth(Type *t);
 void	resumecheckwidth(void);
-uint32	rnd(uint32 o, uint32 r);
+vlong	rnd(vlong o, vlong r);
 void	typeinit(void);
 
 /*
@@ -898,9 +1001,11 @@ void	defaultlit(Node **np, Type *t);
 void	defaultlit2(Node **lp, Node **rp, int force);
 void	evconst(Node *n);
 int	isconst(Node *n, int ct);
+int	isgoconst(Node *n);
 Node*	nodcplxlit(Val r, Val i);
 Node*	nodlit(Val v);
 long	nonnegconst(Node *n);
+int	doesoverflow(Val v, Type *t);
 void	overflow(Val v, Type *t);
 int	smallintconst(Node *n);
 Val	toint(Val v);
@@ -910,7 +1015,7 @@ Mpflt*	truncfltlit(Mpflt *oldv, Type *t);
  *	cplx.c
  */
 void	complexadd(int op, Node *nl, Node *nr, Node *res);
-void	complexbool(int op, Node *nl, Node *nr, int true, Prog *to);
+void	complexbool(int op, Node *nl, Node *nr, int true, int likely, Prog *to);
 void	complexgen(Node *n, Node *res);
 void	complexminus(Node *nl, Node *res);
 void	complexmove(Node *f, Node *t);
@@ -921,10 +1026,10 @@ void	nodfconst(Node *n, Type *t, Mpflt* fval);
 /*
  *	dcl.c
  */
-void	addmethod(Sym *sf, Type *t, int local);
+void	addmethod(Sym *sf, Type *t, int local, int nointerface);
 void	addvar(Node *n, Type *t, int ctxt);
 NodeList*	checkarglist(NodeList *all, int input);
-Node*	colas(NodeList *left, NodeList *right);
+Node*	colas(NodeList *left, NodeList *right, int32 lno);
 void	colasdefn(NodeList *left, Node *defn);
 NodeList*	constiter(NodeList *vl, Node *t, NodeList *cl);
 Node*	dclname(Sym *s);
@@ -954,6 +1059,7 @@ Node*	typedcl0(Sym *s);
 Node*	typedcl1(Node *n, Node *t, int local);
 Node*	typenod(Type *t);
 NodeList*	variter(NodeList *vl, Node *t, NodeList *el);
+Sym*	funcsym(Sym*);
 
 /*
  *	esc.c
@@ -987,6 +1093,8 @@ void	dumplist(char *s, NodeList *l);
 void	addrescapes(Node *n);
 void	cgen_as(Node *nl, Node *nr);
 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	checklabels(void);
 int	dotoffset(Node *n, int *oary, Node **nn);
@@ -1115,8 +1223,11 @@ void	dumptypestructs(void);
 Type*	methodfunc(Type *f, Type*);
 Node*	typename(Type *t);
 Sym*	typesym(Type *t);
+Sym*	typenamesym(Type *t);
+Sym*	tracksym(Type *t);
 Sym*	typesymprefix(char *prefix, Type *t);
 int	haspointers(Type *t);
+void	usefield(Node*);
 
 /*
  *	select.c
@@ -1214,6 +1325,7 @@ Node*	safeexpr(Node *n, NodeList **init);
 void	saveerrors(void);
 Node*	cheapexpr(Node *n, NodeList **init);
 Node*	localexpr(Node *n, Type *t, NodeList **init);
+void	saveorignode(Node *n);
 int32	setlineno(Node *n);
 void	setmaxarg(Type *t);
 Type*	shallow(Type *t);
@@ -1274,6 +1386,7 @@ void	walkexprlistsafe(NodeList *l, NodeList **init);
 void	walkstmt(Node **np);
 void	walkstmtlist(NodeList *l);
 Node*	conv(Node*, Type*);
+int	candiscard(Node*);
 
 /*
  *	arch-specific ggen.c/gsubr.c/gobj.c/pgen.c
@@ -1302,7 +1415,8 @@ EXTERN	Node*	nodfp;
 
 int	anyregalloc(void);
 void	betypeinit(void);
-void	bgen(Node *n, int true, Prog *to);
+void	bgen(Node *n, int true, int likely, Prog *to);
+void	checkref(Node*);
 void	cgen(Node*, Node*);
 void	cgen_asop(Node *n);
 void	cgen_call(Node *n, int proc);
@@ -1323,8 +1437,8 @@ void	gdata(Node*, Node*, int);
 void	gdatacomplex(Node*, Mpcplx*);
 void	gdatastring(Node*, Strlit*);
 void	genembedtramp(Type*, Type*, Sym*, int iface);
-void	ggloblnod(Node *nam, int32 width);
-void	ggloblsym(Sym *s, int32 width, int dupok);
+void	ggloblnod(Node *nam);
+void	ggloblsym(Sym *s, int32 width, int dupok, int rodata);
 Prog*	gjmp(Prog*);
 void	gused(Node*);
 int	isfat(Type*);
@@ -1364,3 +1478,8 @@ void	zname(Biobuf *b, Sym *s, int t);
 #pragma	varargck	type	"V"	Val*
 #pragma	varargck	type	"Y"	char*
 #pragma	varargck	type	"Z"	Strlit*
+
+/*
+ *	racewalk.c
+ */
+void	racewalk(Node *fn);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index f950587..794961e 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -37,8 +37,8 @@ static void fixlbrace(int);
 // |sed 's/.*	//' |9 fmt -l1 |sort |9 fmt -l50 | sed 's/^/%xxx		/'
 
 %token	<val>	LLITERAL
-%token	<i>	LASOP
-%token	<sym>	LBREAK LCASE LCHAN LCOLAS LCONST LCONTINUE LDDD
+%token	<i>	LASOP LCOLAS
+%token	<sym>	LBREAK LCASE LCHAN LCONST LCONTINUE LDDD
 %token	<sym>	LDEFAULT LDEFER LELSE LFALL LFOR LFUNC LGO LGOTO
 %token	<sym>	LIF LIMPORT LINTERFACE LMAP LNAME
 %token	<sym>	LPACKAGE LRANGE LRETURN LSELECT LSTRUCT LSWITCH
@@ -54,10 +54,10 @@ static void fixlbrace(int);
 %type	<node>	stmt ntype
 %type	<node>	arg_type
 %type	<node>	case caseblock
-%type	<node>	compound_stmt dotname embed expr complitexpr
+%type	<node>	compound_stmt dotname embed expr complitexpr bare_complitexpr
 %type	<node>	expr_or_type
 %type	<node>	fndcl hidden_fndcl fnliteral
-%type	<node>	for_body for_header for_stmt if_header if_stmt else non_dcl_stmt
+%type	<node>	for_body for_header for_stmt if_header if_stmt non_dcl_stmt
 %type	<node>	interfacedcl keyval labelname name
 %type	<node>	name_or_type non_expr_type
 %type	<node>	new_name dcl_name oexpr typedclname
@@ -70,7 +70,7 @@ static void fixlbrace(int);
 
 %type	<list>	xdcl fnbody fnres loop_body dcl_name_list
 %type	<list>	new_name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list
-%type	<list>	oexpr_list caseblock_list stmt_list oarg_type_list_ocomma arg_type_list
+%type	<list>	oexpr_list caseblock_list elseif elseif_list else stmt_list oarg_type_list_ocomma arg_type_list
 %type	<list>	interfacedcl_list vardcl vardcl_list structdcl structdcl_list
 %type	<list>	common_dcl constdcl constdcl1 constdcl_list typedcl_list
 
@@ -405,6 +405,20 @@ simple_stmt:
 	expr
 	{
 		$$ = $1;
+
+		// These nodes do not carry line numbers.
+		// Since a bare name used as an expression is an error,
+		// introduce a wrapper node to give the correct line.
+		switch($$->op) {
+		case ONAME:
+		case ONONAME:
+		case OTYPE:
+		case OPACK:
+		case OLITERAL:
+			$$ = nod(OPAREN, $$, N);
+			$$->implicit = 1;
+			break;
+		}
 	}
 |	expr LASOP expr
 	{
@@ -437,7 +451,7 @@ simple_stmt:
 				$$->left = dclname($1->n->sym);  // it's a colas, so must not re-use an oldname.
 			break;
 		}
-		$$ = colas($1, $3);
+		$$ = colas($1, $3, $2);
 	}
 |	expr LINC
 	{
@@ -496,7 +510,7 @@ case:
 		// done in casebody()
 		markdcl();
 		$$ = nod(OXCASE, N, N);
-		$$->list = list1(colas($2, list1($4)));
+		$$->list = list1(colas($2, list1($4), $3));
 	}
 |	LDEFAULT ':'
 	{
@@ -661,25 +675,56 @@ if_stmt:
 	{
 		$3->nbody = $5;
 	}
-	else
+	elseif_list else
 	{
-		popdcl();
+		Node *n;
+		NodeList *nn;
+
 		$$ = $3;
-		if($7 != N)
-			$$->nelse = list1($7);
+		n = $3;
+		popdcl();
+		for(nn = concat($7, $8); nn; nn = nn->next) {
+			if(nn->n->op == OIF)
+				popdcl();
+			n->nelse = list1(nn->n);
+			n = nn->n;
+		}
 	}
 
-else:
+elseif:
+	LELSE LIF 
 	{
-		$$ = N;
+		markdcl();
 	}
-|	LELSE if_stmt
+	if_header loop_body
 	{
-		$$ = $2;
+		if($4->ntest == N)
+			yyerror("missing condition in if statement");
+		$4->nbody = $5;
+		$$ = list1($4);
+	}
+
+elseif_list:
+	{
+		$$ = nil;
+	}
+|	elseif_list elseif
+	{
+		$$ = concat($1, $2);
+	}
+
+else:
+	{
+		$$ = nil;
 	}
 |	LELSE compound_stmt
 	{
-		$$ = $2;
+		NodeList *node;
+		
+		node = mal(sizeof *node);
+		node->n = $2;
+		node->end = node;
+		$$ = node;
 	}
 
 switch_stmt:
@@ -902,7 +947,7 @@ pexpr_no_paren:
 		$$ = nod(OSLICE, $1, nod(OKEY, $3, $5));
 	}
 |	pseudocall
-|	convtype '(' expr ')'
+|	convtype '(' expr ocomma ')'
 	{
 		// conversion
 		$$ = nod(OCALL, $1, N);
@@ -943,6 +988,30 @@ keyval:
 		$$ = nod(OKEY, $1, $3);
 	}
 
+bare_complitexpr:
+	expr
+	{
+		// These nodes do not carry line numbers.
+		// Since a composite literal commonly spans several lines,
+		// the line number on errors may be misleading.
+		// Introduce a wrapper node to give the correct line.
+		$$ = $1;
+		switch($$->op) {
+		case ONAME:
+		case ONONAME:
+		case OTYPE:
+		case OPACK:
+		case OLITERAL:
+			$$ = nod(OPAREN, $$, N);
+			$$->implicit = 1;
+		}
+	}
+|	'{' start_complit braced_keyval_list '}'
+	{
+		$$ = $2;
+		$$->list = $3;
+	}
+
 complitexpr:
 	expr
 |	'{' start_complit braced_keyval_list '}'
@@ -966,6 +1035,7 @@ pexpr:
 		case OPACK:
 		case OTYPE:
 		case OLITERAL:
+		case OTYPESW:
 			$$ = nod(OPAREN, $$, N);
 		}
 	}
@@ -1030,10 +1100,16 @@ sym:
 hidden_importsym:
 	'@' LLITERAL '.' LNAME
 	{
+		Pkg *p;
+
 		if($2.u.sval->len == 0)
-			$$ = pkglookup($4->name, importpkg);
-		else
-			$$ = pkglookup($4->name, mkpkg($2.u.sval));
+			p = importpkg;
+		else {
+			if(isbadimport($2.u.sval))
+				errorexit();
+			p = mkpkg($2.u.sval);
+		}
+		$$ = pkglookup($4->name, p);
 	}
 
 name:
@@ -1201,8 +1277,11 @@ xfndcl:
 		$$ = $2;
 		if($$ == N)
 			break;
+		if(noescape && $3 != nil)
+			yyerror("can only use //go:noescape with external func implementations");
 		$$->nbody = $3;
 		$$->endlineno = lineno;
+		$$->noescape = noescape;
 		funcbody($$);
 	}
 
@@ -1269,6 +1348,7 @@ fndcl:
 		$$->nname = methodname1($$->shortname, rcvr->right);
 		$$->nname->defn = $$;
 		$$->nname->ntype = t;
+		$$->nname->nointerface = nointerface;
 		declare($$->nname, PFUNC);
 
 		funchdr($$);
@@ -1287,8 +1367,10 @@ hidden_fndcl:
 
 		importsym(s, ONAME);
 		if(s->def != N && s->def->op == ONAME) {
-			if(eqtype(t, s->def->type))
+			if(eqtype(t, s->def->type)) {
+				dclcontext = PDISCARD;  // since we skip funchdr below
 				break;
+			}
 			yyerror("inconsistent definition for func %S during import\n\t%T\n\t%T", s, s->def->type, t);
 		}
 
@@ -1304,7 +1386,8 @@ hidden_fndcl:
 		$$->type = functype($2->n, $6, $8);
 
 		checkwidth($$->type);
-		addmethod($4, $$->type, 0);
+		addmethod($4, $$->type, 0, nointerface);
+		nointerface = 0;
 		funchdr($$);
 		
 		// inl.c's inlnode in on a dotmeth node expects to find the inlineable body as
@@ -1381,6 +1464,8 @@ xdcl_list:
 		$$ = concat($1, $2);
 		if(nsyntaxerrors == 0)
 			testdclstack();
+		nointerface = 0;
+		noescape = 0;
 	}
 
 vardcl_list:
@@ -1719,7 +1804,7 @@ keyval_list:
 	{
 		$$ = list1($1);
 	}
-|	complitexpr
+|	bare_complitexpr
 	{
 		$$ = list1($1);
 	}
@@ -1727,7 +1812,7 @@ keyval_list:
 	{
 		$$ = list($1, $3);
 	}
-|	keyval_list ',' complitexpr
+|	keyval_list ',' bare_complitexpr
 	{
 		$$ = list($1, $3);
 	}
@@ -1818,8 +1903,10 @@ hidden_import:
 	}
 |	LFUNC hidden_fndcl fnbody ';'
 	{
-		if($2 == N)
+		if($2 == N) {
+			dclcontext = PEXTERN;  // since we skip the funcbody below
 			break;
+		}
 
 		$2->inl = $3;
 
@@ -1828,7 +1915,7 @@ hidden_import:
 
 		if(debug['E']) {
 			print("import [%Z] func %lN \n", importpkg->path, $2);
-			if(debug['l'] > 2 && $2->inl)
+			if(debug['m'] > 2 && $2->inl)
 				print("inl body:%+H\n", $2->inl);
 		}
 	}
@@ -2039,6 +2126,8 @@ hidden_constant:
 			mpaddfixfix($2->val.u.xval, $4->val.u.xval, 0);
 			break;
 		}
+		$4->val.u.cval->real = $4->val.u.cval->imag;
+		mpmovecflt(&$4->val.u.cval->imag, 0.0);
 		$$ = nodcplxlit($2->val, $4->val);
 	}
 
diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c
index be402cc..918d371 100644
--- a/src/cmd/gc/init.c
+++ b/src/cmd/gc/init.c
@@ -55,6 +55,10 @@ anyinit(NodeList *n)
 		case ODCLTYPE:
 		case OEMPTY:
 			break;
+		case OAS:
+			if(isblank(l->n->left) && candiscard(l->n->right))
+				break;
+			// fall through
 		default:
 			return 1;
 		}
diff --git a/src/cmd/gc/inl.c b/src/cmd/gc/inl.c
index b2b1faf..1cc13a3 100644
--- a/src/cmd/gc/inl.c
+++ b/src/cmd/gc/inl.c
@@ -13,7 +13,7 @@
 //      0: disabled
 //      1: 40-nodes leaf functions, oneliners, lazy typechecking (default)
 //      2: early typechecking of all imported bodies 
-//      3: 
+//      3: allow variadic functions
 //      4: allow non-leaf functions , (breaks runtime.Caller)
 //      5: transitive inlining
 //
@@ -39,9 +39,10 @@ static int	ishairylist(NodeList *ll, int *budget);
 // Used by inlcalls
 static void	inlnodelist(NodeList *l);
 static void	inlnode(Node **np);
-static void	mkinlcall(Node **np, Node *fn);
+static void	mkinlcall(Node **np, Node *fn, int isddd);
 static Node*	inlvar(Node *n);
 static Node*	retvar(Type *n, int i);
+static Node*	argvar(Type *n, int i);
 static Node*	newlabel(void);
 static Node*	inlsubst(Node *n);
 static NodeList* inlsubstlist(NodeList *l);
@@ -82,20 +83,18 @@ typecheckinl(Node *fn)
 	Pkg *pkg;
 	int save_safemode, lno;
 
-	if(fn->typecheck)
-		return;
-
 	lno = setlineno(fn);
 
-	if (debug['m']>2)
-		print("typecheck import [%S] %lN { %#H }\n", fn->sym, fn, fn->inl);
-
-	// typecheckinl is only used for imported functions;
+	// typecheckinl is only for imported functions;
 	// their bodies may refer to unsafe as long as the package
 	// was marked safe during import (which was checked then).
+	// the ->inl of a local function has been typechecked before caninl copied it.
 	pkg = fnpkg(fn);
 	if (pkg == localpkg || pkg == nil)
-		fatal("typecheckinl on local function %lN", fn);
+		return; // typecheckinl on local function
+
+	if (debug['m']>2)
+		print("typecheck import [%S] %lN { %#H }\n", fn->sym, fn, fn->inl);
 
 	save_safemode = safemode;
 	safemode = 0;
@@ -103,7 +102,6 @@ typecheckinl(Node *fn)
 	savefn = curfn;
 	curfn = fn;
 	typechecklist(fn->inl, Etop);
-	fn->typecheck = 1;
 	curfn = savefn;
 
 	safemode = save_safemode;
@@ -111,10 +109,9 @@ typecheckinl(Node *fn)
 	lineno = lno;
 }
 
-// Caninl determines whether fn is inlineable. Currently that means:
-// fn is exactly 1 statement, either a return or an assignment, and
-// some temporary constraints marked TODO.  If fn is inlineable, saves
-// fn->nbody in fn->inl and substitutes it with a copy.
+// Caninl determines whether fn is inlineable.
+// If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy.
+// fn and ->nbody will already have been typechecked.
 void
 caninl(Node *fn)
 {
@@ -131,10 +128,14 @@ caninl(Node *fn)
 	if(fn->nbody == nil)
 		return;
 
+	if(fn->typecheck == 0)
+		fatal("caninl on non-typechecked function %N", fn);
+
 	// can't handle ... args yet
-	for(t=fn->type->type->down->down->type; t; t=t->down)
-		if(t->isddd)
-			return;
+	if(debug['l'] < 3)
+		for(t=fn->type->type->down->down->type; t; t=t->down)
+			if(t->isddd)
+				return;
 
 	budget = 40;  // allowed hairyness
 	if(ishairylist(fn->nbody, &budget))
@@ -145,8 +146,6 @@ caninl(Node *fn)
 
 	fn->nname->inl = fn->nbody;
 	fn->nbody = inlcopylist(fn->nname->inl);
-	// nbody will have been typechecked, so we can set this:
-	fn->typecheck = 1;
 
 	// hack, TODO, check for better way to link method nodes back to the thing with the ->inl
 	// this is so export can find the body of a method
@@ -195,19 +194,11 @@ ishairy(Node *n, int *budget)
 	case OSWITCH:
 	case OPROC:
 	case ODEFER:
-	case ODCL:	// declares locals as globals b/c of @"". qualification
 	case ODCLTYPE:  // can't print yet
 	case ODCLCONST:  // can't print yet
 		return 1;
 
 		break;
-	case OAS:
-		// x = <N> zero initializing assignments aren't representible in export yet.
-		// alternatively we may just skip them in printing and hope their DCL printed
-		// as a var will regenerate it
-		if(n->right == N)
-			return 1;
-		break;
 	}
 
 	(*budget)--;
@@ -366,8 +357,8 @@ inlnode(Node **np)
 		}
 
 	case OCLOSURE:
-		// TODO do them here instead of in lex.c phase 6b, so escape analysis
-		// can avoid more heapmoves.
+		// TODO do them here (or earlier) instead of in walkcallclosure,
+		// so escape analysis can avoid more heapmoves.
 		return;
 	}
 
@@ -464,10 +455,10 @@ inlnode(Node **np)
 		if(debug['m']>3)
 			print("%L:call to func %+N\n", n->lineno, n->left);
 		if(n->left->inl)	// normal case
-			mkinlcall(np, n->left);
+			mkinlcall(np, n->left, n->isddd);
 		else if(n->left->op == ONAME && n->left->left && n->left->left->op == OTYPE && n->left->right &&  n->left->right->op == ONAME)  // methods called as functions
 			if(n->left->sym->def)
-				mkinlcall(np, n->left->sym->def);
+				mkinlcall(np, n->left->sym->def, n->isddd);
 		break;
 
 	case OCALLMETH:
@@ -480,7 +471,7 @@ inlnode(Node **np)
 		if(n->left->type->nname == N) 
 			fatal("no function definition for [%p] %+T\n", n->left->type, n->left->type);
 
-		mkinlcall(np, n->left->type->nname);
+		mkinlcall(np, n->left->type->nname, n->isddd);
 
 		break;
 	}
@@ -488,10 +479,10 @@ inlnode(Node **np)
 	lineno = lno;
 }
 
-static void	mkinlcall1(Node **np, Node *fn);
+static void	mkinlcall1(Node **np, Node *fn, int isddd);
 
 static void
-mkinlcall(Node **np, Node *fn)
+mkinlcall(Node **np, Node *fn, int isddd)
 {
 	int save_safemode;
 	Pkg *pkg;
@@ -503,7 +494,7 @@ mkinlcall(Node **np, Node *fn)
 	pkg = fnpkg(fn);
 	if(pkg != localpkg && pkg != nil)
 		safemode = 0;
-	mkinlcall1(np, fn);
+	mkinlcall1(np, fn, isddd);
 	safemode = save_safemode;
 }
 
@@ -519,17 +510,25 @@ tinlvar(Type *t)
 	return nblank;
 }
 
+static int inlgen;
+
 // if *np is a call, and fn is a function with an inlinable body, substitute *np with an OINLCALL.
 // On return ninit has the parameter assignments, the nbody is the
 // inlined function body and list, rlist contain the input, output
 // parameters.
 static void
-mkinlcall1(Node **np, Node *fn)
+mkinlcall1(Node **np, Node *fn, int isddd)
 {
 	int i;
+	int chkargcount;
 	Node *n, *call, *saveinlfn, *as, *m;
 	NodeList *dcl, *ll, *ninit, *body;
 	Type *t;
+	// For variadic fn.
+	int variadic, varargcount, multiret;
+	Node *vararg;
+	NodeList *varargs;
+	Type *varargtype, *vararrtype;
 
 	if (fn->inl == nil)
 		return;
@@ -556,6 +555,8 @@ mkinlcall1(Node **np, Node *fn)
 
 	ninit = n->ninit;
 
+//dumplist("ninit pre", ninit);
+
 	if (fn->defn) // local function
 		dcl = fn->defn->dcl;
 	else // imported function
@@ -567,7 +568,10 @@ mkinlcall1(Node **np, Node *fn)
 	for(ll = dcl; ll; ll=ll->next)
 		if(ll->n->op == ONAME) {
 			ll->n->inlvar = inlvar(ll->n);
-			ninit = list(ninit, nod(ODCL, ll->n->inlvar, N));  // otherwise gen won't emit the allocations for heapallocs
+			// Typecheck because inlvar is not necessarily a function parameter.
+			typecheck(&ll->n->inlvar, Erv);
+			if ((ll->n->class&~PHEAP) != PAUTO)
+				ninit = list(ninit, nod(ODCL, ll->n->inlvar, N));  // otherwise gen won't emit the allocations for heapallocs
 			if (ll->n->class == PPARAMOUT)  // we rely on the order being correct here
 				inlretvars = list(inlretvars, ll->n->inlvar);
 		}
@@ -580,49 +584,118 @@ mkinlcall1(Node **np, Node *fn)
 			inlretvars = list(inlretvars, m);
 		}
 
-	// assign arguments to the parameters' temp names
-	as = N;
-	if(fn->type->thistuple) {
+	// assign receiver.
+	if(fn->type->thistuple && n->left->op == ODOTMETH) {
+		// method call with a receiver.
 		t = getthisx(fn->type)->type;
 		if(t != T && t->nname != N && !isblank(t->nname) && !t->nname->inlvar)
 			fatal("missing inlvar for %N\n", t->nname);
-
-		if(n->left->op == ODOTMETH) {
-			if(!n->left->left)
-				fatal("method call without receiver: %+N", n);
-			if(t == T)
-				fatal("method call unknown receiver type: %+N", n);
-			as = nod(OAS, tinlvar(t), n->left->left);
-		} else {  // non-method call to method
-			if(!n->list)
-				fatal("non-method call to method without first arg: %+N", n);
-			if(t != T)
-				as = nod(OAS, tinlvar(t), n->list->n);
-		}
-
+		if(!n->left->left)
+			fatal("method call without receiver: %+N", n);
+		if(t == T)
+			fatal("method call unknown receiver type: %+N", n);
+		as = nod(OAS, tinlvar(t), n->left->left);
 		if(as != N) {
 			typecheck(&as, Etop);
 			ninit = list(ninit, as);
 		}
 	}
 
+	// check if inlined function is variadic.
+	variadic = 0;
+	varargtype = T;
+	varargcount = 0;
+	for(t=fn->type->type->down->down->type; t; t=t->down) {
+		if(t->isddd) {
+			variadic = 1;
+			varargtype = t->type;
+		}
+	}
+	// but if argument is dotted too forget about variadicity.
+	if(variadic && isddd)
+		variadic = 0;
+
+	// check if argument is actually a returned tuple from call.
+	multiret = 0;
+	if(n->list && !n->list->next) {
+		switch(n->list->n->op) {
+		case OCALL:
+		case OCALLFUNC:
+		case OCALLINTER:
+		case OCALLMETH:
+			if(n->list->n->left->type->outtuple > 1)
+				multiret = n->list->n->left->type->outtuple-1;
+		}
+	}
+
+	if(variadic) {
+		varargcount = count(n->list) + multiret;
+		if(n->left->op != ODOTMETH)
+			varargcount -= fn->type->thistuple;
+		varargcount -= fn->type->intuple - 1;
+	}
+
+	// assign arguments to the parameters' temp names
 	as = nod(OAS2, N, N);
-	if(fn->type->intuple > 1 && n->list && !n->list->next) {
-		// TODO check that n->list->n is a call?
-		// TODO: non-method call to T.meth(f()) where f returns t, args...
-		as->rlist = n->list;
-		for(t = getinargx(fn->type)->type; t; t=t->down)
-			as->list = list(as->list, tinlvar(t));		
-	} else {
-		ll = n->list;
-		if(fn->type->thistuple && n->left->op != ODOTMETH) // non method call to method
-			ll=ll->next;  // was handled above in if(thistuple)
+	as->rlist = n->list;
+	ll = n->list;
+
+	// TODO: if len(nlist) == 1 but multiple args, check that n->list->n is a call?
+	if(fn->type->thistuple && n->left->op != ODOTMETH) {
+		// non-method call to method
+		if(!n->list)
+			fatal("non-method call to method without first arg: %+N", n);
+		// append receiver inlvar to LHS.
+		t = getthisx(fn->type)->type;
+		if(t != T && t->nname != N && !isblank(t->nname) && !t->nname->inlvar)
+			fatal("missing inlvar for %N\n", t->nname);
+		if(t == T)
+			fatal("method call unknown receiver type: %+N", n);
+		as->list = list(as->list, tinlvar(t));
+		ll = ll->next; // track argument count.
+	}
 
-		for(t = getinargx(fn->type)->type; t && ll; t=t->down) {
+	// append ordinary arguments to LHS.
+	chkargcount = n->list && n->list->next;
+	vararg = N;    // the slice argument to a variadic call
+	varargs = nil; // the list of LHS names to put in vararg.
+	if(!chkargcount) {
+		// 0 or 1 expression on RHS.
+		for(t = getinargx(fn->type)->type; t; t=t->down) {
+			if(variadic && t->isddd) {
+				vararg = tinlvar(t);
+				for(i=0; i<varargcount && ll; i++) {
+					m = argvar(varargtype, i);
+					varargs = list(varargs, m);
+					as->list = list(as->list, m);
+				}
+				break;
+			}
+			as->list = list(as->list, tinlvar(t));
+		}
+	} else {
+		// match arguments except final variadic (unless the call is dotted itself)
+		for(t = getinargx(fn->type)->type; t;) {
+			if(!ll)
+				break;
+			if(variadic && t->isddd)
+				break;
 			as->list = list(as->list, tinlvar(t));
-			as->rlist = list(as->rlist, ll->n);
+			t=t->down;
 			ll=ll->next;
 		}
+		// match varargcount arguments with variadic parameters.
+		if(variadic && t && t->isddd) {
+			vararg = tinlvar(t);
+			for(i=0; i<varargcount && ll; i++) {
+				m = argvar(varargtype, i);
+				varargs = list(varargs, m);
+				as->list = list(as->list, m);
+				ll=ll->next;
+			}
+			if(i==varargcount)
+				t=t->down;
+		}
 		if(ll || t)
 			fatal("arg count mismatch: %#T  vs %,H\n",  getinargx(fn->type), n->list);
 	}
@@ -632,6 +705,25 @@ mkinlcall1(Node **np, Node *fn)
 		ninit = list(ninit, as);
 	}
 
+	// turn the variadic args into a slice.
+	if(variadic) {
+		as = nod(OAS, vararg, N);
+		if(!varargcount) {
+			as->right = nodnil();
+			as->right->type = varargtype;
+		} else {
+			vararrtype = typ(TARRAY);
+			vararrtype->type = varargtype->type;
+			vararrtype->bound = varargcount;
+
+			as->right = nod(OCOMPLIT, N, typenod(varargtype));
+			as->right->list = varargs;
+			as->right = nod(OSLICE, as->right, nod(OKEY, N, N));
+		}
+		typecheck(&as, Etop);
+		ninit = list(ninit, as);
+	}
+
 	// zero the outparams
 	for(ll = inlretvars; ll; ll=ll->next) {
 		as = nod(OAS, ll->n, N);
@@ -640,12 +732,14 @@ mkinlcall1(Node **np, Node *fn)
 	}
 
 	inlretlabel = newlabel();
+	inlgen++;
 	body = inlsubstlist(fn->inl);
 
 	body = list(body, nod(OGOTO, inlretlabel, N));	// avoid 'not used' when function doesnt have return
 	body = list(body, nod(OLABEL, inlretlabel, N));
 
 	typechecklist(body, Etop);
+//dumplist("ninit post", ninit);
 
 	call = nod(OINLCALL, N, N);
 	call->ninit = ninit;
@@ -655,6 +749,7 @@ mkinlcall1(Node **np, Node *fn)
 	call->typecheck = 1;
 
 	setlno(call, n->lineno);
+//dumplist("call body", body);
 
 	*np = call;
 
@@ -705,7 +800,24 @@ retvar(Type *t, int i)
 {
 	Node *n;
 
-	snprint(namebuf, sizeof(namebuf), ".r%d", i);
+	snprint(namebuf, sizeof(namebuf), "~r%d", i);
+	n = newname(lookup(namebuf));
+	n->type = t->type;
+	n->class = PAUTO;
+	n->used = 1;
+	n->curfn = curfn;   // the calling function, not the called one
+	curfn->dcl = list(curfn->dcl, n);
+	return n;
+}
+
+// Synthesize a variable to store the inlined function's arguments
+// when they come from a multiple return call.
+static Node*
+argvar(Type *t, int i)
+{
+	Node *n;
+
+	snprint(namebuf, sizeof(namebuf), "~arg%d", i);
 	n = newname(lookup(namebuf));
 	n->type = t->type;
 	n->class = PAUTO;
@@ -746,6 +858,7 @@ inlsubstlist(NodeList *ll)
 static Node*
 inlsubst(Node *n)
 {
+	char *p;
 	Node *m, *as;
 	NodeList *ll;
 
@@ -788,6 +901,16 @@ inlsubst(Node *n)
 		typecheck(&m, Etop);
 //		dump("Return after substitution", m);
 		return m;
+	
+	case OGOTO:
+	case OLABEL:
+		m = nod(OXXX, N, N);
+		*m = *n;
+		m->ninit = nil;
+		p = smprint("%s·%d", n->left->sym->name, inlgen);	
+		m->left = newname(lookup(p));
+		free(p);
+		return m;	
 	}
 
 
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 624dfb0..68ae686 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -30,6 +30,8 @@ static void	addidir(char*);
 static int	getlinepragma(void);
 static char *goos, *goarch, *goroot;
 
+#define	BOM	0xFEFF
+
 // Compiler experiments.
 // These are controlled by the GOEXPERIMENT environment
 // variable recorded when the compiler is built.
@@ -38,6 +40,7 @@ static struct {
 	int *val;
 } exper[] = {
 //	{"rune32", &rune32},
+	{"fieldtrack", &fieldtrack_enabled},
 	{nil, nil},
 };
 
@@ -96,7 +99,7 @@ yy_isdigit(int c)
 static int
 yy_isspace(int c)
 {
-	return c >= 0 && c <= 0xFF && isspace(c);
+	return c == ' ' || c == '\t' || c == '\n' || c == '\r';
 }
 
 static int
@@ -130,42 +133,8 @@ enum
 void
 usage(void)
 {
-	print("gc: usage: %cg [flags] file.go...\n", thechar);
-	print("flags:\n");
-	// -A allow use of "any" type, for bootstrapping
-	// -B disable bounds checking
-	// -E print imported declarations
-	// -K warn when lineno is zero
-	// -M print arguments to gmove
-	// -P print peephole diagnostics
-	// -R print optimizer diagnostics
-	// -g print code generation diagnostics
-	// -i print line history
-	// -j print variables to be initialized at runtime
-	// -r print generated helper functions
-	// -s print redundant types in composite literals
-	// -v print more information with -P or -R
-	// -y print declarations in cannedimports (used with -d)
-	// -% print non-static initializers
-	// -+ indicate that the runtime is being compiled
-	print("  -D PATH interpret local imports relative to this import path\n");
-	print("  -I DIR search for packages in DIR\n");
-	print("  -L show full path in file:line prints\n");
-	print("  -N disable optimizations\n");
-	print("  -S print the assembly language\n");
-	print("  -V print the compiler version\n");
-	print("  -W print the parse tree after typing\n");
-	print("  -d print declarations\n");
-	print("  -e no limit on number of errors printed\n");
-	print("  -f print stack frame structure\n");
-	print("  -h panic on an error\n");
-	print("  -l disable inlining\n");
-	print("  -m print optimization decisions\n");
-	print("  -o file specify output file\n");
-	print("  -p assumed import path for this code\n");
-	print("  -u disable package unsafe\n");
-	print("  -w print type checking details\n");
-	print("  -x print lex tokens\n");
+	print("usage: %cg [options] file.go...\n", thechar);
+	flagprint(1);
 	exits("usage");
 }
 
@@ -183,11 +152,23 @@ fault(int s)
 	fatal("fault");
 }
 
+void
+doversion(void)
+{
+	char *p;
+
+	p = expstring();
+	if(strcmp(p, "X:none") == 0)
+		p = "";
+	print("%cg version %s%s%s\n", thechar, getgoversion(), *p ? " " : "", p);
+	exits(0);
+}
+
 int
 main(int argc, char *argv[])
 {
-	int i, c;
-	NodeList *l, *batch;
+	int i;
+	NodeList *l;
 	char *p;
 
 #ifdef	SIGBUS	
@@ -197,25 +178,41 @@ main(int argc, char *argv[])
 
 	localpkg = mkpkg(strlit(""));
 	localpkg->prefix = "\"\"";
-
+	
+	// pseudo-package, for scoping
 	builtinpkg = mkpkg(strlit("go.builtin"));
 
+	// pseudo-package, accessed by import "unsafe"
+	unsafepkg = mkpkg(strlit("unsafe"));
+	unsafepkg->name = "unsafe";
+
+	// real package, referred to by generated runtime calls
+	runtimepkg = mkpkg(strlit("runtime"));
+	runtimepkg->name = "runtime";
+
+	// pseudo-packages used in symbol tables
 	gostringpkg = mkpkg(strlit("go.string"));
 	gostringpkg->name = "go.string";
 	gostringpkg->prefix = "go.string";	// not go%2estring
 
-	runtimepkg = mkpkg(strlit("runtime"));
-	runtimepkg->name = "runtime";
+	itabpkg = mkpkg(strlit("go.itab"));
+	itabpkg->name = "go.itab";
+	itabpkg->prefix = "go.itab";	// not go%2eitab
 
-	typepkg = mkpkg(strlit("type"));
-	typepkg->name = "type";
+	weaktypepkg = mkpkg(strlit("go.weak.type"));
+	weaktypepkg->name = "go.weak.type";
+	weaktypepkg->prefix = "go.weak.type";  // not go%2eweak%2etype
+	
+	typelinkpkg = mkpkg(strlit("go.typelink"));
+	typelinkpkg->name = "go.typelink";
+	typelinkpkg->prefix = "go.typelink"; // not go%2etypelink
 
-	weaktypepkg = mkpkg(strlit("weak.type"));
-	weaktypepkg->name = "weak.type";
-	weaktypepkg->prefix = "weak.type";  // not weak%2etype
+	trackpkg = mkpkg(strlit("go.track"));
+	trackpkg->name = "go.track";
+	trackpkg->prefix = "go.track";  // not go%2etrack
 
-	unsafepkg = mkpkg(strlit("unsafe"));
-	unsafepkg->name = "unsafe";
+	typepkg = mkpkg(strlit("type"));
+	typepkg->name = "type";
 
 	goroot = getgoroot();
 	goos = getgoos();
@@ -224,41 +221,55 @@ main(int argc, char *argv[])
 	setexp();
 
 	outfile = nil;
-	ARGBEGIN {
-	default:
-		c = ARGC();
-		if(c >= 0 && c < sizeof(debug))
-			debug[c]++;
-		break;
-
-	case 'o':
-		outfile = EARGF(usage());
-		break;
-	
-	case 'p':
-		myimportpath = EARGF(usage());
-		break;
+	flagcount("+", "compiling runtime", &compiling_runtime);
+	flagcount("%", "debug non-static initializers", &debug['%']);
+	flagcount("A", "for bootstrapping, allow 'any' type", &debug['A']);
+	flagcount("B", "disable bounds checking", &debug['B']);
+	flagstr("D", "path: set relative path for local imports", &localimport);
+	flagcount("E", "debug symbol export", &debug['E']);
+	flagfn1("I", "dir: add dir to import search path", addidir);
+	flagcount("K", "debug missing line numbers", &debug['K']);
+	flagcount("L", "use full (long) path in error messages", &debug['L']);
+	flagcount("M", "debug move generation", &debug['M']);
+	flagcount("N", "disable optimizations", &debug['N']);
+	flagcount("P", "debug peephole optimizer", &debug['P']);
+	flagcount("R", "debug register optimizer", &debug['R']);
+	flagcount("S", "print assembly listing", &debug['S']);
+	flagfn0("V", "print compiler version", doversion);
+	flagcount("W", "debug parse tree after type checking", &debug['W']);
+	flagcount("complete", "compiling complete package (no C or assembly)", &pure_go);
+	flagcount("d", "debug declarations", &debug['d']);
+	flagcount("e", "no limit on number of errors reported", &debug['e']);
+	flagcount("f", "debug stack frames", &debug['f']);
+	flagcount("g", "debug code generation", &debug['g']);
+	flagcount("h", "halt on error", &debug['h']);
+	flagcount("i", "debug line number stack", &debug['i']);
+	flagcount("j", "debug runtime-initialized variables", &debug['j']);
+	flagcount("l", "disable inlining", &debug['l']);
+	flagcount("m", "print optimization decisions", &debug['m']);
+	flagstr("o", "obj: set output file", &outfile);
+	flagstr("p", "path: set expected package import path", &myimportpath);
+	flagcount("r", "debug generated wrappers", &debug['r']);
+	flagcount("race", "enable race detector", &flag_race);
+	flagcount("s", "warn about composite literals that can be simplified", &debug['s']);
+	flagcount("u", "reject unsafe code", &safemode);
+	flagcount("v", "increase debug verbosity", &debug['v']);
+	flagcount("w", "debug type checking", &debug['w']);
+	flagcount("x", "debug lexer", &debug['x']);
+	flagcount("y", "debug declarations in canned imports (with -d)", &debug['y']);
+	if(thechar == '6')
+		flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel);
+
+	flagparse(&argc, &argv, usage);
 
-	case 'u':
-		safemode = 1;
-		break;
+	if(argc < 1)
+		usage();
 
-	case 'D':
-		localimport = EARGF(usage());
-		break;
+	if(flag_race) {
+		racepkg = mkpkg(strlit("runtime/race"));
+		racepkg->name = "race";
+	}
 
-	case 'I':
-		addidir(EARGF(usage()));
-		break;
-	
-	case 'V':
-		p = expstring();
-		if(strcmp(p, "X:none") == 0)
-			p = "";
-		print("%cg version %s%s%s\n", thechar, getgoversion(), *p ? " " : "", p);
-		exits(0);
-	} ARGEND
-	
 	// enable inlining.  for now:
 	//	default: inlining on.  (debug['l'] == 1)
 	//	-l: inlining off  (debug['l'] == 0)
@@ -266,11 +277,15 @@ main(int argc, char *argv[])
 	if(debug['l'] <= 1)
 		debug['l'] = 1 - debug['l'];
 
-	if(argc < 1)
-		usage();
-
-	// special flag to detect compilation of package runtime
-	compiling_runtime = debug['+'];
+	if(thechar == '8') {
+		p = getgo386();
+		if(strcmp(p, "387") == 0)
+			use_sse = 0;
+		else if(strcmp(p, "sse2") == 0)
+			use_sse = 1;
+		else
+			sysfatal("unsupported setting GO386=%s", p);
+	}
 
 	pathname = mal(1000);
 	if(getwd(pathname, 999) == 0)
@@ -315,6 +330,10 @@ main(int argc, char *argv[])
 		curio.peekc1 = 0;
 		curio.nlsemi = 0;
 
+		// Skip initial BOM if present.
+		if(Bgetrune(curio.bin) != BOM)
+			Bungetrune(curio.bin);
+
 		block = 1;
 		iota = -1000000;
 
@@ -335,6 +354,7 @@ main(int argc, char *argv[])
 		frame(1);
 
 	// Process top-level declarations in phases.
+
 	// Phase 1: const, type, and names and types of funcs.
 	//   This will gather all the information about types
 	//   and methods but doesn't depend on any of it.
@@ -367,7 +387,7 @@ main(int argc, char *argv[])
 		errorexit();
 
 	// Phase 4: Inlining
-	if (debug['l'] > 1) {
+	if(debug['l'] > 1) {
 		// Typecheck imported function bodies if debug['l'] > 1,
 		// otherwise lazily when used or re-exported.
 		for(l=importlist; l; l=l->next)
@@ -380,7 +400,7 @@ main(int argc, char *argv[])
 			errorexit();
 	}
 
-	if (debug['l']) {
+	if(debug['l']) {
 		// Find functions that can be inlined and clone them before walk expands them.
 		for(l=xtop; l; l=l->next)
 			if(l->n->op == ODCLFUNC)
@@ -392,7 +412,7 @@ main(int argc, char *argv[])
 				inlcalls(l->n);
 	}
 
-	// Phase 5: escape analysis.
+	// Phase 5: Escape analysis.
 	if(!debug['N'])
 		escapes(xtop);
 
@@ -404,21 +424,7 @@ main(int argc, char *argv[])
 	if(nsavederrors+nerrors == 0)
 		fninit(xtop);
 
-	// Phase 6b: Compile all closures.
-	// Can generate more closures, so run in batches.
-	while(closures) {
-		batch = closures;
-		closures = nil;
-		if(debug['l'])
-			for(l=batch; l; l=l->next)
-				inlcalls(l->n);
-		if(!debug['N'])
-			escapes(batch);
-		for(l=batch; l; l=l->next)
-			funccompile(l->n, 1);
-	}
-
-	// Phase 7: check external declarations.
+	// Phase 7: Check external declarations.
 	for(l=externdcl; l; l=l->next)
 		if(l->n->op == ONAME)
 			typecheck(&l->n, Erv);
@@ -483,7 +489,7 @@ skiptopkgdef(Biobuf *b)
 	if(memcmp(p, "!<arch>\n", 8) != 0)
 		return 0;
 	/* symbol table is first; skip it */
-	sz = arsize(b, "__.SYMDEF");
+	sz = arsize(b, "__.GOSYMDEF");
 	if(sz < 0)
 		return 0;
 	Bseek(b, sz, 1);
@@ -533,7 +539,7 @@ static int
 findpkg(Strlit *name)
 {
 	Idir *p;
-	char *q;
+	char *q, *race;
 
 	if(islocalname(name)) {
 		if(safemode)
@@ -571,10 +577,13 @@ findpkg(Strlit *name)
 			return 1;
 	}
 	if(goroot != nil) {
-		snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s/%Z.a", goroot, goos, goarch, name);
+		race = "";
+		if(flag_race)
+			race = "_race";
+		snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s%s/%Z.a", goroot, goos, goarch, race, name);
 		if(access(namebuf, 0) >= 0)
 			return 1;
-		snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s/%Z.%c", goroot, goos, goarch, name, thechar);
+		snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s%s/%Z.%c", goroot, goos, goarch, race, name, thechar);
 		if(access(namebuf, 0) >= 0)
 			return 1;
 	}
@@ -659,6 +668,11 @@ importfile(Val *f, int line)
 		strcat(cleanbuf, path->s);
 		cleanname(cleanbuf);
 		path = strlit(cleanbuf);
+		
+		if(isbadimport(path)) {
+			fakeimport();
+			return;
+		}
 	}
 
 	if(!findpkg(path)) {
@@ -667,6 +681,16 @@ importfile(Val *f, int line)
 	}
 	importpkg = mkpkg(path);
 
+	// If we already saw that package, feed a dummy statement
+	// to the lexer to avoid parsing export data twice.
+	if(importpkg->imported) {
+		file = strdup(namebuf);
+		p = smprint("package %s\n$$\n", importpkg->name);
+		cannedimports(file, p);
+		return;
+	}
+	importpkg->imported = 1;
+
 	imp = Bopen(namebuf, OREAD);
 	if(imp == nil) {
 		yyerror("can't open import: \"%Z\": %r", f->u.sval);
@@ -767,12 +791,8 @@ static int
 isfrog(int c)
 {
 	// complain about possibly invisible control characters
-	if(c < 0)
-		return 1;
 	if(c < ' ') {
-		if(c == '\n' || c== '\r' || c == '\t')	// good white space
-			return 0;
-		return 1;
+		return !yy_isspace(c);	// exclude good white space
 	}
 	if(0x7f <= c && c <= 0xa0)	// DEL, unicode block including unbreakable space.
 		return 1;
@@ -982,6 +1002,7 @@ l0:
 		c1 = getc();
 		if(c1 == '=') {
 			c = LCOLAS;
+			yylval.i = lexlineno;
 			goto lx;
 		}
 		break;
@@ -1145,6 +1166,11 @@ l0:
 	case '[':
 		if(loophack || lstk != nil) {
 			h = malloc(sizeof *h);
+			if(h == nil) {
+				flusherrors();
+				yyerror("out of memory");
+				errorexit();
+			}
 			h->v = loophack;
 			h->next = lstk;
 			lstk = h;
@@ -1208,7 +1234,7 @@ talph:
 			rune = getr();
 			// 0xb7 · is used for internal names
 			if(!isalpharune(rune) && !isdigitrune(rune) && (importpkg == nil || rune != 0xb7))
-				yyerror("invalid identifier character 0x%ux", rune);
+				yyerror("invalid identifier character U+%04x", rune);
 			cp += runetochar(cp, &rune);
 		} else if(!yy_isalnum(c) && c != '_')
 			break;
@@ -1270,12 +1296,14 @@ tnum:
 				continue;
 			if(cp == lexbuf+2)
 				yyerror("malformed hex constant");
+			if(c == 'p')
+				goto caseep;
 			goto ncu;
 		}
 	}
 
 	if(c == 'p')	// 0p begins floating point zero
-		goto casep;
+		goto caseep;
 
 	c1 = 0;
 	for(;;) {
@@ -1293,7 +1321,7 @@ tnum:
 	if(c == '.')
 		goto casedot;
 	if(c == 'e' || c == 'E')
-		goto casee;
+		goto caseep;
 	if(c == 'i')
 		goto casei;
 	if(c1)
@@ -1303,10 +1331,8 @@ tnum:
 dc:
 	if(c == '.')
 		goto casedot;
-	if(c == 'e' || c == 'E')
-		goto casee;
-	if(c == 'p' || c == 'P')
-		goto casep;
+	if(c == 'e' || c == 'E' || c == 'p' || c == 'P')
+		goto caseep;
 	if(c == 'i')
 		goto casei;
 
@@ -1342,29 +1368,8 @@ casedot:
 	if(c != 'e' && c != 'E')
 		goto caseout;
 
-casee:
-	*cp++ = 'e';
-	c = getc();
-	if(c == '+' || c == '-') {
-		*cp++ = c;
-		c = getc();
-	}
-	if(!yy_isdigit(c))
-		yyerror("malformed fp constant exponent");
-	while(yy_isdigit(c)) {
-		if(cp+10 >= ep) {
-			yyerror("identifier too long");
-			errorexit();
-		}
-		*cp++ = c;
-		c = getc();
-	}
-	if(c == 'i')
-		goto casei;
-	goto caseout;
-
-casep:
-	*cp++ = 'p';
+caseep:
+	*cp++ = c;
 	c = getc();
 	if(c == '+' || c == '-') {
 		*cp++ = c;
@@ -1430,7 +1435,12 @@ getlinepragma(void)
 	char *cp, *ep, *linep;
 	Hist *h;
 
-	for(i=0; i<5; i++) {
+	c = getr();
+	if(c == 'g')
+		goto go;
+	if(c != 'l')	
+		goto out;
+	for(i=1; i<5; i++) {
 		c = getr();
 		if(c != "line "[i])
 			goto out;
@@ -1478,7 +1488,35 @@ getlinepragma(void)
 		}
 	}
 	linehist(strdup(lexbuf), n, 0);
+	goto out;
+
+go:
+	cp = lexbuf;
+	ep = lexbuf+sizeof(lexbuf)-5;
+	*cp++ = 'g'; // already read
+	for(;;) {
+		c = getr();
+		if(c == EOF || c >= Runeself)
+			goto out;
+		if(c == '\n')
+			break;
+		if(cp < ep)
+			*cp++ = c;
+	}
+	*cp = 0;
+	ep = strchr(lexbuf, ' ');
+	if(ep != nil)
+		*ep = 0;
 
+	if(strcmp(lexbuf, "go:nointerface") == 0 && fieldtrack_enabled) {
+		nointerface = 1;
+		goto out;
+	}
+	if(strcmp(lexbuf, "go:noescape") == 0) {
+		noescape = 1;
+		goto out;
+	}
+	
 out:
 	return c;
 }
@@ -1524,24 +1562,35 @@ yylex(void)
 static int
 getc(void)
 {
-	int c;
+	int c, c1, c2;
 
 	c = curio.peekc;
 	if(c != 0) {
 		curio.peekc = curio.peekc1;
 		curio.peekc1 = 0;
-		if(c == '\n' && pushedio.bin == nil)
-			lexlineno++;
-		return c;
+		goto check;
 	}
 	
 	if(curio.bin == nil) {
 		c = *curio.cp & 0xff;
 		if(c != 0)
 			curio.cp++;
-	} else
+	} else {
+	loop:
 		c = Bgetc(curio.bin);
+		if(c == 0xef) {
+			c1 = Bgetc(curio.bin);
+			c2 = Bgetc(curio.bin);
+			if(c1 == 0xbb && c2 == 0xbf) {
+				yyerrorl(lexlineno, "Unicode (UTF-8) BOM in middle of file");
+				goto loop;
+			}
+			Bungetc(curio.bin);
+			Bungetc(curio.bin);
+		}
+	}
 
+check:
 	switch(c) {
 	case 0:
 		if(curio.bin != nil) {
@@ -1820,16 +1869,16 @@ lexinit(void)
 		if(etype != Txxx) {
 			if(etype < 0 || etype >= nelem(types))
 				fatal("lexinit: %s bad etype", s->name);
+			s1 = pkglookup(syms[i].name, builtinpkg);
 			t = types[etype];
 			if(t == T) {
 				t = typ(etype);
-				t->sym = s;
+				t->sym = s1;
 
 				if(etype != TANY && etype != TSTRING)
 					dowidth(t);
 				types[etype] = t;
 			}
-			s1 = pkglookup(syms[i].name, builtinpkg);
 			s1->lexical = LNAME;
 			s1->def = typenod(t);
 			continue;
@@ -1959,8 +2008,10 @@ lexfini(void)
 		s->lexical = lex;
 
 		etype = syms[i].etype;
-		if(etype != Txxx && (etype != TANY || debug['A']) && s->def == N)
+		if(etype != Txxx && (etype != TANY || debug['A']) && s->def == N) {
 			s->def = typenod(types[etype]);
+			s->origpkg = builtinpkg;
+		}
 
 		etype = syms[i].op;
 		if(etype != OXXX && s->def == N) {
@@ -1968,54 +2019,68 @@ lexfini(void)
 			s->def->sym = s;
 			s->def->etype = etype;
 			s->def->builtin = 1;
+			s->origpkg = builtinpkg;
 		}
 	}
 
+	// backend-specific builtin types (e.g. int).
 	for(i=0; typedefs[i].name; i++) {
 		s = lookup(typedefs[i].name);
-		if(s->def == N)
+		if(s->def == N) {
 			s->def = typenod(types[typedefs[i].etype]);
+			s->origpkg = builtinpkg;
+		}
 	}
 
 	// there's only so much table-driven we can handle.
 	// these are special cases.
 	s = lookup("byte");
-	if(s->def == N)
+	if(s->def == N) {
 		s->def = typenod(bytetype);
-	
+		s->origpkg = builtinpkg;
+	}
+
 	s = lookup("error");
-	if(s->def == N)
+	if(s->def == N) {
 		s->def = typenod(errortype);
+		s->origpkg = builtinpkg;
+	}
 
 	s = lookup("rune");
-	if(s->def == N)
+	if(s->def == N) {
 		s->def = typenod(runetype);
+		s->origpkg = builtinpkg;
+	}
 
 	s = lookup("nil");
 	if(s->def == N) {
 		v.ctype = CTNIL;
 		s->def = nodlit(v);
 		s->def->sym = s;
+		s->origpkg = builtinpkg;
 	}
-	
+
 	s = lookup("iota");
 	if(s->def == N) {
 		s->def = nod(OIOTA, N, N);
 		s->def->sym = s;
+		s->origpkg = builtinpkg;
 	}
 
 	s = lookup("true");
 	if(s->def == N) {
 		s->def = nodbool(1);
 		s->def->sym = s;
+		s->origpkg = builtinpkg;
 	}
 
 	s = lookup("false");
 	if(s->def == N) {
 		s->def = nodbool(0);
 		s->def->sym = s;
+		s->origpkg = builtinpkg;
 	}
-	
+
 	nodfp = nod(ONAME, N, N);
 	nodfp->type = types[TINT32];
 	nodfp->xoffset = 0;
@@ -2179,7 +2244,7 @@ mkpackage(char* pkgname)
 {
 	Sym *s;
 	int32 h;
-	char *p;
+	char *p, *q;
 
 	if(localpkg->name == nil) {
 		if(strcmp(pkgname, "_") == 0)
@@ -2219,6 +2284,11 @@ mkpackage(char* pkgname)
 
 	if(outfile == nil) {
 		p = strrchr(infile, '/');
+		if(windows) {
+			q = strrchr(infile, '\\');
+			if(q > p)
+				p = q;
+		}
 		if(p == nil)
 			p = infile;
 		else
diff --git a/src/cmd/gc/mparith1.c b/src/cmd/gc/mparith1.c
index 33fa90e..e25044a 100644
--- a/src/cmd/gc/mparith1.c
+++ b/src/cmd/gc/mparith1.c
@@ -43,10 +43,10 @@ mpcmpfixfix(Mpint *a, Mpint *b)
 int
 mpcmpfixc(Mpint *b, vlong c)
 {
-	Mpint a;
+	Mpint c1;
 
-	mpmovecfix(&a, c);
-	return mpcmpfixfix(&a, b);
+	mpmovecfix(&c1, c);
+	return mpcmpfixfix(b, &c1);
 }
 
 int
@@ -232,16 +232,78 @@ mppow10flt(Mpflt *a, int p)
 		mpmulcflt(a, 10);
 }
 
+static void
+mphextofix(Mpint *a, char *s, int n)
+{
+	char *hexdigitp, *end, c;
+	long d;
+	int bit;
+
+	while(*s == '0') {
+		s++;
+		n--;
+	}
+
+	// overflow
+	if(4*n > Mpscale*Mpprec) {
+		a->ovf = 1;
+		return;
+	}
+
+	end = s+n-1;
+	for(hexdigitp=end; hexdigitp>=s; hexdigitp--) {
+		c = *hexdigitp;
+		if(c >= '0' && c <= '9')
+			d = c-'0';
+		else if(c >= 'A' && c <= 'F')
+			d = c-'A'+10;
+		else
+			d = c-'a'+10;
+
+		bit = 4*(end - hexdigitp);
+		while(d > 0) {
+			if(d & 1)
+				a->a[bit/Mpscale] |= (long)1 << (bit%Mpscale);
+			bit++;
+			d = d >> 1;
+		}
+	}
+}
+
 //
 // floating point input
-// required syntax is [+-]d*[.]d*[e[+-]d*]
+// required syntax is [+-]d*[.]d*[e[+-]d*] or [+-]0xH*[e[+-]d*]
 //
 void
 mpatoflt(Mpflt *a, char *as)
 {
 	Mpflt b;
-	int dp, c, f, ef, ex, eb;
-	char *s;
+	int dp, c, f, ef, ex, eb, base;
+	char *s, *start;
+
+	while(*as == ' ' || *as == '\t')
+		as++;
+
+	/* determine base */
+	s = as;
+	base = -1;
+	while(base == -1) {
+		switch(*s++) {
+		case '-':
+		case '+':
+			break;
+
+		case '0':
+			if(*s == 'x')
+				base = 16;
+			else
+				base = 10;
+			break;
+
+		default:
+			base = 10;
+		}
+	}
 
 	s = as;
 	dp = 0;		/* digits after decimal point */
@@ -250,6 +312,37 @@ mpatoflt(Mpflt *a, char *as)
 	eb = 0;		/* binary point */
 
 	mpmovecflt(a, 0.0);
+	if(base == 16) {
+		start = nil;
+		for(;;) {
+			c = *s;
+			if(c == '-') {
+				f = 1;
+				s++;
+			}
+			else if(c == '+') {
+				s++;
+			}
+			else if(c == '0' && s[1] == 'x') {
+				s += 2;
+				start = s;
+			}
+			else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
+				s++;
+			}
+			else {
+				break;
+			}
+		}
+		if(start == nil)
+			goto bad;
+
+		mphextofix(&a->val, start, s-start);
+		if(a->val.ovf)
+			goto bad;
+		a->exp = 0;
+		mpnorm(a);
+	}
 	for(;;) {
 		switch(c = *s++) {
 		default:
@@ -259,11 +352,13 @@ mpatoflt(Mpflt *a, char *as)
 			f = 1;
 
 		case ' ':
-		case  '\t':
-		case  '+':
+		case '\t':
+		case '+':
 			continue;
 
 		case '.':
+			if(base == 16)
+				goto bad;
 			dp = 1;
 			continue;
 
@@ -355,7 +450,7 @@ void
 mpatofix(Mpint *a, char *as)
 {
 	int c, f;
-	char *s;
+	char *s, *s0;
 
 	s = as;
 	f = 0;
@@ -402,28 +497,19 @@ oct:
 	goto out;
 
 hex:
-	c = *s++;
+	s0 = s;
+	c = *s;
 	while(c) {
-		if(c >= '0' && c <= '9') {
-			mpmulcfix(a, 16);
-			mpaddcfix(a, c-'0');
-			c = *s++;
-			continue;
-		}
-		if(c >= 'a' && c <= 'f') {
-			mpmulcfix(a, 16);
-			mpaddcfix(a, c+10-'a');
-			c = *s++;
-			continue;
-		}
-		if(c >= 'A' && c <= 'F') {
-			mpmulcfix(a, 16);
-			mpaddcfix(a, c+10-'A');
-			c = *s++;
+		if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
+			s++;
+			c = *s;
 			continue;
 		}
 		goto bad;
 	}
+	mphextofix(a, s0, s-s0);
+	if(a->ovf)
+		goto bad;
 
 out:
 	if(f)
@@ -439,8 +525,8 @@ int
 Bconv(Fmt *fp)
 {
 	char buf[500], *p;
-	Mpint *xval, q, r, ten;
-	int f;
+	Mpint *xval, q, r, ten, sixteen;
+	int f, digit;
 
 	xval = va_arg(fp->args, Mpint*);
 	mpmovefixfix(&q, xval);
@@ -449,15 +535,33 @@ Bconv(Fmt *fp)
 		f = 1;
 		mpnegfix(&q);
 	}
-	mpmovecfix(&ten, 10);
 
 	p = &buf[sizeof(buf)];
 	*--p = 0;
-	for(;;) {
-		mpdivmodfixfix(&q, &r, &q, &ten);
-		*--p = mpgetfix(&r) + '0';
-		if(mptestfix(&q) <= 0)
-			break;
+	if(fp->flags & FmtSharp) {
+		// Hexadecimal
+		mpmovecfix(&sixteen, 16);
+		for(;;) {
+			mpdivmodfixfix(&q, &r, &q, &sixteen);
+			digit = mpgetfix(&r);
+			if(digit < 10)
+				*--p = digit + '0';
+			else
+				*--p = digit - 10 + 'A';
+			if(mptestfix(&q) <= 0)
+				break;
+		}
+		*--p = 'x';
+		*--p = '0';
+	} else {
+		// Decimal
+		mpmovecfix(&ten, 10);
+		for(;;) {
+			mpdivmodfixfix(&q, &r, &q, &ten);
+			*--p = mpgetfix(&r) + '0';
+			if(mptestfix(&q) <= 0)
+				break;
+		}
 	}
 	if(f)
 		*--p = '-';
@@ -501,10 +605,10 @@ Fconv(Fmt *fp)
 	}
 
 	if(fv.exp >= 0) {
-		snprint(buf, sizeof(buf), "%Bp+%d", &fv.val, fv.exp);
+		snprint(buf, sizeof(buf), "%#Bp+%d", &fv.val, fv.exp);
 		goto out;
 	}
-	snprint(buf, sizeof(buf), "%Bp-%d", &fv.val, -fv.exp);
+	snprint(buf, sizeof(buf), "%#Bp-%d", &fv.val, -fv.exp);
 
 out:
 	return fmtstrcpy(fp, buf);
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index e45b4e0..b87d35b 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -59,7 +59,13 @@ dumpglobls(void)
 			continue;
 		dowidth(n->type);
 
-		ggloblnod(n, n->type->width);
+		ggloblnod(n);
+	}
+
+	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);
 	}
 }
 
@@ -302,8 +308,8 @@ stringsym(char *s, int len)
 	off = 0;
 	
 	// string header
-	off = dsymptr(sym, off, sym, widthptr+4);
-	off = duint32(sym, off, len);
+	off = dsymptr(sym, off, sym, widthptr+widthint);
+	off = duintxx(sym, off, len, widthint);
 	
 	// string data
 	for(n=0; n<len; n+=m) {
@@ -314,7 +320,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);
+	ggloblsym(sym, off, 1, 1);
 
 	return sym;	
 }
diff --git a/src/cmd/gc/order.c b/src/cmd/gc/order.c
index 2cab5fb..499a4e7 100644
--- a/src/cmd/gc/order.c
+++ b/src/cmd/gc/order.c
@@ -276,11 +276,11 @@ orderstmt(Node *n, NodeList **out)
 			case OSELRECV2:
 				orderexprinplace(&r->left);
 				orderexprinplace(&r->ntest);
-				orderexpr(&r->right->left, out);
+				orderexpr(&r->right->left, &l->n->ninit);
 				break;
 			case OSEND:
-				orderexpr(&r->left, out);
-				orderexpr(&r->right, out);
+				orderexpr(&r->left, &l->n->ninit);
+				orderexpr(&r->right, &l->n->ninit);
 				break;
 			}
 		}
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
index f2b75d6..df8903b 100644
--- a/src/cmd/gc/pgen.c
+++ b/src/cmd/gc/pgen.c
@@ -14,11 +14,12 @@ compile(Node *fn)
 {
 	Plist *pl;
 	Node nod1, *n;
-	Prog *ptxt;
+	Prog *plocals, *ptxt, *p, *p1;
 	int32 lno;
 	Type *t;
 	Iter save;
 	vlong oldstksize;
+	NodeList *l;
 
 	if(newproc == N) {
 		newproc = sysfunc("newproc");
@@ -29,16 +30,19 @@ compile(Node *fn)
 		throwreturn = sysfunc("throwreturn");
 	}
 
-	if(fn->nbody == nil)
-		return;
+	lno = setlineno(fn);
+
+	if(fn->nbody == nil) {
+		if(pure_go || memcmp(fn->nname->sym->name, "init·", 6) == 0)
+			yyerror("missing function body", fn);
+		goto ret;
+	}
 
 	saveerrors();
 
 	// set up domain for labels
 	clearlabels();
 
-	lno = setlineno(fn);
-
 	curfn = fn;
 	dowidth(curfn->type);
 
@@ -63,6 +67,10 @@ compile(Node *fn)
 	walk(curfn);
 	if(nerrors != 0)
 		goto ret;
+	if(flag_race)
+		racewalk(curfn);
+	if(nerrors != 0)
+		goto ret;
 
 	continpc = P;
 	breakpc = P;
@@ -76,15 +84,34 @@ compile(Node *fn)
 	ptxt = gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1);
 	if(fn->dupok)
 		ptxt->TEXTFLAG = DUPOK;
-	afunclit(&ptxt->from);
+	afunclit(&ptxt->from, curfn->nname);
 
 	ginit();
+
+	plocals = gins(ALOCALS, N, N);
+
+	for(t=curfn->paramfld; t; t=t->down)
+		gtrack(tracksym(t->type));
+
+	for(l=fn->dcl; l; l=l->next) {
+		n = l->n;
+		if(n->op != ONAME) // might be OTYPE or OLITERAL
+			continue;
+		switch(n->class) {
+		case PAUTO:
+		case PPARAM:
+		case PPARAMOUT:
+			nodconst(&nod1, types[TUINTPTR], l->n->type->width);
+			p = gins(ATYPE, l->n, &nod1);
+			p->from.gotype = ngotype(l->n);
+			break;
+		}
+	}
+
 	genlist(curfn->enter);
 
 	retpc = nil;
 	if(hasdefer || curfn->exit) {
-		Prog *p1;
-
 		p1 = gjmp(nil);
 		retpc = gjmp(nil);
 		patch(p1, pc);
@@ -111,6 +138,7 @@ compile(Node *fn)
 	gclean();
 	if(nerrors != 0)
 		goto ret;
+
 	pc->as = ARET;	// overwrite AEND
 	pc->lineno = lineno;
 
@@ -120,6 +148,10 @@ compile(Node *fn)
 
 	oldstksize = stksize;
 	allocauto(ptxt);
+
+	plocals->to.type = D_CONST;
+	plocals->to.offset = stksize;
+
 	if(0)
 		print("allocauto: %lld to %lld\n", oldstksize, (vlong)stksize);
 
@@ -177,8 +209,10 @@ allocauto(Prog* ptxt)
 	ll = curfn->dcl;
 	n = ll->n;
 	if (n->class == PAUTO && n->op == ONAME && !n->used) {
+		// No locals used at all
 		curfn->dcl = nil;
 		stksize = 0;
+		fixautoused(ptxt);
 		return;
 	}
 
diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c
new file mode 100644
index 0000000..bae98ec
--- /dev/null
+++ b/src/cmd/gc/racewalk.c
@@ -0,0 +1,579 @@
+// 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.
+
+// The racewalk pass modifies the code tree for the function as follows:
+//
+// 1. It inserts a call to racefuncenter at the beginning of each function.
+// 2. It inserts a call to racefuncexit at the end of each function.
+// 3. It inserts a call to raceread before each memory read.
+// 4. It inserts a call to racewrite before each memory write.
+//
+// The rewriting is not yet complete. Certain nodes are not rewritten
+// but should be.
+
+#include <u.h>
+#include <libc.h>
+#include "go.h"
+
+// TODO(dvyukov): do not instrument initialization as writes:
+// a := make([]int, 10)
+
+static void racewalklist(NodeList *l, NodeList **init);
+static void racewalknode(Node **np, NodeList **init, int wr, int skip);
+static int callinstr(Node **n, NodeList **init, int wr, int skip);
+static Node* uintptraddr(Node *n);
+static Node* basenod(Node *n);
+static void foreach(Node *n, void(*f)(Node*, void*), void *c);
+static void hascallspred(Node *n, void *c);
+static Node* detachexpr(Node *n, NodeList **init);
+
+// Do not instrument the following packages at all,
+// at best instrumentation would cause infinite recursion.
+static const char *omit_pkgs[] = {"runtime", "runtime/race"};
+// Only insert racefuncenter/racefuncexit into the following packages.
+// Memory accesses in the packages are either uninteresting or will cause false positives.
+static const char *noinst_pkgs[] = {"sync", "sync/atomic"};
+
+static int
+ispkgin(const char **pkgs, int n)
+{
+	int i;
+
+	if(myimportpath) {
+		for(i=0; i<n; i++) {
+			if(strcmp(myimportpath, pkgs[i]) == 0)
+				return 1;
+		}
+	}
+	return 0;
+}
+
+void
+racewalk(Node *fn)
+{
+	Node *nd;
+	Node *nodpc;
+	char s[1024];
+
+	if(ispkgin(omit_pkgs, nelem(omit_pkgs)))
+		return;
+
+	if(!ispkgin(noinst_pkgs, nelem(noinst_pkgs))) {
+		racewalklist(fn->nbody, nil);
+		// nothing interesting for race detector in fn->enter
+		racewalklist(fn->exit, nil);
+	}
+
+	// nodpc is the PC of the caller as extracted by
+	// getcallerpc. We use -widthptr(FP) for x86.
+	// BUG: this will not work on arm.
+	nodpc = nod(OXXX, nil, nil);
+	*nodpc = *nodfp;
+	nodpc->type = types[TUINTPTR];
+	nodpc->xoffset = -widthptr;
+	nd = mkcall("racefuncenter", T, nil, nodpc);
+	fn->enter = concat(list1(nd), fn->enter);
+	nd = mkcall("racefuncexit", T, nil);
+	fn->exit = list(fn->exit, nd);
+
+	if(debug['W']) {
+		snprint(s, sizeof(s), "after racewalk %S", fn->nname->sym);
+		dumplist(s, fn->nbody);
+		snprint(s, sizeof(s), "enter %S", fn->nname->sym);
+		dumplist(s, fn->enter);
+		snprint(s, sizeof(s), "exit %S", fn->nname->sym);
+		dumplist(s, fn->exit);
+	}
+}
+
+static void
+racewalklist(NodeList *l, NodeList **init)
+{
+	NodeList *instr;
+
+	for(; l; l = l->next) {
+		instr = nil;
+		racewalknode(&l->n, &instr, 0, 0);
+		if(init == nil)
+			l->n->ninit = concat(l->n->ninit, instr);
+		else
+			*init = concat(*init, instr);
+	}
+}
+
+// walkexpr and walkstmt combined
+// walks the tree and adds calls to the
+// instrumentation code to top-level (statement) nodes' init
+static void
+racewalknode(Node **np, NodeList **init, int wr, int skip)
+{
+	Node *n, *n1;
+	NodeList *l;
+	NodeList *fini;
+
+	n = *np;
+
+	if(n == N)
+		return;
+
+	if(debug['w'] > 1)
+		dump("racewalk-before", n);
+	setlineno(n);
+	if(init == nil || init == &n->ninit)
+		fatal("racewalk: bad init list");
+
+	racewalklist(n->ninit, nil);
+
+	switch(n->op) {
+	default:
+		fatal("racewalk: unknown node type %O", n->op);
+
+	case OASOP:
+	case OAS:
+	case OAS2:
+	case OAS2DOTTYPE:
+	case OAS2RECV:
+	case OAS2FUNC:
+	case OAS2MAPR:
+		racewalknode(&n->left, init, 1, 0);
+		racewalknode(&n->right, init, 0, 0);
+		goto ret;
+	
+	case OCFUNC:
+		// can't matter
+		goto ret;
+
+	case OBLOCK:
+		if(n->list == nil)
+			goto ret;
+
+		switch(n->list->n->op) {
+		case OCALLFUNC:
+		case OCALLMETH:
+		case OCALLINTER:
+			// Blocks are used for multiple return function calls.
+			// x, y := f() becomes BLOCK{CALL f, AS x [SP+0], AS y [SP+n]}
+			// We don't want to instrument between the statements because it will
+			// smash the results.
+			racewalknode(&n->list->n, &n->ninit, 0, 0);
+			fini = nil;
+			racewalklist(n->list->next, &fini);
+			n->list = concat(n->list, fini);
+			break;
+
+		default:
+			// Ordinary block, for loop initialization or inlined bodies.
+			racewalklist(n->list, nil);
+			break;
+		}
+		goto ret;
+
+	case ODEFER:
+		racewalknode(&n->left, init, 0, 0);
+		goto ret;
+
+	case OPROC:
+		racewalknode(&n->left, init, 0, 0);
+		goto ret;
+
+	case OCALLINTER:
+		racewalknode(&n->left, init, 0, 0);
+		goto ret;
+
+	case OCALLFUNC:
+		racewalknode(&n->left, init, 0, 0);
+		goto ret;
+
+	case OSWITCH:
+		if(n->ntest->op == OTYPESW)
+			// TODO(dvyukov): the expression can contain calls or reads.
+			return;
+		goto ret;
+
+	case ONOT:
+	case OMINUS:
+	case OPLUS:
+	case OREAL:
+	case OIMAG:
+		racewalknode(&n->left, init, wr, 0);
+		goto ret;
+
+	case ODOTINTER:
+		racewalknode(&n->left, init, 0, 0);
+		goto ret;
+
+	case ODOT:
+		racewalknode(&n->left, init, 0, 1);
+		callinstr(&n, init, wr, skip);
+		goto ret;
+
+	case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND
+		racewalknode(&n->left, init, 0, 0);
+		callinstr(&n, init, wr, skip);
+		goto ret;
+
+	case OIND: // *p
+		racewalknode(&n->left, init, 0, 0);
+		callinstr(&n, init, wr, skip);
+		goto ret;
+
+	case OLEN:
+	case OCAP:
+		racewalknode(&n->left, init, 0, 0);
+		if(istype(n->left->type, TMAP)) {
+			// crashes on len(m[0]) or len(f())
+			SET(n1);
+			USED(n1);
+			/*
+			n1 = nod(OADDR, n->left, N);
+			n1 = conv(n1, types[TUNSAFEPTR]);
+			n1 = conv(n1, ptrto(ptrto(types[TINT8])));
+			n1 = nod(OIND, n1, N);
+			n1 = nod(OIND, n1, N);
+			typecheck(&n1, Erv);
+			callinstr(&n1, init, 0, skip);
+			*/
+		}
+		goto ret;
+
+	case OLSH:
+	case ORSH:
+	case OAND:
+	case OANDNOT:
+	case OOR:
+	case OXOR:
+	case OSUB:
+	case OMUL:
+	case OEQ:
+	case ONE:
+	case OLT:
+	case OLE:
+	case OGE:
+	case OGT:
+	case OADD:
+	case OCOMPLEX:
+		racewalknode(&n->left, init, wr, 0);
+		racewalknode(&n->right, init, wr, 0);
+		goto ret;
+
+	case OANDAND:
+	case OOROR:
+		racewalknode(&n->left, init, wr, 0);
+		// It requires more complex tree transformation,
+		// because we don't know whether it will be executed or not.
+		//racewalknode(&n->right, init, wr, 0);
+		goto ret;
+
+	case ONAME:
+		callinstr(&n, init, wr, skip);
+		goto ret;
+
+	case OCONV:
+		racewalknode(&n->left, init, wr, 0);
+		goto ret;
+
+	case OCONVNOP:
+		racewalknode(&n->left, init, wr, 0);
+		goto ret;
+
+	case ODIV:
+	case OMOD:
+		// TODO(dvyukov): add a test for this
+		racewalknode(&n->left, init, wr, 0);
+		racewalknode(&n->right, init, wr, 0);
+		goto ret;
+
+	case OINDEX:
+		if(!isfixedarray(n->left->type))
+			racewalknode(&n->left, init, 0, 0);
+		else if(!islvalue(n->left)) {
+			// index of unaddressable array, like Map[k][i].
+			racewalknode(&n->left, init, wr, 0);
+			racewalknode(&n->right, init, 0, 0);
+			goto ret;
+		}
+		racewalknode(&n->right, init, 0, 0);
+		if(n->left->type->etype != TSTRING)
+			callinstr(&n, init, wr, skip);
+		goto ret;
+
+	case OSLICE:
+	case OSLICEARR:
+		// Seems to only lead to double instrumentation.
+		//racewalknode(&n->left, init, 0, 0);
+		goto ret;
+
+	case OADDR:
+		racewalknode(&n->left, init, 0, 1);
+		goto ret;
+
+	case OEFACE:
+		racewalknode(&n->left, init, 0, 0);
+		racewalknode(&n->right, init, 0, 0);
+		goto ret;
+
+	// should not appear in AST by now
+	case OSEND:
+	case ORECV:
+	case OCLOSE:
+	case ONEW:
+	case OXCASE:
+	case OXFALL:
+	case OCASE:
+	case OPANIC:
+	case ORECOVER:
+	case OCONVIFACE:
+		yyerror("racewalk: %O must be lowered by now", n->op);
+		goto ret;
+
+	// just do generic traversal
+	case OFOR:
+	case OIF:
+	case OCALLMETH:
+	case ORETURN:
+	case OSELECT:
+	case OEMPTY:
+		goto ret;
+
+	// does not require instrumentation
+	case OINDEXMAP:  // implemented in runtime
+	case OPRINT:     // don't bother instrumenting it
+	case OPRINTN:    // don't bother instrumenting it
+	case OPARAM:     // it appears only in fn->exit to copy heap params back
+		goto ret;
+
+	// unimplemented
+	case OCMPSTR:
+	case OADDSTR:
+	case OSLICESTR:
+	case OAPPEND:
+	case OCOPY:
+	case OMAKECHAN:
+	case OMAKEMAP:
+	case OMAKESLICE:
+	case ORUNESTR:
+	case OARRAYBYTESTR:
+	case OARRAYRUNESTR:
+	case OSTRARRAYBYTE:
+	case OSTRARRAYRUNE:
+	case OCMPIFACE:
+	case OARRAYLIT:
+	case OMAPLIT:
+	case OSTRUCTLIT:
+	case OCLOSURE:
+	case ODOTTYPE:
+	case ODOTTYPE2:
+	case OCALL:
+	case OBREAK:
+	case ODCL:
+	case OCONTINUE:
+	case OFALL:
+	case OGOTO:
+	case OLABEL:
+	case ODCLCONST:
+	case ODCLTYPE:
+	case OLITERAL:
+	case ORANGE:
+	case OTYPE:
+	case ONONAME:
+	case OINDREG:
+	case OCOM:
+	case ODOTMETH:
+	case OITAB:
+	case OEXTEND:
+	case OHMUL:
+	case OLROT:
+	case ORROTC:
+		goto ret;
+	}
+
+ret:
+	if(n->op != OBLOCK)  // OBLOCK is handled above in a special way.
+		racewalklist(n->list, init);
+	l = nil;
+	racewalknode(&n->ntest, &l, 0, 0);
+	n->ninit = concat(n->ninit, l);
+	l = nil;
+	racewalknode(&n->nincr, &l, 0, 0);
+	n->ninit = concat(n->ninit, l);
+	racewalklist(n->nbody, nil);
+	racewalklist(n->nelse, nil);
+	racewalklist(n->rlist, nil);
+
+	*np = n;
+}
+
+static int
+isartificial(Node *n)
+{
+	// compiler-emitted artificial things that we do not want to instrument,
+	// cant' possibly participate in a data race.
+	if(n->op == ONAME && n->sym != S && n->sym->name != nil) {
+		if(strcmp(n->sym->name, "_") == 0)
+			return 1;
+		// autotmp's are always local
+		if(strncmp(n->sym->name, "autotmp_", sizeof("autotmp_")-1) == 0)
+			return 1;
+		// statictmp's are read-only
+		if(strncmp(n->sym->name, "statictmp_", sizeof("statictmp_")-1) == 0)
+			return 1;
+		// go.itab is accessed only by the compiler and runtime (assume safe)
+		if(n->sym->pkg && n->sym->pkg->name && strcmp(n->sym->pkg->name, "go.itab") == 0)
+			return 1;
+	}
+	return 0;
+}
+
+static int
+callinstr(Node **np, NodeList **init, int wr, int skip)
+{
+	Node *f, *b, *n;
+	Type *t, *t1;
+	int class, res, hascalls;
+
+	n = *np;
+	//print("callinstr for %+N [ %O ] etype=%E class=%d\n",
+	//	  n, n->op, n->type ? n->type->etype : -1, n->class);
+
+	if(skip || n->type == T || n->type->etype >= TIDEAL)
+		return 0;
+	t = n->type;
+	if(isartificial(n))
+		return 0;
+	if(t->etype == TSTRUCT) {
+		// PARAMs w/o PHEAP are not interesting.
+		if(n->class == PPARAM || n->class == PPARAMOUT)
+			return 0;
+		res = 0;
+		hascalls = 0;
+		foreach(n, hascallspred, &hascalls);
+		if(hascalls) {
+			n = detachexpr(n, init);
+			*np = n;
+		}
+		for(t1=t->type; t1; t1=t1->down) {
+			if(t1->sym && strcmp(t1->sym->name, "_")) {
+				n = treecopy(n);
+				f = nod(OXDOT, n, newname(t1->sym));
+				f->type = t1;
+				if(f->type->etype == TFIELD)
+					f->type = f->type->type;
+				if(callinstr(&f, init, wr, 0)) {
+					typecheck(&f, Erv);
+					res = 1;
+				}
+			}
+		}
+		return res;
+	}
+
+	b = basenod(n);
+	// it skips e.g. stores to ... parameter array
+	if(isartificial(b))
+		return 0;
+	class = b->class;
+	// BUG: we _may_ want to instrument PAUTO sometimes
+	// e.g. if we've got a local variable/method receiver
+	// that has got a pointer inside. Whether it points to
+	// the heap or not is impossible to know at compile time
+	if((class&PHEAP) || class == PPARAMREF || class == PEXTERN
+		|| b->type->etype == TARRAY || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
+		hascalls = 0;
+		foreach(n, hascallspred, &hascalls);
+		if(hascalls) {
+			n = detachexpr(n, init);
+			*np = n;
+		}
+		n = treecopy(n);
+		f = mkcall(wr ? "racewrite" : "raceread", T, init, uintptraddr(n));
+		*init = list(*init, f);
+		return 1;
+	}
+	return 0;
+}
+
+static Node*
+uintptraddr(Node *n)
+{
+	Node *r;
+
+	r = nod(OADDR, n, N);
+	r = conv(r, types[TUNSAFEPTR]);
+	r = conv(r, types[TUINTPTR]);
+	return r;
+}
+
+static Node*
+basenod(Node *n)
+{
+	for(;;) {
+		if(n->op == ODOT || n->op == OXDOT || n->op == OCONVNOP || n->op == OCONV || n->op == OPAREN) {
+			n = n->left;
+			continue;
+		}
+		if(n->op == OINDEX) {
+			n = n->left;
+			continue;
+		}
+		break;
+	}
+	return n;
+}
+
+static Node*
+detachexpr(Node *n, NodeList **init)
+{
+	Node *addr, *as, *ind, *l;
+
+	addr = nod(OADDR, n, N);
+	l = temp(ptrto(n->type));
+	as = nod(OAS, l, addr);
+	typecheck(&as, Etop);
+	walkexpr(&as, init);
+	*init = list(*init, as);
+	ind = nod(OIND, l, N);
+	typecheck(&ind, Erv);
+	walkexpr(&ind, init);
+	return ind;
+}
+
+static void
+foreachnode(Node *n, void(*f)(Node*, void*), void *c)
+{
+	if(n)
+		f(n, c);
+}
+
+static void
+foreachlist(NodeList *l, void(*f)(Node*, void*), void *c)
+{
+	for(; l; l = l->next)
+		foreachnode(l->n, f, c);
+}
+
+static void
+foreach(Node *n, void(*f)(Node*, void*), void *c)
+{
+	foreachlist(n->ninit, f, c);
+	foreachnode(n->left, f, c);
+	foreachnode(n->right, f, c);
+	foreachlist(n->list, f, c);
+	foreachnode(n->ntest, f, c);
+	foreachnode(n->nincr, f, c);
+	foreachlist(n->nbody, f, c);
+	foreachlist(n->nelse, f, c);
+	foreachlist(n->rlist, f, c);
+}
+
+static void
+hascallspred(Node *n, void *c)
+{
+	switch(n->op) {
+	case OCALL:
+	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		(*(int*)c)++;
+	}
+}
diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c
index d301e4e..50c4617 100644
--- a/src/cmd/gc/range.c
+++ b/src/cmd/gc/range.c
@@ -72,6 +72,15 @@ typecheckrange(Node *n)
 	if(n->list->next)
 		v2 = n->list->next->n;
 
+	// this is not only a optimization but also a requirement in the spec.
+	// "if the second iteration variable is the blank identifier, the range
+	// clause is equivalent to the same clause with only the first variable
+	// present."
+	if(isblank(v2)) {
+		n->list = list1(v1);
+		v2 = N;
+	}
+
 	if(v1->defn == n)
 		v1->type = t1;
 	else if(v1->type != T && assignop(t1, v1->type, &why) == 0)
@@ -145,7 +154,7 @@ walkrange(Node *n)
 		if(v2) {
 			hp = temp(ptrto(n->type->type));
 			tmp = nod(OINDEX, ha, nodintconst(0));
-			tmp->etype = 1;	// no bounds check
+			tmp->bounded = 1;
 			init = list(init, nod(OAS, hp, nod(OADDR, tmp, N)));
 		}
 
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 62759bc..b8eb799 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -5,6 +5,7 @@
 #include <u.h>
 #include <libc.h>
 #include "go.h"
+#include "../../pkg/runtime/mgc0.h"
 
 /*
  * runtime interface and reflection data structures
@@ -14,12 +15,13 @@ static	NodeList*	signatlist;
 static	Sym*	dtypesym(Type*);
 static	Sym*	weaktypesym(Type*);
 static	Sym*	dalgsym(Type*);
+static	Sym*	dgcsym(Type*);
 
 static int
 sigcmp(Sig *a, Sig *b)
 {
 	int i;
-	
+
 	i = strcmp(a->name, b->name);
 	if(i != 0)
 		return i;
@@ -130,7 +132,12 @@ methodfunc(Type *f, Type *receiver)
 		out = list(out, d);
 	}
 
-	return functype(N, in, out);
+	t = functype(N, in, out);
+	if(f->nname) {
+		// Link to name of original method function.
+		t->nname = f->nname;
+	}
+	return t;
 }
 
 /*
@@ -165,6 +172,8 @@ methods(Type *t)
 			fatal("non-method on %T method %S %T\n", mt, f->sym, f);
 		if (!getthisx(f->type)->type)
 			fatal("receiver with no type on %T method %S %T\n", mt, f->sym, f);
+		if(f->nointerface)
+			continue;
 
 		method = f->sym;
 		if(method == nil)
@@ -203,22 +212,26 @@ methods(Type *t)
 				// but we can generate more efficient code
 				// using genembedtramp if all that is necessary
 				// is a pointer adjustment and a JMP.
+				compiling_wrappers = 1;
 				if(isptr[it->etype] && isptr[this->etype]
 				&& f->embedded && !isifacemethod(f->type))
 					genembedtramp(it, f, a->isym, 1);
 				else
 					genwrapper(it, f, a->isym, 1);
+				compiling_wrappers = 0;
 			}
 		}
 
 		if(!(a->tsym->flags & SymSiggen)) {
 			a->tsym->flags |= SymSiggen;
 			if(!eqtype(this, t)) {
+				compiling_wrappers = 1;
 				if(isptr[t->etype] && isptr[this->etype]
 				&& f->embedded && !isifacemethod(f->type))
 					genembedtramp(t, f, a->tsym, 0);
 				else
 					genwrapper(t, f, a->tsym, 0);
+				compiling_wrappers = 0;
 			}
 		}
 	}
@@ -262,12 +275,12 @@ imethods(Type *t)
 		else
 			last->link = a;
 		last = a;
-		
+
 		// Compiler can only refer to wrappers for
 		// named interface types.
 		if(t->sym == S)
 			continue;
-		
+
 		// NOTE(rsc): Perhaps an oversight that
 		// IfaceType.Method is not in the reflect data.
 		// Generate the method body, so that compiled
@@ -287,7 +300,7 @@ dimportpath(Pkg *p)
 	static Pkg *gopkg;
 	char *nam;
 	Node *n;
-	
+
 	if(p->pathsym != S)
 		return;
 
@@ -303,9 +316,9 @@ dimportpath(Pkg *p)
 	n->class = PEXTERN;
 	n->xoffset = 0;
 	p->pathsym = n->sym;
-	
+
 	gdatastring(n, p->path);
-	ggloblsym(n->sym, types[TSTRING]->width, 1);
+	ggloblsym(n->sym, types[TSTRING]->width, 1, 1);
 }
 
 static int
@@ -319,7 +332,7 @@ dgopkgpath(Sym *s, int ot, Pkg *pkg)
 	// that imports this one directly defines the symbol.
 	if(pkg == localpkg) {
 		static Sym *ns;
-		
+
 		if(ns == nil)
 			ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
 		return dsymptr(s, ot, ns, 0);
@@ -343,7 +356,7 @@ dextratype(Sym *sym, int off, Type *t, int ptroff)
 	m = methods(t);
 	if(t->sym == nil && m == nil)
 		return off;
-	
+
 	// fill in *extraType pointer in header
 	dsymptr(sym, ptroff, sym, off);
 
@@ -367,9 +380,9 @@ dextratype(Sym *sym, int off, Type *t, int ptroff)
 	}
 
 	// slice header
-	ot = dsymptr(s, ot, s, ot + widthptr + 2*4);
-	ot = duint32(s, ot, n);
-	ot = duint32(s, ot, n);
+	ot = dsymptr(s, ot, s, ot + widthptr + 2*widthint);
+	ot = duintxx(s, ot, n, widthint);
+	ot = duintxx(s, ot, n, widthint);
 
 	// methods
 	for(a=m; a; a=a->link) {
@@ -419,7 +432,7 @@ enum {
 	KindString,
 	KindStruct,
 	KindUnsafePointer,
-	
+
 	KindNoPointers = 1<<7,
 };
 
@@ -454,19 +467,6 @@ kinds[] =
 	[TUNSAFEPTR]	= KindUnsafePointer,
 };
 
-static Sym*
-typestruct(Type *t)
-{
-	// We use a weak reference to the reflect type
-	// to avoid requiring package reflect in every binary.
-	// If package reflect is available, the interface{} holding
-	// a runtime type will contain a *reflect.commonType.
-	// Otherwise it will use a nil type word but still be usable
-	// by package runtime (because we always use the memory
-	// after the interface value, not the interface value itself).
-	return pkglookup("*reflect.commonType", weaktypepkg);
-}
-
 int
 haspointers(Type *t)
 {
@@ -521,6 +521,9 @@ dcommontype(Sym *s, int ot, Type *t)
 	Sym *sptr, *algsym;
 	static Sym *algarray;
 	char *p;
+	
+	if(ot != 0)
+		fatal("dcommontype %d", ot);
 
 	sizeofAlg = 4*widthptr;
 	if(algarray == nil)
@@ -536,31 +539,34 @@ dcommontype(Sym *s, int ot, Type *t)
 	else
 		sptr = weaktypesym(ptrto(t));
 
-	// empty interface pointing at this type.
-	// all the references that we emit are *interface{};
-	// they point here.
-	ot = rnd(ot, widthptr);
-	ot = dsymptr(s, ot, typestruct(t), 0);
-	ot = dsymptr(s, ot, s, 2*widthptr);
-
 	// ../../pkg/reflect/type.go:/^type.commonType
 	// actual type structure
 	//	type commonType struct {
-	//		size uintptr;
-	//		hash uint32;
-	//		alg uint8;
-	//		align uint8;
-	//		fieldAlign uint8;
-	//		kind uint8;
-	//		string *string;
-	//		*extraType;
-	//		ptrToThis *Type
+	//		size          uintptr
+	//		hash          uint32
+	//		_             uint8
+	//		align         uint8
+	//		fieldAlign    uint8
+	//		kind          uint8
+	//		alg           unsafe.Pointer
+	//		gc            unsafe.Pointer
+	//		string        *string
+	//		*extraType
+	//		ptrToThis     *Type
 	//	}
 	ot = duintptr(s, ot, t->width);
 	ot = duint32(s, ot, typehash(t));
 	ot = duint8(s, ot, 0);	// unused
+
+	// runtime (and common sense) expects alignment to be a power of two.
+	i = t->align;
+	if(i == 0)
+		i = 1;
+	if((i&(i-1)) != 0)
+		fatal("invalid alignment %d for %T", t->align, t);
 	ot = duint8(s, ot, t->align);	// align
 	ot = duint8(s, ot, t->align);	// fieldAlign
+
 	i = kinds[t->etype];
 	if(t->etype == TARRAY && t->bound < 0)
 		i = KindSlice;
@@ -571,11 +577,12 @@ dcommontype(Sym *s, int ot, Type *t)
 		ot = dsymptr(s, ot, algarray, alg*sizeofAlg);
 	else
 		ot = dsymptr(s, ot, algsym, 0);
+	ot = dsymptr(s, ot, dgcsym(t), 0);  // gc
 	p = smprint("%-uT", t);
 	//print("dcommontype: %s\n", p);
 	ot = dgostringptr(s, ot, p);	// string
 	free(p);
-	
+
 	// skip pointer to extraType,
 	// which follows the rest of this type structure.
 	// caller will fill in if needed.
@@ -600,6 +607,39 @@ typesym(Type *t)
 }
 
 Sym*
+tracksym(Type *t)
+{
+	char *p;
+	Sym *s;
+
+	p = smprint("%-T.%s", t->outer, t->sym->name);
+	s = pkglookup(p, trackpkg);
+	free(p);
+	return s;
+}
+
+Sym*
+typelinksym(Type *t)
+{
+	char *p;
+	Sym *s;
+
+	// %-uT is what the generated Type's string field says.
+	// It uses (ambiguous) package names instead of import paths.
+	// %-T is the complete, unambiguous type name.
+	// We want the types to end up sorted by string field,
+	// so use that first in the name, and then add :%-T to
+	// disambiguate. The names are a little long but they are
+	// discarded by the linker and do not end up in the symbol
+	// table of the final binary.
+	p = smprint("%-uT/%-T", t, t);
+	s = pkglookup(p, typelinkpkg);
+	//print("typelinksym: %s -> %+S\n", p, s);
+	free(p);
+	return s;
+}
+
+Sym*
 typesymprefix(char *prefix, Type *t)
 {
 	char *p;
@@ -612,8 +652,8 @@ typesymprefix(char *prefix, Type *t)
 	return s;
 }
 
-Node*
-typename(Type *t)
+Sym*
+typenamesym(Type *t)
 {
 	Sym *s;
 	Node *n;
@@ -634,7 +674,16 @@ typename(Type *t)
 
 		signatlist = list(signatlist, typenod(t));
 	}
+	return s->def->sym;
+}
+
+Node*
+typename(Type *t)
+{
+	Sym *s;
+	Node *n;
 
+	s = typenamesym(t);
 	n = nod(OADDR, s->def, N);
 	n->type = ptrto(s->def->type);
 	n->addable = 1;
@@ -660,10 +709,16 @@ static Sym*
 dtypesym(Type *t)
 {
 	int ot, xt, n, isddd, dupok;
-	Sym *s, *s1, *s2;
+	Sym *s, *s1, *s2, *slink;
 	Sig *a, *m;
 	Type *t1, *tbase, *t2;
 
+	// Replace byte, rune aliases with real type.
+	// They've been separate internally to make error messages
+	// better, but we have to merge them in the reflect tables.
+	if(t == bytetype || t == runetype)
+		t = types[t->etype];
+
 	if(isideal(t))
 		fatal("dtypesym %T", t);
 
@@ -680,7 +735,7 @@ dtypesym(Type *t)
 		tbase = t->type;
 	dupok = tbase->sym == S;
 
-	if(compiling_runtime && 
+	if(compiling_runtime &&
 			(tbase == types[tbase->etype] ||
 			tbase == bytetype ||
 			tbase == runetype ||
@@ -751,13 +806,13 @@ ok:
 
 		// two slice headers: in and out.
 		ot = rnd(ot, widthptr);
-		ot = dsymptr(s, ot, s, ot+2*(widthptr+2*4));
+		ot = dsymptr(s, ot, s, ot+2*(widthptr+2*widthint));
 		n = t->thistuple + t->intuple;
-		ot = duint32(s, ot, n);
-		ot = duint32(s, ot, n);
-		ot = dsymptr(s, ot, s, ot+1*(widthptr+2*4)+n*widthptr);
-		ot = duint32(s, ot, t->outtuple);
-		ot = duint32(s, ot, t->outtuple);
+		ot = duintxx(s, ot, n, widthint);
+		ot = duintxx(s, ot, n, widthint);
+		ot = dsymptr(s, ot, s, ot+1*(widthptr+2*widthint)+n*widthptr);
+		ot = duintxx(s, ot, t->outtuple, widthint);
+		ot = duintxx(s, ot, t->outtuple, widthint);
 
 		// slice data
 		for(t1=getthisx(t)->type; t1; t1=t1->down, n++)
@@ -779,9 +834,9 @@ ok:
 		// ../../pkg/runtime/type.go:/InterfaceType
 		ot = dcommontype(s, ot, t);
 		xt = ot - 2*widthptr;
-		ot = dsymptr(s, ot, s, ot+widthptr+2*4);
-		ot = duint32(s, ot, n);
-		ot = duint32(s, ot, n);
+		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
 			ot = dgostringptr(s, ot, a->name);
@@ -824,9 +879,9 @@ ok:
 		}
 		ot = dcommontype(s, ot, t);
 		xt = ot - 2*widthptr;
-		ot = dsymptr(s, ot, s, ot+widthptr+2*4);
-		ot = duint32(s, ot, n);
-		ot = duint32(s, ot, n);
+		ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
+		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
 			if(t1->sym && !t1->embedded) {
@@ -837,7 +892,10 @@ ok:
 					ot = dgopkgpath(s, ot, t1->sym->pkg);
 			} else {
 				ot = dgostringptr(s, ot, nil);
-				ot = dgostringptr(s, ot, nil);
+				if(t1->type->sym != S && t1->type->sym->pkg == builtinpkg)
+					ot = dgopkgpath(s, ot, localpkg);
+				else
+					ot = dgostringptr(s, ot, nil);
 			}
 			ot = dsymptr(s, ot, dtypesym(t1->type), 0);
 			ot = dgostrlitptr(s, ot, t1->note);
@@ -846,7 +904,24 @@ ok:
 		break;
 	}
 	ot = dextratype(s, ot, t, xt);
-	ggloblsym(s, ot, dupok);
+	ggloblsym(s, ot, dupok, 1);
+
+	// generate typelink.foo pointing at s = type.foo.
+	// The linker will leave a table of all the typelinks for
+	// types in the binary, so reflect can find them.
+	// We only need the link for unnamed composites that
+	// we want be able to find.
+	if(t->sym == S) {
+		switch(t->etype) {
+		case TARRAY:
+		case TCHAN:
+		case TMAP:
+			slink = typelinksym(t);
+			dsymptr(slink, 0, s, 0);
+			ggloblsym(slink, widthptr, dupok, 1);
+		}
+	}
+
 	return s;
 }
 
@@ -899,12 +974,14 @@ dumptypestructs(void)
 		// emit type structs for error and func(error) string.
 		// The latter is the type of an auto-generated wrapper.
 		dtypesym(ptrto(errortype));
-		dtypesym(functype(nil, 
+		dtypesym(functype(nil,
 			list1(nod(ODCLFIELD, N, typenod(errortype))),
 			list1(nod(ODCLFIELD, N, typenod(types[TSTRING])))));
-		
+
 		// add paths for runtime and main, which 6l imports implicitly.
 		dimportpath(runtimepkg);
+		if(flag_race)
+			dimportpath(racepkg);
 		dimportpath(mkpkg(strlit("main")));
 	}
 }
@@ -944,7 +1021,180 @@ dalgsym(Type *t)
 		break;
 	}
 
-	ggloblsym(s, ot, 1);
+	ggloblsym(s, ot, 1, 1);
 	return s;
 }
 
+static int
+dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
+{
+	Type *t1;
+	vlong o, off2, fieldoffset;
+
+	if(t->align > 0 && (*off % t->align) != 0)
+		fatal("dgcsym1: invalid initial alignment, %T", t);
+	
+	switch(t->etype) {
+	case TINT8:
+	case TUINT8:
+	case TINT16:
+	case TUINT16:
+	case TINT32:
+	case TUINT32:
+	case TINT64:
+	case TUINT64:
+	case TINT:
+	case TUINT:
+	case TUINTPTR:
+	case TBOOL:
+	case TFLOAT32:
+	case TFLOAT64:
+	case TCOMPLEX64:
+	case TCOMPLEX128:
+		*off += t->width;
+		break;
+
+	case TPTR32:
+	case TPTR64:
+		if(*off % widthptr != 0)
+			fatal("dgcsym1: invalid alignment, %T", t);
+		if(!haspointers(t->type) || t->type->etype == TUINT8) {
+			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 TCHAN:
+	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 Hmap*
+	case TMAP:
+		if(*off % widthptr != 0)
+			fatal("dgcsym1: invalid alignment, %T", t);
+		ot = duintptr(s, ot, GC_MAP_PTR);
+		ot = duintptr(s, ot, *off);
+		ot = dsymptr(s, ot, dtypesym(t), 0);
+		*off += 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;
+		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;
+		break;
+
+	case TARRAY:
+		if(t->bound < -1)
+			fatal("dgcsym1: invalid bound, %T", t);
+		if(isslice(t)) {
+			// 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;
+		} else {
+			if(t->bound < 1 || !haspointers(t->type)) {
+				*off += t->width;
+			} else if(t->bound == 1) {
+				ot = dgcsym1(s, ot, t->type, off, stack_size);  // recursive call of dgcsym1
+			} 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;
+			}
+		}
+		break;
+
+	case TSTRUCT:
+		o = 0;
+		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
+			o = fieldoffset + t1->type->width;
+		}
+		*off += t->width - o;
+		break;
+
+	default:
+		fatal("dgcsym1: 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;
+
+	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 15a61d9..c49d05c 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -45,8 +45,7 @@ func appendslice(typ *byte, x any, y []any) any
 func appendstr(typ *byte, x []byte, y string) []byte
 
 func cmpstring(string, string) int
-func slicestring(string, int, int) string
-func slicestring1(string, int) string
+func eqstring(string, string) bool
 func intstring(int64) string
 func slicebytetostring([]byte) string
 func slicerunetostring([]rune) string
@@ -54,14 +53,15 @@ 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 uint32) int
+func copy(to any, fr any, wid uintptr) int
 func slicestringcopy(to any, fr any) int
 
 // interface conversions
+func typ2Itab(typ *byte, typ2 *byte, cache **byte) (ret *byte)
 func convI2E(elem any) (ret any)
 func convI2I(typ *byte, elem any) (ret any)
 func convT2E(typ *byte, elem any) (ret any)
-func convT2I(typ *byte, typ2 *byte, elem any) (ret any)
+func convT2I(typ *byte, typ2 *byte, cache **byte, elem any) (ret any)
 
 // interface type assertions  x.(T)
 func assertE2E(typ *byte, iface any) (ret any)
@@ -76,6 +76,8 @@ func assertI2I(typ *byte, iface any) (ret any)
 func assertI2I2(typ *byte, iface any) (ret any, ok bool)
 func assertI2T(typ *byte, iface any) (ret any)
 func assertI2T2(typ *byte, iface any) (ret any, ok bool)
+func assertI2TOK(typ *byte, iface any) (ok bool)
+func assertE2TOK(typ *byte, iface any) (ok bool)
 
 func ifaceeq(i1 any, i2 any) (ret bool)
 func efaceeq(i1 any, i2 any) (ret bool)
@@ -89,7 +91,6 @@ func makemap(mapType *byte, hint int64) (hmap map[any]any)
 func mapaccess1(mapType *byte, hmap map[any]any, key any) (val any)
 func mapaccess2(mapType *byte, hmap map[any]any, key any) (val any, pres bool)
 func mapassign1(mapType *byte, hmap map[any]any, key any, val any)
-func mapassign2(mapType *byte, hmap map[any]any, key any, val any, pres bool)
 func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
 func mapdelete(mapType *byte, hmap map[any]any, key any)
 func mapiternext(hiter *any)
@@ -107,7 +108,7 @@ 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 int) (sel *byte)
+func newselect(size int32) (sel *byte)
 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)
@@ -117,11 +118,6 @@ func block()
 
 func makeslice(typ *byte, nel int64, cap int64) (ary []any)
 func growslice(typ *byte, old []any, n int64) (ary []any)
-func sliceslice1(old []any, lb uint64, width uint64) (ary []any)
-func sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
-func slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) (ary []any)
-
-func closure() // has args, but compiler fills in
 
 func memequal(eq *bool, size uintptr, x, y *any)
 func memequal8(eq *bool, size uintptr, x, y *any)
@@ -141,3 +137,9 @@ func int64tofloat64(int64) float64
 func uint64tofloat64(uint64) float64
 
 func complex128div(num complex128, den complex128) (quo complex128)
+
+// race detection
+func racefuncenter(uintptr)
+func racefuncexit()
+func raceread(uintptr)
+func racewrite(uintptr)
diff --git a/src/cmd/gc/select.c b/src/cmd/gc/select.c
index 8ace1d4..cd3de8c 100644
--- a/src/cmd/gc/select.c
+++ b/src/cmd/gc/select.c
@@ -62,7 +62,7 @@ typecheckselect(Node *sel)
 
 			case OAS2RECV:
 				// convert x, ok = <-c into OSELRECV2(x, <-c) with ntest=ok
-				if(n->right->op != ORECV) {
+				if(n->rlist->n->op != ORECV) {
 					yyerror("select assignment must have receive on right hand side");
 					break;
 				}
@@ -70,6 +70,7 @@ typecheckselect(Node *sel)
 				n->left = n->list->n;
 				n->ntest = n->list->next->n;
 				n->right = n->rlist->n;
+				n->rlist = nil;
 				break;
 
 			case ORECV:
@@ -146,7 +147,7 @@ walkselect(Node *sel)
 				
 				a = nod(OAS2, N, N);
 				a->list = n->list;
-				a->rlist = n->rlist;
+				a->rlist = list1(n->right);
 				n = a;
 				typecheck(&n, Etop);
 				break;
@@ -296,15 +297,15 @@ walkselect(Node *sel)
 		setlineno(cas);
 		n = cas->left;
 		r = nod(OIF, N, N);
-		r->nbody = cas->ninit;
+		r->ninit = cas->ninit;
 		cas->ninit = nil;
 		if(n != nil) {
-			r->nbody = concat(r->nbody, n->ninit);
+			r->ninit = concat(r->ninit, n->ninit);
 			n->ninit = nil;
 		}
 		if(n == nil) {
 			// selectdefault(sel *byte);
-			r->ntest = mkcall("selectdefault", types[TBOOL], &init, var);
+			r->ntest = mkcall("selectdefault", types[TBOOL], &r->ninit, var);
 		} else {
 			switch(n->op) {
 			default:
@@ -312,25 +313,25 @@ walkselect(Node *sel)
 	
 			case OSEND:
 				// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
-				n->left = safeexpr(n->left, &r->ninit);
+				n->left = localexpr(safeexpr(n->left, &r->ninit), n->left->type, &r->ninit);
 				n->right = localexpr(n->right, n->left->type->type, &r->ninit);
 				n->right = nod(OADDR, n->right, N);
 				n->right->etype = 1;  // pointer does not escape
 				typecheck(&n->right, Erv);
 				r->ntest = mkcall1(chanfn("selectsend", 2, n->left->type), types[TBOOL],
-					&init, var, n->left, n->right);
+					&r->ninit, var, n->left, n->right);
 				break;
 
 			case OSELRECV:
 				// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
 				r->ntest = mkcall1(chanfn("selectrecv", 2, n->right->left->type), types[TBOOL],
-					&init, var, n->right->left, n->left);
+					&r->ninit, var, n->right->left, n->left);
 				break;
 
 			case OSELRECV2:
 				// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
 				r->ntest = mkcall1(chanfn("selectrecv2", 2, n->right->left->type), types[TBOOL],
-					&init, var, n->right->left, n->left, n->ntest);
+					&r->ninit, var, n->right->left, n->left, n->ntest);
 				break;
 			}
 		}
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index c8796f8..353fc00 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -37,6 +37,12 @@ init1(Node *n, NodeList **out)
 	for(l=n->list; l; l=l->next)
 		init1(l->n, out);
 
+	if(n->left && n->type && n->left->op == OTYPE && n->class == PFUNC) {
+		// Methods called as Type.Method(receiver, ...).
+		// Definitions for method expressions are stored in type->nname.
+		init1(n->type->nname, out);
+	}
+
 	if(n->op != ONAME)
 		return;
 	switch(n->class) {
@@ -78,6 +84,11 @@ init1(Node *n, NodeList **out)
 	}
 	n->initorder = InitPending;
 	l = malloc(sizeof *l);
+	if(l == nil) {
+		flusherrors();
+		yyerror("out of memory");
+		errorexit();
+	}
 	l->next = initlist;
 	l->n = n;
 	l->end = nil;
@@ -97,6 +108,13 @@ init1(Node *n, NodeList **out)
 		case OAS:
 			if(n->defn->left != n)
 				goto bad;
+			if(isblank(n->defn->left) && candiscard(n->defn->right)) {
+				n->defn->op = OEMPTY;
+				n->defn->left = N;
+				n->defn->right = N;
+				break;
+			}
+
 		/*
 			n->defn->dodata = 1;
 			init1(n->defn->right, out);
@@ -167,6 +185,11 @@ init2(Node *n, NodeList **out)
 	init2list(n->rlist, out);
 	init2list(n->nbody, out);
 	init2list(n->nelse, out);
+	
+	if(n->op == OCLOSURE)
+		init2list(n->closure->nbody, out);
+	if(n->op == ODOTMETH)
+		init2(n->type->nname, out);
 }
 
 static void
@@ -291,9 +314,9 @@ staticcopy(Node *l, Node *r, NodeList **out)
 			n1.xoffset = l->xoffset + Array_array;
 			gdata(&n1, nod(OADDR, a, N), widthptr);
 			n1.xoffset = l->xoffset + Array_nel;
-			gdata(&n1, r->right, 4);
+			gdata(&n1, r->right, widthint);
 			n1.xoffset = l->xoffset + Array_cap;
-			gdata(&n1, r->right, 4);
+			gdata(&n1, r->right, widthint);
 			return 1;
 		}
 		// fall through
@@ -394,9 +417,9 @@ staticassign(Node *l, Node *r, NodeList **out)
 			n1.xoffset = l->xoffset + Array_array;
 			gdata(&n1, nod(OADDR, a, N), widthptr);
 			n1.xoffset = l->xoffset + Array_nel;
-			gdata(&n1, r->right, 4);
+			gdata(&n1, r->right, widthint);
 			n1.xoffset = l->xoffset + Array_cap;
-			gdata(&n1, r->right, 4);
+			gdata(&n1, r->right, widthint);
 			// Fall through to init underlying array.
 			l = a;
 		}
@@ -747,7 +770,7 @@ slicelit(int ctxt, Node *n, Node *var, NodeList **init)
 		index = r->left;
 		value = r->right;
 		a = nod(OINDEX, var, index);
-		a->etype = 1;	// no bounds checking
+		a->bounded = 1;
 		// TODO need to check bounds?
 
 		switch(value->op) {
@@ -879,11 +902,11 @@ ctxt = 0;
 		index = temp(types[TINT]);
 
 		a = nod(OINDEX, vstat, index);
-		a->etype = 1;	// no bounds checking
+		a->bounded = 1;
 		a = nod(ODOT, a, newname(symb));
 
 		r = nod(OINDEX, vstat, index);
-		r->etype = 1;	// no bounds checking
+		r->bounded = 1;
 		r = nod(ODOT, r, newname(syma));
 		r = nod(OINDEX, var, r);
 
@@ -930,7 +953,7 @@ void
 anylit(int ctxt, Node *n, Node *var, NodeList **init)
 {
 	Type *t;
-	Node *a, *vstat;
+	Node *a, *vstat, *r;
 
 	t = n->type;
 	switch(n->op) {
@@ -941,7 +964,14 @@ anylit(int ctxt, Node *n, Node *var, NodeList **init)
 		if(!isptr[t->etype])
 			fatal("anylit: not ptr");
 
-		a = nod(OAS, var, callnew(t->type));
+		r = nod(ONEW, N, N);
+		r->typecheck = 1;
+		r->type = t;
+		r->esc = n->esc;
+		walkexpr(&r, init);
+
+		a = nod(OAS, var, r);
+
 		typecheck(&a, Etop);
 		*init = list(*init, a);
 
@@ -1223,11 +1253,11 @@ slice:
 	gdata(&nam, nl, types[tptr]->width);
 
 	nam.xoffset += Array_nel-Array_array;
-	nodconst(&nod1, types[TINT32], nr->type->bound);
-	gdata(&nam, &nod1, types[TINT32]->width);
+	nodconst(&nod1, types[TINT], nr->type->bound);
+	gdata(&nam, &nod1, widthint);
 
 	nam.xoffset += Array_cap-Array_nel;
-	gdata(&nam, &nod1, types[TINT32]->width);
+	gdata(&nam, &nod1, widthint);
 
 	goto yes;
 
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index bd53520..c53eaf2 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -142,18 +142,32 @@ yyerror(char *fmt, ...)
 		if(debug['x'])	
 			print("yyerror: yystate=%d yychar=%d\n", yystate, yychar);
 
+		// An unexpected EOF caused a syntax error. Use the previous
+		// line number since getc generated a fake newline character.
+		if(curio.eofnl)
+			lexlineno = prevlineno;
+
 		// only one syntax error per line
 		if(lastsyntax == lexlineno)
 			return;
 		lastsyntax = lexlineno;
-		
-		if(strstr(fmt, "{ or {")) {
+			
+		if(strstr(fmt, "{ or {") || strstr(fmt, " or ?") || strstr(fmt, " or @")) {
 			// The grammar has { and LBRACE but both show up as {.
 			// Rewrite syntax error referring to "{ or {" to say just "{".
 			strecpy(buf, buf+sizeof buf, fmt);
 			p = strstr(buf, "{ or {");
 			if(p)
 				memmove(p+1, p+6, strlen(p+6)+1);
+			
+			// The grammar has ? and @ but only for reading imports.
+			// Silence them in ordinary errors.
+			p = strstr(buf, " or ?");
+			if(p)
+				memmove(p, p+5, strlen(p+5)+1);
+			p = strstr(buf, " or @");
+			if(p)
+				memmove(p, p+5, strlen(p+5)+1);
 			fmt = buf;
 		}
 		
@@ -214,6 +228,8 @@ warnl(int line, char *fmt, ...)
 	va_start(arg, fmt);
 	adderr(line, fmt, arg);
 	va_end(arg);
+	if(debug['m'])
+		flusherrors();
 }
 
 void
@@ -377,6 +393,7 @@ importdot(Pkg *opkg, Node *pack)
 	Sym *s, *s1;
 	uint32 h;
 	int n;
+	char *pkgerror;
 
 	n = 0;
 	for(h=0; h<NHASH; h++) {
@@ -389,12 +406,14 @@ importdot(Pkg *opkg, Node *pack)
 				continue;
 			s1 = lookup(s->name);
 			if(s1->def != N) {
-				redeclare(s1, "during import");
+				pkgerror = smprint("during import \"%Z\"", opkg->path);
+				redeclare(s1, pkgerror);
 				continue;
 			}
 			s1->def = s->def;
 			s1->block = s->block;
 			s1->def->pack = pack;
+			s1->origpkg = opkg;
 			n++;
 		}
 	}
@@ -494,6 +513,31 @@ nod(int op, Node *nleft, Node *nright)
 	return n;
 }
 
+void
+saveorignode(Node *n)
+{
+	Node *norig;
+
+	if(n->orig != N)
+		return;
+	norig = nod(n->op, N, N);
+	*norig = *n;
+	n->orig = norig;
+}
+
+// ispaddedfield returns whether the given field
+// is followed by padding. For the case where t is
+// the last field, total gives the size of the enclosing struct.
+static int
+ispaddedfield(Type *t, vlong total)
+{
+	if(t->etype != TFIELD)
+		fatal("ispaddedfield called non-field %T", t);
+	if(t->down == T)
+		return t->width + t->type->width != total;
+	return t->width + t->type->width != t->down->width;
+}
+
 int
 algtype1(Type *t, Type **bad)
 {
@@ -571,8 +615,12 @@ algtype1(Type *t, Type **bad)
 		}
 		ret = AMEM;
 		for(t1=t->type; t1!=T; t1=t1->down) {
-			if(isblanksym(t1->sym))
+			// Blank fields and padding must be ignored,
+			// so need special compare.
+			if(isblanksym(t1->sym) || ispaddedfield(t1, t->width)) {
+				ret = -1;
 				continue;
+			}
 			a = algtype1(t1->type, bad);
 			if(a == ANOEQ)
 				return ANOEQ;  // not comparable
@@ -813,6 +861,7 @@ treecopy(Node *n)
 	default:
 		m = nod(OXXX, N, N);
 		*m = *n;
+		m->orig = m;
 		m->left = treecopy(n->left);
 		m->right = treecopy(n->right);
 		m->list = listtreecopy(n->list);
@@ -1214,7 +1263,7 @@ assignop(Type *src, Type *dst, char **why)
 		return 0;
 	}
 	if(src->etype == TINTER && dst->etype != TBLANK) {
-		if(why != nil)
+		if(why != nil && implements(dst, src, &missing, &have, &ptr))
 			*why = ": need type assertion";
 		return 0;
 	}
@@ -1379,6 +1428,7 @@ assignconv(Node *n, Type *t, char *context)
 	r->type = t;
 	r->typecheck = 1;
 	r->implicit = 1;
+	r->orig = n->orig;
 	return r;
 }
 
@@ -2029,11 +2079,13 @@ cheapexpr(Node *n, NodeList **init)
 
 /*
  * return n in a local variable of type t if it is not already.
+ * the value is guaranteed not to change except by direct
+ * assignment to it.
  */
 Node*
 localexpr(Node *n, Type *t, NodeList **init)
 {
-	if(n->op == ONAME &&
+	if(n->op == ONAME && !n->addrtaken &&
 		(n->class == PAUTO || n->class == PPARAM || n->class == PPARAMOUT) &&
 		convertop(n->type, t, nil) == OCONVNOP)
 		return n;
@@ -2508,6 +2560,9 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
 
 	funcbody(fn);
 	curfn = fn;
+	// wrappers where T is anonymous (struct{ NamedType }) can be duplicated.
+	if(rcvr->etype == TSTRUCT || isptr[rcvr->etype] && rcvr->type->etype == TSTRUCT)
+		fn->dupok = 1;
 	typecheck(&fn, Etop);
 	typechecklist(fn->nbody, Etop);
 	curfn = nil;
@@ -2591,7 +2646,7 @@ genhash(Sym *sym, Type *t)
 	Node *hashel;
 	Type *first, *t1;
 	int old_safemode;
-	int64 size, mul;
+	int64 size, mul, offend;
 
 	if(debug['r'])
 		print("genhash %S %T\n", sym, t);
@@ -2664,7 +2719,7 @@ genhash(Sym *sym, Type *t)
 		call->list = list(call->list, nh);
 		call->list = list(call->list, nodintconst(t->type->width));
 		nx = nod(OINDEX, np, ni);
-		nx->etype = 1;  // no bounds check
+		nx->bounded = 1;
 		na = nod(OADDR, nx, N);
 		na->etype = 1;  // no escape to heap
 		call->list = list(call->list, na);
@@ -2677,22 +2732,21 @@ genhash(Sym *sym, Type *t)
 		// Walk the struct using memhash for runs of AMEM
 		// and calling specific hash functions for the others.
 		first = T;
+		offend = 0;
 		for(t1=t->type;; t1=t1->down) {
-			if(t1 != T && (isblanksym(t1->sym) || algtype1(t1->type, nil) == AMEM)) {
-				if(first == T && !isblanksym(t1->sym))
+			if(t1 != T && algtype1(t1->type, nil) == AMEM && !isblanksym(t1->sym)) {
+				offend = t1->width + t1->type->width;
+				if(first == T)
 					first = t1;
-				continue;
+				// If it's a memory field but it's padded, stop here.
+				if(ispaddedfield(t1, t->width))
+					t1 = t1->down;
+				else
+					continue;
 			}
 			// Run memhash for fields up to this one.
-			while(first != T && isblanksym(first->sym))
-				first = first->down;
 			if(first != T) {
-				if(first->down == t1)
-					size = first->type->width;
-				else if(t1 == T)
-					size = t->width - first->width;  // first->width is offset
-				else
-					size = t1->width - first->width;  // both are offsets
+				size = offend - first->width; // first->width is offset
 				hashel = hashmem(first->type);
 				// hashel(h, size, &p.first)
 				call = nod(OCALL, hashel, N);
@@ -2708,6 +2762,8 @@ genhash(Sym *sym, Type *t)
 			}
 			if(t1 == T)
 				break;
+			if(isblanksym(t1->sym))
+				continue;
 
 			// Run hash for this field.
 			hashel = hashfor(t1->type);
@@ -2721,6 +2777,8 @@ genhash(Sym *sym, Type *t)
 			call->list = list(call->list, na);
 			fn->nbody = list(fn->nbody, call);
 		}
+		// make sure body is not empty.
+		fn->nbody = list(fn->nbody, nod(ORETURN, N, N));
 		break;
 	}
 
@@ -2822,6 +2880,7 @@ geneq(Sym *sym, Type *t)
 	Type *t1, *first;
 	int old_safemode;
 	int64 size;
+	int64 offend;
 
 	if(debug['r'])
 		print("geneq %S %T\n", sym, t);
@@ -2875,9 +2934,9 @@ geneq(Sym *sym, Type *t)
 		
 		// if p[i] != q[i] { *eq = false; return }
 		nx = nod(OINDEX, np, ni);
-		nx->etype = 1;  // no bounds check
+		nx->bounded = 1;
 		ny = nod(OINDEX, nq, ni);
-		ny->etype = 1;  // no bounds check
+		ny->bounded = 1;
 
 		nif = nod(OIF, N, N);
 		nif->ntest = nod(ONE, nx, ny);
@@ -2893,18 +2952,23 @@ geneq(Sym *sym, Type *t)
 	case TSTRUCT:
 		// Walk the struct using memequal for runs of AMEM
 		// and calling specific equality tests for the others.
+		// Skip blank-named fields.
 		first = T;
+		offend = 0;
 		for(t1=t->type;; t1=t1->down) {
-			if(t1 != T && (isblanksym(t1->sym) || algtype1(t1->type, nil) == AMEM)) {
-				if(first == T && !isblanksym(t1->sym))
+			if(t1 != T && algtype1(t1->type, nil) == AMEM && !isblanksym(t1->sym)) {
+				offend = t1->width + t1->type->width;
+				if(first == T)
 					first = t1;
-				continue;
+				// If it's a memory field but it's padded, stop here.
+				if(ispaddedfield(t1, t->width))
+					t1 = t1->down;
+				else
+					continue;
 			}
 			// Run memequal for fields up to this one.
 			// TODO(rsc): All the calls to newname are wrong for
 			// cross-package unexported fields.
-			while(first != T && isblanksym(first->sym))
-				first = first->down;
 			if(first != T) {
 				if(first->down == t1) {
 					fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
@@ -2915,16 +2979,15 @@ geneq(Sym *sym, Type *t)
 						fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
 				} else {
 					// More than two fields: use memequal.
-					if(t1 == T)
-						size = t->width - first->width;  // first->width is offset
-					else
-						size = t1->width - first->width;  // both are offsets
+					size = offend - first->width; // first->width is offset
 					fn->nbody = list(fn->nbody, eqmem(np, nq, newname(first->sym), size, neq));
 				}
 				first = T;
 			}
 			if(t1 == T)
 				break;
+			if(isblanksym(t1->sym))
+				continue;
 
 			// Check this field, which is not just memory.
 			fn->nbody = list(fn->nbody, eqfield(np, nq, newname(t1->sym), neq));
@@ -3031,7 +3094,7 @@ implements(Type *t, Type *iface, Type **m, Type **samename, int *ptr)
 	for(im=iface->type; im; im=im->down) {
 		imtype = methodfunc(im->type, 0);
 		tm = ifacelookdot(im->sym, t, &followptr, 0);
-		if(tm == T || !eqtype(methodfunc(tm->type, 0), imtype)) {
+		if(tm == T || tm->nointerface || !eqtype(methodfunc(tm->type, 0), imtype)) {
 			if(tm == T)
 				tm = ifacelookdot(im->sym, t, &followptr, 1);
 			*m = im;
@@ -3504,11 +3567,8 @@ umagic(Magic *m)
 Sym*
 ngotype(Node *n)
 {
-	if(n->sym != S && n->realtype != T)
-	if(strncmp(n->sym->name, "autotmp_", 8) != 0)
-	if(strncmp(n->sym->name, "statictmp_", 8) != 0)
-		return typename(n->realtype)->left->sym;
-
+	if(n->type != T)
+		return typenamesym(n->type);
 	return S;
 }
 
@@ -3564,9 +3624,6 @@ mkpkg(Strlit *path)
 	Pkg *p;
 	int h;
 
-	if(isbadimport(path))
-		errorexit();
-	
 	h = stringhash(path->s) & (nelem(phash)-1);
 	for(p=phash[h]; p; p=p->link)
 		if(p->path->len == path->len && memcmp(path->s, p->path->s, path->len) == 0)
@@ -3615,9 +3672,15 @@ addinit(Node **np, NodeList *init)
 	n->ullman = UINF;
 }
 
+static char* reservedimports[] = {
+	"go",
+	"type",
+};
+
 int
 isbadimport(Strlit *path)
 {
+	int i;
 	char *s;
 	Rune r;
 
@@ -3625,6 +3688,13 @@ isbadimport(Strlit *path)
 		yyerror("import path contains NUL");
 		return 1;
 	}
+	
+	for(i=0; i<nelem(reservedimports); i++) {
+		if(strcmp(path->s, reservedimports[i]) == 0) {
+			yyerror("import path \"%s\" is reserved and cannot be used", path->s);
+			return 1;
+		}
+	}
 
 	s = path->s;
 	while(*s) {
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
index f1a9558..a497b86 100644
--- a/src/cmd/gc/swt.c
+++ b/src/cmd/gc/swt.c
@@ -117,12 +117,15 @@ exprcmp(Case *c1, Case *c2)
 	n1 = c1->node->left;
 	n2 = c2->node->left;
 
+	// sort by type (for switches on interface)
 	ct = n1->val.ctype;
-	if(ct != n2->val.ctype) {
-		// invalid program, but return a sort
-		// order so that we can give a better
-		// error later.
+	if(ct != n2->val.ctype)
 		return ct - n2->val.ctype;
+	if(!eqtype(n1->type, n2->type)) {
+		if(n1->type->vargen > n2->type->vargen)
+			return +1;
+		else
+			return -1;
 	}
 
 	// sort by constant value
@@ -259,10 +262,11 @@ casebody(Node *sw, Node *typeswvar)
 	Node *go, *br;
 	int32 lno, needvar;
 
-	lno = setlineno(sw);
 	if(sw->list == nil)
 		return;
 
+	lno = setlineno(sw);
+
 	cas = nil;	// cases
 	stat = nil;	// statements
 	def = N;	// defaults
@@ -270,7 +274,7 @@ casebody(Node *sw, Node *typeswvar)
 
 	for(l=sw->list; l; l=l->next) {
 		n = l->n;
-		lno = setlineno(n);
+		setlineno(n);
 		if(n->op != OXCASE)
 			fatal("casebody %O", n->op);
 		n->op = OCASE;
@@ -378,6 +382,7 @@ mkcaselist(Node *sw, int arg)
 		case Strue:
 		case Sfalse:
 			c->type = Texprvar;
+			c->hash = typehash(n->left->type);
 			switch(consttype(n->left)) {
 			case CTFLT:
 			case CTINT:
@@ -442,6 +447,10 @@ exprbsw(Case *c0, int ncase, int arg)
 			n = c0->node;
 			lno = setlineno(n);
 
+			if(assignop(n->left->type, exprname->type, nil) == OCONVIFACE ||
+			   assignop(exprname->type, n->left->type, nil) == OCONVIFACE)
+				goto snorm;
+
 			switch(arg) {
 			case Strue:
 				a = nod(OIF, N, N);
@@ -457,6 +466,7 @@ exprbsw(Case *c0, int ncase, int arg)
 				break;
 
 			default:
+			snorm:
 				a = nod(OIF, N, N);
 				a->ntest = nod(OEQ, exprname, n->left);	// if name == val
 				typecheck(&a->ntest, Erv);
@@ -520,6 +530,8 @@ exprswitch(Node *sw)
 		exprname = temp(sw->ntest->type);
 		cas = list1(nod(OAS, exprname, sw->ntest));
 		typechecklist(cas, Etop);
+	} else {
+		exprname = nodbool(arg == Strue);
 	}
 
 	c0 = mkcaselist(sw, arg);
@@ -786,7 +798,6 @@ typeswitch(Node *sw)
 void
 walkswitch(Node *sw)
 {
-
 	/*
 	 * reorder the body into (OLIST, cases, statements)
 	 * cases have OGOTO into statements.
@@ -813,7 +824,7 @@ typecheckswitch(Node *n)
 {
 	int top, lno, ptr;
 	char *nilonly;
-	Type *t, *missing, *have;
+	Type *t, *badtype, *missing, *have;
 	NodeList *l, *ll;
 	Node *ncase, *nvar;
 	Node *def;
@@ -839,10 +850,14 @@ typecheckswitch(Node *n)
 		} else
 			t = types[TBOOL];
 		if(t) {
-			if(!okforeq[t->etype] || isfixedarray(t))
+			if(!okforeq[t->etype])
 				yyerror("cannot switch on %lN", n->ntest);
-			else if(t->etype == TARRAY)
+			else if(t->etype == TARRAY && !isfixedarray(t))
 				nilonly = "slice";
+			else if(t->etype == TARRAY && isfixedarray(t) && algtype1(t, nil) == ANOEQ)
+				yyerror("cannot switch on %lN", n->ntest);
+			else if(t->etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ)
+				yyerror("cannot switch on %lN (struct containing %T cannot be compared)", n->ntest, badtype);
 			else if(t->etype == TFUNC)
 				nilonly = "func";
 			else if(t->etype == TMAP)
@@ -889,7 +904,7 @@ typecheckswitch(Node *n)
 						yyerror("%lN is not a type", ll->n);
 						// reset to original type
 						ll->n = n->ntest->right;
-					} else if(ll->n->type->etype != TINTER && !implements(ll->n->type, t, &missing, &have, &ptr)) {
+					} else if(ll->n->type->etype != TINTER && t->etype == TINTER && !implements(ll->n->type, t, &missing, &have, &ptr)) {
 						if(have && !missing->broke && !have->broke)
 							yyerror("impossible type switch case: %lN cannot have dynamic type %T"
 								" (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT",
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index cc4faf5..fbab85d 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -31,6 +31,8 @@ static void	checkassign(Node*);
 static void	checkassignlist(NodeList*);
 static void	stringtoarraylit(Node**);
 static Node*	resolve(Node*);
+static void	checkdefergo(Node*);
+static int	checkmake(Type*, char*, Node*);
 
 static	NodeList*	typecheckdefstack;
 
@@ -106,6 +108,27 @@ typekind(Type *t)
 }
 
 /*
+ * sprint_depchain prints a dependency chain
+ * of nodes into fmt.
+ * It is used by typecheck in the case of OLITERAL nodes
+ * to print constant definition loops.
+ */
+static void
+sprint_depchain(Fmt *fmt, NodeList *stack, Node *cur, Node *first)
+{
+	NodeList *l;
+
+	for(l = stack; l; l=l->next) {
+		if(l->n->op == cur->op) {
+			if(l->n != first)
+				sprint_depchain(fmt, l->next, l->n, first);
+			fmtprint(fmt, "\n\t%L: %N uses %N", l->n->lineno, l->n, cur);
+			return;
+		}
+	}
+}
+
+/*
  * type check node *np.
  * replaces *np with a new pointer in some cases.
  * returns the final value of *np as a convenience.
@@ -155,6 +178,24 @@ typecheck(Node **np, int top)
 	}
 
 	if(n->typecheck == 2) {
+		// Typechecking loop. Trying printing a meaningful message,
+		// otherwise a stack trace of typechecking.
+		switch(n->op) {
+		case ONAME:
+			// We can already diagnose variables used as types.
+			if((top & (Erv|Etype)) == Etype)
+				yyerror("%N is not a type", n);
+			break;
+		case OLITERAL:
+			if((top & (Erv|Etype)) == Etype) {
+				yyerror("%N is not a type", n);
+				break;
+			}
+			fmtstrinit(&fmt);
+			sprint_depchain(&fmt, tcstack, n, n);
+			yyerrorl(n->lineno, "constant definition loop%s", fmtstrflush(&fmt));
+			break;
+		}
 		if(nsavederrors+nerrors == 0) {
 			fmtstrinit(&fmt);
 			for(l=tcstack; l; l=l->next)
@@ -165,7 +206,7 @@ typecheck(Node **np, int top)
 		return n;
 	}
 	n->typecheck = 2;
-	
+
 	if(tcfree != nil) {
 		l = tcfree;
 		tcfree = l->next;
@@ -206,6 +247,12 @@ callrecv(Node *n)
 	case OCALLINTER:
 	case OCALLFUNC:
 	case ORECV:
+	case OCAP:
+	case OLEN:
+	case OCOPY:
+	case ONEW:
+	case OAPPEND:
+	case ODELETE:
 		return 1;
 	}
 
@@ -249,7 +296,6 @@ typecheck1(Node **np, int top)
 		}
 
 		typecheckdef(n);
-		n->realtype = n->type;
 		if(n->op == ONONAME)
 			goto error;
 	}
@@ -331,8 +377,11 @@ reswitch:
 			t->bound = -1;	// slice
 		} else if(l->op == ODDD) {
 			t->bound = -100;	// to be filled in
-			if(!(top&Ecomplit))
+			if(!(top&Ecomplit) && !n->diag) {
+				t->broke = 1;
+				n->diag = 1;
 				yyerror("use of [...] array outside of array literal");
+			}
 		} else {
 			l = typecheck(&n->left, Erv);
 			switch(consttype(l)) {
@@ -351,8 +400,10 @@ reswitch:
 			if(t->bound < 0) {
 				yyerror("array bound must be non-negative");
 				goto error;
-			} else
-				overflow(v, types[TINT]);
+			} else if(doesoverflow(v, types[TINT])) {
+				yyerror("array bound is too large"); 
+				goto error;
+			}
 		}
 		typecheck(&r, Etype);
 		if(r->type == T)
@@ -396,7 +447,7 @@ reswitch:
 		ok |= Etype;
 		n->op = OTYPE;
 		n->type = tostruct(n->list);
-		if(n->type == T)
+		if(n->type == T || n->type->broke)
 			goto error;
 		n->list = nil;
 		break;
@@ -436,8 +487,11 @@ reswitch:
 			goto ret;
 		}
 		if(!isptr[t->etype]) {
-			yyerror("invalid indirect of %lN", n->left);
-			goto error;
+			if(top & (Erv | Etop)) {
+				yyerror("invalid indirect of %lN", n->left);
+				goto error;
+			}
+			goto ret;
 		}
 		ok |= Erv;
 		n->type = t->type;
@@ -567,7 +621,10 @@ reswitch:
 				n->left = l;
 				n->right = r;
 			}
-		}
+		// non-comparison operators on ideal bools should make them lose their ideal-ness
+		} else if(t == idealbool)
+			t = types[TBOOL];
+
 		if(et == TSTRING) {
 			if(iscmp[n->op]) {
 				n->etype = n->op;
@@ -587,6 +644,13 @@ reswitch:
 				n->op = OCMPIFACE;
 			}
 		}
+
+		if((op == ODIV || op == OMOD) && isconst(r, CTINT))
+		if(mpcmpfixc(r->val.u.xval, 0) == 0) {
+			yyerror("division by zero");
+			goto error;
+		} 
+
 		n->type = t;
 		goto ret;
 
@@ -697,6 +761,10 @@ reswitch:
 			n->op = ODOTPTR;
 			checkwidth(t);
 		}
+		if(isblank(n->right)) {
+			yyerror("cannot refer to blank field or method");
+			goto error;
+		}
 		if(!lookdot(n, t, 0)) {
 			if(lookdot(n, t, 1))
 				yyerror("%N undefined (cannot refer to unexported field or method %S)", n, n->right->sym);
@@ -735,14 +803,20 @@ reswitch:
 		}
 		if(n->type != T && n->type->etype != TINTER)
 		if(!implements(n->type, t, &missing, &have, &ptr)) {
-			if(have)
-				yyerror("impossible type assertion: %lN cannot have dynamic type %T"
-					" (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT",
-					l, n->type, missing->sym, have->sym, have->type,
-					missing->sym, missing->type);
+			if(have && have->sym == missing->sym)
+				yyerror("impossible type assertion:\n\t%T does not implement %T (wrong type for %S method)\n"
+					"\t\thave %S%hhT\n\t\twant %S%hhT", n->type, t, missing->sym,
+					have->sym, have->type, missing->sym, missing->type);
+			else if(ptr)
+				yyerror("impossible type assertion:\n\t%T does not implement %T (%S method requires pointer receiver)",
+					n->type, t, missing->sym);
+			else if(have)
+				yyerror("impossible type assertion:\n\t%T does not implement %T (missing %S method)\n"
+					"\t\thave %S%hhT\n\t\twant %S%hhT", n->type, t, missing->sym,
+					have->sym, have->type, missing->sym, missing->type);
 			else
-				yyerror("impossible type assertion: %lN cannot have dynamic type %T"
-					" (missing %S method)", l, n->type, missing->sym);
+				yyerror("impossible type assertion:\n\t%T does not implement %T (missing %S method)",
+					n->type, t, missing->sym);
 			goto error;
 		}
 		goto ret;
@@ -762,11 +836,35 @@ reswitch:
 			yyerror("invalid operation: %N (index of type %T)", n, t);
 			goto error;
 
+
+		case TSTRING:
 		case TARRAY:
 			defaultlit(&n->right, T);
-			if(n->right->type != T && !isint[n->right->type->etype])
-				yyerror("non-integer array index %N", n->right);
-			n->type = t->type;
+			if(t->etype == TSTRING)
+				n->type = types[TUINT8];
+			else
+				n->type = t->type;
+			why = "string";
+			if(t->etype == TARRAY) {
+				if(isfixedarray(t))
+					why = "array";
+				else
+					why = "slice";
+			}
+			if(n->right->type != T && !isint[n->right->type->etype]) {
+				yyerror("non-integer %s index %N", why, n->right);
+				break;
+			}
+			if(n->right->op == OLITERAL) {
+			       	if(mpgetfix(n->right->val.u.xval) < 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)
+					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)
+					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);
+			}
 			break;
 
 		case TMAP:
@@ -777,13 +875,6 @@ reswitch:
 			n->type = t->type;
 			n->op = OINDEXMAP;
 			break;
-
-		case TSTRING:
-			defaultlit(&n->right, types[TUINT]);
-			if(n->right->type != T && !isint[n->right->type->etype])
-				yyerror("non-integer string index %N", n->right);
-			n->type = types[TUINT8];
-			break;
 		}
 		goto ret;
 
@@ -843,7 +934,8 @@ reswitch:
 		defaultlit(&n->left, T);
 		defaultlit(&n->right->left, T);
 		defaultlit(&n->right->right, T);
-		if(isfixedarray(n->left->type)) {
+		l = n->left;
+		if(isfixedarray(l->type)) {
 			if(!islvalue(n->left)) {
 				yyerror("invalid operation %N (slice of unaddressable value)", n);
 				goto error;
@@ -851,6 +943,26 @@ reswitch:
 			n->left = nod(OADDR, n->left, N);
 			n->left->implicit = 1;
 			typecheck(&n->left, Erv);
+			l = n->left;
+		}
+		if((t = l->type) == T)
+			goto error;
+		tp = nil;
+		if(istype(t, TSTRING)) {
+			n->type = t;
+			n->op = OSLICESTR;
+		} else if(isptr[t->etype] && isfixedarray(t->type)) {
+			tp = t->type;
+			n->type = typ(TARRAY);
+			n->type->type = tp->type;
+			n->type->bound = -1;
+			dowidth(n->type);
+			n->op = OSLICEARR;
+		} else if(isslice(t)) {
+			n->type = t;
+		} else {
+			yyerror("cannot slice %N (type %T)", l, t);
+			goto error;
 		}
 		if(n->right->left != N) {
 			if((t = n->right->left->type) == T)
@@ -859,6 +971,18 @@ reswitch:
 				yyerror("invalid slice index %N (type %T)", n->right->left, t);
 				goto error;
 			}
+			if(n->right->left->op == OLITERAL) {
+				if(mpgetfix(n->right->left->val.u.xval) < 0) {
+					yyerror("invalid slice index %N (index must be non-negative)", n->right->left);
+					goto error;
+				} else if(tp != nil && tp->bound > 0 && mpgetfix(n->right->left->val.u.xval) > tp->bound) {
+					yyerror("invalid slice index %N (out of bounds for %d-element array)", n->right->left, tp->bound);
+					goto error;
+				} else if(mpcmpfixfix(n->right->left->val.u.xval, maxintval[TINT]) > 0) {
+					yyerror("invalid slice index %N (index too large)", n->right->left);
+					goto error;
+				}
+			}
 		}
 		if(n->right->right != N) {
 			if((t = n->right->right->type) == T)
@@ -867,29 +991,28 @@ reswitch:
 				yyerror("invalid slice index %N (type %T)", n->right->right, t);
 				goto error;
 			}
+			if(n->right->right->op == OLITERAL) {
+				if(mpgetfix(n->right->right->val.u.xval) < 0) {
+					yyerror("invalid slice index %N (index must be non-negative)", n->right->right);
+					goto error;
+				} else if(tp != nil && tp->bound > 0 && mpgetfix(n->right->right->val.u.xval) > tp->bound) {
+					yyerror("invalid slice index %N (out of bounds for %d-element array)", n->right->right, tp->bound);
+					goto error;
+				} else if(mpcmpfixfix(n->right->right->val.u.xval, maxintval[TINT]) > 0) {
+					yyerror("invalid slice index %N (index too large)", n->right->right);
+					goto error;
+				}
+			}
 		}
-		l = n->left;
-		if((t = l->type) == T)
+		if(n->right->left != N
+		   && n->right->right != N
+		   && n->right->left->op == OLITERAL
+		   && n->right->right->op == OLITERAL
+		   && mpcmpfixfix(n->right->left->val.u.xval, n->right->right->val.u.xval) > 0) {
+			yyerror("inverted slice index %N > %N", n->right->left, n->right->right);
 			goto error;
-		if(istype(t, TSTRING)) {
-			n->type = t;
-			n->op = OSLICESTR;
-			goto ret;
-		}
-		if(isptr[t->etype] && isfixedarray(t->type)) {
-			n->type = typ(TARRAY);
-			n->type->type = t->type->type;
-			n->type->bound = -1;
-			dowidth(n->type);
-			n->op = OSLICEARR;
-			goto ret;
-		}
-		if(isslice(t)) {
-			n->type = t;
-			goto ret;
 		}
-		yyerror("cannot slice %N (type %T)", l, t);
-		goto error;
+		goto ret;
 
 	/*
 	 * call and call like
@@ -916,8 +1039,11 @@ reswitch:
 		defaultlit(&n->left, T);
 		l = n->left;
 		if(l->op == OTYPE) {
-			if(n->isddd || l->type->bound == -100)
-				yyerror("invalid use of ... in type conversion", l);
+			if(n->isddd || l->type->bound == -100) {
+				if(!l->type->broke)
+					yyerror("invalid use of ... in type conversion", l);
+				n->diag = 1;
+			}
 			// pick off before type-checking arguments
 			ok |= Erv;
 			// turn CALL(type, arg) into CONV(arg) w/ type
@@ -929,7 +1055,7 @@ reswitch:
 			goto doconv;
 		}
 
-		if(count(n->list) == 1)
+		if(count(n->list) == 1 && !n->isddd)
 			typecheck(&n->list->n, Erv | Efnstruct);
 		else
 			typechecklist(n->list, Erv);
@@ -1011,10 +1137,12 @@ reswitch:
 			if(!iscomplex[t->etype])
 				goto badcall1;
 			if(isconst(l, CTCPLX)){
+				r = n;
 				if(n->op == OREAL)
 					n = nodfltconst(&l->val.u.cval->real);
 				else
 					n = nodfltconst(&l->val.u.cval->imag);
+				n->orig = r;
 			}
 			n->type = types[cplxsubtype(t->etype)];
 			goto ret;
@@ -1074,7 +1202,9 @@ reswitch:
 		}
 		if(l->op == OLITERAL && r->op == OLITERAL) {
 			// make it a complex literal
-			n = nodcplxlit(l->val, r->val);
+			r = nodcplxlit(l->val, r->val);
+			r->orig = n;
+			n = r;
 		}
 		n->type = t;
 		goto ret;
@@ -1214,17 +1344,25 @@ reswitch:
 	case OCONV:
 	doconv:
 		ok |= Erv;
+		saveorignode(n);
 		typecheck(&n->left, Erv | (top & (Eindir | Eiota)));
 		convlit1(&n->left, n->type, 1);
 		if((t = n->left->type) == T || n->type == T)
 			goto error;
 		if((n->op = convertop(t, n->type, &why)) == 0) {
-			yyerror("cannot convert %lN to type %T%s", n->left, n->type, why);
+			if(!n->diag && !n->type->broke) {
+				yyerror("cannot convert %lN to type %T%s", n->left, n->type, why);
+				n->diag = 1;
+			}
 			n->op = OCONV;
 		}
 		switch(n->op) {
 		case OCONVNOP:
 			if(n->left->op == OLITERAL) {
+				r = nod(OXXX, N, N);
+				n->op = OCONV;
+				n->orig = r;
+				*r = *n;
 				n->op = OLITERAL;
 				n->val = n->left->val;
 			}
@@ -1267,22 +1405,20 @@ reswitch:
 			l = args->n;
 			args = args->next;
 			typecheck(&l, Erv);
-			defaultlit(&l, types[TINT]);
 			r = N;
 			if(args != nil) {
 				r = args->n;
 				args = args->next;
 				typecheck(&r, Erv);
-				defaultlit(&r, types[TINT]);
 			}
 			if(l->type == T || (r && r->type == T))
 				goto error;
-			if(!isint[l->type->etype]) {
-				yyerror("non-integer len argument to make(%T)", t);
+			et = checkmake(t, "len", l) < 0;
+			et |= r && checkmake(t, "cap", r) < 0;
+			if(et)
 				goto error;
-			}
-			if(r && !isint[r->type->etype]) {
-				yyerror("non-integer cap argument to make(%T)", t);
+			if(isconst(l, CTINT) && r && isconst(r, CTINT) && mpcmpfixfix(l->val.u.xval, r->val.u.xval) > 0) {
+				yyerror("len larger than cap in make(%T)", t);
 				goto error;
 			}
 			n->left = l;
@@ -1298,10 +1434,8 @@ reswitch:
 				defaultlit(&l, types[TINT]);
 				if(l->type == T)
 					goto error;
-				if(!isint[l->type->etype]) {
-					yyerror("non-integer size argument to make(%T)", t);
+				if(checkmake(t, "size", l) < 0)
 					goto error;
-				}
 				n->left = l;
 			} else
 				n->left = nodintconst(0);
@@ -1317,10 +1451,8 @@ reswitch:
 				defaultlit(&l, types[TINT]);
 				if(l->type == T)
 					goto error;
-				if(!isint[l->type->etype]) {
-					yyerror("non-integer buffer argument to make(%T)", t);
+				if(checkmake(t, "buffer", l) < 0)
 					goto error;
-				}
 				n->left = l;
 			} else
 				n->left = nodintconst(0);
@@ -1402,6 +1534,21 @@ reswitch:
 			fatal("OITAB of %T", t);
 		n->type = ptrto(types[TUINTPTR]);
 		goto ret;
+	
+	case OCLOSUREVAR:
+		ok |= Erv;
+		goto ret;
+	
+	case OCFUNC:
+		ok |= Erv;
+		typecheck(&n->left, Erv);
+		n->type = types[TUINTPTR];
+		goto ret;
+
+	case OCONVNOP:
+		ok |= Erv;
+		typecheck(&n->left, Erv);
+		goto ret;
 
 	/*
 	 * statements
@@ -1428,12 +1575,15 @@ reswitch:
 
 	case ODEFER:
 		ok |= Etop;
-		typecheck(&n->left, Etop);
+		typecheck(&n->left, Etop|Erv);
+		if(!n->left->diag)
+			checkdefergo(n);
 		goto ret;
 
 	case OPROC:
 		ok |= Etop;
-		typecheck(&n->left, Etop|Eproc);
+		typecheck(&n->left, Etop|Eproc|Erv);
+		checkdefergo(n);
 		goto ret;
 
 	case OFOR:
@@ -1530,9 +1680,7 @@ ret:
 		}
 	}
 
-	// TODO(rsc): should not need to check importpkg,
-	// but reflect mentions unsafe.Pointer.
-	if(safemode && !incannedimport && !importpkg && t && t->etype == TUNSAFEPTR)
+	if(safemode && !incannedimport && !importpkg && !compiling_wrappers && t && t->etype == TUNSAFEPTR)
 		yyerror("cannot use unsafe.Pointer");
 
 	evconst(n);
@@ -1555,7 +1703,7 @@ ret:
 	}
 	if((top & Etop) && !(top & (Ecall|Erv|Etype)) && !(ok & Etop)) {
 		if(n->diag == 0) {
-			yyerror("%N not used", n);
+			yyerror("%N evaluated but not used", n);
 			n->diag = 1;
 		}
 		goto error;
@@ -1579,6 +1727,56 @@ out:
 }
 
 static void
+checkdefergo(Node *n)
+{
+	char *what;
+	
+	what = "defer";
+	if(n->op == OPROC)
+		what = "go";
+
+	switch(n->left->op) {
+	case OCALLINTER:
+	case OCALLMETH:
+	case OCALLFUNC:
+	case OCLOSE:
+	case OCOPY:
+	case ODELETE:
+	case OPANIC:
+	case OPRINT:
+	case OPRINTN:
+	case ORECOVER:
+		// ok
+		break;
+	case OAPPEND:
+	case OCAP:
+	case OCOMPLEX:
+	case OIMAG:
+	case OLEN:
+	case OMAKE:
+	case OMAKESLICE:
+	case OMAKECHAN:
+	case OMAKEMAP:
+	case ONEW:
+	case OREAL:
+	case OLITERAL: // conversion or unsafe.Alignof, Offsetof, Sizeof
+		if(n->left->orig != N && n->left->orig->op == OCONV)
+			goto conv;
+		yyerror("%s discards result of %N", what, n->left);
+		break;
+	default:
+	conv:
+		if(!n->diag) {
+			// The syntax made sure it was a call, so this must be
+			// a conversion.
+			n->diag = 1;
+			yyerror("%s requires function call, not conversion", what);
+		}
+		break;
+	}
+}
+
+static void
 implicitstar(Node **nn)
 {
 	Type *t;
@@ -1682,7 +1880,7 @@ lookdot1(Node *errnode, Sym *s, Type *t, Type *f, int dostrcmp)
 static int
 looktypedot(Node *n, Type *t, int dostrcmp)
 {
-	Type *f1, *f2, *tt;
+	Type *f1, *f2;
 	Sym *s;
 	
 	s = n->right->sym;
@@ -1692,8 +1890,6 @@ looktypedot(Node *n, Type *t, int dostrcmp)
 		if(f1 == T)
 			return 0;
 
-		if(f1->width == BADWIDTH)
-			fatal("lookdot badwidth %T %p", f1, f1);
 		n->right = methodname(n->right, t);
 		n->xoffset = f1->width;
 		n->type = f1->type;
@@ -1701,11 +1897,9 @@ looktypedot(Node *n, Type *t, int dostrcmp)
 		return 1;
 	}
 
-	tt = t;
-	if(t->sym == S && isptr[t->etype])
-		tt = t->type;
-
-	f2 = methtype(tt, 0);
+	// Find the base type: methtype will fail if t
+	// is not of the form T or *T.
+	f2 = methtype(t, 0);
 	if(f2 == T)
 		return 0;
 
@@ -1769,6 +1963,7 @@ lookdot(Node *n, Type *t, int dostrcmp)
 			fatal("lookdot badwidth %T %p", f1, f1);
 		n->xoffset = f1->width;
 		n->type = f1->type;
+		n->paramfld = f1;
 		if(t->etype == TINTER) {
 			if(isptr[n->left->type->etype]) {
 				n->left = nod(OIND, n->left, N);	// implicitstar
@@ -2129,10 +2324,10 @@ static void
 typecheckcomplit(Node **np)
 {
 	int bad, i, len, nerr;
-	Node *l, *n, *r, **hash;
+	Node *l, *n, *norig, *r, **hash;
 	NodeList *ll;
 	Type *t, *f;
-	Sym *s;
+	Sym *s, *s1;
 	int32 lno;
 	ulong nhash;
 	Node *autohash[101];
@@ -2146,14 +2341,18 @@ typecheckcomplit(Node **np)
 		yyerror("missing type in composite literal");
 		goto error;
 	}
-	
+
+	// Save original node (including n->right)
+	norig = nod(n->op, N, N);
+	*norig = *n;
+
 	setlineno(n->right);
 	l = typecheck(&n->right /* sic */, Etype|Ecomplit);
 	if((t = l->type) == T)
 		goto error;
 	nerr = nerrors;
 	n->type = t;
-	
+
 	if(isptr[t->etype]) {
 		// For better or worse, we don't allow pointers as the composite literal type,
 		// except when using the &T syntax, which sets implicit on the OIND.
@@ -2161,13 +2360,12 @@ typecheckcomplit(Node **np)
 			yyerror("invalid pointer type %T for composite literal (use &%T instead)", t, t->type);
 			goto error;
 		}
-		
 		// Also, the underlying type must be a struct, map, slice, or array.
 		if(!iscomptype(t)) {
 			yyerror("invalid pointer type %T for composite literal", t);
 			goto error;
 		}
-		t = t->type;		
+		t = t->type;
 	}
 
 	switch(t->etype) {
@@ -2298,9 +2496,11 @@ typecheckcomplit(Node **np)
 				// Sym might have resolved to name in other top-level
 				// package, because of import dot.  Redirect to correct sym
 				// before we do the lookup.
-				if(s->pkg != localpkg && exportname(s->name))
-					s = lookup(s->name);
-
+				if(s->pkg != localpkg && exportname(s->name)) {
+					s1 = lookup(s->name);
+					if(s1->origpkg == s->pkg)
+						s = s1;
+				}
 				f = lookdot1(nil, s, t, t->type, 0);
 				if(f == nil) {
 					yyerror("unknown %T field '%S' in struct literal", t, s);
@@ -2323,6 +2523,7 @@ typecheckcomplit(Node **np)
 	if(nerr != nerrors)
 		goto error;
 	
+	n->orig = norig;
 	if(isptr[n->type->etype]) {
 		n = nod(OPTRLIT, n, N);
 		n->typecheck = 1;
@@ -2331,6 +2532,7 @@ typecheckcomplit(Node **np)
 		n->left->typecheck = 1;
 	}
 
+	n->orig = norig;
 	*np = n;
 	lineno = lno;
 	return;
@@ -2527,7 +2729,6 @@ typecheckas2(Node *n)
 			goto common;
 		case ORECV:
 			n->op = OAS2RECV;
-			n->right = n->rlist->n;
 			goto common;
 		case ODOTTYPE:
 			n->op = OAS2DOTTYPE;
@@ -2572,7 +2773,7 @@ typecheckfunc(Node *n)
 	t->nname = n->nname;
 	rcvr = getthisx(t)->type;
 	if(rcvr != nil && n->shortname != N && !isblank(n->shortname))
-		addmethod(n->shortname->sym, t, 1);
+		addmethod(n->shortname->sym, t, 1, n->nname->nointerface);
 }
 
 static void
@@ -2715,6 +2916,7 @@ typecheckdeftype(Node *n)
 	typecheck(&n->ntype, Etype);
 	if((t = n->ntype->type) == T) {
 		n->diag = 1;
+		n->type = T;
 		goto ret;
 	}
 	if(n->type == T) {
@@ -2828,14 +3030,14 @@ typecheckdef(Node *n)
 			yyerror("xxx");
 		}
 		typecheck(&e, Erv | Eiota);
-		if(e->type != T && e->op != OLITERAL) {
-			yyerror("const initializer must be constant");
-			goto ret;
-		}
 		if(isconst(e, CTNIL)) {
 			yyerror("const initializer cannot be nil");
 			goto ret;
 		}
+		if(e->type != T && e->op != OLITERAL || !isgoconst(e)) {
+			yyerror("const initializer %N is not a constant", e);
+			goto ret;
+		}
 		t = n->type;
 		if(t != T) {
 			if(!okforconst[t->etype]) {
@@ -2912,3 +3114,33 @@ ret:
 	n->walkdef = 1;
 	return n;
 }
+
+static int
+checkmake(Type *t, char *arg, Node *n)
+{
+	if(n->op == OLITERAL) {
+		n->val = toint(n->val);
+		if(mpcmpfixc(n->val.u.xval, 0) < 0) {
+			yyerror("negative %s argument in make(%T)", arg, t);
+			return -1;
+		}
+		if(mpcmpfixfix(n->val.u.xval, maxintval[TINT]) > 0) {
+			yyerror("%s argument too large in make(%T)", arg, t);
+			return -1;
+		}
+		
+		// Delay defaultlit until after we've checked range, to avoid
+		// a redundant "constant NNN overflows int" error.
+		defaultlit(&n, types[TINT]);
+		return 0;
+	}
+	
+	// Defaultlit still necessary for non-constant: n might be 1<<k.
+	defaultlit(&n, types[TINT]);
+
+	if(!isint[n->type->etype]) {
+		yyerror("non-integer %s argument in make(%T) - %T", arg, t, n->type);
+		return -1;
+	}
+	return 0;
+}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index a4edc90..de2105e 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -21,7 +21,13 @@ static	NodeList*	reorder3(NodeList*);
 static	Node*	addstr(Node*, NodeList**);
 static	Node*	appendslice(Node*, NodeList**);
 static	Node*	append(Node*, NodeList**);
+static	Node*	sliceany(Node*, NodeList**);
 static	void	walkcompare(Node**, NodeList**);
+static	void	walkrotate(Node**);
+static	void	walkmul(Node**, NodeList**);
+static	void	walkdiv(Node**, NodeList**);
+static	int	bounded(Node*, int64);
+static	Mpint	mpzero;
 
 // can this code branch reach the end
 // without an unconditional RETURN
@@ -178,8 +184,8 @@ walkstmt(Node **np)
 		dump("nottop", n);
 		break;
 
-	case OASOP:
 	case OAS:
+	case OASOP:
 	case OAS2:
 	case OAS2DOTTYPE:
 	case OAS2RECV:
@@ -368,9 +374,10 @@ walkexpr(Node **np, NodeList **init)
 	NodeList *ll, *lr, *lpost;
 	Type *t;
 	int et;
-	int64 v, v1, v2, len;
+	int64 v;
 	int32 lno;
-	Node *n, *fn;
+	Node *n, *fn, *n1, *n2;
+	Sym *sym;
 	char buf[100], *p;
 
 	n = *np;
@@ -409,7 +416,7 @@ walkexpr(Node **np, NodeList **init)
 	switch(n->op) {
 	default:
 		dump("walk", n);
-		fatal("walkexpr: switch 1 unknown op %N", n);
+		fatal("walkexpr: switch 1 unknown op %+hN", n);
 		break;
 
 	case OTYPE:
@@ -424,14 +431,23 @@ walkexpr(Node **np, NodeList **init)
 	case OCOM:
 	case OREAL:
 	case OIMAG:
-	case ODOT:
-	case ODOTPTR:
 	case ODOTMETH:
 	case ODOTINTER:
 	case OIND:
 		walkexpr(&n->left, init);
 		goto ret;
 
+	case ODOT:
+	case ODOTPTR:
+		usefield(n);
+		walkexpr(&n->left, init);
+		goto ret;
+
+	case OEFACE:
+		walkexpr(&n->left, init);
+		walkexpr(&n->right, init);
+		goto ret;
+
 	case OITAB:
 		walkexpr(&n->left, init);
 		goto ret;
@@ -454,19 +470,34 @@ walkexpr(Node **np, NodeList **init)
 
 	case OLSH:
 	case ORSH:
+		walkexpr(&n->left, init);
+		walkexpr(&n->right, init);
+	shiftwalked:
+		t = n->left->type;
+		n->bounded = bounded(n->right, 8*t->width);
+		if(debug['m'] && n->etype && !isconst(n->right, CTINT))
+			warn("shift bounds check elided");
+		goto ret;
+
 	case OAND:
-	case OOR:
-	case OXOR:
 	case OSUB:
-	case OMUL:
+	case OHMUL:
 	case OLT:
 	case OLE:
 	case OGE:
 	case OGT:
 	case OADD:
 	case OCOMPLEX:
+	case OLROT:
+		walkexpr(&n->left, init);
+		walkexpr(&n->right, init);
+		goto ret;
+
+	case OOR:
+	case OXOR:
 		walkexpr(&n->left, init);
 		walkexpr(&n->right, init);
+		walkrotate(&n);
 		goto ret;
 
 	case OEQ:
@@ -505,6 +536,11 @@ walkexpr(Node **np, NodeList **init)
 		n->addable = 1;
 		goto ret;
 
+	case OCLOSUREVAR:
+	case OCFUNC:
+		n->addable = 1;
+		goto ret;
+
 	case ONAME:
 		if(!(n->class & PHEAP) && n->class != PPARAMREF)
 			n->addable = 1;
@@ -525,10 +561,12 @@ walkexpr(Node **np, NodeList **init)
 		if(n->list && n->list->n->op == OAS)
 			goto ret;
 
+		/*
 		if(n->left->op == OCLOSURE) {
 			walkcallclosure(n, init);
 			t = n->left->type;
 		}
+		*/
 
 		walkexpr(&n->left, init);
 		walkexprlist(n->list, init);
@@ -656,6 +694,31 @@ walkexpr(Node **np, NodeList **init)
 		n->ninit = nil;
 		r = n->rlist->n;
 		walkexprlistsafe(n->list, init);
+		if(isblank(n->list->n) && !isinter(r->type)) {
+			strcpy(buf, "assert");
+			p = buf+strlen(buf);
+			if(isnilinter(r->left->type))
+				*p++ = 'E';
+			else
+				*p++ = 'I';
+			*p++ = '2';
+			*p++ = 'T';
+			*p++ = 'O';
+			*p++ = 'K';
+			*p = '\0';
+			
+			fn = syslook(buf, 1);
+			ll = list1(typename(r->type));
+			ll = list(ll, r->left);
+			argtype(fn, r->left->type);
+			n1 = nod(OCALL, fn, N);
+			n1->list = ll;
+			n = nod(OAS, n->list->next->n, n1);
+			typecheck(&n, Etop);
+			walkexpr(&n, init);
+			goto ret;
+		}
+
 		r->op = ODOTTYPE2;
 		walkexpr(&r, init);
 		ll = ascompatet(n->op, n->list, &r->type, 0, init);
@@ -694,10 +757,22 @@ walkexpr(Node **np, NodeList **init)
 		goto ret;
 
 	case OCONVIFACE:
+		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)]) {
+			l = nod(OEFACE, typename(n->left->type), n->left);
+			l->type = n->type;
+			l->typecheck = n->typecheck;
+			n = l;
+			goto ret;
+		}
+
 		// Build name of function: convI2E etc.
 		// Not all names are possible
 		// (e.g., we'll never generate convE2E or convE2I).
-		walkexpr(&n->left, init);
 		strcpy(buf, "conv");
 		p = buf+strlen(buf);
 		if(isnilinter(n->left->type))
@@ -719,6 +794,60 @@ walkexpr(Node **np, NodeList **init)
 			ll = list(ll, typename(n->left->type));
 		if(!isnilinter(n->type))
 			ll = list(ll, typename(n->type));
+		if(!isinter(n->left->type) && !isnilinter(n->type)){
+			sym = pkglookup(smprint("%-T.%-T", n->left->type, n->type), itabpkg);
+			if(sym->def == N) {
+				l = nod(ONAME, N, N);
+				l->sym = sym;
+				l->type = ptrto(types[TUINT8]);
+				l->addable = 1;
+				l->class = PEXTERN;
+				l->xoffset = 0;
+				sym->def = l;
+				ggloblsym(sym, widthptr, 1, 0);
+			}
+			l = nod(OADDR, sym->def, N);
+			l->addable = 1;
+			ll = list(ll, l);
+
+			if(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:
+				 * 	Itab *tab = atomicloadtype(&cache);
+				 * 	if(tab == nil)
+				 * 		tab = typ2Itab(type, itype, &cache);
+				 *
+				 * The CONVIFACE expression is replaced with this:
+				 * 	OEFACE{tab, ptr};
+				 */
+				l = temp(ptrto(types[TUINT8]));
+
+				n1 = nod(OAS, l, sym->def);
+				typecheck(&n1, Etop);
+				*init = list(*init, n1);
+
+				fn = syslook("typ2Itab", 1);
+				n1 = nod(OCALL, fn, N);
+				n1->list = ll;
+				typecheck(&n1, Erv);
+				walkexpr(&n1, init);
+
+				n2 = nod(OIF, N, N);
+				n2->ntest = nod(OEQ, l, nodnil());
+				n2->nbody = list1(nod(OAS, l, n1));
+				n2->likely = -1;
+				typecheck(&n2, Etop);
+				*init = list(*init, n2);
+
+				l = nod(OEFACE, l, n->left);
+				l->typecheck = n->typecheck; 
+				l->type = n->type;
+				n = l;
+				goto ret;
+			}
+		}
 		ll = list(ll, n->left);
 		argtype(fn, n->left->type);
 		argtype(fn, n->type);
@@ -772,7 +901,7 @@ walkexpr(Node **np, NodeList **init)
 		 * on 386, rewrite float ops into l = l op r.
 		 * everywhere, rewrite map ops into l = l op r.
 		 * everywhere, rewrite string += into l = l op r.
-		 * everywhere, rewrite complex /= into l = l op r.
+		 * everywhere, rewrite integer/complex /= into l = l op r.
 		 * TODO(rsc): Maybe this rewrite should be done always?
 		 */
 		et = n->left->type->etype;
@@ -780,7 +909,8 @@ walkexpr(Node **np, NodeList **init)
 		   (thechar == '8' && isfloat[et]) ||
 		   l->op == OINDEXMAP ||
 		   et == TSTRING ||
-		   (iscomplex[et] && n->etype == ODIV)) {
+		   (!isfloat[et] && n->etype == ODIV) ||
+		   n->etype == OMOD) {
 			l = safeexpr(n->left, init);
 			a = l;
 			if(a->op == OINDEXMAP) {
@@ -794,15 +924,24 @@ walkexpr(Node **np, NodeList **init)
 			typecheck(&r, Etop);
 			walkexpr(&r, init);
 			n = r;
+			goto ret;
 		}
+		if(n->etype == OLSH || n->etype == ORSH)
+			goto shiftwalked;
 		goto ret;
 
 	case OANDNOT:
 		walkexpr(&n->left, init);
-		walkexpr(&n->right, init);
 		n->op = OAND;
 		n->right = nod(OCOM, n->right, N);
 		typecheck(&n->right, Erv);
+		walkexpr(&n->right, init);
+		goto ret;
+
+	case OMUL:
+		walkexpr(&n->left, init);
+		walkexpr(&n->right, init);
+		walkmul(&n, init);
 		goto ret;
 
 	case ODIV:
@@ -821,63 +960,80 @@ walkexpr(Node **np, NodeList **init)
 			n = conv(n, t);
 			goto ret;
 		}
+		// Nothing to do for float divisions.
+		if(isfloat[et])
+			goto ret;
+
+		// Try rewriting as shifts or magic multiplies.
+		walkdiv(&n, init);
+
 		/*
-		 * rewrite div and mod into function calls
+		 * rewrite 64-bit div and mod into function calls
 		 * on 32-bit architectures.
 		 */
-		if(widthptr > 4 || (et != TUINT64 && et != TINT64))
-			goto ret;
-		if(et == TINT64)
-			strcpy(namebuf, "int64");
-		else
-			strcpy(namebuf, "uint64");
-		if(n->op == ODIV)
-			strcat(namebuf, "div");
-		else
-			strcat(namebuf, "mod");
-		n = mkcall(namebuf, n->type, init,
-			conv(n->left, types[et]), conv(n->right, types[et]));
+		switch(n->op) {
+		case OMOD:
+		case ODIV:
+			if(widthptr > 4 || (et != TUINT64 && et != TINT64))
+				goto ret;
+			if(et == TINT64)
+				strcpy(namebuf, "int64");
+			else
+				strcpy(namebuf, "uint64");
+			if(n->op == ODIV)
+				strcat(namebuf, "div");
+			else
+				strcat(namebuf, "mod");
+			n = mkcall(namebuf, n->type, init,
+				conv(n->left, types[et]), conv(n->right, types[et]));
+			break;
+		default:
+			break;
+		}
 		goto ret;
 
 	case OINDEX:
 		walkexpr(&n->left, init);
+		// save the original node for bounds checking elision.
+		// If it was a ODIV/OMOD walk might rewrite it.
+		r = n->right;
 		walkexpr(&n->right, init);
 
 		// if range of type cannot exceed static array bound,
-		// disable bounds check
-		if(isfixedarray(n->left->type))
-		if(!issigned[n->right->type->etype])
-		if(n->right->type->width < 4)
-		if((1<<(8*n->right->type->width)) <= n->left->type->bound)
-			n->etype = 1;
-
-		if(isconst(n->left, CTSTR))
-		if(!issigned[n->right->type->etype])
-		if(n->right->type->width < 4)
-		if((1<<(8*n->right->type->width)) <= n->left->val.u.sval->len)
-			n->etype = 1;
-
-		// check for static out of bounds
-		if(isconst(n->right, CTINT) && !n->etype) {
-			v = mpgetfix(n->right->val.u.xval);
-			len = 1LL<<60;
-			t = n->left->type;
-			if(isconst(n->left, CTSTR))
-				len = n->left->val.u.sval->len;
-			if(t != T && isptr[t->etype])
-				t = t->type;
-			if(isfixedarray(t))
-				len = t->bound;
-			if(v < 0 || v >= (1LL<<31) || v >= len)
+		// disable bounds check.
+		if(n->bounded)
+			goto ret;
+		t = n->left->type;
+		if(t != T && isptr[t->etype])
+			t = t->type;
+		if(isfixedarray(t)) {
+			n->bounded = bounded(r, t->bound);
+			if(debug['m'] && n->bounded && !isconst(n->right, CTINT))
+				warn("index bounds check elided");
+			if(smallintconst(n->right) && !n->bounded)
 				yyerror("index out of bounds");
-			else if(isconst(n->left, CTSTR)) {
-				// replace "abc"[2] with 'b'.
-				// delayed until now because "abc"[2] is not
-				// an ideal constant.
-				nodconst(n, n->type, n->left->val.u.sval->s[v]);
-				n->typecheck = 1;
+		} else if(isconst(n->left, CTSTR)) {
+			n->bounded = bounded(r, n->left->val.u.sval->len);
+			if(debug['m'] && n->bounded && !isconst(n->right, CTINT))
+				warn("index bounds check elided");
+			if(smallintconst(n->right)) {
+				if(!n->bounded)
+					yyerror("index out of bounds");
+				else {
+					// replace "abc"[2] with 'b'.
+					// delayed until now because "abc"[2] is not
+					// an ideal constant.
+					v = mpgetfix(n->right->val.u.xval);
+					nodconst(n, n->type, n->left->val.u.sval->s[v]);
+					n->typecheck = 1;
+				}
 			}
 		}
+
+		if(isconst(n->right, CTINT))
+		if(mpcmpfixfix(n->right->val.u.xval, &mpzero) < 0 ||
+		   mpcmpfixfix(n->right->val.u.xval, maxintval[TINT]) > 0)
+			yyerror("index out of bounds");
 		goto ret;
 
 	case OINDEXMAP:
@@ -895,95 +1051,29 @@ walkexpr(Node **np, NodeList **init)
 		goto ret;
 
 	case OSLICE:
+		if(n->right != N && n->right->left == N && n->right->right == N) { // noop
+			walkexpr(&n->left, init);
+			n = n->left;
+			goto ret;
+		}
+		// fallthrough
 	case OSLICEARR:
+	case OSLICESTR:
+		if(n->right == N) // already processed
+			goto ret;
+
 		walkexpr(&n->left, init);
-		n->left = safeexpr(n->left, init);
+		// cgen_slice can't handle string literals as source
+		// TODO the OINDEX case is a bug elsewhere that needs to be traced.  it causes a crash on ([2][]int{ ... })[1][lo:hi]
+		if((n->op == OSLICESTR && n->left->op == OLITERAL) || (n->left->op == OINDEX))
+			n->left = copyexpr(n->left, n->left->type, init);
+		else
+			n->left = safeexpr(n->left, init);
 		walkexpr(&n->right->left, init);
 		n->right->left = safeexpr(n->right->left, init);
 		walkexpr(&n->right->right, init);
 		n->right->right = safeexpr(n->right->right, init);
-
-		len = 1LL<<60;
-		t = n->left->type;
-		if(t != T && isptr[t->etype])
-			t = t->type;
-		if(isfixedarray(t))
-			len = t->bound;
-
-		// check for static out of bounds
-		// NOTE: v > len not v >= len.
-		v1 = -1;
-		v2 = -1;
-		if(isconst(n->right->left, CTINT)) {
-			v1 = mpgetfix(n->right->left->val.u.xval);
-			if(v1 < 0 || v1 >= (1LL<<31) || v1 > len) {
-				yyerror("slice index out of bounds");
-				v1 = -1;
-			}
-		}
-		if(isconst(n->right->right, CTINT)) {
-			v2 = mpgetfix(n->right->right->val.u.xval);
-			if(v2 < 0 || v2 >= (1LL<<31) || v2 > len) {
-				yyerror("slice index out of bounds");
-				v2 = -1;
-			}
-		}
-		if(v1 >= 0 && v2 >= 0 && v1 > v2)
-			yyerror("inverted slice range");
-
-		if(n->op == OSLICEARR)
-			goto slicearray;
-
-		// dynamic slice
-		// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
-		// sliceslice1(old []any, lb uint64, width uint64) (ary []any)
-		t = n->type;
-		et = n->etype;
-		if(n->right->left == N)
-			l = nodintconst(0);
-		else
-			l = conv(n->right->left, types[TUINT64]);
-		if(n->right->right != N) {
-			fn = syslook("sliceslice", 1);
-			argtype(fn, t->type);			// any-1
-			argtype(fn, t->type);			// any-2
-			n = mkcall1(fn, t, init,
-				n->left,
-				l,
-				conv(n->right->right, types[TUINT64]),
-				nodintconst(t->type->width));
-		} else {
-			fn = syslook("sliceslice1", 1);
-			argtype(fn, t->type);			// any-1
-			argtype(fn, t->type);			// any-2
-			n = mkcall1(fn, t, init,
-				n->left,
-				l,
-				nodintconst(t->type->width));
-		}
-		n->etype = et;	// preserve no-typecheck flag from OSLICE to the slice* call.
-		goto ret;
-
-	slicearray:
-		// static slice
-		// slicearray(old *any, uint64 nel, lb uint64, hb uint64, width uint64) (ary []any)
-		t = n->type;
-		fn = syslook("slicearray", 1);
-		argtype(fn, n->left->type->type);	// any-1
-		argtype(fn, t->type);			// any-2
-		if(n->right->left == N)
-			l = nodintconst(0);
-		else
-			l = conv(n->right->left, types[TUINT64]);
-		if(n->right->right == N)
-			r = nodintconst(n->left->type->type->bound);
-		else
-			r = conv(n->right->right, types[TUINT64]);
-		n = mkcall1(fn, t, init,
-			n->left, nodintconst(n->left->type->type->bound),
-			l,
-			r,
-			nodintconst(t->type->width));
+		n = sliceany(n, init);  // chops n->right, sets n->list
 		goto ret;
 
 	case OADDR:
@@ -1031,27 +1121,34 @@ walkexpr(Node **np, NodeList **init)
 			goto ret;
 		}
 
-		// prepare for rewrite below
 		if(n->etype == OEQ || n->etype == ONE) {
+			// prepare for rewrite below
 			n->left = cheapexpr(n->left, init);
 			n->right = cheapexpr(n->right, init);
-		}
 
-		// sys_cmpstring(s1, s2) :: 0
-		r = mkcall("cmpstring", types[TINT], init,
-			conv(n->left, types[TSTRING]),
-			conv(n->right, types[TSTRING]));
-		r = nod(n->etype, r, nodintconst(0));
+			r = mkcall("eqstring", types[TBOOL], init,
+				conv(n->left, types[TSTRING]),
+				conv(n->right, types[TSTRING]));
 
-		// quick check of len before full compare for == or !=
-		if(n->etype == OEQ || n->etype == ONE) {
-			if(n->etype == OEQ)
+			// quick check of len before full compare for == or !=
+			if(n->etype == OEQ) {
+				// len(left) == len(right) && eqstring(left, right)
 				r = nod(OANDAND, nod(OEQ, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
-			else
+			} else {
+				// len(left) != len(right) || !eqstring(left, right)
+				r = nod(ONOT, r, N);
 				r = nod(OOROR, nod(ONE, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
+			}
 			typecheck(&r, Erv);
 			walkexpr(&r, nil);
+		} else {
+			// sys_cmpstring(s1, s2) :: 0
+			r = mkcall("cmpstring", types[TINT], init,
+				conv(n->left, types[TSTRING]),
+				conv(n->right, types[TSTRING]));
+			r = nod(n->etype, r, nodintconst(0));
 		}
+
 		typecheck(&r, Erv);
 		if(n->type->etype != TBOOL) fatal("cmp %T", n->type);
 		r->type = n->type;
@@ -1061,25 +1158,7 @@ walkexpr(Node **np, NodeList **init)
 	case OADDSTR:
 		n = addstr(n, init);
 		goto ret;
-
-	case OSLICESTR:
-		// sys_slicestring(s, lb, hb)
-		if(n->right->left == N)
-			l = nodintconst(0);
-		else
-			l = conv(n->right->left, types[TINT]);
-		if(n->right->right) {
-			n = mkcall("slicestring", n->type, init,
-				conv(n->left, types[TSTRING]),
-				l,
-				conv(n->right->right, types[TINT]));
-		} else {
-			n = mkcall("slicestring1", n->type, init,
-				conv(n->left, types[TSTRING]),
-				l);
-		}
-		goto ret;
-
+	
 	case OAPPEND:
 		if(n->isddd) {
 			if(istype(n->type->type, TUINT8) && istype(n->list->next->n->type, TSTRING))
@@ -1177,6 +1256,9 @@ walkexpr(Node **np, NodeList **init)
 			fn = syslook("efaceeq", 1);
 		else
 			fn = syslook("ifaceeq", 1);
+
+		n->right = cheapexpr(n->right, init);
+		n->left = cheapexpr(n->left, init);
 		argtype(fn, n->right->type);
 		argtype(fn, n->left->type);
 		r = mkcall1(fn, n->type, init, n->left, n->right);
@@ -1189,7 +1271,7 @@ walkexpr(Node **np, NodeList **init)
 		else
 			r = nod(OOROR, nod(ONE, nod(OITAB, n->left, N), nod(OITAB, n->right, N)), r);
 		typecheck(&r, Erv);
-		walkexpr(&r, nil);
+		walkexpr(&r, init);
 		r->type = n->type;
 		n = r;
 		goto ret;
@@ -1226,9 +1308,16 @@ ret:
 static Node*
 ascompatee1(int op, Node *l, Node *r, NodeList **init)
 {
+	Node *n;
 	USED(op);
+	
+	// convas will turn map assigns into function calls,
+	// making it impossible for reorder3 to work.
+	n = nod(OAS, l, r);
+	if(l->op == OINDEXMAP)
+		return n;
 
-	return convas(nod(OAS, l, r), init);
+	return convas(n, init);
 }
 
 static NodeList*
@@ -1249,12 +1338,16 @@ ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
 		lr->n = safeexpr(lr->n, init);
 
 	nn = nil;
-	for(ll=nl, lr=nr; ll && lr; ll=ll->next, lr=lr->next)
+	for(ll=nl, lr=nr; ll && lr; ll=ll->next, lr=lr->next) {
+		// Do not generate 'x = x' during return. See issue 4014.
+		if(op == ORETURN && ll->n == lr->n)
+			continue;
 		nn = list(nn, ascompatee1(op, ll->n, lr->n, init));
+	}
 
 	// cannot happen: caller checked that lists had same length
 	if(ll || lr)
-		yyerror("error in shape across %+H %O %+H", nl, op, nr);
+		yyerror("error in shape across %+H %O %+H / %d %d [%s]", nl, op, nr, count(nl), count(nr), curfn->nname->sym->name);
 	return nn;
 }
 
@@ -1826,13 +1919,14 @@ static int aliased(Node*, NodeList*, NodeList*);
 static NodeList*
 reorder3(NodeList *all)
 {
-	NodeList *list, *early;
+	NodeList *list, *early, *mapinit;
 	Node *l;
 
 	// If a needed expression may be affected by an
 	// earlier assignment, make an early copy of that
 	// expression and use the copy instead.
 	early = nil;
+	mapinit = nil;
 	for(list=all; list; list=list->next) {
 		l = list->n->left;
 
@@ -1856,8 +1950,11 @@ reorder3(NodeList *all)
 		case ONAME:
 			break;
 		case OINDEX:
+		case OINDEXMAP:
 			reorder3save(&l->left, all, list, &early);
 			reorder3save(&l->right, all, list, &early);
+			if(l->op == OINDEXMAP)
+				list->n = convas(list->n, &mapinit);
 			break;
 		case OIND:
 		case ODOTPTR:
@@ -1868,6 +1965,7 @@ reorder3(NodeList *all)
 		reorder3save(&list->n->right, all, list, &early);
 	}
 
+	early = concat(mapinit, early);
 	return concat(early, all);
 }
 
@@ -2119,6 +2217,8 @@ paramstoheap(Type **argin, int out)
 	nn = nil;
 	for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
 		v = t->nname;
+		if(v && v->sym && v->sym->name[0] == '~')
+			v = N;
 		if(v == N && out && hasdefer) {
 			// Defer might stop a panic and show the
 			// return values as they exist at the time of panic.
@@ -2395,12 +2495,12 @@ append(Node *n, NodeList **init)
 	l = list(l, nod(OAS, nn, nod(OLEN, ns, N)));	 // n = len(s)
 
 	nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na)));	 // ...s[:n+argc]
-	nx->etype = 1;	// disable bounds check
+	nx->bounded = 1;
 	l = list(l, nod(OAS, ns, nx));			// s = s[:n+argc]
 
 	for (a = n->list->next;	 a != nil; a = a->next) {
 		nx = nod(OINDEX, ns, nn);		// s[n] ...
-		nx->etype = 1;	// disable bounds check
+		nx->bounded = 1;
 		l = list(l, nod(OAS, nx, a->n));	// s[n] = arg
 		if (a->next != nil)
 			l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1))));  // n = n + 1
@@ -2412,6 +2512,151 @@ append(Node *n, NodeList **init)
 	return ns;
 }
 
+
+// Generate frontend part for OSLICE[ARR|STR]
+// 
+static	Node*
+sliceany(Node* n, NodeList **init)
+{
+	int bounded;
+	Node *src, *lb, *hb, *bound, *chk, *chk1, *chk2;
+	int64 lbv, hbv, bv, w;
+	Type *bt;
+
+//	print("before sliceany: %+N\n", n);
+
+	src = n->left;
+	lb = n->right->left;
+	hb = n->right->right;
+
+	bounded = n->etype;
+	
+	if(n->op == OSLICESTR)
+		bound = nod(OLEN, src, N);
+	else
+		bound = nod(OCAP, src, N);
+
+	typecheck(&bound, Erv);
+	walkexpr(&bound, init);  // if src is an array, bound will be a const now.
+
+	// static checks if possible
+	bv = 1LL<<50;
+	if(isconst(bound, CTINT)) {
+		if(!smallintconst(bound))
+			yyerror("array len too large");
+		else
+			bv = mpgetfix(bound->val.u.xval);
+	}
+
+	if(isconst(hb, CTINT)) {
+		hbv = mpgetfix(hb->val.u.xval);
+		if(hbv < 0 || hbv > bv) {
+			yyerror("slice index out of bounds");
+			hbv = -1;
+		}
+	}
+	if(isconst(lb, CTINT)) {
+		lbv = mpgetfix(lb->val.u.xval);
+		if(lbv < 0 || lbv > bv) {
+			yyerror("slice index out of bounds");
+			lbv = -1;
+		}
+		if(lbv == 0)
+			lb = N;
+	}
+
+	// dynamic checks convert all bounds to unsigned to save us the bound < 0 comparison
+	// generate
+	//     if hb > bound || lb > hb { panicslice() }
+	chk = N;
+	chk1 = N;
+	chk2 = N;
+
+	bt = types[simtype[TUINT]];
+	if(hb != N && hb->type->width > 4)
+		bt = types[TUINT64];
+	if(lb != N && lb->type->width > 4)
+		bt = types[TUINT64];
+
+	bound = cheapexpr(conv(bound, bt), init);
+
+	if(hb != N) {
+		hb = cheapexpr(conv(hb, bt), init);
+		if(!bounded)
+			chk1 = nod(OLT, bound, hb);  
+	} else if(n->op == OSLICEARR) {
+		hb = bound;
+	} else {
+		hb = nod(OLEN, src, N);
+		typecheck(&hb, Erv);
+		walkexpr(&hb, init);
+		hb = cheapexpr(conv(hb, bt), init);
+	}
+
+	if(lb != N) {
+		lb = cheapexpr(conv(lb, bt), init);
+		if(!bounded)
+			chk2 = nod(OLT, hb, lb);  
+	}
+
+	if(chk1 != N || chk2 != N) {
+		chk = nod(OIF, N, N);
+		chk->nbody = list1(mkcall("panicslice", T, init));
+		if(chk1 != N)
+			chk->ntest = chk1;
+		if(chk2 != N) {
+			if(chk->ntest == N)
+				chk->ntest = chk2;
+			else
+				chk->ntest = nod(OOROR, chk->ntest, chk2);
+		}
+		typecheck(&chk, Etop);
+		walkstmt(&chk);
+		*init = concat(*init, chk->ninit);
+		chk->ninit = nil;
+		*init = list(*init, chk);
+	}
+	
+	// prepare new cap, len and offs for backend cgen_slice
+	// cap = bound [ - lo ]
+	n->right = N;
+	n->list = nil;
+	if(lb == N)
+		bound = conv(bound, types[simtype[TUINT]]);
+	else
+		bound = nod(OSUB, conv(bound, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]]));
+	typecheck(&bound, Erv);
+	walkexpr(&bound, init);
+	n->list = list(n->list, bound);
+
+	// len = hi [ - lo]
+	if(lb == N)
+		hb = conv(hb, types[simtype[TUINT]]);
+	else
+		hb = nod(OSUB, conv(hb, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]]));
+	typecheck(&hb, Erv);
+	walkexpr(&hb, init);
+	n->list = list(n->list, hb);
+
+	// offs = [width *] lo, but omit if zero
+	if(lb != N) {
+		if(n->op == OSLICESTR)
+			w = 1;
+		else
+			w = n->type->type->width;
+		lb = conv(lb, types[TUINTPTR]);
+		if(w > 1)
+			lb = nod(OMUL, nodintconst(w), lb);
+		typecheck(&lb, Erv);
+		walkexpr(&lb, init);
+		n->list = list(n->list, lb);
+	}
+
+//	print("after sliceany: %+N\n", n);
+
+	return n;
+}
+
 static Node*
 eqfor(Type *t)
 {
@@ -2531,6 +2776,8 @@ walkcompare(Node **np, NodeList **init)
 		// Struct of four or fewer fields.
 		// Inline comparisons.
 		for(t1=t->type; t1; t1=t1->down) {
+			if(isblanksym(t1->sym))
+				continue;
 			li = nod(OXDOT, l, newname(t1->sym));
 			ri = nod(OXDOT, r, newname(t1->sym));
 			a = nod(n->op, li, ri);
@@ -2596,3 +2843,591 @@ hard:
 	*np = r;
 	return;
 }
+
+static int
+samecheap(Node *a, Node *b)
+{
+	if(a == N || b == N || a->op != b->op)
+		return 0;
+	
+	switch(a->op) {
+	case ONAME:
+		return a == b;
+	// TODO: Could do more here, but maybe this is enough.
+	// It's all cheapexpr does.
+	}
+	return 0;
+}
+
+static void
+walkrotate(Node **np)
+{
+	int w, sl, sr, s;
+	Node *l, *r;
+	Node *n;
+	
+	n = *np;
+
+	// Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value.
+	l = n->left;
+	r = n->right;
+	if((n->op != OOR && n->op != OXOR) ||
+	   (l->op != OLSH && l->op != ORSH) ||
+	   (r->op != OLSH && r->op != ORSH) ||
+	   n->type == T || issigned[n->type->etype] ||
+	   l->op == r->op) {
+		return;
+	}
+
+	// Want same, side effect-free expression on lhs of both shifts.
+	if(!samecheap(l->left, r->left))
+		return;
+	
+	// Constants adding to width?
+	w = l->type->width * 8;
+	if(smallintconst(l->right) && smallintconst(r->right)) {
+		if((sl=mpgetfix(l->right->val.u.xval)) >= 0 && (sr=mpgetfix(r->right->val.u.xval)) >= 0 && sl+sr == w)
+			goto yes;
+		return;
+	}
+	
+	// TODO: Could allow s and 32-s if s is bounded (maybe s&31 and 32-s&31).
+	return;
+	
+yes:
+	// Rewrite left shift half to left rotate.
+	if(l->op == OLSH)
+		n = l;
+	else
+		n = r;
+	n->op = OLROT;
+	
+	// Remove rotate 0 and rotate w.
+	s = mpgetfix(n->right->val.u.xval);
+	if(s == 0 || s == w)
+		n = n->left;
+
+	*np = n;
+	return;
+}
+
+/*
+ * walkmul rewrites integer multiplication by powers of two as shifts.
+ */
+static void
+walkmul(Node **np, NodeList **init)
+{
+	Node *n, *nl, *nr;
+	int pow, neg, w;
+	
+	n = *np;
+	if(!isint[n->type->etype])
+		return;
+
+	if(n->right->op == OLITERAL) {
+		nl = n->left;
+		nr = n->right;
+	} else if(n->left->op == OLITERAL) {
+		nl = n->right;
+		nr = n->left;
+	} else
+		return;
+
+	neg = 0;
+
+	// x*0 is 0 (and side effects of x).
+	if(mpgetfix(nr->val.u.xval) == 0) {
+		cheapexpr(nl, init);
+		nodconst(n, n->type, 0);
+		goto ret;
+	}
+
+	// nr is a constant.
+	pow = powtwo(nr);
+	if(pow < 0)
+		return;
+	if(pow >= 1000) {
+		// negative power of 2, like -16
+		neg = 1;
+		pow -= 1000;
+	}
+
+	w = nl->type->width*8;
+	if(pow+1 >= w)// too big, shouldn't happen
+		return;
+
+	nl = cheapexpr(nl, init);
+
+	if(pow == 0) {
+		// x*1 is x
+		n = nl;
+		goto ret;
+	}
+	
+	n = nod(OLSH, nl, nodintconst(pow));
+
+ret:
+	if(neg)
+		n = nod(OMINUS, n, N);
+
+	typecheck(&n, Erv);
+	walkexpr(&n, init);
+	*np = n;
+}
+
+/*
+ * walkdiv rewrites division by a constant as less expensive
+ * operations.
+ */
+static void
+walkdiv(Node **np, NodeList **init)
+{
+	Node *n, *nl, *nr, *nc;
+	Node *n1, *n2, *n3, *n4;
+	int pow; // if >= 0, nr is 1<<pow
+	int s; // 1 if nr is negative.
+	int w;
+	Type *twide;
+	Magic m;
+
+	n = *np;
+	if(n->right->op != OLITERAL)
+		return;
+	// nr is a constant.
+	nl = cheapexpr(n->left, init);
+	nr = n->right;
+
+	// special cases of mod/div
+	// by a constant
+	w = nl->type->width*8;
+	s = 0;
+	pow = powtwo(nr);
+	if(pow >= 1000) {
+		// negative power of 2
+		s = 1;
+		pow -= 1000;
+	}
+
+	if(pow+1 >= w) {
+		// divisor too large.
+		return;
+	}
+	if(pow < 0) {
+		goto divbymul;
+	}
+
+	switch(pow) {
+	case 0:
+		if(n->op == OMOD) {
+			// nl % 1 is zero.
+			nodconst(n, n->type, 0);
+		} else if(s) {
+			// divide by -1
+			n->op = OMINUS;
+			n->right = N;
+		} else {
+			// divide by 1
+			n = nl;
+		}
+		break;
+	default:
+		if(issigned[n->type->etype]) {
+			if(n->op == OMOD) {
+				// signed modulo 2^pow is like ANDing
+				// with the last pow bits, but if nl < 0,
+				// nl & (2^pow-1) is (nl+1)%2^pow - 1.
+				nc = nod(OXXX, N, N);
+				nodconst(nc, types[simtype[TUINT]], w-1);
+				n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0.
+				if(pow == 1) {
+					typecheck(&n1, Erv);
+					n1 = cheapexpr(n1, init);
+					// n = (nl+ε)&1 -ε where ε=1 iff nl<0.
+					n2 = nod(OSUB, nl, n1);
+					nc = nod(OXXX, N, N);
+					nodconst(nc, nl->type, 1);
+					n3 = nod(OAND, n2, nc);
+					n = nod(OADD, n3, n1);
+				} else {
+					// n = (nl+ε)&(nr-1) - ε where ε=2^pow-1 iff nl<0.
+					nc = nod(OXXX, N, N);
+					nodconst(nc, nl->type, (1LL<<pow)-1);
+					n2 = nod(OAND, n1, nc); // n2 = 2^pow-1 iff nl<0.
+					typecheck(&n2, Erv);
+					n2 = cheapexpr(n2, init);
+
+					n3 = nod(OADD, nl, n2);
+					n4 = nod(OAND, n3, nc);
+					n = nod(OSUB, n4, n2);
+				}
+				break;
+			} else {
+				// arithmetic right shift does not give the correct rounding.
+				// if nl >= 0, nl >> n == nl / nr
+				// if nl < 0, we want to add 2^n-1 first.
+				nc = nod(OXXX, N, N);
+				nodconst(nc, types[simtype[TUINT]], w-1);
+				n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0.
+				if(pow == 1) {
+					// nl+1 is nl-(-1)
+					n->left = nod(OSUB, nl, n1);
+				} else {
+					// Do a logical right right on -1 to keep pow bits.
+					nc = nod(OXXX, N, N);
+					nodconst(nc, types[simtype[TUINT]], w-pow);
+					n2 = nod(ORSH, conv(n1, tounsigned(nl->type)), nc);
+					n->left = nod(OADD, nl, conv(n2, nl->type));
+				}
+				// n = (nl + 2^pow-1) >> pow
+				n->op = ORSH;
+				nc = nod(OXXX, N, N);
+				nodconst(nc, types[simtype[TUINT]], pow);
+				n->right = nc;
+				n->typecheck = 0;
+			}
+			if(s)
+				n = nod(OMINUS, n, N);
+			break;
+		}
+		nc = nod(OXXX, N, N);
+		if(n->op == OMOD) {
+			// n = nl & (nr-1)
+			n->op = OAND;
+			nodconst(nc, nl->type, mpgetfix(nr->val.u.xval)-1);
+		} else {
+			// n = nl >> pow
+			n->op = ORSH;
+			nodconst(nc, types[simtype[TUINT]], pow);
+		}
+		n->typecheck = 0;
+		n->right = nc;
+		break;
+	}
+	goto ret;
+
+divbymul:
+	// try to do division by multiply by (2^w)/d
+	// see hacker's delight chapter 10
+	// TODO: support 64-bit magic multiply here.
+	m.w = w;
+	if(issigned[nl->type->etype]) {
+		m.sd = mpgetfix(nr->val.u.xval);
+		smagic(&m);
+	} else {
+		m.ud = mpgetfix(nr->val.u.xval);
+		umagic(&m);
+	}
+	if(m.bad)
+		return;
+
+	// We have a quick division method so use it
+	// for modulo too.
+	if(n->op == OMOD)
+		goto longmod;
+
+	switch(simtype[nl->type->etype]) {
+	default:
+		return;
+
+	case TUINT8:
+	case TUINT16:
+	case TUINT32:
+		// n1 = nl * magic >> w (HMUL)
+		nc = nod(OXXX, N, N);
+		nodconst(nc, nl->type, m.um);
+		n1 = nod(OMUL, nl, nc);
+		typecheck(&n1, Erv);
+		n1->op = OHMUL;
+		if(m.ua) {
+			// Select a Go type with (at least) twice the width.
+			switch(simtype[nl->type->etype]) {
+			default:
+				return;
+			case TUINT8:
+			case TUINT16:
+				twide = types[TUINT32];
+				break;
+			case TUINT32:
+				twide = types[TUINT64];
+				break;
+			case TINT8:
+			case TINT16:
+				twide = types[TINT32];
+				break;
+			case TINT32:
+				twide = types[TINT64];
+				break;
+			}
+
+			// add numerator (might overflow).
+			// n2 = (n1 + nl)
+			n2 = nod(OADD, conv(n1, twide), conv(nl, twide));
+
+			// shift by m.s
+			nc = nod(OXXX, N, N);
+			nodconst(nc, types[TUINT], m.s);
+			n = conv(nod(ORSH, n2, nc), nl->type);
+		} else {
+			// n = n1 >> m.s
+			nc = nod(OXXX, N, N);
+			nodconst(nc, types[TUINT], m.s);
+			n = nod(ORSH, n1, nc);
+		}
+		break;
+
+	case TINT8:
+	case TINT16:
+	case TINT32:
+		// n1 = nl * magic >> w
+		nc = nod(OXXX, N, N);
+		nodconst(nc, nl->type, m.sm);
+		n1 = nod(OMUL, nl, nc);
+		typecheck(&n1, Erv);
+		n1->op = OHMUL;
+		if(m.sm < 0) {
+			// add the numerator.
+			n1 = nod(OADD, n1, nl);
+		}
+		// shift by m.s
+		nc = nod(OXXX, N, N);
+		nodconst(nc, types[TUINT], m.s);
+		n2 = conv(nod(ORSH, n1, nc), nl->type);
+		// add 1 iff n1 is negative.
+		nc = nod(OXXX, N, N);
+		nodconst(nc, types[TUINT], w-1);
+		n3 = nod(ORSH, nl, nc); // n4 = -1 iff n1 is negative.
+		n = nod(OSUB, n2, n3);
+		// apply sign.
+		if(m.sd < 0)
+			n = nod(OMINUS, n, N);
+		break;
+	}
+	goto ret;
+
+longmod:
+	// rewrite as A%B = A - (A/B*B).
+	n1 = nod(ODIV, nl, nr);
+	n2 = nod(OMUL, n1, nr);
+	n = nod(OSUB, nl, n2);
+	goto ret;
+
+ret:
+	typecheck(&n, Erv);
+	walkexpr(&n, init);
+	*np = n;
+}
+
+// return 1 if integer n must be in range [0, max), 0 otherwise
+static int
+bounded(Node *n, int64 max)
+{
+	int64 v;
+	int32 bits;
+	int sign;
+
+	if(n->type == T || !isint[n->type->etype])
+		return 0;
+
+	sign = issigned[n->type->etype];
+	bits = 8*n->type->width;
+
+	if(smallintconst(n)) {
+		v = mpgetfix(n->val.u.xval);
+		return 0 <= v && v < max;
+	}
+
+	switch(n->op) {
+	case OAND:
+		v = -1;
+		if(smallintconst(n->left)) {
+			v = mpgetfix(n->left->val.u.xval);
+		} else if(smallintconst(n->right)) {
+			v = mpgetfix(n->right->val.u.xval);
+		}
+		if(0 <= v && v < max)
+			return 1;
+		break;
+
+	case OMOD:
+		if(!sign && smallintconst(n->right)) {
+			v = mpgetfix(n->right->val.u.xval);
+			if(0 <= v && v <= max)
+				return 1;
+		}
+		break;
+	
+	case ODIV:
+		if(!sign && smallintconst(n->right)) {
+			v = mpgetfix(n->right->val.u.xval);
+			while(bits > 0 && v >= 2) {
+				bits--;
+				v >>= 1;
+			}
+		}
+		break;
+	
+	case ORSH:
+		if(!sign && smallintconst(n->right)) {
+			v = mpgetfix(n->right->val.u.xval);
+			if(v > bits)
+				return 1;
+			bits -= v;
+		}
+		break;
+	}
+	
+	if(!sign && bits <= 62 && (1LL<<bits) <= max)
+		return 1;
+	
+	return 0;
+}
+
+void
+usefield(Node *n)
+{
+	Type *field, *l;
+
+	if(!fieldtrack_enabled)
+		return;
+
+	switch(n->op) {
+	default:
+		fatal("usefield %O", n->op);
+	case ODOT:
+	case ODOTPTR:
+		break;
+	}
+	
+	field = n->paramfld;
+	if(field == T)
+		fatal("usefield %T %S without paramfld", n->left->type, n->right->sym);
+	if(field->note == nil || strstr(field->note->s, "go:\"track\"") == nil)
+		return;
+
+	// dedup on list
+	if(field->lastfn == curfn)
+		return;
+	field->lastfn = curfn;
+	field->outer = n->left->type;
+	if(isptr[field->outer->etype])
+		field->outer = field->outer->type;
+	if(field->outer->sym == S)
+		yyerror("tracked field must be in named struct type");
+	if(!exportname(field->sym->name))
+		yyerror("tracked field must be exported (upper case)");
+
+	l = typ(0);
+	l->type = field;
+	l->down = curfn->paramfld;
+	curfn->paramfld = l;
+}
+
+static int
+candiscardlist(NodeList *l)
+{
+	for(; l; l=l->next)
+		if(!candiscard(l->n))
+			return 0;
+	return 1;
+}
+
+int
+candiscard(Node *n)
+{
+	if(n == N)
+		return 1;
+	
+	switch(n->op) {
+	default:
+		return 0;
+
+	case ONAME:
+	case ONONAME:
+	case OTYPE:
+	case OPACK:
+	case OLITERAL:
+	case OADD:
+	case OSUB:
+	case OOR:
+	case OXOR:
+	case OADDSTR:
+	case OADDR:
+	case OANDAND:
+	case OARRAYBYTESTR:
+	case OARRAYRUNESTR:
+	case OSTRARRAYBYTE:
+	case OSTRARRAYRUNE:
+	case OCAP:
+	case OCMPIFACE:
+	case OCMPSTR:
+	case OCOMPLIT:
+	case OMAPLIT:
+	case OSTRUCTLIT:
+	case OARRAYLIT:
+	case OPTRLIT:
+	case OCONV:
+	case OCONVIFACE:
+	case OCONVNOP:
+	case ODOT:
+	case OEQ:
+	case ONE:
+	case OLT:
+	case OLE:
+	case OGT:
+	case OGE:
+	case OKEY:
+	case OLEN:
+	case OMUL:
+	case OLSH:
+	case ORSH:
+	case OAND:
+	case OANDNOT:
+	case ONEW:
+	case ONOT:
+	case OCOM:
+	case OPLUS:
+	case OMINUS:
+	case OOROR:
+	case OPAREN:
+	case ORUNESTR:
+	case OREAL:
+	case OIMAG:
+	case OCOMPLEX:
+		// Discardable as long as the subpieces are.
+		break;
+
+	case ODIV:
+	case OMOD:
+		// Discardable as long as we know it's not division by zero.
+		if(isconst(n->right, CTINT) && mpcmpfixc(n->right->val.u.xval, 0) != 0)
+			break;
+		if(isconst(n->right, CTFLT) && mpcmpfltc(n->right->val.u.fval, 0) != 0)
+			break;
+		return 0;
+
+	case OMAKECHAN:
+	case OMAKEMAP:
+		// Discardable as long as we know it won't fail because of a bad size.
+		if(isconst(n->left, CTINT) && mpcmpfixc(n->left->val.u.xval, 0) == 0)
+			break;
+		return 0;
+	
+	case OMAKESLICE:
+		// Difficult to tell what sizes are okay.
+		return 0;		
+	}
+	
+	if(!candiscard(n->left) ||
+	   !candiscard(n->right) ||
+	   !candiscard(n->ntest) ||
+	   !candiscard(n->nincr) ||
+	   !candiscardlist(n->ninit) ||
+	   !candiscardlist(n->nbody) ||
+	   !candiscardlist(n->nelse) ||
+	   !candiscardlist(n->list) ||
+	   !candiscardlist(n->rlist)) {
+		return 0;
+	}
+	
+	return 1;
+}
diff --git a/src/cmd/gc/y.tab.c b/src/cmd/gc/y.tab.c
index 97bf233..7517545 100644
--- a/src/cmd/gc/y.tab.c
+++ b/src/cmd/gc/y.tab.c
@@ -1,21 +1,24 @@
-/* A Bison parser, made by GNU Bison 2.5.  */
+/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Bison implementation for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2011 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.5"
+#define YYBISON_VERSION "2.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -52,52 +55,11 @@
 /* Pure parsers.  */
 #define YYPURE 0
 
-/* Push parsers.  */
-#define YYPUSH 0
-
-/* Pull parsers.  */
-#define YYPULL 1
-
 /* Using locations.  */
 #define YYLSP_NEEDED 0
 
 
 
-/* Copy the first part of user declarations.  */
-
-/* Line 268 of yacc.c  */
-#line 20 "go.y"
-
-#include <u.h>
-#include <stdio.h>	/* if we don't, bison will, and go.h re-#defines getc */
-#include <libc.h>
-#include "go.h"
-
-static void fixlbrace(int);
-
-
-/* Line 268 of yacc.c  */
-#line 81 "y.tab.c"
-
-/* 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 1
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
@@ -106,10 +68,10 @@ static void fixlbrace(int);
    enum yytokentype {
      LLITERAL = 258,
      LASOP = 259,
-     LBREAK = 260,
-     LCASE = 261,
-     LCHAN = 262,
-     LCOLAS = 263,
+     LCOLAS = 260,
+     LBREAK = 261,
+     LCASE = 262,
+     LCHAN = 263,
      LCONST = 264,
      LCONTINUE = 265,
      LDDD = 266,
@@ -158,10 +120,10 @@ static void fixlbrace(int);
 /* Tokens.  */
 #define LLITERAL 258
 #define LASOP 259
-#define LBREAK 260
-#define LCASE 261
-#define LCHAN 262
-#define LCOLAS 263
+#define LCOLAS 260
+#define LBREAK 261
+#define LCASE 262
+#define LCHAN 263
 #define LCONST 264
 #define LCONTINUE 265
 #define LDDD 266
@@ -209,36 +171,61 @@ static void fixlbrace(int);
 
 
 
+/* Copy the first part of user declarations.  */
+#line 20 "go.y"
+
+#include <u.h>
+#include <stdio.h>	/* if we don't, bison will, and go.h re-#defines getc */
+#include <libc.h>
+#include "go.h"
+
+static void fixlbrace(int);
+
+
+/* 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 1
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-{
-
-/* Line 293 of yacc.c  */
 #line 28 "go.y"
-
+{
 	Node*		node;
 	NodeList*		list;
 	Type*		type;
 	Sym*		sym;
 	struct	Val	val;
 	int		i;
-
-
-
-/* Line 293 of yacc.c  */
-#line 230 "y.tab.c"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
+}
+/* Line 193 of yacc.c.  */
+#line 216 "y.tab.c"
+	YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 
+
 /* Copy the second part of user declarations.  */
 
 
-/* Line 343 of yacc.c  */
-#line 242 "y.tab.c"
+/* Line 216 of yacc.c.  */
+#line 229 "y.tab.c"
 
 #ifdef short
 # undef short
@@ -313,14 +300,14 @@ typedef short int yytype_int16;
 #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
 
@@ -341,11 +328,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 */
-#     ifndef EXIT_SUCCESS
-#      define EXIT_SUCCESS 0
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
 #     endif
 #    endif
 #   endif
@@ -368,24 +355,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
@@ -401,9 +388,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)
@@ -414,27 +401,6 @@ union yyalloc
      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
       + YYSTACK_GAP_MAXIMUM)
 
-# define YYCOPY_NEEDED 1
-
-/* 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)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
-
-#endif
-
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
 /* Copy COUNT objects from FROM to TO.  The source and destination do
    not overlap.  */
 # ifndef YYCOPY
@@ -452,21 +418,38 @@ union yyalloc
       while (YYID (0))
 #  endif
 # endif
-#endif /* !YYCOPY_NEEDED */
+
+/* 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)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
 
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  4
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   2131
+#define YYLAST   2194
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  76
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  138
+#define YYNNTS  142
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  344
+#define YYNRULES  349
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  653
+#define YYNSTATES  663
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -524,148 +507,150 @@ static const yytype_uint16 yyprhs[] =
      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,   267,   268,   271,   274,   275,   276,   284,   285,
-     291,   293,   297,   301,   305,   309,   313,   317,   321,   325,
-     329,   333,   337,   341,   345,   349,   353,   357,   361,   365,
-     369,   373,   375,   378,   381,   384,   387,   390,   393,   396,
-     399,   403,   409,   416,   418,   420,   424,   430,   436,   441,
-     448,   450,   455,   461,   467,   475,   477,   478,   482,   484,
-     489,   491,   495,   497,   499,   501,   503,   505,   507,   509,
-     510,   512,   514,   516,   518,   523,   525,   527,   529,   532,
-     534,   536,   538,   540,   542,   546,   548,   550,   552,   555,
-     557,   559,   561,   563,   567,   569,   571,   573,   575,   577,
-     579,   581,   583,   585,   589,   594,   599,   602,   606,   612,
-     614,   616,   619,   623,   629,   633,   639,   643,   647,   653,
-     662,   668,   677,   683,   684,   688,   689,   691,   695,   697,
-     702,   705,   706,   710,   712,   716,   718,   722,   724,   728,
-     730,   734,   736,   740,   744,   747,   752,   756,   762,   768,
-     770,   774,   776,   779,   781,   785,   790,   792,   795,   798,
-     800,   802,   806,   807,   810,   811,   813,   815,   817,   819,
-     821,   823,   825,   827,   829,   830,   835,   837,   840,   843,
-     846,   849,   852,   855,   857,   861,   863,   867,   869,   873,
-     875,   879,   881,   885,   887,   889,   893,   897,   898,   901,
-     902,   904,   905,   907,   908,   910,   911,   913,   914,   916,
-     917,   919,   920,   922,   923,   925,   926,   928,   933,   938,
-     944,   951,   956,   961,   963,   965,   967,   969,   971,   973,
-     975,   977,   979,   983,   988,   994,   999,  1004,  1007,  1010,
-    1015,  1019,  1023,  1029,  1033,  1038,  1042,  1048,  1050,  1051,
-    1053,  1057,  1059,  1061,  1064,  1066,  1068,  1074,  1075,  1078,
-    1080,  1084,  1086,  1090,  1092
+     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,   459,   465,   471,   477,   485,   487,
+     488,   492,   494,   499,   501,   506,   508,   512,   514,   516,
+     518,   520,   522,   524,   526,   527,   529,   531,   533,   535,
+     540,   542,   544,   546,   549,   551,   553,   555,   557,   559,
+     563,   565,   567,   569,   572,   574,   576,   578,   580,   584,
+     586,   588,   590,   592,   594,   596,   598,   600,   602,   606,
+     611,   616,   619,   623,   629,   631,   633,   636,   640,   646,
+     650,   656,   660,   664,   670,   679,   685,   694,   700,   701,
+     705,   706,   708,   712,   714,   719,   722,   723,   727,   729,
+     733,   735,   739,   741,   745,   747,   751,   753,   757,   761,
+     764,   769,   773,   779,   785,   787,   791,   793,   796,   798,
+     802,   807,   809,   812,   815,   817,   819,   823,   824,   827,
+     828,   830,   832,   834,   836,   838,   840,   842,   844,   846,
+     847,   852,   854,   857,   860,   863,   866,   869,   872,   874,
+     878,   880,   884,   886,   890,   892,   896,   898,   902,   904,
+     906,   910,   914,   915,   918,   919,   921,   922,   924,   925,
+     927,   928,   930,   931,   933,   934,   936,   937,   939,   940,
+     942,   943,   945,   950,   955,   961,   968,   973,   978,   980,
+     982,   984,   986,   988,   990,   992,   994,   996,  1000,  1005,
+    1011,  1016,  1021,  1024,  1027,  1032,  1036,  1040,  1046,  1050,
+    1055,  1059,  1065,  1067,  1068,  1070,  1074,  1076,  1078,  1081,
+    1083,  1085,  1091,  1092,  1095,  1097,  1101,  1103,  1107,  1109
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int16 yyrhs[] =
 {
-      77,     0,    -1,    79,    78,    81,   162,    -1,    -1,    25,
-     137,    62,    -1,    -1,    80,    86,    88,    -1,    -1,    81,
-      82,    62,    -1,    21,    83,    -1,    21,    59,    84,   186,
+      77,     0,    -1,    79,    78,    81,   166,    -1,    -1,    25,
+     141,    62,    -1,    -1,    80,    86,    88,    -1,    -1,    81,
+      82,    62,    -1,    21,    83,    -1,    21,    59,    84,   190,
       60,    -1,    21,    59,    60,    -1,    85,    86,    88,    -1,
       85,    88,    -1,    83,    -1,    84,    62,    83,    -1,     3,
-      -1,   137,     3,    -1,    63,     3,    -1,    25,    24,    87,
-      62,    -1,    -1,    24,    -1,    -1,    89,   210,    64,    64,
-      -1,    -1,    91,    -1,   154,    -1,   177,    -1,     1,    -1,
-      32,    93,    -1,    32,    59,   163,   186,    60,    -1,    32,
-      59,    60,    -1,    92,    94,    -1,    92,    59,    94,   186,
-      60,    -1,    92,    59,    94,    62,   164,   186,    60,    -1,
-      92,    59,    60,    -1,    31,    97,    -1,    31,    59,   165,
-     186,    60,    -1,    31,    59,    60,    -1,     9,    -1,   181,
-     142,    -1,   181,   142,    65,   182,    -1,   181,    65,   182,
-      -1,   181,   142,    65,   182,    -1,   181,    65,   182,    -1,
-      94,    -1,   181,   142,    -1,   181,    -1,   137,    -1,    96,
-     142,    -1,   123,    -1,   123,     4,   123,    -1,   182,    65,
-     182,    -1,   182,     8,   182,    -1,   123,    42,    -1,   123,
-      37,    -1,     6,   183,    66,    -1,     6,   183,    65,   123,
-      66,    -1,     6,   183,     8,   123,    66,    -1,    12,    66,
-      -1,    -1,    67,   101,   179,    68,    -1,    -1,    99,   103,
-     179,    -1,    -1,   104,   102,    -1,    -1,    35,   106,   179,
-      68,    -1,   182,    65,    26,   123,    -1,   182,     8,    26,
-     123,    -1,   190,    62,   190,    62,   190,    -1,   190,    -1,
+      -1,   141,     3,    -1,    63,     3,    -1,    25,    24,    87,
+      62,    -1,    -1,    24,    -1,    -1,    89,   214,    64,    64,
+      -1,    -1,    91,    -1,   158,    -1,   181,    -1,     1,    -1,
+      32,    93,    -1,    32,    59,   167,   190,    60,    -1,    32,
+      59,    60,    -1,    92,    94,    -1,    92,    59,    94,   190,
+      60,    -1,    92,    59,    94,    62,   168,   190,    60,    -1,
+      92,    59,    60,    -1,    31,    97,    -1,    31,    59,   169,
+     190,    60,    -1,    31,    59,    60,    -1,     9,    -1,   185,
+     146,    -1,   185,   146,    65,   186,    -1,   185,    65,   186,
+      -1,   185,   146,    65,   186,    -1,   185,    65,   186,    -1,
+      94,    -1,   185,   146,    -1,   185,    -1,   141,    -1,    96,
+     146,    -1,   126,    -1,   126,     4,   126,    -1,   186,    65,
+     186,    -1,   186,     5,   186,    -1,   126,    42,    -1,   126,
+      37,    -1,     7,   187,    66,    -1,     7,   187,    65,   126,
+      66,    -1,     7,   187,     5,   126,    66,    -1,    12,    66,
+      -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,
-     190,    -1,   190,    62,   190,    -1,    -1,    -1,    -1,    20,
-     114,   112,   115,   105,   116,   117,    -1,    -1,    14,   113,
-      -1,    14,   100,    -1,    -1,    -1,    30,   119,   112,   120,
-      35,   104,    68,    -1,    -1,    28,   122,    35,   104,    68,
-      -1,   124,    -1,   123,    47,   123,    -1,   123,    33,   123,
-      -1,   123,    38,   123,    -1,   123,    46,   123,    -1,   123,
-      45,   123,    -1,   123,    43,   123,    -1,   123,    39,   123,
-      -1,   123,    40,   123,    -1,   123,    49,   123,    -1,   123,
-      50,   123,    -1,   123,    51,   123,    -1,   123,    52,   123,
-      -1,   123,    53,   123,    -1,   123,    54,   123,    -1,   123,
-      55,   123,    -1,   123,    56,   123,    -1,   123,    34,   123,
-      -1,   123,    44,   123,    -1,   123,    48,   123,    -1,   123,
-      36,   123,    -1,   130,    -1,    53,   124,    -1,    56,   124,
-      -1,    49,   124,    -1,    50,   124,    -1,    69,   124,    -1,
-      70,   124,    -1,    52,   124,    -1,    36,   124,    -1,   130,
-      59,    60,    -1,   130,    59,   183,   187,    60,    -1,   130,
-      59,   183,    11,   187,    60,    -1,     3,    -1,   139,    -1,
-     130,    63,   137,    -1,   130,    63,    59,   131,    60,    -1,
-     130,    63,    59,    31,    60,    -1,   130,    71,   123,    72,
-      -1,   130,    71,   188,    66,   188,    72,    -1,   125,    -1,
-     145,    59,   123,    60,    -1,   146,   133,   127,   185,    68,
-      -1,   126,    67,   127,   185,    68,    -1,    59,   131,    60,
-      67,   127,   185,    68,    -1,   161,    -1,    -1,   123,    66,
-     129,    -1,   123,    -1,    67,   127,   185,    68,    -1,   126,
-      -1,    59,   131,    60,    -1,   123,    -1,   143,    -1,   142,
-      -1,    35,    -1,    67,    -1,   137,    -1,   137,    -1,    -1,
-     134,    -1,    24,    -1,   138,    -1,    73,    -1,    74,     3,
-      63,    24,    -1,   137,    -1,   134,    -1,    11,    -1,    11,
-     142,    -1,   151,    -1,   157,    -1,   149,    -1,   150,    -1,
-     148,    -1,    59,   142,    60,    -1,   151,    -1,   157,    -1,
-     149,    -1,    53,   143,    -1,   157,    -1,   149,    -1,   150,
-      -1,   148,    -1,    59,   142,    60,    -1,   157,    -1,   149,
-      -1,   149,    -1,   151,    -1,   157,    -1,   149,    -1,   150,
-      -1,   148,    -1,   139,    -1,   139,    63,   137,    -1,    71,
-     188,    72,   142,    -1,    71,    11,    72,   142,    -1,     7,
-     144,    -1,     7,    36,   142,    -1,    23,    71,   142,    72,
-     142,    -1,   152,    -1,   153,    -1,    53,   142,    -1,    36,
-       7,   142,    -1,    29,   133,   166,   186,    68,    -1,    29,
-     133,    68,    -1,    22,   133,   167,   186,    68,    -1,    22,
-     133,    68,    -1,    17,   155,   158,    -1,   137,    59,   175,
-      60,   159,    -1,    59,   175,    60,   137,    59,   175,    60,
-     159,    -1,   196,    59,   191,    60,   206,    -1,    59,   211,
-      60,   137,    59,   191,    60,   206,    -1,    17,    59,   175,
-      60,   159,    -1,    -1,    67,   179,    68,    -1,    -1,   147,
-      -1,    59,   175,    60,    -1,   157,    -1,   160,   133,   179,
-      68,    -1,   160,     1,    -1,    -1,   162,    90,    62,    -1,
-      93,    -1,   163,    62,    93,    -1,    95,    -1,   164,    62,
-      95,    -1,    97,    -1,   165,    62,    97,    -1,   168,    -1,
-     166,    62,   168,    -1,   171,    -1,   167,    62,   171,    -1,
-     180,   142,   194,    -1,   170,   194,    -1,    59,   170,    60,
-     194,    -1,    53,   170,   194,    -1,    59,    53,   170,    60,
-     194,    -1,    53,    59,   170,    60,   194,    -1,    24,    -1,
-      24,    63,   137,    -1,   169,    -1,   134,   172,    -1,   169,
-      -1,    59,   169,    60,    -1,    59,   175,    60,   159,    -1,
-     132,    -1,   137,   132,    -1,   137,   141,    -1,   141,    -1,
-     173,    -1,   174,    75,   173,    -1,    -1,   174,   187,    -1,
-      -1,   100,    -1,    91,    -1,   177,    -1,     1,    -1,    98,
-      -1,   110,    -1,   118,    -1,   121,    -1,   113,    -1,    -1,
-     140,    66,   178,   176,    -1,    15,    -1,     5,   136,    -1,
-      10,   136,    -1,    18,   125,    -1,    13,   125,    -1,    19,
-     134,    -1,    27,   189,    -1,   176,    -1,   179,    62,   176,
-      -1,   134,    -1,   180,    75,   134,    -1,   135,    -1,   181,
-      75,   135,    -1,   123,    -1,   182,    75,   123,    -1,   131,
-      -1,   183,    75,   131,    -1,   128,    -1,   129,    -1,   184,
-      75,   128,    -1,   184,    75,   129,    -1,    -1,   184,   187,
-      -1,    -1,    62,    -1,    -1,    75,    -1,    -1,   123,    -1,
-      -1,   182,    -1,    -1,    98,    -1,    -1,   211,    -1,    -1,
-     212,    -1,    -1,   213,    -1,    -1,     3,    -1,    21,    24,
-       3,    62,    -1,    32,   196,   198,    62,    -1,     9,   196,
-      65,   209,    62,    -1,     9,   196,   198,    65,   209,    62,
-      -1,    31,   197,   198,    62,    -1,    17,   156,   158,    62,
-      -1,   138,    -1,   196,    -1,   200,    -1,   201,    -1,   202,
-      -1,   200,    -1,   202,    -1,   138,    -1,    24,    -1,    71,
-      72,   198,    -1,    71,     3,    72,   198,    -1,    23,    71,
-     198,    72,   198,    -1,    29,    67,   192,    68,    -1,    22,
-      67,   193,    68,    -1,    53,   198,    -1,     7,   199,    -1,
-       7,    59,   201,    60,    -1,     7,    36,   198,    -1,    36,
-       7,   198,    -1,    17,    59,   191,    60,   206,    -1,   137,
-     198,   194,    -1,   137,    11,   198,   194,    -1,   137,   198,
-     194,    -1,   137,    59,   191,    60,   206,    -1,   198,    -1,
-      -1,   207,    -1,    59,   191,    60,    -1,   198,    -1,     3,
-      -1,    50,     3,    -1,   137,    -1,   208,    -1,    59,   208,
-      49,   208,    60,    -1,    -1,   210,   195,    -1,   203,    -1,
-     211,    75,   203,    -1,   204,    -1,   212,    62,   204,    -1,
-     205,    -1,   213,    62,   205,    -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,   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,
+     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.  */
@@ -676,36 +661,36 @@ static const yytype_uint16 yyrline[] =
      259,   260,   267,   267,   280,   284,   285,   289,   294,   300,
      304,   308,   312,   318,   324,   330,   335,   339,   343,   349,
      355,   359,   363,   369,   373,   379,   380,   384,   390,   399,
-     405,   409,   414,   426,   442,   447,   454,   474,   492,   501,
-     520,   519,   531,   530,   561,   564,   571,   570,   581,   587,
-     596,   607,   613,   616,   624,   623,   634,   640,   652,   656,
-     661,   651,   673,   676,   680,   687,   691,   686,   709,   708,
-     724,   725,   729,   733,   737,   741,   745,   749,   753,   757,
-     761,   765,   769,   773,   777,   781,   785,   789,   793,   797,
-     802,   808,   809,   813,   824,   828,   832,   836,   841,   845,
-     855,   859,   864,   872,   876,   877,   888,   892,   896,   900,
-     904,   905,   911,   918,   924,   931,   934,   941,   947,   948,
-     955,   956,   974,   975,   978,   981,   985,   996,  1005,  1011,
-    1014,  1017,  1024,  1025,  1031,  1040,  1048,  1060,  1065,  1071,
-    1072,  1073,  1074,  1075,  1076,  1082,  1083,  1084,  1085,  1091,
-    1092,  1093,  1094,  1095,  1101,  1102,  1105,  1108,  1109,  1110,
-    1111,  1112,  1115,  1116,  1129,  1133,  1138,  1143,  1148,  1152,
-    1153,  1156,  1162,  1169,  1175,  1182,  1188,  1199,  1210,  1239,
-    1278,  1301,  1318,  1327,  1330,  1338,  1342,  1346,  1353,  1359,
-    1364,  1376,  1379,  1387,  1388,  1394,  1395,  1401,  1405,  1411,
-    1412,  1418,  1422,  1428,  1451,  1456,  1462,  1468,  1475,  1484,
-    1493,  1508,  1514,  1519,  1523,  1530,  1543,  1544,  1550,  1556,
-    1559,  1563,  1569,  1572,  1581,  1584,  1585,  1589,  1590,  1596,
-    1597,  1598,  1599,  1600,  1602,  1601,  1616,  1621,  1625,  1629,
-    1633,  1637,  1642,  1661,  1667,  1675,  1679,  1685,  1689,  1695,
-    1699,  1705,  1709,  1718,  1722,  1726,  1730,  1736,  1739,  1747,
-    1748,  1750,  1751,  1754,  1757,  1760,  1763,  1766,  1769,  1772,
-    1775,  1778,  1781,  1784,  1787,  1790,  1793,  1799,  1803,  1807,
-    1811,  1815,  1819,  1837,  1844,  1855,  1856,  1857,  1860,  1861,
-    1864,  1868,  1878,  1882,  1886,  1890,  1894,  1898,  1902,  1908,
-    1914,  1922,  1930,  1936,  1943,  1959,  1977,  1981,  1987,  1990,
-    1993,  1997,  2007,  2011,  2026,  2034,  2035,  2045,  2046,  2049,
-    2053,  2059,  2063,  2069,  2073
+     405,   423,   428,   440,   456,   461,   468,   488,   506,   515,
+     534,   533,   545,   544,   575,   578,   585,   584,   595,   601,
+     610,   621,   627,   630,   638,   637,   648,   654,   666,   670,
+     675,   665,   696,   695,   708,   711,   717,   720,   732,   736,
+     731,   754,   753,   769,   770,   774,   778,   782,   786,   790,
+     794,   798,   802,   806,   810,   814,   818,   822,   826,   830,
+     834,   838,   842,   847,   853,   854,   858,   869,   873,   877,
+     881,   886,   890,   900,   904,   909,   917,   921,   922,   933,
+     937,   941,   945,   949,   950,   956,   963,   969,   976,   979,
+     986,   992,  1009,  1016,  1017,  1024,  1025,  1044,  1045,  1048,
+    1051,  1055,  1066,  1075,  1081,  1084,  1087,  1094,  1095,  1101,
+    1116,  1124,  1136,  1141,  1147,  1148,  1149,  1150,  1151,  1152,
+    1158,  1159,  1160,  1161,  1167,  1168,  1169,  1170,  1171,  1177,
+    1178,  1181,  1184,  1185,  1186,  1187,  1188,  1191,  1192,  1205,
+    1209,  1214,  1219,  1224,  1228,  1229,  1232,  1238,  1245,  1251,
+    1258,  1264,  1275,  1289,  1318,  1358,  1383,  1401,  1410,  1413,
+    1421,  1425,  1429,  1436,  1442,  1447,  1459,  1462,  1472,  1473,
+    1479,  1480,  1486,  1490,  1496,  1497,  1503,  1507,  1513,  1536,
+    1541,  1547,  1553,  1560,  1569,  1578,  1593,  1599,  1604,  1608,
+    1615,  1628,  1629,  1635,  1641,  1644,  1648,  1654,  1657,  1666,
+    1669,  1670,  1674,  1675,  1681,  1682,  1683,  1684,  1685,  1687,
+    1686,  1701,  1706,  1710,  1714,  1718,  1722,  1727,  1746,  1752,
+    1760,  1764,  1770,  1774,  1780,  1784,  1790,  1794,  1803,  1807,
+    1811,  1815,  1821,  1824,  1832,  1833,  1835,  1836,  1839,  1842,
+    1845,  1848,  1851,  1854,  1857,  1860,  1863,  1866,  1869,  1872,
+    1875,  1878,  1884,  1888,  1892,  1896,  1900,  1904,  1924,  1931,
+    1942,  1943,  1944,  1947,  1948,  1951,  1955,  1965,  1969,  1973,
+    1977,  1981,  1985,  1989,  1995,  2001,  2009,  2017,  2023,  2030,
+    2046,  2064,  2068,  2074,  2077,  2080,  2084,  2094,  2098,  2113,
+    2121,  2122,  2134,  2135,  2138,  2142,  2148,  2152,  2158,  2162
 };
 #endif
 
@@ -714,8 +699,8 @@ static const yytype_uint16 yyrline[] =
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 const char *yytname[] =
 {
-  "$end", "error", "$undefined", "LLITERAL", "LASOP", "LBREAK", "LCASE",
-  "LCHAN", "LCOLAS", "LCONST", "LCONTINUE", "LDDD", "LDEFAULT", "LDEFER",
+  "$end", "error", "$undefined", "LLITERAL", "LASOP", "LCOLAS", "LBREAK",
+  "LCASE", "LCHAN", "LCONST", "LCONTINUE", "LDDD", "LDEFAULT", "LDEFER",
   "LELSE", "LFALL", "LFOR", "LFUNC", "LGO", "LGOTO", "LIF", "LIMPORT",
   "LINTERFACE", "LMAP", "LNAME", "LPACKAGE", "LRANGE", "LRETURN",
   "LSELECT", "LSTRUCT", "LSWITCH", "LTYPE", "LVAR", "LANDAND", "LANDNOT",
@@ -724,30 +709,31 @@ const char *yytname[] =
   "'/'", "'%'", "'&'", "NotPackage", "NotParen", "'('", "')'",
   "PreferToRightParen", "';'", "'.'", "'$'", "'='", "':'", "'{'", "'}'",
   "'!'", "'~'", "'['", "']'", "'?'", "'@'", "','", "$accept", "file",
-  "package", "loadsys", "$@1", "imports", "import", "import_stmt",
+  "package", "loadsys", "@1", "imports", "import", "import_stmt",
   "import_stmt_list", "import_here", "import_package", "import_safety",
-  "import_there", "$@2", "xdcl", "common_dcl", "lconst", "vardcl",
+  "import_there", "@2", "xdcl", "common_dcl", "lconst", "vardcl",
   "constdcl", "constdcl1", "typedclname", "typedcl", "simple_stmt", "case",
-  "compound_stmt", "$@3", "caseblock", "$@4", "caseblock_list",
-  "loop_body", "$@5", "range_stmt", "for_header", "for_body", "for_stmt",
-  "$@6", "if_header", "if_stmt", "$@7", "$@8", "$@9", "else",
-  "switch_stmt", "$@10", "$@11", "select_stmt", "$@12", "expr", "uexpr",
-  "pseudocall", "pexpr_no_paren", "start_complit", "keyval", "complitexpr",
-  "pexpr", "expr_or_type", "name_or_type", "lbrace", "new_name",
-  "dcl_name", "onew_name", "sym", "hidden_importsym", "name", "labelname",
-  "dotdotdot", "ntype", "non_expr_type", "non_recvchantype", "convtype",
-  "comptype", "fnret_type", "dotname", "othertype", "ptrtype",
-  "recvchantype", "structtype", "interfacetype", "xfndcl", "fndcl",
-  "hidden_fndcl", "fntype", "fnbody", "fnres", "fnlitdcl", "fnliteral",
-  "xdcl_list", "vardcl_list", "constdcl_list", "typedcl_list",
-  "structdcl_list", "interfacedcl_list", "structdcl", "packname", "embed",
-  "interfacedcl", "indcl", "arg_type", "arg_type_list",
-  "oarg_type_list_ocomma", "stmt", "non_dcl_stmt", "$@13", "stmt_list",
-  "new_name_list", "dcl_name_list", "expr_list", "expr_or_type_list",
-  "keyval_list", "braced_keyval_list", "osemi", "ocomma", "oexpr",
-  "oexpr_list", "osimple_stmt", "ohidden_funarg_list",
-  "ohidden_structdcl_list", "ohidden_interfacedcl_list", "oliteral",
-  "hidden_import", "hidden_pkg_importsym", "hidden_pkgtype", "hidden_type",
+  "compound_stmt", "@3", "caseblock", "@4", "caseblock_list", "loop_body",
+  "@5", "range_stmt", "for_header", "for_body", "for_stmt", "@6",
+  "if_header", "if_stmt", "@7", "@8", "@9", "elseif", "@10", "elseif_list",
+  "else", "switch_stmt", "@11", "@12", "select_stmt", "@13", "expr",
+  "uexpr", "pseudocall", "pexpr_no_paren", "start_complit", "keyval",
+  "bare_complitexpr", "complitexpr", "pexpr", "expr_or_type",
+  "name_or_type", "lbrace", "new_name", "dcl_name", "onew_name", "sym",
+  "hidden_importsym", "name", "labelname", "dotdotdot", "ntype",
+  "non_expr_type", "non_recvchantype", "convtype", "comptype",
+  "fnret_type", "dotname", "othertype", "ptrtype", "recvchantype",
+  "structtype", "interfacetype", "xfndcl", "fndcl", "hidden_fndcl",
+  "fntype", "fnbody", "fnres", "fnlitdcl", "fnliteral", "xdcl_list",
+  "vardcl_list", "constdcl_list", "typedcl_list", "structdcl_list",
+  "interfacedcl_list", "structdcl", "packname", "embed", "interfacedcl",
+  "indcl", "arg_type", "arg_type_list", "oarg_type_list_ocomma", "stmt",
+  "non_dcl_stmt", "@14", "stmt_list", "new_name_list", "dcl_name_list",
+  "expr_list", "expr_or_type_list", "keyval_list", "braced_keyval_list",
+  "osemi", "ocomma", "oexpr", "oexpr_list", "osimple_stmt",
+  "ohidden_funarg_list", "ohidden_structdcl_list",
+  "ohidden_interfacedcl_list", "oliteral", "hidden_import",
+  "hidden_pkg_importsym", "hidden_pkgtype", "hidden_type",
   "hidden_type_non_recv_chan", "hidden_type_misc", "hidden_type_recv_chan",
   "hidden_type_func", "hidden_funarg", "hidden_structdcl",
   "hidden_interfacedcl", "ohidden_funres", "hidden_funres",
@@ -784,33 +770,33 @@ static const yytype_uint8 yyr1[] =
       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,   117,   117,   117,   119,   120,   118,   122,   121,
-     123,   123,   123,   123,   123,   123,   123,   123,   123,   123,
-     123,   123,   123,   123,   123,   123,   123,   123,   123,   123,
-     123,   124,   124,   124,   124,   124,   124,   124,   124,   124,
-     125,   125,   125,   126,   126,   126,   126,   126,   126,   126,
-     126,   126,   126,   126,   126,   126,   127,   128,   129,   129,
-     130,   130,   131,   131,   132,   133,   133,   134,   135,   136,
-     136,   137,   137,   137,   138,   139,   140,   141,   141,   142,
-     142,   142,   142,   142,   142,   143,   143,   143,   143,   144,
-     144,   144,   144,   144,   145,   145,   146,   147,   147,   147,
-     147,   147,   148,   148,   149,   149,   149,   149,   149,   149,
-     149,   150,   151,   152,   152,   153,   153,   154,   155,   155,
-     156,   156,   157,   158,   158,   159,   159,   159,   160,   161,
-     161,   162,   162,   163,   163,   164,   164,   165,   165,   166,
-     166,   167,   167,   168,   168,   168,   168,   168,   168,   169,
-     169,   170,   171,   171,   171,   172,   173,   173,   173,   173,
-     174,   174,   175,   175,   176,   176,   176,   176,   176,   177,
-     177,   177,   177,   177,   178,   177,   177,   177,   177,   177,
-     177,   177,   177,   179,   179,   180,   180,   181,   181,   182,
-     182,   183,   183,   184,   184,   184,   184,   185,   185,   186,
-     186,   187,   187,   188,   188,   189,   189,   190,   190,   191,
-     191,   192,   192,   193,   193,   194,   194,   195,   195,   195,
-     195,   195,   195,   196,   197,   198,   198,   198,   199,   199,
-     200,   200,   200,   200,   200,   200,   200,   200,   200,   200,
-     200,   201,   202,   203,   203,   204,   205,   205,   206,   206,
-     207,   207,   208,   208,   208,   209,   209,   210,   210,   211,
-     211,   212,   212,   213,   213
+     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,   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,
+     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.  */
@@ -824,663 +810,674 @@ static const yytype_uint8 yyr2[] =
        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,     7,     0,     2,     2,     0,     0,     7,     0,     5,
-       1,     3,     3,     3,     3,     3,     3,     3,     3,     3,
+       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,     1,     2,     2,     2,     2,     2,     2,     2,     2,
-       3,     5,     6,     1,     1,     3,     5,     5,     4,     6,
-       1,     4,     5,     5,     7,     1,     0,     3,     1,     4,
-       1,     3,     1,     1,     1,     1,     1,     1,     1,     0,
-       1,     1,     1,     1,     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,     1,     2,     2,     2,     2,     2,
+       2,     2,     2,     3,     5,     6,     1,     1,     3,     5,
+       5,     4,     6,     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,
+       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 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_uint16 yydefact[] =
 {
-       5,     0,     3,     0,     1,     0,     7,     0,    22,   151,
-     153,     0,     0,   152,   211,    20,     6,   337,     0,     4,
+       5,     0,     3,     0,     1,     0,     7,     0,    22,   156,
+     158,     0,     0,   157,   216,    20,     6,   342,     0,     4,
        0,     0,     0,    21,     0,     0,     0,    16,     0,     0,
-       9,    22,     0,     8,    28,   123,   149,     0,    39,   149,
-       0,   256,    74,     0,     0,     0,    78,     0,     0,   285,
-      88,     0,    85,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   283,     0,    25,     0,   249,   250,
-     253,   251,   252,    50,    90,   130,   140,   111,   156,   155,
-     124,     0,     0,     0,   176,   189,   190,    26,   208,     0,
-     135,    27,     0,    19,     0,     0,     0,     0,     0,     0,
-     338,   154,    11,    14,   279,    18,    22,    13,    17,   150,
-     257,   147,     0,     0,     0,     0,   155,   182,   186,   172,
-     170,   171,   169,   258,   130,     0,   287,   242,     0,   203,
-     130,   261,   287,   145,   146,     0,     0,   269,   286,   262,
-       0,     0,   287,     0,     0,    36,    48,     0,    29,   267,
-     148,     0,   119,   114,   115,   118,   112,   113,     0,     0,
-     142,     0,   143,   167,   165,   166,   116,   117,     0,   284,
-       0,   212,     0,    32,     0,     0,     0,     0,     0,    55,
+       9,    22,     0,     8,    28,   126,   154,     0,    39,   154,
+       0,   261,    74,     0,     0,     0,    78,     0,     0,   290,
+      91,     0,    88,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   288,     0,    25,     0,   254,   255,
+     258,   256,   257,    50,    93,   133,   145,   114,   161,   160,
+     127,     0,     0,     0,   181,   194,   195,    26,   213,     0,
+     138,    27,     0,    19,     0,     0,     0,     0,     0,     0,
+     343,   159,    11,    14,   284,    18,    22,    13,    17,   155,
+     262,   152,     0,     0,     0,     0,   160,   187,   191,   177,
+     175,   176,   174,   263,   133,     0,   292,   247,     0,   208,
+     133,   266,   292,   150,   151,     0,     0,   274,   291,   267,
+       0,     0,   292,     0,     0,    36,    48,     0,    29,   272,
+     153,     0,   122,   117,   118,   121,   115,   116,     0,     0,
+     147,     0,   148,   172,   170,   171,   119,   120,     0,   289,
+       0,   217,     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,   136,     0,
-       0,   283,   254,     0,   136,   210,     0,     0,     0,     0,
-     303,     0,     0,   203,     0,     0,   304,     0,     0,    23,
-     280,     0,    12,   242,     0,     0,   187,   163,   161,   162,
-     159,   160,   191,     0,     0,   288,    72,     0,    75,     0,
-      71,   157,   236,   155,   239,   144,   240,   281,     0,   242,
-       0,   197,    79,    76,   151,     0,   196,     0,   279,   233,
-     221,     0,    64,     0,     0,   194,   265,   279,   219,   231,
-     295,     0,    86,    38,   217,   279,    49,    31,   213,   279,
-       0,     0,    40,     0,   168,   141,     0,     0,    35,   279,
-       0,     0,    51,    92,   107,   110,    93,    97,    98,    96,
-     108,    95,    94,    91,   109,    99,   100,   101,   102,   103,
-     104,   105,   106,   277,   120,   271,   281,     0,   125,   284,
-       0,     0,     0,   277,   248,    60,   246,   245,   263,   247,
-       0,    53,    52,   270,     0,     0,     0,     0,   311,     0,
-       0,     0,     0,     0,   310,     0,   305,   306,   307,     0,
-     339,     0,     0,   289,     0,     0,     0,    15,    10,     0,
-       0,     0,   173,   183,    66,    73,     0,     0,   287,   158,
-     237,   238,   282,   243,   205,     0,     0,     0,   287,     0,
-     229,     0,   242,   232,   280,     0,     0,     0,     0,   295,
-       0,     0,   280,     0,   296,   224,     0,   295,     0,   280,
-       0,   280,     0,    42,   268,     0,     0,     0,   192,   163,
-     161,   162,   160,   136,   185,   184,   280,     0,    44,     0,
-     136,   138,   273,   274,   281,     0,   281,   282,     0,     0,
-       0,   128,   283,   255,   131,     0,     0,     0,   209,     0,
-       0,   318,   308,   309,   289,   293,     0,   291,     0,   317,
-     332,     0,     0,   334,   335,     0,     0,     0,     0,     0,
-     295,     0,     0,   302,     0,   290,   297,   301,   298,   205,
-     164,     0,     0,     0,     0,   241,   242,   155,   206,   181,
-     179,   180,   177,   178,   202,   205,   204,    80,    77,   230,
-     234,     0,   222,   195,   188,     0,     0,    89,    62,    65,
-       0,   226,     0,   295,   220,   193,   266,   223,    64,   218,
-      37,   214,    30,    41,     0,   277,    45,   215,   279,    47,
-      33,    43,   277,     0,   282,   278,   133,   282,     0,   272,
-     121,   127,   126,     0,   132,     0,   264,   320,     0,     0,
-     311,     0,   310,     0,   327,   343,   294,     0,     0,     0,
-     341,   292,   321,   333,     0,   299,     0,   312,     0,   295,
-     323,     0,   340,   328,     0,    69,    68,   287,     0,   242,
-     198,    82,   205,     0,    59,     0,   295,   295,   225,     0,
-     164,     0,   280,     0,    46,     0,   138,   137,   275,   276,
-     122,   129,    61,   319,   328,   289,   316,     0,     0,   295,
-     315,     0,     0,   313,   300,   324,   289,   289,   331,   200,
-     329,    67,    70,   207,     0,     0,    81,   235,     0,     0,
-      56,     0,    63,   228,   227,    87,   134,   216,    34,   139,
-     322,     0,   344,   314,   325,   342,     0,     0,     0,   205,
-      84,    83,     0,     0,   328,   336,   328,   330,   199,    58,
-      57,   326,   201
+       0,     0,     0,     0,     0,     0,     0,     0,   139,     0,
+       0,   288,   259,     0,   139,   215,     0,     0,     0,     0,
+     308,     0,     0,   208,     0,     0,   309,     0,     0,    23,
+     285,     0,    12,   247,     0,     0,   192,   168,   166,   167,
+     164,   165,   196,     0,     0,   293,    72,     0,    75,     0,
+      71,   162,   241,   160,   244,   149,   245,   286,     0,   247,
+       0,   202,    79,    76,   156,     0,   201,     0,   284,   238,
+     226,     0,    64,     0,     0,   199,   270,   284,   224,   236,
+     300,     0,    89,    38,   222,   284,    49,    31,   218,   284,
+       0,     0,    40,     0,   173,   146,     0,     0,    35,   284,
+       0,     0,    51,    95,   110,   113,    96,   100,   101,    99,
+     111,    98,    97,    94,   112,   102,   103,   104,   105,   106,
+     107,   108,   109,   282,   123,   276,   286,     0,   128,   289,
+       0,     0,   286,   282,   253,    60,   251,   250,   268,   252,
+       0,    53,    52,   275,     0,     0,     0,     0,   316,     0,
+       0,     0,     0,     0,   315,     0,   310,   311,   312,     0,
+     344,     0,     0,   294,     0,     0,     0,    15,    10,     0,
+       0,     0,   178,   188,    66,    73,     0,     0,   292,   163,
+     242,   243,   287,   248,   210,     0,     0,     0,   292,     0,
+     234,     0,   247,   237,   285,     0,     0,     0,     0,   300,
+       0,     0,   285,     0,   301,   229,     0,   300,     0,   285,
+       0,   285,     0,    42,   273,     0,     0,     0,   197,   168,
+     166,   167,   165,   139,   190,   189,   285,     0,    44,     0,
+     139,   141,   278,   279,   286,     0,   286,   287,     0,     0,
+       0,   131,   288,   260,   287,     0,     0,     0,     0,   214,
+       0,     0,   323,   313,   314,   294,   298,     0,   296,     0,
+     322,   337,     0,     0,   339,   340,     0,     0,     0,     0,
+       0,   300,     0,     0,   307,     0,   295,   302,   306,   303,
+     210,   169,     0,     0,     0,     0,   246,   247,   160,   211,
+     186,   184,   185,   182,   183,   207,   210,   209,    80,    77,
+     235,   239,     0,   227,   200,   193,     0,     0,    92,    62,
+      65,     0,   231,     0,   300,   225,   198,   271,   228,    64,
+     223,    37,   219,    30,    41,     0,   282,    45,   220,   284,
+      47,    33,    43,   282,     0,   287,   283,   136,     0,   277,
+     124,   130,   129,     0,   134,   135,     0,   269,   325,     0,
+       0,   316,     0,   315,     0,   332,   348,   299,     0,     0,
+       0,   346,   297,   326,   338,     0,   304,     0,   317,     0,
+     300,   328,     0,   345,   333,     0,    69,    68,   292,     0,
+     247,   203,    84,   210,     0,    59,     0,   300,   300,   230,
+       0,   169,     0,   285,     0,    46,     0,   139,   143,   140,
+     280,   281,   125,   132,    61,   324,   333,   294,   321,     0,
+       0,   300,   320,     0,     0,   318,   305,   329,   294,   294,
+     336,   205,   334,    67,    70,   212,     0,    86,   240,     0,
+       0,    56,     0,    63,   233,   232,    90,   137,   221,    34,
+     142,   282,   327,     0,   349,   319,   330,   347,     0,     0,
+       0,   210,     0,    85,    81,     0,     0,     0,   333,   341,
+     333,   335,   204,    82,    87,    58,    57,   144,   331,   206,
+     292,     0,    83
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
       -1,     1,     6,     2,     3,    14,    21,    30,   104,    31,
-       8,    24,    16,    17,    65,   326,    67,   148,   516,   517,
-     144,   145,    68,   498,   327,   436,   499,   575,   387,   365,
-     471,   236,   237,   238,    69,   126,   252,    70,   132,   377,
-     571,   616,    71,   142,   398,    72,   140,    73,    74,    75,
-      76,   313,   422,   423,    77,   315,   242,   135,    78,   149,
-     110,   116,    13,    80,    81,   244,   245,   162,   118,    82,
-      83,   478,   227,    84,   229,   230,    85,    86,    87,   129,
-     213,    88,   251,   484,    89,    90,    22,   279,   518,   275,
-     267,   258,   268,   269,   270,   260,   383,   246,   247,   248,
-     328,   329,   321,   330,   271,   151,    92,   316,   424,   425,
-     221,   373,   170,   139,   253,   464,   549,   543,   395,   100,
-     211,   217,   608,   441,   346,   347,   348,   350,   550,   545,
-     609,   610,   454,   455,    25,   465,   551,   546
+       8,    24,    16,    17,    65,   326,    67,   148,   517,   518,
+     144,   145,    68,   499,   327,   437,   500,   576,   387,   365,
+     472,   236,   237,   238,    69,   126,   252,    70,   132,   377,
+     572,   643,   660,   617,   644,    71,   142,   398,    72,   140,
+      73,    74,    75,    76,   313,   422,   423,   589,    77,   315,
+     242,   135,    78,   149,   110,   116,    13,    80,    81,   244,
+     245,   162,   118,    82,    83,   479,   227,    84,   229,   230,
+      85,    86,    87,   129,   213,    88,   251,   485,    89,    90,
+      22,   279,   519,   275,   267,   258,   268,   269,   270,   260,
+     383,   246,   247,   248,   328,   329,   321,   330,   271,   151,
+      92,   316,   424,   425,   221,   373,   170,   139,   253,   465,
+     550,   544,   395,   100,   211,   217,   610,   442,   346,   347,
+     348,   350,   551,   546,   611,   612,   455,   456,    25,   466,
+     552,   547
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -551
+#define YYPACT_NINF -485
 static const yytype_int16 yypact[] =
 {
-    -551,    46,    48,   121,  -551,    58,  -551,   135,  -551,  -551,
-    -551,    65,    72,  -551,   147,   156,  -551,  -551,   112,  -551,
-      50,   134,   904,  -551,   162,   463,   209,  -551,    54,   237,
-    -551,   121,   245,  -551,  -551,  -551,    58,  1666,  -551,    58,
-     288,  -551,  -551,    34,   288,    58,  -551,    36,   184,  1467,
-    -551,    36,  -551,   316,   462,  1467,  1467,  1467,  1467,  1467,
-    1467,  1522,  1467,  1467,   965,   198,  -551,   506,  -551,  -551,
-    -551,  -551,  -551,   796,  -551,  -551,   195,     1,  -551,   199,
-    -551,   207,   216,    36,   221,  -551,  -551,  -551,   226,    53,
-    -551,  -551,   108,  -551,   214,   110,   269,   214,   214,   233,
-    -551,  -551,  -551,  -551,   238,  -551,  -551,  -551,  -551,  -551,
-    -551,  -551,   242,  1691,  1691,  1691,  -551,   240,  -551,  -551,
-    -551,  -551,  -551,  -551,   154,     1,  1467,  1658,   247,   246,
-     290,  -551,  1467,  -551,  -551,   419,  1691,  2004,   229,  -551,
-     272,   333,  1467,   258,  1691,  -551,  -551,   485,  -551,  -551,
-    -551,   656,  -551,  -551,  -551,  -551,  -551,  -551,  1577,  1522,
-    2004,   255,  -551,    10,  -551,    51,  -551,  -551,   251,  2004,
-     256,  -551,   508,  -551,  1632,  1467,  1467,  1467,  1467,  -551,
-    1467,  1467,  1467,  -551,  1467,  1467,  1467,  1467,  1467,  1467,
-    1467,  1467,  1467,  1467,  1467,  1467,  1467,  1467,  -551,  1192,
-     552,  1467,  -551,  1467,  -551,  -551,  1134,  1467,  1467,  1467,
-    -551,  1203,    58,   246,   260,   332,  -551,  1838,  1838,  -551,
-      76,   282,  -551,  1658,   344,  1691,  -551,  -551,  -551,  -551,
-    -551,  -551,  -551,   293,    58,  -551,  -551,   328,  -551,   178,
-     303,  1691,  -551,  1658,  -551,  -551,  -551,   295,   308,  1658,
-    1134,  -551,  -551,   309,   271,   364,  -551,   334,   337,  -551,
-    -551,   330,  -551,    11,    66,  -551,  -551,   342,  -551,  -551,
-     397,   664,  -551,  -551,  -551,   351,  -551,  -551,  -551,   352,
-    1467,    58,   343,  1719,  -551,   349,  1691,  1691,  -551,   356,
-    1467,   357,  2004,  2075,  -551,  2028,   692,   692,   692,   692,
-    -551,   692,   692,  2052,  -551,   593,   593,   593,   593,  -551,
-    -551,  -551,  -551,  1247,  -551,  -551,    22,  1302,  -551,  1877,
-     355,  1060,  1979,  1247,  -551,  -551,  -551,  -551,  -551,  -551,
-      86,   229,   229,  2004,  1777,   367,   361,   359,  -551,   366,
-     427,  1838,    52,    29,  -551,   370,  -551,  -551,  -551,   784,
-    -551,   118,   379,    58,   396,   400,   401,  -551,  -551,   404,
-    1691,   409,  -551,  -551,  -551,  -551,  1357,  1412,  1467,  -551,
-    -551,  -551,  1658,  -551,  1744,   414,   109,   328,  1467,    58,
-     416,   423,  1658,  -551,   561,   417,  1691,    44,   364,   397,
-     364,   428,   451,   421,  -551,  -551,    58,   397,   456,    58,
-     436,    58,   438,   229,  -551,  1467,  1752,  1691,  -551,    24,
-     171,   287,   338,  -551,  -551,  -551,    58,   439,   229,  1467,
-    -551,  1907,  -551,  -551,   425,   435,   430,  1522,   446,   448,
-     453,  -551,  1467,  -551,  -551,   443,  1134,  1060,  -551,  1838,
-     479,  -551,  -551,  -551,    58,  1805,  1838,    58,  1838,  -551,
-    -551,   514,   161,  -551,  -551,   460,   454,  1838,    52,  1838,
-     397,    58,    58,  -551,   458,   459,  -551,  -551,  -551,  1744,
-    -551,  1134,  1467,  1467,   467,  -551,  1658,   472,  -551,  -551,
-    -551,  -551,  -551,  -551,  -551,  1744,  -551,  -551,  -551,  -551,
-    -551,   477,  -551,  -551,  -551,  1522,   474,  -551,  -551,  -551,
-     482,  -551,   500,   397,  -551,  -551,  -551,  -551,  -551,  -551,
-    -551,  -551,  -551,   229,   501,  1247,  -551,  -551,   505,  1632,
-    -551,   229,  1247,  1247,  1247,  -551,  -551,  -551,   503,  -551,
-    -551,  -551,  -551,   511,  -551,   137,  -551,  -551,   518,   528,
-     532,   534,   535,   530,  -551,  -551,   537,   533,  1838,   536,
-    -551,   538,  -551,  -551,   560,  -551,  1838,  -551,   551,   397,
-    -551,   557,  -551,  1830,   151,  2004,  2004,  1467,   558,  1658,
-    -551,   605,  1744,   125,  -551,  1060,   397,   397,  -551,    75,
-     360,   554,    58,   563,   357,   556,  2004,  -551,  -551,  -551,
-    -551,  -551,  -551,  -551,  1830,    58,  -551,  1805,  1838,   397,
-    -551,    58,   161,  -551,  -551,  -551,    58,    58,  -551,  -551,
-    -551,  -551,  -551,  -551,   570,    78,  -551,  -551,  1467,  1467,
-    -551,  1522,   569,  -551,  -551,  -551,  -551,  -551,  -551,  -551,
-    -551,   576,  -551,  -551,  -551,  -551,   578,   582,   584,  1744,
-    -551,  -551,  1931,  1955,  1830,  -551,  1830,  -551,  -551,  -551,
-    -551,  -551,  -551
+    -485,    67,    35,    55,  -485,    44,  -485,    64,  -485,  -485,
+    -485,    96,    38,  -485,    77,    85,  -485,  -485,    66,  -485,
+      34,    84,  1059,  -485,    86,   294,   147,  -485,   165,   210,
+    -485,    55,   221,  -485,  -485,  -485,    44,  1762,  -485,    44,
+     290,  -485,  -485,   442,   290,    44,  -485,    80,    69,  1608,
+    -485,    80,  -485,   450,   452,  1608,  1608,  1608,  1608,  1608,
+    1608,  1651,  1608,  1608,   920,   157,  -485,   460,  -485,  -485,
+    -485,  -485,  -485,   718,  -485,  -485,   167,   344,  -485,   176,
+    -485,   180,   193,    80,   206,  -485,  -485,  -485,   218,    91,
+    -485,  -485,    76,  -485,   205,    10,   260,   205,   205,   223,
+    -485,  -485,  -485,  -485,   230,  -485,  -485,  -485,  -485,  -485,
+    -485,  -485,   237,  1770,  1770,  1770,  -485,   236,  -485,  -485,
+    -485,  -485,  -485,  -485,   220,   344,  1608,   990,   241,   235,
+     262,  -485,  1608,  -485,  -485,   405,  1770,  2090,   254,  -485,
+     297,   444,  1608,    61,  1770,  -485,  -485,   271,  -485,  -485,
+    -485,   671,  -485,  -485,  -485,  -485,  -485,  -485,  1694,  1651,
+    2090,   291,  -485,   181,  -485,    60,  -485,  -485,   287,  2090,
+     301,  -485,   496,  -485,   912,  1608,  1608,  1608,  1608,  -485,
+    1608,  1608,  1608,  -485,  1608,  1608,  1608,  1608,  1608,  1608,
+    1608,  1608,  1608,  1608,  1608,  1608,  1608,  1608,  -485,  1290,
+     468,  1608,  -485,  1608,  -485,  -485,  1221,  1608,  1608,  1608,
+    -485,   573,    44,   235,   275,   347,  -485,  1301,  1301,  -485,
+     113,   302,  -485,   990,   358,  1770,  -485,  -485,  -485,  -485,
+    -485,  -485,  -485,   316,    44,  -485,  -485,   340,  -485,    78,
+     318,  1770,  -485,   990,  -485,  -485,  -485,   307,   325,   990,
+    1221,  -485,  -485,   324,   117,   365,  -485,   343,   337,  -485,
+    -485,   333,  -485,    32,    23,  -485,  -485,   350,  -485,  -485,
+     406,  1737,  -485,  -485,  -485,   351,  -485,  -485,  -485,   352,
+    1608,    44,   354,  1796,  -485,   353,  1770,  1770,  -485,   359,
+    1608,   357,  2090,  1928,  -485,  2114,  1212,  1212,  1212,  1212,
+    -485,  1212,  1212,  2138,  -485,   566,   566,   566,   566,  -485,
+    -485,  -485,  -485,  1345,  -485,  -485,    31,  1400,  -485,  1988,
+     360,  1147,  1955,  1345,  -485,  -485,  -485,  -485,  -485,  -485,
+      95,   254,   254,  2090,  1857,   368,   361,   371,  -485,   363,
+     427,  1301,   247,    51,  -485,   374,  -485,  -485,  -485,  1890,
+    -485,    36,   382,    44,   384,   385,   387,  -485,  -485,   391,
+    1770,   395,  -485,  -485,  -485,  -485,  1455,  1510,  1608,  -485,
+    -485,  -485,   990,  -485,  1823,   399,   135,   340,  1608,    44,
+     397,   403,   990,  -485,   542,   407,  1770,   278,   365,   406,
+     365,   411,   364,   413,  -485,  -485,    44,   406,   430,    44,
+     423,    44,   425,   254,  -485,  1608,  1849,  1770,  -485,   216,
+     219,   274,   288,  -485,  -485,  -485,    44,   426,   254,  1608,
+    -485,  2018,  -485,  -485,   414,   422,   416,  1651,   433,   434,
+     436,  -485,  1608,  -485,  -485,   439,   437,  1221,  1147,  -485,
+    1301,   466,  -485,  -485,  -485,    44,  1882,  1301,    44,  1301,
+    -485,  -485,   504,   207,  -485,  -485,   446,   438,  1301,   247,
+    1301,   406,    44,    44,  -485,   453,   455,  -485,  -485,  -485,
+    1823,  -485,  1221,  1608,  1608,   467,  -485,   990,   472,  -485,
+    -485,  -485,  -485,  -485,  -485,  -485,  1823,  -485,  -485,  -485,
+    -485,  -485,   475,  -485,  -485,  -485,  1651,   470,  -485,  -485,
+    -485,   490,  -485,   493,   406,  -485,  -485,  -485,  -485,  -485,
+    -485,  -485,  -485,  -485,   254,   495,  1345,  -485,  -485,   498,
+     912,  -485,   254,  1345,  1553,  1345,  -485,  -485,   497,  -485,
+    -485,  -485,  -485,   486,  -485,  -485,   143,  -485,  -485,   501,
+     502,   473,   508,   513,   505,  -485,  -485,   515,   503,  1301,
+     511,  -485,   518,  -485,  -485,   533,  -485,  1301,  -485,   522,
+     406,  -485,   526,  -485,  1916,   144,  2090,  2090,  1608,   527,
+     990,  -485,  -485,  1823,    39,  -485,  1147,   406,   406,  -485,
+     315,   293,   521,    44,   548,   357,   525,  -485,  2090,  -485,
+    -485,  -485,  -485,  -485,  -485,  -485,  1916,    44,  -485,  1882,
+    1301,   406,  -485,    44,   207,  -485,  -485,  -485,    44,    44,
+    -485,  -485,  -485,  -485,  -485,  -485,   551,   572,  -485,  1608,
+    1608,  -485,  1651,   550,  -485,  -485,  -485,  -485,  -485,  -485,
+    -485,  1345,  -485,   558,  -485,  -485,  -485,  -485,   563,   564,
+     565,  1823,    46,  -485,  -485,  2042,  2066,   559,  1916,  -485,
+    1916,  -485,  -485,  -485,  -485,  -485,  -485,  -485,  -485,  -485,
+    1608,   340,  -485
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -551,  -551,  -551,  -551,  -551,  -551,  -551,    -6,  -551,  -551,
-     608,  -551,   -11,  -551,  -551,   623,  -551,  -134,   -25,    68,
-    -551,  -135,  -121,  -551,    39,  -551,  -551,  -551,   145,   278,
-    -551,  -551,  -551,  -551,  -551,  -551,   515,    41,  -551,  -551,
-    -551,  -551,  -551,  -551,  -551,  -551,  -551,   579,   493,    45,
-    -551,  -192,   138,  -246,   192,   -47,   415,   200,   -20,   380,
-     626,    -5,   449,   346,  -551,   426,    95,   509,  -551,  -551,
-    -551,  -551,   -33,    38,   -31,   -18,  -551,  -551,  -551,  -551,
-    -551,    43,   457,  -467,  -551,  -551,  -551,  -551,  -551,  -551,
-    -551,  -551,   280,  -126,  -227,   292,  -551,   302,  -551,  -220,
-    -297,   662,  -551,  -248,  -551,   -66,    18,   194,  -551,  -295,
-    -228,  -289,  -191,  -551,  -119,  -403,  -551,  -551,  -305,  -551,
-     -32,  -551,   127,  -551,   362,   250,   363,   232,    90,    98,
-    -550,  -551,  -426,   241,  -551,   486,  -551,  -551
+    -485,  -485,  -485,  -485,  -485,  -485,  -485,    -6,  -485,  -485,
+     597,  -485,    -3,  -485,  -485,   608,  -485,  -131,   -28,    50,
+    -485,  -135,  -106,  -485,    -7,  -485,  -485,  -485,   125,  -370,
+    -485,  -485,  -485,  -485,  -485,  -485,  -138,  -485,  -485,  -485,
+    -485,  -485,  -485,  -485,  -485,  -485,  -485,  -485,  -485,  -485,
+     665,    15,   116,  -485,  -190,   111,   112,  -485,   164,   -59,
+     398,   137,    14,   367,   603,    -5,   454,   432,  -485,   402,
+     -50,   491,  -485,  -485,  -485,  -485,   -36,    18,   -34,    -9,
+    -485,  -485,  -485,  -485,  -485,   257,   441,  -445,  -485,  -485,
+    -485,  -485,  -485,  -485,  -485,  -485,   259,  -116,  -218,   265,
+    -485,   284,  -485,  -217,  -286,   636,  -485,  -237,  -485,   -62,
+     -24,   166,  -485,  -314,  -246,  -265,  -177,  -485,  -115,  -415,
+    -485,  -485,  -379,  -485,    -8,  -485,   435,  -485,   326,   225,
+     327,   204,    65,    70,  -484,  -485,  -426,   211,  -485,   462,
+    -485,  -485
 };
 
 /* 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.  */
-#define YYTABLE_NINF -270
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -275
 static const yytype_int16 yytable[] =
 {
-      12,   174,   376,   359,   119,   235,   121,   240,   274,   259,
-     320,   235,   323,   278,   161,    32,   109,    79,   570,   109,
-     107,   235,   103,    32,   433,   131,   554,   428,   435,   375,
-     385,   111,   456,   426,   111,   380,   389,   391,   128,   393,
-     111,   539,   173,   164,   630,  -176,     4,   400,   146,   150,
-     495,   402,  -208,    27,   205,   450,   496,    27,     9,  -172,
-     199,   417,   150,   214,   200,   216,   218,   138,    18,  -175,
-     388,   133,   201,     5,     9,   120,     9,  -176,     9,    27,
-     122,   495,     9,  -172,   501,   124,  -208,   496,   133,   130,
-     380,  -172,   507,   127,   651,   222,   652,   427,    46,   163,
-       9,   457,   451,   134,   165,   617,   174,    10,    11,    28,
-    -174,   452,   497,    29,   102,   257,   207,    29,  -208,   390,
-     134,   266,   243,    10,    11,    10,    11,    10,    11,   381,
-     111,    10,    11,   618,    19,   525,   111,   528,   146,    29,
-     536,   164,   150,   625,   239,   325,     7,   289,   437,    10,
-      11,   228,   228,   228,   438,   560,   231,   231,   231,    15,
-    -260,   500,   491,   502,   450,   228,  -260,   150,    20,   212,
-     231,   437,   648,   208,   228,    26,   636,   486,   461,   231,
-      23,   164,   228,   209,    11,     9,   366,   231,   535,   228,
-     619,   620,   631,   462,   231,   318,    33,   163,   578,   437,
-     621,    79,   165,   637,   638,   592,  -170,   349,   226,   232,
-     233,   451,   228,   437,   357,    32,  -260,   231,   243,   611,
-     581,   515,  -260,   564,    93,   331,   332,   585,   522,   363,
-    -170,   261,   125,   101,    10,    11,   125,   163,  -170,   276,
-     105,   533,   165,   367,   243,    79,   282,   235,   108,   474,
-     409,   141,   411,   209,   605,   136,   568,   235,   259,   488,
-     171,   228,   198,   228,   509,  -147,   231,   511,   231,   291,
-     430,   623,   624,   202,  -229,   203,   150,   587,   589,   228,
-    -175,   228,     9,   204,   231,  -174,   231,   228,    11,   206,
-     583,    35,   231,   215,   634,    37,  -259,   219,   403,   164,
-     220,   223,  -259,   234,   209,   112,   249,   262,   418,   228,
-      47,    48,     9,   250,   231,   285,    79,    51,   273,   353,
-     361,   410,  -171,   286,   228,   228,   412,   622,   287,   231,
-     231,    10,    11,  -229,   379,   354,   369,   453,   345,  -229,
-       9,   479,   358,   481,   355,   356,  -171,    61,   349,   614,
-     519,   360,  -259,   362,  -171,   163,   482,   254,  -259,    64,
-     165,    10,    11,   364,   257,   368,   397,   243,   374,   477,
-     372,   378,   266,  -169,   489,   143,   506,   243,   408,   111,
-     529,   414,   415,   117,   331,   332,   263,   111,   380,    10,
-      11,   111,   264,   382,   146,  -173,   150,  -169,   228,   384,
-     394,   265,   386,   231,   392,  -169,    10,    11,   405,   164,
-     228,   150,   480,   399,   401,   231,   413,   483,   416,  -173,
-     228,   432,   419,   513,   228,   231,   444,  -173,   445,   231,
-     446,    79,    79,   447,   448,   458,   479,   521,   481,   349,
-     541,   463,   548,   254,   228,   228,   235,   453,   612,   231,
-     231,   482,   479,   453,   481,   408,   561,   349,   466,   117,
-     117,   117,   467,   468,   469,   163,    79,   482,   449,   470,
-     165,   243,    94,   117,   485,   254,   460,   164,   255,   379,
-      95,   494,   117,   490,    96,   493,     9,   256,   503,   505,
-     117,   508,    10,    11,    97,    98,   510,   117,   512,   520,
-     524,   226,   514,   526,   263,   527,   530,   480,   531,     9,
-     264,   534,   483,   532,   228,   340,   519,   553,   563,   231,
-     117,   147,   555,   480,    10,    11,   556,    99,   483,   567,
-       9,   569,     9,   163,   462,    10,    11,   572,   165,   479,
-     574,   481,   576,   210,   210,   277,   210,   210,   152,   153,
-     154,   155,   156,   157,   482,   166,   167,   228,    10,    11,
-     577,   580,   231,   590,   243,   172,   537,   582,   288,   117,
-      79,   117,   544,   547,   529,   552,     9,   150,   593,    10,
-      11,    10,    11,   591,   557,   254,   559,   117,   594,   117,
-     349,  -151,   541,   595,  -152,   117,   548,   453,   596,   597,
-     601,   349,   349,   164,   600,   598,   479,   228,   481,   602,
-     480,   317,   231,   604,   584,   483,   606,   117,   613,   615,
-     255,   482,   626,   628,   629,    10,    11,   177,   137,   117,
-     639,   437,   117,   117,    10,    11,   644,   185,   645,   106,
-     160,   189,   646,   169,   647,    66,   194,   195,   196,   197,
-     627,   152,   156,   579,   640,   487,   641,   272,   370,   163,
-     344,   404,   588,    37,   165,   123,   344,   344,   284,   371,
-     352,    37,   504,   112,   475,   599,   492,   480,    47,    48,
-       9,   112,   483,   603,    91,    51,    47,    48,     9,   573,
-     538,   635,   224,    51,   562,   632,   442,   443,   351,   558,
-     224,     0,     0,     0,     0,     0,   117,     0,     0,   114,
-       0,     0,     0,     0,     0,   225,     0,   114,   117,     0,
-     117,   280,     0,   225,   544,   633,   177,    64,   117,    10,
-      11,   281,   117,     0,     0,    64,   185,    10,    11,   396,
+      12,   119,   161,   121,   272,   174,   359,   488,   274,   436,
+     502,   240,   385,   376,   323,    32,   278,    79,   508,   259,
+     235,   393,   103,    32,   320,   138,   235,   555,   107,   400,
+     540,   111,   375,   402,   111,   433,   235,    27,   128,   173,
+     111,   571,   426,   417,   619,   389,   391,   380,   146,   150,
+     109,   428,   164,   109,   457,   120,   380,   435,     9,   131,
+       5,  -213,   150,   226,   232,   233,   653,     4,     9,   212,
+     152,   153,   154,   155,   156,   157,   390,   166,   167,   163,
+       7,   207,   561,   366,    11,     9,   261,   214,    15,   216,
+     218,   388,   205,    28,   276,  -213,   462,    29,    20,    18,
+      19,   282,   239,   222,   620,   621,   427,    10,    11,    23,
+     174,   463,   632,   325,   622,   133,    27,    10,    11,  -179,
+    -234,   273,   243,   458,   291,   579,   133,  -213,   618,    26,
+     111,   228,   228,   228,    10,    11,   111,     9,   146,   381,
+     136,   208,   150,   367,   289,   228,    33,   134,    93,   257,
+     164,   209,   537,   209,   228,   266,   124,   438,   134,   526,
+     130,   528,   228,   439,   658,   492,   659,   150,    27,   228,
+     501,   101,   503,   152,   156,   361,    29,   163,   638,  -234,
+     379,   607,   633,   331,   332,  -234,    10,    11,   141,     9,
+     164,   369,   228,   639,   640,   318,   652,   438,   624,   625,
+     536,    79,   582,   487,   125,   438,   438,   349,   125,   586,
+     451,   594,   613,   105,   357,    32,  -181,   163,   243,   171,
+     204,   397,   636,   516,   108,   102,   206,  -265,    29,   363,
+     523,     9,  -265,   408,   198,   565,   414,   415,    10,    11,
+    -180,   228,  -152,   228,   243,    79,   202,   409,  -181,   411,
+     451,  -177,   203,   475,  -175,   533,   403,   452,   430,   228,
+     569,   228,   235,   489,   510,  -180,   418,   228,   259,  -264,
+     512,     9,   235,   584,  -264,  -177,   150,  -179,  -175,    11,
+      10,    11,  -265,  -177,   215,   496,  -175,   219,  -265,   228,
+     497,   662,   220,    35,   122,     9,   223,   452,    37,   234,
+     249,   410,   250,    94,   228,   228,   453,   112,   164,  -176,
+     408,    95,    47,    48,     9,    96,    79,   647,   165,    51,
+      10,    11,   496,  -174,  -264,    97,    98,   497,  -178,   209,
+    -264,   277,   262,  -176,   353,   163,   495,   454,   480,   623,
+     482,  -176,   331,   332,    10,    11,   498,  -174,   349,    61,
+     354,   285,  -178,   616,   520,  -174,   226,   515,    99,   286,
+    -178,    64,   358,    10,    11,   483,   360,   243,   529,   478,
+     231,   231,   231,   287,   490,   364,   362,   243,   228,   111,
+     368,   514,   372,   626,   231,   374,   378,   111,   254,   380,
+     228,   111,   481,   231,   146,   522,   150,   631,   257,   384,
+     228,   231,   382,   199,   228,   386,   266,   200,   231,   394,
+     507,   150,   392,   399,   401,   201,   165,   263,   164,   405,
+     413,   416,   419,   264,   228,   228,   432,   445,   446,   254,
+     448,   231,    79,    79,   480,   449,   482,    10,    11,   459,
+     349,   542,   447,   549,   464,   163,   467,   468,   454,   469,
+     480,   470,   482,   614,   454,   471,   165,   562,   349,   486,
+     379,   483,   235,   491,   255,   509,     9,    79,   254,   117,
+     585,   504,   243,   256,     9,   494,     9,   483,    10,    11,
+     231,   506,   231,   511,     9,   513,   521,   164,   481,   525,
+     527,   434,     9,   530,   531,   228,   532,   263,   231,   534,
+     231,   127,   340,   264,   481,   535,   231,   554,   556,   143,
+     557,   147,   265,   564,   163,    10,    11,    10,    11,   172,
+       9,   520,   661,    10,    11,    10,    11,   317,   231,   568,
+     463,   570,  -156,    10,    11,   573,   575,   480,   228,   482,
+     412,    10,    11,   231,   231,   117,   117,   117,   210,   210,
+     577,   210,   210,   578,   235,   581,   288,   592,   593,   117,
+     583,   595,   596,   529,   483,   243,   254,   597,   117,    10,
+      11,    79,  -157,   598,   165,   600,   117,   599,   150,   602,
+     603,   334,   604,   117,   606,   608,   642,   615,   228,   627,
+     335,   481,   349,   630,   542,   336,   337,   338,   549,   454,
+     177,   255,   339,   349,   349,   480,   117,   482,   629,   340,
+     185,   641,   438,   164,   189,    10,    11,   231,   648,   194,
+     195,   196,   197,   649,   650,   651,   341,   657,   106,   231,
+      66,   484,   483,   628,   580,   654,   590,   591,   342,   231,
+     163,   370,   123,   231,   343,   371,   345,    11,   404,   493,
+     284,   505,   355,   356,   352,   117,   476,   117,    91,   481,
+     443,   444,   574,   231,   231,   344,   539,   563,   637,   634,
+     559,   344,   344,   117,   351,   117,     0,     0,     0,    37,
+       0,   117,     0,     0,   165,     0,     0,     0,   112,     0,
+       0,     0,     0,    47,    48,     9,     0,     0,     0,     0,
+      51,     0,     0,   117,     0,     0,     0,   224,     0,     0,
+       0,     0,     0,     0,   137,   117,     0,     0,   117,   117,
+       0,     0,   175,  -274,   114,     0,   160,   484,     0,   169,
+     225,     0,     0,     0,   231,     0,   280,     0,     0,     0,
+       0,     0,    64,   484,    10,    11,   281,     0,     0,     0,
+       0,   176,   177,   165,   178,   179,   180,   181,   182,     0,
+     183,   184,   185,   186,   187,   188,   189,   190,   191,   192,
+     193,   194,   195,   196,   197,     0,   450,   231,     0,     0,
+       0,     0,     0,  -274,   461,     0,     0,     0,   344,     0,
+       0,     0,   117,  -274,     0,   344,     0,     0,     0,     0,
+       0,     0,     0,   344,   117,     0,   117,     0,     0,     0,
+       0,     0,     0,     0,   117,     0,     0,     0,   117,     0,
+       0,     0,     0,     0,     0,     0,     0,   231,     0,     0,
+     484,     0,     0,     0,     0,     0,     0,     0,   117,   117,
+     292,   293,   294,   295,     0,   296,   297,   298,     0,   299,
+     300,   301,   302,   303,   304,   305,   306,   307,   308,   309,
+     310,   311,   312,     0,   160,     0,   319,     0,   322,     0,
+       0,     0,   137,   137,   333,   538,     0,     0,     0,   165,
+       0,   545,   548,     0,   553,     0,     0,     0,     0,     0,
+       0,     0,     0,   558,   344,   560,     0,     0,   484,     0,
+     543,   344,   117,   344,     0,     0,     0,     0,     0,   117,
+       0,     0,   344,     0,   344,     0,     0,     0,   117,     0,
+      37,     0,     0,    35,     0,     0,     0,     0,    37,   112,
+       0,   168,     0,     0,    47,    48,     9,   112,     0,     0,
+       0,    51,    47,    48,     9,   137,     0,     0,   224,    51,
+       0,     0,   117,     0,     0,   137,    55,     0,     0,     0,
+       0,     0,     0,     0,     0,   114,     0,     0,     0,    56,
+      57,   225,    58,    59,     0,     0,    60,   290,   421,    61,
+       0,     0,   160,    64,   601,    10,    11,   281,   421,    62,
+      63,    64,   605,    10,    11,     0,     0,     0,    37,     0,
+       0,   241,   117,   344,     0,   117,     0,   112,     0,     0,
+       0,   344,    47,    48,     9,     0,     0,     0,   344,    51,
+       0,     0,     0,     0,     0,     0,   224,     0,     0,     0,
+       0,   137,   137,     0,   545,   635,     0,     0,     0,     0,
+       0,     0,     0,   114,     0,     0,     0,     0,     0,   225,
+     344,     0,     0,   543,   344,     0,     0,     0,     0,    -2,
+      34,    64,    35,    10,    11,    36,     0,    37,    38,    39,
+     137,     0,    40,   117,    41,    42,    43,    44,    45,    46,
+       0,    47,    48,     9,   137,     0,    49,    50,    51,    52,
+      53,    54,   160,     0,     0,    55,     0,   169,     0,     0,
+       0,     0,   344,     0,   344,     0,     0,     0,    56,    57,
+       0,    58,    59,     0,     0,    60,     0,     0,    61,     0,
+       0,   -24,     0,     0,     0,     0,     0,     0,    62,    63,
+      64,     0,    10,    11,     0,     0,     0,     0,   566,   567,
+       0,     0,     0,     0,     0,     0,     0,     0,   324,     0,
+      35,     0,     0,    36,  -249,    37,    38,    39,     0,  -249,
+      40,   160,    41,    42,   112,    44,    45,    46,     0,    47,
+      48,     9,     0,     0,    49,    50,    51,    52,    53,    54,
+       0,   421,     0,    55,     0,     0,     0,     0,   421,   588,
+     421,     0,     0,     0,     0,     0,    56,    57,     0,    58,
+      59,     0,     0,    60,     0,     0,    61,     0,     0,  -249,
+       0,     0,     0,     0,   325,  -249,    62,    63,    64,     0,
+      10,    11,   324,     0,    35,     0,     0,    36,     0,    37,
+      38,    39,     0,     0,    40,     0,    41,    42,   112,    44,
+      45,    46,     0,    47,    48,     9,   177,     0,    49,    50,
+      51,    52,    53,    54,     0,     0,   185,    55,     0,     0,
      189,   190,   191,   192,   193,   194,   195,   196,   197,     0,
-       0,     0,   117,   117,   292,   293,   294,   295,     0,   296,
-     297,   298,     0,   299,   300,   301,   302,   303,   304,   305,
-     306,   307,   308,   309,   310,   311,   312,     0,   160,     0,
-     319,     0,   322,   344,     0,     0,   137,   137,   333,     0,
-     344,   334,     0,     0,     0,   459,     0,     0,   344,     0,
-     175,   335,     0,     0,  -269,     0,   336,   337,   338,     0,
-       0,     0,     0,   339,     0,   117,     0,     0,     0,     0,
-     340,     0,   117,     0,     0,     0,     0,     0,     0,   176,
-     177,   117,   178,   179,   180,   181,   182,   341,   183,   184,
-     185,   186,   187,   188,   189,   190,   191,   192,   193,   194,
-     195,   196,   197,     0,     0,   343,     0,     0,    11,   137,
-       0,  -269,     0,     0,     0,   117,     0,     0,     0,   137,
-       0,  -269,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   344,     0,
-       0,     0,   421,     0,   542,   344,   160,   344,     0,     0,
-       0,     0,   421,     0,    -2,    34,   344,    35,   344,    36,
-       0,    37,     0,    38,    39,   117,     0,    40,   117,    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,   137,   137,     0,     0,     0,
-       0,     0,     0,    56,    57,     0,    58,    59,     0,     0,
-      60,     0,     0,    61,     0,     0,   -24,     0,    35,     0,
-       0,     0,    37,    62,    63,    64,   168,    10,    11,     0,
-       0,     0,   112,     0,   137,   117,     0,    47,    48,     9,
-       0,     0,     0,     0,    51,     0,     0,   344,   137,     0,
-       0,    55,     0,     0,     0,   344,   160,     0,     0,     0,
-       0,   169,   344,     0,    56,    57,     0,    58,    59,     0,
-       0,    60,     0,     0,    61,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    62,    63,    64,     0,    10,    11,
-       0,     0,     0,   344,     0,     0,   542,   344,     0,     0,
-       0,   565,   566,     0,     0,     0,     0,     0,     0,     0,
-       0,   324,     0,    35,     0,    36,  -244,    37,     0,    38,
-      39,     0,  -244,    40,   160,    41,    42,   112,    44,    45,
-      46,     0,    47,    48,     9,     0,     0,    49,    50,    51,
-      52,    53,    54,   344,   421,   344,    55,     0,     0,     0,
-       0,   421,   586,   421,     0,     0,     0,     0,     0,    56,
-      57,     0,    58,    59,     0,     0,    60,     0,     0,    61,
-       0,     0,  -244,     0,     0,     0,     0,   325,  -244,    62,
-      63,    64,     0,    10,    11,   324,     0,    35,     0,    36,
-       0,    37,     0,    38,    39,     0,     0,    40,     0,    41,
-      42,   112,    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,    35,  -244,   642,   643,    37,
-     160,   325,  -244,    62,    63,    64,     0,    10,    11,   112,
-     334,     0,     0,     0,    47,    48,     9,     0,     0,     0,
-     335,    51,     0,     0,     0,   336,   337,   338,   158,     0,
-       0,     0,   339,     0,     0,     0,     0,     0,     0,   340,
-       0,    56,    57,     0,    58,   159,     0,     0,    60,     0,
-      35,    61,   314,     0,    37,     0,   341,     0,     0,     0,
-       0,    62,    63,    64,   112,    10,    11,     0,   342,    47,
-      48,     9,     0,     0,   343,     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,
-      59,     0,     0,    60,     0,    35,    61,     0,     0,    37,
-       0,     0,     0,     0,   420,     0,    62,    63,    64,   112,
-      10,    11,     0,     0,    47,    48,     9,     0,     0,     0,
-       0,    51,     0,   429,     0,     0,     0,     0,   158,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    56,    57,     0,    58,   159,     0,     0,    60,     0,
-      35,    61,     0,     0,    37,     0,     0,     0,     0,     0,
-       0,    62,    63,    64,   112,    10,    11,     0,     0,    47,
-      48,     9,     0,   472,     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,    37,
-       0,     0,     0,     0,     0,     0,    62,    63,    64,   112,
-      10,    11,     0,     0,    47,    48,     9,     0,   473,     0,
-       0,    51,     0,     0,     0,     0,     0,     0,    55,     0,
+      56,    57,     0,    58,    59,     0,     0,    60,     0,     0,
+      61,     0,     0,  -249,   645,   646,     0,   160,   325,  -249,
+      62,    63,    64,    35,    10,    11,   421,     0,    37,     0,
+       0,     0,     0,     0,     0,     0,     0,   112,     0,   334,
+       0,     0,    47,    48,     9,     0,     0,     0,   335,    51,
+       0,     0,     0,   336,   337,   338,   158,     0,     0,     0,
+     339,     0,     0,     0,     0,     0,     0,   340,     0,    56,
+      57,     0,    58,   159,     0,     0,    60,     0,    35,    61,
+     314,     0,     0,    37,   341,     0,     0,     0,     0,    62,
+      63,    64,   112,    10,    11,     0,     0,    47,    48,     9,
+       0,     0,   343,     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,    59,     0,
+       0,    60,     0,    35,    61,     0,     0,     0,    37,     0,
+       0,     0,   420,     0,    62,    63,    64,   112,    10,    11,
+       0,     0,    47,    48,     9,     0,     0,     0,     0,    51,
+       0,   429,     0,     0,     0,     0,   158,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    56,
+      57,     0,    58,   159,     0,     0,    60,     0,    35,    61,
+       0,     0,     0,    37,     0,     0,     0,     0,     0,    62,
+      63,    64,   112,    10,    11,     0,     0,    47,    48,     9,
+       0,   473,     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,   112,    10,    11,
+       0,     0,    47,    48,     9,     0,   474,     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,
+     112,     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,    56,    57,     0,    58,    59,     0,     0,    60,     0,
-      35,    61,     0,     0,    37,     0,     0,     0,     0,     0,
-       0,    62,    63,    64,   112,    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,    37,
-       0,     0,     0,     0,     0,     0,    62,    63,    64,   112,
-      10,    11,     0,     0,    47,    48,     9,     0,     0,     0,
-       0,    51,     0,     0,     0,     0,     0,     0,   158,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    56,    57,     0,    58,   159,     0,     0,    60,     0,
-      35,    61,     0,     0,   283,     0,     0,     0,     0,     0,
-       0,    62,    63,    64,   112,    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,     0,    61,     0,     0,    37,
-       0,     0,     0,     0,     0,     0,    62,    63,    64,   112,
-      10,    11,     0,     0,    47,    48,     9,     0,     0,     0,
-       0,    51,     0,     0,     0,    37,     0,     0,   224,   241,
-       0,     0,     0,    37,     0,   112,     0,     0,     0,     0,
-      47,    48,     9,   112,     0,   114,     0,    51,    47,    48,
-       9,   225,     0,     0,   224,    51,     0,   290,    37,     0,
-       0,     0,   113,    64,     0,    10,    11,   281,   112,     0,
-       0,   114,     0,    47,    48,     9,     0,   225,     0,   114,
-      51,     0,     0,     0,     0,   115,    37,   224,     0,    64,
-       0,    10,    11,     0,     0,     0,   112,    64,     0,    10,
-      11,    47,    48,     9,   114,     0,     0,     0,    51,     0,
-     225,    37,     0,     0,     0,   406,     0,     0,     0,   283,
-       0,   112,    64,     0,    10,    11,    47,    48,     9,   112,
-       0,     0,   114,    51,    47,    48,     9,     0,   407,     0,
-     224,    51,     0,     0,   334,     0,     0,     0,   224,     0,
-      64,     0,    10,    11,   335,     0,     0,   114,     0,   336,
-     337,   338,     0,   476,     0,   114,   339,     0,     0,     0,
-       0,   225,   334,   439,     0,    64,     0,    10,    11,     0,
-       0,     0,   335,    64,     0,    10,    11,   336,   337,   540,
-     341,     0,     0,     0,   339,     0,   440,   334,     0,     0,
-       0,   340,     0,     0,     0,   334,     0,   335,   343,     0,
-       0,    11,   336,   337,   338,   335,     0,     0,   341,   339,
-     336,   337,   338,     0,     0,     0,   340,   339,     0,     0,
-       0,     0,     0,     0,   340,     0,   343,     0,    10,    11,
-       0,     0,     0,   341,     0,     0,     0,     0,     0,   607,
-       0,   341,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   343,     0,     0,    11,     0,     0,     0,     0,   343,
-     176,   177,    11,   178,     0,   180,   181,   182,     0,     0,
-     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
-     194,   195,   196,   197,     0,     0,     0,     0,     0,     0,
-     176,   177,     0,   178,     0,   180,   181,   182,     0,   431,
-     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
-     194,   195,   196,   197,   176,   177,     0,   178,     0,   180,
-     181,   182,     0,   523,   184,   185,   186,   187,   188,   189,
-     190,   191,   192,   193,   194,   195,   196,   197,   176,   177,
-       0,   178,     0,   180,   181,   182,     0,   649,   184,   185,
+       0,     0,    56,    57,     0,    58,    59,     0,     0,    60,
+       0,    35,    61,     0,     0,     0,    37,     0,     0,     0,
+     587,     0,    62,    63,    64,   112,    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,   112,     0,
+       0,     0,     0,    47,    48,     9,     0,    62,    63,    64,
+      51,    10,    11,     0,     0,     0,     0,   158,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    35,     0,     0,
+      56,    57,   283,    58,   159,     0,     0,    60,     0,     0,
+      61,   112,     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,   112,     0,     0,     0,     0,    47,
+      48,     9,     0,    62,    63,    64,    51,    10,    11,     0,
+      37,     0,     0,   224,     0,     0,     0,     0,    37,   112,
+       0,     0,     0,     0,    47,    48,     9,   112,     0,     0,
+     114,    51,    47,    48,     9,     0,   225,     0,   113,    51,
+       0,     0,     0,     0,    37,     0,   224,     0,    64,     0,
+      10,    11,   396,   112,     0,   114,     0,     0,    47,    48,
+       9,   115,     0,   114,     0,    51,     0,     0,     0,   225,
+       0,    37,   406,    64,     0,    10,    11,     0,     0,     0,
+     112,    64,     0,    10,    11,    47,    48,     9,     0,   114,
+       0,     0,    51,     0,     0,   407,     0,   283,     0,   224,
+       0,     0,     0,     0,     0,   334,   112,    64,     0,    10,
+      11,    47,    48,     9,   335,     0,   114,     0,    51,   336,
+     337,   338,   477,     0,     0,   224,   339,     0,     0,     0,
+     334,     0,     0,   440,    64,     0,    10,    11,   334,   335,
+       0,   460,   114,     0,   336,   337,   541,   335,   225,     0,
+     341,   339,   336,   337,   338,     0,   441,     0,   340,   339,
+      64,     0,    10,    11,   334,     0,   340,     0,   343,     0,
+       0,    11,     0,   335,     0,   341,     0,     0,   336,   337,
+     338,     0,     0,   341,     0,   339,     0,     0,     0,     0,
+       0,     0,   340,   343,     0,    10,    11,     0,     0,     0,
+       0,   343,   177,     0,    11,     0,   180,   181,   182,   341,
+       0,   184,   185,   186,   187,   609,   189,   190,   191,   192,
+     193,   194,   195,   196,   197,     0,     0,   343,   176,   177,
+      11,   178,     0,   180,   181,   182,     0,     0,   184,   185,
      186,   187,   188,   189,   190,   191,   192,   193,   194,   195,
-     196,   197,   176,   177,     0,   178,     0,   180,   181,   182,
-       0,   650,   184,   185,   186,   187,   188,   189,   190,   191,
-     192,   193,   194,   195,   196,   197,     0,   176,   177,   434,
-     178,     0,   180,   181,   182,     0,     0,   184,   185,   186,
+     196,   197,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   176,   177,     0,   178,     0,   180,   181,   182,     0,
+     434,   184,   185,   186,   187,   188,   189,   190,   191,   192,
+     193,   194,   195,   196,   197,     0,     0,     0,     0,     0,
+       0,   176,   177,     0,   178,     0,   180,   181,   182,     0,
+     431,   184,   185,   186,   187,   188,   189,   190,   191,   192,
+     193,   194,   195,   196,   197,   176,   177,     0,   178,     0,
+     180,   181,   182,     0,   524,   184,   185,   186,   187,   188,
+     189,   190,   191,   192,   193,   194,   195,   196,   197,   176,
+     177,     0,   178,     0,   180,   181,   182,     0,   655,   184,
+     185,   186,   187,   188,   189,   190,   191,   192,   193,   194,
+     195,   196,   197,   176,   177,     0,   178,     0,   180,   181,
+     182,     0,   656,   184,   185,   186,   187,   188,   189,   190,
+     191,   192,   193,   194,   195,   196,   197,   176,   177,     0,
+       0,     0,   180,   181,   182,     0,     0,   184,   185,   186,
      187,   188,   189,   190,   191,   192,   193,   194,   195,   196,
      197,   176,   177,     0,     0,     0,   180,   181,   182,     0,
-       0,   184,   185,   186,   187,   188,   189,   190,   191,   192,
-     193,   194,   195,   196,   197,   176,   177,     0,     0,     0,
-     180,   181,   182,     0,     0,   184,   185,   186,   187,     0,
-     189,   190,   191,   192,   193,   194,   195,   196,   197,   177,
-       0,     0,     0,   180,   181,   182,     0,     0,   184,   185,
-     186,   187,     0,   189,   190,   191,   192,   193,   194,   195,
-     196,   197
+       0,   184,   185,   186,   187,     0,   189,   190,   191,   192,
+     193,   194,   195,   196,   197
 };
 
-#define yypact_value_is_default(yystate) \
-  ((yystate) == (-551))
-
-#define yytable_value_is_error(yytable_value) \
-  YYID (0)
-
 static const yytype_int16 yycheck[] =
 {
-       5,    67,   250,   223,    37,   126,    37,   126,   143,   135,
-     201,   132,   204,   147,    61,    20,    36,    22,   485,    39,
-      31,   142,    28,    28,   321,    45,   452,   316,   323,   249,
-     258,    36,     3,    11,    39,    24,   263,   264,    43,   267,
-      45,   444,    67,    61,   594,    35,     0,   275,    53,    54,
-       6,   279,     1,     3,     1,     3,    12,     3,    24,    35,
-      59,   289,    67,    95,    63,    97,    98,    49,     3,    59,
-      59,    35,    71,    25,    24,    37,    24,    67,    24,     3,
-      37,     6,    24,    59,   389,    40,    35,    12,    35,    44,
-      24,    67,   397,    59,   644,   106,   646,    75,    20,    61,
-      24,    72,    50,    67,    61,   572,   172,    73,    74,    59,
-      59,    59,    68,    63,    60,   135,     8,    63,    67,    53,
-      67,   141,   127,    73,    74,    73,    74,    73,    74,   255,
-     135,    73,    74,     8,    62,   424,   141,   426,   143,    63,
-     437,   159,   147,    68,   126,    67,    25,   172,    62,    73,
-      74,   113,   114,   115,    68,   460,   113,   114,   115,    24,
-       6,   388,   382,   390,     3,   127,    12,   172,    21,    59,
-     127,    62,   639,    65,   136,    63,   602,    68,    60,   136,
-      24,   199,   144,    75,    74,    24,     8,   144,   436,   151,
-      65,    66,   595,    75,   151,   200,    62,   159,   503,    62,
-      75,   206,   159,   606,   607,    68,    35,   212,   113,   114,
-     115,    50,   174,    62,   220,   220,    62,   174,   223,    68,
-     515,   413,    68,   471,    62,   207,   208,   522,   420,   234,
-      59,   136,    40,    24,    73,    74,    44,   199,    67,   144,
-       3,   432,   199,    65,   249,   250,   151,   368,     3,   368,
-     283,    51,   283,    75,   559,    71,   476,   378,   384,   378,
-      62,   223,    67,   225,   399,    66,   223,   401,   225,   174,
-     317,   576,   577,    66,     3,    59,   281,   523,   524,   241,
-      59,   243,    24,    83,   241,    59,   243,   249,    74,    89,
-     518,     3,   249,    24,   599,     7,     6,    64,   280,   317,
-      62,    59,    12,    63,    75,    17,    59,    35,   290,   271,
-      22,    23,    24,    67,   271,    60,   321,    29,    60,    59,
-     225,   283,    35,    72,   286,   287,   283,   575,    72,   286,
-     287,    73,    74,    62,    63,     3,   241,   342,   211,    68,
-      24,   374,    60,   374,   217,   218,    59,    59,   353,   569,
-     416,     7,    62,    60,    67,   317,   374,    24,    68,    71,
-     317,    73,    74,    35,   384,    62,   271,   372,    60,   374,
-      75,    62,   392,    35,   379,    59,   396,   382,   283,   384,
-     427,   286,   287,    37,   366,   367,    53,   392,    24,    73,
-      74,   396,    59,    59,   399,    35,   401,    59,   360,    62,
-       3,    68,    72,   360,    62,    67,    73,    74,    65,   427,
-     372,   416,   374,    62,    62,   372,    67,   374,    62,    59,
-     382,    66,    65,   405,   386,   382,    59,    67,    67,   386,
-      71,   436,   437,    67,     7,    65,   469,   419,   469,   444,
-     445,    62,   447,    24,   406,   407,   567,   452,   567,   406,
-     407,   469,   485,   458,   485,   360,   461,   462,    62,   113,
-     114,   115,    62,    62,    60,   427,   471,   485,   341,    60,
-     427,   476,     9,   127,    60,    24,   349,   495,    59,    63,
-      17,   386,   136,    60,    21,    68,    24,    68,    60,    68,
-     144,    35,    73,    74,    31,    32,    60,   151,    60,    60,
-      75,   406,   407,    68,    53,    75,    60,   469,    60,    24,
-      59,    68,   469,    60,   476,    36,   582,     3,    60,   476,
-     174,    59,    62,   485,    73,    74,    72,    64,   485,    62,
-      24,    59,    24,   495,    75,    73,    74,    60,   495,   572,
-      66,   572,    60,    94,    95,    60,    97,    98,    55,    56,
-      57,    58,    59,    60,   572,    62,    63,   519,    73,    74,
-      60,    60,   519,    60,   569,    59,   439,    62,    60,   223,
-     575,   225,   445,   446,   621,   448,    24,   582,    60,    73,
-      74,    73,    74,    72,   457,    24,   459,   241,    60,   243,
-     595,    59,   597,    59,    59,   249,   601,   602,    68,    62,
-      62,   606,   607,   621,    68,    72,   639,   569,   639,    49,
-     572,    59,   569,    62,   519,   572,    59,   271,    60,    14,
-      59,   639,    68,    60,    68,    73,    74,    34,    49,   283,
-      60,    62,   286,   287,    73,    74,    60,    44,    60,    31,
-      61,    48,    60,    64,    60,    22,    53,    54,    55,    56,
-     582,   158,   159,   508,   615,   377,   615,   142,   243,   621,
-     211,   281,   524,     7,   621,    39,   217,   218,   159,   243,
-     213,     7,   392,    17,   372,   548,   384,   639,    22,    23,
-      24,    17,   639,   556,    22,    29,    22,    23,    24,   495,
-     440,   601,    36,    29,   462,   597,   334,   334,   212,   458,
-      36,    -1,    -1,    -1,    -1,    -1,   360,    -1,    -1,    53,
-      -1,    -1,    -1,    -1,    -1,    59,    -1,    53,   372,    -1,
-     374,    65,    -1,    59,   597,   598,    34,    71,   382,    73,
-      74,    75,   386,    -1,    -1,    71,    44,    73,    74,    75,
+       5,    37,    61,    37,   142,    67,   223,   377,   143,   323,
+     389,   126,   258,   250,   204,    20,   147,    22,   397,   135,
+     126,   267,    28,    28,   201,    49,   132,   453,    31,   275,
+     445,    36,   249,   279,    39,   321,   142,     3,    43,    67,
+      45,   486,    11,   289,     5,   263,   264,    24,    53,    54,
+      36,   316,    61,    39,     3,    37,    24,   322,    24,    45,
+      25,     1,    67,   113,   114,   115,    20,     0,    24,    59,
+      55,    56,    57,    58,    59,    60,    53,    62,    63,    61,
+      25,     5,   461,     5,    74,    24,   136,    95,    24,    97,
+      98,    59,     1,    59,   144,    35,    60,    63,    21,     3,
+      62,   151,   126,   106,    65,    66,    75,    73,    74,    24,
+     172,    75,   596,    67,    75,    35,     3,    73,    74,    59,
+       3,    60,   127,    72,   174,   504,    35,    67,   573,    63,
+     135,   113,   114,   115,    73,    74,   141,    24,   143,   255,
+      71,    65,   147,    65,   172,   127,    62,    67,    62,   135,
+     159,    75,   438,    75,   136,   141,    40,    62,    67,   424,
+      44,   426,   144,    68,   648,   382,   650,   172,     3,   151,
+     388,    24,   390,   158,   159,   225,    63,   159,   604,    62,
+      63,   560,   597,   207,   208,    68,    73,    74,    51,    24,
+     199,   241,   174,   608,   609,   200,   641,    62,   577,   578,
+     437,   206,   516,    68,    40,    62,    62,   212,    44,   523,
+       3,    68,    68,     3,   220,   220,    35,   199,   223,    62,
+      83,   271,   601,   413,     3,    60,    89,     7,    63,   234,
+     420,    24,    12,   283,    67,   472,   286,   287,    73,    74,
+      59,   223,    66,   225,   249,   250,    66,   283,    67,   283,
+       3,    35,    59,   368,    35,   432,   280,    50,   317,   241,
+     477,   243,   368,   378,   399,    59,   290,   249,   384,     7,
+     401,    24,   378,   519,    12,    59,   281,    59,    59,    74,
+      73,    74,    62,    67,    24,     7,    67,    64,    68,   271,
+      12,   661,    62,     3,    37,    24,    59,    50,     8,    63,
+      59,   283,    67,     9,   286,   287,    59,    17,   317,    35,
+     360,    17,    22,    23,    24,    21,   321,   631,    61,    29,
+      73,    74,     7,    35,    62,    31,    32,    12,    35,    75,
+      68,    60,    35,    59,    59,   317,   386,   342,   374,   576,
+     374,    67,   366,   367,    73,    74,    68,    59,   353,    59,
+       3,    60,    59,   570,   416,    67,   406,   407,    64,    72,
+      67,    71,    60,    73,    74,   374,     8,   372,   427,   374,
+     113,   114,   115,    72,   379,    35,    60,   382,   360,   384,
+      62,   405,    75,    68,   127,    60,    62,   392,    24,    24,
+     372,   396,   374,   136,   399,   419,   401,   587,   384,    62,
+     382,   144,    59,    59,   386,    72,   392,    63,   151,     3,
+     396,   416,    62,    62,    62,    71,   159,    53,   427,    65,
+      67,    62,    65,    59,   406,   407,    66,    59,    67,    24,
+      67,   174,   437,   438,   470,     8,   470,    73,    74,    65,
+     445,   446,    71,   448,    62,   427,    62,    62,   453,    62,
+     486,    60,   486,   568,   459,    60,   199,   462,   463,    60,
+      63,   470,   568,    60,    59,    35,    24,   472,    24,    37,
+     520,    60,   477,    68,    24,    68,    24,   486,    73,    74,
+     223,    68,   225,    60,    24,    60,    60,   496,   470,    75,
+      68,    75,    24,    60,    60,   477,    60,    53,   241,    60,
+     243,    59,    36,    59,   486,    68,   249,     3,    62,    59,
+      72,    59,    68,    60,   496,    73,    74,    73,    74,    59,
+      24,   583,   660,    73,    74,    73,    74,    59,   271,    62,
+      75,    59,    59,    73,    74,    60,    66,   573,   520,   573,
+     283,    73,    74,   286,   287,   113,   114,   115,    94,    95,
+      60,    97,    98,    60,   660,    60,    60,    60,    72,   127,
+      62,    60,    60,   622,   573,   570,    24,    59,   136,    73,
+      74,   576,    59,    68,   317,    72,   144,    62,   583,    68,
+      62,     8,    49,   151,    62,    59,    14,    60,   570,    68,
+      17,   573,   597,    68,   599,    22,    23,    24,   603,   604,
+      34,    59,    29,   608,   609,   641,   174,   641,    60,    36,
+      44,    60,    62,   622,    48,    73,    74,   360,    60,    53,
+      54,    55,    56,    60,    60,    60,    53,    68,    31,   372,
+      22,   374,   641,   583,   509,   642,   525,   525,    65,   382,
+     622,   243,    39,   386,    71,   243,   211,    74,   281,   384,
+     159,   392,   217,   218,   213,   223,   372,   225,    22,   641,
+     334,   334,   496,   406,   407,   211,   441,   463,   603,   599,
+     459,   217,   218,   241,   212,   243,    -1,    -1,    -1,     8,
+      -1,   249,    -1,    -1,   427,    -1,    -1,    -1,    17,    -1,
+      -1,    -1,    -1,    22,    23,    24,    -1,    -1,    -1,    -1,
+      29,    -1,    -1,   271,    -1,    -1,    -1,    36,    -1,    -1,
+      -1,    -1,    -1,    -1,    49,   283,    -1,    -1,   286,   287,
+      -1,    -1,     4,     5,    53,    -1,    61,   470,    -1,    64,
+      59,    -1,    -1,    -1,   477,    -1,    65,    -1,    -1,    -1,
+      -1,    -1,    71,   486,    73,    74,    75,    -1,    -1,    -1,
+      -1,    33,    34,   496,    36,    37,    38,    39,    40,    -1,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    -1,   341,   520,    -1,    -1,
+      -1,    -1,    -1,    65,   349,    -1,    -1,    -1,   334,    -1,
+      -1,    -1,   360,    75,    -1,   341,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   349,   372,    -1,   374,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   382,    -1,    -1,    -1,   386,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   570,    -1,    -1,
+     573,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   406,   407,
+     175,   176,   177,   178,    -1,   180,   181,   182,    -1,   184,
+     185,   186,   187,   188,   189,   190,   191,   192,   193,   194,
+     195,   196,   197,    -1,   199,    -1,   201,    -1,   203,    -1,
+      -1,    -1,   207,   208,   209,   440,    -1,    -1,    -1,   622,
+      -1,   446,   447,    -1,   449,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   458,   440,   460,    -1,    -1,   641,    -1,
+     446,   447,   470,   449,    -1,    -1,    -1,    -1,    -1,   477,
+      -1,    -1,   458,    -1,   460,    -1,    -1,    -1,   486,    -1,
+       8,    -1,    -1,     3,    -1,    -1,    -1,    -1,     8,    17,
+      -1,    11,    -1,    -1,    22,    23,    24,    17,    -1,    -1,
+      -1,    29,    22,    23,    24,   280,    -1,    -1,    36,    29,
+      -1,    -1,   520,    -1,    -1,   290,    36,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    53,    -1,    -1,    -1,    49,
+      50,    59,    52,    53,    -1,    -1,    56,    65,   313,    59,
+      -1,    -1,   317,    71,   549,    73,    74,    75,   323,    69,
+      70,    71,   557,    73,    74,    -1,    -1,    -1,     8,    -1,
+      -1,    11,   570,   549,    -1,   573,    -1,    17,    -1,    -1,
+      -1,   557,    22,    23,    24,    -1,    -1,    -1,   564,    29,
+      -1,    -1,    -1,    -1,    -1,    -1,    36,    -1,    -1,    -1,
+      -1,   366,   367,    -1,   599,   600,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    53,    -1,    -1,    -1,    -1,    -1,    59,
+     596,    -1,    -1,   599,   600,    -1,    -1,    -1,    -1,     0,
+       1,    71,     3,    73,    74,     6,    -1,     8,     9,    10,
+     405,    -1,    13,   641,    15,    16,    17,    18,    19,    20,
+      -1,    22,    23,    24,   419,    -1,    27,    28,    29,    30,
+      31,    32,   427,    -1,    -1,    36,    -1,   432,    -1,    -1,
+      -1,    -1,   648,    -1,   650,    -1,    -1,    -1,    49,    50,
+      -1,    52,    53,    -1,    -1,    56,    -1,    -1,    59,    -1,
+      -1,    62,    -1,    -1,    -1,    -1,    -1,    -1,    69,    70,
+      71,    -1,    73,    74,    -1,    -1,    -1,    -1,   473,   474,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,     1,    -1,
+       3,    -1,    -1,     6,     7,     8,     9,    10,    -1,    12,
+      13,   496,    15,    16,    17,    18,    19,    20,    -1,    22,
+      23,    24,    -1,    -1,    27,    28,    29,    30,    31,    32,
+      -1,   516,    -1,    36,    -1,    -1,    -1,    -1,   523,   524,
+     525,    -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,    34,    -1,    27,    28,
+      29,    30,    31,    32,    -1,    -1,    44,    36,    -1,    -1,
       48,    49,    50,    51,    52,    53,    54,    55,    56,    -1,
-      -1,    -1,   406,   407,   175,   176,   177,   178,    -1,   180,
-     181,   182,    -1,   184,   185,   186,   187,   188,   189,   190,
-     191,   192,   193,   194,   195,   196,   197,    -1,   199,    -1,
-     201,    -1,   203,   334,    -1,    -1,   207,   208,   209,    -1,
-     341,     7,    -1,    -1,    -1,    11,    -1,    -1,   349,    -1,
-       4,    17,    -1,    -1,     8,    -1,    22,    23,    24,    -1,
-      -1,    -1,    -1,    29,    -1,   469,    -1,    -1,    -1,    -1,
-      36,    -1,   476,    -1,    -1,    -1,    -1,    -1,    -1,    33,
-      34,   485,    36,    37,    38,    39,    40,    53,    42,    43,
-      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
-      54,    55,    56,    -1,    -1,    71,    -1,    -1,    74,   280,
-      -1,    65,    -1,    -1,    -1,   519,    -1,    -1,    -1,   290,
-      -1,    75,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   439,    -1,
-      -1,    -1,   313,    -1,   445,   446,   317,   448,    -1,    -1,
-      -1,    -1,   323,    -1,     0,     1,   457,     3,   459,     5,
-      -1,     7,    -1,     9,    10,   569,    -1,    13,   572,    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,   366,   367,    -1,    -1,    -1,
-      -1,    -1,    -1,    49,    50,    -1,    52,    53,    -1,    -1,
-      56,    -1,    -1,    59,    -1,    -1,    62,    -1,     3,    -1,
-      -1,    -1,     7,    69,    70,    71,    11,    73,    74,    -1,
-      -1,    -1,    17,    -1,   405,   639,    -1,    22,    23,    24,
-      -1,    -1,    -1,    -1,    29,    -1,    -1,   548,   419,    -1,
-      -1,    36,    -1,    -1,    -1,   556,   427,    -1,    -1,    -1,
-      -1,   432,   563,    -1,    49,    50,    -1,    52,    53,    -1,
-      -1,    56,    -1,    -1,    59,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    69,    70,    71,    -1,    73,    74,
-      -1,    -1,    -1,   594,    -1,    -1,   597,   598,    -1,    -1,
-      -1,   472,   473,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,     1,    -1,     3,    -1,     5,     6,     7,    -1,     9,
-      10,    -1,    12,    13,   495,    15,    16,    17,    18,    19,
-      20,    -1,    22,    23,    24,    -1,    -1,    27,    28,    29,
-      30,    31,    32,   644,   515,   646,    36,    -1,    -1,    -1,
-      -1,   522,   523,   524,    -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,     5,
-      -1,     7,    -1,     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,    -1,    59,    -1,     3,    62,   618,   619,     7,
-     621,    67,    68,    69,    70,    71,    -1,    73,    74,    17,
-       7,    -1,    -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,     7,    -1,    53,    -1,    -1,    -1,
-      -1,    69,    70,    71,    17,    73,    74,    -1,    65,    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,    -1,    -1,     7,
-      -1,    -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,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    49,    50,    -1,    52,    53,    -1,    -1,    56,    -1,
-       3,    59,    -1,    -1,     7,    -1,    -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,     7,
-      -1,    -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,
+      49,    50,    -1,    52,    53,    -1,    -1,    56,    -1,    -1,
+      59,    -1,    -1,    62,   619,   620,    -1,   622,    67,    68,
+      69,    70,    71,     3,    73,    74,   631,    -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,    -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,    -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,    36,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    49,    50,    -1,    52,    53,    -1,    -1,    56,    -1,
-       3,    59,    -1,    -1,     7,    -1,    -1,    -1,    -1,    -1,
-      -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,     7,
-      -1,    -1,    -1,    -1,    -1,    -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,     7,    -1,    -1,    -1,    -1,    -1,
-      -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,    -1,    59,    -1,    -1,     7,
-      -1,    -1,    -1,    -1,    -1,    -1,    69,    70,    71,    17,
-      73,    74,    -1,    -1,    22,    23,    24,    -1,    -1,    -1,
-      -1,    29,    -1,    -1,    -1,     7,    -1,    -1,    36,    11,
-      -1,    -1,    -1,     7,    -1,    17,    -1,    -1,    -1,    -1,
-      22,    23,    24,    17,    -1,    53,    -1,    29,    22,    23,
-      24,    59,    -1,    -1,    36,    29,    -1,    65,     7,    -1,
-      -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,     7,    36,    -1,    71,
-      -1,    73,    74,    -1,    -1,    -1,    17,    71,    -1,    73,
-      74,    22,    23,    24,    53,    -1,    -1,    -1,    29,    -1,
-      59,     7,    -1,    -1,    -1,    36,    -1,    -1,    -1,     7,
-      -1,    17,    71,    -1,    73,    74,    22,    23,    24,    17,
-      -1,    -1,    53,    29,    22,    23,    24,    -1,    59,    -1,
-      36,    29,    -1,    -1,     7,    -1,    -1,    -1,    36,    -1,
-      71,    -1,    73,    74,    17,    -1,    -1,    53,    -1,    22,
-      23,    24,    -1,    59,    -1,    53,    29,    -1,    -1,    -1,
-      -1,    59,     7,    36,    -1,    71,    -1,    73,    74,    -1,
-      -1,    -1,    17,    71,    -1,    73,    74,    22,    23,    24,
-      53,    -1,    -1,    -1,    29,    -1,    59,     7,    -1,    -1,
-      -1,    36,    -1,    -1,    -1,     7,    -1,    17,    71,    -1,
-      -1,    74,    22,    23,    24,    17,    -1,    -1,    53,    29,
-      22,    23,    24,    -1,    -1,    -1,    36,    29,    -1,    -1,
-      -1,    -1,    -1,    -1,    36,    -1,    71,    -1,    73,    74,
-      -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,    39,    40,    -1,    -1,
-      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,
+      -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,
+       8,    -1,    -1,    36,    -1,    -1,    -1,    -1,     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,    -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,    -1,    -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,
+      -1,    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,    33,    34,    -1,    36,    -1,    38,    39,    40,
-      -1,    66,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,    52,    53,    54,    55,    56,    -1,    33,    34,    60,
-      36,    -1,    38,    39,    40,    -1,    -1,    43,    44,    45,
+      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,    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,    34,
-      -1,    -1,    -1,    38,    39,    40,    -1,    -1,    43,    44,
-      45,    46,    -1,    48,    49,    50,    51,    52,    53,    54,
-      55,    56
+      -1,    43,    44,    45,    46,    -1,    48,    49,    50,    51,
+      52,    53,    54,    55,    56
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -1488,71 +1485,72 @@ static const yytype_int16 yycheck[] =
 static const yytype_uint8 yystos[] =
 {
        0,    77,    79,    80,     0,    25,    78,    25,    86,    24,
-      73,    74,   137,   138,    81,    24,    88,    89,     3,    62,
-      21,    82,   162,    24,    87,   210,    63,     3,    59,    63,
-      83,    85,   137,    62,     1,     3,     5,     7,     9,    10,
+      73,    74,   141,   142,    81,    24,    88,    89,     3,    62,
+      21,    82,   166,    24,    87,   214,    63,     3,    59,    63,
+      83,    85,   141,    62,     1,     3,     6,     8,     9,    10,
       13,    15,    16,    17,    18,    19,    20,    22,    23,    27,
       28,    29,    30,    31,    32,    36,    49,    50,    52,    53,
       56,    59,    69,    70,    71,    90,    91,    92,    98,   110,
-     113,   118,   121,   123,   124,   125,   126,   130,   134,   137,
-     139,   140,   145,   146,   149,   152,   153,   154,   157,   160,
-     161,   177,   182,    62,     9,    17,    21,    31,    32,    64,
-     195,    24,    60,    83,    84,     3,    86,    88,     3,   134,
-     136,   137,    17,    36,    53,    59,   137,   139,   144,   148,
-     149,   150,   157,   136,   125,   130,   111,    59,   137,   155,
-     125,   134,   114,    35,    67,   133,    71,   123,   182,   189,
-     122,   133,   119,    59,    96,    97,   137,    59,    93,   135,
-     137,   181,   124,   124,   124,   124,   124,   124,    36,    53,
-     123,   131,   143,   149,   151,   157,   124,   124,    11,   123,
-     188,    62,    59,    94,   181,     4,    33,    34,    36,    37,
+     113,   121,   124,   126,   127,   128,   129,   134,   138,   141,
+     143,   144,   149,   150,   153,   156,   157,   158,   161,   164,
+     165,   181,   186,    62,     9,    17,    21,    31,    32,    64,
+     199,    24,    60,    83,    84,     3,    86,    88,     3,   138,
+     140,   141,    17,    36,    53,    59,   141,   143,   148,   152,
+     153,   154,   161,   140,   128,   134,   111,    59,   141,   159,
+     128,   138,   114,    35,    67,   137,    71,   126,   186,   193,
+     125,   137,   122,    59,    96,    97,   141,    59,    93,   139,
+     141,   185,   127,   127,   127,   127,   127,   127,    36,    53,
+     126,   135,   147,   153,   155,   161,   127,   127,    11,   126,
+     192,    62,    59,    94,   185,     4,    33,    34,    36,    37,
       38,    39,    40,    42,    43,    44,    45,    46,    47,    48,
       49,    50,    51,    52,    53,    54,    55,    56,    67,    59,
-      63,    71,    66,    59,   133,     1,   133,     8,    65,    75,
-     138,   196,    59,   156,   196,    24,   196,   197,   196,    64,
-      62,   186,    88,    59,    36,    59,   142,   148,   149,   150,
-     151,   157,   142,   142,    63,    98,   107,   108,   109,   182,
-     190,    11,   132,   137,   141,   142,   173,   174,   175,    59,
-      67,   158,   112,   190,    24,    59,    68,   134,   167,   169,
-     171,   142,    35,    53,    59,    68,   134,   166,   168,   169,
-     170,   180,   112,    60,    97,   165,   142,    60,    93,   163,
-      65,    75,   142,     7,   143,    60,    72,    72,    60,    94,
-      65,   142,   123,   123,   123,   123,   123,   123,   123,   123,
-     123,   123,   123,   123,   123,   123,   123,   123,   123,   123,
-     123,   123,   123,   127,    60,   131,   183,    59,   137,   123,
-     188,   178,   123,   127,     1,    67,    91,   100,   176,   177,
-     179,   182,   182,   123,     7,    17,    22,    23,    24,    29,
-      36,    53,    65,    71,   138,   198,   200,   201,   202,   137,
-     203,   211,   158,    59,     3,   198,   198,    83,    60,   175,
-       7,   142,    60,   137,    35,   105,     8,    65,    62,   142,
-     132,   141,    75,   187,    60,   175,   179,   115,    62,    63,
-      24,   169,    59,   172,    62,   186,    72,   104,    59,   170,
-      53,   170,    62,   186,     3,   194,    75,   142,   120,    62,
-     186,    62,   186,   182,   135,    65,    36,    59,   142,   148,
-     149,   150,   157,    67,   142,   142,    62,   186,   182,    65,
-      67,   123,   128,   129,   184,   185,    11,    75,   187,    31,
-     131,    72,    66,   176,    60,   185,   101,    62,    68,    36,
-      59,   199,   200,   202,    59,    67,    71,    67,     7,   198,
-       3,    50,    59,   137,   208,   209,     3,    72,    65,    11,
-     198,    60,    75,    62,   191,   211,    62,    62,    62,    60,
-      60,   106,    26,    26,   190,   173,    59,   137,   147,   148,
-     149,   150,   151,   157,   159,    60,    68,   105,   190,   137,
-      60,   175,   171,    68,   142,     6,    12,    68,    99,   102,
-     170,   194,   170,    60,   168,    68,   134,   194,    35,    97,
-      60,    93,    60,   182,   142,   127,    94,    95,   164,   181,
-      60,   182,   127,    66,    75,   187,    68,    75,   187,   131,
-      60,    60,    60,   188,    68,   179,   176,   198,   201,   191,
-      24,   137,   138,   193,   198,   205,   213,   198,   137,   192,
-     204,   212,   198,     3,   208,    62,    72,   198,   209,   198,
-     194,   137,   203,    60,   179,   123,   123,    62,   175,    59,
-     159,   116,    60,   183,    66,   103,    60,    60,   194,   104,
-      60,   185,    62,   186,   142,   185,   123,   129,   128,   129,
-      60,    72,    68,    60,    60,    59,    68,    62,    72,   198,
-      68,    62,    49,   198,    62,   194,    59,    59,   198,   206,
-     207,    68,   190,    60,   175,    14,   117,   159,     8,    65,
-      66,    75,   179,   194,   194,    68,    68,    95,    60,    68,
-     206,   191,   205,   198,   194,   204,   208,   191,   191,    60,
-     100,   113,   123,   123,    60,    60,    60,    60,   159,    66,
-      66,   206,   206
+      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,   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,    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,   210,   195,   209,   202,   198,   208,   212,   195,
+     195,    60,    14,   117,   120,   126,   126,   189,    60,    60,
+      60,    60,   163,    20,   100,    66,    66,    68,   210,   210,
+     118,   112,   105
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -1567,18 +1565,9 @@ 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)
 
@@ -1588,6 +1577,7 @@ do								\
     {								\
       yychar = (Token);						\
       yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
       YYPOPSTACK (1);						\
       goto yybackup;						\
     }								\
@@ -1629,10 +1619,19 @@ while (YYID (0))
 #endif
 
 
-/* This macro is provided for backward compatibility. */
+/* 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
 
 
@@ -1736,20 +1735,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");
 }
 
@@ -1783,11 +1779,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");
     }
 }
 
@@ -1824,6 +1820,7 @@ int yydebug;
 # define YYMAXDEPTH 10000
 #endif
 
+
 
 #if YYERROR_VERBOSE
 
@@ -1926,142 +1923,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 (0, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
-  YYSIZE_T yysize1;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = 0;
-  /* 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];
-                yysize1 = yysize + yytnamerr (0, 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;
+	  }
 
-  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.  |
@@ -2093,9 +2063,10 @@ yydestruct (yymsg, yytype, yyvaluep)
 	break;
     }
 }
-
+
 
 /* Prevent warnings from -Wmissing-prototypes.  */
+
 #ifdef YYPARSE_PARAM
 #if defined __STDC__ || defined __cplusplus
 int yyparse (void *YYPARSE_PARAM);
@@ -2111,16 +2082,18 @@ int yyparse ();
 #endif /* ! YYPARSE_PARAM */
 
 
-/* The lookahead symbol.  */
+
+/* The look-ahead symbol.  */
 int yychar, yystate;
 
-/* The semantic value of the lookahead symbol.  */
+/* The semantic value of the look-ahead symbol.  */
 YYSTYPE yylval;
 
 /* Number of syntax errors so far.  */
 int yynerrs;
 
 
+
 /*----------.
 | yyparse.  |
 `----------*/
@@ -2147,36 +2120,13 @@ yyparse ()
 #endif
 #endif
 {
-    /* 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 thru 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 yyn;
   int yyresult;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken;
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
 #if YYERROR_VERBOSE
   /* Buffer for error messages, and its allocated size.  */
   char yymsgbuf[128];
@@ -2184,28 +2134,51 @@ 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;
 
-  yytoken = 0;
-  yyss = yyssa;
-  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;
 
@@ -2235,6 +2208,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
@@ -2242,6 +2216,7 @@ yyparse ()
 	yyoverflow (YY_("memory exhausted"),
 		    &yyss1, yysize * sizeof (*yyssp),
 		    &yyvs1, yysize * sizeof (*yyvsp),
+
 		    &yystacksize);
 
 	yyss = yyss1;
@@ -2264,8 +2239,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);
@@ -2276,6 +2252,7 @@ yyparse ()
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
+
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
 		  (unsigned long int) yystacksize));
 
@@ -2285,9 +2262,6 @@ yyparse ()
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
-  if (yystate == YYFINAL)
-    YYACCEPT;
-
   goto yybackup;
 
 /*-----------.
@@ -2296,16 +2270,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: "));
@@ -2331,22 +2305,26 @@ 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;
   *++yyvsp = yylval;
@@ -2386,8 +2364,6 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-
-/* Line 1806 of yacc.c  */
 #line 128 "go.y"
     {
 		xtop = concat(xtop, (yyvsp[(4) - (4)].list));
@@ -2395,8 +2371,6 @@ yyreduce:
     break;
 
   case 3:
-
-/* Line 1806 of yacc.c  */
 #line 134 "go.y"
     {
 		prevlineno = lineno;
@@ -2407,8 +2381,6 @@ yyreduce:
     break;
 
   case 4:
-
-/* Line 1806 of yacc.c  */
 #line 141 "go.y"
     {
 		mkpackage((yyvsp[(2) - (3)].sym)->name);
@@ -2416,8 +2388,6 @@ yyreduce:
     break;
 
   case 5:
-
-/* Line 1806 of yacc.c  */
 #line 151 "go.y"
     {
 		importpkg = runtimepkg;
@@ -2431,8 +2401,6 @@ yyreduce:
     break;
 
   case 6:
-
-/* Line 1806 of yacc.c  */
 #line 162 "go.y"
     {
 		importpkg = nil;
@@ -2440,8 +2408,6 @@ yyreduce:
     break;
 
   case 12:
-
-/* Line 1806 of yacc.c  */
 #line 176 "go.y"
     {
 		Pkg *ipkg;
@@ -2478,8 +2444,6 @@ yyreduce:
     break;
 
   case 13:
-
-/* Line 1806 of yacc.c  */
 #line 209 "go.y"
     {
 		// When an invalid import path is passed to importfile,
@@ -2492,8 +2456,6 @@ yyreduce:
     break;
 
   case 16:
-
-/* Line 1806 of yacc.c  */
 #line 224 "go.y"
     {
 		// import with original name
@@ -2504,8 +2466,6 @@ yyreduce:
     break;
 
   case 17:
-
-/* Line 1806 of yacc.c  */
 #line 231 "go.y"
     {
 		// import with given name
@@ -2516,8 +2476,6 @@ yyreduce:
     break;
 
   case 18:
-
-/* Line 1806 of yacc.c  */
 #line 238 "go.y"
     {
 		// import into my name space
@@ -2528,8 +2486,6 @@ yyreduce:
     break;
 
   case 19:
-
-/* Line 1806 of yacc.c  */
 #line 247 "go.y"
     {
 		if(importpkg->name == nil) {
@@ -2545,8 +2501,6 @@ yyreduce:
     break;
 
   case 21:
-
-/* Line 1806 of yacc.c  */
 #line 261 "go.y"
     {
 		if(strcmp((yyvsp[(1) - (1)].sym)->name, "safe") == 0)
@@ -2555,8 +2509,6 @@ yyreduce:
     break;
 
   case 22:
-
-/* Line 1806 of yacc.c  */
 #line 267 "go.y"
     {
 		defercheckwidth();
@@ -2564,8 +2516,6 @@ yyreduce:
     break;
 
   case 23:
-
-/* Line 1806 of yacc.c  */
 #line 271 "go.y"
     {
 		resumecheckwidth();
@@ -2574,8 +2524,6 @@ yyreduce:
     break;
 
   case 24:
-
-/* Line 1806 of yacc.c  */
 #line 280 "go.y"
     {
 		yyerror("empty top-level declaration");
@@ -2584,8 +2532,6 @@ yyreduce:
     break;
 
   case 26:
-
-/* Line 1806 of yacc.c  */
 #line 286 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
@@ -2593,8 +2539,6 @@ yyreduce:
     break;
 
   case 27:
-
-/* Line 1806 of yacc.c  */
 #line 290 "go.y"
     {
 		yyerror("non-declaration statement outside function body");
@@ -2603,8 +2547,6 @@ yyreduce:
     break;
 
   case 28:
-
-/* Line 1806 of yacc.c  */
 #line 295 "go.y"
     {
 		(yyval.list) = nil;
@@ -2612,8 +2554,6 @@ yyreduce:
     break;
 
   case 29:
-
-/* Line 1806 of yacc.c  */
 #line 301 "go.y"
     {
 		(yyval.list) = (yyvsp[(2) - (2)].list);
@@ -2621,8 +2561,6 @@ yyreduce:
     break;
 
   case 30:
-
-/* Line 1806 of yacc.c  */
 #line 305 "go.y"
     {
 		(yyval.list) = (yyvsp[(3) - (5)].list);
@@ -2630,8 +2568,6 @@ yyreduce:
     break;
 
   case 31:
-
-/* Line 1806 of yacc.c  */
 #line 309 "go.y"
     {
 		(yyval.list) = nil;
@@ -2639,8 +2575,6 @@ yyreduce:
     break;
 
   case 32:
-
-/* Line 1806 of yacc.c  */
 #line 313 "go.y"
     {
 		(yyval.list) = (yyvsp[(2) - (2)].list);
@@ -2650,8 +2584,6 @@ yyreduce:
     break;
 
   case 33:
-
-/* Line 1806 of yacc.c  */
 #line 319 "go.y"
     {
 		(yyval.list) = (yyvsp[(3) - (5)].list);
@@ -2661,8 +2593,6 @@ yyreduce:
     break;
 
   case 34:
-
-/* Line 1806 of yacc.c  */
 #line 325 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(3) - (7)].list), (yyvsp[(5) - (7)].list));
@@ -2672,8 +2602,6 @@ yyreduce:
     break;
 
   case 35:
-
-/* Line 1806 of yacc.c  */
 #line 331 "go.y"
     {
 		(yyval.list) = nil;
@@ -2682,8 +2610,6 @@ yyreduce:
     break;
 
   case 36:
-
-/* Line 1806 of yacc.c  */
 #line 336 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(2) - (2)].node));
@@ -2691,8 +2617,6 @@ yyreduce:
     break;
 
   case 37:
-
-/* Line 1806 of yacc.c  */
 #line 340 "go.y"
     {
 		(yyval.list) = (yyvsp[(3) - (5)].list);
@@ -2700,8 +2624,6 @@ yyreduce:
     break;
 
   case 38:
-
-/* Line 1806 of yacc.c  */
 #line 344 "go.y"
     {
 		(yyval.list) = nil;
@@ -2709,8 +2631,6 @@ yyreduce:
     break;
 
   case 39:
-
-/* Line 1806 of yacc.c  */
 #line 350 "go.y"
     {
 		iota = 0;
@@ -2718,8 +2638,6 @@ yyreduce:
     break;
 
   case 40:
-
-/* Line 1806 of yacc.c  */
 #line 356 "go.y"
     {
 		(yyval.list) = variter((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node), nil);
@@ -2727,8 +2645,6 @@ yyreduce:
     break;
 
   case 41:
-
-/* Line 1806 of yacc.c  */
 #line 360 "go.y"
     {
 		(yyval.list) = variter((yyvsp[(1) - (4)].list), (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].list));
@@ -2736,8 +2652,6 @@ yyreduce:
     break;
 
   case 42:
-
-/* Line 1806 of yacc.c  */
 #line 364 "go.y"
     {
 		(yyval.list) = variter((yyvsp[(1) - (3)].list), nil, (yyvsp[(3) - (3)].list));
@@ -2745,8 +2659,6 @@ yyreduce:
     break;
 
   case 43:
-
-/* Line 1806 of yacc.c  */
 #line 370 "go.y"
     {
 		(yyval.list) = constiter((yyvsp[(1) - (4)].list), (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].list));
@@ -2754,8 +2666,6 @@ yyreduce:
     break;
 
   case 44:
-
-/* Line 1806 of yacc.c  */
 #line 374 "go.y"
     {
 		(yyval.list) = constiter((yyvsp[(1) - (3)].list), N, (yyvsp[(3) - (3)].list));
@@ -2763,8 +2673,6 @@ yyreduce:
     break;
 
   case 46:
-
-/* Line 1806 of yacc.c  */
 #line 381 "go.y"
     {
 		(yyval.list) = constiter((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node), nil);
@@ -2772,8 +2680,6 @@ yyreduce:
     break;
 
   case 47:
-
-/* Line 1806 of yacc.c  */
 #line 385 "go.y"
     {
 		(yyval.list) = constiter((yyvsp[(1) - (1)].list), N, nil);
@@ -2781,8 +2687,6 @@ yyreduce:
     break;
 
   case 48:
-
-/* Line 1806 of yacc.c  */
 #line 391 "go.y"
     {
 		// different from dclname because the name
@@ -2793,8 +2697,6 @@ yyreduce:
     break;
 
   case 49:
-
-/* Line 1806 of yacc.c  */
 #line 400 "go.y"
     {
 		(yyval.node) = typedcl1((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node), 1);
@@ -2802,18 +2704,28 @@ yyreduce:
     break;
 
   case 50:
-
-/* Line 1806 of yacc.c  */
 #line 406 "go.y"
     {
 		(yyval.node) = (yyvsp[(1) - (1)].node);
+
+		// These nodes do not carry line numbers.
+		// Since a bare name used as an expression is an error,
+		// introduce a wrapper node to give the correct line.
+		switch((yyval.node)->op) {
+		case ONAME:
+		case ONONAME:
+		case OTYPE:
+		case OPACK:
+		case OLITERAL:
+			(yyval.node) = nod(OPAREN, (yyval.node), N);
+			(yyval.node)->implicit = 1;
+			break;
+		}
 	}
     break;
 
   case 51:
-
-/* Line 1806 of yacc.c  */
-#line 410 "go.y"
+#line 424 "go.y"
     {
 		(yyval.node) = nod(OASOP, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 		(yyval.node)->etype = (yyvsp[(2) - (3)].i);			// rathole to pass opcode
@@ -2821,9 +2733,7 @@ yyreduce:
     break;
 
   case 52:
-
-/* Line 1806 of yacc.c  */
-#line 415 "go.y"
+#line 429 "go.y"
     {
 		if((yyvsp[(1) - (3)].list)->next == nil && (yyvsp[(3) - (3)].list)->next == nil) {
 			// simple
@@ -2838,9 +2748,7 @@ yyreduce:
     break;
 
   case 53:
-
-/* Line 1806 of yacc.c  */
-#line 427 "go.y"
+#line 441 "go.y"
     {
 		if((yyvsp[(3) - (3)].list)->n->op == OTYPESW) {
 			(yyval.node) = nod(OTYPESW, N, (yyvsp[(3) - (3)].list)->n->right);
@@ -2854,14 +2762,12 @@ yyreduce:
 				(yyval.node)->left = dclname((yyvsp[(1) - (3)].list)->n->sym);  // it's a colas, so must not re-use an oldname.
 			break;
 		}
-		(yyval.node) = colas((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
+		(yyval.node) = colas((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list), (yyvsp[(2) - (3)].i));
 	}
     break;
 
   case 54:
-
-/* Line 1806 of yacc.c  */
-#line 443 "go.y"
+#line 457 "go.y"
     {
 		(yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1));
 		(yyval.node)->etype = OADD;
@@ -2869,9 +2775,7 @@ yyreduce:
     break;
 
   case 55:
-
-/* Line 1806 of yacc.c  */
-#line 448 "go.y"
+#line 462 "go.y"
     {
 		(yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1));
 		(yyval.node)->etype = OSUB;
@@ -2879,9 +2783,7 @@ yyreduce:
     break;
 
   case 56:
-
-/* Line 1806 of yacc.c  */
-#line 455 "go.y"
+#line 469 "go.y"
     {
 		Node *n, *nn;
 
@@ -2904,9 +2806,7 @@ yyreduce:
     break;
 
   case 57:
-
-/* Line 1806 of yacc.c  */
-#line 475 "go.y"
+#line 489 "go.y"
     {
 		Node *n;
 
@@ -2927,23 +2827,19 @@ yyreduce:
     break;
 
   case 58:
-
-/* Line 1806 of yacc.c  */
-#line 493 "go.y"
+#line 507 "go.y"
     {
 		// will be converted to OCASE
 		// right will point to next case
 		// done in casebody()
 		markdcl();
 		(yyval.node) = nod(OXCASE, N, N);
-		(yyval.node)->list = list1(colas((yyvsp[(2) - (5)].list), list1((yyvsp[(4) - (5)].node))));
+		(yyval.node)->list = list1(colas((yyvsp[(2) - (5)].list), list1((yyvsp[(4) - (5)].node)), (yyvsp[(3) - (5)].i)));
 	}
     break;
 
   case 59:
-
-/* Line 1806 of yacc.c  */
-#line 502 "go.y"
+#line 516 "go.y"
     {
 		Node *n, *nn;
 
@@ -2962,18 +2858,14 @@ yyreduce:
     break;
 
   case 60:
-
-/* Line 1806 of yacc.c  */
-#line 520 "go.y"
+#line 534 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 61:
-
-/* Line 1806 of yacc.c  */
-#line 524 "go.y"
+#line 538 "go.y"
     {
 		(yyval.node) = liststmt((yyvsp[(3) - (4)].list));
 		popdcl();
@@ -2981,9 +2873,7 @@ yyreduce:
     break;
 
   case 62:
-
-/* Line 1806 of yacc.c  */
-#line 531 "go.y"
+#line 545 "go.y"
     {
 		// If the last token read by the lexer was consumed
 		// as part of the case, clear it (parser has cleared yychar).
@@ -2996,9 +2886,7 @@ yyreduce:
     break;
 
   case 63:
-
-/* Line 1806 of yacc.c  */
-#line 541 "go.y"
+#line 555 "go.y"
     {
 		int last;
 
@@ -3020,36 +2908,28 @@ yyreduce:
     break;
 
   case 64:
-
-/* Line 1806 of yacc.c  */
-#line 561 "go.y"
+#line 575 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 65:
-
-/* Line 1806 of yacc.c  */
-#line 565 "go.y"
+#line 579 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node));
 	}
     break;
 
   case 66:
-
-/* Line 1806 of yacc.c  */
-#line 571 "go.y"
+#line 585 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 67:
-
-/* Line 1806 of yacc.c  */
-#line 575 "go.y"
+#line 589 "go.y"
     {
 		(yyval.list) = (yyvsp[(3) - (4)].list);
 		popdcl();
@@ -3057,9 +2937,7 @@ yyreduce:
     break;
 
   case 68:
-
-/* Line 1806 of yacc.c  */
-#line 582 "go.y"
+#line 596 "go.y"
     {
 		(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
 		(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -3068,9 +2946,7 @@ yyreduce:
     break;
 
   case 69:
-
-/* Line 1806 of yacc.c  */
-#line 588 "go.y"
+#line 602 "go.y"
     {
 		(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
 		(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -3080,9 +2956,7 @@ yyreduce:
     break;
 
   case 70:
-
-/* Line 1806 of yacc.c  */
-#line 597 "go.y"
+#line 611 "go.y"
     {
 		// init ; test ; incr
 		if((yyvsp[(5) - (5)].node) != N && (yyvsp[(5) - (5)].node)->colas != 0)
@@ -3096,9 +2970,7 @@ yyreduce:
     break;
 
   case 71:
-
-/* Line 1806 of yacc.c  */
-#line 608 "go.y"
+#line 622 "go.y"
     {
 		// normal test
 		(yyval.node) = nod(OFOR, N, N);
@@ -3107,9 +2979,7 @@ yyreduce:
     break;
 
   case 73:
-
-/* Line 1806 of yacc.c  */
-#line 617 "go.y"
+#line 631 "go.y"
     {
 		(yyval.node) = (yyvsp[(1) - (2)].node);
 		(yyval.node)->nbody = concat((yyval.node)->nbody, (yyvsp[(2) - (2)].list));
@@ -3117,18 +2987,14 @@ yyreduce:
     break;
 
   case 74:
-
-/* Line 1806 of yacc.c  */
-#line 624 "go.y"
+#line 638 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 75:
-
-/* Line 1806 of yacc.c  */
-#line 628 "go.y"
+#line 642 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (3)].node);
 		popdcl();
@@ -3136,9 +3002,7 @@ yyreduce:
     break;
 
   case 76:
-
-/* Line 1806 of yacc.c  */
-#line 635 "go.y"
+#line 649 "go.y"
     {
 		// test
 		(yyval.node) = nod(OIF, N, N);
@@ -3147,9 +3011,7 @@ yyreduce:
     break;
 
   case 77:
-
-/* Line 1806 of yacc.c  */
-#line 641 "go.y"
+#line 655 "go.y"
     {
 		// init ; test
 		(yyval.node) = nod(OIF, N, N);
@@ -3160,18 +3022,14 @@ yyreduce:
     break;
 
   case 78:
-
-/* Line 1806 of yacc.c  */
-#line 652 "go.y"
+#line 666 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 79:
-
-/* Line 1806 of yacc.c  */
-#line 656 "go.y"
+#line 670 "go.y"
     {
 		if((yyvsp[(3) - (3)].node)->ntest == N)
 			yyerror("missing condition in if statement");
@@ -3179,66 +3037,89 @@ yyreduce:
     break;
 
   case 80:
-
-/* Line 1806 of yacc.c  */
-#line 661 "go.y"
+#line 675 "go.y"
     {
 		(yyvsp[(3) - (5)].node)->nbody = (yyvsp[(5) - (5)].list);
 	}
     break;
 
   case 81:
-
-/* Line 1806 of yacc.c  */
-#line 665 "go.y"
+#line 679 "go.y"
     {
+		Node *n;
+		NodeList *nn;
+
+		(yyval.node) = (yyvsp[(3) - (8)].node);
+		n = (yyvsp[(3) - (8)].node);
 		popdcl();
-		(yyval.node) = (yyvsp[(3) - (7)].node);
-		if((yyvsp[(7) - (7)].node) != N)
-			(yyval.node)->nelse = list1((yyvsp[(7) - (7)].node));
+		for(nn = concat((yyvsp[(7) - (8)].list), (yyvsp[(8) - (8)].list)); nn; nn = nn->next) {
+			if(nn->n->op == OIF)
+				popdcl();
+			n->nelse = list1(nn->n);
+			n = nn->n;
+		}
 	}
     break;
 
   case 82:
-
-/* Line 1806 of yacc.c  */
-#line 673 "go.y"
+#line 696 "go.y"
     {
-		(yyval.node) = N;
+		markdcl();
 	}
     break;
 
   case 83:
-
-/* Line 1806 of yacc.c  */
-#line 677 "go.y"
+#line 700 "go.y"
     {
-		(yyval.node) = (yyvsp[(2) - (2)].node);
+		if((yyvsp[(4) - (5)].node)->ntest == N)
+			yyerror("missing condition in if statement");
+		(yyvsp[(4) - (5)].node)->nbody = (yyvsp[(5) - (5)].list);
+		(yyval.list) = list1((yyvsp[(4) - (5)].node));
 	}
     break;
 
   case 84:
-
-/* Line 1806 of yacc.c  */
-#line 681 "go.y"
+#line 708 "go.y"
     {
-		(yyval.node) = (yyvsp[(2) - (2)].node);
+		(yyval.list) = nil;
 	}
     break;
 
   case 85:
-
-/* Line 1806 of yacc.c  */
-#line 687 "go.y"
+#line 712 "go.y"
     {
-		markdcl();
+		(yyval.list) = concat((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list));
 	}
     break;
 
   case 86:
+#line 717 "go.y"
+    {
+		(yyval.list) = nil;
+	}
+    break;
+
+  case 87:
+#line 721 "go.y"
+    {
+		NodeList *node;
+		
+		node = mal(sizeof *node);
+		node->n = (yyvsp[(2) - (2)].node);
+		node->end = node;
+		(yyval.list) = node;
+	}
+    break;
+
+  case 88:
+#line 732 "go.y"
+    {
+		markdcl();
+	}
+    break;
 
-/* Line 1806 of yacc.c  */
-#line 691 "go.y"
+  case 89:
+#line 736 "go.y"
     {
 		Node *n;
 		n = (yyvsp[(3) - (3)].node)->ntest;
@@ -3248,10 +3129,8 @@ yyreduce:
 	}
     break;
 
-  case 87:
-
-/* Line 1806 of yacc.c  */
-#line 699 "go.y"
+  case 90:
+#line 744 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (7)].node);
 		(yyval.node)->op = OSWITCH;
@@ -3261,19 +3140,15 @@ yyreduce:
 	}
     break;
 
-  case 88:
-
-/* Line 1806 of yacc.c  */
-#line 709 "go.y"
+  case 91:
+#line 754 "go.y"
     {
 		typesw = nod(OXXX, typesw, N);
 	}
     break;
 
-  case 89:
-
-/* Line 1806 of yacc.c  */
-#line 713 "go.y"
+  case 92:
+#line 758 "go.y"
     {
 		(yyval.node) = nod(OSELECT, N, N);
 		(yyval.node)->lineno = typesw->lineno;
@@ -3282,199 +3157,155 @@ yyreduce:
 	}
     break;
 
-  case 91:
-
-/* Line 1806 of yacc.c  */
-#line 726 "go.y"
+  case 94:
+#line 771 "go.y"
     {
 		(yyval.node) = nod(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 92:
-
-/* Line 1806 of yacc.c  */
-#line 730 "go.y"
+  case 95:
+#line 775 "go.y"
     {
 		(yyval.node) = nod(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 93:
-
-/* Line 1806 of yacc.c  */
-#line 734 "go.y"
+  case 96:
+#line 779 "go.y"
     {
 		(yyval.node) = nod(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 94:
-
-/* Line 1806 of yacc.c  */
-#line 738 "go.y"
+  case 97:
+#line 783 "go.y"
     {
 		(yyval.node) = nod(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 95:
-
-/* Line 1806 of yacc.c  */
-#line 742 "go.y"
+  case 98:
+#line 787 "go.y"
     {
 		(yyval.node) = nod(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 96:
-
-/* Line 1806 of yacc.c  */
-#line 746 "go.y"
+  case 99:
+#line 791 "go.y"
     {
 		(yyval.node) = nod(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 97:
-
-/* Line 1806 of yacc.c  */
-#line 750 "go.y"
+  case 100:
+#line 795 "go.y"
     {
 		(yyval.node) = nod(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 98:
-
-/* Line 1806 of yacc.c  */
-#line 754 "go.y"
+  case 101:
+#line 799 "go.y"
     {
 		(yyval.node) = nod(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 99:
-
-/* Line 1806 of yacc.c  */
-#line 758 "go.y"
+  case 102:
+#line 803 "go.y"
     {
 		(yyval.node) = nod(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 100:
-
-/* Line 1806 of yacc.c  */
-#line 762 "go.y"
+  case 103:
+#line 807 "go.y"
     {
 		(yyval.node) = nod(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 101:
-
-/* Line 1806 of yacc.c  */
-#line 766 "go.y"
+  case 104:
+#line 811 "go.y"
     {
 		(yyval.node) = nod(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 102:
-
-/* Line 1806 of yacc.c  */
-#line 770 "go.y"
+  case 105:
+#line 815 "go.y"
     {
 		(yyval.node) = nod(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 103:
-
-/* Line 1806 of yacc.c  */
-#line 774 "go.y"
+  case 106:
+#line 819 "go.y"
     {
 		(yyval.node) = nod(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 104:
-
-/* Line 1806 of yacc.c  */
-#line 778 "go.y"
+  case 107:
+#line 823 "go.y"
     {
 		(yyval.node) = nod(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 105:
-
-/* Line 1806 of yacc.c  */
-#line 782 "go.y"
+  case 108:
+#line 827 "go.y"
     {
 		(yyval.node) = nod(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 106:
-
-/* Line 1806 of yacc.c  */
-#line 786 "go.y"
+  case 109:
+#line 831 "go.y"
     {
 		(yyval.node) = nod(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 107:
-
-/* Line 1806 of yacc.c  */
-#line 790 "go.y"
+  case 110:
+#line 835 "go.y"
     {
 		(yyval.node) = nod(OANDNOT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 108:
-
-/* Line 1806 of yacc.c  */
-#line 794 "go.y"
+  case 111:
+#line 839 "go.y"
     {
 		(yyval.node) = nod(OLSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 109:
-
-/* Line 1806 of yacc.c  */
-#line 798 "go.y"
+  case 112:
+#line 843 "go.y"
     {
 		(yyval.node) = nod(ORSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 110:
-
-/* Line 1806 of yacc.c  */
-#line 803 "go.y"
+  case 113:
+#line 848 "go.y"
     {
 		(yyval.node) = nod(OSEND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 112:
-
-/* Line 1806 of yacc.c  */
-#line 810 "go.y"
+  case 115:
+#line 855 "go.y"
     {
 		(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 113:
-
-/* Line 1806 of yacc.c  */
-#line 814 "go.y"
+  case 116:
+#line 859 "go.y"
     {
 		if((yyvsp[(2) - (2)].node)->op == OCOMPLIT) {
 			// Special case for &T{...}: turn into (*T){...}.
@@ -3487,84 +3318,66 @@ yyreduce:
 	}
     break;
 
-  case 114:
-
-/* Line 1806 of yacc.c  */
-#line 825 "go.y"
+  case 117:
+#line 870 "go.y"
     {
 		(yyval.node) = nod(OPLUS, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 115:
-
-/* Line 1806 of yacc.c  */
-#line 829 "go.y"
+  case 118:
+#line 874 "go.y"
     {
 		(yyval.node) = nod(OMINUS, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 116:
-
-/* Line 1806 of yacc.c  */
-#line 833 "go.y"
+  case 119:
+#line 878 "go.y"
     {
 		(yyval.node) = nod(ONOT, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 117:
-
-/* Line 1806 of yacc.c  */
-#line 837 "go.y"
+  case 120:
+#line 882 "go.y"
     {
 		yyerror("the bitwise complement operator is ^");
 		(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 118:
-
-/* Line 1806 of yacc.c  */
-#line 842 "go.y"
+  case 121:
+#line 887 "go.y"
     {
 		(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 119:
-
-/* Line 1806 of yacc.c  */
-#line 846 "go.y"
+  case 122:
+#line 891 "go.y"
     {
 		(yyval.node) = nod(ORECV, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 120:
-
-/* Line 1806 of yacc.c  */
-#line 856 "go.y"
+  case 123:
+#line 901 "go.y"
     {
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (3)].node), N);
 	}
     break;
 
-  case 121:
-
-/* Line 1806 of yacc.c  */
-#line 860 "go.y"
+  case 124:
+#line 905 "go.y"
     {
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
 		(yyval.node)->list = (yyvsp[(3) - (5)].list);
 	}
     break;
 
-  case 122:
-
-/* Line 1806 of yacc.c  */
-#line 865 "go.y"
+  case 125:
+#line 910 "go.y"
     {
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (6)].node), N);
 		(yyval.node)->list = (yyvsp[(3) - (6)].list);
@@ -3572,19 +3385,15 @@ yyreduce:
 	}
     break;
 
-  case 123:
-
-/* Line 1806 of yacc.c  */
-#line 873 "go.y"
+  case 126:
+#line 918 "go.y"
     {
 		(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
 	}
     break;
 
-  case 125:
-
-/* Line 1806 of yacc.c  */
-#line 878 "go.y"
+  case 128:
+#line 923 "go.y"
     {
 		if((yyvsp[(1) - (3)].node)->op == OPACK) {
 			Sym *s;
@@ -3597,57 +3406,45 @@ yyreduce:
 	}
     break;
 
-  case 126:
-
-/* Line 1806 of yacc.c  */
-#line 889 "go.y"
+  case 129:
+#line 934 "go.y"
     {
 		(yyval.node) = nod(ODOTTYPE, (yyvsp[(1) - (5)].node), (yyvsp[(4) - (5)].node));
 	}
     break;
 
-  case 127:
-
-/* Line 1806 of yacc.c  */
-#line 893 "go.y"
+  case 130:
+#line 938 "go.y"
     {
 		(yyval.node) = nod(OTYPESW, N, (yyvsp[(1) - (5)].node));
 	}
     break;
 
-  case 128:
-
-/* Line 1806 of yacc.c  */
-#line 897 "go.y"
+  case 131:
+#line 942 "go.y"
     {
 		(yyval.node) = nod(OINDEX, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
 	}
     break;
 
-  case 129:
-
-/* Line 1806 of yacc.c  */
-#line 901 "go.y"
+  case 132:
+#line 946 "go.y"
     {
 		(yyval.node) = nod(OSLICE, (yyvsp[(1) - (6)].node), nod(OKEY, (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node)));
 	}
     break;
 
-  case 131:
-
-/* Line 1806 of yacc.c  */
-#line 906 "go.y"
+  case 134:
+#line 951 "go.y"
     {
 		// conversion
-		(yyval.node) = nod(OCALL, (yyvsp[(1) - (4)].node), N);
-		(yyval.node)->list = list1((yyvsp[(3) - (4)].node));
+		(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
+		(yyval.node)->list = list1((yyvsp[(3) - (5)].node));
 	}
     break;
 
-  case 132:
-
-/* Line 1806 of yacc.c  */
-#line 912 "go.y"
+  case 135:
+#line 957 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (5)].node);
 		(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3656,10 +3453,8 @@ yyreduce:
 	}
     break;
 
-  case 133:
-
-/* Line 1806 of yacc.c  */
-#line 919 "go.y"
+  case 136:
+#line 964 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (5)].node);
 		(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3667,10 +3462,8 @@ yyreduce:
 	}
     break;
 
-  case 134:
-
-/* Line 1806 of yacc.c  */
-#line 925 "go.y"
+  case 137:
+#line 970 "go.y"
     {
 		yyerror("cannot parenthesize type in composite literal");
 		(yyval.node) = (yyvsp[(5) - (7)].node);
@@ -3679,10 +3472,8 @@ yyreduce:
 	}
     break;
 
-  case 136:
-
-/* Line 1806 of yacc.c  */
-#line 934 "go.y"
+  case 139:
+#line 979 "go.y"
     {
 		// composite expression.
 		// make node early so we get the right line number.
@@ -3690,29 +3481,51 @@ yyreduce:
 	}
     break;
 
-  case 137:
-
-/* Line 1806 of yacc.c  */
-#line 942 "go.y"
+  case 140:
+#line 987 "go.y"
     {
 		(yyval.node) = nod(OKEY, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 139:
+  case 141:
+#line 993 "go.y"
+    {
+		// These nodes do not carry line numbers.
+		// Since a composite literal commonly spans several lines,
+		// the line number on errors may be misleading.
+		// Introduce a wrapper node to give the correct line.
+		(yyval.node) = (yyvsp[(1) - (1)].node);
+		switch((yyval.node)->op) {
+		case ONAME:
+		case ONONAME:
+		case OTYPE:
+		case OPACK:
+		case OLITERAL:
+			(yyval.node) = nod(OPAREN, (yyval.node), N);
+			(yyval.node)->implicit = 1;
+		}
+	}
+    break;
 
-/* Line 1806 of yacc.c  */
-#line 949 "go.y"
+  case 142:
+#line 1010 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (4)].node);
 		(yyval.node)->list = (yyvsp[(3) - (4)].list);
 	}
     break;
 
-  case 141:
+  case 144:
+#line 1018 "go.y"
+    {
+		(yyval.node) = (yyvsp[(2) - (4)].node);
+		(yyval.node)->list = (yyvsp[(3) - (4)].list);
+	}
+    break;
 
-/* Line 1806 of yacc.c  */
-#line 957 "go.y"
+  case 146:
+#line 1026 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (3)].node);
 		
@@ -3725,33 +3538,28 @@ yyreduce:
 		case OPACK:
 		case OTYPE:
 		case OLITERAL:
+		case OTYPESW:
 			(yyval.node) = nod(OPAREN, (yyval.node), N);
 		}
 	}
     break;
 
-  case 145:
-
-/* Line 1806 of yacc.c  */
-#line 982 "go.y"
+  case 150:
+#line 1052 "go.y"
     {
 		(yyval.i) = LBODY;
 	}
     break;
 
-  case 146:
-
-/* Line 1806 of yacc.c  */
-#line 986 "go.y"
+  case 151:
+#line 1056 "go.y"
     {
 		(yyval.i) = '{';
 	}
     break;
 
-  case 147:
-
-/* Line 1806 of yacc.c  */
-#line 997 "go.y"
+  case 152:
+#line 1067 "go.y"
     {
 		if((yyvsp[(1) - (1)].sym) == S)
 			(yyval.node) = N;
@@ -3760,28 +3568,22 @@ yyreduce:
 	}
     break;
 
-  case 148:
-
-/* Line 1806 of yacc.c  */
-#line 1006 "go.y"
+  case 153:
+#line 1076 "go.y"
     {
 		(yyval.node) = dclname((yyvsp[(1) - (1)].sym));
 	}
     break;
 
-  case 149:
-
-/* Line 1806 of yacc.c  */
-#line 1011 "go.y"
+  case 154:
+#line 1081 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
-  case 151:
-
-/* Line 1806 of yacc.c  */
-#line 1018 "go.y"
+  case 156:
+#line 1088 "go.y"
     {
 		(yyval.sym) = (yyvsp[(1) - (1)].sym);
 		// during imports, unqualified non-exported identifiers are from builtinpkg
@@ -3790,31 +3592,31 @@ yyreduce:
 	}
     break;
 
-  case 153:
-
-/* Line 1806 of yacc.c  */
-#line 1026 "go.y"
+  case 158:
+#line 1096 "go.y"
     {
 		(yyval.sym) = S;
 	}
     break;
 
-  case 154:
-
-/* Line 1806 of yacc.c  */
-#line 1032 "go.y"
+  case 159:
+#line 1102 "go.y"
     {
+		Pkg *p;
+
 		if((yyvsp[(2) - (4)].val).u.sval->len == 0)
-			(yyval.sym) = pkglookup((yyvsp[(4) - (4)].sym)->name, importpkg);
-		else
-			(yyval.sym) = pkglookup((yyvsp[(4) - (4)].sym)->name, mkpkg((yyvsp[(2) - (4)].val).u.sval));
+			p = importpkg;
+		else {
+			if(isbadimport((yyvsp[(2) - (4)].val).u.sval))
+				errorexit();
+			p = mkpkg((yyvsp[(2) - (4)].val).u.sval);
+		}
+		(yyval.sym) = pkglookup((yyvsp[(4) - (4)].sym)->name, p);
 	}
     break;
 
-  case 155:
-
-/* Line 1806 of yacc.c  */
-#line 1041 "go.y"
+  case 160:
+#line 1117 "go.y"
     {
 		(yyval.node) = oldname((yyvsp[(1) - (1)].sym));
 		if((yyval.node)->pack != N)
@@ -3822,56 +3624,44 @@ yyreduce:
 	}
     break;
 
-  case 157:
-
-/* Line 1806 of yacc.c  */
-#line 1061 "go.y"
+  case 162:
+#line 1137 "go.y"
     {
 		yyerror("final argument in variadic function missing type");
 		(yyval.node) = nod(ODDD, typenod(typ(TINTER)), N);
 	}
     break;
 
-  case 158:
-
-/* Line 1806 of yacc.c  */
-#line 1066 "go.y"
+  case 163:
+#line 1142 "go.y"
     {
 		(yyval.node) = nod(ODDD, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 164:
-
-/* Line 1806 of yacc.c  */
-#line 1077 "go.y"
+  case 169:
+#line 1153 "go.y"
     {
 		(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
 	}
     break;
 
-  case 168:
-
-/* Line 1806 of yacc.c  */
-#line 1086 "go.y"
+  case 173:
+#line 1162 "go.y"
     {
 		(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 173:
-
-/* Line 1806 of yacc.c  */
-#line 1096 "go.y"
+  case 178:
+#line 1172 "go.y"
     {
 		(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
 	}
     break;
 
-  case 183:
-
-/* Line 1806 of yacc.c  */
-#line 1117 "go.y"
+  case 188:
+#line 1193 "go.y"
     {
 		if((yyvsp[(1) - (3)].node)->op == OPACK) {
 			Sym *s;
@@ -3884,77 +3674,61 @@ yyreduce:
 	}
     break;
 
-  case 184:
-
-/* Line 1806 of yacc.c  */
-#line 1130 "go.y"
+  case 189:
+#line 1206 "go.y"
     {
 		(yyval.node) = nod(OTARRAY, (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].node));
 	}
     break;
 
-  case 185:
-
-/* Line 1806 of yacc.c  */
-#line 1134 "go.y"
+  case 190:
+#line 1210 "go.y"
     {
 		// array literal of nelem
 		(yyval.node) = nod(OTARRAY, nod(ODDD, N, N), (yyvsp[(4) - (4)].node));
 	}
     break;
 
-  case 186:
-
-/* Line 1806 of yacc.c  */
-#line 1139 "go.y"
+  case 191:
+#line 1215 "go.y"
     {
 		(yyval.node) = nod(OTCHAN, (yyvsp[(2) - (2)].node), N);
 		(yyval.node)->etype = Cboth;
 	}
     break;
 
-  case 187:
-
-/* Line 1806 of yacc.c  */
-#line 1144 "go.y"
+  case 192:
+#line 1220 "go.y"
     {
 		(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
 		(yyval.node)->etype = Csend;
 	}
     break;
 
-  case 188:
-
-/* Line 1806 of yacc.c  */
-#line 1149 "go.y"
+  case 193:
+#line 1225 "go.y"
     {
 		(yyval.node) = nod(OTMAP, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
 	}
     break;
 
-  case 191:
-
-/* Line 1806 of yacc.c  */
-#line 1157 "go.y"
+  case 196:
+#line 1233 "go.y"
     {
 		(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 192:
-
-/* Line 1806 of yacc.c  */
-#line 1163 "go.y"
+  case 197:
+#line 1239 "go.y"
     {
 		(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
 		(yyval.node)->etype = Crecv;
 	}
     break;
 
-  case 193:
-
-/* Line 1806 of yacc.c  */
-#line 1170 "go.y"
+  case 198:
+#line 1246 "go.y"
     {
 		(yyval.node) = nod(OTSTRUCT, N, N);
 		(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3962,20 +3736,16 @@ yyreduce:
 	}
     break;
 
-  case 194:
-
-/* Line 1806 of yacc.c  */
-#line 1176 "go.y"
+  case 199:
+#line 1252 "go.y"
     {
 		(yyval.node) = nod(OTSTRUCT, N, N);
 		fixlbrace((yyvsp[(2) - (3)].i));
 	}
     break;
 
-  case 195:
-
-/* Line 1806 of yacc.c  */
-#line 1183 "go.y"
+  case 200:
+#line 1259 "go.y"
     {
 		(yyval.node) = nod(OTINTER, N, N);
 		(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3983,34 +3753,31 @@ yyreduce:
 	}
     break;
 
-  case 196:
-
-/* Line 1806 of yacc.c  */
-#line 1189 "go.y"
+  case 201:
+#line 1265 "go.y"
     {
 		(yyval.node) = nod(OTINTER, N, N);
 		fixlbrace((yyvsp[(2) - (3)].i));
 	}
     break;
 
-  case 197:
-
-/* Line 1806 of yacc.c  */
-#line 1200 "go.y"
+  case 202:
+#line 1276 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (3)].node);
 		if((yyval.node) == N)
 			break;
+		if(noescape && (yyvsp[(3) - (3)].list) != nil)
+			yyerror("can only use //go:noescape with external func implementations");
 		(yyval.node)->nbody = (yyvsp[(3) - (3)].list);
 		(yyval.node)->endlineno = lineno;
+		(yyval.node)->noescape = noescape;
 		funcbody((yyval.node));
 	}
     break;
 
-  case 198:
-
-/* Line 1806 of yacc.c  */
-#line 1211 "go.y"
+  case 203:
+#line 1290 "go.y"
     {
 		Node *t;
 
@@ -4041,10 +3808,8 @@ yyreduce:
 	}
     break;
 
-  case 199:
-
-/* Line 1806 of yacc.c  */
-#line 1240 "go.y"
+  case 204:
+#line 1319 "go.y"
     {
 		Node *rcvr, *t;
 
@@ -4077,16 +3842,15 @@ yyreduce:
 		(yyval.node)->nname = methodname1((yyval.node)->shortname, rcvr->right);
 		(yyval.node)->nname->defn = (yyval.node);
 		(yyval.node)->nname->ntype = t;
+		(yyval.node)->nname->nointerface = nointerface;
 		declare((yyval.node)->nname, PFUNC);
 
 		funchdr((yyval.node));
 	}
     break;
 
-  case 200:
-
-/* Line 1806 of yacc.c  */
-#line 1279 "go.y"
+  case 205:
+#line 1359 "go.y"
     {
 		Sym *s;
 		Type *t;
@@ -4098,8 +3862,10 @@ yyreduce:
 
 		importsym(s, ONAME);
 		if(s->def != N && s->def->op == ONAME) {
-			if(eqtype(t, s->def->type))
+			if(eqtype(t, s->def->type)) {
+				dclcontext = PDISCARD;  // since we skip funchdr below
 				break;
+			}
 			yyerror("inconsistent definition for func %S during import\n\t%T\n\t%T", s, s->def->type, t);
 		}
 
@@ -4111,16 +3877,15 @@ yyreduce:
 	}
     break;
 
-  case 201:
-
-/* Line 1806 of yacc.c  */
-#line 1302 "go.y"
+  case 206:
+#line 1384 "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));
 
 		checkwidth((yyval.node)->type);
-		addmethod((yyvsp[(4) - (8)].sym), (yyval.node)->type, 0);
+		addmethod((yyvsp[(4) - (8)].sym), (yyval.node)->type, 0, nointerface);
+		nointerface = 0;
 		funchdr((yyval.node));
 		
 		// inl.c's inlnode in on a dotmeth node expects to find the inlineable body as
@@ -4131,10 +3896,8 @@ yyreduce:
 	}
     break;
 
-  case 202:
-
-/* Line 1806 of yacc.c  */
-#line 1319 "go.y"
+  case 207:
+#line 1402 "go.y"
     {
 		(yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1);
 		(yyval.node) = nod(OTFUNC, N, N);
@@ -4143,19 +3906,15 @@ yyreduce:
 	}
     break;
 
-  case 203:
-
-/* Line 1806 of yacc.c  */
-#line 1327 "go.y"
+  case 208:
+#line 1410 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
-  case 204:
-
-/* Line 1806 of yacc.c  */
-#line 1331 "go.y"
+  case 209:
+#line 1414 "go.y"
     {
 		(yyval.list) = (yyvsp[(2) - (3)].list);
 		if((yyval.list) == nil)
@@ -4163,149 +3922,119 @@ yyreduce:
 	}
     break;
 
-  case 205:
-
-/* Line 1806 of yacc.c  */
-#line 1339 "go.y"
+  case 210:
+#line 1422 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
-  case 206:
-
-/* Line 1806 of yacc.c  */
-#line 1343 "go.y"
+  case 211:
+#line 1426 "go.y"
     {
 		(yyval.list) = list1(nod(ODCLFIELD, N, (yyvsp[(1) - (1)].node)));
 	}
     break;
 
-  case 207:
-
-/* Line 1806 of yacc.c  */
-#line 1347 "go.y"
+  case 212:
+#line 1430 "go.y"
     {
 		(yyvsp[(2) - (3)].list) = checkarglist((yyvsp[(2) - (3)].list), 0);
 		(yyval.list) = (yyvsp[(2) - (3)].list);
 	}
     break;
 
-  case 208:
-
-/* Line 1806 of yacc.c  */
-#line 1354 "go.y"
+  case 213:
+#line 1437 "go.y"
     {
 		closurehdr((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 209:
-
-/* Line 1806 of yacc.c  */
-#line 1360 "go.y"
+  case 214:
+#line 1443 "go.y"
     {
 		(yyval.node) = closurebody((yyvsp[(3) - (4)].list));
 		fixlbrace((yyvsp[(2) - (4)].i));
 	}
     break;
 
-  case 210:
-
-/* Line 1806 of yacc.c  */
-#line 1365 "go.y"
+  case 215:
+#line 1448 "go.y"
     {
 		(yyval.node) = closurebody(nil);
 	}
     break;
 
-  case 211:
-
-/* Line 1806 of yacc.c  */
-#line 1376 "go.y"
+  case 216:
+#line 1459 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
-  case 212:
-
-/* Line 1806 of yacc.c  */
-#line 1380 "go.y"
+  case 217:
+#line 1463 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].list));
 		if(nsyntaxerrors == 0)
 			testdclstack();
+		nointerface = 0;
+		noescape = 0;
 	}
     break;
 
-  case 214:
-
-/* Line 1806 of yacc.c  */
-#line 1389 "go.y"
+  case 219:
+#line 1474 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
 	}
     break;
 
-  case 216:
-
-/* Line 1806 of yacc.c  */
-#line 1396 "go.y"
+  case 221:
+#line 1481 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
 	}
     break;
 
-  case 217:
-
-/* Line 1806 of yacc.c  */
-#line 1402 "go.y"
+  case 222:
+#line 1487 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 218:
-
-/* Line 1806 of yacc.c  */
-#line 1406 "go.y"
+  case 223:
+#line 1491 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 220:
-
-/* Line 1806 of yacc.c  */
-#line 1413 "go.y"
+  case 225:
+#line 1498 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
 	}
     break;
 
-  case 221:
-
-/* Line 1806 of yacc.c  */
-#line 1419 "go.y"
+  case 226:
+#line 1504 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 222:
-
-/* Line 1806 of yacc.c  */
-#line 1423 "go.y"
+  case 227:
+#line 1508 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 223:
-
-/* Line 1806 of yacc.c  */
-#line 1429 "go.y"
+  case 228:
+#line 1514 "go.y"
     {
 		NodeList *l;
 
@@ -4330,20 +4059,16 @@ yyreduce:
 	}
     break;
 
-  case 224:
-
-/* Line 1806 of yacc.c  */
-#line 1452 "go.y"
+  case 229:
+#line 1537 "go.y"
     {
 		(yyvsp[(1) - (2)].node)->val = (yyvsp[(2) - (2)].val);
 		(yyval.list) = list1((yyvsp[(1) - (2)].node));
 	}
     break;
 
-  case 225:
-
-/* Line 1806 of yacc.c  */
-#line 1457 "go.y"
+  case 230:
+#line 1542 "go.y"
     {
 		(yyvsp[(2) - (4)].node)->val = (yyvsp[(4) - (4)].val);
 		(yyval.list) = list1((yyvsp[(2) - (4)].node));
@@ -4351,10 +4076,8 @@ yyreduce:
 	}
     break;
 
-  case 226:
-
-/* Line 1806 of yacc.c  */
-#line 1463 "go.y"
+  case 231:
+#line 1548 "go.y"
     {
 		(yyvsp[(2) - (3)].node)->right = nod(OIND, (yyvsp[(2) - (3)].node)->right, N);
 		(yyvsp[(2) - (3)].node)->val = (yyvsp[(3) - (3)].val);
@@ -4362,10 +4085,8 @@ yyreduce:
 	}
     break;
 
-  case 227:
-
-/* Line 1806 of yacc.c  */
-#line 1469 "go.y"
+  case 232:
+#line 1554 "go.y"
     {
 		(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
 		(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4374,10 +4095,8 @@ yyreduce:
 	}
     break;
 
-  case 228:
-
-/* Line 1806 of yacc.c  */
-#line 1476 "go.y"
+  case 233:
+#line 1561 "go.y"
     {
 		(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
 		(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4386,10 +4105,8 @@ yyreduce:
 	}
     break;
 
-  case 229:
-
-/* Line 1806 of yacc.c  */
-#line 1485 "go.y"
+  case 234:
+#line 1570 "go.y"
     {
 		Node *n;
 
@@ -4400,10 +4117,8 @@ yyreduce:
 	}
     break;
 
-  case 230:
-
-/* Line 1806 of yacc.c  */
-#line 1494 "go.y"
+  case 235:
+#line 1579 "go.y"
     {
 		Pkg *pkg;
 
@@ -4418,48 +4133,38 @@ yyreduce:
 	}
     break;
 
-  case 231:
-
-/* Line 1806 of yacc.c  */
-#line 1509 "go.y"
+  case 236:
+#line 1594 "go.y"
     {
 		(yyval.node) = embedded((yyvsp[(1) - (1)].sym));
 	}
     break;
 
-  case 232:
-
-/* Line 1806 of yacc.c  */
-#line 1515 "go.y"
+  case 237:
+#line 1600 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
 		ifacedcl((yyval.node));
 	}
     break;
 
-  case 233:
-
-/* Line 1806 of yacc.c  */
-#line 1520 "go.y"
+  case 238:
+#line 1605 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(1) - (1)].sym)));
 	}
     break;
 
-  case 234:
-
-/* Line 1806 of yacc.c  */
-#line 1524 "go.y"
+  case 239:
+#line 1609 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(2) - (3)].sym)));
 		yyerror("cannot parenthesize embedded type");
 	}
     break;
 
-  case 235:
-
-/* Line 1806 of yacc.c  */
-#line 1531 "go.y"
+  case 240:
+#line 1616 "go.y"
     {
 		// without func keyword
 		(yyvsp[(2) - (4)].list) = checkarglist((yyvsp[(2) - (4)].list), 1);
@@ -4469,10 +4174,8 @@ yyreduce:
 	}
     break;
 
-  case 237:
-
-/* Line 1806 of yacc.c  */
-#line 1545 "go.y"
+  case 242:
+#line 1630 "go.y"
     {
 		(yyval.node) = nod(ONONAME, N, N);
 		(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4480,10 +4183,8 @@ yyreduce:
 	}
     break;
 
-  case 238:
-
-/* Line 1806 of yacc.c  */
-#line 1551 "go.y"
+  case 243:
+#line 1636 "go.y"
     {
 		(yyval.node) = nod(ONONAME, N, N);
 		(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4491,83 +4192,65 @@ yyreduce:
 	}
     break;
 
-  case 240:
-
-/* Line 1806 of yacc.c  */
-#line 1560 "go.y"
+  case 245:
+#line 1645 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 241:
-
-/* Line 1806 of yacc.c  */
-#line 1564 "go.y"
+  case 246:
+#line 1649 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 242:
-
-/* Line 1806 of yacc.c  */
-#line 1569 "go.y"
+  case 247:
+#line 1654 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
-  case 243:
-
-/* Line 1806 of yacc.c  */
-#line 1573 "go.y"
+  case 248:
+#line 1658 "go.y"
     {
 		(yyval.list) = (yyvsp[(1) - (2)].list);
 	}
     break;
 
-  case 244:
-
-/* Line 1806 of yacc.c  */
-#line 1581 "go.y"
+  case 249:
+#line 1666 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
-  case 246:
-
-/* Line 1806 of yacc.c  */
-#line 1586 "go.y"
+  case 251:
+#line 1671 "go.y"
     {
 		(yyval.node) = liststmt((yyvsp[(1) - (1)].list));
 	}
     break;
 
-  case 248:
-
-/* Line 1806 of yacc.c  */
-#line 1591 "go.y"
+  case 253:
+#line 1676 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
-  case 254:
-
-/* Line 1806 of yacc.c  */
-#line 1602 "go.y"
+  case 259:
+#line 1687 "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 255:
-
-/* Line 1806 of yacc.c  */
-#line 1607 "go.y"
+  case 260:
+#line 1692 "go.y"
     {
 		NodeList *l;
 
@@ -4579,66 +4262,52 @@ yyreduce:
 	}
     break;
 
-  case 256:
-
-/* Line 1806 of yacc.c  */
-#line 1617 "go.y"
+  case 261:
+#line 1702 "go.y"
     {
 		// will be converted to OFALL
 		(yyval.node) = nod(OXFALL, N, N);
 	}
     break;
 
-  case 257:
-
-/* Line 1806 of yacc.c  */
-#line 1622 "go.y"
+  case 262:
+#line 1707 "go.y"
     {
 		(yyval.node) = nod(OBREAK, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 258:
-
-/* Line 1806 of yacc.c  */
-#line 1626 "go.y"
+  case 263:
+#line 1711 "go.y"
     {
 		(yyval.node) = nod(OCONTINUE, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 259:
-
-/* Line 1806 of yacc.c  */
-#line 1630 "go.y"
+  case 264:
+#line 1715 "go.y"
     {
 		(yyval.node) = nod(OPROC, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 260:
-
-/* Line 1806 of yacc.c  */
-#line 1634 "go.y"
+  case 265:
+#line 1719 "go.y"
     {
 		(yyval.node) = nod(ODEFER, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
-  case 261:
-
-/* Line 1806 of yacc.c  */
-#line 1638 "go.y"
+  case 266:
+#line 1723 "go.y"
     {
 		(yyval.node) = nod(OGOTO, (yyvsp[(2) - (2)].node), N);
 		(yyval.node)->sym = dclstack;  // context, for goto restrictions
 	}
     break;
 
-  case 262:
-
-/* Line 1806 of yacc.c  */
-#line 1643 "go.y"
+  case 267:
+#line 1728 "go.y"
     {
 		(yyval.node) = nod(ORETURN, N, N);
 		(yyval.node)->list = (yyvsp[(2) - (2)].list);
@@ -4657,10 +4326,8 @@ yyreduce:
 	}
     break;
 
-  case 263:
-
-/* Line 1806 of yacc.c  */
-#line 1662 "go.y"
+  case 268:
+#line 1747 "go.y"
     {
 		(yyval.list) = nil;
 		if((yyvsp[(1) - (1)].node) != N)
@@ -4668,10 +4335,8 @@ yyreduce:
 	}
     break;
 
-  case 264:
-
-/* Line 1806 of yacc.c  */
-#line 1668 "go.y"
+  case 269:
+#line 1753 "go.y"
     {
 		(yyval.list) = (yyvsp[(1) - (3)].list);
 		if((yyvsp[(3) - (3)].node) != N)
@@ -4679,247 +4344,195 @@ yyreduce:
 	}
     break;
 
-  case 265:
-
-/* Line 1806 of yacc.c  */
-#line 1676 "go.y"
+  case 270:
+#line 1761 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 266:
-
-/* Line 1806 of yacc.c  */
-#line 1680 "go.y"
+  case 271:
+#line 1765 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 267:
-
-/* Line 1806 of yacc.c  */
-#line 1686 "go.y"
+  case 272:
+#line 1771 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 268:
-
-/* Line 1806 of yacc.c  */
-#line 1690 "go.y"
+  case 273:
+#line 1775 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 269:
-
-/* Line 1806 of yacc.c  */
-#line 1696 "go.y"
+  case 274:
+#line 1781 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 270:
-
-/* Line 1806 of yacc.c  */
-#line 1700 "go.y"
+  case 275:
+#line 1785 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 271:
-
-/* Line 1806 of yacc.c  */
-#line 1706 "go.y"
+  case 276:
+#line 1791 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 272:
-
-/* Line 1806 of yacc.c  */
-#line 1710 "go.y"
+  case 277:
+#line 1795 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 273:
-
-/* Line 1806 of yacc.c  */
-#line 1719 "go.y"
+  case 278:
+#line 1804 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 274:
-
-/* Line 1806 of yacc.c  */
-#line 1723 "go.y"
+  case 279:
+#line 1808 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 275:
-
-/* Line 1806 of yacc.c  */
-#line 1727 "go.y"
+  case 280:
+#line 1812 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 276:
-
-/* Line 1806 of yacc.c  */
-#line 1731 "go.y"
+  case 281:
+#line 1816 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 277:
-
-/* Line 1806 of yacc.c  */
-#line 1736 "go.y"
+  case 282:
+#line 1821 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
-  case 278:
-
-/* Line 1806 of yacc.c  */
-#line 1740 "go.y"
+  case 283:
+#line 1825 "go.y"
     {
 		(yyval.list) = (yyvsp[(1) - (2)].list);
 	}
     break;
 
-  case 283:
-
-/* Line 1806 of yacc.c  */
-#line 1754 "go.y"
+  case 288:
+#line 1839 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
-  case 285:
-
-/* Line 1806 of yacc.c  */
-#line 1760 "go.y"
+  case 290:
+#line 1845 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
-  case 287:
-
-/* Line 1806 of yacc.c  */
-#line 1766 "go.y"
+  case 292:
+#line 1851 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
-  case 289:
-
-/* Line 1806 of yacc.c  */
-#line 1772 "go.y"
+  case 294:
+#line 1857 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
-  case 291:
-
-/* Line 1806 of yacc.c  */
-#line 1778 "go.y"
+  case 296:
+#line 1863 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
-  case 293:
-
-/* Line 1806 of yacc.c  */
-#line 1784 "go.y"
+  case 298:
+#line 1869 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
-  case 295:
-
-/* Line 1806 of yacc.c  */
-#line 1790 "go.y"
+  case 300:
+#line 1875 "go.y"
     {
 		(yyval.val).ctype = CTxxx;
 	}
     break;
 
-  case 297:
-
-/* Line 1806 of yacc.c  */
-#line 1800 "go.y"
+  case 302:
+#line 1885 "go.y"
     {
 		importimport((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].val).u.sval);
 	}
     break;
 
-  case 298:
-
-/* Line 1806 of yacc.c  */
-#line 1804 "go.y"
+  case 303:
+#line 1889 "go.y"
     {
 		importvar((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].type));
 	}
     break;
 
-  case 299:
-
-/* Line 1806 of yacc.c  */
-#line 1808 "go.y"
+  case 304:
+#line 1893 "go.y"
     {
 		importconst((yyvsp[(2) - (5)].sym), types[TIDEAL], (yyvsp[(4) - (5)].node));
 	}
     break;
 
-  case 300:
-
-/* Line 1806 of yacc.c  */
-#line 1812 "go.y"
+  case 305:
+#line 1897 "go.y"
     {
 		importconst((yyvsp[(2) - (6)].sym), (yyvsp[(3) - (6)].type), (yyvsp[(5) - (6)].node));
 	}
     break;
 
-  case 301:
-
-/* Line 1806 of yacc.c  */
-#line 1816 "go.y"
+  case 306:
+#line 1901 "go.y"
     {
 		importtype((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].type));
 	}
     break;
 
-  case 302:
-
-/* Line 1806 of yacc.c  */
-#line 1820 "go.y"
+  case 307:
+#line 1905 "go.y"
     {
-		if((yyvsp[(2) - (4)].node) == N)
+		if((yyvsp[(2) - (4)].node) == N) {
+			dclcontext = PEXTERN;  // since we skip the funcbody below
 			break;
+		}
 
 		(yyvsp[(2) - (4)].node)->inl = (yyvsp[(3) - (4)].list);
 
@@ -4928,45 +4541,37 @@ yyreduce:
 
 		if(debug['E']) {
 			print("import [%Z] func %lN \n", importpkg->path, (yyvsp[(2) - (4)].node));
-			if(debug['l'] > 2 && (yyvsp[(2) - (4)].node)->inl)
+			if(debug['m'] > 2 && (yyvsp[(2) - (4)].node)->inl)
 				print("inl body:%+H\n", (yyvsp[(2) - (4)].node)->inl);
 		}
 	}
     break;
 
-  case 303:
-
-/* Line 1806 of yacc.c  */
-#line 1838 "go.y"
+  case 308:
+#line 1925 "go.y"
     {
 		(yyval.sym) = (yyvsp[(1) - (1)].sym);
 		structpkg = (yyval.sym)->pkg;
 	}
     break;
 
-  case 304:
-
-/* Line 1806 of yacc.c  */
-#line 1845 "go.y"
+  case 309:
+#line 1932 "go.y"
     {
 		(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
 		importsym((yyvsp[(1) - (1)].sym), OTYPE);
 	}
     break;
 
-  case 310:
-
-/* Line 1806 of yacc.c  */
-#line 1865 "go.y"
+  case 315:
+#line 1952 "go.y"
     {
 		(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
 	}
     break;
 
-  case 311:
-
-/* Line 1806 of yacc.c  */
-#line 1869 "go.y"
+  case 316:
+#line 1956 "go.y"
     {
 		// predefined name like uint8
 		(yyvsp[(1) - (1)].sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg);
@@ -4978,64 +4583,50 @@ yyreduce:
 	}
     break;
 
-  case 312:
-
-/* Line 1806 of yacc.c  */
-#line 1879 "go.y"
+  case 317:
+#line 1966 "go.y"
     {
 		(yyval.type) = aindex(N, (yyvsp[(3) - (3)].type));
 	}
     break;
 
-  case 313:
-
-/* Line 1806 of yacc.c  */
-#line 1883 "go.y"
+  case 318:
+#line 1970 "go.y"
     {
 		(yyval.type) = aindex(nodlit((yyvsp[(2) - (4)].val)), (yyvsp[(4) - (4)].type));
 	}
     break;
 
-  case 314:
-
-/* Line 1806 of yacc.c  */
-#line 1887 "go.y"
+  case 319:
+#line 1974 "go.y"
     {
 		(yyval.type) = maptype((yyvsp[(3) - (5)].type), (yyvsp[(5) - (5)].type));
 	}
     break;
 
-  case 315:
-
-/* Line 1806 of yacc.c  */
-#line 1891 "go.y"
+  case 320:
+#line 1978 "go.y"
     {
 		(yyval.type) = tostruct((yyvsp[(3) - (4)].list));
 	}
     break;
 
-  case 316:
-
-/* Line 1806 of yacc.c  */
-#line 1895 "go.y"
+  case 321:
+#line 1982 "go.y"
     {
 		(yyval.type) = tointerface((yyvsp[(3) - (4)].list));
 	}
     break;
 
-  case 317:
-
-/* Line 1806 of yacc.c  */
-#line 1899 "go.y"
+  case 322:
+#line 1986 "go.y"
     {
 		(yyval.type) = ptrto((yyvsp[(2) - (2)].type));
 	}
     break;
 
-  case 318:
-
-/* Line 1806 of yacc.c  */
-#line 1903 "go.y"
+  case 323:
+#line 1990 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(2) - (2)].type);
@@ -5043,10 +4634,8 @@ yyreduce:
 	}
     break;
 
-  case 319:
-
-/* Line 1806 of yacc.c  */
-#line 1909 "go.y"
+  case 324:
+#line 1996 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(3) - (4)].type);
@@ -5054,10 +4643,8 @@ yyreduce:
 	}
     break;
 
-  case 320:
-
-/* Line 1806 of yacc.c  */
-#line 1915 "go.y"
+  case 325:
+#line 2002 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -5065,10 +4652,8 @@ yyreduce:
 	}
     break;
 
-  case 321:
-
-/* Line 1806 of yacc.c  */
-#line 1923 "go.y"
+  case 326:
+#line 2010 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -5076,19 +4661,15 @@ yyreduce:
 	}
     break;
 
-  case 322:
-
-/* Line 1806 of yacc.c  */
-#line 1931 "go.y"
+  case 327:
+#line 2018 "go.y"
     {
 		(yyval.type) = functype(nil, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list));
 	}
     break;
 
-  case 323:
-
-/* Line 1806 of yacc.c  */
-#line 1937 "go.y"
+  case 328:
+#line 2024 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(2) - (3)].type)));
 		if((yyvsp[(1) - (3)].sym))
@@ -5097,10 +4678,8 @@ yyreduce:
 	}
     break;
 
-  case 324:
-
-/* Line 1806 of yacc.c  */
-#line 1944 "go.y"
+  case 329:
+#line 2031 "go.y"
     {
 		Type *t;
 	
@@ -5116,10 +4695,8 @@ yyreduce:
 	}
     break;
 
-  case 325:
-
-/* Line 1806 of yacc.c  */
-#line 1960 "go.y"
+  case 330:
+#line 2047 "go.y"
     {
 		Sym *s;
 
@@ -5137,64 +4714,50 @@ yyreduce:
 	}
     break;
 
-  case 326:
-
-/* Line 1806 of yacc.c  */
-#line 1978 "go.y"
+  case 331:
+#line 2065 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, newname((yyvsp[(1) - (5)].sym)), typenod(functype(fakethis(), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list))));
 	}
     break;
 
-  case 327:
-
-/* Line 1806 of yacc.c  */
-#line 1982 "go.y"
+  case 332:
+#line 2069 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type)));
 	}
     break;
 
-  case 328:
-
-/* Line 1806 of yacc.c  */
-#line 1987 "go.y"
+  case 333:
+#line 2074 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
-  case 330:
-
-/* Line 1806 of yacc.c  */
-#line 1994 "go.y"
+  case 335:
+#line 2081 "go.y"
     {
 		(yyval.list) = (yyvsp[(2) - (3)].list);
 	}
     break;
 
-  case 331:
-
-/* Line 1806 of yacc.c  */
-#line 1998 "go.y"
+  case 336:
+#line 2085 "go.y"
     {
 		(yyval.list) = list1(nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type))));
 	}
     break;
 
-  case 332:
-
-/* Line 1806 of yacc.c  */
-#line 2008 "go.y"
+  case 337:
+#line 2095 "go.y"
     {
 		(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
 	}
     break;
 
-  case 333:
-
-/* Line 1806 of yacc.c  */
-#line 2012 "go.y"
+  case 338:
+#line 2099 "go.y"
     {
 		(yyval.node) = nodlit((yyvsp[(2) - (2)].val));
 		switch((yyval.node)->val.ctype){
@@ -5211,10 +4774,8 @@ yyreduce:
 	}
     break;
 
-  case 334:
-
-/* Line 1806 of yacc.c  */
-#line 2027 "go.y"
+  case 339:
+#line 2114 "go.y"
     {
 		(yyval.node) = oldname(pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg));
 		if((yyval.node)->op != OLITERAL)
@@ -5222,91 +4783,67 @@ yyreduce:
 	}
     break;
 
-  case 336:
-
-/* Line 1806 of yacc.c  */
-#line 2036 "go.y"
+  case 341:
+#line 2123 "go.y"
     {
 		if((yyvsp[(2) - (5)].node)->val.ctype == CTRUNE && (yyvsp[(4) - (5)].node)->val.ctype == CTINT) {
 			(yyval.node) = (yyvsp[(2) - (5)].node);
 			mpaddfixfix((yyvsp[(2) - (5)].node)->val.u.xval, (yyvsp[(4) - (5)].node)->val.u.xval, 0);
 			break;
 		}
+		(yyvsp[(4) - (5)].node)->val.u.cval->real = (yyvsp[(4) - (5)].node)->val.u.cval->imag;
+		mpmovecflt(&(yyvsp[(4) - (5)].node)->val.u.cval->imag, 0.0);
 		(yyval.node) = nodcplxlit((yyvsp[(2) - (5)].node)->val, (yyvsp[(4) - (5)].node)->val);
 	}
     break;
 
-  case 339:
-
-/* Line 1806 of yacc.c  */
-#line 2050 "go.y"
+  case 344:
+#line 2139 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 340:
-
-/* Line 1806 of yacc.c  */
-#line 2054 "go.y"
+  case 345:
+#line 2143 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 341:
-
-/* Line 1806 of yacc.c  */
-#line 2060 "go.y"
+  case 346:
+#line 2149 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 342:
-
-/* Line 1806 of yacc.c  */
-#line 2064 "go.y"
+  case 347:
+#line 2153 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
-  case 343:
-
-/* Line 1806 of yacc.c  */
-#line 2070 "go.y"
+  case 348:
+#line 2159 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
-  case 344:
-
-/* Line 1806 of yacc.c  */
-#line 2074 "go.y"
+  case 349:
+#line 2163 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
 
-
-/* Line 1806 of yacc.c  */
-#line 5298 "y.tab.c"
+/* Line 1267 of yacc.c.  */
+#line 4846 "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);
@@ -5315,6 +4852,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.  */
@@ -5334,10 +4872,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)
     {
@@ -5345,36 +4879,37 @@ yyerrlab:
 #if ! YYERROR_VERBOSE
       yyerror (YY_("syntax error"));
 #else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
-                                        yyssp, yytoken)
       {
-        char *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
     }
 
@@ -5382,7 +4917,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)
@@ -5399,7 +4934,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;
 
@@ -5433,7 +4968,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)
@@ -5456,6 +4991,9 @@ yyerrlab1:
       YY_STACK_PRINT (yyss, yyssp);
     }
 
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
   *++yyvsp = yylval;
 
 
@@ -5480,7 +5018,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#if !defined(yyoverflow) || YYERROR_VERBOSE
+#ifndef yyoverflow
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -5491,14 +5029,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);
@@ -5522,9 +5055,7 @@ yyreturn:
 }
 
 
-
-/* Line 2067 of yacc.c  */
-#line 2078 "go.y"
+#line 2167 "go.y"
 
 
 static void
diff --git a/src/cmd/gc/y.tab.h b/src/cmd/gc/y.tab.h
index bc6c47d..d01fbe1 100644
--- a/src/cmd/gc/y.tab.h
+++ b/src/cmd/gc/y.tab.h
@@ -1,21 +1,24 @@
-/* A Bison parser, made by GNU Bison 2.5.  */
+/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Bison interface for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2011 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,11 +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.  */
 
-
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
@@ -39,10 +41,10 @@
    enum yytokentype {
      LLITERAL = 258,
      LASOP = 259,
-     LBREAK = 260,
-     LCASE = 261,
-     LCHAN = 262,
-     LCOLAS = 263,
+     LCOLAS = 260,
+     LBREAK = 261,
+     LCASE = 262,
+     LCHAN = 263,
      LCONST = 264,
      LCONTINUE = 265,
      LDDD = 266,
@@ -91,10 +93,10 @@
 /* Tokens.  */
 #define LLITERAL 258
 #define LASOP 259
-#define LBREAK 260
-#define LCASE 261
-#define LCHAN 262
-#define LCOLAS 263
+#define LCOLAS 260
+#define LBREAK 261
+#define LCASE 262
+#define LCHAN 263
 #define LCONST 264
 #define LCONTINUE 265
 #define LDDD 266
@@ -144,28 +146,22 @@
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-{
-
-/* Line 2068 of yacc.c  */
 #line 28 "go.y"
-
+{
 	Node*		node;
 	NodeList*		list;
 	Type*		type;
 	Sym*		sym;
 	struct	Val	val;
 	int		i;
-
-
-
-/* Line 2068 of yacc.c  */
-#line 163 "y.tab.h"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
+}
+/* Line 1529 of yacc.c.  */
+#line 160 "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;
 
-
diff --git a/src/cmd/gc/yerr.h b/src/cmd/gc/yerr.h
index 588890d..e7eb651 100644
--- a/src/cmd/gc/yerr.h
+++ b/src/cmd/gc/yerr.h
@@ -26,7 +26,7 @@ static struct {
 	237, ';',
 	"unexpected semicolon or newline before {",
 
-	474, LBODY,
+	475, LBODY,
 	"unexpected semicolon or newline before {",
 
 	22, '{',
@@ -44,7 +44,7 @@ static struct {
 	37, ',',
 	"unexpected comma in channel type",
 
-	437, LELSE,
+	438, LELSE,
 	"unexpected semicolon or newline before else",
 
 	257, ',',
@@ -65,9 +65,12 @@ static struct {
 	425, ';',
 	"need trailing comma before newline in composite literal",
 	
+	436, ';',
+	"need trailing comma before newline in composite literal",
+	
 	112, LNAME,
 	"nested func not allowed",
 
-	615, ';',
+	642, ';',
 	"else must be followed by if or statement block"
 };
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 767ddfd..38fc43e 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -8,6 +8,7 @@ import (
 	"bytes"
 	"container/heap"
 	"errors"
+	"flag"
 	"fmt"
 	"go/build"
 	"io"
@@ -59,7 +60,12 @@ The build flags are shared by the build, install, run, and test commands:
 		do not delete it when exiting.
 	-x
 		print the commands.
+	-race
+		enable data race detection.
+		Supported only on linux/amd64, darwin/amd64 and windows/amd64.
 
+	-ccflags 'arg list'
+		arguments to pass on each 5c, 6c, or 8c compiler invocation
 	-compiler name
 		name of compiler to use, as in runtime.Compiler (gccgo or gc)
 	-gccgoflags 'arg list'
@@ -73,6 +79,9 @@ The build flags are shared by the build, install, run, and test commands:
 		See the documentation for the go/build package for
 		more information about build tags.
 
+The list flags accept a space-separated list of strings. To embed spaces
+in an element in the list, surround it with either single or double quotes.
+
 For more about specifying packages, see 'go help packages'.
 For more about where packages and binaries are installed,
 see 'go help gopath'.
@@ -99,8 +108,10 @@ var buildX bool               // -x flag
 var buildO = cmdBuild.Flag.String("o", "", "output file")
 var buildWork bool           // -work flag
 var buildGcflags []string    // -gcflags flag
+var buildCcflags []string    // -ccflags flag
 var buildLdflags []string    // -ldflags flag
 var buildGccgoflags []string // -gccgoflags flag
+var buildRace bool           // -race flag
 
 var buildContext = build.Default
 var buildToolchain toolchain = noToolchain{}
@@ -115,7 +126,7 @@ func (c buildCompiler) Set(value string) error {
 	case "gc":
 		buildToolchain = gcToolchain{}
 	case "gccgo":
-		buildToolchain = gccgcToolchain{}
+		buildToolchain = gccgoToolchain{}
 	default:
 		return fmt.Errorf("unknown compiler %q", value)
 	}
@@ -132,7 +143,7 @@ func init() {
 	case "gc":
 		buildToolchain = gcToolchain{}
 	case "gccgo":
-		buildToolchain = gccgcToolchain{}
+		buildToolchain = gccgoToolchain{}
 	}
 }
 
@@ -146,10 +157,12 @@ func addBuildFlags(cmd *Command) {
 	cmd.Flag.BoolVar(&buildX, "x", false, "")
 	cmd.Flag.BoolVar(&buildWork, "work", false, "")
 	cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "")
+	cmd.Flag.Var((*stringsFlag)(&buildCcflags), "ccflags", "")
 	cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "")
 	cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "")
 	cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
 	cmd.Flag.Var(buildCompiler{}, "compiler", "")
+	cmd.Flag.BoolVar(&buildRace, "race", false, "")
 }
 
 func addBuildFlagsNX(cmd *Command) {
@@ -157,11 +170,52 @@ func addBuildFlagsNX(cmd *Command) {
 	cmd.Flag.BoolVar(&buildX, "x", false, "")
 }
 
+func isSpaceByte(c byte) bool {
+	return c == ' ' || c == '\t' || c == '\n' || c == '\r'
+}
+
 type stringsFlag []string
 
 func (v *stringsFlag) Set(s string) error {
-	*v = strings.Fields(s)
-	return nil
+	var err error
+	*v, err = splitQuotedFields(s)
+	return err
+}
+
+func splitQuotedFields(s string) ([]string, error) {
+	// Split fields allowing '' or "" around elements.
+	// Quotes further inside the string do not count.
+	var f []string
+	for len(s) > 0 {
+		for len(s) > 0 && isSpaceByte(s[0]) {
+			s = s[1:]
+		}
+		if len(s) == 0 {
+			break
+		}
+		// Accepted quoted string. No unescaping inside.
+		if s[0] == '"' || s[0] == '\'' {
+			quote := s[0]
+			s = s[1:]
+			i := 0
+			for i < len(s) && s[i] != quote {
+				i++
+			}
+			if i >= len(s) {
+				return nil, fmt.Errorf("unterminated %c string", quote)
+			}
+			f = append(f, s[:i])
+			s = s[i+1:]
+			continue
+		}
+		i := 0
+		for i < len(s) && !isSpaceByte(s[i]) {
+			i++
+		}
+		f = append(f, s[:i])
+		s = s[i:]
+	}
+	return f, nil
 }
 
 func (v *stringsFlag) String() string {
@@ -169,6 +223,7 @@ func (v *stringsFlag) String() string {
 }
 
 func runBuild(cmd *Command, args []string) {
+	raceInit()
 	var b builder
 	b.init()
 
@@ -179,6 +234,21 @@ func runBuild(cmd *Command, args []string) {
 		*buildO += exeSuffix
 	}
 
+	// sanity check some often mis-used options
+	switch buildContext.Compiler {
+	case "gccgo":
+		if len(buildGcflags) != 0 {
+			fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
+		}
+		if len(buildLdflags) != 0 {
+			fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
+		}
+	case "gc":
+		if len(buildGccgoflags) != 0 {
+			fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags")
+		}
+	}
+
 	if *buildO != "" {
 		if len(pkgs) > 1 {
 			fatalf("go build: cannot use -o with multiple packages")
@@ -213,11 +283,12 @@ See also: go build, go get, go clean.
 }
 
 func runInstall(cmd *Command, args []string) {
+	raceInit()
 	pkgs := packagesForBuild(args)
 
 	for _, p := range pkgs {
 		if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") {
-			errorf("go install: no install location for %s", p.ImportPath)
+			errorf("go install: no install location for directory %s outside GOPATH", p.Dir)
 		}
 	}
 	exitIfErrors()
@@ -437,7 +508,7 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
 	// using cgo, to make sure we do not overwrite the binary while
 	// a package is using it.  If this is a cross-build, then the cgo we
 	// are writing is not the cgo we need to use.
-	if goos == runtime.GOOS && goarch == runtime.GOARCH {
+	if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
 		if len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo" {
 			var stk importStack
 			p1 := loadPackage("cmd/cgo", &stk)
@@ -456,7 +527,7 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
 			return a
 		}
 		// gccgo standard library is "fake" too.
-		if _, ok := buildToolchain.(gccgcToolchain); ok {
+		if _, ok := buildToolchain.(gccgoToolchain); ok {
 			// the target name is needed for cgo.
 			a.target = p.target
 			return a
@@ -487,9 +558,18 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
 		a.f = (*builder).build
 		a.target = a.objpkg
 		if a.link {
-			// An executable file.
-			// (This is the name of a temporary file.)
-			a.target = a.objdir + "a.out" + exeSuffix
+			// An executable file. (This is the name of a temporary file.)
+			// Because we run the temporary file in 'go run' and 'go test',
+			// the name will show up in ps listings. If the caller has specified
+			// a name, use that instead of a.out. The binary is generated
+			// in an otherwise empty subdirectory named exe to avoid
+			// naming conflicts.  The only possible conflict is if we were
+			// to create a top-level package named exe.
+			name := "a.out"
+			if p.exeName != "" {
+				name = p.exeName
+			}
+			a.target = a.objdir + filepath.Join("exe", name) + exeSuffix
 		}
 	}
 
@@ -535,7 +615,6 @@ func (b *builder) do(root *action) {
 	}
 
 	b.readySema = make(chan bool, len(all))
-	done := make(chan bool)
 
 	// Initialize per-action execution state.
 	for _, a := range all {
@@ -583,10 +662,11 @@ func (b *builder) do(root *action) {
 
 		if a == root {
 			close(b.readySema)
-			done <- true
 		}
 	}
 
+	var wg sync.WaitGroup
+
 	// Kick off goroutines according to parallelism.
 	// If we are using the -n flag (just printing commands)
 	// drop the parallelism to 1, both to make the output
@@ -596,19 +676,40 @@ func (b *builder) do(root *action) {
 		par = 1
 	}
 	for i := 0; i < par; i++ {
+		wg.Add(1)
 		go func() {
-			for _ = range b.readySema {
-				// Receiving a value from b.sema entitles
-				// us to take from the ready queue.
-				b.exec.Lock()
-				a := b.ready.pop()
-				b.exec.Unlock()
-				handle(a)
+			defer wg.Done()
+			for {
+				select {
+				case _, ok := <-b.readySema:
+					if !ok {
+						return
+					}
+					// Receiving a value from b.readySema entitles
+					// us to take from the ready queue.
+					b.exec.Lock()
+					a := b.ready.pop()
+					b.exec.Unlock()
+					handle(a)
+				case <-interrupted:
+					setExitStatus(1)
+					return
+				}
 			}
 		}()
 	}
 
-	<-done
+	wg.Wait()
+}
+
+// hasString reports whether s appears in the list of strings.
+func hasString(strings []string, s string) bool {
+	for _, t := range strings {
+		if s == t {
+			return true
+		}
+	}
+	return false
 }
 
 // build is the action for building a single package or command.
@@ -631,12 +732,25 @@ func (b *builder) build(a *action) (err error) {
 		fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
 	}
 
+	if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" &&
+		!hasString(a.p.HFiles, "zasm_"+buildContext.GOOS+"_"+buildContext.GOARCH+".h") {
+		return fmt.Errorf("%s/%s must be bootstrapped using make.bash", buildContext.GOOS, buildContext.GOARCH)
+	}
+
 	// Make build directory.
 	obj := a.objdir
 	if err := b.mkdir(obj); err != nil {
 		return err
 	}
 
+	// make target directory
+	dir, _ := filepath.Split(a.target)
+	if dir != "" {
+		if err := b.mkdir(dir); err != nil {
+			return err
+		}
+	}
+
 	var gofiles, cfiles, sfiles, objects, cgoObjects []string
 	gofiles = append(gofiles, a.p.GoFiles...)
 	cfiles = append(cfiles, a.p.CFiles...)
@@ -680,16 +794,37 @@ func (b *builder) build(a *action) (err error) {
 		gofiles = append(gofiles, outGo...)
 	}
 
+	// Run SWIG.
+	if a.p.usesSwig() {
+		// In a package using SWIG, any .c or .s files are
+		// compiled with gcc.
+		gccfiles := append(cfiles, sfiles...)
+		cfiles = nil
+		sfiles = nil
+		outGo, outObj, err := b.swig(a.p, obj, gccfiles)
+		if err != nil {
+			return err
+		}
+		cgoObjects = append(cgoObjects, outObj...)
+		gofiles = append(gofiles, outGo...)
+	}
+
 	// Prepare Go import path list.
 	inc := b.includeArgs("-I", a.deps)
 
 	// Compile Go.
 	if len(gofiles) > 0 {
-		if out, err := buildToolchain.gc(b, a.p, obj, inc, gofiles); err != nil {
+		ofile, out, err := buildToolchain.gc(b, a.p, obj, inc, gofiles)
+		if len(out) > 0 {
+			b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(out))
+			if err != nil {
+				return errPrintedOutput
+			}
+		}
+		if err != nil {
 			return err
-		} else {
-			objects = append(objects, out)
 		}
+		objects = append(objects, ofile)
 	}
 
 	// Copy .h files named for goos or goarch or goos_goarch
@@ -718,8 +853,13 @@ func (b *builder) build(a *action) (err error) {
 		}
 	}
 
+	objExt := archChar
+	if _, ok := buildToolchain.(gccgoToolchain); ok {
+		objExt = "o"
+	}
+
 	for _, file := range cfiles {
-		out := file[:len(file)-len(".c")] + "." + archChar
+		out := file[:len(file)-len(".c")] + "." + objExt
 		if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil {
 			return err
 		}
@@ -728,7 +868,7 @@ func (b *builder) build(a *action) (err error) {
 
 	// Assemble .s files.
 	for _, file := range sfiles {
-		out := file[:len(file)-len(".s")] + "." + archChar
+		out := file[:len(file)-len(".s")] + "." + objExt
 		if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil {
 			return err
 		}
@@ -795,6 +935,20 @@ func (b *builder) install(a *action) (err error) {
 		defer os.Remove(a1.target)
 	}
 
+	if a.p.usesSwig() {
+		for _, f := range stringList(a.p.SwigFiles, a.p.SwigCXXFiles) {
+			dir = a.p.swigDir(&buildContext)
+			if err := b.mkdir(dir); err != nil {
+				return err
+			}
+			soname := a.p.swigSoname(f)
+			target := filepath.Join(dir, soname)
+			if err = b.copyFile(a, target, soname, perm); err != nil {
+				return err
+			}
+		}
+	}
+
 	return b.copyFile(a, a.target, a1.target, perm)
 }
 
@@ -826,10 +980,13 @@ func (b *builder) includeArgs(flag string, all []*action) []string {
 	for _, a1 := range all {
 		if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] {
 			incMap[dir] = true
-			if _, ok := buildToolchain.(gccgcToolchain); ok {
-				dir = filepath.Join(dir, "gccgo")
+			if _, ok := buildToolchain.(gccgoToolchain); ok {
+				dir = filepath.Join(dir, "gccgo_"+goos+"_"+goarch)
 			} else {
 				dir = filepath.Join(dir, goos+"_"+goarch)
+				if buildRace {
+					dir += "_race"
+				}
 			}
 			inc = append(inc, flag, dir)
 		}
@@ -905,6 +1062,8 @@ var objectMagic = [][]byte{
 	{0xCE, 0xFA, 0xED, 0xFE},                         // Mach-O little-endian 32-bit
 	{0xCF, 0xFA, 0xED, 0xFE},                         // Mach-O little-endian 64-bit
 	{0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x04, 0x00}, // PE (Windows) as generated by 6l/8l
+	{0x00, 0x00, 0x01, 0xEB},                         // Plan 9 i386
+	{0x00, 0x00, 0x8a, 0x97},                         // Plan 9 amd64
 }
 
 func isObject(s string) bool {
@@ -1024,19 +1183,18 @@ func relPaths(paths []string) []string {
 // print this error.
 var errPrintedOutput = errors.New("already printed output - no need to show error")
 
+var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`)
+
 // run runs the command given by cmdline in the directory dir.
 // If the command fails, run prints information about the failure
 // and returns a non-nil error.
 func (b *builder) run(dir string, desc string, cmdargs ...interface{}) error {
 	out, err := b.runOut(dir, desc, cmdargs...)
 	if len(out) > 0 {
-		if out[len(out)-1] != '\n' {
-			out = append(out, '\n')
-		}
 		if desc == "" {
 			desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " "))
 		}
-		b.showOutput(dir, desc, string(out))
+		b.showOutput(dir, desc, b.processOutput(out))
 		if err != nil {
 			err = errPrintedOutput
 		}
@@ -1044,6 +1202,23 @@ func (b *builder) run(dir string, desc string, cmdargs ...interface{}) error {
 	return err
 }
 
+// processOutput prepares the output of runOut to be output to the console.
+func (b *builder) processOutput(out []byte) string {
+	if out[len(out)-1] != '\n' {
+		out = append(out, '\n')
+	}
+	messages := string(out)
+	// Fix up output referring to cgo-generated code to be more readable.
+	// Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19.
+	// Replace _Ctype_foo with C.foo.
+	// If we're using -x, assume we're debugging and want the full dump, so disable the rewrite.
+	if !buildX && cgoLine.MatchString(messages) {
+		messages = cgoLine.ReplaceAllString(messages, "")
+		messages = strings.Replace(messages, "type _Ctype_", "type C.", -1)
+	}
+	return messages
+}
+
 // runOut runs the command given by cmdline in the directory dir.
 // It returns the command output and any errors that occurred.
 func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byte, error) {
@@ -1062,7 +1237,7 @@ func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byt
 		cmd.Stdout = &buf
 		cmd.Stderr = &buf
 		cmd.Dir = dir
-		// TODO: cmd.Env
+		cmd.Env = envForDir(cmd.Dir)
 		err := cmd.Run()
 
 		// cmd.Run will fail on Unix if some other process has the binary
@@ -1077,7 +1252,7 @@ func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byt
 		// not worry about other processes inheriting the fd accidentally.
 		// The answer is that running a command is fork and exec.
 		// A child forked while the cgo fd is open inherits that fd.
-		// Until the child has called exec, it holds the fd open and the 
+		// Until the child has called exec, it holds the fd open and the
 		// kernel will not let us run cgo.  Even if the child were to close
 		// the fd explicitly, it would still be open from the time of the fork
 		// until the time of the explicit close, and the race would remain.
@@ -1161,7 +1336,7 @@ type toolchain interface {
 	// gc runs the compiler in a specific directory on a set of files
 	// and returns the name of the generated output file.
 	// The compiler runs in the directory dir.
-	gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, err error)
+	gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
 	// cc runs the toolchain's C compiler in a directory on a C file
 	// to produce an output file.
 	cc(b *builder, p *Package, objdir, ofile, cfile string) error
@@ -1198,8 +1373,8 @@ func (noToolchain) linker() string {
 	return ""
 }
 
-func (noToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, err error) {
-	return "", noCompiler()
+func (noToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
+	return "", nil, noCompiler()
 }
 
 func (noToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
@@ -1234,7 +1409,7 @@ func (gcToolchain) linker() string {
 	return tool(archChar + "l")
 }
 
-func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, err error) {
+func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
 	out := "_go_." + archChar
 	ofile = obj + out
 	gcargs := []string{"-p", p.ImportPath}
@@ -1244,16 +1419,33 @@ func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, g
 		gcargs = append(gcargs, "-+")
 	}
 
+	// If we're giving the compiler the entire package (no C etc files), tell it that,
+	// so that it can give good error messages about forward declarations.
+	// Exceptions: a few standard packages have forward declarations for
+	// pieces supplied behind-the-scenes by package runtime.
+	extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles)
+	if p.Standard {
+		switch p.ImportPath {
+		case "os", "runtime/pprof", "sync", "time":
+			extFiles++
+		}
+	}
+	if extFiles == 0 {
+		gcargs = append(gcargs, "-complete")
+	}
+
 	args := stringList(tool(archChar+"g"), "-o", ofile, buildGcflags, gcargs, "-D", p.localPrefix, importArgs)
 	for _, f := range gofiles {
 		args = append(args, mkAbs(p.Dir, f))
 	}
-	return ofile, b.run(p.Dir, p.ImportPath, args)
+
+	output, err = b.runOut(p.Dir, p.ImportPath, args)
+	return ofile, output, err
 }
 
 func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
 	sfile = mkAbs(p.Dir, sfile)
-	return b.run(p.Dir, p.ImportPath, tool(archChar+"a"), "-I", obj, "-o", ofile, "-DGOOS_"+goos, "-DGOARCH_"+goarch, sfile)
+	return b.run(p.Dir, p.ImportPath, tool(archChar+"a"), "-I", obj, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile)
 }
 
 func (gcToolchain) pkgpath(basedir string, p *Package) string {
@@ -1266,62 +1458,86 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
 	for _, f := range ofiles {
 		absOfiles = append(absOfiles, mkAbs(objDir, f))
 	}
-	return b.run(p.Dir, p.ImportPath, tool("pack"), "grc", mkAbs(objDir, afile), absOfiles)
+	return b.run(p.Dir, p.ImportPath, tool("pack"), "grcP", b.work, mkAbs(objDir, afile), absOfiles)
 }
 
 func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
 	importArgs := b.includeArgs("-L", allactions)
-	return b.run(".", p.ImportPath, tool(archChar+"l"), "-o", out, importArgs, buildLdflags, mainpkg)
+	swigDirs := make(map[string]bool)
+	swigArg := []string{}
+	for _, a := range allactions {
+		if a.p != nil && a.p.usesSwig() {
+			sd := a.p.swigDir(&buildContext)
+			if len(swigArg) == 0 {
+				swigArg = []string{"-r", sd}
+			} else if !swigDirs[sd] {
+				swigArg[1] += ":"
+				swigArg[1] += sd
+			}
+			swigDirs[sd] = true
+		}
+	}
+	return b.run(".", p.ImportPath, tool(archChar+"l"), "-o", out, importArgs, swigArg, buildLdflags, mainpkg)
 }
 
 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)
-	return b.run(p.Dir, p.ImportPath, tool(archChar+"c"), "-FVw",
-		"-I", objdir, "-I", inc, "-o", ofile,
-		"-DGOOS_"+goos, "-DGOARCH_"+goarch, cfile)
+	args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile)
+	return b.run(p.Dir, p.ImportPath, args)
 }
 
 // The Gccgo toolchain.
-type gccgcToolchain struct{}
+type gccgoToolchain struct{}
 
 var gccgoBin, _ = exec.LookPath("gccgo")
 
-func (gccgcToolchain) compiler() string {
+func (gccgoToolchain) compiler() string {
 	return gccgoBin
 }
 
-func (gccgcToolchain) linker() string {
+func (gccgoToolchain) linker() string {
 	return gccgoBin
 }
 
-func (gccgcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, err error) {
+func (gccgoToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
 	out := p.Name + ".o"
 	ofile = obj + out
 	gcargs := []string{"-g"}
-	if prefix := gccgoPrefix(p); prefix != "" {
-		gcargs = append(gcargs, "-fgo-prefix="+gccgoPrefix(p))
+	gcargs = append(gcargs, b.gccArchArgs()...)
+	if pkgpath := gccgoPkgpath(p); pkgpath != "" {
+		gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath)
+	}
+	if p.localPrefix != "" {
+		gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix)
 	}
 	args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
 	for _, f := range gofiles {
 		args = append(args, mkAbs(p.Dir, f))
 	}
-	return ofile, b.run(p.Dir, p.ImportPath, args)
+
+	output, err = b.runOut(p.Dir, p.ImportPath, args)
+	return ofile, output, err
 }
 
-func (gccgcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
+func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
 	sfile = mkAbs(p.Dir, sfile)
-	return b.run(p.Dir, p.ImportPath, "gccgo", "-I", obj, "-o", ofile, "-DGOOS_"+goos, "-DGOARCH_"+goarch, sfile)
+	defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
+	if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
+		defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
+	}
+	defs = append(defs, b.gccArchArgs()...)
+	return b.run(p.Dir, p.ImportPath, "gccgo", "-I", obj, "-o", ofile, defs, sfile)
 }
 
-func (gccgcToolchain) pkgpath(basedir string, p *Package) string {
+func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
 	end := filepath.FromSlash(p.ImportPath + ".a")
 	afile := filepath.Join(basedir, end)
 	// add "lib" to the final element
 	return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile))
 }
 
-func (gccgcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
 	var absOfiles []string
 	for _, f := range ofiles {
 		absOfiles = append(absOfiles, mkAbs(objDir, f))
@@ -1329,12 +1545,14 @@ func (gccgcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles
 	return b.run(p.Dir, p.ImportPath, "ar", "cru", mkAbs(objDir, afile), absOfiles)
 }
 
-func (tools gccgcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
+func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
 	// gccgo needs explicit linking with all package dependencies,
 	// and all LDFLAGS from cgo dependencies.
 	afiles := make(map[*Package]string)
-	ldflags := []string{}
+	sfiles := make(map[*Package][]string)
+	ldflags := b.gccArchArgs()
 	cgoldflags := []string{}
+	usesCgo := false
 	for _, a := range allactions {
 		if a.p != nil {
 			if !a.p.Standard {
@@ -1343,31 +1561,99 @@ func (tools gccgcToolchain) ld(b *builder, p *Package, out string, allactions []
 				}
 			}
 			cgoldflags = append(cgoldflags, a.p.CgoLDFLAGS...)
+			if len(a.p.CgoFiles) > 0 {
+				usesCgo = true
+			}
+			if a.p.usesSwig() {
+				sd := a.p.swigDir(&buildContext)
+				for _, f := range stringList(a.p.SwigFiles, a.p.SwigCXXFiles) {
+					soname := a.p.swigSoname(f)
+					sfiles[a.p] = append(sfiles[a.p], filepath.Join(sd, soname))
+				}
+				usesCgo = true
+			}
 		}
 	}
 	for _, afile := range afiles {
 		ldflags = append(ldflags, afile)
 	}
+	for _, sfiles := range sfiles {
+		ldflags = append(ldflags, sfiles...)
+	}
 	ldflags = append(ldflags, cgoldflags...)
-	return b.run(".", p.ImportPath, "gccgo", "-o", out, buildGccgoflags, ofiles, "-Wl,-(", ldflags, "-Wl,-)")
+	if usesCgo && goos == "linux" {
+		ldflags = append(ldflags, "-Wl,-E")
+	}
+	return b.run(".", p.ImportPath, "gccgo", "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags)
 }
 
-func (gccgcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+func (gccgoToolchain) 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)
+	defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
+	defs = append(defs, b.gccArchArgs()...)
+	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, "gcc", "-Wall", "-g",
-		"-I", objdir, "-I", inc, "-o", ofile,
-		"-DGOOS_"+goos, "-DGOARCH_"+goarch, "-c", cfile)
+		"-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile)
 }
 
-func gccgoPrefix(p *Package) string {
-	switch {
-	case p.build.IsCommand() && !p.forceLibrary:
+func gccgoPkgpath(p *Package) string {
+	if p.build.IsCommand() && !p.forceLibrary {
 		return ""
-	case p.fake:
-		return "fake_" + p.ImportPath
 	}
-	return "go_" + p.ImportPath
+	return p.ImportPath
+}
+
+func gccgoCleanPkgpath(p *Package) string {
+	clean := func(r rune) rune {
+		switch {
+		case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
+			'0' <= r && r <= '9':
+			return r
+		}
+		return '_'
+	}
+	return strings.Map(clean, gccgoPkgpath(p))
+}
+
+// libgcc returns the filename for libgcc, as determined by invoking gcc with
+// the -print-libgcc-file-name option.
+func (b *builder) libgcc(p *Package) (string, error) {
+	var buf bytes.Buffer
+
+	gccCmd := b.gccCmd(p.Dir)
+
+	prev := b.print
+	if buildN {
+		// In -n mode we temporarily swap out the builder's
+		// print function to capture the command-line. This
+		// let's us assign it to $LIBGCC and produce a valid
+		// buildscript for cgo packages.
+		b.print = func(a ...interface{}) (n int, err error) {
+			return fmt.Fprint(&buf, a...)
+		}
+	}
+	f, err := b.runOut(p.Dir, p.ImportPath, gccCmd, "-print-libgcc-file-name")
+	if err != nil {
+		return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", err, f)
+	}
+	if buildN {
+		s := fmt.Sprintf("LIBGCC=$(%s)\n", buf.Next(buf.Len()-1))
+		b.print = prev
+		b.print(s)
+		return "$LIBGCC", nil
+	}
+
+	// clang 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)) {
+		return "", nil
+	}
+
+	return strings.Trim(string(f), "\r\n"), nil
 }
 
 // gcc runs the gcc C compiler to create an object from a single C file.
@@ -1386,20 +1672,19 @@ func (b *builder) gccCmd(objdir string) []string {
 	// NOTE: env.go's mkEnv knows that the first three
 	// strings returned are "gcc", "-I", objdir (and cuts them off).
 
-	// TODO: HOST_CC?
-	a := []string{"gcc", "-I", objdir, "-g", "-O2"}
+	gcc := strings.Fields(os.Getenv("CC"))
+	if len(gcc) == 0 {
+		gcc = append(gcc, "gcc")
+	}
+	a := []string{gcc[0], "-I", objdir, "-g", "-O2"}
+	a = append(a, gcc[1:]...)
 
 	// Definitely want -fPIC but on Windows gcc complains
 	// "-fPIC ignored for target (all code is position independent)"
 	if goos != "windows" {
 		a = append(a, "-fPIC")
 	}
-	switch archChar {
-	case "8":
-		a = append(a, "-m32")
-	case "6":
-		a = append(a, "-m64")
-	}
+	a = append(a, b.gccArchArgs()...)
 	// gcc-4.5 and beyond require explicit "-pthread" flag
 	// for multithreading with pthread library.
 	if buildContext.CgoEnabled {
@@ -1411,6 +1696,11 @@ func (b *builder) gccCmd(objdir string) []string {
 		}
 	}
 
+	// clang is too smart about command-line arguments
+	if strings.Contains(a[0], "clang") {
+		a = append(a, "-Qunused-arguments")
+	}
+
 	// On OS X, some of the compilers behave as if -fno-common
 	// is always set, and the Mach-O linker in 6l/8l assumes this.
 	// See http://golang.org/issue/3253.
@@ -1421,12 +1711,31 @@ func (b *builder) gccCmd(objdir string) []string {
 	return a
 }
 
+// gccArchArgs returns arguments to pass to gcc based on the architecture.
+func (b *builder) gccArchArgs() []string {
+	switch archChar {
+	case "8":
+		return []string{"-m32"}
+	case "6":
+		return []string{"-m64"}
+	case "5":
+		return []string{"-marm"} // not thumb
+	}
+	return nil
+}
+
 func envList(key string) []string {
 	return strings.Fields(os.Getenv(key))
 }
 
 var cgoRe = regexp.MustCompile(`[/\\:]`)
 
+var (
+	cgoLibGccFile     string
+	cgoLibGccErr      error
+	cgoLibGccFileOnce sync.Once
+)
+
 func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, outObj []string, err error) {
 	if goos != toolGOOS {
 		return nil, nil, errors.New("cannot use cgo when compiling for a different operating system")
@@ -1478,10 +1787,14 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
 	if p.Standard && p.ImportPath == "runtime/cgo" {
 		cgoflags = append(cgoflags, "-import_runtime_cgo=false")
 	}
-	if _, ok := buildToolchain.(gccgcToolchain); ok {
+	if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/cgo") {
+		cgoflags = append(cgoflags, "-import_syscall=false")
+	}
+
+	if _, ok := buildToolchain.(gccgoToolchain); ok {
 		cgoflags = append(cgoflags, "-gccgo")
-		if prefix := gccgoPrefix(p); prefix != "" {
-			cgoflags = append(cgoflags, "-gccgoprefix="+gccgoPrefix(p))
+		if pkgpath := gccgoPkgpath(p); pkgpath != "" {
+			cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath)
 		}
 		objExt = "o"
 	}
@@ -1499,6 +1812,36 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
 
 	// gcc
 	var linkobj []string
+
+	var bareLDFLAGS []string
+	// filter out -lsomelib, and -framework X if on Darwin
+	for i := 0; i < len(cgoLDFLAGS); i++ {
+		f := cgoLDFLAGS[i]
+		if !strings.HasPrefix(f, "-l") {
+			if goos == "darwin" && f == "-framework" { // skip the -framework X
+				i += 1
+				continue
+			}
+			bareLDFLAGS = append(bareLDFLAGS, f)
+		}
+	}
+
+	cgoLibGccFileOnce.Do(func() {
+		cgoLibGccFile, cgoLibGccErr = b.libgcc(p)
+	})
+	if cgoLibGccFile == "" && cgoLibGccErr != nil {
+		return nil, nil, err
+	}
+
+	var staticLibs []string
+	if goos == "windows" {
+		// libmingw32 and libmingwex might also use libgcc, so libgcc must come last
+		staticLibs = []string{"-lmingwex", "-lmingw32"}
+	}
+	if cgoLibGccFile != "" {
+		staticLibs = append(staticLibs, cgoLibGccFile)
+	}
+
 	for _, cfile := range cfiles {
 		ofile := obj + cfile[:len(cfile)-1] + "o"
 		if err := b.gcc(p, ofile, cgoCFLAGS, obj+cfile); err != nil {
@@ -1517,19 +1860,30 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
 		linkobj = append(linkobj, ofile)
 		outObj = append(outObj, ofile)
 	}
+	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
+		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
+		cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1]
+	}
 
-	if _, ok := buildToolchain.(gccgcToolchain); ok {
+	if _, ok := buildToolchain.(gccgoToolchain); ok {
 		// we don't use dynimport when using gccgo.
 		return outGo, outObj, nil
 	}
 
 	// cgo -dynimport
 	importC := obj + "_cgo_import.c"
-	if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC); err != nil {
+	cgoflags = []string{}
+	if p.Standard && p.ImportPath == "runtime/cgo" {
+		cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker
+	}
+	if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil {
 		return nil, nil, err
 	}
 
@@ -1539,14 +1893,162 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
 		return nil, nil, err
 	}
 
+	ofile := obj + "_all.o"
+	var gccObjs, nonGccObjs []string
+	for _, f := range outObj {
+		if strings.HasSuffix(f, ".o") {
+			gccObjs = append(gccObjs, f)
+		} else {
+			nonGccObjs = append(nonGccObjs, f)
+		}
+	}
+	if err := b.gccld(p, ofile, stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs), gccObjs); err != nil {
+		return nil, nil, err
+	}
+
 	// NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows
 	// must be processed before the gcc-generated objects.
 	// Put it first.  http://golang.org/issue/2601
-	outObj = append([]string{importObj}, outObj...)
+	outObj = stringList(importObj, nonGccObjs, ofile)
 
 	return outGo, outObj, nil
 }
 
+// Run SWIG on all SWIG input files.
+func (b *builder) swig(p *Package, obj string, gccfiles []string) (outGo, outObj []string, err error) {
+
+	intgosize, err := b.swigIntSize(obj)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	for _, f := range p.SwigFiles {
+		goFile, objFile, err := b.swigOne(p, f, obj, false, intgosize)
+		if err != nil {
+			return nil, nil, err
+		}
+		if goFile != "" {
+			outGo = append(outGo, goFile)
+		}
+		if objFile != "" {
+			outObj = append(outObj, objFile)
+		}
+	}
+	for _, f := range p.SwigCXXFiles {
+		goFile, objFile, err := b.swigOne(p, f, obj, true, intgosize)
+		if err != nil {
+			return nil, nil, err
+		}
+		if goFile != "" {
+			outGo = append(outGo, goFile)
+		}
+		if objFile != "" {
+			outObj = append(outObj, objFile)
+		}
+	}
+	return outGo, outObj, nil
+}
+
+// This code fails to build if sizeof(int) <= 32
+const swigIntSizeCode = `
+package main
+const i int = 1 << 32
+`
+
+// Determine the size of int on the target system for the -intgosize option
+// of swig >= 2.0.9
+func (b *builder) swigIntSize(obj string) (intsize string, err error) {
+	src := filepath.Join(b.work, "swig_intsize.go")
+	if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0644); err != nil {
+		return
+	}
+	srcs := []string{src}
+
+	p := goFilesPackage(srcs)
+
+	if _, _, e := buildToolchain.gc(b, p, obj, nil, srcs); e != nil {
+		return "32", nil
+	}
+	return "64", nil
+}
+
+// Run SWIG on one SWIG input file.
+func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize string) (outGo, outObj string, err error) {
+	n := 5 // length of ".swig"
+	if cxx {
+		n = 8 // length of ".swigcxx"
+	}
+	base := file[:len(file)-n]
+	goFile := base + ".go"
+	cBase := base + "_gc."
+	gccBase := base + "_wrap."
+	gccExt := "c"
+	if cxx {
+		gccExt = "cxx"
+	}
+	soname := p.swigSoname(file)
+
+	_, gccgo := buildToolchain.(gccgoToolchain)
+
+	// swig
+	args := []string{
+		"-go",
+		"-intgosize", intgosize,
+		"-module", base,
+		"-soname", soname,
+		"-o", obj + gccBase + gccExt,
+		"-outdir", obj,
+	}
+	if gccgo {
+		args = append(args, "-gccgo")
+	}
+	if cxx {
+		args = append(args, "-c++")
+	}
+
+	if out, err := b.runOut(p.Dir, p.ImportPath, "swig", args, file); err != nil {
+		if len(out) > 0 {
+			if bytes.Contains(out, []byte("Unrecognized option -intgosize")) {
+				return "", "", errors.New("must have SWIG version >= 2.0.9\n")
+			}
+			b.showOutput(p.Dir, p.ImportPath, b.processOutput(out))
+			return "", "", errPrintedOutput
+		}
+		return "", "", err
+	}
+
+	var cObj string
+	if !gccgo {
+		// cc
+		cObj = obj + cBase + archChar
+		if err := buildToolchain.cc(b, p, obj, cObj, obj+cBase+"c"); err != nil {
+			return "", "", err
+		}
+	}
+
+	// gcc
+	gccObj := obj + gccBase + "o"
+	if err := b.gcc(p, gccObj, []string{"-g", "-fPIC", "-O2"}, obj+gccBase+gccExt); err != nil {
+		return "", "", err
+	}
+
+	// create shared library
+	osldflags := map[string][]string{
+		"darwin":  {"-dynamiclib", "-Wl,-undefined,dynamic_lookup"},
+		"freebsd": {"-shared", "-lpthread", "-lm"},
+		"linux":   {"-shared", "-lpthread", "-lm"},
+		"windows": {"-shared", "-lm", "-mthreads"},
+	}
+	var cxxlib []string
+	if cxx {
+		cxxlib = []string{"-lstdc++"}
+	}
+	ldflags := stringList(osldflags[goos], cxxlib)
+	b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), "-o", soname, gccObj, ldflags)
+
+	return obj + goFile, cObj, nil
+}
+
 // An actionQueue is a priority queue of actions.
 type actionQueue []*action
 
@@ -1569,3 +2071,18 @@ func (q *actionQueue) push(a *action) {
 func (q *actionQueue) pop() *action {
 	return heap.Pop(q).(*action)
 }
+
+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])
+		os.Exit(2)
+	}
+	buildGcflags = append(buildGcflags, "-race")
+	buildLdflags = append(buildLdflags, "-race")
+	buildCcflags = append(buildCcflags, "-D", "RACE")
+	buildContext.InstallTag = "race"
+	buildContext.BuildTags = append(buildContext.BuildTags, "race")
+}
diff --git a/src/cmd/go/clean.go b/src/cmd/go/clean.go
index 7739518..ba600d3 100644
--- a/src/cmd/go/clean.go
+++ b/src/cmd/go/clean.go
@@ -34,6 +34,7 @@ source directories corresponding to the import paths:
 	DIR(.exe)        from go build
 	DIR.test(.exe)   from go test -c
 	MAINFILE(.exe)   from go build MAINFILE.go
+	*.so             from SWIG
 
 In the list, DIR represents the final path element of the
 directory, and MAINFILE is the base name of any Go source
@@ -93,11 +94,12 @@ var cleanFile = map[string]bool{
 }
 
 var cleanExt = map[string]bool{
-	".5": true,
-	".6": true,
-	".8": true,
-	".a": true,
-	".o": true,
+	".5":  true,
+	".6":  true,
+	".8":  true,
+	".a":  true,
+	".o":  true,
+	".so": true,
 }
 
 func clean(p *Package) {
@@ -168,7 +170,9 @@ func clean(p *Package) {
 						continue
 					}
 				}
-				os.RemoveAll(filepath.Join(p.Dir, name))
+				if err := os.RemoveAll(filepath.Join(p.Dir, name)); err != nil {
+					errorf("go clean: %v", err)
+				}
 			}
 			continue
 		}
@@ -178,7 +182,7 @@ func clean(p *Package) {
 		}
 
 		if cleanFile[name] || cleanExt[filepath.Ext(name)] || toRemove[name] {
-			os.Remove(filepath.Join(p.Dir, name))
+			removeFile(filepath.Join(p.Dir, name))
 		}
 	}
 
@@ -187,7 +191,21 @@ func clean(p *Package) {
 			b.showcmd("", "rm -f %s", p.target)
 		}
 		if !cleanN {
-			os.Remove(p.target)
+			removeFile(p.target)
+		}
+	}
+
+	if cleanI && p.usesSwig() {
+		for _, f := range stringList(p.SwigFiles, p.SwigCXXFiles) {
+			dir := p.swigDir(&buildContext)
+			soname := p.swigSoname(f)
+			target := filepath.Join(dir, soname)
+			if cleanN || cleanX {
+				b.showcmd("", "rm -f %s", target)
+			}
+			if !cleanN {
+				removeFile(target)
+			}
 		}
 	}
 
@@ -197,3 +215,11 @@ func clean(p *Package) {
 		}
 	}
 }
+
+// removeFile tries to remove file f, if error other than file doesn't exist
+// occurs, it will report the error.
+func removeFile(f string) {
+	if err := os.Remove(f); err != nil && !os.IsNotExist(err) {
+		errorf("go clean: %v", err)
+	}
+}
diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go
index 5e7b106..0297b76 100644
--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -76,7 +76,12 @@ The build flags are shared by the build, install, run, and test commands:
 		do not delete it when exiting.
 	-x
 		print the commands.
+	-race
+		enable data race detection.
+		Supported only on linux/amd64, darwin/amd64 and windows/amd64.
 
+	-ccflags 'arg list'
+		arguments to pass on each 5c, 6c, or 8c compiler invocation
 	-compiler name
 		name of compiler to use, as in runtime.Compiler (gccgo or gc)
 	-gccgoflags 'arg list'
@@ -90,6 +95,9 @@ The build flags are shared by the build, install, run, and test commands:
 		See the documentation for the go/build package for
 		more information about build tags.
 
+The list flags accept a space-separated list of strings. To embed spaces
+in an element in the list, surround it with either single or double quotes.
+
 For more about specifying packages, see 'go help packages'.
 For more about where packages and binaries are installed,
 see 'go help gopath'.
@@ -121,6 +129,7 @@ source directories corresponding to the import paths:
 	DIR(.exe)        from go build
 	DIR.test(.exe)   from go test -c
 	MAINFILE(.exe)   from go build MAINFILE.go
+	*.so             from SWIG
 
 In the list, DIR represents the final path element of the
 directory, and MAINFILE is the base name of any Go source
@@ -215,14 +224,11 @@ Download and install packages and dependencies
 
 Usage:
 
-	go get [-a] [-d] [-fix] [-n] [-p n] [-u] [-v] [-x] [packages]
+	go get [-d] [-fix] [-u] [build flags] [packages]
 
 Get downloads and installs the packages named by the import paths,
 along with their dependencies.
 
-The -a, -n, -v, -x, and -p flags have the same meaning as in 'go build'
-and 'go install'.  See 'go help build'.
-
 The -d flag instructs get to stop after downloading the packages; that is,
 it instructs get not to install the packages.
 
@@ -233,6 +239,9 @@ The -u flag instructs get to use the network to update the named packages
 and their dependencies.  By default, get uses the network to check out
 missing packages but does not use it to look for updates to existing packages.
 
+Get also accepts all the flags in the 'go build' and 'go install' commands,
+to control the installation. See 'go help build'.
+
 When checking out or updating a package, get looks for a branch or tag
 that matches the locally installed version of Go. The most important
 rule is that if the local installation is running version "go1", get
@@ -266,7 +275,7 @@ List packages
 
 Usage:
 
-	go list [-e] [-f format] [-json] [packages]
+	go list [-e] [-f format] [-json] [-tags 'tag list'] [packages]
 
 List lists the packages named by the import paths, one per line.
 
@@ -276,10 +285,10 @@ The default output shows the package import path:
     code.google.com/p/goauth2/oauth
     code.google.com/p/sqlite
 
-The -f flag specifies an alternate format for the list,
-using the syntax of package template.  The default output
-is equivalent to -f '{{.ImportPath}}'.  The struct
-being passed to the template is:
+The -f flag specifies an alternate format for the list, using the
+syntax of package template.  The default output is equivalent to -f
+'{{.ImportPath}}'.  One extra template function is available, "join",
+which calls strings.Join. The struct being passed to the template is:
 
     type Package struct {
         Dir        string // directory containing package sources
@@ -293,12 +302,15 @@ being passed to the template is:
         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"
-        CFiles   []string  // .c source files
-        HFiles   []string  // .h source files
-        SFiles   []string  // .s source files
-        SysoFiles []string // .syso object files to add to archive
+        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
+        HFiles   []string       // .h source files
+        SFiles   []string       // .s source files
+        SysoFiles []string      // .syso object files to add to archive
+        SwigFiles []string      // .swig files
+        SwigCXXFiles []string   // .swigcxx files
 
         // Cgo directives
         CgoCFLAGS    []string // cgo: flags for C compiler
@@ -333,6 +345,9 @@ printing.  Erroneous packages will have a non-empty ImportPath and
 a non-nil Error field; other information may or may not be missing
 (zeroed).
 
+The -tags flag specifies a list of build tags, like in the 'go build'
+command.
+
 For more about specifying packages, see 'go help packages'.
 
 
@@ -368,6 +383,7 @@ 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".  These additional files can contain test functions,
 benchmark functions, and example functions.  See 'go help testfunc' for more.
+Each listed package causes the execution of a separate test binary.
 
 By default, go test needs no arguments.  It compiles and tests the package
 with source in the current directory, including tests, and runs the tests.
@@ -445,7 +461,7 @@ On Unix, the value is a colon-separated string.
 On Windows, the value is a semicolon-separated string.
 On Plan 9, the value is a list.
 
-GOPATH must be set to build and install packages outside the
+GOPATH must be set to get, build and install packages outside the
 standard Go tree.
 
 Each directory listed in GOPATH must have a prescribed structure:
@@ -491,7 +507,7 @@ Here's an example directory layout:
                     bar.a          (installed package object)
 
 Go searches each directory listed in GOPATH to find source code,
-but new packages are always downloaded into the first directory 
+but new packages are always downloaded into the first directory
 in the list.
 
 
@@ -509,13 +525,13 @@ denotes the package in that directory.
 
 Otherwise, the import path P denotes the package found in
 the directory DIR/src/P for some DIR listed in the GOPATH
-environment variable (see 'go help gopath'). 
+environment variable (see 'go help gopath').
 
 If no import paths are given, the action applies to the
 package in the current directory.
 
 The special import path "all" expands to all package directories
-found in all the GOPATH trees.  For example, 'go list all' 
+found in all the GOPATH trees.  For example, 'go list all'
 lists all the packages on the local system.
 
 The special import path "std" is like all but expands to just the
@@ -623,7 +639,7 @@ The meta tag has the form:
 
 	<meta name="go-import" content="import-prefix vcs repo-root">
 
-The import-prefix is the import path correponding to the repository
+The import-prefix is the import path corresponding to the repository
 root. It must be a prefix or an exact match of the package being
 fetched with "go get". If it's not an exact match, another http
 request is made at the prefix to verify the <meta> tags match.
@@ -663,28 +679,47 @@ Description of testing flags
 The 'go test' command takes both flags that apply to 'go test' itself
 and flags that apply to the resulting test binary.
 
-The test binary, called pkg.test, where pkg is the name of the
-directory containing the package sources, has its own flags:
-
-	-test.v
-	    Verbose output: log all tests as they are run.
+The following flags are recognized by the 'go test' command and
+control the execution of any test:
 
-	-test.run pattern
-	    Run only those tests and examples matching the regular
-	    expression.
-
-	-test.bench pattern
+	-bench regexp
 	    Run benchmarks matching the regular expression.
-	    By default, no benchmarks run.
+	    By default, no benchmarks run. To run all benchmarks,
+	    use '-bench .' or '-bench=.'.
+
+	-benchmem
+	    Print memory allocation statistics for benchmarks.
+
+	-benchtime t
+		Run enough iterations of each benchmark to take t, specified
+		as a time.Duration (for example, -benchtime 1h30s).
+		The default is 1 second (1s).
+
+	-blockprofile block.out
+	    Write a goroutine blocking profile to the specified file
+	    when all tests are complete.
+
+	-blockprofilerate n
+	    Control the detail provided in goroutine blocking profiles by setting
+	    runtime.BlockProfileRate to n.  See 'godoc runtime BlockProfileRate'.
+	    The profiler aims to sample, on average, one blocking event every
+	    n nanoseconds the program spends blocked.  By default,
+	    if -test.blockprofile is set without this flag, all blocking events
+	    are recorded, equivalent to -test.blockprofilerate=1.
+
+	-cpu 1,2,4
+	    Specify a list of GOMAXPROCS values for which the tests or
+	    benchmarks should be executed.  The default is the current value
+	    of GOMAXPROCS.
 
-	-test.cpuprofile cpu.out
+	-cpuprofile cpu.out
 	    Write a CPU profile to the specified file before exiting.
 
-	-test.memprofile mem.out
+	-memprofile mem.out
 	    Write a memory profile to the specified file when all tests
 	    are complete.
 
-	-test.memprofilerate n
+	-memprofilerate n
 	    Enable more precise (and expensive) memory profiles by setting
 	    runtime.MemProfileRate.  See 'godoc runtime MemProfileRate'.
 	    To profile all memory allocations, use -test.memprofilerate=1
@@ -692,32 +727,35 @@ directory containing the package sources, has its own flags:
 	    garbage collector, provided the test can run in the available
 	    memory without garbage collection.
 
-	-test.parallel n
+	-parallel n
 	    Allow parallel execution of test functions that call t.Parallel.
 	    The value of this flag is the maximum number of tests to run
 	    simultaneously; by default, it is set to the value of GOMAXPROCS.
 
-	-test.short
+	-run regexp
+	    Run only those tests and examples matching the regular
+	    expression.
+
+	-short
 	    Tell long-running tests to shorten their run time.
 	    It is off by default but set during all.bash so that installing
 	    the Go tree can run a sanity check but not spend time running
 	    exhaustive tests.
 
-	-test.timeout t
+	-timeout t
 		If a test runs longer than t, panic.
 
-	-test.benchtime n
-		Run enough iterations of each benchmark to take n seconds.
-		The default is 1 second.
+	-v
+	    Verbose output: log all tests as they are run.
 
-	-test.cpu 1,2,4
-	    Specify a list of GOMAXPROCS values for which the tests or
-	    benchmarks should be executed.  The default is the current value
-	    of GOMAXPROCS.
+The test binary, called pkg.test where pkg is the name of the
+directory containing the package sources, can be invoked directly
+after building it with 'go test -c'. When invoking the test binary
+directly, each of the standard flag names must be prefixed with 'test.',
+as in -test.run=TestMyFunc or -test.v.
 
-For convenience, each of these -test.X flags of the test binary is
-also available as the flag -X in 'go test' itself.  Flags not listed
-here are passed through unaltered.  For instance, the command
+When running 'go test', flags not listed above are passed through
+unaltered. For instance, the command
 
 	go test -x -v -cpuprofile=prof.out -dir=testdata -update
 
@@ -725,6 +763,11 @@ will compile the test binary and then run it as
 
 	pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update
 
+The test flags that generate profiles also leave the test binary in pkg.test
+for use when analyzing the profiles.
+
+Flags not recognized by 'go test' must be placed after any specified packages.
+
 
 Description of testing functions
 
@@ -740,8 +783,8 @@ A benchmark function is one named BenchmarkXXX and should have the signature,
 
 	func BenchmarkXXX(b *testing.B) { ... }
 
-An example function is similar to a test function but, instead of using *testing.T
-to report success or failure, prints output to os.Stdout and os.Stderr.
+An example function is similar to a test function but, instead of using
+*testing.T to report success or failure, prints output to os.Stdout.
 That output is compared against the function's "Output:" comment, which
 must be the last comment in the function body (see example below). An
 example with no such comment, or with no text after "Output:" is compiled
@@ -769,6 +812,6 @@ See the documentation of the testing package for more information.
 
 
 */
-package documentation
+package main
 
 // NOTE: cmdDoc is in fmt.go.
diff --git a/src/cmd/go/env.go b/src/cmd/go/env.go
index d5b0348..6cab37b 100644
--- a/src/cmd/go/env.go
+++ b/src/cmd/go/env.go
@@ -6,6 +6,7 @@ package main
 
 import (
 	"fmt"
+	"os"
 	"runtime"
 	"strings"
 )
@@ -33,16 +34,22 @@ func mkEnv() []envVar {
 	b.init()
 
 	env := []envVar{
-		{"GOROOT", goroot},
-		{"GOBIN", gobin},
 		{"GOARCH", goarch},
+		{"GOBIN", gobin},
 		{"GOCHAR", archChar},
-		{"GOOS", goos},
 		{"GOEXE", exeSuffix},
 		{"GOHOSTARCH", runtime.GOARCH},
 		{"GOHOSTOS", runtime.GOOS},
+		{"GOOS", goos},
+		{"GOPATH", os.Getenv("GOPATH")},
+		{"GOROOT", goroot},
 		{"GOTOOLDIR", toolDir},
-		{"GOGCCFLAGS", strings.Join(b.gccCmd(".")[3:], " ")},
+	}
+
+	if goos != "plan9" {
+		cmd := b.gccCmd(".")
+		env = append(env, envVar{"CC", cmd[0]})
+		env = append(env, envVar{"GOGCCFLAGS", strings.Join(cmd[3:], " ")})
 	}
 
 	if buildContext.CgoEnabled {
diff --git a/src/cmd/go/fix.go b/src/cmd/go/fix.go
index ef02b57..8736cce 100644
--- a/src/cmd/go/fix.go
+++ b/src/cmd/go/fix.go
@@ -25,6 +25,6 @@ func runFix(cmd *Command, args []string) {
 		// Use pkg.gofiles instead of pkg.Dir so that
 		// the command only applies to this package,
 		// not to packages in subdirectories.
-		run(stringList(tool("fix"), relPaths(pkg.gofiles)))
+		run(stringList(tool("fix"), relPaths(pkg.allgofiles)))
 	}
 }
diff --git a/src/cmd/go/fmt.go b/src/cmd/go/fmt.go
index b1aba32..9d3c911 100644
--- a/src/cmd/go/fmt.go
+++ b/src/cmd/go/fmt.go
@@ -34,7 +34,7 @@ func runFmt(cmd *Command, args []string) {
 		// Use pkg.gofiles instead of pkg.Dir so that
 		// the command only applies to this package,
 		// not to packages in subdirectories.
-		run(stringList("gofmt", "-l", "-w", relPaths(pkg.gofiles)))
+		run(stringList("gofmt", "-l", "-w", relPaths(pkg.allgofiles)))
 	}
 }
 
diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go
index fe45697..8c08ab2 100644
--- a/src/cmd/go/get.go
+++ b/src/cmd/go/get.go
@@ -18,15 +18,12 @@ import (
 )
 
 var cmdGet = &Command{
-	UsageLine: "get [-a] [-d] [-fix] [-n] [-p n] [-u] [-v] [-x] [packages]",
+	UsageLine: "get [-d] [-fix] [-u] [build flags] [packages]",
 	Short:     "download and install packages and dependencies",
 	Long: `
 Get downloads and installs the packages named by the import paths,
 along with their dependencies.
 
-The -a, -n, -v, -x, and -p flags have the same meaning as in 'go build'
-and 'go install'.  See 'go help build'.
-
 The -d flag instructs get to stop after downloading the packages; that is,
 it instructs get not to install the packages.
 
@@ -37,6 +34,9 @@ The -u flag instructs get to use the network to update the named packages
 and their dependencies.  By default, get uses the network to check out
 missing packages but does not use it to look for updates to existing packages.
 
+Get also accepts all the flags in the 'go build' and 'go install' commands,
+to control the installation. See 'go help build'.
+
 When checking out or updating a package, get looks for a branch or tag
 that matches the locally installed version of Go. The most important
 rule is that if the local installation is running version "go1", get
@@ -93,7 +93,7 @@ func runGet(cmd *Command, args []string) {
 	runInstall(cmd, args)
 }
 
-// downloadPath prepares the list of paths to pass to download.
+// downloadPaths prepares the list of paths to pass to download.
 // It expands ... patterns that can be expanded.  If there is no match
 // for a particular pattern, downloadPaths leaves it in the result list,
 // in the hope that we can figure out the repository from the
@@ -105,7 +105,7 @@ func downloadPaths(args []string) []string {
 		if strings.Contains(a, "...") {
 			var expand []string
 			// Use matchPackagesInFS to avoid printing
-			// warnings.  They will be printed by the 
+			// warnings.  They will be printed by the
 			// eventual call to importPaths instead.
 			if build.IsLocalImport(a) {
 				expand = matchPackagesInFS(a)
@@ -204,7 +204,7 @@ func download(arg string, stk *importStack) {
 	// due to wildcard expansion.
 	for _, p := range pkgs {
 		if *getFix {
-			run(stringList(tool("fix"), relPaths(p.gofiles)))
+			run(stringList(tool("fix"), relPaths(p.allgofiles)))
 
 			// The imports might have changed, so reload again.
 			p = reloadPackage(arg, stk)
@@ -247,16 +247,17 @@ func downloadPackage(p *Package) error {
 	}
 
 	if p.build.SrcRoot == "" {
-		// Package not found.  Put in first directory of $GOPATH or else $GOROOT.
-		// Guard against people setting GOPATH=$GOROOT.  We have to use
-		// $GOROOT's directory hierarchy (src/pkg, not just src) in that case.
-		if list := filepath.SplitList(buildContext.GOPATH); len(list) > 0 && list[0] != goroot {
-			p.build.SrcRoot = filepath.Join(list[0], "src")
-			p.build.PkgRoot = filepath.Join(list[0], "pkg")
-		} else {
-			p.build.SrcRoot = filepath.Join(goroot, "src", "pkg")
-			p.build.PkgRoot = filepath.Join(goroot, "pkg")
+		// Package not found.  Put in first directory of $GOPATH.
+		list := filepath.SplitList(buildContext.GOPATH)
+		if len(list) == 0 {
+			return fmt.Errorf("cannot download, $GOPATH not set. For more details see: go help gopath")
+		}
+		// Guard against people setting GOPATH=$GOROOT.
+		if list[0] == goroot {
+			return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath")
 		}
+		p.build.SrcRoot = filepath.Join(list[0], "src")
+		p.build.PkgRoot = filepath.Join(list[0], "pkg")
 	}
 	root := filepath.Join(p.build.SrcRoot, rootPath)
 	// If we've considered this repository already, don't do it again.
diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go
index 7539753..6d2bd7d 100644
--- a/src/cmd/go/help.go
+++ b/src/cmd/go/help.go
@@ -186,7 +186,7 @@ On Unix, the value is a colon-separated string.
 On Windows, the value is a semicolon-separated string.
 On Plan 9, the value is a list.
 
-GOPATH must be set to build and install packages outside the
+GOPATH must be set to get, build and install packages outside the
 standard Go tree.
 
 Each directory listed in GOPATH must have a prescribed structure:
diff --git a/src/cmd/go/http.go b/src/cmd/go/http.go
index 6de9a3e..107b820 100644
--- a/src/cmd/go/http.go
+++ b/src/cmd/go/http.go
@@ -20,9 +20,13 @@ import (
 	"net/url"
 )
 
+// httpClient is the default HTTP client, but a variable so it can be
+// changed by tests, without modifying http.DefaultClient.
+var httpClient = http.DefaultClient
+
 // httpGET returns the data from an HTTP GET request for the given URL.
 func httpGET(url string) ([]byte, error) {
-	resp, err := http.Get(url)
+	resp, err := httpClient.Get(url)
 	if err != nil {
 		return nil, err
 	}
@@ -37,10 +41,6 @@ func httpGET(url string) ([]byte, error) {
 	return b, nil
 }
 
-// httpClient is the default HTTP client, but a variable so it can be
-// changed by tests, without modifying http.DefaultClient.
-var httpClient = http.DefaultClient
-
 // httpsOrHTTP returns the body of either the importPath's
 // https resource or, if unavailable, the http resource.
 func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err error) {
diff --git a/src/cmd/go/list.go b/src/cmd/go/list.go
index edb59aa..2d23d07 100644
--- a/src/cmd/go/list.go
+++ b/src/cmd/go/list.go
@@ -9,11 +9,12 @@ import (
 	"encoding/json"
 	"io"
 	"os"
+	"strings"
 	"text/template"
 )
 
 var cmdList = &Command{
-	UsageLine: "list [-e] [-f format] [-json] [packages]",
+	UsageLine: "list [-e] [-f format] [-json] [-tags 'tag list'] [packages]",
 	Short:     "list packages",
 	Long: `
 List lists the packages named by the import paths, one per line.
@@ -24,10 +25,10 @@ The default output shows the package import path:
     code.google.com/p/goauth2/oauth
     code.google.com/p/sqlite
 
-The -f flag specifies an alternate format for the list,
-using the syntax of package template.  The default output
-is equivalent to -f '{{.ImportPath}}'.  The struct
-being passed to the template is:
+The -f flag specifies an alternate format for the list, using the
+syntax of package template.  The default output is equivalent to -f
+'{{.ImportPath}}'.  One extra template function is available, "join",
+which calls strings.Join. The struct being passed to the template is:
 
     type Package struct {
         Dir        string // directory containing package sources
@@ -41,12 +42,15 @@ being passed to the template is:
         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"
-        CFiles   []string  // .c source files
-        HFiles   []string  // .h source files
-        SFiles   []string  // .s source files
-        SysoFiles []string // .syso object files to add to archive
+        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
+        HFiles   []string       // .h source files
+        SFiles   []string       // .s source files
+        SysoFiles []string      // .syso object files to add to archive
+        SwigFiles []string      // .swig files
+        SwigCXXFiles []string   // .swigcxx files
 
         // Cgo directives
         CgoCFLAGS    []string // cgo: flags for C compiler
@@ -81,6 +85,9 @@ printing.  Erroneous packages will have a non-empty ImportPath and
 a non-nil Error field; other information may or may not be missing
 (zeroed).
 
+The -tags flag specifies a list of build tags, like in the 'go build'
+command.
+
 For more about specifying packages, see 'go help packages'.
 	`,
 }
@@ -88,6 +95,7 @@ For more about specifying packages, see 'go help packages'.
 func init() {
 	cmdList.Run = runList // break init cycle
 	cmdList.Flag.Var(buildCompiler{}, "compiler", "")
+	cmdList.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
 }
 
 var listE = cmdList.Flag.Bool("e", false, "")
@@ -96,7 +104,7 @@ var listJson = cmdList.Flag.Bool("json", false, "")
 var nl = []byte{'\n'}
 
 func runList(cmd *Command, args []string) {
-	out := newCountingWriter(os.Stdout)
+	out := newTrackingWriter(os.Stdout)
 	defer out.w.Flush()
 
 	var do func(*Package)
@@ -111,18 +119,17 @@ func runList(cmd *Command, args []string) {
 			out.Write(nl)
 		}
 	} else {
-		tmpl, err := template.New("main").Parse(*listFmt)
+		tmpl, err := template.New("main").Funcs(template.FuncMap{"join": strings.Join}).Parse(*listFmt)
 		if err != nil {
 			fatalf("%s", err)
 		}
 		do = func(p *Package) {
-			out.Reset()
 			if err := tmpl.Execute(out, p); err != nil {
 				out.Flush()
 				fatalf("%s", err)
 			}
-			if out.Count() > 0 {
-				out.w.WriteRune('\n')
+			if out.NeedNL() {
+				out.Write([]byte{'\n'})
 			}
 		}
 	}
@@ -137,32 +144,33 @@ func runList(cmd *Command, args []string) {
 	}
 }
 
-// CountingWriter counts its data, so we can avoid appending a newline
-// if there was no actual output.
-type CountingWriter struct {
-	w     *bufio.Writer
-	count int64
+// TrackingWriter tracks the last byte written on every write so
+// we can avoid printing a newline if one was already written or
+// if there is no output at all.
+type TrackingWriter struct {
+	w    *bufio.Writer
+	last byte
 }
 
-func newCountingWriter(w io.Writer) *CountingWriter {
-	return &CountingWriter{
-		w: bufio.NewWriter(w),
+func newTrackingWriter(w io.Writer) *TrackingWriter {
+	return &TrackingWriter{
+		w:    bufio.NewWriter(w),
+		last: '\n',
 	}
 }
 
-func (cw *CountingWriter) Write(p []byte) (n int, err error) {
-	cw.count += int64(len(p))
-	return cw.w.Write(p)
-}
-
-func (cw *CountingWriter) Flush() {
-	cw.w.Flush()
+func (t *TrackingWriter) Write(p []byte) (n int, err error) {
+	n, err = t.w.Write(p)
+	if n > 0 {
+		t.last = p[n-1]
+	}
+	return
 }
 
-func (cw *CountingWriter) Reset() {
-	cw.count = 0
+func (t *TrackingWriter) Flush() {
+	t.w.Flush()
 }
 
-func (cw *CountingWriter) Count() int64 {
-	return cw.count
+func (t *TrackingWriter) NeedNL() bool {
+	return t.last != '\n'
 }
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index 20585d1..bf1dad4 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -127,6 +127,17 @@ func main() {
 	// which is not what most people want when they do it.
 	if gopath := os.Getenv("GOPATH"); gopath == runtime.GOROOT() {
 		fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath)
+	} else {
+		for _, p := range filepath.SplitList(gopath) {
+			if strings.Contains(p, "~") && runtime.GOOS != "windows" {
+				fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot contain shell metacharacter '~': %q\n", p)
+				os.Exit(2)
+			}
+			if build.IsLocalImport(p) {
+				fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nRun 'go help gopath' for usage.\n", p)
+				os.Exit(2)
+			}
+		}
 	}
 
 	for _, cmd := range commands {
@@ -189,7 +200,7 @@ var documentationTemplate = `// Copyright 2011 The Go Authors.  All rights reser
 
 
 {{end}}*/
-package documentation
+package main
 
 // NOTE: cmdDoc is in fmt.go.
 `
@@ -368,6 +379,25 @@ func runOut(dir string, cmdargs ...interface{}) []byte {
 	return out
 }
 
+// envForDir returns a copy of the environment
+// suitable for running in the given directory.
+// The environment is the current process's environment
+// but with an updated $PWD, so that an os.Getwd in the
+// child will be faster.
+func envForDir(dir string) []string {
+	env := os.Environ()
+	for i, kv := range env {
+		if strings.HasPrefix(kv, "PWD=") {
+			env[i] = "PWD=" + dir
+			return env
+		}
+	}
+	// Internally we only use rooted paths, so dir is rooted.
+	// Even if dir is not rooted, no harm done.
+	env = append(env, "PWD="+dir)
+	return env
+}
+
 // matchPattern(pattern)(name) reports whether
 // name matches pattern.  Pattern is a limited glob
 // pattern in which '...' means 'any string' and there
@@ -423,19 +453,20 @@ func matchPackages(pattern string) []string {
 			return filepath.SkipDir
 		}
 
-		_, err = build.ImportDir(path, 0)
-		if err != nil {
-			return nil
-		}
-
 		// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
 		name = "cmd/" + name
-		if !have[name] {
-			have[name] = true
-			if match(name) {
-				pkgs = append(pkgs, name)
-			}
+		if have[name] {
+			return nil
 		}
+		have[name] = true
+		if !match(name) {
+			return nil
+		}
+		_, err = buildContext.ImportDir(path, 0)
+		if err != nil {
+			return nil
+		}
+		pkgs = append(pkgs, name)
 		return nil
 	})
 
@@ -463,14 +494,14 @@ func matchPackages(pattern string) []string {
 				return nil
 			}
 			have[name] = true
-
-			_, err = build.ImportDir(path, 0)
-			if err != nil && strings.Contains(err.Error(), "no Go source files") {
+			if !match(name) {
 				return nil
 			}
-			if match(name) {
-				pkgs = append(pkgs, name)
+			_, err = buildContext.ImportDir(path, 0)
+			if err != nil && strings.Contains(err.Error(), "no Go source files") {
+				return nil
 			}
+			pkgs = append(pkgs, name)
 			return nil
 		})
 	}
@@ -559,3 +590,60 @@ func stringList(args ...interface{}) []string {
 	}
 	return x
 }
+
+// toFold returns a string with the property that
+//	strings.EqualFold(s, t) iff toFold(s) == toFold(t)
+// This lets us test a large set of strings for fold-equivalent
+// duplicates without making a quadratic number of calls
+// to EqualFold. Note that strings.ToUpper and strings.ToLower
+// have the desired property in some corner cases.
+func toFold(s string) string {
+	// Fast path: all ASCII, no upper case.
+	// Most paths look like this already.
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' {
+			goto Slow
+		}
+	}
+	return s
+
+Slow:
+	var buf bytes.Buffer
+	for _, r := range s {
+		// SimpleFold(x) cycles to the next equivalent rune > x
+		// or wraps around to smaller values. Iterate until it wraps,
+		// and we've found the minimum value.
+		for {
+			r0 := r
+			r = unicode.SimpleFold(r0)
+			if r <= r0 {
+				break
+			}
+		}
+		// Exception to allow fast path above: A-Z => a-z
+		if 'A' <= r && r <= 'Z' {
+			r += 'a' - 'A'
+		}
+		buf.WriteRune(r)
+	}
+	return buf.String()
+}
+
+// foldDup reports a pair of strings from the list that are
+// equal according to strings.EqualFold.
+// It returns "", "" if there are no such strings.
+func foldDup(list []string) (string, string) {
+	clash := map[string]string{}
+	for _, s := range list {
+		fold := toFold(s)
+		if t := clash[fold]; t != "" {
+			if s > t {
+				s, t = t, s
+			}
+			return s, t
+		}
+		clash[fold] = s
+	}
+	return "", ""
+}
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index 30bbfad..7fc61fd 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -36,12 +36,15 @@ type Package struct {
 	Root       string `json:",omitempty"` // Go root or Go path dir containing this package
 
 	// Source files
-	GoFiles   []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
-	CgoFiles  []string `json:",omitempty"` // .go sources files that import "C"
-	CFiles    []string `json:",omitempty"` // .c source files
-	HFiles    []string `json:",omitempty"` // .h source files
-	SFiles    []string `json:",omitempty"` // .s source files
-	SysoFiles []string `json:",omitempty"` // .syso system object files added to package
+	GoFiles        []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+	CgoFiles       []string `json:",omitempty"` // .go sources files that import "C"
+	IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints
+	CFiles         []string `json:",omitempty"` // .c source files
+	HFiles         []string `json:",omitempty"` // .h source files
+	SFiles         []string `json:",omitempty"` // .s source files
+	SysoFiles      []string `json:",omitempty"` // .syso system object files added to package
+	SwigFiles      []string `json:",omitempty"` // .swig files
+	SwigCXXFiles   []string `json:",omitempty"` // .swigcxx files
 
 	// Cgo directives
 	CgoCFLAGS    []string `json:",omitempty"` // cgo: flags for C compiler
@@ -69,12 +72,14 @@ type Package struct {
 	imports      []*Package
 	deps         []*Package
 	gofiles      []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
+	allgofiles   []string // gofiles + IgnoredGoFiles, absolute paths
 	target       string   // installed file for this package (may be executable)
 	fake         bool     // synthesized package
 	forceBuild   bool     // this package must be rebuilt
 	forceLibrary bool     // this package is a library (even if named "main")
 	local        bool     // imported via local path (./ or ../)
 	localPrefix  string   // interpret ./ and ../ imports relative to this prefix
+	exeName      string   // desired name for temporary executable
 }
 
 func (p *Package) copyBuild(pp *build.Package) {
@@ -90,10 +95,13 @@ func (p *Package) copyBuild(pp *build.Package) {
 	p.Standard = p.Goroot && p.ImportPath != "" && !strings.Contains(p.ImportPath, ".")
 	p.GoFiles = pp.GoFiles
 	p.CgoFiles = pp.CgoFiles
+	p.IgnoredGoFiles = pp.IgnoredGoFiles
 	p.CFiles = pp.CFiles
 	p.HFiles = pp.HFiles
 	p.SFiles = pp.SFiles
 	p.SysoFiles = pp.SysoFiles
+	p.SwigFiles = pp.SwigFiles
+	p.SwigCXXFiles = pp.SwigCXXFiles
 	p.CgoCFLAGS = pp.CgoCFLAGS
 	p.CgoLDFLAGS = pp.CgoLDFLAGS
 	p.CgoPkgConfig = pp.CgoPkgConfig
@@ -117,6 +125,9 @@ func (p *PackageError) Error() string {
 		// is the most important thing.
 		return p.Pos + ": " + p.Err
 	}
+	if len(p.ImportStack) == 0 {
+		return p.Err
+	}
 	return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Err
 }
 
@@ -246,7 +257,7 @@ func reusePackage(p *Package, stk *importStack) *Package {
 		if p.Error == nil {
 			p.Error = &PackageError{
 				ImportStack: stk.copy(),
-				Err:         "import loop",
+				Err:         "import cycle not allowed",
 			}
 		}
 		p.Incomplete = true
@@ -260,13 +271,11 @@ func reusePackage(p *Package, stk *importStack) *Package {
 // isGoTool is the list of directories for Go programs that are installed in
 // $GOROOT/pkg/tool.
 var isGoTool = map[string]bool{
-	"cmd/api":      true,
-	"cmd/cgo":      true,
-	"cmd/fix":      true,
-	"cmd/vet":      true,
-	"cmd/yacc":     true,
-	"exp/gotype":   true,
-	"exp/ebnflint": true,
+	"cmd/api":  true,
+	"cmd/cgo":  true,
+	"cmd/fix":  true,
+	"cmd/vet":  true,
+	"cmd/yacc": true,
 }
 
 // expandScanner expands a scanner.List error into all the errors in the list.
@@ -316,11 +325,13 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
 			// Install cross-compiled binaries to subdirectories of bin.
 			elem = full
 		}
-		p.target = filepath.Join(p.build.BinDir, elem)
-		if p.Goroot && isGoTool[p.ImportPath] {
+		if p.build.BinDir != "" {
+			p.target = filepath.Join(p.build.BinDir, elem)
+		}
+		if p.Goroot && (isGoTool[p.ImportPath] || strings.HasPrefix(p.ImportPath, "exp/")) {
 			p.target = filepath.Join(gorootPkg, "tool", full)
 		}
-		if buildContext.GOOS == "windows" {
+		if p.target != "" && buildContext.GOOS == "windows" {
 			p.target += ".exe"
 		}
 	} else if p.local {
@@ -340,6 +351,11 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
 	// Everything depends on runtime, except runtime and unsafe.
 	if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") {
 		importPaths = append(importPaths, "runtime")
+		// When race detection enabled everything depends on runtime/race.
+		// Exclude runtime/cgo and cmd/cgo to avoid circular dependencies.
+		if buildRace && (!p.Standard || (p.ImportPath != "runtime/race" && p.ImportPath != "runtime/cgo" && p.ImportPath != "cmd/cgo")) {
+			importPaths = append(importPaths, "runtime/race")
+		}
 	}
 
 	// Build list of full paths to all Go files in the package,
@@ -350,6 +366,38 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
 	}
 	sort.Strings(p.gofiles)
 
+	p.allgofiles = stringList(p.IgnoredGoFiles)
+	for i := range p.allgofiles {
+		p.allgofiles[i] = filepath.Join(p.Dir, p.allgofiles[i])
+	}
+	p.allgofiles = append(p.allgofiles, p.gofiles...)
+	sort.Strings(p.allgofiles)
+
+	// Check for case-insensitive collision of input files.
+	// To avoid problems on case-insensitive files, we reject any package
+	// where two different input files have equal names under a case-insensitive
+	// comparison.
+	f1, f2 := foldDup(stringList(
+		p.GoFiles,
+		p.CgoFiles,
+		p.IgnoredGoFiles,
+		p.CFiles,
+		p.HFiles,
+		p.SFiles,
+		p.SysoFiles,
+		p.SwigFiles,
+		p.SwigCXXFiles,
+		p.TestGoFiles,
+		p.XTestGoFiles,
+	))
+	if f1 != "" {
+		p.Error = &PackageError{
+			ImportStack: stk.copy(),
+			Err:         fmt.Sprintf("case-insensitive file name collision: %q and %q", f1, f2),
+		}
+		return p
+	}
+
 	// Build list of imported packages and full dependency list.
 	imports := make([]*Package, 0, len(p.Imports))
 	deps := make(map[string]bool)
@@ -403,11 +451,47 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
 	if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
 		p.target = ""
 	}
-
 	p.Target = p.target
+
+	// In the absence of errors lower in the dependency tree,
+	// check for case-insensitive collisions of import paths.
+	if len(p.DepsErrors) == 0 {
+		dep1, dep2 := foldDup(p.Deps)
+		if dep1 != "" {
+			p.Error = &PackageError{
+				ImportStack: stk.copy(),
+				Err:         fmt.Sprintf("case-insensitive import collision: %q and %q", dep1, dep2),
+			}
+			return p
+		}
+	}
+
 	return p
 }
 
+// usesSwig returns whether the package needs to run SWIG.
+func (p *Package) usesSwig() bool {
+	return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0
+}
+
+// swigSoname returns the name of the shared library we create for a
+// SWIG input file.
+func (p *Package) swigSoname(file string) string {
+	return strings.Replace(p.ImportPath, "/", "-", -1) + "-" + strings.Replace(file, ".", "-", -1) + ".so"
+}
+
+// swigDir returns the name of the shared SWIG directory for a
+// package.
+func (p *Package) swigDir(ctxt *build.Context) string {
+	dir := p.build.PkgRoot
+	if ctxt.Compiler == "gccgo" {
+		dir = filepath.Join(dir, "gccgo_"+ctxt.GOOS+"_"+ctxt.GOARCH)
+	} else {
+		dir = filepath.Join(dir, ctxt.GOOS+"_"+ctxt.GOARCH)
+	}
+	return filepath.Join(dir, "swig")
+}
+
 // packageList returns the list of packages in the dag rooted at roots
 // as visited in a depth-first post-order traversal.
 func packageList(roots []*Package) []*Package {
@@ -459,7 +543,7 @@ func isStale(p *Package, topRoot map[string]bool) bool {
 	// distributions of Go packages, although such binaries are
 	// only useful with the specific version of the toolchain that
 	// created them.
-	if len(p.gofiles) == 0 {
+	if len(p.gofiles) == 0 && !p.usesSwig() {
 		return false
 	}
 
@@ -491,14 +575,19 @@ func isStale(p *Package, topRoot map[string]bool) bool {
 	// As a courtesy to developers installing new versions of the compiler
 	// frequently, define that packages are stale if they are
 	// older than the compiler, and commands if they are older than
-	// the linker.  This heuristic will not work if the binaries are back-dated,
-	// as some binary distributions may do, but it does handle a very
-	// common case.  See issue 3036.
-	if olderThan(buildToolchain.compiler()) {
-		return true
-	}
-	if p.build.IsCommand() && olderThan(buildToolchain.linker()) {
-		return true
+	// the linker.  This heuristic will not work if the binaries are
+	// back-dated, as some binary distributions may do, but it does handle
+	// a very common case.
+	// See issue 3036.
+	// Assume code in $GOROOT is up to date, since it may not be writeable.
+	// See issue 4106.
+	if p.Root != goroot {
+		if olderThan(buildToolchain.compiler()) {
+			return true
+		}
+		if p.build.IsCommand() && olderThan(buildToolchain.linker()) {
+			return true
+		}
 	}
 
 	// Have installed copy, probably built using current compilers,
@@ -522,6 +611,21 @@ func isStale(p *Package, topRoot map[string]bool) bool {
 		}
 	}
 
+	for _, src := range stringList(p.SwigFiles, p.SwigCXXFiles) {
+		if olderThan(filepath.Join(p.Dir, src)) {
+			return true
+		}
+		soname := p.swigSoname(src)
+		fi, err := os.Stat(soname)
+		if err != nil {
+			return true
+		}
+		fiSrc, err := os.Stat(src)
+		if err != nil || fiSrc.ModTime().After(fi.ModTime()) {
+			return true
+		}
+	}
+
 	return false
 }
 
@@ -546,13 +650,24 @@ func loadPackage(arg string, stk *importStack) *Package {
 			arg = sub
 		}
 	}
-	if strings.HasPrefix(arg, "cmd/") && !strings.Contains(arg[4:], "/") {
+	if strings.HasPrefix(arg, "cmd/") {
 		if p := cmdCache[arg]; p != nil {
 			return p
 		}
 		stk.push(arg)
 		defer stk.pop()
-		bp, err := build.ImportDir(filepath.Join(gorootSrc, arg), 0)
+
+		if strings.Contains(arg[4:], "/") {
+			p := &Package{
+				Error: &PackageError{
+					ImportStack: stk.copy(),
+					Err:         fmt.Sprintf("invalid import path: cmd/... is reserved for Go commands"),
+				},
+			}
+			return p
+		}
+
+		bp, err := buildContext.ImportDir(filepath.Join(gorootSrc, arg), 0)
 		bp.ImportPath = arg
 		bp.Goroot = true
 		bp.BinDir = gorootBin
@@ -580,7 +695,7 @@ func loadPackage(arg string, stk *importStack) *Package {
 	// referring to io/ioutil rather than a hypothetical import of
 	// "./ioutil".
 	if build.IsLocalImport(arg) {
-		bp, _ := build.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
+		bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
 		if bp.ImportPath != "" && bp.ImportPath != "." {
 			arg = bp.ImportPath
 		}
@@ -621,10 +736,14 @@ func packagesAndErrors(args []string) []*Package {
 	args = importPaths(args)
 	var pkgs []*Package
 	var stk importStack
+	var set = make(map[string]bool)
+
 	for _, arg := range args {
-		pkgs = append(pkgs, loadPackage(arg, &stk))
+		if !set[arg] {
+			pkgs = append(pkgs, loadPackage(arg, &stk))
+			set[arg] = true
+		}
 	}
-
 	computeStale(pkgs...)
 
 	return pkgs
diff --git a/src/cmd/go/run.go b/src/cmd/go/run.go
index 6043b7e..b505693 100644
--- a/src/cmd/go/run.go
+++ b/src/cmd/go/run.go
@@ -34,6 +34,7 @@ func printStderr(args ...interface{}) (int, error) {
 }
 
 func runRun(cmd *Command, args []string) {
+	raceInit()
 	var b builder
 	b.init()
 	b.print = printStderr
@@ -45,6 +46,13 @@ func runRun(cmd *Command, args []string) {
 	if len(files) == 0 {
 		fatalf("go run: no go files listed")
 	}
+	for _, file := range files {
+		if strings.HasSuffix(file, "_test.go") {
+			// goFilesPackage is going to assign this to TestGoFiles.
+			// Reject since it won't be part of the build.
+			fatalf("go run: cannot run *_test.go files (%s)", file)
+		}
+	}
 	p := goFilesPackage(files)
 	if p.Error != nil {
 		fatalf("%s", p.Error)
@@ -57,6 +65,21 @@ func runRun(cmd *Command, args []string) {
 		fatalf("go run: cannot run non-main package")
 	}
 	p.target = "" // must build - not up to date
+	var src string
+	if len(p.GoFiles) > 0 {
+		src = p.GoFiles[0]
+	} else if len(p.CgoFiles) > 0 {
+		src = p.CgoFiles[0]
+	} else {
+		// this case could only happen if the provided source uses cgo
+		// while cgo is disabled.
+		hint := ""
+		if !buildContext.CgoEnabled {
+			hint = " (cgo is disabled)"
+		}
+		fatalf("go run: no suitable source files%s", hint)
+	}
+	p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file
 	a1 := b.action(modeBuild, modeBuild, p)
 	a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}}
 	b.do(a)
@@ -83,6 +106,7 @@ func runStdin(cmdargs ...interface{}) {
 	cmd.Stdin = os.Stdin
 	cmd.Stdout = os.Stdout
 	cmd.Stderr = os.Stderr
+	startSigHandlers()
 	if err := cmd.Run(); err != nil {
 		errorf("%v", err)
 	}
diff --git a/src/cmd/go/signal.go b/src/cmd/go/signal.go
new file mode 100644
index 0000000..e8ba0d3
--- /dev/null
+++ b/src/cmd/go/signal.go
@@ -0,0 +1,31 @@
+// 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 main
+
+import (
+	"os"
+	"os/signal"
+	"sync"
+)
+
+// interrupted is closed, if go process is interrupted.
+var interrupted = make(chan struct{})
+
+// processSignals setups signal handler.
+func processSignals() {
+	sig := make(chan os.Signal)
+	signal.Notify(sig, signalsToIgnore...)
+	go func() {
+		<-sig
+		close(interrupted)
+	}()
+}
+
+var onceProcessSignals sync.Once
+
+// startSigHandlers start signal handlers.
+func startSigHandlers() {
+	onceProcessSignals.Do(processSignals)
+}
diff --git a/src/cmd/go/signal_notunix.go b/src/cmd/go/signal_notunix.go
new file mode 100644
index 0000000..ef13c19
--- /dev/null
+++ b/src/cmd/go/signal_notunix.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 plan9 windows
+
+package main
+
+import (
+	"os"
+)
+
+var signalsToIgnore = []os.Signal{os.Interrupt}
diff --git a/src/cmd/go/signal_unix.go b/src/cmd/go/signal_unix.go
new file mode 100644
index 0000000..489a73b
--- /dev/null
+++ b/src/cmd/go/signal_unix.go
@@ -0,0 +1,14 @@
+// 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 freebsd linux netbsd openbsd
+
+package main
+
+import (
+	"os"
+	"syscall"
+)
+
+var signalsToIgnore = []os.Signal{os.Interrupt, syscall.SIGQUIT}
diff --git a/src/cmd/go/test.bash b/src/cmd/go/test.bash
index fe186d4..460061a 100755
--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -76,6 +76,12 @@ if ! ./testgo test ./testdata/testimport; then
 	ok=false
 fi
 
+# Test installation with relative imports.
+if ! ./testgo test -i ./testdata/testimport; then
+    echo "go test -i ./testdata/testimport failed"
+    ok=false
+fi
+
 # Test tests with relative imports in packages synthesized
 # from Go files named on the command line.
 if ! ./testgo test ./testdata/testimport/*.go; then
@@ -119,6 +125,208 @@ elif ! test -x testdata/bin1/helloworld; then
 	ok=false
 fi
 
+# Reject relative paths in GOPATH.
+if GOPATH=. ./testgo build testdata/src/go-cmd-test/helloworld.go; then
+    echo 'GOPATH="." go build should have failed, did not'
+    ok=false
+fi
+
+if GOPATH=:$(pwd)/testdata:. ./testgo build go-cmd-test; then
+    echo 'GOPATH=":$(pwd)/testdata:." go build should have failed, did not'
+    ok=false
+fi
+
+# issue 4104
+if [ $(./testgo test fmt fmt fmt fmt fmt | wc -l) -ne 1 ] ; then
+    echo 'go test fmt fmt fmt fmt fmt tested the same package multiple times'
+    ok=false
+fi
+
+# ensure that output of 'go list' is consistent between runs
+./testgo list std > test_std.list
+if ! ./testgo list std | cmp -s test_std.list - ; then
+	echo "go list std ordering is inconsistent"
+	ok=false
+fi
+rm -f test_std.list
+
+# issue 4096. Validate the output of unsucessful go install foo/quxx 
+if [ $(./testgo install 'foo/quxx' 2>&1 | grep -c 'cannot find package "foo/quxx" in any of') -ne 1 ] ; then
+	echo 'go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of'
+	ok=false
+fi 
+# test GOROOT search failure is reported
+if [ $(./testgo install 'foo/quxx' 2>&1 | egrep -c 'foo/quxx \(from \$GOROOT\)$') -ne 1 ] ; then
+        echo 'go install foo/quxx expected error: .*foo/quxx (from $GOROOT)'
+        ok=false
+fi
+# test multiple GOPATH entries are reported separately
+if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/./src/foo/quxx') -ne 2 ] ; then
+        echo 'go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx'
+        ok=false
+fi
+# test (from $GOPATH) annotation is reported for the first GOPATH entry
+if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/a/src/foo/quxx \(from \$GOPATH\)$') -ne 1 ] ; then
+        echo 'go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)'
+        ok=false
+fi
+# but not on the second
+if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/b/src/foo/quxx$') -ne 1 ] ; then
+        echo 'go install foo/quxx expected error: .*testdata/b/src/foo/quxx'
+        ok=false
+fi
+# test missing GOPATH is reported
+if [ $(GOPATH= ./testgo install 'foo/quxx' 2>&1 | egrep -c '\(\$GOPATH not set\)$') -ne 1 ] ; then
+        echo 'go install foo/quxx expected error: ($GOPATH not set)'
+        ok=false
+fi
+
+# issue 4186. go get cannot be used to download packages to $GOROOT
+# Test that without GOPATH set, go get should fail
+d=$(mktemp -d -t testgo)
+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'
+	ok=false
+fi	
+rm -rf $d
+# Test that with GOPATH=$GOROOT, go get should fail
+d=$(mktemp -d -t testgo)
+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'
+        ok=false
+fi
+rm -rf $d
+
+# issue 3941: args with spaces
+d=$(mktemp -d -t testgo)
+cat >$d/main.go<<EOF
+package main
+var extern string
+func main() {
+	println(extern)
+}
+EOF
+./testgo run -ldflags '-X main.extern "hello world"' $d/main.go 2>hello.out
+if ! grep -q '^hello world' hello.out; then
+	echo "ldflags -X main.extern 'hello world' failed. Output:"
+	cat hello.out
+	ok=false
+fi
+rm -rf $d
+
+# test that go test -cpuprofile leaves binary behind
+./testgo test -cpuprofile strings.prof strings || ok=false
+if [ ! -x strings.test ]; then
+	echo "go test -cpuprofile did not create strings.test"
+	ok=false
+fi
+rm -f strings.prof strings.test
+
+# issue 4568. test that symlinks don't screw things up too badly.
+old=$(pwd)
+d=$(mktemp -d -t testgo)
+mkdir -p $d/src
+(
+	ln -s $d $d/src/dir1
+	cd $d/src/dir1
+	echo package p >p.go
+	export GOPATH=$d
+	if [ "$($old/testgo list -f '{{.Root}}' .)" != "$d" ]; then
+		echo got lost in symlink tree:
+		pwd
+		env|grep WD
+		$old/testgo list -json . dir1
+		touch $d/failed
+	fi		
+)
+if [ -f $d/failed ]; then
+	ok=false
+fi
+rm -rf $d
+
+# issue 4515.
+d=$(mktemp -d -t testgo)
+mkdir -p $d/src/example/a $d/src/example/b $d/bin
+cat >$d/src/example/a/main.go <<EOF
+package main
+func main() {}
+EOF
+cat >$d/src/example/b/main.go <<EOF
+// +build mytag
+
+package main
+func main() {}
+EOF
+GOPATH=$d ./testgo install -tags mytag example/a example/b || ok=false
+if [ ! -x $d/bin/a -o ! -x $d/bin/b ]; then
+	echo go install example/a example/b did not install binaries
+	ok=false
+fi
+rm -f $d/bin/*
+GOPATH=$d ./testgo install -tags mytag example/... || ok=false
+if [ ! -x $d/bin/a -o ! -x $d/bin/b ]; then
+	echo go install example/... did not install binaries
+	ok=false
+fi
+rm -f $d/bin/*go
+export GOPATH=$d
+if [ "$(./testgo list -tags mytag example/b...)" != "example/b" ]; then
+	echo go list example/b did not find example/b
+	ok=false
+fi
+unset GOPATH
+rm -rf $d
+
+# issue 4773. case-insensitive collisions
+d=$(mktemp -d -t testgo)
+export GOPATH=$d
+mkdir -p $d/src/example/a $d/src/example/b
+cat >$d/src/example/a/a.go <<EOF
+package p
+import (
+	_ "math/rand"
+	_ "math/Rand"
+)
+EOF
+if ./testgo list example/a 2>$d/out; then
+	echo go list example/a should have failed, did not.
+	ok=false
+elif ! grep "case-insensitive import collision" $d/out >/dev/null; then
+	echo go list example/a did not report import collision.
+	ok=false
+fi
+cat >$d/src/example/b/file.go <<EOF
+package b
+EOF
+cat >$d/src/example/b/FILE.go <<EOF
+package b
+EOF
+if [ $(ls $d/src/example/b | wc -l) = 2 ]; then
+	# case-sensitive file system, let directory read find both files
+	args="example/b"
+else
+	# case-insensitive file system, list files explicitly on command line.
+	args="$d/src/example/b/file.go $d/src/example/b/FILE.go"
+fi
+if ./testgo list $args 2>$d/out; then
+	echo go list example/b should have failed, did not.
+	ok=false
+elif ! grep "case-insensitive file name collision" $d/out >/dev/null; then
+	echo go list example/b did not report file name collision.
+	ok=false
+fi
+unset GOPATH
+rm -rf $d
+
+# Only succeeds if source order is preserved.
+./testgo test testdata/example[12]_test.go
+
+# clean up
+rm -rf testdata/bin testdata/bin1
+rm -f testgo
+
 if $ok; then
 	echo PASS
 else
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index 870ab19..3132ab2 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -48,6 +48,7 @@ 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".  These additional files can contain test functions,
 benchmark functions, and example functions.  See 'go help testfunc' for more.
+Each listed package causes the execution of a separate test binary.
 
 By default, go test needs no arguments.  It compiles and tests the package
 with source in the current directory, including tests, and runs the tests.
@@ -80,28 +81,47 @@ var helpTestflag = &Command{
 The 'go test' command takes both flags that apply to 'go test' itself
 and flags that apply to the resulting test binary.
 
-The test binary, called pkg.test, where pkg is the name of the
-directory containing the package sources, has its own flags:
+The following flags are recognized by the 'go test' command and
+control the execution of any test:
 
-	-test.v
-	    Verbose output: log all tests as they are run.
-
-	-test.run pattern
-	    Run only those tests and examples matching the regular
-	    expression.
-
-	-test.bench pattern
+	-bench regexp
 	    Run benchmarks matching the regular expression.
-	    By default, no benchmarks run.
+	    By default, no benchmarks run. To run all benchmarks,
+	    use '-bench .' or '-bench=.'.
+
+	-benchmem
+	    Print memory allocation statistics for benchmarks.
+
+	-benchtime t
+		Run enough iterations of each benchmark to take t, specified
+		as a time.Duration (for example, -benchtime 1h30s).
+		The default is 1 second (1s).
+
+	-blockprofile block.out
+	    Write a goroutine blocking profile to the specified file
+	    when all tests are complete.
+
+	-blockprofilerate n
+	    Control the detail provided in goroutine blocking profiles by setting
+	    runtime.BlockProfileRate to n.  See 'godoc runtime BlockProfileRate'.
+	    The profiler aims to sample, on average, one blocking event every
+	    n nanoseconds the program spends blocked.  By default,
+	    if -test.blockprofile is set without this flag, all blocking events
+	    are recorded, equivalent to -test.blockprofilerate=1.
+
+	-cpu 1,2,4
+	    Specify a list of GOMAXPROCS values for which the tests or
+	    benchmarks should be executed.  The default is the current value
+	    of GOMAXPROCS.
 
-	-test.cpuprofile cpu.out
+	-cpuprofile cpu.out
 	    Write a CPU profile to the specified file before exiting.
 
-	-test.memprofile mem.out
+	-memprofile mem.out
 	    Write a memory profile to the specified file when all tests
 	    are complete.
 
-	-test.memprofilerate n
+	-memprofilerate n
 	    Enable more precise (and expensive) memory profiles by setting
 	    runtime.MemProfileRate.  See 'godoc runtime MemProfileRate'.
 	    To profile all memory allocations, use -test.memprofilerate=1
@@ -109,38 +129,46 @@ directory containing the package sources, has its own flags:
 	    garbage collector, provided the test can run in the available
 	    memory without garbage collection.
 
-	-test.parallel n
+	-parallel n
 	    Allow parallel execution of test functions that call t.Parallel.
 	    The value of this flag is the maximum number of tests to run
 	    simultaneously; by default, it is set to the value of GOMAXPROCS.
 
-	-test.short
+	-run regexp
+	    Run only those tests and examples matching the regular
+	    expression.
+
+	-short
 	    Tell long-running tests to shorten their run time.
 	    It is off by default but set during all.bash so that installing
 	    the Go tree can run a sanity check but not spend time running
 	    exhaustive tests.
 
-	-test.timeout t
+	-timeout t
 		If a test runs longer than t, panic.
 
-	-test.benchtime n
-		Run enough iterations of each benchmark to take n seconds.
-		The default is 1 second.
+	-v
+	    Verbose output: log all tests as they are run.
 
-	-test.cpu 1,2,4
-	    Specify a list of GOMAXPROCS values for which the tests or
-	    benchmarks should be executed.  The default is the current value
-	    of GOMAXPROCS.
+The test binary, called pkg.test where pkg is the name of the
+directory containing the package sources, can be invoked directly
+after building it with 'go test -c'. When invoking the test binary
+directly, each of the standard flag names must be prefixed with 'test.',
+as in -test.run=TestMyFunc or -test.v.
 
-For convenience, each of these -test.X flags of the test binary is
-also available as the flag -X in 'go test' itself.  Flags not listed
-here are passed through unaltered.  For instance, the command
+When running 'go test', flags not listed above are passed through
+unaltered. For instance, the command
 
 	go test -x -v -cpuprofile=prof.out -dir=testdata -update
 
 will compile the test binary and then run it as
 
 	pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update
+
+The test flags that generate profiles also leave the test binary in pkg.test
+for use when analyzing the profiles.
+
+Flags not recognized by 'go test' must be placed after any specified packages.
 `,
 }
 
@@ -160,8 +188,8 @@ A benchmark function is one named BenchmarkXXX and should have the signature,
 
 	func BenchmarkXXX(b *testing.B) { ... }
 
-An example function is similar to a test function but, instead of using *testing.T
-to report success or failure, prints output to os.Stdout and os.Stderr.
+An example function is similar to a test function but, instead of using
+*testing.T to report success or failure, prints output to os.Stdout.
 That output is compared against the function's "Output:" comment, which
 must be the last comment in the function body (see example below). An
 example with no such comment, or with no text after "Output:" is compiled
@@ -191,6 +219,7 @@ See the documentation of the testing package for more information.
 
 var (
 	testC            bool     // -c flag
+	testProfile      bool     // some profiling flag
 	testI            bool     // -i flag
 	testV            bool     // -v flag
 	testFiles        []string // -file flag(s)  TODO: not respected
@@ -207,6 +236,7 @@ func runTest(cmd *Command, args []string) {
 	var pkgArgs []string
 	pkgArgs, testArgs = testFlags(args)
 
+	raceInit()
 	pkgs := packagesForBuild(pkgArgs)
 	if len(pkgs) == 0 {
 		fatalf("no packages to test")
@@ -215,12 +245,15 @@ func runTest(cmd *Command, args []string) {
 	if testC && len(pkgs) != 1 {
 		fatalf("cannot use -c flag with multiple packages")
 	}
+	if testProfile && len(pkgs) != 1 {
+		fatalf("cannot use test profile flag with multiple packages")
+	}
 
 	// If a test timeout was given and is parseable, set our kill timeout
 	// to that timeout plus one minute.  This is a backup alarm in case
 	// the test wedges with a goroutine spinning and its background
 	// timer does not get a chance to fire.
-	if dt, err := time.ParseDuration(testTimeout); err == nil {
+	if dt, err := time.ParseDuration(testTimeout); err == nil && dt > 0 {
 		testKillTimeout = dt + 1*time.Minute
 	}
 
@@ -276,7 +309,9 @@ func runTest(cmd *Command, args []string) {
 
 		all := []string{}
 		for path := range deps {
-			all = append(all, path)
+			if !build.IsLocalImport(path) {
+				all = append(all, path)
+			}
 		}
 		sort.Strings(all)
 
@@ -361,7 +396,11 @@ func runTest(cmd *Command, args []string) {
 		if args != "" {
 			args = " " + args
 		}
-		fmt.Fprintf(os.Stderr, "installing these packages with 'go test -i%s' will speed future tests.\n\n", args)
+		extraOpts := ""
+		if buildRace {
+			extraOpts = "-race "
+		}
+		fmt.Fprintf(os.Stderr, "installing these packages with 'go test %s-i%s' will speed future tests.\n\n", extraOpts, args)
 	}
 
 	b.do(root)
@@ -405,7 +444,14 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
 
 	// Use last element of import path, not package name.
 	// They differ when package name is "main".
-	_, elem := path.Split(p.ImportPath)
+	// But if the import path is "command-line-arguments",
+	// like it is during 'go run', use the package name.
+	var elem string
+	if p.ImportPath == "command-line-arguments" {
+		elem = p.Name
+	} else {
+		_, elem = path.Split(p.ImportPath)
+	}
 	testBinary := elem + ".test"
 
 	// The ptest package needs to be importable under the
@@ -532,14 +578,17 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
 	a.target = filepath.Join(testDir, testBinary) + exeSuffix
 	pmainAction := a
 
-	if testC {
-		// -c flag: create action to copy binary to ./test.out.
+	if testC || testProfile {
+		// -c or profiling flag: create action to copy binary to ./test.out.
 		runAction = &action{
 			f:      (*builder).install,
 			deps:   []*action{pmainAction},
 			p:      pmain,
-			target: testBinary + exeSuffix,
+			target: filepath.Join(cwd, testBinary+exeSuffix),
 		}
+		pmainAction = runAction // in case we are running the test
+	}
+	if testC {
 		printAction = &action{p: p, deps: []*action{runAction}} // nop
 	} else {
 		// run test
@@ -586,6 +635,7 @@ func (b *builder) runTest(a *action) error {
 
 	cmd := exec.Command(args[0], args[1:]...)
 	cmd.Dir = a.p.Dir
+	cmd.Env = envForDir(cmd.Dir)
 	var buf bytes.Buffer
 	if testStreamOutput {
 		cmd.Stdout = os.Stdout
@@ -595,14 +645,34 @@ func (b *builder) runTest(a *action) error {
 		cmd.Stderr = &buf
 	}
 
+	// If there are any local SWIG dependencies, we want to load
+	// the shared library from the build directory.
+	if a.p.usesSwig() {
+		env := cmd.Env
+		found := false
+		prefix := "LD_LIBRARY_PATH="
+		for i, v := range env {
+			if strings.HasPrefix(v, prefix) {
+				env[i] = v + ":."
+				found = true
+				break
+			}
+		}
+		if !found {
+			env = append(env, "LD_LIBRARY_PATH=.")
+		}
+		cmd.Env = env
+	}
+
 	t0 := time.Now()
 	err := cmd.Start()
 
 	// This is a last-ditch deadline to detect and
 	// stop wedged test binaries, to keep the builders
 	// running.
-	tick := time.NewTimer(testKillTimeout)
 	if err == nil {
+		tick := time.NewTimer(testKillTimeout)
+		startSigHandlers()
 		done := make(chan error)
 		go func() {
 			done <- cmd.Wait()
@@ -613,13 +683,12 @@ func (b *builder) runTest(a *action) error {
 		case <-tick.C:
 			cmd.Process.Kill()
 			err = <-done
-			fmt.Fprintf(&buf, "*** Test killed: ran too long.\n")
+			fmt.Fprintf(&buf, "*** Test killed: ran too long (%v).\n", testKillTimeout)
 		}
 		tick.Stop()
 	}
 	out := buf.Bytes()
-	t1 := time.Now()
-	t := fmt.Sprintf("%.3fs", t1.Sub(t0).Seconds())
+	t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds())
 	if err == nil {
 		if testShowPass {
 			a.testOutput.Write(out)
@@ -750,8 +819,10 @@ func (t *testFuncs) load(filename, pkg string, seen *bool) error {
 			*seen = true
 		}
 	}
-	for _, e := range doc.Examples(f) {
-		if e.Output == "" {
+	ex := doc.Examples(f)
+	sort.Sort(byOrder(ex))
+	for _, e := range ex {
+		if e.Output == "" && !e.EmptyOutput {
 			// Don't run examples with no output.
 			continue
 		}
@@ -761,6 +832,12 @@ func (t *testFuncs) load(filename, pkg string, seen *bool) error {
 	return nil
 }
 
+type byOrder []*doc.Example
+
+func (x byOrder) Len() int           { return len(x) }
+func (x byOrder) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byOrder) Less(i, j int) bool { return x[i].Order < x[j].Order }
+
 var testmainTmpl = template.Must(template.New("main").Parse(`
 package main
 
diff --git a/src/cmd/go/testdata/example1_test.go b/src/cmd/go/testdata/example1_test.go
new file mode 100644
index 0000000..ec7092e
--- /dev/null
+++ b/src/cmd/go/testdata/example1_test.go
@@ -0,0 +1,23 @@
+// 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.
+
+// Make sure that go test runs Example_Z before Example_A, preserving source order.
+
+package p
+
+import "fmt"
+
+var n int
+
+func Example_Z() {
+	n++
+	fmt.Println(n)
+	// Output: 1
+}
+
+func Example_A() {
+	n++
+	fmt.Println(n)
+	// Output: 2
+}
diff --git a/src/cmd/go/testdata/example2_test.go b/src/cmd/go/testdata/example2_test.go
new file mode 100644
index 0000000..1e0e80b
--- /dev/null
+++ b/src/cmd/go/testdata/example2_test.go
@@ -0,0 +1,21 @@
+// 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.
+
+// Make sure that go test runs Example_Y before Example_B, preserving source order.
+
+package p
+
+import "fmt"
+
+func Example_Y() {
+	n++
+	fmt.Println(n)
+	// Output: 3
+}
+
+func Example_B() {
+	n++
+	fmt.Println(n)
+	// Output: 4
+}
diff --git a/src/cmd/go/testflag.go b/src/cmd/go/testflag.go
index ecf5bf4..b2ca66b 100644
--- a/src/cmd/go/testflag.go
+++ b/src/cmd/go/testflag.go
@@ -25,11 +25,14 @@ var usageMessage = `Usage of go test:
 
   // These flags can be passed with or without a "test." prefix: -v or -test.v.
   -bench="": passes -test.bench to test
-  -benchtime=1: passes -test.benchtime to test
+  -benchmem=false: print memory allocation statistics for benchmarks
+  -benchtime=1s: passes -test.benchtime to test
   -cpu="": passes -test.cpu to test
   -cpuprofile="": passes -test.cpuprofile to test
   -memprofile="": passes -test.memprofile to test
   -memprofilerate=0: passes -test.memprofilerate to test
+  -blockprofile="": pases -test.blockprofile to test
+  -blockprofilerate=0: passes -test.blockprofilerate to test
   -parallel=0: passes -test.parallel to test
   -run="": passes -test.run to test
   -short=false: passes -test.short to test
@@ -71,14 +74,18 @@ var testFlagDefn = []*testFlagSpec{
 	{name: "gccgoflags"},
 	{name: "tags"},
 	{name: "compiler"},
+	{name: "race", boolVar: &buildRace},
 
 	// passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
 	{name: "bench", passToTest: true},
+	{name: "benchmem", boolVar: new(bool), passToTest: true},
 	{name: "benchtime", passToTest: true},
 	{name: "cpu", passToTest: true},
 	{name: "cpuprofile", passToTest: true},
 	{name: "memprofile", passToTest: true},
 	{name: "memprofilerate", passToTest: true},
+	{name: "blockprofile", passToTest: true},
+	{name: "blockprofilerate", passToTest: true},
 	{name: "parallel", passToTest: true},
 	{name: "run", passToTest: true},
 	{name: "short", boolVar: new(bool), passToTest: true},
@@ -117,7 +124,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
 		f, value, extraWord := testFlag(args, i)
 		if f == nil {
 			// This is a flag we do not know; we must assume
-			// that any args we see after this might be flag 
+			// that any args we see after this might be flag
 			// arguments, not package names.
 			inPkg = false
 			if packageNames == nil {
@@ -127,18 +134,28 @@ func testFlags(args []string) (packageNames, passToTest []string) {
 			passToTest = append(passToTest, args[i])
 			continue
 		}
+		var err error
 		switch f.name {
 		// bool flags.
-		case "a", "c", "i", "n", "x", "v", "work":
+		case "a", "c", "i", "n", "x", "v", "work", "race":
 			setBoolFlag(f.boolVar, value)
 		case "p":
 			setIntFlag(&buildP, value)
 		case "gcflags":
-			buildGcflags = strings.Fields(value)
+			buildGcflags, err = splitQuotedFields(value)
+			if err != nil {
+				fatalf("invalid flag argument for -%s: %v", f.name, err)
+			}
 		case "ldflags":
-			buildLdflags = strings.Fields(value)
+			buildLdflags, err = splitQuotedFields(value)
+			if err != nil {
+				fatalf("invalid flag argument for -%s: %v", f.name, err)
+			}
 		case "gccgoflags":
-			buildGccgoflags = strings.Fields(value)
+			buildGccgoflags, err = splitQuotedFields(value)
+			if err != nil {
+				fatalf("invalid flag argument for -%s: %v", f.name, err)
+			}
 		case "tags":
 			buildContext.BuildTags = strings.Fields(value)
 		case "compiler":
@@ -150,6 +167,8 @@ func testFlags(args []string) (packageNames, passToTest []string) {
 			testBench = true
 		case "timeout":
 			testTimeout = value
+		case "blockprofile", "cpuprofile", "memprofile":
+			testProfile = true
 		}
 		if extraWord {
 			i++
@@ -176,9 +195,7 @@ func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool)
 	}
 	name := arg[1:]
 	// If there's already "test.", drop it for now.
-	if strings.HasPrefix(name, "test.") {
-		name = name[5:]
-	}
+	name = strings.TrimPrefix(name, "test.")
 	equals := strings.Index(name, "=")
 	if equals >= 0 {
 		value = name[equals+1:]
diff --git a/src/cmd/go/tool.go b/src/cmd/go/tool.go
index cb463a2..299b94c 100644
--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -47,7 +47,7 @@ const toolWindowsExtension = ".exe"
 
 func tool(name string) string {
 	p := filepath.Join(toolDir, name)
-	if toolIsWindows {
+	if toolIsWindows && name != "pprof" {
 		p += toolWindowsExtension
 	}
 	return p
@@ -76,6 +76,16 @@ func runTool(cmd *Command, args []string) {
 		setExitStatus(3)
 		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:], " "))
@@ -90,7 +100,14 @@ func runTool(cmd *Command, args []string) {
 	}
 	err := toolCmd.Run()
 	if err != nil {
-		fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
+		// Only print about the exit status if the command
+		// didn't even run (not an ExitError) or it didn't exit cleanly
+		// or we're printing command lines too (-x mode).
+		// Assume if command exited cleanly (even with non-zero status)
+		// it printed any messages it wanted to print.
+		if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || buildX {
+			fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
+		}
 		setExitStatus(1)
 		return
 	}
diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go
index 1c12167..b995794 100644
--- a/src/cmd/go/vcs.go
+++ b/src/cmd/go/vcs.go
@@ -81,7 +81,7 @@ var vcsHg = &vcsCmd{
 	tagSyncCmd:     "update -r {tag}",
 	tagSyncDefault: "update default",
 
-	scheme:  []string{"https", "http"},
+	scheme:  []string{"https", "http", "ssh"},
 	pingCmd: "identify {scheme}://{repo}",
 }
 
@@ -180,8 +180,17 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
 		args[i] = expand(m, arg)
 	}
 
+	_, err := exec.LookPath(v.cmd)
+	if err != nil {
+		fmt.Fprintf(os.Stderr,
+			"go: missing %s command. See http://golang.org/s/gogetcmd\n",
+			v.name)
+		return nil, err
+	}
+
 	cmd := exec.Command(v.cmd, args...)
 	cmd.Dir = dir
+	cmd.Env = envForDir(cmd.Dir)
 	if buildX {
 		fmt.Printf("cd %s\n", dir)
 		fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " "))
@@ -189,7 +198,7 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
 	var buf bytes.Buffer
 	cmd.Stdout = &buf
 	cmd.Stderr = &buf
-	err := cmd.Run()
+	err = cmd.Run()
 	out := buf.Bytes()
 	if err != nil {
 		if verbose || buildV {
diff --git a/src/cmd/go/version.go b/src/cmd/go/version.go
index 09e2f16..a41f4a7 100644
--- a/src/cmd/go/version.go
+++ b/src/cmd/go/version.go
@@ -21,5 +21,5 @@ func runVersion(cmd *Command, args []string) {
 		cmd.Usage()
 	}
 
-	fmt.Printf("go version %s\n", runtime.Version())
+	fmt.Printf("go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
 }
diff --git a/src/cmd/godoc/appinit.go b/src/cmd/godoc/appinit.go
index 70da001..996b2b8 100644
--- a/src/cmd/godoc/appinit.go
+++ b/src/cmd/godoc/appinit.go
@@ -17,9 +17,12 @@ import (
 )
 
 func serveError(w http.ResponseWriter, r *http.Request, relpath string, err error) {
-	contents := applyTemplate(errorHTML, "errorHTML", err) // err may contain an absolute path!
 	w.WriteHeader(http.StatusNotFound)
-	servePage(w, relpath, "File "+relpath, "", "", contents)
+	servePage(w, Page{
+		Title:    "File " + relpath,
+		Subtitle: relpath,
+		Body:     applyTemplate(errorHTML, "errorHTML", err), // err may contain an absolute path!
+	})
 }
 
 func init() {
@@ -34,6 +37,7 @@ func init() {
 	*indexFiles = indexFilenames
 	*maxResults = 100    // reduce latency by limiting the number of fulltext search results
 	*indexThrottle = 0.3 // in case *indexFiles is empty (and thus the indexer is run)
+	*showPlayground = true
 
 	// read .zip file and set up file systems
 	const zipfile = zipFilename
@@ -48,6 +52,7 @@ func init() {
 	readTemplates()
 	initHandlers()
 	registerPublicHandlers(http.DefaultServeMux)
+	registerPlaygroundHandlers(http.DefaultServeMux)
 
 	// initialize default directory tree with corresponding timestamp.
 	initFSTree()
diff --git a/src/cmd/godoc/codewalk.go b/src/cmd/godoc/codewalk.go
index f7f51d0..e68c0fa 100644
--- a/src/cmd/godoc/codewalk.go
+++ b/src/cmd/godoc/codewalk.go
@@ -68,8 +68,11 @@ func codewalk(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	b := applyTemplate(codewalkHTML, "codewalk", cw)
-	servePage(w, cw.Title, "Codewalk: "+cw.Title, "", "", b)
+	servePage(w, Page{
+		Title:    "Codewalk: " + cw.Title,
+		Tabtitle: cw.Title,
+		Body:     applyTemplate(codewalkHTML, "codewalk", cw),
+	})
 }
 
 // A Codewalk represents a single codewalk read from an XML file.
@@ -199,8 +202,10 @@ func codewalkDir(w http.ResponseWriter, r *http.Request, relpath, abspath string
 		}
 	}
 
-	b := applyTemplate(codewalkdirHTML, "codewalkdir", v)
-	servePage(w, "", "Codewalks", "", "", b)
+	servePage(w, Page{
+		Title: "Codewalks",
+		Body:  applyTemplate(codewalkdirHTML, "codewalkdir", v),
+	})
 }
 
 // codewalkFileprint serves requests with ?fileprint=f&lo=lo&hi=hi.
diff --git a/src/cmd/godoc/dirtrees.go b/src/cmd/godoc/dirtrees.go
index b9b529f..fda7adc 100644
--- a/src/cmd/godoc/dirtrees.go
+++ b/src/cmd/godoc/dirtrees.go
@@ -74,7 +74,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
 	// determine number of subdirectories and if there are package files
 	ndirs := 0
 	hasPkgFiles := false
-	var synopses [4]string // prioritized package documentation (0 == highest priority)
+	var synopses [3]string // prioritized package documentation (0 == highest priority)
 	for _, d := range list {
 		switch {
 		case isPkgDir(d):
@@ -95,12 +95,10 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
 						switch file.Name.Name {
 						case name:
 							i = 0 // normal case: directory name matches package name
-						case fakePkgName:
-							i = 1 // synopses for commands
 						case "main":
-							i = 2 // directory contains a main package
+							i = 1 // directory contains a main package
 						default:
-							i = 3 // none of the above
+							i = 2 // none of the above
 						}
 						if 0 <= i && i < len(synopses) && synopses[i] == "" {
 							synopses[i] = doc.Synopsis(file.Doc.Text())
@@ -229,9 +227,7 @@ func (dir *Directory) lookupLocal(name string) *Directory {
 }
 
 func splitPath(p string) []string {
-	if strings.HasPrefix(p, "/") {
-		p = p[1:]
-	}
+	p = strings.TrimPrefix(p, "/")
 	if p == "" {
 		return nil
 	}
@@ -264,7 +260,7 @@ type DirEntry struct {
 	Height   int    // = DirList.MaxHeight - Depth, > 0
 	Path     string // directory path; includes Name, relative to DirList root
 	Name     string // directory name
-	HasPkg   bool   // true if the directory contains at least one package 
+	HasPkg   bool   // true if the directory contains at least one package
 	Synopsis string // package documentation, if any
 }
 
@@ -310,14 +306,9 @@ func (root *Directory) listing(skipRoot bool) *DirList {
 		// the path is relative to root.Path - remove the root.Path
 		// prefix (the prefix should always be present but avoid
 		// crashes and check)
-		path := d.Path
-		if strings.HasPrefix(d.Path, root.Path) {
-			path = d.Path[len(root.Path):]
-		}
+		path := strings.TrimPrefix(d.Path, root.Path)
 		// remove leading separator if any - path must be relative
-		if len(path) > 0 && path[0] == '/' {
-			path = path[1:]
-		}
+		path = strings.TrimPrefix(path, "/")
 		p.Path = path
 		p.Name = d.Name
 		p.HasPkg = d.HasPkg
diff --git a/src/cmd/godoc/doc.go b/src/cmd/godoc/doc.go
index 39ecc6e..ddb6d26 100644
--- a/src/cmd/godoc/doc.go
+++ b/src/cmd/godoc/doc.go
@@ -67,8 +67,6 @@ The flags are:
 	-maxresults=10000
 		maximum number of full text search results shown
 		(no full text index is built if maxresults <= 0)
-	-path=""
-		additional package directories (colon-separated)
 	-html
 		print HTML in command-line mode
 	-goroot=$GOROOT
@@ -88,20 +86,8 @@ The flags are:
 		zip file providing the file system to serve; disabled if empty
 
 By default, godoc looks at the packages it finds via $GOROOT and $GOPATH (if set).
-Additional directories may be specified via the -path flag which accepts a list
-of colon-separated paths; unrooted paths are relative to the current working
-directory. Each path is considered as an additional root for packages in order
-of appearance. The last (absolute) path element is the prefix for the package
-path. For instance, given the flag value:
-
-	path=".:/home/bar:/public"
-
-for a godoc started in /home/user/godoc, absolute paths are mapped to package paths
-as follows:
-
-	/home/user/godoc/x -> godoc/x
-	/home/bar/x        -> bar/x
-	/public/x          -> public/x
+This behavior can be altered by providing an alternative $GOROOT with the -goroot
+flag.
 
 When godoc runs as a web server and -index is set, a search index is maintained.
 The index is created at startup.
@@ -141,4 +127,4 @@ See "Godoc: documenting Go code" for how to write good comments for godoc:
 http://golang.org/doc/articles/godoc_documenting_go_code.html
 
 */
-package documentation
+package main
diff --git a/src/cmd/godoc/filesystem.go b/src/cmd/godoc/filesystem.go
index 09d7b24..0309d7c 100644
--- a/src/cmd/godoc/filesystem.go
+++ b/src/cmd/godoc/filesystem.go
@@ -41,7 +41,7 @@ import (
 // paths can assume they are slash-separated and should be using
 // package path (often imported as pathpkg) to manipulate them,
 // even on Windows.
-// 
+//
 var fs = nameSpace{} // the underlying file system for godoc
 
 // Setting debugNS = true will enable debugging prints about
@@ -138,7 +138,7 @@ func hasPathPrefix(x, y string) bool {
 // but we want to be able to mount multiple file systems on a single
 // mount point and have the system behave as if the union of those
 // file systems were present at the mount point.
-// For example, if the OS file system has a Go installation in 
+// For example, if the OS file system has a Go installation in
 // c:\Go and additional Go path trees in  d:\Work1 and d:\Work2, then
 // this name space creates the view we want for the godoc server:
 //
@@ -179,7 +179,7 @@ func hasPathPrefix(x, y string) bool {
 //	OS(`d:\Work1').ReadDir("/src/code")
 //	OS(`d:\Work2').ReadDir("/src/code")
 //
-// Note that the "/src/pkg" in "/src/pkg/code" has been replaced by 
+// Note that the "/src/pkg" in "/src/pkg/code" has been replaced by
 // just "/src" in the final two calls.
 //
 // OS is itself an implementation of a file system: it implements
@@ -459,9 +459,7 @@ func (ns nameSpace) ReadDir(path string) ([]os.FileInfo, error) {
 		if hasPathPrefix(old, path) && old != path {
 			// Find next element after path in old.
 			elem := old[len(path):]
-			if strings.HasPrefix(elem, "/") {
-				elem = elem[1:]
-			}
+			elem = strings.TrimPrefix(elem, "/")
 			if i := strings.Index(elem, "/"); i >= 0 {
 				elem = elem[:i]
 			}
diff --git a/src/cmd/godoc/format.go b/src/cmd/godoc/format.go
index 3b1b9a8..122ddc7 100644
--- a/src/cmd/godoc/format.go
+++ b/src/cmd/godoc/format.go
@@ -54,6 +54,8 @@ type SegmentWriter func(w io.Writer, text []byte, selections int)
 // Selection is ignored.
 //
 func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection, sw SegmentWriter, selections ...Selection) {
+	// If we have a link writer, make the links
+	// selection the last entry in selections
 	if lw != nil {
 		selections = append(selections, links)
 	}
@@ -108,8 +110,8 @@ func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection,
 			break
 		}
 		// determine the kind of segment change
-		if index == len(selections)-1 {
-			// we have a link segment change:
+		if lw != nil && index == len(selections)-1 {
+			// we have a link segment change (see start of this function):
 			// format the previous selection segment, write the
 			// link tag and start a new selection segment
 			segment(offs)
@@ -119,7 +121,7 @@ func FormatSelections(w io.Writer, text []byte, lw LinkWriter, links Selection,
 		} else {
 			// we have a selection change:
 			// format the previous selection segment, determine
-			// the new selection bitset and start a new segment 
+			// the new selection bitset and start a new segment
 			segment(offs)
 			lastOffs = offs
 			mask := 1 << uint(index)
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index f6dc678..872b0dc 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -12,8 +12,10 @@ import (
 	"go/ast"
 	"go/build"
 	"go/doc"
+	"go/format"
 	"go/printer"
 	"go/token"
+	htmlpkg "html"
 	"io"
 	"io/ioutil"
 	"log"
@@ -57,12 +59,13 @@ var (
 	// TODO(gri) consider the invariant that goroot always end in '/'
 	goroot  = flag.String("goroot", runtime.GOROOT(), "Go root directory")
 	testDir = flag.String("testdir", "", "Go root subdirectory - for testing only (faster startups)")
-	pkgPath = flag.String("path", "", "additional package directories (colon-separated)")
 
 	// layout control
 	tabwidth       = flag.Int("tabwidth", 4, "tab width")
 	showTimestamps = flag.Bool("timestamps", false, "show timestamps with directory listings")
 	templateDir    = flag.String("templates", "", "directory containing alternate template files")
+	showPlayground = flag.Bool("play", false, "enable playground in web interface")
+	showExamples   = flag.Bool("ex", false, "show examples in command line mode")
 
 	// search index
 	indexEnabled = flag.Bool("index", false, "enable search index")
@@ -80,22 +83,19 @@ var (
 	fileServer http.Handler // default file server
 	cmdHandler docServer
 	pkgHandler docServer
+
+	// which code 'Notes' to show
+	notes = flag.String("notes", "BUG", "comma separated list of Note markers as per pkg:go/doc")
+	// list of 'Notes' to show
+	notesToShow []string
 )
 
 func initHandlers() {
-	// Add named directories in -path argument as
-	// subdirectories of src/pkg.
-	for _, p := range filepath.SplitList(*pkgPath) {
-		_, elem := filepath.Split(p)
-		if elem == "" {
-			log.Fatalf("invalid -path argument: %q has no final element", p)
-		}
-		fs.Bind("/src/pkg/"+elem, OS(p), "/", bindReplace)
-	}
+	notesToShow = strings.Split(*notes, ",")
 
 	fileServer = http.FileServer(&httpFS{fs})
-	cmdHandler = docServer{"/cmd/", "/src/cmd", false}
-	pkgHandler = docServer{"/pkg/", "/src/pkg", true}
+	cmdHandler = docServer{"/cmd/", "/src/cmd"}
+	pkgHandler = docServer{"/pkg/", "/src/pkg"}
 }
 
 func registerPublicHandlers(mux *http.ServeMux) {
@@ -326,18 +326,62 @@ func startsWithUppercase(s string) bool {
 
 var exampleOutputRx = regexp.MustCompile(`(?i)//[[:space:]]*output:`)
 
-func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.FileSet) string {
+// stripExampleSuffix strips lowercase braz in Foo_braz or Foo_Bar_braz from name
+// while keeping uppercase Braz in Foo_Braz.
+func stripExampleSuffix(name string) string {
+	if i := strings.LastIndex(name, "_"); i != -1 {
+		if i < len(name)-1 && !startsWithUppercase(name[i+1:]) {
+			name = name[:i]
+		}
+	}
+	return name
+}
+
+func example_textFunc(funcName string, examples []*doc.Example, fset *token.FileSet, indent string) string {
+	if !*showExamples {
+		return ""
+	}
+
 	var buf bytes.Buffer
+	first := true
 	for _, eg := range examples {
-		name := eg.Name
+		name := stripExampleSuffix(eg.Name)
+		if name != funcName {
+			continue
+		}
 
-		// strip lowercase braz in Foo_braz or Foo_Bar_braz from name
-		// while keeping uppercase Braz in Foo_Braz
-		if i := strings.LastIndex(name, "_"); i != -1 {
-			if i < len(name)-1 && !startsWithUppercase(name[i+1:]) {
-				name = name[:i]
-			}
+		if !first {
+			buf.WriteString("\n")
 		}
+		first = false
+
+		// print code
+		cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
+		var buf1 bytes.Buffer
+		writeNode(&buf1, fset, cnode)
+		code := buf1.String()
+		// Additional formatting if this is a function body.
+		if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
+			// remove surrounding braces
+			code = code[1 : n-1]
+			// unindent
+			code = strings.Replace(code, "\n    ", "\n", -1)
+		}
+		code = strings.Trim(code, "\n")
+		code = strings.Replace(code, "\n", "\n\t", -1)
+
+		buf.WriteString(indent)
+		buf.WriteString("Example:\n\t")
+		buf.WriteString(code)
+		buf.WriteString("\n")
+	}
+	return buf.String()
+}
+
+func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.FileSet) string {
+	var buf bytes.Buffer
+	for _, eg := range examples {
+		name := stripExampleSuffix(eg.Name)
 
 		if name != funcName {
 			continue
@@ -347,9 +391,11 @@ func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.File
 		cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
 		code := node_htmlFunc(cnode, fset)
 		out := eg.Output
+		wholeFile := true
 
-		// additional formatting if this is a function body
+		// Additional formatting if this is a function body.
 		if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
+			wholeFile = false
 			// remove surrounding braces
 			code = code[1 : n-1]
 			// unindent
@@ -358,14 +404,28 @@ func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.File
 			if loc := exampleOutputRx.FindStringIndex(code); loc != nil {
 				code = strings.TrimSpace(code[:loc[0]])
 			}
-		} else {
-			// drop output, as the output comment will appear in the code
+		}
+
+		// Write out the playground code in standard Go style
+		// (use tabs, no comment highlight, etc).
+		play := ""
+		if eg.Play != nil && *showPlayground {
+			var buf bytes.Buffer
+			if err := format.Node(&buf, fset, eg.Play); err != nil {
+				log.Print(err)
+			} else {
+				play = buf.String()
+			}
+		}
+
+		// Drop output, as the output comment will appear in the code.
+		if wholeFile && play == "" {
 			out = ""
 		}
 
 		err := exampleHTML.Execute(&buf, struct {
-			Name, Doc, Code, Output string
-		}{eg.Name, eg.Doc, code, out})
+			Name, Doc, Code, Play, Output string
+		}{eg.Name, eg.Doc, code, play, out})
 		if err != nil {
 			log.Print(err)
 		}
@@ -393,6 +453,10 @@ func example_suffixFunc(name string) string {
 	return suffix
 }
 
+func noteTitle(note string) string {
+	return strings.Title(strings.ToLower(note))
+}
+
 func splitExampleName(s string) (name, suffix string) {
 	i := strings.LastIndex(s, "_")
 	if 0 <= i && i < len(s)-1 && !startsWithUppercase(s[i+1:]) {
@@ -408,9 +472,7 @@ func pkgLinkFunc(path string) string {
 	relpath := path[1:]
 	// because of the irregular mapping under goroot
 	// we need to correct certain relative paths
-	if strings.HasPrefix(relpath, "src/pkg/") {
-		relpath = relpath[len("src/pkg/"):]
-	}
+	relpath = strings.TrimPrefix(relpath, "src/pkg/")
 	return pkgHandler.pattern[1:] + relpath // remove trailing '/' for relative URL
 }
 
@@ -485,8 +547,12 @@ var fmap = template.FuncMap{
 
 	// formatting of Examples
 	"example_html":   example_htmlFunc,
+	"example_text":   example_textFunc,
 	"example_name":   example_nameFunc,
 	"example_suffix": example_suffixFunc,
+
+	// formatting of Notes
+	"noteTitle": noteTitle,
 }
 
 func readTemplate(name string) *template.Template {
@@ -538,31 +604,28 @@ func readTemplates() {
 // ----------------------------------------------------------------------------
 // Generic HTML wrapper
 
-func servePage(w http.ResponseWriter, tabtitle, title, subtitle, query string, content []byte) {
-	if tabtitle == "" {
-		tabtitle = title
-	}
-	d := struct {
-		Tabtitle  string
-		Title     string
-		Subtitle  string
-		SearchBox bool
-		Query     string
-		Version   string
-		Menu      []byte
-		Content   []byte
-	}{
-		tabtitle,
-		title,
-		subtitle,
-		*indexEnabled,
-		query,
-		runtime.Version(),
-		nil,
-		content,
-	}
-
-	if err := godocHTML.Execute(w, &d); err != nil {
+// Page describes the contents of the top-level godoc webpage.
+type Page struct {
+	Title    string
+	Tabtitle string
+	Subtitle string
+	Query    string
+	Body     []byte
+
+	// filled in by servePage
+	SearchBox  bool
+	Playground bool
+	Version    string
+}
+
+func servePage(w http.ResponseWriter, page Page) {
+	if page.Tabtitle == "" {
+		page.Tabtitle = page.Title
+	}
+	page.SearchBox = *indexEnabled
+	page.Playground = *showPlayground
+	page.Version = runtime.Version()
+	if err := godocHTML.Execute(w, page); err != nil {
 		log.Printf("godocHTML.Execute: %s", err)
 	}
 }
@@ -627,7 +690,11 @@ func serveHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath strin
 		src = buf.Bytes()
 	}
 
-	servePage(w, "", meta.Title, meta.Subtitle, "", src)
+	servePage(w, Page{
+		Title:    meta.Title,
+		Subtitle: meta.Subtitle,
+		Body:     src,
+	})
 }
 
 func applyTemplate(t *template.Template, name string, data interface{}) []byte {
@@ -640,11 +707,25 @@ func applyTemplate(t *template.Template, name string, data interface{}) []byte {
 
 func redirect(w http.ResponseWriter, r *http.Request) (redirected bool) {
 	canonical := pathpkg.Clean(r.URL.Path)
-	if !strings.HasSuffix("/", canonical) {
+	if !strings.HasSuffix(canonical, "/") {
 		canonical += "/"
 	}
 	if r.URL.Path != canonical {
-		http.Redirect(w, r, canonical, http.StatusMovedPermanently)
+		url := *r.URL
+		url.Path = canonical
+		http.Redirect(w, r, url.String(), http.StatusMovedPermanently)
+		redirected = true
+	}
+	return
+}
+
+func redirectFile(w http.ResponseWriter, r *http.Request) (redirected bool) {
+	c := pathpkg.Clean(r.URL.Path)
+	c = strings.TrimRight(c, "/")
+	if r.URL.Path != c {
+		url := *r.URL
+		url.Path = c
+		http.Redirect(w, r, url.String(), http.StatusMovedPermanently)
 		redirected = true
 	}
 	return
@@ -658,12 +739,22 @@ func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, tit
 		return
 	}
 
+	if r.FormValue("m") == "text" {
+		serveText(w, src)
+		return
+	}
+
 	var buf bytes.Buffer
 	buf.WriteString("<pre>")
 	FormatText(&buf, src, 1, pathpkg.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s")))
 	buf.WriteString("</pre>")
+	fmt.Fprintf(&buf, `<p><a href="/%s?m=text">View as plain text</a></p>`, htmlpkg.EscapeString(relpath))
 
-	servePage(w, relpath, title+" "+relpath, "", "", buf.Bytes())
+	servePage(w, Page{
+		Title:    title + " " + relpath,
+		Tabtitle: relpath,
+		Body:     buf.Bytes(),
+	})
 }
 
 func serveDirectory(w http.ResponseWriter, r *http.Request, abspath, relpath string) {
@@ -677,8 +768,11 @@ func serveDirectory(w http.ResponseWriter, r *http.Request, abspath, relpath str
 		return
 	}
 
-	contents := applyTemplate(dirlistHTML, "dirlistHTML", list)
-	servePage(w, relpath, "Directory "+relpath, "", "", contents)
+	servePage(w, Page{
+		Title:    "Directory " + relpath,
+		Tabtitle: relpath,
+		Body:     applyTemplate(dirlistHTML, "dirlistHTML", list),
+	})
 }
 
 func serveFile(w http.ResponseWriter, r *http.Request) {
@@ -734,6 +828,9 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
 	}
 
 	if isTextFile(abspath) {
+		if redirectFile(w, r) {
+			return
+		}
 		serveTextFile(w, r, abspath, relpath, "Text file")
 		return
 	}
@@ -754,10 +851,6 @@ func serveSearchDesc(w http.ResponseWriter, r *http.Request) {
 // ----------------------------------------------------------------------------
 // Packages
 
-// Fake package file and name for commands. Contains the command documentation.
-const fakePkgFile = "doc.go"
-const fakePkgName = "documentation"
-
 // Fake relative package path for built-ins. Documentation for all globals
 // (not just exported ones) will be shown for packages in this directory.
 const builtinPkgPath = "builtin"
@@ -814,17 +907,21 @@ func remoteSearchURL(query string, html bool) string {
 }
 
 type PageInfo struct {
-	Dirname  string         // directory containing the package
-	PList    []string       // list of package names found
-	FSet     *token.FileSet // corresponding file set
-	PAst     *ast.File      // nil if no single AST with package exports
-	PDoc     *doc.Package   // nil if no single package documentation
-	Examples []*doc.Example // nil if no example code
-	Dirs     *DirList       // nil if no directory information
-	DirTime  time.Time      // directory time stamp
-	DirFlat  bool           // if set, show directory in a flat (non-indented) manner
-	IsPkg    bool           // false if this is not documenting a real package
-	Err      error          // I/O error or nil
+	Dirname string // directory containing the package
+	Err     error  // error or nil
+
+	// package info
+	FSet     *token.FileSet      // nil if no package documentation
+	PDoc     *doc.Package        // nil if no package documentation
+	Examples []*doc.Example      // nil if no example code
+	Notes    map[string][]string // nil if no package Notes
+	PAst     *ast.File           // nil if no AST with package exports
+	IsMain   bool                // true for package main
+
+	// directory info
+	Dirs    *DirList  // nil if no directory information
+	DirTime time.Time // directory time stamp
+	DirFlat bool      // if set, show directory in a flat (non-indented) manner
 }
 
 func (info *PageInfo) IsEmpty() bool {
@@ -834,30 +931,97 @@ func (info *PageInfo) IsEmpty() bool {
 type docServer struct {
 	pattern string // url pattern; e.g. "/pkg/"
 	fsRoot  string // file system root to which the pattern is mapped
-	isPkg   bool   // true if this handler serves real package documentation (as opposed to command documentation)
 }
 
 // fsReadDir implements ReadDir for the go/build package.
 func fsReadDir(dir string) ([]os.FileInfo, error) {
-	return fs.ReadDir(dir)
+	return fs.ReadDir(filepath.ToSlash(dir))
 }
 
 // fsOpenFile implements OpenFile for the go/build package.
 func fsOpenFile(name string) (r io.ReadCloser, err error) {
-	data, err := ReadFile(fs, name)
+	data, err := ReadFile(fs, filepath.ToSlash(name))
 	if err != nil {
 		return nil, err
 	}
 	return ioutil.NopCloser(bytes.NewReader(data)), nil
 }
 
-func inList(name string, list []string) bool {
-	for _, l := range list {
-		if name == l {
-			return true
+// packageExports is a local implementation of ast.PackageExports
+// which correctly updates each package file's comment list.
+// (The ast.PackageExports signature is frozen, hence the local
+// implementation).
+//
+func packageExports(fset *token.FileSet, pkg *ast.Package) {
+	for _, src := range pkg.Files {
+		cmap := ast.NewCommentMap(fset, src, src.Comments)
+		ast.FileExports(src)
+		src.Comments = cmap.Filter(src).Comments()
+	}
+}
+
+// addNames adds the names declared by decl to the names set.
+// Method names are added in the form ReceiverTypeName_Method.
+func addNames(names map[string]bool, decl ast.Decl) {
+	switch d := decl.(type) {
+	case *ast.FuncDecl:
+		name := d.Name.Name
+		if d.Recv != nil {
+			var typeName string
+			switch r := d.Recv.List[0].Type.(type) {
+			case *ast.StarExpr:
+				typeName = r.X.(*ast.Ident).Name
+			case *ast.Ident:
+				typeName = r.Name
+			}
+			name = typeName + "_" + name
+		}
+		names[name] = true
+	case *ast.GenDecl:
+		for _, spec := range d.Specs {
+			switch s := spec.(type) {
+			case *ast.TypeSpec:
+				names[s.Name.Name] = true
+			case *ast.ValueSpec:
+				for _, id := range s.Names {
+					names[id.Name] = true
+				}
+			}
+		}
+	}
+}
+
+// globalNames returns a set of the names declared by all package-level
+// declarations. Method names are returned in the form Receiver_Method.
+func globalNames(pkg *ast.Package) map[string]bool {
+	names := make(map[string]bool)
+	for _, file := range pkg.Files {
+		for _, decl := range file.Decls {
+			addNames(names, decl)
 		}
 	}
-	return false
+	return names
+}
+
+// collectExamples collects examples for pkg from testfiles.
+func collectExamples(pkg *ast.Package, testfiles map[string]*ast.File) []*doc.Example {
+	var files []*ast.File
+	for _, f := range testfiles {
+		files = append(files, f)
+	}
+
+	var examples []*doc.Example
+	globals := globalNames(pkg)
+	for _, e := range doc.Examples(files...) {
+		name := stripExampleSuffix(e.Name)
+		if name == "" || globals[name] {
+			examples = append(examples, e)
+		} else {
+			log.Printf("skipping example 'Example%s' because '%s' is not a known function or type", e.Name, e.Name)
+		}
+	}
+
+	return examples
 }
 
 // getPageInfo returns the PageInfo for a package directory abspath. If the
@@ -865,132 +1029,56 @@ func inList(name string, list []string) bool {
 // computed (PageInfo.PAst), otherwise package documentation (PageInfo.Doc)
 // is extracted from the AST. If there is no corresponding package in the
 // directory, PageInfo.PAst and PageInfo.PDoc are nil. If there are no sub-
-// directories, PageInfo.Dirs is nil. If a directory read error occurred,
-// PageInfo.Err is set to the respective error but the error is not logged.
+// directories, PageInfo.Dirs is nil. If an error occurred, PageInfo.Err is
+// set to the respective error but the error is not logged.
 //
-func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoMode) PageInfo {
-	var pkgFiles []string
+func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) (info PageInfo) {
+	info.Dirname = abspath
 
-	// If we're showing the default package, restrict to the ones
-	// that would be used when building the package on this
-	// system.  This makes sure that if there are separate
-	// implementations for, say, Windows vs Unix, we don't
+	// Restrict to the package files that would be used when building
+	// the package on this system.  This makes sure that if there are
+	// separate implementations for, say, Windows vs Unix, we don't
 	// jumble them all together.
-	if pkgname == "" {
-		// Note: Uses current binary's GOOS/GOARCH.
-		// To use different pair, such as if we allowed the user
-		// to choose, set ctxt.GOOS and ctxt.GOARCH before
-		// calling ctxt.ScanDir.
-		ctxt := build.Default
-		ctxt.IsAbsPath = pathpkg.IsAbs
-		ctxt.ReadDir = fsReadDir
-		ctxt.OpenFile = fsOpenFile
-		dir, err := ctxt.ImportDir(abspath, 0)
-		if err == nil {
-			pkgFiles = append(dir.GoFiles, dir.CgoFiles...)
-		}
-	}
-
-	// filter function to select the desired .go files
-	filter := func(d os.FileInfo) bool {
-		// Only Go files.
-		if !isPkgFile(d) {
-			return false
-		}
-		// If we are looking at cmd documentation, only accept
-		// the special fakePkgFile containing the documentation.
-		if !h.isPkg {
-			return d.Name() == fakePkgFile
-		}
-		// Also restrict file list to pkgFiles.
-		return pkgFiles == nil || inList(d.Name(), pkgFiles)
-	}
-
-	// get package ASTs
-	fset := token.NewFileSet()
-	pkgs, err := parseDir(fset, abspath, filter)
-	if err != nil && pkgs == nil {
-		// only report directory read errors, ignore parse errors
-		// (may be able to extract partial package information)
-		return PageInfo{Dirname: abspath, Err: err}
-	}
-
-	// select package
-	var pkg *ast.Package // selected package
-	var plist []string   // list of other package (names), if any
-	if len(pkgs) == 1 {
-		// Exactly one package - select it.
-		for _, p := range pkgs {
-			pkg = p
-		}
-
-	} else if len(pkgs) > 1 {
-		// Multiple packages - select the best matching package: The
-		// 1st choice is the package with pkgname, the 2nd choice is
-		// the package with dirname, and the 3rd choice is a package
-		// that is not called "main" if there is exactly one such
-		// package. Otherwise, don't select a package.
-		dirpath, dirname := pathpkg.Split(abspath)
-
-		// If the dirname is "go" we might be in a sub-directory for
-		// .go files - use the outer directory name instead for better
-		// results.
-		if dirname == "go" {
-			_, dirname = pathpkg.Split(pathpkg.Clean(dirpath))
-		}
-
-		var choice3 *ast.Package
-	loop:
-		for _, p := range pkgs {
-			switch {
-			case p.Name == pkgname:
-				pkg = p
-				break loop // 1st choice; we are done
-			case p.Name == dirname:
-				pkg = p // 2nd choice
-			case p.Name != "main":
-				choice3 = p
-			}
-		}
-		if pkg == nil && len(pkgs) == 2 {
-			pkg = choice3
-		}
-
-		// Compute the list of other packages
-		// (excluding the selected package, if any).
-		plist = make([]string, len(pkgs))
-		i := 0
-		for name := range pkgs {
-			if pkg == nil || name != pkg.Name {
-				plist[i] = name
-				i++
-			}
-		}
-		plist = plist[0:i]
-		sort.Strings(plist)
+	// Note: Uses current binary's GOOS/GOARCH.
+	// To use different pair, such as if we allowed the user to choose,
+	// set ctxt.GOOS and ctxt.GOARCH before calling ctxt.ImportDir.
+	ctxt := build.Default
+	ctxt.IsAbsPath = pathpkg.IsAbs
+	ctxt.ReadDir = fsReadDir
+	ctxt.OpenFile = fsOpenFile
+	pkginfo, err := ctxt.ImportDir(abspath, 0)
+	// continue if there are no Go source files; we still want the directory info
+	if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
+		info.Err = err
+		return
 	}
 
-	// get examples from *_test.go files
-	var examples []*doc.Example
-	filter = func(d os.FileInfo) bool {
-		return isGoFile(d) && strings.HasSuffix(d.Name(), "_test.go")
-	}
-	if testpkgs, err := parseDir(fset, abspath, filter); err != nil {
-		log.Println("parsing test files:", err)
-	} else {
-		for _, testpkg := range testpkgs {
-			var files []*ast.File
-			for _, f := range testpkg.Files {
-				files = append(files, f)
-			}
-			examples = append(examples, doc.Examples(files...)...)
+	// collect package files
+	pkgname := pkginfo.Name
+	pkgfiles := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
+	if len(pkgfiles) == 0 {
+		// Commands written in C have no .go files in the build.
+		// Instead, documentation may be found in an ignored file.
+		// The file may be ignored via an explicit +build ignore
+		// constraint (recommended), or by defining the package
+		// documentation (historic).
+		pkgname = "main" // assume package main since pkginfo.Name == ""
+		pkgfiles = pkginfo.IgnoredGoFiles
+	}
+
+	// get package information, if any
+	if len(pkgfiles) > 0 {
+		// build package AST
+		fset := token.NewFileSet()
+		files, err := parseFiles(fset, abspath, pkgfiles)
+		if err != nil {
+			info.Err = err
+			return
 		}
-	}
+		pkg := &ast.Package{Name: pkgname, Files: files}
 
-	// compute package documentation
-	var past *ast.File
-	var pdoc *doc.Package
-	if pkg != nil {
+		// extract package documentation
+		info.FSet = fset
 		if mode&showSource == 0 {
 			// show extracted documentation
 			var m doc.Mode
@@ -1000,19 +1088,39 @@ func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoM
 			if mode&allMethods != 0 {
 				m |= doc.AllMethods
 			}
-			pdoc = doc.New(pkg, pathpkg.Clean(relpath), m) // no trailing '/' in importpath
+			info.PDoc = doc.New(pkg, pathpkg.Clean(relpath), m) // no trailing '/' in importpath
+
+			// collect examples
+			testfiles := append(pkginfo.TestGoFiles, pkginfo.XTestGoFiles...)
+			files, err = parseFiles(fset, abspath, testfiles)
+			if err != nil {
+				log.Println("parsing examples:", err)
+			}
+			info.Examples = collectExamples(pkg, files)
+
+			// collect any notes that we want to show
+			if info.PDoc.Notes != nil {
+				info.Notes = make(map[string][]string)
+				for _, m := range notesToShow {
+					if n := info.PDoc.Notes[m]; n != nil {
+						info.Notes[m] = n
+					}
+				}
+			}
+
 		} else {
 			// show source code
 			// TODO(gri) Consider eliminating export filtering in this mode,
 			//           or perhaps eliminating the mode altogether.
 			if mode&noFiltering == 0 {
-				ast.PackageExports(pkg)
+				packageExports(fset, pkg)
 			}
-			past = ast.MergePackageFiles(pkg, ast.FilterUnassociatedComments)
+			info.PAst = ast.MergePackageFiles(pkg, 0)
 		}
+		info.IsMain = pkgname == "main"
 	}
 
-	// get directory information
+	// get directory information, if any
 	var dir *Directory
 	var timestamp time.Time
 	if tree, ts := fsTree.get(); tree != nil && tree.(*Directory) != nil {
@@ -1030,20 +1138,11 @@ func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoM
 		dir = newDirectory(abspath, 1)
 		timestamp = time.Now()
 	}
+	info.Dirs = dir.listing(true)
+	info.DirTime = timestamp
+	info.DirFlat = mode&flatDir != 0
 
-	return PageInfo{
-		Dirname:  abspath,
-		PList:    plist,
-		FSet:     fset,
-		PAst:     past,
-		PDoc:     pdoc,
-		Examples: examples,
-		Dirs:     dir.listing(true),
-		DirTime:  timestamp,
-		DirFlat:  mode&flatDir != 0,
-		IsPkg:    h.isPkg,
-		Err:      nil,
-	}
+	return
 }
 
 func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -1057,7 +1156,7 @@ func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	if relpath == builtinPkgPath {
 		mode = noFiltering
 	}
-	info := h.getPageInfo(abspath, relpath, r.FormValue("p"), mode)
+	info := h.getPageInfo(abspath, relpath, mode)
 	if info.Err != nil {
 		log.Print(info.Err)
 		serveError(w, r, relpath, info.Err)
@@ -1065,8 +1164,7 @@ func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	}
 
 	if mode&noHtml != 0 {
-		contents := applyTemplate(packageText, "packageText", info)
-		serveText(w, contents)
+		serveText(w, applyTemplate(packageText, "packageText", info))
 		return
 	}
 
@@ -1074,26 +1172,25 @@ func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	switch {
 	case info.PAst != nil:
 		tabtitle = info.PAst.Name.Name
-		title = "Package " + tabtitle
 	case info.PDoc != nil:
-		if info.PDoc.Name == fakePkgName {
-			// assume that the directory name is the command name
-			_, tabtitle = pathpkg.Split(relpath)
-		} else {
-			tabtitle = info.PDoc.Name
-		}
-		if info.IsPkg {
-			title = "Package " + tabtitle
-		} else {
-			title = "Command " + tabtitle
-		}
+		tabtitle = info.PDoc.Name
 	default:
 		tabtitle = info.Dirname
-		title = "Directory " + tabtitle
+		title = "Directory "
 		if *showTimestamps {
 			subtitle = "Last update: " + info.DirTime.String()
 		}
 	}
+	if title == "" {
+		if info.IsMain {
+			// assume that the directory name is the command name
+			_, tabtitle = pathpkg.Split(relpath)
+			title = "Command "
+		} else {
+			title = "Package "
+		}
+	}
+	title += tabtitle
 
 	// special cases for top-level package/command directories
 	switch tabtitle {
@@ -1103,8 +1200,12 @@ func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		tabtitle = "Commands"
 	}
 
-	contents := applyTemplate(packageHTML, "packageHTML", info)
-	servePage(w, tabtitle, title, subtitle, "", contents)
+	servePage(w, Page{
+		Title:    title,
+		Tabtitle: tabtitle,
+		Subtitle: subtitle,
+		Body:     applyTemplate(packageHTML, "packageHTML", info),
+	})
 }
 
 // ----------------------------------------------------------------------------
@@ -1181,8 +1282,7 @@ func search(w http.ResponseWriter, r *http.Request) {
 	result := lookup(query)
 
 	if getPageInfoMode(r)&noHtml != 0 {
-		contents := applyTemplate(searchText, "searchText", result)
-		serveText(w, contents)
+		serveText(w, applyTemplate(searchText, "searchText", result))
 		return
 	}
 
@@ -1193,8 +1293,12 @@ func search(w http.ResponseWriter, r *http.Request) {
 		title = fmt.Sprintf(`No results found for query %q`, query)
 	}
 
-	contents := applyTemplate(searchHTML, "searchHTML", result)
-	servePage(w, query, title, "", query, contents)
+	servePage(w, Page{
+		Title:    title,
+		Tabtitle: query,
+		Query:    query,
+		Body:     applyTemplate(searchHTML, "searchHTML", result),
+	})
 }
 
 // ----------------------------------------------------------------------------
diff --git a/src/cmd/godoc/index.go b/src/cmd/godoc/index.go
index 1bef796..91c5646 100644
--- a/src/cmd/godoc/index.go
+++ b/src/cmd/godoc/index.go
@@ -148,7 +148,7 @@ func init() {
 	// sanity check: if nKinds is too large, the SpotInfo
 	// accessor functions may need to be updated
 	if nKinds > 8 {
-		panic("nKinds > 8")
+		panic("internal error: nKinds > 8")
 	}
 }
 
@@ -457,12 +457,6 @@ func (x *Indexer) addSnippet(s *Snippet) int {
 	return index
 }
 
-func (x *Indexer) visitComment(c *ast.CommentGroup) {
-	if c != nil {
-		ast.Walk(x, c)
-	}
-}
-
 func (x *Indexer) visitIdent(kind SpotKind, id *ast.Ident) {
 	if id != nil {
 		lists, found := x.words[id.Name]
@@ -486,20 +480,24 @@ func (x *Indexer) visitIdent(kind SpotKind, id *ast.Ident) {
 	}
 }
 
-func (x *Indexer) visitSpec(spec ast.Spec, isVarDecl bool) {
+func (x *Indexer) visitFieldList(kind SpotKind, list *ast.FieldList) {
+	for _, f := range list.List {
+		x.decl = nil // no snippets for fields
+		for _, name := range f.Names {
+			x.visitIdent(kind, name)
+		}
+		ast.Walk(x, f.Type)
+		// ignore tag - not indexed at the moment
+	}
+}
+
+func (x *Indexer) visitSpec(kind SpotKind, spec ast.Spec) {
 	switch n := spec.(type) {
 	case *ast.ImportSpec:
-		x.visitComment(n.Doc)
 		x.visitIdent(ImportDecl, n.Name)
-		ast.Walk(x, n.Path)
-		x.visitComment(n.Comment)
+		// ignore path - not indexed at the moment
 
 	case *ast.ValueSpec:
-		x.visitComment(n.Doc)
-		kind := ConstDecl
-		if isVarDecl {
-			kind = VarDecl
-		}
 		for _, n := range n.Names {
 			x.visitIdent(kind, n)
 		}
@@ -507,57 +505,51 @@ func (x *Indexer) visitSpec(spec ast.Spec, isVarDecl bool) {
 		for _, v := range n.Values {
 			ast.Walk(x, v)
 		}
-		x.visitComment(n.Comment)
 
 	case *ast.TypeSpec:
-		x.visitComment(n.Doc)
 		x.visitIdent(TypeDecl, n.Name)
 		ast.Walk(x, n.Type)
-		x.visitComment(n.Comment)
+	}
+}
+
+func (x *Indexer) visitGenDecl(decl *ast.GenDecl) {
+	kind := VarDecl
+	if decl.Tok == token.CONST {
+		kind = ConstDecl
+	}
+	x.decl = decl
+	for _, s := range decl.Specs {
+		x.visitSpec(kind, s)
 	}
 }
 
 func (x *Indexer) Visit(node ast.Node) ast.Visitor {
-	// TODO(gri): methods in interface types are categorized as VarDecl
 	switch n := node.(type) {
 	case nil:
-		return nil
+		// nothing to do
 
 	case *ast.Ident:
 		x.visitIdent(Use, n)
 
-	case *ast.Field:
-		x.decl = nil // no snippets for fields
-		x.visitComment(n.Doc)
-		for _, m := range n.Names {
-			x.visitIdent(VarDecl, m)
-		}
-		ast.Walk(x, n.Type)
-		ast.Walk(x, n.Tag)
-		x.visitComment(n.Comment)
+	case *ast.FieldList:
+		x.visitFieldList(VarDecl, n)
+
+	case *ast.InterfaceType:
+		x.visitFieldList(MethodDecl, n.Methods)
 
 	case *ast.DeclStmt:
+		// local declarations should only be *ast.GenDecls;
+		// ignore incorrect ASTs
 		if decl, ok := n.Decl.(*ast.GenDecl); ok {
-			// local declarations can only be *ast.GenDecls
 			x.decl = nil // no snippets for local declarations
-			x.visitComment(decl.Doc)
-			for _, s := range decl.Specs {
-				x.visitSpec(s, decl.Tok == token.VAR)
-			}
-		} else {
-			// handle error case gracefully
-			ast.Walk(x, n.Decl)
+			x.visitGenDecl(decl)
 		}
 
 	case *ast.GenDecl:
 		x.decl = n
-		x.visitComment(n.Doc)
-		for _, s := range n.Specs {
-			x.visitSpec(s, n.Tok == token.VAR)
-		}
+		x.visitGenDecl(n)
 
 	case *ast.FuncDecl:
-		x.visitComment(n.Doc)
 		kind := FuncDecl
 		if n.Recv != nil {
 			kind = MethodDecl
@@ -571,15 +563,11 @@ func (x *Indexer) Visit(node ast.Node) ast.Visitor {
 		}
 
 	case *ast.File:
-		x.visitComment(n.Doc)
 		x.decl = nil
 		x.visitIdent(PackageClause, n.Name)
 		for _, d := range n.Decls {
 			ast.Walk(x, d)
 		}
-		// don't visit package level comments for now
-		// to avoid duplicate visiting from individual
-		// nodes
 
 	default:
 		return x
@@ -622,7 +610,7 @@ func (x *Indexer) addFile(filename string, goFile bool) (file *token.File, ast *
 	// the file set implementation changed or we have another error.
 	base := x.fset.Base()
 	if x.sources.Len() != base {
-		panic("internal error - file base incorrect")
+		panic("internal error: file base incorrect")
 	}
 
 	// append file contents (src) to x.sources
diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go
index 2e2889e..1344100 100644
--- a/src/cmd/godoc/main.go
+++ b/src/cmd/godoc/main.go
@@ -36,6 +36,7 @@ import (
 	"fmt"
 	"go/ast"
 	"go/build"
+	"go/printer"
 	"io"
 	"log"
 	"net/http"
@@ -73,9 +74,12 @@ var (
 )
 
 func serveError(w http.ResponseWriter, r *http.Request, relpath string, err error) {
-	contents := applyTemplate(errorHTML, "errorHTML", err) // err may contain an absolute path!
 	w.WriteHeader(http.StatusNotFound)
-	servePage(w, relpath, "File "+relpath, "", "", contents)
+	servePage(w, Page{
+		Title:    "File " + relpath,
+		Subtitle: relpath,
+		Body:     applyTemplate(errorHTML, "errorHTML", err), // err may contain an absolute path!
+	})
 }
 
 func usage() {
@@ -221,6 +225,8 @@ func main() {
 	// Print content that would be served at the URL *urlFlag.
 	if *urlFlag != "" {
 		registerPublicHandlers(http.DefaultServeMux)
+		initFSTree()
+		updateMetadata()
 		// Try up to 10 fetches, following redirects.
 		urlstr := *urlFlag
 		for i := 0; i < 10; i++ {
@@ -278,10 +284,7 @@ func main() {
 		}
 
 		registerPublicHandlers(http.DefaultServeMux)
-
-		// Playground handlers are not available in local godoc.
-		http.HandleFunc("/compile", disabledHandler)
-		http.HandleFunc("/share", disabledHandler)
+		registerPlaygroundHandlers(http.DefaultServeMux)
 
 		// Initialize default directory tree with corresponding timestamp.
 		// (Do it in a goroutine so that launch is quick.)
@@ -344,7 +347,7 @@ func main() {
 		fs.Bind(target, OS(path), "/", bindReplace)
 		abspath = target
 	} else if strings.HasPrefix(path, cmdPrefix) {
-		path = path[len(cmdPrefix):]
+		path = strings.TrimPrefix(path, cmdPrefix)
 		forceCmd = true
 	} else if bp, _ := build.Import(path, "", build.FindOnly); bp.Dir != "" && bp.ImportPath != "" {
 		fs.Bind(target, OS(bp.Dir), "/", bindReplace)
@@ -369,13 +372,11 @@ func main() {
 		}
 		mode |= showSource
 	}
-	// TODO(gri): Provide a mechanism (flag?) to select a package
-	//            if there are multiple packages in a directory.
 
 	// first, try as package unless forced as command
 	var info PageInfo
 	if !forceCmd {
-		info = pkgHandler.getPageInfo(abspath, relpath, "", mode)
+		info = pkgHandler.getPageInfo(abspath, relpath, mode)
 	}
 
 	// second, try as command unless the path is absolute
@@ -383,7 +384,7 @@ func main() {
 	var cinfo PageInfo
 	if !filepath.IsAbs(path) {
 		abspath = pathpkg.Join(cmdHandler.fsRoot, path)
-		cinfo = cmdHandler.getPageInfo(abspath, relpath, "", mode)
+		cinfo = cmdHandler.getPageInfo(abspath, relpath, mode)
 	}
 
 	// determine what to use
@@ -421,20 +422,24 @@ func main() {
 		filter := func(s string) bool { return rx.MatchString(s) }
 		switch {
 		case info.PAst != nil:
+			cmap := ast.NewCommentMap(info.FSet, info.PAst, info.PAst.Comments)
 			ast.FilterFile(info.PAst, filter)
 			// Special case: Don't use templates for printing
 			// so we only get the filtered declarations without
 			// package clause or extra whitespace.
 			for i, d := range info.PAst.Decls {
+				// determine the comments associated with d only
+				comments := cmap.Filter(d).Comments()
+				cn := &printer.CommentedNode{Node: d, Comments: comments}
 				if i > 0 {
 					fmt.Println()
 				}
 				if *html {
 					var buf bytes.Buffer
-					writeNode(&buf, info.FSet, d)
+					writeNode(&buf, info.FSet, cn)
 					FormatText(os.Stdout, buf.Bytes(), -1, true, "", nil)
 				} else {
-					writeNode(os.Stdout, info.FSet, d)
+					writeNode(os.Stdout, info.FSet, cn)
 				}
 				fmt.Println()
 			}
@@ -459,9 +464,3 @@ type httpWriter struct {
 
 func (w *httpWriter) Header() http.Header  { return w.h }
 func (w *httpWriter) WriteHeader(code int) { w.code = code }
-
-// disabledHandler serves a 501 "Not Implemented" response.
-func disabledHandler(w http.ResponseWriter, r *http.Request) {
-	w.WriteHeader(http.StatusNotImplemented)
-	fmt.Fprint(w, "This functionality is not available via local godoc.")
-}
diff --git a/src/cmd/godoc/parser.go b/src/cmd/godoc/parser.go
index c6b7c2d..42a5d2d 100644
--- a/src/cmd/godoc/parser.go
+++ b/src/cmd/godoc/parser.go
@@ -2,10 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This file contains support functions for parsing .go files.
-// Similar functionality is found in package go/parser but the
-// functions here operate using godoc's file system fs instead
-// of calling the OS's file operations directly.
+// This file contains support functions for parsing .go files
+// accessed via godoc's file system fs.
 
 package main
 
@@ -13,7 +11,6 @@ import (
 	"go/ast"
 	"go/parser"
 	"go/token"
-	"os"
 	pathpkg "path"
 )
 
@@ -25,44 +22,16 @@ func parseFile(fset *token.FileSet, filename string, mode parser.Mode) (*ast.Fil
 	return parser.ParseFile(fset, filename, src, mode)
 }
 
-func parseFiles(fset *token.FileSet, filenames []string) (pkgs map[string]*ast.Package, first error) {
-	pkgs = make(map[string]*ast.Package)
-	for _, filename := range filenames {
-		file, err := parseFile(fset, filename, parser.ParseComments)
+func parseFiles(fset *token.FileSet, abspath string, localnames []string) (map[string]*ast.File, error) {
+	files := make(map[string]*ast.File)
+	for _, f := range localnames {
+		absname := pathpkg.Join(abspath, f)
+		file, err := parseFile(fset, absname, parser.ParseComments)
 		if err != nil {
-			if first == nil {
-				first = err
-			}
-			continue
-		}
-
-		name := file.Name.Name
-		pkg, found := pkgs[name]
-		if !found {
-			// TODO(gri) Use NewPackage here; reconsider ParseFiles API.
-			pkg = &ast.Package{Name: name, Files: make(map[string]*ast.File)}
-			pkgs[name] = pkg
-		}
-		pkg.Files[filename] = file
-	}
-	return
-}
-
-func parseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool) (map[string]*ast.Package, error) {
-	list, err := fs.ReadDir(path)
-	if err != nil {
-		return nil, err
-	}
-
-	filenames := make([]string, len(list))
-	i := 0
-	for _, d := range list {
-		if filter == nil || filter(d) {
-			filenames[i] = pathpkg.Join(path, d.Name())
-			i++
+			return nil, err
 		}
+		files[absname] = file
 	}
-	filenames = filenames[0:i]
 
-	return parseFiles(fset, filenames)
+	return files, nil
 }
diff --git a/src/cmd/godoc/play-appengine.go b/src/cmd/godoc/play-appengine.go
new file mode 100644
index 0000000..9e351d1
--- /dev/null
+++ b/src/cmd/godoc/play-appengine.go
@@ -0,0 +1,35 @@
+// 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.
+
+// App Engine godoc Playground functionality.
+
+// +build appengine
+
+package main
+
+import (
+	"io"
+	"net/http"
+
+	"appengine"
+	"appengine/urlfetch"
+)
+
+func bounceToPlayground(w http.ResponseWriter, req *http.Request) {
+	c := appengine.NewContext(req)
+	client := urlfetch.Client(c)
+	url := playgroundBaseURL + req.URL.Path
+	defer req.Body.Close()
+	resp, err := client.Post(url, req.Header.Get("Content-type"), req.Body)
+	if err != nil {
+		http.Error(w, "Internal Server Error", 500)
+		c.Errorf("making POST request: %v", err)
+		return
+	}
+	defer resp.Body.Close()
+	if _, err := io.Copy(w, resp.Body); err != nil {
+		http.Error(w, "Internal Server Error", 500)
+		c.Errorf("making POST request: %v", err)
+	}
+}
diff --git a/src/cmd/godoc/play-local.go b/src/cmd/godoc/play-local.go
new file mode 100644
index 0000000..637ce5e
--- /dev/null
+++ b/src/cmd/godoc/play-local.go
@@ -0,0 +1,41 @@
+// 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.
+
+// Stand-alone godoc Playground functionality.
+
+// +build !appengine
+
+package main
+
+import (
+	"io"
+	"net/http"
+	"net/url"
+)
+
+var playgroundScheme, playgroundHost string
+
+func init() {
+	u, err := url.Parse(playgroundBaseURL)
+	if err != nil {
+		panic(err)
+	}
+	playgroundScheme = u.Scheme
+	playgroundHost = u.Host
+}
+
+// bounceToPlayground forwards the request to play.golang.org.
+func bounceToPlayground(w http.ResponseWriter, req *http.Request) {
+	defer req.Body.Close()
+	req.URL.Scheme = playgroundScheme
+	req.URL.Host = playgroundHost
+	resp, err := http.Post(req.URL.String(), req.Header.Get("Content-type"), req.Body)
+	if err != nil {
+		http.Error(w, err.Error(), 500)
+		return
+	}
+	w.WriteHeader(resp.StatusCode)
+	io.Copy(w, resp.Body)
+	resp.Body.Close()
+}
diff --git a/src/cmd/godoc/play.go b/src/cmd/godoc/play.go
new file mode 100644
index 0000000..47a11f6
--- /dev/null
+++ b/src/cmd/godoc/play.go
@@ -0,0 +1,52 @@
+// 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.
+
+// Common Playground functionality.
+
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	"go/format"
+	"net/http"
+)
+
+// The server that will service compile and share requests.
+const playgroundBaseURL = "http://play.golang.org"
+
+func registerPlaygroundHandlers(mux *http.ServeMux) {
+	if *showPlayground {
+		mux.HandleFunc("/compile", bounceToPlayground)
+		mux.HandleFunc("/share", bounceToPlayground)
+	} else {
+		mux.HandleFunc("/compile", disabledHandler)
+		mux.HandleFunc("/share", disabledHandler)
+	}
+	http.HandleFunc("/fmt", fmtHandler)
+}
+
+type fmtResponse struct {
+	Body  string
+	Error string
+}
+
+// fmtHandler takes a Go program in its "body" form value, formats it with
+// standard gofmt formatting, and writes a fmtResponse as a JSON object.
+func fmtHandler(w http.ResponseWriter, r *http.Request) {
+	resp := new(fmtResponse)
+	body, err := format.Source([]byte(r.FormValue("body")))
+	if err != nil {
+		resp.Error = err.Error()
+	} else {
+		resp.Body = string(body)
+	}
+	json.NewEncoder(w).Encode(resp)
+}
+
+// disabledHandler serves a 501 "Not Implemented" response.
+func disabledHandler(w http.ResponseWriter, r *http.Request) {
+	w.WriteHeader(http.StatusNotImplemented)
+	fmt.Fprint(w, "This functionality is not available via local godoc.")
+}
diff --git a/src/cmd/godoc/setup-godoc-app.bash b/src/cmd/godoc/setup-godoc-app.bash
old mode 100644
new mode 100755
index b8dc4dc..792e0d4
--- a/src/cmd/godoc/setup-godoc-app.bash
+++ b/src/cmd/godoc/setup-godoc-app.bash
@@ -4,13 +4,14 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-# This script creates the .zip, index, and configuration files for running
-# godoc on app-engine.
+# This script creates a complete godoc app in $APPDIR.
+# It copies the cmd/godoc and src/pkg/go/... sources from GOROOT,
+# synthesizes an app.yaml file, and creates the .zip, index, and
+# configuration files.
 #
 # If an argument is provided it is assumed to be the app-engine godoc directory.
-# Without an argument, $APPDIR is used instead. If GOROOT is not set, the
-# current working directory is assumed to be $GOROOT. Various sanity checks
-# prevent accidents.
+# Without an argument, $APPDIR is used instead. If GOROOT is not set, "go env"
+# is consulted to find the $GOROOT.
 #
 # The script creates a .zip file representing the $GOROOT file system
 # and computes the correspondig search index files. These files are then
@@ -29,8 +30,8 @@ error() {
 
 getArgs() {
 	if [ -z $GOROOT ]; then
-		GOROOT=$(pwd)
-		echo "GOROOT not set, using cwd instead"
+		GOROOT=$(go env GOROOT)
+		echo "GOROOT not set explicitly, using $GOROOT instead"
 	fi
 	if [ -z $APPDIR ]; then
 		if [ $# == 0 ]; then
@@ -47,14 +48,8 @@ getArgs() {
 	if [ ! -x $GOROOT/bin/godoc ]; then
 		error "$GOROOT/bin/godoc does not exist or is not executable"
 	fi
-	if [ ! -d $APPDIR ]; then
-		error "$APPDIR is not a directory"
-	fi
-	if [ ! -e $APPDIR/app.yaml ]; then
-		error "$APPDIR is not an app-engine directory; missing file app.yaml"
-	fi
-	if [ ! -d $APPDIR/godoc ]; then
-		error "$APPDIR is missing directory godoc"
+	if [ -e $APPDIR ]; then
+		error "$APPDIR exists; check and remove it before trying again"
 	fi
 
 	# reporting
@@ -62,12 +57,32 @@ getArgs() {
 	echo "APPDIR = $APPDIR"
 }
 
-cleanup() {
-	echo "*** cleanup $APPDIR"
-	rm $APPDIR/$ZIPFILE
-	rm $APPDIR/$INDEXFILE
-	rm $APPDIR/$SPLITFILES*
-	rm $APPDIR/$CONFIGFILE
+copyGodoc() {
+	echo "*** copy $GOROOT/src/cmd/godoc to $APPDIR/godoc"
+	cp -r $GOROOT/src/cmd/godoc $APPDIR/godoc
+}
+
+copyGoPackages() {
+	echo "*** copy $GOROOT/src/pkg/go to $APPDIR/newgo and rewrite imports"
+	cp -r $GOROOT/src/pkg/go $APPDIR/newgo
+	find $APPDIR/newgo -type d -name testdata | xargs rm -r
+	gofiles=$(find $APPDIR -name '*.go')
+	sed -i '' 's_^\(."\)\(go/[a-z]*\)"$_\1new\2"_' $gofiles
+	sed -i '' 's_^\(import "\)\(go/[a-z]*\)"$_\1new\2"_' $gofiles
+}
+
+makeAppYaml() {
+	echo "*** make $APPDIR/app.yaml"
+	cat > $APPDIR/app.yaml <<EOF
+application: godoc
+version: 1
+runtime: go
+api_version: go1
+
+handlers:
+- url: /.*
+  script: _go_app
+EOF
 }
 
 makeZipfile() {
@@ -112,7 +127,11 @@ EOF
 }
 
 getArgs "$@"
-cleanup
+set -e
+mkdir $APPDIR
+copyGodoc
+copyGoPackages
+makeAppYaml
 makeZipfile
 makeIndexfile
 splitIndexfile
diff --git a/src/cmd/godoc/template.go b/src/cmd/godoc/template.go
index d709bae..7b9b9cf 100644
--- a/src/cmd/godoc/template.go
+++ b/src/cmd/godoc/template.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Template support for writing HTML documents.
-// Documents that include Template: true in their 
+// Documents that include Template: true in their
 // metadata are executed as input to text/template.
 //
 // This file defines functions for those templates to invoke.
@@ -57,8 +57,8 @@ func contents(name string) string {
 	return string(file)
 }
 
-// format returns a textual representation of the arg, formatted according to its nature.
-func format(arg interface{}) string {
+// stringFor returns a textual representation of the arg, formatted according to its nature.
+func stringFor(arg interface{}) string {
 	switch arg := arg.(type) {
 	case int:
 		return fmt.Sprintf("%d", arg)
@@ -87,10 +87,10 @@ func code(file string, arg ...interface{}) (s string, err error) {
 		// text is already whole file.
 		command = fmt.Sprintf("code %q", file)
 	case 1:
-		command = fmt.Sprintf("code %q %s", file, format(arg[0]))
+		command = fmt.Sprintf("code %q %s", file, stringFor(arg[0]))
 		text = oneLine(file, text, arg[0])
 	case 2:
-		command = fmt.Sprintf("code %q %s %s", file, format(arg[0]), format(arg[1]))
+		command = fmt.Sprintf("code %q %s %s", file, stringFor(arg[0]), stringFor(arg[1]))
 		text = multipleLines(file, text, arg[0], arg[1])
 	default:
 		return "", fmt.Errorf("incorrect code invocation: code %q %q", file, arg)
diff --git a/src/cmd/gofmt/doc.go b/src/cmd/gofmt/doc.go
index 65842a3..fffc7f0 100644
--- a/src/cmd/gofmt/doc.go
+++ b/src/cmd/gofmt/doc.go
@@ -72,6 +72,6 @@ To convert the package tree from explicit slice upper bounds to implicit ones:
 
 	gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src/pkg
 */
-package documentation
+package main
 
 // BUG(rsc): The implementation of -r is a bit slow.
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index 0bc385b..861ff93 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -29,7 +29,7 @@ var (
 	rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')")
 	simplifyAST = flag.Bool("s", false, "simplify code")
 	doDiff      = flag.Bool("d", false, "display diffs instead of rewriting files")
-	allErrors   = flag.Bool("e", false, "print all (including spurious) errors")
+	allErrors   = flag.Bool("e", false, "report all errors (not just the first 10 on different lines)")
 
 	// layout control
 	comments  = flag.Bool("comments", true, "print comments")
@@ -65,7 +65,7 @@ func initParserMode() {
 		parserMode |= parser.ParseComments
 	}
 	if *allErrors {
-		parserMode |= parser.SpuriousErrors
+		parserMode |= parser.AllErrors
 	}
 }
 
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index 4b28050..202d0a5 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -56,31 +56,37 @@ func runTest(t *testing.T, in, out, flags string) {
 		return
 	}
 
-	if got := buf.Bytes(); bytes.Compare(got, expected) != 0 {
+	if got := buf.Bytes(); !bytes.Equal(got, expected) {
 		t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in)
 		d, err := diff(expected, got)
 		if err == nil {
 			t.Errorf("%s", d)
 		}
-		ioutil.WriteFile(in+".gofmt", got, 0666)
+		if err := ioutil.WriteFile(in+".gofmt", got, 0666); err != nil {
+			t.Error(err)
+		}
 	}
 }
 
-// TODO(gri) Add more test cases!
 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/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
 }
 
 func TestRewrite(t *testing.T) {
@@ -103,3 +109,24 @@ func TestRewrite(t *testing.T) {
 		}
 	}
 }
+
+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
+
+	data, err := ioutil.ReadFile(input)
+	if err != nil {
+		t.Error(err)
+	}
+	if bytes.Index(data, []byte("\r\n")) < 0 {
+		t.Errorf("%s contains no CR/LF's", input)
+	}
+
+	data, err = ioutil.ReadFile(golden)
+	if err != nil {
+		t.Error(err)
+	}
+	if bytes.Index(data, []byte("\r")) >= 0 {
+		t.Errorf("%s contains CR's", golden)
+	}
+}
diff --git a/src/cmd/gofmt/long_test.go b/src/cmd/gofmt/long_test.go
index edbce60..862e9d9 100644
--- a/src/cmd/gofmt/long_test.go
+++ b/src/cmd/gofmt/long_test.go
@@ -84,7 +84,7 @@ func testFile(t *testing.T, b1, b2 *bytes.Buffer, filename string) {
 	}
 
 	// the first and 2nd result should be identical
-	if bytes.Compare(b1.Bytes(), b2.Bytes()) != 0 {
+	if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
 		t.Errorf("gofmt %s not idempotent", filename)
 	}
 }
diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go
index 3c7861f..dfabb61 100644
--- a/src/cmd/gofmt/rewrite.go
+++ b/src/cmd/gofmt/rewrite.go
@@ -55,6 +55,7 @@ func dump(msg string, val reflect.Value) {
 
 // rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file.
 func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
+	cmap := ast.NewCommentMap(fileSet, p, p.Comments)
 	m := make(map[string]reflect.Value)
 	pat := reflect.ValueOf(pattern)
 	repl := reflect.ValueOf(replace)
@@ -73,7 +74,9 @@ func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
 		}
 		return val
 	}
-	return apply(f, reflect.ValueOf(p)).Interface().(*ast.File)
+	r := apply(f, reflect.ValueOf(p)).Interface().(*ast.File)
+	r.Comments = cmap.Filter(r).Comments() // recreate comments list
+	return r
 }
 
 // setValue is a wrapper for x.SetValue(y); it protects
diff --git a/src/cmd/gofmt/simplify.go b/src/cmd/gofmt/simplify.go
index 470c006..e9a67a7 100644
--- a/src/cmd/gofmt/simplify.go
+++ b/src/cmd/gofmt/simplify.go
@@ -10,7 +10,9 @@ import (
 	"reflect"
 )
 
-type simplifier struct{}
+type simplifier struct {
+	hasDotImport bool // package file contains: import . "some/import/path"
+}
 
 func (s *simplifier) Visit(node ast.Node) ast.Visitor {
 	switch n := node.(type) {
@@ -34,7 +36,7 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
 					x = t.Value
 					px = &t.Value
 				}
-				simplify(x)
+				ast.Walk(s, x) // simplify x
 				// if the element is a composite literal and its literal type
 				// matches the outer literal's element type exactly, the inner
 				// literal type may be omitted
@@ -62,20 +64,54 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
 			return nil
 		}
 
+	case *ast.SliceExpr:
+		// 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()
+			break
+		}
+		if s, _ := n.X.(*ast.Ident); s != nil && s.Obj != nil {
+			// the array/slice object is a single, resolved identifier
+			if call, _ := n.High.(*ast.CallExpr); call != nil && len(call.Args) == 1 && !call.Ellipsis.IsValid() {
+				// the high expression is a function call with a single argument
+				if fun, _ := call.Fun.(*ast.Ident); fun != nil && fun.Name == "len" && fun.Obj == nil {
+					// the function called is "len" and it is not locally defined; and
+					// because we don't have dot imports, it must be the predefined len()
+					if arg, _ := call.Args[0].(*ast.Ident); arg != nil && arg.Obj == s.Obj {
+						// the len argument is the array/slice object
+						n.High = nil
+					}
+				}
+			}
+		}
+		// Note: We could also simplify slice expressions of the form s[0:b] to s[:b]
+		//       but we leave them as is since sometimes we want to be very explicit
+		//       about the lower bound.
+
 	case *ast.RangeStmt:
-		// 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 n.Value != nil {
-			if ident, ok := n.Value.(*ast.Ident); ok && ident.Name == "_" {
-				n.Value = nil
-			}
+		if ident, _ := n.Value.(*ast.Ident); ident != nil && ident.Name == "_" {
+			n.Value = nil
 		}
 	}
 
 	return s
 }
 
-func simplify(node ast.Node) {
+func simplify(f *ast.File) {
 	var s simplifier
-	ast.Walk(&s, node)
+
+	// determine if f contains dot imports
+	for _, imp := range f.Imports {
+		if imp.Name != nil && imp.Name.Name == "." {
+			s.hasDotImport = true
+			break
+		}
+	}
+
+	ast.Walk(&s, f)
 }
diff --git a/src/cmd/gofmt/testdata/crlf.golden b/src/cmd/gofmt/testdata/crlf.golden
new file mode 100644
index 0000000..57679f7
--- /dev/null
+++ b/src/cmd/gofmt/testdata/crlf.golden
@@ -0,0 +1,12 @@
+/*
+	Source containing CR/LF line endings.
+	The gofmt'ed output must only have LF
+	line endings.
+*/
+package main
+
+func main() {
+	// line comment
+	println("hello, world!") // another line comment
+	println()
+}
diff --git a/src/cmd/gofmt/testdata/crlf.input b/src/cmd/gofmt/testdata/crlf.input
new file mode 100644
index 0000000..61a1aa0
--- /dev/null
+++ b/src/cmd/gofmt/testdata/crlf.input
@@ -0,0 +1,12 @@
+/*
+	Source containing CR/LF line endings.
+	The gofmt'ed output must only have LF
+	line endings.
+*/
+package main
+
+func main() {
+	// line comment
+	println("hello, world!") // another line comment
+	println()
+}
diff --git a/src/cmd/gofmt/testdata/rewrite5.golden b/src/cmd/gofmt/testdata/rewrite5.golden
new file mode 100644
index 0000000..5a448a6
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite5.golden
@@ -0,0 +1,15 @@
+// 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.
+
+// Rewriting of expressions containing nodes with associated comments to
+// expressions without those nodes must also eliminate the associated
+// comments.
+
+package p
+
+func f(x int) int {
+	_ = 2 * x // this comment remains in the rewrite
+	_ = 2 * x
+	return 2 * x
+}
diff --git a/src/cmd/gofmt/testdata/rewrite5.input b/src/cmd/gofmt/testdata/rewrite5.input
new file mode 100644
index 0000000..0d759e6
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite5.input
@@ -0,0 +1,15 @@
+// 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.
+
+// Rewriting of expressions containing nodes with associated comments to
+// expressions without those nodes must also eliminate the associated
+// comments.
+
+package p
+
+func f(x int) int {
+	_ = x + x // this comment remains in the rewrite
+	_ = x /* this comment must not be in the rewrite */ + x
+	return x /* this comment must not be in the rewrite */ + x
+}
diff --git a/src/cmd/gofmt/testdata/slices1.golden b/src/cmd/gofmt/testdata/slices1.golden
new file mode 100644
index 0000000..61e074f
--- /dev/null
+++ b/src/cmd/gofmt/testdata/slices1.golden
@@ -0,0 +1,58 @@
+// Test cases for slice expression simplification.
+package p
+
+var (
+	a [10]byte
+	b [20]float32
+	s []int
+	t struct {
+		s []byte
+	}
+
+	_ = a[0:]
+	_ = a[1:10]
+	_ = a[2:]
+	_ = a[3:(len(a))]
+	_ = a[len(a) : len(a)-1]
+	_ = a[0:len(b)]
+
+	_ = a[:]
+	_ = a[:10]
+	_ = a[:]
+	_ = a[:(len(a))]
+	_ = a[:len(a)-1]
+	_ = a[:len(b)]
+
+	_ = s[0:]
+	_ = s[1:10]
+	_ = s[2:]
+	_ = s[3:(len(s))]
+	_ = s[len(a) : len(s)-1]
+	_ = s[0:len(b)]
+
+	_ = s[:]
+	_ = s[:10]
+	_ = s[:]
+	_ = s[:(len(s))]
+	_ = s[:len(s)-1]
+	_ = s[:len(b)]
+
+	_ = t.s[0:]
+	_ = t.s[1:10]
+	_ = t.s[2:len(t.s)]
+	_ = t.s[3:(len(t.s))]
+	_ = t.s[len(a) : len(t.s)-1]
+	_ = t.s[0:len(b)]
+
+	_ = t.s[:]
+	_ = t.s[:10]
+	_ = t.s[:len(t.s)]
+	_ = t.s[:(len(t.s))]
+	_ = t.s[:len(t.s)-1]
+	_ = t.s[:len(b)]
+)
+
+func _() {
+	s := s[0:]
+	_ = s
+}
diff --git a/src/cmd/gofmt/testdata/slices1.input b/src/cmd/gofmt/testdata/slices1.input
new file mode 100644
index 0000000..4d2cbff
--- /dev/null
+++ b/src/cmd/gofmt/testdata/slices1.input
@@ -0,0 +1,58 @@
+// Test cases for slice expression simplification.
+package p
+
+var (
+	a [10]byte
+	b [20]float32
+	s []int
+	t struct {
+		s []byte
+	}
+
+	_ = a[0:]
+	_ = a[1:10]
+	_ = a[2:len(a)]
+	_ = a[3:(len(a))]
+	_ = a[len(a) : len(a)-1]
+	_ = a[0:len(b)]
+
+	_ = a[:]
+	_ = a[:10]
+	_ = a[:len(a)]
+	_ = a[:(len(a))]
+	_ = a[:len(a)-1]
+	_ = a[:len(b)]
+
+	_ = s[0:]
+	_ = s[1:10]
+	_ = s[2:len(s)]
+	_ = s[3:(len(s))]
+	_ = s[len(a) : len(s)-1]
+	_ = s[0:len(b)]
+
+	_ = s[:]
+	_ = s[:10]
+	_ = s[:len(s)]
+	_ = s[:(len(s))]
+	_ = s[:len(s)-1]
+	_ = s[:len(b)]
+
+	_ = t.s[0:]
+	_ = t.s[1:10]
+	_ = t.s[2:len(t.s)]
+	_ = t.s[3:(len(t.s))]
+	_ = t.s[len(a) : len(t.s)-1]
+	_ = t.s[0:len(b)]
+
+	_ = t.s[:]
+	_ = t.s[:10]
+	_ = t.s[:len(t.s)]
+	_ = t.s[:(len(t.s))]
+	_ = t.s[:len(t.s)-1]
+	_ = t.s[:len(b)]
+)
+
+func _() {
+	s := s[0:len(s)]
+	_ = s
+}
diff --git a/src/cmd/gofmt/testdata/slices2.golden b/src/cmd/gofmt/testdata/slices2.golden
new file mode 100644
index 0000000..433788e
--- /dev/null
+++ b/src/cmd/gofmt/testdata/slices2.golden
@@ -0,0 +1,61 @@
+// Test cases for slice expression simplification.
+// Because of a dot import, these slices must remain untouched.
+package p
+
+import . "math"
+
+var (
+	a [10]byte
+	b [20]float32
+	s []int
+	t struct {
+		s []byte
+	}
+
+	_ = a[0:]
+	_ = a[1:10]
+	_ = a[2:len(a)]
+	_ = a[3:(len(a))]
+	_ = a[len(a) : len(a)-1]
+	_ = a[0:len(b)]
+
+	_ = a[:]
+	_ = a[:10]
+	_ = a[:len(a)]
+	_ = a[:(len(a))]
+	_ = a[:len(a)-1]
+	_ = a[:len(b)]
+
+	_ = s[0:]
+	_ = s[1:10]
+	_ = s[2:len(s)]
+	_ = s[3:(len(s))]
+	_ = s[len(a) : len(s)-1]
+	_ = s[0:len(b)]
+
+	_ = s[:]
+	_ = s[:10]
+	_ = s[:len(s)]
+	_ = s[:(len(s))]
+	_ = s[:len(s)-1]
+	_ = s[:len(b)]
+
+	_ = t.s[0:]
+	_ = t.s[1:10]
+	_ = t.s[2:len(t.s)]
+	_ = t.s[3:(len(t.s))]
+	_ = t.s[len(a) : len(t.s)-1]
+	_ = t.s[0:len(b)]
+
+	_ = t.s[:]
+	_ = t.s[:10]
+	_ = t.s[:len(t.s)]
+	_ = t.s[:(len(t.s))]
+	_ = t.s[:len(t.s)-1]
+	_ = t.s[:len(b)]
+)
+
+func _() {
+	s := s[0:len(s)]
+	_ = s
+}
diff --git a/src/cmd/gofmt/testdata/slices2.input b/src/cmd/gofmt/testdata/slices2.input
new file mode 100644
index 0000000..433788e
--- /dev/null
+++ b/src/cmd/gofmt/testdata/slices2.input
@@ -0,0 +1,61 @@
+// Test cases for slice expression simplification.
+// Because of a dot import, these slices must remain untouched.
+package p
+
+import . "math"
+
+var (
+	a [10]byte
+	b [20]float32
+	s []int
+	t struct {
+		s []byte
+	}
+
+	_ = a[0:]
+	_ = a[1:10]
+	_ = a[2:len(a)]
+	_ = a[3:(len(a))]
+	_ = a[len(a) : len(a)-1]
+	_ = a[0:len(b)]
+
+	_ = a[:]
+	_ = a[:10]
+	_ = a[:len(a)]
+	_ = a[:(len(a))]
+	_ = a[:len(a)-1]
+	_ = a[:len(b)]
+
+	_ = s[0:]
+	_ = s[1:10]
+	_ = s[2:len(s)]
+	_ = s[3:(len(s))]
+	_ = s[len(a) : len(s)-1]
+	_ = s[0:len(b)]
+
+	_ = s[:]
+	_ = s[:10]
+	_ = s[:len(s)]
+	_ = s[:(len(s))]
+	_ = s[:len(s)-1]
+	_ = s[:len(b)]
+
+	_ = t.s[0:]
+	_ = t.s[1:10]
+	_ = t.s[2:len(t.s)]
+	_ = t.s[3:(len(t.s))]
+	_ = t.s[len(a) : len(t.s)-1]
+	_ = t.s[0:len(b)]
+
+	_ = t.s[:]
+	_ = t.s[:10]
+	_ = t.s[:len(t.s)]
+	_ = t.s[:(len(t.s))]
+	_ = t.s[:len(t.s)-1]
+	_ = t.s[:len(b)]
+)
+
+func _() {
+	s := s[0:len(s)]
+	_ = s
+}
diff --git a/src/cmd/gofmt/testdata/typeswitch.golden b/src/cmd/gofmt/testdata/typeswitch.golden
new file mode 100644
index 0000000..87e9161
--- /dev/null
+++ b/src/cmd/gofmt/testdata/typeswitch.golden
@@ -0,0 +1,60 @@
+/*
+	Parenthesized type switch expressions originally
+	accepted by gofmt must continue to be rewritten
+	into the correct unparenthesized form.
+
+	Only type-switches that didn't declare a variable
+	in the the type switch type assertion and which
+	contained only "expression-like" (named) types in their
+	cases were permitted to have their type assertion parenthesized
+	by go/parser (due to a weak predicate in the parser). All others
+	were rejected always, either with a syntax error in the
+	type switch header or in the case.
+
+	See also issue 4470.
+*/
+package p
+
+func f() {
+	var x interface{}
+	switch x.(type) { // should remain the same
+	}
+	switch x.(type) { // should become: switch x.(type) {
+	}
+
+	switch x.(type) { // should remain the same
+	case int:
+	}
+	switch x.(type) { // should become: switch x.(type) {
+	case int:
+	}
+
+	switch x.(type) { // should remain the same
+	case []int:
+	}
+
+	// Parenthesized (x.(type)) in type switches containing cases
+	// with unnamed (literal) types were never permitted by gofmt;
+	// thus there won't be any code in the wild using this style if
+	// the code was gofmt-ed.
+	/*
+		switch (x.(type)) {
+		case []int:
+		}
+	*/
+
+	switch t := x.(type) { // should remain the same
+	default:
+		_ = t
+	}
+
+	// Parenthesized (x.(type)) in type switches declaring a variable
+	// were never permitted by gofmt; thus there won't be any code in
+	// the wild using this style if the code was gofmt-ed.
+	/*
+		switch t := (x.(type)) {
+		default:
+			_ = t
+		}
+	*/
+}
diff --git a/src/cmd/gofmt/testdata/typeswitch.input b/src/cmd/gofmt/testdata/typeswitch.input
new file mode 100644
index 0000000..f90f289
--- /dev/null
+++ b/src/cmd/gofmt/testdata/typeswitch.input
@@ -0,0 +1,60 @@
+/*
+	Parenthesized type switch expressions originally
+	accepted by gofmt must continue to be rewritten
+	into the correct unparenthesized form.
+
+	Only type-switches that didn't declare a variable
+	in the the type switch type assertion and which
+	contained only "expression-like" (named) types in their
+	cases were permitted to have their type assertion parenthesized
+	by go/parser (due to a weak predicate in the parser). All others
+	were rejected always, either with a syntax error in the
+	type switch header or in the case.
+
+	See also issue 4470.
+*/
+package p
+
+func f() {
+	var x interface{}
+	switch x.(type) { // should remain the same
+	}
+	switch (x.(type)) { // should become: switch x.(type) {
+	}
+
+	switch x.(type) { // should remain the same
+	case int:
+	}
+	switch (x.(type)) { // should become: switch x.(type) {
+	case int:
+	}
+
+	switch x.(type) { // should remain the same
+	case []int:
+	}
+
+	// Parenthesized (x.(type)) in type switches containing cases
+	// with unnamed (literal) types were never permitted by gofmt;
+	// thus there won't be any code in the wild using this style if
+	// the code was gofmt-ed.
+	/*
+	switch (x.(type)) {
+	case []int:
+	}
+	*/
+
+	switch t := x.(type) { // should remain the same
+	default:
+		_ = t
+	}
+
+	// Parenthesized (x.(type)) in type switches declaring a variable
+	// were never permitted by gofmt; thus there won't be any code in
+	// the wild using this style if the code was gofmt-ed.
+	/*
+	switch t := (x.(type)) {
+	default:
+		_ = t
+	}
+	*/
+}
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 786c10b..6c6b1be 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -34,6 +34,7 @@
 #include	"../ld/lib.h"
 #include	"../ld/elf.h"
 #include	"../ld/pe.h"
+#include	"../../pkg/runtime/mgc0.h"
 
 void	dynreloc(void);
 static vlong addaddrplus4(Sym *s, Sym *t, int32 add);
@@ -57,70 +58,73 @@ datcmp(Sym *s1, Sym *s2)
 }
 
 Sym*
-datsort(Sym *l)
+listsort(Sym *l, int (*cmp)(Sym*, Sym*), int off)
 {
 	Sym *l1, *l2, *le;
+	#define NEXT(l) (*(Sym**)((char*)(l)+off))
 
-	if(l == 0 || l->next == 0)
+	if(l == 0 || NEXT(l) == 0)
 		return l;
 
 	l1 = l;
 	l2 = l;
 	for(;;) {
-		l2 = l2->next;
+		l2 = NEXT(l2);
 		if(l2 == 0)
 			break;
-		l2 = l2->next;
+		l2 = NEXT(l2);
 		if(l2 == 0)
 			break;
-		l1 = l1->next;
+		l1 = NEXT(l1);
 	}
 
-	l2 = l1->next;
-	l1->next = 0;
-	l1 = datsort(l);
-	l2 = datsort(l2);
+	l2 = NEXT(l1);
+	NEXT(l1) = 0;
+	l1 = listsort(l, cmp, off);
+	l2 = listsort(l2, cmp, off);
 
 	/* set up lead element */
-	if(datcmp(l1, l2) < 0) {
+	if(cmp(l1, l2) < 0) {
 		l = l1;
-		l1 = l1->next;
+		l1 = NEXT(l1);
 	} else {
 		l = l2;
-		l2 = l2->next;
+		l2 = NEXT(l2);
 	}
 	le = l;
 
 	for(;;) {
 		if(l1 == 0) {
 			while(l2) {
-				le->next = l2;
+				NEXT(le) = l2;
 				le = l2;
-				l2 = l2->next;
+				l2 = NEXT(l2);
 			}
-			le->next = 0;
+			NEXT(le) = 0;
 			break;
 		}
 		if(l2 == 0) {
 			while(l1) {
-				le->next = l1;
+				NEXT(le) = l1;
 				le = l1;
-				l1 = l1->next;
+				l1 = NEXT(l1);
 			}
 			break;
 		}
-		if(datcmp(l1, l2) < 0) {
-			le->next = l1;
+		if(cmp(l1, l2) < 0) {
+			NEXT(le) = l1;
 			le = l1;
-			l1 = l1->next;
+			l1 = NEXT(l1);
 		} else {
-			le->next = l2;
+			NEXT(le) = l2;
 			le = l2;
-			l2 = l2->next;
+			l2 = NEXT(l2);
 		}
 	}
-	le->next = 0;
+	NEXT(le) = 0;
 	return l;
+	
+	#undef NEXT
 }
 
 Reloc*
@@ -145,21 +149,22 @@ void
 relocsym(Sym *s)
 {
 	Reloc *r;
+	Sym *rs;
 	Prog p;
 	int32 i, off, siz, fl;
 	vlong o;
 	uchar *cast;
-	
+
 	cursym = s;
 	memset(&p, 0, sizeof p);
 	for(r=s->r; r<s->r+s->nr; r++) {
 		off = r->off;
 		siz = r->siz;
-		if(off < 0 || off+(siz&~Rbig) > s->np) {
-			diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz&~Rbig, 0, s->np);
+		if(off < 0 || off+siz > s->np) {
+			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 == 0 || r->sym->type == SXREF)) {
+		if(r->sym != S && (r->sym->type & SMASK == 0 || r->sym->type & SMASK == SXREF)) {
 			diag("%s: not defined", r->sym->name);
 			continue;
 		}
@@ -175,18 +180,35 @@ relocsym(Sym *s)
 		switch(r->type) {
 		default:
 			o = 0;
-			if(archreloc(r, s, &o) < 0)
+			if(isobj || archreloc(r, s, &o) < 0)
 				diag("unknown reloc %d", r->type);
 			break;
 		case D_ADDR:
 			o = symaddr(r->sym) + r->add;
+			if(isobj && r->sym->type != SCONST) {
+				if(thechar == '6')
+					o = 0;
+				else {
+					// set up addend for eventual relocation via outer symbol
+					rs = r->sym;
+					while(rs->outer != nil)
+						rs = rs->outer;
+					o -= symaddr(rs);
+				}
+			}
 			break;
 		case D_PCREL:
-			// r->sym can be null when CALL $(constant) is transformed from absoulte PC to relative PC call.
+			// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
 			o = 0;
 			if(r->sym)
 				o += symaddr(r->sym);
 			o += r->add - (s->value + r->off + r->siz);
+			if(isobj && r->sym->type != SCONST) {
+				if(thechar == '6')
+					o = 0;
+				else
+					o = r->add - r->siz;
+			}
 			break;
 		case D_SIZE:
 			o = r->sym->size + r->add;
@@ -197,20 +219,6 @@ relocsym(Sym *s)
 		default:
 			cursym = s;
 			diag("bad reloc size %#ux for %s", siz, r->sym->name);
-		case 4 + Rbig:
-			fl = o;
-			s->p[off] = fl>>24;
-			s->p[off+1] = fl>>16;
-			s->p[off+2] = fl>>8;
-			s->p[off+3] = fl;
-			break;
-		case 4 + Rlittle:
-			fl = o;
-			s->p[off] = fl;
-			s->p[off+1] = fl>>8;
-			s->p[off+2] = fl>>16;
-			s->p[off+3] = fl>>24;
-			break;
 		case 4:
 			fl = o;
 			cast = (uchar*)&fl;
@@ -222,7 +230,7 @@ relocsym(Sym *s)
 			for(i=0; i<8; i++)
 				s->p[off+i] = cast[inuxi8[i]];
 			break;
-		}		
+		}
 	}
 }
 
@@ -230,7 +238,7 @@ void
 reloc(void)
 {
 	Sym *s;
-	
+
 	if(debug['v'])
 		Bprint(&bso, "%5.2f reloc\n", cputime());
 	Bflush(&bso);
@@ -245,10 +253,12 @@ void
 dynrelocsym(Sym *s)
 {
 	Reloc *r;
+	Sym *rel;
+	Sym *got;
 	
 	if(HEADTYPE == Hwindows) {
 		Sym *rel, *targ;
-		
+
 		rel = lookup(".rel", 0);
 		if(s == rel)
 			return;
@@ -258,7 +268,7 @@ dynrelocsym(Sym *s)
 				targ->plt = rel->size;
 				r->sym = rel;
 				r->add = targ->plt;
-				
+
 				// jmp *addr
 				if(thechar == '8') {
 					adduint8(rel, 0xff);
@@ -281,16 +291,30 @@ dynrelocsym(Sym *s)
 		return;
 	}
 
-	for(r=s->r; r<s->r+s->nr; r++)
-		if(r->sym->type == SDYNIMPORT || r->type >= 256)
+	got = rel = nil;
+	if(flag_shared) {
+		rel = lookuprel();
+		got = lookup(".got", 0);
+	}
+	s->rel_ro = 0;
+	for(r=s->r; r<s->r+s->nr; r++) {
+		if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256)
 			adddynrel(s, r);
+		if(flag_shared && r->sym != S && (r->sym->dynimpname == nil || r->sym->dynexport) && r->type == D_ADDR
+				&& (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) {
+			// Create address based RELATIVE relocation
+			adddynrela(rel, s, r);
+			if(s->type < SNOPTRDATA)
+				s->rel_ro = 1;
+		}
+	}
 }
 
 void
 dynreloc(void)
 {
 	Sym *s;
-	
+
 	// -d supresses dynamic loader format, so we may as well not
 	// compute these sections or mark their symbols as reachable.
 	if(debug['d'] && HEADTYPE != Hwindows)
@@ -363,12 +387,12 @@ savedata(Sym *s, Prog *p, char *pn)
 			break;
 		}
 		break;
-	
+
 	case D_SCONST:
 		for(i=0; i<siz; i++)
 			s->p[off+i] = p->to.scon[i];
 		break;
-	
+
 	case D_CONST:
 		if(p->to.sym)
 			goto Addr;
@@ -449,12 +473,12 @@ blk(Sym *start, int32 addr, int32 size)
 			errorexit();
 		}
 	}
-	
+
 	for(; addr < eaddr; addr++)
 		cput(0);
 	cflush();
 }
-			
+
 void
 codeblk(int32 addr, int32 size)
 {
@@ -497,7 +521,7 @@ codeblk(int32 addr, int32 size)
 			Bprint(&bso, "%.6llux\t%-20s | foreign text\n", (vlong)addr, sym->name);
 			n = sym->size;
 			q = sym->p;
-			
+
 			while(n >= 16) {
 				Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q);
 				addr += 16;
@@ -509,7 +533,7 @@ codeblk(int32 addr, int32 size)
 			addr += n;
 			continue;
 		}
-			
+
 		Bprint(&bso, "%.6llux\t%-20s | %P\n", (vlong)sym->value, sym->name, p);
 		for(p = p->link; p != P; p = p->link) {
 			if(p->link != P)
@@ -531,7 +555,7 @@ codeblk(int32 addr, int32 size)
 	}
 	Bflush(&bso);
 }
-			
+
 void
 datblk(int32 addr, int32 size)
 {
@@ -579,7 +603,7 @@ datblk(int32 addr, int32 size)
 void
 strnput(char *s, int n)
 {
-	for(; *s && n > 0; s++) {
+	for(; n > 0 && *s; s++) {
 		cput(*s);
 		n--;
 	}
@@ -594,18 +618,22 @@ addstrdata(char *name, char *value)
 {
 	Sym *s, *sp;
 	char *p;
-	
+
 	p = smprint("%s.str", name);
 	sp = lookup(p, 0);
 	free(p);
 	addstring(sp, value);
 
 	s = lookup(name, 0);
+	s->size = 0;
 	s->dupok = 1;
 	addaddr(s, sp);
 	adduint32(s, strlen(value));
 	if(PtrSize == 8)
 		adduint32(s, 0);  // round struct to pointer width
+
+	// in case reachability has already been computed
+	sp->reachable = s->reachable;
 }
 
 vlong
@@ -628,41 +656,51 @@ addstring(Sym *s, char *str)
 }
 
 vlong
-adduintxx(Sym *s, uint64 v, int wid)
+setuintxx(Sym *s, vlong off, uint64 v, int wid)
 {
-	int32 i, r, fl;
+	int32 i, fl;
 	vlong o;
 	uchar *cast;
 
 	if(s->type == 0)
 		s->type = SDATA;
 	s->reachable = 1;
-	r = s->size;
-	s->size += wid;
-	symgrow(s, s->size);
-	assert(r+wid <= s->size);
+	if(s->size < off+wid) {
+		s->size = off+wid;
+		symgrow(s, s->size);
+	}
 	fl = v;
 	cast = (uchar*)&fl;
 	switch(wid) {
 	case 1:
-		s->p[r] = cast[inuxi1[0]];
+		s->p[off] = cast[inuxi1[0]];
 		break;
 	case 2:
 		for(i=0; i<2; i++)
-			s->p[r+i] = cast[inuxi2[i]];
+			s->p[off+i] = cast[inuxi2[i]];
 		break;
 	case 4:
 		for(i=0; i<4; i++)
-			s->p[r+i] = cast[inuxi4[i]];
+			s->p[off+i] = cast[inuxi4[i]];
 		break;
 	case 8:
 		o = v;
 		cast = (uchar*)&o;
 		for(i=0; i<8; i++)
-			s->p[r+i] = cast[inuxi8[i]];
+			s->p[off+i] = cast[inuxi8[i]];
 		break;
 	}
-	return r;
+	return off;
+}
+
+vlong
+adduintxx(Sym *s, uint64 v, int wid)
+{
+	int32 off;
+
+	off = s->size;
+	setuintxx(s, off, v, wid);
+	return off;
 }
 
 vlong
@@ -689,6 +727,30 @@ adduint64(Sym *s, uint64 v)
 	return adduintxx(s, v, 8);
 }
 
+void
+setuint8(Sym *s, vlong r, uint8 v)
+{
+	setuintxx(s, r, v, 1);
+}
+
+void
+setuint16(Sym *s, vlong r, uint16 v)
+{
+	setuintxx(s, r, v, 2);
+}
+
+void
+setuint32(Sym *s, vlong r, uint32 v)
+{
+	setuintxx(s, r, v, 4);
+}
+
+void
+setuint64(Sym *s, vlong r, uint64 v)
+{
+	setuintxx(s, r, v, 8);
+}
+
 vlong
 addaddrplus(Sym *s, Sym *t, int32 add)
 {
@@ -736,7 +798,7 @@ addpcrelplus(Sym *s, Sym *t, int32 add)
 {
 	vlong i;
 	Reloc *r;
-	
+
 	if(s->type == 0)
 		s->type = SDATA;
 	s->reachable = 1;
@@ -759,6 +821,33 @@ addaddr(Sym *s, Sym *t)
 }
 
 vlong
+setaddrplus(Sym *s, vlong off, Sym *t, int32 add)
+{
+	Reloc *r;
+
+	if(s->type == 0)
+		s->type = SDATA;
+	s->reachable = 1;
+	if(off+PtrSize > s->size) {
+		s->size = off + PtrSize;
+		symgrow(s, s->size);
+	}
+	r = addrel(s);
+	r->sym = t;
+	r->off = off;
+	r->siz = PtrSize;
+	r->type = D_ADDR;
+	r->add = add;
+	return off;
+}
+
+vlong
+setaddr(Sym *s, vlong off, Sym *t)
+{
+	return setaddrplus(s, off, t, 0);
+}
+
+vlong
 addsize(Sym *s, Sym *t)
 {
 	vlong i;
@@ -793,17 +882,91 @@ dosymtype(void)
 	}
 }
 
+static int32
+alignsymsize(int32 s)
+{
+	if(s >= 8)
+		s = rnd(s, 8);
+	else if(s >= PtrSize)
+		s = rnd(s, PtrSize);
+	else if(s > 2)
+		s = rnd(s, 4);
+	return s;
+}
+
+static int32
+aligndatsize(int32 datsize, Sym *s)
+{
+	int32 t;
+
+	if(s->align != 0) {
+		datsize = rnd(datsize, s->align);
+	} else {
+		t = alignsymsize(s->size);
+		if(t & 1) {
+			;
+		} else if(t & 2)
+			datsize = rnd(datsize, 2);
+		else if(t & 4)
+			datsize = rnd(datsize, 4);
+		else
+			datsize = rnd(datsize, 8);
+	}
+	return datsize;
+}
+
+static void
+gcaddsym(Sym *gc, Sym *s, int32 off)
+{
+	int32 a;
+	Sym *gotype;
+
+	if(s->size < PtrSize)
+		return;
+	if(strcmp(s->name, ".string") == 0)
+		return;
+
+	gotype = s->gotype;
+	if(gotype != nil) {
+		//print("gcaddsym:    %s    %d    %s\n", s->name, s->size, gotype->name);
+		adduintxx(gc, GC_CALL, PtrSize);
+		adduintxx(gc, off, PtrSize);
+		addpcrelplus(gc, decodetype_gc(gotype), 3*PtrSize+4);
+		if(PtrSize == 8)
+			adduintxx(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(gc, GC_APTR, PtrSize);
+			adduintxx(gc, off+a, PtrSize);
+		}
+	}
+}
+
 void
 dodata(void)
 {
 	int32 t, datsize;
-	Section *sect, *noptr;
+	Section *sect;
 	Sym *s, *last, **l;
+	Sym *gcdata1, *gcbss1;
 
 	if(debug['v'])
 		Bprint(&bso, "%5.2f dodata\n", cputime());
 	Bflush(&bso);
 
+	// define garbage collection symbols
+	gcdata1 = lookup("gcdata1", 0);
+	gcdata1->type = SGCDATA;
+	gcdata1->reachable = 1;
+	gcbss1 = lookup("gcbss1", 0);
+	gcbss1->type = SGCBSS;
+	gcbss1->reachable = 1;
+
+	// size of .data and .bss section. the zero value is later replaced by the actual size of the section.
+	adduintxx(gcdata1, 0, PtrSize);
+	adduintxx(gcbss1, 0, PtrSize);
+
 	last = nil;
 	datap = nil;
 
@@ -834,7 +997,7 @@ dodata(void)
 	 * symbol, which is itself data.
 	 */
 	dynreloc();
-	
+
 	/* some symbols may no longer belong in datap (Mach-O) */
 	for(l=&datap; (s=*l) != nil; ) {
 		if(s->type <= STEXT || SXREF <= s->type)
@@ -844,19 +1007,150 @@ dodata(void)
 	}
 	*l = nil;
 
-	datap = datsort(datap);
+	if(flag_shared) {
+		for(s=datap; s != nil; s = s->next) {
+			if(s->rel_ro)
+				s->type = SDATARELRO;
+		}
+	}
+	datap = listsort(datap, datcmp, offsetof(Sym, next));
 
 	/*
-	 * allocate data sections.  list is sorted by type,
+	 * allocate sections.  list is sorted by type,
 	 * so we can just walk it for each piece we want to emit.
+	 * segdata is processed before segtext, because we need
+	 * to see all symbols in the .data and .bss sections in order
+	 * to generate garbage collection information.
 	 */
 
+	/* begin segdata */
+
+	/* skip symbols belonging to segtext */
+	s = datap;
+	for(; s != nil && s->type < SELFSECT; s = s->next)
+		;
+
+	/* writable ELF sections */
+	datsize = 0;
+	for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
+		sect = addsection(&segdata, s->name, 06);
+		if(s->align != 0)
+			datsize = rnd(datsize, s->align);
+		sect->vaddr = datsize;
+		s->sect = sect;
+		s->type = SDATA;
+		s->value = datsize;
+		datsize += rnd(s->size, PtrSize);
+		sect->len = datsize - sect->vaddr;
+	}
+
+	/* pointer-free data */
+	sect = addsection(&segdata, ".noptrdata", 06);
+	sect->vaddr = datsize;
+	lookup("noptrdata", 0)->sect = sect;
+	lookup("enoptrdata", 0)->sect = sect;
+	for(; s != nil && s->type < SDATARELRO; s = s->next) {
+		s->sect = sect;
+		s->type = SDATA;
+		t = alignsymsize(s->size);
+		datsize = aligndatsize(datsize, s);
+		s->value = datsize;
+		datsize += t;
+	}
+	sect->len = datsize - sect->vaddr;
+	datsize = rnd(datsize, PtrSize);
+
+	/* dynamic relocated rodata */
+	if(flag_shared) {
+		sect = addsection(&segdata, ".data.rel.ro", 06);
+		sect->vaddr = datsize;
+		lookup("datarelro", 0)->sect = sect;
+		lookup("edatarelro", 0)->sect = sect;
+		for(; s != nil && s->type == SDATARELRO; s = s->next) {
+			if(s->align != 0)
+				datsize = rnd(datsize, s->align);
+			s->sect = sect;
+			s->type = SDATA;
+			s->value = datsize;
+			datsize += rnd(s->size, PtrSize);
+		}
+		sect->len = datsize - sect->vaddr;
+		datsize = rnd(datsize, PtrSize);
+	}
+
+	/* data */
+	sect = addsection(&segdata, ".data", 06);
+	sect->vaddr = datsize;
+	lookup("data", 0)->sect = sect;
+	lookup("edata", 0)->sect = sect;
+	for(; s != nil && s->type < SBSS; s = s->next) {
+		if(s->type == SDATARELRO) {
+			cursym = s;
+			diag("unexpected symbol type %d", s->type);
+		}
+		s->sect = sect;
+		s->type = SDATA;
+		t = alignsymsize(s->size);
+		datsize = aligndatsize(datsize, s);
+		s->value = datsize;
+		gcaddsym(gcdata1, s, datsize - sect->vaddr);  // gc
+		datsize += t;
+	}
+	sect->len = datsize - sect->vaddr;
+	datsize = rnd(datsize, PtrSize);
+
+	adduintxx(gcdata1, GC_END, PtrSize);
+	setuintxx(gcdata1, 0, sect->len, PtrSize);
+
+	/* bss */
+	sect = addsection(&segdata, ".bss", 06);
+	sect->vaddr = datsize;
+	lookup("bss", 0)->sect = sect;
+	lookup("ebss", 0)->sect = sect;
+	for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
+		s->sect = sect;
+		t = alignsymsize(s->size);
+		datsize = aligndatsize(datsize, s);
+		s->value = datsize;
+		gcaddsym(gcbss1, s, datsize - sect->vaddr);  // gc
+		datsize += t;
+	}
+	sect->len = datsize - sect->vaddr;
+	datsize = rnd(datsize, PtrSize);
+
+	adduintxx(gcbss1, GC_END, PtrSize);
+	setuintxx(gcbss1, 0, sect->len, PtrSize);
+
+	/* pointer-free bss */
+	sect = addsection(&segdata, ".noptrbss", 06);
+	sect->vaddr = datsize;
+	lookup("noptrbss", 0)->sect = sect;
+	lookup("enoptrbss", 0)->sect = sect;
+	for(; s != nil; s = s->next) {
+		if(s->type > SNOPTRBSS) {
+			cursym = s;
+			diag("unexpected symbol type %d", s->type);
+		}
+		s->sect = sect;
+		t = alignsymsize(s->size);
+		datsize = aligndatsize(datsize, s);
+		s->value = datsize;
+		datsize += t;
+	}
+	sect->len = datsize - sect->vaddr;
+	lookup("end", 0)->sect = sect;
+
+	/* we finished segdata, begin segtext */
+
 	/* read-only data */
 	sect = addsection(&segtext, ".rodata", 04);
 	sect->vaddr = 0;
+	lookup("rodata", 0)->sect = sect;
+	lookup("erodata", 0)->sect = sect;
 	datsize = 0;
 	s = datap;
-	for(; s != nil && s->type < SSYMTAB; s = s->next) {
+	for(; s != nil && s->type < STYPELINK; s = s->next) {
+		s->sect = sect;
 		if(s->align != 0)
 			datsize = rnd(datsize, s->align);
 		s->type = SRODATA;
@@ -864,11 +1158,57 @@ dodata(void)
 		datsize += rnd(s->size, PtrSize);
 	}
 	sect->len = datsize - sect->vaddr;
+	datsize = rnd(datsize, PtrSize);
+
+	/* type */
+	sect = addsection(&segtext, ".typelink", 04);
+	sect->vaddr = datsize;
+	lookup("typelink", 0)->sect = sect;
+	lookup("etypelink", 0)->sect = sect;
+	for(; s != nil && s->type == STYPELINK; s = s->next) {
+		s->sect = sect;
+		s->type = SRODATA;
+		s->value = datsize;
+		datsize += s->size;
+	}
+	sect->len = datsize - sect->vaddr;
+	datsize = rnd(datsize, PtrSize);
+
+	/* gcdata */
+	sect = addsection(&segtext, ".gcdata", 04);
+	sect->vaddr = datsize;
+	lookup("gcdata", 0)->sect = sect;
+	lookup("egcdata", 0)->sect = sect;
+	for(; s != nil && s->type == SGCDATA; s = s->next) {
+		s->sect = sect;
+		s->type = SRODATA;
+		s->value = datsize;
+		datsize += s->size;
+	}
+	sect->len = datsize - sect->vaddr;
+	datsize = rnd(datsize, PtrSize);
+
+	/* gcbss */
+	sect = addsection(&segtext, ".gcbss", 04);
+	sect->vaddr = datsize;
+	lookup("gcbss", 0)->sect = sect;
+	lookup("egcbss", 0)->sect = sect;
+	for(; s != nil && s->type == SGCBSS; s = s->next) {
+		s->sect = sect;
+		s->type = SRODATA;
+		s->value = datsize;
+		datsize += s->size;
+	}
+	sect->len = datsize - sect->vaddr;
+	datsize = rnd(datsize, PtrSize);
 
 	/* gosymtab */
 	sect = addsection(&segtext, ".gosymtab", 04);
 	sect->vaddr = datsize;
+	lookup("symtab", 0)->sect = sect;
+	lookup("esymtab", 0)->sect = sect;
 	for(; s != nil && s->type < SPCLNTAB; s = s->next) {
+		s->sect = sect;
 		s->type = SRODATA;
 		s->value = datsize;
 		datsize += s->size;
@@ -879,7 +1219,10 @@ dodata(void)
 	/* gopclntab */
 	sect = addsection(&segtext, ".gopclntab", 04);
 	sect->vaddr = datsize;
+	lookup("pclntab", 0)->sect = sect;
+	lookup("epclntab", 0)->sect = sect;
 	for(; s != nil && s->type < SELFROSECT; s = s->next) {
+		s->sect = sect;
 		s->type = SRODATA;
 		s->value = datsize;
 		datsize += s->size;
@@ -893,101 +1236,12 @@ dodata(void)
 		if(s->align != 0)
 			datsize = rnd(datsize, s->align);
 		sect->vaddr = datsize;
+		s->sect = sect;
 		s->type = SRODATA;
 		s->value = datsize;
 		datsize += rnd(s->size, PtrSize);
 		sect->len = datsize - sect->vaddr;
 	}
-
-	/* writable ELF sections */
-	datsize = 0;
-	for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
-		sect = addsection(&segdata, s->name, 06);
-		if(s->align != 0)
-			datsize = rnd(datsize, s->align);
-		sect->vaddr = datsize;
-		s->type = SDATA;
-		s->value = datsize;
-		datsize += rnd(s->size, PtrSize);
-		sect->len = datsize - sect->vaddr;
-	}
-	
-	/* pointer-free data, then data */
-	sect = addsection(&segdata, ".noptrdata", 06);
-	sect->vaddr = datsize;
-	noptr = sect;
-	for(; ; s = s->next) {
-		if((s == nil || s->type >= SDATA) && sect == noptr) {
-			// finish noptrdata, start data
-			datsize = rnd(datsize, 8);
-			sect->len = datsize - sect->vaddr;
-			sect = addsection(&segdata, ".data", 06);
-			sect->vaddr = datsize;
-		}
-		if(s == nil || s->type >= SBSS) {
-			// finish data
-			sect->len = datsize - sect->vaddr;
-			break;
-		}
-		s->type = SDATA;
-		t = s->size;
-		if(t >= PtrSize)
-			t = rnd(t, PtrSize);
-		else if(t > 2)
-			t = rnd(t, 4);
-		if(s->align != 0)
-			datsize = rnd(datsize, s->align);
-		else if(t & 1) {
-			;
-		} else if(t & 2)
-			datsize = rnd(datsize, 2);
-		else if(t & 4)
-			datsize = rnd(datsize, 4);
-		else
-			datsize = rnd(datsize, 8);
-		s->value = datsize;
-		datsize += t;
-	}
-
-	/* bss, then pointer-free bss */
-	noptr = nil;
-	sect = addsection(&segdata, ".bss", 06);
-	sect->vaddr = datsize;
-	for(; ; s = s->next) {
-		if((s == nil || s->type >= SNOPTRBSS) && noptr == nil) {
-			// finish bss, start noptrbss
-			datsize = rnd(datsize, 8);
-			sect->len = datsize - sect->vaddr;
-			sect = addsection(&segdata, ".noptrbss", 06);
-			sect->vaddr = datsize;
-			noptr = sect;
-		}
-		if(s == nil) {
-			sect->len = datsize - sect->vaddr;
-			break;
-		}
-		if(s->type > SNOPTRBSS) {
-			cursym = s;
-			diag("unexpected symbol type %d", s->type);
-		}
-		t = s->size;
-		if(t >= PtrSize)
-			t = rnd(t, PtrSize);
-		else if(t > 2)
-			t = rnd(t, 4);
-		if(s->align != 0)
-			datsize = rnd(datsize, s->align);
-		else if(t & 1) {
-			;
-		} else if(t & 2)
-			datsize = rnd(datsize, 2);
-		else if(t & 4)
-			datsize = rnd(datsize, 4);
-		else
-			datsize = rnd(datsize, 8);
-		s->value = datsize;
-		datsize += t;
-	}
 }
 
 // assign addresses to text
@@ -1002,16 +1256,21 @@ textaddress(void)
 	addsection(&segtext, ".text", 05);
 
 	// Assign PCs in text segment.
-	// Could parallelize, by assigning to text 
+	// Could parallelize, by assigning to text
 	// and then letting threads copy down, but probably not worth it.
 	sect = segtext.sect;
+	lookup("text", 0)->sect = sect;
+	lookup("etext", 0)->sect = sect;
 	va = INITTEXT;
 	sect->vaddr = va;
 	for(sym = textp; sym != nil; sym = sym->next) {
+		sym->sect = sect;
 		if(sym->type & SSUB)
 			continue;
 		if(sym->align != 0)
 			va = rnd(va, sym->align);
+		else if(sym->text != P)
+			va = rnd(va, FuncAlign);
 		sym->value = 0;
 		for(sub = sym; sub != S; sub = sub->sub) {
 			sub->value += va;
@@ -1023,7 +1282,7 @@ textaddress(void)
 		}
 		va += sym->size;
 	}
-	
+
 	// Align end of code so that rodata starts aligned.
 	// 128 bytes is likely overkill but definitely cheap.
 	va = rnd(va, 128);
@@ -1035,7 +1294,8 @@ textaddress(void)
 void
 address(void)
 {
-	Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
+	Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
+	Section *gcdata, *gcbss, *typelink;
 	Sym *sym, *sub;
 	uvlong va;
 
@@ -1058,12 +1318,13 @@ address(void)
 	segdata.filelen = 0;
 	if(HEADTYPE == Hwindows)
 		segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
-	if(HEADTYPE == Hplan9x32)
+	if(HEADTYPE == Hplan9x64 || HEADTYPE == Hplan9x32)
 		segdata.fileoff = segtext.fileoff + segtext.filelen;
 	data = nil;
 	noptr = nil;
 	bss = nil;
 	noptrbss = nil;
+	datarelro = nil;
 	for(s=segdata.sect; s != nil; s=s->next) {
 		s->vaddr = va;
 		va += s->len;
@@ -1077,12 +1338,17 @@ address(void)
 			bss = s;
 		if(strcmp(s->name, ".noptrbss") == 0)
 			noptrbss = s;
+		if(strcmp(s->name, ".data.rel.ro") == 0)
+			datarelro = s;
 	}
 	segdata.filelen -= bss->len + noptrbss->len; // deduct .bss
 
 	text = segtext.sect;
 	rodata = text->next;
-	symtab = rodata->next;
+	typelink = rodata->next;
+	gcdata = typelink->next;
+	gcbss = gcdata->next;
+	symtab = gcbss->next;
 	pclntab = symtab->next;
 
 	for(sym = datap; sym != nil; sym = sym->next) {
@@ -1094,11 +1360,21 @@ address(void)
 		for(sub = sym->sub; sub != nil; sub = sub->sub)
 			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);
+	if(datarelro != nil) {
+		xdefine("datarelro", SRODATA, datarelro->vaddr);
+		xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
+	}
+	xdefine("gcdata", SGCDATA, gcdata->vaddr);
+	xdefine("egcdata", SGCDATA, gcdata->vaddr + gcdata->len);
+	xdefine("gcbss", SGCBSS, gcbss->vaddr);
+	xdefine("egcbss", SGCBSS, gcbss->vaddr + gcbss->len);
 	xdefine("symtab", SRODATA, symtab->vaddr);
 	xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
 	xdefine("pclntab", SRODATA, pclntab->vaddr);
diff --git a/src/cmd/ld/decodesym.c b/src/cmd/ld/decodesym.c
new file mode 100644
index 0000000..ab3f4fb
--- /dev/null
+++ b/src/cmd/ld/decodesym.c
@@ -0,0 +1,215 @@
+// 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	"l.h"
+#include	"lib.h"
+#include	"../../pkg/runtime/typekind.h"
+
+// Decoding the type.* symbols.	 This has to be in sync with
+// ../../pkg/runtime/type.go, or more specificaly, with what
+// ../gc/reflect.c stuffs in these.
+
+static Reloc*
+decode_reloc(Sym *s, int32 off)
+{
+	int i;
+
+	for (i = 0; i < s->nr; i++)
+		if (s->r[i].off == off)
+			return s->r + i;
+	return nil;
+}
+
+static Sym*
+decode_reloc_sym(Sym *s, int32 off)
+{
+	Reloc *r;
+
+	r = decode_reloc(s,off);
+	if (r == nil)
+		return nil;
+	return r->sym;
+}
+
+static uvlong
+decode_inuxi(uchar* p, int sz)
+{
+	uint64 v;
+	uint32 l;
+	uchar *cast, *inuxi;
+	int i;
+
+	v = l = 0;
+	cast = nil;
+	inuxi = nil;
+	switch (sz) {
+	case 2:
+		cast = (uchar*)&l;
+		inuxi = inuxi2;
+		break;
+	case 4:
+		cast = (uchar*)&l;
+		inuxi = inuxi4;
+		break;
+	case 8:
+		cast = (uchar*)&v;
+		inuxi = inuxi8;
+		break;
+	default:
+		diag("dwarf: decode inuxi %d", sz);
+		errorexit();
+	}
+	for (i = 0; i < sz; i++)
+		cast[inuxi[i]] = p[i];
+	if (sz == 8)
+		return v;
+	return l;
+}
+
+// Type.commonType.kind
+uint8
+decodetype_kind(Sym *s)
+{
+	return s->p[1*PtrSize + 7] & ~KindNoPointers;	//  0x13 / 0x1f
+}
+
+// Type.commonType.size
+vlong
+decodetype_size(Sym *s)
+{
+	return decode_inuxi(s->p, PtrSize);	 // 0x8 / 0x10
+}
+
+// Type.commonType.gc
+Sym*
+decodetype_gc(Sym *s)
+{
+	return decode_reloc_sym(s, 1*PtrSize + 8 + 1*PtrSize);
+}
+
+// Type.ArrayType.elem and Type.SliceType.Elem
+Sym*
+decodetype_arrayelem(Sym *s)
+{
+	return decode_reloc_sym(s, CommonSize);	// 0x1c / 0x30
+}
+
+vlong
+decodetype_arraylen(Sym *s)
+{
+	return decode_inuxi(s->p + CommonSize+PtrSize, PtrSize);
+}
+
+// Type.PtrType.elem
+Sym*
+decodetype_ptrelem(Sym *s)
+{
+	return decode_reloc_sym(s, CommonSize);	// 0x1c / 0x30
+}
+
+// Type.MapType.key, elem
+Sym*
+decodetype_mapkey(Sym *s)
+{
+	return decode_reloc_sym(s, CommonSize);	// 0x1c / 0x30
+}
+Sym*
+decodetype_mapvalue(Sym *s)
+{
+	return decode_reloc_sym(s, CommonSize+PtrSize);	// 0x20 / 0x38
+}
+
+// Type.ChanType.elem
+Sym*
+decodetype_chanelem(Sym *s)
+{
+	return decode_reloc_sym(s, CommonSize);	// 0x1c / 0x30
+}
+
+// Type.FuncType.dotdotdot
+int
+decodetype_funcdotdotdot(Sym *s)
+{
+	return s->p[CommonSize];
+}
+
+// Type.FuncType.in.len
+int
+decodetype_funcincount(Sym *s)
+{
+	return decode_inuxi(s->p + CommonSize+2*PtrSize, IntSize);
+}
+
+int
+decodetype_funcoutcount(Sym *s)
+{
+	return decode_inuxi(s->p + CommonSize+3*PtrSize + 2*IntSize, IntSize);
+}
+
+Sym*
+decodetype_funcintype(Sym *s, int i)
+{
+	Reloc *r;
+
+	r = decode_reloc(s, CommonSize + PtrSize);
+	if (r == nil)
+		return nil;
+	return decode_reloc_sym(r->sym, r->add + i * PtrSize);
+}
+
+Sym*
+decodetype_funcouttype(Sym *s, int i)
+{
+	Reloc *r;
+
+	r = decode_reloc(s, CommonSize + 2*PtrSize + 2*IntSize);
+	if (r == nil)
+		return nil;
+	return decode_reloc_sym(r->sym, r->add + i * PtrSize);
+}
+
+// Type.StructType.fields.Slice::len
+int
+decodetype_structfieldcount(Sym *s)
+{
+	return decode_inuxi(s->p + CommonSize + PtrSize, IntSize);
+}
+
+enum {
+	StructFieldSize = 5*PtrSize
+};
+// Type.StructType.fields[]-> name, typ and offset.
+char*
+decodetype_structfieldname(Sym *s, int i)
+{
+	Reloc *r;
+
+	// go.string."foo"  0x28 / 0x40
+	s = decode_reloc_sym(s, CommonSize + PtrSize + 2*IntSize + i*StructFieldSize);
+	if (s == nil)			// embedded structs have a nil name.
+		return nil;
+	r = decode_reloc(s, 0);		// s has a pointer to the string data at offset 0
+	if (r == nil)			// shouldn't happen.
+		return nil;
+	return (char*) r->sym->p + r->add;	// the c-string
+}
+
+Sym*
+decodetype_structfieldtype(Sym *s, int i)
+{
+	return decode_reloc_sym(s, CommonSize + PtrSize + 2*IntSize + i*StructFieldSize + 2*PtrSize);
+}
+
+vlong
+decodetype_structfieldoffs(Sym *s, int i)
+{
+	return decode_inuxi(s->p + CommonSize + PtrSize + 2*IntSize + i*StructFieldSize + 4*PtrSize, IntSize);
+}
+
+// InterfaceTYpe.methods.len
+vlong
+decodetype_ifacemethodcount(Sym *s)
+{
+	return decode_inuxi(s->p + CommonSize + PtrSize, IntSize);
+}
diff --git a/src/cmd/ld/doc.go b/src/cmd/ld/doc.go
index e99e504..bad4e54 100644
--- a/src/cmd/ld/doc.go
+++ b/src/cmd/ld/doc.go
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build ignore
+
 /*
 
 Ld is the portable code for a modified version of the Plan 9 linker.  The original is documented at
 
-	http://plan9.bell-labs.com/magic/man2html/1/2l
+	http://plan9.bell-labs.com/magic/man2html/1/8l
 
 It reads object files (.5, .6, or .8 files) and writes a binary named for the
 architecture (5.out, 6.out, 8.out) by default (if $GOOS is windows, a .exe suffix
@@ -33,7 +35,7 @@ Options new in this version:
 		Write Apple Mach-O binaries (default when $GOOS is darwin)
 	-Hlinux
 		Write Linux ELF binaries (default when $GOOS is linux)
-	-Hfreebsd    (only in 6l/8l)
+	-Hfreebsd
 		Write FreeBSD ELF binaries (default when $GOOS is freebsd)
 	-Hnetbsd     (only in 6l/8l)
 		Write NetBSD ELF binaries (default when $GOOS is netbsd)
@@ -56,5 +58,18 @@ Options new in this version:
 		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".
+	-race
+		Link with race detection libraries.
+	-B value
+		Add a NT_GNU_BUILD_ID note when using ELF.  The value
+		should start with 0x and be an even number of hex digits.
+	-Z
+		Zero stack on function entry. This is expensive but it might
+		be useful in cases where you are suffering from false positives
+		during garbage collection and are willing to trade the CPU time
+		for getting rid of the false positives.
+		NOTE: it only eliminates false positives caused by other function
+		calls, not false positives caused by dead temporaries stored in
+		the current function call.
 */
-package documentation
+package main
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index 57e5a42..d6a357e 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -19,6 +19,7 @@
 #include	"../ld/elf.h"
 #include	"../ld/macho.h"
 #include	"../ld/pe.h"
+#include	"../../pkg/runtime/typekind.h"
 
 /*
  * Offsets and sizes of the debug_* sections in the cout file.
@@ -740,241 +741,6 @@ newabslocexprattr(DWDie *die, vlong addr)
 	memmove(die->attr->data, block, i);
 }
 
-// Decoding the type.* symbols.	 This has to be in sync with
-// ../../pkg/runtime/type.go, or more specificaly, with what
-// ../gc/reflect.c stuffs in these.
-
-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,
-
-	// size of Type interface header + CommonType structure.
-	CommonSize = 2*PtrSize+ 5*PtrSize + 8,
-};
-
-static Reloc*
-decode_reloc(Sym *s, int32 off)
-{
-	int i;
-
-	for (i = 0; i < s->nr; i++)
-		if (s->r[i].off == off)
-			return s->r + i;
-	return nil;
-}
-
-static Sym*
-decode_reloc_sym(Sym *s, int32 off)
-{
-	Reloc *r;
-
-	r = decode_reloc(s,off);
-	if (r == nil)
-		return nil;
-	return r->sym;
-}
-
-static uvlong
-decode_inuxi(uchar* p, int sz)
-{
-	uint64 v;
-	uint32 l;
-	uchar *cast, *inuxi;
-	int i;
-
-	v = l = 0;
-	cast = nil;
-	inuxi = nil;
-	switch (sz) {
-	case 2:
-		cast = (uchar*)&l;
-		inuxi = inuxi2;
-		break;
-	case 4:
-		cast = (uchar*)&l;
-		inuxi = inuxi4;
-		break;
-	case 8:
-		cast = (uchar*)&v;
-		inuxi = inuxi8;
-		break;
-	default:
-		diag("dwarf: decode inuxi %d", sz);
-		errorexit();
-	}
-	for (i = 0; i < sz; i++)
-		cast[inuxi[i]] = p[i];
-	if (sz == 8)
-		return v;
-	return l;
-}
-
-// Type.commonType.kind
-static uint8
-decodetype_kind(Sym *s)
-{
-	return s->p[3*PtrSize + 7] & ~KindNoPointers;	//  0x13 / 0x1f
-}
-
-// Type.commonType.size
-static vlong
-decodetype_size(Sym *s)
-{
-	return decode_inuxi(s->p + 2*PtrSize, PtrSize);	 // 0x8 / 0x10
-}
-
-// Type.ArrayType.elem and Type.SliceType.Elem
-static Sym*
-decodetype_arrayelem(Sym *s)
-{
-	return decode_reloc_sym(s, CommonSize);	// 0x1c / 0x30
-}
-
-static vlong
-decodetype_arraylen(Sym *s)
-{
-	return decode_inuxi(s->p + CommonSize+PtrSize, PtrSize);
-}
-
-// Type.PtrType.elem
-static Sym*
-decodetype_ptrelem(Sym *s)
-{
-	return decode_reloc_sym(s, CommonSize);	// 0x1c / 0x30
-}
-
-// Type.MapType.key, elem
-static Sym*
-decodetype_mapkey(Sym *s)
-{
-	return decode_reloc_sym(s, CommonSize);	// 0x1c / 0x30
-}
-static Sym*
-decodetype_mapvalue(Sym *s)
-{
-	return decode_reloc_sym(s, CommonSize+PtrSize);	// 0x20 / 0x38
-}
-
-// Type.ChanType.elem
-static Sym*
-decodetype_chanelem(Sym *s)
-{
-	return decode_reloc_sym(s, CommonSize);	// 0x1c / 0x30
-}
-
-// Type.FuncType.dotdotdot
-static int
-decodetype_funcdotdotdot(Sym *s)
-{
-	return s->p[CommonSize];
-}
-
-// Type.FuncType.in.len
-static int
-decodetype_funcincount(Sym *s)
-{
-	return decode_inuxi(s->p + CommonSize+2*PtrSize, 4);
-}
-
-static int
-decodetype_funcoutcount(Sym *s)
-{
-	return decode_inuxi(s->p + CommonSize+3*PtrSize + 2*4, 4);
-}
-
-static Sym*
-decodetype_funcintype(Sym *s, int i)
-{
-	Reloc *r;
-
-	r = decode_reloc(s, CommonSize + PtrSize);
-	if (r == nil)
-		return nil;
-	return decode_reloc_sym(r->sym, r->add + i * PtrSize);
-}
-
-static Sym*
-decodetype_funcouttype(Sym *s, int i)
-{
-	Reloc *r;
-
-	r = decode_reloc(s, CommonSize + 2*PtrSize + 2*4);
-	if (r == nil)
-		return nil;
-	return decode_reloc_sym(r->sym, r->add + i * PtrSize);
-}
-
-// Type.StructType.fields.Slice::len
-static int
-decodetype_structfieldcount(Sym *s)
-{
-	return decode_inuxi(s->p + CommonSize + PtrSize, 4);
-}
-
-enum {
-	StructFieldSize = 5*PtrSize
-};
-// Type.StructType.fields[]-> name, typ and offset.
-static char*
-decodetype_structfieldname(Sym *s, int i)
-{
-	Reloc *r;
-
-	// go.string."foo"  0x28 / 0x40
-	s = decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize);
-	if (s == nil)			// embedded structs have a nil name.
-		return nil;
-	r = decode_reloc(s, 0);		// s has a pointer to the string data at offset 0
-	if (r == nil)			// shouldn't happen.
-		return nil;
-	return (char*) r->sym->p + r->add;	// the c-string
-}
-
-static Sym*
-decodetype_structfieldtype(Sym *s, int i)
-{
-	return decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize + 2*PtrSize);
-}
-
-static vlong
-decodetype_structfieldoffs(Sym *s, int i)
-{
-	return decode_inuxi(s->p + CommonSize + PtrSize + 2*4 + i*StructFieldSize + 4*PtrSize, 4);
-}
-
-// InterfaceTYpe.methods.len
-static vlong
-decodetype_ifacemethodcount(Sym *s)
-{
-	return decode_inuxi(s->p + CommonSize + PtrSize, 4);
-}
-
 
 // Fake attributes for slices, maps and channel
 enum {
@@ -1531,6 +1297,10 @@ decodez(char *s)
 		return 0;
 
 	r = malloc(len + 1);
+	if(r == nil) {
+		diag("out of memory");
+		errorexit();
+	}
 	rb = r;
 	re = rb + len + 1;
 
@@ -1709,6 +1479,10 @@ inithist(Auto *a)
 			continue;
 		if (linehist == 0 || linehist->absline != absline) {
 			Linehist* lh = malloc(sizeof *lh);
+			if(lh == nil) {
+				diag("out of memory");
+				errorexit();
+			}
 			lh->link = linehist;
 			lh->absline = absline;
 			linehist = lh;
@@ -2162,7 +1936,8 @@ writeinfo(void)
  *  because we need die->offs and infoo/infosize;
  */
 static int
-ispubname(DWDie *die) {
+ispubname(DWDie *die)
+{
 	DWAttr *a;
 
 	switch(die->abbrev) {
@@ -2175,7 +1950,8 @@ ispubname(DWDie *die) {
 }
 
 static int
-ispubtype(DWDie *die) {
+ispubtype(DWDie *die)
+{
 	return die->abbrev >= DW_ABRV_NULLTYPE;
 }
 
@@ -2316,7 +2092,7 @@ dwarfemitdebugsections(void)
 	newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, PtrSize, 0);
 
 	// Needed by the prettyprinter code for interface inspection.
-	defgotype(lookup_or_diag("type.runtime.commonType"));
+	defgotype(lookup_or_diag("type.runtime.rtype"));
 	defgotype(lookup_or_diag("type.runtime.interfaceType"));
 	defgotype(lookup_or_diag("type.runtime.itab"));
 
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index de9e6b8..6309066 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -11,7 +11,7 @@
  * in order to write the code just once.  The 64-bit data structure is
  * written in the 32-bit format on the 32-bit machines.
  */
-#define	NSECT	32
+#define	NSECT	48
 
 int	iself;
 
@@ -31,6 +31,8 @@ struct Elfstring
 static Elfstring elfstr[100];
 static int nelfstr;
 
+static char buildinfo[32];
+
 /*
  Initialize the global variable that describes the ELF header. It will be updated as
  we write section and prog headers.
@@ -52,6 +54,11 @@ elfinit(void)
 		break;
 
 	// 32-bit architectures
+	case '5':
+		// we only use EABI on linux/arm
+		if(HEADTYPE == Hlinux)
+			hdr.flags = 0x5000002; // has entry point, Version5 EABI
+		// fallthrough
 	default:
 		hdr.phoff = ELF32HDRSIZE;	/* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */
 		hdr.shoff = ELF32HDRSIZE;	/* Will move as we add PHeaders */
@@ -190,19 +197,13 @@ newElfPhdr(void)
 }
 
 ElfShdr*
-newElfShstrtab(vlong name)
-{
-	hdr.shstrndx = hdr.shnum;
-	return newElfShdr(name);
-}
-
-ElfShdr*
 newElfShdr(vlong name)
 {
 	ElfShdr *e;
 
 	e = mal(sizeof *e);
 	e->name = name;
+	e->shnum = hdr.shnum;
 	if (hdr.shnum >= NSECT) {
 		diag("too many shdrs");
 	} else {
@@ -332,26 +333,53 @@ elfinterp(ElfShdr *sh, uint64 startva, uint64 resoff, char *p)
 }
 
 int
-elfwriteinterp(vlong stridx)
+elfwriteinterp(void)
 {
-	ElfShdr *sh = nil;
-	int i;
-
-	for(i = 0; i < hdr.shnum; i++)
-		if(shdr[i]->name == stridx)
-			sh = shdr[i];
-	if(sh == nil || interp == nil)
-		return 0;
-
+	ElfShdr *sh;
+	
+	sh = elfshname(".interp");
 	cseek(sh->off);
 	cwrite(interp, sh->size);
 	return sh->size;
 }
 
-// Defined in NetBSD's sys/exec_elf.h
-#define ELF_NOTE_TYPE_NETBSD_TAG	1
+int
+elfnote(ElfShdr *sh, uint64 startva, uint64 resoff, int sz)
+{
+	uint64 n;
+
+	n = sizeof(Elf_Note) + sz + resoff % 4;
+
+	sh->type = SHT_NOTE;
+	sh->flags = SHF_ALLOC;
+	sh->addralign = 4;
+	sh->addr = startva + resoff - n;
+	sh->off = resoff - n;
+	sh->size = n;
+
+	return n;
+}
+
+ElfShdr *
+elfwritenotehdr(char *str, uint32 namesz, uint32 descsz, uint32 tag)
+{
+	ElfShdr *sh;
+	
+	sh = elfshname(str);
+
+	// Write Elf_Note header.
+	cseek(sh->off);
+	LPUT(namesz);
+	LPUT(descsz);
+	LPUT(tag);
+
+	return sh;
+}
+
+// NetBSD Signature (as per sys/exec_elf.h)
 #define ELF_NOTE_NETBSD_NAMESZ		7
 #define ELF_NOTE_NETBSD_DESCSZ		4
+#define ELF_NOTE_NETBSD_TAG		1
 #define ELF_NOTE_NETBSD_NAME		"NetBSD\0\0"
 #define ELF_NOTE_NETBSD_VERSION		599000000	/* NetBSD 5.99 */
 
@@ -360,37 +388,131 @@ elfnetbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff)
 {
 	int n;
 
-	n = sizeof(Elf_Note) + ELF_NOTE_NETBSD_NAMESZ + ELF_NOTE_NETBSD_DESCSZ + 1;
-	n += resoff % 4;
-	sh->addr = startva + resoff - n;
-	sh->off = resoff - n;
-	sh->size = n;
-
-	return n;
+	n = ELF_NOTE_NETBSD_NAMESZ + ELF_NOTE_NETBSD_DESCSZ + 1;
+	return elfnote(sh, startva, resoff, n);
 }
 
 int
-elfwritenetbsdsig(vlong stridx) {
-	ElfShdr *sh = nil;
-	int i;
+elfwritenetbsdsig(void)
+{
+	ElfShdr *sh;
 
-	for(i = 0; i < hdr.shnum; i++)
-		if(shdr[i]->name == stridx)
-			sh = shdr[i];
+	// Write Elf_Note header.
+	sh = elfwritenotehdr(".note.netbsd.ident", ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG);
 	if(sh == nil)
 		return 0;
 
-	// Write Elf_Note header followed by NetBSD string.
-	cseek(sh->off);
-	LPUT(ELF_NOTE_NETBSD_NAMESZ);
-	LPUT(ELF_NOTE_NETBSD_DESCSZ);
-	LPUT(ELF_NOTE_TYPE_NETBSD_TAG);
-	cwrite(ELF_NOTE_NETBSD_NAME, 8);
+	// Followed by NetBSD string and version.
+	cwrite(ELF_NOTE_NETBSD_NAME, ELF_NOTE_NETBSD_NAMESZ + 1);
 	LPUT(ELF_NOTE_NETBSD_VERSION);
 
 	return sh->size;
 }
 
+// OpenBSD Signature
+#define ELF_NOTE_OPENBSD_NAMESZ		8
+#define ELF_NOTE_OPENBSD_DESCSZ		4
+#define ELF_NOTE_OPENBSD_TAG		1
+#define ELF_NOTE_OPENBSD_NAME		"OpenBSD\0"
+#define ELF_NOTE_OPENBSD_VERSION	0
+
+int
+elfopenbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff)
+{
+	int n;
+
+	n = ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ;
+	return elfnote(sh, startva, resoff, n);
+}
+
+int
+elfwriteopenbsdsig(void)
+{
+	ElfShdr *sh;
+
+	// Write Elf_Note header.
+	sh = elfwritenotehdr(".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG);
+	if(sh == nil)
+		return 0;
+
+	// Followed by OpenBSD string and version.
+	cwrite(ELF_NOTE_OPENBSD_NAME, ELF_NOTE_OPENBSD_NAMESZ);
+	LPUT(ELF_NOTE_OPENBSD_VERSION);
+
+	return sh->size;
+}
+
+void
+addbuildinfo(char *val)
+{
+	char *ov;
+	int i, b, j;
+
+	if(val[0] != '0' || val[1] != 'x') {
+		fprint(2, "%s: -B argument must start with 0x: %s\n", argv0, val);
+		exits("usage");
+	}
+	ov = val;
+	val += 2;
+	i = 0;
+	while(*val != '\0') {
+		if(val[1] == '\0') {
+			fprint(2, "%s: -B argument must have even number of digits: %s\n", argv0, ov);
+			exits("usage");
+		}
+		b = 0;
+		for(j = 0; j < 2; j++, val++) {
+			b *= 16;
+		  	if(*val >= '0' && *val <= '9')
+				b += *val - '0';
+			else if(*val >= 'a' && *val <= 'f')
+				b += *val - 'a' + 10;
+			else if(*val >= 'A' && *val <= 'F')
+				b += *val - 'A' + 10;
+			else {
+				fprint(2, "%s: -B argument contains invalid hex digit %c: %s\n", argv0, *val, ov);
+				exits("usage");
+			}
+		}
+		if(i >= nelem(buildinfo)) {
+			fprint(2, "%s: -B option too long (max %d digits): %s\n", argv0, (int)nelem(buildinfo), ov);
+			exits("usage");
+		}
+		buildinfo[i++] = b;
+	}
+	buildinfolen = i;
+}
+
+// Build info note
+#define ELF_NOTE_BUILDINFO_NAMESZ	4
+#define ELF_NOTE_BUILDINFO_TAG		3
+#define ELF_NOTE_BUILDINFO_NAME		"GNU\0"
+
+int
+elfbuildinfo(ElfShdr *sh, uint64 startva, uint64 resoff)
+{
+	int n;
+
+	n = ELF_NOTE_BUILDINFO_NAMESZ + rnd(buildinfolen, 4);
+	return elfnote(sh, startva, resoff, n);
+}
+
+int
+elfwritebuildinfo(void)
+{
+	ElfShdr *sh;
+
+	sh = elfwritenotehdr(".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, buildinfolen, ELF_NOTE_BUILDINFO_TAG);
+	if(sh == nil)
+		return 0;
+
+	cwrite(ELF_NOTE_BUILDINFO_NAME, ELF_NOTE_BUILDINFO_NAMESZ);
+	cwrite(buildinfo, buildinfolen);
+	cwrite("\0\0\0", rnd(buildinfolen, 4) - buildinfolen);
+
+	return sh->size;
+}
+
 extern int nelfsym;
 int elfverneed;
 
@@ -584,18 +706,18 @@ elfphload(Segment *seg)
 }
 
 ElfShdr*
-elfshbits(Section *sect)
+elfshname(char *name)
 {
 	int i, off;
 	ElfShdr *sh;
 	
 	for(i=0; i<nelfstr; i++) {
-		if(strcmp(sect->name, elfstr[i].s) == 0) {
+		if(strcmp(name, elfstr[i].s) == 0) {
 			off = elfstr[i].off;
 			goto found;
 		}
 	}
-	diag("cannot find elf name %s", sect->name);
+	diag("cannot find elf name %s", name);
 	errorexit();
 	return nil;
 
@@ -605,8 +727,30 @@ found:
 		if(sh->name == off)
 			return sh;
 	}
-
+	
 	sh = newElfShdr(off);
+	return sh;
+}
+
+ElfShdr*
+elfshalloc(Section *sect)
+{
+	ElfShdr *sh;
+	
+	sh = elfshname(sect->name);
+	sect->elfsect = sh;
+	return sh;
+}
+
+ElfShdr*
+elfshbits(Section *sect)
+{
+	ElfShdr *sh;
+	
+	sh = elfshalloc(sect);
+	if(sh->type > 0)
+		return sh;
+
 	if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen)
 		sh->type = SHT_PROGBITS;
 	else
@@ -616,10 +760,732 @@ found:
 		sh->flags |= SHF_EXECINSTR;
 	if(sect->rwx & 2)
 		sh->flags |= SHF_WRITE;
-	sh->addr = sect->vaddr;
+	if(!isobj)
+		sh->addr = sect->vaddr;
 	sh->addralign = PtrSize;
 	sh->size = sect->len;
 	sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
+
+	return sh;
+}
+
+ElfShdr*
+elfshreloc(Section *sect)
+{
+	int typ;
+	ElfShdr *sh;
+	char *prefix;
+	char buf[100];
 	
+	// If main section is SHT_NOBITS, nothing to relocate.
+	// Also nothing to relocate in .shstrtab.
+	if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen)
+		return nil;
+	if(strcmp(sect->name, ".shstrtab") == 0)
+		return nil;
+
+	if(thechar == '6') {
+		prefix = ".rela";
+		typ = SHT_RELA;
+	} else {
+		prefix = ".rel";
+		typ = SHT_REL;
+	}
+
+	snprint(buf, sizeof buf, "%s%s", prefix, sect->name);
+	sh = elfshname(buf);
+	sh->type = typ;
+	sh->entsize = PtrSize*(2+(typ==SHT_RELA));
+	sh->link = elfshname(".symtab")->shnum;
+	sh->info = sect->elfsect->shnum;
+	sh->off = sect->reloff;
+	sh->size = sect->rellen;
+	sh->addralign = PtrSize;
 	return sh;
 }
+
+void
+elfrelocsect(Section *sect, Sym *first)
+{
+	Sym *sym, *rs;
+	int32 eaddr;
+	Reloc *r;
+	int64 add;
+
+	// If main section is SHT_NOBITS, nothing to relocate.
+	// Also nothing to relocate in .shstrtab.
+	if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen)
+		return;
+	if(strcmp(sect->name, ".shstrtab") == 0)
+		return;
+
+	sect->reloff = cpos();
+	for(sym = first; sym != nil; sym = sym->next) {
+		if(!sym->reachable)
+			continue;
+		if(sym->value >= sect->vaddr)
+			break;
+	}
+	
+	eaddr = sect->vaddr + sect->len;
+	for(; sym != nil; sym = sym->next) {
+		if(!sym->reachable)
+			continue;
+		if(sym->value >= eaddr)
+			break;
+		cursym = sym;
+		
+		for(r = sym->r; r < sym->r+sym->nr; r++) {
+			// Ignore relocations handled by reloc already.
+			switch(r->type) {
+			case D_SIZE:
+				continue;
+			case D_ADDR:
+			case D_PCREL:
+				if(r->sym->type == SCONST)
+					continue;
+				break;
+			}
+
+			add = r->add;
+			rs = r->sym;
+			while(rs->outer != nil) {
+				add += rs->value - rs->outer->value;
+				rs = rs->outer;
+			}
+				
+			if(rs->elfsym == 0)
+				diag("reloc %d to non-elf symbol %s (rs=%s) %d", r->type, r->sym->name, rs->name, rs->type);
+
+			if(elfreloc1(r, sym->value - sect->vaddr + r->off, rs->elfsym, add) < 0)
+				diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
+		}
+	}
+		
+	sect->rellen = cpos() - sect->reloff;
+}	
+	
+void
+elfemitreloc(void)
+{
+	Section *sect;
+
+	while(cpos()&7)
+		cput(0);
+
+	elfrelocsect(segtext.sect, textp);
+	for(sect=segtext.sect->next; sect!=nil; sect=sect->next)
+		elfrelocsect(sect, datap);	
+	for(sect=segdata.sect; sect!=nil; sect=sect->next)
+		elfrelocsect(sect, datap);	
+}
+
+void
+doelf(void)
+{
+	Sym *s, *shstrtab, *dynstr;
+
+	if(!iself)
+		return;
+
+	/* predefine strings we need for section headers */
+	shstrtab = lookup(".shstrtab", 0);
+	shstrtab->type = SELFROSECT;
+	shstrtab->reachable = 1;
+
+	addstring(shstrtab, "");
+	addstring(shstrtab, ".text");
+	addstring(shstrtab, ".noptrdata");
+	addstring(shstrtab, ".data");
+	addstring(shstrtab, ".bss");
+	addstring(shstrtab, ".noptrbss");
+	if(HEADTYPE == Hnetbsd)
+		addstring(shstrtab, ".note.netbsd.ident");
+	if(HEADTYPE == Hopenbsd)
+		addstring(shstrtab, ".note.openbsd.ident");
+	if(buildinfolen > 0)
+		addstring(shstrtab, ".note.gnu.build-id");
+	addstring(shstrtab, ".elfdata");
+	addstring(shstrtab, ".rodata");
+	addstring(shstrtab, ".typelink");
+	if(flag_shared)
+		addstring(shstrtab, ".data.rel.ro");
+	addstring(shstrtab, ".gcdata");
+	addstring(shstrtab, ".gcbss");
+	addstring(shstrtab, ".gosymtab");
+	addstring(shstrtab, ".gopclntab");
+	
+	if(isobj) {
+		debug['s'] = 0;
+		debug['d'] = 1;
+
+		if(thechar == '6') {
+			addstring(shstrtab, ".rela.text");
+			addstring(shstrtab, ".rela.rodata");
+			addstring(shstrtab, ".rela.typelink");
+			addstring(shstrtab, ".rela.gcdata");
+			addstring(shstrtab, ".rela.gcbss");
+			addstring(shstrtab, ".rela.gosymtab");
+			addstring(shstrtab, ".rela.gopclntab");
+			addstring(shstrtab, ".rela.noptrdata");
+			addstring(shstrtab, ".rela.data");
+		} else {
+			addstring(shstrtab, ".rel.text");
+			addstring(shstrtab, ".rel.rodata");
+			addstring(shstrtab, ".rel.typelink");
+			addstring(shstrtab, ".rel.gcdata");
+			addstring(shstrtab, ".rel.gcbss");
+			addstring(shstrtab, ".rel.gosymtab");
+			addstring(shstrtab, ".rel.gopclntab");
+			addstring(shstrtab, ".rel.noptrdata");
+			addstring(shstrtab, ".rel.data");
+		}
+	}
+
+	if(!debug['s']) {
+		addstring(shstrtab, ".symtab");
+		addstring(shstrtab, ".strtab");
+		dwarfaddshstrings(shstrtab);
+	}
+	addstring(shstrtab, ".shstrtab");
+
+	if(!debug['d']) {	/* -d suppresses dynamic loader format */
+		addstring(shstrtab, ".interp");
+		addstring(shstrtab, ".hash");
+		addstring(shstrtab, ".got");
+		addstring(shstrtab, ".got.plt");
+		addstring(shstrtab, ".dynamic");
+		addstring(shstrtab, ".dynsym");
+		addstring(shstrtab, ".dynstr");
+		if(thechar == '6') {
+			addstring(shstrtab, ".rela");
+			addstring(shstrtab, ".rela.plt");
+		} else {
+			addstring(shstrtab, ".rel");
+			addstring(shstrtab, ".rel.plt");
+		}
+		addstring(shstrtab, ".plt");
+		addstring(shstrtab, ".gnu.version");
+		addstring(shstrtab, ".gnu.version_r");
+
+		/* dynamic symbol table - first entry all zeros */
+		s = lookup(".dynsym", 0);
+		s->type = SELFROSECT;
+		s->reachable = 1;
+		if(thechar == '6')
+			s->size += ELF64SYMSIZE;
+		else
+			s->size += ELF32SYMSIZE;
+
+		/* dynamic string table */
+		s = lookup(".dynstr", 0);
+		s->type = SELFROSECT;
+		s->reachable = 1;
+		if(s->size == 0)
+			addstring(s, "");
+		dynstr = s;
+
+		/* relocation table */
+		if(thechar == '6')
+			s = lookup(".rela", 0);
+		else
+			s = lookup(".rel", 0);
+		s->reachable = 1;
+		s->type = SELFROSECT;
+
+		/* global offset table */
+		s = lookup(".got", 0);
+		s->reachable = 1;
+		s->type = SELFSECT; // writable
+
+		/* hash */
+		s = lookup(".hash", 0);
+		s->reachable = 1;
+		s->type = SELFROSECT;
+
+		s = lookup(".got.plt", 0);
+		s->reachable = 1;
+		s->type = SELFSECT; // writable
+
+		s = lookup(".plt", 0);
+		s->reachable = 1;
+		s->type = SELFROSECT;
+		
+		elfsetupplt();
+		
+		if(thechar == '6')
+			s = lookup(".rela.plt", 0);
+		else
+			s = lookup(".rel.plt", 0);
+		s->reachable = 1;
+		s->type = SELFROSECT;
+		
+		s = lookup(".gnu.version", 0);
+		s->reachable = 1;
+		s->type = SELFROSECT;
+		
+		s = lookup(".gnu.version_r", 0);
+		s->reachable = 1;
+		s->type = SELFROSECT;
+
+		/* define dynamic elf table */
+		s = lookup(".dynamic", 0);
+		s->reachable = 1;
+		s->type = SELFSECT; // writable
+
+		/*
+		 * .dynamic table
+		 */
+		elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
+		elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
+		if(thechar == '6')
+			elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
+		else
+			elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
+		elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
+		elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
+		if(thechar == '6') {
+			elfwritedynentsym(s, DT_RELA, lookup(".rela", 0));
+			elfwritedynentsymsize(s, DT_RELASZ, lookup(".rela", 0));
+			elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
+		} else {
+			elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
+			elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
+			elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
+		}
+		if(rpath)
+			elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
+		
+		elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
+
+		if(thechar == '6') {
+			elfwritedynent(s, DT_PLTREL, DT_RELA);
+			elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0));
+			elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0));
+		} else {
+			elfwritedynent(s, DT_PLTREL, DT_REL);
+			elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
+			elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
+		}
+		
+		elfwritedynent(s, DT_DEBUG, 0);
+
+		if(flag_shared) {
+			Sym *init_sym = lookup(LIBINITENTRY, 0);
+			if(init_sym->type != STEXT)
+				diag("entry not text: %s", init_sym->name);
+			elfwritedynentsym(s, DT_INIT, init_sym);
+		}
+
+		// Do not write DT_NULL.  elfdynhash will finish it.
+	}
+}
+
+void
+shsym(ElfShdr *sh, Sym *s)
+{
+	vlong addr;
+	addr = symaddr(s);
+	if(sh->flags&SHF_ALLOC)
+		sh->addr = addr;
+	sh->off = datoff(addr);
+	sh->size = s->size;
+}
+
+void
+phsh(ElfPhdr *ph, ElfShdr *sh)
+{
+	ph->vaddr = sh->addr;
+	ph->paddr = ph->vaddr;
+	ph->off = sh->off;
+	ph->filesz = sh->size;
+	ph->memsz = sh->size;
+	ph->align = sh->addralign;
+}
+
+void
+asmbelfsetup(void)
+{
+	Section *sect;
+
+	/* This null SHdr must appear before all others */
+	elfshname("");
+	
+	for(sect=segtext.sect; sect!=nil; sect=sect->next)
+		elfshalloc(sect);
+	for(sect=segdata.sect; sect!=nil; sect=sect->next)
+		elfshalloc(sect);
+}
+
+void
+asmbelf(vlong symo)
+{
+	int a, o;
+	vlong startva, resoff;
+	ElfEhdr *eh;
+	ElfPhdr *ph, *pph, *pnote;
+	ElfShdr *sh;
+	Section *sect;
+
+	eh = getElfEhdr();
+	switch(thechar) {
+	default:
+		diag("unknown architecture in asmbelf");
+		errorexit();
+	case '5':
+		eh->machine = EM_ARM;
+		break;
+	case '6':
+		eh->machine = EM_X86_64;
+		break;
+	case '8':
+		eh->machine = EM_386;
+		break;
+	}
+
+	startva = INITTEXT - HEADR;
+	resoff = ELFRESERVE;
+	
+	pph = nil;
+	if(isobj) {
+		/* skip program headers */
+		eh->phoff = 0;
+		eh->phentsize = 0;
+		goto elfobj;
+	}
+
+	/* program header info */
+	pph = newElfPhdr();
+	pph->type = PT_PHDR;
+	pph->flags = PF_R + PF_X;
+	pph->off = eh->ehsize;
+	pph->vaddr = INITTEXT - HEADR + pph->off;
+	pph->paddr = INITTEXT - HEADR + pph->off;
+	pph->align = INITRND;
+
+	/*
+	 * PHDR must be in a loaded segment. Adjust the text
+	 * segment boundaries downwards to include it.
+	 */
+	o = segtext.vaddr - pph->vaddr;
+	segtext.vaddr -= o;
+	segtext.len += o;
+	o = segtext.fileoff - pph->off;
+	segtext.fileoff -= o;
+	segtext.filelen += o;
+
+	if(!debug['d']) {
+		/* interpreter */
+		sh = elfshname(".interp");
+		sh->type = SHT_PROGBITS;
+		sh->flags = SHF_ALLOC;
+		sh->addralign = 1;
+		if(interpreter == nil) {
+			switch(HEADTYPE) {
+			case Hlinux:
+				interpreter = linuxdynld;
+				break;
+			case Hfreebsd:
+				interpreter = freebsddynld;
+				break;
+			case Hnetbsd:
+				interpreter = netbsddynld;
+				break;
+			case Hopenbsd:
+				interpreter = openbsddynld;
+				break;
+			}
+		}
+		resoff -= elfinterp(sh, startva, resoff, interpreter);
+
+		ph = newElfPhdr();
+		ph->type = PT_INTERP;
+		ph->flags = PF_R;
+		phsh(ph, sh);
+	}
+
+	pnote = nil;
+	if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
+		sh = nil;
+		switch(HEADTYPE) {
+		case Hnetbsd:
+			sh = elfshname(".note.netbsd.ident");
+			resoff -= elfnetbsdsig(sh, startva, resoff);
+			break;
+		case Hopenbsd:
+			sh = elfshname(".note.openbsd.ident");
+			resoff -= elfopenbsdsig(sh, startva, resoff);
+			break;
+		}
+
+		pnote = newElfPhdr();
+		pnote->type = PT_NOTE;
+		pnote->flags = PF_R;
+		phsh(pnote, sh);
+	}
+
+	if(buildinfolen > 0) {
+		sh = elfshname(".note.gnu.build-id");
+		resoff -= elfbuildinfo(sh, startva, resoff);
+
+		if(pnote == nil) {
+			pnote = newElfPhdr();
+			pnote->type = PT_NOTE;
+			pnote->flags = PF_R;
+		}
+		phsh(pnote, sh);
+	}
+
+	// Additions to the reserved area must be above this line.
+	USED(resoff);
+
+	elfphload(&segtext);
+	elfphload(&segdata);
+
+	/* Dynamic linking sections */
+	if(!debug['d']) {	/* -d suppresses dynamic loader format */
+		sh = elfshname(".dynsym");
+		sh->type = SHT_DYNSYM;
+		sh->flags = SHF_ALLOC;
+		if(PtrSize == 8)
+			sh->entsize = ELF64SYMSIZE;
+		else
+			sh->entsize = ELF32SYMSIZE;
+		sh->addralign = PtrSize;
+		sh->link = elfshname(".dynstr")->shnum;
+		// sh->info = index of first non-local symbol (number of local symbols)
+		shsym(sh, lookup(".dynsym", 0));
+
+		sh = elfshname(".dynstr");
+		sh->type = SHT_STRTAB;
+		sh->flags = SHF_ALLOC;
+		sh->addralign = 1;
+		shsym(sh, lookup(".dynstr", 0));
+
+		if(elfverneed) {
+			sh = elfshname(".gnu.version");
+			sh->type = SHT_GNU_VERSYM;
+			sh->flags = SHF_ALLOC;
+			sh->addralign = 2;
+			sh->link = elfshname(".dynsym")->shnum;
+			sh->entsize = 2;
+			shsym(sh, lookup(".gnu.version", 0));
+			
+			sh = elfshname(".gnu.version_r");
+			sh->type = SHT_GNU_VERNEED;
+			sh->flags = SHF_ALLOC;
+			sh->addralign = PtrSize;
+			sh->info = elfverneed;
+			sh->link = elfshname(".dynstr")->shnum;
+			shsym(sh, lookup(".gnu.version_r", 0));
+		}
+
+		switch(eh->machine) {
+		case EM_X86_64:
+			sh = elfshname(".rela.plt");
+			sh->type = SHT_RELA;
+			sh->flags = SHF_ALLOC;
+			sh->entsize = ELF64RELASIZE;
+			sh->addralign = PtrSize;
+			sh->link = elfshname(".dynsym")->shnum;
+			sh->info = elfshname(".plt")->shnum;
+			shsym(sh, lookup(".rela.plt", 0));
+
+			sh = elfshname(".rela");
+			sh->type = SHT_RELA;
+			sh->flags = SHF_ALLOC;
+			sh->entsize = ELF64RELASIZE;
+			sh->addralign = 8;
+			sh->link = elfshname(".dynsym")->shnum;
+			shsym(sh, lookup(".rela", 0));
+			break;
+		
+		default:
+			sh = elfshname(".rel.plt");
+			sh->type = SHT_REL;
+			sh->flags = SHF_ALLOC;
+			sh->entsize = ELF32RELSIZE;
+			sh->link = elfshname(".dynsym")->shnum;
+			shsym(sh, lookup(".rel.plt", 0));
+
+			sh = elfshname(".rel");
+			sh->type = SHT_REL;
+			sh->flags = SHF_ALLOC;
+			sh->entsize = ELF32RELSIZE;
+			sh->addralign = 4;
+			sh->link = elfshname(".dynsym")->shnum;
+			shsym(sh, lookup(".rel", 0));
+			break;
+		}
+
+		sh = elfshname(".plt");
+		sh->type = SHT_PROGBITS;
+		sh->flags = SHF_ALLOC+SHF_EXECINSTR;
+		if(eh->machine == EM_X86_64)
+			sh->entsize = 16;
+		else
+			sh->entsize = 4;
+		sh->addralign = 4;
+		shsym(sh, lookup(".plt", 0));
+
+		sh = elfshname(".got");
+		sh->type = SHT_PROGBITS;
+		sh->flags = SHF_ALLOC+SHF_WRITE;
+		sh->entsize = PtrSize;
+		sh->addralign = PtrSize;
+		shsym(sh, lookup(".got", 0));
+
+		sh = elfshname(".got.plt");
+		sh->type = SHT_PROGBITS;
+		sh->flags = SHF_ALLOC+SHF_WRITE;
+		sh->entsize = PtrSize;
+		sh->addralign = PtrSize;
+		shsym(sh, lookup(".got.plt", 0));
+		
+		sh = elfshname(".hash");
+		sh->type = SHT_HASH;
+		sh->flags = SHF_ALLOC;
+		sh->entsize = 4;
+		sh->addralign = PtrSize;
+		sh->link = elfshname(".dynsym")->shnum;
+		shsym(sh, lookup(".hash", 0));
+
+		/* sh and PT_DYNAMIC for .dynamic section */
+		sh = elfshname(".dynamic");
+		sh->type = SHT_DYNAMIC;
+		sh->flags = SHF_ALLOC+SHF_WRITE;
+		sh->entsize = 2*PtrSize;
+		sh->addralign = PtrSize;
+		sh->link = elfshname(".dynstr")->shnum;
+		shsym(sh, lookup(".dynamic", 0));
+		ph = newElfPhdr();
+		ph->type = PT_DYNAMIC;
+		ph->flags = PF_R + PF_W;
+		phsh(ph, sh);
+		
+		/*
+		 * Thread-local storage segment (really just size).
+		 */
+		// Do not emit PT_TLS for OpenBSD since ld.so(1) does
+		// not currently support it. This is handled
+		// appropriately in runtime/cgo.
+		if(tlsoffset != 0 && HEADTYPE != Hopenbsd) {
+			ph = newElfPhdr();
+			ph->type = PT_TLS;
+			ph->flags = PF_R;
+			ph->memsz = -tlsoffset;
+			ph->align = PtrSize;
+		}
+	}
+
+	if(HEADTYPE == Hlinux) {
+		ph = newElfPhdr();
+		ph->type = PT_GNU_STACK;
+		ph->flags = PF_W+PF_R;
+		ph->align = PtrSize;
+		
+		ph = newElfPhdr();
+		ph->type = PT_PAX_FLAGS;
+		ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled
+		ph->align = PtrSize;
+	}
+
+elfobj:
+	sh = elfshname(".shstrtab");
+	sh->type = SHT_STRTAB;
+	sh->addralign = 1;
+	shsym(sh, lookup(".shstrtab", 0));
+	eh->shstrndx = sh->shnum;
+
+	// put these sections early in the list
+	if(!debug['s']) {
+		elfshname(".symtab");
+		elfshname(".strtab");
+	}
+
+	for(sect=segtext.sect; sect!=nil; sect=sect->next)
+		elfshbits(sect);
+	for(sect=segdata.sect; sect!=nil; sect=sect->next)
+		elfshbits(sect);
+
+	if(isobj) {
+		for(sect=segtext.sect; sect!=nil; sect=sect->next)
+			elfshreloc(sect);
+		for(sect=segdata.sect; sect!=nil; sect=sect->next)
+			elfshreloc(sect);
+	}
+		
+	if(!debug['s']) {
+		sh = elfshname(".symtab");
+		sh->type = SHT_SYMTAB;
+		sh->off = symo;
+		sh->size = symsize;
+		sh->addralign = PtrSize;
+		sh->entsize = 8+2*PtrSize;
+		sh->link = elfshname(".strtab")->shnum;
+		sh->info = elfglobalsymndx;
+
+		sh = elfshname(".strtab");
+		sh->type = SHT_STRTAB;
+		sh->off = symo+symsize;
+		sh->size = elfstrsize;
+		sh->addralign = 1;
+
+		// TODO(rsc): Enable for isobj too, once we know it works.
+		if(!isobj)
+			dwarfaddelfheaders();
+	}
+
+	/* Main header */
+	eh->ident[EI_MAG0] = '\177';
+	eh->ident[EI_MAG1] = 'E';
+	eh->ident[EI_MAG2] = 'L';
+	eh->ident[EI_MAG3] = 'F';
+	if(HEADTYPE == Hfreebsd)
+		eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
+	else if(HEADTYPE == Hnetbsd)
+		eh->ident[EI_OSABI] = ELFOSABI_NETBSD;
+	else if(HEADTYPE == Hopenbsd)
+		eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
+	if(PtrSize == 8)
+		eh->ident[EI_CLASS] = ELFCLASS64;
+	else
+		eh->ident[EI_CLASS] = ELFCLASS32;
+	eh->ident[EI_DATA] = ELFDATA2LSB;
+	eh->ident[EI_VERSION] = EV_CURRENT;
+
+	if(flag_shared)
+		eh->type = ET_DYN;
+	else if(isobj)
+		eh->type = ET_REL;
+	else
+		eh->type = ET_EXEC;
+
+	if(!isobj)
+		eh->entry = entryvalue();
+
+	eh->version = EV_CURRENT;
+
+	if(pph != nil) {
+		pph->filesz = eh->phnum * eh->phentsize;
+		pph->memsz = pph->filesz;
+	}
+
+	cseek(0);
+	a = 0;
+	a += elfwritehdr();
+	a += elfwritephdrs();
+	a += elfwriteshdrs();
+	if(!debug['d'])
+		a += elfwriteinterp();
+	if(!isobj) {
+		if(HEADTYPE == Hnetbsd)
+			a += elfwritenetbsdsig();
+		if(HEADTYPE == Hopenbsd)
+			a += elfwriteopenbsdsig();
+		if(buildinfolen > 0)
+			a += elfwritebuildinfo();
+	}
+	if(a > ELFRESERVE)	
+		diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
+}
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index 690ade9..3e22125 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -251,6 +251,7 @@ typedef struct {
 #define PT_LOPROC	0x70000000	/* First processor-specific type. */
 #define PT_HIPROC	0x7fffffff	/* Last processor-specific type. */
 #define PT_GNU_STACK	0x6474e551
+#define PT_PAX_FLAGS	0x65041580
 
 /* Values for p_flags. */
 #define PF_X		0x1		/* Executable. */
@@ -562,6 +563,10 @@ typedef struct {
 #define	R_ARM_GOTPC		25	/* Add PC-relative GOT table address. */
 #define	R_ARM_GOT32		26	/* Add PC-relative GOT offset. */
 #define	R_ARM_PLT32		27	/* Add PC-relative PLT offset. */
+#define	R_ARM_CALL		28
+#define	R_ARM_JUMP24	29
+#define	R_ARM_V4BX		40
+#define	R_ARM_GOT_PREL		96
 #define	R_ARM_GNU_VTENTRY	100
 #define	R_ARM_GNU_VTINHERIT	101
 #define	R_ARM_RSBREL32		250
@@ -571,7 +576,7 @@ typedef struct {
 #define	R_ARM_RPC24		254
 #define	R_ARM_RBASE		255
 
-#define	R_ARM_COUNT		33	/* Count of defined relocation types. */
+#define	R_ARM_COUNT		37	/* Count of defined relocation types. */
 
 
 #define	R_386_NONE	0	/* No relocation. */
@@ -836,7 +841,8 @@ typedef struct {
  * Section header.
  */
 
-typedef struct {
+typedef struct Elf64_Shdr Elf64_Shdr;
+struct Elf64_Shdr {
 	Elf64_Word	name;	/* Section name (index into the
 					   section header string table). */
 	Elf64_Word	type;	/* Section type. */
@@ -848,7 +854,9 @@ typedef struct {
 	Elf64_Word	info;	/* Depends on section type. */
 	Elf64_Xword	addralign;	/* Alignment in bytes. */
 	Elf64_Xword	entsize;	/* Size of each entry in section. */
-} Elf64_Shdr;
+	
+	int	shnum; /* section number, not stored on disk */
+};
 
 /*
  * Program header.
@@ -952,7 +960,6 @@ typedef Elf64_Phdr ElfPhdr;
 
 void	elfinit(void);
 ElfEhdr	*getElfEhdr(void);
-ElfShdr	*newElfShstrtab(vlong);
 ElfShdr	*newElfShdr(vlong);
 ElfPhdr	*newElfPhdr(void);
 uint32	elfwritehdr(void);
@@ -969,18 +976,40 @@ extern	int	numelfshdr;
 extern	int	iself;
 extern	int	elfverneed;
 int	elfinterp(ElfShdr*, uint64, uint64, char*);
-int	elfwriteinterp(vlong);
+int	elfwriteinterp(void);
 int	elfnetbsdsig(ElfShdr*, uint64, uint64);
-int	elfwritenetbsdsig(vlong);
+int	elfwritenetbsdsig(void);
+int	elfopenbsdsig(ElfShdr*, uint64, uint64);
+int	elfwriteopenbsdsig(void);
+void	addbuildinfo(char*);
+int	elfbuildinfo(ElfShdr*, uint64, uint64);
+int	elfwritebuildinfo(void);
 void	elfdynhash(void);
 ElfPhdr* elfphload(Segment*);
 ElfShdr* elfshbits(Section*);
+ElfShdr* elfshalloc(Section*);
+ElfShdr* elfshname(char*);
+ElfShdr* elfshreloc(Section*);
 void	elfsetstring(char*, int);
 void	elfaddverneed(Sym*);
+void	elfemitreloc(void);
+void	shsym(ElfShdr*, Sym*);
+void	phsh(ElfPhdr*, ElfShdr*);
+void	doelf(void);
+void	elfsetupplt(void);
+void	dwarfaddshstrings(Sym*);
+void	dwarfaddelfheaders(void);
+void	asmbelf(vlong symo);
+void	asmbelfsetup(void);
+extern char linuxdynld[];
+extern char freebsddynld[];
+extern char netbsddynld[];
+extern char openbsddynld[];
+int	elfreloc1(Reloc*, vlong off, int32 elfsym, vlong add);
 
 EXTERN	int	elfstrsize;
 EXTERN	char*	elfstrdat;
-EXTERN	int	elftextsh;
+EXTERN	int	buildinfolen;
 
 /*
  * Total amount of space to reserve at the start of the file
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index 3271be1..b2527b1 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -67,8 +67,7 @@ ilookup(char *name)
 }
 
 static void loadpkgdata(char*, char*, char*, int);
-static void loaddynimport(char*, char*, char*, int);
-static void loaddynexport(char*, char*, char*, int);
+static void loadcgo(char*, char*, char*, int);
 static int parsemethod(char**, char*, char**);
 static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**);
 
@@ -177,12 +176,12 @@ ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence)
 
 	loadpkgdata(filename, pkg, p0, p1 - p0);
 
-	// look for dynimport section
-	p0 = strstr(p1, "\n$$  // dynimport");
+	// look for cgo section
+	p0 = strstr(p1, "\n$$  // cgo");
 	if(p0 != nil) {
 		p0 = strchr(p0+1, '\n');
 		if(p0 == nil) {
-			fprint(2, "%s: found $$ // dynimport but no newline in %s\n", argv0, filename);
+			fprint(2, "%s: found $$ // cgo but no newline in %s\n", argv0, filename);
 			if(debug['u'])
 				errorexit();
 			return;
@@ -191,34 +190,12 @@ ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence)
 		if(p1 == nil)
 			p1 = strstr(p0, "\n!\n");
 		if(p1 == nil) {
-			fprint(2, "%s: cannot find end of // dynimport section in %s\n", argv0, filename);
+			fprint(2, "%s: cannot find end of // cgo section in %s\n", argv0, filename);
 			if(debug['u'])
 				errorexit();
 			return;
 		}
-		loaddynimport(filename, pkg, p0 + 1, p1 - (p0+1));
-	}
-
-	// look for dynexp section
-	p0 = strstr(p1, "\n$$  // dynexport");
-	if(p0 != nil) {
-		p0 = strchr(p0+1, '\n');
-		if(p0 == nil) {
-			fprint(2, "%s: found $$ // dynexporg but no newline in %s\n", argv0, filename);
-			if(debug['u'])
-				errorexit();
-			return;
-		}
-		p1 = strstr(p0, "\n$$");
-		if(p1 == nil)
-			p1 = strstr(p0, "\n!\n");
-		if(p1 == nil) {
-			fprint(2, "%s: cannot find end of // dynexporg section in %s\n", argv0, filename);
-			if(debug['u'])
-				errorexit();
-			return;
-		}
-		loaddynexport(filename, pkg, p0 + 1, p1 - (p0+1));
+		loadcgo(filename, pkg, p0 + 1, p1 - (p0+1));
 	}
 }
 
@@ -409,10 +386,16 @@ parsemethod(char **pp, char *ep, char **methp)
 	if(p == ep)
 		return 0;
 
+	// might be a comment about the method
+	if(p + 2 < ep && strncmp(p, "//", 2) == 0)
+		goto useline;
+	
 	// if it says "func (", it's a method
-	if(p + 6 >= ep || strncmp(p, "func (", 6) != 0)
-		return 0;
+	if(p + 6 < ep && strncmp(p, "func (", 6) == 0)
+		goto useline;
+	return 0;
 
+useline:
 	// definition to end of line
 	*methp = p;
 	while(p < ep && *p != '\n')
@@ -428,173 +411,182 @@ parsemethod(char **pp, char *ep, char **methp)
 }
 
 static void
-loaddynimport(char *file, char *pkg, char *p, int n)
+loadcgo(char *file, char *pkg, char *p, int n)
 {
-	char *pend, *next, *name, *def, *p0, *lib, *q;
+	char *pend, *next, *p0, *q;
+	char *f[10], *local, *remote, *lib;
+	int nf;
 	Sym *s;
 
 	USED(file);
 	pend = p + n;
+	p0 = nil;
 	for(; p<pend; p=next) {
 		next = strchr(p, '\n');
 		if(next == nil)
 			next = "";
 		else
 			*next++ = '\0';
-		p0 = p;
-		if(strncmp(p, "dynimport ", 10) != 0)
-			goto err;
-		p += 10;
-		name = p;
-		p = strchr(name, ' ');
-		if(p == nil)
-			goto err;
-		while(*p == ' ')
-			p++;
-		def = p;
-		p = strchr(def, ' ');
-		if(p == nil)
-			goto err;
-		while(*p == ' ')
-			p++;
-		lib = p;
 
-		// successful parse: now can edit the line
-		*strchr(name, ' ') = 0;
-		*strchr(def, ' ') = 0;
+		free(p0);
+		p0 = strdup(p); // save for error message
+		nf = tokenize(p, f, nelem(f));
 		
-		if(debug['d']) {
-			fprint(2, "%s: %s: cannot use dynamic imports with -d flag\n", argv0, file);
-			nerrors++;
-			return;
-		}
+		if(strcmp(f[0], "cgo_import_dynamic") == 0) {
+			if(nf < 2 || nf > 4)
+				goto err;
+			
+			local = f[1];
+			remote = local;
+			if(nf > 2)
+				remote = f[2];
+			lib = "";
+			if(nf > 3)
+				lib = f[3];
+			
+			if(debug['d']) {
+				fprint(2, "%s: %s: cannot use dynamic imports with -d flag\n", argv0, file);
+				nerrors++;
+				return;
+			}
 		
-		if(strcmp(name, "_") == 0 && strcmp(def, "_") == 0) {
-			// allow #pragma dynimport _ _ "foo.so"
-			// to force a link of foo.so.
-			havedynamic = 1;
-			adddynlib(lib);
+			if(strcmp(local, "_") == 0 && strcmp(remote, "_") == 0) {
+				// allow #pragma dynimport _ _ "foo.so"
+				// to force a link of foo.so.
+				havedynamic = 1;
+				adddynlib(lib);
+				continue;
+			}
+
+			local = expandpkg(local, pkg);
+			q = strchr(remote, '#');
+			if(q)
+				*q++ = '\0';
+			s = lookup(local, 0);
+			if(local != f[1])
+				free(local);
+			if(s->type == 0 || s->type == SXREF) {
+				s->dynimplib = lib;
+				s->dynimpname = remote;
+				s->dynimpvers = q;
+				s->type = SDYNIMPORT;
+				havedynamic = 1;
+			}
 			continue;
 		}
-
-		name = expandpkg(name, pkg);
-		q = strchr(def, '@');
-		if(q)
-			*q++ = '\0';
-		s = lookup(name, 0);
-		free(name);
-		if(s->type == 0 || s->type == SXREF) {
-			s->dynimplib = lib;
-			s->dynimpname = def;
-			s->dynimpvers = q;
-			s->type = SDYNIMPORT;
-			havedynamic = 1;
+		
+		if(strcmp(f[0], "cgo_import_static") == 0) {
+			if(nf != 2)
+				goto err;
+			if(isobj) {
+				local = f[1];
+				s = lookup(local, 0);
+				s->type = SHOSTOBJ;
+				s->size = 0;
+			}
+			continue;
 		}
-	}
-	return;
 
-err:
-	fprint(2, "%s: %s: invalid dynimport line: %s\n", argv0, file, p0);
-	nerrors++;
-}
-
-static void
-loaddynexport(char *file, char *pkg, char *p, int n)
-{
-	char *pend, *next, *local, *elocal, *remote, *p0;
-	Sym *s;
-
-	USED(file);
-	pend = p + n;
-	for(; p<pend; p=next) {
-		next = strchr(p, '\n');
-		if(next == nil)
-			next = "";
-		else
-			*next++ = '\0';
-		p0 = p;
-		if(strncmp(p, "dynexport ", 10) != 0)
-			goto err;
-		p += 10;
-		local = p;
-		p = strchr(local, ' ');
-		if(p == nil)
-			goto err;
-		while(*p == ' ')
-			p++;
-		remote = p;
-
-		// successful parse: now can edit the line
-		*strchr(local, ' ') = 0;
+		if(strcmp(f[0], "cgo_export") == 0) {
+			if(nf < 2 || nf > 3)
+				goto err;
+			local = f[1];
+			if(nf > 2)
+				remote = f[2];
+			else
+				remote = local;
+			local = expandpkg(local, pkg);
+			s = lookup(local, 0);
+			if(s->dynimplib != nil) {
+				fprint(2, "%s: symbol is both imported and exported: %s\n", argv0, local);
+				nerrors++;
+			}
+			s->dynimpname = remote;
+			s->dynexport = 1;
 
-		elocal = expandpkg(local, pkg);
+			if(ndynexp%32 == 0)
+				dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
+			dynexp[ndynexp++] = s;
 
-		s = lookup(elocal, 0);
-		if(s->dynimplib != nil) {
-			fprint(2, "%s: symbol is both dynimport and dynexport %s\n", argv0, local);
-			nerrors++;
+			if(local != f[1])
+				free(local);
+			continue;
+		}
+		
+		if(strcmp(f[0], "cgo_dynamic_linker") == 0) {
+			if(nf != 2)
+				goto err;
+			
+			if(!debug['I']) { // not overridden by command line
+				if(interpreter != nil && strcmp(interpreter, f[1]) != 0) {
+					fprint(2, "%s: conflict dynlinker: %s and %s\n", argv0, interpreter, f[1]);
+					nerrors++;
+					return;
+				}
+				free(interpreter);
+				interpreter = strdup(f[1]);
+			}
+			continue;
 		}
-		s->dynimpname = remote;
-		s->dynexport = 1;
-
-		if(ndynexp%32 == 0)
-			dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
-		dynexp[ndynexp++] = s;
-
-		if (elocal != local)
-			free(elocal);
 	}
+	free(p0);
 	return;
 
 err:
-	fprint(2, "%s: invalid dynexport line: %s\n", argv0, p0);
+	fprint(2, "%s: %s: invalid dynimport line: %s\n", argv0, file, p0);
 	nerrors++;
 }
 
-static int markdepth;
+static Sym *markq;
+static Sym *emarkq;
 
 static void
-marktext(Sym *s)
+mark1(Sym *s, Sym *parent)
 {
-	Auto *a;
-	Prog *p;
-
-	if(s == S)
+	if(s == S || s->reachable)
 		return;
-	markdepth++;
-	if(debug['v'] > 1)
-		Bprint(&bso, "%d marktext %s\n", markdepth, s->name);
-	for(a=s->autom; a; a=a->link)
-		mark(a->gotype);
-	for(p=s->text; p != P; p=p->link) {
-		if(p->from.sym)
-			mark(p->from.sym);
-		if(p->to.sym)
-			mark(p->to.sym);
-	}
-	markdepth--;
+	if(strncmp(s->name, "go.weak.", 8) == 0)
+		return;
+	s->reachable = 1;
+	s->reachparent = parent;
+	if(markq == nil)
+		markq = s;
+	else
+		emarkq->queue = s;
+	emarkq = s;
 }
 
 void
 mark(Sym *s)
 {
-	int i;
+	mark1(s, nil);
+}
 
-	if(s == S || s->reachable)
-		return;
-	if(strncmp(s->name, "weak.", 5) == 0)
-		return;
-	s->reachable = 1;
-	if(s->text)
-		marktext(s);
-	for(i=0; i<s->nr; i++)
-		mark(s->r[i].sym);
-	if(s->gotype)
-		mark(s->gotype);
-	if(s->sub)
-		mark(s->sub);
-	if(s->outer)
-		mark(s->outer);
+static void
+markflood(void)
+{
+	Auto *a;
+	Prog *p;
+	Sym *s;
+	int i;
+	
+	for(s=markq; s!=S; s=s->queue) {
+		if(s->text) {
+			if(debug['v'] > 1)
+				Bprint(&bso, "marktext %s\n", s->name);
+			for(a=s->autom; a; a=a->link)
+				mark1(a->gotype, s);
+			for(p=s->text; p != P; p=p->link) {
+				mark1(p->from.sym, s);
+				mark1(p->to.sym, s);
+			}
+		}
+		for(i=0; i<s->nr; i++)
+			mark1(s->r[i].sym, s);
+		mark1(s->gotype, s);
+		mark1(s->sub, s);
+		mark1(s->outer, s);
+	}
 }
 
 static char*
@@ -651,19 +643,30 @@ void
 deadcode(void)
 {
 	int i;
-	Sym *s, *last;
+	Sym *s, *last, *p;
 	Auto *z;
+	Fmt fmt;
 
 	if(debug['v'])
 		Bprint(&bso, "%5.2f deadcode\n", cputime());
 
 	mark(lookup(INITENTRY, 0));
+	if(flag_shared)
+		mark(lookup(LIBINITENTRY, 0));
 	for(i=0; i<nelem(morename); i++)
 		mark(lookup(morename[i], 0));
 
 	for(i=0; i<ndynexp; i++)
 		mark(dynexp[i]);
+
+	markflood();
 	
+	// keep each beginning with 'typelink.' if the symbol it points at is being kept.
+	for(s = allsym; s != S; s = s->allsym) {
+		if(strncmp(s->name, "go.typelink.", 12) == 0)
+			s->reachable = s->nr==1 && s->r[0].sym->reachable;
+	}
+
 	// remove dead text but keep file information (z symbols).
 	last = nil;
 	z = nil;
@@ -690,11 +693,34 @@ deadcode(void)
 		last->next = nil;
 	
 	for(s = allsym; s != S; s = s->allsym)
-		if(strncmp(s->name, "weak.", 5) == 0) {
+		if(strncmp(s->name, "go.weak.", 8) == 0) {
 			s->special = 1;  // do not lay out in data segment
 			s->reachable = 1;
 			s->hide = 1;
 		}
+	
+	// record field tracking references
+	fmtstrinit(&fmt);
+	for(s = allsym; s != S; s = s->allsym) {
+		if(strncmp(s->name, "go.track.", 9) == 0) {
+			s->special = 1;  // do not lay out in data segment
+			s->hide = 1;
+			if(s->reachable) {
+				fmtprint(&fmt, "%s", s->name+9);
+				for(p=s->reachparent; p; p=p->reachparent)
+					fmtprint(&fmt, "\t%s", p->name);
+				fmtprint(&fmt, "\n");
+			}
+			s->type = SCONST;
+			s->value = 0;
+		}
+	}
+	if(tracksym == nil)
+		return;
+	s = lookup(tracksym, 0);
+	if(!s->reachable)
+		return;
+	addstrdata(tracksym, fmtstrflush(&fmt));
 }
 
 void
@@ -705,11 +731,12 @@ doweak(void)
 	// resolve weak references only if
 	// target symbol will be in binary anyway.
 	for(s = allsym; s != S; s = s->allsym) {
-		if(strncmp(s->name, "weak.", 5) == 0) {
-			t = rlookup(s->name+5, s->version);
+		if(strncmp(s->name, "go.weak.", 8) == 0) {
+			t = rlookup(s->name+8, s->version);
 			if(t && t->type != 0 && t->reachable) {
 				s->value = t->value;
 				s->type = t->type;
+				s->outer = t;
 			} else {
 				s->type = SCONST;
 				s->value = 0;
@@ -871,3 +898,28 @@ importcycles(void)
 	for(p=pkgall; p; p=p->all)
 		cycle(p);
 }
+
+static int
+scmp(const void *p1, const void *p2)
+{
+	Sym *s1, *s2;
+
+	s1 = *(Sym**)p1;
+	s2 = *(Sym**)p2;
+	return strcmp(s1->dynimpname, s2->dynimpname);
+}
+void
+sortdynexp(void)
+{
+	int i;
+
+	// On Mac OS X Mountain Lion, we must sort exported symbols
+	// So we sort them here and pre-allocate dynid for them
+	// See http://golang.org/issue/4029
+	if(HEADTYPE != Hdarwin)
+		return;
+	qsort(dynexp, ndynexp, sizeof dynexp[0], scmp);
+	for(i=0; i<ndynexp; i++) {
+		dynexp[i]->dynid = -i-100; // also known to [68]l/asm.c:^adddynsym
+	}
+}
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
index bd4f3e7..2bbf4f8 100644
--- a/src/cmd/ld/ldelf.c
+++ b/src/cmd/ld/ldelf.c
@@ -308,9 +308,19 @@ uchar ElfMagic[4] = { 0x7F, 'E', 'L', 'F' };
 
 static ElfSect*	section(ElfObj*, char*);
 static int	map(ElfObj*, ElfSect*);
-static int	readsym(ElfObj*, int i, ElfSym*);
+static int	readsym(ElfObj*, int i, ElfSym*, int);
 static int	reltype(char*, int, uchar*);
 
+int
+valuecmp(Sym *a, Sym *b)
+{
+	if(a->value < b->value)
+		return -1;
+	if(a->value > b->value)
+		return +1;
+	return 0;
+}
+
 void
 ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
 {
@@ -327,8 +337,10 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
 	Endian *e;
 	Reloc *r, *rp;
 	Sym *s;
+	Sym **symbols;
+
+	symbols = nil;
 
-	USED(pkg);
 	if(debug['v'])
 		Bprint(&bso, "%5.2f ldelf %s\n", cputime(), pn);
 
@@ -516,7 +528,7 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
 		if(sect->type != ElfSectNobits && map(obj, sect) < 0)
 			goto bad;
 		
-		name = smprint("%s(%s)", pn, sect->name);
+		name = smprint("%s(%s)", pkg, sect->name);
 		s = lookup(name, version);
 		free(name);
 		switch((int)sect->flags&(ElfSectFlagAlloc|ElfSectFlagWrite|ElfSectFlagExec)) {
@@ -539,15 +551,99 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
 		}
 		s->size = sect->size;
 		s->align = sect->align;
+		sect->sym = s;
+	}
+
+	// enter sub-symbols into symbol table.
+	// symbol 0 is the null symbol.
+	symbols = malloc(obj->nsymtab * sizeof(symbols[0]));
+	if(symbols == nil) {
+		diag("out of memory");
+		errorexit();
+	}
+	for(i=1; i<obj->nsymtab; i++) {
+		if(readsym(obj, i, &sym, 1) < 0)
+			goto bad;
+		symbols[i] = sym.sym;
+		if(sym.type != ElfSymTypeFunc && sym.type != ElfSymTypeObject && sym.type != ElfSymTypeNone)
+			continue;
+		if(sym.shndx == ElfSymShnCommon) {
+			s = sym.sym;
+			if(s->size < sym.size)
+				s->size = sym.size;
+			if(s->type == 0 || s->type == SXREF)
+				s->type = SBSS;
+			continue;
+		}
+		if(sym.shndx >= obj->nsect || sym.shndx == 0)
+			continue;
+		// even when we pass needSym == 1 to readsym, it might still return nil to skip some unwanted symbols
+		if(sym.sym == S)
+			continue;
+		sect = obj->sect+sym.shndx;
+		if(sect->sym == nil) {
+			diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type);
+			continue;
+		}
+		s = sym.sym;
+		if(s->outer != S) {
+			if(s->dupok)
+				continue;
+			diag("%s: duplicate symbol reference: %s in both %s and %s", pn, s->name, s->outer->name, sect->sym->name);
+			errorexit();
+		}
+		s->sub = sect->sym->sub;
+		sect->sym->sub = s;
+		s->type = sect->sym->type | (s->type&~SMASK) | SSUB;
+		if(!s->dynexport) {
+			s->dynimplib = nil;  // satisfy dynimport
+			s->dynimpname = nil;  // satisfy dynimport
+		}
+		s->value = sym.value;
+		s->size = sym.size;
+		s->outer = sect->sym;
+		if(sect->sym->type == STEXT) {
+			Prog *p;
+
+			if(s->text != P) {
+				if(!s->dupok)
+					diag("%s: duplicate definition of %s", pn, s->name);
+			} else {
+				// build a TEXT instruction with a unique pc
+				// just to make the rest of the linker happy.
+				p = prg();
+				p->as = ATEXT;
+				p->from.type = D_EXTERN;
+				p->from.sym = s;
+				p->textflag = 7;
+				p->to.type = D_CONST;
+				p->link = nil;
+				p->pc = pc++;
+				s->text = p;
+			}
+		}
+	}
+	
+	// Sort outer lists by address, adding to textp.
+	// This keeps textp in increasing address order.
+	for(i=0; i<obj->nsect; i++) {
+		s = obj->sect[i].sym;
+		if(s == S)
+			continue;
+		if(s->sub)
+			s->sub = listsort(s->sub, valuecmp, offsetof(Sym, sub));
 		if(s->type == STEXT) {
 			if(etextp)
 				etextp->next = s;
 			else
 				textp = s;
 			etextp = s;
+			for(s = s->sub; s != S; s = s->sub) {
+				etextp->next = s;
+				etextp = s;
+			}
 		}
-		sect->sym = s;
-	}		
+	}
 
 	// load relocations
 	for(i=0; i<obj->nsect; i++) {
@@ -588,14 +684,24 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
 					p += 4;
 				}
 			}
-			if(readsym(obj, info>>32, &sym) < 0)
-				goto bad;
-			if(sym.sym == nil) {
-				werrstr("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d",
-					sect->sym->name, j, (int)(info>>32), sym.name, sym.shndx, sym.type);
-				goto bad;
+			if((info & 0xffffffff) == 0) { // skip R_*_NONE relocation
+				j--;
+				n--;
+				continue;
+			}
+			if((info >> 32) == 0) { // absolute relocation, don't bother reading the null symbol
+				rp->sym = S;
+			} else {
+				if(readsym(obj, info>>32, &sym, 0) < 0)
+					goto bad;
+				sym.sym = symbols[info>>32];
+				if(sym.sym == nil) {
+					werrstr("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d",
+						sect->sym->name, j, (int)(info>>32), sym.name, sym.shndx, sym.type);
+					goto bad;
+				}
+				rp->sym = sym.sym;
 			}
-			rp->sym = sym.sym;
 			rp->type = reltype(pn, (uint32)info, &rp->siz);
 			if(rela)
 				rp->add = add;
@@ -615,65 +721,13 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
 		s->r = r;
 		s->nr = n;
 	}
+	free(symbols);
 
-	// enter sub-symbols into symbol table.
-	// symbol 0 is the null symbol.
-	for(i=1; i<obj->nsymtab; i++) {
-		if(readsym(obj, i, &sym) < 0)
-			goto bad;
-		if(sym.type != ElfSymTypeFunc && sym.type != ElfSymTypeObject && sym.type != ElfSymTypeNone)
-			continue;
-		if(sym.shndx == ElfSymShnCommon) {
-			s = sym.sym;
-			if(s->size < sym.size)
-				s->size = sym.size;
-			if(s->type == 0 || s->type == SXREF)
-				s->type = SBSS;
-			continue;
-		}
-		if(sym.shndx >= obj->nsect || sym.shndx == 0)
-			continue;
-		sect = obj->sect+sym.shndx;
-		if(sect->sym == nil) {
-			diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type);
-			continue;
-		}
-		s = sym.sym;
-		s->sub = sect->sym->sub;
-		sect->sym->sub = s;
-		s->type = sect->sym->type | SSUB;
-		if(!s->dynexport) {
-			s->dynimplib = nil;  // satisfy dynimport
-			s->dynimpname = nil;  // satisfy dynimport
-		}
-		s->value = sym.value;
-		s->size = sym.size;
-		s->outer = sect->sym;
-		if(sect->sym->type == STEXT) {
-			Prog *p;
-
-			if(s->text != P)
-				diag("%s: duplicate definition of %s", pn, s->name);
-			// build a TEXT instruction with a unique pc
-			// just to make the rest of the linker happy.
-			p = prg();
-			p->as = ATEXT;
-			p->from.type = D_EXTERN;
-			p->from.sym = s;
-			p->textflag = 7;
-			p->to.type = D_CONST;
-			p->link = nil;
-			p->pc = pc++;
-			s->text = p;
-
-			etextp->next = s;
-			etextp = s;
-		}
-	}
 	return;
 
 bad:
 	diag("%s: malformed elf file: %r", pn);
+	free(symbols);
 }
 
 static ElfSect*
@@ -707,7 +761,7 @@ map(ElfObj *obj, ElfSect *sect)
 }
 
 static int
-readsym(ElfObj *obj, int i, ElfSym *sym)
+readsym(ElfObj *obj, int i, ElfSym *sym, int needSym)
 {
 	Sym *s;
 
@@ -715,6 +769,9 @@ readsym(ElfObj *obj, int i, ElfSym *sym)
 		werrstr("invalid elf symbol index");
 		return -1;
 	}
+	if(i == 0) {
+		diag("readym: read null symbol!");
+	}
 
 	if(obj->is64) {
 		ElfSymBytes64 *b;
@@ -743,8 +800,6 @@ readsym(ElfObj *obj, int i, ElfSym *sym)
 	s = nil;
 	if(strcmp(sym->name, "_GLOBAL_OFFSET_TABLE_") == 0)
 		sym->name = ".got";
-	if(strcmp(sym->name, "__stack_chk_fail_local") == 0)
-		sym->other = 0;  // rewrite hidden -> default visibility
 	switch(sym->type) {
 	case ElfSymTypeSection:
 		s = obj->sect[sym->shndx].sym;
@@ -754,13 +809,37 @@ readsym(ElfObj *obj, int i, ElfSym *sym)
 	case ElfSymTypeNone:
 		switch(sym->bind) {
 		case ElfSymBindGlobal:
-			if(sym->other != 2) {
+			if(needSym) {
 				s = lookup(sym->name, 0);
-				break;
+				// for global scoped hidden symbols we should insert it into
+				// symbol hash table, but mark them as hidden.
+				// __i686.get_pc_thunk.bx is allowed to be duplicated, to
+				// workaround that we set dupok.
+				// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
+				// set dupok generally. See http://codereview.appspot.com/5823055/
+				// comment #5 for details.
+				if(s && sym->other == 2) {
+					s->type |= SHIDDEN;
+					s->dupok = 1;
+				}
 			}
-			// fall through
+			break;
 		case ElfSymBindLocal:
-			s = lookup(sym->name, version);
+			if(!(thechar == '5' && (strcmp(sym->name, "$a") == 0 || strcmp(sym->name, "$d") == 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
+					// don't bother to add them into hash table
+					s = newsym(sym->name, version);
+					s->type |= SHIDDEN;
+				}
+			break;
+		case ElfSymBindWeak:
+			if(needSym) {
+				s = newsym(sym->name, 0);
+				if(sym->other == 2)
+					s->type |= SHIDDEN;
+			}
 			break;
 		default:
 			werrstr("%s: invalid symbol binding %d", sym->name, sym->bind);
@@ -797,6 +876,18 @@ reltype(char *pn, int elftype, uchar *siz)
 	switch(R(thechar, elftype)) {
 	default:
 		diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype);
+	case R('5', R_ARM_ABS32):
+	case R('5', R_ARM_GOT32):
+	case R('5', R_ARM_PLT32):
+	case R('5', R_ARM_GOTOFF):
+	case R('5', R_ARM_GOTPC):
+	case R('5', R_ARM_THM_PC22):
+	case R('5', R_ARM_REL32):
+	case R('5', R_ARM_CALL):
+	case R('5', R_ARM_V4BX):
+	case R('5', R_ARM_GOT_PREL):
+	case R('5', R_ARM_PC24):
+	case R('5', R_ARM_JUMP24):
 	case R('6', R_X86_64_PC32):
 	case R('6', R_X86_64_PLT32):
 	case R('6', R_X86_64_GOTPCREL):
diff --git a/src/cmd/ld/ldmacho.c b/src/cmd/ld/ldmacho.c
index 3888487..41852f1 100644
--- a/src/cmd/ld/ldmacho.c
+++ b/src/cmd/ld/ldmacho.c
@@ -440,7 +440,6 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
 	Reloc *r, *rp;
 	char *name;
 
-	USED(pkg);
 	version++;
 	base = Boffset(f);
 	if(Bread(f, hdr, sizeof hdr) != sizeof hdr)
@@ -566,16 +565,21 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
 			continue;
 		if(strcmp(sect->name, "__eh_frame") == 0)
 			continue;
-		name = smprint("%s(%s/%s)", pn, sect->segname, sect->name);
+		name = smprint("%s(%s/%s)", pkg, sect->segname, sect->name);
 		s = lookup(name, version);
 		if(s->type != 0) {
 			werrstr("duplicate %s/%s", sect->segname, sect->name);
 			goto bad;
 		}
 		free(name);
-		s->p = dat + sect->addr - c->seg.vmaddr;
+
 		s->np = sect->size;
 		s->size = s->np;
+		if((sect->flags & 0xff) == 1) // S_ZEROFILL
+			s->p = mal(s->size);
+		else {
+			s->p = dat + sect->addr - c->seg.vmaddr;
+		}
 		
 		if(strcmp(sect->segname, "__TEXT") == 0) {
 			if(strcmp(sect->name, "__text") == 0)
@@ -589,13 +593,6 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
 			} else
 				s->type = SDATA;
 		}
-		if(s->type == STEXT) {
-			if(etextp)
-				etextp->next = s;
-			else
-				textp = s;
-			etextp = s;
-		}
 		sect->sym = s;
 	}
 	
@@ -627,6 +624,12 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
 			werrstr("reference to invalid section %s/%s", sect->segname, sect->name);
 			continue;
 		}
+		if(s->outer != S) {
+			if(s->dupok)
+				continue;
+			diag("%s: duplicate symbol reference: %s in both %s and %s", pn, s->name, s->outer->name, sect->sym->name);
+			errorexit();
+		}
 		s->type = outer->type | SSUB;
 		s->sub = outer->sub;
 		outer->sub = s;
@@ -657,11 +660,29 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
 			p->link = nil;
 			p->pc = pc++;
 			s->text = p;
+		}
+		sym->sym = s;
+	}
 
-			etextp->next = s;
+	// Sort outer lists by address, adding to textp.
+	// This keeps textp in increasing address order.
+	for(i=0; i<c->seg.nsect; i++) {
+		sect = &c->seg.sect[i];
+		if((s = sect->sym) == S)
+			continue;
+		if(s->sub)
+			s->sub = listsort(s->sub, valuecmp, offsetof(Sym, sub));
+		if(s->type == STEXT) {
+			if(etextp)
+				etextp->next = s;
+			else
+				textp = s;
 			etextp = s;
+			for(s = s->sub; s != S; s = s->sub) {
+				etextp->next = s;
+				etextp = s;
+			}
 		}
-		sym->sym = s;
 	}
 
 	// load relocations
@@ -680,19 +701,28 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
 				int k;
 				MachoSect *ks;
 
-				if(thechar != '8')
+				if(thechar != '8') {
+					// mach-o only uses scattered relocation on 32-bit platforms
 					diag("unexpected scattered relocation");
+					continue;
+				}
 
-				// on 386, rewrite scattered 4/1 relocation into
-				// the pseudo-pc-relative reference that it is.
+				// on 386, rewrite scattered 4/1 relocation and some
+				// scattered 2/1 relocation into the pseudo-pc-relative
+				// reference that it is.
 				// assume that the second in the pair is in this section
 				// and use that as the pc-relative base.
-				if(thechar != '8' || rel->type != 4 || j+1 >= sect->nreloc ||
-						!(rel+1)->scattered || (rel+1)->type != 1 ||
-						(rel+1)->value < sect->addr || (rel+1)->value >= sect->addr+sect->size) {
+				if(j+1 >= sect->nreloc) {
+					werrstr("unsupported scattered relocation %d", (int)rel->type);
+					goto bad;
+				}
+				if(!(rel+1)->scattered || (rel+1)->type != 1 ||
+				   (rel->type != 4 && rel->type != 2) ||
+				   (rel+1)->value < sect->addr || (rel+1)->value >= sect->addr+sect->size) {
 					werrstr("unsupported scattered relocation %d/%d", (int)rel->type, (int)(rel+1)->type);
 					goto bad;
 				}
+
 				rp->siz = rel->length;
 				rp->off = rel->addr;
 				
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
index feb8620..39c15e6 100644
--- a/src/cmd/ld/ldpe.c
+++ b/src/cmd/ld/ldpe.c
@@ -145,7 +145,6 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 	PeSym *sym;
 
 	USED(len);
-	USED(pkg);
 	if(debug['v'])
 		Bprint(&bso, "%5.2f ldpe %s\n", cputime(), pn);
 	
@@ -213,7 +212,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 		if(map(obj, sect) < 0)
 			goto bad;
 		
-		name = smprint("%s(%s)", pn, sect->name);
+		name = smprint("%s(%s)", pkg, sect->name);
 		s = lookup(name, version);
 		free(name);
 		switch(sect->sh.Characteristics&(IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_CNT_INITIALIZED_DATA|
@@ -237,13 +236,6 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 		s->p = sect->base;
 		s->np = sect->size;
 		s->size = sect->size;
-		if(s->type == STEXT) {
-			if(etextp)
-				etextp->next = s;
-			else
-				textp = s;
-			etextp = s;
-		}
 		sect->sym = s;
 		if(strcmp(sect->name, ".rsrc") == 0)
 			setpersrc(sect->sym);
@@ -300,6 +292,11 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 					rp->add = le64(rsect->base+rp->off);
 					break;
 			}
+			// 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;
 		}
 		qsort(r, rsect->sh.NumberOfRelocations, sizeof r[0], rbyoff);
 		
@@ -341,6 +338,13 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 
 		if(sect == nil) 
 			return;
+
+		if(s->outer != S) {
+			if(s->dupok)
+				continue;
+			diag("%s: duplicate symbol reference: %s in both %s and %s", pn, s->name, s->outer->name, sect->sym->name);
+			errorexit();
+		}
 		s->sub = sect->sym->sub;
 		sect->sym->sub = s;
 		s->type = sect->sym->type | SSUB;
@@ -363,9 +367,27 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 			p->link = nil;
 			p->pc = pc++;
 			s->text = p;
-	
-			etextp->next = s;
+		}
+	}
+
+	// Sort outer lists by address, adding to textp.
+	// This keeps textp in increasing address order.
+	for(i=0; i<obj->nsect; i++) {
+		s = obj->sect[i].sym;
+		if(s == S)
+			continue;
+		if(s->sub)
+			s->sub = listsort(s->sub, valuecmp, offsetof(Sym, sub));
+		if(s->type == STEXT) {
+			if(etextp)
+				etextp->next = s;
+			else
+				textp = s;
 			etextp = s;
+			for(s = s->sub; s != S; s = s->sub) {
+				etextp->next = s;
+				etextp = s;
+			}
 		}
 	}
 
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index 4a100ca..26fa4f2 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -72,6 +72,8 @@ Lflag(char *arg)
 void
 libinit(void)
 {
+	char *race;
+
 	fmtinstall('i', iconv);
 	fmtinstall('Y', Yconv);
 	fmtinstall('Z', Zconv);
@@ -80,7 +82,10 @@ libinit(void)
 		print("goarch is not known: %s\n", goarch);
 
 	// add goroot to the end of the libdir list.
-	Lflag(smprint("%s/pkg/%s_%s", goroot, goos, goarch));
+	race = "";
+	if(flag_race)
+		race = "_race";
+	Lflag(smprint("%s/pkg/%s_%s%s", goroot, goos, goarch, race));
 
 	// Unix doesn't like it when we write to a running (or, sometimes,
 	// recently run) binary, so remove the output file before writing it.
@@ -99,6 +104,13 @@ libinit(void)
 		sprint(INITENTRY, "_rt0_%s_%s", goarch, goos);
 	}
 	lookup(INITENTRY, 0)->type = SXREF;
+	if(flag_shared) {
+		if(LIBINITENTRY == nil) {
+			LIBINITENTRY = mal(strlen(goarch)+strlen(goos)+20);
+			sprint(LIBINITENTRY, "_rt0_%s_%s_lib", goarch, goos);
+		}
+		lookup(LIBINITENTRY, 0)->type = SXREF;
+	}
 }
 
 void
@@ -281,6 +293,8 @@ loadlib(void)
 	loadinternal("runtime");
 	if(thechar == '5')
 		loadinternal("math");
+	if(flag_race)
+		loadinternal("runtime/race");
 
 	for(i=0; i<libraryp; i++) {
 		if(debug['v'])
@@ -298,10 +312,11 @@ loadlib(void)
 	//
 	// Exception: on OS X, programs such as Shark only work with dynamic
 	// binaries, so leave it enabled on OS X (Mach-O) binaries.
-	if(!havedynamic && HEADTYPE != Hdarwin)
+	if(!flag_shared && !havedynamic && HEADTYPE != Hdarwin)
 		debug['d'] = 1;
 	
 	importcycles();
+	sortdynexp();
 }
 
 /*
@@ -366,7 +381,7 @@ objfile(char *file, char *pkg)
 		return;
 	}
 	
-	/* skip over __.SYMDEF */
+	/* skip over __.GOSYMDEF */
 	off = Boffset(f);
 	if((l = nextar(f, off, &arhdr)) <= 0) {
 		diag("%s: short read on archive file symbol header", file);
@@ -402,7 +417,7 @@ objfile(char *file, char *pkg)
 	 * the individual symbols that are unused.
 	 *
 	 * loading every object will also make it possible to
-	 * load foreign objects not referenced by __.SYMDEF.
+	 * load foreign objects not referenced by __.GOSYMDEF.
 	 */
 	for(;;) {
 		l = nextar(f, off, &arhdr);
@@ -548,6 +563,36 @@ eof:
 	free(pn);
 }
 
+Sym*
+newsym(char *symb, int v)
+{
+	Sym *s;
+	int l;
+
+	l = strlen(symb) + 1;
+	s = mal(sizeof(*s));
+	if(debug['v'] > 1)
+		Bprint(&bso, "newsym %s\n", symb);
+
+	s->dynid = -1;
+	s->plt = -1;
+	s->got = -1;
+	s->name = mal(l + 1);
+	memmove(s->name, symb, l);
+
+	s->type = 0;
+	s->version = v;
+	s->value = 0;
+	s->sig = 0;
+	s->size = 0;
+	nsymbol++;
+
+	s->allsym = allsym;
+	allsym = s;
+
+	return s;
+}
+
 static Sym*
 _lookup(char *symb, int v, int creat)
 {
@@ -569,27 +614,10 @@ _lookup(char *symb, int v, int creat)
 	if(!creat)
 		return nil;
 
-	s = mal(sizeof(*s));
-	if(debug['v'] > 1)
-		Bprint(&bso, "lookup %s\n", symb);
-
-	s->dynid = -1;
-	s->plt = -1;
-	s->got = -1;
-	s->name = mal(l + 1);
-	memmove(s->name, symb, l);
-
+	s = newsym(symb, v);
 	s->hash = hash[h];
-	s->type = 0;
-	s->version = v;
-	s->value = 0;
-	s->sig = 0;
-	s->size = 0;
 	hash[h] = s;
-	nsymbol++;
 
-	s->allsym = allsym;
-	allsym = s;
 	return s;
 }
 
@@ -1372,6 +1400,19 @@ headtype(char *name)
 	return -1;  // not reached
 }
 
+char*
+headstr(int v)
+{
+	static char buf[20];
+	int i;
+
+	for(i=0; headers[i].name; i++)
+		if(v == headers[i].val)
+			return headers[i].name;
+	snprint(buf, sizeof buf, "%d", v);
+	return buf;
+}
+
 void
 undef(void)
 {
@@ -1419,6 +1460,23 @@ Yconv(Fmt *fp)
 
 vlong coutpos;
 
+static void
+dowrite(int fd, char *p, int n)
+{
+	int m;
+	
+	while(n > 0) {
+		m = write(fd, p, n);
+		if(m <= 0) {
+			cursym = S;
+			diag("write error: %r");
+			errorexit();
+		}
+		n -= m;
+		p += m;
+	}
+}
+
 void
 cflush(void)
 {
@@ -1427,13 +1485,8 @@ cflush(void)
 	if(cbpmax < cbp)
 		cbpmax = cbp;
 	n = cbpmax - buf.cbuf;
-	if(n) {
-		if(write(cout, buf.cbuf, n) != n) {
-			diag("write error: %r");
-			errorexit();
-		}
-		coutpos += n;
-	}
+	dowrite(cout, buf.cbuf, n);
+	coutpos += n;
 	cbp = buf.cbuf;
 	cbc = sizeof(buf.cbuf);
 	cbpmax = cbp;
@@ -1472,9 +1525,142 @@ void
 cwrite(void *buf, int n)
 {
 	cflush();
-	if(write(cout, buf, n) != n) {
-		diag("write error: %r");
-		errorexit();
-	}
+	if(n <= 0)
+		return;
+	dowrite(cout, buf, n);
 	coutpos += n;
 }
+
+void
+usage(void)
+{
+	fprint(2, "usage: %cl [options] main.%c\n", thechar, thechar);
+	flagprint(2);
+	exits("usage");
+}
+
+void
+setheadtype(char *s)
+{
+	HEADTYPE = headtype(s);
+}
+
+void
+setinterp(char *s)
+{
+	debug['I'] = 1; // denote cmdline interpreter override
+	interpreter = s;
+}
+
+void
+doversion(void)
+{
+	print("%cl version %s\n", thechar, getgoversion());
+	errorexit();
+}
+
+void
+genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
+{
+	Auto *a;
+	Sym *s;
+	int32 off;
+
+	// 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 = lookup("text", 0);
+	if(s->type == STEXT)
+		put(s, s->name, 'T', s->value, s->size, s->version, 0);
+	s = lookup("etext", 0);
+	if(s->type == STEXT)
+		put(s, s->name, 'T', s->value, s->size, s->version, 0);
+
+	for(s=allsym; s!=S; s=s->allsym) {
+		if(s->hide)
+			continue;
+		switch(s->type&SMASK) {
+		case SCONST:
+		case SRODATA:
+		case SSYMTAB:
+		case SPCLNTAB:
+		case SDATA:
+		case SNOPTRDATA:
+		case SELFROSECT:
+		case SMACHOGOT:
+		case STYPE:
+		case SSTRING:
+		case SGOSTRING:
+		case SWINDOWS:
+		case SGCDATA:
+		case SGCBSS:
+			if(!s->reachable)
+				continue;
+			put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
+			continue;
+
+		case SBSS:
+		case SNOPTRBSS:
+			if(!s->reachable)
+				continue;
+			if(s->np > 0)
+				diag("%s should not be bss (size=%d type=%d special=%d)", s->name, (int)s->np, s->type, s->special);
+			put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
+			continue;
+
+		case SFILE:
+			put(nil, s->name, 'f', s->value, 0, s->version, 0);
+			continue;
+		}
+	}
+
+	for(s = textp; s != nil; s = s->next) {
+		if(s->text == nil)
+			continue;
+
+		/* filenames first */
+		for(a=s->autom; a; a=a->link)
+			if(a->type == D_FILE)
+				put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0);
+			else
+			if(a->type == D_FILE1)
+				put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
+
+		put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
+
+		/* frame, locals, args, auto and param after */
+		put(nil, ".frame", 'm', (uint32)s->text->to.offset+PtrSize, 0, 0, 0);
+		put(nil, ".locals", 'm', s->locals, 0, 0, 0);
+		put(nil, ".args", 'm', s->args, 0, 0, 0);
+
+		for(a=s->autom; a; a=a->link) {
+			// Emit a or p according to actual offset, even if label is wrong.
+			// This avoids negative offsets, which cannot be encoded.
+			if(a->type != D_AUTO && a->type != D_PARAM)
+				continue;
+			
+			// compute offset relative to FP
+			if(a->type == D_PARAM)
+				off = a->aoffset;
+			else
+				off = a->aoffset - PtrSize;
+			
+			// FP
+			if(off >= 0) {
+				put(nil, a->asym->name, 'p', off, 0, 0, a->gotype);
+				continue;
+			}
+			
+			// SP
+			if(off <= -PtrSize) {
+				put(nil, a->asym->name, 'a', -(off+PtrSize), 0, 0, a->gotype);
+				continue;
+			}
+			
+			// Otherwise, off is addressing the saved program counter.
+			// Something underhanded is going on. Say nothing.
+		}
+	}
+	if(debug['v'] || debug['n'])
+		Bprint(&bso, "symsize = %ud\n", symsize);
+	Bflush(&bso);
+}
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 02dac6e..94ad76e 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -31,7 +31,7 @@
 enum
 {
 	Sxxx,
-	
+
 	/* order here is order in output file */
 	STEXT,
 	SMACHOPLT,
@@ -39,11 +39,15 @@ enum
 	SSTRING,
 	SGOSTRING,
 	SRODATA,
+	STYPELINK,
+	SGCDATA,
+	SGCBSS,
 	SSYMTAB,
 	SPCLNTAB,
 	SELFROSECT,
 	SELFSECT,
 	SNOPTRDATA,
+	SDATARELRO,
 	SDATA,
 	SMACHO,	/* Mach-O __nl_symbol_ptr */
 	SMACHOGOT,
@@ -59,9 +63,12 @@ enum
 	SFILE,
 	SCONST,
 	SDYNIMPORT,
+	SHOSTOBJ,
 
 	SSUB = 1<<8,	/* sub-symbol, linked from parent via ->sub list */
-	
+	SMASK = SSUB - 1,
+	SHIDDEN = 1<<9, // hidden or local symbol
+
 	NHASH = 100003,
 };
 
@@ -92,6 +99,8 @@ struct Segment
 	Section*	sect;
 };
 
+#pragma incomplete struct Elf64_Shdr
+
 struct Section
 {
 	uchar	rwx;
@@ -100,6 +109,9 @@ struct Section
 	uvlong	len;
 	Section	*next;	// in segment list
 	Segment	*seg;
+	struct Elf64_Shdr *elfsect;
+	uvlong	reloff;
+	uvlong	rellen;
 };
 
 extern	char	symname[];
@@ -128,6 +140,12 @@ EXTERN	char*	thestring;
 EXTERN	int	ndynexp;
 EXTERN	int	havedynamic;
 EXTERN	int	iscgo;
+EXTERN	int	isobj;
+EXTERN	int	elfglobalsymndx;
+EXTERN	int	flag_race;
+EXTERN	int flag_shared;
+EXTERN	char*	tracksym;
+EXTERN	char*	interpreter;
 
 EXTERN	Segment	segtext;
 EXTERN	Segment	segdata;
@@ -142,6 +160,7 @@ void	addhist(int32 line, int type);
 void	asmlc(void);
 void	histtoauto(void);
 void	collapsefrog(Sym *s);
+Sym*	newsym(char *symb, int v);
 Sym*	lookup(char *symb, int v);
 Sym*	rlookup(char *symb, int v);
 void	nuxiinit(void);
@@ -163,6 +182,8 @@ void	symtab(void);
 void	Lflag(char *arg);
 void	usage(void);
 void	adddynrel(Sym*, Reloc*);
+void	adddynrela(Sym*, Sym*, Reloc*);
+Sym*	lookuprel(void);
 void	ldobj1(Biobuf *f, char*, int64 len, char *pn);
 void	ldobj(Biobuf*, char*, int64, char*, int);
 void	ldelf(Biobuf*, char*, int64, char*);
@@ -176,21 +197,26 @@ void	deadcode(void);
 Reloc*	addrel(Sym*);
 void	codeblk(int32, int32);
 void	datblk(int32, int32);
-Sym*	datsort(Sym*);
 void	reloc(void);
 void	relocsym(Sym*);
 void	savedata(Sym*, Prog*, char*);
 void	symgrow(Sym*, int32);
 void	addstrdata(char*, char*);
 vlong	addstring(Sym*, char*);
+vlong	adduint8(Sym*, uint8);
+vlong	adduint16(Sym*, uint16);
 vlong	adduint32(Sym*, uint32);
 vlong	adduint64(Sym*, uint64);
 vlong	addaddr(Sym*, Sym*);
 vlong	addaddrplus(Sym*, Sym*, int32);
 vlong	addpcrelplus(Sym*, Sym*, int32);
 vlong	addsize(Sym*, Sym*);
-vlong	adduint8(Sym*, uint8);
-vlong	adduint16(Sym*, uint16);
+vlong	setaddrplus(Sym*, vlong, Sym*, int32);
+vlong	setaddr(Sym*, vlong, Sym*);
+void	setuint8(Sym*, vlong, uint8);
+void	setuint16(Sym*, vlong, uint16);
+void	setuint32(Sym*, vlong, uint32);
+void	setuint64(Sym*, vlong, uint64);
 void	asmsym(void);
 void	asmelfsym(void);
 void	asmplan9sym(void);
@@ -209,6 +235,11 @@ void	dostkcheck(void);
 void	undef(void);
 void	doweak(void);
 void	setpersrc(Sym*);
+void	doversion(void);
+void	usage(void);
+void	setinterp(char*);
+Sym*	listsort(Sym*, int(*cmp)(Sym*, Sym*), int);
+int	valuecmp(Sym*, Sym*);
 
 int	pathchar(void);
 void*	mal(uint32);
@@ -233,12 +264,6 @@ struct Endian
 
 extern Endian be, le;
 
-// relocation size bits
-enum {
-	Rbig = 128,
-	Rlittle = 64,
-};
-
 /* set by call to mywhatsys() */
 extern	char*	goroot;
 extern	char*	goarch;
@@ -282,6 +307,8 @@ EXTERN	char*	headstring;
 extern	Header	headers[];
 
 int	headtype(char*);
+char*	headstr(int);
+void	setheadtype(char*);
 
 int	Yconv(Fmt*);
 
@@ -312,3 +339,25 @@ void	cseek(vlong);
 void	cwrite(void*, int);
 void	importcycles(void);
 int	Zconv(Fmt*);
+
+uint8	decodetype_kind(Sym*);
+vlong	decodetype_size(Sym*);
+Sym*	decodetype_gc(Sym*);
+Sym*	decodetype_arrayelem(Sym*);
+vlong	decodetype_arraylen(Sym*);
+Sym*	decodetype_ptrelem(Sym*);
+Sym*	decodetype_mapkey(Sym*);
+Sym*	decodetype_mapvalue(Sym*);
+Sym*	decodetype_chanelem(Sym*);
+int	decodetype_funcdotdotdot(Sym*);
+int	decodetype_funcincount(Sym*);
+int	decodetype_funcoutcount(Sym*);
+Sym*	decodetype_funcintype(Sym*, int);
+Sym*	decodetype_funcouttype(Sym*, int);
+int	decodetype_structfieldcount(Sym*);
+char*	decodetype_structfieldname(Sym*, int);
+Sym*	decodetype_structfieldtype(Sym*, int);
+vlong	decodetype_structfieldoffs(Sym*, int);
+vlong	decodetype_ifacemethodcount(Sym*);
+
+void	sortdynexp(void);
diff --git a/src/cmd/ld/macho.h b/src/cmd/ld/macho.h
index f551041..baea6ff 100644
--- a/src/cmd/ld/macho.h
+++ b/src/cmd/ld/macho.h
@@ -50,7 +50,7 @@ struct MachoDebug {
 	uint32	filesize;
 };
 
-MachoHdr*	getMachoHdr();
+MachoHdr*	getMachoHdr(void);
 MachoSeg*	newMachoSeg(char*, int);
 MachoSect*	newMachoSect(MachoSeg*, char*);
 MachoLoad*	newMachoLoad(uint32, uint32);
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index 1d70b48..f2903ba 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -148,6 +148,9 @@ peinit(void)
 	PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN);
 	nextsectoff = PESECTHEADR;
 	nextfileoff = PEFILEHEADR;
+
+	// some mingw libs depend on this symbol, for example, FindPESectionByName
+	xdefine("__image_base__", SDATA, PEBASE);
 }
 
 static void
@@ -533,6 +536,7 @@ addexcept(IMAGE_SECTION_HEADER *text)
 	uvlong n;
 	Sym *sym;
 
+	USED(text);
 	if(thechar != '6')
 		return;
 
@@ -656,7 +660,7 @@ asmbpe(void)
 	// for other threads we specify stack size in runtime explicitly
 	// (runtime knows whether cgo is enabled or not).
 	// If you change stack reserve sizes here,
-	// change them in runtime/cgo/windows_386/amd64.c as well.
+	// change STACKSIZE in runtime/cgo/gcc_windows_{386,amd64}.c as well.
 	if(!iscgo) {
 		set(SizeOfStackReserve, 0x00010000);
 		set(SizeOfStackCommit, 0x0000ffff);
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index 129b13e..89a5948 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -36,7 +36,7 @@
 
 static int maxelfstr;
 
-int
+static int
 putelfstr(char *s)
 {
 	int off, n;
@@ -57,14 +57,14 @@ putelfstr(char *s)
 	return off;
 }
 
-void
-putelfsyment(int off, vlong addr, vlong size, int info, int shndx)
+static void
+putelfsyment(int off, vlong addr, vlong size, int info, int shndx, int other)
 {
 	switch(thechar) {
 	case '6':
 		LPUT(off);
 		cput(info);
-		cput(0);
+		cput(other);
 		WPUT(shndx);
 		VPUT(addr);
 		VPUT(size);
@@ -75,17 +75,21 @@ putelfsyment(int off, vlong addr, vlong size, int info, int shndx)
 		LPUT(addr);
 		LPUT(size);
 		cput(info);
-		cput(0);
+		cput(other);
 		WPUT(shndx);
 		symsize += ELF32SYMSIZE;
 		break;
 	}
 }
 
-void
+static int numelfsym = 1; // 0 is reserved
+static int elfbind;
+
+static void
 putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
 {
-	int bind, type, shndx, off;
+	int bind, type, off;
+	Sym *xo;
 
 	USED(go);
 	switch(t) {
@@ -93,37 +97,68 @@ putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
 		return;
 	case 'T':
 		type = STT_FUNC;
-		shndx = elftextsh + 0;
 		break;
 	case 'D':
 		type = STT_OBJECT;
-		if((x->type&~SSUB) == SRODATA)
-			shndx = elftextsh + 1;
-		else
-			shndx = elftextsh + 2;
 		break;
 	case 'B':
 		type = STT_OBJECT;
-		shndx = elftextsh + 3;
 		break;
 	}
-	bind = ver ? STB_LOCAL : STB_GLOBAL;
+	xo = x;
+	while(xo->outer != nil)
+		xo = xo->outer;
+	if(xo->sect == nil) {
+		cursym = x;
+		diag("missing section in putelfsym");
+		return;
+	}
+	if(xo->sect->elfsect == nil) {
+		cursym = x;
+		diag("missing ELF section in putelfsym");
+		return;
+	}
+
+	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
+	// maybe one day STB_WEAK.
+	bind = (ver || (x->type & SHIDDEN)) ? STB_LOCAL : STB_GLOBAL;
+	if(bind != elfbind)
+		return;
+
 	off = putelfstr(s);
-	putelfsyment(off, addr, size, (bind<<4)|(type&0xf), shndx);
+	if(isobj)
+		addr -= xo->sect->vaddr;
+	putelfsyment(off, addr, size, (bind<<4)|(type&0xf), xo->sect->elfsect->shnum, (x->type & SHIDDEN) ? 2 : 0);
+	x->elfsym = numelfsym++;
 }
 
 void
 asmelfsym(void)
 {
+	Sym *s;
+
 	// the first symbol entry is reserved
-	putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0);
+	putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0, 0);
+
+	elfbind = STB_LOCAL;
 	genasmsym(putelfsym);
+
+	elfbind = STB_GLOBAL;
+	elfglobalsymndx = numelfsym;
+	genasmsym(putelfsym);
+	
+	for(s=allsym; s!=S; s=s->allsym) {
+		if(s->type != SHOSTOBJ)
+			continue;
+		putelfsyment(putelfstr(s->name), 0, 0, (STB_GLOBAL<<4)|STT_NOTYPE, 0, 0);
+		s->elfsym = numelfsym++;
+	}
 }
 
-void
+static void
 putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
 {
-	int i;
+	int i, l;
 
 	USED(go);
 	USED(ver);
@@ -142,6 +177,11 @@ putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
 	case 'z':
 	case 'Z':
 	case 'm':
+		l = 4;
+		if(HEADTYPE == Hplan9x64 && !debug['8']) {
+			lputb(addr>>32);
+			l = 8;
+		}
 		lputb(addr);
 		cput(t+0x80); /* 0x80 is variable length */
 
@@ -162,7 +202,7 @@ putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
 				cput(s[i]);
 			cput(0);
 		}
-		symsize += 4 + 1 + i + 1;
+		symsize += l + 1 + i + 1;
 		break;
 	default:
 		return;
@@ -192,7 +232,7 @@ static void
 slputb(int32 v)
 {
 	uchar *p;
-	
+
 	symgrow(symt, symt->size+4);
 	p = symt->p + symt->size;
 	*p++ = v>>24;
@@ -202,6 +242,22 @@ slputb(int32 v)
 	symt->size += 4;
 }
 
+static void
+slputl(int32 v)
+{
+	uchar *p;
+
+	symgrow(symt, symt->size+4);
+	p = symt->p + symt->size;
+	*p++ = v;
+	*p++ = v>>8;
+	*p++ = v>>16;
+	*p = v>>24;
+	symt->size += 4;
+}
+
+static void (*slput)(int32);
+
 void
 wputl(ushort w)
 {
@@ -248,32 +304,76 @@ vputl(uint64 v)
 	lputl(v >> 32);
 }
 
+// Emit symbol table entry.
+// The table format is described at the top of ../../pkg/runtime/symtab.c.
 void
 putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
 {
-	int i, f, l;
+	int i, f, c;
+	vlong v1;
 	Reloc *rel;
 
 	USED(size);
-	if(t == 'f')
-		name++;
-	l = 4;
-//	if(!debug['8'])
-//		l = 8;
+	
+	// type byte
+	if('A' <= t && t <= 'Z')
+		c = t - 'A';
+	else if('a' <= t && t <= 'z')
+		c = t - 'a' + 26;
+	else {
+		diag("invalid symbol table type %c", t);
+		errorexit();
+		return;
+	}
+	
+	if(s != nil)
+		c |= 0x40; // wide value
+	if(typ != nil)
+		c |= 0x80; // has go type
+	scput(c);
+
+	// value
 	if(s != nil) {
+		// full width
 		rel = addrel(symt);
-		rel->siz = l + Rbig;
+		rel->siz = PtrSize;
 		rel->sym = s;
 		rel->type = D_ADDR;
 		rel->off = symt->size;
-		v = 0;
-	}	
-	if(l == 8)
-		slputb(v>>32);
-	slputb(v);
-	if(ver)
-		t += 'a' - 'A';
-	scput(t+0x80);			/* 0x80 is variable length */
+		if(PtrSize == 8)
+			slput(0);
+		slput(0);
+	} else {
+		// varint
+		if(v < 0) {
+			diag("negative value in symbol table: %s %lld", name, v);
+			errorexit();
+		}
+		v1 = v;
+		while(v1 >= 0x80) {
+			scput(v1 | 0x80);
+			v1 >>= 7;
+		}
+		scput(v1);
+	}
+
+	// go type if present
+	if(typ != nil) {
+		if(!typ->reachable)
+			diag("unreachable type %s", typ->name);
+		rel = addrel(symt);
+		rel->siz = PtrSize;
+		rel->sym = typ;
+		rel->type = D_ADDR;
+		rel->off = symt->size;
+		if(PtrSize == 8)
+			slput(0);
+		slput(0);
+	}
+	
+	// name	
+	if(t == 'f')
+		name++;
 
 	if(t == 'Z' || t == 'z') {
 		scput(name[0]);
@@ -283,24 +383,11 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
 		}
 		scput(0);
 		scput(0);
-	}
-	else {
+	} else {
 		for(i=0; name[i]; i++)
 			scput(name[i]);
 		scput(0);
 	}
-	if(typ) {
-		if(!typ->reachable)
-			diag("unreachable type %s", typ->name);
-		rel = addrel(symt);
-		rel->siz = l;
-		rel->sym = typ;
-		rel->type = D_ADDR;
-		rel->off = symt->size;
-	}
-	if(l == 8)
-		slputb(0);
-	slputb(0);
 
 	if(debug['n']) {
 		if(t == 'z' || t == 'Z') {
@@ -313,25 +400,34 @@ putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
 			return;
 		}
 		if(ver)
-			Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, s->name, ver, typ ? typ->name : "");
+			Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, name, ver, typ ? typ->name : "");
 		else
-			Bprint(&bso, "%c %.8llux %s %s\n", t, v, s->name, typ ? typ->name : "");
+			Bprint(&bso, "%c %.8llux %s %s\n", t, v, name, typ ? typ->name : "");
 	}
 }
 
 void
 symtab(void)
 {
-	Sym *s;
-
+	Sym *s, *symtype, *symtypelink, *symgostring;
 	dosymtype();
 
 	// 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);
+	if(flag_shared) {
+		xdefine("datarelro", SDATARELRO, 0);
+		xdefine("edatarelro", SDATARELRO, 0);
+	}
+	xdefine("gcdata", SGCDATA, 0);
+	xdefine("egcdata", SGCDATA, 0);
+	xdefine("gcbss", SGCBSS, 0);
+	xdefine("egcbss", SGCBSS, 0);
 	xdefine("noptrdata", SNOPTRDATA, 0);
 	xdefine("enoptrdata", SNOPTRDATA, 0);
 	xdefine("data", SDATA, 0);
@@ -343,23 +439,27 @@ symtab(void)
 	xdefine("end", SBSS, 0);
 	xdefine("epclntab", SRODATA, 0);
 	xdefine("esymtab", SRODATA, 0);
-	
+
 	// pseudo-symbols to mark locations of type, string, and go string data.
 	s = lookup("type.*", 0);
 	s->type = STYPE;
 	s->size = 0;
 	s->reachable = 1;
+	symtype = s;
 
 	s = lookup("go.string.*", 0);
 	s->type = SGOSTRING;
 	s->size = 0;
 	s->reachable = 1;
+	symgostring = s;
+	
+	symtypelink = lookup("typelink", 0);
 
 	symt = lookup("symtab", 0);
 	symt->type = SSYMTAB;
 	symt->size = 0;
 	symt->reachable = 1;
-	
+
 	// assign specific types so that they sort together.
 	// within a type they sort by size, so the .* symbols
 	// just defined above will be first.
@@ -370,14 +470,44 @@ symtab(void)
 		if(strncmp(s->name, "type.", 5) == 0) {
 			s->type = STYPE;
 			s->hide = 1;
+			s->outer = symtype;
+		}
+		if(strncmp(s->name, "go.typelink.", 12) == 0) {
+			s->type = STYPELINK;
+			s->hide = 1;
+			s->outer = symtypelink;
 		}
 		if(strncmp(s->name, "go.string.", 10) == 0) {
 			s->type = SGOSTRING;
 			s->hide = 1;
+			s->outer = symgostring;
 		}
 	}
 
 	if(debug['s'])
 		return;
+
+	switch(thechar) {
+	default:
+		diag("unknown architecture %c", thechar);
+		errorexit();
+	case '5':
+	case '6':
+	case '8':
+		// little-endian symbol table
+		slput = slputl;
+		break;
+	case 'v':
+		// big-endian symbol table
+		slput = slputb;
+		break;
+	}
+	// new symbol table header.
+	slput(0xfffffffd);
+	scput(0);
+	scput(0);
+	scput(0);
+	scput(PtrSize);
+
 	genasmsym(putsymb);
 }
diff --git a/src/cmd/nm/doc.go b/src/cmd/nm/doc.go
index c84369a..480c1c3 100644
--- a/src/cmd/nm/doc.go
+++ b/src/cmd/nm/doc.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 ignore
+
 /*
 
 Nm is a version of the Plan 9 nm command.  The original is documented at
@@ -11,11 +13,11 @@ Nm is a version of the Plan 9 nm command.  The original is documented at
 It prints the name list (symbol table) for programs compiled by gc as well as the
 Plan 9 C compiler.
 
-This implementation adds the flag -S, which prints each symbol's size 
+This implementation adds the flag -S, which prints each symbol's size
 in decimal after its address.
 
 Usage:
 	go tool nm [-aghnsTu] file
 
 */
-package documentation
+package main
diff --git a/src/cmd/nm/nm.c b/src/cmd/nm/nm.c
index 845b6c7..6682390 100644
--- a/src/cmd/nm/nm.c
+++ b/src/cmd/nm/nm.c
@@ -43,7 +43,7 @@ enum{
 
 char	*errs;			/* exit status */
 char	*filename;		/* current file */
-char	symname[]="__.SYMDEF";	/* table of contents file name */
+char	symname[]="__.GOSYMDEF";	/* table of contents file name */
 int	multifile;		/* processing multiple files */
 int	aflag;
 int	gflag;
diff --git a/src/cmd/pack/ar.c b/src/cmd/pack/ar.c
index 7e07fbc..7053f84 100644
--- a/src/cmd/pack/ar.c
+++ b/src/cmd/pack/ar.c
@@ -77,9 +77,7 @@ typedef struct	Armember	/* Temp file entry - one per archive member */
 
 typedef	struct Arfile		/* Temp file control block - one per tempfile */
 {
-	int	paged;		/* set when some data paged to disk */
 	char	*fname;		/* paging file name */
-	int	fd;		/* paging file descriptor */
 	vlong	size;
 	Armember *head;		/* head of member chain */
 	Armember *tail;		/* tail of member chain */
@@ -113,7 +111,7 @@ char	*opt =		"uvnbailogS";
 char	artemp[] =	"/tmp/vXXXXX";
 char	movtemp[] =	"/tmp/v1XXXXX";
 char	tailtemp[] =	"/tmp/v2XXXXX";
-char	symdef[] =	"__.SYMDEF";
+char	symdef[] =	"__.GOSYMDEF";
 char	pkgdef[] =	"__.PKGDEF";
 
 int	aflag;				/* command line flags */
@@ -159,7 +157,6 @@ int	bamatch(char*, char*);
 int	duplicate(char*, char**);
 Armember *getdir(Biobuf*);
 void	getpkgdef(char**, int*);
-int	getspace(void);
 void	install(char*, Arfile*, Arfile*, Arfile*, int);
 void	loadpkgdata(char*, int);
 void	longt(Armember*);
@@ -169,7 +166,6 @@ Arfile	*newtempfile(char*);
 Armember *newmember(void);
 void	objsym(Sym*, void*);
 int	openar(char*, int, int);
-int	page(Arfile*);
 void	pmode(long);
 void	rl(int);
 void	scanobj(Biobuf*, Arfile*, long);
@@ -1534,24 +1530,8 @@ void
 arstream(int fd, Arfile *ap)
 {
 	Armember *bp;
-	int i;
-	char buf[8192];
-
-	if (ap->paged) {		/* copy from disk */
-		seek(ap->fd, 0, 0);
-		for (;;) {
-			i = read(ap->fd, buf, sizeof(buf));
-			if (i < 0)
-				rderr();
-			if (i == 0)
-				break;
-			if (write(fd, buf, i) != i)
-				wrerr();
-		}
-		close(ap->fd);
-		ap->paged = 0;
-	}
-		/* dump the in-core buffers */
+
+	/* dump the in-core buffers */
 	for (bp = ap->head; bp; bp = bp->next) {
 		if (!arwrite(fd, bp))
 			wrerr();
@@ -1576,35 +1556,6 @@ arwrite(int fd, Armember *bp)
 	return 1;
 }
 
-/*
- *	Spill a member to a disk copy of a temp file
- */
-int
-page(Arfile *ap)
-{
-	USED(ap);
-
-	sysfatal("page");
-	return 1;
-}
-
-/*
- *	try to reclaim space by paging.  we try to spill the start, middle,
- *	and end files, in that order.  there is no particular reason for the
- *	ordering.
- */
-int
-getspace(void)
-{
-	if (astart && astart->head && page(astart))
-		return 1;
-	if (amiddle && amiddle->head && page(amiddle))
-		return 1;
-	if (aend && aend->head && page(aend))
-		return 1;
-	return 0;
-}
-
 void
 arfree(Arfile *ap)		/* free a member buffer */
 {
@@ -1633,13 +1584,11 @@ armalloc(int n)
 	if(n&1)
 		n++;
 
-	do {
-		cp = malloc(n);
-		if (cp) {
-			memset(cp, 0, n);
-			return cp;
-		}
-	} while (getspace());
+	cp = malloc(n);
+	if (cp) {
+		memset(cp, 0, n);
+		return cp;
+	}
 	fprint(2, "pack: out of memory\n");
 	exits("malloc");
 	return 0;
diff --git a/src/cmd/pack/doc.go b/src/cmd/pack/doc.go
index 8b17f3c..67b7897 100644
--- a/src/cmd/pack/doc.go
+++ b/src/cmd/pack/doc.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 ignore
+
 /*
 
 Pack is a variant of the Plan 9 ar tool.  The original is documented at
@@ -24,4 +26,4 @@ The new option 'P' causes pack to remove the given prefix
 from file names in the line number information in object files
 that are already stored in or added to the archive.
 */
-package documentation
+package main
diff --git a/src/cmd/5c/Makefile b/src/cmd/prof/Makefile
similarity index 100%
copy from src/cmd/5c/Makefile
copy to src/cmd/prof/Makefile
diff --git a/src/cmd/prof/doc.go b/src/cmd/prof/doc.go
new file mode 100644
index 0000000..2640167
--- /dev/null
+++ b/src/cmd/prof/doc.go
@@ -0,0 +1,49 @@
+// 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
+
+/*
+
+Prof is a rudimentary real-time profiler.
+
+Given a command to run or the process id (pid) of a command already
+running, it samples the program's state at regular intervals and reports
+on its behavior.  With no options, it prints a histogram of the locations
+in the code that were sampled during execution.
+
+Since it is a real-time profiler, unlike a traditional profiler it samples
+the program's state even when it is not running, such as when it is
+asleep or waiting for I/O.  Each thread contributes equally to the
+statistics.
+
+Usage:
+	go tool prof -p pid [-t total_secs] [-d delta_msec] [6.out args ...]
+
+The output modes (default -h) are:
+
+	-P file.prof:
+		Write the profile information to file.prof, in the format used by pprof.
+		At the moment, this only works on Linux amd64 binaries and requires that the
+		binary be written using 6l -e to produce ELF debug info.
+		See http://code.google.com/p/google-perftools for details.
+	-h: histograms
+		How many times a sample occurred at each location.
+	-f: dynamic functions
+		At each sample period, print the name of the executing function.
+	-l: dynamic file and line numbers
+		At each sample period, print the file and line number of the executing instruction.
+	-r: dynamic registers
+		At each sample period, print the register contents.
+	-s: dynamic function stack traces
+		At each sample period, print the symbolic stack trace.
+
+Flag -t sets the maximum real time to sample, in seconds, and -d
+sets the sampling interval in milliseconds.  The default is to sample
+every 100ms until the program completes.
+
+It is installed as go tool prof and is architecture-independent.
+
+*/
+package main
diff --git a/src/cmd/prof/main.c b/src/cmd/prof/main.c
new file mode 100644
index 0000000..6c591ba
--- /dev/null
+++ b/src/cmd/prof/main.c
@@ -0,0 +1,910 @@
+// 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 !plan9
+
+#include <u.h>
+#include <time.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+
+#define Ureg Ureg_amd64
+	#include <ureg_amd64.h>
+#undef Ureg
+#define Ureg Ureg_x86
+	#include <ureg_x86.h>
+#undef Ureg
+#include <mach.h>
+
+char* file = "6.out";
+static Fhdr fhdr;
+int have_syms;
+int fd;
+struct Ureg_amd64 ureg_amd64;
+struct Ureg_x86 ureg_x86;
+int total_sec = 0;
+int delta_msec = 100;
+int nsample;
+int nsamplethread;
+
+// pprof data, stored as sequences of N followed by N PC values.
+// See http://code.google.com/p/google-perftools .
+uvlong	*ppdata;	// traces
+Biobuf*	pproffd;	// file descriptor to write trace info
+long	ppstart;	// start position of current trace
+long	nppdata;	// length of data
+long	ppalloc;	// size of allocated data
+char	ppmapdata[10*1024];	// the map information for the output file
+
+// output formats
+int pprof;	// print pprof output to named file
+int functions;	// print functions
+int histograms;	// print histograms
+int linenums;	// print file and line numbers rather than function names
+int registers;	// print registers
+int stacks;		// print stack traces
+
+int pid;		// main process pid
+
+int nthread;	// number of threads
+int thread[32];	// thread pids
+Map *map[32];	// thread maps
+
+void
+Usage(void)
+{
+	fprint(2, "Usage: prof -p pid [-t total_secs] [-d delta_msec]\n");
+	fprint(2, "       prof [-t total_secs] [-d delta_msec] 6.out args ...\n");
+	fprint(2, "\tformats (default -h):\n");
+	fprint(2, "\t\t-P file.prof: write [c]pprof output to file.prof\n");
+	fprint(2, "\t\t-h: histograms\n");
+	fprint(2, "\t\t-f: dynamic functions\n");
+	fprint(2, "\t\t-l: dynamic file and line numbers\n");
+	fprint(2, "\t\t-r: dynamic registers\n");
+	fprint(2, "\t\t-s: dynamic function stack traces\n");
+	fprint(2, "\t\t-hs: include stack info in histograms\n");
+	exit(2);
+}
+
+typedef struct PC PC;
+struct PC {
+	uvlong pc;
+	uvlong callerpc;
+	unsigned int count;
+	PC* next;
+};
+
+enum {
+	Ncounters = 256
+};
+
+PC *counters[Ncounters];
+
+// Set up by setarch() to make most of the code architecture-independent.
+typedef struct Arch Arch;
+struct Arch {
+	char*	name;
+	void	(*regprint)(void);
+	int	(*getregs)(Map*);
+	int	(*getPC)(Map*);
+	int	(*getSP)(Map*);
+	uvlong	(*uregPC)(void);
+	uvlong	(*uregSP)(void);
+	void	(*ppword)(uvlong w);
+};
+
+void
+amd64_regprint(void)
+{
+	fprint(2, "ax\t0x%llux\n", ureg_amd64.ax);
+	fprint(2, "bx\t0x%llux\n", ureg_amd64.bx);
+	fprint(2, "cx\t0x%llux\n", ureg_amd64.cx);
+	fprint(2, "dx\t0x%llux\n", ureg_amd64.dx);
+	fprint(2, "si\t0x%llux\n", ureg_amd64.si);
+	fprint(2, "di\t0x%llux\n", ureg_amd64.di);
+	fprint(2, "bp\t0x%llux\n", ureg_amd64.bp);
+	fprint(2, "r8\t0x%llux\n", ureg_amd64.r8);
+	fprint(2, "r9\t0x%llux\n", ureg_amd64.r9);
+	fprint(2, "r10\t0x%llux\n", ureg_amd64.r10);
+	fprint(2, "r11\t0x%llux\n", ureg_amd64.r11);
+	fprint(2, "r12\t0x%llux\n", ureg_amd64.r12);
+	fprint(2, "r13\t0x%llux\n", ureg_amd64.r13);
+	fprint(2, "r14\t0x%llux\n", ureg_amd64.r14);
+	fprint(2, "r15\t0x%llux\n", ureg_amd64.r15);
+	fprint(2, "ds\t0x%llux\n", ureg_amd64.ds);
+	fprint(2, "es\t0x%llux\n", ureg_amd64.es);
+	fprint(2, "fs\t0x%llux\n", ureg_amd64.fs);
+	fprint(2, "gs\t0x%llux\n", ureg_amd64.gs);
+	fprint(2, "type\t0x%llux\n", ureg_amd64.type);
+	fprint(2, "error\t0x%llux\n", ureg_amd64.error);
+	fprint(2, "pc\t0x%llux\n", ureg_amd64.ip);
+	fprint(2, "cs\t0x%llux\n", ureg_amd64.cs);
+	fprint(2, "flags\t0x%llux\n", ureg_amd64.flags);
+	fprint(2, "sp\t0x%llux\n", ureg_amd64.sp);
+	fprint(2, "ss\t0x%llux\n", ureg_amd64.ss);
+}
+
+int
+amd64_getregs(Map *map)
+{
+	int i;
+	union {
+		uvlong regs[1];
+		struct Ureg_amd64 ureg;
+	} u;
+
+	for(i = 0; i < sizeof ureg_amd64; i+=8) {
+		if(get8(map, (uvlong)i, &u.regs[i/8]) < 0)
+			return -1;
+	}
+	ureg_amd64 = u.ureg;
+	return 0;
+}
+
+int
+amd64_getPC(Map *map)
+{
+	uvlong x;
+	int r;
+
+	r = get8(map, offsetof(struct Ureg_amd64, ip), &x);
+	ureg_amd64.ip = x;
+	return r;
+}
+
+int
+amd64_getSP(Map *map)
+{
+	uvlong x;
+	int r;
+
+	r = get8(map, offsetof(struct Ureg_amd64, sp), &x);
+	ureg_amd64.sp = x;
+	return r;
+}
+
+uvlong
+amd64_uregPC(void)
+{
+	return ureg_amd64.ip;
+}
+
+uvlong
+amd64_uregSP(void)
+{
+	return ureg_amd64.sp;
+}
+
+void
+amd64_ppword(uvlong w)
+{
+	uchar buf[8];
+
+	buf[0] = w;
+	buf[1] = w >> 8;
+	buf[2] = w >> 16;
+	buf[3] = w >> 24;
+	buf[4] = w >> 32;
+	buf[5] = w >> 40;
+	buf[6] = w >> 48;
+	buf[7] = w >> 56;
+	Bwrite(pproffd, buf, 8);
+}
+
+void
+x86_regprint(void)
+{
+	fprint(2, "ax\t0x%ux\n", ureg_x86.ax);
+	fprint(2, "bx\t0x%ux\n", ureg_x86.bx);
+	fprint(2, "cx\t0x%ux\n", ureg_x86.cx);
+	fprint(2, "dx\t0x%ux\n", ureg_x86.dx);
+	fprint(2, "si\t0x%ux\n", ureg_x86.si);
+	fprint(2, "di\t0x%ux\n", ureg_x86.di);
+	fprint(2, "bp\t0x%ux\n", ureg_x86.bp);
+	fprint(2, "ds\t0x%ux\n", ureg_x86.ds);
+	fprint(2, "es\t0x%ux\n", ureg_x86.es);
+	fprint(2, "fs\t0x%ux\n", ureg_x86.fs);
+	fprint(2, "gs\t0x%ux\n", ureg_x86.gs);
+	fprint(2, "cs\t0x%ux\n", ureg_x86.cs);
+	fprint(2, "flags\t0x%ux\n", ureg_x86.flags);
+	fprint(2, "pc\t0x%ux\n", ureg_x86.pc);
+	fprint(2, "sp\t0x%ux\n", ureg_x86.sp);
+	fprint(2, "ss\t0x%ux\n", ureg_x86.ss);
+}
+
+int
+x86_getregs(Map *map)
+{
+	int i;
+
+	for(i = 0; i < sizeof ureg_x86; i+=4) {
+		if(get4(map, (uvlong)i, &((uint32*)&ureg_x86)[i/4]) < 0)
+			return -1;
+	}
+	return 0;
+}
+
+int
+x86_getPC(Map* map)
+{
+	return get4(map, offsetof(struct Ureg_x86, pc), &ureg_x86.pc);
+}
+
+int
+x86_getSP(Map* map)
+{
+	return get4(map, offsetof(struct Ureg_x86, sp), &ureg_x86.sp);
+}
+
+uvlong
+x86_uregPC(void)
+{
+	return (uvlong)ureg_x86.pc;
+}
+
+uvlong
+x86_uregSP(void)
+{
+	return (uvlong)ureg_x86.sp;
+}
+
+void
+x86_ppword(uvlong w)
+{
+	uchar buf[4];
+
+	buf[0] = w;
+	buf[1] = w >> 8;
+	buf[2] = w >> 16;
+	buf[3] = w >> 24;
+	Bwrite(pproffd, buf, 4);
+}
+
+Arch archtab[] = {
+	{
+		"amd64",
+		amd64_regprint,
+		amd64_getregs,
+		amd64_getPC,
+		amd64_getSP,
+		amd64_uregPC,
+		amd64_uregSP,
+		amd64_ppword,
+	},
+	{
+		"386",
+		x86_regprint,
+		x86_getregs,
+		x86_getPC,
+		x86_getSP,
+		x86_uregPC,
+		x86_uregSP,
+		x86_ppword,
+	},
+	{
+		nil
+	}
+};
+
+Arch *arch;
+
+int
+setarch(void)
+{
+	int i;
+
+	if(mach != nil) {
+		for(i = 0; archtab[i].name != nil; i++) {
+			if (strcmp(mach->name, archtab[i].name) == 0) {
+				arch = &archtab[i];
+				return 0;
+			}
+		}
+	}
+	return -1;
+}
+
+int
+getthreads(void)
+{
+	int i, j, curn, found;
+	Map *curmap[nelem(map)];
+	int curthread[nelem(map)];
+	static int complained = 0;
+
+	curn = procthreadpids(pid, curthread, nelem(curthread));
+	if(curn <= 0)
+		return curn;
+
+	if(curn > nelem(map)) {
+		if(complained == 0) {
+			fprint(2, "prof: too many threads; limiting to %d\n", nthread, nelem(map));
+			complained = 1;
+		}
+		curn = nelem(map);
+	}
+	if(curn == nthread && memcmp(thread, curthread, curn*sizeof(*thread)) == 0)
+		return curn;	// no changes
+
+	// Number of threads has changed (might be the init case).
+	// A bit expensive but rare enough not to bother being clever.
+	for(i = 0; i < curn; i++) {
+		found = 0;
+		for(j = 0; j < nthread; j++) {
+			if(curthread[i] == thread[j]) {
+				found = 1;
+				curmap[i] = map[j];
+				map[j] = nil;
+				break;
+			}
+		}
+		if(found)
+			continue;
+
+		// map new thread
+		curmap[i] = attachproc(curthread[i], &fhdr);
+		if(curmap[i] == nil) {
+			fprint(2, "prof: can't attach to %d: %r\n", curthread[i]);
+			return -1;
+		}
+	}
+
+	for(j = 0; j < nthread; j++)
+		if(map[j] != nil)
+			detachproc(map[j]);
+
+	nthread = curn;
+	memmove(thread, curthread, nthread*sizeof thread[0]);
+	memmove(map, curmap, sizeof map);
+	return nthread;
+}
+
+int
+sample(Map *map)
+{
+	static int n;
+
+	n++;
+	if(registers) {
+		if(arch->getregs(map) < 0)
+			goto bad;
+	} else {
+		// we need only two registers
+		if(arch->getPC(map) < 0)
+			goto bad;
+		if(arch->getSP(map) < 0)
+			goto bad;
+	}
+	return 1;
+bad:
+	if(n == 1)
+		fprint(2, "prof: can't read registers: %r\n");
+	return 0;
+}
+
+void
+addtohistogram(uvlong pc, uvlong callerpc, uvlong sp)
+{
+	int h;
+	PC *x;
+	
+	USED(sp);
+
+	h = (pc + callerpc*101) % Ncounters;
+	for(x = counters[h]; x != NULL; x = x->next) {
+		if(x->pc == pc && x->callerpc == callerpc) {
+			x->count++;
+			return;
+		}
+	}
+	x = malloc(sizeof(PC));
+	if(x == nil)
+		sysfatal("out of memory");
+	x->pc = pc;
+	x->callerpc = callerpc;
+	x->count = 1;
+	x->next = counters[h];
+	counters[h] = x;
+}
+
+void
+addppword(uvlong pc)
+{
+	if(pc == 0) {
+		return;
+	}
+	if(nppdata == ppalloc) {
+		ppalloc = (1000+nppdata)*2;
+		ppdata = realloc(ppdata, ppalloc * sizeof ppdata[0]);
+		if(ppdata == nil) {
+			fprint(2, "prof: realloc failed: %r\n");
+			exit(2);
+		}
+	}
+	ppdata[nppdata++] = pc;
+}
+
+void
+startpptrace(void)
+{
+	ppstart = nppdata;
+	addppword(~0);
+}
+
+void
+endpptrace(void)
+{
+	ppdata[ppstart] = nppdata-ppstart-1;
+}
+
+uvlong nextpc;
+
+void
+xptrace(Map *map, uvlong pc, uvlong sp, Symbol *sym)
+{
+	USED(map);
+
+	char buf[1024];
+	if(sym == nil){
+		fprint(2, "syms\n");
+		return;
+	}
+	if(histograms)
+		addtohistogram(nextpc, pc, sp);
+	if(!histograms || stacks > 1 || pprof) {
+		if(nextpc == 0)
+			nextpc = sym->value;
+		if(stacks){
+			fprint(2, "%s(", sym->name);
+			fprint(2, ")");
+			if(nextpc != sym->value)
+				fprint(2, "+%#llux ", nextpc - sym->value);
+			if(have_syms && linenums && fileline(buf, sizeof buf, pc)) {
+				fprint(2, " %s", buf);
+			}
+			fprint(2, "\n");
+		}
+		if (pprof) {
+			addppword(nextpc);
+		}
+	}
+	nextpc = pc;
+}
+
+void
+stacktracepcsp(Map *map, uvlong pc, uvlong sp)
+{
+	nextpc = pc;
+	if(pprof){
+		startpptrace();
+	}
+	if(machdata->ctrace==nil)
+		fprint(2, "no machdata->ctrace\n");
+	else if(machdata->ctrace(map, pc, sp, 0, xptrace) <= 0)
+		fprint(2, "no stack frame: pc=%#p sp=%#p\n", pc, sp);
+	else {
+		addtohistogram(nextpc, 0, sp);
+		if(stacks)
+			fprint(2, "\n");
+	}
+	if(pprof){
+		endpptrace();
+	}
+}
+
+void
+printpc(Map *map, uvlong pc, uvlong sp)
+{
+	char buf[1024];
+	if(registers)
+		arch->regprint();
+	if(have_syms > 0 && linenums &&  fileline(buf, sizeof buf, pc))
+		fprint(2, "%s\n", buf);
+	if(have_syms > 0 && functions) {
+		symoff(buf, sizeof(buf), pc, CANY);
+		fprint(2, "%s\n", buf);
+	}
+	if(stacks || pprof){
+		stacktracepcsp(map, pc, sp);
+	}
+	else if(histograms){
+		addtohistogram(pc, 0, sp);
+	}
+}
+
+void
+ppmaps(void)
+{
+	int fd, n;
+	char tmp[100];
+	Seg *seg;
+
+	// If it's Linux, the info is in /proc/$pid/maps
+	snprint(tmp, sizeof tmp, "/proc/%d/maps", pid);
+	fd = open(tmp, 0);
+	if(fd >= 0) {
+		n = read(fd, ppmapdata, sizeof ppmapdata - 1);
+		close(fd);
+		if(n < 0) {
+			fprint(2, "prof: can't read %s: %r\n", tmp);
+			exit(2);
+		}
+		ppmapdata[n] = 0;
+		return;
+	}
+
+	// It's probably a mac. Synthesize an entry for the text file.
+	// The register segment may come first but it has a zero offset, so grab the first non-zero offset segment.
+	for(n = 0; n < 3; n++){
+		seg = &map[0]->seg[n];
+		if(seg->b == 0) {
+			continue;
+		}
+		snprint(ppmapdata, sizeof ppmapdata,
+			"%.16x-%.16x r-xp %d 00:00 34968549                           %s\n",
+			seg->b, seg->e, seg->f, "/home/r/6.out"
+		);
+		return;
+	}
+	fprint(2, "prof: no text segment in maps for %s\n", file);
+	exit(2);
+}
+
+void
+samples(void)
+{
+	int i, pid, msec;
+	struct timespec req;
+	int getmaps;
+
+	req.tv_sec = delta_msec/1000;
+	req.tv_nsec = 1000000*(delta_msec % 1000);
+	getmaps = 0;
+	if(pprof)
+		getmaps= 1;
+	for(msec = 0; total_sec <= 0 || msec < 1000*total_sec; msec += delta_msec) {
+		nsample++;
+		nsamplethread += nthread;
+		for(i = 0; i < nthread; i++) {
+			pid = thread[i];
+			if(ctlproc(pid, "stop") < 0)
+				return;
+			if(!sample(map[i])) {
+				ctlproc(pid, "start");
+				return;
+			}
+			printpc(map[i], arch->uregPC(), arch->uregSP());
+			ctlproc(pid, "start");
+		}
+		nanosleep(&req, NULL);
+		getthreads();
+		if(nthread == 0)
+			break;
+		if(getmaps) {
+			getmaps = 0;
+			ppmaps();
+		}
+	}
+}
+
+typedef struct Func Func;
+struct Func
+{
+	Func *next;
+	Symbol s;
+	uint onstack;
+	uint leaf;
+};
+
+Func *func[257];
+int nfunc;
+
+Func*
+findfunc(uvlong pc)
+{
+	Func *f;
+	uint h;
+	Symbol s;
+
+	if(pc == 0)
+		return nil;
+
+	if(!findsym(pc, CTEXT, &s))
+		return nil;
+
+	h = s.value % nelem(func);
+	for(f = func[h]; f != NULL; f = f->next)
+		if(f->s.value == s.value)
+			return f;
+
+	f = malloc(sizeof *f);
+	if(f == nil)
+		sysfatal("out of memory");
+	memset(f, 0, sizeof *f);
+	f->s = s;
+	f->next = func[h];
+	func[h] = f;
+	nfunc++;
+	return f;
+}
+
+int
+compareleaf(const void *va, const void *vb)
+{
+	Func *a, *b;
+
+	a = *(Func**)va;
+	b = *(Func**)vb;
+	if(a->leaf != b->leaf)
+		return b->leaf - a->leaf;
+	if(a->onstack != b->onstack)
+		return b->onstack - a->onstack;
+	return strcmp(a->s.name, b->s.name);
+}
+
+void
+dumphistogram(void)
+{
+	int i, h, n;
+	PC *x;
+	Func *f, **ff;
+
+	if(!histograms)
+		return;
+
+	// assign counts to functions.
+	for(h = 0; h < Ncounters; h++) {
+		for(x = counters[h]; x != NULL; x = x->next) {
+			f = findfunc(x->pc);
+			if(f) {
+				f->onstack += x->count;
+				f->leaf += x->count;
+			}
+			f = findfunc(x->callerpc);
+			if(f)
+				f->leaf -= x->count;
+		}
+	}
+
+	// build array
+	ff = malloc(nfunc*sizeof ff[0]);
+	if(ff == nil)
+		sysfatal("out of memory");
+	n = 0;
+	for(h = 0; h < nelem(func); h++)
+		for(f = func[h]; f != NULL; f = f->next)
+			ff[n++] = f;
+
+	// sort by leaf counts
+	qsort(ff, nfunc, sizeof ff[0], compareleaf);
+
+	// print.
+	fprint(2, "%d samples (avg %.1g threads)\n", nsample, (double)nsamplethread/nsample);
+	for(i = 0; i < nfunc; i++) {
+		f = ff[i];
+		fprint(2, "%6.2f%%\t", 100.0*(double)f->leaf/nsample);
+		if(stacks)
+			fprint(2, "%6.2f%%\t", 100.0*(double)f->onstack/nsample);
+		fprint(2, "%s\n", f->s.name);
+	}
+}
+
+typedef struct Trace Trace;
+struct Trace {
+	int	count;
+	int	npc;
+	uvlong	*pc;
+	Trace	*next;
+};
+
+void
+dumppprof(void)
+{
+	uvlong i, n, *p, *e;
+	int ntrace;
+	Trace *trace, *tp, *up, *prev;
+
+	if(!pprof)
+		return;
+	e = ppdata + nppdata;
+	// Create list of traces.  First, count the traces
+	ntrace = 0;
+	for(p = ppdata; p < e;) {
+		n = *p++;
+		p += n;
+		if(n == 0)
+			continue;
+		ntrace++;
+	}
+	if(ntrace <= 0)
+		return;
+	// Allocate and link the traces together.
+	trace = malloc(ntrace * sizeof(Trace));
+	if(trace == nil)
+		sysfatal("out of memory");
+	tp = trace;
+	for(p = ppdata; p < e;) {
+		n = *p++;
+		if(n == 0)
+			continue;
+		tp->count = 1;
+		tp->npc = n;
+		tp->pc = p;
+		tp->next = tp+1;
+		tp++;
+		p += n;
+	}
+	trace[ntrace-1].next = nil;
+	// Eliminate duplicates.  Lousy algorithm, although not as bad as it looks because
+	// the list collapses fast.
+	for(tp = trace; tp != nil; tp = tp->next) {
+		prev = tp;
+		for(up = tp->next; up != nil; up = up->next) {
+			if(up->npc == tp->npc && memcmp(up->pc, tp->pc, up->npc*sizeof up->pc[0]) == 0) {
+				tp->count++;
+				prev->next = up->next;
+			} else {
+				prev = up;
+			}
+		}
+	}
+	// Write file.
+	// See http://code.google.com/p/google-perftools/source/browse/trunk/doc/cpuprofile-fileformat.html
+	// 1) Header
+	arch->ppword(0);	// must be zero
+	arch->ppword(3);	// 3 words follow in header
+	arch->ppword(0);	// must be zero
+	arch->ppword(delta_msec * 1000);	// sampling period in microseconds
+	arch->ppword(0);	// must be zero (padding)
+	// 2) One record for each trace.
+	for(tp = trace; tp != nil; tp = tp->next) {
+		arch->ppword(tp->count);
+		arch->ppword(tp->npc);
+		for(i = 0; i < tp->npc; i++) {
+			arch->ppword(tp->pc[i]);
+		}
+	}
+	// 3) Binary trailer
+	arch->ppword(0);	// must be zero
+	arch->ppword(1);	// must be one
+	arch->ppword(0);	// must be zero
+	// 4) Mapped objects.
+	Bwrite(pproffd, ppmapdata, strlen(ppmapdata));
+	// 5) That's it.
+	Bterm(pproffd);
+}
+
+int
+startprocess(char **argv)
+{
+	int pid;
+
+	if((pid = fork()) == 0) {
+		pid = getpid();
+		if(ctlproc(pid, "hang") < 0){
+			fprint(2, "prof: child process could not hang\n");
+			exits(0);
+		}
+		execv(argv[0], argv);
+		fprint(2, "prof: could not exec %s: %r\n", argv[0]);
+		exits(0);
+	}
+
+	if(pid == -1) {
+		fprint(2, "prof: could not fork\n");
+		exit(1);
+	}
+	if(ctlproc(pid, "attached") < 0 || ctlproc(pid, "waitstop") < 0) {
+		fprint(2, "prof: could not attach to child process: %r\n");
+		exit(1);
+	}
+	return pid;
+}
+
+void
+detach(void)
+{
+	int i;
+
+	for(i = 0; i < nthread; i++)
+		detachproc(map[i]);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int i;
+	char *ppfile;
+
+	ARGBEGIN{
+	case 'P':
+		pprof =1;
+		ppfile = EARGF(Usage());
+		pproffd = Bopen(ppfile, OWRITE);
+		if(pproffd == nil) {
+			fprint(2, "prof: cannot open %s: %r\n", ppfile);
+			exit(2);
+		}
+		break;
+	case 'd':
+		delta_msec = atoi(EARGF(Usage()));
+		break;
+	case 't':
+		total_sec = atoi(EARGF(Usage()));
+		break;
+	case 'p':
+		pid = atoi(EARGF(Usage()));
+		break;
+	case 'f':
+		functions = 1;
+		break;
+	case 'h':
+		histograms = 1;
+		break;
+	case 'l':
+		linenums = 1;
+		break;
+	case 'r':
+		registers = 1;
+		break;
+	case 's':
+		stacks++;
+		break;
+	default:
+		Usage();
+	}ARGEND
+	if(pid <= 0 && argc == 0)
+		Usage();
+	if(functions+linenums+registers+stacks+pprof == 0)
+		histograms = 1;
+	if(!machbyname("amd64")) {
+		fprint(2, "prof: no amd64 support\n", pid);
+		exit(1);
+	}
+	if(argc > 0)
+		file = argv[0];
+	else if(pid) {
+		file = proctextfile(pid);
+		if (file == NULL) {
+			fprint(2, "prof: can't find file for pid %d: %r\n", pid);
+			fprint(2, "prof: on Darwin, need to provide file name explicitly\n");
+			exit(1);
+		}
+	}
+	fd = open(file, 0);
+	if(fd < 0) {
+		fprint(2, "prof: can't open %s: %r\n", file);
+		exit(1);
+	}
+	if(crackhdr(fd, &fhdr)) {
+		have_syms = syminit(fd, &fhdr);
+		if(!have_syms) {
+			fprint(2, "prof: no symbols for %s: %r\n", file);
+		}
+	} else {
+		fprint(2, "prof: crack header for %s: %r\n", file);
+		exit(1);
+	}
+	if(pid <= 0)
+		pid = startprocess(argv);
+	attachproc(pid, &fhdr);	// initializes thread list
+	if(setarch() < 0) {
+		detach();
+		fprint(2, "prof: can't identify binary architecture for pid %d\n", pid);
+		exit(1);
+	}
+	if(getthreads() <= 0) {
+		detach();
+		fprint(2, "prof: can't find threads for pid %d\n", pid);
+		exit(1);
+	}
+	for(i = 0; i < nthread; i++)
+		ctlproc(thread[i], "start");
+	samples();
+	detach();
+	dumphistogram();
+	dumppprof();
+	exit(0);
+}
diff --git a/src/cmd/vet/Makefile b/src/cmd/vet/Makefile
index 2a35d1a..307f472 100644
--- a/src/cmd/vet/Makefile
+++ b/src/cmd/vet/Makefile
@@ -3,5 +3,6 @@
 # license that can be found in the LICENSE file.
 
 test testshort:
-	go build
-	../../../test/errchk ./vet -printfuncs='Warn:1,Warnf:1' print.go
+	go build -tags vet_test
+	../../../test/errchk ./vet -compositewhitelist=false -printfuncs='Warn:1,Warnf:1' *.go
+
diff --git a/src/cmd/vet/atomic.go b/src/cmd/vet/atomic.go
new file mode 100644
index 0000000..4ab256f
--- /dev/null
+++ b/src/cmd/vet/atomic.go
@@ -0,0 +1,59 @@
+// 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 main
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// checkAtomicAssignment walks the assignment statement checking for common
+// mistaken usage of atomic package, such as: x = atomic.AddUint64(&x, 1)
+func (f *File) checkAtomicAssignment(n *ast.AssignStmt) {
+	if !vet("atomic") {
+		return
+	}
+
+	if len(n.Lhs) != len(n.Rhs) {
+		return
+	}
+
+	for i, right := range n.Rhs {
+		call, ok := right.(*ast.CallExpr)
+		if !ok {
+			continue
+		}
+		sel, ok := call.Fun.(*ast.SelectorExpr)
+		if !ok {
+			continue
+		}
+		pkg, ok := sel.X.(*ast.Ident)
+		if !ok || pkg.Name != "atomic" {
+			continue
+		}
+
+		switch sel.Sel.Name {
+		case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr":
+			f.checkAtomicAddAssignment(n.Lhs[i], call)
+		}
+	}
+}
+
+// checkAtomicAddAssignment walks the atomic.Add* method calls checking for assigning the return value
+// to the same variable being used in the operation
+func (f *File) checkAtomicAddAssignment(left ast.Expr, call *ast.CallExpr) {
+	arg := call.Args[0]
+	broken := false
+
+	if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND {
+		broken = f.gofmt(left) == f.gofmt(uarg.X)
+	} else if star, ok := left.(*ast.StarExpr); ok {
+		broken = f.gofmt(star.X) == f.gofmt(arg)
+	}
+
+	if broken {
+		f.Warn(left.Pos(), "direct assignment to atomic value")
+	}
+}
diff --git a/src/cmd/vet/buildtag.go b/src/cmd/vet/buildtag.go
new file mode 100644
index 0000000..4b75804
--- /dev/null
+++ b/src/cmd/vet/buildtag.go
@@ -0,0 +1,91 @@
+// 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 main
+
+import (
+	"bytes"
+	"fmt"
+	"os"
+	"strings"
+	"unicode"
+)
+
+var (
+	nl         = []byte("\n")
+	slashSlash = []byte("//")
+	plusBuild  = []byte("+build")
+)
+
+// checkBuildTag checks that build tags are in the correct location and well-formed.
+func checkBuildTag(name string, data []byte) {
+	if !vet("buildtags") {
+		return
+	}
+	lines := bytes.SplitAfter(data, nl)
+
+	// Determine cutpoint where +build comments are no longer valid.
+	// They are valid in leading // comments in the file followed by
+	// a blank line.
+	var cutoff int
+	for i, line := range lines {
+		line = bytes.TrimSpace(line)
+		if len(line) == 0 {
+			cutoff = i
+			continue
+		}
+		if bytes.HasPrefix(line, slashSlash) {
+			continue
+		}
+		break
+	}
+
+	for i, line := range lines {
+		line = bytes.TrimSpace(line)
+		if !bytes.HasPrefix(line, slashSlash) {
+			continue
+		}
+		text := bytes.TrimSpace(line[2:])
+		if bytes.HasPrefix(text, plusBuild) {
+			fields := bytes.Fields(text)
+			if !bytes.Equal(fields[0], plusBuild) {
+				// Comment is something like +buildasdf not +build.
+				fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1)
+				continue
+			}
+			if i >= cutoff {
+				fmt.Fprintf(os.Stderr, "%s:%d: +build comment appears too late in file\n", name, i+1)
+				setExit(1)
+				continue
+			}
+			// Check arguments.
+		Args:
+			for _, arg := range fields[1:] {
+				for _, elem := range strings.Split(string(arg), ",") {
+					if strings.HasPrefix(elem, "!!") {
+						fmt.Fprintf(os.Stderr, "%s:%d: invalid double negative in build constraint: %s\n", name, i+1, arg)
+						setExit(1)
+						break Args
+					}
+					if strings.HasPrefix(elem, "!") {
+						elem = elem[1:]
+					}
+					for _, c := range elem {
+						if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' {
+							fmt.Fprintf(os.Stderr, "%s:%d: invalid non-alphanumeric build constraint: %s\n", name, i+1, arg)
+							setExit(1)
+							break Args
+						}
+					}
+				}
+			}
+			continue
+		}
+		// Comment with +build but not at beginning.
+		if bytes.Contains(line, plusBuild) && i < cutoff {
+			fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1)
+			continue
+		}
+	}
+}
diff --git a/src/cmd/vet/buildtag_bad.go b/src/cmd/vet/buildtag_bad.go
new file mode 100644
index 0000000..4dca6a4
--- /dev/null
+++ b/src/cmd/vet/buildtag_bad.go
@@ -0,0 +1,11 @@
+// This file contains misplaced or malformed build constraints.
+// The Go tool will skip it, because the constraints are invalid.
+// It serves only to test the tag checker during make test.
+
+// Mention +build // ERROR "possible malformed \+build comment"
+
+// +build !!bang // ERROR "invalid double negative in build constraint"
+// +build @#$ // ERROR "invalid non-alphanumeric build constraint"
+
+// +build toolate // ERROR "build comment appears too late in file"
+package main
diff --git a/src/cmd/vet/doc.go b/src/cmd/vet/doc.go
index 620964a..f164eac 100644
--- a/src/cmd/vet/doc.go
+++ b/src/cmd/vet/doc.go
@@ -9,9 +9,12 @@ calls whose arguments do not align with the format string. Vet uses heuristics
 that do not guarantee all reports are genuine problems, but it can find errors
 not caught by the compilers.
 
+By default all checks are performed, but if explicit flags are provided, only
+those identified by the flags are performed.
+
 Available checks:
 
-1. Printf family
+1. Printf family, flag -printf
 
 Suspicious calls to functions in the Printf family, including any functions
 with these names:
@@ -28,24 +31,29 @@ complains about arguments that look like format descriptor strings.
 It also checks for errors such as using a Writer as the first argument of
 Printf.
 
-2. Methods
+2. Methods, flag -methods
 
 Non-standard signatures for methods with familiar names, including:
 	Format GobEncode GobDecode MarshalJSON MarshalXML
-	Peek ReadByte ReadFrom ReadRune Scan Seek 
+	Peek ReadByte ReadFrom ReadRune Scan Seek
 	UnmarshalJSON UnreadByte UnreadRune WriteByte
 	WriteTo
 
-3. Struct tags
+3. Struct tags, flag -structtags
 
 Struct tags that do not follow the format understood by reflect.StructTag.Get.
 
+4. Untagged composite literals, flag -composites
+
+Composite struct literals that do not use the type-tagged syntax.
+
+
 Usage:
 
 	go tool vet [flag] [file.go ...]
 	go tool vet [flag] [directory ...] # Scan all .go files under directory, recursively
 
-The flags are:
+The other flags are:
 	-v
 		Verbose mode
 	-printfuncs
@@ -59,4 +67,4 @@ The flags are:
 			-printfuncs=Warn:1,Warnf:1
 
 */
-package documentation
+package main
diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go
index 6251333..20f6cca 100644
--- a/src/cmd/vet/main.go
+++ b/src/cmd/vet/main.go
@@ -11,9 +11,12 @@ import (
 	"flag"
 	"fmt"
 	"go/ast"
+	"go/build"
 	"go/parser"
+	"go/printer"
 	"go/token"
-	"io"
+	"go/types"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strconv"
@@ -23,6 +26,24 @@ import (
 var verbose = flag.Bool("v", false, "verbose")
 var exitCode = 0
 
+// Flags to control which checks to perform. "all" is set to true here, and disabled later if
+// a flag is set explicitly.
+var report = map[string]*bool{
+	"all":        flag.Bool("all", true, "check everything; disabled if any explicit check is requested"),
+	"atomic":     flag.Bool("atomic", false, "check for common mistaken usages of the sync/atomic package"),
+	"buildtags":  flag.Bool("buildtags", false, "check that +build tags are valid"),
+	"composites": flag.Bool("composites", false, "check that composite literals used type-tagged elements"),
+	"methods":    flag.Bool("methods", false, "check that canonically named methods are canonically defined"),
+	"printf":     flag.Bool("printf", false, "check printf-like invocations"),
+	"structtags": flag.Bool("structtags", false, "check that struct field tags have canonical format"),
+	"rangeloops": flag.Bool("rangeloops", false, "check that range loop variables are used correctly"),
+}
+
+// vet tells whether to report errors for the named check, a flag name.
+func vet(name string) bool {
+	return *report["all"] || *report[name]
+}
+
 // setExit sets the value for os.Exit when it is called, later.  It
 // remembers the highest value.
 func setExit(err int) {
@@ -34,6 +55,8 @@ func setExit(err int) {
 // Usage is a replacement usage function for the flags package.
 func Usage() {
 	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
+	fmt.Fprintf(os.Stderr, "\tvet [flags] directory...\n")
+	fmt.Fprintf(os.Stderr, "\tvet [flags] files... # Must be a single package\n")
 	flag.PrintDefaults()
 	os.Exit(2)
 }
@@ -41,7 +64,9 @@ func Usage() {
 // File is a wrapper for the state of a file used in the parser.
 // The parse tree walkers are all methods of this type.
 type File struct {
+	pkg  *Package
 	fset *token.FileSet
+	name string
 	file *ast.File
 	b    bytes.Buffer // for use by methods
 }
@@ -50,6 +75,14 @@ func main() {
 	flag.Usage = Usage
 	flag.Parse()
 
+	// If a check is named explicitly, turn off the 'all' flag.
+	for name, ptr := range report {
+		if name != "all" && *ptr {
+			*report["all"] = false
+			break
+		}
+	}
+
 	if *printfuncs != "" {
 		for _, name := range strings.Split(*printfuncs, ",") {
 			if len(name) == 0 {
@@ -74,41 +107,135 @@ func main() {
 	}
 
 	if flag.NArg() == 0 {
-		doFile("stdin", os.Stdin)
-	} else {
+		Usage()
+	}
+	dirs := false
+	files := false
+	for _, name := range flag.Args() {
+		// Is it a directory?
+		fi, err := os.Stat(name)
+		if err != nil {
+			warnf("error walking tree: %s", err)
+			continue
+		}
+		if fi.IsDir() {
+			dirs = true
+		} else {
+			files = true
+		}
+	}
+	if dirs && files {
+		Usage()
+	}
+	if dirs {
 		for _, name := range flag.Args() {
-			// Is it a directory?
-			if fi, err := os.Stat(name); err == nil && fi.IsDir() {
-				walkDir(name)
-			} else {
-				doFile(name, nil)
-			}
+			walkDir(name)
 		}
+		return
 	}
+	doPackage(flag.Args())
 	os.Exit(exitCode)
 }
 
-// doFile analyzes one file.  If the reader is nil, the source code is read from the
-// named file.
-func doFile(name string, reader io.Reader) {
-	fs := token.NewFileSet()
-	parsedFile, err := parser.ParseFile(fs, name, reader, 0)
+// prefixDirectory places the directory name on the beginning of each name in the list.
+func prefixDirectory(directory string, names []string) {
+	if directory != "." {
+		for i, name := range names {
+			names[i] = filepath.Join(directory, name)
+		}
+	}
+}
+
+// doPackageDir analyzes the single package found in the directory, if there is one,
+// plus a test package, if there is one.
+func doPackageDir(directory string) {
+	pkg, err := build.Default.ImportDir(directory, 0)
 	if err != nil {
-		errorf("%s: %s", name, err)
+		// If it's just that there are no go source files, that's fine.
+		if _, nogo := err.(*build.NoGoError); nogo {
+			return
+		}
+		// Non-fatal: we are doing a recursive walk and there may be other directories.
+		warnf("cannot process directory %s: %s", directory, err)
 		return
 	}
-	file := &File{fset: fs, file: parsedFile}
-	file.walkFile(name, parsedFile)
+	var names []string
+	names = append(names, pkg.GoFiles...)
+	names = append(names, pkg.CgoFiles...)
+	names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
+	prefixDirectory(directory, names)
+	doPackage(names)
+	// Is there also a "foo_test" package? If so, do that one as well.
+	if len(pkg.XTestGoFiles) > 0 {
+		names = pkg.XTestGoFiles
+		prefixDirectory(directory, names)
+		doPackage(names)
+	}
+}
+
+type Package struct {
+	types  map[ast.Expr]types.Type
+	values map[ast.Expr]interface{}
+}
+
+// doPackage analyzes the single package constructed from the named files.
+func doPackage(names []string) {
+	var files []*File
+	var astFiles []*ast.File
+	fs := token.NewFileSet()
+	for _, name := range names {
+		f, err := os.Open(name)
+		if err != nil {
+			errorf("%s: %s", name, err)
+		}
+		defer f.Close()
+		data, err := ioutil.ReadAll(f)
+		if err != nil {
+			errorf("%s: %s", name, err)
+		}
+		checkBuildTag(name, data)
+		parsedFile, err := parser.ParseFile(fs, name, bytes.NewReader(data), 0)
+		if err != nil {
+			errorf("%s: %s", name, err)
+		}
+		files = append(files, &File{fset: fs, name: name, file: parsedFile})
+		astFiles = append(astFiles, parsedFile)
+	}
+	pkg := new(Package)
+	pkg.types = make(map[ast.Expr]types.Type)
+	pkg.values = make(map[ast.Expr]interface{})
+	exprFn := func(x ast.Expr, typ types.Type, val interface{}) {
+		pkg.types[x] = typ
+		if val != nil {
+			pkg.values[x] = val
+		}
+	}
+	// By providing the Context with our own error function, it will continue
+	// past the first error. There is no need for that function to do anything.
+	context := types.Context{
+		Expr:  exprFn,
+		Error: func(error) {},
+	}
+	// Type check the package.
+	_, err := context.Check(fs, astFiles)
+	if err != nil && *verbose {
+		warnf("%s", err)
+	}
+	for _, file := range files {
+		file.pkg = pkg
+		file.walkFile(file.name, file.file)
+	}
 }
 
 func visit(path string, f os.FileInfo, err error) error {
 	if err != nil {
 		errorf("walk error: %s", err)
-		return nil
 	}
-	if !f.IsDir() && strings.HasSuffix(path, ".go") {
-		doFile(path, nil)
+	// One package per directory. Ignore the files themselves.
+	if !f.IsDir() {
+		return nil
 	}
+	doPackageDir(path)
 	return nil
 }
 
@@ -117,11 +244,18 @@ func walkDir(root string) {
 	filepath.Walk(root, visit)
 }
 
-// error formats the error to standard error, adding program
-// identification and a newline
+// errorf formats the error to standard error, adding program
+// identification and a newline, and exits.
 func errorf(format string, args ...interface{}) {
 	fmt.Fprintf(os.Stderr, "vet: "+format+"\n", args...)
-	setExit(2)
+	os.Exit(2)
+}
+
+// warnf formats the error to standard error, adding program
+// identification and a newline, but does not exit.
+func warnf(format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, "vet: "+format+"\n", args...)
+	setExit(1)
 }
 
 // Println is fmt.Println guarded by -v.
@@ -152,16 +286,22 @@ func (f *File) Badf(pos token.Pos, format string, args ...interface{}) {
 	setExit(1)
 }
 
+func (f *File) loc(pos token.Pos) string {
+	// Do not print columns. Because the pos often points to the start of an
+	// expression instead of the inner part with the actual error, the
+	// precision can mislead.
+	posn := f.fset.Position(pos)
+	return fmt.Sprintf("%s:%d: ", posn.Filename, posn.Line)
+}
+
 // Warn reports an error but does not set the exit code.
 func (f *File) Warn(pos token.Pos, args ...interface{}) {
-	loc := f.fset.Position(pos).String() + ": "
-	fmt.Fprint(os.Stderr, loc+fmt.Sprintln(args...))
+	fmt.Fprint(os.Stderr, f.loc(pos)+fmt.Sprintln(args...))
 }
 
 // Warnf reports a formatted error but does not set the exit code.
 func (f *File) Warnf(pos token.Pos, format string, args ...interface{}) {
-	loc := f.fset.Position(pos).String() + ": "
-	fmt.Fprintf(os.Stderr, loc+format+"\n", args...)
+	fmt.Fprintf(os.Stderr, f.loc(pos)+format+"\n", args...)
 }
 
 // walkFile walks the file's tree.
@@ -173,6 +313,8 @@ func (f *File) walkFile(name string, file *ast.File) {
 // Visit implements the ast.Visitor interface.
 func (f *File) Visit(node ast.Node) ast.Visitor {
 	switch n := node.(type) {
+	case *ast.AssignStmt:
+		f.walkAssignStmt(n)
 	case *ast.CallExpr:
 		f.walkCallExpr(n)
 	case *ast.CompositeLit:
@@ -183,15 +325,32 @@ func (f *File) Visit(node ast.Node) ast.Visitor {
 		f.walkMethodDecl(n)
 	case *ast.InterfaceType:
 		f.walkInterfaceType(n)
+	case *ast.RangeStmt:
+		f.walkRangeStmt(n)
 	}
 	return f
 }
 
+// walkAssignStmt walks an assignment statement
+func (f *File) walkAssignStmt(stmt *ast.AssignStmt) {
+	f.checkAtomicAssignment(stmt)
+}
+
 // walkCall walks a call expression.
 func (f *File) walkCall(call *ast.CallExpr, name string) {
 	f.checkFmtPrintfCall(call, name)
 }
 
+// walkCallExpr walks a call expression.
+func (f *File) walkCallExpr(call *ast.CallExpr) {
+	switch x := call.Fun.(type) {
+	case *ast.Ident:
+		f.walkCall(call, x.Name)
+	case *ast.SelectorExpr:
+		f.walkCall(call, x.Sel.Name)
+	}
+}
+
 // walkCompositeLit walks a composite literal.
 func (f *File) walkCompositeLit(c *ast.CompositeLit) {
 	f.checkUntaggedLiteral(c)
@@ -228,12 +387,14 @@ func (f *File) walkInterfaceType(t *ast.InterfaceType) {
 	}
 }
 
-// walkCallExpr walks a call expression.
-func (f *File) walkCallExpr(call *ast.CallExpr) {
-	switch x := call.Fun.(type) {
-	case *ast.Ident:
-		f.walkCall(call, x.Name)
-	case *ast.SelectorExpr:
-		f.walkCall(call, x.Sel.Name)
-	}
+// walkRangeStmt walks a range statement.
+func (f *File) walkRangeStmt(n *ast.RangeStmt) {
+	checkRangeLoop(f, n)
+}
+
+// gofmt returns a string representation of the expression.
+func (f *File) gofmt(x ast.Expr) string {
+	f.b.Reset()
+	printer.Fprint(&f.b, f.fset, x)
+	return f.b.String()
 }
diff --git a/src/cmd/vet/method.go b/src/cmd/vet/method.go
index 41cb40f..bf982dc 100644
--- a/src/cmd/vet/method.go
+++ b/src/cmd/vet/method.go
@@ -55,6 +55,9 @@ var canonicalMethods = map[string]MethodSig{
 }
 
 func (f *File) checkCanonicalMethod(id *ast.Ident, t *ast.FuncType) {
+	if !vet("methods") {
+		return
+	}
 	// Expected input/output.
 	expect, ok := canonicalMethods[id.Name]
 	if !ok {
@@ -87,9 +90,7 @@ func (f *File) checkCanonicalMethod(id *ast.Ident, t *ast.FuncType) {
 			fmt.Fprintf(&f.b, "<%s>", err)
 		}
 		actual := f.b.String()
-		if strings.HasPrefix(actual, "func(") {
-			actual = actual[4:]
-		}
+		actual = strings.TrimPrefix(actual, "func")
 		actual = id.Name + actual
 
 		f.Warnf(id.Pos(), "method %s should have signature %s", actual, expectFmt)
diff --git a/src/cmd/vet/print.go b/src/cmd/vet/print.go
index ee9a33c..fb0fb9f 100644
--- a/src/cmd/vet/print.go
+++ b/src/cmd/vet/print.go
@@ -8,9 +8,10 @@ package main
 
 import (
 	"flag"
-	"fmt"
 	"go/ast"
 	"go/token"
+	"go/types"
+	"strconv"
 	"strings"
 	"unicode/utf8"
 )
@@ -43,6 +44,9 @@ var printList = map[string]int{
 
 // checkCall triggers the print-specific checks if the call invokes a print function.
 func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
+	if !vet("printf") {
+		return
+	}
 	name := strings.ToLower(Name)
 	if skip, ok := printfList[name]; ok {
 		f.checkPrintf(call, Name, skip)
@@ -54,73 +58,134 @@ func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
 	}
 }
 
+// literal returns the literal value represented by the expression, or nil if it is not a literal.
+func (f *File) literal(value ast.Expr) *ast.BasicLit {
+	switch v := value.(type) {
+	case *ast.BasicLit:
+		return v
+	case *ast.ParenExpr:
+		return f.literal(v.X)
+	case *ast.BinaryExpr:
+		if v.Op != token.ADD {
+			break
+		}
+		litX := f.literal(v.X)
+		litY := f.literal(v.Y)
+		if litX != nil && litY != nil {
+			lit := *litX
+			x, errX := strconv.Unquote(litX.Value)
+			y, errY := strconv.Unquote(litY.Value)
+			if errX == nil && errY == nil {
+				return &ast.BasicLit{
+					ValuePos: lit.ValuePos,
+					Kind:     lit.Kind,
+					Value:    strconv.Quote(x + y),
+				}
+			}
+		}
+	case *ast.Ident:
+		// See if it's a constant or initial value (we can't tell the difference).
+		if v.Obj == nil || v.Obj.Decl == nil {
+			return nil
+		}
+		valueSpec, ok := v.Obj.Decl.(*ast.ValueSpec)
+		if ok && len(valueSpec.Names) == len(valueSpec.Values) {
+			// Find the index in the list of names
+			var i int
+			for i = 0; i < len(valueSpec.Names); i++ {
+				if valueSpec.Names[i].Name == v.Name {
+					if lit, ok := valueSpec.Values[i].(*ast.BasicLit); ok {
+						return lit
+					}
+					return nil
+				}
+			}
+		}
+	}
+	return nil
+}
+
 // checkPrintf checks a call to a formatted print routine such as Printf.
-// The skip argument records how many arguments to ignore; that is,
-// call.Args[skip] is (well, should be) the format argument.
-func (f *File) checkPrintf(call *ast.CallExpr, name string, skip int) {
-	if len(call.Args) <= skip {
+// call.Args[formatIndex] is (well, should be) the format argument.
+func (f *File) checkPrintf(call *ast.CallExpr, name string, formatIndex int) {
+	if formatIndex >= len(call.Args) {
 		return
 	}
-	// Common case: literal is first argument.
-	arg := call.Args[skip]
-	lit, ok := arg.(*ast.BasicLit)
-	if !ok {
-		// Too hard to check.
+	lit := f.literal(call.Args[formatIndex])
+	if lit == nil {
 		if *verbose {
 			f.Warn(call.Pos(), "can't check non-literal format in call to", name)
 		}
 		return
 	}
-	if lit.Kind == token.STRING {
-		if !strings.Contains(lit.Value, "%") {
-			if len(call.Args) > skip+1 {
-				f.Badf(call.Pos(), "no formatting directive in %s call", name)
-			}
-			return
+	if lit.Kind != token.STRING {
+		f.Badf(call.Pos(), "literal %v not a string in call to", lit.Value, name)
+	}
+	format, err := strconv.Unquote(lit.Value)
+	if err != nil {
+		// Shouldn't happen if parser returned no errors, but be safe.
+		f.Badf(call.Pos(), "invalid quoted string literal")
+	}
+	firstArg := formatIndex + 1 // Arguments are immediately after format string.
+	if !strings.Contains(format, "%") {
+		if len(call.Args) > firstArg {
+			f.Badf(call.Pos(), "no formatting directive in %s call", name)
 		}
+		return
 	}
 	// Hard part: check formats against args.
-	// Trivial but useful test: count.
-	numArgs := 0
-	for i, w := 0, 0; i < len(lit.Value); i += w {
+	argNum := firstArg
+	for i, w := 0, 0; i < len(format); i += w {
 		w = 1
-		if lit.Value[i] == '%' {
-			nbytes, nargs := f.parsePrintfVerb(call, lit.Value[i:])
+		if format[i] == '%' {
+			verb, flags, nbytes, nargs := f.parsePrintfVerb(call, format[i:])
 			w = nbytes
-			numArgs += nargs
+			if verb == '%' { // "%%" does nothing interesting.
+				continue
+			}
+			// If we've run out of args, print after loop will pick that up.
+			if argNum+nargs <= len(call.Args) {
+				f.checkPrintfArg(call, verb, flags, argNum, nargs)
+			}
+			argNum += nargs
 		}
 	}
-	expect := len(call.Args) - (skip + 1)
-	if numArgs != expect {
-		f.Badf(call.Pos(), "wrong number of args in %s call: %d needed but %d args", name, numArgs, expect)
+	// TODO: Dotdotdot is hard.
+	if call.Ellipsis.IsValid() && argNum != len(call.Args) {
+		return
+	}
+	if argNum != len(call.Args) {
+		expect := argNum - firstArg
+		numArgs := len(call.Args) - firstArg
+		f.Badf(call.Pos(), "wrong number of args for format in %s call: %d needed but %d args", name, expect, numArgs)
 	}
 }
 
-// parsePrintfVerb returns the number of bytes and number of arguments
-// consumed by the Printf directive that begins s, including its percent sign
-// and verb.
-func (f *File) parsePrintfVerb(call *ast.CallExpr, s string) (nbytes, nargs int) {
+// parsePrintfVerb returns the verb that begins the format string, along with its flags,
+// the number of bytes to advance the format to step past the verb, and number of
+// arguments it consumes.
+func (f *File) parsePrintfVerb(call *ast.CallExpr, format string) (verb rune, flags []byte, nbytes, nargs int) {
 	// There's guaranteed a percent sign.
-	flags := make([]byte, 0, 5)
+	flags = make([]byte, 0, 5)
 	nbytes = 1
-	end := len(s)
+	end := len(format)
 	// There may be flags.
 FlagLoop:
 	for nbytes < end {
-		switch s[nbytes] {
+		switch format[nbytes] {
 		case '#', '0', '+', '-', ' ':
-			flags = append(flags, s[nbytes])
+			flags = append(flags, format[nbytes])
 			nbytes++
 		default:
 			break FlagLoop
 		}
 	}
 	getNum := func() {
-		if nbytes < end && s[nbytes] == '*' {
+		if nbytes < end && format[nbytes] == '*' {
 			nbytes++
 			nargs++
 		} else {
-			for nbytes < end && '0' <= s[nbytes] && s[nbytes] <= '9' {
+			for nbytes < end && '0' <= format[nbytes] && format[nbytes] <= '9' {
 				nbytes++
 			}
 		}
@@ -128,24 +193,38 @@ FlagLoop:
 	// There may be a width.
 	getNum()
 	// If there's a period, there may be a precision.
-	if nbytes < end && s[nbytes] == '.' {
+	if nbytes < end && format[nbytes] == '.' {
 		flags = append(flags, '.') // Treat precision as a flag.
 		nbytes++
 		getNum()
 	}
 	// Now a verb.
-	c, w := utf8.DecodeRuneInString(s[nbytes:])
+	c, w := utf8.DecodeRuneInString(format[nbytes:])
 	nbytes += w
+	verb = c
 	if c != '%' {
 		nargs++
-		f.checkPrintfVerb(call, c, flags)
 	}
 	return
 }
 
+// printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask.
+type printfArgType int
+
+const (
+	argBool printfArgType = 1 << iota
+	argInt
+	argRune
+	argString
+	argFloat
+	argPointer
+	anyType printfArgType = ^0
+)
+
 type printVerb struct {
 	verb  rune
 	flags string // known flags are all ASCII
+	typ   printfArgType
 }
 
 // Common flag sets for printf verbs.
@@ -164,36 +243,57 @@ var printVerbs = []printVerb{
 	// '+' is required sign for numbers, Go format for %v.
 	// '#' is alternate format for several verbs.
 	// ' ' is spacer for numbers
-	{'b', numFlag},
-	{'c', "-"},
-	{'d', numFlag},
-	{'e', numFlag},
-	{'E', numFlag},
-	{'f', numFlag},
-	{'F', numFlag},
-	{'g', numFlag},
-	{'G', numFlag},
-	{'o', sharpNumFlag},
-	{'p', "-#"},
-	{'q', "-+#."},
-	{'s', "-."},
-	{'t', "-"},
-	{'T', "-"},
-	{'U', "-#"},
-	{'v', allFlags},
-	{'x', sharpNumFlag},
-	{'X', sharpNumFlag},
+	{'b', numFlag, argInt | argFloat},
+	{'c', "-", argRune | argInt},
+	{'d', numFlag, argInt},
+	{'e', numFlag, argFloat},
+	{'E', numFlag, argFloat},
+	{'f', numFlag, argFloat},
+	{'F', numFlag, argFloat},
+	{'g', numFlag, argFloat},
+	{'G', numFlag, argFloat},
+	{'o', sharpNumFlag, argInt},
+	{'p', "-#", argPointer},
+	{'q', " -+.0#", argRune | argInt | argString},
+	{'s', " -+.0", argString},
+	{'t', "-", argBool},
+	{'T', "-", anyType},
+	{'U', "-#", argRune | argInt},
+	{'v', allFlags, anyType},
+	{'x', sharpNumFlag, argRune | argInt | argString},
+	{'X', sharpNumFlag, argRune | argInt | argString},
 }
 
 const printfVerbs = "bcdeEfFgGopqstTvxUX"
 
-func (f *File) checkPrintfVerb(call *ast.CallExpr, verb rune, flags []byte) {
+func (f *File) checkPrintfArg(call *ast.CallExpr, verb rune, flags []byte, argNum, nargs int) {
 	// Linear scan is fast enough for a small list.
 	for _, v := range printVerbs {
 		if v.verb == verb {
 			for _, flag := range flags {
 				if !strings.ContainsRune(v.flags, rune(flag)) {
 					f.Badf(call.Pos(), "unrecognized printf flag for verb %q: %q", verb, flag)
+					return
+				}
+			}
+			// Verb is good. If nargs>1, we have something like %.*s and all but the final
+			// arg must be integer.
+			for i := 0; i < nargs-1; i++ {
+				if !f.matchArgType(argInt, call.Args[argNum+i]) {
+					f.Badf(call.Pos(), "arg %s for * in printf format not of type int", f.gofmt(call.Args[argNum+i]))
+				}
+			}
+			for _, v := range printVerbs {
+				if v.verb == verb {
+					arg := call.Args[argNum+nargs-1]
+					if !f.matchArgType(v.typ, arg) {
+						typeString := ""
+						if typ := f.pkg.types[arg]; typ != nil {
+							typeString = typ.String()
+						}
+						f.Badf(call.Pos(), "arg %s for printf verb %%%c of wrong type: %s", f.gofmt(arg), verb, typeString)
+					}
+					break
 				}
 			}
 			return
@@ -202,15 +302,67 @@ func (f *File) checkPrintfVerb(call *ast.CallExpr, verb rune, flags []byte) {
 	f.Badf(call.Pos(), "unrecognized printf verb %q", verb)
 }
 
+func (f *File) matchArgType(t printfArgType, arg ast.Expr) bool {
+	// TODO: for now, we can only test builtin types and untyped constants.
+	typ := f.pkg.types[arg]
+	if typ == nil {
+		return true
+	}
+	basic, ok := typ.(*types.Basic)
+	if !ok {
+		return true
+	}
+	switch basic.Kind {
+	case types.Bool:
+		return t&argBool != 0
+	case types.Int, types.Int8, types.Int16, types.Int32, types.Int64:
+		fallthrough
+	case types.Uint, types.Uint8, types.Uint16, types.Uint32, types.Uint64, types.Uintptr:
+		return t&argInt != 0
+	case types.Float32, types.Float64, types.Complex64, types.Complex128:
+		return t&argFloat != 0
+	case types.String:
+		return t&argString != 0
+	case types.UnsafePointer:
+		return t&(argPointer|argInt) != 0
+	case types.UntypedBool:
+		return t&argBool != 0
+	case types.UntypedComplex:
+		return t&argFloat != 0
+	case types.UntypedFloat:
+		// If it's integral, we can use an int format.
+		switch f.pkg.values[arg].(type) {
+		case int, int8, int16, int32, int64:
+			return t&(argInt|argFloat) != 0
+		case uint, uint8, uint16, uint32, uint64:
+			return t&(argInt|argFloat) != 0
+		}
+		return t&argFloat != 0
+	case types.UntypedInt:
+		return t&argInt != 0
+	case types.UntypedRune:
+		return t&(argInt|argRune) != 0
+	case types.UntypedString:
+		return t&argString != 0
+	case types.UntypedNil:
+		return t&argPointer != 0 // TODO?
+	case types.Invalid:
+		if *verbose {
+			f.Warnf(arg.Pos(), "printf argument %v has invalid or unknown type", arg)
+		}
+		return true // Probably a type check problem.
+	}
+	return false
+}
+
 // checkPrint checks a call to an unformatted print routine such as Println.
-// The skip argument records how many arguments to ignore; that is,
-// call.Args[skip] is the first argument to be printed.
-func (f *File) checkPrint(call *ast.CallExpr, name string, skip int) {
+// call.Args[firstArg] is the first argument to be printed.
+func (f *File) checkPrint(call *ast.CallExpr, name string, firstArg int) {
 	isLn := strings.HasSuffix(name, "ln")
 	isF := strings.HasPrefix(name, "F")
 	args := call.Args
 	// check for Println(os.Stderr, ...)
-	if skip == 0 && !isF && len(args) > 0 {
+	if firstArg == 0 && !isF && len(args) > 0 {
 		if sel, ok := args[0].(*ast.SelectorExpr); ok {
 			if x, ok := sel.X.(*ast.Ident); ok {
 				if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
@@ -219,13 +371,23 @@ func (f *File) checkPrint(call *ast.CallExpr, name string, skip int) {
 			}
 		}
 	}
-	if len(args) <= skip {
-		if *verbose && !isLn {
-			f.Badf(call.Pos(), "no args in %s call", name)
+	if len(args) <= firstArg {
+		// If we have a call to a method called Error that satisfies the Error interface,
+		// then it's ok. Otherwise it's something like (*T).Error from the testing package
+		// and we need to check it.
+		if name == "Error" && f.isErrorMethodCall(call) {
+			return
+		}
+		// If it's an Error call now, it's probably for printing errors.
+		if !isLn {
+			// Check the signature to be sure: there are niladic functions called "error".
+			if firstArg != 0 || f.numArgsInSignature(call) != firstArg {
+				f.Badf(call.Pos(), "no args in %s call", name)
+			}
 		}
 		return
 	}
-	arg := args[skip]
+	arg := args[firstArg]
 	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
 		if strings.Contains(lit.Value, "%") {
 			f.Badf(call.Pos(), "possible formatting directive in %s call", name)
@@ -242,37 +404,63 @@ func (f *File) checkPrint(call *ast.CallExpr, name string, skip int) {
 	}
 }
 
-// This function never executes, but it serves as a simple test for the program.
-// Test with make test.
-func BadFunctionUsedInTests() {
-	fmt.Println()                      // not an error
-	fmt.Println("%s", "hi")            // ERROR "possible formatting directive in Println call"
-	fmt.Printf("%s", "hi", 3)          // ERROR "wrong number of args in Printf call"
-	fmt.Printf("%s%%%d", "hi", 3)      // correct
-	fmt.Printf("%.*d", 3, 3)           // correct
-	fmt.Printf("%.*d", 3, 3, 3)        // ERROR "wrong number of args in Printf call"
-	printf("now is the time", "buddy") // ERROR "no formatting directive"
-	Printf("now is the time", "buddy") // ERROR "no formatting directive"
-	Printf("hi")                       // ok
-	f := new(File)
-	f.Warn(0, "%s", "hello", 3)  // ERROR "possible formatting directive in Warn call"
-	f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args in Warnf call"
-	f.Warnf(0, "%r", "hello")    // ERROR "unrecognized printf verb"
-	f.Warnf(0, "%#s", "hello")   // ERROR "unrecognized printf flag"
-}
-
-type BadTypeUsedInTests struct {
-	X int "hello" // ERROR "struct field tag"
-}
-
-func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "method Scan[(]x fmt.ScanState, c byte[)] should have signature Scan[(]fmt.ScanState, rune[)] error"
-}
-
-type BadInterfaceUsedInTests interface {
-	ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
+// numArgsInSignature tells how many formal arguments the function type
+// being called has.
+func (f *File) numArgsInSignature(call *ast.CallExpr) int {
+	// Check the type of the function or method declaration
+	typ := f.pkg.types[call.Fun]
+	if typ == nil {
+		return 0
+	}
+	// The type must be a signature, but be sure for safety.
+	sig, ok := typ.(*types.Signature)
+	if !ok {
+		return 0
+	}
+	return len(sig.Params)
 }
 
-// printf is used by the test.
-func printf(format string, args ...interface{}) {
-	panic("don't call - testing only")
+// isErrorMethodCall reports whether the call is of a method with signature
+//	func Error() string
+// where "string" is the universe's string type. We know the method is called "Error".
+func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
+	// Is it a selector expression? Otherwise it's a function call, not a method call.
+	sel, ok := call.Fun.(*ast.SelectorExpr)
+	if !ok {
+		return false
+	}
+	// The package is type-checked, so if there are no arguments, we're done.
+	if len(call.Args) > 0 {
+		return false
+	}
+	// Check the type of the method declaration
+	typ := f.pkg.types[sel]
+	if typ == nil {
+		return false
+	}
+	// The type must be a signature, but be sure for safety.
+	sig, ok := typ.(*types.Signature)
+	if !ok {
+		return false
+	}
+	// There must be a receiver for it to be a method call. Otherwise it is
+	// a function, not something that satisfies the error interface.
+	if sig.Recv == nil {
+		return false
+	}
+	// There must be no arguments. Already verified by type checking, but be thorough.
+	if len(sig.Params) > 0 {
+		return false
+	}
+	// Finally the real questions.
+	// There must be one result.
+	if len(sig.Results) != 1 {
+		return false
+	}
+	// It must have return type "string" from the universe.
+	result := sig.Results[0].Type
+	if types.IsIdentical(result, types.Typ[types.String]) {
+		return true
+	}
+	return false
 }
diff --git a/src/cmd/vet/rangeloop.go b/src/cmd/vet/rangeloop.go
new file mode 100644
index 0000000..ecc5954
--- /dev/null
+++ b/src/cmd/vet/rangeloop.go
@@ -0,0 +1,65 @@
+// 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.
+
+/*
+This file contains the code to check range loop variables bound inside function
+literals that are deferred or launched in new goroutines. We only check
+instances where the defer or go statement is the last statement in the loop
+body, as otherwise we would need whole program analysis.
+
+For example:
+
+	for i, v := range s {
+		go func() {
+			println(i, v) // not what you might expect
+		}()
+	}
+
+See: http://golang.org/doc/go_faq.html#closures_and_goroutines
+*/
+
+package main
+
+import "go/ast"
+
+// checkRangeLoop walks the body of the provided range statement, checking if
+// its index or value variables are used unsafely inside goroutines or deferred
+// function literals.
+func checkRangeLoop(f *File, n *ast.RangeStmt) {
+	if !vet("rangeloops") {
+		return
+	}
+	key, _ := n.Key.(*ast.Ident)
+	val, _ := n.Value.(*ast.Ident)
+	if key == nil && val == nil {
+		return
+	}
+	sl := n.Body.List
+	if len(sl) == 0 {
+		return
+	}
+	var last *ast.CallExpr
+	switch s := sl[len(sl)-1].(type) {
+	case *ast.GoStmt:
+		last = s.Call
+	case *ast.DeferStmt:
+		last = s.Call
+	default:
+		return
+	}
+	lit, ok := last.Fun.(*ast.FuncLit)
+	if !ok {
+		return
+	}
+	ast.Inspect(lit.Body, func(n ast.Node) bool {
+		id, ok := n.(*ast.Ident)
+		if !ok || id.Obj == nil {
+			return true
+		}
+		if key != nil && id.Obj == key.Obj || val != nil && id.Obj == val.Obj {
+			f.Warn(id.Pos(), "range variable", id.Name, "enclosed by function")
+		}
+		return true
+	})
+}
diff --git a/src/cmd/vet/structtag.go b/src/cmd/vet/structtag.go
index ea2a9d8..545e420 100644
--- a/src/cmd/vet/structtag.go
+++ b/src/cmd/vet/structtag.go
@@ -14,6 +14,9 @@ import (
 
 // checkField checks a struct field tag.
 func (f *File) checkCanonicalFieldTag(field *ast.Field) {
+	if !vet("structtags") {
+		return
+	}
 	if field.Tag == nil {
 		return
 	}
diff --git a/src/cmd/vet/taglit.go b/src/cmd/vet/taglit.go
index c3c4f32..0324e37 100644
--- a/src/cmd/vet/taglit.go
+++ b/src/cmd/vet/taglit.go
@@ -7,13 +7,38 @@
 package main
 
 import (
+	"flag"
 	"go/ast"
+	"go/types"
 	"strings"
 )
 
+var compositeWhiteList = flag.Bool("compositewhitelist", true, "use composite white list; for testing only")
+
 // checkUntaggedLiteral checks if a composite literal is an struct literal with
 // untagged fields.
 func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
+	if !vet("composites") {
+		return
+	}
+
+	// Check that the CompositeLit's type is a slice or array (which needs no tag), if possible.
+	typ := f.pkg.types[c]
+	if typ != nil {
+		// If it's a named type, pull out the underlying type.
+		if namedType, ok := typ.(*types.NamedType); ok {
+			typ = namedType.Underlying
+		}
+		switch typ.(type) {
+		case *types.Slice:
+			return
+		case *types.Array:
+			return
+		}
+	}
+
+	// It's a struct, or we can't tell it's not a struct because we don't have types.
+
 	// Check if the CompositeLit contains an untagged field.
 	allKeyValue := true
 	for _, e := range c.Elts {
@@ -42,12 +67,12 @@ func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
 		f.Warnf(c.Pos(), "unresolvable package for %s.%s literal", pkg.Name, s.Sel.Name)
 		return
 	}
-	typ := path + "." + s.Sel.Name
-	if untaggedLiteralWhitelist[typ] {
+	typeName := path + "." + s.Sel.Name
+	if *compositeWhiteList && untaggedLiteralWhitelist[typeName] {
 		return
 	}
 
-	f.Warnf(c.Pos(), "%s struct literal uses untagged fields", typ)
+	f.Warnf(c.Pos(), "%s composite literal uses untagged fields", typ)
 }
 
 // pkgPath returns the import path "image/png" for the package name "png".
diff --git a/src/cmd/vet/test_atomic.go b/src/cmd/vet/test_atomic.go
new file mode 100644
index 0000000..9231e9d
--- /dev/null
+++ b/src/cmd/vet/test_atomic.go
@@ -0,0 +1,43 @@
+// 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 vet_test
+
+// This file contains tests for the atomic checker.
+
+package main
+
+import (
+	"sync/atomic"
+)
+
+type Counter uint64
+
+func AtomicTests() {
+	x := uint64(1)
+	x = atomic.AddUint64(&x, 1)        // ERROR "direct assignment to atomic value"
+	_, x = 10, atomic.AddUint64(&x, 1) // ERROR "direct assignment to atomic value"
+	x, _ = atomic.AddUint64(&x, 1), 10 // ERROR "direct assignment to atomic value"
+
+	y := &x
+	*y = atomic.AddUint64(y, 1) // ERROR "direct assignment to atomic value"
+
+	var su struct{ Counter uint64 }
+	su.Counter = atomic.AddUint64(&su.Counter, 1) // ERROR "direct assignment to atomic value"
+	z1 := atomic.AddUint64(&su.Counter, 1)
+	_ = z1 // Avoid err "z declared and not used"
+
+	var sp struct{ Counter *uint64 }
+	*sp.Counter = atomic.AddUint64(sp.Counter, 1) // ERROR "direct assignment to atomic value"
+	z2 := atomic.AddUint64(sp.Counter, 1)
+	_ = z2 // Avoid err "z declared and not used"
+
+	au := []uint64{10, 20}
+	au[0] = atomic.AddUint64(&au[0], 1) // ERROR "direct assignment to atomic value"
+	au[1] = atomic.AddUint64(&au[0], 1)
+
+	ap := []*uint64{&au[0], &au[1]}
+	*ap[0] = atomic.AddUint64(ap[0], 1) // ERROR "direct assignment to atomic value"
+	*ap[1] = atomic.AddUint64(ap[0], 1)
+}
diff --git a/src/cmd/vet/test_buildtag.go b/src/cmd/vet/test_buildtag.go
new file mode 100644
index 0000000..d7174ad
--- /dev/null
+++ b/src/cmd/vet/test_buildtag.go
@@ -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.
+
+// This file contains tests for the buildtag checker.
+
+// +build vet_test
+// +builder // ERROR "possible malformed \+build comment"
+// +build !ignore
+
+package main
+
+// +build toolate // ERROR "build comment appears too late in file"
+
+var _ = 3
diff --git a/src/cmd/vet/test_method.go b/src/cmd/vet/test_method.go
new file mode 100644
index 0000000..41de62b
--- /dev/null
+++ b/src/cmd/vet/test_method.go
@@ -0,0 +1,24 @@
+// 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.
+
+// This file contains tests for the canonical method checker.
+
+// +build vet_test
+
+// This file contains the code to check canonical methods.
+
+package main
+
+import (
+	"fmt"
+)
+
+type MethodTest int
+
+func (t *MethodTest) Scan(x fmt.ScanState, c byte) { // ERROR "should have signature Scan"
+}
+
+type MethodTestInterface interface {
+	ReadByte() byte // ERROR "should have signature ReadByte"
+}
diff --git a/src/cmd/vet/test_print.go b/src/cmd/vet/test_print.go
new file mode 100644
index 0000000..8b41e6c
--- /dev/null
+++ b/src/cmd/vet/test_print.go
@@ -0,0 +1,153 @@
+// 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.
+
+// +build vet_test
+
+// This file contains tests for the printf checker.
+
+package main
+
+import (
+	"fmt"
+	"unsafe" // just for test case printing unsafe.Pointer
+)
+
+func UnsafePointerPrintfTest() {
+	var up unsafe.Pointer
+	fmt.Printf("%p, %x %X", up, up, up)
+}
+
+// Error methods that do not satisfy the Error interface and should be checked.
+type errorTest1 int
+
+func (errorTest1) Error(...interface{}) string {
+	return "hi"
+}
+
+type errorTest2 int // Analogous to testing's *T type.
+func (errorTest2) Error(...interface{}) {
+}
+
+type errorTest3 int
+
+func (errorTest3) Error() { // No return value.
+}
+
+type errorTest4 int
+
+func (errorTest4) Error() int { // Different return type.
+	return 3
+}
+
+type errorTest5 int
+
+func (errorTest5) error() { // niladic; don't complain if no args (was bug)
+}
+
+// This function never executes, but it serves as a simple test for the program.
+// Test with make test.
+func PrintfTests() {
+	var b bool
+	var i int
+	var r rune
+	var s string
+	var x float64
+	var p *int
+	// Some good format/argtypes
+	fmt.Printf("")
+	fmt.Printf("%b %b", 3, i)
+	fmt.Printf("%c %c %c %c", 3, i, 'x', r)
+	fmt.Printf("%d %d", 3, i)
+	fmt.Printf("%e %e", 3e9, x)
+	fmt.Printf("%E %E", 3e9, x)
+	fmt.Printf("%f %f", 3e9, x)
+	fmt.Printf("%F %F", 3e9, x)
+	fmt.Printf("%g %g", 3e9, x)
+	fmt.Printf("%G %G", 3e9, x)
+	fmt.Printf("%o %o", 3, i)
+	fmt.Printf("%p %p", p, nil)
+	fmt.Printf("%q %q %q %q", 3, i, 'x', r)
+	fmt.Printf("%s %s", "hi", s)
+	fmt.Printf("%t %t", true, b)
+	fmt.Printf("%T %T", 3, i)
+	fmt.Printf("%U %U", 3, i)
+	fmt.Printf("%v %v", 3, i)
+	fmt.Printf("%x %x %x %x", 3, i, "hi", s)
+	fmt.Printf("%X %X %X %X", 3, i, "hi", s)
+	fmt.Printf("%.*s %d %g", 3, "hi", 23, 2.3)
+	// Some bad format/argTypes
+	fmt.Printf("%b", "hi")                     // ERROR "arg .hi. for printf verb %b of wrong type"
+	fmt.Printf("%c", 2.3)                      // ERROR "arg 2.3 for printf verb %c of wrong type"
+	fmt.Printf("%d", 2.3)                      // ERROR "arg 2.3 for printf verb %d of wrong type"
+	fmt.Printf("%e", "hi")                     // ERROR "arg .hi. for printf verb %e of wrong type"
+	fmt.Printf("%E", true)                     // ERROR "arg true for printf verb %E of wrong type"
+	fmt.Printf("%f", "hi")                     // ERROR "arg .hi. for printf verb %f of wrong type"
+	fmt.Printf("%F", 'x')                      // ERROR "arg 'x' for printf verb %F of wrong type"
+	fmt.Printf("%g", "hi")                     // ERROR "arg .hi. for printf verb %g of wrong type"
+	fmt.Printf("%G", i)                        // ERROR "arg i for printf verb %G of wrong type"
+	fmt.Printf("%o", x)                        // ERROR "arg x for printf verb %o of wrong type"
+	fmt.Printf("%p", 23)                       // ERROR "arg 23 for printf verb %p of wrong type"
+	fmt.Printf("%q", x)                        // ERROR "arg x for printf verb %q of wrong type"
+	fmt.Printf("%s", b)                        // ERROR "arg b for printf verb %s of wrong type"
+	fmt.Printf("%t", 23)                       // ERROR "arg 23 for printf verb %t of wrong type"
+	fmt.Printf("%U", x)                        // ERROR "arg x for printf verb %U of wrong type"
+	fmt.Printf("%x", nil)                      // ERROR "arg nil for printf verb %x of wrong type"
+	fmt.Printf("%X", 2.3)                      // ERROR "arg 2.3 for printf verb %X of wrong type"
+	fmt.Printf("%.*s %d %g", 3, "hi", 23, 'x') // ERROR "arg 'x' for printf verb %g of wrong type"
+	// TODO
+	fmt.Println()                      // not an error
+	fmt.Println("%s", "hi")            // ERROR "possible formatting directive in Println call"
+	fmt.Printf("%s", "hi", 3)          // ERROR "wrong number of args for format in Printf call"
+	fmt.Printf("%"+("s"), "hi", 3)     // ERROR "wrong number of args for format in Printf call"
+	fmt.Printf("%s%%%d", "hi", 3)      // correct
+	fmt.Printf("%08s", "woo")          // correct
+	fmt.Printf("% 8s", "woo")          // correct
+	fmt.Printf("%.*d", 3, 3)           // correct
+	fmt.Printf("%.*d", 3, 3, 3)        // ERROR "wrong number of args for format in Printf call"
+	fmt.Printf("%.*d", "hi", 3)        // ERROR "arg .hi. for \* in printf format not of type int"
+	fmt.Printf("%.*d", i, 3)           // correct
+	fmt.Printf("%.*d", s, 3)           // ERROR "arg s for \* in printf format not of type int"
+	fmt.Printf("%q %q", multi()...)    // ok
+	fmt.Printf("%#q", `blah`)          // ok
+	printf("now is the time", "buddy") // ERROR "no formatting directive"
+	Printf("now is the time", "buddy") // ERROR "no formatting directive"
+	Printf("hi")                       // ok
+	const format = "%s %s\n"
+	Printf(format, "hi", "there")
+	Printf(format, "hi") // ERROR "wrong number of args for format in Printf call"
+	f := new(File)
+	f.Warn(0, "%s", "hello", 3)  // ERROR "possible formatting directive in Warn call"
+	f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args for format in Warnf call"
+	f.Warnf(0, "%r", "hello")    // ERROR "unrecognized printf verb"
+	f.Warnf(0, "%#s", "hello")   // ERROR "unrecognized printf flag"
+	// Something that satisfies the error interface.
+	var e error
+	fmt.Println(e.Error()) // ok
+	// Something that looks like an error interface but isn't, such as the (*T).Error method
+	// in the testing package.
+	var et1 errorTest1
+	fmt.Println(et1.Error())        // ERROR "no args in Error call"
+	fmt.Println(et1.Error("hi"))    // ok
+	fmt.Println(et1.Error("%d", 3)) // ERROR "possible formatting directive in Error call"
+	var et2 errorTest2
+	et2.Error()        // ERROR "no args in Error call"
+	et2.Error("hi")    // ok, not an error method.
+	et2.Error("%d", 3) // ERROR "possible formatting directive in Error call"
+	var et3 errorTest3
+	et3.Error() // ok, not an error method.
+	var et4 errorTest4
+	et4.Error() // ok, not an error method.
+	var et5 errorTest5
+	et5.error() // ok, not an error method.
+}
+
+// printf is used by the test.
+func printf(format string, args ...interface{}) {
+	panic("don't call - testing only")
+}
+
+// multi is used by the test.
+func multi() []interface{} {
+	panic("don't call - testing only")
+}
diff --git a/src/cmd/vet/test_rangeloop.go b/src/cmd/vet/test_rangeloop.go
new file mode 100644
index 0000000..941fd72
--- /dev/null
+++ b/src/cmd/vet/test_rangeloop.go
@@ -0,0 +1,61 @@
+// 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.
+
+// This file contains tests for the rangeloop checker.
+
+// +build vet_test
+
+package main
+
+func RangeLoopTests() {
+	var s []int
+	for i, v := range s {
+		go func() {
+			println(i) // ERROR "range variable i enclosed by function"
+			println(v) // ERROR "range variable v enclosed by function"
+		}()
+	}
+	for i, v := range s {
+		defer func() {
+			println(i) // ERROR "range variable i enclosed by function"
+			println(v) // ERROR "range variable v enclosed by function"
+		}()
+	}
+	for i := range s {
+		go func() {
+			println(i) // ERROR "range variable i enclosed by function"
+		}()
+	}
+	for _, v := range s {
+		go func() {
+			println(v) // ERROR "range variable v enclosed by function"
+		}()
+	}
+	for i, v := range s {
+		go func() {
+			println(i, v)
+		}()
+		println("unfortunately, we don't catch the error above because of this statement")
+	}
+	for i, v := range s {
+		go func(i, v int) {
+			println(i, v)
+		}(i, v)
+	}
+	for i, v := range s {
+		i, v := i, v
+		go func() {
+			println(i, v)
+		}()
+	}
+	// If the key of the range statement is not an identifier
+	// the code should not panic (it used to).
+	var x [2]int
+	var f int
+	for x[0], f = range s {
+		go func() {
+			_ = f // ERROR "range variable f enclosed by function"
+		}()
+	}
+}
diff --git a/src/cmd/vet/test_structtag.go b/src/cmd/vet/test_structtag.go
new file mode 100644
index 0000000..08cf737
--- /dev/null
+++ b/src/cmd/vet/test_structtag.go
@@ -0,0 +1,15 @@
+// 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.
+
+// This file contains tests for the structtag checker.
+
+// +build vet_test
+
+// This file contains the test for canonical struct tags.
+
+package main
+
+type StructTagTest struct {
+	X int "hello" // ERROR "not compatible with reflect.StructTag.Get"
+}
diff --git a/src/cmd/vet/test_taglit.go b/src/cmd/vet/test_taglit.go
new file mode 100644
index 0000000..0d83b18
--- /dev/null
+++ b/src/cmd/vet/test_taglit.go
@@ -0,0 +1,31 @@
+// 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.
+
+// This file contains tests for the untagged struct literal checker.
+
+// +build vet_test
+
+// This file contains the test for untagged struct literals.
+
+package main
+
+import (
+	"flag"
+	"go/scanner"
+)
+
+// Testing is awkward because we need to reference things from a separate package
+// to trigger the warnings.
+
+var BadStructLiteralUsedInTests = flag.Flag{ // ERROR "untagged fields"
+	"Name",
+	"Usage",
+	nil, // Value
+	"DefValue",
+}
+
+// Used to test the check for slices and arrays: If that test is disabled and
+// vet is run with --compositewhitelist=false, this line triggers an error.
+// Clumsy but sufficient.
+var scannerErrorListTest = scanner.ErrorList{nil, nil}
diff --git a/src/cmd/yacc/doc.go b/src/cmd/yacc/doc.go
index 4a2c2a3..792c104 100644
--- a/src/cmd/yacc/doc.go
+++ b/src/cmd/yacc/doc.go
@@ -48,4 +48,4 @@ referenced by yacc's generated code.  Setting it to distinct values
 allows multiple grammars to be placed in a single package.
 
 */
-package documentation
+package main
diff --git a/src/cmd/yacc/units.txt b/src/cmd/yacc/units.txt
index ddb2bc2..df8f567 100644
--- a/src/cmd/yacc/units.txt
+++ b/src/cmd/yacc/units.txt
@@ -215,58 +215,58 @@ lumen			cd sr
 lux			cd sr/m²
 
 / MONEY DATE
-/ Thu Sep 10 2009
-
-argentinapeso			1 | 0.2595 $
-australiadollar			1 | 0.8618 $
-boliviaboliviano		1 | 0.1425 $
-brazilreal			1 | 0.5522 $
-britainpound			1 | 1.6651 $
-canadadollar			1 | 0.9277 $
-chilepeso			1 | 0.0018 $
-chinayuan			1 | 0.1464 $
-colombiapeso			1 | 0.0005 $
-czechkoruna			1 | 0.0572 $
-denmarkkrone			1 | 0.1958 $
-dominicanpeso			1 | 0.0278 $
-egyptpound			1 | 0.181 $
-elsalvadorcolon			1 | 0.1143 $
-europeuro			1 | 1.4577 $
-guatemalaquetzal		1 | 0.121 $
-honduraslempira			1 | 0.0529 $
-hongkongdollar			1 | 0.129 $
-hungaryforint			1 | 0.0054 $
-indiarupee			1 | 0.0207 $
-indonesiarupiah			1 | 0.0001 $
-israelshekel			1 | 0.2643 $
-japanyen			1 | 0.0109 $
-kenyashilling			1 | 0.0132 $
-kuwaitdinar			1 | 3.4854 $
-lebanonpound			1 | 0.0007 $
-malaysiaringgit			1 | 0.286 $
-mexicopeso			1 | 0.0748 $
-newzealanddollar		1 | 0.7028 $
-nicaraguacordoba		1 | 0.0487 $
-norwaykrone			1 | 0.1681 $
-pakistanrupee			1 | 0.0121 $
-paraguayguarani			1 | 0.0002 $
-perunewsol			1 | 0.3384 $
-philippinespeso			1 | 0.0207 $
-polandzloty			1 | 0.352 $
-russiaruble			1 | 0.0324 $
-saudiarabiariyal		1 | 0.2666 $
-singaporedollar			1 | 0.7018 $
-slovakkoruna			1 | 0.0484 $
-southafricarand			1 | 0.132 $
-southkoreawon			1 | 0.0008 $
-swedenkrona			1 | 0.1429 $
-switzerlandfranc		1 | 0.9627 $
-taiwandollar			1 | 0.0306 $
-thailandbaht			1 | 0.0294 $
-turkeynewlira			1 | 0.6678 $
-uaedirham			1 | 0.2722 $
-uruguaynewpeso			1 | 0.0451 $
-vietnamdong			1 | 0.0001 $
+/ Wed Aug 29, 2012
+
+argentinapeso			$ 0.2160
+australiadollar			$ 1.0372
+boliviaboliviano		$ 0.1427
+brazilreal			$ 0.4872
+britainpound			$ 1.5843
+canadadollar			$ 1.0117
+chilepeso			$ 1 | 480.6
+chinayuan			$ 0.1574
+colombiapeso			$ 1 | 1834
+czechkoruna			$ 0.0506
+denmarkkrone			$ 0.1681
+dominicanpeso			$ 0.0256
+egyptpound			$ 0.1640
+elsalvadorcolon			$ 1 | 8.75
+europeuro			$ 1.2528
+guatemalaquetzal		$ 0.1290
+honduraslempira			$ 0.0511
+hongkongdollar			$ 0.1289
+hungaryforint			$ 1 | 226.5
+indiarupee			$ 0.0180
+indonesiarupiah			$ 1 | 9540
+israelshekel			$ 0.2479
+japanyen			$ 0.0127
+kenyashilling			$ 0.0119
+kuwaitdinar			$ 3.5456
+lebanonpound			$ 1 | 1505.5
+malaysiaringgit			$ 0.3204
+mexicopeso			$ 0.0754
+newzealanddollar		$ 0.8035
+nicaraguacordoba		$ 0.0421
+norwaykrone			$ 0.1717
+pakistanrupee			$ 0.0106
+paraguayguarani			$ 1 | 4415
+perunewsol			$ 0.3832
+philippinespeso			$ 0.0236
+polandzloty			$ 0.3001
+russiaruble			$ 0.0311
+saudiarabiariyal		$ 1 | 3.75
+singaporedollar			$ 0.7976
+slovakkoruna			1 | 30.126 europeuro
+southafricarand			$ 0.1188
+southkoreawon			$ 1 | 1135
+swedenkrona			$ 0.1502
+switzerlandfranc		$ 1.0431
+taiwandollar			$ 0.0334
+thailandbaht			$ 0.0319
+turkeynewlira			$ 0.5504
+uaedirham			$ 0.2723
+uruguaynewpeso			$ 0.0465
+vietnamdong			$ 1 | 20865
 
 / END MONEY
  
diff --git a/src/cmd/yacc/units.y b/src/cmd/yacc/units.y
index 7258e3e..9c1b0b3 100644
--- a/src/cmd/yacc/units.y
+++ b/src/cmd/yacc/units.y
@@ -11,6 +11,11 @@
 
 %{
 
+// This tag will end up in the generated y.go, so that forgetting
+// 'make clean' does not fail the next build.
+
+// +build ignore
+
 // units.y
 // example of a Go yacc program
 // usage is
@@ -26,11 +31,13 @@
 package main
 
 import (
+	"bufio"
 	"flag"
 	"fmt"
-	"bufio"
-	"os"
 	"math"
+	"runtime"
+	"os"
+	"path/filepath"
 	"strconv"
 	"unicode/utf8"
 )
@@ -74,9 +81,9 @@ var vflag bool
 
 %type	<node>	prog expr expr0 expr1 expr2 expr3 expr4
 
-%token	<vval>	VAL
+%token	<vval>	VÄL // dieresis to test UTF-8
 %token	<vvar>	VAR
-%token	<numb>	SUP
+%token	<numb>	_SUP // tests leading underscore in token name
 %%
 prog:
 	':' VAR expr
@@ -157,7 +164,7 @@ expr3:
 
 expr2:
 	expr1
-|	expr2 SUP
+|	expr2 _SUP
 	{
 		xpn(&$$, &$1, $2)
 	}
@@ -197,7 +204,7 @@ expr0:
 			$$ = $1.node
 		}
 	}
-|	VAL
+|	VÄL
 	{
 		$$ = one
 		$$.vval = $1
@@ -234,13 +241,13 @@ loop:
 		return '/'
 	case '¹', 'ⁱ':
 		yylval.numb = 1
-		return SUP
+		return _SUP
 	case '²', '⁲':
 		yylval.numb = 2
-		return SUP
+		return _SUP
 	case '³', '⁳':
 		yylval.numb = 3
-		return SUP
+		return _SUP
 	}
 	return int(c)
 
@@ -273,7 +280,7 @@ numb:
 		f = 0
 	}
 	yylval.vval = f
-	return VAL
+	return VÄL
 }
 
 func (UnitsLex) Error(s string) {
@@ -287,13 +294,11 @@ func main() {
 
 	flag.Parse()
 
-	if dir := os.Getenv("GOROOT"); dir != "" {
-		file = dir + "/src/cmd/yacc/units.txt"
-	}
+	file = filepath.Join(runtime.GOROOT(), "src/cmd/yacc/units.txt")
 	if flag.NArg() > 0 {
 		file = flag.Arg(0)
 	} else if file == "" {
-		fmt.Fprintf(os.Stderr, "can not find data file units.txt; provide it as argument or set $GOROOT\n")
+		fmt.Fprintf(os.Stderr, "cannot find data file units.txt; provide it as argument or set $GOROOT\n")
 		os.Exit(1)
 	}
 
@@ -308,7 +313,7 @@ func main() {
 
 	/*
 	 * read the 'units' file to
-	 * develope a database
+	 * develop a database
 	 */
 	lineno = 0
 	for {
diff --git a/src/cmd/yacc/yacc.go b/src/cmd/yacc/yacc.go
index e942281..0c18f93 100644
--- a/src/cmd/yacc/yacc.go
+++ b/src/cmd/yacc/yacc.go
@@ -51,6 +51,8 @@ import (
 	"fmt"
 	"os"
 	"strings"
+	"unicode"
+	"unicode/utf8"
 )
 
 // the following are adjustable
@@ -153,6 +155,8 @@ var ftable *bufio.Writer    // y.go file
 var fcode = &bytes.Buffer{} // saved code
 var foutput *bufio.Writer   // y.output file
 
+var fmtImported bool // output file has recorded an import of "fmt"
+
 var oflag string  // -o [y.go]		- y.go file
 var vflag string  // -v [y.output]	- y.output file
 var lflag bool    // -l			- disable line directives
@@ -323,7 +327,6 @@ var resrv = []Resrv{
 var zznewstate = 0
 
 const EOF = -1
-const UTFmax = 0x3f
 
 func main() {
 
@@ -716,8 +719,8 @@ func moreprod() {
 }
 
 //
-// define s to be a terminal if t=0
-// or a nonterminal if t=1
+// define s to be a terminal if nt==0
+// or a nonterminal if nt==1
 //
 func defin(nt int, s string) int {
 	val := 0
@@ -750,56 +753,66 @@ func defin(nt int, s string) int {
 
 	// establish value for token
 	// single character literal
-	if s[0] == ' ' && len(s) == 1+1 {
-		val = int(s[1])
-	} else if s[0] == ' ' && s[1] == '\\' { // escape sequence
-		if len(s) == 2+1 {
-			// single character escape sequence
-			switch s[2] {
-			case '\'':
-				val = '\''
-			case '"':
-				val = '"'
-			case '\\':
-				val = '\\'
-			case 'a':
-				val = '\a'
-			case 'b':
-				val = '\b'
-			case 'n':
-				val = '\n'
-			case 'r':
-				val = '\r'
-			case 't':
-				val = '\t'
-			case 'v':
-				val = '\v'
-			default:
-				errorf("invalid escape %v", s[1:3])
-			}
-		} else if s[2] == 'u' && len(s) == 2+1+4 { // \unnnn sequence
-			val = 0
-			s = s[3:]
-			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
+	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("illegal \\unnnn construction")
+					errorf("invalid escape %s", s)
 				}
-				val = val*16 + c
-				s = s[1:]
-			}
-			if val == 0 {
-				errorf("'\\u0000' is illegal")
+			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)
 			}
-		} else {
-			errorf("unknown escape")
+		}
+		if val == 0 {
+			errorf("token value 0 is illegal")
 		}
 	} else {
 		val = extval
@@ -985,7 +998,7 @@ func gettok() int {
 
 func getword(c rune) {
 	tokname = ""
-	for isword(c) || isdigit(c) || c == '_' || c == '.' || c == '$' {
+	for isword(c) || isdigit(c) || c == '.' || c == '$' {
 		tokname += string(c)
 		c = getrune(finput)
 	}
@@ -1073,6 +1086,7 @@ out:
 
 //
 // saves code between %{ and %}
+// adds an import for __fmt__ the first time
 //
 func cpycode() {
 	lno := lineno
@@ -1085,15 +1099,18 @@ func cpycode() {
 	if !lflag {
 		fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
 	}
+	// accumulate until %}
+	code := make([]rune, 0, 1024)
 	for c != EOF {
 		if c == '%' {
 			c = getrune(finput)
 			if c == '}' {
+				emitcode(code, lno+1)
 				return
 			}
-			ftable.WriteRune('%')
+			code = append(code, '%')
 		}
-		ftable.WriteRune(c)
+		code = append(code, c)
 		if c == '\n' {
 			lineno++
 		}
@@ -1104,6 +1121,107 @@ func cpycode() {
 }
 
 //
+// emits code saved up from between %{ and %}
+// called by cpycode
+// adds an import for __yyfmt__ after the package clause
+//
+func emitcode(code []rune, lineno int) {
+	for i, line := range lines(code) {
+		writecode(line)
+		if !fmtImported && isPackageClause(line) {
+			fmt.Fprintln(ftable, `import __yyfmt__ "fmt"`)
+			fmt.Fprintf(ftable, "//line %v:%v\n\t\t", infile, lineno+i)
+			fmtImported = true
+		}
+	}
+}
+
+//
+// does this line look like a package clause?  not perfect: might be confused by early comments.
+//
+func isPackageClause(line []rune) bool {
+	line = skipspace(line)
+
+	// must be big enough.
+	if len(line) < len("package X\n") {
+		return false
+	}
+
+	// must start with "package"
+	for i, r := range []rune("package") {
+		if line[i] != r {
+			return false
+		}
+	}
+	line = skipspace(line[len("package"):])
+
+	// must have another identifier.
+	if len(line) == 0 || (!unicode.IsLetter(line[0]) && line[0] != '_') {
+		return false
+	}
+	for len(line) > 0 {
+		if !unicode.IsLetter(line[0]) && !unicode.IsDigit(line[0]) && line[0] != '_' {
+			break
+		}
+		line = line[1:]
+	}
+	line = skipspace(line)
+
+	// eol, newline, or comment must follow
+	if len(line) == 0 {
+		return true
+	}
+	if line[0] == '\r' || line[0] == '\n' {
+		return true
+	}
+	if len(line) >= 2 {
+		return line[0] == '/' && (line[1] == '/' || line[1] == '*')
+	}
+	return false
+}
+
+//
+// skip initial spaces
+//
+func skipspace(line []rune) []rune {
+	for len(line) > 0 {
+		if line[0] != ' ' && line[0] != '\t' {
+			break
+		}
+		line = line[1:]
+	}
+	return line
+}
+
+//
+// break code into lines
+//
+func lines(code []rune) [][]rune {
+	l := make([][]rune, 0, 100)
+	for len(code) > 0 {
+		// one line per loop
+		var i int
+		for i = range code {
+			if code[i] == '\n' {
+				break
+			}
+		}
+		l = append(l, code[:i+1])
+		code = code[i+1:]
+	}
+	return l
+}
+
+//
+// writes code to ftable
+//
+func writecode(code []rune) {
+	for _, r := range code {
+		ftable.WriteRune(r)
+	}
+}
+
+//
 // skip over comments
 // skipcom is called after reading a '/'
 //
@@ -1230,7 +1348,7 @@ loop:
 				if j >= max {
 					errorf("Illegal use of $%v", j)
 				}
-			} else if isword(c) || c == '_' || c == '.' {
+			} else if isword(c) || c == '.' {
 				// look for $name
 				ungetrune(finput, c)
 				if gettok() != IDENTIFIER {
@@ -2775,7 +2893,7 @@ func others() {
 		j = tokset[i].value
 		if j >= 0 && j < 256 {
 			if temp1[j] != 0 {
-				fmt.Print("yacc bug -- cant have 2 different Ts with same value\n")
+				fmt.Print("yacc bug -- cannot have 2 different Ts with same value\n")
 				fmt.Printf("	%s and %s\n", tokset[i].name, tokset[temp1[j]].name)
 				nerrors++
 			}
@@ -2799,7 +2917,7 @@ func others() {
 		j = tokset[i].value - PRIVATE
 		if j >= 0 && j < 256 {
 			if temp1[j] != 0 {
-				fmt.Print("yacc bug -- cant have 2 different Ts with same value\n")
+				fmt.Print("yacc bug -- cannot have 2 different Ts with same value\n")
 				fmt.Printf("	%s and %s\n", tokset[i].name, tokset[temp1[j]].name)
 				nerrors++
 			}
@@ -2982,7 +3100,7 @@ var peekrune rune
 func isdigit(c rune) bool { return c >= '0' && c <= '9' }
 
 func isword(c rune) bool {
-	return c >= 0xa0 || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+	return c >= 0xa0 || c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
 }
 
 func mktemp(t string) string { return t }
@@ -3110,12 +3228,13 @@ type $$Lexer interface {
 const $$Flag = -1000
 
 func $$Tokname(c int) string {
-	if c > 0 && c <= len($$Toknames) {
-		if $$Toknames[c-1] != "" {
-			return $$Toknames[c-1]
+	// 4 is TOKSTART above
+	if c >= 4 && c-4 < len($$Toknames) {
+		if $$Toknames[c-4] != "" {
+			return $$Toknames[c-4]
 		}
 	}
-	return fmt.Sprintf("tok-%v", c)
+	return __yyfmt__.Sprintf("tok-%v", c)
 }
 
 func $$Statname(s int) string {
@@ -3124,7 +3243,7 @@ func $$Statname(s int) string {
 			return $$Statenames[s]
 		}
 	}
-	return fmt.Sprintf("state-%v", s)
+	return __yyfmt__.Sprintf("state-%v", s)
 }
 
 func $$lex1(lex $$Lexer, lval *$$SymType) int {
@@ -3157,7 +3276,7 @@ out:
 		c = $$Tok2[1] /* unknown char */
 	}
 	if $$Debug >= 3 {
-		fmt.Printf("lex %U %s\n", uint(char), $$Tokname(c))
+		__yyfmt__.Printf("lex %U %s\n", uint(char), $$Tokname(c))
 	}
 	return c
 }
@@ -3184,7 +3303,7 @@ ret1:
 $$stack:
 	/* put a state and value onto the stack */
 	if $$Debug >= 4 {
-		fmt.Printf("char %v in %v\n", $$Tokname($$char), $$Statname($$state))
+		__yyfmt__.Printf("char %v in %v\n", $$Tokname($$char), $$Statname($$state))
 	}
 
 	$$p++
@@ -3253,8 +3372,8 @@ $$default:
 			$$lex.Error("syntax error")
 			Nerrs++
 			if $$Debug >= 1 {
-				fmt.Printf("%s", $$Statname($$state))
-				fmt.Printf("saw %s\n", $$Tokname($$char))
+				__yyfmt__.Printf("%s", $$Statname($$state))
+				__yyfmt__.Printf("saw %s\n", $$Tokname($$char))
 			}
 			fallthrough
 
@@ -3273,7 +3392,7 @@ $$default:
 
 				/* the current p has no shift on "error", pop stack */
 				if $$Debug >= 2 {
-					fmt.Printf("error recovery pops state %d\n", $$S[$$p].yys)
+					__yyfmt__.Printf("error recovery pops state %d\n", $$S[$$p].yys)
 				}
 				$$p--
 			}
@@ -3282,7 +3401,7 @@ $$default:
 
 		case 3: /* no shift yet; clobber input char */
 			if $$Debug >= 2 {
-				fmt.Printf("error recovery discards %s\n", $$Tokname($$char))
+				__yyfmt__.Printf("error recovery discards %s\n", $$Tokname($$char))
 			}
 			if $$char == $$EofCode {
 				goto ret1
@@ -3294,7 +3413,7 @@ $$default:
 
 	/* reduction by production $$n */
 	if $$Debug >= 2 {
-		fmt.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state))
+		__yyfmt__.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state))
 	}
 
 	$$nt := $$n
diff --git a/src/lib9/argv0.c b/src/lib9/argv0.c
deleted file mode 100644
index 6239851..0000000
--- a/src/lib9/argv0.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-Plan 9 from User Space src/lib9/argv0.c
-http://code.swtch.com/plan9port/src/tip/src/lib9/argv0.c
-
-Copyright 2001-2007 Russ Cox.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-#include <u.h>
-#include <libc.h>
-
-char *argv0;
-
-/*
- * Mac OS can't deal with files that only declare data.
- * ARGBEGIN mentions this function so that this file gets pulled in.
- */
-void __fixargv0(void) { }
diff --git a/src/lib9/flag.c b/src/lib9/flag.c
new file mode 100644
index 0000000..7c79c1a
--- /dev/null
+++ b/src/lib9/flag.c
@@ -0,0 +1,307 @@
+// 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 <u.h>
+#include <libc.h>
+
+// Flag hash.
+typedef struct Flag Flag;
+
+struct Flag
+{
+	char *name;
+	int namelen;
+	char *desc;
+	int iscount;
+	void (*set)(char*, void*);
+	void (*set2)(char*, char*, void*);
+	void *arg;
+	Flag *next;
+	Flag *allnext;
+};
+
+static Flag *curflag;
+
+static Flag *fhash[512];
+static Flag *first, *last;
+
+char *argv0;
+
+/*
+ * Mac OS can't deal with files that only declare data.
+ * ARGBEGIN mentions this function so that this file gets pulled in.
+ */
+void __fixargv0(void) { }
+
+// FNV-1 hash. http://isthe.com/chongo/tech/comp/fnv/
+static uint32
+fnv(char *p, int n)
+{
+	uint32 h;
+	
+	h = 2166136261U;
+	while(n-- > 0)
+		h = (h*16777619) ^ (uchar)*p++;
+	return h;
+}
+
+static Flag*
+lookflag(char *name, int namelen, int creat)
+{
+	uint32 h;
+	Flag *f;
+
+	h = fnv(name, namelen) & (nelem(fhash)-1);
+	for(f=fhash[h]; f; f=f->next) {
+		if(f->namelen == namelen && memcmp(f->name, name, namelen) == 0) {
+			if(creat)
+				sysfatal("multiple definitions of flag -%s", name);
+			return f;
+		}
+	}
+	
+	if(!creat)
+		return nil;
+
+	f = malloc(sizeof *f);
+	if(f == nil)
+		sysfatal("out of memory");
+	memset(f, 0, sizeof *f);
+	f->name = name;
+	f->namelen = namelen;
+	f->next = fhash[h];
+	if(first == nil)
+		first = f;
+	else
+		last->allnext = f;
+	last = f;
+	fhash[h] = f;
+	return f;
+}
+
+static void
+count(char *arg, void *p)
+{
+	int *ip;
+	
+	ip = p;
+	if(arg != nil)
+		*ip = atoi(arg);
+	else
+		(*ip)++;
+}
+
+void
+flagcount(char *name, char *desc, int *p)
+{
+	Flag *f;
+	
+	f = lookflag(name, strlen(name), 1);
+	f->desc = desc;
+	f->iscount = 1;
+	f->set = count;
+	f->arg = p;
+}
+
+static void
+atollwhex(char *s, void *p)
+{
+	char *t;
+
+	*(int64*)p = strtoll(s, &t, 0);
+	if(*s == '\0' || *t != '\0')
+		sysfatal("invalid numeric argument -%s=%s", curflag->name, s);
+}
+
+void
+flagint64(char *name, char *desc, int64 *p)
+{
+	Flag *f;
+	
+	f = lookflag(name, strlen(name), 1);
+	f->desc = desc;
+	f->set = atollwhex;
+	f->arg = p;
+}
+
+static void
+atolwhex(char *s, void *p)
+{
+	char *t;
+
+	*(int32*)p = strtol(s, &t, 0);
+	if(*s == '\0' || *t != '\0')
+		sysfatal("invalid numeric argument -%s=%s", curflag->name, s);
+}
+
+void
+flagint32(char *name, char *desc, int32 *p)
+{
+	Flag *f;
+	
+	f = lookflag(name, strlen(name), 1);
+	f->desc = desc;
+	f->set = atolwhex;
+	f->arg = p;
+}
+
+static void
+string(char *s, void *p)
+{
+	*(char**)p = s;
+}
+
+void
+flagstr(char *name, char *desc, char **p)
+{
+
+	Flag *f;
+	
+	f = lookflag(name, strlen(name), 1);
+	f->desc = desc;
+	f->set = string;
+	f->arg = p;
+}	
+
+static void
+fn0(char *s, void *p)
+{
+	USED(s);
+	((void(*)(void))p)();
+}
+
+void
+flagfn0(char *name, char *desc, void (*fn)(void))
+{
+	Flag *f;
+	
+	f = lookflag(name, strlen(name), 1);
+	f->desc = desc;
+	f->set = fn0;
+	f->arg = fn;
+	f->iscount = 1;
+}
+
+static void
+fn1(char *s, void *p)
+{
+	((void(*)(char*))p)(s);
+}
+
+void
+flagfn1(char *name, char *desc, void (*fn)(char*))
+{
+	Flag *f;
+	
+	f = lookflag(name, strlen(name), 1);
+	f->desc = desc;
+	f->set = fn1;
+	f->arg = fn;
+}
+
+static void
+fn2(char *s, char *t, void *p)
+{
+	((void(*)(char*, char*))p)(s, t);
+}
+
+void
+flagfn2(char *name, char *desc, void (*fn)(char*, char*))
+{
+	Flag *f;
+	
+	f = lookflag(name, strlen(name), 1);
+	f->desc = desc;
+	f->set2 = fn2;
+	f->arg = fn;
+}
+
+void
+flagparse(int *argcp, char ***argvp, void (*usage)(void))
+{
+	int argc;
+	char **argv, *p, *q;
+	char *name;
+	int namelen;
+	Flag *f;
+	
+	argc = *argcp;
+	argv = *argvp;
+
+	argv0 = argv[0];
+	argc--;
+	argv++;
+	
+	while(argc > 0) {
+		p = *argv;
+		// stop before non-flag or -
+		if(*p != '-' || p[1] == '\0')
+			break;
+		argc--;
+		argv++;
+		// stop after --
+		if(p[1] == '-' && p[2] == '\0') {
+			break;
+		}
+		
+		// turn --foo into -foo
+		if(p[1] == '-' && p[2] != '-')
+			p++;
+		
+		// allow -flag=arg if present
+		name = p+1;
+		q = strchr(name, '=');
+		if(q != nil)
+			namelen = q++ - name;
+		else
+			namelen = strlen(name);
+		f = lookflag(name, namelen, 0);
+		if(f == nil) {
+			if(strcmp(p, "-h") == 0 || strcmp(p, "-help") == 0 || strcmp(p, "-?") == 0)
+				usage();
+			sysfatal("unknown flag %s", p);
+		}
+		curflag = f;
+
+		// otherwise consume next argument if non-boolean
+		if(!f->iscount && q == nil) {
+			if(argc-- == 0)
+				sysfatal("missing argument to flag %s", p);
+			q = *argv++;
+		}
+		
+		// and another if we need two
+		if(f->set2 != nil) {
+			if(argc-- == 0)
+				sysfatal("missing second argument to flag %s", p);
+			f->set2(q, *argv++, f->arg);
+			continue;
+		}
+
+		f->set(q, f->arg);			
+	}
+	
+	*argcp = argc;
+	*argvp = argv;		
+}
+
+void
+flagprint(int fd)
+{
+	Flag *f;
+	char *p, *q;
+	
+	for(f=first; f; f=f->allnext) {
+		p = f->desc;
+		if(p == nil || *p == '\0') // undocumented flag
+			continue;
+		q = strstr(p, ": ");
+		if(q)
+			fprint(fd, "  -%s %.*s\n    \t%s\n", f->name, utfnlen(p, q-p), p, q+2);
+		else if(f->namelen > 1)
+			fprint(fd, "  -%s\n    \t%s\n", f->name, p);
+		else
+			fprint(fd, "  -%s\t%s\n", f->name, p);
+	}
+}
diff --git a/src/lib9/fmt/test.c b/src/lib9/fmt/test.c
index 1710c5e..d82ff78 100644
--- a/src/lib9/fmt/test.c
+++ b/src/lib9/fmt/test.c
@@ -1,3 +1,5 @@
+// +build ignore
+
 /*
  * The authors of this software are Rob Pike and Ken Thompson,
  * with contributions from Mike Burrows and Sean Dorward.
diff --git a/src/lib9/getuser.c b/src/lib9/getuser.c
deleted file mode 100644
index d611f44..0000000
--- a/src/lib9/getuser.c
+++ /dev/null
@@ -1,43 +0,0 @@
-// +build !windows
-
-/*
-Plan 9 from User Space src/lib9/getuser.c
-http://code.swtch.com/plan9port/src/tip/src/lib9/getuser.c
-
-Copyright 2001-2007 Russ Cox.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-#include <u.h>
-#include <pwd.h>
-#include <libc.h>
-
-char*
-getuser(void)
-{
-	static char user[64];
-	struct passwd *pw;
-
-	pw = getpwuid(getuid());
-	if(pw == nil)
-		return "none";
-	strecpy(user, user+sizeof user, pw->pw_name);
-	return user;
-}
diff --git a/src/lib9/getwd.c b/src/lib9/getwd.c
index 3c8cafb..566d3f6 100644
--- a/src/lib9/getwd.c
+++ b/src/lib9/getwd.c
@@ -26,10 +26,9 @@ THE SOFTWARE.
 #include <u.h>
 #include <errno.h>
 #include <sys/stat.h>
+#define NOPLAN9DEFINES
 #include <libc.h>
 
-#undef getwd
-
 char*
 p9getwd(char *s, int ns)
 {
diff --git a/src/lib9/goos.c b/src/lib9/goos.c
index f3ee111..3b00271 100644
--- a/src/lib9/goos.c
+++ b/src/lib9/goos.c
@@ -39,3 +39,15 @@ getgoversion(void)
 {
 	return GOVERSION;
 }
+
+char*
+getgoarm(void)
+{
+	return defgetenv("GOARM", GOARM);
+}
+
+char*
+getgo386(void)
+{
+	return defgetenv("GO386", GO386);
+}
diff --git a/src/lib9/main.c b/src/lib9/main.c
index 45f86c7..816494a 100644
--- a/src/lib9/main.c
+++ b/src/lib9/main.c
@@ -27,11 +27,31 @@ THE SOFTWARE.
 #define NOPLAN9DEFINES
 #include <libc.h>
 
+#ifdef WIN32
+#include <windows.h>
+
+static void
+crashhandler(int sig)
+{
+	USED(sig);
+	fprint(2, "%s: internal fatal error.\n", argv0);
+	exit(1);
+}
+#endif
+
 extern void p9main(int, char**);
 
 int
 main(int argc, char **argv)
 {
+#ifdef WIN32
+	signal(SIGSEGV, crashhandler);
+	signal(SIGBUS, crashhandler);
+	// don't display the crash dialog
+	DWORD mode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
+	SetErrorMode(mode | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+	argv0 = argv[0];
+#endif
 	p9main(argc, argv);
 	exits("main");
 	return 99;
diff --git a/src/lib9/utf/Makefile b/src/lib9/utf/Makefile
index bbb2da6..5c9cdf0 100644
--- a/src/lib9/utf/Makefile
+++ b/src/lib9/utf/Makefile
@@ -15,13 +15,13 @@ UnicodeData-%.txt:
 mkrunetype: mkrunetype.c
 	cc -I../../../include -o mkrunetype -L$(GOROOT)/pkg/obj/$(GOOS)_$(GOARCH)/ mkrunetype.c -l9
 
-runetypebody-%.c: mkrunetype UnicodeData-%.txt
+runetypebody-%.h: mkrunetype UnicodeData-%.txt
 	mkrunetype -p UnicodeData-$*.txt >_$@
 	mv _$@ $@
 
 CLEANFILES+=UnicodeData.txt
 
-UNICODE_VERSION=6.0.0
+UNICODE_VERSION=6.2.0
 
 test: mkrunetype UnicodeData-$(UNICODE_VERSION).txt
 	mkrunetype -c UnicodeData-$(UNICODE_VERSION).txt
diff --git a/src/lib9/utf/rune.c b/src/lib9/utf/rune.c
index cf98bab..818771c 100644
--- a/src/lib9/utf/rune.c
+++ b/src/lib9/utf/rune.c
@@ -36,12 +36,14 @@ enum
 	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 */
+	Rune4	= (1<<(Bit4+3*Bitx))-1,		/* 0001 1111 1111 1111 1111 1111 */
 
 	Maskx	= (1<<Bitx)-1,			/* 0011 1111 */
 	Testx	= Maskx ^ 0xFF,			/* 1100 0000 */
 
+	SurrogateMin	= 0xD800,
+	SurrogateMax	= 0xDFFF,
+
 	Bad	= Runeerror,
 };
 
@@ -122,6 +124,8 @@ charntorune(Rune *rune, const char *str, int length)
 		l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
 		if(l <= Rune2)
 			goto bad;
+		if (SurrogateMin <= l && l <= SurrogateMax)
+			goto bad;
 		*rune = l;
 		return 3;
 	}
@@ -138,7 +142,7 @@ charntorune(Rune *rune, const char *str, int length)
 		goto bad;
 	if (c < T5) {
 		l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
-		if (l <= Rune3)
+		if (l <= Rune3 || l > Runemax)
 			goto bad;
 		*rune = l;
 		return 4;
@@ -208,6 +212,8 @@ chartorune(Rune *rune, const char *str)
 		l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
 		if(l <= Rune2)
 			goto bad;
+		if (SurrogateMin <= l && l <= SurrogateMax)
+			goto bad;
 		*rune = l;
 		return 3;
 	}
@@ -221,7 +227,7 @@ chartorune(Rune *rune, const char *str)
 		goto bad;
 	if (c < T5) {
 		l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
-		if (l <= Rune3)
+		if (l <= Rune3 || l > Runemax)
 			goto bad;
 		*rune = l;
 		return 4;
@@ -241,7 +247,8 @@ bad:
 }
 
 int
-isvalidcharntorune(const char* str, int length, Rune* rune, int* consumed) {
+isvalidcharntorune(const char* str, int length, Rune* rune, int* consumed)
+{
 	*consumed = charntorune(rune, str, length);
 	return *rune != Runeerror || *consumed == 3;
 }
@@ -273,13 +280,15 @@ runetochar(char *str, const Rune *rune)
 	}
 
 	/*
-	 * If the Rune is out of range, convert it to the error rune.
+	 * 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
diff --git a/src/lib9/utf/runetype.c b/src/lib9/utf/runetype.c
index 51729fb..b363496 100644
--- a/src/lib9/utf/runetype.c
+++ b/src/lib9/utf/runetype.c
@@ -35,4 +35,4 @@ rbsearch(Rune c, Rune *t, int n, int ne)
 	return 0;
 }
 
-#include "runetypebody-6.0.0.h"
+#include "runetypebody-6.2.0.h"
diff --git a/src/lib9/utf/runetypebody-6.0.0.h b/src/lib9/utf/runetypebody-6.0.0.h
deleted file mode 100644
index 47c0faf..0000000
--- a/src/lib9/utf/runetypebody-6.0.0.h
+++ /dev/null
@@ -1,1565 +0,0 @@
-/* generated automatically by mkrunetype.c from UnicodeData-6.0.0.txt */
-
-static Rune __isspacer[] = {
-	0x0009, 0x000d,
-	0x0020, 0x0020,
-	0x0085, 0x0085,
-	0x00a0, 0x00a0,
-	0x1680, 0x1680,
-	0x180e, 0x180e,
-	0x2000, 0x200a,
-	0x2028, 0x2029,
-	0x202f, 0x202f,
-	0x205f, 0x205f,
-	0x3000, 0x3000,
-	0xfeff, 0xfeff,
-};
-
-int
-isspacerune(Rune c)
-{
-	Rune *p;
-
-	p = rbsearch(c, __isspacer, nelem(__isspacer)/2, 2);
-	if(p && c >= p[0] && c <= p[1])
-		return 1;
-	return 0;
-}
-
-static Rune __isdigitr[] = {
-	0x0030, 0x0039,
-	0x0660, 0x0669,
-	0x06f0, 0x06f9,
-	0x07c0, 0x07c9,
-	0x0966, 0x096f,
-	0x09e6, 0x09ef,
-	0x0a66, 0x0a6f,
-	0x0ae6, 0x0aef,
-	0x0b66, 0x0b6f,
-	0x0be6, 0x0bef,
-	0x0c66, 0x0c6f,
-	0x0ce6, 0x0cef,
-	0x0d66, 0x0d6f,
-	0x0e50, 0x0e59,
-	0x0ed0, 0x0ed9,
-	0x0f20, 0x0f29,
-	0x1040, 0x1049,
-	0x1090, 0x1099,
-	0x17e0, 0x17e9,
-	0x1810, 0x1819,
-	0x1946, 0x194f,
-	0x19d0, 0x19d9,
-	0x1a80, 0x1a89,
-	0x1a90, 0x1a99,
-	0x1b50, 0x1b59,
-	0x1bb0, 0x1bb9,
-	0x1c40, 0x1c49,
-	0x1c50, 0x1c59,
-	0xa620, 0xa629,
-	0xa8d0, 0xa8d9,
-	0xa900, 0xa909,
-	0xa9d0, 0xa9d9,
-	0xaa50, 0xaa59,
-	0xabf0, 0xabf9,
-	0xff10, 0xff19,
-	0x104a0, 0x104a9,
-	0x11066, 0x1106f,
-	0x1d7ce, 0x1d7ff,
-};
-
-int
-isdigitrune(Rune c)
-{
-	Rune *p;
-
-	p = rbsearch(c, __isdigitr, nelem(__isdigitr)/2, 2);
-	if(p && c >= p[0] && c <= p[1])
-		return 1;
-	return 0;
-}
-
-static Rune __isalphar[] = {
-	0x0041, 0x005a,
-	0x0061, 0x007a,
-	0x00c0, 0x00d6,
-	0x00d8, 0x00f6,
-	0x00f8, 0x02c1,
-	0x02c6, 0x02d1,
-	0x02e0, 0x02e4,
-	0x0370, 0x0374,
-	0x0376, 0x0377,
-	0x037a, 0x037d,
-	0x0388, 0x038a,
-	0x038e, 0x03a1,
-	0x03a3, 0x03f5,
-	0x03f7, 0x0481,
-	0x048a, 0x0527,
-	0x0531, 0x0556,
-	0x0561, 0x0587,
-	0x05d0, 0x05ea,
-	0x05f0, 0x05f2,
-	0x0620, 0x064a,
-	0x066e, 0x066f,
-	0x0671, 0x06d3,
-	0x06e5, 0x06e6,
-	0x06ee, 0x06ef,
-	0x06fa, 0x06fc,
-	0x0712, 0x072f,
-	0x074d, 0x07a5,
-	0x07ca, 0x07ea,
-	0x07f4, 0x07f5,
-	0x0800, 0x0815,
-	0x0840, 0x0858,
-	0x0904, 0x0939,
-	0x0958, 0x0961,
-	0x0971, 0x0977,
-	0x0979, 0x097f,
-	0x0985, 0x098c,
-	0x098f, 0x0990,
-	0x0993, 0x09a8,
-	0x09aa, 0x09b0,
-	0x09b6, 0x09b9,
-	0x09dc, 0x09dd,
-	0x09df, 0x09e1,
-	0x09f0, 0x09f1,
-	0x0a05, 0x0a0a,
-	0x0a0f, 0x0a10,
-	0x0a13, 0x0a28,
-	0x0a2a, 0x0a30,
-	0x0a32, 0x0a33,
-	0x0a35, 0x0a36,
-	0x0a38, 0x0a39,
-	0x0a59, 0x0a5c,
-	0x0a72, 0x0a74,
-	0x0a85, 0x0a8d,
-	0x0a8f, 0x0a91,
-	0x0a93, 0x0aa8,
-	0x0aaa, 0x0ab0,
-	0x0ab2, 0x0ab3,
-	0x0ab5, 0x0ab9,
-	0x0ae0, 0x0ae1,
-	0x0b05, 0x0b0c,
-	0x0b0f, 0x0b10,
-	0x0b13, 0x0b28,
-	0x0b2a, 0x0b30,
-	0x0b32, 0x0b33,
-	0x0b35, 0x0b39,
-	0x0b5c, 0x0b5d,
-	0x0b5f, 0x0b61,
-	0x0b85, 0x0b8a,
-	0x0b8e, 0x0b90,
-	0x0b92, 0x0b95,
-	0x0b99, 0x0b9a,
-	0x0b9e, 0x0b9f,
-	0x0ba3, 0x0ba4,
-	0x0ba8, 0x0baa,
-	0x0bae, 0x0bb9,
-	0x0c05, 0x0c0c,
-	0x0c0e, 0x0c10,
-	0x0c12, 0x0c28,
-	0x0c2a, 0x0c33,
-	0x0c35, 0x0c39,
-	0x0c58, 0x0c59,
-	0x0c60, 0x0c61,
-	0x0c85, 0x0c8c,
-	0x0c8e, 0x0c90,
-	0x0c92, 0x0ca8,
-	0x0caa, 0x0cb3,
-	0x0cb5, 0x0cb9,
-	0x0ce0, 0x0ce1,
-	0x0cf1, 0x0cf2,
-	0x0d05, 0x0d0c,
-	0x0d0e, 0x0d10,
-	0x0d12, 0x0d3a,
-	0x0d60, 0x0d61,
-	0x0d7a, 0x0d7f,
-	0x0d85, 0x0d96,
-	0x0d9a, 0x0db1,
-	0x0db3, 0x0dbb,
-	0x0dc0, 0x0dc6,
-	0x0e01, 0x0e30,
-	0x0e32, 0x0e33,
-	0x0e40, 0x0e46,
-	0x0e81, 0x0e82,
-	0x0e87, 0x0e88,
-	0x0e94, 0x0e97,
-	0x0e99, 0x0e9f,
-	0x0ea1, 0x0ea3,
-	0x0eaa, 0x0eab,
-	0x0ead, 0x0eb0,
-	0x0eb2, 0x0eb3,
-	0x0ec0, 0x0ec4,
-	0x0edc, 0x0edd,
-	0x0f40, 0x0f47,
-	0x0f49, 0x0f6c,
-	0x0f88, 0x0f8c,
-	0x1000, 0x102a,
-	0x1050, 0x1055,
-	0x105a, 0x105d,
-	0x1065, 0x1066,
-	0x106e, 0x1070,
-	0x1075, 0x1081,
-	0x10a0, 0x10c5,
-	0x10d0, 0x10fa,
-	0x1100, 0x1248,
-	0x124a, 0x124d,
-	0x1250, 0x1256,
-	0x125a, 0x125d,
-	0x1260, 0x1288,
-	0x128a, 0x128d,
-	0x1290, 0x12b0,
-	0x12b2, 0x12b5,
-	0x12b8, 0x12be,
-	0x12c2, 0x12c5,
-	0x12c8, 0x12d6,
-	0x12d8, 0x1310,
-	0x1312, 0x1315,
-	0x1318, 0x135a,
-	0x1380, 0x138f,
-	0x13a0, 0x13f4,
-	0x1401, 0x166c,
-	0x166f, 0x167f,
-	0x1681, 0x169a,
-	0x16a0, 0x16ea,
-	0x1700, 0x170c,
-	0x170e, 0x1711,
-	0x1720, 0x1731,
-	0x1740, 0x1751,
-	0x1760, 0x176c,
-	0x176e, 0x1770,
-	0x1780, 0x17b3,
-	0x1820, 0x1877,
-	0x1880, 0x18a8,
-	0x18b0, 0x18f5,
-	0x1900, 0x191c,
-	0x1950, 0x196d,
-	0x1970, 0x1974,
-	0x1980, 0x19ab,
-	0x19c1, 0x19c7,
-	0x1a00, 0x1a16,
-	0x1a20, 0x1a54,
-	0x1b05, 0x1b33,
-	0x1b45, 0x1b4b,
-	0x1b83, 0x1ba0,
-	0x1bae, 0x1baf,
-	0x1bc0, 0x1be5,
-	0x1c00, 0x1c23,
-	0x1c4d, 0x1c4f,
-	0x1c5a, 0x1c7d,
-	0x1ce9, 0x1cec,
-	0x1cee, 0x1cf1,
-	0x1d00, 0x1dbf,
-	0x1e00, 0x1f15,
-	0x1f18, 0x1f1d,
-	0x1f20, 0x1f45,
-	0x1f48, 0x1f4d,
-	0x1f50, 0x1f57,
-	0x1f5f, 0x1f7d,
-	0x1f80, 0x1fb4,
-	0x1fb6, 0x1fbc,
-	0x1fc2, 0x1fc4,
-	0x1fc6, 0x1fcc,
-	0x1fd0, 0x1fd3,
-	0x1fd6, 0x1fdb,
-	0x1fe0, 0x1fec,
-	0x1ff2, 0x1ff4,
-	0x1ff6, 0x1ffc,
-	0x2090, 0x209c,
-	0x210a, 0x2113,
-	0x2119, 0x211d,
-	0x212a, 0x212d,
-	0x212f, 0x2139,
-	0x213c, 0x213f,
-	0x2145, 0x2149,
-	0x2183, 0x2184,
-	0x2c00, 0x2c2e,
-	0x2c30, 0x2c5e,
-	0x2c60, 0x2ce4,
-	0x2ceb, 0x2cee,
-	0x2d00, 0x2d25,
-	0x2d30, 0x2d65,
-	0x2d80, 0x2d96,
-	0x2da0, 0x2da6,
-	0x2da8, 0x2dae,
-	0x2db0, 0x2db6,
-	0x2db8, 0x2dbe,
-	0x2dc0, 0x2dc6,
-	0x2dc8, 0x2dce,
-	0x2dd0, 0x2dd6,
-	0x2dd8, 0x2dde,
-	0x3005, 0x3006,
-	0x3031, 0x3035,
-	0x303b, 0x303c,
-	0x3041, 0x3096,
-	0x309d, 0x309f,
-	0x30a1, 0x30fa,
-	0x30fc, 0x30ff,
-	0x3105, 0x312d,
-	0x3131, 0x318e,
-	0x31a0, 0x31ba,
-	0x31f0, 0x31ff,
-	0x3400, 0x4db5,
-	0x4e00, 0x9fcb,
-	0xa000, 0xa48c,
-	0xa4d0, 0xa4fd,
-	0xa500, 0xa60c,
-	0xa610, 0xa61f,
-	0xa62a, 0xa62b,
-	0xa640, 0xa66e,
-	0xa67f, 0xa697,
-	0xa6a0, 0xa6e5,
-	0xa717, 0xa71f,
-	0xa722, 0xa788,
-	0xa78b, 0xa78e,
-	0xa790, 0xa791,
-	0xa7a0, 0xa7a9,
-	0xa7fa, 0xa801,
-	0xa803, 0xa805,
-	0xa807, 0xa80a,
-	0xa80c, 0xa822,
-	0xa840, 0xa873,
-	0xa882, 0xa8b3,
-	0xa8f2, 0xa8f7,
-	0xa90a, 0xa925,
-	0xa930, 0xa946,
-	0xa960, 0xa97c,
-	0xa984, 0xa9b2,
-	0xaa00, 0xaa28,
-	0xaa40, 0xaa42,
-	0xaa44, 0xaa4b,
-	0xaa60, 0xaa76,
-	0xaa80, 0xaaaf,
-	0xaab5, 0xaab6,
-	0xaab9, 0xaabd,
-	0xaadb, 0xaadd,
-	0xab01, 0xab06,
-	0xab09, 0xab0e,
-	0xab11, 0xab16,
-	0xab20, 0xab26,
-	0xab28, 0xab2e,
-	0xabc0, 0xabe2,
-	0xac00, 0xd7a3,
-	0xd7b0, 0xd7c6,
-	0xd7cb, 0xd7fb,
-	0xf900, 0xfa2d,
-	0xfa30, 0xfa6d,
-	0xfa70, 0xfad9,
-	0xfb00, 0xfb06,
-	0xfb13, 0xfb17,
-	0xfb1f, 0xfb28,
-	0xfb2a, 0xfb36,
-	0xfb38, 0xfb3c,
-	0xfb40, 0xfb41,
-	0xfb43, 0xfb44,
-	0xfb46, 0xfbb1,
-	0xfbd3, 0xfd3d,
-	0xfd50, 0xfd8f,
-	0xfd92, 0xfdc7,
-	0xfdf0, 0xfdfb,
-	0xfe70, 0xfe74,
-	0xfe76, 0xfefc,
-	0xff21, 0xff3a,
-	0xff41, 0xff5a,
-	0xff66, 0xffbe,
-	0xffc2, 0xffc7,
-	0xffca, 0xffcf,
-	0xffd2, 0xffd7,
-	0xffda, 0xffdc,
-	0x10000, 0x1000b,
-	0x1000d, 0x10026,
-	0x10028, 0x1003a,
-	0x1003c, 0x1003d,
-	0x1003f, 0x1004d,
-	0x10050, 0x1005d,
-	0x10080, 0x100fa,
-	0x10280, 0x1029c,
-	0x102a0, 0x102d0,
-	0x10300, 0x1031e,
-	0x10330, 0x10340,
-	0x10342, 0x10349,
-	0x10380, 0x1039d,
-	0x103a0, 0x103c3,
-	0x103c8, 0x103cf,
-	0x10400, 0x1049d,
-	0x10800, 0x10805,
-	0x1080a, 0x10835,
-	0x10837, 0x10838,
-	0x1083f, 0x10855,
-	0x10900, 0x10915,
-	0x10920, 0x10939,
-	0x10a10, 0x10a13,
-	0x10a15, 0x10a17,
-	0x10a19, 0x10a33,
-	0x10a60, 0x10a7c,
-	0x10b00, 0x10b35,
-	0x10b40, 0x10b55,
-	0x10b60, 0x10b72,
-	0x10c00, 0x10c48,
-	0x11003, 0x11037,
-	0x11083, 0x110af,
-	0x12000, 0x1236e,
-	0x13000, 0x1342e,
-	0x16800, 0x16a38,
-	0x1b000, 0x1b001,
-	0x1d400, 0x1d454,
-	0x1d456, 0x1d49c,
-	0x1d49e, 0x1d49f,
-	0x1d4a5, 0x1d4a6,
-	0x1d4a9, 0x1d4ac,
-	0x1d4ae, 0x1d4b9,
-	0x1d4bd, 0x1d4c3,
-	0x1d4c5, 0x1d505,
-	0x1d507, 0x1d50a,
-	0x1d50d, 0x1d514,
-	0x1d516, 0x1d51c,
-	0x1d51e, 0x1d539,
-	0x1d53b, 0x1d53e,
-	0x1d540, 0x1d544,
-	0x1d54a, 0x1d550,
-	0x1d552, 0x1d6a5,
-	0x1d6a8, 0x1d6c0,
-	0x1d6c2, 0x1d6da,
-	0x1d6dc, 0x1d6fa,
-	0x1d6fc, 0x1d714,
-	0x1d716, 0x1d734,
-	0x1d736, 0x1d74e,
-	0x1d750, 0x1d76e,
-	0x1d770, 0x1d788,
-	0x1d78a, 0x1d7a8,
-	0x1d7aa, 0x1d7c2,
-	0x1d7c4, 0x1d7cb,
-	0x20000, 0x2a6d6,
-	0x2a700, 0x2b734,
-	0x2b740, 0x2b81d,
-	0x2f800, 0x2fa1d,
-};
-
-static Rune __isalphas[] = {
-	0x00aa,
-	0x00b5,
-	0x00ba,
-	0x02ec,
-	0x02ee,
-	0x0386,
-	0x038c,
-	0x0559,
-	0x06d5,
-	0x06ff,
-	0x0710,
-	0x07b1,
-	0x07fa,
-	0x081a,
-	0x0824,
-	0x0828,
-	0x093d,
-	0x0950,
-	0x09b2,
-	0x09bd,
-	0x09ce,
-	0x0a5e,
-	0x0abd,
-	0x0ad0,
-	0x0b3d,
-	0x0b71,
-	0x0b83,
-	0x0b9c,
-	0x0bd0,
-	0x0c3d,
-	0x0cbd,
-	0x0cde,
-	0x0d3d,
-	0x0d4e,
-	0x0dbd,
-	0x0e84,
-	0x0e8a,
-	0x0e8d,
-	0x0ea5,
-	0x0ea7,
-	0x0ebd,
-	0x0ec6,
-	0x0f00,
-	0x103f,
-	0x1061,
-	0x108e,
-	0x10fc,
-	0x1258,
-	0x12c0,
-	0x17d7,
-	0x17dc,
-	0x18aa,
-	0x1aa7,
-	0x1f59,
-	0x1f5b,
-	0x1f5d,
-	0x1fbe,
-	0x2071,
-	0x207f,
-	0x2102,
-	0x2107,
-	0x2115,
-	0x2124,
-	0x2126,
-	0x2128,
-	0x214e,
-	0x2d6f,
-	0x2e2f,
-	0xa8fb,
-	0xa9cf,
-	0xaa7a,
-	0xaab1,
-	0xaac0,
-	0xaac2,
-	0xfb1d,
-	0xfb3e,
-	0x10808,
-	0x1083c,
-	0x10a00,
-	0x1d4a2,
-	0x1d4bb,
-	0x1d546,
-};
-
-int
-isalpharune(Rune c)
-{
-	Rune *p;
-
-	p = rbsearch(c, __isalphar, nelem(__isalphar)/2, 2);
-	if(p && c >= p[0] && c <= p[1])
-		return 1;
-	p = rbsearch(c, __isalphas, nelem(__isalphas), 1);
-	if(p && c == p[0])
-		return 1;
-	return 0;
-}
-
-static Rune __isupperr[] = {
-	0x0041, 0x005a,
-	0x00c0, 0x00d6,
-	0x00d8, 0x00de,
-	0x0178, 0x0179,
-	0x0181, 0x0182,
-	0x0186, 0x0187,
-	0x0189, 0x018b,
-	0x018e, 0x0191,
-	0x0193, 0x0194,
-	0x0196, 0x0198,
-	0x019c, 0x019d,
-	0x019f, 0x01a0,
-	0x01a6, 0x01a7,
-	0x01ae, 0x01af,
-	0x01b1, 0x01b3,
-	0x01b7, 0x01b8,
-	0x01f6, 0x01f8,
-	0x023a, 0x023b,
-	0x023d, 0x023e,
-	0x0243, 0x0246,
-	0x0388, 0x038a,
-	0x038e, 0x038f,
-	0x0391, 0x03a1,
-	0x03a3, 0x03ab,
-	0x03d2, 0x03d4,
-	0x03f9, 0x03fa,
-	0x03fd, 0x042f,
-	0x04c0, 0x04c1,
-	0x0531, 0x0556,
-	0x10a0, 0x10c5,
-	0x1f08, 0x1f0f,
-	0x1f18, 0x1f1d,
-	0x1f28, 0x1f2f,
-	0x1f38, 0x1f3f,
-	0x1f48, 0x1f4d,
-	0x1f68, 0x1f6f,
-	0x1f88, 0x1f8f,
-	0x1f98, 0x1f9f,
-	0x1fa8, 0x1faf,
-	0x1fb8, 0x1fbc,
-	0x1fc8, 0x1fcc,
-	0x1fd8, 0x1fdb,
-	0x1fe8, 0x1fec,
-	0x1ff8, 0x1ffc,
-	0x210b, 0x210d,
-	0x2110, 0x2112,
-	0x2119, 0x211d,
-	0x212a, 0x212d,
-	0x2130, 0x2133,
-	0x213e, 0x213f,
-	0x2160, 0x216f,
-	0x24b6, 0x24cf,
-	0x2c00, 0x2c2e,
-	0x2c62, 0x2c64,
-	0x2c6d, 0x2c70,
-	0x2c7e, 0x2c80,
-	0xa77d, 0xa77e,
-	0xff21, 0xff3a,
-	0x10400, 0x10427,
-	0x1d400, 0x1d419,
-	0x1d434, 0x1d44d,
-	0x1d468, 0x1d481,
-	0x1d49e, 0x1d49f,
-	0x1d4a5, 0x1d4a6,
-	0x1d4a9, 0x1d4ac,
-	0x1d4ae, 0x1d4b5,
-	0x1d4d0, 0x1d4e9,
-	0x1d504, 0x1d505,
-	0x1d507, 0x1d50a,
-	0x1d50d, 0x1d514,
-	0x1d516, 0x1d51c,
-	0x1d538, 0x1d539,
-	0x1d53b, 0x1d53e,
-	0x1d540, 0x1d544,
-	0x1d54a, 0x1d550,
-	0x1d56c, 0x1d585,
-	0x1d5a0, 0x1d5b9,
-	0x1d5d4, 0x1d5ed,
-	0x1d608, 0x1d621,
-	0x1d63c, 0x1d655,
-	0x1d670, 0x1d689,
-	0x1d6a8, 0x1d6c0,
-	0x1d6e2, 0x1d6fa,
-	0x1d71c, 0x1d734,
-	0x1d756, 0x1d76e,
-	0x1d790, 0x1d7a8,
-};
-
-static Rune __isupperp[] = {
-	0x0100, 0x0136,
-	0x0139, 0x0147,
-	0x014a, 0x0176,
-	0x017b, 0x017d,
-	0x01a2, 0x01a4,
-	0x01cd, 0x01db,
-	0x01de, 0x01ee,
-	0x01fa, 0x0232,
-	0x0248, 0x024e,
-	0x0370, 0x0372,
-	0x03d8, 0x03ee,
-	0x0460, 0x0480,
-	0x048a, 0x04be,
-	0x04c3, 0x04cd,
-	0x04d0, 0x0526,
-	0x1e00, 0x1e94,
-	0x1e9e, 0x1efe,
-	0x1f59, 0x1f5f,
-	0x2124, 0x2128,
-	0x2c67, 0x2c6b,
-	0x2c82, 0x2ce2,
-	0x2ceb, 0x2ced,
-	0xa640, 0xa66c,
-	0xa680, 0xa696,
-	0xa722, 0xa72e,
-	0xa732, 0xa76e,
-	0xa779, 0xa77b,
-	0xa780, 0xa786,
-	0xa78b, 0xa78d,
-	0xa7a0, 0xa7a8,
-};
-
-static Rune __isuppers[] = {
-	0x0184,
-	0x01a9,
-	0x01ac,
-	0x01b5,
-	0x01bc,
-	0x01c4,
-	0x01c7,
-	0x01ca,
-	0x01f1,
-	0x01f4,
-	0x0241,
-	0x0376,
-	0x0386,
-	0x038c,
-	0x03cf,
-	0x03f4,
-	0x03f7,
-	0x2102,
-	0x2107,
-	0x2115,
-	0x2145,
-	0x2183,
-	0x2c60,
-	0x2c72,
-	0x2c75,
-	0xa790,
-	0x1d49c,
-	0x1d4a2,
-	0x1d546,
-	0x1d7ca,
-};
-
-int
-isupperrune(Rune c)
-{
-	Rune *p;
-
-	p = rbsearch(c, __isupperr, nelem(__isupperr)/2, 2);
-	if(p && c >= p[0] && c <= p[1])
-		return 1;
-	p = rbsearch(c, __isupperp, nelem(__isupperp)/2, 2);
-	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
-		return 1;
-	p = rbsearch(c, __isuppers, nelem(__isuppers), 1);
-	if(p && c == p[0])
-		return 1;
-	return 0;
-}
-
-static Rune __islowerr[] = {
-	0x0061, 0x007a,
-	0x00df, 0x00f6,
-	0x00f8, 0x00ff,
-	0x0137, 0x0138,
-	0x0148, 0x0149,
-	0x017e, 0x0180,
-	0x018c, 0x018d,
-	0x0199, 0x019b,
-	0x01aa, 0x01ab,
-	0x01b9, 0x01ba,
-	0x01bd, 0x01bf,
-	0x01dc, 0x01dd,
-	0x01ef, 0x01f0,
-	0x0233, 0x0239,
-	0x023f, 0x0240,
-	0x024f, 0x0293,
-	0x0295, 0x02af,
-	0x037b, 0x037d,
-	0x03ac, 0x03ce,
-	0x03d0, 0x03d1,
-	0x03d5, 0x03d7,
-	0x03ef, 0x03f3,
-	0x03fb, 0x03fc,
-	0x0430, 0x045f,
-	0x04ce, 0x04cf,
-	0x0561, 0x0587,
-	0x1d00, 0x1d2b,
-	0x1d62, 0x1d77,
-	0x1d79, 0x1d9a,
-	0x1e95, 0x1e9d,
-	0x1eff, 0x1f07,
-	0x1f10, 0x1f15,
-	0x1f20, 0x1f27,
-	0x1f30, 0x1f37,
-	0x1f40, 0x1f45,
-	0x1f50, 0x1f57,
-	0x1f60, 0x1f67,
-	0x1f70, 0x1f7d,
-	0x1f80, 0x1f87,
-	0x1f90, 0x1f97,
-	0x1fa0, 0x1fa7,
-	0x1fb0, 0x1fb4,
-	0x1fb6, 0x1fb7,
-	0x1fc2, 0x1fc4,
-	0x1fc6, 0x1fc7,
-	0x1fd0, 0x1fd3,
-	0x1fd6, 0x1fd7,
-	0x1fe0, 0x1fe7,
-	0x1ff2, 0x1ff4,
-	0x1ff6, 0x1ff7,
-	0x210e, 0x210f,
-	0x213c, 0x213d,
-	0x2146, 0x2149,
-	0x2170, 0x217f,
-	0x24d0, 0x24e9,
-	0x2c30, 0x2c5e,
-	0x2c65, 0x2c66,
-	0x2c73, 0x2c74,
-	0x2c76, 0x2c7c,
-	0x2ce3, 0x2ce4,
-	0x2d00, 0x2d25,
-	0xa72f, 0xa731,
-	0xa771, 0xa778,
-	0xfb00, 0xfb06,
-	0xfb13, 0xfb17,
-	0xff41, 0xff5a,
-	0x10428, 0x1044f,
-	0x1d41a, 0x1d433,
-	0x1d44e, 0x1d454,
-	0x1d456, 0x1d467,
-	0x1d482, 0x1d49b,
-	0x1d4b6, 0x1d4b9,
-	0x1d4bd, 0x1d4c3,
-	0x1d4c5, 0x1d4cf,
-	0x1d4ea, 0x1d503,
-	0x1d51e, 0x1d537,
-	0x1d552, 0x1d56b,
-	0x1d586, 0x1d59f,
-	0x1d5ba, 0x1d5d3,
-	0x1d5ee, 0x1d607,
-	0x1d622, 0x1d63b,
-	0x1d656, 0x1d66f,
-	0x1d68a, 0x1d6a5,
-	0x1d6c2, 0x1d6da,
-	0x1d6dc, 0x1d6e1,
-	0x1d6fc, 0x1d714,
-	0x1d716, 0x1d71b,
-	0x1d736, 0x1d74e,
-	0x1d750, 0x1d755,
-	0x1d770, 0x1d788,
-	0x1d78a, 0x1d78f,
-	0x1d7aa, 0x1d7c2,
-	0x1d7c4, 0x1d7c9,
-};
-
-static Rune __islowerp[] = {
-	0x0101, 0x0135,
-	0x013a, 0x0146,
-	0x014b, 0x0177,
-	0x017a, 0x017c,
-	0x0183, 0x0185,
-	0x01a1, 0x01a5,
-	0x01b4, 0x01b6,
-	0x01cc, 0x01da,
-	0x01df, 0x01ed,
-	0x01f3, 0x01f5,
-	0x01f9, 0x0231,
-	0x0247, 0x024d,
-	0x0371, 0x0373,
-	0x03d9, 0x03ed,
-	0x0461, 0x0481,
-	0x048b, 0x04bf,
-	0x04c2, 0x04cc,
-	0x04d1, 0x0527,
-	0x1e01, 0x1e93,
-	0x1e9f, 0x1efd,
-	0x2c68, 0x2c6c,
-	0x2c81, 0x2ce1,
-	0x2cec, 0x2cee,
-	0xa641, 0xa66d,
-	0xa681, 0xa697,
-	0xa723, 0xa72d,
-	0xa733, 0xa76f,
-	0xa77a, 0xa77c,
-	0xa77f, 0xa787,
-	0xa78c, 0xa78e,
-	0xa7a1, 0xa7a9,
-};
-
-static Rune __islowers[] = {
-	0x00aa,
-	0x00b5,
-	0x00ba,
-	0x0188,
-	0x0192,
-	0x0195,
-	0x019e,
-	0x01a8,
-	0x01ad,
-	0x01b0,
-	0x01c6,
-	0x01c9,
-	0x023c,
-	0x0242,
-	0x0377,
-	0x0390,
-	0x03f5,
-	0x03f8,
-	0x1fbe,
-	0x210a,
-	0x2113,
-	0x212f,
-	0x2134,
-	0x2139,
-	0x214e,
-	0x2184,
-	0x2c61,
-	0x2c71,
-	0xa791,
-	0xa7fa,
-	0x1d4bb,
-	0x1d7cb,
-};
-
-int
-islowerrune(Rune c)
-{
-	Rune *p;
-
-	p = rbsearch(c, __islowerr, nelem(__islowerr)/2, 2);
-	if(p && c >= p[0] && c <= p[1])
-		return 1;
-	p = rbsearch(c, __islowerp, nelem(__islowerp)/2, 2);
-	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
-		return 1;
-	p = rbsearch(c, __islowers, nelem(__islowers), 1);
-	if(p && c == p[0])
-		return 1;
-	return 0;
-}
-
-static Rune __istitler[] = {
-	0x0041, 0x005a,
-	0x00c0, 0x00d6,
-	0x00d8, 0x00de,
-	0x0178, 0x0179,
-	0x0181, 0x0182,
-	0x0186, 0x0187,
-	0x0189, 0x018b,
-	0x018e, 0x0191,
-	0x0193, 0x0194,
-	0x0196, 0x0198,
-	0x019c, 0x019d,
-	0x019f, 0x01a0,
-	0x01a6, 0x01a7,
-	0x01ae, 0x01af,
-	0x01b1, 0x01b3,
-	0x01b7, 0x01b8,
-	0x01f6, 0x01f8,
-	0x023a, 0x023b,
-	0x023d, 0x023e,
-	0x0243, 0x0246,
-	0x0388, 0x038a,
-	0x038e, 0x038f,
-	0x0391, 0x03a1,
-	0x03a3, 0x03ab,
-	0x03f9, 0x03fa,
-	0x03fd, 0x042f,
-	0x04c0, 0x04c1,
-	0x0531, 0x0556,
-	0x10a0, 0x10c5,
-	0x1f08, 0x1f0f,
-	0x1f18, 0x1f1d,
-	0x1f28, 0x1f2f,
-	0x1f38, 0x1f3f,
-	0x1f48, 0x1f4d,
-	0x1f68, 0x1f6f,
-	0x1f88, 0x1f8f,
-	0x1f98, 0x1f9f,
-	0x1fa8, 0x1faf,
-	0x1fb8, 0x1fbc,
-	0x1fc8, 0x1fcc,
-	0x1fd8, 0x1fdb,
-	0x1fe8, 0x1fec,
-	0x1ff8, 0x1ffc,
-	0x2160, 0x216f,
-	0x24b6, 0x24cf,
-	0x2c00, 0x2c2e,
-	0x2c62, 0x2c64,
-	0x2c6d, 0x2c70,
-	0x2c7e, 0x2c80,
-	0xa77d, 0xa77e,
-	0xff21, 0xff3a,
-	0x10400, 0x10427,
-};
-
-static Rune __istitlep[] = {
-	0x0100, 0x012e,
-	0x0132, 0x0136,
-	0x0139, 0x0147,
-	0x014a, 0x0176,
-	0x017b, 0x017d,
-	0x01a2, 0x01a4,
-	0x01cb, 0x01db,
-	0x01de, 0x01ee,
-	0x01f2, 0x01f4,
-	0x01fa, 0x0232,
-	0x0248, 0x024e,
-	0x0370, 0x0372,
-	0x03d8, 0x03ee,
-	0x0460, 0x0480,
-	0x048a, 0x04be,
-	0x04c3, 0x04cd,
-	0x04d0, 0x0526,
-	0x1e00, 0x1e94,
-	0x1ea0, 0x1efe,
-	0x1f59, 0x1f5f,
-	0x2c67, 0x2c6b,
-	0x2c82, 0x2ce2,
-	0x2ceb, 0x2ced,
-	0xa640, 0xa66c,
-	0xa680, 0xa696,
-	0xa722, 0xa72e,
-	0xa732, 0xa76e,
-	0xa779, 0xa77b,
-	0xa780, 0xa786,
-	0xa78b, 0xa78d,
-	0xa7a0, 0xa7a8,
-};
-
-static Rune __istitles[] = {
-	0x0184,
-	0x01a9,
-	0x01ac,
-	0x01b5,
-	0x01bc,
-	0x01c5,
-	0x01c8,
-	0x0241,
-	0x0376,
-	0x0386,
-	0x038c,
-	0x03cf,
-	0x03f7,
-	0x2132,
-	0x2183,
-	0x2c60,
-	0x2c72,
-	0x2c75,
-	0xa790,
-};
-
-int
-istitlerune(Rune c)
-{
-	Rune *p;
-
-	p = rbsearch(c, __istitler, nelem(__istitler)/2, 2);
-	if(p && c >= p[0] && c <= p[1])
-		return 1;
-	p = rbsearch(c, __istitlep, nelem(__istitlep)/2, 2);
-	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
-		return 1;
-	p = rbsearch(c, __istitles, nelem(__istitles), 1);
-	if(p && c == p[0])
-		return 1;
-	return 0;
-}
-
-static Rune __toupperr[] = {
-	0x0061, 0x007a, 1048544,
-	0x00e0, 0x00f6, 1048544,
-	0x00f8, 0x00fe, 1048544,
-	0x023f, 0x0240, 1059391,
-	0x0256, 0x0257, 1048371,
-	0x028a, 0x028b, 1048359,
-	0x037b, 0x037d, 1048706,
-	0x03ad, 0x03af, 1048539,
-	0x03b1, 0x03c1, 1048544,
-	0x03c3, 0x03cb, 1048544,
-	0x03cd, 0x03ce, 1048513,
-	0x0430, 0x044f, 1048544,
-	0x0450, 0x045f, 1048496,
-	0x0561, 0x0586, 1048528,
-	0x1f00, 0x1f07, 1048584,
-	0x1f10, 0x1f15, 1048584,
-	0x1f20, 0x1f27, 1048584,
-	0x1f30, 0x1f37, 1048584,
-	0x1f40, 0x1f45, 1048584,
-	0x1f60, 0x1f67, 1048584,
-	0x1f70, 0x1f71, 1048650,
-	0x1f72, 0x1f75, 1048662,
-	0x1f76, 0x1f77, 1048676,
-	0x1f78, 0x1f79, 1048704,
-	0x1f7a, 0x1f7b, 1048688,
-	0x1f7c, 0x1f7d, 1048702,
-	0x1f80, 0x1f87, 1048584,
-	0x1f90, 0x1f97, 1048584,
-	0x1fa0, 0x1fa7, 1048584,
-	0x1fb0, 0x1fb1, 1048584,
-	0x1fd0, 0x1fd1, 1048584,
-	0x1fe0, 0x1fe1, 1048584,
-	0x2170, 0x217f, 1048560,
-	0x24d0, 0x24e9, 1048550,
-	0x2c30, 0x2c5e, 1048528,
-	0x2d00, 0x2d25, 1041312,
-	0xff41, 0xff5a, 1048544,
-	0x10428, 0x1044f, 1048536,
-};
-
-static Rune __toupperp[] = {
-	0x0101, 0x012f, 1048575,
-	0x0133, 0x0137, 1048575,
-	0x013a, 0x0148, 1048575,
-	0x014b, 0x0177, 1048575,
-	0x017a, 0x017e, 1048575,
-	0x0183, 0x0185, 1048575,
-	0x01a1, 0x01a5, 1048575,
-	0x01b4, 0x01b6, 1048575,
-	0x01ce, 0x01dc, 1048575,
-	0x01df, 0x01ef, 1048575,
-	0x01f9, 0x021f, 1048575,
-	0x0223, 0x0233, 1048575,
-	0x0247, 0x024f, 1048575,
-	0x0371, 0x0373, 1048575,
-	0x03d9, 0x03ef, 1048575,
-	0x0461, 0x0481, 1048575,
-	0x048b, 0x04bf, 1048575,
-	0x04c2, 0x04ce, 1048575,
-	0x04d1, 0x0527, 1048575,
-	0x1e01, 0x1e95, 1048575,
-	0x1ea1, 0x1eff, 1048575,
-	0x1f51, 0x1f57, 1048584,
-	0x2c68, 0x2c6c, 1048575,
-	0x2c81, 0x2ce3, 1048575,
-	0x2cec, 0x2cee, 1048575,
-	0xa641, 0xa66d, 1048575,
-	0xa681, 0xa697, 1048575,
-	0xa723, 0xa72f, 1048575,
-	0xa733, 0xa76f, 1048575,
-	0xa77a, 0xa77c, 1048575,
-	0xa77f, 0xa787, 1048575,
-	0xa7a1, 0xa7a9, 1048575,
-};
-
-static Rune __touppers[] = {
-	0x00b5, 1049319,
-	0x00ff, 1048697,
-	0x0131, 1048344,
-	0x017f, 1048276,
-	0x0180, 1048771,
-	0x0188, 1048575,
-	0x018c, 1048575,
-	0x0192, 1048575,
-	0x0195, 1048673,
-	0x0199, 1048575,
-	0x019a, 1048739,
-	0x019e, 1048706,
-	0x01a8, 1048575,
-	0x01ad, 1048575,
-	0x01b0, 1048575,
-	0x01b9, 1048575,
-	0x01bd, 1048575,
-	0x01bf, 1048632,
-	0x01c5, 1048575,
-	0x01c6, 1048574,
-	0x01c8, 1048575,
-	0x01c9, 1048574,
-	0x01cb, 1048575,
-	0x01cc, 1048574,
-	0x01dd, 1048497,
-	0x01f2, 1048575,
-	0x01f3, 1048574,
-	0x01f5, 1048575,
-	0x023c, 1048575,
-	0x0242, 1048575,
-	0x0250, 1059359,
-	0x0251, 1059356,
-	0x0252, 1059358,
-	0x0253, 1048366,
-	0x0254, 1048370,
-	0x0259, 1048374,
-	0x025b, 1048373,
-	0x0260, 1048371,
-	0x0263, 1048369,
-	0x0265, 1090856,
-	0x0268, 1048367,
-	0x0269, 1048365,
-	0x026b, 1059319,
-	0x026f, 1048365,
-	0x0271, 1059325,
-	0x0272, 1048363,
-	0x0275, 1048362,
-	0x027d, 1059303,
-	0x0280, 1048358,
-	0x0283, 1048358,
-	0x0288, 1048358,
-	0x0289, 1048507,
-	0x028c, 1048505,
-	0x0292, 1048357,
-	0x0345, 1048660,
-	0x0377, 1048575,
-	0x03ac, 1048538,
-	0x03c2, 1048545,
-	0x03cc, 1048512,
-	0x03d0, 1048514,
-	0x03d1, 1048519,
-	0x03d5, 1048529,
-	0x03d6, 1048522,
-	0x03d7, 1048568,
-	0x03f0, 1048490,
-	0x03f1, 1048496,
-	0x03f2, 1048583,
-	0x03f5, 1048480,
-	0x03f8, 1048575,
-	0x03fb, 1048575,
-	0x04cf, 1048561,
-	0x1d79, 1083908,
-	0x1d7d, 1052390,
-	0x1e9b, 1048517,
-	0x1fb3, 1048585,
-	0x1fbe, 1041371,
-	0x1fc3, 1048585,
-	0x1fe5, 1048583,
-	0x1ff3, 1048585,
-	0x214e, 1048548,
-	0x2184, 1048575,
-	0x2c61, 1048575,
-	0x2c65, 1037781,
-	0x2c66, 1037784,
-	0x2c73, 1048575,
-	0x2c76, 1048575,
-	0xa78c, 1048575,
-	0xa791, 1048575,
-};
-
-Rune
-toupperrune(Rune c)
-{
-	Rune *p;
-
-	p = rbsearch(c, __toupperr, nelem(__toupperr)/3, 3);
-	if(p && c >= p[0] && c <= p[1])
-		return c + p[2] - 1048576;
-	p = rbsearch(c, __toupperp, nelem(__toupperp)/3, 3);
-	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
-		return c + p[2] - 1048576;
-	p = rbsearch(c, __touppers, nelem(__touppers)/2, 2);
-	if(p && c == p[0])
-		return c + p[1] - 1048576;
-	return c;
-}
-
-static Rune __tolowerr[] = {
-	0x0041, 0x005a, 1048608,
-	0x00c0, 0x00d6, 1048608,
-	0x00d8, 0x00de, 1048608,
-	0x0189, 0x018a, 1048781,
-	0x01b1, 0x01b2, 1048793,
-	0x0388, 0x038a, 1048613,
-	0x038e, 0x038f, 1048639,
-	0x0391, 0x03a1, 1048608,
-	0x03a3, 0x03ab, 1048608,
-	0x03fd, 0x03ff, 1048446,
-	0x0400, 0x040f, 1048656,
-	0x0410, 0x042f, 1048608,
-	0x0531, 0x0556, 1048624,
-	0x10a0, 0x10c5, 1055840,
-	0x1f08, 0x1f0f, 1048568,
-	0x1f18, 0x1f1d, 1048568,
-	0x1f28, 0x1f2f, 1048568,
-	0x1f38, 0x1f3f, 1048568,
-	0x1f48, 0x1f4d, 1048568,
-	0x1f68, 0x1f6f, 1048568,
-	0x1f88, 0x1f8f, 1048568,
-	0x1f98, 0x1f9f, 1048568,
-	0x1fa8, 0x1faf, 1048568,
-	0x1fb8, 0x1fb9, 1048568,
-	0x1fba, 0x1fbb, 1048502,
-	0x1fc8, 0x1fcb, 1048490,
-	0x1fd8, 0x1fd9, 1048568,
-	0x1fda, 0x1fdb, 1048476,
-	0x1fe8, 0x1fe9, 1048568,
-	0x1fea, 0x1feb, 1048464,
-	0x1ff8, 0x1ff9, 1048448,
-	0x1ffa, 0x1ffb, 1048450,
-	0x2160, 0x216f, 1048592,
-	0x24b6, 0x24cf, 1048602,
-	0x2c00, 0x2c2e, 1048624,
-	0x2c7e, 0x2c7f, 1037761,
-	0xff21, 0xff3a, 1048608,
-	0x10400, 0x10427, 1048616,
-};
-
-static Rune __tolowerp[] = {
-	0x0100, 0x012e, 1048577,
-	0x0132, 0x0136, 1048577,
-	0x0139, 0x0147, 1048577,
-	0x014a, 0x0176, 1048577,
-	0x017b, 0x017d, 1048577,
-	0x01a2, 0x01a4, 1048577,
-	0x01b3, 0x01b5, 1048577,
-	0x01cd, 0x01db, 1048577,
-	0x01de, 0x01ee, 1048577,
-	0x01f8, 0x021e, 1048577,
-	0x0222, 0x0232, 1048577,
-	0x0248, 0x024e, 1048577,
-	0x0370, 0x0372, 1048577,
-	0x03d8, 0x03ee, 1048577,
-	0x0460, 0x0480, 1048577,
-	0x048a, 0x04be, 1048577,
-	0x04c3, 0x04cd, 1048577,
-	0x04d0, 0x0526, 1048577,
-	0x1e00, 0x1e94, 1048577,
-	0x1ea0, 0x1efe, 1048577,
-	0x1f59, 0x1f5f, 1048568,
-	0x2c67, 0x2c6b, 1048577,
-	0x2c80, 0x2ce2, 1048577,
-	0x2ceb, 0x2ced, 1048577,
-	0xa640, 0xa66c, 1048577,
-	0xa680, 0xa696, 1048577,
-	0xa722, 0xa72e, 1048577,
-	0xa732, 0xa76e, 1048577,
-	0xa779, 0xa77b, 1048577,
-	0xa780, 0xa786, 1048577,
-	0xa7a0, 0xa7a8, 1048577,
-};
-
-static Rune __tolowers[] = {
-	0x0130, 1048377,
-	0x0178, 1048455,
-	0x0179, 1048577,
-	0x0181, 1048786,
-	0x0182, 1048577,
-	0x0184, 1048577,
-	0x0186, 1048782,
-	0x0187, 1048577,
-	0x018b, 1048577,
-	0x018e, 1048655,
-	0x018f, 1048778,
-	0x0190, 1048779,
-	0x0191, 1048577,
-	0x0193, 1048781,
-	0x0194, 1048783,
-	0x0196, 1048787,
-	0x0197, 1048785,
-	0x0198, 1048577,
-	0x019c, 1048787,
-	0x019d, 1048789,
-	0x019f, 1048790,
-	0x01a0, 1048577,
-	0x01a6, 1048794,
-	0x01a7, 1048577,
-	0x01a9, 1048794,
-	0x01ac, 1048577,
-	0x01ae, 1048794,
-	0x01af, 1048577,
-	0x01b7, 1048795,
-	0x01b8, 1048577,
-	0x01bc, 1048577,
-	0x01c4, 1048578,
-	0x01c5, 1048577,
-	0x01c7, 1048578,
-	0x01c8, 1048577,
-	0x01ca, 1048578,
-	0x01cb, 1048577,
-	0x01f1, 1048578,
-	0x01f2, 1048577,
-	0x01f4, 1048577,
-	0x01f6, 1048479,
-	0x01f7, 1048520,
-	0x0220, 1048446,
-	0x023a, 1059371,
-	0x023b, 1048577,
-	0x023d, 1048413,
-	0x023e, 1059368,
-	0x0241, 1048577,
-	0x0243, 1048381,
-	0x0244, 1048645,
-	0x0245, 1048647,
-	0x0246, 1048577,
-	0x0376, 1048577,
-	0x0386, 1048614,
-	0x038c, 1048640,
-	0x03cf, 1048584,
-	0x03f4, 1048516,
-	0x03f7, 1048577,
-	0x03f9, 1048569,
-	0x03fa, 1048577,
-	0x04c0, 1048591,
-	0x04c1, 1048577,
-	0x1e9e, 1040961,
-	0x1fbc, 1048567,
-	0x1fcc, 1048567,
-	0x1fec, 1048569,
-	0x1ffc, 1048567,
-	0x2126, 1041059,
-	0x212a, 1040193,
-	0x212b, 1040314,
-	0x2132, 1048604,
-	0x2183, 1048577,
-	0x2c60, 1048577,
-	0x2c62, 1037833,
-	0x2c63, 1044762,
-	0x2c64, 1037849,
-	0x2c6d, 1037796,
-	0x2c6e, 1037827,
-	0x2c6f, 1037793,
-	0x2c70, 1037794,
-	0x2c72, 1048577,
-	0x2c75, 1048577,
-	0xa77d, 1013244,
-	0xa77e, 1048577,
-	0xa78b, 1048577,
-	0xa78d, 1006296,
-	0xa790, 1048577,
-};
-
-Rune
-tolowerrune(Rune c)
-{
-	Rune *p;
-
-	p = rbsearch(c, __tolowerr, nelem(__tolowerr)/3, 3);
-	if(p && c >= p[0] && c <= p[1])
-		return c + p[2] - 1048576;
-	p = rbsearch(c, __tolowerp, nelem(__tolowerp)/3, 3);
-	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
-		return c + p[2] - 1048576;
-	p = rbsearch(c, __tolowers, nelem(__tolowers)/2, 2);
-	if(p && c == p[0])
-		return c + p[1] - 1048576;
-	return c;
-}
-
-static Rune __totitler[] = {
-	0x0061, 0x007a, 1048544,
-	0x00e0, 0x00f6, 1048544,
-	0x00f8, 0x00fe, 1048544,
-	0x023f, 0x0240, 1059391,
-	0x0256, 0x0257, 1048371,
-	0x028a, 0x028b, 1048359,
-	0x037b, 0x037d, 1048706,
-	0x03ad, 0x03af, 1048539,
-	0x03b1, 0x03c1, 1048544,
-	0x03c3, 0x03cb, 1048544,
-	0x03cd, 0x03ce, 1048513,
-	0x0430, 0x044f, 1048544,
-	0x0450, 0x045f, 1048496,
-	0x0561, 0x0586, 1048528,
-	0x1f00, 0x1f07, 1048584,
-	0x1f10, 0x1f15, 1048584,
-	0x1f20, 0x1f27, 1048584,
-	0x1f30, 0x1f37, 1048584,
-	0x1f40, 0x1f45, 1048584,
-	0x1f60, 0x1f67, 1048584,
-	0x1f70, 0x1f71, 1048650,
-	0x1f72, 0x1f75, 1048662,
-	0x1f76, 0x1f77, 1048676,
-	0x1f78, 0x1f79, 1048704,
-	0x1f7a, 0x1f7b, 1048688,
-	0x1f7c, 0x1f7d, 1048702,
-	0x1f80, 0x1f87, 1048584,
-	0x1f90, 0x1f97, 1048584,
-	0x1fa0, 0x1fa7, 1048584,
-	0x1fb0, 0x1fb1, 1048584,
-	0x1fd0, 0x1fd1, 1048584,
-	0x1fe0, 0x1fe1, 1048584,
-	0x2170, 0x217f, 1048560,
-	0x24d0, 0x24e9, 1048550,
-	0x2c30, 0x2c5e, 1048528,
-	0x2d00, 0x2d25, 1041312,
-	0xff41, 0xff5a, 1048544,
-	0x10428, 0x1044f, 1048536,
-};
-
-static Rune __totitlep[] = {
-	0x0101, 0x012f, 1048575,
-	0x0133, 0x0137, 1048575,
-	0x013a, 0x0148, 1048575,
-	0x014b, 0x0177, 1048575,
-	0x017a, 0x017e, 1048575,
-	0x0183, 0x0185, 1048575,
-	0x01a1, 0x01a5, 1048575,
-	0x01b4, 0x01b6, 1048575,
-	0x01cc, 0x01dc, 1048575,
-	0x01df, 0x01ef, 1048575,
-	0x01f3, 0x01f5, 1048575,
-	0x01f9, 0x021f, 1048575,
-	0x0223, 0x0233, 1048575,
-	0x0247, 0x024f, 1048575,
-	0x0371, 0x0373, 1048575,
-	0x03d9, 0x03ef, 1048575,
-	0x0461, 0x0481, 1048575,
-	0x048b, 0x04bf, 1048575,
-	0x04c2, 0x04ce, 1048575,
-	0x04d1, 0x0527, 1048575,
-	0x1e01, 0x1e95, 1048575,
-	0x1ea1, 0x1eff, 1048575,
-	0x1f51, 0x1f57, 1048584,
-	0x2c68, 0x2c6c, 1048575,
-	0x2c81, 0x2ce3, 1048575,
-	0x2cec, 0x2cee, 1048575,
-	0xa641, 0xa66d, 1048575,
-	0xa681, 0xa697, 1048575,
-	0xa723, 0xa72f, 1048575,
-	0xa733, 0xa76f, 1048575,
-	0xa77a, 0xa77c, 1048575,
-	0xa77f, 0xa787, 1048575,
-	0xa7a1, 0xa7a9, 1048575,
-};
-
-static Rune __totitles[] = {
-	0x00b5, 1049319,
-	0x00ff, 1048697,
-	0x0131, 1048344,
-	0x017f, 1048276,
-	0x0180, 1048771,
-	0x0188, 1048575,
-	0x018c, 1048575,
-	0x0192, 1048575,
-	0x0195, 1048673,
-	0x0199, 1048575,
-	0x019a, 1048739,
-	0x019e, 1048706,
-	0x01a8, 1048575,
-	0x01ad, 1048575,
-	0x01b0, 1048575,
-	0x01b9, 1048575,
-	0x01bd, 1048575,
-	0x01bf, 1048632,
-	0x01c4, 1048577,
-	0x01c6, 1048575,
-	0x01c7, 1048577,
-	0x01c9, 1048575,
-	0x01ca, 1048577,
-	0x01dd, 1048497,
-	0x01f1, 1048577,
-	0x023c, 1048575,
-	0x0242, 1048575,
-	0x0250, 1059359,
-	0x0251, 1059356,
-	0x0252, 1059358,
-	0x0253, 1048366,
-	0x0254, 1048370,
-	0x0259, 1048374,
-	0x025b, 1048373,
-	0x0260, 1048371,
-	0x0263, 1048369,
-	0x0265, 1090856,
-	0x0268, 1048367,
-	0x0269, 1048365,
-	0x026b, 1059319,
-	0x026f, 1048365,
-	0x0271, 1059325,
-	0x0272, 1048363,
-	0x0275, 1048362,
-	0x027d, 1059303,
-	0x0280, 1048358,
-	0x0283, 1048358,
-	0x0288, 1048358,
-	0x0289, 1048507,
-	0x028c, 1048505,
-	0x0292, 1048357,
-	0x0345, 1048660,
-	0x0377, 1048575,
-	0x03ac, 1048538,
-	0x03c2, 1048545,
-	0x03cc, 1048512,
-	0x03d0, 1048514,
-	0x03d1, 1048519,
-	0x03d5, 1048529,
-	0x03d6, 1048522,
-	0x03d7, 1048568,
-	0x03f0, 1048490,
-	0x03f1, 1048496,
-	0x03f2, 1048583,
-	0x03f5, 1048480,
-	0x03f8, 1048575,
-	0x03fb, 1048575,
-	0x04cf, 1048561,
-	0x1d79, 1083908,
-	0x1d7d, 1052390,
-	0x1e9b, 1048517,
-	0x1fb3, 1048585,
-	0x1fbe, 1041371,
-	0x1fc3, 1048585,
-	0x1fe5, 1048583,
-	0x1ff3, 1048585,
-	0x214e, 1048548,
-	0x2184, 1048575,
-	0x2c61, 1048575,
-	0x2c65, 1037781,
-	0x2c66, 1037784,
-	0x2c73, 1048575,
-	0x2c76, 1048575,
-	0xa78c, 1048575,
-	0xa791, 1048575,
-};
-
-Rune
-totitlerune(Rune c)
-{
-	Rune *p;
-
-	p = rbsearch(c, __totitler, nelem(__totitler)/3, 3);
-	if(p && c >= p[0] && c <= p[1])
-		return c + p[2] - 1048576;
-	p = rbsearch(c, __totitlep, nelem(__totitlep)/3, 3);
-	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
-		return c + p[2] - 1048576;
-	p = rbsearch(c, __totitles, nelem(__totitles)/2, 2);
-	if(p && c == p[0])
-		return c + p[1] - 1048576;
-	return c;
-}
-
diff --git a/src/lib9/utf/runetypebody-6.2.0.h b/src/lib9/utf/runetypebody-6.2.0.h
new file mode 100644
index 0000000..a603af0
--- /dev/null
+++ b/src/lib9/utf/runetypebody-6.2.0.h
@@ -0,0 +1,1639 @@
+/* generated automatically by mkrunetype.c from UnicodeData-6.2.0.txt */
+
+static Rune __isspacer[] = {
+	0x0009, 0x000d,
+	0x0020, 0x0020,
+	0x0085, 0x0085,
+	0x00a0, 0x00a0,
+	0x1680, 0x1680,
+	0x180e, 0x180e,
+	0x2000, 0x200a,
+	0x2028, 0x2029,
+	0x202f, 0x202f,
+	0x205f, 0x205f,
+	0x3000, 0x3000,
+	0xfeff, 0xfeff,
+};
+
+int
+isspacerune(Rune c)
+{
+	Rune *p;
+
+	p = rbsearch(c, __isspacer, nelem(__isspacer)/2, 2);
+	if(p && c >= p[0] && c <= p[1])
+		return 1;
+	return 0;
+}
+
+static Rune __isdigitr[] = {
+	0x0030, 0x0039,
+	0x0660, 0x0669,
+	0x06f0, 0x06f9,
+	0x07c0, 0x07c9,
+	0x0966, 0x096f,
+	0x09e6, 0x09ef,
+	0x0a66, 0x0a6f,
+	0x0ae6, 0x0aef,
+	0x0b66, 0x0b6f,
+	0x0be6, 0x0bef,
+	0x0c66, 0x0c6f,
+	0x0ce6, 0x0cef,
+	0x0d66, 0x0d6f,
+	0x0e50, 0x0e59,
+	0x0ed0, 0x0ed9,
+	0x0f20, 0x0f29,
+	0x1040, 0x1049,
+	0x1090, 0x1099,
+	0x17e0, 0x17e9,
+	0x1810, 0x1819,
+	0x1946, 0x194f,
+	0x19d0, 0x19d9,
+	0x1a80, 0x1a89,
+	0x1a90, 0x1a99,
+	0x1b50, 0x1b59,
+	0x1bb0, 0x1bb9,
+	0x1c40, 0x1c49,
+	0x1c50, 0x1c59,
+	0xa620, 0xa629,
+	0xa8d0, 0xa8d9,
+	0xa900, 0xa909,
+	0xa9d0, 0xa9d9,
+	0xaa50, 0xaa59,
+	0xabf0, 0xabf9,
+	0xff10, 0xff19,
+	0x104a0, 0x104a9,
+	0x11066, 0x1106f,
+	0x110f0, 0x110f9,
+	0x11136, 0x1113f,
+	0x111d0, 0x111d9,
+	0x116c0, 0x116c9,
+	0x1d7ce, 0x1d7ff,
+};
+
+int
+isdigitrune(Rune c)
+{
+	Rune *p;
+
+	p = rbsearch(c, __isdigitr, nelem(__isdigitr)/2, 2);
+	if(p && c >= p[0] && c <= p[1])
+		return 1;
+	return 0;
+}
+
+static Rune __isalphar[] = {
+	0x0041, 0x005a,
+	0x0061, 0x007a,
+	0x00c0, 0x00d6,
+	0x00d8, 0x00f6,
+	0x00f8, 0x02c1,
+	0x02c6, 0x02d1,
+	0x02e0, 0x02e4,
+	0x0370, 0x0374,
+	0x0376, 0x0377,
+	0x037a, 0x037d,
+	0x0388, 0x038a,
+	0x038e, 0x03a1,
+	0x03a3, 0x03f5,
+	0x03f7, 0x0481,
+	0x048a, 0x0527,
+	0x0531, 0x0556,
+	0x0561, 0x0587,
+	0x05d0, 0x05ea,
+	0x05f0, 0x05f2,
+	0x0620, 0x064a,
+	0x066e, 0x066f,
+	0x0671, 0x06d3,
+	0x06e5, 0x06e6,
+	0x06ee, 0x06ef,
+	0x06fa, 0x06fc,
+	0x0712, 0x072f,
+	0x074d, 0x07a5,
+	0x07ca, 0x07ea,
+	0x07f4, 0x07f5,
+	0x0800, 0x0815,
+	0x0840, 0x0858,
+	0x08a2, 0x08ac,
+	0x0904, 0x0939,
+	0x0958, 0x0961,
+	0x0971, 0x0977,
+	0x0979, 0x097f,
+	0x0985, 0x098c,
+	0x098f, 0x0990,
+	0x0993, 0x09a8,
+	0x09aa, 0x09b0,
+	0x09b6, 0x09b9,
+	0x09dc, 0x09dd,
+	0x09df, 0x09e1,
+	0x09f0, 0x09f1,
+	0x0a05, 0x0a0a,
+	0x0a0f, 0x0a10,
+	0x0a13, 0x0a28,
+	0x0a2a, 0x0a30,
+	0x0a32, 0x0a33,
+	0x0a35, 0x0a36,
+	0x0a38, 0x0a39,
+	0x0a59, 0x0a5c,
+	0x0a72, 0x0a74,
+	0x0a85, 0x0a8d,
+	0x0a8f, 0x0a91,
+	0x0a93, 0x0aa8,
+	0x0aaa, 0x0ab0,
+	0x0ab2, 0x0ab3,
+	0x0ab5, 0x0ab9,
+	0x0ae0, 0x0ae1,
+	0x0b05, 0x0b0c,
+	0x0b0f, 0x0b10,
+	0x0b13, 0x0b28,
+	0x0b2a, 0x0b30,
+	0x0b32, 0x0b33,
+	0x0b35, 0x0b39,
+	0x0b5c, 0x0b5d,
+	0x0b5f, 0x0b61,
+	0x0b85, 0x0b8a,
+	0x0b8e, 0x0b90,
+	0x0b92, 0x0b95,
+	0x0b99, 0x0b9a,
+	0x0b9e, 0x0b9f,
+	0x0ba3, 0x0ba4,
+	0x0ba8, 0x0baa,
+	0x0bae, 0x0bb9,
+	0x0c05, 0x0c0c,
+	0x0c0e, 0x0c10,
+	0x0c12, 0x0c28,
+	0x0c2a, 0x0c33,
+	0x0c35, 0x0c39,
+	0x0c58, 0x0c59,
+	0x0c60, 0x0c61,
+	0x0c85, 0x0c8c,
+	0x0c8e, 0x0c90,
+	0x0c92, 0x0ca8,
+	0x0caa, 0x0cb3,
+	0x0cb5, 0x0cb9,
+	0x0ce0, 0x0ce1,
+	0x0cf1, 0x0cf2,
+	0x0d05, 0x0d0c,
+	0x0d0e, 0x0d10,
+	0x0d12, 0x0d3a,
+	0x0d60, 0x0d61,
+	0x0d7a, 0x0d7f,
+	0x0d85, 0x0d96,
+	0x0d9a, 0x0db1,
+	0x0db3, 0x0dbb,
+	0x0dc0, 0x0dc6,
+	0x0e01, 0x0e30,
+	0x0e32, 0x0e33,
+	0x0e40, 0x0e46,
+	0x0e81, 0x0e82,
+	0x0e87, 0x0e88,
+	0x0e94, 0x0e97,
+	0x0e99, 0x0e9f,
+	0x0ea1, 0x0ea3,
+	0x0eaa, 0x0eab,
+	0x0ead, 0x0eb0,
+	0x0eb2, 0x0eb3,
+	0x0ec0, 0x0ec4,
+	0x0edc, 0x0edf,
+	0x0f40, 0x0f47,
+	0x0f49, 0x0f6c,
+	0x0f88, 0x0f8c,
+	0x1000, 0x102a,
+	0x1050, 0x1055,
+	0x105a, 0x105d,
+	0x1065, 0x1066,
+	0x106e, 0x1070,
+	0x1075, 0x1081,
+	0x10a0, 0x10c5,
+	0x10d0, 0x10fa,
+	0x10fc, 0x1248,
+	0x124a, 0x124d,
+	0x1250, 0x1256,
+	0x125a, 0x125d,
+	0x1260, 0x1288,
+	0x128a, 0x128d,
+	0x1290, 0x12b0,
+	0x12b2, 0x12b5,
+	0x12b8, 0x12be,
+	0x12c2, 0x12c5,
+	0x12c8, 0x12d6,
+	0x12d8, 0x1310,
+	0x1312, 0x1315,
+	0x1318, 0x135a,
+	0x1380, 0x138f,
+	0x13a0, 0x13f4,
+	0x1401, 0x166c,
+	0x166f, 0x167f,
+	0x1681, 0x169a,
+	0x16a0, 0x16ea,
+	0x1700, 0x170c,
+	0x170e, 0x1711,
+	0x1720, 0x1731,
+	0x1740, 0x1751,
+	0x1760, 0x176c,
+	0x176e, 0x1770,
+	0x1780, 0x17b3,
+	0x1820, 0x1877,
+	0x1880, 0x18a8,
+	0x18b0, 0x18f5,
+	0x1900, 0x191c,
+	0x1950, 0x196d,
+	0x1970, 0x1974,
+	0x1980, 0x19ab,
+	0x19c1, 0x19c7,
+	0x1a00, 0x1a16,
+	0x1a20, 0x1a54,
+	0x1b05, 0x1b33,
+	0x1b45, 0x1b4b,
+	0x1b83, 0x1ba0,
+	0x1bae, 0x1baf,
+	0x1bba, 0x1be5,
+	0x1c00, 0x1c23,
+	0x1c4d, 0x1c4f,
+	0x1c5a, 0x1c7d,
+	0x1ce9, 0x1cec,
+	0x1cee, 0x1cf1,
+	0x1cf5, 0x1cf6,
+	0x1d00, 0x1dbf,
+	0x1e00, 0x1f15,
+	0x1f18, 0x1f1d,
+	0x1f20, 0x1f45,
+	0x1f48, 0x1f4d,
+	0x1f50, 0x1f57,
+	0x1f5f, 0x1f7d,
+	0x1f80, 0x1fb4,
+	0x1fb6, 0x1fbc,
+	0x1fc2, 0x1fc4,
+	0x1fc6, 0x1fcc,
+	0x1fd0, 0x1fd3,
+	0x1fd6, 0x1fdb,
+	0x1fe0, 0x1fec,
+	0x1ff2, 0x1ff4,
+	0x1ff6, 0x1ffc,
+	0x2090, 0x209c,
+	0x210a, 0x2113,
+	0x2119, 0x211d,
+	0x212a, 0x212d,
+	0x212f, 0x2139,
+	0x213c, 0x213f,
+	0x2145, 0x2149,
+	0x2183, 0x2184,
+	0x2c00, 0x2c2e,
+	0x2c30, 0x2c5e,
+	0x2c60, 0x2ce4,
+	0x2ceb, 0x2cee,
+	0x2cf2, 0x2cf3,
+	0x2d00, 0x2d25,
+	0x2d30, 0x2d67,
+	0x2d80, 0x2d96,
+	0x2da0, 0x2da6,
+	0x2da8, 0x2dae,
+	0x2db0, 0x2db6,
+	0x2db8, 0x2dbe,
+	0x2dc0, 0x2dc6,
+	0x2dc8, 0x2dce,
+	0x2dd0, 0x2dd6,
+	0x2dd8, 0x2dde,
+	0x3005, 0x3006,
+	0x3031, 0x3035,
+	0x303b, 0x303c,
+	0x3041, 0x3096,
+	0x309d, 0x309f,
+	0x30a1, 0x30fa,
+	0x30fc, 0x30ff,
+	0x3105, 0x312d,
+	0x3131, 0x318e,
+	0x31a0, 0x31ba,
+	0x31f0, 0x31ff,
+	0x3400, 0x4db5,
+	0x4e00, 0x9fcc,
+	0xa000, 0xa48c,
+	0xa4d0, 0xa4fd,
+	0xa500, 0xa60c,
+	0xa610, 0xa61f,
+	0xa62a, 0xa62b,
+	0xa640, 0xa66e,
+	0xa67f, 0xa697,
+	0xa6a0, 0xa6e5,
+	0xa717, 0xa71f,
+	0xa722, 0xa788,
+	0xa78b, 0xa78e,
+	0xa790, 0xa793,
+	0xa7a0, 0xa7aa,
+	0xa7f8, 0xa801,
+	0xa803, 0xa805,
+	0xa807, 0xa80a,
+	0xa80c, 0xa822,
+	0xa840, 0xa873,
+	0xa882, 0xa8b3,
+	0xa8f2, 0xa8f7,
+	0xa90a, 0xa925,
+	0xa930, 0xa946,
+	0xa960, 0xa97c,
+	0xa984, 0xa9b2,
+	0xaa00, 0xaa28,
+	0xaa40, 0xaa42,
+	0xaa44, 0xaa4b,
+	0xaa60, 0xaa76,
+	0xaa80, 0xaaaf,
+	0xaab5, 0xaab6,
+	0xaab9, 0xaabd,
+	0xaadb, 0xaadd,
+	0xaae0, 0xaaea,
+	0xaaf2, 0xaaf4,
+	0xab01, 0xab06,
+	0xab09, 0xab0e,
+	0xab11, 0xab16,
+	0xab20, 0xab26,
+	0xab28, 0xab2e,
+	0xabc0, 0xabe2,
+	0xac00, 0xd7a3,
+	0xd7b0, 0xd7c6,
+	0xd7cb, 0xd7fb,
+	0xf900, 0xfa6d,
+	0xfa70, 0xfad9,
+	0xfb00, 0xfb06,
+	0xfb13, 0xfb17,
+	0xfb1f, 0xfb28,
+	0xfb2a, 0xfb36,
+	0xfb38, 0xfb3c,
+	0xfb40, 0xfb41,
+	0xfb43, 0xfb44,
+	0xfb46, 0xfbb1,
+	0xfbd3, 0xfd3d,
+	0xfd50, 0xfd8f,
+	0xfd92, 0xfdc7,
+	0xfdf0, 0xfdfb,
+	0xfe70, 0xfe74,
+	0xfe76, 0xfefc,
+	0xff21, 0xff3a,
+	0xff41, 0xff5a,
+	0xff66, 0xffbe,
+	0xffc2, 0xffc7,
+	0xffca, 0xffcf,
+	0xffd2, 0xffd7,
+	0xffda, 0xffdc,
+	0x10000, 0x1000b,
+	0x1000d, 0x10026,
+	0x10028, 0x1003a,
+	0x1003c, 0x1003d,
+	0x1003f, 0x1004d,
+	0x10050, 0x1005d,
+	0x10080, 0x100fa,
+	0x10280, 0x1029c,
+	0x102a0, 0x102d0,
+	0x10300, 0x1031e,
+	0x10330, 0x10340,
+	0x10342, 0x10349,
+	0x10380, 0x1039d,
+	0x103a0, 0x103c3,
+	0x103c8, 0x103cf,
+	0x10400, 0x1049d,
+	0x10800, 0x10805,
+	0x1080a, 0x10835,
+	0x10837, 0x10838,
+	0x1083f, 0x10855,
+	0x10900, 0x10915,
+	0x10920, 0x10939,
+	0x10980, 0x109b7,
+	0x109be, 0x109bf,
+	0x10a10, 0x10a13,
+	0x10a15, 0x10a17,
+	0x10a19, 0x10a33,
+	0x10a60, 0x10a7c,
+	0x10b00, 0x10b35,
+	0x10b40, 0x10b55,
+	0x10b60, 0x10b72,
+	0x10c00, 0x10c48,
+	0x11003, 0x11037,
+	0x11083, 0x110af,
+	0x110d0, 0x110e8,
+	0x11103, 0x11126,
+	0x11183, 0x111b2,
+	0x111c1, 0x111c4,
+	0x11680, 0x116aa,
+	0x12000, 0x1236e,
+	0x13000, 0x1342e,
+	0x16800, 0x16a38,
+	0x16f00, 0x16f44,
+	0x16f93, 0x16f9f,
+	0x1b000, 0x1b001,
+	0x1d400, 0x1d454,
+	0x1d456, 0x1d49c,
+	0x1d49e, 0x1d49f,
+	0x1d4a5, 0x1d4a6,
+	0x1d4a9, 0x1d4ac,
+	0x1d4ae, 0x1d4b9,
+	0x1d4bd, 0x1d4c3,
+	0x1d4c5, 0x1d505,
+	0x1d507, 0x1d50a,
+	0x1d50d, 0x1d514,
+	0x1d516, 0x1d51c,
+	0x1d51e, 0x1d539,
+	0x1d53b, 0x1d53e,
+	0x1d540, 0x1d544,
+	0x1d54a, 0x1d550,
+	0x1d552, 0x1d6a5,
+	0x1d6a8, 0x1d6c0,
+	0x1d6c2, 0x1d6da,
+	0x1d6dc, 0x1d6fa,
+	0x1d6fc, 0x1d714,
+	0x1d716, 0x1d734,
+	0x1d736, 0x1d74e,
+	0x1d750, 0x1d76e,
+	0x1d770, 0x1d788,
+	0x1d78a, 0x1d7a8,
+	0x1d7aa, 0x1d7c2,
+	0x1d7c4, 0x1d7cb,
+	0x1ee00, 0x1ee03,
+	0x1ee05, 0x1ee1f,
+	0x1ee21, 0x1ee22,
+	0x1ee29, 0x1ee32,
+	0x1ee34, 0x1ee37,
+	0x1ee4d, 0x1ee4f,
+	0x1ee51, 0x1ee52,
+	0x1ee61, 0x1ee62,
+	0x1ee67, 0x1ee6a,
+	0x1ee6c, 0x1ee72,
+	0x1ee74, 0x1ee77,
+	0x1ee79, 0x1ee7c,
+	0x1ee80, 0x1ee89,
+	0x1ee8b, 0x1ee9b,
+	0x1eea1, 0x1eea3,
+	0x1eea5, 0x1eea9,
+	0x1eeab, 0x1eebb,
+	0x20000, 0x2a6d6,
+	0x2a700, 0x2b734,
+	0x2b740, 0x2b81d,
+	0x2f800, 0x2fa1d,
+};
+
+static Rune __isalphas[] = {
+	0x00aa,
+	0x00b5,
+	0x00ba,
+	0x02ec,
+	0x02ee,
+	0x0386,
+	0x038c,
+	0x0559,
+	0x06d5,
+	0x06ff,
+	0x0710,
+	0x07b1,
+	0x07fa,
+	0x081a,
+	0x0824,
+	0x0828,
+	0x08a0,
+	0x093d,
+	0x0950,
+	0x09b2,
+	0x09bd,
+	0x09ce,
+	0x0a5e,
+	0x0abd,
+	0x0ad0,
+	0x0b3d,
+	0x0b71,
+	0x0b83,
+	0x0b9c,
+	0x0bd0,
+	0x0c3d,
+	0x0cbd,
+	0x0cde,
+	0x0d3d,
+	0x0d4e,
+	0x0dbd,
+	0x0e84,
+	0x0e8a,
+	0x0e8d,
+	0x0ea5,
+	0x0ea7,
+	0x0ebd,
+	0x0ec6,
+	0x0f00,
+	0x103f,
+	0x1061,
+	0x108e,
+	0x10c7,
+	0x10cd,
+	0x1258,
+	0x12c0,
+	0x17d7,
+	0x17dc,
+	0x18aa,
+	0x1aa7,
+	0x1f59,
+	0x1f5b,
+	0x1f5d,
+	0x1fbe,
+	0x2071,
+	0x207f,
+	0x2102,
+	0x2107,
+	0x2115,
+	0x2124,
+	0x2126,
+	0x2128,
+	0x214e,
+	0x2d27,
+	0x2d2d,
+	0x2d6f,
+	0x2e2f,
+	0xa8fb,
+	0xa9cf,
+	0xaa7a,
+	0xaab1,
+	0xaac0,
+	0xaac2,
+	0xfb1d,
+	0xfb3e,
+	0x10808,
+	0x1083c,
+	0x10a00,
+	0x16f50,
+	0x1d4a2,
+	0x1d4bb,
+	0x1d546,
+	0x1ee24,
+	0x1ee27,
+	0x1ee39,
+	0x1ee3b,
+	0x1ee42,
+	0x1ee47,
+	0x1ee49,
+	0x1ee4b,
+	0x1ee54,
+	0x1ee57,
+	0x1ee59,
+	0x1ee5b,
+	0x1ee5d,
+	0x1ee5f,
+	0x1ee64,
+	0x1ee7e,
+};
+
+int
+isalpharune(Rune c)
+{
+	Rune *p;
+
+	p = rbsearch(c, __isalphar, nelem(__isalphar)/2, 2);
+	if(p && c >= p[0] && c <= p[1])
+		return 1;
+	p = rbsearch(c, __isalphas, nelem(__isalphas), 1);
+	if(p && c == p[0])
+		return 1;
+	return 0;
+}
+
+static Rune __isupperr[] = {
+	0x0041, 0x005a,
+	0x00c0, 0x00d6,
+	0x00d8, 0x00de,
+	0x0178, 0x0179,
+	0x0181, 0x0182,
+	0x0186, 0x0187,
+	0x0189, 0x018b,
+	0x018e, 0x0191,
+	0x0193, 0x0194,
+	0x0196, 0x0198,
+	0x019c, 0x019d,
+	0x019f, 0x01a0,
+	0x01a6, 0x01a7,
+	0x01ae, 0x01af,
+	0x01b1, 0x01b3,
+	0x01b7, 0x01b8,
+	0x01f6, 0x01f8,
+	0x023a, 0x023b,
+	0x023d, 0x023e,
+	0x0243, 0x0246,
+	0x0388, 0x038a,
+	0x038e, 0x038f,
+	0x0391, 0x03a1,
+	0x03a3, 0x03ab,
+	0x03d2, 0x03d4,
+	0x03f9, 0x03fa,
+	0x03fd, 0x042f,
+	0x04c0, 0x04c1,
+	0x0531, 0x0556,
+	0x10a0, 0x10c5,
+	0x1f08, 0x1f0f,
+	0x1f18, 0x1f1d,
+	0x1f28, 0x1f2f,
+	0x1f38, 0x1f3f,
+	0x1f48, 0x1f4d,
+	0x1f68, 0x1f6f,
+	0x1f88, 0x1f8f,
+	0x1f98, 0x1f9f,
+	0x1fa8, 0x1faf,
+	0x1fb8, 0x1fbc,
+	0x1fc8, 0x1fcc,
+	0x1fd8, 0x1fdb,
+	0x1fe8, 0x1fec,
+	0x1ff8, 0x1ffc,
+	0x210b, 0x210d,
+	0x2110, 0x2112,
+	0x2119, 0x211d,
+	0x212a, 0x212d,
+	0x2130, 0x2133,
+	0x213e, 0x213f,
+	0x2160, 0x216f,
+	0x24b6, 0x24cf,
+	0x2c00, 0x2c2e,
+	0x2c62, 0x2c64,
+	0x2c6d, 0x2c70,
+	0x2c7e, 0x2c80,
+	0xa77d, 0xa77e,
+	0xff21, 0xff3a,
+	0x10400, 0x10427,
+	0x1d400, 0x1d419,
+	0x1d434, 0x1d44d,
+	0x1d468, 0x1d481,
+	0x1d49e, 0x1d49f,
+	0x1d4a5, 0x1d4a6,
+	0x1d4a9, 0x1d4ac,
+	0x1d4ae, 0x1d4b5,
+	0x1d4d0, 0x1d4e9,
+	0x1d504, 0x1d505,
+	0x1d507, 0x1d50a,
+	0x1d50d, 0x1d514,
+	0x1d516, 0x1d51c,
+	0x1d538, 0x1d539,
+	0x1d53b, 0x1d53e,
+	0x1d540, 0x1d544,
+	0x1d54a, 0x1d550,
+	0x1d56c, 0x1d585,
+	0x1d5a0, 0x1d5b9,
+	0x1d5d4, 0x1d5ed,
+	0x1d608, 0x1d621,
+	0x1d63c, 0x1d655,
+	0x1d670, 0x1d689,
+	0x1d6a8, 0x1d6c0,
+	0x1d6e2, 0x1d6fa,
+	0x1d71c, 0x1d734,
+	0x1d756, 0x1d76e,
+	0x1d790, 0x1d7a8,
+};
+
+static Rune __isupperp[] = {
+	0x0100, 0x0136,
+	0x0139, 0x0147,
+	0x014a, 0x0176,
+	0x017b, 0x017d,
+	0x01a2, 0x01a4,
+	0x01cd, 0x01db,
+	0x01de, 0x01ee,
+	0x01fa, 0x0232,
+	0x0248, 0x024e,
+	0x0370, 0x0372,
+	0x03d8, 0x03ee,
+	0x0460, 0x0480,
+	0x048a, 0x04be,
+	0x04c3, 0x04cd,
+	0x04d0, 0x0526,
+	0x1e00, 0x1e94,
+	0x1e9e, 0x1efe,
+	0x1f59, 0x1f5f,
+	0x2124, 0x2128,
+	0x2c67, 0x2c6b,
+	0x2c82, 0x2ce2,
+	0x2ceb, 0x2ced,
+	0xa640, 0xa66c,
+	0xa680, 0xa696,
+	0xa722, 0xa72e,
+	0xa732, 0xa76e,
+	0xa779, 0xa77b,
+	0xa780, 0xa786,
+	0xa78b, 0xa78d,
+	0xa790, 0xa792,
+	0xa7a0, 0xa7aa,
+};
+
+static Rune __isuppers[] = {
+	0x0184,
+	0x01a9,
+	0x01ac,
+	0x01b5,
+	0x01bc,
+	0x01c4,
+	0x01c7,
+	0x01ca,
+	0x01f1,
+	0x01f4,
+	0x0241,
+	0x0376,
+	0x0386,
+	0x038c,
+	0x03cf,
+	0x03f4,
+	0x03f7,
+	0x10c7,
+	0x10cd,
+	0x2102,
+	0x2107,
+	0x2115,
+	0x2145,
+	0x2183,
+	0x2c60,
+	0x2c72,
+	0x2c75,
+	0x2cf2,
+	0x1d49c,
+	0x1d4a2,
+	0x1d546,
+	0x1d7ca,
+};
+
+int
+isupperrune(Rune c)
+{
+	Rune *p;
+
+	p = rbsearch(c, __isupperr, nelem(__isupperr)/2, 2);
+	if(p && c >= p[0] && c <= p[1])
+		return 1;
+	p = rbsearch(c, __isupperp, nelem(__isupperp)/2, 2);
+	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
+		return 1;
+	p = rbsearch(c, __isuppers, nelem(__isuppers), 1);
+	if(p && c == p[0])
+		return 1;
+	return 0;
+}
+
+static Rune __islowerr[] = {
+	0x0061, 0x007a,
+	0x00df, 0x00f6,
+	0x00f8, 0x00ff,
+	0x0137, 0x0138,
+	0x0148, 0x0149,
+	0x017e, 0x0180,
+	0x018c, 0x018d,
+	0x0199, 0x019b,
+	0x01aa, 0x01ab,
+	0x01b9, 0x01ba,
+	0x01bd, 0x01bf,
+	0x01dc, 0x01dd,
+	0x01ef, 0x01f0,
+	0x0233, 0x0239,
+	0x023f, 0x0240,
+	0x024f, 0x0293,
+	0x0295, 0x02af,
+	0x037b, 0x037d,
+	0x03ac, 0x03ce,
+	0x03d0, 0x03d1,
+	0x03d5, 0x03d7,
+	0x03ef, 0x03f3,
+	0x03fb, 0x03fc,
+	0x0430, 0x045f,
+	0x04ce, 0x04cf,
+	0x0561, 0x0587,
+	0x1d00, 0x1d2b,
+	0x1d6b, 0x1d77,
+	0x1d79, 0x1d9a,
+	0x1e95, 0x1e9d,
+	0x1eff, 0x1f07,
+	0x1f10, 0x1f15,
+	0x1f20, 0x1f27,
+	0x1f30, 0x1f37,
+	0x1f40, 0x1f45,
+	0x1f50, 0x1f57,
+	0x1f60, 0x1f67,
+	0x1f70, 0x1f7d,
+	0x1f80, 0x1f87,
+	0x1f90, 0x1f97,
+	0x1fa0, 0x1fa7,
+	0x1fb0, 0x1fb4,
+	0x1fb6, 0x1fb7,
+	0x1fc2, 0x1fc4,
+	0x1fc6, 0x1fc7,
+	0x1fd0, 0x1fd3,
+	0x1fd6, 0x1fd7,
+	0x1fe0, 0x1fe7,
+	0x1ff2, 0x1ff4,
+	0x1ff6, 0x1ff7,
+	0x210e, 0x210f,
+	0x213c, 0x213d,
+	0x2146, 0x2149,
+	0x2170, 0x217f,
+	0x24d0, 0x24e9,
+	0x2c30, 0x2c5e,
+	0x2c65, 0x2c66,
+	0x2c73, 0x2c74,
+	0x2c76, 0x2c7b,
+	0x2ce3, 0x2ce4,
+	0x2d00, 0x2d25,
+	0xa72f, 0xa731,
+	0xa771, 0xa778,
+	0xfb00, 0xfb06,
+	0xfb13, 0xfb17,
+	0xff41, 0xff5a,
+	0x10428, 0x1044f,
+	0x1d41a, 0x1d433,
+	0x1d44e, 0x1d454,
+	0x1d456, 0x1d467,
+	0x1d482, 0x1d49b,
+	0x1d4b6, 0x1d4b9,
+	0x1d4bd, 0x1d4c3,
+	0x1d4c5, 0x1d4cf,
+	0x1d4ea, 0x1d503,
+	0x1d51e, 0x1d537,
+	0x1d552, 0x1d56b,
+	0x1d586, 0x1d59f,
+	0x1d5ba, 0x1d5d3,
+	0x1d5ee, 0x1d607,
+	0x1d622, 0x1d63b,
+	0x1d656, 0x1d66f,
+	0x1d68a, 0x1d6a5,
+	0x1d6c2, 0x1d6da,
+	0x1d6dc, 0x1d6e1,
+	0x1d6fc, 0x1d714,
+	0x1d716, 0x1d71b,
+	0x1d736, 0x1d74e,
+	0x1d750, 0x1d755,
+	0x1d770, 0x1d788,
+	0x1d78a, 0x1d78f,
+	0x1d7aa, 0x1d7c2,
+	0x1d7c4, 0x1d7c9,
+};
+
+static Rune __islowerp[] = {
+	0x0101, 0x0135,
+	0x013a, 0x0146,
+	0x014b, 0x0177,
+	0x017a, 0x017c,
+	0x0183, 0x0185,
+	0x01a1, 0x01a5,
+	0x01b4, 0x01b6,
+	0x01cc, 0x01da,
+	0x01df, 0x01ed,
+	0x01f3, 0x01f5,
+	0x01f9, 0x0231,
+	0x0247, 0x024d,
+	0x0371, 0x0373,
+	0x03d9, 0x03ed,
+	0x0461, 0x0481,
+	0x048b, 0x04bf,
+	0x04c2, 0x04cc,
+	0x04d1, 0x0527,
+	0x1e01, 0x1e93,
+	0x1e9f, 0x1efd,
+	0x2c68, 0x2c6c,
+	0x2c81, 0x2ce1,
+	0x2cec, 0x2cee,
+	0xa641, 0xa66d,
+	0xa681, 0xa697,
+	0xa723, 0xa72d,
+	0xa733, 0xa76f,
+	0xa77a, 0xa77c,
+	0xa77f, 0xa787,
+	0xa78c, 0xa78e,
+	0xa791, 0xa793,
+	0xa7a1, 0xa7a9,
+};
+
+static Rune __islowers[] = {
+	0x00b5,
+	0x0188,
+	0x0192,
+	0x0195,
+	0x019e,
+	0x01a8,
+	0x01ad,
+	0x01b0,
+	0x01c6,
+	0x01c9,
+	0x023c,
+	0x0242,
+	0x0377,
+	0x0390,
+	0x03f5,
+	0x03f8,
+	0x1fbe,
+	0x210a,
+	0x2113,
+	0x212f,
+	0x2134,
+	0x2139,
+	0x214e,
+	0x2184,
+	0x2c61,
+	0x2c71,
+	0x2cf3,
+	0x2d27,
+	0x2d2d,
+	0xa7fa,
+	0x1d4bb,
+	0x1d7cb,
+};
+
+int
+islowerrune(Rune c)
+{
+	Rune *p;
+
+	p = rbsearch(c, __islowerr, nelem(__islowerr)/2, 2);
+	if(p && c >= p[0] && c <= p[1])
+		return 1;
+	p = rbsearch(c, __islowerp, nelem(__islowerp)/2, 2);
+	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
+		return 1;
+	p = rbsearch(c, __islowers, nelem(__islowers), 1);
+	if(p && c == p[0])
+		return 1;
+	return 0;
+}
+
+static Rune __istitler[] = {
+	0x0041, 0x005a,
+	0x00c0, 0x00d6,
+	0x00d8, 0x00de,
+	0x0178, 0x0179,
+	0x0181, 0x0182,
+	0x0186, 0x0187,
+	0x0189, 0x018b,
+	0x018e, 0x0191,
+	0x0193, 0x0194,
+	0x0196, 0x0198,
+	0x019c, 0x019d,
+	0x019f, 0x01a0,
+	0x01a6, 0x01a7,
+	0x01ae, 0x01af,
+	0x01b1, 0x01b3,
+	0x01b7, 0x01b8,
+	0x01f6, 0x01f8,
+	0x023a, 0x023b,
+	0x023d, 0x023e,
+	0x0243, 0x0246,
+	0x0388, 0x038a,
+	0x038e, 0x038f,
+	0x0391, 0x03a1,
+	0x03a3, 0x03ab,
+	0x03f9, 0x03fa,
+	0x03fd, 0x042f,
+	0x04c0, 0x04c1,
+	0x0531, 0x0556,
+	0x10a0, 0x10c5,
+	0x1f08, 0x1f0f,
+	0x1f18, 0x1f1d,
+	0x1f28, 0x1f2f,
+	0x1f38, 0x1f3f,
+	0x1f48, 0x1f4d,
+	0x1f68, 0x1f6f,
+	0x1f88, 0x1f8f,
+	0x1f98, 0x1f9f,
+	0x1fa8, 0x1faf,
+	0x1fb8, 0x1fbc,
+	0x1fc8, 0x1fcc,
+	0x1fd8, 0x1fdb,
+	0x1fe8, 0x1fec,
+	0x1ff8, 0x1ffc,
+	0x2160, 0x216f,
+	0x24b6, 0x24cf,
+	0x2c00, 0x2c2e,
+	0x2c62, 0x2c64,
+	0x2c6d, 0x2c70,
+	0x2c7e, 0x2c80,
+	0xa77d, 0xa77e,
+	0xff21, 0xff3a,
+	0x10400, 0x10427,
+};
+
+static Rune __istitlep[] = {
+	0x0100, 0x012e,
+	0x0132, 0x0136,
+	0x0139, 0x0147,
+	0x014a, 0x0176,
+	0x017b, 0x017d,
+	0x01a2, 0x01a4,
+	0x01cb, 0x01db,
+	0x01de, 0x01ee,
+	0x01f2, 0x01f4,
+	0x01fa, 0x0232,
+	0x0248, 0x024e,
+	0x0370, 0x0372,
+	0x03d8, 0x03ee,
+	0x0460, 0x0480,
+	0x048a, 0x04be,
+	0x04c3, 0x04cd,
+	0x04d0, 0x0526,
+	0x1e00, 0x1e94,
+	0x1ea0, 0x1efe,
+	0x1f59, 0x1f5f,
+	0x2c67, 0x2c6b,
+	0x2c82, 0x2ce2,
+	0x2ceb, 0x2ced,
+	0xa640, 0xa66c,
+	0xa680, 0xa696,
+	0xa722, 0xa72e,
+	0xa732, 0xa76e,
+	0xa779, 0xa77b,
+	0xa780, 0xa786,
+	0xa78b, 0xa78d,
+	0xa790, 0xa792,
+	0xa7a0, 0xa7aa,
+};
+
+static Rune __istitles[] = {
+	0x0184,
+	0x01a9,
+	0x01ac,
+	0x01b5,
+	0x01bc,
+	0x01c5,
+	0x01c8,
+	0x0241,
+	0x0376,
+	0x0386,
+	0x038c,
+	0x03cf,
+	0x03f7,
+	0x10c7,
+	0x10cd,
+	0x2132,
+	0x2183,
+	0x2c60,
+	0x2c72,
+	0x2c75,
+	0x2cf2,
+};
+
+int
+istitlerune(Rune c)
+{
+	Rune *p;
+
+	p = rbsearch(c, __istitler, nelem(__istitler)/2, 2);
+	if(p && c >= p[0] && c <= p[1])
+		return 1;
+	p = rbsearch(c, __istitlep, nelem(__istitlep)/2, 2);
+	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
+		return 1;
+	p = rbsearch(c, __istitles, nelem(__istitles), 1);
+	if(p && c == p[0])
+		return 1;
+	return 0;
+}
+
+static Rune __toupperr[] = {
+	0x0061, 0x007a, 1048544,
+	0x00e0, 0x00f6, 1048544,
+	0x00f8, 0x00fe, 1048544,
+	0x023f, 0x0240, 1059391,
+	0x0256, 0x0257, 1048371,
+	0x028a, 0x028b, 1048359,
+	0x037b, 0x037d, 1048706,
+	0x03ad, 0x03af, 1048539,
+	0x03b1, 0x03c1, 1048544,
+	0x03c3, 0x03cb, 1048544,
+	0x03cd, 0x03ce, 1048513,
+	0x0430, 0x044f, 1048544,
+	0x0450, 0x045f, 1048496,
+	0x0561, 0x0586, 1048528,
+	0x1f00, 0x1f07, 1048584,
+	0x1f10, 0x1f15, 1048584,
+	0x1f20, 0x1f27, 1048584,
+	0x1f30, 0x1f37, 1048584,
+	0x1f40, 0x1f45, 1048584,
+	0x1f60, 0x1f67, 1048584,
+	0x1f70, 0x1f71, 1048650,
+	0x1f72, 0x1f75, 1048662,
+	0x1f76, 0x1f77, 1048676,
+	0x1f78, 0x1f79, 1048704,
+	0x1f7a, 0x1f7b, 1048688,
+	0x1f7c, 0x1f7d, 1048702,
+	0x1f80, 0x1f87, 1048584,
+	0x1f90, 0x1f97, 1048584,
+	0x1fa0, 0x1fa7, 1048584,
+	0x1fb0, 0x1fb1, 1048584,
+	0x1fd0, 0x1fd1, 1048584,
+	0x1fe0, 0x1fe1, 1048584,
+	0x2170, 0x217f, 1048560,
+	0x24d0, 0x24e9, 1048550,
+	0x2c30, 0x2c5e, 1048528,
+	0x2d00, 0x2d25, 1041312,
+	0xff41, 0xff5a, 1048544,
+	0x10428, 0x1044f, 1048536,
+};
+
+static Rune __toupperp[] = {
+	0x0101, 0x012f, 1048575,
+	0x0133, 0x0137, 1048575,
+	0x013a, 0x0148, 1048575,
+	0x014b, 0x0177, 1048575,
+	0x017a, 0x017e, 1048575,
+	0x0183, 0x0185, 1048575,
+	0x01a1, 0x01a5, 1048575,
+	0x01b4, 0x01b6, 1048575,
+	0x01ce, 0x01dc, 1048575,
+	0x01df, 0x01ef, 1048575,
+	0x01f9, 0x021f, 1048575,
+	0x0223, 0x0233, 1048575,
+	0x0247, 0x024f, 1048575,
+	0x0371, 0x0373, 1048575,
+	0x03d9, 0x03ef, 1048575,
+	0x0461, 0x0481, 1048575,
+	0x048b, 0x04bf, 1048575,
+	0x04c2, 0x04ce, 1048575,
+	0x04d1, 0x0527, 1048575,
+	0x1e01, 0x1e95, 1048575,
+	0x1ea1, 0x1eff, 1048575,
+	0x1f51, 0x1f57, 1048584,
+	0x2c68, 0x2c6c, 1048575,
+	0x2c81, 0x2ce3, 1048575,
+	0x2cec, 0x2cee, 1048575,
+	0xa641, 0xa66d, 1048575,
+	0xa681, 0xa697, 1048575,
+	0xa723, 0xa72f, 1048575,
+	0xa733, 0xa76f, 1048575,
+	0xa77a, 0xa77c, 1048575,
+	0xa77f, 0xa787, 1048575,
+	0xa791, 0xa793, 1048575,
+	0xa7a1, 0xa7a9, 1048575,
+};
+
+static Rune __touppers[] = {
+	0x00b5, 1049319,
+	0x00ff, 1048697,
+	0x0131, 1048344,
+	0x017f, 1048276,
+	0x0180, 1048771,
+	0x0188, 1048575,
+	0x018c, 1048575,
+	0x0192, 1048575,
+	0x0195, 1048673,
+	0x0199, 1048575,
+	0x019a, 1048739,
+	0x019e, 1048706,
+	0x01a8, 1048575,
+	0x01ad, 1048575,
+	0x01b0, 1048575,
+	0x01b9, 1048575,
+	0x01bd, 1048575,
+	0x01bf, 1048632,
+	0x01c5, 1048575,
+	0x01c6, 1048574,
+	0x01c8, 1048575,
+	0x01c9, 1048574,
+	0x01cb, 1048575,
+	0x01cc, 1048574,
+	0x01dd, 1048497,
+	0x01f2, 1048575,
+	0x01f3, 1048574,
+	0x01f5, 1048575,
+	0x023c, 1048575,
+	0x0242, 1048575,
+	0x0250, 1059359,
+	0x0251, 1059356,
+	0x0252, 1059358,
+	0x0253, 1048366,
+	0x0254, 1048370,
+	0x0259, 1048374,
+	0x025b, 1048373,
+	0x0260, 1048371,
+	0x0263, 1048369,
+	0x0265, 1090856,
+	0x0266, 1090884,
+	0x0268, 1048367,
+	0x0269, 1048365,
+	0x026b, 1059319,
+	0x026f, 1048365,
+	0x0271, 1059325,
+	0x0272, 1048363,
+	0x0275, 1048362,
+	0x027d, 1059303,
+	0x0280, 1048358,
+	0x0283, 1048358,
+	0x0288, 1048358,
+	0x0289, 1048507,
+	0x028c, 1048505,
+	0x0292, 1048357,
+	0x0345, 1048660,
+	0x0377, 1048575,
+	0x03ac, 1048538,
+	0x03c2, 1048545,
+	0x03cc, 1048512,
+	0x03d0, 1048514,
+	0x03d1, 1048519,
+	0x03d5, 1048529,
+	0x03d6, 1048522,
+	0x03d7, 1048568,
+	0x03f0, 1048490,
+	0x03f1, 1048496,
+	0x03f2, 1048583,
+	0x03f5, 1048480,
+	0x03f8, 1048575,
+	0x03fb, 1048575,
+	0x04cf, 1048561,
+	0x1d79, 1083908,
+	0x1d7d, 1052390,
+	0x1e9b, 1048517,
+	0x1fb3, 1048585,
+	0x1fbe, 1041371,
+	0x1fc3, 1048585,
+	0x1fe5, 1048583,
+	0x1ff3, 1048585,
+	0x214e, 1048548,
+	0x2184, 1048575,
+	0x2c61, 1048575,
+	0x2c65, 1037781,
+	0x2c66, 1037784,
+	0x2c73, 1048575,
+	0x2c76, 1048575,
+	0x2cf3, 1048575,
+	0x2d27, 1041312,
+	0x2d2d, 1041312,
+	0xa78c, 1048575,
+};
+
+Rune
+toupperrune(Rune c)
+{
+	Rune *p;
+
+	p = rbsearch(c, __toupperr, nelem(__toupperr)/3, 3);
+	if(p && c >= p[0] && c <= p[1])
+		return c + p[2] - 1048576;
+	p = rbsearch(c, __toupperp, nelem(__toupperp)/3, 3);
+	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
+		return c + p[2] - 1048576;
+	p = rbsearch(c, __touppers, nelem(__touppers)/2, 2);
+	if(p && c == p[0])
+		return c + p[1] - 1048576;
+	return c;
+}
+
+static Rune __tolowerr[] = {
+	0x0041, 0x005a, 1048608,
+	0x00c0, 0x00d6, 1048608,
+	0x00d8, 0x00de, 1048608,
+	0x0189, 0x018a, 1048781,
+	0x01b1, 0x01b2, 1048793,
+	0x0388, 0x038a, 1048613,
+	0x038e, 0x038f, 1048639,
+	0x0391, 0x03a1, 1048608,
+	0x03a3, 0x03ab, 1048608,
+	0x03fd, 0x03ff, 1048446,
+	0x0400, 0x040f, 1048656,
+	0x0410, 0x042f, 1048608,
+	0x0531, 0x0556, 1048624,
+	0x10a0, 0x10c5, 1055840,
+	0x1f08, 0x1f0f, 1048568,
+	0x1f18, 0x1f1d, 1048568,
+	0x1f28, 0x1f2f, 1048568,
+	0x1f38, 0x1f3f, 1048568,
+	0x1f48, 0x1f4d, 1048568,
+	0x1f68, 0x1f6f, 1048568,
+	0x1f88, 0x1f8f, 1048568,
+	0x1f98, 0x1f9f, 1048568,
+	0x1fa8, 0x1faf, 1048568,
+	0x1fb8, 0x1fb9, 1048568,
+	0x1fba, 0x1fbb, 1048502,
+	0x1fc8, 0x1fcb, 1048490,
+	0x1fd8, 0x1fd9, 1048568,
+	0x1fda, 0x1fdb, 1048476,
+	0x1fe8, 0x1fe9, 1048568,
+	0x1fea, 0x1feb, 1048464,
+	0x1ff8, 0x1ff9, 1048448,
+	0x1ffa, 0x1ffb, 1048450,
+	0x2160, 0x216f, 1048592,
+	0x24b6, 0x24cf, 1048602,
+	0x2c00, 0x2c2e, 1048624,
+	0x2c7e, 0x2c7f, 1037761,
+	0xff21, 0xff3a, 1048608,
+	0x10400, 0x10427, 1048616,
+};
+
+static Rune __tolowerp[] = {
+	0x0100, 0x012e, 1048577,
+	0x0132, 0x0136, 1048577,
+	0x0139, 0x0147, 1048577,
+	0x014a, 0x0176, 1048577,
+	0x017b, 0x017d, 1048577,
+	0x01a2, 0x01a4, 1048577,
+	0x01b3, 0x01b5, 1048577,
+	0x01cd, 0x01db, 1048577,
+	0x01de, 0x01ee, 1048577,
+	0x01f8, 0x021e, 1048577,
+	0x0222, 0x0232, 1048577,
+	0x0248, 0x024e, 1048577,
+	0x0370, 0x0372, 1048577,
+	0x03d8, 0x03ee, 1048577,
+	0x0460, 0x0480, 1048577,
+	0x048a, 0x04be, 1048577,
+	0x04c3, 0x04cd, 1048577,
+	0x04d0, 0x0526, 1048577,
+	0x1e00, 0x1e94, 1048577,
+	0x1ea0, 0x1efe, 1048577,
+	0x1f59, 0x1f5f, 1048568,
+	0x2c67, 0x2c6b, 1048577,
+	0x2c80, 0x2ce2, 1048577,
+	0x2ceb, 0x2ced, 1048577,
+	0xa640, 0xa66c, 1048577,
+	0xa680, 0xa696, 1048577,
+	0xa722, 0xa72e, 1048577,
+	0xa732, 0xa76e, 1048577,
+	0xa779, 0xa77b, 1048577,
+	0xa780, 0xa786, 1048577,
+	0xa790, 0xa792, 1048577,
+	0xa7a0, 0xa7a8, 1048577,
+};
+
+static Rune __tolowers[] = {
+	0x0130, 1048377,
+	0x0178, 1048455,
+	0x0179, 1048577,
+	0x0181, 1048786,
+	0x0182, 1048577,
+	0x0184, 1048577,
+	0x0186, 1048782,
+	0x0187, 1048577,
+	0x018b, 1048577,
+	0x018e, 1048655,
+	0x018f, 1048778,
+	0x0190, 1048779,
+	0x0191, 1048577,
+	0x0193, 1048781,
+	0x0194, 1048783,
+	0x0196, 1048787,
+	0x0197, 1048785,
+	0x0198, 1048577,
+	0x019c, 1048787,
+	0x019d, 1048789,
+	0x019f, 1048790,
+	0x01a0, 1048577,
+	0x01a6, 1048794,
+	0x01a7, 1048577,
+	0x01a9, 1048794,
+	0x01ac, 1048577,
+	0x01ae, 1048794,
+	0x01af, 1048577,
+	0x01b7, 1048795,
+	0x01b8, 1048577,
+	0x01bc, 1048577,
+	0x01c4, 1048578,
+	0x01c5, 1048577,
+	0x01c7, 1048578,
+	0x01c8, 1048577,
+	0x01ca, 1048578,
+	0x01cb, 1048577,
+	0x01f1, 1048578,
+	0x01f2, 1048577,
+	0x01f4, 1048577,
+	0x01f6, 1048479,
+	0x01f7, 1048520,
+	0x0220, 1048446,
+	0x023a, 1059371,
+	0x023b, 1048577,
+	0x023d, 1048413,
+	0x023e, 1059368,
+	0x0241, 1048577,
+	0x0243, 1048381,
+	0x0244, 1048645,
+	0x0245, 1048647,
+	0x0246, 1048577,
+	0x0376, 1048577,
+	0x0386, 1048614,
+	0x038c, 1048640,
+	0x03cf, 1048584,
+	0x03f4, 1048516,
+	0x03f7, 1048577,
+	0x03f9, 1048569,
+	0x03fa, 1048577,
+	0x04c0, 1048591,
+	0x04c1, 1048577,
+	0x10c7, 1055840,
+	0x10cd, 1055840,
+	0x1e9e, 1040961,
+	0x1fbc, 1048567,
+	0x1fcc, 1048567,
+	0x1fec, 1048569,
+	0x1ffc, 1048567,
+	0x2126, 1041059,
+	0x212a, 1040193,
+	0x212b, 1040314,
+	0x2132, 1048604,
+	0x2183, 1048577,
+	0x2c60, 1048577,
+	0x2c62, 1037833,
+	0x2c63, 1044762,
+	0x2c64, 1037849,
+	0x2c6d, 1037796,
+	0x2c6e, 1037827,
+	0x2c6f, 1037793,
+	0x2c70, 1037794,
+	0x2c72, 1048577,
+	0x2c75, 1048577,
+	0x2cf2, 1048577,
+	0xa77d, 1013244,
+	0xa77e, 1048577,
+	0xa78b, 1048577,
+	0xa78d, 1006296,
+	0xa7aa, 1006268,
+};
+
+Rune
+tolowerrune(Rune c)
+{
+	Rune *p;
+
+	p = rbsearch(c, __tolowerr, nelem(__tolowerr)/3, 3);
+	if(p && c >= p[0] && c <= p[1])
+		return c + p[2] - 1048576;
+	p = rbsearch(c, __tolowerp, nelem(__tolowerp)/3, 3);
+	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
+		return c + p[2] - 1048576;
+	p = rbsearch(c, __tolowers, nelem(__tolowers)/2, 2);
+	if(p && c == p[0])
+		return c + p[1] - 1048576;
+	return c;
+}
+
+static Rune __totitler[] = {
+	0x0061, 0x007a, 1048544,
+	0x00e0, 0x00f6, 1048544,
+	0x00f8, 0x00fe, 1048544,
+	0x023f, 0x0240, 1059391,
+	0x0256, 0x0257, 1048371,
+	0x028a, 0x028b, 1048359,
+	0x037b, 0x037d, 1048706,
+	0x03ad, 0x03af, 1048539,
+	0x03b1, 0x03c1, 1048544,
+	0x03c3, 0x03cb, 1048544,
+	0x03cd, 0x03ce, 1048513,
+	0x0430, 0x044f, 1048544,
+	0x0450, 0x045f, 1048496,
+	0x0561, 0x0586, 1048528,
+	0x1f00, 0x1f07, 1048584,
+	0x1f10, 0x1f15, 1048584,
+	0x1f20, 0x1f27, 1048584,
+	0x1f30, 0x1f37, 1048584,
+	0x1f40, 0x1f45, 1048584,
+	0x1f60, 0x1f67, 1048584,
+	0x1f70, 0x1f71, 1048650,
+	0x1f72, 0x1f75, 1048662,
+	0x1f76, 0x1f77, 1048676,
+	0x1f78, 0x1f79, 1048704,
+	0x1f7a, 0x1f7b, 1048688,
+	0x1f7c, 0x1f7d, 1048702,
+	0x1f80, 0x1f87, 1048584,
+	0x1f90, 0x1f97, 1048584,
+	0x1fa0, 0x1fa7, 1048584,
+	0x1fb0, 0x1fb1, 1048584,
+	0x1fd0, 0x1fd1, 1048584,
+	0x1fe0, 0x1fe1, 1048584,
+	0x2170, 0x217f, 1048560,
+	0x24d0, 0x24e9, 1048550,
+	0x2c30, 0x2c5e, 1048528,
+	0x2d00, 0x2d25, 1041312,
+	0xff41, 0xff5a, 1048544,
+	0x10428, 0x1044f, 1048536,
+};
+
+static Rune __totitlep[] = {
+	0x0101, 0x012f, 1048575,
+	0x0133, 0x0137, 1048575,
+	0x013a, 0x0148, 1048575,
+	0x014b, 0x0177, 1048575,
+	0x017a, 0x017e, 1048575,
+	0x0183, 0x0185, 1048575,
+	0x01a1, 0x01a5, 1048575,
+	0x01b4, 0x01b6, 1048575,
+	0x01cc, 0x01dc, 1048575,
+	0x01df, 0x01ef, 1048575,
+	0x01f3, 0x01f5, 1048575,
+	0x01f9, 0x021f, 1048575,
+	0x0223, 0x0233, 1048575,
+	0x0247, 0x024f, 1048575,
+	0x0371, 0x0373, 1048575,
+	0x03d9, 0x03ef, 1048575,
+	0x0461, 0x0481, 1048575,
+	0x048b, 0x04bf, 1048575,
+	0x04c2, 0x04ce, 1048575,
+	0x04d1, 0x0527, 1048575,
+	0x1e01, 0x1e95, 1048575,
+	0x1ea1, 0x1eff, 1048575,
+	0x1f51, 0x1f57, 1048584,
+	0x2c68, 0x2c6c, 1048575,
+	0x2c81, 0x2ce3, 1048575,
+	0x2cec, 0x2cee, 1048575,
+	0xa641, 0xa66d, 1048575,
+	0xa681, 0xa697, 1048575,
+	0xa723, 0xa72f, 1048575,
+	0xa733, 0xa76f, 1048575,
+	0xa77a, 0xa77c, 1048575,
+	0xa77f, 0xa787, 1048575,
+	0xa791, 0xa793, 1048575,
+	0xa7a1, 0xa7a9, 1048575,
+};
+
+static Rune __totitles[] = {
+	0x00b5, 1049319,
+	0x00ff, 1048697,
+	0x0131, 1048344,
+	0x017f, 1048276,
+	0x0180, 1048771,
+	0x0188, 1048575,
+	0x018c, 1048575,
+	0x0192, 1048575,
+	0x0195, 1048673,
+	0x0199, 1048575,
+	0x019a, 1048739,
+	0x019e, 1048706,
+	0x01a8, 1048575,
+	0x01ad, 1048575,
+	0x01b0, 1048575,
+	0x01b9, 1048575,
+	0x01bd, 1048575,
+	0x01bf, 1048632,
+	0x01c4, 1048577,
+	0x01c6, 1048575,
+	0x01c7, 1048577,
+	0x01c9, 1048575,
+	0x01ca, 1048577,
+	0x01dd, 1048497,
+	0x01f1, 1048577,
+	0x023c, 1048575,
+	0x0242, 1048575,
+	0x0250, 1059359,
+	0x0251, 1059356,
+	0x0252, 1059358,
+	0x0253, 1048366,
+	0x0254, 1048370,
+	0x0259, 1048374,
+	0x025b, 1048373,
+	0x0260, 1048371,
+	0x0263, 1048369,
+	0x0265, 1090856,
+	0x0266, 1090884,
+	0x0268, 1048367,
+	0x0269, 1048365,
+	0x026b, 1059319,
+	0x026f, 1048365,
+	0x0271, 1059325,
+	0x0272, 1048363,
+	0x0275, 1048362,
+	0x027d, 1059303,
+	0x0280, 1048358,
+	0x0283, 1048358,
+	0x0288, 1048358,
+	0x0289, 1048507,
+	0x028c, 1048505,
+	0x0292, 1048357,
+	0x0345, 1048660,
+	0x0377, 1048575,
+	0x03ac, 1048538,
+	0x03c2, 1048545,
+	0x03cc, 1048512,
+	0x03d0, 1048514,
+	0x03d1, 1048519,
+	0x03d5, 1048529,
+	0x03d6, 1048522,
+	0x03d7, 1048568,
+	0x03f0, 1048490,
+	0x03f1, 1048496,
+	0x03f2, 1048583,
+	0x03f5, 1048480,
+	0x03f8, 1048575,
+	0x03fb, 1048575,
+	0x04cf, 1048561,
+	0x1d79, 1083908,
+	0x1d7d, 1052390,
+	0x1e9b, 1048517,
+	0x1fb3, 1048585,
+	0x1fbe, 1041371,
+	0x1fc3, 1048585,
+	0x1fe5, 1048583,
+	0x1ff3, 1048585,
+	0x214e, 1048548,
+	0x2184, 1048575,
+	0x2c61, 1048575,
+	0x2c65, 1037781,
+	0x2c66, 1037784,
+	0x2c73, 1048575,
+	0x2c76, 1048575,
+	0x2cf3, 1048575,
+	0x2d27, 1041312,
+	0x2d2d, 1041312,
+	0xa78c, 1048575,
+};
+
+Rune
+totitlerune(Rune c)
+{
+	Rune *p;
+
+	p = rbsearch(c, __totitler, nelem(__totitler)/3, 3);
+	if(p && c >= p[0] && c <= p[1])
+		return c + p[2] - 1048576;
+	p = rbsearch(c, __totitlep, nelem(__totitlep)/3, 3);
+	if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))
+		return c + p[2] - 1048576;
+	p = rbsearch(c, __totitles, nelem(__totitles)/2, 2);
+	if(p && c == p[0])
+		return c + p[1] - 1048576;
+	return c;
+}
+
diff --git a/src/lib9/windows.c b/src/lib9/windows.c
index 90753bb..d8ee402 100644
--- a/src/lib9/windows.c
+++ b/src/lib9/windows.c
@@ -5,22 +5,26 @@
 #include <u.h>
 #include <libc.h>
 
-int fork()
+int
+fork(void)
 {
 	return -1;
 }
 
-int p9rfork(int flags)
+int
+p9rfork(int flags)
 {
 	return -1;
 }
 
-Waitmsg *p9wait()
+Waitmsg*
+p9wait(void)
 {
 	return 0;
 }
 
-int p9waitpid()
+int
+p9waitpid(void)
 {
 	return -1;
 }
diff --git a/src/libmach/5obj.c b/src/libmach/5obj.c
index e539362..57573b8 100644
--- a/src/libmach/5obj.c
+++ b/src/libmach/5obj.c
@@ -42,6 +42,7 @@ struct Addr
 	char	type;
 	char	sym;
 	char	name;
+	char	gotype;
 };
 static Addr addr(Biobuf*);
 static char type2char(int);
@@ -115,6 +116,7 @@ addr(Biobuf *bp)
 	skip(bp,1);		/* reg */
 	a.sym = Bgetc(bp);	/* sym index */
 	a.name = Bgetc(bp);	/* sym type */
+	a.gotype = Bgetc(bp);	/* go type */
 	switch(a.type){
 	default:
 	case D_NONE:
@@ -124,6 +126,7 @@ addr(Biobuf *bp)
 	case D_FPCR:
 		break;
 	case D_REGREG:
+	case D_REGREG2:
 		Bgetc(bp);
 		break;
 	case D_CONST2:
diff --git a/src/libmach/8db.c b/src/libmach/8db.c
index ce1b4dd..9ef02c4 100644
--- a/src/libmach/8db.c
+++ b/src/libmach/8db.c
@@ -622,6 +622,7 @@ static Optable optab0F[256]=
 [0x15] =	{ RM,0,		"UNPCKH%s	%x,%X" },
 [0x16] =	{ RM,0,		"MOV[L]H%s	%x,%X" },	/* TO DO: L if source is XMM */
 [0x17] =	{ RM,0,		"MOVH%s	%X,%x" },
+[0x1F] =	{ RM,0,		"NOP%S	%e" },
 [0x20] =	{ RMR,0,		"MOVL	%C,%e" },
 [0x21] =	{ RMR,0,		"MOVL	%D,%e" },
 [0x22] =	{ RMR,0,		"MOVL	%e,%C" },
diff --git a/src/libmach/darwin.c b/src/libmach/darwin.c
index 63abde3..753d940 100644
--- a/src/libmach/darwin.c
+++ b/src/libmach/darwin.c
@@ -751,7 +751,7 @@ havet:
 static void*
 excthread(void *v)
 {
-	extern boolean_t exc_server();
+	extern boolean_t exc_server(mach_msg_header_t *, mach_msg_header_t *);
 	mach_msg_server(exc_server, 2048, excport, 0);
 	return 0;
 }
diff --git a/src/libmach/executable.c b/src/libmach/executable.c
index 3db3e7d..a93a8c2 100644
--- a/src/libmach/executable.c
+++ b/src/libmach/executable.c
@@ -1091,12 +1091,21 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
 	}
 
 	cmdbuf = malloc(mp->sizeofcmds);
+	if(!cmdbuf) {
+		werrstr("out of memory");
+		return 0;
+	}
 	seek(fd, hdrsize, 0);
 	if(read(fd, cmdbuf, mp->sizeofcmds) != mp->sizeofcmds) {
 		free(cmdbuf);
 		return 0;
 	}
 	cmd = malloc(mp->ncmds * sizeof(MachCmd*));
+	if(!cmd) {
+		free(cmdbuf);
+		werrstr("out of memory");
+		return 0;
+	}
 	cmdp = cmdbuf;
 	textva = 0;
 	textoff = 0;
@@ -1340,12 +1349,12 @@ static int
 pedotout(int fd, Fhdr *fp, ExecHdr *hp)
 {
 	uint32 start, magic;
-	uint32 symtab, esymtab;
+	uint32 symtab, esymtab, pclntab, epclntab;
 	IMAGE_FILE_HEADER fh;
 	IMAGE_SECTION_HEADER sh;
 	IMAGE_OPTIONAL_HEADER oh;
 	uint8 sym[18];
-	uint32 *valp;
+	uint32 *valp, ib;
 	int i;
 
 	USED(hp);
@@ -1380,6 +1389,19 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
 		return 0;
 	}
 
+	switch(oh.Magic) {
+	case 0x10b:	// PE32
+		fp->type = FI386;
+		break;
+	case 0x20b:	// PE32+
+		fp->type = FAMD64;
+		break;
+	default:
+		werrstr("invalid PE Optional magic number");
+		return 0;
+	}
+
+	ib=leswal(oh.ImageBase);
 	seek(fd, start+sizeof(magic)+sizeof(fh)+leswab(fh.SizeOfOptionalHeader), 0);
 	fp->txtaddr = 0;
 	fp->dataddr = 0;
@@ -1389,9 +1411,9 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
 			return 0;
 		}
 		if (match8(sh.Name, ".text"))
-			settext(fp, leswal(sh.VirtualAddress), leswal(oh.AddressOfEntryPoint), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
+			settext(fp, ib+leswal(oh.AddressOfEntryPoint), ib+leswal(sh.VirtualAddress), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
 		if (match8(sh.Name, ".data"))
-			setdata(fp, leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
+			setdata(fp, ib+leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
 	}
 	if (fp->txtaddr==0 || fp->dataddr==0) {
 		werrstr("no .text or .data");
@@ -1399,7 +1421,7 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
 	}
 
 	seek(fd, leswal(fh.PointerToSymbolTable), 0);
-	symtab = esymtab = 0;
+	symtab = esymtab = pclntab = epclntab = 0;
 	for (i=0; i<leswal(fh.NumberOfSymbols); i++) {
 		if (readn(fd, sym, sizeof(sym)) != sizeof(sym)) {
 			werrstr("crippled COFF symbol %d", i);
@@ -1410,12 +1432,16 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
 			symtab = leswal(*valp);
 		if (match8(sym, "esymtab"))
 			esymtab = leswal(*valp);
+		if (match8(sym, "pclntab"))
+			pclntab = leswal(*valp);
+		if (match8(sym, "epclntab"))
+			epclntab = leswal(*valp);
 	}
-	if (symtab==0 || esymtab==0) {
-		werrstr("no symtab or esymtab in COFF symbol table");
+	if (symtab==0 || esymtab==0 || pclntab==0 || epclntab==0) {
+		werrstr("no symtab or esymtab or pclntab or epclntab in COFF symbol table");
 		return 0;
 	}
-	setsym(fp, symtab, esymtab-symtab, 0, 0, 0, 0);
+	setsym(fp, symtab, esymtab-symtab, 0, 0, pclntab, epclntab-pclntab);
 
 	return 1;
 }
diff --git a/src/libmach/obj.c b/src/libmach/obj.c
index 7999f24..2a5e047 100644
--- a/src/libmach/obj.c
+++ b/src/libmach/obj.c
@@ -293,6 +293,8 @@ objlookup(int id, char *name, int type, uint sig)
 			}
 	}
 	sp = malloc(sizeof(Symtab));
+	if(sp == nil)
+		sysfatal("out of memory");
 	sp->s.name = name;
 	sp->s.type = type;
 	sp->s.sig = sig;
diff --git a/src/libmach/sym.c b/src/libmach/sym.c
index 1512d7a..120328d 100644
--- a/src/libmach/sym.c
+++ b/src/libmach/sym.c
@@ -1,11 +1,11 @@
 // Inferno libmach/sym.c
 // http://code.google.com/p/inferno-os/source/browse/utils/libmach/sym.c
 //
-// 	Copyright © 1994-1999 Lucent Technologies Inc.
-// 	Power PC support Copyright © 1995-2004 C H Forsyth (forsyth at terzarima.net).
-// 	Portions Copyright © 1997-1999 Vita Nuova Limited.
-// 	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// 	Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
+//	Copyright © 1994-1999 Lucent Technologies Inc.
+//	Power PC support Copyright © 1995-2004 C H Forsyth (forsyth at terzarima.net).
+//	Portions Copyright © 1997-1999 Vita Nuova Limited.
+//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
+//	Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
 //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -112,13 +112,19 @@ syminit(int fd, Fhdr *fp)
 	int32 i, l, size;
 	vlong vl;
 	Biobuf b;
-	int svalsz;
+	int svalsz, newformat, shift;
+	uvlong (*swav)(uvlong);
+	uint32 (*swal)(uint32);
+	uchar buf[8], c;
 
 	if(fp->symsz == 0)
 		return 0;
 	if(fp->type == FNONE)
 		return 0;
 
+	swav = beswav;
+	swal = beswal;
+
 	cleansyms();
 	textseg(fp->txtaddr, fp);
 		/* minimum symbol record size = 4+1+2 bytes */
@@ -129,40 +135,128 @@ syminit(int fd, Fhdr *fp)
 	}
 	Binit(&b, fd, OREAD);
 	Bseek(&b, fp->symoff, 0);
+	memset(buf, 0, sizeof buf);
+	Bread(&b, buf, sizeof buf);
+	newformat = 0;
+	if(memcmp(buf, "\xfd\xff\xff\xff\x00\x00\x00", 7) == 0) {
+		swav = leswav;
+		swal = leswal;
+		newformat = 1;
+	} else if(memcmp(buf, "\xff\xff\xff\xfd\x00\x00\x00", 7) == 0) {
+		newformat = 1;
+	} else if(memcmp(buf, "\xfe\xff\xff\xff\x00\x00", 6) == 0) {
+		// Table format used between Go 1.0 and Go 1.1:
+		// little-endian but otherwise same as the old Go 1.0 table.
+		// Not likely to be seen much in practice, but easy to handle.
+		swav = leswav;
+		swal = leswal;
+		Bseek(&b, fp->symoff+6, 0);
+	} else {
+		Bseek(&b, fp->symoff, 0);
+	}
+	svalsz = 0;
+	if(newformat) {
+		svalsz = buf[7];
+		if(svalsz != 4 && svalsz != 8) {
+			werrstr("invalid word size %d bytes", svalsz);
+			return -1;
+		}
+	}
+
 	nsym = 0;
 	size = 0;
 	for(p = symbols; size < fp->symsz; p++, nsym++) {
-		if(fp->_magic && (fp->magic & HDR_MAGIC)){
-			svalsz = 8;
-			if(Bread(&b, &vl, 8) != 8)
-				return symerrmsg(8, "symbol");
-			p->value = beswav(vl);
-		}
-		else{
-			svalsz = 4;
-			if(Bread(&b, &l, 4) != 4)
-				return symerrmsg(4, "symbol");
-			p->value = (u32int)beswal(l);
-		}
-		if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type))
-			return symerrmsg(sizeof(p->value), "symbol");
-
-		i = decodename(&b, p);
-		if(i < 0)
-			return -1;
-		size += i+svalsz+sizeof(p->type);
-
-		if(svalsz == 8){
-			if(Bread(&b, &vl, 8) != 8)
-				return symerrmsg(8, "symbol");
-			p->gotype = beswav(vl);
-		}
-		else{
-			if(Bread(&b, &l, 4) != 4)
-				return symerrmsg(4, "symbol");
-			p->gotype = (u32int)beswal(l);
+		if(newformat) {
+			// Go 1.1 format. See comment at top of ../pkg/runtime/symtab.c.
+			if(Bread(&b, &c, 1) != 1)
+				return symerrmsg(1, "symbol");
+			if((c&0x3F) < 26)
+				p->type = (c&0x3F)+ 'A';
+			else
+				p->type = (c&0x3F) - 26 + 'a';
+			size++;
+
+			if(c&0x40) {
+				// Fixed-width address.
+				if(svalsz == 8) {
+					if(Bread(&b, &vl, 8) != 8)
+						return symerrmsg(8, "symbol");
+					p->value = swav(vl);
+				} else {
+					if(Bread(&b, &l, 4) != 4)
+						return symerrmsg(4, "symbol");
+					p->value = (u32int)swal(l);
+				}
+				size += svalsz;
+			} else {
+				// Varint address.
+				shift = 0;
+				p->value = 0;
+				for(;;) {
+					if(Bread(&b, buf, 1) != 1)
+						return symerrmsg(1, "symbol");
+					p->value |= (uint64)(buf[0]&0x7F)<<shift;
+					shift += 7;
+					size++;
+					if((buf[0]&0x80) == 0)
+						break;
+				}
+			}
+			p->gotype = 0;
+			if(c&0x80) {
+				// Has Go type. Fixed-width address.
+				if(svalsz == 8) {
+					if(Bread(&b, &vl, 8) != 8)
+						return symerrmsg(8, "symbol");
+					p->gotype = swav(vl);
+				} else {
+					if(Bread(&b, &l, 4) != 4)
+						return symerrmsg(4, "symbol");
+					p->gotype = (u32int)swal(l);
+				}
+				size += svalsz;
+			}
+			
+			// Name.
+			p->type |= 0x80; // for decodename
+			i = decodename(&b, p);
+			if(i < 0)
+				return -1;
+			size += i;
+		} else {
+			// Go 1.0 format: Plan 9 format + go type symbol.
+			if(fp->_magic && (fp->magic & HDR_MAGIC)){
+				svalsz = 8;
+				if(Bread(&b, &vl, 8) != 8)
+					return symerrmsg(8, "symbol");
+				p->value = swav(vl);
+			}
+			else{
+				svalsz = 4;
+				if(Bread(&b, &l, 4) != 4)
+					return symerrmsg(4, "symbol");
+				p->value = (u32int)swal(l);
+			}
+			if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type))
+				return symerrmsg(sizeof(p->value), "symbol");
+	
+			i = decodename(&b, p);
+			if(i < 0)
+				return -1;
+			size += i+svalsz+sizeof(p->type);
+	
+			if(svalsz == 8){
+				if(Bread(&b, &vl, 8) != 8)
+					return symerrmsg(8, "symbol");
+				p->gotype = swav(vl);
+			}
+			else{
+				if(Bread(&b, &l, 4) != 4)
+					return symerrmsg(4, "symbol");
+				p->gotype = (u32int)swal(l);
+			}
+			size += svalsz;
 		}
-		size += svalsz;
 
 		/* count global & auto vars, text symbols, and file names */
 		switch (p->type) {
@@ -576,7 +670,8 @@ lookup(char *fn, char *var, Symbol *s)
  * strcmp, but allow '_' to match center dot (rune 00b7 == bytes c2 b7)
  */
 int
-cdotstrcmp(char *sym, char *user) {
+cdotstrcmp(char *sym, char *user)
+{
 	for (;;) {
 		while (*sym == *user) {
 			if (*sym++ == '\0')
diff --git a/src/libmach/windows.c b/src/libmach/windows.c
index 81fa6b6..aea7bac 100644
--- a/src/libmach/windows.c
+++ b/src/libmach/windows.c
@@ -48,8 +48,12 @@ procthreadpids(int pid, int *p, int np)
 int 
 pread(int fd, void *buf, int count, int offset)
 {
-	sysfatal("pread unimplemented in Windows");
-	return -1;
+	int oldoffset, n;
+	
+	oldoffset = seek(fd, offset, 0);
+	n = read(fd, buf, count);
+	seek(fd, oldoffset, 0);
+	return n;
 }
 
 int 
diff --git a/src/make.bash b/src/make.bash
index b2de37b..2d83b6f 100755
--- a/src/make.bash
+++ b/src/make.bash
@@ -23,9 +23,15 @@
 # GO_LDFLAGS: Additional 5l/6l/8l arguments to use when
 # building the commands.
 #
+# GO_CCFLAGS: Additional 5c/6c/8c arguments to use when
+# building.
+#
 # CGO_ENABLED: Controls cgo usage during the build. Set it to 1
 # to include all cgo related files, .c and .go file with "cgo"
 # build directive, in the build. Set it to 0 to ignore them.
+#
+# CC: Command line to run to get at host C compiler.
+# Default is "gcc". Also supported: "clang".
 
 set -e
 if [ ! -f run.bash ]; then
@@ -77,6 +83,13 @@ do
 	fi
 done
 
+# Test for debian/kFreeBSD.
+# cmd/dist will detect kFreeBSD as freebsd/$GOARCH, but we need to
+# disable cgo manually.
+if [ "$(uname -s)" == "GNU/kFreeBSD" ]; then
+        export CGO_ENABLED=0
+fi
+
 # Clean old generated file that will cause problems in the build.
 rm -f ./pkg/runtime/runtime_defs.go
 
@@ -93,7 +106,7 @@ case "$GOHOSTARCH" in
 386) mflag=-m32;;
 amd64) mflag=-m64;;
 esac
-gcc $mflag -O2 -Wall -Werror -ggdb -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
+${CC:-gcc} $mflag -O2 -Wall -Werror -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
 
 eval $(./cmd/dist/dist env -p)
 echo
@@ -122,12 +135,12 @@ echo
 if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOHOSTOS" != "$GOOS" ]; then
 	echo "# Building packages and commands for host, $GOHOSTOS/$GOHOSTARCH."
 	GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \
-		"$GOTOOLDIR"/go_bootstrap install -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
+		"$GOTOOLDIR"/go_bootstrap install -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
 	echo
 fi
 
 echo "# Building packages and commands for $GOOS/$GOARCH."
-"$GOTOOLDIR"/go_bootstrap install -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
+"$GOTOOLDIR"/go_bootstrap install $GO_FLAGS -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
 echo
 
 rm -f "$GOTOOLDIR"/go_bootstrap
diff --git a/src/make.bat b/src/make.bat
index ec39392..be1c8f5 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/buildruntime.c cmd/dist/goc2c.c cmd/dist/main.c cmd/dist/windows.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/buildruntime.c cmd/dist/goc2c.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
@@ -68,6 +68,9 @@ call env.bat
 del env.bat
 echo.
 
+if x%1==x--dist-tool goto copydist
+if x%2==x--dist-tool goto copydist
+
 echo # Building compilers and Go bootstrap tool.
 set buildall=-a
 if x%1==x--no-clean set buildall=
@@ -105,6 +108,11 @@ if x%1==x--no-banner goto nobanner
 
 goto end
 
+:copydist
+mkdir %GOTOOLDIR% 2>NUL
+copy cmd\dist\dist.exe %GOTOOLDIR%\
+goto end
+
 :fail
 set GOBUILDFAIL=1
 
diff --git a/src/make.rc b/src/make.rc
new file mode 100755
index 0000000..83d16c0
--- /dev/null
+++ b/src/make.rc
@@ -0,0 +1,97 @@
+#!/bin/rc -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.
+
+# Environment variables that control make.rc:
+#
+# GOROOT_FINAL: The expected final Go root, baked into binaries.
+# The default is the location of the Go tree during the build.
+#
+# GOHOSTARCH: The architecture for host tools (compilers and
+# binaries).  Binaries of this type must be executable on the current
+# system, so the only common reason to set this is to set
+# GOHOSTARCH=386 on an amd64 machine.
+#
+# GOARCH: The target architecture for installed packages and tools.
+#
+# GOOS: The target operating system for installed packages and tools.
+#
+# GO_GCFLAGS: Additional 5g/6g/8g arguments to use when
+# building the packages and commands.
+#
+# GO_LDFLAGS: Additional 5l/6l/8l arguments to use when
+# building the commands.
+#
+# GO_CCFLAGS: Additional 5c/6c/8c arguments to use when
+# building.
+#
+# CGO_ENABLED: Controls cgo usage during the build. Set it to 1
+# to include all cgo related files, .c and .go file with "cgo"
+# build directive, in the build. Set it to 0 to ignore them.
+
+rfork e
+if(! test -f run.rc){
+	echo 'make.rc must be run from $GOROOT/src' >[1=2]
+	exit wrongdir
+}
+
+# Clean old generated file that will cause problems in the build.
+rm -f ./pkg/runtime/runtime_defs.go
+
+# Determine the host compiler toolchain.
+eval `{grep '^(CC|LD|O)=' /$objtype/mkfile}
+
+echo '# Building C bootstrap tool.'
+echo cmd/dist
+GOROOT = `{cd .. && pwd}
+if(! ~ $#GOROOT_FINAL 1)
+	GOROOT_FINAL = $GOROOT
+DEFGOROOT='-DGOROOT_FINAL="'$GOROOT_FINAL'"'
+
+for(i in cmd/dist/*.c)
+	$CC -FTVwp+ -DPLAN9 $DEFGOROOT $i
+$LD -o cmd/dist/dist *.$O
+rm *.$O
+
+eval `{./cmd/dist/dist env -9}
+echo
+
+if(~ $1 --dist-tool){
+	# Stop after building dist tool.
+	mkdir -p $GOTOOLDIR
+	if(! ~ $2 '')
+		cp cmd/dist/dist $2
+	mv cmd/dist/dist $GOTOOLDIR/dist
+	exit
+}
+
+echo '# Building compilers and Go bootstrap tool for host,' $GOHOSTOS/$GOHOSTARCH^.
+buildall = -a
+if(~ $1 --no-clean)
+	buildall = ()
+./cmd/dist/dist bootstrap $buildall -v # builds go_bootstrap
+# Delay move of dist tool to now, because bootstrap may clear tool directory.
+mv cmd/dist/dist $GOTOOLDIR/dist
+$GOTOOLDIR/go_bootstrap clean -i std
+echo
+
+# Run only one process at a time on 9vx.
+if(~ $sysname vx32)
+	pflag = (-p 1)
+
+if(! ~ $GOHOSTARCH $GOARCH || ! ~ $GOHOSTOS $GOOS){
+	echo '# Building packages and commands for host,' $GOHOSTOS/$GOHOSTARCH^.
+	GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \
+		$GOTOOLDIR/go_bootstrap install -ccflags $"GO_CCFLAGS -gcflags $"GO_GCFLAGS -ldflags $"GO_LDFLAGS -v $pflag std
+	echo
+}
+
+echo '# Building packages and commands for' $GOOS/$GOARCH^.
+$GOTOOLDIR/go_bootstrap install -ccflags $"GO_CCFLAGS -gcflags $"GO_GCFLAGS -ldflags $"GO_LDFLAGS -v $pflag std
+echo
+
+rm -f $GOTOOLDIR/go_bootstrap
+
+if(! ~ $1 --no-banner)
+	$GOTOOLDIR/dist banner
diff --git a/src/pkg/archive/tar/common.go b/src/pkg/archive/tar/common.go
index fc7a409..60d207c 100644
--- a/src/pkg/archive/tar/common.go
+++ b/src/pkg/archive/tar/common.go
@@ -9,9 +9,16 @@
 // References:
 //   http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5
 //   http://www.gnu.org/software/tar/manual/html_node/Standard.html
+//   http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
 package tar
 
-import "time"
+import (
+	"errors"
+	"fmt"
+	"os"
+	"path"
+	"time"
+)
 
 const (
 	blockSize = 512
@@ -28,6 +35,8 @@ const (
 	TypeCont          = '7'    // reserved
 	TypeXHeader       = 'x'    // extended header
 	TypeXGlobalHeader = 'g'    // global extended header
+	TypeGNULongName   = 'L'    // Next file has a long name
+	TypeGNULongLink   = 'K'    // Next file symlinks to a file w/ a long name
 )
 
 // A Header represents a single header in a tar archive.
@@ -49,6 +58,179 @@ type Header struct {
 	ChangeTime time.Time // status change time
 }
 
+// File name constants from the tar spec.
+const (
+	fileNameSize       = 100 // Maximum number of bytes in a standard tar name.
+	fileNamePrefixSize = 155 // Maximum number of ustar extension bytes.
+)
+
+// FileInfo returns an os.FileInfo for the Header.
+func (h *Header) FileInfo() os.FileInfo {
+	return headerFileInfo{h}
+}
+
+// headerFileInfo implements os.FileInfo.
+type headerFileInfo struct {
+	h *Header
+}
+
+func (fi headerFileInfo) Size() int64        { return fi.h.Size }
+func (fi headerFileInfo) IsDir() bool        { return fi.Mode().IsDir() }
+func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime }
+func (fi headerFileInfo) Sys() interface{}   { return fi.h }
+
+// Name returns the base name of the file.
+func (fi headerFileInfo) Name() string {
+	if fi.IsDir() {
+		return path.Clean(fi.h.Name)
+	}
+	return fi.h.Name
+}
+
+// Mode returns the permission and mode bits for the headerFileInfo.
+func (fi headerFileInfo) Mode() (mode os.FileMode) {
+	// Set file permission bits.
+	mode = os.FileMode(fi.h.Mode).Perm()
+
+	// Set setuid, setgid and sticky bits.
+	if fi.h.Mode&c_ISUID != 0 {
+		// setuid
+		mode |= os.ModeSetuid
+	}
+	if fi.h.Mode&c_ISGID != 0 {
+		// setgid
+		mode |= os.ModeSetgid
+	}
+	if fi.h.Mode&c_ISVTX != 0 {
+		// sticky
+		mode |= os.ModeSticky
+	}
+
+	// Set file mode bits.
+	// clear perm, setuid, setgid and sticky bits.
+	m := os.FileMode(fi.h.Mode) &^ 07777
+	if m == c_ISDIR {
+		// directory
+		mode |= os.ModeDir
+	}
+	if m == c_ISFIFO {
+		// named pipe (FIFO)
+		mode |= os.ModeNamedPipe
+	}
+	if m == c_ISLNK {
+		// symbolic link
+		mode |= os.ModeSymlink
+	}
+	if m == c_ISBLK {
+		// device file
+		mode |= os.ModeDevice
+	}
+	if m == c_ISCHR {
+		// Unix character device
+		mode |= os.ModeDevice
+		mode |= os.ModeCharDevice
+	}
+	if m == c_ISSOCK {
+		// Unix domain socket
+		mode |= os.ModeSocket
+	}
+
+	switch fi.h.Typeflag {
+	case TypeLink, TypeSymlink:
+		// hard link, symbolic link
+		mode |= os.ModeSymlink
+	case TypeChar:
+		// character device node
+		mode |= os.ModeDevice
+		mode |= os.ModeCharDevice
+	case TypeBlock:
+		// block device node
+		mode |= os.ModeDevice
+	case TypeDir:
+		// directory
+		mode |= os.ModeDir
+	case TypeFifo:
+		// fifo node
+		mode |= os.ModeNamedPipe
+	}
+
+	return mode
+}
+
+// sysStat, if non-nil, populates h from system-dependent fields of fi.
+var sysStat func(fi os.FileInfo, h *Header) error
+
+// Mode constants from the tar spec.
+const (
+	c_ISUID  = 04000   // Set uid
+	c_ISGID  = 02000   // Set gid
+	c_ISVTX  = 01000   // Save text (sticky bit)
+	c_ISDIR  = 040000  // Directory
+	c_ISFIFO = 010000  // FIFO
+	c_ISREG  = 0100000 // Regular file
+	c_ISLNK  = 0120000 // Symbolic link
+	c_ISBLK  = 060000  // Block special file
+	c_ISCHR  = 020000  // Character special file
+	c_ISSOCK = 0140000 // Socket
+)
+
+// FileInfoHeader creates a partially-populated Header from fi.
+// If fi describes a symlink, FileInfoHeader records link as the link target.
+// If fi describes a directory, a slash is appended to the name.
+func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
+	if fi == nil {
+		return nil, errors.New("tar: FileInfo is nil")
+	}
+	fm := fi.Mode()
+	h := &Header{
+		Name:    fi.Name(),
+		ModTime: fi.ModTime(),
+		Mode:    int64(fm.Perm()), // or'd with c_IS* constants later
+	}
+	switch {
+	case fm.IsRegular():
+		h.Mode |= c_ISREG
+		h.Typeflag = TypeReg
+		h.Size = fi.Size()
+	case fi.IsDir():
+		h.Typeflag = TypeDir
+		h.Mode |= c_ISDIR
+		h.Name += "/"
+	case fm&os.ModeSymlink != 0:
+		h.Typeflag = TypeSymlink
+		h.Mode |= c_ISLNK
+		h.Linkname = link
+	case fm&os.ModeDevice != 0:
+		if fm&os.ModeCharDevice != 0 {
+			h.Mode |= c_ISCHR
+			h.Typeflag = TypeChar
+		} else {
+			h.Mode |= c_ISBLK
+			h.Typeflag = TypeBlock
+		}
+	case fm&os.ModeNamedPipe != 0:
+		h.Typeflag = TypeFifo
+		h.Mode |= c_ISFIFO
+	case fm&os.ModeSocket != 0:
+		h.Mode |= c_ISSOCK
+	default:
+		return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm)
+	}
+	if fm&os.ModeSetuid != 0 {
+		h.Mode |= c_ISUID
+	}
+	if fm&os.ModeSetgid != 0 {
+		h.Mode |= c_ISGID
+	}
+	if fm&os.ModeSticky != 0 {
+		h.Mode |= c_ISVTX
+	}
+	if sysStat != nil {
+		return h, sysStat(fi, h)
+	}
+	return h, nil
+}
+
 var zeroBlock = make([]byte, blockSize)
 
 // POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signed byte values.
diff --git a/src/pkg/archive/tar/example_test.go b/src/pkg/archive/tar/example_test.go
new file mode 100644
index 0000000..351eaa0
--- /dev/null
+++ b/src/pkg/archive/tar/example_test.go
@@ -0,0 +1,79 @@
+// 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 tar_test
+
+import (
+	"archive/tar"
+	"bytes"
+	"fmt"
+	"io"
+	"log"
+	"os"
+)
+
+func Example() {
+	// Create a buffer to write our archive to.
+	buf := new(bytes.Buffer)
+
+	// Create a new tar archive.
+	tw := tar.NewWriter(buf)
+
+	// Add some files to the archive.
+	var files = []struct {
+		Name, Body string
+	}{
+		{"readme.txt", "This archive contains some text files."},
+		{"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},
+		{"todo.txt", "Get animal handling licence."},
+	}
+	for _, file := range files {
+		hdr := &tar.Header{
+			Name: file.Name,
+			Size: int64(len(file.Body)),
+		}
+		if err := tw.WriteHeader(hdr); err != nil {
+			log.Fatalln(err)
+		}
+		if _, err := tw.Write([]byte(file.Body)); err != nil {
+			log.Fatalln(err)
+		}
+	}
+	// Make sure to check the error on Close.
+	if err := tw.Close(); err != nil {
+		log.Fatalln(err)
+	}
+
+	// Open the tar archive for reading.
+	r := bytes.NewReader(buf.Bytes())
+	tr := tar.NewReader(r)
+
+	// Iterate through the files in the archive.
+	for {
+		hdr, err := tr.Next()
+		if err == io.EOF {
+			// end of tar archive
+			break
+		}
+		if err != nil {
+			log.Fatalln(err)
+		}
+		fmt.Printf("Contents of %s:\n", hdr.Name)
+		if _, err := io.Copy(os.Stdout, tr); err != nil {
+			log.Fatalln(err)
+		}
+		fmt.Println()
+	}
+
+	// Output:
+	// Contents of readme.txt:
+	// This archive contains some text files.
+	// Contents of gopher.txt:
+	// Gopher names:
+	// George
+	// Geoffrey
+	// Gonzo
+	// Contents of todo.txt:
+	// Get animal handling licence.
+}
diff --git a/src/pkg/archive/tar/reader.go b/src/pkg/archive/tar/reader.go
index 1b40af8..05f82a4 100644
--- a/src/pkg/archive/tar/reader.go
+++ b/src/pkg/archive/tar/reader.go
@@ -14,6 +14,7 @@ import (
 	"io/ioutil"
 	"os"
 	"strconv"
+	"strings"
 	"time"
 )
 
@@ -21,24 +22,12 @@ var (
 	ErrHeader = errors.New("archive/tar: invalid tar header")
 )
 
+const maxNanoSecondIntSize = 9
+
 // A Reader provides sequential access to the contents of a tar archive.
 // A tar archive consists of a sequence of files.
 // 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.
-//
-// Example:
-//	tr := tar.NewReader(r)
-//	for {
-//		hdr, err := tr.Next()
-//		if err == io.EOF {
-//			// end of tar archive
-//			break
-//		}
-//		if err != nil {
-//			// handle error
-//		}
-//		io.Copy(data, tr)
-//	}
 type Reader struct {
 	r   io.Reader
 	err error
@@ -55,13 +44,183 @@ func (tr *Reader) Next() (*Header, error) {
 	if tr.err == nil {
 		tr.skipUnread()
 	}
-	if tr.err == nil {
+	if tr.err != nil {
+		return hdr, tr.err
+	}
+	hdr = tr.readHeader()
+	if hdr == nil {
+		return hdr, tr.err
+	}
+	// Check for PAX/GNU header.
+	switch hdr.Typeflag {
+	case TypeXHeader:
+		//  PAX extended header
+		headers, err := parsePAX(tr)
+		if err != nil {
+			return nil, err
+		}
+		// We actually read the whole file,
+		// but this skips alignment padding
+		tr.skipUnread()
 		hdr = tr.readHeader()
+		mergePAX(hdr, headers)
+		return hdr, nil
+	case TypeGNULongName:
+		// We have a GNU long name header. Its contents are the real file name.
+		realname, err := ioutil.ReadAll(tr)
+		if err != nil {
+			return nil, err
+		}
+		hdr, err := tr.Next()
+		hdr.Name = cString(realname)
+		return hdr, err
+	case TypeGNULongLink:
+		// We have a GNU long link header.
+		realname, err := ioutil.ReadAll(tr)
+		if err != nil {
+			return nil, err
+		}
+		hdr, err := tr.Next()
+		hdr.Linkname = cString(realname)
+		return hdr, err
 	}
 	return hdr, tr.err
 }
 
-// Parse bytes as a NUL-terminated C-style string.
+// mergePAX merges well known headers according to PAX standard.
+// In general headers with the same name as those found
+// in the header struct overwrite those found in the header
+// struct with higher precision or longer values. Esp. useful
+// for name and linkname fields.
+func mergePAX(hdr *Header, headers map[string]string) error {
+	for k, v := range headers {
+		switch k {
+		case "path":
+			hdr.Name = v
+		case "linkpath":
+			hdr.Linkname = v
+		case "gname":
+			hdr.Gname = v
+		case "uname":
+			hdr.Uname = v
+		case "uid":
+			uid, err := strconv.ParseInt(v, 10, 0)
+			if err != nil {
+				return err
+			}
+			hdr.Uid = int(uid)
+		case "gid":
+			gid, err := strconv.ParseInt(v, 10, 0)
+			if err != nil {
+				return err
+			}
+			hdr.Gid = int(gid)
+		case "atime":
+			t, err := parsePAXTime(v)
+			if err != nil {
+				return err
+			}
+			hdr.AccessTime = t
+		case "mtime":
+			t, err := parsePAXTime(v)
+			if err != nil {
+				return err
+			}
+			hdr.ModTime = t
+		case "ctime":
+			t, err := parsePAXTime(v)
+			if err != nil {
+				return err
+			}
+			hdr.ChangeTime = t
+		case "size":
+			size, err := strconv.ParseInt(v, 10, 0)
+			if err != nil {
+				return err
+			}
+			hdr.Size = int64(size)
+		}
+
+	}
+	return nil
+}
+
+// parsePAXTime takes a string of the form %d.%d as described in
+// the PAX specification.
+func parsePAXTime(t string) (time.Time, error) {
+	buf := []byte(t)
+	pos := bytes.IndexByte(buf, '.')
+	var seconds, nanoseconds int64
+	var err error
+	if pos == -1 {
+		seconds, err = strconv.ParseInt(t, 10, 0)
+		if err != nil {
+			return time.Time{}, err
+		}
+	} else {
+		seconds, err = strconv.ParseInt(string(buf[:pos]), 10, 0)
+		if err != nil {
+			return time.Time{}, err
+		}
+		nano_buf := string(buf[pos+1:])
+		// Pad as needed before converting to a decimal.
+		// For example .030 -> .030000000 -> 30000000 nanoseconds
+		if len(nano_buf) < maxNanoSecondIntSize {
+			// Right pad
+			nano_buf += strings.Repeat("0", maxNanoSecondIntSize-len(nano_buf))
+		} else if len(nano_buf) > maxNanoSecondIntSize {
+			// Right truncate
+			nano_buf = nano_buf[:maxNanoSecondIntSize]
+		}
+		nanoseconds, err = strconv.ParseInt(string(nano_buf), 10, 0)
+		if err != nil {
+			return time.Time{}, err
+		}
+	}
+	ts := time.Unix(seconds, nanoseconds)
+	return ts, nil
+}
+
+// parsePAX parses PAX headers.
+// If an extended header (type 'x') is invalid, ErrHeader is returned
+func parsePAX(r io.Reader) (map[string]string, error) {
+	buf, err := ioutil.ReadAll(r)
+	if err != nil {
+		return nil, err
+	}
+	headers := make(map[string]string)
+	// Each record is constructed as
+	//     "%d %s=%s\n", length, keyword, value
+	for len(buf) > 0 {
+		// or the header was empty to start with.
+		var sp int
+		// The size field ends at the first space.
+		sp = bytes.IndexByte(buf, ' ')
+		if sp == -1 {
+			return nil, ErrHeader
+		}
+		// Parse the first token as a decimal integer.
+		n, err := strconv.ParseInt(string(buf[:sp]), 10, 0)
+		if err != nil {
+			return nil, ErrHeader
+		}
+		// Extract everything between the decimal and the n -1 on the
+		// beginning to to eat the ' ', -1 on the end to skip the newline.
+		var record []byte
+		record, buf = buf[sp+1:n-1], buf[n:]
+		// The first equals is guaranteed to mark the end of the key.
+		// Everything else is value.
+		eq := bytes.IndexByte(record, '=')
+		if eq == -1 {
+			return nil, ErrHeader
+		}
+		key, value := record[:eq], record[eq+1:]
+		headers[string(key)] = string(value)
+	}
+	return headers, nil
+}
+
+// cString parses bytes as a NUL-terminated C-style string.
 // If a NUL byte is not found then the whole slice is returned as a string.
 func cString(b []byte) string {
 	n := 0
@@ -72,6 +231,18 @@ func cString(b []byte) string {
 }
 
 func (tr *Reader) octal(b []byte) int64 {
+	// Check for binary format first.
+	if len(b) > 0 && b[0]&0x80 != 0 {
+		var x int64
+		for i, c := range b {
+			if i == 0 {
+				c &= 0x7f // ignore signal bit in first byte
+			}
+			x = x<<8 | int64(c)
+		}
+		return x
+	}
+
 	// Removing leading spaces.
 	for len(b) > 0 && b[0] == ' ' {
 		b = b[1:]
@@ -87,7 +258,7 @@ func (tr *Reader) octal(b []byte) int64 {
 	return int64(x)
 }
 
-// Skip any unread bytes in the existing file entry, as well as any alignment padding.
+// skipUnread skips any unread bytes in the existing file entry, as well as any alignment padding.
 func (tr *Reader) skipUnread() {
 	nr := tr.nb + tr.pad // number of bytes to skip
 	tr.nb, tr.pad = 0, 0
diff --git a/src/pkg/archive/tar/reader_test.go b/src/pkg/archive/tar/reader_test.go
index 0a8646c..9a19682 100644
--- a/src/pkg/archive/tar/reader_test.go
+++ b/src/pkg/archive/tar/reader_test.go
@@ -10,6 +10,8 @@ import (
 	"fmt"
 	"io"
 	"os"
+	"reflect"
+	"strings"
 	"testing"
 	"time"
 )
@@ -108,6 +110,38 @@ var untarTests = []*untarTest{
 			},
 		},
 	},
+	{
+		file: "testdata/pax.tar",
+		headers: []*Header{
+			{
+				Name:       "a/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
+				Mode:       0664,
+				Uid:        1000,
+				Gid:        1000,
+				Uname:      "shane",
+				Gname:      "shane",
+				Size:       7,
+				ModTime:    time.Unix(1350244992, 23960108),
+				ChangeTime: time.Unix(1350244992, 23960108),
+				AccessTime: time.Unix(1350244992, 23960108),
+				Typeflag:   TypeReg,
+			},
+			{
+				Name:       "a/b",
+				Mode:       0777,
+				Uid:        1000,
+				Gid:        1000,
+				Uname:      "shane",
+				Gname:      "shane",
+				Size:       0,
+				ModTime:    time.Unix(1350266320, 910238425),
+				ChangeTime: time.Unix(1350266320, 910238425),
+				AccessTime: time.Unix(1350266320, 910238425),
+				Typeflag:   TypeSymlink,
+				Linkname:   "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
+			},
+		},
+	},
 }
 
 func TestReader(t *testing.T) {
@@ -133,7 +167,7 @@ testLoop:
 		}
 		hdr, err := tr.Next()
 		if err == io.EOF {
-			break
+			continue testLoop
 		}
 		if hdr != nil || err != nil {
 			t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, hdr, err)
@@ -260,3 +294,73 @@ func TestNonSeekable(t *testing.T) {
 		t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(test.headers), nread)
 	}
 }
+
+func TestParsePAXHeader(t *testing.T) {
+	paxTests := [][3]string{
+		{"a", "a=name", "10 a=name\n"}, // Test case involving multiple acceptable lengths
+		{"a", "a=name", "9 a=name\n"},  // Test case involving multiple acceptable length
+		{"mtime", "mtime=1350244992.023960108", "30 mtime=1350244992.023960108\n"}}
+	for _, test := range paxTests {
+		key, expected, raw := test[0], test[1], test[2]
+		reader := bytes.NewBuffer([]byte(raw))
+		headers, err := parsePAX(reader)
+		if err != nil {
+			t.Errorf("Couldn't parse correctly formatted headers: %v", err)
+			continue
+		}
+		if strings.EqualFold(headers[key], expected) {
+			t.Errorf("mtime header incorrectly parsed: got %s, wanted %s", headers[key], expected)
+			continue
+		}
+		trailer := make([]byte, 100)
+		n, err := reader.Read(trailer)
+		if err != io.EOF || n != 0 {
+			t.Error("Buffer wasn't consumed")
+		}
+	}
+	badHeader := bytes.NewBuffer([]byte("3 somelongkey="))
+	if _, err := parsePAX(badHeader); err != ErrHeader {
+		t.Fatal("Unexpected success when parsing bad header")
+	}
+}
+
+func TestParsePAXTime(t *testing.T) {
+	// Some valid PAX time values
+	timestamps := map[string]time.Time{
+		"1350244992.023960108":  time.Unix(1350244992, 23960108), // The commoon case
+		"1350244992.02396010":   time.Unix(1350244992, 23960100), // Lower precision value
+		"1350244992.0239601089": time.Unix(1350244992, 23960108), // Higher precision value
+		"1350244992":            time.Unix(1350244992, 0),        // Low precision value
+	}
+	for input, expected := range timestamps {
+		ts, err := parsePAXTime(input)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !ts.Equal(expected) {
+			t.Fatalf("Time parsing failure %s %s", ts, expected)
+		}
+	}
+}
+
+func TestMergePAX(t *testing.T) {
+	hdr := new(Header)
+	// Test a string, integer, and time based value.
+	headers := map[string]string{
+		"path":  "a/b/c",
+		"uid":   "1000",
+		"mtime": "1350244992.023960108",
+	}
+	err := mergePAX(hdr, headers)
+	if err != nil {
+		t.Fatal(err)
+	}
+	want := &Header{
+		Name:    "a/b/c",
+		Uid:     1000,
+		ModTime: time.Unix(1350244992, 23960108),
+	}
+	if !reflect.DeepEqual(hdr, want) {
+		t.Errorf("incorrect merge: got %+v, want %+v", hdr, want)
+	}
+}
diff --git a/src/pkg/archive/tar/stat_atim.go b/src/pkg/archive/tar/stat_atim.go
new file mode 100644
index 0000000..6029b08
--- /dev/null
+++ b/src/pkg/archive/tar/stat_atim.go
@@ -0,0 +1,20 @@
+// 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 linux openbsd
+
+package tar
+
+import (
+	"syscall"
+	"time"
+)
+
+func statAtime(st *syscall.Stat_t) time.Time {
+	return time.Unix(st.Atim.Unix())
+}
+
+func statCtime(st *syscall.Stat_t) time.Time {
+	return time.Unix(st.Ctim.Unix())
+}
diff --git a/src/pkg/archive/tar/stat_atimespec.go b/src/pkg/archive/tar/stat_atimespec.go
new file mode 100644
index 0000000..6f17dbe
--- /dev/null
+++ b/src/pkg/archive/tar/stat_atimespec.go
@@ -0,0 +1,20 @@
+// 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 freebsd netbsd
+
+package tar
+
+import (
+	"syscall"
+	"time"
+)
+
+func statAtime(st *syscall.Stat_t) time.Time {
+	return time.Unix(st.Atimespec.Unix())
+}
+
+func statCtime(st *syscall.Stat_t) time.Time {
+	return time.Unix(st.Ctimespec.Unix())
+}
diff --git a/src/pkg/archive/tar/stat_unix.go b/src/pkg/archive/tar/stat_unix.go
new file mode 100644
index 0000000..92bc924
--- /dev/null
+++ b/src/pkg/archive/tar/stat_unix.go
@@ -0,0 +1,32 @@
+// 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 linux darwin freebsd openbsd netbsd
+
+package tar
+
+import (
+	"os"
+	"syscall"
+)
+
+func init() {
+	sysStat = statUnix
+}
+
+func statUnix(fi os.FileInfo, h *Header) error {
+	sys, ok := fi.Sys().(*syscall.Stat_t)
+	if !ok {
+		return nil
+	}
+	h.Uid = int(sys.Uid)
+	h.Gid = int(sys.Gid)
+	// TODO(bradfitz): populate username & group.  os/user
+	// doesn't cache LookupId lookups, and lacks group
+	// lookup functions.
+	h.AccessTime = statAtime(sys)
+	h.ChangeTime = statCtime(sys)
+	// TODO(bradfitz): major/minor device numbers?
+	return nil
+}
diff --git a/src/pkg/archive/tar/tar_test.go b/src/pkg/archive/tar/tar_test.go
new file mode 100644
index 0000000..dd63103
--- /dev/null
+++ b/src/pkg/archive/tar/tar_test.go
@@ -0,0 +1,271 @@
+// 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 tar
+
+import (
+	"bytes"
+	"io/ioutil"
+	"os"
+	"reflect"
+	"testing"
+	"time"
+)
+
+func TestFileInfoHeader(t *testing.T) {
+	fi, err := os.Stat("testdata/small.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	h, err := FileInfoHeader(fi, "")
+	if err != nil {
+		t.Fatalf("FileInfoHeader: %v", err)
+	}
+	if g, e := h.Name, "small.txt"; g != e {
+		t.Errorf("Name = %q; want %q", g, e)
+	}
+	if g, e := h.Mode, int64(fi.Mode().Perm())|c_ISREG; g != e {
+		t.Errorf("Mode = %#o; want %#o", g, e)
+	}
+	if g, e := h.Size, int64(5); g != e {
+		t.Errorf("Size = %v; want %v", g, e)
+	}
+	if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) {
+		t.Errorf("ModTime = %v; want %v", g, e)
+	}
+}
+
+func TestFileInfoHeaderDir(t *testing.T) {
+	fi, err := os.Stat("testdata")
+	if err != nil {
+		t.Fatal(err)
+	}
+	h, err := FileInfoHeader(fi, "")
+	if err != nil {
+		t.Fatalf("FileInfoHeader: %v", err)
+	}
+	if g, e := h.Name, "testdata/"; g != e {
+		t.Errorf("Name = %q; want %q", g, e)
+	}
+	// Ignoring c_ISGID for golang.org/issue/4867
+	if g, e := h.Mode&^c_ISGID, int64(fi.Mode().Perm())|c_ISDIR; g != e {
+		t.Errorf("Mode = %#o; want %#o", g, e)
+	}
+	if g, e := h.Size, int64(0); g != e {
+		t.Errorf("Size = %v; want %v", g, e)
+	}
+	if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) {
+		t.Errorf("ModTime = %v; want %v", g, e)
+	}
+}
+
+func TestFileInfoHeaderSymlink(t *testing.T) {
+	h, err := FileInfoHeader(symlink{}, "some-target")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, e := h.Name, "some-symlink"; g != e {
+		t.Errorf("Name = %q; want %q", g, e)
+	}
+	if g, e := h.Linkname, "some-target"; g != e {
+		t.Errorf("Linkname = %q; want %q", g, e)
+	}
+}
+
+type symlink struct{}
+
+func (symlink) Name() string       { return "some-symlink" }
+func (symlink) Size() int64        { return 0 }
+func (symlink) Mode() os.FileMode  { return os.ModeSymlink }
+func (symlink) ModTime() time.Time { return time.Time{} }
+func (symlink) IsDir() bool        { return false }
+func (symlink) Sys() interface{}   { return nil }
+
+func TestRoundTrip(t *testing.T) {
+	data := []byte("some file contents")
+
+	var b bytes.Buffer
+	tw := NewWriter(&b)
+	hdr := &Header{
+		Name:    "file.txt",
+		Uid:     1 << 21, // too big for 8 octal digits
+		Size:    int64(len(data)),
+		ModTime: time.Now(),
+	}
+	// tar only supports second precision.
+	hdr.ModTime = hdr.ModTime.Add(-time.Duration(hdr.ModTime.Nanosecond()) * time.Nanosecond)
+	if err := tw.WriteHeader(hdr); err != nil {
+		t.Fatalf("tw.WriteHeader: %v", err)
+	}
+	if _, err := tw.Write(data); err != nil {
+		t.Fatalf("tw.Write: %v", err)
+	}
+	if err := tw.Close(); err != nil {
+		t.Fatalf("tw.Close: %v", err)
+	}
+
+	// Read it back.
+	tr := NewReader(&b)
+	rHdr, err := tr.Next()
+	if err != nil {
+		t.Fatalf("tr.Next: %v", err)
+	}
+	if !reflect.DeepEqual(rHdr, hdr) {
+		t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr)
+	}
+	rData, err := ioutil.ReadAll(tr)
+	if err != nil {
+		t.Fatalf("Read: %v", err)
+	}
+	if !bytes.Equal(rData, data) {
+		t.Errorf("Data mismatch.\n got %q\nwant %q", rData, data)
+	}
+}
+
+type headerRoundTripTest struct {
+	h  *Header
+	fm os.FileMode
+}
+
+func TestHeaderRoundTrip(t *testing.T) {
+	golden := []headerRoundTripTest{
+		// regular file.
+		{
+			h: &Header{
+				Name:     "test.txt",
+				Mode:     0644 | c_ISREG,
+				Size:     12,
+				ModTime:  time.Unix(1360600916, 0),
+				Typeflag: TypeReg,
+			},
+			fm: 0644,
+		},
+		// hard link.
+		{
+			h: &Header{
+				Name:     "hard.txt",
+				Mode:     0644 | c_ISLNK,
+				Size:     0,
+				ModTime:  time.Unix(1360600916, 0),
+				Typeflag: TypeLink,
+			},
+			fm: 0644 | os.ModeSymlink,
+		},
+		// symbolic link.
+		{
+			h: &Header{
+				Name:     "link.txt",
+				Mode:     0777 | c_ISLNK,
+				Size:     0,
+				ModTime:  time.Unix(1360600852, 0),
+				Typeflag: TypeSymlink,
+			},
+			fm: 0777 | os.ModeSymlink,
+		},
+		// character device node.
+		{
+			h: &Header{
+				Name:     "dev/null",
+				Mode:     0666 | c_ISCHR,
+				Size:     0,
+				ModTime:  time.Unix(1360578951, 0),
+				Typeflag: TypeChar,
+			},
+			fm: 0666 | os.ModeDevice | os.ModeCharDevice,
+		},
+		// block device node.
+		{
+			h: &Header{
+				Name:     "dev/sda",
+				Mode:     0660 | c_ISBLK,
+				Size:     0,
+				ModTime:  time.Unix(1360578954, 0),
+				Typeflag: TypeBlock,
+			},
+			fm: 0660 | os.ModeDevice,
+		},
+		// directory.
+		{
+			h: &Header{
+				Name:     "dir/",
+				Mode:     0755 | c_ISDIR,
+				Size:     0,
+				ModTime:  time.Unix(1360601116, 0),
+				Typeflag: TypeDir,
+			},
+			fm: 0755 | os.ModeDir,
+		},
+		// fifo node.
+		{
+			h: &Header{
+				Name:     "dev/initctl",
+				Mode:     0600 | c_ISFIFO,
+				Size:     0,
+				ModTime:  time.Unix(1360578949, 0),
+				Typeflag: TypeFifo,
+			},
+			fm: 0600 | os.ModeNamedPipe,
+		},
+		// setuid.
+		{
+			h: &Header{
+				Name:     "bin/su",
+				Mode:     0755 | c_ISREG | c_ISUID,
+				Size:     23232,
+				ModTime:  time.Unix(1355405093, 0),
+				Typeflag: TypeReg,
+			},
+			fm: 0755 | os.ModeSetuid,
+		},
+		// setguid.
+		{
+			h: &Header{
+				Name:     "group.txt",
+				Mode:     0750 | c_ISREG | c_ISGID,
+				Size:     0,
+				ModTime:  time.Unix(1360602346, 0),
+				Typeflag: TypeReg,
+			},
+			fm: 0750 | os.ModeSetgid,
+		},
+		// sticky.
+		{
+			h: &Header{
+				Name:     "sticky.txt",
+				Mode:     0600 | c_ISREG | c_ISVTX,
+				Size:     7,
+				ModTime:  time.Unix(1360602540, 0),
+				Typeflag: TypeReg,
+			},
+			fm: 0600 | os.ModeSticky,
+		},
+	}
+
+	for i, g := range golden {
+		fi := g.h.FileInfo()
+		h2, err := FileInfoHeader(fi, "")
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		if got, want := h2.Name, g.h.Name; got != want {
+			t.Errorf("i=%d: Name: got %v, want %v", i, got, want)
+		}
+		if got, want := h2.Size, g.h.Size; got != want {
+			t.Errorf("i=%d: Size: got %v, want %v", i, got, want)
+		}
+		if got, want := h2.Mode, g.h.Mode; got != want {
+			t.Errorf("i=%d: Mode: got %o, want %o", i, got, want)
+		}
+		if got, want := fi.Mode(), g.fm; got != want {
+			t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want)
+		}
+		if got, want := h2.ModTime, g.h.ModTime; got != want {
+			t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want)
+		}
+		if sysh, ok := fi.Sys().(*Header); !ok || sysh != g.h {
+			t.Errorf("i=%d: Sys didn't return original *Header", i)
+		}
+	}
+}
diff --git a/src/pkg/archive/tar/testdata/pax.tar b/src/pkg/archive/tar/testdata/pax.tar
new file mode 100644
index 0000000..9bc24b6
Binary files /dev/null and b/src/pkg/archive/tar/testdata/pax.tar differ
diff --git a/src/pkg/archive/tar/testdata/ustar.tar b/src/pkg/archive/tar/testdata/ustar.tar
new file mode 100644
index 0000000..29679d9
Binary files /dev/null and b/src/pkg/archive/tar/testdata/ustar.tar differ
diff --git a/src/pkg/archive/tar/writer.go b/src/pkg/archive/tar/writer.go
index b2b7a58..d92dd06 100644
--- a/src/pkg/archive/tar/writer.go
+++ b/src/pkg/archive/tar/writer.go
@@ -8,33 +8,28 @@ package tar
 // - catch more errors (no first header, etc.)
 
 import (
+	"bytes"
 	"errors"
 	"fmt"
 	"io"
+	"os"
+	"path"
 	"strconv"
+	"strings"
+	"time"
 )
 
 var (
 	ErrWriteTooLong    = errors.New("archive/tar: write too long")
 	ErrFieldTooLong    = errors.New("archive/tar: header field too long")
 	ErrWriteAfterClose = errors.New("archive/tar: write after close")
+	errNameTooLong     = errors.New("archive/tar: name too long")
 )
 
 // A Writer provides sequential writing of a tar archive in POSIX.1 format.
 // A tar archive consists of a sequence of files.
 // Call WriteHeader to begin a new file, and then call Write to supply that file's data,
 // writing at most hdr.Size bytes in total.
-//
-// Example:
-//	tw := tar.NewWriter(w)
-//	hdr := new(Header)
-//	hdr.Size = length of data in bytes
-//	// populate other hdr fields as desired
-//	if err := tw.WriteHeader(hdr); err != nil {
-//		// handle error
-//	}
-//	io.Copy(tw, data)
-//	tw.Close()
 type Writer struct {
 	w          io.Writer
 	err        error
@@ -110,6 +105,12 @@ func (tw *Writer) numeric(b []byte, x int64) {
 	b[0] |= 0x80 // highest bit indicates binary format
 }
 
+var (
+	minTime = time.Unix(0, 0)
+	// There is room for 11 octal digits (33 bits) of mtime.
+	maxTime = minTime.Add((1<<33 - 1) * time.Second)
+)
+
 // WriteHeader writes hdr and prepares to accept the file's contents.
 // WriteHeader calls Flush if it is not the first header.
 // Calling after a Close will return ErrWriteAfterClose.
@@ -123,34 +124,60 @@ func (tw *Writer) WriteHeader(hdr *Header) error {
 	if tw.err != nil {
 		return tw.err
 	}
-
+	// Decide whether or not to use PAX extensions
+	// TODO(shanemhansen): we might want to use PAX headers for
+	// subsecond time resolution, but for now let's just capture
+	// the long name/long symlink use case.
+	suffix := hdr.Name
+	prefix := ""
+	if len(hdr.Name) > fileNameSize || len(hdr.Linkname) > fileNameSize {
+		var err error
+		prefix, suffix, err = tw.splitUSTARLongName(hdr.Name)
+		// Either we were unable to pack the long name into ustar format
+		// or the link name is too long; use PAX headers.
+		if err == errNameTooLong || len(hdr.Linkname) > fileNameSize {
+			if err := tw.writePAXHeader(hdr); err != nil {
+				return err
+			}
+		} else if err != nil {
+			return err
+		}
+	}
 	tw.nb = int64(hdr.Size)
 	tw.pad = -tw.nb & (blockSize - 1) // blockSize is a power of two
 
 	header := make([]byte, blockSize)
 	s := slicer(header)
+	tw.cString(s.next(fileNameSize), suffix)
 
-	// TODO(dsymonds): handle names longer than 100 chars
-	copy(s.next(100), []byte(hdr.Name))
-
-	tw.octal(s.next(8), hdr.Mode)              // 100:108
-	tw.numeric(s.next(8), int64(hdr.Uid))      // 108:116
-	tw.numeric(s.next(8), int64(hdr.Gid))      // 116:124
-	tw.numeric(s.next(12), hdr.Size)           // 124:136
-	tw.numeric(s.next(12), hdr.ModTime.Unix()) // 136:148
-	s.next(8)                                  // chksum (148:156)
-	s.next(1)[0] = hdr.Typeflag                // 156:157
-	tw.cString(s.next(100), hdr.Linkname)      // linkname (157:257)
-	copy(s.next(8), []byte("ustar\x0000"))     // 257:265
-	tw.cString(s.next(32), hdr.Uname)          // 265:297
-	tw.cString(s.next(32), hdr.Gname)          // 297:329
-	tw.numeric(s.next(8), hdr.Devmajor)        // 329:337
-	tw.numeric(s.next(8), hdr.Devminor)        // 337:345
+	// Handle out of range ModTime carefully.
+	var modTime int64
+	if !hdr.ModTime.Before(minTime) && !hdr.ModTime.After(maxTime) {
+		modTime = hdr.ModTime.Unix()
+	}
 
+	tw.octal(s.next(8), hdr.Mode)          // 100:108
+	tw.numeric(s.next(8), int64(hdr.Uid))  // 108:116
+	tw.numeric(s.next(8), int64(hdr.Gid))  // 116:124
+	tw.numeric(s.next(12), hdr.Size)       // 124:136
+	tw.numeric(s.next(12), modTime)        // 136:148
+	s.next(8)                              // chksum (148:156)
+	s.next(1)[0] = hdr.Typeflag            // 156:157
+	tw.cString(s.next(100), hdr.Linkname)  // linkname (157:257)
+	copy(s.next(8), []byte("ustar\x0000")) // 257:265
+	tw.cString(s.next(32), hdr.Uname)      // 265:297
+	tw.cString(s.next(32), hdr.Gname)      // 297:329
+	tw.numeric(s.next(8), hdr.Devmajor)    // 329:337
+	tw.numeric(s.next(8), hdr.Devminor)    // 337:345
+	tw.cString(s.next(155), prefix)        // 345:500
 	// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
 	if tw.usedBinary {
 		copy(header[257:265], []byte("ustar  \x00"))
 	}
+	// Use the ustar magic if we used ustar long names.
+	if len(prefix) > 0 {
+		copy(header[257:265], []byte("ustar\000"))
+	}
 
 	// The chksum field is terminated by a NUL and a space.
 	// This is different from the other octal fields.
@@ -168,6 +195,78 @@ func (tw *Writer) WriteHeader(hdr *Header) error {
 	return tw.err
 }
 
+// writeUSTARLongName splits a USTAR long name hdr.Name.
+// name must be < 256 characters. errNameTooLong is returned
+// if hdr.Name can't be split. The splitting heuristic
+// is compatible with gnu tar.
+func (tw *Writer) splitUSTARLongName(name string) (prefix, suffix string, err error) {
+	length := len(name)
+	if length > fileNamePrefixSize+1 {
+		length = fileNamePrefixSize + 1
+	} else if name[length-1] == '/' {
+		length--
+	}
+	i := strings.LastIndex(name[:length], "/")
+	nlen := length - i - 1
+	if i <= 0 || nlen > fileNameSize || nlen == 0 {
+		err = errNameTooLong
+		return
+	}
+	prefix, suffix = name[:i], name[i+1:]
+	return
+}
+
+// writePaxHeader writes an extended pax header to the
+// archive.
+func (tw *Writer) writePAXHeader(hdr *Header) error {
+	// Prepare extended header
+	ext := new(Header)
+	ext.Typeflag = TypeXHeader
+	// Setting ModTime is required for reader parsing to
+	// succeed, and seems harmless enough.
+	ext.ModTime = hdr.ModTime
+	// The spec asks that we namespace our pseudo files
+	// with the current pid.
+	pid := os.Getpid()
+	dir, file := path.Split(hdr.Name)
+	ext.Name = path.Join(dir,
+		fmt.Sprintf("PaxHeaders.%d", pid), file)[0:100]
+	// Construct the body
+	var buf bytes.Buffer
+	if len(hdr.Name) > fileNameSize {
+		fmt.Fprint(&buf, paxHeader("path="+hdr.Name))
+	}
+	if len(hdr.Linkname) > fileNameSize {
+		fmt.Fprint(&buf, paxHeader("linkpath="+hdr.Linkname))
+	}
+	ext.Size = int64(len(buf.Bytes()))
+	if err := tw.WriteHeader(ext); err != nil {
+		return err
+	}
+	if _, err := tw.Write(buf.Bytes()); err != nil {
+		return err
+	}
+	if err := tw.Flush(); err != nil {
+		return err
+	}
+	return nil
+}
+
+// paxHeader formats a single pax record, prefixing it with the appropriate length
+func paxHeader(msg string) string {
+	const padding = 2 // Extra padding for space and newline
+	size := len(msg) + padding
+	size += len(strconv.Itoa(size))
+	record := fmt.Sprintf("%d %s\n", size, msg)
+	if len(record) != size {
+		// Final adjustment if adding size increased
+		// the number of digits in size
+		size = len(record)
+		record = fmt.Sprintf("%d %s\n", size, msg)
+	}
+	return record
+}
+
 // Write writes to the current entry in the tar archive.
 // Write returns the error ErrWriteTooLong if more than
 // hdr.Size bytes are written after WriteHeader.
diff --git a/src/pkg/archive/tar/writer_test.go b/src/pkg/archive/tar/writer_test.go
index a214e57..4cf7c72 100644
--- a/src/pkg/archive/tar/writer_test.go
+++ b/src/pkg/archive/tar/writer_test.go
@@ -9,6 +9,7 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"os"
 	"strings"
 	"testing"
 	"testing/iotest"
@@ -101,6 +102,27 @@ var writerTests = []*writerTest{
 			},
 		},
 	},
+	// This file was produced using gnu tar 1.17
+	// gnutar  -b 4 --format=ustar (longname/)*15 + file.txt
+	{
+		file: "testdata/ustar.tar",
+		entries: []*writerTestEntry{
+			{
+				header: &Header{
+					Name:     strings.Repeat("longname/", 15) + "file.txt",
+					Mode:     0644,
+					Uid:      0765,
+					Gid:      024,
+					Size:     06,
+					ModTime:  time.Unix(1360135598, 0),
+					Typeflag: '0',
+					Uname:    "shane",
+					Gname:    "staff",
+				},
+				contents: "hello\n",
+			},
+		},
+	},
 }
 
 // Render byte array in a two-character hexadecimal string, spaced for easy visual inspection.
@@ -180,3 +202,61 @@ testLoop:
 		}
 	}
 }
+
+func TestPax(t *testing.T) {
+	// Create an archive with a large name
+	fileinfo, err := os.Stat("testdata/small.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	hdr, err := FileInfoHeader(fileinfo, "")
+	if err != nil {
+		t.Fatalf("os.Stat: %v", err)
+	}
+	// Force a PAX long name to be written
+	longName := strings.Repeat("ab", 100)
+	contents := strings.Repeat(" ", int(hdr.Size))
+	hdr.Name = longName
+	var buf bytes.Buffer
+	writer := NewWriter(&buf)
+	if err := writer.WriteHeader(hdr); err != nil {
+		t.Fatal(err)
+	}
+	if _, err = writer.Write([]byte(contents)); err != nil {
+		t.Fatal(err)
+	}
+	if err := writer.Close(); err != nil {
+		t.Fatal(err)
+	}
+	// Simple test to make sure PAX extensions are in effect
+	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+		t.Fatal("Expected at least one PAX header to be written.")
+	}
+	// Test that we can get a long name back out of the archive.
+	reader := NewReader(&buf)
+	hdr, err = reader.Next()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if hdr.Name != longName {
+		t.Fatal("Couldn't recover long file name")
+	}
+}
+
+func TestPAXHeader(t *testing.T) {
+	medName := strings.Repeat("CD", 50)
+	longName := strings.Repeat("AB", 100)
+	paxTests := [][2]string{
+		{"name=/etc/hosts", "19 name=/etc/hosts\n"},
+		{"a=b", "6 a=b\n"},          // Single digit length
+		{"a=names", "11 a=names\n"}, // Test case involving carries
+		{"name=" + longName, fmt.Sprintf("210 name=%s\n", longName)},
+		{"name=" + medName, fmt.Sprintf("110 name=%s\n", medName)}}
+
+	for _, test := range paxTests {
+		key, expected := test[0], test[1]
+		if result := paxHeader(key); result != expected {
+			t.Fatalf("paxHeader: got %s, expected %s", result, expected)
+		}
+	}
+}
diff --git a/src/pkg/archive/zip/reader.go b/src/pkg/archive/zip/reader.go
index ddd5075..c10f29a 100644
--- a/src/pkg/archive/zip/reader.go
+++ b/src/pkg/archive/zip/reader.go
@@ -103,7 +103,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
 		}
 		z.File = append(z.File, f)
 	}
-	if uint16(len(z.File)) != end.directoryRecords {
+	if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here
 		// Return the readDirectoryHeader error if we read
 		// the wrong number of directory entries.
 		return err
@@ -123,7 +123,7 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
 	if err != nil {
 		return
 	}
-	size := int64(f.CompressedSize)
+	size := int64(f.CompressedSize64)
 	r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size)
 	switch f.Method {
 	case Store: // (no compression)
@@ -220,6 +220,8 @@ func readDirectoryHeader(f *File, r io.Reader) error {
 	f.CRC32 = b.uint32()
 	f.CompressedSize = b.uint32()
 	f.UncompressedSize = b.uint32()
+	f.CompressedSize64 = uint64(f.CompressedSize)
+	f.UncompressedSize64 = uint64(f.UncompressedSize)
 	filenameLen := int(b.uint16())
 	extraLen := int(b.uint16())
 	commentLen := int(b.uint16())
@@ -233,6 +235,35 @@ func readDirectoryHeader(f *File, r io.Reader) error {
 	f.Name = string(d[:filenameLen])
 	f.Extra = d[filenameLen : filenameLen+extraLen]
 	f.Comment = string(d[filenameLen+extraLen:])
+
+	if len(f.Extra) > 0 {
+		b := readBuf(f.Extra)
+		for len(b) >= 4 { // need at least tag and size
+			tag := b.uint16()
+			size := b.uint16()
+			if int(size) > len(b) {
+				return ErrFormat
+			}
+			if tag == zip64ExtraId {
+				// update directory values from the zip64 extra block
+				eb := readBuf(b)
+				if len(eb) >= 8 {
+					f.UncompressedSize64 = eb.uint64()
+				}
+				if len(eb) >= 8 {
+					f.CompressedSize64 = eb.uint64()
+				}
+				if len(eb) >= 8 {
+					f.headerOffset = int64(eb.uint64())
+				}
+			}
+			b = b[size:]
+		}
+		// Should have consumed the whole header.
+		if len(b) != 0 {
+			return ErrFormat
+		}
+	}
 	return nil
 }
 
@@ -263,15 +294,23 @@ func readDataDescriptor(r io.Reader, f *File) error {
 		return err
 	}
 	b := readBuf(buf[:12])
-	f.CRC32 = b.uint32()
-	f.CompressedSize = b.uint32()
-	f.UncompressedSize = b.uint32()
+	if b.uint32() != f.CRC32 {
+		return ErrChecksum
+	}
+
+	// The two sizes that follow here can be either 32 bits or 64 bits
+	// but the spec is not very clear on this and different
+	// interpretations has been made causing incompatibilities. We
+	// already have the sizes from the central directory so we can
+	// just ignore these.
+
 	return nil
 }
 
 func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) {
 	// look for directoryEndSignature in the last 1k, then in the last 65k
 	var buf []byte
+	var directoryEndOffset int64
 	for i, bLen := range []int64{1024, 65 * 1024} {
 		if bLen > size {
 			bLen = size
@@ -282,6 +321,7 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error)
 		}
 		if p := findSignatureInBlock(buf); p >= 0 {
 			buf = buf[p:]
+			directoryEndOffset = size - bLen + int64(p)
 			break
 		}
 		if i == 1 || bLen == size {
@@ -292,12 +332,12 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error)
 	// read header into struct
 	b := readBuf(buf[4:]) // skip signature
 	d := &directoryEnd{
-		diskNbr:            b.uint16(),
-		dirDiskNbr:         b.uint16(),
-		dirRecordsThisDisk: b.uint16(),
-		directoryRecords:   b.uint16(),
-		directorySize:      b.uint32(),
-		directoryOffset:    b.uint32(),
+		diskNbr:            uint32(b.uint16()),
+		dirDiskNbr:         uint32(b.uint16()),
+		dirRecordsThisDisk: uint64(b.uint16()),
+		directoryRecords:   uint64(b.uint16()),
+		directorySize:      uint64(b.uint32()),
+		directoryOffset:    uint64(b.uint32()),
 		commentLen:         b.uint16(),
 	}
 	l := int(d.commentLen)
@@ -305,9 +345,62 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error)
 		return nil, errors.New("zip: invalid comment length")
 	}
 	d.comment = string(b[:l])
+
+	p, err := findDirectory64End(r, directoryEndOffset)
+	if err == nil && p >= 0 {
+		err = readDirectory64End(r, p, d)
+	}
+	if err != nil {
+		return nil, err
+	}
 	return d, nil
 }
 
+// findDirectory64End tries to read the zip64 locator just before the
+// directory end and returns the offset of the zip64 directory end if
+// found.
+func findDirectory64End(r io.ReaderAt, directoryEndOffset int64) (int64, error) {
+	locOffset := directoryEndOffset - directory64LocLen
+	if locOffset < 0 {
+		return -1, nil // no need to look for a header outside the file
+	}
+	buf := make([]byte, directory64LocLen)
+	if _, err := r.ReadAt(buf, locOffset); err != nil {
+		return -1, err
+	}
+	b := readBuf(buf)
+	if sig := b.uint32(); sig != directory64LocSignature {
+		return -1, nil
+	}
+	b = b[4:]       // skip number of the disk with the start of the zip64 end of central directory
+	p := b.uint64() // relative offset of the zip64 end of central directory record
+	return int64(p), nil
+}
+
+// readDirectory64End reads the zip64 directory end and updates the
+// directory end with the zip64 directory end values.
+func readDirectory64End(r io.ReaderAt, offset int64, d *directoryEnd) (err error) {
+	buf := make([]byte, directory64EndLen)
+	if _, err := r.ReadAt(buf, offset); err != nil {
+		return err
+	}
+
+	b := readBuf(buf)
+	if sig := b.uint32(); sig != directory64EndSignature {
+		return ErrFormat
+	}
+
+	b = b[12:]                        // skip dir size, version and version needed (uint64 + 2x uint16)
+	d.diskNbr = b.uint32()            // number of this disk
+	d.dirDiskNbr = b.uint32()         // number of the disk with the start of the central directory
+	d.dirRecordsThisDisk = b.uint64() // total number of entries in the central directory on this disk
+	d.directoryRecords = b.uint64()   // total number of entries in the central directory
+	d.directorySize = b.uint64()      // size of the central directory
+	d.directoryOffset = b.uint64()    // offset of start of central directory with respect to the starting disk number
+
+	return nil
+}
+
 func findSignatureInBlock(b []byte) int {
 	for i := len(b) - directoryEndLen; i >= 0; i-- {
 		// defined from directoryEndSignature in struct.go
@@ -335,3 +428,9 @@ func (b *readBuf) uint32() uint32 {
 	*b = (*b)[4:]
 	return v
 }
+
+func (b *readBuf) uint64() uint64 {
+	v := binary.LittleEndian.Uint64(*b)
+	*b = (*b)[8:]
+	return v
+}
diff --git a/src/pkg/archive/zip/reader_test.go b/src/pkg/archive/zip/reader_test.go
index 5f1d1b2..cf9c59c 100644
--- a/src/pkg/archive/zip/reader_test.go
+++ b/src/pkg/archive/zip/reader_test.go
@@ -206,6 +206,17 @@ var tests = []ZipTest{
 			},
 		},
 	},
+	{
+		Name: "zip64.zip",
+		File: []ZipTestFile{
+			{
+				Name:    "README",
+				Content: []byte("This small file is in ZIP64 format.\n"),
+				Mtime:   "08-10-12 14:33:32",
+				Mode:    0644,
+			},
+		},
+	},
 }
 
 var crossPlatform = []ZipTestFile{
diff --git a/src/pkg/archive/zip/struct.go b/src/pkg/archive/zip/struct.go
index 55f3dcf..ea067f3 100644
--- a/src/pkg/archive/zip/struct.go
+++ b/src/pkg/archive/zip/struct.go
@@ -7,12 +7,19 @@ Package zip provides support for reading and writing ZIP archives.
 
 See: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
 
-This package does not support ZIP64 or disk spanning.
+This package does not support disk spanning.
+
+A note about ZIP64:
+
+To be backwards compatible the FileHeader has both 32 and 64 bit Size
+fields. The 64 bit fields will always contain the correct value and
+for normal archives both fields will be the same. For files requiring
+the ZIP64 format the 32 bit fields will be 0xffffffff and the 64 bit
+fields must be used instead.
 */
 package zip
 
 import (
-	"errors"
 	"os"
 	"time"
 )
@@ -27,11 +34,16 @@ const (
 	fileHeaderSignature      = 0x04034b50
 	directoryHeaderSignature = 0x02014b50
 	directoryEndSignature    = 0x06054b50
+	directory64LocSignature  = 0x07064b50
+	directory64EndSignature  = 0x06064b50
 	dataDescriptorSignature  = 0x08074b50 // de-facto standard; required by OS X Finder
 	fileHeaderLen            = 30         // + filename + extra
 	directoryHeaderLen       = 46         // + filename + extra + comment
 	directoryEndLen          = 22         // + comment
 	dataDescriptorLen        = 16         // four uint32: descriptor signature, crc32, compressed size, size
+	dataDescriptor64Len      = 24         // descriptor with 8 byte sizes
+	directory64LocLen        = 20         //
+	directory64EndLen        = 56         // + extra
 
 	// Constants for the first byte in CreatorVersion
 	creatorFAT    = 0
@@ -39,22 +51,35 @@ const (
 	creatorNTFS   = 11
 	creatorVFAT   = 14
 	creatorMacOSX = 19
+
+	// version numbers
+	zipVersion20 = 20 // 2.0
+	zipVersion45 = 45 // 4.5 (reads and writes zip64 archives)
+
+	// limits for non zip64 files
+	uint16max = (1 << 16) - 1
+	uint32max = (1 << 32) - 1
+
+	// extra header id's
+	zip64ExtraId = 0x0001 // zip64 Extended Information Extra Field
 )
 
 type FileHeader struct {
-	Name             string
-	CreatorVersion   uint16
-	ReaderVersion    uint16
-	Flags            uint16
-	Method           uint16
-	ModifiedTime     uint16 // MS-DOS time
-	ModifiedDate     uint16 // MS-DOS date
-	CRC32            uint32
-	CompressedSize   uint32
-	UncompressedSize uint32
-	Extra            []byte
-	ExternalAttrs    uint32 // Meaning depends on CreatorVersion
-	Comment          string
+	Name               string
+	CreatorVersion     uint16
+	ReaderVersion      uint16
+	Flags              uint16
+	Method             uint16
+	ModifiedTime       uint16 // MS-DOS time
+	ModifiedDate       uint16 // MS-DOS date
+	CRC32              uint32
+	CompressedSize     uint32 // deprecated; use CompressedSize64
+	UncompressedSize   uint32 // deprecated; use UncompressedSize64
+	CompressedSize64   uint64
+	UncompressedSize64 uint64
+	Extra              []byte
+	ExternalAttrs      uint32 // Meaning depends on CreatorVersion
+	Comment            string
 }
 
 // FileInfo returns an os.FileInfo for the FileHeader.
@@ -67,8 +92,13 @@ type headerFileInfo struct {
 	fh *FileHeader
 }
 
-func (fi headerFileInfo) Name() string       { return fi.fh.Name }
-func (fi headerFileInfo) Size() int64        { return int64(fi.fh.UncompressedSize) }
+func (fi headerFileInfo) Name() string { return fi.fh.Name }
+func (fi headerFileInfo) Size() int64 {
+	if fi.fh.UncompressedSize64 > 0 {
+		return int64(fi.fh.UncompressedSize64)
+	}
+	return int64(fi.fh.UncompressedSize)
+}
 func (fi headerFileInfo) IsDir() bool        { return fi.Mode().IsDir() }
 func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() }
 func (fi headerFileInfo) Mode() os.FileMode  { return fi.fh.Mode() }
@@ -78,25 +108,27 @@ func (fi headerFileInfo) Sys() interface{}   { return fi.fh }
 // os.FileInfo.
 func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
 	size := fi.Size()
-	if size > (1<<32 - 1) {
-		return nil, errors.New("zip: file over 4GB")
-	}
 	fh := &FileHeader{
-		Name:             fi.Name(),
-		UncompressedSize: uint32(size),
+		Name:               fi.Name(),
+		UncompressedSize64: uint64(size),
 	}
 	fh.SetModTime(fi.ModTime())
 	fh.SetMode(fi.Mode())
+	if fh.UncompressedSize64 > uint32max {
+		fh.UncompressedSize = uint32max
+	} else {
+		fh.UncompressedSize = uint32(fh.UncompressedSize64)
+	}
 	return fh, nil
 }
 
 type directoryEnd struct {
-	diskNbr            uint16 // unused
-	dirDiskNbr         uint16 // unused
-	dirRecordsThisDisk uint16 // unused
-	directoryRecords   uint16
-	directorySize      uint32
-	directoryOffset    uint32 // relative to file
+	diskNbr            uint32 // unused
+	dirDiskNbr         uint32 // unused
+	dirRecordsThisDisk uint64 // unused
+	directoryRecords   uint64
+	directorySize      uint64
+	directoryOffset    uint64 // relative to file
 	commentLen         uint16
 	comment            string
 }
@@ -190,6 +222,11 @@ func (h *FileHeader) SetMode(mode os.FileMode) {
 	}
 }
 
+// isZip64 returns true if the file size exceeds the 32 bit limit
+func (fh *FileHeader) isZip64() bool {
+	return fh.CompressedSize64 > uint32max || fh.UncompressedSize64 > uint32max
+}
+
 func msdosModeToFileMode(m uint32) (mode os.FileMode) {
 	if m&msdosDir != 0 {
 		mode = os.ModeDir | 0777
diff --git a/src/pkg/archive/zip/testdata/zip64.zip b/src/pkg/archive/zip/testdata/zip64.zip
new file mode 100644
index 0000000..a2ee1fa
Binary files /dev/null and b/src/pkg/archive/zip/testdata/zip64.zip differ
diff --git a/src/pkg/archive/zip/writer.go b/src/pkg/archive/zip/writer.go
index 45eb6bd..4c696e1 100644
--- a/src/pkg/archive/zip/writer.go
+++ b/src/pkg/archive/zip/writer.go
@@ -27,7 +27,7 @@ type Writer struct {
 
 type header struct {
 	*FileHeader
-	offset uint32
+	offset uint64
 }
 
 // NewWriter returns a new Writer writing a zip file to w.
@@ -62,14 +62,36 @@ func (w *Writer) Close() error {
 		b.uint16(h.ModifiedTime)
 		b.uint16(h.ModifiedDate)
 		b.uint32(h.CRC32)
-		b.uint32(h.CompressedSize)
-		b.uint32(h.UncompressedSize)
+		if h.isZip64() || h.offset > uint32max {
+			// the file needs a zip64 header. store maxint in both
+			// 32 bit size fields (and offset later) to signal that the
+			// zip64 extra header should be used.
+			b.uint32(uint32max) // compressed size
+			b.uint32(uint32max) // uncompressed size
+
+			// append a zip64 extra block to Extra
+			var buf [28]byte // 2x uint16 + 3x uint64
+			eb := writeBuf(buf[:])
+			eb.uint16(zip64ExtraId)
+			eb.uint16(24) // size = 3x uint64
+			eb.uint64(h.UncompressedSize64)
+			eb.uint64(h.CompressedSize64)
+			eb.uint64(h.offset)
+			h.Extra = append(h.Extra, buf[:]...)
+		} else {
+			b.uint32(h.CompressedSize)
+			b.uint32(h.UncompressedSize)
+		}
 		b.uint16(uint16(len(h.Name)))
 		b.uint16(uint16(len(h.Extra)))
 		b.uint16(uint16(len(h.Comment)))
 		b = b[4:] // skip disk number start and internal file attr (2x uint16)
 		b.uint32(h.ExternalAttrs)
-		b.uint32(h.offset)
+		if h.offset > uint32max {
+			b.uint32(uint32max)
+		} else {
+			b.uint32(uint32(h.offset))
+		}
 		if _, err := w.cw.Write(buf[:]); err != nil {
 			return err
 		}
@@ -85,15 +107,52 @@ func (w *Writer) Close() error {
 	}
 	end := w.cw.count
 
+	records := uint64(len(w.dir))
+	size := uint64(end - start)
+	offset := uint64(start)
+
+	if records > uint16max || size > uint32max || offset > uint32max {
+		var buf [directory64EndLen + directory64LocLen]byte
+		b := writeBuf(buf[:])
+
+		// zip64 end of central directory record
+		b.uint32(directory64EndSignature)
+		b.uint64(directory64EndLen)
+		b.uint16(zipVersion45) // version made by
+		b.uint16(zipVersion45) // version needed to extract
+		b.uint32(0)            // number of this disk
+		b.uint32(0)            // number of the disk with the start of the central directory
+		b.uint64(records)      // total number of entries in the central directory on this disk
+		b.uint64(records)      // total number of entries in the central directory
+		b.uint64(size)         // size of the central directory
+		b.uint64(offset)       // offset of start of central directory with respect to the starting disk number
+
+		// zip64 end of central directory locator
+		b.uint32(directory64LocSignature)
+		b.uint32(0)           // number of the disk with the start of the zip64 end of central directory
+		b.uint64(uint64(end)) // relative offset of the zip64 end of central directory record
+		b.uint32(1)           // total number of disks
+
+		if _, err := w.cw.Write(buf[:]); err != nil {
+			return err
+		}
+
+		// store max values in the regular end record to signal that
+		// that the zip64 values should be used instead
+		records = uint16max
+		size = uint32max
+		offset = uint32max
+	}
+
 	// write end record
 	var buf [directoryEndLen]byte
 	b := writeBuf(buf[:])
 	b.uint32(uint32(directoryEndSignature))
-	b = b[4:]                     // skip over disk number and first disk number (2x uint16)
-	b.uint16(uint16(len(w.dir)))  // number of entries this disk
-	b.uint16(uint16(len(w.dir)))  // number of entries total
-	b.uint32(uint32(end - start)) // size of directory
-	b.uint32(uint32(start))       // start of directory
+	b = b[4:]                 // skip over disk number and first disk number (2x uint16)
+	b.uint16(uint16(records)) // number of entries this disk
+	b.uint16(uint16(records)) // number of entries total
+	b.uint32(uint32(size))    // size of directory
+	b.uint32(uint32(offset))  // start of directory
 	// skipped size of comment (always zero)
 	if _, err := w.cw.Write(buf[:]); err != nil {
 		return err
@@ -115,7 +174,7 @@ func (w *Writer) Create(name string) (io.Writer, error) {
 }
 
 // CreateHeader adds a file to the zip file using the provided FileHeader
-// for the file metadata. 
+// for the file metadata.
 // It returns a Writer to which the file contents should be written.
 // The file's contents must be written to the io.Writer before the next
 // call to Create, CreateHeader, or Close.
@@ -127,8 +186,9 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
 	}
 
 	fh.Flags |= 0x8 // we will write a data descriptor
-	fh.CreatorVersion = fh.CreatorVersion&0xff00 | 0x14
-	fh.ReaderVersion = 0x14
+
+	fh.CreatorVersion = fh.CreatorVersion&0xff00 | zipVersion20 // preserve compatibility byte
+	fh.ReaderVersion = zipVersion20
 
 	fw := &fileWriter{
 		zipw:      w.cw,
@@ -151,7 +211,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
 
 	h := &header{
 		FileHeader: fh,
-		offset:     uint32(w.cw.count),
+		offset:     uint64(w.cw.count),
 	}
 	w.dir = append(w.dir, h)
 	fw.header = h
@@ -173,9 +233,9 @@ func writeHeader(w io.Writer, h *FileHeader) error {
 	b.uint16(h.Method)
 	b.uint16(h.ModifiedTime)
 	b.uint16(h.ModifiedDate)
-	b.uint32(h.CRC32)
-	b.uint32(h.CompressedSize)
-	b.uint32(h.UncompressedSize)
+	b.uint32(0) // since we are writing a data descriptor crc32,
+	b.uint32(0) // compressed size,
+	b.uint32(0) // and uncompressed size should be zero
 	b.uint16(uint16(len(h.Name)))
 	b.uint16(uint16(len(h.Extra)))
 	if _, err := w.Write(buf[:]); err != nil {
@@ -218,17 +278,40 @@ func (w *fileWriter) close() error {
 	// update FileHeader
 	fh := w.header.FileHeader
 	fh.CRC32 = w.crc32.Sum32()
-	fh.CompressedSize = uint32(w.compCount.count)
-	fh.UncompressedSize = uint32(w.rawCount.count)
+	fh.CompressedSize64 = uint64(w.compCount.count)
+	fh.UncompressedSize64 = uint64(w.rawCount.count)
 
-	// write data descriptor
-	var buf [dataDescriptorLen]byte
-	b := writeBuf(buf[:])
+	if fh.isZip64() {
+		fh.CompressedSize = uint32max
+		fh.UncompressedSize = uint32max
+		fh.ReaderVersion = zipVersion45 // requires 4.5 - File uses ZIP64 format extensions
+	} else {
+		fh.CompressedSize = uint32(fh.CompressedSize64)
+		fh.UncompressedSize = uint32(fh.UncompressedSize64)
+	}
+
+	// Write data descriptor. This is more complicated than one would
+	// think, see e.g. comments in zipfile.c:putextended() and
+	// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588.
+	// The approach here is to write 8 byte sizes if needed without
+	// adding a zip64 extra in the local header (too late anyway).
+	var buf []byte
+	if fh.isZip64() {
+		buf = make([]byte, dataDescriptor64Len)
+	} else {
+		buf = make([]byte, dataDescriptorLen)
+	}
+	b := writeBuf(buf)
 	b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X
 	b.uint32(fh.CRC32)
-	b.uint32(fh.CompressedSize)
-	b.uint32(fh.UncompressedSize)
-	_, err := w.zipw.Write(buf[:])
+	if fh.isZip64() {
+		b.uint64(fh.CompressedSize64)
+		b.uint64(fh.UncompressedSize64)
+	} else {
+		b.uint32(fh.CompressedSize)
+		b.uint32(fh.UncompressedSize)
+	}
+	_, err := w.zipw.Write(buf)
 	return err
 }
 
@@ -262,3 +345,8 @@ func (b *writeBuf) uint32(v uint32) {
 	binary.LittleEndian.PutUint32(*b, v)
 	*b = (*b)[4:]
 }
+
+func (b *writeBuf) uint64(v uint64) {
+	binary.LittleEndian.PutUint64(*b, v)
+	*b = (*b)[8:]
+}
diff --git a/src/pkg/archive/zip/zip_test.go b/src/pkg/archive/zip/zip_test.go
index d6490c4..a8af206 100644
--- a/src/pkg/archive/zip/zip_test.go
+++ b/src/pkg/archive/zip/zip_test.go
@@ -9,7 +9,8 @@ package zip
 import (
 	"bytes"
 	"fmt"
-	"reflect"
+	"io"
+	"io/ioutil"
 	"strings"
 	"testing"
 	"time"
@@ -17,8 +18,7 @@ import (
 
 func TestOver65kFiles(t *testing.T) {
 	if testing.Short() {
-		t.Logf("slow test; skipping")
-		return
+		t.Skip("slow test; skipping")
 	}
 	buf := new(bytes.Buffer)
 	w := NewWriter(buf)
@@ -58,6 +58,33 @@ func TestModTime(t *testing.T) {
 	}
 }
 
+func testHeaderRoundTrip(fh *FileHeader, wantUncompressedSize uint32, wantUncompressedSize64 uint64, t *testing.T) {
+	fi := fh.FileInfo()
+	fh2, err := FileInfoHeader(fi)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got, want := fh2.Name, fh.Name; got != want {
+		t.Errorf("Name: got %s, want %s\n", got, want)
+	}
+	if got, want := fh2.UncompressedSize, wantUncompressedSize; got != want {
+		t.Errorf("UncompressedSize: got %d, want %d\n", got, want)
+	}
+	if got, want := fh2.UncompressedSize64, wantUncompressedSize64; got != want {
+		t.Errorf("UncompressedSize64: got %d, want %d\n", got, want)
+	}
+	if got, want := fh2.ModifiedTime, fh.ModifiedTime; got != want {
+		t.Errorf("ModifiedTime: got %d, want %d\n", got, want)
+	}
+	if got, want := fh2.ModifiedDate, fh.ModifiedDate; got != want {
+		t.Errorf("ModifiedDate: got %d, want %d\n", got, want)
+	}
+
+	if sysfh, ok := fi.Sys().(*FileHeader); !ok && sysfh != fh {
+		t.Errorf("Sys didn't return original *FileHeader")
+	}
+}
+
 func TestFileHeaderRoundTrip(t *testing.T) {
 	fh := &FileHeader{
 		Name:             "foo.txt",
@@ -65,17 +92,164 @@ func TestFileHeaderRoundTrip(t *testing.T) {
 		ModifiedTime:     1234,
 		ModifiedDate:     5678,
 	}
-	fi := fh.FileInfo()
-	fh2, err := FileInfoHeader(fi)
+	testHeaderRoundTrip(fh, fh.UncompressedSize, uint64(fh.UncompressedSize), t)
+}
 
-	// Ignore these fields:
-	fh2.CreatorVersion = 0
-	fh2.ExternalAttrs = 0
+func TestFileHeaderRoundTrip64(t *testing.T) {
+	fh := &FileHeader{
+		Name:               "foo.txt",
+		UncompressedSize64: 9876543210,
+		ModifiedTime:       1234,
+		ModifiedDate:       5678,
+	}
+	testHeaderRoundTrip(fh, uint32max, fh.UncompressedSize64, t)
+}
 
-	if !reflect.DeepEqual(fh, fh2) {
-		t.Errorf("mismatch\n input=%#v\noutput=%#v\nerr=%v", fh, fh2, err)
+func TestZip64(t *testing.T) {
+	if testing.Short() {
+		t.Skip("slow test; skipping")
 	}
-	if sysfh, ok := fi.Sys().(*FileHeader); !ok && sysfh != fh {
-		t.Errorf("Sys didn't return original *FileHeader")
+	// write 2^32 bytes plus "END\n" to a zip file
+	buf := new(bytes.Buffer)
+	w := NewWriter(buf)
+	f, err := w.Create("huge.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	chunk := make([]byte, 1024)
+	for i := range chunk {
+		chunk[i] = '.'
+	}
+	chunk[len(chunk)-1] = '\n'
+	end := []byte("END\n")
+	for i := 0; i < (1<<32)/1024; i++ {
+		_, err := f.Write(chunk)
+		if err != nil {
+			t.Fatal("write chunk:", err)
+		}
+	}
+	_, err = f.Write(end)
+	if err != nil {
+		t.Fatal("write end:", err)
+	}
+	if err := w.Close(); err != nil {
+		t.Fatal(err)
+	}
+
+	// read back zip file and check that we get to the end of it
+	r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
+	if err != nil {
+		t.Fatal("reader:", err)
+	}
+	f0 := r.File[0]
+	rc, err := f0.Open()
+	if err != nil {
+		t.Fatal("opening:", err)
+	}
+	for i := 0; i < (1<<32)/1024; i++ {
+		_, err := io.ReadFull(rc, chunk)
+		if err != nil {
+			t.Fatal("read:", err)
+		}
+	}
+	gotEnd, err := ioutil.ReadAll(rc)
+	if err != nil {
+		t.Fatal("read end:", err)
+	}
+	if !bytes.Equal(gotEnd, end) {
+		t.Errorf("End of zip64 archive %q, want %q", gotEnd, end)
+	}
+	err = rc.Close()
+	if err != nil {
+		t.Fatal("closing:", err)
+	}
+	if got, want := f0.UncompressedSize, uint32(uint32max); got != want {
+		t.Errorf("UncompressedSize %d, want %d", got, want)
+	}
+
+	if got, want := f0.UncompressedSize64, (1<<32)+uint64(len(end)); got != want {
+		t.Errorf("UncompressedSize64 %d, want %d", got, want)
+	}
+}
+
+func testInvalidHeader(h *FileHeader, t *testing.T) {
+	var buf bytes.Buffer
+	z := NewWriter(&buf)
+
+	f, err := z.CreateHeader(h)
+	if err != nil {
+		t.Fatalf("error creating header: %v", err)
+	}
+	if _, err := f.Write([]byte("hi")); err != nil {
+		t.Fatalf("error writing content: %v", err)
+	}
+	if err := z.Close(); err != nil {
+		t.Fatalf("error closing zip writer: %v", err)
+	}
+
+	b := buf.Bytes()
+	if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != ErrFormat {
+		t.Fatalf("got %v, expected ErrFormat", err)
+	}
+}
+
+func testValidHeader(h *FileHeader, t *testing.T) {
+	var buf bytes.Buffer
+	z := NewWriter(&buf)
+
+	f, err := z.CreateHeader(h)
+	if err != nil {
+		t.Fatalf("error creating header: %v", err)
+	}
+	if _, err := f.Write([]byte("hi")); err != nil {
+		t.Fatalf("error writing content: %v", err)
+	}
+	if err := z.Close(); err != nil {
+		t.Fatalf("error closing zip writer: %v", err)
+	}
+
+	b := buf.Bytes()
+	if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != nil {
+		t.Fatalf("got %v, expected nil", err)
+	}
+}
+
+// Issue 4302.
+func TestHeaderInvalidTagAndSize(t *testing.T) {
+	const timeFormat = "20060102T150405.000.txt"
+
+	ts := time.Now()
+	filename := ts.Format(timeFormat)
+
+	h := FileHeader{
+		Name:   filename,
+		Method: Deflate,
+		Extra:  []byte(ts.Format(time.RFC3339Nano)), // missing tag and len
+	}
+	h.SetModTime(ts)
+
+	testInvalidHeader(&h, t)
+}
+
+func TestHeaderTooShort(t *testing.T) {
+	h := FileHeader{
+		Name:   "foo.txt",
+		Method: Deflate,
+		Extra:  []byte{zip64ExtraId}, // missing size
+	}
+	testInvalidHeader(&h, t)
+}
+
+// Issue 4393. It is valid to have an extra data header
+// which contains no body.
+func TestZeroLengthHeader(t *testing.T) {
+	h := FileHeader{
+		Name:   "extadata.txt",
+		Method: Deflate,
+		Extra: []byte{
+			85, 84, 5, 0, 3, 154, 144, 195, 77, // tag 21589 size 5
+			85, 120, 0, 0, // tag 30805 size 0
+		},
 	}
+	testValidHeader(&h, t)
 }
diff --git a/src/pkg/bufio/bufio.go b/src/pkg/bufio/bufio.go
index b44d0e7..ee69c2d 100644
--- a/src/pkg/bufio/bufio.go
+++ b/src/pkg/bufio/bufio.go
@@ -64,6 +64,8 @@ func NewReader(rd io.Reader) *Reader {
 	return NewReaderSize(rd, defaultBufSize)
 }
 
+var errNegativeRead = errors.New("bufio: reader returned negative count from Read")
+
 // fill reads a new chunk into the buffer.
 func (b *Reader) fill() {
 	// Slide existing data to beginning.
@@ -74,10 +76,13 @@ func (b *Reader) fill() {
 	}
 
 	// Read new data.
-	n, e := b.rd.Read(b.buf[b.w:])
+	n, err := b.rd.Read(b.buf[b.w:])
+	if n < 0 {
+		panic(errNegativeRead)
+	}
 	b.w += n
-	if e != nil {
-		b.err = e
+	if err != nil {
+		b.err = err
 	}
 }
 
@@ -272,6 +277,9 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
 	panic("not reached")
 }
 
+// ReadLine is a low-level line-reading primitive. Most callers should use
+// ReadBytes('\n') or ReadString('\n') instead or use a Scanner.
+//
 // ReadLine tries to return a single line, not including the end-of-line bytes.
 // If the line was too long for the buffer then isPrefix is set and the
 // beginning of the line is returned. The rest of the line will be returned
@@ -279,6 +287,9 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
 // of the line. The returned buffer is only valid until the next call to
 // ReadLine. ReadLine either returns a non-nil line or it returns an error,
 // never both.
+//
+// The text returned from ReadLine does not include the line end ("\r\n" or "\n").
+// No indication or error is given if the input ends without a final line end.
 func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) {
 	line, err = b.ReadSlice('\n')
 	if err == ErrBufferFull {
@@ -320,6 +331,7 @@ func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) {
 // it returns the data read before the error and the error itself (often io.EOF).
 // ReadBytes returns err != nil if and only if the returned data does not end in
 // delim.
+// For simple uses, a Scanner may be more convenient.
 func (b *Reader) ReadBytes(delim byte) (line []byte, err error) {
 	// Use ReadSlice to look for array,
 	// accumulating full buffers.
@@ -367,9 +379,45 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err error) {
 // it returns the data read before the error and the error itself (often io.EOF).
 // ReadString returns err != nil if and only if the returned data does not end in
 // delim.
+// For simple uses, a Scanner may be more convenient.
 func (b *Reader) ReadString(delim byte) (line string, err error) {
-	bytes, e := b.ReadBytes(delim)
-	return string(bytes), e
+	bytes, err := b.ReadBytes(delim)
+	return string(bytes), err
+}
+
+// WriteTo implements io.WriterTo.
+func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
+	n, err = b.writeBuf(w)
+	if err != nil {
+		return
+	}
+
+	if r, ok := b.rd.(io.WriterTo); ok {
+		m, err := r.WriteTo(w)
+		n += m
+		return n, err
+	}
+
+	for b.fill(); b.r < b.w; b.fill() {
+		m, err := b.writeBuf(w)
+		n += m
+		if err != nil {
+			return n, err
+		}
+	}
+
+	if b.err == io.EOF {
+		b.err = nil
+	}
+
+	return n, b.readErr()
+}
+
+// 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])
+	b.r += n
+	return int64(n), err
 }
 
 // buffered output
@@ -415,17 +463,17 @@ func (b *Writer) Flush() error {
 	if b.n == 0 {
 		return nil
 	}
-	n, e := b.wr.Write(b.buf[0:b.n])
-	if n < b.n && e == nil {
-		e = io.ErrShortWrite
+	n, err := b.wr.Write(b.buf[0:b.n])
+	if n < b.n && err == nil {
+		err = io.ErrShortWrite
 	}
-	if e != nil {
+	if err != nil {
 		if n > 0 && n < b.n {
 			copy(b.buf[0:b.n-n], b.buf[n:b.n])
 		}
 		b.n -= n
-		b.err = e
-		return e
+		b.err = err
+		return err
 	}
 	b.n = 0
 	return nil
@@ -529,6 +577,36 @@ func (b *Writer) WriteString(s string) (int, error) {
 	return nn, nil
 }
 
+// ReadFrom implements io.ReaderFrom.
+func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
+	if b.Buffered() == 0 {
+		if w, ok := b.wr.(io.ReaderFrom); ok {
+			return w.ReadFrom(r)
+		}
+	}
+	var m int
+	for {
+		m, err = r.Read(b.buf[b.n:])
+		if m == 0 {
+			break
+		}
+		b.n += m
+		n += int64(m)
+		if b.Available() == 0 {
+			if err1 := b.Flush(); err1 != nil {
+				return n, err1
+			}
+		}
+		if err != nil {
+			break
+		}
+	}
+	if err == io.EOF {
+		err = nil
+	}
+	return n, err
+}
+
 // buffered input and output
 
 // ReadWriter stores pointers to a Reader and a Writer.
diff --git a/src/pkg/bufio/bufio_test.go b/src/pkg/bufio/bufio_test.go
index a43cbd2..b0e8114 100644
--- a/src/pkg/bufio/bufio_test.go
+++ b/src/pkg/bufio/bufio_test.go
@@ -28,9 +28,9 @@ func newRot13Reader(r io.Reader) *rot13Reader {
 }
 
 func (r13 *rot13Reader) Read(p []byte) (int, error) {
-	n, e := r13.r.Read(p)
-	if e != nil {
-		return n, e
+	n, err := r13.r.Read(p)
+	if err != nil {
+		return n, err
 	}
 	for i := 0; i < n; i++ {
 		c := p[i] | 0x20 // lowercase byte
@@ -48,15 +48,15 @@ func readBytes(buf *Reader) string {
 	var b [1000]byte
 	nb := 0
 	for {
-		c, e := buf.ReadByte()
-		if e == io.EOF {
+		c, err := buf.ReadByte()
+		if err == io.EOF {
 			break
 		}
-		if e == nil {
+		if err == nil {
 			b[nb] = c
 			nb++
-		} else if e != iotest.ErrTimeout {
-			panic("Data: " + e.Error())
+		} else if err != iotest.ErrTimeout {
+			panic("Data: " + err.Error())
 		}
 	}
 	return string(b[0:nb])
@@ -93,12 +93,12 @@ var readMakers = []readMaker{
 func readLines(b *Reader) string {
 	s := ""
 	for {
-		s1, e := b.ReadString('\n')
-		if e == io.EOF {
+		s1, err := b.ReadString('\n')
+		if err == io.EOF {
 			break
 		}
-		if e != nil && e != iotest.ErrTimeout {
-			panic("GetLines: " + e.Error())
+		if err != nil && err != iotest.ErrTimeout {
+			panic("GetLines: " + err.Error())
 		}
 		s += s1
 	}
@@ -110,9 +110,9 @@ func reads(buf *Reader, m int) string {
 	var b [1000]byte
 	nb := 0
 	for {
-		n, e := buf.Read(b[nb : nb+m])
+		n, err := buf.Read(b[nb : nb+m])
 		nb += n
-		if e == io.EOF {
+		if err == io.EOF {
 			break
 		}
 	}
@@ -748,7 +748,7 @@ func testReadLineNewlines(t *testing.T, input string, expect []readLineResult) {
 	b := NewReaderSize(strings.NewReader(input), minReadBufferSize)
 	for i, e := range expect {
 		line, isPrefix, err := b.ReadLine()
-		if bytes.Compare(line, e.line) != 0 {
+		if !bytes.Equal(line, e.line) {
 			t.Errorf("%q call %d, line == %q, want %q", input, i, line, e.line)
 			return
 		}
@@ -762,3 +762,283 @@ func testReadLineNewlines(t *testing.T, input string, expect []readLineResult) {
 		}
 	}
 }
+
+func createTestInput(n int) []byte {
+	input := make([]byte, n)
+	for i := range input {
+		// 101 and 251 are arbitrary prime numbers.
+		// The idea is to create an input sequence
+		// which doesn't repeat too frequently.
+		input[i] = byte(i % 251)
+		if i%101 == 0 {
+			input[i] ^= byte(i / 101)
+		}
+	}
+	return input
+}
+
+func TestReaderWriteTo(t *testing.T) {
+	input := createTestInput(8192)
+	r := NewReader(onlyReader{bytes.NewBuffer(input)})
+	w := new(bytes.Buffer)
+	if n, err := r.WriteTo(w); err != nil || n != int64(len(input)) {
+		t.Fatalf("r.WriteTo(w) = %d, %v, want %d, nil", n, err, len(input))
+	}
+
+	for i, val := range w.Bytes() {
+		if val != input[i] {
+			t.Errorf("after write: out[%d] = %#x, want %#x", i, val, input[i])
+		}
+	}
+}
+
+type errorWriterToTest struct {
+	rn, wn     int
+	rerr, werr error
+	expected   error
+}
+
+func (r errorWriterToTest) Read(p []byte) (int, error) {
+	return len(p) * r.rn, r.rerr
+}
+
+func (w errorWriterToTest) Write(p []byte) (int, error) {
+	return len(p) * w.wn, w.werr
+}
+
+var errorWriterToTests = []errorWriterToTest{
+	{1, 0, nil, io.ErrClosedPipe, io.ErrClosedPipe},
+	{0, 1, io.ErrClosedPipe, nil, io.ErrClosedPipe},
+	{0, 0, io.ErrUnexpectedEOF, io.ErrClosedPipe, io.ErrClosedPipe},
+	{0, 1, io.EOF, nil, nil},
+}
+
+func TestReaderWriteToErrors(t *testing.T) {
+	for i, rw := range errorWriterToTests {
+		r := NewReader(rw)
+		if _, err := r.WriteTo(rw); err != rw.expected {
+			t.Errorf("r.WriteTo(errorWriterToTests[%d]) = _, %v, want _,%v", i, err, rw.expected)
+		}
+	}
+}
+
+func TestWriterReadFrom(t *testing.T) {
+	ws := []func(io.Writer) io.Writer{
+		func(w io.Writer) io.Writer { return onlyWriter{w} },
+		func(w io.Writer) io.Writer { return w },
+	}
+
+	rs := []func(io.Reader) io.Reader{
+		iotest.DataErrReader,
+		func(r io.Reader) io.Reader { return r },
+	}
+
+	for ri, rfunc := range rs {
+		for wi, wfunc := range ws {
+			input := createTestInput(8192)
+			b := new(bytes.Buffer)
+			w := NewWriter(wfunc(b))
+			r := rfunc(bytes.NewBuffer(input))
+			if n, err := w.ReadFrom(r); err != nil || n != int64(len(input)) {
+				t.Errorf("ws[%d],rs[%d]: w.ReadFrom(r) = %d, %v, want %d, nil", wi, ri, n, err, len(input))
+				continue
+			}
+			if got, want := b.String(), string(input); got != want {
+				t.Errorf("ws[%d], rs[%d]:\ngot  %q\nwant %q\n", wi, ri, got, want)
+			}
+		}
+	}
+}
+
+type errorReaderFromTest struct {
+	rn, wn     int
+	rerr, werr error
+	expected   error
+}
+
+func (r errorReaderFromTest) Read(p []byte) (int, error) {
+	return len(p) * r.rn, r.rerr
+}
+
+func (w errorReaderFromTest) Write(p []byte) (int, error) {
+	return len(p) * w.wn, w.werr
+}
+
+var errorReaderFromTests = []errorReaderFromTest{
+	{0, 1, io.EOF, nil, nil},
+	{1, 1, io.EOF, nil, nil},
+	{0, 1, io.ErrClosedPipe, nil, io.ErrClosedPipe},
+	{0, 0, io.ErrClosedPipe, io.ErrShortWrite, io.ErrClosedPipe},
+	{1, 0, nil, io.ErrShortWrite, io.ErrShortWrite},
+}
+
+func TestWriterReadFromErrors(t *testing.T) {
+	for i, rw := range errorReaderFromTests {
+		w := NewWriter(rw)
+		if _, err := w.ReadFrom(rw); err != rw.expected {
+			t.Errorf("w.ReadFrom(errorReaderFromTests[%d]) = _, %v, want _,%v", i, err, rw.expected)
+		}
+	}
+}
+
+// TestWriterReadFromCounts tests that using io.Copy to copy into a
+// bufio.Writer does not prematurely flush the buffer. For example, when
+// buffering writes to a network socket, excessive network writes should be
+// avoided.
+func TestWriterReadFromCounts(t *testing.T) {
+	var w0 writeCountingDiscard
+	b0 := NewWriterSize(&w0, 1234)
+	b0.WriteString(strings.Repeat("x", 1000))
+	if w0 != 0 {
+		t.Fatalf("write 1000 'x's: got %d writes, want 0", w0)
+	}
+	b0.WriteString(strings.Repeat("x", 200))
+	if w0 != 0 {
+		t.Fatalf("write 1200 'x's: got %d writes, want 0", w0)
+	}
+	io.Copy(b0, onlyReader{strings.NewReader(strings.Repeat("x", 30))})
+	if w0 != 0 {
+		t.Fatalf("write 1230 'x's: got %d writes, want 0", w0)
+	}
+	io.Copy(b0, onlyReader{strings.NewReader(strings.Repeat("x", 9))})
+	if w0 != 1 {
+		t.Fatalf("write 1239 'x's: got %d writes, want 1", w0)
+	}
+
+	var w1 writeCountingDiscard
+	b1 := NewWriterSize(&w1, 1234)
+	b1.WriteString(strings.Repeat("x", 1200))
+	b1.Flush()
+	if w1 != 1 {
+		t.Fatalf("flush 1200 'x's: got %d writes, want 1", w1)
+	}
+	b1.WriteString(strings.Repeat("x", 89))
+	if w1 != 1 {
+		t.Fatalf("write 1200 + 89 'x's: got %d writes, want 1", w1)
+	}
+	io.Copy(b1, onlyReader{strings.NewReader(strings.Repeat("x", 700))})
+	if w1 != 1 {
+		t.Fatalf("write 1200 + 789 'x's: got %d writes, want 1", w1)
+	}
+	io.Copy(b1, onlyReader{strings.NewReader(strings.Repeat("x", 600))})
+	if w1 != 2 {
+		t.Fatalf("write 1200 + 1389 'x's: got %d writes, want 2", w1)
+	}
+	b1.Flush()
+	if w1 != 3 {
+		t.Fatalf("flush 1200 + 1389 'x's: got %d writes, want 3", w1)
+	}
+}
+
+// A writeCountingDiscard is like ioutil.Discard and counts the number of times
+// Write is called on it.
+type writeCountingDiscard int
+
+func (w *writeCountingDiscard) Write(p []byte) (int, error) {
+	*w++
+	return len(p), nil
+}
+
+type negativeReader int
+
+func (r *negativeReader) Read([]byte) (int, error) { return -1, nil }
+
+func TestNegativeRead(t *testing.T) {
+	// should panic with a description pointing at the reader, not at itself.
+	// (should NOT panic with slice index error, for example.)
+	b := NewReader(new(negativeReader))
+	defer func() {
+		switch err := recover().(type) {
+		case nil:
+			t.Fatal("read did not panic")
+		case error:
+			if !strings.Contains(err.Error(), "reader returned negative count from Read") {
+				t.Fatalf("wrong panic: %v", err)
+			}
+		default:
+			t.Fatalf("unexpected panic value: %T(%v)", err, err)
+		}
+	}()
+	b.Read(make([]byte, 100))
+}
+
+// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have.
+type onlyReader struct {
+	r io.Reader
+}
+
+func (r onlyReader) Read(b []byte) (int, error) {
+	return r.r.Read(b)
+}
+
+// An onlyWriter only implements io.Writer, no matter what other methods the underlying implementation may have.
+type onlyWriter struct {
+	w io.Writer
+}
+
+func (w onlyWriter) Write(b []byte) (int, error) {
+	return w.w.Write(b)
+}
+
+func BenchmarkReaderCopyOptimal(b *testing.B) {
+	// Optimal case is where the underlying reader implements io.WriterTo
+	for i := 0; i < b.N; i++ {
+		b.StopTimer()
+		src := NewReader(bytes.NewBuffer(make([]byte, 8192)))
+		dst := onlyWriter{new(bytes.Buffer)}
+		b.StartTimer()
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkReaderCopyUnoptimal(b *testing.B) {
+	// Unoptimal case is where the underlying reader doesn't implement io.WriterTo
+	for i := 0; i < b.N; i++ {
+		b.StopTimer()
+		src := NewReader(onlyReader{bytes.NewBuffer(make([]byte, 8192))})
+		dst := onlyWriter{new(bytes.Buffer)}
+		b.StartTimer()
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkReaderCopyNoWriteTo(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		b.StopTimer()
+		src := onlyReader{NewReader(bytes.NewBuffer(make([]byte, 8192)))}
+		dst := onlyWriter{new(bytes.Buffer)}
+		b.StartTimer()
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkWriterCopyOptimal(b *testing.B) {
+	// Optimal case is where the underlying writer implements io.ReaderFrom
+	for i := 0; i < b.N; i++ {
+		b.StopTimer()
+		src := onlyReader{bytes.NewBuffer(make([]byte, 8192))}
+		dst := NewWriter(new(bytes.Buffer))
+		b.StartTimer()
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkWriterCopyUnoptimal(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		b.StopTimer()
+		src := onlyReader{bytes.NewBuffer(make([]byte, 8192))}
+		dst := NewWriter(onlyWriter{new(bytes.Buffer)})
+		b.StartTimer()
+		io.Copy(dst, src)
+	}
+}
+
+func BenchmarkWriterCopyNoReadFrom(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		b.StopTimer()
+		src := onlyReader{bytes.NewBuffer(make([]byte, 8192))}
+		dst := onlyWriter{NewWriter(new(bytes.Buffer))}
+		b.StartTimer()
+		io.Copy(dst, src)
+	}
+}
diff --git a/src/pkg/bufio/example_test.go b/src/pkg/bufio/example_test.go
new file mode 100644
index 0000000..b545ce3
--- /dev/null
+++ b/src/pkg/bufio/example_test.go
@@ -0,0 +1,74 @@
+// 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 bufio_test
+
+import (
+	"bufio"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+)
+
+// The simplest use of a Scanner, to read standard input as a set of lines.
+func ExampleScanner_lines() {
+	scanner := bufio.NewScanner(os.Stdin)
+	for scanner.Scan() {
+		fmt.Println(scanner.Text()) // Println will add back the final '\n'
+	}
+	if err := scanner.Err(); err != nil {
+		fmt.Fprintln(os.Stdout, "reading standard input:", err)
+	}
+}
+
+// Use a Scanner to implement a simple word-count utility by scanning the
+// input as a sequence of space-delimited tokens.
+func ExampleScanner_words() {
+	// An artificial input source.
+	const input = "Now is the winter of our discontent,\nMade glorious summer by this sun of York.\n"
+	scanner := bufio.NewScanner(strings.NewReader(input))
+	// Set the split function for the scanning operation.
+	scanner.Split(bufio.ScanWords)
+	// Count the words.
+	count := 0
+	for scanner.Scan() {
+		count++
+	}
+	if err := scanner.Err(); err != nil {
+		fmt.Fprintln(os.Stdout, "reading input:", err)
+	}
+	fmt.Printf("%d\n", count)
+	// Output: 15
+}
+
+// Use a Scanner with a custom split function (built by wrapping ScanWords) to validate
+// 32-bit decimal input.
+func ExampleScanner_custom() {
+	// An artificial input source.
+	const input = "1234 5678 1234567901234567890"
+	scanner := bufio.NewScanner(strings.NewReader(input))
+	// Create a custom split function by wrapping the existing ScanWords function.
+	split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
+		advance, token, err = bufio.ScanWords(data, atEOF)
+		if err == nil && token != nil {
+			_, err = strconv.ParseInt(string(token), 10, 32)
+		}
+		return
+	}
+	// Set the split function for the scanning operation.
+	scanner.Split(split)
+	// Validate the input
+	for scanner.Scan() {
+		fmt.Printf("%s\n", scanner.Text())
+	}
+
+	if err := scanner.Err(); err != nil {
+		fmt.Printf("Invalid input: %s", err)
+	}
+	// Output:
+	// 1234
+	// 5678
+	// Invalid input: strconv.ParseInt: parsing "1234567901234567890": value out of range
+}
diff --git a/src/pkg/bufio/export_test.go b/src/pkg/bufio/export_test.go
new file mode 100644
index 0000000..3d3bb27
--- /dev/null
+++ b/src/pkg/bufio/export_test.go
@@ -0,0 +1,27 @@
+// 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 bufio
+
+// Exported for testing only.
+import (
+	"unicode/utf8"
+)
+
+var IsSpace = isSpace
+
+func (s *Scanner) MaxTokenSize(n int) {
+	if n < utf8.UTFMax || n > 1e9 {
+		panic("bad max token size")
+	}
+	if n < len(s.buf) {
+		s.buf = make([]byte, n)
+	}
+	s.maxTokenSize = n
+}
+
+// ErrOrEOF is like Err, but returns EOF. Used to test a corner case.
+func (s *Scanner) ErrOrEOF() error {
+	return s.err
+}
diff --git a/src/pkg/bufio/scan.go b/src/pkg/bufio/scan.go
new file mode 100644
index 0000000..268ce6d
--- /dev/null
+++ b/src/pkg/bufio/scan.go
@@ -0,0 +1,338 @@
+// 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 bufio
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"unicode/utf8"
+)
+
+// Scanner provides a convenient interface for reading data such as
+// a file of newline-delimited lines of text. Successive calls to
+// the Scan method will step through the 'tokens' of a file, skipping
+// the bytes between the tokens. The specification of a token is
+// defined by a split function of type SplitFunc; the default split
+// function breaks the input into lines with newlines stripped. Split
+// functions are defined in this package for scanning a file into
+// lines, bytes, UTF-8-encoded runes, and space-delimited words. The
+// client may instead provide a custom split function.
+//
+// Scanning stops unrecoverably at EOF, the first I/O error, or a token too
+// large to fit in the buffer. When a scan stops, the reader may have
+// advanced arbitrarily far past the last token. Programs that need more
+// control over error handling or large tokens, or must run sequential scans
+// on a reader, should use bufio.Reader instead.
+//
+// TODO(r): Provide executable examples.
+//
+type Scanner struct {
+	r            io.Reader // The reader provided by the client.
+	split        SplitFunc // The function to split the tokens.
+	maxTokenSize int       // Maximum size of a token; modified by tests.
+	token        []byte    // Last token returned by split.
+	buf          []byte    // Buffer used as argument to split.
+	start        int       // First non-processed byte in buf.
+	end          int       // End of data in buf.
+	err          error     // Sticky error.
+}
+
+// SplitFunc is the signature of the split function used to tokenize the
+// input. The arguments are an initial substring of the remaining unprocessed
+// data and a flag, atEOF, that reports whether the Reader has no more data
+// to give. The return values are the number of bytes to advance the input
+// and the next token to return to the user, plus an error, if any. If the
+// data does not yet hold a complete token, for instance if it has no newline
+// while scanning lines, SplitFunc can return (0, nil) to signal the Scanner
+// to read more data into the slice and try again with a longer slice
+// starting at the same point in the input.
+//
+// If the returned error is non-nil, scanning stops and the error
+// is returned to the client.
+//
+// The function is never called with an empty data slice unless atEOF
+// is true. If atEOF is true, however, data may be non-empty and,
+// as always, holds unprocessed text.
+type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
+
+// Errors returned by Scanner.
+var (
+	ErrTooLong         = errors.New("bufio.Scanner: token too long")
+	ErrNegativeAdvance = errors.New("bufio.Scanner: SplitFunc returns negative advance count")
+	ErrAdvanceTooFar   = errors.New("bufio.Scanner: SplitFunc returns advance count beyond input")
+)
+
+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 = 64 * 1024
+)
+
+// NewScanner returns a new Scanner to read from r.
+func NewScanner(r io.Reader) *Scanner {
+	return &Scanner{
+		r:            r,
+		split:        ScanLines,
+		maxTokenSize: MaxScanTokenSize,
+		buf:          make([]byte, 4096), // Plausible starting size; needn't be large.
+	}
+}
+
+// Err returns the first non-EOF error that was encountered by the Scanner.
+func (s *Scanner) Err() error {
+	if s.err == io.EOF {
+		return nil
+	}
+	return s.err
+}
+
+// Bytes returns the most recent token generated by a call to Scan.
+// The underlying array may point to data that will be overwritten
+// by a subsequent call to Scan. It does no allocation.
+func (s *Scanner) Bytes() []byte {
+	return s.token
+}
+
+// Text returns the most recent token generated by a call to Scan
+// as a newly allocated string holding its bytes.
+func (s *Scanner) Text() string {
+	return string(s.token)
+}
+
+// Scan advances the Scanner to the next token, which will then be
+// available through the Bytes or Text method. It returns false when the
+// scan stops, either by reaching the end of the input or an error.
+// 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.
+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 {
+			advance, token, err := s.split(s.buf[s.start:s.end], s.err != nil)
+			if err != nil {
+				s.setErr(err)
+				return false
+			}
+			if !s.advance(advance) {
+				return false
+			}
+			s.token = token
+			if token != nil {
+				return true
+			}
+		}
+		// We cannot generate a token with what we are holding.
+		// If we've already hit EOF or an I/O error, we are done.
+		if s.err != nil {
+			// Shut it down.
+			s.start = 0
+			s.end = 0
+			return false
+		}
+		// Must read more data.
+		// First, shift data to beginning of buffer if there's lots of empty space
+		// or space is neded.
+		if s.start > 0 && (s.end == len(s.buf) || s.start > len(s.buf)/2) {
+			copy(s.buf, s.buf[s.start:s.end])
+			s.end -= s.start
+			s.start = 0
+		}
+		// Is the buffer full? If so, resize.
+		if s.end == len(s.buf) {
+			if len(s.buf) >= s.maxTokenSize {
+				s.setErr(ErrTooLong)
+				return false
+			}
+			newSize := len(s.buf) * 2
+			if newSize > s.maxTokenSize {
+				newSize = s.maxTokenSize
+			}
+			newBuf := make([]byte, newSize)
+			copy(newBuf, s.buf[s.start:s.end])
+			s.buf = newBuf
+			s.end -= s.start
+			s.start = 0
+			continue
+		}
+		// Finally we can read some input.
+		n, err := s.r.Read(s.buf[s.end:len(s.buf)])
+		if err != nil {
+			s.setErr(err)
+		}
+		if n == 0 { // Don't loop forever if Reader doesn't deliver EOF.
+			s.err = io.EOF
+		}
+		s.end += n
+	}
+	panic("not reached")
+}
+
+// advance consumes n bytes of the buffer. It reports whether the advance was legal.
+func (s *Scanner) advance(n int) bool {
+	if n < 0 {
+		s.setErr(ErrNegativeAdvance)
+		return false
+	}
+	if n > s.end-s.start {
+		s.setErr(ErrAdvanceTooFar)
+		return false
+	}
+	s.start += n
+	return true
+}
+
+// setErr records the first error encountered.
+func (s *Scanner) setErr(err error) {
+	if s.err == nil || s.err == io.EOF {
+		s.err = err
+	}
+}
+
+// Split sets the split function for the Scanner. If called, it must be
+// called before Scan. The default split function is ScanLines.
+func (s *Scanner) Split(split SplitFunc) {
+	s.split = split
+}
+
+// Split functions
+
+// ScanBytes is a split function for a Scanner that returns each byte as a token.
+func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
+	if atEOF && len(data) == 0 {
+		return 0, nil, nil
+	}
+	return 1, data[0:1], nil
+}
+
+var errorRune = []byte(string(utf8.RuneError))
+
+// ScanRunes is a split function for a Scanner that returns each
+// UTF-8-encoded rune as a token. The sequence of runes returned is
+// equivalent to that from a range loop over the input as a string, which
+// means that erroneous UTF-8 encodings translate to U+FFFD = "\xef\xbf\xbd".
+// Because of the Scan interface, this makes it impossible for the client to
+// distinguish correctly encoded replacement runes from encoding errors.
+func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error) {
+	if atEOF && len(data) == 0 {
+		return 0, nil, nil
+	}
+
+	// Fast path 1: ASCII.
+	if data[0] < utf8.RuneSelf {
+		return 1, data[0:1], nil
+	}
+
+	// Fast path 2: Correct UTF-8 decode without error.
+	_, width := utf8.DecodeRune(data)
+	if width > 1 {
+		// It's a valid encoding. Width cannot be one for a correctly encoded
+		// non-ASCII rune.
+		return width, data[0:width], nil
+	}
+
+	// We know it's an error: we have width==1 and implicitly r==utf8.RuneError.
+	// Is the error because there wasn't a full rune to be decoded?
+	// FullRune distinguishes correctly between erroneous and incomplete encodings.
+	if !atEOF && !utf8.FullRune(data) {
+		// Incomplete; get more bytes.
+		return 0, nil, nil
+	}
+
+	// We have a real UTF-8 encoding error. Return a properly encoded error rune
+	// but advance only one byte. This matches the behavior of a range loop over
+	// an incorrectly encoded string.
+	return 1, errorRune, nil
+}
+
+// dropCR drops a terminal \r from the data.
+func dropCR(data []byte) []byte {
+	if len(data) > 0 && data[len(data)-1] == '\r' {
+		return data[0 : len(data)-1]
+	}
+	return data
+}
+
+// ScanLines is a split function for a Scanner that returns each line of
+// text, stripped of any trailing end-of-line marker. The returned line may
+// be empty. The end-of-line marker is one optional carriage return followed
+// by one mandatory newline. In regular expression notation, it is `\r?\n'.
+// The last non-empty line of input will be returned even if it has no
+// newline.
+func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
+	if atEOF && len(data) == 0 {
+		return 0, nil, nil
+	}
+	if i := bytes.IndexByte(data, '\n'); i >= 0 {
+		// We have a full newline-terminated line.
+		return i + 1, dropCR(data[0:i]), nil
+	}
+	// If we're at EOF, we have a final, non-terminated line. Return it.
+	if atEOF {
+		return len(data), dropCR(data), nil
+	}
+	// Request more data.
+	return 0, nil, nil
+}
+
+// isSpace returns whether the character is a Unicode white space character.
+// We avoid dependency on the unicode package, but check validity of the implementation
+// in the tests.
+func isSpace(r rune) bool {
+	if r <= '\u00FF' {
+		// Obvious ASCII ones: \t through \r plus space. Plus two Latin-1 oddballs.
+		switch r {
+		case ' ', '\t', '\n', '\v', '\f', '\r':
+			return true
+		case '\u0085', '\u00A0':
+			return true
+		}
+		return false
+	}
+	// High-valued ones.
+	if '\u2000' <= r && r <= '\u200a' {
+		return true
+	}
+	switch r {
+	case '\u1680', '\u180e', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000':
+		return true
+	}
+	return false
+}
+
+// ScanWords is a split function for a Scanner that returns each
+// space-separated word of text, with surrounding spaces deleted. It will
+// never return an empty string. The definition of space is set by
+// unicode.IsSpace.
+func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) {
+	// Skip leading spaces.
+	start := 0
+	for width := 0; start < len(data); start += width {
+		var r rune
+		r, width = utf8.DecodeRune(data[start:])
+		if !isSpace(r) {
+			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
+		r, width = utf8.DecodeRune(data[i:])
+		if isSpace(r) {
+			return i + width, data[start:i], nil
+		}
+	}
+	// If we're at EOF, we have a final, non-empty, non-terminated word. Return it.
+	if atEOF && len(data) > start {
+		return len(data), data[start:], nil
+	}
+	// Request more data.
+	return 0, nil, nil
+}
diff --git a/src/pkg/bufio/scan_test.go b/src/pkg/bufio/scan_test.go
new file mode 100644
index 0000000..48729aa
--- /dev/null
+++ b/src/pkg/bufio/scan_test.go
@@ -0,0 +1,370 @@
+// 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 bufio_test
+
+import (
+	. "bufio"
+	"bytes"
+	"errors"
+	"io"
+	"strings"
+	"testing"
+	"unicode"
+	"unicode/utf8"
+)
+
+// Test white space table matches the Unicode definition.
+func TestSpace(t *testing.T) {
+	for r := rune(0); r <= utf8.MaxRune; r++ {
+		if IsSpace(r) != unicode.IsSpace(r) {
+			t.Fatalf("white space property disagrees: %#U should be %t", r, unicode.IsSpace(r))
+		}
+	}
+}
+
+var scanTests = []string{
+	"",
+	"a",
+	"¼",
+	"☹",
+	"\x81",   // UTF-8 error
+	"\uFFFD", // correctly encoded RuneError
+	"abcdefgh",
+	"abc def\n\t\tgh    ",
+	"abc¼☹\x81\uFFFD日本語\x82abc",
+}
+
+func TestScanByte(t *testing.T) {
+	for n, test := range scanTests {
+		buf := bytes.NewBufferString(test)
+		s := NewScanner(buf)
+		s.Split(ScanBytes)
+		var i int
+		for i = 0; s.Scan(); i++ {
+			if b := s.Bytes(); len(b) != 1 || b[0] != test[i] {
+				t.Errorf("#%d: %d: expected %q got %q", n, i, test, b)
+			}
+		}
+		if i != len(test) {
+			t.Errorf("#%d: termination expected at %d; got %d", n, len(test), i)
+		}
+		err := s.Err()
+		if err != nil {
+			t.Errorf("#%d: %v", n, err)
+		}
+	}
+}
+
+// Test that the rune splitter returns same sequence of runes (not bytes) as for range string.
+func TestScanRune(t *testing.T) {
+	for n, test := range scanTests {
+		buf := bytes.NewBufferString(test)
+		s := NewScanner(buf)
+		s.Split(ScanRunes)
+		var i, runeCount int
+		var expect rune
+		// Use a string range loop to validate the sequence of runes.
+		for i, expect = range string(test) {
+			if !s.Scan() {
+				break
+			}
+			runeCount++
+			got, _ := utf8.DecodeRune(s.Bytes())
+			if got != expect {
+				t.Errorf("#%d: %d: expected %q got %q", n, i, expect, got)
+			}
+		}
+		if s.Scan() {
+			t.Errorf("#%d: scan ran too long, got %q", n, s.Text())
+		}
+		testRuneCount := utf8.RuneCountInString(test)
+		if runeCount != testRuneCount {
+			t.Errorf("#%d: termination expected at %d; got %d", n, testRuneCount, runeCount)
+		}
+		err := s.Err()
+		if err != nil {
+			t.Errorf("#%d: %v", n, err)
+		}
+	}
+}
+
+var wordScanTests = []string{
+	"",
+	" ",
+	"\n",
+	"a",
+	" a ",
+	"abc def",
+	" abc def ",
+	" abc\tdef\nghi\rjkl\fmno\vpqr\u0085stu\u00a0\n",
+}
+
+// Test that the word splitter returns the same data as strings.Fields.
+func TestScanWords(t *testing.T) {
+	for n, test := range wordScanTests {
+		buf := bytes.NewBufferString(test)
+		s := NewScanner(buf)
+		s.Split(ScanWords)
+		words := strings.Fields(test)
+		var wordCount int
+		for wordCount = 0; wordCount < len(words); wordCount++ {
+			if !s.Scan() {
+				break
+			}
+			got := s.Text()
+			if got != words[wordCount] {
+				t.Errorf("#%d: %d: expected %q got %q", n, wordCount, words[wordCount], got)
+			}
+		}
+		if s.Scan() {
+			t.Errorf("#%d: scan ran too long, got %q", n, s.Text())
+		}
+		if wordCount != len(words) {
+			t.Errorf("#%d: termination expected at %d; got %d", n, len(words), wordCount)
+		}
+		err := s.Err()
+		if err != nil {
+			t.Errorf("#%d: %v", n, err)
+		}
+	}
+}
+
+// slowReader is a reader that returns only a few bytes at a time, to test the incremental
+// reads in Scanner.Scan.
+type slowReader struct {
+	max int
+	buf *bytes.Buffer
+}
+
+func (sr *slowReader) Read(p []byte) (n int, err error) {
+	if len(p) > sr.max {
+		p = p[0:sr.max]
+	}
+	return sr.buf.Read(p)
+}
+
+// genLine writes to buf a predictable but non-trivial line of text of length
+// n, including the terminal newline and an occasional carriage return.
+// If addNewline is false, the \r and \n are not emitted.
+func genLine(buf *bytes.Buffer, lineNum, n int, addNewline bool) {
+	buf.Reset()
+	doCR := lineNum%5 == 0
+	if doCR {
+		n--
+	}
+	for i := 0; i < n-1; i++ { // Stop early for \n.
+		c := 'a' + byte(lineNum+i)
+		if c == '\n' || c == '\r' { // Don't confuse us.
+			c = 'N'
+		}
+		buf.WriteByte(c)
+	}
+	if addNewline {
+		if doCR {
+			buf.WriteByte('\r')
+		}
+		buf.WriteByte('\n')
+	}
+	return
+}
+
+// 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)
+	lineNum := 0
+	j := 0
+	for i := 0; i < 2*smallMaxTokenSize; i++ {
+		genLine(tmp, lineNum, j, true)
+		if j < smallMaxTokenSize {
+			j++
+		} else {
+			j--
+		}
+		buf.Write(tmp.Bytes())
+		lineNum++
+	}
+	s := NewScanner(&slowReader{1, buf})
+	s.Split(ScanLines)
+	s.MaxTokenSize(smallMaxTokenSize)
+	j = 0
+	for lineNum := 0; s.Scan(); lineNum++ {
+		genLine(tmp, lineNum, j, false)
+		if j < smallMaxTokenSize {
+			j++
+		} else {
+			j--
+		}
+		line := tmp.String() // We use the string-valued token here, for variety.
+		if s.Text() != line {
+			t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Text(), line)
+		}
+	}
+	err := s.Err()
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+// Test that the line splitter errors out on a long line.
+func TestScanLineTooLong(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)
+	lineNum := 0
+	j := 0
+	for i := 0; i < 2*smallMaxTokenSize; i++ {
+		genLine(tmp, lineNum, j, true)
+		j++
+		buf.Write(tmp.Bytes())
+		lineNum++
+	}
+	s := NewScanner(&slowReader{3, buf})
+	s.Split(ScanLines)
+	s.MaxTokenSize(smallMaxTokenSize)
+	j = 0
+	for lineNum := 0; s.Scan(); lineNum++ {
+		genLine(tmp, lineNum, j, false)
+		if j < smallMaxTokenSize {
+			j++
+		} else {
+			j--
+		}
+		line := tmp.Bytes()
+		if !bytes.Equal(s.Bytes(), line) {
+			t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Bytes(), line)
+		}
+	}
+	err := s.Err()
+	if err != ErrTooLong {
+		t.Fatalf("expected ErrTooLong; got %s", err)
+	}
+}
+
+// Test that the line splitter handles a final line without a newline.
+func testNoNewline(text string, lines []string, t *testing.T) {
+	buf := bytes.NewBufferString(text)
+	s := NewScanner(&slowReader{7, buf})
+	s.Split(ScanLines)
+	for lineNum := 0; s.Scan(); lineNum++ {
+		line := lines[lineNum]
+		if s.Text() != line {
+			t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Bytes(), line)
+		}
+	}
+	err := s.Err()
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+var noNewlineLines = []string{
+	"abcdefghijklmn\nopqrstuvwxyz",
+}
+
+// Test that the line splitter handles a final line without a newline.
+func TestScanLineNoNewline(t *testing.T) {
+	const text = "abcdefghijklmn\nopqrstuvwxyz"
+	lines := []string{
+		"abcdefghijklmn",
+		"opqrstuvwxyz",
+	}
+	testNoNewline(text, lines, t)
+}
+
+// Test that the line splitter handles a final line with a carriage return but nonewline.
+func TestScanLineReturnButNoNewline(t *testing.T) {
+	const text = "abcdefghijklmn\nopqrstuvwxyz\r"
+	lines := []string{
+		"abcdefghijklmn",
+		"opqrstuvwxyz",
+	}
+	testNoNewline(text, lines, t)
+}
+
+// Test that the line splitter handles a final empty line.
+func TestScanLineEmptyFinalLine(t *testing.T) {
+	const text = "abcdefghijklmn\nopqrstuvwxyz\n\n"
+	lines := []string{
+		"abcdefghijklmn",
+		"opqrstuvwxyz",
+		"",
+	}
+	testNoNewline(text, lines, t)
+}
+
+// Test that the line splitter handles a final empty line with a carriage return but no newline.
+func TestScanLineEmptyFinalLineWithCR(t *testing.T) {
+	const text = "abcdefghijklmn\nopqrstuvwxyz\n\r"
+	lines := []string{
+		"abcdefghijklmn",
+		"opqrstuvwxyz",
+		"",
+	}
+	testNoNewline(text, lines, t)
+}
+
+var testError = errors.New("testError")
+
+// Test the correct error is returned when the split function errors out.
+func TestSplitError(t *testing.T) {
+	// Create a split function that delivers a little data, then a predictable error.
+	numSplits := 0
+	const okCount = 7
+	errorSplit := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
+		if atEOF {
+			panic("didn't get enough data")
+		}
+		if numSplits >= okCount {
+			return 0, nil, testError
+		}
+		numSplits++
+		return 1, data[0:1], nil
+	}
+	// Read the data.
+	const text = "abcdefghijklmnopqrstuvwxyz"
+	buf := bytes.NewBufferString(text)
+	s := NewScanner(&slowReader{1, buf})
+	s.Split(errorSplit)
+	var i int
+	for i = 0; s.Scan(); i++ {
+		if len(s.Bytes()) != 1 || text[i] != s.Bytes()[0] {
+			t.Errorf("#%d: expected %q got %q", i, text[i], s.Bytes()[0])
+		}
+	}
+	// Check correct termination location and error.
+	if i != okCount {
+		t.Errorf("unexpected termination; expected %d tokens got %d", okCount, i)
+	}
+	err := s.Err()
+	if err != testError {
+		t.Fatalf("expected %q got %v", testError, err)
+	}
+}
+
+// Test that an EOF is overridden by a user-generated scan error.
+func TestErrAtEOF(t *testing.T) {
+	s := NewScanner(strings.NewReader("1 2 33"))
+	// This spitter will fail on last entry, after s.err==EOF.
+	split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
+		advance, token, err = ScanWords(data, atEOF)
+		if len(token) > 1 {
+			if s.ErrOrEOF() != io.EOF {
+				t.Fatal("not testing EOF")
+			}
+			err = testError
+		}
+		return
+	}
+	s.Split(split)
+	for s.Scan() {
+	}
+	if s.Err() != testError {
+		t.Fatal("wrong error:", s.Err())
+	}
+}
diff --git a/src/pkg/builtin/builtin.go b/src/pkg/builtin/builtin.go
index e81616c..7b5e9ab 100644
--- a/src/pkg/builtin/builtin.go
+++ b/src/pkg/builtin/builtin.go
@@ -81,9 +81,8 @@ type uintptr uintptr
 // integer values.
 type byte byte
 
-// rune is an alias for int and is equivalent to int in all ways. It is
+// rune is an alias for int32 and is equivalent to int32 in all ways. It is
 // used, by convention, to distinguish character values from integer values.
-// In a future version of Go, it will change to an alias of int32.
 type rune rune
 
 // Type is here for the purposes of documentation only. It is a stand-in
@@ -115,6 +114,8 @@ type ComplexType complex64
 // result of append, often in the variable holding the slice itself:
 //	slice = append(slice, elem1, elem2)
 //	slice = append(slice, anotherSlice...)
+// As a special case, it is legal to append a string to a byte slice, like this:
+//	slice = append([]byte("hello "), "world"...)
 func append(slice []Type, elems ...Type) []Type
 
 // The copy built-in function copies elements from a source slice into a
@@ -125,8 +126,8 @@ func append(slice []Type, elems ...Type) []Type
 func copy(dst, src []Type) int
 
 // The delete built-in function deletes the element with the specified key
-// (m[key]) from the map. If there is no such element, delete is a no-op.
-// If m is nil, delete panics.
+// (m[key]) from the map. If m is nil or there is no such element, delete
+// is a no-op.
 func delete(m map[Type]Type1, key Type)
 
 // The len built-in function returns the length of v, according to its type:
diff --git a/src/pkg/bytes/asm_386.s b/src/pkg/bytes/asm_386.s
index e7833de..c444b55 100644
--- a/src/pkg/bytes/asm_386.s
+++ b/src/pkg/bytes/asm_386.s
@@ -3,31 +3,31 @@
 // license that can be found in the LICENSE file.
 
 TEXT ·IndexByte(SB),7,$0
-	MOVL	p+0(FP), SI
-	MOVL	len+4(FP), CX
-	MOVB	b+12(FP), AL
+	MOVL	s+0(FP), SI
+	MOVL	s+4(FP), CX
+	MOVB	c+12(FP), AL
 	MOVL	SI, DI
 	CLD; REPN; SCASB
 	JZ 3(PC)
-	MOVL	$-1, ret+16(FP)
+	MOVL	$-1, r+16(FP)
 	RET
 	SUBL	SI, DI
 	SUBL	$1, DI
-	MOVL	DI, ret+16(FP)
+	MOVL	DI, r+16(FP)
 	RET
 
 TEXT ·Equal(SB),7,$0
-	MOVL	len+4(FP), BX
-	MOVL	len1+16(FP), CX
+	MOVL	a+4(FP), BX
+	MOVL	b+16(FP), CX
 	MOVL	$0, AX
 	CMPL	BX, CX
 	JNE	eqret
-	MOVL	p+0(FP), SI
-	MOVL	q+12(FP), DI
+	MOVL	a+0(FP), SI
+	MOVL	b+12(FP), DI
 	CLD
 	REP; CMPSB
 	JNE eqret
 	MOVL	$1, AX
 eqret:
-	MOVB	AX, ret+24(FP)
+	MOVB	AX, r+24(FP)
 	RET
diff --git a/src/pkg/bytes/asm_amd64.s b/src/pkg/bytes/asm_amd64.s
index 5caea5c..4824226 100644
--- a/src/pkg/bytes/asm_amd64.s
+++ b/src/pkg/bytes/asm_amd64.s
@@ -3,12 +3,12 @@
 // license that can be found in the LICENSE file.
 
 TEXT ·IndexByte(SB),7,$0
-	MOVQ p+0(FP), SI
-	MOVL len+8(FP), BX
-	MOVB b+16(FP), AL
+	MOVQ s+0(FP), SI
+	MOVQ s+8(FP), BX
+	MOVB c+24(FP), AL
 	MOVQ SI, DI
 
-	CMPL BX, $16
+	CMPQ BX, $16
 	JLT small
 
 	// round up to first 16-byte boundary
@@ -63,15 +63,15 @@ condition:
 	JZ success
 
 failure:
-	MOVL $-1, ret+24(FP)
+	MOVQ $-1, r+32(FP)
 	RET
 
 // handle for lengths < 16
 small:
-	MOVL BX, CX
+	MOVQ BX, CX
 	REPN; SCASB
 	JZ success
-	MOVL $-1, ret+24(FP)
+	MOVQ $-1, r+32(FP)
 	RET
 
 // we've found the chunk containing the byte
@@ -81,28 +81,28 @@ ssesuccess:
 	BSFW DX, DX
 	SUBQ SI, DI
 	ADDQ DI, DX
-	MOVL DX, ret+24(FP)
+	MOVQ DX, r+32(FP)
 	RET
 
 success:
 	SUBQ SI, DI
 	SUBL $1, DI
-	MOVL DI, ret+24(FP)
+	MOVQ DI, r+32(FP)
 	RET
 
 TEXT ·Equal(SB),7,$0
-	MOVL	len+8(FP), BX
-	MOVL	len1+24(FP), CX
+	MOVQ	a+8(FP), BX
+	MOVQ	b+32(FP), CX
 	MOVL	$0, AX
-	CMPL	BX, CX
+	CMPQ	BX, CX
 	JNE	eqret
-	MOVQ	p+0(FP), SI
-	MOVQ	q+16(FP), DI
+	MOVQ	a+0(FP), SI
+	MOVQ	b+24(FP), DI
 	CLD
 	REP; CMPSB
 	MOVL	$1, DX
 	CMOVLEQ	DX, AX
 eqret:
-	MOVB	AX, ret+32(FP)
+	MOVB	AX, r+48(FP)
 	RET
 
diff --git a/src/pkg/bytes/asm_arm.s b/src/pkg/bytes/asm_arm.s
index 4ed0c15..c7685f0 100644
--- a/src/pkg/bytes/asm_arm.s
+++ b/src/pkg/bytes/asm_arm.s
@@ -2,10 +2,55 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// no memchr implementation on arm yet
 TEXT ·IndexByte(SB),7,$0
-	B	·indexBytePortable(SB)
+	MOVW	s+0(FP), R0
+	MOVW	s+4(FP), R1
+	MOVBU	c+12(FP), R2	// byte to find
+	MOVW	R0, R4		// store base for later
+	ADD	R0, R1		// end 
+
+_loop:
+	CMP	R0, R1
+	B.EQ	_notfound
+	MOVBU.P	1(R0), R3
+	CMP	R2, R3
+	B.NE	_loop
+
+	SUB	$1, R0		// R0 will be one beyond the position we want
+	SUB	R4, R0		// remove base
+	MOVW    R0, r+16(FP) 
+	RET
+
+_notfound:
+	MOVW	$-1, R0
+	MOVW	R0, r+16(FP)
+	RET
 
-// no memcmp implementation on arm yet
 TEXT ·Equal(SB),7,$0
-	B	·equalPortable(SB)
+	MOVW	a+4(FP), R1
+	MOVW	b+16(FP), R3
+	
+	CMP	R1, R3		// unequal lengths are not equal
+	B.NE	_notequal
+
+	MOVW	a+0(FP), R0
+	MOVW	b+12(FP), R2
+	ADD	R0, R1		// end
+
+_next:
+	CMP	R0, R1
+	B.EQ	_equal		// reached the end
+	MOVBU.P	1(R0), R4
+	MOVBU.P	1(R2), R5
+	CMP	R4, R5
+	B.EQ	_next
+
+_notequal:
+	MOVW	$0, R0
+	MOVBU	R0, r+24(FP)
+	RET
+
+_equal:
+	MOVW	$1, R0
+	MOVBU	R0, r+24(FP)
+	RET
diff --git a/src/pkg/bytes/buffer.go b/src/pkg/bytes/buffer.go
index afdf220..85c1577 100644
--- a/src/pkg/bytes/buffer.go
+++ b/src/pkg/bytes/buffer.go
@@ -99,6 +99,19 @@ func (b *Buffer) grow(n int) int {
 	return b.off + m
 }
 
+// Grow grows the buffer's capacity, if necessary, to guarantee space for
+// another n bytes. After Grow(n), at least n bytes can be written to the
+// buffer without another allocation.
+// If n is negative, Grow will panic.
+// If the buffer can't grow it will panic with ErrTooLarge.
+func (b *Buffer) Grow(n int) {
+	if n < 0 {
+		panic("bytes.Buffer.Grow: negative count")
+	}
+	m := b.grow(n)
+	b.buf = b.buf[0:m]
+}
+
 // Write appends the contents of p to the buffer.  The return
 // value n is the length of p; err is always nil.
 // If the buffer becomes too large, Write will panic with
@@ -347,16 +360,25 @@ func (b *Buffer) UnreadByte() error {
 // ReadBytes returns err != nil if and only if the returned data does not end in
 // delim.
 func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
+	slice, err := b.readSlice(delim)
+	// return a copy of slice. The buffer's backing array may
+	// be overwritten by later calls.
+	line = append(line, slice...)
+	return
+}
+
+// readSlice is like ReadBytes but returns a reference to internal buffer data.
+func (b *Buffer) readSlice(delim byte) (line []byte, err error) {
 	i := IndexByte(b.buf[b.off:], delim)
-	size := i + 1
+	end := b.off + i + 1
 	if i < 0 {
-		size = len(b.buf) - b.off
+		end = len(b.buf)
 		err = io.EOF
 	}
-	line = make([]byte, size)
-	copy(line, b.buf[b.off:])
-	b.off += size
-	return
+	line = b.buf[b.off:end]
+	b.off = end
+	b.lastRead = opRead
+	return line, err
 }
 
 // ReadString reads until the first occurrence of delim in the input,
@@ -366,8 +388,8 @@ func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
 // ReadString returns err != nil if and only if the returned data does not end
 // in delim.
 func (b *Buffer) ReadString(delim byte) (line string, err error) {
-	bytes, err := b.ReadBytes(delim)
-	return string(bytes), err
+	slice, err := b.readSlice(delim)
+	return string(slice), err
 }
 
 // NewBuffer creates and initializes a new Buffer using buf as its initial
diff --git a/src/pkg/bytes/buffer_test.go b/src/pkg/bytes/buffer_test.go
index d0af11f..f9fb262 100644
--- a/src/pkg/bytes/buffer_test.go
+++ b/src/pkg/bytes/buffer_test.go
@@ -8,20 +8,21 @@ import (
 	. "bytes"
 	"io"
 	"math/rand"
+	"runtime"
 	"testing"
 	"unicode/utf8"
 )
 
-const N = 10000  // make this bigger for a larger (and slower) test
-var data string  // test data for write tests
-var bytes []byte // test data; same as data but as a slice.
+const N = 10000      // make this bigger for a larger (and slower) test
+var data string      // test data for write tests
+var testBytes []byte // test data; same as data but as a slice.
 
 func init() {
-	bytes = make([]byte, N)
+	testBytes = make([]byte, N)
 	for i := 0; i < N; i++ {
-		bytes[i] = 'a' + byte(i%26)
+		testBytes[i] = 'a' + byte(i%26)
 	}
-	data = string(bytes)
+	data = string(testBytes)
 }
 
 // Verify that contents of buf match the string s.
@@ -84,7 +85,7 @@ func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub
 }
 
 func TestNewBuffer(t *testing.T) {
-	buf := NewBuffer(bytes)
+	buf := NewBuffer(testBytes)
 	check(t, "NewBuffer", buf, data)
 }
 
@@ -187,7 +188,7 @@ func TestLargeByteWrites(t *testing.T) {
 		limit = 9
 	}
 	for i := 3; i < limit; i += 3 {
-		s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, bytes)
+		s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, testBytes)
 		empty(t, "TestLargeByteWrites (2)", &buf, s, make([]byte, len(data)/i))
 	}
 	check(t, "TestLargeByteWrites (3)", &buf, "")
@@ -205,7 +206,7 @@ func TestLargeStringReads(t *testing.T) {
 func TestLargeByteReads(t *testing.T) {
 	var buf Buffer
 	for i := 3; i < 30; i += 3 {
-		s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, bytes[0:len(bytes)/i])
+		s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
 		empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data)))
 	}
 	check(t, "TestLargeByteReads (3)", &buf, "")
@@ -219,7 +220,7 @@ func TestMixedReadsAndWrites(t *testing.T) {
 		if i%2 == 0 {
 			s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0:wlen])
 		} else {
-			s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, bytes[0:wlen])
+			s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testBytes[0:wlen])
 		}
 
 		rlen := rand.Intn(len(data))
@@ -240,7 +241,7 @@ func TestNil(t *testing.T) {
 func TestReadFrom(t *testing.T) {
 	var buf Buffer
 	for i := 3; i < 30; i += 3 {
-		s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, bytes[0:len(bytes)/i])
+		s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
 		var b Buffer
 		b.ReadFrom(&buf)
 		empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(data)))
@@ -250,16 +251,16 @@ func TestReadFrom(t *testing.T) {
 func TestWriteTo(t *testing.T) {
 	var buf Buffer
 	for i := 3; i < 30; i += 3 {
-		s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, bytes[0:len(bytes)/i])
+		s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
 		var b Buffer
 		buf.WriteTo(&b)
-		empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(data)))
+		empty(t, "TestWriteTo (2)", &b, s, make([]byte, len(data)))
 	}
 }
 
 func TestRuneIO(t *testing.T) {
 	const NRune = 1000
-	// Built a test array while we write the data
+	// Built a test slice while we write the data
 	b := make([]byte, utf8.UTFMax*NRune)
 	var buf Buffer
 	n := 0
@@ -374,6 +375,72 @@ func TestReadBytes(t *testing.T) {
 	}
 }
 
+func TestReadString(t *testing.T) {
+	for _, test := range readBytesTests {
+		buf := NewBufferString(test.buffer)
+		var err error
+		for _, expected := range test.expected {
+			var s string
+			s, err = buf.ReadString(test.delim)
+			if s != expected {
+				t.Errorf("expected %q, got %q", expected, s)
+			}
+			if err != nil {
+				break
+			}
+		}
+		if err != test.err {
+			t.Errorf("expected error %v, got %v", test.err, err)
+		}
+	}
+}
+
+func BenchmarkReadString(b *testing.B) {
+	const n = 32 << 10
+
+	data := make([]byte, n)
+	data[n-1] = 'x'
+	b.SetBytes(int64(n))
+	for i := 0; i < b.N; i++ {
+		buf := NewBuffer(data)
+		_, err := buf.ReadString('x')
+		if err != nil {
+			b.Fatal(err)
+		}
+	}
+}
+
+func TestGrow(t *testing.T) {
+	x := []byte{'x'}
+	y := []byte{'y'}
+	tmp := make([]byte, 72)
+	for _, startLen := range []int{0, 100, 1000, 10000, 100000} {
+		xBytes := Repeat(x, startLen)
+		for _, growLen := range []int{0, 100, 1000, 10000, 100000} {
+			buf := NewBuffer(xBytes)
+			// If we read, this affects buf.off, which is good to test.
+			readBytes, _ := buf.Read(tmp)
+			buf.Grow(growLen)
+			yBytes := Repeat(y, growLen)
+			// Check no allocation occurs in write, as long as we're single-threaded.
+			var m1, m2 runtime.MemStats
+			runtime.ReadMemStats(&m1)
+			buf.Write(yBytes)
+			runtime.ReadMemStats(&m2)
+			if runtime.GOMAXPROCS(-1) == 1 && m1.Mallocs != m2.Mallocs {
+				t.Errorf("allocation occurred during write")
+			}
+			// Check that buffer has correct data.
+			if !Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) {
+				t.Errorf("bad initial data at %d %d", startLen, growLen)
+			}
+			if !Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) {
+				t.Errorf("bad written data at %d %d", startLen, growLen)
+			}
+		}
+	}
+}
+
 // Was a bug: used to give EOF reading empty slice at EOF.
 func TestReadEmptyAtEOF(t *testing.T) {
 	b := new(Buffer)
@@ -386,3 +453,25 @@ func TestReadEmptyAtEOF(t *testing.T) {
 		t.Errorf("wrong count; got %d want 0", n)
 	}
 }
+
+func TestUnreadByte(t *testing.T) {
+	b := new(Buffer)
+	b.WriteString("abcdefghijklmnopqrstuvwxyz")
+
+	_, err := b.ReadBytes('m')
+	if err != nil {
+		t.Fatalf("ReadBytes: %v", err)
+	}
+
+	err = b.UnreadByte()
+	if err != nil {
+		t.Fatalf("UnreadByte: %v", err)
+	}
+	c, err := b.ReadByte()
+	if err != nil {
+		t.Fatalf("ReadByte: %v", err)
+	}
+	if c != 'm' {
+		t.Errorf("ReadByte = %q; want %q", c, 'm')
+	}
+}
diff --git a/src/pkg/bytes/bytes.go b/src/pkg/bytes/bytes.go
index 7d1426f..3bab65e 100644
--- a/src/pkg/bytes/bytes.go
+++ b/src/pkg/bytes/bytes.go
@@ -11,8 +11,8 @@ import (
 	"unicode/utf8"
 )
 
-// Compare returns an integer comparing the two byte arrays lexicographically.
-// The result will be 0 if a==b, -1 if a < b, and +1 if a > b
+// Compare returns an integer comparing two byte slices lexicographically.
+// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
 // A nil argument is equivalent to an empty slice.
 func Compare(a, b []byte) int {
 	m := len(a)
@@ -37,10 +37,6 @@ func Compare(a, b []byte) int {
 	return 0
 }
 
-// Equal returns a boolean reporting whether a == b.
-// A nil argument is equivalent to an empty slice.
-func Equal(a, b []byte) bool
-
 func equalPortable(a, b []byte) bool {
 	if len(a) != len(b) {
 		return false
@@ -53,8 +49,8 @@ func equalPortable(a, b []byte) bool {
 	return true
 }
 
-// explode splits s into an array of UTF-8 sequences, one per Unicode character (still arrays of bytes),
-// up to a maximum of n byte arrays. Invalid UTF-8 sequences are chopped into individual bytes.
+// explode splits s into a slice of UTF-8 sequences, one per Unicode character (still slices of bytes),
+// up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes.
 func explode(s []byte, n int) [][]byte {
 	if n <= 0 {
 		n = len(s)
@@ -226,7 +222,7 @@ func LastIndexAny(s []byte, chars string) int {
 }
 
 // Generic split: splits after each instance of sep,
-// including sepSave bytes of sep in the subarrays.
+// including sepSave bytes of sep in the subslices.
 func genSplit(s, sep []byte, sepSave, n int) [][]byte {
 	if n == 0 {
 		return nil
@@ -287,15 +283,15 @@ func SplitAfter(s, sep []byte) [][]byte {
 	return genSplit(s, sep, len(sep), -1)
 }
 
-// Fields splits the array s around each instance of one or more consecutive white space
-// characters, returning a slice of subarrays of s or an empty list if s contains only white space.
+// Fields splits the slice s around each instance of one or more consecutive white space
+// characters, returning a slice of subslices of s or an empty list if s contains only white space.
 func Fields(s []byte) [][]byte {
 	return FieldsFunc(s, unicode.IsSpace)
 }
 
 // FieldsFunc interprets s as a sequence of UTF-8-encoded Unicode code points.
-// It splits the array s at each run of code points c satisfying f(c) and
-// returns a slice of subarrays of s.  If no code points in s satisfy f(c), an
+// It splits the slice s at each run of code points c satisfying f(c) and
+// returns a slice of subslices of s.  If no code points in s satisfy f(c), an
 // empty slice is returned.
 func FieldsFunc(s []byte, f func(rune) bool) [][]byte {
 	n := 0
@@ -333,45 +329,46 @@ func FieldsFunc(s []byte, f func(rune) bool) [][]byte {
 	return a[0:na]
 }
 
-// Join concatenates the elements of a to create a single byte array.   The separator
-// sep is placed between elements in the resulting array.
-func Join(a [][]byte, sep []byte) []byte {
-	if len(a) == 0 {
+// Join concatenates the elements of s to create a new byte slice. The separator
+// sep is placed between elements in the resulting slice.
+func Join(s [][]byte, sep []byte) []byte {
+	if len(s) == 0 {
 		return []byte{}
 	}
-	if len(a) == 1 {
-		return a[0]
+	if len(s) == 1 {
+		// Just return a copy.
+		return append([]byte(nil), s[0]...)
 	}
-	n := len(sep) * (len(a) - 1)
-	for i := 0; i < len(a); i++ {
-		n += len(a[i])
+	n := len(sep) * (len(s) - 1)
+	for _, v := range s {
+		n += len(v)
 	}
 
 	b := make([]byte, n)
-	bp := copy(b, a[0])
-	for _, s := range a[1:] {
+	bp := copy(b, s[0])
+	for _, v := range s[1:] {
 		bp += copy(b[bp:], sep)
-		bp += copy(b[bp:], s)
+		bp += copy(b[bp:], v)
 	}
 	return b
 }
 
-// HasPrefix tests whether the byte array s begins with prefix.
+// HasPrefix tests whether the byte slice s begins with prefix.
 func HasPrefix(s, prefix []byte) bool {
 	return len(s) >= len(prefix) && Equal(s[0:len(prefix)], prefix)
 }
 
-// HasSuffix tests whether the byte array s ends with suffix.
+// HasSuffix tests whether the byte slice s ends with suffix.
 func HasSuffix(s, suffix []byte) bool {
 	return len(s) >= len(suffix) && Equal(s[len(s)-len(suffix):], suffix)
 }
 
-// Map returns a copy of the byte array s with all its characters modified
+// Map returns a copy of the byte slice s with all its characters modified
 // according to the mapping function. If mapping returns a negative value, the character is
 // dropped from the string with no replacement.  The characters in s and the
 // output are interpreted as UTF-8-encoded Unicode code points.
 func Map(mapping func(r rune) rune, s []byte) []byte {
-	// In the worst case, the array can grow when mapped, making
+	// In the worst case, the slice can grow when mapped, making
 	// things unpleasant.  But it's so rare we barge in assuming it's
 	// fine.  It could also shrink but that falls out naturally.
 	maxbytes := len(s) // length of b
@@ -412,28 +409,28 @@ func Repeat(b []byte, count int) []byte {
 	return nb
 }
 
-// ToUpper returns a copy of the byte array s with all Unicode letters mapped to their upper case.
+// ToUpper returns a copy of the byte slice s with all Unicode letters mapped to their upper case.
 func ToUpper(s []byte) []byte { return Map(unicode.ToUpper, s) }
 
-// ToUpper returns a copy of the byte array s with all Unicode letters mapped to their lower case.
+// ToLower returns a copy of the byte slice s with all Unicode letters mapped to their lower case.
 func ToLower(s []byte) []byte { return Map(unicode.ToLower, s) }
 
-// ToTitle returns a copy of the byte array s with all Unicode letters mapped to their title case.
+// ToTitle returns a copy of the byte slice s with all Unicode letters mapped to their title case.
 func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
 
-// ToUpperSpecial returns a copy of the byte array s with all Unicode letters mapped to their
+// ToUpperSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
 // upper case, giving priority to the special casing rules.
 func ToUpperSpecial(_case unicode.SpecialCase, s []byte) []byte {
 	return Map(func(r rune) rune { return _case.ToUpper(r) }, s)
 }
 
-// ToLowerSpecial returns a copy of the byte array s with all Unicode letters mapped to their
+// ToLowerSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
 // lower case, giving priority to the special casing rules.
 func ToLowerSpecial(_case unicode.SpecialCase, s []byte) []byte {
 	return Map(func(r rune) rune { return _case.ToLower(r) }, s)
 }
 
-// ToTitleSpecial returns a copy of the byte array s with all Unicode letters mapped to their
+// ToTitleSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
 // title case, giving priority to the special casing rules.
 func ToTitleSpecial(_case unicode.SpecialCase, s []byte) []byte {
 	return Map(func(r rune) rune { return _case.ToTitle(r) }, s)
@@ -514,6 +511,24 @@ func TrimFunc(s []byte, f func(r rune) bool) []byte {
 	return TrimRightFunc(TrimLeftFunc(s, f), f)
 }
 
+// TrimPrefix returns s without the provided leading prefix string.
+// If s doesn't start with prefix, s is returned unchanged.
+func TrimPrefix(s, prefix []byte) []byte {
+	if HasPrefix(s, prefix) {
+		return s[len(prefix):]
+	}
+	return s
+}
+
+// TrimSuffix returns s without the provided trailing suffix string.
+// If s doesn't end with suffix, s is returned unchanged.
+func TrimSuffix(s, suffix []byte) []byte {
+	if HasSuffix(s, suffix) {
+		return s[:len(s)-len(suffix)]
+	}
+	return s
+}
+
 // IndexFunc interprets s as a sequence of UTF-8-encoded Unicode code points.
 // It returns the byte index in s of the first Unicode
 // code point satisfying f(c), or -1 if none do.
@@ -552,7 +567,10 @@ func indexFunc(s []byte, f func(r rune) bool, truth bool) int {
 // inverted.
 func lastIndexFunc(s []byte, f func(r rune) bool, truth bool) int {
 	for i := len(s); i > 0; {
-		r, size := utf8.DecodeLastRune(s[0:i])
+		r, size := rune(s[i-1]), 1
+		if r >= utf8.RuneSelf {
+			r, size = utf8.DecodeLastRune(s[0:i])
+		}
 		i -= size
 		if f(r) == truth {
 			return i
@@ -619,10 +637,8 @@ func Replace(s, old, new []byte, n int) []byte {
 		m = Count(s, old)
 	}
 	if m == 0 {
-		// Nothing to do. Just copy.
-		t := make([]byte, len(s))
-		copy(t, s)
-		return t
+		// Just return a copy.
+		return append([]byte(nil), s...)
 	}
 	if n < 0 || m < n {
 		n = m
diff --git a/src/pkg/bytes/bytes_decl.go b/src/pkg/bytes/bytes_decl.go
index 5d2b9e6..ce78be4 100644
--- a/src/pkg/bytes/bytes_decl.go
+++ b/src/pkg/bytes/bytes_decl.go
@@ -4,5 +4,13 @@
 
 package bytes
 
+//go:noescape
+
 // IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s.
 func IndexByte(s []byte, c byte) int // asm_$GOARCH.s
+
+//go:noescape
+
+// Equal returns a boolean reporting whether a == b.
+// A nil argument is equivalent to an empty slice.
+func Equal(a, b []byte) bool // asm_$GOARCH.s
diff --git a/src/pkg/bytes/bytes_test.go b/src/pkg/bytes/bytes_test.go
index 000f235..1d6274c 100644
--- a/src/pkg/bytes/bytes_test.go
+++ b/src/pkg/bytes/bytes_test.go
@@ -6,6 +6,7 @@ package bytes_test
 
 import (
 	. "bytes"
+	"math/rand"
 	"reflect"
 	"testing"
 	"unicode"
@@ -24,16 +25,16 @@ func eq(a, b []string) bool {
 	return true
 }
 
-func arrayOfString(a [][]byte) []string {
-	result := make([]string, len(a))
-	for j := 0; j < len(a); j++ {
-		result[j] = string(a[j])
+func sliceOfString(s [][]byte) []string {
+	result := make([]string, len(s))
+	for i, v := range s {
+		result[i] = string(v)
 	}
 	return result
 }
 
 // For ease of reading, the test cases use strings that are converted to byte
-// arrays before invoking the functions.
+// slices before invoking the functions.
 
 var abcd = "abcd"
 var faces = "☺☻☹"
@@ -434,7 +435,7 @@ var explodetests = []ExplodeTest{
 func TestExplode(t *testing.T) {
 	for _, tt := range explodetests {
 		a := SplitN([]byte(tt.s), nil, tt.n)
-		result := arrayOfString(a)
+		result := sliceOfString(a)
 		if !eq(result, tt.a) {
 			t.Errorf(`Explode("%s", %d) = %v; want %v`, tt.s, tt.n, result, tt.a)
 			continue
@@ -472,7 +473,7 @@ var splittests = []SplitTest{
 func TestSplit(t *testing.T) {
 	for _, tt := range splittests {
 		a := SplitN([]byte(tt.s), []byte(tt.sep), tt.n)
-		result := arrayOfString(a)
+		result := sliceOfString(a)
 		if !eq(result, tt.a) {
 			t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
 			continue
@@ -490,6 +491,12 @@ func TestSplit(t *testing.T) {
 				t.Errorf("Split disagrees withSplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
 			}
 		}
+		if len(a) > 0 {
+			in, out := a[0], s
+			if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] {
+				t.Errorf("Join(%#v, %q) didn't copy", a, tt.sep)
+			}
+		}
 	}
 }
 
@@ -512,7 +519,7 @@ var splitaftertests = []SplitTest{
 func TestSplitAfter(t *testing.T) {
 	for _, tt := range splitaftertests {
 		a := SplitAfterN([]byte(tt.s), []byte(tt.sep), tt.n)
-		result := arrayOfString(a)
+		result := sliceOfString(a)
 		if !eq(result, tt.a) {
 			t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
 			continue
@@ -552,7 +559,7 @@ var fieldstests = []FieldsTest{
 func TestFields(t *testing.T) {
 	for _, tt := range fieldstests {
 		a := Fields([]byte(tt.s))
-		result := arrayOfString(a)
+		result := sliceOfString(a)
 		if !eq(result, tt.a) {
 			t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a)
 			continue
@@ -561,6 +568,14 @@ func TestFields(t *testing.T) {
 }
 
 func TestFieldsFunc(t *testing.T) {
+	for _, tt := range fieldstests {
+		a := FieldsFunc([]byte(tt.s), unicode.IsSpace)
+		result := sliceOfString(a)
+		if !eq(result, tt.a) {
+			t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a)
+			continue
+		}
+	}
 	pred := func(c rune) bool { return c == 'X' }
 	var fieldsFuncTests = []FieldsTest{
 		{"", []string{}},
@@ -570,15 +585,15 @@ func TestFieldsFunc(t *testing.T) {
 	}
 	for _, tt := range fieldsFuncTests {
 		a := FieldsFunc([]byte(tt.s), pred)
-		result := arrayOfString(a)
+		result := sliceOfString(a)
 		if !eq(result, tt.a) {
 			t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a)
 		}
 	}
 }
 
-// Test case for any function which accepts and returns a byte array.
-// For ease of creation, we write the byte arrays as strings.
+// Test case for any function which accepts and returns a byte slice.
+// For ease of creation, we write the byte slices as strings.
 type StringTest struct {
 	in, out string
 }
@@ -779,8 +794,8 @@ func TestRunes(t *testing.T) {
 }
 
 type TrimTest struct {
-	f               string
-	in, cutset, out string
+	f            string
+	in, arg, out string
 }
 
 var trimTests = []TrimTest{
@@ -805,12 +820,17 @@ var trimTests = []TrimTest{
 	{"TrimRight", "", "123", ""},
 	{"TrimRight", "", "", ""},
 	{"TrimRight", "☺\xc0", "☺", "☺\xc0"},
+	{"TrimPrefix", "aabb", "a", "abb"},
+	{"TrimPrefix", "aabb", "b", "aabb"},
+	{"TrimSuffix", "aabb", "a", "aabb"},
+	{"TrimSuffix", "aabb", "b", "aab"},
 }
 
 func TestTrim(t *testing.T) {
 	for _, tc := range trimTests {
 		name := tc.f
 		var f func([]byte, string) []byte
+		var fb func([]byte, []byte) []byte
 		switch name {
 		case "Trim":
 			f = Trim
@@ -818,12 +838,21 @@ func TestTrim(t *testing.T) {
 			f = TrimLeft
 		case "TrimRight":
 			f = TrimRight
+		case "TrimPrefix":
+			fb = TrimPrefix
+		case "TrimSuffix":
+			fb = TrimSuffix
 		default:
 			t.Errorf("Undefined trim function %s", name)
 		}
-		actual := string(f([]byte(tc.in), tc.cutset))
+		var actual string
+		if f != nil {
+			actual = string(f([]byte(tc.in), tc.arg))
+		} else {
+			actual = string(fb([]byte(tc.in), []byte(tc.arg)))
+		}
 		if actual != tc.out {
-			t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
+			t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
 		}
 	}
 }
@@ -1008,3 +1037,46 @@ func TestEqualFold(t *testing.T) {
 		}
 	}
 }
+
+var makeFieldsInput = func() []byte {
+	x := make([]byte, 1<<20)
+	// Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
+	for i := range x {
+		switch rand.Intn(10) {
+		case 0:
+			x[i] = ' '
+		case 1:
+			if i > 0 && x[i-1] == 'x' {
+				copy(x[i-1:], "χ")
+				break
+			}
+			fallthrough
+		default:
+			x[i] = 'x'
+		}
+	}
+	return x
+}
+
+var fieldsInput = makeFieldsInput()
+
+func BenchmarkFields(b *testing.B) {
+	b.SetBytes(int64(len(fieldsInput)))
+	for i := 0; i < b.N; i++ {
+		Fields(fieldsInput)
+	}
+}
+
+func BenchmarkFieldsFunc(b *testing.B) {
+	b.SetBytes(int64(len(fieldsInput)))
+	for i := 0; i < b.N; i++ {
+		FieldsFunc(fieldsInput, unicode.IsSpace)
+	}
+}
+
+func BenchmarkTrimSpace(b *testing.B) {
+	s := []byte("  Some text.  \n")
+	for i := 0; i < b.N; i++ {
+		TrimSpace(s)
+	}
+}
diff --git a/src/pkg/bytes/example_test.go b/src/pkg/bytes/example_test.go
index 6fe8cd5..ad2dbc6 100644
--- a/src/pkg/bytes/example_test.go
+++ b/src/pkg/bytes/example_test.go
@@ -5,24 +5,81 @@
 package bytes_test
 
 import (
-	. "bytes"
+	"bytes"
 	"encoding/base64"
+	"fmt"
 	"io"
 	"os"
+	"sort"
 )
 
 func ExampleBuffer() {
-	var b Buffer // A Buffer needs no initialization.
+	var b bytes.Buffer // A Buffer needs no initialization.
 	b.Write([]byte("Hello "))
-	b.Write([]byte("world!"))
+	fmt.Fprintf(&b, "world!")
 	b.WriteTo(os.Stdout)
 	// Output: Hello world!
 }
 
 func ExampleBuffer_reader() {
 	// A Buffer can turn a string or a []byte into an io.Reader.
-	buf := NewBufferString("R29waGVycyBydWxlIQ==")
+	buf := bytes.NewBufferString("R29waGVycyBydWxlIQ==")
 	dec := base64.NewDecoder(base64.StdEncoding, buf)
 	io.Copy(os.Stdout, dec)
 	// Output: Gophers rule!
 }
+
+func ExampleCompare() {
+	// Interpret Compare's result by comparing it to zero.
+	var a, b []byte
+	if bytes.Compare(a, b) < 0 {
+		// a less b
+	}
+	if bytes.Compare(a, b) <= 0 {
+		// a less or equal b
+	}
+	if bytes.Compare(a, b) > 0 {
+		// a greater b
+	}
+	if bytes.Compare(a, b) >= 0 {
+		// a greater or equal b
+	}
+
+	// Prefer Equal to Compare for equality comparisons.
+	if bytes.Equal(a, b) {
+		// a equal b
+	}
+	if !bytes.Equal(a, b) {
+		// a not equal b
+	}
+}
+
+func ExampleCompare_search() {
+	// Binary search to find a matching byte slice.
+	var needle []byte
+	var haystack [][]byte // Assume sorted
+	i := sort.Search(len(haystack), func(i int) bool {
+		// Return haystack[i] >= needle.
+		return bytes.Compare(haystack[i], needle) >= 0
+	})
+	if i < len(haystack) && bytes.Equal(haystack[i], needle) {
+		// Found it!
+	}
+}
+
+func ExampleTrimSuffix() {
+	var b = []byte("Hello, goodbye, etc!")
+	b = bytes.TrimSuffix(b, []byte("goodbye, etc!"))
+	b = bytes.TrimSuffix(b, []byte("gopher"))
+	b = append(b, bytes.TrimSuffix([]byte("world!"), []byte("x!"))...)
+	os.Stdout.Write(b)
+	// Output: Hello, world!
+}
+
+func ExampleTrimPrefix() {
+	var b = []byte("Goodbye,, world!")
+	b = bytes.TrimPrefix(b, []byte("Goodbye,"))
+	b = bytes.TrimPrefix(b, []byte("See ya,"))
+	fmt.Printf("Hello%s", b)
+	// Output: Hello, world!
+}
diff --git a/src/pkg/bytes/reader.go b/src/pkg/bytes/reader.go
index a062e54..77511b9 100644
--- a/src/pkg/bytes/reader.go
+++ b/src/pkg/bytes/reader.go
@@ -10,7 +10,7 @@ import (
 	"unicode/utf8"
 )
 
-// A Reader implements the io.Reader, io.ReaderAt, io.Seeker,
+// A Reader implements the io.Reader, io.ReaderAt, io.WriterTo, io.Seeker,
 // io.ByteScanner, and io.RuneScanner interfaces by reading from
 // a byte slice.
 // Unlike a Buffer, a Reader is read-only and supports seeking.
@@ -121,5 +121,24 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) {
 	return abs, nil
 }
 
+// WriteTo implements the io.WriterTo interface.
+func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
+	r.prevRune = -1
+	if r.i >= len(r.s) {
+		return 0, nil
+	}
+	b := r.s[r.i:]
+	m, err := w.Write(b)
+	if m > len(b) {
+		panic("bytes.Reader.WriteTo: invalid Write count")
+	}
+	r.i += m
+	n = int64(m)
+	if m != len(b) && err == nil {
+		err = io.ErrShortWrite
+	}
+	return
+}
+
 // NewReader returns a new Reader reading from b.
 func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }
diff --git a/src/pkg/bytes/reader_test.go b/src/pkg/bytes/reader_test.go
index 2e4b1f2..f0a3e26 100644
--- a/src/pkg/bytes/reader_test.go
+++ b/src/pkg/bytes/reader_test.go
@@ -8,6 +8,7 @@ import (
 	. "bytes"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"os"
 	"testing"
 )
@@ -86,3 +87,51 @@ func TestReaderAt(t *testing.T) {
 		}
 	}
 }
+
+func TestReaderWriteTo(t *testing.T) {
+	for i := 0; i < 30; i += 3 {
+		var l int
+		if i > 0 {
+			l = len(data) / i
+		}
+		s := data[:l]
+		r := NewReader(testBytes[:l])
+		var b Buffer
+		n, err := r.WriteTo(&b)
+		if expect := int64(len(s)); n != expect {
+			t.Errorf("got %v; want %v", n, expect)
+		}
+		if err != nil {
+			t.Errorf("for length %d: got error = %v; want nil", l, err)
+		}
+		if b.String() != s {
+			t.Errorf("got string %q; want %q", b.String(), s)
+		}
+		if r.Len() != 0 {
+			t.Errorf("reader contains %v bytes; want 0", r.Len())
+		}
+	}
+}
+
+// verify that copying from an empty reader always has the same results,
+// regardless of the presence of a WriteTo method.
+func TestReaderCopyNothing(t *testing.T) {
+	type nErr struct {
+		n   int64
+		err error
+	}
+	type justReader struct {
+		io.Reader
+	}
+	type justWriter struct {
+		io.Writer
+	}
+	discard := justWriter{ioutil.Discard} // hide ReadFrom
+
+	var with, withOut nErr
+	with.n, with.err = io.Copy(discard, NewReader(nil))
+	withOut.n, withOut.err = io.Copy(discard, justReader{NewReader(nil)})
+	if with != withOut {
+		t.Errorf("behavior differs: with = %#v; without: %#v", with, withOut)
+	}
+}
diff --git a/src/pkg/compress/bzip2/bit_reader.go b/src/pkg/compress/bzip2/bit_reader.go
index b35c69a..ab1d606 100644
--- a/src/pkg/compress/bzip2/bit_reader.go
+++ b/src/pkg/compress/bzip2/bit_reader.go
@@ -14,21 +14,16 @@ import (
 // because the error handling was verbose. Instead, any error is kept and can
 // be checked afterwards.
 type bitReader struct {
-	r    byteReader
+	r    io.ByteReader
 	n    uint64
 	bits uint
 	err  error
 }
 
-// bitReader needs to read bytes from an io.Reader. We attempt to convert the
-// given io.Reader to this interface and, if it doesn't already fit, we wrap in
-// a bufio.Reader.
-type byteReader interface {
-	ReadByte() (byte, error)
-}
-
+// newBitReader returns a new bitReader reading from r. If r is not
+// already an io.ByteReader, it will be converted via a bufio.Reader.
 func newBitReader(r io.Reader) bitReader {
-	byter, ok := r.(byteReader)
+	byter, ok := r.(io.ByteReader)
 	if !ok {
 		byter = bufio.NewReader(r)
 	}
diff --git a/src/pkg/compress/flate/copy.go b/src/pkg/compress/flate/copy.go
new file mode 100644
index 0000000..06e5d2e
--- /dev/null
+++ b/src/pkg/compress/flate/copy.go
@@ -0,0 +1,17 @@
+// 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 flate
+
+// forwardCopy is like the built-in copy function except that it always goes
+// forward from the start, even if the dst and src overlap.
+func forwardCopy(dst, src []byte) int {
+	if len(src) > len(dst) {
+		src = src[:len(dst)]
+	}
+	for i, x := range src {
+		dst[i] = x
+	}
+	return len(src)
+}
diff --git a/src/pkg/compress/flate/copy_test.go b/src/pkg/compress/flate/copy_test.go
new file mode 100644
index 0000000..a9281d4
--- /dev/null
+++ b/src/pkg/compress/flate/copy_test.go
@@ -0,0 +1,52 @@
+// 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 flate
+
+import (
+	"testing"
+)
+
+func TestForwardCopy(t *testing.T) {
+	testCases := []struct {
+		dst0, dst1 int
+		src0, src1 int
+		want       string
+	}{
+		{0, 9, 0, 9, "012345678"},
+		{0, 5, 4, 9, "45678"},
+		{4, 9, 0, 5, "01230"},
+		{1, 6, 3, 8, "34567"},
+		{3, 8, 1, 6, "12121"},
+		{0, 9, 3, 6, "345"},
+		{3, 6, 0, 9, "012"},
+		{1, 6, 0, 9, "00000"},
+		{0, 4, 7, 8, "7"},
+		{0, 1, 6, 8, "6"},
+		{4, 4, 6, 9, ""},
+		{2, 8, 6, 6, ""},
+		{0, 0, 0, 0, ""},
+	}
+	for _, tc := range testCases {
+		b := []byte("0123456789")
+		dst := b[tc.dst0:tc.dst1]
+		src := b[tc.src0:tc.src1]
+		n := forwardCopy(dst, src)
+		got := string(dst[:n])
+		if got != tc.want {
+			t.Errorf("dst=b[%d:%d], src=b[%d:%d]: got %q, want %q",
+				tc.dst0, tc.dst1, tc.src0, tc.src1, got, tc.want)
+		}
+		// Check that the bytes outside of dst[:n] were not modified.
+		for i, x := range b {
+			if i >= tc.dst0 && i < tc.dst0+n {
+				continue
+			}
+			if int(x) != '0'+i {
+				t.Errorf("dst=b[%d:%d], src=b[%d:%d]: copy overrun at b[%d]: got '%c', want '%c'",
+					tc.dst0, tc.dst1, tc.src0, tc.src1, i, x, '0'+i)
+			}
+		}
+	}
+}
diff --git a/src/pkg/compress/flate/deflate.go b/src/pkg/compress/flate/deflate.go
index e511b50..d357fe3 100644
--- a/src/pkg/compress/flate/deflate.go
+++ b/src/pkg/compress/flate/deflate.go
@@ -22,7 +22,7 @@ const (
 	logMaxOffsetSize   = 15  // Standard DEFLATE
 	minMatchLength     = 3   // The smallest match that the compressor looks for
 	maxMatchLength     = 258 // The longest match for the compressor
-	minOffsetSize      = 1   // The shortest offset that makes any sence
+	minOffsetSize      = 1   // The shortest offset that makes any sense
 
 	// The maximum number of tokens we put into a single flat block, just too
 	// stop things from getting too large.
diff --git a/src/pkg/compress/flate/deflate_test.go b/src/pkg/compress/flate/deflate_test.go
index f1e6db2..8f4e196 100644
--- a/src/pkg/compress/flate/deflate_test.go
+++ b/src/pkg/compress/flate/deflate_test.go
@@ -124,8 +124,7 @@ func (r *sparseReader) Read(b []byte) (n int, err error) {
 
 func TestVeryLongSparseChunk(t *testing.T) {
 	if testing.Short() {
-		t.Logf("skipping sparse chunk during short test")
-		return
+		t.Skip("skipping sparse chunk during short test")
 	}
 	w, err := NewWriter(ioutil.Discard, 1)
 	if err != nil {
@@ -334,7 +333,7 @@ var deflateInflateStringTests = []deflateInflateStringTest{
 	{
 		"../testdata/e.txt",
 		"2.718281828...",
-		[...]int{10013, 5065, 5096, 5115, 5093, 5079, 5079, 5079, 5079, 5079},
+		[...]int{100018, 50650, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790},
 	},
 	{
 		"../testdata/Mark.Twain-Tom.Sawyer.txt",
diff --git a/src/pkg/compress/flate/fixedhuff.go b/src/pkg/compress/flate/fixedhuff.go
new file mode 100644
index 0000000..41a6b25
--- /dev/null
+++ b/src/pkg/compress/flate/fixedhuff.go
@@ -0,0 +1,74 @@
+package flate
+
+// autogenerated by gen.go, DO NOT EDIT
+
+var fixedHuffmanDecoder = huffmanDecoder{
+	7,
+	[huffmanNumChunks]uint32{
+		0x1007, 0x0508, 0x0108, 0x1188, 0x1107, 0x0708, 0x0308, 0x0c09,
+		0x1087, 0x0608, 0x0208, 0x0a09, 0x0008, 0x0808, 0x0408, 0x0e09,
+		0x1047, 0x0588, 0x0188, 0x0909, 0x1147, 0x0788, 0x0388, 0x0d09,
+		0x10c7, 0x0688, 0x0288, 0x0b09, 0x0088, 0x0888, 0x0488, 0x0f09,
+		0x1027, 0x0548, 0x0148, 0x11c8, 0x1127, 0x0748, 0x0348, 0x0c89,
+		0x10a7, 0x0648, 0x0248, 0x0a89, 0x0048, 0x0848, 0x0448, 0x0e89,
+		0x1067, 0x05c8, 0x01c8, 0x0989, 0x1167, 0x07c8, 0x03c8, 0x0d89,
+		0x10e7, 0x06c8, 0x02c8, 0x0b89, 0x00c8, 0x08c8, 0x04c8, 0x0f89,
+		0x1017, 0x0528, 0x0128, 0x11a8, 0x1117, 0x0728, 0x0328, 0x0c49,
+		0x1097, 0x0628, 0x0228, 0x0a49, 0x0028, 0x0828, 0x0428, 0x0e49,
+		0x1057, 0x05a8, 0x01a8, 0x0949, 0x1157, 0x07a8, 0x03a8, 0x0d49,
+		0x10d7, 0x06a8, 0x02a8, 0x0b49, 0x00a8, 0x08a8, 0x04a8, 0x0f49,
+		0x1037, 0x0568, 0x0168, 0x11e8, 0x1137, 0x0768, 0x0368, 0x0cc9,
+		0x10b7, 0x0668, 0x0268, 0x0ac9, 0x0068, 0x0868, 0x0468, 0x0ec9,
+		0x1077, 0x05e8, 0x01e8, 0x09c9, 0x1177, 0x07e8, 0x03e8, 0x0dc9,
+		0x10f7, 0x06e8, 0x02e8, 0x0bc9, 0x00e8, 0x08e8, 0x04e8, 0x0fc9,
+		0x1007, 0x0518, 0x0118, 0x1198, 0x1107, 0x0718, 0x0318, 0x0c29,
+		0x1087, 0x0618, 0x0218, 0x0a29, 0x0018, 0x0818, 0x0418, 0x0e29,
+		0x1047, 0x0598, 0x0198, 0x0929, 0x1147, 0x0798, 0x0398, 0x0d29,
+		0x10c7, 0x0698, 0x0298, 0x0b29, 0x0098, 0x0898, 0x0498, 0x0f29,
+		0x1027, 0x0558, 0x0158, 0x11d8, 0x1127, 0x0758, 0x0358, 0x0ca9,
+		0x10a7, 0x0658, 0x0258, 0x0aa9, 0x0058, 0x0858, 0x0458, 0x0ea9,
+		0x1067, 0x05d8, 0x01d8, 0x09a9, 0x1167, 0x07d8, 0x03d8, 0x0da9,
+		0x10e7, 0x06d8, 0x02d8, 0x0ba9, 0x00d8, 0x08d8, 0x04d8, 0x0fa9,
+		0x1017, 0x0538, 0x0138, 0x11b8, 0x1117, 0x0738, 0x0338, 0x0c69,
+		0x1097, 0x0638, 0x0238, 0x0a69, 0x0038, 0x0838, 0x0438, 0x0e69,
+		0x1057, 0x05b8, 0x01b8, 0x0969, 0x1157, 0x07b8, 0x03b8, 0x0d69,
+		0x10d7, 0x06b8, 0x02b8, 0x0b69, 0x00b8, 0x08b8, 0x04b8, 0x0f69,
+		0x1037, 0x0578, 0x0178, 0x11f8, 0x1137, 0x0778, 0x0378, 0x0ce9,
+		0x10b7, 0x0678, 0x0278, 0x0ae9, 0x0078, 0x0878, 0x0478, 0x0ee9,
+		0x1077, 0x05f8, 0x01f8, 0x09e9, 0x1177, 0x07f8, 0x03f8, 0x0de9,
+		0x10f7, 0x06f8, 0x02f8, 0x0be9, 0x00f8, 0x08f8, 0x04f8, 0x0fe9,
+		0x1007, 0x0508, 0x0108, 0x1188, 0x1107, 0x0708, 0x0308, 0x0c19,
+		0x1087, 0x0608, 0x0208, 0x0a19, 0x0008, 0x0808, 0x0408, 0x0e19,
+		0x1047, 0x0588, 0x0188, 0x0919, 0x1147, 0x0788, 0x0388, 0x0d19,
+		0x10c7, 0x0688, 0x0288, 0x0b19, 0x0088, 0x0888, 0x0488, 0x0f19,
+		0x1027, 0x0548, 0x0148, 0x11c8, 0x1127, 0x0748, 0x0348, 0x0c99,
+		0x10a7, 0x0648, 0x0248, 0x0a99, 0x0048, 0x0848, 0x0448, 0x0e99,
+		0x1067, 0x05c8, 0x01c8, 0x0999, 0x1167, 0x07c8, 0x03c8, 0x0d99,
+		0x10e7, 0x06c8, 0x02c8, 0x0b99, 0x00c8, 0x08c8, 0x04c8, 0x0f99,
+		0x1017, 0x0528, 0x0128, 0x11a8, 0x1117, 0x0728, 0x0328, 0x0c59,
+		0x1097, 0x0628, 0x0228, 0x0a59, 0x0028, 0x0828, 0x0428, 0x0e59,
+		0x1057, 0x05a8, 0x01a8, 0x0959, 0x1157, 0x07a8, 0x03a8, 0x0d59,
+		0x10d7, 0x06a8, 0x02a8, 0x0b59, 0x00a8, 0x08a8, 0x04a8, 0x0f59,
+		0x1037, 0x0568, 0x0168, 0x11e8, 0x1137, 0x0768, 0x0368, 0x0cd9,
+		0x10b7, 0x0668, 0x0268, 0x0ad9, 0x0068, 0x0868, 0x0468, 0x0ed9,
+		0x1077, 0x05e8, 0x01e8, 0x09d9, 0x1177, 0x07e8, 0x03e8, 0x0dd9,
+		0x10f7, 0x06e8, 0x02e8, 0x0bd9, 0x00e8, 0x08e8, 0x04e8, 0x0fd9,
+		0x1007, 0x0518, 0x0118, 0x1198, 0x1107, 0x0718, 0x0318, 0x0c39,
+		0x1087, 0x0618, 0x0218, 0x0a39, 0x0018, 0x0818, 0x0418, 0x0e39,
+		0x1047, 0x0598, 0x0198, 0x0939, 0x1147, 0x0798, 0x0398, 0x0d39,
+		0x10c7, 0x0698, 0x0298, 0x0b39, 0x0098, 0x0898, 0x0498, 0x0f39,
+		0x1027, 0x0558, 0x0158, 0x11d8, 0x1127, 0x0758, 0x0358, 0x0cb9,
+		0x10a7, 0x0658, 0x0258, 0x0ab9, 0x0058, 0x0858, 0x0458, 0x0eb9,
+		0x1067, 0x05d8, 0x01d8, 0x09b9, 0x1167, 0x07d8, 0x03d8, 0x0db9,
+		0x10e7, 0x06d8, 0x02d8, 0x0bb9, 0x00d8, 0x08d8, 0x04d8, 0x0fb9,
+		0x1017, 0x0538, 0x0138, 0x11b8, 0x1117, 0x0738, 0x0338, 0x0c79,
+		0x1097, 0x0638, 0x0238, 0x0a79, 0x0038, 0x0838, 0x0438, 0x0e79,
+		0x1057, 0x05b8, 0x01b8, 0x0979, 0x1157, 0x07b8, 0x03b8, 0x0d79,
+		0x10d7, 0x06b8, 0x02b8, 0x0b79, 0x00b8, 0x08b8, 0x04b8, 0x0f79,
+		0x1037, 0x0578, 0x0178, 0x11f8, 0x1137, 0x0778, 0x0378, 0x0cf9,
+		0x10b7, 0x0678, 0x0278, 0x0af9, 0x0078, 0x0878, 0x0478, 0x0ef9,
+		0x1077, 0x05f8, 0x01f8, 0x09f9, 0x1177, 0x07f8, 0x03f8, 0x0df9,
+		0x10f7, 0x06f8, 0x02f8, 0x0bf9, 0x00f8, 0x08f8, 0x04f8, 0x0ff9,
+	},
+	nil, 0,
+}
diff --git a/src/pkg/compress/flate/flate_test.go b/src/pkg/compress/flate/flate_test.go
index 94efc90..aba820a 100644
--- a/src/pkg/compress/flate/flate_test.go
+++ b/src/pkg/compress/flate/flate_test.go
@@ -10,122 +10,9 @@ package flate
 
 import (
 	"bytes"
-	"reflect"
 	"testing"
 )
 
-// The Huffman code lengths used by the fixed-format Huffman blocks.
-var fixedHuffmanBits = [...]int{
-	// 0-143 length 8
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-
-	// 144-255 length 9
-	9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-	9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-	9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-	9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-	9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-	9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-	9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-
-	// 256-279 length 7
-	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-	7, 7, 7, 7, 7, 7, 7, 7,
-
-	// 280-287 length 8
-	8, 8, 8, 8, 8, 8, 8, 8,
-}
-
-type InitDecoderTest struct {
-	in  []int
-	out huffmanDecoder
-	ok  bool
-}
-
-var initDecoderTests = []*InitDecoderTest{
-	// Example from Connell 1973,
-	{
-		[]int{3, 5, 2, 4, 3, 5, 5, 4, 4, 3, 4, 5},
-		huffmanDecoder{
-			2, 5,
-			[maxCodeLen + 1]int{2: 0, 4, 13, 31},
-			[maxCodeLen + 1]int{2: 0, 1, 6, 20},
-			// Paper used different code assignment:
-			// 2, 9, 4, 0, 10, 8, 3, 7, 1, 5, 11, 6
-			// Reordered here so that codes of same length
-			// are assigned to increasing numbers.
-			[]int{2, 0, 4, 9, 3, 7, 8, 10, 1, 5, 6, 11},
-		},
-		true,
-	},
-
-	// Example from RFC 1951 section 3.2.2
-	{
-		[]int{2, 1, 3, 3},
-		huffmanDecoder{
-			1, 3,
-			[maxCodeLen + 1]int{1: 0, 2, 7},
-			[maxCodeLen + 1]int{1: 0, 1, 4},
-			[]int{1, 0, 2, 3},
-		},
-		true,
-	},
-
-	// Second example from RFC 1951 section 3.2.2
-	{
-		[]int{3, 3, 3, 3, 3, 2, 4, 4},
-		huffmanDecoder{
-			2, 4,
-			[maxCodeLen + 1]int{2: 0, 6, 15},
-			[maxCodeLen + 1]int{2: 0, 1, 8},
-			[]int{5, 0, 1, 2, 3, 4, 6, 7},
-		},
-		true,
-	},
-
-	// Static Huffman codes (RFC 1951 section 3.2.6)
-	{
-		fixedHuffmanBits[0:],
-		fixedHuffmanDecoder,
-		true,
-	},
-
-	// Illegal input.
-	{
-		[]int{},
-		huffmanDecoder{},
-		false,
-	},
-
-	// Illegal input.
-	{
-		[]int{0, 0, 0, 0, 0, 0, 0},
-		huffmanDecoder{},
-		false,
-	},
-}
-
-func TestInitDecoder(t *testing.T) {
-	for i, tt := range initDecoderTests {
-		var h huffmanDecoder
-		if h.init(tt.in) != tt.ok {
-			t.Errorf("test %d: init = %v", i, !tt.ok)
-			continue
-		}
-		if !reflect.DeepEqual(&h, &tt.out) {
-			t.Errorf("test %d:\nhave %v\nwant %v", i, h, tt.out)
-		}
-	}
-}
-
 func TestUncompressedSource(t *testing.T) {
 	decoder := NewReader(bytes.NewBuffer([]byte{0x01, 0x01, 0x00, 0xfe, 0xff, 0x11}))
 	output := make([]byte, 1)
diff --git a/src/pkg/compress/flate/gen.go b/src/pkg/compress/flate/gen.go
new file mode 100644
index 0000000..1427557
--- /dev/null
+++ b/src/pkg/compress/flate/gen.go
@@ -0,0 +1,165 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// This program generates fixedhuff.go
+// Invoke as
+//
+//      go run gen.go |gofmt >fixedhuff.go
+
+package main
+
+import (
+	"fmt"
+)
+
+const maxCodeLen = 16
+
+// Note: the definition of the huffmanDecoder struct is copied from
+// inflate.go, as it is private to the implementation.
+
+// chunk & 15 is number of bits
+// chunk >> 4 is value, including table link
+
+const (
+	huffmanChunkBits  = 9
+	huffmanNumChunks  = 1 << huffmanChunkBits
+	huffmanCountMask  = 15
+	huffmanValueShift = 4
+)
+
+type huffmanDecoder struct {
+	min      int                      // the minimum code length
+	chunks   [huffmanNumChunks]uint32 // chunks as described above
+	links    [][]uint32               // overflow links
+	linkMask uint32                   // mask the width of the link table
+}
+
+// Initialize Huffman decoding tables from array of code lengths.
+func (h *huffmanDecoder) init(bits []int) bool {
+	// Count number of codes of each length,
+	// compute min and max length.
+	var count [maxCodeLen]int
+	var min, max int
+	for _, n := range bits {
+		if n == 0 {
+			continue
+		}
+		if min == 0 || n < min {
+			min = n
+		}
+		if n > max {
+			max = n
+		}
+		count[n]++
+	}
+	if max == 0 {
+		return false
+	}
+
+	h.min = min
+	var linkBits uint
+	var numLinks int
+	if max > huffmanChunkBits {
+		linkBits = uint(max) - huffmanChunkBits
+		numLinks = 1 << linkBits
+		h.linkMask = uint32(numLinks - 1)
+	}
+	code := 0
+	var nextcode [maxCodeLen]int
+	for i := min; i <= max; i++ {
+		if i == huffmanChunkBits+1 {
+			// create link tables
+			link := code >> 1
+			h.links = make([][]uint32, huffmanNumChunks-link)
+			for j := uint(link); j < huffmanNumChunks; j++ {
+				reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8
+				reverse >>= uint(16 - huffmanChunkBits)
+				off := j - uint(link)
+				h.chunks[reverse] = uint32(off<<huffmanValueShift + uint(i))
+				h.links[off] = make([]uint32, 1<<linkBits)
+			}
+		}
+		n := count[i]
+		nextcode[i] = code
+		code += n
+		code <<= 1
+	}
+
+	for i, n := range bits {
+		if n == 0 {
+			continue
+		}
+		code := nextcode[n]
+		nextcode[n]++
+		chunk := uint32(i<<huffmanValueShift | n)
+		reverse := int(reverseByte[code>>8]) | int(reverseByte[code&0xff])<<8
+		reverse >>= uint(16 - n)
+		if n <= huffmanChunkBits {
+			for off := reverse; off < huffmanNumChunks; off += 1 << uint(n) {
+				h.chunks[off] = chunk
+			}
+		} else {
+			linktab := h.links[h.chunks[reverse&(huffmanNumChunks-1)]>>huffmanValueShift]
+			reverse >>= huffmanChunkBits
+			for off := reverse; off < numLinks; off += 1 << uint(n-huffmanChunkBits) {
+				linktab[off] = chunk
+			}
+		}
+	}
+	return true
+}
+
+func main() {
+	var h huffmanDecoder
+	var bits [288]int
+	initReverseByte()
+	for i := 0; i < 144; i++ {
+		bits[i] = 8
+	}
+	for i := 144; i < 256; i++ {
+		bits[i] = 9
+	}
+	for i := 256; i < 280; i++ {
+		bits[i] = 7
+	}
+	for i := 280; i < 288; i++ {
+		bits[i] = 8
+	}
+	h.init(bits[:])
+	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{")
+	for i := 0; i < huffmanNumChunks; i++ {
+		if i&7 == 0 {
+			fmt.Printf("\t\t")
+		} else {
+			fmt.Printf(" ")
+		}
+		fmt.Printf("0x%04x,", h.chunks[i])
+		if i&7 == 7 {
+			fmt.Println()
+		}
+	}
+	fmt.Println("\t},")
+	fmt.Println("\tnil, 0,")
+	fmt.Println("}")
+}
+
+var reverseByte [256]byte
+
+func initReverseByte() {
+	for x := 0; x < 256; x++ {
+		var result byte
+		for i := uint(0); i < 8; i++ {
+			result |= byte(((x >> i) & 1) << (7 - i))
+		}
+		reverseByte[x] = result
+	}
+}
diff --git a/src/pkg/compress/flate/inflate.go b/src/pkg/compress/flate/inflate.go
index 3f2042b..a8d6460 100644
--- a/src/pkg/compress/flate/inflate.go
+++ b/src/pkg/compress/flate/inflate.go
@@ -16,9 +16,10 @@ import (
 const (
 	maxCodeLen = 16    // max length of Huffman code
 	maxHist    = 32768 // max history required
-	maxLit     = 286
-	maxDist    = 32
-	numCodes   = 19 // number of codes in Huffman meta-code
+	// The next three numbers come from the RFC, section 3.2.7.
+	maxLit   = 286
+	maxDist  = 32
+	numCodes = 19 // number of codes in Huffman meta-code
 )
 
 // A CorruptInputError reports the presence of corrupt input at a given offset.
@@ -53,32 +54,46 @@ func (e *WriteError) Error() string {
 	return "flate: write error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
 }
 
-// Huffman decoder is based on
-// J. Brian Connell, ``A Huffman-Shannon-Fano Code,''
-// Proceedings of the IEEE, 61(7) (July 1973), pp 1046-1047.
-type huffmanDecoder struct {
-	// min, max code length
-	min, max int
+// Note that much of the implemenation of huffmanDecoder is also copied
+// into gen.go (in package main) for the purpose of precomputing the
+// fixed huffman tables so they can be included statically.
+
+// The data structure for decoding Huffman tables is based on that of
+// zlib. There is a lookup table of a fixed bit width (huffmanChunkBits),
+// For codes smaller than the table width, there are multiple entries
+// (each combination of trailing bits has the same value). For codes
+// larger than the table width, the table contains a link to an overflow
+// table. The width of each entry in the link table is the maximum code
+// size minus the chunk width.
+
+// Note that you can do a lookup in the table even without all bits
+// filled. Since the extra bits are zero, and the DEFLATE Huffman codes
+// have the property that shorter codes come before longer ones, the
+// bit length estimate in the result is a lower bound on the actual
+// number of bits.
 
-	// limit[i] = largest code word of length i
-	// Given code v of length n,
-	// need more bits if v > limit[n].
-	limit [maxCodeLen + 1]int
+// chunk & 15 is number of bits
+// chunk >> 4 is value, including table link
 
-	// base[i] = smallest code word of length i - seq number
-	base [maxCodeLen + 1]int
+const (
+	huffmanChunkBits  = 9
+	huffmanNumChunks  = 1 << huffmanChunkBits
+	huffmanCountMask  = 15
+	huffmanValueShift = 4
+)
 
-	// codes[seq number] = output code.
-	// Given code v of length n, value is
-	// codes[v - base[n]].
-	codes []int
+type huffmanDecoder struct {
+	min      int                      // the minimum code length
+	chunks   [huffmanNumChunks]uint32 // chunks as described above
+	links    [][]uint32               // overflow links
+	linkMask uint32                   // mask the width of the link table
 }
 
 // Initialize Huffman decoding tables from array of code lengths.
 func (h *huffmanDecoder) init(bits []int) bool {
 	// Count number of codes of each length,
 	// compute min and max length.
-	var count [maxCodeLen + 1]int
+	var count [maxCodeLen]int
 	var min, max int
 	for _, n := range bits {
 		if n == 0 {
@@ -97,93 +112,58 @@ func (h *huffmanDecoder) init(bits []int) bool {
 	}
 
 	h.min = min
-	h.max = max
-
-	// For each code range, compute
-	// nextcode (first code of that length),
-	// limit (last code of that length), and
-	// base (offset from first code to sequence number).
+	var linkBits uint
+	var numLinks int
+	if max > huffmanChunkBits {
+		linkBits = uint(max) - huffmanChunkBits
+		numLinks = 1 << linkBits
+		h.linkMask = uint32(numLinks - 1)
+	}
 	code := 0
-	seq := 0
 	var nextcode [maxCodeLen]int
 	for i := min; i <= max; i++ {
+		if i == huffmanChunkBits+1 {
+			// create link tables
+			link := code >> 1
+			h.links = make([][]uint32, huffmanNumChunks-link)
+			for j := uint(link); j < huffmanNumChunks; j++ {
+				reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8
+				reverse >>= uint(16 - huffmanChunkBits)
+				off := j - uint(link)
+				h.chunks[reverse] = uint32(off<<huffmanValueShift + uint(i))
+				h.links[off] = make([]uint32, 1<<linkBits)
+			}
+		}
 		n := count[i]
 		nextcode[i] = code
-		h.base[i] = code - seq
 		code += n
-		seq += n
-		h.limit[i] = code - 1
 		code <<= 1
 	}
 
-	// Make array mapping sequence numbers to codes.
-	if len(h.codes) < len(bits) {
-		h.codes = make([]int, len(bits))
-	}
 	for i, n := range bits {
 		if n == 0 {
 			continue
 		}
 		code := nextcode[n]
 		nextcode[n]++
-		seq := code - h.base[n]
-		h.codes[seq] = i
+		chunk := uint32(i<<huffmanValueShift | n)
+		reverse := int(reverseByte[code>>8]) | int(reverseByte[code&0xff])<<8
+		reverse >>= uint(16 - n)
+		if n <= huffmanChunkBits {
+			for off := reverse; off < huffmanNumChunks; off += 1 << uint(n) {
+				h.chunks[off] = chunk
+			}
+		} else {
+			linktab := h.links[h.chunks[reverse&(huffmanNumChunks-1)]>>huffmanValueShift]
+			reverse >>= huffmanChunkBits
+			for off := reverse; off < numLinks; off += 1 << uint(n-huffmanChunkBits) {
+				linktab[off] = chunk
+			}
+		}
 	}
 	return true
 }
 
-// Hard-coded Huffman tables for DEFLATE algorithm.
-// See RFC 1951, section 3.2.6.
-var fixedHuffmanDecoder = huffmanDecoder{
-	7, 9,
-	[maxCodeLen + 1]int{7: 23, 199, 511},
-	[maxCodeLen + 1]int{7: 0, 24, 224},
-	[]int{
-		// length 7: 256-279
-		256, 257, 258, 259, 260, 261, 262,
-		263, 264, 265, 266, 267, 268, 269,
-		270, 271, 272, 273, 274, 275, 276,
-		277, 278, 279,
-
-		// length 8: 0-143
-		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
-		12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
-		22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-		32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
-		42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-		52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-		62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-		72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
-		82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
-		92, 93, 94, 95, 96, 97, 98, 99, 100,
-		101, 102, 103, 104, 105, 106, 107, 108,
-		109, 110, 111, 112, 113, 114, 115, 116,
-		117, 118, 119, 120, 121, 122, 123, 124,
-		125, 126, 127, 128, 129, 130, 131, 132,
-		133, 134, 135, 136, 137, 138, 139, 140,
-		141, 142, 143,
-
-		// length 8: 280-287
-		280, 281, 282, 283, 284, 285, 286, 287,
-
-		// length 9: 144-255
-		144, 145, 146, 147, 148, 149, 150, 151,
-		152, 153, 154, 155, 156, 157, 158, 159,
-		160, 161, 162, 163, 164, 165, 166, 167,
-		168, 169, 170, 171, 172, 173, 174, 175,
-		176, 177, 178, 179, 180, 181, 182, 183,
-		184, 185, 186, 187, 188, 189, 190, 191,
-		192, 193, 194, 195, 196, 197, 198, 199,
-		200, 201, 202, 203, 204, 205, 206, 207,
-		208, 209, 210, 211, 212, 213, 214, 215,
-		216, 217, 218, 219, 220, 221, 222, 223,
-		224, 225, 226, 227, 228, 229, 230, 231,
-		232, 233, 234, 235, 236, 237, 238, 239,
-		240, 241, 242, 243, 244, 245, 246, 247,
-		248, 249, 250, 251, 252, 253, 254, 255,
-	},
-}
-
 // The actual read interface needed by NewReader.
 // If the passed in io.Reader does not also have ReadByte,
 // the NewReader will introduce its own buffering.
@@ -207,11 +187,11 @@ type decompressor struct {
 	h1, h2 huffmanDecoder
 
 	// Length arrays used to define Huffman codes.
-	bits     [maxLit + maxDist]int
-	codebits [numCodes]int
+	bits     *[maxLit + maxDist]int
+	codebits *[numCodes]int
 
 	// Output history, buffer.
-	hist  [maxHist]byte
+	hist  *[maxHist]byte
 	hp    int  // current output position in buffer
 	hw    int  // have written hist[0:hw] already
 	hfull bool // buffer has filled at least once
@@ -306,10 +286,15 @@ func (f *decompressor) readHuffman() error {
 		}
 	}
 	nlit := int(f.b&0x1F) + 257
+	if nlit > maxLit {
+		return CorruptInputError(f.roffset)
+	}
 	f.b >>= 5
 	ndist := int(f.b&0x1F) + 1
+	// maxDist is 32, so ndist is always valid.
 	f.b >>= 5
 	nclen := int(f.b&0xF) + 4
+	// numCodes is 19, so nclen is always valid.
 	f.b >>= 4
 	f.nb -= 5 + 5 + 4
 
@@ -505,51 +490,49 @@ func (f *decompressor) huffmanBlock() {
 			return
 		}
 
-		p := f.hp - dist
-		if p < 0 {
-			p += len(f.hist)
-		}
-		for i := 0; i < length; i++ {
-			f.hist[f.hp] = f.hist[p]
-			f.hp++
-			p++
-			if f.hp == len(f.hist) {
-				// After flush continue copying out of history.
-				f.copyLen = length - (i + 1)
-				f.copyDist = dist
-				f.flush((*decompressor).copyHuff)
-				return
-			}
-			if p == len(f.hist) {
-				p = 0
-			}
+		f.copyLen, f.copyDist = length, dist
+		if f.copyHist() {
+			return
 		}
 	}
 	panic("unreached")
 }
 
-func (f *decompressor) copyHuff() {
-	length := f.copyLen
-	dist := f.copyDist
-	p := f.hp - dist
+// copyHist copies f.copyLen bytes from f.hist (f.copyDist bytes ago) to itself.
+// It reports whether the f.hist buffer is full.
+func (f *decompressor) copyHist() bool {
+	p := f.hp - f.copyDist
 	if p < 0 {
 		p += len(f.hist)
 	}
-	for i := 0; i < length; i++ {
-		f.hist[f.hp] = f.hist[p]
-		f.hp++
-		p++
+	for f.copyLen > 0 {
+		n := f.copyLen
+		if x := len(f.hist) - f.hp; n > x {
+			n = x
+		}
+		if x := len(f.hist) - p; n > x {
+			n = x
+		}
+		forwardCopy(f.hist[f.hp:f.hp+n], f.hist[p:p+n])
+		p += n
+		f.hp += n
+		f.copyLen -= n
 		if f.hp == len(f.hist) {
-			f.copyLen = length - (i + 1)
+			// After flush continue copying out of history.
 			f.flush((*decompressor).copyHuff)
-			return
+			return true
 		}
 		if p == len(f.hist) {
 			p = 0
 		}
 	}
+	return false
+}
 
-	// Continue processing Huffman block.
+func (f *decompressor) copyHuff() {
+	if f.copyHist() {
+		return
+	}
 	f.huffmanBlock()
 }
 
@@ -584,9 +567,9 @@ func (f *decompressor) dataBlock() {
 	f.copyData()
 }
 
+// copyData copies f.copyLen bytes from the underlying reader into f.hist.
+// It pauses for reads when f.hist is full.
 func (f *decompressor) copyData() {
-	// Read f.dataLen bytes into history,
-	// pausing for reads as history fills.
 	n := f.copyLen
 	for n > 0 {
 		m := len(f.hist) - f.hp
@@ -640,23 +623,23 @@ func (f *decompressor) moreBits() error {
 
 // Read the next Huffman-encoded symbol from f according to h.
 func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) {
-	for n := uint(h.min); n <= uint(h.max); n++ {
-		lim := h.limit[n]
-		if lim == -1 {
-			continue
-		}
+	n := uint(h.min)
+	for {
 		for f.nb < n {
 			if err := f.moreBits(); err != nil {
 				return 0, err
 			}
 		}
-		v := int(f.b & uint32(1<<n-1))
-		v <<= 16 - n
-		v = int(reverseByte[v>>8]) | int(reverseByte[v&0xFF])<<8 // reverse bits
-		if v <= lim {
+		chunk := h.chunks[f.b&(huffmanNumChunks-1)]
+		n = uint(chunk & huffmanCountMask)
+		if n > huffmanChunkBits {
+			chunk = h.links[chunk>>huffmanValueShift][(f.b>>huffmanChunkBits)&h.linkMask]
+			n = uint(chunk & huffmanCountMask)
+		}
+		if n <= f.nb {
 			f.b >>= n
 			f.nb -= n
-			return h.codes[v-h.base[n]], nil
+			return int(chunk >> huffmanValueShift), nil
 		}
 	}
 	return 0, CorruptInputError(f.roffset)
@@ -688,7 +671,10 @@ func makeReader(r io.Reader) Reader {
 // finished reading.
 func NewReader(r io.Reader) io.ReadCloser {
 	var f decompressor
+	f.bits = new([maxLit + maxDist]int)
+	f.codebits = new([numCodes]int)
 	f.r = makeReader(r)
+	f.hist = new([maxHist]byte)
 	f.step = (*decompressor).nextBlock
 	return &f
 }
@@ -700,8 +686,11 @@ func NewReader(r io.Reader) io.ReadCloser {
 // to read data compressed by NewWriterDict.
 func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser {
 	var f decompressor
-	f.setDict(dict)
 	f.r = makeReader(r)
+	f.hist = new([maxHist]byte)
+	f.bits = new([maxLit + maxDist]int)
+	f.codebits = new([numCodes]int)
 	f.step = (*decompressor).nextBlock
+	f.setDict(dict)
 	return &f
 }
diff --git a/src/pkg/compress/flate/reader_test.go b/src/pkg/compress/flate/reader_test.go
new file mode 100644
index 0000000..54ed788
--- /dev/null
+++ b/src/pkg/compress/flate/reader_test.go
@@ -0,0 +1,95 @@
+// 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 flate
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+func TestNlitOutOfRange(t *testing.T) {
+	// Trying to decode this bogus flate data, which has a Huffman table
+	// with nlit=288, should not panic.
+	io.Copy(ioutil.Discard, NewReader(strings.NewReader(
+		"\xfc\xfe\x36\xe7\x5e\x1c\xef\xb3\x55\x58\x77\xb6\x56\xb5\x43\xf4"+
+			"\x6f\xf2\xd2\xe6\x3d\x99\xa0\x85\x8c\x48\xeb\xf8\xda\x83\x04\x2a"+
+			"\x75\xc4\xf8\x0f\x12\x11\xb9\xb4\x4b\x09\xa0\xbe\x8b\x91\x4c")))
+}
+
+const (
+	digits = iota
+	twain
+)
+
+var testfiles = []string{
+	// Digits is the digits of the irrational number e. Its decimal representation
+	// does not repeat, but there are only 10 posible digits, so it should be
+	// reasonably compressible.
+	digits: "../testdata/e.txt",
+	// Twain is Project Gutenberg's edition of Mark Twain's classic English novel.
+	twain: "../testdata/Mark.Twain-Tom.Sawyer.txt",
+}
+
+func benchmarkDecode(b *testing.B, testfile, level, n int) {
+	b.StopTimer()
+	b.SetBytes(int64(n))
+	buf0, err := ioutil.ReadFile(testfiles[testfile])
+	if err != nil {
+		b.Fatal(err)
+	}
+	if len(buf0) == 0 {
+		b.Fatalf("test file %q has no data", testfiles[testfile])
+	}
+	compressed := new(bytes.Buffer)
+	w, err := NewWriter(compressed, level)
+	if err != nil {
+		b.Fatal(err)
+	}
+	for i := 0; i < n; i += len(buf0) {
+		if len(buf0) > n-i {
+			buf0 = buf0[:n-i]
+		}
+		io.Copy(w, bytes.NewBuffer(buf0))
+	}
+	w.Close()
+	buf1 := compressed.Bytes()
+	buf0, compressed, w = nil, nil, nil
+	runtime.GC()
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		io.Copy(ioutil.Discard, NewReader(bytes.NewBuffer(buf1)))
+	}
+}
+
+// These short names are so that gofmt doesn't break the BenchmarkXxx function
+// bodies below over multiple lines.
+const (
+	speed    = BestSpeed
+	default_ = DefaultCompression
+	compress = BestCompression
+)
+
+func BenchmarkDecodeDigitsSpeed1e4(b *testing.B)    { benchmarkDecode(b, digits, speed, 1e4) }
+func BenchmarkDecodeDigitsSpeed1e5(b *testing.B)    { benchmarkDecode(b, digits, speed, 1e5) }
+func BenchmarkDecodeDigitsSpeed1e6(b *testing.B)    { benchmarkDecode(b, digits, speed, 1e6) }
+func BenchmarkDecodeDigitsDefault1e4(b *testing.B)  { benchmarkDecode(b, digits, default_, 1e4) }
+func BenchmarkDecodeDigitsDefault1e5(b *testing.B)  { benchmarkDecode(b, digits, default_, 1e5) }
+func BenchmarkDecodeDigitsDefault1e6(b *testing.B)  { benchmarkDecode(b, digits, default_, 1e6) }
+func BenchmarkDecodeDigitsCompress1e4(b *testing.B) { benchmarkDecode(b, digits, compress, 1e4) }
+func BenchmarkDecodeDigitsCompress1e5(b *testing.B) { benchmarkDecode(b, digits, compress, 1e5) }
+func BenchmarkDecodeDigitsCompress1e6(b *testing.B) { benchmarkDecode(b, digits, compress, 1e6) }
+func BenchmarkDecodeTwainSpeed1e4(b *testing.B)     { benchmarkDecode(b, twain, speed, 1e4) }
+func BenchmarkDecodeTwainSpeed1e5(b *testing.B)     { benchmarkDecode(b, twain, speed, 1e5) }
+func BenchmarkDecodeTwainSpeed1e6(b *testing.B)     { benchmarkDecode(b, twain, speed, 1e6) }
+func BenchmarkDecodeTwainDefault1e4(b *testing.B)   { benchmarkDecode(b, twain, default_, 1e4) }
+func BenchmarkDecodeTwainDefault1e5(b *testing.B)   { benchmarkDecode(b, twain, default_, 1e5) }
+func BenchmarkDecodeTwainDefault1e6(b *testing.B)   { benchmarkDecode(b, twain, default_, 1e6) }
+func BenchmarkDecodeTwainCompress1e4(b *testing.B)  { benchmarkDecode(b, twain, compress, 1e4) }
+func BenchmarkDecodeTwainCompress1e5(b *testing.B)  { benchmarkDecode(b, twain, compress, 1e5) }
+func BenchmarkDecodeTwainCompress1e6(b *testing.B)  { benchmarkDecode(b, twain, compress, 1e6) }
diff --git a/src/pkg/compress/flate/writer_test.go b/src/pkg/compress/flate/writer_test.go
new file mode 100644
index 0000000..5843177
--- /dev/null
+++ b/src/pkg/compress/flate/writer_test.go
@@ -0,0 +1,60 @@
+// 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 flate
+
+import (
+	"io/ioutil"
+	"runtime"
+	"testing"
+)
+
+func benchmarkEncoder(b *testing.B, testfile, level, n int) {
+	b.StopTimer()
+	b.SetBytes(int64(n))
+	buf0, err := ioutil.ReadFile(testfiles[testfile])
+	if err != nil {
+		b.Fatal(err)
+	}
+	if len(buf0) == 0 {
+		b.Fatalf("test file %q has no data", testfiles[testfile])
+	}
+	buf1 := make([]byte, n)
+	for i := 0; i < n; i += len(buf0) {
+		if len(buf0) > n-i {
+			buf0 = buf0[:n-i]
+		}
+		copy(buf1[i:], buf0)
+	}
+	buf0 = nil
+	runtime.GC()
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		w, err := NewWriter(ioutil.Discard, level)
+		if err != nil {
+			b.Fatal(err)
+		}
+		w.Write(buf1)
+		w.Close()
+	}
+}
+
+func BenchmarkEncodeDigitsSpeed1e4(b *testing.B)    { benchmarkEncoder(b, digits, speed, 1e4) }
+func BenchmarkEncodeDigitsSpeed1e5(b *testing.B)    { benchmarkEncoder(b, digits, speed, 1e5) }
+func BenchmarkEncodeDigitsSpeed1e6(b *testing.B)    { benchmarkEncoder(b, digits, speed, 1e6) }
+func BenchmarkEncodeDigitsDefault1e4(b *testing.B)  { benchmarkEncoder(b, digits, default_, 1e4) }
+func BenchmarkEncodeDigitsDefault1e5(b *testing.B)  { benchmarkEncoder(b, digits, default_, 1e5) }
+func BenchmarkEncodeDigitsDefault1e6(b *testing.B)  { benchmarkEncoder(b, digits, default_, 1e6) }
+func BenchmarkEncodeDigitsCompress1e4(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e4) }
+func BenchmarkEncodeDigitsCompress1e5(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e5) }
+func BenchmarkEncodeDigitsCompress1e6(b *testing.B) { benchmarkEncoder(b, digits, compress, 1e6) }
+func BenchmarkEncodeTwainSpeed1e4(b *testing.B)     { benchmarkEncoder(b, twain, speed, 1e4) }
+func BenchmarkEncodeTwainSpeed1e5(b *testing.B)     { benchmarkEncoder(b, twain, speed, 1e5) }
+func BenchmarkEncodeTwainSpeed1e6(b *testing.B)     { benchmarkEncoder(b, twain, speed, 1e6) }
+func BenchmarkEncodeTwainDefault1e4(b *testing.B)   { benchmarkEncoder(b, twain, default_, 1e4) }
+func BenchmarkEncodeTwainDefault1e5(b *testing.B)   { benchmarkEncoder(b, twain, default_, 1e5) }
+func BenchmarkEncodeTwainDefault1e6(b *testing.B)   { benchmarkEncoder(b, twain, default_, 1e6) }
+func BenchmarkEncodeTwainCompress1e4(b *testing.B)  { benchmarkEncoder(b, twain, compress, 1e4) }
+func BenchmarkEncodeTwainCompress1e5(b *testing.B)  { benchmarkEncoder(b, twain, compress, 1e5) }
+func BenchmarkEncodeTwainCompress1e6(b *testing.B)  { benchmarkEncoder(b, twain, compress, 1e6) }
diff --git a/src/pkg/compress/lzw/reader_test.go b/src/pkg/compress/lzw/reader_test.go
index e5be12f..6f155b1 100644
--- a/src/pkg/compress/lzw/reader_test.go
+++ b/src/pkg/compress/lzw/reader_test.go
@@ -114,11 +114,19 @@ func TestReader(t *testing.T) {
 func benchmarkDecoder(b *testing.B, n int) {
 	b.StopTimer()
 	b.SetBytes(int64(n))
-	buf0, _ := ioutil.ReadFile("../testdata/e.txt")
-	buf0 = buf0[:10000]
+	buf0, err := ioutil.ReadFile("../testdata/e.txt")
+	if err != nil {
+		b.Fatal(err)
+	}
+	if len(buf0) == 0 {
+		b.Fatalf("test file has no data")
+	}
 	compressed := new(bytes.Buffer)
 	w := NewWriter(compressed, LSB, 8)
 	for i := 0; i < n; i += len(buf0) {
+		if len(buf0) > n-i {
+			buf0 = buf0[:n-i]
+		}
 		io.Copy(w, bytes.NewBuffer(buf0))
 	}
 	w.Close()
diff --git a/src/pkg/compress/lzw/writer.go b/src/pkg/compress/lzw/writer.go
index 488ba64..b206918 100644
--- a/src/pkg/compress/lzw/writer.go
+++ b/src/pkg/compress/lzw/writer.go
@@ -13,7 +13,7 @@ import (
 
 // A writer is a buffered, flushable writer.
 type writer interface {
-	WriteByte(byte) error
+	io.ByteWriter
 	Flush() error
 }
 
@@ -131,13 +131,14 @@ func (e *encoder) incHi() error {
 }
 
 // Write writes a compressed representation of p to e's underlying writer.
-func (e *encoder) Write(p []byte) (int, error) {
+func (e *encoder) Write(p []byte) (n int, err error) {
 	if e.err != nil {
 		return 0, e.err
 	}
 	if len(p) == 0 {
 		return 0, nil
 	}
+	n = len(p)
 	litMask := uint32(1<<e.litWidth - 1)
 	code := e.savedCode
 	if code == invalidCode {
@@ -167,11 +168,11 @@ loop:
 		code = literal
 		// Increment e.hi, the next implied code. If we run out of codes, reset
 		// the encoder state (including clearing the hash table) and continue.
-		if err := e.incHi(); err != nil {
-			if err == errOutOfCodes {
+		if err1 := e.incHi(); err1 != nil {
+			if err1 == errOutOfCodes {
 				continue
 			}
-			e.err = err
+			e.err = err1
 			return 0, e.err
 		}
 		// Otherwise, insert key -> e.hi into the map that e.table represents.
@@ -184,7 +185,7 @@ loop:
 		}
 	}
 	e.savedCode = code
-	return len(p), nil
+	return n, nil
 }
 
 // Close closes the encoder, flushing any pending output. It does not close or
diff --git a/src/pkg/compress/lzw/writer_test.go b/src/pkg/compress/lzw/writer_test.go
index d249a09..3e4e6de 100644
--- a/src/pkg/compress/lzw/writer_test.go
+++ b/src/pkg/compress/lzw/writer_test.go
@@ -96,13 +96,29 @@ func TestWriter(t *testing.T) {
 	}
 }
 
+func TestWriterReturnValues(t *testing.T) {
+	w := NewWriter(ioutil.Discard, LSB, 8)
+	n, err := w.Write([]byte("asdf"))
+	if n != 4 || err != nil {
+		t.Errorf("got %d, %v, want 4, nil", n, err)
+	}
+}
+
 func benchmarkEncoder(b *testing.B, n int) {
 	b.StopTimer()
 	b.SetBytes(int64(n))
-	buf0, _ := ioutil.ReadFile("../testdata/e.txt")
-	buf0 = buf0[:10000]
+	buf0, err := ioutil.ReadFile("../testdata/e.txt")
+	if err != nil {
+		b.Fatal(err)
+	}
+	if len(buf0) == 0 {
+		b.Fatalf("test file has no data")
+	}
 	buf1 := make([]byte, n)
 	for i := 0; i < n; i += len(buf0) {
+		if len(buf0) > n-i {
+			buf0 = buf0[:n-i]
+		}
 		copy(buf1[i:], buf0)
 	}
 	buf0 = nil
diff --git a/src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt b/src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt
index 8d0ff4e..c97da7e 100644
--- a/src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt
+++ b/src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt
@@ -1,4 +1,4 @@
-The Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
+The Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
 by Mark Twain (Samuel Clemens)
 
 This eBook is for the use of anyone anywhere at no cost and with
diff --git a/src/pkg/compress/testdata/e.txt b/src/pkg/compress/testdata/e.txt
index 76cf2a7..5ca186f 100644
--- a/src/pkg/compress/testdata/e.txt
+++ b/src/pkg/compress/testdata/e.txt
@@ -1 +1 @@
-2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190115738341879307021540891499348841675092447614606680822648001684774118537423454424371075390777449920695517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416928368190255151086574637721112523897844250569536967707854499699679468644549059879316368892300987931277361782154249992295763514822082698951936680331825288693984964651058209392398294887933203625094431173012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509961818815930416903515988885193458072738667385894228792284998920868058257492796104841984443634632449684875602336248270419786232090021609902353043699418491463140934317381436405462531520961836908887070167683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354021234078498193343210681701210056278802351930332247450158539047304199577770935036604169973297250886876966403555707162268447162560798826517871341951246652010305921236677194325278675398558944896970964097545918569563802363701621120477427228364896134225164450781824423529486363721417402388934412479635743702637552944483379980161254922785092577825620926226483262779333865664816277251640191059004916449982893150566047258027786318641551956532442586982946959308019152987211725563475463964479101459040905862984967912874068705048958586717479854667757573205681288459205413340539220001137863009455606881667400169842055804033637953764520304024322566135278369511778838638744396625322498506549958862342818997077332761717839280349465014345588970719425863987727547109629537415211151368350627526023264847287039207643100595841166120545297030236472549296669381151373227536450988890313602057248176585118063036442812314965507047510254465011727211555194866850800368532281831521960037356252794495158284188294787610852639813955990067376482922443752871846245780361929819713991475644882626039033814418232625150974827987779964373089970388867782271383605772978824125611907176639465070633045279546618550966661856647097113444740160704626215680717481877844371436988218559670959102596862002353718588748569652200050311734392073211390803293634479727355955277349071783793421637012050054513263835440001863239914907054797780566978533580489669062951194324730995876552368128590413832411607226029983305353708761389396391779574540161372236187893652605381558415871869255386061647798340254351284396129460352913325942794904337299085731580290958631382683291477116396337092400316894586360606458459251269946557248391865642097526850823075442545993769170419777800853627309417101634349076964237222943523661255725088147792231519747780605696725380171807763603462459278778465850656050780844211529697521890874019660906651803516501792504619501366585436632712549639908549144200014574760819302212066024330096412704894390397177195180699086998606636583232278709376502260149291011517177635944602023249300280401867723910288097866605651183260043688508817157238669842242201024950551881694803221002515426494639812873677658927688163598312477886520141174110913601164995076629077943646005851941998560162647907615321038727557126992518275687989302761761146162549356495903798045838182323368612016243736569846703785853305275833337939907521660692380533698879565137285593883499894707416181550125397064648171946708348197214488898790676503795903669672494992545279033729636162658976039498576741397359441023744329709355477982629614591442936451428617158587339746791897571211956187385783644758448423555581050025611492391518893099463428413936080383091662818811503715284967059741625628236092168075150177725387402564253470879089137291722828611515915683725241630772254406337875931059826760944203261924285317018781772960235413060672136046000389661093647095141417185777014180606443636815464440053316087783143174440811949422975599314011888683314832802706553833004693290115744147563139997221703804617092894579096271662260740718749975359212756084414737823303270330168237193648002173285734935947564334129943024850235732214597843282641421684878721673367010615094243456984401873312810107945127223737886126058165668053714396127888732527373890392890506865324138062796025930387727697783792868409325365880733988457218746021005311483351323850047827169376218004904795597959290591655470505777514308175112698985188408718564026035305583737832422924185625644255022672155980274012617971928047139600689163828665277009752767069777036439260224372841840883251848770472638440379530166905465937461619323840363893131364327137688841026811219891275223056256756254701725086349765367288605966752740868627407912856576996313789753034660616669804218267724560530660773899624218340859882071864682623215080288286359746839654358856685503773131296587975810501214916207656769950659715344763470320853215603674828608378656803073062657633469774295634643716709397193060876963495328846833613038829431040800296873869117066666146800015121143442256023874474325250769387077775193299942137277211258843608715834835626961661980572526612206797540621062080649882918454395301529982092503005498257043390553570168653120526495614857249257386206917403695213533732531666345466588597286659451136441370331393672118569553952108458407244323835586063106806964924851232632699514603596037297253198368423363904632136710116192821711150282801604488058802382031981493096369596735832742024988245684941273860566491352526706046234450549227581151709314921879592718001940968866986837037302200475314338181092708030017205935530520700706072233999463990571311587099635777359027196285061146514837526209565346713290025994397663114545902685898979115837093419370441155121920117164880566945938131183843765620627846310490346293950029458341164824114969758326011800731699437393506966295712410273239138741754923071862454543222039552735295240245903805744502892246886285336542213815722131163288112052146489805180092024719391710555390113943316681515828843687606961102505171007392762385553386272553538830960671644662370922646809671254061869502143176211668140097595281493907222601112681153108387317617323235263605838173151034595736538223534992935822836851007810884634349983518404451704270189381994243410090575376257767571118090088164183319201962623416288166521374717325477727783488774366518828752156685719506371936565390389449366421764003121527870222366463635755503565576948886549500270853923617105502131147413744106134445544192101336172996285694899193369184729478580729156088510396781959429833186480756083679551496636448965592948187851784038773326247051945050419847742014183947731202815886845707290544057510601285258056594703046836344592652552137008068752009593453607316226118728173928074623094685367823106097921599360019946237993434210687813497346959246469752506246958616909178573976595199392993995567542714654910456860702099012606818704984178079173924071945996323060254707901774527513186809982284730860766536866855516467702911336827563107223346726113705490795365834538637196235856312618387156774118738527722922594743373785695538456246801013905727871016512966636764451872465653730402443684140814488732957847348490003019477888020460324660842875351848364959195082888323206522128104190448047247949291342284951970022601310430062410717971502793433263407995960531446053230488528972917659876016667811937932372453857209607582277178483361613582612896226118129455927462767137794487586753657544861407611931125958512655759734573015333642630767985443385761715333462325270572005303988289499034259566232975782488735029259166825894456894655992658454762694528780516501720674785417887982276806536650641910973434528878338621726156269582654478205672987756426325321594294418039943217000090542650763095588465895171709147607437136893319469090981904501290307099566226620303182649365733698419555776963787624918852865686607600566025605445711337286840205574416030837052312242587223438854123179481388550075689381124935386318635287083799845692619981794523364087429591180747453419551420351726184200845509170845682368200897739455842679214273477560879644279202708312150156406341341617166448069815483764491573900121217041547872591998943825364950514771379399147205219529079396137621107238494290616357604596231253506068537651423115349665683715116604220796394466621163255157729070978473156278277598788136491951257483328793771571459091064841642678309949723674420175862269402159407924480541255360431317992696739157542419296607312393763542139230617876753958711436104089409966089471418340698362993675362621545247298464213752891079884381306095552622720837518629837066787224430195793793786072107254277289071732854874374355781966511716618330881129120245204048682200072344035025448202834254187884653602591506445271657700044521097735585897622655484941621714989532383421600114062950718490427789258552743035221396835679018076406042138307308774460170842688272261177180842664333651780002171903449234264266292261456004337383868335555343453004264818473989215627086095650629340405264943244261445665921291225648893569655009154306426134252668472594914314239398845432486327461842846655985332312210466259890141712103446084271616619001257195870793217569698544013397622096749454185407118446433946990162698351607848924514058940946395267807354579700307051163682519487701189764002827648414160587206184185297189154019688253289309149665345753571427318482016384644832499037886069008072709327673127581966563941148961716832980455139729506687604740915420428429993541025829113502241690769431668574242522509026939034814856451303069925199590436384028429267412573422447765584177886171737265462085498294498946787350929581652632072258992368768457017823038096567883112289305809140572610865884845873101658151167533327674887014829167419701512559782572707406431808601428149024146780472327597684269633935773542930186739439716388611764209004068663398856841681003872389214483176070116684503887212364367043314091155733280182977988736590916659612402021778558854876176161989370794380056663364884365089144805571039765214696027662583599051987042300179465536788
+2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190115738341879307021540891499348841675092447614606680822648001684774118537423454424371075390777449920695517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416928368190255151086574637721112523897844250569536967707854499699679468644549059879316368892300987931277361782154249992295763514822082698951936680331825288693984964651058209392398294887933203625094431173012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509961818815930416903515988885193458072738667385894228792284998920868058257492796104841984443634632449684875602336248270419786232090021609902353043699418491463140934317381436405462531520961836908887070167683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354021234078498193343210681701210056278802351930332247450158539047304199577770935036604169973297250886876966403555707162268447162560798826517871341951246652010305921236677194325278675398558944896970964097545918569563802363701621120477427228364896134225164450781824423529486363721417402388934412479635743702637552944483379980161254922785092577825620926226483262779333865664816277251640191059004916449982893150566047258027786318641551956532442586982946959308019152987211725563475463964479101459040905862984967912874068705048958586717479854667757573205681288459205413340539220001137863009455606881667400169842055804033637953764520304024322566135278369511778838638744396625322498506549958862342818997077332761717839280349465014345588970719425863987727547109629537415211151368350627526023264847287039207643100595841166120545297030236472549296669381151373227536450988890313602057248176585118063036442812314965507047510254465011727211555194866850800368532281831521960037356252794495158284188294787610852639813955990067376482922443752871846245780361929819713991475644882626039033814418232625150974827987779964373089970388867782271383605772978824125611907176639465070633045279546618550966661856647097113444740160704626215680717481877844371436988218559670959102596862002353718588748569652200050311734392073211390803293634479727355955277349071783793421637012050054513263835440001863239914907054797780566978533580489669062951194324730995876552368128590413832411607226029983305353708761389396391779574540161372236187893652605381558415871869255386061647798340254351284396129460352913325942794904337299085731580290958631382683291477116396337092400316894586360606458459251269946557248391865642097526850823075442545993769170419777800853627309417101634349076964237222943523661255725088147792231519747780605696725380171807763603462459278778465850656050780844211529697521890874019660906651803516501792504619501366585436632712549639908549144200014574760819302212066024330096412704894390397177195180699086998606636583232278709376502260149291011517177635944602023249300280401867723910288097866605651183260043688508817157238669842242201024950551881694803221002515426494639812873677658927688163598312477886520141174110913601164995076629077943646005851941998560162647907615321038727557126992518275687989302761761146162549356495903798045838182323368612016243736569846703785853305275833337939907521660692380533698879565137285593883499894707416181550125397064648171946708348197214488898790676503795903669672494992545279033729636162658976039498576741397359441023744329709355477982629614591442936451428617158587339746791897571211956187385783644758448423555581050025611492391518893099463428413936080383091662818811503715284967059741625628236092168075150177725387402564253470879089137291722828611515915683725241630772254406337875931059826760944203261924285317018781772960235413060672136046000389661093647095141417185777014180606443636815464440053316087783143174440811949422975599314011888683314832802706553833004693290115744147563139997221703804617092894579096271662260740718749975359212756084414737823303270330168237193648002173285734935947564334129943024850235732214597843282641421684878721673367010615094243456984401873312810107945127223737886126058165668053714396127888732527373890392890506865324138062796025930387727697783792868409325365880733988457218746021005311483351323850047827169376218004904795597959290591655470505777514308175112698985188408718564026035305583737832422924185625644255022672155980274012617971928047139600689163828665277009752767069777036439260224372841840883251848770472638440379530166905465937461619323840363893131364327137688841026811219891275223056256756254701725086349765367288605966752740868627407912856576996313789753034660616669804218267724560530660773899624218340859882071864682623215080288286359746839654358856685503773131296587975810501214916207656769950659715344763470320853215603674828608378656803073062657633469774295634643716709397193060876963495328846833613038829431040800296873869117066666146800015121143442256023874474325250769387077775193299942137277211258843608715834835626961661980572526612206797540621062080649882918454395301529982092503005498257043390553570168653120526495614857249257386206917403695213533732531666345466588597286659451136441370331393672118569553952108458407244323835586063106806964924851232632699514603596037297253198368423363904632136710116192821711150282801604488058802382031981493096369596735832742024988245684941273860566491352526706046234450549227581151709314921879592718001940968866986837037302200475314338181092708030017205935530520700706072233999463990571311587099635777359027196285061146514837526209565346713290025994397663114545902685898979115837093419370441155121920117164880566945938131183843765620627846310490346293950029458341164824114969758326011800731699437393506966295712410273239138741754923071862454543222039552735295240245903805744502892246886285336542213815722131163288112052146489805180092024719391710555390113943316681515828843687606961102505171007392762385553386272553538830960671644662370922646809671254061869502143176211668140097595281493907222601112681153108387317617323235263605838173151034595736538223534992935822836851007810884634349983518404451704270189381994243410090575376257767571118090088164183319201962623416288166521374717325477727783488774366518828752156685719506371936565390389449366421764003121527870222366463635755503565576948886549500270853923617105502131147413744106134445544192101336172996285694899193369184729478580729156088510396781959429833186480756083679551496636448965592948187851784038773326247051945050419847742014183947731202815886845707290544057510601285258056594703046836344592652552137008068752009593453607316226118728173928074623094685367823106097921599360019946237993434210687813497346959246469752506246958616909178573976595199392993995567542714654910456860702099012606818704984178079173924071945996323060254707901774527513186809982284730860766536866855516467702911336827563107223346726113705490795365834538637196235856312618387156774118738527722922594743373785695538456246801013905727871016512966636764451872465653730402443684140814488732957847348490003019477888020460324660842875351848364959195082888323206522128104190448047247949291342284951970022601310430062410717971502793433263407995960531446053230488528972917659876016667811937932372453857209607582277178483361613582612896226118129455927462767137794487586753657544861407611931125958512655759734573015333642630767985443385761715333462325270572005303988289499034259566232975782488735029259166825894456894655992658454762694528780516501720674785417887982276806536650641910973434528878338621726156269582654478205672987756426325321594294418039943217000090542650763095588465895171709147607437136893319469090981904501290307099566226620303182649365733698419555776963787624918852865686607600566025605445711337286840205574416030837052312242587223438854123179481388550075689381124935386318635287083799845692619981794523364087429591180747453419551420351726184200845509170845682368200897739455842679214273477560879644279202708312150156406341341617166448069815483764491573900121217041547872591998943825364950514771379399147205219529079396137621107238494290616357604596231253506068537651423115349665683715116604220796394466621163255157729070978473156278277598788136491951257483328793771571459091064841642678309949723674420175862269402159407924480541255360431317992696739157542419296607312393763542139230617876753958711436104089409966089471418340698362993675362621545247298464213752891079884381306095552622720837518629837066787224430195793793786072107254277289071732854874374355781966511716618330881129120245204048682200072344035025448202834254187884653602591506445271657700044521097735585897622655484941621714989532383421600114062950718490427789258552743035221396835679018076406042138307308774460170842688272261177180842664333651780002171903449234264266292261456004337383868335555343453004264818473989215627086095650629340405264943244261445665921291225648893569655009154306426134252668472594914314239398845432486327461842846655985332312210466259890141712103446084271616619001257195870793217569698544013397622096749454185407118446433946990162698351607848924514058940946395267807354579700307051163682519487701189764002827648414160587206184185297189154019688253289309149665345753571427318482016384644832499037886069008072709327673127581966563941148961716832980455139729506687604740915420428429993541025829113502241690769431668574242522509026939034814856451303069925199590436384028429267412573422447765584177886171737265462085498294498946787350929581652632072258992368768457017823038096567883112289305809140572610865884845873101658151167533327674887014829167419701512559782572707406431808601428149024146780472327597684269633935773542930186739439716388611764209004068663398856841681003872389214483176070116684503887212364367043314091155733280182977988736590916659612402021778558854876176161989370794380056663364884365089144805571039765214696027662583599051987042300179465536788567430285974600143785483237068701190078499404930918919181649327259774030074879681484882342932023012128032327460392219687528340516906974194257614673978110715464186273369091584973185011183960482533518748438923177292613543024932562896371361977285456622924461644497284597867711574125670307871885109336344480149675240618536569532074170533486782754827815415561966911055101472799040386897220465550833170782394808785990501947563108984124144672821865459971596639015641941751820935932616316888380132758752601460507676098392625726411120135288591317848299475682472564885533357279772205543568126302535748216585414000805314820697137262149755576051890481622376790414926742600071045922695314835188137463887104273544767623577933993970632396604969145303273887874557905934937772320142954803345000695256980935282887783710670585567749481373858630385762823040694005665340584887527005308832459182183494318049834199639981458773435863115940570443683515285383609442955964360676090221741896883548131643997437764158365242234642619597390455450680695232850751868719449064767791886720306418630751053512149851051207313846648717547518382979990189317751550639981016466414592102406838294603208535554058147159273220677567669213664081505900806952540610628536408293276621931939933861623836069111767785448236129326858199965239275488427435414402884536455595124735546139403154952097397051896240157976832639450633230452192645049651735466775699295718989690470902730288544945416699791992948038254980285946029052763145580316514066229171223429375806143993484914362107993576737317948964252488813720435579287511385856973381976083524423240466778020948399639946684833774706725483618848273000648319163826022110555221246733323184463005504481849916996622087746140216157021029603318588727333298779352570182393861244026868339555870607758169954398469568540671174444932479519572159419645863736126915526457574786985964242176592896862383506370433939811671397544736228625506803682664135541448048997721373174119199970017293907303350869020922519124447393278376156321810842898207706974138707053266117683698647741787180202729412982310888796831880854367327806879771659111654224453806625861711729498038248879986504061563975629936962809358189761491017145343556659542757064194408833816841111166200759787244137082333917886114708228657531078536674695018462140736493917366254937783014074302668422150335117736471853872324040421037907750266020114814935482228916663640782450166815341213505278578539332606110249802273093636740213515386431693015267460536064351732154701091440650878823636764236831187390937464232609021646365627553976834019482932795750624399645272578624400375983422050808935129023122475970644105678361870877172333555465482598906861201410107222465904008553798235253885171623518256518482203125214950700378300411216212126052726059944320443056274522916128891766814160639131235975350390320077529587392412476451850809163911459296071156344204347133544720981178461451077872399140606290228276664309264900592249810291068759434533858330391178747575977065953570979640012224092199031158229259667913153991561438070129260780197022589662923368154312499412259460023399472228171056603931877226800493833148980338548909468685130789292064242819174795866199944411196208730498064385006852620258432842085582338566936649849720817046135376163584015342840674118587581546514598270228676671855309311923340191286170613364873183197560812569460089402953094429119590295968563923037689976327462283900735457144596414108229285922239332836210192822937243590283003884445701383771632056518351970100115722010956997890484964453434612129224964732356126321951155701565824427661599326463155806672053127596948538057364208384918887095176052287817339462747644656858900936266123311152910816041524100214195937349786431661556732702792109593543055579732660554677963552005378304619540636971842916168582734122217145885870814274090248185446421774876925093328785670674677381226752831653559245204578070541352576903253522738963847495646255940378924925007624386893776475310102323746733771474581625530698032499033676455430305274561512961214585944432150749051491453950981001388737926379964873728396416897555132275962011838248650746985492038097691932606437608743209385602815642849756549307909733854185583515789409814007691892389063090542534883896831762904120212949167195811935791203162514344096503132835216728021372415947344095498316138322505486708172221475138425166790445416617303200820330902895488808516797258495813407132180533988828139346049850532340472595097214331492586604248511405819579711564191458842833000525684776874305916390494306871343118796189637475503362820939949343690321031976898112055595369465424704173323895394046035325396758354395350516720261647961347790912327995264929045151148307923369382166010702872651938143844844532639517394110131152502750465749343063766541866128915264446926222884366299462732467958736383501937142786471398054038215513463223702071533134887083174146591492406359493020921122052610312390682941345696785958518393491382340884274312419099152870804332809132993078936867127413922890033069995875921815297612482409116951587789964090352577345938248232053055567238095022266790439614231852991989181065554412477204508510210071522352342792531266930108270633942321762570076323139159349709946933241013908779161651226804414809765618979735043151396066913258379033748620836695475083280318786707751177525663963479259219733577949555498655214193398170268639987388347010255262052312317215254062571636771270010760912281528326508984359568975961038372157726831170734552250194121701541318793651818502020877326906133592182000762327269503283827391243828198170871168108951187896746707073377869592565542713340052326706040004348843432902760360498027862160749469654989210474443927871934536701798673920803845633723311983855862638008516345597194441994344624761123844617615736242015935078520825600604101556889899501732554337298073561699861101908472096600708320280569917042590103876928658336557728758684250492690370934262028022399861803400211320742198642917383679176232826444645756330336556777374808644109969141827774253417010988435853189339175934511574023847292909015468559163792696196841000676598399744972047287881831200233383298030567865480871476464512824264478216644266616732096012564794514827125671326697067367144617795643752391742928503987022583734069852309190464967260243411270345611114149835783901793499713790913696706497637127248466613279908254305449295528594932793818341607827091326680865655921102733746700132583428715240835661522165574998431236278287106649401564670141943713823863454729606978693335973109537126499416282656463708490580151538205338326511289504938566468752921135932220265681856418260827538790002407915892646028490894922299966167437731347776134150965262448332709343898412056926145108857812249139616912534202918139898683901335795857624435194008943955180554746554000051766240202825944828833811886381749594284892013520090951007864941868256009273977667585642598378587497776669563350170748579027248701370264203283965756348010818356182372177082236423186591595883669487322411726504487268392328453010991677518376831599821263237123854357312681202445175401852132663740538802901249728180895021553100673598184430429105288459323064725590442355960551978839325930339572934663055160430923785677229293537208416693134575284011873746854691620648991164726909428982971065606801805807843600461866223562874591385185904416250663222249561448724413813849763797102676020845531824111963927941069619465426480006761727618115630063644321116224837379105623611358836334550102286170517890440570419577859833348463317921904494652923021469259756566389965893747728751393377105569802455757436190501772466214587592374418657530064998056688376964229825501195065837843125232135309371235243969149662310110328243570065781487677299160941153954063362752423712935549926713485031578238899567545287915578420483105749330060197958207739558522807307048950936235550769837881926357141779338750216344391014187576711938914416277109602859415809719913429313295145924373636456473035037374538503489286113141638094752301745088784885645741275003353303416138096560043105860548355773946625033230034341587814634602169235079216111013148948281895391028916816328709309713184139815427678818067628650978085718262117003140003377301581536334149093237034703637513354537634521050370995452942055232078817449370937677056009306353645510913481627378204985657055608784211964039972344556458607689515569686899384896439195225232309703301037277227710870564912966121061494072782442033414057441446459968236966118878411656290355117839944070961772567164919790168195234523807446299877664824873753313018142763910519234685081979001796519907050490865237442841652776611425351538665162781316090964802801234493372427866930894827913465443931965254154829494577875758599482099181824522449312077768250830768282335001597040419199560509705364696473142448453825888112602753909548852639708652339052941829691802357120545328231809270356491743371932080628731303589640570873779967845174740515317401384878082881006046388936711640477755985481263907504747295012609419990373721246201677030517790352952793168766305099837441859803498821239340919805055103821539827677291373138006715339240126954586376422065097810852907639079727841301764553247527073788764069366420012194745702358295481365781809867944020220280822637957006755393575808086318932075864444206644691649334467698180811716568665213389686173592450920801465312529777966137198695916451869432324246404401672381978020728394418264502183131483366019384891972317817154372192103946638473715630226701801343515930442853848941825678870721238520597263859224934763623122188113706307506918260109689069251417142514218153491532129077723748506635489170892850760234351768218355008829647410655814882049239533702270536705630750317499788187009989251020178015601042277836283644323729779929935160925884515772055232896978333126427671291093993103773425910592303277652667641874842441076564447767097790392324958416348527735171981064673837142742974468992320406932506062834468937543016787815320616009057693404906146176607094380110915443261929000745209895959201159412324102274845482605404361871836330268992858623582145643879695210235266673372434423091577183277565800211928270391042391966426911155333594569685782817020325495552528875464466074620294766116004435551604735044292127916358748473501590215522120388281168021413865865168464569964810015633741255098479730138656275460161279246359783661480163871602794405482710196290774543628092612567507181773641749763254436773503632580004042919906963117397787875081560227368824967077635559869284901628768699628053790181848148810833946900016380791075960745504688912686792812391148880036720729730801354431325347713094186717178607522981373539126772812593958220524289991371690685650421575056729991274177149279608831502358697816190894908487717722503860872618384947939757440664912760518878124233683125467278331513186758915668300679210215947336858591201395360301678110413444411030903388761520488296909104689167671555373346622545575975202624771242796225983278405833585897671474205724047439720232895903726148688388003174146490203843590358527993123871042845981608996101945691646983837718267264685264869172948414153004604004299585035164101899027529366867431834955447458124140190754681607770977920579383895378192128847409929537040546962226547278807248685508046571043123854873351653070570784584243335550958221912862797205455466267099131902370311779690892786623112661337671178512943059323281605826535623848164192144732543731002062738466812351691016359252588256806438946389880872735284406462208149513862275239938938734905082625472417781702582044129853760499827899020083498387362992498125742354568439023012261733665820546785671147973065077035475620567428300187473019197310881157516777005071432012726354601912460800451608108641835539669946936947322271670748972850464195392966434725254724357659192969949061670189061433616907056148280980363243454128229968275980226694045642181328624517549652147221620839824594576613342710564957193564431561774500828376935700995419541839029151033187933907614207467028867968594985439789457300768939890070073924697461812855764662265412913204052279071212820653775058280040897163467163709024906774736309136904002615646432159560910851092445162454420141442641660181385990017417408244245378610158433361777292580611159192008414091888191208858207627011483671760749046980914443057262211104583300789331698191603917150622792986282709446275915009683226345073725451366858172483498470080840163868209726371345205439802277866337293290829914010645589761697455978409211409167684020269370229231743334499986901841510888993165125090001163719114994852024821586396216294981753094623047604832399379391002142532996476235163569009445086058091202459904612118623318278614464727795523218635916551883057930657703331498510068357135624341881884405780028844018129031378653794869614630467726914552953690154167025838032477842272417994513653582260971652588356712133519546838335349801503269359798167463231847628306340588324731228951257944267639877946713121042763380872695738609314631539148548792514028885025189788076023838995615684850391995855029256054176767663145354058496296796781349420116003325874431438746248313850214980401681940795687219268462617287403480967931949965604299190281810597603263251746405016454606266765529010639868703668263299050577706266397868453584384057673298268163448646707439990917504018892319267557518354054956017732907127219134577524905771512773358423314008356080926962298894163047287780054743798498545562870729968407382937218623831766524716090967192007237658894226186550487552614557855898773008703234726418384831040394818743616224455286163287628541175946460497027724490799275146445792982549802258601001772437840167723166802004162547244179415547810554178036773553354467030326469619447560812831933095679685582771932031205941616693902049665352189672822671972640029493307384717544753761937017882976382487233361813499414541694736549254840633793674361541081593464960431603544354737728802361047743115330785159902977771499610274627769759612488879448609863349422852847651310277926279743981957617505591300993377368240510902583759345170015340522266144077237050890044496613295859536020556034009492820943862994618834790932894161098856594954213114335608810239423706087108026465913203560121875933791639666437282836752328391688865373751335794859860107569374889645657187292540448508624449947816273842517229343960137212406286783636675845331904743954740664015260871940915743955282773904303868772728262065663129387459875317749973799293043294371763801856280061141619563942414312254397099163565102848315765427037906837175764870230052388197498746636856292655058222887713221781440489538099681072143012394693530931524054081215705402274414521876541901428386744260011889041724570537470755550581632831687247110220353727166112304857340460879272501694701067831178927095527253222125224361673343366384756590949728221809418684074238351567868893421148203905824224324264643630201441787982022116248471657468291146315407563770222740135841109076078464780070182766336227978104546331131294044833570134869585165267459515187680033395522410548181767867772152798270250117195816577603549732923724732067853690257536233971216884390878879262188202305529937132397194333083536231248870386416194361506529551267334207198502259771408638122015980894363561808597010080081622557455039101321981979045520049618583777721048046635533806616517023595097133203631578945644487800945620369784973459902004606886572701865867757842758530645706617127194967371083950603267501532435909029491516973738110897934782297684100117657987098185725131372267749706609250481876835516003714638685918913011736805218743265426063700710595364425062760458252336880552521181566417553430681181548267844169315284408461087588214317641649835663127518728182948655658524206852221830755306118393326934164459415342651778653397980580828158806300749952897558204686612590853678738603318442905510689778698417735603118111677563872589911516803236547002987989628986181014596471307916144369564690909518788574398821730583884980809523077569358851616027719521488998358632323127308909861560777386006984035267826785387215920936255817889813416247486456433211043194821421299793188104636399541496539441501383868748384870224681829391860319598667962363489309283087840712400431022706137591368056518861313458307990705003607588327248867879324093380071864152853317943535073401891193638546730000660453783784472469288830546979000131248952100446949032058838294923613919284305249167833012980192255157050378521810552961623637523647962685751660066539364142273063001648652613891842243501797455993616794063303522111829071597538821839777552812981538570168702202620274678647916644030729018445497956399844836807851997088201407769199261674991148329821854382718946282165387064858588646221611410343570342878862979083418871606214430014533275029715104673156021000043869510583773779766003460887624861640938645252177935289947578496255243925598620521409052346250847830487046492688313289470553891357290706967599556298586669559721686506052072801342104355762779184021797626656484580261591407173477009039475168017709900129391137881248534255949312866653465033728846390649968460644741907524313323903404908195233044389559060547854954620263256676813262435925020249516275607080900436460421497025691488555265022810327762115842282433269528629137662675481993546118143913367579700141255870143319434764035725376914388899683088262844616425575034001428982557620386364384137906519612917777354183694676232982904981261717676191554292570438432239918482261744350470199171258214687683172646078959690569981353264435973965173473319484798758064137926885413552523275720457329477215706850016950046959758389373527538622664943456437071610511521617176237598050900553232154896062817794302268640579555845730600598376482703339859420098582351400179507104569019191359062304102336798080907240196312675268916362136351032648077232914950859151265812143823371072949148088472355286394195993455684156344577951727033374238129903260198160571971183950662758220321837136059718025940870615534713104482272716848395524105913605919812444978458110854511231668173534838253724825347636777581712867205865148285317273569069839935110763432091319780314031658897379628301178409806410175016511072932907832177487566289310650383806093372841399226733384778203302020700517188941706465146238366720632742644336612174011766914919235570905644803016342294301837655263108450172510307540942604409687066288066265900569082451407632599158164499361455172452057020443093722305550217222299706209749268609762787409626448772056043078634808885709143464793241536214303199965695610753570417207285334250171325558818113295504095217830139465216436594262960768570585698507157151317262928960072587601564840556088613165411835958628710665496282599535127193244635791046554389165150954187306071015034430609582302257455974944275067630926322529966338219395202927917973247094559691016402983683080426309910481567503623509654924302589575273521412445149542462972258510120707802110188106722347972579330653187713438466713807546383471635428854957610942841898601794658721444495198801550804042506452191484989920400007310672369944655246020908767882300064337725657385010969899058191290957079866699453765080407917852438222041070599278889267745752084287526377986730360561230710723922581504781379172731261234878334034473833573601973235946604273704635201327182592410906040097638585857716958419563109577748529579836844756803121874818202833941887076311731615289811756429711334181497218078040465077657204457082859417475114926179367379999220181789399433337731146911970737861041963986422166045588965683206701337505745038872111332436739840284188639147633491695114032583475841514170325690161784931455706904169858050217798497637014758914810543205854914100662201721719726878930012101267481270235940855162601689425111458499658315589660460091525797881670384625905383256920520425791378948827579603278877535466861441826827797651258953563761485994485049706638406266121957141911063246061774180577212381659872472432252969098533628440799030007594546281549235506086481557928961969617060715201589825299772803520002610888814176506636216905928021516429198484077446143617891415191517976537848282687018750030264867608433204658525470555882410254654806040437372771834769014720664234434374255514129178503032471263418076525187802925534774001104853996960549926508093910691337614841834884596365621526610332239417467064368340504749943339802285610313083038484571294767389856293937641914407036507544622061186499127249643799875806537850203753189972618014404667793050140301580709266213229273649718653952866567538572115133606114457222800851183757899219543063413692302293139751143702404830227357629039911794499248480915071002444078482866598579406525539141041497342780203520135419925977628178182825372022920108186449448349255421793982723279357095828748597126780783134286180750497175747373730296280477376908932558914598141724852658299510882230055223242218586191394795184220131553319634363922684259164168669438122537135960710031743651959027712571604588486044820674410935215327906816032054215967959066411120187618531256710150212239401285668608469435937408158536481912528004920724042172170913983123118054043277015835629513656274610248827706488865037765175678806872498861657094846665770674577000207144332525555736557083150320019082992096545498737419756608619533492312940263904930982014700371161829485939931199955070455381196711289367735249958182011774799788636393286405807810818657337668157893827656450642917396685579555053188715314552353070355994740186225988149854660737787698781542360397080977412361518245964026869979609564523828584235953564615185448165799966460648261396618720304839119560250381111550938420209894591555760083897989949964566262540514195610780090298667014635238532066032574466820259430618801773091109212741138269148784355679352572808875543164693077235363768226036080174040660997151176880434927489197133087822951123746632635635328517394189466510943745768270782209928468034684157443127739811044186762032954475468077511126663685479944460934809992951875666499902261686019672053749149951226823637895865245462813439289338365156536992413109638102559114643923805213907862893561660998836479175633176725856523591069520326895990054884753424160586689820067483163174286329119633399132709086065074595260357157323069712106423424081597068328707624437165532750228797802598690981111226558888151520837482450034463046505984569690276166958278982913613535306291331427881888249342136442417833519319786543940201465328083410341785272489879050919932369270996567133507711905899945951923990615156165480300145359212550696405345263823452155999210578191371030188979206408883974767667144727314254467923500524618849237455307575734902707342496298879996942094595961008702501329453325358045689285707241207965919809225550560061971283541270202072583994171175520920820151096509526685113897577150810849443508285458749912943857563115668324566827992991861539009255871716840495663991959154034218364537212023678608655364745175654879318925644085274489190918193411667583563439758886046349413111875241038425467937999203546910411935443113219136068129657568583611774564654674861061988591414805799318725367531243470335482637527081353105570818049642498584646147973467599315946514787025065271083508782350656532331797738656666181652390017664988485456054961300215776115255813396184027067814900350252876823607822107397102339146870159735868589015297010347780503292154014359595298683404657471756232196640515401477953167461726208727304820634652469109953327375561090578378455945469160223687689641425960164689647106348074109928546482353083540132332924864037318003195202317476206537726163717445360549726690601711176761047774971666890152163838974311714180622222345718567941507299526201086205084783127474791909996889937275229053674785020500038630036526218800670926674104806027341997756660029427941090400064654281074454007616429525362460261476180471744322889953285828397762184600967669267581270302806519535452053173536808954589902180783145775891280203970053633193821100095443241244197949192916205234421346395653840781209416214835001155883618421164283992454027590719621537570187067083731012246141362048926555668109467076386536083015847614512581588569610030337081197058344452874666198891534664244887911940711423940115986970795745946337170243268484864632018986352827092313047089215684758207753034387689978702323438584381125011714013265769320554911860153519551654627941175593967947958810333935413289702528893533748106257875620364294270257512121137330213811951395756419122685155962476203282038726342066227347868223036522019655729325905068134849292299647248229359787842720945578267329975853818536442370617353517653060396801087899490506654491544577952166038552398013798104340564182403396162494910454712104839439200945914647542424785991096900046541371091630096785951563947332190934511838669964622788855817353221326876634958059123761251203010983867841195725887799206041260049865895027247133146763722204388398558347770112599424691208308595666787531942465131444389971195968105937957532155524204659410081418351120174196853432672343271868099625045432475688702055341969199545300952644398446384346598830418262932239295612610045884644244285011551557765935780379565026806130721758672048541797157896401554276881090475899564605488362989140226580026134158039480357971019004151547655018391755772677897148793477372747525743898158705040701968215101218826088040084551332795162841280679678965570163917067779841529149397403158167896865448841319046368332179115059107813898261026271979696826411179918656038993895418928488851750122504754778999508544083983800725431468842988412616042682248823097788556495765424017114510393927980290997604904428832198976751320535115230545666467143795931915272680278210241540629795828828466355623580986725638200565215519951793551069127710538552661926903526081367717666435071213453983711357500975854405939558661737828297120544693182260401670308530911657973113259516101749193468250063285777004686987177255226525708428745733039859744230639751837209975339055095883623642814493247460522424051972825153787541962759327436278819283740253185668545040893929401040561666867664402868211607294830305236465560955351079987185041352121321534713770667681396211443891632403235741573773787908838267618458756361026435182951815392455211729022985278518025598478407179607904114472041476091765804302984501746867981277584971731733287305281134969591668387877072315968334322509070204019030503595891994666652037530271923764252552910347950343816357721698115464329245608951158732012675424975710520894362639501382962152214033621065422821876739580121286442788547491928976959315766891987305176388698461503354594898541849550251690616888419122873385522699976822609645007504500096116866129171093180282355042553653997166054753907348915189650027442328981181709248273610863801576007240601649547082331349361582435128299050405405333992577071321011503713898695076713447940748097845416328110406350804863393555238405735580863718763530261867971725608155328716436111474875107033512913923595452951407437943144900950809932872153235195999616750297532475931909938012968640379783553559071355708369947311923538531051736669154087312467233440702525006918026747725078958903448856673081487299464807786497709361969389290891718228134002845552513917355978456150353144603409441211512001738697261466786933733154341007587514908295822756919350542184106448264951943804240543255345965248373785310657979037977505031436474651422484768831323479762673689855474944277949916560108528257618964374464656819789319422077536824661110427671936481836360534108748971066866318805026555929568123959680449295166615409802610781691689418764353363449482900125929366840591370059526914934421861891742142561071896846626335874414976973921566392767687720145153302241853125308442727245771161505550519076276250016522166274796257424425420546785767478190959486500575711016264847833741198041625940813327229905891486422127968042984725356237202887830051788539737909455265135144073130049869453403245984236934627060242579432563660640597549471239092372458126154582526667304702319359866523378856244229188278436440434628094888288712101968642736370461639297485616780079779959696843367730352483047478240669928277140069031660709951473154191919911453182543906294573298686613524886500574780251977607442660798300291573030523199052185718628543687577860915726925232573171665625274275808460620177046433101212443409281314659760221360416223031167750085960128475289259463348312408766740128170543067985261868949895004918275008304998926472034986965363326210919830621495095877228260815566702155693484634079776879525038204442326697479264829899016938511552124688935873289878336267819361764023681714606495185508780596635354698788205094762016350757090024201498400967867845405354130050482404996646978558002628931826518708714613909521454987992300431779500489569529280112698632533646737179519363094399609176354568799002814515169743717518330632232942199132137614506411391269837128970829395360832883050256072727563548374205497856659895469089938558918441085605111510354367477810778500572718180809661542709143010161515013086522842238721618109043183163796046431523184434669799904865336375319295967726080853457652274714047941973192220960296582500937408249714373040087376988068797038047223488825819819025644086847749767508999164153502160223967816357097637814023962825054332801828798160046910336602415904504637333597488119998663995617171089911809851197616486499233594328274275983382931099806461605360243604040848379619072542165869409486682092396143083817303621520642297839982533698027039931804024928814430649614747600087654305571672697259114631990688823893005380061568007730984416061355843701277573463708822073792921409548717956947854414951731561828176343929570234710460088230637509877521391223419548471196982303169544468045517922669260631327498272520906329003279972932906827204647650366969765227673645419031639887433042226322021325368176044169612053532174352764937901877252263626883107879345194133825996368795020985033021472307603375442346871647223795507794130304865403488955400210765171630884759704098331306109510294140865574071074640401937347718815339902047036749084359309086354777210564861918603858715882024476138160390378532660185842568914109194464566162667753712365992832481865739251429498555141512136758288423285957759412684479036912662015308418041737698963759002546999454131659341985624780714434977201991702665380714107259910648709897259362243300706760476097690456341576573395549588448948093604077155688747288451838106069038026528318275560395905381507241627615047252487759578650784894547389096573312763852962664517004459626327934637721151028545472312880039058405918498833810711366073657536918428084655898982349219315205257478363855266205400703561310260405145079325925798227406012199249391735122145336707913500607486561657301854049217477162051678486507913573336334257685988361252720250944019430674728667983441293018131344299088234006652915385763779110955708000600143579956351811596764725075668367726052352939773016348235753572874236648294604770429166438403558846422370760111774821079625901180265548868995181239470625954254584491340203400196442965370643088660925268811549596291166168612036195319253262662271108142149856132646467211954801142455133946382385908540917878668826947602781853283155445565265933912487885639504644196022475186011405239187543742526581685003052301877096152411653980646785444273124462179491306502631062903402737260479940181929954454297256377507172705659271779285537195547433852182309492703218343678206382655341157162788603990157495208065443409462446634653253581574814022471260618973060860559065082163068709634119751925774318683671722139063093061019303182326666420628155129647685313861018672921889347039342072245556791239578260248978371473556820782675452142687314252252601795889759116238720807580527221031327444754083319215135934526961397220564699247718289310588394769170851420631557192703636345039529604362885088555160008371973526383838996789184600327073682083234847108471706160879195227388252347506380811606090840124222431476103563328940609282430125462013806032608121942876847907192546246309055749298781661271916548229644317263587524548607563020667656942355342774617635549231817456159185668061686428714964129290560130053913469569829490891003991259088290348791943368696942620662946948514931472688923571615032405542263391673583102728579723061998175868700492227418629077079508809336215346303842967525604369606110193842723883107587771653594778681499030978765900869583480043137176832954871752604714113064847270887246697164585218774442100900090916189819413456305028950484575822161887397443918833085509908566008543102796375247476265353031558684515120283396640547496946343986288291957510384781539068343717740714095628337554413567955424664601335663617305811711646062717854078898495334329100315985673932305693426085376230981047171826940937686754301837015557540822371538037838383342702379535934403549452173960327095407712107332936507766465603712364707109272580867897181182493799540477008369348889220963814281561595610931815183701135104790176383595168144627670903450457460997444500166918675661035889313483800512736411157304599205955471122443903196476642761038164285918037488354360663299436899730090925177601162043761411616688128178292382311221745850238080733727204908880095181889576314103157447684338100457385008523652069340710078955916549813037292944462306371284357984809871964143085146878525033128989319500645722582281175483887671061073178169281242483613796475692482076321356427357261609825142445262515952514875273805633150964052552659776922077806644338105562443538136258941809788015677378951310313157361136026047890761945591820289365770116416881703644242694283057457471567494391573593353763114830246668754727566653059819746822346578699972291792416156043557665183382167059157867799311835820189855730344883681934418305987021880502259192818047775223884407167894780414701414651073580452021499197980812095692195622632313741870979731320870864552236740416185590793816745658234353037283309503729022429802768451559528656923189798000383061378732434546500582722712325031420712488100290697226311129067629080951145758060270806092801504406139446350643069742785469477459876821004441453438033759717384777232052065301037861326418823586036569054773343070911759152582503029410738914441818378779490613137536794654893375260322906277631983337976816641721083140551864133302224787118511817036598365960493964571491686005656771360533192423185262166760222073368844844409234470948568027905894191829969467724456269443308241243846160408284006424867072583661011433404214473683453638496544701067827313169538435919120440283949541956874453676459875488726170687163109591315801609722382049772577307454562979127906177531663252857205858766376754282917933549923678212008601904369428956102301731743150352204665675088491593025926618816581008701658499456495586855628208747248318351516339189292646558880593601275151838235485893426165223086697314511412035659916934103076974774451947043836739600076578628245472064617380804602903639144493859012422380173377038154675297645596518492676039300171943042511794045679862114630138402371099347243455794730048929825402680821621522346560274258486595687074510352794291633405915025075992398611224340312056999780516223878772230396359709132856830486160362127579561601328561866388146004722200580017580282279272167842720649966956840905752590774886105493806116954293569077377792821084159737469613143291808510446953973485067590503662391722108732333169909603363771705474725026941732982890400239372879549386540463828596742216318201530139629734398479588628632934746650690284066719018081265539973675916799759010867483920062877888531102781695087545740384607594616919584610655963327283485609570305572502494416337066573150237126843581984154103154401008430380631442183776750349813408169325201240813452285974626715177152223063741359255747513535160669108359443999692315898156732033027129284241219651936303734407981204656795322986357374589031654007016472204989445629050395873788912680565516464274460174738175296313458739390484560414203426465560422112239134631023161290836446988901247285192778589195228773637440432659264672239982186452797664826673070168802722052338600372842903155828454593854349099449420750911108532138744823216151007808922516285123275724355101999038195993350032641446053470357293073912578481757987468353429629749652545426864234949270336399427519354240001973125098882419600095766257217621860474573769577649582201796258392376391717855799468922496750179251915218219624653575570564228220399546682648329822996167217080156801080799777126517156274295763666959661983507435667132218383358509536665806605597148376773866922551603463644386269977295750658468929599809168949981898588529537874489519527097766262684177088590284321676352132630838812766335363319004134332844347630067982023716933653652880580156390360562722752187272454764258840995216482554453662083811789117725225682611478014242896970967121967502094421226279437073328703410646312100557376727450271638975234111426287828736758358819056742163061523416789476056879277154789714326222041069587947186435439940738639948986836168919377836648327137363654676901173760246643082285362494712605173293777247276797635865806019396287718060679122426813922872134061694882029506831654589707623668302556167559477498715183426989208952182644710514911419441192277010977616645850068963849426165593473112961064282379048216056210094265076173838082479030510998790719611852832556787472942907151041468948104916751035295897242381802288151276582257190705537652455285511598636421244284176256230139538669970308943645907600684938040875210854159851278070333207779865635907968462191534944587677170063778573171211036517486371634098385626541555573292664616402279791195975248525300376741774056125700303625811704838385391207273191845064713669122576415213769896260940351804147432053600369234179035440735703058314741623452840188940808983125191307741823338981880316339159565954543405777784331681162551898060409183018907512170192983622897099598983405484962284289398469847938668614293324543983592637036699355184231661615244505980576745765335552338715678211466689996845227042954589710922163652573965950289645637766038988037941517917867910675199009966139206238732318786758420544279396366759104126821843375015743069045967947046685602358283919759975285865384338189120042853787549302768972168199113340697282255535300044743958830079799736518459131437946494086272149669719100359399974735262764126125995350902609540048669398955899487421379590802893196914845826873123710180229775301190684280440780938156598081694611679374425663244656799606363751546304833112722231812338371779800439731087402647536582575657351059978314264831879619843765495877803685261751835391844920488198629786329743136948511780579298636452193232481339393090754566368038513630619718033957979522539508697432546502659123585049283028832934489284591373621624852528877442891851104093746333590660233239711922814450735588373324057814862662207486215513375036775585494138678352928273109003823116855374520901095101174796663003330352534143230024288248051396631446632656081582045216883922312025671065388459503224002320453633895521539919011035217362720909565500846486605368975498478995875596103167696587161281951919668893326641203784750417081752273735270989343717167642329956935697166213782736138899530515711822960896394055380431939398453970864418654291655853168697537052760701061488025700785387150835779480952313152747735711713643356413242974208137266896149109564214803567792270566625834289773407718710649866150447478726164249976671481383053947984958938064202886667951943482750168192023591633247099185942520392818083953020434979919361853380201407072481627304313418985942503858404365993281651941497377286729589582881907490040331593436076189609669494800067194371424058105327517721952474344983414191979918179909864631583246021516575531754156198940698289315745851842783390581029411600498699307751428513021286202539508732388779357409781288187000829944831476678183644656510024467827445695591845768068704978044824105799710771577579093525803824227377612436908709875189149049904225568041463131309240101049368241449253427992201346380538342369643767428862595140146178201810734100565466708236854312816339049676558789901487477972479202502227218169405159042170892104287552188658308608452708423928652597536146290037780167001654671681605343292907573031466562485809639550080023347676187068086526878722783177420214068980703410506200235273632267291964034093571225623659496432076928058165514428643204955256838543079254299909353199329432966018220787933122323225928276556048763399988478426451731890365879756498207607478270258861409976050788036706732268192473513646356758611212953074644777149423343867876705824452296605797007134458987594126654609414211447540007211790607458330686866231309155780005966522736183536340439991445294960728379007338249976020630448806064574892740547730693971337007962746135534442514745423654662752252624869916077111131569725392943756732215758704952417232428206555322808868670153681482911738542735797154157943689491063759749151524510096986573825654899585216747260540468342338610760823605782941948009334370046866568258579827323875158302566720152604684361412652956519894291184887986819088277339147282063794512260294515707367105637720023427811802621502691790400488001808901847311751199425460594416773315777951735444490965752131026306836047140331442314298077895617051256930051804287472368435536402764392777908638966566390166776625678575354239947427919442544664643315554138265543388487778859972063679660692327601733858843763144148113561693030468420017434061395220072403658812798249143261731617813894970955038369479594617979829257740992171922783223006387384996138434398468502234780438733784470928703890536420557474836284616809363650973790900204118525835525201575239280826462555785658190226958376345342663420946214426672453987171047721482128157607275305173330963455909323664528978019175132987747952929099598069790148515839540444283988381797511245355548426126784217797728268989735007954505834273726937288386902125284843370917479603207479554080911491866208687184899550445210616155437083299502854903659617362726552868081324793106686855857401668022408227992433394360936223390321499357262507480617409173636062365464458476384647869520547719533384203403990244761056010612777546471464177412625548519830144627405538601855708359981544891286863480720710061787059669365218674805943569985859699554089329219507269337550235821561424994538234781138316591662683103065194730233419384164076823699357668723462219641322516076261161976034708844046473083172682611277723613381938490606534404043904909864126903479263503943531836741051762565704797064478004684323069430241749029731181951132935746854550484711078742905499870600373983113761544808189067620753424526993443755719446665453524088287267537759197074526286322840219629557247932987132852479994638938924943286917770190128914220188747760484939855471168524810559991574441551507431214406120333762869533792439547155394213121021954430556748370425907553004950664994802614794524739012802842646689229455664958621308118913500279654910344806150170407268010067948926855360944990373928383520627992820181576427054962997401900837493444950600754365525758905546552402103412862124809003162941975876195941956592556732874237856112669741771367104424821916671499611728903944393665340294226514575682907490402153401026923964977275904729573320027982816062130523130658731513076913832317193626664465502290735017347656293033318520949298475227462534564256702254695786484819977513326393221579478212493307051107367474918016345667888810782101151826314878755138027101379868751299375133303843885631415175908928986956197561123025310875057188962535763225834275763348421016668109884514141469311719314272028007223449941999003964948245457520704922091620614222912795322688239046498239081592961111003756999529251250673688233852648213896986384052437049402152187547825163347082430303521036927849762517317825860862215614519165573478940019558704784741658847364803865995119651409542615026615147651220820245816010801218275982577477652393859159165067449846149161165153821266726927461290533753163055654440793427876550267301214578324885948736899073512166118397877342715872870912311383472485146035661382188014840560716074652441118841800734067898587159273982452147328317214621907330492060817440914125388918087968538960627860118193099489240811702350413554126823863744341209267781729790694714759018264824761112414556423937732224538665992861551475342773370683344173073150805440138894084087253197595538897613986400165639906934600670780501058567196636796167140097031535132386972899001749862948883362389858632127176571330142071330179992326381982094042993377790345261665892577931395405145369730429462079488033141099249907113241694504241391265397274078984953073730364134893688060340009640631540701820289244667315059736321311926231179142794944897281477264038321021720718017561601025111179022163703476297572233435788863537030535008357679180120653016668316780269873860755423748298548246360981608957670421903145684942967286646362305101773132268579232832164818921732941553151386988781837232271364011755881332524294135348699384658137175857614330952147617551708342432434174779579226338663454959438736807839569911987059388085500837507984051126658973018149321061950769007587519836861526164087252594820126991923916722273718430385263107266000047367872474915828601694439920041571102706081507270147619679971490141639274282889578424398001497985658130305740620028554097382687819891158955487586486645709231721825870342960508203415938806006561845735081804032347750084214100574577342802985404049555529215986404933246481040773076611691605586804857302606467764258503301836174306413323887707999698641372275526317649662882467901094531117120243890323410259937511584651917675138077575448307953064925086002835629697045016137935696266759775923436166369375035368699454550392874449940328328128905560530091416446608691247256021455381248285307613556149618444364923014290938289373215312818797541139219415606631622784836152140668972661027123715779503062132916001988806369127647416567067485490795342762338253943990022498972883660263920518704790601584084302914787302246651371144395418253441269003331181914268070735159284180415100555199146564934872796969351992963117195821262627236458009708099166752820365818699111948365866102758375863322993225541477479210421324166848264953111826527351008031659958888814809945737293785681411438021523876706455063233067233939551964260397443829874822322662036352861302543796600943104500158604854027036789711934695579989189112302233381602302236277726084846296189550730850698061500281436425336666311433321645213882557346329366870956708432252564333895997812402164189946978348320376011613913855499933990786652305860332060641949298931012423081105800169745975038516887112037747631577311831360002742502722451570906304496369230938382329175076469684003556425503797106891999812319602533733677437970687713814747552190142928586781724044248049323750330957002929126630316970587409214456472022710796484778657310660832173093768033821742156446602190335203981531618935787083561603302255162155107179460621892674335641960083663483835896703409115513087820138723494714321400450513941428998350576038799343355677628023346565854351219361896876831439866735726040869511136649881229957801618882834124004126142251475184552502502640896823664946401177803776799157180146386554733265278569418005501363433953502870836220605121839418516239153709790768084909674194289061134979961034672077354959593868862427986411437928435620575955500144308051267664432183688321434583708549082240014585748228606859593502657405750939203135881722442164955416889785558265198046245527898343289578416968890756237467281044803018524217706136533236073856228166664597654076844715963930782091017090763377917711485205493367936868430832404126789220929930411890501756484917499452393770674524578019171841679541825554377930299249277892416277257788147974770446005423669346157135208417428211847353652367573702352791459837645712257646122605628127852169580892808988394594406165340521932514843306105322700231133680378433377389724881307874325614952744243584753011150345103737688223837573804282007358586938044331529253129961025096113761670187568525921208929131354473196308440066835155160913925692912175784379179004808848023029304392630921342768601226558630456913133560978156776098711809238440656353136182676923761613389237802972720736243967239854144480757286813436768000573823963610796223140429490728058551444771338682314499547929338131259971996894072233847404542592316639781608209399269744676323921370773991899853301483814622364299493902073285072098040905300059160091641710175605409814301906444379905831277826625762288108104414704097708248077905168225857235732665234414956169007985520848841886027352780861218049418060017941147110410688703738674378147161236141950474056521041002268987858525470689031657094677131822113205505046579701869337769278257145248837213394613987859786320048011792814546859096532616616068403160077901584946840224344163938313618742275417712170336151163782359059685168880561304838542087505126933144171705880517278127917564053282929427357971823360842784676292324980318169828654166132873909074116734612367109059236155113860447246378721244612580406931724769152219217409096880209008801535633471775664392125733993165330324425899852598966724744126503608416484160724482125980550754851232313331300621490042708542735985913041306918279258584509440150719217604794274047740253314305451367710311947544521321732225875550489799267468541529538871443696399406391099267018219539890685186755868574434469213792094590683677929528246795437302263472495359466300235998990248299853826140395410812427393530207575128774273992824866921285637240069184859771126480352376025469714309316636539718514623865421671429236191647402172547787238964043145364190541101514371773797752463632741619269990461595895793940622986041489302535678633503526382069821487003578061101552210224486633247184367035502326672749787730470216165019711937442505629639916559369593557640005236360445141148916155147776301876302136068825296274460238077523189646894043033182148655637014692476427395401909403584437251915352134557610698046469739424511797999048754951422010043090235713636892619493763602673645872492900162675597083797995647487354531686531900176427222751039446099641439322672532108666047912598938351926694497553568096931962642014042788365702610390456105151611792018698900673027082384103280213487456720062839744828713298223957579105420819286308176631987048287388639069922461848323992902685392499812367091421613488781501234093387999776097433615750910992585468475923085725368613605356762146929424264323906626708602846163376051573599050869800314239735368928435294958099434465414316189806451480849292695749412903363373410480943579407321266012450796613789442208485840536446021616517885568969302685188950832476793300404851688934411125834396590422211152736276278672366665845757559585409486248261694480201791748223085835007862255216359325125768382924978090431102048708975715033330963651576804501966025215527080352103848176167004443740572131294252820989545456276344353575741673638980108310579931697917916718271145837435222026387771805250290791645414791173616253155840768495583288190293564201219633684854080865928095131505012602919562576032932512847250469881908146475324342363863860247943921015193235101390117789997483527186469346024554247028375300033725403910085997650987642832802908445662021678362267272292737780213652404028817217012490974899454430826861772239385250883760749742195942655217301733355851389407457348144161511380845358039740277795072051893487170722955427683655826706766313911972211811528466502223383490906676554168336907959409404576472940901354356409277969379842065738891481990225399022315913388145851487225126560927576795873759207013915029216513720851137197522734365458411622066281660256333632074449918511469174455062297146086578736313585389023662557285424516018080487167823688885575325066254262367702604215835160174851981885460860036597606743233346410471991027562358645341748631726556391320606407754779439671383653877377610828300019937359760370467245737880967939894493795829602910746901609451288456550071458091887879542641820145369659962842686882363495879277007025298960996798975941955735253914237782443302746708282008722602053415292735847582937522487377937899136764642153727843553986244015856488692101644781661602962113570056638347990334049623875941092886778920270077504951511405782565295015024484968204744379710872943108541684540513016310902267112951959140520827546866418137305837933236150599142045255880213558474751516267815309465541240524091663857551298894834797423322854504140527354235070335984964593699534959698554244978249586929179182415068053002553370412778703476446244329205906832901886692400222391918714603175399666877477960121790688623311002908668305431787009355066944389131913333586368037447530664502418437136030852288582121720231274167009740351431532131803978033680228154223490183737494117973254478594157962104378787072154814091725163615415163381388912588517924237727229603497305533840942889918919161186249580560073570527227874940321250645426206304469470804277945973817146810395192821550688079136701210109944220737024613687196031491162370967939354636396448139025711768057799751751298979667073292674886430097398814873780767363792886767781170520534367705731566895899181530825761606591843760505051704242093231358724816618683821026679970982966436224723644898648976857100173643547336955619347638598187756855912376232580849341570570863450733443976604780386678461711520325115528237161469200634713570383377229877321365028868868859434051205798386937002783312365427450532283462669786446920780944052138528653384627970748017872477988461146015077617116261800781557915472305214759943058006652042710117125674185860274188801377931279938153727692612114066810156521441903567333926116697140453812010040811760123270513163743154487571768761575554916236601762880220601068655524141619314312671535587154866747899398685510873576261006923021359580838145290642217792987748784161516349497309700794368305080955621264592795333690631936594413261117944256602433064619312002953123619348034504503004315096798588111896950537335671086336886944665564112662287921812114121425167348136472449021275252555647623248505638391391630760976364990288930588053406631352470996993362568102360392264043588787550723319888417590521211390376609272658409023873553418516426444865247805763826160023858280693148922231457758783791564902227590699346481624734399733206013058796068136378152964615963260698744961105368384203105364183675373594176373955988088591188920114871545460924735613515979992999722298041707112256996310945945097765566409972722824015293663094891067963296735505830412258608050740410916678539569261234499102819759563955711753011823480304181029089719655278245770283085321733741593938595853203645590564229716679900322284081259569032886928291260139267587858284765599075828016611120063145411315144108875767081854894287737618991537664505164279985451077400771946398046265077776614053524831090497899859510873112620613018757108643735744708366215377470972660188656210681516328000908086198554303597948479869789466434027029290899143432223920333487108261968698934611177160561910681226015874410833093070377506876977485840324132474643763087889666151972556180371472590029550718424245405129246729039791532535999005557334600111693557020225722442772950263840538309433999383388018839553821540371447394465152512354603526742382254148328248990134023054550811390236768038649723899924257800315803725555410178461863478690646045865826036072306952576113184134225274786464852363324759102670562466350802553058142201552282050989197818420425028259521880098846231828512448393059455162005455907776121981297954040150653985341579053629101777939776957892084510979265382905626736402636703151957650493344879513766262192237185642999150828898080904189181015450813145034385734032579549707819385285699926238835221520814478940626889936085239827537174490903769904145555260249190126341431327373827075950390882531223536876389814182564965563294518709637484074360669912550026080424160562533591856230955376566866124027875883101021495284600804805028045254063691285010599912421270508133194975917146762267305044225075915290251742774636494555052325186322411388406191257012917881384181566918237215400893603475101448554254698937834239606460813666829750019379115061709452680984785152862123171377897417492087541064556959508967969794980679770961683057941674310519254486327358885118436597143583348756027405400165571178309126113117314169066606067613797690123141099672013123730329707678988740099317309687380126740538923612230370779727025191340850390101739924877352408881040807749924412635346413181858792480760553268122881584307471326768283097203149049868884456187976015468233715478415429742230166504759393312132256510189175368566338139736836336126010908419590215582111816677413843969205870515074254852744810154541079359513596653630049188769523677579147319184225806802539818418929888943038224766186405856591859943091324575886587044653095332668532261321209825839180538360814144791320319699276037194760191286674308615217243049852806380129834255379486287824758850820609389214668693729881191560115633701248675404205911464930888219050248857645752083363921499441937170268576222251074166230901665867067714568862793343153513505688216165112807318529333124070912343832502302341169501745502360505475824093175657701604884577017762183184615567978427541088499501610912720817913532406784267161792013428902861583277304794830971705537485109380418091491750245433432217445924133037928381694330975012918544596923388733288616144238100112755828623259628572648121538348900698511503485369544461542161283241700533583180520082915722904696365553178152398468725451306350506984981006205514844020769539324155096762680887603572463913955278222246439122592651921288446961107463586148252820017348957533954255019475442643148903233373926763409115527189768429887783617346613535388507656327107814312435018965109238453660236940276060642119384227665755210663671879603217527184404651560427289869560206997012906367847161654793068868305846508082886614111979138822898112498261434559408961813509226857611474609406147937240008842153535862052780125014270055274468359151840373309373580494342483940467505708347927948338133276237937844629209323999417593374917899786484958148818865149169302451512835579818112344900827168644548306546633975256079615935830821400021951611342337058359111545217293721664061708131602078213341260356852013161345136871600980378712556766143923146458085652084039744217352744813741215277475202259244561520365608268890193913957991844109971588312780020898275935898106482117936157951837937026741451400902833064466209280549839169261068975151083963132117128513257434964510681479694782619701483204392206140109523453209269311762298139422044308117317394338867965739135764377642819353621467837436136161591167926578700137748127848510041447845416464568496606699139509524527949914769441031612575776863713634644477006787131066832417871556281779122339077841275184193161188155887229676749605752053192594847679397486414128879475647133049543555044790277128690095643357913405127375570391806822344718167939329121448449553897728696601037841520390662890781218240141299368590465146519209198605347788576842696538459445700169758422531241268031418456268722581132040056433413524302102739213788415250475704533878002467378571470021087314693254557923134757243640544448132093266582986850659125571745568328831440322798049274104403921761438405750750288608423536966715191668510428001748971774811216784160854454400190449242294333666338347684438072624307319019363571067447363413698467328522605570126450123348367412135721830146848071241856625742852208909104583727386227300781566668914250733456373259567253354316171586533339843321723688126003809020585719930855573100508771533737446465211874481748868710652311198691114058503492239156755462142467550498676710264926176510110766876596258810039163948397811986615585196216487695936398904500383258041054420595482859955239065758108017936807080830518996468540836412752905182813744878769639548306385089756146421874889271294890398025623046812175145502330254086076115859321603465240763923593699949180470780496764486889980902123735780457040380820770357387588525976042434608851075199334470112741787878845674656640471901619633546770714090590826954225196409446319547658653032104723804625249971910690110456227579220926904132753699634145768795242244563973018311291451151322757841320376225862458224784696669785947914981610522628786944136373683125108310682898766123782697506343047263278453719024447970975017396831214493357290791648779915089163278018852504558488782722376705263811803792477835540018117452957747339714012352011459901984753358434861297092928529424139865507522507808919352104173963493428604871342370429572757862549365917805401652536330410692033704691093097588782938291296447890613200063096560747882082122140978472301680600835812336957051454650181292694364578357815608503303392466039553797630836137289498678842851139853615593352782103740733076818433040893624460576706096188294529171362940967592507631348636606011346115980434147450705511490716640635688739020690279453438236930531133440901381392849163507484449076828386687476663619303412376248380175840467851210698290605196112357188811150723607303158506622574566366740720668999061320627793994112805759798332878792144188725498543014546662945079670707688135022230580562225942983096887732856788971494623888272184647618153045844390967248232348259587963698908456664795754200195991919240707615823002328977439748112690476546256873684352229063217889227643289360535947903046811114130586348244566489159211382258867880972564351646404364328416076247766114349880319792230537889671148058968061594279189647401954989466232962162567264739015818692956765601444248501821713300527995551312539849919933907083138030214072556753022600033565715934283182650908979350869698950542635843046765145668997627989606295925119763672907762567862769469947280606094290314917493590511523235698715397127866718077578671910380368991445381484562682604003456798248689847811138328054940490519768008320299631757043011485087384048591850157264392187414592464617404735275250506783992273121600117160338604710710015235631159734711153198198710616109850375758965576728904060387168114313084172893710817412764581206119054145955378853200366615264923610030157044627231777788649806700723598889528747481372190175074700005571108178930354895017924552067329003818814068686247959272205591627902292600592107710510448103392878991286820705448979977319695574374529708195463942431669050083984398993036790655541596099324867822475424361758944371791403787168166189093900243862038610001362193667280872414291108080291896093127526202667881902085595708111853836166128848729527875143202956393295910508349687029060692838441522579419764824996318479414814660898281725690484184326061946254276693688953540732363428302189694947766126078346328490315128061501009539164530614554234923393806214007779256337619373052025699319099789404390847443596972052065999017828537676265683558625452697455260991024576619614037537859594506363227095122489241931813728141668427013096050734578659047904243852086508154491350136491698639048125666610843702294730266721499164849610746803261583352580352858275799038584091667618877199539888680431991650866887781701439663176815592262016991396613153738021294160006906947533431677802632207226265881842757216055461439677336258462997385077307751473833315101468395296411397329672457933540390136107395245686243008096720460995545708974893048753897955544443791303790422346037768729236001386569593952300768091377768847789746299699489949016141866131552200856673695770822720338936659590666350594330040363762591189195691561626122704788696510356062748423100605472091437069471661080277379848576543481249822444235828329813543645124092220896643987201997945619030397327254617823136363375927622656301565813545578319730419339269008282952718252138855126583037630477490625995514925943105307478901043009876580816508144862607975129633326675259272351611791836777128931053144471668835182920514343609292493191180249366051791485330421043899773019267686085347768149502299280938065840007311767895491286098112311307002535600347898600653805084532572431553654422067661352337408211307834360326940015926958459588297845649462271300855594293344520727007718206398887404742186697709349647758173683580193168322111365547392288184271373843690526638607662451284299368435082612881367358536293873792369928837047900484722240370919885912556341130849457067599032002751632513926694249485692320904596897775676762684224768120033279577059394613185252356456291805905295974791266162882381429824622654141067246487216174351317397697122228010100668178786776119825961537643641828573481088089988571570279722274734750248439022607880448075724807701621064670166965100202654371260046641935546165838945950143502160890185703558173661823437491622669077311800121188299737319891006060966841193266075165452741829459541189277264192546108246351931647783837078295218389645376236304858042774417907169146356546201215125418664885396161542055152375000426794253417764590821513675258479774465114750438460596325820468809667795709044645884673847481638045635188183210386594798204376334738389017759714236223057776395541011294523488098341476645559342209402059733452337956309441446698222457026367119493286653989491344225517746402732596722993581333110831711807234044326813737231209669052411856734897392234152750707954137453460386506786693396236535556479102508529284294227710593056660625152290924148057080971159783458351173168204129645967070633303569271821496292272073250126955216172649821895790908865085382490848904421755530946832055636316431893917626269931034289485184392539670922412565933079102365485294162132200251193795272480340133135247014182195618419055761030190199521647459734401211601239235679307823190770288415814605647291481745105388060109787505925537152356112290181284710137917215124667428500061818271276125025241876177485994084521492727902567005925854431027704636911098800554312457229683836980470864041706010966962231877065395275783874454229129966623016408054769705821417128636329650130416501278156397799631957412627634011130135082721772287129164002237230234809031485343677016544959380750634285293053131127965945266651960426350406454862543383772209428482543536823186182982713182489884498260285705690699045790998144649193654563259496570044689011049923939218088155626191834404362264965506449848521612498442375928443642612004256628602157801140467879662339228190804577624109076487087406157070486658398144845855803277997327929143195789110373530019873110486895656281917362036703039179710646309906285483702836118486672219457621775034511770110458001291255925462680537427727378863726783016568351092332280649908459179620305691566806180826586923920561895421631986004793961133953226395999749526798801074576466538377400437463695133685671362553184054638475191646737948743270916620098057717103475575333102702706317395612448413745782734376330101853438497450236265733191742446567787499665000938706441886733491099877926005340862442833450486907338279348425305698737469497333364267191968992849534561045719338665222471536681145666596959735075972188416698767321649331898967182978657974612216573922404856900225324160367805329990925438960169901664189038843548375648056012628830409421321300206164540821986138099462721214327234457806819925823202851398237118926541234460723597174777907172041523181575194793527456442984630888846385381068621715274531612303165705848974316209831401326306699896632888532682145204083110738032052784669279984003137878996525635126885368435559620598057278951754498694219326972133205286374577983487319388899574634252048213337552584571056619586932031563299451502519194559691231437579991138301656117185508816658756751184338145761060365142858427872190232598107834593970738225147111878311540875777560020664124562293239116606733386480367086953749244898068000217666674827426925968686433731916548717750106343608307376281613984107392410037196754833838054369880310983922140260514297591221159148505938770679068701351029862207502287721123345624421024715163941251258954337788492834236361124473822814504596821452253550035968325337489186278678359443979041598043992124889848660795045011701169092519383155609441705397900600291315024253848282782826223304151370929502192196508374714697845805550615914539506437316401173317807741497557116733034632008408954066541694665746735785483133770133628948904397670025863002540635264006601631712883920305576358989492412827022489373848906764385339931878608019223108328847459816417701264089078551777830131616162049792779670521847212730327970738223860581986744668610994383049960437407323195784473254857416239738852016202384784256163512597161783106850156299135559874758848151014815490937380933394074455700842090155903853444962128368313687375166780513082594599771257467939781491953642874321122421579851584491669362551569370916855252644720786527971466476760328471332985501945689772758983450586004316822658631176606237201721007922216410188299330808409384014213759697185976897042759041500946595252763487628135867117352364964121058854934496645898651826545634382851159137631569519895230262881794959971545221250667461174394884433312659432286710965281109501693028351496524082850120190831078678067061851145740970787563117610746428835593915985421673115153096948758378955979586132649569817205284291038172721213138681565524428109871168862743968021885581515367531218374119972919471325465199144188500672036481975944167950887487934416759598361960010994838744709079104099785974656112459851972157558134628546189728615020774374529539536929655449012953097288963767713353842429715394179547179095580120134210175150931491664699052366350233024087218654727629639065723341455005903913890253699317155917179823065162679744711857951506573868504088229934804445549850597823297898617029498418376255258757455303112991914341109413088238114443068843062655305601658801408561023324210300218460588586954418502977463085858496130037238190325162225570729975710727306066072916922978033647048840958711228045188511908718588299514331534128549297173849768523136276076868494780364948299904475715771141080958058141208956059471668626290036145602625334863284986816039463372436667112964460292915746181117789169695839947080954788863503281129626899231110099889317815313946681882028368363373822281414974006917942192888817139116283910295684918233358930813360131488748366464224381776081007739183393749346933644748150564933649323157235306109385796839902153381449126925350768211098738352197507736653475499431740580563099143218212547336281359488317681489194306530426029773885492974570569448783077945878865062970895499843760181694031056909587141386804846359853684034105948341788438963179956468815791937174656705047441528027712541569401365862097760735632832966564135817028088013546326104892768731829917950379944446328158595181380144716817284996793061814177131912099236282922612543236071226270324572637946863533391758737446552006008819975294017572421299723542069630427857950608911113416534893431149175314953530067419744979017235181671568754163484949491289001739377451431928382431183263265079530371177806185851153508809998200482761808307209649636476943066172549186143700971387567940218696710148540307471561091358933165600167252126542502898612259306484105898847129649230941215144563947889999327145875969555737090855150648002321476443037232466147111552578583071024936898814562568786834745518893385181791667579054210421036349316257870476543126790661216644142285017446278477132740595579600648343288827864837043456066966456899746910373987712891593313271266247505582258634928427718355831641593667712218537642376222104779338956378722902509543014182257180331300148113377736941508488867501893156994849838936052666818012783912005801431596441910546663236810148207799356523056490420711364192200177189107935243234322761787712568251126481332974354926568682748715986654943041648468220593921673359485057849622807932422649812705271398407720995707236227009245067665680069149966555737866411877079767754867028786431817941521796178310655030287157272282250812017060713380339641841211253856248920130010782462165136989511064611133562443838185366273563783436921279354709230119655914915800561707258518503167289370411936374780625824298250726464801821523430268081486978164824349353456855843696378384153838051184406043696871666416514036129729992912630842812149152469877429332305214999981829046119471676727503742221367186614654042534463141660649871499001000660041544868437352208483059495953182872280520828676300361091734508632133033647289584176588755345227938480297724485711815574893561311524926772006362198369980664159549388683836411891430443767715498026544959061738265591178545999378510861446014967645550103653971251138583505085112442517772923814396233043724036032603181442991365750246012787514117944901305803452199992701148071712847770301254994886841867572975189214295652512486943983729047410363121899124217339550688778643130750024823361832738729697376598820053895902935486054979802320400472236873557411858132734337978931582039412878989728973298812553514507641535360519462112217000676321611195841029252568536561813138784086477147099724553013170761712163186600291464501378587854802096244703771373587720086738054108140042311418525803293267396324596914044834665722042880679280616029884043400536534009706581694636096660911110968789751801325224478246957913251892122653056085866541115373584912790254654369020869419871125588453729063224423222287139122012248769976837147645598526739225904997885514250047585260297929306159913444898341973583316070107516452301310796620382579278533125161760789984630103493496981494261055367836366022561213767081421091373531780682420175737470287189310207606953355721704357535177461573524838432101571399813798596607129664438314791296359275429627129436142685922138993054980645399144588692472767598544271527788443836760149912897358259961869729756588978741082189422337344547375227693199222635973520722998387368484349176841191020246627479579564349615012657433845758638834735832242535328142047826934473129971189346354502994681747128179298167439644524956655532311649920677163664580318205849626132234652606175413532444702007661807418914040158148560001030119994109595492321434406067634769713089513389171050503856336503545166431774489640061738861761193622676890576955693918707703942304940038440622614449572516631017080642923345170422426679607075404028551182398361531383751432493056398381877995594942545196756559181968690885283434886050828529642437578712929439366177362830136595872723080969468398938676366226456791132977469812675226595621009318322081754694778878755356188335083870248295346078597023609865656376722755704495258739871812593441903785275571333409842450127258596692434317689018966145404453679047136294238156127656824247864736176671770647002431119711090007474065945650315375044177982192306323700872039212085499569681061379189029961178936752146022386905665481382858280449537530160921422195940638787074787991194920898374091788534417523064715030278397979864517336625329511775105559014160459873338186887977858817291976604516353353556047648420520888811722831990044504284486852338334530105533929637308039738230604714104525470094899407601215247602819963846343554852932377161410869591950786873276075400085220065031871239272857835807010762542769655355964789450166013816295177908531139811092831583216931563867459747449584385282701658246192092219529134323496779345585613140207765996142546463288677356891785576835169608392864188830094883324700447958316931533832382377876344426323456301679513671047510469669001217777128065522453689371871451567394733440447280450959433090683667110655953338602938000999949010642769859623260401863733572846679531229683156358145420890540651226419162015504500430562136991850941034609601030543816694795964585804425194905110733387679946734471718615647723811737035654917628707589456035519195603962301157866323750234725054461073979402475184415558178087962822231972692984516683306919505079993357259165675557294585962182052650473353712351623662770479333289322136141858785972771685682725303734836891911847197133753088446777943274857148827821608844765700041403499921376794209627560883081509438030705666022764678117533361028187800710219794428777313146387857817205661409023041499923248268982477222109852189758140879763486146763606368674611966620347304608917277240045953051376938375381543486981101990651706961774052218247422657652138152740612699012706880875386408669901461740890540981877671880076124151967064152117653084325544261017536348281196837493395825742541244634247233586360777980960199745187758845459645895956779558869098404768259253477849930457883128541747079059795909431627722327844578918694214929451540174214623240300841907975296782445969183509474202123617940309048634960534054931299919496087957952586977170236680033862505764938088740994009589948109397983231108838769236490221499111120870639202892490698435333152727991330986335454324971441378059132240814960156485679843966464780280409057580889190254236606774500413415794312112501275232250148067232979652230488493751166084976116412777395311302041566848265531411348993243747890268935173904043294851610659785832253168204202834993641595980197343889883020994152152288611175126686173051956249367180053845637855129171848417841594797435580617856680758491080185805695567990185198397660693358224779136504562705766735170961550493338390452612404395517449136885115987454340932040102218982707539212403241042424451570052968378815749468441508011138612561164102477190903050040240662278945607061512108266146098662040425010583978098192019726759010749924884966139441184159734610382401178556739080566483321039073867083298691078093495828888707110651559651222542929154212923108071159723275797510859911398076844732639426419452063138217862260999160086752446265457028969067192282283045169111363652774517975842147102219099906257373383472726498678244401048998507631630668050267115944636293525120269424810854530602810627264236538250773340575475701704367039596467715959261029438313074897245505729085688496091346323165819468660587092144653716755655531962091865952628448253731353698162517351930115341581171353292035873164168839107994000677266031617527582917398395852606454113318985505747847121053505795649095931672167565624818782002769963734155880000867852567422461511406015760115910256449002264980039498403358091309140197877843650167960167465370287466062584346329708303725980494653589318912163976013193079476972058034710553111117215859219066231028099212084069283091906017370764654655683413207556315315006453462321007133584907633048328153458698497332599801187479664273140279381289961720524540674695271948079930396730194274036466594154400092799908634806622334906695224044652158992864203435098858422692019340575496840904812955522654754650713532842543496616084954788090727649930252702815067862810825243222979985391759845188868387004477101866772159439708514664612871148749531862180941719676843144666435175837688436786081446319641912566574047718699160915550910878919431253671945651261878486910876729910565595155159739659034383628124629118117760949411880105946336671039049777312004243578115790429823045072038322781246413671297959415082918378213212876890545963586369344879749784841123274921331663162812456388238288715648447883142417650147980187858215768793063001153788998014623690135803753306246148576074932567807682651045738059018831237617271889933790487113395588485234240255002352200613574914318259142479829367775490496399350755839668967578364316618369307625603528602940662803255416535431518013714821941772672244005268401996533334184004345525296592918502940131600651124395297874364222806977720437363717873457948420238745151249157913139411148608416429347958793681868609689684640858334131017858142710955416293375915178392341303110543328703526599993904966822112768158316511246866451167351378214345336650598328347443536290312393672084593164394941881138607974670134709640378534907149089842317891739783650654751982883367395714360000003439863363212091718954899055748693397700245632475954504411422582410783866837655467400137324322809113692670682805397549111166171102397437749479335174036135005397581475520834285772800986189401984375446435081498218360112577632447389452051636938585136484259964518361856989088721789764694721246807900330925083496645841656554261294195108847197209106605105540933731954888406444080280579549008076040034154662137669606444293774985897353625591959618552448187940317374508256072895120945456562159540405425814886929842786582357673195799285293120866275922366115137445767916063621675267440451221051052090834707443986137829082352772895849625656881972792768694795806100573787084121444815034797422312103295359297822377134077549545477791813823542607184617108389097825964406170543546968567030745411634244134486308676327949177682923093183221341455482591367202823284396549001805653203960795517074496039006696990334199278212696767771835209083959545341866777944872740383733381985235884202840150981579594685874537989503257362809837592216229258598599123843993575573285028613155970362934249814178056461615863415338635077223269996508860870999964899373049307170967888740149746147542880387421250689212155876692242387434701120990859082164073576380817386959755176083877600277517253037133445654852635661720197563001580049790223419586738061442401502436288957503206533690825756785507020555105572381878574650371086308158185862815883054564662297694803970618265491385181326737485227188267917919091354407852685476254126683398240534022469989966652573155637645862251862823092085424412805997628505488913098331761884983352975136073772030571342739638126588567405013841074788943393996603591853934198416322617654857376671943132840050626295140357877264680649549355746326408186979718630218760025813995719923601345374229758918285167511358171472625828596940798518571870075823122317068134867930884899275181661399609753105295773584618525865211893339375771859916335112163441037910451845019023066893064178977808158101360449495409665363660370075881004450265734935127707426742578608784898185628869980851665713320835842613381142623855420315774246613108873106318111989880289722849790551075148403702290580483052731884959994156606537314021296702220821915862905952604040620011815269664910068587592655660567562963361434230232810747488395040380984981860056164646099819257616235478710913832967563761506732550860683433720438748186791668975746563456020002562889601191100980453350423842063824039434163502977688802779835087481178298349417211674919425601608685332435385951152061809031241698182079314615062073826097180458265687043623935757495737332781578904386011378078508110273049446611821957450170106059384336519458628360682108585130499820420578458577175933849015564447305834515291412561679970569657426139901681932056241927977282026714297258700193234337873153939403115411184101414292741703537542003698760608765500109345299007034032401334806388514095769557147190364152027721127070187421548123931953220997506553022646844227700020589045922742423904937051507367764629844971682121994198274794049092601715727439368569721862936007387077810797440975556627807371228030350048829843919546433753355787895064018998685060281902452191177018634505171087023903398550540704454189088472042376499749035038518949505897971286631644699407490959473411581934618336692169573605081585080837952036335619947691937965065016808710250735070825260046821242820434367245824478859256555487861614478717581068572356895150707602217433511627331709472765932413249132702425519391509083601346239612335001086614623850633127072987745618984384288764099836164964775714638573247333226653894523588365972955159905187411779288608760239306160016168434070611663449248395156319152882728822831375458678269830696691220130954815935450754923554167766876455212545681242936427474153815692219503331560151614492247512488957534835926226263545406704767033866410025277276800886383266629488582740369655329362236090572479794734434077704284318507901973469071141230364111729224929307731939309795452877412451183953480382210373644697046967493042810911797232448615413264031578430955396671061468083815548947146733652483679138566431084747848676243012018489329109615281108087617422779131629345494425395422727309645057976122885347393189600810965202090151104579377602529543130188938184010247010134929317443562883578609861545691161669857388024973756940558138630581099823372565164920155443216861690537054630176154809626620800633059320775897175589925862195462096455464624399535391743228225433267174308492508396461328929584567927365409119947616225155964704061297047759818551878441419948614013153859322060745185909608884280218943358691959604936409651570327527570641500776261323783648149005245481413195989296398441371781402764122087644989688629798910870164270169014007825748311598976330612951195680427485317886333041169767175063822135213839779138443325644288490872919067009802496281560626258636942322658490628628035057282983101266919109637258378149363774960594515216932644945188292639525772348420077356021656909077097264985642831778694777804964343991762549216500608626285329471055602670413384500507827390640287529864161287496473708235188892189612641279553536442286955430551308700009878557534223100547153412810957024870812654319123261956462149376527526356402127388765103883255007364899937167183280028398832319373301564123277185395654932422977953016534830128490677845037490891749347389015649588574802194996722621185874361039774946338633057887487405540005440439344888192044102134790034598411927024921557026873700970995205391930979319495883265922171508324621942300185974396706491149559411733728199869021311629886680267446443489233020607003821262841723679627307191405008084085703978151998148822390059948911946474438682533745889962375133378280532928272016815977970066488394482446332210928320504045983008943565954267256879714918703447338237767914829203283196838105907715727191903042365315650957464549643425328069510396558733549803850995143463506175361480050195045201350200180281506933241918267855737764414097080945745624854867704904368368717590918057269794010465019484853146726642978667687697789291431128505043098192949736165944259471754765135205245072597538577958372797702972231435199958499522344049394502115428867244188717409524554771867484911475031801773304689909317974472957035192387686405544278134169807249382219749124257510162187439772902147704638010731470653154201300583810458905006764557332998149945854655105526374914354195867992595981412218735238407957416123372264063860431988936249867649693592569592128495906254446474331759999685163660305216426770428154681777589339252115538590526823311608302751194384823861552852465010329467297198112105314125898165100120742688143577590825227466863206188376830450921784582526239594189673003640808624233657620979111641766331328852352062487922978959456450333733139422384778582717195412347860434376165241568717943562570215636666680088531006728947033079540804583324192188488870712275670333173939262509073556164513677064199539111948881240659821685787131385056850623094155206877987539740658484250135205615103489821873770245063583314243624807432542464195984647411575625441010389671576677263196442524931941806472423789334668561083789808830313571333157729435664956078125304917594015895146954965223118559669048559467607968190167266634650186182955669893965019614544401768162810604465068448139561667220729261210164692339016793399632833013163850830967942792934551268435760356901970523138364640961311774904600772840862214747547653221505518116489887879087780918009050706040061220010051271575991225725282523378026809030528461581739558198122397010092017202251606352922464781615533532275453264543087093320924631855976580561717446840450048285353396546862678852330044967795580761661801833668792312510460809773895565488962815089519622093675058841609752282328250433712970186608193748968699961301486924694482420723632912367052542145464162968910442981633373266871675946715392611950649224725627254543274193495995569590243279097174392258098103601486364409101491734183079646345064833303404765711827040276868271418084574998493392039317445402616663674646668754385093967129918067471909885312710726724428584870694307099756567949198418996425748884764622030325637751112534060087936904565779272035205921345924272965206683338510673615276261016026647772485083344719891986802656197236420847504962661607797092906844757798251795569758235084371746103310387911789239441630112634077535773520558040066982523191225570519133631407211349723226549151062961739050617857127509403623146700931176133132018631158730886798239298009805089491510788371194099750375473674305745187265414016446924576792185753680363289139664155342066705623272936001177781498886100830877849571709880858667023104043242526785955562077310543072298032125941107957349146684680220501816192150766649106862033378713826058987655210423668198670177861672671972374156917880001690656659046965316154923604061891820982414006103779407166342002735828911994182647812782659666207030384795881442790246669264032799404016800137293477301530941805070587421153284642203006550763966756168318897005152026656649929417382840327305940740147117478464839241225676523593418554066440983706083636457657081801664285044258224551650808864421212113914352453935225522162483791737330329812349528984098613273709957407786789349311975204237925022851375880436791854547836416773151821457226504640800104202100410766027807729152555503218182387221708112766208665317651926458452495269685376314437998340336947124447247796973890514941120010934140073794061859447165516612674930799374705772930521750426383798367668159183589049652163726492960837147204067428996276720315410211504333742057182854090136325721437592054640471894328548696883599785122262130812989581571391597464534806099601555877223193450760315411663112963843719400333736013305526352571490454327925190794007111504785378036370897340146753465517470747096935814912797188187854376797751675927822300312945518595042883902735494672667647506072643698761394806879080593531793001711000214417701504495496412454361656210150919997862972495905809191825255486358703529320142005857057855419217730505342687533799076038746689684283402648733290888881745453047194740939258407362058242849349024756883352446212456101562729065130618520732925434179252299417447855189995098959999877410951464170076989305620163502192692653166599093238118295411937545448509428621839424186218067457128099385258842631930670182098008050900019819621758458932516877698594110522845465835679362969619219080897536813210484518784516230623911878024604050824909336069998094776253792973597037759066145994638578378211017122446355845171941670344732162722443265914858595797823752976323442911242311368603724514438765801271594060878788638511089680883165505046309006148832545452819908256238805872042843941834687865142541377686054291079721004271658
diff --git a/src/pkg/compress/testdata/pi.txt b/src/pkg/compress/testdata/pi.txt
index 58d8f3b..ca99bbc 100644
--- a/src/pkg/compress/testdata/pi.txt
+++ b/src/pkg/compress/testdata/pi.txt
@@ -1 +1 @@
-3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678
+3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678566722796619885782794848855834397518744545512965634434803966420557982936804352202770984294232533022576341807039476994159791594530069752148293366555661567873640053666564165473217043903521329543529169414599041608753201868379370234888689479151071637852902345292440773659495630510074210871426134974595615138498713757047101787957310422969066670214498637464595280824369445789772330048764765241339075920434019634039114732023380715095222010682563427471646024335440051521266932493419673977041595683753555166730273900749729736354964533288869844061196496162773449518273695588220757355176651589855190986665393549481068873206859907540792342402300925900701731960362254756478940647548346647760411463233905651343306844953979070903023460461470961696886885014083470405460742958699138296682468185710318879065287036650832431974404771855678934823089431068287027228097362480939962706074726455399253994428081137369433887294063079261595995462624629707062594845569034711972996409089418059534393251236235508134949004364278527138315912568989295196427287573946914272534366941532361004537304881985517065941217352462589548730167600298865925786628561249665523533829428785425340483083307016537228563559152534784459818313411290019992059813522051173365856407826484942764411376393866924803118364453698589175442647399882284621844900877769776312795722672655562596282542765318300134070922334365779160128093179401718598599933849235495640057099558561134980252499066984233017350358044081168552653117099570899427328709258487894436460050410892266917835258707859512983441729535195378855345737426085902908176515578039059464087350612322611200937310804854852635722825768203416050484662775045003126200800799804925485346941469775164932709504934639382432227188515974054702148289711177792376122578873477188196825462981268685817050740272550263329044976277894423621674119186269439650671515779586756482399391760426017633870454990176143641204692182370764887834196896861181558158736062938603810171215855272668300823834046564758804051380801633638874216371406435495561868964112282140753302655100424104896783528588290243670904887118190909494533144218287661810310073547705498159680772009474696134360928614849417850171807793068108546900094458995279424398139213505586422196483491512639012803832001097738680662877923971801461343244572640097374257007359210031541508936793008169980536520276007277496745840028362405346037263416554259027601834840306811381855105979705664007509426087885735796037324514146786703688098806097164258497595138069309449401515422221943291302173912538355915031003330325111749156969174502714943315155885403922164097229101129035521815762823283182342548326111912800928252561902052630163911477247331485739107775874425387611746578671169414776421441111263583553871361011023267987756410246824032264834641766369806637857681349204530224081972785647198396308781543221166912246415911776732253264335686146186545222681268872684459684424161078540167681420808850280054143613146230821025941737562389942075713627516745731891894562835257044133543758575342698699472547031656613991999682628247270641336222178923903176085428943733935618891651250424404008952719837873864805847268954624388234375178852014395600571048119498842390606136957342315590796703461491434478863604103182350736502778590897578272731305048893989009923913503373250855982655867089242612429473670193907727130706869170926462548423240748550366080136046689511840093668609546325002145852930950000907151058236267293264537382104938724996699339424685516483261134146110680267446637334375340764294026682973865220935701626384648528514903629320199199688285171839536691345222444708045923966028171565515656661113598231122506289058549145097157553900243931535190902107119457300243880176615035270862602537881797519478061013715004489917210022201335013106016391541589578037117792775225978742891917915522417189585361680594741234193398420218745649256443462392531953135103311476394911995072858430658361935369329699289837914941939406085724863968836903265564364216644257607914710869984315733749648835292769328220762947282381537409961545598798259891093717126218283025848112389011968221429457667580718653806506487026133892822994972574530332838963818439447707794022843598834100358385423897354243956475556840952248445541392394100016207693636846776413017819659379971557468541946334893748439129742391433659360410035234377706588867781139498616478747140793263858738624732889645643598774667638479466504074111825658378878454858148962961273998413442726086061872455452360643153710112746809778704464094758280348769758948328241239292960582948619196670918958089833201210318430340128495116203534280144127617285830243559830032042024512072872535581195840149180969253395075778400067465526031446167050827682772223534191102634163157147406123850425845988419907611287258059113935689601431668283176323567325417073420817332230462987992804908514094790368878687894930546955703072619009502076433493359106024545086453628935456862958531315337183868265617862273637169757741830239860065914816164049449650117321313895747062088474802365371031150898427992754426853277974311395143574172219759799359685252285745263796289612691572357986620573408375766873884266405990993505000813375432454635967504844235284874701443545419576258473564216198134073468541117668831186544893776979566517279662326714810338643913751865946730024434500544995399742372328712494834706044063471606325830649829795510109541836235030309453097335834462839476304775645015008507578949548931393944899216125525597701436858943585877526379625597081677643800125436502371412783467926101995585224717220177723700417808419423948725406801556035998390548985723546745642390585850216719031395262944554391316631345308939062046784387785054239390524731362012947691874975191011472315289326772533918146607300089027768963114810902209724520759167297007850580717186381054967973100167870850694207092232908070383263453452038027860990556900134137182368370991949516489600755049341267876436746384902063964019766685592335654639138363185745698147196210841080961884605456039038455343729141446513474940784884423772175154334260306698831768331001133108690421939031080143784334151370924353013677631084913516156422698475074303297167469640666531527035325467112667522460551199581831963763707617991919203579582007595605302346267757943936307463056901080114942714100939136913810725813781357894005599500183542511841721360557275221035268037357265279224173736057511278872181908449006178013889710770822931002797665935838758909395688148560263224393726562472776037890814458837855019702843779362407825052704875816470324581290878395232453237896029841669225489649715606981192186584926770403956481278102179913217416305810554598801300484562997651121241536374515005635070127815926714241342103301566165356024733807843028655257222753049998837015348793008062601809623815161366903341111386538510919367393835229345888322550887064507539473952043968079067086806445096986548801682874343786126453815834280753061845485903798217994599681154419742536344399602902510015888272164745006820704193761584547123183460072629339550548239557137256840232268213012476794522644820910235647752723082081063518899152692889108455571126603965034397896278250016110153235160519655904211844949907789992007329476905868577878720982901352956613978884860509786085957017731298155314951681467176959760994210036183559138777817698458758104466283998806006162298486169353373865787735983361613384133853684211978938900185295691967804554482858483701170967212535338758621582310133103877668272115726949518179589754693992642197915523385766231676275475703546994148929041301863861194391962838870543677743224276809132365449485366768000001065262485473055861598999140170769838548318875014293890899506854530765116803337322265175662207526951791442252808165171667766727930354851542040238174608923283917032754257508676551178593950027933895920576682789677644531840404185540104351348389531201326378369283580827193783126549617459970567450718332065034556644034490453627560011250184335607361222765949278393706478426456763388188075656121689605041611390390639601620221536849410926053876887148379895599991120991646464411918568277004574243434021672276445589330127781586869525069499364610175685060167145354315814801054588605645501332037586454858403240298717093480910556211671546848477803944756979804263180991756422809873998766973237695737015808068229045992123661689025962730430679316531149401764737693873514093361833216142802149763399189835484875625298752423873077559555955465196394401821840998412489826236737714672260616336432964063357281070788758164043814850188411431885988276944901193212968271588841338694346828590066640806314077757725705630729400492940302420498416565479736705485580445865720227637840466823379852827105784319753541795011347273625774080213476826045022851579795797647467022840999561601569108903845824502679265942055503958792298185264800706837650418365620945554346135134152570065974881916341359556719649654032187271602648593049039787489589066127250794828276938953521753621850796297785146188432719223223810158744450528665238022532843891375273845892384422535472653098171578447834215822327020690287232330053862163479885094695472004795231120150432932266282727632177908840087861480221475376578105819702226309717495072127248479478169572961423658595782090830733233560348465318730293026659645013718375428897557971449924654038681799213893469244741985097334626793321072686870768062639919361965044099542167627840914669856925715074315740793805323925239477557441591845821562518192155233709607483329234921034514626437449805596103307994145347784574699992128599999399612281615219314888769388022281083001986016549416542616968586788372609587745676182507275992950893180521872924610867639958916145855058397274209809097817293239301067663868240401113040247007350857828724627134946368531815469690466968693925472519413992914652423857762550047485295476814795467007050347999588867695016124972282040303995463278830695976249361510102436555352230690612949388599015734661023712235478911292547696176005047974928060721268039226911027772261025441492215765045081206771735712027180242968106203776578837166909109418074487814049075517820385653909910477594141321543284406250301802757169650820964273484146957263978842560084531214065935809041271135920041975985136254796160632288736181367373244506079244117639975974619383584574915988097667447093006546342423460634237474666080431701260052055928493695941434081468529815053947178900451835755154125223590590687264878635752541911288877371766374860276606349603536794702692322971868327717393236192007774522126247518698334951510198642698878471719396649769070825217423365662725928440620430214113719922785269984698847702323823840055655517889087661360130477098438611687052310553149162517283732728676007248172987637569816335415074608838663640693470437206688651275688266149730788657015685016918647488541679154596507234287730699853713904300266530783987763850323818215535597323530686043010675760838908627049841888595138091030423595782495143988590113185835840667472370297149785084145853085781339156270760356390763947311455495832266945702494139831634332378975955680856836297253867913275055542524491943589128405045226953812179131914513500993846311774017971512283785460116035955402864405902496466930707769055481028850208085800878115773817191741776017330738554758006056014337743299012728677253043182519757916792969965041460706645712588834697979642931622965520168797300035646304579308840327480771811555330909887025505207680463034608658165394876951960044084820659673794731680864156456505300498816164905788311543454850526600698230931577765003780704661264706021457505793270962047825615247145918965223608396645624105195510522357239739512881816405978591427914816542632892004281609136937773722299983327082082969955737727375667615527113922588055201898876201141680054687365580633471603734291703907986396522961312801782679717289822936070288069087768660593252746378405397691848082041021944719713869256084162451123980620113184541244782050110798760717155683154078865439041210873032402010685341947230476666721749869868547076781205124736792479193150856444775379853799732234456122785843296846647513336573692387201464723679427870042503255589926884349592876124007558756946413705625140011797133166207153715436006876477318675587148783989081074295309410605969443158477539700943988394914432353668539209946879645066533985738887866147629443414010498889931600512076781035886116602029611936396821349607501116498327856353161451684576956871090029997698412632665023477167286573785790857466460772283415403114415294188047825438761770790430001566986776795760909966936075594965152736349811896413043311662774712338817406037317439705406703109676765748695358789670031925866259410510533584384656023391796749267844763708474978333655579007384191473198862713525954625181604342253729962863267496824058060296421146386436864224724887283434170441573482481833301640566959668866769563491416328426414974533349999480002669987588815935073578151958899005395120853510357261373640343675347141048360175464883004078464167452167371904831096767113443494819262681110739948250607394950735031690197318521195526356325843390998224986240670310768318446607291248747540316179699411397387765899868554170318847788675929026070043212666179192235209382278788809886335991160819235355570464634911320859189796132791319756490976000139962344455350143464268604644958624769094347048293294140411146540923988344435159133201077394411184074107684981066347241048239358274019449356651610884631256785297769734684303061462418035852933159734583038455410337010916767763742762102137013548544509263071901147318485749233181672072137279355679528443925481560913728128406333039373562420016045664557414588166052166608738748047243391212955877763906969037078828527753894052460758496231574369171131761347838827194168606625721036851321566478001476752310393578606896111259960281839309548709059073861351914591819510297327875571049729011487171897180046961697770017913919613791417162707018958469214343696762927459109940060084983568425201915593703701011049747339493877885989417433031785348707603221982970579751191440510994235883034546353492349826883624043327267415540301619505680654180939409982020609994140216890900708213307230896621197755306659188141191577836272927461561857103721724710095214236964830864102592887457999322374955191221951903424452307535133806856807354464995127203174487195403976107308060269906258076020292731455252078079914184290638844373499681458273372072663917670201183004648190002413083508846584152148991276106513741539435657211390328574918769094413702090517031487773461652879848235338297260136110984514841823808120540996125274580881099486972216128524897425555516076371675054896173016809613803811914361143992106380050832140987604599309324851025168294467260666138151745712559754953580239983146982203613380828499356705575524712902745397762140493182014658008021566536067765508783804304134310591804606800834591136640834887408005741272586704792258319127415739080914383138456424150940849133918096840251163991936853225557338966953749026620923261318855891580832455571948453875628786128859004106006073746501402627824027346962528217174941582331749239683530136178653673760642166778137739951006589528877427662636841830680190804609849809469763667335662282915132352788806157768278159588669180238940333076441912403412022316368577860357276941541778826435238131905028087018575047046312933353757285386605888904583111450773942935201994321971171642235005644042979892081594307167019857469273848653833436145794634175922573898588001698014757420542995801242958105456510831046297282937584161162532562516572498078492099897990620035936509934721582965174135798491047111660791587436986541222348341887722929446335178653856731962559852026072947674072616767145573649812105677716893484917660771705277187601199908144113058645577910525684304811440261938402322470939249802933550731845890355397133088446174107959162511714864874468611247605428673436709046678468670274091881014249711149657817724279347070216688295610877794405048437528443375108828264771978540006509704033021862556147332117771174413350281608840351781452541964320309576018694649088681545285621346988355444560249556668436602922195124830910605377201980218310103270417838665447181260397190688462370857518080035327047185659499476124248110999288679158969049563947624608424065930948621507690314987020673533848349550836366017848771060809804269247132410009464014373603265645184566792456669551001502298330798496079949882497061723674493612262229617908143114146609412341593593095854079139087208322733549572080757165171876599449856937956238755516175754380917805280294642004472153962807463602113294255916002570735628126387331060058910652457080244749375431841494014821199962764531068006631183823761639663180931444671298615527598201451410275600689297502463040173514891945763607893528555053173314164570504996443890936308438744847839616840518452732884032345202470568516465716477139323775517294795126132398229602394548579754586517458787713318138752959809412174227300352296508089177705068259248822322154938048371454781647213976820963320508305647920482085920475499857320388876391601995240918938945576768749730856955958010659526503036266159750662225084067428898265907510637563569968211510949669744580547288693631020367823250182323708459790111548472087618212477813266330412076216587312970811230758159821248639807212407868878114501655825136178903070860870198975889807456643955157415363193191981070575336633738038272152798849350397480015890519420879711308051233933221903466249917169150948541401871060354603794643379005890957721180804465743962806186717861017156740967662080295766577051291209907944304632892947306159510430902221439371849560634056189342513057268291465783293340524635028929175470872564842600349629611654138230077313327298305001602567240141851520418907011542885799208121984493156999059182011819733500126187728036812481995877070207532406361259313438595542547781961142935163561223496661522614735399674051584998603552953329245752388810136202347624669055816438967863097627365504724348643071218494373485300606387644566272186661701238127715621379746149861328744117714552444708997144522885662942440230184791205478498574521634696448973892062401943518310088283480249249085403077863875165911302873958787098100772718271874529013972836614842142871705531796543076504534324600536361472618180969976933486264077435199928686323835088756683595097265574815431940195576850437248001020413749831872259677387154958399718444907279141965845930083942637020875635398216962055324803212267498911402678528599673405242031091797899905718821949391320753431707980023736590985375520238911643467185582906853711897952626234492483392496342449714656846591248918556629589329909035239233333647435203707701010843880032907598342170185542283861617210417603011645918780539367447472059985023582891833692922337323999480437108419659473162654825748099482509991833006976569367159689364493348864744213500840700660883597235039532340179582557036016936990988671132109798897070517280755855191269930673099250704070245568507786790694766126298082251633136399521170984528092630375922426742575599892892783704744452189363203489415521044597261883800300677617931381399162058062701651024458869247649246891924612125310275731390840470007143561362316992371694848132554200914530410371354532966206392105479824392125172540132314902740585892063217589494345489068463993137570910346332714153162232805522972979538018801628590735729554162788676498274186164218789885741071649069191851162815285486794173638906653885764229158342500673612453849160674137340173572779956341043326883569507814931378007362354180070619180267328551191942676091221035987469241172837493126163395001239599240508454375698507957046222664619000103500490183034153545842833764378111988556318777792537201166718539541835984438305203762819440761594106820716970302285152250573126093046898423433152732131361216582808075212631547730604423774753505952287174402666389148817173086436111389069420279088143119448799417154042103412190847094080254023932942945493878640230512927119097513536000921971105412096683111516328705423028470073120658032626417116165957613272351566662536672718998534199895236884830999302757419916463841427077988708874229277053891227172486322028898425125287217826030500994510824783572905691988555467886079462805371227042466543192145281760741482403827835829719301017888345674167811398954750448339314689630763396657226727043393216745421824557062524797219978668542798977992339579057581890622525473582205236424850783407110144980478726691990186438822932305382318559732869780922253529591017341407334884761005564018242392192695062083183814546983923664613639891012102177095976704908305081854704194664371312299692358895384930136356576186106062228705599423371631021278457446463989738188566746260879482018647487672727222062676465338099801966883680994159075776852639865146253336312450536402610569605513183813174261184420189088853196356986962795036738424313011331753305329802016688817481342988681585577810343231753064784983210629718425184385534427620128234570716988530518326179641178579608888150329602290705614476220915094739035946646916235396809201394578175891088931992112260073928149169481615273842736264298098234063200244024495894456129167049508235812487391799648641133480324757775219708932772262349486015046652681439877051615317026696929704928316285504212898146706195331970269507214378230476875280287354126166391708245925170010714180854800636923259462019002278087409859771921805158532147392653251559035410209284665925299914353791825314545290598415817637058927906909896911164381187809435371521332261443625314490127454772695739393481546916311624928873574718824071503995009446731954316193855485207665738825139639163576723151005556037263394867208207808653734942440115799667507360711159351331959197120948964717553024531364770942094635696982226673775209945168450643623824211853534887989395673187806606107885440005508276570305587448541805778891719207881423351138662929667179643468760077047999537883387870348718021842437342112273940255717690819603092018240188427057046092622564178375265263358324240661253311529423457965569502506810018310900411245379015332966156970522379210325706937051090830789479999004999395322153622748476603613677697978567386584670936679588583788795625946464891376652199588286933801836011932368578558558195556042156250883650203322024513762158204618106705195330653060606501054887167245377942831338871631395596905832083416898476065607118347136218123246227258841990286142087284956879639325464285343075301105285713829643709990356948885285190402956047346131138263878897551788560424998748316382804046848618938189590542039889872650697620201995548412650005394428203930127481638158530396439925470201672759328574366661644110962566337305409219519675148328734808957477775278344221091073111351828046036347198185655572957144747682552857863349342858423118749440003229690697758315903858039353521358860079600342097547392296733310649395601812237812854584317605561733861126734780745850676063048229409653041118306671081893031108871728167519579675347188537229309616143204006381322465841111157758358581135018569047815368938137718472814751998350504781297718599084707621974605887423256995828892535041937958260616211842368768511418316068315867994601652057740529423053601780313357263267054790338401257305912339601880137825421927094767337191987287385248057421248921183470876629667207272325650565129333126059505777727542471241648312832982072361750574673870128209575544305968395555686861188397135522084452852640081252027665557677495969626612604565245684086139238265768583384698499778726706555191854468698469478495734622606294219624557085371272776523098955450193037732166649182578154677292005212667143463209637891852323215018976126034373684067194193037746880999296877582441047878123266253181845960453853543839114496775312864260925211537673258866722604042523491087026958099647595805794663973419064010036361904042033113579336542426303561457009011244800890020801478056603710154122328891465722393145076071670643556827437743965789067972687438473076346451677562103098604092717090951280863090297385044527182892749689212106670081648583395537735919136950153162018908887484210798706899114804669270650940762046502772528650728905328548561433160812693005693785417861096969202538865034577183176686885923681488475276498468821949739729707737187188400414323127636504814531122850990020742409255859252926103021067368154347015252348786351643976235860419194129697690405264832347009911154242601273438022089331096686367898694977994001260164227609260823493041180643829138347354679725399262338791582998486459271734059225620749105308531537182911681637219395188700957788181586850464507699343940987433514431626330317247747486897918209239480833143970840673084079589358108966564775859905563769525232653614424780230826811831037735887089240613031336477371011628214614661679404090518615260360092521947218890918107335871964142144478654899528582343947050079830388538860831035719306002771194558021911942899922722353458707566246926177663178855144350218287026685610665003531050216318206017609217984684936863161293727951873078972637353717150256378733579771808184878458866504335824377004147710414934927438457587107159731559439426412570270965125108115548247939403597681188117282472158250109496096625393395380922195591918188552678062149923172763163218339896938075616855911752998450132067129392404144593862398809381240452191484831646210147389182510109096773869066404158973610476436500068077105656718486281496371118832192445663945814491486165500495676982690308911185687986929470513524816091743243015383684707292898982846022237301452655679898627767968091469798378268764311598832109043715611299766521539635464420869197567370005738764978437686287681792497469438427465256316323005551304174227341646455127812784577772457520386543754282825671412885834544435132562054464241011037955464190581168623059644769587054072141985212106734332410756767575818456990693046047522770167005684543969234041711089888993416350585157887353430815520811772071880379104046983069578685473937656433631979786803671873079693924236321448450354776315670255390065423117920153464977929066241508328858395290542637687668968805033317227800185885069736232403894700471897619347344308437443759925034178807972235859134245813144049847701732361694719765715353197754997162785663119046912609182591249890367654176979903623755286526375733763526969344354400473067198868901968147428767790866979688522501636949856730217523132529265375896415171479559538784278499866456302878831962099830494519874396369070682762657485810439112232618794059941554063270131989895703761105323606298674803779153767511583043208498720920280929752649812569163425000522908872646925284666104665392171482080130502298052637836426959733707053922789153510568883938113249757071331029504430346715989448786847116438328050692507766274500122003526203709466023414648998390252588830148678162196775194583167718762757200505439794412459900771152051546199305098386982542846407255540927403132571632640792934183342147090412542533523248021932277075355546795871638358750181593387174236061551171013123525633485820365146141870049205704372018261733194715700867578539336078622739558185797587258744102542077105475361294047460100094095444959662881486915903899071865980563617137692227290764197755177720104276496949611056220592502420217704269622154958726453989227697660310524980855759471631075870133208861463266412591148633881220284440694169488261529577625325019870359870674380469821942056381255833436421949232275937221289056420943082352544084110864545369404969271494003319782861318186188811118408257865928757426384450059944229568586460481033015388911499486935436030221810943466764000022362550573631294626296096198760564259963946138692330837196265954739234624134597795748524647837980795693198650815977675350553918991151335252298736112779182748542008689539658359421963331502869561192012298889887006079992795411188269023078913107603617634779489432032102773359416908650071932804017163840644987871753756781185321328408216571107549528294974936214608215583205687232185574065161096274874375098092230211609982633033915469494644491004515280925089745074896760324090768983652940657920198315265410658136823791984090645712468948470209357761193139980246813405200394781949866202624008902150166163813538381515037735022966074627952910384068685569070157516624192987244482719429331004854824454580718897633003232525821581280327467962002814762431828622171054352898348208273451680186131719593324711074662228508710666117703465352839577625997744672185715816126411143271794347885990892808486694914139097716736900277758502686646540565950394867841110790116104008572744562938425494167594605487117235946429105850909950214958793112196135908315882620682332156153086833730838173279328196983875087083483880463884784418840031847126974543709373298362402875197920802321878744882872843727378017827008058782410749357514889978911739746129320351081432703251409030487462262942344327571260086642508333187688650756429271605525289544921537651751492196367181049435317858383453865255656640657251363575064353236508936790431702597878177190314867963840828810209461490079715137717099061954969640070867667102330048672631475510537231757114322317411411680622864206388906210192355223546711662137499693269321737043105987225039456574924616978260970253359475020913836673772894438696400028110344026084712899000746807764844088711341352503367877316797709372778682166117865344231732264637847697875144332095340001650692130546476890985050203015044880834261845208730530973189492916425322933612431514306578264070283898409841602950309241897120971601649265613413433422298827909921786042679812457285345801338260995877178113102167340256562744007296834066198480676615805021691833723680399027931606420436812079900316264449146190219458229690992122788553948783538305646864881655562294315673128274390826450611628942803501661336697824051770155219626522725455850738640585299830379180350432876703809252167907571204061237596327685674845079151147313440001832570344920909712435809447900462494313455028900680648704293534037436032625820535790118395649089354345101342969617545249573960621490288728932792520696535386396443225388327522499605986974759882329916263545973324445163755334377492928990581175786355555626937426910947117002165411718219750519831787137106051063795558588905568852887989084750915764639074693619881507814685262133252473837651192990156109189777922008705793396463827490680698769168197492365624226087154176100430608904377976678519661891404144925270480881971498801542057787006521594009289777601330756847966992955433656139847738060394368895887646054983871478968482805384701730871117761159663505039979343869339119789887109156541709133082607647406305711411098839388095481437828474528838368079418884342666222070438722887413947801017721392281911992365405516395893474263953824829609036900288359327745855060801317988407162446563997948275783650195514221551339281978226984278638391679715091262410548725700924070045488485692950448110738087996547481568913935380943474556972128919827177020766613602489581468119133614121258783895577357194986317210844398901423948496659251731388171602663261931065366535041473070804414939169363262373767777095850313255990095762731957308648042467701212327020533742667053142448208168130306397378736642483672539837487690980602182785786216512738563513290148903509883270617258932575363993979055729175160097615459044771692265806315111028038436017374742152476085152099016158582312571590733421736576267142390478279587281505095633092802668458937649649770232973641319060982740633531089792464242134583740901169391964250459128813403498810635400887596820054408364386516617880557608956896727531538081942077332597917278437625661184319891025007491829086475149794003160703845549465385946027452447466812314687943441610993338908992638411847425257044572517459325738989565185716575961481266020310797628254165590506042479114016957900338356574869252800743025623419498286467914476322774005529460903940177536335655471931000175430047504719144899841040015867946179241610016454716551337074073950260442769538553834397550548871099785205401175169747581344926079433689543783221172450687344231989878844128542064742809735625807066983106979935260693392135685881391214807354728463227784908087002467776303605551232386656295178853719673034634701222939581606792509153217489030840886516061119011498443412350124646928028805996134283511884715449771278473361766285062169778717743824362565711779450064477718370221999106695021656757644044997940765037999954845002710665987813603802314126836905783190460792765297277694043613023051787080546511542469395265127101052927070306673024447125973939950514628404767431363739978259184541176413327906460636584152927019030276017339474866960348694976541752429306040727005059039503148522921392575594845078867977925253931765156416197168443524369794447355964260633391055126826061595726217036698506473281266724521989060549880280782881429796336696744124805982192146339565745722102298677599746738126069367069134081559412016115960190237753525556300606247983261249881288192937343476862689219239777833910733106588256813777172328315329082525092733047850724977139448333892552081175608452966590553940965568541706001179857293813998258319293679100391844099286575605993598910002969864460974714718470101531283762631146774209145574041815908800064943237855839308530828305476076799524357391631221886057549673832243195650655460852881201902363644712703748634421727257879503428486312944916318475347531435041392096108796057730987201352484075057637199253650470908582513936863463863368042891767107602111159828875539940120076013947033661793715396306139863655492213741597905119083588290097656647300733879314678913181465109316761575821351424860442292445304113160652700974330088499034675405518640677342603583409608605533747362760935658853109760994238347382222087292464497684560579562516765574088410321731345627735856052358236389532038534024842273371639123973215995440828421666636023296545694703577184873442034227706653837387506169212768015766181095420097708363604361110592409117889540338021426523948929686439808926114635414571535194342850721353453018315875628275733898268898523557799295727645229391567477566676051087887648453493636068278050564622813598885879259940946446041705204470046315137975431737187756039815962647501410906658866162180038266989961965580587208639721176995219466789857011798332440601811575658074284182910615193917630059194314434605154047710570054339000182453117733718955857603607182860506356479979004139761808955363669603162193113250223851791672055180659263518036251214575926238369348222665895576994660491938112486609099798128571823494006615552196112207203092277646200999315244273589488710576623894693889446495093960330454340842102462401048723328750081749179875543879387381439894238011762700837196053094383940063756116458560943129517597713935396074322792489221267045808183313764165818269562105872892447740035947009268662659651422050630078592002488291860839743732353849083964326147000532423540647042089499210250404726781059083644007466380020870126664209457181702946752278540074508552377720890581683918446592829417018288233014971554235235911774818628592967605048203864343108779562892925405638946621948268711042828163893975711757786915430165058602965217459581988878680408110328432739867198621306205559855266036405046282152306154594474489908839081999738747452969810776201487134000122535522246695409315213115337915798026979555710508507473874750758068765376445782524432638046143042889235934852961058269382103498000405248407084403561167817170512813378805705643450616119330424440798260377951198548694559152051960093041271007277849301555038895360338261929343797081874320949914159593396368110627557295278004254863060054523839151068998913578820019411786535682149118528207852130125518518493711503422159542244511900207393539627400208110465530207932867254740543652717595893500716336076321614725815407642053020045340183572338292661915308354095120226329165054426123619197051613839357326693760156914429944943744856809775696303129588719161129294681884936338647392747601226964158848900965717086160598147204467428664208765334799858222090619802173211614230419477754990738738567941189824660913091691772274207233367635032678340586301930193242996397204445179288122854478211953530898910125342975524727635730226281382091807439748671453590778633530160821559911314144205091447293535022230817193663509346865858656314855575862447818620108711889760652969899269328178705576435143382060141077329261063431525337182243385263520217735440715281898137698755157574546939727150488469793619500477720970561793913828989845327426227288647108883270173723258818244658436249580592560338105215606206155713299156084892064340303395262263451454283678698288074251422567451806184149564686111635404971897682154227722479474033571527436819409892050113653400123846714296551867344153741615042563256713430247655125219218035780169240326699541746087592409207004669340396510178134857835694440760470232540755557764728450751826890418293966113310160131119077398632462778219023650660374041606724962490137433217246454097412995570529142438208076098364823465973886691349919784013108015581343979194852830436739012482082444814128095443773898320059864909159505322857914576884962578665885999179867520554558099004556461178755249370124553217170194282884617402736649978475508294228020232901221630102309772151569446427909802190826689868834263071609207914085197695235553488657743425277531197247430873043619511396119080030255878387644206085044730631299277888942729189727169890575925244679660189707482960949190648764693702750773866432391919042254290235318923377293166736086996228032557185308919284403805071030064776847863243191000223929785255372375566213644740096760539439838235764606992465260089090624105904215453927904411529580345334500256244101006359530039598864466169595626351878060688513723462707997327233134693971456285542615467650632465676620279245208581347717608521691340946520307673391841147504140168924121319826881568664561485380287539331160232292555618941042995335640095786495340935115266454024418775949316930560448686420862757201172319526405023099774567647838488973464317215980626787671838005247696884084989185086149003432403476742686245952395890358582135006450998178244636087317754378859677672919526111213859194725451400301180503437875277664402762618941017576872680428176623860680477885242887430259145247073950546525135339459598789619778911041890292943818567205070964606263541732944649576612651953495701860015412623962286413897796733329070567376962156498184506842263690367849555970026079867996261019039331263768556968767029295371162528005543100786408728939225714512481135778627664902425161990277471090335933309304948380597856628844787441469841499067123764789582263294904679812089984857163571087831191848630254501620929805829208334813638405421720056121989353669371336733392464416125223196943471206417375491216357008573694397305979709719726666642267431117762176403068681310351899112271339724036887000996862922546465006385288620393800504778276912835603372548255793912985251506829969107754257647488325341412132800626717094009098223529657957997803018282428490221470748111124018607613415150387569830918652780658896682362523937845272634530420418802508442363190383318384550522367992357752929106925043261446950109861088899914658551881873582528164302520939285258077969737620845637482114433988162710031703151334402309526351929588680690821355853680161000213740851154484912685841268695899174149133820578492800698255195740201818105641297250836070356851055331787840829000041552511865779453963317538532092149720526607831260281961164858098684587525129997404092797683176639914655386108937587952214971731728131517932904431121815871023518740757222100123768721944747209349312324107065080618562372526732540733324875754482967573450019321902199119960797989373383673242576103938985349278777473980508080015544764061053522202325409443567718794565430406735896491017610775948364540823486130254718476485189575836674399791508512858020607820554462991723202028222914886959399729974297471155371858924238493855858595407438104882624648788053304271463011941589896328792678327322456103852197011130466587100500083285177311776489735230926661234588873102883515626446023671996644554727608310118788389151149340939344750073025855814756190881398752357812331342279866503522725367171230756861045004548970360079569827626392344107146584895780241408158405229536937499710665594894459246286619963556350652623405339439142111271810691052290024657423604130093691889255865784668461215679554256605416005071276641766056874274200329577160643448606201239821698271723197826816628249938714995449137302051843669076723577400053932662622760323659751718925901801104290384274185507894887438832703063283279963007200698012244365116394086922220745320244624121155804354542064215121585056896157356414313068883443185280853975927734433655384188340303517822946253702015782157373265523185763554098954033236382319219892171177449469403678296185920803403867575834111518824177439145077366384071880489358256868542011645031357633355509440319236720348651010561049872726472131986543435450409131859513145181276437310438972507004981987052176272494065214619959232142314439776546708351714749367986186552791715824080651063799500184295938799158350171580759883784962257398512129810326379376218322456594236685376799113140108043139732335449090824910499143325843298821033984698141715756010829706583065211347076803680695322971990599904451209087275776225351040902392888779424630483280319132710495478599180196967835321464441189260631526618167443193550817081875477050802654025294109218264858213857526688155584113198560022135158887210365696087515063187533002942118682221893775546027227291290504292259787710667873840000616772154638441292371193521828499824350920891801685572798156421858191197490985730570332667646460728757430565372602768982373259745084479649545648030771598153955827779139373601717422996027353102768719449444917939785144631597314435351850491413941557329382048542123508173912549749819308714396615132942045919380106231421774199184060180347949887691051557905554806953878540066453375981862846419905220452803306263695626490910827627115903856995051246529996062855443838330327638599800792922846659503551211245284087516229060262011857775313747949362055496401073001348853150735487353905602908933526400713274732621960311773433943673385759124508149335736911664541281788171454023054750667136518258284898099512139193995633241336556777098003081910272040997148687418134667006094051021462690280449159646545330107754695413088714165312544813061192407821188690056027781824235022696189344352547633573536485619363254417756613981703930632872166905722259745209192917262199844409646158269456380239502837121686446561785235565164127712826918688615572716201474934052276946595712198314943381622114006936307430444173284786101777743837977037231795255434107223445512555589998646183876764903972461167959018100035098928641204195163551108763204267612979826529425882951141275841262732790798807559751851576841264742209479721843309352972665210015662514552994745127631550917636730259462132930190402837954246323258550301096706922720227074863419005438302650681214142135057154175057508639907673946335146209082888934938376439399256900604067311422093312195936202982972351163259386772241477911629572780752395056251581603133359382311500518626890530658368129988108663263271980611271548858798093487912913707498230575929091862939195014721197586067270092547718025750337730799397134539532646195269996596385654917590458333585799102012713204583903200853878881633637685182083727885131175227769609787962142372162545214591281831798216044111311671406914827170981015457781939202311563871950805024679725792497605772625913328559726371211201905720771409148645074094926718035815157571514050397610963846755569298970383547314100223802583468767350129775413279532060971154506484212185936490997917766874774481882870632315515865032898164228288232746866106592732197907162384642153489852476216789050260998045266483929542357287343977680495774091449538391575565485459058976495198513801007958010783759945775299196700547602252552034453988712538780171960718164078124847847257912407824544361682345239570689514272269750431873633263011103053423335821609333191218806608268341428910415173247216053355849993224548730778822905252324234861531520976938461042582849714963475341837562003014915703279685301868631572488401526639835689563634657435321783493199825542117308467745297085839507616458229630324424328237737450517028560698067889521768198156710781633405266759539424926280756968326107495323390536223090807081455919837355377748742029039018142937311529334644468151212945097596534306284215319445727118614900017650558177095302468875263250119705209476159416768727784472000192789137251841622857783792284439084301181121496366424659033634194540657183544771912446621259392656620306888520055599121235363718226922531781458792593750441448933981608657900876165024635197045828895481793756681046474614105142498870252139936870509372305447734112641354892806841059107716677821238332810262185587751312721179344448201440425745083063944738363793906283008973306241380614589414227694747931665717623182472168350678076487573420491557628217583972975134478990696589532548940335615613167403276472469212505759116251529654568544633498114317670257295661844775487469378464233737238981920662048511894378868224807279352022501796545343757274163910791972952950812942922205347717304184477915673991738418311710362524395716152714669005814700002633010452643547865903290733205468338872078735444762647925297690170912007874183736735087713376977683496344252419949951388315074877537433849458259765560996555954318040920178497184685497370696212088524377013853757681416632722412634423982152941645378000492507262765150789085071265997036708726692764308377229685985169122305037462744310852934305273078865283977335246017463527703205938179125396915621063637625882937571373840754406468964783100704580613446731271591194608435935825987782835266531151065041623295329047772174083559349723758552138048305090009646676088301540612824308740645594431853413755220166305812111033453120745086824339432159043594430312431227471385842030390106070940315235556172767994160020393975099897629335325855575624808996691829864222677502360193257974726742578211119734709402357457222271212526852384295874273501563660093188045493338989741571490544182559738080871565281430102670460284316819230392535297795765862414392701549740879273131051636119137577008929564823323648298263024607975875767745377160102490804624301856524161756655600160859121534556267602192689982855377872583145144082654583484409478463178777374794653580169960779405568701192328608041130904629350871827125934668712766694873899824598527786499569165464029458935064964335809824765965165142090986755203808309203230487342703468288751604071546653834619611223013759451579252696743642531927390036038608236450762698827497618723575476762889950752114804852527950845033958570838130476937881321123674281319487950228066320170022460331989671970649163741175854851878484012054844672588851401562725019821719066960812627785485964818369621410721714214986361918774754509650308957099470934337856981674465828267911940611956037845397855839240761276344105766751024307559814552786167815949657062559755074306521085301597908073343736079432866757890533483669555486803913433720156498834220893399971641479746938696905480089193067138057171505857307148815649920714086758259602876056459782423770242469805328056632787041926768467116266879463486950464507420219373945259262668613552940624781361206202636498199999498405143868285258956342264328707663299304891723400725471764188685351372332667877921738347541480022803392997357936152412755829569276837231234798989446274330454566790062032420516396282588443085438307201495672106460533238537203143242112607424485845094580494081820927639140008540422023556260218564348994145439950410980591817948882628052066441086319001688568155169229486203010738897181007709290590480749092427141018933542818429995988169660993836961644381528877214085268088757488293258735809905670755817017949161906114001908553744882726200936685604475596557476485674008177381703307380305476973609786543859382187220583902344443508867499866506040645874346005331827436296177862518081893144363251205107094690813586440519229512932450078833398788429339342435126343365204385812912834345297308652909783300671261798130316794385535726296998740359570458452230856390098913179475948752126397078375944861139451960286751210561638976008880092746115860800207803341591451797073036835196977766076373785333012024120112046988609209339085365773222392412449051532780950955866459477634482269986074813297302630975028812103517723124465095349653693090018637764094094349837313251321862080214809922685502948454661814715557444709669530177690434272031892770604717784527939160472281534379803539679861424370956683221491465438014593829277393396032754048009552231816667380357183932757077142046723838624617803976292377131209580789363841447929802588065522129262093623930637313496640186619510811583471173312025805866727639992763579078063818813069156366274125431259589936119647626101405563503399523140323113819656236327198961837254845333702062563464223952766943568376761368711962921818754576081617053031590728828700712313666308722754918661395773730546065997437810987649802414011242142773668082751390959313404155826266789510846776118665957660165998178089414985754976284387856100263796543178313634025135814161151902096499133548733131115022700681930135929595971640197196053625033558479980963488718039111612813595968565478868325856437896173159762002419621552896297904819822199462269487137462444729093456470028537694958859591606789282491054412515996300781368367490209374915732896270028656829344431342347351239298259166739503425995868970697267332582735903121288746660451461487850346142827765991608090398652575717263081833494441820193533385071292345774375579344062178711330063106003324053991693682603746176638565758877580201229366353270267100681261825172914608202541892885935244491070138206211553827793565296914576502048643282865557934707209634807372692141186895467322767751335690190153723669036865389161291688887876407525493494249733427181178892759931596719354758988097924525262363659036320070854440784544797348291802082044926670634420437555325050527522833778887040804033531923407685630109347772125639088640413101073817853338316038135280828119040832564401842053746792992622037698718018061122624490909242641985820861751177113789051609140381575003366424156095216328197122335023167422600567941281406217219641842705784328959802882335059828208196666249035857789940333152274817776952843681630088531769694783690580671064828083598046698841098135158654906933319522394363287923990534810987830274500172065433699066117784554364687723631844464768069142828004551074686645392805399409108754939166095731619715033166968309929466349142798780842257220697148875580637480308862995118473187124777291910070227588893486939456289515802965372150409603107761289831263589964893410247036036645058687287589051406841238124247386385427908282733827973326885504935874303160274749063129572349742611221517417153133618622410913869500688835898962349276317316478340077460886655598733382113829928776911495492184192087771606068472874673681886167507221017261103830671787856694812948785048943063086169948798703160515884108282351274153538513365895332948629494495061868514779105804696039069372662670386512905201137810858616188886947957607413585534585151768051973334433495230120395770739623771316030242887200537320998253008977618973129817881944671731160647231476248457551928732782825127182446807824215216469567819294098238926284943760248852279003620219386696482215628093605373178040863727268426696421929946819214908701707533361094791381804063287387593848269535583077395761447997270003472880182785281389503217986345216111066608839314053226944905455527867894417579202440021450780192099804461382547805858048442416404775031536054906591430078158372430123137511562284015838644270890718284816757527123846782459534334449622010096071051370608461801187543120725491334994247617115633321408934609156561550600317384218701570226103101916603887064661438897736318780940711527528174689576401581047016965247557740891644568677717158500583269943401677202156767724068128366565264122982439465133197359199709403275938502669557470231813203243716420586141033606524536939160050644953060161267822648942437397166717661231048975031885732165554988342121802846912529086101485527815277625623750456375769497734336846015607727035509629049392487088406281067943622418704747008368842671022558302403599841645951122485272633632645114017395248086194635840783753556885622317115520947223065437092606797351000565549381224575483728545711797393615756167641692895805257297522338558611388322171107362265816218842443178857488798109026653793426664216990914056536432249301334867988154886628665052346997235574738424830590423677143278792316422403877764330192600192284778313837632536121025336935812624086866699738275977365682227907215832478888642369346396164363308730139814211430306008730666164803678984091335926293402304324974926887831643602681011309570716141912830686577323532639653677390317661361315965553584999398600565155921936759977717933019744688148371103206503693192894521402650915465184309936553493337183425298433679915939417466223900389527673813330617747629574943868716978453767219493506590875711917720875477107189937960894774512654757501871194870738736785890200617373321075693302216320628432065671192096950585761173961632326217708945426214609858410237813215817727602222738133495410481003073275107799948991977963883530734443457532975914263768405442264784216063122769646967156473999043715903323906560726644116438605404838847161912109008701019130726071044114143241976796828547885524779476481802959736049439700479596040292746299203572099761950140348315380947714601056333446998820822120587281510729182971211917876424880354672316916541852256729234429187128163232596965413548589577133208339911288775917226115273379010341362085614577992398778325083550730199818459025958355989260553299673770491722454935329683300002230181517226575787524058832249085821280089747909326100762578770428656006996176212176845478996440705066241710213327486796237430229155358200780141165348065647488230615003392068983794766255036549822805329662862117930628430170492402301985719978948836897183043805182174419147660429752437251683435411217038631379411422095295885798060152938752753799030938871683572095760715221900279379292786303637268765822681241993384808166021603722154710143007377537792699069587121289288019052031601285861825494413353820784883465311632650407642428390870121015194231961652268422003711230464300673442064747718021353070124098860353399152667923871101706221865883573781210935179775604425634694999787251125440854522274810914874307259869602040275941178942581281882159952359658979181144077653354321757595255536158128001163846720319346507296807990793963714961774312119402021297573125165253768017359101557338153772001952444543620071848475663415407442328621060997613243487548847434539665981338717466093020535070271952983943271425371155766600025784423031073429551533945060486222764966687624079324353192992639253731076892135352572321080889819339168668278948281170472624501948409700975760920983724090074717973340788141825195842598096241747610138252643955135259311885045636264188300338539652435997416931322894719878308427600401368074703904097238473945834896186539790594118599310356168436869219485382055780395773881360679549900085123259442529724486666766834641402189915944565309423440650667851948417766779470472041958822043295380326310537494883122180391279678446100139726753892195119117836587662528083690053249004597410947068772912328214304635337283519953648274325833119144459017809607782883583730111857543659958982724531925310588115026307542571493943024453931870179923608166611305426253995833897942971602070338767815033010280120095997252222280801423571094760351925544434929986767817891045559063015953809761875920358937341978962358931125983902598310267193304189215109689156225069659119828323455503059081730735195503721665870288053992138576037035377105178021280129566841984140362872725623214428754302210909472721073474134975514190737043318276626177275996888826027225247133683353452816692779591328861381766349857728936900965749562287103024362590772412219094300871755692625758065709912016659622436080242870024547362036394841255954881727272473653467783647201918303998717627037515724649922289467932322693619177641614618795613956699567783068290316589699430767333508234990790624100202506134057344300695745474682175690441651540636584680463692621274211075399042188716127617787014258864825775223889184599523376292377915585744549477361295525952226578636462118377598473700347971408206994145580719080213590732269233100831759510659019121294795408603640757358750205890208704579670007055262505811420663907459215273309406823649441590891009220296680523325266198911311842016291631076894084723564366808182168657219688268358402785500782804043453710183651096951782335743030504852653738073531074185917705610397395062640355442275156101107261779370634723804990666922161971194259120445084641746383589938239946517395509000859479990136026674261494290066467115067175422177038774507673563742154782905911012619157555870238957001405117822646989944917908301795475876760168094100135837613578591356924455647764464178667115391951357696104864922490083446715486383054477914330097680486878348184672733758436892724310447406807685278625585165092088263813233623148733336714764520450876627614950389949504809560460989604329123358348859990294526400284994280878624039811814884767301216754161106629995553668193123287425702063738352020086863691311733469731741219153633246745325630871347302792174956227014687325867891734558379964351358800959350877556356248810493852999007675135513527792412429277488565888566513247302514710210575352516511814850902750476845518252096331899068527614435138213662152368890578786699432288816028377482035506016029894009119713850179871683633744139275973644017007014763706655703504338121113576415018451821413619823495159601064752712575935185304332875537783057509567425442684712219618709178560783936144511383335649103256405733898667178123972237519316430617013859539474367843392670986712452211189690840236327411496601243483098929941738030588417166613073040067588380432111555379440605497721705942821514886165672771240903387727745629097110134885184374118695655449745736845218066982911045058004299887953899027804383596282409421860556287788428802127553884803728640019441614257499904272009595204654170598104989967504511936471172772220436102614079750809686975176600237187748348016120310234680567112644766123747627852190241202569943534716226660893675219833111813511146503854895025120655772636145473604426859498074396932331297127377157347099713952291182653485155587137336629120242714302503763269501350911612952993785864681307226486008270881333538193703682598867893321238327053297625857382790097826460545598555131836688844628265133798491667839409761353766251798258249663458771950124384040359140849209733754642474488176184070023569580177410177696925077814893386672557898564589851056891960924398841569280696983352240225634570497312245269354193837004843183357196516626721575524193401933099018319309196582920969656247667683659647019595754739345514337413708761517323677204227385674279170698204549953095918872434939524094441678998846319845504852393662972079777452814399418256789457795712552426826089940863317371538896262889629402112108884427376568624527612130371017300785135715404533041507959447776143597437803742436646973247138410492124314138903579092416036406314038149831481905251720937103964026808994832572297954564042701757722904173234796073618787889913318305843069394825961318713816423467218730845133877219086975104942843769325024981656673816260615941768252509993741672883951744066932549653403101452225316189009235376486378482881344209870048096227171226407489571939002918573307460104360729190945767994614929290427981687729426487729952858434647775386906950148984133924540394144680263625402118614317031251117577642829914644533408920976961699098372652361768745605894704968170136974909523072082682887890730190018253425805343421705928713931737993142410852647390948284596418093614138475831136130576108462366837237695913492615824516221552134879244145041756848064120636520170386330129532777699023118648020067556905682295016354931992305914246396217025329747573114094220180199368035026495636955866425906762685687372110339156793839895765565193177883000241613539562437777840801748819373095020699900890899328088397430367736595524891300156633294077907139615464534088791510300651321934486673248275907946807879819425019582622320395131252014109960531260696555404248670549986786923021746989009547850725672978794769888831093487464426400718183160331655511534276155622405474473378049246214952133258527698847336269182649174338987824789278468918828054669982303689939783413747587025805716349413568433929396068192061773331791738208562436433635359863494496890781064019674074436583667071586924521182997893804077137501290858646578905771426833582768978554717687184427726120509266486102051535642840632368481807287940717127966820060727559555904040233178749447346454760628189541512139162918444297651066947969354016866010055196077687335396511614930937570968554559381513789569039251014953265628147011998326992200066392875374713135236421589265126204072887716578358405219646054105435443642166562244565042999010256586927279142752931172082793937751326106052881235373451068372939893580871243869385934389175713376300720319760816604464683937725806909237297523486702916910426369262090199605204121024077648190316014085863558427609537086558164273995349346546314504040199528537252004957805254656251154109252437991326262713609099402902262062836752132305065183934057450112099341464918433323646569371725914489324159006242020612885732926133596808726500045628284557574596592120530341310111827501306961509835515632004310784601906565493806542525229161991819959602752327702249855738824899882707465936355768582560518068964285376850772012220347920993936179268206590142165615925306737944568949070853263568196831861772268249911472615732035807646298116244013316737892788689229032593349861797021994981925739617673075834417098559222170171825712777534491508205278430904619460835217402005838672849709411023266953921445461066215006410674740207009189911951376466904481267253691537162290791385403937560077835153374167747942100384002308951850994548779039346122220865060160500351776264831611153325587705073541279249909859373473787081194253055121436979749914951860535920403830235716352727630874693219622190064260886183676103346002255477477813641012691906569686495012688376296907233961276287223041141813610060264044030035996988919945827397624114613744804059697062576764723766065541618574690527229238228275186799156983390747671146103022776606020061246876477728819096791613354019881402757992174167678799231603963569492851513633647219540611171767387372555728522940054361785176502307544693869307873499110352182532929726044553210797887711449898870911511237250604238753734841257086064069052058452122754533848008205302450456517669518576913200042816758054924811780519832646032445792829730129105318385636821206215531288668564956512613892261367064093953334570526986959692350353094224543865278677673027540402702246384483553239914751363441044050092330361271496081355490531539021002299595756583705381261965683144286057956696622154721695620870013727768536960840704833325132793112232507148630206951245395003735723346807094656483089209801534878705633491092366057554050864111521441481434630437273271045027768661953107858323334857840297160925215326092558932655600672124359464255065996771770388445396181632879614460817789272171836908880126778207430106422524634807454300476492885553409062185153654355474125476152769772667769772777058315801412185688011705028365275543214803488004442979998062157904564161957212784508928489806426497427090579129069217807298769477975112447305991406050629946894280931034216416629935614828130998870745292716048433630818404126469637925843094185442216359084576146078558562473814931427078266215185541603870206876980461747400808324343665382354555109449498431093494759944672673665352517662706772194183191977196378015702169933675083760057163454643671776723387588643405644871566964321041282595645349841388412890420682047007615596916843038999348366793542549210328113363184722592305554383058206941675629992013373175489122037230349072681068534454035993561823576312837767640631013125335212141994611869350833176587852047112364331226765129964171325217513553261867681942338790365468908001827135283584888444111761234101179918709236507184857856221021104009776994453121795022479578069506532965940383987369907240797679040826794007618729547835963492793904576973661643405359792219285870574957481696694062334272619733518136626063735982575552496509807260123668283605928341855848026958413772558970883789942910549800331113884603401939166122186696058491571485733568286149500019097591125218800396419762163559375743718011480559442298730418196808085647265713547612831629200449880315402105530597076666362749328308916880932359290081787411985738317192616728834918402429721290434965526942726402559641463525914348400675867690350382320572934132981593533044446496829441367323442158380761694831219333119819061096142952201536170298575105594326461468505452684975764807808009221335811378197749271768545075538328768874474591593731162470601091244609829424841287520224462594477638749491997840446829257360968534549843266536862844489365704111817793806441616531223600214918768769467398407517176307516849856359201486892943105940202457969622924566644881967576294349535326382171613395757790766370764569570259738800438415805894336137106551859987600754924187211714889295221737721146081154344982665479872580056674724051122007383459271575727715218589946948117940644466399432370044291140747218180224825837736017346685300744985564715420036123593397312914458591522887408719508708632218837288262822884631843717261903305777147651564143822306791847386039147683108141358275755853643597721650028277803713422869688787349795096031108899196143386664068450697420787700280509367203387232629637856038653216432348815557557018469089074647879122436375556668678067610544955017260791142930831285761254481944449473244819093795369008206384631678225064809531810406570254327604385703505922818919878065865412184299217273720955103242251079718077833042609086794273428955735559252723805511440438001239041687716445180226491681641927401106451622431101700056691121733189423400547959684669804298017362570406733282129962153684881404102194463424646220745575643960452985313071409084608499653767803793201899140865814662175319337665970114330608625009829566917638846056762972931464911493704624469351984039534449135141193667933301936617663652555149174982307987072280860859626112660504289296966535652516688885572112276802772743708917389639772257564890533401038855931125679991516589025016486961427207005916056166159702451989051832969278935550303934681219761582183980483960562523091462638447386296039848924386187298507775928792722068554807210497817653286210187476766897248841139560349480376727036316921007350834073865261684507482496448597428134936480372426116704266870831925040997615319076855770327421785010006441984124207396400139603601583810565928413684574119102736420274163723488214524101347716529603128408658419787951116511529827814620379139855006399960326591248525308493690313130100799977191362230866011099929142871249388541612038020411340188887219693477904497527454288072803509305828754420755134816660927879353566521255620139988249628478726214432362853676502591450468377635282587652139156480972141929675549384375582600253168536356731379262475878049445944183429172756988376226261846365452743497662411138451305481449836311789784489732076719508784158618879692955819733250699951402601511675529750575437810242238957925786562128432731202200716730574069286869363930186765958251326499145950260917069347519408975357464016830811798846452473618956056479426358070562563281189269663026479535951097127659136233180866921535788607812759910537171402204506186075374866306350591483916467656723205714516886170790984695932236724946737583099607042589220481550799132752088583781117685214269334786921895240622657921043620348852926267984013953216458791151579050460579710838983371864038024417511347226472547010794793996953554669619726763255229914654933499663234185951450360980344092212206712567698723427940708857070474293173329188523896721971353924492426178641188637790962814486917869468177591717150669111480020759432012061969637795103227089029566085562225452602610460736131368869009281721068198618553780982018471154163630326265699283424155023600978046417108525537612728905335045506135684143775854429677977014660294387687225115363801191758154028120818255606485410787933598921064427244898618961629413418001295130683638609294100083136673372153008352696235737175330738653338204842190308186449184093723944033405244909554558016406460761581010301767488475017661908692946098769201691202181688291040870709560951470416921147027413390052253340834812870353031023919699978597413908593605433599697075604460134242453682496098772581311024732798562072126572499003468293886872304895562253204463602639854225258416464324271611419817802482595563544907219226583863662663750835944314877635156145710745528016159677048442714194435183275698407552677926411261765250615965235457187956673170913319358761628255920783080185206890151504713340386100310055914817852110384754542933389188444120517943969970194112695119526564919594189975418393234647424290702718875223534393673633663200307232747037407123982562024662651974090199762452056198557625760008708173083288344381831070054514493545885422678578551915372292379555494333410174420169600090696415612732297770221217951868376359082255128816470021992348864043959153018464004714321186360622527011541122283802778538911098490201342741014121559769965438877197485376431158229838533123071751132961904559007938064276695819014842627991221792947987348901868471676503827328552059082984529806259250352128451925927986593506132961946796252373972565584157853744567558998032405492186962888490332560851455344391660226257775512916200772796852629387937530454181080729285891989715381797343496187232927614747850192611450413274873242970583408471112333746274617274626582415324271059322506255302314738759251724787322881491455915605036334575424233779160374952502493022351481961381162563911415610326844958072508273431765944054098269765269344579863479709743124498271933113863873159636361218623497261409556079920628316999420072054811525353393946076850019909886553861433495781650089961649079678142901148387645682174914075623767618453775144031475411206760160726460556859257799322070337333398916369504346690694828436629980037414527627716547623825546170883189810868806847853705536480469350958818025360529740793538676511195079373282083146268960071075175520614433784114549950136432446328193346389050936545714506900864483440180428363390513578157273973334537284263372174065775771079830517555721036795976901889958494130195999573017901240193908681356585539661941371794487632079868800371607303220547423572266896801882123424391885984168972277652194032493227314793669234004848976059037958094696041754279613782553781223947646147832926976545162290281701100437846038756544151739433960048915318817576650500951697402415644771293656614253949368884230517400129920556854289853897942669956777027089146513736892206104415481662156804219838476730871787590279209175900695273456682026513373111518000181434120962601658629821076663523361774007837783423709152644063054071807843358061072961105550020415131696373046849213356837265400307509829089364612047891114753037049893952833457824082817386441322710002968311940203323456420826473276233830294639378998375836554559919340866235090967961134004867027123176526663710778725111860354037554487418693519733656621772359229396776463251562023487570113795712096237723431370212031004965152111976013176419408203437348512852602913334915125083119802850177855710725373149139215709105130965059885999931560863655477403551898166733535880048214665099741433761182777723351910741217572841592580872591315074606025634903777263373914461377038021318347447301113032670296917335047701632106616227830027269283365584011791419447808748253360714403296252285775009808599609040936312635621328162071453406104224112083010008587264252112262480142647519426184325853386753874054743491072710049754281159466017136122590440158991600229827801796035194080046513534752698777609527839984368086908989197839693532179980139135442552717910225397010810632143048511378291498511381969143043497500189980681644412123273328307192824362406733196554692677851193152775113446468905504248113361434984604849051258345683266441528489713972376040328212660253516693914082049947320486021627759791771234751097502403078935759937715095021751693555827072533911892334070223832077585802137174778378778391015234132098489423459613692340497998279304144463162707214796117456975719681239291913740982925805561955207434243295982898980529233366415419256367380689494201471241340525072204061794355252555225008748790086568314542835167750542294803274783044056438581591952666758282929705226127628711040134801787224801789684052407924360582742467443076721645270313451354167649668901274786801010295133862698649748212118629040337691568576240699296372493097201628707200189835423690364149270236961938547372480329855045112089192879829874467864129159417531675602533435310626745254507114181483239880607297140234725520713490798398982355268723950909365667878992383712578976248755990443228895388377317348941122757071410959790047919301046740750411435381782464630795989555638991884773781341347070246747362112048986226991888517456251732519341352038115863350123913054441910073628447567514161050410973505852762044489190978901984315485280533985777844313933883994310444465669244550885946314081751220331390681596592510546858013133838152176418210433429788826119630443111388796258746090226130900849975430395771243230616906262919403921439740270894777663702488155499322458825979020631257436910946393252806241642476868495455324938017639371615636847859823715902385421265840615367228607131702674740131145261063765383390315921943469817605358380310612887852051546933639241088467632009567089718367490578163085158138161966882222047570437590614338040725853862083565176998426774523195824182683698270160237414938363496629351576854061397342746470899685618170160551104880971554859118617189668025973541705423985135560018720335079060946421271143993196046527424050882225359773481519135438571253258540493946010865793798058620143366078825219717809025817370870916460452727977153509910340736425020386386718220522879694458387652947951048660717390229327455426785669776865939923416834122274663015062155320502655341460995249356050854921756549134830958906536175693817637473644183378974229700703545206663170929607591989627732423090252397443861014263098687733913882518684316501027964911497737582888913450341148865948670215492101084328080783428089417298008983297536940644969903125399863919581601468995220880662285408414864274786281975546629278814621607171381880180840572084715868906836919393381864278454537956719272397972364651667592011057995663962598535512763558768140213409829016296873429850792471846056874828331381259161962476156902875901072733103299140623864608333378638257926302391590003557609032477281338887339178096966601469615031754226751125993315529674213336300222964906480934582008181061802100227664580400278213336758573019011371754672763059044353131319036092489097246427928455549913490005180295707082919052556781889913899625138662319380053611346224294610248954072404857123256628888931722116432947816190554868054943441034090680716088028227959686950133643814268252170472870863010137301155236861416908375675747637239763185757038109443390564564468524183028148107998376918512127201935044041804604721626939445788377090105974693219720558114078775989772072009689382249303236830515862657281114637996983137517937623215111252349734305240622105244234353732905655163406669506165892878218707756794176080712973781335187117931650033155523822487730653444179453415395202424449703410120874072188109388268167512042299404948179449472732894770111574139441228455521828424922240658752689172272780607116754046973008037039618787796694882555614674384392570115829546661358678671897661297311267200072971553613027503556167817765442287442114729881614802705243806817653573275578602505847084013208837932816008769081300492491473682517035382219619039014999523495387105997351143478292339499187936608692301375596368532373806703591144243268561512109404259582639301678017128669239283231057658851714020211196957064799814031505633045141564414623163763809904402816256917576489142569714163598439317433270237812336938043012892626375382667795034169334323607500248175741808750388475094939454896209740485442635637164995949920980884294790363666297526003243856352945844728944547166209297495496616877414120882130477022816116456044007236351581149729739218966737382647204722642221242016560150284971306332795814302516013694825567014780935790889657134926158161346901806965089556310121218491805847922720691871696316330044858020102860657858591269974637661741463934159569539554203314628026518951167938074573315759846086173702687867602943677780500244673391332431669880354073232388281847501051641331189537036488422690270478052742490603492082954755054003457160184072574536938145531175354210726557835615499874447480427323457880061873149341566046352979779455075359304795687209316724536547208381685855606043801977030764246083489876101345709394877002946175792061952549255757109038525171488525265671045349813419803390641529876343695420256080277614421914318921393908834543131769685101840103844472348948869520981943531906506555354617335814045544837884752526253949665869992058417652780125341033896469818642430034146791380619028059607854888010789705516946215228773090104467462497979992627120951684779568482583341402266477210843362437593741610536734041954738964197895425335036301861400951534766961476255651873823292468547356935802896011536791787303553159378363082248615177770541577576561759358512016692943111138863582159667618830326104164651714846979385422621687161400122378213779774131268977266712992025922017408770076956283473932201088159356286281928563571893384958850603853158179760679479840878360975960149733420572704603521790605647603285569276273495182203236144112584182426247712012035776388895974318232827871314608053533574494297621796789034568169889553518504478325616380709476951699086247100019748809205009521943632378719764870339223811540363475488626845956159755193765410115014067001226927474393888589943859730245414801061235908036274585288493563251585384383242493252666087588908318700709100237377106576985056433928854337658342596750653715005333514489908293887737352051459333049626531415141386124437935885070944688045486975358170212908490787347806814366323322819415827345671356443171537967818058195852464840084032909981943781718177302317003989733050495387356116261023999433259780126893432605584710278764901070923443884634011735556865903585244919370181041626208504299258697435817098133894045934471937493877624232409852832762266604942385129709453245586252103600829286649724174919141988966129558076770979594795306013119159011773943104209049079424448868513086844493705909026006120649425744710353547657859242708130410618546219881830090634588187038755856274911587375421064667951346487586771543838018521348281915812462599335160198935595167968932852205824799421034512715877163345222995418839680448835529753361286837225935390079201666941339091168758803988828869216002373257361588207163516271332810518187602104852180675526648673908900907195138058626735124312215691637902277328705410842037841525683288718046987952513073266340278519059417338920358540395677035611329354482585628287610610698229721420961993509331312171187891078766872044548876089410174798647137882462153955933333275562009439580434537919782280590395959927436913793778664940964048777841748336432684026282932406260081908081804390914556351936856063045089142289645219987798849347477729132797266027658401667890136490508741142126861969862044126965282981087045479861559545338021201155646979976785738920186243599326777689454060508218838227909833627167124490026761178498264377033002081844590009717235204331994708242098771514449751017055643029542821819670009202515615844174205933658148134902693111517093872260026458630561325605792560927332265579346280805683443921373688405650434307396574061017779370141424615493070741360805442100295600095663588977899267630517718781943706761498217564186590116160865408635391513039201316805769034172596453692350806417446562351523929050409479953184074862151210561833854566176652606393713658802521666223576132201941701372664966073252010771947931265282763302413805164907174565964853748354669194523580315301969160480994606814904037819829732360930087135760798621425422096419004367905479049930078372421581954535418371129368658430553842717628035279128821129308351575656599944741788438381565148434229858704245592434693295232821803508333726283791830216591836181554217157448465778420134329982594566884558266171979012180849480332448787258183774805522268151011371745368417870280274452442905474518234674919564188551244421337783521423865979925988203287085109338386829906571994614906290257427686038850511032638544540419184958866538545040571323629681069146814847869659166861842756798460041868762298055562963045953227923051616721591968675849523635298935788507746081537321454642984792310511676357749494622952569497660359473962430995343310404994209677883827002714478494069037073249106444151696053256560586778757417472110827435774315194060757983563629143326397812218946287447798119807225646714664054850131009656786314880090303749338875364183165134982546694673316118123364854397649325026179549357204305402182974871251107404011611405899911093062492312813116340549262571356721818628932786138833718028535056503591952741400869510926167541476792668032109237467087213606278332922386413619594121339278036118276324106004740971111048140003623342714514483334641675466354699731494756643423659493496845884551524150756376605086632827424794136062876041290644913828519456402643153225858624043141838669590633245063000392213192647625962691510904457695301444054618037857503036686212462278639752746667870121003392984873375014475600322100622358029343774955032037012738468163061026570300872275462966796880890587127676361066225722352229739206443093524327228100859973095132528630601105497915644791845004618046762408928925680912930592960642357021061524646205023248966593987324933967376952023991760898474571843531936646529125848064480196520162838795189499336759241485626136995945307287254532463291529110128763770605570609531377527751867923292134955245133089867969165129073841302167573238637575820080363575728002754490327953079900799442541108725693188014667935595834676432868876966610097395749967836593397846346959948950610490383647409504695226063858046758073069912290474089879166872117147527644711604401952718169508289733537148530928937046384420893299771125856840846608339934045689026787516008775461267988015465856522061210953490796707365539702576199431376639960606061106406959330828171876426043573425361756943784848495250108266488395159700490598380812105221111091943323951136051446459834210799058082093716464523127704023160072138543723461267260997870385657091998507595634613248460188409850194287687902268734556500519121546544063829253851276317663922050938345204300773017029940362615434001322763910912988327863920412300445551684054889809080779174636092439334912641164240093880746356607262336695842764583698268734815881961058571835767462009650526065929263548291499045768307210893245857073701660717398194485028842603963660746031184786225831056580870870305567595861341700745402965687634774176431051751036732869245558582082372038601781739405175130437994868822320044378043103170921034261674998000073016094814586374488778522273076330495383944345382770608760763542098445008306247630253572781032783461766970544287155315340016497076657195985041748199087201490875686037783591994719343352772947285537925787684832301101859365800717291186967617655053775030293033830706448912811412025506150896411007623824574488655182581058140345320124754723269087547507078577659732542844459353044992070014538748948226556442223696365544194225441338212225477497535494624827680533336983284156138692363443358553868471111430498248398991803165458638289353799130535222833430137953372954016257623228081138499491876144141322933767106563492528814528239506209022357876684650116660097382753660405446941653422239052108314585847035529352219928272760574821266065291385530345549744551470344939486863429459658431024190785923680224560763936784166270518555178702904073557304620639692453307795782245949710420188043000183881429008173039450507342787013124466860092778581811040911511729374873627887874907465285565434748886831064110051023020875107768918781525622735251550379532444857787277617001964853703555167655209119339343762866284619844026295252183678522367475108809781507098978413086245881522660963551401874495836926917799047120726494905737264286005211403581231076006699518536124862746756375896225299116496066876508261734178484789337295056739007878617925351440621045366250640463728815698232317500596261080921955211150859302955654967538862612972339914628358476048627627027309739202001432248707582337354915246085608210328882974183906478869923273691360048837436615223517058437705545210815513361262142911815615301758882573594892507108879262128641392443309383797333867806131795237315266773820858024701433527009243803266951742119507670884326346442749127558907746863582162166042741315170212458586056233631493164646913946562497471741958354218607748711057338458433689939645913740603382159352243594751626239188685307822821763983237306180204246560477527943104796189724299533029792497481684052893791044947004590864991872727345413508101983881864673609392571930511968645601855782450218231065889437986522432050677379966196955472440585922417953006820451795370043472451762893566770508490213107736625751697335527462302943031203596260953423574397249659211010657817826108745318874803187430823573699195156340957162700992444929749105489851519658664740148225106335367949737142510229341882585117371994499115097583746130105505064197721531929354875371191630262030328588658528480193509225875775597425276584011721342323648084027143356367542046375182552524944329657043861387865901965738802868401894087672816714137033661732650120578653915780703088714261519075001492576112927675193096728453971160213606303090542243966320674323582797889332324405779199278484633339777737655901870574806828678347965624146102899508487399692970750432753029972872297327934442988646412725348160603779707298299173029296308695801996312413304939350493325412355071054461182591141116454534710329881047844067780138077131465400099386306481266614330858206811395838319169545558259426895769841428893743467084107946318932539106963955780706021245974898293564613560788983472419979478564362042094613412387613198865352358312996862268948608408456655606876954501274486631405054735351746873009806322780468912246821460806727627708402402266155485024008952891657117617439020337584877842911289623247059191874691042005848326140677333751027195653994697162517248312230633919328707983800748485726516123434933273356664473358556430235280883924348278760886164943289399166399210488307847777048045728491456303353265070029588906265915498509407972767567129795010098229476228961891591441520032283878773485130979081019129267227103778898053964156362364169154985768408398468861684375407065121039062506128107663799047908879674778069738473170475253442156390387201238806323688037017949308954900776331523063548374256816653361606641980030188287123767481898330246836371488309259283375902278942588060087286038859168849730693948020511221766359138251524278670094406942355120201568377778851824670025651708509249623747726813694284350062938814429987905301056217375459182679973217735029368928065210025396268807498092643458011655715886700443503976505323478287327368840863540002740676783821963522226539290939807367391364082898722017776747168118195856133721583119054682936083236976113450281757830202934845982925000895682630271263295866292147653142233351793093387951357095346377183684092444422096319331295620305575517340067973740614162107923633423805646850092037167152642556371853889571416419772387422610596667396997173168169415435095283193556417705668622215217991151355639707143312893657553844648326201206424338016955862698561022460646069330793847858814367407000599769703649019273328826135329363112403650698652160638987250267238087403396744397830258296894256896741864336134979475245526291426522842419243083388103580053787023999542172113686550275341362211693140694669513186928102574795985605145005021715913317751609957865551981886193211282110709442287240442481153406055895958355815232012184605820563592699303478851132068626627588771446035996656108430725696500563064489187599466596772847171539573612108180841547273142661748933134174632662354222072600146012701206934639520564445543291662986660783089068118790090815295063626782075614388815781351134695366303878412092346942868730839320432333872775496805210302821544324723388845215343727250128589747691460808314404125868181540049187772287869801853454537006526655649170915429522756709222217474112062720656622989806032891672068743654948246108697367225547404812889242471854323605753411672850757552057131156697954584887398742228135887985840783135060548290551482785294891121905383195624228719484759407859398047901094194070671764439032730712135887385049993638838205501683402777496070276844880281912220636888636811043569529300652195528261526991271637277388418993287130563464688227398288763198645709836308917786487086676185485680047672552675414742851028145807403152992197814557756843681110185317498167016426647884090262682824448258027532094549915104518517716546311804904567985713257528117913656278158111288816562285876030875974963849435275676612168959261485030785362045274507752950631012480341804584059432926079854435620093708091821523920371790678121992280496069738238743312626730306795943960954957189577217915597300588693646845576676092450906088202212235719254536715191834872587423919410890444115959932760044506556206461164655665487594247369252336955993030355095817626176231849561906494839673002037763874369343999829430209147073618947932692762445186560239559053705128978163455423320114975994896278424327483788032701418676952621180975006405149755889650293004867605208010491537885413909424531691719987628941277221129464568294860281493181560249677887949813777216229359437811004448060797672429276249510784153446429150842764520002042769470698041775832209097020291657347251582904630910359037842977572651720877244740952267166306005469716387943171196873484688738186656751279298575016363411314627530499019135646823804329970695770150789337728658035712790913767420805655493624646
diff --git a/src/pkg/compress/zlib/example_test.go b/src/pkg/compress/zlib/example_test.go
new file mode 100644
index 0000000..b934ffa
--- /dev/null
+++ b/src/pkg/compress/zlib/example_test.go
@@ -0,0 +1,37 @@
+// 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 zlib_test
+
+import (
+	"bytes"
+	"compress/zlib"
+	"fmt"
+	"io"
+	"os"
+)
+
+func ExampleNewWriter() {
+	var b bytes.Buffer
+
+	w := zlib.NewWriter(&b)
+	w.Write([]byte("hello, world\n"))
+	w.Close()
+	fmt.Println(b.Bytes())
+	// Output: [120 156 202 72 205 201 201 215 81 40 207 47 202 73 225 2 4 0 0 255 255 33 231 4 147]
+}
+
+func ExampleNewReader() {
+	buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207,
+		47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147}
+	b := bytes.NewBuffer(buff)
+
+	r, err := zlib.NewReader(b)
+	if err != nil {
+		panic(err)
+	}
+	io.Copy(os.Stdout, r)
+	// Output: hello, world
+	r.Close()
+}
diff --git a/src/pkg/compress/zlib/reader.go b/src/pkg/compress/zlib/reader.go
index f38ef5a..d54746f 100644
--- a/src/pkg/compress/zlib/reader.go
+++ b/src/pkg/compress/zlib/reader.go
@@ -11,7 +11,7 @@ and compress during writing.  For example, to write compressed data
 to a buffer:
 
 	var b bytes.Buffer
-	w, err := zlib.NewWriter(&b)
+	w := zlib.NewWriter(&b)
 	w.Write([]byte("hello, world\n"))
 	w.Close()
 
diff --git a/src/pkg/container/heap/example_intheap_test.go b/src/pkg/container/heap/example_intheap_test.go
new file mode 100644
index 0000000..e718cbc
--- /dev/null
+++ b/src/pkg/container/heap/example_intheap_test.go
@@ -0,0 +1,43 @@
+// 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.
+
+// This example demonstrates an integer heap built using the heap interface.
+package heap_test
+
+import (
+	"container/heap"
+	"fmt"
+)
+
+// An IntHeap is a min-heap of ints.
+type IntHeap []int
+
+func (h IntHeap) Len() int           { return len(h) }
+func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
+func (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
+
+func (h *IntHeap) Push(x interface{}) {
+	// Push and Pop use pointer receivers because they modify the slice's length,
+	// not just its contents.
+	*h = append(*h, x.(int))
+}
+
+func (h *IntHeap) Pop() interface{} {
+	old := *h
+	n := len(old)
+	x := old[n-1]
+	*h = old[0 : n-1]
+	return x
+}
+
+// This example inserts several ints into an IntHeap and removes them in order of priority.
+func Example_intHeap() {
+	h := &IntHeap{2, 1, 5}
+	heap.Init(h)
+	heap.Push(h, 3)
+	for h.Len() > 0 {
+		fmt.Printf("%d ", heap.Pop(h))
+	}
+	// Output: 1 2 3 5
+}
diff --git a/src/pkg/container/heap/example_pq_test.go b/src/pkg/container/heap/example_pq_test.go
new file mode 100644
index 0000000..8cbeb8d
--- /dev/null
+++ b/src/pkg/container/heap/example_pq_test.go
@@ -0,0 +1,95 @@
+// 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.
+
+// This example demonstrates a priority queue built using the heap interface.
+package heap_test
+
+import (
+	"container/heap"
+	"fmt"
+)
+
+// An Item is something we manage in a priority queue.
+type Item struct {
+	value    string // The value of the item; arbitrary.
+	priority int    // The priority of the item in the queue.
+	// The index is needed by update and is maintained by the heap.Interface methods.
+	index int // The index of the item in the heap.
+}
+
+// A PriorityQueue implements heap.Interface and holds Items.
+type PriorityQueue []*Item
+
+func (pq PriorityQueue) Len() int { return len(pq) }
+
+func (pq PriorityQueue) Less(i, j int) bool {
+	// We want Pop to give us the highest, not lowest, priority so we use greater than here.
+	return pq[i].priority > pq[j].priority
+}
+
+func (pq PriorityQueue) Swap(i, j int) {
+	pq[i], pq[j] = pq[j], pq[i]
+	pq[i].index = i
+	pq[j].index = j
+}
+
+func (pq *PriorityQueue) Push(x interface{}) {
+	n := len(*pq)
+	item := x.(*Item)
+	item.index = n
+	*pq = append(*pq, item)
+}
+
+func (pq *PriorityQueue) Pop() interface{} {
+	old := *pq
+	n := len(old)
+	item := old[n-1]
+	item.index = -1 // for safety
+	*pq = old[0 : n-1]
+	return item
+}
+
+// update modifies the priority and value of an Item in the queue.
+func (pq *PriorityQueue) update(item *Item, value string, priority int) {
+	heap.Remove(pq, item.index)
+	item.value = value
+	item.priority = priority
+	heap.Push(pq, item)
+}
+
+// This example inserts some items into a PriorityQueue, manipulates an item,
+// and then removes the items in priority order.
+func Example_priorityQueue() {
+	// Some items and their priorities.
+	items := map[string]int{
+		"banana": 3, "apple": 2, "pear": 4,
+	}
+
+	// Create a priority queue and put the items in it.
+	pq := &PriorityQueue{}
+	heap.Init(pq)
+	for value, priority := range items {
+		item := &Item{
+			value:    value,
+			priority: priority,
+		}
+		heap.Push(pq, item)
+	}
+
+	// Insert a new item and then modify its priority.
+	item := &Item{
+		value:    "orange",
+		priority: 1,
+	}
+	heap.Push(pq, item)
+	pq.update(item, item.value, 5)
+
+	// Take the items out; they arrive in decreasing priority order.
+	for pq.Len() > 0 {
+		item := heap.Pop(pq).(*Item)
+		fmt.Printf("%.2d:%s ", item.priority, item.value)
+	}
+	// Output:
+	// 05:orange 04:pear 03:banana 02:apple
+}
diff --git a/src/pkg/container/heap/example_test.go b/src/pkg/container/heap/example_test.go
deleted file mode 100644
index 2050bc8..0000000
--- a/src/pkg/container/heap/example_test.go
+++ /dev/null
@@ -1,105 +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.
-
-// This example demonstrates a priority queue built using the heap interface.
-package heap_test
-
-import (
-	"container/heap"
-	"fmt"
-)
-
-// An Item is something we manage in a priority queue.
-type Item struct {
-	value    string // The value of the item; arbitrary.
-	priority int    // The priority of the item in the queue.
-	// The index is needed by changePriority and is maintained by the heap.Interface methods.
-	index int // The index of the item in the heap.
-}
-
-// A PriorityQueue implements heap.Interface and holds Items.
-type PriorityQueue []*Item
-
-func (pq PriorityQueue) Len() int { return len(pq) }
-
-func (pq PriorityQueue) Less(i, j int) bool {
-	// We want Pop to give us the highest, not lowest, priority so we use greater than here.
-	return pq[i].priority > pq[j].priority
-}
-
-func (pq PriorityQueue) Swap(i, j int) {
-	pq[i], pq[j] = pq[j], pq[i]
-	pq[i].index = i
-	pq[j].index = j
-}
-
-func (pq *PriorityQueue) Push(x interface{}) {
-	// Push and Pop use pointer receivers because they modify the slice's length,
-	// not just its contents.
-	// To simplify indexing expressions in these methods, we save a copy of the
-	// slice object. We could instead write (*pq)[i].
-	a := *pq
-	n := len(a)
-	a = a[0 : n+1]
-	item := x.(*Item)
-	item.index = n
-	a[n] = item
-	*pq = a
-}
-
-func (pq *PriorityQueue) Pop() interface{} {
-	a := *pq
-	n := len(a)
-	item := a[n-1]
-	item.index = -1 // for safety
-	*pq = a[0 : n-1]
-	return item
-}
-
-// update is not used by the example but shows how to take the top item from
-// the queue, update its priority and value, and put it back.
-func (pq *PriorityQueue) update(value string, priority int) {
-	item := heap.Pop(pq).(*Item)
-	item.value = value
-	item.priority = priority
-	heap.Push(pq, item)
-}
-
-// changePriority is not used by the example but shows how to change the
-// priority of an arbitrary item.
-func (pq *PriorityQueue) changePriority(item *Item, priority int) {
-	heap.Remove(pq, item.index)
-	item.priority = priority
-	heap.Push(pq, item)
-}
-
-// This example pushes 10 items into a PriorityQueue and takes them out in
-// order of priority.
-func Example() {
-	const nItem = 10
-	// Random priorities for the items (a permutation of 0..9, times 11)).
-	priorities := [nItem]int{
-		77, 22, 44, 55, 11, 88, 33, 99, 00, 66,
-	}
-	values := [nItem]string{
-		"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
-	}
-	// Create a priority queue and put some items in it.
-	pq := make(PriorityQueue, 0, nItem)
-	for i := 0; i < cap(pq); i++ {
-		item := &Item{
-			value:    values[i],
-			priority: priorities[i],
-		}
-		heap.Push(&pq, item)
-	}
-	// Take the items out; should arrive in decreasing priority order.
-	// For example, the highest priority (99) is the seventh item, so output starts with 99:"seven".
-	for i := 0; i < nItem; i++ {
-		item := heap.Pop(&pq).(*Item)
-		fmt.Printf("%.2d:%s ", item.priority, item.value)
-	}
-	// Output:
-	// 99:seven 88:five 77:zero 66:nine 55:three 44:two 33:six 22:one 11:four 00:eight
-}
diff --git a/src/pkg/container/heap/heap.go b/src/pkg/container/heap/heap.go
index 67018e6..c37e50e 100644
--- a/src/pkg/container/heap/heap.go
+++ b/src/pkg/container/heap/heap.go
@@ -4,13 +4,13 @@
 
 // Package heap provides heap operations for any type that implements
 // heap.Interface. A heap is a tree with the property that each node is the
-// highest-valued node in its subtree.
+// minimum-valued node in its subtree.
 //
 // A heap is a common way to implement a priority queue. To build a priority
 // queue, implement the Heap interface with the (negative) priority as the
 // ordering for the Less method, so Push adds items while Pop removes the
 // highest-priority item from the queue. The Examples include such an
-// implementation; the file example_test.go has the complete source.
+// implementation; the file example_pq_test.go has the complete source.
 //
 package heap
 
@@ -79,7 +79,7 @@ func Remove(h Interface, i int) interface{} {
 func up(h Interface, j int) {
 	for {
 		i := (j - 1) / 2 // parent
-		if i == j || h.Less(i, j) {
+		if i == j || !h.Less(j, i) {
 			break
 		}
 		h.Swap(i, j)
@@ -90,14 +90,14 @@ func up(h Interface, j int) {
 func down(h Interface, i, n int) {
 	for {
 		j1 := 2*i + 1
-		if j1 >= n {
+		if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
 			break
 		}
 		j := j1 // left child
 		if j2 := j1 + 1; j2 < n && !h.Less(j1, j2) {
 			j = j2 // = 2*i + 2  // right child
 		}
-		if h.Less(i, j) {
+		if !h.Less(j, i) {
 			break
 		}
 		h.Swap(i, j)
diff --git a/src/pkg/container/heap/heap_test.go b/src/pkg/container/heap/heap_test.go
index cb31ef6..274d587 100644
--- a/src/pkg/container/heap/heap_test.go
+++ b/src/pkg/container/heap/heap_test.go
@@ -2,10 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package heap_test
+package heap
 
 import (
-	. "container/heap"
 	"testing"
 )
 
@@ -170,3 +169,16 @@ func TestRemove2(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkDup(b *testing.B) {
+	const n = 10000
+	h := make(myHeap, n)
+	for i := 0; i < b.N; i++ {
+		for j := 0; j < n; j++ {
+			Push(&h, 0) // all elements are the same
+		}
+		for h.Len() > 0 {
+			Pop(&h)
+		}
+	}
+}
diff --git a/src/pkg/container/list/example_test.go b/src/pkg/container/list/example_test.go
new file mode 100644
index 0000000..7361212
--- /dev/null
+++ b/src/pkg/container/list/example_test.go
@@ -0,0 +1,30 @@
+// 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 list_test
+
+import (
+	"container/list"
+	"fmt"
+)
+
+func Example() {
+	// Create a new list and put some numbers in it.
+	l := list.New()
+	e4 := l.PushBack(4)
+	e1 := l.PushFront(1)
+	l.InsertBefore(3, e4)
+	l.InsertAfter(2, e1)
+
+	// Iterate through list and and print its contents.
+	for e := l.Front(); e != nil; e = e.Next() {
+		fmt.Println(e.Value)
+	}
+
+	// Output:
+	// 1
+	// 2
+	// 3
+	// 4
+}
diff --git a/src/pkg/container/list/list.go b/src/pkg/container/list/list.go
index a3fd4b3..562a5ba 100644
--- a/src/pkg/container/list/list.go
+++ b/src/pkg/container/list/list.go
@@ -11,201 +11,187 @@
 //
 package list
 
-// Element is an element in the linked list.
+// Element is an element of a linked list.
 type Element struct {
 	// Next and previous pointers in the doubly-linked list of elements.
-	// The front of the list has prev = nil, and the back has next = nil.
+	// To simplify the implementation, internally a list l is implemented
+	// as a ring, such that &l.root is both the next element of the last
+	// list element (l.Back()) and the previous element of the first list
+	// element (l.Front()).
 	next, prev *Element
 
 	// The list to which this element belongs.
 	list *List
 
-	// The contents of this list element.
+	// The value stored with this element.
 	Value interface{}
 }
 
 // Next returns the next list element or nil.
-func (e *Element) Next() *Element { return e.next }
+func (e *Element) Next() *Element {
+	if p := e.next; p != &e.list.root {
+		return p
+	}
+	return nil
+}
 
 // Prev returns the previous list element or nil.
-func (e *Element) Prev() *Element { return e.prev }
+func (e *Element) Prev() *Element {
+	if p := e.prev; p != &e.list.root {
+		return p
+	}
+	return nil
+}
 
 // List represents a doubly linked list.
 // The zero value for List is an empty list ready to use.
 type List struct {
-	front, back *Element
-	len         int
+	root Element // sentinel list element, only &root, root.prev, and root.next are used
+	len  int     // current list length excluding (this) sentinel element
 }
 
-// Init initializes or clears a List.
+// Init initializes or clears list l.
 func (l *List) Init() *List {
-	l.front = nil
-	l.back = nil
+	l.root.next = &l.root
+	l.root.prev = &l.root
 	l.len = 0
 	return l
 }
 
 // New returns an initialized list.
-func New() *List { return new(List) }
-
-// Front returns the first element in the list.
-func (l *List) Front() *Element { return l.front }
+func New() *List { return new(List).Init() }
 
-// Back returns the last element in the list.
-func (l *List) Back() *Element { return l.back }
+// Len returns the number of elements of list l.
+func (l *List) Len() int { return l.len }
 
-// Remove removes the element from the list
-// and returns its Value.
-func (l *List) Remove(e *Element) interface{} {
-	l.remove(e)
-	e.list = nil // do what remove does not
-	return e.Value
+// Front returns the first element of list l or nil
+func (l *List) Front() *Element {
+	if l.len == 0 {
+		return nil
+	}
+	return l.root.next
 }
 
-// remove the element from the list, but do not clear the Element's list field.
-// This is so that other List methods may use remove when relocating Elements
-// without needing to restore the list field.
-func (l *List) remove(e *Element) {
-	if e.list != l {
-		return
-	}
-	if e.prev == nil {
-		l.front = e.next
-	} else {
-		e.prev.next = e.next
-	}
-	if e.next == nil {
-		l.back = e.prev
-	} else {
-		e.next.prev = e.prev
+// Back returns the last element of list l or nil.
+func (l *List) Back() *Element {
+	if l.len == 0 {
+		return nil
 	}
-
-	e.prev = nil
-	e.next = nil
-	l.len--
+	return l.root.prev
 }
 
-func (l *List) insertBefore(e *Element, mark *Element) {
-	if mark.prev == nil {
-		// new front of the list
-		l.front = e
-	} else {
-		mark.prev.next = e
+// lazyInit lazily initializes a zero List value.
+func (l *List) lazyInit() {
+	if l.root.next == nil {
+		l.Init()
 	}
-	e.prev = mark.prev
-	mark.prev = e
-	e.next = mark
-	l.len++
 }
 
-func (l *List) insertAfter(e *Element, mark *Element) {
-	if mark.next == nil {
-		// new back of the list
-		l.back = e
-	} else {
-		mark.next.prev = e
-	}
-	e.next = mark.next
-	mark.next = e
-	e.prev = mark
+// insert inserts e after at, increments l.len, and returns e.
+func (l *List) insert(e, at *Element) *Element {
+	n := at.next
+	at.next = e
+	e.prev = at
+	e.next = n
+	n.prev = e
+	e.list = l
 	l.len++
+	return e
 }
 
-func (l *List) insertFront(e *Element) {
-	if l.front == nil {
-		// empty list
-		l.front, l.back = e, e
-		e.prev, e.next = nil, nil
-		l.len = 1
-		return
-	}
-	l.insertBefore(e, l.front)
+// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
+func (l *List) insertValue(v interface{}, at *Element) *Element {
+	return l.insert(&Element{Value: v}, at)
 }
 
-func (l *List) insertBack(e *Element) {
-	if l.back == nil {
-		// empty list
-		l.front, l.back = e, e
-		e.prev, e.next = nil, nil
-		l.len = 1
-		return
+// remove removes e from its list, decrements l.len, and returns e.
+func (l *List) remove(e *Element) *Element {
+	e.prev.next = e.next
+	e.next.prev = e.prev
+	e.next = nil // avoid memory leaks
+	e.prev = nil // avoid memory leaks
+	e.list = nil
+	l.len--
+	return e
+}
+
+// Remove removes e from l if e is an element of list l.
+// It returns the element value e.Value.
+func (l *List) Remove(e *Element) interface{} {
+	if e.list == l {
+		// if e.list == l, l must have been initialized when e was inserted
+		// in l or l == nil (e is a zero Element) and l.remove will crash
+		l.remove(e)
 	}
-	l.insertAfter(e, l.back)
+	return e.Value
 }
 
-// PushFront inserts the value at the front of the list and returns a new Element containing the value.
-func (l *List) PushFront(value interface{}) *Element {
-	e := &Element{nil, nil, l, value}
-	l.insertFront(e)
-	return e
+// Pushfront inserts a new element e with value v at the front of list l and returns e.
+func (l *List) PushFront(v interface{}) *Element {
+	l.lazyInit()
+	return l.insertValue(v, &l.root)
 }
 
-// PushBack inserts the value at the back of the list and returns a new Element containing the value.
-func (l *List) PushBack(value interface{}) *Element {
-	e := &Element{nil, nil, l, value}
-	l.insertBack(e)
-	return e
+// PushBack inserts a new element e with value v at the back of list l and returns e.
+func (l *List) PushBack(v interface{}) *Element {
+	l.lazyInit()
+	return l.insertValue(v, l.root.prev)
 }
 
-// InsertBefore inserts the value immediately before mark and returns a new Element containing the value.
-func (l *List) InsertBefore(value interface{}, mark *Element) *Element {
+// InsertBefore inserts a new element e with value v immediately before mark and returns e.
+// If mark is not an element of l, the list is not modified.
+func (l *List) InsertBefore(v interface{}, mark *Element) *Element {
 	if mark.list != l {
 		return nil
 	}
-	e := &Element{nil, nil, l, value}
-	l.insertBefore(e, mark)
-	return e
+	// see comment in List.Remove about initialization of l
+	return l.insertValue(v, mark.prev)
 }
 
-// InsertAfter inserts the value immediately after mark and returns a new Element containing the value.
-func (l *List) InsertAfter(value interface{}, mark *Element) *Element {
+// InsertAfter inserts a new element e with value v immediately after mark and returns e.
+// If mark is not an element of l, the list is not modified.
+func (l *List) InsertAfter(v interface{}, mark *Element) *Element {
 	if mark.list != l {
 		return nil
 	}
-	e := &Element{nil, nil, l, value}
-	l.insertAfter(e, mark)
-	return e
+	// see comment in List.Remove about initialization of l
+	return l.insertValue(v, mark)
 }
 
-// MoveToFront moves the element to the front of the list.
+// MoveToFront moves element e to the front of list l.
+// If e is not an element of l, the list is not modified.
 func (l *List) MoveToFront(e *Element) {
-	if e.list != l || l.front == e {
+	if e.list != l || l.root.next == e {
 		return
 	}
-	l.remove(e)
-	l.insertFront(e)
+	// see comment in List.Remove about initialization of l
+	l.insert(l.remove(e), &l.root)
 }
 
-// MoveToBack moves the element to the back of the list.
+// MoveToBack moves element e to the back of list l.
+// If e is not an element of l, the list is not modified.
 func (l *List) MoveToBack(e *Element) {
-	if e.list != l || l.back == e {
+	if e.list != l || l.root.prev == e {
 		return
 	}
-	l.remove(e)
-	l.insertBack(e)
+	// see comment in List.Remove about initialization of l
+	l.insert(l.remove(e), l.root.prev)
 }
 
-// Len returns the number of elements in the list.
-func (l *List) Len() int { return l.len }
-
-// PushBackList inserts each element of ol at the back of the list.
-func (l *List) PushBackList(ol *List) {
-	last := ol.Back()
-	for e := ol.Front(); e != nil; e = e.Next() {
-		l.PushBack(e.Value)
-		if e == last {
-			break
-		}
+// PushBackList inserts a copy of an other list at the back of list l.
+// The lists l and other may be the same.
+func (l *List) PushBackList(other *List) {
+	l.lazyInit()
+	for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
+		l.insertValue(e.Value, l.root.prev)
 	}
 }
 
-// PushFrontList inserts each element of ol at the front of the list. The ordering of the passed list is preserved.
-func (l *List) PushFrontList(ol *List) {
-	first := ol.Front()
-	for e := ol.Back(); e != nil; e = e.Prev() {
-		l.PushFront(e.Value)
-		if e == first {
-			break
-		}
+// PushFrontList inserts a copy of an other list at the front of list l.
+// The lists l and other may be the same.
+func (l *List) PushFrontList(other *List) {
+	l.lazyInit()
+	for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
+		l.insertValue(e.Value, &l.root)
 	}
 }
diff --git a/src/pkg/container/list/list_test.go b/src/pkg/container/list/list_test.go
index 1d44ff8..b4fc77d 100644
--- a/src/pkg/container/list/list_test.go
+++ b/src/pkg/container/list/list_test.go
@@ -4,65 +4,75 @@
 
 package list
 
-import (
-	"testing"
-)
+import "testing"
+
+func checkListLen(t *testing.T, l *List, len int) bool {
+	if n := l.Len(); n != len {
+		t.Errorf("l.Len() = %d, want %d", n, len)
+		return false
+	}
+	return true
+}
 
 func checkListPointers(t *testing.T, l *List, es []*Element) {
-	if len(es) == 0 {
-		if l.front != nil || l.back != nil {
-			t.Errorf("l.front/l.back = %v/%v should be nil/nil", l.front, l.back)
-		}
+	root := &l.root
+
+	if !checkListLen(t, l, len(es)) {
 		return
 	}
 
-	if l.front != es[0] {
-		t.Errorf("l.front = %v, want %v", l.front, es[0])
-	}
-	if last := es[len(es)-1]; l.back != last {
-		t.Errorf("l.back = %v, want %v", l.back, last)
+	// zero length lists must be the zero value or properly initialized (sentinel circle)
+	if len(es) == 0 {
+		if l.root.next != nil && l.root.next != root || l.root.prev != nil && l.root.prev != root {
+			t.Errorf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p", l.root.next, l.root.prev, root)
+		}
+		return
 	}
+	// len(es) > 0
 
+	// check internal and external prev/next connections
 	for i, e := range es {
-		var e_prev, e_next *Element = nil, nil
+		prev := root
+		Prev := (*Element)(nil)
 		if i > 0 {
-			e_prev = es[i-1]
+			prev = es[i-1]
+			Prev = prev
+		}
+		if p := e.prev; p != prev {
+			t.Errorf("elt[%d](%p).prev = %p, want %p", i, e, p, prev)
+		}
+		if p := e.Prev(); p != Prev {
+			t.Errorf("elt[%d](%p).Prev() = %p, want %p", i, e, p, Prev)
 		}
+
+		next := root
+		Next := (*Element)(nil)
 		if i < len(es)-1 {
-			e_next = es[i+1]
+			next = es[i+1]
+			Next = next
 		}
-		if e.prev != e_prev {
-			t.Errorf("elt #%d (%v) has prev=%v, want %v", i, e, e.prev, e_prev)
+		if n := e.next; n != next {
+			t.Errorf("elt[%d](%p).next = %p, want %p", i, e, n, next)
 		}
-		if e.next != e_next {
-			t.Errorf("elt #%d (%v) has next=%v, want %v", i, e, e.next, e_next)
+		if n := e.Next(); n != Next {
+			t.Errorf("elt[%d](%p).Next() = %p, want %p", i, e, n, Next)
 		}
 	}
 }
 
-func checkListLen(t *testing.T, l *List, n int) {
-	if an := l.Len(); an != n {
-		t.Errorf("l.Len() = %d, want %d", an, n)
-	}
-}
-
 func TestList(t *testing.T) {
 	l := New()
 	checkListPointers(t, l, []*Element{})
-	checkListLen(t, l, 0)
 
 	// Single element list
 	e := l.PushFront("a")
-	checkListLen(t, l, 1)
 	checkListPointers(t, l, []*Element{e})
 	l.MoveToFront(e)
 	checkListPointers(t, l, []*Element{e})
 	l.MoveToBack(e)
 	checkListPointers(t, l, []*Element{e})
-	checkListLen(t, l, 1)
 	l.Remove(e)
 	checkListPointers(t, l, []*Element{})
-	checkListLen(t, l, 0)
 
 	// Bigger list
 	e2 := l.PushFront(2)
@@ -70,11 +80,9 @@ func TestList(t *testing.T) {
 	e3 := l.PushBack(3)
 	e4 := l.PushBack("banana")
 	checkListPointers(t, l, []*Element{e1, e2, e3, e4})
-	checkListLen(t, l, 4)
 
 	l.Remove(e2)
 	checkListPointers(t, l, []*Element{e1, e3, e4})
-	checkListLen(t, l, 3)
 
 	l.MoveToFront(e3) // move from middle
 	checkListPointers(t, l, []*Element{e3, e1, e4})
@@ -121,7 +129,7 @@ func TestList(t *testing.T) {
 		}
 	}
 	if sum != 4 {
-		t.Errorf("sum over l.Iter() = %d, want 4", sum)
+		t.Errorf("sum over l = %d, want 4", sum)
 	}
 
 	// Clear all elements by iterating
@@ -131,19 +139,18 @@ func TestList(t *testing.T) {
 		l.Remove(e)
 	}
 	checkListPointers(t, l, []*Element{})
-	checkListLen(t, l, 0)
 }
 
 func checkList(t *testing.T, l *List, es []interface{}) {
-	if l.Len() != len(es) {
-		t.Errorf("list has len=%v, want %v", l.Len(), len(es))
+	if !checkListLen(t, l, len(es)) {
 		return
 	}
+
 	i := 0
 	for e := l.Front(); e != nil; e = e.Next() {
 		le := e.Value.(int)
 		if le != es[i] {
-			t.Errorf("elt #%d has value=%v, want %v", i, le, es[i])
+			t.Errorf("elt[%d].Value = %v, want %v", i, le, es[i])
 		}
 		i++
 	}
@@ -202,8 +209,27 @@ func TestRemove(t *testing.T) {
 	e := l.Front()
 	l.Remove(e)
 	checkListPointers(t, l, []*Element{e2})
-	checkListLen(t, l, 1)
 	l.Remove(e)
 	checkListPointers(t, l, []*Element{e2})
-	checkListLen(t, l, 1)
+}
+
+func TestIssue4103(t *testing.T) {
+	l1 := New()
+	l1.PushBack(1)
+	l1.PushBack(2)
+
+	l2 := New()
+	l2.PushBack(3)
+	l2.PushBack(4)
+
+	e := l1.Front()
+	l2.Remove(e) // l2 should not change because e is not an element of l2
+	if n := l2.Len(); n != 2 {
+		t.Errorf("l2.Len() = %d, want 2", n)
+	}
+
+	l1.InsertBefore(8, e)
+	if n := l1.Len(); n != 3 {
+		t.Errorf("l1.Len() = %d, want 3", n)
+	}
 }
diff --git a/src/pkg/container/ring/ring.go b/src/pkg/container/ring/ring.go
index 1d96918..6d3b3e5 100644
--- a/src/pkg/container/ring/ring.go
+++ b/src/pkg/container/ring/ring.go
@@ -74,7 +74,7 @@ func New(n int) *Ring {
 	return r
 }
 
-// Link connects ring r with with ring s such that r.Next()
+// Link connects ring r with ring s such that r.Next()
 // becomes s and returns the original value for r.Next().
 // r must not be empty.
 //
diff --git a/src/pkg/crypto/aes/aes_test.go b/src/pkg/crypto/aes/aes_test.go
index e500c66..6261dd0 100644
--- a/src/pkg/crypto/aes/aes_test.go
+++ b/src/pkg/crypto/aes/aes_test.go
@@ -221,7 +221,10 @@ L:
 		if tt.dec != nil {
 			dec = make([]uint32, len(tt.dec))
 		}
-		expandKey(tt.key, enc, dec)
+		// This test could only test Go version of expandKey because asm
+		// version might use different memory layout for expanded keys
+		// This is OK because we don't expose expanded keys to the outside
+		expandKeyGo(tt.key, enc, dec)
 		for j, v := range enc {
 			if v != tt.enc[j] {
 				t.Errorf("key %d: enc[%d] = %#x, want %#x", i, j, v, tt.enc[j])
@@ -352,15 +355,39 @@ func TestCipherDecrypt(t *testing.T) {
 }
 
 func BenchmarkEncrypt(b *testing.B) {
-	b.StopTimer()
 	tt := encryptTests[0]
 	c, err := NewCipher(tt.key)
 	if err != nil {
 		b.Fatal("NewCipher:", err)
 	}
 	out := make([]byte, len(tt.in))
-	b.StartTimer()
+	b.SetBytes(int64(len(out)))
+	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		c.Encrypt(out, tt.in)
 	}
 }
+
+func BenchmarkDecrypt(b *testing.B) {
+	tt := encryptTests[0]
+	c, err := NewCipher(tt.key)
+	if err != nil {
+		b.Fatal("NewCipher:", err)
+	}
+	out := make([]byte, len(tt.out))
+	b.SetBytes(int64(len(out)))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		c.Decrypt(out, tt.out)
+	}
+}
+
+func BenchmarkExpand(b *testing.B) {
+	tt := encryptTests[0]
+	n := len(tt.key) + 28
+	c := &aesCipher{make([]uint32, n), make([]uint32, n)}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		expandKey(tt.key, c.enc, c.dec)
+	}
+}
diff --git a/src/pkg/crypto/aes/asm_amd64.s b/src/pkg/crypto/aes/asm_amd64.s
new file mode 100644
index 0000000..25decf9
--- /dev/null
+++ b/src/pkg/crypto/aes/asm_amd64.s
@@ -0,0 +1,287 @@
+// 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.
+
+// func hasAsm() bool
+// returns whether AES-NI is supported
+TEXT ·hasAsm(SB),7,$0
+	XORQ AX, AX
+	INCL AX
+	CPUID
+	SHRQ $25, CX
+	ANDQ $1, CX
+	MOVB CX, ret+0(FP)
+	RET
+
+// func encryptBlockAsm(nr int, xk *uint32, dst, src *byte)
+TEXT ·encryptBlockAsm(SB),7,$0
+	MOVQ nr+0(FP), CX
+	MOVQ xk+8(FP), AX
+	MOVQ dst+16(FP), DX
+	MOVQ src+24(FP), BX
+	MOVUPS 0(AX), X1
+	MOVUPS 0(BX), X0
+	ADDQ $16, AX
+	PXOR X1, X0
+	SUBQ $12, CX
+	JE Lenc196
+	JB Lenc128
+Lenc256:
+	MOVUPS 0(AX), X1
+	AESENC X1, X0
+	MOVUPS 16(AX), X1
+	AESENC X1, X0
+	ADDQ $32, AX
+Lenc196:
+	MOVUPS 0(AX), X1
+	AESENC X1, X0
+	MOVUPS 16(AX), X1
+	AESENC X1, X0
+	ADDQ $32, AX
+Lenc128:
+	MOVUPS 0(AX), X1
+	AESENC X1, X0
+	MOVUPS 16(AX), X1
+	AESENC X1, X0
+	MOVUPS 32(AX), X1
+	AESENC X1, X0
+	MOVUPS 48(AX), X1
+	AESENC X1, X0
+	MOVUPS 64(AX), X1
+	AESENC X1, X0
+	MOVUPS 80(AX), X1
+	AESENC X1, X0
+	MOVUPS 96(AX), X1
+	AESENC X1, X0
+	MOVUPS 112(AX), X1
+	AESENC X1, X0
+	MOVUPS 128(AX), X1
+	AESENC X1, X0
+	MOVUPS 144(AX), X1
+	AESENCLAST X1, X0
+	MOVUPS X0, 0(DX)
+	RET
+
+// func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
+TEXT ·decryptBlockAsm(SB),7,$0
+	MOVQ nr+0(FP), CX
+	MOVQ xk+8(FP), AX
+	MOVQ dst+16(FP), DX
+	MOVQ src+24(FP), BX
+	MOVUPS 0(AX), X1
+	MOVUPS 0(BX), X0
+	ADDQ $16, AX
+	PXOR X1, X0
+	SUBQ $12, CX
+	JE Ldec196
+	JB Ldec128
+Ldec256:
+	MOVUPS 0(AX), X1
+	AESDEC X1, X0
+	MOVUPS 16(AX), X1
+	AESDEC X1, X0
+	ADDQ $32, AX
+Ldec196:
+	MOVUPS 0(AX), X1
+	AESDEC X1, X0
+	MOVUPS 16(AX), X1
+	AESDEC X1, X0
+	ADDQ $32, AX
+Ldec128:
+	MOVUPS 0(AX), X1
+	AESDEC X1, X0
+	MOVUPS 16(AX), X1
+	AESDEC X1, X0
+	MOVUPS 32(AX), X1
+	AESDEC X1, X0
+	MOVUPS 48(AX), X1
+	AESDEC X1, X0
+	MOVUPS 64(AX), X1
+	AESDEC X1, X0
+	MOVUPS 80(AX), X1
+	AESDEC X1, X0
+	MOVUPS 96(AX), X1
+	AESDEC X1, X0
+	MOVUPS 112(AX), X1
+	AESDEC X1, X0
+	MOVUPS 128(AX), X1
+	AESDEC X1, X0
+	MOVUPS 144(AX), X1
+	AESDECLAST X1, X0
+	MOVUPS X0, 0(DX)
+	RET
+
+// func expandKeyAsm(nr int, key *byte, enc, dec *uint32) {
+// Note that round keys are stored in uint128 format, not uint32
+TEXT ·expandKeyAsm(SB),7,$0
+	MOVQ nr+0(FP), CX
+	MOVQ key+8(FP), AX
+	MOVQ enc+16(FP), BX
+	MOVQ dec+24(FP), DX
+	MOVUPS (AX), X0
+	// enc
+	MOVUPS X0, (BX)
+	ADDQ $16, BX
+	PXOR X4, X4 // _expand_key_* expect X4 to be zero
+	CMPL CX, $12
+	JE Lexp_enc196
+	JB Lexp_enc128
+Lexp_enc256:
+	MOVUPS 16(AX), X2
+	MOVUPS X2, (BX)
+	ADDQ $16, BX
+	AESKEYGENASSIST $0x01, X2, X1
+	CALL _expand_key_256a<>(SB)
+	AESKEYGENASSIST $0x01, X0, X1
+	CALL _expand_key_256b<>(SB)
+	AESKEYGENASSIST $0x02, X2, X1
+	CALL _expand_key_256a<>(SB)
+	AESKEYGENASSIST $0x02, X0, X1
+	CALL _expand_key_256b<>(SB)
+	AESKEYGENASSIST $0x04, X2, X1
+	CALL _expand_key_256a<>(SB)
+	AESKEYGENASSIST $0x04, X0, X1
+	CALL _expand_key_256b<>(SB)
+	AESKEYGENASSIST $0x08, X2, X1
+	CALL _expand_key_256a<>(SB)
+	AESKEYGENASSIST $0x08, X0, X1
+	CALL _expand_key_256b<>(SB)
+	AESKEYGENASSIST $0x10, X2, X1
+	CALL _expand_key_256a<>(SB)
+	AESKEYGENASSIST $0x10, X0, X1
+	CALL _expand_key_256b<>(SB)
+	AESKEYGENASSIST $0x20, X2, X1
+	CALL _expand_key_256a<>(SB)
+	AESKEYGENASSIST $0x20, X0, X1
+	CALL _expand_key_256b<>(SB)
+	AESKEYGENASSIST $0x40, X2, X1
+	CALL _expand_key_256a<>(SB)
+	JMP Lexp_dec
+Lexp_enc196:
+	MOVQ 16(AX), X2
+	AESKEYGENASSIST $0x01, X2, X1
+	CALL _expand_key_192a<>(SB)
+	AESKEYGENASSIST $0x02, X2, X1
+	CALL _expand_key_192b<>(SB)
+	AESKEYGENASSIST $0x04, X2, X1
+	CALL _expand_key_192a<>(SB)
+	AESKEYGENASSIST $0x08, X2, X1
+	CALL _expand_key_192b<>(SB)
+	AESKEYGENASSIST $0x10, X2, X1
+	CALL _expand_key_192a<>(SB)
+	AESKEYGENASSIST $0x20, X2, X1
+	CALL _expand_key_192b<>(SB)
+	AESKEYGENASSIST $0x40, X2, X1
+	CALL _expand_key_192a<>(SB)
+	AESKEYGENASSIST $0x80, X2, X1
+	CALL _expand_key_192b<>(SB)
+	JMP Lexp_dec
+Lexp_enc128:
+	AESKEYGENASSIST $0x01, X0, X1
+	CALL _expand_key_128<>(SB)
+	AESKEYGENASSIST $0x02, X0, X1
+	CALL _expand_key_128<>(SB)
+	AESKEYGENASSIST $0x04, X0, X1
+	CALL _expand_key_128<>(SB)
+	AESKEYGENASSIST $0x08, X0, X1
+	CALL _expand_key_128<>(SB)
+	AESKEYGENASSIST $0x10, X0, X1
+	CALL _expand_key_128<>(SB)
+	AESKEYGENASSIST $0x20, X0, X1
+	CALL _expand_key_128<>(SB)
+	AESKEYGENASSIST $0x40, X0, X1
+	CALL _expand_key_128<>(SB)
+	AESKEYGENASSIST $0x80, X0, X1
+	CALL _expand_key_128<>(SB)
+	AESKEYGENASSIST $0x1b, X0, X1
+	CALL _expand_key_128<>(SB)
+	AESKEYGENASSIST $0x36, X0, X1
+	CALL _expand_key_128<>(SB)
+Lexp_dec:
+	// dec
+	SUBQ $16, BX
+	MOVUPS (BX), X1
+	MOVUPS X1, (DX)
+	DECQ CX
+Lexp_dec_loop:
+	MOVUPS -16(BX), X1
+	AESIMC X1, X0
+	MOVUPS X0, 16(DX)
+	SUBQ $16, BX
+	ADDQ $16, DX
+	DECQ CX
+	JNZ Lexp_dec_loop
+	MOVUPS -16(BX), X0
+	MOVUPS X0, 16(DX)
+	RET
+
+#define PSHUFD_X0_X0_ BYTE $0x66; BYTE $0x0f; BYTE $0x70; BYTE $0xc0
+#define PSHUFD_X1_X1_ BYTE $0x66; BYTE $0x0f; BYTE $0x70; BYTE $0xc9
+TEXT _expand_key_128<>(SB),7,$0
+	PSHUFD $0xff, X1, X1
+	SHUFPS $0x10, X0, X4
+	PXOR X4, X0
+	SHUFPS $0x8c, X0, X4
+	PXOR X4, X0
+	PXOR X1, X0
+	MOVUPS X0, (BX)
+	ADDQ $16, BX
+	RET
+
+#define PSLLDQ_X5_ BYTE $0x66; BYTE $0x0f; BYTE $0x73; BYTE $0xfd
+#define PSHUFD_X0_X3_ BYTE $0x66; BYTE $0x0f; BYTE $0x70; BYTE $0xd8
+TEXT _expand_key_192a<>(SB),7,$0
+	PSHUFD $0x55, X1, X1
+	SHUFPS $0x10, X0, X4
+	PXOR X4, X0
+	SHUFPS $0x8c, X0, X4
+	PXOR X4, X0
+	PXOR X1, X0
+
+	MOVAPS X2, X5
+	MOVAPS X2, X6
+	PSLLDQ_X5_; BYTE $0x4
+	PSHUFD $0xff, X0, X3
+	PXOR X3, X2
+	PXOR X5, X2
+
+	MOVAPS X0, X1
+	SHUFPS $0x44, X0, X6
+	MOVUPS X6, (BX)
+	SHUFPS $0x4e, X2, X1
+	MOVUPS X1, 16(BX)
+	ADDQ $32, BX
+	RET
+
+TEXT _expand_key_192b<>(SB),7,$0
+	PSHUFD $0x55, X1, X1
+	SHUFPS $0x10, X0, X4
+	PXOR X4, X0
+	SHUFPS $0x8c, X0, X4
+	PXOR X4, X0
+	PXOR X1, X0
+
+	MOVAPS X2, X5
+	PSLLDQ_X5_; BYTE $0x4
+	PSHUFD $0xff, X0, X3
+	PXOR X3, X2
+	PXOR X5, X2
+
+	MOVUPS X0, (BX)
+	ADDQ $16, BX
+	RET
+
+TEXT _expand_key_256a<>(SB),7,$0
+	JMP _expand_key_128<>(SB)
+
+TEXT _expand_key_256b<>(SB),7,$0
+	PSHUFD $0xaa, X1, X1
+	SHUFPS $0x10, X2, X4
+	PXOR X4, X2
+	SHUFPS $0x8c, X2, X4
+	PXOR X4, X2
+	PXOR X1, X2
+
+	MOVUPS X2, (BX)
+	ADDQ $16, BX
+	RET
diff --git a/src/pkg/crypto/aes/block.go b/src/pkg/crypto/aes/block.go
index b930787..57a7e9e 100644
--- a/src/pkg/crypto/aes/block.go
+++ b/src/pkg/crypto/aes/block.go
@@ -37,7 +37,7 @@
 package aes
 
 // Encrypt one block from src into dst, using the expanded key xk.
-func encryptBlock(xk []uint32, dst, src []byte) {
+func encryptBlockGo(xk []uint32, dst, src []byte) {
 	var s0, s1, s2, s3, t0, t1, t2, t3 uint32
 
 	s0 = uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
@@ -82,7 +82,7 @@ func encryptBlock(xk []uint32, dst, src []byte) {
 }
 
 // Decrypt one block from src into dst, using the expanded key xk.
-func decryptBlock(xk []uint32, dst, src []byte) {
+func decryptBlockGo(xk []uint32, dst, src []byte) {
 	var s0, s1, s2, s3, t0, t1, t2, t3 uint32
 
 	s0 = uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
@@ -139,7 +139,7 @@ func rotw(w uint32) uint32 { return w<<8 | w>>24 }
 
 // Key expansion algorithm.  See FIPS-197, Figure 11.
 // Their rcon[i] is our powx[i-1] << 24.
-func expandKey(key []byte, enc, dec []uint32) {
+func expandKeyGo(key []byte, enc, dec []uint32) {
 	// Encryption key setup.
 	var i int
 	nk := len(key) / 4
diff --git a/src/pkg/crypto/aes/cipher.go b/src/pkg/crypto/aes/cipher.go
index 7d307c9..d931134 100644
--- a/src/pkg/crypto/aes/cipher.go
+++ b/src/pkg/crypto/aes/cipher.go
@@ -45,6 +45,10 @@ func NewCipher(key []byte) (cipher.Block, error) {
 
 func (c *aesCipher) BlockSize() int { return BlockSize }
 
-func (c *aesCipher) Encrypt(dst, src []byte) { encryptBlock(c.enc, dst, src) }
+func (c *aesCipher) Encrypt(dst, src []byte) {
+	encryptBlock(c.enc, dst, src)
+}
 
-func (c *aesCipher) Decrypt(dst, src []byte) { decryptBlock(c.dec, dst, src) }
+func (c *aesCipher) Decrypt(dst, src []byte) {
+	decryptBlock(c.dec, dst, src)
+}
diff --git a/src/pkg/crypto/aes/cipher_asm.go b/src/pkg/crypto/aes/cipher_asm.go
new file mode 100644
index 0000000..21369fc
--- /dev/null
+++ b/src/pkg/crypto/aes/cipher_asm.go
@@ -0,0 +1,46 @@
+// 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 amd64
+
+package aes
+
+// defined in asm_$GOARCH.s
+func hasAsm() bool
+func encryptBlockAsm(nr int, xk *uint32, dst, src *byte)
+func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
+func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32)
+
+var useAsm = hasAsm()
+
+func encryptBlock(xk []uint32, dst, src []byte) {
+	if useAsm {
+		encryptBlockAsm(len(xk)/4-1, &xk[0], &dst[0], &src[0])
+	} else {
+		encryptBlockGo(xk, dst, src)
+	}
+}
+func decryptBlock(xk []uint32, dst, src []byte) {
+	if useAsm {
+		decryptBlockAsm(len(xk)/4-1, &xk[0], &dst[0], &src[0])
+	} else {
+		decryptBlockGo(xk, dst, src)
+	}
+}
+func expandKey(key []byte, enc, dec []uint32) {
+	if useAsm {
+		rounds := 10
+		switch len(key) {
+		case 128 / 8:
+			rounds = 10
+		case 192 / 8:
+			rounds = 12
+		case 256 / 8:
+			rounds = 14
+		}
+		expandKeyAsm(rounds, &key[0], &enc[0], &dec[0])
+	} else {
+		expandKeyGo(key, enc, dec)
+	}
+}
diff --git a/src/pkg/crypto/aes/cipher_generic.go b/src/pkg/crypto/aes/cipher_generic.go
new file mode 100644
index 0000000..1714e0f
--- /dev/null
+++ b/src/pkg/crypto/aes/cipher_generic.go
@@ -0,0 +1,19 @@
+// 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 !amd64
+
+package aes
+
+func encryptBlock(xk []uint32, dst, src []byte) {
+	encryptBlockGo(xk, dst, src)
+}
+
+func decryptBlock(xk []uint32, dst, src []byte) {
+	decryptBlockGo(xk, dst, src)
+}
+
+func expandKey(key []byte, enc, dec []uint32) {
+	expandKeyGo(key, enc, dec)
+}
diff --git a/src/pkg/crypto/cipher/cbc.go b/src/pkg/crypto/cipher/cbc.go
index a48929c..913a564 100644
--- a/src/pkg/crypto/cipher/cbc.go
+++ b/src/pkg/crypto/cipher/cbc.go
@@ -33,12 +33,21 @@ type cbcEncrypter cbc
 // mode, using the given Block. The length of iv must be the same as the
 // Block's block size.
 func NewCBCEncrypter(b Block, iv []byte) BlockMode {
+	if len(iv) != b.BlockSize() {
+		panic("cipher.NewCBCEncrypter: IV length must equal block size")
+	}
 	return (*cbcEncrypter)(newCBC(b, iv))
 }
 
 func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
 
 func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
+	if len(src)%x.blockSize != 0 {
+		panic("crypto/cipher: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
 	for len(src) > 0 {
 		for i := 0; i < x.blockSize; i++ {
 			x.iv[i] ^= src[i]
@@ -58,12 +67,21 @@ type cbcDecrypter cbc
 // mode, using the given Block. The length of iv must be the same as the
 // Block's block size and must match the iv used to encrypt the data.
 func NewCBCDecrypter(b Block, iv []byte) BlockMode {
+	if len(iv) != b.BlockSize() {
+		panic("cipher.NewCBCDecrypter: IV length must equal block size")
+	}
 	return (*cbcDecrypter)(newCBC(b, iv))
 }
 
 func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
 
 func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
+	if len(src)%x.blockSize != 0 {
+		panic("crypto/cipher: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
 	for len(src) > 0 {
 		x.b.Decrypt(x.tmp, src[:x.blockSize])
 		for i := 0; i < x.blockSize; i++ {
diff --git a/src/pkg/crypto/cipher/cfb.go b/src/pkg/crypto/cipher/cfb.go
index d14165a..99006b5 100644
--- a/src/pkg/crypto/cipher/cfb.go
+++ b/src/pkg/crypto/cipher/cfb.go
@@ -17,6 +17,9 @@ type cfb struct {
 // using the given Block. The iv must be the same length as the Block's block
 // size.
 func NewCFBEncrypter(block Block, iv []byte) Stream {
+	if len(iv) != block.BlockSize() {
+		panic("cipher.NewCBFEncrypter: IV length must equal block size")
+	}
 	return newCFB(block, iv, false)
 }
 
@@ -24,6 +27,9 @@ func NewCFBEncrypter(block Block, iv []byte) Stream {
 // using the given Block. The iv must be the same length as the Block's block
 // size.
 func NewCFBDecrypter(block Block, iv []byte) Stream {
+	if len(iv) != block.BlockSize() {
+		panic("cipher.NewCBFEncrypter: IV length must equal block size")
+	}
 	return newCFB(block, iv, true)
 }
 
diff --git a/src/pkg/crypto/cipher/cipher_test.go b/src/pkg/crypto/cipher/cipher_test.go
new file mode 100644
index 0000000..8da5bce
--- /dev/null
+++ b/src/pkg/crypto/cipher/cipher_test.go
@@ -0,0 +1,36 @@
+// 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 cipher_test
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"testing"
+)
+
+func TestCryptBlocks(t *testing.T) {
+	buf := make([]byte, 16)
+	block, _ := aes.NewCipher(buf)
+
+	mode := cipher.NewCBCDecrypter(block, buf)
+	mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) })
+	mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) })
+
+	mode = cipher.NewCBCEncrypter(block, buf)
+	mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) })
+	mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) })
+}
+
+func mustPanic(t *testing.T, msg string, f func()) {
+	defer func() {
+		err := recover()
+		if err == nil {
+			t.Errorf("function did not panic, wanted %q", msg)
+		} else if err != msg {
+			t.Errorf("got panic %v, wanted %q", err, msg)
+		}
+	}()
+	f()
+}
diff --git a/src/pkg/crypto/cipher/ctr.go b/src/pkg/crypto/cipher/ctr.go
index 147b74f..d9ee9d8 100644
--- a/src/pkg/crypto/cipher/ctr.go
+++ b/src/pkg/crypto/cipher/ctr.go
@@ -23,7 +23,7 @@ type ctr struct {
 // counter mode. The length of iv must be the same as the Block's block size.
 func NewCTR(block Block, iv []byte) Stream {
 	if len(iv) != block.BlockSize() {
-		panic("cipher.NewCTR: iv length must equal block size")
+		panic("cipher.NewCTR: IV length must equal block size")
 	}
 
 	return &ctr{
diff --git a/src/pkg/crypto/cipher/example_test.go b/src/pkg/crypto/cipher/example_test.go
new file mode 100644
index 0000000..e0027ca
--- /dev/null
+++ b/src/pkg/crypto/cipher/example_test.go
@@ -0,0 +1,283 @@
+// 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 cipher_test
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/rand"
+	"encoding/hex"
+	"fmt"
+	"io"
+	"os"
+)
+
+func ExampleNewCBCDecrypter() {
+	key := []byte("example key 1234")
+	ciphertext, _ := hex.DecodeString("f363f3ccdcb12bb883abf484ba77d9cd7d32b5baecb3d4b1b3e0e4beffdb3ded")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	if len(ciphertext) < aes.BlockSize {
+		panic("ciphertext too short")
+	}
+	iv := ciphertext[:aes.BlockSize]
+	ciphertext = ciphertext[aes.BlockSize:]
+
+	// CBC mode always works in whole blocks.
+	if len(ciphertext)%aes.BlockSize != 0 {
+		panic("ciphertext is not a multiple of the block size")
+	}
+
+	mode := cipher.NewCBCDecrypter(block, iv)
+
+	// CryptBlocks can work in-place if the two arguments are the same.
+	mode.CryptBlocks(ciphertext, ciphertext)
+
+	// If the original plaintext lengths are not a multiple of the block
+	// size, padding would have to be added when encrypting, which would be
+	// removed at this point. For an example, see
+	// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. However, it's
+	// critical to note that ciphertexts must be authenticated (i.e. by
+	// using crypto/hmac) before being decrypted in order to avoid creating
+	// a padding oracle.
+
+	fmt.Printf("%s\n", ciphertext)
+	// Output: exampleplaintext
+}
+
+func ExampleNewCBCEncrypter() {
+	key := []byte("example key 1234")
+	plaintext := []byte("exampleplaintext")
+
+	// CBC mode works on blocks so plaintexts may need to be padded to the
+	// next whole block. For an example of such padding, see
+	// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
+	// assume that the plaintext is already of the correct length.
+	if len(plaintext)%aes.BlockSize != 0 {
+		panic("plaintext is not a multiple of the block size")
+	}
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+	iv := ciphertext[:aes.BlockSize]
+	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+		panic(err)
+	}
+
+	mode := cipher.NewCBCEncrypter(block, iv)
+	mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
+
+	// It's important to remember that ciphertexts must be authenticated
+	// (i.e. by using crypto/hmac) as well as being encrypted in order to
+	// be secure.
+
+	fmt.Printf("%x\n", ciphertext)
+}
+
+func ExampleNewCFBDecrypter() {
+	key := []byte("example key 1234")
+	ciphertext, _ := hex.DecodeString("22277966616d9bc47177bd02603d08c9a67d5380d0fe8cf3b44438dff7b9")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	if len(ciphertext) < aes.BlockSize {
+		panic("ciphertext too short")
+	}
+	iv := ciphertext[:aes.BlockSize]
+	ciphertext = ciphertext[aes.BlockSize:]
+
+	stream := cipher.NewCFBDecrypter(block, iv)
+
+	// XORKeyStream can work in-place if the two arguments are the same.
+	stream.XORKeyStream(ciphertext, ciphertext)
+	fmt.Printf("%s", ciphertext)
+	// Output: some plaintext
+}
+
+func ExampleNewCFBEncrypter() {
+	key := []byte("example key 1234")
+	plaintext := []byte("some plaintext")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+	iv := ciphertext[:aes.BlockSize]
+	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+		panic(err)
+	}
+
+	stream := cipher.NewCFBEncrypter(block, iv)
+	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+	// It's important to remember that ciphertexts must be authenticated
+	// (i.e. by using crypto/hmac) as well as being encrypted in order to
+	// be secure.
+}
+
+func ExampleNewCTR() {
+	key := []byte("example key 1234")
+	plaintext := []byte("some plaintext")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+	iv := ciphertext[:aes.BlockSize]
+	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+		panic(err)
+	}
+
+	stream := cipher.NewCTR(block, iv)
+	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+	// It's important to remember that ciphertexts must be authenticated
+	// (i.e. by using crypto/hmac) as well as being encrypted in order to
+	// be secure.
+
+	// CTR mode is the same for both encryption and decryption, so we can
+	// also decrypt that ciphertext with NewCTR.
+
+	plaintext2 := make([]byte, len(plaintext))
+	stream = cipher.NewCTR(block, iv)
+	stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
+
+	fmt.Printf("%s\n", plaintext2)
+	// Output: some plaintext
+}
+
+func ExampleNewOFB() {
+	key := []byte("example key 1234")
+	plaintext := []byte("some plaintext")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// The IV needs to be unique, but not secure. Therefore it's common to
+	// include it at the beginning of the ciphertext.
+	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+	iv := ciphertext[:aes.BlockSize]
+	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+		panic(err)
+	}
+
+	stream := cipher.NewOFB(block, iv)
+	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+	// It's important to remember that ciphertexts must be authenticated
+	// (i.e. by using crypto/hmac) as well as being encrypted in order to
+	// be secure.
+
+	// OFB mode is the same for both encryption and decryption, so we can
+	// also decrypt that ciphertext with NewOFB.
+
+	plaintext2 := make([]byte, len(plaintext))
+	stream = cipher.NewOFB(block, iv)
+	stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
+
+	fmt.Printf("%s\n", plaintext2)
+	// Output: some plaintext
+}
+
+func ExampleStreamReader() {
+	key := []byte("example key 1234")
+
+	inFile, err := os.Open("encrypted-file")
+	if err != nil {
+		panic(err)
+	}
+	defer inFile.Close()
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// If the key is unique for each ciphertext, then it's ok to use a zero
+	// IV.
+	var iv [aes.BlockSize]byte
+	stream := cipher.NewOFB(block, iv[:])
+
+	outFile, err := os.OpenFile("decrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+	if err != nil {
+		panic(err)
+	}
+	defer outFile.Close()
+
+	reader := &cipher.StreamReader{stream, inFile}
+	// Copy the input file to the output file, decrypting as we go.
+	if _, err := io.Copy(outFile, reader); err != nil {
+		panic(err)
+	}
+
+	// Note that this example is simplistic in that it omits any
+	// authentication of the encrypted data. It you were actually to use
+	// StreamReader in this manner, an attacker could flip arbitrary bits in
+	// the output.
+}
+
+func ExampleStreamWriter() {
+	key := []byte("example key 1234")
+
+	inFile, err := os.Open("plaintext-file")
+	if err != nil {
+		panic(err)
+	}
+	defer inFile.Close()
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err)
+	}
+
+	// If the key is unique for each ciphertext, then it's ok to use a zero
+	// IV.
+	var iv [aes.BlockSize]byte
+	stream := cipher.NewOFB(block, iv[:])
+
+	outFile, err := os.OpenFile("encrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+	if err != nil {
+		panic(err)
+	}
+	defer outFile.Close()
+
+	writer := &cipher.StreamWriter{stream, outFile, nil}
+	// Copy the input file to the output file, encrypting as we go.
+	if _, err := io.Copy(writer, inFile); err != nil {
+		panic(err)
+	}
+
+	// Note that this example is simplistic in that it omits any
+	// authentication of the encrypted data. It 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/io.go b/src/pkg/crypto/cipher/io.go
index 76048fb..807e8da 100644
--- a/src/pkg/crypto/cipher/io.go
+++ b/src/pkg/crypto/cipher/io.go
@@ -28,13 +28,10 @@ func (r StreamReader) Read(dst []byte) (n int, err error) {
 type StreamWriter struct {
 	S   Stream
 	W   io.Writer
-	Err error
+	Err error // unused
 }
 
 func (w StreamWriter) Write(src []byte) (n int, err error) {
-	if w.Err != nil {
-		return 0, w.Err
-	}
 	c := make([]byte, len(src))
 	w.S.XORKeyStream(c, src)
 	n, err = w.W.Write(c)
@@ -42,7 +39,6 @@ func (w StreamWriter) Write(src []byte) (n int, err error) {
 		if err == nil { // should never happen
 			err = io.ErrShortWrite
 		}
-		w.Err = err
 	}
 	return
 }
diff --git a/src/pkg/crypto/des/des_test.go b/src/pkg/crypto/des/des_test.go
index e9fc236..2e87e99 100644
--- a/src/pkg/crypto/des/des_test.go
+++ b/src/pkg/crypto/des/des_test.go
@@ -1503,3 +1503,21 @@ func TestSubstitutionTableKnownAnswerDecrypt(t *testing.T) {
 		}
 	}
 }
+
+func ExampleNewTripleDESCipher() {
+	// NewTripleDESCipher can also be used when EDE2 is required by
+	// duplicating the first 8 bytes of the 16-byte key.
+	ede2Key := []byte("example key 1234")
+
+	var tripleDESKey []byte
+	tripleDESKey = append(tripleDESKey, ede2Key[:16]...)
+	tripleDESKey = append(tripleDESKey, ede2Key[:8]...)
+
+	_, err := NewTripleDESCipher(tripleDESKey)
+	if err != nil {
+		panic(err)
+	}
+
+	// See crypto/cipher for how to use a cipher.Block for encryption and
+	// decryption.
+}
diff --git a/src/pkg/crypto/ecdsa/ecdsa.go b/src/pkg/crypto/ecdsa/ecdsa.go
index 8508e3b..512d20c 100644
--- a/src/pkg/crypto/ecdsa/ecdsa.go
+++ b/src/pkg/crypto/ecdsa/ecdsa.go
@@ -140,14 +140,16 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
 	w := new(big.Int).ModInverse(s, N)
 
 	u1 := e.Mul(e, w)
+	u1.Mod(u1, N)
 	u2 := w.Mul(r, w)
+	u2.Mod(u2, N)
 
 	x1, y1 := c.ScalarBaseMult(u1.Bytes())
 	x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes())
-	if x1.Cmp(x2) == 0 {
+	x, y := c.Add(x1, y1, x2, y2)
+	if x.Sign() == 0 && y.Sign() == 0 {
 		return false
 	}
-	x, _ := c.Add(x1, y1, x2, y2)
 	x.Mod(x, N)
 	return x.Cmp(r) == 0
 }
diff --git a/src/pkg/crypto/ecdsa/ecdsa_test.go b/src/pkg/crypto/ecdsa/ecdsa_test.go
index 3a2b3ef..0c06431 100644
--- a/src/pkg/crypto/ecdsa/ecdsa_test.go
+++ b/src/pkg/crypto/ecdsa/ecdsa_test.go
@@ -5,11 +5,19 @@
 package ecdsa
 
 import (
+	"bufio"
+	"compress/bzip2"
 	"crypto/elliptic"
 	"crypto/rand"
 	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/sha512"
 	"encoding/hex"
+	"hash"
+	"io"
 	"math/big"
+	"os"
+	"strings"
 	"testing"
 )
 
@@ -72,156 +80,112 @@ func fromHex(s string) *big.Int {
 	return r
 }
 
-// These test vectors were taken from
-//   http://csrc.nist.gov/groups/STM/cavp/documents/dss/ecdsatestvectors.zip
-var testVectors = []struct {
-	msg    string
-	Qx, Qy string
-	r, s   string
-	ok     bool
-}{
-	{
-		"09626b45493672e48f3d1226a3aff3201960e577d33a7f72c7eb055302db8fe8ed61685dd036b554942a5737cd1512cdf811ee0c00e6dd2f08c69f08643be396e85dafda664801e772cdb7396868ac47b172245b41986aa2648cb77fbbfa562581be06651355a0c4b090f9d17d8f0ab6cced4e0c9d386cf465a516630f0231bd",
-		"9504b5b82d97a264d8b3735e0568decabc4b6ca275bc53cbadfc1c40",
-		"03426f80e477603b10dee670939623e3da91a94267fc4e51726009ed",
-		"81d3ac609f9575d742028dd496450a58a60eea2dcf8b9842994916e1",
-		"96a8c5f382c992e8f30ccce9af120b067ec1d74678fa8445232f75a5",
-		false,
-	},
-	{
-		"96b2b6536f6df29be8567a72528aceeaccbaa66c66c534f3868ca9778b02faadb182e4ed34662e73b9d52ecbe9dc8e875fc05033c493108b380689ebf47e5b062e6a0cdb3dd34ce5fe347d92768d72f7b9b377c20aea927043b509c078ed2467d7113405d2ddd458811e6faf41c403a2a239240180f1430a6f4330df5d77de37",
-		"851e3100368a22478a0029353045ae40d1d8202ef4d6533cfdddafd8",
-		"205302ac69457dd345e86465afa72ee8c74ca97e2b0b999aec1f10c2",
-		"4450c2d38b697e990721aa2dbb56578d32b4f5aeb3b9072baa955ee0",
-		"e26d4b589166f7b4ba4b1c8fce823fa47aad22f8c9c396b8c6526e12",
-		false,
-	},
-	{
-		"86778dbb4a068a01047a8d245d632f636c11d2ad350740b36fad90428b454ad0f120cb558d12ea5c8a23db595d87543d06d1ef489263d01ee529871eb68737efdb8ff85bc7787b61514bed85b7e01d6be209e0a4eb0db5c8df58a5c5bf706d76cb2bdf7800208639e05b89517155d11688236e6a47ed37d8e5a2b1e0adea338e",
-		"ad5bda09d319a717c1721acd6688d17020b31b47eef1edea57ceeffc",
-		"c8ce98e181770a7c9418c73c63d01494b8b80a41098c5ea50692c984",
-		"de5558c257ab4134e52c19d8db3b224a1899cbd08cc508ce8721d5e9",
-		"745db7af5a477e5046705c0a5eff1f52cb94a79d481f0c5a5e108ecd",
-		true,
-	},
-	{
-		"4bc6ef1958556686dab1e39c3700054a304cbd8f5928603dcd97fafd1f29e69394679b638f71c9344ce6a535d104803d22119f57b5f9477e253817a52afa9bfbc9811d6cc8c8be6b6566c6ef48b439bbb532abe30627548c598867f3861ba0b154dc1c3deca06eb28df8efd28258554b5179883a36fbb1eecf4f93ee19d41e3d",
-		"cc5eea2edf964018bdc0504a3793e4d2145142caa09a72ac5fb8d3e8",
-		"a48d78ae5d08aa725342773975a00d4219cf7a8029bb8cf3c17c374a",
-		"67b861344b4e416d4094472faf4272f6d54a497177fbc5f9ef292836",
-		"1d54f3fcdad795bf3b23408ecbac3e1321d1d66f2e4e3d05f41f7020",
-		false,
-	},
-	{
-		"bb658732acbf3147729959eb7318a2058308b2739ec58907dd5b11cfa3ecf69a1752b7b7d806fe00ec402d18f96039f0b78dbb90a59c4414fb33f1f4e02e4089de4122cd93df5263a95be4d7084e2126493892816e6a5b4ed123cb705bf930c8f67af0fb4514d5769232a9b008a803af225160ce63f675bd4872c4c97b146e5e",
-		"6234c936e27bf141fc7534bfc0a7eedc657f91308203f1dcbd642855",
-		"27983d87ca785ef4892c3591ef4a944b1deb125dd58bd351034a6f84",
-		"e94e05b42d01d0b965ffdd6c3a97a36a771e8ea71003de76c4ecb13f",
-		"1dc6464ffeefbd7872a081a5926e9fc3e66d123f1784340ba17737e9",
-		false,
-	},
-	{
-		"7c00be9123bfa2c4290be1d8bc2942c7f897d9a5b7917e3aabd97ef1aab890f148400a89abd554d19bec9d8ed911ce57b22fbcf6d30ca2115f13ce0a3f569a23bad39ee645f624c49c60dcfc11e7d2be24de9c905596d8f23624d63dc46591d1f740e46f982bfae453f107e80db23545782be23ce43708245896fc54e1ee5c43",
-		"9f3f037282aaf14d4772edffff331bbdda845c3f65780498cde334f1",
-		"8308ee5a16e3bcb721b6bc30000a0419bc1aaedd761be7f658334066",
-		"6381d7804a8808e3c17901e4d283b89449096a8fba993388fa11dc54",
-		"8e858f6b5b253686a86b757bad23658cda53115ac565abca4e3d9f57",
-		false,
-	},
-	{
-		"cffc122a44840dc705bb37130069921be313d8bde0b66201aebc48add028ca131914ef2e705d6bedd19dc6cf9459bbb0f27cdfe3c50483808ffcdaffbeaa5f062e097180f07a40ef4ab6ed03fe07ed6bcfb8afeb42c97eafa2e8a8df469de07317c5e1494c41547478eff4d8c7d9f0f484ad90fedf6e1c35ee68fa73f1691601",
-		"a03b88a10d930002c7b17ca6af2fd3e88fa000edf787dc594f8d4fd4",
-		"e0cf7acd6ddc758e64847fe4df9915ebda2f67cdd5ec979aa57421f5",
-		"387b84dcf37dc343c7d2c5beb82f0bf8bd894b395a7b894565d296c1",
-		"4adc12ce7d20a89ce3925e10491c731b15ddb3f339610857a21b53b4",
-		false,
-	},
-	{
-		"26e0e0cafd85b43d16255908ccfd1f061c680df75aba3081246b337495783052ba06c60f4a486c1591a4048bae11b4d7fec4f161d80bdc9a7b79d23e44433ed625eab280521a37f23dd3e1bdc5c6a6cfaa026f3c45cf703e76dab57add93fe844dd4cda67dc3bddd01f9152579e49df60969b10f09ce9372fdd806b0c7301866",
-		"9a8983c42f2b5a87c37a00458b5970320d247f0c8a88536440173f7d",
-		"15e489ec6355351361900299088cfe8359f04fe0cab78dde952be80c",
-		"929a21baa173d438ec9f28d6a585a2f9abcfc0a4300898668e476dc0",
-		"59a853f046da8318de77ff43f26fe95a92ee296fa3f7e56ce086c872",
-		true,
-	},
-	{
-		"1078eac124f48ae4f807e946971d0de3db3748dd349b14cca5c942560fb25401b2252744f18ad5e455d2d97ed5ae745f55ff509c6c8e64606afe17809affa855c4c4cdcaf6b69ab4846aa5624ed0687541aee6f2224d929685736c6a23906d974d3c257abce1a3fb8db5951b89ecb0cda92b5207d93f6618fd0f893c32cf6a6e",
-		"d6e55820bb62c2be97650302d59d667a411956138306bd566e5c3c2b",
-		"631ab0d64eaf28a71b9cbd27a7a88682a2167cee6251c44e3810894f",
-		"65af72bc7721eb71c2298a0eb4eed3cec96a737cc49125706308b129",
-		"bd5a987c78e2d51598dbd9c34a9035b0069c580edefdacee17ad892a",
-		false,
-	},
-	{
-		"919deb1fdd831c23481dfdb2475dcbe325b04c34f82561ced3d2df0b3d749b36e255c4928973769d46de8b95f162b53cd666cad9ae145e7fcfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82130761231f536e6a3d59792f784902c469aa897aabf9a0678f93446610d56d5e0981e4c8a563556b",
-		"269b455b1024eb92d860a420f143ac1286b8cce43031562ae7664574",
-		"baeb6ca274a77c44a0247e5eb12ca72bdd9a698b3f3ae69c9f1aaa57",
-		"cb4ec2160f04613eb0dfe4608486091a25eb12aa4dec1afe91cfb008",
-		"40b01d8cd06589481574f958b98ca08ade9d2a8fe31024375c01bb40",
-		false,
-	},
-	{
-		"6e012361250dacf6166d2dd1aa7be544c3206a9d43464b3fcd90f3f8cf48d08ec099b59ba6fe7d9bdcfaf244120aed1695d8be32d1b1cd6f143982ab945d635fb48a7c76831c0460851a3d62b7209c30cd9c2abdbe3d2a5282a9fcde1a6f418dd23c409bc351896b9b34d7d3a1a63bbaf3d677e612d4a80fa14829386a64b33f",
-		"6d2d695efc6b43b13c14111f2109608f1020e3e03b5e21cfdbc82fcd",
-		"26a4859296b7e360b69cf40be7bd97ceaffa3d07743c8489fc47ca1b",
-		"9a8cb5f2fdc288b7183c5b32d8e546fc2ed1ca4285eeae00c8b572ad",
-		"8c623f357b5d0057b10cdb1a1593dab57cda7bdec9cf868157a79b97",
-		true,
-	},
-	{
-		"bf6bd7356a52b234fe24d25557200971fc803836f6fec3cade9642b13a8e7af10ab48b749de76aada9d8927f9b12f75a2c383ca7358e2566c4bb4f156fce1fd4e87ef8c8d2b6b1bdd351460feb22cdca0437ac10ca5e0abbbce9834483af20e4835386f8b1c96daaa41554ceee56730aac04f23a5c765812efa746051f396566",
-		"14250131b2599939cf2d6bc491be80ddfe7ad9de644387ee67de2d40",
-		"b5dc473b5d014cd504022043c475d3f93c319a8bdcb7262d9e741803",
-		"4f21642f2201278a95339a80f75cc91f8321fcb3c9462562f6cbf145",
-		"452a5f816ea1f75dee4fd514fa91a0d6a43622981966c59a1b371ff8",
-		false,
-	},
-	{
-		"0eb7f4032f90f0bd3cf9473d6d9525d264d14c031a10acd31a053443ed5fe919d5ac35e0be77813071b4062f0b5fdf58ad5f637b76b0b305aec18f82441b6e607b44cdf6e0e3c7c57f24e6fd565e39430af4a6b1d979821ed0175fa03e3125506847654d7e1ae904ce1190ae38dc5919e257bdac2db142a6e7cd4da6c2e83770",
-		"d1f342b7790a1667370a1840255ac5bbbdc66f0bc00ae977d99260ac",
-		"76416cabae2de9a1000b4646338b774baabfa3db4673790771220cdb",
-		"bc85e3fc143d19a7271b2f9e1c04b86146073f3fab4dda1c3b1f35ca",
-		"9a5c70ede3c48d5f43307a0c2a4871934424a3303b815df4bb0f128e",
-		false,
-	},
-	{
-		"5cc25348a05d85e56d4b03cec450128727bc537c66ec3a9fb613c151033b5e86878632249cba83adcefc6c1e35dcd31702929c3b57871cda5c18d1cf8f9650a25b917efaed56032e43b6fc398509f0d2997306d8f26675f3a8683b79ce17128e006aa0903b39eeb2f1001be65de0520115e6f919de902b32c38d691a69c58c92",
-		"7e49a7abf16a792e4c7bbc4d251820a2abd22d9f2fc252a7bf59c9a6",
-		"44236a8fb4791c228c26637c28ae59503a2f450d4cfb0dc42aa843b9",
-		"084461b4050285a1a85b2113be76a17878d849e6bc489f4d84f15cd8",
-		"079b5bddcc4d45de8dbdfd39f69817c7e5afa454a894d03ee1eaaac3",
-		false,
-	},
-	{
-		"1951533ce33afb58935e39e363d8497a8dd0442018fd96dff167b3b23d7206a3ee182a3194765df4768a3284e23b8696c199b4686e670d60c9d782f08794a4bccc05cffffbd1a12acd9eb1cfa01f7ebe124da66ecff4599ea7720c3be4bb7285daa1a86ebf53b042bd23208d468c1b3aa87381f8e1ad63e2b4c2ba5efcf05845",
-		"31945d12ebaf4d81f02be2b1768ed80784bf35cf5e2ff53438c11493",
-		"a62bebffac987e3b9d3ec451eb64c462cdf7b4aa0b1bbb131ceaa0a4",
-		"bc3c32b19e42b710bca5c6aaa128564da3ddb2726b25f33603d2af3c",
-		"ed1a719cc0c507edc5239d76fe50e2306c145ad252bd481da04180c0",
-		false,
-	},
-}
-
 func TestVectors(t *testing.T) {
-	sha := sha1.New()
+	// This test runs the full set of NIST test vectors from
+	// http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip
+	//
+	// The SigVer.rsp file has been edited to remove test vectors for
+	// unsupported algorithms and has been compressed.
+
+	if testing.Short() {
+		return
+	}
+
+	f, err := os.Open("testdata/SigVer.rsp.bz2")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	buf := bufio.NewReader(bzip2.NewReader(f))
+
+	lineNo := 1
+	var h hash.Hash
+	var msg []byte
+	var hashed []byte
+	var r, s *big.Int
+	pub := new(PublicKey)
 
-	for i, test := range testVectors {
-		pub := PublicKey{
-			Curve: elliptic.P224(),
-			X:     fromHex(test.Qx),
-			Y:     fromHex(test.Qy),
+	for {
+		line, err := buf.ReadString('\n')
+		if len(line) == 0 {
+			if err == io.EOF {
+				break
+			}
+			t.Fatalf("error reading from input: %s", err)
 		}
-		msg, _ := hex.DecodeString(test.msg)
-		sha.Reset()
-		sha.Write(msg)
-		hashed := sha.Sum(nil)
-		r := fromHex(test.r)
-		s := fromHex(test.s)
-		if Verify(&pub, hashed, r, s) != test.ok {
-			t.Errorf("%d: bad result", i)
+		lineNo++
+		// Need to remove \r\n from the end of the line.
+		if !strings.HasSuffix(line, "\r\n") {
+			t.Fatalf("bad line ending (expected \\r\\n) on line %d", lineNo)
 		}
-		if testing.Short() {
-			break
+		line = line[:len(line)-2]
+
+		if len(line) == 0 || line[0] == '#' {
+			continue
+		}
+
+		if line[0] == '[' {
+			line = line[1 : len(line)-1]
+			parts := strings.SplitN(line, ",", 2)
+
+			switch parts[0] {
+			case "P-224":
+				pub.Curve = elliptic.P224()
+			case "P-256":
+				pub.Curve = elliptic.P256()
+			case "P-384":
+				pub.Curve = elliptic.P384()
+			case "P-521":
+				pub.Curve = elliptic.P521()
+			default:
+				pub.Curve = nil
+			}
+
+			switch parts[1] {
+			case "SHA-1":
+				h = sha1.New()
+			case "SHA-224":
+				h = sha256.New224()
+			case "SHA-256":
+				h = sha256.New()
+			case "SHA-384":
+				h = sha512.New384()
+			case "SHA-512":
+				h = sha512.New()
+			default:
+				h = nil
+			}
+
+			continue
+		}
+
+		if h == nil || pub.Curve == nil {
+			continue
+		}
+
+		switch {
+		case strings.HasPrefix(line, "Msg = "):
+			if msg, err = hex.DecodeString(line[6:]); err != nil {
+				t.Fatalf("failed to decode message on line %d: %s", lineNo, err)
+			}
+		case strings.HasPrefix(line, "Qx = "):
+			pub.X = fromHex(line[5:])
+		case strings.HasPrefix(line, "Qy = "):
+			pub.Y = fromHex(line[5:])
+		case strings.HasPrefix(line, "R = "):
+			r = fromHex(line[4:])
+		case strings.HasPrefix(line, "S = "):
+			s = fromHex(line[4:])
+		case strings.HasPrefix(line, "Result = "):
+			expected := line[9] == 'P'
+			h.Reset()
+			h.Write(msg)
+			hashed := h.Sum(hashed[:0])
+			if Verify(pub, hashed, r, s) != expected {
+				t.Fatalf("incorrect result on line %d", lineNo)
+			}
+		default:
+			t.Fatalf("unknown variable on line %d: %s", lineNo, line)
 		}
 	}
 }
diff --git a/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2 b/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2
new file mode 100644
index 0000000..09fe2b4
Binary files /dev/null and b/src/pkg/crypto/ecdsa/testdata/SigVer.rsp.bz2 differ
diff --git a/src/pkg/crypto/elliptic/elliptic.go b/src/pkg/crypto/elliptic/elliptic.go
index 30835a9..7a4ff66 100644
--- a/src/pkg/crypto/elliptic/elliptic.go
+++ b/src/pkg/crypto/elliptic/elliptic.go
@@ -31,10 +31,10 @@ type Curve interface {
 	// Double returns 2*(x,y)
 	Double(x1, y1 *big.Int) (x, y *big.Int)
 	// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
-	ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int)
-	// ScalarBaseMult returns k*G, where G is the base point of the group and k
-	// is an integer in big-endian form.
-	ScalarBaseMult(scalar []byte) (x, y *big.Int)
+	ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int)
+	// ScalarBaseMult returns k*G, where G is the base point of the group
+	// and k is an integer in big-endian form.
+	ScalarBaseMult(k []byte) (x, y *big.Int)
 }
 
 // CurveParams contains the parameters of an elliptic curve and also provides
@@ -69,9 +69,24 @@ func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
 	return x3.Cmp(y2) == 0
 }
 
+// zForAffine returns a Jacobian Z value for the affine point (x, y). If x and
+// y are zero, it assumes that they represent the point at infinity because (0,
+// 0) is not on the any of the curves handled here.
+func zForAffine(x, y *big.Int) *big.Int {
+	z := new(big.Int)
+	if x.Sign() != 0 || y.Sign() != 0 {
+		z.SetInt64(1)
+	}
+	return z
+}
+
 // affineFromJacobian reverses the Jacobian transform. See the comment at the
-// top of the file.
+// top of the file. If the point is ∞ it returns 0, 0.
 func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
+	if z.Sign() == 0 {
+		return new(big.Int), new(big.Int)
+	}
+
 	zinv := new(big.Int).ModInverse(z, curve.P)
 	zinvsq := new(big.Int).Mul(zinv, zinv)
 
@@ -84,14 +99,29 @@ func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.
 }
 
 func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
-	z := new(big.Int).SetInt64(1)
-	return curve.affineFromJacobian(curve.addJacobian(x1, y1, z, x2, y2, z))
+	z1 := zForAffine(x1, y1)
+	z2 := zForAffine(x2, y2)
+	return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2))
 }
 
 // addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
 // (x2, y2, z2) and returns their sum, also in Jacobian form.
 func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
 	// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
+	x3, y3, z3 := new(big.Int), new(big.Int), new(big.Int)
+	if z1.Sign() == 0 {
+		x3.Set(x2)
+		y3.Set(y2)
+		z3.Set(z2)
+		return x3, y3, z3
+	}
+	if z2.Sign() == 0 {
+		x3.Set(x1)
+		y3.Set(y1)
+		z3.Set(z1)
+		return x3, y3, z3
+	}
+
 	z1z1 := new(big.Int).Mul(z1, z1)
 	z1z1.Mod(z1z1, curve.P)
 	z2z2 := new(big.Int).Mul(z2, z2)
@@ -102,6 +132,7 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
 	u2 := new(big.Int).Mul(x2, z1z1)
 	u2.Mod(u2, curve.P)
 	h := new(big.Int).Sub(u2, u1)
+	xEqual := h.Sign() == 0
 	if h.Sign() == -1 {
 		h.Add(h, curve.P)
 	}
@@ -119,17 +150,21 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
 	if r.Sign() == -1 {
 		r.Add(r, curve.P)
 	}
+	yEqual := r.Sign() == 0
+	if xEqual && yEqual {
+		return curve.doubleJacobian(x1, y1, z1)
+	}
 	r.Lsh(r, 1)
 	v := new(big.Int).Mul(u1, i)
 
-	x3 := new(big.Int).Set(r)
+	x3.Set(r)
 	x3.Mul(x3, x3)
 	x3.Sub(x3, j)
 	x3.Sub(x3, v)
 	x3.Sub(x3, v)
 	x3.Mod(x3, curve.P)
 
-	y3 := new(big.Int).Set(r)
+	y3.Set(r)
 	v.Sub(v, x3)
 	y3.Mul(y3, v)
 	s1.Mul(s1, j)
@@ -137,16 +172,10 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
 	y3.Sub(y3, s1)
 	y3.Mod(y3, curve.P)
 
-	z3 := new(big.Int).Add(z1, z2)
+	z3.Add(z1, z2)
 	z3.Mul(z3, z3)
 	z3.Sub(z3, z1z1)
-	if z3.Sign() == -1 {
-		z3.Add(z3, curve.P)
-	}
 	z3.Sub(z3, z2z2)
-	if z3.Sign() == -1 {
-		z3.Add(z3, curve.P)
-	}
 	z3.Mul(z3, h)
 	z3.Mod(z3, curve.P)
 
@@ -154,7 +183,7 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
 }
 
 func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
-	z1 := new(big.Int).SetInt64(1)
+	z1 := zForAffine(x1, y1)
 	return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1))
 }
 
@@ -219,40 +248,19 @@ func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
 }
 
 func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
-	// We have a slight problem in that the identity of the group (the
-	// point at infinity) cannot be represented in (x, y) form on a finite
-	// machine. Thus the standard add/double algorithm has to be tweaked
-	// slightly: our initial state is not the identity, but x, and we
-	// ignore the first true bit in |k|.  If we don't find any true bits in
-	// |k|, then we return nil, nil, because we cannot return the identity
-	// element.
-
 	Bz := new(big.Int).SetInt64(1)
-	x := Bx
-	y := By
-	z := Bz
+	x, y, z := new(big.Int), new(big.Int), new(big.Int)
 
-	seenFirstTrue := false
 	for _, byte := range k {
 		for bitNum := 0; bitNum < 8; bitNum++ {
-			if seenFirstTrue {
-				x, y, z = curve.doubleJacobian(x, y, z)
-			}
+			x, y, z = curve.doubleJacobian(x, y, z)
 			if byte&0x80 == 0x80 {
-				if !seenFirstTrue {
-					seenFirstTrue = true
-				} else {
-					x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z)
-				}
+				x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z)
 			}
 			byte <<= 1
 		}
 	}
 
-	if !seenFirstTrue {
-		return nil, nil
-	}
-
 	return curve.affineFromJacobian(x, y, z)
 }
 
@@ -370,7 +378,7 @@ func P384() Curve {
 	return p384
 }
 
-// P256 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
+// P521 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
 func P521() Curve {
 	initonce.Do(initAll)
 	return p521
diff --git a/src/pkg/crypto/elliptic/elliptic_test.go b/src/pkg/crypto/elliptic/elliptic_test.go
index 1e3407e..58f9039 100644
--- a/src/pkg/crypto/elliptic/elliptic_test.go
+++ b/src/pkg/crypto/elliptic/elliptic_test.go
@@ -322,6 +322,44 @@ func TestGenericBaseMult(t *testing.T) {
 	}
 }
 
+func TestInfinity(t *testing.T) {
+	tests := []struct {
+		name  string
+		curve Curve
+	}{
+		{"p224", P224()},
+		{"p256", P256()},
+	}
+
+	for _, test := range tests {
+		curve := test.curve
+		x, y := curve.ScalarBaseMult(nil)
+		if x.Sign() != 0 || y.Sign() != 0 {
+			t.Errorf("%s: x^0 != ∞", test.name)
+		}
+		x.SetInt64(0)
+		y.SetInt64(0)
+
+		x2, y2 := curve.Double(x, y)
+		if x2.Sign() != 0 || y2.Sign() != 0 {
+			t.Errorf("%s: 2∞ != ∞", test.name)
+		}
+
+		baseX := curve.Params().Gx
+		baseY := curve.Params().Gy
+
+		x3, y3 := curve.Add(baseX, baseY, x, y)
+		if x3.Cmp(baseX) != 0 || y3.Cmp(baseY) != 0 {
+			t.Errorf("%s: x+∞ != x", test.name)
+		}
+
+		x4, y4 := curve.Add(x, y, baseX, baseY)
+		if x4.Cmp(baseX) != 0 || y4.Cmp(baseY) != 0 {
+			t.Errorf("%s: ∞+x != x", test.name)
+		}
+	}
+}
+
 func BenchmarkBaseMult(b *testing.B) {
 	b.ResetTimer()
 	p224 := P224()
diff --git a/src/pkg/crypto/elliptic/p224.go b/src/pkg/crypto/elliptic/p224.go
index 17571c2..1f7ff3f 100644
--- a/src/pkg/crypto/elliptic/p224.go
+++ b/src/pkg/crypto/elliptic/p224.go
@@ -80,10 +80,14 @@ func (p224Curve) Add(bigX1, bigY1, bigX2, bigY2 *big.Int) (x, y *big.Int) {
 
 	p224FromBig(&x1, bigX1)
 	p224FromBig(&y1, bigY1)
-	z1[0] = 1
+	if bigX1.Sign() != 0 || bigY1.Sign() != 0 {
+		z1[0] = 1
+	}
 	p224FromBig(&x2, bigX2)
 	p224FromBig(&y2, bigY2)
-	z2[0] = 1
+	if bigX2.Sign() != 0 || bigY2.Sign() != 0 {
+		z2[0] = 1
+	}
 
 	p224AddJacobian(&x3, &y3, &z3, &x1, &y1, &z1, &x2, &y2, &z2)
 	return p224ToAffine(&x3, &y3, &z3)
@@ -132,6 +136,44 @@ func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
 // exactly, making the reflections during a reduce much nicer.
 type p224FieldElement [8]uint32
 
+// p224P is the order of the field, represented as a p224FieldElement.
+var p224P = [8]uint32{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
+
+// p224IsZero returns 1 if a == 0 mod p and 0 otherwise.
+//
+// a[i] < 2**29
+func p224IsZero(a *p224FieldElement) uint32 {
+	// Since a p224FieldElement contains 224 bits there are two possible
+	// representations of 0: 0 and p.
+	var minimal p224FieldElement
+	p224Contract(&minimal, a)
+
+	var isZero, isP uint32
+	for i, v := range minimal {
+		isZero |= v
+		isP |= v - p224P[i]
+	}
+
+	// If either isZero or isP is 0, then we should return 1.
+	isZero |= isZero >> 16
+	isZero |= isZero >> 8
+	isZero |= isZero >> 4
+	isZero |= isZero >> 2
+	isZero |= isZero >> 1
+
+	isP |= isP >> 16
+	isP |= isP >> 8
+	isP |= isP >> 4
+	isP |= isP >> 2
+	isP |= isP >> 1
+
+	// For isZero and isP, the LSB is 0 iff all the bits are zero.
+	result := isZero & isP
+	result = (^result) & 1
+
+	return result
+}
+
 // p224Add computes *out = a+b
 //
 // a[i] + b[i] < 2**32
@@ -406,7 +448,7 @@ func p224Contract(out, in *p224FieldElement) {
 	// true.
 	top4AllOnes := uint32(0xffffffff)
 	for i := 4; i < 8; i++ {
-		top4AllOnes &= (out[i] & bottom28Bits) - 1
+		top4AllOnes &= out[i]
 	}
 	top4AllOnes |= 0xf0000000
 	// Now we replicate any zero bits to all the bits in top4AllOnes.
@@ -441,7 +483,7 @@ func p224Contract(out, in *p224FieldElement) {
 	out3Equal = ^uint32(int32(out3Equal<<31) >> 31)
 
 	// If out[3] > 0xffff000 then n's MSB will be zero.
-	out3GT := ^uint32(int32(n<<31) >> 31)
+	out3GT := ^uint32(int32(n) >> 31)
 
 	mask := top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT)
 	out[0] -= 1 & mask
@@ -463,6 +505,9 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
 	var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement
 	var c p224LargeFieldElement
 
+	z1IsZero := p224IsZero(z1)
+	z2IsZero := p224IsZero(z2)
+
 	// Z1Z1 = Z1²
 	p224Square(&z1z1, z1, &c)
 	// Z2Z2 = Z2²
@@ -480,6 +525,7 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
 	// H = U2-U1
 	p224Sub(&h, &u2, &u1)
 	p224Reduce(&h)
+	xEqual := p224IsZero(&h)
 	// I = (2*H)²
 	for j := 0; j < 8; j++ {
 		i[j] = h[j] << 1
@@ -491,6 +537,11 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
 	// r = 2*(S2-S1)
 	p224Sub(&r, &s2, &s1)
 	p224Reduce(&r)
+	yEqual := p224IsZero(&r)
+	if xEqual == 1 && yEqual == 1 && z1IsZero == 0 && z2IsZero == 0 {
+		p224DoubleJacobian(x3, y3, z3, x1, y1, z1)
+		return
+	}
 	for i := 0; i < 8; i++ {
 		r[i] <<= 1
 	}
@@ -524,6 +575,13 @@ func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
 	p224Mul(&z1z1, &z1z1, &r, &c)
 	p224Sub(y3, &z1z1, &s1)
 	p224Reduce(y3)
+
+	p224CopyConditional(x3, x2, z1IsZero)
+	p224CopyConditional(x3, x1, z2IsZero)
+	p224CopyConditional(y3, y2, z1IsZero)
+	p224CopyConditional(y3, y1, z2IsZero)
+	p224CopyConditional(z3, z2, z1IsZero)
+	p224CopyConditional(z3, z1, z2IsZero)
 }
 
 // p224DoubleJacobian computes *out = a+a.
@@ -593,22 +651,19 @@ func p224CopyConditional(out, in *p224FieldElement, control uint32) {
 func p224ScalarMult(outX, outY, outZ, inX, inY, inZ *p224FieldElement, scalar []byte) {
 	var xx, yy, zz p224FieldElement
 	for i := 0; i < 8; i++ {
+		outX[i] = 0
+		outY[i] = 0
 		outZ[i] = 0
 	}
 
-	firstBit := uint32(1)
 	for _, byte := range scalar {
 		for bitNum := uint(0); bitNum < 8; bitNum++ {
 			p224DoubleJacobian(outX, outY, outZ, outX, outY, outZ)
 			bit := uint32((byte >> (7 - bitNum)) & 1)
 			p224AddJacobian(&xx, &yy, &zz, inX, inY, inZ, outX, outY, outZ)
-			p224CopyConditional(outX, inX, firstBit&bit)
-			p224CopyConditional(outY, inY, firstBit&bit)
-			p224CopyConditional(outZ, inZ, firstBit&bit)
-			p224CopyConditional(outX, &xx, ^firstBit&bit)
-			p224CopyConditional(outY, &yy, ^firstBit&bit)
-			p224CopyConditional(outZ, &zz, ^firstBit&bit)
-			firstBit = firstBit & ^bit
+			p224CopyConditional(outX, &xx, bit)
+			p224CopyConditional(outY, &yy, bit)
+			p224CopyConditional(outZ, &zz, bit)
 		}
 	}
 }
@@ -618,16 +673,8 @@ func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) {
 	var zinv, zinvsq, outx, outy p224FieldElement
 	var tmp p224LargeFieldElement
 
-	isPointAtInfinity := true
-	for i := 0; i < 8; i++ {
-		if z[i] != 0 {
-			isPointAtInfinity = false
-			break
-		}
-	}
-
-	if isPointAtInfinity {
-		return nil, nil
+	if isPointAtInfinity := p224IsZero(z); isPointAtInfinity == 1 {
+		return new(big.Int), new(big.Int)
 	}
 
 	p224Invert(&zinv, z)
diff --git a/src/pkg/crypto/hmac/hmac.go b/src/pkg/crypto/hmac/hmac.go
index a97ce09..b6f4919 100644
--- a/src/pkg/crypto/hmac/hmac.go
+++ b/src/pkg/crypto/hmac/hmac.go
@@ -2,13 +2,27 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
-// defined in U.S. Federal Information Processing Standards Publication 198.
-// An HMAC is a cryptographic hash that uses a key to sign a message.
-// The receiver verifies the hash by recomputing it using the same key.
+/*
+Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
+defined in U.S. Federal Information Processing Standards Publication 198.
+An HMAC is a cryptographic hash that uses a key to sign a message.
+The receiver verifies the hash by recomputing it using the same key.
+
+Receivers should be careful to use Equal to compare MACs in order to avoid
+timing side-channels:
+
+	// CheckMAC returns true if messageMAC is a valid HMAC tag for message.
+	func CheckMAC(message, messageMAC, key []byte) bool {
+		mac := hmac.New(sha256.New, key)
+		mac.Write(message)
+		expectedMAC := mac.Sum(nil)
+		return hmac.Equal(messageMAC, expectedMAC)
+	}
+*/
 package hmac
 
 import (
+	"crypto/subtle"
 	"hash"
 )
 
@@ -57,7 +71,7 @@ func (h *hmac) BlockSize() int { return h.blocksize }
 func (h *hmac) Reset() {
 	h.inner.Reset()
 	h.tmpPad(0x36)
-	h.inner.Write(h.tmp[0:h.blocksize])
+	h.inner.Write(h.tmp[:h.blocksize])
 }
 
 // New returns a new HMAC hash using the given hash.Hash type and key.
@@ -78,3 +92,11 @@ func New(h func() hash.Hash, key []byte) hash.Hash {
 	hm.Reset()
 	return hm
 }
+
+// Equal compares two MACs for equality without leaking timing information.
+func Equal(mac1, mac2 []byte) bool {
+	// We don't have to be constant time if the lengths of the MACs are
+	// different as that suggests that a completely different hash function
+	// was used.
+	return len(mac1) == len(mac2) && subtle.ConstantTimeCompare(mac1, mac2) == 1
+}
diff --git a/src/pkg/crypto/hmac/hmac_test.go b/src/pkg/crypto/hmac/hmac_test.go
index 0795741..d486042 100644
--- a/src/pkg/crypto/hmac/hmac_test.go
+++ b/src/pkg/crypto/hmac/hmac_test.go
@@ -491,3 +491,22 @@ func TestHMAC(t *testing.T) {
 		}
 	}
 }
+
+func TestEqual(t *testing.T) {
+	a := []byte("test")
+	b := []byte("test1")
+	c := []byte("test2")
+
+	if !Equal(b, b) {
+		t.Error("Equal failed with equal arguments")
+	}
+	if Equal(a, b) {
+		t.Error("Equal accepted a prefix of the second argument")
+	}
+	if Equal(b, a) {
+		t.Error("Equal accepted a prefix of the first argument")
+	}
+	if Equal(b, c) {
+		t.Error("Equal accepted unequal slices")
+	}
+}
diff --git a/src/pkg/crypto/md5/gen.go b/src/pkg/crypto/md5/gen.go
new file mode 100644
index 0000000..966bdae
--- /dev/null
+++ b/src/pkg/crypto/md5/gen.go
@@ -0,0 +1,300 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// This program generates md5block.go
+// Invoke as
+//
+//	go run gen.go [-full] |gofmt >md5block.go
+//
+// The -full flag causes the generated code to do a full
+// (16x) unrolling instead of a 4x unrolling.
+
+package main
+
+import (
+	"flag"
+	"log"
+	"os"
+	"strings"
+	"text/template"
+)
+
+func main() {
+	flag.Parse()
+
+	t := template.Must(template.New("main").Funcs(funcs).Parse(program))
+	if err := t.Execute(os.Stdout, data); err != nil {
+		log.Fatal(err)
+	}
+}
+
+type Data struct {
+	a, b, c, d string
+	Shift1     []int
+	Shift2     []int
+	Shift3     []int
+	Shift4     []int
+	Table1     []uint32
+	Table2     []uint32
+	Table3     []uint32
+	Table4     []uint32
+	Full       bool
+}
+
+var funcs = template.FuncMap{
+	"dup":     dup,
+	"relabel": relabel,
+	"rotate":  rotate,
+}
+
+func dup(count int, x []int) []int {
+	var out []int
+	for i := 0; i < count; i++ {
+		out = append(out, x...)
+	}
+	return out
+}
+
+func relabel(s string) string {
+	return strings.NewReplacer("a", data.a, "b", data.b, "c", data.c, "d", data.d).Replace(s)
+}
+
+func rotate() string {
+	data.a, data.b, data.c, data.d = data.d, data.a, data.b, data.c
+	return "" // no output
+}
+
+func init() {
+	flag.BoolVar(&data.Full, "full", false, "complete unrolling")
+}
+
+var data = Data{
+	a:      "a",
+	b:      "b",
+	c:      "c",
+	d:      "d",
+	Shift1: []int{7, 12, 17, 22},
+	Shift2: []int{5, 9, 14, 20},
+	Shift3: []int{4, 11, 16, 23},
+	Shift4: []int{6, 10, 15, 21},
+
+	// table[i] = int((1<<32) * abs(sin(i+1 radians))).
+	Table1: []uint32{
+		// round 1
+		0xd76aa478,
+		0xe8c7b756,
+		0x242070db,
+		0xc1bdceee,
+		0xf57c0faf,
+		0x4787c62a,
+		0xa8304613,
+		0xfd469501,
+		0x698098d8,
+		0x8b44f7af,
+		0xffff5bb1,
+		0x895cd7be,
+		0x6b901122,
+		0xfd987193,
+		0xa679438e,
+		0x49b40821,
+	},
+	Table2: []uint32{
+		// round 2
+		0xf61e2562,
+		0xc040b340,
+		0x265e5a51,
+		0xe9b6c7aa,
+		0xd62f105d,
+		0x2441453,
+		0xd8a1e681,
+		0xe7d3fbc8,
+		0x21e1cde6,
+		0xc33707d6,
+		0xf4d50d87,
+		0x455a14ed,
+		0xa9e3e905,
+		0xfcefa3f8,
+		0x676f02d9,
+		0x8d2a4c8a,
+	},
+	Table3: []uint32{
+		// round3
+		0xfffa3942,
+		0x8771f681,
+		0x6d9d6122,
+		0xfde5380c,
+		0xa4beea44,
+		0x4bdecfa9,
+		0xf6bb4b60,
+		0xbebfbc70,
+		0x289b7ec6,
+		0xeaa127fa,
+		0xd4ef3085,
+		0x4881d05,
+		0xd9d4d039,
+		0xe6db99e5,
+		0x1fa27cf8,
+		0xc4ac5665,
+	},
+	Table4: []uint32{
+		// round 4
+		0xf4292244,
+		0x432aff97,
+		0xab9423a7,
+		0xfc93a039,
+		0x655b59c3,
+		0x8f0ccc92,
+		0xffeff47d,
+		0x85845dd1,
+		0x6fa87e4f,
+		0xfe2ce6e0,
+		0xa3014314,
+		0x4e0811a1,
+		0xf7537e82,
+		0xbd3af235,
+		0x2ad7d2bb,
+		0xeb86d391,
+	},
+}
+
+var program = `
+package md5
+
+import (
+	"unsafe"
+	"runtime"
+)
+
+{{if not .Full}}
+	var t1 = [...]uint32{
+	{{range .Table1}}{{printf "\t%#x,\n" .}}{{end}}
+	}
+	
+	var t2 = [...]uint32{
+	{{range .Table2}}{{printf "\t%#x,\n" .}}{{end}}
+	}
+	
+	var t3 = [...]uint32{
+	{{range .Table3}}{{printf "\t%#x,\n" .}}{{end}}
+	}
+	
+	var t4 = [...]uint32{
+	{{range .Table4}}{{printf "\t%#x,\n" .}}{{end}}
+	}
+{{end}}
+
+func block(dig *digest, p []byte) {
+	a := dig.s[0]
+	b := dig.s[1]
+	c := dig.s[2]
+	d := dig.s[3]
+	var X *[16]uint32
+	var xbuf [16]uint32
+	for len(p) >= chunk {
+		aa, bb, cc, dd := a, b, c, d
+
+		// This is a constant condition - it is not evaluated on each iteration.
+		if runtime.GOARCH == "amd64" || runtime.GOARCH == "386" {
+			// MD5 was designed so that x86 processors can just iterate
+			// over the block data directly as uint32s, and we generate
+			// less code and run 1.3x faster if we take advantage of that.
+			// My apologies.
+			X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+		} else if uintptr(unsafe.Pointer(&p[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+			X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+		} else {
+			X = &xbuf
+			j := 0
+			for i := 0; i < 16; i++ {
+				X[i&15] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+				j += 4
+			}
+		}
+
+		{{if .Full}}
+			// Round 1.
+			{{range $i, $s := dup 4 .Shift1}}
+				{{index $.Table1 $i | printf "a += (((c^d)&b)^d) + X[%d] + %d" $i | relabel}}
+				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+				{{rotate}}
+			{{end}}
+	
+			// Round 2.
+			{{range $i, $s := dup 4 .Shift2}}
+				{{index $.Table2 $i | printf "a += (((b^c)&d)^c) + X[(1+5*%d)&15] + %d" $i | relabel}}
+				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+				{{rotate}}
+			{{end}}
+	
+			// Round 3.
+			{{range $i, $s := dup 4 .Shift3}}
+				{{index $.Table3 $i | printf "a += (b^c^d) + X[(5+3*%d)&15] + %d" $i | relabel}}
+				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+				{{rotate}}
+			{{end}}
+	
+			// Round 4.
+			{{range $i, $s := dup 4 .Shift4}}
+				{{index $.Table4 $i | printf "a += (c^(b|^d)) + X[(7*%d)&15] + %d" $i | relabel}}
+				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+				{{rotate}}
+			{{end}}
+		{{else}}
+			// Round 1.
+			for i := uint(0); i < 16; {
+				{{range $s := .Shift1}}
+					{{printf "a += (((c^d)&b)^d) + X[i&15] + t1[i&15]" | relabel}}
+					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+					i++
+					{{rotate}}
+				{{end}}
+			}
+	
+			// Round 2.
+			for i := uint(0); i < 16; {
+				{{range $s := .Shift2}}
+					{{printf "a += (((b^c)&d)^c) + X[(1+5*i)&15] + t2[i&15]" | relabel}}
+					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+					i++
+					{{rotate}}
+				{{end}}
+			}
+	
+			// Round 3.
+			for i := uint(0); i < 16; {
+				{{range $s := .Shift3}}
+					{{printf "a += (b^c^d) + X[(5+3*i)&15] + t3[i&15]" | relabel}}
+					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+					i++
+					{{rotate}}
+				{{end}}
+			}
+	
+			// Round 4.
+			for i := uint(0); i < 16; {
+				{{range $s := .Shift4}}
+					{{printf "a += (c^(b|^d)) + X[(7*i)&15] + t4[i&15]" | relabel}}
+					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
+					i++
+					{{rotate}}
+				{{end}}
+			}
+		{{end}}
+
+		a += aa
+		b += bb
+		c += cc
+		d += dd
+
+		p = p[chunk:]
+	}
+
+	dig.s[0] = a
+	dig.s[1] = b
+	dig.s[2] = c
+	dig.s[3] = d
+}
+`
diff --git a/src/pkg/crypto/md5/md5.go b/src/pkg/crypto/md5/md5.go
index cfb728c..825e5c8 100644
--- a/src/pkg/crypto/md5/md5.go
+++ b/src/pkg/crypto/md5/md5.go
@@ -21,26 +21,26 @@ const Size = 16
 const BlockSize = 64
 
 const (
-	_Chunk = 64
-	_Init0 = 0x67452301
-	_Init1 = 0xEFCDAB89
-	_Init2 = 0x98BADCFE
-	_Init3 = 0x10325476
+	chunk = 64
+	init0 = 0x67452301
+	init1 = 0xEFCDAB89
+	init2 = 0x98BADCFE
+	init3 = 0x10325476
 )
 
 // digest represents the partial evaluation of a checksum.
 type digest struct {
 	s   [4]uint32
-	x   [_Chunk]byte
+	x   [chunk]byte
 	nx  int
 	len uint64
 }
 
 func (d *digest) Reset() {
-	d.s[0] = _Init0
-	d.s[1] = _Init1
-	d.s[2] = _Init2
-	d.s[3] = _Init3
+	d.s[0] = init0
+	d.s[1] = init1
+	d.s[2] = init2
+	d.s[3] = init3
 	d.nx = 0
 	d.len = 0
 }
@@ -61,21 +61,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
 	d.len += uint64(nn)
 	if d.nx > 0 {
 		n := len(p)
-		if n > _Chunk-d.nx {
-			n = _Chunk - d.nx
+		if n > chunk-d.nx {
+			n = chunk - d.nx
 		}
 		for i := 0; i < n; i++ {
 			d.x[d.nx+i] = p[i]
 		}
 		d.nx += n
-		if d.nx == _Chunk {
-			_Block(d, d.x[0:])
+		if d.nx == chunk {
+			block(d, d.x[0:chunk])
 			d.nx = 0
 		}
 		p = p[n:]
 	}
-	n := _Block(d, p)
-	p = p[n:]
+	if len(p) >= chunk {
+		n := len(p) &^ (chunk - 1)
+		block(d, p[:n])
+		p = p[n:]
+	}
 	if len(p) > 0 {
 		d.nx = copy(d.x[:], p)
 	}
diff --git a/src/pkg/crypto/md5/md5_test.go b/src/pkg/crypto/md5/md5_test.go
index aae8754..3ef4519 100644
--- a/src/pkg/crypto/md5/md5_test.go
+++ b/src/pkg/crypto/md5/md5_test.go
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package md5_test
+package md5
 
 import (
-	"crypto/md5"
 	"fmt"
 	"io"
 	"testing"
+	"unsafe"
 )
 
 type md5Test struct {
@@ -53,14 +53,20 @@ var golden = []md5Test{
 func TestGolden(t *testing.T) {
 	for i := 0; i < len(golden); i++ {
 		g := golden[i]
-		c := md5.New()
-		for j := 0; j < 3; j++ {
+		c := New()
+		buf := make([]byte, len(g.in)+4)
+		for j := 0; j < 3+4; j++ {
 			if j < 2 {
 				io.WriteString(c, g.in)
-			} else {
+			} else if j == 2 {
 				io.WriteString(c, g.in[0:len(g.in)/2])
 				c.Sum(nil)
 				io.WriteString(c, g.in[len(g.in)/2:])
+			} else if j > 2 {
+				// test unaligned write
+				buf = buf[1:]
+				copy(buf, g.in)
+				c.Write(buf[:len(g.in)])
 			}
 			s := fmt.Sprintf("%x", c.Sum(nil))
 			if s != g.out {
@@ -72,9 +78,53 @@ func TestGolden(t *testing.T) {
 }
 
 func ExampleNew() {
-	h := md5.New()
+	h := New()
 	io.WriteString(h, "The fog is getting thicker!")
 	io.WriteString(h, "And Leon's getting laaarger!")
 	fmt.Printf("%x", h.Sum(nil))
 	// Output: e2c569be17396eca2a2e3c11578123ed
 }
+
+var bench = New()
+var buf = make([]byte, 8192+1)
+var sum = make([]byte, bench.Size())
+
+func benchmarkSize(b *testing.B, size int, unaligned bool) {
+	b.SetBytes(int64(size))
+	buf := buf
+	if unaligned {
+		if uintptr(unsafe.Pointer(&buf[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+			buf = buf[1:]
+		}
+	}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bench.Reset()
+		bench.Write(buf[:size])
+		bench.Sum(sum[:0])
+	}
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+	benchmarkSize(b, 8, false)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+	benchmarkSize(b, 1024, false)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+	benchmarkSize(b, 8192, false)
+}
+
+func BenchmarkHash8BytesUnaligned(b *testing.B) {
+	benchmarkSize(b, 8, true)
+}
+
+func BenchmarkHash1KUnaligned(b *testing.B) {
+	benchmarkSize(b, 1024, true)
+}
+
+func BenchmarkHash8KUnaligned(b *testing.B) {
+	benchmarkSize(b, 8192, true)
+}
diff --git a/src/pkg/crypto/md5/md5block.go b/src/pkg/crypto/md5/md5block.go
index a887e2e..0ca4217 100644
--- a/src/pkg/crypto/md5/md5block.go
+++ b/src/pkg/crypto/md5/md5block.go
@@ -1,172 +1,258 @@
-// 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 md5
 
-// MD5 block step.
-// In its own file so that a faster assembly or C version
-// can be substituted easily.
+import (
+	"runtime"
+	"unsafe"
+)
 
-package md5
+const x86 = runtime.GOARCH == "amd64" || runtime.GOARCH == "386"
 
-// table[i] = int((1<<32) * abs(sin(i+1 radians))).
-var table = []uint32{
-	// round 1
-	0xd76aa478,
-	0xe8c7b756,
-	0x242070db,
-	0xc1bdceee,
-	0xf57c0faf,
-	0x4787c62a,
-	0xa8304613,
-	0xfd469501,
-	0x698098d8,
-	0x8b44f7af,
-	0xffff5bb1,
-	0x895cd7be,
-	0x6b901122,
-	0xfd987193,
-	0xa679438e,
-	0x49b40821,
-
-	// round 2
-	0xf61e2562,
-	0xc040b340,
-	0x265e5a51,
-	0xe9b6c7aa,
-	0xd62f105d,
-	0x2441453,
-	0xd8a1e681,
-	0xe7d3fbc8,
-	0x21e1cde6,
-	0xc33707d6,
-	0xf4d50d87,
-	0x455a14ed,
-	0xa9e3e905,
-	0xfcefa3f8,
-	0x676f02d9,
-	0x8d2a4c8a,
-
-	// round3
-	0xfffa3942,
-	0x8771f681,
-	0x6d9d6122,
-	0xfde5380c,
-	0xa4beea44,
-	0x4bdecfa9,
-	0xf6bb4b60,
-	0xbebfbc70,
-	0x289b7ec6,
-	0xeaa127fa,
-	0xd4ef3085,
-	0x4881d05,
-	0xd9d4d039,
-	0xe6db99e5,
-	0x1fa27cf8,
-	0xc4ac5665,
-
-	// round 4
-	0xf4292244,
-	0x432aff97,
-	0xab9423a7,
-	0xfc93a039,
-	0x655b59c3,
-	0x8f0ccc92,
-	0xffeff47d,
-	0x85845dd1,
-	0x6fa87e4f,
-	0xfe2ce6e0,
-	0xa3014314,
-	0x4e0811a1,
-	0xf7537e82,
-	0xbd3af235,
-	0x2ad7d2bb,
-	0xeb86d391,
-}
+var littleEndian bool
 
-var shift1 = []uint{7, 12, 17, 22}
-var shift2 = []uint{5, 9, 14, 20}
-var shift3 = []uint{4, 11, 16, 23}
-var shift4 = []uint{6, 10, 15, 21}
+func init() {
+	x := uint32(0x04030201)
+	y := [4]byte{0x1, 0x2, 0x3, 0x4}
+	littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y
+}
 
-func _Block(dig *digest, p []byte) int {
+func block(dig *digest, p []byte) {
 	a := dig.s[0]
 	b := dig.s[1]
 	c := dig.s[2]
 	d := dig.s[3]
-	n := 0
-	var X [16]uint32
-	for len(p) >= _Chunk {
+	var X *[16]uint32
+	var xbuf [16]uint32
+	for len(p) >= chunk {
 		aa, bb, cc, dd := a, b, c, d
 
-		j := 0
-		for i := 0; i < 16; i++ {
-			X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
-			j += 4
+		// This is a constant condition - it is not evaluated on each iteration.
+		if x86 {
+			// MD5 was designed so that x86 processors can just iterate
+			// over the block data directly as uint32s, and we generate
+			// less code and run 1.3x faster if we take advantage of that.
+			// My apologies.
+			X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+		} else if littleEndian && uintptr(unsafe.Pointer(&p[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+			X = (*[16]uint32)(unsafe.Pointer(&p[0]))
+		} else {
+			X = &xbuf
+			j := 0
+			for i := 0; i < 16; i++ {
+				X[i&15] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+				j += 4
+			}
 		}
 
-		// If this needs to be made faster in the future,
-		// the usual trick is to unroll each of these
-		// loops by a factor of 4; that lets you replace
-		// the shift[] lookups with constants and,
-		// with suitable variable renaming in each
-		// unrolled body, delete the a, b, c, d = d, a, b, c
-		// (or you can let the optimizer do the renaming).
-		//
-		// The index variables are uint so that % by a power
-		// of two can be optimized easily by a compiler.
-
 		// Round 1.
-		for i := uint(0); i < 16; i++ {
-			x := i
-			s := shift1[i%4]
-			f := ((c ^ d) & b) ^ d
-			a += f + X[x] + table[i]
-			a = a<<s | a>>(32-s) + b
-			a, b, c, d = d, a, b, c
-		}
+
+		a += (((c ^ d) & b) ^ d) + X[0] + 3614090360
+		a = a<<7 | a>>(32-7) + b
+
+		d += (((b ^ c) & a) ^ c) + X[1] + 3905402710
+		d = d<<12 | d>>(32-12) + a
+
+		c += (((a ^ b) & d) ^ b) + X[2] + 606105819
+		c = c<<17 | c>>(32-17) + d
+
+		b += (((d ^ a) & c) ^ a) + X[3] + 3250441966
+		b = b<<22 | b>>(32-22) + c
+
+		a += (((c ^ d) & b) ^ d) + X[4] + 4118548399
+		a = a<<7 | a>>(32-7) + b
+
+		d += (((b ^ c) & a) ^ c) + X[5] + 1200080426
+		d = d<<12 | d>>(32-12) + a
+
+		c += (((a ^ b) & d) ^ b) + X[6] + 2821735955
+		c = c<<17 | c>>(32-17) + d
+
+		b += (((d ^ a) & c) ^ a) + X[7] + 4249261313
+		b = b<<22 | b>>(32-22) + c
+
+		a += (((c ^ d) & b) ^ d) + X[8] + 1770035416
+		a = a<<7 | a>>(32-7) + b
+
+		d += (((b ^ c) & a) ^ c) + X[9] + 2336552879
+		d = d<<12 | d>>(32-12) + a
+
+		c += (((a ^ b) & d) ^ b) + X[10] + 4294925233
+		c = c<<17 | c>>(32-17) + d
+
+		b += (((d ^ a) & c) ^ a) + X[11] + 2304563134
+		b = b<<22 | b>>(32-22) + c
+
+		a += (((c ^ d) & b) ^ d) + X[12] + 1804603682
+		a = a<<7 | a>>(32-7) + b
+
+		d += (((b ^ c) & a) ^ c) + X[13] + 4254626195
+		d = d<<12 | d>>(32-12) + a
+
+		c += (((a ^ b) & d) ^ b) + X[14] + 2792965006
+		c = c<<17 | c>>(32-17) + d
+
+		b += (((d ^ a) & c) ^ a) + X[15] + 1236535329
+		b = b<<22 | b>>(32-22) + c
 
 		// Round 2.
-		for i := uint(0); i < 16; i++ {
-			x := (1 + 5*i) % 16
-			s := shift2[i%4]
-			g := ((b ^ c) & d) ^ c
-			a += g + X[x] + table[i+16]
-			a = a<<s | a>>(32-s) + b
-			a, b, c, d = d, a, b, c
-		}
+
+		a += (((b ^ c) & d) ^ c) + X[(1+5*0)&15] + 4129170786
+		a = a<<5 | a>>(32-5) + b
+
+		d += (((a ^ b) & c) ^ b) + X[(1+5*1)&15] + 3225465664
+		d = d<<9 | d>>(32-9) + a
+
+		c += (((d ^ a) & b) ^ a) + X[(1+5*2)&15] + 643717713
+		c = c<<14 | c>>(32-14) + d
+
+		b += (((c ^ d) & a) ^ d) + X[(1+5*3)&15] + 3921069994
+		b = b<<20 | b>>(32-20) + c
+
+		a += (((b ^ c) & d) ^ c) + X[(1+5*4)&15] + 3593408605
+		a = a<<5 | a>>(32-5) + b
+
+		d += (((a ^ b) & c) ^ b) + X[(1+5*5)&15] + 38016083
+		d = d<<9 | d>>(32-9) + a
+
+		c += (((d ^ a) & b) ^ a) + X[(1+5*6)&15] + 3634488961
+		c = c<<14 | c>>(32-14) + d
+
+		b += (((c ^ d) & a) ^ d) + X[(1+5*7)&15] + 3889429448
+		b = b<<20 | b>>(32-20) + c
+
+		a += (((b ^ c) & d) ^ c) + X[(1+5*8)&15] + 568446438
+		a = a<<5 | a>>(32-5) + b
+
+		d += (((a ^ b) & c) ^ b) + X[(1+5*9)&15] + 3275163606
+		d = d<<9 | d>>(32-9) + a
+
+		c += (((d ^ a) & b) ^ a) + X[(1+5*10)&15] + 4107603335
+		c = c<<14 | c>>(32-14) + d
+
+		b += (((c ^ d) & a) ^ d) + X[(1+5*11)&15] + 1163531501
+		b = b<<20 | b>>(32-20) + c
+
+		a += (((b ^ c) & d) ^ c) + X[(1+5*12)&15] + 2850285829
+		a = a<<5 | a>>(32-5) + b
+
+		d += (((a ^ b) & c) ^ b) + X[(1+5*13)&15] + 4243563512
+		d = d<<9 | d>>(32-9) + a
+
+		c += (((d ^ a) & b) ^ a) + X[(1+5*14)&15] + 1735328473
+		c = c<<14 | c>>(32-14) + d
+
+		b += (((c ^ d) & a) ^ d) + X[(1+5*15)&15] + 2368359562
+		b = b<<20 | b>>(32-20) + c
 
 		// Round 3.
-		for i := uint(0); i < 16; i++ {
-			x := (5 + 3*i) % 16
-			s := shift3[i%4]
-			h := b ^ c ^ d
-			a += h + X[x] + table[i+32]
-			a = a<<s | a>>(32-s) + b
-			a, b, c, d = d, a, b, c
-		}
+
+		a += (b ^ c ^ d) + X[(5+3*0)&15] + 4294588738
+		a = a<<4 | a>>(32-4) + b
+
+		d += (a ^ b ^ c) + X[(5+3*1)&15] + 2272392833
+		d = d<<11 | d>>(32-11) + a
+
+		c += (d ^ a ^ b) + X[(5+3*2)&15] + 1839030562
+		c = c<<16 | c>>(32-16) + d
+
+		b += (c ^ d ^ a) + X[(5+3*3)&15] + 4259657740
+		b = b<<23 | b>>(32-23) + c
+
+		a += (b ^ c ^ d) + X[(5+3*4)&15] + 2763975236
+		a = a<<4 | a>>(32-4) + b
+
+		d += (a ^ b ^ c) + X[(5+3*5)&15] + 1272893353
+		d = d<<11 | d>>(32-11) + a
+
+		c += (d ^ a ^ b) + X[(5+3*6)&15] + 4139469664
+		c = c<<16 | c>>(32-16) + d
+
+		b += (c ^ d ^ a) + X[(5+3*7)&15] + 3200236656
+		b = b<<23 | b>>(32-23) + c
+
+		a += (b ^ c ^ d) + X[(5+3*8)&15] + 681279174
+		a = a<<4 | a>>(32-4) + b
+
+		d += (a ^ b ^ c) + X[(5+3*9)&15] + 3936430074
+		d = d<<11 | d>>(32-11) + a
+
+		c += (d ^ a ^ b) + X[(5+3*10)&15] + 3572445317
+		c = c<<16 | c>>(32-16) + d
+
+		b += (c ^ d ^ a) + X[(5+3*11)&15] + 76029189
+		b = b<<23 | b>>(32-23) + c
+
+		a += (b ^ c ^ d) + X[(5+3*12)&15] + 3654602809
+		a = a<<4 | a>>(32-4) + b
+
+		d += (a ^ b ^ c) + X[(5+3*13)&15] + 3873151461
+		d = d<<11 | d>>(32-11) + a
+
+		c += (d ^ a ^ b) + X[(5+3*14)&15] + 530742520
+		c = c<<16 | c>>(32-16) + d
+
+		b += (c ^ d ^ a) + X[(5+3*15)&15] + 3299628645
+		b = b<<23 | b>>(32-23) + c
 
 		// Round 4.
-		for i := uint(0); i < 16; i++ {
-			x := (7 * i) % 16
-			s := shift4[i%4]
-			j := c ^ (b | ^d)
-			a += j + X[x] + table[i+48]
-			a = a<<s | a>>(32-s) + b
-			a, b, c, d = d, a, b, c
-		}
+
+		a += (c ^ (b | ^d)) + X[(7*0)&15] + 4096336452
+		a = a<<6 | a>>(32-6) + b
+
+		d += (b ^ (a | ^c)) + X[(7*1)&15] + 1126891415
+		d = d<<10 | d>>(32-10) + a
+
+		c += (a ^ (d | ^b)) + X[(7*2)&15] + 2878612391
+		c = c<<15 | c>>(32-15) + d
+
+		b += (d ^ (c | ^a)) + X[(7*3)&15] + 4237533241
+		b = b<<21 | b>>(32-21) + c
+
+		a += (c ^ (b | ^d)) + X[(7*4)&15] + 1700485571
+		a = a<<6 | a>>(32-6) + b
+
+		d += (b ^ (a | ^c)) + X[(7*5)&15] + 2399980690
+		d = d<<10 | d>>(32-10) + a
+
+		c += (a ^ (d | ^b)) + X[(7*6)&15] + 4293915773
+		c = c<<15 | c>>(32-15) + d
+
+		b += (d ^ (c | ^a)) + X[(7*7)&15] + 2240044497
+		b = b<<21 | b>>(32-21) + c
+
+		a += (c ^ (b | ^d)) + X[(7*8)&15] + 1873313359
+		a = a<<6 | a>>(32-6) + b
+
+		d += (b ^ (a | ^c)) + X[(7*9)&15] + 4264355552
+		d = d<<10 | d>>(32-10) + a
+
+		c += (a ^ (d | ^b)) + X[(7*10)&15] + 2734768916
+		c = c<<15 | c>>(32-15) + d
+
+		b += (d ^ (c | ^a)) + X[(7*11)&15] + 1309151649
+		b = b<<21 | b>>(32-21) + c
+
+		a += (c ^ (b | ^d)) + X[(7*12)&15] + 4149444226
+		a = a<<6 | a>>(32-6) + b
+
+		d += (b ^ (a | ^c)) + X[(7*13)&15] + 3174756917
+		d = d<<10 | d>>(32-10) + a
+
+		c += (a ^ (d | ^b)) + X[(7*14)&15] + 718787259
+		c = c<<15 | c>>(32-15) + d
+
+		b += (d ^ (c | ^a)) + X[(7*15)&15] + 3951481745
+		b = b<<21 | b>>(32-21) + c
 
 		a += aa
 		b += bb
 		c += cc
 		d += dd
 
-		p = p[_Chunk:]
-		n += _Chunk
+		p = p[chunk:]
 	}
 
 	dig.s[0] = a
 	dig.s[1] = b
 	dig.s[2] = c
 	dig.s[3] = d
-	return n
 }
diff --git a/src/pkg/crypto/rand/example_test.go b/src/pkg/crypto/rand/example_test.go
new file mode 100644
index 0000000..5af8e46
--- /dev/null
+++ b/src/pkg/crypto/rand/example_test.go
@@ -0,0 +1,29 @@
+// 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 rand_test
+
+import (
+	"bytes"
+	"crypto/rand"
+	"fmt"
+	"io"
+)
+
+// This example reads 10 cryptographically secure pseudorandom numbers from
+// rand.Reader and writes them to a byte slice.
+func ExampleRead() {
+	c := 10
+	b := make([]byte, c)
+	n, err := io.ReadFull(rand.Reader, b)
+	if n != len(b) || err != nil {
+		fmt.Println("error:", err)
+		return
+	}
+	// The slice should now contain random bytes instead of only zeroes.
+	fmt.Println(bytes.Equal(b, make([]byte, c)))
+
+	// Output:
+	// false
+}
diff --git a/src/pkg/crypto/rand/rand_test.go b/src/pkg/crypto/rand/rand_test.go
index be3a5a2..e46e61d 100644
--- a/src/pkg/crypto/rand/rand_test.go
+++ b/src/pkg/crypto/rand/rand_test.go
@@ -7,6 +7,7 @@ package rand
 import (
 	"bytes"
 	"compress/flate"
+	"io"
 	"testing"
 )
 
@@ -16,9 +17,9 @@ func TestRead(t *testing.T) {
 		n = 1e5
 	}
 	b := make([]byte, n)
-	n, err := Read(b)
+	n, err := io.ReadFull(Reader, b)
 	if n != len(b) || err != nil {
-		t.Fatalf("Read(buf) = %d, %s", n, err)
+		t.Fatalf("ReadFull(buf) = %d, %s", n, err)
 	}
 
 	var z bytes.Buffer
@@ -29,3 +30,14 @@ func TestRead(t *testing.T) {
 		t.Fatalf("Compressed %d -> %d", len(b), z.Len())
 	}
 }
+
+func TestReadEmpty(t *testing.T) {
+	n, err := Reader.Read(make([]byte, 0))
+	if n != 0 || err != nil {
+		t.Fatalf("Read(make([]byte, 0)) = %d, %v", n, err)
+	}
+	n, err = Reader.Read(nil)
+	if n != 0 || err != nil {
+		t.Fatalf("Read(nil) = %d, %v", n, err)
+	}
+}
diff --git a/src/pkg/crypto/rand/rand_unix.go b/src/pkg/crypto/rand/rand_unix.go
index 5eb4cda..18f4824 100644
--- a/src/pkg/crypto/rand/rand_unix.go
+++ b/src/pkg/crypto/rand/rand_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 freebsd linux netbsd openbsd
+// +build darwin freebsd linux netbsd openbsd plan9
 
 // Unix cryptographically secure pseudorandom number
 // generator.
@@ -15,6 +15,7 @@ import (
 	"crypto/cipher"
 	"io"
 	"os"
+	"runtime"
 	"sync"
 	"time"
 )
@@ -22,7 +23,13 @@ import (
 // Easy implementation: read from /dev/urandom.
 // This is sufficient on Linux, OS X, and FreeBSD.
 
-func init() { Reader = &devReader{name: "/dev/urandom"} }
+func init() {
+	if runtime.GOOS == "plan9" {
+		Reader = newReader(nil)
+	} else {
+		Reader = &devReader{name: "/dev/urandom"}
+	}
+}
 
 // A devReader satisfies reads by reading the file named name.
 type devReader struct {
@@ -39,14 +46,17 @@ func (r *devReader) Read(b []byte) (n int, err error) {
 		if f == nil {
 			return 0, err
 		}
-		r.f = bufio.NewReader(f)
+		if runtime.GOOS == "plan9" {
+			r.f = f
+		} else {
+			r.f = bufio.NewReader(f)
+		}
 	}
 	return r.f.Read(b)
 }
 
 // Alternate pseudo-random implementation for use on
-// systems without a reliable /dev/urandom.  So far we
-// haven't needed it.
+// systems without a reliable /dev/urandom.
 
 // newReader returns a new pseudorandom generator that
 // seeds itself by reading from entropy.  If entropy == nil,
diff --git a/src/pkg/crypto/rand/rand_windows.go b/src/pkg/crypto/rand/rand_windows.go
index 2b2bd4b..82b39b6 100644
--- a/src/pkg/crypto/rand/rand_windows.go
+++ b/src/pkg/crypto/rand/rand_windows.go
@@ -35,6 +35,10 @@ func (r *rngReader) Read(b []byte) (n int, err error) {
 		}
 	}
 	r.mu.Unlock()
+
+	if len(b) == 0 {
+		return 0, nil
+	}
 	err = syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
 	if err != nil {
 		return 0, os.NewSyscallError("CryptGenRandom", err)
diff --git a/src/pkg/crypto/rand/util.go b/src/pkg/crypto/rand/util.go
index 5391c18..50e5b16 100644
--- a/src/pkg/crypto/rand/util.go
+++ b/src/pkg/crypto/rand/util.go
@@ -10,6 +10,21 @@ import (
 	"math/big"
 )
 
+// smallPrimes is a list of small, prime numbers that allows us to rapidly
+// exclude some fraction of composite candidates when searching for a random
+// prime. This list is truncated at the point where smallPrimesProduct exceeds
+// a uint64. It does not include two because we ensure that the candidates are
+// odd by construction.
+var smallPrimes = []uint8{
+	3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
+}
+
+// smallPrimesProduct is the product of the values in smallPrimes and allows us
+// to reduce a candidate prime by this number and then determine whether it's
+// coprime to all the elements of smallPrimes without further big.Int
+// operations.
+var smallPrimesProduct = new(big.Int).SetUint64(16294579238595022365)
+
 // Prime returns a number, p, of the given size, such that p is prime
 // with high probability.
 func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
@@ -25,6 +40,8 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
 	bytes := make([]byte, (bits+7)/8)
 	p = new(big.Int)
 
+	bigMod := new(big.Int)
+
 	for {
 		_, err = io.ReadFull(rand, bytes)
 		if err != nil {
@@ -33,13 +50,51 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
 
 		// Clear bits in the first byte to make sure the candidate has a size <= bits.
 		bytes[0] &= uint8(int(1<<b) - 1)
-		// Don't let the value be too small, i.e, set the most significant bit.
-		bytes[0] |= 1 << (b - 1)
+		// Don't let the value be too small, i.e, set the most significant two bits.
+		// Setting the top two bits, rather than just the top bit,
+		// means that when two of these values are multiplied together,
+		// the result isn't ever one bit short.
+		if b >= 2 {
+			bytes[0] |= 3 << (b - 2)
+		} else {
+			// Here b==1, because b cannot be zero.
+			bytes[0] |= 1
+			if len(bytes) > 1 {
+				bytes[1] |= 0x80
+			}
+		}
 		// Make the value odd since an even number this large certainly isn't prime.
 		bytes[len(bytes)-1] |= 1
 
 		p.SetBytes(bytes)
-		if p.ProbablyPrime(20) {
+
+		// Calculate the value mod the product of smallPrimes.  If it's
+		// a multiple of any of these primes we add two until it isn't.
+		// The probability of overflowing is minimal and can be ignored
+		// because we still perform Miller-Rabin tests on the result.
+		bigMod.Mod(p, smallPrimesProduct)
+		mod := bigMod.Uint64()
+
+	NextDelta:
+		for delta := uint64(0); delta < 1<<20; delta += 2 {
+			m := mod + delta
+			for _, prime := range smallPrimes {
+				if m%uint64(prime) == 0 {
+					continue NextDelta
+				}
+			}
+
+			if delta > 0 {
+				bigMod.SetUint64(delta)
+				p.Add(p, bigMod)
+			}
+			break
+		}
+
+		// There is a tiny possibility that, by adding delta, we caused
+		// the number to be one bit too long. Thus we check BitLen
+		// here.
+		if p.ProbablyPrime(20) && p.BitLen() == bits {
 			return
 		}
 	}
diff --git a/src/pkg/crypto/rc4/rc4.go b/src/pkg/crypto/rc4/rc4.go
index 1bb278f..e0c33fa 100644
--- a/src/pkg/crypto/rc4/rc4.go
+++ b/src/pkg/crypto/rc4/rc4.go
@@ -42,17 +42,6 @@ func NewCipher(key []byte) (*Cipher, error) {
 	return &c, nil
 }
 
-// XORKeyStream sets dst to the result of XORing src with the key stream.
-// Dst and src may be the same slice but otherwise should not overlap.
-func (c *Cipher) XORKeyStream(dst, src []byte) {
-	for i := range src {
-		c.i += 1
-		c.j += c.s[c.i]
-		c.s[c.i], c.s[c.j] = c.s[c.j], c.s[c.i]
-		dst[i] = src[i] ^ c.s[c.s[c.i]+c.s[c.j]]
-	}
-}
-
 // Reset zeros the key data so that it will no longer appear in the
 // process's memory.
 func (c *Cipher) Reset() {
diff --git a/src/pkg/crypto/rc4/rc4_amd64.s b/src/pkg/crypto/rc4/rc4_amd64.s
new file mode 100644
index 0000000..ffe9ada
--- /dev/null
+++ b/src/pkg/crypto/rc4/rc4_amd64.s
@@ -0,0 +1,53 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// func xorKeyStream(dst, src *byte, n int, state *[256]byte, i, j *uint8)
+TEXT ·xorKeyStream(SB),7,$0
+	MOVQ dst+0(FP), DI
+	MOVQ src+8(FP), SI
+	MOVQ n+16(FP), CX
+	MOVQ state+24(FP), R8
+
+	MOVQ xPtr+32(FP), AX
+	MOVBQZX (AX), AX
+	MOVQ yPtr+40(FP), BX
+	MOVBQZX (BX), BX
+
+loop:
+	CMPQ CX, $0
+	JE done
+
+	// c.i += 1
+	INCB AX
+
+	// c.j += c.s[c.i]
+	MOVB (R8)(AX*1), R9
+	ADDB R9, BX
+
+	MOVBQZX (R8)(BX*1), R10
+
+	MOVB R10, (R8)(AX*1)
+	MOVB R9, (R8)(BX*1)
+
+	// R11 = c.s[c.i]+c.s[c.j]
+	MOVQ R10, R11
+	ADDB R9, R11
+
+	MOVB (R8)(R11*1), R11
+	MOVB (SI), R12
+	XORB R11, R12
+	MOVB R12, (DI)
+
+	INCQ SI
+	INCQ DI
+	DECQ CX
+
+	JMP loop
+done:
+	MOVQ xPtr+32(FP), R8
+	MOVB AX, (R8)
+	MOVQ yPtr+40(FP), R8
+	MOVB BX, (R8)
+
+	RET
diff --git a/src/pkg/crypto/rc4/rc4_arm.s b/src/pkg/crypto/rc4/rc4_arm.s
new file mode 100644
index 0000000..51a332f
--- /dev/null
+++ b/src/pkg/crypto/rc4/rc4_arm.s
@@ -0,0 +1,58 @@
+// 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.
+
+// Registers
+dst = 0
+src = 1
+n = 2
+state = 3
+pi = 4
+pj = 5
+i = 6
+j = 7
+k = 8
+t = 11
+t2 = 12
+
+// func xorKeyStream(dst, src *byte, n int, state *[256]byte, i, j *uint8)
+TEXT ·xorKeyStream(SB),7,$0
+	MOVW 0(FP), R(dst)
+	MOVW 4(FP), R(src)
+	MOVW 8(FP), R(n)
+	MOVW 12(FP), R(state)
+	MOVW 16(FP), R(pi)
+	MOVW 20(FP), R(pj)
+	MOVBU (R(pi)), R(i)
+	MOVBU (R(pj)), R(j)
+	MOVW $0, R(k)
+
+loop:
+	// i += 1; j += state[i]
+	ADD $1, R(i)
+	AND $0xff, R(i)
+	MOVBU R(i)<<0(R(state)), R(t)
+	ADD R(t), R(j)
+	AND $0xff, R(j)
+
+	// swap state[i] <-> state[j]
+	MOVBU R(j)<<0(R(state)), R(t2)
+	MOVB R(t2), R(i)<<0(R(state))
+	MOVB R(t), R(j)<<0(R(state))
+
+	// dst[k] = src[k] ^ state[state[i] + state[j]]
+	ADD R(t2), R(t)
+	AND $0xff, R(t)
+	MOVBU R(t)<<0(R(state)), R(t)
+	MOVBU R(k)<<0(R(src)), R(t2)
+	EOR R(t), R(t2)
+	MOVB R(t2), R(k)<<0(R(dst))
+
+	ADD $1, R(k)
+	CMP R(k), R(n)
+	BNE loop
+
+done:
+	MOVB R(i), (R(pi))
+	MOVB R(j), (R(pj))
+	RET
diff --git a/src/pkg/crypto/rc4/rc4_asm.go b/src/pkg/crypto/rc4/rc4_asm.go
new file mode 100644
index 0000000..0b66e4a
--- /dev/null
+++ b/src/pkg/crypto/rc4/rc4_asm.go
@@ -0,0 +1,18 @@
+// 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 amd64 arm
+
+package rc4
+
+func xorKeyStream(dst, src *byte, n int, state *[256]byte, i, j *uint8)
+
+// XORKeyStream sets dst to the result of XORing src with the key stream.
+// Dst and src may be the same slice but otherwise should not overlap.
+func (c *Cipher) XORKeyStream(dst, src []byte) {
+	if len(src) == 0 {
+		return
+	}
+	xorKeyStream(&dst[0], &src[0], len(src), &c.s, &c.i, &c.j)
+}
diff --git a/src/pkg/crypto/rc4/rc4_ref.go b/src/pkg/crypto/rc4/rc4_ref.go
new file mode 100644
index 0000000..1018548
--- /dev/null
+++ b/src/pkg/crypto/rc4/rc4_ref.go
@@ -0,0 +1,20 @@
+// 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 !amd64,!arm
+
+package rc4
+
+// XORKeyStream sets dst to the result of XORing src with the key stream.
+// Dst and src may be the same slice but otherwise should not overlap.
+func (c *Cipher) XORKeyStream(dst, src []byte) {
+	i, j := c.i, c.j
+	for k, v := range src {
+		i += 1
+		j += c.s[i]
+		c.s[i], c.s[j] = c.s[j], c.s[i]
+		dst[k] = v ^ c.s[c.s[i]+c.s[j]]
+	}
+	c.i, c.j = i, j
+}
diff --git a/src/pkg/crypto/rc4/rc4_test.go b/src/pkg/crypto/rc4/rc4_test.go
index 6265d94..9e12789 100644
--- a/src/pkg/crypto/rc4/rc4_test.go
+++ b/src/pkg/crypto/rc4/rc4_test.go
@@ -37,6 +37,39 @@ var golden = []rc4Test{
 		[]byte{0x57, 0x69, 0x6b, 0x69},
 		[]byte{0x60, 0x44, 0xdb, 0x6d, 0x41, 0xb7},
 	},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{
+			0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a,
+			0x8a, 0x06, 0x1e, 0x67, 0x57, 0x6e, 0x92, 0x6d,
+			0xc7, 0x1a, 0x7f, 0xa3, 0xf0, 0xcc, 0xeb, 0x97,
+			0x45, 0x2b, 0x4d, 0x32, 0x27, 0x96, 0x5f, 0x9e,
+			0xa8, 0xcc, 0x75, 0x07, 0x6d, 0x9f, 0xb9, 0xc5,
+			0x41, 0x7a, 0xa5, 0xcb, 0x30, 0xfc, 0x22, 0x19,
+			0x8b, 0x34, 0x98, 0x2d, 0xbb, 0x62, 0x9e, 0xc0,
+			0x4b, 0x4f, 0x8b, 0x05, 0xa0, 0x71, 0x08, 0x50,
+			0x92, 0xa0, 0xc3, 0x58, 0x4a, 0x48, 0xe4, 0xa3,
+			0x0a, 0x39, 0x7b, 0x8a, 0xcd, 0x1d, 0x00, 0x9e,
+			0xc8, 0x7d, 0x68, 0x11, 0xf2, 0x2c, 0xf4, 0x9c,
+			0xa3, 0xe5, 0x93, 0x54, 0xb9, 0x45, 0x15, 0x35,
+			0xa2, 0x18, 0x7a, 0x86, 0x42, 0x6c, 0xca, 0x7d,
+			0x5e, 0x82, 0x3e, 0xba, 0x00, 0x44, 0x12, 0x67,
+			0x12, 0x57, 0xb8, 0xd8, 0x60, 0xae, 0x4c, 0xbd,
+			0x4c, 0x49, 0x06, 0xbb, 0xc5, 0x35, 0xef, 0xe1,
+			0x58, 0x7f, 0x08, 0xdb, 0x33, 0x95, 0x5c, 0xdb,
+			0xcb, 0xad, 0x9b, 0x10, 0xf5, 0x3f, 0xc4, 0xe5,
+			0x2c, 0x59, 0x15, 0x65, 0x51, 0x84, 0x87, 0xfe,
+			0x08, 0x4d, 0x0e, 0x3f, 0x03, 0xde, 0xbc, 0xc9,
+			0xda, 0x1c, 0xe9, 0x0d, 0x08, 0x5c, 0x2d, 0x8a,
+			0x19, 0xd8, 0x37, 0x30, 0x86, 0x16, 0x36, 0x92,
+			0x14, 0x2b, 0xd8, 0xfc, 0x5d, 0x7a, 0x73, 0x49,
+			0x6a, 0x8e, 0x59, 0xee, 0x7e, 0xcf, 0x6b, 0x94,
+			0x06, 0x63, 0xf4, 0xa6, 0xbe, 0xe6, 0x5b, 0xd2,
+			0xc8, 0x5c, 0x46, 0x98, 0x6c, 0x1b, 0xef, 0x34,
+			0x90, 0xd3, 0x7b, 0x38, 0xda, 0x85, 0xd3, 0x2e,
+			0x97, 0x39, 0xcb, 0x23, 0x4a, 0x2b, 0xe7, 0x40,
+		},
+	},
 }
 
 func TestGolden(t *testing.T) {
@@ -51,9 +84,34 @@ func TestGolden(t *testing.T) {
 		c.XORKeyStream(keystream, keystream)
 		for j, v := range keystream {
 			if g.keystream[j] != v {
-				t.Errorf("Failed at golden index %d", i)
+				t.Errorf("Failed at golden index %d:\n%x\nvs\n%x", i, keystream, g.keystream)
 				break
 			}
 		}
 	}
 }
+
+func benchmark(b *testing.B, size int64) {
+	buf := make([]byte, size)
+	c, err := NewCipher(golden[0].key)
+	if err != nil {
+		panic(err)
+	}
+	b.SetBytes(size)
+
+	for i := 0; i < b.N; i++ {
+		c.XORKeyStream(buf, buf)
+	}
+}
+
+func BenchmarkRC4_128(b *testing.B) {
+	benchmark(b, 128)
+}
+
+func BenchmarkRC4_1K(b *testing.B) {
+	benchmark(b, 1024)
+}
+
+func BenchmarkRC4_8K(b *testing.B) {
+	benchmark(b, 8096)
+}
diff --git a/src/pkg/crypto/rsa/pkcs1v15.go b/src/pkg/crypto/rsa/pkcs1v15.go
index a32236e..28ca5d7 100644
--- a/src/pkg/crypto/rsa/pkcs1v15.go
+++ b/src/pkg/crypto/rsa/pkcs1v15.go
@@ -19,16 +19,19 @@ import (
 // WARNING: use of this function to encrypt plaintexts other than session keys
 // is dangerous. Use RSA OAEP in new protocols.
 func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) {
+	if err := checkPub(pub); err != nil {
+		return nil, err
+	}
 	k := (pub.N.BitLen() + 7) / 8
 	if len(msg) > k-11 {
 		err = ErrMessageTooLong
 		return
 	}
 
-	// EM = 0x02 || PS || 0x00 || M
-	em := make([]byte, k-1)
-	em[0] = 2
-	ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
+	// EM = 0x00 || 0x02 || PS || 0x00 || M
+	em := make([]byte, k)
+	em[1] = 2
+	ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
 	err = nonZeroRandomBytes(ps, rand)
 	if err != nil {
 		return
@@ -38,13 +41,18 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
 
 	m := new(big.Int).SetBytes(em)
 	c := encrypt(new(big.Int), pub, m)
-	out = c.Bytes()
+
+	copyWithLeftPad(em, c.Bytes())
+	out = em
 	return
 }
 
 // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
 // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
 func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) {
+	if err := checkPub(&priv.PublicKey); err != nil {
+		return nil, err
+	}
 	valid, out, err := decryptPKCS1v15(rand, priv, ciphertext)
 	if err == nil && valid == 0 {
 		err = ErrDecryption
@@ -67,6 +75,9 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [
 // Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
 // (Crypto '98).
 func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
+	if err := checkPub(&priv.PublicKey); err != nil {
+		return err
+	}
 	k := (priv.N.BitLen() + 7) / 8
 	if k-(len(key)+3+8) < 0 {
 		err = ErrDecryption
@@ -185,9 +196,12 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
 
 	m := new(big.Int).SetBytes(em)
 	c, err := decrypt(rand, priv, m)
-	if err == nil {
-		s = c.Bytes()
+	if err != nil {
+		return
 	}
+
+	copyWithLeftPad(em, c.Bytes())
+	s = em
 	return
 }
 
@@ -233,11 +247,21 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
 func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
 	hashLen = hash.Size()
 	if inLen != hashLen {
-		return 0, nil, errors.New("input must be hashed message")
+		return 0, nil, errors.New("crypto/rsa: input must be hashed message")
 	}
 	prefix, ok := hashPrefixes[hash]
 	if !ok {
-		return 0, nil, errors.New("unsupported hash function")
+		return 0, nil, errors.New("crypto/rsa: unsupported hash function")
 	}
 	return
 }
+
+// copyWithLeftPad copies src to the end of dest, padding with zero bytes as
+// needed.
+func copyWithLeftPad(dest, src []byte) {
+	numPaddingBytes := len(dest) - len(src)
+	for i := 0; i < numPaddingBytes; i++ {
+		dest[i] = 0
+	}
+	copy(dest[numPaddingBytes:], src)
+}
diff --git a/src/pkg/crypto/rsa/pkcs1v15_test.go b/src/pkg/crypto/rsa/pkcs1v15_test.go
index 58d5fda..bf9219b 100644
--- a/src/pkg/crypto/rsa/pkcs1v15_test.go
+++ b/src/pkg/crypto/rsa/pkcs1v15_test.go
@@ -57,7 +57,7 @@ func TestDecryptPKCS1v15(t *testing.T) {
 			t.Errorf("#%d error decrypting", i)
 		}
 		want := []byte(test.out)
-		if bytes.Compare(out, want) != 0 {
+		if !bytes.Equal(out, want) {
 			t.Errorf("#%d got:%#v want:%#v", i, out, want)
 		}
 	}
@@ -90,7 +90,7 @@ func TestEncryptPKCS1v15(t *testing.T) {
 			return false
 		}
 
-		if bytes.Compare(plaintext, in) != 0 {
+		if !bytes.Equal(plaintext, in) {
 			t.Errorf("output mismatch: %#v %#v", plaintext, in)
 			return false
 		}
@@ -132,7 +132,7 @@ func TestEncryptPKCS1v15SessionKey(t *testing.T) {
 			t.Errorf("#%d error decrypting", i)
 		}
 		want := []byte(test.out)
-		if bytes.Compare(key, want) != 0 {
+		if !bytes.Equal(key, want) {
 			t.Errorf("#%d got:%#v want:%#v", i, key, want)
 		}
 	}
@@ -176,7 +176,7 @@ func TestSignPKCS1v15(t *testing.T) {
 		}
 
 		expected, _ := hex.DecodeString(test.out)
-		if bytes.Compare(s, expected) != 0 {
+		if !bytes.Equal(s, expected) {
 			t.Errorf("#%d got: %x want: %x", i, s, expected)
 		}
 	}
diff --git a/src/pkg/crypto/rsa/rsa.go b/src/pkg/crypto/rsa/rsa.go
index ec77e68..35a5f7c 100644
--- a/src/pkg/crypto/rsa/rsa.go
+++ b/src/pkg/crypto/rsa/rsa.go
@@ -25,6 +25,30 @@ type PublicKey struct {
 	E int      // public exponent
 }
 
+var (
+	errPublicModulus       = errors.New("crypto/rsa: missing public modulus")
+	errPublicExponentSmall = errors.New("crypto/rsa: public exponent too small")
+	errPublicExponentLarge = errors.New("crypto/rsa: public exponent too large")
+)
+
+// checkPub sanity checks the public key before we use it.
+// We require pub.E to fit into a 32-bit integer so that we
+// do not have different behavior depending on whether
+// int is 32 or 64 bits. See also
+// http://www.imperialviolet.org/2012/03/16/rsae.html.
+func checkPub(pub *PublicKey) error {
+	if pub.N == nil {
+		return errPublicModulus
+	}
+	if pub.E < 2 {
+		return errPublicExponentSmall
+	}
+	if pub.E > 1<<31-1 {
+		return errPublicExponentLarge
+	}
+	return nil
+}
+
 // A PrivateKey represents an RSA key
 type PrivateKey struct {
 	PublicKey            // public part.
@@ -37,7 +61,7 @@ type PrivateKey struct {
 }
 
 type PrecomputedValues struct {
-	Dp, Dq *big.Int // D mod (P-1) (or mod Q-1) 
+	Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
 	Qinv   *big.Int // Q^-1 mod Q
 
 	// CRTValues is used for the 3rd and subsequent primes. Due to a
@@ -57,13 +81,17 @@ type CRTValue struct {
 // Validate performs basic sanity checks on the key.
 // It returns nil if the key is valid, or else an error describing a problem.
 func (priv *PrivateKey) Validate() error {
+	if err := checkPub(&priv.PublicKey); err != nil {
+		return err
+	}
+
 	// Check that the prime factors are actually prime. Note that this is
 	// just a sanity check. Since the random witnesses chosen by
 	// ProbablyPrime are deterministic, given the candidate number, it's
 	// easy for an attack to generate composites that pass this test.
 	for _, prime := range priv.Primes {
 		if !prime.ProbablyPrime(20) {
-			return errors.New("prime factor is composite")
+			return errors.New("crypto/rsa: prime factor is composite")
 		}
 	}
 
@@ -73,27 +101,23 @@ func (priv *PrivateKey) Validate() error {
 		modulus.Mul(modulus, prime)
 	}
 	if modulus.Cmp(priv.N) != 0 {
-		return errors.New("invalid modulus")
+		return errors.New("crypto/rsa: invalid modulus")
 	}
-	// Check that e and totient(Πprimes) are coprime.
-	totient := new(big.Int).Set(bigOne)
+
+	// Check that de ≡ 1 mod p-1, for each prime.
+	// This implies that e is coprime to each p-1 as e has a multiplicative
+	// inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) =
+	// exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1
+	// mod p. Thus a^de ≡ a mod n for all a coprime to n, as required.
+	congruence := new(big.Int)
+	de := new(big.Int).SetInt64(int64(priv.E))
+	de.Mul(de, priv.D)
 	for _, prime := range priv.Primes {
 		pminus1 := new(big.Int).Sub(prime, bigOne)
-		totient.Mul(totient, pminus1)
-	}
-	e := big.NewInt(int64(priv.E))
-	gcd := new(big.Int)
-	x := new(big.Int)
-	y := new(big.Int)
-	gcd.GCD(x, y, totient, e)
-	if gcd.Cmp(bigOne) != 0 {
-		return errors.New("invalid public exponent E")
-	}
-	// Check that de ≡ 1 (mod totient(Πprimes))
-	de := new(big.Int).Mul(priv.D, e)
-	de.Mod(de, totient)
-	if de.Cmp(bigOne) != 0 {
-		return errors.New("invalid private exponent D")
+		congruence.Mod(de, pminus1)
+		if congruence.Cmp(bigOne) != 0 {
+			return errors.New("crypto/rsa: invalid exponents")
+		}
 	}
 	return nil
 }
@@ -118,7 +142,7 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *Priva
 	priv.E = 65537
 
 	if nprimes < 2 {
-		return nil, errors.New("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
+		return nil, errors.New("crypto/rsa: GenerateMultiPrimeKey: nprimes must be >= 2")
 	}
 
 	primes := make([]*big.Int, nprimes)
@@ -126,6 +150,20 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *Priva
 NextSetOfPrimes:
 	for {
 		todo := bits
+		// crypto/rand should set the top two bits in each prime.
+		// Thus each prime has the form
+		//   p_i = 2^bitlen(p_i) × 0.11... (in base 2).
+		// And the product is:
+		//   P = 2^todo × α
+		// where α is the product of nprimes numbers of the form 0.11...
+		//
+		// If α < 1/2 (which can happen for nprimes > 2), we need to
+		// shift todo to compensate for lost bits: the mean value of 0.11...
+		// is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2
+		// will give good results.
+		if nprimes >= 7 {
+			todo += (nprimes - 2) / 5
+		}
 		for i := 0; i < nprimes; i++ {
 			primes[i], err = rand.Prime(random, todo/(nprimes-i))
 			if err != nil {
@@ -151,6 +189,12 @@ NextSetOfPrimes:
 			pminus1.Sub(prime, bigOne)
 			totient.Mul(totient, pminus1)
 		}
+		if n.BitLen() != bits {
+			// This should never happen for nprimes == 2 because
+			// crypto/rand should set the top two bits in each prime.
+			// For nprimes > 2 we hope it does not happen often.
+			continue NextSetOfPrimes
+		}
 
 		g := new(big.Int)
 		priv.D = new(big.Int)
@@ -220,6 +264,9 @@ func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
 // The message must be no longer than the length of the public modulus less
 // twice the hash length plus 2.
 func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error) {
+	if err := checkPub(pub); err != nil {
+		return nil, err
+	}
 	hash.Reset()
 	k := (pub.N.BitLen() + 7) / 8
 	if len(msg) > k-2*hash.Size()-2 {
@@ -406,6 +453,9 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er
 // DecryptOAEP decrypts ciphertext using RSA-OAEP.
 // If random != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
 func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
+	if err := checkPub(&priv.PublicKey); err != nil {
+		return nil, err
+	}
 	k := (priv.N.BitLen() + 7) / 8
 	if len(ciphertext) > k ||
 		k < hash.Size()*2+2 {
diff --git a/src/pkg/crypto/rsa/rsa_test.go b/src/pkg/crypto/rsa/rsa_test.go
index 0fb9875..f08cfe7 100644
--- a/src/pkg/crypto/rsa/rsa_test.go
+++ b/src/pkg/crypto/rsa/rsa_test.go
@@ -21,15 +21,18 @@ func TestKeyGeneration(t *testing.T) {
 	if err != nil {
 		t.Errorf("failed to generate key")
 	}
+	if bits := priv.N.BitLen(); bits != size {
+		t.Errorf("key too short (%d vs %d)", bits, size)
+	}
 	testKeyBasics(t, priv)
 }
 
 func Test3PrimeKeyGeneration(t *testing.T) {
+	size := 768
 	if testing.Short() {
-		return
+		size = 256
 	}
 
-	size := 768
 	priv, err := GenerateMultiPrimeKey(rand.Reader, 3, size)
 	if err != nil {
 		t.Errorf("failed to generate key")
@@ -38,11 +41,11 @@ func Test3PrimeKeyGeneration(t *testing.T) {
 }
 
 func Test4PrimeKeyGeneration(t *testing.T) {
+	size := 768
 	if testing.Short() {
-		return
+		size = 256
 	}
 
-	size := 768
 	priv, err := GenerateMultiPrimeKey(rand.Reader, 4, size)
 	if err != nil {
 		t.Errorf("failed to generate key")
@@ -50,6 +53,42 @@ func Test4PrimeKeyGeneration(t *testing.T) {
 	testKeyBasics(t, priv)
 }
 
+func TestNPrimeKeyGeneration(t *testing.T) {
+	primeSize := 64
+	maxN := 24
+	if testing.Short() {
+		primeSize = 16
+		maxN = 16
+	}
+	// Test that generation of N-prime keys works for N > 4.
+	for n := 5; n < maxN; n++ {
+		priv, err := GenerateMultiPrimeKey(rand.Reader, n, 64+n*primeSize)
+		if err == nil {
+			testKeyBasics(t, priv)
+		} else {
+			t.Errorf("failed to generate %d-prime key", n)
+		}
+	}
+}
+
+func TestGnuTLSKey(t *testing.T) {
+	// This is a key generated by `certtool --generate-privkey --bits 128`.
+	// It's such that de ≢ 1 mod φ(n), but is congruent mod the order of
+	// the group.
+	priv := &PrivateKey{
+		PublicKey: PublicKey{
+			N: fromBase10("290684273230919398108010081414538931343"),
+			E: 65537,
+		},
+		D: fromBase10("31877380284581499213530787347443987241"),
+		Primes: []*big.Int{
+			fromBase10("16775196964030542637"),
+			fromBase10("17328218193455850539"),
+		},
+	}
+	testKeyBasics(t, priv)
+}
+
 func testKeyBasics(t *testing.T, priv *PrivateKey) {
 	if err := priv.Validate(); err != nil {
 		t.Errorf("Validate() failed: %s", err)
@@ -98,7 +137,7 @@ func BenchmarkRSA2048Decrypt(b *testing.B) {
 	}
 	priv.Precompute()
 
-	c := fromBase10("1000")
+	c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
 
 	b.StartTimer()
 
@@ -123,7 +162,7 @@ func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
 	}
 	priv.Precompute()
 
-	c := fromBase10("1000")
+	c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
 
 	b.StartTimer()
 
@@ -158,7 +197,7 @@ func TestEncryptOAEP(t *testing.T) {
 			if err != nil {
 				t.Errorf("#%d,%d error: %s", i, j, err)
 			}
-			if bytes.Compare(out, message.out) != 0 {
+			if !bytes.Equal(out, message.out) {
 				t.Errorf("#%d,%d bad result: %x (want %x)", i, j, out, message.out)
 			}
 		}
@@ -182,7 +221,7 @@ func TestDecryptOAEP(t *testing.T) {
 			out, err := DecryptOAEP(sha1, nil, private, message.out, nil)
 			if err != nil {
 				t.Errorf("#%d,%d error: %s", i, j, err)
-			} else if bytes.Compare(out, message.in) != 0 {
+			} else if !bytes.Equal(out, message.in) {
 				t.Errorf("#%d,%d bad result: %#v (want %#v)", i, j, out, message.in)
 			}
 
@@ -190,7 +229,7 @@ func TestDecryptOAEP(t *testing.T) {
 			out, err = DecryptOAEP(sha1, random, private, message.out, nil)
 			if err != nil {
 				t.Errorf("#%d,%d (blind) error: %s", i, j, err)
-			} else if bytes.Compare(out, message.in) != 0 {
+			} else if !bytes.Equal(out, message.in) {
 				t.Errorf("#%d,%d (blind) bad result: %#v (want %#v)", i, j, out, message.in)
 			}
 		}
diff --git a/src/pkg/crypto/sha1/sha1.go b/src/pkg/crypto/sha1/sha1.go
index 876e799..7cfde47 100644
--- a/src/pkg/crypto/sha1/sha1.go
+++ b/src/pkg/crypto/sha1/sha1.go
@@ -21,28 +21,28 @@ const Size = 20
 const BlockSize = 64
 
 const (
-	_Chunk = 64
-	_Init0 = 0x67452301
-	_Init1 = 0xEFCDAB89
-	_Init2 = 0x98BADCFE
-	_Init3 = 0x10325476
-	_Init4 = 0xC3D2E1F0
+	chunk = 64
+	init0 = 0x67452301
+	init1 = 0xEFCDAB89
+	init2 = 0x98BADCFE
+	init3 = 0x10325476
+	init4 = 0xC3D2E1F0
 )
 
 // digest represents the partial evaluation of a checksum.
 type digest struct {
 	h   [5]uint32
-	x   [_Chunk]byte
+	x   [chunk]byte
 	nx  int
 	len uint64
 }
 
 func (d *digest) Reset() {
-	d.h[0] = _Init0
-	d.h[1] = _Init1
-	d.h[2] = _Init2
-	d.h[3] = _Init3
-	d.h[4] = _Init4
+	d.h[0] = init0
+	d.h[1] = init1
+	d.h[2] = init2
+	d.h[3] = init3
+	d.h[4] = init4
 	d.nx = 0
 	d.len = 0
 }
@@ -63,21 +63,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
 	d.len += uint64(nn)
 	if d.nx > 0 {
 		n := len(p)
-		if n > _Chunk-d.nx {
-			n = _Chunk - d.nx
+		if n > chunk-d.nx {
+			n = chunk - d.nx
 		}
 		for i := 0; i < n; i++ {
 			d.x[d.nx+i] = p[i]
 		}
 		d.nx += n
-		if d.nx == _Chunk {
-			_Block(d, d.x[0:])
+		if d.nx == chunk {
+			block(d, d.x[0:])
 			d.nx = 0
 		}
 		p = p[n:]
 	}
-	n := _Block(d, p)
-	p = p[n:]
+	if len(p) >= chunk {
+		n := len(p) &^ (chunk - 1)
+		block(d, p[:n])
+		p = p[n:]
+	}
 	if len(p) > 0 {
 		d.nx = copy(d.x[:], p)
 	}
diff --git a/src/pkg/crypto/sha1/sha1_test.go b/src/pkg/crypto/sha1/sha1_test.go
index 2dc14ac..57cd431 100644
--- a/src/pkg/crypto/sha1/sha1_test.go
+++ b/src/pkg/crypto/sha1/sha1_test.go
@@ -4,10 +4,9 @@
 
 // SHA1 hash algorithm.  See RFC 3174.
 
-package sha1_test
+package sha1
 
 import (
-	"crypto/sha1"
 	"fmt"
 	"io"
 	"testing"
@@ -55,7 +54,7 @@ var golden = []sha1Test{
 func TestGolden(t *testing.T) {
 	for i := 0; i < len(golden); i++ {
 		g := golden[i]
-		c := sha1.New()
+		c := New()
 		for j := 0; j < 3; j++ {
 			if j < 2 {
 				io.WriteString(c, g.in)
@@ -74,8 +73,33 @@ func TestGolden(t *testing.T) {
 }
 
 func ExampleNew() {
-	h := sha1.New()
+	h := New()
 	io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.")
 	fmt.Printf("% x", h.Sum(nil))
 	// Output: 59 7f 6a 54 00 10 f9 4c 15 d7 18 06 a9 9a 2c 87 10 e7 47 bd
 }
+
+var bench = New()
+var buf = make([]byte, 8192)
+
+func benchmarkSize(b *testing.B, size int) {
+	b.SetBytes(int64(size))
+	sum := make([]byte, bench.Size())
+	for i := 0; i < b.N; i++ {
+		bench.Reset()
+		bench.Write(buf[:size])
+		bench.Sum(sum[:0])
+	}
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+	benchmarkSize(b, 8)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+	benchmarkSize(b, 1024)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+	benchmarkSize(b, 8192)
+}
diff --git a/src/pkg/crypto/sha1/sha1block.go b/src/pkg/crypto/sha1/sha1block.go
index b5d32af..1c9507c 100644
--- a/src/pkg/crypto/sha1/sha1block.go
+++ b/src/pkg/crypto/sha1/sha1block.go
@@ -15,54 +15,67 @@ const (
 	_K3 = 0xCA62C1D6
 )
 
-func _Block(dig *digest, p []byte) int {
-	var w [80]uint32
+func block(dig *digest, p []byte) {
+	var w [16]uint32
 
-	n := 0
 	h0, h1, h2, h3, h4 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4]
-	for len(p) >= _Chunk {
+	for len(p) >= chunk {
 		// Can interlace the computation of w with the
 		// rounds below if needed for speed.
 		for i := 0; i < 16; i++ {
 			j := i * 4
 			w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
 		}
-		for i := 16; i < 80; i++ {
-			tmp := w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]
-			w[i] = tmp<<1 | tmp>>(32-1)
-		}
 
 		a, b, c, d, e := h0, h1, h2, h3, h4
 
 		// Each of the four 20-iteration rounds
 		// differs only in the computation of f and
 		// the choice of K (_K0, _K1, etc).
-		for i := 0; i < 20; i++ {
+		i := 0
+		for ; i < 16; i++ {
+			f := b&c | (^b)&d
+			a5 := a<<5 | a>>(32-5)
+			b30 := b<<30 | b>>(32-30)
+			t := a5 + f + e + w[i&0xf] + _K0
+			a, b, c, d, e = t, a, b30, c, d
+		}
+		for ; i < 20; i++ {
+			tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+			w[i&0xf] = tmp<<1 | tmp>>(32-1)
+
 			f := b&c | (^b)&d
 			a5 := a<<5 | a>>(32-5)
 			b30 := b<<30 | b>>(32-30)
-			t := a5 + f + e + w[i] + _K0
+			t := a5 + f + e + w[i&0xf] + _K0
 			a, b, c, d, e = t, a, b30, c, d
 		}
-		for i := 20; i < 40; i++ {
+		for ; i < 40; i++ {
+			tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+			w[i&0xf] = tmp<<1 | tmp>>(32-1)
 			f := b ^ c ^ d
 			a5 := a<<5 | a>>(32-5)
 			b30 := b<<30 | b>>(32-30)
-			t := a5 + f + e + w[i] + _K1
+			t := a5 + f + e + w[i&0xf] + _K1
 			a, b, c, d, e = t, a, b30, c, d
 		}
-		for i := 40; i < 60; i++ {
-			f := b&c | b&d | c&d
+		for ; i < 60; i++ {
+			tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+			w[i&0xf] = tmp<<1 | tmp>>(32-1)
+			f := ((b | c) & d) | (b & c)
+
 			a5 := a<<5 | a>>(32-5)
 			b30 := b<<30 | b>>(32-30)
-			t := a5 + f + e + w[i] + _K2
+			t := a5 + f + e + w[i&0xf] + _K2
 			a, b, c, d, e = t, a, b30, c, d
 		}
-		for i := 60; i < 80; i++ {
+		for ; i < 80; i++ {
+			tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
+			w[i&0xf] = tmp<<1 | tmp>>(32-1)
 			f := b ^ c ^ d
 			a5 := a<<5 | a>>(32-5)
 			b30 := b<<30 | b>>(32-30)
-			t := a5 + f + e + w[i] + _K3
+			t := a5 + f + e + w[i&0xf] + _K3
 			a, b, c, d, e = t, a, b30, c, d
 		}
 
@@ -72,10 +85,8 @@ func _Block(dig *digest, p []byte) int {
 		h3 += d
 		h4 += e
 
-		p = p[_Chunk:]
-		n += _Chunk
+		p = p[chunk:]
 	}
 
 	dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4] = h0, h1, h2, h3, h4
-	return n
 }
diff --git a/src/pkg/crypto/sha256/sha256.go b/src/pkg/crypto/sha256/sha256.go
index a61e30b..dc0e18f 100644
--- a/src/pkg/crypto/sha256/sha256.go
+++ b/src/pkg/crypto/sha256/sha256.go
@@ -26,29 +26,29 @@ const Size224 = 28
 const BlockSize = 64
 
 const (
-	_Chunk     = 64
-	_Init0     = 0x6A09E667
-	_Init1     = 0xBB67AE85
-	_Init2     = 0x3C6EF372
-	_Init3     = 0xA54FF53A
-	_Init4     = 0x510E527F
-	_Init5     = 0x9B05688C
-	_Init6     = 0x1F83D9AB
-	_Init7     = 0x5BE0CD19
-	_Init0_224 = 0xC1059ED8
-	_Init1_224 = 0x367CD507
-	_Init2_224 = 0x3070DD17
-	_Init3_224 = 0xF70E5939
-	_Init4_224 = 0xFFC00B31
-	_Init5_224 = 0x68581511
-	_Init6_224 = 0x64F98FA7
-	_Init7_224 = 0xBEFA4FA4
+	chunk     = 64
+	init0     = 0x6A09E667
+	init1     = 0xBB67AE85
+	init2     = 0x3C6EF372
+	init3     = 0xA54FF53A
+	init4     = 0x510E527F
+	init5     = 0x9B05688C
+	init6     = 0x1F83D9AB
+	init7     = 0x5BE0CD19
+	init0_224 = 0xC1059ED8
+	init1_224 = 0x367CD507
+	init2_224 = 0x3070DD17
+	init3_224 = 0xF70E5939
+	init4_224 = 0xFFC00B31
+	init5_224 = 0x68581511
+	init6_224 = 0x64F98FA7
+	init7_224 = 0xBEFA4FA4
 )
 
 // digest represents the partial evaluation of a checksum.
 type digest struct {
 	h     [8]uint32
-	x     [_Chunk]byte
+	x     [chunk]byte
 	nx    int
 	len   uint64
 	is224 bool // mark if this digest is SHA-224
@@ -56,23 +56,23 @@ type digest struct {
 
 func (d *digest) Reset() {
 	if !d.is224 {
-		d.h[0] = _Init0
-		d.h[1] = _Init1
-		d.h[2] = _Init2
-		d.h[3] = _Init3
-		d.h[4] = _Init4
-		d.h[5] = _Init5
-		d.h[6] = _Init6
-		d.h[7] = _Init7
+		d.h[0] = init0
+		d.h[1] = init1
+		d.h[2] = init2
+		d.h[3] = init3
+		d.h[4] = init4
+		d.h[5] = init5
+		d.h[6] = init6
+		d.h[7] = init7
 	} else {
-		d.h[0] = _Init0_224
-		d.h[1] = _Init1_224
-		d.h[2] = _Init2_224
-		d.h[3] = _Init3_224
-		d.h[4] = _Init4_224
-		d.h[5] = _Init5_224
-		d.h[6] = _Init6_224
-		d.h[7] = _Init7_224
+		d.h[0] = init0_224
+		d.h[1] = init1_224
+		d.h[2] = init2_224
+		d.h[3] = init3_224
+		d.h[4] = init4_224
+		d.h[5] = init5_224
+		d.h[6] = init6_224
+		d.h[7] = init7_224
 	}
 	d.nx = 0
 	d.len = 0
@@ -107,21 +107,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
 	d.len += uint64(nn)
 	if d.nx > 0 {
 		n := len(p)
-		if n > _Chunk-d.nx {
-			n = _Chunk - d.nx
+		if n > chunk-d.nx {
+			n = chunk - d.nx
 		}
 		for i := 0; i < n; i++ {
 			d.x[d.nx+i] = p[i]
 		}
 		d.nx += n
-		if d.nx == _Chunk {
-			_Block(d, d.x[0:])
+		if d.nx == chunk {
+			block(d, d.x[0:])
 			d.nx = 0
 		}
 		p = p[n:]
 	}
-	n := _Block(d, p)
-	p = p[n:]
+	if len(p) >= chunk {
+		n := len(p) &^ (chunk - 1)
+		block(d, p[:n])
+		p = p[n:]
+	}
 	if len(p) > 0 {
 		d.nx = copy(d.x[:], p)
 	}
diff --git a/src/pkg/crypto/sha256/sha256_test.go b/src/pkg/crypto/sha256/sha256_test.go
index a6efb37..29bf161 100644
--- a/src/pkg/crypto/sha256/sha256_test.go
+++ b/src/pkg/crypto/sha256/sha256_test.go
@@ -123,3 +123,28 @@ func TestGolden(t *testing.T) {
 		}
 	}
 }
+
+var bench = New()
+var buf = make([]byte, 8192)
+
+func benchmarkSize(b *testing.B, size int) {
+	b.SetBytes(int64(size))
+	sum := make([]byte, bench.Size())
+	for i := 0; i < b.N; i++ {
+		bench.Reset()
+		bench.Write(buf[:size])
+		bench.Sum(sum[:0])
+	}
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+	benchmarkSize(b, 8)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+	benchmarkSize(b, 1024)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+	benchmarkSize(b, 8192)
+}
diff --git a/src/pkg/crypto/sha256/sha256block.go b/src/pkg/crypto/sha256/sha256block.go
index 7b0f554..2ac4910 100644
--- a/src/pkg/crypto/sha256/sha256block.go
+++ b/src/pkg/crypto/sha256/sha256block.go
@@ -75,11 +75,10 @@ var _K = []uint32{
 	0xc67178f2,
 }
 
-func _Block(dig *digest, p []byte) int {
+func block(dig *digest, p []byte) {
 	var w [64]uint32
-	n := 0
 	h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
-	for len(p) >= _Chunk {
+	for len(p) >= chunk {
 		// Can interlace the computation of w with the
 		// rounds below if needed for speed.
 		for i := 0; i < 16; i++ {
@@ -87,10 +86,10 @@ func _Block(dig *digest, p []byte) int {
 			w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
 		}
 		for i := 16; i < 64; i++ {
-			t1 := (w[i-2]>>17 | w[i-2]<<(32-17)) ^ (w[i-2]>>19 | w[i-2]<<(32-19)) ^ (w[i-2] >> 10)
-
-			t2 := (w[i-15]>>7 | w[i-15]<<(32-7)) ^ (w[i-15]>>18 | w[i-15]<<(32-18)) ^ (w[i-15] >> 3)
-
+			v1 := w[i-2]
+			t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10)
+			v2 := w[i-15]
+			t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3)
 			w[i] = t1 + w[i-7] + t2 + w[i-16]
 		}
 
@@ -120,10 +119,8 @@ func _Block(dig *digest, p []byte) int {
 		h6 += g
 		h7 += h
 
-		p = p[_Chunk:]
-		n += _Chunk
+		p = p[chunk:]
 	}
 
 	dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
-	return n
 }
diff --git a/src/pkg/crypto/sha512/sha512.go b/src/pkg/crypto/sha512/sha512.go
index a245fd6..4aec529 100644
--- a/src/pkg/crypto/sha512/sha512.go
+++ b/src/pkg/crypto/sha512/sha512.go
@@ -26,29 +26,29 @@ const Size384 = 48
 const BlockSize = 128
 
 const (
-	_Chunk     = 128
-	_Init0     = 0x6a09e667f3bcc908
-	_Init1     = 0xbb67ae8584caa73b
-	_Init2     = 0x3c6ef372fe94f82b
-	_Init3     = 0xa54ff53a5f1d36f1
-	_Init4     = 0x510e527fade682d1
-	_Init5     = 0x9b05688c2b3e6c1f
-	_Init6     = 0x1f83d9abfb41bd6b
-	_Init7     = 0x5be0cd19137e2179
-	_Init0_384 = 0xcbbb9d5dc1059ed8
-	_Init1_384 = 0x629a292a367cd507
-	_Init2_384 = 0x9159015a3070dd17
-	_Init3_384 = 0x152fecd8f70e5939
-	_Init4_384 = 0x67332667ffc00b31
-	_Init5_384 = 0x8eb44a8768581511
-	_Init6_384 = 0xdb0c2e0d64f98fa7
-	_Init7_384 = 0x47b5481dbefa4fa4
+	chunk     = 128
+	init0     = 0x6a09e667f3bcc908
+	init1     = 0xbb67ae8584caa73b
+	init2     = 0x3c6ef372fe94f82b
+	init3     = 0xa54ff53a5f1d36f1
+	init4     = 0x510e527fade682d1
+	init5     = 0x9b05688c2b3e6c1f
+	init6     = 0x1f83d9abfb41bd6b
+	init7     = 0x5be0cd19137e2179
+	init0_384 = 0xcbbb9d5dc1059ed8
+	init1_384 = 0x629a292a367cd507
+	init2_384 = 0x9159015a3070dd17
+	init3_384 = 0x152fecd8f70e5939
+	init4_384 = 0x67332667ffc00b31
+	init5_384 = 0x8eb44a8768581511
+	init6_384 = 0xdb0c2e0d64f98fa7
+	init7_384 = 0x47b5481dbefa4fa4
 )
 
 // digest represents the partial evaluation of a checksum.
 type digest struct {
 	h     [8]uint64
-	x     [_Chunk]byte
+	x     [chunk]byte
 	nx    int
 	len   uint64
 	is384 bool // mark if this digest is SHA-384
@@ -56,23 +56,23 @@ type digest struct {
 
 func (d *digest) Reset() {
 	if !d.is384 {
-		d.h[0] = _Init0
-		d.h[1] = _Init1
-		d.h[2] = _Init2
-		d.h[3] = _Init3
-		d.h[4] = _Init4
-		d.h[5] = _Init5
-		d.h[6] = _Init6
-		d.h[7] = _Init7
+		d.h[0] = init0
+		d.h[1] = init1
+		d.h[2] = init2
+		d.h[3] = init3
+		d.h[4] = init4
+		d.h[5] = init5
+		d.h[6] = init6
+		d.h[7] = init7
 	} else {
-		d.h[0] = _Init0_384
-		d.h[1] = _Init1_384
-		d.h[2] = _Init2_384
-		d.h[3] = _Init3_384
-		d.h[4] = _Init4_384
-		d.h[5] = _Init5_384
-		d.h[6] = _Init6_384
-		d.h[7] = _Init7_384
+		d.h[0] = init0_384
+		d.h[1] = init1_384
+		d.h[2] = init2_384
+		d.h[3] = init3_384
+		d.h[4] = init4_384
+		d.h[5] = init5_384
+		d.h[6] = init6_384
+		d.h[7] = init7_384
 	}
 	d.nx = 0
 	d.len = 0
@@ -107,21 +107,24 @@ func (d *digest) Write(p []byte) (nn int, err error) {
 	d.len += uint64(nn)
 	if d.nx > 0 {
 		n := len(p)
-		if n > _Chunk-d.nx {
-			n = _Chunk - d.nx
+		if n > chunk-d.nx {
+			n = chunk - d.nx
 		}
 		for i := 0; i < n; i++ {
 			d.x[d.nx+i] = p[i]
 		}
 		d.nx += n
-		if d.nx == _Chunk {
-			_Block(d, d.x[0:])
+		if d.nx == chunk {
+			block(d, d.x[0:])
 			d.nx = 0
 		}
 		p = p[n:]
 	}
-	n := _Block(d, p)
-	p = p[n:]
+	if len(p) >= chunk {
+		n := len(p) &^ (chunk - 1)
+		block(d, p[:n])
+		p = p[n:]
+	}
 	if len(p) > 0 {
 		d.nx = copy(d.x[:], p)
 	}
diff --git a/src/pkg/crypto/sha512/sha512_test.go b/src/pkg/crypto/sha512/sha512_test.go
index a70f7c5..6eafb1b 100644
--- a/src/pkg/crypto/sha512/sha512_test.go
+++ b/src/pkg/crypto/sha512/sha512_test.go
@@ -123,3 +123,28 @@ func TestGolden(t *testing.T) {
 		}
 	}
 }
+
+var bench = New()
+var buf = make([]byte, 8192)
+
+func benchmarkSize(b *testing.B, size int) {
+	b.SetBytes(int64(size))
+	sum := make([]byte, bench.Size())
+	for i := 0; i < b.N; i++ {
+		bench.Reset()
+		bench.Write(buf[:size])
+		bench.Sum(sum[:0])
+	}
+}
+
+func BenchmarkHash8Bytes(b *testing.B) {
+	benchmarkSize(b, 8)
+}
+
+func BenchmarkHash1K(b *testing.B) {
+	benchmarkSize(b, 1024)
+}
+
+func BenchmarkHash8K(b *testing.B) {
+	benchmarkSize(b, 8192)
+}
diff --git a/src/pkg/crypto/sha512/sha512block.go b/src/pkg/crypto/sha512/sha512block.go
index 6b75062..3577b4f 100644
--- a/src/pkg/crypto/sha512/sha512block.go
+++ b/src/pkg/crypto/sha512/sha512block.go
@@ -91,20 +91,20 @@ var _K = []uint64{
 	0x6c44198c4a475817,
 }
 
-func _Block(dig *digest, p []byte) int {
+func block(dig *digest, p []byte) {
 	var w [80]uint64
-	n := 0
 	h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
-	for len(p) >= _Chunk {
+	for len(p) >= chunk {
 		for i := 0; i < 16; i++ {
 			j := i * 8
 			w[i] = uint64(p[j])<<56 | uint64(p[j+1])<<48 | uint64(p[j+2])<<40 | uint64(p[j+3])<<32 |
 				uint64(p[j+4])<<24 | uint64(p[j+5])<<16 | uint64(p[j+6])<<8 | uint64(p[j+7])
 		}
 		for i := 16; i < 80; i++ {
-			t1 := (w[i-2]>>19 | w[i-2]<<(64-19)) ^ (w[i-2]>>61 | w[i-2]<<(64-61)) ^ (w[i-2] >> 6)
-
-			t2 := (w[i-15]>>1 | w[i-15]<<(64-1)) ^ (w[i-15]>>8 | w[i-15]<<(64-8)) ^ (w[i-15] >> 7)
+			v1 := w[i-2]
+			t1 := (v1>>19 | v1<<(64-19)) ^ (v1>>61 | v1<<(64-61)) ^ (v1 >> 6)
+			v2 := w[i-15]
+			t2 := (v2>>1 | v2<<(64-1)) ^ (v2>>8 | v2<<(64-8)) ^ (v2 >> 7)
 
 			w[i] = t1 + w[i-7] + t2 + w[i-16]
 		}
@@ -135,10 +135,8 @@ func _Block(dig *digest, p []byte) int {
 		h6 += g
 		h7 += h
 
-		p = p[_Chunk:]
-		n += _Chunk
+		p = p[chunk:]
 	}
 
 	dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
-	return n
 }
diff --git a/src/pkg/crypto/tls/cipher_suites.go b/src/pkg/crypto/tls/cipher_suites.go
index 5039f31..a647e19 100644
--- a/src/pkg/crypto/tls/cipher_suites.go
+++ b/src/pkg/crypto/tls/cipher_suites.go
@@ -55,9 +55,11 @@ var cipherSuites = []*cipherSuite{
 	{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
 	{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, false, cipher3DES, macSHA1},
 	{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1},
+	{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, false, cipherAES, macSHA1},
 	{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
 	{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, true, cipher3DES, macSHA1},
 	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
+	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
 }
 
 func cipherRC4(key, iv []byte, isRead bool) interface{} {
@@ -182,7 +184,9 @@ const (
 	TLS_RSA_WITH_RC4_128_SHA            uint16 = 0x0005
 	TLS_RSA_WITH_3DES_EDE_CBC_SHA       uint16 = 0x000a
 	TLS_RSA_WITH_AES_128_CBC_SHA        uint16 = 0x002f
+	TLS_RSA_WITH_AES_256_CBC_SHA        uint16 = 0x0035
 	TLS_ECDHE_RSA_WITH_RC4_128_SHA      uint16 = 0xc011
 	TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
 	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA  uint16 = 0xc013
+	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA  uint16 = 0xc014
 )
diff --git a/src/pkg/crypto/tls/common.go b/src/pkg/crypto/tls/common.go
index 4ba0bf8..a888df7 100644
--- a/src/pkg/crypto/tls/common.go
+++ b/src/pkg/crypto/tls/common.go
@@ -41,6 +41,7 @@ const (
 const (
 	typeClientHello        uint8 = 1
 	typeServerHello        uint8 = 2
+	typeNewSessionTicket   uint8 = 4
 	typeCertificate        uint8 = 11
 	typeServerKeyExchange  uint8 = 12
 	typeCertificateRequest uint8 = 13
@@ -63,6 +64,7 @@ var (
 	extensionStatusRequest   uint16 = 5
 	extensionSupportedCurves uint16 = 10
 	extensionSupportedPoints uint16 = 11
+	extensionSessionTicket   uint16 = 35
 	extensionNextProtoNeg    uint16 = 13172 // not IANA assigned
 )
 
@@ -97,6 +99,7 @@ const (
 // ConnectionState records basic TLS details about the connection.
 type ConnectionState struct {
 	HandshakeComplete          bool
+	DidResume                  bool
 	CipherSuite                uint16
 	NegotiatedProtocol         string
 	NegotiatedProtocolIsMutual bool
@@ -180,6 +183,28 @@ type Config struct {
 	// CipherSuites is a list of supported cipher suites. If CipherSuites
 	// is nil, TLS uses a list of suites supported by the implementation.
 	CipherSuites []uint16
+
+	// PreferServerCipherSuites controls whether the server selects the
+	// client's most preferred ciphersuite, or the server's most preferred
+	// ciphersuite. If true then the server's preference, as expressed in
+	// the order of elements in CipherSuites, is used.
+	PreferServerCipherSuites bool
+
+	// SessionTicketsDisabled may be set to true to disable session ticket
+	// (resumption) support.
+	SessionTicketsDisabled bool
+
+	// SessionTicketKey is used by TLS servers to provide session
+	// resumption. See RFC 5077. If zero, it will be filled with
+	// random data before the first server handshake.
+	//
+	// If multiple servers are terminating connections for the same host
+	// they should all have the same SessionTicketKey. If the
+	// SessionTicketKey leaks, previously recorded and future TLS
+	// connections using that key are compromised.
+	SessionTicketKey [32]byte
+
+	serverInitOnce sync.Once
 }
 
 func (c *Config) rand() io.Reader {
diff --git a/src/pkg/crypto/tls/conn.go b/src/pkg/crypto/tls/conn.go
index 2a5115d..d8c2be0 100644
--- a/src/pkg/crypto/tls/conn.go
+++ b/src/pkg/crypto/tls/conn.go
@@ -31,6 +31,7 @@ type Conn struct {
 	haveVers          bool       // version has been negotiated
 	config            *Config    // configuration passed to constructor
 	handshakeComplete bool
+	didResume         bool // whether this connection was a session resumption
 	cipherSuite       uint16
 	ocspResponse      []byte // stapled OCSP response
 	peerCertificates  []*x509.Certificate
@@ -44,8 +45,7 @@ type Conn struct {
 	clientProtocolFallback bool
 
 	// first permanent error
-	errMutex sync.Mutex
-	err      error
+	connErr
 
 	// input/output
 	in, out  halfConn     // in.Mutex < out.Mutex
@@ -56,21 +56,25 @@ type Conn struct {
 	tmp [16]byte
 }
 
-func (c *Conn) setError(err error) error {
-	c.errMutex.Lock()
-	defer c.errMutex.Unlock()
+type connErr struct {
+	mu    sync.Mutex
+	value error
+}
+
+func (e *connErr) setError(err error) error {
+	e.mu.Lock()
+	defer e.mu.Unlock()
 
-	if c.err == nil {
-		c.err = err
+	if e.value == nil {
+		e.value = err
 	}
 	return err
 }
 
-func (c *Conn) error() error {
-	c.errMutex.Lock()
-	defer c.errMutex.Unlock()
-
-	return c.err
+func (e *connErr) error() error {
+	e.mu.Lock()
+	defer e.mu.Unlock()
+	return e.value
 }
 
 // Access to net.Conn methods.
@@ -487,6 +491,16 @@ Again:
 		return err
 	}
 	typ := recordType(b.data[0])
+
+	// No valid TLS record has a type of 0x80, however SSLv2 handshakes
+	// start with a uint16 length where the MSB is set and the first record
+	// is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
+	// an SSLv2 client.
+	if want == recordTypeHandshake && typ == 0x80 {
+		c.sendAlert(alertProtocolVersion)
+		return errors.New("tls: unsupported SSLv2 handshake received")
+	}
+
 	vers := uint16(b.data[1])<<8 | uint16(b.data[2])
 	n := int(b.data[3])<<8 | int(b.data[4])
 	if c.haveVers && vers != c.vers {
@@ -499,7 +513,7 @@ Again:
 		// First message, be extra suspicious:
 		// this might not be a TLS client.
 		// Bail out before reading a full 'body', if possible.
-		// The current max version is 3.1. 
+		// The current max version is 3.1.
 		// If the version is >= 16.0, it's probably not real.
 		// Similarly, a clientHello message encodes in
 		// well under a kilobyte.  If the length is >= 12 kB,
@@ -590,9 +604,11 @@ Again:
 // sendAlert sends a TLS alert message.
 // c.out.Mutex <= L.
 func (c *Conn) sendAlertLocked(err alert) error {
-	c.tmp[0] = alertLevelError
-	if err == alertNoRenegotiation {
+	switch err {
+	case alertNoRenegotiation, alertCloseNotify:
 		c.tmp[0] = alertLevelWarning
+	default:
+		c.tmp[0] = alertLevelError
 	}
 	c.tmp[1] = byte(err)
 	c.writeRecord(recordTypeAlert, c.tmp[0:2])
@@ -650,8 +666,7 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
 			c.tmp[0] = alertLevelError
 			c.tmp[1] = byte(err.(alert))
 			c.writeRecord(recordTypeAlert, c.tmp[0:2])
-			c.err = &net.OpError{Op: "local error", Err: err}
-			return n, c.err
+			return n, c.setError(&net.OpError{Op: "local error", Err: err})
 		}
 	}
 	return
@@ -662,8 +677,8 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
 // c.in.Mutex < L; c.out.Mutex < L.
 func (c *Conn) readHandshake() (interface{}, error) {
 	for c.hand.Len() < 4 {
-		if c.err != nil {
-			return nil, c.err
+		if err := c.error(); err != nil {
+			return nil, err
 		}
 		if err := c.readRecord(recordTypeHandshake); err != nil {
 			return nil, err
@@ -674,11 +689,11 @@ func (c *Conn) readHandshake() (interface{}, error) {
 	n := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
 	if n > maxHandshake {
 		c.sendAlert(alertInternalError)
-		return nil, c.err
+		return nil, c.error()
 	}
 	for c.hand.Len() < 4+n {
-		if c.err != nil {
-			return nil, c.err
+		if err := c.error(); err != nil {
+			return nil, err
 		}
 		if err := c.readRecord(recordTypeHandshake); err != nil {
 			return nil, err
@@ -728,12 +743,12 @@ func (c *Conn) readHandshake() (interface{}, error) {
 
 // Write writes data to the connection.
 func (c *Conn) Write(b []byte) (int, error) {
-	if c.err != nil {
-		return 0, c.err
+	if err := c.error(); err != nil {
+		return 0, err
 	}
 
-	if c.err = c.Handshake(); c.err != nil {
-		return 0, c.err
+	if err := c.Handshake(); err != nil {
+		return 0, c.setError(err)
 	}
 
 	c.out.Lock()
@@ -743,9 +758,28 @@ func (c *Conn) Write(b []byte) (int, error) {
 		return 0, alertInternalError
 	}
 
-	var n int
-	n, c.err = c.writeRecord(recordTypeApplicationData, b)
-	return n, c.err
+	// SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
+	// attack when using block mode ciphers due to predictable IVs.
+	// This can be prevented by splitting each Application Data
+	// record into two records, effectively randomizing the IV.
+	//
+	// http://www.openssl.org/~bodo/tls-cbc.txt
+	// https://bugzilla.mozilla.org/show_bug.cgi?id=665814
+	// http://www.imperialviolet.org/2012/01/15/beastfollowup.html
+
+	var m int
+	if len(b) > 1 && c.vers <= versionTLS10 {
+		if _, ok := c.out.cipher.(cipher.BlockMode); ok {
+			n, err := c.writeRecord(recordTypeApplicationData, b[:1])
+			if err != nil {
+				return n, c.setError(err)
+			}
+			m, b = 1, b[1:]
+		}
+	}
+
+	n, err := c.writeRecord(recordTypeApplicationData, b)
+	return n + m, c.setError(err)
 }
 
 // Read can be made to time out and return a net.Error with Timeout() == true
@@ -758,14 +792,14 @@ func (c *Conn) Read(b []byte) (n int, err error) {
 	c.in.Lock()
 	defer c.in.Unlock()
 
-	for c.input == nil && c.err == nil {
+	for c.input == nil && c.error() == nil {
 		if err := c.readRecord(recordTypeApplicationData); err != nil {
 			// Soft error, like EAGAIN
 			return 0, err
 		}
 	}
-	if c.err != nil {
-		return 0, c.err
+	if err := c.error(); err != nil {
+		return 0, err
 	}
 	n, err = c.input.Read(b)
 	if c.input.off >= len(c.input.data) {
@@ -819,6 +853,7 @@ func (c *Conn) ConnectionState() ConnectionState {
 	state.HandshakeComplete = c.handshakeComplete
 	if c.handshakeComplete {
 		state.NegotiatedProtocol = c.clientProtocol
+		state.DidResume = c.didResume
 		state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
 		state.CipherSuite = c.cipherSuite
 		state.PeerCertificates = c.peerCertificates
diff --git a/src/pkg/crypto/tls/generate_cert.go b/src/pkg/crypto/tls/generate_cert.go
index 84be5bf..215644d 100644
--- a/src/pkg/crypto/tls/generate_cert.go
+++ b/src/pkg/crypto/tls/generate_cert.go
@@ -16,36 +16,80 @@ import (
 	"crypto/x509/pkix"
 	"encoding/pem"
 	"flag"
+	"fmt"
 	"log"
 	"math/big"
+	"net"
 	"os"
+	"strings"
 	"time"
 )
 
-var hostName *string = flag.String("host", "127.0.0.1", "Hostname to generate a certificate for")
+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", 1024, "Size of RSA key to generate")
+)
 
 func main() {
 	flag.Parse()
 
-	priv, err := rsa.GenerateKey(rand.Reader, 1024)
+	if len(*host) == 0 {
+		log.Fatalf("Missing required --host parameter")
+	}
+
+	priv, err := rsa.GenerateKey(rand.Reader, *rsaBits)
 	if err != nil {
 		log.Fatalf("failed to generate private key: %s", err)
 		return
 	}
 
-	now := time.Now()
+	var notBefore time.Time
+	if len(*validFrom) == 0 {
+		notBefore = time.Now()
+	} else {
+		notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err)
+			os.Exit(1)
+		}
+	}
+
+	notAfter := notBefore.Add(*validFor)
+
+	// end of ASN.1 time
+	endOfTime := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC)
+	if notAfter.After(endOfTime) {
+		notAfter = endOfTime
+	}
 
 	template := x509.Certificate{
 		SerialNumber: new(big.Int).SetInt64(0),
 		Subject: pkix.Name{
-			CommonName:   *hostName,
 			Organization: []string{"Acme Co"},
 		},
-		NotBefore: now.Add(-5 * time.Minute).UTC(),
-		NotAfter:  now.AddDate(1, 0, 0).UTC(), // valid for 1 year.
+		NotBefore: notBefore,
+		NotAfter:  notAfter,
+
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+		BasicConstraintsValid: true,
+	}
+
+	hosts := strings.Split(*host, ",")
+	for _, h := range hosts {
+		if ip := net.ParseIP(h); ip != nil {
+			template.IPAddresses = append(template.IPAddresses, ip)
+		} else {
+			template.DNSNames = append(template.DNSNames, h)
+		}
+	}
 
-		SubjectKeyId: []byte{1, 2, 3, 4},
-		KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+	if *isCA {
+		template.IsCA = true
+		template.KeyUsage |= x509.KeyUsageCertSign
 	}
 
 	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
diff --git a/src/pkg/crypto/tls/handshake_client.go b/src/pkg/crypto/tls/handshake_client.go
index 2877f17..7db13bf 100644
--- a/src/pkg/crypto/tls/handshake_client.go
+++ b/src/pkg/crypto/tls/handshake_client.go
@@ -278,8 +278,9 @@ func (c *Conn) clientHandshake() error {
 		c.writeRecord(recordTypeHandshake, certVerify.marshal())
 	}
 
-	masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
-		keysFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
+	masterSecret := masterFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random)
+	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+		keysFromMasterSecret(c.vers, masterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
 
 	clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */)
 	clientHash := suite.mac(c.vers, clientMAC)
@@ -306,8 +307,8 @@ func (c *Conn) clientHandshake() error {
 	serverHash := suite.mac(c.vers, serverMAC)
 	c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
 	c.readRecord(recordTypeChangeCipherSpec)
-	if c.err != nil {
-		return c.err
+	if err := c.error(); err != nil {
+		return err
 	}
 
 	msg, err = c.readHandshake()
diff --git a/src/pkg/crypto/tls/handshake_client_test.go b/src/pkg/crypto/tls/handshake_client_test.go
index 8c56daa..9673947 100644
--- a/src/pkg/crypto/tls/handshake_client_test.go
+++ b/src/pkg/crypto/tls/handshake_client_test.go
@@ -9,6 +9,7 @@ import (
 	"flag"
 	"io"
 	"net"
+	"os"
 	"testing"
 )
 
@@ -39,7 +40,15 @@ func testClientScript(t *testing.T, name string, clientScript [][]byte, config *
 }
 
 func TestHandshakeClientRC4(t *testing.T) {
-	testClientScript(t, "RC4", rc4ClientScript, testConfig)
+	var config = *testConfig
+	config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
+	testClientScript(t, "RC4", rc4ClientScript, &config)
+}
+
+func TestHandshakeClientECDHEAES(t *testing.T) {
+	var config = *testConfig
+	config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}
+	testClientScript(t, "ECDHE-AES", ecdheAESClientScript, &config)
 }
 
 var connect = flag.Bool("connect", false, "connect to a TLS server on :10443")
@@ -49,25 +58,33 @@ func TestRunClient(t *testing.T) {
 		return
 	}
 
-	testConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}
-
-	conn, err := Dial("tcp", "127.0.0.1:10443", testConfig)
+	tcpConn, err := net.Dial("tcp", "127.0.0.1:10443")
 	if err != nil {
 		t.Fatal(err)
 	}
 
+	record := &recordingConn{
+		Conn: tcpConn,
+	}
+
+	config := GetTestConfig()
+	conn := Client(record, config)
+	if err := conn.Handshake(); err != nil {
+		t.Fatalf("error from TLS handshake: %s", err)
+	}
+
 	conn.Write([]byte("hello\n"))
 	conn.Close()
+
+	record.WriteTo(os.Stdout)
 }
 
 // Script of interaction with gnutls implementation.
 // The values for this test are obtained by building and running in client mode:
-//   % go test -run "TestRunClient" -connect
-// and then:
-//   % gnutls-serv -p 10443 --debug 100 --x509keyfile key.pem --x509certfile cert.pem -a > /tmp/log 2>&1
-//   % python parse-gnutls-cli-debug-log.py < /tmp/log
+//   % go test -test.run "TestRunClient" -connect
+// The recorded bytes are written to stdout.
 //
-// Where key.pem is:
+// The server private key is:
 // -----BEGIN RSA PRIVATE KEY-----
 // MIIBPAIBAAJBAJ+zw4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVD
 // TGiXav6ooKXfX3j/7tdkuD8Ey2//Kv7+ue0CAwEAAQJAN6W31vDEP2DjdqhzCDDu
@@ -78,17 +95,20 @@ func TestRunClient(t *testing.T) {
 // vnlEGo8K85u+KwIOimM48ZG8oTk7iFdkqLJR1utT3aU=
 // -----END RSA PRIVATE KEY-----
 //
-// and cert.pem is:
+// and certificate is:
 // -----BEGIN CERTIFICATE-----
-// MIIBoDCCAUoCAQAwDQYJKoZIhvcNAQEEBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV
-// BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD
-// VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw05NzA5MDkwMzQxMjZa
-// Fw05NzEwMDkwMzQxMjZaMF4xCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0
-// YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMT
-// DkVyaWMgdGhlIFlvdW5nMFEwCQYFKw4DAgwFAANEAAJBALVEqPODnpI4rShlY8S7
-// tB713JNvabvn6Gned7zylwLLiXQAo/PAT6mfdWPTyCX9RlId/Aroh1ou893BA32Q
-// sggwDQYJKoZIhvcNAQEEBQADQQCU5SSgapJSdRXJoX+CpCvFy+JVh9HpSjCpSNKO
-// 19raHv98hKAUJuP9HyM+SUsffO6mAIgitUaqW8/wDMePhEC3
+// MIICKzCCAdWgAwIBAgIJALE1E2URIMWSMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+// BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+// aWRnaXRzIFB0eSBMdGQwHhcNMTIwNDA2MTcxMDEzWhcNMTUwNDA2MTcxMDEzWjBF
+// MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+// ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+z
+// w4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/
+// 7tdkuD8Ey2//Kv7+ue0CAwEAAaOBpzCBpDAdBgNVHQ4EFgQUeKaXmmO1xaGlM7oi
+// fCNuWxt6zCswdQYDVR0jBG4wbIAUeKaXmmO1xaGlM7oifCNuWxt6zCuhSaRHMEUx
+// CzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRl
+// cm5ldCBXaWRnaXRzIFB0eSBMdGSCCQCxNRNlESDFkjAMBgNVHRMEBTADAQH/MA0G
+// CSqGSIb3DQEBBQUAA0EAhTZAc8G7GtrUWZ8tonAxRnTsg26oyDxRrzms7EC86CJG
+// HZnWRiok1IsFCEv7NRFukrt3uuQSu/TIXpyBqJdgTA==
 // -----END CERTIFICATE-----
 var rc4ClientScript = [][]byte{
 	{
@@ -210,3 +230,179 @@ var rc4ClientScript = [][]byte{
 		0x59, 0xac, 0xc6, 0xb5, 0x56, 0x55, 0x96,
 	},
 }
+
+var ecdheAESClientScript = [][]byte{
+	{
+		0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
+		0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x13,
+		0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+		0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+		0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
+	},
+	{
+		0x16, 0x03, 0x01, 0x00, 0x52, 0x02, 0x00, 0x00,
+		0x4e, 0x03, 0x01, 0x50, 0xad, 0x72, 0xb1, 0x14,
+		0x45, 0xce, 0x0a, 0x95, 0xf9, 0x63, 0xef, 0xa8,
+		0xe5, 0x07, 0x34, 0x04, 0xe9, 0x08, 0x0f, 0x38,
+		0xe4, 0x28, 0x27, 0x91, 0x07, 0x03, 0xe2, 0xfe,
+		0xe3, 0x25, 0xf7, 0x20, 0x08, 0x42, 0xa2, 0x01,
+		0x69, 0x53, 0xf0, 0xd9, 0x4c, 0xfa, 0x01, 0xa1,
+		0xce, 0x4b, 0xf8, 0x28, 0x21, 0xad, 0x06, 0xbe,
+		0xe0, 0x1b, 0x3b, 0xf7, 0xec, 0xd2, 0x52, 0xae,
+		0x2a, 0x57, 0xb7, 0xa8, 0xc0, 0x13, 0x00, 0x00,
+		0x06, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x16,
+		0x03, 0x01, 0x02, 0x39, 0x0b, 0x00, 0x02, 0x35,
+		0x00, 0x02, 0x32, 0x00, 0x02, 0x2f, 0x30, 0x82,
+		0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5, 0xa0, 0x03,
+		0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xb1, 0x35,
+		0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30, 0x0d,
+		0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+		0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+		0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+		0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+		0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+		0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+		0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+		0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+		0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+		0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+		0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+		0x31, 0x32, 0x30, 0x34, 0x30, 0x36, 0x31, 0x37,
+		0x31, 0x30, 0x31, 0x33, 0x5a, 0x17, 0x0d, 0x31,
+		0x35, 0x30, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31,
+		0x30, 0x31, 0x33, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+		0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+		0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+		0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+		0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+		0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+		0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+		0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+		0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+		0x4c, 0x74, 0x64, 0x30, 0x5c, 0x30, 0x0d, 0x06,
+		0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+		0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30,
+		0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3, 0xc3, 0x84,
+		0x27, 0x95, 0xff, 0x12, 0x31, 0x52, 0x0f, 0x15,
+		0xef, 0x46, 0x11, 0xc4, 0xad, 0x80, 0xe6, 0x36,
+		0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61, 0x8d, 0xe0,
+		0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe, 0x55, 0x66,
+		0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a, 0xfe, 0xa8,
+		0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff, 0xee, 0xd7,
+		0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f, 0xff, 0x2a,
+		0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03, 0x01, 0x00,
+		0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, 0xa4, 0x30,
+		0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
+		0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a, 0x63, 0xb5,
+		0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22, 0x7c, 0x23,
+		0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b, 0x30, 0x75,
+		0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x6e, 0x30,
+		0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97, 0x9a, 0x63,
+		0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22, 0x7c,
+		0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b, 0xa1,
+		0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, 0x0b, 0x30,
+		0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+		0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+		0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+		0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+		0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+		0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+		0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+		0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+		0x74, 0x64, 0x82, 0x09, 0x00, 0xb1, 0x35, 0x13,
+		0x65, 0x11, 0x20, 0xc5, 0x92, 0x30, 0x0c, 0x06,
+		0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03,
+		0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+		0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+		0x05, 0x00, 0x03, 0x41, 0x00, 0x85, 0x36, 0x40,
+		0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4, 0x59, 0x9f,
+		0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74, 0xec, 0x83,
+		0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf, 0x39, 0xac,
+		0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46, 0x1d, 0x99,
+		0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b, 0x05, 0x08,
+		0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92, 0xbb, 0x77,
+		0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8, 0x5e, 0x9c,
+		0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16, 0x03, 0x01,
+		0x00, 0x8b, 0x0c, 0x00, 0x00, 0x87, 0x03, 0x00,
+		0x17, 0x41, 0x04, 0x1c, 0x8f, 0x9c, 0x6d, 0xe7,
+		0xab, 0x3e, 0xf8, 0x0a, 0x5d, 0xe1, 0x86, 0xb4,
+		0xe2, 0x8e, 0xb2, 0x1c, 0x3b, 0xd9, 0xb6, 0x08,
+		0x80, 0x58, 0x21, 0xe9, 0x0e, 0xc6, 0x66, 0x67,
+		0x97, 0xcb, 0xb9, 0x92, 0x07, 0x00, 0xc4, 0xe5,
+		0xec, 0x5f, 0xb4, 0xe2, 0x20, 0xa9, 0xc9, 0x62,
+		0xd0, 0x98, 0xd5, 0xe3, 0x53, 0xff, 0xd0, 0x0a,
+		0x6e, 0x29, 0x69, 0x39, 0x2a, 0x4b, 0x5c, 0xd8,
+		0x6c, 0xf5, 0xfe, 0x00, 0x40, 0x35, 0xa7, 0x26,
+		0x2e, 0xc2, 0x48, 0x93, 0x32, 0xf7, 0x7d, 0x0f,
+		0x0d, 0x77, 0x56, 0x9a, 0x85, 0x0c, 0xa6, 0x74,
+		0x06, 0xb8, 0x3d, 0x90, 0x56, 0x12, 0x63, 0xff,
+		0x00, 0x5e, 0x0f, 0xf7, 0x24, 0xf7, 0xdb, 0x48,
+		0x71, 0xe9, 0x2e, 0x03, 0xd3, 0xfa, 0x3a, 0xae,
+		0xa0, 0xc1, 0x77, 0x3c, 0x4c, 0x59, 0xce, 0x33,
+		0x1a, 0xd2, 0x47, 0x83, 0xfa, 0xea, 0xd8, 0x1e,
+		0x06, 0xe7, 0x7d, 0xa0, 0x9b, 0x16, 0x03, 0x01,
+		0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+	},
+	{
+		0x16, 0x03, 0x01, 0x00, 0x46, 0x10, 0x00, 0x00,
+		0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d,
+		0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5,
+		0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd,
+		0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce,
+		0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e,
+		0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56,
+		0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49,
+		0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
+		0xdc, 0x5a, 0x89, 0x14, 0x03, 0x01, 0x00, 0x01,
+		0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xd9, 0xa7,
+		0x80, 0x56, 0x3f, 0xa3, 0x8f, 0x96, 0x72, 0x4e,
+		0x4e, 0x6e, 0x23, 0x41, 0x8f, 0xda, 0x91, 0xb2,
+		0x9e, 0x63, 0x23, 0x82, 0x64, 0xcd, 0x07, 0x24,
+		0xd3, 0x40, 0x20, 0x22, 0x4c, 0xe3, 0xff, 0x38,
+		0xbb, 0x43, 0x9d, 0x57, 0x11, 0xd5, 0x46, 0xa5,
+		0x05, 0x29, 0x92, 0x02, 0xce, 0xdf,
+	},
+	{
+		0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+		0x01, 0x00, 0x90, 0xe7, 0xba, 0x0e, 0xb1, 0xda,
+		0x92, 0xb5, 0x77, 0x56, 0x38, 0xa6, 0x22, 0xc1,
+		0x72, 0xeb, 0x8a, 0x68, 0x09, 0xb6, 0x74, 0xad,
+		0xb3, 0x4a, 0xf2, 0xdd, 0x09, 0x9b, 0xc9, 0x4f,
+		0x84, 0x73, 0x8b, 0xd6, 0x97, 0x50, 0x23, 0x1c,
+		0xa0, 0xc2, 0x0c, 0x25, 0x18, 0xdd, 0x5e, 0x15,
+		0x4d, 0xd9, 0xef, 0x4f, 0x6a, 0x43, 0x61, 0x9c,
+		0x95, 0xde, 0x3c, 0x66, 0xc4, 0xc1, 0x33, 0x56,
+		0xdd, 0x2f, 0x90, 0xaf, 0x68, 0x5c, 0x9c, 0xa4,
+		0x90, 0x6d, 0xbf, 0x51, 0x1d, 0x68, 0xcb, 0x81,
+		0x77, 0x52, 0xa0, 0x93, 0x2a, 0xf8, 0xc7, 0x61,
+		0x87, 0x76, 0xca, 0x93, 0x9e, 0xd6, 0xee, 0x6f,
+		0x3f, 0xeb, 0x7d, 0x06, 0xdd, 0x73, 0x4e, 0x27,
+		0x16, 0x63, 0x92, 0xe4, 0xb2, 0x3f, 0x91, 0x23,
+		0x21, 0x97, 0x90, 0xce, 0x53, 0xb8, 0xb0, 0x9d,
+		0xbd, 0xbd, 0x33, 0x84, 0xad, 0x6b, 0x2e, 0x7b,
+		0xf5, 0xeb, 0x1d, 0x64, 0x37, 0x2e, 0x29, 0x4e,
+		0xb0, 0x93, 0xdb, 0x92, 0xc7, 0xaa, 0x94, 0xa5,
+		0x3b, 0x64, 0xd0,
+	},
+	{
+		0x17, 0x03, 0x01, 0x00, 0x20, 0x11, 0xd8, 0x6b,
+		0x3c, 0xf6, 0xbe, 0xf4, 0x54, 0x87, 0xec, 0x75,
+		0x0c, 0x44, 0xdb, 0x92, 0xfc, 0xde, 0x7e, 0x0f,
+		0x9f, 0x87, 0x87, 0x9c, 0x03, 0xd5, 0x07, 0x84,
+		0xe0, 0x3a, 0xf8, 0xae, 0x14, 0x17, 0x03, 0x01,
+		0x00, 0x20, 0xba, 0x54, 0xef, 0x5b, 0xce, 0xfd,
+		0x47, 0x76, 0x6d, 0xa1, 0x8b, 0xfd, 0x48, 0xde,
+		0x6e, 0x26, 0xc1, 0x0c, 0x9d, 0x54, 0xbf, 0x98,
+		0xf6, 0x1c, 0x80, 0xb9, 0xca, 0x93, 0x81, 0x0a,
+		0x2e, 0x06, 0x15, 0x03, 0x01, 0x00, 0x20, 0x93,
+		0x3e, 0x38, 0x17, 0xc9, 0x0a, 0xc3, 0xea, 0xd3,
+		0x92, 0x75, 0xa6, 0x53, 0x37, 0x4d, 0x74, 0x94,
+		0xbe, 0x01, 0xdc, 0x5c, 0x5a, 0x0f, 0x09, 0xf6,
+		0x57, 0x33, 0xc3, 0xbc, 0x3f, 0x7a, 0x4d,
+	},
+}
diff --git a/src/pkg/crypto/tls/handshake_messages.go b/src/pkg/crypto/tls/handshake_messages.go
index 54c7a3e..cdd4917 100644
--- a/src/pkg/crypto/tls/handshake_messages.go
+++ b/src/pkg/crypto/tls/handshake_messages.go
@@ -18,6 +18,8 @@ type clientHelloMsg struct {
 	ocspStapling       bool
 	supportedCurves    []uint16
 	supportedPoints    []uint8
+	ticketSupported    bool
+	sessionTicket      []uint8
 }
 
 func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -36,7 +38,9 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
 		m.serverName == m1.serverName &&
 		m.ocspStapling == m1.ocspStapling &&
 		eqUint16s(m.supportedCurves, m1.supportedCurves) &&
-		bytes.Equal(m.supportedPoints, m1.supportedPoints)
+		bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
+		m.ticketSupported == m1.ticketSupported &&
+		bytes.Equal(m.sessionTicket, m1.sessionTicket)
 }
 
 func (m *clientHelloMsg) marshal() []byte {
@@ -66,6 +70,10 @@ func (m *clientHelloMsg) marshal() []byte {
 		extensionsLength += 1 + len(m.supportedPoints)
 		numExtensions++
 	}
+	if m.ticketSupported {
+		extensionsLength += len(m.sessionTicket)
+		numExtensions++
+	}
 	if numExtensions > 0 {
 		extensionsLength += 4 * numExtensions
 		length += 2 + extensionsLength
@@ -180,6 +188,17 @@ func (m *clientHelloMsg) marshal() []byte {
 			z = z[1:]
 		}
 	}
+	if m.ticketSupported {
+		// http://tools.ietf.org/html/rfc5077#section-3.2
+		z[0] = byte(extensionSessionTicket >> 8)
+		z[1] = byte(extensionSessionTicket)
+		l := len(m.sessionTicket)
+		z[2] = byte(l >> 8)
+		z[3] = byte(l)
+		z = z[4:]
+		copy(z, m.sessionTicket)
+		z = z[len(m.sessionTicket):]
+	}
 
 	m.raw = x
 
@@ -228,6 +247,8 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
 	m.nextProtoNeg = false
 	m.serverName = ""
 	m.ocspStapling = false
+	m.ticketSupported = false
+	m.sessionTicket = nil
 
 	if len(data) == 0 {
 		// ClientHello is optionally followed by extension data
@@ -311,6 +332,10 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
 			}
 			m.supportedPoints = make([]uint8, l)
 			copy(m.supportedPoints, data[1:])
+		case extensionSessionTicket:
+			// http://tools.ietf.org/html/rfc5077#section-3.2
+			m.ticketSupported = true
+			m.sessionTicket = data[:length]
 		}
 		data = data[length:]
 	}
@@ -328,6 +353,7 @@ type serverHelloMsg struct {
 	nextProtoNeg      bool
 	nextProtos        []string
 	ocspStapling      bool
+	ticketSupported   bool
 }
 
 func (m *serverHelloMsg) equal(i interface{}) bool {
@@ -344,7 +370,8 @@ func (m *serverHelloMsg) equal(i interface{}) bool {
 		m.compressionMethod == m1.compressionMethod &&
 		m.nextProtoNeg == m1.nextProtoNeg &&
 		eqStrings(m.nextProtos, m1.nextProtos) &&
-		m.ocspStapling == m1.ocspStapling
+		m.ocspStapling == m1.ocspStapling &&
+		m.ticketSupported == m1.ticketSupported
 }
 
 func (m *serverHelloMsg) marshal() []byte {
@@ -368,6 +395,9 @@ func (m *serverHelloMsg) marshal() []byte {
 	if m.ocspStapling {
 		numExtensions++
 	}
+	if m.ticketSupported {
+		numExtensions++
+	}
 	if numExtensions > 0 {
 		extensionsLength += 4 * numExtensions
 		length += 2 + extensionsLength
@@ -416,6 +446,11 @@ func (m *serverHelloMsg) marshal() []byte {
 		z[1] = byte(extensionStatusRequest)
 		z = z[4:]
 	}
+	if m.ticketSupported {
+		z[0] = byte(extensionSessionTicket >> 8)
+		z[1] = byte(extensionSessionTicket)
+		z = z[4:]
+	}
 
 	m.raw = x
 
@@ -445,6 +480,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
 	m.nextProtoNeg = false
 	m.nextProtos = nil
 	m.ocspStapling = false
+	m.ticketSupported = false
 
 	if len(data) == 0 {
 		// ServerHello is optionally followed by extension data
@@ -474,14 +510,14 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
 		switch extension {
 		case extensionNextProtoNeg:
 			m.nextProtoNeg = true
-			d := data
+			d := data[:length]
 			for len(d) > 0 {
 				l := int(d[0])
 				d = d[1:]
 				if l == 0 || l > len(d) {
 					return false
 				}
-				m.nextProtos = append(m.nextProtos, string(d[0:l]))
+				m.nextProtos = append(m.nextProtos, string(d[:l]))
 				d = d[l:]
 			}
 		case extensionStatusRequest:
@@ -489,6 +525,11 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
 				return false
 			}
 			m.ocspStapling = true
+		case extensionSessionTicket:
+			if length > 0 {
+				return false
+			}
+			m.ticketSupported = true
 		}
 		data = data[length:]
 	}
@@ -1030,6 +1071,65 @@ func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
 	return true
 }
 
+type newSessionTicketMsg struct {
+	raw    []byte
+	ticket []byte
+}
+
+func (m *newSessionTicketMsg) equal(i interface{}) bool {
+	m1, ok := i.(*newSessionTicketMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.ticket, m1.ticket)
+}
+
+func (m *newSessionTicketMsg) marshal() (x []byte) {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	// See http://tools.ietf.org/html/rfc5077#section-3.3
+	ticketLen := len(m.ticket)
+	length := 2 + 4 + ticketLen
+	x = make([]byte, 4+length)
+	x[0] = typeNewSessionTicket
+	x[1] = uint8(length >> 16)
+	x[2] = uint8(length >> 8)
+	x[3] = uint8(length)
+	x[8] = uint8(ticketLen >> 8)
+	x[9] = uint8(ticketLen)
+	copy(x[10:], m.ticket)
+
+	m.raw = x
+
+	return
+}
+
+func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
+	m.raw = data
+
+	if len(data) < 10 {
+		return false
+	}
+
+	length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+	if uint32(len(data))-4 != length {
+		return false
+	}
+
+	ticketLen := int(data[8])<<8 + int(data[9])
+	if len(data)-10 != ticketLen {
+		return false
+	}
+
+	m.ticket = data[10:]
+
+	return true
+}
+
 func eqUint16s(x, y []uint16) bool {
 	if len(x) != len(y) {
 		return false
diff --git a/src/pkg/crypto/tls/handshake_messages_test.go b/src/pkg/crypto/tls/handshake_messages_test.go
index e62a9d5..3434bad 100644
--- a/src/pkg/crypto/tls/handshake_messages_test.go
+++ b/src/pkg/crypto/tls/handshake_messages_test.go
@@ -22,6 +22,8 @@ var tests = []interface{}{
 	&certificateStatusMsg{},
 	&clientKeyExchangeMsg{},
 	&nextProtoMsg{},
+	&newSessionTicketMsg{},
+	&sessionState{},
 }
 
 type testMessage interface {
@@ -127,6 +129,12 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 	for i := range m.supportedCurves {
 		m.supportedCurves[i] = uint16(rand.Intn(30000))
 	}
+	if rand.Intn(10) > 5 {
+		m.ticketSupported = true
+		if rand.Intn(10) > 5 {
+			m.sessionTicket = randomBytes(rand.Intn(300), rand)
+		}
+	}
 
 	return reflect.ValueOf(m)
 }
@@ -149,6 +157,13 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 		}
 	}
 
+	if rand.Intn(10) > 5 {
+		m.ocspStapling = true
+	}
+	if rand.Intn(10) > 5 {
+		m.ticketSupported = true
+	}
+
 	return reflect.ValueOf(m)
 }
 
@@ -207,3 +222,22 @@ func (*nextProtoMsg) Generate(rand *rand.Rand, size int) reflect.Value {
 	m.proto = randomString(rand.Intn(255), rand)
 	return reflect.ValueOf(m)
 }
+
+func (*newSessionTicketMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &newSessionTicketMsg{}
+	m.ticket = randomBytes(rand.Intn(4), rand)
+	return reflect.ValueOf(m)
+}
+
+func (*sessionState) Generate(rand *rand.Rand, size int) reflect.Value {
+	s := &sessionState{}
+	s.vers = uint16(rand.Intn(10000))
+	s.cipherSuite = uint16(rand.Intn(10000))
+	s.masterSecret = randomBytes(rand.Intn(100), rand)
+	numCerts := rand.Intn(20)
+	s.certificates = make([][]byte, numCerts)
+	for i := 0; i < numCerts; i++ {
+		s.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
+	}
+	return reflect.ValueOf(s)
+}
diff --git a/src/pkg/crypto/tls/handshake_server.go b/src/pkg/crypto/tls/handshake_server.go
index 76adc54..7309910 100644
--- a/src/pkg/crypto/tls/handshake_server.go
+++ b/src/pkg/crypto/tls/handshake_server.go
@@ -13,31 +13,120 @@ import (
 	"io"
 )
 
+// serverHandshakeState contains details of a server handshake in progress.
+// It's discarded once the handshake has completed.
+type serverHandshakeState struct {
+	c               *Conn
+	clientHello     *clientHelloMsg
+	hello           *serverHelloMsg
+	suite           *cipherSuite
+	ellipticOk      bool
+	sessionState    *sessionState
+	finishedHash    finishedHash
+	masterSecret    []byte
+	certsFromClient [][]byte
+}
+
+// serverHandshake performs a TLS handshake as a server.
 func (c *Conn) serverHandshake() error {
 	config := c.config
-	msg, err := c.readHandshake()
+
+	// If this is the first server handshake, we generate a random key to
+	// encrypt the tickets with.
+	config.serverInitOnce.Do(func() {
+		if config.SessionTicketsDisabled {
+			return
+		}
+
+		// If the key has already been set then we have nothing to do.
+		for _, b := range config.SessionTicketKey {
+			if b != 0 {
+				return
+			}
+		}
+
+		if _, err := io.ReadFull(config.rand(), config.SessionTicketKey[:]); err != nil {
+			config.SessionTicketsDisabled = true
+		}
+	})
+
+	hs := serverHandshakeState{
+		c: c,
+	}
+	isResume, err := hs.readClientHello()
 	if err != nil {
 		return err
 	}
-	clientHello, ok := msg.(*clientHelloMsg)
+
+	// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
+	if isResume {
+		// The client has included a session ticket and so we do an abbreviated handshake.
+		if err := hs.doResumeHandshake(); err != nil {
+			return err
+		}
+		if err := hs.establishKeys(); err != nil {
+			return err
+		}
+		if err := hs.sendFinished(); err != nil {
+			return err
+		}
+		if err := hs.readFinished(); err != nil {
+			return err
+		}
+		c.didResume = true
+	} else {
+		// The client didn't include a session ticket, or it wasn't
+		// valid so we do a full handshake.
+		if err := hs.doFullHandshake(); err != nil {
+			return err
+		}
+		if err := hs.establishKeys(); err != nil {
+			return err
+		}
+		if err := hs.readFinished(); err != nil {
+			return err
+		}
+		if err := hs.sendSessionTicket(); err != nil {
+			return err
+		}
+		if err := hs.sendFinished(); err != nil {
+			return err
+		}
+	}
+	c.handshakeComplete = true
+
+	return nil
+}
+
+// readClientHello reads a ClientHello message from the client and decides
+// whether we will perform session resumption.
+func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
+	config := hs.c.config
+	c := hs.c
+
+	msg, err := c.readHandshake()
+	if err != nil {
+		return false, err
+	}
+	var ok bool
+	hs.clientHello, ok = msg.(*clientHelloMsg)
 	if !ok {
-		return c.sendAlert(alertUnexpectedMessage)
+		return false, c.sendAlert(alertUnexpectedMessage)
 	}
-	vers, ok := mutualVersion(clientHello.vers)
+	c.vers, ok = mutualVersion(hs.clientHello.vers)
 	if !ok {
-		return c.sendAlert(alertProtocolVersion)
+		return false, c.sendAlert(alertProtocolVersion)
 	}
-	c.vers = vers
 	c.haveVers = true
 
-	finishedHash := newFinishedHash(vers)
-	finishedHash.Write(clientHello.marshal())
+	hs.finishedHash = newFinishedHash(c.vers)
+	hs.finishedHash.Write(hs.clientHello.marshal())
 
-	hello := new(serverHelloMsg)
+	hs.hello = new(serverHelloMsg)
 
 	supportedCurve := false
 Curves:
-	for _, curve := range clientHello.supportedCurves {
+	for _, curve := range hs.clientHello.supportedCurves {
 		switch curve {
 		case curveP256, curveP384, curveP521:
 			supportedCurve = true
@@ -46,110 +135,182 @@ Curves:
 	}
 
 	supportedPointFormat := false
-	for _, pointFormat := range clientHello.supportedPoints {
+	for _, pointFormat := range hs.clientHello.supportedPoints {
 		if pointFormat == pointFormatUncompressed {
 			supportedPointFormat = true
 			break
 		}
 	}
-
-	ellipticOk := supportedCurve && supportedPointFormat
-
-	var suite *cipherSuite
-FindCipherSuite:
-	for _, id := range clientHello.cipherSuites {
-		for _, supported := range config.cipherSuites() {
-			if id == supported {
-				var candidate *cipherSuite
-
-				for _, s := range cipherSuites {
-					if s.id == id {
-						candidate = s
-						break
-					}
-				}
-				if candidate == nil {
-					continue
-				}
-				// Don't select a ciphersuite which we can't
-				// support for this client.
-				if candidate.elliptic && !ellipticOk {
-					continue
-				}
-				suite = candidate
-				break FindCipherSuite
-			}
-		}
-	}
+	hs.ellipticOk = supportedCurve && supportedPointFormat
 
 	foundCompression := false
 	// We only support null compression, so check that the client offered it.
-	for _, compression := range clientHello.compressionMethods {
+	for _, compression := range hs.clientHello.compressionMethods {
 		if compression == compressionNone {
 			foundCompression = true
 			break
 		}
 	}
 
-	if suite == nil || !foundCompression {
-		return c.sendAlert(alertHandshakeFailure)
+	if !foundCompression {
+		return false, c.sendAlert(alertHandshakeFailure)
 	}
 
-	hello.vers = vers
-	hello.cipherSuite = suite.id
+	hs.hello.vers = c.vers
 	t := uint32(config.time().Unix())
-	hello.random = make([]byte, 32)
-	hello.random[0] = byte(t >> 24)
-	hello.random[1] = byte(t >> 16)
-	hello.random[2] = byte(t >> 8)
-	hello.random[3] = byte(t)
-	_, err = io.ReadFull(config.rand(), hello.random[4:])
+	hs.hello.random = make([]byte, 32)
+	hs.hello.random[0] = byte(t >> 24)
+	hs.hello.random[1] = byte(t >> 16)
+	hs.hello.random[2] = byte(t >> 8)
+	hs.hello.random[3] = byte(t)
+	_, err = io.ReadFull(config.rand(), hs.hello.random[4:])
 	if err != nil {
-		return c.sendAlert(alertInternalError)
+		return false, c.sendAlert(alertInternalError)
+	}
+	hs.hello.compressionMethod = compressionNone
+	if len(hs.clientHello.serverName) > 0 {
+		c.serverName = hs.clientHello.serverName
+	}
+	if hs.clientHello.nextProtoNeg {
+		hs.hello.nextProtoNeg = true
+		hs.hello.nextProtos = config.NextProtos
+	}
+
+	if hs.checkForResumption() {
+		return true, nil
+	}
+
+	var preferenceList, supportedList []uint16
+	if c.config.PreferServerCipherSuites {
+		preferenceList = c.config.cipherSuites()
+		supportedList = hs.clientHello.cipherSuites
+	} else {
+		preferenceList = hs.clientHello.cipherSuites
+		supportedList = c.config.cipherSuites()
+	}
+
+	for _, id := range preferenceList {
+		if hs.suite = c.tryCipherSuite(id, supportedList, hs.ellipticOk); hs.suite != nil {
+			break
+		}
+	}
+
+	if hs.suite == nil {
+		return false, c.sendAlert(alertHandshakeFailure)
+	}
+
+	return false, nil
+}
+
+// checkForResumption returns true if we should perform resumption on this connection.
+func (hs *serverHandshakeState) checkForResumption() bool {
+	c := hs.c
+
+	var ok bool
+	if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
+		return false
 	}
-	hello.compressionMethod = compressionNone
-	if clientHello.nextProtoNeg {
-		hello.nextProtoNeg = true
-		hello.nextProtos = config.NextProtos
+
+	if hs.sessionState.vers > hs.clientHello.vers {
+		return false
+	}
+	if vers, ok := mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
+		return false
+	}
+
+	cipherSuiteOk := false
+	// Check that the client is still offering the ciphersuite in the session.
+	for _, id := range hs.clientHello.cipherSuites {
+		if id == hs.sessionState.cipherSuite {
+			cipherSuiteOk = true
+			break
+		}
+	}
+	if !cipherSuiteOk {
+		return false
+	}
+
+	// Check that we also support the ciphersuite from the session.
+	hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.ellipticOk)
+	if hs.suite == nil {
+		return false
+	}
+
+	sessionHasClientCerts := len(hs.sessionState.certificates) != 0
+	needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
+	if needClientCerts && !sessionHasClientCerts {
+		return false
+	}
+	if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
+		return false
 	}
 
+	return true
+}
+
+func (hs *serverHandshakeState) doResumeHandshake() error {
+	c := hs.c
+
+	hs.hello.cipherSuite = hs.suite.id
+	// We echo the client's session ID in the ServerHello to let it know
+	// that we're doing a resumption.
+	hs.hello.sessionId = hs.clientHello.sessionId
+	hs.finishedHash.Write(hs.hello.marshal())
+	c.writeRecord(recordTypeHandshake, hs.hello.marshal())
+
+	if len(hs.sessionState.certificates) > 0 {
+		if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
+			return err
+		}
+	}
+
+	hs.masterSecret = hs.sessionState.masterSecret
+
+	return nil
+}
+
+func (hs *serverHandshakeState) doFullHandshake() error {
+	config := hs.c.config
+	c := hs.c
+
 	if len(config.Certificates) == 0 {
 		return c.sendAlert(alertInternalError)
 	}
 	cert := &config.Certificates[0]
-	if len(clientHello.serverName) > 0 {
-		c.serverName = clientHello.serverName
-		cert = config.getCertificateForName(clientHello.serverName)
+	if len(hs.clientHello.serverName) > 0 {
+		cert = config.getCertificateForName(hs.clientHello.serverName)
 	}
 
-	if clientHello.ocspStapling && len(cert.OCSPStaple) > 0 {
-		hello.ocspStapling = true
+	if hs.clientHello.ocspStapling && len(cert.OCSPStaple) > 0 {
+		hs.hello.ocspStapling = true
 	}
 
-	finishedHash.Write(hello.marshal())
-	c.writeRecord(recordTypeHandshake, hello.marshal())
+	hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled
+	hs.hello.cipherSuite = hs.suite.id
+	hs.finishedHash.Write(hs.hello.marshal())
+	c.writeRecord(recordTypeHandshake, hs.hello.marshal())
 
 	certMsg := new(certificateMsg)
 	certMsg.certificates = cert.Certificate
-	finishedHash.Write(certMsg.marshal())
+	hs.finishedHash.Write(certMsg.marshal())
 	c.writeRecord(recordTypeHandshake, certMsg.marshal())
 
-	if hello.ocspStapling {
+	if hs.hello.ocspStapling {
 		certStatus := new(certificateStatusMsg)
 		certStatus.statusType = statusTypeOCSP
 		certStatus.response = cert.OCSPStaple
-		finishedHash.Write(certStatus.marshal())
+		hs.finishedHash.Write(certStatus.marshal())
 		c.writeRecord(recordTypeHandshake, certStatus.marshal())
 	}
 
-	keyAgreement := suite.ka()
-	skx, err := keyAgreement.generateServerKeyExchange(config, cert, clientHello, hello)
+	keyAgreement := hs.suite.ka()
+	skx, err := keyAgreement.generateServerKeyExchange(config, cert, hs.clientHello, hs.hello)
 	if err != nil {
 		c.sendAlert(alertHandshakeFailure)
 		return err
 	}
 	if skx != nil {
-		finishedHash.Write(skx.marshal())
+		hs.finishedHash.Write(skx.marshal())
 		c.writeRecord(recordTypeHandshake, skx.marshal())
 	}
 
@@ -166,28 +327,29 @@ FindCipherSuite:
 		if config.ClientCAs != nil {
 			certReq.certificateAuthorities = config.ClientCAs.Subjects()
 		}
-		finishedHash.Write(certReq.marshal())
+		hs.finishedHash.Write(certReq.marshal())
 		c.writeRecord(recordTypeHandshake, certReq.marshal())
 	}
 
 	helloDone := new(serverHelloDoneMsg)
-	finishedHash.Write(helloDone.marshal())
+	hs.finishedHash.Write(helloDone.marshal())
 	c.writeRecord(recordTypeHandshake, helloDone.marshal())
 
 	var pub *rsa.PublicKey // public key for client auth, if any
 
-	msg, err = c.readHandshake()
+	msg, err := c.readHandshake()
 	if err != nil {
 		return err
 	}
 
+	var ok bool
 	// If we requested a client certificate, then the client must send a
 	// certificate message, even if it's empty.
 	if config.ClientAuth >= RequestClientCert {
 		if certMsg, ok = msg.(*certificateMsg); !ok {
 			return c.sendAlert(alertHandshakeFailure)
 		}
-		finishedHash.Write(certMsg.marshal())
+		hs.finishedHash.Write(certMsg.marshal())
 
 		if len(certMsg.certificates) == 0 {
 			// The client didn't actually send a certificate
@@ -198,54 +360,9 @@ FindCipherSuite:
 			}
 		}
 
-		certs := make([]*x509.Certificate, len(certMsg.certificates))
-		for i, asn1Data := range certMsg.certificates {
-			if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
-				c.sendAlert(alertBadCertificate)
-				return errors.New("tls: failed to parse client certificate: " + err.Error())
-			}
-		}
-
-		if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
-			opts := x509.VerifyOptions{
-				Roots:         c.config.ClientCAs,
-				CurrentTime:   c.config.time(),
-				Intermediates: x509.NewCertPool(),
-			}
-
-			for i, cert := range certs {
-				if i == 0 {
-					continue
-				}
-				opts.Intermediates.AddCert(cert)
-			}
-
-			chains, err := certs[0].Verify(opts)
-			if err != nil {
-				c.sendAlert(alertBadCertificate)
-				return errors.New("tls: failed to verify client's certificate: " + err.Error())
-			}
-
-			ok := false
-			for _, ku := range certs[0].ExtKeyUsage {
-				if ku == x509.ExtKeyUsageClientAuth {
-					ok = true
-					break
-				}
-			}
-			if !ok {
-				c.sendAlert(alertHandshakeFailure)
-				return errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
-			}
-
-			c.verifiedChains = chains
-		}
-
-		if len(certs) > 0 {
-			if pub, ok = certs[0].PublicKey.(*rsa.PublicKey); !ok {
-				return c.sendAlert(alertUnsupportedCertificate)
-			}
-			c.peerCertificates = certs
+		pub, err = hs.processCertsFromClient(certMsg.certificates)
+		if err != nil {
+			return err
 		}
 
 		msg, err = c.readHandshake()
@@ -259,7 +376,7 @@ FindCipherSuite:
 	if !ok {
 		return c.sendAlert(alertUnexpectedMessage)
 	}
-	finishedHash.Write(ckx.marshal())
+	hs.finishedHash.Write(ckx.marshal())
 
 	// If we received a client cert in response to our certificate request message,
 	// the client will send us a certificateVerifyMsg immediately after the
@@ -278,15 +395,15 @@ FindCipherSuite:
 		}
 
 		digest := make([]byte, 0, 36)
-		digest = finishedHash.serverMD5.Sum(digest)
-		digest = finishedHash.serverSHA1.Sum(digest)
+		digest = hs.finishedHash.serverMD5.Sum(digest)
+		digest = hs.finishedHash.serverSHA1.Sum(digest)
 		err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
 		if err != nil {
 			c.sendAlert(alertBadCertificate)
 			return errors.New("could not validate signature of connection nonces: " + err.Error())
 		}
 
-		finishedHash.Write(certVerify.marshal())
+		hs.finishedHash.Write(certVerify.marshal())
 	}
 
 	preMasterSecret, err := keyAgreement.processClientKeyExchange(config, cert, ckx, c.vers)
@@ -294,20 +411,38 @@ FindCipherSuite:
 		c.sendAlert(alertHandshakeFailure)
 		return err
 	}
+	hs.masterSecret = masterFromPreMasterSecret(c.vers, preMasterSecret, hs.clientHello.random, hs.hello.random)
+
+	return nil
+}
+
+func (hs *serverHandshakeState) establishKeys() error {
+	c := hs.c
 
-	masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
-		keysFromPreMasterSecret(c.vers, preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
+	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+		keysFromMasterSecret(c.vers, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
 
-	clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */)
-	clientHash := suite.mac(c.vers, clientMAC)
+	clientCipher := hs.suite.cipher(clientKey, clientIV, true /* for reading */)
+	clientHash := hs.suite.mac(c.vers, clientMAC)
 	c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
+
+	serverCipher := hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
+	serverHash := hs.suite.mac(c.vers, serverMAC)
+	c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
+
+	return nil
+}
+
+func (hs *serverHandshakeState) readFinished() error {
+	c := hs.c
+
 	c.readRecord(recordTypeChangeCipherSpec)
 	if err := c.error(); err != nil {
 		return err
 	}
 
-	if hello.nextProtoNeg {
-		msg, err = c.readHandshake()
+	if hs.hello.nextProtoNeg {
+		msg, err := c.readHandshake()
 		if err != nil {
 			return err
 		}
@@ -315,11 +450,11 @@ FindCipherSuite:
 		if !ok {
 			return c.sendAlert(alertUnexpectedMessage)
 		}
-		finishedHash.Write(nextProto.marshal())
+		hs.finishedHash.Write(nextProto.marshal())
 		c.clientProtocol = nextProto.proto
 	}
 
-	msg, err = c.readHandshake()
+	msg, err := c.readHandshake()
 	if err != nil {
 		return err
 	}
@@ -328,25 +463,142 @@ FindCipherSuite:
 		return c.sendAlert(alertUnexpectedMessage)
 	}
 
-	verify := finishedHash.clientSum(masterSecret)
+	verify := hs.finishedHash.clientSum(hs.masterSecret)
 	if len(verify) != len(clientFinished.verifyData) ||
 		subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
 		return c.sendAlert(alertHandshakeFailure)
 	}
 
-	finishedHash.Write(clientFinished.marshal())
+	hs.finishedHash.Write(clientFinished.marshal())
+	return nil
+}
+
+func (hs *serverHandshakeState) sendSessionTicket() error {
+	if !hs.hello.ticketSupported {
+		return nil
+	}
+
+	c := hs.c
+	m := new(newSessionTicketMsg)
+
+	var err error
+	state := sessionState{
+		vers:         c.vers,
+		cipherSuite:  hs.suite.id,
+		masterSecret: hs.masterSecret,
+		certificates: hs.certsFromClient,
+	}
+	m.ticket, err = c.encryptTicket(&state)
+	if err != nil {
+		return err
+	}
+
+	hs.finishedHash.Write(m.marshal())
+	c.writeRecord(recordTypeHandshake, m.marshal())
+
+	return nil
+}
+
+func (hs *serverHandshakeState) sendFinished() error {
+	c := hs.c
 
-	serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */)
-	serverHash := suite.mac(c.vers, serverMAC)
-	c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
 	c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
 
 	finished := new(finishedMsg)
-	finished.verifyData = finishedHash.serverSum(masterSecret)
+	finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
+	hs.finishedHash.Write(finished.marshal())
 	c.writeRecord(recordTypeHandshake, finished.marshal())
 
-	c.handshakeComplete = true
-	c.cipherSuite = suite.id
+	c.cipherSuite = hs.suite.id
+
+	return nil
+}
+
+// processCertsFromClient takes a chain of client certificates either from a
+// Certificates message or from a sessionState and verifies them. It returns
+// the public key of the leaf certificate.
+func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (*rsa.PublicKey, error) {
+	c := hs.c
+
+	hs.certsFromClient = certificates
+	certs := make([]*x509.Certificate, len(certificates))
+	var err error
+	for i, asn1Data := range certificates {
+		if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
+			c.sendAlert(alertBadCertificate)
+			return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
+		}
+	}
+
+	if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
+		opts := x509.VerifyOptions{
+			Roots:         c.config.ClientCAs,
+			CurrentTime:   c.config.time(),
+			Intermediates: x509.NewCertPool(),
+			KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
+		}
+
+		for _, cert := range certs[1:] {
+			opts.Intermediates.AddCert(cert)
+		}
+
+		chains, err := certs[0].Verify(opts)
+		if err != nil {
+			c.sendAlert(alertBadCertificate)
+			return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
+		}
+
+		ok := false
+		for _, ku := range certs[0].ExtKeyUsage {
+			if ku == x509.ExtKeyUsageClientAuth {
+				ok = true
+				break
+			}
+		}
+		if !ok {
+			c.sendAlert(alertHandshakeFailure)
+			return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
+		}
+
+		c.verifiedChains = chains
+	}
+
+	if len(certs) > 0 {
+		pub, ok := certs[0].PublicKey.(*rsa.PublicKey)
+		if !ok {
+			return nil, c.sendAlert(alertUnsupportedCertificate)
+		}
+		c.peerCertificates = certs
+		return pub, nil
+	}
+
+	return nil, nil
+}
+
+// tryCipherSuite returns a cipherSuite with the given id if that cipher suite
+// is acceptable to use.
+func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, ellipticOk bool) *cipherSuite {
+	for _, supported := range supportedCipherSuites {
+		if id == supported {
+			var candidate *cipherSuite
+
+			for _, s := range cipherSuites {
+				if s.id == id {
+					candidate = s
+					break
+				}
+			}
+			if candidate == nil {
+				continue
+			}
+			// Don't select a ciphersuite which we can't
+			// support for this client.
+			if candidate.elliptic && !ellipticOk {
+				continue
+			}
+			return candidate
+		}
+	}
 
 	return nil
 }
diff --git a/src/pkg/crypto/tls/handshake_server_test.go b/src/pkg/crypto/tls/handshake_server_test.go
index 7c12671..bf8cbe3 100644
--- a/src/pkg/crypto/tls/handshake_server_test.go
+++ b/src/pkg/crypto/tls/handshake_server_test.go
@@ -11,12 +11,15 @@ import (
 	"encoding/hex"
 	"encoding/pem"
 	"flag"
+	"fmt"
 	"io"
 	"log"
 	"math/big"
 	"net"
+	"os"
 	"strconv"
 	"strings"
+	"sync"
 	"testing"
 	"time"
 )
@@ -80,13 +83,20 @@ func TestRejectBadProtocolVersion(t *testing.T) {
 }
 
 func TestNoSuiteOverlap(t *testing.T) {
-	clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{0xff00}, []uint8{0}, false, "", false, nil, nil}
+	clientHello := &clientHelloMsg{
+		vers:               0x0301,
+		cipherSuites:       []uint16{0xff00},
+		compressionMethods: []uint8{0},
+	}
 	testClientHelloFailure(t, clientHello, alertHandshakeFailure)
-
 }
 
 func TestNoCompressionOverlap(t *testing.T) {
-	clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{TLS_RSA_WITH_RC4_128_SHA}, []uint8{0xff}, false, "", false, nil, nil}
+	clientHello := &clientHelloMsg{
+		vers:               0x0301,
+		cipherSuites:       []uint16{TLS_RSA_WITH_RC4_128_SHA},
+		compressionMethods: []uint8{0xff},
+	}
 	testClientHelloFailure(t, clientHello, alertHandshakeFailure)
 }
 
@@ -115,6 +125,50 @@ func TestClose(t *testing.T) {
 	}
 }
 
+func testHandshake(clientConfig, serverConfig *Config) (state ConnectionState, err error) {
+	c, s := net.Pipe()
+	go func() {
+		cli := Client(c, clientConfig)
+		cli.Handshake()
+		c.Close()
+	}()
+	server := Server(s, serverConfig)
+	err = server.Handshake()
+	if err == nil {
+		state = server.ConnectionState()
+	}
+	s.Close()
+	return
+}
+
+func TestCipherSuitePreference(t *testing.T) {
+	serverConfig := &Config{
+		CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+		Certificates: testConfig.Certificates,
+	}
+	clientConfig := &Config{
+		CipherSuites:       []uint16{TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_RC4_128_SHA},
+		InsecureSkipVerify: true,
+	}
+	state, err := testHandshake(clientConfig, serverConfig)
+	if err != nil {
+		t.Fatalf("handshake failed: %s", err)
+	}
+	if state.CipherSuite != TLS_RSA_WITH_AES_128_CBC_SHA {
+		// By default the server should use the client's preference.
+		t.Fatalf("Client's preference was not used, got %x", state.CipherSuite)
+	}
+
+	serverConfig.PreferServerCipherSuites = true
+	state, err = testHandshake(clientConfig, serverConfig)
+	if err != nil {
+		t.Fatalf("handshake failed: %s", err)
+	}
+	if state.CipherSuite != TLS_RSA_WITH_RC4_128_SHA {
+		t.Fatalf("Server's preference was not used, got %x", state.CipherSuite)
+	}
+}
+
 func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config, peers []*x509.Certificate) {
 	c, s := net.Pipe()
 	srv := Server(s, config)
@@ -186,6 +240,11 @@ func TestHandshakeServerSNI(t *testing.T) {
 	testServerScript(t, "SNI", selectCertificateBySNIScript, testConfig, nil)
 }
 
+func TestResumption(t *testing.T) {
+	testServerScript(t, "IssueTicket", issueSessionTicketTest, testConfig, nil)
+	testServerScript(t, "Resume", serverResumeTest, testConfig, nil)
+}
+
 type clientauthTest struct {
 	name       string
 	clientauth ClientAuthType
@@ -203,55 +262,133 @@ func TestClientAuth(t *testing.T) {
 	}
 }
 
+// recordingConn is a net.Conn that records the traffic that passes through it.
+// WriteTo can be used to produce Go code that contains the recorded traffic.
+type recordingConn struct {
+	net.Conn
+	lock             sync.Mutex
+	flows            [][]byte
+	currentlyReading bool
+}
+
+func (r *recordingConn) Read(b []byte) (n int, err error) {
+	if n, err = r.Conn.Read(b); n == 0 {
+		return
+	}
+	b = b[:n]
+
+	r.lock.Lock()
+	defer r.lock.Unlock()
+
+	if l := len(r.flows); l == 0 || !r.currentlyReading {
+		buf := make([]byte, len(b))
+		copy(buf, b)
+		r.flows = append(r.flows, buf)
+	} else {
+		r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+	}
+	r.currentlyReading = true
+	return
+}
+
+func (r *recordingConn) Write(b []byte) (n int, err error) {
+	if n, err = r.Conn.Write(b); n == 0 {
+		return
+	}
+	b = b[:n]
+
+	r.lock.Lock()
+	defer r.lock.Unlock()
+
+	if l := len(r.flows); l == 0 || r.currentlyReading {
+		buf := make([]byte, len(b))
+		copy(buf, b)
+		r.flows = append(r.flows, buf)
+	} else {
+		r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+	}
+	r.currentlyReading = false
+	return
+}
+
+// WriteTo writes Go source code to w that contains the recorded traffic.
+func (r *recordingConn) WriteTo(w io.Writer) {
+	fmt.Fprintf(w, "var changeMe = [][]byte {\n")
+	for _, buf := range r.flows {
+		fmt.Fprintf(w, "\t{")
+		for i, b := range buf {
+			if i%8 == 0 {
+				fmt.Fprintf(w, "\n\t\t")
+			}
+			fmt.Fprintf(w, "0x%02x, ", b)
+		}
+		fmt.Fprintf(w, "\n\t},\n")
+	}
+	fmt.Fprintf(w, "}\n")
+}
+
 var serve = flag.Bool("serve", false, "run a TLS server on :10443")
 var testCipherSuites = flag.String("ciphersuites",
 	"0x"+strconv.FormatInt(int64(TLS_RSA_WITH_RC4_128_SHA), 16),
 	"cipher suites to accept in serving mode")
 var testClientAuth = flag.Int("clientauth", 0, "value for tls.Config.ClientAuth")
 
-func TestRunServer(t *testing.T) {
-	if !*serve {
-		return
-	}
-
+func GetTestConfig() *Config {
+	var config = *testConfig
 	suites := strings.Split(*testCipherSuites, ",")
-	testConfig.CipherSuites = make([]uint16, len(suites))
+	config.CipherSuites = make([]uint16, len(suites))
 	for i := range suites {
 		suite, err := strconv.ParseUint(suites[i], 0, 64)
 		if err != nil {
 			panic(err)
 		}
-		testConfig.CipherSuites[i] = uint16(suite)
+		config.CipherSuites[i] = uint16(suite)
 	}
 
-	testConfig.ClientAuth = ClientAuthType(*testClientAuth)
+	config.ClientAuth = ClientAuthType(*testClientAuth)
+	return &config
+}
+
+func TestRunServer(t *testing.T) {
+	if !*serve {
+		return
+	}
+
+	config := GetTestConfig()
 
-	l, err := Listen("tcp", ":10443", testConfig)
+	const addr = ":10443"
+	l, err := net.Listen("tcp", addr)
 	if err != nil {
 		t.Fatal(err)
 	}
+	log.Printf("Now listening for connections on %s", addr)
 
 	for {
-		c, err := l.Accept()
+		tcpConn, err := l.Accept()
 		if err != nil {
+			log.Printf("error accepting connection: %s", err)
+			break
+		}
+
+		record := &recordingConn{
+			Conn: tcpConn,
+		}
+
+		conn := Server(record, config)
+		if err := conn.Handshake(); err != nil {
 			log.Printf("error from TLS handshake: %s", err)
 			break
 		}
 
-		_, err = c.Write([]byte("hello, world\n"))
+		_, err = conn.Write([]byte("hello, world\n"))
 		if err != nil {
-			log.Printf("error from TLS: %s", err)
+			log.Printf("error from Write: %s", err)
 			continue
 		}
 
-		st := c.(*Conn).ConnectionState()
-		if len(st.PeerCertificates) > 0 {
-			log.Print("Handling request from client ", st.PeerCertificates[0].Subject.CommonName)
-		} else {
-			log.Print("Handling request from anon client")
-		}
+		conn.Close()
 
-		c.Close()
+		record.WriteTo(os.Stdout)
 	}
 }
 
@@ -296,30 +433,23 @@ func loadPEMCert(in string) *x509.Certificate {
 
 // Script of interaction with gnutls implementation.
 // The values for this test are obtained by building and running in server mode:
-//   % go test -run "TestRunServer" -serve
-// and then:
-//   % gnutls-cli --insecure --debug 100 -p 10443 localhost > /tmp/log 2>&1
-//   % python parse-gnutls-cli-debug-log.py < /tmp/log
+//   % go test -test.run "TestRunServer" -serve
+// The recorded bytes are written to stdout.
 var rc4ServerScript = [][]byte{
 	{
-		0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
-		0x76, 0x03, 0x02, 0x4e, 0xdd, 0xe6, 0xa5, 0xf7,
-		0x00, 0x36, 0xf7, 0x83, 0xec, 0x93, 0x7c, 0xd2,
-		0x4d, 0xe7, 0x7b, 0xf5, 0x4c, 0xf7, 0xe3, 0x86,
-		0xe8, 0xec, 0x3b, 0xbd, 0x2c, 0x9a, 0x3f, 0x57,
-		0xf0, 0xa4, 0xd4, 0x00, 0x00, 0x34, 0x00, 0x33,
-		0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
-		0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
-		0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
-		0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
-		0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
-		0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
-		0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
-		0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
-		0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
-		0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+		0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
+		0x50, 0x03, 0x01, 0x50, 0x77, 0x3d, 0xbd, 0x32,
+		0x13, 0xd7, 0xea, 0x33, 0x65, 0x02, 0xb8, 0x70,
+		0xb7, 0x84, 0xc4, 0x05, 0x1f, 0xa4, 0x24, 0xc4,
+		0x91, 0x69, 0x04, 0x32, 0x96, 0xfe, 0x5b, 0x49,
+		0x71, 0x60, 0x9a, 0x00, 0x00, 0x28, 0x00, 0x39,
+		0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+		0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+		0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+		0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+		0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+		0x00,
 	},
-
 	{
 		0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
 		0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -418,86 +548,145 @@ var rc4ServerScript = [][]byte{
 		0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
 		0x00, 0x00, 0x00,
 	},
-
 	{
 		0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
-		0x82, 0x00, 0x80, 0x39, 0xe2, 0x0f, 0x49, 0xa0,
-		0xe6, 0xe4, 0x3b, 0x0c, 0x5f, 0xce, 0x39, 0x97,
-		0x6c, 0xb6, 0x41, 0xd9, 0xe1, 0x52, 0x8f, 0x43,
-		0xb3, 0xc6, 0x4f, 0x9a, 0xe2, 0x1e, 0xb9, 0x3b,
-		0xe3, 0x72, 0x17, 0x68, 0xb2, 0x0d, 0x7b, 0x71,
-		0x33, 0x96, 0x5c, 0xf9, 0xfe, 0x18, 0x8f, 0x2f,
-		0x2b, 0x82, 0xec, 0x03, 0xf2, 0x16, 0xa8, 0xf8,
-		0x39, 0xf9, 0xbb, 0x5a, 0xd3, 0x0c, 0xc1, 0x2a,
-		0x52, 0xa1, 0x90, 0x20, 0x6b, 0x24, 0xc9, 0x55,
-		0xee, 0x05, 0xd8, 0xb3, 0x43, 0x58, 0xf6, 0x7f,
-		0x68, 0x2d, 0xb3, 0xd1, 0x1b, 0x30, 0xaa, 0xdf,
-		0xfc, 0x85, 0xf1, 0xab, 0x14, 0x51, 0x91, 0x78,
-		0x29, 0x35, 0x65, 0xe0, 0x9c, 0xf6, 0xb7, 0x35,
-		0x33, 0xdb, 0x28, 0x93, 0x4d, 0x86, 0xbc, 0xfe,
-		0xaa, 0xd1, 0xc0, 0x2e, 0x4d, 0xec, 0xa2, 0x98,
-		0xca, 0x08, 0xb2, 0x91, 0x14, 0xde, 0x97, 0x3a,
-		0xc4, 0x6b, 0x49, 0x14, 0x03, 0x01, 0x00, 0x01,
-		0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0x7a, 0xcb,
-		0x3b, 0x0e, 0xbb, 0x7a, 0x56, 0x39, 0xaf, 0x83,
-		0xae, 0xfd, 0x25, 0xfd, 0x64, 0xb4, 0x0c, 0x0c,
-		0x17, 0x46, 0x54, 0x2c, 0x6a, 0x07, 0x83, 0xc6,
-		0x46, 0x08, 0x0b, 0xcd, 0x15, 0x53, 0xef, 0x40,
-		0x4e, 0x56,
+		0x82, 0x00, 0x80, 0x2d, 0x09, 0x7c, 0x7f, 0xfc,
+		0x84, 0xce, 0xb3, 0x30, 0x9b, 0xf9, 0xb7, 0xc8,
+		0xc3, 0xff, 0xee, 0x6f, 0x20, 0x8a, 0xf4, 0xfb,
+		0x86, 0x55, 0x1f, 0x6a, 0xb4, 0x81, 0x50, 0x3a,
+		0x46, 0x1b, 0xd3, 0xca, 0x4b, 0x11, 0xff, 0xef,
+		0x02, 0xbc, 0x18, 0xb8, 0x4a, 0x7d, 0x43, 0x23,
+		0x96, 0x92, 0x27, 0x7c, 0xca, 0xcf, 0xe6, 0x91,
+		0xe8, 0x14, 0x97, 0x68, 0xb4, 0xe5, 0xc0, 0xc9,
+		0x23, 0xdd, 0x54, 0x07, 0xa6, 0x2e, 0x8c, 0x98,
+		0xfc, 0xc6, 0x8c, 0x04, 0x6b, 0x1b, 0x5f, 0xd5,
+		0x3d, 0x8b, 0x6c, 0x55, 0x4f, 0x7a, 0xe6, 0x6c,
+		0x74, 0x2c, 0x1e, 0x34, 0xdb, 0xfb, 0x00, 0xb1,
+		0x4e, 0x10, 0x21, 0x16, 0xe0, 0x3e, 0xc5, 0x64,
+		0x84, 0x28, 0x2b, 0x2b, 0x29, 0x47, 0x51, 0x34,
+		0x76, 0x15, 0x20, 0x71, 0x0b, 0x30, 0xa1, 0x85,
+		0xd5, 0x15, 0x18, 0x14, 0x64, 0x4b, 0x40, 0x7c,
+		0x4f, 0xb3, 0x7b, 0x14, 0x03, 0x01, 0x00, 0x01,
+		0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xab, 0xee,
+		0xf5, 0x97, 0x5f, 0xc6, 0x78, 0xf3, 0xc6, 0x83,
+		0x5b, 0x55, 0x4f, 0xcb, 0x45, 0x3f, 0xfa, 0xf7,
+		0x05, 0x02, 0xc2, 0x63, 0x87, 0x18, 0xb5, 0x9a,
+		0x62, 0xe2, 0x3f, 0x88, 0x5a, 0x60, 0x61, 0x72,
+		0xfa, 0x9c,
 	},
-
 	{
 		0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
-		0x01, 0x00, 0x24, 0xd3, 0x72, 0xeb, 0x29, 0xb9,
-		0x15, 0x29, 0xb5, 0xe5, 0xb7, 0xef, 0x5c, 0xb2,
-		0x9d, 0xf6, 0xc8, 0x47, 0xd6, 0xa0, 0x84, 0xf0,
-		0x8c, 0xcb, 0xe6, 0xbe, 0xbc, 0xfb, 0x38, 0x90,
-		0x89, 0x60, 0xa2, 0xe8, 0xaa, 0xb3, 0x12, 0x17,
-		0x03, 0x01, 0x00, 0x21, 0x67, 0x4a, 0x3d, 0x31,
-		0x6c, 0x5a, 0x1c, 0xf9, 0x6e, 0xf1, 0xd8, 0x12,
-		0x0e, 0xb9, 0xfd, 0xfc, 0x66, 0x91, 0xd1, 0x1d,
-		0x6e, 0xe4, 0x55, 0xdd, 0x11, 0xb9, 0xb8, 0xa2,
-		0x65, 0xa1, 0x95, 0x64, 0x1c, 0x15, 0x03, 0x01,
-		0x00, 0x16, 0x9b, 0xa0, 0x24, 0xe3, 0xcb, 0xae,
-		0xad, 0x51, 0xb3, 0x63, 0x59, 0x78, 0x49, 0x24,
-		0x06, 0x6e, 0xee, 0x7a, 0xd7, 0x74, 0x53, 0x04,
+		0x01, 0x00, 0x24, 0x72, 0xa4, 0xe4, 0xaa, 0xd2,
+		0xc4, 0x39, 0x7e, 0x2a, 0xc1, 0x6f, 0x34, 0x42,
+		0x28, 0xcb, 0x9d, 0x7a, 0x09, 0xca, 0x96, 0xad,
+		0x0e, 0x11, 0x51, 0x8a, 0x06, 0xb0, 0xe9, 0xca,
+		0xeb, 0xce, 0xe2, 0xd5, 0x2e, 0xc1, 0x8d, 0x17,
+		0x03, 0x01, 0x00, 0x21, 0x2e, 0x61, 0x86, 0x17,
+		0xdb, 0xa6, 0x30, 0xe2, 0x62, 0x06, 0x2a, 0x8b,
+		0x75, 0x2c, 0x2d, 0xcf, 0xf5, 0x01, 0x11, 0x52,
+		0x81, 0x38, 0xcf, 0xd5, 0xf7, 0xdc, 0x52, 0x31,
+		0x1f, 0x97, 0x43, 0xc2, 0x71, 0x15, 0x03, 0x01,
+		0x00, 0x16, 0xe0, 0x21, 0xfe, 0x36, 0x2e, 0x68,
+		0x2c, 0xf1, 0xbe, 0x04, 0xec, 0xd4, 0xc6, 0xdd,
+		0xac, 0x6f, 0x4c, 0x85, 0x32, 0x3f, 0x87, 0x1b,
 	},
 }
 
 var des3ServerScript = [][]byte{
 	{
-		0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
-		0x76, 0x03, 0x02, 0x4e, 0x84, 0xf4, 0x3c, 0xe4,
-		0xb8, 0xc7, 0xa0, 0x30, 0x55, 0x2a, 0xbc, 0xb7,
-		0x04, 0x6b, 0x6f, 0x87, 0x93, 0x96, 0xbd, 0x1a,
-		0x7a, 0x1e, 0xce, 0xd2, 0x0d, 0xf3, 0x01, 0x03,
-		0xbe, 0x7b, 0x17, 0x00, 0x00, 0x34, 0x00, 0x33,
-		0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
-		0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
-		0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
-		0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
-		0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
-		0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
-		0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
-		0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
-		0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
-		0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+		0x16, 0x03, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00,
+		0xc1, 0x03, 0x03, 0x50, 0xae, 0x5d, 0x38, 0xec,
+		0xaa, 0x2f, 0x41, 0xf9, 0xd2, 0x7b, 0xa1, 0xfd,
+		0x0f, 0xff, 0x4e, 0x54, 0x0e, 0x15, 0x57, 0xaf,
+		0x2c, 0x91, 0xb5, 0x35, 0x5b, 0x2e, 0xb0, 0xec,
+		0x20, 0xe5, 0xd2, 0x00, 0x00, 0x50, 0xc0, 0x09,
+		0xc0, 0x23, 0xc0, 0x2b, 0xc0, 0x0a, 0xc0, 0x24,
+		0xc0, 0x2c, 0xc0, 0x08, 0xc0, 0x13, 0xc0, 0x27,
+		0xc0, 0x2f, 0xc0, 0x14, 0xc0, 0x30, 0xc0, 0x12,
+		0x00, 0x33, 0x00, 0x67, 0x00, 0x45, 0x00, 0x9e,
+		0x00, 0x39, 0x00, 0x6b, 0x00, 0x88, 0x00, 0x16,
+		0x00, 0x32, 0x00, 0x40, 0x00, 0x44, 0x00, 0xa2,
+		0x00, 0x38, 0x00, 0x6a, 0x00, 0x87, 0x00, 0x13,
+		0x00, 0x66, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x41,
+		0x00, 0x9c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x84,
+		0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x01, 0x00,
+		0x00, 0x48, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+		0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00,
+		0x00, 0x23, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c,
+		0x00, 0x0a, 0x00, 0x13, 0x00, 0x15, 0x00, 0x17,
+		0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02,
+		0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a,
+		0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x05, 0x01,
+		0x05, 0x03, 0x06, 0x01, 0x06, 0x03, 0x03, 0x01,
+		0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02,
+		0x02, 0x03,
 	},
-
 	{
-		0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
-		0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+		0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x16,
-		0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
-		0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
-		0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
-		0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
-		0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
-		0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-		0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
+		0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+		0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+		0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+		0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+		0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+		0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+		0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+		0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+		0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+		0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+		0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+		0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+		0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+		0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+		0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+		0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+		0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+		0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+		0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+		0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+		0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+		0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+		0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+		0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+		0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+		0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+		0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+		0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+		0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+		0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+		0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+		0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+		0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+		0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+		0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+		0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+		0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+		0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+		0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+		0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+		0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+		0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+		0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+		0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+		0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+		0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+		0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+		0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+		0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+		0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+		0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+		0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+		0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+		0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+		0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+		0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+		0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+		0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+		0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
 		0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
 		0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
 		0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
@@ -506,172 +695,207 @@ var des3ServerScript = [][]byte{
 		0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
 		0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
 		0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
-		0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
-		0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
-		0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
-		0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
-		0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
-		0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
-		0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
-		0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
-		0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
-		0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
-		0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
-		0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
-		0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
-		0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
-		0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-		0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
-		0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
-		0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
-		0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
-		0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
-		0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
-		0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
-		0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
-		0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
-		0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
-		0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
-		0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
-		0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
-		0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
-		0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
-		0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
-		0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
-		0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
-		0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
-		0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
-		0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
-		0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
-		0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
-		0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
-		0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
-		0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
-		0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
-		0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
-		0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
-		0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
-		0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
-		0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
-		0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
-		0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
-		0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
-		0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
-		0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
-		0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
-		0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
-		0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
-		0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-		0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
-		0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
-		0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
-		0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
-		0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
-		0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
-		0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
-		0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
-		0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
-		0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
-		0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
-		0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
-		0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
-		0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
-		0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
-		0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
-		0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
-		0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
-		0x00, 0x00, 0x00,
+		0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+		0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+		0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+		0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+		0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+		0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+		0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+		0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+		0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+		0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+		0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+		0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+		0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+		0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+		0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+		0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+		0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+		0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+		0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+		0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+		0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+		0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+		0x16, 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00,
+		0x00,
 	},
-
 	{
 		0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
-		0x82, 0x00, 0x80, 0xae, 0xcf, 0x4f, 0x70, 0x0e,
-		0xe5, 0xe7, 0xba, 0xef, 0x0c, 0x66, 0xe9, 0xae,
-		0x76, 0xf4, 0xe0, 0xbc, 0x1c, 0x22, 0x5b, 0x72,
-		0xc9, 0x68, 0x63, 0x44, 0xec, 0x72, 0xc2, 0xca,
-		0xac, 0xc2, 0xf5, 0x5c, 0x28, 0xa1, 0xaf, 0xd0,
-		0xc2, 0xf7, 0x79, 0x71, 0x32, 0x73, 0x86, 0xea,
-		0x39, 0xf6, 0x04, 0x26, 0x19, 0x84, 0x1d, 0x7d,
-		0xa1, 0x21, 0xa6, 0x88, 0xbf, 0x33, 0x5a, 0x64,
-		0xb0, 0xc2, 0xcc, 0x19, 0x7a, 0x8b, 0x6e, 0x94,
-		0x9e, 0x2e, 0x20, 0xbe, 0xdc, 0xe9, 0x8e, 0xae,
-		0x5c, 0x39, 0xc8, 0xcd, 0x0e, 0x19, 0x9a, 0xa2,
-		0xfc, 0x3f, 0x61, 0x9a, 0xca, 0x58, 0x69, 0x0d,
-		0xa8, 0x7b, 0xbe, 0x98, 0x8f, 0xb9, 0x9d, 0x8b,
-		0x68, 0x65, 0xa9, 0x74, 0xcc, 0x8d, 0x0c, 0xb2,
-		0xc4, 0x0f, 0xdc, 0x56, 0x3e, 0x44, 0x61, 0x0a,
-		0x26, 0x93, 0x99, 0xef, 0x67, 0xff, 0x6e, 0x73,
-		0x01, 0xa1, 0x90, 0x14, 0x03, 0x01, 0x00, 0x01,
-		0x01, 0x16, 0x03, 0x01, 0x00, 0x60, 0x49, 0x36,
-		0xc8, 0x38, 0x95, 0xe4, 0x5d, 0x8e, 0x80, 0x10,
-		0x26, 0x9f, 0x87, 0x7d, 0xcd, 0xb9, 0x32, 0x6c,
-		0xff, 0xaa, 0xe0, 0x07, 0xec, 0x33, 0xe2, 0x36,
-		0x9d, 0xd5, 0x83, 0x2c, 0xf0, 0x0a, 0xa0, 0xa8,
-		0x12, 0x9f, 0xca, 0x72, 0xda, 0x70, 0x7d, 0x76,
-		0x80, 0x12, 0x88, 0x07, 0xaa, 0x27, 0x62, 0x33,
-		0xab, 0x55, 0xad, 0x3c, 0x2b, 0x54, 0xc4, 0x1c,
-		0x91, 0xfd, 0x8f, 0x9c, 0xa7, 0x8b, 0x75, 0x10,
-		0xa8, 0x6e, 0xfc, 0x30, 0x52, 0x8a, 0x61, 0x02,
-		0xdb, 0x9c, 0x6f, 0xc8, 0x19, 0x93, 0x5d, 0x41,
-		0x1d, 0x36, 0x68, 0x0b, 0xec, 0x30, 0xae, 0xfb,
-		0x90, 0xdb, 0x6d, 0x83, 0xb0, 0xf2,
+		0x82, 0x00, 0x80, 0x51, 0x04, 0xf1, 0x7a, 0xbf,
+		0xe8, 0xa5, 0x86, 0x09, 0xa7, 0xf3, 0xcc, 0x93,
+		0x00, 0x10, 0x5b, 0xb8, 0xc1, 0x51, 0x0d, 0x5b,
+		0xcd, 0xed, 0x26, 0x01, 0x69, 0x73, 0xf4, 0x05,
+		0x8a, 0x6a, 0xc3, 0xb1, 0x9e, 0x84, 0x4e, 0x39,
+		0xcf, 0x5e, 0x55, 0xa9, 0x70, 0x19, 0x96, 0x91,
+		0xcd, 0x2c, 0x78, 0x3c, 0xa2, 0x6d, 0xb0, 0x49,
+		0x86, 0xf6, 0xd1, 0x3a, 0xde, 0x00, 0x4b, 0xa6,
+		0x25, 0xbf, 0x85, 0x39, 0xce, 0xb1, 0xcf, 0xbc,
+		0x16, 0xc7, 0x66, 0xac, 0xf8, 0xd2, 0x3b, 0xd1,
+		0xcc, 0x16, 0xac, 0x63, 0x3c, 0xbe, 0xd9, 0xb6,
+		0x6a, 0xe4, 0x13, 0x8a, 0xf4, 0x56, 0x2f, 0x92,
+		0x54, 0xd8, 0xf0, 0x84, 0x01, 0x32, 0x1a, 0xa9,
+		0x2d, 0xaf, 0x82, 0x0e, 0x00, 0xfa, 0x07, 0x88,
+		0xd9, 0x87, 0xe7, 0xdc, 0x9e, 0xe9, 0x72, 0x49,
+		0xb8, 0xfa, 0x8c, 0x7b, 0x07, 0x0b, 0x03, 0x7c,
+		0x10, 0x8c, 0x8a, 0x14, 0x03, 0x01, 0x00, 0x01,
+		0x01, 0x16, 0x03, 0x01, 0x00, 0xa8, 0x61, 0xa4,
+		0xf4, 0x5f, 0x8a, 0x1f, 0x5c, 0x92, 0x3f, 0x8c,
+		0xdb, 0xd6, 0x10, 0xcd, 0x9e, 0xe7, 0xf0, 0xc4,
+		0x3c, 0xb6, 0x1c, 0x9a, 0x56, 0x73, 0x7f, 0xa6,
+		0x14, 0x24, 0xcb, 0x96, 0x1f, 0xe0, 0xaf, 0xcd,
+		0x3c, 0x66, 0x43, 0xb7, 0x37, 0x65, 0x34, 0x47,
+		0xf8, 0x43, 0xf1, 0xcc, 0x15, 0xb8, 0xdc, 0x35,
+		0xe0, 0xa4, 0x2d, 0x78, 0x94, 0xe0, 0x02, 0xf3,
+		0x76, 0x46, 0xf7, 0x9b, 0x8d, 0x0d, 0x5d, 0x0b,
+		0xd3, 0xdd, 0x9a, 0x9e, 0x62, 0x2e, 0xc5, 0x98,
+		0x75, 0x63, 0x0c, 0xbf, 0x8e, 0x49, 0x33, 0x23,
+		0x7c, 0x00, 0xcf, 0xfb, 0xcf, 0xba, 0x0f, 0x41,
+		0x39, 0x89, 0xb9, 0xcc, 0x59, 0xd0, 0x2b, 0xb6,
+		0xec, 0x04, 0xe2, 0xc0, 0x52, 0xc7, 0xcf, 0x71,
+		0x47, 0xff, 0x70, 0x7e, 0xa9, 0xbd, 0x1c, 0xdd,
+		0x17, 0xa5, 0x6c, 0xb7, 0x10, 0x4f, 0x42, 0x18,
+		0x37, 0x69, 0xa9, 0xd2, 0xb3, 0x18, 0x84, 0x92,
+		0xa7, 0x47, 0x21, 0xf6, 0x95, 0x63, 0x29, 0xd6,
+		0xa5, 0xb6, 0xda, 0x65, 0x67, 0x69, 0xc4, 0x26,
+		0xac, 0x8b, 0x08, 0x58, 0xdd, 0x3c, 0x31, 0x20,
+		0xd5, 0x0c, 0x88, 0x72, 0x18, 0x16, 0x88, 0x1e,
+		0x4a, 0x0f, 0xe1, 0xcf, 0x95, 0x24,
 	},
-
 	{
-		0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
-		0x01, 0x00, 0x28, 0x07, 0xf3, 0x33, 0x84, 0xb1,
-		0x5d, 0x2b, 0x52, 0xa4, 0x63, 0x3c, 0x32, 0xe0,
-		0x0d, 0x22, 0xf5, 0x23, 0xec, 0xf9, 0xa6, 0xec,
-		0xc0, 0x12, 0x69, 0x88, 0xf6, 0x7d, 0x37, 0xcd,
-		0xc2, 0x74, 0x2f, 0xef, 0xf6, 0x49, 0x15, 0xea,
-		0x88, 0x3f, 0x55, 0x17, 0x03, 0x01, 0x00, 0x28,
-		0xaf, 0x00, 0x84, 0xff, 0x11, 0x01, 0x6d, 0xba,
-		0x39, 0x5e, 0x45, 0xe1, 0x52, 0x5e, 0xc1, 0xab,
-		0xde, 0x5b, 0x16, 0xdd, 0xd6, 0x61, 0x57, 0xb8,
-		0x66, 0x8b, 0x2d, 0xde, 0x51, 0x41, 0xc5, 0x09,
-		0xb3, 0x6a, 0x06, 0x43, 0xb4, 0x73, 0x5c, 0xf1,
-		0x15, 0x03, 0x01, 0x00, 0x18, 0xbd, 0x65, 0xb2,
-		0xce, 0x77, 0x2e, 0xf9, 0x11, 0xc4, 0x80, 0x43,
-		0x5a, 0x73, 0x8b, 0x73, 0xdd, 0xf0, 0x54, 0x44,
-		0x7c, 0x56, 0x19, 0x54, 0xda,
+		0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00,
+		0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+		0xe8, 0x4b, 0xde, 0xef, 0xba, 0x3e, 0x18, 0x1c,
+		0x1e, 0x5e, 0xbc, 0x87, 0xf1, 0x87, 0x8d, 0x72,
+		0xe3, 0xbe, 0x0f, 0xdf, 0xfd, 0xd0, 0xb2, 0x89,
+		0xf8, 0x05, 0x9a, 0x52, 0x47, 0x77, 0x9e, 0xe8,
+		0xb1, 0x1d, 0x18, 0xed, 0x6a, 0x4b, 0x63, 0x1d,
+		0xf1, 0x62, 0xd2, 0x65, 0x21, 0x26, 0x73, 0xd4,
+		0x35, 0x5b, 0x95, 0x89, 0x12, 0x59, 0x23, 0x8c,
+		0xc3, 0xfc, 0xf9, 0x4d, 0x21, 0x79, 0xa0, 0xbd,
+		0xff, 0x33, 0xa2, 0x3d, 0x0b, 0x6f, 0x89, 0xc9,
+		0x23, 0xe4, 0xe7, 0x9f, 0x1d, 0x98, 0xf6, 0xed,
+		0x02, 0x8d, 0xac, 0x1a, 0xf9, 0xcb, 0xa5, 0x14,
+		0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+		0x00, 0x28, 0x91, 0x56, 0x80, 0xe2, 0x6d, 0x51,
+		0x88, 0x03, 0xf8, 0x49, 0xe6, 0x6a, 0x5a, 0xfb,
+		0x2f, 0x0b, 0xb5, 0xa1, 0x0d, 0x63, 0x83, 0xae,
+		0xb9, 0xbc, 0x05, 0xf0, 0x81, 0x00, 0x61, 0x83,
+		0x38, 0xda, 0x14, 0xf6, 0xea, 0xd8, 0x78, 0x65,
+		0xc7, 0x26, 0x17, 0x03, 0x01, 0x00, 0x18, 0x81,
+		0x30, 0x8b, 0x22, 0x5a, 0xd3, 0x7f, 0xc8, 0xf2,
+		0x8a, 0x6b, 0xa3, 0xba, 0x4d, 0xe7, 0x6e, 0xd2,
+		0xfd, 0xbf, 0xf2, 0xc5, 0x28, 0xa0, 0x62, 0x17,
+		0x03, 0x01, 0x00, 0x28, 0x17, 0x83, 0x3c, 0x78,
+		0x18, 0xfa, 0x8d, 0x58, 0x5c, 0xaa, 0x05, 0x7d,
+		0x67, 0x96, 0x11, 0x60, 0x11, 0xc0, 0x1e, 0x0d,
+		0x6a, 0x6e, 0x5f, 0x1d, 0x98, 0x4b, 0xff, 0x82,
+		0xee, 0x21, 0x06, 0x29, 0xd3, 0x8b, 0x80, 0x78,
+		0x39, 0x05, 0x34, 0x9b, 0x15, 0x03, 0x01, 0x00,
+		0x18, 0xa9, 0x38, 0x18, 0x4f, 0x9d, 0x84, 0x75,
+		0x88, 0x53, 0xd6, 0x85, 0xc2, 0x15, 0x4b, 0xe3,
+		0xe3, 0x35, 0x9a, 0x74, 0xc9, 0x3e, 0x13, 0xc1,
+		0x8c,
 	},
 }
 
 var aesServerScript = [][]byte{
 	{
-		0x16, 0x03, 0x02, 0x00, 0x7f, 0x01, 0x00, 0x00,
-		0x7b, 0x03, 0x02, 0x4d, 0x08, 0x2d, 0x0b, 0xb3,
-		0x57, 0x85, 0x71, 0x4b, 0xfb, 0x34, 0xab, 0x16,
-		0xd4, 0x92, 0x50, 0x81, 0x16, 0x95, 0x11, 0x28,
-		0x1a, 0xcb, 0xff, 0x09, 0x4d, 0x23, 0xa6, 0xfe,
-		0x2e, 0xbb, 0x78, 0x00, 0x00, 0x34, 0x00, 0x33,
-		0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
-		0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
-		0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
-		0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
-		0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
-		0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
-		0x00, 0x8a, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x09,
-		0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
-		0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
-		0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0xff,
-		0x01, 0x00, 0x01, 0x00,
+		0x16, 0x03, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00,
+		0xc1, 0x03, 0x03, 0x50, 0xae, 0x5c, 0xe9, 0x5e,
+		0x31, 0x93, 0x82, 0xa5, 0x6f, 0x51, 0x82, 0xc8,
+		0x55, 0x4f, 0x1f, 0x2e, 0x90, 0x98, 0x81, 0x13,
+		0x27, 0x80, 0x68, 0xb4, 0x2d, 0xba, 0x3a, 0x76,
+		0xd8, 0xd7, 0x2c, 0x00, 0x00, 0x50, 0xc0, 0x09,
+		0xc0, 0x23, 0xc0, 0x2b, 0xc0, 0x0a, 0xc0, 0x24,
+		0xc0, 0x2c, 0xc0, 0x08, 0xc0, 0x13, 0xc0, 0x27,
+		0xc0, 0x2f, 0xc0, 0x14, 0xc0, 0x30, 0xc0, 0x12,
+		0x00, 0x33, 0x00, 0x67, 0x00, 0x45, 0x00, 0x9e,
+		0x00, 0x39, 0x00, 0x6b, 0x00, 0x88, 0x00, 0x16,
+		0x00, 0x32, 0x00, 0x40, 0x00, 0x44, 0x00, 0xa2,
+		0x00, 0x38, 0x00, 0x6a, 0x00, 0x87, 0x00, 0x13,
+		0x00, 0x66, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x41,
+		0x00, 0x9c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x84,
+		0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x01, 0x00,
+		0x00, 0x48, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00,
+		0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00,
+		0x00, 0x23, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c,
+		0x00, 0x0a, 0x00, 0x13, 0x00, 0x15, 0x00, 0x17,
+		0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02,
+		0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a,
+		0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x05, 0x01,
+		0x05, 0x03, 0x06, 0x01, 0x06, 0x03, 0x03, 0x01,
+		0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02,
+		0x02, 0x03,
 	},
-
 	{
-		0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
-		0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+		0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x16,
-		0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
-		0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
-		0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
-		0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
-		0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
-		0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-		0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,
+		0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+		0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+		0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+		0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+		0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+		0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+		0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+		0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+		0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+		0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+		0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+		0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+		0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+		0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+		0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+		0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+		0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+		0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+		0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+		0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+		0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+		0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+		0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+		0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+		0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+		0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+		0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+		0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+		0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+		0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+		0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+		0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+		0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+		0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+		0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+		0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+		0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+		0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+		0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+		0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+		0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+		0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+		0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+		0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+		0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+		0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+		0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+		0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+		0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+		0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+		0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+		0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+		0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+		0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+		0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+		0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+		0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+		0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+		0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
 		0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
 		0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
 		0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
@@ -680,136 +904,144 @@ var aesServerScript = [][]byte{
 		0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
 		0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
 		0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
-		0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
-		0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
-		0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
-		0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
-		0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
-		0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
-		0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
-		0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
-		0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
-		0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
-		0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
-		0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
-		0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
-		0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
-		0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-		0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
-		0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
-		0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
-		0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
-		0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
-		0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
-		0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
-		0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
-		0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
-		0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
-		0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
-		0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
-		0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
-		0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
-		0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
-		0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
-		0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
-		0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
-		0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
-		0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
-		0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
-		0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
-		0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
-		0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
-		0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
-		0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
-		0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
-		0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
-		0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
-		0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
-		0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
-		0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
-		0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
-		0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
-		0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
-		0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
-		0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
-		0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
-		0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
-		0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
-		0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-		0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
-		0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
-		0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
-		0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
-		0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
-		0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
-		0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
-		0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
-		0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
-		0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
-		0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
-		0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
-		0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
-		0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
-		0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
-		0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
-		0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
-		0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
-		0x00, 0x00, 0x00,
+		0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+		0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+		0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+		0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+		0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+		0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+		0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+		0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+		0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+		0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+		0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+		0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+		0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+		0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+		0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+		0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+		0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+		0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+		0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+		0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+		0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+		0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+		0x16, 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00,
+		0x00,
 	},
-
 	{
 		0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
-		0x82, 0x00, 0x80, 0x71, 0x9c, 0xe7, 0x23, 0xfc,
-		0xb9, 0x19, 0x29, 0x82, 0xbf, 0xef, 0x08, 0xf7,
-		0x99, 0x36, 0xc3, 0x4c, 0x6f, 0x05, 0xd2, 0x8b,
-		0x62, 0x2b, 0x19, 0x9b, 0x7f, 0xc0, 0xcc, 0x48,
-		0x30, 0x5f, 0xcd, 0xc3, 0x70, 0x55, 0x53, 0x73,
-		0xfa, 0x79, 0x74, 0xf3, 0xa3, 0x76, 0x9f, 0xa1,
-		0x7f, 0x98, 0xc2, 0xc0, 0xe3, 0xc5, 0xa0, 0x31,
-		0x2f, 0xa6, 0xe8, 0x1e, 0x61, 0x46, 0xb3, 0x9b,
-		0x4b, 0x16, 0xf1, 0x2d, 0xc7, 0x63, 0x7f, 0x79,
-		0x22, 0x30, 0xd1, 0xf2, 0xfc, 0x77, 0x98, 0x0a,
-		0x16, 0x11, 0x63, 0x71, 0x7f, 0x70, 0xef, 0x16,
-		0xbb, 0x39, 0x87, 0x34, 0xac, 0x49, 0xbd, 0x07,
-		0x67, 0xcb, 0x9c, 0xcc, 0xde, 0xef, 0xb1, 0xe0,
-		0xdb, 0x01, 0xb5, 0x35, 0xa9, 0xb3, 0x10, 0x0c,
-		0x4b, 0xee, 0xb3, 0x4e, 0xfd, 0xbe, 0x15, 0x27,
-		0xf0, 0x46, 0xb2, 0x38, 0xba, 0x5f, 0xcc, 0x89,
-		0xec, 0x29, 0x82, 0x14, 0x03, 0x01, 0x00, 0x01,
-		0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0x3c, 0xfb,
-		0xa4, 0x12, 0xcb, 0x00, 0xf9, 0x57, 0x7e, 0x9b,
-		0xc9, 0xdc, 0x0c, 0xba, 0x9a, 0x81, 0x62, 0xfb,
-		0x26, 0x13, 0x53, 0xfe, 0xaa, 0xcc, 0x82, 0xbb,
-		0xb6, 0x67, 0x7f, 0x39, 0xbe, 0x4d, 0xbb, 0xc0,
-		0x6c, 0x24, 0x31, 0x83, 0xa5, 0x50, 0x3a, 0x75,
-		0x32, 0x64, 0xb5, 0xdb, 0xbe, 0x0a,
+		0x82, 0x00, 0x80, 0x51, 0x2e, 0xec, 0x0d, 0x86,
+		0xf3, 0x9f, 0xf2, 0x77, 0x04, 0x27, 0x2b, 0x0e,
+		0x9c, 0xab, 0x35, 0x84, 0x65, 0xff, 0x36, 0xef,
+		0xc0, 0x08, 0xc9, 0x1d, 0x9f, 0x29, 0xae, 0x8d,
+		0xc5, 0x66, 0x81, 0x31, 0x92, 0x5e, 0x3d, 0xac,
+		0xaa, 0x37, 0x28, 0x2c, 0x06, 0x91, 0xa6, 0xc2,
+		0xd0, 0x83, 0x34, 0x24, 0x1c, 0x88, 0xfc, 0x0a,
+		0xcf, 0xbf, 0xc2, 0x94, 0xe2, 0xed, 0xa7, 0x6a,
+		0xa8, 0x8d, 0x3d, 0xf7, 0x06, 0x7d, 0x69, 0xf8,
+		0x0d, 0xb2, 0xf7, 0xe4, 0x45, 0xcb, 0x0a, 0x25,
+		0xcb, 0xb2, 0x2e, 0x38, 0x9a, 0x84, 0x75, 0xe8,
+		0xe1, 0x42, 0x39, 0xa2, 0x18, 0x0e, 0x48, 0xca,
+		0x33, 0x16, 0x4e, 0xf6, 0x2f, 0xec, 0x07, 0xe7,
+		0x57, 0xe1, 0x20, 0x40, 0x40, 0x6d, 0x4e, 0x29,
+		0x04, 0x1a, 0x8c, 0x99, 0xfb, 0x19, 0x3c, 0xaa,
+		0x75, 0x64, 0xd3, 0xa6, 0xe6, 0xed, 0x3f, 0x5a,
+		0xd2, 0xc9, 0x80, 0x14, 0x03, 0x01, 0x00, 0x01,
+		0x01, 0x16, 0x03, 0x01, 0x01, 0x10, 0xe9, 0x9e,
+		0x06, 0x92, 0x18, 0xbf, 0x5e, 0xaf, 0x33, 0xc1,
+		0xbf, 0x0e, 0x12, 0x07, 0x48, 0x4f, 0x6b, 0x6c,
+		0xf5, 0x23, 0x5e, 0x87, 0xa7, 0xd3, 0x50, 0x79,
+		0x38, 0xdc, 0xe0, 0x49, 0xd3, 0x81, 0x21, 0x12,
+		0xd0, 0x3d, 0x9a, 0xfb, 0x83, 0xc1, 0x8b, 0xfc,
+		0x14, 0xd5, 0xd5, 0xa7, 0xa3, 0x34, 0x14, 0x71,
+		0xbe, 0xea, 0x37, 0x18, 0x12, 0x7f, 0x41, 0xfb,
+		0xc5, 0x51, 0x17, 0x9d, 0x96, 0x58, 0x14, 0xfb,
+		0x4f, 0xd7, 0xd3, 0x15, 0x0f, 0xec, 0x5a, 0x0d,
+		0x35, 0xbb, 0x3c, 0x81, 0x5b, 0x3f, 0xdf, 0x52,
+		0xa4, 0x4c, 0xcd, 0x13, 0xe1, 0x10, 0x37, 0x34,
+		0xbf, 0xb4, 0x80, 0x1e, 0x8d, 0xe2, 0xc3, 0x7a,
+		0x0f, 0x7b, 0x7d, 0x23, 0xeb, 0xd0, 0x99, 0x69,
+		0xad, 0x0a, 0x2d, 0xb3, 0x6c, 0xd6, 0x80, 0x11,
+		0x7f, 0x6c, 0xed, 0x1b, 0xcd, 0x08, 0x22, 0x56,
+		0x90, 0x0e, 0xa4, 0xc3, 0x29, 0x33, 0x96, 0x30,
+		0x34, 0x94, 0xa1, 0xeb, 0x9c, 0x1b, 0x5a, 0xd1,
+		0x03, 0x61, 0xf9, 0xdd, 0xf3, 0x64, 0x8a, 0xfd,
+		0x5f, 0x44, 0xdb, 0x2e, 0xa7, 0xfd, 0xe1, 0x1a,
+		0x66, 0xc5, 0x01, 0x9c, 0xc7, 0xd1, 0xc4, 0xd3,
+		0xea, 0x14, 0x3c, 0xed, 0x74, 0xbb, 0x1b, 0x97,
+		0x8f, 0xf1, 0x29, 0x39, 0x33, 0x92, 0x93, 0x4e,
+		0xf5, 0x87, 0x91, 0x61, 0x65, 0x8d, 0x27, 0x8d,
+		0x76, 0xc1, 0xfa, 0x6a, 0x99, 0x80, 0xb1, 0x9b,
+		0x29, 0x53, 0xce, 0x3e, 0xb6, 0x9a, 0xce, 0x3c,
+		0x19, 0x5e, 0x48, 0x83, 0xaa, 0xa7, 0x66, 0x98,
+		0x59, 0xf4, 0xbb, 0xf2, 0xbc, 0xd9, 0xc5, 0x9a,
+		0xc8, 0x2c, 0x63, 0x58, 0xd5, 0xd4, 0xbc, 0x03,
+		0xa9, 0x06, 0xa9, 0x80, 0x0d, 0xb3, 0x46, 0x2d,
+		0xe3, 0xc6, 0xaf, 0x1a, 0x39, 0x18, 0x7e, 0x1e,
+		0x83, 0x80, 0x46, 0x11, 0xd2, 0x13, 0x9f, 0xda,
+		0xfc, 0x2d, 0x42, 0xaa, 0x5a, 0x1d, 0x4c, 0x31,
+		0xe5, 0x58, 0x78, 0x5e, 0xe2, 0x04, 0xd6, 0x23,
+		0x7f, 0x3f, 0x06, 0xc0, 0x54, 0xf8,
 	},
-
 	{
-		0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
-		0x01, 0x00, 0x30, 0x43, 0x24, 0x42, 0x55, 0x08,
-		0xe4, 0xc2, 0x15, 0xc9, 0xdb, 0x71, 0x69, 0xee,
-		0x09, 0xc5, 0x1c, 0xfd, 0x46, 0x10, 0xa0, 0x68,
-		0x21, 0xf2, 0x48, 0xac, 0x6c, 0xc0, 0x2b, 0x62,
-		0x07, 0x8f, 0x48, 0x33, 0x0a, 0x6b, 0x62, 0x28,
-		0x2e, 0x2c, 0xad, 0xcb, 0x34, 0x85, 0xca, 0x2e,
-		0xcd, 0x84, 0xf0,
+		0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00,
+		0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+		0xe8, 0x4b, 0xfb, 0xef, 0xba, 0xed, 0xc5, 0x36,
+		0xc8, 0x5a, 0x41, 0x3f, 0x05, 0xfa, 0xfe, 0x48,
+		0xc3, 0x91, 0x12, 0x8b, 0xe8, 0x32, 0x6a, 0x9f,
+		0xdc, 0x97, 0xe2, 0x77, 0xb9, 0x96, 0x2d, 0xd4,
+		0xe5, 0xbd, 0xa1, 0xfd, 0x94, 0xbb, 0x74, 0x63,
+		0xb1, 0x0c, 0x38, 0xbc, 0x6f, 0x69, 0xaf, 0xa3,
+		0x46, 0x9c, 0x96, 0x41, 0xde, 0x59, 0x23, 0xff,
+		0x15, 0x6b, 0x3a, 0xef, 0x91, 0x6d, 0x92, 0x44,
+		0xdc, 0x72, 0x1f, 0x40, 0x3d, 0xb5, 0x34, 0x8f,
+		0x2a, 0xac, 0x21, 0x69, 0x05, 0x6f, 0xb2, 0x60,
+		0x32, 0x5d, 0x3d, 0x97, 0xb4, 0x24, 0x99, 0x14,
+		0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+		0x00, 0x30, 0x68, 0x27, 0x97, 0xca, 0x63, 0x09,
+		0x22, 0xed, 0x0e, 0x61, 0x7c, 0x76, 0x31, 0x9c,
+		0xbe, 0x27, 0xc9, 0xe6, 0x09, 0xc3, 0xc3, 0xc2,
+		0xf4, 0xa2, 0x32, 0xba, 0x7c, 0xf2, 0x0f, 0xb8,
+		0x3d, 0xcb, 0xe2, 0x4c, 0xc0, 0x7d, 0x8e, 0x5b,
+		0x5a, 0xed, 0x05, 0x5c, 0x15, 0x96, 0x69, 0xc2,
+		0x6f, 0x5f, 0x17, 0x03, 0x01, 0x00, 0x20, 0x5a,
+		0xfe, 0x0b, 0xe1, 0x6f, 0xa8, 0x54, 0x19, 0x78,
+		0xca, 0xba, 0x2e, 0x1e, 0x2e, 0xe1, 0x5d, 0x17,
+		0xe5, 0x97, 0x05, 0x2c, 0x08, 0x0c, 0xff, 0xa8,
+		0x59, 0xa9, 0xde, 0x5e, 0x21, 0x34, 0x04, 0x17,
+		0x03, 0x01, 0x00, 0x30, 0x86, 0xb1, 0x3f, 0x88,
+		0x43, 0xf0, 0x07, 0xee, 0xa8, 0xf4, 0xbc, 0xe7,
+		0x5f, 0xc6, 0x8c, 0x86, 0x4c, 0xca, 0x70, 0x88,
+		0xcc, 0x6a, 0xb4, 0x3d, 0x40, 0xe8, 0x54, 0x89,
+		0x19, 0x43, 0x1f, 0x76, 0xe2, 0xac, 0xb2, 0x5b,
+		0x92, 0xf8, 0x57, 0x39, 0x2a, 0xc3, 0x6d, 0x13,
+		0x45, 0xfa, 0x36, 0x9e, 0x15, 0x03, 0x01, 0x00,
+		0x20, 0x6d, 0xed, 0x7b, 0x59, 0x28, 0x2a, 0x27,
+		0x04, 0x15, 0x07, 0x4e, 0xeb, 0x13, 0x00, 0xe3,
+		0x3a, 0x3f, 0xf8, 0xaa, 0x2b, 0x3b, 0x1a, 0x8c,
+		0x12, 0xd6, 0x4c, 0xec, 0x2a, 0xaf, 0x33, 0x60,
+		0xaf,
 	},
 }
 
 var sslv3ServerScript = [][]byte{
 	{
-		0x16, 0x03, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00,
-		0x3d, 0x03, 0x00, 0x4e, 0x70, 0xe2, 0x18, 0x86,
-		0xd6, 0xc6, 0x6f, 0xf3, 0xc8, 0xf4, 0x02, 0xd6,
-		0x4d, 0xee, 0x17, 0x32, 0x4b, 0xd2, 0x78, 0xd8,
-		0xa1, 0x03, 0x5d, 0x68, 0x82, 0x89, 0xbe, 0xfd,
-		0x12, 0xb9, 0x06, 0x00, 0x00, 0x16, 0x00, 0x33,
-		0x00, 0x39, 0x00, 0x16, 0x00, 0x32, 0x00, 0x38,
-		0x00, 0x13, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a,
-		0x00, 0x05, 0x00, 0x04, 0x01, 0x00,
+		0x16, 0x03, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00,
+		0x50, 0x03, 0x00, 0x50, 0x77, 0x3d, 0x42, 0xae,
+		0x84, 0xbd, 0xc5, 0x07, 0xa5, 0xc4, 0xd6, 0x16,
+		0x4e, 0xd5, 0xc5, 0xfa, 0x02, 0x7a, 0x0f, 0x1d,
+		0xc1, 0xe1, 0xaa, 0xe3, 0x3b, 0x4b, 0x6f, 0x11,
+		0xfa, 0x1a, 0xa4, 0x00, 0x00, 0x28, 0x00, 0x39,
+		0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+		0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+		0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+		0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+		0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+		0x00,
 	},
-
 	{
 		0x16, 0x03, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00,
 		0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -908,74 +1140,71 @@ var sslv3ServerScript = [][]byte{
 		0xbd, 0xd9, 0x16, 0x03, 0x00, 0x00, 0x04, 0x0e,
 		0x00, 0x00, 0x00,
 	},
-
 	{
 		0x16, 0x03, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00,
-		0x80, 0x74, 0x0e, 0x3a, 0xcf, 0xba, 0x9f, 0x1a,
-		0x9b, 0xb2, 0xa4, 0xc7, 0x5d, 0xf3, 0x0c, 0x80,
-		0x06, 0x80, 0xf3, 0x57, 0xb2, 0xd9, 0x36, 0x24,
-		0x6a, 0x06, 0x13, 0x40, 0xf9, 0x7c, 0xb9, 0x3e,
-		0x4b, 0x68, 0x4f, 0x21, 0x90, 0x2d, 0xbd, 0xca,
-		0xd4, 0x83, 0xf0, 0x7a, 0xeb, 0x7a, 0x74, 0x1b,
-		0xcd, 0xfe, 0x69, 0xef, 0xc0, 0x86, 0xa0, 0x24,
-		0x31, 0x65, 0x40, 0xd2, 0xdd, 0x6f, 0xb9, 0xd7,
-		0x8d, 0xc1, 0x69, 0x60, 0x44, 0x7a, 0x75, 0xfb,
-		0x42, 0x6a, 0x0f, 0x66, 0x45, 0x10, 0x73, 0xee,
-		0x87, 0x28, 0x37, 0x83, 0x86, 0xd8, 0x5a, 0xc8,
-		0x60, 0x87, 0xda, 0x33, 0x87, 0xaf, 0x34, 0x8b,
-		0xf5, 0x61, 0x63, 0x7a, 0x5c, 0x60, 0x26, 0xb9,
-		0xdb, 0xa1, 0xb7, 0xe3, 0x60, 0x38, 0x94, 0x5c,
-		0x83, 0x23, 0xd6, 0x8d, 0xc2, 0x14, 0x4a, 0x0f,
-		0x0e, 0x4f, 0xf9, 0x4e, 0x7b, 0x15, 0xcd, 0x18,
-		0x04, 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16,
-		0x03, 0x00, 0x00, 0x3c, 0xbd, 0xbc, 0xec, 0xdc,
-		0x79, 0xb1, 0xae, 0x16, 0xc9, 0x26, 0x9a, 0xc0,
-		0xc0, 0x2c, 0x33, 0x36, 0x13, 0x91, 0x58, 0x5d,
-		0x7d, 0xee, 0x4e, 0xd8, 0x7e, 0xac, 0x88, 0x87,
-		0x0a, 0x75, 0x66, 0xb1, 0x44, 0x79, 0x2f, 0x42,
-		0xe8, 0x92, 0x74, 0x4c, 0xab, 0x36, 0xc8, 0x17,
-		0x5f, 0x02, 0x8a, 0x20, 0x53, 0xe9, 0x1d, 0xb4,
-		0xfe, 0x5c, 0x2b, 0xd9, 0x0a, 0xfb, 0xc6, 0x63,
+		0x80, 0x4a, 0x8d, 0xc4, 0x38, 0x7a, 0x9c, 0xd6,
+		0xe8, 0x72, 0x9e, 0xa3, 0xdf, 0x37, 0xb4, 0x6c,
+		0x58, 0x33, 0x59, 0xd9, 0xc9, 0x4b, 0x50, 0x33,
+		0x6c, 0xed, 0x73, 0x38, 0x2a, 0x46, 0x55, 0x31,
+		0xa9, 0x8e, 0x8e, 0xfc, 0x0b, 0x5d, 0x5f, 0x3c,
+		0x88, 0x28, 0x3f, 0x60, 0x51, 0x13, 0xf1, 0x59,
+		0x0c, 0xa3, 0x5e, 0xe0, 0xa3, 0x35, 0x06, 0xb1,
+		0x71, 0x59, 0x24, 0x4e, 0xed, 0x07, 0x15, 0x88,
+		0x50, 0xef, 0xc2, 0xb2, 0x2a, 0x52, 0x30, 0x6a,
+		0x7c, 0xbe, 0x2f, 0xc6, 0x8f, 0xa8, 0x83, 0xc5,
+		0x80, 0x14, 0x62, 0x74, 0x7f, 0x96, 0x9f, 0x41,
+		0x32, 0x74, 0xdd, 0x76, 0x2d, 0x7b, 0xeb, 0x7b,
+		0xea, 0xd0, 0x4f, 0x0c, 0xcf, 0x9a, 0x9c, 0xc5,
+		0x7a, 0xe4, 0xbc, 0xf8, 0xa6, 0xe1, 0x09, 0x8e,
+		0x7c, 0x53, 0x3a, 0xe3, 0x30, 0x8f, 0x76, 0xee,
+		0x58, 0xbb, 0xfd, 0x0b, 0x06, 0xb8, 0xdf, 0xb7,
+		0x31, 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16,
+		0x03, 0x00, 0x00, 0x3c, 0x13, 0x91, 0xc6, 0x4a,
+		0x0c, 0x59, 0x25, 0xce, 0x54, 0xc0, 0x1d, 0xb9,
+		0x2a, 0xff, 0x4d, 0xca, 0x26, 0x0c, 0x8c, 0x04,
+		0x98, 0x7c, 0x7c, 0x38, 0xa3, 0xf5, 0xf9, 0x36,
+		0x1c, 0x04, 0x32, 0x47, 0x2d, 0x48, 0x0e, 0x96,
+		0xe8, 0x2b, 0x5e, 0x5a, 0xc6, 0x0a, 0x48, 0x41,
+		0x34, 0x5e, 0x62, 0xd5, 0x68, 0x4e, 0x44, 0x1d,
+		0xb2, 0xa1, 0x11, 0xad, 0x6e, 0x14, 0x85, 0x61,
 	},
-
 	{
 		0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16, 0x03,
-		0x00, 0x00, 0x3c, 0xaa, 0xa1, 0x98, 0xc4, 0x6b,
-		0x5a, 0x16, 0x3f, 0x5f, 0xa4, 0x96, 0x3e, 0x78,
-		0xe4, 0x6f, 0x49, 0x05, 0x47, 0xc4, 0x05, 0x60,
-		0xeb, 0x0b, 0x45, 0xe3, 0xbc, 0x50, 0x11, 0x24,
-		0x5f, 0x01, 0xd7, 0xb8, 0x8f, 0x60, 0x63, 0x66,
-		0xbd, 0x3e, 0xd9, 0xa8, 0x80, 0x43, 0x9f, 0x0b,
-		0x51, 0x61, 0xed, 0x13, 0xc6, 0x21, 0xd0, 0xfe,
-		0xbc, 0x17, 0x3c, 0x36, 0xb0, 0x82, 0x7f, 0x17,
-		0x03, 0x00, 0x00, 0x21, 0xee, 0x44, 0xf3, 0xa6,
-		0x88, 0x9d, 0x78, 0x44, 0xde, 0xdf, 0xeb, 0xc5,
-		0xad, 0xc4, 0xcc, 0x56, 0x5c, 0x54, 0x96, 0x52,
-		0x3f, 0xd9, 0x40, 0x6e, 0x79, 0xd8, 0x58, 0x78,
-		0x4f, 0x5a, 0xe9, 0x06, 0xef, 0x15, 0x03, 0x00,
-		0x00, 0x16, 0xd3, 0xc2, 0x52, 0x99, 0x2a, 0x84,
-		0xc4, 0x52, 0x5f, 0x3b, 0x19, 0xe7, 0xfc, 0x65,
-		0xaf, 0xd3, 0xb7, 0xa3, 0xcc, 0x4a, 0x1d, 0x2e,
+		0x00, 0x00, 0x3c, 0x88, 0xae, 0xa9, 0xd4, 0xa8,
+		0x10, 0x8d, 0x65, 0xa6, 0x3e, 0x1e, 0xed, 0xd2,
+		0xfc, 0xc4, 0x7c, 0xa8, 0x94, 0x4f, 0x11, 0xaf,
+		0xa6, 0x87, 0x09, 0x37, 0x54, 0xf7, 0x69, 0xd1,
+		0xb5, 0x25, 0x6b, 0xb5, 0xed, 0xcb, 0x25, 0x39,
+		0x73, 0xeb, 0x53, 0x6c, 0xc7, 0xb4, 0x29, 0x8f,
+		0xd6, 0x49, 0xd1, 0x95, 0x59, 0x80, 0x9a, 0x67,
+		0x5c, 0xb2, 0xe0, 0xbd, 0x1e, 0xff, 0xaa, 0x17,
+		0x03, 0x00, 0x00, 0x21, 0x65, 0x7b, 0x99, 0x09,
+		0x02, 0xc3, 0x9d, 0x54, 0xd6, 0xe7, 0x32, 0x62,
+		0xab, 0xc1, 0x09, 0x91, 0x30, 0x0a, 0xc9, 0xfa,
+		0x70, 0xec, 0x06, 0x7b, 0xa3, 0xe1, 0x5f, 0xb4,
+		0x63, 0xe6, 0x5c, 0xba, 0x1f, 0x15, 0x03, 0x00,
+		0x00, 0x16, 0x40, 0x70, 0xbe, 0xe6, 0xa6, 0xee,
+		0x8f, 0xd0, 0x87, 0xa0, 0x43, 0xa1, 0x92, 0xd7,
+		0xd0, 0x1a, 0x0c, 0x20, 0x7c, 0xbf, 0xa2, 0xb5,
 	},
 }
 
 var selectCertificateBySNIScript = [][]byte{
 	{
-		0x16, 0x03, 0x01, 0x00, 0x6e, 0x01, 0x00, 0x00,
-		0x6a, 0x03, 0x01, 0x4f, 0x85, 0xc4, 0xc2, 0xb9,
-		0x39, 0x80, 0x91, 0x66, 0x65, 0x56, 0x8e, 0xdd,
-		0x48, 0xe9, 0xca, 0x34, 0x02, 0x3c, 0xaf, 0x0d,
-		0x73, 0xb5, 0x2a, 0x05, 0x6e, 0xbd, 0x5e, 0x8f,
-		0x38, 0xf9, 0xe5, 0x00, 0x00, 0x28, 0x00, 0x39,
+		0x16, 0x03, 0x01, 0x00, 0x6a, 0x01, 0x00, 0x00,
+		0x66, 0x03, 0x01, 0x50, 0x77, 0x3d, 0xfe, 0xfb,
+		0x8d, 0xc2, 0x68, 0xeb, 0xf9, 0xfa, 0x54, 0x97,
+		0x86, 0x45, 0xa2, 0xa3, 0xed, 0xb1, 0x91, 0xb8,
+		0x28, 0xc0, 0x47, 0xaf, 0xfb, 0xcd, 0xdc, 0x0e,
+		0xb3, 0xea, 0xa5, 0x00, 0x00, 0x28, 0x00, 0x39,
 		0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
 		0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
 		0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
 		0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
 		0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
-		0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00,
+		0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00,
 		0x0e, 0x00, 0x00, 0x0b, 0x73, 0x6e, 0x69, 0x74,
-		0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x00,
-		0x23, 0x00, 0x00,
+		0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d,
 	},
 	{
 		0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
@@ -1053,632 +1282,684 @@ var selectCertificateBySNIScript = [][]byte{
 	},
 	{
 		0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
-		0x82, 0x00, 0x80, 0x70, 0x1d, 0x34, 0x75, 0xa2,
-		0xe7, 0xe3, 0x2f, 0x3d, 0xc1, 0x1d, 0xca, 0x0b,
-		0xe3, 0x64, 0xb9, 0x1a, 0x00, 0x69, 0xc4, 0x14,
-		0x05, 0x07, 0x7e, 0xc3, 0x51, 0x43, 0x52, 0x66,
-		0xe3, 0xbd, 0xff, 0x1b, 0x1a, 0x6a, 0x84, 0xf2,
-		0x07, 0x24, 0xd7, 0x12, 0xa8, 0x58, 0xcf, 0x8a,
-		0x50, 0x30, 0xe8, 0xc8, 0xb2, 0xf9, 0x58, 0x1c,
-		0x56, 0x53, 0x76, 0x21, 0xe0, 0x03, 0x7f, 0x77,
-		0xa7, 0xf1, 0xad, 0x67, 0xd4, 0xe2, 0x8f, 0xa0,
-		0x58, 0x6c, 0xe0, 0x28, 0x59, 0xf3, 0xd1, 0x53,
-		0x2b, 0x21, 0xbd, 0xa3, 0x84, 0x31, 0x73, 0xbf,
-		0x84, 0x0f, 0x83, 0xf4, 0xc4, 0xd0, 0xe5, 0x3c,
-		0x2d, 0x3e, 0xf2, 0x8a, 0x1e, 0xe7, 0xe9, 0x1f,
-		0x12, 0x13, 0xad, 0x29, 0xd6, 0x0c, 0xc7, 0xc6,
-		0x05, 0x53, 0x7d, 0x5e, 0xc6, 0x92, 0x72, 0xba,
-		0xd2, 0x93, 0x8f, 0x53, 0x84, 0x87, 0x44, 0x05,
-		0x9f, 0x5d, 0x66, 0x14, 0x03, 0x01, 0x00, 0x01,
-		0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xfc, 0x71,
-		0xaa, 0xa8, 0x37, 0xa8, 0xbd, 0x63, 0xb7, 0xbc,
-		0x95, 0xef, 0x0c, 0xcf, 0x39, 0x31, 0x93, 0xe6,
-		0x86, 0xbd, 0x3f, 0x56, 0x9d, 0xf0, 0xb2, 0xb5,
-		0xd1, 0xa7, 0xc6, 0x45, 0x89, 0x18, 0xfb, 0xa0,
-		0x7f, 0xc1,
+		0x82, 0x00, 0x80, 0x69, 0xc3, 0xd4, 0x0e, 0xcc,
+		0xdc, 0xbc, 0x5e, 0xc2, 0x64, 0xa6, 0xde, 0x3c,
+		0x0c, 0x7e, 0x0c, 0x6b, 0x80, 0x0f, 0xd4, 0x8f,
+		0x02, 0x4b, 0xb2, 0xba, 0x8d, 0x01, 0xeb, 0x6b,
+		0xa1, 0x2e, 0x79, 0x37, 0xba, 0xae, 0x24, 0xc2,
+		0x26, 0x72, 0x51, 0xe1, 0x82, 0x8e, 0x51, 0x41,
+		0x1c, 0x54, 0xa4, 0x26, 0xbe, 0x13, 0xcd, 0x1b,
+		0xc6, 0xed, 0x3d, 0x1f, 0xfd, 0x72, 0x80, 0x90,
+		0xdb, 0xbf, 0xd6, 0x39, 0x94, 0x5f, 0x48, 0xfb,
+		0x25, 0x5a, 0xc9, 0x60, 0x9b, 0xd7, 0xc6, 0x20,
+		0xa8, 0x66, 0x64, 0x13, 0xf3, 0x65, 0xc8, 0xb1,
+		0xd5, 0x33, 0x21, 0x0e, 0x73, 0x41, 0xc0, 0x18,
+		0x1a, 0x37, 0xfe, 0xcf, 0x28, 0x2a, 0xcd, 0xe4,
+		0x0b, 0xac, 0xdd, 0x25, 0x5e, 0xcb, 0x17, 0x51,
+		0x69, 0xd5, 0x8c, 0xf4, 0xb6, 0x21, 0x98, 0xef,
+		0x20, 0xdb, 0x14, 0x67, 0xf3, 0x7c, 0x95, 0x6a,
+		0x48, 0x2a, 0x6a, 0x14, 0x03, 0x01, 0x00, 0x01,
+		0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0x36, 0x1b,
+		0x09, 0xe5, 0xb9, 0xb9, 0x4d, 0x7d, 0xae, 0x87,
+		0xb6, 0x0f, 0xaf, 0xec, 0x22, 0xba, 0x0d, 0xa5,
+		0x96, 0x5e, 0x64, 0x65, 0xe7, 0xfb, 0xe3, 0xf3,
+		0x6b, 0x72, 0xa8, 0xdb, 0xed, 0xd8, 0x69, 0x9c,
+		0x08, 0xd8,
 	},
 	{
 		0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
-		0x01, 0x00, 0x24, 0xb8, 0x6d, 0x9a, 0x90, 0x3c,
-		0x45, 0xe0, 0xff, 0x63, 0xba, 0xab, 0x3d, 0x7a,
-		0xa6, 0x49, 0x5a, 0x13, 0xdc, 0x0e, 0xa3, 0xba,
-		0x7f, 0x04, 0x19, 0x45, 0xfd, 0xfb, 0xbd, 0x00,
-		0xa3, 0xa7, 0x78, 0x81, 0x38, 0x9f, 0x10, 0x17,
-		0x03, 0x01, 0x00, 0x21, 0x43, 0xc3, 0x91, 0xb7,
-		0xbf, 0x50, 0x0b, 0x04, 0xb4, 0x5d, 0xc6, 0x20,
-		0x64, 0xb8, 0x01, 0x09, 0x25, 0x2c, 0x03, 0x30,
-		0xc0, 0x77, 0xc9, 0x5e, 0xe6, 0xe0, 0x99, 0xdc,
-		0xcd, 0x75, 0x9d, 0x51, 0x82, 0x15, 0x03, 0x01,
-		0x00, 0x16, 0x2d, 0x7a, 0x89, 0x7b, 0x36, 0x85,
-		0x2a, 0x93, 0xcb, 0x83, 0xa7, 0x2f, 0x9e, 0x91,
-		0xfc, 0xad, 0x57, 0xca, 0xf5, 0xbc, 0x13, 0x2f,
+		0x01, 0x00, 0x24, 0x60, 0xf7, 0x09, 0x5f, 0xd1,
+		0xcb, 0xc9, 0xe1, 0x22, 0xb5, 0x2a, 0xcc, 0xde,
+		0x7c, 0xa7, 0xb8, 0x85, 0x00, 0xbc, 0xfd, 0x85,
+		0xe1, 0x91, 0x36, 0xbb, 0x07, 0x42, 0xad, 0x3d,
+		0x29, 0x62, 0x69, 0xc1, 0x45, 0x92, 0x6f, 0x17,
+		0x03, 0x01, 0x00, 0x21, 0x0d, 0xf9, 0xd5, 0x87,
+		0xb9, 0x57, 0x3c, 0x50, 0x19, 0xe4, 0x3a, 0x50,
+		0x45, 0xcc, 0x86, 0x89, 0xd4, 0x32, 0x79, 0x45,
+		0x7c, 0x9f, 0x96, 0xd4, 0x54, 0x56, 0x0c, 0x63,
+		0x72, 0x81, 0xc3, 0xd3, 0xe3, 0x15, 0x03, 0x01,
+		0x00, 0x16, 0x84, 0xec, 0x2e, 0xf6, 0xaf, 0x4f,
+		0xee, 0x48, 0x0f, 0xbe, 0xcd, 0x82, 0x5c, 0x56,
+		0x16, 0xe4, 0xfb, 0x89, 0xc5, 0x57, 0x3e, 0x91,
 	},
 }
 
-var clientauthTests = []clientauthTest{
-	// Server doesn't asks for cert
-	// go test -run "TestRunServer" -serve -clientauth 0
-	// gnutls-cli --insecure --debug 100 -p 10443 localhost 2>&1 |
-	//   python parse-gnutls-cli-debug-log.py
-	{"NoClientCert", NoClientCert, nil,
-		[][]byte{{
-			0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
-			0x76, 0x03, 0x02, 0x4e, 0xe0, 0x92, 0x5d, 0xcd,
-			0xfe, 0x0c, 0x69, 0xd4, 0x7d, 0x8e, 0xa6, 0x88,
-			0xde, 0x72, 0x04, 0x29, 0x6a, 0x4a, 0x16, 0x23,
-			0xd7, 0x8f, 0xbc, 0xfa, 0x80, 0x73, 0x2e, 0x12,
-			0xb7, 0x0b, 0x39, 0x00, 0x00, 0x34, 0x00, 0x33,
-			0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
-			0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
-			0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
-			0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
-			0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
-			0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
-			0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
-			0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
-			0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
-			0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
-		},
+var issueSessionTicketTest = [][]byte{
+	{
+		0x16, 0x03, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x00,
+		0x56, 0x03, 0x01, 0x50, 0x77, 0x3e, 0x49, 0x7a,
+		0xb7, 0x86, 0x5c, 0x27, 0xd2, 0x97, 0x61, 0xe3,
+		0x49, 0x41, 0x48, 0xe7, 0x0e, 0xaa, 0x7e, 0x4d,
+		0xb8, 0xdc, 0x01, 0x97, 0xfb, 0xab, 0x53, 0xb2,
+		0x5e, 0x36, 0xf6, 0x00, 0x00, 0x28, 0x00, 0x39,
+		0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+		0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+		0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+		0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+		0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+		0x00, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00,
+	},
+	{
+		0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+		0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+		0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+		0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+		0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+		0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+		0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+		0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+		0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+		0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+		0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+		0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+		0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+		0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+		0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+		0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+		0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+		0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+		0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+		0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+		0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+		0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+		0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+		0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+		0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+		0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+		0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+		0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+		0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+		0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+		0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+		0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+		0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+		0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+		0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+		0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+		0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+		0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+		0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+		0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+		0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+		0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+		0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+		0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+		0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+		0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+		0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+		0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+		0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+		0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+		0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+		0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+		0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+		0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+		0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+		0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+		0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+		0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+		0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+		0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+		0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
+		0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+		0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+		0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+		0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+		0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+		0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+		0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+		0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+		0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+		0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+		0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+		0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+		0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+		0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+		0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+		0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+		0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+		0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+		0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+		0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+		0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+		0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+		0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+		0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+		0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+		0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+		0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+		0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+		0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+		0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+		0x16, 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00,
+		0x00,
+	},
+	{
+		0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+		0x82, 0x00, 0x80, 0x68, 0x10, 0xdc, 0x80, 0xbc,
+		0xb3, 0x5a, 0x10, 0x75, 0x89, 0xcc, 0xe5, 0x9f,
+		0xbf, 0xe2, 0xce, 0xa4, 0x9f, 0x7f, 0x60, 0xc4,
+		0xfe, 0x5c, 0xb5, 0x02, 0x2d, 0xa5, 0xa9, 0x1e,
+		0x2c, 0x10, 0x79, 0x15, 0x0f, 0xed, 0x96, 0xb3,
+		0xa8, 0x5e, 0x21, 0xbc, 0x5b, 0xdc, 0x58, 0x04,
+		0x7d, 0x37, 0xdb, 0xa0, 0x31, 0xe8, 0x4f, 0x04,
+		0xbc, 0x46, 0x7c, 0xdb, 0x2e, 0x93, 0x07, 0xaf,
+		0xa6, 0x36, 0xd3, 0x39, 0x8d, 0x1d, 0x95, 0xa8,
+		0x50, 0x4b, 0xc4, 0x2b, 0xde, 0xd7, 0x04, 0x6d,
+		0x77, 0x6c, 0x4d, 0x70, 0x51, 0x88, 0x16, 0x31,
+		0x40, 0xb5, 0xba, 0x90, 0x47, 0x64, 0x0c, 0x87,
+		0xa5, 0x19, 0xf9, 0x89, 0x24, 0x3c, 0x5e, 0x4b,
+		0xaa, 0xe0, 0x60, 0x47, 0x0f, 0x2e, 0xcc, 0xc2,
+		0xd5, 0x21, 0xed, 0x72, 0xd0, 0xa9, 0xdd, 0x2a,
+		0x2b, 0xef, 0x08, 0x3a, 0x65, 0xea, 0x8b, 0x52,
+		0x77, 0x2d, 0xcc, 0x14, 0x03, 0x01, 0x00, 0x01,
+		0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xe2, 0x95,
+		0x62, 0x3c, 0x18, 0xe5, 0xc7, 0x2c, 0xda, 0x16,
+		0x9b, 0x28, 0x0d, 0xf7, 0x88, 0x7b, 0x5d, 0x33,
+		0x55, 0x3b, 0x01, 0x73, 0xf2, 0xc6, 0x4e, 0x96,
+		0x01, 0x01, 0x83, 0x65, 0xd4, 0xef, 0x12, 0x13,
+		0x1d, 0x42,
+	},
+	{
+		0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00,
+		0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+		0xe8, 0x4b, 0xd1, 0xef, 0xba, 0xfb, 0x41, 0x92,
+		0x6d, 0x37, 0x5f, 0xf8, 0x7d, 0x90, 0x0f, 0x01,
+		0xf8, 0x8c, 0xee, 0xbc, 0xd9, 0x0c, 0x97, 0x7e,
+		0x23, 0x46, 0xe2, 0x6b, 0x52, 0xc6, 0xc6, 0x97,
+		0x1d, 0xab, 0xde, 0xa0, 0x86, 0x94, 0xc8, 0x2e,
+		0x8b, 0x2e, 0x42, 0x5f, 0xc2, 0x70, 0x35, 0xc9,
+		0xee, 0x37, 0xeb, 0x70, 0xaa, 0x59, 0x23, 0x6c,
+		0xc8, 0xc1, 0x84, 0x89, 0x39, 0x87, 0x73, 0x0a,
+		0x7e, 0xba, 0xca, 0xed, 0x63, 0xba, 0x4e, 0x4f,
+		0xf3, 0x31, 0x4b, 0xf0, 0xee, 0x91, 0xa5, 0xb4,
+		0x62, 0x01, 0x9e, 0xbd, 0xbc, 0xb3, 0x35, 0x14,
+		0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+		0x00, 0x24, 0x3f, 0x66, 0xe4, 0x98, 0xc1, 0x3f,
+		0xc6, 0x2c, 0x81, 0xfb, 0xa9, 0x9f, 0x27, 0xe9,
+		0x63, 0x20, 0x1e, 0x0e, 0x4f, 0xfc, 0x5d, 0x12,
+		0xee, 0x77, 0x73, 0xc6, 0x96, 0x51, 0xf2, 0x26,
+		0x35, 0x3f, 0xce, 0x6a, 0xa9, 0xfd, 0x17, 0x03,
+		0x01, 0x00, 0x21, 0x8d, 0xd5, 0x67, 0x60, 0x5d,
+		0xa7, 0x93, 0xcc, 0x39, 0x78, 0x59, 0xab, 0xdb,
+		0x10, 0x96, 0xf2, 0xad, 0xa2, 0x85, 0xe2, 0x93,
+		0x43, 0x43, 0xcf, 0x82, 0xbd, 0x1f, 0xdc, 0x7a,
+		0x72, 0xd6, 0x83, 0x3b, 0x15, 0x03, 0x01, 0x00,
+		0x16, 0x89, 0x55, 0xf6, 0x42, 0x71, 0xa9, 0xe9,
+		0x05, 0x68, 0xe8, 0xce, 0x0d, 0x21, 0xe9, 0xec,
+		0xf2, 0x27, 0x67, 0xa7, 0x94, 0xf8, 0x34,
+	},
+}
+var serverResumeTest = [][]byte{
+	{
+		0x16, 0x03, 0x01, 0x00, 0xc2, 0x01, 0x00, 0x00,
+		0xbe, 0x03, 0x01, 0x50, 0x77, 0x3e, 0x4f, 0x1f,
+		0x6f, 0xa5, 0x81, 0xeb, 0xb8, 0x80, 0x55, 0xa4,
+		0x76, 0xc2, 0x7f, 0x27, 0xf2, 0xe7, 0xc9, 0x7a,
+		0x01, 0x3c, 0xd8, 0xc1, 0xde, 0x99, 0x1f, 0x7c,
+		0xab, 0x35, 0x98, 0x00, 0x00, 0x28, 0x00, 0x39,
+		0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+		0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+		0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+		0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+		0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+		0x00, 0x00, 0x6c, 0x00, 0x23, 0x00, 0x68, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+		0xe8, 0x4b, 0xd1, 0xef, 0xba, 0xfb, 0x41, 0x92,
+		0x6d, 0x37, 0x5f, 0xf8, 0x7d, 0x90, 0x0f, 0x01,
+		0xf8, 0x8c, 0xee, 0xbc, 0xd9, 0x0c, 0x97, 0x7e,
+		0x23, 0x46, 0xe2, 0x6b, 0x52, 0xc6, 0xc6, 0x97,
+		0x1d, 0xab, 0xde, 0xa0, 0x86, 0x94, 0xc8, 0x2e,
+		0x8b, 0x2e, 0x42, 0x5f, 0xc2, 0x70, 0x35, 0xc9,
+		0xee, 0x37, 0xeb, 0x70, 0xaa, 0x59, 0x23, 0x6c,
+		0xc8, 0xc1, 0x84, 0x89, 0x39, 0x87, 0x73, 0x0a,
+		0x7e, 0xba, 0xca, 0xed, 0x63, 0xba, 0x4e, 0x4f,
+		0xf3, 0x31, 0x4b, 0xf0, 0xee, 0x91, 0xa5, 0xb4,
+		0x62, 0x01, 0x9e, 0xbd, 0xbc, 0xb3, 0x35,
+	},
+	{
+		0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+		0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x14,
+		0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+		0x00, 0x24, 0xc5, 0x35, 0x74, 0x19, 0x05, 0xc5,
+		0x85, 0x68, 0x48, 0xe8, 0xb5, 0xe9, 0xaf, 0x78,
+		0xbd, 0x35, 0x6f, 0xe9, 0x79, 0x34, 0x1b, 0xf0,
+		0x35, 0xd4, 0x4e, 0x55, 0x2e, 0x3c, 0xd5, 0xaf,
+		0xfc, 0xba, 0xf5, 0x1e, 0x83, 0x32,
+	},
+	{
+		0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+		0x01, 0x00, 0x24, 0x27, 0x28, 0x88, 0xe1, 0x7e,
+		0x0d, 0x9c, 0x12, 0x50, 0xf6, 0x7a, 0xa7, 0x32,
+		0x21, 0x68, 0xba, 0xd8, 0x0a, 0xdc, 0x39, 0xef,
+		0x68, 0x95, 0x82, 0xae, 0xbd, 0x12, 0x79, 0xa1,
+		0x99, 0xfd, 0xd0, 0x10, 0x8e, 0x4b, 0xd8,
+	},
+	{
+		0x17, 0x03, 0x01, 0x00, 0x21, 0xc5, 0x7e, 0x0a,
+		0x52, 0x6a, 0xb9, 0xaa, 0x1d, 0xae, 0x9e, 0x24,
+		0x9c, 0x34, 0x1e, 0xdb, 0x50, 0x95, 0xee, 0x76,
+		0xd7, 0x28, 0x88, 0x08, 0xe3, 0x2e, 0x58, 0xf7,
+		0xdb, 0x34, 0x75, 0xa5, 0x7f, 0x9d, 0x15, 0x03,
+		0x01, 0x00, 0x16, 0x2c, 0xc1, 0x29, 0x5f, 0x12,
+		0x1d, 0x19, 0xab, 0xb3, 0xf4, 0x35, 0x1c, 0x62,
+		0x6a, 0x80, 0x29, 0x0d, 0x0e, 0xef, 0x7d, 0x6e,
+		0x50,
+	},
+}
 
-			{
-				0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
-				0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
-				0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
-				0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
-				0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
-				0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
-				0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
-				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-				0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
-				0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
-				0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
-				0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
-				0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
-				0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
-				0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
-				0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
-				0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
-				0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
-				0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
-				0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
-				0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
-				0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
-				0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
-				0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
-				0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
-				0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
-				0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
-				0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
-				0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
-				0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
-				0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
-				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-				0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
-				0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
-				0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
-				0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
-				0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
-				0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
-				0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
-				0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
-				0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
-				0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
-				0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
-				0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
-				0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
-				0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
-				0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
-				0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
-				0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
-				0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
-				0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
-				0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
-				0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
-				0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
-				0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
-				0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
-				0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
-				0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
-				0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
-				0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
-				0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
-				0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
-				0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
-				0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
-				0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
-				0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
-				0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
-				0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
-				0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
-				0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
-				0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
-				0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
-				0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-				0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
-				0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
-				0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
-				0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
-				0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
-				0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
-				0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
-				0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
-				0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
-				0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
-				0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
-				0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
-				0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
-				0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
-				0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
-				0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
-				0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
-				0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
-				0x00, 0x00, 0x00,
-			},
-
-			{
-				0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
-				0x82, 0x00, 0x80, 0x10, 0xe1, 0x00, 0x3d, 0x0a,
-				0x6b, 0x02, 0x7f, 0x97, 0xde, 0xfb, 0x65, 0x46,
-				0x1a, 0x50, 0x4e, 0x34, 0x9a, 0xae, 0x14, 0x7e,
-				0xec, 0xef, 0x85, 0x15, 0x3b, 0x39, 0xc2, 0x45,
-				0x04, 0x40, 0x92, 0x71, 0xd6, 0x7e, 0xf6, 0xfd,
-				0x4d, 0x84, 0xf7, 0xc4, 0x77, 0x99, 0x3d, 0xe2,
-				0xc3, 0x8d, 0xb0, 0x4c, 0x74, 0xc8, 0x51, 0xec,
-				0xb2, 0xe8, 0x6b, 0xa1, 0xd2, 0x4d, 0xd8, 0x61,
-				0x92, 0x7a, 0x24, 0x57, 0x44, 0x4f, 0xa2, 0x1e,
-				0x74, 0x0b, 0x06, 0x4b, 0x80, 0x34, 0x8b, 0xfe,
-				0xc2, 0x0e, 0xc1, 0xcd, 0xab, 0x0c, 0x3f, 0x54,
-				0xe2, 0x44, 0xe9, 0x6c, 0x2b, 0xba, 0x7b, 0x64,
-				0xf1, 0x93, 0x65, 0x75, 0xf2, 0x35, 0xff, 0x27,
-				0x03, 0xd5, 0x64, 0xe6, 0x8e, 0xe7, 0x7b, 0x56,
-				0xb6, 0x61, 0x73, 0xeb, 0xa2, 0xdc, 0xa4, 0x6e,
-				0x52, 0xac, 0xbc, 0xba, 0x11, 0xa3, 0xd2, 0x61,
-				0x4a, 0xe0, 0xbb, 0x14, 0x03, 0x01, 0x00, 0x01,
-				0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xd2, 0x5a,
-				0x0c, 0x2a, 0x27, 0x96, 0xba, 0xa9, 0x67, 0xd2,
-				0x51, 0x68, 0x32, 0x68, 0x22, 0x1f, 0xb9, 0x27,
-				0x79, 0x59, 0x28, 0xdf, 0x38, 0x1f, 0x92, 0x21,
-				0x5d, 0x0f, 0xf4, 0xc0, 0xee, 0xb7, 0x10, 0x5a,
-				0xa9, 0x45,
-			},
-
-			{
-				0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
-				0x01, 0x00, 0x24, 0x13, 0x6f, 0x6c, 0x71, 0x83,
-				0x59, 0xcf, 0x32, 0x72, 0xe9, 0xce, 0xcc, 0x7a,
-				0x6c, 0xf0, 0x72, 0x39, 0x16, 0xae, 0x40, 0x61,
-				0xfa, 0x92, 0x4c, 0xe7, 0xf2, 0x1a, 0xd7, 0x0c,
-				0x84, 0x76, 0x6c, 0xe9, 0x11, 0x43, 0x19, 0x17,
-				0x03, 0x01, 0x00, 0x21, 0xc0, 0xa2, 0x13, 0x28,
-				0x94, 0x8c, 0x5c, 0xd6, 0x79, 0xb9, 0xfe, 0xae,
-				0x45, 0x4b, 0xc0, 0x7c, 0xae, 0x2d, 0xb4, 0x0d,
-				0x31, 0xc4, 0xad, 0x22, 0xd7, 0x1e, 0x99, 0x1c,
-				0x4c, 0x69, 0xab, 0x42, 0x61, 0x15, 0x03, 0x01,
-				0x00, 0x16, 0xe1, 0x0c, 0x67, 0xf3, 0xf4, 0xb9,
-				0x8e, 0x81, 0x8e, 0x01, 0xb8, 0xa0, 0x69, 0x8c,
-				0x03, 0x11, 0x43, 0x3e, 0xee, 0xb7, 0x4d, 0x69,
-			}}},
+var clientauthTests = []clientauthTest{
 	// Server asks for cert with empty CA list, client doesn't give it.
 	// go test -run "TestRunServer" -serve -clientauth 1
-	// gnutls-cli --insecure --debug 100 -p 10443 localhost
-	{"RequestClientCert, none given", RequestClientCert, nil,
-		[][]byte{{
-			0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
-			0x76, 0x03, 0x02, 0x4e, 0xe0, 0x93, 0xe2, 0x47,
-			0x06, 0xa0, 0x61, 0x0c, 0x51, 0xdd, 0xf0, 0xef,
-			0xf4, 0x30, 0x72, 0xe1, 0xa6, 0x50, 0x68, 0x82,
-			0x3c, 0xfb, 0xcb, 0x72, 0x5e, 0x73, 0x9d, 0xda,
-			0x27, 0x35, 0x72, 0x00, 0x00, 0x34, 0x00, 0x33,
-			0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
-			0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
-			0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
-			0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
-			0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
-			0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
-			0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
-			0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
-			0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
-			0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+	{"RequestClientCert, none given", RequestClientCert, nil, [][]byte{
+		{
+			0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
+			0x50, 0x03, 0x01, 0x50, 0x77, 0x43, 0x9e, 0x31,
+			0xe6, 0x36, 0x5e, 0x5e, 0x24, 0xe4, 0x0d, 0x26,
+			0x34, 0xa7, 0x1c, 0x2e, 0x59, 0x6d, 0xa5, 0x3e,
+			0x72, 0xf3, 0xa3, 0x1c, 0xbc, 0xb3, 0x27, 0xaf,
+			0x92, 0x5b, 0x7d, 0x00, 0x00, 0x28, 0x00, 0x39,
+			0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+			0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+			0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+			0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+			0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+			0x00,
 		},
-
-			{
-				0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
-				0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
-				0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
-				0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
-				0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
-				0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
-				0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
-				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-				0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
-				0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
-				0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
-				0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
-				0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
-				0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
-				0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
-				0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
-				0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
-				0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
-				0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
-				0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
-				0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
-				0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
-				0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
-				0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
-				0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
-				0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
-				0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
-				0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
-				0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
-				0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
-				0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
-				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-				0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
-				0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
-				0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
-				0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
-				0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
-				0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
-				0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
-				0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
-				0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
-				0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
-				0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
-				0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
-				0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
-				0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
-				0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
-				0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
-				0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
-				0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
-				0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
-				0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
-				0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
-				0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
-				0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
-				0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
-				0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
-				0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
-				0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
-				0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
-				0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
-				0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
-				0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
-				0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
-				0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
-				0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
-				0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
-				0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
-				0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
-				0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
-				0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
-				0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
-				0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-				0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
-				0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
-				0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
-				0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
-				0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
-				0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
-				0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
-				0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
-				0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
-				0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
-				0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
-				0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
-				0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
-				0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
-				0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
-				0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
-				0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
-				0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
-				0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
-				0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
-			},
-
-			{
-				0x16, 0x03, 0x01, 0x00, 0x07, 0x0b, 0x00, 0x00,
-				0x03, 0x00, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00,
-				0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x64,
-				0x28, 0xb9, 0x3f, 0x48, 0xaf, 0x06, 0x22, 0x39,
-				0x56, 0xd8, 0x6f, 0x63, 0x5d, 0x03, 0x48, 0x63,
-				0x01, 0x13, 0xa2, 0xd6, 0x76, 0xc0, 0xab, 0xda,
-				0x25, 0x30, 0x75, 0x6c, 0xaa, 0xb4, 0xdc, 0x35,
-				0x72, 0xdc, 0xf2, 0x43, 0xe4, 0x1d, 0x82, 0xfb,
-				0x6c, 0x64, 0xe2, 0xa7, 0x8f, 0x32, 0x67, 0x6b,
-				0xcd, 0xd2, 0xb2, 0x36, 0x94, 0xbc, 0x6f, 0x46,
-				0x79, 0x29, 0x42, 0xe3, 0x1a, 0xbf, 0xfb, 0x41,
-				0xd5, 0xe3, 0xb4, 0x2a, 0xf6, 0x95, 0x6f, 0x0c,
-				0x87, 0xb9, 0x03, 0x18, 0xa1, 0xea, 0x4a, 0xe2,
-				0x2e, 0x0f, 0x50, 0x00, 0xc1, 0xe8, 0x8c, 0xc8,
-				0xa2, 0xf6, 0xa4, 0x05, 0xf4, 0x38, 0x3e, 0xd9,
-				0x6e, 0x63, 0x96, 0x0c, 0x34, 0x73, 0x90, 0x03,
-				0x55, 0xa6, 0x34, 0xb0, 0x5e, 0x8c, 0x48, 0x40,
-				0x25, 0x45, 0x84, 0xa6, 0x21, 0x3f, 0x81, 0x97,
-				0xa7, 0x11, 0x09, 0x14, 0x95, 0xa5, 0xe5, 0x14,
-				0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
-				0x00, 0x24, 0x16, 0xaa, 0x01, 0x2c, 0xa8, 0xc1,
-				0x28, 0xaf, 0x35, 0xc1, 0xc1, 0xf3, 0x0a, 0x25,
-				0x66, 0x6e, 0x27, 0x11, 0xa3, 0xa4, 0xd9, 0xe9,
-				0xea, 0x15, 0x09, 0x9d, 0x28, 0xe3, 0x5b, 0x2b,
-				0xa6, 0x25, 0xa7, 0x14, 0x24, 0x3a,
-			},
-
-			{
-				0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
-				0x01, 0x00, 0x24, 0x9a, 0xa8, 0xd6, 0x77, 0x46,
-				0x45, 0x68, 0x9d, 0x5d, 0xa9, 0x68, 0x03, 0xe5,
-				0xaf, 0xe8, 0xc8, 0x21, 0xc5, 0xc6, 0xc1, 0x50,
-				0xe0, 0xd8, 0x52, 0xce, 0xa3, 0x4f, 0x2d, 0xf4,
-				0xe3, 0xa7, 0x7d, 0x35, 0x80, 0x84, 0x12, 0x17,
-				0x03, 0x01, 0x00, 0x21, 0x8a, 0x82, 0x0c, 0x54,
-				0x1b, 0xeb, 0x77, 0x90, 0x2c, 0x3e, 0xbc, 0xf0,
-				0x23, 0xcc, 0xa8, 0x9f, 0x25, 0x08, 0x12, 0xed,
-				0x43, 0xf1, 0xf9, 0x06, 0xad, 0xa9, 0x4b, 0x97,
-				0x82, 0xb7, 0xc4, 0x0b, 0x4c, 0x15, 0x03, 0x01,
-				0x00, 0x16, 0x05, 0x2d, 0x9d, 0x45, 0x03, 0xb7,
-				0xc2, 0xd1, 0xb5, 0x1a, 0x43, 0xcf, 0x1a, 0x37,
-				0xf4, 0x70, 0xcc, 0xb4, 0xed, 0x07, 0x76, 0x3a,
-			}}},
+		{
+			0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+			0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+			0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+			0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+			0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+			0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+			0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+			0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+			0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+			0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+			0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+			0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+			0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+			0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+			0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+			0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+			0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+			0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+			0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+			0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+			0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+			0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+			0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+			0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+			0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+			0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+			0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+			0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+			0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+			0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+			0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+			0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+			0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+			0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+			0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+			0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+			0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+			0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+			0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+			0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+			0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+			0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+			0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+			0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+			0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+			0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+			0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+			0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+			0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+			0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+			0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+			0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+			0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+			0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+			0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+			0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+			0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+			0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+			0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+			0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+			0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+			0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+			0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+			0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+			0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+			0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+			0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+			0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+			0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+			0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+			0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+			0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+			0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+			0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+			0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+			0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+			0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+			0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+			0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+			0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+			0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+			0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+			0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+			0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+			0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+			0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+			0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+			0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+			0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+			0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
+			0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
+			0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+		},
+		{
+			0x16, 0x03, 0x01, 0x00, 0x07, 0x0b, 0x00, 0x00,
+			0x03, 0x00, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00,
+			0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x04,
+			0x58, 0x63, 0x26, 0x32, 0x1b, 0x34, 0xbe, 0x10,
+			0xe4, 0xe4, 0x3e, 0xcd, 0x36, 0x7f, 0xa8, 0xa8,
+			0xe0, 0x19, 0xe8, 0x94, 0x13, 0xd9, 0x35, 0xc4,
+			0x71, 0xb4, 0x91, 0xd4, 0xbc, 0x74, 0x57, 0x9f,
+			0x93, 0xb7, 0x5d, 0x3b, 0x9c, 0xff, 0x5d, 0x79,
+			0xdb, 0x86, 0xfc, 0xdc, 0x74, 0x1e, 0x0c, 0xc6,
+			0xe8, 0x93, 0xcf, 0xaf, 0xba, 0x1d, 0xfd, 0x8a,
+			0xeb, 0xef, 0xbf, 0xfa, 0xa6, 0xe7, 0x53, 0x98,
+			0x60, 0x4e, 0x0e, 0x60, 0x7d, 0xea, 0x40, 0x8d,
+			0x1d, 0x8f, 0xa3, 0xc6, 0x83, 0xbc, 0xef, 0xb7,
+			0x9a, 0x4a, 0xe7, 0x99, 0xee, 0x0b, 0xc7, 0x46,
+			0x75, 0x45, 0x66, 0xe8, 0x5f, 0x4b, 0x08, 0xa4,
+			0xc1, 0x36, 0xd0, 0x36, 0x2c, 0xf2, 0x9a, 0x44,
+			0x1e, 0x5f, 0x22, 0xf4, 0xbe, 0x66, 0x66, 0x17,
+			0xd8, 0xb6, 0x0a, 0x89, 0xed, 0x22, 0x80, 0xdb,
+			0xad, 0x05, 0xd1, 0xb5, 0x93, 0xa1, 0x1c, 0x14,
+			0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+			0x00, 0x24, 0x62, 0x6f, 0x3d, 0x30, 0x56, 0x97,
+			0xde, 0x03, 0x67, 0xa9, 0x63, 0x21, 0xb6, 0xe6,
+			0x05, 0x69, 0x94, 0xfb, 0x50, 0xc1, 0x99, 0xdd,
+			0xf6, 0xe8, 0x60, 0xbd, 0xe6, 0xba, 0xe3, 0x50,
+			0x0a, 0xcd, 0xde, 0x14, 0x16, 0xc4,
+		},
+		{
+			0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+			0x01, 0x00, 0x24, 0xf0, 0x21, 0xf6, 0x84, 0x6a,
+			0xe3, 0x6b, 0x8a, 0xc5, 0x46, 0x50, 0xca, 0x40,
+			0xea, 0x4e, 0x82, 0xc1, 0x70, 0x25, 0xd8, 0x7d,
+			0x60, 0xf5, 0x51, 0x7f, 0x64, 0x03, 0x9f, 0x53,
+			0xec, 0xfb, 0x57, 0xa9, 0xfc, 0x26, 0x15, 0x17,
+			0x03, 0x01, 0x00, 0x21, 0xa6, 0xc6, 0x94, 0x2b,
+			0xa9, 0xcb, 0x93, 0xff, 0xb6, 0xa6, 0xe7, 0xc5,
+			0x37, 0x86, 0x15, 0x37, 0x57, 0xce, 0xef, 0x54,
+			0x96, 0x5d, 0x50, 0xa0, 0x50, 0x69, 0x5e, 0x82,
+			0x61, 0x8d, 0x42, 0xfb, 0x78, 0x15, 0x03, 0x01,
+			0x00, 0x16, 0x45, 0xd1, 0x86, 0x68, 0x59, 0xc1,
+			0xaf, 0xac, 0x5c, 0x46, 0x8a, 0x68, 0x69, 0x0c,
+			0xd7, 0x67, 0xbf, 0xf0, 0x3e, 0xee, 0x45, 0x55,
+		},
+	}},
 	// Server asks for cert with empty CA list, client gives one
 	// go test -run "TestRunServer" -serve -clientauth 1
-	// gnutls-cli --insecure --debug 100 -p 10443 localhost
-	{"RequestClientCert, client gives it", RequestClientCert,
-		[]*x509.Certificate{clientCertificate},
-		[][]byte{{
-			0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
-			0x76, 0x03, 0x02, 0x4e, 0xe7, 0x44, 0xda, 0x58,
-			0x7d, 0x46, 0x4a, 0x48, 0x97, 0x9f, 0xe5, 0x91,
-			0x11, 0x64, 0xa7, 0x1e, 0x4d, 0xb7, 0xfe, 0x9b,
-			0xc6, 0x63, 0xf8, 0xa4, 0xb5, 0x0b, 0x18, 0xb5,
-			0xbd, 0x19, 0xb3, 0x00, 0x00, 0x34, 0x00, 0x33,
-			0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
-			0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
-			0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
-			0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
-			0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
-			0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
-			0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
-			0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
-			0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
-			0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+	{"RequestClientCert, client gives it", RequestClientCert, []*x509.Certificate{clientCertificate}, [][]byte{
+		{
+			0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
+			0x50, 0x03, 0x01, 0x50, 0x77, 0x43, 0x47, 0xfd,
+			0x1d, 0xb0, 0x60, 0x4c, 0x25, 0x86, 0x45, 0x4a,
+			0xe5, 0x3f, 0x80, 0x56, 0x18, 0x91, 0x5c, 0xe2,
+			0x62, 0xc5, 0x77, 0xc2, 0x92, 0xdd, 0xdc, 0x39,
+			0x23, 0x1d, 0xc5, 0x00, 0x00, 0x28, 0x00, 0x39,
+			0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
+			0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
+			0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+			0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+			0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
+			0x00,
 		},
-
-			{
-				0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
-				0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
-				0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
-				0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
-				0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
-				0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
-				0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
-				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-				0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
-				0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
-				0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
-				0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
-				0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
-				0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
-				0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
-				0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
-				0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
-				0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
-				0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
-				0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
-				0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
-				0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
-				0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
-				0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
-				0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
-				0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
-				0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
-				0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
-				0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
-				0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
-				0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
-				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-				0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
-				0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
-				0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
-				0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
-				0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
-				0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
-				0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
-				0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
-				0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
-				0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
-				0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
-				0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
-				0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
-				0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
-				0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
-				0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
-				0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
-				0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
-				0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
-				0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
-				0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
-				0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
-				0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
-				0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
-				0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
-				0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
-				0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
-				0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
-				0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
-				0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
-				0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
-				0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
-				0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
-				0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
-				0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
-				0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
-				0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
-				0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
-				0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
-				0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
-				0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-				0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
-				0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
-				0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
-				0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
-				0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
-				0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
-				0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
-				0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
-				0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
-				0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
-				0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
-				0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
-				0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
-				0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
-				0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
-				0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
-				0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
-				0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
-				0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
-				0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
-			},
-
-			{
-				0x16, 0x03, 0x01, 0x01, 0xfb, 0x0b, 0x00, 0x01,
-				0xf7, 0x00, 0x01, 0xf4, 0x00, 0x01, 0xf1, 0x30,
-				0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x58, 0xa0,
-				0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30,
-				0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-				0x0d, 0x01, 0x01, 0x05, 0x30, 0x26, 0x31, 0x10,
-				0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
-				0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
-				0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
-				0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
-				0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d,
-				0x31, 0x31, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37,
-				0x35, 0x35, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x31,
-				0x32, 0x31, 0x32, 0x30, 0x37, 0x30, 0x38, 0x30,
-				0x30, 0x31, 0x32, 0x5a, 0x30, 0x26, 0x31, 0x10,
-				0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
-				0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
-				0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
-				0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
-				0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9c, 0x30,
-				0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-				0x0d, 0x01, 0x01, 0x01, 0x03, 0x81, 0x8c, 0x00,
-				0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0x4e, 0xd0,
-				0x7b, 0x31, 0xe3, 0x82, 0x64, 0xd9, 0x59, 0xc0,
-				0xc2, 0x87, 0xa4, 0x5e, 0x1e, 0x8b, 0x73, 0x33,
-				0xc7, 0x63, 0x53, 0xdf, 0x66, 0x92, 0x06, 0x84,
-				0xf6, 0x64, 0xd5, 0x8f, 0xe4, 0x36, 0xa7, 0x1d,
-				0x2b, 0xe8, 0xb3, 0x20, 0x36, 0x45, 0x23, 0xb5,
-				0xe3, 0x95, 0xae, 0xed, 0xe0, 0xf5, 0x20, 0x9c,
-				0x8d, 0x95, 0xdf, 0x7f, 0x5a, 0x12, 0xef, 0x87,
-				0xe4, 0x5b, 0x68, 0xe4, 0xe9, 0x0e, 0x74, 0xec,
-				0x04, 0x8a, 0x7f, 0xde, 0x93, 0x27, 0xc4, 0x01,
-				0x19, 0x7a, 0xbd, 0xf2, 0xdc, 0x3d, 0x14, 0xab,
-				0xd0, 0x54, 0xca, 0x21, 0x0c, 0xd0, 0x4d, 0x6e,
-				0x87, 0x2e, 0x5c, 0xc5, 0xd2, 0xbb, 0x4d, 0x4b,
-				0x4f, 0xce, 0xb6, 0x2c, 0xf7, 0x7e, 0x88, 0xec,
-				0x7c, 0xd7, 0x02, 0x91, 0x74, 0xa6, 0x1e, 0x0c,
-				0x1a, 0xda, 0xe3, 0x4a, 0x5a, 0x2e, 0xde, 0x13,
-				0x9c, 0x4c, 0x40, 0x88, 0x59, 0x93, 0x02, 0x03,
-				0x01, 0x00, 0x01, 0xa3, 0x32, 0x30, 0x30, 0x30,
-				0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
-				0xff, 0x04, 0x04, 0x03, 0x02, 0x00, 0xa0, 0x30,
-				0x0d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x06,
-				0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, 0x0f,
-				0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x08, 0x30,
-				0x06, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30,
-				0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
-				0x0d, 0x01, 0x01, 0x05, 0x03, 0x81, 0x81, 0x00,
-				0x36, 0x1f, 0xb3, 0x7a, 0x0c, 0x75, 0xc9, 0x6e,
-				0x37, 0x46, 0x61, 0x2b, 0xd5, 0xbd, 0xc0, 0xa7,
-				0x4b, 0xcc, 0x46, 0x9a, 0x81, 0x58, 0x7c, 0x85,
-				0x79, 0x29, 0xc8, 0xc8, 0xc6, 0x67, 0xdd, 0x32,
-				0x56, 0x45, 0x2b, 0x75, 0xb6, 0xe9, 0x24, 0xa9,
-				0x50, 0x9a, 0xbe, 0x1f, 0x5a, 0xfa, 0x1a, 0x15,
-				0xd9, 0xcc, 0x55, 0x95, 0x72, 0x16, 0x83, 0xb9,
-				0xc2, 0xb6, 0x8f, 0xfd, 0x88, 0x8c, 0x38, 0x84,
-				0x1d, 0xab, 0x5d, 0x92, 0x31, 0x13, 0x4f, 0xfd,
-				0x83, 0x3b, 0xc6, 0x9d, 0xf1, 0x11, 0x62, 0xb6,
-				0x8b, 0xec, 0xab, 0x67, 0xbe, 0xc8, 0x64, 0xb0,
-				0x11, 0x50, 0x46, 0x58, 0x17, 0x6b, 0x99, 0x1c,
-				0xd3, 0x1d, 0xfc, 0x06, 0xf1, 0x0e, 0xe5, 0x96,
-				0xa8, 0x0c, 0xf9, 0x78, 0x20, 0xb7, 0x44, 0x18,
-				0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf,
-				0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85,
-				0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
-				0x82, 0x00, 0x80, 0xa7, 0x2f, 0xed, 0xfa, 0xc2,
-				0xbd, 0x46, 0xa1, 0xf2, 0x69, 0xc5, 0x1d, 0xa1,
-				0x34, 0xd6, 0xd0, 0x84, 0xf5, 0x5d, 0x8c, 0x82,
-				0x8d, 0x98, 0x82, 0x9c, 0xd9, 0x07, 0xe0, 0xf7,
-				0x55, 0x49, 0x4d, 0xa1, 0x48, 0x59, 0x02, 0xd3,
-				0x84, 0x37, 0xaf, 0x01, 0xb3, 0x3a, 0xf4, 0xed,
-				0x99, 0xbe, 0x67, 0x36, 0x19, 0x55, 0xf3, 0xf9,
-				0xcb, 0x94, 0xe5, 0x7b, 0x8b, 0x77, 0xf2, 0x5f,
-				0x4c, 0xfe, 0x01, 0x1f, 0x7b, 0xd7, 0x23, 0x49,
-				0x0c, 0xcb, 0x6c, 0xb0, 0xe7, 0x77, 0xd6, 0xcf,
-				0xa8, 0x7d, 0xdb, 0xa7, 0x14, 0xe2, 0xf5, 0xf3,
-				0xff, 0xba, 0x23, 0xd2, 0x9a, 0x36, 0x14, 0x60,
-				0x2a, 0x91, 0x5d, 0x2b, 0x35, 0x3b, 0xb6, 0xdd,
-				0xcb, 0x6b, 0xdc, 0x18, 0xdc, 0x33, 0xb8, 0xb3,
-				0xc7, 0x27, 0x7e, 0xfc, 0xd2, 0xf7, 0x97, 0x90,
-				0x5e, 0x17, 0xac, 0x14, 0x8e, 0x0f, 0xca, 0xb5,
-				0x6f, 0xc9, 0x2d, 0x16, 0x03, 0x01, 0x00, 0x86,
-				0x0f, 0x00, 0x00, 0x82, 0x00, 0x80, 0x44, 0x7f,
-				0xa2, 0x59, 0x60, 0x0b, 0x5a, 0xc4, 0xaf, 0x1e,
-				0x60, 0xa5, 0x24, 0xea, 0xc1, 0xc3, 0x22, 0x21,
-				0x6b, 0x22, 0x8b, 0x2a, 0x11, 0x82, 0x68, 0x7d,
-				0xb9, 0xdd, 0x9c, 0x27, 0x4c, 0xc2, 0xc8, 0xa2,
-				0x8b, 0x6b, 0x77, 0x8d, 0x3a, 0x2b, 0x8d, 0x2f,
-				0x6a, 0x2b, 0x43, 0xd2, 0xd1, 0xc6, 0x41, 0x79,
-				0xa2, 0x4f, 0x2b, 0xc2, 0xf7, 0xb2, 0x10, 0xad,
-				0xa6, 0x01, 0x51, 0x51, 0x25, 0xe7, 0x58, 0x7a,
-				0xcf, 0x3b, 0xc4, 0x29, 0xb5, 0xe5, 0xa7, 0x83,
-				0xe6, 0xcb, 0x1e, 0xf3, 0x02, 0x0f, 0x53, 0x3b,
-				0xb5, 0x39, 0xef, 0x9c, 0x42, 0xe0, 0xa6, 0x9b,
-				0x2b, 0xdd, 0x60, 0xae, 0x0a, 0x73, 0x35, 0xbe,
-				0x26, 0x10, 0x1b, 0xe9, 0xe9, 0x61, 0xab, 0x20,
-				0xa5, 0x48, 0xc6, 0x60, 0xa6, 0x50, 0x3c, 0xfb,
-				0xa7, 0xca, 0xb0, 0x80, 0x95, 0x1e, 0xce, 0xc7,
-				0xbb, 0x68, 0x44, 0xdc, 0x0e, 0x0e, 0x14, 0x03,
-				0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00,
-				0x24, 0xb6, 0xcd, 0x0c, 0x78, 0xfd, 0xd6, 0xff,
-				0xbe, 0x97, 0xd5, 0x0a, 0x7d, 0x4f, 0xa1, 0x03,
-				0x78, 0xc8, 0x61, 0x6f, 0xf2, 0x4b, 0xa8, 0x56,
-				0x4f, 0x3c, 0xa2, 0xd9, 0xd0, 0x20, 0x13, 0x1b,
-				0x8b, 0x36, 0xb7, 0x33, 0x9c,
-			},
-
-			{
-				0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
-				0x01, 0x00, 0x24, 0xa3, 0x43, 0x94, 0xe7, 0xdf,
-				0xb6, 0xc3, 0x03, 0x9f, 0xc1, 0x59, 0x0c, 0xc3,
-				0x13, 0xae, 0xed, 0xcf, 0xff, 0xf1, 0x80, 0xf3,
-				0x13, 0x63, 0x1c, 0xf0, 0xca, 0xad, 0x9e, 0x71,
-				0x46, 0x5f, 0x6b, 0xeb, 0x10, 0x3f, 0xe3, 0x17,
-				0x03, 0x01, 0x00, 0x21, 0xe9, 0x80, 0x95, 0x6e,
-				0x05, 0x55, 0x2f, 0xed, 0x4d, 0xde, 0x17, 0x3a,
-				0x32, 0x9b, 0x2a, 0x74, 0x30, 0x4f, 0xe0, 0x9f,
-				0x4e, 0xd3, 0x06, 0xbd, 0x3a, 0x43, 0x75, 0x8b,
-				0x5b, 0x9a, 0xd8, 0x2e, 0x56, 0x15, 0x03, 0x01,
-				0x00, 0x16, 0x53, 0xf5, 0xff, 0xe0, 0xa1, 0x6c,
-				0x33, 0xf4, 0x4e, 0x89, 0x68, 0xe1, 0xf7, 0x61,
-				0x13, 0xb3, 0x12, 0xa1, 0x8e, 0x5a, 0x7a, 0x02,
-			},
+		{
+			0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+			0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+			0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+			0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+			0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+			0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+			0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+			0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+			0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+			0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+			0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+			0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+			0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+			0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+			0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+			0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+			0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+			0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+			0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+			0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+			0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+			0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+			0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+			0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+			0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+			0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+			0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+			0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+			0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+			0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+			0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+			0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+			0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+			0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+			0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+			0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+			0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+			0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+			0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+			0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+			0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+			0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+			0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+			0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+			0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+			0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+			0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+			0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+			0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+			0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+			0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+			0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+			0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+			0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+			0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+			0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+			0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+			0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+			0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+			0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+			0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+			0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+			0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+			0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+			0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+			0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+			0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+			0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+			0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+			0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+			0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+			0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+			0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+			0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+			0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+			0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+			0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+			0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+			0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+			0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+			0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+			0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+			0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+			0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+			0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+			0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+			0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+			0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+			0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+			0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
+			0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
+			0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
 		},
-	},
+		{
+			0x16, 0x03, 0x01, 0x01, 0xfb, 0x0b, 0x00, 0x01,
+			0xf7, 0x00, 0x01, 0xf4, 0x00, 0x01, 0xf1, 0x30,
+			0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x58, 0xa0,
+			0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30,
+			0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x01, 0x05, 0x30, 0x26, 0x31, 0x10,
+			0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+			0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+			0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+			0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+			0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d,
+			0x31, 0x31, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37,
+			0x35, 0x35, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x31,
+			0x32, 0x31, 0x32, 0x30, 0x37, 0x30, 0x38, 0x30,
+			0x30, 0x31, 0x32, 0x5a, 0x30, 0x26, 0x31, 0x10,
+			0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+			0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+			0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+			0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+			0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9c, 0x30,
+			0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x01, 0x01, 0x03, 0x81, 0x8c, 0x00,
+			0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0x4e, 0xd0,
+			0x7b, 0x31, 0xe3, 0x82, 0x64, 0xd9, 0x59, 0xc0,
+			0xc2, 0x87, 0xa4, 0x5e, 0x1e, 0x8b, 0x73, 0x33,
+			0xc7, 0x63, 0x53, 0xdf, 0x66, 0x92, 0x06, 0x84,
+			0xf6, 0x64, 0xd5, 0x8f, 0xe4, 0x36, 0xa7, 0x1d,
+			0x2b, 0xe8, 0xb3, 0x20, 0x36, 0x45, 0x23, 0xb5,
+			0xe3, 0x95, 0xae, 0xed, 0xe0, 0xf5, 0x20, 0x9c,
+			0x8d, 0x95, 0xdf, 0x7f, 0x5a, 0x12, 0xef, 0x87,
+			0xe4, 0x5b, 0x68, 0xe4, 0xe9, 0x0e, 0x74, 0xec,
+			0x04, 0x8a, 0x7f, 0xde, 0x93, 0x27, 0xc4, 0x01,
+			0x19, 0x7a, 0xbd, 0xf2, 0xdc, 0x3d, 0x14, 0xab,
+			0xd0, 0x54, 0xca, 0x21, 0x0c, 0xd0, 0x4d, 0x6e,
+			0x87, 0x2e, 0x5c, 0xc5, 0xd2, 0xbb, 0x4d, 0x4b,
+			0x4f, 0xce, 0xb6, 0x2c, 0xf7, 0x7e, 0x88, 0xec,
+			0x7c, 0xd7, 0x02, 0x91, 0x74, 0xa6, 0x1e, 0x0c,
+			0x1a, 0xda, 0xe3, 0x4a, 0x5a, 0x2e, 0xde, 0x13,
+			0x9c, 0x4c, 0x40, 0x88, 0x59, 0x93, 0x02, 0x03,
+			0x01, 0x00, 0x01, 0xa3, 0x32, 0x30, 0x30, 0x30,
+			0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
+			0xff, 0x04, 0x04, 0x03, 0x02, 0x00, 0xa0, 0x30,
+			0x0d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x06,
+			0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, 0x0f,
+			0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x08, 0x30,
+			0x06, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30,
+			0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+			0x0d, 0x01, 0x01, 0x05, 0x03, 0x81, 0x81, 0x00,
+			0x36, 0x1f, 0xb3, 0x7a, 0x0c, 0x75, 0xc9, 0x6e,
+			0x37, 0x46, 0x61, 0x2b, 0xd5, 0xbd, 0xc0, 0xa7,
+			0x4b, 0xcc, 0x46, 0x9a, 0x81, 0x58, 0x7c, 0x85,
+			0x79, 0x29, 0xc8, 0xc8, 0xc6, 0x67, 0xdd, 0x32,
+			0x56, 0x45, 0x2b, 0x75, 0xb6, 0xe9, 0x24, 0xa9,
+			0x50, 0x9a, 0xbe, 0x1f, 0x5a, 0xfa, 0x1a, 0x15,
+			0xd9, 0xcc, 0x55, 0x95, 0x72, 0x16, 0x83, 0xb9,
+			0xc2, 0xb6, 0x8f, 0xfd, 0x88, 0x8c, 0x38, 0x84,
+			0x1d, 0xab, 0x5d, 0x92, 0x31, 0x13, 0x4f, 0xfd,
+			0x83, 0x3b, 0xc6, 0x9d, 0xf1, 0x11, 0x62, 0xb6,
+			0x8b, 0xec, 0xab, 0x67, 0xbe, 0xc8, 0x64, 0xb0,
+			0x11, 0x50, 0x46, 0x58, 0x17, 0x6b, 0x99, 0x1c,
+			0xd3, 0x1d, 0xfc, 0x06, 0xf1, 0x0e, 0xe5, 0x96,
+			0xa8, 0x0c, 0xf9, 0x78, 0x20, 0xb7, 0x44, 0x18,
+			0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf,
+			0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85,
+			0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+			0x82, 0x00, 0x80, 0x81, 0x46, 0x43, 0xf9, 0xe7,
+			0xda, 0x8c, 0x92, 0x3a, 0x78, 0x1a, 0x86, 0xb3,
+			0xbe, 0x83, 0x22, 0xb6, 0xaa, 0x57, 0x37, 0x68,
+			0x9e, 0x54, 0x3f, 0xd3, 0xce, 0x4d, 0x5e, 0x2a,
+			0xdc, 0xb0, 0x49, 0x02, 0xbb, 0xc0, 0x45, 0x58,
+			0x79, 0x10, 0xc7, 0x94, 0x60, 0x9f, 0x1b, 0x5f,
+			0x18, 0x31, 0x37, 0x9c, 0xe0, 0xe6, 0xdf, 0x5e,
+			0x70, 0x44, 0xf6, 0x8b, 0xdf, 0xf1, 0xf6, 0x43,
+			0xc8, 0x2f, 0xd1, 0xce, 0xd0, 0xd6, 0x64, 0x4f,
+			0xe8, 0x2b, 0xfa, 0xd3, 0xd0, 0xd1, 0x2e, 0xaa,
+			0x9b, 0x1d, 0x13, 0x5c, 0xbe, 0x57, 0x41, 0x6c,
+			0x5e, 0x8d, 0xea, 0xa9, 0x3c, 0x58, 0xa0, 0x30,
+			0x92, 0x77, 0x7a, 0xed, 0x64, 0x58, 0xe5, 0x7f,
+			0x6a, 0x93, 0x89, 0x66, 0x3d, 0x13, 0x16, 0x56,
+			0xa0, 0xad, 0xdc, 0x68, 0x95, 0x87, 0x81, 0xd0,
+			0x90, 0x4d, 0x5f, 0xfe, 0x3e, 0x83, 0x15, 0x2e,
+			0x50, 0x3c, 0xdd, 0x16, 0x03, 0x01, 0x00, 0x86,
+			0x0f, 0x00, 0x00, 0x82, 0x00, 0x80, 0x2b, 0xf8,
+			0x56, 0x48, 0xbb, 0x02, 0x37, 0x15, 0x02, 0x74,
+			0x33, 0x53, 0x65, 0xa7, 0x7c, 0x2f, 0xc6, 0x5d,
+			0x80, 0x59, 0xc1, 0xc2, 0x3b, 0xa9, 0xde, 0x4e,
+			0x70, 0x51, 0xd2, 0xde, 0x58, 0x7f, 0xd8, 0xb9,
+			0xb6, 0x3b, 0xc8, 0xaa, 0xfc, 0x3d, 0x53, 0x2d,
+			0x61, 0x4d, 0xf5, 0x60, 0x12, 0xc2, 0xa5, 0x39,
+			0x0c, 0xa7, 0xc6, 0xac, 0x26, 0x4b, 0xf4, 0x5f,
+			0xe9, 0xf4, 0xf2, 0x73, 0x48, 0xe4, 0x3b, 0xee,
+			0xf2, 0xee, 0xc0, 0xee, 0xfb, 0x5b, 0x60, 0xc2,
+			0x74, 0xe6, 0xf6, 0x43, 0x3e, 0xa4, 0xf7, 0x97,
+			0x3d, 0xfc, 0xe9, 0x44, 0x21, 0x18, 0x46, 0x05,
+			0x33, 0xf8, 0xfe, 0x35, 0x5b, 0xe6, 0x8f, 0xef,
+			0x4d, 0x4c, 0x87, 0xf6, 0xb4, 0x6e, 0x6b, 0x39,
+			0xd8, 0xaa, 0x1b, 0x33, 0xc9, 0x1c, 0x66, 0x48,
+			0xbe, 0xfa, 0xb5, 0x92, 0x09, 0xfd, 0xb9, 0xb9,
+			0xca, 0xe6, 0x6d, 0x71, 0xc6, 0x89, 0x14, 0x03,
+			0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00,
+			0x24, 0xe3, 0x2b, 0xef, 0x17, 0xd5, 0xa6, 0x4c,
+			0x2e, 0x10, 0xac, 0x9c, 0xfe, 0x0f, 0x18, 0x43,
+			0x95, 0x00, 0x81, 0xf7, 0x7c, 0x00, 0x5b, 0x89,
+			0x52, 0x41, 0xe4, 0x8a, 0x8a, 0x34, 0x31, 0x09,
+			0x48, 0x7c, 0xc5, 0xc3, 0x83,
+		},
+		{
+			0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+			0x01, 0x00, 0x24, 0x24, 0xaa, 0xaa, 0x56, 0x8b,
+			0x41, 0x87, 0x01, 0xbe, 0x80, 0x05, 0x51, 0x36,
+			0x08, 0xfc, 0xaf, 0xff, 0x7f, 0xf4, 0x74, 0x84,
+			0x88, 0xdc, 0xb8, 0x8e, 0x70, 0x6c, 0x22, 0x04,
+			0xee, 0x45, 0x8d, 0xda, 0xed, 0xc6, 0x05, 0x17,
+			0x03, 0x01, 0x00, 0x21, 0x91, 0x49, 0x4b, 0xed,
+			0xa3, 0x41, 0xe9, 0x88, 0x3b, 0xa3, 0x01, 0xee,
+			0x77, 0x4e, 0x12, 0xb4, 0xcd, 0x5e, 0xcc, 0x45,
+			0x02, 0x5a, 0x20, 0xd6, 0xe8, 0xac, 0xcb, 0x60,
+			0xcb, 0x1b, 0xef, 0xf9, 0xc2, 0x15, 0x03, 0x01,
+			0x00, 0x16, 0xd4, 0xcd, 0x92, 0x3c, 0x10, 0x93,
+			0x68, 0xc3, 0xdd, 0xaf, 0xe9, 0xcb, 0x5d, 0x94,
+			0x1a, 0x06, 0x81, 0xa7, 0x78, 0x0f, 0xc3, 0x03,
+		},
+	}},
 }
 
 // cert.pem and key.pem were generated with generate_cert.go
@@ -1703,7 +1984,7 @@ GFGNEH5PlGffo05wc46QkYU=
 
 /* corresponding key.pem for cert.pem is:
 -----BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgE7QezHjgmTZWcDCh6ReHotzM8djU99mkgaE9mTVj+Q2px0r6LMg
+MIICWgIBAAKBgE7QezHjgmTZWcDCh6ReHotzM8djU99mkgaE9mTVj+Q2px0r6LMg
 NkUjteOVru3g9SCcjZXff1oS74fkW2jk6Q507ASKf96TJ8QBGXq98tw9FKvQVMoh
 DNBNbocuXMXSu01LT862LPd+iOx81wKRdKYeDBra40paLt4TnExAiFmTAgMBAAEC
 gYBxvXd8yNteFTns8A/2yomEMC4yeosJJSpp1CsN3BJ7g8/qTnrVPxBy+RU+qr63
@@ -1715,6 +1996,6 @@ RkKVpenBHyrGg0oeN5La7URILWKj7CPXAkBKo6F+d+phNjwIFoN1Xb/RA32w/D1I
 saG9sF+UEhRt9AxUfW/U/tIQ9V0ZHHcSg1XaCM5Nvp934brdKdvTOKnJAkBD5h/3
 Rybatlvg/fzBEaJFyq09zhngkxlZOUtBVTqzl17RVvY2orgH02U4HbCHy4phxOn7
 qTdQRYlHRftgnWK1AkANibn9PRYJ7mJyJ9Dyj2QeNcSkSTzrt0tPvUMf4+meJymN
-1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvAMAA=
+1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvA
 -----END RSA PRIVATE KEY-----
 */
diff --git a/src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py b/src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py
deleted file mode 100644
index 5692bd3..0000000
--- a/src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py
+++ /dev/null
@@ -1,57 +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.
-
-# This code is used to parse the debug log from gnutls-cli and generate a
-# script of the handshake. This script is included in handshake_server_test.go.
-# See the comments there for details.
-
-import sys
-
-blocks = []
-
-READ = 1
-WRITE = 2
-
-currentBlockType = 0
-currentBlock = []
-for line in sys.stdin.readlines():
-        line = line[:-1]
-        if line.startswith("|<7>| WRITE: "):
-                if currentBlockType != WRITE:
-                        if len(currentBlock) > 0:
-                                blocks.append(currentBlock)
-                        currentBlock = []
-                        currentBlockType = WRITE
-        elif line.startswith("|<7>| READ: "):
-                if currentBlockType != READ:
-                        if len(currentBlock) > 0:
-                                blocks.append(currentBlock)
-                        currentBlock = []
-                        currentBlockType = READ
-        elif line.startswith("|<7>| 0"):
-                line = line[13:]
-                line = line.strip()
-                bs = line.split()
-                for b in bs:
-                        currentBlock.append(int(b, 16))
-	elif line.startswith("|<7>| RB-PEEK: Read 1 bytes"):
-		currentBlock = currentBlock[:-1]
-
-if len(currentBlock) > 0:
-        blocks.append(currentBlock)
-
-for block in blocks:
-        sys.stdout.write("\t{\n")
-
-        i = 0
-        for b in block:
-                if i % 8 == 0:
-                        sys.stdout.write("\t\t")
-                sys.stdout.write("0x%02x," % b)
-                if i % 8 == 7:
-                        sys.stdout.write("\n")
-                else:
-                        sys.stdout.write(" ")
-                i += 1
-        sys.stdout.write("\n\t},\n\n")
diff --git a/src/pkg/crypto/tls/prf.go b/src/pkg/crypto/tls/prf.go
index 637ef03..df1eaad 100644
--- a/src/pkg/crypto/tls/prf.go
+++ b/src/pkg/crypto/tls/prf.go
@@ -106,10 +106,9 @@ var keyExpansionLabel = []byte("key expansion")
 var clientFinishedLabel = []byte("client finished")
 var serverFinishedLabel = []byte("server finished")
 
-// keysFromPreMasterSecret generates the connection keys from the pre master
-// secret, given the lengths of the MAC key, cipher key and IV, as defined in
-// RFC 2246, section 6.3.
-func keysFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+// masterFromPreMasterSecret generates the master secret from the pre-master
+// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
+func masterFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte) []byte {
 	prf := pRF10
 	if version == versionSSL30 {
 		prf = pRF30
@@ -118,9 +117,21 @@ func keysFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serv
 	var seed [tlsRandomLength * 2]byte
 	copy(seed[0:len(clientRandom)], clientRandom)
 	copy(seed[len(clientRandom):], serverRandom)
-	masterSecret = make([]byte, masterSecretLength)
+	masterSecret := make([]byte, masterSecretLength)
 	prf(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+	return masterSecret
+}
 
+// keysFromMasterSecret generates the connection keys from the master
+// secret, given the lengths of the MAC key, cipher key and IV, as defined in
+// RFC 2246, section 6.3.
+func keysFromMasterSecret(version uint16, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+	prf := pRF10
+	if version == versionSSL30 {
+		prf = pRF30
+	}
+
+	var seed [tlsRandomLength * 2]byte
 	copy(seed[0:len(clientRandom)], serverRandom)
 	copy(seed[len(serverRandom):], clientRandom)
 
diff --git a/src/pkg/crypto/tls/prf_test.go b/src/pkg/crypto/tls/prf_test.go
index a32392c..773a2b2 100644
--- a/src/pkg/crypto/tls/prf_test.go
+++ b/src/pkg/crypto/tls/prf_test.go
@@ -48,18 +48,23 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
 		in, _ := hex.DecodeString(test.preMasterSecret)
 		clientRandom, _ := hex.DecodeString(test.clientRandom)
 		serverRandom, _ := hex.DecodeString(test.serverRandom)
-		master, clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromPreMasterSecret(test.version, in, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
-		masterString := hex.EncodeToString(master)
+
+		masterSecret := masterFromPreMasterSecret(test.version, in, clientRandom, serverRandom)
+		if s := hex.EncodeToString(masterSecret); s != test.masterSecret {
+			t.Errorf("#%d: bad master secret %s, want %s", i, s, test.masterSecret)
+			continue
+		}
+
+		clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromMasterSecret(test.version, masterSecret, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
 		clientMACString := hex.EncodeToString(clientMAC)
 		serverMACString := hex.EncodeToString(serverMAC)
 		clientKeyString := hex.EncodeToString(clientKey)
 		serverKeyString := hex.EncodeToString(serverKey)
-		if masterString != test.masterSecret ||
-			clientMACString != test.clientMAC ||
+		if clientMACString != test.clientMAC ||
 			serverMACString != test.serverMAC ||
 			clientKeyString != test.clientKey ||
 			serverKeyString != test.serverKey {
-			t.Errorf("#%d: got: (%s, %s, %s, %s, %s) want: (%s, %s, %s, %s, %s)", i, masterString, clientMACString, serverMACString, clientKeyString, serverKeyString, test.masterSecret, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey)
+			t.Errorf("#%d: got: (%s, %s, %s, %s) want: (%s, %s, %s, %s)", i, clientMACString, serverMACString, clientKeyString, serverKeyString, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey)
 		}
 	}
 }
diff --git a/src/pkg/crypto/tls/root_test.go b/src/pkg/crypto/tls/root_test.go
deleted file mode 100644
index e61c218..0000000
--- a/src/pkg/crypto/tls/root_test.go
+++ /dev/null
@@ -1,61 +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 tls
-
-import (
-	"crypto/x509"
-	"runtime"
-	"testing"
-)
-
-var tlsServers = []string{
-	"google.com",
-	"github.com",
-	"twitter.com",
-}
-
-func TestOSCertBundles(t *testing.T) {
-	if testing.Short() {
-		t.Logf("skipping certificate tests in short mode")
-		return
-	}
-
-	for _, addr := range tlsServers {
-		conn, err := Dial("tcp", addr+":443", &Config{ServerName: addr})
-		if err != nil {
-			t.Errorf("unable to verify %v: %v", addr, err)
-			continue
-		}
-		err = conn.Close()
-		if err != nil {
-			t.Error(err)
-		}
-	}
-}
-
-func TestCertHostnameVerifyWindows(t *testing.T) {
-	if runtime.GOOS != "windows" {
-		return
-	}
-
-	if testing.Short() {
-		t.Logf("skipping certificate tests in short mode")
-		return
-	}
-
-	for _, addr := range tlsServers {
-		cfg := &Config{ServerName: "example.com"}
-		conn, err := Dial("tcp", addr+":443", cfg)
-		if err == nil {
-			conn.Close()
-			t.Errorf("should fail to verify for example.com: %v", addr)
-			continue
-		}
-		_, ok := err.(x509.HostnameError)
-		if !ok {
-			t.Errorf("error type mismatch, got: %v", err)
-		}
-	}
-}
diff --git a/src/pkg/crypto/tls/ticket.go b/src/pkg/crypto/tls/ticket.go
new file mode 100644
index 0000000..4cfc5a5
--- /dev/null
+++ b/src/pkg/crypto/tls/ticket.go
@@ -0,0 +1,182 @@
+// 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 tls
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/hmac"
+	"crypto/sha256"
+	"crypto/subtle"
+	"errors"
+	"io"
+)
+
+// sessionState contains the information that is serialized into a session
+// ticket in order to later resume a connection.
+type sessionState struct {
+	vers         uint16
+	cipherSuite  uint16
+	masterSecret []byte
+	certificates [][]byte
+}
+
+func (s *sessionState) equal(i interface{}) bool {
+	s1, ok := i.(*sessionState)
+	if !ok {
+		return false
+	}
+
+	if s.vers != s1.vers ||
+		s.cipherSuite != s1.cipherSuite ||
+		!bytes.Equal(s.masterSecret, s1.masterSecret) {
+		return false
+	}
+
+	if len(s.certificates) != len(s1.certificates) {
+		return false
+	}
+
+	for i := range s.certificates {
+		if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
+			return false
+		}
+	}
+
+	return true
+}
+
+func (s *sessionState) marshal() []byte {
+	length := 2 + 2 + 2 + len(s.masterSecret) + 2
+	for _, cert := range s.certificates {
+		length += 4 + len(cert)
+	}
+
+	ret := make([]byte, length)
+	x := ret
+	x[0] = byte(s.vers >> 8)
+	x[1] = byte(s.vers)
+	x[2] = byte(s.cipherSuite >> 8)
+	x[3] = byte(s.cipherSuite)
+	x[4] = byte(len(s.masterSecret) >> 8)
+	x[5] = byte(len(s.masterSecret))
+	x = x[6:]
+	copy(x, s.masterSecret)
+	x = x[len(s.masterSecret):]
+
+	x[0] = byte(len(s.certificates) >> 8)
+	x[1] = byte(len(s.certificates))
+	x = x[2:]
+
+	for _, cert := range s.certificates {
+		x[0] = byte(len(cert) >> 24)
+		x[1] = byte(len(cert) >> 16)
+		x[2] = byte(len(cert) >> 8)
+		x[3] = byte(len(cert))
+		copy(x[4:], cert)
+		x = x[4+len(cert):]
+	}
+
+	return ret
+}
+
+func (s *sessionState) unmarshal(data []byte) bool {
+	if len(data) < 8 {
+		return false
+	}
+
+	s.vers = uint16(data[0])<<8 | uint16(data[1])
+	s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
+	masterSecretLen := int(data[4])<<8 | int(data[5])
+	data = data[6:]
+	if len(data) < masterSecretLen {
+		return false
+	}
+
+	s.masterSecret = data[:masterSecretLen]
+	data = data[masterSecretLen:]
+
+	if len(data) < 2 {
+		return false
+	}
+
+	numCerts := int(data[0])<<8 | int(data[1])
+	data = data[2:]
+
+	s.certificates = make([][]byte, numCerts)
+	for i := range s.certificates {
+		if len(data) < 4 {
+			return false
+		}
+		certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+		data = data[4:]
+		if certLen < 0 {
+			return false
+		}
+		if len(data) < certLen {
+			return false
+		}
+		s.certificates[i] = data[:certLen]
+		data = data[certLen:]
+	}
+
+	if len(data) > 0 {
+		return false
+	}
+
+	return true
+}
+
+func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) {
+	serialized := state.marshal()
+	encrypted := make([]byte, aes.BlockSize+len(serialized)+sha256.Size)
+	iv := encrypted[:aes.BlockSize]
+	macBytes := encrypted[len(encrypted)-sha256.Size:]
+
+	if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
+		return nil, err
+	}
+	block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
+	if err != nil {
+		return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
+	}
+	cipher.NewCTR(block, iv).XORKeyStream(encrypted[aes.BlockSize:], serialized)
+
+	mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
+	mac.Write(encrypted[:len(encrypted)-sha256.Size])
+	mac.Sum(macBytes[:0])
+
+	return encrypted, nil
+}
+
+func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
+	if len(encrypted) < aes.BlockSize+sha256.Size {
+		return nil, false
+	}
+
+	iv := encrypted[:aes.BlockSize]
+	macBytes := encrypted[len(encrypted)-sha256.Size:]
+
+	mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
+	mac.Write(encrypted[:len(encrypted)-sha256.Size])
+	expected := mac.Sum(nil)
+
+	if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
+		return nil, false
+	}
+
+	block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
+	if err != nil {
+		return nil, false
+	}
+	ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size]
+	plaintext := ciphertext
+	cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
+
+	state := new(sessionState)
+	ok := state.unmarshal(plaintext)
+	return state, ok
+}
diff --git a/src/pkg/crypto/tls/tls.go b/src/pkg/crypto/tls/tls.go
index 09df5ad..9230656 100644
--- a/src/pkg/crypto/tls/tls.go
+++ b/src/pkg/crypto/tls/tls.go
@@ -6,6 +6,8 @@
 package tls
 
 import (
+	"crypto"
+	"crypto/ecdsa"
 	"crypto/rsa"
 	"crypto/x509"
 	"encoding/pem"
@@ -146,30 +148,22 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error)
 		return
 	}
 
-	keyDERBlock, _ := pem.Decode(keyPEMBlock)
-	if keyDERBlock == nil {
-		err = errors.New("crypto/tls: failed to parse key PEM data")
-		return
-	}
-
-	// OpenSSL 0.9.8 generates PKCS#1 private keys by default, while
-	// OpenSSL 1.0.0 generates PKCS#8 keys. We try both.
-	var key *rsa.PrivateKey
-	if key, err = x509.ParsePKCS1PrivateKey(keyDERBlock.Bytes); err != nil {
-		var privKey interface{}
-		if privKey, err = x509.ParsePKCS8PrivateKey(keyDERBlock.Bytes); err != nil {
-			err = errors.New("crypto/tls: failed to parse key: " + err.Error())
+	var keyDERBlock *pem.Block
+	for {
+		keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
+		if keyDERBlock == nil {
+			err = errors.New("crypto/tls: failed to parse key PEM data")
 			return
 		}
-
-		var ok bool
-		if key, ok = privKey.(*rsa.PrivateKey); !ok {
-			err = errors.New("crypto/tls: found non-RSA private key in PKCS#8 wrapping")
-			return
+		if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
+			break
 		}
 	}
 
-	cert.PrivateKey = key
+	cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
+	if err != nil {
+		return
+	}
 
 	// We don't need to parse the public key for TLS, but we so do anyway
 	// to check that it looks sane and matches the private key.
@@ -178,10 +172,54 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error)
 		return
 	}
 
-	if x509Cert.PublicKeyAlgorithm != x509.RSA || x509Cert.PublicKey.(*rsa.PublicKey).N.Cmp(key.PublicKey.N) != 0 {
-		err = errors.New("crypto/tls: private key does not match public key")
+	switch pub := x509Cert.PublicKey.(type) {
+	case *rsa.PublicKey:
+		priv, ok := cert.PrivateKey.(*rsa.PrivateKey)
+		if !ok {
+			err = errors.New("crypto/tls: private key type does not match public key type")
+			return
+		}
+		if pub.N.Cmp(priv.N) != 0 {
+			err = errors.New("crypto/tls: private key does not match public key")
+			return
+		}
+	case *ecdsa.PublicKey:
+		priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
+		if !ok {
+			err = errors.New("crypto/tls: private key type does not match public key type")
+			return
+
+		}
+		if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
+			err = errors.New("crypto/tls: private key does not match public key")
+			return
+		}
+	default:
+		err = errors.New("crypto/tls: unknown public key algorithm")
 		return
 	}
 
 	return
 }
+
+// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
+// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
+// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
+func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
+	if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
+		return key, nil
+	}
+	if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
+		switch key := key.(type) {
+		case *rsa.PrivateKey, *ecdsa.PrivateKey:
+			return key, nil
+		default:
+			return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping")
+		}
+	}
+	if key, err := x509.ParseECPrivateKey(der); err == nil {
+		return key, nil
+	}
+
+	return nil, errors.New("crypto/tls: failed to parse private key")
+}
diff --git a/src/pkg/crypto/tls/tls_test.go b/src/pkg/crypto/tls/tls_test.go
new file mode 100644
index 0000000..3822901
--- /dev/null
+++ b/src/pkg/crypto/tls/tls_test.go
@@ -0,0 +1,107 @@
+// 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 tls
+
+import (
+	"testing"
+)
+
+var rsaCertPEM = `-----BEGIN CERTIFICATE-----
+MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ
+hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa
+rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv
+zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW
+r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V
+-----END CERTIFICATE-----
+`
+
+var rsaKeyPEM = `-----BEGIN RSA PRIVATE KEY-----
+MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
+k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
+6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
+MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
+SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
+xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
+D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
+-----END RSA PRIVATE KEY-----
+`
+
+// keyPEM is the same as rsaKeyPEM, but declares itself as just
+// "PRIVATE KEY", not "RSA PRIVATE KEY".  http://golang.org/issue/4477
+var keyPEM = `-----BEGIN PRIVATE KEY-----
+MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
+k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
+6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
+MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
+SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
+xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
+D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
+-----END PRIVATE KEY-----
+`
+
+var ecdsaCertPEM = `-----BEGIN CERTIFICATE-----
+MIIB/jCCAWICCQDscdUxw16XFDAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQwHhcNMTIxMTE0MTI0MDQ4WhcNMTUxMTE0MTI0MDQ4WjBFMQswCQYDVQQG
+EwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lk
+Z2l0cyBQdHkgTHRkMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBY9+my9OoeSUR
+lDQdV/x8LsOuLilthhiS1Tz4aGDHIPwC1mlvnf7fg5lecYpMCrLLhauAc1UJXcgl
+01xoLuzgtAEAgv2P/jgytzRSpUYvgLBt1UA0leLYBy6mQQbrNEuqT3INapKIcUv8
+XxYP0xMEUksLPq6Ca+CRSqTtrd/23uTnapkwCQYHKoZIzj0EAQOBigAwgYYCQXJo
+A7Sl2nLVf+4Iu/tAX/IF4MavARKC4PPHK3zfuGfPR3oCCcsAoz3kAzOeijvd0iXb
+H5jBImIxPL4WxQNiBTexAkF8D1EtpYuWdlVQ80/h/f4pBcGiXPqX5h2PQSQY7hP1
++jwM1FGS4fREIOvlBYr/SzzQRtwrvrzGYxDEDbsC0ZGRnA==
+-----END CERTIFICATE-----
+`
+
+var ecdsaKeyPEM = `-----BEGIN EC PARAMETERS-----
+BgUrgQQAIw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBrsoKp0oqcv6/JovJJDoDVSGWdirrkgCWxrprGlzB9o0X8fV675X0
+NwuBenXFfeZvVcwluO7/Q9wkYoPd/t3jGImgBwYFK4EEACOhgYkDgYYABAFj36bL
+06h5JRGUNB1X/Hwuw64uKW2GGJLVPPhoYMcg/ALWaW+d/t+DmV5xikwKssuFq4Bz
+VQldyCXTXGgu7OC0AQCC/Y/+ODK3NFKlRi+AsG3VQDSV4tgHLqZBBus0S6pPcg1q
+kohxS/xfFg/TEwRSSws+roJr4JFKpO2t3/be5OdqmQ==
+-----END EC PRIVATE KEY-----
+`
+
+var keyPairTests = []struct {
+	algo string
+	cert string
+	key  string
+}{
+	{"ECDSA", ecdsaCertPEM, ecdsaKeyPEM},
+	{"RSA", rsaCertPEM, rsaKeyPEM},
+	{"RSA-untyped", rsaCertPEM, keyPEM}, // golang.org/issue/4477
+}
+
+func TestX509KeyPair(t *testing.T) {
+	var pem []byte
+	for _, test := range keyPairTests {
+		pem = []byte(test.cert + test.key)
+		if _, err := X509KeyPair(pem, pem); err != nil {
+			t.Errorf("Failed to load %s cert followed by %s key: %s", test.algo, test.algo, err)
+		}
+		pem = []byte(test.key + test.cert)
+		if _, err := X509KeyPair(pem, pem); err != nil {
+			t.Errorf("Failed to load %s key followed by %s cert: %s", test.algo, test.algo, err)
+		}
+	}
+}
+
+func TestX509MixedKeyPair(t *testing.T) {
+	if _, err := X509KeyPair([]byte(rsaCertPEM), []byte(ecdsaKeyPEM)); err == nil {
+		t.Error("Load of RSA certificate succeeded with ECDSA private key")
+	}
+	if _, err := X509KeyPair([]byte(ecdsaCertPEM), []byte(rsaKeyPEM)); err == nil {
+		t.Error("Load of ECDSA certificate succeeded with RSA private key")
+	}
+}
diff --git a/src/pkg/crypto/x509/cert_pool.go b/src/pkg/crypto/x509/cert_pool.go
index 616a0b3..505f4d4 100644
--- a/src/pkg/crypto/x509/cert_pool.go
+++ b/src/pkg/crypto/x509/cert_pool.go
@@ -103,7 +103,7 @@ func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
 }
 
 // Subjects returns a list of the DER-encoded subjects of
-// all of the certificates in the pool. 
+// all of the certificates in the pool.
 func (s *CertPool) Subjects() (res [][]byte) {
 	res = make([][]byte, len(s.certs))
 	for i, c := range s.certs {
diff --git a/src/pkg/crypto/x509/pem_decrypt.go b/src/pkg/crypto/x509/pem_decrypt.go
new file mode 100644
index 0000000..194c81b
--- /dev/null
+++ b/src/pkg/crypto/x509/pem_decrypt.go
@@ -0,0 +1,233 @@
+// 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 x509
+
+// RFC 1423 describes the encryption of PEM blocks. The algorithm used to
+// generate a key from the password was derived by looking at the OpenSSL
+// implementation.
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/des"
+	"crypto/md5"
+	"encoding/hex"
+	"encoding/pem"
+	"errors"
+	"io"
+	"strings"
+)
+
+type PEMCipher int
+
+// Possible values for the EncryptPEMBlock encryption algorithm.
+const (
+	_ PEMCipher = iota
+	PEMCipherDES
+	PEMCipher3DES
+	PEMCipherAES128
+	PEMCipherAES192
+	PEMCipherAES256
+)
+
+// rfc1423Algo holds a method for enciphering a PEM block.
+type rfc1423Algo struct {
+	cipher     PEMCipher
+	name       string
+	cipherFunc func(key []byte) (cipher.Block, error)
+	keySize    int
+	blockSize  int
+}
+
+// rfc1423Algos holds a slice of the possible ways to encrypt a PEM
+// block.  The ivSize numbers were taken from the OpenSSL source.
+var rfc1423Algos = []rfc1423Algo{{
+	cipher:     PEMCipherDES,
+	name:       "DES-CBC",
+	cipherFunc: des.NewCipher,
+	keySize:    8,
+	blockSize:  des.BlockSize,
+}, {
+	cipher:     PEMCipher3DES,
+	name:       "DES-EDE3-CBC",
+	cipherFunc: des.NewTripleDESCipher,
+	keySize:    24,
+	blockSize:  des.BlockSize,
+}, {
+	cipher:     PEMCipherAES128,
+	name:       "AES-128-CBC",
+	cipherFunc: aes.NewCipher,
+	keySize:    16,
+	blockSize:  aes.BlockSize,
+}, {
+	cipher:     PEMCipherAES192,
+	name:       "AES-192-CBC",
+	cipherFunc: aes.NewCipher,
+	keySize:    24,
+	blockSize:  aes.BlockSize,
+}, {
+	cipher:     PEMCipherAES256,
+	name:       "AES-256-CBC",
+	cipherFunc: aes.NewCipher,
+	keySize:    32,
+	blockSize:  aes.BlockSize,
+},
+}
+
+// deriveKey uses a key derivation function to stretch the password into a key
+// with the number of bits our cipher requires. This algorithm was derived from
+// the OpenSSL source.
+func (c rfc1423Algo) deriveKey(password, salt []byte) []byte {
+	hash := md5.New()
+	out := make([]byte, c.keySize)
+	var digest []byte
+
+	for i := 0; i < len(out); i += len(digest) {
+		hash.Reset()
+		hash.Write(digest)
+		hash.Write(password)
+		hash.Write(salt)
+		digest = hash.Sum(digest[:0])
+		copy(out[i:], digest)
+	}
+	return out
+}
+
+// IsEncryptedPEMBlock returns if the PEM block is password encrypted.
+func IsEncryptedPEMBlock(b *pem.Block) bool {
+	_, ok := b.Headers["DEK-Info"]
+	return ok
+}
+
+// IncorrectPasswordError is returned when an incorrect password is detected.
+var IncorrectPasswordError = errors.New("x509: decryption password incorrect")
+
+// DecryptPEMBlock takes a password encrypted PEM block and the password used to
+// encrypt it and returns a slice of decrypted DER encoded bytes. It inspects
+// the DEK-Info header to determine the algorithm used for decryption. If no
+// DEK-Info header is present, an error is returned. If an incorrect password
+// is detected an IncorrectPasswordError is returned.
+func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) {
+	dek, ok := b.Headers["DEK-Info"]
+	if !ok {
+		return nil, errors.New("x509: no DEK-Info header in block")
+	}
+
+	idx := strings.Index(dek, ",")
+	if idx == -1 {
+		return nil, errors.New("x509: malformed DEK-Info header")
+	}
+
+	mode, hexIV := dek[:idx], dek[idx+1:]
+	ciph := cipherByName(mode)
+	if ciph == nil {
+		return nil, errors.New("x509: unknown encryption mode")
+	}
+	iv, err := hex.DecodeString(hexIV)
+	if err != nil {
+		return nil, err
+	}
+	if len(iv) != ciph.blockSize {
+		return nil, errors.New("x509: incorrect IV size")
+	}
+
+	// Based on the OpenSSL implementation. The salt is the first 8 bytes
+	// of the initialization vector.
+	key := ciph.deriveKey(password, iv[:8])
+	block, err := ciph.cipherFunc(key)
+	if err != nil {
+		return nil, err
+	}
+
+	data := make([]byte, len(b.Bytes))
+	dec := cipher.NewCBCDecrypter(block, iv)
+	dec.CryptBlocks(data, b.Bytes)
+
+	// Blocks are padded using a scheme where the last n bytes of padding are all
+	// equal to n. It can pad from 1 to blocksize bytes inclusive. See RFC 1423.
+	// For example:
+	//	[x y z 2 2]
+	//	[x y 7 7 7 7 7 7 7]
+	// If we detect a bad padding, we assume it is an invalid password.
+	dlen := len(data)
+	if dlen == 0 || dlen%ciph.blockSize != 0 {
+		return nil, errors.New("x509: invalid padding")
+	}
+	last := int(data[dlen-1])
+	if dlen < last {
+		return nil, IncorrectPasswordError
+	}
+	if last == 0 || last > ciph.blockSize {
+		return nil, IncorrectPasswordError
+	}
+	for _, val := range data[dlen-last:] {
+		if int(val) != last {
+			return nil, IncorrectPasswordError
+		}
+	}
+	return data[:dlen-last], nil
+}
+
+// EncryptPEMBlock returns a PEM block of the specified type holding the
+// given DER-encoded data encrypted with the specified algorithm and
+// password.
+func EncryptPEMBlock(rand io.Reader, blockType string, data, password []byte, alg PEMCipher) (*pem.Block, error) {
+	ciph := cipherByKey(alg)
+	if ciph == nil {
+		return nil, errors.New("x509: unknown encryption mode")
+	}
+	iv := make([]byte, ciph.blockSize)
+	if _, err := io.ReadFull(rand, iv); err != nil {
+		return nil, errors.New("x509: cannot generate IV: " + err.Error())
+	}
+	// The salt is the first 8 bytes of the initialization vector,
+	// matching the key derivation in DecryptPEMBlock.
+	key := ciph.deriveKey(password, iv[:8])
+	block, err := ciph.cipherFunc(key)
+	if err != nil {
+		return nil, err
+	}
+	enc := cipher.NewCBCEncrypter(block, iv)
+	pad := ciph.blockSize - len(data)%ciph.blockSize
+	encrypted := make([]byte, len(data), len(data)+pad)
+	// We could save this copy by encrypting all the whole blocks in
+	// the data separately, but it doesn't seem worth the additional
+	// code.
+	copy(encrypted, data)
+	// See RFC 1423, section 1.1
+	for i := 0; i < pad; i++ {
+		encrypted = append(encrypted, byte(pad))
+	}
+	enc.CryptBlocks(encrypted, encrypted)
+
+	return &pem.Block{
+		Type: blockType,
+		Headers: map[string]string{
+			"Proc-Type": "4,ENCRYPTED",
+			"DEK-Info":  ciph.name + "," + hex.EncodeToString(iv),
+		},
+		Bytes: encrypted,
+	}, nil
+}
+
+func cipherByName(name string) *rfc1423Algo {
+	for i := range rfc1423Algos {
+		alg := &rfc1423Algos[i]
+		if alg.name == name {
+			return alg
+		}
+	}
+	return nil
+}
+
+func cipherByKey(key PEMCipher) *rfc1423Algo {
+	for i := range rfc1423Algos {
+		alg := &rfc1423Algos[i]
+		if alg.cipher == key {
+			return alg
+		}
+	}
+	return nil
+}
diff --git a/src/pkg/crypto/x509/pem_decrypt_test.go b/src/pkg/crypto/x509/pem_decrypt_test.go
new file mode 100644
index 0000000..59ba6f9
--- /dev/null
+++ b/src/pkg/crypto/x509/pem_decrypt_test.go
@@ -0,0 +1,223 @@
+// 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 x509
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/base64"
+	"encoding/pem"
+	"testing"
+)
+
+func TestDecrypt(t *testing.T) {
+	for i, data := range testData {
+		t.Logf("test %d. %s", i, data.kind)
+		block, rest := pem.Decode(data.pemData)
+		if len(rest) > 0 {
+			t.Error("extra data")
+		}
+		der, err := DecryptPEMBlock(block, data.password)
+		if err != nil {
+			t.Error("decrypt failed: ", err)
+			continue
+		}
+		if _, err := ParsePKCS1PrivateKey(der); err != nil {
+			t.Error("invalid private key: ", err)
+		}
+		plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
+		if err != nil {
+			t.Fatal("cannot decode test DER data: ", err)
+		}
+		if !bytes.Equal(der, plainDER) {
+			t.Error("data mismatch")
+		}
+	}
+}
+
+func TestEncrypt(t *testing.T) {
+	for i, data := range testData {
+		t.Logf("test %d. %s", i, data.kind)
+		plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
+		if err != nil {
+			t.Fatal("cannot decode test DER data: ", err)
+		}
+		password := []byte("kremvax1")
+		block, err := EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", plainDER, password, data.kind)
+		if err != nil {
+			t.Error("encrypt: ", err)
+			continue
+		}
+		if !IsEncryptedPEMBlock(block) {
+			t.Error("PEM block does not appear to be encrypted")
+		}
+		if block.Type != "RSA PRIVATE KEY" {
+			t.Errorf("unexpected block type; got %q want %q", block.Type, "RSA PRIVATE KEY")
+		}
+		if block.Headers["Proc-Type"] != "4,ENCRYPTED" {
+			t.Errorf("block does not have correct Proc-Type header")
+		}
+		der, err := DecryptPEMBlock(block, password)
+		if err != nil {
+			t.Error("decrypt: ", err)
+			continue
+		}
+		if !bytes.Equal(der, plainDER) {
+			t.Errorf("data mismatch")
+		}
+	}
+}
+
+var testData = []struct {
+	kind     PEMCipher
+	password []byte
+	pemData  []byte
+	plainDER string
+}{
+	{
+		kind:     PEMCipherDES,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CBC,34F09A4FC8DE22B5
+
+WXxy8kbZdiZvANtKvhmPBLV7eVFj2A5z6oAxvI9KGyhG0ZK0skfnt00C24vfU7m5
+ICXeoqP67lzJ18xCzQfHjDaBNs53DSDT+Iz4e8QUep1xQ30+8QKX2NA2coee3nwc
+6oM1cuvhNUDemBH2i3dKgMVkfaga0zQiiOq6HJyGSncCMSruQ7F9iWEfRbFcxFCx
+qtHb1kirfGKEtgWTF+ynyco6+2gMXNu70L7nJcnxnV/RLFkHt7AUU1yrclxz7eZz
+XOH9VfTjb52q/I8Suozq9coVQwg4tXfIoYUdT//O+mB7zJb9HI9Ps77b9TxDE6Gm
+4C9brwZ3zg2vqXcwwV6QRZMtyll9rOpxkbw6NPlpfBqkc3xS51bbxivbO/Nve4KD
+r12ymjFNF4stXCfJnNqKoZ50BHmEEUDu5Wb0fpVn82XrGw7CYc4iug==
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MIIBPAIBAAJBAPASZe+tCPU6p80AjHhDkVsLYa51D35e/YGa8QcZyooeZM8EHozo
+KD0fNiKI+53bHdy07N+81VQ8/ejPcRoXPlsCAwEAAQJBAMTxIuSq27VpR+zZ7WJf
+c6fvv1OBvpMZ0/d1pxL/KnOAgq2rD5hDtk9b0LGhTPgQAmrrMTKuSeGoIuYE+gKQ
+QvkCIQD+GC1m+/do+QRurr0uo46Kx1LzLeSCrjBk34wiOp2+dwIhAPHfTLRXS2fv
+7rljm0bYa4+eDZpz+E8RcXEgzhhvcQQ9AiAI5eHZJGOyml3MXnQjiPi55WcDOw0w
+glcRgT6QCEtz2wIhANSyqaFtosIkHKqrDUGfz/bb5tqMYTAnBruVPaf/WEOBAiEA
+9xORWeRG1tRpso4+dYy4KdDkuLPIO01KY6neYGm3BCM=`,
+	},
+	{
+		kind:     PEMCipher3DES,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C1F4A6A03682C2C7
+
+0JqVdBEH6iqM7drTkj+e2W/bE3LqakaiWhb9WUVonFkhyu8ca/QzebY3b5gCvAZQ
+YwBvDcT/GHospKqPx+cxDHJNsUASDZws6bz8ZXWJGwZGExKzr0+Qx5fgXn44Ms3x
+8g1ENFuTXtxo+KoNK0zuAMAqp66Llcds3Fjl4XR18QaD0CrVNAfOdgATWZm5GJxk
+Fgx5f84nT+/ovvreG+xeOzWgvtKo0UUZVrhGOgfKLpa57adumcJ6SkUuBtEFpZFB
+ldw5w7WC7d13x2LsRkwo8ZrDKgIV+Y9GNvhuCCkTzNP0V3gNeJpd201HZHR+9n3w
+3z0VjR/MGqsfcy1ziEWMNOO53At3zlG6zP05aHMnMcZoVXadEK6L1gz++inSSDCq
+gI0UJP4e3JVB7AkgYymYAwiYALAkoEIuanxoc50njJk=
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MIIBOwIBAAJBANOCXKdoNS/iP/MAbl9cf1/SF3P+Ns7ZeNL27CfmDh0O6Zduaax5
+NBiumd2PmjkaCu7lQ5JOibHfWn+xJsc3kw0CAwEAAQJANX/W8d1Q/sCqzkuAn4xl
+B5a7qfJWaLHndu1QRLNTRJPn0Ee7OKJ4H0QKOhQM6vpjRrz+P2u9thn6wUxoPsef
+QQIhAP/jCkfejFcy4v15beqKzwz08/tslVjF+Yq41eJGejmxAiEA05pMoqfkyjcx
+fyvGhpoOyoCp71vSGUfR2I9CR65oKh0CIC1Msjs66LlfJtQctRq6bCEtFCxEcsP+
+eEjYo/Sk6WphAiEAxpgWPMJeU/shFT28gS+tmhjPZLpEoT1qkVlC14u0b3ECIQDX
+tZZZxCtPAm7shftEib0VU77Lk8MsXJcx2C4voRsjEw==`,
+	},
+	{
+		kind:     PEMCipherAES128,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,D4492E793FC835CC038A728ED174F78A
+
+EyfQSzXSjv6BaNH+NHdXRlkHdimpF9izWlugVJAPApgXrq5YldPe2aGIOFXyJ+QE
+ZIG20DYqaPzJRjTEbPNZ6Es0S2JJ5yCpKxwJuDkgJZKtF39Q2i36JeGbSZQIuWJE
+GZbBpf1jDH/pr0iGonuAdl2PCCZUiy+8eLsD2tyviHUkFLOB+ykYoJ5t8ngZ/B6D
+33U43LLb7+9zD4y3Q9OVHqBFGyHcxCY9+9Qh4ZnFp7DTf6RY5TNEvE3s4g6aDpBs
+3NbvRVvYTgs8K9EPk4K+5R+P2kD8J8KvEIGxVa1vz8QoCJ/jr7Ka2rvNgPCex5/E
+080LzLHPCrXKdlr/f50yhNWq08ZxMWQFkui+FDHPDUaEELKAXV8/5PDxw80Rtybo
+AVYoCVIbZXZCuCO81op8UcOgEpTtyU5Lgh3Mw5scQL0=
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MIIBOgIBAAJBAMBlj5FxYtqbcy8wY89d/S7n0+r5MzD9F63BA/Lpl78vQKtdJ5dT
+cDGh/rBt1ufRrNp0WihcmZi7Mpl/3jHjiWECAwEAAQJABNOHYnKhtDIqFYj1OAJ3
+k3GlU0OlERmIOoeY/cL2V4lgwllPBEs7r134AY4wMmZSBUj8UR/O4SNO668ElKPE
+cQIhAOuqY7/115x5KCdGDMWi+jNaMxIvI4ETGwV40ykGzqlzAiEA0P9oEC3m9tHB
+kbpjSTxaNkrXxDgdEOZz8X0uOUUwHNsCIAwzcSCiGLyYJTULUmP1ESERfW1mlV78
+XzzESaJpIM/zAiBQkSTcl9VhcJreQqvjn5BnPZLP4ZHS4gPwJAGdsj5J4QIhAOVR
+B3WlRNTXR2WsJ5JdByezg9xzdXzULqmga0OE339a`,
+	},
+	{
+		kind:     PEMCipherAES192,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,E2C9FB02BCA23ADE1829F8D8BC5F5369
+
+cqVslvHqDDM6qwU6YjezCRifXmKsrgEev7ng6Qs7UmDJOpHDgJQZI9fwMFUhIyn5
+FbCu1SHkLMW52Ld3CuEqMnzWMlhPrW8tFvUOrMWPYSisv7nNq88HobZEJcUNL2MM
+Y15XmHW6IJwPqhKyLHpWXyOCVEh4ODND2nV15PCoi18oTa475baxSk7+1qH7GuIs
+Rb7tshNTMqHbCpyo9Rn3UxeFIf9efdl8YLiMoIqc7J8E5e9VlbeQSdLMQOgDAQJG
+ReUtTw8exmKsY4gsSjhkg5uiw7/ZB1Ihto0qnfQJgjGc680qGkT1d6JfvOfeYAk6
+xn5RqS/h8rYAYm64KnepfC9vIujo4NqpaREDmaLdX5MJPQ+SlytITQvgUsUq3q/t
+Ss85xjQEZH3hzwjQqdJvmA4hYP6SUjxYpBM+02xZ1Xw=
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MIIBOwIBAAJBAMGcRrZiNNmtF20zyS6MQ7pdGx17aFDl+lTl+qnLuJRUCMUG05xs
+OmxmL/O1Qlf+bnqR8Bgg65SfKg21SYuLhiMCAwEAAQJBAL94uuHyO4wux2VC+qpj
+IzPykjdU7XRcDHbbvksf4xokSeUFjjD3PB0Qa83M94y89ZfdILIqS9x5EgSB4/lX
+qNkCIQD6cCIqLfzq/lYbZbQgAAjpBXeQVYsbvVtJrPrXJAlVVQIhAMXpDKMeFPMn
+J0g2rbx1gngx0qOa5r5iMU5w/noN4W2XAiBjf+WzCG5yFvazD+dOx3TC0A8+4x3P
+uZ3pWbaXf5PNuQIgAcdXarvhelH2w2piY1g3BPeFqhzBSCK/yLGxR82KIh8CIQDD
++qGKsd09NhQ/G27y/DARzOYtml1NvdmCQAgsDIIOLA==`,
+	},
+	{
+		kind:     PEMCipherAES256,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,8E7ED5CD731902CE938957A886A5FFBD
+
+4Mxr+KIzRVwoOP0wwq6caSkvW0iS+GE2h2Ov/u+n9ZTMwL83PRnmjfjzBgfRZLVf
+JFPXxUK26kMNpIdssNnqGOds+DhB+oSrsNKoxgxSl5OBoYv9eJTVYm7qOyAFIsjr
+DRKAcjYCmzfesr7PVTowwy0RtHmYwyXMGDlAzzZrEvaiySFFmMyKKvtoavwaFoc7
+Pz3RZScwIuubzTGJ1x8EzdffYOsdCa9Mtgpp3L136+23dOd6L/qK2EG2fzrJSHs/
+2XugkleBFSMKzEp9mxXKRfa++uidQvMZTFLDK9w5YjrRvMBo/l2BoZIsq0jAIE1N
+sv5Z/KwlX+3MDEpPQpUwGPlGGdLnjI3UZ+cjgqBcoMiNc6HfgbBgYJSU6aDSHuCk
+clCwByxWkBNgJ2GrkwNrF26v+bGJJJNR4SKouY1jQf0=
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MIIBOgIBAAJBAKy3GFkstoCHIEeUU/qO8207m8WSrjksR+p9B4tf1w5k+2O1V/GY
+AQ5WFCApItcOkQe/I0yZZJk/PmCqMzSxrc8CAwEAAQJAOCAz0F7AW9oNelVQSP8F
+Sfzx7O1yom+qWyAQQJF/gFR11gpf9xpVnnyu1WxIRnDUh1LZwUsjwlDYb7MB74id
+oQIhANPcOiLwOPT4sIUpRM5HG6BF1BI7L77VpyGVk8xNP7X/AiEA0LMHZtk4I+lJ
+nClgYp4Yh2JZ1Znbu7IoQMCEJCjwKDECIGd8Dzm5tViTkUW6Hs3Tlf73nNs65duF
+aRnSglss8I3pAiEAonEnKruawgD8RavDFR+fUgmQiPz4FnGGeVgfwpGG1JECIBYq
+PXHYtPqxQIbD2pScR5qum7iGUh11lEUPkmt+2uqS`,
+	},
+	{
+		// generated with:
+		// openssl genrsa -aes128 -passout pass:asdf -out server.orig.key 128
+		kind:     PEMCipherAES128,
+		password: []byte("asdf"),
+		pemData: []byte(`
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7
+
+6ei/MlytjE0FFgZOGQ+jrwomKfpl8kdefeE0NSt/DMRrw8OacHAzBNi3pPEa0eX3
+eND9l7C9meCirWovjj9QWVHrXyugFuDIqgdhQ8iHTgCfF3lrmcttVrbIfMDw+smD
+hTP8O1mS/MHl92NE0nhv0w==
+-----END RSA PRIVATE KEY-----`),
+		plainDER: `
+MGMCAQACEQC6ssxmYuauuHGOCDAI54RdAgMBAAECEQCWIn6Yv2O+kBcDF7STctKB
+AgkA8SEfu/2i3g0CCQDGNlXbBHX7kQIIK3Ww5o0cYbECCQDCimPb0dYGsQIIeQ7A
+jryIst8=`,
+	},
+}
diff --git a/src/pkg/crypto/x509/pkcs8.go b/src/pkg/crypto/x509/pkcs8.go
index 4d8e051..30caacb 100644
--- a/src/pkg/crypto/x509/pkcs8.go
+++ b/src/pkg/crypto/x509/pkcs8.go
@@ -11,8 +11,9 @@ import (
 	"fmt"
 )
 
-// pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See 
-// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn.
+// pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See
+// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn
+// and RFC5208.
 type pkcs8 struct {
 	Version    int
 	Algo       pkix.AlgorithmIdentifier
@@ -21,19 +22,32 @@ type pkcs8 struct {
 }
 
 // ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key. See
-// http://www.rsa.com/rsalabs/node.asp?id=2130
+// http://www.rsa.com/rsalabs/node.asp?id=2130 and RFC5208.
 func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
 	var privKey pkcs8
 	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
 		return nil, err
 	}
 	switch {
-	case privKey.Algo.Algorithm.Equal(oidRSA):
+	case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA):
 		key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
 		if err != nil {
 			return nil, errors.New("crypto/x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
 		}
 		return key, nil
+
+	case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA):
+		bytes := privKey.Algo.Parameters.FullBytes
+		namedCurveOID := new(asn1.ObjectIdentifier)
+		if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
+			namedCurveOID = nil
+		}
+		key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
+		if err != nil {
+			return nil, errors.New("crypto/x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
+		}
+		return key, nil
+
 	default:
 		return nil, fmt.Errorf("crypto/x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
 	}
diff --git a/src/pkg/crypto/x509/pkcs8_test.go b/src/pkg/crypto/x509/pkcs8_test.go
index 372005f..4114efd 100644
--- a/src/pkg/crypto/x509/pkcs8_test.go
+++ b/src/pkg/crypto/x509/pkcs8_test.go
@@ -9,12 +9,20 @@ import (
 	"testing"
 )
 
-var pkcs8PrivateKeyHex = `30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031`
+var pkcs8RSAPrivateKeyHex = `30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031`
+
+// Generated using:
+//   openssl ecparam -genkey -name secp521r1 | openssl pkcs8 -topk8 -nocrypt
+var pkcs8ECPrivateKeyHex = `3081ed020100301006072a8648ce3d020106052b810400230481d53081d20201010441850d81618c5da1aec74c2eed608ba816038506975e6427237c2def150c96a3b13efbfa1f89f1be15cdf4d0ac26422e680e65a0ddd4ad3541ad76165fbf54d6e34ba18189038186000400da97bcedba1eb6d30aeb93c9f9a1454598fa47278df27d6f60ea73eb672d8dc528a9b67885b5b5dcef93c9824f7449ab512ee6a27e76142f56b94b474cfd697e810046c8ca70419365245c1d7d44d0db82c334073835d002232714548abbae6e5700f5ef315ee08b929d8581383dcf2d1c98c2f8a9fccbf79c9579f7b2fd8a90115ac2`
 
 func TestPKCS8(t *testing.T) {
-	derBytes, _ := hex.DecodeString(pkcs8PrivateKeyHex)
-	_, err := ParsePKCS8PrivateKey(derBytes)
-	if err != nil {
-		t.Errorf("failed to decode PKCS8 key: %s", err)
+	derBytes, _ := hex.DecodeString(pkcs8RSAPrivateKeyHex)
+	if _, err := ParsePKCS8PrivateKey(derBytes); err != nil {
+		t.Errorf("failed to decode PKCS8 with RSA private key: %s", err)
+	}
+
+	derBytes, _ = hex.DecodeString(pkcs8ECPrivateKeyHex)
+	if _, err := ParsePKCS8PrivateKey(derBytes); err != nil {
+		t.Errorf("failed to decode PKCS8 with EC private key: %s", err)
 	}
 }
diff --git a/src/pkg/crypto/x509/root_darwin.go b/src/pkg/crypto/x509/root_darwin.go
index 0f99581..ad3bfb4 100644
--- a/src/pkg/crypto/x509/root_darwin.go
+++ b/src/pkg/crypto/x509/root_darwin.go
@@ -70,11 +70,12 @@ func initSystemRoots() {
 
 	var data C.CFDataRef = nil
 	err := C.FetchPEMRoots(&data)
-	if err != -1 {
-		defer C.CFRelease(C.CFTypeRef(data))
-		buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
-		roots.AppendCertsFromPEM(buf)
+	if err == -1 {
+		return
 	}
 
+	defer C.CFRelease(C.CFTypeRef(data))
+	buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
+	roots.AppendCertsFromPEM(buf)
 	systemRoots = roots
 }
diff --git a/src/pkg/crypto/x509/root_plan9.go b/src/pkg/crypto/x509/root_plan9.go
new file mode 100644
index 0000000..9965caa
--- /dev/null
+++ b/src/pkg/crypto/x509/root_plan9.go
@@ -0,0 +1,33 @@
+// 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 plan9
+
+package x509
+
+import "io/ioutil"
+
+// Possible certificate files; stop after finding one.
+var certFiles = []string{
+	"/sys/lib/tls/ca.pem",
+}
+
+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
+	return nil, nil
+}
+
+func initSystemRoots() {
+	roots := NewCertPool()
+	for _, file := range certFiles {
+		data, err := ioutil.ReadFile(file)
+		if err == nil {
+			roots.AppendCertsFromPEM(data)
+			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_stub.go b/src/pkg/crypto/x509/root_stub.go
index 5680041..4c742cc 100644
--- a/src/pkg/crypto/x509/root_stub.go
+++ b/src/pkg/crypto/x509/root_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 plan9 darwin,!cgo
+// +build darwin,!cgo
 
 package x509
 
@@ -11,5 +11,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
 }
 
 func initSystemRoots() {
-	systemRoots = NewCertPool()
 }
diff --git a/src/pkg/crypto/x509/root_unix.go b/src/pkg/crypto/x509/root_unix.go
index 76e79f4..1b25a94 100644
--- a/src/pkg/crypto/x509/root_unix.go
+++ b/src/pkg/crypto/x509/root_unix.go
@@ -27,9 +27,11 @@ func initSystemRoots() {
 		data, err := ioutil.ReadFile(file)
 		if err == nil {
 			roots.AppendCertsFromPEM(data)
-			break
+			systemRoots = roots
+			return
 		}
 	}
 
-	systemRoots = roots
+	// 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/pkg/crypto/x509/root_windows.go
index 7e8f2af..e8f70a4 100644
--- a/src/pkg/crypto/x509/root_windows.go
+++ b/src/pkg/crypto/x509/root_windows.go
@@ -98,9 +98,13 @@ func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) e
 // checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for
 // use as a certificate chain for a SSL/TLS server.
 func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error {
+	servernamep, err := syscall.UTF16PtrFromString(opts.DNSName)
+	if err != nil {
+		return err
+	}
 	sslPara := &syscall.SSLExtraCertChainPolicyPara{
 		AuthType:   syscall.AUTHTYPE_SERVER,
-		ServerName: syscall.StringToUTF16Ptr(opts.DNSName),
+		ServerName: servernamep,
 	}
 	sslPara.Size = uint32(unsafe.Sizeof(*sslPara))
 
@@ -110,7 +114,7 @@ func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContex
 	para.Size = uint32(unsafe.Sizeof(*para))
 
 	status := syscall.CertChainPolicyStatus{}
-	err := syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status)
+	err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status)
 	if err != nil {
 		return err
 	}
@@ -222,5 +226,4 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
 }
 
 func initSystemRoots() {
-	systemRoots = NewCertPool()
 }
diff --git a/src/pkg/crypto/x509/sec1.go b/src/pkg/crypto/x509/sec1.go
new file mode 100644
index 0000000..8a2840f
--- /dev/null
+++ b/src/pkg/crypto/x509/sec1.go
@@ -0,0 +1,69 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x509
+
+import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"encoding/asn1"
+	"errors"
+	"fmt"
+	"math/big"
+)
+
+const ecPrivKeyVersion = 1
+
+// ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure.
+// References:
+//   RFC5915
+//   SEC1 - http://www.secg.org/download/aid-780/sec1-v2.pdf
+// Per RFC5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in
+// most cases it is not.
+type ecPrivateKey struct {
+	Version       int
+	PrivateKey    []byte
+	NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
+	PublicKey     asn1.BitString        `asn1:"optional,explicit,tag:1"`
+}
+
+// ParseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
+func ParseECPrivateKey(der []byte) (key *ecdsa.PrivateKey, err error) {
+	return parseECPrivateKey(nil, der)
+}
+
+// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
+// The OID for the named curve may be provided from another source (such as
+// the PKCS8 container) - if it is provided then use this instead of the OID
+// that may exist in the EC private key structure.
+func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) {
+	var privKey ecPrivateKey
+	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
+		return nil, errors.New("crypto/x509: failed to parse EC private key: " + err.Error())
+	}
+	if privKey.Version != ecPrivKeyVersion {
+		return nil, fmt.Errorf("crypto/x509: unknown EC private key version %d", privKey.Version)
+	}
+
+	var curve elliptic.Curve
+	if namedCurveOID != nil {
+		curve = namedCurveFromOID(*namedCurveOID)
+	} else {
+		curve = namedCurveFromOID(privKey.NamedCurveOID)
+	}
+	if curve == nil {
+		return nil, errors.New("crypto/x509: unknown elliptic curve")
+	}
+
+	k := new(big.Int).SetBytes(privKey.PrivateKey)
+	if k.Cmp(curve.Params().N) >= 0 {
+		return nil, errors.New("crypto/x509: invalid elliptic curve private key value")
+	}
+	priv := new(ecdsa.PrivateKey)
+	priv.Curve = curve
+	priv.D = k
+	priv.X, priv.Y = curve.ScalarBaseMult(privKey.PrivateKey)
+
+	return priv, nil
+}
diff --git a/src/pkg/crypto/x509/sec1_test.go b/src/pkg/crypto/x509/sec1_test.go
new file mode 100644
index 0000000..7135699
--- /dev/null
+++ b/src/pkg/crypto/x509/sec1_test.go
@@ -0,0 +1,22 @@
+// 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 x509
+
+import (
+	"encoding/hex"
+	"testing"
+)
+
+// Generated using:
+//   openssl ecparam -genkey -name secp384r1 -outform PEM
+var ecPrivateKeyHex = `3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50`
+
+func TestParseECPrivateKey(t *testing.T) {
+	derBytes, _ := hex.DecodeString(ecPrivateKeyHex)
+	_, err := ParseECPrivateKey(derBytes)
+	if err != nil {
+		t.Errorf("failed to decode EC private key: %s", err)
+	}
+}
diff --git a/src/pkg/crypto/x509/verify.go b/src/pkg/crypto/x509/verify.go
index 307c5ef..b29ddbc 100644
--- a/src/pkg/crypto/x509/verify.go
+++ b/src/pkg/crypto/x509/verify.go
@@ -5,6 +5,7 @@
 package x509
 
 import (
+	"net"
 	"runtime"
 	"strings"
 	"time"
@@ -27,6 +28,9 @@ const (
 	// TooManyIntermediates results when a path length constraint is
 	// violated.
 	TooManyIntermediates
+	// IncompatibleUsage results when the certificate's key usage indicates
+	// that it may only be used for a different purpose.
+	IncompatibleUsage
 )
 
 // CertificateInvalidError results when an odd error occurs. Users of this
@@ -39,13 +43,15 @@ type CertificateInvalidError struct {
 func (e CertificateInvalidError) Error() string {
 	switch e.Reason {
 	case NotAuthorizedToSign:
-		return "x509: certificate is not authorized to sign other other certificates"
+		return "x509: certificate is not authorized to sign other certificates"
 	case Expired:
 		return "x509: certificate has expired or is not yet valid"
 	case CANotAuthorizedForThisName:
 		return "x509: a root or intermediate certificate is not authorized to sign in this domain"
 	case TooManyIntermediates:
 		return "x509: too many intermediates for path length constraint"
+	case IncompatibleUsage:
+		return "x509: certificate specifies an incompatible key usage"
 	}
 	return "x509: unknown error"
 }
@@ -58,14 +64,28 @@ type HostnameError struct {
 }
 
 func (h HostnameError) Error() string {
-	var valid string
 	c := h.Certificate
-	if len(c.DNSNames) > 0 {
-		valid = strings.Join(c.DNSNames, ", ")
+
+	var valid string
+	if ip := net.ParseIP(h.Host); ip != nil {
+		// Trying to validate an IP
+		if len(c.IPAddresses) == 0 {
+			return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
+		}
+		for _, san := range c.IPAddresses {
+			if len(valid) > 0 {
+				valid += ", "
+			}
+			valid += san.String()
+		}
 	} else {
-		valid = c.Subject.CommonName
+		if len(c.DNSNames) > 0 {
+			valid = strings.Join(c.DNSNames, ", ")
+		} else {
+			valid = c.Subject.CommonName
+		}
 	}
-	return "certificate is valid for " + valid + ", not " + h.Host
+	return "x509: certificate is valid for " + valid + ", not " + h.Host
 }
 
 // UnknownAuthorityError results when the certificate issuer is unknown
@@ -77,6 +97,14 @@ func (e UnknownAuthorityError) Error() string {
 	return "x509: certificate signed by unknown authority"
 }
 
+// SystemRootsError results when we fail to load the system root certificates.
+type SystemRootsError struct {
+}
+
+func (e SystemRootsError) Error() string {
+	return "x509: failed to load system roots and no roots provided"
+}
+
 // VerifyOptions contains parameters for Certificate.Verify. It's a structure
 // because other PKIX verification APIs have ended up needing many options.
 type VerifyOptions struct {
@@ -84,6 +112,11 @@ type VerifyOptions struct {
 	Intermediates *CertPool
 	Roots         *CertPool // if nil, the system roots are used
 	CurrentTime   time.Time // if zero, the current time is used
+	// KeyUsage specifies which Extended Key Usage values are acceptable.
+	// An empty list means ExtKeyUsageServerAuth. Key usage is considered a
+	// constraint down the chain which mirrors Windows CryptoAPI behaviour,
+	// but not the spec. To accept any key usage, include ExtKeyUsageAny.
+	KeyUsages []ExtKeyUsage
 }
 
 const (
@@ -160,6 +193,9 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
 
 	if opts.Roots == nil {
 		opts.Roots = systemRootsPool()
+		if opts.Roots == nil {
+			return nil, SystemRootsError{}
+		}
 	}
 
 	err = c.isValid(leafCertificate, nil, &opts)
@@ -174,7 +210,35 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
 		}
 	}
 
-	return c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
+	candidateChains, err := c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
+	if err != nil {
+		return
+	}
+
+	keyUsages := opts.KeyUsages
+	if len(keyUsages) == 0 {
+		keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
+	}
+
+	// If any key usage is acceptable then we're done.
+	for _, usage := range keyUsages {
+		if usage == ExtKeyUsageAny {
+			chains = candidateChains
+			return
+		}
+	}
+
+	for _, candidate := range candidateChains {
+		if checkChainForKeyUsage(candidate, keyUsages) {
+			chains = append(chains, candidate)
+		}
+	}
+
+	if len(chains) == 0 {
+		err = CertificateInvalidError{c, IncompatibleUsage}
+	}
+
+	return
 }
 
 func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
@@ -285,6 +349,22 @@ func toLowerCaseASCII(in string) string {
 // VerifyHostname returns nil if c is a valid certificate for the named host.
 // Otherwise it returns an error describing the mismatch.
 func (c *Certificate) VerifyHostname(h string) error {
+	// IP addresses may be written in [ ].
+	candidateIP := h
+	if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
+		candidateIP = h[1 : len(h)-1]
+	}
+	if ip := net.ParseIP(candidateIP); ip != nil {
+		// We only match IP addresses against IP SANs.
+		// https://tools.ietf.org/html/rfc6125#appendix-B.2
+		for _, candidate := range c.IPAddresses {
+			if ip.Equal(candidate) {
+				return nil
+			}
+		}
+		return HostnameError{c, candidateIP}
+	}
+
 	lowered := toLowerCaseASCII(h)
 
 	if len(c.DNSNames) > 0 {
@@ -300,3 +380,64 @@ func (c *Certificate) VerifyHostname(h string) error {
 
 	return HostnameError{c, h}
 }
+
+func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
+	usages := make([]ExtKeyUsage, len(keyUsages))
+	copy(usages, keyUsages)
+
+	if len(chain) == 0 {
+		return false
+	}
+
+	usagesRemaining := len(usages)
+
+	// We walk down the list and cross out any usages that aren't supported
+	// by each certificate. If we cross out all the usages, then the chain
+	// is unacceptable.
+
+	for i := len(chain) - 1; i >= 0; i-- {
+		cert := chain[i]
+		if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
+			// The certificate doesn't have any extended key usage specified.
+			continue
+		}
+
+		for _, usage := range cert.ExtKeyUsage {
+			if usage == ExtKeyUsageAny {
+				// The certificate is explicitly good for any usage.
+				continue
+			}
+		}
+
+		const invalidUsage ExtKeyUsage = -1
+
+	NextRequestedUsage:
+		for i, requestedUsage := range usages {
+			if requestedUsage == invalidUsage {
+				continue
+			}
+
+			for _, usage := range cert.ExtKeyUsage {
+				if requestedUsage == usage {
+					continue NextRequestedUsage
+				} else if requestedUsage == ExtKeyUsageServerAuth &&
+					(usage == ExtKeyUsageNetscapeServerGatedCrypto ||
+						usage == ExtKeyUsageMicrosoftServerGatedCrypto) {
+					// In order to support COMODO
+					// certificate chains, we have to
+					// accept Netscape or Microsoft SGC
+					// usages as equal to ServerAuth.
+					continue NextRequestedUsage
+				}
+			}
+
+			usages[i] = invalidUsage
+			usagesRemaining--
+			if usagesRemaining == 0 {
+				return false
+			}
+		}
+	}
+
+	return true
+}
diff --git a/src/pkg/crypto/x509/verify_test.go b/src/pkg/crypto/x509/verify_test.go
index 7b171b2..5103ed8 100644
--- a/src/pkg/crypto/x509/verify_test.go
+++ b/src/pkg/crypto/x509/verify_test.go
@@ -15,12 +15,14 @@ import (
 )
 
 type verifyTest struct {
-	leaf          string
-	intermediates []string
-	roots         []string
-	currentTime   int64
-	dnsName       string
-	systemSkip    bool
+	leaf                 string
+	intermediates        []string
+	roots                []string
+	currentTime          int64
+	dnsName              string
+	systemSkip           bool
+	keyUsages            []ExtKeyUsage
+	testSystemRootsError bool
 
 	errorCallback  func(*testing.T, int, error) bool
 	expectedChains [][]string
@@ -28,6 +30,17 @@ type verifyTest struct {
 
 var verifyTests = []verifyTest{
 	{
+		leaf:                 googleLeaf,
+		intermediates:        []string{thawteIntermediate},
+		currentTime:          1302726541,
+		dnsName:              "www.google.com",
+		testSystemRootsError: true,
+
+		// Without any roots specified we should get a system roots
+		// error.
+		errorCallback: expectSystemRootsError,
+	},
+	{
 		leaf:          googleLeaf,
 		intermediates: []string{thawteIntermediate},
 		roots:         []string{verisignRoot},
@@ -113,6 +126,51 @@ var verifyTests = []verifyTest{
 			{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority", "StartCom Certification Authority"},
 		},
 	},
+	{
+		// The default configuration should reject an S/MIME chain.
+		leaf:        smimeLeaf,
+		roots:       []string{smimeIntermediate},
+		currentTime: 1339436154,
+
+		// Key usage not implemented for Windows yet.
+		systemSkip:    true,
+		errorCallback: expectUsageError,
+	},
+	{
+		leaf:        smimeLeaf,
+		roots:       []string{smimeIntermediate},
+		currentTime: 1339436154,
+		keyUsages:   []ExtKeyUsage{ExtKeyUsageServerAuth},
+
+		// Key usage not implemented for Windows yet.
+		systemSkip:    true,
+		errorCallback: expectUsageError,
+	},
+	{
+		leaf:        smimeLeaf,
+		roots:       []string{smimeIntermediate},
+		currentTime: 1339436154,
+		keyUsages:   []ExtKeyUsage{ExtKeyUsageEmailProtection},
+
+		// Key usage not implemented for Windows yet.
+		systemSkip: true,
+		expectedChains: [][]string{
+			{"Ryan Hurst", "GlobalSign PersonalSign 2 CA - G2"},
+		},
+	},
+	{
+		leaf:          megaLeaf,
+		intermediates: []string{comodoIntermediate1},
+		roots:         []string{comodoRoot},
+		currentTime:   1360431182,
+
+		// CryptoAPI can find alternative validation paths so we don't
+		// perform this test with system validation.
+		systemSkip: true,
+		expectedChains: [][]string{
+			{"mega.co.nz", "EssentialSSL CA", "COMODO Certification Authority"},
+		},
+	},
 }
 
 func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
@@ -131,6 +189,14 @@ func expectExpired(t *testing.T, i int, err error) (ok bool) {
 	return true
 }
 
+func expectUsageError(t *testing.T, i int, err error) (ok bool) {
+	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != IncompatibleUsage {
+		t.Errorf("#%d: error was not IncompatibleUsage: %s", i, err)
+		return false
+	}
+	return true
+}
+
 func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) {
 	if _, ok := err.(UnknownAuthorityError); !ok {
 		t.Errorf("#%d: error was not UnknownAuthorityError: %s", i, err)
@@ -139,6 +205,14 @@ func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) {
 	return true
 }
 
+func expectSystemRootsError(t *testing.T, i int, err error) bool {
+	if _, ok := err.(SystemRootsError); !ok {
+		t.Errorf("#%d: error was not SystemRootsError: %s", i, err)
+		return false
+	}
+	return true
+}
+
 func certificateFromPEM(pemBytes string) (*Certificate, error) {
 	block, _ := pem.Decode([]byte(pemBytes))
 	if block == nil {
@@ -152,11 +226,15 @@ func testVerify(t *testing.T, useSystemRoots bool) {
 		if useSystemRoots && test.systemSkip {
 			continue
 		}
+		if runtime.GOOS == "windows" && test.testSystemRootsError {
+			continue
+		}
 
 		opts := VerifyOptions{
 			Intermediates: NewCertPool(),
 			DNSName:       test.dnsName,
 			CurrentTime:   time.Unix(test.currentTime, 0),
+			KeyUsages:     test.keyUsages,
 		}
 
 		if !useSystemRoots {
@@ -184,8 +262,19 @@ func testVerify(t *testing.T, useSystemRoots bool) {
 			return
 		}
 
+		var oldSystemRoots *CertPool
+		if test.testSystemRootsError {
+			oldSystemRoots = systemRootsPool()
+			systemRoots = nil
+			opts.Roots = nil
+		}
+
 		chains, err := leaf.Verify(opts)
 
+		if test.testSystemRootsError {
+			systemRoots = oldSystemRoots
+		}
+
 		if test.errorCallback == nil && err != nil {
 			t.Errorf("#%d: unexpected error: %s", i, err)
 		}
@@ -233,8 +322,7 @@ func TestGoVerify(t *testing.T) {
 
 func TestSystemVerify(t *testing.T) {
 	if runtime.GOOS != "windows" {
-		t.Logf("skipping verify test using system APIs on %q", runtime.GOOS)
-		return
+		t.Skipf("skipping verify test using system APIs on %q", runtime.GOOS)
 	}
 
 	testVerify(t, true)
@@ -433,3 +521,145 @@ O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
 um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
 NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
 -----END CERTIFICATE-----`
+
+const smimeLeaf = `-----BEGIN CERTIFICATE-----
+MIIFBjCCA+6gAwIBAgISESFvrjT8XcJTEe6rBlPptILlMA0GCSqGSIb3DQEBBQUA
+MFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSowKAYD
+VQQDEyFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiAyIENBIC0gRzIwHhcNMTIwMTIz
+MTYzNjU5WhcNMTUwMTIzMTYzNjU5WjCBlDELMAkGA1UEBhMCVVMxFjAUBgNVBAgT
+DU5ldyBIYW1zcGhpcmUxEzARBgNVBAcTClBvcnRzbW91dGgxGTAXBgNVBAoTEEds
+b2JhbFNpZ24sIEluYy4xEzARBgNVBAMTClJ5YW4gSHVyc3QxKDAmBgkqhkiG9w0B
+CQEWGXJ5YW4uaHVyc3RAZ2xvYmFsc2lnbi5jb20wggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQC4ASSTvavmsFQAob60ukSSwOAL9nT/s99ltNUCAf5fPH5j
+NceMKxaQse2miOmRRIXaykcq1p/TbI70Ztce38r2mbOwqDHHPVi13GxJEyUXWgaR
+BteDMu5OGyWNG1kchVsGWpbstT0Z4v0md5m1BYFnxB20ebJyOR2lXDxsFK28nnKV
++5eMj76U8BpPQ4SCH7yTMG6y0XXsB3cCrBKr2o3TOYgEKv+oNnbaoMt3UxMt9nSf
+9jyIshjqfnT5Aew3CUNMatO55g5FXXdIukAweg1YSb1ls05qW3sW00T3d7dQs9/7
+NuxCg/A2elmVJSoy8+MLR8JSFEf/aMgjO/TyLg/jAgMBAAGjggGPMIIBizAOBgNV
+HQ8BAf8EBAMCBaAwTQYDVR0gBEYwRDBCBgorBgEEAaAyASgKMDQwMgYIKwYBBQUH
+AgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMCQGA1Ud
+EQQdMBuBGXJ5YW4uaHVyc3RAZ2xvYmFsc2lnbi5jb20wCQYDVR0TBAIwADAdBgNV
+HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwQwYDVR0fBDwwOjA4oDagNIYyaHR0
+cDovL2NybC5nbG9iYWxzaWduLmNvbS9ncy9nc3BlcnNvbmFsc2lnbjJnMi5jcmww
+VQYIKwYBBQUHAQEESTBHMEUGCCsGAQUFBzAChjlodHRwOi8vc2VjdXJlLmdsb2Jh
+bHNpZ24uY29tL2NhY2VydC9nc3BlcnNvbmFsc2lnbjJnMi5jcnQwHQYDVR0OBBYE
+FFWiECe0/L72eVYqcWYnLV6SSjzhMB8GA1UdIwQYMBaAFD8V0m18L+cxnkMKBqiU
+bCw7xe5lMA0GCSqGSIb3DQEBBQUAA4IBAQAhQi6hLPeudmf3IBF4IDzCvRI0FaYd
+BKfprSk/H0PDea4vpsLbWpA0t0SaijiJYtxKjlM4bPd+2chb7ejatDdyrZIzmDVy
+q4c30/xMninGKokpYA11/Ve+i2dvjulu65qasrtQRGybAuuZ67lrp/K3OMFgjV5N
+C3AHYLzvNU4Dwc4QQ1BaMOg6KzYSrKbABRZajfrpC9uiePsv7mDIXLx/toBPxWNl
+a5vJm5DrZdn7uHdvBCE6kMykbOLN5pmEK0UIlwKh6Qi5XD0pzlVkEZliFkBMJgub
+d/eF7xeg7TKPWC5xyOFp9SdMolJM7LTC3wnSO3frBAev+q/nGs9Xxyvs
+-----END CERTIFICATE-----`
+
+const smimeIntermediate = `-----BEGIN CERTIFICATE-----
+MIIEFjCCAv6gAwIBAgILBAAAAAABL07hL1IwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0MTMxMDAw
+MDBaFw0xOTA0MTMxMDAwMDBaMFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMSowKAYDVQQDEyFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiAy
+IENBIC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBa0H5Nez4
+En3dIlFpX7e5E0YndxQ74xOBbz7kdBd+DLX0LOQMjVPU3DAgKL9ujhH+ZhHkURbH
+3X/94TQSUL/z2JjsaQvS0NqyZXHhM5eeuquzOJRzEQ8+odETzHg2G0Erv7yjSeww
+gkwDWDJnYUDlOjYTDUEG6+i+8Mn425reo4I0E277wD542kmVWeW7+oHv5dZo9e1Q
+yWwiKTEP6BEQVVSBgThXMG4traSSDRUt3T1eQTZx5EObpiBEBO4OTqiBTJfg4vEI
+YgkXzKLpnfszTB6YMDpR9/QS6p3ANB3kfAb+t6udSO3WCst0DGrwHDLBFGDR4UeY
+T5KGGnI7cWL7AgMBAAGjgeUwgeIwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI
+MAYBAf8CAQAwHQYDVR0OBBYEFD8V0m18L+cxnkMKBqiUbCw7xe5lMEcGA1UdIARA
+MD4wPAYEVR0gADA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWdu
+LmNvbS9yZXBvc2l0b3J5LzAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmds
+b2JhbHNpZ24ubmV0L3Jvb3QuY3JsMB8GA1UdIwQYMBaAFGB7ZhpFDZfKiVAvfQTN
+NKj//P1LMA0GCSqGSIb3DQEBBQUAA4IBAQBDc3nMpMxJMQMcYUCB3+C73UpvwDE8
+eCOr7t2F/uaQKKcyqqstqLZc6vPwI/rcE9oDHugY5QEjQzIBIEaTnN6P0vege2IX
+eCOr7t2F/uaQKKcyqqstqLZc6vPwI/rcE9oDHugY5QEjQzIBIEaTnN6P0vege2IX
+YEvTWbWwGdPytDFPYIl3/6OqNSXSnZ7DxPcdLJq2uyiga8PB/TTIIHYkdM2+1DE0
+7y3rH/7TjwDVD7SLu5/SdOfKskuMPTjOEvz3K161mymW06klVhubCIWOro/Gx1Q2
+2FQOZ7/2k4uYoOdBTSlb8kTAuzZNgIE0rB2BIYCTz/P6zZIKW0ogbRSH
+-----END CERTIFICATE-----`
+
+var megaLeaf = `-----BEGIN CERTIFICATE-----
+MIIFOjCCBCKgAwIBAgIQWYE8Dup170kZ+k11Lg51OjANBgkqhkiG9w0BAQUFADBy
+MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
+VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEYMBYGA1UE
+AxMPRXNzZW50aWFsU1NMIENBMB4XDTEyMTIxNDAwMDAwMFoXDTE0MTIxNDIzNTk1
+OVowfzEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMS4wLAYDVQQL
+EyVIb3N0ZWQgYnkgSW5zdHJhIENvcnBvcmF0aW9uIFB0eS4gTFREMRUwEwYDVQQL
+EwxFc3NlbnRpYWxTU0wxEzARBgNVBAMTCm1lZ2EuY28ubnowggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDcxMCClae8BQIaJHBUIVttlLvhbK4XhXPk3RQ3
+G5XA6tLZMBQ33l3F9knYJ0YErXtr8IdfYoulRQFmKFMJl9GtWyg4cGQi2Rcr5VN5
+S5dA1vu4oyJBxE9fPELcK6Yz1vqaf+n6za+mYTiQYKggVdS8/s8hmNuXP9Zk1pIn
++q0pGsf8NAcSHMJgLqPQrTDw+zae4V03DvcYfNKjuno88d2226ld7MAmQZ7uRNsI
+/CnkdelVs+akZsXf0szefSqMJlf08SY32t2jj4Ra7RApVYxOftD9nij/aLfuqOU6
+ow6IgIcIG2ZvXLZwK87c5fxL7UAsTTV+M1sVv8jA33V2oKLhAgMBAAGjggG9MIIB
+uTAfBgNVHSMEGDAWgBTay+qtWwhdzP/8JlTOSeVVxjj0+DAdBgNVHQ4EFgQUmP9l
+6zhyrZ06Qj4zogt+6LKFk4AwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAw
+NAYDVR0lBC0wKwYIKwYBBQUHAwEGCCsGAQUFBwMCBgorBgEEAYI3CgMDBglghkgB
+hvhCBAEwTwYDVR0gBEgwRjA6BgsrBgEEAbIxAQICBzArMCkGCCsGAQUFBwIBFh1o
+dHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzAIBgZngQwBAgEwOwYDVR0fBDQw
+MjAwoC6gLIYqaHR0cDovL2NybC5jb21vZG9jYS5jb20vRXNzZW50aWFsU1NMQ0Eu
+Y3JsMG4GCCsGAQUFBwEBBGIwYDA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21v
+ZG9jYS5jb20vRXNzZW50aWFsU1NMQ0FfMi5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6
+Ly9vY3NwLmNvbW9kb2NhLmNvbTAlBgNVHREEHjAcggptZWdhLmNvLm56gg53d3cu
+bWVnYS5jby5uejANBgkqhkiG9w0BAQUFAAOCAQEAcYhrsPSvDuwihMOh0ZmRpbOE
+Gw6LqKgLNTmaYUPQhzi2cyIjhUhNvugXQQlP5f0lp5j8cixmArafg1dTn4kQGgD3
+ivtuhBTgKO1VYB/VRoAt6Lmswg3YqyiS7JiLDZxjoV7KoS5xdiaINfHDUaBBY4ZH
+j2BUlPniNBjCqXe/HndUTVUewlxbVps9FyCmH+C4o9DWzdGBzDpCkcmo5nM+cp7q
+ZhTIFTvZfo3zGuBoyu8BzuopCJcFRm3cRiXkpI7iOMUIixO1szkJS6WpL1sKdT73
+UXp08U0LBqoqG130FbzEJBBV3ixbvY6BWMHoCWuaoF12KJnC5kHt2RoWAAgMXA==
+-----END CERTIFICATE-----`
+
+var comodoIntermediate1 = `-----BEGIN CERTIFICATE-----
+MIIFAzCCA+ugAwIBAgIQGLLLuqME8aAPwfLzJkYqSjANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0xOTEyMzEyMzU5NTlaMHIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVh
+dGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9E
+TyBDQSBMaW1pdGVkMRgwFgYDVQQDEw9Fc3NlbnRpYWxTU0wgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt8AiwcsargxIxF3CJhakgEtSYau2A1NHf
+5I5ZLdOWIY120j8YC0YZYwvHIPPlC92AGvFaoL0dds23Izp0XmEbdaqb1IX04XiR
+0y3hr/yYLgbSeT1awB8hLRyuIVPGOqchfr7tZ291HRqfalsGs2rjsQuqag7nbWzD
+ypWMN84hHzWQfdvaGlyoiBSyD8gSIF/F03/o4Tjg27z5H6Gq1huQByH6RSRQXScq
+oChBRVt9vKCiL6qbfltTxfEFFld+Edc7tNkBdtzffRDPUanlOPJ7FAB1WfnwWdsX
+Pvev5gItpHnBXaIcw5rIp6gLSApqLn8tl2X2xQScRMiZln5+pN0vAgMBAAGjggGD
+MIIBfzAfBgNVHSMEGDAWgBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAdBgNVHQ4EFgQU
+2svqrVsIXcz//CZUzknlVcY49PgwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI
+MAYBAf8CAQAwIAYDVR0lBBkwFwYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMD4GA1Ud
+IAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21v
+ZG8uY29tL0NQUzBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9kb2Nh
+LmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBsBggrBgEFBQcB
+AQRgMF4wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NvbW9k
+b1VUTlNHQ0NBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2Eu
+Y29tMA0GCSqGSIb3DQEBBQUAA4IBAQAtlzR6QDLqcJcvgTtLeRJ3rvuq1xqo2l/z
+odueTZbLN3qo6u6bldudu+Ennv1F7Q5Slqz0J790qpL0pcRDAB8OtXj5isWMcL2a
+ejGjKdBZa0wztSz4iw+SY1dWrCRnilsvKcKxudokxeRiDn55w/65g+onO7wdQ7Vu
+F6r7yJiIatnyfKH2cboZT7g440LX8NqxwCPf3dfxp+0Jj1agq8MLy6SSgIGSH6lv
++Wwz3D5XxqfyH8wqfOQsTEZf6/Nh9yvENZ+NWPU6g0QO2JOsTGvMd/QDzczc4BxL
+XSXaPV7Od4rhPsbXlM1wSTz/Dr0ISKvlUhQVnQ6cGodWaK2cCQBk
+-----END CERTIFICATE-----`
+
+var comodoRoot = `-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----`
diff --git a/src/pkg/crypto/x509/x509.go b/src/pkg/crypto/x509/x509.go
index c4d85e6..b802bf4 100644
--- a/src/pkg/crypto/x509/x509.go
+++ b/src/pkg/crypto/x509/x509.go
@@ -9,6 +9,8 @@ import (
 	"bytes"
 	"crypto"
 	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
 	"crypto/rsa"
 	"crypto/sha1"
 	"crypto/x509/pkix"
@@ -17,6 +19,8 @@ import (
 	"errors"
 	"io"
 	"math/big"
+	"net"
+	"strconv"
 	"time"
 )
 
@@ -106,6 +110,8 @@ type dsaSignature struct {
 	R, S *big.Int
 }
 
+type ecdsaSignature dsaSignature
+
 type validity struct {
 	NotBefore, NotAfter time.Time
 }
@@ -133,6 +139,10 @@ const (
 	SHA512WithRSA
 	DSAWithSHA1
 	DSAWithSHA256
+	ECDSAWithSHA1
+	ECDSAWithSHA256
+	ECDSAWithSHA384
+	ECDSAWithSHA512
 )
 
 type PublicKeyAlgorithm int
@@ -141,14 +151,15 @@ const (
 	UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota
 	RSA
 	DSA
+	ECDSA
 )
 
 // OIDs for signature algorithms
 //
 // pkcs-1 OBJECT IDENTIFIER ::= {
 //    iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
-// 
-// 
+//
+//
 // RFC 3279 2.2.1 RSA Signature Algorithms
 //
 // md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
@@ -156,13 +167,19 @@ const (
 // md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
 //
 // sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
-// 
+//
 // dsaWithSha1 OBJECT IDENTIFIER ::= {
-//    iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 } 
+//    iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 }
+//
+// RFC 3279 2.2.3 ECDSA Signature Algorithm
+//
+// ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
+// 	  iso(1) member-body(2) us(840) ansi-x962(10045)
+//    signatures(4) ecdsa-with-SHA1(1)}
 //
 //
 // RFC 4055 5 PKCS #1 Version 1.5
-// 
+//
 // sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
 //
 // sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
@@ -176,15 +193,30 @@ const (
 //    joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101)
 //    csor(3) algorithms(4) id-dsa-with-sha2(3) 2}
 //
+// RFC 5758 3.2 ECDSA Signature Algorithm
+//
+// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+//    us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
+//
+// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+//    us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
+//
+// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+//    us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
+
 var (
-	oidSignatureMD2WithRSA    = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
-	oidSignatureMD5WithRSA    = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
-	oidSignatureSHA1WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
-	oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
-	oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
-	oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
-	oidSignatureDSAWithSHA1   = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
-	oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
+	oidSignatureMD2WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
+	oidSignatureMD5WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
+	oidSignatureSHA1WithRSA     = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
+	oidSignatureSHA256WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
+	oidSignatureSHA384WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
+	oidSignatureSHA512WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
+	oidSignatureDSAWithSHA1     = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
+	oidSignatureDSAWithSHA256   = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
+	oidSignatureECDSAWithSHA1   = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
+	oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
+	oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
+	oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
 )
 
 func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm {
@@ -205,6 +237,14 @@ func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm
 		return DSAWithSHA1
 	case oid.Equal(oidSignatureDSAWithSHA256):
 		return DSAWithSHA256
+	case oid.Equal(oidSignatureECDSAWithSHA1):
+		return ECDSAWithSHA1
+	case oid.Equal(oidSignatureECDSAWithSHA256):
+		return ECDSAWithSHA256
+	case oid.Equal(oidSignatureECDSAWithSHA384):
+		return ECDSAWithSHA384
+	case oid.Equal(oidSignatureECDSAWithSHA512):
+		return ECDSAWithSHA512
 	}
 	return UnknownSignatureAlgorithm
 }
@@ -218,21 +258,81 @@ func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm
 //
 // id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
 //    x9-57(10040) x9cm(4) 1 }
+//
+// RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters
+//
+// id-ecPublicKey OBJECT IDENTIFIER ::= {
+//       iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
 var (
-	oidPublicKeyRsa = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
-	oidPublicKeyDsa = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
+	oidPublicKeyRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
+	oidPublicKeyDSA   = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
+	oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
 )
 
 func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm {
 	switch {
-	case oid.Equal(oidPublicKeyRsa):
+	case oid.Equal(oidPublicKeyRSA):
 		return RSA
-	case oid.Equal(oidPublicKeyDsa):
+	case oid.Equal(oidPublicKeyDSA):
 		return DSA
+	case oid.Equal(oidPublicKeyECDSA):
+		return ECDSA
 	}
 	return UnknownPublicKeyAlgorithm
 }
 
+// RFC 5480, 2.1.1.1. Named Curve
+//
+// secp224r1 OBJECT IDENTIFIER ::= {
+//   iso(1) identified-organization(3) certicom(132) curve(0) 33 }
+//
+// secp256r1 OBJECT IDENTIFIER ::= {
+//   iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
+//   prime(1) 7 }
+//
+// secp384r1 OBJECT IDENTIFIER ::= {
+//   iso(1) identified-organization(3) certicom(132) curve(0) 34 }
+//
+// secp521r1 OBJECT IDENTIFIER ::= {
+//   iso(1) identified-organization(3) certicom(132) curve(0) 35 }
+//
+// NB: secp256r1 is equivalent to prime256v1
+var (
+	oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
+	oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
+	oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
+	oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
+)
+
+func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
+	switch {
+	case oid.Equal(oidNamedCurveP224):
+		return elliptic.P224()
+	case oid.Equal(oidNamedCurveP256):
+		return elliptic.P256()
+	case oid.Equal(oidNamedCurveP384):
+		return elliptic.P384()
+	case oid.Equal(oidNamedCurveP521):
+		return elliptic.P521()
+	}
+	return nil
+}
+
+func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
+	switch curve {
+	case elliptic.P224():
+		return oidNamedCurveP224, true
+	case elliptic.P256():
+		return oidNamedCurveP256, true
+	case elliptic.P384():
+		return oidNamedCurveP384, true
+	case elliptic.P521():
+		return oidNamedCurveP521, true
+	}
+
+	return nil, false
+}
+
 // KeyUsage represents the set of actions that are valid for a given key. It's
 // a bitmap of the KeyUsage* constants.
 type KeyUsage int
@@ -262,13 +362,18 @@ const (
 // id-kp-timeStamping           OBJECT IDENTIFIER ::= { id-kp 8 }
 // id-kp-OCSPSigning            OBJECT IDENTIFIER ::= { id-kp 9 }
 var (
-	oidExtKeyUsageAny             = asn1.ObjectIdentifier{2, 5, 29, 37, 0}
-	oidExtKeyUsageServerAuth      = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}
-	oidExtKeyUsageClientAuth      = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
-	oidExtKeyUsageCodeSigning     = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
-	oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
-	oidExtKeyUsageTimeStamping    = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
-	oidExtKeyUsageOCSPSigning     = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
+	oidExtKeyUsageAny                        = asn1.ObjectIdentifier{2, 5, 29, 37, 0}
+	oidExtKeyUsageServerAuth                 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}
+	oidExtKeyUsageClientAuth                 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
+	oidExtKeyUsageCodeSigning                = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
+	oidExtKeyUsageEmailProtection            = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
+	oidExtKeyUsageIPSECEndSystem             = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5}
+	oidExtKeyUsageIPSECTunnel                = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6}
+	oidExtKeyUsageIPSECUser                  = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7}
+	oidExtKeyUsageTimeStamping               = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
+	oidExtKeyUsageOCSPSigning                = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
+	oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3}
+	oidExtKeyUsageNetscapeServerGatedCrypto  = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1}
 )
 
 // ExtKeyUsage represents an extended set of actions that are valid for a given key.
@@ -281,10 +386,52 @@ const (
 	ExtKeyUsageClientAuth
 	ExtKeyUsageCodeSigning
 	ExtKeyUsageEmailProtection
+	ExtKeyUsageIPSECEndSystem
+	ExtKeyUsageIPSECTunnel
+	ExtKeyUsageIPSECUser
 	ExtKeyUsageTimeStamping
 	ExtKeyUsageOCSPSigning
+	ExtKeyUsageMicrosoftServerGatedCrypto
+	ExtKeyUsageNetscapeServerGatedCrypto
 )
 
+// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID.
+var extKeyUsageOIDs = []struct {
+	extKeyUsage ExtKeyUsage
+	oid         asn1.ObjectIdentifier
+}{
+	{ExtKeyUsageAny, oidExtKeyUsageAny},
+	{ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth},
+	{ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth},
+	{ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning},
+	{ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection},
+	{ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem},
+	{ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel},
+	{ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser},
+	{ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping},
+	{ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning},
+	{ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto},
+	{ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto},
+}
+
+func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) {
+	for _, pair := range extKeyUsageOIDs {
+		if oid.Equal(pair.oid) {
+			return pair.extKeyUsage, true
+		}
+	}
+	return
+}
+
+func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) {
+	for _, pair := range extKeyUsageOIDs {
+		if eku == pair.extKeyUsage {
+			return pair.oid, true
+		}
+	}
+	return
+}
+
 // A Certificate represents an X.509 certificate.
 type Certificate struct {
 	Raw                     []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
@@ -319,6 +466,7 @@ type Certificate struct {
 	// Subject Alternate Name values
 	DNSNames       []string
 	EmailAddresses []string
+	IPAddresses    []net.IP
 
 	// Name constraints
 	PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
@@ -344,6 +492,55 @@ func (c *Certificate) Equal(other *Certificate) bool {
 	return bytes.Equal(c.Raw, other.Raw)
 }
 
+// Entrust have a broken root certificate (CN=Entrust.net Certification
+// Authority (2048)) which isn't marked as a CA certificate and is thus invalid
+// according to PKIX.
+// We recognise this certificate by its SubjectPublicKeyInfo and exempt it
+// from the Basic Constraints requirement.
+// See http://www.entrust.net/knowledge-base/technote.cfm?tn=7869
+//
+// TODO(agl): remove this hack once their reissued root is sufficiently
+// widespread.
+var entrustBrokenSPKI = []byte{
+	0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09,
+	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+	0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00,
+	0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
+	0x00, 0x97, 0xa3, 0x2d, 0x3c, 0x9e, 0xde, 0x05,
+	0xda, 0x13, 0xc2, 0x11, 0x8d, 0x9d, 0x8e, 0xe3,
+	0x7f, 0xc7, 0x4b, 0x7e, 0x5a, 0x9f, 0xb3, 0xff,
+	0x62, 0xab, 0x73, 0xc8, 0x28, 0x6b, 0xba, 0x10,
+	0x64, 0x82, 0x87, 0x13, 0xcd, 0x57, 0x18, 0xff,
+	0x28, 0xce, 0xc0, 0xe6, 0x0e, 0x06, 0x91, 0x50,
+	0x29, 0x83, 0xd1, 0xf2, 0xc3, 0x2a, 0xdb, 0xd8,
+	0xdb, 0x4e, 0x04, 0xcc, 0x00, 0xeb, 0x8b, 0xb6,
+	0x96, 0xdc, 0xbc, 0xaa, 0xfa, 0x52, 0x77, 0x04,
+	0xc1, 0xdb, 0x19, 0xe4, 0xae, 0x9c, 0xfd, 0x3c,
+	0x8b, 0x03, 0xef, 0x4d, 0xbc, 0x1a, 0x03, 0x65,
+	0xf9, 0xc1, 0xb1, 0x3f, 0x72, 0x86, 0xf2, 0x38,
+	0xaa, 0x19, 0xae, 0x10, 0x88, 0x78, 0x28, 0xda,
+	0x75, 0xc3, 0x3d, 0x02, 0x82, 0x02, 0x9c, 0xb9,
+	0xc1, 0x65, 0x77, 0x76, 0x24, 0x4c, 0x98, 0xf7,
+	0x6d, 0x31, 0x38, 0xfb, 0xdb, 0xfe, 0xdb, 0x37,
+	0x02, 0x76, 0xa1, 0x18, 0x97, 0xa6, 0xcc, 0xde,
+	0x20, 0x09, 0x49, 0x36, 0x24, 0x69, 0x42, 0xf6,
+	0xe4, 0x37, 0x62, 0xf1, 0x59, 0x6d, 0xa9, 0x3c,
+	0xed, 0x34, 0x9c, 0xa3, 0x8e, 0xdb, 0xdc, 0x3a,
+	0xd7, 0xf7, 0x0a, 0x6f, 0xef, 0x2e, 0xd8, 0xd5,
+	0x93, 0x5a, 0x7a, 0xed, 0x08, 0x49, 0x68, 0xe2,
+	0x41, 0xe3, 0x5a, 0x90, 0xc1, 0x86, 0x55, 0xfc,
+	0x51, 0x43, 0x9d, 0xe0, 0xb2, 0xc4, 0x67, 0xb4,
+	0xcb, 0x32, 0x31, 0x25, 0xf0, 0x54, 0x9f, 0x4b,
+	0xd1, 0x6f, 0xdb, 0xd4, 0xdd, 0xfc, 0xaf, 0x5e,
+	0x6c, 0x78, 0x90, 0x95, 0xde, 0xca, 0x3a, 0x48,
+	0xb9, 0x79, 0x3c, 0x9b, 0x19, 0xd6, 0x75, 0x05,
+	0xa0, 0xf9, 0x88, 0xd7, 0xc1, 0xe8, 0xa5, 0x09,
+	0xe4, 0x1a, 0x15, 0xdc, 0x87, 0x23, 0xaa, 0xb2,
+	0x75, 0x8c, 0x63, 0x25, 0x87, 0xd8, 0xf8, 0x3d,
+	0xa6, 0xc2, 0xcc, 0x66, 0xff, 0xa5, 0x66, 0x68,
+	0x55, 0x02, 0x03, 0x01, 0x00, 0x01,
+}
+
 // CheckSignatureFrom verifies that the signature on c is a valid signature
 // from parent.
 func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) {
@@ -352,8 +549,10 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) {
 	// certificate, or the extension is present but the cA boolean is not
 	// asserted, then the certified public key MUST NOT be used to verify
 	// certificate signatures."
-	if parent.Version == 3 && !parent.BasicConstraintsValid ||
-		parent.BasicConstraintsValid && !parent.IsCA {
+	// (except for Entrust, see comment above entrustBrokenSPKI)
+	if (parent.Version == 3 && !parent.BasicConstraintsValid ||
+		parent.BasicConstraintsValid && !parent.IsCA) &&
+		!bytes.Equal(c.RawSubjectPublicKeyInfo, entrustBrokenSPKI) {
 		return ConstraintViolationError{}
 	}
 
@@ -376,13 +575,13 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
 	var hashType crypto.Hash
 
 	switch algo {
-	case SHA1WithRSA, DSAWithSHA1:
+	case SHA1WithRSA, DSAWithSHA1, ECDSAWithSHA1:
 		hashType = crypto.SHA1
-	case SHA256WithRSA, DSAWithSHA256:
+	case SHA256WithRSA, DSAWithSHA256, ECDSAWithSHA256:
 		hashType = crypto.SHA256
-	case SHA384WithRSA:
+	case SHA384WithRSA, ECDSAWithSHA384:
 		hashType = crypto.SHA384
-	case SHA512WithRSA:
+	case SHA512WithRSA, ECDSAWithSHA512:
 		hashType = crypto.SHA512
 	default:
 		return ErrUnsupportedAlgorithm
@@ -411,6 +610,18 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
 			return errors.New("DSA verification failure")
 		}
 		return
+	case *ecdsa.PublicKey:
+		ecdsaSig := new(ecdsaSignature)
+		if _, err := asn1.Unmarshal(signature, ecdsaSig); err != nil {
+			return err
+		}
+		if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+			return errors.New("crypto/x509: ECDSA signature contained zero or negative values")
+		}
+		if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) {
+			return errors.New("crypto/x509: ECDSA verification failure")
+		}
+		return
 	}
 	return ErrUnsupportedAlgorithm
 }
@@ -446,8 +657,6 @@ type nameConstraints struct {
 
 type generalSubtree struct {
 	Name string `asn1:"tag:2,optional,ia5"`
-	Min  int    `asn1:"optional,tag:0"`
-	Max  int    `asn1:"optional,tag:1"`
 }
 
 func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
@@ -460,6 +669,13 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
 			return nil, err
 		}
 
+		if p.N.Sign() <= 0 {
+			return nil, errors.New("x509: RSA modulus is not a positive number")
+		}
+		if p.E <= 0 {
+			return nil, errors.New("x509: RSA public exponent is not a positive number")
+		}
+
 		pub := &rsa.PublicKey{
 			E: p.E,
 			N: p.N,
@@ -489,6 +705,27 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
 			Y: p,
 		}
 		return pub, nil
+	case ECDSA:
+		paramsData := keyData.Algorithm.Parameters.FullBytes
+		namedCurveOID := new(asn1.ObjectIdentifier)
+		_, err := asn1.Unmarshal(paramsData, namedCurveOID)
+		if err != nil {
+			return nil, err
+		}
+		namedCurve := namedCurveFromOID(*namedCurveOID)
+		if namedCurve == nil {
+			return nil, errors.New("crypto/x509: unsupported elliptic curve")
+		}
+		x, y := elliptic.Unmarshal(namedCurve, asn1Data)
+		if x == nil {
+			return nil, errors.New("crypto/x509: failed to unmarshal elliptic curve point")
+		}
+		pub := &ecdsa.PublicKey{
+			Curve: namedCurve,
+			X:     x,
+			Y:     y,
+		}
+		return pub, nil
 	default:
 		return nil, nil
 	}
@@ -607,6 +844,13 @@ func parseCertificate(in *certificate) (*Certificate, error) {
 					case 2:
 						out.DNSNames = append(out.DNSNames, string(v.Bytes))
 						parsedName = true
+					case 7:
+						switch len(v.Bytes) {
+						case net.IPv4len, net.IPv6len:
+							out.IPAddresses = append(out.IPAddresses, v.Bytes)
+						default:
+							return nil, errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes)))
+						}
 					}
 				}
 
@@ -643,7 +887,7 @@ func parseCertificate(in *certificate) (*Certificate, error) {
 				}
 
 				for _, subtree := range constraints.Permitted {
-					if subtree.Min > 0 || subtree.Max > 0 || len(subtree.Name) == 0 {
+					if len(subtree.Name) == 0 {
 						if e.Critical {
 							return out, UnhandledCriticalExtension{}
 						}
@@ -679,22 +923,9 @@ func parseCertificate(in *certificate) (*Certificate, error) {
 				}
 
 				for _, u := range keyUsage {
-					switch {
-					case u.Equal(oidExtKeyUsageAny):
-						out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageAny)
-					case u.Equal(oidExtKeyUsageServerAuth):
-						out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageServerAuth)
-					case u.Equal(oidExtKeyUsageClientAuth):
-						out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageClientAuth)
-					case u.Equal(oidExtKeyUsageCodeSigning):
-						out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageCodeSigning)
-					case u.Equal(oidExtKeyUsageEmailProtection):
-						out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageEmailProtection)
-					case u.Equal(oidExtKeyUsageTimeStamping):
-						out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageTimeStamping)
-					case u.Equal(oidExtKeyUsageOCSPSigning):
-						out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageOCSPSigning)
-					default:
+					if extKeyUsage, ok := extKeyUsageFromOID(u); ok {
+						out.ExtKeyUsage = append(out.ExtKeyUsage, extKeyUsage)
+					} else {
 						out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u)
 					}
 				}
@@ -783,6 +1014,7 @@ func reverseBitsInAByte(in byte) byte {
 var (
 	oidExtensionSubjectKeyId        = []int{2, 5, 29, 14}
 	oidExtensionKeyUsage            = []int{2, 5, 29, 15}
+	oidExtensionExtendedKeyUsage    = []int{2, 5, 29, 37}
 	oidExtensionAuthorityKeyId      = []int{2, 5, 29, 35}
 	oidExtensionBasicConstraints    = []int{2, 5, 29, 19}
 	oidExtensionSubjectAltName      = []int{2, 5, 29, 17}
@@ -791,7 +1023,7 @@ var (
 )
 
 func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
-	ret = make([]pkix.Extension, 7 /* maximum number of elements. */)
+	ret = make([]pkix.Extension, 8 /* maximum number of elements. */)
 	n := 0
 
 	if template.KeyUsage != 0 {
@@ -814,6 +1046,27 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
 		n++
 	}
 
+	if len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0 {
+		ret[n].Id = oidExtensionExtendedKeyUsage
+
+		var oids []asn1.ObjectIdentifier
+		for _, u := range template.ExtKeyUsage {
+			if oid, ok := oidFromExtKeyUsage(u); ok {
+				oids = append(oids, oid)
+			} else {
+				panic("internal error")
+			}
+		}
+
+		oids = append(oids, template.UnknownExtKeyUsage...)
+
+		ret[n].Value, err = asn1.Marshal(oids)
+		if err != nil {
+			return
+		}
+		n++
+	}
+
 	if template.BasicConstraintsValid {
 		ret[n].Id = oidExtensionBasicConstraints
 		ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, template.MaxPathLen})
@@ -842,11 +1095,22 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
 		n++
 	}
 
-	if len(template.DNSNames) > 0 {
+	if len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 {
 		ret[n].Id = oidExtensionSubjectAltName
-		rawValues := make([]asn1.RawValue, len(template.DNSNames))
-		for i, name := range template.DNSNames {
-			rawValues[i] = asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)}
+		var rawValues []asn1.RawValue
+		for _, name := range template.DNSNames {
+			rawValues = append(rawValues, asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)})
+		}
+		for _, email := range template.EmailAddresses {
+			rawValues = append(rawValues, asn1.RawValue{Tag: 1, Class: 2, Bytes: []byte(email)})
+		}
+		for _, rawIP := range template.IPAddresses {
+			// If possible, we always want to encode IPv4 addresses in 4 bytes.
+			ip := rawIP.To4()
+			if ip == nil {
+				ip = rawIP
+			}
+			rawValues = append(rawValues, asn1.RawValue{Tag: 7, Class: 2, Bytes: ip})
 		}
 		ret[n].Value, err = asn1.Marshal(rawValues)
 		if err != nil {
@@ -890,11 +1154,6 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
 	return ret[0:n], nil
 }
 
-var (
-	oidSHA1WithRSA = []int{1, 2, 840, 113549, 1, 1, 5}
-	oidRSA         = []int{1, 2, 840, 113549, 1, 1, 1}
-)
-
 func subjectBytes(cert *Certificate) ([]byte, error) {
 	if len(cert.RawSubject) > 0 {
 		return cert.RawSubject, nil
@@ -905,8 +1164,9 @@ func subjectBytes(cert *Certificate) ([]byte, error) {
 
 // CreateCertificate creates a new certificate based on a template. The
 // following members of template are used: SerialNumber, Subject, NotBefore,
-// NotAfter, KeyUsage, BasicConstraintsValid, IsCA, MaxPathLen, SubjectKeyId,
-// DNSNames, PermittedDNSDomainsCritical, PermittedDNSDomains.
+// NotAfter, KeyUsage, ExtKeyUsage, UnknownExtKeyUsage, BasicConstraintsValid,
+// IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
+// PermittedDNSDomains.
 //
 // The certificate is signed by parent. If parent is equal to template then the
 // certificate is self-signed. The parameter pub is the public key of the
@@ -914,23 +1174,61 @@ func subjectBytes(cert *Certificate) ([]byte, error) {
 //
 // The returned slice is the certificate in DER encoding.
 //
-// The only supported key type is RSA (*rsa.PublicKey for pub, *rsa.PrivateKey
-// for priv).
+// The only supported key types are RSA and ECDSA (*rsa.PublicKey or
+// *ecdsa.PublicKey for pub, *rsa.PrivateKey or *ecdsa.PublicKey for priv).
 func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interface{}, priv interface{}) (cert []byte, err error) {
-	rsaPub, ok := pub.(*rsa.PublicKey)
-	if !ok {
-		return nil, errors.New("x509: non-RSA public keys not supported")
+	var publicKeyBytes []byte
+	var publicKeyAlgorithm pkix.AlgorithmIdentifier
+
+	switch pub := pub.(type) {
+	case *rsa.PublicKey:
+		publicKeyBytes, err = asn1.Marshal(rsaPublicKey{
+			N: pub.N,
+			E: pub.E,
+		})
+		publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
+	case *ecdsa.PublicKey:
+		oid, ok := oidFromNamedCurve(pub.Curve)
+		if !ok {
+			return nil, errors.New("x509: unknown elliptic curve")
+		}
+		publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
+		var paramBytes []byte
+		paramBytes, err = asn1.Marshal(oid)
+		if err != nil {
+			return
+		}
+		publicKeyAlgorithm.Parameters.FullBytes = paramBytes
+		publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
+	default:
+		return nil, errors.New("x509: only RSA and ECDSA public keys supported")
 	}
 
-	rsaPriv, ok := priv.(*rsa.PrivateKey)
-	if !ok {
-		return nil, errors.New("x509: non-RSA private keys not supported")
+	var signatureAlgorithm pkix.AlgorithmIdentifier
+	var hashFunc crypto.Hash
+
+	switch priv := priv.(type) {
+	case *rsa.PrivateKey:
+		signatureAlgorithm.Algorithm = oidSignatureSHA1WithRSA
+		hashFunc = crypto.SHA1
+	case *ecdsa.PrivateKey:
+		switch priv.Curve {
+		case elliptic.P224(), elliptic.P256():
+			hashFunc = crypto.SHA256
+			signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA256
+		case elliptic.P384():
+			hashFunc = crypto.SHA384
+			signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA384
+		case elliptic.P521():
+			hashFunc = crypto.SHA512
+			signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA512
+		default:
+			return nil, errors.New("x509: unknown elliptic curve")
+		}
+	default:
+		return nil, errors.New("x509: only RSA and ECDSA private keys supported")
 	}
 
-	asn1PublicKey, err := asn1.Marshal(rsaPublicKey{
-		N: rsaPub.N,
-		E: rsaPub.E,
-	})
 	if err != nil {
 		return
 	}
@@ -954,15 +1252,15 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
 		return
 	}
 
-	encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey}
+	encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
 	c := tbsCertificate{
 		Version:            2,
 		SerialNumber:       template.SerialNumber,
-		SignatureAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
+		SignatureAlgorithm: signatureAlgorithm,
 		Issuer:             asn1.RawValue{FullBytes: asn1Issuer},
-		Validity:           validity{template.NotBefore, template.NotAfter},
+		Validity:           validity{template.NotBefore.UTC(), template.NotAfter.UTC()},
 		Subject:            asn1.RawValue{FullBytes: asn1Subject},
-		PublicKey:          publicKeyInfo{nil, pkix.AlgorithmIdentifier{Algorithm: oidRSA}, encodedPublicKey},
+		PublicKey:          publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
 		Extensions:         extensions,
 	}
 
@@ -973,11 +1271,24 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
 
 	c.Raw = tbsCertContents
 
-	h := sha1.New()
+	h := hashFunc.New()
 	h.Write(tbsCertContents)
 	digest := h.Sum(nil)
 
-	signature, err := rsa.SignPKCS1v15(rand, rsaPriv, crypto.SHA1, digest)
+	var signature []byte
+
+	switch priv := priv.(type) {
+	case *rsa.PrivateKey:
+		signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest)
+	case *ecdsa.PrivateKey:
+		var r, s *big.Int
+		if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil {
+			signature, err = asn1.Marshal(ecdsaSignature{r, s})
+		}
+	default:
+		panic("internal error")
+	}
+
 	if err != nil {
 		return
 	}
@@ -985,7 +1296,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
 	cert, err = asn1.Marshal(certificate{
 		nil,
 		c,
-		pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
+		signatureAlgorithm,
 		asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
 	})
 	return
@@ -1037,8 +1348,8 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts [
 			Algorithm: oidSignatureSHA1WithRSA,
 		},
 		Issuer:              c.Subject.ToRDNSequence(),
-		ThisUpdate:          now,
-		NextUpdate:          expiry,
+		ThisUpdate:          now.UTC(),
+		NextUpdate:          expiry.UTC(),
 		RevokedCertificates: revokedCerts,
 	}
 
diff --git a/src/pkg/crypto/x509/x509_test.go b/src/pkg/crypto/x509/x509_test.go
index f0327b0..abd4fe8 100644
--- a/src/pkg/crypto/x509/x509_test.go
+++ b/src/pkg/crypto/x509/x509_test.go
@@ -7,14 +7,20 @@ package x509
 import (
 	"bytes"
 	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
 	"crypto/rand"
 	"crypto/rsa"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
 	"crypto/x509/pkix"
 	"encoding/asn1"
 	"encoding/base64"
 	"encoding/hex"
 	"encoding/pem"
 	"math/big"
+	"net"
+	"reflect"
 	"testing"
 	"time"
 )
@@ -169,6 +175,49 @@ func TestMatchHostnames(t *testing.T) {
 	}
 }
 
+func TestMatchIP(t *testing.T) {
+	// Check that pattern matching is working.
+	c := &Certificate{
+		DNSNames: []string{"*.foo.bar.baz"},
+		Subject: pkix.Name{
+			CommonName: "*.foo.bar.baz",
+		},
+	}
+	err := c.VerifyHostname("quux.foo.bar.baz")
+	if err != nil {
+		t.Fatalf("VerifyHostname(quux.foo.bar.baz): %v", err)
+	}
+
+	// But check that if we change it to be matching against an IP address,
+	// it is rejected.
+	c = &Certificate{
+		DNSNames: []string{"*.2.3.4"},
+		Subject: pkix.Name{
+			CommonName: "*.2.3.4",
+		},
+	}
+	err = c.VerifyHostname("1.2.3.4")
+	if err == nil {
+		t.Fatalf("VerifyHostname(1.2.3.4) should have failed, did not")
+	}
+
+	c = &Certificate{
+		IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")},
+	}
+	err = c.VerifyHostname("127.0.0.1")
+	if err != nil {
+		t.Fatalf("VerifyHostname(127.0.0.1): %v", err)
+	}
+	err = c.VerifyHostname("::1")
+	if err != nil {
+		t.Fatalf("VerifyHostname(::1): %v", err)
+	}
+	err = c.VerifyHostname("[::1]")
+	if err != nil {
+		t.Fatalf("VerifyHostname([::1]): %v", err)
+	}
+}
+
 func TestCertificateParse(t *testing.T) {
 	s, _ := hex.DecodeString(certBytes)
 	certs, err := ParseCertificates(s)
@@ -237,65 +286,220 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
 	random := rand.Reader
 
 	block, _ := pem.Decode([]byte(pemPrivateKey))
-	priv, err := ParsePKCS1PrivateKey(block.Bytes)
+	rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes)
 	if err != nil {
-		t.Errorf("Failed to parse private key: %s", err)
-		return
+		t.Fatalf("Failed to parse private key: %s", err)
 	}
 
-	commonName := "test.example.com"
-	template := Certificate{
-		SerialNumber: big.NewInt(1),
-		Subject: pkix.Name{
-			CommonName:   commonName,
-			Organization: []string{"Acme Co"},
-		},
-		NotBefore: time.Unix(1000, 0),
-		NotAfter:  time.Unix(100000, 0),
+	ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		t.Fatalf("Failed to generate ECDSA key: %s", err)
+	}
 
-		SubjectKeyId: []byte{1, 2, 3, 4},
-		KeyUsage:     KeyUsageCertSign,
+	tests := []struct {
+		name      string
+		pub, priv interface{}
+		checkSig  bool
+	}{
+		{"RSA/RSA", &rsaPriv.PublicKey, rsaPriv, true},
+		{"RSA/ECDSA", &rsaPriv.PublicKey, ecdsaPriv, false},
+		{"ECDSA/RSA", &ecdsaPriv.PublicKey, rsaPriv, false},
+		{"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true},
+	}
 
-		BasicConstraintsValid: true,
-		IsCA:                  true,
-		DNSNames:              []string{"test.example.com"},
+	testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
+	testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{3, 2, 1}}
 
-		PolicyIdentifiers:   []asn1.ObjectIdentifier{[]int{1, 2, 3}},
-		PermittedDNSDomains: []string{".example.com", "example.com"},
-	}
+	for _, test := range tests {
+		commonName := "test.example.com"
+		template := Certificate{
+			SerialNumber: big.NewInt(1),
+			Subject: pkix.Name{
+				CommonName:   commonName,
+				Organization: []string{"Σ Acme Co"},
+			},
+			NotBefore: time.Unix(1000, 0),
+			NotAfter:  time.Unix(100000, 0),
 
-	derBytes, err := CreateCertificate(random, &template, &template, &priv.PublicKey, priv)
-	if err != nil {
-		t.Errorf("Failed to create certificate: %s", err)
-		return
-	}
+			SubjectKeyId: []byte{1, 2, 3, 4},
+			KeyUsage:     KeyUsageCertSign,
 
-	cert, err := ParseCertificate(derBytes)
-	if err != nil {
-		t.Errorf("Failed to parse certificate: %s", err)
-		return
-	}
+			ExtKeyUsage:        testExtKeyUsage,
+			UnknownExtKeyUsage: testUnknownExtKeyUsage,
 
-	if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
-		t.Errorf("Failed to parse policy identifiers: got:%#v want:%#v", cert.PolicyIdentifiers, template.PolicyIdentifiers)
-	}
+			BasicConstraintsValid: true,
+			IsCA: true,
 
-	if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
-		t.Errorf("Failed to parse name constraints: %#v", cert.PermittedDNSDomains)
-	}
+			DNSNames:       []string{"test.example.com"},
+			EmailAddresses: []string{"gopher at golang.org"},
+			IPAddresses:    []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
 
-	if cert.Subject.CommonName != commonName {
-		t.Errorf("Subject wasn't correctly copied from the template. Got %s, want %s", cert.Subject.CommonName, commonName)
-	}
+			PolicyIdentifiers:   []asn1.ObjectIdentifier{[]int{1, 2, 3}},
+			PermittedDNSDomains: []string{".example.com", "example.com"},
+		}
+
+		derBytes, err := CreateCertificate(random, &template, &template, test.pub, test.priv)
+		if err != nil {
+			t.Errorf("%s: failed to create certificate: %s", test.name, err)
+			continue
+		}
+
+		cert, err := ParseCertificate(derBytes)
+		if err != nil {
+			t.Errorf("%s: failed to parse certificate: %s", test.name, err)
+			continue
+		}
+
+		if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
+			t.Errorf("%s: failed to parse policy identifiers: got:%#v want:%#v", test.name, cert.PolicyIdentifiers, template.PolicyIdentifiers)
+		}
+
+		if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
+			t.Errorf("%s: failed to parse name constraints: %#v", test.name, cert.PermittedDNSDomains)
+		}
+
+		if cert.Subject.CommonName != commonName {
+			t.Errorf("%s: subject wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Subject.CommonName, commonName)
+		}
+
+		if cert.Issuer.CommonName != commonName {
+			t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName)
+		}
+
+		if !reflect.DeepEqual(cert.ExtKeyUsage, testExtKeyUsage) {
+			t.Errorf("%s: extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.ExtKeyUsage, testExtKeyUsage)
+		}
 
-	if cert.Issuer.CommonName != commonName {
-		t.Errorf("Issuer wasn't correctly copied from the template. Got %s, want %s", cert.Issuer.CommonName, commonName)
+		if !reflect.DeepEqual(cert.UnknownExtKeyUsage, testUnknownExtKeyUsage) {
+			t.Errorf("%s: unknown extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.UnknownExtKeyUsage, testUnknownExtKeyUsage)
+		}
+
+		if !reflect.DeepEqual(cert.DNSNames, template.DNSNames) {
+			t.Errorf("%s: SAN DNS names differ from template. Got %v, want %v", test.name, cert.DNSNames, template.DNSNames)
+		}
+
+		if !reflect.DeepEqual(cert.EmailAddresses, template.EmailAddresses) {
+			t.Errorf("%s: SAN emails differ from template. Got %v, want %v", test.name, cert.EmailAddresses, template.EmailAddresses)
+		}
+
+		if !reflect.DeepEqual(cert.IPAddresses, template.IPAddresses) {
+			t.Errorf("%s: SAN IPs differ from template. Got %v, want %v", test.name, cert.IPAddresses, template.IPAddresses)
+		}
+
+		if test.checkSig {
+			err = cert.CheckSignatureFrom(cert)
+			if err != nil {
+				t.Errorf("%s: signature verification failed: %s", test.name, err)
+			}
+		}
 	}
+}
 
-	err = cert.CheckSignatureFrom(cert)
-	if err != nil {
-		t.Errorf("Signature verification failed: %s", err)
-		return
+// Self-signed certificate using ECDSA with SHA1 & secp256r1
+var ecdsaSHA1CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICDjCCAbUCCQDF6SfN0nsnrjAJBgcqhkjOPQQBMIGPMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMG
+A1UECgwMR29vZ2xlLCBJbmMuMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIwMjAyMDUw
+WhcNMjIwNTE4MjAyMDUwWjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTATBgNVBAoMDEdvb2dsZSwg
+SW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAhBgkqhkiG9w0BCQEWFGdv
+bGFuZy1kZXZAZ21haWwuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/Wgn
+WQDo5+bz71T0327ERgd5SDDXFbXLpzIZDXTkjpe8QTEbsF+ezsQfrekrpDPC4Cd3
+P9LY0tG+aI8IyVKdUjAJBgcqhkjOPQQBA0gAMEUCIGlsqMcRqWVIWTD6wXwe6Jk2
+DKxL46r/FLgJYnzBEH99AiEA3fBouObsvV1R3oVkb4BQYnD4/4LeId6lAT43YvyV
+a/A=
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA256 & secp256r1
+var ecdsaSHA256p256CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICDzCCAbYCCQDlsuMWvgQzhTAKBggqhkjOPQQDAjCBjzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
+BgNVBAoMDEdvb2dsZSwgSW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAh
+BgkqhkiG9w0BCQEWFGdvbGFuZy1kZXZAZ21haWwuY29tMB4XDTEyMDUyMTAwMTkx
+NloXDTIyMDUxOTAwMTkxNlowgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYDVQQKDAxHb29nbGUs
+IEluYy4xFzAVBgNVBAMMDnd3dy5nb29nbGUuY29tMSMwIQYJKoZIhvcNAQkBFhRn
+b2xhbmctZGV2QGdtYWlsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPMt
+2ErhxAty5EJRu9yM+MTy+hUXm3pdW1ensAv382KoGExSXAFWP7pjJnNtHO+XSwVm
+YNtqjcAGFKpweoN//kQwCgYIKoZIzj0EAwIDRwAwRAIgIYSaUA/IB81gjbIw/hUV
+70twxJr5EcgOo0hLp3Jm+EYCIFDO3NNcgmURbJ1kfoS3N/0O+irUtoPw38YoNkqJ
+h5wi
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA256 & secp384r1
+var ecdsaSHA256p384CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICSjCCAdECCQDje/no7mXkVzAKBggqhkjOPQQDAjCBjjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
+BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMDYxMDM0
+WhcNMjIwNTE5MDYxMDM0WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
+SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
+YW5nLWRldkBnbWFpbC5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARRuzRNIKRK
+jIktEmXanNmrTR/q/FaHXLhWRZ6nHWe26Fw7Rsrbk+VjGy4vfWtNn7xSFKrOu5ze
+qxKnmE0h5E480MNgrUiRkaGO2GMJJVmxx20aqkXOk59U8yGA4CghE6MwCgYIKoZI
+zj0EAwIDZwAwZAIwBZEN8gvmRmfeP/9C1PRLzODIY4JqWub2PLRT4mv9GU+yw3Gr
+PU9A3CHMdEcdw/MEAjBBO1lId8KOCh9UZunsSMfqXiVurpzmhWd6VYZ/32G+M+Mh
+3yILeYQzllt/g0rKVRk=
+-----END CERTIFICATE-----
+`
+
+// Self-signed certificate using ECDSA with SHA384 & secp521r1
+var ecdsaSHA384p521CertPem = `
+-----BEGIN CERTIFICATE-----
+MIICljCCAfcCCQDhp1AFD/ahKjAKBggqhkjOPQQDAzCBjjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
+BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
+CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMTUwNDI5
+WhcNMjIwNTE5MTUwNDI5WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
+b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
+SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
+YW5nLWRldkBnbWFpbC5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACqx9Rv
+IssRs1LWYcNN+WffwlHw4Tv3y8/LIAA9MF1ZScIonU9nRMxt4a2uGJVCPDw6JHpz
+PaYc0E9puLoE9AfKpwFr59Jkot7dBg55SKPEFkddoip/rvmN7NPAWjMBirOwjOkm
+8FPthvPhGPqsu9AvgVuHu3PosWiHGNrhh379pva8MzAKBggqhkjOPQQDAwOBjAAw
+gYgCQgEHNmswkUdPpHqrVxp9PvLVl+xxPuHBkT+75z9JizyxtqykHQo9Uh6SWCYH
+BF9KLolo01wMt8DjoYP5Fb3j5MH7xwJCAbWZzTOp4l4DPkIvAh4LeC4VWbwPPyqh
+kBg71w/iEcSY3wUKgHGcJJrObZw7wys91I5kENljqw/Samdr3ka+jBJa
+-----END CERTIFICATE-----
+`
+
+var ecdsaTests = []struct {
+	sigAlgo SignatureAlgorithm
+	pemCert string
+}{
+	{ECDSAWithSHA1, ecdsaSHA1CertPem},
+	{ECDSAWithSHA256, ecdsaSHA256p256CertPem},
+	{ECDSAWithSHA256, ecdsaSHA256p384CertPem},
+	{ECDSAWithSHA384, ecdsaSHA384p521CertPem},
+}
+
+func TestECDSA(t *testing.T) {
+	for i, test := range ecdsaTests {
+		pemBlock, _ := pem.Decode([]byte(test.pemCert))
+		cert, err := ParseCertificate(pemBlock.Bytes)
+		if err != nil {
+			t.Errorf("%d: failed to parse certificate: %s", i, err)
+			continue
+		}
+		if sa := cert.SignatureAlgorithm; sa != test.sigAlgo {
+			t.Errorf("%d: signature algorithm is %v, want %v", i, sa, test.sigAlgo)
+		}
+		if parsedKey, ok := cert.PublicKey.(*ecdsa.PublicKey); !ok {
+			t.Errorf("%d: wanted an ECDSA public key but found: %#v", i, parsedKey)
+		}
+		if pka := cert.PublicKeyAlgorithm; pka != ECDSA {
+			t.Errorf("%d: public key algorithm is %v, want ECDSA", i, pka)
+		}
+		if err = cert.CheckSignatureFrom(cert); err != nil {
+			t.Errorf("%d: certificate verification failed: %s", i, err)
+		}
 	}
 }
 
@@ -374,7 +578,7 @@ func TestVerifyCertificateWithDSASignature(t *testing.T) {
 	}
 	// test cert is self-signed
 	if err = cert.CheckSignatureFrom(cert); err != nil {
-		t.Fatalf("DSA Certificate verfication failed: %s", err)
+		t.Fatalf("DSA Certificate verification failed: %s", err)
 	}
 }
 
diff --git a/src/pkg/database/sql/convert.go b/src/pkg/database/sql/convert.go
index bfcb03c..853a782 100644
--- a/src/pkg/database/sql/convert.go
+++ b/src/pkg/database/sql/convert.go
@@ -14,53 +14,115 @@ import (
 	"strconv"
 )
 
-// subsetTypeArgs takes a slice of arguments from callers of the sql
-// package and converts them into a slice of the driver package's
-// "subset types".
-func subsetTypeArgs(args []interface{}) ([]driver.Value, error) {
-	out := make([]driver.Value, len(args))
+var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
+
+// driverArgs converts arguments from callers of Stmt.Exec and
+// Stmt.Query into driver Values.
+//
+// The statement si may be nil, if no statement is available.
+func driverArgs(si driver.Stmt, args []interface{}) ([]driver.Value, error) {
+	dargs := make([]driver.Value, len(args))
+	cc, ok := si.(driver.ColumnConverter)
+
+	// Normal path, for a driver.Stmt that is not a ColumnConverter.
+	if !ok {
+		for n, arg := range args {
+			var err error
+			dargs[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
+			if err != nil {
+				return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
+			}
+		}
+		return dargs, nil
+	}
+
+	// Let the Stmt convert its own arguments.
 	for n, arg := range args {
+		// First, see if the value itself knows how to convert
+		// itself to a driver type.  For example, a NullString
+		// struct changing into a string or nil.
+		if svi, ok := arg.(driver.Valuer); ok {
+			sv, err := svi.Value()
+			if err != nil {
+				return nil, fmt.Errorf("sql: argument index %d from Value: %v", n, err)
+			}
+			if !driver.IsValue(sv) {
+				return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from Value", n, sv)
+			}
+			arg = sv
+		}
+
+		// Second, ask the column to sanity check itself. For
+		// example, drivers might use this to make sure that
+		// an int64 values being inserted into a 16-bit
+		// integer field is in range (before getting
+		// truncated), or that a nil can't go into a NOT NULL
+		// column before going across the network to get the
+		// same error.
 		var err error
-		out[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
+		dargs[n], err = cc.ColumnConverter(n).ConvertValue(arg)
 		if err != nil {
-			return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n+1, err)
+			return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n, err)
+		}
+		if !driver.IsValue(dargs[n]) {
+			return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T",
+				arg, dargs[n])
 		}
 	}
-	return out, nil
+
+	return dargs, nil
 }
 
 // convertAssign copies to dest the value in src, converting it if possible.
 // An error is returned if the copy would result in loss of information.
 // dest should be a pointer type.
 func convertAssign(dest, src interface{}) error {
-	// Common cases, without reflect.  Fall through.
+	// Common cases, without reflect.
 	switch s := src.(type) {
 	case string:
 		switch d := dest.(type) {
 		case *string:
+			if d == nil {
+				return errNilPtr
+			}
 			*d = s
 			return nil
 		case *[]byte:
+			if d == nil {
+				return errNilPtr
+			}
 			*d = []byte(s)
 			return nil
 		}
 	case []byte:
 		switch d := dest.(type) {
 		case *string:
+			if d == nil {
+				return errNilPtr
+			}
 			*d = string(s)
 			return nil
 		case *interface{}:
+			if d == nil {
+				return errNilPtr
+			}
 			bcopy := make([]byte, len(s))
 			copy(bcopy, s)
 			*d = bcopy
 			return nil
 		case *[]byte:
+			if d == nil {
+				return errNilPtr
+			}
 			*d = s
 			return nil
 		}
 	case nil:
 		switch d := dest.(type) {
 		case *[]byte:
+			if d == nil {
+				return errNilPtr
+			}
 			*d = nil
 			return nil
 		}
@@ -98,6 +160,9 @@ func convertAssign(dest, src interface{}) error {
 	if dpv.Kind() != reflect.Ptr {
 		return errors.New("destination not a pointer")
 	}
+	if dpv.IsNil() {
+		return errNilPtr
+	}
 
 	if !sv.IsValid() {
 		sv = reflect.ValueOf(src)
diff --git a/src/pkg/database/sql/doc.txt b/src/pkg/database/sql/doc.txt
index fb16595..405c5ed 100644
--- a/src/pkg/database/sql/doc.txt
+++ b/src/pkg/database/sql/doc.txt
@@ -21,7 +21,7 @@ Goals of the sql and sql/driver packages:
   Database Driver -> sql (to register) + sql/driver (implement interfaces)
 
 * Make type casting/conversions consistent between all drivers. To
-  achieve this, most of the conversions are done in the db package,
+  achieve this, most of the conversions are done in the sql package,
   not in each driver. The drivers then only have to deal with a
   smaller set of types.
 
diff --git a/src/pkg/database/sql/driver/driver.go b/src/pkg/database/sql/driver/driver.go
index 2f5280d..2434e41 100644
--- a/src/pkg/database/sql/driver/driver.go
+++ b/src/pkg/database/sql/driver/driver.go
@@ -56,7 +56,7 @@ var ErrBadConn = errors.New("driver: bad connection")
 
 // Execer is an optional interface that may be implemented by a Conn.
 //
-// If a Conn does not implement Execer, the db package's DB.Exec will
+// If a Conn does not implement Execer, the sql package's DB.Exec will
 // first prepare a query, execute the statement, and then close the
 // statement.
 //
@@ -65,6 +65,17 @@ type Execer interface {
 	Exec(query string, args []Value) (Result, error)
 }
 
+// Queryer is an optional interface that may be implemented by a Conn.
+//
+// If a Conn does not implement Queryer, the sql package's DB.Query will
+// first prepare a query, execute the statement, and then close the
+// statement.
+//
+// Query may return ErrSkip.
+type Queryer interface {
+	Query(query string, args []Value) (Rows, error)
+}
+
 // Conn is a connection to a database. It is not used concurrently
 // by multiple goroutines.
 //
@@ -104,23 +115,8 @@ type Result interface {
 type Stmt interface {
 	// Close closes the statement.
 	//
-	// Closing a statement should not interrupt any outstanding
-	// query created from that statement. That is, the following
-	// order of operations is valid:
-	//
-	//  * create a driver statement
-	//  * call Query on statement, returning Rows
-	//  * close the statement
-	//  * read from Rows
-	//
-	// If closing a statement invalidates currently-running
-	// queries, the final step above will incorrectly fail.
-	//
-	// TODO(bradfitz): possibly remove the restriction above, if
-	// enough driver authors object and find it complicates their
-	// code too much. The sql package could be smarter about
-	// refcounting the statement and closing it at the appropriate
-	// time.
+	// As of Go 1.1, a Stmt will not be closed if it's in use
+	// by any queries.
 	Close() error
 
 	// NumInput returns the number of placeholder parameters.
diff --git a/src/pkg/database/sql/example_test.go b/src/pkg/database/sql/example_test.go
new file mode 100644
index 0000000..d47eed5
--- /dev/null
+++ b/src/pkg/database/sql/example_test.go
@@ -0,0 +1,45 @@
+// 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 sql_test
+
+import (
+	"database/sql"
+	"fmt"
+	"log"
+)
+
+var db *sql.DB
+
+func ExampleDB_Query() {
+	age := 27
+	rows, err := db.Query("SELECT name FROM users WHERE age=?", age)
+	if err != nil {
+		log.Fatal(err)
+	}
+	for rows.Next() {
+		var name string
+		if err := rows.Scan(&name); err != nil {
+			log.Fatal(err)
+		}
+		fmt.Printf("%s is %d\n", name, age)
+	}
+	if err := rows.Err(); err != nil {
+		log.Fatal(err)
+	}
+}
+
+func ExampleDB_QueryRow() {
+	id := 123
+	var username string
+	err := db.QueryRow("SELECT username FROM users WHERE id=?", id).Scan(&username)
+	switch {
+	case err == sql.ErrNoRows:
+		log.Printf("No user with that ID.")
+	case err != nil:
+		log.Fatal(err)
+	default:
+		fmt.Printf("Username is %s\n", username)
+	}
+}
diff --git a/src/pkg/database/sql/fakedb_test.go b/src/pkg/database/sql/fakedb_test.go
index 184e775..55597f7 100644
--- a/src/pkg/database/sql/fakedb_test.go
+++ b/src/pkg/database/sql/fakedb_test.go
@@ -31,7 +31,7 @@ var _ = log.Printf
 //   INSERT|<tablename>|col=val,col2=val2,col3=?
 //   SELECT|<tablename>|projectcol1,projectcol2|filtercol=?,filtercol2=?
 //
-// When opening a a fakeDriver's database, it starts empty with no
+// When opening a fakeDriver's database, it starts empty with no
 // tables.  All tables and data are stored in memory only.
 type fakeDriver struct {
 	mu        sync.Mutex
@@ -42,9 +42,10 @@ type fakeDriver struct {
 type fakeDB struct {
 	name string
 
-	mu     sync.Mutex
-	free   []*fakeConn
-	tables map[string]*table
+	mu      sync.Mutex
+	free    []*fakeConn
+	tables  map[string]*table
+	badConn bool
 }
 
 type table struct {
@@ -83,6 +84,7 @@ type fakeConn struct {
 	stmtsMade   int
 	stmtsClosed int
 	numPrepare  int
+	bad         bool
 }
 
 func (c *fakeConn) incrStat(v *int) {
@@ -122,7 +124,9 @@ func init() {
 
 // Supports dsn forms:
 //    <dbname>
-//    <dbname>;<opts>  (no currently supported options)
+//    <dbname>;<opts>  (only currently supported option is `badConn`,
+//                      which causes driver.ErrBadConn to be returned on
+//                      every other conn.Begin())
 func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
 	parts := strings.Split(dsn, ";")
 	if len(parts) < 1 {
@@ -135,7 +139,12 @@ func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
 	d.mu.Lock()
 	d.openCount++
 	d.mu.Unlock()
-	return &fakeConn{db: db}, nil
+	conn := &fakeConn{db: db}
+
+	if len(parts) >= 2 && parts[1] == "badConn" {
+		conn.bad = true
+	}
+	return conn, nil
 }
 
 func (d *fakeDriver) getDB(name string) *fakeDB {
@@ -199,7 +208,20 @@ func (db *fakeDB) columnType(table, column string) (typ string, ok bool) {
 	return "", false
 }
 
+func (c *fakeConn) isBad() bool {
+	// if not simulating bad conn, do nothing
+	if !c.bad {
+		return false
+	}
+	// alternate between bad conn and not bad conn
+	c.db.badConn = !c.db.badConn
+	return c.db.badConn
+}
+
 func (c *fakeConn) Begin() (driver.Tx, error) {
+	if c.isBad() {
+		return nil, driver.ErrBadConn
+	}
 	if c.currTx != nil {
 		return nil, errors.New("already in a transaction")
 	}
@@ -234,7 +256,19 @@ func checkSubsetTypes(args []driver.Value) error {
 
 func (c *fakeConn) Exec(query string, args []driver.Value) (driver.Result, error) {
 	// This is an optional interface, but it's implemented here
-	// just to check that all the args of of the proper types.
+	// just to check that all the args are of the proper types.
+	// ErrSkip is returned so the caller acts as if we didn't
+	// implement this at all.
+	err := checkSubsetTypes(args)
+	if err != nil {
+		return nil, err
+	}
+	return nil, driver.ErrSkip
+}
+
+func (c *fakeConn) Query(query string, args []driver.Value) (driver.Rows, error) {
+	// This is an optional interface, but it's implemented here
+	// just to check that all the args are of the proper types.
 	// ErrSkip is returned so the caller acts as if we didn't
 	// implement this at all.
 	err := checkSubsetTypes(args)
@@ -249,7 +283,7 @@ func errf(msg string, args ...interface{}) error {
 }
 
 // parts are table|selectCol1,selectCol2|whereCol=?,whereCol2=?
-// (note that where where columns must always contain ? marks,
+// (note that where columns must always contain ? marks,
 //  just a limitation for fakedb)
 func (c *fakeConn) prepareSelect(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
 	if len(parts) != 3 {
@@ -383,6 +417,9 @@ func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
 }
 
 func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
+	if len(s.placeholderConverter) == 0 {
+		return driver.DefaultParameterConverter
+	}
 	return s.placeholderConverter[idx]
 }
 
@@ -598,6 +635,28 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
 	return nil
 }
 
+// fakeDriverString is like driver.String, but indirects pointers like
+// DefaultValueConverter.
+//
+// This could be surprising behavior to retroactively apply to
+// driver.String now that Go1 is out, but this is convenient for
+// our TestPointerParamsAndScans.
+//
+type fakeDriverString struct{}
+
+func (fakeDriverString) ConvertValue(v interface{}) (driver.Value, error) {
+	switch c := v.(type) {
+	case string, []byte:
+		return v, nil
+	case *string:
+		if c == nil {
+			return nil, nil
+		}
+		return *c, nil
+	}
+	return fmt.Sprintf("%v", v), nil
+}
+
 func converterForType(typ string) driver.ValueConverter {
 	switch typ {
 	case "bool":
@@ -607,9 +666,9 @@ func converterForType(typ string) driver.ValueConverter {
 	case "int32":
 		return driver.Int32
 	case "string":
-		return driver.NotNull{Converter: driver.String}
+		return driver.NotNull{Converter: fakeDriverString{}}
 	case "nullstring":
-		return driver.Null{Converter: driver.String}
+		return driver.Null{Converter: fakeDriverString{}}
 	case "int64":
 		// TODO(coopernurse): add type-specific converter
 		return driver.NotNull{Converter: driver.DefaultParameterConverter}
diff --git a/src/pkg/database/sql/sql.go b/src/pkg/database/sql/sql.go
index 89136ef..4faaa11 100644
--- a/src/pkg/database/sql/sql.go
+++ b/src/pkg/database/sql/sql.go
@@ -11,6 +11,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"runtime"
 	"sync"
 )
 
@@ -189,9 +190,66 @@ type DB struct {
 	driver driver.Driver
 	dsn    string
 
-	mu       sync.Mutex // protects freeConn and closed
-	freeConn []driver.Conn
-	closed   bool
+	mu        sync.Mutex           // protects following fields
+	outConn   map[driver.Conn]bool // whether the conn is in use
+	freeConn  []driver.Conn
+	closed    bool
+	dep       map[finalCloser]depSet
+	onConnPut map[driver.Conn][]func() // code (with mu held) run when conn is next returned
+	lastPut   map[driver.Conn]string   // stacktrace of last conn's put; debug only
+}
+
+// depSet is a finalCloser's outstanding dependencies
+type depSet map[interface{}]bool // set of true bools
+
+// The finalCloser interface is used by (*DB).addDep and (*DB).get
+type finalCloser interface {
+	// finalClose is called when the reference count of an object
+	// goes to zero. (*DB).mu is not held while calling it.
+	finalClose() error
+}
+
+// addDep notes that x now depends on dep, and x's finalClose won't be
+// called until all of x's dependencies are removed with removeDep.
+func (db *DB) addDep(x finalCloser, dep interface{}) {
+	//println(fmt.Sprintf("addDep(%T %p, %T %p)", x, x, dep, dep))
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	if db.dep == nil {
+		db.dep = make(map[finalCloser]depSet)
+	}
+	xdep := db.dep[x]
+	if xdep == nil {
+		xdep = make(depSet)
+		db.dep[x] = xdep
+	}
+	xdep[dep] = true
+}
+
+// removeDep notes that x no longer depends on dep.
+// If x still has dependencies, nil is returned.
+// If x no longer has any dependencies, its finalClose method will be
+// called and its error value will be returned.
+func (db *DB) removeDep(x finalCloser, dep interface{}) error {
+	//println(fmt.Sprintf("removeDep(%T %p, %T %p)", x, x, dep, dep))
+	done := false
+
+	db.mu.Lock()
+	xdep := db.dep[x]
+	if xdep != nil {
+		delete(xdep, dep)
+		if len(xdep) == 0 {
+			delete(db.dep, x)
+			done = true
+		}
+	}
+	db.mu.Unlock()
+
+	if !done {
+		return nil
+	}
+	//println(fmt.Sprintf("calling final close on %T %v (%#v)", x, x, x))
+	return x.finalClose()
 }
 
 // Open opens a database specified by its database driver name and a
@@ -201,11 +259,20 @@ type DB struct {
 // Most users will open a database via a driver-specific connection
 // helper function that returns a *DB.
 func Open(driverName, dataSourceName string) (*DB, error) {
-	driver, ok := drivers[driverName]
+	driveri, ok := drivers[driverName]
 	if !ok {
 		return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
 	}
-	return &DB{driver: driver, dsn: dataSourceName}, nil
+	// TODO: optionally proactively connect to a Conn to check
+	// the dataSourceName: golang.org/issue/4804
+	db := &DB{
+		driver:    driveri,
+		dsn:       dataSourceName,
+		outConn:   make(map[driver.Conn]bool),
+		lastPut:   make(map[driver.Conn]string),
+		onConnPut: make(map[driver.Conn][]func()),
+	}
+	return db, nil
 }
 
 // Close closes the database, releasing any open resources.
@@ -241,22 +308,38 @@ func (db *DB) conn() (driver.Conn, error) {
 	if n := len(db.freeConn); n > 0 {
 		conn := db.freeConn[n-1]
 		db.freeConn = db.freeConn[:n-1]
+		db.outConn[conn] = true
 		db.mu.Unlock()
 		return conn, nil
 	}
 	db.mu.Unlock()
-	return db.driver.Open(db.dsn)
+	conn, err := db.driver.Open(db.dsn)
+	if err == nil {
+		db.mu.Lock()
+		db.outConn[conn] = true
+		db.mu.Unlock()
+	}
+	return conn, err
 }
 
+// connIfFree returns (wanted, true) if wanted is still a valid conn and
+// isn't in use.
+//
+// If wanted is valid but in use, connIfFree returns (wanted, false).
+// If wanted is invalid, connIfFre returns (nil, false).
 func (db *DB) connIfFree(wanted driver.Conn) (conn driver.Conn, ok bool) {
 	db.mu.Lock()
 	defer db.mu.Unlock()
+	if db.outConn[wanted] {
+		return conn, false
+	}
 	for i, conn := range db.freeConn {
 		if conn != wanted {
 			continue
 		}
 		db.freeConn[i] = db.freeConn[len(db.freeConn)-1]
 		db.freeConn = db.freeConn[:len(db.freeConn)-1]
+		db.outConn[wanted] = true
 		return wanted, true
 	}
 	return nil, false
@@ -265,14 +348,52 @@ func (db *DB) connIfFree(wanted driver.Conn) (conn driver.Conn, ok bool) {
 // putConnHook is a hook for testing.
 var putConnHook func(*DB, driver.Conn)
 
+// noteUnusedDriverStatement notes that si is no longer used and should
+// be closed whenever possible (when c is next not in use), unless c is
+// already closed.
+func (db *DB) noteUnusedDriverStatement(c driver.Conn, si driver.Stmt) {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	if db.outConn[c] {
+		db.onConnPut[c] = append(db.onConnPut[c], func() {
+			si.Close()
+		})
+	} else {
+		si.Close()
+	}
+}
+
+// debugGetPut determines whether getConn & putConn calls' stack traces
+// are returned for more verbose crashes.
+const debugGetPut = false
+
 // putConn adds a connection to the db's free pool.
-// err is optionally the last error that occured on this connection.
+// err is optionally the last error that occurred on this connection.
 func (db *DB) putConn(c driver.Conn, err error) {
+	db.mu.Lock()
+	if !db.outConn[c] {
+		if debugGetPut {
+			fmt.Printf("putConn(%v) DUPLICATE was: %s\n\nPREVIOUS was: %s", c, stack(), db.lastPut[c])
+		}
+		panic("sql: connection returned that was never out")
+	}
+	if debugGetPut {
+		db.lastPut[c] = stack()
+	}
+	delete(db.outConn, c)
+
+	if fns, ok := db.onConnPut[c]; ok {
+		for _, fn := range fns {
+			fn()
+		}
+		delete(db.onConnPut, c)
+	}
+
 	if err == driver.ErrBadConn {
 		// Don't reuse bad connections.
+		db.mu.Unlock()
 		return
 	}
-	db.mu.Lock()
 	if putConnHook != nil {
 		putConnHook(db, c)
 	}
@@ -287,7 +408,9 @@ func (db *DB) putConn(c driver.Conn, err error) {
 	c.Close()
 }
 
-// Prepare creates a prepared statement for later execution.
+// Prepare creates a prepared statement for later queries or executions.
+// Multiple queries or executions may be run concurrently from the
+// returned statement.
 func (db *DB) Prepare(query string) (*Stmt, error) {
 	var stmt *Stmt
 	var err error
@@ -300,7 +423,7 @@ func (db *DB) Prepare(query string) (*Stmt, error) {
 	return stmt, err
 }
 
-func (db *DB) prepare(query string) (stmt *Stmt, err error) {
+func (db *DB) prepare(query string) (*Stmt, error) {
 	// TODO: check if db.driver supports an optional
 	// driver.Preparer interface and call that instead, if so,
 	// otherwise we make a prepared statement that's bound
@@ -311,28 +434,27 @@ func (db *DB) prepare(query string) (stmt *Stmt, err error) {
 	if err != nil {
 		return nil, err
 	}
-	defer db.putConn(ci, err)
 	si, err := ci.Prepare(query)
 	if err != nil {
+		db.putConn(ci, err)
 		return nil, err
 	}
-	stmt = &Stmt{
+	stmt := &Stmt{
 		db:    db,
 		query: query,
 		css:   []connStmt{{ci, si}},
 	}
+	db.addDep(stmt, stmt)
 	return stmt, nil
 }
 
 // Exec executes a query without returning any rows.
+// The args are for any placeholder parameters in the query.
 func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
-	sargs, err := subsetTypeArgs(args)
-	if err != nil {
-		return nil, err
-	}
 	var res Result
+	var err error
 	for i := 0; i < 10; i++ {
-		res, err = db.exec(query, sargs)
+		res, err = db.exec(query, args)
 		if err != driver.ErrBadConn {
 			break
 		}
@@ -340,15 +462,21 @@ func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
 	return res, err
 }
 
-func (db *DB) exec(query string, sargs []driver.Value) (res Result, err error) {
+func (db *DB) exec(query string, args []interface{}) (res Result, err error) {
 	ci, err := db.conn()
 	if err != nil {
 		return nil, err
 	}
-	defer db.putConn(ci, err)
+	defer func() {
+		db.putConn(ci, err)
+	}()
 
 	if execer, ok := ci.(driver.Execer); ok {
-		resi, err := execer.Exec(query, sargs)
+		dargs, err := driverArgs(nil, args)
+		if err != nil {
+			return nil, err
+		}
+		resi, err := execer.Exec(query, dargs)
 		if err != driver.ErrSkip {
 			if err != nil {
 				return nil, err
@@ -363,25 +491,83 @@ func (db *DB) exec(query string, sargs []driver.Value) (res Result, err error) {
 	}
 	defer sti.Close()
 
-	resi, err := sti.Exec(sargs)
+	return resultFromStatement(sti, args...)
+}
+
+// Query executes a query that returns rows, typically a SELECT.
+// The args are for any placeholder parameters in the query.
+func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
+	var rows *Rows
+	var err error
+	for i := 0; i < 10; i++ {
+		rows, err = db.query(query, args)
+		if err != driver.ErrBadConn {
+			break
+		}
+	}
+	return rows, err
+}
+
+func (db *DB) query(query string, args []interface{}) (*Rows, error) {
+	ci, err := db.conn()
 	if err != nil {
 		return nil, err
 	}
-	return result{resi}, nil
+
+	releaseConn := func(err error) { db.putConn(ci, err) }
+
+	return db.queryConn(ci, releaseConn, query, args)
 }
 
-// Query executes a query that returns rows, typically a SELECT.
-func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
-	stmt, err := db.Prepare(query)
+// queryConn executes a query on the given connection.
+// The connection gets released by the releaseConn function.
+func (db *DB) queryConn(ci driver.Conn, releaseConn func(error), query string, args []interface{}) (*Rows, error) {
+	if queryer, ok := ci.(driver.Queryer); ok {
+		dargs, err := driverArgs(nil, args)
+		if err != nil {
+			releaseConn(err)
+			return nil, err
+		}
+		rowsi, err := queryer.Query(query, dargs)
+		if err != driver.ErrSkip {
+			if err != nil {
+				releaseConn(err)
+				return nil, err
+			}
+			// Note: ownership of ci passes to the *Rows, to be freed
+			// with releaseConn.
+			rows := &Rows{
+				db:          db,
+				ci:          ci,
+				releaseConn: releaseConn,
+				rowsi:       rowsi,
+			}
+			return rows, nil
+		}
+	}
+
+	sti, err := ci.Prepare(query)
 	if err != nil {
+		releaseConn(err)
 		return nil, err
 	}
-	rows, err := stmt.Query(args...)
+
+	rowsi, err := rowsiFromStatement(sti, args...)
 	if err != nil {
-		stmt.Close()
+		releaseConn(err)
+		sti.Close()
 		return nil, err
 	}
-	rows.closeStmt = stmt
+
+	// Note: ownership of ci passes to the *Rows, to be freed
+	// with releaseConn.
+	rows := &Rows{
+		db:          db,
+		ci:          ci,
+		releaseConn: releaseConn,
+		rowsi:       rowsi,
+		closeStmt:   sti,
+	}
 	return rows, nil
 }
 
@@ -415,7 +601,7 @@ func (db *DB) begin() (tx *Tx, err error) {
 	txi, err := ci.Begin()
 	if err != nil {
 		db.putConn(ci, err)
-		return nil, fmt.Errorf("sql: failed to Begin transaction: %v", err)
+		return nil, err
 	}
 	return &Tx{
 		db:  db,
@@ -577,13 +763,12 @@ func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
 	}
 	defer tx.releaseConn()
 
-	sargs, err := subsetTypeArgs(args)
-	if err != nil {
-		return nil, err
-	}
-
 	if execer, ok := ci.(driver.Execer); ok {
-		resi, err := execer.Exec(query, sargs)
+		dargs, err := driverArgs(nil, args)
+		if err != nil {
+			return nil, err
+		}
+		resi, err := execer.Exec(query, dargs)
 		if err == nil {
 			return result{resi}, nil
 		}
@@ -598,29 +783,19 @@ func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
 	}
 	defer sti.Close()
 
-	resi, err := sti.Exec(sargs)
-	if err != nil {
-		return nil, err
-	}
-	return result{resi}, nil
+	return resultFromStatement(sti, args...)
 }
 
 // Query executes a query that returns rows, typically a SELECT.
 func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
-	if tx.done {
-		return nil, ErrTxDone
-	}
-	stmt, err := tx.Prepare(query)
-	if err != nil {
-		return nil, err
-	}
-	rows, err := stmt.Query(args...)
+	ci, err := tx.grabConn()
 	if err != nil {
-		stmt.Close()
 		return nil, err
 	}
-	rows.closeStmt = stmt
-	return rows, err
+
+	releaseConn := func(err error) { tx.releaseConn() }
+
+	return tx.db.queryConn(ci, releaseConn, query, args)
 }
 
 // QueryRow executes a query that is expected to return at most one row.
@@ -644,6 +819,8 @@ type Stmt struct {
 	query     string // that created the Stmt
 	stickyErr error  // if non-nil, this error is returned for all operations
 
+	closemu sync.RWMutex // held exclusively during close, for read otherwise.
+
 	// If in a transaction, else both nil:
 	tx   *Tx
 	txsi driver.Stmt
@@ -661,12 +838,18 @@ type Stmt struct {
 // Exec executes a prepared statement with the given arguments and
 // returns a Result summarizing the effect of the statement.
 func (s *Stmt) Exec(args ...interface{}) (Result, error) {
+	s.closemu.RLock()
+	defer s.closemu.RUnlock()
 	_, releaseConn, si, err := s.connStmt()
 	if err != nil {
 		return nil, err
 	}
 	defer releaseConn(nil)
 
+	return resultFromStatement(si, args...)
+}
+
+func resultFromStatement(si driver.Stmt, args ...interface{}) (Result, error) {
 	// -1 means the driver doesn't know how to count the number of
 	// placeholders, so we won't sanity check input here and instead let the
 	// driver deal with errors.
@@ -674,51 +857,12 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) {
 		return nil, fmt.Errorf("sql: expected %d arguments, got %d", want, len(args))
 	}
 
-	sargs := make([]driver.Value, len(args))
-
-	// Convert args to subset types.
-	if cc, ok := si.(driver.ColumnConverter); ok {
-		for n, arg := range args {
-			// First, see if the value itself knows how to convert
-			// itself to a driver type.  For example, a NullString
-			// struct changing into a string or nil.
-			if svi, ok := arg.(driver.Valuer); ok {
-				sv, err := svi.Value()
-				if err != nil {
-					return nil, fmt.Errorf("sql: argument index %d from Value: %v", n, err)
-				}
-				if !driver.IsValue(sv) {
-					return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from Value", n, sv)
-				}
-				arg = sv
-			}
-
-			// Second, ask the column to sanity check itself. For
-			// example, drivers might use this to make sure that
-			// an int64 values being inserted into a 16-bit
-			// integer field is in range (before getting
-			// truncated), or that a nil can't go into a NOT NULL
-			// column before going across the network to get the
-			// same error.
-			sargs[n], err = cc.ColumnConverter(n).ConvertValue(arg)
-			if err != nil {
-				return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
-			}
-			if !driver.IsValue(sargs[n]) {
-				return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T",
-					arg, sargs[n])
-			}
-		}
-	} else {
-		for n, arg := range args {
-			sargs[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
-			if err != nil {
-				return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
-			}
-		}
+	dargs, err := driverArgs(si, args)
+	if err != nil {
+		return nil, err
 	}
 
-	resi, err := si.Exec(sargs)
+	resi, err := si.Exec(dargs)
 	if err != nil {
 		return nil, err
 	}
@@ -794,35 +938,54 @@ func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(error), si driver.St
 // Query executes a prepared query statement with the given arguments
 // and returns the query results as a *Rows.
 func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
+	s.closemu.RLock()
+	defer s.closemu.RUnlock()
+
 	ci, releaseConn, si, err := s.connStmt()
 	if err != nil {
 		return nil, err
 	}
 
+	rowsi, err := rowsiFromStatement(si, args...)
+	if err != nil {
+		releaseConn(err)
+		return nil, err
+	}
+
+	// Note: ownership of ci passes to the *Rows, to be freed
+	// with releaseConn.
+	rows := &Rows{
+		db:    s.db,
+		ci:    ci,
+		rowsi: rowsi,
+		// releaseConn set below
+	}
+	s.db.addDep(s, rows)
+	rows.releaseConn = func(err error) {
+		releaseConn(err)
+		s.db.removeDep(s, rows)
+	}
+	return rows, nil
+}
+
+func rowsiFromStatement(si driver.Stmt, args ...interface{}) (driver.Rows, error) {
 	// -1 means the driver doesn't know how to count the number of
 	// placeholders, so we won't sanity check input here and instead let the
 	// driver deal with errors.
 	if want := si.NumInput(); want != -1 && len(args) != want {
 		return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", si.NumInput(), len(args))
 	}
-	sargs, err := subsetTypeArgs(args)
+
+	dargs, err := driverArgs(si, args)
 	if err != nil {
 		return nil, err
 	}
-	rowsi, err := si.Query(sargs)
+
+	rowsi, err := si.Query(dargs)
 	if err != nil {
-		releaseConn(err)
 		return nil, err
 	}
-	// Note: ownership of ci passes to the *Rows, to be freed
-	// with releaseConn.
-	rows := &Rows{
-		db:          s.db,
-		ci:          ci,
-		releaseConn: releaseConn,
-		rowsi:       rowsi,
-	}
-	return rows, nil
+	return rowsi, nil
 }
 
 // QueryRow executes a prepared query statement with the given arguments.
@@ -846,6 +1009,9 @@ func (s *Stmt) QueryRow(args ...interface{}) *Row {
 
 // Close closes the statement.
 func (s *Stmt) Close() error {
+	s.closemu.Lock()
+	defer s.closemu.Unlock()
+
 	if s.stickyErr != nil {
 		return s.stickyErr
 	}
@@ -858,18 +1024,17 @@ func (s *Stmt) Close() error {
 
 	if s.tx != nil {
 		s.txsi.Close()
-	} else {
-		for _, v := range s.css {
-			if ci, match := s.db.connIfFree(v.ci); match {
-				v.si.Close()
-				s.db.putConn(ci, nil)
-			} else {
-				// TODO(bradfitz): care that we can't close
-				// this statement because the statement's
-				// connection is in use?
-			}
-		}
+		return nil
+	}
+
+	return s.db.removeDep(s, s)
+}
+
+func (s *Stmt) finalClose() error {
+	for _, v := range s.css {
+		s.db.noteUnusedDriverStatement(v.ci, v.si)
 	}
+	s.css = nil
 	return nil
 }
 
@@ -888,14 +1053,14 @@ func (s *Stmt) Close() error {
 //     ...
 type Rows struct {
 	db          *DB
-	ci          driver.Conn // owned; must call putconn when closed to release
+	ci          driver.Conn // owned; must call releaseConn when closed to release
 	releaseConn func(error)
 	rowsi       driver.Rows
 
 	closed    bool
 	lastcols  []driver.Value
 	lasterr   error
-	closeStmt *Stmt // if non-nil, statement to Close on close
+	closeStmt driver.Stmt // if non-nil, statement to Close on close
 }
 
 // Next prepares the next result row for reading with the Scan method.
@@ -1064,3 +1229,8 @@ type Result interface {
 type result struct {
 	driver.Result
 }
+
+func stack() string {
+	var buf [1024]byte
+	return string(buf[:runtime.Stack(buf[:], false)])
+}
diff --git a/src/pkg/database/sql/sql_test.go b/src/pkg/database/sql/sql_test.go
index b296705..53b2296 100644
--- a/src/pkg/database/sql/sql_test.go
+++ b/src/pkg/database/sql/sql_test.go
@@ -8,7 +8,6 @@ import (
 	"database/sql/driver"
 	"fmt"
 	"reflect"
-	"runtime"
 	"strings"
 	"testing"
 	"time"
@@ -63,6 +62,10 @@ func exec(t *testing.T, db *DB, query string, args ...interface{}) {
 }
 
 func closeDB(t *testing.T, db *DB) {
+	if e := recover(); e != nil {
+		fmt.Printf("Panic: %v\n", e)
+		panic(e)
+	}
 	err := db.Close()
 	if err != nil {
 		t.Fatalf("error closing DB: %v", err)
@@ -270,6 +273,35 @@ func TestStatementQueryRow(t *testing.T) {
 
 }
 
+// golang.org/issue/3734
+func TestStatementQueryRowConcurrent(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	stmt, err := db.Prepare("SELECT|people|age|name=?")
+	if err != nil {
+		t.Fatalf("Prepare: %v", err)
+	}
+	defer stmt.Close()
+
+	const n = 10
+	ch := make(chan error, n)
+	for i := 0; i < n; i++ {
+		go func() {
+			var age int
+			err := stmt.QueryRow("Alice").Scan(&age)
+			if err == nil && age != 1 {
+				err = fmt.Errorf("unexpected age %d", age)
+			}
+			ch <- err
+		}()
+	}
+	for i := 0; i < n; i++ {
+		if err := <-ch; err != nil {
+			t.Error(err)
+		}
+	}
+}
+
 // just a test of fakedb itself
 func TestBogusPreboundParameters(t *testing.T) {
 	db := newTestDB(t, "foo")
@@ -306,8 +338,8 @@ func TestExec(t *testing.T) {
 		{[]interface{}{7, 9}, ""},
 
 		// Invalid conversions:
-		{[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting Exec argument #1's type: sql/driver: value 4294967295 overflows int32"},
-		{[]interface{}{"Brad", "strconv fail"}, "sql: converting Exec argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
+		{[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument #1's type: sql/driver: value 4294967295 overflows int32"},
+		{[]interface{}{"Brad", "strconv fail"}, "sql: converting argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
 
 		// Wrong number of args:
 		{[]interface{}{}, "sql: expected 2 arguments, got 0"},
@@ -402,6 +434,39 @@ func TestTxQueryInvalid(t *testing.T) {
 	}
 }
 
+// Tests fix for issue 4433, that retries in Begin happen when
+// conn.Begin() returns ErrBadConn
+func TestTxErrBadConn(t *testing.T) {
+	db, err := Open("test", fakeDBName+";badConn")
+	if err != nil {
+		t.Fatalf("Open: %v", err)
+	}
+	if _, err := db.Exec("WIPE"); err != nil {
+		t.Fatalf("exec wipe: %v", err)
+	}
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+	if err != nil {
+		t.Fatalf("Stmt, err = %v, %v", stmt, err)
+	}
+	defer stmt.Close()
+	tx, err := db.Begin()
+	if err != nil {
+		t.Fatalf("Begin = %v", err)
+	}
+	txs := tx.Stmt(stmt)
+	defer txs.Close()
+	_, err = txs.Exec("Bobby", 7)
+	if err != nil {
+		t.Fatalf("Exec = %v", err)
+	}
+	err = tx.Commit()
+	if err != nil {
+		t.Fatalf("Commit = %v", err)
+	}
+}
+
 // Tests fix for issue 2542, that we release a lock when querying on
 // a closed connection.
 func TestIssue2542Deadlock(t *testing.T) {
@@ -415,6 +480,30 @@ func TestIssue2542Deadlock(t *testing.T) {
 	}
 }
 
+// From golang.org/issue/3865
+func TestCloseStmtBeforeRows(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	s, err := db.Prepare("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	r, err := s.Query()
+	if err != nil {
+		s.Close()
+		t.Fatal(err)
+	}
+
+	err = s.Close()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	r.Close()
+}
+
 // Tests fix for issue 2788, that we bind nil to a []byte if the
 // value in the column is sql null
 func TestNullByteSlice(t *testing.T) {
@@ -608,7 +697,14 @@ func nullTestRun(t *testing.T, spec nullTestSpec) {
 	}
 }
 
-func stack() string {
-	buf := make([]byte, 1024)
-	return string(buf[:runtime.Stack(buf, false)])
+// golang.org/issue/4859
+func TestQueryRowNilScanDest(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	var name *string // nil pointer
+	err := db.QueryRow("SELECT|people|name|").Scan(name)
+	want := "sql: Scan error on column index 0: destination pointer is nil"
+	if err == nil || err.Error() != want {
+		t.Errorf("error = %q; want %q", err.Error(), want)
+	}
 }
diff --git a/src/pkg/debug/dwarf/const.go b/src/pkg/debug/dwarf/const.go
index 918b153..ad696dc 100644
--- a/src/pkg/debug/dwarf/const.go
+++ b/src/pkg/debug/dwarf/const.go
@@ -207,6 +207,7 @@ const (
 	formRef8        format = 0x14
 	formRefUdata    format = 0x15
 	formIndirect    format = 0x16
+	formFlagPresent format = 0x19
 )
 
 // A Tag is the classification (the type) of an Entry.
diff --git a/src/pkg/debug/dwarf/entry.go b/src/pkg/debug/dwarf/entry.go
index 2885d8f..f376e40 100644
--- a/src/pkg/debug/dwarf/entry.go
+++ b/src/pkg/debug/dwarf/entry.go
@@ -185,6 +185,10 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
 		// flag
 		case formFlag:
 			val = b.uint8() == 1
+		case formFlagPresent:
+			// The attribute is implicitly indicated as present, and no value is
+			// encoded in the debugging information entry itself.
+			val = true
 
 		// reference to other entry
 		case formRefAddr:
diff --git a/src/pkg/debug/elf/file.go b/src/pkg/debug/elf/file.go
index 184ca83..acb9817 100644
--- a/src/pkg/debug/elf/file.go
+++ b/src/pkg/debug/elf/file.go
@@ -31,6 +31,7 @@ type FileHeader struct {
 	ByteOrder  binary.ByteOrder
 	Type       Type
 	Machine    Machine
+	Entry      uint64
 }
 
 // A File represents an open ELF file.
@@ -240,6 +241,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
 		}
 		f.Type = Type(hdr.Type)
 		f.Machine = Machine(hdr.Machine)
+		f.Entry = uint64(hdr.Entry)
 		if v := Version(hdr.Version); v != f.Version {
 			return nil, &FormatError{0, "mismatched ELF version", v}
 		}
@@ -258,6 +260,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
 		}
 		f.Type = Type(hdr.Type)
 		f.Machine = Machine(hdr.Machine)
+		f.Entry = uint64(hdr.Entry)
 		if v := Version(hdr.Version); v != f.Version {
 			return nil, &FormatError{0, "mismatched ELF version", v}
 		}
@@ -269,7 +272,8 @@ func NewFile(r io.ReaderAt) (*File, error) {
 		shnum = int(hdr.Shnum)
 		shstrndx = int(hdr.Shstrndx)
 	}
-	if shstrndx < 0 || shstrndx >= shnum {
+
+	if shnum > 0 && shoff > 0 && (shstrndx < 0 || shstrndx >= shnum) {
 		return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx}
 	}
 
@@ -364,6 +368,10 @@ func NewFile(r io.ReaderAt) (*File, error) {
 		f.Sections[i] = s
 	}
 
+	if len(f.Sections) == 0 {
+		return f, nil
+	}
+
 	// Load section header string table.
 	shstrtab, err := f.Sections[shstrndx].Data()
 	if err != nil {
@@ -414,10 +422,6 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
 		return nil, nil, errors.New("cannot load string table section")
 	}
 
-	// The first entry is all zeros.
-	var skip [Sym32Size]byte
-	symtab.Read(skip[0:])
-
 	symbols := make([]Symbol, symtab.Len()/Sym32Size)
 
 	i := 0
@@ -457,10 +461,6 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
 		return nil, nil, errors.New("cannot load string table section")
 	}
 
-	// The first entry is all zeros.
-	var skip [Sym64Size]byte
-	symtab.Read(skip[0:])
-
 	symbols := make([]Symbol, symtab.Len()/Sym64Size)
 
 	i := 0
@@ -705,8 +705,8 @@ func (f *File) gnuVersionInit(str []byte) {
 // gnuVersion adds Library and Version information to sym,
 // which came from offset i of the symbol table.
 func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
-	// Each entry is two bytes; skip undef entry at beginning.
-	i = (i + 1) * 2
+	// Each entry is two bytes.
+	i = i * 2
 	if i >= len(f.gnuVersym) {
 		return
 	}
@@ -723,6 +723,20 @@ func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
 // referred to by the binary f that are expected to be
 // linked with the binary at dynamic link time.
 func (f *File) ImportedLibraries() ([]string, error) {
+	return f.DynString(DT_NEEDED)
+}
+
+// DynString returns the strings listed for the given tag in the file's dynamic
+// section.
+//
+// The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or
+// DT_RUNPATH.
+func (f *File) DynString(tag DynTag) ([]string, error) {
+	switch tag {
+	case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH:
+	default:
+		return nil, fmt.Errorf("non-string-valued tag %v", tag)
+	}
 	ds := f.SectionByType(SHT_DYNAMIC)
 	if ds == nil {
 		// not dynamic, so no libraries
@@ -738,25 +752,24 @@ func (f *File) ImportedLibraries() ([]string, error) {
 	}
 	var all []string
 	for len(d) > 0 {
-		var tag DynTag
-		var value uint64
+		var t DynTag
+		var v uint64
 		switch f.Class {
 		case ELFCLASS32:
-			tag = DynTag(f.ByteOrder.Uint32(d[0:4]))
-			value = uint64(f.ByteOrder.Uint32(d[4:8]))
+			t = DynTag(f.ByteOrder.Uint32(d[0:4]))
+			v = uint64(f.ByteOrder.Uint32(d[4:8]))
 			d = d[8:]
 		case ELFCLASS64:
-			tag = DynTag(f.ByteOrder.Uint64(d[0:8]))
-			value = f.ByteOrder.Uint64(d[8:16])
+			t = DynTag(f.ByteOrder.Uint64(d[0:8]))
+			v = f.ByteOrder.Uint64(d[8:16])
 			d = d[16:]
 		}
-		if tag == DT_NEEDED {
-			s, ok := getString(str, int(value))
+		if t == tag {
+			s, ok := getString(str, int(v))
 			if ok {
 				all = append(all, s)
 			}
 		}
 	}
-
 	return all, nil
 }
diff --git a/src/pkg/debug/elf/file_test.go b/src/pkg/debug/elf/file_test.go
index 98f2723..f9aa726 100644
--- a/src/pkg/debug/elf/file_test.go
+++ b/src/pkg/debug/elf/file_test.go
@@ -5,10 +5,14 @@
 package elf
 
 import (
+	"bytes"
+	"compress/gzip"
 	"debug/dwarf"
 	"encoding/binary"
+	"io"
 	"net"
 	"os"
+	"path"
 	"reflect"
 	"runtime"
 	"testing"
@@ -19,12 +23,13 @@ type fileTest struct {
 	hdr      FileHeader
 	sections []SectionHeader
 	progs    []ProgHeader
+	needed   []string
 }
 
 var fileTests = []fileTest{
 	{
 		"testdata/gcc-386-freebsd-exec",
-		FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386},
+		FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc},
 		[]SectionHeader{
 			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
 			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0},
@@ -64,10 +69,11 @@ var fileTests = []fileTest{
 			{PT_LOAD, PF_R + PF_W, 0x5fc, 0x80495fc, 0x80495fc, 0xd8, 0xf8, 0x1000},
 			{PT_DYNAMIC, PF_R + PF_W, 0x60c, 0x804960c, 0x804960c, 0x98, 0x98, 0x4},
 		},
+		[]string{"libc.so.6"},
 	},
 	{
 		"testdata/gcc-amd64-linux-exec",
-		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64},
+		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0},
 		[]SectionHeader{
 			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
 			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0},
@@ -117,6 +123,32 @@ var fileTests = []fileTest{
 			{PT_LOOS + 0x474E550, PF_R, 0x5b8, 0x4005b8, 0x4005b8, 0x24, 0x24, 0x4},
 			{PT_LOOS + 0x474E551, PF_R + PF_W, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8},
 		},
+		[]string{"libc.so.6"},
+	},
+	{
+		"testdata/hello-world-core.gz",
+		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_CORE, EM_X86_64, 0x0},
+		[]SectionHeader{},
+		[]ProgHeader{
+			{Type: PT_NOTE, Flags: 0x0, Off: 0x3f8, Vaddr: 0x0, Paddr: 0x0, Filesz: 0x8ac, Memsz: 0x0, Align: 0x0},
+			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x1000, Vaddr: 0x400000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_R, Off: 0x1000, Vaddr: 0x401000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x2000, Vaddr: 0x402000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3000, Vaddr: 0x7f54078b8000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1b5000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: 0x0, Off: 0x3000, Vaddr: 0x7f5407a6d000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1ff000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_R, Off: 0x3000, Vaddr: 0x7f5407c6c000, Paddr: 0x0, Filesz: 0x4000, Memsz: 0x4000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x7000, Vaddr: 0x7f5407c70000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x9000, Vaddr: 0x7f5407c72000, Paddr: 0x0, Filesz: 0x5000, Memsz: 0x5000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0xe000, Vaddr: 0x7f5407c77000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x22000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0xe000, Vaddr: 0x7f5407e81000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x11000, Vaddr: 0x7f5407e96000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_R, Off: 0x14000, Vaddr: 0x7f5407e99000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x15000, Vaddr: 0x7f5407e9a000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x17000, Vaddr: 0x7fff79972000, Paddr: 0x0, Filesz: 0x23000, Memsz: 0x23000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3a000, Vaddr: 0x7fff799f8000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
+			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3b000, Vaddr: 0xffffffffff600000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
+		},
+		nil,
 	},
 }
 
@@ -124,9 +156,18 @@ func TestOpen(t *testing.T) {
 	for i := range fileTests {
 		tt := &fileTests[i]
 
-		f, err := Open(tt.file)
+		var f *File
+		var err error
+		if path.Ext(tt.file) == ".gz" {
+			var r io.ReaderAt
+			if r, err = decompress(tt.file); err == nil {
+				f, err = NewFile(r)
+			}
+		} else {
+			f, err = Open(tt.file)
+		}
 		if err != nil {
-			t.Error(err)
+			t.Errorf("cannot open file %s: %v", tt.file, err)
 			continue
 		}
 		if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
@@ -161,26 +202,69 @@ func TestOpen(t *testing.T) {
 		if tn != fn {
 			t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn)
 		}
+		tl := tt.needed
+		fl, err := f.ImportedLibraries()
+		if err != nil {
+			t.Error(err)
+		}
+		if !reflect.DeepEqual(tl, fl) {
+			t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl)
+		}
 	}
 }
 
+// elf.NewFile requires io.ReaderAt, which compress/gzip cannot
+// provide. Decompress the file to a bytes.Reader.
+func decompress(gz string) (io.ReaderAt, error) {
+	in, err := os.Open(gz)
+	if err != nil {
+		return nil, err
+	}
+	defer in.Close()
+	r, err := gzip.NewReader(in)
+	if err != nil {
+		return nil, err
+	}
+	var out bytes.Buffer
+	_, err = io.Copy(&out, r)
+	return bytes.NewReader(out.Bytes()), err
+}
+
+type relocationTestEntry struct {
+	entryNumber int
+	entry       *dwarf.Entry
+}
+
 type relocationTest struct {
-	file       string
-	firstEntry *dwarf.Entry
+	file    string
+	entries []relocationTestEntry
 }
 
 var relocationTests = []relocationTest{
 	{
 		"testdata/go-relocation-test-gcc441-x86-64.obj",
-		&dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x6)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}},
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x6)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
+		},
 	},
 	{
 		"testdata/go-relocation-test-gcc441-x86.obj",
-		&dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "t.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x5)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}},
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "t.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x5)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
+		},
 	},
 	{
 		"testdata/go-relocation-test-gcc424-x86-64.obj",
-		&dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x6)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}},
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x6)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
+		},
+	},
+	{
+		"testdata/gcc-amd64-openbsd-debug-with-rela.obj",
+		[]relocationTestEntry{
+			{203, &dwarf.Entry{Offset: 0xc62, Tag: dwarf.TagMember, Children: false, Field: []dwarf.Field{{Attr: dwarf.AttrName, Val: "it_interval"}, {Attr: dwarf.AttrDeclFile, Val: int64(7)}, {Attr: dwarf.AttrDeclLine, Val: int64(236)}, {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f)}, {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}}}}},
+			{204, &dwarf.Entry{Offset: 0xc70, Tag: dwarf.TagMember, Children: false, Field: []dwarf.Field{{Attr: dwarf.AttrName, Val: "it_value"}, {Attr: dwarf.AttrDeclFile, Val: int64(7)}, {Attr: dwarf.AttrDeclLine, Val: int64(237)}, {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f)}, {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}}}}},
+		},
 	},
 }
 
@@ -196,20 +280,24 @@ func TestDWARFRelocations(t *testing.T) {
 			t.Error(err)
 			continue
 		}
-		reader := dwarf.Reader()
-		// Checking only the first entry is sufficient since it has
-		// many different strings. If the relocation had failed, all
-		// the string offsets would be zero and all the strings would
-		// end up being the same.
-		firstEntry, err := reader.Next()
-		if err != nil {
-			t.Error(err)
-			continue
-		}
-
-		if !reflect.DeepEqual(test.firstEntry, firstEntry) {
-			t.Errorf("#%d: mismatch: got:%#v want:%#v", i, firstEntry, test.firstEntry)
-			continue
+		for _, testEntry := range test.entries {
+			reader := dwarf.Reader()
+			for j := 0; j < testEntry.entryNumber; j++ {
+				entry, err := reader.Next()
+				if entry == nil || err != nil {
+					t.Errorf("Failed to skip to entry %d: %v", testEntry.entryNumber, err)
+					continue
+				}
+			}
+			entry, err := reader.Next()
+			if err != nil {
+				t.Error(err)
+				continue
+			}
+			if !reflect.DeepEqual(testEntry.entry, entry) {
+				t.Errorf("#%d/%d: mismatch: got:%#v want:%#v", i, testEntry.entryNumber, entry, testEntry.entry)
+				continue
+			}
 		}
 	}
 }
diff --git a/src/pkg/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj b/src/pkg/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj
new file mode 100644
index 0000000..f62b1ea
Binary files /dev/null and b/src/pkg/debug/elf/testdata/gcc-amd64-openbsd-debug-with-rela.obj differ
diff --git a/src/pkg/debug/elf/testdata/hello-world-core.gz b/src/pkg/debug/elf/testdata/hello-world-core.gz
new file mode 100644
index 0000000..806af6e
Binary files /dev/null and b/src/pkg/debug/elf/testdata/hello-world-core.gz differ
diff --git a/src/pkg/debug/gosym/pclntab_test.go b/src/pkg/debug/gosym/pclntab_test.go
index ade7043..20acba6 100644
--- a/src/pkg/debug/gosym/pclntab_test.go
+++ b/src/pkg/debug/gosym/pclntab_test.go
@@ -52,6 +52,14 @@ func dotest() bool {
 	return true
 }
 
+func endtest() {
+	if pclineTempDir != "" {
+		os.RemoveAll(pclineTempDir)
+		pclineTempDir = ""
+		pclinetestBinary = ""
+	}
+}
+
 func getTable(t *testing.T) *Table {
 	f, tab := crack(os.Args[0], t)
 	f.Close()
@@ -95,6 +103,7 @@ func TestLineFromAline(t *testing.T) {
 	if !dotest() {
 		return
 	}
+	defer endtest()
 
 	tab := getTable(t)
 
@@ -129,7 +138,7 @@ func TestLineFromAline(t *testing.T) {
 		if !ok {
 			t.Errorf("file %s starts on line %d", path, line)
 		} else if line != ll+1 {
-			t.Errorf("expected next line of file %s to be %d, got %d", path, ll+1, line)
+			t.Fatalf("expected next line of file %s to be %d, got %d", path, ll+1, line)
 		}
 		lastline[path] = line
 	}
@@ -142,6 +151,7 @@ func TestLineAline(t *testing.T) {
 	if !dotest() {
 		return
 	}
+	defer endtest()
 
 	tab := getTable(t)
 
@@ -183,7 +193,7 @@ func TestPCLine(t *testing.T) {
 	if !dotest() {
 		return
 	}
-	defer os.RemoveAll(pclineTempDir)
+	defer endtest()
 
 	f, tab := crack(pclinetestBinary, t)
 	text := f.Section(".text")
diff --git a/src/pkg/debug/gosym/symtab.go b/src/pkg/debug/gosym/symtab.go
index 52d7d55..81ed4fb 100644
--- a/src/pkg/debug/gosym/symtab.go
+++ b/src/pkg/debug/gosym/symtab.go
@@ -13,6 +13,7 @@ package gosym
 // and the Go format is the runtime source, specifically ../../runtime/symtab.c.
 
 import (
+	"bytes"
 	"encoding/binary"
 	"fmt"
 	"strconv"
@@ -98,24 +99,116 @@ type Table struct {
 }
 
 type sym struct {
-	value  uint32
-	gotype uint32
+	value  uint64
+	gotype uint64
 	typ    byte
 	name   []byte
 }
 
+var littleEndianSymtab = []byte{0xFD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00}
+var bigEndianSymtab = []byte{0xFF, 0xFF, 0xFF, 0xFD, 0x00, 0x00, 0x00}
+
+var oldLittleEndianSymtab = []byte{0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00}
+
 func walksymtab(data []byte, fn func(sym) error) error {
+	var order binary.ByteOrder = binary.BigEndian
+	newTable := false
+	switch {
+	case bytes.HasPrefix(data, oldLittleEndianSymtab):
+		// Same as Go 1.0, but little endian.
+		// Format was used during interim development between Go 1.0 and Go 1.1.
+		// Should not be widespread, but easy to support.
+		data = data[6:]
+		order = binary.LittleEndian
+	case bytes.HasPrefix(data, bigEndianSymtab):
+		newTable = true
+	case bytes.HasPrefix(data, littleEndianSymtab):
+		newTable = true
+		order = binary.LittleEndian
+	}
+	var ptrsz int
+	if newTable {
+		if len(data) < 8 {
+			return &DecodingError{len(data), "unexpected EOF", nil}
+		}
+		ptrsz = int(data[7])
+		if ptrsz != 4 && ptrsz != 8 {
+			return &DecodingError{7, "invalid pointer size", ptrsz}
+		}
+		data = data[8:]
+	}
 	var s sym
 	p := data
-	for len(p) >= 6 {
-		s.value = binary.BigEndian.Uint32(p[0:4])
-		typ := p[4]
-		if typ&0x80 == 0 {
-			return &DecodingError{len(data) - len(p) + 4, "bad symbol type", typ}
+	for len(p) >= 4 {
+		var typ byte
+		if newTable {
+			// Symbol type, value, Go type.
+			typ = p[0] & 0x3F
+			wideValue := p[0]&0x40 != 0
+			goType := p[0]&0x80 != 0
+			if typ < 26 {
+				typ += 'A'
+			} else {
+				typ += 'a' - 26
+			}
+			s.typ = typ
+			p = p[1:]
+			if wideValue {
+				if len(p) < ptrsz {
+					return &DecodingError{len(data), "unexpected EOF", nil}
+				}
+				// fixed-width value
+				if ptrsz == 8 {
+					s.value = order.Uint64(p[0:8])
+					p = p[8:]
+				} else {
+					s.value = uint64(order.Uint32(p[0:4]))
+					p = p[4:]
+				}
+			} else {
+				// varint value
+				s.value = 0
+				shift := uint(0)
+				for len(p) > 0 && p[0]&0x80 != 0 {
+					s.value |= uint64(p[0]&0x7F) << shift
+					shift += 7
+					p = p[1:]
+				}
+				if len(p) == 0 {
+					return &DecodingError{len(data), "unexpected EOF", nil}
+				}
+				s.value |= uint64(p[0]) << shift
+				p = p[1:]
+			}
+			if goType {
+				if len(p) < ptrsz {
+					return &DecodingError{len(data), "unexpected EOF", nil}
+				}
+				// fixed-width go type
+				if ptrsz == 8 {
+					s.gotype = order.Uint64(p[0:8])
+					p = p[8:]
+				} else {
+					s.gotype = uint64(order.Uint32(p[0:4]))
+					p = p[4:]
+				}
+			}
+		} else {
+			// Value, symbol type.
+			s.value = uint64(order.Uint32(p[0:4]))
+			if len(p) < 5 {
+				return &DecodingError{len(data), "unexpected EOF", nil}
+			}
+			typ = p[4]
+			if typ&0x80 == 0 {
+				return &DecodingError{len(data) - len(p) + 4, "bad symbol type", typ}
+			}
+			typ &^= 0x80
+			s.typ = typ
+			p = p[5:]
 		}
-		typ &^= 0x80
-		s.typ = typ
-		p = p[5:]
+
+		// Name.
 		var i int
 		var nnul int
 		for i = 0; i < len(p); i++ {
@@ -134,13 +227,21 @@ func walksymtab(data []byte, fn func(sym) error) error {
 				}
 			}
 		}
-		if i+nnul+4 > len(p) {
+		if len(p) < i+nnul {
 			return &DecodingError{len(data), "unexpected EOF", nil}
 		}
 		s.name = p[0:i]
 		i += nnul
-		s.gotype = binary.BigEndian.Uint32(p[i : i+4])
-		p = p[i+4:]
+		p = p[i:]
+
+		if !newTable {
+			if len(p) < 4 {
+				return &DecodingError{len(data), "unexpected EOF", nil}
+			}
+			// Go type.
+			s.gotype = uint64(order.Uint32(p[:4]))
+			p = p[4:]
+		}
 		fn(s)
 	}
 	return nil
diff --git a/src/pkg/debug/pe/file.go b/src/pkg/debug/pe/file.go
index 6b98a5f..f521566 100644
--- a/src/pkg/debug/pe/file.go
+++ b/src/pkg/debug/pe/file.go
@@ -19,6 +19,7 @@ import (
 type File struct {
 	FileHeader
 	Sections []*Section
+	Symbols  []*Symbol
 
 	closer io.Closer
 }
@@ -49,6 +50,14 @@ type Section struct {
 	sr *io.SectionReader
 }
 
+type Symbol struct {
+	Name          string
+	Value         uint32
+	SectionNumber int16
+	Type          uint16
+	StorageClass  uint8
+}
+
 type ImportDirectory struct {
 	OriginalFirstThunk uint32
 	TimeDateStamp      uint32
@@ -122,12 +131,13 @@ func NewFile(r io.ReaderAt) (*File, error) {
 	}
 	var base int64
 	if dosheader[0] == 'M' && dosheader[1] == 'Z' {
+		signoff := int64(binary.LittleEndian.Uint32(dosheader[0x3c:]))
 		var sign [4]byte
-		r.ReadAt(sign[0:], int64(dosheader[0x3c]))
+		r.ReadAt(sign[:], signoff)
 		if !(sign[0] == 'P' && sign[1] == 'E' && sign[2] == 0 && sign[3] == 0) {
 			return nil, errors.New("Invalid PE File Format.")
 		}
-		base = int64(dosheader[0x3c]) + 4
+		base = signoff + 4
 	} else {
 		base = int64(0)
 	}
@@ -138,16 +148,52 @@ func NewFile(r io.ReaderAt) (*File, error) {
 	if f.FileHeader.Machine != IMAGE_FILE_MACHINE_UNKNOWN && f.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64 && f.FileHeader.Machine != IMAGE_FILE_MACHINE_I386 {
 		return nil, errors.New("Invalid PE File Format.")
 	}
-	// get symbol string table
-	sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), os.SEEK_SET)
-	var l uint32
-	if err := binary.Read(sr, binary.LittleEndian, &l); err != nil {
-		return nil, err
-	}
-	ss := make([]byte, l)
-	if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols)); err != nil {
-		return nil, err
+
+	var ss []byte
+	if f.FileHeader.NumberOfSymbols > 0 {
+		// Get COFF string table, which is located at the end of the COFF symbol table.
+		sr.Seek(int64(f.FileHeader.PointerToSymbolTable+COFFSymbolSize*f.FileHeader.NumberOfSymbols), os.SEEK_SET)
+		var l uint32
+		if err := binary.Read(sr, binary.LittleEndian, &l); err != nil {
+			return nil, err
+		}
+		ss = make([]byte, l)
+		if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+COFFSymbolSize*f.FileHeader.NumberOfSymbols)); err != nil {
+			return nil, err
+		}
+
+		// Process COFF symbol table.
+		sr.Seek(int64(f.FileHeader.PointerToSymbolTable), os.SEEK_SET)
+		aux := uint8(0)
+		for i := 0; i < int(f.FileHeader.NumberOfSymbols); i++ {
+			cs := new(COFFSymbol)
+			if err := binary.Read(sr, binary.LittleEndian, cs); err != nil {
+				return nil, err
+			}
+			if aux > 0 {
+				aux--
+				continue
+			}
+			var name string
+			if cs.Name[0] == 0 && cs.Name[1] == 0 && cs.Name[2] == 0 && cs.Name[3] == 0 {
+				si := int(binary.LittleEndian.Uint32(cs.Name[4:]))
+				name, _ = getString(ss, si)
+			} else {
+				name = cstring(cs.Name[:])
+			}
+			aux = cs.NumberOfAuxSymbols
+			s := &Symbol{
+				Name:          name,
+				Value:         cs.Value,
+				SectionNumber: cs.SectionNumber,
+				Type:          cs.Type,
+				StorageClass:  cs.StorageClass,
+			}
+			f.Symbols = append(f.Symbols, s)
+		}
 	}
+
+	// Process sections.
 	sr.Seek(base, os.SEEK_SET)
 	binary.Read(sr, binary.LittleEndian, &f.FileHeader)
 	sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), os.SEEK_CUR) //Skip OptionalHeader
diff --git a/src/pkg/debug/pe/file_test.go b/src/pkg/debug/pe/file_test.go
index 2815d72..c0f9fcb 100644
--- a/src/pkg/debug/pe/file_test.go
+++ b/src/pkg/debug/pe/file_test.go
@@ -13,6 +13,7 @@ type fileTest struct {
 	file     string
 	hdr      FileHeader
 	sections []*SectionHeader
+	symbols  []*Symbol
 }
 
 var fileTests = []fileTest{
@@ -33,6 +34,24 @@ var fileTests = []fileTest{
 			{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
 			{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
 		},
+		[]*Symbol{
+			{".file", 0x0, -2, 0x0, 0x67},
+			{"_main", 0x0, 1, 0x20, 0x2},
+			{".text", 0x0, 1, 0x0, 0x3},
+			{".data", 0x0, 2, 0x0, 0x3},
+			{".bss", 0x0, 3, 0x0, 0x3},
+			{".debug_abbrev", 0x0, 4, 0x0, 0x3},
+			{".debug_info", 0x0, 5, 0x0, 0x3},
+			{".debug_line", 0x0, 6, 0x0, 0x3},
+			{".rdata", 0x0, 7, 0x0, 0x3},
+			{".debug_frame", 0x0, 8, 0x0, 0x3},
+			{".debug_loc", 0x0, 9, 0x0, 0x3},
+			{".debug_pubnames", 0x0, 10, 0x0, 0x3},
+			{".debug_pubtypes", 0x0, 11, 0x0, 0x3},
+			{".debug_aranges", 0x0, 12, 0x0, 0x3},
+			{"___main", 0x0, 0, 0x20, 0x2},
+			{"_puts", 0x0, 0, 0x20, 0x2},
+		},
 	},
 	{
 		"testdata/gcc-386-mingw-exec",
@@ -54,6 +73,7 @@ var fileTests = []fileTest{
 			{Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000},
 			{Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
 		},
+		[]*Symbol{},
 	},
 }
 
@@ -86,7 +106,15 @@ func TestOpen(t *testing.T) {
 		if tn != fn {
 			t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
 		}
-
+		for i, have := range f.Symbols {
+			if i >= len(tt.symbols) {
+				break
+			}
+			want := tt.symbols[i]
+			if !reflect.DeepEqual(have, want) {
+				t.Errorf("open %s, symbol %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
+			}
+		}
 	}
 }
 
diff --git a/src/pkg/debug/pe/pe.go b/src/pkg/debug/pe/pe.go
index b3dab73..0606217 100644
--- a/src/pkg/debug/pe/pe.go
+++ b/src/pkg/debug/pe/pe.go
@@ -27,6 +27,17 @@ type SectionHeader32 struct {
 	Characteristics      uint32
 }
 
+const COFFSymbolSize = 18
+
+type COFFSymbol struct {
+	Name               [8]uint8
+	Value              uint32
+	SectionNumber      int16
+	Type               uint16
+	StorageClass       uint8
+	NumberOfAuxSymbols uint8
+}
+
 const (
 	IMAGE_FILE_MACHINE_UNKNOWN   = 0x0
 	IMAGE_FILE_MACHINE_AM33      = 0x1d3
diff --git a/src/pkg/encoding/asn1/asn1.go b/src/pkg/encoding/asn1/asn1.go
index ac2b5f8..cac9d64 100644
--- a/src/pkg/encoding/asn1/asn1.go
+++ b/src/pkg/encoding/asn1/asn1.go
@@ -77,15 +77,15 @@ func parseInt64(bytes []byte) (ret int64, err error) {
 
 // parseInt treats the given bytes as a big-endian, signed integer and returns
 // the result.
-func parseInt(bytes []byte) (int, error) {
+func parseInt32(bytes []byte) (int32, error) {
 	ret64, err := parseInt64(bytes)
 	if err != nil {
 		return 0, err
 	}
-	if ret64 != int64(int(ret64)) {
+	if ret64 != int64(int32(ret64)) {
 		return 0, StructuralError{"integer too large"}
 	}
-	return int(ret64), nil
+	return int32(ret64), nil
 }
 
 var bigOne = big.NewInt(1)
@@ -670,7 +670,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		err = err1
 		return
 	case enumeratedType:
-		parsedInt, err1 := parseInt(innerBytes)
+		parsedInt, err1 := parseInt32(innerBytes)
 		if err1 == nil {
 			v.SetInt(int64(parsedInt))
 		}
@@ -692,19 +692,20 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		}
 		err = err1
 		return
-	case reflect.Int, reflect.Int32:
-		parsedInt, err1 := parseInt(innerBytes)
-		if err1 == nil {
-			val.SetInt(int64(parsedInt))
-		}
-		err = err1
-		return
-	case reflect.Int64:
-		parsedInt, err1 := parseInt64(innerBytes)
-		if err1 == nil {
-			val.SetInt(parsedInt)
+	case reflect.Int, reflect.Int32, reflect.Int64:
+		if val.Type().Size() == 4 {
+			parsedInt, err1 := parseInt32(innerBytes)
+			if err1 == nil {
+				val.SetInt(int64(parsedInt))
+			}
+			err = err1
+		} else {
+			parsedInt, err1 := parseInt64(innerBytes)
+			if err1 == nil {
+				val.SetInt(parsedInt)
+			}
+			err = err1
 		}
-		err = err1
 		return
 	// TODO(dfc) Add support for the remaining integer types
 	case reflect.Struct:
diff --git a/src/pkg/encoding/asn1/asn1_test.go b/src/pkg/encoding/asn1/asn1_test.go
index eb848bd..6e98dcf 100644
--- a/src/pkg/encoding/asn1/asn1_test.go
+++ b/src/pkg/encoding/asn1/asn1_test.go
@@ -64,7 +64,7 @@ var int32TestData = []int32Test{
 
 func TestParseInt32(t *testing.T) {
 	for i, test := range int32TestData {
-		ret, err := parseInt(test.in)
+		ret, err := parseInt32(test.in)
 		if (err == nil) != test.ok {
 			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
 		}
@@ -124,7 +124,7 @@ func TestBitString(t *testing.T) {
 			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
 		}
 		if err == nil {
-			if test.bitLength != ret.BitLength || bytes.Compare(ret.Bytes, test.out) != 0 {
+			if test.bitLength != ret.BitLength || !bytes.Equal(ret.Bytes, test.out) {
 				t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength)
 			}
 		}
@@ -166,7 +166,7 @@ func TestBitStringRightAlign(t *testing.T) {
 	for i, test := range bitStringRightAlignTests {
 		bs := BitString{test.in, test.inlen}
 		out := bs.RightAlign()
-		if bytes.Compare(out, test.out) != 0 {
+		if !bytes.Equal(out, test.out) {
 			t.Errorf("#%d got: %x want: %x", i, out, test.out)
 		}
 	}
@@ -477,7 +477,7 @@ func TestRawStructs(t *testing.T) {
 	if s.A != 0x50 {
 		t.Errorf("bad value for A: got %d want %d", s.A, 0x50)
 	}
-	if bytes.Compare([]byte(s.Raw), input) != 0 {
+	if !bytes.Equal([]byte(s.Raw), input) {
 		t.Errorf("bad value for Raw: got %x want %x", s.Raw, input)
 	}
 }
diff --git a/src/pkg/encoding/asn1/common.go b/src/pkg/encoding/asn1/common.go
index 03856bc..33a117e 100644
--- a/src/pkg/encoding/asn1/common.go
+++ b/src/pkg/encoding/asn1/common.go
@@ -98,6 +98,8 @@ func parseFieldParameters(str string) (ret fieldParameters) {
 			ret.stringType = tagIA5String
 		case part == "printable":
 			ret.stringType = tagPrintableString
+		case part == "utf8":
+			ret.stringType = tagUTF8String
 		case strings.HasPrefix(part, "default:"):
 			i, err := strconv.ParseInt(part[8:], 10, 64)
 			if err == nil {
diff --git a/src/pkg/encoding/asn1/marshal.go b/src/pkg/encoding/asn1/marshal.go
index 163bca5..0c216fd 100644
--- a/src/pkg/encoding/asn1/marshal.go
+++ b/src/pkg/encoding/asn1/marshal.go
@@ -6,11 +6,13 @@ package asn1
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"io"
 	"math/big"
 	"reflect"
 	"time"
+	"unicode/utf8"
 )
 
 // A forkableWriter is an in-memory buffer that can be
@@ -280,6 +282,11 @@ func marshalIA5String(out *forkableWriter, s string) (err error) {
 	return
 }
 
+func marshalUTF8String(out *forkableWriter, s string) (err error) {
+	_, err = out.Write([]byte(s))
+	return
+}
+
 func marshalTwoDigits(out *forkableWriter, v int) (err error) {
 	err = out.WriteByte(byte('0' + (v/10)%10))
 	if err != nil {
@@ -289,8 +296,7 @@ func marshalTwoDigits(out *forkableWriter, v int) (err error) {
 }
 
 func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
-	utc := t.UTC()
-	year, month, day := utc.Date()
+	year, month, day := t.Date()
 
 	switch {
 	case 1950 <= year && year < 2000:
@@ -314,7 +320,7 @@ func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
 		return
 	}
 
-	hour, min, sec := utc.Clock()
+	hour, min, sec := t.Clock()
 
 	err = marshalTwoDigits(out, hour)
 	if err != nil {
@@ -446,10 +452,13 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
 		}
 		return
 	case reflect.String:
-		if params.stringType == tagIA5String {
+		switch params.stringType {
+		case tagIA5String:
 			return marshalIA5String(out, v.String())
-		} else {
+		case tagPrintableString:
 			return marshalPrintableString(out, v.String())
+		default:
+			return marshalUTF8String(out, v.String())
 		}
 		return
 	}
@@ -492,11 +501,27 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 	}
 	class := classUniversal
 
-	if params.stringType != 0 {
-		if tag != tagPrintableString {
-			return StructuralError{"Explicit string type given to non-string member"}
+	if params.stringType != 0 && tag != tagPrintableString {
+		return StructuralError{"Explicit string type given to non-string member"}
+	}
+
+	if tag == tagPrintableString {
+		if params.stringType == 0 {
+			// This is a string without an explicit string type. We'll use
+			// a PrintableString if the character set in the string is
+			// sufficiently limited, otherwise we'll use a UTF8String.
+			for _, r := range v.String() {
+				if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
+					if !utf8.ValidString(v.String()) {
+						return errors.New("asn1: string not valid UTF-8")
+					}
+					tag = tagUTF8String
+					break
+				}
+			}
+		} else {
+			tag = params.stringType
 		}
-		tag = params.stringType
 	}
 
 	if params.set {
diff --git a/src/pkg/encoding/asn1/marshal_test.go b/src/pkg/encoding/asn1/marshal_test.go
index f43bcae..b4dbe71 100644
--- a/src/pkg/encoding/asn1/marshal_test.go
+++ b/src/pkg/encoding/asn1/marshal_test.go
@@ -82,7 +82,7 @@ var marshalTests = []marshalTest{
 	{explicitTagTest{64}, "3005a503020140"},
 	{time.Unix(0, 0).UTC(), "170d3730303130313030303030305a"},
 	{time.Unix(1258325776, 0).UTC(), "170d3039313131353232353631365a"},
-	{time.Unix(1258325776, 0).In(PST), "17113039313131353232353631362d30383030"},
+	{time.Unix(1258325776, 0).In(PST), "17113039313131353134353631362d30383030"},
 	{BitString{[]byte{0x80}, 1}, "03020780"},
 	{BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"},
 	{ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"},
@@ -122,6 +122,7 @@ var marshalTests = []marshalTest{
 	{testSET([]int{10}), "310302010a"},
 	{omitEmptyTest{[]string{}}, "3000"},
 	{omitEmptyTest{[]string{"1"}}, "30053003130131"},
+	{"Σ", "0c02cea3"},
 }
 
 func TestMarshal(t *testing.T) {
@@ -131,9 +132,16 @@ func TestMarshal(t *testing.T) {
 			t.Errorf("#%d failed: %s", i, err)
 		}
 		out, _ := hex.DecodeString(test.out)
-		if bytes.Compare(out, data) != 0 {
+		if !bytes.Equal(out, data) {
 			t.Errorf("#%d got: %x want %x\n\t%q\n\t%q", i, data, out, data, out)
 
 		}
 	}
 }
+
+func TestInvalidUTF8(t *testing.T) {
+	_, err := Marshal(string([]byte{0xff, 0xff}))
+	if err == nil {
+		t.Errorf("invalid UTF8 string was accepted")
+	}
+}
diff --git a/src/pkg/encoding/base32/base32.go b/src/pkg/encoding/base32/base32.go
index 71da6e2..dbefc48 100644
--- a/src/pkg/encoding/base32/base32.go
+++ b/src/pkg/encoding/base32/base32.go
@@ -237,7 +237,6 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
 		dlen := 8
 
 		// do the top bytes contain any data?
-	dbufloop:
 		for j := 0; j < 8; {
 			if len(src) == 0 {
 				return n, false, CorruptInputError(len(osrc) - len(src) - j)
@@ -258,7 +257,7 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
 				}
 				dlen = j
 				end = true
-				break dbufloop
+				break
 			}
 			dbuf[j] = enc.decodeMap[in]
 			if dbuf[j] == 0xFF {
diff --git a/src/pkg/encoding/base32/example_test.go b/src/pkg/encoding/base32/example_test.go
new file mode 100644
index 0000000..f6128d9
--- /dev/null
+++ b/src/pkg/encoding/base32/example_test.go
@@ -0,0 +1,45 @@
+// 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.
+
+// Keep in sync with ../base64/example_test.go.
+
+package base32_test
+
+import (
+	"encoding/base32"
+	"fmt"
+	"os"
+)
+
+func ExampleEncoding_EncodeToString() {
+	data := []byte("any + old & data")
+	str := base32.StdEncoding.EncodeToString(data)
+	fmt.Println(str)
+	// Output:
+	// MFXHSIBLEBXWYZBAEYQGIYLUME======
+}
+
+func ExampleEncoding_DecodeString() {
+	str := "ONXW2ZJAMRQXIYJAO5UXI2BAAAQGC3TEEDX3XPY="
+	data, err := base32.StdEncoding.DecodeString(str)
+	if err != nil {
+		fmt.Println("error:", err)
+		return
+	}
+	fmt.Printf("%q\n", data)
+	// Output:
+	// "some data with \x00 and \ufeff"
+}
+
+func ExampleNewEncoder() {
+	input := []byte("foo\x00bar")
+	encoder := base32.NewEncoder(base32.StdEncoding, os.Stdout)
+	encoder.Write(input)
+	// Must close the encoder when finished to flush any partial blocks.
+	// If you comment out the following line, the last partial block "r"
+	// won't be encoded.
+	encoder.Close()
+	// Output:
+	// MZXW6ADCMFZA====
+}
diff --git a/src/pkg/encoding/base64/base64.go b/src/pkg/encoding/base64/base64.go
index 0b842f0..e66672a 100644
--- a/src/pkg/encoding/base64/base64.go
+++ b/src/pkg/encoding/base64/base64.go
@@ -216,7 +216,6 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
 		var dbuf [4]byte
 		dlen := 4
 
-	dbufloop:
 		for j := 0; j < 4; {
 			if len(src) == 0 {
 				return n, false, CorruptInputError(len(osrc) - len(src) - j)
@@ -240,7 +239,7 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
 				}
 				dlen = j
 				end = true
-				break dbufloop
+				break
 			}
 			dbuf[j] = enc.decodeMap[in]
 			if dbuf[j] == 0xFF {
diff --git a/src/pkg/encoding/base64/base64_test.go b/src/pkg/encoding/base64/base64_test.go
index f9b863c..2166abd 100644
--- a/src/pkg/encoding/base64/base64_test.go
+++ b/src/pkg/encoding/base64/base64_test.go
@@ -257,6 +257,7 @@ func TestDecoderIssue3577(t *testing.T) {
 	wantErr := errors.New("my error")
 	next <- nextRead{5, nil}
 	next <- nextRead{10, wantErr}
+	next <- nextRead{0, wantErr}
 	d := NewDecoder(StdEncoding, &faultInjectReader{
 		source: "VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==", // twas brillig...
 		nextc:  next,
diff --git a/src/pkg/encoding/base64/example_test.go b/src/pkg/encoding/base64/example_test.go
new file mode 100644
index 0000000..d18b856
--- /dev/null
+++ b/src/pkg/encoding/base64/example_test.go
@@ -0,0 +1,45 @@
+// 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.
+
+// Keep in sync with ../base32/example_test.go.
+
+package base64_test
+
+import (
+	"encoding/base64"
+	"fmt"
+	"os"
+)
+
+func ExampleEncoding_EncodeToString() {
+	data := []byte("any + old & data")
+	str := base64.StdEncoding.EncodeToString(data)
+	fmt.Println(str)
+	// Output:
+	// YW55ICsgb2xkICYgZGF0YQ==
+}
+
+func ExampleEncoding_DecodeString() {
+	str := "c29tZSBkYXRhIHdpdGggACBhbmQg77u/"
+	data, err := base64.StdEncoding.DecodeString(str)
+	if err != nil {
+		fmt.Println("error:", err)
+		return
+	}
+	fmt.Printf("%q\n", data)
+	// Output:
+	// "some data with \x00 and \ufeff"
+}
+
+func ExampleNewEncoder() {
+	input := []byte("foo\x00bar")
+	encoder := base64.NewEncoder(base64.StdEncoding, os.Stdout)
+	encoder.Write(input)
+	// Must close the encoder when finished to flush any partial blocks.
+	// If you comment out the following line, the last partial block "r"
+	// won't be encoded.
+	encoder.Close()
+	// Output:
+	// Zm9vAGJhcg==
+}
diff --git a/src/pkg/encoding/binary/binary.go b/src/pkg/encoding/binary/binary.go
index 712e490..edbac19 100644
--- a/src/pkg/encoding/binary/binary.go
+++ b/src/pkg/encoding/binary/binary.go
@@ -125,6 +125,9 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
 // of fixed-size values.
 // Bytes read from r are decoded using the specified byte order
 // and written to successive fields of the data.
+// When reading into structs, the field data for fields with
+// blank (_) field names is skipped; i.e., blank field names
+// may be used for padding.
 func Read(r io.Reader, order ByteOrder, data interface{}) error {
 	// Fast path for basic types.
 	if n := intDestSize(data); n != 0 {
@@ -154,7 +157,7 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
 		return nil
 	}
 
-	// Fallback to reflect-based.
+	// Fallback to reflect-based decoding.
 	var v reflect.Value
 	switch d := reflect.ValueOf(data); d.Kind() {
 	case reflect.Ptr:
@@ -164,9 +167,9 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
 	default:
 		return errors.New("binary.Read: invalid type " + d.Type().String())
 	}
-	size := dataSize(v)
-	if size < 0 {
-		return errors.New("binary.Read: invalid type " + v.Type().String())
+	size, err := dataSize(v)
+	if err != nil {
+		return errors.New("binary.Read: " + err.Error())
 	}
 	d := &decoder{order: order, buf: make([]byte, size)}
 	if _, err := io.ReadFull(r, d.buf); err != nil {
@@ -181,6 +184,8 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
 // values, or a pointer to such data.
 // Bytes written to w are encoded using the specified byte order
 // and read from successive fields of the data.
+// When writing structs, zero values are written for fields
+// with blank (_) field names.
 func Write(w io.Writer, order ByteOrder, data interface{}) error {
 	// Fast path for basic types.
 	var b [8]byte
@@ -239,76 +244,80 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error {
 		_, err := w.Write(bs)
 		return err
 	}
+
+	// Fallback to reflect-based encoding.
 	v := reflect.Indirect(reflect.ValueOf(data))
-	size := dataSize(v)
-	if size < 0 {
-		return errors.New("binary.Write: invalid type " + v.Type().String())
+	size, err := dataSize(v)
+	if err != nil {
+		return errors.New("binary.Write: " + err.Error())
 	}
 	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.
 func Size(v interface{}) int {
-	return dataSize(reflect.Indirect(reflect.ValueOf(v)))
+	n, err := dataSize(reflect.Indirect(reflect.ValueOf(v)))
+	if err != nil {
+		return -1
+	}
+	return n
 }
 
 // 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 {
+func dataSize(v reflect.Value) (int, error) {
 	if v.Kind() == reflect.Slice {
-		elem := sizeof(v.Type().Elem())
-		if elem < 0 {
-			return -1
+		elem, err := sizeof(v.Type().Elem())
+		if err != nil {
+			return 0, err
 		}
-		return v.Len() * elem
+		return v.Len() * elem, nil
 	}
 	return sizeof(v.Type())
 }
 
-func sizeof(t reflect.Type) int {
+func sizeof(t reflect.Type) (int, error) {
 	switch t.Kind() {
 	case reflect.Array:
-		n := sizeof(t.Elem())
-		if n < 0 {
-			return -1
+		n, err := sizeof(t.Elem())
+		if err != nil {
+			return 0, err
 		}
-		return t.Len() * n
+		return t.Len() * n, nil
 
 	case reflect.Struct:
 		sum := 0
 		for i, n := 0, t.NumField(); i < n; i++ {
-			s := sizeof(t.Field(i).Type)
-			if s < 0 {
-				return -1
+			s, err := sizeof(t.Field(i).Type)
+			if err != nil {
+				return 0, err
 			}
 			sum += s
 		}
-		return sum
+		return sum, nil
 
 	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())
+		return int(t.Size()), nil
 	}
-	return -1
+	return 0, errors.New("invalid type " + t.String())
 }
 
-type decoder struct {
+type coder struct {
 	order ByteOrder
 	buf   []byte
 }
 
-type encoder struct {
-	order ByteOrder
-	buf   []byte
-}
+type decoder coder
+type encoder coder
 
 func (d *decoder) uint8() uint8 {
 	x := d.buf[0]
@@ -379,9 +388,19 @@ func (d *decoder) value(v reflect.Value) {
 		}
 
 	case reflect.Struct:
+		t := v.Type()
 		l := v.NumField()
 		for i := 0; i < l; i++ {
-			d.value(v.Field(i))
+			// Note: Calling v.CanSet() below is an optimization.
+			// It would be sufficient to check the field name,
+			// but creating the StructField info for each field is
+			// costly (run "go test -bench=ReadStruct" and compare
+			// results when making changes to this code).
+			if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
+				d.value(v)
+			} else {
+				d.skip(v)
+			}
 		}
 
 	case reflect.Slice:
@@ -435,9 +454,15 @@ func (e *encoder) value(v reflect.Value) {
 		}
 
 	case reflect.Struct:
+		t := v.Type()
 		l := v.NumField()
 		for i := 0; i < l; i++ {
-			e.value(v.Field(i))
+			// see comment for corresponding code in decoder.value()
+			if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
+				e.value(v)
+			} else {
+				e.skip(v)
+			}
 		}
 
 	case reflect.Slice:
@@ -492,6 +517,19 @@ func (e *encoder) value(v reflect.Value) {
 	}
 }
 
+func (d *decoder) skip(v reflect.Value) {
+	n, _ := dataSize(v)
+	d.buf = d.buf[n:]
+}
+
+func (e *encoder) skip(v reflect.Value) {
+	n, _ := dataSize(v)
+	for i := range e.buf[0:n] {
+		e.buf[i] = 0
+	}
+	e.buf = e.buf[n:]
+}
+
 // intDestSize returns the size of the integer that ptrType points to,
 // or 0 if the type is not supported.
 func intDestSize(ptrType interface{}) int {
diff --git a/src/pkg/encoding/binary/binary_test.go b/src/pkg/encoding/binary/binary_test.go
index ff361b7..056f099 100644
--- a/src/pkg/encoding/binary/binary_test.go
+++ b/src/pkg/encoding/binary/binary_test.go
@@ -9,6 +9,7 @@ import (
 	"io"
 	"math"
 	"reflect"
+	"strings"
 	"testing"
 )
 
@@ -120,18 +121,14 @@ func testWrite(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
 	checkResult(t, "Write", order, err, buf.Bytes(), b)
 }
 
-func TestBigEndianRead(t *testing.T) { testRead(t, BigEndian, big, s) }
-
-func TestLittleEndianRead(t *testing.T) { testRead(t, LittleEndian, little, s) }
-
-func TestBigEndianWrite(t *testing.T) { testWrite(t, BigEndian, big, s) }
-
-func TestLittleEndianWrite(t *testing.T) { testWrite(t, LittleEndian, little, s) }
+func TestLittleEndianRead(t *testing.T)     { testRead(t, LittleEndian, little, s) }
+func TestLittleEndianWrite(t *testing.T)    { testWrite(t, LittleEndian, little, s) }
+func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
 
+func TestBigEndianRead(t *testing.T)     { testRead(t, BigEndian, big, s) }
+func TestBigEndianWrite(t *testing.T)    { testWrite(t, BigEndian, big, s) }
 func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) }
 
-func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
-
 func TestReadSlice(t *testing.T) {
 	slice := make([]int32, 2)
 	err := Read(bytes.NewBuffer(src), BigEndian, slice)
@@ -147,20 +144,81 @@ func TestWriteSlice(t *testing.T) {
 func TestWriteT(t *testing.T) {
 	buf := new(bytes.Buffer)
 	ts := T{}
-	err := Write(buf, BigEndian, ts)
-	if err == nil {
-		t.Errorf("WriteT: have nil, want non-nil")
+	if err := Write(buf, BigEndian, ts); err == nil {
+		t.Errorf("WriteT: have err == nil, want non-nil")
 	}
 
 	tv := reflect.Indirect(reflect.ValueOf(ts))
 	for i, n := 0, tv.NumField(); i < n; i++ {
-		err = Write(buf, BigEndian, tv.Field(i).Interface())
-		if err == nil {
-			t.Errorf("WriteT.%v: have nil, want non-nil", tv.Field(i).Type())
+		typ := tv.Field(i).Type().String()
+		if typ == "[4]int" {
+			typ = "int" // the problem is int, not the [4]
+		}
+		if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil {
+			t.Errorf("WriteT.%v: have err == nil, want non-nil", tv.Field(i).Type())
+		} else if !strings.Contains(err.Error(), typ) {
+			t.Errorf("WriteT: have err == %q, want it to mention %s", err, typ)
 		}
 	}
 }
 
+type BlankFields struct {
+	A uint32
+	_ int32
+	B float64
+	_ [4]int16
+	C byte
+	_ [7]byte
+	_ struct {
+		f [8]float32
+	}
+}
+
+type BlankFieldsProbe struct {
+	A  uint32
+	P0 int32
+	B  float64
+	P1 [4]int16
+	C  byte
+	P2 [7]byte
+	P3 struct {
+		F [8]float32
+	}
+}
+
+func TestBlankFields(t *testing.T) {
+	buf := new(bytes.Buffer)
+	b1 := BlankFields{A: 1234567890, B: 2.718281828, C: 42}
+	if err := Write(buf, LittleEndian, &b1); err != nil {
+		t.Error(err)
+	}
+
+	// zero values must have been written for blank fields
+	var p BlankFieldsProbe
+	if err := Read(buf, LittleEndian, &p); err != nil {
+		t.Error(err)
+	}
+
+	// quick test: only check first value of slices
+	if p.P0 != 0 || p.P1[0] != 0 || p.P2[0] != 0 || p.P3.F[0] != 0 {
+		t.Errorf("non-zero values for originally blank fields: %#v", p)
+	}
+
+	// write p and see if we can probe only some fields
+	if err := Write(buf, LittleEndian, &p); err != nil {
+		t.Error(err)
+	}
+
+	// read should ignore blank fields in b2
+	var b2 BlankFields
+	if err := Read(buf, LittleEndian, &b2); err != nil {
+		t.Error(err)
+	}
+	if b1.A != b2.A || b1.B != b2.B || b1.C != b2.C {
+		t.Errorf("%#v != %#v", b1, b2)
+	}
+}
+
 type byteSliceReader struct {
 	remain []byte
 }
@@ -187,7 +245,7 @@ func BenchmarkReadStruct(b *testing.B) {
 	bsr := &byteSliceReader{}
 	var buf bytes.Buffer
 	Write(&buf, BigEndian, &s)
-	n := dataSize(reflect.ValueOf(s))
+	n, _ := dataSize(reflect.ValueOf(s))
 	b.SetBytes(int64(n))
 	t := s
 	b.ResetTimer()
diff --git a/src/pkg/encoding/binary/varint.go b/src/pkg/encoding/binary/varint.go
index b756afd..7035529 100644
--- a/src/pkg/encoding/binary/varint.go
+++ b/src/pkg/encoding/binary/varint.go
@@ -123,7 +123,7 @@ func ReadUvarint(r io.ByteReader) (uint64, error) {
 	panic("unreachable")
 }
 
-// ReadVarint reads an encoded unsigned integer from r and returns it as a uint64.
+// ReadVarint reads an encoded signed integer from r and returns it as an int64.
 func ReadVarint(r io.ByteReader) (int64, error) {
 	ux, err := ReadUvarint(r) // ok to continue in presence of error
 	x := int64(ux >> 1)
diff --git a/src/pkg/encoding/csv/writer.go b/src/pkg/encoding/csv/writer.go
index c4dcba5..1faecb6 100644
--- a/src/pkg/encoding/csv/writer.go
+++ b/src/pkg/encoding/csv/writer.go
@@ -22,7 +22,7 @@ import (
 //
 // If UseCRLF is true, the Writer ends each record with \r\n instead of \n.
 type Writer struct {
-	Comma   rune // Field delimiter (set to to ',' by NewWriter)
+	Comma   rune // Field delimiter (set to ',' by NewWriter)
 	UseCRLF bool // True to use \r\n as the line terminator
 	w       *bufio.Writer
 }
@@ -92,20 +92,26 @@ func (w *Writer) Write(record []string) (err error) {
 }
 
 // Flush writes any buffered data to the underlying io.Writer.
+// To check if an error occurred during the Flush, call Error.
 func (w *Writer) Flush() {
 	w.w.Flush()
 }
 
+// Error reports any error that has occurred during a previous Write or Flush.
+func (w *Writer) Error() error {
+	_, err := w.w.Write(nil)
+	return err
+}
+
 // WriteAll writes multiple CSV records to w using Write and then calls Flush.
 func (w *Writer) WriteAll(records [][]string) (err error) {
 	for _, record := range records {
 		err = w.Write(record)
 		if err != nil {
-			break
+			return err
 		}
 	}
-	w.Flush()
-	return nil
+	return w.w.Flush()
 }
 
 // fieldNeedsQuotes returns true if our field must be enclosed in quotes.
diff --git a/src/pkg/encoding/csv/writer_test.go b/src/pkg/encoding/csv/writer_test.go
index 5789590..03ca6b0 100644
--- a/src/pkg/encoding/csv/writer_test.go
+++ b/src/pkg/encoding/csv/writer_test.go
@@ -6,6 +6,7 @@ package csv
 
 import (
 	"bytes"
+	"errors"
 	"testing"
 )
 
@@ -42,3 +43,30 @@ func TestWrite(t *testing.T) {
 		}
 	}
 }
+
+type errorWriter struct{}
+
+func (e errorWriter) Write(b []byte) (int, error) {
+	return 0, errors.New("Test")
+}
+
+func TestError(t *testing.T) {
+	b := &bytes.Buffer{}
+	f := NewWriter(b)
+	f.Write([]string{"abc"})
+	f.Flush()
+	err := f.Error()
+
+	if err != nil {
+		t.Errorf("Unexpected error: %s\n", err)
+	}
+
+	f = NewWriter(errorWriter{})
+	f.Write([]string{"abc"})
+	f.Flush()
+	err = f.Error()
+
+	if err == nil {
+		t.Error("Error should not be nil")
+	}
+}
diff --git a/src/pkg/encoding/gob/codec_test.go b/src/pkg/encoding/gob/codec_test.go
index ebcbb78..482212b 100644
--- a/src/pkg/encoding/gob/codec_test.go
+++ b/src/pkg/encoding/gob/codec_test.go
@@ -7,6 +7,7 @@ package gob
 import (
 	"bytes"
 	"errors"
+	"flag"
 	"math"
 	"math/rand"
 	"reflect"
@@ -16,6 +17,8 @@ import (
 	"unsafe"
 )
 
+var doFuzzTests = flag.Bool("gob.fuzz", false, "run the fuzz tests, which are large and very slow")
+
 // Guarantee encoding format by comparing some encodings to hand-written values
 type EncodeT struct {
 	x uint64
@@ -1434,7 +1437,8 @@ func encFuzzDec(rng *rand.Rand, in interface{}) error {
 
 // This does some "fuzz testing" by attempting to decode a sequence of random bytes.
 func TestFuzz(t *testing.T) {
-	if testing.Short() {
+	if !*doFuzzTests {
+		t.Logf("disabled; run with -gob.fuzz to enable")
 		return
 	}
 
@@ -1453,11 +1457,16 @@ func TestFuzz(t *testing.T) {
 }
 
 func TestFuzzRegressions(t *testing.T) {
+	if !*doFuzzTests {
+		t.Logf("disabled; run with -gob.fuzz to enable")
+		return
+	}
+
 	// An instance triggering a type name of length ~102 GB.
 	testFuzz(t, 1328492090837718000, 100, new(float32))
 	// An instance triggering a type name of 1.6 GB.
-	// Commented out because it takes 5m to run.
-	//testFuzz(t, 1330522872628565000, 100, new(int))
+	// Note: can take several minutes to run.
+	testFuzz(t, 1330522872628565000, 100, new(int))
 }
 
 func testFuzz(t *testing.T, seed int64, n int, input ...interface{}) {
diff --git a/src/pkg/encoding/gob/decode.go b/src/pkg/encoding/gob/decode.go
index e32a178..a80d9f9 100644
--- a/src/pkg/encoding/gob/decode.go
+++ b/src/pkg/encoding/gob/decode.go
@@ -62,15 +62,15 @@ func overflow(name string) error {
 // Used only by the Decoder to read the message length.
 func decodeUintReader(r io.Reader, buf []byte) (x uint64, width int, err error) {
 	width = 1
-	_, err = r.Read(buf[0:width])
-	if err != nil {
+	n, err := io.ReadFull(r, buf[0:width])
+	if n == 0 {
 		return
 	}
 	b := buf[0]
 	if b <= 0x7f {
 		return uint64(b), width, nil
 	}
-	n := -int(int8(b))
+	n = -int(int8(b))
 	if n > uint64Size {
 		err = errBadUint
 		return
@@ -562,6 +562,9 @@ func (dec *Decoder) ignoreSingle(engine *decEngine) {
 func (dec *Decoder) decodeArrayHelper(state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
 	instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
 	for i := 0; i < length; i++ {
+		if state.b.Len() == 0 {
+			errorf("decoding array or slice: length exceeds input size (%d elements)", length)
+		}
 		up := unsafe.Pointer(p)
 		if elemIndir > 1 {
 			up = decIndirect(up, elemIndir)
@@ -652,9 +655,6 @@ func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) {
 // Slices are encoded as an unsigned length followed by the elements.
 func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) {
 	nr := state.decodeUint()
-	if nr > uint64(state.b.Len()) {
-		errorf("length of slice exceeds input size (%d elements)", nr)
-	}
 	n := int(nr)
 	if indir > 0 {
 		up := unsafe.Pointer(p)
@@ -717,7 +717,9 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p ui
 		errorf("name too long (%d bytes): %.20q...", len(name), name)
 	}
 	// The concrete type must be registered.
+	registerLock.RLock()
 	typ, ok := nameToConcreteType[name]
+	registerLock.RUnlock()
 	if !ok {
 		errorf("name not registered for interface: %q", name)
 	}
diff --git a/src/pkg/encoding/gob/decoder.go b/src/pkg/encoding/gob/decoder.go
index c5c7d3f..04f706c 100644
--- a/src/pkg/encoding/gob/decoder.go
+++ b/src/pkg/encoding/gob/decoder.go
@@ -87,21 +87,38 @@ func (dec *Decoder) recvMessage() bool {
 
 // readMessage reads the next nbytes bytes from the input.
 func (dec *Decoder) readMessage(nbytes int) {
-	// Allocate the buffer.
-	if cap(dec.tmp) < nbytes {
-		dec.tmp = make([]byte, nbytes+100) // room to grow
+	// Allocate the dec.tmp buffer, up to 10KB.
+	const maxBuf = 10 * 1024
+	nTmp := nbytes
+	if nTmp > maxBuf {
+		nTmp = maxBuf
 	}
-	dec.tmp = dec.tmp[:nbytes]
+	if cap(dec.tmp) < nTmp {
+		nAlloc := nTmp + 100 // A little extra for growth.
+		if nAlloc > maxBuf {
+			nAlloc = maxBuf
+		}
+		dec.tmp = make([]byte, nAlloc)
+	}
+	dec.tmp = dec.tmp[:nTmp]
 
 	// Read the data
-	_, dec.err = io.ReadFull(dec.r, dec.tmp)
-	if dec.err != nil {
-		if dec.err == io.EOF {
-			dec.err = io.ErrUnexpectedEOF
+	dec.buf.Grow(nbytes)
+	for nbytes > 0 {
+		if nbytes < nTmp {
+			dec.tmp = dec.tmp[:nbytes]
 		}
-		return
+		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.Write(dec.tmp)
+		nbytes -= nRead
 	}
-	dec.buf.Write(dec.tmp)
 }
 
 // toInt turns an encoded uint64 into an int, according to the marshaling rules.
diff --git a/src/pkg/encoding/gob/doc.go b/src/pkg/encoding/gob/doc.go
index 821d9a3..5bd61b1 100644
--- a/src/pkg/encoding/gob/doc.go
+++ b/src/pkg/encoding/gob/doc.go
@@ -67,11 +67,13 @@ point values may be received into any floating point variable.  However,
 the destination variable must be able to represent the value or the decode
 operation will fail.
 
-Structs, arrays and slices are also supported.  Strings and arrays of bytes are
-supported with a special, efficient representation (see below).  When a slice is
-decoded, if the existing slice has capacity the slice will be extended in place;
-if not, a new array is allocated.  Regardless, the length of the resulting slice
-reports the number of elements decoded.
+Structs, arrays and slices are also supported.  Structs encode and
+decode only exported fields. Strings and arrays of bytes are supported
+with a special, efficient representation (see below).  When a slice
+is decoded, if the existing slice has capacity the slice will be
+extended in place; if not, a new array is allocated.  Regardless,
+the length of the resulting slice reports the number of elements
+decoded.
 
 Functions and channels cannot be sent in a gob.  Attempting
 to encode a value that contains one will fail.
@@ -118,7 +120,7 @@ elements using the standard gob encoding for their type, recursively.
 
 Maps are sent as an unsigned count followed by that many key, element
 pairs. Empty but non-nil maps are sent, so if the sender has allocated
-a map, the receiver will allocate a map even no elements are
+a map, the receiver will allocate a map even if no elements are
 transmitted.
 
 Structs are sent as a sequence of (field number, field value) pairs.  The field
@@ -328,7 +330,7 @@ reserved).
 	01	// Add 1 to get field number 0: field[1].name
 	01	// 1 byte
 	59	// structType.field[1].name = "Y"
-	01	// Add 1 to get field number 1: field[0].id
+	01	// Add 1 to get field number 1: field[1].id
 	04	// struct.Type.field[1].typeId is 2 (signed int).
 	00	// End of structType.field[1]; end of structType.field.
 	00	// end of wireType.structType structure
diff --git a/src/pkg/encoding/gob/encode.go b/src/pkg/encoding/gob/encode.go
index 168e08b..ea37a6c 100644
--- a/src/pkg/encoding/gob/encode.go
+++ b/src/pkg/encoding/gob/encode.go
@@ -426,6 +426,12 @@ func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp e
 // 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) {
+	// Gobs can encode nil interface values but not typed interface
+	// values holding nil pointers, since nil pointers point to no value.
+	elem := iv.Elem()
+	if elem.Kind() == reflect.Ptr && elem.IsNil() {
+		errorf("gob: cannot encode nil pointer of type %s inside interface", iv.Elem().Type())
+	}
 	state := enc.newEncoderState(b)
 	state.fieldnum = -1
 	state.sendZero = true
@@ -435,7 +441,9 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
 	}
 
 	ut := userType(iv.Elem().Type())
+	registerLock.RLock()
 	name, ok := concreteTypeToName[ut.base]
+	registerLock.RUnlock()
 	if !ok {
 		errorf("type not registered for interface: %s", ut.base)
 	}
@@ -454,7 +462,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
 	enc.pushWriter(b)
 	data := new(bytes.Buffer)
 	data.Write(spaceForLength)
-	enc.encode(data, iv.Elem(), ut)
+	enc.encode(data, elem, ut)
 	if enc.err != nil {
 		error_(enc.err)
 	}
@@ -698,9 +706,20 @@ func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine {
 		error_(err1)
 	}
 	if info.encoder == nil {
-		// mark this engine as underway before compiling to handle recursive types.
+		// 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
 	}
 	return info.encoder
 }
diff --git a/src/pkg/encoding/gob/encoder.go b/src/pkg/encoding/gob/encoder.go
index a15b5a1..f669c3d 100644
--- a/src/pkg/encoding/gob/encoder.go
+++ b/src/pkg/encoding/gob/encoder.go
@@ -132,13 +132,13 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
 	return true
 }
 
-// sendType sends the type info to the other side, if necessary. 
+// sendType sends the type info to the other side, if necessary.
 func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) {
 	ut := userType(origt)
 	if ut.isGobEncoder {
 		// The rules are different: regardless of the underlying type's representation,
-		// we need to tell the other side that this exact type is a GobEncoder.
-		return enc.sendActualType(w, state, ut, ut.user)
+		// we need to tell the other side that the base type is a GobEncoder.
+		return enc.sendActualType(w, state, ut, ut.base)
 	}
 
 	// It's a concrete value, so drill down to the base type.
@@ -218,6 +218,12 @@ func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) {
 // EncodeValue transmits the data item represented by the reflection value,
 // guaranteeing that all necessary type information has been transmitted first.
 func (enc *Encoder) EncodeValue(value reflect.Value) error {
+	// Gobs contain values. They cannot represent nil pointers, which
+	// have no value to encode.
+	if value.Kind() == reflect.Ptr && value.IsNil() {
+		panic("gob: cannot encode nil pointer of type " + value.Type().String())
+	}
+
 	// Make sure we're single-threaded through here, so multiple
 	// goroutines can share an encoder.
 	enc.mutex.Lock()
diff --git a/src/pkg/encoding/gob/encoder_test.go b/src/pkg/encoding/gob/encoder_test.go
index c4947cb..b684772 100644
--- a/src/pkg/encoding/gob/encoder_test.go
+++ b/src/pkg/encoding/gob/encoder_test.go
@@ -736,3 +736,109 @@ func TestPtrToMapOfMap(t *testing.T) {
 		t.Fatalf("expected %v got %v", data, newData)
 	}
 }
+
+// A top-level nil pointer generates a panic with a helpful string-valued message.
+func TestTopLevelNilPointer(t *testing.T) {
+	errMsg := topLevelNilPanic(t)
+	if errMsg == "" {
+		t.Fatal("top-level nil pointer did not panic")
+	}
+	if !strings.Contains(errMsg, "nil pointer") {
+		t.Fatal("expected nil pointer error, got:", errMsg)
+	}
+}
+
+func topLevelNilPanic(t *testing.T) (panicErr string) {
+	defer func() {
+		e := recover()
+		if err, ok := e.(string); ok {
+			panicErr = err
+		}
+	}()
+	var ip *int
+	buf := new(bytes.Buffer)
+	if err := NewEncoder(buf).Encode(ip); err != nil {
+		t.Fatal("error in encode:", err)
+	}
+	return
+}
+
+func TestNilPointerInsideInterface(t *testing.T) {
+	var ip *int
+	si := struct {
+		I interface{}
+	}{
+		I: ip,
+	}
+	buf := new(bytes.Buffer)
+	err := NewEncoder(buf).Encode(si)
+	if err == nil {
+		t.Fatal("expected error, got none")
+	}
+	errMsg := err.Error()
+	if !strings.Contains(errMsg, "nil pointer") || !strings.Contains(errMsg, "interface") {
+		t.Fatal("expected error about nil pointer and interface, got:", errMsg)
+	}
+}
+
+type Bug4Public struct {
+	Name   string
+	Secret Bug4Secret
+}
+
+type Bug4Secret struct {
+	a int // error: no exported fields.
+}
+
+// Test that a failed compilation doesn't leave around an executable encoder.
+// Issue 3273.
+func TestMutipleEncodingsOfBadType(t *testing.T) {
+	x := Bug4Public{
+		Name:   "name",
+		Secret: Bug4Secret{1},
+	}
+	buf := new(bytes.Buffer)
+	enc := NewEncoder(buf)
+	err := enc.Encode(x)
+	if err == nil {
+		t.Fatal("first encoding: expected error")
+	}
+	buf.Reset()
+	enc = NewEncoder(buf)
+	err = enc.Encode(x)
+	if err == nil {
+		t.Fatal("second encoding: expected error")
+	}
+	if !strings.Contains(err.Error(), "no exported fields") {
+		t.Errorf("expected error about no exported fields; got %v", err)
+	}
+}
+
+// There was an error check comparing the length of the input with the
+// length of the slice being decoded. It was wrong because the next
+// thing in the input might be a type definition, which would lead to
+// an incorrect length check.  This test reproduces the corner case.
+
+type Z struct {
+}
+
+func Test29ElementSlice(t *testing.T) {
+	Register(Z{})
+	src := make([]interface{}, 100) // Size needs to be bigger than size of type definition.
+	for i := range src {
+		src[i] = Z{}
+	}
+	buf := new(bytes.Buffer)
+	err := NewEncoder(buf).Encode(src)
+	if err != nil {
+		t.Fatalf("encode: %v", err)
+		return
+	}
+
+	var dst []interface{}
+	err = NewDecoder(buf).Decode(&dst)
+	if err != nil {
+		t.Errorf("decode: %v", err)
+		return
+	}
+}
diff --git a/src/pkg/encoding/gob/gobencdec_test.go b/src/pkg/encoding/gob/gobencdec_test.go
index 45240d7..ddcd80b 100644
--- a/src/pkg/encoding/gob/gobencdec_test.go
+++ b/src/pkg/encoding/gob/gobencdec_test.go
@@ -1,4 +1,4 @@
-// Copyright 20011 The Go Authors. All rights reserved.
+// 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.
 
@@ -142,6 +142,18 @@ type GobTest5 struct {
 	V *ValueGobber
 }
 
+type GobTest6 struct {
+	X int // guarantee we have  something in common with GobTest*
+	V ValueGobber
+	W *ValueGobber
+}
+
+type GobTest7 struct {
+	X int // guarantee we have  something in common with GobTest*
+	V *ValueGobber
+	W ValueGobber
+}
+
 type GobTestIgnoreEncoder struct {
 	X int // guarantee we have  something in common with GobTest*
 }
@@ -336,7 +348,7 @@ func TestGobEncoderFieldsOfDifferentType(t *testing.T) {
 		t.Fatal("decode error:", err)
 	}
 	if y.G.s != "XYZ" {
-		t.Fatalf("expected `XYZ` got %c", y.G.s)
+		t.Fatalf("expected `XYZ` got %q", y.G.s)
 	}
 }
 
@@ -360,6 +372,61 @@ func TestGobEncoderValueEncoder(t *testing.T) {
 	}
 }
 
+// Test that we can use a value then a pointer type of a GobEncoder
+// in the same encoded value.  Bug 4647.
+func TestGobEncoderValueThenPointer(t *testing.T) {
+	v := ValueGobber("forty-two")
+	w := ValueGobber("six-by-nine")
+
+	// this was a bug: encoding a GobEncoder by value before a GobEncoder
+	// pointer would cause duplicate type definitions to be sent.
+
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	if err := enc.Encode(GobTest6{42, v, &w}); err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest6)
+	if err := dec.Decode(x); err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if got, want := x.V, v; got != want {
+		t.Errorf("v = %q, want %q", got, want)
+	}
+	if got, want := x.W, w; got == nil {
+		t.Errorf("w = nil, want %q", want)
+	} else if *got != want {
+		t.Errorf("w = %q, want %q", *got, want)
+	}
+}
+
+// Test that we can use a pointer then a value type of a GobEncoder
+// in the same encoded value.
+func TestGobEncoderPointerThenValue(t *testing.T) {
+	v := ValueGobber("forty-two")
+	w := ValueGobber("six-by-nine")
+
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	if err := enc.Encode(GobTest7{42, &v, w}); err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest7)
+	if err := dec.Decode(x); err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if got, want := x.V, v; got == nil {
+		t.Errorf("v = nil, want %q", want)
+	} else if *got != want {
+		t.Errorf("v = %q, want %q", got, want)
+	}
+	if got, want := x.W, w; got != want {
+		t.Errorf("w = %q, want %q", got, want)
+	}
+}
+
 func TestGobEncoderFieldTypeError(t *testing.T) {
 	// GobEncoder to non-decoder: error
 	b := new(bytes.Buffer)
diff --git a/src/pkg/encoding/gob/timing_test.go b/src/pkg/encoding/gob/timing_test.go
index b9371c4..13eb119 100644
--- a/src/pkg/encoding/gob/timing_test.go
+++ b/src/pkg/encoding/gob/timing_test.go
@@ -9,7 +9,6 @@ import (
 	"fmt"
 	"io"
 	"os"
-	"runtime"
 	"testing"
 )
 
@@ -50,47 +49,43 @@ func BenchmarkEndToEndByteBuffer(b *testing.B) {
 }
 
 func TestCountEncodeMallocs(t *testing.T) {
+	const N = 1000
+
 	var buf bytes.Buffer
 	enc := NewEncoder(&buf)
 	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
-	memstats := new(runtime.MemStats)
-	runtime.ReadMemStats(memstats)
-	mallocs := 0 - memstats.Mallocs
-	const count = 1000
-	for i := 0; i < count; i++ {
+
+	allocs := testing.AllocsPerRun(N, func() {
 		err := enc.Encode(bench)
 		if err != nil {
 			t.Fatal("encode:", err)
 		}
-	}
-	runtime.ReadMemStats(memstats)
-	mallocs += memstats.Mallocs
-	fmt.Printf("mallocs per encode of type Bench: %d\n", mallocs/count)
+	})
+	fmt.Printf("mallocs per encode of type Bench: %v\n", allocs)
 }
 
 func TestCountDecodeMallocs(t *testing.T) {
+	const N = 1000
+
 	var buf bytes.Buffer
 	enc := NewEncoder(&buf)
 	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
-	const count = 1000
-	for i := 0; i < count; i++ {
+
+	// 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)
-	memstats := new(runtime.MemStats)
-	runtime.ReadMemStats(memstats)
-	mallocs := 0 - memstats.Mallocs
-	for i := 0; i < count; i++ {
+	allocs := testing.AllocsPerRun(N, func() {
 		*bench = Bench{}
 		err := dec.Decode(&bench)
 		if err != nil {
 			t.Fatal("decode:", err)
 		}
-	}
-	runtime.ReadMemStats(memstats)
-	mallocs += memstats.Mallocs
-	fmt.Printf("mallocs per decode of type Bench: %d\n", mallocs/count)
+	})
+	fmt.Printf("mallocs per decode of type Bench: %v\n", allocs)
 }
diff --git a/src/pkg/encoding/gob/type.go b/src/pkg/encoding/gob/type.go
index 0dd7a0a..ea0db4e 100644
--- a/src/pkg/encoding/gob/type.go
+++ b/src/pkg/encoding/gob/type.go
@@ -712,6 +712,7 @@ type GobDecoder interface {
 }
 
 var (
+	registerLock       sync.RWMutex
 	nameToConcreteType = make(map[string]reflect.Type)
 	concreteTypeToName = make(map[reflect.Type]string)
 )
@@ -723,6 +724,8 @@ func RegisterName(name string, value interface{}) {
 		// reserved for nil
 		panic("attempt to register empty name")
 	}
+	registerLock.Lock()
+	defer registerLock.Unlock()
 	ut := userType(reflect.TypeOf(value))
 	// Check for incompatible duplicates. The name must refer to the
 	// same user type, and vice versa.
@@ -749,12 +752,28 @@ func Register(value interface{}) {
 	rt := reflect.TypeOf(value)
 	name := rt.String()
 
-	// But for named types (or pointers to them), qualify with import path.
+	// But for named types (or pointers to them), qualify with import path (but see inner comment).
 	// Dereference one pointer looking for a named type.
 	star := ""
 	if rt.Name() == "" {
 		if pt := rt; pt.Kind() == reflect.Ptr {
 			star = "*"
+			// NOTE: The following line should be rt = pt.Elem() to implement
+			// what the comment above claims, but fixing it would break compatibility
+			// with existing gobs.
+			//
+			// Given package p imported as "full/p" with these definitions:
+			//     package p
+			//     type T1 struct { ... }
+			// this table shows the intended and actual strings used by gob to
+			// name the types:
+			//
+			// Type      Correct string     Actual string
+			//
+			// T1        full/p.T1          full/p.T1
+			// *T1       *full/p.T1         *p.T1
+			//
+			// The missing full path cannot be fixed without breaking existing gob decoders.
 			rt = pt
 		}
 	}
diff --git a/src/pkg/encoding/gob/type_test.go b/src/pkg/encoding/gob/type_test.go
index 42bdb4c..e230d22 100644
--- a/src/pkg/encoding/gob/type_test.go
+++ b/src/pkg/encoding/gob/type_test.go
@@ -5,6 +5,7 @@
 package gob
 
 import (
+	"bytes"
 	"reflect"
 	"testing"
 )
@@ -159,3 +160,63 @@ func TestRegistration(t *testing.T) {
 	Register(new(T))
 	Register(new(T))
 }
+
+type N1 struct{}
+type N2 struct{}
+
+// See comment in type.go/Register.
+func TestRegistrationNaming(t *testing.T) {
+	testCases := []struct {
+		t    interface{}
+		name string
+	}{
+		{&N1{}, "*gob.N1"},
+		{N2{}, "encoding/gob.N2"},
+	}
+
+	for _, tc := range testCases {
+		Register(tc.t)
+
+		tct := reflect.TypeOf(tc.t)
+		registerLock.RLock()
+		ct := nameToConcreteType[tc.name]
+		registerLock.RUnlock()
+		if ct != tct {
+			t.Errorf("nameToConcreteType[%q] = %v, want %v", tc.name, ct, tct)
+		}
+		// concreteTypeToName is keyed off the base type.
+		if tct.Kind() == reflect.Ptr {
+			tct = tct.Elem()
+		}
+		if n := concreteTypeToName[tct]; n != tc.name {
+			t.Errorf("concreteTypeToName[%v] got %v, want %v", tct, n, tc.name)
+		}
+	}
+}
+
+func TestStressParallel(t *testing.T) {
+	type T2 struct{ A int }
+	c := make(chan bool)
+	const N = 10
+	for i := 0; i < N; i++ {
+		go func() {
+			p := new(T2)
+			Register(p)
+			b := new(bytes.Buffer)
+			enc := NewEncoder(b)
+			err := enc.Encode(p)
+			if err != nil {
+				t.Error("encoder fail:", err)
+			}
+			dec := NewDecoder(b)
+			err = dec.Decode(p)
+			if err != nil {
+				t.Error("decoder fail:", err)
+			}
+			c <- true
+		}()
+	}
+	for i := 0; i < N; i++ {
+		<-c
+	}
+}
diff --git a/src/pkg/encoding/hex/hex_test.go b/src/pkg/encoding/hex/hex_test.go
index 456f9ea..356f590 100644
--- a/src/pkg/encoding/hex/hex_test.go
+++ b/src/pkg/encoding/hex/hex_test.go
@@ -65,7 +65,7 @@ func TestDecodeString(t *testing.T) {
 			t.Errorf("#%d: unexpected err value: %s", i, err)
 			continue
 		}
-		if bytes.Compare(dst, test.dec) != 0 {
+		if !bytes.Equal(dst, test.dec) {
 			t.Errorf("#%d: got: %#v want: #%v", i, dst, test.dec)
 		}
 	}
diff --git a/src/pkg/encoding/json/bench_test.go b/src/pkg/encoding/json/bench_test.go
index 333c1c0..29dbc26 100644
--- a/src/pkg/encoding/json/bench_test.go
+++ b/src/pkg/encoding/json/bench_test.go
@@ -153,5 +153,37 @@ func BenchmarkCodeUnmarshalReuse(b *testing.B) {
 			b.Fatal("Unmmarshal:", err)
 		}
 	}
-	b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkUnmarshalString(b *testing.B) {
+	data := []byte(`"hello, world"`)
+	var s string
+
+	for i := 0; i < b.N; i++ {
+		if err := Unmarshal(data, &s); err != nil {
+			b.Fatal("Unmarshal:", err)
+		}
+	}
+}
+
+func BenchmarkUnmarshalFloat64(b *testing.B) {
+	var f float64
+	data := []byte(`3.14`)
+
+	for i := 0; i < b.N; i++ {
+		if err := Unmarshal(data, &f); err != nil {
+			b.Fatal("Unmarshal:", err)
+		}
+	}
+}
+
+func BenchmarkUnmarshalInt64(b *testing.B) {
+	var x int64
+	data := []byte(`3`)
+
+	for i := 0; i < b.N; i++ {
+		if err := Unmarshal(data, &x); err != nil {
+			b.Fatal("Unmarshal:", err)
+		}
+	}
 }
diff --git a/src/pkg/encoding/json/decode.go b/src/pkg/encoding/json/decode.go
index d61f887..f2ec9cb 100644
--- a/src/pkg/encoding/json/decode.go
+++ b/src/pkg/encoding/json/decode.go
@@ -33,6 +33,10 @@ import (
 // the value pointed at by the pointer.  If the pointer is nil, Unmarshal
 // allocates a new value for it to point to.
 //
+// To unmarshal JSON into a struct, Unmarshal matches incoming object
+// keys to the keys used by Marshal (either the struct field name or its tag),
+// preferring an exact match but also accepting a case-insensitive match.
+//
 // To unmarshal JSON into an interface value, Unmarshal unmarshals
 // the JSON into the concrete value contained in the interface value.
 // If the interface value is nil, that is, has no concrete value stored in it,
@@ -51,24 +55,29 @@ import (
 // If no more serious errors are encountered, Unmarshal returns
 // an UnmarshalTypeError describing the earliest such error.
 //
+// When unmarshaling quoted strings, invalid UTF-8 or
+// invalid UTF-16 surrogate pairs are not treated as an error.
+// Instead, they are replaced by the Unicode replacement
+// character U+FFFD.
+//
 func Unmarshal(data []byte, v interface{}) error {
-	d := new(decodeState).init(data)
-
-	// Quick check for well-formedness.
+	// Check for well-formedness.
 	// Avoids filling out half a data structure
 	// before discovering a JSON syntax error.
+	var d decodeState
 	err := checkValid(data, &d.scan)
 	if err != nil {
 		return err
 	}
 
+	d.init(data)
 	return d.unmarshal(v)
 }
 
 // Unmarshaler is the interface implemented by objects
 // that can unmarshal a JSON description of themselves.
-// The input can be assumed to be a valid JSON object
-// encoding.  UnmarshalJSON must copy the JSON data
+// The input can be assumed to be a valid encoding of
+// a JSON value. UnmarshalJSON must copy the JSON data
 // if it wishes to retain the data after returning.
 type Unmarshaler interface {
 	UnmarshalJSON([]byte) error
@@ -87,6 +96,7 @@ func (e *UnmarshalTypeError) Error() string {
 
 // An UnmarshalFieldError describes a JSON object key that
 // led to an unexported (and therefore unwritable) struct field.
+// (No longer used; kept for compatibility.)
 type UnmarshalFieldError struct {
 	Key   string
 	Type  reflect.Type
@@ -125,18 +135,33 @@ func (d *decodeState) unmarshal(v interface{}) (err error) {
 	}()
 
 	rv := reflect.ValueOf(v)
-	pv := rv
-	if pv.Kind() != reflect.Ptr || pv.IsNil() {
+	if rv.Kind() != reflect.Ptr || rv.IsNil() {
 		return &InvalidUnmarshalError{reflect.TypeOf(v)}
 	}
 
 	d.scan.reset()
-	// We decode rv not pv.Elem because the Unmarshaler interface
+	// We decode rv not rv.Elem because the Unmarshaler interface
 	// test must be applied at the top level of the value.
 	d.value(rv)
 	return d.savedError
 }
 
+// A Number represents a JSON number literal.
+type Number string
+
+// String returns the literal text of the number.
+func (n Number) String() string { return string(n) }
+
+// Float64 returns the number as a float64.
+func (n Number) Float64() (float64, error) {
+	return strconv.ParseFloat(string(n), 64)
+}
+
+// Int64 returns the number as an int64.
+func (n Number) Int64() (int64, error) {
+	return strconv.ParseInt(string(n), 10, 64)
+}
+
 // decodeState represents the state while decoding a JSON value.
 type decodeState struct {
 	data       []byte
@@ -145,6 +170,7 @@ type decodeState struct {
 	nextscan   scanner // for calls to nextValue
 	savedError error
 	tempstr    string // scratch space to avoid some allocations
+	useNumber  bool
 }
 
 // errPhase is used for errors that should not happen unless
@@ -265,47 +291,32 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler,
 		v = v.Addr()
 	}
 	for {
-		var isUnmarshaler bool
-		if v.Type().NumMethod() > 0 {
-			// Remember that this is an unmarshaler,
-			// but wait to return it until after allocating
-			// the pointer (if necessary).
-			_, isUnmarshaler = v.Interface().(Unmarshaler)
-		}
-
 		// Load value from interface, but only if the result will be
 		// usefully addressable.
-		if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() {
-			e := iv.Elem()
+		if v.Kind() == reflect.Interface && !v.IsNil() {
+			e := v.Elem()
 			if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
 				v = e
 				continue
 			}
 		}
 
-		pv := v
-		if pv.Kind() != reflect.Ptr {
+		if v.Kind() != reflect.Ptr {
 			break
 		}
 
-		if pv.Elem().Kind() != reflect.Ptr && decodingNull && pv.CanSet() {
-			return nil, pv
+		if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
+			break
 		}
-		if pv.IsNil() {
-			pv.Set(reflect.New(pv.Type().Elem()))
+		if v.IsNil() {
+			v.Set(reflect.New(v.Type().Elem()))
 		}
-		if isUnmarshaler {
-			// Using v.Interface().(Unmarshaler)
-			// here means that we have to use a pointer
-			// as the struct field.  We cannot use a value inside
-			// a pointer to a struct, because in that case
-			// v.Interface() is the value (x.f) not the pointer (&x.f).
-			// This is an unfortunate consequence of reflect.
-			// An alternative would be to look up the
-			// UnmarshalJSON method and return a FuncValue.
-			return v.Interface().(Unmarshaler), reflect.Value{}
+		if v.Type().NumMethod() > 0 {
+			if unmarshaler, ok := v.Interface().(Unmarshaler); ok {
+				return unmarshaler, reflect.Value{}
+			}
 		}
-		v = pv.Elem()
+		v = v.Elem()
 	}
 	return nil, v
 }
@@ -327,15 +338,19 @@ func (d *decodeState) array(v reflect.Value) {
 
 	// Check type of target.
 	switch v.Kind() {
+	case reflect.Interface:
+		if v.NumMethod() == 0 {
+			// Decoding into nil interface?  Switch to non-reflect code.
+			v.Set(reflect.ValueOf(d.arrayInterface()))
+			return
+		}
+		// Otherwise it's invalid.
+		fallthrough
 	default:
 		d.saveError(&UnmarshalTypeError{"array", v.Type()})
 		d.off--
 		d.next()
 		return
-	case reflect.Interface:
-		// Decoding into nil interface?  Switch to non-reflect code.
-		v.Set(reflect.ValueOf(d.arrayInterface()))
-		return
 	case reflect.Array:
 	case reflect.Slice:
 		break
@@ -421,36 +436,27 @@ func (d *decodeState) object(v reflect.Value) {
 	v = pv
 
 	// Decoding into nil interface?  Switch to non-reflect code.
-	iv := v
-	if iv.Kind() == reflect.Interface {
-		iv.Set(reflect.ValueOf(d.objectInterface()))
+	if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
+		v.Set(reflect.ValueOf(d.objectInterface()))
 		return
 	}
 
 	// Check type of target: struct or map[string]T
-	var (
-		mv reflect.Value
-		sv reflect.Value
-	)
 	switch v.Kind() {
 	case reflect.Map:
-		// map must have string type
+		// map must have string kind
 		t := v.Type()
-		if t.Key() != reflect.TypeOf("") {
+		if t.Key().Kind() != reflect.String {
 			d.saveError(&UnmarshalTypeError{"object", v.Type()})
 			break
 		}
-		mv = v
-		if mv.IsNil() {
-			mv.Set(reflect.MakeMap(t))
+		if v.IsNil() {
+			v.Set(reflect.MakeMap(t))
 		}
 	case reflect.Struct:
-		sv = v
+
 	default:
 		d.saveError(&UnmarshalTypeError{"object", v.Type()})
-	}
-
-	if !mv.IsValid() && !sv.IsValid() {
 		d.off--
 		d.next() // skip over { } in input
 		return
@@ -482,8 +488,8 @@ func (d *decodeState) object(v reflect.Value) {
 		var subv reflect.Value
 		destring := false // whether the value is wrapped in a string to be decoded first
 
-		if mv.IsValid() {
-			elemType := mv.Type().Elem()
+		if v.Kind() == reflect.Map {
+			elemType := v.Type().Elem()
 			if !mapElem.IsValid() {
 				mapElem = reflect.New(elemType).Elem()
 			} else {
@@ -491,51 +497,30 @@ func (d *decodeState) object(v reflect.Value) {
 			}
 			subv = mapElem
 		} else {
-			var f reflect.StructField
-			var ok bool
-			st := sv.Type()
-			for i := 0; i < sv.NumField(); i++ {
-				sf := st.Field(i)
-				tag := sf.Tag.Get("json")
-				if tag == "-" {
-					// Pretend this field doesn't exist.
-					continue
-				}
-				if sf.Anonymous {
-					// Pretend this field doesn't exist,
-					// so that we can do a good job with
-					// these in a later version.
-					continue
-				}
-				// First, tag match
-				tagName, _ := parseTag(tag)
-				if tagName == key {
-					f = sf
-					ok = true
-					break // no better match possible
-				}
-				// Second, exact field name match
-				if sf.Name == key {
-					f = sf
-					ok = true
+			var f *field
+			fields := cachedTypeFields(v.Type())
+			for i := range fields {
+				ff := &fields[i]
+				if ff.name == key {
+					f = ff
+					break
 				}
-				// Third, case-insensitive field name match,
-				// but only if a better match hasn't already been seen
-				if !ok && strings.EqualFold(sf.Name, key) {
-					f = sf
-					ok = true
+				if f == nil && strings.EqualFold(ff.name, key) {
+					f = ff
 				}
 			}
-
-			// Extract value; name must be exported.
-			if ok {
-				if f.PkgPath != "" {
-					d.saveError(&UnmarshalFieldError{key, st, f})
-				} else {
-					subv = sv.FieldByIndex(f.Index)
+			if f != nil {
+				subv = v
+				destring = f.quoted
+				for _, i := range f.index {
+					if subv.Kind() == reflect.Ptr {
+						if subv.IsNil() {
+							subv.Set(reflect.New(subv.Type().Elem()))
+						}
+						subv = subv.Elem()
+					}
+					subv = subv.Field(i)
 				}
-				_, opts := parseTag(f.Tag.Get("json"))
-				destring = opts.Contains("string")
 			}
 		}
 
@@ -554,10 +539,12 @@ func (d *decodeState) object(v reflect.Value) {
 		} else {
 			d.value(subv)
 		}
+
 		// Write value back to map;
 		// if using struct, subv points into struct already.
-		if mv.IsValid() {
-			mv.SetMapIndex(reflect.ValueOf(key), subv)
+		if v.Kind() == reflect.Map {
+			kv := reflect.ValueOf(key).Convert(v.Type().Key())
+			v.SetMapIndex(kv, subv)
 		}
 
 		// Next token must be , or }.
@@ -586,6 +573,21 @@ func (d *decodeState) literal(v reflect.Value) {
 	d.literalStore(d.data[start:d.off], v, false)
 }
 
+// convertNumber converts the number literal s to a float64 or a Number
+// depending on the setting of d.useNumber.
+func (d *decodeState) convertNumber(s string) (interface{}, error) {
+	if d.useNumber {
+		return Number(s), nil
+	}
+	f, err := strconv.ParseFloat(s, 64)
+	if err != nil {
+		return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0)}
+	}
+	return f, nil
+}
+
+var numberType = reflect.TypeOf(Number(""))
+
 // literalStore decodes a literal stored in item into v.
 //
 // fromQuoted indicates whether this literal came from unwrapping a
@@ -612,12 +614,10 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
 	switch c := item[0]; c {
 	case 'n': // null
 		switch v.Kind() {
-		default:
-			d.saveError(&UnmarshalTypeError{"null", v.Type()})
 		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
 			v.Set(reflect.Zero(v.Type()))
+			// otherwise, ignore null for primitives/string
 		}
-
 	case 't', 'f': // true, false
 		value := c == 't'
 		switch v.Kind() {
@@ -630,7 +630,11 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
 		case reflect.Bool:
 			v.SetBool(value)
 		case reflect.Interface:
-			v.Set(reflect.ValueOf(value))
+			if v.NumMethod() == 0 {
+				v.Set(reflect.ValueOf(value))
+			} else {
+				d.saveError(&UnmarshalTypeError{"bool", v.Type()})
+			}
 		}
 
 	case '"': // string
@@ -660,7 +664,11 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
 		case reflect.String:
 			v.SetString(string(s))
 		case reflect.Interface:
-			v.Set(reflect.ValueOf(string(s)))
+			if v.NumMethod() == 0 {
+				v.Set(reflect.ValueOf(string(s)))
+			} else {
+				d.saveError(&UnmarshalTypeError{"string", v.Type()})
+			}
 		}
 
 	default: // number
@@ -674,15 +682,23 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
 		s := string(item)
 		switch v.Kind() {
 		default:
+			if v.Kind() == reflect.String && v.Type() == numberType {
+				v.SetString(s)
+				break
+			}
 			if fromQuoted {
 				d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
 			} else {
 				d.error(&UnmarshalTypeError{"number", v.Type()})
 			}
 		case reflect.Interface:
-			n, err := strconv.ParseFloat(s, 64)
+			n, err := d.convertNumber(s)
 			if err != nil {
-				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+				d.saveError(err)
+				break
+			}
+			if v.NumMethod() != 0 {
+				d.saveError(&UnmarshalTypeError{"number", v.Type()})
 				break
 			}
 			v.Set(reflect.ValueOf(n))
@@ -735,7 +751,7 @@ func (d *decodeState) valueInterface() interface{} {
 
 // arrayInterface is like array but returns []interface{}.
 func (d *decodeState) arrayInterface() []interface{} {
-	var v []interface{}
+	var v = make([]interface{}, 0)
 	for {
 		// Look ahead for ] - can only happen on first iteration.
 		op := d.scanWhile(scanSkipSpace)
@@ -836,9 +852,9 @@ func (d *decodeState) literalInterface() interface{} {
 		if c != '-' && (c < '0' || c > '9') {
 			d.error(errPhase)
 		}
-		n, err := strconv.ParseFloat(string(item), 64)
+		n, err := d.convertNumber(string(item))
 		if err != nil {
-			d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)})
+			d.saveError(err)
 		}
 		return n
 	}
@@ -979,11 +995,3 @@ func unquoteBytes(s []byte) (t []byte, ok bool) {
 	}
 	return b[0:w], true
 }
-
-// The following is issue 3069.
-
-// BUG(rsc): This package ignores anonymous (embedded) struct fields
-// during encoding and decoding.  A future version may assign meaning
-// to them.  To force an anonymous field to be ignored in all future
-// versions of this package, use an explicit `json:"-"` tag in the struct
-// definition.
diff --git a/src/pkg/encoding/json/decode_test.go b/src/pkg/encoding/json/decode_test.go
index 6fac22c..e1bd918 100644
--- a/src/pkg/encoding/json/decode_test.go
+++ b/src/pkg/encoding/json/decode_test.go
@@ -7,9 +7,11 @@ package json
 import (
 	"bytes"
 	"fmt"
+	"image"
 	"reflect"
 	"strings"
 	"testing"
+	"time"
 )
 
 type T struct {
@@ -18,6 +20,32 @@ type T struct {
 	Z int `json:"-"`
 }
 
+type U struct {
+	Alphabet string `json:"alpha"`
+}
+
+type V struct {
+	F1 interface{}
+	F2 int32
+	F3 Number
+}
+
+// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshalling with and
+// without UseNumber
+var ifaceNumAsFloat64 = map[string]interface{}{
+	"k1": float64(1),
+	"k2": "s",
+	"k3": []interface{}{float64(1), float64(2.0), float64(3e-3)},
+	"k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)},
+}
+
+var ifaceNumAsNumber = map[string]interface{}{
+	"k1": Number("1"),
+	"k2": "s",
+	"k3": []interface{}{Number("1"), Number("2.0"), Number("3e-3")},
+	"k4": map[string]interface{}{"kk1": "s", "kk2": Number("2")},
+}
+
 type tx struct {
 	x int
 }
@@ -48,55 +76,297 @@ var (
 	umstruct = ustruct{unmarshaler{true}}
 )
 
+// Test data structures for anonymous fields.
+
+type Point struct {
+	Z int
+}
+
+type Top struct {
+	Level0 int
+	Embed0
+	*Embed0a
+	*Embed0b `json:"e,omitempty"` // treated as named
+	Embed0c  `json:"-"`           // ignored
+	Loop
+	Embed0p // has Point with X, Y, used
+	Embed0q // has Point with Z, used
+}
+
+type Embed0 struct {
+	Level1a int // overridden by Embed0a's Level1a with json tag
+	Level1b int // used because Embed0a's Level1b is renamed
+	Level1c int // used because Embed0a's Level1c is ignored
+	Level1d int // annihilated by Embed0a's Level1d
+	Level1e int `json:"x"` // annihilated by Embed0a.Level1e
+}
+
+type Embed0a struct {
+	Level1a int `json:"Level1a,omitempty"`
+	Level1b int `json:"LEVEL1B,omitempty"`
+	Level1c int `json:"-"`
+	Level1d int // annihilated by Embed0's Level1d
+	Level1f int `json:"x"` // annihilated by Embed0's Level1e
+}
+
+type Embed0b Embed0
+
+type Embed0c Embed0
+
+type Embed0p struct {
+	image.Point
+}
+
+type Embed0q struct {
+	Point
+}
+
+type Loop struct {
+	Loop1 int `json:",omitempty"`
+	Loop2 int `json:",omitempty"`
+	*Loop
+}
+
+// From reflect test:
+// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
+type S5 struct {
+	S6
+	S7
+	S8
+}
+
+type S6 struct {
+	X int
+}
+
+type S7 S6
+
+type S8 struct {
+	S9
+}
+
+type S9 struct {
+	X int
+	Y int
+}
+
+// From reflect test:
+// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
+type S10 struct {
+	S11
+	S12
+	S13
+}
+
+type S11 struct {
+	S6
+}
+
+type S12 struct {
+	S6
+}
+
+type S13 struct {
+	S8
+}
+
 type unmarshalTest struct {
-	in  string
-	ptr interface{}
-	out interface{}
-	err error
+	in        string
+	ptr       interface{}
+	out       interface{}
+	err       error
+	useNumber bool
+}
+
+type Ambig struct {
+	// Given "hello", the first match should win.
+	First  int `json:"HELLO"`
+	Second int `json:"Hello"`
 }
 
 var unmarshalTests = []unmarshalTest{
 	// basic types
-	{`true`, new(bool), true, nil},
-	{`1`, new(int), 1, nil},
-	{`1.2`, new(float64), 1.2, nil},
-	{`-5`, new(int16), int16(-5), nil},
-	{`"a\u1234"`, new(string), "a\u1234", nil},
-	{`"http:\/\/"`, new(string), "http://", nil},
-	{`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil},
-	{`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
-	{"null", new(interface{}), nil, nil},
-	{`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}},
-	{`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
+	{in: `true`, ptr: new(bool), out: true},
+	{in: `1`, ptr: new(int), out: 1},
+	{in: `1.2`, ptr: new(float64), out: 1.2},
+	{in: `-5`, ptr: new(int16), out: int16(-5)},
+	{in: `2`, ptr: new(Number), out: Number("2"), useNumber: true},
+	{in: `2`, ptr: new(Number), out: Number("2")},
+	{in: `2`, ptr: new(interface{}), out: float64(2.0)},
+	{in: `2`, ptr: new(interface{}), out: Number("2"), useNumber: true},
+	{in: `"a\u1234"`, ptr: new(string), out: "a\u1234"},
+	{in: `"http:\/\/"`, ptr: new(string), out: "http://"},
+	{in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
+	{in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
+	{in: "null", ptr: new(interface{}), out: nil},
+	{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf("")}},
+	{in: `{"x": 1}`, ptr: new(tx), out: tx{}},
+	{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
+	{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
+	{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64},
+	{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true},
+
+	// raw values with whitespace
+	{in: "\n true ", ptr: new(bool), out: true},
+	{in: "\t 1 ", ptr: new(int), out: 1},
+	{in: "\r 1.2 ", ptr: new(float64), out: 1.2},
+	{in: "\t -5 \n", ptr: new(int16), out: int16(-5)},
+	{in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"},
 
 	// Z has a "-" tag.
-	{`{"Y": 1, "Z": 2}`, new(T), T{Y: 1}, nil},
+	{in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}},
+
+	{in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}},
+	{in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}},
+	{in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}},
 
 	// syntax errors
-	{`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
-	{`[1, 2, 3+]`, nil, nil, &SyntaxError{"invalid character '+' after array element", 9}},
+	{in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}},
+	{in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
+	{in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true},
+
+	// raw value errors
+	{in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
+	{in: " 42 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 5}},
+	{in: "\x01 true", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
+	{in: " false \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 8}},
+	{in: "\x01 1.2", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
+	{in: " 3.4 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 6}},
+	{in: "\x01 \"string\"", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
+	{in: " \"string\" \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 11}},
 
 	// array tests
-	{`[1, 2, 3]`, new([3]int), [3]int{1, 2, 3}, nil},
-	{`[1, 2, 3]`, new([1]int), [1]int{1}, nil},
-	{`[1, 2, 3]`, new([5]int), [5]int{1, 2, 3, 0, 0}, nil},
+	{in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
+	{in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
+	{in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
+
+	// empty array to interface test
+	{in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
+	{in: `null`, ptr: new([]interface{}), out: []interface{}(nil)},
+	{in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}},
+	{in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}},
 
 	// composite tests
-	{allValueIndent, new(All), allValue, nil},
-	{allValueCompact, new(All), allValue, nil},
-	{allValueIndent, new(*All), &allValue, nil},
-	{allValueCompact, new(*All), &allValue, nil},
-	{pallValueIndent, new(All), pallValue, nil},
-	{pallValueCompact, new(All), pallValue, nil},
-	{pallValueIndent, new(*All), &pallValue, nil},
-	{pallValueCompact, new(*All), &pallValue, nil},
+	{in: allValueIndent, ptr: new(All), out: allValue},
+	{in: allValueCompact, ptr: new(All), out: allValue},
+	{in: allValueIndent, ptr: new(*All), out: &allValue},
+	{in: allValueCompact, ptr: new(*All), out: &allValue},
+	{in: pallValueIndent, ptr: new(All), out: pallValue},
+	{in: pallValueCompact, ptr: new(All), out: pallValue},
+	{in: pallValueIndent, ptr: new(*All), out: &pallValue},
+	{in: pallValueCompact, ptr: new(*All), out: &pallValue},
 
 	// unmarshal interface test
-	{`{"T":false}`, &um0, umtrue, nil}, // use "false" so test will fail if custom unmarshaler is not called
-	{`{"T":false}`, &ump, &umtrue, nil},
-	{`[{"T":false}]`, &umslice, umslice, nil},
-	{`[{"T":false}]`, &umslicep, &umslice, nil},
-	{`{"M":{"T":false}}`, &umstruct, umstruct, nil},
+	{in: `{"T":false}`, ptr: &um0, out: umtrue}, // use "false" so test will fail if custom unmarshaler is not called
+	{in: `{"T":false}`, ptr: &ump, out: &umtrue},
+	{in: `[{"T":false}]`, ptr: &umslice, out: umslice},
+	{in: `[{"T":false}]`, ptr: &umslicep, out: &umslice},
+	{in: `{"M":{"T":false}}`, ptr: &umstruct, out: umstruct},
+
+	{
+		in: `{
+			"Level0": 1,
+			"Level1b": 2,
+			"Level1c": 3,
+			"x": 4,
+			"Level1a": 5,
+			"LEVEL1B": 6,
+			"e": {
+				"Level1a": 8,
+				"Level1b": 9,
+				"Level1c": 10,
+				"Level1d": 11,
+				"x": 12
+			},
+			"Loop1": 13,
+			"Loop2": 14,
+			"X": 15,
+			"Y": 16,
+			"Z": 17
+		}`,
+		ptr: new(Top),
+		out: Top{
+			Level0: 1,
+			Embed0: Embed0{
+				Level1b: 2,
+				Level1c: 3,
+			},
+			Embed0a: &Embed0a{
+				Level1a: 5,
+				Level1b: 6,
+			},
+			Embed0b: &Embed0b{
+				Level1a: 8,
+				Level1b: 9,
+				Level1c: 10,
+				Level1d: 11,
+				Level1e: 12,
+			},
+			Loop: Loop{
+				Loop1: 13,
+				Loop2: 14,
+			},
+			Embed0p: Embed0p{
+				Point: image.Point{X: 15, Y: 16},
+			},
+			Embed0q: Embed0q{
+				Point: Point{Z: 17},
+			},
+		},
+	},
+	{
+		in:  `{"hello": 1}`,
+		ptr: new(Ambig),
+		out: Ambig{First: 1},
+	},
+
+	{
+		in:  `{"X": 1,"Y":2}`,
+		ptr: new(S5),
+		out: S5{S8: S8{S9: S9{Y: 2}}},
+	},
+	{
+		in:  `{"X": 1,"Y":2}`,
+		ptr: new(S10),
+		out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}},
+	},
+
+	// invalid UTF-8 is coerced to valid UTF-8.
+	{
+		in:  "\"hello\xffworld\"",
+		ptr: new(string),
+		out: "hello\ufffdworld",
+	},
+	{
+		in:  "\"hello\xc2\xc2world\"",
+		ptr: new(string),
+		out: "hello\ufffd\ufffdworld",
+	},
+	{
+		in:  "\"hello\xc2\xffworld\"",
+		ptr: new(string),
+		out: "hello\ufffd\ufffdworld",
+	},
+	{
+		in:  "\"hello\\ud800world\"",
+		ptr: new(string),
+		out: "hello\ufffdworld",
+	},
+	{
+		in:  "\"hello\\ud800\\ud800world\"",
+		ptr: new(string),
+		out: "hello\ufffd\ufffdworld",
+	},
+	{
+		in:  "\"hello\\ud800\\ud800world\"",
+		ptr: new(string),
+		out: "hello\ufffd\ufffdworld",
+	},
+	{
+		in:  "\"hello\xed\xa0\x80\xed\xb0\x80world\"",
+		ptr: new(string),
+		out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld",
+	},
 }
 
 func TestMarshal(t *testing.T) {
@@ -135,6 +405,18 @@ func TestMarshalBadUTF8(t *testing.T) {
 	}
 }
 
+func TestMarshalNumberZeroVal(t *testing.T) {
+	var n Number
+	out, err := Marshal(n)
+	if err != nil {
+		t.Fatal(err)
+	}
+	outStr := string(out)
+	if outStr != "0" {
+		t.Fatalf("Invalid zero val for Number: %q", outStr)
+	}
+}
+
 func TestUnmarshal(t *testing.T) {
 	for i, tt := range unmarshalTests {
 		var scan scanner
@@ -150,7 +432,11 @@ func TestUnmarshal(t *testing.T) {
 		}
 		// v = new(right-type)
 		v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
-		if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
+		dec := NewDecoder(bytes.NewBuffer(in))
+		if tt.useNumber {
+			dec.UseNumber()
+		}
+		if err := dec.Decode(v.Interface()); !reflect.DeepEqual(err, tt.err) {
 			t.Errorf("#%d: %v want %v", i, err, tt.err)
 			continue
 		}
@@ -162,6 +448,28 @@ func TestUnmarshal(t *testing.T) {
 			println(string(data))
 			continue
 		}
+
+		// Check round trip.
+		if tt.err == nil {
+			enc, err := Marshal(v.Interface())
+			if err != nil {
+				t.Errorf("#%d: error re-marshaling: %v", i, err)
+				continue
+			}
+			vv := reflect.New(reflect.TypeOf(tt.ptr).Elem())
+			dec = NewDecoder(bytes.NewBuffer(enc))
+			if tt.useNumber {
+				dec.UseNumber()
+			}
+			if err := dec.Decode(vv.Interface()); err != nil {
+				t.Errorf("#%d: error re-unmarshaling: %v", i, err)
+				continue
+			}
+			if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) {
+				t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface())
+				continue
+			}
+		}
 	}
 }
 
@@ -175,13 +483,45 @@ func TestUnmarshalMarshal(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Marshal: %v", err)
 	}
-	if bytes.Compare(jsonBig, b) != 0 {
+	if !bytes.Equal(jsonBig, b) {
 		t.Errorf("Marshal jsonBig")
 		diff(t, b, jsonBig)
 		return
 	}
 }
 
+var numberTests = []struct {
+	in       string
+	i        int64
+	intErr   string
+	f        float64
+	floatErr string
+}{
+	{in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1},
+	{in: "-12", i: -12, f: -12.0},
+	{in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"},
+}
+
+// Independent of Decode, basic coverage of the accessors in Number
+func TestNumberAccessors(t *testing.T) {
+	for _, tt := range numberTests {
+		n := Number(tt.in)
+		if s := n.String(); s != tt.in {
+			t.Errorf("Number(%q).String() is %q", tt.in, s)
+		}
+		if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i {
+			t.Errorf("Number(%q).Int64() is %d", tt.in, i)
+		} else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) {
+			t.Errorf("Number(%q).Int64() wanted error %q but got: %v", tt.in, tt.intErr, err)
+		}
+		if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f {
+			t.Errorf("Number(%q).Float64() is %g", tt.in, f)
+		} else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) {
+			t.Errorf("Number(%q).Float64() wanted error %q but got: %v", tt.in, tt.floatErr, err)
+		}
+	}
+}
+
 func TestLargeByteSlice(t *testing.T) {
 	s0 := make([]byte, 2000)
 	for i := range s0 {
@@ -195,7 +535,7 @@ func TestLargeByteSlice(t *testing.T) {
 	if err := Unmarshal(b, &s1); err != nil {
 		t.Fatalf("Unmarshal: %v", err)
 	}
-	if bytes.Compare(s0, s1) != 0 {
+	if !bytes.Equal(s0, s1) {
 		t.Errorf("Marshal large byte slice")
 		diff(t, s0, s1)
 	}
@@ -610,35 +950,6 @@ func TestRefUnmarshal(t *testing.T) {
 	}
 }
 
-// Test that anonymous fields are ignored.
-// We may assign meaning to them later.
-func TestAnonymous(t *testing.T) {
-	type S struct {
-		T
-		N int
-	}
-
-	data, err := Marshal(new(S))
-	if err != nil {
-		t.Fatalf("Marshal: %v", err)
-	}
-	want := `{"N":0}`
-	if string(data) != want {
-		t.Fatalf("Marshal = %#q, want %#q", string(data), want)
-	}
-
-	var s S
-	if err := Unmarshal([]byte(`{"T": 1, "T": {"Y": 1}, "N": 2}`), &s); err != nil {
-		t.Fatalf("Unmarshal: %v", err)
-	}
-	if s.N != 2 {
-		t.Fatal("Unmarshal: did not set N")
-	}
-	if s.T.Y != 0 {
-		t.Fatal("Unmarshal: did set T.Y")
-	}
-}
-
 // Test that the empty string doesn't panic decoding when ,string is specified
 // Issue 3450
 func TestEmptyString(t *testing.T) {
@@ -703,3 +1014,167 @@ func TestInterfaceSet(t *testing.T) {
 		}
 	}
 }
+
+// JSON null values should be ignored for primitives and string values instead of resulting in an error.
+// Issue 2540
+func TestUnmarshalNulls(t *testing.T) {
+	jsonData := []byte(`{
+		"Bool"    : null, 
+		"Int"     : null, 
+		"Int8"    : null,
+		"Int16"   : null,
+		"Int32"   : null,
+		"Int64"   : null,
+		"Uint"    : null,
+		"Uint8"   : null,
+		"Uint16"  : null,
+		"Uint32"  : null,
+		"Uint64"  : null,
+		"Float32" : null,
+		"Float64" : null,
+		"String"  : null}`)
+
+	nulls := All{
+		Bool:    true,
+		Int:     2,
+		Int8:    3,
+		Int16:   4,
+		Int32:   5,
+		Int64:   6,
+		Uint:    7,
+		Uint8:   8,
+		Uint16:  9,
+		Uint32:  10,
+		Uint64:  11,
+		Float32: 12.1,
+		Float64: 13.1,
+		String:  "14"}
+
+	err := Unmarshal(jsonData, &nulls)
+	if err != nil {
+		t.Errorf("Unmarshal of null values failed: %v", err)
+	}
+	if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 ||
+		nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 ||
+		nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" {
+
+		t.Errorf("Unmarshal of null values affected primitives")
+	}
+}
+
+func TestStringKind(t *testing.T) {
+	type stringKind string
+	type aMap map[stringKind]int
+
+	var m1, m2 map[stringKind]int
+	m1 = map[stringKind]int{
+		"foo": 42,
+	}
+
+	data, err := Marshal(m1)
+	if err != nil {
+		t.Errorf("Unexpected error marshalling: %v", err)
+	}
+
+	err = Unmarshal(data, &m2)
+	if err != nil {
+		t.Errorf("Unexpected error unmarshalling: %v", err)
+	}
+
+	if !reflect.DeepEqual(m1, m2) {
+		t.Error("Items should be equal after encoding and then decoding")
+	}
+
+}
+
+var decodeTypeErrorTests = []struct {
+	dest interface{}
+	src  string
+}{
+	{new(string), `{"user": "name"}`}, // issue 4628.
+	{new(error), `{}`},                // issue 4222
+	{new(error), `[]`},
+	{new(error), `""`},
+	{new(error), `123`},
+	{new(error), `true`},
+}
+
+func TestUnmarshalTypeError(t *testing.T) {
+	for _, item := range decodeTypeErrorTests {
+		err := Unmarshal([]byte(item.src), item.dest)
+		if _, ok := err.(*UnmarshalTypeError); !ok {
+			t.Errorf("expected type error for Unmarshal(%q, type %T): got %T",
+				item.src, item.dest, err)
+		}
+	}
+}
+
+var unmarshalSyntaxTests = []string{
+	"tru",
+	"fals",
+	"nul",
+	"123e",
+	`"hello`,
+	`[1,2,3`,
+	`{"key":1`,
+	`{"key":1,`,
+}
+
+func TestUnmarshalSyntax(t *testing.T) {
+	var x interface{}
+	for _, src := range unmarshalSyntaxTests {
+		err := Unmarshal([]byte(src), &x)
+		if _, ok := err.(*SyntaxError); !ok {
+			t.Errorf("expected syntax error for Unmarshal(%q): got %T", src, err)
+		}
+	}
+}
+
+// Test handling of unexported fields that should be ignored.
+// Issue 4660
+type unexportedFields struct {
+	Name string
+	m    map[string]interface{} `json:"-"`
+	m2   map[string]interface{} `json:"abcd"`
+}
+
+func TestUnmarshalUnexported(t *testing.T) {
+	input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}}`
+	want := &unexportedFields{Name: "Bob"}
+
+	out := &unexportedFields{}
+	err := Unmarshal([]byte(input), out)
+	if err != nil {
+		t.Errorf("got error %v, expected nil", err)
+	}
+	if !reflect.DeepEqual(out, want) {
+		t.Errorf("got %q, want %q", out, want)
+	}
+}
+
+// Time3339 is a time.Time which encodes to and from JSON
+// as an RFC 3339 time in UTC.
+type Time3339 time.Time
+
+func (t *Time3339) UnmarshalJSON(b []byte) error {
+	if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
+		return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b)
+	}
+	tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1]))
+	if err != nil {
+		return err
+	}
+	*t = Time3339(tm)
+	return nil
+}
+
+func TestUnmarshalJSONLiteralError(t *testing.T) {
+	var t3 Time3339
+	err := Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3)
+	if err == nil {
+		t.Fatalf("expected error; got time %v", time.Time(t3))
+	}
+	if !strings.Contains(err.Error(), "range") {
+		t.Errorf("got err = %v; want out of range error", err)
+	}
+}
diff --git a/src/pkg/encoding/json/encode.go b/src/pkg/encoding/json/encode.go
index b6e1cb1..fb57f1d 100644
--- a/src/pkg/encoding/json/encode.go
+++ b/src/pkg/encoding/json/encode.go
@@ -36,7 +36,7 @@ import (
 //
 // Boolean values encode as JSON booleans.
 //
-// Floating point and integer values encode as JSON numbers.
+// Floating point, integer, and Number values encode as JSON numbers.
 //
 // String values encode as JSON strings, with each invalid UTF-8 sequence
 // replaced by the encoding of the Unicode replacement character U+FFFD.
@@ -55,7 +55,7 @@ import (
 // nil pointer or interface value, and any array, slice, map, or string of
 // length zero. The object's default key string is the struct field name
 // but can be specified in the struct field's tag value. The "json" key in
-// struct field's tag value is the key name, followed by an optional comma
+// the struct field's tag value is the key name, followed by an optional comma
 // and options. Examples:
 //
 //   // Field is ignored by this package.
@@ -75,8 +75,9 @@ import (
 //   Field int `json:",omitempty"`
 //
 // The "string" option signals that a field is stored as JSON inside a
-// JSON-encoded string.  This extra level of encoding is sometimes
-// used when communicating with JavaScript programs:
+// JSON-encoded string. It applies only to fields of string, floating point,
+// or integer types. This extra level of encoding is sometimes used when
+// communicating with JavaScript programs:
 //
 //    Int64String int64 `json:",string"`
 //
@@ -84,6 +85,16 @@ import (
 // only Unicode letters, digits, dollar signs, percent signs, hyphens,
 // underscores and slashes.
 //
+// Anonymous struct fields are usually marshaled as if their inner exported fields
+// were fields in the outer struct, subject to the usual Go visibility rules.
+// An anonymous struct field with a name given in its JSON tag is treated as
+// having that name instead of as anonymous.
+//
+// Handling of anonymous struct fields is new in Go 1.1.
+// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
+// an anonymous struct field in both current and earlier versions, give the field
+// a JSON tag of "-".
+//
 // Map values encode as JSON objects.
 // The map's key type must be string; the object keys are used directly
 // as map keys.
@@ -312,6 +323,14 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
 			e.Write(b)
 		}
 	case reflect.String:
+		if v.Type() == numberType {
+			numStr := v.String()
+			if numStr == "" {
+				numStr = "0" // Number's zero-val
+			}
+			e.WriteString(numStr)
+			break
+		}
 		if quoted {
 			sb, err := Marshal(v.String())
 			if err != nil {
@@ -325,9 +344,9 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
 	case reflect.Struct:
 		e.WriteByte('{')
 		first := true
-		for _, ef := range encodeFields(v.Type()) {
-			fieldValue := v.Field(ef.i)
-			if ef.omitEmpty && isEmptyValue(fieldValue) {
+		for _, f := range cachedTypeFields(v.Type()) {
+			fv := fieldByIndex(v, f.index)
+			if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
 				continue
 			}
 			if first {
@@ -335,9 +354,9 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
 			} else {
 				e.WriteByte(',')
 			}
-			e.string(ef.tag)
+			e.string(f.name)
 			e.WriteByte(':')
-			e.reflectValueQuoted(fieldValue, ef.quoted)
+			e.reflectValueQuoted(fv, f.quoted)
 		}
 		e.WriteByte('}')
 
@@ -419,7 +438,7 @@ func isValidTag(s string) bool {
 	}
 	for _, c := range s {
 		switch {
-		case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~", c):
+		case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
 			// Backslash and quote chars are reserved, but
 			// otherwise any punctuation chars are allowed
 			// in a tag name.
@@ -432,6 +451,19 @@ func isValidTag(s string) bool {
 	return true
 }
 
+func fieldByIndex(v reflect.Value, index []int) reflect.Value {
+	for _, i := range index {
+		if v.Kind() == reflect.Ptr {
+			if v.IsNil() {
+				return reflect.Value{}
+			}
+			v = v.Elem()
+		}
+		v = v.Field(i)
+	}
+	return v
+}
+
 // stringValues is a slice of reflect.Value holding *reflect.StringValue.
 // It implements the methods to sort by string.
 type stringValues []reflect.Value
@@ -490,67 +522,185 @@ func (e *encodeState) string(s string) (int, error) {
 	return e.Len() - len0, nil
 }
 
-// encodeField contains information about how to encode a field of a
-// struct.
-type encodeField struct {
-	i         int // field index in struct
-	tag       string
-	quoted    bool
+// A field represents a single field found in a struct.
+type field struct {
+	name      string
+	tag       bool
+	index     []int
+	typ       reflect.Type
 	omitEmpty bool
+	quoted    bool
 }
 
-var (
-	typeCacheLock     sync.RWMutex
-	encodeFieldsCache = make(map[reflect.Type][]encodeField)
-)
+// byName sorts field by name, breaking ties with depth,
+// then breaking ties with "name came from json tag", then
+// breaking ties with index sequence.
+type byName []field
 
-// encodeFields returns a slice of encodeField for a given
-// struct type.
-func encodeFields(t reflect.Type) []encodeField {
-	typeCacheLock.RLock()
-	fs, ok := encodeFieldsCache[t]
-	typeCacheLock.RUnlock()
-	if ok {
-		return fs
-	}
+func (x byName) Len() int { return len(x) }
+
+func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
 
-	typeCacheLock.Lock()
-	defer typeCacheLock.Unlock()
-	fs, ok = encodeFieldsCache[t]
-	if ok {
-		return fs
+func (x byName) Less(i, j int) bool {
+	if x[i].name != x[j].name {
+		return x[i].name < x[j].name
 	}
+	if len(x[i].index) != len(x[j].index) {
+		return len(x[i].index) < len(x[j].index)
+	}
+	if x[i].tag != x[j].tag {
+		return x[i].tag
+	}
+	return byIndex(x).Less(i, j)
+}
 
-	v := reflect.Zero(t)
-	n := v.NumField()
-	for i := 0; i < n; i++ {
-		f := t.Field(i)
-		if f.PkgPath != "" {
-			continue
+// byIndex sorts field by index sequence.
+type byIndex []field
+
+func (x byIndex) Len() int { return len(x) }
+
+func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+func (x byIndex) Less(i, j int) bool {
+	for k, xik := range x[i].index {
+		if k >= len(x[j].index) {
+			return false
 		}
-		if f.Anonymous {
-			// We want to do a better job with these later,
-			// so for now pretend they don't exist.
-			continue
+		if xik != x[j].index[k] {
+			return xik < x[j].index[k]
 		}
-		var ef encodeField
-		ef.i = i
-		ef.tag = f.Name
+	}
+	return len(x[i].index) < len(x[j].index)
+}
+
+// typeFields returns a list of fields that JSON should recognize for the given type.
+// The algorithm is breadth-first search over the set of structs to include - the top struct
+// and then any reachable anonymous structs.
+func typeFields(t reflect.Type) []field {
+	// Anonymous fields to explore at the current level and the next.
+	current := []field{}
+	next := []field{{typ: t}}
+
+	// Count of queued names for current level and the next.
+	count := map[reflect.Type]int{}
+	nextCount := map[reflect.Type]int{}
+
+	// Types already visited at an earlier level.
+	visited := map[reflect.Type]bool{}
+
+	// Fields found.
+	var fields []field
+
+	for len(next) > 0 {
+		current, next = next, current[:0]
+		count, nextCount = nextCount, map[reflect.Type]int{}
 
-		tv := f.Tag.Get("json")
-		if tv != "" {
-			if tv == "-" {
+		for _, f := range current {
+			if visited[f.typ] {
 				continue
 			}
-			name, opts := parseTag(tv)
-			if isValidTag(name) {
-				ef.tag = name
+			visited[f.typ] = true
+
+			// Scan f.typ for fields to include.
+			for i := 0; i < f.typ.NumField(); i++ {
+				sf := f.typ.Field(i)
+				if sf.PkgPath != "" { // unexported
+					continue
+				}
+				tag := sf.Tag.Get("json")
+				if tag == "-" {
+					continue
+				}
+				name, opts := parseTag(tag)
+				if !isValidTag(name) {
+					name = ""
+				}
+				index := make([]int, len(f.index)+1)
+				copy(index, f.index)
+				index[len(f.index)] = i
+
+				ft := sf.Type
+				if ft.Name() == "" && ft.Kind() == reflect.Ptr {
+					// Follow pointer.
+					ft = ft.Elem()
+				}
+
+				// Record found field and index sequence.
+				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
+					tagged := name != ""
+					if name == "" {
+						name = sf.Name
+					}
+					fields = append(fields, field{name, tagged, index, ft,
+						opts.Contains("omitempty"), opts.Contains("string")})
+					if count[f.typ] > 1 {
+						// If there were multiple instances, add a second,
+						// so that the annihilation code will see a duplicate.
+						// It only cares about the distinction between 1 or 2,
+						// so don't bother generating any more copies.
+						fields = append(fields, fields[len(fields)-1])
+					}
+					continue
+				}
+
+				// Record new anonymous struct to explore in next round.
+				nextCount[ft]++
+				if nextCount[ft] == 1 {
+					next = append(next, field{name: ft.Name(), index: index, typ: ft})
+				}
 			}
-			ef.omitEmpty = opts.Contains("omitempty")
-			ef.quoted = opts.Contains("string")
 		}
-		fs = append(fs, ef)
 	}
-	encodeFieldsCache[t] = fs
-	return fs
+
+	sort.Sort(byName(fields))
+
+	// Remove fields with annihilating name collisions
+	// and also fields shadowed by fields with explicit JSON tags.
+	name := ""
+	out := fields[:0]
+	for _, f := range fields {
+		if f.name != name {
+			name = f.name
+			out = append(out, f)
+			continue
+		}
+		if n := len(out); n > 0 && out[n-1].name == name && (!out[n-1].tag || f.tag) {
+			out = out[:n-1]
+		}
+	}
+	fields = out
+
+	sort.Sort(byIndex(fields))
+
+	return fields
+}
+
+var fieldCache struct {
+	sync.RWMutex
+	m map[reflect.Type][]field
+}
+
+// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
+func cachedTypeFields(t reflect.Type) []field {
+	fieldCache.RLock()
+	f := fieldCache.m[t]
+	fieldCache.RUnlock()
+	if f != nil {
+		return f
+	}
+
+	// Compute fields without lock.
+	// Might duplicate effort but won't hold other computations back.
+	f = typeFields(t)
+	if f == nil {
+		f = []field{}
+	}
+
+	fieldCache.Lock()
+	if fieldCache.m == nil {
+		fieldCache.m = map[reflect.Type][]field{}
+	}
+	fieldCache.m[t] = f
+	fieldCache.Unlock()
+	return f
 }
diff --git a/src/pkg/encoding/json/encode_test.go b/src/pkg/encoding/json/encode_test.go
index cb1c77e..be74c99 100644
--- a/src/pkg/encoding/json/encode_test.go
+++ b/src/pkg/encoding/json/encode_test.go
@@ -186,3 +186,23 @@ func TestMarshalerEscaping(t *testing.T) {
 		t.Errorf("got %q, want %q", got, want)
 	}
 }
+
+type IntType int
+
+type MyStruct struct {
+	IntType
+}
+
+func TestAnonymousNonstruct(t *testing.T) {
+	var i IntType = 11
+	a := MyStruct{i}
+	const want = `{"IntType":11}`
+
+	b, err := Marshal(a)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	if got := string(b); got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+}
diff --git a/src/pkg/encoding/json/scanner_test.go b/src/pkg/encoding/json/scanner_test.go
index 14d8508..77d3455 100644
--- a/src/pkg/encoding/json/scanner_test.go
+++ b/src/pkg/encoding/json/scanner_test.go
@@ -92,7 +92,7 @@ func TestCompactBig(t *testing.T) {
 		t.Fatalf("Compact: %v", err)
 	}
 	b := buf.Bytes()
-	if bytes.Compare(b, jsonBig) != 0 {
+	if !bytes.Equal(b, jsonBig) {
 		t.Error("Compact(jsonBig) != jsonBig")
 		diff(t, b, jsonBig)
 		return
@@ -118,7 +118,7 @@ func TestIndentBig(t *testing.T) {
 		t.Fatalf("Indent2: %v", err)
 	}
 	b1 := buf1.Bytes()
-	if bytes.Compare(b1, b) != 0 {
+	if !bytes.Equal(b1, b) {
 		t.Error("Indent(Indent(jsonBig)) != Indent(jsonBig)")
 		diff(t, b1, b)
 		return
@@ -130,7 +130,7 @@ func TestIndentBig(t *testing.T) {
 		t.Fatalf("Compact: %v", err)
 	}
 	b1 = buf1.Bytes()
-	if bytes.Compare(b1, jsonBig) != 0 {
+	if !bytes.Equal(b1, jsonBig) {
 		t.Error("Compact(Indent(jsonBig)) != jsonBig")
 		diff(t, b1, jsonBig)
 		return
@@ -277,9 +277,6 @@ func genArray(n int) []interface{} {
 	if f > n {
 		f = n
 	}
-	if n > 0 && f == 0 {
-		f = 1
-	}
 	x := make([]interface{}, f)
 	for i := range x {
 		x[i] = genValue(((i+1)*n)/f - (i*n)/f)
diff --git a/src/pkg/encoding/json/stream.go b/src/pkg/encoding/json/stream.go
index 7d1cc5f..00f4726 100644
--- a/src/pkg/encoding/json/stream.go
+++ b/src/pkg/encoding/json/stream.go
@@ -5,6 +5,7 @@
 package json
 
 import (
+	"bytes"
 	"errors"
 	"io"
 )
@@ -26,6 +27,10 @@ func NewDecoder(r io.Reader) *Decoder {
 	return &Decoder{r: r}
 }
 
+// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
+// Number instead of as a float64.
+func (dec *Decoder) UseNumber() { dec.d.useNumber = true }
+
 // Decode reads the next JSON-encoded value from its
 // input and stores it in the value pointed to by v.
 //
@@ -54,6 +59,12 @@ func (dec *Decoder) Decode(v interface{}) error {
 	return err
 }
 
+// Buffered returns a reader of the data remaining in the Decoder's
+// buffer. The reader is valid until the next call to Decode.
+func (dec *Decoder) Buffered() io.Reader {
+	return bytes.NewReader(dec.buf)
+}
+
 // readValue reads a JSON value into dec.buf.
 // It returns the length of the encoding.
 func (dec *Decoder) readValue() (int, error) {
@@ -74,7 +85,7 @@ Input:
 			// scanEnd is delayed one byte.
 			// We might block trying to get that byte from src,
 			// so instead invent a space byte.
-			if v == scanEndObject && dec.scan.step(&dec.scan, ' ') == scanEnd {
+			if (v == scanEndObject || v == scanEndArray) && dec.scan.step(&dec.scan, ' ') == scanEnd {
 				scanp += i + 1
 				break Input
 			}
diff --git a/src/pkg/encoding/json/stream_test.go b/src/pkg/encoding/json/stream_test.go
index ce5a7e6..07c9e1d 100644
--- a/src/pkg/encoding/json/stream_test.go
+++ b/src/pkg/encoding/json/stream_test.go
@@ -6,7 +6,10 @@ package json
 
 import (
 	"bytes"
+	"io/ioutil"
+	"net"
 	"reflect"
+	"strings"
 	"testing"
 )
 
@@ -82,6 +85,28 @@ func TestDecoder(t *testing.T) {
 	}
 }
 
+func TestDecoderBuffered(t *testing.T) {
+	r := strings.NewReader(`{"Name": "Gopher"} extra `)
+	var m struct {
+		Name string
+	}
+	d := NewDecoder(r)
+	err := d.Decode(&m)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if m.Name != "Gopher" {
+		t.Errorf("Name = %q; want Gopher", m.Name)
+	}
+	rest, err := ioutil.ReadAll(d.Buffered())
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, w := string(rest), " extra "; g != w {
+		t.Errorf("Remaining = %q; want %q", g, w)
+	}
+}
+
 func nlines(s string, n int) string {
 	if n <= 0 {
 		return ""
@@ -145,3 +170,24 @@ func TestNullRawMessage(t *testing.T) {
 		t.Fatalf("Marshal: have %#q want %#q", b, msg)
 	}
 }
+
+var blockingTests = []string{
+	`{"x": 1}`,
+	`[1, 2, 3]`,
+}
+
+func TestBlocking(t *testing.T) {
+	for _, enc := range blockingTests {
+		r, w := net.Pipe()
+		go w.Write([]byte(enc))
+		var val interface{}
+
+		// If Decode reads beyond what w.Write writes above,
+		// it will block, and the test will deadlock.
+		if err := NewDecoder(r).Decode(&val); err != nil {
+			t.Errorf("decoding %s: %v", enc, err)
+		}
+		r.Close()
+		w.Close()
+	}
+}
diff --git a/src/pkg/encoding/json/tagkey_test.go b/src/pkg/encoding/json/tagkey_test.go
index da8b12b..23e71c7 100644
--- a/src/pkg/encoding/json/tagkey_test.go
+++ b/src/pkg/encoding/json/tagkey_test.go
@@ -60,6 +60,14 @@ type badCodeTag struct {
 	Z string `json:" !\"#&'()*+,."`
 }
 
+type spaceTag struct {
+	Q string `json:"With space"`
+}
+
+type unicodeTag struct {
+	W string `json:"Ελλάδα"`
+}
+
 var structTagObjectKeyTests = []struct {
 	raw   interface{}
 	value string
@@ -78,6 +86,8 @@ var structTagObjectKeyTests = []struct {
 	{badCodeTag{"Reliable Man"}, "Reliable Man", "Z"},
 	{percentSlashTag{"brut"}, "brut", "text/html%"},
 	{punctuationTag{"Union Rags"}, "Union Rags", "!#$%&()*+-./:<=>?@[]^_{|}~"},
+	{spaceTag{"Perreddu"}, "Perreddu", "With space"},
+	{unicodeTag{"Loukanikos"}, "Loukanikos", "Ελλάδα"},
 }
 
 func TestStructTagObjectKey(t *testing.T) {
diff --git a/src/pkg/encoding/pem/pem.go b/src/pkg/encoding/pem/pem.go
index 3c1f5ab..8ff7ee8 100644
--- a/src/pkg/encoding/pem/pem.go
+++ b/src/pkg/encoding/pem/pem.go
@@ -11,6 +11,7 @@ import (
 	"bytes"
 	"encoding/base64"
 	"io"
+	"sort"
 )
 
 // A Block represents a PEM encoded structure.
@@ -209,26 +210,46 @@ func (l *lineBreaker) Close() (err error) {
 	return
 }
 
-func Encode(out io.Writer, b *Block) (err error) {
-	_, err = out.Write(pemStart[1:])
-	if err != nil {
-		return
+func writeHeader(out io.Writer, k, v string) error {
+	_, err := out.Write([]byte(k + ": " + v + "\n"))
+	return err
+}
+
+func Encode(out io.Writer, b *Block) error {
+	if _, err := out.Write(pemStart[1:]); err != nil {
+		return err
 	}
-	_, err = out.Write([]byte(b.Type + "-----\n"))
-	if err != nil {
-		return
+	if _, err := out.Write([]byte(b.Type + "-----\n")); err != nil {
+		return err
 	}
 
 	if len(b.Headers) > 0 {
-		for k, v := range b.Headers {
-			_, err = out.Write([]byte(k + ": " + v + "\n"))
-			if err != nil {
-				return
+		const procType = "Proc-Type"
+		h := make([]string, 0, len(b.Headers))
+		hasProcType := false
+		for k := range b.Headers {
+			if k == procType {
+				hasProcType = true
+				continue
 			}
+			h = append(h, k)
 		}
-		_, err = out.Write([]byte{'\n'})
-		if err != nil {
-			return
+		// The Proc-Type header must be written first.
+		// See RFC 1421, section 4.6.1.1
+		if hasProcType {
+			if err := writeHeader(out, procType, b.Headers[procType]); err != nil {
+				return err
+			}
+		}
+		// For consistency of output, write other headers sorted by key.
+		sort.Strings(h)
+		for _, k := range h {
+			if err := writeHeader(out, k, b.Headers[k]); err != nil {
+				return err
+			}
+		}
+		if _, err := out.Write([]byte{'\n'}); err != nil {
+			return err
 		}
 	}
 
@@ -236,19 +257,17 @@ func Encode(out io.Writer, b *Block) (err error) {
 	breaker.out = out
 
 	b64 := base64.NewEncoder(base64.StdEncoding, &breaker)
-	_, err = b64.Write(b.Bytes)
-	if err != nil {
-		return
+	if _, err := b64.Write(b.Bytes); err != nil {
+		return err
 	}
 	b64.Close()
 	breaker.Close()
 
-	_, err = out.Write(pemEnd[1:])
-	if err != nil {
-		return
+	if _, err := out.Write(pemEnd[1:]); err != nil {
+		return err
 	}
-	_, err = out.Write([]byte(b.Type + "-----\n"))
-	return
+	_, err := out.Write([]byte(b.Type + "-----\n"))
+	return err
 }
 
 func EncodeToMemory(b *Block) []byte {
diff --git a/src/pkg/encoding/pem/pem_test.go b/src/pkg/encoding/pem/pem_test.go
index 6133534..ccce42c 100644
--- a/src/pkg/encoding/pem/pem_test.go
+++ b/src/pkg/encoding/pem/pem_test.go
@@ -43,7 +43,7 @@ func TestDecode(t *testing.T) {
 	if !reflect.DeepEqual(result, privateKey) {
 		t.Errorf("#1 got:%#v want:%#v", result, privateKey)
 	}
-	result, _ = Decode([]byte(pemPrivateKey))
+	result, _ = Decode([]byte(pemPrivateKey2))
 	if !reflect.DeepEqual(result, privateKey2) {
 		t.Errorf("#2 got:%#v want:%#v", result, privateKey2)
 	}
@@ -51,8 +51,8 @@ func TestDecode(t *testing.T) {
 
 func TestEncode(t *testing.T) {
 	r := EncodeToMemory(privateKey2)
-	if string(r) != pemPrivateKey {
-		t.Errorf("got:%s want:%s", r, pemPrivateKey)
+	if string(r) != pemPrivateKey2 {
+		t.Errorf("got:%s want:%s", r, pemPrivateKey2)
 	}
 }
 
@@ -341,50 +341,64 @@ var privateKey = &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,
-		0xd4, 0x0, 0xae, 0x6a, 0x4d, 0x1b, 0x8a, 0x3b, 0x6a, 0x13,
-		0x64, 0x2b, 0x23, 0xf2, 0x8b, 0x0, 0x3b, 0xfb, 0x97, 0x79,
-		0xa, 0xde, 0x9a, 0x4c, 0xc8, 0x2b, 0x8b, 0x2a, 0x81, 0x74,
-		0x7d, 0xde, 0xc0, 0x8b, 0x62, 0x96, 0xe5, 0x3a, 0x8, 0xc3,
-		0x31, 0x68, 0x7e, 0xf2, 0x5c, 0x4b, 0xf4, 0x93, 0x6b, 0xa1,
-		0xc0, 0xe6, 0x4, 0x1e, 0x9d, 0x15, 0x2, 0x3, 0x1, 0x0, 0x1,
-		0x2, 0x41, 0x0, 0x8a, 0xbd, 0x6a, 0x69, 0xf4, 0xd1, 0xa4,
-		0xb4, 0x87, 0xf0, 0xab, 0x8d, 0x7a, 0xae, 0xfd, 0x38, 0x60,
-		0x94, 0x5, 0xc9, 0x99, 0x98, 0x4e, 0x30, 0xf5, 0x67, 0xe1,
-		0xe8, 0xae, 0xef, 0xf4, 0x4e, 0x8b, 0x18, 0xbd, 0xb1, 0xec,
-		0x78, 0xdf, 0xa3, 0x1a, 0x55, 0xe3, 0x2a, 0x48, 0xd7, 0xfb,
-		0x13, 0x1f, 0x5a, 0xf1, 0xf4, 0x4d, 0x7d, 0x6b, 0x2c, 0xed,
-		0x2a, 0x9d, 0xf5, 0xe5, 0xae, 0x45, 0x35, 0x2, 0x21, 0x0,
-		0xda, 0xb2, 0xf1, 0x80, 0x48, 0xba, 0xa6, 0x8d, 0xe7, 0xdf,
-		0x4, 0xd2, 0xd3, 0x5d, 0x5d, 0x80, 0xe6, 0xe, 0x2d, 0xfa,
-		0x42, 0xd5, 0xa, 0x9b, 0x4, 0x21, 0x90, 0x32, 0x71, 0x5e,
-		0x46, 0xb3, 0x2, 0x21, 0x0, 0xd1, 0xf, 0x2e, 0x66, 0xb1,
-		0xd0, 0xc1, 0x3f, 0x10, 0xef, 0x99, 0x27, 0xbf, 0x53, 0x24,
-		0xa3, 0x79, 0xca, 0x21, 0x81, 0x46, 0xcb, 0xf9, 0xca, 0xfc,
-		0x79, 0x52, 0x21, 0xf1, 0x6a, 0x31, 0x17, 0x2, 0x20, 0x21,
-		0x2, 0x89, 0x79, 0x37, 0x81, 0x14, 0xca, 0xae, 0x88, 0xf7,
-		0xd, 0x6b, 0x61, 0xd8, 0x4f, 0x30, 0x6a, 0x4b, 0x7e, 0x4e,
-		0xc0, 0x21, 0x4d, 0xac, 0x9d, 0xf4, 0x49, 0xe8, 0xda, 0xb6,
-		0x9, 0x2, 0x20, 0x16, 0xb3, 0xec, 0x59, 0x10, 0xa4, 0x57,
-		0xe8, 0xe, 0x61, 0xc6, 0xa3, 0xf, 0x5e, 0xeb, 0x12, 0xa9,
-		0xae, 0x2e, 0xb7, 0x48, 0x45, 0xec, 0x69, 0x83, 0xc3, 0x75,
-		0xc, 0xe4, 0x97, 0xa0, 0x9f, 0x2, 0x20, 0x69, 0x52, 0xb4,
-		0x6, 0xe8, 0x50, 0x60, 0x71, 0x4c, 0x3a, 0xb7, 0x66, 0xba,
-		0xd, 0x8a, 0xc9, 0xb7, 0xd, 0xa3, 0x8, 0x6c, 0xa3, 0xf2,
-		0x62, 0xb0, 0x2a, 0x84, 0xaa, 0x2f, 0xd6, 0x1e, 0x55,
+var privateKey2 = &Block{
+	Type: "RSA PRIVATE KEY",
+	Headers: map[string]string{
+		"Proc-Type":      "4,ENCRYPTED",
+		"DEK-Info":       "AES-128-CBC,BFCD243FEDBB40A4AA6DDAA1335473A4",
+		"Content-Domain": "RFC822",
+	},
+	Bytes: []uint8{
+		0xa8, 0x35, 0xcc, 0x2b, 0xb9, 0xcb, 0x21, 0xab, 0xc0,
+		0x9d, 0x76, 0x61, 0x0, 0xf4, 0x81, 0xad, 0x69, 0xd2,
+		0xc0, 0x42, 0x41, 0x3b, 0xe4, 0x3c, 0xaf, 0x59, 0x5e,
+		0x6d, 0x2a, 0x3c, 0x9c, 0xa1, 0xa4, 0x5e, 0x68, 0x37,
+		0xc4, 0x8c, 0x70, 0x1c, 0xa9, 0x18, 0xe6, 0xc2, 0x2b,
+		0x8a, 0x91, 0xdc, 0x2d, 0x1f, 0x8, 0x23, 0x39, 0xf1,
+		0x4b, 0x8b, 0x1b, 0x2f, 0x46, 0xb, 0xb2, 0x26, 0xba,
+		0x4f, 0x40, 0x80, 0x39, 0xc4, 0xb1, 0xcb, 0x3b, 0xb4,
+		0x65, 0x3f, 0x1b, 0xb2, 0xf7, 0x8, 0xd2, 0xc6, 0xd5,
+		0xa8, 0x9f, 0x23, 0x69, 0xb6, 0x3d, 0xf9, 0xac, 0x1c,
+		0xb3, 0x13, 0x87, 0x64, 0x4, 0x37, 0xdb, 0x40, 0xc8,
+		0x82, 0xc, 0xd0, 0xf8, 0x21, 0x7c, 0xdc, 0xbd, 0x9, 0x4,
+		0x20, 0x16, 0xb0, 0x97, 0xe2, 0x6d, 0x56, 0x1d, 0xe3,
+		0xec, 0xf0, 0xfc, 0xe2, 0x56, 0xad, 0xa4, 0x3, 0x70,
+		0x6d, 0x63, 0x3c, 0x1, 0xbe, 0x3e, 0x28, 0x38, 0x6f,
+		0xc0, 0xe6, 0xfd, 0x85, 0xd1, 0x53, 0xa8, 0x9b, 0xcb,
+		0xd4, 0x4, 0xb1, 0x73, 0xb9, 0x73, 0x32, 0xd6, 0x7a,
+		0xc6, 0x29, 0x25, 0xa5, 0xda, 0x17, 0x93, 0x7a, 0x10,
+		0xe8, 0x41, 0xfb, 0xa5, 0x17, 0x20, 0xf8, 0x4e, 0xe9,
+		0xe3, 0x8f, 0x51, 0x20, 0x13, 0xbb, 0xde, 0xb7, 0x93,
+		0xae, 0x13, 0x8a, 0xf6, 0x9, 0xf4, 0xa6, 0x41, 0xe0,
+		0x2b, 0x51, 0x1a, 0x30, 0x38, 0xd, 0xb1, 0x3b, 0x67,
+		0x87, 0x64, 0xf5, 0xca, 0x32, 0x67, 0xd1, 0xc8, 0xa5,
+		0x3d, 0x23, 0x72, 0xc4, 0x6, 0xaf, 0x8f, 0x7b, 0x26,
+		0xac, 0x3c, 0x75, 0x91, 0xa1, 0x0, 0x13, 0xc6, 0x5c,
+		0x49, 0xd5, 0x3c, 0xe7, 0xb2, 0xb2, 0x99, 0xe0, 0xd5,
+		0x25, 0xfa, 0xe2, 0x12, 0x80, 0x37, 0x85, 0xcf, 0x92,
+		0xca, 0x1b, 0x9f, 0xf3, 0x4e, 0xd8, 0x80, 0xef, 0x3c,
+		0xce, 0xcd, 0xf5, 0x90, 0x9e, 0xf9, 0xa7, 0xb2, 0xc,
+		0x49, 0x4, 0xf1, 0x9, 0x8f, 0xea, 0x63, 0xd2, 0x70,
+		0xbb, 0x86, 0xbf, 0x34, 0xab, 0xb2, 0x3, 0xb1, 0x59,
+		0x33, 0x16, 0x17, 0xb0, 0xdb, 0x77, 0x38, 0xf4, 0xb4,
+		0x94, 0xb, 0x25, 0x16, 0x7e, 0x22, 0xd4, 0xf9, 0x22,
+		0xb9, 0x78, 0xa3, 0x4, 0x84, 0x4, 0xd2, 0xda, 0x84,
+		0x2d, 0x63, 0xdd, 0xf8, 0x50, 0x6a, 0xf6, 0xe3, 0xf5,
+		0x65, 0x40, 0x7c, 0xa9,
 	},
 }
 
-var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
-MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
-fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
-/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
-RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
-EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
-IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
-tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
+var pemPrivateKey2 = `-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+Content-Domain: RFC822
+DEK-Info: AES-128-CBC,BFCD243FEDBB40A4AA6DDAA1335473A4
+
+qDXMK7nLIavAnXZhAPSBrWnSwEJBO+Q8r1lebSo8nKGkXmg3xIxwHKkY5sIripHc
+LR8IIznxS4sbL0YLsia6T0CAOcSxyzu0ZT8bsvcI0sbVqJ8jabY9+awcsxOHZAQ3
+20DIggzQ+CF83L0JBCAWsJfibVYd4+zw/OJWraQDcG1jPAG+Pig4b8Dm/YXRU6ib
+y9QEsXO5czLWesYpJaXaF5N6EOhB+6UXIPhO6eOPUSATu963k64TivYJ9KZB4CtR
+GjA4DbE7Z4dk9coyZ9HIpT0jcsQGr497Jqw8dZGhABPGXEnVPOeyspng1SX64hKA
+N4XPksobn/NO2IDvPM7N9ZCe+aeyDEkE8QmP6mPScLuGvzSrsgOxWTMWF7Dbdzj0
+tJQLJRZ+ItT5Irl4owSEBNLahC1j3fhQavbj9WVAfKk=
 -----END RSA PRIVATE KEY-----
 `
diff --git a/src/pkg/encoding/xml/example_test.go b/src/pkg/encoding/xml/example_test.go
index 97c8c0b..becedd5 100644
--- a/src/pkg/encoding/xml/example_test.go
+++ b/src/pkg/encoding/xml/example_test.go
@@ -50,6 +50,46 @@ func ExampleMarshalIndent() {
 	//   </person>
 }
 
+func ExampleEncoder() {
+	type Address struct {
+		City, State string
+	}
+	type Person struct {
+		XMLName   xml.Name `xml:"person"`
+		Id        int      `xml:"id,attr"`
+		FirstName string   `xml:"name>first"`
+		LastName  string   `xml:"name>last"`
+		Age       int      `xml:"age"`
+		Height    float32  `xml:"height,omitempty"`
+		Married   bool
+		Address
+		Comment string `xml:",comment"`
+	}
+
+	v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}
+	v.Comment = " Need more details. "
+	v.Address = Address{"Hanga Roa", "Easter Island"}
+
+	enc := xml.NewEncoder(os.Stdout)
+	enc.Indent("  ", "    ")
+	if err := enc.Encode(v); err != nil {
+		fmt.Printf("error: %v\n", err)
+	}
+
+	// Output:
+	//   <person id="13">
+	//       <name>
+	//           <first>John</first>
+	//           <last>Doe</last>
+	//       </name>
+	//       <age>42</age>
+	//       <Married>false</Married>
+	//       <City>Hanga Roa</City>
+	//       <State>Easter Island</State>
+	//       <!-- Need more details. -->
+	//   </person>
+}
+
 // This example demonstrates unmarshaling an XML excerpt into a value with
 // some preset fields. Note that the Phone field isn't modified and that
 // the XML <Company> element is ignored. Also, the Groups field is assigned
diff --git a/src/pkg/encoding/xml/marshal.go b/src/pkg/encoding/xml/marshal.go
index 6c3170b..ea58ce2 100644
--- a/src/pkg/encoding/xml/marshal.go
+++ b/src/pkg/encoding/xml/marshal.go
@@ -45,7 +45,7 @@ const (
 //     - a field with tag "name,attr" becomes an attribute with
 //       the given name in the XML element.
 //     - a field with tag ",attr" becomes an attribute with the
-//       field name in the in the XML element.
+//       field name in the XML element.
 //     - a field with tag ",chardata" is written as character data,
 //       not as an XML element.
 //     - a field with tag ",innerxml" is written verbatim, not subject
@@ -57,8 +57,8 @@ const (
 //       if the field value is empty. The empty values are false, 0, any
 //       nil pointer or interface value, and any array, slice, map, or
 //       string of length zero.
-//     - a non-pointer anonymous struct field is handled as if the
-//       fields of its value were part of the outer struct.
+//     - an anonymous struct field is handled as if the fields of its
+//       value were part of the outer struct.
 //
 // If a field uses a tag "a>b>c", then the element c will be nested inside
 // parent elements a and b.  Fields that appear next to each other that name
@@ -81,11 +81,8 @@ func Marshal(v interface{}) ([]byte, error) {
 func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
 	var b bytes.Buffer
 	enc := NewEncoder(&b)
-	enc.prefix = prefix
-	enc.indent = indent
-	err := enc.marshalValue(reflect.ValueOf(v), nil)
-	enc.Flush()
-	if err != nil {
+	enc.Indent(prefix, indent)
+	if err := enc.Encode(v); err != nil {
 		return nil, err
 	}
 	return b.Bytes(), nil
@@ -101,14 +98,24 @@ func NewEncoder(w io.Writer) *Encoder {
 	return &Encoder{printer{Writer: bufio.NewWriter(w)}}
 }
 
+// Indent sets the encoder to generate XML in which each element
+// begins on a new indented line that starts with prefix and is followed by
+// one or more copies of indent according to the nesting depth.
+func (enc *Encoder) Indent(prefix, indent string) {
+	enc.prefix = prefix
+	enc.indent = indent
+}
+
 // Encode writes the XML encoding of v to the stream.
 //
 // See the documentation for Marshal for details about the conversion
 // of Go values to XML.
 func (enc *Encoder) Encode(v interface{}) error {
 	err := enc.marshalValue(reflect.ValueOf(v), nil)
-	enc.Flush()
-	return err
+	if err != nil {
+		return err
+	}
+	return enc.Flush()
 }
 
 type printer struct {
@@ -117,6 +124,7 @@ type printer struct {
 	prefix     string
 	depth      int
 	indentedIn bool
+	putNewline bool
 }
 
 // marshalValue writes one or more XML elements representing val.
@@ -164,7 +172,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
 		xmlname := tinfo.xmlname
 		if xmlname.name != "" {
 			xmlns, name = xmlname.xmlns, xmlname.name
-		} else if v, ok := val.FieldByIndex(xmlname.idx).Interface().(Name); ok && v.Local != "" {
+		} else if v, ok := xmlname.value(val).Interface().(Name); ok && v.Local != "" {
 			xmlns, name = v.Space, v.Local
 		}
 	}
@@ -185,7 +193,9 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
 	if xmlns != "" {
 		p.WriteString(` xmlns="`)
 		// TODO: EscapeString, to avoid the allocation.
-		Escape(p, []byte(xmlns))
+		if err := EscapeText(p, []byte(xmlns)); err != nil {
+			return err
+		}
 		p.WriteByte('"')
 	}
 
@@ -195,7 +205,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
 		if finfo.flags&fAttr == 0 {
 			continue
 		}
-		fv := val.FieldByIndex(finfo.idx)
+		fv := finfo.value(val)
 		if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
 			continue
 		}
@@ -224,7 +234,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
 	p.WriteString(name)
 	p.WriteByte('>')
 
-	return nil
+	return p.cachedWriteError()
 }
 
 var timeType = reflect.TypeOf(time.Time{})
@@ -241,50 +251,70 @@ func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error {
 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 		p.WriteString(strconv.FormatUint(val.Uint(), 10))
 	case reflect.Float32, reflect.Float64:
-		p.WriteString(strconv.FormatFloat(val.Float(), 'g', -1, 64))
+		p.WriteString(strconv.FormatFloat(val.Float(), 'g', -1, val.Type().Bits()))
 	case reflect.String:
 		// TODO: Add EscapeString.
-		Escape(p, []byte(val.String()))
+		EscapeText(p, []byte(val.String()))
 	case reflect.Bool:
 		p.WriteString(strconv.FormatBool(val.Bool()))
 	case reflect.Array:
 		// will be [...]byte
-		bytes := make([]byte, val.Len())
-		for i := range bytes {
-			bytes[i] = val.Index(i).Interface().(byte)
+		var bytes []byte
+		if val.CanAddr() {
+			bytes = val.Slice(0, val.Len()).Bytes()
+		} else {
+			bytes = make([]byte, val.Len())
+			reflect.Copy(reflect.ValueOf(bytes), val)
 		}
-		Escape(p, bytes)
+		EscapeText(p, bytes)
 	case reflect.Slice:
 		// will be []byte
-		Escape(p, val.Bytes())
+		EscapeText(p, val.Bytes())
 	default:
 		return &UnsupportedTypeError{typ}
 	}
-	return nil
+	return p.cachedWriteError()
 }
 
 var ddBytes = []byte("--")
 
 func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
 	if val.Type() == timeType {
-		p.WriteString(val.Interface().(time.Time).Format(time.RFC3339Nano))
-		return nil
+		_, err := p.WriteString(val.Interface().(time.Time).Format(time.RFC3339Nano))
+		return err
 	}
 	s := parentStack{printer: p}
 	for i := range tinfo.fields {
 		finfo := &tinfo.fields[i]
-		if finfo.flags&(fAttr|fAny) != 0 {
+		if finfo.flags&(fAttr) != 0 {
 			continue
 		}
-		vf := val.FieldByIndex(finfo.idx)
+		vf := finfo.value(val)
 		switch finfo.flags & fMode {
 		case fCharData:
+			var scratch [64]byte
 			switch vf.Kind() {
+			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+				Escape(p, strconv.AppendInt(scratch[:0], vf.Int(), 10))
+			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+				Escape(p, strconv.AppendUint(scratch[:0], vf.Uint(), 10))
+			case reflect.Float32, reflect.Float64:
+				Escape(p, strconv.AppendFloat(scratch[:0], vf.Float(), 'g', -1, vf.Type().Bits()))
+			case reflect.Bool:
+				Escape(p, strconv.AppendBool(scratch[:0], vf.Bool()))
 			case reflect.String:
-				Escape(p, []byte(vf.String()))
+				if err := EscapeText(p, []byte(vf.String())); err != nil {
+					return err
+				}
 			case reflect.Slice:
 				if elem, ok := vf.Interface().([]byte); ok {
-					Escape(p, elem)
+					if err := EscapeText(p, elem); err != nil {
+						return err
+					}
+				}
+			case reflect.Struct:
+				if vf.Type() == timeType {
+					Escape(p, []byte(vf.Interface().(time.Time).Format(time.RFC3339Nano)))
 				}
 			}
 			continue
@@ -340,7 +370,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
 				continue
 			}
 
-		case fElement:
+		case fElement, fElement | fAny:
 			s.trim(finfo.parents)
 			if len(finfo.parents) > len(s.stack) {
 				if vf.Kind() != reflect.Ptr && vf.Kind() != reflect.Interface || !vf.IsNil() {
@@ -353,7 +383,13 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
 		}
 	}
 	s.trim(nil)
-	return nil
+	return p.cachedWriteError()
+}
+
+// return the bufio Writer's cached write error
+func (p *printer) cachedWriteError() error {
+	_, err := p.Write(nil)
+	return err
 }
 
 func (p *printer) writeIndent(depthDelta int) {
@@ -368,7 +404,11 @@ func (p *printer) writeIndent(depthDelta int) {
 		}
 		p.indentedIn = false
 	}
-	p.WriteByte('\n')
+	if p.putNewline {
+		p.WriteByte('\n')
+	} else {
+		p.putNewline = true
+	}
 	if len(p.prefix) > 0 {
 		p.WriteString(p.prefix)
 	}
diff --git a/src/pkg/encoding/xml/marshal_test.go b/src/pkg/encoding/xml/marshal_test.go
index b6978a1..3a190de 100644
--- a/src/pkg/encoding/xml/marshal_test.go
+++ b/src/pkg/encoding/xml/marshal_test.go
@@ -5,6 +5,10 @@
 package xml
 
 import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
 	"reflect"
 	"strconv"
 	"strings"
@@ -56,6 +60,36 @@ type Book struct {
 	Title   string   `xml:",chardata"`
 }
 
+type Event struct {
+	XMLName struct{} `xml:"event"`
+	Year    int      `xml:",chardata"`
+}
+
+type Movie struct {
+	XMLName struct{} `xml:"movie"`
+	Length  uint     `xml:",chardata"`
+}
+
+type Pi struct {
+	XMLName       struct{} `xml:"pi"`
+	Approximation float32  `xml:",chardata"`
+}
+
+type Universe struct {
+	XMLName struct{} `xml:"universe"`
+	Visible float64  `xml:",chardata"`
+}
+
+type Particle struct {
+	XMLName struct{} `xml:"particle"`
+	HasMass bool     `xml:",chardata"`
+}
+
+type Departure struct {
+	XMLName struct{}  `xml:"departure"`
+	When    time.Time `xml:",chardata"`
+}
+
 type SecretAgent struct {
 	XMLName   struct{} `xml:"agent"`
 	Handle    string   `xml:"handle,attr"`
@@ -108,7 +142,7 @@ type EmbedA struct {
 
 type EmbedB struct {
 	FieldB string
-	EmbedC
+	*EmbedC
 }
 
 type EmbedC struct {
@@ -185,6 +219,18 @@ type AnyTest struct {
 	AnyField AnyHolder `xml:",any"`
 }
 
+type AnyOmitTest struct {
+	XMLName  struct{}   `xml:"a"`
+	Nested   string     `xml:"nested>value"`
+	AnyField *AnyHolder `xml:",any,omitempty"`
+}
+
+type AnySliceTest struct {
+	XMLName  struct{}    `xml:"a"`
+	Nested   string      `xml:"nested>value"`
+	AnyField []AnyHolder `xml:",any"`
+}
+
 type AnyHolder struct {
 	XMLName Name
 	XML     string `xml:",innerxml"`
@@ -330,6 +376,12 @@ var marshalTests = []struct {
 	{Value: &Domain{Name: []byte("google.com&friends")}, ExpectXML: `<domain>google.com&friends</domain>`},
 	{Value: &Domain{Name: []byte("google.com"), Comment: []byte(" &friends ")}, ExpectXML: `<domain>google.com<!-- &friends --></domain>`},
 	{Value: &Book{Title: "Pride & Prejudice"}, ExpectXML: `<book>Pride & Prejudice</book>`},
+	{Value: &Event{Year: -3114}, ExpectXML: `<event>-3114</event>`},
+	{Value: &Movie{Length: 13440}, ExpectXML: `<movie>13440</movie>`},
+	{Value: &Pi{Approximation: 3.14159265}, ExpectXML: `<pi>3.1415927</pi>`},
+	{Value: &Universe{Visible: 9.3e13}, ExpectXML: `<universe>9.3e+13</universe>`},
+	{Value: &Particle{HasMass: true}, ExpectXML: `<particle>true</particle>`},
+	{Value: &Departure{When: ParseTime("2013-01-09T00:15:00-09:00")}, ExpectXML: `<departure>2013-01-09T00:15:00-09:00</departure>`},
 	{Value: atomValue, ExpectXML: atomXml},
 	{
 		Value: &Ship{
@@ -493,7 +545,7 @@ var marshalTests = []struct {
 			},
 			EmbedB: EmbedB{
 				FieldB: "A.B.B",
-				EmbedC: EmbedC{
+				EmbedC: &EmbedC{
 					FieldA1: "A.B.C.A1",
 					FieldA2: "A.B.C.A2",
 					FieldB:  "", // Shadowed by A.B.B
@@ -649,12 +701,43 @@ var marshalTests = []struct {
 				XML:     "<sub>unknown</sub>",
 			},
 		},
-		UnmarshalOnly: true,
 	},
 	{
-		Value:       &AnyTest{Nested: "known", AnyField: AnyHolder{XML: "<unknown/>"}},
-		ExpectXML:   `<a><nested><value>known</value></nested></a>`,
-		MarshalOnly: true,
+		Value: &AnyTest{Nested: "known",
+			AnyField: AnyHolder{
+				XML:     "<unknown/>",
+				XMLName: Name{Local: "AnyField"},
+			},
+		},
+		ExpectXML: `<a><nested><value>known</value></nested><AnyField><unknown/></AnyField></a>`,
+	},
+	{
+		ExpectXML: `<a><nested><value>b</value></nested></a>`,
+		Value: &AnyOmitTest{
+			Nested: "b",
+		},
+	},
+	{
+		ExpectXML: `<a><nested><value>b</value></nested><c><d>e</d></c><g xmlns="f"><h>i</h></g></a>`,
+		Value: &AnySliceTest{
+			Nested: "b",
+			AnyField: []AnyHolder{
+				{
+					XMLName: Name{Local: "c"},
+					XML:     "<d>e</d>",
+				},
+				{
+					XMLName: Name{Space: "f", Local: "g"},
+					XML:     "<h>i</h>",
+				},
+			},
+		},
+	},
+	{
+		ExpectXML: `<a><nested><value>b</value></nested></a>`,
+		Value: &AnySliceTest{
+			Nested: "b",
+		},
 	},
 
 	// Test recursive types.
@@ -684,6 +767,29 @@ var marshalTests = []struct {
 		Value:         &IgnoreTest{},
 		UnmarshalOnly: true,
 	},
+
+	// Test escaping.
+	{
+		ExpectXML: `<a><nested><value>dquote: "; squote: '; ampersand: &; less: <; greater: >;</value></nested><empty></empty></a>`,
+		Value: &AnyTest{
+			Nested:   `dquote: "; squote: '; ampersand: &; less: <; greater: >;`,
+			AnyField: AnyHolder{XMLName: Name{Local: "empty"}},
+		},
+	},
+	{
+		ExpectXML: `<a><nested><value>newline: &#xA;; cr: &#xD;; tab: &#x9;;</value></nested><AnyField></AnyField></a>`,
+		Value: &AnyTest{
+			Nested:   "newline: \n; cr: \r; tab: \t;",
+			AnyField: AnyHolder{XMLName: Name{Local: "AnyField"}},
+		},
+	},
+	{
+		ExpectXML: "<a><nested><value>1\r2\r\n3\n\r4\n5</value></nested></a>",
+		Value: &AnyTest{
+			Nested: "1\n2\n3\n\n4\n5",
+		},
+		UnmarshalOnly: true,
+	},
 }
 
 func TestMarshal(t *testing.T) {
@@ -735,6 +841,24 @@ var marshalErrorTests = []struct {
 	},
 }
 
+var marshalIndentTests = []struct {
+	Value     interface{}
+	Prefix    string
+	Indent    string
+	ExpectXML string
+}{
+	{
+		Value: &SecretAgent{
+			Handle:    "007",
+			Identity:  "James Bond",
+			Obfuscate: "<redacted/>",
+		},
+		Prefix:    "",
+		Indent:    "\t",
+		ExpectXML: fmt.Sprintf("<agent handle=\"007\">\n\t<Identity>James Bond</Identity><redacted/>\n</agent>"),
+	},
+}
+
 func TestMarshalErrors(t *testing.T) {
 	for idx, test := range marshalErrorTests {
 		_, err := Marshal(test.Value)
@@ -779,6 +903,78 @@ func TestUnmarshal(t *testing.T) {
 	}
 }
 
+func TestMarshalIndent(t *testing.T) {
+	for i, test := range marshalIndentTests {
+		data, err := MarshalIndent(test.Value, test.Prefix, test.Indent)
+		if err != nil {
+			t.Errorf("#%d: Error: %s", i, err)
+			continue
+		}
+		if got, want := string(data), test.ExpectXML; got != want {
+			t.Errorf("#%d: MarshalIndent:\nGot:%s\nWant:\n%s", i, got, want)
+		}
+	}
+}
+
+type limitedBytesWriter struct {
+	w      io.Writer
+	remain int // until writes fail
+}
+
+func (lw *limitedBytesWriter) Write(p []byte) (n int, err error) {
+	if lw.remain <= 0 {
+		println("error")
+		return 0, errors.New("write limit hit")
+	}
+	if len(p) > lw.remain {
+		p = p[:lw.remain]
+		n, _ = lw.w.Write(p)
+		lw.remain = 0
+		return n, errors.New("write limit hit")
+	}
+	n, err = lw.w.Write(p)
+	lw.remain -= n
+	return n, err
+}
+
+func TestMarshalWriteErrors(t *testing.T) {
+	var buf bytes.Buffer
+	const writeCap = 1024
+	w := &limitedBytesWriter{&buf, writeCap}
+	enc := NewEncoder(w)
+	var err error
+	var i int
+	const n = 4000
+	for i = 1; i <= n; i++ {
+		err = enc.Encode(&Passenger{
+			Name:   []string{"Alice", "Bob"},
+			Weight: 5,
+		})
+		if err != nil {
+			break
+		}
+	}
+	if err == nil {
+		t.Error("expected an error")
+	}
+	if i == n {
+		t.Errorf("expected to fail before the end")
+	}
+	if buf.Len() != writeCap {
+		t.Errorf("buf.Len() = %d; want %d", buf.Len(), writeCap)
+	}
+}
+
+func TestMarshalWriteIOErrors(t *testing.T) {
+	enc := NewEncoder(errWriter{})
+
+	expectErr := "unwritable"
+	err := enc.Encode(&Passenger{})
+	if err == nil || err.Error() != expectErr {
+		t.Errorf("EscapeTest = [error] %v, want %v", err, expectErr)
+	}
+}
+
 func BenchmarkMarshal(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		Marshal(atomValue)
diff --git a/src/pkg/encoding/xml/read.go b/src/pkg/encoding/xml/read.go
index c216824..344ab51 100644
--- a/src/pkg/encoding/xml/read.go
+++ b/src/pkg/encoding/xml/read.go
@@ -81,8 +81,8 @@ import (
 //      of the above rules and the struct has a field with tag ",any",
 //      unmarshal maps the sub-element to that struct field.
 //
-//   * A non-pointer anonymous struct field is handled as if the
-//      fields of its value were part of the outer struct.
+//   * An anonymous struct field is handled as if the fields of its
+//      value were part of the outer struct.
 //
 //   * A struct field with tag "-" is never unmarshalled into.
 //
@@ -248,7 +248,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
 				}
 				return UnmarshalError(e)
 			}
-			fv := sv.FieldByIndex(finfo.idx)
+			fv := finfo.value(sv)
 			if _, ok := fv.Interface().(Name); ok {
 				fv.Set(reflect.ValueOf(start.Name))
 			}
@@ -260,7 +260,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
 			finfo := &tinfo.fields[i]
 			switch finfo.flags & fMode {
 			case fAttr:
-				strv := sv.FieldByIndex(finfo.idx)
+				strv := finfo.value(sv)
 				// Look for attribute.
 				for _, a := range start.Attr {
 					if a.Name.Local == finfo.name {
@@ -271,22 +271,22 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
 
 			case fCharData:
 				if !saveData.IsValid() {
-					saveData = sv.FieldByIndex(finfo.idx)
+					saveData = finfo.value(sv)
 				}
 
 			case fComment:
 				if !saveComment.IsValid() {
-					saveComment = sv.FieldByIndex(finfo.idx)
+					saveComment = finfo.value(sv)
 				}
 
-			case fAny:
+			case fAny, fAny | fElement:
 				if !saveAny.IsValid() {
-					saveAny = sv.FieldByIndex(finfo.idx)
+					saveAny = finfo.value(sv)
 				}
 
 			case fInnerXml:
 				if !saveXML.IsValid() {
-					saveXML = sv.FieldByIndex(finfo.idx)
+					saveXML = finfo.value(sv)
 					if p.saved == nil {
 						saveXMLIndex = 0
 						p.saved = new(bytes.Buffer)
@@ -374,68 +374,58 @@ Loop:
 }
 
 func copyValue(dst reflect.Value, src []byte) (err error) {
-	// Helper functions for integer and unsigned integer conversions
-	var itmp int64
-	getInt64 := func() bool {
-		itmp, err = strconv.ParseInt(string(src), 10, 64)
-		// TODO: should check sizes
-		return err == nil
-	}
-	var utmp uint64
-	getUint64 := func() bool {
-		utmp, err = strconv.ParseUint(string(src), 10, 64)
-		// TODO: check for overflow?
-		return err == nil
-	}
-	var ftmp float64
-	getFloat64 := func() bool {
-		ftmp, err = strconv.ParseFloat(string(src), 64)
-		// TODO: check for overflow?
-		return err == nil
+	if dst.Kind() == reflect.Ptr {
+		if dst.IsNil() {
+			dst.Set(reflect.New(dst.Type().Elem()))
+		}
+		dst = dst.Elem()
 	}
 
 	// Save accumulated data.
-	switch t := dst; t.Kind() {
+	switch dst.Kind() {
 	case reflect.Invalid:
-		// Probably a comment.
+		// Probably a commendst.
 	default:
-		return errors.New("cannot happen: unknown type " + t.Type().String())
+		return errors.New("cannot happen: unknown type " + dst.Type().String())
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		if !getInt64() {
+		itmp, err := strconv.ParseInt(string(src), 10, dst.Type().Bits())
+		if err != nil {
 			return err
 		}
-		t.SetInt(itmp)
+		dst.SetInt(itmp)
 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		if !getUint64() {
+		utmp, err := strconv.ParseUint(string(src), 10, dst.Type().Bits())
+		if err != nil {
 			return err
 		}
-		t.SetUint(utmp)
+		dst.SetUint(utmp)
 	case reflect.Float32, reflect.Float64:
-		if !getFloat64() {
+		ftmp, err := strconv.ParseFloat(string(src), dst.Type().Bits())
+		if err != nil {
 			return err
 		}
-		t.SetFloat(ftmp)
+		dst.SetFloat(ftmp)
 	case reflect.Bool:
 		value, err := strconv.ParseBool(strings.TrimSpace(string(src)))
 		if err != nil {
 			return err
 		}
-		t.SetBool(value)
+		dst.SetBool(value)
 	case reflect.String:
-		t.SetString(string(src))
+		dst.SetString(string(src))
 	case reflect.Slice:
 		if len(src) == 0 {
 			// non-nil to flag presence
 			src = []byte{}
 		}
-		t.SetBytes(src)
+		dst.SetBytes(src)
 	case reflect.Struct:
-		if t.Type() == timeType {
+		if dst.Type() == timeType {
 			tv, err := time.Parse(time.RFC3339, string(src))
 			if err != nil {
 				return err
 			}
-			t.Set(reflect.ValueOf(tv))
+			dst.Set(reflect.ValueOf(tv))
 		}
 	}
 	return nil
@@ -461,7 +451,7 @@ Loop:
 		}
 		if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
 			// It's a perfect match, unmarshal the field.
-			return true, p.unmarshal(sv.FieldByIndex(finfo.idx), start)
+			return true, p.unmarshal(finfo.value(sv), start)
 		}
 		if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
 			// It's a prefix for the field. Break and recurse
diff --git a/src/pkg/encoding/xml/read_test.go b/src/pkg/encoding/xml/read_test.go
index 8df09b3..b45e2f0 100644
--- a/src/pkg/encoding/xml/read_test.go
+++ b/src/pkg/encoding/xml/read_test.go
@@ -355,3 +355,47 @@ func TestUnmarshalWithoutNameType(t *testing.T) {
 		t.Fatalf("have %v\nwant %v", x.Attr, OK)
 	}
 }
+
+func TestUnmarshalAttr(t *testing.T) {
+	type ParamVal struct {
+		Int int `xml:"int,attr"`
+	}
+
+	type ParamPtr struct {
+		Int *int `xml:"int,attr"`
+	}
+
+	type ParamStringPtr struct {
+		Int *string `xml:"int,attr"`
+	}
+
+	x := []byte(`<Param int="1" />`)
+
+	p1 := &ParamPtr{}
+	if err := Unmarshal(x, p1); err != nil {
+		t.Fatalf("Unmarshal: %s", err)
+	}
+	if p1.Int == nil {
+		t.Fatalf("Unmarshal failed in to *int field")
+	} else if *p1.Int != 1 {
+		t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p1.Int, 1)
+	}
+
+	p2 := &ParamVal{}
+	if err := Unmarshal(x, p2); err != nil {
+		t.Fatalf("Unmarshal: %s", err)
+	}
+	if p2.Int != 1 {
+		t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p2.Int, 1)
+	}
+
+	p3 := &ParamStringPtr{}
+	if err := Unmarshal(x, p3); err != nil {
+		t.Fatalf("Unmarshal: %s", err)
+	}
+	if p3.Int == nil {
+		t.Fatalf("Unmarshal failed in to *string field")
+	} else if *p3.Int != "1" {
+		t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p3.Int, 1)
+	}
+}
diff --git a/src/pkg/encoding/xml/typeinfo.go b/src/pkg/encoding/xml/typeinfo.go
index 8e2e450..bbeb28d 100644
--- a/src/pkg/encoding/xml/typeinfo.go
+++ b/src/pkg/encoding/xml/typeinfo.go
@@ -66,10 +66,14 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
 
 			// For embedded structs, embed its fields.
 			if f.Anonymous {
-				if f.Type.Kind() != reflect.Struct {
+				t := f.Type
+				if t.Kind() == reflect.Ptr {
+					t = t.Elem()
+				}
+				if t.Kind() != reflect.Struct {
 					continue
 				}
-				inner, err := getTypeInfo(f.Type)
+				inner, err := getTypeInfo(t)
 				if err != nil {
 					return nil, err
 				}
@@ -150,6 +154,9 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
 			// This will also catch multiple modes in a single field.
 			valid = false
 		}
+		if finfo.flags&fMode == fAny {
+			finfo.flags |= fElement
+		}
 		if finfo.flags&fOmitEmpty != 0 && finfo.flags&(fElement|fAttr) == 0 {
 			valid = false
 		}
@@ -327,3 +334,22 @@ type TagPathError struct {
 func (e *TagPathError) Error() string {
 	return fmt.Sprintf("%s field %q with tag %q conflicts with field %q with tag %q", e.Struct, e.Field1, e.Tag1, e.Field2, e.Tag2)
 }
+
+// value returns v's field value corresponding to finfo.
+// It's equivalent to v.FieldByIndex(finfo.idx), but initializes
+// and dereferences pointers as necessary.
+func (finfo *fieldInfo) value(v reflect.Value) reflect.Value {
+	for i, x := range finfo.idx {
+		if i > 0 {
+			t := v.Type()
+			if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct {
+				if v.IsNil() {
+					v.Set(reflect.New(v.Type().Elem()))
+				}
+				v = v.Elem()
+			}
+		}
+		v = v.Field(x)
+	}
+	return v
+}
diff --git a/src/pkg/encoding/xml/xml.go b/src/pkg/encoding/xml/xml.go
index 5066f5c..143fec5 100644
--- a/src/pkg/encoding/xml/xml.go
+++ b/src/pkg/encoding/xml/xml.go
@@ -181,7 +181,6 @@ type Decoder struct {
 	ns        map[string]string
 	err       error
 	line      int
-	tmp       [32]byte
 }
 
 // NewDecoder creates a new XML parser reading from r.
@@ -584,6 +583,7 @@ func (d *Decoder) RawToken() (Token, error) {
 			if inquote == 0 && b == '>' && depth == 0 {
 				break
 			}
+		HandleB:
 			d.buf.WriteByte(b)
 			switch {
 			case b == inquote:
@@ -599,7 +599,35 @@ func (d *Decoder) RawToken() (Token, error) {
 				depth--
 
 			case b == '<' && inquote == 0:
-				depth++
+				// Look for <!-- to begin comment.
+				s := "!--"
+				for i := 0; i < len(s); i++ {
+					if b, ok = d.mustgetc(); !ok {
+						return nil, d.err
+					}
+					if b != s[i] {
+						for j := 0; j < i; j++ {
+							d.buf.WriteByte(s[j])
+						}
+						depth++
+						goto HandleB
+					}
+				}
+
+				// Remove < that was written above.
+				d.buf.Truncate(d.buf.Len() - 1)
+
+				// Look for terminator.
+				var b0, b1 byte
+				for {
+					if b, ok = d.mustgetc(); !ok {
+						return nil, d.err
+					}
+					if b0 == '-' && b1 == '-' && b == '>' {
+						break
+					}
+					b0, b1 = b1, b
+				}
 			}
 		}
 		return Directive(d.buf.Bytes()), nil
@@ -848,78 +876,103 @@ Input:
 			// XML in all its glory allows a document to define and use
 			// its own character names with <!ENTITY ...> directives.
 			// Parsers are required to recognize lt, gt, amp, apos, and quot
-			// even if they have not been declared.  That's all we allow.
-			var i int
-			for i = 0; i < len(d.tmp); i++ {
-				var ok bool
-				d.tmp[i], ok = d.getc()
-				if !ok {
-					if d.err == io.EOF {
-						d.err = d.syntaxError("unexpected EOF")
-					}
+			// even if they have not been declared.
+			before := d.buf.Len()
+			d.buf.WriteByte('&')
+			var ok bool
+			var text string
+			var haveText bool
+			if b, ok = d.mustgetc(); !ok {
+				return nil
+			}
+			if b == '#' {
+				d.buf.WriteByte(b)
+				if b, ok = d.mustgetc(); !ok {
 					return nil
 				}
-				c := d.tmp[i]
-				if c == ';' {
-					break
-				}
-				if 'a' <= c && c <= 'z' ||
-					'A' <= c && c <= 'Z' ||
-					'0' <= c && c <= '9' ||
-					c == '_' || c == '#' {
-					continue
+				base := 10
+				if b == 'x' {
+					base = 16
+					d.buf.WriteByte(b)
+					if b, ok = d.mustgetc(); !ok {
+						return nil
+					}
 				}
-				d.ungetc(c)
-				break
-			}
-			s := string(d.tmp[0:i])
-			if i >= len(d.tmp) {
-				if !d.Strict {
-					b0, b1 = 0, 0
-					d.buf.WriteByte('&')
-					d.buf.Write(d.tmp[0:i])
-					continue Input
+				start := d.buf.Len()
+				for '0' <= b && b <= '9' ||
+					base == 16 && 'a' <= b && b <= 'f' ||
+					base == 16 && 'A' <= b && b <= 'F' {
+					d.buf.WriteByte(b)
+					if b, ok = d.mustgetc(); !ok {
+						return nil
+					}
 				}
-				d.err = d.syntaxError("character entity expression &" + s + "... too long")
-				return nil
-			}
-			var haveText bool
-			var text string
-			if i >= 2 && s[0] == '#' {
-				var n uint64
-				var err error
-				if i >= 3 && s[1] == 'x' {
-					n, err = strconv.ParseUint(s[2:], 16, 64)
+				if b != ';' {
+					d.ungetc(b)
 				} else {
-					n, err = strconv.ParseUint(s[1:], 10, 64)
-				}
-				if err == nil && n <= unicode.MaxRune {
-					text = string(n)
-					haveText = true
+					s := string(d.buf.Bytes()[start:])
+					d.buf.WriteByte(';')
+					n, err := strconv.ParseUint(s, base, 64)
+					if err == nil && n <= unicode.MaxRune {
+						text = string(n)
+						haveText = true
+					}
 				}
 			} else {
-				if r, ok := entity[s]; ok {
-					text = string(r)
-					haveText = true
-				} else if d.Entity != nil {
-					text, haveText = d.Entity[s]
+				d.ungetc(b)
+				if !d.readName() {
+					if d.err != nil {
+						return nil
+					}
+					ok = false
 				}
-			}
-			if !haveText {
-				if !d.Strict {
-					b0, b1 = 0, 0
-					d.buf.WriteByte('&')
-					d.buf.Write(d.tmp[0:i])
-					continue Input
+				if b, ok = d.mustgetc(); !ok {
+					return nil
 				}
-				d.err = d.syntaxError("invalid character entity &" + s + ";")
-				return nil
+				if b != ';' {
+					d.ungetc(b)
+				} else {
+					name := d.buf.Bytes()[before+1:]
+					d.buf.WriteByte(';')
+					if isName(name) {
+						s := string(name)
+						if r, ok := entity[s]; ok {
+							text = string(r)
+							haveText = true
+						} else if d.Entity != nil {
+							text, haveText = d.Entity[s]
+						}
+					}
+				}
+			}
+
+			if haveText {
+				d.buf.Truncate(before)
+				d.buf.Write([]byte(text))
+				b0, b1 = 0, 0
+				continue Input
 			}
-			d.buf.Write([]byte(text))
-			b0, b1 = 0, 0
-			continue Input
+			if !d.Strict {
+				b0, b1 = 0, 0
+				continue Input
+			}
+			ent := string(d.buf.Bytes()[before])
+			if ent[len(ent)-1] != ';' {
+				ent += " (no semicolon)"
+			}
+			d.err = d.syntaxError("invalid character entity " + ent)
+			return nil
 		}
-		d.buf.WriteByte(b)
+
+		// We must rewrite unescaped \r and \r\n into \n.
+		if b == '\r' {
+			d.buf.WriteByte('\n')
+		} else if b1 == '\r' && b == '\n' {
+			// Skip \r\n--we already wrote \n.
+		} else {
+			d.buf.WriteByte(b)
+		}
+
 		b0, b1 = b1, b
 	}
 	data := d.buf.Bytes()
@@ -940,20 +993,7 @@ Input:
 		}
 	}
 
-	// Must rewrite \r and \r\n into \n.
-	w := 0
-	for r := 0; r < len(data); r++ {
-		b := data[r]
-		if b == '\r' {
-			if r+1 < len(data) && data[r+1] == '\n' {
-				continue
-			}
-			b = '\n'
-		}
-		data[w] = b
-		w++
-	}
-	return data[0:w]
+	return data
 }
 
 // Decide whether the given rune is in the XML Character Range, per
@@ -989,18 +1029,34 @@ func (d *Decoder) nsname() (name Name, ok bool) {
 // Do not set d.err if the name is missing (unless unexpected EOF is received):
 // let the caller provide better context.
 func (d *Decoder) name() (s string, ok bool) {
+	d.buf.Reset()
+	if !d.readName() {
+		return "", false
+	}
+
+	// Now we check the characters.
+	s = d.buf.String()
+	if !isName([]byte(s)) {
+		d.err = d.syntaxError("invalid XML name: " + s)
+		return "", false
+	}
+	return s, true
+}
+
+// Read a name and append its bytes to d.buf.
+// The name is delimited by any single-byte character not valid in names.
+// All multi-byte characters are accepted; the caller must check their validity.
+func (d *Decoder) readName() (ok bool) {
 	var b byte
 	if b, ok = d.mustgetc(); !ok {
 		return
 	}
-
-	// As a first approximation, we gather the bytes [A-Za-z_:.-\x80-\xFF]*
 	if b < utf8.RuneSelf && !isNameByte(b) {
 		d.ungetc(b)
-		return "", false
+		return false
 	}
-	d.buf.Reset()
 	d.buf.WriteByte(b)
+
 	for {
 		if b, ok = d.mustgetc(); !ok {
 			return
@@ -1011,16 +1067,7 @@ func (d *Decoder) name() (s string, ok bool) {
 		}
 		d.buf.WriteByte(b)
 	}
-
-	// Then we check the characters.
-	s = d.buf.String()
-	for i, c := range s {
-		if !unicode.Is(first, c) && (i == 0 || !unicode.Is(second, c)) {
-			d.err = d.syntaxError("invalid XML name: " + s)
-			return "", false
-		}
-	}
-	return s, true
+	return true
 }
 
 func isNameByte(c byte) bool {
@@ -1030,6 +1077,30 @@ func isNameByte(c byte) bool {
 		c == '_' || c == ':' || c == '.' || c == '-'
 }
 
+func isName(s []byte) bool {
+	if len(s) == 0 {
+		return false
+	}
+	c, n := utf8.DecodeRune(s)
+	if c == utf8.RuneError && n == 1 {
+		return false
+	}
+	if !unicode.Is(first, c) {
+		return false
+	}
+	for n < len(s) {
+		s = s[n:]
+		c, n = utf8.DecodeRune(s)
+		if c == utf8.RuneError && n == 1 {
+			return false
+		}
+		if !unicode.Is(first, c) && !unicode.Is(second, c) {
+			return false
+		}
+	}
+	return true
+}
+
 // These tables were generated by cut and paste from Appendix B of
 // the XML spec at http://www.xml.com/axml/testaxml.htm
 // and then reformatting.  First corresponds to (Letter | '_' | ':')
@@ -1621,7 +1692,7 @@ var HTMLAutoClose = htmlAutoClose
 var htmlAutoClose = []string{
 	/*
 		hget http://www.w3.org/TR/html4/loose.dtd |
-		9 sed -n 's/<!ELEMENT (.*) - O EMPTY.+/	"\1",/p' | tr A-Z a-z
+		9 sed -n 's/<!ELEMENT ([^ ]*) +- O EMPTY.+/	"\1",/p' | tr A-Z a-z
 	*/
 	"basefont",
 	"br",
@@ -1631,7 +1702,7 @@ var htmlAutoClose = []string{
 	"param",
 	"hr",
 	"input",
-	"col     ",
+	"col",
 	"frame",
 	"isindex",
 	"base",
@@ -1644,11 +1715,14 @@ var (
 	esc_amp  = []byte("&")
 	esc_lt   = []byte("<")
 	esc_gt   = []byte(">")
+	esc_tab  = []byte("&#x9;")
+	esc_nl   = []byte("&#xA;")
+	esc_cr   = []byte("&#xD;")
 )
 
-// Escape writes to w the properly escaped XML equivalent
+// EscapeText writes to w the properly escaped XML equivalent
 // of the plain text data s.
-func Escape(w io.Writer, s []byte) {
+func EscapeText(w io.Writer, s []byte) error {
 	var esc []byte
 	last := 0
 	for i, c := range s {
@@ -1663,14 +1737,34 @@ func Escape(w io.Writer, s []byte) {
 			esc = esc_lt
 		case '>':
 			esc = esc_gt
+		case '\t':
+			esc = esc_tab
+		case '\n':
+			esc = esc_nl
+		case '\r':
+			esc = esc_cr
 		default:
 			continue
 		}
-		w.Write(s[last:i])
-		w.Write(esc)
+		if _, err := w.Write(s[last:i]); err != nil {
+			return err
+		}
+		if _, err := w.Write(esc); err != nil {
+			return err
+		}
 		last = i + 1
 	}
-	w.Write(s[last:])
+	if _, err := w.Write(s[last:]); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Escape is like EscapeText but omits the error return value.
+// It is provided for backwards compatibility with Go 1.0.
+// Code targeting Go 1.1 or later should use EscapeText.
+func Escape(w io.Writer, s []byte) {
+	EscapeText(w, s)
 }
 
 // procInstEncoding parses the `encoding="..."` or `encoding='...'`
diff --git a/src/pkg/encoding/xml/xml_test.go b/src/pkg/encoding/xml/xml_test.go
index 1d0696c..54dab54 100644
--- a/src/pkg/encoding/xml/xml_test.go
+++ b/src/pkg/encoding/xml/xml_test.go
@@ -5,6 +5,7 @@
 package xml
 
 import (
+	"fmt"
 	"io"
 	"reflect"
 	"strings"
@@ -18,6 +19,7 @@ const testInput = `
 <body xmlns:foo="ns1" xmlns="ns2" xmlns:tag="ns3" ` +
 	"\r\n\t" + `  >
   <hello lang="en">World <>'" &#x767d;鵬翔</hello>
+  <query>&何; &is-it;</query>
   <goodbye />
   <outer foo:attr="value" xmlns:tag="ns4">
     <inner/>
@@ -27,6 +29,8 @@ const testInput = `
   </tag:name>
 </body><!-- missing final newline -->`
 
+var testEntity = map[string]string{"何": "What", "is-it": "is it?"}
+
 var rawTokens = []Token{
 	CharData("\n"),
 	ProcInst{"xml", []byte(`version="1.0" encoding="UTF-8"`)},
@@ -40,6 +44,10 @@ var rawTokens = []Token{
 	CharData("World <>'\" 白鵬翔"),
 	EndElement{Name{"", "hello"}},
 	CharData("\n  "),
+	StartElement{Name{"", "query"}, []Attr{}},
+	CharData("What is it?"),
+	EndElement{Name{"", "query"}},
+	CharData("\n  "),
 	StartElement{Name{"", "goodbye"}, []Attr{}},
 	EndElement{Name{"", "goodbye"}},
 	CharData("\n  "),
@@ -73,6 +81,10 @@ var cookedTokens = []Token{
 	CharData("World <>'\" 白鵬翔"),
 	EndElement{Name{"ns2", "hello"}},
 	CharData("\n  "),
+	StartElement{Name{"ns2", "query"}, []Attr{}},
+	CharData("What is it?"),
+	EndElement{Name{"ns2", "query"}},
+	CharData("\n  "),
 	StartElement{Name{"ns2", "goodbye"}, []Attr{}},
 	EndElement{Name{"ns2", "goodbye"}},
 	CharData("\n  "),
@@ -155,9 +167,65 @@ var xmlInput = []string{
 
 func TestRawToken(t *testing.T) {
 	d := NewDecoder(strings.NewReader(testInput))
+	d.Entity = testEntity
 	testRawToken(t, d, rawTokens)
 }
 
+const nonStrictInput = `
+<tag>non&entity</tag>
+<tag>&unknown;entity</tag>
+<tag>&#123</tag>
+<tag>&#zzz;</tag>
+<tag>&なまえ3;</tag>
+<tag>&lt-gt;</tag>
+<tag>&;</tag>
+<tag>&0a;</tag>
+`
+
+var nonStringEntity = map[string]string{"": "oops!", "0a": "oops!"}
+
+var nonStrictTokens = []Token{
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("non&entity"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&unknown;entity"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&#123"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&#zzz;"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&なまえ3;"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&lt-gt;"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&;"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("&0a;"),
+	EndElement{Name{"", "tag"}},
+	CharData("\n"),
+}
+
+func TestNonStrictRawToken(t *testing.T) {
+	d := NewDecoder(strings.NewReader(nonStrictInput))
+	d.Strict = false
+	testRawToken(t, d, nonStrictTokens)
+}
+
 type downCaser struct {
 	t *testing.T
 	r io.ByteReader
@@ -219,7 +287,18 @@ func testRawToken(t *testing.T, d *Decoder, rawTokens []Token) {
 			t.Fatalf("token %d: unexpected error: %s", i, err)
 		}
 		if !reflect.DeepEqual(have, want) {
-			t.Errorf("token %d = %#v want %#v", i, have, want)
+			var shave, swant string
+			if _, ok := have.(CharData); ok {
+				shave = fmt.Sprintf("CharData(%q)", have)
+			} else {
+				shave = fmt.Sprintf("%#v", have)
+			}
+			if _, ok := want.(CharData); ok {
+				swant = fmt.Sprintf("CharData(%q)", want)
+			} else {
+				swant = fmt.Sprintf("%#v", want)
+			}
+			t.Errorf("token %d = %s, want %s", i, shave, swant)
 		}
 	}
 }
@@ -272,6 +351,7 @@ func TestNestedDirectives(t *testing.T) {
 
 func TestToken(t *testing.T) {
 	d := NewDecoder(strings.NewReader(testInput))
+	d.Entity = testEntity
 
 	for i, want := range cookedTokens {
 		have, err := d.Token()
@@ -531,8 +611,8 @@ var characterTests = []struct {
 	{"\xef\xbf\xbe<doc/>", "illegal character code U+FFFE"},
 	{"<?xml version=\"1.0\"?><doc>\r\n<hiya/>\x07<toots/></doc>", "illegal character code U+0007"},
 	{"<?xml version=\"1.0\"?><doc \x12='value'>what's up</doc>", "expected attribute name in element"},
-	{"<doc>&\x01;</doc>", "invalid character entity &;"},
-	{"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity &;"},
+	{"<doc>&\x01;</doc>", "invalid character entity & (no semicolon)"},
+	{"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity & (no semicolon)"},
 }
 
 func TestDisallowedCharacters(t *testing.T) {
@@ -576,3 +656,50 @@ func TestProcInstEncoding(t *testing.T) {
 		}
 	}
 }
+
+// Ensure that directives with comments include the complete
+// text of any nested directives.
+
+var directivesWithCommentsInput = `
+<!DOCTYPE [<!-- a comment --><!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]>
+<!DOCTYPE [<!ENTITY go "Golang"><!-- a comment-->]>
+<!DOCTYPE <!-> <!> <!----> <!-->--> <!--->--> [<!ENTITY go "Golang"><!-- a comment-->]>
+`
+
+var directivesWithCommentsTokens = []Token{
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY go "Golang">]`),
+	CharData("\n"),
+	Directive(`DOCTYPE <!-> <!>    [<!ENTITY go "Golang">]`),
+	CharData("\n"),
+}
+
+func TestDirectivesWithComments(t *testing.T) {
+	d := NewDecoder(strings.NewReader(directivesWithCommentsInput))
+
+	for i, want := range directivesWithCommentsTokens {
+		have, err := d.Token()
+		if err != nil {
+			t.Fatalf("token %d: unexpected error: %s", i, err)
+		}
+		if !reflect.DeepEqual(have, want) {
+			t.Errorf("token %d = %#v want %#v", i, have, want)
+		}
+	}
+}
+
+// Writer whose Write method always returns an error.
+type errWriter struct{}
+
+func (errWriter) Write(p []byte) (n int, err error) { return 0, fmt.Errorf("unwritable") }
+
+func TestEscapeTextIOErrors(t *testing.T) {
+	expectErr := "unwritable"
+	err := EscapeText(errWriter{}, []byte{'A'})
+
+	if err == nil || err.Error() != expectErr {
+		t.Errorf("EscapeTest = [error] %v, want %v", err, expectErr)
+	}
+}
diff --git a/src/pkg/exp/norm/Makefile b/src/pkg/exp/norm/Makefile
new file mode 100644
index 0000000..f278eb0
--- /dev/null
+++ b/src/pkg/exp/norm/Makefile
@@ -0,0 +1,30 @@
+# 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.
+
+maketables: maketables.go triegen.go
+	go build $^
+
+maketesttables: maketesttables.go triegen.go
+	go build $^
+
+normregtest: normregtest.go
+	go build $^
+
+tables:	maketables
+	./maketables > tables.go
+	gofmt -w tables.go
+
+trietesttables: maketesttables
+	./maketesttables > triedata_test.go
+	gofmt -w triedata_test.go
+
+# Downloads from www.unicode.org, so not part
+# of standard test scripts.
+test: testtables regtest
+
+testtables: maketables
+	./maketables -test -tables=
+
+regtest: normregtest
+	./normregtest
diff --git a/src/pkg/exp/norm/composition.go b/src/pkg/exp/norm/composition.go
new file mode 100644
index 0000000..2d52f99
--- /dev/null
+++ b/src/pkg/exp/norm/composition.go
@@ -0,0 +1,382 @@
+// 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 norm
+
+import "unicode/utf8"
+
+const (
+	maxCombiningChars = 30
+	maxBufferSize     = maxCombiningChars + 2 // +1 to hold starter +1 to hold CGJ
+	maxBackRunes      = maxCombiningChars - 1
+	maxNFCExpansion   = 3  // NFC(0x1D160)
+	maxNFKCExpansion  = 18 // NFKC(0xFDFA)
+
+	maxByteBufferSize = utf8.UTFMax * maxBufferSize // 128
+)
+
+// reorderBuffer is used to normalize a single segment.  Characters inserted with
+// insert are decomposed and reordered based on CCC. The compose method can
+// be used to recombine characters.  Note that the byte buffer does not hold
+// the UTF-8 characters in order.  Only the rune array is maintained in sorted
+// order. flush writes the resulting segment to a byte array.
+type reorderBuffer struct {
+	rune  [maxBufferSize]Properties // Per character info.
+	byte  [maxByteBufferSize]byte   // UTF-8 buffer. Referenced by runeInfo.pos.
+	nrune int                       // Number of runeInfos.
+	nbyte uint8                     // Number or bytes.
+	f     formInfo
+
+	src      input
+	nsrc     int
+	tmpBytes input
+}
+
+func (rb *reorderBuffer) init(f Form, src []byte) {
+	rb.f = *formTable[f]
+	rb.src.setBytes(src)
+	rb.nsrc = len(src)
+}
+
+func (rb *reorderBuffer) initString(f Form, src string) {
+	rb.f = *formTable[f]
+	rb.src.setString(src)
+	rb.nsrc = len(src)
+}
+
+// reset discards all characters from the buffer.
+func (rb *reorderBuffer) reset() {
+	rb.nrune = 0
+	rb.nbyte = 0
+}
+
+// flush appends the normalized segment to out and resets rb.
+func (rb *reorderBuffer) flush(out []byte) []byte {
+	for i := 0; i < rb.nrune; i++ {
+		start := rb.rune[i].pos
+		end := start + rb.rune[i].size
+		out = append(out, rb.byte[start:end]...)
+	}
+	rb.reset()
+	return out
+}
+
+// flushCopy copies the normalized segment to buf and resets rb.
+// It returns the number of bytes written to buf.
+func (rb *reorderBuffer) flushCopy(buf []byte) int {
+	p := 0
+	for i := 0; i < rb.nrune; i++ {
+		runep := rb.rune[i]
+		p += copy(buf[p:], rb.byte[runep.pos:runep.pos+runep.size])
+	}
+	rb.reset()
+	return p
+}
+
+// insertOrdered inserts a rune in the buffer, ordered by Canonical Combining Class.
+// It returns false if the buffer is not large enough to hold the rune.
+// It is used internally by insert and insertString only.
+func (rb *reorderBuffer) insertOrdered(info Properties) bool {
+	n := rb.nrune
+	if n >= maxCombiningChars+1 {
+		return false
+	}
+	b := rb.rune[:]
+	cc := info.ccc
+	if cc > 0 {
+		// Find insertion position + move elements to make room.
+		for ; n > 0; n-- {
+			if b[n-1].ccc <= cc {
+				break
+			}
+			b[n] = b[n-1]
+		}
+	}
+	rb.nrune += 1
+	pos := uint8(rb.nbyte)
+	rb.nbyte += utf8.UTFMax
+	info.pos = pos
+	b[n] = info
+	return true
+}
+
+// insert inserts the given rune in the buffer ordered by CCC.
+// It returns true if the buffer was large enough to hold the decomposed rune.
+func (rb *reorderBuffer) insert(src input, i int, info Properties) bool {
+	if rune := src.hangul(i); rune != 0 {
+		return rb.decomposeHangul(rune)
+	}
+	if info.hasDecomposition() {
+		return rb.insertDecomposed(info.Decomposition())
+	}
+	return rb.insertSingle(src, i, info)
+}
+
+// insertDecomposed inserts an entry in to the reorderBuffer for each rune
+// in dcomp.  dcomp must be a sequence of decomposed UTF-8-encoded runes.
+func (rb *reorderBuffer) insertDecomposed(dcomp []byte) bool {
+	saveNrune, saveNbyte := rb.nrune, rb.nbyte
+	rb.tmpBytes.setBytes(dcomp)
+	for i := 0; i < len(dcomp); {
+		info := rb.f.info(rb.tmpBytes, i)
+		pos := rb.nbyte
+		if !rb.insertOrdered(info) {
+			rb.nrune, rb.nbyte = saveNrune, saveNbyte
+			return false
+		}
+		i += copy(rb.byte[pos:], dcomp[i:i+int(info.size)])
+	}
+	return true
+}
+
+// insertSingle inserts an entry in the reorderBuffer for the rune at
+// position i. info is the runeInfo for the rune at position i.
+func (rb *reorderBuffer) insertSingle(src input, i int, info Properties) bool {
+	// insertOrder changes nbyte
+	pos := rb.nbyte
+	if !rb.insertOrdered(info) {
+		return false
+	}
+	src.copySlice(rb.byte[pos:], i, i+int(info.size))
+	return true
+}
+
+// appendRune inserts a rune at the end of the buffer. It is used for Hangul.
+func (rb *reorderBuffer) appendRune(r rune) {
+	bn := rb.nbyte
+	sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
+	rb.nbyte += utf8.UTFMax
+	rb.rune[rb.nrune] = Properties{pos: bn, size: uint8(sz)}
+	rb.nrune++
+}
+
+// assignRune sets a rune at position pos. It is used for Hangul and recomposition.
+func (rb *reorderBuffer) assignRune(pos int, r rune) {
+	bn := rb.rune[pos].pos
+	sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
+	rb.rune[pos] = Properties{pos: bn, size: uint8(sz)}
+}
+
+// runeAt returns the rune at position n. It is used for Hangul and recomposition.
+func (rb *reorderBuffer) runeAt(n int) rune {
+	inf := rb.rune[n]
+	r, _ := utf8.DecodeRune(rb.byte[inf.pos : inf.pos+inf.size])
+	return r
+}
+
+// bytesAt returns the UTF-8 encoding of the rune at position n.
+// It is used for Hangul and recomposition.
+func (rb *reorderBuffer) bytesAt(n int) []byte {
+	inf := rb.rune[n]
+	return rb.byte[inf.pos : int(inf.pos)+int(inf.size)]
+}
+
+// For Hangul we combine algorithmically, instead of using tables.
+const (
+	hangulBase  = 0xAC00 // UTF-8(hangulBase) -> EA B0 80
+	hangulBase0 = 0xEA
+	hangulBase1 = 0xB0
+	hangulBase2 = 0x80
+
+	hangulEnd  = hangulBase + jamoLVTCount // UTF-8(0xD7A4) -> ED 9E A4
+	hangulEnd0 = 0xED
+	hangulEnd1 = 0x9E
+	hangulEnd2 = 0xA4
+
+	jamoLBase  = 0x1100 // UTF-8(jamoLBase) -> E1 84 00
+	jamoLBase0 = 0xE1
+	jamoLBase1 = 0x84
+	jamoLEnd   = 0x1113
+	jamoVBase  = 0x1161
+	jamoVEnd   = 0x1176
+	jamoTBase  = 0x11A7
+	jamoTEnd   = 0x11C3
+
+	jamoTCount   = 28
+	jamoVCount   = 21
+	jamoVTCount  = 21 * 28
+	jamoLVTCount = 19 * 21 * 28
+)
+
+const hangulUTF8Size = 3
+
+func isHangul(b []byte) bool {
+	if len(b) < hangulUTF8Size {
+		return false
+	}
+	b0 := b[0]
+	if b0 < hangulBase0 {
+		return false
+	}
+	b1 := b[1]
+	switch {
+	case b0 == hangulBase0:
+		return b1 >= hangulBase1
+	case b0 < hangulEnd0:
+		return true
+	case b0 > hangulEnd0:
+		return false
+	case b1 < hangulEnd1:
+		return true
+	}
+	return b1 == hangulEnd1 && b[2] < hangulEnd2
+}
+
+func isHangulString(b string) bool {
+	if len(b) < hangulUTF8Size {
+		return false
+	}
+	b0 := b[0]
+	if b0 < hangulBase0 {
+		return false
+	}
+	b1 := b[1]
+	switch {
+	case b0 == hangulBase0:
+		return b1 >= hangulBase1
+	case b0 < hangulEnd0:
+		return true
+	case b0 > hangulEnd0:
+		return false
+	case b1 < hangulEnd1:
+		return true
+	}
+	return b1 == hangulEnd1 && b[2] < hangulEnd2
+}
+
+// Caller must ensure len(b) >= 2.
+func isJamoVT(b []byte) bool {
+	// True if (rune & 0xff00) == jamoLBase
+	return b[0] == jamoLBase0 && (b[1]&0xFC) == jamoLBase1
+}
+
+func isHangulWithoutJamoT(b []byte) bool {
+	c, _ := utf8.DecodeRune(b)
+	c -= hangulBase
+	return c < jamoLVTCount && c%jamoTCount == 0
+}
+
+// decomposeHangul writes the decomposed Hangul to buf and returns the number
+// of bytes written.  len(buf) should be at least 9.
+func decomposeHangul(buf []byte, r rune) int {
+	const JamoUTF8Len = 3
+	r -= hangulBase
+	x := r % jamoTCount
+	r /= jamoTCount
+	utf8.EncodeRune(buf, jamoLBase+r/jamoVCount)
+	utf8.EncodeRune(buf[JamoUTF8Len:], jamoVBase+r%jamoVCount)
+	if x != 0 {
+		utf8.EncodeRune(buf[2*JamoUTF8Len:], jamoTBase+x)
+		return 3 * JamoUTF8Len
+	}
+	return 2 * JamoUTF8Len
+}
+
+// decomposeHangul algorithmically decomposes a Hangul rune into
+// its Jamo components.
+// See http://unicode.org/reports/tr15/#Hangul for details on decomposing Hangul.
+func (rb *reorderBuffer) decomposeHangul(r rune) bool {
+	b := rb.rune[:]
+	n := rb.nrune
+	if n+3 > len(b) {
+		return false
+	}
+	r -= hangulBase
+	x := r % jamoTCount
+	r /= jamoTCount
+	rb.appendRune(jamoLBase + r/jamoVCount)
+	rb.appendRune(jamoVBase + r%jamoVCount)
+	if x != 0 {
+		rb.appendRune(jamoTBase + x)
+	}
+	return true
+}
+
+// combineHangul algorithmically combines Jamo character components into Hangul.
+// See http://unicode.org/reports/tr15/#Hangul for details on combining Hangul.
+func (rb *reorderBuffer) combineHangul(s, i, k int) {
+	b := rb.rune[:]
+	bn := rb.nrune
+	for ; i < bn; i++ {
+		cccB := b[k-1].ccc
+		cccC := b[i].ccc
+		if cccB == 0 {
+			s = k - 1
+		}
+		if s != k-1 && cccB >= cccC {
+			// b[i] is blocked by greater-equal cccX below it
+			b[k] = b[i]
+			k++
+		} else {
+			l := rb.runeAt(s) // also used to compare to hangulBase
+			v := rb.runeAt(i) // also used to compare to jamoT
+			switch {
+			case jamoLBase <= l && l < jamoLEnd &&
+				jamoVBase <= v && v < jamoVEnd:
+				// 11xx plus 116x to LV
+				rb.assignRune(s, hangulBase+
+					(l-jamoLBase)*jamoVTCount+(v-jamoVBase)*jamoTCount)
+			case hangulBase <= l && l < hangulEnd &&
+				jamoTBase < v && v < jamoTEnd &&
+				((l-hangulBase)%jamoTCount) == 0:
+				// ACxx plus 11Ax to LVT
+				rb.assignRune(s, l+v-jamoTBase)
+			default:
+				b[k] = b[i]
+				k++
+			}
+		}
+	}
+	rb.nrune = k
+}
+
+// compose recombines the runes in the buffer.
+// It should only be used to recompose a single segment, as it will not
+// handle alternations between Hangul and non-Hangul characters correctly.
+func (rb *reorderBuffer) compose() {
+	// UAX #15, section X5 , including Corrigendum #5
+	// "In any character sequence beginning with starter S, a character C is
+	//  blocked from S if and only if there is some character B between S
+	//  and C, and either B is a starter or it has the same or higher
+	//  combining class as C."
+	bn := rb.nrune
+	if bn == 0 {
+		return
+	}
+	k := 1
+	b := rb.rune[:]
+	for s, i := 0, 1; i < bn; i++ {
+		if isJamoVT(rb.bytesAt(i)) {
+			// Redo from start in Hangul mode. Necessary to support
+			// U+320E..U+321E in NFKC mode.
+			rb.combineHangul(s, i, k)
+			return
+		}
+		ii := b[i]
+		// We can only use combineForward as a filter if we later
+		// get the info for the combined character. This is more
+		// expensive than using the filter. Using combinesBackward()
+		// is safe.
+		if ii.combinesBackward() {
+			cccB := b[k-1].ccc
+			cccC := ii.ccc
+			blocked := false // b[i] blocked by starter or greater or equal CCC?
+			if cccB == 0 {
+				s = k - 1
+			} else {
+				blocked = s != k-1 && cccB >= cccC
+			}
+			if !blocked {
+				combined := combine(rb.runeAt(s), rb.runeAt(i))
+				if combined != 0 {
+					rb.assignRune(s, combined)
+					continue
+				}
+			}
+		}
+		b[k] = b[i]
+		k++
+	}
+	rb.nrune = k
+}
diff --git a/src/pkg/exp/norm/composition_test.go b/src/pkg/exp/norm/composition_test.go
new file mode 100644
index 0000000..976aa21
--- /dev/null
+++ b/src/pkg/exp/norm/composition_test.go
@@ -0,0 +1,143 @@
+// 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 norm
+
+import "testing"
+
+// TestCase is used for most tests.
+type TestCase struct {
+	in  []rune
+	out []rune
+}
+
+type insertFunc func(rb *reorderBuffer, r rune) bool
+
+func insert(rb *reorderBuffer, r rune) bool {
+	src := inputString(string(r))
+	return rb.insert(src, 0, rb.f.info(src, 0))
+}
+
+func runTests(t *testing.T, name string, fm Form, f insertFunc, tests []TestCase) {
+	rb := reorderBuffer{}
+	rb.init(fm, nil)
+	for i, test := range tests {
+		rb.reset()
+		for j, rune := range test.in {
+			b := []byte(string(rune))
+			src := inputBytes(b)
+			if !rb.insert(src, 0, rb.f.info(src, 0)) {
+				t.Errorf("%s:%d: insert failed for rune %d", name, i, j)
+			}
+		}
+		if rb.f.composing {
+			rb.compose()
+		}
+		if rb.nrune != len(test.out) {
+			t.Errorf("%s:%d: length = %d; want %d", name, i, rb.nrune, len(test.out))
+			continue
+		}
+		for j, want := range test.out {
+			found := rune(rb.runeAt(j))
+			if found != want {
+				t.Errorf("%s:%d: runeAt(%d) = %U; want %U", name, i, j, found, want)
+			}
+		}
+	}
+}
+
+type flushFunc func(rb *reorderBuffer) []byte
+
+func testFlush(t *testing.T, name string, fn flushFunc) {
+	rb := reorderBuffer{}
+	rb.init(NFC, nil)
+	out := fn(&rb)
+	if len(out) != 0 {
+		t.Errorf("%s: wrote bytes on flush of empty buffer. (len(out) = %d)", name, len(out))
+	}
+
+	for _, r := range []rune("world!") {
+		insert(&rb, r)
+	}
+
+	out = []byte("Hello ")
+	out = rb.flush(out)
+	want := "Hello world!"
+	if string(out) != want {
+		t.Errorf(`%s: output after flush was "%s"; want "%s"`, name, string(out), want)
+	}
+	if rb.nrune != 0 {
+		t.Errorf("%s: non-null size of info buffer (rb.nrune == %d)", name, rb.nrune)
+	}
+	if rb.nbyte != 0 {
+		t.Errorf("%s: non-null size of byte buffer (rb.nbyte == %d)", name, rb.nbyte)
+	}
+}
+
+func flushF(rb *reorderBuffer) []byte {
+	out := make([]byte, 0)
+	return rb.flush(out)
+}
+
+func flushCopyF(rb *reorderBuffer) []byte {
+	out := make([]byte, maxByteBufferSize)
+	n := rb.flushCopy(out)
+	return out[:n]
+}
+
+func TestFlush(t *testing.T) {
+	testFlush(t, "flush", flushF)
+	testFlush(t, "flushCopy", flushCopyF)
+}
+
+var insertTests = []TestCase{
+	{[]rune{'a'}, []rune{'a'}},
+	{[]rune{0x300}, []rune{0x300}},
+	{[]rune{0x300, 0x316}, []rune{0x316, 0x300}}, // CCC(0x300)==230; CCC(0x316)==220
+	{[]rune{0x316, 0x300}, []rune{0x316, 0x300}},
+	{[]rune{0x41, 0x316, 0x300}, []rune{0x41, 0x316, 0x300}},
+	{[]rune{0x41, 0x300, 0x316}, []rune{0x41, 0x316, 0x300}},
+	{[]rune{0x300, 0x316, 0x41}, []rune{0x316, 0x300, 0x41}},
+	{[]rune{0x41, 0x300, 0x40, 0x316}, []rune{0x41, 0x300, 0x40, 0x316}},
+}
+
+func TestInsert(t *testing.T) {
+	runTests(t, "TestInsert", NFD, insert, insertTests)
+}
+
+var decompositionNFDTest = []TestCase{
+	{[]rune{0xC0}, []rune{0x41, 0x300}},
+	{[]rune{0xAC00}, []rune{0x1100, 0x1161}},
+	{[]rune{0x01C4}, []rune{0x01C4}},
+	{[]rune{0x320E}, []rune{0x320E}},
+	{[]rune("음ẻ과"), []rune{0x110B, 0x1173, 0x11B7, 0x65, 0x309, 0x1100, 0x116A}},
+}
+
+var decompositionNFKDTest = []TestCase{
+	{[]rune{0xC0}, []rune{0x41, 0x300}},
+	{[]rune{0xAC00}, []rune{0x1100, 0x1161}},
+	{[]rune{0x01C4}, []rune{0x44, 0x5A, 0x030C}},
+	{[]rune{0x320E}, []rune{0x28, 0x1100, 0x1161, 0x29}},
+}
+
+func TestDecomposition(t *testing.T) {
+	runTests(t, "TestDecompositionNFD", NFD, insert, decompositionNFDTest)
+	runTests(t, "TestDecompositionNFKD", NFKD, insert, decompositionNFKDTest)
+}
+
+var compositionTest = []TestCase{
+	{[]rune{0x41, 0x300}, []rune{0xC0}},
+	{[]rune{0x41, 0x316}, []rune{0x41, 0x316}},
+	{[]rune{0x41, 0x300, 0x35D}, []rune{0xC0, 0x35D}},
+	{[]rune{0x41, 0x316, 0x300}, []rune{0xC0, 0x316}},
+	// blocking starter
+	{[]rune{0x41, 0x316, 0x40, 0x300}, []rune{0x41, 0x316, 0x40, 0x300}},
+	{[]rune{0x1100, 0x1161}, []rune{0xAC00}},
+	// parenthesized Hangul, alternate between ASCII and Hangul.
+	{[]rune{0x28, 0x1100, 0x1161, 0x29}, []rune{0x28, 0xAC00, 0x29}},
+}
+
+func TestComposition(t *testing.T) {
+	runTests(t, "TestComposition", NFC, insert, compositionTest)
+}
diff --git a/src/pkg/exp/norm/example_iter_test.go b/src/pkg/exp/norm/example_iter_test.go
new file mode 100644
index 0000000..edb9fcf
--- /dev/null
+++ b/src/pkg/exp/norm/example_iter_test.go
@@ -0,0 +1,81 @@
+// 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 norm_test
+
+import (
+	"bytes"
+	"exp/norm"
+	"fmt"
+	"unicode/utf8"
+)
+
+// EqualSimple uses a norm.Iter to compare two non-normalized
+// strings for equivalence.
+func EqualSimple(a, b string) bool {
+	var ia, ib norm.Iter
+	ia.InitString(norm.NFKD, a)
+	ib.InitString(norm.NFKD, b)
+	for !ia.Done() && !ib.Done() {
+		if !bytes.Equal(ia.Next(), ib.Next()) {
+			return false
+		}
+	}
+	return ia.Done() && ib.Done()
+}
+
+// FindPrefix finds the longest common prefix of ASCII characters
+// of a and b.
+func FindPrefix(a, b string) int {
+	i := 0
+	for ; i < len(a) && i < len(b) && a[i] < utf8.RuneSelf && a[i] == b[i]; i++ {
+	}
+	return i
+}
+
+// EqualOpt is like EqualSimple, but optimizes the special
+// case for ASCII characters.
+func EqualOpt(a, b string) bool {
+	n := FindPrefix(a, b)
+	a, b = a[n:], b[n:]
+	var ia, ib norm.Iter
+	ia.InitString(norm.NFKD, a)
+	ib.InitString(norm.NFKD, b)
+	for !ia.Done() && !ib.Done() {
+		if !bytes.Equal(ia.Next(), ib.Next()) {
+			return false
+		}
+		if n := int64(FindPrefix(a[ia.Pos():], b[ib.Pos():])); n != 0 {
+			ia.Seek(n, 1)
+			ib.Seek(n, 1)
+		}
+	}
+	return ia.Done() && ib.Done()
+}
+
+var compareTests = []struct{ a, b string }{
+	{"aaa", "aaa"},
+	{"aaa", "aab"},
+	{"a\u0300a", "\u00E0a"},
+	{"a\u0300\u0320b", "a\u0320\u0300b"},
+	{"\u1E0A\u0323", "\x44\u0323\u0307"},
+	// A character that decomposes into multiple segments
+	// spans several iterations.
+	{"\u3304", "\u30A4\u30CB\u30F3\u30AF\u3099"},
+}
+
+func ExampleIter() {
+	for i, t := range compareTests {
+		r0 := EqualSimple(t.a, t.b)
+		r1 := EqualOpt(t.a, t.b)
+		fmt.Printf("%d: %v %v\n", i, r0, r1)
+	}
+	// Output:
+	// 0: true true
+	// 1: false false
+	// 2: true true
+	// 3: true true
+	// 4: true true
+	// 5: true true
+}
diff --git a/src/pkg/exp/norm/forminfo.go b/src/pkg/exp/norm/forminfo.go
new file mode 100644
index 0000000..7f7ee72
--- /dev/null
+++ b/src/pkg/exp/norm/forminfo.go
@@ -0,0 +1,229 @@
+// 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 norm
+
+// This file contains Form-specific logic and wrappers for data in tables.go.
+
+// Rune info is stored in a separate trie per composing form. A composing form
+// and its corresponding decomposing form share the same trie.  Each trie maps
+// a rune to a uint16. The values take two forms.  For v >= 0x8000:
+//   bits
+//   0..8:   ccc
+//   9..12:  qcInfo (see below). isYesD is always true (no decompostion).
+//   16:     1
+// For v < 0x8000, the respective rune has a decomposition and v is an index
+// into a byte array of UTF-8 decomposition sequences and additional info and
+// has the form:
+//    <header> <decomp_byte>* [<tccc> [<lccc>]]
+// The header contains the number of bytes in the decomposition (excluding this
+// length byte). The two most significant bits of this length byte correspond
+// to bit 2 and 3 of qcIfo (see below).  The byte sequence itself starts at v+1.
+// The byte sequence is followed by a trailing and leading CCC if the values
+// for these are not zero.  The value of v determines which ccc are appended
+// to the sequences.  For v < firstCCC, there are none, for v >= firstCCC,
+// the sequence is followed by a trailing ccc, and for v >= firstLeadingCC
+// there is an additional leading ccc.
+
+const (
+	qcInfoMask      = 0xF  // to clear all but the relevant bits in a qcInfo
+	headerLenMask   = 0x3F // extract the length value from the header byte
+	headerFlagsMask = 0xC0 // extract the qcInfo bits from the header byte
+)
+
+// Properties provides access to normalization properties of a rune.
+type Properties struct {
+	pos   uint8  // start position in reorderBuffer; used in composition.go
+	size  uint8  // length of UTF-8 encoding of this rune
+	ccc   uint8  // leading canonical combining class (ccc if not decomposition)
+	tccc  uint8  // trailing canonical combining class (ccc if not decomposition)
+	flags qcInfo // quick check flags
+	index uint16
+}
+
+// functions dispatchable per form
+type lookupFunc func(b input, i int) Properties
+
+// formInfo holds Form-specific functions and tables.
+type formInfo struct {
+	form                     Form
+	composing, compatibility bool // form type
+	info                     lookupFunc
+	nextMain                 iterFunc
+}
+
+var formTable []*formInfo
+
+func init() {
+	formTable = make([]*formInfo, 4)
+
+	for i := range formTable {
+		f := &formInfo{}
+		formTable[i] = f
+		f.form = Form(i)
+		if Form(i) == NFKD || Form(i) == NFKC {
+			f.compatibility = true
+			f.info = lookupInfoNFKC
+		} else {
+			f.info = lookupInfoNFC
+		}
+		f.nextMain = nextDecomposed
+		if Form(i) == NFC || Form(i) == NFKC {
+			f.nextMain = nextComposed
+			f.composing = true
+		}
+	}
+}
+
+// We do not distinguish between boundaries for NFC, NFD, etc. to avoid
+// unexpected behavior for the user.  For example, in NFD, there is a boundary
+// after 'a'.  However, 'a' might combine with modifiers, so from the application's
+// perspective it is not a good boundary. We will therefore always use the
+// boundaries for the combining variants.
+
+// BoundaryBefore returns true if this rune starts a new segment and
+// cannot combine with any rune on the left.
+func (p Properties) BoundaryBefore() bool {
+	if p.ccc == 0 && !p.combinesBackward() {
+		return true
+	}
+	// We assume that the CCC of the first character in a decomposition
+	// is always non-zero if different from info.ccc and that we can return
+	// false at this point. This is verified by maketables.
+	return false
+}
+
+// BoundaryAfter returns true if this rune cannot combine with runes to the right
+// and always denotes the end of a segment.
+func (p Properties) BoundaryAfter() bool {
+	return p.isInert()
+}
+
+// We pack quick check data in 4 bits:
+//   0:    NFD_QC Yes (0) or No (1). No also means there is a decomposition.
+//   1..2: NFC_QC Yes(00), No (10), or Maybe (11)
+//   3:    Combines forward  (0 == false, 1 == true)
+//
+// When all 4 bits are zero, the character is inert, meaning it is never
+// influenced by normalization.
+type qcInfo uint8
+
+func (p Properties) isYesC() bool { return p.flags&0x4 == 0 }
+func (p Properties) isYesD() bool { return p.flags&0x1 == 0 }
+
+func (p Properties) combinesForward() bool  { return p.flags&0x8 != 0 }
+func (p Properties) combinesBackward() bool { return p.flags&0x2 != 0 } // == isMaybe
+func (p Properties) hasDecomposition() bool { return p.flags&0x1 != 0 } // == isNoD
+
+func (p Properties) isInert() bool {
+	return p.flags&0xf == 0 && p.ccc == 0
+}
+
+func (p Properties) multiSegment() bool {
+	return p.index >= firstMulti && p.index < endMulti
+}
+
+// Decomposition returns the decomposition for the underlying rune
+// or nil if there is none.
+func (p Properties) Decomposition() []byte {
+	if p.index == 0 {
+		return nil
+	}
+	i := p.index
+	n := decomps[i] & headerLenMask
+	i++
+	return decomps[i : i+uint16(n)]
+}
+
+// Size returns the length of UTF-8 encoding of the rune.
+func (p Properties) Size() int {
+	return int(p.size)
+}
+
+// CCC returns the canonical combining class of the underlying rune.
+func (p Properties) CCC() uint8 {
+	if p.index > firstCCCZeroExcept {
+		return 0
+	}
+	return p.ccc
+}
+
+// LeadCCC returns the CCC of the first rune in the decomposition.
+// If there is no decomposition, LeadCCC equals CCC.
+func (p Properties) LeadCCC() uint8 {
+	return p.ccc
+}
+
+// TrailCCC returns the CCC of the last rune in the decomposition.
+// If there is no decomposition, TrailCCC equals CCC.
+func (p Properties) TrailCCC() uint8 {
+	return p.tccc
+}
+
+// Recomposition
+// We use 32-bit keys instead of 64-bit for the two codepoint keys.
+// This clips off the bits of three entries, but we know this will not
+// result in a collision. In the unlikely event that changes to
+// UnicodeData.txt introduce collisions, the compiler will catch it.
+// Note that the recomposition map for NFC and NFKC are identical.
+
+// combine returns the combined rune or 0 if it doesn't exist.
+func combine(a, b rune) rune {
+	key := uint32(uint16(a))<<16 + uint32(uint16(b))
+	return recompMap[key]
+}
+
+func lookupInfoNFC(b input, i int) Properties {
+	v, sz := b.charinfoNFC(i)
+	return compInfo(v, sz)
+}
+
+func lookupInfoNFKC(b input, i int) Properties {
+	v, sz := b.charinfoNFKC(i)
+	return compInfo(v, sz)
+}
+
+// Properties returns properties for the first rune in s.
+func (f Form) Properties(s []byte) Properties {
+	if f == NFC || f == NFD {
+		return compInfo(nfcTrie.lookup(s))
+	}
+	return compInfo(nfkcTrie.lookup(s))
+}
+
+// PropertiesString returns properties for the first rune in s.
+func (f Form) PropertiesString(s string) Properties {
+	if f == NFC || f == NFD {
+		return compInfo(nfcTrie.lookupString(s))
+	}
+	return compInfo(nfkcTrie.lookupString(s))
+}
+
+// compInfo converts the information contained in v and sz
+// to a Properties.  See the comment at the top of the file
+// for more information on the format.
+func compInfo(v uint16, sz int) Properties {
+	if v == 0 {
+		return Properties{size: uint8(sz)}
+	} else if v >= 0x8000 {
+		return Properties{
+			size:  uint8(sz),
+			ccc:   uint8(v),
+			tccc:  uint8(v),
+			flags: qcInfo(v>>8) & qcInfoMask,
+		}
+	}
+	// has decomposition
+	h := decomps[v]
+	f := (qcInfo(h&headerFlagsMask) >> 4) | 0x1
+	ri := Properties{size: uint8(sz), flags: f, index: v}
+	if v >= firstCCC {
+		v += uint16(h&headerLenMask) + 1
+		ri.tccc = decomps[v]
+		if v >= firstLeadingCCC {
+			ri.ccc = decomps[v+1]
+		}
+	}
+	return ri
+}
diff --git a/src/pkg/exp/norm/input.go b/src/pkg/exp/norm/input.go
new file mode 100644
index 0000000..d0177a1
--- /dev/null
+++ b/src/pkg/exp/norm/input.go
@@ -0,0 +1,105 @@
+// 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 norm
+
+import "unicode/utf8"
+
+type input struct {
+	str   string
+	bytes []byte
+}
+
+func inputBytes(str []byte) input {
+	return input{bytes: str}
+}
+
+func inputString(str string) input {
+	return input{str: str}
+}
+
+func (in *input) setBytes(str []byte) {
+	in.str = ""
+	in.bytes = str
+}
+
+func (in *input) setString(str string) {
+	in.str = str
+	in.bytes = nil
+}
+
+func (in *input) _byte(p int) byte {
+	if in.bytes == nil {
+		return in.str[p]
+	}
+	return in.bytes[p]
+}
+
+func (in *input) skipASCII(p, max int) int {
+	if in.bytes == nil {
+		for ; p < max && in.str[p] < utf8.RuneSelf; p++ {
+		}
+	} else {
+		for ; p < max && in.bytes[p] < utf8.RuneSelf; p++ {
+		}
+	}
+	return p
+}
+
+func (in *input) skipNonStarter(p int) int {
+	if in.bytes == nil {
+		for ; p < len(in.str) && !utf8.RuneStart(in.str[p]); p++ {
+		}
+	} else {
+		for ; p < len(in.bytes) && !utf8.RuneStart(in.bytes[p]); p++ {
+		}
+	}
+	return p
+}
+
+func (in *input) appendSlice(buf []byte, b, e int) []byte {
+	if in.bytes != nil {
+		return append(buf, in.bytes[b:e]...)
+	}
+	for i := b; i < e; i++ {
+		buf = append(buf, in.str[i])
+	}
+	return buf
+}
+
+func (in *input) copySlice(buf []byte, b, e int) int {
+	if in.bytes == nil {
+		return copy(buf, in.str[b:e])
+	}
+	return copy(buf, in.bytes[b:e])
+}
+
+func (in *input) charinfoNFC(p int) (uint16, int) {
+	if in.bytes == nil {
+		return nfcTrie.lookupString(in.str[p:])
+	}
+	return nfcTrie.lookup(in.bytes[p:])
+}
+
+func (in *input) charinfoNFKC(p int) (uint16, int) {
+	if in.bytes == nil {
+		return nfkcTrie.lookupString(in.str[p:])
+	}
+	return nfkcTrie.lookup(in.bytes[p:])
+}
+
+func (in *input) hangul(p int) (r rune) {
+	if in.bytes == nil {
+		if !isHangulString(in.str[p:]) {
+			return 0
+		}
+		r, _ = utf8.DecodeRuneInString(in.str[p:])
+	} else {
+		if !isHangul(in.bytes[p:]) {
+			return 0
+		}
+		r, _ = utf8.DecodeRune(in.bytes[p:])
+	}
+	return r
+}
diff --git a/src/pkg/exp/norm/iter.go b/src/pkg/exp/norm/iter.go
new file mode 100644
index 0000000..a954624
--- /dev/null
+++ b/src/pkg/exp/norm/iter.go
@@ -0,0 +1,401 @@
+// 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 norm
+
+import (
+	"fmt"
+	"unicode/utf8"
+)
+
+const MaxSegmentSize = maxByteBufferSize
+
+// An Iter iterates over a string or byte slice, while normalizing it
+// to a given Form.
+type Iter struct {
+	rb     reorderBuffer
+	buf    [maxByteBufferSize]byte
+	info   Properties // first character saved from previous iteration
+	next   iterFunc   // implementation of next depends on form
+	asciiF iterFunc
+
+	p        int    // current position in input source
+	multiSeg []byte // remainder of multi-segment decomposition
+}
+
+type iterFunc func(*Iter) []byte
+
+// Init initializes i to iterate over src after normalizing it to Form f.
+func (i *Iter) Init(f Form, src []byte) {
+	i.p = 0
+	if len(src) == 0 {
+		i.setDone()
+		i.rb.nsrc = 0
+		return
+	}
+	i.multiSeg = nil
+	i.rb.init(f, src)
+	i.next = i.rb.f.nextMain
+	i.asciiF = nextASCIIBytes
+	i.info = i.rb.f.info(i.rb.src, i.p)
+}
+
+// InitString initializes i to iterate over src after normalizing it to Form f.
+func (i *Iter) InitString(f Form, src string) {
+	i.p = 0
+	if len(src) == 0 {
+		i.setDone()
+		i.rb.nsrc = 0
+		return
+	}
+	i.multiSeg = nil
+	i.rb.initString(f, src)
+	i.next = i.rb.f.nextMain
+	i.asciiF = nextASCIIString
+	i.info = i.rb.f.info(i.rb.src, i.p)
+}
+
+// Seek sets the segment to be returned by the next call to Next to start
+// at position p.  It is the responsibility of the caller to set p to the
+// start of a UTF8 rune.
+func (i *Iter) Seek(offset int64, whence int) (int64, error) {
+	var abs int64
+	switch whence {
+	case 0:
+		abs = offset
+	case 1:
+		abs = int64(i.p) + offset
+	case 2:
+		abs = int64(i.rb.nsrc) + offset
+	default:
+		return 0, fmt.Errorf("norm: invalid whence")
+	}
+	if abs < 0 {
+		return 0, fmt.Errorf("norm: negative position")
+	}
+	if int(abs) >= i.rb.nsrc {
+		i.setDone()
+		return int64(i.p), nil
+	}
+	i.p = int(abs)
+	i.multiSeg = nil
+	i.next = i.rb.f.nextMain
+	i.info = i.rb.f.info(i.rb.src, i.p)
+	return abs, nil
+}
+
+// returnSlice returns a slice of the underlying input type as a byte slice.
+// If the underlying is of type []byte, it will simply return a slice.
+// If the underlying is of type string, it will copy the slice to the buffer
+// and return that.
+func (i *Iter) returnSlice(a, b int) []byte {
+	if i.rb.src.bytes == nil {
+		return i.buf[:copy(i.buf[:], i.rb.src.str[a:b])]
+	}
+	return i.rb.src.bytes[a:b]
+}
+
+// Pos returns the byte position at which the next call to Next will commence processing.
+func (i *Iter) Pos() int {
+	return i.p
+}
+
+func (i *Iter) setDone() {
+	i.next = nextDone
+	i.p = i.rb.nsrc
+}
+
+// Done returns true if there is no more input to process.
+func (i *Iter) Done() bool {
+	return i.p >= i.rb.nsrc
+}
+
+// Next returns f(i.input[i.Pos():n]), where n is a boundary of i.input.
+// For any input a and b for which f(a) == f(b), subsequent calls
+// to Next will return the same segments.
+// Modifying runes are grouped together with the preceding starter, if such a starter exists.
+// Although not guaranteed, n will typically be the smallest possible n.
+func (i *Iter) Next() []byte {
+	return i.next(i)
+}
+
+func nextASCIIBytes(i *Iter) []byte {
+	p := i.p + 1
+	if p >= i.rb.nsrc {
+		i.setDone()
+		return i.rb.src.bytes[i.p:p]
+	}
+	if i.rb.src.bytes[p] < utf8.RuneSelf {
+		p0 := i.p
+		i.p = p
+		return i.rb.src.bytes[p0:p]
+	}
+	i.info = i.rb.f.info(i.rb.src, i.p)
+	i.next = i.rb.f.nextMain
+	return i.next(i)
+}
+
+func nextASCIIString(i *Iter) []byte {
+	p := i.p + 1
+	if p >= i.rb.nsrc {
+		i.buf[0] = i.rb.src.str[i.p]
+		i.setDone()
+		return i.buf[:1]
+	}
+	if i.rb.src.str[p] < utf8.RuneSelf {
+		i.buf[0] = i.rb.src.str[i.p]
+		i.p = p
+		return i.buf[:1]
+	}
+	i.info = i.rb.f.info(i.rb.src, i.p)
+	i.next = i.rb.f.nextMain
+	return i.next(i)
+}
+
+func nextHangul(i *Iter) []byte {
+	if r := i.rb.src.hangul(i.p); r != 0 {
+		i.p += hangulUTF8Size
+		if i.p >= i.rb.nsrc {
+			i.setDone()
+		}
+		return i.buf[:decomposeHangul(i.buf[:], r)]
+	}
+	i.info = i.rb.f.info(i.rb.src, i.p)
+	i.next = i.rb.f.nextMain
+	return i.next(i)
+}
+
+func nextDone(i *Iter) []byte {
+	return nil
+}
+
+// nextMulti is used for iterating over multi-segment decompositions
+// for decomposing normal forms.
+func nextMulti(i *Iter) []byte {
+	j := 0
+	d := i.multiSeg
+	// skip first rune
+	for j = 1; j < len(d) && !utf8.RuneStart(d[j]); j++ {
+	}
+	for j < len(d) {
+		info := i.rb.f.info(input{bytes: d}, j)
+		if info.ccc == 0 {
+			i.multiSeg = d[j:]
+			return d[:j]
+		}
+		j += int(info.size)
+	}
+	// treat last segment as normal decomposition
+	i.next = i.rb.f.nextMain
+	return i.next(i)
+}
+
+// nextMultiNorm is used for iterating over multi-segment decompositions
+// for composing normal forms.
+func nextMultiNorm(i *Iter) []byte {
+	j := 0
+	d := i.multiSeg
+	// skip first rune
+	for j = 1; j < len(d) && !utf8.RuneStart(d[j]); j++ {
+	}
+	for j < len(d) {
+		info := i.rb.f.info(input{bytes: d}, j)
+		if info.ccc == 0 {
+			i.multiSeg = d[j:]
+			return d[:j]
+		}
+		j += int(info.size)
+	}
+	i.multiSeg = nil
+	i.next = nextComposed
+	i.p++ // restore old valud of i.p. See nextComposed.
+	if i.p >= i.rb.nsrc {
+		i.setDone()
+	}
+	return d
+}
+
+// nextDecomposed is the implementation of Next for forms NFD and NFKD.
+func nextDecomposed(i *Iter) (next []byte) {
+	startp, outp := i.p, 0
+	inCopyStart, outCopyStart := i.p, 0
+	for {
+		if sz := int(i.info.size); sz <= 1 {
+			p := i.p
+			i.p++ // ASCII or illegal byte.  Either way, advance by 1.
+			if i.p >= i.rb.nsrc {
+				i.setDone()
+				return i.returnSlice(p, i.p)
+			} else if i.rb.src._byte(i.p) < utf8.RuneSelf {
+				i.next = i.asciiF
+				return i.returnSlice(p, i.p)
+			}
+			outp++
+		} else if d := i.info.Decomposition(); d != nil {
+			// Note: If leading CCC != 0, then len(d) == 2 and last is also non-zero.
+			// Case 1: there is a leftover to copy.  In this case the decomposition
+			// must begin with a modifier and should always be appended.
+			// Case 2: no leftover. Simply return d if followed by a ccc == 0 value.
+			p := outp + len(d)
+			if outp > 0 {
+				i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+				if p > len(i.buf) {
+					return i.buf[:outp]
+				}
+			} else if i.info.multiSegment() {
+				// outp must be 0 as multi-segment decompositions always
+				// start a new segment.
+				if i.multiSeg == nil {
+					i.multiSeg = d
+					i.next = nextMulti
+					return nextMulti(i)
+				}
+				// We are in the last segment.  Treat as normal decomposition.
+				d = i.multiSeg
+				i.multiSeg = nil
+				p = len(d)
+			}
+			prevCC := i.info.tccc
+			if i.p += sz; i.p >= i.rb.nsrc {
+				i.setDone()
+				i.info = Properties{} // Force BoundaryBefore to succeed.
+			} else {
+				i.info = i.rb.f.info(i.rb.src, i.p)
+			}
+			if i.info.BoundaryBefore() {
+				if outp > 0 {
+					copy(i.buf[outp:], d)
+					return i.buf[:p]
+				}
+				return d
+			}
+			copy(i.buf[outp:], d)
+			outp = p
+			inCopyStart, outCopyStart = i.p, outp
+			if i.info.ccc < prevCC {
+				goto doNorm
+			}
+			continue
+		} else if r := i.rb.src.hangul(i.p); r != 0 {
+			i.next = nextHangul
+			i.p += hangulUTF8Size
+			if i.p >= i.rb.nsrc {
+				i.setDone()
+			}
+			return i.buf[:decomposeHangul(i.buf[:], r)]
+		} else {
+			p := outp + sz
+			if p > len(i.buf) {
+				break
+			}
+			outp = p
+			i.p += sz
+		}
+		if i.p >= i.rb.nsrc {
+			i.setDone()
+			break
+		}
+		prevCC := i.info.tccc
+		i.info = i.rb.f.info(i.rb.src, i.p)
+		if i.info.BoundaryBefore() {
+			break
+		} else if i.info.ccc < prevCC {
+			goto doNorm
+		}
+	}
+	if outCopyStart == 0 {
+		return i.returnSlice(inCopyStart, i.p)
+	} else if inCopyStart < i.p {
+		i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+	}
+	return i.buf[:outp]
+doNorm:
+	// Insert what we have decomposed so far in the reorderBuffer.
+	// As we will only reorder, there will always be enough room.
+	i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+	if !i.rb.insertDecomposed(i.buf[0:outp]) {
+		// Start over to prevent decompositions from crossing segment boundaries.
+		// This is a rare occurrence.
+		i.p = startp
+		i.info = i.rb.f.info(i.rb.src, i.p)
+	}
+	for {
+		if !i.rb.insert(i.rb.src, i.p, i.info) {
+			break
+		}
+		if i.p += int(i.info.size); i.p >= i.rb.nsrc {
+			i.setDone()
+			break
+		}
+		i.info = i.rb.f.info(i.rb.src, i.p)
+		if i.info.ccc == 0 {
+			break
+		}
+	}
+	// new segment or too many combining characters: exit normalization
+	return i.buf[:i.rb.flushCopy(i.buf[:])]
+}
+
+// nextComposed is the implementation of Next for forms NFC and NFKC.
+func nextComposed(i *Iter) []byte {
+	outp, startp := 0, i.p
+	var prevCC uint8
+	for {
+		if !i.info.isYesC() {
+			goto doNorm
+		}
+		if cc := i.info.ccc; cc == 0 && outp > 0 {
+			break
+		} else if cc < prevCC {
+			goto doNorm
+		}
+		prevCC = i.info.tccc
+		sz := int(i.info.size)
+		if sz == 0 {
+			sz = 1 // illegal rune: copy byte-by-byte
+		}
+		p := outp + sz
+		if p > len(i.buf) {
+			break
+		}
+		outp = p
+		i.p += sz
+		if i.p >= i.rb.nsrc {
+			i.setDone()
+			break
+		} else if i.rb.src._byte(i.p) < utf8.RuneSelf {
+			i.next = i.asciiF
+			break
+		}
+		i.info = i.rb.f.info(i.rb.src, i.p)
+	}
+	return i.returnSlice(startp, i.p)
+doNorm:
+	multi := false
+	i.p = startp
+	i.info = i.rb.f.info(i.rb.src, i.p)
+	for {
+		if !i.rb.insert(i.rb.src, i.p, i.info) {
+			break
+		}
+		multi = multi || i.info.multiSegment()
+		if i.p += int(i.info.size); i.p >= i.rb.nsrc {
+			i.setDone()
+			break
+		}
+		i.info = i.rb.f.info(i.rb.src, i.p)
+		if i.info.BoundaryBefore() {
+			break
+		}
+	}
+	i.rb.compose()
+	seg := i.buf[:i.rb.flushCopy(i.buf[:])]
+	if multi {
+		i.p-- // fake not being done yet
+		i.multiSeg = seg
+		i.next = nextMultiNorm
+		return nextMultiNorm(i)
+	}
+	return seg
+}
diff --git a/src/pkg/exp/norm/iter_test.go b/src/pkg/exp/norm/iter_test.go
new file mode 100644
index 0000000..8261193
--- /dev/null
+++ b/src/pkg/exp/norm/iter_test.go
@@ -0,0 +1,188 @@
+// 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 norm
+
+import (
+	"strings"
+	"testing"
+)
+
+func doIterNorm(f Form, s string) []byte {
+	acc := []byte{}
+	i := Iter{}
+	i.InitString(f, s)
+	for !i.Done() {
+		acc = append(acc, i.Next()...)
+	}
+	return acc
+}
+
+func runIterTests(t *testing.T, name string, f Form, tests []AppendTest, norm bool) {
+	for i, test := range tests {
+		in := test.left + test.right
+		gold := test.out
+		if norm {
+			gold = string(f.AppendString(nil, test.out))
+		}
+		out := string(doIterNorm(f, in))
+		if len(out) != len(gold) {
+			const msg = "%s:%d: length is %d; want %d"
+			t.Errorf(msg, name, i, len(out), len(gold))
+		}
+		if out != gold {
+			// Find first rune that differs and show context.
+			ir := []rune(out)
+			ig := []rune(gold)
+			t.Errorf("\n%X != \n%X", ir, ig)
+			for j := 0; j < len(ir) && j < len(ig); j++ {
+				if ir[j] == ig[j] {
+					continue
+				}
+				if j -= 3; j < 0 {
+					j = 0
+				}
+				for e := j + 7; j < e && j < len(ir) && j < len(ig); j++ {
+					const msg = "%s:%d: runeAt(%d) = %U; want %U"
+					t.Errorf(msg, name, i, j, ir[j], ig[j])
+				}
+				break
+			}
+		}
+	}
+}
+
+func rep(r rune, n int) string {
+	return strings.Repeat(string(r), n)
+}
+
+const segSize = maxByteBufferSize
+
+var iterTests = []AppendTest{
+	{"", ascii, ascii},
+	{"", txt_all, txt_all},
+	{"", "a" + rep(0x0300, segSize/2), "a" + rep(0x0300, segSize/2)},
+}
+
+var iterTestsD = []AppendTest{
+	{ // segment overflow on unchanged character
+		"",
+		"a" + rep(0x0300, segSize/2) + "\u0316",
+		"a" + rep(0x0300, segSize/2-1) + "\u0316\u0300",
+	},
+	{ // segment overflow on unchanged character + start value
+		"",
+		"a" + rep(0x0300, segSize/2+maxCombiningChars+4) + "\u0316",
+		"a" + rep(0x0300, segSize/2+maxCombiningChars) + "\u0316" + rep(0x300, 4),
+	},
+	{ // segment overflow on decomposition
+		"",
+		"a" + rep(0x0300, segSize/2-1) + "\u0340",
+		"a" + rep(0x0300, segSize/2),
+	},
+	{ // segment overflow on decomposition + start value
+		"",
+		"a" + rep(0x0300, segSize/2-1) + "\u0340" + rep(0x300, maxCombiningChars+4) + "\u0320",
+		"a" + rep(0x0300, segSize/2-1) + rep(0x300, maxCombiningChars+1) + "\u0320" + rep(0x300, 4),
+	},
+	{ // start value after ASCII overflow
+		"",
+		rep('a', segSize) + rep(0x300, maxCombiningChars+2) + "\u0320",
+		rep('a', segSize) + rep(0x300, maxCombiningChars) + "\u0320\u0300\u0300",
+	},
+	{ // start value after Hangul overflow
+		"",
+		rep(0xAC00, segSize/6) + rep(0x300, maxCombiningChars+2) + "\u0320",
+		strings.Repeat("\u1100\u1161", segSize/6) + rep(0x300, maxCombiningChars+1) + "\u0320" + rep(0x300, 1),
+	},
+	{ // start value after cc=0
+		"",
+		"您您" + rep(0x300, maxCombiningChars+4) + "\u0320",
+		"您您" + rep(0x300, maxCombiningChars) + "\u0320" + rep(0x300, 4),
+	},
+	{ // start value after normalization
+		"",
+		"\u0300\u0320a" + rep(0x300, maxCombiningChars+4) + "\u0320",
+		"\u0320\u0300a" + rep(0x300, maxCombiningChars) + "\u0320" + rep(0x300, 4),
+	},
+}
+
+var iterTestsC = []AppendTest{
+	{ // ordering of non-composing combining characters
+		"",
+		"\u0305\u0316",
+		"\u0316\u0305",
+	},
+	{ // segment overflow
+		"",
+		"a" + rep(0x0305, segSize/2+4) + "\u0316",
+		"a" + rep(0x0305, segSize/2-1) + "\u0316" + rep(0x305, 5),
+	},
+}
+
+func TestIterNextD(t *testing.T) {
+	runIterTests(t, "IterNextD1", NFKD, appendTests, true)
+	runIterTests(t, "IterNextD2", NFKD, iterTests, true)
+	runIterTests(t, "IterNextD3", NFKD, iterTestsD, false)
+}
+
+func TestIterNextC(t *testing.T) {
+	runIterTests(t, "IterNextC1", NFKC, appendTests, true)
+	runIterTests(t, "IterNextC2", NFKC, iterTests, true)
+	runIterTests(t, "IterNextC3", NFKC, iterTestsC, false)
+}
+
+type SegmentTest struct {
+	in  string
+	out []string
+}
+
+var segmentTests = []SegmentTest{
+	{"\u1E0A\u0323a", []string{"\x44\u0323\u0307", "a", ""}},
+	{rep('a', segSize), append(strings.Split(rep('a', segSize), ""), "")},
+	{rep('a', segSize+2), append(strings.Split(rep('a', segSize+2), ""), "")},
+	{rep('a', segSize) + "\u0300aa",
+		append(strings.Split(rep('a', segSize-1), ""), "a\u0300", "a", "a", "")},
+}
+
+var segmentTestsK = []SegmentTest{
+	{"\u3332", []string{"\u30D5", "\u30A1", "\u30E9", "\u30C3", "\u30C8\u3099", ""}},
+	// last segment of multi-segment decomposition needs normalization
+	{"\u3332\u093C", []string{"\u30D5", "\u30A1", "\u30E9", "\u30C3", "\u30C8\u093C\u3099", ""}},
+	// Hangul and Jamo are grouped togeter.
+	{"\uAC00", []string{"\u1100\u1161", ""}},
+	{"\uAC01", []string{"\u1100\u1161\u11A8", ""}},
+	{"\u1100\u1161", []string{"\u1100\u1161", ""}},
+}
+
+// Note that, by design, segmentation is equal for composing and decomposing forms.
+func TestIterSegmentation(t *testing.T) {
+	segmentTest(t, "SegmentTestD", NFD, segmentTests)
+	segmentTest(t, "SegmentTestC", NFC, segmentTests)
+	segmentTest(t, "SegmentTestD", NFKD, segmentTestsK)
+	segmentTest(t, "SegmentTestC", NFKC, segmentTestsK)
+}
+
+func segmentTest(t *testing.T, name string, f Form, tests []SegmentTest) {
+	iter := Iter{}
+	for i, tt := range tests {
+		iter.InitString(f, tt.in)
+		for j, seg := range tt.out {
+			if seg == "" {
+				if !iter.Done() {
+					res := string(iter.Next())
+					t.Errorf(`%s:%d:%d: expected Done()==true, found segment "%s"`, name, i, j, res)
+				}
+				continue
+			}
+			if iter.Done() {
+				t.Errorf("%s:%d:%d: Done()==true, want false", name, i, j)
+			}
+			seg = f.String(seg)
+			if res := string(iter.Next()); res != seg {
+				t.Errorf(`%s:%d:%d" segment was "%s" (%d); want "%s" (%d) %X %X`, name, i, j, res, len(res), seg, len(seg), []rune(res), []rune(seg))
+			}
+		}
+	}
+}
diff --git a/src/pkg/exp/norm/maketables.go b/src/pkg/exp/norm/maketables.go
new file mode 100644
index 0000000..50c0c31
--- /dev/null
+++ b/src/pkg/exp/norm/maketables.go
@@ -0,0 +1,923 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Normalization table generator.
+// Data read from the web.
+// See forminfo.go for a description of the trie values associated with each rune.
+
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"unicode"
+)
+
+func main() {
+	flag.Parse()
+	loadUnicodeData()
+	loadCompositionExclusions()
+	completeCharFields(FCanonical)
+	completeCharFields(FCompatibility)
+	verifyComputed()
+	printChars()
+	makeTables()
+	testDerived()
+}
+
+var url = flag.String("url",
+	"http://www.unicode.org/Public/"+unicode.Version+"/ucd/",
+	"URL of Unicode database directory")
+var tablelist = flag.String("tables",
+	"all",
+	"comma-separated list of which tables to generate; "+
+		"can be 'decomp', 'recomp', 'info' and 'all'")
+var test = flag.Bool("test",
+	false,
+	"test existing tables; can be used to compare web data with package data")
+var verbose = flag.Bool("verbose",
+	false,
+	"write data to stdout as it is parsed")
+var localFiles = flag.Bool("local",
+	false,
+	"data files have been copied to the current directory; for debugging only")
+
+var logger = log.New(os.Stderr, "", log.Lshortfile)
+
+// UnicodeData.txt has form:
+//	0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;;
+//	007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A
+// See http://unicode.org/reports/tr44/ for full explanation
+// The fields:
+const (
+	FCodePoint = iota
+	FName
+	FGeneralCategory
+	FCanonicalCombiningClass
+	FBidiClass
+	FDecompMapping
+	FDecimalValue
+	FDigitValue
+	FNumericValue
+	FBidiMirrored
+	FUnicode1Name
+	FISOComment
+	FSimpleUppercaseMapping
+	FSimpleLowercaseMapping
+	FSimpleTitlecaseMapping
+	NumField
+
+	MaxChar = 0x10FFFF // anything above this shouldn't exist
+)
+
+// Quick Check properties of runes allow us to quickly
+// determine whether a rune may occur in a normal form.
+// For a given normal form, a rune may be guaranteed to occur
+// verbatim (QC=Yes), may or may not combine with another
+// rune (QC=Maybe), or may not occur (QC=No).
+type QCResult int
+
+const (
+	QCUnknown QCResult = iota
+	QCYes
+	QCNo
+	QCMaybe
+)
+
+func (r QCResult) String() string {
+	switch r {
+	case QCYes:
+		return "Yes"
+	case QCNo:
+		return "No"
+	case QCMaybe:
+		return "Maybe"
+	}
+	return "***UNKNOWN***"
+}
+
+const (
+	FCanonical     = iota // NFC or NFD
+	FCompatibility        // NFKC or NFKD
+	FNumberOfFormTypes
+)
+
+const (
+	MComposed   = iota // NFC or NFKC
+	MDecomposed        // NFD or NFKD
+	MNumberOfModes
+)
+
+// This contains only the properties we're interested in.
+type Char struct {
+	name          string
+	codePoint     rune  // if zero, this index is not a valid code point.
+	ccc           uint8 // canonical combining class
+	excludeInComp bool  // from CompositionExclusions.txt
+	compatDecomp  bool  // it has a compatibility expansion
+
+	forms [FNumberOfFormTypes]FormInfo // For FCanonical and FCompatibility
+
+	state State
+}
+
+var chars = make([]Char, MaxChar+1)
+
+func (c Char) String() string {
+	buf := new(bytes.Buffer)
+
+	fmt.Fprintf(buf, "%U [%s]:\n", c.codePoint, c.name)
+	fmt.Fprintf(buf, "  ccc: %v\n", c.ccc)
+	fmt.Fprintf(buf, "  excludeInComp: %v\n", c.excludeInComp)
+	fmt.Fprintf(buf, "  compatDecomp: %v\n", c.compatDecomp)
+	fmt.Fprintf(buf, "  state: %v\n", c.state)
+	fmt.Fprintf(buf, "  NFC:\n")
+	fmt.Fprint(buf, c.forms[FCanonical])
+	fmt.Fprintf(buf, "  NFKC:\n")
+	fmt.Fprint(buf, c.forms[FCompatibility])
+
+	return buf.String()
+}
+
+// In UnicodeData.txt, some ranges are marked like this:
+//	3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
+//	4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;;
+// parseCharacter keeps a state variable indicating the weirdness.
+type State int
+
+const (
+	SNormal State = iota // known to be zero for the type
+	SFirst
+	SLast
+	SMissing
+)
+
+var lastChar = rune('\u0000')
+
+func (c Char) isValid() bool {
+	return c.codePoint != 0 && c.state != SMissing
+}
+
+type FormInfo struct {
+	quickCheck [MNumberOfModes]QCResult // index: MComposed or MDecomposed
+	verified   [MNumberOfModes]bool     // index: MComposed or MDecomposed
+
+	combinesForward  bool // May combine with rune on the right
+	combinesBackward bool // May combine with rune on the left
+	isOneWay         bool // Never appears in result
+	inDecomp         bool // Some decompositions result in this char.
+	decomp           Decomposition
+	expandedDecomp   Decomposition
+}
+
+func (f FormInfo) String() string {
+	buf := bytes.NewBuffer(make([]byte, 0))
+
+	fmt.Fprintf(buf, "    quickCheck[C]: %v\n", f.quickCheck[MComposed])
+	fmt.Fprintf(buf, "    quickCheck[D]: %v\n", f.quickCheck[MDecomposed])
+	fmt.Fprintf(buf, "    cmbForward: %v\n", f.combinesForward)
+	fmt.Fprintf(buf, "    cmbBackward: %v\n", f.combinesBackward)
+	fmt.Fprintf(buf, "    isOneWay: %v\n", f.isOneWay)
+	fmt.Fprintf(buf, "    inDecomp: %v\n", f.inDecomp)
+	fmt.Fprintf(buf, "    decomposition: %X\n", f.decomp)
+	fmt.Fprintf(buf, "    expandedDecomp: %X\n", f.expandedDecomp)
+
+	return buf.String()
+}
+
+type Decomposition []rune
+
+func openReader(file string) (input io.ReadCloser) {
+	if *localFiles {
+		f, err := os.Open(file)
+		if err != nil {
+			logger.Fatal(err)
+		}
+		input = f
+	} else {
+		path := *url + file
+		resp, err := http.Get(path)
+		if err != nil {
+			logger.Fatal(err)
+		}
+		if resp.StatusCode != 200 {
+			logger.Fatal("bad GET status for "+file, resp.Status)
+		}
+		input = resp.Body
+	}
+	return
+}
+
+func parseDecomposition(s string, skipfirst bool) (a []rune, e error) {
+	decomp := strings.Split(s, " ")
+	if len(decomp) > 0 && skipfirst {
+		decomp = decomp[1:]
+	}
+	for _, d := range decomp {
+		point, err := strconv.ParseUint(d, 16, 64)
+		if err != nil {
+			return a, err
+		}
+		a = append(a, rune(point))
+	}
+	return a, nil
+}
+
+func parseCharacter(line string) {
+	field := strings.Split(line, ";")
+	if len(field) != NumField {
+		logger.Fatalf("%5s: %d fields (expected %d)\n", line, len(field), NumField)
+	}
+	x, err := strconv.ParseUint(field[FCodePoint], 16, 64)
+	point := int(x)
+	if err != nil {
+		logger.Fatalf("%.5s...: %s", line, err)
+	}
+	if point == 0 {
+		return // not interesting and we use 0 as unset
+	}
+	if point > MaxChar {
+		logger.Fatalf("%5s: Rune %X > MaxChar (%X)", line, point, MaxChar)
+		return
+	}
+	state := SNormal
+	switch {
+	case strings.Index(field[FName], ", First>") > 0:
+		state = SFirst
+	case strings.Index(field[FName], ", Last>") > 0:
+		state = SLast
+	}
+	firstChar := lastChar + 1
+	lastChar = rune(point)
+	if state != SLast {
+		firstChar = lastChar
+	}
+	x, err = strconv.ParseUint(field[FCanonicalCombiningClass], 10, 64)
+	if err != nil {
+		logger.Fatalf("%U: bad ccc field: %s", int(x), err)
+	}
+	ccc := uint8(x)
+	decmap := field[FDecompMapping]
+	exp, e := parseDecomposition(decmap, false)
+	isCompat := false
+	if e != nil {
+		if len(decmap) > 0 {
+			exp, e = parseDecomposition(decmap, true)
+			if e != nil {
+				logger.Fatalf(`%U: bad decomp |%v|: "%s"`, int(x), decmap, e)
+			}
+			isCompat = true
+		}
+	}
+	for i := firstChar; i <= lastChar; i++ {
+		char := &chars[i]
+		char.name = field[FName]
+		char.codePoint = i
+		char.forms[FCompatibility].decomp = exp
+		if !isCompat {
+			char.forms[FCanonical].decomp = exp
+		} else {
+			char.compatDecomp = true
+		}
+		if len(decmap) > 0 {
+			char.forms[FCompatibility].decomp = exp
+		}
+		char.ccc = ccc
+		char.state = SMissing
+		if i == lastChar {
+			char.state = state
+		}
+	}
+	return
+}
+
+func loadUnicodeData() {
+	f := openReader("UnicodeData.txt")
+	defer f.Close()
+	scanner := bufio.NewScanner(f)
+	for scanner.Scan() {
+		parseCharacter(scanner.Text())
+	}
+	if scanner.Err() != nil {
+		logger.Fatal(scanner.Err())
+	}
+}
+
+var singlePointRe = regexp.MustCompile(`^([0-9A-F]+) *$`)
+
+// CompositionExclusions.txt has form:
+// 0958    # ...
+// See http://unicode.org/reports/tr44/ for full explanation
+func parseExclusion(line string) int {
+	comment := strings.Index(line, "#")
+	if comment >= 0 {
+		line = line[0:comment]
+	}
+	if len(line) == 0 {
+		return 0
+	}
+	matches := singlePointRe.FindStringSubmatch(line)
+	if len(matches) != 2 {
+		logger.Fatalf("%s: %d matches (expected 1)\n", line, len(matches))
+	}
+	point, err := strconv.ParseUint(matches[1], 16, 64)
+	if err != nil {
+		logger.Fatalf("%.5s...: %s", line, err)
+	}
+	return int(point)
+}
+
+func loadCompositionExclusions() {
+	f := openReader("CompositionExclusions.txt")
+	defer f.Close()
+	scanner := bufio.NewScanner(f)
+	for scanner.Scan() {
+		point := parseExclusion(scanner.Text())
+		if point == 0 {
+			continue
+		}
+		c := &chars[point]
+		if c.excludeInComp {
+			logger.Fatalf("%U: Duplicate entry in exclusions.", c.codePoint)
+		}
+		c.excludeInComp = true
+	}
+	if scanner.Err() != nil {
+		log.Fatal(scanner.Err())
+	}
+}
+
+// hasCompatDecomp returns true if any of the recursive
+// decompositions contains a compatibility expansion.
+// In this case, the character may not occur in NFK*.
+func hasCompatDecomp(r rune) bool {
+	c := &chars[r]
+	if c.compatDecomp {
+		return true
+	}
+	for _, d := range c.forms[FCompatibility].decomp {
+		if hasCompatDecomp(d) {
+			return true
+		}
+	}
+	return false
+}
+
+// Hangul related constants.
+const (
+	HangulBase = 0xAC00
+	HangulEnd  = 0xD7A4 // hangulBase + Jamo combinations (19 * 21 * 28)
+
+	JamoLBase = 0x1100
+	JamoLEnd  = 0x1113
+	JamoVBase = 0x1161
+	JamoVEnd  = 0x1176
+	JamoTBase = 0x11A8
+	JamoTEnd  = 0x11C3
+)
+
+func isHangul(r rune) bool {
+	return HangulBase <= r && r < HangulEnd
+}
+
+func ccc(r rune) uint8 {
+	return chars[r].ccc
+}
+
+// Insert a rune in a buffer, ordered by Canonical Combining Class.
+func insertOrdered(b Decomposition, r rune) Decomposition {
+	n := len(b)
+	b = append(b, 0)
+	cc := ccc(r)
+	if cc > 0 {
+		// Use bubble sort.
+		for ; n > 0; n-- {
+			if ccc(b[n-1]) <= cc {
+				break
+			}
+			b[n] = b[n-1]
+		}
+	}
+	b[n] = r
+	return b
+}
+
+// Recursively decompose.
+func decomposeRecursive(form int, r rune, d Decomposition) Decomposition {
+	if isHangul(r) {
+		return d
+	}
+	dcomp := chars[r].forms[form].decomp
+	if len(dcomp) == 0 {
+		return insertOrdered(d, r)
+	}
+	for _, c := range dcomp {
+		d = decomposeRecursive(form, c, d)
+	}
+	return d
+}
+
+func completeCharFields(form int) {
+	// Phase 0: pre-expand decomposition.
+	for i := range chars {
+		f := &chars[i].forms[form]
+		if len(f.decomp) == 0 {
+			continue
+		}
+		exp := make(Decomposition, 0)
+		for _, c := range f.decomp {
+			exp = decomposeRecursive(form, c, exp)
+		}
+		f.expandedDecomp = exp
+	}
+
+	// Phase 1: composition exclusion, mark decomposition.
+	for i := range chars {
+		c := &chars[i]
+		f := &c.forms[form]
+
+		// Marks script-specific exclusions and version restricted.
+		f.isOneWay = c.excludeInComp
+
+		// Singletons
+		f.isOneWay = f.isOneWay || len(f.decomp) == 1
+
+		// Non-starter decompositions
+		if len(f.decomp) > 1 {
+			chk := c.ccc != 0 || chars[f.decomp[0]].ccc != 0
+			f.isOneWay = f.isOneWay || chk
+		}
+
+		// Runes that decompose into more than two runes.
+		f.isOneWay = f.isOneWay || len(f.decomp) > 2
+
+		if form == FCompatibility {
+			f.isOneWay = f.isOneWay || hasCompatDecomp(c.codePoint)
+		}
+
+		for _, r := range f.decomp {
+			chars[r].forms[form].inDecomp = true
+		}
+	}
+
+	// Phase 2: forward and backward combining.
+	for i := range chars {
+		c := &chars[i]
+		f := &c.forms[form]
+
+		if !f.isOneWay && len(f.decomp) == 2 {
+			f0 := &chars[f.decomp[0]].forms[form]
+			f1 := &chars[f.decomp[1]].forms[form]
+			if !f0.isOneWay {
+				f0.combinesForward = true
+			}
+			if !f1.isOneWay {
+				f1.combinesBackward = true
+			}
+		}
+	}
+
+	// Phase 3: quick check values.
+	for i := range chars {
+		c := &chars[i]
+		f := &c.forms[form]
+
+		switch {
+		case len(f.decomp) > 0:
+			f.quickCheck[MDecomposed] = QCNo
+		case isHangul(rune(i)):
+			f.quickCheck[MDecomposed] = QCNo
+		default:
+			f.quickCheck[MDecomposed] = QCYes
+		}
+		switch {
+		case f.isOneWay:
+			f.quickCheck[MComposed] = QCNo
+		case (i & 0xffff00) == JamoLBase:
+			f.quickCheck[MComposed] = QCYes
+			if JamoLBase <= i && i < JamoLEnd {
+				f.combinesForward = true
+			}
+			if JamoVBase <= i && i < JamoVEnd {
+				f.quickCheck[MComposed] = QCMaybe
+				f.combinesBackward = true
+				f.combinesForward = true
+			}
+			if JamoTBase <= i && i < JamoTEnd {
+				f.quickCheck[MComposed] = QCMaybe
+				f.combinesBackward = true
+			}
+		case !f.combinesBackward:
+			f.quickCheck[MComposed] = QCYes
+		default:
+			f.quickCheck[MComposed] = QCMaybe
+		}
+	}
+}
+
+func printBytes(b []byte, name string) {
+	fmt.Printf("// %s: %d bytes\n", name, len(b))
+	fmt.Printf("var %s = [...]byte {", name)
+	for i, c := range b {
+		switch {
+		case i%64 == 0:
+			fmt.Printf("\n// Bytes %x - %x\n", i, i+63)
+		case i%8 == 0:
+			fmt.Printf("\n")
+		}
+		fmt.Printf("0x%.2X, ", c)
+	}
+	fmt.Print("\n}\n\n")
+}
+
+// See forminfo.go for format.
+func makeEntry(f *FormInfo) uint16 {
+	e := uint16(0)
+	if f.combinesForward {
+		e |= 0x8
+	}
+	if f.quickCheck[MDecomposed] == QCNo {
+		e |= 0x1
+	}
+	switch f.quickCheck[MComposed] {
+	case QCYes:
+	case QCNo:
+		e |= 0x4
+	case QCMaybe:
+		e |= 0x6
+	default:
+		log.Fatalf("Illegal quickcheck value %v.", f.quickCheck[MComposed])
+	}
+	return e
+}
+
+// decompSet keeps track of unique decompositions, grouped by whether
+// the decomposition is followed by a trailing and/or leading CCC.
+type decompSet [6]map[string]bool
+
+const (
+	normalDecomp = iota
+	firstMulti
+	firstCCC
+	endMulti
+	firstLeadingCCC
+	firstCCCZeroExcept
+	lastDecomp
+)
+
+var cname = []string{"firstMulti", "firstCCC", "endMulti", "firstLeadingCCC", "firstCCCZeroExcept", "lastDecomp"}
+
+func makeDecompSet() decompSet {
+	m := decompSet{}
+	for i := range m {
+		m[i] = make(map[string]bool)
+	}
+	return m
+}
+func (m *decompSet) insert(key int, s string) {
+	m[key][s] = true
+}
+
+func printCharInfoTables() int {
+	mkstr := func(r rune, f *FormInfo) (int, string) {
+		d := f.expandedDecomp
+		s := string([]rune(d))
+		if max := 1 << 6; len(s) >= max {
+			const msg = "%U: too many bytes in decomposition: %d >= %d"
+			logger.Fatalf(msg, r, len(s), max)
+		}
+		head := uint8(len(s))
+		if f.quickCheck[MComposed] != QCYes {
+			head |= 0x40
+		}
+		if f.combinesForward {
+			head |= 0x80
+		}
+		s = string([]byte{head}) + s
+
+		lccc := ccc(d[0])
+		tccc := ccc(d[len(d)-1])
+		cc := ccc(r)
+		if cc != 0 && lccc == 0 && tccc == 0 {
+			logger.Fatalf("%U: trailing and leading ccc are 0 for non-zero ccc %d", r, cc)
+		}
+		if tccc < lccc && lccc != 0 {
+			const msg = "%U: lccc (%d) must be <= tcc (%d)"
+			logger.Fatalf(msg, r, lccc, tccc)
+		}
+		index := normalDecomp
+		if tccc > 0 || lccc > 0 {
+			s += string([]byte{tccc})
+			index = endMulti
+			for _, r := range d[1:] {
+				if ccc(r) == 0 {
+					index = firstCCC
+				}
+			}
+			if lccc > 0 {
+				s += string([]byte{lccc})
+				if index == firstCCC {
+					logger.Fatalf("%U: multi-segment decomposition not supported for decompositions with leading CCC != 0", r)
+				}
+				index = firstLeadingCCC
+			}
+			if cc != lccc {
+				if cc != 0 {
+					logger.Fatalf("%U: for lccc != ccc, expected ccc to be 0; was %d", r, cc)
+				}
+				index = firstCCCZeroExcept
+			}
+		} else if len(d) > 1 {
+			index = firstMulti
+		}
+		return index, s
+	}
+
+	decompSet := makeDecompSet()
+
+	// Store the uniqued decompositions in a byte buffer,
+	// preceded by their byte length.
+	for _, c := range chars {
+		for _, f := range c.forms {
+			if len(f.expandedDecomp) == 0 {
+				continue
+			}
+			if f.combinesBackward {
+				logger.Fatalf("%U: combinesBackward and decompose", c.codePoint)
+			}
+			index, s := mkstr(c.codePoint, &f)
+			decompSet.insert(index, s)
+		}
+	}
+
+	decompositions := bytes.NewBuffer(make([]byte, 0, 10000))
+	size := 0
+	positionMap := make(map[string]uint16)
+	decompositions.WriteString("\000")
+	fmt.Println("const (")
+	for i, m := range decompSet {
+		sa := []string{}
+		for s := range m {
+			sa = append(sa, s)
+		}
+		sort.Strings(sa)
+		for _, s := range sa {
+			p := decompositions.Len()
+			decompositions.WriteString(s)
+			positionMap[s] = uint16(p)
+		}
+		if cname[i] != "" {
+			fmt.Printf("%s = 0x%X\n", cname[i], decompositions.Len())
+		}
+	}
+	fmt.Println("maxDecomp = 0x8000")
+	fmt.Println(")")
+	b := decompositions.Bytes()
+	printBytes(b, "decomps")
+	size += len(b)
+
+	varnames := []string{"nfc", "nfkc"}
+	for i := 0; i < FNumberOfFormTypes; i++ {
+		trie := newNode()
+		for r, c := range chars {
+			f := c.forms[i]
+			d := f.expandedDecomp
+			if len(d) != 0 {
+				_, key := mkstr(c.codePoint, &f)
+				trie.insert(rune(r), positionMap[key])
+				if c.ccc != ccc(d[0]) {
+					// We assume the lead ccc of a decomposition !=0 in this case.
+					if ccc(d[0]) == 0 {
+						logger.Fatalf("Expected leading CCC to be non-zero; ccc is %d", c.ccc)
+					}
+				}
+			} else if v := makeEntry(&f)<<8 | uint16(c.ccc); v != 0 {
+				trie.insert(c.codePoint, 0x8000|v)
+			}
+		}
+		size += trie.printTables(varnames[i])
+	}
+	return size
+}
+
+func contains(sa []string, s string) bool {
+	for _, a := range sa {
+		if a == s {
+			return true
+		}
+	}
+	return false
+}
+
+// Extract the version number from the URL.
+func version() string {
+	// From http://www.unicode.org/standard/versions/#Version_Numbering:
+	// for the later Unicode versions, data files are located in
+	// versioned directories.
+	fields := strings.Split(*url, "/")
+	for _, f := range fields {
+		if match, _ := regexp.MatchString(`[0-9]\.[0-9]\.[0-9]`, f); match {
+			return f
+		}
+	}
+	logger.Fatal("unknown version")
+	return "Unknown"
+}
+
+const fileHeader = `// Generated by running
+//	maketables --tables=%s --url=%s
+// DO NOT EDIT
+
+package norm
+
+`
+
+func makeTables() {
+	size := 0
+	if *tablelist == "" {
+		return
+	}
+	list := strings.Split(*tablelist, ",")
+	if *tablelist == "all" {
+		list = []string{"recomp", "info"}
+	}
+	fmt.Printf(fileHeader, *tablelist, *url)
+
+	fmt.Println("// Version is the Unicode edition from which the tables are derived.")
+	fmt.Printf("const Version = %q\n\n", version())
+
+	if contains(list, "info") {
+		size += printCharInfoTables()
+	}
+
+	if contains(list, "recomp") {
+		// Note that we use 32 bit keys, instead of 64 bit.
+		// This clips the bits of three entries, but we know
+		// this won't cause a collision. The compiler will catch
+		// any changes made to UnicodeData.txt that introduces
+		// a collision.
+		// Note that the recomposition map for NFC and NFKC
+		// are identical.
+
+		// Recomposition map
+		nrentries := 0
+		for _, c := range chars {
+			f := c.forms[FCanonical]
+			if !f.isOneWay && len(f.decomp) > 0 {
+				nrentries++
+			}
+		}
+		sz := nrentries * 8
+		size += sz
+		fmt.Printf("// recompMap: %d bytes (entries only)\n", sz)
+		fmt.Println("var recompMap = map[uint32]rune{")
+		for i, c := range chars {
+			f := c.forms[FCanonical]
+			d := f.decomp
+			if !f.isOneWay && len(d) > 0 {
+				key := uint32(uint16(d[0]))<<16 + uint32(uint16(d[1]))
+				fmt.Printf("0x%.8X: 0x%.4X,\n", key, i)
+			}
+		}
+		fmt.Printf("}\n\n")
+	}
+
+	fmt.Printf("// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size)
+}
+
+func printChars() {
+	if *verbose {
+		for _, c := range chars {
+			if !c.isValid() || c.state == SMissing {
+				continue
+			}
+			fmt.Println(c)
+		}
+	}
+}
+
+// verifyComputed does various consistency tests.
+func verifyComputed() {
+	for i, c := range chars {
+		for _, f := range c.forms {
+			isNo := (f.quickCheck[MDecomposed] == QCNo)
+			if (len(f.decomp) > 0) != isNo && !isHangul(rune(i)) {
+				log.Fatalf("%U: NF*D must be no if rune decomposes", i)
+			}
+
+			isMaybe := f.quickCheck[MComposed] == QCMaybe
+			if f.combinesBackward != isMaybe {
+				log.Fatalf("%U: NF*C must be maybe if combinesBackward", i)
+			}
+		}
+		nfc := c.forms[FCanonical]
+		nfkc := c.forms[FCompatibility]
+		if nfc.combinesBackward != nfkc.combinesBackward {
+			logger.Fatalf("%U: Cannot combine combinesBackward\n", c.codePoint)
+		}
+	}
+}
+
+var qcRe = regexp.MustCompile(`([0-9A-F\.]+) *; (NF.*_QC); ([YNM]) #.*`)
+
+// Use values in DerivedNormalizationProps.txt to compare against the
+// values we computed.
+// DerivedNormalizationProps.txt has form:
+// 00C0..00C5    ; NFD_QC; N # ...
+// 0374          ; NFD_QC; N # ...
+// See http://unicode.org/reports/tr44/ for full explanation
+func testDerived() {
+	if !*test {
+		return
+	}
+	f := openReader("DerivedNormalizationProps.txt")
+	defer f.Close()
+	scanner := bufio.NewScanner(f)
+	for scanner.Scan() {
+		line := scanner.Text()
+		qc := qcRe.FindStringSubmatch(line)
+		if qc == nil {
+			continue
+		}
+		rng := strings.Split(qc[1], "..")
+		i, err := strconv.ParseUint(rng[0], 16, 64)
+		if err != nil {
+			log.Fatal(err)
+		}
+		j := i
+		if len(rng) > 1 {
+			j, err = strconv.ParseUint(rng[1], 16, 64)
+			if err != nil {
+				log.Fatal(err)
+			}
+		}
+		var ftype, mode int
+		qt := strings.TrimSpace(qc[2])
+		switch qt {
+		case "NFC_QC":
+			ftype, mode = FCanonical, MComposed
+		case "NFD_QC":
+			ftype, mode = FCanonical, MDecomposed
+		case "NFKC_QC":
+			ftype, mode = FCompatibility, MComposed
+		case "NFKD_QC":
+			ftype, mode = FCompatibility, MDecomposed
+		default:
+			log.Fatalf(`Unexpected quick check type "%s"`, qt)
+		}
+		var qr QCResult
+		switch qc[3] {
+		case "Y":
+			qr = QCYes
+		case "N":
+			qr = QCNo
+		case "M":
+			qr = QCMaybe
+		default:
+			log.Fatalf(`Unexpected quick check value "%s"`, qc[3])
+		}
+		var lastFailed bool
+		// Verify current
+		for ; i <= j; i++ {
+			c := &chars[int(i)]
+			c.forms[ftype].verified[mode] = true
+			curqr := c.forms[ftype].quickCheck[mode]
+			if curqr != qr {
+				if !lastFailed {
+					logger.Printf("%s: %.4X..%.4X -- %s\n",
+						qt, int(i), int(j), line[0:50])
+				}
+				logger.Printf("%U: FAILED %s (was %v need %v)\n",
+					int(i), qt, curqr, qr)
+				lastFailed = true
+			}
+		}
+	}
+	if scanner.Err() != nil {
+		logger.Fatal(scanner.Err())
+	}
+	// Any unspecified value must be QCYes. Verify this.
+	for i, c := range chars {
+		for j, fd := range c.forms {
+			for k, qr := range fd.quickCheck {
+				if !fd.verified[k] && qr != QCYes {
+					m := "%U: FAIL F:%d M:%d (was %v need Yes) %s\n"
+					logger.Printf(m, i, j, k, qr, c.name)
+				}
+			}
+		}
+	}
+}
diff --git a/src/pkg/exp/norm/maketesttables.go b/src/pkg/exp/norm/maketesttables.go
new file mode 100644
index 0000000..6d11ec0
--- /dev/null
+++ b/src/pkg/exp/norm/maketesttables.go
@@ -0,0 +1,45 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Generate test data for trie code.
+
+package main
+
+import (
+	"fmt"
+)
+
+func main() {
+	printTestTables()
+}
+
+// We take the smallest, largest and an arbitrary value for each
+// of the UTF-8 sequence lengths.
+var testRunes = []rune{
+	0x01, 0x0C, 0x7F, // 1-byte sequences
+	0x80, 0x100, 0x7FF, // 2-byte sequences
+	0x800, 0x999, 0xFFFF, // 3-byte sequences
+	0x10000, 0x10101, 0x10FFFF, // 4-byte sequences
+	0x200, 0x201, 0x202, 0x210, 0x215, // five entries in one sparse block
+}
+
+const fileHeader = `// Generated by running
+//	maketesttables
+// DO NOT EDIT
+
+package norm
+
+`
+
+func printTestTables() {
+	fmt.Print(fileHeader)
+	fmt.Printf("var testRunes = %#v\n\n", testRunes)
+	t := newNode()
+	for i, r := range testRunes {
+		t.insert(r, uint16(i))
+	}
+	t.printTables("testdata")
+}
diff --git a/src/pkg/exp/norm/norm_test.go b/src/pkg/exp/norm/norm_test.go
new file mode 100644
index 0000000..12dacfc
--- /dev/null
+++ b/src/pkg/exp/norm/norm_test.go
@@ -0,0 +1,14 @@
+// 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 norm_test
+
+import (
+	"testing"
+)
+
+func TestPlaceHolder(t *testing.T) {
+	// Does nothing, just allows the Makefile to be canonical
+	// while waiting for the package itself to be written.
+}
diff --git a/src/pkg/exp/norm/normalize.go b/src/pkg/exp/norm/normalize.go
new file mode 100644
index 0000000..1c3e49b
--- /dev/null
+++ b/src/pkg/exp/norm/normalize.go
@@ -0,0 +1,478 @@
+// 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 norm contains types and functions for normalizing Unicode strings.
+package norm
+
+import "unicode/utf8"
+
+// A Form denotes a canonical representation of Unicode code points.
+// The Unicode-defined normalization and equivalence forms are:
+//
+//   NFC   Unicode Normalization Form C
+//   NFD   Unicode Normalization Form D
+//   NFKC  Unicode Normalization Form KC
+//   NFKD  Unicode Normalization Form KD
+//
+// For a Form f, this documentation uses the notation f(x) to mean
+// the bytes or string x converted to the given form.
+// A position n in x is called a boundary if conversion to the form can
+// proceed independently on both sides:
+//   f(x) == append(f(x[0:n]), f(x[n:])...)
+//
+// References: http://unicode.org/reports/tr15/ and
+// http://unicode.org/notes/tn5/.
+type Form int
+
+const (
+	NFC Form = iota
+	NFD
+	NFKC
+	NFKD
+)
+
+// Bytes returns f(b). May return b if f(b) = b.
+func (f Form) Bytes(b []byte) []byte {
+	rb := reorderBuffer{}
+	rb.init(f, b)
+	n := quickSpan(&rb, 0)
+	if n == len(b) {
+		return b
+	}
+	out := make([]byte, n, len(b))
+	copy(out, b[0:n])
+	return doAppend(&rb, out, n)
+}
+
+// String returns f(s).
+func (f Form) String(s string) string {
+	rb := reorderBuffer{}
+	rb.initString(f, s)
+	n := quickSpan(&rb, 0)
+	if n == len(s) {
+		return s
+	}
+	out := make([]byte, n, len(s))
+	copy(out, s[0:n])
+	return string(doAppend(&rb, out, n))
+}
+
+// IsNormal returns true if b == f(b).
+func (f Form) IsNormal(b []byte) bool {
+	rb := reorderBuffer{}
+	rb.init(f, b)
+	bp := quickSpan(&rb, 0)
+	if bp == len(b) {
+		return true
+	}
+	for bp < len(b) {
+		decomposeSegment(&rb, bp)
+		if rb.f.composing {
+			rb.compose()
+		}
+		for i := 0; i < rb.nrune; i++ {
+			info := rb.rune[i]
+			if bp+int(info.size) > len(b) {
+				return false
+			}
+			p := info.pos
+			pe := p + info.size
+			for ; p < pe; p++ {
+				if b[bp] != rb.byte[p] {
+					return false
+				}
+				bp++
+			}
+		}
+		rb.reset()
+		bp = quickSpan(&rb, bp)
+	}
+	return true
+}
+
+// IsNormalString returns true if s == f(s).
+func (f Form) IsNormalString(s string) bool {
+	rb := reorderBuffer{}
+	rb.initString(f, s)
+	bp := quickSpan(&rb, 0)
+	if bp == len(s) {
+		return true
+	}
+	for bp < len(s) {
+		decomposeSegment(&rb, bp)
+		if rb.f.composing {
+			rb.compose()
+		}
+		for i := 0; i < rb.nrune; i++ {
+			info := rb.rune[i]
+			if bp+int(info.size) > len(s) {
+				return false
+			}
+			p := info.pos
+			pe := p + info.size
+			for ; p < pe; p++ {
+				if s[bp] != rb.byte[p] {
+					return false
+				}
+				bp++
+			}
+		}
+		rb.reset()
+		bp = quickSpan(&rb, bp)
+	}
+	return true
+}
+
+// patchTail fixes a case where a rune may be incorrectly normalized
+// if it is followed by illegal continuation bytes. It returns the
+// patched buffer and whether there were trailing continuation bytes.
+func patchTail(rb *reorderBuffer, buf []byte) ([]byte, bool) {
+	info, p := lastRuneStart(&rb.f, buf)
+	if p == -1 || info.size == 0 {
+		return buf, false
+	}
+	end := p + int(info.size)
+	extra := len(buf) - end
+	if extra > 0 {
+		// Potentially allocating memory. However, this only
+		// happens with ill-formed UTF-8.
+		x := make([]byte, 0)
+		x = append(x, buf[len(buf)-extra:]...)
+		buf = decomposeToLastBoundary(rb, buf[:end])
+		if rb.f.composing {
+			rb.compose()
+		}
+		buf = rb.flush(buf)
+		return append(buf, x...), true
+	}
+	return buf, false
+}
+
+func appendQuick(rb *reorderBuffer, dst []byte, i int) ([]byte, int) {
+	if rb.nsrc == i {
+		return dst, i
+	}
+	end := quickSpan(rb, i)
+	return rb.src.appendSlice(dst, i, end), end
+}
+
+// Append returns f(append(out, b...)).
+// The buffer out must be nil, empty, or equal to f(out).
+func (f Form) Append(out []byte, src ...byte) []byte {
+	if len(src) == 0 {
+		return out
+	}
+	rb := reorderBuffer{}
+	rb.init(f, src)
+	return doAppend(&rb, out, 0)
+}
+
+func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
+	src, n := rb.src, rb.nsrc
+	doMerge := len(out) > 0
+	if q := src.skipNonStarter(p); q > p {
+		// Move leading non-starters to destination.
+		out = src.appendSlice(out, p, q)
+		buf, endsInError := patchTail(rb, out)
+		if endsInError {
+			out = buf
+			doMerge = false // no need to merge, ends with illegal UTF-8
+		} else {
+			out = decomposeToLastBoundary(rb, buf) // force decomposition
+		}
+		p = q
+	}
+	fd := &rb.f
+	if doMerge {
+		var info Properties
+		if p < n {
+			info = fd.info(src, p)
+			if p == 0 && !info.BoundaryBefore() {
+				out = decomposeToLastBoundary(rb, out)
+			}
+		}
+		if info.size == 0 || info.BoundaryBefore() {
+			if fd.composing {
+				rb.compose()
+			}
+			out = rb.flush(out)
+			if info.size == 0 {
+				// Append incomplete UTF-8 encoding.
+				return src.appendSlice(out, p, n)
+			}
+		}
+	}
+	if rb.nrune == 0 {
+		out, p = appendQuick(rb, out, p)
+	}
+	for p < n {
+		p = decomposeSegment(rb, p)
+		if fd.composing {
+			rb.compose()
+		}
+		out = rb.flush(out)
+		out, p = appendQuick(rb, out, p)
+	}
+	return out
+}
+
+// AppendString returns f(append(out, []byte(s))).
+// The buffer out must be nil, empty, or equal to f(out).
+func (f Form) AppendString(out []byte, src string) []byte {
+	if len(src) == 0 {
+		return out
+	}
+	rb := reorderBuffer{}
+	rb.initString(f, src)
+	return doAppend(&rb, out, 0)
+}
+
+// QuickSpan returns a boundary n such that b[0:n] == f(b[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) QuickSpan(b []byte) int {
+	rb := reorderBuffer{}
+	rb.init(f, b)
+	n := quickSpan(&rb, 0)
+	return n
+}
+
+func quickSpan(rb *reorderBuffer, i int) int {
+	var lastCC uint8
+	var nc int
+	lastSegStart := i
+	src, n := rb.src, rb.nsrc
+	for i < n {
+		if j := src.skipASCII(i, n); i != j {
+			i = j
+			lastSegStart = i - 1
+			lastCC = 0
+			nc = 0
+			continue
+		}
+		info := rb.f.info(src, i)
+		if info.size == 0 {
+			// include incomplete runes
+			return n
+		}
+		cc := info.ccc
+		if rb.f.composing {
+			if !info.isYesC() {
+				break
+			}
+		} else {
+			if !info.isYesD() {
+				break
+			}
+		}
+		if cc == 0 {
+			lastSegStart = i
+			nc = 0
+		} else {
+			if nc >= maxCombiningChars {
+				lastSegStart = i
+				lastCC = cc
+				nc = 1
+			} else {
+				if lastCC > cc {
+					return lastSegStart
+				}
+				nc++
+			}
+		}
+		lastCC = cc
+		i += int(info.size)
+	}
+	if i == n {
+		return n
+	}
+	if rb.f.composing {
+		return lastSegStart
+	}
+	return i
+}
+
+// QuickSpanString returns a boundary n such that b[0:n] == f(s[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) QuickSpanString(s string) int {
+	rb := reorderBuffer{}
+	rb.initString(f, s)
+	return quickSpan(&rb, 0)
+}
+
+// FirstBoundary returns the position i of the first boundary in b
+// or -1 if b contains no boundary.
+func (f Form) FirstBoundary(b []byte) int {
+	rb := reorderBuffer{}
+	rb.init(f, b)
+	return firstBoundary(&rb)
+}
+
+func firstBoundary(rb *reorderBuffer) int {
+	src, nsrc := rb.src, rb.nsrc
+	i := src.skipNonStarter(0)
+	if i >= nsrc {
+		return -1
+	}
+	fd := &rb.f
+	info := fd.info(src, i)
+	for n := 0; info.size != 0 && !info.BoundaryBefore(); {
+		i += int(info.size)
+		if n++; n >= maxCombiningChars {
+			return i
+		}
+		if i >= nsrc {
+			if !info.BoundaryAfter() {
+				return -1
+			}
+			return nsrc
+		}
+		info = fd.info(src, i)
+	}
+	if info.size == 0 {
+		return -1
+	}
+	return i
+}
+
+// FirstBoundaryInString returns the position i of the first boundary in s
+// or -1 if s contains no boundary.
+func (f Form) FirstBoundaryInString(s string) int {
+	rb := reorderBuffer{}
+	rb.initString(f, s)
+	return firstBoundary(&rb)
+}
+
+// LastBoundary returns the position i of the last boundary in b
+// or -1 if b contains no boundary.
+func (f Form) LastBoundary(b []byte) int {
+	return lastBoundary(formTable[f], b)
+}
+
+func lastBoundary(fd *formInfo, b []byte) int {
+	i := len(b)
+	info, p := lastRuneStart(fd, b)
+	if p == -1 {
+		return -1
+	}
+	if info.size == 0 { // ends with incomplete rune
+		if p == 0 { // starts with incomplete rune
+			return -1
+		}
+		i = p
+		info, p = lastRuneStart(fd, b[:i])
+		if p == -1 { // incomplete UTF-8 encoding or non-starter bytes without a starter
+			return i
+		}
+	}
+	if p+int(info.size) != i { // trailing non-starter bytes: illegal UTF-8
+		return i
+	}
+	if info.BoundaryAfter() {
+		return i
+	}
+	i = p
+	for n := 0; i >= 0 && !info.BoundaryBefore(); {
+		info, p = lastRuneStart(fd, b[:i])
+		if n++; n >= maxCombiningChars {
+			return len(b)
+		}
+		if p+int(info.size) != i {
+			if p == -1 { // no boundary found
+				return -1
+			}
+			return i // boundary after an illegal UTF-8 encoding
+		}
+		i = p
+	}
+	return i
+}
+
+// decomposeSegment scans the first segment in src into rb.
+// It returns the number of bytes consumed from src.
+// TODO(mpvl): consider inserting U+034f (Combining Grapheme Joiner)
+// when we detect a sequence of 30+ non-starter chars.
+func decomposeSegment(rb *reorderBuffer, sp int) int {
+	// Force one character to be consumed.
+	info := rb.f.info(rb.src, sp)
+	if info.size == 0 {
+		return 0
+	}
+	for rb.insert(rb.src, sp, info) {
+		sp += int(info.size)
+		if sp >= rb.nsrc {
+			break
+		}
+		info = rb.f.info(rb.src, sp)
+		bound := info.BoundaryBefore()
+		if bound || info.size == 0 {
+			break
+		}
+	}
+	return sp
+}
+
+// lastRuneStart returns the runeInfo and position of the last
+// rune in buf or the zero runeInfo and -1 if no rune was found.
+func lastRuneStart(fd *formInfo, buf []byte) (Properties, int) {
+	p := len(buf) - 1
+	for ; p >= 0 && !utf8.RuneStart(buf[p]); p-- {
+	}
+	if p < 0 {
+		return Properties{}, -1
+	}
+	return fd.info(inputBytes(buf), p), p
+}
+
+// decomposeToLastBoundary finds an open segment at the end of the buffer
+// and scans it into rb. Returns the buffer minus the last segment.
+func decomposeToLastBoundary(rb *reorderBuffer, buf []byte) []byte {
+	fd := &rb.f
+	info, i := lastRuneStart(fd, buf)
+	if int(info.size) != len(buf)-i {
+		// illegal trailing continuation bytes
+		return buf
+	}
+	if info.BoundaryAfter() {
+		return buf
+	}
+	var add [maxBackRunes]Properties // stores runeInfo in reverse order
+	add[0] = info
+	padd := 1
+	n := 1
+	p := len(buf) - int(info.size)
+	for ; p >= 0 && !info.BoundaryBefore(); p -= int(info.size) {
+		info, i = lastRuneStart(fd, buf[:p])
+		if int(info.size) != p-i {
+			break
+		}
+		// Check that decomposition doesn't result in overflow.
+		if info.hasDecomposition() {
+			if isHangul(buf) {
+				i += int(info.size)
+				n++
+			} else {
+				dcomp := info.Decomposition()
+				for i := 0; i < len(dcomp); {
+					inf := rb.f.info(inputBytes(dcomp), i)
+					i += int(inf.size)
+					n++
+				}
+			}
+		} else {
+			n++
+		}
+		if n > maxBackRunes {
+			break
+		}
+		add[padd] = info
+		padd++
+	}
+	pp := p
+	for padd--; padd >= 0; padd-- {
+		info = add[padd]
+		rb.insert(inputBytes(buf), pp, info)
+		pp += int(info.size)
+	}
+	return buf[:p]
+}
diff --git a/src/pkg/exp/norm/normalize_test.go b/src/pkg/exp/norm/normalize_test.go
new file mode 100644
index 0000000..9a6b46e
--- /dev/null
+++ b/src/pkg/exp/norm/normalize_test.go
@@ -0,0 +1,750 @@
+// 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 norm
+
+import (
+	"bytes"
+	"io"
+	"strings"
+	"testing"
+)
+
+type PositionTest struct {
+	input  string
+	pos    int
+	buffer string // expected contents of reorderBuffer, if applicable
+}
+
+type positionFunc func(rb *reorderBuffer, s string) int
+
+func runPosTests(t *testing.T, name string, f Form, fn positionFunc, tests []PositionTest) {
+	rb := reorderBuffer{}
+	rb.init(f, nil)
+	for i, test := range tests {
+		rb.reset()
+		rb.src = inputString(test.input)
+		rb.nsrc = len(test.input)
+		pos := fn(&rb, test.input)
+		if pos != test.pos {
+			t.Errorf("%s:%d: position is %d; want %d", name, i, pos, test.pos)
+		}
+		runes := []rune(test.buffer)
+		if rb.nrune != len(runes) {
+			t.Errorf("%s:%d: reorder buffer length is %d; want %d", name, i, rb.nrune, len(runes))
+			continue
+		}
+		for j, want := range runes {
+			found := rune(rb.runeAt(j))
+			if found != want {
+				t.Errorf("%s:%d: rune at %d is %U; want %U", name, i, j, found, want)
+			}
+		}
+	}
+}
+
+var decomposeSegmentTests = []PositionTest{
+	// illegal runes
+	{"\xC0", 0, ""},
+	{"\u00E0\x80", 2, "\u0061\u0300"},
+	// starter
+	{"a", 1, "a"},
+	{"ab", 1, "a"},
+	// starter + composing
+	{"a\u0300", 3, "a\u0300"},
+	{"a\u0300b", 3, "a\u0300"},
+	// with decomposition
+	{"\u00C0", 2, "A\u0300"},
+	{"\u00C0b", 2, "A\u0300"},
+	// long
+	{strings.Repeat("\u0300", 31), 62, strings.Repeat("\u0300", 31)},
+	// ends with incomplete UTF-8 encoding
+	{"\xCC", 0, ""},
+	{"\u0300\xCC", 2, "\u0300"},
+}
+
+func decomposeSegmentF(rb *reorderBuffer, s string) int {
+	rb.src = inputString(s)
+	rb.nsrc = len(s)
+	return decomposeSegment(rb, 0)
+}
+
+func TestDecomposeSegment(t *testing.T) {
+	runPosTests(t, "TestDecomposeSegment", NFC, decomposeSegmentF, decomposeSegmentTests)
+}
+
+var firstBoundaryTests = []PositionTest{
+	// no boundary
+	{"", -1, ""},
+	{"\u0300", -1, ""},
+	{"\x80\x80", -1, ""},
+	// illegal runes
+	{"\xff", 0, ""},
+	{"\u0300\xff", 2, ""},
+	{"\u0300\xc0\x80\x80", 2, ""},
+	// boundaries
+	{"a", 0, ""},
+	{"\u0300a", 2, ""},
+	// Hangul
+	{"\u1103\u1161", 0, ""},
+	{"\u110B\u1173\u11B7", 0, ""},
+	{"\u1161\u110B\u1173\u11B7", 3, ""},
+	{"\u1173\u11B7\u1103\u1161", 6, ""},
+	// too many combining characters.
+	{strings.Repeat("\u0300", maxCombiningChars-1), -1, ""},
+	{strings.Repeat("\u0300", maxCombiningChars), 60, ""},
+	{strings.Repeat("\u0300", maxCombiningChars+1), 60, ""},
+}
+
+func firstBoundaryF(rb *reorderBuffer, s string) int {
+	return rb.f.form.FirstBoundary([]byte(s))
+}
+
+func firstBoundaryStringF(rb *reorderBuffer, s string) int {
+	return rb.f.form.FirstBoundaryInString(s)
+}
+
+func TestFirstBoundary(t *testing.T) {
+	runPosTests(t, "TestFirstBoundary", NFC, firstBoundaryF, firstBoundaryTests)
+	runPosTests(t, "TestFirstBoundaryInString", NFC, firstBoundaryStringF, firstBoundaryTests)
+}
+
+var decomposeToLastTests = []PositionTest{
+	// ends with inert character
+	{"Hello!", 6, ""},
+	{"\u0632", 2, ""},
+	{"a\u0301\u0635", 5, ""},
+	// ends with non-inert starter
+	{"a", 0, "a"},
+	{"a\u0301a", 3, "a"},
+	{"a\u0301\u03B9", 3, "\u03B9"},
+	{"a\u0327", 0, "a\u0327"},
+	// illegal runes
+	{"\xFF", 1, ""},
+	{"aa\xFF", 3, ""},
+	{"\xC0\x80\x80", 3, ""},
+	{"\xCC\x80\x80", 3, ""},
+	// ends with incomplete UTF-8 encoding
+	{"a\xCC", 2, ""},
+	// ends with combining characters
+	{"\u0300\u0301", 0, "\u0300\u0301"},
+	{"a\u0300\u0301", 0, "a\u0300\u0301"},
+	{"a\u0301\u0308", 0, "a\u0301\u0308"},
+	{"a\u0308\u0301", 0, "a\u0308\u0301"},
+	{"aaaa\u0300\u0301", 3, "a\u0300\u0301"},
+	{"\u0300a\u0300\u0301", 2, "a\u0300\u0301"},
+	{"\u00C0", 0, "A\u0300"},
+	{"a\u00C0", 1, "A\u0300"},
+	// decomposing
+	{"a\u0300\uFDC0", 3, "\u0645\u062C\u064A"},
+	{"\uFDC0" + strings.Repeat("\u0300", 26), 0, "\u0645\u062C\u064A" + strings.Repeat("\u0300", 26)},
+	// Hangul
+	{"a\u1103", 1, "\u1103"},
+	{"a\u110B", 1, "\u110B"},
+	{"a\u110B\u1173", 1, "\u110B\u1173"},
+	// See comment in composition.go:compBoundaryAfter.
+	{"a\u110B\u1173\u11B7", 1, "\u110B\u1173\u11B7"},
+	{"a\uC73C", 1, "\u110B\u1173"},
+	{"다음", 3, "\u110B\u1173\u11B7"},
+	{"다", 0, "\u1103\u1161"},
+	{"\u1103\u1161\u110B\u1173\u11B7", 6, "\u110B\u1173\u11B7"},
+	{"\u110B\u1173\u11B7\u1103\u1161", 9, "\u1103\u1161"},
+	{"다음음", 6, "\u110B\u1173\u11B7"},
+	{"음다다", 6, "\u1103\u1161"},
+	// buffer overflow
+	{"a" + strings.Repeat("\u0300", 30), 3, strings.Repeat("\u0300", 29)},
+	{"\uFDFA" + strings.Repeat("\u0300", 14), 3, strings.Repeat("\u0300", 14)},
+	// weird UTF-8
+	{"a\u0300\u11B7", 0, "a\u0300\u11B7"},
+}
+
+func decomposeToLast(rb *reorderBuffer, s string) int {
+	buf := decomposeToLastBoundary(rb, []byte(s))
+	return len(buf)
+}
+
+func TestDecomposeToLastBoundary(t *testing.T) {
+	runPosTests(t, "TestDecomposeToLastBoundary", NFKC, decomposeToLast, decomposeToLastTests)
+}
+
+var lastBoundaryTests = []PositionTest{
+	// ends with inert character
+	{"Hello!", 6, ""},
+	{"\u0632", 2, ""},
+	// ends with non-inert starter
+	{"a", 0, ""},
+	// illegal runes
+	{"\xff", 1, ""},
+	{"aa\xff", 3, ""},
+	{"a\xff\u0300", 1, ""},
+	{"\xc0\x80\x80", 3, ""},
+	{"\xc0\x80\x80\u0300", 3, ""},
+	// ends with incomplete UTF-8 encoding
+	{"\xCC", -1, ""},
+	{"\xE0\x80", -1, ""},
+	{"\xF0\x80\x80", -1, ""},
+	{"a\xCC", 0, ""},
+	{"\x80\xCC", 1, ""},
+	{"\xCC\xCC", 1, ""},
+	// ends with combining characters
+	{"a\u0300\u0301", 0, ""},
+	{"aaaa\u0300\u0301", 3, ""},
+	{"\u0300a\u0300\u0301", 2, ""},
+	{"\u00C0", 0, ""},
+	{"a\u00C0", 1, ""},
+	// decomposition may recombine
+	{"\u0226", 0, ""},
+	// no boundary
+	{"", -1, ""},
+	{"\u0300\u0301", -1, ""},
+	{"\u0300", -1, ""},
+	{"\x80\x80", -1, ""},
+	{"\x80\x80\u0301", -1, ""},
+	// Hangul
+	{"다음", 3, ""},
+	{"다", 0, ""},
+	{"\u1103\u1161\u110B\u1173\u11B7", 6, ""},
+	{"\u110B\u1173\u11B7\u1103\u1161", 9, ""},
+	// too many combining characters.
+	{strings.Repeat("\u0300", maxCombiningChars-1), -1, ""},
+	{strings.Repeat("\u0300", maxCombiningChars), 60, ""},
+	{strings.Repeat("\u0300", maxCombiningChars+1), 62, ""},
+}
+
+func lastBoundaryF(rb *reorderBuffer, s string) int {
+	return rb.f.form.LastBoundary([]byte(s))
+}
+
+func TestLastBoundary(t *testing.T) {
+	runPosTests(t, "TestLastBoundary", NFC, lastBoundaryF, lastBoundaryTests)
+}
+
+var quickSpanTests = []PositionTest{
+	{"", 0, ""},
+	// starters
+	{"a", 1, ""},
+	{"abc", 3, ""},
+	{"\u043Eb", 3, ""},
+	// incomplete last rune.
+	{"\xCC", 1, ""},
+	{"a\xCC", 2, ""},
+	// incorrectly ordered combining characters
+	{"\u0300\u0316", 0, ""},
+	{"\u0300\u0316cd", 0, ""},
+	// have a maximum number of combining characters.
+	{strings.Repeat("\u035D", 30) + "\u035B", 62, ""},
+	{"a" + strings.Repeat("\u035D", 30) + "\u035B", 63, ""},
+	{"Ɵ" + strings.Repeat("\u035D", 30) + "\u035B", 64, ""},
+	{"aa" + strings.Repeat("\u035D", 30) + "\u035B", 64, ""},
+}
+
+var quickSpanNFDTests = []PositionTest{
+	// needs decomposing
+	{"\u00C0", 0, ""},
+	{"abc\u00C0", 3, ""},
+	// correctly ordered combining characters
+	{"\u0300", 2, ""},
+	{"ab\u0300", 4, ""},
+	{"ab\u0300cd", 6, ""},
+	{"\u0300cd", 4, ""},
+	{"\u0316\u0300", 4, ""},
+	{"ab\u0316\u0300", 6, ""},
+	{"ab\u0316\u0300cd", 8, ""},
+	{"ab\u0316\u0300\u00C0", 6, ""},
+	{"\u0316\u0300cd", 6, ""},
+	{"\u043E\u0308b", 5, ""},
+	// incorrectly ordered combining characters
+	{"ab\u0300\u0316", 1, ""}, // TODO: we could skip 'b' as well.
+	{"ab\u0300\u0316cd", 1, ""},
+	// Hangul
+	{"같은", 0, ""},
+}
+
+var quickSpanNFCTests = []PositionTest{
+	// okay composed
+	{"\u00C0", 2, ""},
+	{"abc\u00C0", 5, ""},
+	// correctly ordered combining characters
+	{"ab\u0300", 1, ""},
+	{"ab\u0300cd", 1, ""},
+	{"ab\u0316\u0300", 1, ""},
+	{"ab\u0316\u0300cd", 1, ""},
+	{"\u00C0\u035D", 4, ""},
+	// we do not special case leading combining characters
+	{"\u0300cd", 0, ""},
+	{"\u0300", 0, ""},
+	{"\u0316\u0300", 0, ""},
+	{"\u0316\u0300cd", 0, ""},
+	// incorrectly ordered combining characters
+	{"ab\u0300\u0316", 1, ""},
+	{"ab\u0300\u0316cd", 1, ""},
+	// Hangul
+	{"같은", 6, ""},
+}
+
+func doQuickSpan(rb *reorderBuffer, s string) int {
+	return rb.f.form.QuickSpan([]byte(s))
+}
+
+func doQuickSpanString(rb *reorderBuffer, s string) int {
+	return rb.f.form.QuickSpanString(s)
+}
+
+func TestQuickSpan(t *testing.T) {
+	runPosTests(t, "TestQuickSpanNFD1", NFD, doQuickSpan, quickSpanTests)
+	runPosTests(t, "TestQuickSpanNFD2", NFD, doQuickSpan, quickSpanNFDTests)
+	runPosTests(t, "TestQuickSpanNFC1", NFC, doQuickSpan, quickSpanTests)
+	runPosTests(t, "TestQuickSpanNFC2", NFC, doQuickSpan, quickSpanNFCTests)
+
+	runPosTests(t, "TestQuickSpanStringNFD1", NFD, doQuickSpanString, quickSpanTests)
+	runPosTests(t, "TestQuickSpanStringNFD2", NFD, doQuickSpanString, quickSpanNFDTests)
+	runPosTests(t, "TestQuickSpanStringNFC1", NFC, doQuickSpanString, quickSpanTests)
+	runPosTests(t, "TestQuickSpanStringNFC2", NFC, doQuickSpanString, quickSpanNFCTests)
+}
+
+var isNormalTests = []PositionTest{
+	{"", 1, ""},
+	// illegal runes
+	{"\xff", 1, ""},
+	// starters
+	{"a", 1, ""},
+	{"abc", 1, ""},
+	{"\u043Eb", 1, ""},
+	// incorrectly ordered combining characters
+	{"\u0300\u0316", 0, ""},
+	{"ab\u0300\u0316", 0, ""},
+	{"ab\u0300\u0316cd", 0, ""},
+	{"\u0300\u0316cd", 0, ""},
+}
+var isNormalNFDTests = []PositionTest{
+	// needs decomposing
+	{"\u00C0", 0, ""},
+	{"abc\u00C0", 0, ""},
+	// correctly ordered combining characters
+	{"\u0300", 1, ""},
+	{"ab\u0300", 1, ""},
+	{"ab\u0300cd", 1, ""},
+	{"\u0300cd", 1, ""},
+	{"\u0316\u0300", 1, ""},
+	{"ab\u0316\u0300", 1, ""},
+	{"ab\u0316\u0300cd", 1, ""},
+	{"\u0316\u0300cd", 1, ""},
+	{"\u043E\u0308b", 1, ""},
+	// Hangul
+	{"같은", 0, ""},
+}
+var isNormalNFCTests = []PositionTest{
+	// okay composed
+	{"\u00C0", 1, ""},
+	{"abc\u00C0", 1, ""},
+	// need reordering
+	{"a\u0300", 0, ""},
+	{"a\u0300cd", 0, ""},
+	{"a\u0316\u0300", 0, ""},
+	{"a\u0316\u0300cd", 0, ""},
+	// correctly ordered combining characters
+	{"ab\u0300", 1, ""},
+	{"ab\u0300cd", 1, ""},
+	{"ab\u0316\u0300", 1, ""},
+	{"ab\u0316\u0300cd", 1, ""},
+	{"\u00C0\u035D", 1, ""},
+	{"\u0300", 1, ""},
+	{"\u0316\u0300cd", 1, ""},
+	// Hangul
+	{"같은", 1, ""},
+}
+
+func isNormalF(rb *reorderBuffer, s string) int {
+	if rb.f.form.IsNormal([]byte(s)) {
+		return 1
+	}
+	return 0
+}
+
+func TestIsNormal(t *testing.T) {
+	runPosTests(t, "TestIsNormalNFD1", NFD, isNormalF, isNormalTests)
+	runPosTests(t, "TestIsNormalNFD2", NFD, isNormalF, isNormalNFDTests)
+	runPosTests(t, "TestIsNormalNFC1", NFC, isNormalF, isNormalTests)
+	runPosTests(t, "TestIsNormalNFC2", NFC, isNormalF, isNormalNFCTests)
+}
+
+type AppendTest struct {
+	left  string
+	right string
+	out   string
+}
+
+type appendFunc func(f Form, out []byte, s string) []byte
+
+func runAppendTests(t *testing.T, name string, f Form, fn appendFunc, tests []AppendTest) {
+	for i, test := range tests {
+		out := []byte(test.left)
+		out = fn(f, out, test.right)
+		outs := string(out)
+		if len(outs) != len(test.out) {
+			t.Errorf("%s:%d: length is %d; want %d", name, i, len(outs), len(test.out))
+		}
+		if outs != test.out {
+			// Find first rune that differs and show context.
+			ir := []rune(outs)
+			ig := []rune(test.out)
+			for j := 0; j < len(ir) && j < len(ig); j++ {
+				if ir[j] == ig[j] {
+					continue
+				}
+				if j -= 3; j < 0 {
+					j = 0
+				}
+				for e := j + 7; j < e && j < len(ir) && j < len(ig); j++ {
+					t.Errorf("%s:%d: runeAt(%d) = %U; want %U", name, i, j, ir[j], ig[j])
+				}
+				break
+			}
+		}
+	}
+}
+
+var appendTests = []AppendTest{
+	// empty buffers
+	{"", "", ""},
+	{"a", "", "a"},
+	{"", "a", "a"},
+	{"", "\u0041\u0307\u0304", "\u01E0"},
+	// segment split across buffers
+	{"", "a\u0300b", "\u00E0b"},
+	{"a", "\u0300b", "\u00E0b"},
+	{"a", "\u0300\u0316", "\u00E0\u0316"},
+	{"a", "\u0316\u0300", "\u00E0\u0316"},
+	{"a", "\u0300a\u0300", "\u00E0\u00E0"},
+	{"a", "\u0300a\u0300a\u0300", "\u00E0\u00E0\u00E0"},
+	{"a", "\u0300aaa\u0300aaa\u0300", "\u00E0aa\u00E0aa\u00E0"},
+	{"a\u0300", "\u0327", "\u00E0\u0327"},
+	{"a\u0327", "\u0300", "\u00E0\u0327"},
+	{"a\u0316", "\u0300", "\u00E0\u0316"},
+	{"\u0041\u0307", "\u0304", "\u01E0"},
+	// Hangul
+	{"", "\u110B\u1173", "\uC73C"},
+	{"", "\u1103\u1161", "\uB2E4"},
+	{"", "\u110B\u1173\u11B7", "\uC74C"},
+	{"", "\u320E", "\x28\uAC00\x29"},
+	{"", "\x28\u1100\u1161\x29", "\x28\uAC00\x29"},
+	{"\u1103", "\u1161", "\uB2E4"},
+	{"\u110B", "\u1173\u11B7", "\uC74C"},
+	{"\u110B\u1173", "\u11B7", "\uC74C"},
+	{"\uC73C", "\u11B7", "\uC74C"},
+	// UTF-8 encoding split across buffers
+	{"a\xCC", "\x80", "\u00E0"},
+	{"a\xCC", "\x80b", "\u00E0b"},
+	{"a\xCC", "\x80a\u0300", "\u00E0\u00E0"},
+	{"a\xCC", "\x80\x80", "\u00E0\x80"},
+	{"a\xCC", "\x80\xCC", "\u00E0\xCC"},
+	{"a\u0316\xCC", "\x80a\u0316\u0300", "\u00E0\u0316\u00E0\u0316"},
+	// ending in incomplete UTF-8 encoding
+	{"", "\xCC", "\xCC"},
+	{"a", "\xCC", "a\xCC"},
+	{"a", "b\xCC", "ab\xCC"},
+	{"\u0226", "\xCC", "\u0226\xCC"},
+	// illegal runes
+	{"", "\x80", "\x80"},
+	{"", "\x80\x80\x80", "\x80\x80\x80"},
+	{"", "\xCC\x80\x80\x80", "\xCC\x80\x80\x80"},
+	{"", "a\x80", "a\x80"},
+	{"", "a\x80\x80\x80", "a\x80\x80\x80"},
+	{"", "a\x80\x80\x80\x80\x80\x80", "a\x80\x80\x80\x80\x80\x80"},
+	{"a", "\x80\x80\x80", "a\x80\x80\x80"},
+	// overflow
+	{"", strings.Repeat("\x80", 33), strings.Repeat("\x80", 33)},
+	{strings.Repeat("\x80", 33), "", strings.Repeat("\x80", 33)},
+	{strings.Repeat("\x80", 33), strings.Repeat("\x80", 33), strings.Repeat("\x80", 66)},
+	// overflow of combining characters
+	{strings.Repeat("\u0300", 33), "", strings.Repeat("\u0300", 33)},
+	// weird UTF-8
+	{"\u00E0\xE1", "\x86", "\u00E0\xE1\x86"},
+	{"a\u0300\u11B7", "\u0300", "\u00E0\u11B7\u0300"},
+	{"a\u0300\u11B7\u0300", "\u0300", "\u00E0\u11B7\u0300\u0300"},
+	{"\u0300", "\xF8\x80\x80\x80\x80\u0300", "\u0300\xF8\x80\x80\x80\x80\u0300"},
+	{"\u0300", "\xFC\x80\x80\x80\x80\x80\u0300", "\u0300\xFC\x80\x80\x80\x80\x80\u0300"},
+	{"\xF8\x80\x80\x80\x80\u0300", "\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
+	{"\xFC\x80\x80\x80\x80\x80\u0300", "\u0300", "\xFC\x80\x80\x80\x80\x80\u0300\u0300"},
+	{"\xF8\x80\x80\x80", "\x80\u0300\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
+}
+
+func appendF(f Form, out []byte, s string) []byte {
+	return f.Append(out, []byte(s)...)
+}
+
+func appendStringF(f Form, out []byte, s string) []byte {
+	return f.AppendString(out, s)
+}
+
+func bytesF(f Form, out []byte, s string) []byte {
+	buf := []byte{}
+	buf = append(buf, out...)
+	buf = append(buf, s...)
+	return f.Bytes(buf)
+}
+
+func stringF(f Form, out []byte, s string) []byte {
+	outs := string(out) + s
+	return []byte(f.String(outs))
+}
+
+func TestAppend(t *testing.T) {
+	runAppendTests(t, "TestAppend", NFKC, appendF, appendTests)
+	runAppendTests(t, "TestAppendString", NFKC, appendStringF, appendTests)
+	runAppendTests(t, "TestBytes", NFKC, bytesF, appendTests)
+	runAppendTests(t, "TestString", NFKC, stringF, appendTests)
+}
+
+func appendBench(f Form, in []byte) func() {
+	buf := make([]byte, 0, 4*len(in))
+	return func() {
+		f.Append(buf, in...)
+	}
+}
+
+func iterBench(f Form, in []byte) func() {
+	iter := Iter{}
+	return func() {
+		iter.Init(f, in)
+		for !iter.Done() {
+			iter.Next()
+		}
+	}
+}
+
+func readerBench(f Form, in []byte) func() {
+	buf := make([]byte, 4*len(in))
+	return func() {
+		r := f.Reader(bytes.NewReader(in))
+		var err error
+		for err == nil {
+			_, err = r.Read(buf)
+		}
+		if err != io.EOF {
+			panic("")
+		}
+	}
+}
+
+func writerBench(f Form, in []byte) func() {
+	buf := make([]byte, 0, 4*len(in))
+	return func() {
+		r := f.Writer(bytes.NewBuffer(buf))
+		if _, err := r.Write(in); err != nil {
+			panic("")
+		}
+	}
+}
+
+func appendBenchmarks(bm []func(), f Form, in []byte) []func() {
+	//bm = append(bm, appendBench(f, in))
+	bm = append(bm, iterBench(f, in))
+	//bm = append(bm, readerBench(f, in))
+	//bm = append(bm, writerBench(f, in))
+	return bm
+}
+
+func doFormBenchmark(b *testing.B, inf, f Form, s string) {
+	b.StopTimer()
+	in := inf.Bytes([]byte(s))
+	bm := appendBenchmarks(nil, f, in)
+	b.SetBytes(int64(len(in) * len(bm)))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		for _, fn := range bm {
+			fn()
+		}
+	}
+}
+
+var ascii = strings.Repeat("There is nothing to change here! ", 500)
+
+func BenchmarkNormalizeAsciiNFC(b *testing.B) {
+	doFormBenchmark(b, NFC, NFC, ascii)
+}
+func BenchmarkNormalizeAsciiNFD(b *testing.B) {
+	doFormBenchmark(b, NFC, NFD, ascii)
+}
+func BenchmarkNormalizeAsciiNFKC(b *testing.B) {
+	doFormBenchmark(b, NFC, NFKC, ascii)
+}
+func BenchmarkNormalizeAsciiNFKD(b *testing.B) {
+	doFormBenchmark(b, NFC, NFKD, ascii)
+}
+
+func BenchmarkNormalizeNFC2NFC(b *testing.B) {
+	doFormBenchmark(b, NFC, NFC, txt_all)
+}
+func BenchmarkNormalizeNFC2NFD(b *testing.B) {
+	doFormBenchmark(b, NFC, NFD, txt_all)
+}
+func BenchmarkNormalizeNFD2NFC(b *testing.B) {
+	doFormBenchmark(b, NFD, NFC, txt_all)
+}
+func BenchmarkNormalizeNFD2NFD(b *testing.B) {
+	doFormBenchmark(b, NFD, NFD, txt_all)
+}
+
+// Hangul is often special-cased, so we test it separately.
+func BenchmarkNormalizeHangulNFC2NFC(b *testing.B) {
+	doFormBenchmark(b, NFC, NFC, txt_kr)
+}
+func BenchmarkNormalizeHangulNFC2NFD(b *testing.B) {
+	doFormBenchmark(b, NFC, NFD, txt_kr)
+}
+func BenchmarkNormalizeHangulNFD2NFC(b *testing.B) {
+	doFormBenchmark(b, NFD, NFC, txt_kr)
+}
+func BenchmarkNormalizeHangulNFD2NFD(b *testing.B) {
+	doFormBenchmark(b, NFD, NFD, txt_kr)
+}
+
+var forms = []Form{NFC, NFD, NFKC, NFKD}
+
+func doTextBenchmark(b *testing.B, s string) {
+	b.StopTimer()
+	in := []byte(s)
+	bm := []func(){}
+	for _, f := range forms {
+		bm = appendBenchmarks(bm, f, in)
+	}
+	b.SetBytes(int64(len(s) * len(bm)))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		for _, f := range bm {
+			f()
+		}
+	}
+}
+
+func BenchmarkCanonicalOrdering(b *testing.B) {
+	doTextBenchmark(b, txt_canon)
+}
+func BenchmarkExtendedLatin(b *testing.B) {
+	doTextBenchmark(b, txt_vn)
+}
+func BenchmarkMiscTwoByteUtf8(b *testing.B) {
+	doTextBenchmark(b, twoByteUtf8)
+}
+func BenchmarkMiscThreeByteUtf8(b *testing.B) {
+	doTextBenchmark(b, threeByteUtf8)
+}
+func BenchmarkHangul(b *testing.B) {
+	doTextBenchmark(b, txt_kr)
+}
+func BenchmarkJapanese(b *testing.B) {
+	doTextBenchmark(b, txt_jp)
+}
+func BenchmarkChinese(b *testing.B) {
+	doTextBenchmark(b, txt_cn)
+}
+func BenchmarkOverflow(b *testing.B) {
+	doTextBenchmark(b, overflow)
+}
+
+var overflow = string(bytes.Repeat([]byte("\u035D"), 4096)) + "\u035B"
+
+// Tests sampled from the Canonical ordering tests (Part 2) of
+// http://unicode.org/Public/UNIDATA/NormalizationTest.txt
+const txt_canon = `\u0061\u0315\u0300\u05AE\u0300\u0062 \u0061\u0300\u0315\u0300\u05AE\u0062
+\u0061\u0302\u0315\u0300\u05AE\u0062 \u0061\u0307\u0315\u0300\u05AE\u0062
+\u0061\u0315\u0300\u05AE\u030A\u0062 \u0061\u059A\u0316\u302A\u031C\u0062
+\u0061\u032E\u059A\u0316\u302A\u0062 \u0061\u0338\u093C\u0334\u0062 
+\u0061\u059A\u0316\u302A\u0339       \u0061\u0341\u0315\u0300\u05AE\u0062
+\u0061\u0348\u059A\u0316\u302A\u0062 \u0061\u0361\u0345\u035D\u035C\u0062
+\u0061\u0366\u0315\u0300\u05AE\u0062 \u0061\u0315\u0300\u05AE\u0486\u0062
+\u0061\u05A4\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0613\u0062
+\u0061\u0315\u0300\u05AE\u0615\u0062 \u0061\u0617\u0315\u0300\u05AE\u0062
+\u0061\u0619\u0618\u064D\u064E\u0062 \u0061\u0315\u0300\u05AE\u0654\u0062
+\u0061\u0315\u0300\u05AE\u06DC\u0062 \u0061\u0733\u0315\u0300\u05AE\u0062
+\u0061\u0744\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0745\u0062
+\u0061\u09CD\u05B0\u094D\u3099\u0062 \u0061\u0E38\u0E48\u0E38\u0C56\u0062
+\u0061\u0EB8\u0E48\u0E38\u0E49\u0062 \u0061\u0F72\u0F71\u0EC8\u0F71\u0062
+\u0061\u1039\u05B0\u094D\u3099\u0062 \u0061\u05B0\u094D\u3099\u1A60\u0062
+\u0061\u3099\u093C\u0334\u1BE6\u0062 \u0061\u3099\u093C\u0334\u1C37\u0062
+\u0061\u1CD9\u059A\u0316\u302A\u0062 \u0061\u2DED\u0315\u0300\u05AE\u0062
+\u0061\u2DEF\u0315\u0300\u05AE\u0062 \u0061\u302D\u302E\u059A\u0316\u0062`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/vn/
+const txt_vn = `Với các điều kiện sau: Ghi nhận công của tác giả. 
+Nếu bạn sử dụng, chuyển đổi, hoặc xây dựng dự án từ 
+nội dung được chia sẻ này, bạn phải áp dụng giấy phép này hoặc 
+một giấy phép khác có các điều khoản tương tự như giấy phép này
+cho dự án của bạn. Hiểu rằng: Miễn — Bất kỳ các điều kiện nào
+trên đây cũng có thể được miễn bỏ nếu bạn được sự cho phép của
+người sở hữu bản quyền. Phạm vi công chúng — Khi tác phẩm hoặc
+bất kỳ chương nào của tác phẩm đã trong vùng dành cho công
+chúng theo quy định của pháp luật thì tình trạng của nó không 
+bị ảnh hưởng bởi giấy phép trong bất kỳ trường hợp nào.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/1.0/deed.ru
+const txt_ru = `При обязательном соблюдении следующих условий:
+Attribution — Вы должны атрибутировать произведение (указывать
+автора и источник) в порядке, предусмотренном автором или
+лицензиаром (но только так, чтобы никоим образом не подразумевалось,
+что они поддерживают вас или использование вами данного произведения).
+Υπό τις ακόλουθες προϋποθέσεις:`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/gr/
+const txt_gr = `Αναφορά Δημιουργού — Θα πρέπει να κάνετε την αναφορά στο έργο με τον
+τρόπο που έχει οριστεί από το δημιουργό ή το χορηγούντο την άδεια
+(χωρίς όμως να εννοείται με οποιονδήποτε τρόπο ότι εγκρίνουν εσάς ή
+τη χρήση του έργου από εσάς). Παρόμοια Διανομή — Εάν αλλοιώσετε,
+τροποποιήσετε ή δημιουργήσετε περαιτέρω βασισμένοι στο έργο θα
+μπορείτε να διανέμετε το έργο που θα προκύψει μόνο με την ίδια ή
+παρόμοια άδεια.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/deed.ar
+const txt_ar = `بموجب الشروط التالية نسب المصنف — يجب عليك أن
+تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من
+الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل).
+المشاركة على قدم المساواة — إذا كنت يعدل ، والتغيير ، أو الاستفادة
+من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد
+لهذا الترخيص.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/1.0/il/
+const txt_il = `בכפוף לתנאים הבאים: ייחוס — עליך לייחס את היצירה (לתת קרדיט) באופן
+המצויין על-ידי היוצר או מעניק הרישיון (אך לא בשום אופן המרמז על כך
+שהם תומכים בך או בשימוש שלך ביצירה). שיתוף זהה — אם תחליט/י לשנות,
+לעבד או ליצור יצירה נגזרת בהסתמך על יצירה זו, תוכל/י להפיץ את יצירתך
+החדשה רק תחת אותו הרישיון או רישיון דומה לרישיון זה.`
+
+const twoByteUtf8 = txt_ru + txt_gr + txt_ar + txt_il
+
+// Taken from http://creativecommons.org/licenses/by-sa/2.0/kr/
+const txt_kr = `다음과 같은 조건을 따라야 합니다: 저작자표시
+(Attribution) — 저작자나 이용허락자가 정한 방법으로 저작물의
+원저작자를 표시하여야 합니다(그러나 원저작자가 이용자나 이용자의
+이용을 보증하거나 추천한다는 의미로 표시해서는 안됩니다). 
+동일조건변경허락 — 이 저작물을 이용하여 만든 이차적 저작물에는 본
+라이선스와 동일한 라이선스를 적용해야 합니다.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/th/
+const txt_th = `ภายใต้เงื่อนไข ดังต่อไปนี้ : แสดงที่มา — คุณต้องแสดงที่
+มาของงานดังกล่าว ตามรูปแบบที่ผู้สร้างสรรค์หรือผู้อนุญาตกำหนด (แต่
+ไม่ใช่ในลักษณะที่ว่า พวกเขาสนับสนุนคุณหรือสนับสนุนการที่
+คุณนำงานไปใช้) อนุญาตแบบเดียวกัน — หากคุณดัดแปลง เปลี่ยนรูป หรื
+อต่อเติมงานนี้ คุณต้องใช้สัญญาอนุญาตแบบเดียวกันหรือแบบที่เหมื
+อนกับสัญญาอนุญาตที่ใช้กับงานนี้เท่านั้น`
+
+const threeByteUtf8 = txt_th
+
+// Taken from http://creativecommons.org/licenses/by-sa/2.0/jp/
+const txt_jp = `あなたの従うべき条件は以下の通りです。
+表示 — あなたは原著作者のクレジットを表示しなければなりません。
+継承 — もしあなたがこの作品を改変、変形または加工した場合、
+あなたはその結果生じた作品をこの作品と同一の許諾条件の下でのみ
+頒布することができます。`
+
+// http://creativecommons.org/licenses/by-sa/2.5/cn/
+const txt_cn = `您可以自由: 复制、发行、展览、表演、放映、
+广播或通过信息网络传播本作品 创作演绎作品
+对本作品进行商业性使用 惟须遵守下列条件:
+署名 — 您必须按照作者或者许可人指定的方式对作品进行署名。
+相同方式共享 — 如果您改变、转换本作品或者以本作品为基础进行创作,
+您只能采用与本协议相同的许可协议发布基于本作品的演绎作品。`
+
+const txt_cjk = txt_cn + txt_jp + txt_kr
+const txt_all = txt_vn + twoByteUtf8 + threeByteUtf8 + txt_cjk
diff --git a/src/pkg/exp/norm/normregtest.go b/src/pkg/exp/norm/normregtest.go
new file mode 100644
index 0000000..b77b5b5
--- /dev/null
+++ b/src/pkg/exp/norm/normregtest.go
@@ -0,0 +1,304 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"exp/norm"
+	"flag"
+	"fmt"
+	"log"
+	"net/http"
+	"os"
+	"path"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"time"
+	"unicode"
+	"unicode/utf8"
+)
+
+func main() {
+	flag.Parse()
+	loadTestData()
+	CharacterByCharacterTests()
+	StandardTests()
+	PerformanceTest()
+	if errorCount == 0 {
+		fmt.Println("PASS")
+	}
+}
+
+const file = "NormalizationTest.txt"
+
+var url = flag.String("url",
+	"http://www.unicode.org/Public/"+unicode.Version+"/ucd/"+file,
+	"URL of Unicode database directory")
+var localFiles = flag.Bool("local",
+	false,
+	"data files have been copied to the current directory; for debugging only")
+
+var logger = log.New(os.Stderr, "", log.Lshortfile)
+
+// This regression test runs the test set in NormalizationTest.txt
+// (taken from http://www.unicode.org/Public/<unicode.Version>/ucd/).
+//
+// NormalizationTest.txt has form:
+// @Part0 # Specific cases
+// #
+// 1E0A;1E0A;0044 0307;1E0A;0044 0307; # (Ḋ; Ḋ; D◌̇; Ḋ; D◌̇; ) LATIN CAPITAL LETTER D WITH DOT ABOVE
+// 1E0C;1E0C;0044 0323;1E0C;0044 0323; # (Ḍ; Ḍ; D◌̣; Ḍ; D◌̣; ) LATIN CAPITAL LETTER D WITH DOT BELOW
+//
+// Each test has 5 columns (c1, c2, c3, c4, c5), where
+// (c1, c2, c3, c4, c5) == (c1, NFC(c1), NFD(c1), NFKC(c1), NFKD(c1))
+//
+// CONFORMANCE:
+// 1. The following invariants must be true for all conformant implementations
+//
+//    NFC
+//      c2 ==  NFC(c1) ==  NFC(c2) ==  NFC(c3)
+//      c4 ==  NFC(c4) ==  NFC(c5)
+//
+//    NFD
+//      c3 ==  NFD(c1) ==  NFD(c2) ==  NFD(c3)
+//      c5 ==  NFD(c4) ==  NFD(c5)
+//
+//    NFKC
+//      c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
+//
+//    NFKD
+//      c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
+//
+// 2. For every code point X assigned in this version of Unicode that is not
+//    specifically listed in Part 1, the following invariants must be true
+//    for all conformant implementations:
+//
+//      X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X)
+//
+
+// Column types.
+const (
+	cRaw = iota
+	cNFC
+	cNFD
+	cNFKC
+	cNFKD
+	cMaxColumns
+)
+
+// Holds data from NormalizationTest.txt
+var part []Part
+
+type Part struct {
+	name   string
+	number int
+	tests  []Test
+}
+
+type Test struct {
+	name   string
+	partnr int
+	number int
+	r      rune                // used for character by character test
+	cols   [cMaxColumns]string // Each has 5 entries, see below.
+}
+
+func (t Test) Name() string {
+	if t.number < 0 {
+		return part[t.partnr].name
+	}
+	return fmt.Sprintf("%s:%d", part[t.partnr].name, t.number)
+}
+
+var partRe = regexp.MustCompile(`@Part(\d) # (.*)$`)
+var testRe = regexp.MustCompile(`^` + strings.Repeat(`([\dA-F ]+);`, 5) + ` # (.*)$`)
+
+var counter int
+
+// Load the data form NormalizationTest.txt
+func loadTestData() {
+	if *localFiles {
+		pwd, _ := os.Getwd()
+		*url = "file://" + path.Join(pwd, file)
+	}
+	t := &http.Transport{}
+	t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
+	c := &http.Client{Transport: t}
+	resp, err := c.Get(*url)
+	if err != nil {
+		logger.Fatal(err)
+	}
+	if resp.StatusCode != 200 {
+		logger.Fatal("bad GET status for "+file, resp.Status)
+	}
+	f := resp.Body
+	defer f.Close()
+	scanner := bufio.NewScanner(f)
+	for scanner.Scan() {
+		line := scanner.Text()
+		if len(line) == 0 || line[0] == '#' {
+			continue
+		}
+		m := partRe.FindStringSubmatch(line)
+		if m != nil {
+			if len(m) < 3 {
+				logger.Fatal("Failed to parse Part: ", line)
+			}
+			i, err := strconv.Atoi(m[1])
+			if err != nil {
+				logger.Fatal(err)
+			}
+			name := m[2]
+			part = append(part, Part{name: name[:len(name)-1], number: i})
+			continue
+		}
+		m = testRe.FindStringSubmatch(line)
+		if m == nil || len(m) < 7 {
+			logger.Fatalf(`Failed to parse: "%s" result: %#v`, line, m)
+		}
+		test := Test{name: m[6], partnr: len(part) - 1, number: counter}
+		counter++
+		for j := 1; j < len(m)-1; j++ {
+			for _, split := range strings.Split(m[j], " ") {
+				r, err := strconv.ParseUint(split, 16, 64)
+				if err != nil {
+					logger.Fatal(err)
+				}
+				if test.r == 0 {
+					// save for CharacterByCharacterTests
+					test.r = rune(r)
+				}
+				var buf [utf8.UTFMax]byte
+				sz := utf8.EncodeRune(buf[:], rune(r))
+				test.cols[j-1] += string(buf[:sz])
+			}
+		}
+		part := &part[len(part)-1]
+		part.tests = append(part.tests, test)
+	}
+	if scanner.Err() != nil {
+		logger.Fatal(scanner.Err())
+	}
+}
+
+var fstr = []string{"NFC", "NFD", "NFKC", "NFKD"}
+
+var errorCount int
+
+func cmpResult(t *Test, name string, f norm.Form, gold, test, result string) {
+	if gold != result {
+		errorCount++
+		if errorCount > 20 {
+			return
+		}
+		st, sr, sg := []rune(test), []rune(result), []rune(gold)
+		logger.Printf("%s:%s: %s(%X)=%X; want:%X: %s",
+			t.Name(), name, fstr[f], st, sr, sg, t.name)
+	}
+}
+
+func cmpIsNormal(t *Test, name string, f norm.Form, test string, result, want bool) {
+	if result != want {
+		errorCount++
+		if errorCount > 20 {
+			return
+		}
+		logger.Printf("%s:%s: %s(%X)=%v; want: %v", t.Name(), name, fstr[f], []rune(test), result, want)
+	}
+}
+
+func doTest(t *Test, f norm.Form, gold, test string) {
+	result := f.Bytes([]byte(test))
+	cmpResult(t, "Bytes", f, gold, test, string(result))
+	sresult := f.String(test)
+	cmpResult(t, "String", f, gold, test, sresult)
+	acc := []byte{}
+	i := norm.Iter{}
+	i.InitString(f, test)
+	for !i.Done() {
+		acc = append(acc, i.Next()...)
+	}
+	cmpResult(t, "Iter.Next", f, gold, test, string(acc))
+	for i := range test {
+		out := f.Append(f.Bytes([]byte(test[:i])), []byte(test[i:])...)
+		cmpResult(t, fmt.Sprintf(":Append:%d", i), f, gold, test, string(out))
+	}
+	cmpIsNormal(t, "IsNormal", f, test, f.IsNormal([]byte(test)), test == gold)
+}
+
+func doConformanceTests(t *Test, partn int) {
+	for i := 0; i <= 2; i++ {
+		doTest(t, norm.NFC, t.cols[1], t.cols[i])
+		doTest(t, norm.NFD, t.cols[2], t.cols[i])
+		doTest(t, norm.NFKC, t.cols[3], t.cols[i])
+		doTest(t, norm.NFKD, t.cols[4], t.cols[i])
+	}
+	for i := 3; i <= 4; i++ {
+		doTest(t, norm.NFC, t.cols[3], t.cols[i])
+		doTest(t, norm.NFD, t.cols[4], t.cols[i])
+		doTest(t, norm.NFKC, t.cols[3], t.cols[i])
+		doTest(t, norm.NFKD, t.cols[4], t.cols[i])
+	}
+}
+
+func CharacterByCharacterTests() {
+	tests := part[1].tests
+	var last rune = 0
+	for i := 0; i <= len(tests); i++ { // last one is special case
+		var r rune
+		if i == len(tests) {
+			r = 0x2FA1E // Don't have to go to 0x10FFFF
+		} else {
+			r = tests[i].r
+		}
+		for last++; last < r; last++ {
+			// Check all characters that were not explicitly listed in the test.
+			t := &Test{partnr: 1, number: -1}
+			char := string(last)
+			doTest(t, norm.NFC, char, char)
+			doTest(t, norm.NFD, char, char)
+			doTest(t, norm.NFKC, char, char)
+			doTest(t, norm.NFKD, char, char)
+		}
+		if i < len(tests) {
+			doConformanceTests(&tests[i], 1)
+		}
+	}
+}
+
+func StandardTests() {
+	for _, j := range []int{0, 2, 3} {
+		for _, test := range part[j].tests {
+			doConformanceTests(&test, j)
+		}
+	}
+}
+
+// PerformanceTest verifies that normalization is O(n). If any of the
+// code does not properly check for maxCombiningChars, normalization
+// may exhibit O(n**2) behavior.
+func PerformanceTest() {
+	runtime.GOMAXPROCS(2)
+	success := make(chan bool, 1)
+	go func() {
+		buf := bytes.Repeat([]byte("\u035D"), 1024*1024)
+		buf = append(buf, "\u035B"...)
+		norm.NFC.Append(nil, buf...)
+		success <- true
+	}()
+	timeout := time.After(1 * time.Second)
+	select {
+	case <-success:
+		// test completed before the timeout
+	case <-timeout:
+		errorCount++
+		logger.Printf(`unexpectedly long time to complete PerformanceTest`)
+	}
+}
diff --git a/src/pkg/exp/norm/readwriter.go b/src/pkg/exp/norm/readwriter.go
new file mode 100644
index 0000000..2682894
--- /dev/null
+++ b/src/pkg/exp/norm/readwriter.go
@@ -0,0 +1,126 @@
+// 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 norm
+
+import "io"
+
+type normWriter struct {
+	rb  reorderBuffer
+	w   io.Writer
+	buf []byte
+}
+
+// Write implements the standard write interface.  If the last characters are
+// not at a normalization boundary, the bytes will be buffered for the next
+// write. The remaining bytes will be written on close.
+func (w *normWriter) Write(data []byte) (n int, err error) {
+	// Process data in pieces to keep w.buf size bounded.
+	const chunk = 4000
+
+	for len(data) > 0 {
+		// Normalize into w.buf.
+		m := len(data)
+		if m > chunk {
+			m = chunk
+		}
+		w.rb.src = inputBytes(data[:m])
+		w.rb.nsrc = m
+		w.buf = doAppend(&w.rb, w.buf, 0)
+		data = data[m:]
+		n += m
+
+		// Write out complete prefix, save remainder.
+		// Note that lastBoundary looks back at most 30 runes.
+		i := lastBoundary(&w.rb.f, w.buf)
+		if i == -1 {
+			i = 0
+		}
+		if i > 0 {
+			if _, err = w.w.Write(w.buf[:i]); err != nil {
+				break
+			}
+			bn := copy(w.buf, w.buf[i:])
+			w.buf = w.buf[:bn]
+		}
+	}
+	return n, err
+}
+
+// Close forces data that remains in the buffer to be written.
+func (w *normWriter) Close() error {
+	if len(w.buf) > 0 {
+		_, err := w.w.Write(w.buf)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// Writer returns a new writer that implements Write(b)
+// by writing f(b) to w.  The returned writer may use an
+// an internal buffer to maintain state across Write calls.
+// Calling its Close method writes any buffered data to w.
+func (f Form) Writer(w io.Writer) io.WriteCloser {
+	wr := &normWriter{rb: reorderBuffer{}, w: w}
+	wr.rb.init(f, nil)
+	return wr
+}
+
+type normReader struct {
+	rb           reorderBuffer
+	r            io.Reader
+	inbuf        []byte
+	outbuf       []byte
+	bufStart     int
+	lastBoundary int
+	err          error
+}
+
+// Read implements the standard read interface.
+func (r *normReader) Read(p []byte) (int, error) {
+	for {
+		if r.lastBoundary-r.bufStart > 0 {
+			n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
+			r.bufStart += n
+			if r.lastBoundary-r.bufStart > 0 {
+				return n, nil
+			}
+			return n, r.err
+		}
+		if r.err != nil {
+			return 0, r.err
+		}
+		outn := copy(r.outbuf, r.outbuf[r.lastBoundary:])
+		r.outbuf = r.outbuf[0:outn]
+		r.bufStart = 0
+
+		n, err := r.r.Read(r.inbuf)
+		r.rb.src = inputBytes(r.inbuf[0:n])
+		r.rb.nsrc, r.err = n, err
+		if n > 0 {
+			r.outbuf = doAppend(&r.rb, r.outbuf, 0)
+		}
+		if err == io.EOF {
+			r.lastBoundary = len(r.outbuf)
+		} else {
+			r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
+			if r.lastBoundary == -1 {
+				r.lastBoundary = 0
+			}
+		}
+	}
+	panic("should not reach here")
+}
+
+// Reader returns a new reader that implements Read
+// by reading data from r and returning f(data).
+func (f Form) Reader(r io.Reader) io.Reader {
+	const chunk = 4000
+	buf := make([]byte, chunk)
+	rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
+	rr.rb.init(f, buf)
+	return rr
+}
diff --git a/src/pkg/exp/norm/readwriter_test.go b/src/pkg/exp/norm/readwriter_test.go
new file mode 100644
index 0000000..3b49eb0
--- /dev/null
+++ b/src/pkg/exp/norm/readwriter_test.go
@@ -0,0 +1,68 @@
+// 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 norm
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+var ioTests = []AppendTest{
+	{"", strings.Repeat("a\u0316\u0300", 6), strings.Repeat("\u00E0\u0316", 6)},
+	{"", strings.Repeat("a\u0300\u0316", 4000), strings.Repeat("\u00E0\u0316", 4000)},
+	{"", strings.Repeat("\x80\x80", 4000), strings.Repeat("\x80\x80", 4000)},
+	{"", "\u0041\u0307\u0304", "\u01E0"},
+}
+
+var bufSizes = []int{1, 2, 3, 4, 5, 6, 7, 8, 100, 101, 102, 103, 4000, 4001, 4002, 4003}
+
+func readFunc(size int) appendFunc {
+	return func(f Form, out []byte, s string) []byte {
+		out = append(out, s...)
+		r := f.Reader(bytes.NewBuffer(out))
+		buf := make([]byte, size)
+		result := []byte{}
+		for n, err := 0, error(nil); err == nil; {
+			n, err = r.Read(buf)
+			result = append(result, buf[:n]...)
+		}
+		return result
+	}
+}
+
+func TestReader(t *testing.T) {
+	for _, s := range bufSizes {
+		name := fmt.Sprintf("TestReader%da", s)
+		runAppendTests(t, name, NFKC, readFunc(s), appendTests)
+		name = fmt.Sprintf("TestReader%db", s)
+		runAppendTests(t, name, NFKC, readFunc(s), ioTests)
+	}
+}
+
+func writeFunc(size int) appendFunc {
+	return func(f Form, out []byte, s string) []byte {
+		in := append(out, s...)
+		result := new(bytes.Buffer)
+		w := f.Writer(result)
+		buf := make([]byte, size)
+		for n := 0; len(in) > 0; in = in[n:] {
+			n = copy(buf, in)
+			_, _ = w.Write(buf[:n])
+		}
+		w.Close()
+		return result.Bytes()
+	}
+}
+
+func TestWriter(t *testing.T) {
+	for _, s := range bufSizes {
+		name := fmt.Sprintf("TestWriter%da", s)
+		runAppendTests(t, name, NFKC, writeFunc(s), appendTests)
+		name = fmt.Sprintf("TestWriter%db", s)
+		runAppendTests(t, name, NFKC, writeFunc(s), ioTests)
+	}
+}
diff --git a/src/pkg/exp/norm/tables.go b/src/pkg/exp/norm/tables.go
new file mode 100644
index 0000000..fa33a34
--- /dev/null
+++ b/src/pkg/exp/norm/tables.go
@@ -0,0 +1,6779 @@
+// Generated by running
+//	maketables --tables=all --url=http://www.unicode.org/Public/6.2.0/ucd/
+// DO NOT EDIT
+
+package norm
+
+// Version is the Unicode edition from which the tables are derived.
+const Version = "6.2.0"
+
+const (
+	firstMulti         = 0x18CF
+	firstCCC           = 0x2E74
+	endMulti           = 0x2F4A
+	firstLeadingCCC    = 0x4994
+	firstCCCZeroExcept = 0x49AA
+	lastDecomp         = 0x49D1
+	maxDecomp          = 0x8000
+)
+
+// decomps: 18897 bytes
+var decomps = [...]byte{
+	// Bytes 0 - 3f
+	0x00, 0x41, 0x20, 0x41, 0x21, 0x41, 0x22, 0x41,
+	0x23, 0x41, 0x24, 0x41, 0x25, 0x41, 0x26, 0x41,
+	0x27, 0x41, 0x28, 0x41, 0x29, 0x41, 0x2A, 0x41,
+	0x2B, 0x41, 0x2C, 0x41, 0x2D, 0x41, 0x2E, 0x41,
+	0x2F, 0x41, 0x30, 0x41, 0x31, 0x41, 0x32, 0x41,
+	0x33, 0x41, 0x34, 0x41, 0x35, 0x41, 0x36, 0x41,
+	0x37, 0x41, 0x38, 0x41, 0x39, 0x41, 0x3A, 0x41,
+	0x3B, 0x41, 0x3C, 0x41, 0x3D, 0x41, 0x3E, 0x41,
+	// Bytes 40 - 7f
+	0x3F, 0x41, 0x40, 0x41, 0x41, 0x41, 0x42, 0x41,
+	0x43, 0x41, 0x44, 0x41, 0x45, 0x41, 0x46, 0x41,
+	0x47, 0x41, 0x48, 0x41, 0x49, 0x41, 0x4A, 0x41,
+	0x4B, 0x41, 0x4C, 0x41, 0x4D, 0x41, 0x4E, 0x41,
+	0x4F, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41,
+	0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41,
+	0x57, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5A, 0x41,
+	0x5B, 0x41, 0x5C, 0x41, 0x5D, 0x41, 0x5E, 0x41,
+	// Bytes 80 - bf
+	0x5F, 0x41, 0x60, 0x41, 0x61, 0x41, 0x62, 0x41,
+	0x63, 0x41, 0x64, 0x41, 0x65, 0x41, 0x66, 0x41,
+	0x67, 0x41, 0x68, 0x41, 0x69, 0x41, 0x6A, 0x41,
+	0x6B, 0x41, 0x6C, 0x41, 0x6D, 0x41, 0x6E, 0x41,
+	0x6F, 0x41, 0x70, 0x41, 0x71, 0x41, 0x72, 0x41,
+	0x73, 0x41, 0x74, 0x41, 0x75, 0x41, 0x76, 0x41,
+	0x77, 0x41, 0x78, 0x41, 0x79, 0x41, 0x7A, 0x41,
+	0x7B, 0x41, 0x7C, 0x41, 0x7D, 0x41, 0x7E, 0x42,
+	// Bytes c0 - ff
+	0xC2, 0xA2, 0x42, 0xC2, 0xA3, 0x42, 0xC2, 0xA5,
+	0x42, 0xC2, 0xA6, 0x42, 0xC2, 0xAC, 0x42, 0xC2,
+	0xB4, 0x42, 0xC2, 0xB7, 0x42, 0xC3, 0x86, 0x42,
+	0xC3, 0xB0, 0x42, 0xC4, 0xA6, 0x42, 0xC4, 0xA7,
+	0x42, 0xC4, 0xB1, 0x42, 0xC5, 0x8B, 0x42, 0xC5,
+	0x93, 0x42, 0xC6, 0x8E, 0x42, 0xC6, 0x90, 0x42,
+	0xC6, 0xAB, 0x42, 0xC8, 0xA2, 0x42, 0xC8, 0xB7,
+	0x42, 0xC9, 0x90, 0x42, 0xC9, 0x91, 0x42, 0xC9,
+	// Bytes 100 - 13f
+	0x92, 0x42, 0xC9, 0x94, 0x42, 0xC9, 0x95, 0x42,
+	0xC9, 0x99, 0x42, 0xC9, 0x9B, 0x42, 0xC9, 0x9C,
+	0x42, 0xC9, 0x9F, 0x42, 0xC9, 0xA1, 0x42, 0xC9,
+	0xA3, 0x42, 0xC9, 0xA5, 0x42, 0xC9, 0xA6, 0x42,
+	0xC9, 0xA8, 0x42, 0xC9, 0xA9, 0x42, 0xC9, 0xAA,
+	0x42, 0xC9, 0xAD, 0x42, 0xC9, 0xAF, 0x42, 0xC9,
+	0xB0, 0x42, 0xC9, 0xB1, 0x42, 0xC9, 0xB2, 0x42,
+	0xC9, 0xB3, 0x42, 0xC9, 0xB4, 0x42, 0xC9, 0xB5,
+	// Bytes 140 - 17f
+	0x42, 0xC9, 0xB8, 0x42, 0xC9, 0xB9, 0x42, 0xC9,
+	0xBB, 0x42, 0xCA, 0x81, 0x42, 0xCA, 0x82, 0x42,
+	0xCA, 0x83, 0x42, 0xCA, 0x89, 0x42, 0xCA, 0x8A,
+	0x42, 0xCA, 0x8B, 0x42, 0xCA, 0x8C, 0x42, 0xCA,
+	0x90, 0x42, 0xCA, 0x91, 0x42, 0xCA, 0x92, 0x42,
+	0xCA, 0x95, 0x42, 0xCA, 0x9D, 0x42, 0xCA, 0x9F,
+	0x42, 0xCA, 0xB9, 0x42, 0xCE, 0x91, 0x42, 0xCE,
+	0x92, 0x42, 0xCE, 0x93, 0x42, 0xCE, 0x94, 0x42,
+	// Bytes 180 - 1bf
+	0xCE, 0x95, 0x42, 0xCE, 0x96, 0x42, 0xCE, 0x97,
+	0x42, 0xCE, 0x98, 0x42, 0xCE, 0x99, 0x42, 0xCE,
+	0x9A, 0x42, 0xCE, 0x9B, 0x42, 0xCE, 0x9C, 0x42,
+	0xCE, 0x9D, 0x42, 0xCE, 0x9E, 0x42, 0xCE, 0x9F,
+	0x42, 0xCE, 0xA0, 0x42, 0xCE, 0xA1, 0x42, 0xCE,
+	0xA3, 0x42, 0xCE, 0xA4, 0x42, 0xCE, 0xA5, 0x42,
+	0xCE, 0xA6, 0x42, 0xCE, 0xA7, 0x42, 0xCE, 0xA8,
+	0x42, 0xCE, 0xA9, 0x42, 0xCE, 0xB1, 0x42, 0xCE,
+	// Bytes 1c0 - 1ff
+	0xB2, 0x42, 0xCE, 0xB3, 0x42, 0xCE, 0xB4, 0x42,
+	0xCE, 0xB5, 0x42, 0xCE, 0xB6, 0x42, 0xCE, 0xB7,
+	0x42, 0xCE, 0xB8, 0x42, 0xCE, 0xB9, 0x42, 0xCE,
+	0xBA, 0x42, 0xCE, 0xBB, 0x42, 0xCE, 0xBC, 0x42,
+	0xCE, 0xBD, 0x42, 0xCE, 0xBE, 0x42, 0xCE, 0xBF,
+	0x42, 0xCF, 0x80, 0x42, 0xCF, 0x81, 0x42, 0xCF,
+	0x82, 0x42, 0xCF, 0x83, 0x42, 0xCF, 0x84, 0x42,
+	0xCF, 0x85, 0x42, 0xCF, 0x86, 0x42, 0xCF, 0x87,
+	// Bytes 200 - 23f
+	0x42, 0xCF, 0x88, 0x42, 0xCF, 0x89, 0x42, 0xCF,
+	0x9C, 0x42, 0xCF, 0x9D, 0x42, 0xD0, 0xBD, 0x42,
+	0xD7, 0x90, 0x42, 0xD7, 0x91, 0x42, 0xD7, 0x92,
+	0x42, 0xD7, 0x93, 0x42, 0xD7, 0x94, 0x42, 0xD7,
+	0x9B, 0x42, 0xD7, 0x9C, 0x42, 0xD7, 0x9D, 0x42,
+	0xD7, 0xA2, 0x42, 0xD7, 0xA8, 0x42, 0xD7, 0xAA,
+	0x42, 0xD8, 0xA1, 0x42, 0xD8, 0xA7, 0x42, 0xD8,
+	0xA8, 0x42, 0xD8, 0xA9, 0x42, 0xD8, 0xAA, 0x42,
+	// Bytes 240 - 27f
+	0xD8, 0xAB, 0x42, 0xD8, 0xAC, 0x42, 0xD8, 0xAD,
+	0x42, 0xD8, 0xAE, 0x42, 0xD8, 0xAF, 0x42, 0xD8,
+	0xB0, 0x42, 0xD8, 0xB1, 0x42, 0xD8, 0xB2, 0x42,
+	0xD8, 0xB3, 0x42, 0xD8, 0xB4, 0x42, 0xD8, 0xB5,
+	0x42, 0xD8, 0xB6, 0x42, 0xD8, 0xB7, 0x42, 0xD8,
+	0xB8, 0x42, 0xD8, 0xB9, 0x42, 0xD8, 0xBA, 0x42,
+	0xD9, 0x81, 0x42, 0xD9, 0x82, 0x42, 0xD9, 0x83,
+	0x42, 0xD9, 0x84, 0x42, 0xD9, 0x85, 0x42, 0xD9,
+	// Bytes 280 - 2bf
+	0x86, 0x42, 0xD9, 0x87, 0x42, 0xD9, 0x88, 0x42,
+	0xD9, 0x89, 0x42, 0xD9, 0x8A, 0x42, 0xD9, 0xAE,
+	0x42, 0xD9, 0xAF, 0x42, 0xD9, 0xB1, 0x42, 0xD9,
+	0xB9, 0x42, 0xD9, 0xBA, 0x42, 0xD9, 0xBB, 0x42,
+	0xD9, 0xBE, 0x42, 0xD9, 0xBF, 0x42, 0xDA, 0x80,
+	0x42, 0xDA, 0x83, 0x42, 0xDA, 0x84, 0x42, 0xDA,
+	0x86, 0x42, 0xDA, 0x87, 0x42, 0xDA, 0x88, 0x42,
+	0xDA, 0x8C, 0x42, 0xDA, 0x8D, 0x42, 0xDA, 0x8E,
+	// Bytes 2c0 - 2ff
+	0x42, 0xDA, 0x91, 0x42, 0xDA, 0x98, 0x42, 0xDA,
+	0xA1, 0x42, 0xDA, 0xA4, 0x42, 0xDA, 0xA6, 0x42,
+	0xDA, 0xA9, 0x42, 0xDA, 0xAD, 0x42, 0xDA, 0xAF,
+	0x42, 0xDA, 0xB1, 0x42, 0xDA, 0xB3, 0x42, 0xDA,
+	0xBA, 0x42, 0xDA, 0xBB, 0x42, 0xDA, 0xBE, 0x42,
+	0xDB, 0x81, 0x42, 0xDB, 0x85, 0x42, 0xDB, 0x86,
+	0x42, 0xDB, 0x87, 0x42, 0xDB, 0x88, 0x42, 0xDB,
+	0x89, 0x42, 0xDB, 0x8B, 0x42, 0xDB, 0x8C, 0x42,
+	// Bytes 300 - 33f
+	0xDB, 0x90, 0x42, 0xDB, 0x92, 0x43, 0xE0, 0xBC,
+	0x8B, 0x43, 0xE1, 0x83, 0x9C, 0x43, 0xE1, 0x84,
+	0x80, 0x43, 0xE1, 0x84, 0x81, 0x43, 0xE1, 0x84,
+	0x82, 0x43, 0xE1, 0x84, 0x83, 0x43, 0xE1, 0x84,
+	0x84, 0x43, 0xE1, 0x84, 0x85, 0x43, 0xE1, 0x84,
+	0x86, 0x43, 0xE1, 0x84, 0x87, 0x43, 0xE1, 0x84,
+	0x88, 0x43, 0xE1, 0x84, 0x89, 0x43, 0xE1, 0x84,
+	0x8A, 0x43, 0xE1, 0x84, 0x8B, 0x43, 0xE1, 0x84,
+	// Bytes 340 - 37f
+	0x8C, 0x43, 0xE1, 0x84, 0x8D, 0x43, 0xE1, 0x84,
+	0x8E, 0x43, 0xE1, 0x84, 0x8F, 0x43, 0xE1, 0x84,
+	0x90, 0x43, 0xE1, 0x84, 0x91, 0x43, 0xE1, 0x84,
+	0x92, 0x43, 0xE1, 0x84, 0x94, 0x43, 0xE1, 0x84,
+	0x95, 0x43, 0xE1, 0x84, 0x9A, 0x43, 0xE1, 0x84,
+	0x9C, 0x43, 0xE1, 0x84, 0x9D, 0x43, 0xE1, 0x84,
+	0x9E, 0x43, 0xE1, 0x84, 0xA0, 0x43, 0xE1, 0x84,
+	0xA1, 0x43, 0xE1, 0x84, 0xA2, 0x43, 0xE1, 0x84,
+	// Bytes 380 - 3bf
+	0xA3, 0x43, 0xE1, 0x84, 0xA7, 0x43, 0xE1, 0x84,
+	0xA9, 0x43, 0xE1, 0x84, 0xAB, 0x43, 0xE1, 0x84,
+	0xAC, 0x43, 0xE1, 0x84, 0xAD, 0x43, 0xE1, 0x84,
+	0xAE, 0x43, 0xE1, 0x84, 0xAF, 0x43, 0xE1, 0x84,
+	0xB2, 0x43, 0xE1, 0x84, 0xB6, 0x43, 0xE1, 0x85,
+	0x80, 0x43, 0xE1, 0x85, 0x87, 0x43, 0xE1, 0x85,
+	0x8C, 0x43, 0xE1, 0x85, 0x97, 0x43, 0xE1, 0x85,
+	0x98, 0x43, 0xE1, 0x85, 0x99, 0x43, 0xE1, 0x85,
+	// Bytes 3c0 - 3ff
+	0xA0, 0x43, 0xE1, 0x85, 0xA1, 0x43, 0xE1, 0x85,
+	0xA2, 0x43, 0xE1, 0x85, 0xA3, 0x43, 0xE1, 0x85,
+	0xA4, 0x43, 0xE1, 0x85, 0xA5, 0x43, 0xE1, 0x85,
+	0xA6, 0x43, 0xE1, 0x85, 0xA7, 0x43, 0xE1, 0x85,
+	0xA8, 0x43, 0xE1, 0x85, 0xA9, 0x43, 0xE1, 0x85,
+	0xAA, 0x43, 0xE1, 0x85, 0xAB, 0x43, 0xE1, 0x85,
+	0xAC, 0x43, 0xE1, 0x85, 0xAD, 0x43, 0xE1, 0x85,
+	0xAE, 0x43, 0xE1, 0x85, 0xAF, 0x43, 0xE1, 0x85,
+	// Bytes 400 - 43f
+	0xB0, 0x43, 0xE1, 0x85, 0xB1, 0x43, 0xE1, 0x85,
+	0xB2, 0x43, 0xE1, 0x85, 0xB3, 0x43, 0xE1, 0x85,
+	0xB4, 0x43, 0xE1, 0x85, 0xB5, 0x43, 0xE1, 0x86,
+	0x84, 0x43, 0xE1, 0x86, 0x85, 0x43, 0xE1, 0x86,
+	0x88, 0x43, 0xE1, 0x86, 0x91, 0x43, 0xE1, 0x86,
+	0x92, 0x43, 0xE1, 0x86, 0x94, 0x43, 0xE1, 0x86,
+	0x9E, 0x43, 0xE1, 0x86, 0xA1, 0x43, 0xE1, 0x86,
+	0xAA, 0x43, 0xE1, 0x86, 0xAC, 0x43, 0xE1, 0x86,
+	// Bytes 440 - 47f
+	0xAD, 0x43, 0xE1, 0x86, 0xB0, 0x43, 0xE1, 0x86,
+	0xB1, 0x43, 0xE1, 0x86, 0xB2, 0x43, 0xE1, 0x86,
+	0xB3, 0x43, 0xE1, 0x86, 0xB4, 0x43, 0xE1, 0x86,
+	0xB5, 0x43, 0xE1, 0x87, 0x87, 0x43, 0xE1, 0x87,
+	0x88, 0x43, 0xE1, 0x87, 0x8C, 0x43, 0xE1, 0x87,
+	0x8E, 0x43, 0xE1, 0x87, 0x93, 0x43, 0xE1, 0x87,
+	0x97, 0x43, 0xE1, 0x87, 0x99, 0x43, 0xE1, 0x87,
+	0x9D, 0x43, 0xE1, 0x87, 0x9F, 0x43, 0xE1, 0x87,
+	// Bytes 480 - 4bf
+	0xB1, 0x43, 0xE1, 0x87, 0xB2, 0x43, 0xE1, 0xB4,
+	0x82, 0x43, 0xE1, 0xB4, 0x96, 0x43, 0xE1, 0xB4,
+	0x97, 0x43, 0xE1, 0xB4, 0x9C, 0x43, 0xE1, 0xB4,
+	0x9D, 0x43, 0xE1, 0xB4, 0xA5, 0x43, 0xE1, 0xB5,
+	0xBB, 0x43, 0xE1, 0xB6, 0x85, 0x43, 0xE2, 0x80,
+	0x82, 0x43, 0xE2, 0x80, 0x83, 0x43, 0xE2, 0x80,
+	0x90, 0x43, 0xE2, 0x80, 0x93, 0x43, 0xE2, 0x80,
+	0x94, 0x43, 0xE2, 0x82, 0xA9, 0x43, 0xE2, 0x86,
+	// Bytes 4c0 - 4ff
+	0x90, 0x43, 0xE2, 0x86, 0x91, 0x43, 0xE2, 0x86,
+	0x92, 0x43, 0xE2, 0x86, 0x93, 0x43, 0xE2, 0x88,
+	0x82, 0x43, 0xE2, 0x88, 0x87, 0x43, 0xE2, 0x88,
+	0x91, 0x43, 0xE2, 0x88, 0x92, 0x43, 0xE2, 0x94,
+	0x82, 0x43, 0xE2, 0x96, 0xA0, 0x43, 0xE2, 0x97,
+	0x8B, 0x43, 0xE2, 0xA6, 0x85, 0x43, 0xE2, 0xA6,
+	0x86, 0x43, 0xE2, 0xB5, 0xA1, 0x43, 0xE3, 0x80,
+	0x81, 0x43, 0xE3, 0x80, 0x82, 0x43, 0xE3, 0x80,
+	// Bytes 500 - 53f
+	0x88, 0x43, 0xE3, 0x80, 0x89, 0x43, 0xE3, 0x80,
+	0x8A, 0x43, 0xE3, 0x80, 0x8B, 0x43, 0xE3, 0x80,
+	0x8C, 0x43, 0xE3, 0x80, 0x8D, 0x43, 0xE3, 0x80,
+	0x8E, 0x43, 0xE3, 0x80, 0x8F, 0x43, 0xE3, 0x80,
+	0x90, 0x43, 0xE3, 0x80, 0x91, 0x43, 0xE3, 0x80,
+	0x92, 0x43, 0xE3, 0x80, 0x94, 0x43, 0xE3, 0x80,
+	0x95, 0x43, 0xE3, 0x80, 0x96, 0x43, 0xE3, 0x80,
+	0x97, 0x43, 0xE3, 0x82, 0xA1, 0x43, 0xE3, 0x82,
+	// Bytes 540 - 57f
+	0xA2, 0x43, 0xE3, 0x82, 0xA3, 0x43, 0xE3, 0x82,
+	0xA4, 0x43, 0xE3, 0x82, 0xA5, 0x43, 0xE3, 0x82,
+	0xA6, 0x43, 0xE3, 0x82, 0xA7, 0x43, 0xE3, 0x82,
+	0xA8, 0x43, 0xE3, 0x82, 0xA9, 0x43, 0xE3, 0x82,
+	0xAA, 0x43, 0xE3, 0x82, 0xAB, 0x43, 0xE3, 0x82,
+	0xAD, 0x43, 0xE3, 0x82, 0xAF, 0x43, 0xE3, 0x82,
+	0xB1, 0x43, 0xE3, 0x82, 0xB3, 0x43, 0xE3, 0x82,
+	0xB5, 0x43, 0xE3, 0x82, 0xB7, 0x43, 0xE3, 0x82,
+	// Bytes 580 - 5bf
+	0xB9, 0x43, 0xE3, 0x82, 0xBB, 0x43, 0xE3, 0x82,
+	0xBD, 0x43, 0xE3, 0x82, 0xBF, 0x43, 0xE3, 0x83,
+	0x81, 0x43, 0xE3, 0x83, 0x83, 0x43, 0xE3, 0x83,
+	0x84, 0x43, 0xE3, 0x83, 0x86, 0x43, 0xE3, 0x83,
+	0x88, 0x43, 0xE3, 0x83, 0x8A, 0x43, 0xE3, 0x83,
+	0x8B, 0x43, 0xE3, 0x83, 0x8C, 0x43, 0xE3, 0x83,
+	0x8D, 0x43, 0xE3, 0x83, 0x8E, 0x43, 0xE3, 0x83,
+	0x8F, 0x43, 0xE3, 0x83, 0x92, 0x43, 0xE3, 0x83,
+	// Bytes 5c0 - 5ff
+	0x95, 0x43, 0xE3, 0x83, 0x98, 0x43, 0xE3, 0x83,
+	0x9B, 0x43, 0xE3, 0x83, 0x9E, 0x43, 0xE3, 0x83,
+	0x9F, 0x43, 0xE3, 0x83, 0xA0, 0x43, 0xE3, 0x83,
+	0xA1, 0x43, 0xE3, 0x83, 0xA2, 0x43, 0xE3, 0x83,
+	0xA3, 0x43, 0xE3, 0x83, 0xA4, 0x43, 0xE3, 0x83,
+	0xA5, 0x43, 0xE3, 0x83, 0xA6, 0x43, 0xE3, 0x83,
+	0xA7, 0x43, 0xE3, 0x83, 0xA8, 0x43, 0xE3, 0x83,
+	0xA9, 0x43, 0xE3, 0x83, 0xAA, 0x43, 0xE3, 0x83,
+	// Bytes 600 - 63f
+	0xAB, 0x43, 0xE3, 0x83, 0xAC, 0x43, 0xE3, 0x83,
+	0xAD, 0x43, 0xE3, 0x83, 0xAF, 0x43, 0xE3, 0x83,
+	0xB0, 0x43, 0xE3, 0x83, 0xB1, 0x43, 0xE3, 0x83,
+	0xB2, 0x43, 0xE3, 0x83, 0xB3, 0x43, 0xE3, 0x83,
+	0xBB, 0x43, 0xE3, 0x83, 0xBC, 0x43, 0xE3, 0x92,
+	0x9E, 0x43, 0xE3, 0x92, 0xB9, 0x43, 0xE3, 0x92,
+	0xBB, 0x43, 0xE3, 0x93, 0x9F, 0x43, 0xE3, 0x94,
+	0x95, 0x43, 0xE3, 0x9B, 0xAE, 0x43, 0xE3, 0x9B,
+	// Bytes 640 - 67f
+	0xBC, 0x43, 0xE3, 0x9E, 0x81, 0x43, 0xE3, 0xA0,
+	0xAF, 0x43, 0xE3, 0xA1, 0xA2, 0x43, 0xE3, 0xA1,
+	0xBC, 0x43, 0xE3, 0xA3, 0x87, 0x43, 0xE3, 0xA3,
+	0xA3, 0x43, 0xE3, 0xA4, 0x9C, 0x43, 0xE3, 0xA4,
+	0xBA, 0x43, 0xE3, 0xA8, 0xAE, 0x43, 0xE3, 0xA9,
+	0xAC, 0x43, 0xE3, 0xAB, 0xA4, 0x43, 0xE3, 0xAC,
+	0x88, 0x43, 0xE3, 0xAC, 0x99, 0x43, 0xE3, 0xAD,
+	0x89, 0x43, 0xE3, 0xAE, 0x9D, 0x43, 0xE3, 0xB0,
+	// Bytes 680 - 6bf
+	0x98, 0x43, 0xE3, 0xB1, 0x8E, 0x43, 0xE3, 0xB4,
+	0xB3, 0x43, 0xE3, 0xB6, 0x96, 0x43, 0xE3, 0xBA,
+	0xAC, 0x43, 0xE3, 0xBA, 0xB8, 0x43, 0xE3, 0xBC,
+	0x9B, 0x43, 0xE3, 0xBF, 0xBC, 0x43, 0xE4, 0x80,
+	0x88, 0x43, 0xE4, 0x80, 0x98, 0x43, 0xE4, 0x80,
+	0xB9, 0x43, 0xE4, 0x81, 0x86, 0x43, 0xE4, 0x82,
+	0x96, 0x43, 0xE4, 0x83, 0xA3, 0x43, 0xE4, 0x84,
+	0xAF, 0x43, 0xE4, 0x88, 0x82, 0x43, 0xE4, 0x88,
+	// Bytes 6c0 - 6ff
+	0xA7, 0x43, 0xE4, 0x8A, 0xA0, 0x43, 0xE4, 0x8C,
+	0x81, 0x43, 0xE4, 0x8C, 0xB4, 0x43, 0xE4, 0x8D,
+	0x99, 0x43, 0xE4, 0x8F, 0x95, 0x43, 0xE4, 0x8F,
+	0x99, 0x43, 0xE4, 0x90, 0x8B, 0x43, 0xE4, 0x91,
+	0xAB, 0x43, 0xE4, 0x94, 0xAB, 0x43, 0xE4, 0x95,
+	0x9D, 0x43, 0xE4, 0x95, 0xA1, 0x43, 0xE4, 0x95,
+	0xAB, 0x43, 0xE4, 0x97, 0x97, 0x43, 0xE4, 0x97,
+	0xB9, 0x43, 0xE4, 0x98, 0xB5, 0x43, 0xE4, 0x9A,
+	// Bytes 700 - 73f
+	0xBE, 0x43, 0xE4, 0x9B, 0x87, 0x43, 0xE4, 0xA6,
+	0x95, 0x43, 0xE4, 0xA7, 0xA6, 0x43, 0xE4, 0xA9,
+	0xAE, 0x43, 0xE4, 0xA9, 0xB6, 0x43, 0xE4, 0xAA,
+	0xB2, 0x43, 0xE4, 0xAC, 0xB3, 0x43, 0xE4, 0xAF,
+	0x8E, 0x43, 0xE4, 0xB3, 0x8E, 0x43, 0xE4, 0xB3,
+	0xAD, 0x43, 0xE4, 0xB3, 0xB8, 0x43, 0xE4, 0xB5,
+	0x96, 0x43, 0xE4, 0xB8, 0x80, 0x43, 0xE4, 0xB8,
+	0x81, 0x43, 0xE4, 0xB8, 0x83, 0x43, 0xE4, 0xB8,
+	// Bytes 740 - 77f
+	0x89, 0x43, 0xE4, 0xB8, 0x8A, 0x43, 0xE4, 0xB8,
+	0x8B, 0x43, 0xE4, 0xB8, 0x8D, 0x43, 0xE4, 0xB8,
+	0x99, 0x43, 0xE4, 0xB8, 0xA6, 0x43, 0xE4, 0xB8,
+	0xA8, 0x43, 0xE4, 0xB8, 0xAD, 0x43, 0xE4, 0xB8,
+	0xB2, 0x43, 0xE4, 0xB8, 0xB6, 0x43, 0xE4, 0xB8,
+	0xB8, 0x43, 0xE4, 0xB8, 0xB9, 0x43, 0xE4, 0xB8,
+	0xBD, 0x43, 0xE4, 0xB8, 0xBF, 0x43, 0xE4, 0xB9,
+	0x81, 0x43, 0xE4, 0xB9, 0x99, 0x43, 0xE4, 0xB9,
+	// Bytes 780 - 7bf
+	0x9D, 0x43, 0xE4, 0xBA, 0x82, 0x43, 0xE4, 0xBA,
+	0x85, 0x43, 0xE4, 0xBA, 0x86, 0x43, 0xE4, 0xBA,
+	0x8C, 0x43, 0xE4, 0xBA, 0x94, 0x43, 0xE4, 0xBA,
+	0xA0, 0x43, 0xE4, 0xBA, 0xA4, 0x43, 0xE4, 0xBA,
+	0xAE, 0x43, 0xE4, 0xBA, 0xBA, 0x43, 0xE4, 0xBB,
+	0x80, 0x43, 0xE4, 0xBB, 0x8C, 0x43, 0xE4, 0xBB,
+	0xA4, 0x43, 0xE4, 0xBC, 0x81, 0x43, 0xE4, 0xBC,
+	0x91, 0x43, 0xE4, 0xBD, 0xA0, 0x43, 0xE4, 0xBE,
+	// Bytes 7c0 - 7ff
+	0x80, 0x43, 0xE4, 0xBE, 0x86, 0x43, 0xE4, 0xBE,
+	0x8B, 0x43, 0xE4, 0xBE, 0xAE, 0x43, 0xE4, 0xBE,
+	0xBB, 0x43, 0xE4, 0xBE, 0xBF, 0x43, 0xE5, 0x80,
+	0x82, 0x43, 0xE5, 0x80, 0xAB, 0x43, 0xE5, 0x81,
+	0xBA, 0x43, 0xE5, 0x82, 0x99, 0x43, 0xE5, 0x83,
+	0x8F, 0x43, 0xE5, 0x83, 0x9A, 0x43, 0xE5, 0x83,
+	0xA7, 0x43, 0xE5, 0x84, 0xAA, 0x43, 0xE5, 0x84,
+	0xBF, 0x43, 0xE5, 0x85, 0x80, 0x43, 0xE5, 0x85,
+	// Bytes 800 - 83f
+	0x85, 0x43, 0xE5, 0x85, 0x8D, 0x43, 0xE5, 0x85,
+	0x94, 0x43, 0xE5, 0x85, 0xA4, 0x43, 0xE5, 0x85,
+	0xA5, 0x43, 0xE5, 0x85, 0xA7, 0x43, 0xE5, 0x85,
+	0xA8, 0x43, 0xE5, 0x85, 0xA9, 0x43, 0xE5, 0x85,
+	0xAB, 0x43, 0xE5, 0x85, 0xAD, 0x43, 0xE5, 0x85,
+	0xB7, 0x43, 0xE5, 0x86, 0x80, 0x43, 0xE5, 0x86,
+	0x82, 0x43, 0xE5, 0x86, 0x8D, 0x43, 0xE5, 0x86,
+	0x92, 0x43, 0xE5, 0x86, 0x95, 0x43, 0xE5, 0x86,
+	// Bytes 840 - 87f
+	0x96, 0x43, 0xE5, 0x86, 0x97, 0x43, 0xE5, 0x86,
+	0x99, 0x43, 0xE5, 0x86, 0xA4, 0x43, 0xE5, 0x86,
+	0xAB, 0x43, 0xE5, 0x86, 0xAC, 0x43, 0xE5, 0x86,
+	0xB5, 0x43, 0xE5, 0x86, 0xB7, 0x43, 0xE5, 0x87,
+	0x89, 0x43, 0xE5, 0x87, 0x8C, 0x43, 0xE5, 0x87,
+	0x9C, 0x43, 0xE5, 0x87, 0x9E, 0x43, 0xE5, 0x87,
+	0xA0, 0x43, 0xE5, 0x87, 0xB5, 0x43, 0xE5, 0x88,
+	0x80, 0x43, 0xE5, 0x88, 0x83, 0x43, 0xE5, 0x88,
+	// Bytes 880 - 8bf
+	0x87, 0x43, 0xE5, 0x88, 0x97, 0x43, 0xE5, 0x88,
+	0x9D, 0x43, 0xE5, 0x88, 0xA9, 0x43, 0xE5, 0x88,
+	0xBA, 0x43, 0xE5, 0x88, 0xBB, 0x43, 0xE5, 0x89,
+	0x86, 0x43, 0xE5, 0x89, 0x8D, 0x43, 0xE5, 0x89,
+	0xB2, 0x43, 0xE5, 0x89, 0xB7, 0x43, 0xE5, 0x8A,
+	0x89, 0x43, 0xE5, 0x8A, 0x9B, 0x43, 0xE5, 0x8A,
+	0xA3, 0x43, 0xE5, 0x8A, 0xB3, 0x43, 0xE5, 0x8A,
+	0xB4, 0x43, 0xE5, 0x8B, 0x87, 0x43, 0xE5, 0x8B,
+	// Bytes 8c0 - 8ff
+	0x89, 0x43, 0xE5, 0x8B, 0x92, 0x43, 0xE5, 0x8B,
+	0x9E, 0x43, 0xE5, 0x8B, 0xA4, 0x43, 0xE5, 0x8B,
+	0xB5, 0x43, 0xE5, 0x8B, 0xB9, 0x43, 0xE5, 0x8B,
+	0xBA, 0x43, 0xE5, 0x8C, 0x85, 0x43, 0xE5, 0x8C,
+	0x86, 0x43, 0xE5, 0x8C, 0x95, 0x43, 0xE5, 0x8C,
+	0x97, 0x43, 0xE5, 0x8C, 0x9A, 0x43, 0xE5, 0x8C,
+	0xB8, 0x43, 0xE5, 0x8C, 0xBB, 0x43, 0xE5, 0x8C,
+	0xBF, 0x43, 0xE5, 0x8D, 0x81, 0x43, 0xE5, 0x8D,
+	// Bytes 900 - 93f
+	0x84, 0x43, 0xE5, 0x8D, 0x85, 0x43, 0xE5, 0x8D,
+	0x89, 0x43, 0xE5, 0x8D, 0x91, 0x43, 0xE5, 0x8D,
+	0x94, 0x43, 0xE5, 0x8D, 0x9A, 0x43, 0xE5, 0x8D,
+	0x9C, 0x43, 0xE5, 0x8D, 0xA9, 0x43, 0xE5, 0x8D,
+	0xB0, 0x43, 0xE5, 0x8D, 0xB3, 0x43, 0xE5, 0x8D,
+	0xB5, 0x43, 0xE5, 0x8D, 0xBD, 0x43, 0xE5, 0x8D,
+	0xBF, 0x43, 0xE5, 0x8E, 0x82, 0x43, 0xE5, 0x8E,
+	0xB6, 0x43, 0xE5, 0x8F, 0x83, 0x43, 0xE5, 0x8F,
+	// Bytes 940 - 97f
+	0x88, 0x43, 0xE5, 0x8F, 0x8A, 0x43, 0xE5, 0x8F,
+	0x8C, 0x43, 0xE5, 0x8F, 0x9F, 0x43, 0xE5, 0x8F,
+	0xA3, 0x43, 0xE5, 0x8F, 0xA5, 0x43, 0xE5, 0x8F,
+	0xAB, 0x43, 0xE5, 0x8F, 0xAF, 0x43, 0xE5, 0x8F,
+	0xB1, 0x43, 0xE5, 0x8F, 0xB3, 0x43, 0xE5, 0x90,
+	0x86, 0x43, 0xE5, 0x90, 0x88, 0x43, 0xE5, 0x90,
+	0x8D, 0x43, 0xE5, 0x90, 0x8F, 0x43, 0xE5, 0x90,
+	0x9D, 0x43, 0xE5, 0x90, 0xB8, 0x43, 0xE5, 0x90,
+	// Bytes 980 - 9bf
+	0xB9, 0x43, 0xE5, 0x91, 0x82, 0x43, 0xE5, 0x91,
+	0x88, 0x43, 0xE5, 0x91, 0xA8, 0x43, 0xE5, 0x92,
+	0x9E, 0x43, 0xE5, 0x92, 0xA2, 0x43, 0xE5, 0x92,
+	0xBD, 0x43, 0xE5, 0x93, 0xB6, 0x43, 0xE5, 0x94,
+	0x90, 0x43, 0xE5, 0x95, 0x8F, 0x43, 0xE5, 0x95,
+	0x93, 0x43, 0xE5, 0x95, 0x95, 0x43, 0xE5, 0x95,
+	0xA3, 0x43, 0xE5, 0x96, 0x84, 0x43, 0xE5, 0x96,
+	0x87, 0x43, 0xE5, 0x96, 0x99, 0x43, 0xE5, 0x96,
+	// Bytes 9c0 - 9ff
+	0x9D, 0x43, 0xE5, 0x96, 0xAB, 0x43, 0xE5, 0x96,
+	0xB3, 0x43, 0xE5, 0x96, 0xB6, 0x43, 0xE5, 0x97,
+	0x80, 0x43, 0xE5, 0x97, 0x82, 0x43, 0xE5, 0x97,
+	0xA2, 0x43, 0xE5, 0x98, 0x86, 0x43, 0xE5, 0x99,
+	0x91, 0x43, 0xE5, 0x99, 0xA8, 0x43, 0xE5, 0x99,
+	0xB4, 0x43, 0xE5, 0x9B, 0x97, 0x43, 0xE5, 0x9B,
+	0x9B, 0x43, 0xE5, 0x9B, 0xB9, 0x43, 0xE5, 0x9C,
+	0x96, 0x43, 0xE5, 0x9C, 0x97, 0x43, 0xE5, 0x9C,
+	// Bytes a00 - a3f
+	0x9F, 0x43, 0xE5, 0x9C, 0xB0, 0x43, 0xE5, 0x9E,
+	0x8B, 0x43, 0xE5, 0x9F, 0x8E, 0x43, 0xE5, 0x9F,
+	0xB4, 0x43, 0xE5, 0xA0, 0x8D, 0x43, 0xE5, 0xA0,
+	0xB1, 0x43, 0xE5, 0xA0, 0xB2, 0x43, 0xE5, 0xA1,
+	0x80, 0x43, 0xE5, 0xA1, 0x9A, 0x43, 0xE5, 0xA1,
+	0x9E, 0x43, 0xE5, 0xA2, 0xA8, 0x43, 0xE5, 0xA2,
+	0xAC, 0x43, 0xE5, 0xA2, 0xB3, 0x43, 0xE5, 0xA3,
+	0x98, 0x43, 0xE5, 0xA3, 0x9F, 0x43, 0xE5, 0xA3,
+	// Bytes a40 - a7f
+	0xAB, 0x43, 0xE5, 0xA3, 0xAE, 0x43, 0xE5, 0xA3,
+	0xB0, 0x43, 0xE5, 0xA3, 0xB2, 0x43, 0xE5, 0xA3,
+	0xB7, 0x43, 0xE5, 0xA4, 0x82, 0x43, 0xE5, 0xA4,
+	0x86, 0x43, 0xE5, 0xA4, 0x8A, 0x43, 0xE5, 0xA4,
+	0x95, 0x43, 0xE5, 0xA4, 0x9A, 0x43, 0xE5, 0xA4,
+	0x9C, 0x43, 0xE5, 0xA4, 0xA2, 0x43, 0xE5, 0xA4,
+	0xA7, 0x43, 0xE5, 0xA4, 0xA9, 0x43, 0xE5, 0xA5,
+	0x84, 0x43, 0xE5, 0xA5, 0x88, 0x43, 0xE5, 0xA5,
+	// Bytes a80 - abf
+	0x91, 0x43, 0xE5, 0xA5, 0x94, 0x43, 0xE5, 0xA5,
+	0xA2, 0x43, 0xE5, 0xA5, 0xB3, 0x43, 0xE5, 0xA7,
+	0x98, 0x43, 0xE5, 0xA7, 0xAC, 0x43, 0xE5, 0xA8,
+	0x9B, 0x43, 0xE5, 0xA8, 0xA7, 0x43, 0xE5, 0xA9,
+	0xA2, 0x43, 0xE5, 0xA9, 0xA6, 0x43, 0xE5, 0xAA,
+	0xB5, 0x43, 0xE5, 0xAC, 0x88, 0x43, 0xE5, 0xAC,
+	0xA8, 0x43, 0xE5, 0xAC, 0xBE, 0x43, 0xE5, 0xAD,
+	0x90, 0x43, 0xE5, 0xAD, 0x97, 0x43, 0xE5, 0xAD,
+	// Bytes ac0 - aff
+	0xA6, 0x43, 0xE5, 0xAE, 0x80, 0x43, 0xE5, 0xAE,
+	0x85, 0x43, 0xE5, 0xAE, 0x97, 0x43, 0xE5, 0xAF,
+	0x83, 0x43, 0xE5, 0xAF, 0x98, 0x43, 0xE5, 0xAF,
+	0xA7, 0x43, 0xE5, 0xAF, 0xAE, 0x43, 0xE5, 0xAF,
+	0xB3, 0x43, 0xE5, 0xAF, 0xB8, 0x43, 0xE5, 0xAF,
+	0xBF, 0x43, 0xE5, 0xB0, 0x86, 0x43, 0xE5, 0xB0,
+	0x8F, 0x43, 0xE5, 0xB0, 0xA2, 0x43, 0xE5, 0xB0,
+	0xB8, 0x43, 0xE5, 0xB0, 0xBF, 0x43, 0xE5, 0xB1,
+	// Bytes b00 - b3f
+	0xA0, 0x43, 0xE5, 0xB1, 0xA2, 0x43, 0xE5, 0xB1,
+	0xA4, 0x43, 0xE5, 0xB1, 0xA5, 0x43, 0xE5, 0xB1,
+	0xAE, 0x43, 0xE5, 0xB1, 0xB1, 0x43, 0xE5, 0xB2,
+	0x8D, 0x43, 0xE5, 0xB3, 0x80, 0x43, 0xE5, 0xB4,
+	0x99, 0x43, 0xE5, 0xB5, 0x83, 0x43, 0xE5, 0xB5,
+	0x90, 0x43, 0xE5, 0xB5, 0xAB, 0x43, 0xE5, 0xB5,
+	0xAE, 0x43, 0xE5, 0xB5, 0xBC, 0x43, 0xE5, 0xB6,
+	0xB2, 0x43, 0xE5, 0xB6, 0xBA, 0x43, 0xE5, 0xB7,
+	// Bytes b40 - b7f
+	0x9B, 0x43, 0xE5, 0xB7, 0xA1, 0x43, 0xE5, 0xB7,
+	0xA2, 0x43, 0xE5, 0xB7, 0xA5, 0x43, 0xE5, 0xB7,
+	0xA6, 0x43, 0xE5, 0xB7, 0xB1, 0x43, 0xE5, 0xB7,
+	0xBD, 0x43, 0xE5, 0xB7, 0xBE, 0x43, 0xE5, 0xB8,
+	0xA8, 0x43, 0xE5, 0xB8, 0xBD, 0x43, 0xE5, 0xB9,
+	0xA9, 0x43, 0xE5, 0xB9, 0xB2, 0x43, 0xE5, 0xB9,
+	0xB4, 0x43, 0xE5, 0xB9, 0xBA, 0x43, 0xE5, 0xB9,
+	0xBC, 0x43, 0xE5, 0xB9, 0xBF, 0x43, 0xE5, 0xBA,
+	// Bytes b80 - bbf
+	0xA6, 0x43, 0xE5, 0xBA, 0xB0, 0x43, 0xE5, 0xBA,
+	0xB3, 0x43, 0xE5, 0xBA, 0xB6, 0x43, 0xE5, 0xBB,
+	0x89, 0x43, 0xE5, 0xBB, 0x8A, 0x43, 0xE5, 0xBB,
+	0x92, 0x43, 0xE5, 0xBB, 0x93, 0x43, 0xE5, 0xBB,
+	0x99, 0x43, 0xE5, 0xBB, 0xAC, 0x43, 0xE5, 0xBB,
+	0xB4, 0x43, 0xE5, 0xBB, 0xBE, 0x43, 0xE5, 0xBC,
+	0x84, 0x43, 0xE5, 0xBC, 0x8B, 0x43, 0xE5, 0xBC,
+	0x93, 0x43, 0xE5, 0xBC, 0xA2, 0x43, 0xE5, 0xBD,
+	// Bytes bc0 - bff
+	0x90, 0x43, 0xE5, 0xBD, 0x93, 0x43, 0xE5, 0xBD,
+	0xA1, 0x43, 0xE5, 0xBD, 0xA2, 0x43, 0xE5, 0xBD,
+	0xA9, 0x43, 0xE5, 0xBD, 0xAB, 0x43, 0xE5, 0xBD,
+	0xB3, 0x43, 0xE5, 0xBE, 0x8B, 0x43, 0xE5, 0xBE,
+	0x8C, 0x43, 0xE5, 0xBE, 0x97, 0x43, 0xE5, 0xBE,
+	0x9A, 0x43, 0xE5, 0xBE, 0xA9, 0x43, 0xE5, 0xBE,
+	0xAD, 0x43, 0xE5, 0xBF, 0x83, 0x43, 0xE5, 0xBF,
+	0x8D, 0x43, 0xE5, 0xBF, 0x97, 0x43, 0xE5, 0xBF,
+	// Bytes c00 - c3f
+	0xB5, 0x43, 0xE5, 0xBF, 0xB9, 0x43, 0xE6, 0x80,
+	0x92, 0x43, 0xE6, 0x80, 0x9C, 0x43, 0xE6, 0x81,
+	0xB5, 0x43, 0xE6, 0x82, 0x81, 0x43, 0xE6, 0x82,
+	0x94, 0x43, 0xE6, 0x83, 0x87, 0x43, 0xE6, 0x83,
+	0x98, 0x43, 0xE6, 0x83, 0xA1, 0x43, 0xE6, 0x84,
+	0x88, 0x43, 0xE6, 0x85, 0x84, 0x43, 0xE6, 0x85,
+	0x88, 0x43, 0xE6, 0x85, 0x8C, 0x43, 0xE6, 0x85,
+	0x8E, 0x43, 0xE6, 0x85, 0xA0, 0x43, 0xE6, 0x85,
+	// Bytes c40 - c7f
+	0xA8, 0x43, 0xE6, 0x85, 0xBA, 0x43, 0xE6, 0x86,
+	0x8E, 0x43, 0xE6, 0x86, 0x90, 0x43, 0xE6, 0x86,
+	0xA4, 0x43, 0xE6, 0x86, 0xAF, 0x43, 0xE6, 0x86,
+	0xB2, 0x43, 0xE6, 0x87, 0x9E, 0x43, 0xE6, 0x87,
+	0xB2, 0x43, 0xE6, 0x87, 0xB6, 0x43, 0xE6, 0x88,
+	0x80, 0x43, 0xE6, 0x88, 0x88, 0x43, 0xE6, 0x88,
+	0x90, 0x43, 0xE6, 0x88, 0x9B, 0x43, 0xE6, 0x88,
+	0xAE, 0x43, 0xE6, 0x88, 0xB4, 0x43, 0xE6, 0x88,
+	// Bytes c80 - cbf
+	0xB6, 0x43, 0xE6, 0x89, 0x8B, 0x43, 0xE6, 0x89,
+	0x93, 0x43, 0xE6, 0x89, 0x9D, 0x43, 0xE6, 0x8A,
+	0x95, 0x43, 0xE6, 0x8A, 0xB1, 0x43, 0xE6, 0x8B,
+	0x89, 0x43, 0xE6, 0x8B, 0x8F, 0x43, 0xE6, 0x8B,
+	0x93, 0x43, 0xE6, 0x8B, 0x94, 0x43, 0xE6, 0x8B,
+	0xBC, 0x43, 0xE6, 0x8B, 0xBE, 0x43, 0xE6, 0x8C,
+	0x87, 0x43, 0xE6, 0x8C, 0xBD, 0x43, 0xE6, 0x8D,
+	0x90, 0x43, 0xE6, 0x8D, 0x95, 0x43, 0xE6, 0x8D,
+	// Bytes cc0 - cff
+	0xA8, 0x43, 0xE6, 0x8D, 0xBB, 0x43, 0xE6, 0x8E,
+	0x83, 0x43, 0xE6, 0x8E, 0xA0, 0x43, 0xE6, 0x8E,
+	0xA9, 0x43, 0xE6, 0x8F, 0x84, 0x43, 0xE6, 0x8F,
+	0x85, 0x43, 0xE6, 0x8F, 0xA4, 0x43, 0xE6, 0x90,
+	0x9C, 0x43, 0xE6, 0x90, 0xA2, 0x43, 0xE6, 0x91,
+	0x92, 0x43, 0xE6, 0x91, 0xA9, 0x43, 0xE6, 0x91,
+	0xB7, 0x43, 0xE6, 0x91, 0xBE, 0x43, 0xE6, 0x92,
+	0x9A, 0x43, 0xE6, 0x92, 0x9D, 0x43, 0xE6, 0x93,
+	// Bytes d00 - d3f
+	0x84, 0x43, 0xE6, 0x94, 0xAF, 0x43, 0xE6, 0x94,
+	0xB4, 0x43, 0xE6, 0x95, 0x8F, 0x43, 0xE6, 0x95,
+	0x96, 0x43, 0xE6, 0x95, 0xAC, 0x43, 0xE6, 0x95,
+	0xB8, 0x43, 0xE6, 0x96, 0x87, 0x43, 0xE6, 0x96,
+	0x97, 0x43, 0xE6, 0x96, 0x99, 0x43, 0xE6, 0x96,
+	0xA4, 0x43, 0xE6, 0x96, 0xB0, 0x43, 0xE6, 0x96,
+	0xB9, 0x43, 0xE6, 0x97, 0x85, 0x43, 0xE6, 0x97,
+	0xA0, 0x43, 0xE6, 0x97, 0xA2, 0x43, 0xE6, 0x97,
+	// Bytes d40 - d7f
+	0xA3, 0x43, 0xE6, 0x97, 0xA5, 0x43, 0xE6, 0x98,
+	0x93, 0x43, 0xE6, 0x98, 0xA0, 0x43, 0xE6, 0x99,
+	0x89, 0x43, 0xE6, 0x99, 0xB4, 0x43, 0xE6, 0x9A,
+	0x88, 0x43, 0xE6, 0x9A, 0x91, 0x43, 0xE6, 0x9A,
+	0x9C, 0x43, 0xE6, 0x9A, 0xB4, 0x43, 0xE6, 0x9B,
+	0x86, 0x43, 0xE6, 0x9B, 0xB0, 0x43, 0xE6, 0x9B,
+	0xB4, 0x43, 0xE6, 0x9B, 0xB8, 0x43, 0xE6, 0x9C,
+	0x80, 0x43, 0xE6, 0x9C, 0x88, 0x43, 0xE6, 0x9C,
+	// Bytes d80 - dbf
+	0x89, 0x43, 0xE6, 0x9C, 0x97, 0x43, 0xE6, 0x9C,
+	0x9B, 0x43, 0xE6, 0x9C, 0xA1, 0x43, 0xE6, 0x9C,
+	0xA8, 0x43, 0xE6, 0x9D, 0x8E, 0x43, 0xE6, 0x9D,
+	0x93, 0x43, 0xE6, 0x9D, 0x96, 0x43, 0xE6, 0x9D,
+	0x9E, 0x43, 0xE6, 0x9D, 0xBB, 0x43, 0xE6, 0x9E,
+	0x85, 0x43, 0xE6, 0x9E, 0x97, 0x43, 0xE6, 0x9F,
+	0xB3, 0x43, 0xE6, 0x9F, 0xBA, 0x43, 0xE6, 0xA0,
+	0x97, 0x43, 0xE6, 0xA0, 0x9F, 0x43, 0xE6, 0xA0,
+	// Bytes dc0 - dff
+	0xAA, 0x43, 0xE6, 0xA1, 0x92, 0x43, 0xE6, 0xA2,
+	0x81, 0x43, 0xE6, 0xA2, 0x85, 0x43, 0xE6, 0xA2,
+	0x8E, 0x43, 0xE6, 0xA2, 0xA8, 0x43, 0xE6, 0xA4,
+	0x94, 0x43, 0xE6, 0xA5, 0x82, 0x43, 0xE6, 0xA6,
+	0xA3, 0x43, 0xE6, 0xA7, 0xAA, 0x43, 0xE6, 0xA8,
+	0x82, 0x43, 0xE6, 0xA8, 0x93, 0x43, 0xE6, 0xAA,
+	0xA8, 0x43, 0xE6, 0xAB, 0x93, 0x43, 0xE6, 0xAB,
+	0x9B, 0x43, 0xE6, 0xAC, 0x84, 0x43, 0xE6, 0xAC,
+	// Bytes e00 - e3f
+	0xA0, 0x43, 0xE6, 0xAC, 0xA1, 0x43, 0xE6, 0xAD,
+	0x94, 0x43, 0xE6, 0xAD, 0xA2, 0x43, 0xE6, 0xAD,
+	0xA3, 0x43, 0xE6, 0xAD, 0xB2, 0x43, 0xE6, 0xAD,
+	0xB7, 0x43, 0xE6, 0xAD, 0xB9, 0x43, 0xE6, 0xAE,
+	0x9F, 0x43, 0xE6, 0xAE, 0xAE, 0x43, 0xE6, 0xAE,
+	0xB3, 0x43, 0xE6, 0xAE, 0xBA, 0x43, 0xE6, 0xAE,
+	0xBB, 0x43, 0xE6, 0xAF, 0x8B, 0x43, 0xE6, 0xAF,
+	0x8D, 0x43, 0xE6, 0xAF, 0x94, 0x43, 0xE6, 0xAF,
+	// Bytes e40 - e7f
+	0x9B, 0x43, 0xE6, 0xB0, 0x8F, 0x43, 0xE6, 0xB0,
+	0x94, 0x43, 0xE6, 0xB0, 0xB4, 0x43, 0xE6, 0xB1,
+	0x8E, 0x43, 0xE6, 0xB1, 0xA7, 0x43, 0xE6, 0xB2,
+	0x88, 0x43, 0xE6, 0xB2, 0xBF, 0x43, 0xE6, 0xB3,
+	0x8C, 0x43, 0xE6, 0xB3, 0x8D, 0x43, 0xE6, 0xB3,
+	0xA5, 0x43, 0xE6, 0xB3, 0xA8, 0x43, 0xE6, 0xB4,
+	0x96, 0x43, 0xE6, 0xB4, 0x9B, 0x43, 0xE6, 0xB4,
+	0x9E, 0x43, 0xE6, 0xB4, 0xB4, 0x43, 0xE6, 0xB4,
+	// Bytes e80 - ebf
+	0xBE, 0x43, 0xE6, 0xB5, 0x81, 0x43, 0xE6, 0xB5,
+	0xA9, 0x43, 0xE6, 0xB5, 0xAA, 0x43, 0xE6, 0xB5,
+	0xB7, 0x43, 0xE6, 0xB5, 0xB8, 0x43, 0xE6, 0xB6,
+	0x85, 0x43, 0xE6, 0xB7, 0x8B, 0x43, 0xE6, 0xB7,
+	0x9A, 0x43, 0xE6, 0xB7, 0xAA, 0x43, 0xE6, 0xB7,
+	0xB9, 0x43, 0xE6, 0xB8, 0x9A, 0x43, 0xE6, 0xB8,
+	0xAF, 0x43, 0xE6, 0xB9, 0xAE, 0x43, 0xE6, 0xBA,
+	0x80, 0x43, 0xE6, 0xBA, 0x9C, 0x43, 0xE6, 0xBA,
+	// Bytes ec0 - eff
+	0xBA, 0x43, 0xE6, 0xBB, 0x87, 0x43, 0xE6, 0xBB,
+	0x8B, 0x43, 0xE6, 0xBB, 0x91, 0x43, 0xE6, 0xBB,
+	0x9B, 0x43, 0xE6, 0xBC, 0x8F, 0x43, 0xE6, 0xBC,
+	0x94, 0x43, 0xE6, 0xBC, 0xA2, 0x43, 0xE6, 0xBC,
+	0xA3, 0x43, 0xE6, 0xBD, 0xAE, 0x43, 0xE6, 0xBF,
+	0x86, 0x43, 0xE6, 0xBF, 0xAB, 0x43, 0xE6, 0xBF,
+	0xBE, 0x43, 0xE7, 0x80, 0x9B, 0x43, 0xE7, 0x80,
+	0x9E, 0x43, 0xE7, 0x80, 0xB9, 0x43, 0xE7, 0x81,
+	// Bytes f00 - f3f
+	0x8A, 0x43, 0xE7, 0x81, 0xAB, 0x43, 0xE7, 0x81,
+	0xB0, 0x43, 0xE7, 0x81, 0xB7, 0x43, 0xE7, 0x81,
+	0xBD, 0x43, 0xE7, 0x82, 0x99, 0x43, 0xE7, 0x82,
+	0xAD, 0x43, 0xE7, 0x83, 0x88, 0x43, 0xE7, 0x83,
+	0x99, 0x43, 0xE7, 0x84, 0xA1, 0x43, 0xE7, 0x85,
+	0x85, 0x43, 0xE7, 0x85, 0x89, 0x43, 0xE7, 0x85,
+	0xAE, 0x43, 0xE7, 0x86, 0x9C, 0x43, 0xE7, 0x87,
+	0x8E, 0x43, 0xE7, 0x87, 0x90, 0x43, 0xE7, 0x88,
+	// Bytes f40 - f7f
+	0x90, 0x43, 0xE7, 0x88, 0x9B, 0x43, 0xE7, 0x88,
+	0xA8, 0x43, 0xE7, 0x88, 0xAA, 0x43, 0xE7, 0x88,
+	0xAB, 0x43, 0xE7, 0x88, 0xB5, 0x43, 0xE7, 0x88,
+	0xB6, 0x43, 0xE7, 0x88, 0xBB, 0x43, 0xE7, 0x88,
+	0xBF, 0x43, 0xE7, 0x89, 0x87, 0x43, 0xE7, 0x89,
+	0x90, 0x43, 0xE7, 0x89, 0x99, 0x43, 0xE7, 0x89,
+	0x9B, 0x43, 0xE7, 0x89, 0xA2, 0x43, 0xE7, 0x89,
+	0xB9, 0x43, 0xE7, 0x8A, 0x80, 0x43, 0xE7, 0x8A,
+	// Bytes f80 - fbf
+	0x95, 0x43, 0xE7, 0x8A, 0xAC, 0x43, 0xE7, 0x8A,
+	0xAF, 0x43, 0xE7, 0x8B, 0x80, 0x43, 0xE7, 0x8B,
+	0xBC, 0x43, 0xE7, 0x8C, 0xAA, 0x43, 0xE7, 0x8D,
+	0xB5, 0x43, 0xE7, 0x8D, 0xBA, 0x43, 0xE7, 0x8E,
+	0x84, 0x43, 0xE7, 0x8E, 0x87, 0x43, 0xE7, 0x8E,
+	0x89, 0x43, 0xE7, 0x8E, 0x8B, 0x43, 0xE7, 0x8E,
+	0xA5, 0x43, 0xE7, 0x8E, 0xB2, 0x43, 0xE7, 0x8F,
+	0x9E, 0x43, 0xE7, 0x90, 0x86, 0x43, 0xE7, 0x90,
+	// Bytes fc0 - fff
+	0x89, 0x43, 0xE7, 0x90, 0xA2, 0x43, 0xE7, 0x91,
+	0x87, 0x43, 0xE7, 0x91, 0x9C, 0x43, 0xE7, 0x91,
+	0xA9, 0x43, 0xE7, 0x91, 0xB1, 0x43, 0xE7, 0x92,
+	0x85, 0x43, 0xE7, 0x92, 0x89, 0x43, 0xE7, 0x92,
+	0x98, 0x43, 0xE7, 0x93, 0x8A, 0x43, 0xE7, 0x93,
+	0x9C, 0x43, 0xE7, 0x93, 0xA6, 0x43, 0xE7, 0x94,
+	0x86, 0x43, 0xE7, 0x94, 0x98, 0x43, 0xE7, 0x94,
+	0x9F, 0x43, 0xE7, 0x94, 0xA4, 0x43, 0xE7, 0x94,
+	// Bytes 1000 - 103f
+	0xA8, 0x43, 0xE7, 0x94, 0xB0, 0x43, 0xE7, 0x94,
+	0xB2, 0x43, 0xE7, 0x94, 0xB3, 0x43, 0xE7, 0x94,
+	0xB7, 0x43, 0xE7, 0x94, 0xBB, 0x43, 0xE7, 0x94,
+	0xBE, 0x43, 0xE7, 0x95, 0x99, 0x43, 0xE7, 0x95,
+	0xA5, 0x43, 0xE7, 0x95, 0xB0, 0x43, 0xE7, 0x96,
+	0x8B, 0x43, 0xE7, 0x96, 0x92, 0x43, 0xE7, 0x97,
+	0xA2, 0x43, 0xE7, 0x98, 0x90, 0x43, 0xE7, 0x98,
+	0x9D, 0x43, 0xE7, 0x98, 0x9F, 0x43, 0xE7, 0x99,
+	// Bytes 1040 - 107f
+	0x82, 0x43, 0xE7, 0x99, 0xA9, 0x43, 0xE7, 0x99,
+	0xB6, 0x43, 0xE7, 0x99, 0xBD, 0x43, 0xE7, 0x9A,
+	0xAE, 0x43, 0xE7, 0x9A, 0xBF, 0x43, 0xE7, 0x9B,
+	0x8A, 0x43, 0xE7, 0x9B, 0x9B, 0x43, 0xE7, 0x9B,
+	0xA3, 0x43, 0xE7, 0x9B, 0xA7, 0x43, 0xE7, 0x9B,
+	0xAE, 0x43, 0xE7, 0x9B, 0xB4, 0x43, 0xE7, 0x9C,
+	0x81, 0x43, 0xE7, 0x9C, 0x9E, 0x43, 0xE7, 0x9C,
+	0x9F, 0x43, 0xE7, 0x9D, 0x80, 0x43, 0xE7, 0x9D,
+	// Bytes 1080 - 10bf
+	0x8A, 0x43, 0xE7, 0x9E, 0x8B, 0x43, 0xE7, 0x9E,
+	0xA7, 0x43, 0xE7, 0x9F, 0x9B, 0x43, 0xE7, 0x9F,
+	0xA2, 0x43, 0xE7, 0x9F, 0xB3, 0x43, 0xE7, 0xA1,
+	0x8E, 0x43, 0xE7, 0xA1, 0xAB, 0x43, 0xE7, 0xA2,
+	0x8C, 0x43, 0xE7, 0xA2, 0x91, 0x43, 0xE7, 0xA3,
+	0x8A, 0x43, 0xE7, 0xA3, 0x8C, 0x43, 0xE7, 0xA3,
+	0xBB, 0x43, 0xE7, 0xA4, 0xAA, 0x43, 0xE7, 0xA4,
+	0xBA, 0x43, 0xE7, 0xA4, 0xBC, 0x43, 0xE7, 0xA4,
+	// Bytes 10c0 - 10ff
+	0xBE, 0x43, 0xE7, 0xA5, 0x88, 0x43, 0xE7, 0xA5,
+	0x89, 0x43, 0xE7, 0xA5, 0x90, 0x43, 0xE7, 0xA5,
+	0x96, 0x43, 0xE7, 0xA5, 0x9D, 0x43, 0xE7, 0xA5,
+	0x9E, 0x43, 0xE7, 0xA5, 0xA5, 0x43, 0xE7, 0xA5,
+	0xBF, 0x43, 0xE7, 0xA6, 0x81, 0x43, 0xE7, 0xA6,
+	0x8D, 0x43, 0xE7, 0xA6, 0x8E, 0x43, 0xE7, 0xA6,
+	0x8F, 0x43, 0xE7, 0xA6, 0xAE, 0x43, 0xE7, 0xA6,
+	0xB8, 0x43, 0xE7, 0xA6, 0xBE, 0x43, 0xE7, 0xA7,
+	// Bytes 1100 - 113f
+	0x8A, 0x43, 0xE7, 0xA7, 0x98, 0x43, 0xE7, 0xA7,
+	0xAB, 0x43, 0xE7, 0xA8, 0x9C, 0x43, 0xE7, 0xA9,
+	0x80, 0x43, 0xE7, 0xA9, 0x8A, 0x43, 0xE7, 0xA9,
+	0x8F, 0x43, 0xE7, 0xA9, 0xB4, 0x43, 0xE7, 0xA9,
+	0xBA, 0x43, 0xE7, 0xAA, 0x81, 0x43, 0xE7, 0xAA,
+	0xB1, 0x43, 0xE7, 0xAB, 0x8B, 0x43, 0xE7, 0xAB,
+	0xAE, 0x43, 0xE7, 0xAB, 0xB9, 0x43, 0xE7, 0xAC,
+	0xA0, 0x43, 0xE7, 0xAE, 0x8F, 0x43, 0xE7, 0xAF,
+	// Bytes 1140 - 117f
+	0x80, 0x43, 0xE7, 0xAF, 0x86, 0x43, 0xE7, 0xAF,
+	0x89, 0x43, 0xE7, 0xB0, 0xBE, 0x43, 0xE7, 0xB1,
+	0xA0, 0x43, 0xE7, 0xB1, 0xB3, 0x43, 0xE7, 0xB1,
+	0xBB, 0x43, 0xE7, 0xB2, 0x92, 0x43, 0xE7, 0xB2,
+	0xBE, 0x43, 0xE7, 0xB3, 0x92, 0x43, 0xE7, 0xB3,
+	0x96, 0x43, 0xE7, 0xB3, 0xA3, 0x43, 0xE7, 0xB3,
+	0xA7, 0x43, 0xE7, 0xB3, 0xA8, 0x43, 0xE7, 0xB3,
+	0xB8, 0x43, 0xE7, 0xB4, 0x80, 0x43, 0xE7, 0xB4,
+	// Bytes 1180 - 11bf
+	0x90, 0x43, 0xE7, 0xB4, 0xA2, 0x43, 0xE7, 0xB4,
+	0xAF, 0x43, 0xE7, 0xB5, 0x82, 0x43, 0xE7, 0xB5,
+	0x9B, 0x43, 0xE7, 0xB5, 0xA3, 0x43, 0xE7, 0xB6,
+	0xA0, 0x43, 0xE7, 0xB6, 0xBE, 0x43, 0xE7, 0xB7,
+	0x87, 0x43, 0xE7, 0xB7, 0xB4, 0x43, 0xE7, 0xB8,
+	0x82, 0x43, 0xE7, 0xB8, 0x89, 0x43, 0xE7, 0xB8,
+	0xB7, 0x43, 0xE7, 0xB9, 0x81, 0x43, 0xE7, 0xB9,
+	0x85, 0x43, 0xE7, 0xBC, 0xB6, 0x43, 0xE7, 0xBC,
+	// Bytes 11c0 - 11ff
+	0xBE, 0x43, 0xE7, 0xBD, 0x91, 0x43, 0xE7, 0xBD,
+	0xB2, 0x43, 0xE7, 0xBD, 0xB9, 0x43, 0xE7, 0xBD,
+	0xBA, 0x43, 0xE7, 0xBE, 0x85, 0x43, 0xE7, 0xBE,
+	0x8A, 0x43, 0xE7, 0xBE, 0x95, 0x43, 0xE7, 0xBE,
+	0x9A, 0x43, 0xE7, 0xBE, 0xBD, 0x43, 0xE7, 0xBF,
+	0xBA, 0x43, 0xE8, 0x80, 0x81, 0x43, 0xE8, 0x80,
+	0x85, 0x43, 0xE8, 0x80, 0x8C, 0x43, 0xE8, 0x80,
+	0x92, 0x43, 0xE8, 0x80, 0xB3, 0x43, 0xE8, 0x81,
+	// Bytes 1200 - 123f
+	0x86, 0x43, 0xE8, 0x81, 0xA0, 0x43, 0xE8, 0x81,
+	0xAF, 0x43, 0xE8, 0x81, 0xB0, 0x43, 0xE8, 0x81,
+	0xBE, 0x43, 0xE8, 0x81, 0xBF, 0x43, 0xE8, 0x82,
+	0x89, 0x43, 0xE8, 0x82, 0x8B, 0x43, 0xE8, 0x82,
+	0xAD, 0x43, 0xE8, 0x82, 0xB2, 0x43, 0xE8, 0x84,
+	0x83, 0x43, 0xE8, 0x84, 0xBE, 0x43, 0xE8, 0x87,
+	0x98, 0x43, 0xE8, 0x87, 0xA3, 0x43, 0xE8, 0x87,
+	0xA8, 0x43, 0xE8, 0x87, 0xAA, 0x43, 0xE8, 0x87,
+	// Bytes 1240 - 127f
+	0xAD, 0x43, 0xE8, 0x87, 0xB3, 0x43, 0xE8, 0x87,
+	0xBC, 0x43, 0xE8, 0x88, 0x81, 0x43, 0xE8, 0x88,
+	0x84, 0x43, 0xE8, 0x88, 0x8C, 0x43, 0xE8, 0x88,
+	0x98, 0x43, 0xE8, 0x88, 0x9B, 0x43, 0xE8, 0x88,
+	0x9F, 0x43, 0xE8, 0x89, 0xAE, 0x43, 0xE8, 0x89,
+	0xAF, 0x43, 0xE8, 0x89, 0xB2, 0x43, 0xE8, 0x89,
+	0xB8, 0x43, 0xE8, 0x89, 0xB9, 0x43, 0xE8, 0x8A,
+	0x8B, 0x43, 0xE8, 0x8A, 0x91, 0x43, 0xE8, 0x8A,
+	// Bytes 1280 - 12bf
+	0x9D, 0x43, 0xE8, 0x8A, 0xB1, 0x43, 0xE8, 0x8A,
+	0xB3, 0x43, 0xE8, 0x8A, 0xBD, 0x43, 0xE8, 0x8B,
+	0xA5, 0x43, 0xE8, 0x8B, 0xA6, 0x43, 0xE8, 0x8C,
+	0x9D, 0x43, 0xE8, 0x8C, 0xA3, 0x43, 0xE8, 0x8C,
+	0xB6, 0x43, 0xE8, 0x8D, 0x92, 0x43, 0xE8, 0x8D,
+	0x93, 0x43, 0xE8, 0x8D, 0xA3, 0x43, 0xE8, 0x8E,
+	0xAD, 0x43, 0xE8, 0x8E, 0xBD, 0x43, 0xE8, 0x8F,
+	0x89, 0x43, 0xE8, 0x8F, 0x8A, 0x43, 0xE8, 0x8F,
+	// Bytes 12c0 - 12ff
+	0x8C, 0x43, 0xE8, 0x8F, 0x9C, 0x43, 0xE8, 0x8F,
+	0xA7, 0x43, 0xE8, 0x8F, 0xAF, 0x43, 0xE8, 0x8F,
+	0xB1, 0x43, 0xE8, 0x90, 0xBD, 0x43, 0xE8, 0x91,
+	0x89, 0x43, 0xE8, 0x91, 0x97, 0x43, 0xE8, 0x93,
+	0xAE, 0x43, 0xE8, 0x93, 0xB1, 0x43, 0xE8, 0x93,
+	0xB3, 0x43, 0xE8, 0x93, 0xBC, 0x43, 0xE8, 0x94,
+	0x96, 0x43, 0xE8, 0x95, 0xA4, 0x43, 0xE8, 0x97,
+	0x8D, 0x43, 0xE8, 0x97, 0xBA, 0x43, 0xE8, 0x98,
+	// Bytes 1300 - 133f
+	0x86, 0x43, 0xE8, 0x98, 0x92, 0x43, 0xE8, 0x98,
+	0xAD, 0x43, 0xE8, 0x98, 0xBF, 0x43, 0xE8, 0x99,
+	0x8D, 0x43, 0xE8, 0x99, 0x90, 0x43, 0xE8, 0x99,
+	0x9C, 0x43, 0xE8, 0x99, 0xA7, 0x43, 0xE8, 0x99,
+	0xA9, 0x43, 0xE8, 0x99, 0xAB, 0x43, 0xE8, 0x9A,
+	0x88, 0x43, 0xE8, 0x9A, 0xA9, 0x43, 0xE8, 0x9B,
+	0xA2, 0x43, 0xE8, 0x9C, 0x8E, 0x43, 0xE8, 0x9C,
+	0xA8, 0x43, 0xE8, 0x9D, 0xAB, 0x43, 0xE8, 0x9D,
+	// Bytes 1340 - 137f
+	0xB9, 0x43, 0xE8, 0x9E, 0x86, 0x43, 0xE8, 0x9E,
+	0xBA, 0x43, 0xE8, 0x9F, 0xA1, 0x43, 0xE8, 0xA0,
+	0x81, 0x43, 0xE8, 0xA0, 0x9F, 0x43, 0xE8, 0xA1,
+	0x80, 0x43, 0xE8, 0xA1, 0x8C, 0x43, 0xE8, 0xA1,
+	0xA0, 0x43, 0xE8, 0xA1, 0xA3, 0x43, 0xE8, 0xA3,
+	0x82, 0x43, 0xE8, 0xA3, 0x8F, 0x43, 0xE8, 0xA3,
+	0x97, 0x43, 0xE8, 0xA3, 0x9E, 0x43, 0xE8, 0xA3,
+	0xA1, 0x43, 0xE8, 0xA3, 0xB8, 0x43, 0xE8, 0xA3,
+	// Bytes 1380 - 13bf
+	0xBA, 0x43, 0xE8, 0xA4, 0x90, 0x43, 0xE8, 0xA5,
+	0x81, 0x43, 0xE8, 0xA5, 0xA4, 0x43, 0xE8, 0xA5,
+	0xBE, 0x43, 0xE8, 0xA6, 0x86, 0x43, 0xE8, 0xA6,
+	0x8B, 0x43, 0xE8, 0xA6, 0x96, 0x43, 0xE8, 0xA7,
+	0x92, 0x43, 0xE8, 0xA7, 0xA3, 0x43, 0xE8, 0xA8,
+	0x80, 0x43, 0xE8, 0xAA, 0xA0, 0x43, 0xE8, 0xAA,
+	0xAA, 0x43, 0xE8, 0xAA, 0xBF, 0x43, 0xE8, 0xAB,
+	0x8B, 0x43, 0xE8, 0xAB, 0x92, 0x43, 0xE8, 0xAB,
+	// Bytes 13c0 - 13ff
+	0x96, 0x43, 0xE8, 0xAB, 0xAD, 0x43, 0xE8, 0xAB,
+	0xB8, 0x43, 0xE8, 0xAB, 0xBE, 0x43, 0xE8, 0xAC,
+	0x81, 0x43, 0xE8, 0xAC, 0xB9, 0x43, 0xE8, 0xAD,
+	0x98, 0x43, 0xE8, 0xAE, 0x80, 0x43, 0xE8, 0xAE,
+	0x8A, 0x43, 0xE8, 0xB0, 0xB7, 0x43, 0xE8, 0xB1,
+	0x86, 0x43, 0xE8, 0xB1, 0x88, 0x43, 0xE8, 0xB1,
+	0x95, 0x43, 0xE8, 0xB1, 0xB8, 0x43, 0xE8, 0xB2,
+	0x9D, 0x43, 0xE8, 0xB2, 0xA1, 0x43, 0xE8, 0xB2,
+	// Bytes 1400 - 143f
+	0xA9, 0x43, 0xE8, 0xB2, 0xAB, 0x43, 0xE8, 0xB3,
+	0x81, 0x43, 0xE8, 0xB3, 0x82, 0x43, 0xE8, 0xB3,
+	0x87, 0x43, 0xE8, 0xB3, 0x88, 0x43, 0xE8, 0xB3,
+	0x93, 0x43, 0xE8, 0xB4, 0x88, 0x43, 0xE8, 0xB4,
+	0x9B, 0x43, 0xE8, 0xB5, 0xA4, 0x43, 0xE8, 0xB5,
+	0xB0, 0x43, 0xE8, 0xB5, 0xB7, 0x43, 0xE8, 0xB6,
+	0xB3, 0x43, 0xE8, 0xB6, 0xBC, 0x43, 0xE8, 0xB7,
+	0x8B, 0x43, 0xE8, 0xB7, 0xAF, 0x43, 0xE8, 0xB7,
+	// Bytes 1440 - 147f
+	0xB0, 0x43, 0xE8, 0xBA, 0xAB, 0x43, 0xE8, 0xBB,
+	0x8A, 0x43, 0xE8, 0xBB, 0x94, 0x43, 0xE8, 0xBC,
+	0xA6, 0x43, 0xE8, 0xBC, 0xAA, 0x43, 0xE8, 0xBC,
+	0xB8, 0x43, 0xE8, 0xBC, 0xBB, 0x43, 0xE8, 0xBD,
+	0xA2, 0x43, 0xE8, 0xBE, 0x9B, 0x43, 0xE8, 0xBE,
+	0x9E, 0x43, 0xE8, 0xBE, 0xB0, 0x43, 0xE8, 0xBE,
+	0xB5, 0x43, 0xE8, 0xBE, 0xB6, 0x43, 0xE9, 0x80,
+	0xA3, 0x43, 0xE9, 0x80, 0xB8, 0x43, 0xE9, 0x81,
+	// Bytes 1480 - 14bf
+	0x8A, 0x43, 0xE9, 0x81, 0xA9, 0x43, 0xE9, 0x81,
+	0xB2, 0x43, 0xE9, 0x81, 0xBC, 0x43, 0xE9, 0x82,
+	0x8F, 0x43, 0xE9, 0x82, 0x91, 0x43, 0xE9, 0x82,
+	0x94, 0x43, 0xE9, 0x83, 0x8E, 0x43, 0xE9, 0x83,
+	0x9E, 0x43, 0xE9, 0x83, 0xB1, 0x43, 0xE9, 0x83,
+	0xBD, 0x43, 0xE9, 0x84, 0x91, 0x43, 0xE9, 0x84,
+	0x9B, 0x43, 0xE9, 0x85, 0x89, 0x43, 0xE9, 0x85,
+	0xAA, 0x43, 0xE9, 0x86, 0x99, 0x43, 0xE9, 0x86,
+	// Bytes 14c0 - 14ff
+	0xB4, 0x43, 0xE9, 0x87, 0x86, 0x43, 0xE9, 0x87,
+	0x8C, 0x43, 0xE9, 0x87, 0x8F, 0x43, 0xE9, 0x87,
+	0x91, 0x43, 0xE9, 0x88, 0xB4, 0x43, 0xE9, 0x88,
+	0xB8, 0x43, 0xE9, 0x89, 0xB6, 0x43, 0xE9, 0x89,
+	0xBC, 0x43, 0xE9, 0x8B, 0x97, 0x43, 0xE9, 0x8B,
+	0x98, 0x43, 0xE9, 0x8C, 0x84, 0x43, 0xE9, 0x8D,
+	0x8A, 0x43, 0xE9, 0x8F, 0xB9, 0x43, 0xE9, 0x90,
+	0x95, 0x43, 0xE9, 0x95, 0xB7, 0x43, 0xE9, 0x96,
+	// Bytes 1500 - 153f
+	0x80, 0x43, 0xE9, 0x96, 0x8B, 0x43, 0xE9, 0x96,
+	0xAD, 0x43, 0xE9, 0x96, 0xB7, 0x43, 0xE9, 0x98,
+	0x9C, 0x43, 0xE9, 0x98, 0xAE, 0x43, 0xE9, 0x99,
+	0x8B, 0x43, 0xE9, 0x99, 0x8D, 0x43, 0xE9, 0x99,
+	0xB5, 0x43, 0xE9, 0x99, 0xB8, 0x43, 0xE9, 0x99,
+	0xBC, 0x43, 0xE9, 0x9A, 0x86, 0x43, 0xE9, 0x9A,
+	0xA3, 0x43, 0xE9, 0x9A, 0xB6, 0x43, 0xE9, 0x9A,
+	0xB7, 0x43, 0xE9, 0x9A, 0xB8, 0x43, 0xE9, 0x9A,
+	// Bytes 1540 - 157f
+	0xB9, 0x43, 0xE9, 0x9B, 0x83, 0x43, 0xE9, 0x9B,
+	0xA2, 0x43, 0xE9, 0x9B, 0xA3, 0x43, 0xE9, 0x9B,
+	0xA8, 0x43, 0xE9, 0x9B, 0xB6, 0x43, 0xE9, 0x9B,
+	0xB7, 0x43, 0xE9, 0x9C, 0xA3, 0x43, 0xE9, 0x9C,
+	0xB2, 0x43, 0xE9, 0x9D, 0x88, 0x43, 0xE9, 0x9D,
+	0x91, 0x43, 0xE9, 0x9D, 0x96, 0x43, 0xE9, 0x9D,
+	0x9E, 0x43, 0xE9, 0x9D, 0xA2, 0x43, 0xE9, 0x9D,
+	0xA9, 0x43, 0xE9, 0x9F, 0x8B, 0x43, 0xE9, 0x9F,
+	// Bytes 1580 - 15bf
+	0x9B, 0x43, 0xE9, 0x9F, 0xA0, 0x43, 0xE9, 0x9F,
+	0xAD, 0x43, 0xE9, 0x9F, 0xB3, 0x43, 0xE9, 0x9F,
+	0xBF, 0x43, 0xE9, 0xA0, 0x81, 0x43, 0xE9, 0xA0,
+	0x85, 0x43, 0xE9, 0xA0, 0x8B, 0x43, 0xE9, 0xA0,
+	0x98, 0x43, 0xE9, 0xA0, 0xA9, 0x43, 0xE9, 0xA0,
+	0xBB, 0x43, 0xE9, 0xA1, 0x9E, 0x43, 0xE9, 0xA2,
+	0xA8, 0x43, 0xE9, 0xA3, 0x9B, 0x43, 0xE9, 0xA3,
+	0x9F, 0x43, 0xE9, 0xA3, 0xA2, 0x43, 0xE9, 0xA3,
+	// Bytes 15c0 - 15ff
+	0xAF, 0x43, 0xE9, 0xA3, 0xBC, 0x43, 0xE9, 0xA4,
+	0xA8, 0x43, 0xE9, 0xA4, 0xA9, 0x43, 0xE9, 0xA6,
+	0x96, 0x43, 0xE9, 0xA6, 0x99, 0x43, 0xE9, 0xA6,
+	0xA7, 0x43, 0xE9, 0xA6, 0xAC, 0x43, 0xE9, 0xA7,
+	0x82, 0x43, 0xE9, 0xA7, 0xB1, 0x43, 0xE9, 0xA7,
+	0xBE, 0x43, 0xE9, 0xA9, 0xAA, 0x43, 0xE9, 0xAA,
+	0xA8, 0x43, 0xE9, 0xAB, 0x98, 0x43, 0xE9, 0xAB,
+	0x9F, 0x43, 0xE9, 0xAC, 0x92, 0x43, 0xE9, 0xAC,
+	// Bytes 1600 - 163f
+	0xA5, 0x43, 0xE9, 0xAC, 0xAF, 0x43, 0xE9, 0xAC,
+	0xB2, 0x43, 0xE9, 0xAC, 0xBC, 0x43, 0xE9, 0xAD,
+	0x9A, 0x43, 0xE9, 0xAD, 0xAF, 0x43, 0xE9, 0xB1,
+	0x80, 0x43, 0xE9, 0xB1, 0x97, 0x43, 0xE9, 0xB3,
+	0xA5, 0x43, 0xE9, 0xB3, 0xBD, 0x43, 0xE9, 0xB5,
+	0xA7, 0x43, 0xE9, 0xB6, 0xB4, 0x43, 0xE9, 0xB7,
+	0xBA, 0x43, 0xE9, 0xB8, 0x9E, 0x43, 0xE9, 0xB9,
+	0xB5, 0x43, 0xE9, 0xB9, 0xBF, 0x43, 0xE9, 0xBA,
+	// Bytes 1640 - 167f
+	0x97, 0x43, 0xE9, 0xBA, 0x9F, 0x43, 0xE9, 0xBA,
+	0xA5, 0x43, 0xE9, 0xBA, 0xBB, 0x43, 0xE9, 0xBB,
+	0x83, 0x43, 0xE9, 0xBB, 0x8D, 0x43, 0xE9, 0xBB,
+	0x8E, 0x43, 0xE9, 0xBB, 0x91, 0x43, 0xE9, 0xBB,
+	0xB9, 0x43, 0xE9, 0xBB, 0xBD, 0x43, 0xE9, 0xBB,
+	0xBE, 0x43, 0xE9, 0xBC, 0x85, 0x43, 0xE9, 0xBC,
+	0x8E, 0x43, 0xE9, 0xBC, 0x8F, 0x43, 0xE9, 0xBC,
+	0x93, 0x43, 0xE9, 0xBC, 0x96, 0x43, 0xE9, 0xBC,
+	// Bytes 1680 - 16bf
+	0xA0, 0x43, 0xE9, 0xBC, 0xBB, 0x43, 0xE9, 0xBD,
+	0x83, 0x43, 0xE9, 0xBD, 0x8A, 0x43, 0xE9, 0xBD,
+	0x92, 0x43, 0xE9, 0xBE, 0x8D, 0x43, 0xE9, 0xBE,
+	0x8E, 0x43, 0xE9, 0xBE, 0x9C, 0x43, 0xE9, 0xBE,
+	0x9F, 0x43, 0xE9, 0xBE, 0xA0, 0x43, 0xEA, 0x9D,
+	0xAF, 0x44, 0xF0, 0xA0, 0x84, 0xA2, 0x44, 0xF0,
+	0xA0, 0x94, 0x9C, 0x44, 0xF0, 0xA0, 0x94, 0xA5,
+	0x44, 0xF0, 0xA0, 0x95, 0x8B, 0x44, 0xF0, 0xA0,
+	// Bytes 16c0 - 16ff
+	0x98, 0xBA, 0x44, 0xF0, 0xA0, 0xA0, 0x84, 0x44,
+	0xF0, 0xA0, 0xA3, 0x9E, 0x44, 0xF0, 0xA0, 0xA8,
+	0xAC, 0x44, 0xF0, 0xA0, 0xAD, 0xA3, 0x44, 0xF0,
+	0xA1, 0x93, 0xA4, 0x44, 0xF0, 0xA1, 0x9A, 0xA8,
+	0x44, 0xF0, 0xA1, 0x9B, 0xAA, 0x44, 0xF0, 0xA1,
+	0xA7, 0x88, 0x44, 0xF0, 0xA1, 0xAC, 0x98, 0x44,
+	0xF0, 0xA1, 0xB4, 0x8B, 0x44, 0xF0, 0xA1, 0xB7,
+	0xA4, 0x44, 0xF0, 0xA1, 0xB7, 0xA6, 0x44, 0xF0,
+	// Bytes 1700 - 173f
+	0xA2, 0x86, 0x83, 0x44, 0xF0, 0xA2, 0x86, 0x9F,
+	0x44, 0xF0, 0xA2, 0x8C, 0xB1, 0x44, 0xF0, 0xA2,
+	0x9B, 0x94, 0x44, 0xF0, 0xA2, 0xA1, 0x84, 0x44,
+	0xF0, 0xA2, 0xA1, 0x8A, 0x44, 0xF0, 0xA2, 0xAC,
+	0x8C, 0x44, 0xF0, 0xA2, 0xAF, 0xB1, 0x44, 0xF0,
+	0xA3, 0x80, 0x8A, 0x44, 0xF0, 0xA3, 0x8A, 0xB8,
+	0x44, 0xF0, 0xA3, 0x8D, 0x9F, 0x44, 0xF0, 0xA3,
+	0x8E, 0x93, 0x44, 0xF0, 0xA3, 0x8E, 0x9C, 0x44,
+	// Bytes 1740 - 177f
+	0xF0, 0xA3, 0x8F, 0x83, 0x44, 0xF0, 0xA3, 0x8F,
+	0x95, 0x44, 0xF0, 0xA3, 0x91, 0xAD, 0x44, 0xF0,
+	0xA3, 0x9A, 0xA3, 0x44, 0xF0, 0xA3, 0xA2, 0xA7,
+	0x44, 0xF0, 0xA3, 0xAA, 0x8D, 0x44, 0xF0, 0xA3,
+	0xAB, 0xBA, 0x44, 0xF0, 0xA3, 0xB2, 0xBC, 0x44,
+	0xF0, 0xA3, 0xB4, 0x9E, 0x44, 0xF0, 0xA3, 0xBB,
+	0x91, 0x44, 0xF0, 0xA3, 0xBD, 0x9E, 0x44, 0xF0,
+	0xA3, 0xBE, 0x8E, 0x44, 0xF0, 0xA4, 0x89, 0xA3,
+	// Bytes 1780 - 17bf
+	0x44, 0xF0, 0xA4, 0x8B, 0xAE, 0x44, 0xF0, 0xA4,
+	0x8E, 0xAB, 0x44, 0xF0, 0xA4, 0x98, 0x88, 0x44,
+	0xF0, 0xA4, 0x9C, 0xB5, 0x44, 0xF0, 0xA4, 0xA0,
+	0x94, 0x44, 0xF0, 0xA4, 0xB0, 0xB6, 0x44, 0xF0,
+	0xA4, 0xB2, 0x92, 0x44, 0xF0, 0xA4, 0xBE, 0xA1,
+	0x44, 0xF0, 0xA4, 0xBE, 0xB8, 0x44, 0xF0, 0xA5,
+	0x81, 0x84, 0x44, 0xF0, 0xA5, 0x83, 0xB2, 0x44,
+	0xF0, 0xA5, 0x83, 0xB3, 0x44, 0xF0, 0xA5, 0x84,
+	// Bytes 17c0 - 17ff
+	0x99, 0x44, 0xF0, 0xA5, 0x84, 0xB3, 0x44, 0xF0,
+	0xA5, 0x89, 0x89, 0x44, 0xF0, 0xA5, 0x90, 0x9D,
+	0x44, 0xF0, 0xA5, 0x98, 0xA6, 0x44, 0xF0, 0xA5,
+	0x9A, 0x9A, 0x44, 0xF0, 0xA5, 0x9B, 0x85, 0x44,
+	0xF0, 0xA5, 0xA5, 0xBC, 0x44, 0xF0, 0xA5, 0xAA,
+	0xA7, 0x44, 0xF0, 0xA5, 0xAE, 0xAB, 0x44, 0xF0,
+	0xA5, 0xB2, 0x80, 0x44, 0xF0, 0xA5, 0xB3, 0x90,
+	0x44, 0xF0, 0xA5, 0xBE, 0x86, 0x44, 0xF0, 0xA6,
+	// Bytes 1800 - 183f
+	0x87, 0x9A, 0x44, 0xF0, 0xA6, 0x88, 0xA8, 0x44,
+	0xF0, 0xA6, 0x89, 0x87, 0x44, 0xF0, 0xA6, 0x8B,
+	0x99, 0x44, 0xF0, 0xA6, 0x8C, 0xBE, 0x44, 0xF0,
+	0xA6, 0x93, 0x9A, 0x44, 0xF0, 0xA6, 0x94, 0xA3,
+	0x44, 0xF0, 0xA6, 0x96, 0xA8, 0x44, 0xF0, 0xA6,
+	0x9E, 0xA7, 0x44, 0xF0, 0xA6, 0x9E, 0xB5, 0x44,
+	0xF0, 0xA6, 0xAC, 0xBC, 0x44, 0xF0, 0xA6, 0xB0,
+	0xB6, 0x44, 0xF0, 0xA6, 0xB3, 0x95, 0x44, 0xF0,
+	// Bytes 1840 - 187f
+	0xA6, 0xB5, 0xAB, 0x44, 0xF0, 0xA6, 0xBC, 0xAC,
+	0x44, 0xF0, 0xA6, 0xBE, 0xB1, 0x44, 0xF0, 0xA7,
+	0x83, 0x92, 0x44, 0xF0, 0xA7, 0x8F, 0x8A, 0x44,
+	0xF0, 0xA7, 0x99, 0xA7, 0x44, 0xF0, 0xA7, 0xA2,
+	0xAE, 0x44, 0xF0, 0xA7, 0xA5, 0xA6, 0x44, 0xF0,
+	0xA7, 0xB2, 0xA8, 0x44, 0xF0, 0xA7, 0xBB, 0x93,
+	0x44, 0xF0, 0xA7, 0xBC, 0xAF, 0x44, 0xF0, 0xA8,
+	0x97, 0x92, 0x44, 0xF0, 0xA8, 0x97, 0xAD, 0x44,
+	// Bytes 1880 - 18bf
+	0xF0, 0xA8, 0x9C, 0xAE, 0x44, 0xF0, 0xA8, 0xAF,
+	0xBA, 0x44, 0xF0, 0xA8, 0xB5, 0xB7, 0x44, 0xF0,
+	0xA9, 0x85, 0x85, 0x44, 0xF0, 0xA9, 0x87, 0x9F,
+	0x44, 0xF0, 0xA9, 0x88, 0x9A, 0x44, 0xF0, 0xA9,
+	0x90, 0x8A, 0x44, 0xF0, 0xA9, 0x92, 0x96, 0x44,
+	0xF0, 0xA9, 0x96, 0xB6, 0x44, 0xF0, 0xA9, 0xAC,
+	0xB0, 0x44, 0xF0, 0xAA, 0x83, 0x8E, 0x44, 0xF0,
+	0xAA, 0x84, 0x85, 0x44, 0xF0, 0xAA, 0x88, 0x8E,
+	// Bytes 18c0 - 18ff
+	0x44, 0xF0, 0xAA, 0x8A, 0x91, 0x44, 0xF0, 0xAA,
+	0x8E, 0x92, 0x44, 0xF0, 0xAA, 0x98, 0x80, 0x06,
+	0xE0, 0xA7, 0x87, 0xE0, 0xA6, 0xBE, 0x06, 0xE0,
+	0xA7, 0x87, 0xE0, 0xA7, 0x97, 0x06, 0xE0, 0xAD,
+	0x87, 0xE0, 0xAC, 0xBE, 0x06, 0xE0, 0xAD, 0x87,
+	0xE0, 0xAD, 0x96, 0x06, 0xE0, 0xAD, 0x87, 0xE0,
+	0xAD, 0x97, 0x06, 0xE0, 0xAE, 0x92, 0xE0, 0xAF,
+	0x97, 0x06, 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xBE,
+	// Bytes 1900 - 193f
+	0x06, 0xE0, 0xAF, 0x86, 0xE0, 0xAF, 0x97, 0x06,
+	0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xBE, 0x06, 0xE0,
+	0xB2, 0xBF, 0xE0, 0xB3, 0x95, 0x06, 0xE0, 0xB3,
+	0x86, 0xE0, 0xB3, 0x95, 0x06, 0xE0, 0xB3, 0x86,
+	0xE0, 0xB3, 0x96, 0x06, 0xE0, 0xB5, 0x86, 0xE0,
+	0xB4, 0xBE, 0x06, 0xE0, 0xB5, 0x86, 0xE0, 0xB5,
+	0x97, 0x06, 0xE0, 0xB5, 0x87, 0xE0, 0xB4, 0xBE,
+	0x06, 0xE0, 0xB7, 0x99, 0xE0, 0xB7, 0x9F, 0x06,
+	// Bytes 1940 - 197f
+	0xE1, 0x80, 0xA5, 0xE1, 0x80, 0xAE, 0x06, 0xE1,
+	0xAC, 0x85, 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC,
+	0x87, 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC, 0x89,
+	0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC, 0x8B, 0xE1,
+	0xAC, 0xB5, 0x06, 0xE1, 0xAC, 0x8D, 0xE1, 0xAC,
+	0xB5, 0x06, 0xE1, 0xAC, 0x91, 0xE1, 0xAC, 0xB5,
+	0x06, 0xE1, 0xAC, 0xBA, 0xE1, 0xAC, 0xB5, 0x06,
+	0xE1, 0xAC, 0xBC, 0xE1, 0xAC, 0xB5, 0x06, 0xE1,
+	// Bytes 1980 - 19bf
+	0xAC, 0xBE, 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC,
+	0xBF, 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAD, 0x82,
+	0xE1, 0xAC, 0xB5, 0x08, 0xF0, 0x91, 0x84, 0xB1,
+	0xF0, 0x91, 0x84, 0xA7, 0x08, 0xF0, 0x91, 0x84,
+	0xB2, 0xF0, 0x91, 0x84, 0xA7, 0x09, 0xE0, 0xB3,
+	0x86, 0xE0, 0xB3, 0x82, 0xE0, 0xB3, 0x95, 0x42,
+	0x21, 0x21, 0x42, 0x21, 0x3F, 0x42, 0x2E, 0x2E,
+	0x42, 0x30, 0x2C, 0x42, 0x30, 0x2E, 0x42, 0x31,
+	// Bytes 19c0 - 19ff
+	0x2C, 0x42, 0x31, 0x2E, 0x42, 0x31, 0x30, 0x42,
+	0x31, 0x31, 0x42, 0x31, 0x32, 0x42, 0x31, 0x33,
+	0x42, 0x31, 0x34, 0x42, 0x31, 0x35, 0x42, 0x31,
+	0x36, 0x42, 0x31, 0x37, 0x42, 0x31, 0x38, 0x42,
+	0x31, 0x39, 0x42, 0x32, 0x2C, 0x42, 0x32, 0x2E,
+	0x42, 0x32, 0x30, 0x42, 0x32, 0x31, 0x42, 0x32,
+	0x32, 0x42, 0x32, 0x33, 0x42, 0x32, 0x34, 0x42,
+	0x32, 0x35, 0x42, 0x32, 0x36, 0x42, 0x32, 0x37,
+	// Bytes 1a00 - 1a3f
+	0x42, 0x32, 0x38, 0x42, 0x32, 0x39, 0x42, 0x33,
+	0x2C, 0x42, 0x33, 0x2E, 0x42, 0x33, 0x30, 0x42,
+	0x33, 0x31, 0x42, 0x33, 0x32, 0x42, 0x33, 0x33,
+	0x42, 0x33, 0x34, 0x42, 0x33, 0x35, 0x42, 0x33,
+	0x36, 0x42, 0x33, 0x37, 0x42, 0x33, 0x38, 0x42,
+	0x33, 0x39, 0x42, 0x34, 0x2C, 0x42, 0x34, 0x2E,
+	0x42, 0x34, 0x30, 0x42, 0x34, 0x31, 0x42, 0x34,
+	0x32, 0x42, 0x34, 0x33, 0x42, 0x34, 0x34, 0x42,
+	// Bytes 1a40 - 1a7f
+	0x34, 0x35, 0x42, 0x34, 0x36, 0x42, 0x34, 0x37,
+	0x42, 0x34, 0x38, 0x42, 0x34, 0x39, 0x42, 0x35,
+	0x2C, 0x42, 0x35, 0x2E, 0x42, 0x35, 0x30, 0x42,
+	0x36, 0x2C, 0x42, 0x36, 0x2E, 0x42, 0x37, 0x2C,
+	0x42, 0x37, 0x2E, 0x42, 0x38, 0x2C, 0x42, 0x38,
+	0x2E, 0x42, 0x39, 0x2C, 0x42, 0x39, 0x2E, 0x42,
+	0x3D, 0x3D, 0x42, 0x3F, 0x21, 0x42, 0x3F, 0x3F,
+	0x42, 0x41, 0x55, 0x42, 0x42, 0x71, 0x42, 0x43,
+	// Bytes 1a80 - 1abf
+	0x44, 0x42, 0x44, 0x4A, 0x42, 0x44, 0x5A, 0x42,
+	0x44, 0x7A, 0x42, 0x47, 0x42, 0x42, 0x47, 0x79,
+	0x42, 0x48, 0x50, 0x42, 0x48, 0x56, 0x42, 0x48,
+	0x67, 0x42, 0x48, 0x7A, 0x42, 0x49, 0x49, 0x42,
+	0x49, 0x4A, 0x42, 0x49, 0x55, 0x42, 0x49, 0x56,
+	0x42, 0x49, 0x58, 0x42, 0x4B, 0x42, 0x42, 0x4B,
+	0x4B, 0x42, 0x4B, 0x4D, 0x42, 0x4C, 0x4A, 0x42,
+	0x4C, 0x6A, 0x42, 0x4D, 0x42, 0x42, 0x4D, 0x43,
+	// Bytes 1ac0 - 1aff
+	0x42, 0x4D, 0x44, 0x42, 0x4D, 0x56, 0x42, 0x4D,
+	0x57, 0x42, 0x4E, 0x4A, 0x42, 0x4E, 0x6A, 0x42,
+	0x4E, 0x6F, 0x42, 0x50, 0x48, 0x42, 0x50, 0x52,
+	0x42, 0x50, 0x61, 0x42, 0x52, 0x73, 0x42, 0x53,
+	0x44, 0x42, 0x53, 0x4D, 0x42, 0x53, 0x53, 0x42,
+	0x53, 0x76, 0x42, 0x54, 0x4D, 0x42, 0x56, 0x49,
+	0x42, 0x57, 0x43, 0x42, 0x57, 0x5A, 0x42, 0x57,
+	0x62, 0x42, 0x58, 0x49, 0x42, 0x63, 0x63, 0x42,
+	// Bytes 1b00 - 1b3f
+	0x63, 0x64, 0x42, 0x63, 0x6D, 0x42, 0x64, 0x42,
+	0x42, 0x64, 0x61, 0x42, 0x64, 0x6C, 0x42, 0x64,
+	0x6D, 0x42, 0x64, 0x7A, 0x42, 0x65, 0x56, 0x42,
+	0x66, 0x66, 0x42, 0x66, 0x69, 0x42, 0x66, 0x6C,
+	0x42, 0x66, 0x6D, 0x42, 0x68, 0x61, 0x42, 0x69,
+	0x69, 0x42, 0x69, 0x6A, 0x42, 0x69, 0x6E, 0x42,
+	0x69, 0x76, 0x42, 0x69, 0x78, 0x42, 0x6B, 0x41,
+	0x42, 0x6B, 0x56, 0x42, 0x6B, 0x57, 0x42, 0x6B,
+	// Bytes 1b40 - 1b7f
+	0x67, 0x42, 0x6B, 0x6C, 0x42, 0x6B, 0x6D, 0x42,
+	0x6B, 0x74, 0x42, 0x6C, 0x6A, 0x42, 0x6C, 0x6D,
+	0x42, 0x6C, 0x6E, 0x42, 0x6C, 0x78, 0x42, 0x6D,
+	0x32, 0x42, 0x6D, 0x33, 0x42, 0x6D, 0x41, 0x42,
+	0x6D, 0x56, 0x42, 0x6D, 0x57, 0x42, 0x6D, 0x62,
+	0x42, 0x6D, 0x67, 0x42, 0x6D, 0x6C, 0x42, 0x6D,
+	0x6D, 0x42, 0x6D, 0x73, 0x42, 0x6E, 0x41, 0x42,
+	0x6E, 0x46, 0x42, 0x6E, 0x56, 0x42, 0x6E, 0x57,
+	// Bytes 1b80 - 1bbf
+	0x42, 0x6E, 0x6A, 0x42, 0x6E, 0x6D, 0x42, 0x6E,
+	0x73, 0x42, 0x6F, 0x56, 0x42, 0x70, 0x41, 0x42,
+	0x70, 0x46, 0x42, 0x70, 0x56, 0x42, 0x70, 0x57,
+	0x42, 0x70, 0x63, 0x42, 0x70, 0x73, 0x42, 0x73,
+	0x72, 0x42, 0x73, 0x74, 0x42, 0x76, 0x69, 0x42,
+	0x78, 0x69, 0x43, 0x28, 0x31, 0x29, 0x43, 0x28,
+	0x32, 0x29, 0x43, 0x28, 0x33, 0x29, 0x43, 0x28,
+	0x34, 0x29, 0x43, 0x28, 0x35, 0x29, 0x43, 0x28,
+	// Bytes 1bc0 - 1bff
+	0x36, 0x29, 0x43, 0x28, 0x37, 0x29, 0x43, 0x28,
+	0x38, 0x29, 0x43, 0x28, 0x39, 0x29, 0x43, 0x28,
+	0x41, 0x29, 0x43, 0x28, 0x42, 0x29, 0x43, 0x28,
+	0x43, 0x29, 0x43, 0x28, 0x44, 0x29, 0x43, 0x28,
+	0x45, 0x29, 0x43, 0x28, 0x46, 0x29, 0x43, 0x28,
+	0x47, 0x29, 0x43, 0x28, 0x48, 0x29, 0x43, 0x28,
+	0x49, 0x29, 0x43, 0x28, 0x4A, 0x29, 0x43, 0x28,
+	0x4B, 0x29, 0x43, 0x28, 0x4C, 0x29, 0x43, 0x28,
+	// Bytes 1c00 - 1c3f
+	0x4D, 0x29, 0x43, 0x28, 0x4E, 0x29, 0x43, 0x28,
+	0x4F, 0x29, 0x43, 0x28, 0x50, 0x29, 0x43, 0x28,
+	0x51, 0x29, 0x43, 0x28, 0x52, 0x29, 0x43, 0x28,
+	0x53, 0x29, 0x43, 0x28, 0x54, 0x29, 0x43, 0x28,
+	0x55, 0x29, 0x43, 0x28, 0x56, 0x29, 0x43, 0x28,
+	0x57, 0x29, 0x43, 0x28, 0x58, 0x29, 0x43, 0x28,
+	0x59, 0x29, 0x43, 0x28, 0x5A, 0x29, 0x43, 0x28,
+	0x61, 0x29, 0x43, 0x28, 0x62, 0x29, 0x43, 0x28,
+	// Bytes 1c40 - 1c7f
+	0x63, 0x29, 0x43, 0x28, 0x64, 0x29, 0x43, 0x28,
+	0x65, 0x29, 0x43, 0x28, 0x66, 0x29, 0x43, 0x28,
+	0x67, 0x29, 0x43, 0x28, 0x68, 0x29, 0x43, 0x28,
+	0x69, 0x29, 0x43, 0x28, 0x6A, 0x29, 0x43, 0x28,
+	0x6B, 0x29, 0x43, 0x28, 0x6C, 0x29, 0x43, 0x28,
+	0x6D, 0x29, 0x43, 0x28, 0x6E, 0x29, 0x43, 0x28,
+	0x6F, 0x29, 0x43, 0x28, 0x70, 0x29, 0x43, 0x28,
+	0x71, 0x29, 0x43, 0x28, 0x72, 0x29, 0x43, 0x28,
+	// Bytes 1c80 - 1cbf
+	0x73, 0x29, 0x43, 0x28, 0x74, 0x29, 0x43, 0x28,
+	0x75, 0x29, 0x43, 0x28, 0x76, 0x29, 0x43, 0x28,
+	0x77, 0x29, 0x43, 0x28, 0x78, 0x29, 0x43, 0x28,
+	0x79, 0x29, 0x43, 0x28, 0x7A, 0x29, 0x43, 0x2E,
+	0x2E, 0x2E, 0x43, 0x31, 0x30, 0x2E, 0x43, 0x31,
+	0x31, 0x2E, 0x43, 0x31, 0x32, 0x2E, 0x43, 0x31,
+	0x33, 0x2E, 0x43, 0x31, 0x34, 0x2E, 0x43, 0x31,
+	0x35, 0x2E, 0x43, 0x31, 0x36, 0x2E, 0x43, 0x31,
+	// Bytes 1cc0 - 1cff
+	0x37, 0x2E, 0x43, 0x31, 0x38, 0x2E, 0x43, 0x31,
+	0x39, 0x2E, 0x43, 0x32, 0x30, 0x2E, 0x43, 0x3A,
+	0x3A, 0x3D, 0x43, 0x3D, 0x3D, 0x3D, 0x43, 0x43,
+	0x6F, 0x2E, 0x43, 0x46, 0x41, 0x58, 0x43, 0x47,
+	0x48, 0x7A, 0x43, 0x47, 0x50, 0x61, 0x43, 0x49,
+	0x49, 0x49, 0x43, 0x4C, 0x54, 0x44, 0x43, 0x4C,
+	0xC2, 0xB7, 0x43, 0x4D, 0x48, 0x7A, 0x43, 0x4D,
+	0x50, 0x61, 0x43, 0x4D, 0xCE, 0xA9, 0x43, 0x50,
+	// Bytes 1d00 - 1d3f
+	0x50, 0x4D, 0x43, 0x50, 0x50, 0x56, 0x43, 0x50,
+	0x54, 0x45, 0x43, 0x54, 0x45, 0x4C, 0x43, 0x54,
+	0x48, 0x7A, 0x43, 0x56, 0x49, 0x49, 0x43, 0x58,
+	0x49, 0x49, 0x43, 0x61, 0x2F, 0x63, 0x43, 0x61,
+	0x2F, 0x73, 0x43, 0x61, 0xCA, 0xBE, 0x43, 0x62,
+	0x61, 0x72, 0x43, 0x63, 0x2F, 0x6F, 0x43, 0x63,
+	0x2F, 0x75, 0x43, 0x63, 0x61, 0x6C, 0x43, 0x63,
+	0x6D, 0x32, 0x43, 0x63, 0x6D, 0x33, 0x43, 0x64,
+	// Bytes 1d40 - 1d7f
+	0x6D, 0x32, 0x43, 0x64, 0x6D, 0x33, 0x43, 0x65,
+	0x72, 0x67, 0x43, 0x66, 0x66, 0x69, 0x43, 0x66,
+	0x66, 0x6C, 0x43, 0x67, 0x61, 0x6C, 0x43, 0x68,
+	0x50, 0x61, 0x43, 0x69, 0x69, 0x69, 0x43, 0x6B,
+	0x48, 0x7A, 0x43, 0x6B, 0x50, 0x61, 0x43, 0x6B,
+	0x6D, 0x32, 0x43, 0x6B, 0x6D, 0x33, 0x43, 0x6B,
+	0xCE, 0xA9, 0x43, 0x6C, 0x6F, 0x67, 0x43, 0x6C,
+	0xC2, 0xB7, 0x43, 0x6D, 0x69, 0x6C, 0x43, 0x6D,
+	// Bytes 1d80 - 1dbf
+	0x6D, 0x32, 0x43, 0x6D, 0x6D, 0x33, 0x43, 0x6D,
+	0x6F, 0x6C, 0x43, 0x72, 0x61, 0x64, 0x43, 0x76,
+	0x69, 0x69, 0x43, 0x78, 0x69, 0x69, 0x43, 0xC2,
+	0xB0, 0x43, 0x43, 0xC2, 0xB0, 0x46, 0x43, 0xCA,
+	0xBC, 0x6E, 0x43, 0xCE, 0xBC, 0x41, 0x43, 0xCE,
+	0xBC, 0x46, 0x43, 0xCE, 0xBC, 0x56, 0x43, 0xCE,
+	0xBC, 0x57, 0x43, 0xCE, 0xBC, 0x67, 0x43, 0xCE,
+	0xBC, 0x6C, 0x43, 0xCE, 0xBC, 0x6D, 0x43, 0xCE,
+	// Bytes 1dc0 - 1dff
+	0xBC, 0x73, 0x44, 0x28, 0x31, 0x30, 0x29, 0x44,
+	0x28, 0x31, 0x31, 0x29, 0x44, 0x28, 0x31, 0x32,
+	0x29, 0x44, 0x28, 0x31, 0x33, 0x29, 0x44, 0x28,
+	0x31, 0x34, 0x29, 0x44, 0x28, 0x31, 0x35, 0x29,
+	0x44, 0x28, 0x31, 0x36, 0x29, 0x44, 0x28, 0x31,
+	0x37, 0x29, 0x44, 0x28, 0x31, 0x38, 0x29, 0x44,
+	0x28, 0x31, 0x39, 0x29, 0x44, 0x28, 0x32, 0x30,
+	0x29, 0x44, 0x30, 0xE7, 0x82, 0xB9, 0x44, 0x31,
+	// Bytes 1e00 - 1e3f
+	0xE2, 0x81, 0x84, 0x44, 0x31, 0xE6, 0x97, 0xA5,
+	0x44, 0x31, 0xE6, 0x9C, 0x88, 0x44, 0x31, 0xE7,
+	0x82, 0xB9, 0x44, 0x32, 0xE6, 0x97, 0xA5, 0x44,
+	0x32, 0xE6, 0x9C, 0x88, 0x44, 0x32, 0xE7, 0x82,
+	0xB9, 0x44, 0x33, 0xE6, 0x97, 0xA5, 0x44, 0x33,
+	0xE6, 0x9C, 0x88, 0x44, 0x33, 0xE7, 0x82, 0xB9,
+	0x44, 0x34, 0xE6, 0x97, 0xA5, 0x44, 0x34, 0xE6,
+	0x9C, 0x88, 0x44, 0x34, 0xE7, 0x82, 0xB9, 0x44,
+	// Bytes 1e40 - 1e7f
+	0x35, 0xE6, 0x97, 0xA5, 0x44, 0x35, 0xE6, 0x9C,
+	0x88, 0x44, 0x35, 0xE7, 0x82, 0xB9, 0x44, 0x36,
+	0xE6, 0x97, 0xA5, 0x44, 0x36, 0xE6, 0x9C, 0x88,
+	0x44, 0x36, 0xE7, 0x82, 0xB9, 0x44, 0x37, 0xE6,
+	0x97, 0xA5, 0x44, 0x37, 0xE6, 0x9C, 0x88, 0x44,
+	0x37, 0xE7, 0x82, 0xB9, 0x44, 0x38, 0xE6, 0x97,
+	0xA5, 0x44, 0x38, 0xE6, 0x9C, 0x88, 0x44, 0x38,
+	0xE7, 0x82, 0xB9, 0x44, 0x39, 0xE6, 0x97, 0xA5,
+	// Bytes 1e80 - 1ebf
+	0x44, 0x39, 0xE6, 0x9C, 0x88, 0x44, 0x39, 0xE7,
+	0x82, 0xB9, 0x44, 0x56, 0x49, 0x49, 0x49, 0x44,
+	0x61, 0x2E, 0x6D, 0x2E, 0x44, 0x6B, 0x63, 0x61,
+	0x6C, 0x44, 0x70, 0x2E, 0x6D, 0x2E, 0x44, 0x76,
+	0x69, 0x69, 0x69, 0x44, 0xD5, 0xA5, 0xD6, 0x82,
+	0x44, 0xD5, 0xB4, 0xD5, 0xA5, 0x44, 0xD5, 0xB4,
+	0xD5, 0xAB, 0x44, 0xD5, 0xB4, 0xD5, 0xAD, 0x44,
+	0xD5, 0xB4, 0xD5, 0xB6, 0x44, 0xD5, 0xBE, 0xD5,
+	// Bytes 1ec0 - 1eff
+	0xB6, 0x44, 0xD7, 0x90, 0xD7, 0x9C, 0x44, 0xD8,
+	0xA7, 0xD9, 0xB4, 0x44, 0xD8, 0xA8, 0xD8, 0xAC,
+	0x44, 0xD8, 0xA8, 0xD8, 0xAD, 0x44, 0xD8, 0xA8,
+	0xD8, 0xAE, 0x44, 0xD8, 0xA8, 0xD8, 0xB1, 0x44,
+	0xD8, 0xA8, 0xD8, 0xB2, 0x44, 0xD8, 0xA8, 0xD9,
+	0x85, 0x44, 0xD8, 0xA8, 0xD9, 0x86, 0x44, 0xD8,
+	0xA8, 0xD9, 0x87, 0x44, 0xD8, 0xA8, 0xD9, 0x89,
+	0x44, 0xD8, 0xA8, 0xD9, 0x8A, 0x44, 0xD8, 0xAA,
+	// Bytes 1f00 - 1f3f
+	0xD8, 0xAC, 0x44, 0xD8, 0xAA, 0xD8, 0xAD, 0x44,
+	0xD8, 0xAA, 0xD8, 0xAE, 0x44, 0xD8, 0xAA, 0xD8,
+	0xB1, 0x44, 0xD8, 0xAA, 0xD8, 0xB2, 0x44, 0xD8,
+	0xAA, 0xD9, 0x85, 0x44, 0xD8, 0xAA, 0xD9, 0x86,
+	0x44, 0xD8, 0xAA, 0xD9, 0x87, 0x44, 0xD8, 0xAA,
+	0xD9, 0x89, 0x44, 0xD8, 0xAA, 0xD9, 0x8A, 0x44,
+	0xD8, 0xAB, 0xD8, 0xAC, 0x44, 0xD8, 0xAB, 0xD8,
+	0xB1, 0x44, 0xD8, 0xAB, 0xD8, 0xB2, 0x44, 0xD8,
+	// Bytes 1f40 - 1f7f
+	0xAB, 0xD9, 0x85, 0x44, 0xD8, 0xAB, 0xD9, 0x86,
+	0x44, 0xD8, 0xAB, 0xD9, 0x87, 0x44, 0xD8, 0xAB,
+	0xD9, 0x89, 0x44, 0xD8, 0xAB, 0xD9, 0x8A, 0x44,
+	0xD8, 0xAC, 0xD8, 0xAD, 0x44, 0xD8, 0xAC, 0xD9,
+	0x85, 0x44, 0xD8, 0xAC, 0xD9, 0x89, 0x44, 0xD8,
+	0xAC, 0xD9, 0x8A, 0x44, 0xD8, 0xAD, 0xD8, 0xAC,
+	0x44, 0xD8, 0xAD, 0xD9, 0x85, 0x44, 0xD8, 0xAD,
+	0xD9, 0x89, 0x44, 0xD8, 0xAD, 0xD9, 0x8A, 0x44,
+	// Bytes 1f80 - 1fbf
+	0xD8, 0xAE, 0xD8, 0xAC, 0x44, 0xD8, 0xAE, 0xD8,
+	0xAD, 0x44, 0xD8, 0xAE, 0xD9, 0x85, 0x44, 0xD8,
+	0xAE, 0xD9, 0x89, 0x44, 0xD8, 0xAE, 0xD9, 0x8A,
+	0x44, 0xD8, 0xB3, 0xD8, 0xAC, 0x44, 0xD8, 0xB3,
+	0xD8, 0xAD, 0x44, 0xD8, 0xB3, 0xD8, 0xAE, 0x44,
+	0xD8, 0xB3, 0xD8, 0xB1, 0x44, 0xD8, 0xB3, 0xD9,
+	0x85, 0x44, 0xD8, 0xB3, 0xD9, 0x87, 0x44, 0xD8,
+	0xB3, 0xD9, 0x89, 0x44, 0xD8, 0xB3, 0xD9, 0x8A,
+	// Bytes 1fc0 - 1fff
+	0x44, 0xD8, 0xB4, 0xD8, 0xAC, 0x44, 0xD8, 0xB4,
+	0xD8, 0xAD, 0x44, 0xD8, 0xB4, 0xD8, 0xAE, 0x44,
+	0xD8, 0xB4, 0xD8, 0xB1, 0x44, 0xD8, 0xB4, 0xD9,
+	0x85, 0x44, 0xD8, 0xB4, 0xD9, 0x87, 0x44, 0xD8,
+	0xB4, 0xD9, 0x89, 0x44, 0xD8, 0xB4, 0xD9, 0x8A,
+	0x44, 0xD8, 0xB5, 0xD8, 0xAD, 0x44, 0xD8, 0xB5,
+	0xD8, 0xAE, 0x44, 0xD8, 0xB5, 0xD8, 0xB1, 0x44,
+	0xD8, 0xB5, 0xD9, 0x85, 0x44, 0xD8, 0xB5, 0xD9,
+	// Bytes 2000 - 203f
+	0x89, 0x44, 0xD8, 0xB5, 0xD9, 0x8A, 0x44, 0xD8,
+	0xB6, 0xD8, 0xAC, 0x44, 0xD8, 0xB6, 0xD8, 0xAD,
+	0x44, 0xD8, 0xB6, 0xD8, 0xAE, 0x44, 0xD8, 0xB6,
+	0xD8, 0xB1, 0x44, 0xD8, 0xB6, 0xD9, 0x85, 0x44,
+	0xD8, 0xB6, 0xD9, 0x89, 0x44, 0xD8, 0xB6, 0xD9,
+	0x8A, 0x44, 0xD8, 0xB7, 0xD8, 0xAD, 0x44, 0xD8,
+	0xB7, 0xD9, 0x85, 0x44, 0xD8, 0xB7, 0xD9, 0x89,
+	0x44, 0xD8, 0xB7, 0xD9, 0x8A, 0x44, 0xD8, 0xB8,
+	// Bytes 2040 - 207f
+	0xD9, 0x85, 0x44, 0xD8, 0xB9, 0xD8, 0xAC, 0x44,
+	0xD8, 0xB9, 0xD9, 0x85, 0x44, 0xD8, 0xB9, 0xD9,
+	0x89, 0x44, 0xD8, 0xB9, 0xD9, 0x8A, 0x44, 0xD8,
+	0xBA, 0xD8, 0xAC, 0x44, 0xD8, 0xBA, 0xD9, 0x85,
+	0x44, 0xD8, 0xBA, 0xD9, 0x89, 0x44, 0xD8, 0xBA,
+	0xD9, 0x8A, 0x44, 0xD9, 0x81, 0xD8, 0xAC, 0x44,
+	0xD9, 0x81, 0xD8, 0xAD, 0x44, 0xD9, 0x81, 0xD8,
+	0xAE, 0x44, 0xD9, 0x81, 0xD9, 0x85, 0x44, 0xD9,
+	// Bytes 2080 - 20bf
+	0x81, 0xD9, 0x89, 0x44, 0xD9, 0x81, 0xD9, 0x8A,
+	0x44, 0xD9, 0x82, 0xD8, 0xAD, 0x44, 0xD9, 0x82,
+	0xD9, 0x85, 0x44, 0xD9, 0x82, 0xD9, 0x89, 0x44,
+	0xD9, 0x82, 0xD9, 0x8A, 0x44, 0xD9, 0x83, 0xD8,
+	0xA7, 0x44, 0xD9, 0x83, 0xD8, 0xAC, 0x44, 0xD9,
+	0x83, 0xD8, 0xAD, 0x44, 0xD9, 0x83, 0xD8, 0xAE,
+	0x44, 0xD9, 0x83, 0xD9, 0x84, 0x44, 0xD9, 0x83,
+	0xD9, 0x85, 0x44, 0xD9, 0x83, 0xD9, 0x89, 0x44,
+	// Bytes 20c0 - 20ff
+	0xD9, 0x83, 0xD9, 0x8A, 0x44, 0xD9, 0x84, 0xD8,
+	0xA7, 0x44, 0xD9, 0x84, 0xD8, 0xAC, 0x44, 0xD9,
+	0x84, 0xD8, 0xAD, 0x44, 0xD9, 0x84, 0xD8, 0xAE,
+	0x44, 0xD9, 0x84, 0xD9, 0x85, 0x44, 0xD9, 0x84,
+	0xD9, 0x87, 0x44, 0xD9, 0x84, 0xD9, 0x89, 0x44,
+	0xD9, 0x84, 0xD9, 0x8A, 0x44, 0xD9, 0x85, 0xD8,
+	0xA7, 0x44, 0xD9, 0x85, 0xD8, 0xAC, 0x44, 0xD9,
+	0x85, 0xD8, 0xAD, 0x44, 0xD9, 0x85, 0xD8, 0xAE,
+	// Bytes 2100 - 213f
+	0x44, 0xD9, 0x85, 0xD9, 0x85, 0x44, 0xD9, 0x85,
+	0xD9, 0x89, 0x44, 0xD9, 0x85, 0xD9, 0x8A, 0x44,
+	0xD9, 0x86, 0xD8, 0xAC, 0x44, 0xD9, 0x86, 0xD8,
+	0xAD, 0x44, 0xD9, 0x86, 0xD8, 0xAE, 0x44, 0xD9,
+	0x86, 0xD8, 0xB1, 0x44, 0xD9, 0x86, 0xD8, 0xB2,
+	0x44, 0xD9, 0x86, 0xD9, 0x85, 0x44, 0xD9, 0x86,
+	0xD9, 0x86, 0x44, 0xD9, 0x86, 0xD9, 0x87, 0x44,
+	0xD9, 0x86, 0xD9, 0x89, 0x44, 0xD9, 0x86, 0xD9,
+	// Bytes 2140 - 217f
+	0x8A, 0x44, 0xD9, 0x87, 0xD8, 0xAC, 0x44, 0xD9,
+	0x87, 0xD9, 0x85, 0x44, 0xD9, 0x87, 0xD9, 0x89,
+	0x44, 0xD9, 0x87, 0xD9, 0x8A, 0x44, 0xD9, 0x88,
+	0xD9, 0xB4, 0x44, 0xD9, 0x8A, 0xD8, 0xAC, 0x44,
+	0xD9, 0x8A, 0xD8, 0xAD, 0x44, 0xD9, 0x8A, 0xD8,
+	0xAE, 0x44, 0xD9, 0x8A, 0xD8, 0xB1, 0x44, 0xD9,
+	0x8A, 0xD8, 0xB2, 0x44, 0xD9, 0x8A, 0xD9, 0x85,
+	0x44, 0xD9, 0x8A, 0xD9, 0x86, 0x44, 0xD9, 0x8A,
+	// Bytes 2180 - 21bf
+	0xD9, 0x87, 0x44, 0xD9, 0x8A, 0xD9, 0x89, 0x44,
+	0xD9, 0x8A, 0xD9, 0x8A, 0x44, 0xD9, 0x8A, 0xD9,
+	0xB4, 0x44, 0xDB, 0x87, 0xD9, 0xB4, 0x45, 0x28,
+	0xE1, 0x84, 0x80, 0x29, 0x45, 0x28, 0xE1, 0x84,
+	0x82, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x83, 0x29,
+	0x45, 0x28, 0xE1, 0x84, 0x85, 0x29, 0x45, 0x28,
+	0xE1, 0x84, 0x86, 0x29, 0x45, 0x28, 0xE1, 0x84,
+	0x87, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x89, 0x29,
+	// Bytes 21c0 - 21ff
+	0x45, 0x28, 0xE1, 0x84, 0x8B, 0x29, 0x45, 0x28,
+	0xE1, 0x84, 0x8C, 0x29, 0x45, 0x28, 0xE1, 0x84,
+	0x8E, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x8F, 0x29,
+	0x45, 0x28, 0xE1, 0x84, 0x90, 0x29, 0x45, 0x28,
+	0xE1, 0x84, 0x91, 0x29, 0x45, 0x28, 0xE1, 0x84,
+	0x92, 0x29, 0x45, 0x28, 0xE4, 0xB8, 0x80, 0x29,
+	0x45, 0x28, 0xE4, 0xB8, 0x83, 0x29, 0x45, 0x28,
+	0xE4, 0xB8, 0x89, 0x29, 0x45, 0x28, 0xE4, 0xB9,
+	// Bytes 2200 - 223f
+	0x9D, 0x29, 0x45, 0x28, 0xE4, 0xBA, 0x8C, 0x29,
+	0x45, 0x28, 0xE4, 0xBA, 0x94, 0x29, 0x45, 0x28,
+	0xE4, 0xBB, 0xA3, 0x29, 0x45, 0x28, 0xE4, 0xBC,
+	0x81, 0x29, 0x45, 0x28, 0xE4, 0xBC, 0x91, 0x29,
+	0x45, 0x28, 0xE5, 0x85, 0xAB, 0x29, 0x45, 0x28,
+	0xE5, 0x85, 0xAD, 0x29, 0x45, 0x28, 0xE5, 0x8A,
+	0xB4, 0x29, 0x45, 0x28, 0xE5, 0x8D, 0x81, 0x29,
+	0x45, 0x28, 0xE5, 0x8D, 0x94, 0x29, 0x45, 0x28,
+	// Bytes 2240 - 227f
+	0xE5, 0x90, 0x8D, 0x29, 0x45, 0x28, 0xE5, 0x91,
+	0xBC, 0x29, 0x45, 0x28, 0xE5, 0x9B, 0x9B, 0x29,
+	0x45, 0x28, 0xE5, 0x9C, 0x9F, 0x29, 0x45, 0x28,
+	0xE5, 0xAD, 0xA6, 0x29, 0x45, 0x28, 0xE6, 0x97,
+	0xA5, 0x29, 0x45, 0x28, 0xE6, 0x9C, 0x88, 0x29,
+	0x45, 0x28, 0xE6, 0x9C, 0x89, 0x29, 0x45, 0x28,
+	0xE6, 0x9C, 0xA8, 0x29, 0x45, 0x28, 0xE6, 0xA0,
+	0xAA, 0x29, 0x45, 0x28, 0xE6, 0xB0, 0xB4, 0x29,
+	// Bytes 2280 - 22bf
+	0x45, 0x28, 0xE7, 0x81, 0xAB, 0x29, 0x45, 0x28,
+	0xE7, 0x89, 0xB9, 0x29, 0x45, 0x28, 0xE7, 0x9B,
+	0xA3, 0x29, 0x45, 0x28, 0xE7, 0xA4, 0xBE, 0x29,
+	0x45, 0x28, 0xE7, 0xA5, 0x9D, 0x29, 0x45, 0x28,
+	0xE7, 0xA5, 0xAD, 0x29, 0x45, 0x28, 0xE8, 0x87,
+	0xAA, 0x29, 0x45, 0x28, 0xE8, 0x87, 0xB3, 0x29,
+	0x45, 0x28, 0xE8, 0xB2, 0xA1, 0x29, 0x45, 0x28,
+	0xE8, 0xB3, 0x87, 0x29, 0x45, 0x28, 0xE9, 0x87,
+	// Bytes 22c0 - 22ff
+	0x91, 0x29, 0x45, 0x30, 0xE2, 0x81, 0x84, 0x33,
+	0x45, 0x31, 0x30, 0xE6, 0x97, 0xA5, 0x45, 0x31,
+	0x30, 0xE6, 0x9C, 0x88, 0x45, 0x31, 0x30, 0xE7,
+	0x82, 0xB9, 0x45, 0x31, 0x31, 0xE6, 0x97, 0xA5,
+	0x45, 0x31, 0x31, 0xE6, 0x9C, 0x88, 0x45, 0x31,
+	0x31, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x32, 0xE6,
+	0x97, 0xA5, 0x45, 0x31, 0x32, 0xE6, 0x9C, 0x88,
+	0x45, 0x31, 0x32, 0xE7, 0x82, 0xB9, 0x45, 0x31,
+	// Bytes 2300 - 233f
+	0x33, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x33, 0xE7,
+	0x82, 0xB9, 0x45, 0x31, 0x34, 0xE6, 0x97, 0xA5,
+	0x45, 0x31, 0x34, 0xE7, 0x82, 0xB9, 0x45, 0x31,
+	0x35, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x35, 0xE7,
+	0x82, 0xB9, 0x45, 0x31, 0x36, 0xE6, 0x97, 0xA5,
+	0x45, 0x31, 0x36, 0xE7, 0x82, 0xB9, 0x45, 0x31,
+	0x37, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x37, 0xE7,
+	0x82, 0xB9, 0x45, 0x31, 0x38, 0xE6, 0x97, 0xA5,
+	// Bytes 2340 - 237f
+	0x45, 0x31, 0x38, 0xE7, 0x82, 0xB9, 0x45, 0x31,
+	0x39, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x39, 0xE7,
+	0x82, 0xB9, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x32,
+	0x45, 0x31, 0xE2, 0x81, 0x84, 0x33, 0x45, 0x31,
+	0xE2, 0x81, 0x84, 0x34, 0x45, 0x31, 0xE2, 0x81,
+	0x84, 0x35, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x36,
+	0x45, 0x31, 0xE2, 0x81, 0x84, 0x37, 0x45, 0x31,
+	0xE2, 0x81, 0x84, 0x38, 0x45, 0x31, 0xE2, 0x81,
+	// Bytes 2380 - 23bf
+	0x84, 0x39, 0x45, 0x32, 0x30, 0xE6, 0x97, 0xA5,
+	0x45, 0x32, 0x30, 0xE7, 0x82, 0xB9, 0x45, 0x32,
+	0x31, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x31, 0xE7,
+	0x82, 0xB9, 0x45, 0x32, 0x32, 0xE6, 0x97, 0xA5,
+	0x45, 0x32, 0x32, 0xE7, 0x82, 0xB9, 0x45, 0x32,
+	0x33, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x33, 0xE7,
+	0x82, 0xB9, 0x45, 0x32, 0x34, 0xE6, 0x97, 0xA5,
+	0x45, 0x32, 0x34, 0xE7, 0x82, 0xB9, 0x45, 0x32,
+	// Bytes 23c0 - 23ff
+	0x35, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x36, 0xE6,
+	0x97, 0xA5, 0x45, 0x32, 0x37, 0xE6, 0x97, 0xA5,
+	0x45, 0x32, 0x38, 0xE6, 0x97, 0xA5, 0x45, 0x32,
+	0x39, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0xE2, 0x81,
+	0x84, 0x33, 0x45, 0x32, 0xE2, 0x81, 0x84, 0x35,
+	0x45, 0x33, 0x30, 0xE6, 0x97, 0xA5, 0x45, 0x33,
+	0x31, 0xE6, 0x97, 0xA5, 0x45, 0x33, 0xE2, 0x81,
+	0x84, 0x34, 0x45, 0x33, 0xE2, 0x81, 0x84, 0x35,
+	// Bytes 2400 - 243f
+	0x45, 0x33, 0xE2, 0x81, 0x84, 0x38, 0x45, 0x34,
+	0xE2, 0x81, 0x84, 0x35, 0x45, 0x35, 0xE2, 0x81,
+	0x84, 0x36, 0x45, 0x35, 0xE2, 0x81, 0x84, 0x38,
+	0x45, 0x37, 0xE2, 0x81, 0x84, 0x38, 0x45, 0x41,
+	0xE2, 0x88, 0x95, 0x6D, 0x45, 0x56, 0xE2, 0x88,
+	0x95, 0x6D, 0x45, 0x6D, 0xE2, 0x88, 0x95, 0x73,
+	0x46, 0x31, 0xE2, 0x81, 0x84, 0x31, 0x30, 0x46,
+	0x43, 0xE2, 0x88, 0x95, 0x6B, 0x67, 0x46, 0x6D,
+	// Bytes 2440 - 247f
+	0xE2, 0x88, 0x95, 0x73, 0x32, 0x46, 0xD8, 0xA8,
+	0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xA8, 0xD8,
+	0xAE, 0xD9, 0x8A, 0x46, 0xD8, 0xAA, 0xD8, 0xAC,
+	0xD9, 0x85, 0x46, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9,
+	0x89, 0x46, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9, 0x8A,
+	0x46, 0xD8, 0xAA, 0xD8, 0xAD, 0xD8, 0xAC, 0x46,
+	0xD8, 0xAA, 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD8,
+	0xAA, 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD8, 0xAA,
+	// Bytes 2480 - 24bf
+	0xD8, 0xAE, 0xD9, 0x89, 0x46, 0xD8, 0xAA, 0xD8,
+	0xAE, 0xD9, 0x8A, 0x46, 0xD8, 0xAA, 0xD9, 0x85,
+	0xD8, 0xAC, 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD8,
+	0xAD, 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAE,
+	0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD9, 0x89, 0x46,
+	0xD8, 0xAA, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8,
+	0xAC, 0xD8, 0xAD, 0xD9, 0x89, 0x46, 0xD8, 0xAC,
+	0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xAC, 0xD9,
+	// Bytes 24c0 - 24ff
+	0x85, 0xD8, 0xAD, 0x46, 0xD8, 0xAC, 0xD9, 0x85,
+	0xD9, 0x89, 0x46, 0xD8, 0xAC, 0xD9, 0x85, 0xD9,
+	0x8A, 0x46, 0xD8, 0xAD, 0xD8, 0xAC, 0xD9, 0x8A,
+	0x46, 0xD8, 0xAD, 0xD9, 0x85, 0xD9, 0x89, 0x46,
+	0xD8, 0xAD, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8,
+	0xB3, 0xD8, 0xAC, 0xD8, 0xAD, 0x46, 0xD8, 0xB3,
+	0xD8, 0xAC, 0xD9, 0x89, 0x46, 0xD8, 0xB3, 0xD8,
+	0xAD, 0xD8, 0xAC, 0x46, 0xD8, 0xB3, 0xD8, 0xAE,
+	// Bytes 2500 - 253f
+	0xD9, 0x89, 0x46, 0xD8, 0xB3, 0xD8, 0xAE, 0xD9,
+	0x8A, 0x46, 0xD8, 0xB3, 0xD9, 0x85, 0xD8, 0xAC,
+	0x46, 0xD8, 0xB3, 0xD9, 0x85, 0xD8, 0xAD, 0x46,
+	0xD8, 0xB3, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8,
+	0xB4, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD8, 0xB4,
+	0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD8, 0xB4, 0xD8,
+	0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xB4, 0xD9, 0x85,
+	0xD8, 0xAE, 0x46, 0xD8, 0xB4, 0xD9, 0x85, 0xD9,
+	// Bytes 2540 - 257f
+	0x85, 0x46, 0xD8, 0xB5, 0xD8, 0xAD, 0xD8, 0xAD,
+	0x46, 0xD8, 0xB5, 0xD8, 0xAD, 0xD9, 0x8A, 0x46,
+	0xD8, 0xB5, 0xD9, 0x84, 0xD9, 0x89, 0x46, 0xD8,
+	0xB5, 0xD9, 0x84, 0xDB, 0x92, 0x46, 0xD8, 0xB5,
+	0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8, 0xB6, 0xD8,
+	0xAD, 0xD9, 0x89, 0x46, 0xD8, 0xB6, 0xD8, 0xAD,
+	0xD9, 0x8A, 0x46, 0xD8, 0xB6, 0xD8, 0xAE, 0xD9,
+	0x85, 0x46, 0xD8, 0xB7, 0xD9, 0x85, 0xD8, 0xAD,
+	// Bytes 2580 - 25bf
+	0x46, 0xD8, 0xB7, 0xD9, 0x85, 0xD9, 0x85, 0x46,
+	0xD8, 0xB7, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8,
+	0xB9, 0xD8, 0xAC, 0xD9, 0x85, 0x46, 0xD8, 0xB9,
+	0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8, 0xB9, 0xD9,
+	0x85, 0xD9, 0x89, 0x46, 0xD8, 0xB9, 0xD9, 0x85,
+	0xD9, 0x8A, 0x46, 0xD8, 0xBA, 0xD9, 0x85, 0xD9,
+	0x85, 0x46, 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x89,
+	0x46, 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
+	// Bytes 25c0 - 25ff
+	0xD9, 0x81, 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD9,
+	0x81, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x82,
+	0xD9, 0x84, 0xDB, 0x92, 0x46, 0xD9, 0x82, 0xD9,
+	0x85, 0xD8, 0xAD, 0x46, 0xD9, 0x82, 0xD9, 0x85,
+	0xD9, 0x85, 0x46, 0xD9, 0x82, 0xD9, 0x85, 0xD9,
+	0x8A, 0x46, 0xD9, 0x83, 0xD9, 0x85, 0xD9, 0x85,
+	0x46, 0xD9, 0x83, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
+	0xD9, 0x84, 0xD8, 0xAC, 0xD8, 0xAC, 0x46, 0xD9,
+	// Bytes 2600 - 263f
+	0x84, 0xD8, 0xAC, 0xD9, 0x85, 0x46, 0xD9, 0x84,
+	0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD9, 0x84, 0xD8,
+	0xAD, 0xD9, 0x85, 0x46, 0xD9, 0x84, 0xD8, 0xAD,
+	0xD9, 0x89, 0x46, 0xD9, 0x84, 0xD8, 0xAD, 0xD9,
+	0x8A, 0x46, 0xD9, 0x84, 0xD8, 0xAE, 0xD9, 0x85,
+	0x46, 0xD9, 0x84, 0xD9, 0x85, 0xD8, 0xAD, 0x46,
+	0xD9, 0x84, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9,
+	0x85, 0xD8, 0xAC, 0xD8, 0xAD, 0x46, 0xD9, 0x85,
+	// Bytes 2640 - 267f
+	0xD8, 0xAC, 0xD8, 0xAE, 0x46, 0xD9, 0x85, 0xD8,
+	0xAC, 0xD9, 0x85, 0x46, 0xD9, 0x85, 0xD8, 0xAC,
+	0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD8, 0xAD, 0xD8,
+	0xAC, 0x46, 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x85,
+	0x46, 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x8A, 0x46,
+	0xD9, 0x85, 0xD8, 0xAE, 0xD8, 0xAC, 0x46, 0xD9,
+	0x85, 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD9, 0x85,
+	0xD8, 0xAE, 0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD9,
+	// Bytes 2680 - 26bf
+	0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x86, 0xD8, 0xAC,
+	0xD8, 0xAD, 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD9,
+	0x85, 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x89,
+	0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x8A, 0x46,
+	0xD9, 0x86, 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD9,
+	0x86, 0xD8, 0xAD, 0xD9, 0x89, 0x46, 0xD9, 0x86,
+	0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD9, 0x86, 0xD9,
+	0x85, 0xD9, 0x89, 0x46, 0xD9, 0x86, 0xD9, 0x85,
+	// Bytes 26c0 - 26ff
+	0xD9, 0x8A, 0x46, 0xD9, 0x87, 0xD9, 0x85, 0xD8,
+	0xAC, 0x46, 0xD9, 0x87, 0xD9, 0x85, 0xD9, 0x85,
+	0x46, 0xD9, 0x8A, 0xD8, 0xAC, 0xD9, 0x8A, 0x46,
+	0xD9, 0x8A, 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD9,
+	0x8A, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD9, 0x8A,
+	0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x8A, 0xD9,
+	0x94, 0xD8, 0xA7, 0x46, 0xD9, 0x8A, 0xD9, 0x94,
+	0xD8, 0xAC, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8,
+	// Bytes 2700 - 273f
+	0xAD, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xAE,
+	0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xB1, 0x46,
+	0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xB2, 0x46, 0xD9,
+	0x8A, 0xD9, 0x94, 0xD9, 0x85, 0x46, 0xD9, 0x8A,
+	0xD9, 0x94, 0xD9, 0x86, 0x46, 0xD9, 0x8A, 0xD9,
+	0x94, 0xD9, 0x87, 0x46, 0xD9, 0x8A, 0xD9, 0x94,
+	0xD9, 0x88, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9,
+	0x89, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x8A,
+	// Bytes 2740 - 277f
+	0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xDB, 0x86, 0x46,
+	0xD9, 0x8A, 0xD9, 0x94, 0xDB, 0x87, 0x46, 0xD9,
+	0x8A, 0xD9, 0x94, 0xDB, 0x88, 0x46, 0xD9, 0x8A,
+	0xD9, 0x94, 0xDB, 0x90, 0x46, 0xD9, 0x8A, 0xD9,
+	0x94, 0xDB, 0x95, 0x46, 0xE0, 0xB9, 0x8D, 0xE0,
+	0xB8, 0xB2, 0x46, 0xE0, 0xBA, 0xAB, 0xE0, 0xBA,
+	0x99, 0x46, 0xE0, 0xBA, 0xAB, 0xE0, 0xBA, 0xA1,
+	0x46, 0xE0, 0xBB, 0x8D, 0xE0, 0xBA, 0xB2, 0x46,
+	// Bytes 2780 - 27bf
+	0xE0, 0xBD, 0x80, 0xE0, 0xBE, 0xB5, 0x46, 0xE0,
+	0xBD, 0x82, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD,
+	0x8C, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x91,
+	0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x96, 0xE0,
+	0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x9B, 0xE0, 0xBE,
+	0xB7, 0x46, 0xE0, 0xBE, 0x90, 0xE0, 0xBE, 0xB5,
+	0x46, 0xE0, 0xBE, 0x92, 0xE0, 0xBE, 0xB7, 0x46,
+	0xE0, 0xBE, 0x9C, 0xE0, 0xBE, 0xB7, 0x46, 0xE0,
+	// Bytes 27c0 - 27ff
+	0xBE, 0xA1, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE,
+	0xA6, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xAB,
+	0xE0, 0xBE, 0xB7, 0x46, 0xE1, 0x84, 0x80, 0xE1,
+	0x85, 0xA1, 0x46, 0xE1, 0x84, 0x82, 0xE1, 0x85,
+	0xA1, 0x46, 0xE1, 0x84, 0x83, 0xE1, 0x85, 0xA1,
+	0x46, 0xE1, 0x84, 0x85, 0xE1, 0x85, 0xA1, 0x46,
+	0xE1, 0x84, 0x86, 0xE1, 0x85, 0xA1, 0x46, 0xE1,
+	0x84, 0x87, 0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84,
+	// Bytes 2800 - 283f
+	0x89, 0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84, 0x8B,
+	0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84, 0x8B, 0xE1,
+	0x85, 0xAE, 0x46, 0xE1, 0x84, 0x8C, 0xE1, 0x85,
+	0xA1, 0x46, 0xE1, 0x84, 0x8E, 0xE1, 0x85, 0xA1,
+	0x46, 0xE1, 0x84, 0x8F, 0xE1, 0x85, 0xA1, 0x46,
+	0xE1, 0x84, 0x90, 0xE1, 0x85, 0xA1, 0x46, 0xE1,
+	0x84, 0x91, 0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84,
+	0x92, 0xE1, 0x85, 0xA1, 0x46, 0xE2, 0x80, 0xB2,
+	// Bytes 2840 - 287f
+	0xE2, 0x80, 0xB2, 0x46, 0xE2, 0x80, 0xB5, 0xE2,
+	0x80, 0xB5, 0x46, 0xE2, 0x88, 0xAB, 0xE2, 0x88,
+	0xAB, 0x46, 0xE2, 0x88, 0xAE, 0xE2, 0x88, 0xAE,
+	0x46, 0xE3, 0x81, 0xBB, 0xE3, 0x81, 0x8B, 0x46,
+	0xE3, 0x82, 0x88, 0xE3, 0x82, 0x8A, 0x46, 0xE3,
+	0x82, 0xAD, 0xE3, 0x83, 0xAD, 0x46, 0xE3, 0x82,
+	0xB3, 0xE3, 0x82, 0xB3, 0x46, 0xE3, 0x82, 0xB3,
+	0xE3, 0x83, 0x88, 0x46, 0xE3, 0x83, 0x88, 0xE3,
+	// Bytes 2880 - 28bf
+	0x83, 0xB3, 0x46, 0xE3, 0x83, 0x8A, 0xE3, 0x83,
+	0x8E, 0x46, 0xE3, 0x83, 0x9B, 0xE3, 0x83, 0xB3,
+	0x46, 0xE3, 0x83, 0x9F, 0xE3, 0x83, 0xAA, 0x46,
+	0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xA9, 0x46, 0xE3,
+	0x83, 0xAC, 0xE3, 0x83, 0xA0, 0x46, 0xE5, 0xA4,
+	0xA7, 0xE6, 0xAD, 0xA3, 0x46, 0xE5, 0xB9, 0xB3,
+	0xE6, 0x88, 0x90, 0x46, 0xE6, 0x98, 0x8E, 0xE6,
+	0xB2, 0xBB, 0x46, 0xE6, 0x98, 0xAD, 0xE5, 0x92,
+	// Bytes 28c0 - 28ff
+	0x8C, 0x47, 0x72, 0x61, 0x64, 0xE2, 0x88, 0x95,
+	0x73, 0x47, 0xE3, 0x80, 0x94, 0x53, 0xE3, 0x80,
+	0x95, 0x48, 0x28, 0xE1, 0x84, 0x80, 0xE1, 0x85,
+	0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x82, 0xE1,
+	0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x83,
+	0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84,
+	0x85, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1,
+	0x84, 0x86, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28,
+	// Bytes 2900 - 293f
+	0xE1, 0x84, 0x87, 0xE1, 0x85, 0xA1, 0x29, 0x48,
+	0x28, 0xE1, 0x84, 0x89, 0xE1, 0x85, 0xA1, 0x29,
+	0x48, 0x28, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xA1,
+	0x29, 0x48, 0x28, 0xE1, 0x84, 0x8C, 0xE1, 0x85,
+	0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x8C, 0xE1,
+	0x85, 0xAE, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x8E,
+	0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84,
+	0x8F, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1,
+	// Bytes 2940 - 297f
+	0x84, 0x90, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28,
+	0xE1, 0x84, 0x91, 0xE1, 0x85, 0xA1, 0x29, 0x48,
+	0x28, 0xE1, 0x84, 0x92, 0xE1, 0x85, 0xA1, 0x29,
+	0x48, 0x72, 0x61, 0x64, 0xE2, 0x88, 0x95, 0x73,
+	0x32, 0x48, 0xD8, 0xA7, 0xD9, 0x83, 0xD8, 0xA8,
+	0xD8, 0xB1, 0x48, 0xD8, 0xA7, 0xD9, 0x84, 0xD9,
+	0x84, 0xD9, 0x87, 0x48, 0xD8, 0xB1, 0xD8, 0xB3,
+	0xD9, 0x88, 0xD9, 0x84, 0x48, 0xD8, 0xB1, 0xDB,
+	// Bytes 2980 - 29bf
+	0x8C, 0xD8, 0xA7, 0xD9, 0x84, 0x48, 0xD8, 0xB5,
+	0xD9, 0x84, 0xD8, 0xB9, 0xD9, 0x85, 0x48, 0xD8,
+	0xB9, 0xD9, 0x84, 0xD9, 0x8A, 0xD9, 0x87, 0x48,
+	0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x85, 0xD8, 0xAF,
+	0x48, 0xD9, 0x88, 0xD8, 0xB3, 0xD9, 0x84, 0xD9,
+	0x85, 0x49, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2,
+	0xE2, 0x80, 0xB2, 0x49, 0xE2, 0x80, 0xB5, 0xE2,
+	0x80, 0xB5, 0xE2, 0x80, 0xB5, 0x49, 0xE2, 0x88,
+	// Bytes 29c0 - 29ff
+	0xAB, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0x49,
+	0xE2, 0x88, 0xAE, 0xE2, 0x88, 0xAE, 0xE2, 0x88,
+	0xAE, 0x49, 0xE3, 0x80, 0x94, 0xE4, 0xB8, 0x89,
+	0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE4,
+	0xBA, 0x8C, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80,
+	0x94, 0xE5, 0x8B, 0x9D, 0xE3, 0x80, 0x95, 0x49,
+	0xE3, 0x80, 0x94, 0xE5, 0xAE, 0x89, 0xE3, 0x80,
+	0x95, 0x49, 0xE3, 0x80, 0x94, 0xE6, 0x89, 0x93,
+	// Bytes 2a00 - 2a3f
+	0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE6,
+	0x95, 0x97, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80,
+	0x94, 0xE6, 0x9C, 0xAC, 0xE3, 0x80, 0x95, 0x49,
+	0xE3, 0x80, 0x94, 0xE7, 0x82, 0xB9, 0xE3, 0x80,
+	0x95, 0x49, 0xE3, 0x80, 0x94, 0xE7, 0x9B, 0x97,
+	0xE3, 0x80, 0x95, 0x49, 0xE3, 0x82, 0xA2, 0xE3,
+	0x83, 0xBC, 0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x82,
+	0xA4, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0x49,
+	// Bytes 2a40 - 2a7f
+	0xE3, 0x82, 0xA6, 0xE3, 0x82, 0xA9, 0xE3, 0x83,
+	0xB3, 0x49, 0xE3, 0x82, 0xAA, 0xE3, 0x83, 0xB3,
+	0xE3, 0x82, 0xB9, 0x49, 0xE3, 0x82, 0xAA, 0xE3,
+	0x83, 0xBC, 0xE3, 0x83, 0xA0, 0x49, 0xE3, 0x82,
+	0xAB, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xAA, 0x49,
+	0xE3, 0x82, 0xB1, 0xE3, 0x83, 0xBC, 0xE3, 0x82,
+	0xB9, 0x49, 0xE3, 0x82, 0xB3, 0xE3, 0x83, 0xAB,
+	0xE3, 0x83, 0x8A, 0x49, 0xE3, 0x82, 0xBB, 0xE3,
+	// Bytes 2a80 - 2abf
+	0x83, 0xB3, 0xE3, 0x83, 0x81, 0x49, 0xE3, 0x82,
+	0xBB, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88, 0x49,
+	0xE3, 0x83, 0x86, 0xE3, 0x82, 0x99, 0xE3, 0x82,
+	0xB7, 0x49, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99,
+	0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x83, 0x8E, 0xE3,
+	0x83, 0x83, 0xE3, 0x83, 0x88, 0x49, 0xE3, 0x83,
+	0x8F, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0x84, 0x49,
+	0xE3, 0x83, 0x92, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+	// Bytes 2ac0 - 2aff
+	0xAB, 0x49, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A,
+	0xE3, 0x82, 0xB3, 0x49, 0xE3, 0x83, 0x95, 0xE3,
+	0x83, 0xA9, 0xE3, 0x83, 0xB3, 0x49, 0xE3, 0x83,
+	0x98, 0xE3, 0x82, 0x9A, 0xE3, 0x82, 0xBD, 0x49,
+	0xE3, 0x83, 0x98, 0xE3, 0x83, 0xAB, 0xE3, 0x83,
+	0x84, 0x49, 0xE3, 0x83, 0x9B, 0xE3, 0x83, 0xBC,
+	0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x83, 0x9B, 0xE3,
+	0x83, 0xBC, 0xE3, 0x83, 0xB3, 0x49, 0xE3, 0x83,
+	// Bytes 2b00 - 2b3f
+	0x9E, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xAB, 0x49,
+	0xE3, 0x83, 0x9E, 0xE3, 0x83, 0x83, 0xE3, 0x83,
+	0x8F, 0x49, 0xE3, 0x83, 0x9E, 0xE3, 0x83, 0xAB,
+	0xE3, 0x82, 0xAF, 0x49, 0xE3, 0x83, 0xA4, 0xE3,
+	0x83, 0xBC, 0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x83,
+	0xA6, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xB3, 0x49,
+	0xE3, 0x83, 0xAF, 0xE3, 0x83, 0x83, 0xE3, 0x83,
+	0x88, 0x4C, 0xE1, 0x84, 0x8C, 0xE1, 0x85, 0xAE,
+	// Bytes 2b40 - 2b7f
+	0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xB4, 0x4C, 0xE2,
+	0x80, 0xB2, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2,
+	0xE2, 0x80, 0xB2, 0x4C, 0xE2, 0x88, 0xAB, 0xE2,
+	0x88, 0xAB, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB,
+	0x4C, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xAB, 0xE3,
+	0x83, 0x95, 0xE3, 0x82, 0xA1, 0x4C, 0xE3, 0x82,
+	0xA8, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xAB, 0xE3,
+	0x83, 0xBC, 0x4C, 0xE3, 0x82, 0xAB, 0xE3, 0x82,
+	// Bytes 2b80 - 2bbf
+	0x99, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xB3, 0x4C,
+	0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+	0xB3, 0xE3, 0x83, 0x9E, 0x4C, 0xE3, 0x82, 0xAB,
+	0xE3, 0x83, 0xA9, 0xE3, 0x83, 0x83, 0xE3, 0x83,
+	0x88, 0x4C, 0xE3, 0x82, 0xAB, 0xE3, 0x83, 0xAD,
+	0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC, 0x4C, 0xE3,
+	0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0x8B,
+	0xE3, 0x83, 0xBC, 0x4C, 0xE3, 0x82, 0xAD, 0xE3,
+	// Bytes 2bc0 - 2bff
+	0x83, 0xA5, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC,
+	0x4C, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3,
+	0x83, 0xA9, 0xE3, 0x83, 0xA0, 0x4C, 0xE3, 0x82,
+	0xAF, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xBC, 0xE3,
+	0x83, 0x8D, 0x4C, 0xE3, 0x82, 0xB5, 0xE3, 0x82,
+	0xA4, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAB, 0x4C,
+	0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+	0xBC, 0xE3, 0x82, 0xB9, 0x4C, 0xE3, 0x83, 0x8F,
+	// Bytes 2c00 - 2c3f
+	0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+	0x84, 0x4C, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A,
+	0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAB, 0x4C, 0xE3,
+	0x83, 0x95, 0xE3, 0x82, 0xA3, 0xE3, 0x83, 0xBC,
+	0xE3, 0x83, 0x88, 0x4C, 0xE3, 0x83, 0x98, 0xE3,
+	0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xBF,
+	0x4C, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3,
+	0x83, 0x8B, 0xE3, 0x83, 0x92, 0x4C, 0xE3, 0x83,
+	// Bytes 2c40 - 2c7f
+	0x98, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xB3, 0xE3,
+	0x82, 0xB9, 0x4C, 0xE3, 0x83, 0x9B, 0xE3, 0x82,
+	0x99, 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x88, 0x4C,
+	0xE3, 0x83, 0x9E, 0xE3, 0x82, 0xA4, 0xE3, 0x82,
+	0xAF, 0xE3, 0x83, 0xAD, 0x4C, 0xE3, 0x83, 0x9F,
+	0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAD, 0xE3, 0x83,
+	0xB3, 0x4C, 0xE3, 0x83, 0xA1, 0xE3, 0x83, 0xBC,
+	0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x4C, 0xE3,
+	// Bytes 2c80 - 2cbf
+	0x83, 0xAA, 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88,
+	0xE3, 0x83, 0xAB, 0x4C, 0xE3, 0x83, 0xAB, 0xE3,
+	0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC,
+	0x4C, 0xE6, 0xA0, 0xAA, 0xE5, 0xBC, 0x8F, 0xE4,
+	0xBC, 0x9A, 0xE7, 0xA4, 0xBE, 0x4E, 0x28, 0xE1,
+	0x84, 0x8B, 0xE1, 0x85, 0xA9, 0xE1, 0x84, 0x92,
+	0xE1, 0x85, 0xAE, 0x29, 0x4F, 0xD8, 0xAC, 0xD9,
+	0x84, 0x20, 0xD8, 0xAC, 0xD9, 0x84, 0xD8, 0xA7,
+	// Bytes 2cc0 - 2cff
+	0xD9, 0x84, 0xD9, 0x87, 0x4F, 0xE1, 0x84, 0x8E,
+	0xE1, 0x85, 0xA1, 0xE1, 0x86, 0xB7, 0xE1, 0x84,
+	0x80, 0xE1, 0x85, 0xA9, 0x4F, 0xE3, 0x82, 0xA2,
+	0xE3, 0x83, 0x8F, 0xE3, 0x82, 0x9A, 0xE3, 0x83,
+	0xBC, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x82, 0xA2,
+	0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x98, 0xE3, 0x82,
+	0x9A, 0xE3, 0x82, 0xA2, 0x4F, 0xE3, 0x82, 0xAD,
+	0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xAF, 0xE3, 0x83,
+	// Bytes 2d00 - 2d3f
+	0x83, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x82, 0xB5,
+	0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0xE3, 0x83,
+	0xBC, 0xE3, 0x83, 0xA0, 0x4F, 0xE3, 0x83, 0x8F,
+	0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+	0xAC, 0xE3, 0x83, 0xAB, 0x4F, 0xE3, 0x83, 0x98,
+	0xE3, 0x82, 0xAF, 0xE3, 0x82, 0xBF, 0xE3, 0x83,
+	0xBC, 0xE3, 0x83, 0xAB, 0x4F, 0xE3, 0x83, 0x9B,
+	0xE3, 0x82, 0x9A, 0xE3, 0x82, 0xA4, 0xE3, 0x83,
+	// Bytes 2d40 - 2d7f
+	0xB3, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x83, 0x9E,
+	0xE3, 0x83, 0xB3, 0xE3, 0x82, 0xB7, 0xE3, 0x83,
+	0xA7, 0xE3, 0x83, 0xB3, 0x4F, 0xE3, 0x83, 0xA1,
+	0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+	0x88, 0xE3, 0x83, 0xB3, 0x4F, 0xE3, 0x83, 0xAB,
+	0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x95, 0xE3, 0x82,
+	0x99, 0xE3, 0x83, 0xAB, 0x51, 0x28, 0xE1, 0x84,
+	0x8B, 0xE1, 0x85, 0xA9, 0xE1, 0x84, 0x8C, 0xE1,
+	// Bytes 2d80 - 2dbf
+	0x85, 0xA5, 0xE1, 0x86, 0xAB, 0x29, 0x52, 0xE3,
+	0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xAB,
+	0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+	0xBC, 0x52, 0xE3, 0x82, 0xAD, 0xE3, 0x83, 0xAD,
+	0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+	0xA9, 0xE3, 0x83, 0xA0, 0x52, 0xE3, 0x82, 0xAD,
+	0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xA1, 0xE3, 0x83,
+	0xBC, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x52,
+	// Bytes 2dc0 - 2dff
+	0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+	0xA9, 0xE3, 0x83, 0xA0, 0xE3, 0x83, 0x88, 0xE3,
+	0x83, 0xB3, 0x52, 0xE3, 0x82, 0xAF, 0xE3, 0x83,
+	0xAB, 0xE3, 0x82, 0xBB, 0xE3, 0x82, 0x99, 0xE3,
+	0x82, 0xA4, 0xE3, 0x83, 0xAD, 0x52, 0xE3, 0x83,
+	0x8F, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC, 0xE3,
+	0x82, 0xBB, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88,
+	0x52, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3,
+	// Bytes 2e00 - 2e3f
+	0x82, 0xA2, 0xE3, 0x82, 0xB9, 0xE3, 0x83, 0x88,
+	0xE3, 0x83, 0xAB, 0x52, 0xE3, 0x83, 0x95, 0xE3,
+	0x82, 0x99, 0xE3, 0x83, 0x83, 0xE3, 0x82, 0xB7,
+	0xE3, 0x82, 0xA7, 0xE3, 0x83, 0xAB, 0x52, 0xE3,
+	0x83, 0x9F, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0x8F,
+	0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+	0xAB, 0x52, 0xE3, 0x83, 0xAC, 0xE3, 0x83, 0xB3,
+	0xE3, 0x83, 0x88, 0xE3, 0x82, 0xB1, 0xE3, 0x82,
+	// Bytes 2e40 - 2e7f
+	0x99, 0xE3, 0x83, 0xB3, 0x61, 0xD8, 0xB5, 0xD9,
+	0x84, 0xD9, 0x89, 0x20, 0xD8, 0xA7, 0xD9, 0x84,
+	0xD9, 0x84, 0xD9, 0x87, 0x20, 0xD8, 0xB9, 0xD9,
+	0x84, 0xD9, 0x8A, 0xD9, 0x87, 0x20, 0xD9, 0x88,
+	0xD8, 0xB3, 0xD9, 0x84, 0xD9, 0x85, 0x86, 0xE0,
+	0xB3, 0x86, 0xE0, 0xB3, 0x82, 0x86, 0xE0, 0xB7,
+	0x99, 0xE0, 0xB7, 0x8F, 0x09, 0xE0, 0xB7, 0x99,
+	0xE0, 0xB7, 0x8F, 0xE0, 0xB7, 0x8A, 0x09, 0x44,
+	// Bytes 2e80 - 2ebf
+	0x44, 0x5A, 0xCC, 0x8C, 0xE6, 0x44, 0x44, 0x7A,
+	0xCC, 0x8C, 0xE6, 0x44, 0x64, 0x7A, 0xCC, 0x8C,
+	0xE6, 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x93,
+	0xE6, 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x94,
+	0xE6, 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x95,
+	0xDC, 0x49, 0xE3, 0x83, 0xA1, 0xE3, 0x82, 0xAB,
+	0xE3, 0x82, 0x99, 0x08, 0x4C, 0xE3, 0x82, 0xAD,
+	0xE3, 0x82, 0x99, 0xE3, 0x82, 0xAB, 0xE3, 0x82,
+	// Bytes 2ec0 - 2eff
+	0x99, 0x08, 0x4C, 0xE3, 0x82, 0xB3, 0xE3, 0x83,
+	0xBC, 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x9A, 0x08,
+	0x4C, 0xE3, 0x83, 0xA4, 0xE3, 0x83, 0xBC, 0xE3,
+	0x83, 0x88, 0xE3, 0x82, 0x99, 0x08, 0x4F, 0xE3,
+	0x82, 0xA4, 0xE3, 0x83, 0x8B, 0xE3, 0x83, 0xB3,
+	0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0x08, 0x4F,
+	0xE3, 0x82, 0xB7, 0xE3, 0x83, 0xAA, 0xE3, 0x83,
+	0xB3, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0x08,
+	// Bytes 2f00 - 2f3f
+	0x4F, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3,
+	0x83, 0xBC, 0xE3, 0x82, 0xB7, 0xE3, 0x82, 0x99,
+	0x08, 0x4F, 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x9A,
+	0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88, 0xE3, 0x82,
+	0x99, 0x08, 0x52, 0xE3, 0x82, 0xA8, 0xE3, 0x82,
+	0xB9, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xBC, 0xE3,
+	0x83, 0x88, 0xE3, 0x82, 0x99, 0x08, 0x52, 0xE3,
+	0x83, 0x95, 0xE3, 0x82, 0xA1, 0xE3, 0x83, 0xA9,
+	// Bytes 2f40 - 2f7f
+	0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88, 0xE3, 0x82,
+	0x99, 0x08, 0x03, 0x3C, 0xCC, 0xB8, 0x01, 0x03,
+	0x3D, 0xCC, 0xB8, 0x01, 0x03, 0x3E, 0xCC, 0xB8,
+	0x01, 0x03, 0x41, 0xCC, 0x80, 0xE6, 0x03, 0x41,
+	0xCC, 0x81, 0xE6, 0x03, 0x41, 0xCC, 0x83, 0xE6,
+	0x03, 0x41, 0xCC, 0x84, 0xE6, 0x03, 0x41, 0xCC,
+	0x89, 0xE6, 0x03, 0x41, 0xCC, 0x8C, 0xE6, 0x03,
+	0x41, 0xCC, 0x8F, 0xE6, 0x03, 0x41, 0xCC, 0x91,
+	// Bytes 2f80 - 2fbf
+	0xE6, 0x03, 0x41, 0xCC, 0xA5, 0xDC, 0x03, 0x41,
+	0xCC, 0xA8, 0xCA, 0x03, 0x42, 0xCC, 0x87, 0xE6,
+	0x03, 0x42, 0xCC, 0xA3, 0xDC, 0x03, 0x42, 0xCC,
+	0xB1, 0xDC, 0x03, 0x43, 0xCC, 0x81, 0xE6, 0x03,
+	0x43, 0xCC, 0x82, 0xE6, 0x03, 0x43, 0xCC, 0x87,
+	0xE6, 0x03, 0x43, 0xCC, 0x8C, 0xE6, 0x03, 0x44,
+	0xCC, 0x87, 0xE6, 0x03, 0x44, 0xCC, 0x8C, 0xE6,
+	0x03, 0x44, 0xCC, 0xA3, 0xDC, 0x03, 0x44, 0xCC,
+	// Bytes 2fc0 - 2fff
+	0xA7, 0xCA, 0x03, 0x44, 0xCC, 0xAD, 0xDC, 0x03,
+	0x44, 0xCC, 0xB1, 0xDC, 0x03, 0x45, 0xCC, 0x80,
+	0xE6, 0x03, 0x45, 0xCC, 0x81, 0xE6, 0x03, 0x45,
+	0xCC, 0x83, 0xE6, 0x03, 0x45, 0xCC, 0x86, 0xE6,
+	0x03, 0x45, 0xCC, 0x87, 0xE6, 0x03, 0x45, 0xCC,
+	0x88, 0xE6, 0x03, 0x45, 0xCC, 0x89, 0xE6, 0x03,
+	0x45, 0xCC, 0x8C, 0xE6, 0x03, 0x45, 0xCC, 0x8F,
+	0xE6, 0x03, 0x45, 0xCC, 0x91, 0xE6, 0x03, 0x45,
+	// Bytes 3000 - 303f
+	0xCC, 0xA8, 0xCA, 0x03, 0x45, 0xCC, 0xAD, 0xDC,
+	0x03, 0x45, 0xCC, 0xB0, 0xDC, 0x03, 0x46, 0xCC,
+	0x87, 0xE6, 0x03, 0x47, 0xCC, 0x81, 0xE6, 0x03,
+	0x47, 0xCC, 0x82, 0xE6, 0x03, 0x47, 0xCC, 0x84,
+	0xE6, 0x03, 0x47, 0xCC, 0x86, 0xE6, 0x03, 0x47,
+	0xCC, 0x87, 0xE6, 0x03, 0x47, 0xCC, 0x8C, 0xE6,
+	0x03, 0x47, 0xCC, 0xA7, 0xCA, 0x03, 0x48, 0xCC,
+	0x82, 0xE6, 0x03, 0x48, 0xCC, 0x87, 0xE6, 0x03,
+	// Bytes 3040 - 307f
+	0x48, 0xCC, 0x88, 0xE6, 0x03, 0x48, 0xCC, 0x8C,
+	0xE6, 0x03, 0x48, 0xCC, 0xA3, 0xDC, 0x03, 0x48,
+	0xCC, 0xA7, 0xCA, 0x03, 0x48, 0xCC, 0xAE, 0xDC,
+	0x03, 0x49, 0xCC, 0x80, 0xE6, 0x03, 0x49, 0xCC,
+	0x81, 0xE6, 0x03, 0x49, 0xCC, 0x82, 0xE6, 0x03,
+	0x49, 0xCC, 0x83, 0xE6, 0x03, 0x49, 0xCC, 0x84,
+	0xE6, 0x03, 0x49, 0xCC, 0x86, 0xE6, 0x03, 0x49,
+	0xCC, 0x87, 0xE6, 0x03, 0x49, 0xCC, 0x89, 0xE6,
+	// Bytes 3080 - 30bf
+	0x03, 0x49, 0xCC, 0x8C, 0xE6, 0x03, 0x49, 0xCC,
+	0x8F, 0xE6, 0x03, 0x49, 0xCC, 0x91, 0xE6, 0x03,
+	0x49, 0xCC, 0xA3, 0xDC, 0x03, 0x49, 0xCC, 0xA8,
+	0xCA, 0x03, 0x49, 0xCC, 0xB0, 0xDC, 0x03, 0x4A,
+	0xCC, 0x82, 0xE6, 0x03, 0x4B, 0xCC, 0x81, 0xE6,
+	0x03, 0x4B, 0xCC, 0x8C, 0xE6, 0x03, 0x4B, 0xCC,
+	0xA3, 0xDC, 0x03, 0x4B, 0xCC, 0xA7, 0xCA, 0x03,
+	0x4B, 0xCC, 0xB1, 0xDC, 0x03, 0x4C, 0xCC, 0x81,
+	// Bytes 30c0 - 30ff
+	0xE6, 0x03, 0x4C, 0xCC, 0x8C, 0xE6, 0x03, 0x4C,
+	0xCC, 0xA7, 0xCA, 0x03, 0x4C, 0xCC, 0xAD, 0xDC,
+	0x03, 0x4C, 0xCC, 0xB1, 0xDC, 0x03, 0x4D, 0xCC,
+	0x81, 0xE6, 0x03, 0x4D, 0xCC, 0x87, 0xE6, 0x03,
+	0x4D, 0xCC, 0xA3, 0xDC, 0x03, 0x4E, 0xCC, 0x80,
+	0xE6, 0x03, 0x4E, 0xCC, 0x81, 0xE6, 0x03, 0x4E,
+	0xCC, 0x83, 0xE6, 0x03, 0x4E, 0xCC, 0x87, 0xE6,
+	0x03, 0x4E, 0xCC, 0x8C, 0xE6, 0x03, 0x4E, 0xCC,
+	// Bytes 3100 - 313f
+	0xA3, 0xDC, 0x03, 0x4E, 0xCC, 0xA7, 0xCA, 0x03,
+	0x4E, 0xCC, 0xAD, 0xDC, 0x03, 0x4E, 0xCC, 0xB1,
+	0xDC, 0x03, 0x4F, 0xCC, 0x80, 0xE6, 0x03, 0x4F,
+	0xCC, 0x81, 0xE6, 0x03, 0x4F, 0xCC, 0x86, 0xE6,
+	0x03, 0x4F, 0xCC, 0x89, 0xE6, 0x03, 0x4F, 0xCC,
+	0x8B, 0xE6, 0x03, 0x4F, 0xCC, 0x8C, 0xE6, 0x03,
+	0x4F, 0xCC, 0x8F, 0xE6, 0x03, 0x4F, 0xCC, 0x91,
+	0xE6, 0x03, 0x50, 0xCC, 0x81, 0xE6, 0x03, 0x50,
+	// Bytes 3140 - 317f
+	0xCC, 0x87, 0xE6, 0x03, 0x52, 0xCC, 0x81, 0xE6,
+	0x03, 0x52, 0xCC, 0x87, 0xE6, 0x03, 0x52, 0xCC,
+	0x8C, 0xE6, 0x03, 0x52, 0xCC, 0x8F, 0xE6, 0x03,
+	0x52, 0xCC, 0x91, 0xE6, 0x03, 0x52, 0xCC, 0xA7,
+	0xCA, 0x03, 0x52, 0xCC, 0xB1, 0xDC, 0x03, 0x53,
+	0xCC, 0x82, 0xE6, 0x03, 0x53, 0xCC, 0x87, 0xE6,
+	0x03, 0x53, 0xCC, 0xA6, 0xDC, 0x03, 0x53, 0xCC,
+	0xA7, 0xCA, 0x03, 0x54, 0xCC, 0x87, 0xE6, 0x03,
+	// Bytes 3180 - 31bf
+	0x54, 0xCC, 0x8C, 0xE6, 0x03, 0x54, 0xCC, 0xA3,
+	0xDC, 0x03, 0x54, 0xCC, 0xA6, 0xDC, 0x03, 0x54,
+	0xCC, 0xA7, 0xCA, 0x03, 0x54, 0xCC, 0xAD, 0xDC,
+	0x03, 0x54, 0xCC, 0xB1, 0xDC, 0x03, 0x55, 0xCC,
+	0x80, 0xE6, 0x03, 0x55, 0xCC, 0x81, 0xE6, 0x03,
+	0x55, 0xCC, 0x82, 0xE6, 0x03, 0x55, 0xCC, 0x86,
+	0xE6, 0x03, 0x55, 0xCC, 0x89, 0xE6, 0x03, 0x55,
+	0xCC, 0x8A, 0xE6, 0x03, 0x55, 0xCC, 0x8B, 0xE6,
+	// Bytes 31c0 - 31ff
+	0x03, 0x55, 0xCC, 0x8C, 0xE6, 0x03, 0x55, 0xCC,
+	0x8F, 0xE6, 0x03, 0x55, 0xCC, 0x91, 0xE6, 0x03,
+	0x55, 0xCC, 0xA3, 0xDC, 0x03, 0x55, 0xCC, 0xA4,
+	0xDC, 0x03, 0x55, 0xCC, 0xA8, 0xCA, 0x03, 0x55,
+	0xCC, 0xAD, 0xDC, 0x03, 0x55, 0xCC, 0xB0, 0xDC,
+	0x03, 0x56, 0xCC, 0x83, 0xE6, 0x03, 0x56, 0xCC,
+	0xA3, 0xDC, 0x03, 0x57, 0xCC, 0x80, 0xE6, 0x03,
+	0x57, 0xCC, 0x81, 0xE6, 0x03, 0x57, 0xCC, 0x82,
+	// Bytes 3200 - 323f
+	0xE6, 0x03, 0x57, 0xCC, 0x87, 0xE6, 0x03, 0x57,
+	0xCC, 0x88, 0xE6, 0x03, 0x57, 0xCC, 0xA3, 0xDC,
+	0x03, 0x58, 0xCC, 0x87, 0xE6, 0x03, 0x58, 0xCC,
+	0x88, 0xE6, 0x03, 0x59, 0xCC, 0x80, 0xE6, 0x03,
+	0x59, 0xCC, 0x81, 0xE6, 0x03, 0x59, 0xCC, 0x82,
+	0xE6, 0x03, 0x59, 0xCC, 0x83, 0xE6, 0x03, 0x59,
+	0xCC, 0x84, 0xE6, 0x03, 0x59, 0xCC, 0x87, 0xE6,
+	0x03, 0x59, 0xCC, 0x88, 0xE6, 0x03, 0x59, 0xCC,
+	// Bytes 3240 - 327f
+	0x89, 0xE6, 0x03, 0x59, 0xCC, 0xA3, 0xDC, 0x03,
+	0x5A, 0xCC, 0x81, 0xE6, 0x03, 0x5A, 0xCC, 0x82,
+	0xE6, 0x03, 0x5A, 0xCC, 0x87, 0xE6, 0x03, 0x5A,
+	0xCC, 0x8C, 0xE6, 0x03, 0x5A, 0xCC, 0xA3, 0xDC,
+	0x03, 0x5A, 0xCC, 0xB1, 0xDC, 0x03, 0x61, 0xCC,
+	0x80, 0xE6, 0x03, 0x61, 0xCC, 0x81, 0xE6, 0x03,
+	0x61, 0xCC, 0x83, 0xE6, 0x03, 0x61, 0xCC, 0x84,
+	0xE6, 0x03, 0x61, 0xCC, 0x89, 0xE6, 0x03, 0x61,
+	// Bytes 3280 - 32bf
+	0xCC, 0x8C, 0xE6, 0x03, 0x61, 0xCC, 0x8F, 0xE6,
+	0x03, 0x61, 0xCC, 0x91, 0xE6, 0x03, 0x61, 0xCC,
+	0xA5, 0xDC, 0x03, 0x61, 0xCC, 0xA8, 0xCA, 0x03,
+	0x62, 0xCC, 0x87, 0xE6, 0x03, 0x62, 0xCC, 0xA3,
+	0xDC, 0x03, 0x62, 0xCC, 0xB1, 0xDC, 0x03, 0x63,
+	0xCC, 0x81, 0xE6, 0x03, 0x63, 0xCC, 0x82, 0xE6,
+	0x03, 0x63, 0xCC, 0x87, 0xE6, 0x03, 0x63, 0xCC,
+	0x8C, 0xE6, 0x03, 0x64, 0xCC, 0x87, 0xE6, 0x03,
+	// Bytes 32c0 - 32ff
+	0x64, 0xCC, 0x8C, 0xE6, 0x03, 0x64, 0xCC, 0xA3,
+	0xDC, 0x03, 0x64, 0xCC, 0xA7, 0xCA, 0x03, 0x64,
+	0xCC, 0xAD, 0xDC, 0x03, 0x64, 0xCC, 0xB1, 0xDC,
+	0x03, 0x65, 0xCC, 0x80, 0xE6, 0x03, 0x65, 0xCC,
+	0x81, 0xE6, 0x03, 0x65, 0xCC, 0x83, 0xE6, 0x03,
+	0x65, 0xCC, 0x86, 0xE6, 0x03, 0x65, 0xCC, 0x87,
+	0xE6, 0x03, 0x65, 0xCC, 0x88, 0xE6, 0x03, 0x65,
+	0xCC, 0x89, 0xE6, 0x03, 0x65, 0xCC, 0x8C, 0xE6,
+	// Bytes 3300 - 333f
+	0x03, 0x65, 0xCC, 0x8F, 0xE6, 0x03, 0x65, 0xCC,
+	0x91, 0xE6, 0x03, 0x65, 0xCC, 0xA8, 0xCA, 0x03,
+	0x65, 0xCC, 0xAD, 0xDC, 0x03, 0x65, 0xCC, 0xB0,
+	0xDC, 0x03, 0x66, 0xCC, 0x87, 0xE6, 0x03, 0x67,
+	0xCC, 0x81, 0xE6, 0x03, 0x67, 0xCC, 0x82, 0xE6,
+	0x03, 0x67, 0xCC, 0x84, 0xE6, 0x03, 0x67, 0xCC,
+	0x86, 0xE6, 0x03, 0x67, 0xCC, 0x87, 0xE6, 0x03,
+	0x67, 0xCC, 0x8C, 0xE6, 0x03, 0x67, 0xCC, 0xA7,
+	// Bytes 3340 - 337f
+	0xCA, 0x03, 0x68, 0xCC, 0x82, 0xE6, 0x03, 0x68,
+	0xCC, 0x87, 0xE6, 0x03, 0x68, 0xCC, 0x88, 0xE6,
+	0x03, 0x68, 0xCC, 0x8C, 0xE6, 0x03, 0x68, 0xCC,
+	0xA3, 0xDC, 0x03, 0x68, 0xCC, 0xA7, 0xCA, 0x03,
+	0x68, 0xCC, 0xAE, 0xDC, 0x03, 0x68, 0xCC, 0xB1,
+	0xDC, 0x03, 0x69, 0xCC, 0x80, 0xE6, 0x03, 0x69,
+	0xCC, 0x81, 0xE6, 0x03, 0x69, 0xCC, 0x82, 0xE6,
+	0x03, 0x69, 0xCC, 0x83, 0xE6, 0x03, 0x69, 0xCC,
+	// Bytes 3380 - 33bf
+	0x84, 0xE6, 0x03, 0x69, 0xCC, 0x86, 0xE6, 0x03,
+	0x69, 0xCC, 0x89, 0xE6, 0x03, 0x69, 0xCC, 0x8C,
+	0xE6, 0x03, 0x69, 0xCC, 0x8F, 0xE6, 0x03, 0x69,
+	0xCC, 0x91, 0xE6, 0x03, 0x69, 0xCC, 0xA3, 0xDC,
+	0x03, 0x69, 0xCC, 0xA8, 0xCA, 0x03, 0x69, 0xCC,
+	0xB0, 0xDC, 0x03, 0x6A, 0xCC, 0x82, 0xE6, 0x03,
+	0x6A, 0xCC, 0x8C, 0xE6, 0x03, 0x6B, 0xCC, 0x81,
+	0xE6, 0x03, 0x6B, 0xCC, 0x8C, 0xE6, 0x03, 0x6B,
+	// Bytes 33c0 - 33ff
+	0xCC, 0xA3, 0xDC, 0x03, 0x6B, 0xCC, 0xA7, 0xCA,
+	0x03, 0x6B, 0xCC, 0xB1, 0xDC, 0x03, 0x6C, 0xCC,
+	0x81, 0xE6, 0x03, 0x6C, 0xCC, 0x8C, 0xE6, 0x03,
+	0x6C, 0xCC, 0xA7, 0xCA, 0x03, 0x6C, 0xCC, 0xAD,
+	0xDC, 0x03, 0x6C, 0xCC, 0xB1, 0xDC, 0x03, 0x6D,
+	0xCC, 0x81, 0xE6, 0x03, 0x6D, 0xCC, 0x87, 0xE6,
+	0x03, 0x6D, 0xCC, 0xA3, 0xDC, 0x03, 0x6E, 0xCC,
+	0x80, 0xE6, 0x03, 0x6E, 0xCC, 0x81, 0xE6, 0x03,
+	// Bytes 3400 - 343f
+	0x6E, 0xCC, 0x83, 0xE6, 0x03, 0x6E, 0xCC, 0x87,
+	0xE6, 0x03, 0x6E, 0xCC, 0x8C, 0xE6, 0x03, 0x6E,
+	0xCC, 0xA3, 0xDC, 0x03, 0x6E, 0xCC, 0xA7, 0xCA,
+	0x03, 0x6E, 0xCC, 0xAD, 0xDC, 0x03, 0x6E, 0xCC,
+	0xB1, 0xDC, 0x03, 0x6F, 0xCC, 0x80, 0xE6, 0x03,
+	0x6F, 0xCC, 0x81, 0xE6, 0x03, 0x6F, 0xCC, 0x86,
+	0xE6, 0x03, 0x6F, 0xCC, 0x89, 0xE6, 0x03, 0x6F,
+	0xCC, 0x8B, 0xE6, 0x03, 0x6F, 0xCC, 0x8C, 0xE6,
+	// Bytes 3440 - 347f
+	0x03, 0x6F, 0xCC, 0x8F, 0xE6, 0x03, 0x6F, 0xCC,
+	0x91, 0xE6, 0x03, 0x70, 0xCC, 0x81, 0xE6, 0x03,
+	0x70, 0xCC, 0x87, 0xE6, 0x03, 0x72, 0xCC, 0x81,
+	0xE6, 0x03, 0x72, 0xCC, 0x87, 0xE6, 0x03, 0x72,
+	0xCC, 0x8C, 0xE6, 0x03, 0x72, 0xCC, 0x8F, 0xE6,
+	0x03, 0x72, 0xCC, 0x91, 0xE6, 0x03, 0x72, 0xCC,
+	0xA7, 0xCA, 0x03, 0x72, 0xCC, 0xB1, 0xDC, 0x03,
+	0x73, 0xCC, 0x82, 0xE6, 0x03, 0x73, 0xCC, 0x87,
+	// Bytes 3480 - 34bf
+	0xE6, 0x03, 0x73, 0xCC, 0xA6, 0xDC, 0x03, 0x73,
+	0xCC, 0xA7, 0xCA, 0x03, 0x74, 0xCC, 0x87, 0xE6,
+	0x03, 0x74, 0xCC, 0x88, 0xE6, 0x03, 0x74, 0xCC,
+	0x8C, 0xE6, 0x03, 0x74, 0xCC, 0xA3, 0xDC, 0x03,
+	0x74, 0xCC, 0xA6, 0xDC, 0x03, 0x74, 0xCC, 0xA7,
+	0xCA, 0x03, 0x74, 0xCC, 0xAD, 0xDC, 0x03, 0x74,
+	0xCC, 0xB1, 0xDC, 0x03, 0x75, 0xCC, 0x80, 0xE6,
+	0x03, 0x75, 0xCC, 0x81, 0xE6, 0x03, 0x75, 0xCC,
+	// Bytes 34c0 - 34ff
+	0x82, 0xE6, 0x03, 0x75, 0xCC, 0x86, 0xE6, 0x03,
+	0x75, 0xCC, 0x89, 0xE6, 0x03, 0x75, 0xCC, 0x8A,
+	0xE6, 0x03, 0x75, 0xCC, 0x8B, 0xE6, 0x03, 0x75,
+	0xCC, 0x8C, 0xE6, 0x03, 0x75, 0xCC, 0x8F, 0xE6,
+	0x03, 0x75, 0xCC, 0x91, 0xE6, 0x03, 0x75, 0xCC,
+	0xA3, 0xDC, 0x03, 0x75, 0xCC, 0xA4, 0xDC, 0x03,
+	0x75, 0xCC, 0xA8, 0xCA, 0x03, 0x75, 0xCC, 0xAD,
+	0xDC, 0x03, 0x75, 0xCC, 0xB0, 0xDC, 0x03, 0x76,
+	// Bytes 3500 - 353f
+	0xCC, 0x83, 0xE6, 0x03, 0x76, 0xCC, 0xA3, 0xDC,
+	0x03, 0x77, 0xCC, 0x80, 0xE6, 0x03, 0x77, 0xCC,
+	0x81, 0xE6, 0x03, 0x77, 0xCC, 0x82, 0xE6, 0x03,
+	0x77, 0xCC, 0x87, 0xE6, 0x03, 0x77, 0xCC, 0x88,
+	0xE6, 0x03, 0x77, 0xCC, 0x8A, 0xE6, 0x03, 0x77,
+	0xCC, 0xA3, 0xDC, 0x03, 0x78, 0xCC, 0x87, 0xE6,
+	0x03, 0x78, 0xCC, 0x88, 0xE6, 0x03, 0x79, 0xCC,
+	0x80, 0xE6, 0x03, 0x79, 0xCC, 0x81, 0xE6, 0x03,
+	// Bytes 3540 - 357f
+	0x79, 0xCC, 0x82, 0xE6, 0x03, 0x79, 0xCC, 0x83,
+	0xE6, 0x03, 0x79, 0xCC, 0x84, 0xE6, 0x03, 0x79,
+	0xCC, 0x87, 0xE6, 0x03, 0x79, 0xCC, 0x88, 0xE6,
+	0x03, 0x79, 0xCC, 0x89, 0xE6, 0x03, 0x79, 0xCC,
+	0x8A, 0xE6, 0x03, 0x79, 0xCC, 0xA3, 0xDC, 0x03,
+	0x7A, 0xCC, 0x81, 0xE6, 0x03, 0x7A, 0xCC, 0x82,
+	0xE6, 0x03, 0x7A, 0xCC, 0x87, 0xE6, 0x03, 0x7A,
+	0xCC, 0x8C, 0xE6, 0x03, 0x7A, 0xCC, 0xA3, 0xDC,
+	// Bytes 3580 - 35bf
+	0x03, 0x7A, 0xCC, 0xB1, 0xDC, 0x04, 0xC2, 0xA8,
+	0xCC, 0x80, 0xE6, 0x04, 0xC2, 0xA8, 0xCC, 0x81,
+	0xE6, 0x04, 0xC2, 0xA8, 0xCD, 0x82, 0xE6, 0x04,
+	0xC3, 0x86, 0xCC, 0x81, 0xE6, 0x04, 0xC3, 0x86,
+	0xCC, 0x84, 0xE6, 0x04, 0xC3, 0x98, 0xCC, 0x81,
+	0xE6, 0x04, 0xC3, 0xA6, 0xCC, 0x81, 0xE6, 0x04,
+	0xC3, 0xA6, 0xCC, 0x84, 0xE6, 0x04, 0xC3, 0xB8,
+	0xCC, 0x81, 0xE6, 0x04, 0xC5, 0xBF, 0xCC, 0x87,
+	// Bytes 35c0 - 35ff
+	0xE6, 0x04, 0xC6, 0xB7, 0xCC, 0x8C, 0xE6, 0x04,
+	0xCA, 0x92, 0xCC, 0x8C, 0xE6, 0x04, 0xCE, 0x91,
+	0xCC, 0x80, 0xE6, 0x04, 0xCE, 0x91, 0xCC, 0x81,
+	0xE6, 0x04, 0xCE, 0x91, 0xCC, 0x84, 0xE6, 0x04,
+	0xCE, 0x91, 0xCC, 0x86, 0xE6, 0x04, 0xCE, 0x91,
+	0xCD, 0x85, 0xF0, 0x04, 0xCE, 0x95, 0xCC, 0x80,
+	0xE6, 0x04, 0xCE, 0x95, 0xCC, 0x81, 0xE6, 0x04,
+	0xCE, 0x97, 0xCC, 0x80, 0xE6, 0x04, 0xCE, 0x97,
+	// Bytes 3600 - 363f
+	0xCC, 0x81, 0xE6, 0x04, 0xCE, 0x97, 0xCD, 0x85,
+	0xF0, 0x04, 0xCE, 0x99, 0xCC, 0x80, 0xE6, 0x04,
+	0xCE, 0x99, 0xCC, 0x81, 0xE6, 0x04, 0xCE, 0x99,
+	0xCC, 0x84, 0xE6, 0x04, 0xCE, 0x99, 0xCC, 0x86,
+	0xE6, 0x04, 0xCE, 0x99, 0xCC, 0x88, 0xE6, 0x04,
+	0xCE, 0x9F, 0xCC, 0x80, 0xE6, 0x04, 0xCE, 0x9F,
+	0xCC, 0x81, 0xE6, 0x04, 0xCE, 0xA1, 0xCC, 0x94,
+	0xE6, 0x04, 0xCE, 0xA5, 0xCC, 0x80, 0xE6, 0x04,
+	// Bytes 3640 - 367f
+	0xCE, 0xA5, 0xCC, 0x81, 0xE6, 0x04, 0xCE, 0xA5,
+	0xCC, 0x84, 0xE6, 0x04, 0xCE, 0xA5, 0xCC, 0x86,
+	0xE6, 0x04, 0xCE, 0xA5, 0xCC, 0x88, 0xE6, 0x04,
+	0xCE, 0xA9, 0xCC, 0x80, 0xE6, 0x04, 0xCE, 0xA9,
+	0xCC, 0x81, 0xE6, 0x04, 0xCE, 0xA9, 0xCD, 0x85,
+	0xF0, 0x04, 0xCE, 0xB1, 0xCC, 0x84, 0xE6, 0x04,
+	0xCE, 0xB1, 0xCC, 0x86, 0xE6, 0x04, 0xCE, 0xB1,
+	0xCD, 0x85, 0xF0, 0x04, 0xCE, 0xB5, 0xCC, 0x80,
+	// Bytes 3680 - 36bf
+	0xE6, 0x04, 0xCE, 0xB5, 0xCC, 0x81, 0xE6, 0x04,
+	0xCE, 0xB7, 0xCD, 0x85, 0xF0, 0x04, 0xCE, 0xB9,
+	0xCC, 0x80, 0xE6, 0x04, 0xCE, 0xB9, 0xCC, 0x81,
+	0xE6, 0x04, 0xCE, 0xB9, 0xCC, 0x84, 0xE6, 0x04,
+	0xCE, 0xB9, 0xCC, 0x86, 0xE6, 0x04, 0xCE, 0xB9,
+	0xCD, 0x82, 0xE6, 0x04, 0xCE, 0xBF, 0xCC, 0x80,
+	0xE6, 0x04, 0xCE, 0xBF, 0xCC, 0x81, 0xE6, 0x04,
+	0xCF, 0x81, 0xCC, 0x93, 0xE6, 0x04, 0xCF, 0x81,
+	// Bytes 36c0 - 36ff
+	0xCC, 0x94, 0xE6, 0x04, 0xCF, 0x85, 0xCC, 0x80,
+	0xE6, 0x04, 0xCF, 0x85, 0xCC, 0x81, 0xE6, 0x04,
+	0xCF, 0x85, 0xCC, 0x84, 0xE6, 0x04, 0xCF, 0x85,
+	0xCC, 0x86, 0xE6, 0x04, 0xCF, 0x85, 0xCD, 0x82,
+	0xE6, 0x04, 0xCF, 0x89, 0xCD, 0x85, 0xF0, 0x04,
+	0xCF, 0x92, 0xCC, 0x81, 0xE6, 0x04, 0xCF, 0x92,
+	0xCC, 0x88, 0xE6, 0x04, 0xD0, 0x86, 0xCC, 0x88,
+	0xE6, 0x04, 0xD0, 0x90, 0xCC, 0x86, 0xE6, 0x04,
+	// Bytes 3700 - 373f
+	0xD0, 0x90, 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0x93,
+	0xCC, 0x81, 0xE6, 0x04, 0xD0, 0x95, 0xCC, 0x80,
+	0xE6, 0x04, 0xD0, 0x95, 0xCC, 0x86, 0xE6, 0x04,
+	0xD0, 0x95, 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0x96,
+	0xCC, 0x86, 0xE6, 0x04, 0xD0, 0x96, 0xCC, 0x88,
+	0xE6, 0x04, 0xD0, 0x97, 0xCC, 0x88, 0xE6, 0x04,
+	0xD0, 0x98, 0xCC, 0x80, 0xE6, 0x04, 0xD0, 0x98,
+	0xCC, 0x84, 0xE6, 0x04, 0xD0, 0x98, 0xCC, 0x86,
+	// Bytes 3740 - 377f
+	0xE6, 0x04, 0xD0, 0x98, 0xCC, 0x88, 0xE6, 0x04,
+	0xD0, 0x9A, 0xCC, 0x81, 0xE6, 0x04, 0xD0, 0x9E,
+	0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xA3, 0xCC, 0x84,
+	0xE6, 0x04, 0xD0, 0xA3, 0xCC, 0x86, 0xE6, 0x04,
+	0xD0, 0xA3, 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xA3,
+	0xCC, 0x8B, 0xE6, 0x04, 0xD0, 0xA7, 0xCC, 0x88,
+	0xE6, 0x04, 0xD0, 0xAB, 0xCC, 0x88, 0xE6, 0x04,
+	0xD0, 0xAD, 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xB0,
+	// Bytes 3780 - 37bf
+	0xCC, 0x86, 0xE6, 0x04, 0xD0, 0xB0, 0xCC, 0x88,
+	0xE6, 0x04, 0xD0, 0xB3, 0xCC, 0x81, 0xE6, 0x04,
+	0xD0, 0xB5, 0xCC, 0x80, 0xE6, 0x04, 0xD0, 0xB5,
+	0xCC, 0x86, 0xE6, 0x04, 0xD0, 0xB5, 0xCC, 0x88,
+	0xE6, 0x04, 0xD0, 0xB6, 0xCC, 0x86, 0xE6, 0x04,
+	0xD0, 0xB6, 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xB7,
+	0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xB8, 0xCC, 0x80,
+	0xE6, 0x04, 0xD0, 0xB8, 0xCC, 0x84, 0xE6, 0x04,
+	// Bytes 37c0 - 37ff
+	0xD0, 0xB8, 0xCC, 0x86, 0xE6, 0x04, 0xD0, 0xB8,
+	0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xBA, 0xCC, 0x81,
+	0xE6, 0x04, 0xD0, 0xBE, 0xCC, 0x88, 0xE6, 0x04,
+	0xD1, 0x83, 0xCC, 0x84, 0xE6, 0x04, 0xD1, 0x83,
+	0xCC, 0x86, 0xE6, 0x04, 0xD1, 0x83, 0xCC, 0x88,
+	0xE6, 0x04, 0xD1, 0x83, 0xCC, 0x8B, 0xE6, 0x04,
+	0xD1, 0x87, 0xCC, 0x88, 0xE6, 0x04, 0xD1, 0x8B,
+	0xCC, 0x88, 0xE6, 0x04, 0xD1, 0x8D, 0xCC, 0x88,
+	// Bytes 3800 - 383f
+	0xE6, 0x04, 0xD1, 0x96, 0xCC, 0x88, 0xE6, 0x04,
+	0xD1, 0xB4, 0xCC, 0x8F, 0xE6, 0x04, 0xD1, 0xB5,
+	0xCC, 0x8F, 0xE6, 0x04, 0xD3, 0x98, 0xCC, 0x88,
+	0xE6, 0x04, 0xD3, 0x99, 0xCC, 0x88, 0xE6, 0x04,
+	0xD3, 0xA8, 0xCC, 0x88, 0xE6, 0x04, 0xD3, 0xA9,
+	0xCC, 0x88, 0xE6, 0x04, 0xD8, 0xA7, 0xD9, 0x93,
+	0xE6, 0x04, 0xD8, 0xA7, 0xD9, 0x94, 0xE6, 0x04,
+	0xD8, 0xA7, 0xD9, 0x95, 0xDC, 0x04, 0xD9, 0x88,
+	// Bytes 3840 - 387f
+	0xD9, 0x94, 0xE6, 0x04, 0xD9, 0x8A, 0xD9, 0x94,
+	0xE6, 0x04, 0xDB, 0x81, 0xD9, 0x94, 0xE6, 0x04,
+	0xDB, 0x92, 0xD9, 0x94, 0xE6, 0x04, 0xDB, 0x95,
+	0xD9, 0x94, 0xE6, 0x05, 0x41, 0xCC, 0x82, 0xCC,
+	0x80, 0xE6, 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x81,
+	0xE6, 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x83, 0xE6,
+	0x05, 0x41, 0xCC, 0x82, 0xCC, 0x89, 0xE6, 0x05,
+	0x41, 0xCC, 0x86, 0xCC, 0x80, 0xE6, 0x05, 0x41,
+	// Bytes 3880 - 38bf
+	0xCC, 0x86, 0xCC, 0x81, 0xE6, 0x05, 0x41, 0xCC,
+	0x86, 0xCC, 0x83, 0xE6, 0x05, 0x41, 0xCC, 0x86,
+	0xCC, 0x89, 0xE6, 0x05, 0x41, 0xCC, 0x87, 0xCC,
+	0x84, 0xE6, 0x05, 0x41, 0xCC, 0x88, 0xCC, 0x84,
+	0xE6, 0x05, 0x41, 0xCC, 0x8A, 0xCC, 0x81, 0xE6,
+	0x05, 0x41, 0xCC, 0xA3, 0xCC, 0x82, 0xE6, 0x05,
+	0x41, 0xCC, 0xA3, 0xCC, 0x86, 0xE6, 0x05, 0x43,
+	0xCC, 0xA7, 0xCC, 0x81, 0xE6, 0x05, 0x45, 0xCC,
+	// Bytes 38c0 - 38ff
+	0x82, 0xCC, 0x80, 0xE6, 0x05, 0x45, 0xCC, 0x82,
+	0xCC, 0x81, 0xE6, 0x05, 0x45, 0xCC, 0x82, 0xCC,
+	0x83, 0xE6, 0x05, 0x45, 0xCC, 0x82, 0xCC, 0x89,
+	0xE6, 0x05, 0x45, 0xCC, 0x84, 0xCC, 0x80, 0xE6,
+	0x05, 0x45, 0xCC, 0x84, 0xCC, 0x81, 0xE6, 0x05,
+	0x45, 0xCC, 0xA3, 0xCC, 0x82, 0xE6, 0x05, 0x45,
+	0xCC, 0xA7, 0xCC, 0x86, 0xE6, 0x05, 0x49, 0xCC,
+	0x88, 0xCC, 0x81, 0xE6, 0x05, 0x4C, 0xCC, 0xA3,
+	// Bytes 3900 - 393f
+	0xCC, 0x84, 0xE6, 0x05, 0x4F, 0xCC, 0x82, 0xCC,
+	0x80, 0xE6, 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x81,
+	0xE6, 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x83, 0xE6,
+	0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x89, 0xE6, 0x05,
+	0x4F, 0xCC, 0x83, 0xCC, 0x81, 0xE6, 0x05, 0x4F,
+	0xCC, 0x83, 0xCC, 0x84, 0xE6, 0x05, 0x4F, 0xCC,
+	0x83, 0xCC, 0x88, 0xE6, 0x05, 0x4F, 0xCC, 0x84,
+	0xCC, 0x80, 0xE6, 0x05, 0x4F, 0xCC, 0x84, 0xCC,
+	// Bytes 3940 - 397f
+	0x81, 0xE6, 0x05, 0x4F, 0xCC, 0x87, 0xCC, 0x84,
+	0xE6, 0x05, 0x4F, 0xCC, 0x88, 0xCC, 0x84, 0xE6,
+	0x05, 0x4F, 0xCC, 0x9B, 0xCC, 0x80, 0xE6, 0x05,
+	0x4F, 0xCC, 0x9B, 0xCC, 0x81, 0xE6, 0x05, 0x4F,
+	0xCC, 0x9B, 0xCC, 0x83, 0xE6, 0x05, 0x4F, 0xCC,
+	0x9B, 0xCC, 0x89, 0xE6, 0x05, 0x4F, 0xCC, 0x9B,
+	0xCC, 0xA3, 0xDC, 0x05, 0x4F, 0xCC, 0xA3, 0xCC,
+	0x82, 0xE6, 0x05, 0x4F, 0xCC, 0xA8, 0xCC, 0x84,
+	// Bytes 3980 - 39bf
+	0xE6, 0x05, 0x52, 0xCC, 0xA3, 0xCC, 0x84, 0xE6,
+	0x05, 0x53, 0xCC, 0x81, 0xCC, 0x87, 0xE6, 0x05,
+	0x53, 0xCC, 0x8C, 0xCC, 0x87, 0xE6, 0x05, 0x53,
+	0xCC, 0xA3, 0xCC, 0x87, 0xE6, 0x05, 0x55, 0xCC,
+	0x83, 0xCC, 0x81, 0xE6, 0x05, 0x55, 0xCC, 0x84,
+	0xCC, 0x88, 0xE6, 0x05, 0x55, 0xCC, 0x88, 0xCC,
+	0x80, 0xE6, 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x81,
+	0xE6, 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x84, 0xE6,
+	// Bytes 39c0 - 39ff
+	0x05, 0x55, 0xCC, 0x88, 0xCC, 0x8C, 0xE6, 0x05,
+	0x55, 0xCC, 0x9B, 0xCC, 0x80, 0xE6, 0x05, 0x55,
+	0xCC, 0x9B, 0xCC, 0x81, 0xE6, 0x05, 0x55, 0xCC,
+	0x9B, 0xCC, 0x83, 0xE6, 0x05, 0x55, 0xCC, 0x9B,
+	0xCC, 0x89, 0xE6, 0x05, 0x55, 0xCC, 0x9B, 0xCC,
+	0xA3, 0xDC, 0x05, 0x61, 0xCC, 0x82, 0xCC, 0x80,
+	0xE6, 0x05, 0x61, 0xCC, 0x82, 0xCC, 0x81, 0xE6,
+	0x05, 0x61, 0xCC, 0x82, 0xCC, 0x83, 0xE6, 0x05,
+	// Bytes 3a00 - 3a3f
+	0x61, 0xCC, 0x82, 0xCC, 0x89, 0xE6, 0x05, 0x61,
+	0xCC, 0x86, 0xCC, 0x80, 0xE6, 0x05, 0x61, 0xCC,
+	0x86, 0xCC, 0x81, 0xE6, 0x05, 0x61, 0xCC, 0x86,
+	0xCC, 0x83, 0xE6, 0x05, 0x61, 0xCC, 0x86, 0xCC,
+	0x89, 0xE6, 0x05, 0x61, 0xCC, 0x87, 0xCC, 0x84,
+	0xE6, 0x05, 0x61, 0xCC, 0x88, 0xCC, 0x84, 0xE6,
+	0x05, 0x61, 0xCC, 0x8A, 0xCC, 0x81, 0xE6, 0x05,
+	0x61, 0xCC, 0xA3, 0xCC, 0x82, 0xE6, 0x05, 0x61,
+	// Bytes 3a40 - 3a7f
+	0xCC, 0xA3, 0xCC, 0x86, 0xE6, 0x05, 0x63, 0xCC,
+	0xA7, 0xCC, 0x81, 0xE6, 0x05, 0x65, 0xCC, 0x82,
+	0xCC, 0x80, 0xE6, 0x05, 0x65, 0xCC, 0x82, 0xCC,
+	0x81, 0xE6, 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x83,
+	0xE6, 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x89, 0xE6,
+	0x05, 0x65, 0xCC, 0x84, 0xCC, 0x80, 0xE6, 0x05,
+	0x65, 0xCC, 0x84, 0xCC, 0x81, 0xE6, 0x05, 0x65,
+	0xCC, 0xA3, 0xCC, 0x82, 0xE6, 0x05, 0x65, 0xCC,
+	// Bytes 3a80 - 3abf
+	0xA7, 0xCC, 0x86, 0xE6, 0x05, 0x69, 0xCC, 0x88,
+	0xCC, 0x81, 0xE6, 0x05, 0x6C, 0xCC, 0xA3, 0xCC,
+	0x84, 0xE6, 0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x80,
+	0xE6, 0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x81, 0xE6,
+	0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x83, 0xE6, 0x05,
+	0x6F, 0xCC, 0x82, 0xCC, 0x89, 0xE6, 0x05, 0x6F,
+	0xCC, 0x83, 0xCC, 0x81, 0xE6, 0x05, 0x6F, 0xCC,
+	0x83, 0xCC, 0x84, 0xE6, 0x05, 0x6F, 0xCC, 0x83,
+	// Bytes 3ac0 - 3aff
+	0xCC, 0x88, 0xE6, 0x05, 0x6F, 0xCC, 0x84, 0xCC,
+	0x80, 0xE6, 0x05, 0x6F, 0xCC, 0x84, 0xCC, 0x81,
+	0xE6, 0x05, 0x6F, 0xCC, 0x87, 0xCC, 0x84, 0xE6,
+	0x05, 0x6F, 0xCC, 0x88, 0xCC, 0x84, 0xE6, 0x05,
+	0x6F, 0xCC, 0x9B, 0xCC, 0x80, 0xE6, 0x05, 0x6F,
+	0xCC, 0x9B, 0xCC, 0x81, 0xE6, 0x05, 0x6F, 0xCC,
+	0x9B, 0xCC, 0x83, 0xE6, 0x05, 0x6F, 0xCC, 0x9B,
+	0xCC, 0x89, 0xE6, 0x05, 0x6F, 0xCC, 0x9B, 0xCC,
+	// Bytes 3b00 - 3b3f
+	0xA3, 0xDC, 0x05, 0x6F, 0xCC, 0xA3, 0xCC, 0x82,
+	0xE6, 0x05, 0x6F, 0xCC, 0xA8, 0xCC, 0x84, 0xE6,
+	0x05, 0x72, 0xCC, 0xA3, 0xCC, 0x84, 0xE6, 0x05,
+	0x73, 0xCC, 0x81, 0xCC, 0x87, 0xE6, 0x05, 0x73,
+	0xCC, 0x8C, 0xCC, 0x87, 0xE6, 0x05, 0x73, 0xCC,
+	0xA3, 0xCC, 0x87, 0xE6, 0x05, 0x75, 0xCC, 0x83,
+	0xCC, 0x81, 0xE6, 0x05, 0x75, 0xCC, 0x84, 0xCC,
+	0x88, 0xE6, 0x05, 0x75, 0xCC, 0x88, 0xCC, 0x80,
+	// Bytes 3b40 - 3b7f
+	0xE6, 0x05, 0x75, 0xCC, 0x88, 0xCC, 0x81, 0xE6,
+	0x05, 0x75, 0xCC, 0x88, 0xCC, 0x84, 0xE6, 0x05,
+	0x75, 0xCC, 0x88, 0xCC, 0x8C, 0xE6, 0x05, 0x75,
+	0xCC, 0x9B, 0xCC, 0x80, 0xE6, 0x05, 0x75, 0xCC,
+	0x9B, 0xCC, 0x81, 0xE6, 0x05, 0x75, 0xCC, 0x9B,
+	0xCC, 0x83, 0xE6, 0x05, 0x75, 0xCC, 0x9B, 0xCC,
+	0x89, 0xE6, 0x05, 0x75, 0xCC, 0x9B, 0xCC, 0xA3,
+	0xDC, 0x05, 0xE1, 0xBE, 0xBF, 0xCC, 0x80, 0xE6,
+	// Bytes 3b80 - 3bbf
+	0x05, 0xE1, 0xBE, 0xBF, 0xCC, 0x81, 0xE6, 0x05,
+	0xE1, 0xBE, 0xBF, 0xCD, 0x82, 0xE6, 0x05, 0xE1,
+	0xBF, 0xBE, 0xCC, 0x80, 0xE6, 0x05, 0xE1, 0xBF,
+	0xBE, 0xCC, 0x81, 0xE6, 0x05, 0xE1, 0xBF, 0xBE,
+	0xCD, 0x82, 0xE6, 0x05, 0xE2, 0x86, 0x90, 0xCC,
+	0xB8, 0x01, 0x05, 0xE2, 0x86, 0x92, 0xCC, 0xB8,
+	0x01, 0x05, 0xE2, 0x86, 0x94, 0xCC, 0xB8, 0x01,
+	0x05, 0xE2, 0x87, 0x90, 0xCC, 0xB8, 0x01, 0x05,
+	// Bytes 3bc0 - 3bff
+	0xE2, 0x87, 0x92, 0xCC, 0xB8, 0x01, 0x05, 0xE2,
+	0x87, 0x94, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x88,
+	0x83, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x88, 0x88,
+	0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x88, 0x8B, 0xCC,
+	0xB8, 0x01, 0x05, 0xE2, 0x88, 0xA3, 0xCC, 0xB8,
+	0x01, 0x05, 0xE2, 0x88, 0xA5, 0xCC, 0xB8, 0x01,
+	0x05, 0xE2, 0x88, 0xBC, 0xCC, 0xB8, 0x01, 0x05,
+	0xE2, 0x89, 0x83, 0xCC, 0xB8, 0x01, 0x05, 0xE2,
+	// Bytes 3c00 - 3c3f
+	0x89, 0x85, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89,
+	0x88, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89, 0x8D,
+	0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89, 0xA1, 0xCC,
+	0xB8, 0x01, 0x05, 0xE2, 0x89, 0xA4, 0xCC, 0xB8,
+	0x01, 0x05, 0xE2, 0x89, 0xA5, 0xCC, 0xB8, 0x01,
+	0x05, 0xE2, 0x89, 0xB2, 0xCC, 0xB8, 0x01, 0x05,
+	0xE2, 0x89, 0xB3, 0xCC, 0xB8, 0x01, 0x05, 0xE2,
+	0x89, 0xB6, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89,
+	// Bytes 3c40 - 3c7f
+	0xB7, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89, 0xBA,
+	0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89, 0xBB, 0xCC,
+	0xB8, 0x01, 0x05, 0xE2, 0x89, 0xBC, 0xCC, 0xB8,
+	0x01, 0x05, 0xE2, 0x89, 0xBD, 0xCC, 0xB8, 0x01,
+	0x05, 0xE2, 0x8A, 0x82, 0xCC, 0xB8, 0x01, 0x05,
+	0xE2, 0x8A, 0x83, 0xCC, 0xB8, 0x01, 0x05, 0xE2,
+	0x8A, 0x86, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A,
+	0x87, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A, 0x91,
+	// Bytes 3c80 - 3cbf
+	0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A, 0x92, 0xCC,
+	0xB8, 0x01, 0x05, 0xE2, 0x8A, 0xA2, 0xCC, 0xB8,
+	0x01, 0x05, 0xE2, 0x8A, 0xA8, 0xCC, 0xB8, 0x01,
+	0x05, 0xE2, 0x8A, 0xA9, 0xCC, 0xB8, 0x01, 0x05,
+	0xE2, 0x8A, 0xAB, 0xCC, 0xB8, 0x01, 0x05, 0xE2,
+	0x8A, 0xB2, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A,
+	0xB3, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A, 0xB4,
+	0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A, 0xB5, 0xCC,
+	// Bytes 3cc0 - 3cff
+	0xB8, 0x01, 0x06, 0xCE, 0x91, 0xCC, 0x93, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0x91, 0xCC, 0x94, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0x95, 0xCC, 0x93, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0x95, 0xCC, 0x93, 0xCC,
+	0x81, 0xE6, 0x06, 0xCE, 0x95, 0xCC, 0x94, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0x95, 0xCC, 0x94, 0xCC,
+	0x81, 0xE6, 0x06, 0xCE, 0x97, 0xCC, 0x93, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0x97, 0xCC, 0x94, 0xCD,
+	// Bytes 3d00 - 3d3f
+	0x85, 0xF0, 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCC,
+	0x81, 0xE6, 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCD,
+	0x82, 0xE6, 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCC,
+	0x81, 0xE6, 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCD,
+	0x82, 0xE6, 0x06, 0xCE, 0x9F, 0xCC, 0x93, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0x9F, 0xCC, 0x93, 0xCC,
+	// Bytes 3d40 - 3d7f
+	0x81, 0xE6, 0x06, 0xCE, 0x9F, 0xCC, 0x94, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0x9F, 0xCC, 0x94, 0xCC,
+	0x81, 0xE6, 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCC,
+	0x81, 0xE6, 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCD,
+	0x82, 0xE6, 0x06, 0xCE, 0xA9, 0xCC, 0x93, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xA9, 0xCC, 0x94, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xB1, 0xCC, 0x80, 0xCD,
+	// Bytes 3d80 - 3dbf
+	0x85, 0xF0, 0x06, 0xCE, 0xB1, 0xCC, 0x81, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xB1, 0xCC, 0x93, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xB1, 0xCC, 0x94, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xB1, 0xCD, 0x82, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xB5, 0xCC, 0x93, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0xB5, 0xCC, 0x93, 0xCC,
+	0x81, 0xE6, 0x06, 0xCE, 0xB5, 0xCC, 0x94, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0xB5, 0xCC, 0x94, 0xCC,
+	// Bytes 3dc0 - 3dff
+	0x81, 0xE6, 0x06, 0xCE, 0xB7, 0xCC, 0x80, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xB7, 0xCC, 0x81, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xB7, 0xCC, 0x93, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xB7, 0xCC, 0x94, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xB7, 0xCD, 0x82, 0xCD,
+	0x85, 0xF0, 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCC,
+	0x81, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCD,
+	// Bytes 3e00 - 3e3f
+	0x82, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCC,
+	0x81, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCD,
+	0x82, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCC,
+	0x81, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCD,
+	0x82, 0xE6, 0x06, 0xCE, 0xBF, 0xCC, 0x93, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0xBF, 0xCC, 0x93, 0xCC,
+	// Bytes 3e40 - 3e7f
+	0x81, 0xE6, 0x06, 0xCE, 0xBF, 0xCC, 0x94, 0xCC,
+	0x80, 0xE6, 0x06, 0xCE, 0xBF, 0xCC, 0x94, 0xCC,
+	0x81, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCC,
+	0x80, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCC,
+	0x81, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCD,
+	0x82, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCC,
+	0x80, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCC,
+	0x81, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCD,
+	// Bytes 3e80 - 3ebf
+	0x82, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCC,
+	0x80, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCC,
+	0x81, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCD,
+	0x82, 0xE6, 0x06, 0xCF, 0x89, 0xCC, 0x80, 0xCD,
+	0x85, 0xF0, 0x06, 0xCF, 0x89, 0xCC, 0x81, 0xCD,
+	0x85, 0xF0, 0x06, 0xCF, 0x89, 0xCC, 0x93, 0xCD,
+	0x85, 0xF0, 0x06, 0xCF, 0x89, 0xCC, 0x94, 0xCD,
+	0x85, 0xF0, 0x06, 0xCF, 0x89, 0xCD, 0x82, 0xCD,
+	// Bytes 3ec0 - 3eff
+	0x85, 0xF0, 0x06, 0xE0, 0xA4, 0xA8, 0xE0, 0xA4,
+	0xBC, 0x07, 0x06, 0xE0, 0xA4, 0xB0, 0xE0, 0xA4,
+	0xBC, 0x07, 0x06, 0xE0, 0xA4, 0xB3, 0xE0, 0xA4,
+	0xBC, 0x07, 0x06, 0xE0, 0xB1, 0x86, 0xE0, 0xB1,
+	0x96, 0x5B, 0x06, 0xE0, 0xB7, 0x99, 0xE0, 0xB7,
+	0x8A, 0x09, 0x06, 0xE3, 0x81, 0x86, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x8B, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x8D, 0xE3, 0x82,
+	// Bytes 3f00 - 3f3f
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x8F, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x91, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x93, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x95, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x97, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x99, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x9B, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x9D, 0xE3, 0x82,
+	// Bytes 3f40 - 3f7f
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0x9F, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0xA1, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0xA4, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0xA6, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0xA8, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0xAF, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0xAF, 0xE3, 0x82,
+	0x9A, 0x08, 0x06, 0xE3, 0x81, 0xB2, 0xE3, 0x82,
+	// Bytes 3f80 - 3fbf
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0xB2, 0xE3, 0x82,
+	0x9A, 0x08, 0x06, 0xE3, 0x81, 0xB5, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0xB5, 0xE3, 0x82,
+	0x9A, 0x08, 0x06, 0xE3, 0x81, 0xB8, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0xB8, 0xE3, 0x82,
+	0x9A, 0x08, 0x06, 0xE3, 0x81, 0xBB, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x81, 0xBB, 0xE3, 0x82,
+	0x9A, 0x08, 0x06, 0xE3, 0x82, 0x9D, 0xE3, 0x82,
+	// Bytes 3fc0 - 3fff
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xA6, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xAB, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xAD, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xAF, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xB1, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xB3, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xB5, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xB7, 0xE3, 0x82,
+	// Bytes 4000 - 403f
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xB9, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xBB, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xBD, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x82, 0xBF, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0x81, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0x84, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0x86, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0x88, 0xE3, 0x82,
+	// Bytes 4040 - 407f
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0x8F, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0x8F, 0xE3, 0x82,
+	0x9A, 0x08, 0x06, 0xE3, 0x83, 0x92, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0x92, 0xE3, 0x82,
+	0x9A, 0x08, 0x06, 0xE3, 0x83, 0x95, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0x95, 0xE3, 0x82,
+	0x9A, 0x08, 0x06, 0xE3, 0x83, 0x98, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0x98, 0xE3, 0x82,
+	// Bytes 4080 - 40bf
+	0x9A, 0x08, 0x06, 0xE3, 0x83, 0x9B, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0x9B, 0xE3, 0x82,
+	0x9A, 0x08, 0x06, 0xE3, 0x83, 0xAF, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0xB0, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0xB1, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0xB2, 0xE3, 0x82,
+	0x99, 0x08, 0x06, 0xE3, 0x83, 0xBD, 0xE3, 0x82,
+	0x99, 0x08, 0x08, 0xCE, 0x91, 0xCC, 0x93, 0xCC,
+	// Bytes 40c0 - 40ff
+	0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0x91, 0xCC,
+	0x93, 0xCC, 0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
+	0x91, 0xCC, 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xF0,
+	0x08, 0xCE, 0x91, 0xCC, 0x94, 0xCC, 0x80, 0xCD,
+	0x85, 0xF0, 0x08, 0xCE, 0x91, 0xCC, 0x94, 0xCC,
+	0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0x91, 0xCC,
+	0x94, 0xCD, 0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
+	0x97, 0xCC, 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xF0,
+	// Bytes 4100 - 413f
+	0x08, 0xCE, 0x97, 0xCC, 0x93, 0xCC, 0x81, 0xCD,
+	0x85, 0xF0, 0x08, 0xCE, 0x97, 0xCC, 0x93, 0xCD,
+	0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0x97, 0xCC,
+	0x94, 0xCC, 0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
+	0x97, 0xCC, 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xF0,
+	0x08, 0xCE, 0x97, 0xCC, 0x94, 0xCD, 0x82, 0xCD,
+	0x85, 0xF0, 0x08, 0xCE, 0xA9, 0xCC, 0x93, 0xCC,
+	0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0xA9, 0xCC,
+	// Bytes 4140 - 417f
+	0x93, 0xCC, 0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
+	0xA9, 0xCC, 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xF0,
+	0x08, 0xCE, 0xA9, 0xCC, 0x94, 0xCC, 0x80, 0xCD,
+	0x85, 0xF0, 0x08, 0xCE, 0xA9, 0xCC, 0x94, 0xCC,
+	0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0xA9, 0xCC,
+	0x94, 0xCD, 0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
+	0xB1, 0xCC, 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xF0,
+	0x08, 0xCE, 0xB1, 0xCC, 0x93, 0xCC, 0x81, 0xCD,
+	// Bytes 4180 - 41bf
+	0x85, 0xF0, 0x08, 0xCE, 0xB1, 0xCC, 0x93, 0xCD,
+	0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0xB1, 0xCC,
+	0x94, 0xCC, 0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
+	0xB1, 0xCC, 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xF0,
+	0x08, 0xCE, 0xB1, 0xCC, 0x94, 0xCD, 0x82, 0xCD,
+	0x85, 0xF0, 0x08, 0xCE, 0xB7, 0xCC, 0x93, 0xCC,
+	0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0xB7, 0xCC,
+	0x93, 0xCC, 0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
+	// Bytes 41c0 - 41ff
+	0xB7, 0xCC, 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xF0,
+	0x08, 0xCE, 0xB7, 0xCC, 0x94, 0xCC, 0x80, 0xCD,
+	0x85, 0xF0, 0x08, 0xCE, 0xB7, 0xCC, 0x94, 0xCC,
+	0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0xB7, 0xCC,
+	0x94, 0xCD, 0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCF,
+	0x89, 0xCC, 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xF0,
+	0x08, 0xCF, 0x89, 0xCC, 0x93, 0xCC, 0x81, 0xCD,
+	0x85, 0xF0, 0x08, 0xCF, 0x89, 0xCC, 0x93, 0xCD,
+	// Bytes 4200 - 423f
+	0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCF, 0x89, 0xCC,
+	0x94, 0xCC, 0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCF,
+	0x89, 0xCC, 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xF0,
+	0x08, 0xCF, 0x89, 0xCC, 0x94, 0xCD, 0x82, 0xCD,
+	0x85, 0xF0, 0x08, 0xF0, 0x91, 0x82, 0x99, 0xF0,
+	0x91, 0x82, 0xBA, 0x07, 0x08, 0xF0, 0x91, 0x82,
+	0x9B, 0xF0, 0x91, 0x82, 0xBA, 0x07, 0x08, 0xF0,
+	0x91, 0x82, 0xA5, 0xF0, 0x91, 0x82, 0xBA, 0x07,
+	// Bytes 4240 - 427f
+	0x43, 0x20, 0xCC, 0x81, 0xE6, 0x43, 0x20, 0xCC,
+	0x83, 0xE6, 0x43, 0x20, 0xCC, 0x84, 0xE6, 0x43,
+	0x20, 0xCC, 0x85, 0xE6, 0x43, 0x20, 0xCC, 0x86,
+	0xE6, 0x43, 0x20, 0xCC, 0x87, 0xE6, 0x43, 0x20,
+	0xCC, 0x88, 0xE6, 0x43, 0x20, 0xCC, 0x8A, 0xE6,
+	0x43, 0x20, 0xCC, 0x8B, 0xE6, 0x43, 0x20, 0xCC,
+	0x93, 0xE6, 0x43, 0x20, 0xCC, 0x94, 0xE6, 0x43,
+	0x20, 0xCC, 0xA7, 0xCA, 0x43, 0x20, 0xCC, 0xA8,
+	// Bytes 4280 - 42bf
+	0xCA, 0x43, 0x20, 0xCC, 0xB3, 0xDC, 0x43, 0x20,
+	0xCD, 0x82, 0xE6, 0x43, 0x20, 0xCD, 0x85, 0xF0,
+	0x43, 0x20, 0xD9, 0x8B, 0x1B, 0x43, 0x20, 0xD9,
+	0x8C, 0x1C, 0x43, 0x20, 0xD9, 0x8D, 0x1D, 0x43,
+	0x20, 0xD9, 0x8E, 0x1E, 0x43, 0x20, 0xD9, 0x8F,
+	0x1F, 0x43, 0x20, 0xD9, 0x90, 0x20, 0x43, 0x20,
+	0xD9, 0x91, 0x21, 0x43, 0x20, 0xD9, 0x92, 0x22,
+	0x43, 0x41, 0xCC, 0x8A, 0xE6, 0x43, 0x73, 0xCC,
+	// Bytes 42c0 - 42ff
+	0x87, 0xE6, 0x44, 0x20, 0xE3, 0x82, 0x99, 0x08,
+	0x44, 0x20, 0xE3, 0x82, 0x9A, 0x08, 0x44, 0xC2,
+	0xA8, 0xCC, 0x81, 0xE6, 0x44, 0xCE, 0x91, 0xCC,
+	0x81, 0xE6, 0x44, 0xCE, 0x95, 0xCC, 0x81, 0xE6,
+	0x44, 0xCE, 0x97, 0xCC, 0x81, 0xE6, 0x44, 0xCE,
+	0x99, 0xCC, 0x81, 0xE6, 0x44, 0xCE, 0x9F, 0xCC,
+	0x81, 0xE6, 0x44, 0xCE, 0xA5, 0xCC, 0x81, 0xE6,
+	0x44, 0xCE, 0xA5, 0xCC, 0x88, 0xE6, 0x44, 0xCE,
+	// Bytes 4300 - 433f
+	0xA9, 0xCC, 0x81, 0xE6, 0x44, 0xCE, 0xB1, 0xCC,
+	0x81, 0xE6, 0x44, 0xCE, 0xB5, 0xCC, 0x81, 0xE6,
+	0x44, 0xCE, 0xB7, 0xCC, 0x81, 0xE6, 0x44, 0xCE,
+	0xB9, 0xCC, 0x81, 0xE6, 0x44, 0xCE, 0xBF, 0xCC,
+	0x81, 0xE6, 0x44, 0xCF, 0x85, 0xCC, 0x81, 0xE6,
+	0x44, 0xCF, 0x89, 0xCC, 0x81, 0xE6, 0x44, 0xD7,
+	0x90, 0xD6, 0xB7, 0x11, 0x44, 0xD7, 0x90, 0xD6,
+	0xB8, 0x12, 0x44, 0xD7, 0x90, 0xD6, 0xBC, 0x15,
+	// Bytes 4340 - 437f
+	0x44, 0xD7, 0x91, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
+	0x91, 0xD6, 0xBF, 0x17, 0x44, 0xD7, 0x92, 0xD6,
+	0xBC, 0x15, 0x44, 0xD7, 0x93, 0xD6, 0xBC, 0x15,
+	0x44, 0xD7, 0x94, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
+	0x95, 0xD6, 0xB9, 0x13, 0x44, 0xD7, 0x95, 0xD6,
+	0xBC, 0x15, 0x44, 0xD7, 0x96, 0xD6, 0xBC, 0x15,
+	0x44, 0xD7, 0x98, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
+	0x99, 0xD6, 0xB4, 0x0E, 0x44, 0xD7, 0x99, 0xD6,
+	// Bytes 4380 - 43bf
+	0xBC, 0x15, 0x44, 0xD7, 0x9A, 0xD6, 0xBC, 0x15,
+	0x44, 0xD7, 0x9B, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
+	0x9B, 0xD6, 0xBF, 0x17, 0x44, 0xD7, 0x9C, 0xD6,
+	0xBC, 0x15, 0x44, 0xD7, 0x9E, 0xD6, 0xBC, 0x15,
+	0x44, 0xD7, 0xA0, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
+	0xA1, 0xD6, 0xBC, 0x15, 0x44, 0xD7, 0xA3, 0xD6,
+	0xBC, 0x15, 0x44, 0xD7, 0xA4, 0xD6, 0xBC, 0x15,
+	0x44, 0xD7, 0xA4, 0xD6, 0xBF, 0x17, 0x44, 0xD7,
+	// Bytes 43c0 - 43ff
+	0xA6, 0xD6, 0xBC, 0x15, 0x44, 0xD7, 0xA7, 0xD6,
+	0xBC, 0x15, 0x44, 0xD7, 0xA8, 0xD6, 0xBC, 0x15,
+	0x44, 0xD7, 0xA9, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
+	0xA9, 0xD7, 0x81, 0x18, 0x44, 0xD7, 0xA9, 0xD7,
+	0x82, 0x19, 0x44, 0xD7, 0xAA, 0xD6, 0xBC, 0x15,
+	0x44, 0xD7, 0xB2, 0xD6, 0xB7, 0x11, 0x44, 0xD8,
+	0xA7, 0xD9, 0x8B, 0x1B, 0x44, 0xD8, 0xA7, 0xD9,
+	0x93, 0xE6, 0x44, 0xD8, 0xA7, 0xD9, 0x94, 0xE6,
+	// Bytes 4400 - 443f
+	0x44, 0xD8, 0xA7, 0xD9, 0x95, 0xDC, 0x44, 0xD8,
+	0xB0, 0xD9, 0xB0, 0x23, 0x44, 0xD8, 0xB1, 0xD9,
+	0xB0, 0x23, 0x44, 0xD9, 0x80, 0xD9, 0x8B, 0x1B,
+	0x44, 0xD9, 0x80, 0xD9, 0x8E, 0x1E, 0x44, 0xD9,
+	0x80, 0xD9, 0x8F, 0x1F, 0x44, 0xD9, 0x80, 0xD9,
+	0x90, 0x20, 0x44, 0xD9, 0x80, 0xD9, 0x91, 0x21,
+	0x44, 0xD9, 0x80, 0xD9, 0x92, 0x22, 0x44, 0xD9,
+	0x87, 0xD9, 0xB0, 0x23, 0x44, 0xD9, 0x88, 0xD9,
+	// Bytes 4440 - 447f
+	0x94, 0xE6, 0x44, 0xD9, 0x89, 0xD9, 0xB0, 0x23,
+	0x44, 0xD9, 0x8A, 0xD9, 0x94, 0xE6, 0x44, 0xDB,
+	0x92, 0xD9, 0x94, 0xE6, 0x44, 0xDB, 0x95, 0xD9,
+	0x94, 0xE6, 0x45, 0x20, 0xCC, 0x88, 0xCC, 0x80,
+	0xE6, 0x45, 0x20, 0xCC, 0x88, 0xCC, 0x81, 0xE6,
+	0x45, 0x20, 0xCC, 0x88, 0xCD, 0x82, 0xE6, 0x45,
+	0x20, 0xCC, 0x93, 0xCC, 0x80, 0xE6, 0x45, 0x20,
+	0xCC, 0x93, 0xCC, 0x81, 0xE6, 0x45, 0x20, 0xCC,
+	// Bytes 4480 - 44bf
+	0x93, 0xCD, 0x82, 0xE6, 0x45, 0x20, 0xCC, 0x94,
+	0xCC, 0x80, 0xE6, 0x45, 0x20, 0xCC, 0x94, 0xCC,
+	0x81, 0xE6, 0x45, 0x20, 0xCC, 0x94, 0xCD, 0x82,
+	0xE6, 0x45, 0x20, 0xD9, 0x8C, 0xD9, 0x91, 0x21,
+	0x45, 0x20, 0xD9, 0x8D, 0xD9, 0x91, 0x21, 0x45,
+	0x20, 0xD9, 0x8E, 0xD9, 0x91, 0x21, 0x45, 0x20,
+	0xD9, 0x8F, 0xD9, 0x91, 0x21, 0x45, 0x20, 0xD9,
+	0x90, 0xD9, 0x91, 0x21, 0x45, 0x20, 0xD9, 0x91,
+	// Bytes 44c0 - 44ff
+	0xD9, 0xB0, 0x23, 0x45, 0xE2, 0xAB, 0x9D, 0xCC,
+	0xB8, 0x01, 0x46, 0xCE, 0xB9, 0xCC, 0x88, 0xCC,
+	0x81, 0xE6, 0x46, 0xCF, 0x85, 0xCC, 0x88, 0xCC,
+	0x81, 0xE6, 0x46, 0xD7, 0xA9, 0xD6, 0xBC, 0xD7,
+	0x81, 0x18, 0x46, 0xD7, 0xA9, 0xD6, 0xBC, 0xD7,
+	0x82, 0x19, 0x46, 0xD9, 0x80, 0xD9, 0x8E, 0xD9,
+	0x91, 0x21, 0x46, 0xD9, 0x80, 0xD9, 0x8F, 0xD9,
+	0x91, 0x21, 0x46, 0xD9, 0x80, 0xD9, 0x90, 0xD9,
+	// Bytes 4500 - 453f
+	0x91, 0x21, 0x46, 0xE0, 0xA4, 0x95, 0xE0, 0xA4,
+	0xBC, 0x07, 0x46, 0xE0, 0xA4, 0x96, 0xE0, 0xA4,
+	0xBC, 0x07, 0x46, 0xE0, 0xA4, 0x97, 0xE0, 0xA4,
+	0xBC, 0x07, 0x46, 0xE0, 0xA4, 0x9C, 0xE0, 0xA4,
+	0xBC, 0x07, 0x46, 0xE0, 0xA4, 0xA1, 0xE0, 0xA4,
+	0xBC, 0x07, 0x46, 0xE0, 0xA4, 0xA2, 0xE0, 0xA4,
+	0xBC, 0x07, 0x46, 0xE0, 0xA4, 0xAB, 0xE0, 0xA4,
+	0xBC, 0x07, 0x46, 0xE0, 0xA4, 0xAF, 0xE0, 0xA4,
+	// Bytes 4540 - 457f
+	0xBC, 0x07, 0x46, 0xE0, 0xA6, 0xA1, 0xE0, 0xA6,
+	0xBC, 0x07, 0x46, 0xE0, 0xA6, 0xA2, 0xE0, 0xA6,
+	0xBC, 0x07, 0x46, 0xE0, 0xA6, 0xAF, 0xE0, 0xA6,
+	0xBC, 0x07, 0x46, 0xE0, 0xA8, 0x96, 0xE0, 0xA8,
+	0xBC, 0x07, 0x46, 0xE0, 0xA8, 0x97, 0xE0, 0xA8,
+	0xBC, 0x07, 0x46, 0xE0, 0xA8, 0x9C, 0xE0, 0xA8,
+	0xBC, 0x07, 0x46, 0xE0, 0xA8, 0xAB, 0xE0, 0xA8,
+	0xBC, 0x07, 0x46, 0xE0, 0xA8, 0xB2, 0xE0, 0xA8,
+	// Bytes 4580 - 45bf
+	0xBC, 0x07, 0x46, 0xE0, 0xA8, 0xB8, 0xE0, 0xA8,
+	0xBC, 0x07, 0x46, 0xE0, 0xAC, 0xA1, 0xE0, 0xAC,
+	0xBC, 0x07, 0x46, 0xE0, 0xAC, 0xA2, 0xE0, 0xAC,
+	0xBC, 0x07, 0x46, 0xE0, 0xBE, 0xB2, 0xE0, 0xBE,
+	0x80, 0x82, 0x46, 0xE0, 0xBE, 0xB3, 0xE0, 0xBE,
+	0x80, 0x82, 0x46, 0xE3, 0x83, 0x86, 0xE3, 0x82,
+	0x99, 0x08, 0x48, 0xF0, 0x9D, 0x85, 0x97, 0xF0,
+	0x9D, 0x85, 0xA5, 0xD8, 0x48, 0xF0, 0x9D, 0x85,
+	// Bytes 45c0 - 45ff
+	0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xD8, 0x48, 0xF0,
+	0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xD8,
+	0x48, 0xF0, 0x9D, 0x86, 0xBA, 0xF0, 0x9D, 0x85,
+	0xA5, 0xD8, 0x49, 0xE0, 0xBE, 0xB2, 0xE0, 0xBD,
+	0xB1, 0xE0, 0xBE, 0x80, 0x82, 0x49, 0xE0, 0xBE,
+	0xB3, 0xE0, 0xBD, 0xB1, 0xE0, 0xBE, 0x80, 0x82,
+	0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85,
+	0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0xD8, 0x4C, 0xF0,
+	// Bytes 4600 - 463f
+	0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0,
+	0x9D, 0x85, 0xAF, 0xD8, 0x4C, 0xF0, 0x9D, 0x85,
+	0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85,
+	0xB0, 0xD8, 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0,
+	0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xB1, 0xD8,
+	0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85,
+	0xA5, 0xF0, 0x9D, 0x85, 0xB2, 0xD8, 0x4C, 0xF0,
+	0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xF0,
+	// Bytes 4640 - 467f
+	0x9D, 0x85, 0xAE, 0xD8, 0x4C, 0xF0, 0x9D, 0x86,
+	0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85,
+	0xAF, 0xD8, 0x4C, 0xF0, 0x9D, 0x86, 0xBA, 0xF0,
+	0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0xD8,
+	0x4C, 0xF0, 0x9D, 0x86, 0xBA, 0xF0, 0x9D, 0x85,
+	0xA5, 0xF0, 0x9D, 0x85, 0xAF, 0xD8, 0x83, 0x41,
+	0xCC, 0x82, 0xE6, 0x83, 0x41, 0xCC, 0x86, 0xE6,
+	0x83, 0x41, 0xCC, 0x87, 0xE6, 0x83, 0x41, 0xCC,
+	// Bytes 4680 - 46bf
+	0x88, 0xE6, 0x83, 0x41, 0xCC, 0x8A, 0xE6, 0x83,
+	0x41, 0xCC, 0xA3, 0xDC, 0x83, 0x43, 0xCC, 0xA7,
+	0xCA, 0x83, 0x45, 0xCC, 0x82, 0xE6, 0x83, 0x45,
+	0xCC, 0x84, 0xE6, 0x83, 0x45, 0xCC, 0xA3, 0xDC,
+	0x83, 0x45, 0xCC, 0xA7, 0xCA, 0x83, 0x49, 0xCC,
+	0x88, 0xE6, 0x83, 0x4C, 0xCC, 0xA3, 0xDC, 0x83,
+	0x4F, 0xCC, 0x82, 0xE6, 0x83, 0x4F, 0xCC, 0x83,
+	0xE6, 0x83, 0x4F, 0xCC, 0x84, 0xE6, 0x83, 0x4F,
+	// Bytes 46c0 - 46ff
+	0xCC, 0x87, 0xE6, 0x83, 0x4F, 0xCC, 0x88, 0xE6,
+	0x83, 0x4F, 0xCC, 0x9B, 0xD8, 0x83, 0x4F, 0xCC,
+	0xA3, 0xDC, 0x83, 0x4F, 0xCC, 0xA8, 0xCA, 0x83,
+	0x52, 0xCC, 0xA3, 0xDC, 0x83, 0x53, 0xCC, 0x81,
+	0xE6, 0x83, 0x53, 0xCC, 0x8C, 0xE6, 0x83, 0x53,
+	0xCC, 0xA3, 0xDC, 0x83, 0x55, 0xCC, 0x83, 0xE6,
+	0x83, 0x55, 0xCC, 0x84, 0xE6, 0x83, 0x55, 0xCC,
+	0x88, 0xE6, 0x83, 0x55, 0xCC, 0x9B, 0xD8, 0x83,
+	// Bytes 4700 - 473f
+	0x61, 0xCC, 0x82, 0xE6, 0x83, 0x61, 0xCC, 0x86,
+	0xE6, 0x83, 0x61, 0xCC, 0x87, 0xE6, 0x83, 0x61,
+	0xCC, 0x88, 0xE6, 0x83, 0x61, 0xCC, 0x8A, 0xE6,
+	0x83, 0x61, 0xCC, 0xA3, 0xDC, 0x83, 0x63, 0xCC,
+	0xA7, 0xCA, 0x83, 0x65, 0xCC, 0x82, 0xE6, 0x83,
+	0x65, 0xCC, 0x84, 0xE6, 0x83, 0x65, 0xCC, 0xA3,
+	0xDC, 0x83, 0x65, 0xCC, 0xA7, 0xCA, 0x83, 0x69,
+	0xCC, 0x88, 0xE6, 0x83, 0x6C, 0xCC, 0xA3, 0xDC,
+	// Bytes 4740 - 477f
+	0x83, 0x6F, 0xCC, 0x82, 0xE6, 0x83, 0x6F, 0xCC,
+	0x83, 0xE6, 0x83, 0x6F, 0xCC, 0x84, 0xE6, 0x83,
+	0x6F, 0xCC, 0x87, 0xE6, 0x83, 0x6F, 0xCC, 0x88,
+	0xE6, 0x83, 0x6F, 0xCC, 0x9B, 0xD8, 0x83, 0x6F,
+	0xCC, 0xA3, 0xDC, 0x83, 0x6F, 0xCC, 0xA8, 0xCA,
+	0x83, 0x72, 0xCC, 0xA3, 0xDC, 0x83, 0x73, 0xCC,
+	0x81, 0xE6, 0x83, 0x73, 0xCC, 0x8C, 0xE6, 0x83,
+	0x73, 0xCC, 0xA3, 0xDC, 0x83, 0x75, 0xCC, 0x83,
+	// Bytes 4780 - 47bf
+	0xE6, 0x83, 0x75, 0xCC, 0x84, 0xE6, 0x83, 0x75,
+	0xCC, 0x88, 0xE6, 0x83, 0x75, 0xCC, 0x9B, 0xD8,
+	0x84, 0xCE, 0x91, 0xCC, 0x93, 0xE6, 0x84, 0xCE,
+	0x91, 0xCC, 0x94, 0xE6, 0x84, 0xCE, 0x95, 0xCC,
+	0x93, 0xE6, 0x84, 0xCE, 0x95, 0xCC, 0x94, 0xE6,
+	0x84, 0xCE, 0x97, 0xCC, 0x93, 0xE6, 0x84, 0xCE,
+	0x97, 0xCC, 0x94, 0xE6, 0x84, 0xCE, 0x99, 0xCC,
+	0x93, 0xE6, 0x84, 0xCE, 0x99, 0xCC, 0x94, 0xE6,
+	// Bytes 47c0 - 47ff
+	0x84, 0xCE, 0x9F, 0xCC, 0x93, 0xE6, 0x84, 0xCE,
+	0x9F, 0xCC, 0x94, 0xE6, 0x84, 0xCE, 0xA5, 0xCC,
+	0x94, 0xE6, 0x84, 0xCE, 0xA9, 0xCC, 0x93, 0xE6,
+	0x84, 0xCE, 0xA9, 0xCC, 0x94, 0xE6, 0x84, 0xCE,
+	0xB1, 0xCC, 0x80, 0xE6, 0x84, 0xCE, 0xB1, 0xCC,
+	0x81, 0xE6, 0x84, 0xCE, 0xB1, 0xCC, 0x93, 0xE6,
+	0x84, 0xCE, 0xB1, 0xCC, 0x94, 0xE6, 0x84, 0xCE,
+	0xB1, 0xCD, 0x82, 0xE6, 0x84, 0xCE, 0xB5, 0xCC,
+	// Bytes 4800 - 483f
+	0x93, 0xE6, 0x84, 0xCE, 0xB5, 0xCC, 0x94, 0xE6,
+	0x84, 0xCE, 0xB7, 0xCC, 0x80, 0xE6, 0x84, 0xCE,
+	0xB7, 0xCC, 0x81, 0xE6, 0x84, 0xCE, 0xB7, 0xCC,
+	0x93, 0xE6, 0x84, 0xCE, 0xB7, 0xCC, 0x94, 0xE6,
+	0x84, 0xCE, 0xB7, 0xCD, 0x82, 0xE6, 0x84, 0xCE,
+	0xB9, 0xCC, 0x88, 0xE6, 0x84, 0xCE, 0xB9, 0xCC,
+	0x93, 0xE6, 0x84, 0xCE, 0xB9, 0xCC, 0x94, 0xE6,
+	0x84, 0xCE, 0xBF, 0xCC, 0x93, 0xE6, 0x84, 0xCE,
+	// Bytes 4840 - 487f
+	0xBF, 0xCC, 0x94, 0xE6, 0x84, 0xCF, 0x85, 0xCC,
+	0x88, 0xE6, 0x84, 0xCF, 0x85, 0xCC, 0x93, 0xE6,
+	0x84, 0xCF, 0x85, 0xCC, 0x94, 0xE6, 0x84, 0xCF,
+	0x89, 0xCC, 0x80, 0xE6, 0x84, 0xCF, 0x89, 0xCC,
+	0x81, 0xE6, 0x84, 0xCF, 0x89, 0xCC, 0x93, 0xE6,
+	0x84, 0xCF, 0x89, 0xCC, 0x94, 0xE6, 0x84, 0xCF,
+	0x89, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
+	0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
+	// Bytes 4880 - 48bf
+	0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
+	0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
+	0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
+	0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
+	0x94, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
+	0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
+	0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
+	0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
+	// Bytes 48c0 - 48ff
+	0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
+	0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
+	0x94, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
+	0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
+	0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
+	0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
+	0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
+	0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
+	// Bytes 4900 - 493f
+	0x94, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
+	0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
+	0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
+	0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
+	0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
+	0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
+	0x94, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
+	0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
+	// Bytes 4940 - 497f
+	0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
+	0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
+	0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
+	0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
+	0x94, 0xCD, 0x82, 0xE6, 0x86, 0xCF, 0x89, 0xCC,
+	0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCF, 0x89, 0xCC,
+	0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCF, 0x89, 0xCC,
+	0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCF, 0x89, 0xCC,
+	// Bytes 4980 - 49bf
+	0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCF, 0x89, 0xCC,
+	0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCF, 0x89, 0xCC,
+	0x94, 0xCD, 0x82, 0xE6, 0x42, 0xCC, 0x80, 0xE6,
+	0xE6, 0x42, 0xCC, 0x81, 0xE6, 0xE6, 0x42, 0xCC,
+	0x93, 0xE6, 0xE6, 0x44, 0xCC, 0x88, 0xCC, 0x81,
+	0xE6, 0xE6, 0x43, 0xE3, 0x82, 0x99, 0x08, 0x08,
+	0x43, 0xE3, 0x82, 0x9A, 0x08, 0x08, 0x46, 0xE0,
+	0xBD, 0xB1, 0xE0, 0xBD, 0xB2, 0x82, 0x81, 0x46,
+	// Bytes 49c0 - 49ff
+	0xE0, 0xBD, 0xB1, 0xE0, 0xBD, 0xB4, 0x84, 0x81,
+	0x46, 0xE0, 0xBD, 0xB1, 0xE0, 0xBE, 0x80, 0x82,
+	0x81,
+}
+
+// nfcValues: 2944 entries, 5888 bytes
+// Block 2 is the null block.
+var nfcValues = [2944]uint16{
+	// Block 0x0, offset 0x0
+	0x003c: 0x8800, 0x003d: 0x8800, 0x003e: 0x8800,
+	// Block 0x1, offset 0x40
+	0x0041: 0x8800, 0x0042: 0x8800, 0x0043: 0x8800, 0x0044: 0x8800, 0x0045: 0x8800,
+	0x0046: 0x8800, 0x0047: 0x8800, 0x0048: 0x8800, 0x0049: 0x8800, 0x004a: 0x8800, 0x004b: 0x8800,
+	0x004c: 0x8800, 0x004d: 0x8800, 0x004e: 0x8800, 0x004f: 0x8800, 0x0050: 0x8800,
+	0x0052: 0x8800, 0x0053: 0x8800, 0x0054: 0x8800, 0x0055: 0x8800, 0x0056: 0x8800, 0x0057: 0x8800,
+	0x0058: 0x8800, 0x0059: 0x8800, 0x005a: 0x8800,
+	0x0061: 0x8800, 0x0062: 0x8800, 0x0063: 0x8800,
+	0x0064: 0x8800, 0x0065: 0x8800, 0x0066: 0x8800, 0x0067: 0x8800, 0x0068: 0x8800, 0x0069: 0x8800,
+	0x006a: 0x8800, 0x006b: 0x8800, 0x006c: 0x8800, 0x006d: 0x8800, 0x006e: 0x8800, 0x006f: 0x8800,
+	0x0070: 0x8800, 0x0072: 0x8800, 0x0073: 0x8800, 0x0074: 0x8800, 0x0075: 0x8800,
+	0x0076: 0x8800, 0x0077: 0x8800, 0x0078: 0x8800, 0x0079: 0x8800, 0x007a: 0x8800,
+	// Block 0x2, offset 0x80
+	// Block 0x3, offset 0xc0
+	0x00c0: 0x2f59, 0x00c1: 0x2f5e, 0x00c2: 0x466e, 0x00c3: 0x2f63, 0x00c4: 0x467d, 0x00c5: 0x4682,
+	0x00c6: 0x8800, 0x00c7: 0x468c, 0x00c8: 0x2fcc, 0x00c9: 0x2fd1, 0x00ca: 0x4691, 0x00cb: 0x2fe5,
+	0x00cc: 0x3058, 0x00cd: 0x305d, 0x00ce: 0x3062, 0x00cf: 0x46a5, 0x00d1: 0x30ee,
+	0x00d2: 0x3111, 0x00d3: 0x3116, 0x00d4: 0x46af, 0x00d5: 0x46b4, 0x00d6: 0x46c3,
+	0x00d8: 0x8800, 0x00d9: 0x319d, 0x00da: 0x31a2, 0x00db: 0x31a7, 0x00dc: 0x46f5, 0x00dd: 0x321f,
+	0x00e0: 0x3265, 0x00e1: 0x326a, 0x00e2: 0x46ff, 0x00e3: 0x326f,
+	0x00e4: 0x470e, 0x00e5: 0x4713, 0x00e6: 0x8800, 0x00e7: 0x471d, 0x00e8: 0x32d8, 0x00e9: 0x32dd,
+	0x00ea: 0x4722, 0x00eb: 0x32f1, 0x00ec: 0x3369, 0x00ed: 0x336e, 0x00ee: 0x3373, 0x00ef: 0x4736,
+	0x00f1: 0x33ff, 0x00f2: 0x3422, 0x00f3: 0x3427, 0x00f4: 0x4740, 0x00f5: 0x4745,
+	0x00f6: 0x4754, 0x00f8: 0x8800, 0x00f9: 0x34b3, 0x00fa: 0x34b8, 0x00fb: 0x34bd,
+	0x00fc: 0x4786, 0x00fd: 0x353a, 0x00ff: 0x3553,
+	// Block 0x4, offset 0x100
+	0x0100: 0x2f68, 0x0101: 0x3274, 0x0102: 0x4673, 0x0103: 0x4704, 0x0104: 0x2f86, 0x0105: 0x3292,
+	0x0106: 0x2f9a, 0x0107: 0x32a6, 0x0108: 0x2f9f, 0x0109: 0x32ab, 0x010a: 0x2fa4, 0x010b: 0x32b0,
+	0x010c: 0x2fa9, 0x010d: 0x32b5, 0x010e: 0x2fb3, 0x010f: 0x32bf,
+	0x0112: 0x4696, 0x0113: 0x4727, 0x0114: 0x2fdb, 0x0115: 0x32e7, 0x0116: 0x2fe0, 0x0117: 0x32ec,
+	0x0118: 0x2ffe, 0x0119: 0x330a, 0x011a: 0x2fef, 0x011b: 0x32fb, 0x011c: 0x3017, 0x011d: 0x3323,
+	0x011e: 0x3021, 0x011f: 0x332d, 0x0120: 0x3026, 0x0121: 0x3332, 0x0122: 0x3030, 0x0123: 0x333c,
+	0x0124: 0x3035, 0x0125: 0x3341, 0x0128: 0x3067, 0x0129: 0x3378,
+	0x012a: 0x306c, 0x012b: 0x337d, 0x012c: 0x3071, 0x012d: 0x3382, 0x012e: 0x3094, 0x012f: 0x33a0,
+	0x0130: 0x3076, 0x0134: 0x309e, 0x0135: 0x33aa,
+	0x0136: 0x30b2, 0x0137: 0x33c3, 0x0139: 0x30bc, 0x013a: 0x33cd, 0x013b: 0x30c6,
+	0x013c: 0x33d7, 0x013d: 0x30c1, 0x013e: 0x33d2,
+	// Block 0x5, offset 0x140
+	0x0143: 0x30e9, 0x0144: 0x33fa, 0x0145: 0x3102,
+	0x0146: 0x3413, 0x0147: 0x30f8, 0x0148: 0x3409,
+	0x014c: 0x46b9, 0x014d: 0x474a, 0x014e: 0x311b, 0x014f: 0x342c, 0x0150: 0x3125, 0x0151: 0x3436,
+	0x0154: 0x3143, 0x0155: 0x3454, 0x0156: 0x315c, 0x0157: 0x346d,
+	0x0158: 0x314d, 0x0159: 0x345e, 0x015a: 0x46dc, 0x015b: 0x476d, 0x015c: 0x3166, 0x015d: 0x3477,
+	0x015e: 0x3175, 0x015f: 0x3486, 0x0160: 0x46e1, 0x0161: 0x4772, 0x0162: 0x318e, 0x0163: 0x34a4,
+	0x0164: 0x317f, 0x0165: 0x3495, 0x0168: 0x46eb, 0x0169: 0x477c,
+	0x016a: 0x46f0, 0x016b: 0x4781, 0x016c: 0x31ac, 0x016d: 0x34c2, 0x016e: 0x31b6, 0x016f: 0x34cc,
+	0x0170: 0x31bb, 0x0171: 0x34d1, 0x0172: 0x31d9, 0x0173: 0x34ef, 0x0174: 0x31fc, 0x0175: 0x3512,
+	0x0176: 0x3224, 0x0177: 0x353f, 0x0178: 0x3238, 0x0179: 0x3247, 0x017a: 0x3567, 0x017b: 0x3251,
+	0x017c: 0x3571, 0x017d: 0x3256, 0x017e: 0x3576, 0x017f: 0x8800,
+	// Block 0x6, offset 0x180
+	0x018d: 0x2f72, 0x018e: 0x327e, 0x018f: 0x3080, 0x0190: 0x338c, 0x0191: 0x312a,
+	0x0192: 0x343b, 0x0193: 0x31c0, 0x0194: 0x34d6, 0x0195: 0x39b9, 0x0196: 0x3b48, 0x0197: 0x39b2,
+	0x0198: 0x3b41, 0x0199: 0x39c0, 0x019a: 0x3b4f, 0x019b: 0x39ab, 0x019c: 0x3b3a,
+	0x019e: 0x389a, 0x019f: 0x3a29, 0x01a0: 0x3893, 0x01a1: 0x3a22, 0x01a2: 0x359d, 0x01a3: 0x35af,
+	0x01a6: 0x302b, 0x01a7: 0x3337, 0x01a8: 0x30a8, 0x01a9: 0x33b9,
+	0x01aa: 0x46d2, 0x01ab: 0x4763, 0x01ac: 0x397a, 0x01ad: 0x3b09, 0x01ae: 0x35c1, 0x01af: 0x35c7,
+	0x01b0: 0x33af, 0x01b4: 0x3012, 0x01b5: 0x331e,
+	0x01b8: 0x30e4, 0x01b9: 0x33f5, 0x01ba: 0x38a1, 0x01bb: 0x3a30,
+	0x01bc: 0x3597, 0x01bd: 0x35a9, 0x01be: 0x35a3, 0x01bf: 0x35b5,
+	// Block 0x7, offset 0x1c0
+	0x01c0: 0x2f77, 0x01c1: 0x3283, 0x01c2: 0x2f7c, 0x01c3: 0x3288, 0x01c4: 0x2ff4, 0x01c5: 0x3300,
+	0x01c6: 0x2ff9, 0x01c7: 0x3305, 0x01c8: 0x3085, 0x01c9: 0x3391, 0x01ca: 0x308a, 0x01cb: 0x3396,
+	0x01cc: 0x312f, 0x01cd: 0x3440, 0x01ce: 0x3134, 0x01cf: 0x3445, 0x01d0: 0x3152, 0x01d1: 0x3463,
+	0x01d2: 0x3157, 0x01d3: 0x3468, 0x01d4: 0x31c5, 0x01d5: 0x34db, 0x01d6: 0x31ca, 0x01d7: 0x34e0,
+	0x01d8: 0x3170, 0x01d9: 0x3481, 0x01da: 0x3189, 0x01db: 0x349f,
+	0x01de: 0x3044, 0x01df: 0x3350,
+	0x01e6: 0x4678, 0x01e7: 0x4709, 0x01e8: 0x46a0, 0x01e9: 0x4731,
+	0x01ea: 0x3949, 0x01eb: 0x3ad8, 0x01ec: 0x3926, 0x01ed: 0x3ab5, 0x01ee: 0x46be, 0x01ef: 0x474f,
+	0x01f0: 0x3942, 0x01f1: 0x3ad1, 0x01f2: 0x322e, 0x01f3: 0x3549,
+	// Block 0x8, offset 0x200
+	0x0200: 0x86e6, 0x0201: 0x86e6, 0x0202: 0x86e6, 0x0203: 0x86e6, 0x0204: 0x86e6, 0x0205: 0x80e6,
+	0x0206: 0x86e6, 0x0207: 0x86e6, 0x0208: 0x86e6, 0x0209: 0x86e6, 0x020a: 0x86e6, 0x020b: 0x86e6,
+	0x020c: 0x86e6, 0x020d: 0x80e6, 0x020e: 0x80e6, 0x020f: 0x86e6, 0x0210: 0x80e6, 0x0211: 0x86e6,
+	0x0212: 0x80e6, 0x0213: 0x86e6, 0x0214: 0x86e6, 0x0215: 0x80e8, 0x0216: 0x80dc, 0x0217: 0x80dc,
+	0x0218: 0x80dc, 0x0219: 0x80dc, 0x021a: 0x80e8, 0x021b: 0x86d8, 0x021c: 0x80dc, 0x021d: 0x80dc,
+	0x021e: 0x80dc, 0x021f: 0x80dc, 0x0220: 0x80dc, 0x0221: 0x80ca, 0x0222: 0x80ca, 0x0223: 0x86dc,
+	0x0224: 0x86dc, 0x0225: 0x86dc, 0x0226: 0x86dc, 0x0227: 0x86ca, 0x0228: 0x86ca, 0x0229: 0x80dc,
+	0x022a: 0x80dc, 0x022b: 0x80dc, 0x022c: 0x80dc, 0x022d: 0x86dc, 0x022e: 0x86dc, 0x022f: 0x80dc,
+	0x0230: 0x86dc, 0x0231: 0x86dc, 0x0232: 0x80dc, 0x0233: 0x80dc, 0x0234: 0x8001, 0x0235: 0x8001,
+	0x0236: 0x8001, 0x0237: 0x8001, 0x0238: 0x8601, 0x0239: 0x80dc, 0x023a: 0x80dc, 0x023b: 0x80dc,
+	0x023c: 0x80dc, 0x023d: 0x80e6, 0x023e: 0x80e6, 0x023f: 0x80e6,
+	// Block 0x9, offset 0x240
+	0x0240: 0x4994, 0x0241: 0x4999, 0x0242: 0x86e6, 0x0243: 0x499e, 0x0244: 0x49a3, 0x0245: 0x86f0,
+	0x0246: 0x80e6, 0x0247: 0x80dc, 0x0248: 0x80dc, 0x0249: 0x80dc, 0x024a: 0x80e6, 0x024b: 0x80e6,
+	0x024c: 0x80e6, 0x024d: 0x80dc, 0x024e: 0x80dc, 0x0250: 0x80e6, 0x0251: 0x80e6,
+	0x0252: 0x80e6, 0x0253: 0x80dc, 0x0254: 0x80dc, 0x0255: 0x80dc, 0x0256: 0x80dc, 0x0257: 0x80e6,
+	0x0258: 0x80e8, 0x0259: 0x80dc, 0x025a: 0x80dc, 0x025b: 0x80e6, 0x025c: 0x80e9, 0x025d: 0x80ea,
+	0x025e: 0x80ea, 0x025f: 0x80e9, 0x0260: 0x80ea, 0x0261: 0x80ea, 0x0262: 0x80e9, 0x0263: 0x80e6,
+	0x0264: 0x80e6, 0x0265: 0x80e6, 0x0266: 0x80e6, 0x0267: 0x80e6, 0x0268: 0x80e6, 0x0269: 0x80e6,
+	0x026a: 0x80e6, 0x026b: 0x80e6, 0x026c: 0x80e6, 0x026d: 0x80e6, 0x026e: 0x80e6, 0x026f: 0x80e6,
+	0x0274: 0x0170,
+	0x027e: 0x0037,
+	// Block 0xa, offset 0x280
+	0x0285: 0x358b,
+	0x0286: 0x35d3, 0x0287: 0x00d1, 0x0288: 0x35f1, 0x0289: 0x35fd, 0x028a: 0x360f,
+	0x028c: 0x362d, 0x028e: 0x363f, 0x028f: 0x365d, 0x0290: 0x3df2, 0x0291: 0x8800,
+	0x0295: 0x8800, 0x0297: 0x8800,
+	0x0299: 0x8800,
+	0x029f: 0x8800, 0x02a1: 0x8800,
+	0x02a5: 0x8800, 0x02a9: 0x8800,
+	0x02aa: 0x3621, 0x02ab: 0x3651, 0x02ac: 0x47e4, 0x02ad: 0x3681, 0x02ae: 0x480e, 0x02af: 0x3693,
+	0x02b0: 0x3e5a, 0x02b1: 0x8800, 0x02b5: 0x8800,
+	0x02b7: 0x8800, 0x02b9: 0x8800,
+	0x02bf: 0x8800,
+	// Block 0xb, offset 0x2c0
+	0x02c0: 0x370b, 0x02c1: 0x3717, 0x02c3: 0x3705,
+	0x02c6: 0x8800, 0x02c7: 0x36f3,
+	0x02cc: 0x3747, 0x02cd: 0x372f, 0x02ce: 0x3759, 0x02d0: 0x8800,
+	0x02d3: 0x8800, 0x02d5: 0x8800, 0x02d6: 0x8800, 0x02d7: 0x8800,
+	0x02d8: 0x8800, 0x02d9: 0x373b, 0x02da: 0x8800,
+	0x02de: 0x8800, 0x02e3: 0x8800,
+	0x02e7: 0x8800,
+	0x02eb: 0x8800, 0x02ed: 0x8800,
+	0x02f0: 0x8800, 0x02f3: 0x8800, 0x02f5: 0x8800,
+	0x02f6: 0x8800, 0x02f7: 0x8800, 0x02f8: 0x8800, 0x02f9: 0x37bf, 0x02fa: 0x8800,
+	0x02fe: 0x8800,
+	// Block 0xc, offset 0x300
+	0x0301: 0x371d, 0x0302: 0x37a1,
+	0x0310: 0x36f9, 0x0311: 0x377d,
+	0x0312: 0x36ff, 0x0313: 0x3783, 0x0316: 0x3711, 0x0317: 0x3795,
+	0x0318: 0x8800, 0x0319: 0x8800, 0x031a: 0x3813, 0x031b: 0x3819, 0x031c: 0x3723, 0x031d: 0x37a7,
+	0x031e: 0x3729, 0x031f: 0x37ad, 0x0322: 0x3735, 0x0323: 0x37b9,
+	0x0324: 0x3741, 0x0325: 0x37c5, 0x0326: 0x374d, 0x0327: 0x37d1, 0x0328: 0x8800, 0x0329: 0x8800,
+	0x032a: 0x381f, 0x032b: 0x3825, 0x032c: 0x3777, 0x032d: 0x37fb, 0x032e: 0x3753, 0x032f: 0x37d7,
+	0x0330: 0x375f, 0x0331: 0x37e3, 0x0332: 0x3765, 0x0333: 0x37e9, 0x0334: 0x376b, 0x0335: 0x37ef,
+	0x0338: 0x3771, 0x0339: 0x37f5,
+	// Block 0xd, offset 0x340
+	0x0351: 0x80dc,
+	0x0352: 0x80e6, 0x0353: 0x80e6, 0x0354: 0x80e6, 0x0355: 0x80e6, 0x0356: 0x80dc, 0x0357: 0x80e6,
+	0x0358: 0x80e6, 0x0359: 0x80e6, 0x035a: 0x80de, 0x035b: 0x80dc, 0x035c: 0x80e6, 0x035d: 0x80e6,
+	0x035e: 0x80e6, 0x035f: 0x80e6, 0x0360: 0x80e6, 0x0361: 0x80e6, 0x0362: 0x80dc, 0x0363: 0x80dc,
+	0x0364: 0x80dc, 0x0365: 0x80dc, 0x0366: 0x80dc, 0x0367: 0x80dc, 0x0368: 0x80e6, 0x0369: 0x80e6,
+	0x036a: 0x80dc, 0x036b: 0x80e6, 0x036c: 0x80e6, 0x036d: 0x80de, 0x036e: 0x80e4, 0x036f: 0x80e6,
+	0x0370: 0x800a, 0x0371: 0x800b, 0x0372: 0x800c, 0x0373: 0x800d, 0x0374: 0x800e, 0x0375: 0x800f,
+	0x0376: 0x8010, 0x0377: 0x8011, 0x0378: 0x8012, 0x0379: 0x8013, 0x037a: 0x8013, 0x037b: 0x8014,
+	0x037c: 0x8015, 0x037d: 0x8016, 0x037f: 0x8017,
+	// Block 0xe, offset 0x380
+	0x0388: 0x8800, 0x038a: 0x8800, 0x038b: 0x801b,
+	0x038c: 0x801c, 0x038d: 0x801d, 0x038e: 0x801e, 0x038f: 0x801f, 0x0390: 0x8020, 0x0391: 0x8021,
+	0x0392: 0x8022, 0x0393: 0x86e6, 0x0394: 0x86e6, 0x0395: 0x86dc, 0x0396: 0x80dc, 0x0397: 0x80e6,
+	0x0398: 0x80e6, 0x0399: 0x80e6, 0x039a: 0x80e6, 0x039b: 0x80e6, 0x039c: 0x80dc, 0x039d: 0x80e6,
+	0x039e: 0x80e6, 0x039f: 0x80dc,
+	0x03b0: 0x8023,
+	// Block 0xf, offset 0x3c0
+	0x03c5: 0x8800,
+	0x03c6: 0x1946, 0x03c7: 0x8800, 0x03c8: 0x194d, 0x03c9: 0x8800, 0x03ca: 0x1954, 0x03cb: 0x8800,
+	0x03cc: 0x195b, 0x03cd: 0x8800, 0x03ce: 0x1962, 0x03d1: 0x8800,
+	0x03d2: 0x1969,
+	0x03f4: 0x8007, 0x03f5: 0x8600,
+	0x03fa: 0x8800, 0x03fb: 0x1970,
+	0x03fc: 0x8800, 0x03fd: 0x1977, 0x03fe: 0x8800, 0x03ff: 0x8800,
+	// Block 0x10, offset 0x400
+	0x0400: 0x2f81, 0x0401: 0x328d, 0x0402: 0x2f8b, 0x0403: 0x3297, 0x0404: 0x2f90, 0x0405: 0x329c,
+	0x0406: 0x2f95, 0x0407: 0x32a1, 0x0408: 0x38b6, 0x0409: 0x3a45, 0x040a: 0x2fae, 0x040b: 0x32ba,
+	0x040c: 0x2fb8, 0x040d: 0x32c4, 0x040e: 0x2fc7, 0x040f: 0x32d3, 0x0410: 0x2fbd, 0x0411: 0x32c9,
+	0x0412: 0x2fc2, 0x0413: 0x32ce, 0x0414: 0x38d9, 0x0415: 0x3a68, 0x0416: 0x38e0, 0x0417: 0x3a6f,
+	0x0418: 0x3003, 0x0419: 0x330f, 0x041a: 0x3008, 0x041b: 0x3314, 0x041c: 0x38ee, 0x041d: 0x3a7d,
+	0x041e: 0x300d, 0x041f: 0x3319, 0x0420: 0x301c, 0x0421: 0x3328, 0x0422: 0x303a, 0x0423: 0x3346,
+	0x0424: 0x3049, 0x0425: 0x3355, 0x0426: 0x303f, 0x0427: 0x334b, 0x0428: 0x304e, 0x0429: 0x335a,
+	0x042a: 0x3053, 0x042b: 0x335f, 0x042c: 0x3099, 0x042d: 0x33a5, 0x042e: 0x38f5, 0x042f: 0x3a84,
+	0x0430: 0x30a3, 0x0431: 0x33b4, 0x0432: 0x30ad, 0x0433: 0x33be, 0x0434: 0x30b7, 0x0435: 0x33c8,
+	0x0436: 0x46aa, 0x0437: 0x473b, 0x0438: 0x38fc, 0x0439: 0x3a8b, 0x043a: 0x30d0, 0x043b: 0x33e1,
+	0x043c: 0x30cb, 0x043d: 0x33dc, 0x043e: 0x30d5, 0x043f: 0x33e6,
+	// Block 0x11, offset 0x440
+	0x0440: 0x30da, 0x0441: 0x33eb, 0x0442: 0x30df, 0x0443: 0x33f0, 0x0444: 0x30f3, 0x0445: 0x3404,
+	0x0446: 0x30fd, 0x0447: 0x340e, 0x0448: 0x310c, 0x0449: 0x341d, 0x044a: 0x3107, 0x044b: 0x3418,
+	0x044c: 0x391f, 0x044d: 0x3aae, 0x044e: 0x392d, 0x044f: 0x3abc, 0x0450: 0x3934, 0x0451: 0x3ac3,
+	0x0452: 0x393b, 0x0453: 0x3aca, 0x0454: 0x3139, 0x0455: 0x344a, 0x0456: 0x313e, 0x0457: 0x344f,
+	0x0458: 0x3148, 0x0459: 0x3459, 0x045a: 0x46d7, 0x045b: 0x4768, 0x045c: 0x3981, 0x045d: 0x3b10,
+	0x045e: 0x3161, 0x045f: 0x3472, 0x0460: 0x316b, 0x0461: 0x347c, 0x0462: 0x46e6, 0x0463: 0x4777,
+	0x0464: 0x3988, 0x0465: 0x3b17, 0x0466: 0x398f, 0x0467: 0x3b1e, 0x0468: 0x3996, 0x0469: 0x3b25,
+	0x046a: 0x317a, 0x046b: 0x348b, 0x046c: 0x3184, 0x046d: 0x349a, 0x046e: 0x3198, 0x046f: 0x34ae,
+	0x0470: 0x3193, 0x0471: 0x34a9, 0x0472: 0x31d4, 0x0473: 0x34ea, 0x0474: 0x31e3, 0x0475: 0x34f9,
+	0x0476: 0x31de, 0x0477: 0x34f4, 0x0478: 0x399d, 0x0479: 0x3b2c, 0x047a: 0x39a4, 0x047b: 0x3b33,
+	0x047c: 0x31e8, 0x047d: 0x34fe, 0x047e: 0x31ed, 0x047f: 0x3503,
+	// Block 0x12, offset 0x480
+	0x0480: 0x31f2, 0x0481: 0x3508, 0x0482: 0x31f7, 0x0483: 0x350d, 0x0484: 0x3206, 0x0485: 0x351c,
+	0x0486: 0x3201, 0x0487: 0x3517, 0x0488: 0x320b, 0x0489: 0x3526, 0x048a: 0x3210, 0x048b: 0x352b,
+	0x048c: 0x3215, 0x048d: 0x3530, 0x048e: 0x3233, 0x048f: 0x354e, 0x0490: 0x324c, 0x0491: 0x356c,
+	0x0492: 0x325b, 0x0493: 0x357b, 0x0494: 0x3260, 0x0495: 0x3580, 0x0496: 0x3364, 0x0497: 0x3490,
+	0x0498: 0x3521, 0x0499: 0x355d, 0x049b: 0x35bb,
+	0x04a0: 0x4687, 0x04a1: 0x4718, 0x04a2: 0x2f6d, 0x04a3: 0x3279,
+	0x04a4: 0x3862, 0x04a5: 0x39f1, 0x04a6: 0x385b, 0x04a7: 0x39ea, 0x04a8: 0x3870, 0x04a9: 0x39ff,
+	0x04aa: 0x3869, 0x04ab: 0x39f8, 0x04ac: 0x38a8, 0x04ad: 0x3a37, 0x04ae: 0x387e, 0x04af: 0x3a0d,
+	0x04b0: 0x3877, 0x04b1: 0x3a06, 0x04b2: 0x388c, 0x04b3: 0x3a1b, 0x04b4: 0x3885, 0x04b5: 0x3a14,
+	0x04b6: 0x38af, 0x04b7: 0x3a3e, 0x04b8: 0x469b, 0x04b9: 0x472c, 0x04ba: 0x2fea, 0x04bb: 0x32f6,
+	0x04bc: 0x2fd6, 0x04bd: 0x32e2, 0x04be: 0x38c4, 0x04bf: 0x3a53,
+	// Block 0x13, offset 0x4c0
+	0x04c0: 0x38bd, 0x04c1: 0x3a4c, 0x04c2: 0x38d2, 0x04c3: 0x3a61, 0x04c4: 0x38cb, 0x04c5: 0x3a5a,
+	0x04c6: 0x38e7, 0x04c7: 0x3a76, 0x04c8: 0x307b, 0x04c9: 0x3387, 0x04ca: 0x308f, 0x04cb: 0x339b,
+	0x04cc: 0x46cd, 0x04cd: 0x475e, 0x04ce: 0x3120, 0x04cf: 0x3431, 0x04d0: 0x390a, 0x04d1: 0x3a99,
+	0x04d2: 0x3903, 0x04d3: 0x3a92, 0x04d4: 0x3918, 0x04d5: 0x3aa7, 0x04d6: 0x3911, 0x04d7: 0x3aa0,
+	0x04d8: 0x3973, 0x04d9: 0x3b02, 0x04da: 0x3957, 0x04db: 0x3ae6, 0x04dc: 0x3950, 0x04dd: 0x3adf,
+	0x04de: 0x3965, 0x04df: 0x3af4, 0x04e0: 0x395e, 0x04e1: 0x3aed, 0x04e2: 0x396c, 0x04e3: 0x3afb,
+	0x04e4: 0x31cf, 0x04e5: 0x34e5, 0x04e6: 0x31b1, 0x04e7: 0x34c7, 0x04e8: 0x39ce, 0x04e9: 0x3b5d,
+	0x04ea: 0x39c7, 0x04eb: 0x3b56, 0x04ec: 0x39dc, 0x04ed: 0x3b6b, 0x04ee: 0x39d5, 0x04ef: 0x3b64,
+	0x04f0: 0x39e3, 0x04f1: 0x3b72, 0x04f2: 0x321a, 0x04f3: 0x3535, 0x04f4: 0x3242, 0x04f5: 0x3562,
+	0x04f6: 0x323d, 0x04f7: 0x3558, 0x04f8: 0x3229, 0x04f9: 0x3544,
+	// Block 0x14, offset 0x500
+	0x0500: 0x47ea, 0x0501: 0x47f0, 0x0502: 0x4904, 0x0503: 0x491c, 0x0504: 0x490c, 0x0505: 0x4924,
+	0x0506: 0x4914, 0x0507: 0x492c, 0x0508: 0x4790, 0x0509: 0x4796, 0x050a: 0x4874, 0x050b: 0x488c,
+	0x050c: 0x487c, 0x050d: 0x4894, 0x050e: 0x4884, 0x050f: 0x489c, 0x0510: 0x47fc, 0x0511: 0x4802,
+	0x0512: 0x3da2, 0x0513: 0x3db2, 0x0514: 0x3daa, 0x0515: 0x3dba,
+	0x0518: 0x479c, 0x0519: 0x47a2, 0x051a: 0x3cd2, 0x051b: 0x3ce2, 0x051c: 0x3cda, 0x051d: 0x3cea,
+	0x0520: 0x4814, 0x0521: 0x481a, 0x0522: 0x4934, 0x0523: 0x494c,
+	0x0524: 0x493c, 0x0525: 0x4954, 0x0526: 0x4944, 0x0527: 0x495c, 0x0528: 0x47a8, 0x0529: 0x47ae,
+	0x052a: 0x48a4, 0x052b: 0x48bc, 0x052c: 0x48ac, 0x052d: 0x48c4, 0x052e: 0x48b4, 0x052f: 0x48cc,
+	0x0530: 0x482c, 0x0531: 0x4832, 0x0532: 0x3e02, 0x0533: 0x3e1a, 0x0534: 0x3e0a, 0x0535: 0x3e22,
+	0x0536: 0x3e12, 0x0537: 0x3e2a, 0x0538: 0x47b4, 0x0539: 0x47ba, 0x053a: 0x3d02, 0x053b: 0x3d1a,
+	0x053c: 0x3d0a, 0x053d: 0x3d22, 0x053e: 0x3d12, 0x053f: 0x3d2a,
+	// Block 0x15, offset 0x540
+	0x0540: 0x4838, 0x0541: 0x483e, 0x0542: 0x3e32, 0x0543: 0x3e42, 0x0544: 0x3e3a, 0x0545: 0x3e4a,
+	0x0548: 0x47c0, 0x0549: 0x47c6, 0x054a: 0x3d32, 0x054b: 0x3d42,
+	0x054c: 0x3d3a, 0x054d: 0x3d4a, 0x0550: 0x484a, 0x0551: 0x4850,
+	0x0552: 0x3e6a, 0x0553: 0x3e82, 0x0554: 0x3e72, 0x0555: 0x3e8a, 0x0556: 0x3e7a, 0x0557: 0x3e92,
+	0x0559: 0x47cc, 0x055b: 0x3d52, 0x055d: 0x3d5a,
+	0x055f: 0x3d62, 0x0560: 0x4862, 0x0561: 0x4868, 0x0562: 0x4964, 0x0563: 0x497c,
+	0x0564: 0x496c, 0x0565: 0x4984, 0x0566: 0x4974, 0x0567: 0x498c, 0x0568: 0x47d2, 0x0569: 0x47d8,
+	0x056a: 0x48d4, 0x056b: 0x48ec, 0x056c: 0x48dc, 0x056d: 0x48f4, 0x056e: 0x48e4, 0x056f: 0x48fc,
+	0x0570: 0x47de, 0x0571: 0x4304, 0x0572: 0x367b, 0x0573: 0x430a, 0x0574: 0x4808, 0x0575: 0x4310,
+	0x0576: 0x368d, 0x0577: 0x4316, 0x0578: 0x36ab, 0x0579: 0x431c, 0x057a: 0x36c3, 0x057b: 0x4322,
+	0x057c: 0x4856, 0x057d: 0x4328,
+	// Block 0x16, offset 0x580
+	0x0580: 0x3d8a, 0x0581: 0x3d92, 0x0582: 0x416e, 0x0583: 0x418c, 0x0584: 0x4178, 0x0585: 0x4196,
+	0x0586: 0x4182, 0x0587: 0x41a0, 0x0588: 0x3cc2, 0x0589: 0x3cca, 0x058a: 0x40ba, 0x058b: 0x40d8,
+	0x058c: 0x40c4, 0x058d: 0x40e2, 0x058e: 0x40ce, 0x058f: 0x40ec, 0x0590: 0x3dd2, 0x0591: 0x3dda,
+	0x0592: 0x41aa, 0x0593: 0x41c8, 0x0594: 0x41b4, 0x0595: 0x41d2, 0x0596: 0x41be, 0x0597: 0x41dc,
+	0x0598: 0x3cf2, 0x0599: 0x3cfa, 0x059a: 0x40f6, 0x059b: 0x4114, 0x059c: 0x4100, 0x059d: 0x411e,
+	0x059e: 0x410a, 0x059f: 0x4128, 0x05a0: 0x3eaa, 0x05a1: 0x3eb2, 0x05a2: 0x41e6, 0x05a3: 0x4204,
+	0x05a4: 0x41f0, 0x05a5: 0x420e, 0x05a6: 0x41fa, 0x05a7: 0x4218, 0x05a8: 0x3d6a, 0x05a9: 0x3d72,
+	0x05aa: 0x4132, 0x05ab: 0x4150, 0x05ac: 0x413c, 0x05ad: 0x415a, 0x05ae: 0x4146, 0x05af: 0x4164,
+	0x05b0: 0x366f, 0x05b1: 0x3669, 0x05b2: 0x3d7a, 0x05b3: 0x3675, 0x05b4: 0x3d82,
+	0x05b6: 0x47f6, 0x05b7: 0x3d9a, 0x05b8: 0x35df, 0x05b9: 0x35d9, 0x05ba: 0x35cd, 0x05bb: 0x42d4,
+	0x05bc: 0x35e5, 0x05be: 0x01d3, 0x05bf: 0x8800,
+	// Block 0x17, offset 0x5c0
+	0x05c1: 0x3591, 0x05c2: 0x3dc2, 0x05c3: 0x3687, 0x05c4: 0x3dca,
+	0x05c6: 0x4820, 0x05c7: 0x3de2, 0x05c8: 0x35eb, 0x05c9: 0x42da, 0x05ca: 0x35f7, 0x05cb: 0x42e0,
+	0x05cc: 0x3603, 0x05cd: 0x3b79, 0x05ce: 0x3b80, 0x05cf: 0x3b87, 0x05d0: 0x369f, 0x05d1: 0x3699,
+	0x05d2: 0x3dea, 0x05d3: 0x44ca, 0x05d6: 0x36a5, 0x05d7: 0x3dfa,
+	0x05d8: 0x361b, 0x05d9: 0x3615, 0x05da: 0x3609, 0x05db: 0x42e6, 0x05dd: 0x3b8e,
+	0x05de: 0x3b95, 0x05df: 0x3b9c, 0x05e0: 0x36d5, 0x05e1: 0x36cf, 0x05e2: 0x3e52, 0x05e3: 0x44d2,
+	0x05e4: 0x36b7, 0x05e5: 0x36bd, 0x05e6: 0x36db, 0x05e7: 0x3e62, 0x05e8: 0x364b, 0x05e9: 0x3645,
+	0x05ea: 0x3639, 0x05eb: 0x42f2, 0x05ec: 0x3633, 0x05ed: 0x3585, 0x05ee: 0x42ce, 0x05ef: 0x0081,
+	0x05f2: 0x3e9a, 0x05f3: 0x36e1, 0x05f4: 0x3ea2,
+	0x05f6: 0x486e, 0x05f7: 0x3eba, 0x05f8: 0x3627, 0x05f9: 0x42ec, 0x05fa: 0x3657, 0x05fb: 0x42fe,
+	0x05fc: 0x3663, 0x05fd: 0x00ce, 0x05fe: 0x8800,
+	// Block 0x18, offset 0x600
+	0x0601: 0x3bf0, 0x0603: 0x8800, 0x0604: 0x3bf7, 0x0605: 0x8800,
+	0x0607: 0x3bfe, 0x0608: 0x8800, 0x0609: 0x3c05,
+	0x060d: 0x8800,
+	0x0620: 0x2f4f, 0x0621: 0x8800, 0x0622: 0x3c13,
+	0x0624: 0x8800, 0x0625: 0x8800,
+	0x062d: 0x3c0c, 0x062e: 0x2f4a, 0x062f: 0x2f54,
+	0x0630: 0x3c1a, 0x0631: 0x3c21, 0x0632: 0x8800, 0x0633: 0x8800, 0x0634: 0x3c28, 0x0635: 0x3c2f,
+	0x0636: 0x8800, 0x0637: 0x8800, 0x0638: 0x3c36, 0x0639: 0x3c3d, 0x063a: 0x8800, 0x063b: 0x8800,
+	0x063c: 0x8800, 0x063d: 0x8800,
+	// Block 0x19, offset 0x640
+	0x0640: 0x3c44, 0x0641: 0x3c4b, 0x0642: 0x8800, 0x0643: 0x8800, 0x0644: 0x3c60, 0x0645: 0x3c67,
+	0x0646: 0x8800, 0x0647: 0x8800, 0x0648: 0x3c6e, 0x0649: 0x3c75,
+	0x0651: 0x8800,
+	0x0652: 0x8800,
+	0x0662: 0x8800,
+	0x0668: 0x8800, 0x0669: 0x8800,
+	0x066b: 0x8800, 0x066c: 0x3c8a, 0x066d: 0x3c91, 0x066e: 0x3c98, 0x066f: 0x3c9f,
+	0x0672: 0x8800, 0x0673: 0x8800, 0x0674: 0x8800, 0x0675: 0x8800,
+	// Block 0x1a, offset 0x680
+	0x0686: 0x8800, 0x068b: 0x8800,
+	0x068c: 0x3ef2, 0x068d: 0x8800, 0x068e: 0x3efa, 0x068f: 0x8800, 0x0690: 0x3f02, 0x0691: 0x8800,
+	0x0692: 0x3f0a, 0x0693: 0x8800, 0x0694: 0x3f12, 0x0695: 0x8800, 0x0696: 0x3f1a, 0x0697: 0x8800,
+	0x0698: 0x3f22, 0x0699: 0x8800, 0x069a: 0x3f2a, 0x069b: 0x8800, 0x069c: 0x3f32, 0x069d: 0x8800,
+	0x069e: 0x3f3a, 0x069f: 0x8800, 0x06a0: 0x3f42, 0x06a1: 0x8800, 0x06a2: 0x3f4a,
+	0x06a4: 0x8800, 0x06a5: 0x3f52, 0x06a6: 0x8800, 0x06a7: 0x3f5a, 0x06a8: 0x8800, 0x06a9: 0x3f62,
+	0x06af: 0x8800,
+	0x06b0: 0x3f6a, 0x06b1: 0x3f72, 0x06b2: 0x8800, 0x06b3: 0x3f7a, 0x06b4: 0x3f82, 0x06b5: 0x8800,
+	0x06b6: 0x3f8a, 0x06b7: 0x3f92, 0x06b8: 0x8800, 0x06b9: 0x3f9a, 0x06ba: 0x3fa2, 0x06bb: 0x8800,
+	0x06bc: 0x3faa, 0x06bd: 0x3fb2,
+	// Block 0x1b, offset 0x6c0
+	0x06d4: 0x3eea,
+	0x06d9: 0x8608, 0x06da: 0x8608, 0x06dd: 0x8800,
+	0x06de: 0x3fba,
+	0x06e6: 0x8800,
+	0x06eb: 0x8800, 0x06ec: 0x3fca, 0x06ed: 0x8800, 0x06ee: 0x3fd2, 0x06ef: 0x8800,
+	0x06f0: 0x3fda, 0x06f1: 0x8800, 0x06f2: 0x3fe2, 0x06f3: 0x8800, 0x06f4: 0x3fea, 0x06f5: 0x8800,
+	0x06f6: 0x3ff2, 0x06f7: 0x8800, 0x06f8: 0x3ffa, 0x06f9: 0x8800, 0x06fa: 0x4002, 0x06fb: 0x8800,
+	0x06fc: 0x400a, 0x06fd: 0x8800, 0x06fe: 0x4012, 0x06ff: 0x8800,
+	// Block 0x1c, offset 0x700
+	0x0700: 0x401a, 0x0701: 0x8800, 0x0702: 0x4022, 0x0704: 0x8800, 0x0705: 0x402a,
+	0x0706: 0x8800, 0x0707: 0x4032, 0x0708: 0x8800, 0x0709: 0x403a,
+	0x070f: 0x8800, 0x0710: 0x4042, 0x0711: 0x404a,
+	0x0712: 0x8800, 0x0713: 0x4052, 0x0714: 0x405a, 0x0715: 0x8800, 0x0716: 0x4062, 0x0717: 0x406a,
+	0x0718: 0x8800, 0x0719: 0x4072, 0x071a: 0x407a, 0x071b: 0x8800, 0x071c: 0x4082, 0x071d: 0x408a,
+	0x072f: 0x8800,
+	0x0730: 0x8800, 0x0731: 0x8800, 0x0732: 0x8800, 0x0734: 0x3fc2,
+	0x0737: 0x4092, 0x0738: 0x409a, 0x0739: 0x40a2, 0x073a: 0x40aa,
+	0x073d: 0x8800, 0x073e: 0x40b2,
+	// Block 0x1d, offset 0x740
+	0x0740: 0x13e9, 0x0741: 0x0d6d, 0x0742: 0x1445, 0x0743: 0x1411, 0x0744: 0x0ec9, 0x0745: 0x075d,
+	0x0746: 0x0951, 0x0747: 0x1699, 0x0748: 0x1699, 0x0749: 0x0a7d, 0x074a: 0x14cd, 0x074b: 0x09b5,
+	0x074c: 0x0a79, 0x074d: 0x0c61, 0x074e: 0x1041, 0x074f: 0x11d1, 0x0750: 0x1309, 0x0751: 0x1345,
+	0x0752: 0x1379, 0x0753: 0x148d, 0x0754: 0x0de5, 0x0755: 0x0e71, 0x0756: 0x0f1d, 0x0757: 0x0fb5,
+	0x0758: 0x12d1, 0x0759: 0x14b5, 0x075a: 0x15e1, 0x075b: 0x0781, 0x075c: 0x0925, 0x075d: 0x0df9,
+	0x075e: 0x0f41, 0x075f: 0x1305, 0x0760: 0x1631, 0x0761: 0x0b25, 0x0762: 0x0ee9, 0x0763: 0x12f5,
+	0x0764: 0x1389, 0x0765: 0x0c95, 0x0766: 0x122d, 0x0767: 0x1351, 0x0768: 0x0b91, 0x0769: 0x0d81,
+	0x076a: 0x0e89, 0x076b: 0x0f8d, 0x076c: 0x1499, 0x076d: 0x07c1, 0x076e: 0x0859, 0x076f: 0x08c5,
+	0x0770: 0x0cfd, 0x0771: 0x0df1, 0x0772: 0x0f3d, 0x0773: 0x1061, 0x0774: 0x11e9, 0x0775: 0x12fd,
+	0x0776: 0x1315, 0x0777: 0x1439, 0x0778: 0x155d, 0x0779: 0x1611, 0x077a: 0x162d, 0x077b: 0x109d,
+	0x077c: 0x10dd, 0x077d: 0x1195, 0x077e: 0x12b5, 0x077f: 0x14e9,
+	// Block 0x1e, offset 0x780
+	0x0780: 0x1639, 0x0781: 0x13bd, 0x0782: 0x0a39, 0x0783: 0x0bad, 0x0784: 0x114d, 0x0785: 0x120d,
+	0x0786: 0x0f71, 0x0787: 0x10a5, 0x0788: 0x1409, 0x0789: 0x1555, 0x078a: 0x0a35, 0x078b: 0x0b01,
+	0x078c: 0x0de9, 0x078d: 0x0e9d, 0x078e: 0x0ed1, 0x078f: 0x1185, 0x0790: 0x11ad, 0x0791: 0x1515,
+	0x0792: 0x08c1, 0x0793: 0x1219, 0x0794: 0x0865, 0x0795: 0x0861, 0x0796: 0x1109, 0x0797: 0x1199,
+	0x0798: 0x12cd, 0x0799: 0x151d, 0x079a: 0x13d9, 0x079b: 0x0c99, 0x079c: 0x0de5, 0x079d: 0x13c9,
+	0x079e: 0x0769, 0x079f: 0x0ad5, 0x07a0: 0x0c05, 0x07a1: 0x0fa1, 0x07a2: 0x1021, 0x07a3: 0x08e5,
+	0x07a4: 0x10ad, 0x07a5: 0x07d1, 0x07a6: 0x0be9, 0x07a7: 0x0749, 0x07a8: 0x0e5d, 0x07a9: 0x0d15,
+	0x07aa: 0x1181, 0x07ab: 0x0939, 0x07ac: 0x0a25, 0x07ad: 0x106d, 0x07ae: 0x12d5, 0x07af: 0x13ad,
+	0x07b0: 0x0e29, 0x07b1: 0x1469, 0x07b2: 0x0e55, 0x07b3: 0x0ca9, 0x07b4: 0x128d, 0x07b5: 0x0cc9,
+	0x07b6: 0x101d, 0x07b7: 0x079d, 0x07b8: 0x0819, 0x07b9: 0x085d, 0x07ba: 0x0dc5, 0x07bb: 0x116d,
+	0x07bc: 0x1265, 0x07bd: 0x13b9, 0x07be: 0x14c9, 0x07bf: 0x08cd,
+	// Block 0x1f, offset 0x7c0
+	0x07c0: 0x0981, 0x07c1: 0x0a89, 0x07c2: 0x0ba1, 0x07c3: 0x0d31, 0x07c4: 0x0eed, 0x07c5: 0x10b1,
+	0x07c6: 0x1505, 0x07c7: 0x15e9, 0x07c8: 0x163d, 0x07c9: 0x1655, 0x07ca: 0x08a9, 0x07cb: 0x0d65,
+	0x07cc: 0x0e15, 0x07cd: 0x145d, 0x07ce: 0x0b6d, 0x07cf: 0x0c49, 0x07d0: 0x0c65, 0x07d1: 0x0cf5,
+	0x07d2: 0x0edd, 0x07d3: 0x0f29, 0x07d4: 0x0fd9, 0x07d5: 0x10fd, 0x07d6: 0x11a1, 0x07d7: 0x1205,
+	0x07d8: 0x144d, 0x07d9: 0x12dd, 0x07da: 0x1475, 0x07db: 0x14ed, 0x07dc: 0x0881, 0x07dd: 0x08ad,
+	0x07de: 0x0995, 0x07df: 0x0f19, 0x07e0: 0x1365, 0x07e1: 0x13ad, 0x07e2: 0x0b8d, 0x07e3: 0x0bfd,
+	0x07e4: 0x0cc1, 0x07e5: 0x0e21, 0x07e6: 0x1149, 0x07e7: 0x0f95, 0x07e8: 0x07ad, 0x07e9: 0x09f1,
+	0x07ea: 0x0ad5, 0x07eb: 0x0b39, 0x07ec: 0x0c09, 0x07ed: 0x0fb1, 0x07ee: 0x0fcd, 0x07ef: 0x11dd,
+	0x07f0: 0x11fd, 0x07f1: 0x14d1, 0x07f2: 0x1551, 0x07f3: 0x1561, 0x07f4: 0x159d, 0x07f5: 0x07c5,
+	0x07f6: 0x10f1, 0x07f7: 0x14bd, 0x07f8: 0x1539, 0x07f9: 0x0c21, 0x07fa: 0x0789, 0x07fb: 0x07e9,
+	0x07fc: 0x0ad9, 0x07fd: 0x0af9, 0x07fe: 0x0d21, 0x07ff: 0x0de5,
+	// Block 0x20, offset 0x800
+	0x0800: 0x0f35, 0x0801: 0x103d, 0x0802: 0x12e9, 0x0803: 0x1489, 0x0804: 0x1691, 0x0805: 0x0d55,
+	0x0806: 0x1511, 0x0807: 0x08a5, 0x0808: 0x0da1, 0x0809: 0x0dad, 0x080a: 0x0e81, 0x080b: 0x0eb9,
+	0x080c: 0x0fbd, 0x080d: 0x1019, 0x080e: 0x1099, 0x080f: 0x117d, 0x0810: 0x15a9, 0x0811: 0x0821,
+	0x0812: 0x0c75, 0x0813: 0x1521, 0x0814: 0x07d9, 0x0815: 0x0b1d, 0x0816: 0x0ea1, 0x0817: 0x1451,
+	0x0818: 0x0bd9, 0x0819: 0x0c29, 0x081a: 0x0db5, 0x081b: 0x0fa1, 0x081c: 0x1529, 0x081d: 0x0889,
+	0x081e: 0x0971, 0x081f: 0x0b09, 0x0820: 0x0d45, 0x0821: 0x0d91, 0x0822: 0x0dd1, 0x0823: 0x0e65,
+	0x0824: 0x0fb9, 0x0825: 0x102d, 0x0826: 0x11c9, 0x0827: 0x1369, 0x0828: 0x1375, 0x0829: 0x14c5,
+	0x082a: 0x1545, 0x082b: 0x08f5, 0x082c: 0x0ebd, 0x082d: 0x0975, 0x082e: 0x0f39, 0x082f: 0x0fdd,
+	0x0830: 0x12f9, 0x0831: 0x152d, 0x0832: 0x1619, 0x0833: 0x1641, 0x0834: 0x0da9, 0x0835: 0x0e99,
+	0x0836: 0x1235, 0x0837: 0x1129, 0x0838: 0x1135, 0x0839: 0x1159, 0x083a: 0x0f89, 0x083b: 0x0f11,
+	0x083c: 0x13d5, 0x083d: 0x07a5, 0x083e: 0x129d, 0x083f: 0x088d,
+	// Block 0x21, offset 0x840
+	0x0840: 0x087d, 0x0841: 0x0b7d, 0x0842: 0x0c9d, 0x0843: 0x1165, 0x0844: 0x0ac5, 0x0845: 0x0e75,
+	0x0846: 0x0d61, 0x0847: 0x1459, 0x0848: 0x1359, 0x0849: 0x1519, 0x084a: 0x1395, 0x084b: 0x0b99,
+	0x084c: 0x07f9, 0x084d: 0x09cd, 0x0850: 0x0a21,
+	0x0852: 0x0d51, 0x0855: 0x0869, 0x0856: 0x0f91, 0x0857: 0x1055,
+	0x0858: 0x10b9, 0x0859: 0x10d5, 0x085a: 0x10d9, 0x085b: 0x10ed, 0x085c: 0x1569, 0x085d: 0x115d,
+	0x085e: 0x11e1, 0x0860: 0x1301, 0x0862: 0x13c5,
+	0x0865: 0x1479, 0x0866: 0x14a5,
+	0x086a: 0x15bd, 0x086b: 0x15c1, 0x086c: 0x15c5, 0x086d: 0x1629, 0x086e: 0x149d, 0x086f: 0x1535,
+	0x0870: 0x07c9, 0x0871: 0x07ed, 0x0872: 0x0801, 0x0873: 0x08bd, 0x0874: 0x08c9, 0x0875: 0x0909,
+	0x0876: 0x09bd, 0x0877: 0x09d9, 0x0878: 0x09e1, 0x0879: 0x0a1d, 0x087a: 0x0a29, 0x087b: 0x0b05,
+	0x087c: 0x0b0d, 0x087d: 0x0c15, 0x087e: 0x0c3d, 0x087f: 0x0c45,
+	// Block 0x22, offset 0x880
+	0x0880: 0x0c5d, 0x0881: 0x0d09, 0x0882: 0x0d39, 0x0883: 0x0d59, 0x0884: 0x0dc9, 0x0885: 0x0e8d,
+	0x0886: 0x0ea9, 0x0887: 0x0ed9, 0x0888: 0x0f2d, 0x0889: 0x0f4d, 0x088a: 0x0fc1, 0x088b: 0x10a1,
+	0x088c: 0x10bd, 0x088d: 0x10c5, 0x088e: 0x10c1, 0x088f: 0x10c9, 0x0890: 0x10cd, 0x0891: 0x10d1,
+	0x0892: 0x10e5, 0x0893: 0x10e9, 0x0894: 0x110d, 0x0895: 0x1121, 0x0896: 0x113d, 0x0897: 0x11a1,
+	0x0898: 0x11a9, 0x0899: 0x11b1, 0x089a: 0x11c5, 0x089b: 0x11ed, 0x089c: 0x123d, 0x089d: 0x1271,
+	0x089e: 0x1271, 0x089f: 0x12d9, 0x08a0: 0x1381, 0x08a1: 0x1399, 0x08a2: 0x13cd, 0x08a3: 0x13d1,
+	0x08a4: 0x1415, 0x08a5: 0x1419, 0x08a6: 0x1471, 0x08a7: 0x1479, 0x08a8: 0x1549, 0x08a9: 0x158d,
+	0x08aa: 0x15a5, 0x08ab: 0x0c0d, 0x08ac: 0x1780, 0x08ad: 0x1255,
+	0x08b0: 0x0751, 0x08b1: 0x0855, 0x08b2: 0x0815, 0x08b3: 0x07bd, 0x08b4: 0x07fd, 0x08b5: 0x0829,
+	0x08b6: 0x08b9, 0x08b7: 0x08d5, 0x08b8: 0x09bd, 0x08b9: 0x09a9, 0x08ba: 0x09b9, 0x08bb: 0x09d5,
+	0x08bc: 0x0a21, 0x08bd: 0x0a31, 0x08be: 0x0a75, 0x08bf: 0x0a81,
+	// Block 0x23, offset 0x8c0
+	0x08c0: 0x0a9d, 0x08c1: 0x0aad, 0x08c2: 0x0b95, 0x08c3: 0x0b9d, 0x08c4: 0x0bcd, 0x08c5: 0x0bed,
+	0x08c6: 0x0c1d, 0x08c7: 0x0c35, 0x08c8: 0x0c25, 0x08c9: 0x0c45, 0x08ca: 0x0c39, 0x08cb: 0x0c5d,
+	0x08cc: 0x0c79, 0x08cd: 0x0cd1, 0x08ce: 0x0cdd, 0x08cf: 0x0ce5, 0x08d0: 0x0d0d, 0x08d1: 0x0d51,
+	0x08d2: 0x0d81, 0x08d3: 0x0d85, 0x08d4: 0x0d99, 0x08d5: 0x0e19, 0x08d6: 0x0e29, 0x08d7: 0x0e81,
+	0x08d8: 0x0ecd, 0x08d9: 0x0ec5, 0x08da: 0x0ed9, 0x08db: 0x0ef5, 0x08dc: 0x0f2d, 0x08dd: 0x1085,
+	0x08de: 0x0f51, 0x08df: 0x0f85, 0x08e0: 0x0f91, 0x08e1: 0x0fd1, 0x08e2: 0x0fed, 0x08e3: 0x1011,
+	0x08e4: 0x1035, 0x08e5: 0x1039, 0x08e6: 0x1055, 0x08e7: 0x1059, 0x08e8: 0x1069, 0x08e9: 0x107d,
+	0x08ea: 0x1079, 0x08eb: 0x10a9, 0x08ec: 0x1125, 0x08ed: 0x113d, 0x08ee: 0x1155, 0x08ef: 0x118d,
+	0x08f0: 0x11a1, 0x08f1: 0x11bd, 0x08f2: 0x11ed, 0x08f3: 0x12a1, 0x08f4: 0x12c9, 0x08f5: 0x133d,
+	0x08f6: 0x1385, 0x08f7: 0x1391, 0x08f8: 0x1399, 0x08f9: 0x13b1, 0x08fa: 0x13c5, 0x08fb: 0x13b5,
+	0x08fc: 0x13cd, 0x08fd: 0x13c9, 0x08fe: 0x13c1, 0x08ff: 0x13d1,
+	// Block 0x24, offset 0x900
+	0x0900: 0x13dd, 0x0901: 0x1419, 0x0902: 0x1455, 0x0903: 0x1485, 0x0904: 0x14b9, 0x0905: 0x14d9,
+	0x0906: 0x1525, 0x0907: 0x1549, 0x0908: 0x1569, 0x0909: 0x157d, 0x090a: 0x158d, 0x090b: 0x1599,
+	0x090c: 0x15a5, 0x090d: 0x15f9, 0x090e: 0x1699, 0x090f: 0x1717, 0x0910: 0x1712, 0x0911: 0x1744,
+	0x0912: 0x0679, 0x0913: 0x06a1, 0x0914: 0x06a5, 0x0915: 0x17c6, 0x0916: 0x17f3, 0x0917: 0x186b,
+	0x0918: 0x1685, 0x0919: 0x1695,
+	// Block 0x25, offset 0x940
+	0x0940: 0x076d, 0x0941: 0x0765, 0x0942: 0x0775, 0x0943: 0x16a9, 0x0944: 0x07b9, 0x0945: 0x07c9,
+	0x0946: 0x07cd, 0x0947: 0x07d5, 0x0948: 0x07dd, 0x0949: 0x07e1, 0x094a: 0x07ed, 0x094b: 0x07e5,
+	0x094c: 0x0625, 0x094d: 0x16bd, 0x094e: 0x0801, 0x094f: 0x0805, 0x0950: 0x0809, 0x0951: 0x0825,
+	0x0952: 0x16ae, 0x0953: 0x0629, 0x0954: 0x0811, 0x0955: 0x0831, 0x0956: 0x16b8, 0x0957: 0x0841,
+	0x0958: 0x0849, 0x0959: 0x07a9, 0x095a: 0x0851, 0x095b: 0x0855, 0x095c: 0x1893, 0x095d: 0x0871,
+	0x095e: 0x0879, 0x095f: 0x0631, 0x0960: 0x0891, 0x0961: 0x0895, 0x0962: 0x089d, 0x0963: 0x08a1,
+	0x0964: 0x0635, 0x0965: 0x08b9, 0x0966: 0x08bd, 0x0967: 0x08c9, 0x0968: 0x08d5, 0x0969: 0x08d9,
+	0x096a: 0x08dd, 0x096b: 0x08e5, 0x096c: 0x0905, 0x096d: 0x0909, 0x096e: 0x0911, 0x096f: 0x0921,
+	0x0970: 0x0929, 0x0971: 0x092d, 0x0972: 0x092d, 0x0973: 0x092d, 0x0974: 0x16cc, 0x0975: 0x0f05,
+	0x0976: 0x0941, 0x0977: 0x0949, 0x0978: 0x16d1, 0x0979: 0x0955, 0x097a: 0x095d, 0x097b: 0x0965,
+	0x097c: 0x098d, 0x097d: 0x0979, 0x097e: 0x0985, 0x097f: 0x0989,
+	// Block 0x26, offset 0x980
+	0x0980: 0x0991, 0x0981: 0x0999, 0x0982: 0x099d, 0x0983: 0x09a5, 0x0984: 0x09ad, 0x0985: 0x09b1,
+	0x0986: 0x09b1, 0x0987: 0x09b9, 0x0988: 0x09c1, 0x0989: 0x09c5, 0x098a: 0x09d1, 0x098b: 0x09f5,
+	0x098c: 0x09d9, 0x098d: 0x09f9, 0x098e: 0x09dd, 0x098f: 0x09e5, 0x0990: 0x087d, 0x0991: 0x0a41,
+	0x0992: 0x0a09, 0x0993: 0x0a0d, 0x0994: 0x0a11, 0x0995: 0x0a05, 0x0996: 0x0a19, 0x0997: 0x0a15,
+	0x0998: 0x0a2d, 0x0999: 0x16d6, 0x099a: 0x0a49, 0x099b: 0x0a4d, 0x099c: 0x0a55, 0x099d: 0x0a61,
+	0x099e: 0x0a69, 0x099f: 0x0a85, 0x09a0: 0x16db, 0x09a1: 0x16e0, 0x09a2: 0x0a91, 0x09a3: 0x0a95,
+	0x09a4: 0x0a99, 0x09a5: 0x0a8d, 0x09a6: 0x0aa1, 0x09a7: 0x0639, 0x09a8: 0x063d, 0x09a9: 0x0aa9,
+	0x09aa: 0x0ab1, 0x09ab: 0x0ab1, 0x09ac: 0x16e5, 0x09ad: 0x0acd, 0x09ae: 0x0ad1, 0x09af: 0x0ad5,
+	0x09b0: 0x0add, 0x09b1: 0x16ea, 0x09b2: 0x0ae5, 0x09b3: 0x0ae9, 0x09b4: 0x0bc1, 0x09b5: 0x0af1,
+	0x09b6: 0x0641, 0x09b7: 0x0afd, 0x09b8: 0x0b0d, 0x09b9: 0x0b19, 0x09ba: 0x0b15, 0x09bb: 0x16f4,
+	0x09bc: 0x0b21, 0x09bd: 0x16f9, 0x09be: 0x0b2d, 0x09bf: 0x0b29,
+	// Block 0x27, offset 0x9c0
+	0x09c0: 0x0b31, 0x09c1: 0x0b41, 0x09c2: 0x0b45, 0x09c3: 0x0645, 0x09c4: 0x0b55, 0x09c5: 0x0b5d,
+	0x09c6: 0x0b61, 0x09c7: 0x0b65, 0x09c8: 0x0649, 0x09c9: 0x16fe, 0x09ca: 0x064d, 0x09cb: 0x0b81,
+	0x09cc: 0x0b85, 0x09cd: 0x0b89, 0x09ce: 0x0b91, 0x09cf: 0x18c5, 0x09d0: 0x0ba9, 0x09d1: 0x1708,
+	0x09d2: 0x1708, 0x09d3: 0x1249, 0x09d4: 0x0bb9, 0x09d5: 0x0bb9, 0x09d6: 0x0651, 0x09d7: 0x172b,
+	0x09d8: 0x17fd, 0x09d9: 0x0bc9, 0x09da: 0x0bd1, 0x09db: 0x0655, 0x09dc: 0x0be5, 0x09dd: 0x0bf5,
+	0x09de: 0x0bf9, 0x09df: 0x0c01, 0x09e0: 0x0c11, 0x09e1: 0x065d, 0x09e2: 0x0659, 0x09e3: 0x0c15,
+	0x09e4: 0x170d, 0x09e5: 0x0c19, 0x09e6: 0x0c2d, 0x09e7: 0x0c31, 0x09e8: 0x0c35, 0x09e9: 0x0c31,
+	0x09ea: 0x0c41, 0x09eb: 0x0c45, 0x09ec: 0x0c55, 0x09ed: 0x0c4d, 0x09ee: 0x0c51, 0x09ef: 0x0c59,
+	0x09f0: 0x0c5d, 0x09f1: 0x0c61, 0x09f2: 0x0c6d, 0x09f3: 0x0c71, 0x09f4: 0x0c89, 0x09f5: 0x0c91,
+	0x09f6: 0x0ca1, 0x09f7: 0x0cb5, 0x09f8: 0x171c, 0x09f9: 0x0cb1, 0x09fa: 0x0ca5, 0x09fb: 0x0cbd,
+	0x09fc: 0x0cc5, 0x09fd: 0x0cd9, 0x09fe: 0x1721, 0x09ff: 0x0ce1,
+	// Block 0x28, offset 0xa00
+	0x0a00: 0x0cd5, 0x0a01: 0x0ccd, 0x0a02: 0x0661, 0x0a03: 0x0ce9, 0x0a04: 0x0cf1, 0x0a05: 0x0cf9,
+	0x0a06: 0x0ced, 0x0a07: 0x0665, 0x0a08: 0x0d09, 0x0a09: 0x0d11, 0x0a0a: 0x1726, 0x0a0b: 0x0d3d,
+	0x0a0c: 0x0d71, 0x0a0d: 0x0d4d, 0x0a0e: 0x0671, 0x0a0f: 0x0d59, 0x0a10: 0x066d, 0x0a11: 0x0669,
+	0x0a12: 0x0835, 0x0a13: 0x0839, 0x0a14: 0x0d75, 0x0a15: 0x0d5d, 0x0a16: 0x121d, 0x0a17: 0x06d5,
+	0x0a18: 0x0d81, 0x0a19: 0x0d85, 0x0a1a: 0x0d89, 0x0a1b: 0x0d9d, 0x0a1c: 0x0d95, 0x0a1d: 0x173f,
+	0x0a1e: 0x0675, 0x0a1f: 0x0db1, 0x0a20: 0x0da5, 0x0a21: 0x0dc1, 0x0a22: 0x0dc9, 0x0a23: 0x1749,
+	0x0a24: 0x0dcd, 0x0a25: 0x0db9, 0x0a26: 0x0dd5, 0x0a27: 0x0679, 0x0a28: 0x0dd9, 0x0a29: 0x0ddd,
+	0x0a2a: 0x0de1, 0x0a2b: 0x0ded, 0x0a2c: 0x174e, 0x0a2d: 0x0df5, 0x0a2e: 0x067d, 0x0a2f: 0x0e01,
+	0x0a30: 0x1753, 0x0a31: 0x0e05, 0x0a32: 0x0681, 0x0a33: 0x0e11, 0x0a34: 0x0e1d, 0x0a35: 0x0e29,
+	0x0a36: 0x0e2d, 0x0a37: 0x1758, 0x0a38: 0x16ef, 0x0a39: 0x175d, 0x0a3a: 0x0e4d, 0x0a3b: 0x1762,
+	0x0a3c: 0x0e59, 0x0a3d: 0x0e61, 0x0a3e: 0x0e51, 0x0a3f: 0x0e6d,
+	// Block 0x29, offset 0xa40
+	0x0a40: 0x0e7d, 0x0a41: 0x0e8d, 0x0a42: 0x0e81, 0x0a43: 0x0e85, 0x0a44: 0x0e91, 0x0a45: 0x0e95,
+	0x0a46: 0x1767, 0x0a47: 0x0e79, 0x0a48: 0x0ead, 0x0a49: 0x0eb1, 0x0a4a: 0x0685, 0x0a4b: 0x0ec5,
+	0x0a4c: 0x0ec1, 0x0a4d: 0x176c, 0x0a4e: 0x0ea5, 0x0a4f: 0x0ee1, 0x0a50: 0x1771, 0x0a51: 0x1776,
+	0x0a52: 0x0ee5, 0x0a53: 0x0ef9, 0x0a54: 0x0ef5, 0x0a55: 0x0ef1, 0x0a56: 0x0689, 0x0a57: 0x0efd,
+	0x0a58: 0x0f0d, 0x0a59: 0x0f09, 0x0a5a: 0x0f15, 0x0a5b: 0x16b3, 0x0a5c: 0x0f25, 0x0a5d: 0x177b,
+	0x0a5e: 0x0f31, 0x0a5f: 0x1785, 0x0a60: 0x0f45, 0x0a61: 0x0f51, 0x0a62: 0x0f65, 0x0a63: 0x178a,
+	0x0a64: 0x0f79, 0x0a65: 0x0f7d, 0x0a66: 0x178f, 0x0a67: 0x1794, 0x0a68: 0x0f99, 0x0a69: 0x0fa9,
+	0x0a6a: 0x068d, 0x0a6b: 0x0fad, 0x0a6c: 0x0691, 0x0a6d: 0x0691, 0x0a6e: 0x0fc5, 0x0a6f: 0x0fc9,
+	0x0a70: 0x0fd1, 0x0a71: 0x0fd5, 0x0a72: 0x0fe1, 0x0a73: 0x0695, 0x0a74: 0x0ff9, 0x0a75: 0x1799,
+	0x0a76: 0x1015, 0x0a77: 0x179e, 0x0a78: 0x1021, 0x0a79: 0x1703, 0x0a7a: 0x1031, 0x0a7b: 0x17a3,
+	0x0a7c: 0x17a8, 0x0a7d: 0x17ad, 0x0a7e: 0x0699, 0x0a7f: 0x069d,
+	// Block 0x2a, offset 0xa80
+	0x0a80: 0x1069, 0x0a81: 0x17b7, 0x0a82: 0x17b2, 0x0a83: 0x17bc, 0x0a84: 0x17c1, 0x0a85: 0x1071,
+	0x0a86: 0x1075, 0x0a87: 0x1075, 0x0a88: 0x107d, 0x0a89: 0x06a5, 0x0a8a: 0x1081, 0x0a8b: 0x06a9,
+	0x0a8c: 0x06ad, 0x0a8d: 0x17cb, 0x0a8e: 0x1095, 0x0a8f: 0x109d, 0x0a90: 0x10a9, 0x0a91: 0x06b1,
+	0x0a92: 0x17d0, 0x0a93: 0x10cd, 0x0a94: 0x17d5, 0x0a95: 0x17da, 0x0a96: 0x10ed, 0x0a97: 0x1105,
+	0x0a98: 0x06b5, 0x0a99: 0x110d, 0x0a9a: 0x1111, 0x0a9b: 0x1115, 0x0a9c: 0x17df, 0x0a9d: 0x17e4,
+	0x0a9e: 0x17e4, 0x0a9f: 0x112d, 0x0aa0: 0x06b9, 0x0aa1: 0x17e9, 0x0aa2: 0x1141, 0x0aa3: 0x1145,
+	0x0aa4: 0x06bd, 0x0aa5: 0x17ee, 0x0aa6: 0x1161, 0x0aa7: 0x06c1, 0x0aa8: 0x1171, 0x0aa9: 0x1169,
+	0x0aaa: 0x1179, 0x0aab: 0x17f8, 0x0aac: 0x1191, 0x0aad: 0x06c5, 0x0aae: 0x119d, 0x0aaf: 0x11a5,
+	0x0ab0: 0x11b5, 0x0ab1: 0x06c9, 0x0ab2: 0x1802, 0x0ab3: 0x1807, 0x0ab4: 0x06cd, 0x0ab5: 0x180c,
+	0x0ab6: 0x11cd, 0x0ab7: 0x1811, 0x0ab8: 0x11d9, 0x0ab9: 0x11e5, 0x0aba: 0x11ed, 0x0abb: 0x1816,
+	0x0abc: 0x181b, 0x0abd: 0x1201, 0x0abe: 0x1820, 0x0abf: 0x1209,
+	// Block 0x2b, offset 0xac0
+	0x0ac0: 0x1730, 0x0ac1: 0x06d1, 0x0ac2: 0x1221, 0x0ac3: 0x1225, 0x0ac4: 0x06d9, 0x0ac5: 0x1229,
+	0x0ac6: 0x0aa5, 0x0ac7: 0x1825, 0x0ac8: 0x182a, 0x0ac9: 0x1735, 0x0aca: 0x173a, 0x0acb: 0x1249,
+	0x0acc: 0x124d, 0x0acd: 0x1465, 0x0ace: 0x06dd, 0x0acf: 0x1279, 0x0ad0: 0x1275, 0x0ad1: 0x127d,
+	0x0ad2: 0x08b1, 0x0ad3: 0x1281, 0x0ad4: 0x1285, 0x0ad5: 0x1289, 0x0ad6: 0x1291, 0x0ad7: 0x182f,
+	0x0ad8: 0x128d, 0x0ad9: 0x1295, 0x0ada: 0x12a9, 0x0adb: 0x12ad, 0x0adc: 0x1299, 0x0add: 0x12b1,
+	0x0ade: 0x12c5, 0x0adf: 0x12d9, 0x0ae0: 0x12a5, 0x0ae1: 0x12b9, 0x0ae2: 0x12bd, 0x0ae3: 0x12c1,
+	0x0ae4: 0x1834, 0x0ae5: 0x183e, 0x0ae6: 0x1839, 0x0ae7: 0x06e1, 0x0ae8: 0x12e1, 0x0ae9: 0x12e5,
+	0x0aea: 0x12ed, 0x0aeb: 0x1852, 0x0aec: 0x12f1, 0x0aed: 0x1843, 0x0aee: 0x06e5, 0x0aef: 0x06e9,
+	0x0af0: 0x1848, 0x0af1: 0x184d, 0x0af2: 0x06ed, 0x0af3: 0x1311, 0x0af4: 0x1315, 0x0af5: 0x1319,
+	0x0af6: 0x131d, 0x0af7: 0x1329, 0x0af8: 0x1325, 0x0af9: 0x1331, 0x0afa: 0x132d, 0x0afb: 0x133d,
+	0x0afc: 0x1335, 0x0afd: 0x1339, 0x0afe: 0x1341, 0x0aff: 0x06f1,
+	// Block 0x2c, offset 0xb00
+	0x0b00: 0x1349, 0x0b01: 0x134d, 0x0b02: 0x06f5, 0x0b03: 0x135d, 0x0b04: 0x1361, 0x0b05: 0x1857,
+	0x0b06: 0x136d, 0x0b07: 0x1371, 0x0b08: 0x06f9, 0x0b09: 0x137d, 0x0b0a: 0x062d, 0x0b0b: 0x185c,
+	0x0b0c: 0x1861, 0x0b0d: 0x06fd, 0x0b0e: 0x0701, 0x0b0f: 0x13a9, 0x0b10: 0x13c1, 0x0b11: 0x13dd,
+	0x0b12: 0x13ed, 0x0b13: 0x1866, 0x0b14: 0x1401, 0x0b15: 0x1405, 0x0b16: 0x141d, 0x0b17: 0x1429,
+	0x0b18: 0x1870, 0x0b19: 0x16c2, 0x0b1a: 0x1435, 0x0b1b: 0x1431, 0x0b1c: 0x143d, 0x0b1d: 0x16c7,
+	0x0b1e: 0x1449, 0x0b1f: 0x1455, 0x0b20: 0x1875, 0x0b21: 0x187a, 0x0b22: 0x1495, 0x0b23: 0x14a1,
+	0x0b24: 0x14a9, 0x0b25: 0x187f, 0x0b26: 0x14ad, 0x0b27: 0x14d5, 0x0b28: 0x14e1, 0x0b29: 0x14e5,
+	0x0b2a: 0x14dd, 0x0b2b: 0x14f1, 0x0b2c: 0x14f5, 0x0b2d: 0x1884, 0x0b2e: 0x1501, 0x0b2f: 0x0705,
+	0x0b30: 0x1509, 0x0b31: 0x1889, 0x0b32: 0x0709, 0x0b33: 0x1541, 0x0b34: 0x0b35, 0x0b35: 0x1559,
+	0x0b36: 0x188e, 0x0b37: 0x1898, 0x0b38: 0x070d, 0x0b39: 0x0711, 0x0b3a: 0x1581, 0x0b3b: 0x189d,
+	0x0b3c: 0x0715, 0x0b3d: 0x18a2, 0x0b3e: 0x1599, 0x0b3f: 0x1599,
+	// Block 0x2d, offset 0xb40
+	0x0b40: 0x15a1, 0x0b41: 0x18a7, 0x0b42: 0x15b9, 0x0b43: 0x0719, 0x0b44: 0x15c9, 0x0b45: 0x15d5,
+	0x0b46: 0x15dd, 0x0b47: 0x15e5, 0x0b48: 0x071d, 0x0b49: 0x18ac, 0x0b4a: 0x15f9, 0x0b4b: 0x1615,
+	0x0b4c: 0x1621, 0x0b4d: 0x0721, 0x0b4e: 0x0725, 0x0b4f: 0x1625, 0x0b50: 0x18b1, 0x0b51: 0x0729,
+	0x0b52: 0x18b6, 0x0b53: 0x18bb, 0x0b54: 0x18c0, 0x0b55: 0x1649, 0x0b56: 0x072d, 0x0b57: 0x165d,
+	0x0b58: 0x1665, 0x0b59: 0x1669, 0x0b5a: 0x1671, 0x0b5b: 0x1679, 0x0b5c: 0x1681, 0x0b5d: 0x18ca,
+}
+
+// nfcSparseOffset: 98 entries, 196 bytes
+var nfcSparseOffset = []uint16{0x0, 0x2, 0x6, 0x8, 0x13, 0x23, 0x25, 0x2a, 0x35, 0x44, 0x51, 0x59, 0x5d, 0x62, 0x64, 0x73, 0x7b, 0x82, 0x85, 0x8d, 0x91, 0x95, 0x97, 0x99, 0xa2, 0xa6, 0xad, 0xb2, 0xb5, 0xbf, 0xc1, 0xc8, 0xd0, 0xd3, 0xd5, 0xd7, 0xd9, 0xde, 0xed, 0xf9, 0xfb, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10b, 0x10d, 0x110, 0x113, 0x115, 0x118, 0x11b, 0x11f, 0x128, 0x12a, 0x12d, 0x12f, 0x139, 0x148, 0x14a, 0x158, 0x15b, 0x161, 0x167, 0x172, 0x176, 0x178, 0x17a, 0x17c, 0x17e, 0x180, 0x186, 0x189, 0x18b, 0x18d, 0x18f, 0x192, 0x194, 0x196, 0x198, 0x19a, 0x1a0, 0x1a3, 0x1a5, 0x1a7, 0x1a9, 0x1b7, 0x1c0, 0x1c2, 0x1c4, 0x1ca, 0x1d2, 0x1d9, 0x1dc, 0x1e9, 0x1f3, 0x1f5}
+
+// nfcSparseValues: 503 entries, 2012 bytes
+var nfcSparseValues = [503]valueRange{
+	// Block 0x0, offset 0x1
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8800, lo: 0xa8, hi: 0xa8},
+	// Block 0x1, offset 0x2
+	{value: 0x0091, lo: 0x03},
+	{value: 0x46c8, lo: 0xa0, hi: 0xa1},
+	{value: 0x46fa, lo: 0xaf, hi: 0xb0},
+	{value: 0x8800, lo: 0xb7, hi: 0xb7},
+	// Block 0x2, offset 0x3
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	// Block 0x3, offset 0x4
+	{value: 0x0006, lo: 0x0a},
+	{value: 0x8800, lo: 0x81, hi: 0x81},
+	{value: 0x8800, lo: 0x85, hi: 0x85},
+	{value: 0x8800, lo: 0x89, hi: 0x89},
+	{value: 0x4826, lo: 0x8a, hi: 0x8a},
+	{value: 0x4844, lo: 0x8b, hi: 0x8b},
+	{value: 0x36b1, lo: 0x8c, hi: 0x8c},
+	{value: 0x36c9, lo: 0x8d, hi: 0x8d},
+	{value: 0x485c, lo: 0x8e, hi: 0x8e},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	{value: 0x36e7, lo: 0x93, hi: 0x94},
+	// Block 0x4, offset 0x5
+	{value: 0x0000, lo: 0x0f},
+	{value: 0x8800, lo: 0x83, hi: 0x83},
+	{value: 0x8800, lo: 0x87, hi: 0x87},
+	{value: 0x8800, lo: 0x8b, hi: 0x8b},
+	{value: 0x8800, lo: 0x8d, hi: 0x8d},
+	{value: 0x378f, lo: 0x90, hi: 0x90},
+	{value: 0x379b, lo: 0x91, hi: 0x91},
+	{value: 0x3789, lo: 0x93, hi: 0x93},
+	{value: 0x8800, lo: 0x96, hi: 0x96},
+	{value: 0x3801, lo: 0x97, hi: 0x97},
+	{value: 0x37cb, lo: 0x9c, hi: 0x9c},
+	{value: 0x37b3, lo: 0x9d, hi: 0x9d},
+	{value: 0x37dd, lo: 0x9e, hi: 0x9e},
+	{value: 0x8800, lo: 0xb4, hi: 0xb5},
+	{value: 0x3807, lo: 0xb6, hi: 0xb6},
+	{value: 0x380d, lo: 0xb7, hi: 0xb7},
+	// Block 0x5, offset 0x6
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0x83, hi: 0x87},
+	// Block 0x6, offset 0x7
+	{value: 0x0001, lo: 0x04},
+	{value: 0x8018, lo: 0x81, hi: 0x82},
+	{value: 0x80e6, lo: 0x84, hi: 0x84},
+	{value: 0x80dc, lo: 0x85, hi: 0x85},
+	{value: 0x8012, lo: 0x87, hi: 0x87},
+	// Block 0x7, offset 0x8
+	{value: 0x0000, lo: 0x0a},
+	{value: 0x80e6, lo: 0x90, hi: 0x97},
+	{value: 0x801e, lo: 0x98, hi: 0x98},
+	{value: 0x801f, lo: 0x99, hi: 0x99},
+	{value: 0x8020, lo: 0x9a, hi: 0x9a},
+	{value: 0x382b, lo: 0xa2, hi: 0xa2},
+	{value: 0x3831, lo: 0xa3, hi: 0xa3},
+	{value: 0x383d, lo: 0xa4, hi: 0xa4},
+	{value: 0x3837, lo: 0xa5, hi: 0xa5},
+	{value: 0x3843, lo: 0xa6, hi: 0xa6},
+	{value: 0x8800, lo: 0xa7, hi: 0xa7},
+	// Block 0x8, offset 0x9
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x3855, lo: 0x80, hi: 0x80},
+	{value: 0x8800, lo: 0x81, hi: 0x81},
+	{value: 0x3849, lo: 0x82, hi: 0x82},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	{value: 0x384f, lo: 0x93, hi: 0x93},
+	{value: 0x8800, lo: 0x95, hi: 0x95},
+	{value: 0x80e6, lo: 0x96, hi: 0x9c},
+	{value: 0x80e6, lo: 0x9f, hi: 0xa2},
+	{value: 0x80dc, lo: 0xa3, hi: 0xa3},
+	{value: 0x80e6, lo: 0xa4, hi: 0xa4},
+	{value: 0x80e6, lo: 0xa7, hi: 0xa8},
+	{value: 0x80dc, lo: 0xaa, hi: 0xaa},
+	{value: 0x80e6, lo: 0xab, hi: 0xac},
+	{value: 0x80dc, lo: 0xad, hi: 0xad},
+	// Block 0x9, offset 0xa
+	{value: 0x0000, lo: 0x0c},
+	{value: 0x8024, lo: 0x91, hi: 0x91},
+	{value: 0x80e6, lo: 0xb0, hi: 0xb0},
+	{value: 0x80dc, lo: 0xb1, hi: 0xb1},
+	{value: 0x80e6, lo: 0xb2, hi: 0xb3},
+	{value: 0x80dc, lo: 0xb4, hi: 0xb4},
+	{value: 0x80e6, lo: 0xb5, hi: 0xb6},
+	{value: 0x80dc, lo: 0xb7, hi: 0xb9},
+	{value: 0x80e6, lo: 0xba, hi: 0xba},
+	{value: 0x80dc, lo: 0xbb, hi: 0xbc},
+	{value: 0x80e6, lo: 0xbd, hi: 0xbd},
+	{value: 0x80dc, lo: 0xbe, hi: 0xbe},
+	{value: 0x80e6, lo: 0xbf, hi: 0xbf},
+	// Block 0xa, offset 0xb
+	{value: 0x000a, lo: 0x07},
+	{value: 0x80e6, lo: 0x80, hi: 0x80},
+	{value: 0x80e6, lo: 0x81, hi: 0x81},
+	{value: 0x80dc, lo: 0x82, hi: 0x83},
+	{value: 0x80dc, lo: 0x84, hi: 0x85},
+	{value: 0x80dc, lo: 0x86, hi: 0x87},
+	{value: 0x80dc, lo: 0x88, hi: 0x89},
+	{value: 0x80e6, lo: 0x8a, hi: 0x8a},
+	// Block 0xb, offset 0xc
+	{value: 0x0000, lo: 0x03},
+	{value: 0x80e6, lo: 0xab, hi: 0xb1},
+	{value: 0x80dc, lo: 0xb2, hi: 0xb2},
+	{value: 0x80e6, lo: 0xb3, hi: 0xb3},
+	// Block 0xc, offset 0xd
+	{value: 0x0000, lo: 0x04},
+	{value: 0x80e6, lo: 0x96, hi: 0x99},
+	{value: 0x80e6, lo: 0x9b, hi: 0xa3},
+	{value: 0x80e6, lo: 0xa5, hi: 0xa7},
+	{value: 0x80e6, lo: 0xa9, hi: 0xad},
+	// Block 0xd, offset 0xe
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80dc, lo: 0x99, hi: 0x9b},
+	// Block 0xe, offset 0xf
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x80e6, lo: 0xa4, hi: 0xa5},
+	{value: 0x80dc, lo: 0xa6, hi: 0xa6},
+	{value: 0x80e6, lo: 0xa7, hi: 0xa8},
+	{value: 0x80dc, lo: 0xa9, hi: 0xa9},
+	{value: 0x80e6, lo: 0xaa, hi: 0xac},
+	{value: 0x80dc, lo: 0xad, hi: 0xaf},
+	{value: 0x801b, lo: 0xb0, hi: 0xb0},
+	{value: 0x801c, lo: 0xb1, hi: 0xb1},
+	{value: 0x801d, lo: 0xb2, hi: 0xb2},
+	{value: 0x80e6, lo: 0xb3, hi: 0xb5},
+	{value: 0x80dc, lo: 0xb6, hi: 0xb6},
+	{value: 0x80e6, lo: 0xb7, hi: 0xb8},
+	{value: 0x80dc, lo: 0xb9, hi: 0xba},
+	{value: 0x80e6, lo: 0xbb, hi: 0xbe},
+	// Block 0xf, offset 0x10
+	{value: 0x0000, lo: 0x07},
+	{value: 0x8800, lo: 0xa8, hi: 0xa8},
+	{value: 0x3ec2, lo: 0xa9, hi: 0xa9},
+	{value: 0x8800, lo: 0xb0, hi: 0xb0},
+	{value: 0x3eca, lo: 0xb1, hi: 0xb1},
+	{value: 0x8800, lo: 0xb3, hi: 0xb3},
+	{value: 0x3ed2, lo: 0xb4, hi: 0xb4},
+	{value: 0x8607, lo: 0xbc, hi: 0xbc},
+	// Block 0x10, offset 0x11
+	{value: 0x0008, lo: 0x06},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x80e6, lo: 0x91, hi: 0x91},
+	{value: 0x80dc, lo: 0x92, hi: 0x92},
+	{value: 0x80e6, lo: 0x93, hi: 0x93},
+	{value: 0x80e6, lo: 0x94, hi: 0x94},
+	{value: 0x4502, lo: 0x98, hi: 0x9f},
+	// Block 0x11, offset 0x12
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8007, lo: 0xbc, hi: 0xbc},
+	{value: 0x8600, lo: 0xbe, hi: 0xbe},
+	// Block 0x12, offset 0x13
+	{value: 0x0007, lo: 0x07},
+	{value: 0x8800, lo: 0x87, hi: 0x87},
+	{value: 0x18cf, lo: 0x8b, hi: 0x8c},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8600, lo: 0x97, hi: 0x97},
+	{value: 0x4542, lo: 0x9c, hi: 0x9c},
+	{value: 0x454a, lo: 0x9d, hi: 0x9d},
+	{value: 0x4552, lo: 0x9f, hi: 0x9f},
+	// Block 0x13, offset 0x14
+	{value: 0x0000, lo: 0x03},
+	{value: 0x457a, lo: 0xb3, hi: 0xb3},
+	{value: 0x4582, lo: 0xb6, hi: 0xb6},
+	{value: 0x8007, lo: 0xbc, hi: 0xbc},
+	// Block 0x14, offset 0x15
+	{value: 0x0008, lo: 0x03},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x455a, lo: 0x99, hi: 0x9b},
+	{value: 0x4572, lo: 0x9e, hi: 0x9e},
+	// Block 0x15, offset 0x16
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8007, lo: 0xbc, hi: 0xbc},
+	// Block 0x16, offset 0x17
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	// Block 0x17, offset 0x18
+	{value: 0x0000, lo: 0x08},
+	{value: 0x8800, lo: 0x87, hi: 0x87},
+	{value: 0x18e4, lo: 0x88, hi: 0x88},
+	{value: 0x18dd, lo: 0x8b, hi: 0x8b},
+	{value: 0x18eb, lo: 0x8c, hi: 0x8c},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8600, lo: 0x96, hi: 0x97},
+	{value: 0x458a, lo: 0x9c, hi: 0x9c},
+	{value: 0x4592, lo: 0x9d, hi: 0x9d},
+	// Block 0x18, offset 0x19
+	{value: 0x0000, lo: 0x03},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	{value: 0x18f2, lo: 0x94, hi: 0x94},
+	{value: 0x8600, lo: 0xbe, hi: 0xbe},
+	// Block 0x19, offset 0x1a
+	{value: 0x0000, lo: 0x06},
+	{value: 0x8800, lo: 0x86, hi: 0x87},
+	{value: 0x18f9, lo: 0x8a, hi: 0x8a},
+	{value: 0x1907, lo: 0x8b, hi: 0x8b},
+	{value: 0x1900, lo: 0x8c, hi: 0x8c},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8600, lo: 0x97, hi: 0x97},
+	// Block 0x1a, offset 0x1b
+	{value: 0x0607, lo: 0x04},
+	{value: 0x8800, lo: 0x86, hi: 0x86},
+	{value: 0x3eda, lo: 0x88, hi: 0x88},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8054, lo: 0x95, hi: 0x96},
+	// Block 0x1b, offset 0x1c
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8007, lo: 0xbc, hi: 0xbc},
+	{value: 0x8800, lo: 0xbf, hi: 0xbf},
+	// Block 0x1c, offset 0x1d
+	{value: 0x0000, lo: 0x09},
+	{value: 0x190e, lo: 0x80, hi: 0x80},
+	{value: 0x8600, lo: 0x82, hi: 0x82},
+	{value: 0x8800, lo: 0x86, hi: 0x86},
+	{value: 0x1915, lo: 0x87, hi: 0x87},
+	{value: 0x191c, lo: 0x88, hi: 0x88},
+	{value: 0x2e66, lo: 0x8a, hi: 0x8a},
+	{value: 0x19a5, lo: 0x8b, hi: 0x8b},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8600, lo: 0x95, hi: 0x96},
+	// Block 0x1d, offset 0x1e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8600, lo: 0xbe, hi: 0xbe},
+	// Block 0x1e, offset 0x1f
+	{value: 0x0000, lo: 0x06},
+	{value: 0x8800, lo: 0x86, hi: 0x87},
+	{value: 0x1923, lo: 0x8a, hi: 0x8a},
+	{value: 0x1931, lo: 0x8b, hi: 0x8b},
+	{value: 0x192a, lo: 0x8c, hi: 0x8c},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8600, lo: 0x97, hi: 0x97},
+	// Block 0x1f, offset 0x20
+	{value: 0x0007, lo: 0x07},
+	{value: 0x8609, lo: 0x8a, hi: 0x8a},
+	{value: 0x8600, lo: 0x8f, hi: 0x8f},
+	{value: 0x8800, lo: 0x99, hi: 0x99},
+	{value: 0x3ee2, lo: 0x9a, hi: 0x9a},
+	{value: 0x2e6d, lo: 0x9c, hi: 0x9d},
+	{value: 0x1938, lo: 0x9e, hi: 0x9e},
+	{value: 0x8600, lo: 0x9f, hi: 0x9f},
+	// Block 0x20, offset 0x21
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8067, lo: 0xb8, hi: 0xb9},
+	{value: 0x8009, lo: 0xba, hi: 0xba},
+	// Block 0x21, offset 0x22
+	{value: 0x0000, lo: 0x01},
+	{value: 0x806b, lo: 0x88, hi: 0x8b},
+	// Block 0x22, offset 0x23
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8076, lo: 0xb8, hi: 0xb9},
+	// Block 0x23, offset 0x24
+	{value: 0x0000, lo: 0x01},
+	{value: 0x807a, lo: 0x88, hi: 0x8b},
+	// Block 0x24, offset 0x25
+	{value: 0x0000, lo: 0x04},
+	{value: 0x80dc, lo: 0x98, hi: 0x99},
+	{value: 0x80dc, lo: 0xb5, hi: 0xb5},
+	{value: 0x80dc, lo: 0xb7, hi: 0xb7},
+	{value: 0x80d8, lo: 0xb9, hi: 0xb9},
+	// Block 0x25, offset 0x26
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x2786, lo: 0x83, hi: 0x83},
+	{value: 0x278d, lo: 0x8d, hi: 0x8d},
+	{value: 0x2794, lo: 0x92, hi: 0x92},
+	{value: 0x279b, lo: 0x97, hi: 0x97},
+	{value: 0x27a2, lo: 0x9c, hi: 0x9c},
+	{value: 0x277f, lo: 0xa9, hi: 0xa9},
+	{value: 0x8081, lo: 0xb1, hi: 0xb1},
+	{value: 0x8082, lo: 0xb2, hi: 0xb2},
+	{value: 0x49b6, lo: 0xb3, hi: 0xb3},
+	{value: 0x8084, lo: 0xb4, hi: 0xb4},
+	{value: 0x49bf, lo: 0xb5, hi: 0xb5},
+	{value: 0x459a, lo: 0xb6, hi: 0xb6},
+	{value: 0x45a2, lo: 0xb8, hi: 0xb8},
+	{value: 0x8082, lo: 0xba, hi: 0xbd},
+	// Block 0x26, offset 0x27
+	{value: 0x0000, lo: 0x0b},
+	{value: 0x8082, lo: 0x80, hi: 0x80},
+	{value: 0x49c8, lo: 0x81, hi: 0x81},
+	{value: 0x80e6, lo: 0x82, hi: 0x83},
+	{value: 0x8009, lo: 0x84, hi: 0x84},
+	{value: 0x80e6, lo: 0x86, hi: 0x87},
+	{value: 0x27b0, lo: 0x93, hi: 0x93},
+	{value: 0x27b7, lo: 0x9d, hi: 0x9d},
+	{value: 0x27be, lo: 0xa2, hi: 0xa2},
+	{value: 0x27c5, lo: 0xa7, hi: 0xa7},
+	{value: 0x27cc, lo: 0xac, hi: 0xac},
+	{value: 0x27a9, lo: 0xb9, hi: 0xb9},
+	// Block 0x27, offset 0x28
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80dc, lo: 0x86, hi: 0x86},
+	// Block 0x28, offset 0x29
+	{value: 0x0000, lo: 0x05},
+	{value: 0x8800, lo: 0xa5, hi: 0xa5},
+	{value: 0x193f, lo: 0xa6, hi: 0xa6},
+	{value: 0x8600, lo: 0xae, hi: 0xae},
+	{value: 0x8007, lo: 0xb7, hi: 0xb7},
+	{value: 0x8009, lo: 0xb9, hi: 0xba},
+	// Block 0x29, offset 0x2a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80dc, lo: 0x8d, hi: 0x8d},
+	// Block 0x2a, offset 0x2b
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8800, lo: 0x80, hi: 0x92},
+	// Block 0x2b, offset 0x2c
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8e00, lo: 0xa1, hi: 0xb5},
+	// Block 0x2c, offset 0x2d
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8600, lo: 0xa8, hi: 0xbf},
+	// Block 0x2d, offset 0x2e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8600, lo: 0x80, hi: 0x82},
+	// Block 0x2e, offset 0x2f
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0x9d, hi: 0x9f},
+	// Block 0x2f, offset 0x30
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8009, lo: 0x94, hi: 0x94},
+	{value: 0x8009, lo: 0xb4, hi: 0xb4},
+	// Block 0x30, offset 0x31
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8009, lo: 0x92, hi: 0x92},
+	{value: 0x80e6, lo: 0x9d, hi: 0x9d},
+	// Block 0x31, offset 0x32
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e4, lo: 0xa9, hi: 0xa9},
+	// Block 0x32, offset 0x33
+	{value: 0x0008, lo: 0x02},
+	{value: 0x80de, lo: 0xb9, hi: 0xba},
+	{value: 0x80dc, lo: 0xbb, hi: 0xbb},
+	// Block 0x33, offset 0x34
+	{value: 0x0000, lo: 0x02},
+	{value: 0x80e6, lo: 0x97, hi: 0x97},
+	{value: 0x80dc, lo: 0x98, hi: 0x98},
+	// Block 0x34, offset 0x35
+	{value: 0x0000, lo: 0x03},
+	{value: 0x8009, lo: 0xa0, hi: 0xa0},
+	{value: 0x80e6, lo: 0xb5, hi: 0xbc},
+	{value: 0x80dc, lo: 0xbf, hi: 0xbf},
+	// Block 0x35, offset 0x36
+	{value: 0x0000, lo: 0x08},
+	{value: 0x197e, lo: 0x80, hi: 0x80},
+	{value: 0x1985, lo: 0x81, hi: 0x81},
+	{value: 0x8800, lo: 0x82, hi: 0x82},
+	{value: 0x198c, lo: 0x83, hi: 0x83},
+	{value: 0x8009, lo: 0x84, hi: 0x84},
+	{value: 0x80e6, lo: 0xab, hi: 0xab},
+	{value: 0x80dc, lo: 0xac, hi: 0xac},
+	{value: 0x80e6, lo: 0xad, hi: 0xb3},
+	// Block 0x36, offset 0x37
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0xaa, hi: 0xab},
+	// Block 0x37, offset 0x38
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8007, lo: 0xa6, hi: 0xa6},
+	{value: 0x8009, lo: 0xb2, hi: 0xb3},
+	// Block 0x38, offset 0x39
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8007, lo: 0xb7, hi: 0xb7},
+	// Block 0x39, offset 0x3a
+	{value: 0x0000, lo: 0x09},
+	{value: 0x80e6, lo: 0x90, hi: 0x92},
+	{value: 0x8001, lo: 0x94, hi: 0x94},
+	{value: 0x80dc, lo: 0x95, hi: 0x99},
+	{value: 0x80e6, lo: 0x9a, hi: 0x9b},
+	{value: 0x80dc, lo: 0x9c, hi: 0x9f},
+	{value: 0x80e6, lo: 0xa0, hi: 0xa0},
+	{value: 0x8001, lo: 0xa2, hi: 0xa8},
+	{value: 0x80dc, lo: 0xad, hi: 0xad},
+	{value: 0x80e6, lo: 0xb4, hi: 0xb4},
+	// Block 0x3a, offset 0x3b
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x80e6, lo: 0x80, hi: 0x81},
+	{value: 0x80dc, lo: 0x82, hi: 0x82},
+	{value: 0x80e6, lo: 0x83, hi: 0x89},
+	{value: 0x80dc, lo: 0x8a, hi: 0x8a},
+	{value: 0x80e6, lo: 0x8b, hi: 0x8c},
+	{value: 0x80ea, lo: 0x8d, hi: 0x8d},
+	{value: 0x80d6, lo: 0x8e, hi: 0x8e},
+	{value: 0x80dc, lo: 0x8f, hi: 0x8f},
+	{value: 0x80ca, lo: 0x90, hi: 0x90},
+	{value: 0x80e6, lo: 0x91, hi: 0xa6},
+	{value: 0x80e9, lo: 0xbc, hi: 0xbc},
+	{value: 0x80dc, lo: 0xbd, hi: 0xbd},
+	{value: 0x80e6, lo: 0xbe, hi: 0xbe},
+	{value: 0x80dc, lo: 0xbf, hi: 0xbf},
+	// Block 0x3b, offset 0x3c
+	{value: 0x0004, lo: 0x01},
+	{value: 0x04a5, lo: 0x80, hi: 0x81},
+	// Block 0x3c, offset 0x3d
+	{value: 0x0000, lo: 0x0d},
+	{value: 0x80e6, lo: 0x90, hi: 0x91},
+	{value: 0x8001, lo: 0x92, hi: 0x93},
+	{value: 0x80e6, lo: 0x94, hi: 0x97},
+	{value: 0x8001, lo: 0x98, hi: 0x9a},
+	{value: 0x80e6, lo: 0x9b, hi: 0x9c},
+	{value: 0x80e6, lo: 0xa1, hi: 0xa1},
+	{value: 0x8001, lo: 0xa5, hi: 0xa6},
+	{value: 0x80e6, lo: 0xa7, hi: 0xa7},
+	{value: 0x80dc, lo: 0xa8, hi: 0xa8},
+	{value: 0x80e6, lo: 0xa9, hi: 0xa9},
+	{value: 0x8001, lo: 0xaa, hi: 0xab},
+	{value: 0x80dc, lo: 0xac, hi: 0xaf},
+	{value: 0x80e6, lo: 0xb0, hi: 0xb0},
+	// Block 0x3d, offset 0x3e
+	{value: 0x4261, lo: 0x02},
+	{value: 0x01b8, lo: 0xa6, hi: 0xa6},
+	{value: 0x0057, lo: 0xaa, hi: 0xab},
+	// Block 0x3e, offset 0x3f
+	{value: 0x0007, lo: 0x05},
+	{value: 0x8800, lo: 0x90, hi: 0x90},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	{value: 0x8800, lo: 0x94, hi: 0x94},
+	{value: 0x3ba3, lo: 0x9a, hi: 0x9b},
+	{value: 0x3bb1, lo: 0xae, hi: 0xae},
+	// Block 0x3f, offset 0x40
+	{value: 0x000e, lo: 0x05},
+	{value: 0x3bb8, lo: 0x8d, hi: 0x8e},
+	{value: 0x3bbf, lo: 0x8f, hi: 0x8f},
+	{value: 0x8800, lo: 0x90, hi: 0x90},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	{value: 0x8800, lo: 0x94, hi: 0x94},
+	// Block 0x40, offset 0x41
+	{value: 0x4c1e, lo: 0x0a},
+	{value: 0x8800, lo: 0x83, hi: 0x83},
+	{value: 0x3bcd, lo: 0x84, hi: 0x84},
+	{value: 0x8800, lo: 0x88, hi: 0x88},
+	{value: 0x3bd4, lo: 0x89, hi: 0x89},
+	{value: 0x8800, lo: 0x8b, hi: 0x8b},
+	{value: 0x3bdb, lo: 0x8c, hi: 0x8c},
+	{value: 0x8800, lo: 0xa3, hi: 0xa3},
+	{value: 0x3be2, lo: 0xa4, hi: 0xa5},
+	{value: 0x3be9, lo: 0xa6, hi: 0xa6},
+	{value: 0x8800, lo: 0xbc, hi: 0xbc},
+	// Block 0x41, offset 0x42
+	{value: 0x0007, lo: 0x03},
+	{value: 0x3c52, lo: 0xa0, hi: 0xa1},
+	{value: 0x3c7c, lo: 0xa2, hi: 0xa3},
+	{value: 0x3ca6, lo: 0xaa, hi: 0xad},
+	// Block 0x42, offset 0x43
+	{value: 0x0004, lo: 0x01},
+	{value: 0x04fd, lo: 0xa9, hi: 0xaa},
+	// Block 0x43, offset 0x44
+	{value: 0x0000, lo: 0x01},
+	{value: 0x44c3, lo: 0x9c, hi: 0x9c},
+	// Block 0x44, offset 0x45
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0xaf, hi: 0xb1},
+	// Block 0x45, offset 0x46
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0xbf, hi: 0xbf},
+	// Block 0x46, offset 0x47
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0xa0, hi: 0xbf},
+	// Block 0x47, offset 0x48
+	{value: 0x0000, lo: 0x05},
+	{value: 0x80da, lo: 0xaa, hi: 0xaa},
+	{value: 0x80e4, lo: 0xab, hi: 0xab},
+	{value: 0x80e8, lo: 0xac, hi: 0xac},
+	{value: 0x80de, lo: 0xad, hi: 0xad},
+	{value: 0x80e0, lo: 0xae, hi: 0xaf},
+	// Block 0x48, offset 0x49
+	{value: 0x0000, lo: 0x02},
+	{value: 0x80e6, lo: 0xaf, hi: 0xaf},
+	{value: 0x80e6, lo: 0xb4, hi: 0xbd},
+	// Block 0x49, offset 0x4a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0x9f, hi: 0x9f},
+	// Block 0x4a, offset 0x4b
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0xb0, hi: 0xb1},
+	// Block 0x4b, offset 0x4c
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0x86, hi: 0x86},
+	// Block 0x4c, offset 0x4d
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8009, lo: 0x84, hi: 0x84},
+	{value: 0x80e6, lo: 0xa0, hi: 0xb1},
+	// Block 0x4d, offset 0x4e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80dc, lo: 0xab, hi: 0xad},
+	// Block 0x4e, offset 0x4f
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0x93, hi: 0x93},
+	// Block 0x4f, offset 0x50
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8007, lo: 0xb3, hi: 0xb3},
+	// Block 0x50, offset 0x51
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0x80, hi: 0x80},
+	// Block 0x51, offset 0x52
+	{value: 0x0000, lo: 0x05},
+	{value: 0x80e6, lo: 0xb0, hi: 0xb0},
+	{value: 0x80e6, lo: 0xb2, hi: 0xb3},
+	{value: 0x80dc, lo: 0xb4, hi: 0xb4},
+	{value: 0x80e6, lo: 0xb7, hi: 0xb8},
+	{value: 0x80e6, lo: 0xbe, hi: 0xbf},
+	// Block 0x52, offset 0x53
+	{value: 0x0000, lo: 0x02},
+	{value: 0x80e6, lo: 0x81, hi: 0x81},
+	{value: 0x8009, lo: 0xb6, hi: 0xb6},
+	// Block 0x53, offset 0x54
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0xad, hi: 0xad},
+	// Block 0x54, offset 0x55
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0x80, hi: 0xbf},
+	// Block 0x55, offset 0x56
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0x80, hi: 0xa3},
+	// Block 0x56, offset 0x57
+	{value: 0x0006, lo: 0x0d},
+	{value: 0x4376, lo: 0x9d, hi: 0x9d},
+	{value: 0x801a, lo: 0x9e, hi: 0x9e},
+	{value: 0x43e8, lo: 0x9f, hi: 0x9f},
+	{value: 0x43d6, lo: 0xaa, hi: 0xab},
+	{value: 0x44da, lo: 0xac, hi: 0xac},
+	{value: 0x44e2, lo: 0xad, hi: 0xad},
+	{value: 0x432e, lo: 0xae, hi: 0xb1},
+	{value: 0x434c, lo: 0xb2, hi: 0xb4},
+	{value: 0x4364, lo: 0xb5, hi: 0xb6},
+	{value: 0x4370, lo: 0xb8, hi: 0xb8},
+	{value: 0x437c, lo: 0xb9, hi: 0xbb},
+	{value: 0x4394, lo: 0xbc, hi: 0xbc},
+	{value: 0x439a, lo: 0xbe, hi: 0xbe},
+	// Block 0x57, offset 0x58
+	{value: 0x0006, lo: 0x08},
+	{value: 0x43a0, lo: 0x80, hi: 0x81},
+	{value: 0x43ac, lo: 0x83, hi: 0x84},
+	{value: 0x43be, lo: 0x86, hi: 0x89},
+	{value: 0x43e2, lo: 0x8a, hi: 0x8a},
+	{value: 0x435e, lo: 0x8b, hi: 0x8b},
+	{value: 0x4346, lo: 0x8c, hi: 0x8c},
+	{value: 0x438e, lo: 0x8d, hi: 0x8d},
+	{value: 0x43b8, lo: 0x8e, hi: 0x8e},
+	// Block 0x58, offset 0x59
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0xa0, hi: 0xa6},
+	// Block 0x59, offset 0x5a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80dc, lo: 0xbd, hi: 0xbd},
+	// Block 0x5a, offset 0x5b
+	{value: 0x00db, lo: 0x05},
+	{value: 0x80dc, lo: 0x8d, hi: 0x8d},
+	{value: 0x80e6, lo: 0x8f, hi: 0x8f},
+	{value: 0x80e6, lo: 0xb8, hi: 0xb8},
+	{value: 0x8001, lo: 0xb9, hi: 0xba},
+	{value: 0x8009, lo: 0xbf, hi: 0xbf},
+	// Block 0x5b, offset 0x5c
+	{value: 0x05fe, lo: 0x07},
+	{value: 0x8800, lo: 0x99, hi: 0x99},
+	{value: 0x4222, lo: 0x9a, hi: 0x9a},
+	{value: 0x8800, lo: 0x9b, hi: 0x9b},
+	{value: 0x422c, lo: 0x9c, hi: 0x9c},
+	{value: 0x8800, lo: 0xa5, hi: 0xa5},
+	{value: 0x4236, lo: 0xab, hi: 0xab},
+	{value: 0x8009, lo: 0xb9, hi: 0xba},
+	// Block 0x5c, offset 0x5d
+	{value: 0x0000, lo: 0x06},
+	{value: 0x80e6, lo: 0x80, hi: 0x82},
+	{value: 0x8600, lo: 0xa7, hi: 0xa7},
+	{value: 0x1993, lo: 0xae, hi: 0xae},
+	{value: 0x199c, lo: 0xaf, hi: 0xaf},
+	{value: 0x8800, lo: 0xb1, hi: 0xb2},
+	{value: 0x8009, lo: 0xb3, hi: 0xb4},
+	// Block 0x5d, offset 0x5e
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8009, lo: 0xb6, hi: 0xb6},
+	{value: 0x8007, lo: 0xb7, hi: 0xb7},
+	// Block 0x5e, offset 0x5f
+	{value: 0x0000, lo: 0x0c},
+	{value: 0x45b2, lo: 0x9e, hi: 0x9e},
+	{value: 0x45bc, lo: 0x9f, hi: 0x9f},
+	{value: 0x45f0, lo: 0xa0, hi: 0xa0},
+	{value: 0x45fe, lo: 0xa1, hi: 0xa1},
+	{value: 0x460c, lo: 0xa2, hi: 0xa2},
+	{value: 0x461a, lo: 0xa3, hi: 0xa3},
+	{value: 0x4628, lo: 0xa4, hi: 0xa4},
+	{value: 0x80d8, lo: 0xa5, hi: 0xa6},
+	{value: 0x8001, lo: 0xa7, hi: 0xa9},
+	{value: 0x80e2, lo: 0xad, hi: 0xad},
+	{value: 0x80d8, lo: 0xae, hi: 0xb2},
+	{value: 0x80dc, lo: 0xbb, hi: 0xbf},
+	// Block 0x5f, offset 0x60
+	{value: 0x0000, lo: 0x09},
+	{value: 0x80dc, lo: 0x80, hi: 0x82},
+	{value: 0x80e6, lo: 0x85, hi: 0x89},
+	{value: 0x80dc, lo: 0x8a, hi: 0x8b},
+	{value: 0x80e6, lo: 0xaa, hi: 0xad},
+	{value: 0x45c6, lo: 0xbb, hi: 0xbb},
+	{value: 0x45d0, lo: 0xbc, hi: 0xbc},
+	{value: 0x4636, lo: 0xbd, hi: 0xbd},
+	{value: 0x4652, lo: 0xbe, hi: 0xbe},
+	{value: 0x4644, lo: 0xbf, hi: 0xbf},
+	// Block 0x60, offset 0x61
+	{value: 0x0000, lo: 0x01},
+	{value: 0x4660, lo: 0x80, hi: 0x80},
+	// Block 0x61, offset 0x62
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0x82, hi: 0x84},
+}
+
+// nfcLookup: 1088 bytes
+// Block 0 is the null block.
+var nfcLookup = [1088]uint8{
+	// Block 0x0, offset 0x0
+	// Block 0x1, offset 0x40
+	// Block 0x2, offset 0x80
+	// Block 0x3, offset 0xc0
+	0x0c2: 0x2c, 0x0c3: 0x01, 0x0c4: 0x02, 0x0c5: 0x03, 0x0c6: 0x2d, 0x0c7: 0x04,
+	0x0c8: 0x05, 0x0ca: 0x2e, 0x0cc: 0x06, 0x0cd: 0x07, 0x0ce: 0x08, 0x0cf: 0x2f,
+	0x0d0: 0x09, 0x0d1: 0x30, 0x0d2: 0x31, 0x0d3: 0x0a, 0x0d6: 0x0b, 0x0d7: 0x32,
+	0x0d8: 0x33, 0x0d9: 0x0c, 0x0db: 0x34, 0x0dc: 0x35, 0x0dd: 0x36, 0x0df: 0x37,
+	0x0e0: 0x02, 0x0e1: 0x03, 0x0e2: 0x04, 0x0e3: 0x05,
+	0x0ea: 0x06, 0x0eb: 0x07, 0x0ec: 0x07, 0x0ed: 0x08, 0x0ef: 0x09,
+	0x0f0: 0x0e,
+	// Block 0x4, offset 0x100
+	0x120: 0x38, 0x121: 0x39, 0x123: 0x3a, 0x124: 0x3b, 0x125: 0x3c, 0x126: 0x3d, 0x127: 0x3e,
+	0x128: 0x3f, 0x129: 0x40, 0x12a: 0x41, 0x12b: 0x42, 0x12c: 0x3d, 0x12d: 0x43, 0x12e: 0x44, 0x12f: 0x45,
+	0x131: 0x46, 0x132: 0x47, 0x133: 0x48, 0x134: 0x49, 0x135: 0x4a, 0x137: 0x4b,
+	0x138: 0x4c, 0x139: 0x4d, 0x13a: 0x4e, 0x13b: 0x4f, 0x13c: 0x50, 0x13d: 0x51, 0x13e: 0x52, 0x13f: 0x53,
+	// Block 0x5, offset 0x140
+	0x140: 0x54, 0x142: 0x55, 0x144: 0x56, 0x145: 0x57, 0x146: 0x58, 0x147: 0x59,
+	0x14d: 0x5a,
+	0x15c: 0x5b, 0x15f: 0x5c,
+	0x162: 0x5d, 0x164: 0x5e,
+	0x168: 0x5f, 0x169: 0x60, 0x16c: 0x0d, 0x16d: 0x61, 0x16e: 0x62, 0x16f: 0x63,
+	0x170: 0x64, 0x173: 0x65, 0x177: 0x66,
+	0x178: 0x0e, 0x179: 0x0f, 0x17a: 0x10, 0x17b: 0x11, 0x17c: 0x12, 0x17d: 0x13, 0x17e: 0x14, 0x17f: 0x15,
+	// Block 0x6, offset 0x180
+	0x180: 0x67, 0x183: 0x68, 0x184: 0x69, 0x186: 0x6a, 0x187: 0x6b,
+	0x188: 0x6c, 0x189: 0x16, 0x18a: 0x17, 0x18b: 0x6d, 0x18c: 0x6e,
+	0x1ab: 0x6f,
+	0x1b3: 0x70, 0x1b5: 0x71, 0x1b7: 0x72,
+	// Block 0x7, offset 0x1c0
+	0x1c0: 0x73, 0x1c1: 0x18, 0x1c2: 0x19, 0x1c3: 0x1a,
+	// Block 0x8, offset 0x200
+	0x219: 0x74, 0x21a: 0x75, 0x21b: 0x76,
+	0x220: 0x77, 0x223: 0x78, 0x224: 0x79, 0x225: 0x7a, 0x226: 0x7b, 0x227: 0x7c,
+	0x22a: 0x7d, 0x22b: 0x7e, 0x22f: 0x7f,
+	0x230: 0x80, 0x231: 0x80, 0x232: 0x80, 0x233: 0x80, 0x234: 0x80, 0x235: 0x80, 0x236: 0x80, 0x237: 0x80,
+	0x238: 0x80, 0x239: 0x80, 0x23a: 0x80, 0x23b: 0x80, 0x23c: 0x80, 0x23d: 0x80, 0x23e: 0x80, 0x23f: 0x80,
+	// Block 0x9, offset 0x240
+	0x240: 0x80, 0x241: 0x80, 0x242: 0x80, 0x243: 0x80, 0x244: 0x80, 0x245: 0x80, 0x246: 0x80, 0x247: 0x80,
+	0x248: 0x80, 0x249: 0x80, 0x24a: 0x80, 0x24b: 0x80, 0x24c: 0x80, 0x24d: 0x80, 0x24e: 0x80, 0x24f: 0x80,
+	0x250: 0x80, 0x251: 0x80, 0x252: 0x80, 0x253: 0x80, 0x254: 0x80, 0x255: 0x80, 0x256: 0x80, 0x257: 0x80,
+	0x258: 0x80, 0x259: 0x80, 0x25a: 0x80, 0x25b: 0x80, 0x25c: 0x80, 0x25d: 0x80, 0x25e: 0x80, 0x25f: 0x80,
+	0x260: 0x80, 0x261: 0x80, 0x262: 0x80, 0x263: 0x80, 0x264: 0x80, 0x265: 0x80, 0x266: 0x80, 0x267: 0x80,
+	0x268: 0x80, 0x269: 0x80, 0x26a: 0x80, 0x26b: 0x80, 0x26c: 0x80, 0x26d: 0x80, 0x26e: 0x80, 0x26f: 0x80,
+	0x270: 0x80, 0x271: 0x80, 0x272: 0x80, 0x273: 0x80, 0x274: 0x80, 0x275: 0x80, 0x276: 0x80, 0x277: 0x80,
+	0x278: 0x80, 0x279: 0x80, 0x27a: 0x80, 0x27b: 0x80, 0x27c: 0x80, 0x27d: 0x80, 0x27e: 0x80, 0x27f: 0x80,
+	// Block 0xa, offset 0x280
+	0x280: 0x80, 0x281: 0x80, 0x282: 0x80, 0x283: 0x80, 0x284: 0x80, 0x285: 0x80, 0x286: 0x80, 0x287: 0x80,
+	0x288: 0x80, 0x289: 0x80, 0x28a: 0x80, 0x28b: 0x80, 0x28c: 0x80, 0x28d: 0x80, 0x28e: 0x80, 0x28f: 0x80,
+	0x290: 0x80, 0x291: 0x80, 0x292: 0x80, 0x293: 0x80, 0x294: 0x80, 0x295: 0x80, 0x296: 0x80, 0x297: 0x80,
+	0x298: 0x80, 0x299: 0x80, 0x29a: 0x80, 0x29b: 0x80, 0x29c: 0x80, 0x29d: 0x80, 0x29e: 0x81,
+	// Block 0xb, offset 0x2c0
+	0x2e4: 0x1b, 0x2e5: 0x1c, 0x2e6: 0x1d, 0x2e7: 0x1e,
+	0x2e8: 0x1f, 0x2e9: 0x20, 0x2ea: 0x21, 0x2eb: 0x22, 0x2ec: 0x82, 0x2ed: 0x83,
+	0x2f8: 0x84,
+	// Block 0xc, offset 0x300
+	0x307: 0x85,
+	0x328: 0x86,
+	// Block 0xd, offset 0x340
+	0x341: 0x77, 0x342: 0x87, 0x344: 0x88, 0x347: 0x7c,
+	0x35a: 0x89,
+	// Block 0xe, offset 0x380
+	0x385: 0x8a, 0x386: 0x8b, 0x387: 0x8c,
+	0x389: 0x8d,
+	// Block 0xf, offset 0x3c0
+	0x3e0: 0x23, 0x3e1: 0x24, 0x3e2: 0x25, 0x3e3: 0x26, 0x3e4: 0x27, 0x3e5: 0x28, 0x3e6: 0x29, 0x3e7: 0x2a,
+	0x3e8: 0x2b,
+	// Block 0x10, offset 0x400
+	0x410: 0x0a, 0x411: 0x0b,
+	0x41d: 0x0c,
+	0x42f: 0x0d,
+}
+
+var nfcTrie = trie{nfcLookup[:], nfcValues[:], nfcSparseValues[:], nfcSparseOffset[:], 44}
+
+// nfkcValues: 5760 entries, 11520 bytes
+// Block 2 is the null block.
+var nfkcValues = [5760]uint16{
+	// Block 0x0, offset 0x0
+	0x003c: 0x8800, 0x003d: 0x8800, 0x003e: 0x8800,
+	// Block 0x1, offset 0x40
+	0x0041: 0x8800, 0x0042: 0x8800, 0x0043: 0x8800, 0x0044: 0x8800, 0x0045: 0x8800,
+	0x0046: 0x8800, 0x0047: 0x8800, 0x0048: 0x8800, 0x0049: 0x8800, 0x004a: 0x8800, 0x004b: 0x8800,
+	0x004c: 0x8800, 0x004d: 0x8800, 0x004e: 0x8800, 0x004f: 0x8800, 0x0050: 0x8800,
+	0x0052: 0x8800, 0x0053: 0x8800, 0x0054: 0x8800, 0x0055: 0x8800, 0x0056: 0x8800, 0x0057: 0x8800,
+	0x0058: 0x8800, 0x0059: 0x8800, 0x005a: 0x8800,
+	0x0061: 0x8800, 0x0062: 0x8800, 0x0063: 0x8800,
+	0x0064: 0x8800, 0x0065: 0x8800, 0x0066: 0x8800, 0x0067: 0x8800, 0x0068: 0x8800, 0x0069: 0x8800,
+	0x006a: 0x8800, 0x006b: 0x8800, 0x006c: 0x8800, 0x006d: 0x8800, 0x006e: 0x8800, 0x006f: 0x8800,
+	0x0070: 0x8800, 0x0072: 0x8800, 0x0073: 0x8800, 0x0074: 0x8800, 0x0075: 0x8800,
+	0x0076: 0x8800, 0x0077: 0x8800, 0x0078: 0x8800, 0x0079: 0x8800, 0x007a: 0x8800,
+	// Block 0x2, offset 0x80
+	// Block 0x3, offset 0xc0
+	0x00c0: 0x2f59, 0x00c1: 0x2f5e, 0x00c2: 0x466e, 0x00c3: 0x2f63, 0x00c4: 0x467d, 0x00c5: 0x4682,
+	0x00c6: 0x8800, 0x00c7: 0x468c, 0x00c8: 0x2fcc, 0x00c9: 0x2fd1, 0x00ca: 0x4691, 0x00cb: 0x2fe5,
+	0x00cc: 0x3058, 0x00cd: 0x305d, 0x00ce: 0x3062, 0x00cf: 0x46a5, 0x00d1: 0x30ee,
+	0x00d2: 0x3111, 0x00d3: 0x3116, 0x00d4: 0x46af, 0x00d5: 0x46b4, 0x00d6: 0x46c3,
+	0x00d8: 0x8800, 0x00d9: 0x319d, 0x00da: 0x31a2, 0x00db: 0x31a7, 0x00dc: 0x46f5, 0x00dd: 0x321f,
+	0x00e0: 0x3265, 0x00e1: 0x326a, 0x00e2: 0x46ff, 0x00e3: 0x326f,
+	0x00e4: 0x470e, 0x00e5: 0x4713, 0x00e6: 0x8800, 0x00e7: 0x471d, 0x00e8: 0x32d8, 0x00e9: 0x32dd,
+	0x00ea: 0x4722, 0x00eb: 0x32f1, 0x00ec: 0x3369, 0x00ed: 0x336e, 0x00ee: 0x3373, 0x00ef: 0x4736,
+	0x00f1: 0x33ff, 0x00f2: 0x3422, 0x00f3: 0x3427, 0x00f4: 0x4740, 0x00f5: 0x4745,
+	0x00f6: 0x4754, 0x00f8: 0x8800, 0x00f9: 0x34b3, 0x00fa: 0x34b8, 0x00fb: 0x34bd,
+	0x00fc: 0x4786, 0x00fd: 0x353a, 0x00ff: 0x3553,
+	// Block 0x4, offset 0x100
+	0x0100: 0x2f68, 0x0101: 0x3274, 0x0102: 0x4673, 0x0103: 0x4704, 0x0104: 0x2f86, 0x0105: 0x3292,
+	0x0106: 0x2f9a, 0x0107: 0x32a6, 0x0108: 0x2f9f, 0x0109: 0x32ab, 0x010a: 0x2fa4, 0x010b: 0x32b0,
+	0x010c: 0x2fa9, 0x010d: 0x32b5, 0x010e: 0x2fb3, 0x010f: 0x32bf,
+	0x0112: 0x4696, 0x0113: 0x4727, 0x0114: 0x2fdb, 0x0115: 0x32e7, 0x0116: 0x2fe0, 0x0117: 0x32ec,
+	0x0118: 0x2ffe, 0x0119: 0x330a, 0x011a: 0x2fef, 0x011b: 0x32fb, 0x011c: 0x3017, 0x011d: 0x3323,
+	0x011e: 0x3021, 0x011f: 0x332d, 0x0120: 0x3026, 0x0121: 0x3332, 0x0122: 0x3030, 0x0123: 0x333c,
+	0x0124: 0x3035, 0x0125: 0x3341, 0x0128: 0x3067, 0x0129: 0x3378,
+	0x012a: 0x306c, 0x012b: 0x337d, 0x012c: 0x3071, 0x012d: 0x3382, 0x012e: 0x3094, 0x012f: 0x33a0,
+	0x0130: 0x3076, 0x0132: 0x1a9f, 0x0133: 0x1b29, 0x0134: 0x309e, 0x0135: 0x33aa,
+	0x0136: 0x30b2, 0x0137: 0x33c3, 0x0139: 0x30bc, 0x013a: 0x33cd, 0x013b: 0x30c6,
+	0x013c: 0x33d7, 0x013d: 0x30c1, 0x013e: 0x33d2, 0x013f: 0x1cee,
+	// Block 0x5, offset 0x140
+	0x0140: 0x1d76, 0x0143: 0x30e9, 0x0144: 0x33fa, 0x0145: 0x3102,
+	0x0146: 0x3413, 0x0147: 0x30f8, 0x0148: 0x3409, 0x0149: 0x1d9e,
+	0x014c: 0x46b9, 0x014d: 0x474a, 0x014e: 0x311b, 0x014f: 0x342c, 0x0150: 0x3125, 0x0151: 0x3436,
+	0x0154: 0x3143, 0x0155: 0x3454, 0x0156: 0x315c, 0x0157: 0x346d,
+	0x0158: 0x314d, 0x0159: 0x345e, 0x015a: 0x46dc, 0x015b: 0x476d, 0x015c: 0x3166, 0x015d: 0x3477,
+	0x015e: 0x3175, 0x015f: 0x3486, 0x0160: 0x46e1, 0x0161: 0x4772, 0x0162: 0x318e, 0x0163: 0x34a4,
+	0x0164: 0x317f, 0x0165: 0x3495, 0x0168: 0x46eb, 0x0169: 0x477c,
+	0x016a: 0x46f0, 0x016b: 0x4781, 0x016c: 0x31ac, 0x016d: 0x34c2, 0x016e: 0x31b6, 0x016f: 0x34cc,
+	0x0170: 0x31bb, 0x0171: 0x34d1, 0x0172: 0x31d9, 0x0173: 0x34ef, 0x0174: 0x31fc, 0x0175: 0x3512,
+	0x0176: 0x3224, 0x0177: 0x353f, 0x0178: 0x3238, 0x0179: 0x3247, 0x017a: 0x3567, 0x017b: 0x3251,
+	0x017c: 0x3571, 0x017d: 0x3256, 0x017e: 0x3576, 0x017f: 0x00a7,
+	// Block 0x6, offset 0x180
+	0x0184: 0x2e7f, 0x0185: 0x2e85,
+	0x0186: 0x2e8b, 0x0187: 0x1ab4, 0x0188: 0x1ab7, 0x0189: 0x1b4a, 0x018a: 0x1ac9, 0x018b: 0x1acc,
+	0x018c: 0x1b80, 0x018d: 0x2f72, 0x018e: 0x327e, 0x018f: 0x3080, 0x0190: 0x338c, 0x0191: 0x312a,
+	0x0192: 0x343b, 0x0193: 0x31c0, 0x0194: 0x34d6, 0x0195: 0x39b9, 0x0196: 0x3b48, 0x0197: 0x39b2,
+	0x0198: 0x3b41, 0x0199: 0x39c0, 0x019a: 0x3b4f, 0x019b: 0x39ab, 0x019c: 0x3b3a,
+	0x019e: 0x389a, 0x019f: 0x3a29, 0x01a0: 0x3893, 0x01a1: 0x3a22, 0x01a2: 0x359d, 0x01a3: 0x35af,
+	0x01a6: 0x302b, 0x01a7: 0x3337, 0x01a8: 0x30a8, 0x01a9: 0x33b9,
+	0x01aa: 0x46d2, 0x01ab: 0x4763, 0x01ac: 0x397a, 0x01ad: 0x3b09, 0x01ae: 0x35c1, 0x01af: 0x35c7,
+	0x01b0: 0x33af, 0x01b1: 0x1a84, 0x01b2: 0x1a87, 0x01b3: 0x1b11, 0x01b4: 0x3012, 0x01b5: 0x331e,
+	0x01b8: 0x30e4, 0x01b9: 0x33f5, 0x01ba: 0x38a1, 0x01bb: 0x3a30,
+	0x01bc: 0x3597, 0x01bd: 0x35a9, 0x01be: 0x35a3, 0x01bf: 0x35b5,
+	// Block 0x7, offset 0x1c0
+	0x01c0: 0x2f77, 0x01c1: 0x3283, 0x01c2: 0x2f7c, 0x01c3: 0x3288, 0x01c4: 0x2ff4, 0x01c5: 0x3300,
+	0x01c6: 0x2ff9, 0x01c7: 0x3305, 0x01c8: 0x3085, 0x01c9: 0x3391, 0x01ca: 0x308a, 0x01cb: 0x3396,
+	0x01cc: 0x312f, 0x01cd: 0x3440, 0x01ce: 0x3134, 0x01cf: 0x3445, 0x01d0: 0x3152, 0x01d1: 0x3463,
+	0x01d2: 0x3157, 0x01d3: 0x3468, 0x01d4: 0x31c5, 0x01d5: 0x34db, 0x01d6: 0x31ca, 0x01d7: 0x34e0,
+	0x01d8: 0x3170, 0x01d9: 0x3481, 0x01da: 0x3189, 0x01db: 0x349f,
+	0x01de: 0x3044, 0x01df: 0x3350,
+	0x01e6: 0x4678, 0x01e7: 0x4709, 0x01e8: 0x46a0, 0x01e9: 0x4731,
+	0x01ea: 0x3949, 0x01eb: 0x3ad8, 0x01ec: 0x3926, 0x01ed: 0x3ab5, 0x01ee: 0x46be, 0x01ef: 0x474f,
+	0x01f0: 0x3942, 0x01f1: 0x3ad1, 0x01f2: 0x322e, 0x01f3: 0x3549,
+	// Block 0x8, offset 0x200
+	0x0200: 0x86e6, 0x0201: 0x86e6, 0x0202: 0x86e6, 0x0203: 0x86e6, 0x0204: 0x86e6, 0x0205: 0x80e6,
+	0x0206: 0x86e6, 0x0207: 0x86e6, 0x0208: 0x86e6, 0x0209: 0x86e6, 0x020a: 0x86e6, 0x020b: 0x86e6,
+	0x020c: 0x86e6, 0x020d: 0x80e6, 0x020e: 0x80e6, 0x020f: 0x86e6, 0x0210: 0x80e6, 0x0211: 0x86e6,
+	0x0212: 0x80e6, 0x0213: 0x86e6, 0x0214: 0x86e6, 0x0215: 0x80e8, 0x0216: 0x80dc, 0x0217: 0x80dc,
+	0x0218: 0x80dc, 0x0219: 0x80dc, 0x021a: 0x80e8, 0x021b: 0x86d8, 0x021c: 0x80dc, 0x021d: 0x80dc,
+	0x021e: 0x80dc, 0x021f: 0x80dc, 0x0220: 0x80dc, 0x0221: 0x80ca, 0x0222: 0x80ca, 0x0223: 0x86dc,
+	0x0224: 0x86dc, 0x0225: 0x86dc, 0x0226: 0x86dc, 0x0227: 0x86ca, 0x0228: 0x86ca, 0x0229: 0x80dc,
+	0x022a: 0x80dc, 0x022b: 0x80dc, 0x022c: 0x80dc, 0x022d: 0x86dc, 0x022e: 0x86dc, 0x022f: 0x80dc,
+	0x0230: 0x86dc, 0x0231: 0x86dc, 0x0232: 0x80dc, 0x0233: 0x80dc, 0x0234: 0x8001, 0x0235: 0x8001,
+	0x0236: 0x8001, 0x0237: 0x8001, 0x0238: 0x8601, 0x0239: 0x80dc, 0x023a: 0x80dc, 0x023b: 0x80dc,
+	0x023c: 0x80dc, 0x023d: 0x80e6, 0x023e: 0x80e6, 0x023f: 0x80e6,
+	// Block 0x9, offset 0x240
+	0x0240: 0x4994, 0x0241: 0x4999, 0x0242: 0x86e6, 0x0243: 0x499e, 0x0244: 0x49a3, 0x0245: 0x86f0,
+	0x0246: 0x80e6, 0x0247: 0x80dc, 0x0248: 0x80dc, 0x0249: 0x80dc, 0x024a: 0x80e6, 0x024b: 0x80e6,
+	0x024c: 0x80e6, 0x024d: 0x80dc, 0x024e: 0x80dc, 0x0250: 0x80e6, 0x0251: 0x80e6,
+	0x0252: 0x80e6, 0x0253: 0x80dc, 0x0254: 0x80dc, 0x0255: 0x80dc, 0x0256: 0x80dc, 0x0257: 0x80e6,
+	0x0258: 0x80e8, 0x0259: 0x80dc, 0x025a: 0x80dc, 0x025b: 0x80e6, 0x025c: 0x80e9, 0x025d: 0x80ea,
+	0x025e: 0x80ea, 0x025f: 0x80e9, 0x0260: 0x80ea, 0x0261: 0x80ea, 0x0262: 0x80e9, 0x0263: 0x80e6,
+	0x0264: 0x80e6, 0x0265: 0x80e6, 0x0266: 0x80e6, 0x0267: 0x80e6, 0x0268: 0x80e6, 0x0269: 0x80e6,
+	0x026a: 0x80e6, 0x026b: 0x80e6, 0x026c: 0x80e6, 0x026d: 0x80e6, 0x026e: 0x80e6, 0x026f: 0x80e6,
+	0x0274: 0x0170,
+	0x027a: 0x428b,
+	0x027e: 0x0037,
+	// Block 0xa, offset 0x280
+	0x0284: 0x4240, 0x0285: 0x4461,
+	0x0286: 0x35d3, 0x0287: 0x00d1, 0x0288: 0x35f1, 0x0289: 0x35fd, 0x028a: 0x360f,
+	0x028c: 0x362d, 0x028e: 0x363f, 0x028f: 0x365d, 0x0290: 0x3df2, 0x0291: 0x8800,
+	0x0295: 0x8800, 0x0297: 0x8800,
+	0x0299: 0x8800,
+	0x029f: 0x8800, 0x02a1: 0x8800,
+	0x02a5: 0x8800, 0x02a9: 0x8800,
+	0x02aa: 0x3621, 0x02ab: 0x3651, 0x02ac: 0x47e4, 0x02ad: 0x3681, 0x02ae: 0x480e, 0x02af: 0x3693,
+	0x02b0: 0x3e5a, 0x02b1: 0x8800, 0x02b5: 0x8800,
+	0x02b7: 0x8800, 0x02b9: 0x8800,
+	0x02bf: 0x8800,
+	// Block 0xb, offset 0x2c0
+	0x02c1: 0x8800, 0x02c5: 0x8800,
+	0x02c9: 0x8800, 0x02ca: 0x4826, 0x02cb: 0x4844,
+	0x02cc: 0x36b1, 0x02cd: 0x36c9, 0x02ce: 0x485c, 0x02d0: 0x01be, 0x02d1: 0x01d0,
+	0x02d2: 0x01ac, 0x02d3: 0x42f2, 0x02d4: 0x42f8, 0x02d5: 0x01fa, 0x02d6: 0x01e8,
+	0x02f0: 0x01d6, 0x02f1: 0x01eb, 0x02f2: 0x01ee, 0x02f4: 0x0188, 0x02f5: 0x01c7,
+	0x02f9: 0x01a6,
+	// Block 0xc, offset 0x300
+	0x0300: 0x370b, 0x0301: 0x3717, 0x0303: 0x3705,
+	0x0306: 0x8800, 0x0307: 0x36f3,
+	0x030c: 0x3747, 0x030d: 0x372f, 0x030e: 0x3759, 0x0310: 0x8800,
+	0x0313: 0x8800, 0x0315: 0x8800, 0x0316: 0x8800, 0x0317: 0x8800,
+	0x0318: 0x8800, 0x0319: 0x373b, 0x031a: 0x8800,
+	0x031e: 0x8800, 0x0323: 0x8800,
+	0x0327: 0x8800,
+	0x032b: 0x8800, 0x032d: 0x8800,
+	0x0330: 0x8800, 0x0333: 0x8800, 0x0335: 0x8800,
+	0x0336: 0x8800, 0x0337: 0x8800, 0x0338: 0x8800, 0x0339: 0x37bf, 0x033a: 0x8800,
+	0x033e: 0x8800,
+	// Block 0xd, offset 0x340
+	0x0341: 0x371d, 0x0342: 0x37a1,
+	0x0350: 0x36f9, 0x0351: 0x377d,
+	0x0352: 0x36ff, 0x0353: 0x3783, 0x0356: 0x3711, 0x0357: 0x3795,
+	0x0358: 0x8800, 0x0359: 0x8800, 0x035a: 0x3813, 0x035b: 0x3819, 0x035c: 0x3723, 0x035d: 0x37a7,
+	0x035e: 0x3729, 0x035f: 0x37ad, 0x0362: 0x3735, 0x0363: 0x37b9,
+	0x0364: 0x3741, 0x0365: 0x37c5, 0x0366: 0x374d, 0x0367: 0x37d1, 0x0368: 0x8800, 0x0369: 0x8800,
+	0x036a: 0x381f, 0x036b: 0x3825, 0x036c: 0x3777, 0x036d: 0x37fb, 0x036e: 0x3753, 0x036f: 0x37d7,
+	0x0370: 0x375f, 0x0371: 0x37e3, 0x0372: 0x3765, 0x0373: 0x37e9, 0x0374: 0x376b, 0x0375: 0x37ef,
+	0x0378: 0x3771, 0x0379: 0x37f5,
+	// Block 0xe, offset 0x380
+	0x0387: 0x1ea3,
+	0x0391: 0x80dc,
+	0x0392: 0x80e6, 0x0393: 0x80e6, 0x0394: 0x80e6, 0x0395: 0x80e6, 0x0396: 0x80dc, 0x0397: 0x80e6,
+	0x0398: 0x80e6, 0x0399: 0x80e6, 0x039a: 0x80de, 0x039b: 0x80dc, 0x039c: 0x80e6, 0x039d: 0x80e6,
+	0x039e: 0x80e6, 0x039f: 0x80e6, 0x03a0: 0x80e6, 0x03a1: 0x80e6, 0x03a2: 0x80dc, 0x03a3: 0x80dc,
+	0x03a4: 0x80dc, 0x03a5: 0x80dc, 0x03a6: 0x80dc, 0x03a7: 0x80dc, 0x03a8: 0x80e6, 0x03a9: 0x80e6,
+	0x03aa: 0x80dc, 0x03ab: 0x80e6, 0x03ac: 0x80e6, 0x03ad: 0x80de, 0x03ae: 0x80e4, 0x03af: 0x80e6,
+	0x03b0: 0x800a, 0x03b1: 0x800b, 0x03b2: 0x800c, 0x03b3: 0x800d, 0x03b4: 0x800e, 0x03b5: 0x800f,
+	0x03b6: 0x8010, 0x03b7: 0x8011, 0x03b8: 0x8012, 0x03b9: 0x8013, 0x03ba: 0x8013, 0x03bb: 0x8014,
+	0x03bc: 0x8015, 0x03bd: 0x8016, 0x03bf: 0x8017,
+	// Block 0xf, offset 0x3c0
+	0x03c8: 0x8800, 0x03ca: 0x8800, 0x03cb: 0x801b,
+	0x03cc: 0x801c, 0x03cd: 0x801d, 0x03ce: 0x801e, 0x03cf: 0x801f, 0x03d0: 0x8020, 0x03d1: 0x8021,
+	0x03d2: 0x8022, 0x03d3: 0x86e6, 0x03d4: 0x86e6, 0x03d5: 0x86dc, 0x03d6: 0x80dc, 0x03d7: 0x80e6,
+	0x03d8: 0x80e6, 0x03d9: 0x80e6, 0x03da: 0x80e6, 0x03db: 0x80e6, 0x03dc: 0x80dc, 0x03dd: 0x80e6,
+	0x03de: 0x80e6, 0x03df: 0x80dc,
+	0x03f0: 0x8023, 0x03f5: 0x1ec6,
+	0x03f6: 0x2155, 0x03f7: 0x2191, 0x03f8: 0x218c,
+	// Block 0x10, offset 0x400
+	0x0405: 0x8800,
+	0x0406: 0x1946, 0x0407: 0x8800, 0x0408: 0x194d, 0x0409: 0x8800, 0x040a: 0x1954, 0x040b: 0x8800,
+	0x040c: 0x195b, 0x040d: 0x8800, 0x040e: 0x1962, 0x0411: 0x8800,
+	0x0412: 0x1969,
+	0x0434: 0x8007, 0x0435: 0x8600,
+	0x043a: 0x8800, 0x043b: 0x1970,
+	0x043c: 0x8800, 0x043d: 0x1977, 0x043e: 0x8800, 0x043f: 0x8800,
+	// Block 0x11, offset 0x440
+	0x0440: 0x0069, 0x0441: 0x006b, 0x0442: 0x006f, 0x0443: 0x0083, 0x0444: 0x00f8, 0x0445: 0x00fb,
+	0x0446: 0x0485, 0x0447: 0x0085, 0x0448: 0x0089, 0x0449: 0x008b, 0x044a: 0x0107, 0x044b: 0x010a,
+	0x044c: 0x010d, 0x044d: 0x008f, 0x044f: 0x0097, 0x0450: 0x009b, 0x0451: 0x00e3,
+	0x0452: 0x009f, 0x0453: 0x0101, 0x0454: 0x0489, 0x0455: 0x048d, 0x0456: 0x00a1, 0x0457: 0x00a9,
+	0x0458: 0x00ab, 0x0459: 0x0495, 0x045a: 0x012b, 0x045b: 0x00ad, 0x045c: 0x0499, 0x045d: 0x01be,
+	0x045e: 0x01c1, 0x045f: 0x01c4, 0x0460: 0x01fa, 0x0461: 0x01fd, 0x0462: 0x0093, 0x0463: 0x00a5,
+	0x0464: 0x00ab, 0x0465: 0x00ad, 0x0466: 0x01be, 0x0467: 0x01c1, 0x0468: 0x01eb, 0x0469: 0x01fa,
+	0x046a: 0x01fd,
+	0x0478: 0x020c,
+	// Block 0x12, offset 0x480
+	0x049b: 0x00fe, 0x049c: 0x0087, 0x049d: 0x0104,
+	0x049e: 0x00d7, 0x049f: 0x010d, 0x04a0: 0x008d, 0x04a1: 0x0110, 0x04a2: 0x0113, 0x04a3: 0x0119,
+	0x04a4: 0x011f, 0x04a5: 0x0122, 0x04a6: 0x0125, 0x04a7: 0x049d, 0x04a8: 0x016a, 0x04a9: 0x0128,
+	0x04aa: 0x04a1, 0x04ab: 0x016d, 0x04ac: 0x0131, 0x04ad: 0x012e, 0x04ae: 0x0134, 0x04af: 0x0137,
+	0x04b0: 0x013a, 0x04b1: 0x013d, 0x04b2: 0x0140, 0x04b3: 0x014c, 0x04b4: 0x014f, 0x04b5: 0x00ef,
+	0x04b6: 0x0152, 0x04b7: 0x0155, 0x04b8: 0x0491, 0x04b9: 0x0158, 0x04ba: 0x015b, 0x04bb: 0x00b5,
+	0x04bc: 0x015e, 0x04bd: 0x0161, 0x04be: 0x0164, 0x04bf: 0x01d0,
+	// Block 0x13, offset 0x4c0
+	0x04c0: 0x2f81, 0x04c1: 0x328d, 0x04c2: 0x2f8b, 0x04c3: 0x3297, 0x04c4: 0x2f90, 0x04c5: 0x329c,
+	0x04c6: 0x2f95, 0x04c7: 0x32a1, 0x04c8: 0x38b6, 0x04c9: 0x3a45, 0x04ca: 0x2fae, 0x04cb: 0x32ba,
+	0x04cc: 0x2fb8, 0x04cd: 0x32c4, 0x04ce: 0x2fc7, 0x04cf: 0x32d3, 0x04d0: 0x2fbd, 0x04d1: 0x32c9,
+	0x04d2: 0x2fc2, 0x04d3: 0x32ce, 0x04d4: 0x38d9, 0x04d5: 0x3a68, 0x04d6: 0x38e0, 0x04d7: 0x3a6f,
+	0x04d8: 0x3003, 0x04d9: 0x330f, 0x04da: 0x3008, 0x04db: 0x3314, 0x04dc: 0x38ee, 0x04dd: 0x3a7d,
+	0x04de: 0x300d, 0x04df: 0x3319, 0x04e0: 0x301c, 0x04e1: 0x3328, 0x04e2: 0x303a, 0x04e3: 0x3346,
+	0x04e4: 0x3049, 0x04e5: 0x3355, 0x04e6: 0x303f, 0x04e7: 0x334b, 0x04e8: 0x304e, 0x04e9: 0x335a,
+	0x04ea: 0x3053, 0x04eb: 0x335f, 0x04ec: 0x3099, 0x04ed: 0x33a5, 0x04ee: 0x38f5, 0x04ef: 0x3a84,
+	0x04f0: 0x30a3, 0x04f1: 0x33b4, 0x04f2: 0x30ad, 0x04f3: 0x33be, 0x04f4: 0x30b7, 0x04f5: 0x33c8,
+	0x04f6: 0x46aa, 0x04f7: 0x473b, 0x04f8: 0x38fc, 0x04f9: 0x3a8b, 0x04fa: 0x30d0, 0x04fb: 0x33e1,
+	0x04fc: 0x30cb, 0x04fd: 0x33dc, 0x04fe: 0x30d5, 0x04ff: 0x33e6,
+	// Block 0x14, offset 0x500
+	0x0500: 0x30da, 0x0501: 0x33eb, 0x0502: 0x30df, 0x0503: 0x33f0, 0x0504: 0x30f3, 0x0505: 0x3404,
+	0x0506: 0x30fd, 0x0507: 0x340e, 0x0508: 0x310c, 0x0509: 0x341d, 0x050a: 0x3107, 0x050b: 0x3418,
+	0x050c: 0x391f, 0x050d: 0x3aae, 0x050e: 0x392d, 0x050f: 0x3abc, 0x0510: 0x3934, 0x0511: 0x3ac3,
+	0x0512: 0x393b, 0x0513: 0x3aca, 0x0514: 0x3139, 0x0515: 0x344a, 0x0516: 0x313e, 0x0517: 0x344f,
+	0x0518: 0x3148, 0x0519: 0x3459, 0x051a: 0x46d7, 0x051b: 0x4768, 0x051c: 0x3981, 0x051d: 0x3b10,
+	0x051e: 0x3161, 0x051f: 0x3472, 0x0520: 0x316b, 0x0521: 0x347c, 0x0522: 0x46e6, 0x0523: 0x4777,
+	0x0524: 0x3988, 0x0525: 0x3b17, 0x0526: 0x398f, 0x0527: 0x3b1e, 0x0528: 0x3996, 0x0529: 0x3b25,
+	0x052a: 0x317a, 0x052b: 0x348b, 0x052c: 0x3184, 0x052d: 0x349a, 0x052e: 0x3198, 0x052f: 0x34ae,
+	0x0530: 0x3193, 0x0531: 0x34a9, 0x0532: 0x31d4, 0x0533: 0x34ea, 0x0534: 0x31e3, 0x0535: 0x34f9,
+	0x0536: 0x31de, 0x0537: 0x34f4, 0x0538: 0x399d, 0x0539: 0x3b2c, 0x053a: 0x39a4, 0x053b: 0x3b33,
+	0x053c: 0x31e8, 0x053d: 0x34fe, 0x053e: 0x31ed, 0x053f: 0x3503,
+	// Block 0x15, offset 0x540
+	0x0540: 0x31f2, 0x0541: 0x3508, 0x0542: 0x31f7, 0x0543: 0x350d, 0x0544: 0x3206, 0x0545: 0x351c,
+	0x0546: 0x3201, 0x0547: 0x3517, 0x0548: 0x320b, 0x0549: 0x3526, 0x054a: 0x3210, 0x054b: 0x352b,
+	0x054c: 0x3215, 0x054d: 0x3530, 0x054e: 0x3233, 0x054f: 0x354e, 0x0550: 0x324c, 0x0551: 0x356c,
+	0x0552: 0x325b, 0x0553: 0x357b, 0x0554: 0x3260, 0x0555: 0x3580, 0x0556: 0x3364, 0x0557: 0x3490,
+	0x0558: 0x3521, 0x0559: 0x355d, 0x055a: 0x1d22, 0x055b: 0x42bd,
+	0x0560: 0x4687, 0x0561: 0x4718, 0x0562: 0x2f6d, 0x0563: 0x3279,
+	0x0564: 0x3862, 0x0565: 0x39f1, 0x0566: 0x385b, 0x0567: 0x39ea, 0x0568: 0x3870, 0x0569: 0x39ff,
+	0x056a: 0x3869, 0x056b: 0x39f8, 0x056c: 0x38a8, 0x056d: 0x3a37, 0x056e: 0x387e, 0x056f: 0x3a0d,
+	0x0570: 0x3877, 0x0571: 0x3a06, 0x0572: 0x388c, 0x0573: 0x3a1b, 0x0574: 0x3885, 0x0575: 0x3a14,
+	0x0576: 0x38af, 0x0577: 0x3a3e, 0x0578: 0x469b, 0x0579: 0x472c, 0x057a: 0x2fea, 0x057b: 0x32f6,
+	0x057c: 0x2fd6, 0x057d: 0x32e2, 0x057e: 0x38c4, 0x057f: 0x3a53,
+	// Block 0x16, offset 0x580
+	0x0580: 0x38bd, 0x0581: 0x3a4c, 0x0582: 0x38d2, 0x0583: 0x3a61, 0x0584: 0x38cb, 0x0585: 0x3a5a,
+	0x0586: 0x38e7, 0x0587: 0x3a76, 0x0588: 0x307b, 0x0589: 0x3387, 0x058a: 0x308f, 0x058b: 0x339b,
+	0x058c: 0x46cd, 0x058d: 0x475e, 0x058e: 0x3120, 0x058f: 0x3431, 0x0590: 0x390a, 0x0591: 0x3a99,
+	0x0592: 0x3903, 0x0593: 0x3a92, 0x0594: 0x3918, 0x0595: 0x3aa7, 0x0596: 0x3911, 0x0597: 0x3aa0,
+	0x0598: 0x3973, 0x0599: 0x3b02, 0x059a: 0x3957, 0x059b: 0x3ae6, 0x059c: 0x3950, 0x059d: 0x3adf,
+	0x059e: 0x3965, 0x059f: 0x3af4, 0x05a0: 0x395e, 0x05a1: 0x3aed, 0x05a2: 0x396c, 0x05a3: 0x3afb,
+	0x05a4: 0x31cf, 0x05a5: 0x34e5, 0x05a6: 0x31b1, 0x05a7: 0x34c7, 0x05a8: 0x39ce, 0x05a9: 0x3b5d,
+	0x05aa: 0x39c7, 0x05ab: 0x3b56, 0x05ac: 0x39dc, 0x05ad: 0x3b6b, 0x05ae: 0x39d5, 0x05af: 0x3b64,
+	0x05b0: 0x39e3, 0x05b1: 0x3b72, 0x05b2: 0x321a, 0x05b3: 0x3535, 0x05b4: 0x3242, 0x05b5: 0x3562,
+	0x05b6: 0x323d, 0x05b7: 0x3558, 0x05b8: 0x3229, 0x05b9: 0x3544,
+	// Block 0x17, offset 0x5c0
+	0x05c0: 0x47ea, 0x05c1: 0x47f0, 0x05c2: 0x4904, 0x05c3: 0x491c, 0x05c4: 0x490c, 0x05c5: 0x4924,
+	0x05c6: 0x4914, 0x05c7: 0x492c, 0x05c8: 0x4790, 0x05c9: 0x4796, 0x05ca: 0x4874, 0x05cb: 0x488c,
+	0x05cc: 0x487c, 0x05cd: 0x4894, 0x05ce: 0x4884, 0x05cf: 0x489c, 0x05d0: 0x47fc, 0x05d1: 0x4802,
+	0x05d2: 0x3da2, 0x05d3: 0x3db2, 0x05d4: 0x3daa, 0x05d5: 0x3dba,
+	0x05d8: 0x479c, 0x05d9: 0x47a2, 0x05da: 0x3cd2, 0x05db: 0x3ce2, 0x05dc: 0x3cda, 0x05dd: 0x3cea,
+	0x05e0: 0x4814, 0x05e1: 0x481a, 0x05e2: 0x4934, 0x05e3: 0x494c,
+	0x05e4: 0x493c, 0x05e5: 0x4954, 0x05e6: 0x4944, 0x05e7: 0x495c, 0x05e8: 0x47a8, 0x05e9: 0x47ae,
+	0x05ea: 0x48a4, 0x05eb: 0x48bc, 0x05ec: 0x48ac, 0x05ed: 0x48c4, 0x05ee: 0x48b4, 0x05ef: 0x48cc,
+	0x05f0: 0x482c, 0x05f1: 0x4832, 0x05f2: 0x3e02, 0x05f3: 0x3e1a, 0x05f4: 0x3e0a, 0x05f5: 0x3e22,
+	0x05f6: 0x3e12, 0x05f7: 0x3e2a, 0x05f8: 0x47b4, 0x05f9: 0x47ba, 0x05fa: 0x3d02, 0x05fb: 0x3d1a,
+	0x05fc: 0x3d0a, 0x05fd: 0x3d22, 0x05fe: 0x3d12, 0x05ff: 0x3d2a,
+	// Block 0x18, offset 0x600
+	0x0600: 0x4838, 0x0601: 0x483e, 0x0602: 0x3e32, 0x0603: 0x3e42, 0x0604: 0x3e3a, 0x0605: 0x3e4a,
+	0x0608: 0x47c0, 0x0609: 0x47c6, 0x060a: 0x3d32, 0x060b: 0x3d42,
+	0x060c: 0x3d3a, 0x060d: 0x3d4a, 0x0610: 0x484a, 0x0611: 0x4850,
+	0x0612: 0x3e6a, 0x0613: 0x3e82, 0x0614: 0x3e72, 0x0615: 0x3e8a, 0x0616: 0x3e7a, 0x0617: 0x3e92,
+	0x0619: 0x47cc, 0x061b: 0x3d52, 0x061d: 0x3d5a,
+	0x061f: 0x3d62, 0x0620: 0x4862, 0x0621: 0x4868, 0x0622: 0x4964, 0x0623: 0x497c,
+	0x0624: 0x496c, 0x0625: 0x4984, 0x0626: 0x4974, 0x0627: 0x498c, 0x0628: 0x47d2, 0x0629: 0x47d8,
+	0x062a: 0x48d4, 0x062b: 0x48ec, 0x062c: 0x48dc, 0x062d: 0x48f4, 0x062e: 0x48e4, 0x062f: 0x48fc,
+	0x0630: 0x47de, 0x0631: 0x4304, 0x0632: 0x367b, 0x0633: 0x430a, 0x0634: 0x4808, 0x0635: 0x4310,
+	0x0636: 0x368d, 0x0637: 0x4316, 0x0638: 0x36ab, 0x0639: 0x431c, 0x063a: 0x36c3, 0x063b: 0x4322,
+	0x063c: 0x4856, 0x063d: 0x4328,
+	// Block 0x19, offset 0x640
+	0x0640: 0x3d8a, 0x0641: 0x3d92, 0x0642: 0x416e, 0x0643: 0x418c, 0x0644: 0x4178, 0x0645: 0x4196,
+	0x0646: 0x4182, 0x0647: 0x41a0, 0x0648: 0x3cc2, 0x0649: 0x3cca, 0x064a: 0x40ba, 0x064b: 0x40d8,
+	0x064c: 0x40c4, 0x064d: 0x40e2, 0x064e: 0x40ce, 0x064f: 0x40ec, 0x0650: 0x3dd2, 0x0651: 0x3dda,
+	0x0652: 0x41aa, 0x0653: 0x41c8, 0x0654: 0x41b4, 0x0655: 0x41d2, 0x0656: 0x41be, 0x0657: 0x41dc,
+	0x0658: 0x3cf2, 0x0659: 0x3cfa, 0x065a: 0x40f6, 0x065b: 0x4114, 0x065c: 0x4100, 0x065d: 0x411e,
+	0x065e: 0x410a, 0x065f: 0x4128, 0x0660: 0x3eaa, 0x0661: 0x3eb2, 0x0662: 0x41e6, 0x0663: 0x4204,
+	0x0664: 0x41f0, 0x0665: 0x420e, 0x0666: 0x41fa, 0x0667: 0x4218, 0x0668: 0x3d6a, 0x0669: 0x3d72,
+	0x066a: 0x4132, 0x066b: 0x4150, 0x066c: 0x413c, 0x066d: 0x415a, 0x066e: 0x4146, 0x066f: 0x4164,
+	0x0670: 0x366f, 0x0671: 0x3669, 0x0672: 0x3d7a, 0x0673: 0x3675, 0x0674: 0x3d82,
+	0x0676: 0x47f6, 0x0677: 0x3d9a, 0x0678: 0x35df, 0x0679: 0x35d9, 0x067a: 0x35cd, 0x067b: 0x42d4,
+	0x067c: 0x35e5, 0x067d: 0x426d, 0x067e: 0x01d3, 0x067f: 0x426d,
+	// Block 0x1a, offset 0x680
+	0x0680: 0x4286, 0x0681: 0x4468, 0x0682: 0x3dc2, 0x0683: 0x3687, 0x0684: 0x3dca,
+	0x0686: 0x4820, 0x0687: 0x3de2, 0x0688: 0x35eb, 0x0689: 0x42da, 0x068a: 0x35f7, 0x068b: 0x42e0,
+	0x068c: 0x3603, 0x068d: 0x446f, 0x068e: 0x4476, 0x068f: 0x447d, 0x0690: 0x369f, 0x0691: 0x3699,
+	0x0692: 0x3dea, 0x0693: 0x44ca, 0x0696: 0x36a5, 0x0697: 0x3dfa,
+	0x0698: 0x361b, 0x0699: 0x3615, 0x069a: 0x3609, 0x069b: 0x42e6, 0x069d: 0x4484,
+	0x069e: 0x448b, 0x069f: 0x4492, 0x06a0: 0x36d5, 0x06a1: 0x36cf, 0x06a2: 0x3e52, 0x06a3: 0x44d2,
+	0x06a4: 0x36b7, 0x06a5: 0x36bd, 0x06a6: 0x36db, 0x06a7: 0x3e62, 0x06a8: 0x364b, 0x06a9: 0x3645,
+	0x06aa: 0x3639, 0x06ab: 0x42f2, 0x06ac: 0x3633, 0x06ad: 0x445a, 0x06ae: 0x4461, 0x06af: 0x0081,
+	0x06b2: 0x3e9a, 0x06b3: 0x36e1, 0x06b4: 0x3ea2,
+	0x06b6: 0x486e, 0x06b7: 0x3eba, 0x06b8: 0x3627, 0x06b9: 0x42ec, 0x06ba: 0x3657, 0x06bb: 0x42fe,
+	0x06bc: 0x3663, 0x06bd: 0x4240, 0x06be: 0x4272,
+	// Block 0x1b, offset 0x6c0
+	0x06c0: 0x1d1a, 0x06c1: 0x1d1e, 0x06c2: 0x0047, 0x06c3: 0x1d96, 0x06c5: 0x1d2a,
+	0x06c6: 0x1d2e, 0x06c7: 0x00ec, 0x06c9: 0x1d9a, 0x06ca: 0x008f, 0x06cb: 0x0051,
+	0x06cc: 0x0051, 0x06cd: 0x0051, 0x06ce: 0x0091, 0x06cf: 0x00dd, 0x06d0: 0x0053, 0x06d1: 0x0053,
+	0x06d2: 0x0059, 0x06d3: 0x0099, 0x06d5: 0x005d, 0x06d6: 0x1acf,
+	0x06d9: 0x0061, 0x06da: 0x0063, 0x06db: 0x0065, 0x06dc: 0x0065, 0x06dd: 0x0065,
+	0x06e0: 0x1ae1, 0x06e1: 0x1d0a, 0x06e2: 0x1aea,
+	0x06e4: 0x0075, 0x06e6: 0x01b8, 0x06e8: 0x0075,
+	0x06ea: 0x0057, 0x06eb: 0x42b8, 0x06ec: 0x0045, 0x06ed: 0x0047, 0x06ef: 0x008b,
+	0x06f0: 0x004b, 0x06f1: 0x004d, 0x06f3: 0x005b, 0x06f4: 0x009f, 0x06f5: 0x020f,
+	0x06f6: 0x0212, 0x06f7: 0x0215, 0x06f8: 0x0218, 0x06f9: 0x0093, 0x06fb: 0x1cda,
+	0x06fc: 0x01e8, 0x06fd: 0x01c1, 0x06fe: 0x0179, 0x06ff: 0x01a0,
+	// Block 0x1c, offset 0x700
+	0x0700: 0x04d5, 0x0705: 0x0049,
+	0x0706: 0x0089, 0x0707: 0x008b, 0x0708: 0x0093, 0x0709: 0x0095,
+	0x0710: 0x2370, 0x0711: 0x237c,
+	0x0712: 0x2430, 0x0713: 0x2358, 0x0714: 0x23dc, 0x0715: 0x2364, 0x0716: 0x23e2, 0x0717: 0x23fa,
+	0x0718: 0x2406, 0x0719: 0x236a, 0x071a: 0x240c, 0x071b: 0x2376, 0x071c: 0x2400, 0x071d: 0x2412,
+	0x071e: 0x2418, 0x071f: 0x1dfe, 0x0720: 0x0053, 0x0721: 0x1a9c, 0x0722: 0x1ce6, 0x0723: 0x1aa5,
+	0x0724: 0x006d, 0x0725: 0x1aed, 0x0726: 0x1d12, 0x0727: 0x1e8a, 0x0728: 0x1aa8, 0x0729: 0x0071,
+	0x072a: 0x1af9, 0x072b: 0x1d16, 0x072c: 0x0059, 0x072d: 0x0047, 0x072e: 0x0049, 0x072f: 0x005b,
+	0x0730: 0x0093, 0x0731: 0x1b26, 0x0732: 0x1d5a, 0x0733: 0x1b2f, 0x0734: 0x00ad, 0x0735: 0x1ba4,
+	0x0736: 0x1d8e, 0x0737: 0x1e9e, 0x0738: 0x1b32, 0x0739: 0x00b1, 0x073a: 0x1ba7, 0x073b: 0x1d92,
+	0x073c: 0x0099, 0x073d: 0x0087, 0x073e: 0x0089, 0x073f: 0x009b,
+	// Block 0x1d, offset 0x740
+	0x0741: 0x3bf0, 0x0743: 0x8800, 0x0744: 0x3bf7, 0x0745: 0x8800,
+	0x0747: 0x3bfe, 0x0748: 0x8800, 0x0749: 0x3c05,
+	0x074d: 0x8800,
+	0x0760: 0x2f4f, 0x0761: 0x8800, 0x0762: 0x3c13,
+	0x0764: 0x8800, 0x0765: 0x8800,
+	0x076d: 0x3c0c, 0x076e: 0x2f4a, 0x076f: 0x2f54,
+	0x0770: 0x3c1a, 0x0771: 0x3c21, 0x0772: 0x8800, 0x0773: 0x8800, 0x0774: 0x3c28, 0x0775: 0x3c2f,
+	0x0776: 0x8800, 0x0777: 0x8800, 0x0778: 0x3c36, 0x0779: 0x3c3d, 0x077a: 0x8800, 0x077b: 0x8800,
+	0x077c: 0x8800, 0x077d: 0x8800,
+	// Block 0x1e, offset 0x780
+	0x0780: 0x3c44, 0x0781: 0x3c4b, 0x0782: 0x8800, 0x0783: 0x8800, 0x0784: 0x3c60, 0x0785: 0x3c67,
+	0x0786: 0x8800, 0x0787: 0x8800, 0x0788: 0x3c6e, 0x0789: 0x3c75,
+	0x0791: 0x8800,
+	0x0792: 0x8800,
+	0x07a2: 0x8800,
+	0x07a8: 0x8800, 0x07a9: 0x8800,
+	0x07ab: 0x8800, 0x07ac: 0x3c8a, 0x07ad: 0x3c91, 0x07ae: 0x3c98, 0x07af: 0x3c9f,
+	0x07b2: 0x8800, 0x07b3: 0x8800, 0x07b4: 0x8800, 0x07b5: 0x8800,
+	// Block 0x1f, offset 0x7c0
+	0x07e0: 0x0023, 0x07e1: 0x0025, 0x07e2: 0x0027, 0x07e3: 0x0029,
+	0x07e4: 0x002b, 0x07e5: 0x002d, 0x07e6: 0x002f, 0x07e7: 0x0031, 0x07e8: 0x0033, 0x07e9: 0x19c4,
+	0x07ea: 0x19c7, 0x07eb: 0x19ca, 0x07ec: 0x19cd, 0x07ed: 0x19d0, 0x07ee: 0x19d3, 0x07ef: 0x19d6,
+	0x07f0: 0x19d9, 0x07f1: 0x19dc, 0x07f2: 0x19df, 0x07f3: 0x19e8, 0x07f4: 0x1baa, 0x07f5: 0x1bae,
+	0x07f6: 0x1bb2, 0x07f7: 0x1bb6, 0x07f8: 0x1bba, 0x07f9: 0x1bbe, 0x07fa: 0x1bc2, 0x07fb: 0x1bc6,
+	0x07fc: 0x1bca, 0x07fd: 0x1dc2, 0x07fe: 0x1dc7, 0x07ff: 0x1dcc,
+	// Block 0x20, offset 0x800
+	0x0800: 0x1dd1, 0x0801: 0x1dd6, 0x0802: 0x1ddb, 0x0803: 0x1de0, 0x0804: 0x1de5, 0x0805: 0x1dea,
+	0x0806: 0x1def, 0x0807: 0x1df4, 0x0808: 0x19c1, 0x0809: 0x19e5, 0x080a: 0x1a09, 0x080b: 0x1a2d,
+	0x080c: 0x1a51, 0x080d: 0x1a5a, 0x080e: 0x1a60, 0x080f: 0x1a66, 0x0810: 0x1a6c, 0x0811: 0x1ca2,
+	0x0812: 0x1ca6, 0x0813: 0x1caa, 0x0814: 0x1cae, 0x0815: 0x1cb2, 0x0816: 0x1cb6, 0x0817: 0x1cba,
+	0x0818: 0x1cbe, 0x0819: 0x1cc2, 0x081a: 0x1cc6, 0x081b: 0x1cca, 0x081c: 0x1c36, 0x081d: 0x1c3a,
+	0x081e: 0x1c3e, 0x081f: 0x1c42, 0x0820: 0x1c46, 0x0821: 0x1c4a, 0x0822: 0x1c4e, 0x0823: 0x1c52,
+	0x0824: 0x1c56, 0x0825: 0x1c5a, 0x0826: 0x1c5e, 0x0827: 0x1c62, 0x0828: 0x1c66, 0x0829: 0x1c6a,
+	0x082a: 0x1c6e, 0x082b: 0x1c72, 0x082c: 0x1c76, 0x082d: 0x1c7a, 0x082e: 0x1c7e, 0x082f: 0x1c82,
+	0x0830: 0x1c86, 0x0831: 0x1c8a, 0x0832: 0x1c8e, 0x0833: 0x1c92, 0x0834: 0x1c96, 0x0835: 0x1c9a,
+	0x0836: 0x0043, 0x0837: 0x0045, 0x0838: 0x0047, 0x0839: 0x0049, 0x083a: 0x004b, 0x083b: 0x004d,
+	0x083c: 0x004f, 0x083d: 0x0051, 0x083e: 0x0053, 0x083f: 0x0055,
+	// Block 0x21, offset 0x840
+	0x0840: 0x0731, 0x0841: 0x0755, 0x0842: 0x0761, 0x0843: 0x0771, 0x0844: 0x0779, 0x0845: 0x0785,
+	0x0846: 0x078d, 0x0847: 0x0795, 0x0848: 0x07a1, 0x0849: 0x07f5, 0x084a: 0x080d, 0x084b: 0x081d,
+	0x084c: 0x082d, 0x084d: 0x083d, 0x084e: 0x084d, 0x084f: 0x086d, 0x0850: 0x0871, 0x0851: 0x0875,
+	0x0852: 0x08a9, 0x0853: 0x08d1, 0x0854: 0x08e1, 0x0855: 0x08e9, 0x0856: 0x08ed, 0x0857: 0x08f9,
+	0x0858: 0x0915, 0x0859: 0x0919, 0x085a: 0x0931, 0x085b: 0x0935, 0x085c: 0x093d, 0x085d: 0x094d,
+	0x085e: 0x09e9, 0x085f: 0x09fd, 0x0860: 0x0a3d, 0x0861: 0x0a51, 0x0862: 0x0a59, 0x0863: 0x0a5d,
+	0x0864: 0x0a6d, 0x0865: 0x0a89, 0x0866: 0x0ab5, 0x0867: 0x0ac1, 0x0868: 0x0ae1, 0x0869: 0x0aed,
+	0x086a: 0x0af1, 0x086b: 0x0af5, 0x086c: 0x0b0d, 0x086d: 0x0b11, 0x086e: 0x0b3d, 0x086f: 0x0b49,
+	0x0870: 0x0b51, 0x0871: 0x0b59, 0x0872: 0x0b69, 0x0873: 0x0b71, 0x0874: 0x0b79, 0x0875: 0x0ba5,
+	0x0876: 0x0ba9, 0x0877: 0x0bb1, 0x0878: 0x0bb5, 0x0879: 0x0bbd, 0x087a: 0x0bc5, 0x087b: 0x0bd5,
+	0x087c: 0x0bf1, 0x087d: 0x0c69, 0x087e: 0x0c7d, 0x087f: 0x0c81,
+	// Block 0x22, offset 0x880
+	0x0880: 0x0d01, 0x0881: 0x0d05, 0x0882: 0x0d19, 0x0883: 0x0d1d, 0x0884: 0x0d25, 0x0885: 0x0d2d,
+	0x0886: 0x0d35, 0x0887: 0x0d41, 0x0888: 0x0d69, 0x0889: 0x0d79, 0x088a: 0x0d8d, 0x088b: 0x0dfd,
+	0x088c: 0x0e09, 0x088d: 0x0e19, 0x088e: 0x0e25, 0x088f: 0x0e31, 0x0890: 0x0e39, 0x0891: 0x0e3d,
+	0x0892: 0x0e41, 0x0893: 0x0e45, 0x0894: 0x0e49, 0x0895: 0x0f01, 0x0896: 0x0f49, 0x0897: 0x0f55,
+	0x0898: 0x0f59, 0x0899: 0x0f5d, 0x089a: 0x0f61, 0x089b: 0x0f69, 0x089c: 0x0f6d, 0x089d: 0x0f81,
+	0x089e: 0x0f9d, 0x089f: 0x0fa5, 0x08a0: 0x0fe5, 0x08a1: 0x0fe9, 0x08a2: 0x0ff1, 0x08a3: 0x0ff5,
+	0x08a4: 0x0ffd, 0x08a5: 0x1001, 0x08a6: 0x1025, 0x08a7: 0x1029, 0x08a8: 0x1045, 0x08a9: 0x1049,
+	0x08aa: 0x104d, 0x08ab: 0x1051, 0x08ac: 0x1065, 0x08ad: 0x1089, 0x08ae: 0x108d, 0x08af: 0x1091,
+	0x08b0: 0x10b5, 0x08b1: 0x10f5, 0x08b2: 0x10f9, 0x08b3: 0x1119, 0x08b4: 0x1129, 0x08b5: 0x1131,
+	0x08b6: 0x1151, 0x08b7: 0x1175, 0x08b8: 0x11b9, 0x08b9: 0x11c1, 0x08ba: 0x11d5, 0x08bb: 0x11e1,
+	0x08bc: 0x11e9, 0x08bd: 0x11f1, 0x08be: 0x11f5, 0x08bf: 0x11f9,
+	// Block 0x23, offset 0x8c0
+	0x08c0: 0x1211, 0x08c1: 0x1215, 0x08c2: 0x1231, 0x08c3: 0x1239, 0x08c4: 0x1241, 0x08c5: 0x1245,
+	0x08c6: 0x1251, 0x08c7: 0x1259, 0x08c8: 0x125d, 0x08c9: 0x1261, 0x08ca: 0x1269, 0x08cb: 0x126d,
+	0x08cc: 0x130d, 0x08cd: 0x1321, 0x08ce: 0x1355, 0x08cf: 0x1359, 0x08d0: 0x1361, 0x08d1: 0x138d,
+	0x08d2: 0x1395, 0x08d3: 0x139d, 0x08d4: 0x13a5, 0x08d5: 0x13e1, 0x08d6: 0x13e5, 0x08d7: 0x13ed,
+	0x08d8: 0x13f1, 0x08d9: 0x13f5, 0x08da: 0x1421, 0x08db: 0x1425, 0x08dc: 0x142d, 0x08dd: 0x1441,
+	0x08de: 0x1445, 0x08df: 0x1461, 0x08e0: 0x1469, 0x08e1: 0x146d, 0x08e2: 0x1491, 0x08e3: 0x14b1,
+	0x08e4: 0x14c1, 0x08e5: 0x14c5, 0x08e6: 0x14cd, 0x08e7: 0x14f9, 0x08e8: 0x14fd, 0x08e9: 0x150d,
+	0x08ea: 0x1531, 0x08eb: 0x153d, 0x08ec: 0x154d, 0x08ed: 0x1565, 0x08ee: 0x156d, 0x08ef: 0x1571,
+	0x08f0: 0x1575, 0x08f1: 0x1579, 0x08f2: 0x1585, 0x08f3: 0x1589, 0x08f4: 0x1591, 0x08f5: 0x15ad,
+	0x08f6: 0x15b1, 0x08f7: 0x15b5, 0x08f8: 0x15cd, 0x08f9: 0x15d1, 0x08fa: 0x15d9, 0x08fb: 0x15ed,
+	0x08fc: 0x15f1, 0x08fd: 0x15f5, 0x08fe: 0x15fd, 0x08ff: 0x1601,
+	// Block 0x24, offset 0x900
+	0x0906: 0x8800, 0x090b: 0x8800,
+	0x090c: 0x3ef2, 0x090d: 0x8800, 0x090e: 0x3efa, 0x090f: 0x8800, 0x0910: 0x3f02, 0x0911: 0x8800,
+	0x0912: 0x3f0a, 0x0913: 0x8800, 0x0914: 0x3f12, 0x0915: 0x8800, 0x0916: 0x3f1a, 0x0917: 0x8800,
+	0x0918: 0x3f22, 0x0919: 0x8800, 0x091a: 0x3f2a, 0x091b: 0x8800, 0x091c: 0x3f32, 0x091d: 0x8800,
+	0x091e: 0x3f3a, 0x091f: 0x8800, 0x0920: 0x3f42, 0x0921: 0x8800, 0x0922: 0x3f4a,
+	0x0924: 0x8800, 0x0925: 0x3f52, 0x0926: 0x8800, 0x0927: 0x3f5a, 0x0928: 0x8800, 0x0929: 0x3f62,
+	0x092f: 0x8800,
+	0x0930: 0x3f6a, 0x0931: 0x3f72, 0x0932: 0x8800, 0x0933: 0x3f7a, 0x0934: 0x3f82, 0x0935: 0x8800,
+	0x0936: 0x3f8a, 0x0937: 0x3f92, 0x0938: 0x8800, 0x0939: 0x3f9a, 0x093a: 0x3fa2, 0x093b: 0x8800,
+	0x093c: 0x3faa, 0x093d: 0x3fb2,
+	// Block 0x25, offset 0x940
+	0x0954: 0x3eea,
+	0x0959: 0x8608, 0x095a: 0x8608, 0x095b: 0x42c2, 0x095c: 0x42c8, 0x095d: 0x8800,
+	0x095e: 0x3fba, 0x095f: 0x285f,
+	0x0966: 0x8800,
+	0x096b: 0x8800, 0x096c: 0x3fca, 0x096d: 0x8800, 0x096e: 0x3fd2, 0x096f: 0x8800,
+	0x0970: 0x3fda, 0x0971: 0x8800, 0x0972: 0x3fe2, 0x0973: 0x8800, 0x0974: 0x3fea, 0x0975: 0x8800,
+	0x0976: 0x3ff2, 0x0977: 0x8800, 0x0978: 0x3ffa, 0x0979: 0x8800, 0x097a: 0x4002, 0x097b: 0x8800,
+	0x097c: 0x400a, 0x097d: 0x8800, 0x097e: 0x4012, 0x097f: 0x8800,
+	// Block 0x26, offset 0x980
+	0x0980: 0x401a, 0x0981: 0x8800, 0x0982: 0x4022, 0x0984: 0x8800, 0x0985: 0x402a,
+	0x0986: 0x8800, 0x0987: 0x4032, 0x0988: 0x8800, 0x0989: 0x403a,
+	0x098f: 0x8800, 0x0990: 0x4042, 0x0991: 0x404a,
+	0x0992: 0x8800, 0x0993: 0x4052, 0x0994: 0x405a, 0x0995: 0x8800, 0x0996: 0x4062, 0x0997: 0x406a,
+	0x0998: 0x8800, 0x0999: 0x4072, 0x099a: 0x407a, 0x099b: 0x8800, 0x099c: 0x4082, 0x099d: 0x408a,
+	0x09af: 0x8800,
+	0x09b0: 0x8800, 0x09b1: 0x8800, 0x09b2: 0x8800, 0x09b4: 0x3fc2,
+	0x09b7: 0x4092, 0x09b8: 0x409a, 0x09b9: 0x40a2, 0x09ba: 0x40aa,
+	0x09bd: 0x8800, 0x09be: 0x40b2, 0x09bf: 0x2874,
+	// Block 0x27, offset 0x9c0
+	0x09c0: 0x03a9, 0x09c1: 0x03ad, 0x09c2: 0x047d, 0x09c3: 0x0481, 0x09c4: 0x03b1, 0x09c5: 0x03b5,
+	0x09c6: 0x03b9, 0x09c7: 0x0415, 0x09c8: 0x0419, 0x09c9: 0x041d, 0x09ca: 0x0421, 0x09cb: 0x0425,
+	0x09cc: 0x0429, 0x09cd: 0x042d, 0x09ce: 0x0431,
+	0x09d2: 0x0731, 0x09d3: 0x078d, 0x09d4: 0x073d, 0x09d5: 0x09ed, 0x09d6: 0x0741, 0x09d7: 0x0759,
+	0x09d8: 0x0745, 0x09d9: 0x1005, 0x09da: 0x0779, 0x09db: 0x074d, 0x09dc: 0x0735, 0x09dd: 0x0a71,
+	0x09de: 0x0a01, 0x09df: 0x07a1,
+	// Block 0x28, offset 0xa00
+	0x0a00: 0x2196, 0x0a01: 0x219c, 0x0a02: 0x21a2, 0x0a03: 0x21a8, 0x0a04: 0x21ae, 0x0a05: 0x21b4,
+	0x0a06: 0x21ba, 0x0a07: 0x21c0, 0x0a08: 0x21c6, 0x0a09: 0x21cc, 0x0a0a: 0x21d2, 0x0a0b: 0x21d8,
+	0x0a0c: 0x21de, 0x0a0d: 0x21e4, 0x0a0e: 0x28d1, 0x0a0f: 0x28da, 0x0a10: 0x28e3, 0x0a11: 0x28ec,
+	0x0a12: 0x28f5, 0x0a13: 0x28fe, 0x0a14: 0x2907, 0x0a15: 0x2910, 0x0a16: 0x2919, 0x0a17: 0x292b,
+	0x0a18: 0x2934, 0x0a19: 0x293d, 0x0a1a: 0x2946, 0x0a1b: 0x294f, 0x0a1c: 0x2922, 0x0a1d: 0x2d74,
+	0x0a1e: 0x2ca5, 0x0a20: 0x21ea, 0x0a21: 0x2202, 0x0a22: 0x21f6, 0x0a23: 0x224a,
+	0x0a24: 0x2208, 0x0a25: 0x2226, 0x0a26: 0x21f0, 0x0a27: 0x2220, 0x0a28: 0x21fc, 0x0a29: 0x2232,
+	0x0a2a: 0x2262, 0x0a2b: 0x2280, 0x0a2c: 0x227a, 0x0a2d: 0x226e, 0x0a2e: 0x22bc, 0x0a2f: 0x2250,
+	0x0a30: 0x225c, 0x0a31: 0x2274, 0x0a32: 0x2268, 0x0a33: 0x2292, 0x0a34: 0x223e, 0x0a35: 0x2286,
+	0x0a36: 0x22b0, 0x0a37: 0x2298, 0x0a38: 0x222c, 0x0a39: 0x220e, 0x0a3a: 0x2244, 0x0a3b: 0x2256,
+	0x0a3c: 0x228c, 0x0a3d: 0x2214, 0x0a3e: 0x22b6, 0x0a3f: 0x2238,
+	// Block 0x29, offset 0xa40
+	0x0a40: 0x229e, 0x0a41: 0x221a, 0x0a42: 0x22a4, 0x0a43: 0x22aa, 0x0a44: 0x09a1, 0x0a45: 0x0b75,
+	0x0a46: 0x0d19, 0x0a47: 0x1139,
+	0x0a50: 0x1d06, 0x0a51: 0x19eb,
+	0x0a52: 0x19ee, 0x0a53: 0x19f1, 0x0a54: 0x19f4, 0x0a55: 0x19f7, 0x0a56: 0x19fa, 0x0a57: 0x19fd,
+	0x0a58: 0x1a00, 0x0a59: 0x1a03, 0x0a5a: 0x1a0c, 0x0a5b: 0x1a0f, 0x0a5c: 0x1a12, 0x0a5d: 0x1a15,
+	0x0a5e: 0x1a18, 0x0a5f: 0x1a1b, 0x0a60: 0x030d, 0x0a61: 0x0315, 0x0a62: 0x0319, 0x0a63: 0x0321,
+	0x0a64: 0x0325, 0x0a65: 0x0329, 0x0a66: 0x0331, 0x0a67: 0x0339, 0x0a68: 0x033d, 0x0a69: 0x0345,
+	0x0a6a: 0x0349, 0x0a6b: 0x034d, 0x0a6c: 0x0351, 0x0a6d: 0x0355, 0x0a6e: 0x27d3, 0x0a6f: 0x27da,
+	0x0a70: 0x27e1, 0x0a71: 0x27e8, 0x0a72: 0x27ef, 0x0a73: 0x27f6, 0x0a74: 0x27fd, 0x0a75: 0x2804,
+	0x0a76: 0x2812, 0x0a77: 0x2819, 0x0a78: 0x2820, 0x0a79: 0x2827, 0x0a7a: 0x282e, 0x0a7b: 0x2835,
+	0x0a7c: 0x2cc4, 0x0a7d: 0x2b39, 0x0a7e: 0x280b,
+	// Block 0x2a, offset 0xa80
+	0x0a80: 0x0731, 0x0a81: 0x078d, 0x0a82: 0x073d, 0x0a83: 0x09ed, 0x0a84: 0x0791, 0x0a85: 0x0821,
+	0x0a86: 0x0739, 0x0a87: 0x081d, 0x0a88: 0x077d, 0x0a89: 0x08f9, 0x0a8a: 0x0d79, 0x0a8b: 0x0f01,
+	0x0a8c: 0x0e49, 0x0a8d: 0x0d8d, 0x0a8e: 0x14cd, 0x0a8f: 0x09fd, 0x0a90: 0x0d41, 0x0a91: 0x0dbd,
+	0x0a92: 0x0d7d, 0x0a93: 0x10bd, 0x0a94: 0x096d, 0x0a95: 0x0f75, 0x0a96: 0x13f9, 0x0a97: 0x10d1,
+	0x0a98: 0x08b5, 0x0a99: 0x1101, 0x0a9a: 0x100d, 0x0a9b: 0x0a89, 0x0a9c: 0x1481, 0x0a9d: 0x07f1,
+	0x0a9e: 0x091d, 0x0a9f: 0x0e69, 0x0aa0: 0x1595, 0x0aa1: 0x07b5, 0x0aa2: 0x0845, 0x0aa3: 0x0e0d,
+	0x0aa4: 0x0741, 0x0aa5: 0x0759, 0x0aa6: 0x0745, 0x0aa7: 0x0b4d, 0x0aa8: 0x0961, 0x0aa9: 0x08f1,
+	0x0aaa: 0x0ac9, 0x0aab: 0x0abd, 0x0aac: 0x105d, 0x0aad: 0x07b1, 0x0aae: 0x140d, 0x0aaf: 0x090d,
+	0x0ab0: 0x0a65, 0x0ab1: 0x1a1e, 0x0ab2: 0x1a21, 0x0ab3: 0x1a24, 0x0ab4: 0x1a27, 0x0ab5: 0x1a30,
+	0x0ab6: 0x1a33, 0x0ab7: 0x1a36, 0x0ab8: 0x1a39, 0x0ab9: 0x1a3c, 0x0aba: 0x1a3f, 0x0abb: 0x1a42,
+	0x0abc: 0x1a45, 0x0abd: 0x1a48, 0x0abe: 0x1a4b, 0x0abf: 0x1a54,
+	// Block 0x2b, offset 0xac0
+	0x0ac0: 0x1e08, 0x0ac1: 0x1e17, 0x0ac2: 0x1e26, 0x0ac3: 0x1e35, 0x0ac4: 0x1e44, 0x0ac5: 0x1e53,
+	0x0ac6: 0x1e62, 0x0ac7: 0x1e71, 0x0ac8: 0x1e80, 0x0ac9: 0x22ce, 0x0aca: 0x22e0, 0x0acb: 0x22f2,
+	0x0acc: 0x1a96, 0x0acd: 0x1d46, 0x0ace: 0x1b14, 0x0acf: 0x1cea, 0x0ad0: 0x053d, 0x0ad1: 0x0545,
+	0x0ad2: 0x054d, 0x0ad3: 0x0555, 0x0ad4: 0x055d, 0x0ad5: 0x0561, 0x0ad6: 0x0565, 0x0ad7: 0x0569,
+	0x0ad8: 0x056d, 0x0ad9: 0x0571, 0x0ada: 0x0575, 0x0adb: 0x0579, 0x0adc: 0x057d, 0x0add: 0x0581,
+	0x0ade: 0x0585, 0x0adf: 0x0589, 0x0ae0: 0x058d, 0x0ae1: 0x0595, 0x0ae2: 0x0599, 0x0ae3: 0x059d,
+	0x0ae4: 0x05a1, 0x0ae5: 0x05a5, 0x0ae6: 0x05a9, 0x0ae7: 0x05ad, 0x0ae8: 0x05b1, 0x0ae9: 0x05b5,
+	0x0aea: 0x05b9, 0x0aeb: 0x05bd, 0x0aec: 0x05c1, 0x0aed: 0x05c5, 0x0aee: 0x05c9, 0x0aef: 0x05cd,
+	0x0af0: 0x05d1, 0x0af1: 0x05d5, 0x0af2: 0x05d9, 0x0af3: 0x05e1, 0x0af4: 0x05e9, 0x0af5: 0x05f1,
+	0x0af6: 0x05f5, 0x0af7: 0x05f9, 0x0af8: 0x05fd, 0x0af9: 0x0601, 0x0afa: 0x0605, 0x0afb: 0x0609,
+	0x0afc: 0x060d, 0x0afd: 0x0611, 0x0afe: 0x0615,
+	// Block 0x2c, offset 0xb00
+	0x0b00: 0x2cd4, 0x0b01: 0x2b60, 0x0b02: 0x2ce4, 0x0b03: 0x2a2b, 0x0b04: 0x2ede, 0x0b05: 0x2a35,
+	0x0b06: 0x2a3f, 0x0b07: 0x2f22, 0x0b08: 0x2b6d, 0x0b09: 0x2a49, 0x0b0a: 0x2a53, 0x0b0b: 0x2a5d,
+	0x0b0c: 0x2b94, 0x0b0d: 0x2ba1, 0x0b0e: 0x2b7a, 0x0b0f: 0x2b87, 0x0b10: 0x2eb4, 0x0b11: 0x2bae,
+	0x0b12: 0x2bbb, 0x0b13: 0x2d86, 0x0b14: 0x2866, 0x0b15: 0x2d99, 0x0b16: 0x2dac, 0x0b17: 0x2cf4,
+	0x0b18: 0x2bc8, 0x0b19: 0x2dbf, 0x0b1a: 0x2dd2, 0x0b1b: 0x2bd5, 0x0b1c: 0x2a67, 0x0b1d: 0x2a71,
+	0x0b1e: 0x2ec2, 0x0b1f: 0x2be2, 0x0b20: 0x2d04, 0x0b21: 0x2eef, 0x0b22: 0x2a7b, 0x0b23: 0x2a85,
+	0x0b24: 0x2bef, 0x0b25: 0x2a8f, 0x0b26: 0x2a99, 0x0b27: 0x287b, 0x0b28: 0x2882, 0x0b29: 0x2aa3,
+	0x0b2a: 0x2aad, 0x0b2b: 0x2de5, 0x0b2c: 0x2bfc, 0x0b2d: 0x2d14, 0x0b2e: 0x2df8, 0x0b2f: 0x2c09,
+	0x0b30: 0x2ac1, 0x0b31: 0x2ab7, 0x0b32: 0x2f36, 0x0b33: 0x2c16, 0x0b34: 0x2e0b, 0x0b35: 0x2acb,
+	0x0b36: 0x2d24, 0x0b37: 0x2ad5, 0x0b38: 0x2c30, 0x0b39: 0x2adf, 0x0b3a: 0x2c3d, 0x0b3b: 0x2f00,
+	0x0b3c: 0x2c23, 0x0b3d: 0x2d34, 0x0b3e: 0x2c4a, 0x0b3f: 0x2889,
+	// Block 0x2d, offset 0xb40
+	0x0b40: 0x2f11, 0x0b41: 0x2ae9, 0x0b42: 0x2af3, 0x0b43: 0x2c57, 0x0b44: 0x2afd, 0x0b45: 0x2b07,
+	0x0b46: 0x2b11, 0x0b47: 0x2d44, 0x0b48: 0x2c64, 0x0b49: 0x2890, 0x0b4a: 0x2e1e, 0x0b4b: 0x2ea9,
+	0x0b4c: 0x2d54, 0x0b4d: 0x2c71, 0x0b4e: 0x2ed0, 0x0b4f: 0x2b1b, 0x0b50: 0x2b25, 0x0b51: 0x2c7e,
+	0x0b52: 0x2897, 0x0b53: 0x2c8b, 0x0b54: 0x2d64, 0x0b55: 0x289e, 0x0b56: 0x2e31, 0x0b57: 0x2b2f,
+	0x0b58: 0x1df9, 0x0b59: 0x1e0d, 0x0b5a: 0x1e1c, 0x0b5b: 0x1e2b, 0x0b5c: 0x1e3a, 0x0b5d: 0x1e49,
+	0x0b5e: 0x1e58, 0x0b5f: 0x1e67, 0x0b60: 0x1e76, 0x0b61: 0x1e85, 0x0b62: 0x22d4, 0x0b63: 0x22e6,
+	0x0b64: 0x22f8, 0x0b65: 0x2304, 0x0b66: 0x2310, 0x0b67: 0x231c, 0x0b68: 0x2328, 0x0b69: 0x2334,
+	0x0b6a: 0x2340, 0x0b6b: 0x234c, 0x0b6c: 0x2388, 0x0b6d: 0x2394, 0x0b6e: 0x23a0, 0x0b6f: 0x23ac,
+	0x0b70: 0x23b8, 0x0b71: 0x1d56, 0x0b72: 0x1b08, 0x0b73: 0x1a78, 0x0b74: 0x1d26, 0x0b75: 0x1b89,
+	0x0b76: 0x1b98, 0x0b77: 0x1b0e, 0x0b78: 0x1d3e, 0x0b79: 0x1d42, 0x0b7a: 0x1aa2, 0x0b7b: 0x28ac,
+	0x0b7c: 0x28ba, 0x0b7d: 0x28a5, 0x0b7e: 0x28b3, 0x0b7f: 0x2c98,
+	// Block 0x2e, offset 0xb80
+	0x0b80: 0x1b8c, 0x0b81: 0x1b74, 0x0b82: 0x1da2, 0x0b83: 0x1b5c, 0x0b84: 0x1b35, 0x0b85: 0x1aab,
+	0x0b86: 0x1aba, 0x0b87: 0x1a8a, 0x0b88: 0x1d32, 0x0b89: 0x1e94, 0x0b8a: 0x1b8f, 0x0b8b: 0x1b77,
+	0x0b8c: 0x1da6, 0x0b8d: 0x1db2, 0x0b8e: 0x1b68, 0x0b8f: 0x1b3e, 0x0b90: 0x1a99, 0x0b91: 0x1d5e,
+	0x0b92: 0x1cf2, 0x0b93: 0x1cde, 0x0b94: 0x1d0e, 0x0b95: 0x1db6, 0x0b96: 0x1b6b, 0x0b97: 0x1b0b,
+	0x0b98: 0x1b41, 0x0b99: 0x1b20, 0x0b9a: 0x1b83, 0x0b9b: 0x1dba, 0x0b9c: 0x1b6e, 0x0b9d: 0x1b02,
+	0x0b9e: 0x1b44, 0x0b9f: 0x1d7e, 0x0ba0: 0x1d36, 0x0ba1: 0x1b56, 0x0ba2: 0x1d66, 0x0ba3: 0x1d82,
+	0x0ba4: 0x1d3a, 0x0ba5: 0x1b59, 0x0ba6: 0x1d6a, 0x0ba7: 0x242a, 0x0ba8: 0x243e, 0x0ba9: 0x1ad8,
+	0x0baa: 0x1d62, 0x0bab: 0x1cf6, 0x0bac: 0x1ce2, 0x0bad: 0x1d8a, 0x0bae: 0x28c1, 0x0baf: 0x2958,
+	0x0bb0: 0x1b9b, 0x0bb1: 0x1b86, 0x0bb2: 0x1dbe, 0x0bb3: 0x1b71, 0x0bb4: 0x1b92, 0x0bb5: 0x1b7a,
+	0x0bb6: 0x1daa, 0x0bb7: 0x1b5f, 0x0bb8: 0x1b38, 0x0bb9: 0x1ac3, 0x0bba: 0x1b95, 0x0bbb: 0x1b7d,
+	0x0bbc: 0x1dae, 0x0bbd: 0x1b62, 0x0bbe: 0x1b3b, 0x0bbf: 0x1ac6,
+	// Block 0x2f, offset 0xbc0
+	0x0bc0: 0x1d6e, 0x0bc1: 0x1cfa, 0x0bc2: 0x1e8f, 0x0bc3: 0x1a7b, 0x0bc4: 0x1afc, 0x0bc5: 0x1aff,
+	0x0bc6: 0x2437, 0x0bc7: 0x1cd6, 0x0bc8: 0x1b05, 0x0bc9: 0x1a8d, 0x0bca: 0x1b23, 0x0bcb: 0x1a90,
+	0x0bcc: 0x1b2c, 0x0bcd: 0x1aae, 0x0bce: 0x1ab1, 0x0bcf: 0x1b47, 0x0bd0: 0x1b4d, 0x0bd1: 0x1b50,
+	0x0bd2: 0x1d72, 0x0bd3: 0x1b53, 0x0bd4: 0x1b65, 0x0bd5: 0x1d7a, 0x0bd6: 0x1d86, 0x0bd7: 0x1ad2,
+	0x0bd8: 0x1e99, 0x0bd9: 0x1cfe, 0x0bda: 0x1ad5, 0x0bdb: 0x1b9e, 0x0bdc: 0x1ae7, 0x0bdd: 0x1af6,
+	0x0bde: 0x2424, 0x0bdf: 0x241e, 0x0be0: 0x1e03, 0x0be1: 0x1e12, 0x0be2: 0x1e21, 0x0be3: 0x1e30,
+	0x0be4: 0x1e3f, 0x0be5: 0x1e4e, 0x0be6: 0x1e5d, 0x0be7: 0x1e6c, 0x0be8: 0x1e7b, 0x0be9: 0x22c8,
+	0x0bea: 0x22da, 0x0beb: 0x22ec, 0x0bec: 0x22fe, 0x0bed: 0x230a, 0x0bee: 0x2316, 0x0bef: 0x2322,
+	0x0bf0: 0x232e, 0x0bf1: 0x233a, 0x0bf2: 0x2346, 0x0bf3: 0x2382, 0x0bf4: 0x238e, 0x0bf5: 0x239a,
+	0x0bf6: 0x23a6, 0x0bf7: 0x23b2, 0x0bf8: 0x23be, 0x0bf9: 0x23c4, 0x0bfa: 0x23ca, 0x0bfb: 0x23d0,
+	0x0bfc: 0x23d6, 0x0bfd: 0x23e8, 0x0bfe: 0x23ee, 0x0bff: 0x1d52,
+	// Block 0x30, offset 0xc00
+	0x0c00: 0x13e9, 0x0c01: 0x0d6d, 0x0c02: 0x1445, 0x0c03: 0x1411, 0x0c04: 0x0ec9, 0x0c05: 0x075d,
+	0x0c06: 0x0951, 0x0c07: 0x1699, 0x0c08: 0x1699, 0x0c09: 0x0a7d, 0x0c0a: 0x14cd, 0x0c0b: 0x09b5,
+	0x0c0c: 0x0a79, 0x0c0d: 0x0c61, 0x0c0e: 0x1041, 0x0c0f: 0x11d1, 0x0c10: 0x1309, 0x0c11: 0x1345,
+	0x0c12: 0x1379, 0x0c13: 0x148d, 0x0c14: 0x0de5, 0x0c15: 0x0e71, 0x0c16: 0x0f1d, 0x0c17: 0x0fb5,
+	0x0c18: 0x12d1, 0x0c19: 0x14b5, 0x0c1a: 0x15e1, 0x0c1b: 0x0781, 0x0c1c: 0x0925, 0x0c1d: 0x0df9,
+	0x0c1e: 0x0f41, 0x0c1f: 0x1305, 0x0c20: 0x1631, 0x0c21: 0x0b25, 0x0c22: 0x0ee9, 0x0c23: 0x12f5,
+	0x0c24: 0x1389, 0x0c25: 0x0c95, 0x0c26: 0x122d, 0x0c27: 0x1351, 0x0c28: 0x0b91, 0x0c29: 0x0d81,
+	0x0c2a: 0x0e89, 0x0c2b: 0x0f8d, 0x0c2c: 0x1499, 0x0c2d: 0x07c1, 0x0c2e: 0x0859, 0x0c2f: 0x08c5,
+	0x0c30: 0x0cfd, 0x0c31: 0x0df1, 0x0c32: 0x0f3d, 0x0c33: 0x1061, 0x0c34: 0x11e9, 0x0c35: 0x12fd,
+	0x0c36: 0x1315, 0x0c37: 0x1439, 0x0c38: 0x155d, 0x0c39: 0x1611, 0x0c3a: 0x162d, 0x0c3b: 0x109d,
+	0x0c3c: 0x10dd, 0x0c3d: 0x1195, 0x0c3e: 0x12b5, 0x0c3f: 0x14e9,
+	// Block 0x31, offset 0xc40
+	0x0c40: 0x1639, 0x0c41: 0x13bd, 0x0c42: 0x0a39, 0x0c43: 0x0bad, 0x0c44: 0x114d, 0x0c45: 0x120d,
+	0x0c46: 0x0f71, 0x0c47: 0x10a5, 0x0c48: 0x1409, 0x0c49: 0x1555, 0x0c4a: 0x0a35, 0x0c4b: 0x0b01,
+	0x0c4c: 0x0de9, 0x0c4d: 0x0e9d, 0x0c4e: 0x0ed1, 0x0c4f: 0x1185, 0x0c50: 0x11ad, 0x0c51: 0x1515,
+	0x0c52: 0x08c1, 0x0c53: 0x1219, 0x0c54: 0x0865, 0x0c55: 0x0861, 0x0c56: 0x1109, 0x0c57: 0x1199,
+	0x0c58: 0x12cd, 0x0c59: 0x151d, 0x0c5a: 0x13d9, 0x0c5b: 0x0c99, 0x0c5c: 0x0de5, 0x0c5d: 0x13c9,
+	0x0c5e: 0x0769, 0x0c5f: 0x0ad5, 0x0c60: 0x0c05, 0x0c61: 0x0fa1, 0x0c62: 0x1021, 0x0c63: 0x08e5,
+	0x0c64: 0x10ad, 0x0c65: 0x07d1, 0x0c66: 0x0be9, 0x0c67: 0x0749, 0x0c68: 0x0e5d, 0x0c69: 0x0d15,
+	0x0c6a: 0x1181, 0x0c6b: 0x0939, 0x0c6c: 0x0a25, 0x0c6d: 0x106d, 0x0c6e: 0x12d5, 0x0c6f: 0x13ad,
+	0x0c70: 0x0e29, 0x0c71: 0x1469, 0x0c72: 0x0e55, 0x0c73: 0x0ca9, 0x0c74: 0x128d, 0x0c75: 0x0cc9,
+	0x0c76: 0x101d, 0x0c77: 0x079d, 0x0c78: 0x0819, 0x0c79: 0x085d, 0x0c7a: 0x0dc5, 0x0c7b: 0x116d,
+	0x0c7c: 0x1265, 0x0c7d: 0x13b9, 0x0c7e: 0x14c9, 0x0c7f: 0x08cd,
+	// Block 0x32, offset 0xc80
+	0x0c80: 0x0981, 0x0c81: 0x0a89, 0x0c82: 0x0ba1, 0x0c83: 0x0d31, 0x0c84: 0x0eed, 0x0c85: 0x10b1,
+	0x0c86: 0x1505, 0x0c87: 0x15e9, 0x0c88: 0x163d, 0x0c89: 0x1655, 0x0c8a: 0x08a9, 0x0c8b: 0x0d65,
+	0x0c8c: 0x0e15, 0x0c8d: 0x145d, 0x0c8e: 0x0b6d, 0x0c8f: 0x0c49, 0x0c90: 0x0c65, 0x0c91: 0x0cf5,
+	0x0c92: 0x0edd, 0x0c93: 0x0f29, 0x0c94: 0x0fd9, 0x0c95: 0x10fd, 0x0c96: 0x11a1, 0x0c97: 0x1205,
+	0x0c98: 0x144d, 0x0c99: 0x12dd, 0x0c9a: 0x1475, 0x0c9b: 0x14ed, 0x0c9c: 0x0881, 0x0c9d: 0x08ad,
+	0x0c9e: 0x0995, 0x0c9f: 0x0f19, 0x0ca0: 0x1365, 0x0ca1: 0x13ad, 0x0ca2: 0x0b8d, 0x0ca3: 0x0bfd,
+	0x0ca4: 0x0cc1, 0x0ca5: 0x0e21, 0x0ca6: 0x1149, 0x0ca7: 0x0f95, 0x0ca8: 0x07ad, 0x0ca9: 0x09f1,
+	0x0caa: 0x0ad5, 0x0cab: 0x0b39, 0x0cac: 0x0c09, 0x0cad: 0x0fb1, 0x0cae: 0x0fcd, 0x0caf: 0x11dd,
+	0x0cb0: 0x11fd, 0x0cb1: 0x14d1, 0x0cb2: 0x1551, 0x0cb3: 0x1561, 0x0cb4: 0x159d, 0x0cb5: 0x07c5,
+	0x0cb6: 0x10f1, 0x0cb7: 0x14bd, 0x0cb8: 0x1539, 0x0cb9: 0x0c21, 0x0cba: 0x0789, 0x0cbb: 0x07e9,
+	0x0cbc: 0x0ad9, 0x0cbd: 0x0af9, 0x0cbe: 0x0d21, 0x0cbf: 0x0de5,
+	// Block 0x33, offset 0xcc0
+	0x0cc0: 0x0f35, 0x0cc1: 0x103d, 0x0cc2: 0x12e9, 0x0cc3: 0x1489, 0x0cc4: 0x1691, 0x0cc5: 0x0d55,
+	0x0cc6: 0x1511, 0x0cc7: 0x08a5, 0x0cc8: 0x0da1, 0x0cc9: 0x0dad, 0x0cca: 0x0e81, 0x0ccb: 0x0eb9,
+	0x0ccc: 0x0fbd, 0x0ccd: 0x1019, 0x0cce: 0x1099, 0x0ccf: 0x117d, 0x0cd0: 0x15a9, 0x0cd1: 0x0821,
+	0x0cd2: 0x0c75, 0x0cd3: 0x1521, 0x0cd4: 0x07d9, 0x0cd5: 0x0b1d, 0x0cd6: 0x0ea1, 0x0cd7: 0x1451,
+	0x0cd8: 0x0bd9, 0x0cd9: 0x0c29, 0x0cda: 0x0db5, 0x0cdb: 0x0fa1, 0x0cdc: 0x1529, 0x0cdd: 0x0889,
+	0x0cde: 0x0971, 0x0cdf: 0x0b09, 0x0ce0: 0x0d45, 0x0ce1: 0x0d91, 0x0ce2: 0x0dd1, 0x0ce3: 0x0e65,
+	0x0ce4: 0x0fb9, 0x0ce5: 0x102d, 0x0ce6: 0x11c9, 0x0ce7: 0x1369, 0x0ce8: 0x1375, 0x0ce9: 0x14c5,
+	0x0cea: 0x1545, 0x0ceb: 0x08f5, 0x0cec: 0x0ebd, 0x0ced: 0x0975, 0x0cee: 0x0f39, 0x0cef: 0x0fdd,
+	0x0cf0: 0x12f9, 0x0cf1: 0x152d, 0x0cf2: 0x1619, 0x0cf3: 0x1641, 0x0cf4: 0x0da9, 0x0cf5: 0x0e99,
+	0x0cf6: 0x1235, 0x0cf7: 0x1129, 0x0cf8: 0x1135, 0x0cf9: 0x1159, 0x0cfa: 0x0f89, 0x0cfb: 0x0f11,
+	0x0cfc: 0x13d5, 0x0cfd: 0x07a5, 0x0cfe: 0x129d, 0x0cff: 0x088d,
+	// Block 0x34, offset 0xd00
+	0x0d00: 0x087d, 0x0d01: 0x0b7d, 0x0d02: 0x0c9d, 0x0d03: 0x1165, 0x0d04: 0x0ac5, 0x0d05: 0x0e75,
+	0x0d06: 0x0d61, 0x0d07: 0x1459, 0x0d08: 0x1359, 0x0d09: 0x1519, 0x0d0a: 0x1395, 0x0d0b: 0x0b99,
+	0x0d0c: 0x07f9, 0x0d0d: 0x09cd, 0x0d10: 0x0a21,
+	0x0d12: 0x0d51, 0x0d15: 0x0869, 0x0d16: 0x0f91, 0x0d17: 0x1055,
+	0x0d18: 0x10b9, 0x0d19: 0x10d5, 0x0d1a: 0x10d9, 0x0d1b: 0x10ed, 0x0d1c: 0x1569, 0x0d1d: 0x115d,
+	0x0d1e: 0x11e1, 0x0d20: 0x1301, 0x0d22: 0x13c5,
+	0x0d25: 0x1479, 0x0d26: 0x14a5,
+	0x0d2a: 0x15bd, 0x0d2b: 0x15c1, 0x0d2c: 0x15c5, 0x0d2d: 0x1629, 0x0d2e: 0x149d, 0x0d2f: 0x1535,
+	0x0d30: 0x07c9, 0x0d31: 0x07ed, 0x0d32: 0x0801, 0x0d33: 0x08bd, 0x0d34: 0x08c9, 0x0d35: 0x0909,
+	0x0d36: 0x09bd, 0x0d37: 0x09d9, 0x0d38: 0x09e1, 0x0d39: 0x0a1d, 0x0d3a: 0x0a29, 0x0d3b: 0x0b05,
+	0x0d3c: 0x0b0d, 0x0d3d: 0x0c15, 0x0d3e: 0x0c3d, 0x0d3f: 0x0c45,
+	// Block 0x35, offset 0xd40
+	0x0d40: 0x0c5d, 0x0d41: 0x0d09, 0x0d42: 0x0d39, 0x0d43: 0x0d59, 0x0d44: 0x0dc9, 0x0d45: 0x0e8d,
+	0x0d46: 0x0ea9, 0x0d47: 0x0ed9, 0x0d48: 0x0f2d, 0x0d49: 0x0f4d, 0x0d4a: 0x0fc1, 0x0d4b: 0x10a1,
+	0x0d4c: 0x10bd, 0x0d4d: 0x10c5, 0x0d4e: 0x10c1, 0x0d4f: 0x10c9, 0x0d50: 0x10cd, 0x0d51: 0x10d1,
+	0x0d52: 0x10e5, 0x0d53: 0x10e9, 0x0d54: 0x110d, 0x0d55: 0x1121, 0x0d56: 0x113d, 0x0d57: 0x11a1,
+	0x0d58: 0x11a9, 0x0d59: 0x11b1, 0x0d5a: 0x11c5, 0x0d5b: 0x11ed, 0x0d5c: 0x123d, 0x0d5d: 0x1271,
+	0x0d5e: 0x1271, 0x0d5f: 0x12d9, 0x0d60: 0x1381, 0x0d61: 0x1399, 0x0d62: 0x13cd, 0x0d63: 0x13d1,
+	0x0d64: 0x1415, 0x0d65: 0x1419, 0x0d66: 0x1471, 0x0d67: 0x1479, 0x0d68: 0x1549, 0x0d69: 0x158d,
+	0x0d6a: 0x15a5, 0x0d6b: 0x0c0d, 0x0d6c: 0x1780, 0x0d6d: 0x1255,
+	0x0d70: 0x0751, 0x0d71: 0x0855, 0x0d72: 0x0815, 0x0d73: 0x07bd, 0x0d74: 0x07fd, 0x0d75: 0x0829,
+	0x0d76: 0x08b9, 0x0d77: 0x08d5, 0x0d78: 0x09bd, 0x0d79: 0x09a9, 0x0d7a: 0x09b9, 0x0d7b: 0x09d5,
+	0x0d7c: 0x0a21, 0x0d7d: 0x0a31, 0x0d7e: 0x0a75, 0x0d7f: 0x0a81,
+	// Block 0x36, offset 0xd80
+	0x0d80: 0x0a9d, 0x0d81: 0x0aad, 0x0d82: 0x0b95, 0x0d83: 0x0b9d, 0x0d84: 0x0bcd, 0x0d85: 0x0bed,
+	0x0d86: 0x0c1d, 0x0d87: 0x0c35, 0x0d88: 0x0c25, 0x0d89: 0x0c45, 0x0d8a: 0x0c39, 0x0d8b: 0x0c5d,
+	0x0d8c: 0x0c79, 0x0d8d: 0x0cd1, 0x0d8e: 0x0cdd, 0x0d8f: 0x0ce5, 0x0d90: 0x0d0d, 0x0d91: 0x0d51,
+	0x0d92: 0x0d81, 0x0d93: 0x0d85, 0x0d94: 0x0d99, 0x0d95: 0x0e19, 0x0d96: 0x0e29, 0x0d97: 0x0e81,
+	0x0d98: 0x0ecd, 0x0d99: 0x0ec5, 0x0d9a: 0x0ed9, 0x0d9b: 0x0ef5, 0x0d9c: 0x0f2d, 0x0d9d: 0x1085,
+	0x0d9e: 0x0f51, 0x0d9f: 0x0f85, 0x0da0: 0x0f91, 0x0da1: 0x0fd1, 0x0da2: 0x0fed, 0x0da3: 0x1011,
+	0x0da4: 0x1035, 0x0da5: 0x1039, 0x0da6: 0x1055, 0x0da7: 0x1059, 0x0da8: 0x1069, 0x0da9: 0x107d,
+	0x0daa: 0x1079, 0x0dab: 0x10a9, 0x0dac: 0x1125, 0x0dad: 0x113d, 0x0dae: 0x1155, 0x0daf: 0x118d,
+	0x0db0: 0x11a1, 0x0db1: 0x11bd, 0x0db2: 0x11ed, 0x0db3: 0x12a1, 0x0db4: 0x12c9, 0x0db5: 0x133d,
+	0x0db6: 0x1385, 0x0db7: 0x1391, 0x0db8: 0x1399, 0x0db9: 0x13b1, 0x0dba: 0x13c5, 0x0dbb: 0x13b5,
+	0x0dbc: 0x13cd, 0x0dbd: 0x13c9, 0x0dbe: 0x13c1, 0x0dbf: 0x13d1,
+	// Block 0x37, offset 0xdc0
+	0x0dc0: 0x13dd, 0x0dc1: 0x1419, 0x0dc2: 0x1455, 0x0dc3: 0x1485, 0x0dc4: 0x14b9, 0x0dc5: 0x14d9,
+	0x0dc6: 0x1525, 0x0dc7: 0x1549, 0x0dc8: 0x1569, 0x0dc9: 0x157d, 0x0dca: 0x158d, 0x0dcb: 0x1599,
+	0x0dcc: 0x15a5, 0x0dcd: 0x15f9, 0x0dce: 0x1699, 0x0dcf: 0x1717, 0x0dd0: 0x1712, 0x0dd1: 0x1744,
+	0x0dd2: 0x0679, 0x0dd3: 0x06a1, 0x0dd4: 0x06a5, 0x0dd5: 0x17c6, 0x0dd6: 0x17f3, 0x0dd7: 0x186b,
+	0x0dd8: 0x1685, 0x0dd9: 0x1695,
+	// Block 0x38, offset 0xe00
+	0x0e00: 0x1b17, 0x0e01: 0x1b1a, 0x0e02: 0x1b1d, 0x0e03: 0x1d4a, 0x0e04: 0x1d4e, 0x0e05: 0x1ba1,
+	0x0e06: 0x1ba1,
+	0x0e13: 0x1eb7, 0x0e14: 0x1ea8, 0x0e15: 0x1ead, 0x0e16: 0x1ebc, 0x0e17: 0x1eb2,
+	0x0e1d: 0x4376,
+	0x0e1e: 0x801a, 0x0e1f: 0x43e8, 0x0e20: 0x0227, 0x0e21: 0x020f, 0x0e22: 0x0218, 0x0e23: 0x021b,
+	0x0e24: 0x021e, 0x0e25: 0x0221, 0x0e26: 0x0224, 0x0e27: 0x022a, 0x0e28: 0x022d, 0x0e29: 0x0017,
+	0x0e2a: 0x43d6, 0x0e2b: 0x43dc, 0x0e2c: 0x44da, 0x0e2d: 0x44e2, 0x0e2e: 0x432e, 0x0e2f: 0x4334,
+	0x0e30: 0x433a, 0x0e31: 0x4340, 0x0e32: 0x434c, 0x0e33: 0x4352, 0x0e34: 0x4358, 0x0e35: 0x4364,
+	0x0e36: 0x436a, 0x0e38: 0x4370, 0x0e39: 0x437c, 0x0e3a: 0x4382, 0x0e3b: 0x4388,
+	0x0e3c: 0x4394, 0x0e3e: 0x439a,
+	// Block 0x39, offset 0xe40
+	0x0e40: 0x43a0, 0x0e41: 0x43a6, 0x0e43: 0x43ac, 0x0e44: 0x43b2,
+	0x0e46: 0x43be, 0x0e47: 0x43c4, 0x0e48: 0x43ca, 0x0e49: 0x43d0, 0x0e4a: 0x43e2, 0x0e4b: 0x435e,
+	0x0e4c: 0x4346, 0x0e4d: 0x438e, 0x0e4e: 0x43b8, 0x0e4f: 0x1ec1, 0x0e50: 0x0293, 0x0e51: 0x0293,
+	0x0e52: 0x029c, 0x0e53: 0x029c, 0x0e54: 0x029c, 0x0e55: 0x029c, 0x0e56: 0x029f, 0x0e57: 0x029f,
+	0x0e58: 0x029f, 0x0e59: 0x029f, 0x0e5a: 0x02a5, 0x0e5b: 0x02a5, 0x0e5c: 0x02a5, 0x0e5d: 0x02a5,
+	0x0e5e: 0x0299, 0x0e5f: 0x0299, 0x0e60: 0x0299, 0x0e61: 0x0299, 0x0e62: 0x02a2, 0x0e63: 0x02a2,
+	0x0e64: 0x02a2, 0x0e65: 0x02a2, 0x0e66: 0x0296, 0x0e67: 0x0296, 0x0e68: 0x0296, 0x0e69: 0x0296,
+	0x0e6a: 0x02c9, 0x0e6b: 0x02c9, 0x0e6c: 0x02c9, 0x0e6d: 0x02c9, 0x0e6e: 0x02cc, 0x0e6f: 0x02cc,
+	0x0e70: 0x02cc, 0x0e71: 0x02cc, 0x0e72: 0x02ab, 0x0e73: 0x02ab, 0x0e74: 0x02ab, 0x0e75: 0x02ab,
+	0x0e76: 0x02a8, 0x0e77: 0x02a8, 0x0e78: 0x02a8, 0x0e79: 0x02a8, 0x0e7a: 0x02ae, 0x0e7b: 0x02ae,
+	0x0e7c: 0x02ae, 0x0e7d: 0x02ae, 0x0e7e: 0x02b1, 0x0e7f: 0x02b1,
+	// Block 0x3a, offset 0xe80
+	0x0e80: 0x02b1, 0x0e81: 0x02b1, 0x0e82: 0x02ba, 0x0e83: 0x02ba, 0x0e84: 0x02b7, 0x0e85: 0x02b7,
+	0x0e86: 0x02bd, 0x0e87: 0x02bd, 0x0e88: 0x02b4, 0x0e89: 0x02b4, 0x0e8a: 0x02c3, 0x0e8b: 0x02c3,
+	0x0e8c: 0x02c0, 0x0e8d: 0x02c0, 0x0e8e: 0x02cf, 0x0e8f: 0x02cf, 0x0e90: 0x02cf, 0x0e91: 0x02cf,
+	0x0e92: 0x02d5, 0x0e93: 0x02d5, 0x0e94: 0x02d5, 0x0e95: 0x02d5, 0x0e96: 0x02db, 0x0e97: 0x02db,
+	0x0e98: 0x02db, 0x0e99: 0x02db, 0x0e9a: 0x02d8, 0x0e9b: 0x02d8, 0x0e9c: 0x02d8, 0x0e9d: 0x02d8,
+	0x0e9e: 0x02de, 0x0e9f: 0x02de, 0x0ea0: 0x02e1, 0x0ea1: 0x02e1, 0x0ea2: 0x02e1, 0x0ea3: 0x02e1,
+	0x0ea4: 0x4454, 0x0ea5: 0x4454, 0x0ea6: 0x02e7, 0x0ea7: 0x02e7, 0x0ea8: 0x02e7, 0x0ea9: 0x02e7,
+	0x0eaa: 0x02e4, 0x0eab: 0x02e4, 0x0eac: 0x02e4, 0x0ead: 0x02e4, 0x0eae: 0x0302, 0x0eaf: 0x0302,
+	0x0eb0: 0x444e, 0x0eb1: 0x444e,
+	// Block 0x3b, offset 0xec0
+	0x0ed3: 0x02d2, 0x0ed4: 0x02d2, 0x0ed5: 0x02d2, 0x0ed6: 0x02d2, 0x0ed7: 0x02f0,
+	0x0ed8: 0x02f0, 0x0ed9: 0x02ed, 0x0eda: 0x02ed, 0x0edb: 0x02f3, 0x0edc: 0x02f3, 0x0edd: 0x2191,
+	0x0ede: 0x02f9, 0x0edf: 0x02f9, 0x0ee0: 0x02ea, 0x0ee1: 0x02ea, 0x0ee2: 0x02f6, 0x0ee3: 0x02f6,
+	0x0ee4: 0x02ff, 0x0ee5: 0x02ff, 0x0ee6: 0x02ff, 0x0ee7: 0x02ff, 0x0ee8: 0x0287, 0x0ee9: 0x0287,
+	0x0eea: 0x26ec, 0x0eeb: 0x26ec, 0x0eec: 0x275c, 0x0eed: 0x275c, 0x0eee: 0x272b, 0x0eef: 0x272b,
+	0x0ef0: 0x2747, 0x0ef1: 0x2747, 0x0ef2: 0x2740, 0x0ef3: 0x2740, 0x0ef4: 0x274e, 0x0ef5: 0x274e,
+	0x0ef6: 0x2755, 0x0ef7: 0x2755, 0x0ef8: 0x2755, 0x0ef9: 0x2732, 0x0efa: 0x2732, 0x0efb: 0x2732,
+	0x0efc: 0x02fc, 0x0efd: 0x02fc, 0x0efe: 0x02fc, 0x0eff: 0x02fc,
+	// Block 0x3c, offset 0xf00
+	0x0f00: 0x26f3, 0x0f01: 0x26fa, 0x0f02: 0x2716, 0x0f03: 0x2732, 0x0f04: 0x2739, 0x0f05: 0x1ecb,
+	0x0f06: 0x1ed0, 0x0f07: 0x1ed5, 0x0f08: 0x1ee4, 0x0f09: 0x1ef3, 0x0f0a: 0x1ef8, 0x0f0b: 0x1efd,
+	0x0f0c: 0x1f02, 0x0f0d: 0x1f07, 0x0f0e: 0x1f16, 0x0f0f: 0x1f25, 0x0f10: 0x1f2a, 0x0f11: 0x1f2f,
+	0x0f12: 0x1f3e, 0x0f13: 0x1f4d, 0x0f14: 0x1f52, 0x0f15: 0x1f57, 0x0f16: 0x1f5c, 0x0f17: 0x1f6b,
+	0x0f18: 0x1f70, 0x0f19: 0x1f7f, 0x0f1a: 0x1f84, 0x0f1b: 0x1f89, 0x0f1c: 0x1f98, 0x0f1d: 0x1f9d,
+	0x0f1e: 0x1fa2, 0x0f1f: 0x1fac, 0x0f20: 0x1fe8, 0x0f21: 0x1ff7, 0x0f22: 0x2006, 0x0f23: 0x200b,
+	0x0f24: 0x2010, 0x0f25: 0x201a, 0x0f26: 0x2029, 0x0f27: 0x202e, 0x0f28: 0x203d, 0x0f29: 0x2042,
+	0x0f2a: 0x2047, 0x0f2b: 0x2056, 0x0f2c: 0x205b, 0x0f2d: 0x206a, 0x0f2e: 0x206f, 0x0f2f: 0x2074,
+	0x0f30: 0x2079, 0x0f31: 0x207e, 0x0f32: 0x2083, 0x0f33: 0x2088, 0x0f34: 0x208d, 0x0f35: 0x2092,
+	0x0f36: 0x2097, 0x0f37: 0x209c, 0x0f38: 0x20a1, 0x0f39: 0x20a6, 0x0f3a: 0x20ab, 0x0f3b: 0x20b0,
+	0x0f3c: 0x20b5, 0x0f3d: 0x20ba, 0x0f3e: 0x20bf, 0x0f3f: 0x20c9,
+	// Block 0x3d, offset 0xf40
+	0x0f40: 0x20ce, 0x0f41: 0x20d3, 0x0f42: 0x20d8, 0x0f43: 0x20e2, 0x0f44: 0x20e7, 0x0f45: 0x20f1,
+	0x0f46: 0x20f6, 0x0f47: 0x20fb, 0x0f48: 0x2100, 0x0f49: 0x2105, 0x0f4a: 0x210a, 0x0f4b: 0x210f,
+	0x0f4c: 0x2114, 0x0f4d: 0x2119, 0x0f4e: 0x2128, 0x0f4f: 0x2137, 0x0f50: 0x213c, 0x0f51: 0x2141,
+	0x0f52: 0x2146, 0x0f53: 0x214b, 0x0f54: 0x2150, 0x0f55: 0x215a, 0x0f56: 0x215f, 0x0f57: 0x2164,
+	0x0f58: 0x2173, 0x0f59: 0x2182, 0x0f5a: 0x2187, 0x0f5b: 0x4406, 0x0f5c: 0x440c, 0x0f5d: 0x4442,
+	0x0f5e: 0x4499, 0x0f5f: 0x44a0, 0x0f60: 0x44a7, 0x0f61: 0x44ae, 0x0f62: 0x44b5, 0x0f63: 0x44bc,
+	0x0f64: 0x2708, 0x0f65: 0x270f, 0x0f66: 0x2716, 0x0f67: 0x271d, 0x0f68: 0x2732, 0x0f69: 0x2739,
+	0x0f6a: 0x1eda, 0x0f6b: 0x1edf, 0x0f6c: 0x1ee4, 0x0f6d: 0x1ee9, 0x0f6e: 0x1ef3, 0x0f6f: 0x1ef8,
+	0x0f70: 0x1f0c, 0x0f71: 0x1f11, 0x0f72: 0x1f16, 0x0f73: 0x1f1b, 0x0f74: 0x1f25, 0x0f75: 0x1f2a,
+	0x0f76: 0x1f34, 0x0f77: 0x1f39, 0x0f78: 0x1f3e, 0x0f79: 0x1f43, 0x0f7a: 0x1f4d, 0x0f7b: 0x1f52,
+	0x0f7c: 0x207e, 0x0f7d: 0x2083, 0x0f7e: 0x2092, 0x0f7f: 0x2097,
+	// Block 0x3e, offset 0xf80
+	0x0f80: 0x209c, 0x0f81: 0x20b0, 0x0f82: 0x20b5, 0x0f83: 0x20ba, 0x0f84: 0x20bf, 0x0f85: 0x20d8,
+	0x0f86: 0x20e2, 0x0f87: 0x20e7, 0x0f88: 0x20ec, 0x0f89: 0x2100, 0x0f8a: 0x211e, 0x0f8b: 0x2123,
+	0x0f8c: 0x2128, 0x0f8d: 0x212d, 0x0f8e: 0x2137, 0x0f8f: 0x213c, 0x0f90: 0x4442, 0x0f91: 0x2169,
+	0x0f92: 0x216e, 0x0f93: 0x2173, 0x0f94: 0x2178, 0x0f95: 0x2182, 0x0f96: 0x2187, 0x0f97: 0x26f3,
+	0x0f98: 0x26fa, 0x0f99: 0x2701, 0x0f9a: 0x2716, 0x0f9b: 0x2724, 0x0f9c: 0x1ecb, 0x0f9d: 0x1ed0,
+	0x0f9e: 0x1ed5, 0x0f9f: 0x1ee4, 0x0fa0: 0x1eee, 0x0fa1: 0x1efd, 0x0fa2: 0x1f02, 0x0fa3: 0x1f07,
+	0x0fa4: 0x1f16, 0x0fa5: 0x1f20, 0x0fa6: 0x1f3e, 0x0fa7: 0x1f57, 0x0fa8: 0x1f5c, 0x0fa9: 0x1f6b,
+	0x0faa: 0x1f70, 0x0fab: 0x1f7f, 0x0fac: 0x1f89, 0x0fad: 0x1f98, 0x0fae: 0x1f9d, 0x0faf: 0x1fa2,
+	0x0fb0: 0x1fac, 0x0fb1: 0x1fe8, 0x0fb2: 0x1fed, 0x0fb3: 0x1ff7, 0x0fb4: 0x2006, 0x0fb5: 0x200b,
+	0x0fb6: 0x2010, 0x0fb7: 0x201a, 0x0fb8: 0x2029, 0x0fb9: 0x203d, 0x0fba: 0x2042, 0x0fbb: 0x2047,
+	0x0fbc: 0x2056, 0x0fbd: 0x205b, 0x0fbe: 0x206a, 0x0fbf: 0x206f,
+	// Block 0x3f, offset 0xfc0
+	0x0fc0: 0x2074, 0x0fc1: 0x2079, 0x0fc2: 0x2088, 0x0fc3: 0x208d, 0x0fc4: 0x20a1, 0x0fc5: 0x20a6,
+	0x0fc6: 0x20ab, 0x0fc7: 0x20b0, 0x0fc8: 0x20b5, 0x0fc9: 0x20c9, 0x0fca: 0x20ce, 0x0fcb: 0x20d3,
+	0x0fcc: 0x20d8, 0x0fcd: 0x20dd, 0x0fce: 0x20f1, 0x0fcf: 0x20f6, 0x0fd0: 0x20fb, 0x0fd1: 0x2100,
+	0x0fd2: 0x210f, 0x0fd3: 0x2114, 0x0fd4: 0x2119, 0x0fd5: 0x2128, 0x0fd6: 0x2132, 0x0fd7: 0x2141,
+	0x0fd8: 0x2146, 0x0fd9: 0x4436, 0x0fda: 0x215a, 0x0fdb: 0x215f, 0x0fdc: 0x2164, 0x0fdd: 0x2173,
+	0x0fde: 0x217d, 0x0fdf: 0x2716, 0x0fe0: 0x2724, 0x0fe1: 0x1ee4, 0x0fe2: 0x1eee, 0x0fe3: 0x1f16,
+	0x0fe4: 0x1f20, 0x0fe5: 0x1f3e, 0x0fe6: 0x1f48, 0x0fe7: 0x1fac, 0x0fe8: 0x1fb1, 0x0fe9: 0x1fd4,
+	0x0fea: 0x1fd9, 0x0feb: 0x20b0, 0x0fec: 0x20b5, 0x0fed: 0x20d8, 0x0fee: 0x2128, 0x0fef: 0x2132,
+	0x0ff0: 0x2173, 0x0ff1: 0x217d, 0x0ff2: 0x44ea, 0x0ff3: 0x44f2, 0x0ff4: 0x44fa, 0x0ff5: 0x2033,
+	0x0ff6: 0x2038, 0x0ff7: 0x204c, 0x0ff8: 0x2051, 0x0ff9: 0x2060, 0x0ffa: 0x2065, 0x0ffb: 0x1fb6,
+	0x0ffc: 0x1fbb, 0x0ffd: 0x1fde, 0x0ffe: 0x1fe3, 0x0fff: 0x1f75,
+	// Block 0x40, offset 0x1000
+	0x1000: 0x1f7a, 0x1001: 0x1f61, 0x1002: 0x1f66, 0x1003: 0x1f8e, 0x1004: 0x1f93, 0x1005: 0x1ffc,
+	0x1006: 0x2001, 0x1007: 0x201f, 0x1008: 0x2024, 0x1009: 0x1fc0, 0x100a: 0x1fc5, 0x100b: 0x1fca,
+	0x100c: 0x1fd4, 0x100d: 0x1fcf, 0x100e: 0x1fa7, 0x100f: 0x1ff2, 0x1010: 0x2015, 0x1011: 0x2033,
+	0x1012: 0x2038, 0x1013: 0x204c, 0x1014: 0x2051, 0x1015: 0x2060, 0x1016: 0x2065, 0x1017: 0x1fb6,
+	0x1018: 0x1fbb, 0x1019: 0x1fde, 0x101a: 0x1fe3, 0x101b: 0x1f75, 0x101c: 0x1f7a, 0x101d: 0x1f61,
+	0x101e: 0x1f66, 0x101f: 0x1f8e, 0x1020: 0x1f93, 0x1021: 0x1ffc, 0x1022: 0x2001, 0x1023: 0x201f,
+	0x1024: 0x2024, 0x1025: 0x1fc0, 0x1026: 0x1fc5, 0x1027: 0x1fca, 0x1028: 0x1fd4, 0x1029: 0x1fcf,
+	0x102a: 0x1fa7, 0x102b: 0x1ff2, 0x102c: 0x2015, 0x102d: 0x1fc0, 0x102e: 0x1fc5, 0x102f: 0x1fca,
+	0x1030: 0x1fd4, 0x1031: 0x1fb1, 0x1032: 0x1fd9, 0x1033: 0x202e, 0x1034: 0x1f98, 0x1035: 0x1f9d,
+	0x1036: 0x1fa2, 0x1037: 0x1fc0, 0x1038: 0x1fc5, 0x1039: 0x1fca, 0x103a: 0x202e, 0x103b: 0x203d,
+	0x103c: 0x43ee, 0x103d: 0x43ee,
+	// Block 0x41, offset 0x1040
+	0x1050: 0x2453, 0x1051: 0x2468,
+	0x1052: 0x2468, 0x1053: 0x246f, 0x1054: 0x2476, 0x1055: 0x248b, 0x1056: 0x2492, 0x1057: 0x2499,
+	0x1058: 0x24bc, 0x1059: 0x24bc, 0x105a: 0x24df, 0x105b: 0x24d8, 0x105c: 0x24f4, 0x105d: 0x24e6,
+	0x105e: 0x24ed, 0x105f: 0x2510, 0x1060: 0x2510, 0x1061: 0x2509, 0x1062: 0x2517, 0x1063: 0x2517,
+	0x1064: 0x2541, 0x1065: 0x2541, 0x1066: 0x255d, 0x1067: 0x2525, 0x1068: 0x2525, 0x1069: 0x251e,
+	0x106a: 0x2533, 0x106b: 0x2533, 0x106c: 0x253a, 0x106d: 0x253a, 0x106e: 0x2564, 0x106f: 0x2572,
+	0x1070: 0x2572, 0x1071: 0x2579, 0x1072: 0x2579, 0x1073: 0x2580, 0x1074: 0x2587, 0x1075: 0x258e,
+	0x1076: 0x2595, 0x1077: 0x2595, 0x1078: 0x259c, 0x1079: 0x25aa, 0x107a: 0x25b8, 0x107b: 0x25b1,
+	0x107c: 0x25bf, 0x107d: 0x25bf, 0x107e: 0x25d4, 0x107f: 0x25db,
+	// Block 0x42, offset 0x1080
+	0x1080: 0x260c, 0x1081: 0x261a, 0x1082: 0x2613, 0x1083: 0x25f7, 0x1084: 0x25f7, 0x1085: 0x2621,
+	0x1086: 0x2621, 0x1087: 0x2628, 0x1088: 0x2628, 0x1089: 0x2652, 0x108a: 0x2659, 0x108b: 0x2660,
+	0x108c: 0x2636, 0x108d: 0x2644, 0x108e: 0x2667, 0x108f: 0x266e,
+	0x1092: 0x263d, 0x1093: 0x26c2, 0x1094: 0x26c9, 0x1095: 0x269f, 0x1096: 0x26a6, 0x1097: 0x268a,
+	0x1098: 0x268a, 0x1099: 0x2691, 0x109a: 0x26bb, 0x109b: 0x26b4, 0x109c: 0x26de, 0x109d: 0x26de,
+	0x109e: 0x244c, 0x109f: 0x2461, 0x10a0: 0x245a, 0x10a1: 0x2484, 0x10a2: 0x247d, 0x10a3: 0x24a7,
+	0x10a4: 0x24a0, 0x10a5: 0x24ca, 0x10a6: 0x24ae, 0x10a7: 0x24c3, 0x10a8: 0x24fb, 0x10a9: 0x2548,
+	0x10aa: 0x252c, 0x10ab: 0x256b, 0x10ac: 0x2605, 0x10ad: 0x262f, 0x10ae: 0x26d7, 0x10af: 0x26d0,
+	0x10b0: 0x26e5, 0x10b1: 0x267c, 0x10b2: 0x25e2, 0x10b3: 0x26ad, 0x10b4: 0x25d4, 0x10b5: 0x260c,
+	0x10b6: 0x25a3, 0x10b7: 0x25f0, 0x10b8: 0x2683, 0x10b9: 0x2675, 0x10ba: 0x25fe, 0x10bb: 0x25e9,
+	0x10bc: 0x25fe, 0x10bd: 0x2683, 0x10be: 0x24b5, 0x10bf: 0x24d1,
+	// Block 0x43, offset 0x10c0
+	0x10c0: 0x264b, 0x10c1: 0x25c6, 0x10c2: 0x2445, 0x10c3: 0x25e9, 0x10c4: 0x258e, 0x10c5: 0x255d,
+	0x10c6: 0x2502, 0x10c7: 0x2698,
+	0x10f0: 0x2556, 0x10f1: 0x25cd, 0x10f2: 0x296a, 0x10f3: 0x2961, 0x10f4: 0x2997, 0x10f5: 0x2985,
+	0x10f6: 0x2973, 0x10f7: 0x298e, 0x10f8: 0x29a0, 0x10f9: 0x254f, 0x10fa: 0x2e44, 0x10fb: 0x2cb4,
+	0x10fc: 0x297c,
+	// Block 0x44, offset 0x1100
+	0x1110: 0x0019, 0x1111: 0x04f5,
+	0x1112: 0x04f9, 0x1113: 0x0035, 0x1114: 0x0037, 0x1115: 0x0003, 0x1116: 0x003f, 0x1117: 0x0531,
+	0x1118: 0x0535, 0x1119: 0x1c9e,
+	0x1120: 0x80e6, 0x1121: 0x80e6, 0x1122: 0x80e6, 0x1123: 0x80e6,
+	0x1124: 0x80e6, 0x1125: 0x80e6, 0x1126: 0x80e6,
+	0x1130: 0x19b5, 0x1131: 0x04b5, 0x1132: 0x04b1, 0x1133: 0x007f, 0x1134: 0x007f, 0x1135: 0x0011,
+	0x1136: 0x0013, 0x1137: 0x00b7, 0x1138: 0x00bb, 0x1139: 0x0529, 0x113a: 0x052d, 0x113b: 0x051d,
+	0x113c: 0x0521, 0x113d: 0x0505, 0x113e: 0x0509, 0x113f: 0x04fd,
+	// Block 0x45, offset 0x1140
+	0x1140: 0x0501, 0x1141: 0x050d, 0x1142: 0x0511, 0x1143: 0x0515, 0x1144: 0x0519,
+	0x1147: 0x0077, 0x1148: 0x007b, 0x1149: 0x424f, 0x114a: 0x424f, 0x114b: 0x424f,
+	0x114c: 0x424f, 0x114d: 0x007f, 0x114e: 0x007f, 0x114f: 0x007f, 0x1150: 0x0019, 0x1151: 0x04f5,
+	0x1152: 0x001d, 0x1154: 0x0037, 0x1155: 0x0035, 0x1156: 0x003f, 0x1157: 0x0003,
+	0x1158: 0x04b5, 0x1159: 0x0011, 0x115a: 0x0013, 0x115b: 0x00b7, 0x115c: 0x00bb, 0x115d: 0x0529,
+	0x115e: 0x052d, 0x115f: 0x0007, 0x1160: 0x000d, 0x1161: 0x0015, 0x1162: 0x0017, 0x1163: 0x001b,
+	0x1164: 0x0039, 0x1165: 0x003d, 0x1166: 0x003b, 0x1168: 0x0079, 0x1169: 0x0009,
+	0x116a: 0x000b, 0x116b: 0x0041,
+	0x1170: 0x4290, 0x1171: 0x4412, 0x1172: 0x4295, 0x1174: 0x429a,
+	0x1176: 0x429f, 0x1177: 0x4418, 0x1178: 0x42a4, 0x1179: 0x441e, 0x117a: 0x42a9, 0x117b: 0x4424,
+	0x117c: 0x42ae, 0x117d: 0x442a, 0x117e: 0x42b3, 0x117f: 0x4430,
+	// Block 0x46, offset 0x1180
+	0x1180: 0x0230, 0x1181: 0x43f4, 0x1182: 0x43f4, 0x1183: 0x43fa, 0x1184: 0x43fa, 0x1185: 0x443c,
+	0x1186: 0x443c, 0x1187: 0x4400, 0x1188: 0x4400, 0x1189: 0x4448, 0x118a: 0x4448, 0x118b: 0x4448,
+	0x118c: 0x4448, 0x118d: 0x0233, 0x118e: 0x0233, 0x118f: 0x0236, 0x1190: 0x0236, 0x1191: 0x0236,
+	0x1192: 0x0236, 0x1193: 0x0239, 0x1194: 0x0239, 0x1195: 0x023c, 0x1196: 0x023c, 0x1197: 0x023c,
+	0x1198: 0x023c, 0x1199: 0x023f, 0x119a: 0x023f, 0x119b: 0x023f, 0x119c: 0x023f, 0x119d: 0x0242,
+	0x119e: 0x0242, 0x119f: 0x0242, 0x11a0: 0x0242, 0x11a1: 0x0245, 0x11a2: 0x0245, 0x11a3: 0x0245,
+	0x11a4: 0x0245, 0x11a5: 0x0248, 0x11a6: 0x0248, 0x11a7: 0x0248, 0x11a8: 0x0248, 0x11a9: 0x024b,
+	0x11aa: 0x024b, 0x11ab: 0x024e, 0x11ac: 0x024e, 0x11ad: 0x0251, 0x11ae: 0x0251, 0x11af: 0x0254,
+	0x11b0: 0x0254, 0x11b1: 0x0257, 0x11b2: 0x0257, 0x11b3: 0x0257, 0x11b4: 0x0257, 0x11b5: 0x025a,
+	0x11b6: 0x025a, 0x11b7: 0x025a, 0x11b8: 0x025a, 0x11b9: 0x025d, 0x11ba: 0x025d, 0x11bb: 0x025d,
+	0x11bc: 0x025d, 0x11bd: 0x0260, 0x11be: 0x0260, 0x11bf: 0x0260,
+	// Block 0x47, offset 0x11c0
+	0x11c0: 0x0260, 0x11c1: 0x0263, 0x11c2: 0x0263, 0x11c3: 0x0263, 0x11c4: 0x0263, 0x11c5: 0x0266,
+	0x11c6: 0x0266, 0x11c7: 0x0266, 0x11c8: 0x0266, 0x11c9: 0x0269, 0x11ca: 0x0269, 0x11cb: 0x0269,
+	0x11cc: 0x0269, 0x11cd: 0x026c, 0x11ce: 0x026c, 0x11cf: 0x026c, 0x11d0: 0x026c, 0x11d1: 0x026f,
+	0x11d2: 0x026f, 0x11d3: 0x026f, 0x11d4: 0x026f, 0x11d5: 0x0272, 0x11d6: 0x0272, 0x11d7: 0x0272,
+	0x11d8: 0x0272, 0x11d9: 0x0275, 0x11da: 0x0275, 0x11db: 0x0275, 0x11dc: 0x0275, 0x11dd: 0x0278,
+	0x11de: 0x0278, 0x11df: 0x0278, 0x11e0: 0x0278, 0x11e1: 0x027b, 0x11e2: 0x027b, 0x11e3: 0x027b,
+	0x11e4: 0x027b, 0x11e5: 0x027e, 0x11e6: 0x027e, 0x11e7: 0x027e, 0x11e8: 0x027e, 0x11e9: 0x0281,
+	0x11ea: 0x0281, 0x11eb: 0x0281, 0x11ec: 0x0281, 0x11ed: 0x0284, 0x11ee: 0x0284, 0x11ef: 0x0287,
+	0x11f0: 0x0287, 0x11f1: 0x028a, 0x11f2: 0x028a, 0x11f3: 0x028a, 0x11f4: 0x028a, 0x11f5: 0x2e91,
+	0x11f6: 0x2e91, 0x11f7: 0x2e99, 0x11f8: 0x2e99, 0x11f9: 0x2ea1, 0x11fa: 0x2ea1, 0x11fb: 0x20c4,
+	0x11fc: 0x20c4,
+	// Block 0x48, offset 0x1200
+	0x1200: 0x0081, 0x1201: 0x0083, 0x1202: 0x0085, 0x1203: 0x0087, 0x1204: 0x0089, 0x1205: 0x008b,
+	0x1206: 0x008d, 0x1207: 0x008f, 0x1208: 0x0091, 0x1209: 0x0093, 0x120a: 0x0095, 0x120b: 0x0097,
+	0x120c: 0x0099, 0x120d: 0x009b, 0x120e: 0x009d, 0x120f: 0x009f, 0x1210: 0x00a1, 0x1211: 0x00a3,
+	0x1212: 0x00a5, 0x1213: 0x00a7, 0x1214: 0x00a9, 0x1215: 0x00ab, 0x1216: 0x00ad, 0x1217: 0x00af,
+	0x1218: 0x00b1, 0x1219: 0x00b3, 0x121a: 0x00b5, 0x121b: 0x00b7, 0x121c: 0x00b9, 0x121d: 0x00bb,
+	0x121e: 0x00bd, 0x121f: 0x04e9, 0x1220: 0x04ed, 0x1221: 0x04f9, 0x1222: 0x050d, 0x1223: 0x0511,
+	0x1224: 0x04f5, 0x1225: 0x061d, 0x1226: 0x0615, 0x1227: 0x0539, 0x1228: 0x0541, 0x1229: 0x0549,
+	0x122a: 0x0551, 0x122b: 0x0559, 0x122c: 0x05dd, 0x122d: 0x05e5, 0x122e: 0x05ed, 0x122f: 0x0591,
+	0x1230: 0x0621, 0x1231: 0x053d, 0x1232: 0x0545, 0x1233: 0x054d, 0x1234: 0x0555, 0x1235: 0x055d,
+	0x1236: 0x0561, 0x1237: 0x0565, 0x1238: 0x0569, 0x1239: 0x056d, 0x123a: 0x0571, 0x123b: 0x0575,
+	0x123c: 0x0579, 0x123d: 0x057d, 0x123e: 0x0581, 0x123f: 0x0585,
+	// Block 0x49, offset 0x1240
+	0x1240: 0x0589, 0x1241: 0x058d, 0x1242: 0x0595, 0x1243: 0x0599, 0x1244: 0x059d, 0x1245: 0x05a1,
+	0x1246: 0x05a5, 0x1247: 0x05a9, 0x1248: 0x05ad, 0x1249: 0x05b1, 0x124a: 0x05b5, 0x124b: 0x05b9,
+	0x124c: 0x05bd, 0x124d: 0x05c1, 0x124e: 0x05c5, 0x124f: 0x05c9, 0x1250: 0x05cd, 0x1251: 0x05d1,
+	0x1252: 0x05d5, 0x1253: 0x05d9, 0x1254: 0x05e1, 0x1255: 0x05e9, 0x1256: 0x05f1, 0x1257: 0x05f5,
+	0x1258: 0x05f9, 0x1259: 0x05fd, 0x125a: 0x0601, 0x125b: 0x0605, 0x125c: 0x0609, 0x125d: 0x0619,
+	0x125e: 0x49aa, 0x125f: 0x49b0, 0x1260: 0x03bd, 0x1261: 0x030d, 0x1262: 0x0311, 0x1263: 0x0435,
+	0x1264: 0x0315, 0x1265: 0x0439, 0x1266: 0x043d, 0x1267: 0x0319, 0x1268: 0x031d, 0x1269: 0x0321,
+	0x126a: 0x0441, 0x126b: 0x0445, 0x126c: 0x0449, 0x126d: 0x044d, 0x126e: 0x0451, 0x126f: 0x0455,
+	0x1270: 0x0361, 0x1271: 0x0325, 0x1272: 0x0329, 0x1273: 0x032d, 0x1274: 0x0375, 0x1275: 0x0331,
+	0x1276: 0x0335, 0x1277: 0x0339, 0x1278: 0x033d, 0x1279: 0x0341, 0x127a: 0x0345, 0x127b: 0x0349,
+	0x127c: 0x034d, 0x127d: 0x0351, 0x127e: 0x0355,
+	// Block 0x4a, offset 0x1280
+	0x1280: 0x0063, 0x1281: 0x0065, 0x1282: 0x0067, 0x1283: 0x0069, 0x1284: 0x006b, 0x1285: 0x006d,
+	0x1286: 0x006f, 0x1287: 0x0071, 0x1288: 0x0073, 0x1289: 0x0075, 0x128a: 0x0083, 0x128b: 0x0085,
+	0x128c: 0x0087, 0x128d: 0x0089, 0x128e: 0x008b, 0x128f: 0x008d, 0x1290: 0x008f, 0x1291: 0x0091,
+	0x1292: 0x0093, 0x1293: 0x0095, 0x1294: 0x0097, 0x1295: 0x0099, 0x1296: 0x009b, 0x1297: 0x009d,
+	0x1298: 0x009f, 0x1299: 0x00a1, 0x129a: 0x00a3, 0x129b: 0x00a5, 0x129c: 0x00a7, 0x129d: 0x00a9,
+	0x129e: 0x00ab, 0x129f: 0x00ad, 0x12a0: 0x00af, 0x12a1: 0x00b1, 0x12a2: 0x00b3, 0x12a3: 0x00b5,
+	0x12a4: 0x00e0, 0x12a5: 0x00f5, 0x12a8: 0x0173, 0x12a9: 0x0176,
+	0x12aa: 0x0179, 0x12ab: 0x017c, 0x12ac: 0x017f, 0x12ad: 0x0182, 0x12ae: 0x0185, 0x12af: 0x0188,
+	0x12b0: 0x018b, 0x12b1: 0x018e, 0x12b2: 0x0191, 0x12b3: 0x0194, 0x12b4: 0x0197, 0x12b5: 0x019a,
+	0x12b6: 0x019d, 0x12b7: 0x01a0, 0x12b8: 0x01a3, 0x12b9: 0x0188, 0x12ba: 0x01a6, 0x12bb: 0x01a9,
+	0x12bc: 0x01ac, 0x12bd: 0x01af, 0x12be: 0x01b2, 0x12bf: 0x01b5,
+	// Block 0x4b, offset 0x12c0
+	0x12c0: 0x01fd, 0x12c1: 0x0200, 0x12c2: 0x0203, 0x12c3: 0x04cd, 0x12c4: 0x01c7, 0x12c5: 0x01d0,
+	0x12c6: 0x01d6, 0x12c7: 0x01fa, 0x12c8: 0x01eb, 0x12c9: 0x01e8, 0x12ca: 0x0206, 0x12cb: 0x0209,
+	0x12ce: 0x0021, 0x12cf: 0x0023, 0x12d0: 0x0025, 0x12d1: 0x0027,
+	0x12d2: 0x0029, 0x12d3: 0x002b, 0x12d4: 0x002d, 0x12d5: 0x002f, 0x12d6: 0x0031, 0x12d7: 0x0033,
+	0x12d8: 0x0021, 0x12d9: 0x0023, 0x12da: 0x0025, 0x12db: 0x0027, 0x12dc: 0x0029, 0x12dd: 0x002b,
+	0x12de: 0x002d, 0x12df: 0x002f, 0x12e0: 0x0031, 0x12e1: 0x0033, 0x12e2: 0x0021, 0x12e3: 0x0023,
+	0x12e4: 0x0025, 0x12e5: 0x0027, 0x12e6: 0x0029, 0x12e7: 0x002b, 0x12e8: 0x002d, 0x12e9: 0x002f,
+	0x12ea: 0x0031, 0x12eb: 0x0033, 0x12ec: 0x0021, 0x12ed: 0x0023, 0x12ee: 0x0025, 0x12ef: 0x0027,
+	0x12f0: 0x0029, 0x12f1: 0x002b, 0x12f2: 0x002d, 0x12f3: 0x002f, 0x12f4: 0x0031, 0x12f5: 0x0033,
+	0x12f6: 0x0021, 0x12f7: 0x0023, 0x12f8: 0x0025, 0x12f9: 0x0027, 0x12fa: 0x0029, 0x12fb: 0x002b,
+	0x12fc: 0x002d, 0x12fd: 0x002f, 0x12fe: 0x0031, 0x12ff: 0x0033,
+	// Block 0x4c, offset 0x1300
+	0x1300: 0x0233, 0x1301: 0x0236, 0x1302: 0x0242, 0x1303: 0x024b, 0x1305: 0x0284,
+	0x1306: 0x0254, 0x1307: 0x0245, 0x1308: 0x0263, 0x1309: 0x028a, 0x130a: 0x0275, 0x130b: 0x0278,
+	0x130c: 0x027b, 0x130d: 0x027e, 0x130e: 0x0257, 0x130f: 0x0269, 0x1310: 0x026f, 0x1311: 0x025d,
+	0x1312: 0x0272, 0x1313: 0x0251, 0x1314: 0x025a, 0x1315: 0x023c, 0x1316: 0x023f, 0x1317: 0x0248,
+	0x1318: 0x024e, 0x1319: 0x0260, 0x131a: 0x0266, 0x131b: 0x026c, 0x131c: 0x028d, 0x131d: 0x02de,
+	0x131e: 0x02c6, 0x131f: 0x0290, 0x1321: 0x0236, 0x1322: 0x0242,
+	0x1324: 0x0281, 0x1327: 0x0245, 0x1329: 0x028a,
+	0x132a: 0x0275, 0x132b: 0x0278, 0x132c: 0x027b, 0x132d: 0x027e, 0x132e: 0x0257, 0x132f: 0x0269,
+	0x1330: 0x026f, 0x1331: 0x025d, 0x1332: 0x0272, 0x1334: 0x025a, 0x1335: 0x023c,
+	0x1336: 0x023f, 0x1337: 0x0248, 0x1339: 0x0260, 0x133b: 0x026c,
+	// Block 0x4d, offset 0x1340
+	0x1342: 0x0242,
+	0x1347: 0x0245, 0x1349: 0x028a, 0x134b: 0x0278,
+	0x134d: 0x027e, 0x134e: 0x0257, 0x134f: 0x0269, 0x1351: 0x025d,
+	0x1352: 0x0272, 0x1354: 0x025a, 0x1357: 0x0248,
+	0x1359: 0x0260, 0x135b: 0x026c, 0x135d: 0x02de,
+	0x135f: 0x0290, 0x1361: 0x0236, 0x1362: 0x0242,
+	0x1364: 0x0281, 0x1367: 0x0245, 0x1368: 0x0263, 0x1369: 0x028a,
+	0x136a: 0x0275, 0x136c: 0x027b, 0x136d: 0x027e, 0x136e: 0x0257, 0x136f: 0x0269,
+	0x1370: 0x026f, 0x1371: 0x025d, 0x1372: 0x0272, 0x1374: 0x025a, 0x1375: 0x023c,
+	0x1376: 0x023f, 0x1377: 0x0248, 0x1379: 0x0260, 0x137a: 0x0266, 0x137b: 0x026c,
+	0x137c: 0x028d, 0x137e: 0x02c6,
+	// Block 0x4e, offset 0x1380
+	0x1380: 0x0233, 0x1381: 0x0236, 0x1382: 0x0242, 0x1383: 0x024b, 0x1384: 0x0281, 0x1385: 0x0284,
+	0x1386: 0x0254, 0x1387: 0x0245, 0x1388: 0x0263, 0x1389: 0x028a, 0x138b: 0x0278,
+	0x138c: 0x027b, 0x138d: 0x027e, 0x138e: 0x0257, 0x138f: 0x0269, 0x1390: 0x026f, 0x1391: 0x025d,
+	0x1392: 0x0272, 0x1393: 0x0251, 0x1394: 0x025a, 0x1395: 0x023c, 0x1396: 0x023f, 0x1397: 0x0248,
+	0x1398: 0x024e, 0x1399: 0x0260, 0x139a: 0x0266, 0x139b: 0x026c,
+	0x13a1: 0x0236, 0x13a2: 0x0242, 0x13a3: 0x024b,
+	0x13a5: 0x0284, 0x13a6: 0x0254, 0x13a7: 0x0245, 0x13a8: 0x0263, 0x13a9: 0x028a,
+	0x13ab: 0x0278, 0x13ac: 0x027b, 0x13ad: 0x027e, 0x13ae: 0x0257, 0x13af: 0x0269,
+	0x13b0: 0x026f, 0x13b1: 0x025d, 0x13b2: 0x0272, 0x13b3: 0x0251, 0x13b4: 0x025a, 0x13b5: 0x023c,
+	0x13b6: 0x023f, 0x13b7: 0x0248, 0x13b8: 0x024e, 0x13b9: 0x0260, 0x13ba: 0x0266, 0x13bb: 0x026c,
+	// Block 0x4f, offset 0x13c0
+	0x13c0: 0x19bb, 0x13c1: 0x19b8, 0x13c2: 0x19be, 0x13c3: 0x19e2, 0x13c4: 0x1a06, 0x13c5: 0x1a2a,
+	0x13c6: 0x1a4e, 0x13c7: 0x1a57, 0x13c8: 0x1a5d, 0x13c9: 0x1a63, 0x13ca: 0x1a69,
+	0x13d0: 0x1bce, 0x13d1: 0x1bd2,
+	0x13d2: 0x1bd6, 0x13d3: 0x1bda, 0x13d4: 0x1bde, 0x13d5: 0x1be2, 0x13d6: 0x1be6, 0x13d7: 0x1bea,
+	0x13d8: 0x1bee, 0x13d9: 0x1bf2, 0x13da: 0x1bf6, 0x13db: 0x1bfa, 0x13dc: 0x1bfe, 0x13dd: 0x1c02,
+	0x13de: 0x1c06, 0x13df: 0x1c0a, 0x13e0: 0x1c0e, 0x13e1: 0x1c12, 0x13e2: 0x1c16, 0x13e3: 0x1c1a,
+	0x13e4: 0x1c1e, 0x13e5: 0x1c22, 0x13e6: 0x1c26, 0x13e7: 0x1c2a, 0x13e8: 0x1c2e, 0x13e9: 0x1c32,
+	0x13ea: 0x28c9, 0x13eb: 0x0047, 0x13ec: 0x0065, 0x13ed: 0x1a7e, 0x13ee: 0x1af3,
+	0x13f0: 0x0043, 0x13f1: 0x0045, 0x13f2: 0x0047, 0x13f3: 0x0049, 0x13f4: 0x004b, 0x13f5: 0x004d,
+	0x13f6: 0x004f, 0x13f7: 0x0051, 0x13f8: 0x0053, 0x13f9: 0x0055, 0x13fa: 0x0057, 0x13fb: 0x0059,
+	0x13fc: 0x005b, 0x13fd: 0x005d, 0x13fe: 0x005f, 0x13ff: 0x0061,
+	// Block 0x50, offset 0x1400
+	0x1400: 0x2858, 0x1401: 0x286d, 0x1402: 0x0575,
+	0x1410: 0x0c81, 0x1411: 0x0ab9,
+	0x1412: 0x0945, 0x1413: 0x45aa, 0x1414: 0x078d, 0x1415: 0x0a61, 0x1416: 0x13a1, 0x1417: 0x0a71,
+	0x1418: 0x0799, 0x1419: 0x0d49, 0x141a: 0x0f21, 0x141b: 0x0d21, 0x141c: 0x0899, 0x141d: 0x0bdd,
+	0x141e: 0x0831, 0x141f: 0x0d29, 0x1420: 0x0885, 0x1421: 0x1189, 0x1422: 0x0ff5, 0x1423: 0x13fd,
+	0x1424: 0x0a45, 0x1425: 0x097d, 0x1426: 0x0ed5, 0x1427: 0x0c8d, 0x1428: 0x0cb9, 0x1429: 0x0731,
+	0x142a: 0x073d, 0x142b: 0x147d, 0x142c: 0x0b4d, 0x142d: 0x0759, 0x142e: 0x0961, 0x142f: 0x0cad,
+	0x1430: 0x1425, 0x1431: 0x0c85, 0x1432: 0x10e1, 0x1433: 0x111d, 0x1434: 0x0969, 0x1435: 0x0eb5,
+	0x1436: 0x0d7d, 0x1437: 0x0d79, 0x1438: 0x1009, 0x1439: 0x089d, 0x143a: 0x09c9,
+	// Block 0x51, offset 0x1440
+	0x1440: 0x076d, 0x1441: 0x0765, 0x1442: 0x0775, 0x1443: 0x16a9, 0x1444: 0x07b9, 0x1445: 0x07c9,
+	0x1446: 0x07cd, 0x1447: 0x07d5, 0x1448: 0x07dd, 0x1449: 0x07e1, 0x144a: 0x07ed, 0x144b: 0x07e5,
+	0x144c: 0x0625, 0x144d: 0x16bd, 0x144e: 0x0801, 0x144f: 0x0805, 0x1450: 0x0809, 0x1451: 0x0825,
+	0x1452: 0x16ae, 0x1453: 0x0629, 0x1454: 0x0811, 0x1455: 0x0831, 0x1456: 0x16b8, 0x1457: 0x0841,
+	0x1458: 0x0849, 0x1459: 0x07a9, 0x145a: 0x0851, 0x145b: 0x0855, 0x145c: 0x1893, 0x145d: 0x0871,
+	0x145e: 0x0879, 0x145f: 0x0631, 0x1460: 0x0891, 0x1461: 0x0895, 0x1462: 0x089d, 0x1463: 0x08a1,
+	0x1464: 0x0635, 0x1465: 0x08b9, 0x1466: 0x08bd, 0x1467: 0x08c9, 0x1468: 0x08d5, 0x1469: 0x08d9,
+	0x146a: 0x08dd, 0x146b: 0x08e5, 0x146c: 0x0905, 0x146d: 0x0909, 0x146e: 0x0911, 0x146f: 0x0921,
+	0x1470: 0x0929, 0x1471: 0x092d, 0x1472: 0x092d, 0x1473: 0x092d, 0x1474: 0x16cc, 0x1475: 0x0f05,
+	0x1476: 0x0941, 0x1477: 0x0949, 0x1478: 0x16d1, 0x1479: 0x0955, 0x147a: 0x095d, 0x147b: 0x0965,
+	0x147c: 0x098d, 0x147d: 0x0979, 0x147e: 0x0985, 0x147f: 0x0989,
+	// Block 0x52, offset 0x1480
+	0x1480: 0x0991, 0x1481: 0x0999, 0x1482: 0x099d, 0x1483: 0x09a5, 0x1484: 0x09ad, 0x1485: 0x09b1,
+	0x1486: 0x09b1, 0x1487: 0x09b9, 0x1488: 0x09c1, 0x1489: 0x09c5, 0x148a: 0x09d1, 0x148b: 0x09f5,
+	0x148c: 0x09d9, 0x148d: 0x09f9, 0x148e: 0x09dd, 0x148f: 0x09e5, 0x1490: 0x087d, 0x1491: 0x0a41,
+	0x1492: 0x0a09, 0x1493: 0x0a0d, 0x1494: 0x0a11, 0x1495: 0x0a05, 0x1496: 0x0a19, 0x1497: 0x0a15,
+	0x1498: 0x0a2d, 0x1499: 0x16d6, 0x149a: 0x0a49, 0x149b: 0x0a4d, 0x149c: 0x0a55, 0x149d: 0x0a61,
+	0x149e: 0x0a69, 0x149f: 0x0a85, 0x14a0: 0x16db, 0x14a1: 0x16e0, 0x14a2: 0x0a91, 0x14a3: 0x0a95,
+	0x14a4: 0x0a99, 0x14a5: 0x0a8d, 0x14a6: 0x0aa1, 0x14a7: 0x0639, 0x14a8: 0x063d, 0x14a9: 0x0aa9,
+	0x14aa: 0x0ab1, 0x14ab: 0x0ab1, 0x14ac: 0x16e5, 0x14ad: 0x0acd, 0x14ae: 0x0ad1, 0x14af: 0x0ad5,
+	0x14b0: 0x0add, 0x14b1: 0x16ea, 0x14b2: 0x0ae5, 0x14b3: 0x0ae9, 0x14b4: 0x0bc1, 0x14b5: 0x0af1,
+	0x14b6: 0x0641, 0x14b7: 0x0afd, 0x14b8: 0x0b0d, 0x14b9: 0x0b19, 0x14ba: 0x0b15, 0x14bb: 0x16f4,
+	0x14bc: 0x0b21, 0x14bd: 0x16f9, 0x14be: 0x0b2d, 0x14bf: 0x0b29,
+	// Block 0x53, offset 0x14c0
+	0x14c0: 0x0b31, 0x14c1: 0x0b41, 0x14c2: 0x0b45, 0x14c3: 0x0645, 0x14c4: 0x0b55, 0x14c5: 0x0b5d,
+	0x14c6: 0x0b61, 0x14c7: 0x0b65, 0x14c8: 0x0649, 0x14c9: 0x16fe, 0x14ca: 0x064d, 0x14cb: 0x0b81,
+	0x14cc: 0x0b85, 0x14cd: 0x0b89, 0x14ce: 0x0b91, 0x14cf: 0x18c5, 0x14d0: 0x0ba9, 0x14d1: 0x1708,
+	0x14d2: 0x1708, 0x14d3: 0x1249, 0x14d4: 0x0bb9, 0x14d5: 0x0bb9, 0x14d6: 0x0651, 0x14d7: 0x172b,
+	0x14d8: 0x17fd, 0x14d9: 0x0bc9, 0x14da: 0x0bd1, 0x14db: 0x0655, 0x14dc: 0x0be5, 0x14dd: 0x0bf5,
+	0x14de: 0x0bf9, 0x14df: 0x0c01, 0x14e0: 0x0c11, 0x14e1: 0x065d, 0x14e2: 0x0659, 0x14e3: 0x0c15,
+	0x14e4: 0x170d, 0x14e5: 0x0c19, 0x14e6: 0x0c2d, 0x14e7: 0x0c31, 0x14e8: 0x0c35, 0x14e9: 0x0c31,
+	0x14ea: 0x0c41, 0x14eb: 0x0c45, 0x14ec: 0x0c55, 0x14ed: 0x0c4d, 0x14ee: 0x0c51, 0x14ef: 0x0c59,
+	0x14f0: 0x0c5d, 0x14f1: 0x0c61, 0x14f2: 0x0c6d, 0x14f3: 0x0c71, 0x14f4: 0x0c89, 0x14f5: 0x0c91,
+	0x14f6: 0x0ca1, 0x14f7: 0x0cb5, 0x14f8: 0x171c, 0x14f9: 0x0cb1, 0x14fa: 0x0ca5, 0x14fb: 0x0cbd,
+	0x14fc: 0x0cc5, 0x14fd: 0x0cd9, 0x14fe: 0x1721, 0x14ff: 0x0ce1,
+	// Block 0x54, offset 0x1500
+	0x1500: 0x0cd5, 0x1501: 0x0ccd, 0x1502: 0x0661, 0x1503: 0x0ce9, 0x1504: 0x0cf1, 0x1505: 0x0cf9,
+	0x1506: 0x0ced, 0x1507: 0x0665, 0x1508: 0x0d09, 0x1509: 0x0d11, 0x150a: 0x1726, 0x150b: 0x0d3d,
+	0x150c: 0x0d71, 0x150d: 0x0d4d, 0x150e: 0x0671, 0x150f: 0x0d59, 0x1510: 0x066d, 0x1511: 0x0669,
+	0x1512: 0x0835, 0x1513: 0x0839, 0x1514: 0x0d75, 0x1515: 0x0d5d, 0x1516: 0x121d, 0x1517: 0x06d5,
+	0x1518: 0x0d81, 0x1519: 0x0d85, 0x151a: 0x0d89, 0x151b: 0x0d9d, 0x151c: 0x0d95, 0x151d: 0x173f,
+	0x151e: 0x0675, 0x151f: 0x0db1, 0x1520: 0x0da5, 0x1521: 0x0dc1, 0x1522: 0x0dc9, 0x1523: 0x1749,
+	0x1524: 0x0dcd, 0x1525: 0x0db9, 0x1526: 0x0dd5, 0x1527: 0x0679, 0x1528: 0x0dd9, 0x1529: 0x0ddd,
+	0x152a: 0x0de1, 0x152b: 0x0ded, 0x152c: 0x174e, 0x152d: 0x0df5, 0x152e: 0x067d, 0x152f: 0x0e01,
+	0x1530: 0x1753, 0x1531: 0x0e05, 0x1532: 0x0681, 0x1533: 0x0e11, 0x1534: 0x0e1d, 0x1535: 0x0e29,
+	0x1536: 0x0e2d, 0x1537: 0x1758, 0x1538: 0x16ef, 0x1539: 0x175d, 0x153a: 0x0e4d, 0x153b: 0x1762,
+	0x153c: 0x0e59, 0x153d: 0x0e61, 0x153e: 0x0e51, 0x153f: 0x0e6d,
+	// Block 0x55, offset 0x1540
+	0x1540: 0x0e7d, 0x1541: 0x0e8d, 0x1542: 0x0e81, 0x1543: 0x0e85, 0x1544: 0x0e91, 0x1545: 0x0e95,
+	0x1546: 0x1767, 0x1547: 0x0e79, 0x1548: 0x0ead, 0x1549: 0x0eb1, 0x154a: 0x0685, 0x154b: 0x0ec5,
+	0x154c: 0x0ec1, 0x154d: 0x176c, 0x154e: 0x0ea5, 0x154f: 0x0ee1, 0x1550: 0x1771, 0x1551: 0x1776,
+	0x1552: 0x0ee5, 0x1553: 0x0ef9, 0x1554: 0x0ef5, 0x1555: 0x0ef1, 0x1556: 0x0689, 0x1557: 0x0efd,
+	0x1558: 0x0f0d, 0x1559: 0x0f09, 0x155a: 0x0f15, 0x155b: 0x16b3, 0x155c: 0x0f25, 0x155d: 0x177b,
+	0x155e: 0x0f31, 0x155f: 0x1785, 0x1560: 0x0f45, 0x1561: 0x0f51, 0x1562: 0x0f65, 0x1563: 0x178a,
+	0x1564: 0x0f79, 0x1565: 0x0f7d, 0x1566: 0x178f, 0x1567: 0x1794, 0x1568: 0x0f99, 0x1569: 0x0fa9,
+	0x156a: 0x068d, 0x156b: 0x0fad, 0x156c: 0x0691, 0x156d: 0x0691, 0x156e: 0x0fc5, 0x156f: 0x0fc9,
+	0x1570: 0x0fd1, 0x1571: 0x0fd5, 0x1572: 0x0fe1, 0x1573: 0x0695, 0x1574: 0x0ff9, 0x1575: 0x1799,
+	0x1576: 0x1015, 0x1577: 0x179e, 0x1578: 0x1021, 0x1579: 0x1703, 0x157a: 0x1031, 0x157b: 0x17a3,
+	0x157c: 0x17a8, 0x157d: 0x17ad, 0x157e: 0x0699, 0x157f: 0x069d,
+	// Block 0x56, offset 0x1580
+	0x1580: 0x1069, 0x1581: 0x17b7, 0x1582: 0x17b2, 0x1583: 0x17bc, 0x1584: 0x17c1, 0x1585: 0x1071,
+	0x1586: 0x1075, 0x1587: 0x1075, 0x1588: 0x107d, 0x1589: 0x06a5, 0x158a: 0x1081, 0x158b: 0x06a9,
+	0x158c: 0x06ad, 0x158d: 0x17cb, 0x158e: 0x1095, 0x158f: 0x109d, 0x1590: 0x10a9, 0x1591: 0x06b1,
+	0x1592: 0x17d0, 0x1593: 0x10cd, 0x1594: 0x17d5, 0x1595: 0x17da, 0x1596: 0x10ed, 0x1597: 0x1105,
+	0x1598: 0x06b5, 0x1599: 0x110d, 0x159a: 0x1111, 0x159b: 0x1115, 0x159c: 0x17df, 0x159d: 0x17e4,
+	0x159e: 0x17e4, 0x159f: 0x112d, 0x15a0: 0x06b9, 0x15a1: 0x17e9, 0x15a2: 0x1141, 0x15a3: 0x1145,
+	0x15a4: 0x06bd, 0x15a5: 0x17ee, 0x15a6: 0x1161, 0x15a7: 0x06c1, 0x15a8: 0x1171, 0x15a9: 0x1169,
+	0x15aa: 0x1179, 0x15ab: 0x17f8, 0x15ac: 0x1191, 0x15ad: 0x06c5, 0x15ae: 0x119d, 0x15af: 0x11a5,
+	0x15b0: 0x11b5, 0x15b1: 0x06c9, 0x15b2: 0x1802, 0x15b3: 0x1807, 0x15b4: 0x06cd, 0x15b5: 0x180c,
+	0x15b6: 0x11cd, 0x15b7: 0x1811, 0x15b8: 0x11d9, 0x15b9: 0x11e5, 0x15ba: 0x11ed, 0x15bb: 0x1816,
+	0x15bc: 0x181b, 0x15bd: 0x1201, 0x15be: 0x1820, 0x15bf: 0x1209,
+	// Block 0x57, offset 0x15c0
+	0x15c0: 0x1730, 0x15c1: 0x06d1, 0x15c2: 0x1221, 0x15c3: 0x1225, 0x15c4: 0x06d9, 0x15c5: 0x1229,
+	0x15c6: 0x0aa5, 0x15c7: 0x1825, 0x15c8: 0x182a, 0x15c9: 0x1735, 0x15ca: 0x173a, 0x15cb: 0x1249,
+	0x15cc: 0x124d, 0x15cd: 0x1465, 0x15ce: 0x06dd, 0x15cf: 0x1279, 0x15d0: 0x1275, 0x15d1: 0x127d,
+	0x15d2: 0x08b1, 0x15d3: 0x1281, 0x15d4: 0x1285, 0x15d5: 0x1289, 0x15d6: 0x1291, 0x15d7: 0x182f,
+	0x15d8: 0x128d, 0x15d9: 0x1295, 0x15da: 0x12a9, 0x15db: 0x12ad, 0x15dc: 0x1299, 0x15dd: 0x12b1,
+	0x15de: 0x12c5, 0x15df: 0x12d9, 0x15e0: 0x12a5, 0x15e1: 0x12b9, 0x15e2: 0x12bd, 0x15e3: 0x12c1,
+	0x15e4: 0x1834, 0x15e5: 0x183e, 0x15e6: 0x1839, 0x15e7: 0x06e1, 0x15e8: 0x12e1, 0x15e9: 0x12e5,
+	0x15ea: 0x12ed, 0x15eb: 0x1852, 0x15ec: 0x12f1, 0x15ed: 0x1843, 0x15ee: 0x06e5, 0x15ef: 0x06e9,
+	0x15f0: 0x1848, 0x15f1: 0x184d, 0x15f2: 0x06ed, 0x15f3: 0x1311, 0x15f4: 0x1315, 0x15f5: 0x1319,
+	0x15f6: 0x131d, 0x15f7: 0x1329, 0x15f8: 0x1325, 0x15f9: 0x1331, 0x15fa: 0x132d, 0x15fb: 0x133d,
+	0x15fc: 0x1335, 0x15fd: 0x1339, 0x15fe: 0x1341, 0x15ff: 0x06f1,
+	// Block 0x58, offset 0x1600
+	0x1600: 0x1349, 0x1601: 0x134d, 0x1602: 0x06f5, 0x1603: 0x135d, 0x1604: 0x1361, 0x1605: 0x1857,
+	0x1606: 0x136d, 0x1607: 0x1371, 0x1608: 0x06f9, 0x1609: 0x137d, 0x160a: 0x062d, 0x160b: 0x185c,
+	0x160c: 0x1861, 0x160d: 0x06fd, 0x160e: 0x0701, 0x160f: 0x13a9, 0x1610: 0x13c1, 0x1611: 0x13dd,
+	0x1612: 0x13ed, 0x1613: 0x1866, 0x1614: 0x1401, 0x1615: 0x1405, 0x1616: 0x141d, 0x1617: 0x1429,
+	0x1618: 0x1870, 0x1619: 0x16c2, 0x161a: 0x1435, 0x161b: 0x1431, 0x161c: 0x143d, 0x161d: 0x16c7,
+	0x161e: 0x1449, 0x161f: 0x1455, 0x1620: 0x1875, 0x1621: 0x187a, 0x1622: 0x1495, 0x1623: 0x14a1,
+	0x1624: 0x14a9, 0x1625: 0x187f, 0x1626: 0x14ad, 0x1627: 0x14d5, 0x1628: 0x14e1, 0x1629: 0x14e5,
+	0x162a: 0x14dd, 0x162b: 0x14f1, 0x162c: 0x14f5, 0x162d: 0x1884, 0x162e: 0x1501, 0x162f: 0x0705,
+	0x1630: 0x1509, 0x1631: 0x1889, 0x1632: 0x0709, 0x1633: 0x1541, 0x1634: 0x0b35, 0x1635: 0x1559,
+	0x1636: 0x188e, 0x1637: 0x1898, 0x1638: 0x070d, 0x1639: 0x0711, 0x163a: 0x1581, 0x163b: 0x189d,
+	0x163c: 0x0715, 0x163d: 0x18a2, 0x163e: 0x1599, 0x163f: 0x1599,
+	// Block 0x59, offset 0x1640
+	0x1640: 0x15a1, 0x1641: 0x18a7, 0x1642: 0x15b9, 0x1643: 0x0719, 0x1644: 0x15c9, 0x1645: 0x15d5,
+	0x1646: 0x15dd, 0x1647: 0x15e5, 0x1648: 0x071d, 0x1649: 0x18ac, 0x164a: 0x15f9, 0x164b: 0x1615,
+	0x164c: 0x1621, 0x164d: 0x0721, 0x164e: 0x0725, 0x164f: 0x1625, 0x1650: 0x18b1, 0x1651: 0x0729,
+	0x1652: 0x18b6, 0x1653: 0x18bb, 0x1654: 0x18c0, 0x1655: 0x1649, 0x1656: 0x072d, 0x1657: 0x165d,
+	0x1658: 0x1665, 0x1659: 0x1669, 0x165a: 0x1671, 0x165b: 0x1679, 0x165c: 0x1681, 0x165d: 0x18ca,
+}
+
+// nfkcSparseOffset: 128 entries, 256 bytes
+var nfkcSparseOffset = []uint16{0x0, 0xe, 0x12, 0x1b, 0x25, 0x35, 0x37, 0x3c, 0x47, 0x56, 0x63, 0x6b, 0x6f, 0x74, 0x76, 0x85, 0x8d, 0x94, 0x97, 0x9f, 0xa3, 0xa7, 0xa9, 0xab, 0xb4, 0xb8, 0xbf, 0xc4, 0xc7, 0xd1, 0xd3, 0xda, 0xe2, 0xe6, 0xe8, 0xeb, 0xef, 0xf5, 0x106, 0x112, 0x114, 0x11a, 0x11c, 0x11e, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12b, 0x12e, 0x130, 0x133, 0x136, 0x13a, 0x143, 0x145, 0x148, 0x14a, 0x154, 0x15f, 0x16e, 0x17c, 0x18a, 0x19a, 0x1a8, 0x1af, 0x1b5, 0x1c4, 0x1c8, 0x1ca, 0x1ce, 0x1d0, 0x1d3, 0x1d5, 0x1d8, 0x1da, 0x1dd, 0x1df, 0x1e1, 0x1e3, 0x1ef, 0x1f8, 0x1ff, 0x20c, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21c, 0x21e, 0x220, 0x222, 0x224, 0x22a, 0x22d, 0x22f, 0x231, 0x233, 0x235, 0x244, 0x246, 0x24c, 0x254, 0x25b, 0x25e, 0x26b, 0x275, 0x277, 0x279, 0x27d, 0x282, 0x28e, 0x293, 0x29c, 0x2a2, 0x2a7, 0x2ab, 0x2b0, 0x2b4, 0x2c4, 0x2d2, 0x2e0, 0x2ee, 0x2f8, 0x2fa}
+
+// nfkcSparseValues: 772 entries, 3088 bytes
+var nfkcSparseValues = [772]valueRange{
+	// Block 0x0, offset 0x1
+	{value: 0x0002, lo: 0x0d},
+	{value: 0x0001, lo: 0xa0, hi: 0xa0},
+	{value: 0x425e, lo: 0xa8, hi: 0xa8},
+	{value: 0x0083, lo: 0xaa, hi: 0xaa},
+	{value: 0x424a, lo: 0xaf, hi: 0xaf},
+	{value: 0x0025, lo: 0xb2, hi: 0xb3},
+	{value: 0x4240, lo: 0xb4, hi: 0xb4},
+	{value: 0x01dc, lo: 0xb5, hi: 0xb5},
+	{value: 0x4277, lo: 0xb8, hi: 0xb8},
+	{value: 0x0023, lo: 0xb9, hi: 0xb9},
+	{value: 0x009f, lo: 0xba, hi: 0xba},
+	{value: 0x235e, lo: 0xbc, hi: 0xbc},
+	{value: 0x2352, lo: 0xbd, hi: 0xbd},
+	{value: 0x23f4, lo: 0xbe, hi: 0xbe},
+	// Block 0x1, offset 0x2
+	{value: 0x0091, lo: 0x03},
+	{value: 0x46c8, lo: 0xa0, hi: 0xa1},
+	{value: 0x46fa, lo: 0xaf, hi: 0xb0},
+	{value: 0x8800, lo: 0xb7, hi: 0xb7},
+	// Block 0x2, offset 0x3
+	{value: 0x0003, lo: 0x08},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	{value: 0x0091, lo: 0xb0, hi: 0xb0},
+	{value: 0x011c, lo: 0xb1, hi: 0xb1},
+	{value: 0x0095, lo: 0xb2, hi: 0xb2},
+	{value: 0x00a5, lo: 0xb3, hi: 0xb3},
+	{value: 0x0143, lo: 0xb4, hi: 0xb6},
+	{value: 0x00af, lo: 0xb7, hi: 0xb7},
+	{value: 0x00b3, lo: 0xb8, hi: 0xb8},
+	// Block 0x3, offset 0x4
+	{value: 0x000a, lo: 0x09},
+	{value: 0x4254, lo: 0x98, hi: 0x98},
+	{value: 0x4259, lo: 0x99, hi: 0x9a},
+	{value: 0x427c, lo: 0x9b, hi: 0x9b},
+	{value: 0x4245, lo: 0x9c, hi: 0x9c},
+	{value: 0x4268, lo: 0x9d, hi: 0x9d},
+	{value: 0x0116, lo: 0xa0, hi: 0xa0},
+	{value: 0x0099, lo: 0xa1, hi: 0xa1},
+	{value: 0x00a7, lo: 0xa2, hi: 0xa3},
+	{value: 0x0167, lo: 0xa4, hi: 0xa4},
+	// Block 0x4, offset 0x5
+	{value: 0x0000, lo: 0x0f},
+	{value: 0x8800, lo: 0x83, hi: 0x83},
+	{value: 0x8800, lo: 0x87, hi: 0x87},
+	{value: 0x8800, lo: 0x8b, hi: 0x8b},
+	{value: 0x8800, lo: 0x8d, hi: 0x8d},
+	{value: 0x378f, lo: 0x90, hi: 0x90},
+	{value: 0x379b, lo: 0x91, hi: 0x91},
+	{value: 0x3789, lo: 0x93, hi: 0x93},
+	{value: 0x8800, lo: 0x96, hi: 0x96},
+	{value: 0x3801, lo: 0x97, hi: 0x97},
+	{value: 0x37cb, lo: 0x9c, hi: 0x9c},
+	{value: 0x37b3, lo: 0x9d, hi: 0x9d},
+	{value: 0x37dd, lo: 0x9e, hi: 0x9e},
+	{value: 0x8800, lo: 0xb4, hi: 0xb5},
+	{value: 0x3807, lo: 0xb6, hi: 0xb6},
+	{value: 0x380d, lo: 0xb7, hi: 0xb7},
+	// Block 0x5, offset 0x6
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0x83, hi: 0x87},
+	// Block 0x6, offset 0x7
+	{value: 0x0001, lo: 0x04},
+	{value: 0x8018, lo: 0x81, hi: 0x82},
+	{value: 0x80e6, lo: 0x84, hi: 0x84},
+	{value: 0x80dc, lo: 0x85, hi: 0x85},
+	{value: 0x8012, lo: 0x87, hi: 0x87},
+	// Block 0x7, offset 0x8
+	{value: 0x0000, lo: 0x0a},
+	{value: 0x80e6, lo: 0x90, hi: 0x97},
+	{value: 0x801e, lo: 0x98, hi: 0x98},
+	{value: 0x801f, lo: 0x99, hi: 0x99},
+	{value: 0x8020, lo: 0x9a, hi: 0x9a},
+	{value: 0x382b, lo: 0xa2, hi: 0xa2},
+	{value: 0x3831, lo: 0xa3, hi: 0xa3},
+	{value: 0x383d, lo: 0xa4, hi: 0xa4},
+	{value: 0x3837, lo: 0xa5, hi: 0xa5},
+	{value: 0x3843, lo: 0xa6, hi: 0xa6},
+	{value: 0x8800, lo: 0xa7, hi: 0xa7},
+	// Block 0x8, offset 0x9
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x3855, lo: 0x80, hi: 0x80},
+	{value: 0x8800, lo: 0x81, hi: 0x81},
+	{value: 0x3849, lo: 0x82, hi: 0x82},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	{value: 0x384f, lo: 0x93, hi: 0x93},
+	{value: 0x8800, lo: 0x95, hi: 0x95},
+	{value: 0x80e6, lo: 0x96, hi: 0x9c},
+	{value: 0x80e6, lo: 0x9f, hi: 0xa2},
+	{value: 0x80dc, lo: 0xa3, hi: 0xa3},
+	{value: 0x80e6, lo: 0xa4, hi: 0xa4},
+	{value: 0x80e6, lo: 0xa7, hi: 0xa8},
+	{value: 0x80dc, lo: 0xaa, hi: 0xaa},
+	{value: 0x80e6, lo: 0xab, hi: 0xac},
+	{value: 0x80dc, lo: 0xad, hi: 0xad},
+	// Block 0x9, offset 0xa
+	{value: 0x0000, lo: 0x0c},
+	{value: 0x8024, lo: 0x91, hi: 0x91},
+	{value: 0x80e6, lo: 0xb0, hi: 0xb0},
+	{value: 0x80dc, lo: 0xb1, hi: 0xb1},
+	{value: 0x80e6, lo: 0xb2, hi: 0xb3},
+	{value: 0x80dc, lo: 0xb4, hi: 0xb4},
+	{value: 0x80e6, lo: 0xb5, hi: 0xb6},
+	{value: 0x80dc, lo: 0xb7, hi: 0xb9},
+	{value: 0x80e6, lo: 0xba, hi: 0xba},
+	{value: 0x80dc, lo: 0xbb, hi: 0xbc},
+	{value: 0x80e6, lo: 0xbd, hi: 0xbd},
+	{value: 0x80dc, lo: 0xbe, hi: 0xbe},
+	{value: 0x80e6, lo: 0xbf, hi: 0xbf},
+	// Block 0xa, offset 0xb
+	{value: 0x000a, lo: 0x07},
+	{value: 0x80e6, lo: 0x80, hi: 0x80},
+	{value: 0x80e6, lo: 0x81, hi: 0x81},
+	{value: 0x80dc, lo: 0x82, hi: 0x83},
+	{value: 0x80dc, lo: 0x84, hi: 0x85},
+	{value: 0x80dc, lo: 0x86, hi: 0x87},
+	{value: 0x80dc, lo: 0x88, hi: 0x89},
+	{value: 0x80e6, lo: 0x8a, hi: 0x8a},
+	// Block 0xb, offset 0xc
+	{value: 0x0000, lo: 0x03},
+	{value: 0x80e6, lo: 0xab, hi: 0xb1},
+	{value: 0x80dc, lo: 0xb2, hi: 0xb2},
+	{value: 0x80e6, lo: 0xb3, hi: 0xb3},
+	// Block 0xc, offset 0xd
+	{value: 0x0000, lo: 0x04},
+	{value: 0x80e6, lo: 0x96, hi: 0x99},
+	{value: 0x80e6, lo: 0x9b, hi: 0xa3},
+	{value: 0x80e6, lo: 0xa5, hi: 0xa7},
+	{value: 0x80e6, lo: 0xa9, hi: 0xad},
+	// Block 0xd, offset 0xe
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80dc, lo: 0x99, hi: 0x9b},
+	// Block 0xe, offset 0xf
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x80e6, lo: 0xa4, hi: 0xa5},
+	{value: 0x80dc, lo: 0xa6, hi: 0xa6},
+	{value: 0x80e6, lo: 0xa7, hi: 0xa8},
+	{value: 0x80dc, lo: 0xa9, hi: 0xa9},
+	{value: 0x80e6, lo: 0xaa, hi: 0xac},
+	{value: 0x80dc, lo: 0xad, hi: 0xaf},
+	{value: 0x801b, lo: 0xb0, hi: 0xb0},
+	{value: 0x801c, lo: 0xb1, hi: 0xb1},
+	{value: 0x801d, lo: 0xb2, hi: 0xb2},
+	{value: 0x80e6, lo: 0xb3, hi: 0xb5},
+	{value: 0x80dc, lo: 0xb6, hi: 0xb6},
+	{value: 0x80e6, lo: 0xb7, hi: 0xb8},
+	{value: 0x80dc, lo: 0xb9, hi: 0xba},
+	{value: 0x80e6, lo: 0xbb, hi: 0xbe},
+	// Block 0xf, offset 0x10
+	{value: 0x0000, lo: 0x07},
+	{value: 0x8800, lo: 0xa8, hi: 0xa8},
+	{value: 0x3ec2, lo: 0xa9, hi: 0xa9},
+	{value: 0x8800, lo: 0xb0, hi: 0xb0},
+	{value: 0x3eca, lo: 0xb1, hi: 0xb1},
+	{value: 0x8800, lo: 0xb3, hi: 0xb3},
+	{value: 0x3ed2, lo: 0xb4, hi: 0xb4},
+	{value: 0x8607, lo: 0xbc, hi: 0xbc},
+	// Block 0x10, offset 0x11
+	{value: 0x0008, lo: 0x06},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x80e6, lo: 0x91, hi: 0x91},
+	{value: 0x80dc, lo: 0x92, hi: 0x92},
+	{value: 0x80e6, lo: 0x93, hi: 0x93},
+	{value: 0x80e6, lo: 0x94, hi: 0x94},
+	{value: 0x4502, lo: 0x98, hi: 0x9f},
+	// Block 0x11, offset 0x12
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8007, lo: 0xbc, hi: 0xbc},
+	{value: 0x8600, lo: 0xbe, hi: 0xbe},
+	// Block 0x12, offset 0x13
+	{value: 0x0007, lo: 0x07},
+	{value: 0x8800, lo: 0x87, hi: 0x87},
+	{value: 0x18cf, lo: 0x8b, hi: 0x8c},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8600, lo: 0x97, hi: 0x97},
+	{value: 0x4542, lo: 0x9c, hi: 0x9c},
+	{value: 0x454a, lo: 0x9d, hi: 0x9d},
+	{value: 0x4552, lo: 0x9f, hi: 0x9f},
+	// Block 0x13, offset 0x14
+	{value: 0x0000, lo: 0x03},
+	{value: 0x457a, lo: 0xb3, hi: 0xb3},
+	{value: 0x4582, lo: 0xb6, hi: 0xb6},
+	{value: 0x8007, lo: 0xbc, hi: 0xbc},
+	// Block 0x14, offset 0x15
+	{value: 0x0008, lo: 0x03},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x455a, lo: 0x99, hi: 0x9b},
+	{value: 0x4572, lo: 0x9e, hi: 0x9e},
+	// Block 0x15, offset 0x16
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8007, lo: 0xbc, hi: 0xbc},
+	// Block 0x16, offset 0x17
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	// Block 0x17, offset 0x18
+	{value: 0x0000, lo: 0x08},
+	{value: 0x8800, lo: 0x87, hi: 0x87},
+	{value: 0x18e4, lo: 0x88, hi: 0x88},
+	{value: 0x18dd, lo: 0x8b, hi: 0x8b},
+	{value: 0x18eb, lo: 0x8c, hi: 0x8c},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8600, lo: 0x96, hi: 0x97},
+	{value: 0x458a, lo: 0x9c, hi: 0x9c},
+	{value: 0x4592, lo: 0x9d, hi: 0x9d},
+	// Block 0x18, offset 0x19
+	{value: 0x0000, lo: 0x03},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	{value: 0x18f2, lo: 0x94, hi: 0x94},
+	{value: 0x8600, lo: 0xbe, hi: 0xbe},
+	// Block 0x19, offset 0x1a
+	{value: 0x0000, lo: 0x06},
+	{value: 0x8800, lo: 0x86, hi: 0x87},
+	{value: 0x18f9, lo: 0x8a, hi: 0x8a},
+	{value: 0x1907, lo: 0x8b, hi: 0x8b},
+	{value: 0x1900, lo: 0x8c, hi: 0x8c},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8600, lo: 0x97, hi: 0x97},
+	// Block 0x1a, offset 0x1b
+	{value: 0x0607, lo: 0x04},
+	{value: 0x8800, lo: 0x86, hi: 0x86},
+	{value: 0x3eda, lo: 0x88, hi: 0x88},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8054, lo: 0x95, hi: 0x96},
+	// Block 0x1b, offset 0x1c
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8007, lo: 0xbc, hi: 0xbc},
+	{value: 0x8800, lo: 0xbf, hi: 0xbf},
+	// Block 0x1c, offset 0x1d
+	{value: 0x0000, lo: 0x09},
+	{value: 0x190e, lo: 0x80, hi: 0x80},
+	{value: 0x8600, lo: 0x82, hi: 0x82},
+	{value: 0x8800, lo: 0x86, hi: 0x86},
+	{value: 0x1915, lo: 0x87, hi: 0x87},
+	{value: 0x191c, lo: 0x88, hi: 0x88},
+	{value: 0x2e66, lo: 0x8a, hi: 0x8a},
+	{value: 0x19a5, lo: 0x8b, hi: 0x8b},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8600, lo: 0x95, hi: 0x96},
+	// Block 0x1d, offset 0x1e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8600, lo: 0xbe, hi: 0xbe},
+	// Block 0x1e, offset 0x1f
+	{value: 0x0000, lo: 0x06},
+	{value: 0x8800, lo: 0x86, hi: 0x87},
+	{value: 0x1923, lo: 0x8a, hi: 0x8a},
+	{value: 0x1931, lo: 0x8b, hi: 0x8b},
+	{value: 0x192a, lo: 0x8c, hi: 0x8c},
+	{value: 0x8009, lo: 0x8d, hi: 0x8d},
+	{value: 0x8600, lo: 0x97, hi: 0x97},
+	// Block 0x1f, offset 0x20
+	{value: 0x0007, lo: 0x07},
+	{value: 0x8609, lo: 0x8a, hi: 0x8a},
+	{value: 0x8600, lo: 0x8f, hi: 0x8f},
+	{value: 0x8800, lo: 0x99, hi: 0x99},
+	{value: 0x3ee2, lo: 0x9a, hi: 0x9a},
+	{value: 0x2e6d, lo: 0x9c, hi: 0x9d},
+	{value: 0x1938, lo: 0x9e, hi: 0x9e},
+	{value: 0x8600, lo: 0x9f, hi: 0x9f},
+	// Block 0x20, offset 0x21
+	{value: 0x0000, lo: 0x03},
+	{value: 0x2763, lo: 0xb3, hi: 0xb3},
+	{value: 0x8067, lo: 0xb8, hi: 0xb9},
+	{value: 0x8009, lo: 0xba, hi: 0xba},
+	// Block 0x21, offset 0x22
+	{value: 0x0000, lo: 0x01},
+	{value: 0x806b, lo: 0x88, hi: 0x8b},
+	// Block 0x22, offset 0x23
+	{value: 0x0000, lo: 0x02},
+	{value: 0x2778, lo: 0xb3, hi: 0xb3},
+	{value: 0x8076, lo: 0xb8, hi: 0xb9},
+	// Block 0x23, offset 0x24
+	{value: 0x0000, lo: 0x03},
+	{value: 0x807a, lo: 0x88, hi: 0x8b},
+	{value: 0x276a, lo: 0x9c, hi: 0x9c},
+	{value: 0x2771, lo: 0x9d, hi: 0x9d},
+	// Block 0x24, offset 0x25
+	{value: 0x0000, lo: 0x05},
+	{value: 0x0305, lo: 0x8c, hi: 0x8c},
+	{value: 0x80dc, lo: 0x98, hi: 0x99},
+	{value: 0x80dc, lo: 0xb5, hi: 0xb5},
+	{value: 0x80dc, lo: 0xb7, hi: 0xb7},
+	{value: 0x80d8, lo: 0xb9, hi: 0xb9},
+	// Block 0x25, offset 0x26
+	{value: 0x0000, lo: 0x10},
+	{value: 0x2786, lo: 0x83, hi: 0x83},
+	{value: 0x278d, lo: 0x8d, hi: 0x8d},
+	{value: 0x2794, lo: 0x92, hi: 0x92},
+	{value: 0x279b, lo: 0x97, hi: 0x97},
+	{value: 0x27a2, lo: 0x9c, hi: 0x9c},
+	{value: 0x277f, lo: 0xa9, hi: 0xa9},
+	{value: 0x8081, lo: 0xb1, hi: 0xb1},
+	{value: 0x8082, lo: 0xb2, hi: 0xb2},
+	{value: 0x49b6, lo: 0xb3, hi: 0xb3},
+	{value: 0x8084, lo: 0xb4, hi: 0xb4},
+	{value: 0x49bf, lo: 0xb5, hi: 0xb5},
+	{value: 0x459a, lo: 0xb6, hi: 0xb6},
+	{value: 0x45da, lo: 0xb7, hi: 0xb7},
+	{value: 0x45a2, lo: 0xb8, hi: 0xb8},
+	{value: 0x45e5, lo: 0xb9, hi: 0xb9},
+	{value: 0x8082, lo: 0xba, hi: 0xbd},
+	// Block 0x26, offset 0x27
+	{value: 0x0000, lo: 0x0b},
+	{value: 0x8082, lo: 0x80, hi: 0x80},
+	{value: 0x49c8, lo: 0x81, hi: 0x81},
+	{value: 0x80e6, lo: 0x82, hi: 0x83},
+	{value: 0x8009, lo: 0x84, hi: 0x84},
+	{value: 0x80e6, lo: 0x86, hi: 0x87},
+	{value: 0x27b0, lo: 0x93, hi: 0x93},
+	{value: 0x27b7, lo: 0x9d, hi: 0x9d},
+	{value: 0x27be, lo: 0xa2, hi: 0xa2},
+	{value: 0x27c5, lo: 0xa7, hi: 0xa7},
+	{value: 0x27cc, lo: 0xac, hi: 0xac},
+	{value: 0x27a9, lo: 0xb9, hi: 0xb9},
+	// Block 0x27, offset 0x28
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80dc, lo: 0x86, hi: 0x86},
+	// Block 0x28, offset 0x29
+	{value: 0x0000, lo: 0x05},
+	{value: 0x8800, lo: 0xa5, hi: 0xa5},
+	{value: 0x193f, lo: 0xa6, hi: 0xa6},
+	{value: 0x8600, lo: 0xae, hi: 0xae},
+	{value: 0x8007, lo: 0xb7, hi: 0xb7},
+	{value: 0x8009, lo: 0xb9, hi: 0xba},
+	// Block 0x29, offset 0x2a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80dc, lo: 0x8d, hi: 0x8d},
+	// Block 0x2a, offset 0x2b
+	{value: 0x0000, lo: 0x01},
+	{value: 0x0309, lo: 0xbc, hi: 0xbc},
+	// Block 0x2b, offset 0x2c
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8800, lo: 0x80, hi: 0x92},
+	// Block 0x2c, offset 0x2d
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8e00, lo: 0xa1, hi: 0xb5},
+	// Block 0x2d, offset 0x2e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8600, lo: 0xa8, hi: 0xbf},
+	// Block 0x2e, offset 0x2f
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8600, lo: 0x80, hi: 0x82},
+	// Block 0x2f, offset 0x30
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0x9d, hi: 0x9f},
+	// Block 0x30, offset 0x31
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8009, lo: 0x94, hi: 0x94},
+	{value: 0x8009, lo: 0xb4, hi: 0xb4},
+	// Block 0x31, offset 0x32
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8009, lo: 0x92, hi: 0x92},
+	{value: 0x80e6, lo: 0x9d, hi: 0x9d},
+	// Block 0x32, offset 0x33
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e4, lo: 0xa9, hi: 0xa9},
+	// Block 0x33, offset 0x34
+	{value: 0x0008, lo: 0x02},
+	{value: 0x80de, lo: 0xb9, hi: 0xba},
+	{value: 0x80dc, lo: 0xbb, hi: 0xbb},
+	// Block 0x34, offset 0x35
+	{value: 0x0000, lo: 0x02},
+	{value: 0x80e6, lo: 0x97, hi: 0x97},
+	{value: 0x80dc, lo: 0x98, hi: 0x98},
+	// Block 0x35, offset 0x36
+	{value: 0x0000, lo: 0x03},
+	{value: 0x8009, lo: 0xa0, hi: 0xa0},
+	{value: 0x80e6, lo: 0xb5, hi: 0xbc},
+	{value: 0x80dc, lo: 0xbf, hi: 0xbf},
+	// Block 0x36, offset 0x37
+	{value: 0x0000, lo: 0x08},
+	{value: 0x197e, lo: 0x80, hi: 0x80},
+	{value: 0x1985, lo: 0x81, hi: 0x81},
+	{value: 0x8800, lo: 0x82, hi: 0x82},
+	{value: 0x198c, lo: 0x83, hi: 0x83},
+	{value: 0x8009, lo: 0x84, hi: 0x84},
+	{value: 0x80e6, lo: 0xab, hi: 0xab},
+	{value: 0x80dc, lo: 0xac, hi: 0xac},
+	{value: 0x80e6, lo: 0xad, hi: 0xb3},
+	// Block 0x37, offset 0x38
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0xaa, hi: 0xab},
+	// Block 0x38, offset 0x39
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8007, lo: 0xa6, hi: 0xa6},
+	{value: 0x8009, lo: 0xb2, hi: 0xb3},
+	// Block 0x39, offset 0x3a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8007, lo: 0xb7, hi: 0xb7},
+	// Block 0x3a, offset 0x3b
+	{value: 0x0000, lo: 0x09},
+	{value: 0x80e6, lo: 0x90, hi: 0x92},
+	{value: 0x8001, lo: 0x94, hi: 0x94},
+	{value: 0x80dc, lo: 0x95, hi: 0x99},
+	{value: 0x80e6, lo: 0x9a, hi: 0x9b},
+	{value: 0x80dc, lo: 0x9c, hi: 0x9f},
+	{value: 0x80e6, lo: 0xa0, hi: 0xa0},
+	{value: 0x8001, lo: 0xa2, hi: 0xa8},
+	{value: 0x80dc, lo: 0xad, hi: 0xad},
+	{value: 0x80e6, lo: 0xb4, hi: 0xb4},
+	// Block 0x3b, offset 0x3c
+	{value: 0x0002, lo: 0x0a},
+	{value: 0x0043, lo: 0xac, hi: 0xac},
+	{value: 0x00d4, lo: 0xad, hi: 0xad},
+	{value: 0x0045, lo: 0xae, hi: 0xae},
+	{value: 0x0049, lo: 0xb0, hi: 0xb1},
+	{value: 0x00e9, lo: 0xb2, hi: 0xb2},
+	{value: 0x004f, lo: 0xb3, hi: 0xba},
+	{value: 0x005f, lo: 0xbc, hi: 0xbc},
+	{value: 0x00f2, lo: 0xbd, hi: 0xbd},
+	{value: 0x0061, lo: 0xbe, hi: 0xbe},
+	{value: 0x0065, lo: 0xbf, hi: 0xbf},
+	// Block 0x3c, offset 0x3d
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x80e6, lo: 0x80, hi: 0x81},
+	{value: 0x80dc, lo: 0x82, hi: 0x82},
+	{value: 0x80e6, lo: 0x83, hi: 0x89},
+	{value: 0x80dc, lo: 0x8a, hi: 0x8a},
+	{value: 0x80e6, lo: 0x8b, hi: 0x8c},
+	{value: 0x80ea, lo: 0x8d, hi: 0x8d},
+	{value: 0x80d6, lo: 0x8e, hi: 0x8e},
+	{value: 0x80dc, lo: 0x8f, hi: 0x8f},
+	{value: 0x80ca, lo: 0x90, hi: 0x90},
+	{value: 0x80e6, lo: 0x91, hi: 0xa6},
+	{value: 0x80e9, lo: 0xbc, hi: 0xbc},
+	{value: 0x80dc, lo: 0xbd, hi: 0xbd},
+	{value: 0x80e6, lo: 0xbe, hi: 0xbe},
+	{value: 0x80dc, lo: 0xbf, hi: 0xbf},
+	// Block 0x3d, offset 0x3e
+	{value: 0x0000, lo: 0x0d},
+	{value: 0x0001, lo: 0x80, hi: 0x8a},
+	{value: 0x04ad, lo: 0x91, hi: 0x91},
+	{value: 0x4281, lo: 0x97, hi: 0x97},
+	{value: 0x001d, lo: 0xa4, hi: 0xa4},
+	{value: 0x19b5, lo: 0xa5, hi: 0xa5},
+	{value: 0x1c9e, lo: 0xa6, hi: 0xa6},
+	{value: 0x0001, lo: 0xaf, hi: 0xaf},
+	{value: 0x283c, lo: 0xb3, hi: 0xb3},
+	{value: 0x29a9, lo: 0xb4, hi: 0xb4},
+	{value: 0x2843, lo: 0xb6, hi: 0xb6},
+	{value: 0x29b3, lo: 0xb7, hi: 0xb7},
+	{value: 0x19af, lo: 0xbc, hi: 0xbc},
+	{value: 0x424f, lo: 0xbe, hi: 0xbe},
+	// Block 0x3e, offset 0x3f
+	{value: 0x0002, lo: 0x0d},
+	{value: 0x1a75, lo: 0x87, hi: 0x87},
+	{value: 0x1a72, lo: 0x88, hi: 0x88},
+	{value: 0x19b2, lo: 0x89, hi: 0x89},
+	{value: 0x2b46, lo: 0x97, hi: 0x97},
+	{value: 0x0001, lo: 0x9f, hi: 0x9f},
+	{value: 0x0021, lo: 0xb0, hi: 0xb0},
+	{value: 0x0093, lo: 0xb1, hi: 0xb1},
+	{value: 0x0029, lo: 0xb4, hi: 0xb9},
+	{value: 0x0017, lo: 0xba, hi: 0xba},
+	{value: 0x04d9, lo: 0xbb, hi: 0xbb},
+	{value: 0x003b, lo: 0xbc, hi: 0xbc},
+	{value: 0x0011, lo: 0xbd, hi: 0xbe},
+	{value: 0x009d, lo: 0xbf, hi: 0xbf},
+	// Block 0x3f, offset 0x40
+	{value: 0x0002, lo: 0x0f},
+	{value: 0x0021, lo: 0x80, hi: 0x89},
+	{value: 0x0017, lo: 0x8a, hi: 0x8a},
+	{value: 0x04d9, lo: 0x8b, hi: 0x8b},
+	{value: 0x003b, lo: 0x8c, hi: 0x8c},
+	{value: 0x0011, lo: 0x8d, hi: 0x8e},
+	{value: 0x0083, lo: 0x90, hi: 0x90},
+	{value: 0x008b, lo: 0x91, hi: 0x91},
+	{value: 0x009f, lo: 0x92, hi: 0x92},
+	{value: 0x00b1, lo: 0x93, hi: 0x93},
+	{value: 0x0107, lo: 0x94, hi: 0x94},
+	{value: 0x0091, lo: 0x95, hi: 0x95},
+	{value: 0x0097, lo: 0x96, hi: 0x99},
+	{value: 0x00a1, lo: 0x9a, hi: 0x9a},
+	{value: 0x00a7, lo: 0x9b, hi: 0x9c},
+	{value: 0x1adb, lo: 0xa8, hi: 0xa8},
+	// Block 0x40, offset 0x41
+	{value: 0x0000, lo: 0x0d},
+	{value: 0x80e6, lo: 0x90, hi: 0x91},
+	{value: 0x8001, lo: 0x92, hi: 0x93},
+	{value: 0x80e6, lo: 0x94, hi: 0x97},
+	{value: 0x8001, lo: 0x98, hi: 0x9a},
+	{value: 0x80e6, lo: 0x9b, hi: 0x9c},
+	{value: 0x80e6, lo: 0xa1, hi: 0xa1},
+	{value: 0x8001, lo: 0xa5, hi: 0xa6},
+	{value: 0x80e6, lo: 0xa7, hi: 0xa7},
+	{value: 0x80dc, lo: 0xa8, hi: 0xa8},
+	{value: 0x80e6, lo: 0xa9, hi: 0xa9},
+	{value: 0x8001, lo: 0xaa, hi: 0xab},
+	{value: 0x80dc, lo: 0xac, hi: 0xaf},
+	{value: 0x80e6, lo: 0xb0, hi: 0xb0},
+	// Block 0x41, offset 0x42
+	{value: 0x0007, lo: 0x06},
+	{value: 0x22c2, lo: 0x89, hi: 0x89},
+	{value: 0x8800, lo: 0x90, hi: 0x90},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	{value: 0x8800, lo: 0x94, hi: 0x94},
+	{value: 0x3ba3, lo: 0x9a, hi: 0x9b},
+	{value: 0x3bb1, lo: 0xae, hi: 0xae},
+	// Block 0x42, offset 0x43
+	{value: 0x000e, lo: 0x05},
+	{value: 0x3bb8, lo: 0x8d, hi: 0x8e},
+	{value: 0x3bbf, lo: 0x8f, hi: 0x8f},
+	{value: 0x8800, lo: 0x90, hi: 0x90},
+	{value: 0x8800, lo: 0x92, hi: 0x92},
+	{value: 0x8800, lo: 0x94, hi: 0x94},
+	// Block 0x43, offset 0x44
+	{value: 0x0173, lo: 0x0e},
+	{value: 0x8800, lo: 0x83, hi: 0x83},
+	{value: 0x3bcd, lo: 0x84, hi: 0x84},
+	{value: 0x8800, lo: 0x88, hi: 0x88},
+	{value: 0x3bd4, lo: 0x89, hi: 0x89},
+	{value: 0x8800, lo: 0x8b, hi: 0x8b},
+	{value: 0x3bdb, lo: 0x8c, hi: 0x8c},
+	{value: 0x8800, lo: 0xa3, hi: 0xa3},
+	{value: 0x3be2, lo: 0xa4, hi: 0xa4},
+	{value: 0x8800, lo: 0xa5, hi: 0xa5},
+	{value: 0x3be9, lo: 0xa6, hi: 0xa6},
+	{value: 0x284a, lo: 0xac, hi: 0xad},
+	{value: 0x2851, lo: 0xaf, hi: 0xaf},
+	{value: 0x29c7, lo: 0xb0, hi: 0xb0},
+	{value: 0x8800, lo: 0xbc, hi: 0xbc},
+	// Block 0x44, offset 0x45
+	{value: 0x0007, lo: 0x03},
+	{value: 0x3c52, lo: 0xa0, hi: 0xa1},
+	{value: 0x3c7c, lo: 0xa2, hi: 0xa3},
+	{value: 0x3ca6, lo: 0xaa, hi: 0xad},
+	// Block 0x45, offset 0x46
+	{value: 0x0004, lo: 0x01},
+	{value: 0x04fd, lo: 0xa9, hi: 0xaa},
+	// Block 0x46, offset 0x47
+	{value: 0x0002, lo: 0x03},
+	{value: 0x0057, lo: 0x80, hi: 0x8f},
+	{value: 0x0083, lo: 0x90, hi: 0xa9},
+	{value: 0x0021, lo: 0xaa, hi: 0xaa},
+	// Block 0x47, offset 0x48
+	{value: 0x0000, lo: 0x01},
+	{value: 0x2b53, lo: 0x8c, hi: 0x8c},
+	// Block 0x48, offset 0x49
+	{value: 0x0263, lo: 0x02},
+	{value: 0x1cce, lo: 0xb4, hi: 0xb4},
+	{value: 0x1a6f, lo: 0xb5, hi: 0xb6},
+	// Block 0x49, offset 0x4a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x44c3, lo: 0x9c, hi: 0x9c},
+	// Block 0x4a, offset 0x4b
+	{value: 0x0000, lo: 0x02},
+	{value: 0x0095, lo: 0xbc, hi: 0xbc},
+	{value: 0x006d, lo: 0xbd, hi: 0xbd},
+	// Block 0x4b, offset 0x4c
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0xaf, hi: 0xb1},
+	// Block 0x4c, offset 0x4d
+	{value: 0x0000, lo: 0x02},
+	{value: 0x04f1, lo: 0xaf, hi: 0xaf},
+	{value: 0x8009, lo: 0xbf, hi: 0xbf},
+	// Block 0x4d, offset 0x4e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0xa0, hi: 0xbf},
+	// Block 0x4e, offset 0x4f
+	{value: 0x0000, lo: 0x01},
+	{value: 0x0e35, lo: 0x9f, hi: 0x9f},
+	// Block 0x4f, offset 0x50
+	{value: 0x0000, lo: 0x01},
+	{value: 0x169d, lo: 0xb3, hi: 0xb3},
+	// Block 0x50, offset 0x51
+	{value: 0x0004, lo: 0x0b},
+	{value: 0x1605, lo: 0x80, hi: 0x82},
+	{value: 0x161d, lo: 0x83, hi: 0x83},
+	{value: 0x1635, lo: 0x84, hi: 0x85},
+	{value: 0x1645, lo: 0x86, hi: 0x89},
+	{value: 0x1659, lo: 0x8a, hi: 0x8c},
+	{value: 0x166d, lo: 0x8d, hi: 0x8d},
+	{value: 0x1675, lo: 0x8e, hi: 0x8e},
+	{value: 0x167d, lo: 0x8f, hi: 0x90},
+	{value: 0x1689, lo: 0x91, hi: 0x93},
+	{value: 0x1699, lo: 0x94, hi: 0x94},
+	{value: 0x16a1, lo: 0x95, hi: 0x95},
+	// Block 0x51, offset 0x52
+	{value: 0x0004, lo: 0x08},
+	{value: 0x0001, lo: 0x80, hi: 0x80},
+	{value: 0x80da, lo: 0xaa, hi: 0xaa},
+	{value: 0x80e4, lo: 0xab, hi: 0xac},
+	{value: 0x80de, lo: 0xad, hi: 0xad},
+	{value: 0x80e0, lo: 0xae, hi: 0xae},
+	{value: 0x80e0, lo: 0xaf, hi: 0xaf},
+	{value: 0x0525, lo: 0xb6, hi: 0xb6},
+	{value: 0x08f9, lo: 0xb8, hi: 0xba},
+	// Block 0x52, offset 0x53
+	{value: 0x0004, lo: 0x06},
+	{value: 0x030d, lo: 0xb1, hi: 0xb2},
+	{value: 0x0435, lo: 0xb3, hi: 0xb3},
+	{value: 0x0315, lo: 0xb4, hi: 0xb4},
+	{value: 0x0439, lo: 0xb5, hi: 0xb6},
+	{value: 0x0319, lo: 0xb7, hi: 0xb9},
+	{value: 0x0441, lo: 0xba, hi: 0xbf},
+	// Block 0x53, offset 0x54
+	{value: 0x0004, lo: 0x0c},
+	{value: 0x0361, lo: 0x80, hi: 0x80},
+	{value: 0x0325, lo: 0x81, hi: 0x83},
+	{value: 0x0375, lo: 0x84, hi: 0x84},
+	{value: 0x0331, lo: 0x85, hi: 0x8e},
+	{value: 0x03c1, lo: 0x8f, hi: 0xa3},
+	{value: 0x03bd, lo: 0xa4, hi: 0xa4},
+	{value: 0x0359, lo: 0xa5, hi: 0xa6},
+	{value: 0x0459, lo: 0xa7, hi: 0xad},
+	{value: 0x0365, lo: 0xae, hi: 0xae},
+	{value: 0x0475, lo: 0xaf, hi: 0xb0},
+	{value: 0x0369, lo: 0xb1, hi: 0xb3},
+	{value: 0x0379, lo: 0xb4, hi: 0xbf},
+	// Block 0x54, offset 0x55
+	{value: 0x0000, lo: 0x02},
+	{value: 0x80e6, lo: 0xaf, hi: 0xaf},
+	{value: 0x80e6, lo: 0xb4, hi: 0xbd},
+	// Block 0x55, offset 0x56
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0x9f, hi: 0x9f},
+	// Block 0x56, offset 0x57
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0xb0, hi: 0xb1},
+	// Block 0x57, offset 0x58
+	{value: 0x0000, lo: 0x01},
+	{value: 0x16a5, lo: 0xb0, hi: 0xb0},
+	// Block 0x58, offset 0x59
+	{value: 0x000c, lo: 0x01},
+	{value: 0x00da, lo: 0xb8, hi: 0xb9},
+	// Block 0x59, offset 0x5a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0x86, hi: 0x86},
+	// Block 0x5a, offset 0x5b
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8009, lo: 0x84, hi: 0x84},
+	{value: 0x80e6, lo: 0xa0, hi: 0xb1},
+	// Block 0x5b, offset 0x5c
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80dc, lo: 0xab, hi: 0xad},
+	// Block 0x5c, offset 0x5d
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0x93, hi: 0x93},
+	// Block 0x5d, offset 0x5e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8007, lo: 0xb3, hi: 0xb3},
+	// Block 0x5e, offset 0x5f
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0x80, hi: 0x80},
+	// Block 0x5f, offset 0x60
+	{value: 0x0000, lo: 0x05},
+	{value: 0x80e6, lo: 0xb0, hi: 0xb0},
+	{value: 0x80e6, lo: 0xb2, hi: 0xb3},
+	{value: 0x80dc, lo: 0xb4, hi: 0xb4},
+	{value: 0x80e6, lo: 0xb7, hi: 0xb8},
+	{value: 0x80e6, lo: 0xbe, hi: 0xbf},
+	// Block 0x60, offset 0x61
+	{value: 0x0000, lo: 0x02},
+	{value: 0x80e6, lo: 0x81, hi: 0x81},
+	{value: 0x8009, lo: 0xb6, hi: 0xb6},
+	// Block 0x61, offset 0x62
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8009, lo: 0xad, hi: 0xad},
+	// Block 0x62, offset 0x63
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0x80, hi: 0xbf},
+	// Block 0x63, offset 0x64
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0x80, hi: 0xa3},
+	// Block 0x64, offset 0x65
+	{value: 0x0002, lo: 0x01},
+	{value: 0x0003, lo: 0x81, hi: 0xbf},
+	// Block 0x65, offset 0x66
+	{value: 0x0004, lo: 0x0e},
+	{value: 0x03c1, lo: 0x82, hi: 0x87},
+	{value: 0x03d9, lo: 0x8a, hi: 0x8f},
+	{value: 0x03f1, lo: 0x92, hi: 0x97},
+	{value: 0x0409, lo: 0x9a, hi: 0x9c},
+	{value: 0x00bf, lo: 0xa0, hi: 0xa0},
+	{value: 0x00c2, lo: 0xa1, hi: 0xa1},
+	{value: 0x00cb, lo: 0xa2, hi: 0xa2},
+	{value: 0x424a, lo: 0xa3, hi: 0xa3},
+	{value: 0x00c8, lo: 0xa4, hi: 0xa4},
+	{value: 0x00c5, lo: 0xa5, hi: 0xa5},
+	{value: 0x04b9, lo: 0xa6, hi: 0xa6},
+	{value: 0x04dd, lo: 0xa8, hi: 0xa8},
+	{value: 0x04bd, lo: 0xa9, hi: 0xac},
+	{value: 0x04e1, lo: 0xad, hi: 0xae},
+	// Block 0x66, offset 0x67
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80dc, lo: 0xbd, hi: 0xbd},
+	// Block 0x67, offset 0x68
+	{value: 0x00db, lo: 0x05},
+	{value: 0x80dc, lo: 0x8d, hi: 0x8d},
+	{value: 0x80e6, lo: 0x8f, hi: 0x8f},
+	{value: 0x80e6, lo: 0xb8, hi: 0xb8},
+	{value: 0x8001, lo: 0xb9, hi: 0xba},
+	{value: 0x8009, lo: 0xbf, hi: 0xbf},
+	// Block 0x68, offset 0x69
+	{value: 0x05fe, lo: 0x07},
+	{value: 0x8800, lo: 0x99, hi: 0x99},
+	{value: 0x4222, lo: 0x9a, hi: 0x9a},
+	{value: 0x8800, lo: 0x9b, hi: 0x9b},
+	{value: 0x422c, lo: 0x9c, hi: 0x9c},
+	{value: 0x8800, lo: 0xa5, hi: 0xa5},
+	{value: 0x4236, lo: 0xab, hi: 0xab},
+	{value: 0x8009, lo: 0xb9, hi: 0xba},
+	// Block 0x69, offset 0x6a
+	{value: 0x0000, lo: 0x06},
+	{value: 0x80e6, lo: 0x80, hi: 0x82},
+	{value: 0x8600, lo: 0xa7, hi: 0xa7},
+	{value: 0x1993, lo: 0xae, hi: 0xae},
+	{value: 0x199c, lo: 0xaf, hi: 0xaf},
+	{value: 0x8800, lo: 0xb1, hi: 0xb2},
+	{value: 0x8009, lo: 0xb3, hi: 0xb4},
+	// Block 0x6a, offset 0x6b
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8009, lo: 0xb6, hi: 0xb6},
+	{value: 0x8007, lo: 0xb7, hi: 0xb7},
+	// Block 0x6b, offset 0x6c
+	{value: 0x0000, lo: 0x0c},
+	{value: 0x45b2, lo: 0x9e, hi: 0x9e},
+	{value: 0x45bc, lo: 0x9f, hi: 0x9f},
+	{value: 0x45f0, lo: 0xa0, hi: 0xa0},
+	{value: 0x45fe, lo: 0xa1, hi: 0xa1},
+	{value: 0x460c, lo: 0xa2, hi: 0xa2},
+	{value: 0x461a, lo: 0xa3, hi: 0xa3},
+	{value: 0x4628, lo: 0xa4, hi: 0xa4},
+	{value: 0x80d8, lo: 0xa5, hi: 0xa6},
+	{value: 0x8001, lo: 0xa7, hi: 0xa9},
+	{value: 0x80e2, lo: 0xad, hi: 0xad},
+	{value: 0x80d8, lo: 0xae, hi: 0xb2},
+	{value: 0x80dc, lo: 0xbb, hi: 0xbf},
+	// Block 0x6c, offset 0x6d
+	{value: 0x0000, lo: 0x09},
+	{value: 0x80dc, lo: 0x80, hi: 0x82},
+	{value: 0x80e6, lo: 0x85, hi: 0x89},
+	{value: 0x80dc, lo: 0x8a, hi: 0x8b},
+	{value: 0x80e6, lo: 0xaa, hi: 0xad},
+	{value: 0x45c6, lo: 0xbb, hi: 0xbb},
+	{value: 0x45d0, lo: 0xbc, hi: 0xbc},
+	{value: 0x4636, lo: 0xbd, hi: 0xbd},
+	{value: 0x4652, lo: 0xbe, hi: 0xbe},
+	{value: 0x4644, lo: 0xbf, hi: 0xbf},
+	// Block 0x6d, offset 0x6e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x4660, lo: 0x80, hi: 0x80},
+	// Block 0x6e, offset 0x6f
+	{value: 0x0000, lo: 0x01},
+	{value: 0x80e6, lo: 0x82, hi: 0x84},
+	// Block 0x6f, offset 0x70
+	{value: 0x0002, lo: 0x03},
+	{value: 0x0043, lo: 0x80, hi: 0x99},
+	{value: 0x0083, lo: 0x9a, hi: 0xb3},
+	{value: 0x0043, lo: 0xb4, hi: 0xbf},
+	// Block 0x70, offset 0x71
+	{value: 0x0002, lo: 0x04},
+	{value: 0x005b, lo: 0x80, hi: 0x8d},
+	{value: 0x0083, lo: 0x8e, hi: 0x94},
+	{value: 0x0093, lo: 0x96, hi: 0xa7},
+	{value: 0x0043, lo: 0xa8, hi: 0xbf},
+	// Block 0x71, offset 0x72
+	{value: 0x0002, lo: 0x0b},
+	{value: 0x0073, lo: 0x80, hi: 0x81},
+	{value: 0x0083, lo: 0x82, hi: 0x9b},
+	{value: 0x0043, lo: 0x9c, hi: 0x9c},
+	{value: 0x0047, lo: 0x9e, hi: 0x9f},
+	{value: 0x004f, lo: 0xa2, hi: 0xa2},
+	{value: 0x0055, lo: 0xa5, hi: 0xa6},
+	{value: 0x005d, lo: 0xa9, hi: 0xac},
+	{value: 0x0067, lo: 0xae, hi: 0xb5},
+	{value: 0x0083, lo: 0xb6, hi: 0xb9},
+	{value: 0x008d, lo: 0xbb, hi: 0xbb},
+	{value: 0x0091, lo: 0xbd, hi: 0xbf},
+	// Block 0x72, offset 0x73
+	{value: 0x0002, lo: 0x04},
+	{value: 0x0097, lo: 0x80, hi: 0x83},
+	{value: 0x00a1, lo: 0x85, hi: 0x8f},
+	{value: 0x0043, lo: 0x90, hi: 0xa9},
+	{value: 0x0083, lo: 0xaa, hi: 0xbf},
+	// Block 0x73, offset 0x74
+	{value: 0x0002, lo: 0x08},
+	{value: 0x00af, lo: 0x80, hi: 0x83},
+	{value: 0x0043, lo: 0x84, hi: 0x85},
+	{value: 0x0049, lo: 0x87, hi: 0x8a},
+	{value: 0x0055, lo: 0x8d, hi: 0x94},
+	{value: 0x0067, lo: 0x96, hi: 0x9c},
+	{value: 0x0083, lo: 0x9e, hi: 0xb7},
+	{value: 0x0043, lo: 0xb8, hi: 0xb9},
+	{value: 0x0049, lo: 0xbb, hi: 0xbe},
+	// Block 0x74, offset 0x75
+	{value: 0x0002, lo: 0x05},
+	{value: 0x0053, lo: 0x80, hi: 0x84},
+	{value: 0x005f, lo: 0x86, hi: 0x86},
+	{value: 0x0067, lo: 0x8a, hi: 0x90},
+	{value: 0x0083, lo: 0x92, hi: 0xab},
+	{value: 0x0043, lo: 0xac, hi: 0xbf},
+	// Block 0x75, offset 0x76
+	{value: 0x0002, lo: 0x04},
+	{value: 0x006b, lo: 0x80, hi: 0x85},
+	{value: 0x0083, lo: 0x86, hi: 0x9f},
+	{value: 0x0043, lo: 0xa0, hi: 0xb9},
+	{value: 0x0083, lo: 0xba, hi: 0xbf},
+	// Block 0x76, offset 0x77
+	{value: 0x0002, lo: 0x03},
+	{value: 0x008f, lo: 0x80, hi: 0x93},
+	{value: 0x0043, lo: 0x94, hi: 0xad},
+	{value: 0x0083, lo: 0xae, hi: 0xbf},
+	// Block 0x77, offset 0x78
+	{value: 0x0002, lo: 0x04},
+	{value: 0x00a7, lo: 0x80, hi: 0x87},
+	{value: 0x0043, lo: 0x88, hi: 0xa1},
+	{value: 0x0083, lo: 0xa2, hi: 0xbb},
+	{value: 0x0043, lo: 0xbc, hi: 0xbf},
+	// Block 0x78, offset 0x79
+	{value: 0x0002, lo: 0x03},
+	{value: 0x004b, lo: 0x80, hi: 0x95},
+	{value: 0x0083, lo: 0x96, hi: 0xaf},
+	{value: 0x0043, lo: 0xb0, hi: 0xbf},
+	// Block 0x79, offset 0x7a
+	{value: 0x0003, lo: 0x0f},
+	{value: 0x01b8, lo: 0x80, hi: 0x80},
+	{value: 0x04d1, lo: 0x81, hi: 0x81},
+	{value: 0x01bb, lo: 0x82, hi: 0x9a},
+	{value: 0x04cd, lo: 0x9b, hi: 0x9b},
+	{value: 0x01c7, lo: 0x9c, hi: 0x9c},
+	{value: 0x01d0, lo: 0x9d, hi: 0x9d},
+	{value: 0x01d6, lo: 0x9e, hi: 0x9e},
+	{value: 0x01fa, lo: 0x9f, hi: 0x9f},
+	{value: 0x01eb, lo: 0xa0, hi: 0xa0},
+	{value: 0x01e8, lo: 0xa1, hi: 0xa1},
+	{value: 0x0173, lo: 0xa2, hi: 0xb2},
+	{value: 0x0188, lo: 0xb3, hi: 0xb3},
+	{value: 0x01a6, lo: 0xb4, hi: 0xba},
+	{value: 0x04d1, lo: 0xbb, hi: 0xbb},
+	{value: 0x01bb, lo: 0xbc, hi: 0xbf},
+	// Block 0x7a, offset 0x7b
+	{value: 0x0003, lo: 0x0d},
+	{value: 0x01c7, lo: 0x80, hi: 0x94},
+	{value: 0x04cd, lo: 0x95, hi: 0x95},
+	{value: 0x01c7, lo: 0x96, hi: 0x96},
+	{value: 0x01d0, lo: 0x97, hi: 0x97},
+	{value: 0x01d6, lo: 0x98, hi: 0x98},
+	{value: 0x01fa, lo: 0x99, hi: 0x99},
+	{value: 0x01eb, lo: 0x9a, hi: 0x9a},
+	{value: 0x01e8, lo: 0x9b, hi: 0x9b},
+	{value: 0x0173, lo: 0x9c, hi: 0xac},
+	{value: 0x0188, lo: 0xad, hi: 0xad},
+	{value: 0x01a6, lo: 0xae, hi: 0xb4},
+	{value: 0x04d1, lo: 0xb5, hi: 0xb5},
+	{value: 0x01bb, lo: 0xb6, hi: 0xbf},
+	// Block 0x7b, offset 0x7c
+	{value: 0x0003, lo: 0x0d},
+	{value: 0x01d9, lo: 0x80, hi: 0x8e},
+	{value: 0x04cd, lo: 0x8f, hi: 0x8f},
+	{value: 0x01c7, lo: 0x90, hi: 0x90},
+	{value: 0x01d0, lo: 0x91, hi: 0x91},
+	{value: 0x01d6, lo: 0x92, hi: 0x92},
+	{value: 0x01fa, lo: 0x93, hi: 0x93},
+	{value: 0x01eb, lo: 0x94, hi: 0x94},
+	{value: 0x01e8, lo: 0x95, hi: 0x95},
+	{value: 0x0173, lo: 0x96, hi: 0xa6},
+	{value: 0x0188, lo: 0xa7, hi: 0xa7},
+	{value: 0x01a6, lo: 0xa8, hi: 0xae},
+	{value: 0x04d1, lo: 0xaf, hi: 0xaf},
+	{value: 0x01bb, lo: 0xb0, hi: 0xbf},
+	// Block 0x7c, offset 0x7d
+	{value: 0x0003, lo: 0x0d},
+	{value: 0x01eb, lo: 0x80, hi: 0x88},
+	{value: 0x04cd, lo: 0x89, hi: 0x89},
+	{value: 0x01c7, lo: 0x8a, hi: 0x8a},
+	{value: 0x01d0, lo: 0x8b, hi: 0x8b},
+	{value: 0x01d6, lo: 0x8c, hi: 0x8c},
+	{value: 0x01fa, lo: 0x8d, hi: 0x8d},
+	{value: 0x01eb, lo: 0x8e, hi: 0x8e},
+	{value: 0x01e8, lo: 0x8f, hi: 0x8f},
+	{value: 0x0173, lo: 0x90, hi: 0xa0},
+	{value: 0x0188, lo: 0xa1, hi: 0xa1},
+	{value: 0x01a6, lo: 0xa2, hi: 0xa8},
+	{value: 0x04d1, lo: 0xa9, hi: 0xa9},
+	{value: 0x01bb, lo: 0xaa, hi: 0xbf},
+	// Block 0x7d, offset 0x7e
+	{value: 0x0002, lo: 0x09},
+	{value: 0x0063, lo: 0x80, hi: 0x89},
+	{value: 0x1a93, lo: 0x8a, hi: 0x8a},
+	{value: 0x1ac3, lo: 0x8b, hi: 0x8b},
+	{value: 0x1ade, lo: 0x8c, hi: 0x8c},
+	{value: 0x1ae4, lo: 0x8d, hi: 0x8d},
+	{value: 0x1d02, lo: 0x8e, hi: 0x8e},
+	{value: 0x1af0, lo: 0x8f, hi: 0x8f},
+	{value: 0x1abd, lo: 0xaa, hi: 0xaa},
+	{value: 0x1ac0, lo: 0xab, hi: 0xab},
+	// Block 0x7e, offset 0x7f
+	{value: 0x0000, lo: 0x01},
+	{value: 0x1a81, lo: 0x90, hi: 0x90},
+	// Block 0x7f, offset 0x80
+	{value: 0x0028, lo: 0x09},
+	{value: 0x2a0d, lo: 0x80, hi: 0x80},
+	{value: 0x29d1, lo: 0x81, hi: 0x81},
+	{value: 0x29db, lo: 0x82, hi: 0x82},
+	{value: 0x29ef, lo: 0x83, hi: 0x84},
+	{value: 0x29f9, lo: 0x85, hi: 0x86},
+	{value: 0x29e5, lo: 0x87, hi: 0x87},
+	{value: 0x2a03, lo: 0x88, hi: 0x88},
+	{value: 0x0be1, lo: 0x90, hi: 0x90},
+	{value: 0x0959, lo: 0x91, hi: 0x91},
+}
+
+// nfkcLookup: 1216 bytes
+// Block 0 is the null block.
+var nfkcLookup = [1216]uint8{
+	// Block 0x0, offset 0x0
+	// Block 0x1, offset 0x40
+	// Block 0x2, offset 0x80
+	// Block 0x3, offset 0xc0
+	0x0c2: 0x58, 0x0c3: 0x01, 0x0c4: 0x02, 0x0c5: 0x03, 0x0c6: 0x59, 0x0c7: 0x04,
+	0x0c8: 0x05, 0x0ca: 0x5a, 0x0cb: 0x5b, 0x0cc: 0x06, 0x0cd: 0x07, 0x0ce: 0x08, 0x0cf: 0x09,
+	0x0d0: 0x0a, 0x0d1: 0x5c, 0x0d2: 0x5d, 0x0d3: 0x0b, 0x0d6: 0x0c, 0x0d7: 0x5e,
+	0x0d8: 0x5f, 0x0d9: 0x0d, 0x0db: 0x60, 0x0dc: 0x61, 0x0dd: 0x62, 0x0df: 0x63,
+	0x0e0: 0x02, 0x0e1: 0x03, 0x0e2: 0x04, 0x0e3: 0x05,
+	0x0ea: 0x06, 0x0eb: 0x07, 0x0ec: 0x07, 0x0ed: 0x08, 0x0ef: 0x09,
+	0x0f0: 0x10,
+	// Block 0x4, offset 0x100
+	0x120: 0x64, 0x121: 0x65, 0x123: 0x66, 0x124: 0x67, 0x125: 0x68, 0x126: 0x69, 0x127: 0x6a,
+	0x128: 0x6b, 0x129: 0x6c, 0x12a: 0x6d, 0x12b: 0x6e, 0x12c: 0x69, 0x12d: 0x6f, 0x12e: 0x70, 0x12f: 0x71,
+	0x131: 0x72, 0x132: 0x73, 0x133: 0x74, 0x134: 0x75, 0x135: 0x76, 0x137: 0x77,
+	0x138: 0x78, 0x139: 0x79, 0x13a: 0x7a, 0x13b: 0x7b, 0x13c: 0x7c, 0x13d: 0x7d, 0x13e: 0x7e, 0x13f: 0x7f,
+	// Block 0x5, offset 0x140
+	0x140: 0x80, 0x142: 0x81, 0x143: 0x82, 0x144: 0x83, 0x145: 0x84, 0x146: 0x85, 0x147: 0x86,
+	0x14d: 0x87,
+	0x15c: 0x88, 0x15f: 0x89,
+	0x162: 0x8a, 0x164: 0x8b,
+	0x168: 0x8c, 0x169: 0x8d, 0x16c: 0x0e, 0x16d: 0x8e, 0x16e: 0x8f, 0x16f: 0x90,
+	0x170: 0x91, 0x173: 0x92, 0x174: 0x93, 0x175: 0x0f, 0x176: 0x10, 0x177: 0x94,
+	0x178: 0x11, 0x179: 0x12, 0x17a: 0x13, 0x17b: 0x14, 0x17c: 0x15, 0x17d: 0x16, 0x17e: 0x17, 0x17f: 0x18,
+	// Block 0x6, offset 0x180
+	0x180: 0x95, 0x181: 0x96, 0x182: 0x97, 0x183: 0x98, 0x184: 0x19, 0x185: 0x1a, 0x186: 0x99, 0x187: 0x9a,
+	0x188: 0x9b, 0x189: 0x1b, 0x18a: 0x1c, 0x18b: 0x9c, 0x18c: 0x9d,
+	0x191: 0x1d, 0x192: 0x1e, 0x193: 0x9e,
+	0x1a8: 0x9f, 0x1a9: 0xa0, 0x1ab: 0xa1,
+	0x1b1: 0xa2, 0x1b3: 0xa3, 0x1b5: 0xa4, 0x1b7: 0xa5,
+	0x1ba: 0xa6, 0x1bb: 0xa7, 0x1bc: 0x1f, 0x1bd: 0x20, 0x1be: 0x21, 0x1bf: 0xa8,
+	// Block 0x7, offset 0x1c0
+	0x1c0: 0xa9, 0x1c1: 0x22, 0x1c2: 0x23, 0x1c3: 0x24, 0x1c4: 0xaa, 0x1c5: 0xab, 0x1c6: 0x25,
+	0x1c8: 0x26, 0x1c9: 0x27, 0x1ca: 0x28, 0x1cb: 0x29, 0x1cc: 0x2a, 0x1cd: 0x2b, 0x1ce: 0x2c, 0x1cf: 0x2d,
+	// Block 0x8, offset 0x200
+	0x219: 0xac, 0x21a: 0xad, 0x21b: 0xae, 0x21d: 0xaf, 0x21f: 0xb0,
+	0x220: 0xb1, 0x223: 0xb2, 0x224: 0xb3, 0x225: 0xb4, 0x226: 0xb5, 0x227: 0xb6,
+	0x22a: 0xb7, 0x22b: 0xb8, 0x22f: 0xb9,
+	0x230: 0xba, 0x231: 0xba, 0x232: 0xba, 0x233: 0xba, 0x234: 0xba, 0x235: 0xba, 0x236: 0xba, 0x237: 0xba,
+	0x238: 0xba, 0x239: 0xba, 0x23a: 0xba, 0x23b: 0xba, 0x23c: 0xba, 0x23d: 0xba, 0x23e: 0xba, 0x23f: 0xba,
+	// Block 0x9, offset 0x240
+	0x240: 0xba, 0x241: 0xba, 0x242: 0xba, 0x243: 0xba, 0x244: 0xba, 0x245: 0xba, 0x246: 0xba, 0x247: 0xba,
+	0x248: 0xba, 0x249: 0xba, 0x24a: 0xba, 0x24b: 0xba, 0x24c: 0xba, 0x24d: 0xba, 0x24e: 0xba, 0x24f: 0xba,
+	0x250: 0xba, 0x251: 0xba, 0x252: 0xba, 0x253: 0xba, 0x254: 0xba, 0x255: 0xba, 0x256: 0xba, 0x257: 0xba,
+	0x258: 0xba, 0x259: 0xba, 0x25a: 0xba, 0x25b: 0xba, 0x25c: 0xba, 0x25d: 0xba, 0x25e: 0xba, 0x25f: 0xba,
+	0x260: 0xba, 0x261: 0xba, 0x262: 0xba, 0x263: 0xba, 0x264: 0xba, 0x265: 0xba, 0x266: 0xba, 0x267: 0xba,
+	0x268: 0xba, 0x269: 0xba, 0x26a: 0xba, 0x26b: 0xba, 0x26c: 0xba, 0x26d: 0xba, 0x26e: 0xba, 0x26f: 0xba,
+	0x270: 0xba, 0x271: 0xba, 0x272: 0xba, 0x273: 0xba, 0x274: 0xba, 0x275: 0xba, 0x276: 0xba, 0x277: 0xba,
+	0x278: 0xba, 0x279: 0xba, 0x27a: 0xba, 0x27b: 0xba, 0x27c: 0xba, 0x27d: 0xba, 0x27e: 0xba, 0x27f: 0xba,
+	// Block 0xa, offset 0x280
+	0x280: 0xba, 0x281: 0xba, 0x282: 0xba, 0x283: 0xba, 0x284: 0xba, 0x285: 0xba, 0x286: 0xba, 0x287: 0xba,
+	0x288: 0xba, 0x289: 0xba, 0x28a: 0xba, 0x28b: 0xba, 0x28c: 0xba, 0x28d: 0xba, 0x28e: 0xba, 0x28f: 0xba,
+	0x290: 0xba, 0x291: 0xba, 0x292: 0xba, 0x293: 0xba, 0x294: 0xba, 0x295: 0xba, 0x296: 0xba, 0x297: 0xba,
+	0x298: 0xba, 0x299: 0xba, 0x29a: 0xba, 0x29b: 0xba, 0x29c: 0xba, 0x29d: 0xba, 0x29e: 0xbb,
+	// Block 0xb, offset 0x2c0
+	0x2e4: 0x2e, 0x2e5: 0x2f, 0x2e6: 0x30, 0x2e7: 0x31,
+	0x2e8: 0x32, 0x2e9: 0x33, 0x2ea: 0x34, 0x2eb: 0x35, 0x2ec: 0x36, 0x2ed: 0x37, 0x2ee: 0x38, 0x2ef: 0x39,
+	0x2f0: 0x3a, 0x2f1: 0x3b, 0x2f2: 0x3c, 0x2f3: 0x3d, 0x2f4: 0x3e, 0x2f5: 0x3f, 0x2f6: 0x40, 0x2f7: 0x41,
+	0x2f8: 0x42, 0x2f9: 0x43, 0x2fa: 0x44, 0x2fb: 0x45, 0x2fc: 0xbc, 0x2fd: 0x46, 0x2fe: 0x47, 0x2ff: 0xbd,
+	// Block 0xc, offset 0x300
+	0x307: 0xbe,
+	0x328: 0xbf,
+	// Block 0xd, offset 0x340
+	0x341: 0xb1, 0x342: 0xc0, 0x344: 0xc1, 0x347: 0xb6,
+	0x35a: 0xc2,
+	// Block 0xe, offset 0x380
+	0x385: 0xc3, 0x386: 0xc4, 0x387: 0xc5,
+	0x389: 0xc6,
+	0x390: 0xc7, 0x391: 0xc8, 0x392: 0xc9, 0x393: 0xca, 0x394: 0xcb, 0x395: 0xcc, 0x396: 0xcd, 0x397: 0xce,
+	0x398: 0xcf, 0x399: 0xd0, 0x39a: 0x48, 0x39b: 0xd1, 0x39c: 0xd2, 0x39d: 0xd3, 0x39e: 0xd4, 0x39f: 0x49,
+	// Block 0xf, offset 0x3c0
+	0x3f8: 0x4a, 0x3f9: 0x4b, 0x3fa: 0x4c,
+	// Block 0x10, offset 0x400
+	0x404: 0x4d, 0x405: 0xd5, 0x406: 0xd6,
+	0x408: 0x4e, 0x409: 0xd7,
+	// Block 0x11, offset 0x440
+	0x460: 0x4f, 0x461: 0x50, 0x462: 0x51, 0x463: 0x52, 0x464: 0x53, 0x465: 0x54, 0x466: 0x55, 0x467: 0x56,
+	0x468: 0x57,
+	// Block 0x12, offset 0x480
+	0x490: 0x0a, 0x491: 0x0b,
+	0x49d: 0x0c, 0x49e: 0x0d, 0x49f: 0x0e,
+	0x4af: 0x0f,
+}
+
+var nfkcTrie = trie{nfkcLookup[:], nfkcValues[:], nfkcSparseValues[:], nfkcSparseOffset[:], 88}
+
+// recompMap: 7464 bytes (entries only)
+var recompMap = map[uint32]rune{
+	0x00410300: 0x00C0,
+	0x00410301: 0x00C1,
+	0x00410302: 0x00C2,
+	0x00410303: 0x00C3,
+	0x00410308: 0x00C4,
+	0x0041030A: 0x00C5,
+	0x00430327: 0x00C7,
+	0x00450300: 0x00C8,
+	0x00450301: 0x00C9,
+	0x00450302: 0x00CA,
+	0x00450308: 0x00CB,
+	0x00490300: 0x00CC,
+	0x00490301: 0x00CD,
+	0x00490302: 0x00CE,
+	0x00490308: 0x00CF,
+	0x004E0303: 0x00D1,
+	0x004F0300: 0x00D2,
+	0x004F0301: 0x00D3,
+	0x004F0302: 0x00D4,
+	0x004F0303: 0x00D5,
+	0x004F0308: 0x00D6,
+	0x00550300: 0x00D9,
+	0x00550301: 0x00DA,
+	0x00550302: 0x00DB,
+	0x00550308: 0x00DC,
+	0x00590301: 0x00DD,
+	0x00610300: 0x00E0,
+	0x00610301: 0x00E1,
+	0x00610302: 0x00E2,
+	0x00610303: 0x00E3,
+	0x00610308: 0x00E4,
+	0x0061030A: 0x00E5,
+	0x00630327: 0x00E7,
+	0x00650300: 0x00E8,
+	0x00650301: 0x00E9,
+	0x00650302: 0x00EA,
+	0x00650308: 0x00EB,
+	0x00690300: 0x00EC,
+	0x00690301: 0x00ED,
+	0x00690302: 0x00EE,
+	0x00690308: 0x00EF,
+	0x006E0303: 0x00F1,
+	0x006F0300: 0x00F2,
+	0x006F0301: 0x00F3,
+	0x006F0302: 0x00F4,
+	0x006F0303: 0x00F5,
+	0x006F0308: 0x00F6,
+	0x00750300: 0x00F9,
+	0x00750301: 0x00FA,
+	0x00750302: 0x00FB,
+	0x00750308: 0x00FC,
+	0x00790301: 0x00FD,
+	0x00790308: 0x00FF,
+	0x00410304: 0x0100,
+	0x00610304: 0x0101,
+	0x00410306: 0x0102,
+	0x00610306: 0x0103,
+	0x00410328: 0x0104,
+	0x00610328: 0x0105,
+	0x00430301: 0x0106,
+	0x00630301: 0x0107,
+	0x00430302: 0x0108,
+	0x00630302: 0x0109,
+	0x00430307: 0x010A,
+	0x00630307: 0x010B,
+	0x0043030C: 0x010C,
+	0x0063030C: 0x010D,
+	0x0044030C: 0x010E,
+	0x0064030C: 0x010F,
+	0x00450304: 0x0112,
+	0x00650304: 0x0113,
+	0x00450306: 0x0114,
+	0x00650306: 0x0115,
+	0x00450307: 0x0116,
+	0x00650307: 0x0117,
+	0x00450328: 0x0118,
+	0x00650328: 0x0119,
+	0x0045030C: 0x011A,
+	0x0065030C: 0x011B,
+	0x00470302: 0x011C,
+	0x00670302: 0x011D,
+	0x00470306: 0x011E,
+	0x00670306: 0x011F,
+	0x00470307: 0x0120,
+	0x00670307: 0x0121,
+	0x00470327: 0x0122,
+	0x00670327: 0x0123,
+	0x00480302: 0x0124,
+	0x00680302: 0x0125,
+	0x00490303: 0x0128,
+	0x00690303: 0x0129,
+	0x00490304: 0x012A,
+	0x00690304: 0x012B,
+	0x00490306: 0x012C,
+	0x00690306: 0x012D,
+	0x00490328: 0x012E,
+	0x00690328: 0x012F,
+	0x00490307: 0x0130,
+	0x004A0302: 0x0134,
+	0x006A0302: 0x0135,
+	0x004B0327: 0x0136,
+	0x006B0327: 0x0137,
+	0x004C0301: 0x0139,
+	0x006C0301: 0x013A,
+	0x004C0327: 0x013B,
+	0x006C0327: 0x013C,
+	0x004C030C: 0x013D,
+	0x006C030C: 0x013E,
+	0x004E0301: 0x0143,
+	0x006E0301: 0x0144,
+	0x004E0327: 0x0145,
+	0x006E0327: 0x0146,
+	0x004E030C: 0x0147,
+	0x006E030C: 0x0148,
+	0x004F0304: 0x014C,
+	0x006F0304: 0x014D,
+	0x004F0306: 0x014E,
+	0x006F0306: 0x014F,
+	0x004F030B: 0x0150,
+	0x006F030B: 0x0151,
+	0x00520301: 0x0154,
+	0x00720301: 0x0155,
+	0x00520327: 0x0156,
+	0x00720327: 0x0157,
+	0x0052030C: 0x0158,
+	0x0072030C: 0x0159,
+	0x00530301: 0x015A,
+	0x00730301: 0x015B,
+	0x00530302: 0x015C,
+	0x00730302: 0x015D,
+	0x00530327: 0x015E,
+	0x00730327: 0x015F,
+	0x0053030C: 0x0160,
+	0x0073030C: 0x0161,
+	0x00540327: 0x0162,
+	0x00740327: 0x0163,
+	0x0054030C: 0x0164,
+	0x0074030C: 0x0165,
+	0x00550303: 0x0168,
+	0x00750303: 0x0169,
+	0x00550304: 0x016A,
+	0x00750304: 0x016B,
+	0x00550306: 0x016C,
+	0x00750306: 0x016D,
+	0x0055030A: 0x016E,
+	0x0075030A: 0x016F,
+	0x0055030B: 0x0170,
+	0x0075030B: 0x0171,
+	0x00550328: 0x0172,
+	0x00750328: 0x0173,
+	0x00570302: 0x0174,
+	0x00770302: 0x0175,
+	0x00590302: 0x0176,
+	0x00790302: 0x0177,
+	0x00590308: 0x0178,
+	0x005A0301: 0x0179,
+	0x007A0301: 0x017A,
+	0x005A0307: 0x017B,
+	0x007A0307: 0x017C,
+	0x005A030C: 0x017D,
+	0x007A030C: 0x017E,
+	0x004F031B: 0x01A0,
+	0x006F031B: 0x01A1,
+	0x0055031B: 0x01AF,
+	0x0075031B: 0x01B0,
+	0x0041030C: 0x01CD,
+	0x0061030C: 0x01CE,
+	0x0049030C: 0x01CF,
+	0x0069030C: 0x01D0,
+	0x004F030C: 0x01D1,
+	0x006F030C: 0x01D2,
+	0x0055030C: 0x01D3,
+	0x0075030C: 0x01D4,
+	0x00DC0304: 0x01D5,
+	0x00FC0304: 0x01D6,
+	0x00DC0301: 0x01D7,
+	0x00FC0301: 0x01D8,
+	0x00DC030C: 0x01D9,
+	0x00FC030C: 0x01DA,
+	0x00DC0300: 0x01DB,
+	0x00FC0300: 0x01DC,
+	0x00C40304: 0x01DE,
+	0x00E40304: 0x01DF,
+	0x02260304: 0x01E0,
+	0x02270304: 0x01E1,
+	0x00C60304: 0x01E2,
+	0x00E60304: 0x01E3,
+	0x0047030C: 0x01E6,
+	0x0067030C: 0x01E7,
+	0x004B030C: 0x01E8,
+	0x006B030C: 0x01E9,
+	0x004F0328: 0x01EA,
+	0x006F0328: 0x01EB,
+	0x01EA0304: 0x01EC,
+	0x01EB0304: 0x01ED,
+	0x01B7030C: 0x01EE,
+	0x0292030C: 0x01EF,
+	0x006A030C: 0x01F0,
+	0x00470301: 0x01F4,
+	0x00670301: 0x01F5,
+	0x004E0300: 0x01F8,
+	0x006E0300: 0x01F9,
+	0x00C50301: 0x01FA,
+	0x00E50301: 0x01FB,
+	0x00C60301: 0x01FC,
+	0x00E60301: 0x01FD,
+	0x00D80301: 0x01FE,
+	0x00F80301: 0x01FF,
+	0x0041030F: 0x0200,
+	0x0061030F: 0x0201,
+	0x00410311: 0x0202,
+	0x00610311: 0x0203,
+	0x0045030F: 0x0204,
+	0x0065030F: 0x0205,
+	0x00450311: 0x0206,
+	0x00650311: 0x0207,
+	0x0049030F: 0x0208,
+	0x0069030F: 0x0209,
+	0x00490311: 0x020A,
+	0x00690311: 0x020B,
+	0x004F030F: 0x020C,
+	0x006F030F: 0x020D,
+	0x004F0311: 0x020E,
+	0x006F0311: 0x020F,
+	0x0052030F: 0x0210,
+	0x0072030F: 0x0211,
+	0x00520311: 0x0212,
+	0x00720311: 0x0213,
+	0x0055030F: 0x0214,
+	0x0075030F: 0x0215,
+	0x00550311: 0x0216,
+	0x00750311: 0x0217,
+	0x00530326: 0x0218,
+	0x00730326: 0x0219,
+	0x00540326: 0x021A,
+	0x00740326: 0x021B,
+	0x0048030C: 0x021E,
+	0x0068030C: 0x021F,
+	0x00410307: 0x0226,
+	0x00610307: 0x0227,
+	0x00450327: 0x0228,
+	0x00650327: 0x0229,
+	0x00D60304: 0x022A,
+	0x00F60304: 0x022B,
+	0x00D50304: 0x022C,
+	0x00F50304: 0x022D,
+	0x004F0307: 0x022E,
+	0x006F0307: 0x022F,
+	0x022E0304: 0x0230,
+	0x022F0304: 0x0231,
+	0x00590304: 0x0232,
+	0x00790304: 0x0233,
+	0x00A80301: 0x0385,
+	0x03910301: 0x0386,
+	0x03950301: 0x0388,
+	0x03970301: 0x0389,
+	0x03990301: 0x038A,
+	0x039F0301: 0x038C,
+	0x03A50301: 0x038E,
+	0x03A90301: 0x038F,
+	0x03CA0301: 0x0390,
+	0x03990308: 0x03AA,
+	0x03A50308: 0x03AB,
+	0x03B10301: 0x03AC,
+	0x03B50301: 0x03AD,
+	0x03B70301: 0x03AE,
+	0x03B90301: 0x03AF,
+	0x03CB0301: 0x03B0,
+	0x03B90308: 0x03CA,
+	0x03C50308: 0x03CB,
+	0x03BF0301: 0x03CC,
+	0x03C50301: 0x03CD,
+	0x03C90301: 0x03CE,
+	0x03D20301: 0x03D3,
+	0x03D20308: 0x03D4,
+	0x04150300: 0x0400,
+	0x04150308: 0x0401,
+	0x04130301: 0x0403,
+	0x04060308: 0x0407,
+	0x041A0301: 0x040C,
+	0x04180300: 0x040D,
+	0x04230306: 0x040E,
+	0x04180306: 0x0419,
+	0x04380306: 0x0439,
+	0x04350300: 0x0450,
+	0x04350308: 0x0451,
+	0x04330301: 0x0453,
+	0x04560308: 0x0457,
+	0x043A0301: 0x045C,
+	0x04380300: 0x045D,
+	0x04430306: 0x045E,
+	0x0474030F: 0x0476,
+	0x0475030F: 0x0477,
+	0x04160306: 0x04C1,
+	0x04360306: 0x04C2,
+	0x04100306: 0x04D0,
+	0x04300306: 0x04D1,
+	0x04100308: 0x04D2,
+	0x04300308: 0x04D3,
+	0x04150306: 0x04D6,
+	0x04350306: 0x04D7,
+	0x04D80308: 0x04DA,
+	0x04D90308: 0x04DB,
+	0x04160308: 0x04DC,
+	0x04360308: 0x04DD,
+	0x04170308: 0x04DE,
+	0x04370308: 0x04DF,
+	0x04180304: 0x04E2,
+	0x04380304: 0x04E3,
+	0x04180308: 0x04E4,
+	0x04380308: 0x04E5,
+	0x041E0308: 0x04E6,
+	0x043E0308: 0x04E7,
+	0x04E80308: 0x04EA,
+	0x04E90308: 0x04EB,
+	0x042D0308: 0x04EC,
+	0x044D0308: 0x04ED,
+	0x04230304: 0x04EE,
+	0x04430304: 0x04EF,
+	0x04230308: 0x04F0,
+	0x04430308: 0x04F1,
+	0x0423030B: 0x04F2,
+	0x0443030B: 0x04F3,
+	0x04270308: 0x04F4,
+	0x04470308: 0x04F5,
+	0x042B0308: 0x04F8,
+	0x044B0308: 0x04F9,
+	0x06270653: 0x0622,
+	0x06270654: 0x0623,
+	0x06480654: 0x0624,
+	0x06270655: 0x0625,
+	0x064A0654: 0x0626,
+	0x06D50654: 0x06C0,
+	0x06C10654: 0x06C2,
+	0x06D20654: 0x06D3,
+	0x0928093C: 0x0929,
+	0x0930093C: 0x0931,
+	0x0933093C: 0x0934,
+	0x09C709BE: 0x09CB,
+	0x09C709D7: 0x09CC,
+	0x0B470B56: 0x0B48,
+	0x0B470B3E: 0x0B4B,
+	0x0B470B57: 0x0B4C,
+	0x0B920BD7: 0x0B94,
+	0x0BC60BBE: 0x0BCA,
+	0x0BC70BBE: 0x0BCB,
+	0x0BC60BD7: 0x0BCC,
+	0x0C460C56: 0x0C48,
+	0x0CBF0CD5: 0x0CC0,
+	0x0CC60CD5: 0x0CC7,
+	0x0CC60CD6: 0x0CC8,
+	0x0CC60CC2: 0x0CCA,
+	0x0CCA0CD5: 0x0CCB,
+	0x0D460D3E: 0x0D4A,
+	0x0D470D3E: 0x0D4B,
+	0x0D460D57: 0x0D4C,
+	0x0DD90DCA: 0x0DDA,
+	0x0DD90DCF: 0x0DDC,
+	0x0DDC0DCA: 0x0DDD,
+	0x0DD90DDF: 0x0DDE,
+	0x1025102E: 0x1026,
+	0x1B051B35: 0x1B06,
+	0x1B071B35: 0x1B08,
+	0x1B091B35: 0x1B0A,
+	0x1B0B1B35: 0x1B0C,
+	0x1B0D1B35: 0x1B0E,
+	0x1B111B35: 0x1B12,
+	0x1B3A1B35: 0x1B3B,
+	0x1B3C1B35: 0x1B3D,
+	0x1B3E1B35: 0x1B40,
+	0x1B3F1B35: 0x1B41,
+	0x1B421B35: 0x1B43,
+	0x00410325: 0x1E00,
+	0x00610325: 0x1E01,
+	0x00420307: 0x1E02,
+	0x00620307: 0x1E03,
+	0x00420323: 0x1E04,
+	0x00620323: 0x1E05,
+	0x00420331: 0x1E06,
+	0x00620331: 0x1E07,
+	0x00C70301: 0x1E08,
+	0x00E70301: 0x1E09,
+	0x00440307: 0x1E0A,
+	0x00640307: 0x1E0B,
+	0x00440323: 0x1E0C,
+	0x00640323: 0x1E0D,
+	0x00440331: 0x1E0E,
+	0x00640331: 0x1E0F,
+	0x00440327: 0x1E10,
+	0x00640327: 0x1E11,
+	0x0044032D: 0x1E12,
+	0x0064032D: 0x1E13,
+	0x01120300: 0x1E14,
+	0x01130300: 0x1E15,
+	0x01120301: 0x1E16,
+	0x01130301: 0x1E17,
+	0x0045032D: 0x1E18,
+	0x0065032D: 0x1E19,
+	0x00450330: 0x1E1A,
+	0x00650330: 0x1E1B,
+	0x02280306: 0x1E1C,
+	0x02290306: 0x1E1D,
+	0x00460307: 0x1E1E,
+	0x00660307: 0x1E1F,
+	0x00470304: 0x1E20,
+	0x00670304: 0x1E21,
+	0x00480307: 0x1E22,
+	0x00680307: 0x1E23,
+	0x00480323: 0x1E24,
+	0x00680323: 0x1E25,
+	0x00480308: 0x1E26,
+	0x00680308: 0x1E27,
+	0x00480327: 0x1E28,
+	0x00680327: 0x1E29,
+	0x0048032E: 0x1E2A,
+	0x0068032E: 0x1E2B,
+	0x00490330: 0x1E2C,
+	0x00690330: 0x1E2D,
+	0x00CF0301: 0x1E2E,
+	0x00EF0301: 0x1E2F,
+	0x004B0301: 0x1E30,
+	0x006B0301: 0x1E31,
+	0x004B0323: 0x1E32,
+	0x006B0323: 0x1E33,
+	0x004B0331: 0x1E34,
+	0x006B0331: 0x1E35,
+	0x004C0323: 0x1E36,
+	0x006C0323: 0x1E37,
+	0x1E360304: 0x1E38,
+	0x1E370304: 0x1E39,
+	0x004C0331: 0x1E3A,
+	0x006C0331: 0x1E3B,
+	0x004C032D: 0x1E3C,
+	0x006C032D: 0x1E3D,
+	0x004D0301: 0x1E3E,
+	0x006D0301: 0x1E3F,
+	0x004D0307: 0x1E40,
+	0x006D0307: 0x1E41,
+	0x004D0323: 0x1E42,
+	0x006D0323: 0x1E43,
+	0x004E0307: 0x1E44,
+	0x006E0307: 0x1E45,
+	0x004E0323: 0x1E46,
+	0x006E0323: 0x1E47,
+	0x004E0331: 0x1E48,
+	0x006E0331: 0x1E49,
+	0x004E032D: 0x1E4A,
+	0x006E032D: 0x1E4B,
+	0x00D50301: 0x1E4C,
+	0x00F50301: 0x1E4D,
+	0x00D50308: 0x1E4E,
+	0x00F50308: 0x1E4F,
+	0x014C0300: 0x1E50,
+	0x014D0300: 0x1E51,
+	0x014C0301: 0x1E52,
+	0x014D0301: 0x1E53,
+	0x00500301: 0x1E54,
+	0x00700301: 0x1E55,
+	0x00500307: 0x1E56,
+	0x00700307: 0x1E57,
+	0x00520307: 0x1E58,
+	0x00720307: 0x1E59,
+	0x00520323: 0x1E5A,
+	0x00720323: 0x1E5B,
+	0x1E5A0304: 0x1E5C,
+	0x1E5B0304: 0x1E5D,
+	0x00520331: 0x1E5E,
+	0x00720331: 0x1E5F,
+	0x00530307: 0x1E60,
+	0x00730307: 0x1E61,
+	0x00530323: 0x1E62,
+	0x00730323: 0x1E63,
+	0x015A0307: 0x1E64,
+	0x015B0307: 0x1E65,
+	0x01600307: 0x1E66,
+	0x01610307: 0x1E67,
+	0x1E620307: 0x1E68,
+	0x1E630307: 0x1E69,
+	0x00540307: 0x1E6A,
+	0x00740307: 0x1E6B,
+	0x00540323: 0x1E6C,
+	0x00740323: 0x1E6D,
+	0x00540331: 0x1E6E,
+	0x00740331: 0x1E6F,
+	0x0054032D: 0x1E70,
+	0x0074032D: 0x1E71,
+	0x00550324: 0x1E72,
+	0x00750324: 0x1E73,
+	0x00550330: 0x1E74,
+	0x00750330: 0x1E75,
+	0x0055032D: 0x1E76,
+	0x0075032D: 0x1E77,
+	0x01680301: 0x1E78,
+	0x01690301: 0x1E79,
+	0x016A0308: 0x1E7A,
+	0x016B0308: 0x1E7B,
+	0x00560303: 0x1E7C,
+	0x00760303: 0x1E7D,
+	0x00560323: 0x1E7E,
+	0x00760323: 0x1E7F,
+	0x00570300: 0x1E80,
+	0x00770300: 0x1E81,
+	0x00570301: 0x1E82,
+	0x00770301: 0x1E83,
+	0x00570308: 0x1E84,
+	0x00770308: 0x1E85,
+	0x00570307: 0x1E86,
+	0x00770307: 0x1E87,
+	0x00570323: 0x1E88,
+	0x00770323: 0x1E89,
+	0x00580307: 0x1E8A,
+	0x00780307: 0x1E8B,
+	0x00580308: 0x1E8C,
+	0x00780308: 0x1E8D,
+	0x00590307: 0x1E8E,
+	0x00790307: 0x1E8F,
+	0x005A0302: 0x1E90,
+	0x007A0302: 0x1E91,
+	0x005A0323: 0x1E92,
+	0x007A0323: 0x1E93,
+	0x005A0331: 0x1E94,
+	0x007A0331: 0x1E95,
+	0x00680331: 0x1E96,
+	0x00740308: 0x1E97,
+	0x0077030A: 0x1E98,
+	0x0079030A: 0x1E99,
+	0x017F0307: 0x1E9B,
+	0x00410323: 0x1EA0,
+	0x00610323: 0x1EA1,
+	0x00410309: 0x1EA2,
+	0x00610309: 0x1EA3,
+	0x00C20301: 0x1EA4,
+	0x00E20301: 0x1EA5,
+	0x00C20300: 0x1EA6,
+	0x00E20300: 0x1EA7,
+	0x00C20309: 0x1EA8,
+	0x00E20309: 0x1EA9,
+	0x00C20303: 0x1EAA,
+	0x00E20303: 0x1EAB,
+	0x1EA00302: 0x1EAC,
+	0x1EA10302: 0x1EAD,
+	0x01020301: 0x1EAE,
+	0x01030301: 0x1EAF,
+	0x01020300: 0x1EB0,
+	0x01030300: 0x1EB1,
+	0x01020309: 0x1EB2,
+	0x01030309: 0x1EB3,
+	0x01020303: 0x1EB4,
+	0x01030303: 0x1EB5,
+	0x1EA00306: 0x1EB6,
+	0x1EA10306: 0x1EB7,
+	0x00450323: 0x1EB8,
+	0x00650323: 0x1EB9,
+	0x00450309: 0x1EBA,
+	0x00650309: 0x1EBB,
+	0x00450303: 0x1EBC,
+	0x00650303: 0x1EBD,
+	0x00CA0301: 0x1EBE,
+	0x00EA0301: 0x1EBF,
+	0x00CA0300: 0x1EC0,
+	0x00EA0300: 0x1EC1,
+	0x00CA0309: 0x1EC2,
+	0x00EA0309: 0x1EC3,
+	0x00CA0303: 0x1EC4,
+	0x00EA0303: 0x1EC5,
+	0x1EB80302: 0x1EC6,
+	0x1EB90302: 0x1EC7,
+	0x00490309: 0x1EC8,
+	0x00690309: 0x1EC9,
+	0x00490323: 0x1ECA,
+	0x00690323: 0x1ECB,
+	0x004F0323: 0x1ECC,
+	0x006F0323: 0x1ECD,
+	0x004F0309: 0x1ECE,
+	0x006F0309: 0x1ECF,
+	0x00D40301: 0x1ED0,
+	0x00F40301: 0x1ED1,
+	0x00D40300: 0x1ED2,
+	0x00F40300: 0x1ED3,
+	0x00D40309: 0x1ED4,
+	0x00F40309: 0x1ED5,
+	0x00D40303: 0x1ED6,
+	0x00F40303: 0x1ED7,
+	0x1ECC0302: 0x1ED8,
+	0x1ECD0302: 0x1ED9,
+	0x01A00301: 0x1EDA,
+	0x01A10301: 0x1EDB,
+	0x01A00300: 0x1EDC,
+	0x01A10300: 0x1EDD,
+	0x01A00309: 0x1EDE,
+	0x01A10309: 0x1EDF,
+	0x01A00303: 0x1EE0,
+	0x01A10303: 0x1EE1,
+	0x01A00323: 0x1EE2,
+	0x01A10323: 0x1EE3,
+	0x00550323: 0x1EE4,
+	0x00750323: 0x1EE5,
+	0x00550309: 0x1EE6,
+	0x00750309: 0x1EE7,
+	0x01AF0301: 0x1EE8,
+	0x01B00301: 0x1EE9,
+	0x01AF0300: 0x1EEA,
+	0x01B00300: 0x1EEB,
+	0x01AF0309: 0x1EEC,
+	0x01B00309: 0x1EED,
+	0x01AF0303: 0x1EEE,
+	0x01B00303: 0x1EEF,
+	0x01AF0323: 0x1EF0,
+	0x01B00323: 0x1EF1,
+	0x00590300: 0x1EF2,
+	0x00790300: 0x1EF3,
+	0x00590323: 0x1EF4,
+	0x00790323: 0x1EF5,
+	0x00590309: 0x1EF6,
+	0x00790309: 0x1EF7,
+	0x00590303: 0x1EF8,
+	0x00790303: 0x1EF9,
+	0x03B10313: 0x1F00,
+	0x03B10314: 0x1F01,
+	0x1F000300: 0x1F02,
+	0x1F010300: 0x1F03,
+	0x1F000301: 0x1F04,
+	0x1F010301: 0x1F05,
+	0x1F000342: 0x1F06,
+	0x1F010342: 0x1F07,
+	0x03910313: 0x1F08,
+	0x03910314: 0x1F09,
+	0x1F080300: 0x1F0A,
+	0x1F090300: 0x1F0B,
+	0x1F080301: 0x1F0C,
+	0x1F090301: 0x1F0D,
+	0x1F080342: 0x1F0E,
+	0x1F090342: 0x1F0F,
+	0x03B50313: 0x1F10,
+	0x03B50314: 0x1F11,
+	0x1F100300: 0x1F12,
+	0x1F110300: 0x1F13,
+	0x1F100301: 0x1F14,
+	0x1F110301: 0x1F15,
+	0x03950313: 0x1F18,
+	0x03950314: 0x1F19,
+	0x1F180300: 0x1F1A,
+	0x1F190300: 0x1F1B,
+	0x1F180301: 0x1F1C,
+	0x1F190301: 0x1F1D,
+	0x03B70313: 0x1F20,
+	0x03B70314: 0x1F21,
+	0x1F200300: 0x1F22,
+	0x1F210300: 0x1F23,
+	0x1F200301: 0x1F24,
+	0x1F210301: 0x1F25,
+	0x1F200342: 0x1F26,
+	0x1F210342: 0x1F27,
+	0x03970313: 0x1F28,
+	0x03970314: 0x1F29,
+	0x1F280300: 0x1F2A,
+	0x1F290300: 0x1F2B,
+	0x1F280301: 0x1F2C,
+	0x1F290301: 0x1F2D,
+	0x1F280342: 0x1F2E,
+	0x1F290342: 0x1F2F,
+	0x03B90313: 0x1F30,
+	0x03B90314: 0x1F31,
+	0x1F300300: 0x1F32,
+	0x1F310300: 0x1F33,
+	0x1F300301: 0x1F34,
+	0x1F310301: 0x1F35,
+	0x1F300342: 0x1F36,
+	0x1F310342: 0x1F37,
+	0x03990313: 0x1F38,
+	0x03990314: 0x1F39,
+	0x1F380300: 0x1F3A,
+	0x1F390300: 0x1F3B,
+	0x1F380301: 0x1F3C,
+	0x1F390301: 0x1F3D,
+	0x1F380342: 0x1F3E,
+	0x1F390342: 0x1F3F,
+	0x03BF0313: 0x1F40,
+	0x03BF0314: 0x1F41,
+	0x1F400300: 0x1F42,
+	0x1F410300: 0x1F43,
+	0x1F400301: 0x1F44,
+	0x1F410301: 0x1F45,
+	0x039F0313: 0x1F48,
+	0x039F0314: 0x1F49,
+	0x1F480300: 0x1F4A,
+	0x1F490300: 0x1F4B,
+	0x1F480301: 0x1F4C,
+	0x1F490301: 0x1F4D,
+	0x03C50313: 0x1F50,
+	0x03C50314: 0x1F51,
+	0x1F500300: 0x1F52,
+	0x1F510300: 0x1F53,
+	0x1F500301: 0x1F54,
+	0x1F510301: 0x1F55,
+	0x1F500342: 0x1F56,
+	0x1F510342: 0x1F57,
+	0x03A50314: 0x1F59,
+	0x1F590300: 0x1F5B,
+	0x1F590301: 0x1F5D,
+	0x1F590342: 0x1F5F,
+	0x03C90313: 0x1F60,
+	0x03C90314: 0x1F61,
+	0x1F600300: 0x1F62,
+	0x1F610300: 0x1F63,
+	0x1F600301: 0x1F64,
+	0x1F610301: 0x1F65,
+	0x1F600342: 0x1F66,
+	0x1F610342: 0x1F67,
+	0x03A90313: 0x1F68,
+	0x03A90314: 0x1F69,
+	0x1F680300: 0x1F6A,
+	0x1F690300: 0x1F6B,
+	0x1F680301: 0x1F6C,
+	0x1F690301: 0x1F6D,
+	0x1F680342: 0x1F6E,
+	0x1F690342: 0x1F6F,
+	0x03B10300: 0x1F70,
+	0x03B50300: 0x1F72,
+	0x03B70300: 0x1F74,
+	0x03B90300: 0x1F76,
+	0x03BF0300: 0x1F78,
+	0x03C50300: 0x1F7A,
+	0x03C90300: 0x1F7C,
+	0x1F000345: 0x1F80,
+	0x1F010345: 0x1F81,
+	0x1F020345: 0x1F82,
+	0x1F030345: 0x1F83,
+	0x1F040345: 0x1F84,
+	0x1F050345: 0x1F85,
+	0x1F060345: 0x1F86,
+	0x1F070345: 0x1F87,
+	0x1F080345: 0x1F88,
+	0x1F090345: 0x1F89,
+	0x1F0A0345: 0x1F8A,
+	0x1F0B0345: 0x1F8B,
+	0x1F0C0345: 0x1F8C,
+	0x1F0D0345: 0x1F8D,
+	0x1F0E0345: 0x1F8E,
+	0x1F0F0345: 0x1F8F,
+	0x1F200345: 0x1F90,
+	0x1F210345: 0x1F91,
+	0x1F220345: 0x1F92,
+	0x1F230345: 0x1F93,
+	0x1F240345: 0x1F94,
+	0x1F250345: 0x1F95,
+	0x1F260345: 0x1F96,
+	0x1F270345: 0x1F97,
+	0x1F280345: 0x1F98,
+	0x1F290345: 0x1F99,
+	0x1F2A0345: 0x1F9A,
+	0x1F2B0345: 0x1F9B,
+	0x1F2C0345: 0x1F9C,
+	0x1F2D0345: 0x1F9D,
+	0x1F2E0345: 0x1F9E,
+	0x1F2F0345: 0x1F9F,
+	0x1F600345: 0x1FA0,
+	0x1F610345: 0x1FA1,
+	0x1F620345: 0x1FA2,
+	0x1F630345: 0x1FA3,
+	0x1F640345: 0x1FA4,
+	0x1F650345: 0x1FA5,
+	0x1F660345: 0x1FA6,
+	0x1F670345: 0x1FA7,
+	0x1F680345: 0x1FA8,
+	0x1F690345: 0x1FA9,
+	0x1F6A0345: 0x1FAA,
+	0x1F6B0345: 0x1FAB,
+	0x1F6C0345: 0x1FAC,
+	0x1F6D0345: 0x1FAD,
+	0x1F6E0345: 0x1FAE,
+	0x1F6F0345: 0x1FAF,
+	0x03B10306: 0x1FB0,
+	0x03B10304: 0x1FB1,
+	0x1F700345: 0x1FB2,
+	0x03B10345: 0x1FB3,
+	0x03AC0345: 0x1FB4,
+	0x03B10342: 0x1FB6,
+	0x1FB60345: 0x1FB7,
+	0x03910306: 0x1FB8,
+	0x03910304: 0x1FB9,
+	0x03910300: 0x1FBA,
+	0x03910345: 0x1FBC,
+	0x00A80342: 0x1FC1,
+	0x1F740345: 0x1FC2,
+	0x03B70345: 0x1FC3,
+	0x03AE0345: 0x1FC4,
+	0x03B70342: 0x1FC6,
+	0x1FC60345: 0x1FC7,
+	0x03950300: 0x1FC8,
+	0x03970300: 0x1FCA,
+	0x03970345: 0x1FCC,
+	0x1FBF0300: 0x1FCD,
+	0x1FBF0301: 0x1FCE,
+	0x1FBF0342: 0x1FCF,
+	0x03B90306: 0x1FD0,
+	0x03B90304: 0x1FD1,
+	0x03CA0300: 0x1FD2,
+	0x03B90342: 0x1FD6,
+	0x03CA0342: 0x1FD7,
+	0x03990306: 0x1FD8,
+	0x03990304: 0x1FD9,
+	0x03990300: 0x1FDA,
+	0x1FFE0300: 0x1FDD,
+	0x1FFE0301: 0x1FDE,
+	0x1FFE0342: 0x1FDF,
+	0x03C50306: 0x1FE0,
+	0x03C50304: 0x1FE1,
+	0x03CB0300: 0x1FE2,
+	0x03C10313: 0x1FE4,
+	0x03C10314: 0x1FE5,
+	0x03C50342: 0x1FE6,
+	0x03CB0342: 0x1FE7,
+	0x03A50306: 0x1FE8,
+	0x03A50304: 0x1FE9,
+	0x03A50300: 0x1FEA,
+	0x03A10314: 0x1FEC,
+	0x00A80300: 0x1FED,
+	0x1F7C0345: 0x1FF2,
+	0x03C90345: 0x1FF3,
+	0x03CE0345: 0x1FF4,
+	0x03C90342: 0x1FF6,
+	0x1FF60345: 0x1FF7,
+	0x039F0300: 0x1FF8,
+	0x03A90300: 0x1FFA,
+	0x03A90345: 0x1FFC,
+	0x21900338: 0x219A,
+	0x21920338: 0x219B,
+	0x21940338: 0x21AE,
+	0x21D00338: 0x21CD,
+	0x21D40338: 0x21CE,
+	0x21D20338: 0x21CF,
+	0x22030338: 0x2204,
+	0x22080338: 0x2209,
+	0x220B0338: 0x220C,
+	0x22230338: 0x2224,
+	0x22250338: 0x2226,
+	0x223C0338: 0x2241,
+	0x22430338: 0x2244,
+	0x22450338: 0x2247,
+	0x22480338: 0x2249,
+	0x003D0338: 0x2260,
+	0x22610338: 0x2262,
+	0x224D0338: 0x226D,
+	0x003C0338: 0x226E,
+	0x003E0338: 0x226F,
+	0x22640338: 0x2270,
+	0x22650338: 0x2271,
+	0x22720338: 0x2274,
+	0x22730338: 0x2275,
+	0x22760338: 0x2278,
+	0x22770338: 0x2279,
+	0x227A0338: 0x2280,
+	0x227B0338: 0x2281,
+	0x22820338: 0x2284,
+	0x22830338: 0x2285,
+	0x22860338: 0x2288,
+	0x22870338: 0x2289,
+	0x22A20338: 0x22AC,
+	0x22A80338: 0x22AD,
+	0x22A90338: 0x22AE,
+	0x22AB0338: 0x22AF,
+	0x227C0338: 0x22E0,
+	0x227D0338: 0x22E1,
+	0x22910338: 0x22E2,
+	0x22920338: 0x22E3,
+	0x22B20338: 0x22EA,
+	0x22B30338: 0x22EB,
+	0x22B40338: 0x22EC,
+	0x22B50338: 0x22ED,
+	0x304B3099: 0x304C,
+	0x304D3099: 0x304E,
+	0x304F3099: 0x3050,
+	0x30513099: 0x3052,
+	0x30533099: 0x3054,
+	0x30553099: 0x3056,
+	0x30573099: 0x3058,
+	0x30593099: 0x305A,
+	0x305B3099: 0x305C,
+	0x305D3099: 0x305E,
+	0x305F3099: 0x3060,
+	0x30613099: 0x3062,
+	0x30643099: 0x3065,
+	0x30663099: 0x3067,
+	0x30683099: 0x3069,
+	0x306F3099: 0x3070,
+	0x306F309A: 0x3071,
+	0x30723099: 0x3073,
+	0x3072309A: 0x3074,
+	0x30753099: 0x3076,
+	0x3075309A: 0x3077,
+	0x30783099: 0x3079,
+	0x3078309A: 0x307A,
+	0x307B3099: 0x307C,
+	0x307B309A: 0x307D,
+	0x30463099: 0x3094,
+	0x309D3099: 0x309E,
+	0x30AB3099: 0x30AC,
+	0x30AD3099: 0x30AE,
+	0x30AF3099: 0x30B0,
+	0x30B13099: 0x30B2,
+	0x30B33099: 0x30B4,
+	0x30B53099: 0x30B6,
+	0x30B73099: 0x30B8,
+	0x30B93099: 0x30BA,
+	0x30BB3099: 0x30BC,
+	0x30BD3099: 0x30BE,
+	0x30BF3099: 0x30C0,
+	0x30C13099: 0x30C2,
+	0x30C43099: 0x30C5,
+	0x30C63099: 0x30C7,
+	0x30C83099: 0x30C9,
+	0x30CF3099: 0x30D0,
+	0x30CF309A: 0x30D1,
+	0x30D23099: 0x30D3,
+	0x30D2309A: 0x30D4,
+	0x30D53099: 0x30D6,
+	0x30D5309A: 0x30D7,
+	0x30D83099: 0x30D9,
+	0x30D8309A: 0x30DA,
+	0x30DB3099: 0x30DC,
+	0x30DB309A: 0x30DD,
+	0x30A63099: 0x30F4,
+	0x30EF3099: 0x30F7,
+	0x30F03099: 0x30F8,
+	0x30F13099: 0x30F9,
+	0x30F23099: 0x30FA,
+	0x30FD3099: 0x30FE,
+	0x109910BA: 0x1109A,
+	0x109B10BA: 0x1109C,
+	0x10A510BA: 0x110AB,
+	0x11311127: 0x1112E,
+	0x11321127: 0x1112F,
+}
+
+// Total size of tables: 50KB (51625 bytes)
diff --git a/src/pkg/exp/norm/trie.go b/src/pkg/exp/norm/trie.go
new file mode 100644
index 0000000..82267a8
--- /dev/null
+++ b/src/pkg/exp/norm/trie.go
@@ -0,0 +1,232 @@
+// 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 norm
+
+type valueRange struct {
+	value  uint16 // header: value:stride
+	lo, hi byte   // header: lo:n
+}
+
+type trie struct {
+	index        []uint8
+	values       []uint16
+	sparse       []valueRange
+	sparseOffset []uint16
+	cutoff       uint8 // indices >= cutoff are sparse
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
+// is a list of ranges with an accompanying value. Given a matching range r,
+// the value for b is by r.value + (b - r.lo) * stride.
+func (t *trie) lookupValue(n uint8, b byte) uint16 {
+	if n < t.cutoff {
+		return t.values[uint16(n)<<6+uint16(b)]
+	}
+	offset := t.sparseOffset[n-t.cutoff]
+	header := t.sparse[offset]
+	lo := offset + 1
+	hi := lo + uint16(header.lo)
+	for lo < hi {
+		m := lo + (hi-lo)/2
+		r := t.sparse[m]
+		if r.lo <= b && b <= r.hi {
+			return r.value + uint16(b-r.lo)*header.value
+		}
+		if b < r.lo {
+			hi = m
+		} else {
+			lo = m + 1
+		}
+	}
+	return 0
+}
+
+const (
+	t1 = 0x00 // 0000 0000
+	tx = 0x80 // 1000 0000
+	t2 = 0xC0 // 1100 0000
+	t3 = 0xE0 // 1110 0000
+	t4 = 0xF0 // 1111 0000
+	t5 = 0xF8 // 1111 1000
+	t6 = 0xFC // 1111 1100
+	te = 0xFE // 1111 1110
+)
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *trie) lookup(s []byte) (v uint16, sz int) {
+	c0 := s[0]
+	switch {
+	case c0 < tx:
+		return t.values[c0], 1
+	case c0 < t2:
+		return 0, 1
+	case c0 < t3:
+		if len(s) < 2 {
+			return 0, 0
+		}
+		i := t.index[c0]
+		c1 := s[1]
+		if c1 < tx || t2 <= c1 {
+			return 0, 1
+		}
+		return t.lookupValue(i, c1), 2
+	case c0 < t4:
+		if len(s) < 3 {
+			return 0, 0
+		}
+		i := t.index[c0]
+		c1 := s[1]
+		if c1 < tx || t2 <= c1 {
+			return 0, 1
+		}
+		o := uint16(i)<<6 + uint16(c1)
+		i = t.index[o]
+		c2 := s[2]
+		if c2 < tx || t2 <= c2 {
+			return 0, 2
+		}
+		return t.lookupValue(i, c2), 3
+	case c0 < t5:
+		if len(s) < 4 {
+			return 0, 0
+		}
+		i := t.index[c0]
+		c1 := s[1]
+		if c1 < tx || t2 <= c1 {
+			return 0, 1
+		}
+		o := uint16(i)<<6 + uint16(c1)
+		i = t.index[o]
+		c2 := s[2]
+		if c2 < tx || t2 <= c2 {
+			return 0, 2
+		}
+		o = uint16(i)<<6 + uint16(c2)
+		i = t.index[o]
+		c3 := s[3]
+		if c3 < tx || t2 <= c3 {
+			return 0, 3
+		}
+		return t.lookupValue(i, c3), 4
+	}
+	// Illegal rune
+	return 0, 1
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *trie) lookupString(s string) (v uint16, sz int) {
+	c0 := s[0]
+	switch {
+	case c0 < tx:
+		return t.values[c0], 1
+	case c0 < t2:
+		return 0, 1
+	case c0 < t3:
+		if len(s) < 2 {
+			return 0, 0
+		}
+		i := t.index[c0]
+		c1 := s[1]
+		if c1 < tx || t2 <= c1 {
+			return 0, 1
+		}
+		return t.lookupValue(i, c1), 2
+	case c0 < t4:
+		if len(s) < 3 {
+			return 0, 0
+		}
+		i := t.index[c0]
+		c1 := s[1]
+		if c1 < tx || t2 <= c1 {
+			return 0, 1
+		}
+		o := uint16(i)<<6 + uint16(c1)
+		i = t.index[o]
+		c2 := s[2]
+		if c2 < tx || t2 <= c2 {
+			return 0, 2
+		}
+		return t.lookupValue(i, c2), 3
+	case c0 < t5:
+		if len(s) < 4 {
+			return 0, 0
+		}
+		i := t.index[c0]
+		c1 := s[1]
+		if c1 < tx || t2 <= c1 {
+			return 0, 1
+		}
+		o := uint16(i)<<6 + uint16(c1)
+		i = t.index[o]
+		c2 := s[2]
+		if c2 < tx || t2 <= c2 {
+			return 0, 2
+		}
+		o = uint16(i)<<6 + uint16(c2)
+		i = t.index[o]
+		c3 := s[3]
+		if c3 < tx || t2 <= c3 {
+			return 0, 3
+		}
+		return t.lookupValue(i, c3), 4
+	}
+	// Illegal rune
+	return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must hold a full encoding.
+func (t *trie) lookupUnsafe(s []byte) uint16 {
+	c0 := s[0]
+	if c0 < tx {
+		return t.values[c0]
+	}
+	if c0 < t2 {
+		return 0
+	}
+	i := t.index[c0]
+	if c0 < t3 {
+		return t.lookupValue(i, s[1])
+	}
+	i = t.index[uint16(i)<<6+uint16(s[1])]
+	if c0 < t4 {
+		return t.lookupValue(i, s[2])
+	}
+	i = t.index[uint16(i)<<6+uint16(s[2])]
+	if c0 < t5 {
+		return t.lookupValue(i, s[3])
+	}
+	return 0
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must hold a full encoding.
+func (t *trie) lookupStringUnsafe(s string) uint16 {
+	c0 := s[0]
+	if c0 < tx {
+		return t.values[c0]
+	}
+	if c0 < t2 {
+		return 0
+	}
+	i := t.index[c0]
+	if c0 < t3 {
+		return t.lookupValue(i, s[1])
+	}
+	i = t.index[uint16(i)<<6+uint16(s[1])]
+	if c0 < t4 {
+		return t.lookupValue(i, s[2])
+	}
+	i = t.index[uint16(i)<<6+uint16(s[2])]
+	if c0 < t5 {
+		return t.lookupValue(i, s[3])
+	}
+	return 0
+}
diff --git a/src/pkg/exp/norm/trie_test.go b/src/pkg/exp/norm/trie_test.go
new file mode 100644
index 0000000..1a75cc7
--- /dev/null
+++ b/src/pkg/exp/norm/trie_test.go
@@ -0,0 +1,152 @@
+// 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 norm
+
+import (
+	"testing"
+	"unicode/utf8"
+)
+
+// Test data is located in triedata_test.go; generated by maketesttables.
+var testdata = testdataTrie
+
+type rangeTest struct {
+	block   uint8
+	lookup  byte
+	result  uint16
+	table   []valueRange
+	offsets []uint16
+}
+
+var range1Off = []uint16{0, 2}
+var range1 = []valueRange{
+	{0, 1, 0},
+	{1, 0x80, 0x80},
+	{0, 2, 0},
+	{1, 0x80, 0x80},
+	{9, 0xff, 0xff},
+}
+
+var rangeTests = []rangeTest{
+	{10, 0x80, 1, range1, range1Off},
+	{10, 0x00, 0, range1, range1Off},
+	{11, 0x80, 1, range1, range1Off},
+	{11, 0xff, 9, range1, range1Off},
+	{11, 0x00, 0, range1, range1Off},
+}
+
+func TestLookupSparse(t *testing.T) {
+	for i, test := range rangeTests {
+		n := trie{sparse: test.table, sparseOffset: test.offsets, cutoff: 10}
+		v := n.lookupValue(test.block, test.lookup)
+		if v != test.result {
+			t.Errorf("LookupSparse:%d: found %X; want %X", i, v, test.result)
+		}
+	}
+}
+
+// Test cases for illegal runes.
+type trietest struct {
+	size  int
+	bytes []byte
+}
+
+var tests = []trietest{
+	// illegal runes
+	{1, []byte{0x80}},
+	{1, []byte{0xFF}},
+	{1, []byte{t2, tx - 1}},
+	{1, []byte{t2, t2}},
+	{2, []byte{t3, tx, tx - 1}},
+	{2, []byte{t3, tx, t2}},
+	{1, []byte{t3, tx - 1, tx}},
+	{3, []byte{t4, tx, tx, tx - 1}},
+	{3, []byte{t4, tx, tx, t2}},
+	{1, []byte{t4, t2, tx, tx - 1}},
+	{2, []byte{t4, tx, t2, tx - 1}},
+
+	// short runes
+	{0, []byte{t2}},
+	{0, []byte{t3, tx}},
+	{0, []byte{t4, tx, tx}},
+
+	// we only support UTF-8 up to utf8.UTFMax bytes (4 bytes)
+	{1, []byte{t5, tx, tx, tx, tx}},
+	{1, []byte{t6, tx, tx, tx, tx, tx}},
+}
+
+func mkUTF8(r rune) ([]byte, int) {
+	var b [utf8.UTFMax]byte
+	sz := utf8.EncodeRune(b[:], r)
+	return b[:sz], sz
+}
+
+func TestLookup(t *testing.T) {
+	for i, tt := range testRunes {
+		b, szg := mkUTF8(tt)
+		v, szt := testdata.lookup(b)
+		if int(v) != i {
+			t.Errorf("lookup(%U): found value %#x, expected %#x", tt, v, i)
+		}
+		if szt != szg {
+			t.Errorf("lookup(%U): found size %d, expected %d", tt, szt, szg)
+		}
+	}
+	for i, tt := range tests {
+		v, sz := testdata.lookup(tt.bytes)
+		if v != 0 {
+			t.Errorf("lookup of illegal rune, case %d: found value %#x, expected 0", i, v)
+		}
+		if sz != tt.size {
+			t.Errorf("lookup of illegal rune, case %d: found size %d, expected %d", i, sz, tt.size)
+		}
+	}
+	// Verify defaults.
+	if v, _ := testdata.lookup([]byte{0xC1, 0x8C}); v != 0 {
+		t.Errorf("lookup of non-existing rune should be 0; found %X", v)
+	}
+}
+
+func TestLookupUnsafe(t *testing.T) {
+	for i, tt := range testRunes {
+		b, _ := mkUTF8(tt)
+		v := testdata.lookupUnsafe(b)
+		if int(v) != i {
+			t.Errorf("lookupUnsafe(%U): found value %#x, expected %#x", i, v, i)
+		}
+	}
+}
+
+func TestLookupString(t *testing.T) {
+	for i, tt := range testRunes {
+		b, szg := mkUTF8(tt)
+		v, szt := testdata.lookupString(string(b))
+		if int(v) != i {
+			t.Errorf("lookup(%U): found value %#x, expected %#x", i, v, i)
+		}
+		if szt != szg {
+			t.Errorf("lookup(%U): found size %d, expected %d", i, szt, szg)
+		}
+	}
+	for i, tt := range tests {
+		v, sz := testdata.lookupString(string(tt.bytes))
+		if int(v) != 0 {
+			t.Errorf("lookup of illegal rune, case %d: found value %#x, expected 0", i, v)
+		}
+		if sz != tt.size {
+			t.Errorf("lookup of illegal rune, case %d: found size %d, expected %d", i, sz, tt.size)
+		}
+	}
+}
+
+func TestLookupStringUnsafe(t *testing.T) {
+	for i, tt := range testRunes {
+		b, _ := mkUTF8(tt)
+		v := testdata.lookupStringUnsafe(string(b))
+		if int(v) != i {
+			t.Errorf("lookupUnsafe(%U): found value %#x, expected %#x", i, v, i)
+		}
+	}
+}
diff --git a/src/pkg/exp/norm/triedata_test.go b/src/pkg/exp/norm/triedata_test.go
new file mode 100644
index 0000000..d6c832d
--- /dev/null
+++ b/src/pkg/exp/norm/triedata_test.go
@@ -0,0 +1,85 @@
+// Generated by running
+//	maketesttables
+// DO NOT EDIT
+
+package norm
+
+var testRunes = []int32{1, 12, 127, 128, 256, 2047, 2048, 2457, 65535, 65536, 65793, 1114111, 512, 513, 514, 528, 533}
+
+// testdataValues: 192 entries, 384 bytes
+// Block 2 is the null block.
+var testdataValues = [192]uint16{
+	// Block 0x0, offset 0x0
+	0x000c: 0x0001,
+	// Block 0x1, offset 0x40
+	0x007f: 0x0002,
+	// Block 0x2, offset 0x80
+}
+
+// testdataSparseOffset: 10 entries, 20 bytes
+var testdataSparseOffset = []uint16{0x0, 0x2, 0x4, 0x8, 0xa, 0xc, 0xe, 0x10, 0x12, 0x14}
+
+// testdataSparseValues: 22 entries, 88 bytes
+var testdataSparseValues = [22]valueRange{
+	// Block 0x0, offset 0x1
+	{value: 0x0000, lo: 0x01},
+	{value: 0x0003, lo: 0x80, hi: 0x80},
+	// Block 0x1, offset 0x2
+	{value: 0x0000, lo: 0x01},
+	{value: 0x0004, lo: 0x80, hi: 0x80},
+	// Block 0x2, offset 0x3
+	{value: 0x0001, lo: 0x03},
+	{value: 0x000c, lo: 0x80, hi: 0x82},
+	{value: 0x000f, lo: 0x90, hi: 0x90},
+	{value: 0x0010, lo: 0x95, hi: 0x95},
+	// Block 0x3, offset 0x4
+	{value: 0x0000, lo: 0x01},
+	{value: 0x0005, lo: 0xbf, hi: 0xbf},
+	// Block 0x4, offset 0x5
+	{value: 0x0000, lo: 0x01},
+	{value: 0x0006, lo: 0x80, hi: 0x80},
+	// Block 0x5, offset 0x6
+	{value: 0x0000, lo: 0x01},
+	{value: 0x0007, lo: 0x99, hi: 0x99},
+	// Block 0x6, offset 0x7
+	{value: 0x0000, lo: 0x01},
+	{value: 0x0008, lo: 0xbf, hi: 0xbf},
+	// Block 0x7, offset 0x8
+	{value: 0x0000, lo: 0x01},
+	{value: 0x0009, lo: 0x80, hi: 0x80},
+	// Block 0x8, offset 0x9
+	{value: 0x0000, lo: 0x01},
+	{value: 0x000a, lo: 0x81, hi: 0x81},
+	// Block 0x9, offset 0xa
+	{value: 0x0000, lo: 0x01},
+	{value: 0x000b, lo: 0xbf, hi: 0xbf},
+}
+
+// testdataLookup: 640 bytes
+// Block 0 is the null block.
+var testdataLookup = [640]uint8{
+	// Block 0x0, offset 0x0
+	// Block 0x1, offset 0x40
+	// Block 0x2, offset 0x80
+	// Block 0x3, offset 0xc0
+	0x0c2: 0x01, 0x0c4: 0x02,
+	0x0c8: 0x03,
+	0x0df: 0x04,
+	0x0e0: 0x02,
+	0x0ef: 0x03,
+	0x0f0: 0x05, 0x0f4: 0x07,
+	// Block 0x4, offset 0x100
+	0x120: 0x05, 0x126: 0x06,
+	// Block 0x5, offset 0x140
+	0x17f: 0x07,
+	// Block 0x6, offset 0x180
+	0x180: 0x08, 0x184: 0x09,
+	// Block 0x7, offset 0x1c0
+	0x1d0: 0x04,
+	// Block 0x8, offset 0x200
+	0x23f: 0x0a,
+	// Block 0x9, offset 0x240
+	0x24f: 0x06,
+}
+
+var testdataTrie = trie{testdataLookup[:], testdataValues[:], testdataSparseValues[:], testdataSparseOffset[:], 1}
diff --git a/src/pkg/exp/norm/triegen.go b/src/pkg/exp/norm/triegen.go
new file mode 100644
index 0000000..52c88b0
--- /dev/null
+++ b/src/pkg/exp/norm/triegen.go
@@ -0,0 +1,317 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Trie table generator.
+// Used by make*tables tools to generate a go file with trie data structures
+// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte
+// sequence are used to lookup offsets in the index table to be used for the
+// next byte. The last byte is used to index into a table with 16-bit values.
+
+package main
+
+import (
+	"fmt"
+	"hash/crc32"
+	"log"
+	"unicode/utf8"
+)
+
+const (
+	blockSize        = 64
+	blockOffset      = 2 // Subtract two blocks to compensate for the 0x80 added to continuation bytes.
+	maxSparseEntries = 16
+)
+
+// Intermediate trie structure
+type trieNode struct {
+	table [256]*trieNode
+	value int
+	b     byte
+	leaf  bool
+}
+
+func newNode() *trieNode {
+	return new(trieNode)
+}
+
+func (n trieNode) String() string {
+	s := fmt.Sprint("trieNode{table: { non-nil at index: ")
+	for i, v := range n.table {
+		if v != nil {
+			s += fmt.Sprintf("%d, ", i)
+		}
+	}
+	s += fmt.Sprintf("}, value:%#x, b:%#x leaf:%v}", n.value, n.b, n.leaf)
+	return s
+}
+
+func (n trieNode) isInternal() bool {
+	internal := true
+	for i := 0; i < 256; i++ {
+		if nn := n.table[i]; nn != nil {
+			if !internal && !nn.leaf {
+				log.Fatalf("triegen: isInternal: node contains both leaf and non-leaf children (%v)", n)
+			}
+			internal = internal && !nn.leaf
+		}
+	}
+	return internal
+}
+
+func (n trieNode) mostFrequentStride() int {
+	counts := make(map[int]int)
+	v := 0
+	for _, t := range n.table[0x80 : 0x80+blockSize] {
+		if t != nil {
+			if stride := t.value - v; v != 0 && stride >= 0 {
+				counts[stride]++
+			}
+			v = t.value
+		} else {
+			v = 0
+		}
+	}
+	var maxs, maxc int
+	for stride, cnt := range counts {
+		if cnt > maxc || (cnt == maxc && stride < maxs) {
+			maxs, maxc = stride, cnt
+		}
+	}
+	return maxs
+}
+
+func (n trieNode) countSparseEntries() int {
+	stride := n.mostFrequentStride()
+	var count, v int
+	for _, t := range n.table[0x80 : 0x80+blockSize] {
+		tv := 0
+		if t != nil {
+			tv = t.value
+		}
+		if tv-v != stride {
+			if tv != 0 {
+				count++
+			}
+		}
+		v = tv
+	}
+	return count
+}
+
+func (n *trieNode) insert(r rune, value uint16) {
+	var p [utf8.UTFMax]byte
+	sz := utf8.EncodeRune(p[:], r)
+
+	for i := 0; i < sz; i++ {
+		if n.leaf {
+			log.Fatalf("triegen: insert: node (%#v) should not be a leaf", n)
+		}
+		nn := n.table[p[i]]
+		if nn == nil {
+			nn = newNode()
+			nn.b = p[i]
+			n.table[p[i]] = nn
+		}
+		n = nn
+	}
+	n.value = int(value)
+	n.leaf = true
+}
+
+type nodeIndex struct {
+	lookupBlocks []*trieNode
+	valueBlocks  []*trieNode
+	sparseBlocks []*trieNode
+	sparseOffset []uint16
+	sparseCount  int
+
+	lookupBlockIdx map[uint32]int
+	valueBlockIdx  map[uint32]int
+}
+
+func newIndex() *nodeIndex {
+	index := &nodeIndex{}
+	index.lookupBlocks = make([]*trieNode, 0)
+	index.valueBlocks = make([]*trieNode, 0)
+	index.sparseBlocks = make([]*trieNode, 0)
+	index.sparseOffset = make([]uint16, 1)
+	index.lookupBlockIdx = make(map[uint32]int)
+	index.valueBlockIdx = make(map[uint32]int)
+	return index
+}
+
+func computeOffsets(index *nodeIndex, n *trieNode) int {
+	if n.leaf {
+		return n.value
+	}
+	hasher := crc32.New(crc32.MakeTable(crc32.IEEE))
+	// We only index continuation bytes.
+	for i := 0; i < blockSize; i++ {
+		v := 0
+		if nn := n.table[0x80+i]; nn != nil {
+			v = computeOffsets(index, nn)
+		}
+		hasher.Write([]byte{uint8(v >> 8), uint8(v)})
+	}
+	h := hasher.Sum32()
+	if n.isInternal() {
+		v, ok := index.lookupBlockIdx[h]
+		if !ok {
+			v = len(index.lookupBlocks) - blockOffset
+			index.lookupBlocks = append(index.lookupBlocks, n)
+			index.lookupBlockIdx[h] = v
+		}
+		n.value = v
+	} else {
+		v, ok := index.valueBlockIdx[h]
+		if !ok {
+			if c := n.countSparseEntries(); c > maxSparseEntries {
+				v = len(index.valueBlocks) - blockOffset
+				index.valueBlocks = append(index.valueBlocks, n)
+				index.valueBlockIdx[h] = v
+			} else {
+				v = -len(index.sparseOffset)
+				index.sparseBlocks = append(index.sparseBlocks, n)
+				index.sparseOffset = append(index.sparseOffset, uint16(index.sparseCount))
+				index.sparseCount += c + 1
+				index.valueBlockIdx[h] = v
+			}
+		}
+		n.value = v
+	}
+	return n.value
+}
+
+func printValueBlock(nr int, n *trieNode, offset int) {
+	boff := nr * blockSize
+	fmt.Printf("\n// Block %#x, offset %#x", nr, boff)
+	var printnewline bool
+	for i := 0; i < blockSize; i++ {
+		if i%6 == 0 {
+			printnewline = true
+		}
+		v := 0
+		if nn := n.table[i+offset]; nn != nil {
+			v = nn.value
+		}
+		if v != 0 {
+			if printnewline {
+				fmt.Printf("\n")
+				printnewline = false
+			}
+			fmt.Printf("%#04x:%#04x, ", boff+i, v)
+		}
+	}
+}
+
+func printSparseBlock(nr int, n *trieNode) {
+	boff := -n.value
+	fmt.Printf("\n// Block %#x, offset %#x", nr, boff)
+	v := 0
+	//stride := f(n)
+	stride := n.mostFrequentStride()
+	c := n.countSparseEntries()
+	fmt.Printf("\n{value:%#04x,lo:%#02x},", stride, uint8(c))
+	for i, nn := range n.table[0x80 : 0x80+blockSize] {
+		nv := 0
+		if nn != nil {
+			nv = nn.value
+		}
+		if nv-v != stride {
+			if v != 0 {
+				fmt.Printf(",hi:%#02x},", 0x80+i-1)
+			}
+			if nv != 0 {
+				fmt.Printf("\n{value:%#04x,lo:%#02x", nv, nn.b)
+			}
+		}
+		v = nv
+	}
+	if v != 0 {
+		fmt.Printf(",hi:%#02x},", 0x80+blockSize-1)
+	}
+}
+
+func printLookupBlock(nr int, n *trieNode, offset, cutoff int) {
+	boff := nr * blockSize
+	fmt.Printf("\n// Block %#x, offset %#x", nr, boff)
+	var printnewline bool
+	for i := 0; i < blockSize; i++ {
+		if i%8 == 0 {
+			printnewline = true
+		}
+		v := 0
+		if nn := n.table[i+offset]; nn != nil {
+			v = nn.value
+		}
+		if v != 0 {
+			if v < 0 {
+				v = -v - 1 + cutoff
+			}
+			if printnewline {
+				fmt.Printf("\n")
+				printnewline = false
+			}
+			fmt.Printf("%#03x:%#02x, ", boff+i, v)
+		}
+	}
+}
+
+// printTables returns the size in bytes of the generated tables.
+func (t *trieNode) printTables(name string) int {
+	index := newIndex()
+	// Values for 7-bit ASCII are stored in first two block, followed by nil block.
+	index.valueBlocks = append(index.valueBlocks, nil, nil, nil)
+	// First byte of multi-byte UTF-8 codepoints are indexed in 4th block.
+	index.lookupBlocks = append(index.lookupBlocks, nil, nil, nil, nil)
+	// Index starter bytes of multi-byte UTF-8.
+	for i := 0xC0; i < 0x100; i++ {
+		if t.table[i] != nil {
+			computeOffsets(index, t.table[i])
+		}
+	}
+
+	nv := len(index.valueBlocks) * blockSize
+	fmt.Printf("// %sValues: %d entries, %d bytes\n", name, nv, nv*2)
+	fmt.Printf("// Block 2 is the null block.\n")
+	fmt.Printf("var %sValues = [%d]uint16 {", name, nv)
+	printValueBlock(0, t, 0)
+	printValueBlock(1, t, 64)
+	printValueBlock(2, newNode(), 0)
+	for i := 3; i < len(index.valueBlocks); i++ {
+		printValueBlock(i, index.valueBlocks[i], 0x80)
+	}
+	fmt.Print("\n}\n\n")
+
+	ls := len(index.sparseBlocks)
+	fmt.Printf("// %sSparseOffset: %d entries, %d bytes\n", name, ls, ls*2)
+	fmt.Printf("var %sSparseOffset = %#v\n\n", name, index.sparseOffset[1:])
+
+	ns := index.sparseCount
+	fmt.Printf("// %sSparseValues: %d entries, %d bytes\n", name, ns, ns*4)
+	fmt.Printf("var %sSparseValues = [%d]valueRange {", name, ns)
+	for i, n := range index.sparseBlocks {
+		printSparseBlock(i, n)
+	}
+	fmt.Print("\n}\n\n")
+
+	cutoff := len(index.valueBlocks) - blockOffset
+	ni := len(index.lookupBlocks) * blockSize
+	fmt.Printf("// %sLookup: %d bytes\n", name, ni)
+	fmt.Printf("// Block 0 is the null block.\n")
+	fmt.Printf("var %sLookup = [%d]uint8 {", name, ni)
+	printLookupBlock(0, newNode(), 0, cutoff)
+	printLookupBlock(1, newNode(), 0, cutoff)
+	printLookupBlock(2, newNode(), 0, cutoff)
+	printLookupBlock(3, t, 0xC0, cutoff)
+	for i := 4; i < len(index.lookupBlocks); i++ {
+		printLookupBlock(i, index.lookupBlocks[i], 0x80, cutoff)
+	}
+	fmt.Print("\n}\n\n")
+	fmt.Printf("var %sTrie = trie{ %sLookup[:], %sValues[:], %sSparseValues[:], %sSparseOffset[:], %d}\n\n",
+		name, name, name, name, name, cutoff)
+	return nv*2 + ns*4 + ni + ls*2
+}
diff --git a/src/pkg/expvar/expvar_test.go b/src/pkg/expvar/expvar_test.go
index bbd9dd8..572c62b 100644
--- a/src/pkg/expvar/expvar_test.go
+++ b/src/pkg/expvar/expvar_test.go
@@ -18,6 +18,7 @@ func RemoveAll() {
 }
 
 func TestInt(t *testing.T) {
+	RemoveAll()
 	reqs := NewInt("requests")
 	if reqs.i != 0 {
 		t.Errorf("reqs.i = %v, want 0", reqs.i)
@@ -43,6 +44,7 @@ func TestInt(t *testing.T) {
 }
 
 func TestFloat(t *testing.T) {
+	RemoveAll()
 	reqs := NewFloat("requests-float")
 	if reqs.f != 0.0 {
 		t.Errorf("reqs.f = %v, want 0", reqs.f)
@@ -68,6 +70,7 @@ func TestFloat(t *testing.T) {
 }
 
 func TestString(t *testing.T) {
+	RemoveAll()
 	name := NewString("my-name")
 	if name.s != "" {
 		t.Errorf("name.s = %q, want \"\"", name.s)
@@ -84,6 +87,7 @@ func TestString(t *testing.T) {
 }
 
 func TestMapCounter(t *testing.T) {
+	RemoveAll()
 	colors := NewMap("bike-shed-colors")
 
 	colors.Add("red", 1)
@@ -123,6 +127,7 @@ func TestMapCounter(t *testing.T) {
 }
 
 func TestFunc(t *testing.T) {
+	RemoveAll()
 	var x interface{} = []string{"a", "b"}
 	f := Func(func() interface{} { return x })
 	if s, exp := f.String(), `["a","b"]`; s != exp {
diff --git a/src/pkg/flag/flag.go b/src/pkg/flag/flag.go
index 5444ad1..85dd8c3 100644
--- a/src/pkg/flag/flag.go
+++ b/src/pkg/flag/flag.go
@@ -33,7 +33,7 @@
 
 	After parsing, the arguments after the flag are available as the
 	slice flag.Args() or individually as flag.Arg(i).
-	The arguments are indexed from 0 up to flag.NArg().
+	The arguments are indexed from 0 through flag.NArg()-1.
 
 	Command line flag syntax:
 		-flag
@@ -91,6 +91,15 @@ func (b *boolValue) Set(s string) error {
 
 func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
 
+func (b *boolValue) IsBoolFlag() bool { return true }
+
+// optional interface to indicate boolean flags that can be
+// supplied without "=value" text
+type boolFlag interface {
+	Value
+	IsBoolFlag() bool
+}
+
 // -- int Value
 type intValue int
 
@@ -204,6 +213,10 @@ func (d *durationValue) String() string { return (*time.Duration)(d).String() }
 
 // Value is the interface to the dynamic value stored in a flag.
 // (The default value is represented as a string.)
+//
+// If a Value has an IsBoolFlag() bool method returning true,
+// the command-line parser makes -name equivalent to -name=true
+// rather than using the next command-line argument.
 type Value interface {
 	String() string
 	Set(string) error
@@ -704,10 +717,10 @@ func (f *FlagSet) parseOne() (bool, error) {
 		}
 		return false, f.failf("flag provided but not defined: -%s", name)
 	}
-	if fv, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg
+	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 {
-				f.failf("invalid boolean value %q for  -%s: %v", value, name, err)
+				return false, f.failf("invalid boolean value %q for  -%s: %v", value, name, err)
 			}
 		} else {
 			fv.Set("true")
diff --git a/src/pkg/flag/flag_test.go b/src/pkg/flag/flag_test.go
index a9561f2..ddd54b2 100644
--- a/src/pkg/flag/flag_test.go
+++ b/src/pkg/flag/flag_test.go
@@ -15,17 +15,6 @@ import (
 	"time"
 )
 
-var (
-	test_bool     = Bool("test_bool", false, "bool value")
-	test_int      = Int("test_int", 0, "int value")
-	test_int64    = Int64("test_int64", 0, "int64 value")
-	test_uint     = Uint("test_uint", 0, "uint value")
-	test_uint64   = Uint64("test_uint64", 0, "uint64 value")
-	test_string   = String("test_string", "0", "string value")
-	test_float64  = Float64("test_float64", 0, "float64 value")
-	test_duration = Duration("test_duration", 0, "time.Duration value")
-)
-
 func boolString(s string) string {
 	if s == "0" {
 		return "false"
@@ -34,6 +23,16 @@ func boolString(s string) string {
 }
 
 func TestEverything(t *testing.T) {
+	ResetForTesting(nil)
+	Bool("test_bool", false, "bool value")
+	Int("test_int", 0, "int value")
+	Int64("test_int64", 0, "int64 value")
+	Uint("test_uint", 0, "uint value")
+	Uint64("test_uint64", 0, "uint64 value")
+	String("test_string", "0", "string value")
+	Float64("test_float64", 0, "float64 value")
+	Duration("test_duration", 0, "time.Duration value")
+
 	m := make(map[string]*Flag)
 	desired := "0"
 	visitor := func(f *Flag) {
@@ -208,6 +207,47 @@ func TestUserDefined(t *testing.T) {
 	}
 }
 
+// Declare a user-defined boolean flag type.
+type boolFlagVar struct {
+	count int
+}
+
+func (b *boolFlagVar) String() string {
+	return fmt.Sprintf("%d", b.count)
+}
+
+func (b *boolFlagVar) Set(value string) error {
+	if value == "true" {
+		b.count++
+	}
+	return nil
+}
+
+func (b *boolFlagVar) IsBoolFlag() bool {
+	return b.count < 4
+}
+
+func TestUserDefinedBool(t *testing.T) {
+	var flags FlagSet
+	flags.Init("test", ContinueOnError)
+	var b boolFlagVar
+	var err error
+	flags.Var(&b, "b", "usage")
+	if err = flags.Parse([]string{"-b", "-b", "-b", "-b=true", "-b=false", "-b", "barg", "-b"}); err != nil {
+		if b.count < 4 {
+			t.Error(err)
+		}
+	}
+
+	if b.count != 4 {
+		t.Errorf("want: %d; got: %d", 4, b.count)
+	}
+
+	if err == nil {
+		t.Error("expected error; got none")
+	}
+}
+
 func TestSetOutput(t *testing.T) {
 	var flags FlagSet
 	var buf bytes.Buffer
diff --git a/src/pkg/fmt/doc.go b/src/pkg/fmt/doc.go
index a9b9c9d..3cd02d7 100644
--- a/src/pkg/fmt/doc.go
+++ b/src/pkg/fmt/doc.go
@@ -31,8 +31,8 @@
 		%X	base 16, with upper-case letters for A-F
 		%U	Unicode format: U+1234; same as "U+%04X"
 	Floating-point and complex constituents:
-		%b	decimalless scientific notation with exponent a power of two, 
-			in the manner of strconv.FormatFloat with the 'b' format, 
+		%b	decimalless scientific notation with exponent a power of two,
+			in the manner of strconv.FormatFloat with the 'b' format,
 			e.g. -123456p-78
 		%e	scientific notation, e.g. -1234.456e+78
 		%E	scientific notation, e.g. -1234.456E+78
@@ -56,13 +56,17 @@
 	character '*', causing their values to be obtained from the next
 	operand, which must be of type int.
 
-	For numeric values, width sets the width of the field and precision
-	sets the number of places after the decimal, if appropriate.  For
-	example, the format %6.2f prints 123.45.
+	For numeric values, width sets the minimum width of the field and
+	precision sets the number of places after the decimal, if appropriate,
+	except that for %g/%G it sets the total number of digits. For example,
+	given 123.45 the format %6.2f prints 123.45 while %.4g prints 123.5.
+	The default precision for %e and %f is 6; for %g it is the smallest
+	number of digits necessary to identify the value uniquely.
 
-	For strings, width is the minimum number of characters to output,
-	padding with spaces if necessary, and precision is the maximum
-	number of characters to output, truncating if necessary.
+	For most values, width is the minimum number of characters to output,
+	padding the formatted form with spaces if necessary.
+	For strings, precision is the maximum number of characters to output,
+	truncating if necessary.
 
 	Other flags:
 		+	always print a sign for numeric values;
@@ -70,11 +74,17 @@
 		-	pad with spaces on the right rather than the left (left-justify the field)
 		#	alternate format: add leading 0 for octal (%#o), 0x for hex (%#x);
 			0X for hex (%#X); suppress 0x for %p (%#p);
-			print a raw (backquoted) string if possible for %q (%#q);
+			for %q, print a raw (backquoted) string if strconv.CanBackquote
+			returns true;
 			write e.g. U+0078 'x' if the character is printable for %U (%#U).
 		' '	(space) leave a space for elided sign in numbers (% d);
 			put spaces between bytes printing strings or slices in hex (% x, % X)
-		0	pad with leading zeros rather than spaces
+		0	pad with leading zeros rather than spaces;
+			for numbers, this moves the padding after the sign
+
+	Flags are ignored by verbs that do not expect them.
+	For example there is no alternate decimal format, so %#d and %d
+	behave identically.
 
 	For each Printf-like function, there is also a Print function
 	that takes no format and is equivalent to saying %v for every
@@ -152,6 +162,7 @@
 		%T is not implemented
 		%e %E %f %F %g %G are all equivalent and scan any floating point or complex value
 		%s and %v on strings scan a space-delimited token
+		Flags # and + are not implemented.
 
 	The familiar base-setting prefixes 0 (octal) and 0x
 	(hexadecimal) are accepted when scanning integers without a
diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go
index de03429..af4b5c8 100644
--- a/src/pkg/fmt/fmt_test.go
+++ b/src/pkg/fmt/fmt_test.go
@@ -9,7 +9,6 @@ import (
 	. "fmt"
 	"io"
 	"math"
-	"runtime" // for the malloc count test only
 	"strings"
 	"testing"
 	"time"
@@ -96,7 +95,7 @@ type SI struct {
 	I interface{}
 }
 
-// A type with a String method with pointer receiver for testing %p
+// P is a type with a String method with pointer receiver for testing %p.
 type P int
 
 var pValue P
@@ -105,6 +104,9 @@ func (p *P) String() string {
 	return "String(p)"
 }
 
+var barray = [5]renamedUint8{1, 2, 3, 4, 5}
+var bslice = barray[:]
+
 var b byte
 
 var fmttests = []struct {
@@ -127,6 +129,10 @@ var fmttests = []struct {
 	{"%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"), "0x61 0x62 0x63 0xff"},
+	{"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"},
 	{"% X", []byte("abc\xff"), "61 62 63 FF"},
 	{"%x", []byte("xyz"), "78797a"},
 	{"%X", []byte("xyz"), "78797A"},
@@ -172,6 +178,8 @@ var fmttests = []struct {
 	{"%.3q", "日本語日本語", `"日本語"`},
 	{"%.3q", []byte("日本語日本語"), `"日本語"`},
 	{"%10.1q", "日本語日本語", `       "日"`},
+	{"%10v", nil, "     <nil>"},
+	{"%-10v", nil, "<nil>     "},
 
 	// integers
 	{"%d", 12345, "12345"},
@@ -328,14 +336,18 @@ var fmttests = []struct {
 	// arrays
 	{"%v", array, "[1 2 3 4 5]"},
 	{"%v", iarray, "[1 hello 2.5 <nil>]"},
+	{"%v", barray, "[1 2 3 4 5]"},
 	{"%v", &array, "&[1 2 3 4 5]"},
 	{"%v", &iarray, "&[1 hello 2.5 <nil>]"},
+	{"%v", &barray, "&[1 2 3 4 5]"},
 
 	// slices
 	{"%v", slice, "[1 2 3 4 5]"},
 	{"%v", islice, "[1 hello 2.5 <nil>]"},
+	{"%v", bslice, "[1 2 3 4 5]"},
 	{"%v", &slice, "&[1 2 3 4 5]"},
 	{"%v", &islice, "&[1 hello 2.5 <nil>]"},
+	{"%v", &bslice, "&[1 2 3 4 5]"},
 
 	// complexes with %v
 	{"%v", 1 + 2i, "(1+2i)"},
@@ -350,10 +362,12 @@ var fmttests = []struct {
 	{"%+v", B{1, 2}, `{I:<1> j:2}`},
 	{"%+v", C{1, B{2, 3}}, `{i:1 B:{I:<2> j:3}}`},
 
-	// q on Stringable items
+	// other formats on Stringable items
 	{"%s", I(23), `<23>`},
 	{"%q", I(23), `"<23>"`},
 	{"%x", I(23), `3c32333e`},
+	{"%#x", I(23), `0x3c0x320x330x3e`},
+	{"%# x", I(23), `0x3c 0x32 0x33 0x3e`},
 	{"%d", I(23), `23`}, // Stringer applies only to string formats.
 
 	// go syntax
@@ -375,6 +389,9 @@ var fmttests = []struct {
 	{"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
 	{"%#v", map[int]byte(nil), `map[int]uint8(nil)`},
 	{"%#v", map[int]byte{}, `map[int]uint8{}`},
+	{"%#v", "foo", `"foo"`},
+	{"%#v", barray, `[5]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`},
+	{"%#v", bslice, `[]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`},
 
 	// slices with other formats
 	{"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`},
@@ -400,6 +417,9 @@ var fmttests = []struct {
 	{"%x", renamedString("thing"), "7468696e67"},
 	{"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`},
 	{"%q", renamedBytes([]byte("hello")), `"hello"`},
+	{"%x", []renamedUint8{'a', 'b', 'c'}, "616263"},
+	{"%s", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "hello"},
+	{"%q", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, `"hello"`},
 	{"%v", renamedFloat32(22), "22"},
 	{"%v", renamedFloat64(33), "33"},
 	{"%v", renamedComplex64(3 + 4i), "(3+4i)"},
@@ -419,6 +439,8 @@ var fmttests = []struct {
 	{"%T", renamedComplex128(4 - 3i), "fmt_test.renamedComplex128"},
 	{"%T", intVal, "int"},
 	{"%6T", &intVal, "  *int"},
+	{"%10T", nil, "     <nil>"},
+	{"%-10T", nil, "<nil>     "},
 
 	// %p
 	{"p0=%p", new(int), "p0=0xPTR"},
@@ -441,6 +463,11 @@ var fmttests = []struct {
 	{"%v", (*int)(nil), "<nil>"},
 	{"%v", new(int), "0xPTR"},
 
+	// %d etc. pointers use specified base.
+	{"%d", new(int), "PTR_d"},
+	{"%o", new(int), "PTR_o"},
+	{"%x", new(int), "PTR_x"},
+
 	// %d on Stringer should give integer if possible
 	{"%s", time.Time{}.Month(), "January"},
 	{"%d", time.Time{}.Month(), "1"},
@@ -464,20 +491,37 @@ var fmttests = []struct {
 
 	// Used to crash because nByte didn't allow for a sign.
 	{"%b", int64(-1 << 63), "-1000000000000000000000000000000000000000000000000000000000000000"},
+
+	// Complex fmt used to leave the plus flag set for future entries in the array
+	// causing +2+0i and +3+0i instead of 2+0i and 3+0i.
+	{"%v", []complex64{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"},
+	{"%v", []complex128{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"},
 }
 
 func TestSprintf(t *testing.T) {
 	for _, tt := range fmttests {
 		s := Sprintf(tt.fmt, tt.val)
 		if i := strings.Index(tt.out, "PTR"); i >= 0 {
+			pattern := "PTR"
+			chars := "0123456789abcdefABCDEF"
+			switch {
+			case strings.HasPrefix(tt.out[i:], "PTR_d"):
+				pattern = "PTR_d"
+				chars = chars[:10]
+			case strings.HasPrefix(tt.out[i:], "PTR_o"):
+				pattern = "PTR_o"
+				chars = chars[:8]
+			case strings.HasPrefix(tt.out[i:], "PTR_x"):
+				pattern = "PTR_x"
+			}
 			j := i
 			for ; j < len(s); j++ {
 				c := s[j]
-				if (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F') {
+				if !strings.ContainsRune(chars, rune(c)) {
 					break
 				}
 			}
-			s = s[0:i] + "PTR" + s[j:]
+			s = s[0:i] + pattern + s[j:]
 		}
 		if s != tt.out {
 			if _, ok := tt.val.(string); ok {
@@ -527,6 +571,14 @@ func BenchmarkSprintfFloat(b *testing.B) {
 	}
 }
 
+func BenchmarkManyArgs(b *testing.B) {
+	var buf bytes.Buffer
+	for i := 0; i < b.N; i++ {
+		buf.Reset()
+		Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world")
+	}
+}
+
 var mallocBuf bytes.Buffer
 
 var mallocTest = []struct {
@@ -550,17 +602,9 @@ var _ bytes.Buffer
 
 func TestCountMallocs(t *testing.T) {
 	for _, mt := range mallocTest {
-		const N = 100
-		memstats := new(runtime.MemStats)
-		runtime.ReadMemStats(memstats)
-		mallocs := 0 - memstats.Mallocs
-		for i := 0; i < N; i++ {
-			mt.fn()
-		}
-		runtime.ReadMemStats(memstats)
-		mallocs += memstats.Mallocs
-		if mallocs/N > uint64(mt.count) {
-			t.Errorf("%s: expected %d mallocs, got %d", mt.desc, mt.count, mallocs/N)
+		mallocs := testing.AllocsPerRun(100, mt.fn)
+		if got, max := mallocs, float64(mt.count); got > max {
+			t.Errorf("%s: got %v allocs, want <=%v", mt.desc, got, max)
 		}
 	}
 }
@@ -636,7 +680,8 @@ func TestStructPrinter(t *testing.T) {
 	}
 }
 
-// Check map printing using substrings so we don't depend on the print order.
+// presentInMap checks map printing using substrings so we don't depend on the
+// print order.
 func presentInMap(s string, a []string, t *testing.T) {
 	for i := 0; i < len(a); i++ {
 		loc := strings.Index(s, a[i])
@@ -677,8 +722,8 @@ func TestEmptyMap(t *testing.T) {
 	}
 }
 
-// Check that Sprint (and hence Print, Fprint) puts spaces in the right places,
-// that is, between arg pairs in which neither is a string.
+// TestBlank checks that Sprint (and hence Print, Fprint) puts spaces in the
+// right places, that is, between arg pairs in which neither is a string.
 func TestBlank(t *testing.T) {
 	got := Sprint("<", 1, ">:", 1, 2, 3, "!")
 	expect := "<1>:1 2 3!"
@@ -687,8 +732,8 @@ func TestBlank(t *testing.T) {
 	}
 }
 
-// Check that Sprintln (and hence Println, Fprintln) puts spaces in the right places,
-// that is, between all arg pairs.
+// TestBlankln checks that Sprintln (and hence Println, Fprintln) puts spaces in
+// the right places, that is, between all arg pairs.
 func TestBlankln(t *testing.T) {
 	got := Sprintln("<", 1, ">:", 1, 2, 3, "!")
 	expect := "< 1 >: 1 2 3 !\n"
@@ -697,7 +742,7 @@ func TestBlankln(t *testing.T) {
 	}
 }
 
-// Check Formatter with Sprint, Sprintln, Sprintf
+// TestFormatterPrintln checks Formatter with Sprint, Sprintln, Sprintf.
 func TestFormatterPrintln(t *testing.T) {
 	f := F(1)
 	expect := "<v=F(1)>\n"
@@ -746,7 +791,7 @@ func TestWidthAndPrecision(t *testing.T) {
 	}
 }
 
-// A type that panics in String.
+// Panic is a type that panics in String.
 type Panic struct {
 	message interface{}
 }
@@ -761,7 +806,7 @@ func (p Panic) String() string {
 	panic(p.message)
 }
 
-// A type that panics in Format.
+// PanicF is a type that panics in Format.
 type PanicF struct {
 	message interface{}
 }
@@ -799,7 +844,7 @@ func TestPanics(t *testing.T) {
 	}
 }
 
-// Test that erroneous String routine doesn't cause fatal recursion.
+// recurCount tests that erroneous String routine doesn't cause fatal recursion.
 var recurCount = 0
 
 type Recur struct {
@@ -842,3 +887,15 @@ func TestIsSpace(t *testing.T) {
 		}
 	}
 }
+
+func TestNilDoesNotBecomeTyped(t *testing.T) {
+	type A struct{}
+	type B struct{}
+	var a *A = nil
+	var b B = B{}
+	got := Sprintf("%s %s %s %s %s", nil, a, nil, b, nil)
+	const expect = "%!s(<nil>) %!s(*fmt_test.A=<nil>) %!s(<nil>) {} %!s(<nil>)"
+	if got != expect {
+		t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got)
+	}
+}
diff --git a/src/pkg/fmt/format.go b/src/pkg/fmt/format.go
index caf900d..5665db1 100644
--- a/src/pkg/fmt/format.go
+++ b/src/pkg/fmt/format.go
@@ -72,7 +72,7 @@ func (f *fmt) init(buf *buffer) {
 	f.clearflags()
 }
 
-// Compute left and right padding widths (only one will be non-zero).
+// computePadding computes left and right padding widths (only one will be non-zero).
 func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) {
 	left := !f.minus
 	w := f.wid
@@ -95,7 +95,7 @@ func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth i
 	return
 }
 
-// Generate n bytes of padding.
+// writePadding generates n bytes of padding.
 func (f *fmt) writePadding(n int, padding []byte) {
 	for n > 0 {
 		m := n
@@ -107,14 +107,13 @@ func (f *fmt) writePadding(n int, padding []byte) {
 	}
 }
 
-// Append b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus)
-// clear flags afterwards.
+// pad appends b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus).
 func (f *fmt) pad(b []byte) {
-	var padding []byte
-	var left, right int
-	if f.widPresent && f.wid != 0 {
-		padding, left, right = f.computePadding(len(b))
+	if !f.widPresent || f.wid == 0 {
+		f.buf.Write(b)
+		return
 	}
+	padding, left, right := f.computePadding(len(b))
 	if left > 0 {
 		f.writePadding(left, padding)
 	}
@@ -124,14 +123,13 @@ func (f *fmt) pad(b []byte) {
 	}
 }
 
-// append s to buf, padded on left (w > 0) or right (w < 0 or f.minus).
-// clear flags afterwards.
+// padString appends s to buf, padded on left (w > 0) or right (w < 0 or f.minus).
 func (f *fmt) padString(s string) {
-	var padding []byte
-	var left, right int
-	if f.widPresent && f.wid != 0 {
-		padding, left, right = f.computePadding(utf8.RuneCountInString(s))
+	if !f.widPresent || f.wid == 0 {
+		f.buf.WriteString(s)
+		return
 	}
+	padding, left, right := f.computePadding(utf8.RuneCountInString(s))
 	if left > 0 {
 		f.writePadding(left, padding)
 	}
@@ -141,17 +139,6 @@ func (f *fmt) padString(s string) {
 	}
 }
 
-func putint(buf []byte, base, val uint64, digits string) int {
-	i := len(buf) - 1
-	for val >= base {
-		buf[i] = digits[val%base]
-		i--
-		val /= base
-	}
-	buf[i] = digits[val]
-	return i - 1
-}
-
 var (
 	trueBytes  = []byte("true")
 	falseBytes = []byte("false")
@@ -285,18 +272,41 @@ func (f *fmt) fmt_s(s string) {
 	f.padString(s)
 }
 
-// fmt_sx formats a string as a hexadecimal encoding of its bytes.
-func (f *fmt) fmt_sx(s, digits string) {
+// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
+func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
+	n := len(b)
+	if b == nil {
+		n = len(s)
+	}
+	x := digits[10] - 'a' + 'x'
 	// TODO: Avoid buffer by pre-padding.
-	var b []byte
-	for i := 0; i < len(s); i++ {
+	var buf []byte
+	for i := 0; i < n; i++ {
 		if i > 0 && f.space {
-			b = append(b, ' ')
+			buf = append(buf, ' ')
 		}
-		v := s[i]
-		b = append(b, digits[v>>4], digits[v&0xF])
+		if f.sharp {
+			buf = append(buf, '0', x)
+		}
+		var c byte
+		if b == nil {
+			c = s[i]
+		} else {
+			c = b[i]
+		}
+		buf = append(buf, digits[c>>4], digits[c&0xF])
 	}
-	f.pad(b)
+	f.pad(buf)
+}
+
+// fmt_sx formats a string as a hexadecimal encoding of its bytes.
+func (f *fmt) fmt_sx(s, digits string) {
+	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) {
+	f.fmt_sbx("", b, digits)
 }
 
 // fmt_q formats a string as a double-quoted, escaped Go string constant.
@@ -373,7 +383,7 @@ func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) }
 // fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
 func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) }
 
-// fmt_g64 formats a float64 in the 'f' or 'E' form according to size.
+// fmt_G64 formats a float64 in the 'f' or 'E' form according to size.
 func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) }
 
 // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
@@ -405,6 +415,7 @@ func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
 func (f *fmt) fmt_c64(v complex64, verb rune) {
 	f.buf.WriteByte('(')
 	r := real(v)
+	oldPlus := f.plus
 	for i := 0; ; i++ {
 		switch verb {
 		case 'e':
@@ -424,6 +435,7 @@ func (f *fmt) fmt_c64(v complex64, verb rune) {
 		f.plus = true
 		r = imag(v)
 	}
+	f.plus = oldPlus
 	f.buf.Write(irparenBytes)
 }
 
@@ -431,6 +443,7 @@ func (f *fmt) fmt_c64(v complex64, verb rune) {
 func (f *fmt) fmt_c128(v complex128, verb rune) {
 	f.buf.WriteByte('(')
 	r := real(v)
+	oldPlus := f.plus
 	for i := 0; ; i++ {
 		switch verb {
 		case 'e':
@@ -450,5 +463,6 @@ func (f *fmt) fmt_c128(v complex128, verb rune) {
 		f.plus = true
 		r = imag(v)
 	}
+	f.plus = oldPlus
 	f.buf.Write(irparenBytes)
 }
diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go
index 1343824..7d7aa93 100644
--- a/src/pkg/fmt/print.go
+++ b/src/pkg/fmt/print.go
@@ -26,8 +26,8 @@ var (
 	extraBytes      = []byte("%!(EXTRA ")
 	irparenBytes    = []byte("i)")
 	bytesBytes      = []byte("[]byte{")
-	widthBytes      = []byte("%!(BADWIDTH)")
-	precBytes       = []byte("%!(BADPREC)")
+	badWidthBytes   = []byte("%!(BADWIDTH)")
+	badPrecBytes    = []byte("%!(BADPREC)")
 	noVerbBytes     = []byte("%!(NOVERB)")
 )
 
@@ -153,7 +153,7 @@ func newCache(f func() interface{}) *cache {
 
 var ppFree = newCache(func() interface{} { return new(pp) })
 
-// Allocate a new pp struct or grab a cached one.
+// newPrinter allocates a new pp struct or grab a cached one.
 func newPrinter() *pp {
 	p := ppFree.get().(*pp)
 	p.panicking = false
@@ -162,7 +162,7 @@ func newPrinter() *pp {
 	return p
 }
 
-// Save used pp structs in ppFree; avoids an allocation per invocation.
+// free saves used pp structs in ppFree; avoids an allocation per invocation.
 func (p *pp) free() {
 	// Don't hold on to pp structs with large buffers.
 	if cap(p.buf) > 1024 {
@@ -231,7 +231,7 @@ func Sprintf(format string, a ...interface{}) string {
 	return s
 }
 
-// Errorf formats according to a format specifier and returns the string 
+// Errorf formats according to a format specifier and returns the string
 // as a value that satisfies error.
 func Errorf(format string, a ...interface{}) error {
 	return errors.New(Sprintf(format, a...))
@@ -299,7 +299,7 @@ func Sprintln(a ...interface{}) string {
 	return s
 }
 
-// Get the i'th arg of the struct value.
+// getField gets the i'th arg of the struct value.
 // If the arg itself is an interface, return a value for
 // the thing inside the interface, not the interface itself.
 func getField(v reflect.Value, i int) reflect.Value {
@@ -310,7 +310,7 @@ func getField(v reflect.Value, i int) reflect.Value {
 	return val
 }
 
-// Convert ASCII to integer.  n is 0 (and got is false) if no number present.
+// parsenum converts ASCII to integer.  num is 0 (and isnum is false) if no number present.
 func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
 	if start >= end {
 		return 0, false, end
@@ -545,10 +545,15 @@ func (p *pp) fmtString(v string, verb rune, goSyntax bool) {
 	}
 }
 
-func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, depth int) {
+func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, depth int) {
 	if verb == 'v' || verb == 'd' {
 		if goSyntax {
-			p.buf.Write(bytesBytes)
+			if typ == nil {
+				p.buf.Write(bytesBytes)
+			} else {
+				p.buf.WriteString(typ.String())
+				p.buf.WriteByte('{')
+			}
 		} else {
 			p.buf.WriteByte('[')
 		}
@@ -569,24 +574,27 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, depth int) {
 		}
 		return
 	}
-	s := string(v)
 	switch verb {
 	case 's':
-		p.fmt.fmt_s(s)
+		p.fmt.fmt_s(string(v))
 	case 'x':
-		p.fmt.fmt_sx(s, ldigits)
+		p.fmt.fmt_bx(v, ldigits)
 	case 'X':
-		p.fmt.fmt_sx(s, udigits)
+		p.fmt.fmt_bx(v, udigits)
 	case 'q':
-		p.fmt.fmt_q(s)
+		p.fmt.fmt_q(string(v))
 	default:
 		p.badVerb(verb)
 	}
 }
 
 func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
+	use0x64 := true
 	switch verb {
-	case 'p', 'v', 'b', 'd', 'o', 'x', 'X':
+	case 'p', 'v':
+		// ok
+	case 'b', 'd', 'o', 'x', 'X':
+		use0x64 = false
 		// ok
 	default:
 		p.badVerb(verb)
@@ -616,7 +624,11 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
 	} else if verb == 'v' && u == 0 {
 		p.buf.Write(nilAngleBytes)
 	} else {
-		p.fmt0x64(uint64(u), !p.fmt.sharp)
+		if use0x64 {
+			p.fmt0x64(uint64(u), !p.fmt.sharp)
+		} else {
+			p.fmtUint64(uint64(u), verb, false)
+		}
 	}
 }
 
@@ -712,17 +724,18 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString
 }
 
 func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+	p.field = field
+	p.value = reflect.Value{}
+
 	if field == nil {
 		if verb == 'T' || verb == 'v' {
-			p.buf.Write(nilAngleBytes)
+			p.fmt.pad(nilAngleBytes)
 		} else {
 			p.badVerb(verb)
 		}
 		return false
 	}
 
-	p.field = field
-	p.value = reflect.Value{}
 	// Special processing considerations.
 	// %T (the value's type) and %p (its address) are special; we always do them first.
 	switch verb {
@@ -734,8 +747,17 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
 		return false
 	}
 
-	if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
-		return wasString
+	// 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.
@@ -776,9 +798,16 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
 		p.fmtString(f, verb, goSyntax)
 		wasString = verb == 's' || verb == 'v'
 	case []byte:
-		p.fmtBytes(f, verb, goSyntax, depth)
+		p.fmtBytes(f, verb, goSyntax, 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 wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
+			return wasString
+		}
 		// Need to use reflection
 		return p.printReflectValue(reflect.ValueOf(field), verb, plus, goSyntax, depth)
 	}
@@ -915,19 +944,22 @@ BigSwitch:
 		}
 	case reflect.Array, reflect.Slice:
 		// Byte slices are special.
-		if f.Type().Elem().Kind() == reflect.Uint8 {
-			// We know it's a slice of bytes, but we also know it does not have static type
-			// []byte, or it would have been caught above.  Therefore we cannot convert
-			// it directly in the (slightly) obvious way: f.Interface().([]byte); it doesn't have
-			// that type, and we can't write an expression of the right type and do a
-			// conversion because we don't have a static way to write the right type.
-			// So we build a slice by hand.  This is a rare case but it would be nice
-			// if reflection could help a little more.
-			bytes := make([]byte, f.Len())
-			for i := range bytes {
-				bytes[i] = byte(f.Index(i).Uint())
+		if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 {
+			var bytes []byte
+			if f.Kind() == reflect.Slice {
+				bytes = f.Bytes()
+			} else if f.CanAddr() {
+				bytes = f.Slice(0, f.Len()).Bytes()
+			} else {
+				// We have an array, but we cannot Slice() a non-addressable array,
+				// so we build a slice by hand. This is a rare case but it would be nice
+				// if reflection could help a little more.
+				bytes = make([]byte, f.Len())
+				for i := range bytes {
+					bytes[i] = byte(f.Index(i).Uint())
+				}
 			}
-			p.fmtBytes(bytes, verb, goSyntax, depth)
+			p.fmtBytes(bytes, verb, goSyntax, typ, depth)
 			wasString = verb == 's'
 			break
 		}
@@ -1033,7 +1065,7 @@ func (p *pp) doPrintf(format string, a []interface{}) {
 		if i < end && format[i] == '*' {
 			p.fmt.wid, p.fmt.widPresent, i, fieldnum = intFromArg(a, end, i, fieldnum)
 			if !p.fmt.widPresent {
-				p.buf.Write(widthBytes)
+				p.buf.Write(badWidthBytes)
 			}
 		} else {
 			p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end)
@@ -1043,7 +1075,7 @@ func (p *pp) doPrintf(format string, a []interface{}) {
 			if format[i+1] == '*' {
 				p.fmt.prec, p.fmt.precPresent, i, fieldnum = intFromArg(a, end, i+1, fieldnum)
 				if !p.fmt.precPresent {
-					p.buf.Write(precBytes)
+					p.buf.Write(badPrecBytes)
 				}
 			} else {
 				p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i+1, end)
@@ -1099,7 +1131,7 @@ func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
 	prevString := false
 	for fieldnum := 0; fieldnum < len(a); fieldnum++ {
 		p.fmt.clearflags()
-		// always add spaces if we're doing println
+		// always add spaces if we're doing Println
 		field := a[fieldnum]
 		if fieldnum > 0 {
 			isString := field != nil && reflect.TypeOf(field).Kind() == reflect.String
diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go
index 0b3e040..bf888c4 100644
--- a/src/pkg/fmt/scan.go
+++ b/src/pkg/fmt/scan.go
@@ -33,8 +33,8 @@ type ScanState interface {
 	ReadRune() (r rune, size int, err error)
 	// UnreadRune causes the next call to ReadRune to return the same rune.
 	UnreadRune() error
-	// SkipSpace skips space in the input. Newlines are treated as space 
-	// unless the scan operation is Scanln, Fscanln or Sscanln, in which case 
+	// SkipSpace skips space in the input. Newlines are treated as space
+	// unless the scan operation is Scanln, Fscanln or Sscanln, in which case
 	// a newline is treated as EOF.
 	SkipSpace()
 	// Token skips space in the input if skipSpace is true, then returns the
@@ -312,8 +312,9 @@ func notSpace(r rune) bool {
 	return !isSpace(r)
 }
 
-// skipSpace provides Scan() methods the ability to skip space and newline characters 
-// in keeping with the current scanning mode set by format strings and Scan()/Scanln().
+// SkipSpace provides Scan methods the ability to skip space and newline
+// characters in keeping with the current scanning mode set by format strings
+// and Scan/Scanln.
 func (s *ss) SkipSpace() {
 	s.skipSpace(false)
 }
@@ -337,7 +338,10 @@ func (r *readRune) readByte() (b byte, err error) {
 		r.pending--
 		return
 	}
-	_, err = r.reader.Read(r.pendBuf[0:1])
+	n, err := io.ReadFull(r.reader, r.pendBuf[0:1])
+	if n != 1 {
+		return 0, err
+	}
 	return r.pendBuf[0], err
 }
 
@@ -378,7 +382,7 @@ func (r *readRune) ReadRune() (rr rune, size int, err error) {
 
 var ssFree = newCache(func() interface{} { return new(ss) })
 
-// Allocate a new ss struct or grab a cached one.
+// newScanState allocates a new ss struct or grab a cached one.
 func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) {
 	// If the reader is a *ss, then we've got a recursive
 	// call to Scan, so re-use the scan state.
@@ -410,7 +414,7 @@ func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) {
 	return
 }
 
-// Save used ss structs in ssFree; avoid an allocation per invocation.
+// free saves used ss structs in ssFree; avoid an allocation per invocation.
 func (s *ss) free(old ssave) {
 	// If it was used recursively, just restore the old state.
 	if old.validSave {
@@ -1090,7 +1094,8 @@ func (s *ss) advance(format string) (i int) {
 			// There was space in the format, so there should be space (EOF)
 			// in the input.
 			inputc := s.getRune()
-			if inputc == eof {
+			if inputc == eof || inputc == '\n' {
+				// If we've reached a newline, stop now; don't read ahead.
 				return
 			}
 			if !isSpace(inputc) {
diff --git a/src/pkg/fmt/scan_test.go b/src/pkg/fmt/scan_test.go
index 320857b..4e2c0fe 100644
--- a/src/pkg/fmt/scan_test.go
+++ b/src/pkg/fmt/scan_test.go
@@ -626,7 +626,7 @@ func TestScanlnWithMiddleNewline(t *testing.T) {
 	}
 }
 
-// Special Reader that counts reads at end of file.
+// eofCounter is a special Reader that counts reads at end of file.
 type eofCounter struct {
 	reader   *strings.Reader
 	eofCount int
@@ -640,8 +640,8 @@ func (ec *eofCounter) Read(b []byte) (n int, err error) {
 	return
 }
 
-// Verify that when we scan, we see at most EOF once per call to a Scan function,
-// and then only when it's really an EOF
+// TestEOF verifies that when we scan, we see at most EOF once per call to a
+// Scan function, and then only when it's really an EOF.
 func TestEOF(t *testing.T) {
 	ec := &eofCounter{strings.NewReader("123\n"), 0}
 	var a int
@@ -668,7 +668,7 @@ func TestEOF(t *testing.T) {
 	}
 }
 
-// Verify that we see an EOF error if we run out of input.
+// TestEOFAtEndOfInput verifies that we see an EOF error if we run out of input.
 // This was a buglet: we used to get "expected integer".
 func TestEOFAtEndOfInput(t *testing.T) {
 	var i, j int
@@ -730,7 +730,8 @@ func TestEOFAllTypes(t *testing.T) {
 	}
 }
 
-// Verify that, at least when using bufio, successive calls to Fscan do not lose runes.
+// TestUnreadRuneWithBufio verifies that, at least when using bufio, successive
+// calls to Fscan do not lose runes.
 func TestUnreadRuneWithBufio(t *testing.T) {
 	r := bufio.NewReader(strings.NewReader("123αb"))
 	var i int
@@ -753,7 +754,7 @@ func TestUnreadRuneWithBufio(t *testing.T) {
 
 type TwoLines string
 
-// Attempt to read two lines into the object.  Scanln should prevent this
+// Scan attempts to read two lines into the object.  Scanln should prevent this
 // because it stops at newline; Scan and Scanf should be fine.
 func (t *TwoLines) Scan(state ScanState, verb rune) error {
 	chars := make([]rune, 0, 100)
@@ -810,6 +811,34 @@ func TestMultiLine(t *testing.T) {
 	}
 }
 
+// simpleReader is a strings.Reader that implements only Read, not ReadRune.
+// Good for testing readahead.
+type simpleReader struct {
+	sr *strings.Reader
+}
+
+func (s *simpleReader) Read(b []byte) (n int, err error) {
+	return s.sr.Read(b)
+}
+
+// TestLineByLineFscanf tests that Fscanf does not read past newline. Issue
+// 3481.
+func TestLineByLineFscanf(t *testing.T) {
+	r := &simpleReader{strings.NewReader("1\n2\n")}
+	var i, j int
+	n, err := Fscanf(r, "%v\n", &i)
+	if n != 1 || err != nil {
+		t.Fatalf("first read: %d %q", n, err)
+	}
+	n, err = Fscanf(r, "%v\n", &j)
+	if n != 1 || err != nil {
+		t.Fatalf("second read: %d %q", n, err)
+	}
+	if i != 1 || j != 2 {
+		t.Errorf("wrong values; wanted 1 2 got %d %d", i, j)
+	}
+}
+
 // RecursiveInt accepts a string matching %d.%d.%d....
 // and parses it into a linked list.
 // It allows us to benchmark recursive descent style scanners.
@@ -835,7 +864,7 @@ func (r *RecursiveInt) Scan(state ScanState, verb rune) (err error) {
 	return
 }
 
-// Perform the same scanning task as RecursiveInt.Scan
+// scanInts performs the same scanning task as RecursiveInt.Scan
 // but without recurring through scanner, so we can compare
 // performance more directly.
 func scanInts(r *RecursiveInt, b *bytes.Buffer) (err error) {
diff --git a/src/pkg/go/ast/ast.go b/src/pkg/go/ast/ast.go
index d2e75dc..bf533d1 100644
--- a/src/pkg/go/ast/ast.go
+++ b/src/pkg/go/ast/ast.go
@@ -407,6 +407,7 @@ type (
 	// A ChanType node represents a channel type.
 	ChanType struct {
 		Begin token.Pos // position of "chan" keyword or "<-" (whichever comes first)
+		Arrow token.Pos // position of "<-" (noPos if there is no "<-")
 		Dir   ChanDir   // channel direction
 		Value Expr      // value type
 	}
@@ -554,7 +555,7 @@ type (
 
 	// A DeclStmt node represents a declaration in a statement list.
 	DeclStmt struct {
-		Decl Decl
+		Decl Decl // *GenDecl with CONST, TYPE, or VAR token
 	}
 
 	// An EmptyStmt node represents an empty statement.
diff --git a/src/pkg/go/ast/commentmap.go b/src/pkg/go/ast/commentmap.go
new file mode 100644
index 0000000..252d460
--- /dev/null
+++ b/src/pkg/go/ast/commentmap.go
@@ -0,0 +1,332 @@
+// 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 ast
+
+import (
+	"bytes"
+	"fmt"
+	"go/token"
+	"sort"
+)
+
+type byPos []*CommentGroup
+
+func (a byPos) Len() int           { return len(a) }
+func (a byPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
+func (a byPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+// sortComments sorts the list of comment groups in source order.
+//
+func sortComments(list []*CommentGroup) {
+	// TODO(gri): Does it make sense to check for sorted-ness
+	//            first (because we know that sorted-ness is
+	//            very likely)?
+	if orderedList := byPos(list); !sort.IsSorted(orderedList) {
+		sort.Sort(orderedList)
+	}
+}
+
+// A CommentMap maps an AST node to a list of comment groups
+// associated with it. See NewCommentMap for a description of
+// the association.
+//
+type CommentMap map[Node][]*CommentGroup
+
+func (cmap CommentMap) addComment(n Node, c *CommentGroup) {
+	list := cmap[n]
+	if len(list) == 0 {
+		list = []*CommentGroup{c}
+	} else {
+		list = append(list, c)
+	}
+	cmap[n] = list
+}
+
+type byInterval []Node
+
+func (a byInterval) Len() int { return len(a) }
+func (a byInterval) Less(i, j int) bool {
+	pi, pj := a[i].Pos(), a[j].Pos()
+	return pi < pj || pi == pj && a[i].End() > a[j].End()
+}
+func (a byInterval) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+// nodeList returns the list of nodes of the AST n in source order.
+//
+func nodeList(n Node) []Node {
+	var list []Node
+	Inspect(n, func(n Node) bool {
+		// don't collect comments
+		switch n.(type) {
+		case nil, *CommentGroup, *Comment:
+			return false
+		}
+		list = append(list, n)
+		return true
+	})
+	// Note: The current implementation assumes that Inspect traverses the
+	//       AST in depth-first and thus _source_ order. If AST traversal
+	//       does not follow source order, the sorting call below will be
+	//       required.
+	// sort.Sort(byInterval(list))
+	return list
+}
+
+// A commentListReader helps iterating through a list of comment groups.
+//
+type commentListReader struct {
+	fset     *token.FileSet
+	list     []*CommentGroup
+	index    int
+	comment  *CommentGroup  // comment group at current index
+	pos, end token.Position // source interval of comment group at current index
+}
+
+func (r *commentListReader) eol() bool {
+	return r.index >= len(r.list)
+}
+
+func (r *commentListReader) next() {
+	if !r.eol() {
+		r.comment = r.list[r.index]
+		r.pos = r.fset.Position(r.comment.Pos())
+		r.end = r.fset.Position(r.comment.End())
+		r.index++
+	}
+}
+
+// A nodeStack keeps track of nested nodes.
+// A node lower on the stack lexically contains the nodes higher on the stack.
+//
+type nodeStack []Node
+
+// push pops all nodes that appear lexically before n
+// and then pushes n on the stack.
+//
+func (s *nodeStack) push(n Node) {
+	s.pop(n.Pos())
+	*s = append((*s), n)
+}
+
+// pop pops all nodes that appear lexically before pos
+// (i.e., whose lexical extent has ended before or at pos).
+// It returns the last node popped.
+//
+func (s *nodeStack) pop(pos token.Pos) (top Node) {
+	i := len(*s)
+	for i > 0 && (*s)[i-1].End() <= pos {
+		top = (*s)[i-1]
+		i--
+	}
+	*s = (*s)[0:i]
+	return top
+}
+
+// NewCommentMap creates a new comment map by associating comment groups
+// of the comments list with the nodes of the AST specified by node.
+//
+// A comment group g is associated with a node n if:
+//
+// - g starts on the same line as n ends
+// - g starts on the line immediately following n, and there is
+//   at least one empty line after g and before the next node
+// - g starts before n and is not associated to the node before n
+//   via the previous rules
+//
+// NewCommentMap tries to associate a comment group to the "largest"
+// node possible: For instance, if the comment is a line comment
+// trailing an assignment, the comment is associated with the entire
+// assignment rather than just the last operand in the assignment.
+//
+func NewCommentMap(fset *token.FileSet, node Node, comments []*CommentGroup) CommentMap {
+	if len(comments) == 0 {
+		return nil // no comments to map
+	}
+
+	cmap := make(CommentMap)
+
+	// set up comment reader r
+	tmp := make([]*CommentGroup, len(comments))
+	copy(tmp, comments) // don't change incomming comments
+	sortComments(tmp)
+	r := commentListReader{fset: fset, list: tmp} // !r.eol() because len(comments) > 0
+	r.next()
+
+	// create node list in lexical order
+	nodes := nodeList(node)
+	nodes = append(nodes, nil) // append sentinel
+
+	// set up iteration variables
+	var (
+		p     Node           // previous node
+		pend  token.Position // end of p
+		pg    Node           // previous node group (enclosing nodes of "importance")
+		pgend token.Position // end of pg
+		stack nodeStack      // stack of node groups
+	)
+
+	for _, q := range nodes {
+		var qpos token.Position
+		if q != nil {
+			qpos = fset.Position(q.Pos()) // current node position
+		} else {
+			// set fake sentinel position to infinity so that
+			// all comments get processed before the sentinel
+			const infinity = 1 << 30
+			qpos.Offset = infinity
+			qpos.Line = infinity
+		}
+
+		// process comments before current node
+		for r.end.Offset <= qpos.Offset {
+			// determine recent node group
+			if top := stack.pop(r.comment.Pos()); top != nil {
+				pg = top
+				pgend = fset.Position(pg.End())
+			}
+			// Try to associate a comment first with a node group
+			// (i.e., a node of "importance" such as a declaration);
+			// if that fails, try to associate it with the most recent
+			// node.
+			// TODO(gri) try to simplify the logic below
+			var assoc Node
+			switch {
+			case pg != nil &&
+				(pgend.Line == r.pos.Line ||
+					pgend.Line+1 == r.pos.Line && r.end.Line+1 < qpos.Line):
+				// 1) comment starts on same line as previous node group ends, or
+				// 2) comment starts on the line immediately after the
+				//    previous node group and there is an empty line before
+				//    the current node
+				// => associate comment with previous node group
+				assoc = pg
+			case p != nil &&
+				(pend.Line == r.pos.Line ||
+					pend.Line+1 == r.pos.Line && r.end.Line+1 < qpos.Line ||
+					q == nil):
+				// same rules apply as above for p rather than pg,
+				// but also associate with p if we are at the end (q == nil)
+				assoc = p
+			default:
+				// otherwise, associate comment with current node
+				if q == nil {
+					// we can only reach here if there was no p
+					// which would imply that there were no nodes
+					panic("internal error: no comments should be associated with sentinel")
+				}
+				assoc = q
+			}
+			cmap.addComment(assoc, r.comment)
+			if r.eol() {
+				return cmap
+			}
+			r.next()
+		}
+
+		// update previous node
+		p = q
+		pend = fset.Position(p.End())
+
+		// update previous node group if we see an "important" node
+		switch q.(type) {
+		case *File, *Field, Decl, Spec, Stmt:
+			stack.push(q)
+		}
+	}
+
+	return cmap
+}
+
+// Update replaces an old node in the comment map with the new node
+// and returns the new node. Comments that were associated with the
+// old node are associated with the new node.
+//
+func (cmap CommentMap) Update(old, new Node) Node {
+	if list := cmap[old]; len(list) > 0 {
+		delete(cmap, old)
+		cmap[new] = append(cmap[new], list...)
+	}
+	return new
+}
+
+// Filter returns a new comment map consisting of only those
+// entries of cmap for which a corresponding node exists in
+// the AST specified by node.
+//
+func (cmap CommentMap) Filter(node Node) CommentMap {
+	umap := make(CommentMap)
+	Inspect(node, func(n Node) bool {
+		if g := cmap[n]; len(g) > 0 {
+			umap[n] = g
+		}
+		return true
+	})
+	return umap
+}
+
+// Comments returns the list of comment groups in the comment map.
+// The result is sorted is source order.
+//
+func (cmap CommentMap) Comments() []*CommentGroup {
+	list := make([]*CommentGroup, 0, len(cmap))
+	for _, e := range cmap {
+		list = append(list, e...)
+	}
+	sortComments(list)
+	return list
+}
+
+func summary(list []*CommentGroup) string {
+	const maxLen = 40
+	var buf bytes.Buffer
+
+	// collect comments text
+loop:
+	for _, group := range list {
+		// Note: CommentGroup.Text() does too much work for what we
+		//       need and would only replace this innermost loop.
+		//       Just do it explicitly.
+		for _, comment := range group.List {
+			if buf.Len() >= maxLen {
+				break loop
+			}
+			buf.WriteString(comment.Text)
+		}
+	}
+
+	// truncate if too long
+	if buf.Len() > maxLen {
+		buf.Truncate(maxLen - 3)
+		buf.WriteString("...")
+	}
+
+	// replace any invisibles with blanks
+	bytes := buf.Bytes()
+	for i, b := range bytes {
+		switch b {
+		case '\t', '\n', '\r':
+			bytes[i] = ' '
+		}
+	}
+
+	return string(bytes)
+}
+
+func (cmap CommentMap) String() string {
+	var buf bytes.Buffer
+	fmt.Fprintln(&buf, "CommentMap {")
+	for node, comment := range cmap {
+		// print name of identifiers; print node type for other nodes
+		var s string
+		if ident, ok := node.(*Ident); ok {
+			s = ident.Name
+		} else {
+			s = fmt.Sprintf("%T", node)
+		}
+		fmt.Fprintf(&buf, "\t%p  %20s:  %s\n", node, s, summary(comment))
+	}
+	fmt.Fprintln(&buf, "}")
+	return buf.String()
+}
diff --git a/src/pkg/go/ast/commentmap_test.go b/src/pkg/go/ast/commentmap_test.go
new file mode 100644
index 0000000..e372eab
--- /dev/null
+++ b/src/pkg/go/ast/commentmap_test.go
@@ -0,0 +1,143 @@
+// 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.
+
+// To avoid a cyclic dependency with go/parser, this file is in a separate package.
+
+package ast_test
+
+import (
+	"bytes"
+	"fmt"
+	. "go/ast"
+	"go/parser"
+	"go/token"
+	"sort"
+	"testing"
+)
+
+const src = `
+// the very first comment
+
+// package p
+package p /* the name is p */
+
+// imports
+import (
+	"bytes"     // bytes
+	"fmt"       // fmt
+	"go/ast"
+	"go/parser"
+)
+
+// T
+type T struct {
+	a, b, c int // associated with a, b, c
+	// associated with x, y
+	x, y float64    // float values
+	z    complex128 // complex value
+}
+// also associated with T
+
+// x
+var x = 0 // x = 0
+// also associated with x
+
+// f1
+func f1() {
+	/* associated with s1 */
+	s1()
+	// also associated with s1
+	
+	// associated with s2
+	
+	// also associated with s2
+	s2() // line comment for s2
+}
+// associated with f1
+// also associated with f1
+
+// associated with f2
+
+// f2
+func f2() {
+}
+
+func f3() {
+	i := 1 /* 1 */ + 2 // addition
+	_ = i
+}
+
+// the very last comment
+`
+
+// res maps a key of the form "line number: node type"
+// to the associated comments' text.
+//
+var res = map[string]string{
+	" 5: *ast.File":       "the very first comment\npackage p\n",
+	" 5: *ast.Ident":      " the name is p\n",
+	" 8: *ast.GenDecl":    "imports\n",
+	" 9: *ast.ImportSpec": "bytes\n",
+	"10: *ast.ImportSpec": "fmt\n",
+	"16: *ast.GenDecl":    "T\nalso associated with T\n",
+	"17: *ast.Field":      "associated with a, b, c\n",
+	"19: *ast.Field":      "associated with x, y\nfloat values\n",
+	"20: *ast.Field":      "complex value\n",
+	"25: *ast.GenDecl":    "x\nx = 0\nalso associated with x\n",
+	"29: *ast.FuncDecl":   "f1\nassociated with f1\nalso associated with f1\n",
+	"31: *ast.ExprStmt":   " associated with s1\nalso associated with s1\n",
+	"37: *ast.ExprStmt":   "associated with s2\nalso associated with s2\nline comment for s2\n",
+	"45: *ast.FuncDecl":   "associated with f2\nf2\n",
+	"49: *ast.AssignStmt": "addition\n",
+	"49: *ast.BasicLit":   " 1\n",
+	"50: *ast.Ident":      "the very last comment\n",
+}
+
+func ctext(list []*CommentGroup) string {
+	var buf bytes.Buffer
+	for _, g := range list {
+		buf.WriteString(g.Text())
+	}
+	return buf.String()
+}
+
+func TestCommentMap(t *testing.T) {
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+	cmap := NewCommentMap(fset, f, f.Comments)
+
+	// very correct association of comments
+	for n, list := range cmap {
+		key := fmt.Sprintf("%2d: %T", fset.Position(n.Pos()).Line, n)
+		got := ctext(list)
+		want := res[key]
+		if got != want {
+			t.Errorf("%s: got %q; want %q", key, got, want)
+		}
+	}
+
+	// verify that no comments got lost
+	if n := len(cmap.Comments()); n != len(f.Comments) {
+		t.Errorf("got %d comment groups in map; want %d", n, len(f.Comments))
+	}
+
+	// support code to update test:
+	// set genMap to true to generate res map
+	const genMap = false
+	if genMap {
+		out := make([]string, 0, len(cmap))
+		for n, list := range cmap {
+			out = append(out, fmt.Sprintf("\t\"%2d: %T\":\t%q,", fset.Position(n.Pos()).Line, n, ctext(list)))
+		}
+		sort.Strings(out)
+		for _, s := range out {
+			fmt.Println(s)
+		}
+	}
+}
+
+// TODO(gri): add tests for Filter.
diff --git a/src/pkg/go/ast/filter.go b/src/pkg/go/ast/filter.go
index 4a89b89..4db5814 100644
--- a/src/pkg/go/ast/filter.go
+++ b/src/pkg/go/ast/filter.go
@@ -414,7 +414,7 @@ func MergePackageFiles(pkg *Package, mode MergeMode) *File {
 				if path := imp.Path.Value; !seen[path] {
 					// TODO: consider handling cases where:
 					// - 2 imports exist with the same import path but
-					//   have different local names (one should probably 
+					//   have different local names (one should probably
 					//   keep both of them)
 					// - 2 imports exist but only one has a comment
 					// - 2 imports exist and they both have (possibly
diff --git a/src/pkg/go/ast/import.go b/src/pkg/go/ast/import.go
index 2d4f69a..a68a484 100644
--- a/src/pkg/go/ast/import.go
+++ b/src/pkg/go/ast/import.go
@@ -20,7 +20,7 @@ func SortImports(fset *token.FileSet, f *File) {
 			break
 		}
 
-		if d.Lparen == token.NoPos {
+		if !d.Lparen.IsValid() {
 			// Not a block: sorted by default.
 			continue
 		}
diff --git a/src/pkg/go/ast/print.go b/src/pkg/go/ast/print.go
index 02cf9e0..4a1ce48 100644
--- a/src/pkg/go/ast/print.go
+++ b/src/pkg/go/ast/print.go
@@ -34,7 +34,8 @@ func NotNilFilter(_ string, v reflect.Value) bool {
 //
 // A non-nil FieldFilter f may be provided to control the output:
 // struct fields for which f(fieldname, fieldvalue) is true are
-// are printed; all others are filtered from the output.
+// are printed; all others are filtered from the output. Unexported
+// struct fields are never printed.
 //
 func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (err error) {
 	// setup printer
@@ -107,8 +108,10 @@ func (p *printer) Write(data []byte) (n int, err error) {
 		}
 		p.last = b
 	}
-	m, err = p.output.Write(data[n:])
-	n += m
+	if len(data) > n {
+		m, err = p.output.Write(data[n:])
+		n += m
+	}
 	return
 }
 
@@ -145,15 +148,18 @@ func (p *printer) print(x reflect.Value) {
 		p.print(x.Elem())
 
 	case reflect.Map:
-		p.printf("%s (len = %d) {\n", x.Type(), x.Len())
-		p.indent++
-		for _, key := range x.MapKeys() {
-			p.print(key)
-			p.printf(": ")
-			p.print(x.MapIndex(key))
+		p.printf("%s (len = %d) {", x.Type(), x.Len())
+		if x.Len() > 0 {
+			p.indent++
 			p.printf("\n")
+			for _, key := range x.MapKeys() {
+				p.print(key)
+				p.printf(": ")
+				p.print(x.MapIndex(key))
+				p.printf("\n")
+			}
+			p.indent--
 		}
-		p.indent--
 		p.printf("}")
 
 	case reflect.Ptr:
@@ -169,32 +175,57 @@ func (p *printer) print(x reflect.Value) {
 			p.print(x.Elem())
 		}
 
+	case reflect.Array:
+		p.printf("%s {", x.Type())
+		if x.Len() > 0 {
+			p.indent++
+			p.printf("\n")
+			for i, n := 0, x.Len(); i < n; i++ {
+				p.printf("%d: ", i)
+				p.print(x.Index(i))
+				p.printf("\n")
+			}
+			p.indent--
+		}
+		p.printf("}")
+
 	case reflect.Slice:
 		if s, ok := x.Interface().([]byte); ok {
 			p.printf("%#q", s)
 			return
 		}
-		p.printf("%s (len = %d) {\n", x.Type(), x.Len())
-		p.indent++
-		for i, n := 0, x.Len(); i < n; i++ {
-			p.printf("%d: ", i)
-			p.print(x.Index(i))
+		p.printf("%s (len = %d) {", x.Type(), x.Len())
+		if x.Len() > 0 {
+			p.indent++
 			p.printf("\n")
+			for i, n := 0, x.Len(); i < n; i++ {
+				p.printf("%d: ", i)
+				p.print(x.Index(i))
+				p.printf("\n")
+			}
+			p.indent--
 		}
-		p.indent--
 		p.printf("}")
 
 	case reflect.Struct:
-		p.printf("%s {\n", x.Type())
-		p.indent++
 		t := x.Type()
+		p.printf("%s {", t)
+		p.indent++
+		first := true
 		for i, n := 0, t.NumField(); i < n; i++ {
-			name := t.Field(i).Name
-			value := x.Field(i)
-			if p.filter == nil || p.filter(name, value) {
-				p.printf("%s: ", name)
-				p.print(value)
-				p.printf("\n")
+			// exclude non-exported fields because their
+			// values cannot be accessed via reflection
+			if name := t.Field(i).Name; IsExported(name) {
+				value := x.Field(i)
+				if p.filter == nil || p.filter(name, value) {
+					if first {
+						p.printf("\n")
+						first = false
+					}
+					p.printf("%s: ", name)
+					p.print(value)
+					p.printf("\n")
+				}
 			}
 		}
 		p.indent--
diff --git a/src/pkg/go/ast/print_test.go b/src/pkg/go/ast/print_test.go
index 71c028e..210f164 100644
--- a/src/pkg/go/ast/print_test.go
+++ b/src/pkg/go/ast/print_test.go
@@ -23,6 +23,7 @@ var tests = []struct {
 	{"foobar", "0  \"foobar\""},
 
 	// maps
+	{map[Expr]string{}, `0  map[ast.Expr]string (len = 0) {}`},
 	{map[string]int{"a": 1},
 		`0  map[string]int (len = 1) {
 		1  .  "a": 1
@@ -31,7 +32,21 @@ var tests = []struct {
 	// pointers
 	{new(int), "0  *0"},
 
+	// arrays
+	{[0]int{}, `0  [0]int {}`},
+	{[3]int{1, 2, 3},
+		`0  [3]int {
+		1  .  0: 1
+		2  .  1: 2
+		3  .  2: 3
+		4  }`},
+	{[...]int{42},
+		`0  [1]int {
+		1  .  0: 42
+		2  }`},
+
 	// slices
+	{[]int{}, `0  []int (len = 0) {}`},
 	{[]int{1, 2, 3},
 		`0  []int (len = 3) {
 		1  .  0: 1
@@ -40,6 +55,12 @@ var tests = []struct {
 		4  }`},
 
 	// structs
+	{struct{}{}, `0  struct {} {}`},
+	{struct{ x int }{007}, `0  struct { x int } {}`},
+	{struct{ X, y int }{42, 991},
+		`0  struct { X int; y int } {
+		1  .  X: 42
+		2  }`},
 	{struct{ X, Y int }{42, 991},
 		`0  struct { X int; Y int } {
 		1  .  X: 42
diff --git a/src/pkg/go/ast/resolve.go b/src/pkg/go/ast/resolve.go
index 908e61c..0406bfc 100644
--- a/src/pkg/go/ast/resolve.go
+++ b/src/pkg/go/ast/resolve.go
@@ -57,7 +57,7 @@ func resolve(scope *Scope, ident *Ident) bool {
 // An Importer must determine the canonical import path and
 // check the map to see if it is already present in the imports map.
 // If so, the Importer can return the map entry.  Otherwise, the
-// Importer should load the package data for the given path into 
+// Importer should load the package data for the given path into
 // a new *Object (pkg), record pkg in the imports map, and then
 // return pkg.
 type Importer func(imports map[string]*Object, path string) (pkg *Object, err error)
@@ -136,7 +136,7 @@ func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer,
 				for _, obj := range pkg.Data.(*Scope).Objects {
 					p.declare(fileScope, pkgScope, obj)
 				}
-			} else {
+			} else if name != "_" {
 				// declare imported package object in file scope
 				// (do not re-use pkg in the file scope but create
 				// a new object instead; the Decl field is different
diff --git a/src/pkg/go/ast/scope.go b/src/pkg/go/ast/scope.go
index 11e6b13..8df5b2c 100644
--- a/src/pkg/go/ast/scope.go
+++ b/src/pkg/go/ast/scope.go
@@ -64,18 +64,16 @@ func (s *Scope) String() string {
 // ----------------------------------------------------------------------------
 // Objects
 
-// TODO(gri) Consider replacing the Object struct with an interface
-//           and a corresponding set of object implementations.
-
 // An Object describes a named language entity such as a package,
 // constant, type, variable, function (incl. methods), or label.
 //
 // The Data fields contains object-specific data:
 //
-//	Kind    Data type    Data value
-//	Pkg	*Scope       package scope
-//	Con     int          iota for the respective declaration
-//	Con     != nil       constant value
+//	Kind    Data type         Data value
+//	Pkg	*types.Package    package scope
+//	Con     int               iota for the respective declaration
+//	Con     != nil            constant value
+//	Typ     *Scope            (used as method scope during type checking - transient)
 //
 type Object struct {
 	Kind ObjKind
@@ -137,7 +135,7 @@ func (obj *Object) Pos() token.Pos {
 	return token.NoPos
 }
 
-// ObKind describes what an object represents.
+// ObjKind describes what an object represents.
 type ObjKind int
 
 // The list of possible Object kinds.
diff --git a/src/pkg/go/ast/walk.go b/src/pkg/go/ast/walk.go
index 181cfd1..fef2503 100644
--- a/src/pkg/go/ast/walk.go
+++ b/src/pkg/go/ast/walk.go
@@ -158,7 +158,9 @@ func Walk(v Visitor, node Node) {
 		Walk(v, n.Fields)
 
 	case *FuncType:
-		Walk(v, n.Params)
+		if n.Params != nil {
+			Walk(v, n.Params)
+		}
 		if n.Results != nil {
 			Walk(v, n.Results)
 		}
@@ -344,9 +346,6 @@ func Walk(v Visitor, node Node) {
 		}
 		Walk(v, n.Name)
 		walkDeclList(v, n.Decls)
-		for _, g := range n.Comments {
-			Walk(v, g)
-		}
 		// don't walk n.Comments - they have been
 		// visited already through the individual
 		// nodes
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go
index 7a81d50..16c3da4 100644
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -33,6 +33,7 @@ type Context struct {
 	GOPATH      string   // Go path
 	CgoEnabled  bool     // whether cgo can be used
 	BuildTags   []string // additional tags to recognize in +build lines
+	InstallTag  string   // package install directory suffix
 	UseAllFiles bool     // use files regardless of +build lines, file names
 	Compiler    string   // compiler to assume when computing target paths
 
@@ -116,12 +117,27 @@ func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) {
 		return f(root, dir)
 	}
 
-	if p, err := filepath.EvalSymlinks(root); err == nil {
-		root = p
+	// Try using paths we received.
+	if rel, ok = hasSubdir(root, dir); ok {
+		return
 	}
-	if p, err := filepath.EvalSymlinks(dir); err == nil {
-		dir = p
+
+	// Try expanding symlinks and comparing
+	// expanded against unexpanded and
+	// expanded against expanded.
+	rootSym, _ := filepath.EvalSymlinks(root)
+	dirSym, _ := filepath.EvalSymlinks(dir)
+
+	if rel, ok = hasSubdir(rootSym, dir); ok {
+		return
+	}
+	if rel, ok = hasSubdir(root, dirSym); ok {
+		return
 	}
+	return hasSubdir(rootSym, dirSym)
+}
+
+func hasSubdir(root, dir string) (rel string, ok bool) {
 	const sep = string(filepath.Separator)
 	root = filepath.Clean(root)
 	if !strings.HasSuffix(root, sep) {
@@ -180,6 +196,21 @@ func (ctxt *Context) gopath() []string {
 			// Do not get confused by this common mistake.
 			continue
 		}
+		if strings.Contains(p, "~") && runtime.GOOS != "windows" {
+			// Path segments containing ~ on Unix are almost always
+			// users who have incorrectly quoted ~ while setting GOPATH,
+			// preventing it from expanding to $HOME.
+			// The situation is made more confusing by the fact that
+			// bash allows quoted ~ in $PATH (most shells do not).
+			// Do not get confused by this, and do not try to use the path.
+			// It does not exist, and printing errors about it confuses
+			// those users even more, because they think "sure ~ exists!".
+			// The go command diagnoses this situation and prints a
+			// useful error.
+			// On Windows, ~ is used in short names, such as c:\progra~1
+			// for c:\program files.
+			continue
+		}
 		all = append(all, p)
 	}
 	return all
@@ -213,10 +244,16 @@ var Default Context = defaultContext()
 var cgoEnabled = map[string]bool{
 	"darwin/386":    true,
 	"darwin/amd64":  true,
-	"linux/386":     true,
-	"linux/amd64":   true,
 	"freebsd/386":   true,
 	"freebsd/amd64": true,
+	"linux/386":     true,
+	"linux/amd64":   true,
+	"linux/arm":     true,
+	"netbsd/386":    true,
+	"netbsd/amd64":  true,
+	"netbsd/arm":    true,
+	"openbsd/386":   true,
+	"openbsd/amd64": true,
 	"windows/386":   true,
 	"windows/amd64": true,
 }
@@ -278,12 +315,15 @@ type Package struct {
 	PkgObj     string // installed .a file
 
 	// Source files
-	GoFiles   []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
-	CgoFiles  []string // .go source files that import "C"
-	CFiles    []string // .c source files
-	HFiles    []string // .h source files
-	SFiles    []string // .s source files
-	SysoFiles []string // .syso system object files to add to archive
+	GoFiles        []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+	CgoFiles       []string // .go source files that import "C"
+	IgnoredGoFiles []string // .go source files ignored for this build
+	CFiles         []string // .c source files
+	HFiles         []string // .h source files
+	SFiles         []string // .s source files
+	SysoFiles      []string // .syso system object files to add to archive
+	SwigFiles      []string // .swig files
+	SwigCXXFiles   []string // .swigcxx files
 
 	// Cgo directives
 	CgoPkgConfig []string // Cgo pkg-config directives
@@ -346,6 +386,9 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 	p := &Package{
 		ImportPath: path,
 	}
+	if path == "" {
+		return p, fmt.Errorf("import %q: invalid import path", path)
+	}
 
 	var pkga string
 	var pkgerr error
@@ -354,7 +397,11 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 		dir, elem := pathpkg.Split(p.ImportPath)
 		pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a"
 	case "gc":
-		pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + p.ImportPath + ".a"
+		tag := ""
+		if ctxt.InstallTag != "" {
+			tag = "_" + ctxt.InstallTag
+		}
+		pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + tag + "/" + p.ImportPath + ".a"
 	default:
 		// Save error for end of function.
 		pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)
@@ -410,6 +457,13 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 		if strings.HasPrefix(path, "/") {
 			return p, fmt.Errorf("import %q: cannot import absolute path", path)
 		}
+
+		// tried records the location of unsucsessful package lookups
+		var tried struct {
+			goroot string
+			gopath []string
+		}
+
 		// Determine directory from import path.
 		if ctxt.GOROOT != "" {
 			dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", path)
@@ -421,6 +475,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 				p.Root = ctxt.GOROOT
 				goto Found
 			}
+			tried.goroot = dir
 		}
 		for _, root := range ctxt.gopath() {
 			dir := ctxt.joinPath(root, "src", path)
@@ -431,8 +486,28 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 				p.Root = root
 				goto Found
 			}
+			tried.gopath = append(tried.gopath, dir)
+		}
+
+		// package was not found
+		var paths []string
+		if tried.goroot != "" {
+			paths = append(paths, fmt.Sprintf("\t%s (from $GOROOT)", tried.goroot))
+		} else {
+			paths = append(paths, "\t($GOROOT not set)")
 		}
-		return p, fmt.Errorf("import %q: cannot find package", path)
+		var i int
+		var format = "\t%s (from $GOPATH)"
+		for ; i < len(tried.gopath); i++ {
+			if i > 0 {
+				format = "\t%s"
+			}
+			paths = append(paths, fmt.Sprintf(format, tried.gopath[i]))
+		}
+		if i == 0 {
+			paths = append(paths, "\t($GOPATH not set)")
+		}
+		return p, fmt.Errorf("cannot find package %q in any of:\n%s", path, strings.Join(paths, "\n"))
 	}
 
 Found:
@@ -476,17 +551,22 @@ Found:
 			strings.HasPrefix(name, ".") {
 			continue
 		}
-		if !ctxt.UseAllFiles && !ctxt.goodOSArchFile(name) {
-			continue
-		}
 
 		i := strings.LastIndex(name, ".")
 		if i < 0 {
 			i = len(name)
 		}
 		ext := name[i:]
+
+		if !ctxt.UseAllFiles && !ctxt.goodOSArchFile(name) {
+			if ext == ".go" {
+				p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
+			}
+			continue
+		}
+
 		switch ext {
-		case ".go", ".c", ".s", ".h", ".S":
+		case ".go", ".c", ".s", ".h", ".S", ".swig", ".swigcxx":
 			// tentatively okay - read to make sure
 		case ".syso":
 			// binary objects to add to package archive
@@ -504,7 +584,13 @@ Found:
 		if err != nil {
 			return p, err
 		}
-		data, err := ioutil.ReadAll(f)
+
+		var data []byte
+		if strings.HasSuffix(filename, ".go") {
+			data, err = readImports(f, false)
+		} else {
+			data, err = readComments(f)
+		}
 		f.Close()
 		if err != nil {
 			return p, fmt.Errorf("read %s: %v", filename, err)
@@ -512,6 +598,9 @@ Found:
 
 		// Look for +build comments to accept or reject the file.
 		if !ctxt.UseAllFiles && !ctxt.shouldBuild(data) {
+			if ext == ".go" {
+				p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
+			}
 			continue
 		}
 
@@ -529,6 +618,12 @@ Found:
 		case ".S":
 			Sfiles = append(Sfiles, name)
 			continue
+		case ".swig":
+			p.SwigFiles = append(p.SwigFiles, name)
+			continue
+		case ".swigcxx":
+			p.SwigCXXFiles = append(p.SwigCXXFiles, name)
+			continue
 		}
 
 		pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments)
@@ -536,8 +631,9 @@ Found:
 			return p, err
 		}
 
-		pkg := string(pf.Name.Name)
+		pkg := pf.Name.Name
 		if pkg == "documentation" {
+			p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
 			continue
 		}
 
@@ -570,7 +666,7 @@ Found:
 				if !ok {
 					continue
 				}
-				quoted := string(spec.Path.Value)
+				quoted := spec.Path.Value
 				path, err := strconv.Unquote(quoted)
 				if err != nil {
 					log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted)
@@ -678,7 +774,7 @@ func (ctxt *Context) shouldBuild(content []byte) bool {
 		}
 		line = bytes.TrimSpace(line)
 		if len(line) == 0 { // Blank line
-			end = cap(content) - cap(line) // &line[0] - &content[0]
+			end = len(content) - len(p)
 			continue
 		}
 		if !bytes.HasPrefix(line, slashslash) { // Not comment line
@@ -872,6 +968,8 @@ func splitQuoted(s string) (r []string, err error) {
 //	$GOARCH
 //	cgo (if cgo is enabled)
 //	!cgo (if cgo is disabled)
+//	ctxt.Compiler
+//	!ctxt.Compiler
 //	tag (if tag is listed in ctxt.BuildTags)
 //	!tag (if tag is not listed in ctxt.BuildTags)
 //	a comma-separated list of any of these
@@ -903,7 +1001,7 @@ func (ctxt *Context) match(name string) bool {
 	if ctxt.CgoEnabled && name == "cgo" {
 		return true
 	}
-	if name == ctxt.GOOS || name == ctxt.GOARCH {
+	if name == ctxt.GOOS || name == ctxt.GOARCH || name == ctxt.Compiler {
 		return true
 	}
 
diff --git a/src/pkg/go/build/build_test.go b/src/pkg/go/build/build_test.go
index 560ebad..d8cf988 100644
--- a/src/pkg/go/build/build_test.go
+++ b/src/pkg/go/build/build_test.go
@@ -61,6 +61,19 @@ func TestDotSlashImport(t *testing.T) {
 	}
 }
 
+func TestEmptyImport(t *testing.T) {
+	p, err := Import("", Default.GOROOT, FindOnly)
+	if err == nil {
+		t.Fatal(`Import("") returned nil error.`)
+	}
+	if p == nil {
+		t.Fatal(`Import("") returned nil package.`)
+	}
+	if p.ImportPath != "" {
+		t.Fatalf("ImportPath=%q, want %q.", p.ImportPath, "")
+	}
+}
+
 func TestLocalDirectory(t *testing.T) {
 	cwd, err := os.Getwd()
 	if err != nil {
@@ -75,3 +88,32 @@ func TestLocalDirectory(t *testing.T) {
 		t.Fatalf("ImportPath=%q, want %q", p.ImportPath, "go/build")
 	}
 }
+
+func TestShouldBuild(t *testing.T) {
+	const file1 = "// +build tag1\n\n" +
+		"package main\n"
+
+	const file2 = "// +build cgo\n\n" +
+		"// This package implements parsing of tags like\n" +
+		"// +build tag1\n" +
+		"package build"
+
+	const file3 = "// Copyright The Go Authors.\n\n" +
+		"package build\n\n" +
+		"// shouldBuild checks tags given by lines of the form\n" +
+		"// +build tag\n" +
+		"func shouldBuild(content []byte)\n"
+
+	ctx := &Context{BuildTags: []string{"tag1"}}
+	if !ctx.shouldBuild([]byte(file1)) {
+		t.Errorf("should not build file1, expected the contrary")
+	}
+	if ctx.shouldBuild([]byte(file2)) {
+		t.Errorf("should build file2, expected the contrary")
+	}
+
+	ctx = &Context{BuildTags: nil}
+	if !ctx.shouldBuild([]byte(file3)) {
+		t.Errorf("should not build file3, expected the contrary")
+	}
+}
diff --git a/src/pkg/go/build/deps_test.go b/src/pkg/go/build/deps_test.go
index 4e9f32a..9a715ba 100644
--- a/src/pkg/go/build/deps_test.go
+++ b/src/pkg/go/build/deps_test.go
@@ -5,10 +5,9 @@
 // This file exercises the import parser but also checks that
 // some low-level packages do not have new dependencies added.
 
-package build_test
+package build
 
 import (
-	"go/build"
 	"sort"
 	"testing"
 )
@@ -24,13 +23,13 @@ import (
 // be used as dependencies by other rules.
 //
 // DO NOT CHANGE THIS DATA TO FIX BUILDS.
-// 
+//
 var pkgDeps = map[string][]string{
 	// L0 is the lowest level, core, nearly unavoidable packages.
 	"errors":      {},
 	"io":          {"errors", "sync"},
 	"runtime":     {"unsafe"},
-	"sync":        {"sync/atomic"},
+	"sync":        {"sync/atomic", "unsafe"},
 	"sync/atomic": {"unsafe"},
 	"unsafe":      {},
 
@@ -142,7 +141,7 @@ var pkgDeps = map[string][]string{
 	// Packages used by testing must be low-level (L2+fmt).
 	"regexp":         {"L2", "regexp/syntax"},
 	"regexp/syntax":  {"L2"},
-	"runtime/debug":  {"L2", "fmt", "io/ioutil", "os"},
+	"runtime/debug":  {"L2", "fmt", "io/ioutil", "os", "time"},
 	"runtime/pprof":  {"L2", "fmt", "text/tabwriter"},
 	"text/tabwriter": {"L2"},
 
@@ -177,7 +176,7 @@ var pkgDeps = map[string][]string{
 	},
 
 	// One of a kind.
-	"archive/tar":         {"L4", "OS"},
+	"archive/tar":         {"L4", "OS", "syscall"},
 	"archive/zip":         {"L4", "OS", "compress/flate"},
 	"compress/bzip2":      {"L4"},
 	"compress/flate":      {"L4"},
@@ -249,18 +248,23 @@ var pkgDeps = map[string][]string{
 	"net/mail":      {"L4", "NET", "OS"},
 	"net/textproto": {"L4", "OS", "net"},
 
+	// Support libraries for crypto that aren't L2.
+	"CRYPTO-SUPPORT": {
+		"crypto/subtle",
+	},
+
 	// Core crypto.
 	"crypto/aes":    {"L3"},
 	"crypto/des":    {"L3"},
-	"crypto/hmac":   {"L3"},
+	"crypto/hmac":   {"L3", "CRYPTO-SUPPORT"},
 	"crypto/md5":    {"L3"},
 	"crypto/rc4":    {"L3"},
 	"crypto/sha1":   {"L3"},
 	"crypto/sha256": {"L3"},
 	"crypto/sha512": {"L3"},
-	"crypto/subtle": {"L3"},
 
 	"CRYPTO": {
+		"CRYPTO-SUPPORT",
 		"crypto/aes",
 		"crypto/des",
 		"crypto/hmac",
@@ -269,7 +273,6 @@ var pkgDeps = map[string][]string{
 		"crypto/sha1",
 		"crypto/sha256",
 		"crypto/sha512",
-		"crypto/subtle",
 	},
 
 	// Random byte, number generation.
@@ -300,7 +303,10 @@ var pkgDeps = map[string][]string{
 		"L4", "CRYPTO-MATH", "CGO", "OS",
 		"crypto/x509", "encoding/pem", "net", "syscall",
 	},
-	"crypto/x509":      {"L4", "CRYPTO-MATH", "OS", "CGO", "crypto/x509/pkix", "encoding/pem", "syscall"},
+	"crypto/x509": {
+		"L4", "CRYPTO-MATH", "OS", "CGO",
+		"crypto/x509/pkix", "encoding/pem", "encoding/hex", "net", "syscall",
+	},
 	"crypto/x509/pkix": {"L4", "CRYPTO-MATH"},
 
 	// Simple net+crypto-aware packages.
@@ -375,7 +381,7 @@ func TestDependencies(t *testing.T) {
 	}
 	sort.Strings(all)
 
-	ctxt := build.Default
+	ctxt := Default
 	test := func(mustImport bool) {
 		for _, pkg := range all {
 			if isMacro(pkg) {
diff --git a/src/pkg/go/build/doc.go b/src/pkg/go/build/doc.go
index 67c26ac..c562d05 100644
--- a/src/pkg/go/build/doc.go
+++ b/src/pkg/go/build/doc.go
@@ -23,12 +23,12 @@
 // As in the Go tree, each target operating system and
 // architecture pair has its own subdirectory of pkg
 // (pkg/GOOS_GOARCH).
-// 
+//
 // If DIR is a directory listed in the Go path, a package with
 // source in DIR/src/foo/bar can be imported as "foo/bar" and
 // has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a"
 // (or, for gccgo, "DIR/pkg/gccgo/foo/libbar.a").
-// 
+//
 // The bin/ directory holds compiled commands.
 // Each command is named for its source directory, but only
 // using the final element, not the entire path.  That is, the
@@ -36,11 +36,11 @@
 // DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
 // so that you can add DIR/bin to your PATH to get at the
 // installed commands.
-// 
+//
 // Here's an example directory layout:
-// 
+//
 //	GOPATH=/home/user/gocode
-// 
+//
 //	/home/user/gocode/
 //	    src/
 //	        foo/
@@ -60,9 +60,12 @@
 // A build constraint is a line comment beginning with the directive +build
 // that lists the conditions under which a file should be included in the package.
 // Constraints may appear in any kind of source file (not just Go), but
-// they must be appear near the top of the file, preceded
+// they must appear near the top of the file, preceded
 // only by blank lines and other line comments.
 //
+// To distinguish build constraints from package documentation, a series of
+// build constraints must be followed by a blank line.
+//
 // A build constraint is evaluated as the OR of space-separated options;
 // each option evaluates as the AND of its comma-separated terms;
 // and each term is an alphanumeric word or, preceded by !, its negation.
@@ -74,10 +77,21 @@
 //
 //	(linux AND 386) OR (darwin AND (NOT cgo))
 //
+// A file may have multiple build constraints. The overall constraint is the AND
+// of the individual constraints. That is, the build constraints:
+//
+//	// +build linux darwin
+//	// +build 386
+//
+// corresponds to the boolean formula:
+//
+//	(linux OR darwin) AND 386
+//
 // During a particular build, the following words are satisfied:
 //
 //	- the target operating system, as spelled by runtime.GOOS
 //	- the target architecture, as spelled by runtime.GOARCH
+//	- the compiler being used, currently either "gc" or "gccgo"
 //	- "cgo", if ctxt.CgoEnabled is true
 //	- any additional words listed in ctxt.BuildTags
 //
@@ -100,7 +114,7 @@
 // default functionality for other systems, which in this case would
 // carry the constraint:
 //
-//	// +build !linux !darwin !cgo
+//	// +build !linux,!darwin !cgo
 //
 // Naming a file dns_windows.go will cause it to be included only when
 // building the package for Windows; similarly, math_386.s will be included
diff --git a/src/pkg/go/build/read.go b/src/pkg/go/build/read.go
new file mode 100644
index 0000000..c8079df
--- /dev/null
+++ b/src/pkg/go/build/read.go
@@ -0,0 +1,238 @@
+// 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 build
+
+import (
+	"bufio"
+	"errors"
+	"io"
+)
+
+type importReader struct {
+	b    *bufio.Reader
+	buf  []byte
+	peek byte
+	err  error
+	eof  bool
+	nerr int
+}
+
+func isIdent(c byte) bool {
+	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= 0x80
+}
+
+var (
+	errSyntax = errors.New("syntax error")
+	errNUL    = errors.New("unexpected NUL in input")
+)
+
+// syntaxError records a syntax error, but only if an I/O error has not already been recorded.
+func (r *importReader) syntaxError() {
+	if r.err == nil {
+		r.err = errSyntax
+	}
+}
+
+// readByte reads the next byte from the input, saves it in buf, and returns it.
+// If an error occurs, readByte records the error in r.err and returns 0.
+func (r *importReader) readByte() byte {
+	c, err := r.b.ReadByte()
+	if err == nil {
+		r.buf = append(r.buf, c)
+		if c == 0 {
+			err = errNUL
+		}
+	}
+	if err != nil {
+		if err == io.EOF {
+			r.eof = true
+		} else if r.err == nil {
+			r.err = err
+		}
+		c = 0
+	}
+	return c
+}
+
+// peekByte returns the next byte from the input reader but does not advance beyond it.
+// If skipSpace is set, peekByte skips leading spaces and comments.
+func (r *importReader) peekByte(skipSpace bool) byte {
+	if r.err != nil {
+		if r.nerr++; r.nerr > 10000 {
+			panic("go/build: import reader looping")
+		}
+		return 0
+	}
+
+	// Use r.peek as first input byte.
+	// Don't just return r.peek here: it might have been left by peekByte(false)
+	// and this might be peekByte(true).
+	c := r.peek
+	if c == 0 {
+		c = r.readByte()
+	}
+	for r.err == nil && !r.eof {
+		if skipSpace {
+			// For the purposes of this reader, semicolons are never necessary to
+			// understand the input and are treated as spaces.
+			switch c {
+			case ' ', '\f', '\t', '\r', '\n', ';':
+				c = r.readByte()
+				continue
+
+			case '/':
+				c = r.readByte()
+				if c == '/' {
+					for c != '\n' && r.err == nil && !r.eof {
+						c = r.readByte()
+					}
+				} else if c == '*' {
+					var c1 byte
+					for (c != '*' || c1 != '/') && r.err == nil {
+						if r.eof {
+							r.syntaxError()
+						}
+						c, c1 = c1, r.readByte()
+					}
+				} else {
+					r.syntaxError()
+				}
+				c = r.readByte()
+				continue
+			}
+		}
+		break
+	}
+	r.peek = c
+	return r.peek
+}
+
+// nextByte is like peekByte but advances beyond the returned byte.
+func (r *importReader) nextByte(skipSpace bool) byte {
+	c := r.peekByte(skipSpace)
+	r.peek = 0
+	return c
+}
+
+// readKeyword reads the given keyword from the input.
+// If the keyword is not present, readKeyword records a syntax error.
+func (r *importReader) readKeyword(kw string) {
+	r.peekByte(true)
+	for i := 0; i < len(kw); i++ {
+		if r.nextByte(false) != kw[i] {
+			r.syntaxError()
+			return
+		}
+	}
+	if isIdent(r.peekByte(false)) {
+		r.syntaxError()
+	}
+}
+
+// readIdent reads an identifier from the input.
+// If an identifier is not present, readIdent records a syntax error.
+func (r *importReader) readIdent() {
+	c := r.peekByte(true)
+	if !isIdent(c) {
+		r.syntaxError()
+		return
+	}
+	for isIdent(r.peekByte(false)) {
+		r.peek = 0
+	}
+}
+
+// readString reads a quoted string literal from the input.
+// If an identifier is not present, readString records a syntax error.
+func (r *importReader) readString() {
+	switch r.nextByte(true) {
+	case '`':
+		for r.err == nil {
+			if r.nextByte(false) == '`' {
+				break
+			}
+			if r.eof {
+				r.syntaxError()
+			}
+		}
+	case '"':
+		for r.err == nil {
+			c := r.nextByte(false)
+			if c == '"' {
+				break
+			}
+			if r.eof || c == '\n' {
+				r.syntaxError()
+			}
+			if c == '\\' {
+				r.nextByte(false)
+			}
+		}
+	default:
+		r.syntaxError()
+	}
+}
+
+// readImport reads an import clause - optional identifier followed by quoted string -
+// from the input.
+func (r *importReader) readImport() {
+	c := r.peekByte(true)
+	if c == '.' {
+		r.peek = 0
+	} else if isIdent(c) {
+		r.readIdent()
+	}
+	r.readString()
+}
+
+// readComments is like ioutil.ReadAll, except that it only reads the leading
+// block of comments in the file.
+func readComments(f io.Reader) ([]byte, error) {
+	r := &importReader{b: bufio.NewReader(f)}
+	r.peekByte(true)
+	if r.err == nil && !r.eof {
+		// Didn't reach EOF, so must have found a non-space byte. Remove it.
+		r.buf = r.buf[:len(r.buf)-1]
+	}
+	return r.buf, r.err
+}
+
+// readImports is like ioutil.ReadAll, except that it expects a Go file as input
+// and stops reading the input once the imports have completed.
+func readImports(f io.Reader, reportSyntaxError bool) ([]byte, error) {
+	r := &importReader{b: bufio.NewReader(f)}
+
+	r.readKeyword("package")
+	r.readIdent()
+	for r.peekByte(true) == 'i' {
+		r.readKeyword("import")
+		if r.peekByte(true) == '(' {
+			r.nextByte(false)
+			for r.peekByte(true) != ')' && r.err == nil {
+				r.readImport()
+			}
+			r.nextByte(false)
+		} else {
+			r.readImport()
+		}
+	}
+
+	// If we stopped successfully before EOF, we read a byte that told us we were done.
+	// Return all but that last byte, which would cause a syntax error if we let it through.
+	if r.err == nil && !r.eof {
+		return r.buf[:len(r.buf)-1], nil
+	}
+
+	// If we stopped for a syntax error, consume the whole file so that
+	// we are sure we don't change the errors that go/parser returns.
+	if r.err == errSyntax && !reportSyntaxError {
+		r.err = nil
+		for r.err == nil && !r.eof {
+			r.readByte()
+		}
+	}
+
+	return r.buf, r.err
+}
diff --git a/src/pkg/go/build/read_test.go b/src/pkg/go/build/read_test.go
new file mode 100644
index 0000000..2dcc120
--- /dev/null
+++ b/src/pkg/go/build/read_test.go
@@ -0,0 +1,226 @@
+// 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 build
+
+import (
+	"io"
+	"strings"
+	"testing"
+)
+
+const quote = "`"
+
+type readTest struct {
+	// Test input contains ℙ where readImports should stop.
+	in  string
+	err string
+}
+
+var readImportsTests = []readTest{
+	{
+		`package p`,
+		"",
+	},
+	{
+		`package p; import "x"`,
+		"",
+	},
+	{
+		`package p; import . "x"`,
+		"",
+	},
+	{
+		`package p; import "x";ℙvar x = 1`,
+		"",
+	},
+	{
+		`package p
+		
+		// comment
+		
+		import "x"
+		import _ "x"
+		import a "x"
+		
+		/* comment */
+		
+		import (
+			"x" /* comment */
+			_ "x"
+			a "x" // comment
+			` + quote + `x` + quote + `
+			_ /*comment*/ ` + quote + `x` + quote + `
+			a ` + quote + `x` + quote + `
+		)
+		import (
+		)
+		import ()
+		import()import()import()
+		import();import();import()
+		
+		ℙvar x = 1
+		`,
+		"",
+	},
+}
+
+var readCommentsTests = []readTest{
+	{
+		`ℙpackage p`,
+		"",
+	},
+	{
+		`ℙpackage p; import "x"`,
+		"",
+	},
+	{
+		`ℙpackage p; import . "x"`,
+		"",
+	},
+	{
+		`// foo
+
+		/* bar */
+
+		/* quux */ // baz
+		
+		/*/ zot */
+
+		// asdf
+		ℙHello, world`,
+		"",
+	},
+}
+
+func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) {
+	for i, tt := range tests {
+		var in, testOut string
+		j := strings.Index(tt.in, "ℙ")
+		if j < 0 {
+			in = tt.in
+			testOut = tt.in
+		} else {
+			in = tt.in[:j] + tt.in[j+len("ℙ"):]
+			testOut = tt.in[:j]
+		}
+		r := strings.NewReader(in)
+		buf, err := read(r)
+		if err != nil {
+			if tt.err == "" {
+				t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf))
+				continue
+			}
+			if !strings.Contains(err.Error(), tt.err) {
+				t.Errorf("#%d: err=%q, expected %q", i, err, tt.err)
+				continue
+			}
+			continue
+		}
+		if err == nil && tt.err != "" {
+			t.Errorf("#%d: success, expected %q", i, tt.err)
+			continue
+		}
+
+		out := string(buf)
+		if out != testOut {
+			t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut)
+		}
+	}
+}
+
+func TestReadImports(t *testing.T) {
+	testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return readImports(r, true) })
+}
+
+func TestReadComments(t *testing.T) {
+	testRead(t, readCommentsTests, readComments)
+}
+
+var readFailuresTests = []readTest{
+	{
+		`package`,
+		"syntax error",
+	},
+	{
+		"package p\n\x00\nimport `math`\n",
+		"unexpected NUL in input",
+	},
+	{
+		`package p; import`,
+		"syntax error",
+	},
+	{
+		`package p; import "`,
+		"syntax error",
+	},
+	{
+		"package p; import ` \n\n",
+		"syntax error",
+	},
+	{
+		`package p; import "x`,
+		"syntax error",
+	},
+	{
+		`package p; import _`,
+		"syntax error",
+	},
+	{
+		`package p; import _ "`,
+		"syntax error",
+	},
+	{
+		`package p; import _ "x`,
+		"syntax error",
+	},
+	{
+		`package p; import .`,
+		"syntax error",
+	},
+	{
+		`package p; import . "`,
+		"syntax error",
+	},
+	{
+		`package p; import . "x`,
+		"syntax error",
+	},
+	{
+		`package p; import (`,
+		"syntax error",
+	},
+	{
+		`package p; import ("`,
+		"syntax error",
+	},
+	{
+		`package p; import ("x`,
+		"syntax error",
+	},
+	{
+		`package p; import ("x"`,
+		"syntax error",
+	},
+}
+
+func TestReadFailures(t *testing.T) {
+	// Errors should be reported (true arg to readImports).
+	testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return readImports(r, true) })
+}
+
+func TestReadFailuresIgnored(t *testing.T) {
+	// Syntax errors should not be reported (false arg to readImports).
+	// Instead, entire file should be the output and no error.
+	// Convert tests not to return syntax errors.
+	tests := make([]readTest, len(readFailuresTests))
+	copy(tests, readFailuresTests)
+	for i := range tests {
+		tt := &tests[i]
+		if !strings.Contains(tt.err, "NUL") {
+			tt.err = ""
+		}
+	}
+	testRead(t, tests, func(r io.Reader) ([]byte, error) { return readImports(r, false) })
+}
diff --git a/src/pkg/go/doc/comment.go b/src/pkg/go/doc/comment.go
index 6f0edd4..c4b7e6a 100644
--- a/src/pkg/go/doc/comment.go
+++ b/src/pkg/go/doc/comment.go
@@ -174,7 +174,7 @@ func unindent(block []string) {
 }
 
 // heading returns the trimmed line if it passes as a section heading;
-// otherwise it returns the empty string. 
+// otherwise it returns the empty string.
 func heading(line string) string {
 	line = strings.TrimSpace(line)
 	if len(line) == 0 {
@@ -229,7 +229,8 @@ type block struct {
 var nonAlphaNumRx = regexp.MustCompile(`[^a-zA-Z0-9]`)
 
 func anchorID(line string) string {
-	return nonAlphaNumRx.ReplaceAllString(line, "_")
+	// Add a "hdr-" prefix to avoid conflicting with IDs used for package symbols.
+	return "hdr-" + nonAlphaNumRx.ReplaceAllString(line, "_")
 }
 
 // ToHTML converts comment text to formatted HTML.
diff --git a/src/pkg/go/doc/doc.go b/src/pkg/go/doc/doc.go
index 9c60631..65b1b83 100644
--- a/src/pkg/go/doc/doc.go
+++ b/src/pkg/go/doc/doc.go
@@ -17,7 +17,16 @@ type Package struct {
 	ImportPath string
 	Imports    []string
 	Filenames  []string
-	Bugs       []string
+	// DEPRECATED. For backward compatibility Bugs is still populated,
+	// but all new code should use Notes instead.
+	Bugs []string
+
+	// Notes such as TODO(userid): or SECURITY(userid):
+	// along the lines of BUG(userid). Any marker with 2 or more upper
+	// case [A-Z] letters is recognised.
+	// BUG is explicitly not included in these notes but will
+	// be in a subsequent change when the Bugs field above is removed.
+	Notes map[string][]string
 
 	// declarations
 	Consts []*Value
@@ -89,6 +98,7 @@ func New(pkg *ast.Package, importPath string, mode Mode) *Package {
 		Imports:    sortedKeys(r.imports),
 		Filenames:  r.filenames,
 		Bugs:       r.bugs,
+		Notes:      r.notes,
 		Consts:     sortedValues(r.values, token.CONST),
 		Types:      sortedTypes(r.types, mode&AllMethods != 0),
 		Vars:       sortedValues(r.values, token.VAR),
diff --git a/src/pkg/go/doc/doc_test.go b/src/pkg/go/doc/doc_test.go
index f957ede..8043038 100644
--- a/src/pkg/go/doc/doc_test.go
+++ b/src/pkg/go/doc/doc_test.go
@@ -123,7 +123,7 @@ func test(t *testing.T, mode Mode) {
 		}
 
 		// compare
-		if bytes.Compare(got, want) != 0 {
+		if !bytes.Equal(got, want) {
 			t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want)
 		}
 	}
diff --git a/src/pkg/go/doc/example.go b/src/pkg/go/doc/example.go
index a7e0e25..693ad5b 100644
--- a/src/pkg/go/doc/example.go
+++ b/src/pkg/go/doc/example.go
@@ -9,21 +9,29 @@ package doc
 import (
 	"go/ast"
 	"go/token"
+	"path"
 	"regexp"
 	"sort"
+	"strconv"
 	"strings"
 	"unicode"
 	"unicode/utf8"
 )
 
+// An Example represents an example function found in a source files.
 type Example struct {
-	Name     string // name of the item being exemplified
-	Doc      string // example function doc string
-	Code     ast.Node
-	Comments []*ast.CommentGroup
-	Output   string // expected output
+	Name        string // name of the item being exemplified
+	Doc         string // example function doc string
+	Code        ast.Node
+	Play        *ast.File // a whole program version of the example
+	Comments    []*ast.CommentGroup
+	Output      string // expected output
+	EmptyOutput bool   // expect empty output
+	Order       int    // original source code order
 }
 
+// Examples returns the examples found in the files, sorted by Name field.
+// The Order fields record the order in which the examples were encountered.
 func Examples(files ...*ast.File) []*Example {
 	var list []*Example
 	for _, file := range files {
@@ -52,12 +60,16 @@ func Examples(files ...*ast.File) []*Example {
 			if f.Doc != nil {
 				doc = f.Doc.Text()
 			}
+			output, hasOutput := exampleOutput(f.Body, file.Comments)
 			flist = append(flist, &Example{
-				Name:     name[len("Example"):],
-				Doc:      doc,
-				Code:     f.Body,
-				Comments: file.Comments,
-				Output:   exampleOutput(f, file.Comments),
+				Name:        name[len("Example"):],
+				Doc:         doc,
+				Code:        f.Body,
+				Play:        playExample(file, f.Body),
+				Comments:    file.Comments,
+				Output:      output,
+				EmptyOutput: output == "" && hasOutput,
+				Order:       len(flist),
 			})
 		}
 		if !hasTests && numDecl > 1 && len(flist) == 1 {
@@ -65,6 +77,7 @@ func Examples(files ...*ast.File) []*Example {
 			// other top-level declarations, and no tests or
 			// benchmarks, use the whole file as the example.
 			flist[0].Code = file
+			flist[0].Play = playExampleFile(file)
 		}
 		list = append(list, flist...)
 	}
@@ -74,26 +87,22 @@ func Examples(files ...*ast.File) []*Example {
 
 var outputPrefix = regexp.MustCompile(`(?i)^[[:space:]]*output:`)
 
-func exampleOutput(fun *ast.FuncDecl, comments []*ast.CommentGroup) string {
-	// find the last comment in the function
-	var last *ast.CommentGroup
-	for _, cg := range comments {
-		if cg.Pos() < fun.Pos() {
-			continue
-		}
-		if cg.End() > fun.End() {
-			break
-		}
-		last = cg
-	}
-	if last != nil {
+// Extracts the expected output and whether there was a valid output comment
+func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) (output string, ok bool) {
+	if _, last := lastComment(b, comments); last != nil {
 		// test that it begins with the correct prefix
 		text := last.Text()
 		if loc := outputPrefix.FindStringIndex(text); loc != nil {
-			return strings.TrimSpace(text[loc[1]:])
+			text = text[loc[1]:]
+			// Strip zero or more spaces followed by \n or a single space.
+			text = strings.TrimLeft(text, " ")
+			if len(text) > 0 && text[0] == '\n' {
+				text = text[1:]
+			}
+			return text, true
 		}
 	}
-	return "" // no suitable comment found
+	return "", false // no suitable comment found
 }
 
 // isTest tells whether name looks like a test, example, or benchmark.
@@ -115,3 +124,214 @@ type exampleByName []*Example
 func (s exampleByName) Len() int           { return len(s) }
 func (s exampleByName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
 func (s exampleByName) Less(i, j int) bool { return s[i].Name < s[j].Name }
+
+// playExample synthesizes a new *ast.File based on the provided
+// file with the provided function body as the body of main.
+func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
+	if !strings.HasSuffix(file.Name.Name, "_test") {
+		// We don't support examples that are part of the
+		// greater package (yet).
+		return nil
+	}
+
+	// Find top-level declarations in the file.
+	topDecls := make(map[*ast.Object]bool)
+	for _, decl := range file.Decls {
+		switch d := decl.(type) {
+		case *ast.FuncDecl:
+			topDecls[d.Name.Obj] = true
+		case *ast.GenDecl:
+			for _, spec := range d.Specs {
+				switch s := spec.(type) {
+				case *ast.TypeSpec:
+					topDecls[s.Name.Obj] = true
+				case *ast.ValueSpec:
+					for _, id := range s.Names {
+						topDecls[id.Obj] = true
+					}
+				}
+			}
+		}
+	}
+
+	// Find unresolved identifiers and uses of top-level declarations.
+	unresolved := make(map[string]bool)
+	usesTopDecl := false
+	var inspectFunc func(ast.Node) bool
+	inspectFunc = func(n ast.Node) bool {
+		// For selector expressions, only inspect the left hand side.
+		// (For an expression like fmt.Println, only add "fmt" to the
+		// set of unresolved names, not "Println".)
+		if e, ok := n.(*ast.SelectorExpr); ok {
+			ast.Inspect(e.X, inspectFunc)
+			return false
+		}
+		if id, ok := n.(*ast.Ident); ok {
+			if id.Obj == nil {
+				unresolved[id.Name] = true
+			} else if topDecls[id.Obj] {
+				usesTopDecl = true
+			}
+		}
+		return true
+	}
+	ast.Inspect(body, inspectFunc)
+	if usesTopDecl {
+		// We don't support examples that are not self-contained (yet).
+		return nil
+	}
+
+	// Remove predeclared identifiers from unresolved list.
+	for n := range unresolved {
+		if predeclaredTypes[n] || predeclaredConstants[n] || predeclaredFuncs[n] {
+			delete(unresolved, n)
+		}
+	}
+
+	// Use unresolved identifiers to determine the imports used by this
+	// example. The heuristic assumes package names match base import
+	// paths for imports w/o renames (should be good enough most of the time).
+	namedImports := make(map[string]string) // [name]path
+	var blankImports []ast.Spec             // _ imports
+	for _, s := range file.Imports {
+		p, err := strconv.Unquote(s.Path.Value)
+		if err != nil {
+			continue
+		}
+		n := path.Base(p)
+		if s.Name != nil {
+			n = s.Name.Name
+			switch n {
+			case "_":
+				blankImports = append(blankImports, s)
+				continue
+			case ".":
+				// We can't resolve dot imports (yet).
+				return nil
+			}
+		}
+		if unresolved[n] {
+			namedImports[n] = p
+			delete(unresolved, n)
+		}
+	}
+
+	// If there are other unresolved identifiers, give up because this
+	// synthesized file is not going to build.
+	if len(unresolved) > 0 {
+		return nil
+	}
+
+	// Include documentation belonging to blank imports.
+	var comments []*ast.CommentGroup
+	for _, s := range blankImports {
+		if c := s.(*ast.ImportSpec).Doc; c != nil {
+			comments = append(comments, c)
+		}
+	}
+
+	// Include comments that are inside the function body.
+	for _, c := range file.Comments {
+		if body.Pos() <= c.Pos() && c.End() <= body.End() {
+			comments = append(comments, c)
+		}
+	}
+
+	// Strip "Output:" commment and adjust body end position.
+	body, comments = stripOutputComment(body, comments)
+
+	// Synthesize import declaration.
+	importDecl := &ast.GenDecl{
+		Tok:    token.IMPORT,
+		Lparen: 1, // Need non-zero Lparen and Rparen so that printer
+		Rparen: 1, // treats this as a factored import.
+	}
+	for n, p := range namedImports {
+		s := &ast.ImportSpec{Path: &ast.BasicLit{Value: strconv.Quote(p)}}
+		if path.Base(p) != n {
+			s.Name = ast.NewIdent(n)
+		}
+		importDecl.Specs = append(importDecl.Specs, s)
+	}
+	importDecl.Specs = append(importDecl.Specs, blankImports...)
+
+	// Synthesize main function.
+	funcDecl := &ast.FuncDecl{
+		Name: ast.NewIdent("main"),
+		Type: &ast.FuncType{},
+		Body: body,
+	}
+
+	// Synthesize file.
+	return &ast.File{
+		Name:     ast.NewIdent("main"),
+		Decls:    []ast.Decl{importDecl, funcDecl},
+		Comments: comments,
+	}
+}
+
+// playExampleFile takes a whole file example and synthesizes a new *ast.File
+// such that the example is function main in package main.
+func playExampleFile(file *ast.File) *ast.File {
+	// Strip copyright comment if present.
+	comments := file.Comments
+	if len(comments) > 0 && strings.HasPrefix(comments[0].Text(), "Copyright") {
+		comments = comments[1:]
+	}
+
+	// Copy declaration slice, rewriting the ExampleX function to main.
+	var decls []ast.Decl
+	for _, d := range file.Decls {
+		if f, ok := d.(*ast.FuncDecl); ok && isTest(f.Name.Name, "Example") {
+			// Copy the FuncDecl, as it may be used elsewhere.
+			newF := *f
+			newF.Name = ast.NewIdent("main")
+			newF.Body, comments = stripOutputComment(f.Body, comments)
+			d = &newF
+		}
+		decls = append(decls, d)
+	}
+
+	// Copy the File, as it may be used elsewhere.
+	f := *file
+	f.Name = ast.NewIdent("main")
+	f.Decls = decls
+	f.Comments = comments
+	return &f
+}
+
+// stripOutputComment finds and removes an "Output:" commment from body
+// and comments, and adjusts the body block's end position.
+func stripOutputComment(body *ast.BlockStmt, comments []*ast.CommentGroup) (*ast.BlockStmt, []*ast.CommentGroup) {
+	// Do nothing if no "Output:" comment found.
+	i, last := lastComment(body, comments)
+	if last == nil || !outputPrefix.MatchString(last.Text()) {
+		return body, comments
+	}
+
+	// Copy body and comments, as the originals may be used elsewhere.
+	newBody := &ast.BlockStmt{
+		Lbrace: body.Lbrace,
+		List:   body.List,
+		Rbrace: last.Pos(),
+	}
+	newComments := make([]*ast.CommentGroup, len(comments)-1)
+	copy(newComments, comments[:i])
+	copy(newComments[i:], comments[i+1:])
+	return newBody, newComments
+}
+
+// lastComment returns the last comment inside the provided block.
+func lastComment(b *ast.BlockStmt, c []*ast.CommentGroup) (i int, last *ast.CommentGroup) {
+	pos, end := b.Pos(), b.End()
+	for j, cg := range c {
+		if cg.Pos() < pos {
+			continue
+		}
+		if cg.End() > end {
+			break
+		}
+		i, last = j, cg
+	}
+	return
+}
diff --git a/src/pkg/go/doc/example_test.go b/src/pkg/go/doc/example_test.go
new file mode 100644
index 0000000..b70efd9
--- /dev/null
+++ b/src/pkg/go/doc/example_test.go
@@ -0,0 +1,111 @@
+// 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 doc_test
+
+import (
+	"bytes"
+	"go/doc"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"strings"
+	"testing"
+)
+
+const exampleTestFile = `
+package foo_test
+
+import (
+	"fmt"
+	"log"
+	"os/exec"
+)
+
+func ExampleHello() {
+	fmt.Println("Hello, world!")
+	// Output: Hello, world!
+}
+
+func ExampleImport() {
+	out, err := exec.Command("date").Output()
+	if err != nil {
+		log.Fatal(err)
+	}
+	fmt.Printf("The date is %s\n", out)
+}
+`
+
+var exampleTestCases = []struct {
+	Name, Play, Output string
+}{
+	{
+		Name:   "Hello",
+		Play:   exampleHelloPlay,
+		Output: "Hello, world!\n",
+	},
+	{
+		Name: "Import",
+		Play: exampleImportPlay,
+	},
+}
+
+const exampleHelloPlay = `package main
+
+import (
+	"fmt"
+)
+
+func main() {
+	fmt.Println("Hello, world!")
+}
+`
+const exampleImportPlay = `package main
+
+import (
+	"fmt"
+	"log"
+	"os/exec"
+)
+
+func main() {
+	out, err := exec.Command("date").Output()
+	if err != nil {
+		log.Fatal(err)
+	}
+	fmt.Printf("The date is %s\n", out)
+}
+`
+
+func TestExamples(t *testing.T) {
+	fs := token.NewFileSet()
+	file, err := parser.ParseFile(fs, "test.go", strings.NewReader(exampleTestFile), parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for i, e := range doc.Examples(file) {
+		c := exampleTestCases[i]
+		if e.Name != c.Name {
+			t.Errorf("got Name == %q, want %q", e.Name, c.Name)
+		}
+		if w := c.Play; w != "" {
+			var g string // hah
+			if e.Play == nil {
+				g = "<nil>"
+			} else {
+				b := new(bytes.Buffer)
+				if err := format.Node(b, fs, e.Play); err != nil {
+					t.Fatal(err)
+				}
+				g = b.String()
+			}
+			if g != w {
+				t.Errorf("%s: got Play == %q, want %q", c.Name, g, w)
+			}
+		}
+		if g, w := e.Output, c.Output; g != w {
+			t.Errorf("%s: got Output == %q, want %q", c.Name, g, w)
+		}
+	}
+}
diff --git a/src/pkg/go/doc/exports.go b/src/pkg/go/doc/exports.go
index 146be5d..ff01285 100644
--- a/src/pkg/go/doc/exports.go
+++ b/src/pkg/go/doc/exports.go
@@ -107,7 +107,7 @@ func (r *reader) filterParamList(fields *ast.FieldList) {
 
 // filterType strips any unexported struct fields or method types from typ
 // in place. If fields (or methods) have been removed, the corresponding
-// struct or interface type has the Incomplete field set to true. 
+// struct or interface type has the Incomplete field set to true.
 //
 func (r *reader) filterType(parent *namedType, typ ast.Expr) {
 	switch t := typ.(type) {
diff --git a/src/pkg/go/doc/reader.go b/src/pkg/go/doc/reader.go
index 5eaae37..dd6a572 100644
--- a/src/pkg/go/doc/reader.go
+++ b/src/pkg/go/doc/reader.go
@@ -46,7 +46,7 @@ func (mset methodSet) set(f *ast.FuncDecl) {
 		// since it has documentation, assume f is simply another
 		// implementation and ignore it. This does not happen if the
 		// caller is using go/build.ScanDir to determine the list of
-		// files implementing a package. 
+		// files implementing a package.
 		return
 	}
 	// function doesn't exist or has no documentation; use f
@@ -149,6 +149,7 @@ type reader struct {
 	doc       string // package documentation, if any
 	filenames []string
 	bugs      []string
+	notes     map[string][]string
 
 	// declarations
 	imports map[string]int
@@ -400,10 +401,23 @@ func (r *reader) readFunc(fun *ast.FuncDecl) {
 }
 
 var (
-	bug_markers = regexp.MustCompile("^/[/*][ \t]*BUG\\(.*\\):[ \t]*") // BUG(uid):
-	bug_content = regexp.MustCompile("[^ \n\r\t]+")                    // at least one non-whitespace char
+	noteMarker  = regexp.MustCompile(`^/[/*][ \t]*([A-Z][A-Z]+)\(.+\):[ \t]*(.*)`) // MARKER(uid)
+	noteContent = regexp.MustCompile(`[^ \n\r\t]+`)                                // at least one non-whitespace char
 )
 
+func readNote(c *ast.CommentGroup) (marker, annotation string) {
+	text := c.List[0].Text
+	if m := noteMarker.FindStringSubmatch(text); m != nil {
+		if btxt := m[2]; noteContent.MatchString(btxt) {
+			// non-empty MARKER comment; collect comment without the MARKER prefix
+			list := append([]*ast.Comment(nil), c.List...) // make a copy
+			list[0].Text = m[2]
+			return m[1], (&ast.CommentGroup{List: list}).Text()
+		}
+	}
+	return "", ""
+}
+
 // readFile adds the AST for a source file to the reader.
 //
 func (r *reader) readFile(src *ast.File) {
@@ -469,16 +483,12 @@ func (r *reader) readFile(src *ast.File) {
 		}
 	}
 
-	// collect BUG(...) comments
+	// collect MARKER(...): annotations
 	for _, c := range src.Comments {
-		text := c.List[0].Text
-		if m := bug_markers.FindStringIndex(text); m != nil {
-			// found a BUG comment; maybe empty
-			if btxt := text[m[1]:]; bug_content.MatchString(btxt) {
-				// non-empty BUG comment; collect comment without BUG prefix
-				list := append([]*ast.Comment(nil), c.List...) // make a copy
-				list[0].Text = text[m[1]:]
-				r.bugs = append(r.bugs, (&ast.CommentGroup{List: list}).Text())
+		if marker, text := readNote(c); marker != "" {
+			r.notes[marker] = append(r.notes[marker], text)
+			if marker == "BUG" {
+				r.bugs = append(r.bugs, text)
 			}
 		}
 	}
@@ -492,9 +502,10 @@ func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
 	r.mode = mode
 	r.types = make(map[string]*namedType)
 	r.funcs = make(methodSet)
+	r.notes = make(map[string][]string)
 
 	// sort package files before reading them so that the
-	// result result does not depend on map iteration order
+	// result does not depend on map iteration order
 	i := 0
 	for filename := range pkg.Files {
 		r.filenames[i] = filename
@@ -515,29 +526,6 @@ func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
 // ----------------------------------------------------------------------------
 // Types
 
-var predeclaredTypes = map[string]bool{
-	"bool":       true,
-	"byte":       true,
-	"complex64":  true,
-	"complex128": true,
-	"error":      true,
-	"float32":    true,
-	"float64":    true,
-	"int":        true,
-	"int8":       true,
-	"int16":      true,
-	"int32":      true,
-	"int64":      true,
-	"rune":       true,
-	"string":     true,
-	"uint":       true,
-	"uint8":      true,
-	"uint16":     true,
-	"uint32":     true,
-	"uint64":     true,
-	"uintptr":    true,
-}
-
 func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func {
 	if f == nil || f.Decl == nil || f.Decl.Recv == nil || len(f.Decl.Recv.List) != 1 {
 		return f // shouldn't happen, but be safe
@@ -620,7 +608,7 @@ func (r *reader) computeMethodSets() {
 // types that have no declaration. Instead, these functions and methods
 // are shown at the package level. It also removes types with missing
 // declarations or which are not visible.
-// 
+//
 func (r *reader) cleanupTypes() {
 	for _, t := range r.types {
 		visible := r.isVisible(t.name)
@@ -772,3 +760,54 @@ func sortedFuncs(m methodSet, allMethods bool) []*Func {
 	)
 	return list
 }
+
+// ----------------------------------------------------------------------------
+// Predeclared identifiers
+
+var predeclaredTypes = map[string]bool{
+	"bool":       true,
+	"byte":       true,
+	"complex64":  true,
+	"complex128": true,
+	"error":      true,
+	"float32":    true,
+	"float64":    true,
+	"int":        true,
+	"int8":       true,
+	"int16":      true,
+	"int32":      true,
+	"int64":      true,
+	"rune":       true,
+	"string":     true,
+	"uint":       true,
+	"uint8":      true,
+	"uint16":     true,
+	"uint32":     true,
+	"uint64":     true,
+	"uintptr":    true,
+}
+
+var predeclaredFuncs = map[string]bool{
+	"append":  true,
+	"cap":     true,
+	"close":   true,
+	"complex": true,
+	"copy":    true,
+	"delete":  true,
+	"imag":    true,
+	"len":     true,
+	"make":    true,
+	"new":     true,
+	"panic":   true,
+	"print":   true,
+	"println": true,
+	"real":    true,
+	"recover": true,
+}
+
+var predeclaredConstants = map[string]bool{
+	"false": true,
+	"iota":  true,
+	"nil":   true,
+	"true":  true,
+}
diff --git a/src/pkg/go/doc/synopsis.go b/src/pkg/go/doc/synopsis.go
index 2192d78..2d18174 100644
--- a/src/pkg/go/doc/synopsis.go
+++ b/src/pkg/go/doc/synopsis.go
@@ -4,7 +4,10 @@
 
 package doc
 
-import "unicode"
+import (
+	"strings"
+	"unicode"
+)
 
 // firstSentenceLen returns the length of the first sentence in s.
 // The sentence ends after the first period followed by space and
@@ -24,17 +27,12 @@ func firstSentenceLen(s string) int {
 	return len(s)
 }
 
-// Synopsis returns a cleaned version of the first sentence in s.
-// That sentence ends after the first period followed by space and
-// not preceded by exactly one uppercase letter. The result string
-// has no \n, \r, or \t characters and uses only single spaces between
-// words.
-//
-func Synopsis(s string) string {
-	n := firstSentenceLen(s)
+// clean replaces each sequence of space, \n, \r, or \t characters
+// with a single space and removes any trailing and leading spaces.
+func clean(s string) string {
 	var b []byte
 	p := byte(' ')
-	for i := 0; i < n; i++ {
+	for i := 0; i < len(s); i++ {
 		q := s[i]
 		if q == '\n' || q == '\r' || q == '\t' {
 			q = ' '
@@ -50,3 +48,26 @@ func Synopsis(s string) string {
 	}
 	return string(b)
 }
+
+// Synopsis returns a cleaned version of the first sentence in s.
+// That sentence ends after the first period followed by space and
+// not preceded by exactly one uppercase letter. The result string
+// has no \n, \r, or \t characters and uses only single spaces between
+// words. If s starts with any of the IllegalPrefixes, the result
+// is the empty string.
+//
+func Synopsis(s string) string {
+	s = clean(s[0:firstSentenceLen(s)])
+	for _, prefix := range IllegalPrefixes {
+		if strings.HasPrefix(strings.ToLower(s), prefix) {
+			return ""
+		}
+	}
+	return s
+}
+
+var IllegalPrefixes = []string{
+	"copyright",
+	"all rights",
+	"author",
+}
diff --git a/src/pkg/go/doc/synopsis_test.go b/src/pkg/go/doc/synopsis_test.go
index dfc6598..fd7081a 100644
--- a/src/pkg/go/doc/synopsis_test.go
+++ b/src/pkg/go/doc/synopsis_test.go
@@ -28,6 +28,11 @@ var tests = []struct {
 	{"P. Q.   ", 8, "P. Q."},
 	{"Package Καλημέρα κόσμε.", 36, "Package Καλημέρα κόσμε."},
 	{"Package こんにちは 世界\n", 31, "Package こんにちは 世界"},
+	{"Package foo does bar.", 21, "Package foo does bar."},
+	{"Copyright 2012 Google, Inc. Package foo does bar.", 27, ""},
+	{"All Rights reserved. Package foo does bar.", 20, ""},
+	{"All rights reserved. Package foo does bar.", 20, ""},
+	{"Authors: foo at bar.com. Package foo does bar.", 21, ""},
 }
 
 func TestSynopsis(t *testing.T) {
diff --git a/src/pkg/go/doc/testdata/a.0.golden b/src/pkg/go/doc/testdata/a.0.golden
index 24db02d..ae3756c 100644
--- a/src/pkg/go/doc/testdata/a.0.golden
+++ b/src/pkg/go/doc/testdata/a.0.golden
@@ -8,6 +8,17 @@ FILENAMES
 	testdata/a0.go
 	testdata/a1.go
 
+BUGS .Bugs is now deprecated, please use .Notes instead
+	// bug0 
+	// bug1 
+
 BUGS
 	// bug0 
 	// bug1 
+
+SECBUGS
+	// sec hole 0 need to fix asap 
+
+TODOS
+	// todo0 
+	// todo1 
diff --git a/src/pkg/go/doc/testdata/a.1.golden b/src/pkg/go/doc/testdata/a.1.golden
index 24db02d..ae3756c 100644
--- a/src/pkg/go/doc/testdata/a.1.golden
+++ b/src/pkg/go/doc/testdata/a.1.golden
@@ -8,6 +8,17 @@ FILENAMES
 	testdata/a0.go
 	testdata/a1.go
 
+BUGS .Bugs is now deprecated, please use .Notes instead
+	// bug0 
+	// bug1 
+
 BUGS
 	// bug0 
 	// bug1 
+
+SECBUGS
+	// sec hole 0 need to fix asap 
+
+TODOS
+	// todo0 
+	// todo1 
diff --git a/src/pkg/go/doc/testdata/a.2.golden b/src/pkg/go/doc/testdata/a.2.golden
index 24db02d..ae3756c 100644
--- a/src/pkg/go/doc/testdata/a.2.golden
+++ b/src/pkg/go/doc/testdata/a.2.golden
@@ -8,6 +8,17 @@ FILENAMES
 	testdata/a0.go
 	testdata/a1.go
 
+BUGS .Bugs is now deprecated, please use .Notes instead
+	// bug0 
+	// bug1 
+
 BUGS
 	// bug0 
 	// bug1 
+
+SECBUGS
+	// sec hole 0 need to fix asap 
+
+TODOS
+	// todo0 
+	// todo1 
diff --git a/src/pkg/go/doc/testdata/a0.go b/src/pkg/go/doc/testdata/a0.go
index dc55298..71af470 100644
--- a/src/pkg/go/doc/testdata/a0.go
+++ b/src/pkg/go/doc/testdata/a0.go
@@ -6,3 +6,12 @@
 package a
 
 //BUG(uid): bug0
+
+//TODO(uid): todo0
+
+// A note with some spaces after it, should be ignored (watch out for
+// emacs modes that remove trailing whitespace).
+//NOTE(uid):
+
+// SECBUG(uid): sec hole 0
+// need to fix asap
diff --git a/src/pkg/go/doc/testdata/a1.go b/src/pkg/go/doc/testdata/a1.go
index 098776c..9fad1e0 100644
--- a/src/pkg/go/doc/testdata/a1.go
+++ b/src/pkg/go/doc/testdata/a1.go
@@ -6,3 +6,7 @@
 package a
 
 //BUG(uid): bug1
+
+//TODO(uid): todo1
+
+//TODO(): ignored
diff --git a/src/pkg/go/doc/testdata/benchmark.go b/src/pkg/go/doc/testdata/benchmark.go
index 0aded5b..905e496 100644
--- a/src/pkg/go/doc/testdata/benchmark.go
+++ b/src/pkg/go/doc/testdata/benchmark.go
@@ -13,7 +13,7 @@ import (
 )
 
 var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
-var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
+var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
 
 // An internal type but exported because it is cross-package; part of the implementation
 // of go test.
@@ -151,7 +151,7 @@ func (b *B) launch() {
 
 	b.runN(n)
 	// Run the benchmark for at least the specified amount of time.
-	d := time.Duration(*benchTime * float64(time.Second))
+	d := *benchTime
 	for !b.failed && b.duration < d && n < 1e9 {
 		last := n
 		// Predict iterations/sec.
diff --git a/src/pkg/go/doc/testdata/e.go b/src/pkg/go/doc/testdata/e.go
index 19dd138..ec432e3 100644
--- a/src/pkg/go/doc/testdata/e.go
+++ b/src/pkg/go/doc/testdata/e.go
@@ -106,7 +106,7 @@ type U4 struct {
 	*u5
 }
 
-// U4.M should appear as method of U4. 
+// U4.M should appear as method of U4.
 func (*U4) M() {}
 
 type u5 struct {
diff --git a/src/pkg/go/doc/testdata/error2.1.golden b/src/pkg/go/doc/testdata/error2.1.golden
index 776bd1b..dbcc1b0 100644
--- a/src/pkg/go/doc/testdata/error2.1.golden
+++ b/src/pkg/go/doc/testdata/error2.1.golden
@@ -10,7 +10,7 @@ FILENAMES
 TYPES
 	// 
 	type I0 interface {
-		// When embedded, the the locally declared error interface
+		// When embedded, the locally-declared error interface
 		// is only visible if all declarations are shown.
 		error
 	}
diff --git a/src/pkg/go/doc/testdata/error2.go b/src/pkg/go/doc/testdata/error2.go
index 6cc36fe..6ee96c2 100644
--- a/src/pkg/go/doc/testdata/error2.go
+++ b/src/pkg/go/doc/testdata/error2.go
@@ -5,7 +5,7 @@
 package error2
 
 type I0 interface {
-	// When embedded, the the locally declared error interface
+	// When embedded, the locally-declared error interface
 	// is only visible if all declarations are shown.
 	error
 }
diff --git a/src/pkg/go/doc/testdata/template.txt b/src/pkg/go/doc/testdata/template.txt
index 32e331c..d3882b6 100644
--- a/src/pkg/go/doc/testdata/template.txt
+++ b/src/pkg/go/doc/testdata/template.txt
@@ -60,6 +60,9 @@ TYPES
 {{end}}{{end}}{{end}}{{/*
 
 */}}{{with .Bugs}}
-BUGS
+BUGS .Bugs is now deprecated, please use .Notes instead
 {{range .}}	{{synopsis .}}
-{{end}}{{end}}
\ No newline at end of file
+{{end}}{{end}}{{with .Notes}}{{range $marker, $content := .}}
+{{$marker}}S
+{{range $content}}	{{synopsis .}}
+{{end}}{{end}}{{end}}
\ No newline at end of file
diff --git a/src/pkg/go/doc/testdata/testing.1.golden b/src/pkg/go/doc/testdata/testing.1.golden
index d26a468..ffdb5c3 100644
--- a/src/pkg/go/doc/testdata/testing.1.golden
+++ b/src/pkg/go/doc/testdata/testing.1.golden
@@ -45,7 +45,7 @@ VARIABLES
 	)
 
 	// 
-	var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
+	var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
 
 	// 
 	var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
diff --git a/src/pkg/go/doc/testdata/testing.go b/src/pkg/go/doc/testdata/testing.go
index 71c1d1e..c2499ad 100644
--- a/src/pkg/go/doc/testdata/testing.go
+++ b/src/pkg/go/doc/testdata/testing.go
@@ -197,7 +197,7 @@ func (c *common) Fatalf(format string, args ...interface{}) {
 	c.FailNow()
 }
 
-// Parallel signals that this test is to be run in parallel with (and only with) 
+// Parallel signals that this test is to be run in parallel with (and only with)
 // other parallel tests in this CPU group.
 func (t *T) Parallel() {
 	t.signal <- (*T)(nil) // Release main testing loop
@@ -215,7 +215,7 @@ func tRunner(t *T, test *InternalTest) {
 	t.start = time.Now()
 
 	// When this goroutine is done, either because test.F(t)
-	// returned normally or because a test failure triggered 
+	// returned normally or because a test failure triggered
 	// a call to runtime.Goexit, record the duration and send
 	// a signal saying that the test is done.
 	defer func() {
diff --git a/src/pkg/go/format/format.go b/src/pkg/go/format/format.go
new file mode 100644
index 0000000..65b0e4e
--- /dev/null
+++ b/src/pkg/go/format/format.go
@@ -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.
+
+// 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 writes the result to dst
+// or returns 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 formatted src 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/go/format/format_test.go b/src/pkg/go/format/format_test.go
new file mode 100644
index 0000000..7d7940b
--- /dev/null
+++ b/src/pkg/go/format/format_test.go
@@ -0,0 +1,125 @@
+// 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
+
+import (
+	"bytes"
+	"go/parser"
+	"go/token"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+const testfile = "format_test.go"
+
+func diff(t *testing.T, dst, src []byte) {
+	line := 1
+	offs := 0 // line offset
+	for i := 0; i < len(dst) && i < len(src); i++ {
+		d := dst[i]
+		s := src[i]
+		if d != s {
+			t.Errorf("dst:%d: %s\n", line, dst[offs:i+1])
+			t.Errorf("src:%d: %s\n", line, src[offs:i+1])
+			return
+		}
+		if s == '\n' {
+			line++
+			offs = i + 1
+		}
+	}
+	if len(dst) != len(src) {
+		t.Errorf("len(dst) = %d, len(src) = %d\nsrc = %q", len(dst), len(src), src)
+	}
+}
+
+func TestNode(t *testing.T) {
+	src, err := ioutil.ReadFile(testfile)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	fset := token.NewFileSet()
+	file, err := parser.ParseFile(fset, testfile, src, parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var buf bytes.Buffer
+
+	if err = Node(&buf, fset, file); err != nil {
+		t.Fatal("Node failed:", err)
+	}
+
+	diff(t, buf.Bytes(), src)
+}
+
+func TestSource(t *testing.T) {
+	src, err := ioutil.ReadFile(testfile)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	res, err := Source(src)
+	if err != nil {
+		t.Fatal("Source failed:", err)
+	}
+
+	diff(t, res, src)
+}
+
+// Test cases that are expected to fail are marked by the prefix "ERROR".
+var tests = []string{
+	// declaration lists
+	`import "go/format"`,
+	"var x int",
+	"var x int\n\ntype T struct{}",
+
+	// statement lists
+	"x := 0",
+	"f(a, b, c)\nvar x int = f(1, 2, 3)",
+
+	// indentation, leading and trailing space
+	"\tx := 0\n\tgo f()",
+	"\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
+
+	// erroneous programs
+	"ERRORvar x",
+	"ERROR1 + 2 +",
+	"ERRORx :=  0",
+}
+
+func String(s string) (string, error) {
+	res, err := Source([]byte(s))
+	if err != nil {
+		return "", err
+	}
+	return string(res), nil
+}
+
+func TestPartial(t *testing.T) {
+	for _, src := range tests {
+		if strings.HasPrefix(src, "ERROR") {
+			// test expected to fail
+			src = src[5:] // remove ERROR prefix
+			res, err := String(src)
+			if err == nil && res == src {
+				t.Errorf("formatting succeeded but was expected to fail:\n%q", src)
+			}
+		} else {
+			// test expected to succeed
+			res, err := String(src)
+			if err != nil {
+				t.Errorf("formatting failed (%s):\n%q", err, src)
+			} else if res != src {
+				t.Errorf("formatting incorrect:\nsource: %q\nresult: %q", src, res)
+			}
+		}
+	}
+}
diff --git a/src/pkg/go/parser/error_test.go b/src/pkg/go/parser/error_test.go
index 377c8b8..b59fda1 100644
--- a/src/pkg/go/parser/error_test.go
+++ b/src/pkg/go/parser/error_test.go
@@ -34,9 +34,11 @@ import (
 
 const testdata = "testdata"
 
+var fsetErrs *token.FileSet
+
 // getFile assumes that each filename occurs at most once
 func getFile(filename string) (file *token.File) {
-	fset.Iterate(func(f *token.File) bool {
+	fsetErrs.Iterate(func(f *token.File) bool {
 		if f.Name() == filename {
 			if file != nil {
 				panic(filename + " used multiple times")
@@ -125,7 +127,7 @@ func compareErrors(t *testing.T, expected map[token.Pos]string, found scanner.Er
 	if len(expected) > 0 {
 		t.Errorf("%d errors not reported:", len(expected))
 		for pos, msg := range expected {
-			t.Errorf("%s: %s\n", fset.Position(pos), msg)
+			t.Errorf("%s: %s\n", fsetErrs.Position(pos), msg)
 		}
 	}
 }
@@ -137,12 +139,13 @@ func checkErrors(t *testing.T, filename string, input interface{}) {
 		return
 	}
 
-	_, err = ParseFile(fset, filename, src, DeclarationErrors)
+	_, err = ParseFile(fsetErrs, filename, src, DeclarationErrors|AllErrors)
 	found, ok := err.(scanner.ErrorList)
 	if err != nil && !ok {
 		t.Error(err)
 		return
 	}
+	found.RemoveMultiples()
 
 	// we are expecting the following errors
 	// (collect these after parsing a file so that it is found in the file set)
@@ -153,6 +156,7 @@ 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/interface.go b/src/pkg/go/parser/interface.go
index 5c203a7..39affdd 100644
--- a/src/pkg/go/parser/interface.go
+++ b/src/pkg/go/parser/interface.go
@@ -52,12 +52,13 @@ func readSource(filename string, src interface{}) ([]byte, error) {
 type Mode uint
 
 const (
-	PackageClauseOnly Mode = 1 << iota // parsing stops after package clause
-	ImportsOnly                        // parsing stops after import declarations
-	ParseComments                      // parse comments and add them to AST
-	Trace                              // print a trace of parsed productions
-	DeclarationErrors                  // report declaration errors
-	SpuriousErrors                     // report all (not just the first) errors per line
+	PackageClauseOnly Mode             = 1 << iota // stop parsing after package clause
+	ImportsOnly                                    // stop parsing after import declarations
+	ParseComments                                  // parse comments and add them to AST
+	Trace                                          // print a trace of parsed productions
+	DeclarationErrors                              // report declaration errors
+	SpuriousErrors                                 // same as AllErrors, for backward-compatibility
+	AllErrors         = SpuriousErrors             // report all errors (not just the first 10 on different lines)
 )
 
 // ParseFile parses the source code of a single Go source file and returns
@@ -79,26 +80,39 @@ const (
 // representing the fragments of erroneous source code). Multiple errors
 // are returned via a scanner.ErrorList which is sorted by file position.
 //
-func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (*ast.File, error) {
+func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (f *ast.File, err error) {
 	// get source
 	text, err := readSource(filename, src)
 	if err != nil {
 		return nil, err
 	}
 
-	// parse source
 	var p parser
-	p.init(fset, filename, text, mode)
-	f := p.parseFile()
+	defer func() {
+		if e := recover(); e != nil {
+			_ = e.(bailout) // re-panics if it's not a bailout
+		}
+
+		// set result values
+		if f == nil {
+			// source is not a valid Go source file - satisfy
+			// ParseFile API and return a valid (but) empty
+			// *ast.File
+			f = &ast.File{
+				Name:  new(ast.Ident),
+				Scope: ast.NewScope(nil),
+			}
+		}
 
-	// sort errors
-	if p.mode&SpuriousErrors == 0 {
-		p.errors.RemoveMultiples()
-	} else {
 		p.errors.Sort()
-	}
+		err = p.errors.Err()
+	}()
+
+	// parse source
+	p.init(fset, filename, text, mode)
+	f = p.parseFile()
 
-	return f, p.errors.Err()
+	return
 }
 
 // ParseDir calls ParseFile for the files in the directory specified by path and
@@ -149,7 +163,7 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m
 
 // ParseExpr is a convenience function for obtaining the AST of an expression x.
 // The position information recorded in the AST is undefined.
-// 
+//
 func ParseExpr(x string) (ast.Expr, error) {
 	// parse x within the context of a complete package for correct scopes;
 	// use //line directive for correct positions in error messages and put
diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go
index 20e505d..a021a5a 100644
--- a/src/pkg/go/parser/parser.go
+++ b/src/pkg/go/parser/parser.go
@@ -28,7 +28,7 @@ type parser struct {
 	// Tracing/debugging
 	mode   Mode // parsing mode
 	trace  bool // == (mode & Trace != 0)
-	indent uint // indentation used for tracing output
+	indent int  // indentation used for tracing output
 
 	// Comments
 	comments    []*ast.CommentGroup
@@ -56,7 +56,7 @@ type parser struct {
 	unresolved []*ast.Ident      // unresolved identifiers
 	imports    []*ast.ImportSpec // list of imports
 
-	// Label scope
+	// Label scopes
 	// (maintained by open/close LabelScope)
 	labelScope  *ast.Scope     // label scope for current function
 	targetStack [][]*ast.Ident // stack of unresolved labels
@@ -75,14 +75,6 @@ func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mod
 	p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
 
 	p.next()
-
-	// set up the pkgScope here (as opposed to in parseFile) because
-	// there are other parser entry points (ParseExpr, etc.)
-	p.openScope()
-	p.pkgScope = p.topScope
-
-	// for the same reason, set up a label scope
-	p.openLabelScope()
 }
 
 // ----------------------------------------------------------------------------
@@ -157,7 +149,7 @@ func (p *parser) shortVarDecl(decl *ast.AssignStmt, list []ast.Expr) {
 				}
 			}
 		} else {
-			p.errorExpected(x.Pos(), "identifier")
+			p.errorExpected(x.Pos(), "identifier on left side of :=")
 		}
 	}
 	if n == 0 && p.mode&DeclarationErrors != 0 {
@@ -170,7 +162,12 @@ func (p *parser) shortVarDecl(decl *ast.AssignStmt, list []ast.Expr) {
 // internal consistency.
 var unresolved = new(ast.Object)
 
-func (p *parser) resolve(x ast.Expr) {
+// If x is an identifier, tryResolve attempts to resolve x by looking up
+// the object it denotes. If no object is found and collectUnresolved is
+// set, x is marked as unresolved and collected in the list of unresolved
+// identifiers.
+//
+func (p *parser) tryResolve(x ast.Expr, collectUnresolved bool) {
 	// nothing to do if x is not an identifier or the blank identifier
 	ident, _ := x.(*ast.Ident)
 	if ident == nil {
@@ -191,23 +188,30 @@ func (p *parser) resolve(x ast.Expr) {
 	// must be found either in the file scope, package scope
 	// (perhaps in another file), or universe scope --- collect
 	// them so that they can be resolved later
-	ident.Obj = unresolved
-	p.unresolved = append(p.unresolved, ident)
+	if collectUnresolved {
+		ident.Obj = unresolved
+		p.unresolved = append(p.unresolved, ident)
+	}
+}
+
+func (p *parser) resolve(x ast.Expr) {
+	p.tryResolve(x, true)
 }
 
 // ----------------------------------------------------------------------------
 // Parsing support
 
 func (p *parser) printTrace(a ...interface{}) {
-	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " +
-		". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
-	const n = uint(len(dots))
+	const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
+	const n = len(dots)
 	pos := p.file.Position(p.pos)
 	fmt.Printf("%5d:%3d: ", pos.Line, pos.Column)
 	i := 2 * p.indent
-	for ; i > n; i -= n {
+	for i > n {
 		fmt.Print(dots)
+		i -= n
 	}
+	// i <= n
 	fmt.Print(dots[0:i])
 	fmt.Println(a...)
 }
@@ -218,7 +222,7 @@ func trace(p *parser, msg string) *parser {
 	return p
 }
 
-// Usage pattern: defer un(trace(p, "..."));
+// Usage pattern: defer un(trace(p, "..."))
 func un(p *parser) {
 	p.indent--
 	p.printTrace(")")
@@ -304,14 +308,14 @@ func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline
 func (p *parser) next() {
 	p.leadComment = nil
 	p.lineComment = nil
-	line := p.file.Line(p.pos) // current line
+	prev := p.pos
 	p.next0()
 
 	if p.tok == token.COMMENT {
 		var comment *ast.CommentGroup
 		var endline int
 
-		if p.file.Line(p.pos) == line {
+		if p.file.Line(p.pos) == p.file.Line(prev) {
 			// The comment is on same line as the previous token; it
 			// cannot be a lead comment but may be a line comment.
 			comment, endline = p.consumeCommentGroup(0)
@@ -336,8 +340,26 @@ func (p *parser) next() {
 	}
 }
 
+// A bailout panic is raised to indicate early termination.
+type bailout struct{}
+
 func (p *parser) error(pos token.Pos, msg string) {
-	p.errors.Add(p.file.Position(pos), msg)
+	epos := p.file.Position(pos)
+
+	// If AllErrors is not set, discard errors reported on the same line
+	// as the last recorded error and stop parsing if there are more than
+	// 10 errors.
+	if p.mode&AllErrors == 0 {
+		n := len(p.errors)
+		if n > 0 && p.errors[n-1].Pos.Line == epos.Line {
+			return // discard - likely a spurious error
+		}
+		if n > 10 {
+			panic(bailout{})
+		}
+	}
+
+	p.errors.Add(epos, msg)
 }
 
 func (p *parser) errorExpected(pos token.Pos, msg string) {
@@ -585,14 +607,15 @@ func (p *parser) parseTypeName() ast.Expr {
 	return ident
 }
 
-func (p *parser) parseArrayType(ellipsisOk bool) ast.Expr {
+func (p *parser) parseArrayType() ast.Expr {
 	if p.trace {
 		defer un(trace(p, "ArrayType"))
 	}
 
 	lbrack := p.expect(token.LBRACK)
 	var len ast.Expr
-	if ellipsisOk && p.tok == token.ELLIPSIS {
+	// always permit ellipsis for more fault-tolerant parsing
+	if p.tok == token.ELLIPSIS {
 		len = &ast.Ellipsis{Ellipsis: p.pos}
 		p.next()
 	} else if p.tok != token.RBRACK {
@@ -704,7 +727,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
 	if isParam && p.tok == token.ELLIPSIS {
 		pos := p.pos
 		p.next()
-		typ := p.tryIdentOrType(isParam) // don't use parseType so we can provide better error message
+		typ := p.tryIdentOrType() // don't use parseType so we can provide better error message
 		if typ != nil {
 			p.resolve(typ)
 		} else {
@@ -713,7 +736,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
 		}
 		return &ast.Ellipsis{Ellipsis: pos, Elt: typ}
 	}
-	return p.tryIdentOrType(false)
+	return p.tryIdentOrType()
 }
 
 // If the result is an identifier, it is not resolved.
@@ -931,29 +954,31 @@ func (p *parser) parseChanType() *ast.ChanType {
 
 	pos := p.pos
 	dir := ast.SEND | ast.RECV
+	var arrow token.Pos
 	if p.tok == token.CHAN {
 		p.next()
 		if p.tok == token.ARROW {
+			arrow = p.pos
 			p.next()
 			dir = ast.SEND
 		}
 	} else {
-		p.expect(token.ARROW)
+		arrow = p.expect(token.ARROW)
 		p.expect(token.CHAN)
 		dir = ast.RECV
 	}
 	value := p.parseType()
 
-	return &ast.ChanType{Begin: pos, Dir: dir, Value: value}
+	return &ast.ChanType{Begin: pos, Arrow: arrow, Dir: dir, Value: value}
 }
 
 // If the result is an identifier, it is not resolved.
-func (p *parser) tryIdentOrType(ellipsisOk bool) ast.Expr {
+func (p *parser) tryIdentOrType() ast.Expr {
 	switch p.tok {
 	case token.IDENT:
 		return p.parseTypeName()
 	case token.LBRACK:
-		return p.parseArrayType(ellipsisOk)
+		return p.parseArrayType()
 	case token.STRUCT:
 		return p.parseStructType()
 	case token.MUL:
@@ -980,7 +1005,7 @@ func (p *parser) tryIdentOrType(ellipsisOk bool) ast.Expr {
 }
 
 func (p *parser) tryType() ast.Expr {
-	typ := p.tryIdentOrType(false)
+	typ := p.tryIdentOrType()
 	if typ != nil {
 		p.resolve(typ)
 	}
@@ -1088,7 +1113,7 @@ func (p *parser) parseOperand(lhs bool) ast.Expr {
 		return p.parseFuncTypeOrLit()
 	}
 
-	if typ := p.tryIdentOrType(true); typ != nil {
+	if typ := p.tryIdentOrType(); typ != nil {
 		// could be type for composite literal or conversion
 		_, isIdent := typ.(*ast.Ident)
 		assert(!isIdent, "type cannot be identifier")
@@ -1193,14 +1218,35 @@ func (p *parser) parseElement(keyOk bool) ast.Expr {
 		return p.parseLiteralValue(nil)
 	}
 
-	x := p.checkExpr(p.parseExpr(keyOk)) // don't resolve if map key
+	// Because the parser doesn't know the composite literal type, it cannot
+	// know if a key that's an identifier is a struct field name or a name
+	// denoting a value. The former is not resolved by the parser or the
+	// resolver.
+	//
+	// Instead, _try_ to resolve such a key if possible. If it resolves,
+	// it a) has correctly resolved, or b) incorrectly resolved because
+	// the key is a struct field with a name matching another identifier.
+	// In the former case we are done, and in the latter case we don't
+	// care because the type checker will do a separate field lookup.
+	//
+	// If the key does not resolve, it a) must be defined at the top
+	// level in another file of the same package, the universe scope, or be
+	// undeclared; or b) it is a struct field. In the former case, the type
+	// checker can do a top-level lookup, and in the latter case it will do
+	// a separate field lookup.
+	x := p.checkExpr(p.parseExpr(keyOk))
 	if keyOk {
 		if p.tok == token.COLON {
 			colon := p.pos
 			p.next()
+			// Try to resolve the key but don't collect it
+			// as unresolved identifier if it fails so that
+			// we don't get (possibly false) errors about
+			// undeclared names.
+			p.tryResolve(x, false)
 			return &ast.KeyValueExpr{Key: x, Colon: colon, Value: p.parseElement(false)}
 		}
-		p.resolve(x) // not a map key
+		p.resolve(x) // not a key
 	}
 
 	return x
@@ -1404,16 +1450,49 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
 
 	case token.ARROW:
 		// channel type or receive expression
-		pos := p.pos
+		arrow := p.pos
 		p.next()
-		if p.tok == token.CHAN {
-			p.next()
-			value := p.parseType()
-			return &ast.ChanType{Begin: pos, Dir: ast.RECV, Value: value}
-		}
+
+		// If the next token is token.CHAN we still don't know if it
+		// is a channel type or a receive operation - we only know
+		// once we have found the end of the unary expression. There
+		// are two cases:
+		//
+		//   <- type  => (<-type) must be channel type
+		//   <- expr  => <-(expr) is a receive from an expression
+		//
+		// In the first case, the arrow must be re-associated with
+		// the channel type parsed already:
+		//
+		//   <- (chan type)    =>  (<-chan type)
+		//   <- (chan<- type)  =>  (<-chan (<-type))
 
 		x := p.parseUnaryExpr(false)
-		return &ast.UnaryExpr{OpPos: pos, Op: token.ARROW, X: p.checkExpr(x)}
+
+		// determine which case we have
+		if typ, ok := x.(*ast.ChanType); ok {
+			// (<-type)
+
+			// re-associate position info and <-
+			dir := ast.SEND
+			for ok && dir == ast.SEND {
+				if typ.Dir == ast.RECV {
+					// error: (<-type) is (<-(<-chan T))
+					p.errorExpected(typ.Arrow, "'chan'")
+				}
+				arrow, typ.Begin, typ.Arrow = typ.Arrow, arrow, arrow
+				dir, typ.Dir = typ.Dir, ast.RECV
+				typ, ok = typ.Value.(*ast.ChanType)
+			}
+			if dir == ast.SEND {
+				p.errorExpected(arrow, "channel type")
+			}
+
+			return x
+		}
+
+		// <-(expr)
+		return &ast.UnaryExpr{OpPos: arrow, Op: token.ARROW, X: p.checkExpr(x)}
 
 	case token.MUL:
 		// pointer type or unary "*" expression
@@ -1774,7 +1853,7 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
 				//
 				//	switch t := 0; t := x.(T) { ... }
 				//
-				// (this code is not valid Go because the first t will
+				// (this code is not valid Go because the first t
 				// cannot be accessed and thus is never used, the extra
 				// scope is needed for the correct error message).
 				//
@@ -2012,7 +2091,7 @@ func (p *parser) parseStmt() (s ast.Stmt) {
 // ----------------------------------------------------------------------------
 // Declarations
 
-type parseSpecFunction func(p *parser, doc *ast.CommentGroup, iota int) ast.Spec
+type parseSpecFunction func(p *parser, doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
 
 func isValidImport(lit string) bool {
 	const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
@@ -2025,7 +2104,7 @@ func isValidImport(lit string) bool {
 	return s != ""
 }
 
-func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
+func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
 	if p.trace {
 		defer un(trace(p, "ImportSpec"))
 	}
@@ -2063,15 +2142,15 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
 	return spec
 }
 
-func parseConstSpec(p *parser, doc *ast.CommentGroup, iota int) ast.Spec {
+func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec {
 	if p.trace {
-		defer un(trace(p, "ConstSpec"))
+		defer un(trace(p, keyword.String()+"Spec"))
 	}
 
 	idents := p.parseIdentList()
 	typ := p.tryType()
 	var values []ast.Expr
-	if typ != nil || p.tok == token.ASSIGN || iota == 0 {
+	if p.tok == token.ASSIGN || keyword == token.CONST && (typ != nil || iota == 0) || keyword == token.VAR && typ == nil {
 		p.expect(token.ASSIGN)
 		values = p.parseRhsList()
 	}
@@ -2088,12 +2167,16 @@ func parseConstSpec(p *parser, doc *ast.CommentGroup, iota int) ast.Spec {
 		Values:  values,
 		Comment: p.lineComment,
 	}
-	p.declare(spec, iota, p.topScope, ast.Con, idents...)
+	kind := ast.Con
+	if keyword == token.VAR {
+		kind = ast.Var
+	}
+	p.declare(spec, iota, p.topScope, kind, idents...)
 
 	return spec
 }
 
-func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
+func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
 	if p.trace {
 		defer un(trace(p, "TypeSpec"))
 	}
@@ -2114,36 +2197,6 @@ func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
 	return spec
 }
 
-func parseVarSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
-	if p.trace {
-		defer un(trace(p, "VarSpec"))
-	}
-
-	idents := p.parseIdentList()
-	typ := p.tryType()
-	var values []ast.Expr
-	if typ == nil || p.tok == token.ASSIGN {
-		p.expect(token.ASSIGN)
-		values = p.parseRhsList()
-	}
-	p.expectSemi() // call before accessing p.linecomment
-
-	// Go spec: The scope of a constant or variable identifier declared inside
-	// a function begins at the end of the ConstSpec or VarSpec and ends at
-	// the end of the innermost containing block.
-	// (Global identifiers are resolved in a separate phase after parsing.)
-	spec := &ast.ValueSpec{
-		Doc:     doc,
-		Names:   idents,
-		Type:    typ,
-		Values:  values,
-		Comment: p.lineComment,
-	}
-	p.declare(spec, nil, p.topScope, ast.Var, idents...)
-
-	return spec
-}
-
 func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl {
 	if p.trace {
 		defer un(trace(p, "GenDecl("+keyword.String()+")"))
@@ -2157,12 +2210,12 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen
 		lparen = p.pos
 		p.next()
 		for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ {
-			list = append(list, f(p, p.leadComment, iota))
+			list = append(list, f(p, p.leadComment, keyword, iota))
 		}
 		rparen = p.expect(token.RPAREN)
 		p.expectSemi()
 	} else {
-		list = append(list, f(p, nil, 0))
+		list = append(list, f(p, nil, keyword, 0))
 	}
 
 	return &ast.GenDecl{
@@ -2262,14 +2315,11 @@ func (p *parser) parseDecl(sync func(*parser)) ast.Decl {
 
 	var f parseSpecFunction
 	switch p.tok {
-	case token.CONST:
-		f = parseConstSpec
+	case token.CONST, token.VAR:
+		f = (*parser).parseValueSpec
 
 	case token.TYPE:
-		f = parseTypeSpec
-
-	case token.VAR:
-		f = parseVarSpec
+		f = (*parser).parseTypeSpec
 
 	case token.FUNC:
 		return p.parseFuncDecl()
@@ -2292,6 +2342,12 @@ func (p *parser) parseFile() *ast.File {
 		defer un(trace(p, "File"))
 	}
 
+	// Don't bother parsing the rest if we had errors scanning the first token.
+	// Likely not a Go source file at all.
+	if p.errors.Len() != 0 {
+		return nil
+	}
+
 	// package clause
 	doc := p.leadComment
 	pos := p.expect(token.PACKAGE)
@@ -2303,15 +2359,19 @@ func (p *parser) parseFile() *ast.File {
 	}
 	p.expectSemi()
 
-	var decls []ast.Decl
-
-	// Don't bother parsing the rest if we had errors already.
+	// Don't bother parsing the rest if we had errors parsing the package clause.
 	// Likely not a Go source file at all.
+	if p.errors.Len() != 0 {
+		return nil
+	}
 
-	if p.errors.Len() == 0 && p.mode&PackageClauseOnly == 0 {
+	p.openScope()
+	p.pkgScope = p.topScope
+	var decls []ast.Decl
+	if p.mode&PackageClauseOnly == 0 {
 		// import decls
 		for p.tok == token.IMPORT {
-			decls = append(decls, p.parseGenDecl(token.IMPORT, parseImportSpec))
+			decls = append(decls, p.parseGenDecl(token.IMPORT, (*parser).parseImportSpec))
 		}
 
 		if p.mode&ImportsOnly == 0 {
@@ -2321,8 +2381,9 @@ func (p *parser) parseFile() *ast.File {
 			}
 		}
 	}
-
-	assert(p.topScope == p.pkgScope, "imbalanced scopes")
+	p.closeScope()
+	assert(p.topScope == nil, "unbalanced scopes")
+	assert(p.labelScope == nil, "unbalanced label scopes")
 
 	// resolve global identifiers within the same file
 	i := 0
diff --git a/src/pkg/go/parser/parser_test.go b/src/pkg/go/parser/parser_test.go
index 1b7a41b..1960377 100644
--- a/src/pkg/go/parser/parser_test.go
+++ b/src/pkg/go/parser/parser_test.go
@@ -135,6 +135,53 @@ func TestVarScope(t *testing.T) {
 	}
 }
 
+func TestObjects(t *testing.T) {
+	const src = `
+package p
+import fmt "fmt"
+const pi = 3.14
+type T struct{}
+var x int
+func f() { L: }
+`
+
+	f, err := ParseFile(fset, "", src, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	objects := map[string]ast.ObjKind{
+		"p":   ast.Bad, // not in a scope
+		"fmt": ast.Bad, // not resolved yet
+		"pi":  ast.Con,
+		"T":   ast.Typ,
+		"x":   ast.Var,
+		"int": ast.Bad, // not resolved yet
+		"f":   ast.Fun,
+		"L":   ast.Lbl,
+	}
+
+	ast.Inspect(f, func(n ast.Node) bool {
+		if ident, ok := n.(*ast.Ident); ok {
+			obj := ident.Obj
+			if obj == nil {
+				if objects[ident.Name] != ast.Bad {
+					t.Errorf("no object for %s", ident.Name)
+				}
+				return true
+			}
+			if obj.Name != ident.Name {
+				t.Errorf("names don't match: obj.Name = %s, ident.Name = %s", obj.Name, ident.Name)
+			}
+			kind := objects[ident.Name]
+			if obj.Kind != kind {
+				t.Errorf("%s: obj.Kind = %s; want %s", ident.Name, obj.Kind, kind)
+			}
+		}
+		return true
+	})
+}
+
 func TestUnresolved(t *testing.T) {
 	f, err := ParseFile(fset, "", `
 package p
diff --git a/src/pkg/go/parser/performance_test.go b/src/pkg/go/parser/performance_test.go
new file mode 100644
index 0000000..f2732c0
--- /dev/null
+++ b/src/pkg/go/parser/performance_test.go
@@ -0,0 +1,30 @@
+// 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 parser
+
+import (
+	"go/token"
+	"io/ioutil"
+	"testing"
+)
+
+var src = readFile("parser.go")
+
+func readFile(filename string) []byte {
+	data, err := ioutil.ReadFile(filename)
+	if err != nil {
+		panic(err)
+	}
+	return data
+}
+
+func BenchmarkParse(b *testing.B) {
+	b.SetBytes(int64(len(src)))
+	for i := 0; i < b.N; i++ {
+		if _, err := ParseFile(token.NewFileSet(), "", src, ParseComments); err != nil {
+			b.Fatalf("benchmark failed due to parse error: %s", err)
+		}
+	}
+}
diff --git a/src/pkg/go/parser/short_test.go b/src/pkg/go/parser/short_test.go
index 238492b..c62f7e0 100644
--- a/src/pkg/go/parser/short_test.go
+++ b/src/pkg/go/parser/short_test.go
@@ -13,8 +13,10 @@ var valids = []string{
 	`package p;`,
 	`package p; import "fmt"; func f() { fmt.Println("Hello, World!") };`,
 	`package p; func f() { if f(T{}) {} };`,
-	`package p; func f() { _ = (<-chan int)(x) };`,
-	`package p; func f() { _ = (<-chan <-chan int)(x) };`,
+	`package p; func f() { _ = <-chan int(nil) };`,
+	`package p; func f() { _ = (<-chan int)(nil) };`,
+	`package p; func f() { _ = (<-chan <-chan int)(nil) };`,
+	`package p; func f() { _ = <-chan <-chan <-chan <-chan <-int(nil) };`,
 	`package p; func f(func() func() func());`,
 	`package p; func f(...T);`,
 	`package p; func f(float, ...int);`,
@@ -64,8 +66,11 @@ var invalids = []string{
 	`package p; var a = []int{[ /* ERROR "expected expression" */ ]int};`,
 	`package p; var a = ( /* ERROR "expected expression" */ []int);`,
 	`package p; var a = a[[ /* ERROR "expected expression" */ ]int:[]int];`,
-	`package p; var a = <-  /* ERROR "expected expression" */ chan int;`,
-	`package p; func f() { select { case _ <- chan  /* ERROR "expected expression" */ int: } };`,
+	`package p; var a = <- /* ERROR "expected expression" */ chan int;`,
+	`package p; func f() { select { case _ <- chan /* ERROR "expected expression" */ int: } };`,
+	`package p; func f() { _ = (<-<- /* ERROR "expected 'chan'" */ chan int)(nil) };`,
+	`package p; func f() { _ = (<-chan<-chan<-chan<-chan<-chan<- /* ERROR "expected channel type" */ int)(nil) };`,
+	`package p; func f() { var t []int; t /* ERROR "expected identifier on left side of :=" */ [0] := 0 };`,
 }
 
 func TestInvalid(t *testing.T) {
diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go
index f13f9a5..ee0bbf1 100644
--- a/src/pkg/go/printer/nodes.go
+++ b/src/pkg/go/printer/nodes.go
@@ -83,7 +83,7 @@ func (p *printer) setComment(g *ast.CommentGroup) {
 	// don't overwrite any pending comment in the p.comment cache
 	// (there may be a pending comment when a line comment is
 	// immediately followed by a lead comment with no other
-	// tokens inbetween)
+	// tokens between)
 	if p.commentOffset == infinity {
 		p.nextComment() // get comment ready for use
 	}
@@ -203,7 +203,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 			} else {
 				const r = 4 // threshold
 				ratio := float64(size) / float64(prevSize)
-				useFF = ratio <= 1/r || r <= ratio
+				useFF = ratio <= 1.0/r || r <= ratio
 			}
 		}
 
@@ -307,7 +307,7 @@ func (p *printer) parameters(fields *ast.FieldList) {
 				p.print(blank)
 			}
 			// parameter type
-			p.expr(par.Type)
+			p.expr(stripParensAlways(par.Type))
 			prevLine = parLineEnd
 		}
 		// if the closing ")" is on a separate line from the last parameter,
@@ -325,13 +325,18 @@ func (p *printer) parameters(fields *ast.FieldList) {
 }
 
 func (p *printer) signature(params, result *ast.FieldList) {
-	p.parameters(params)
+	if params != nil {
+		p.parameters(params)
+	} else {
+		p.print(token.LPAREN, token.RPAREN)
+	}
 	n := result.NumFields()
 	if n > 0 {
+		// result != nil
 		p.print(blank)
 		if n == 1 && result.List[0].Names == nil {
 			// single anonymous result; no ()'s
-			p.expr(result.List[0].Type)
+			p.expr(stripParensAlways(result.List[0].Type))
 			return
 		}
 		p.parameters(result)
@@ -725,7 +730,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 
 	case *ast.FuncLit:
 		p.expr(x.Type)
-		p.funcBody(x.Body, p.distance(x.Type.Pos(), p.pos), true)
+		p.adjBlock(p.distanceFrom(x.Type.Pos()), blank, x.Body)
 
 	case *ast.ParenExpr:
 		if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
@@ -786,7 +791,14 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 		if len(x.Args) > 1 {
 			depth++
 		}
-		p.expr1(x.Fun, token.HighestPrec, depth)
+		if _, ok := x.Fun.(*ast.FuncType); ok {
+			// conversions to literal function types require parentheses around the type
+			p.print(token.LPAREN)
+			p.expr1(x.Fun, token.HighestPrec, depth)
+			p.print(token.RPAREN)
+		} else {
+			p.expr1(x.Fun, token.HighestPrec, depth)
+		}
 		p.print(x.Lparen, token.LPAREN)
 		if x.Ellipsis.IsValid() {
 			p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis)
@@ -848,9 +860,9 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 		case ast.SEND | ast.RECV:
 			p.print(token.CHAN)
 		case ast.RECV:
-			p.print(token.ARROW, token.CHAN)
+			p.print(token.ARROW, token.CHAN) // x.Arrow and x.Pos() are the same
 		case ast.SEND:
-			p.print(token.CHAN, token.ARROW)
+			p.print(token.CHAN, x.Arrow, token.ARROW)
 		}
 		p.print(blank)
 		p.expr(x.Value)
@@ -877,30 +889,38 @@ func (p *printer) expr(x ast.Expr) {
 // Print the statement list indented, but without a newline after the last statement.
 // Extra line breaks between statements in the source are respected but at most one
 // empty line is printed between statements.
-func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
-	// TODO(gri): fix _indent code
-	if _indent > 0 {
+func (p *printer) stmtList(list []ast.Stmt, nindent int, nextIsRBrace bool) {
+	if nindent > 0 {
 		p.print(indent)
 	}
 	multiLine := false
-	for i, s := range list {
-		// _indent == 0 only for lists of switch/select case clauses;
-		// in those cases each clause is a new section
-		p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || _indent == 0 || multiLine)
-		p.stmt(s, nextIsRBrace && i == len(list)-1)
-		multiLine = p.isMultiLine(s)
-	}
-	if _indent > 0 {
+	i := 0
+	for _, s := range list {
+		// ignore empty statements (was issue 3466)
+		if _, isEmpty := s.(*ast.EmptyStmt); !isEmpty {
+			// _indent == 0 only for lists of switch/select case clauses;
+			// in those cases each clause is a new section
+			if len(p.output) > 0 {
+				// only print line break if we are not at the beginning of the output
+				// (i.e., we are not printing only a partial program)
+				p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || nindent == 0 || multiLine)
+			}
+			p.stmt(s, nextIsRBrace && i == len(list)-1)
+			multiLine = p.isMultiLine(s)
+			i++
+		}
+	}
+	if nindent > 0 {
 		p.print(unindent)
 	}
 }
 
 // block prints an *ast.BlockStmt; it always spans at least two lines.
-func (p *printer) block(s *ast.BlockStmt, indent int) {
-	p.print(s.Pos(), token.LBRACE)
-	p.stmtList(s.List, indent, true)
-	p.linebreak(p.lineFor(s.Rbrace), 1, ignore, true)
-	p.print(s.Rbrace, token.RBRACE)
+func (p *printer) block(b *ast.BlockStmt, nindent int) {
+	p.print(b.Lbrace, token.LBRACE)
+	p.stmtList(b.List, nindent, true)
+	p.linebreak(p.lineFor(b.Rbrace), 1, ignore, true)
+	p.print(b.Rbrace, token.RBRACE)
 }
 
 func isTypeName(x ast.Expr) bool {
@@ -939,6 +959,13 @@ func stripParens(x ast.Expr) ast.Expr {
 	return x
 }
 
+func stripParensAlways(x ast.Expr) ast.Expr {
+	if x, ok := x.(*ast.ParenExpr); ok {
+		return stripParensAlways(x.X)
+	}
+	return x
+}
+
 func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, post ast.Stmt) {
 	p.print(blank)
 	needsBlank := false
@@ -1405,19 +1432,19 @@ func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
 	return
 }
 
-func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool {
+// bodySize is like nodeSize but it is specialized for *ast.BlockStmt's.
+func (p *printer) bodySize(b *ast.BlockStmt, maxSize int) int {
 	pos1 := b.Pos()
 	pos2 := b.Rbrace
 	if pos1.IsValid() && pos2.IsValid() && p.lineFor(pos1) != p.lineFor(pos2) {
 		// opening and closing brace are on different lines - don't make it a one-liner
-		return false
+		return maxSize + 1
 	}
 	if len(b.List) > 5 || p.commentBefore(p.posFor(pos2)) {
 		// too many statements or there is a comment inside - don't make it a one-liner
-		return false
+		return maxSize + 1
 	}
 	// otherwise, estimate body size
-	const maxSize = 100
 	bodySize := 0
 	for i, s := range b.List {
 		if i > 0 {
@@ -1425,19 +1452,23 @@ func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool {
 		}
 		bodySize += p.nodeSize(s, maxSize)
 	}
-	return headerSize+bodySize <= maxSize
+	return bodySize
 }
 
-func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool) {
+// adjBlock prints an "adjacent" block (e.g., a for-loop or function body) following
+// a header (e.g., a for-loop control clause or function signature) of given headerSize.
+// If the header's and block's size are "small enough" and the block is "simple enough",
+// the block is printed on the current line, without line breaks, spaced from the header
+// by sep. Otherwise the block's opening "{" is printed on the current line, followed by
+// lines for the block's statements and its closing "}".
+//
+func (p *printer) adjBlock(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
 	if b == nil {
 		return
 	}
 
-	if p.isOneLineFunc(b, headerSize) {
-		sep := vtab
-		if isLit {
-			sep = blank
-		}
+	const maxSize = 100
+	if headerSize+p.bodySize(b, maxSize) <= maxSize {
 		p.print(sep, b.Lbrace, token.LBRACE)
 		if len(b.List) > 0 {
 			p.print(blank)
@@ -1453,17 +1484,20 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool) {
 		return
 	}
 
-	p.print(blank)
+	if sep != ignore {
+		p.print(blank) // always use blank
+	}
 	p.block(b, 1)
 }
 
-// distance returns the column difference between from and to if both
-// are on the same line; if they are on different lines (or unknown)
-// the result is infinity.
-func (p *printer) distance(from0 token.Pos, to token.Position) int {
-	from := p.posFor(from0)
-	if from.IsValid() && to.IsValid() && from.Line == to.Line {
-		return to.Column - from.Column
+// distanceFrom returns the column difference between from and p.pos (the current
+// estimated position) if both are on the same line; if they are on different lines
+// (or unknown) the result is infinity.
+func (p *printer) distanceFrom(from token.Pos) int {
+	if from.IsValid() && p.pos.IsValid() {
+		if f := p.posFor(from); f.Line == p.pos.Line {
+			return p.pos.Column - f.Column
+		}
 	}
 	return infinity
 }
@@ -1477,7 +1511,7 @@ func (p *printer) funcDecl(d *ast.FuncDecl) {
 	}
 	p.expr(d.Name)
 	p.signature(d.Type.Params, d.Type.Results)
-	p.funcBody(d.Body, p.distance(d.Pos(), p.pos), false)
+	p.adjBlock(p.distanceFrom(d.Pos()), vtab, d.Body)
 }
 
 func (p *printer) decl(decl ast.Decl) {
@@ -1507,31 +1541,35 @@ func declToken(decl ast.Decl) (tok token.Token) {
 	return
 }
 
-func (p *printer) file(src *ast.File) {
-	p.setComment(src.Doc)
-	p.print(src.Pos(), token.PACKAGE, blank)
-	p.expr(src.Name)
-
-	if len(src.Decls) > 0 {
-		tok := token.ILLEGAL
-		for _, d := range src.Decls {
-			prev := tok
-			tok = declToken(d)
-			// if the declaration token changed (e.g., from CONST to TYPE)
-			// or the next declaration has documentation associated with it,
-			// print an empty line between top-level declarations
-			// (because p.linebreak is called with the position of d, which
-			// is past any documentation, the minimum requirement is satisfied
-			// even w/o the extra getDoc(d) nil-check - leave it in case the
-			// linebreak logic improves - there's already a TODO).
+func (p *printer) declList(list []ast.Decl) {
+	tok := token.ILLEGAL
+	for _, d := range list {
+		prev := tok
+		tok = declToken(d)
+		// If the declaration token changed (e.g., from CONST to TYPE)
+		// or the next declaration has documentation associated with it,
+		// print an empty line between top-level declarations.
+		// (because p.linebreak is called with the position of d, which
+		// is past any documentation, the minimum requirement is satisfied
+		// even w/o the extra getDoc(d) nil-check - leave it in case the
+		// linebreak logic improves - there's already a TODO).
+		if len(p.output) > 0 {
+			// only print line break if we are not at the beginning of the output
+			// (i.e., we are not printing only a partial program)
 			min := 1
 			if prev != tok || getDoc(d) != nil {
 				min = 2
 			}
 			p.linebreak(p.lineFor(d.Pos()), min, ignore, false)
-			p.decl(d)
 		}
+		p.decl(d)
 	}
+}
 
+func (p *printer) file(src *ast.File) {
+	p.setComment(src.Doc)
+	p.print(src.Pos(), token.PACKAGE, blank)
+	p.expr(src.Name)
+	p.declList(src.Decls)
 	p.print(newline)
 }
diff --git a/src/pkg/go/printer/performance_test.go b/src/pkg/go/printer/performance_test.go
index 0c6a4e7..5b29aff 100644
--- a/src/pkg/go/printer/performance_test.go
+++ b/src/pkg/go/printer/performance_test.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // This file implements a simple printer performance benchmark:
-// go test -bench=BenchmarkPrint 
+// go test -bench=BenchmarkPrint
 
 package printer
 
@@ -20,7 +20,7 @@ import (
 var testfile *ast.File
 
 func testprint(out io.Writer, file *ast.File) {
-	if err := (&Config{TabIndent | UseSpaces, 8}).Fprint(out, fset, file); err != nil {
+	if err := (&Config{TabIndent | UseSpaces, 8, 0}).Fprint(out, fset, file); err != nil {
 		log.Fatalf("print error: %s", err)
 	}
 }
diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go
index a027d32..3c8d23e 100644
--- a/src/pkg/go/printer/printer.go
+++ b/src/pkg/go/printer/printer.go
@@ -14,6 +14,7 @@ import (
 	"strconv"
 	"strings"
 	"text/tabwriter"
+	"unicode"
 )
 
 const (
@@ -164,15 +165,15 @@ func (p *printer) atLineBegin(pos token.Position) {
 	// write indentation
 	// use "hard" htabs - indentation columns
 	// must not be discarded by the tabwriter
-	for i := 0; i < p.indent; i++ {
+	n := p.Config.Indent + p.indent // include base indentation
+	for i := 0; i < n; i++ {
 		p.output = append(p.output, '\t')
 	}
 
 	// update positions
-	i := p.indent
-	p.pos.Offset += i
-	p.pos.Column += i
-	p.out.Column += i
+	p.pos.Offset += n
+	p.pos.Column += n
+	p.out.Column += n
 }
 
 // writeByte writes ch n times to p.output and updates p.pos.
@@ -220,14 +221,6 @@ func (p *printer) writeString(pos token.Position, s string, isLit bool) {
 		// atLineBegin updates p.pos if there's indentation, but p.pos
 		// is the position of s.
 		p.pos = pos
-		// reset state if the file changed
-		// (used when printing merged ASTs of different files
-		// e.g., the result of ast.MergePackageFiles)
-		if p.last.IsValid() && p.last.Filename != pos.Filename {
-			p.indent = 0
-			p.mode = 0
-			p.wsbuf = p.wsbuf[0:0]
-		}
 	}
 
 	if isLit {
@@ -405,6 +398,7 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, prev, comment *as
 // Split comment text into lines
 // (using strings.Split(text, "\n") is significantly slower for
 // this specific purpose, as measured with: go test -bench=Print)
+//
 func split(text string) []string {
 	// count lines (comment text never ends in a newline)
 	n := 1
@@ -432,6 +426,7 @@ func split(text string) []string {
 
 // Returns true if s contains only white space
 // (only tabs and blanks can appear in the printer's context).
+//
 func isBlank(s string) bool {
 	for i := 0; i < len(s); i++ {
 		if s[i] > ' ' {
@@ -441,6 +436,7 @@ func isBlank(s string) bool {
 	return true
 }
 
+// commonPrefix returns the common prefix of a and b.
 func commonPrefix(a, b string) string {
 	i := 0
 	for i < len(a) && i < len(b) && a[i] == b[i] && (a[i] <= ' ' || a[i] == '*') {
@@ -449,11 +445,22 @@ func commonPrefix(a, b string) string {
 	return a[0:i]
 }
 
+// trimRight returns s with trailing whitespace removed.
+func trimRight(s string) string {
+	return strings.TrimRightFunc(s, unicode.IsSpace)
+}
+
+// stripCommonPrefix removes a common prefix from /*-style comment lines (unless no
+// comment line is indented, all but the first line have some form of space prefix).
+// The prefix is computed using heuristics such that is likely that the comment
+// contents are nicely laid out after re-printing each line using the printer's
+// current indentation.
+//
 func stripCommonPrefix(lines []string) {
-	if len(lines) < 2 {
+	if len(lines) <= 1 {
 		return // at most one line - nothing to do
 	}
-	// len(lines) >= 2
+	// len(lines) > 1
 
 	// The heuristic in this function tries to handle a few
 	// common patterns of /*-style comments: Comments where
@@ -479,7 +486,7 @@ func stripCommonPrefix(lines []string) {
 		for i, line := range lines[1 : len(lines)-1] {
 			switch {
 			case isBlank(line):
-				lines[1+i] = "" // range starts at line 1
+				lines[1+i] = "" // range starts with lines[1]
 			case first:
 				prefix = commonPrefix(line, line)
 				first = false
@@ -544,9 +551,7 @@ func stripCommonPrefix(lines []string) {
 			}
 			// Shorten the computed common prefix by the length of
 			// suffix, if it is found as suffix of the prefix.
-			if strings.HasSuffix(prefix, string(suffix)) {
-				prefix = prefix[0 : len(prefix)-len(suffix)]
-			}
+			prefix = strings.TrimSuffix(prefix, string(suffix))
 		}
 	}
 
@@ -570,9 +575,9 @@ func stripCommonPrefix(lines []string) {
 	}
 
 	// Remove the common prefix from all but the first and empty lines.
-	for i, line := range lines[1:] {
-		if len(line) != 0 {
-			lines[1+i] = line[len(prefix):] // range starts at line 1
+	for i, line := range lines {
+		if i > 0 && line != "" {
+			lines[i] = line[len(prefix):]
 		}
 	}
 }
@@ -605,13 +610,26 @@ func (p *printer) writeComment(comment *ast.Comment) {
 
 	// shortcut common case of //-style comments
 	if text[1] == '/' {
-		p.writeString(pos, text, true)
+		p.writeString(pos, trimRight(text), true)
 		return
 	}
 
 	// for /*-style comments, print line by line and let the
 	// write function take care of the proper indentation
 	lines := split(text)
+
+	// The comment started in the first column but is going
+	// to be indented. For an idempotent result, add indentation
+	// to all lines such that they look like they were indented
+	// before - this will make sure the common prefix computation
+	// is the same independent of how many times formatting is
+	// applied (was issue 1835).
+	if pos.IsValid() && pos.Column == 1 && p.indent > 0 {
+		for i, line := range lines[1:] {
+			lines[1+i] = "   " + line
+		}
+	}
+
 	stripCommonPrefix(lines)
 
 	// write comment lines, separated by formfeed,
@@ -622,7 +640,7 @@ func (p *printer) writeComment(comment *ast.Comment) {
 			pos = p.pos
 		}
 		if len(line) > 0 {
-			p.writeString(pos, line, true)
+			p.writeString(pos, trimRight(line), true)
 		}
 	}
 }
@@ -1012,9 +1030,9 @@ func (p *printer) printNode(node interface{}) error {
 	case ast.Expr:
 		p.expr(n)
 	case ast.Stmt:
-		// A labeled statement will un-indent to position the
-		// label. Set indent to 1 so we don't get indent "underflow".
-		if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt {
+		// A labeled statement will un-indent to position the label.
+		// Set p.indent to 1 so we don't get indent "underflow".
+		if _, ok := n.(*ast.LabeledStmt); ok {
 			p.indent = 1
 		}
 		p.stmt(n, false)
@@ -1022,6 +1040,17 @@ func (p *printer) printNode(node interface{}) error {
 		p.decl(n)
 	case ast.Spec:
 		p.spec(n, 1, false)
+	case []ast.Stmt:
+		// A labeled statement will un-indent to position the label.
+		// Set p.indent to 1 so we don't get indent "underflow".
+		for _, s := range n {
+			if _, ok := s.(*ast.LabeledStmt); ok {
+				p.indent = 1
+			}
+		}
+		p.stmtList(n, 0, false)
+	case []ast.Decl:
+		p.declList(n)
 	case *ast.File:
 		p.file(n)
 	default:
@@ -1140,7 +1169,7 @@ func (p *trimmer) Write(data []byte) (n int, err error) {
 // ----------------------------------------------------------------------------
 // Public interface
 
-// A Mode value is a set of flags (or 0). They coontrol printing. 
+// A Mode value is a set of flags (or 0). They control printing.
 type Mode uint
 
 const (
@@ -1154,6 +1183,7 @@ const (
 type Config struct {
 	Mode     Mode // default: 0
 	Tabwidth int  // default: 8
+	Indent   int  // default: 0 (all code is indented at least by this much)
 }
 
 // fprint implements Fprint and takes a nodesSizes map for setting up the printer state.
@@ -1198,7 +1228,7 @@ func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{
 	}
 
 	// flush tabwriter, if any
-	if tw, _ := (output).(*tabwriter.Writer); tw != nil {
+	if tw, _ := output.(*tabwriter.Writer); tw != nil {
 		err = tw.Flush()
 	}
 
@@ -1215,8 +1245,8 @@ type CommentedNode struct {
 
 // Fprint "pretty-prints" an AST node to output for a given configuration cfg.
 // Position information is interpreted relative to the file set fset.
-// The node type must be *ast.File, *CommentedNode, or assignment-compatible
-// to ast.Expr, ast.Decl, ast.Spec, or ast.Stmt.
+// The node type must be *ast.File, *CommentedNode, []ast.Decl, []ast.Stmt,
+// or assignment-compatible to ast.Expr, ast.Decl, ast.Spec, or ast.Stmt.
 //
 func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{}) error {
 	return cfg.fprint(output, fset, node, make(map[ast.Node]int))
diff --git a/src/pkg/go/printer/printer_test.go b/src/pkg/go/printer/printer_test.go
index 497d671..8454ac1 100644
--- a/src/pkg/go/printer/printer_test.go
+++ b/src/pkg/go/printer/printer_test.go
@@ -6,7 +6,9 @@ package printer
 
 import (
 	"bytes"
+	"errors"
 	"flag"
+	"fmt"
 	"go/ast"
 	"go/parser"
 	"go/token"
@@ -25,33 +27,28 @@ var update = flag.Bool("update", false, "update golden files")
 
 var fset = token.NewFileSet()
 
-func lineString(text []byte, i int) string {
-	i0 := i
-	for i < len(text) && text[i] != '\n' {
-		i++
-	}
-	return string(text[i0:i])
-}
-
 type checkMode uint
 
 const (
 	export checkMode = 1 << iota
 	rawFormat
+	idempotent
 )
 
-func runcheck(t *testing.T, source, golden string, mode checkMode) {
-	// parse source
-	prog, err := parser.ParseFile(fset, source, nil, parser.ParseComments)
+// format parses src, prints the corresponding AST, verifies the resulting
+// src is syntactically correct, and returns the resulting src or an error
+// if any.
+func format(src []byte, mode checkMode) ([]byte, error) {
+	// parse src
+	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
 	if err != nil {
-		t.Error(err)
-		return
+		return nil, fmt.Errorf("parse: %s\n%s", err, src)
 	}
 
 	// filter exports if necessary
 	if mode&export != 0 {
-		ast.FileExports(prog) // ignore result
-		prog.Comments = nil   // don't print comments that are not in AST
+		ast.FileExports(f) // ignore result
+		f.Comments = nil   // don't print comments that are not in AST
 	}
 
 	// determine printer configuration
@@ -60,17 +57,72 @@ func runcheck(t *testing.T, source, golden string, mode checkMode) {
 		cfg.Mode |= RawFormat
 	}
 
-	// format source
+	// print AST
 	var buf bytes.Buffer
-	if err := cfg.Fprint(&buf, fset, prog); err != nil {
-		t.Error(err)
+	if err := cfg.Fprint(&buf, fset, f); err != nil {
+		return nil, fmt.Errorf("print: %s", err)
 	}
-	res := buf.Bytes()
 
-	// formatted source must be valid
+	// make sure formated output is syntactically correct
+	res := buf.Bytes()
 	if _, err := parser.ParseFile(fset, "", res, 0); err != nil {
+		return nil, fmt.Errorf("re-parse: %s\n%s", err, buf.Bytes())
+	}
+
+	return res, nil
+}
+
+// lineAt returns the line in text starting at offset offs.
+func lineAt(text []byte, offs int) []byte {
+	i := offs
+	for i < len(text) && text[i] != '\n' {
+		i++
+	}
+	return text[offs:i]
+}
+
+// diff compares a and b.
+func diff(aname, bname string, a, b []byte) error {
+	var buf bytes.Buffer // holding long error message
+
+	// compare lengths
+	if len(a) != len(b) {
+		fmt.Fprintf(&buf, "\nlength changed: len(%s) = %d, len(%s) = %d", aname, len(a), bname, len(b))
+	}
+
+	// compare contents
+	line := 1
+	offs := 1
+	for i := 0; i < len(a) && i < len(b); i++ {
+		ch := a[i]
+		if ch != b[i] {
+			fmt.Fprintf(&buf, "\n%s:%d:%d: %s", aname, line, i-offs+1, lineAt(a, offs))
+			fmt.Fprintf(&buf, "\n%s:%d:%d: %s", bname, line, i-offs+1, lineAt(b, offs))
+			fmt.Fprintf(&buf, "\n\n")
+			break
+		}
+		if ch == '\n' {
+			line++
+			offs = i + 1
+		}
+	}
+
+	if buf.Len() > 0 {
+		return errors.New(buf.String())
+	}
+	return nil
+}
+
+func runcheck(t *testing.T, source, golden string, mode checkMode) {
+	src, err := ioutil.ReadFile(source)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	res, err := format(src, mode)
+	if err != nil {
 		t.Error(err)
-		t.Logf("\n%s", res)
 		return
 	}
 
@@ -89,23 +141,19 @@ func runcheck(t *testing.T, source, golden string, mode checkMode) {
 		return
 	}
 
-	// compare lengths
-	if len(res) != len(gld) {
-		t.Errorf("len = %d, expected %d (= len(%s))", len(res), len(gld), golden)
+	// formatted source and golden must be the same
+	if err := diff(source, golden, res, gld); err != nil {
+		t.Error(err)
+		return
 	}
 
-	// compare contents
-	for i, line, offs := 0, 1, 0; i < len(res) && i < len(gld); i++ {
-		ch := res[i]
-		if ch != gld[i] {
-			t.Errorf("%s:%d:%d: %s", source, line, i-offs+1, lineString(res, offs))
-			t.Errorf("%s:%d:%d: %s", golden, line, i-offs+1, lineString(gld, offs))
-			t.Error()
-			return
-		}
-		if ch == '\n' {
-			line++
-			offs = i + 1
+	if mode&idempotent != 0 {
+		// formatting golden must be idempotent
+		// (This is very difficult to achieve in general and for now
+		// it is only checked for files explicitly marked as such.)
+		res, err = format(gld, mode)
+		if err := diff(golden, fmt.Sprintf("format(%s)", golden), gld, res); err != nil {
+			t.Errorf("golden is not idempotent: %s", err)
 		}
 	}
 }
@@ -142,15 +190,16 @@ type entry struct {
 
 // Use go test -update to create/update the respective golden files.
 var data = []entry{
-	{"empty.input", "empty.golden", 0},
+	{"empty.input", "empty.golden", idempotent},
 	{"comments.input", "comments.golden", 0},
 	{"comments.input", "comments.x", export},
-	{"linebreaks.input", "linebreaks.golden", 0},
-	{"expressions.input", "expressions.golden", 0},
-	{"expressions.input", "expressions.raw", rawFormat},
+	{"comments2.input", "comments2.golden", idempotent},
+	{"linebreaks.input", "linebreaks.golden", idempotent},
+	{"expressions.input", "expressions.golden", idempotent},
+	{"expressions.input", "expressions.raw", rawFormat | idempotent},
 	{"declarations.input", "declarations.golden", 0},
 	{"statements.input", "statements.golden", 0},
-	{"slow.input", "slow.golden", 0},
+	{"slow.input", "slow.golden", idempotent},
 }
 
 func TestFiles(t *testing.T) {
@@ -248,7 +297,7 @@ func testComment(t *testing.T, f *ast.File, srclen int, comment *ast.Comment) {
 	}
 }
 
-// Verify that the printer produces always produces a correct program
+// Verify that the printer produces a correct program
 // even if the position information of comments introducing newlines
 // is incorrect.
 func TestBadComments(t *testing.T) {
@@ -385,28 +434,136 @@ func (t *t) foo(a, b, c int) int {
 	}
 }
 
-// TextX is a skeleton test that can be filled in for debugging one-off cases.
-// Do not remove.
-func TestX(t *testing.T) {
-	const src = `
-package p
-func _() {}
-`
-	// parse original
-	f, err := parser.ParseFile(fset, "src", src, parser.ParseComments)
+var decls = []string{
+	`import "fmt"`,
+	"const pi = 3.1415\nconst e = 2.71828\n\nvar x = pi",
+	"func sum(x, y int) int\t{ return x + y }",
+}
+
+func TestDeclLists(t *testing.T) {
+	for _, src := range decls {
+		file, err := parser.ParseFile(fset, "", "package p;"+src, parser.ParseComments)
+		if err != nil {
+			panic(err) // error in test
+		}
+
+		var buf bytes.Buffer
+		err = Fprint(&buf, fset, file.Decls) // only print declarations
+		if err != nil {
+			panic(err) // error in test
+		}
+
+		out := buf.String()
+		if out != src {
+			t.Errorf("\ngot : %q\nwant: %q\n", out, src)
+		}
+	}
+}
+
+var stmts = []string{
+	"i := 0",
+	"select {}\nvar a, b = 1, 2\nreturn a + b",
+	"go f()\ndefer func() {}()",
+}
+
+func TestStmtLists(t *testing.T) {
+	for _, src := range stmts {
+		file, err := parser.ParseFile(fset, "", "package p; func _() {"+src+"}", parser.ParseComments)
+		if err != nil {
+			panic(err) // error in test
+		}
+
+		var buf bytes.Buffer
+		err = Fprint(&buf, fset, file.Decls[0].(*ast.FuncDecl).Body.List) // only print statements
+		if err != nil {
+			panic(err) // error in test
+		}
+
+		out := buf.String()
+		if out != src {
+			t.Errorf("\ngot : %q\nwant: %q\n", out, src)
+		}
+	}
+}
+
+func TestBaseIndent(t *testing.T) {
+	// The testfile must not contain multi-line raw strings since those
+	// are not indented (because their values must not change) and make
+	// this test fail.
+	const filename = "printer.go"
+	src, err := ioutil.ReadFile(filename)
 	if err != nil {
-		t.Fatal(err)
+		panic(err) // error in test
+	}
+
+	file, err := parser.ParseFile(fset, filename, src, 0)
+	if err != nil {
+		panic(err) // error in test
+	}
+
+	var buf bytes.Buffer
+	for indent := 0; indent < 4; indent++ {
+		buf.Reset()
+		(&Config{Tabwidth: tabwidth, Indent: indent}).Fprint(&buf, fset, file)
+		// all code must be indented by at least 'indent' tabs
+		lines := bytes.Split(buf.Bytes(), []byte{'\n'})
+		for i, line := range lines {
+			if len(line) == 0 {
+				continue // empty lines don't have indentation
+			}
+			n := 0
+			for j, b := range line {
+				if b != '\t' {
+					// end of indentation
+					n = j
+					break
+				}
+			}
+			if n < indent {
+				t.Errorf("line %d: got only %d tabs; want at least %d: %q", i, n, indent, line)
+			}
+		}
+	}
+}
+
+// TestFuncType tests that an ast.FuncType with a nil Params field
+// can be printed (per go/ast specification). Test case for issue 3870.
+func TestFuncType(t *testing.T) {
+	src := &ast.File{
+		Name: &ast.Ident{Name: "p"},
+		Decls: []ast.Decl{
+			&ast.FuncDecl{
+				Name: &ast.Ident{Name: "f"},
+				Type: &ast.FuncType{},
+			},
+		},
 	}
 
-	// pretty-print original
 	var buf bytes.Buffer
-	if err = (&Config{Mode: UseSpaces, Tabwidth: 8}).Fprint(&buf, fset, f); err != nil {
+	if err := Fprint(&buf, fset, src); err != nil {
 		t.Fatal(err)
 	}
+	got := buf.String()
 
-	// parse pretty printed original
-	if _, err := parser.ParseFile(fset, "", buf.Bytes(), 0); err != nil {
-		t.Fatalf("%s\n%s", err, buf.Bytes())
+	const want = `package p
+
+func f()
+`
+
+	if got != want {
+		t.Fatalf("got:\n%s\nwant:\n%s\n", got, want)
 	}
+}
 
+// TextX is a skeleton test that can be filled in for debugging one-off cases.
+// Do not remove.
+func TestX(t *testing.T) {
+	const src = `
+package p
+func _() {}
+`
+	_, err := format([]byte(src), 0)
+	if err != nil {
+		t.Error(err)
+	}
 }
diff --git a/src/pkg/go/printer/testdata/comments.golden b/src/pkg/go/printer/testdata/comments.golden
index d9aa2d8..610a42a 100644
--- a/src/pkg/go/printer/testdata/comments.golden
+++ b/src/pkg/go/printer/testdata/comments.golden
@@ -529,7 +529,7 @@ func _() {
 }
 
 func _() {
-	var a = []int{1, 2}// jasldf 
+	var a = []int{1, 2}// jasldf
 
 	_ = a
 }
@@ -626,4 +626,13 @@ func _() {
 	var lflag bool		// -l			- disable line directives
 }
 
+// Trailing white space in comments should be trimmed
+func _() {
+	// This comment has 4 blanks following that should be trimmed:
+	/* Each line of this comment has blanks or tabs following that should be trimmed:
+	   line 2:
+	   line 3:
+	*/
+}
+
 /* This comment is the last entry in this file. It must be printed and should be followed by a newline */
diff --git a/src/pkg/go/printer/testdata/comments.input b/src/pkg/go/printer/testdata/comments.input
index 6084b3f..d121dd4 100644
--- a/src/pkg/go/printer/testdata/comments.input
+++ b/src/pkg/go/printer/testdata/comments.input
@@ -534,7 +534,7 @@ func _() {
 }
 
 func _() {
-	var a = []int{1, 2, // jasldf 
+	var a = []int{1, 2, // jasldf
 	}
 	_ = a
 }
@@ -630,5 +630,13 @@ var	vflag		string				// -v [y.output]	- y.output file
 var	lflag		bool				// -l			- disable line directives
 }
 
+// Trailing white space in comments should be trimmed
+func _() {
+// This comment has 4 blanks following that should be trimmed:    
+/* Each line of this comment has blanks or tabs following that should be trimmed:	
+   line 2:    
+   line 3:    			
+*/
+}
 
 /* This comment is the last entry in this file. It must be printed and should be followed by a newline */
diff --git a/src/pkg/go/printer/testdata/comments2.golden b/src/pkg/go/printer/testdata/comments2.golden
new file mode 100644
index 0000000..d3b50bf
--- /dev/null
+++ b/src/pkg/go/printer/testdata/comments2.golden
@@ -0,0 +1,79 @@
+// 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.
+
+// This is a package for testing comment placement by go/printer.
+//
+package main
+
+// Test cases for idempotent comment formatting (was issue 1835).
+/*
+c1a
+*/
+/*
+   c1b
+*/
+/* foo
+c1c
+*/
+/* foo
+   c1d
+*/
+/*
+c1e
+foo */
+/*
+   c1f
+   foo */
+
+func f() {
+	/*
+	   c2a
+	*/
+	/*
+	   c2b
+	*/
+	/* foo
+	   c2c
+	*/
+	/* foo
+	   c2d
+	*/
+	/*
+	   c2e
+	   foo */
+	/*
+	   c2f
+	   foo */
+}
+
+func g() {
+	/*
+	   c3a
+	*/
+	/*
+	   c3b
+	*/
+	/* foo
+	   c3c
+	*/
+	/* foo
+	   c3d
+	*/
+	/*
+	   c3e
+	   foo */
+	/*
+	   c3f
+	   foo */
+}
+
+// Test case taken literally from issue 1835.
+func main() {
+	/*
+	   prints test 5 times
+	*/
+	for i := 0; i < 5; i++ {
+		println("test")
+	}
+}
diff --git a/src/pkg/go/printer/testdata/comments2.input b/src/pkg/go/printer/testdata/comments2.input
new file mode 100644
index 0000000..6f8c85c
--- /dev/null
+++ b/src/pkg/go/printer/testdata/comments2.input
@@ -0,0 +1,79 @@
+// 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.
+
+// This is a package for testing comment placement by go/printer.
+//
+package main
+
+// Test cases for idempotent comment formatting (was issue 1835).
+/*
+c1a
+*/
+/*
+   c1b
+*/
+/* foo
+c1c
+*/
+/* foo
+   c1d
+*/
+/*
+c1e
+foo */
+/*
+   c1f
+   foo */
+
+func f() {
+/*
+c2a
+*/
+/*
+   c2b
+*/
+/* foo
+c2c
+*/
+/* foo
+   c2d
+*/
+/*
+c2e
+foo */
+/*
+   c2f
+   foo */
+}
+
+func g() {
+/*
+c3a
+*/
+/*
+   c3b
+*/
+/* foo
+c3c
+*/
+/* foo
+   c3d
+*/
+/*
+c3e
+foo */
+/*
+   c3f
+   foo */
+}
+
+// Test case taken literally from issue 1835.
+func main() {
+/*
+prints test 5 times
+*/
+   for i := 0; i < 5; i++ {
+      println("test")
+   }
+}
\ No newline at end of file
diff --git a/src/pkg/go/printer/testdata/declarations.golden b/src/pkg/go/printer/testdata/declarations.golden
index 71ed32e..0ad72d3 100644
--- a/src/pkg/go/printer/testdata/declarations.golden
+++ b/src/pkg/go/printer/testdata/declarations.golden
@@ -654,6 +654,35 @@ var _ = map[int]int{
 	abcde:	a,	// align with previous line
 }
 
+// alignment of map composite entries: test cases from issue 3965
+// aligned
+var _ = T1{
+	a:			x,
+	b:			y,
+	cccccccccccccccccccc:	z,
+}
+
+// not aligned
+var _ = T2{
+	a:	x,
+	b:	y,
+	ccccccccccccccccccccc:	z,
+}
+
+// aligned
+var _ = T3{
+	aaaaaaaaaaaaaaaaaaaa:	x,
+	b:			y,
+	c:			z,
+}
+
+// not aligned
+var _ = T4{
+	aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:	x,
+	b:	y,
+	c:	z,
+}
+
 func _() {
 	var _ = T{
 		a,	// must introduce trailing comma
@@ -858,3 +887,28 @@ type _ interface {
 		r string,
 		x ...int)
 }
+
+// omit superfluous parentheses in parameter lists
+func _(int)
+func _(int)
+func _(x int)
+func _(x int)
+func _(x, y int)
+func _(x, y int)
+
+func _() int
+func _() int
+func _() int
+
+func _() (x int)
+func _() (x int)
+func _() (x int)
+
+// special cases: some channel types require parentheses
+func _(x chan (<-chan int))
+func _(x chan (<-chan int))
+func _(x chan (<-chan int))
+
+func _(x chan<- (chan int))
+func _(x chan<- (chan int))
+func _(x chan<- (chan int))
diff --git a/src/pkg/go/printer/testdata/declarations.input b/src/pkg/go/printer/testdata/declarations.input
index d74cff2..455c0c6 100644
--- a/src/pkg/go/printer/testdata/declarations.input
+++ b/src/pkg/go/printer/testdata/declarations.input
@@ -667,6 +667,35 @@ var _ = map[int]int{
 	abcde: a, // align with previous line
 }
 
+// alignment of map composite entries: test cases from issue 3965
+// aligned
+var _ = T1{
+	a:                    x,
+	b:                    y,
+	cccccccccccccccccccc: z,
+}
+
+// not aligned
+var _ = T2{
+	a: x,
+	b: y,
+	ccccccccccccccccccccc: z,
+}
+
+// aligned
+var _ = T3{
+	aaaaaaaaaaaaaaaaaaaa: x,
+	b:                    y,
+	c:                    z,
+}
+
+// not aligned
+var _ = T4{
+	aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: x,
+	b:                                       y,
+	c:                                       z,
+}
+
 
 func _() {
 	var _ = T{
@@ -867,3 +896,28 @@ p, q,
 r string,
 		x ...int)
 }
+
+// omit superfluous parentheses in parameter lists
+func _((int))
+func _((((((int))))))
+func _(x (int))
+func _(x (((((int))))))
+func _(x, y (int))
+func _(x, y (((((int))))))
+
+func _() (int)
+func _() ((int))
+func _() ((((((int))))))
+
+func _() (x int)
+func _() (x (int))
+func _() (x (((((int))))))
+
+// special cases: some channel types require parentheses
+func _(x chan(<-chan int))
+func _(x (chan(<-chan int)))
+func _(x ((((chan(<-chan int))))))
+
+func _(x chan<-(chan int))
+func _(x (chan<-(chan int)))
+func _(x ((((chan<-(chan int))))))
diff --git a/src/pkg/go/printer/testdata/expressions.golden b/src/pkg/go/printer/testdata/expressions.golden
index 45fa4d9..4291c55 100644
--- a/src/pkg/go/printer/testdata/expressions.golden
+++ b/src/pkg/go/printer/testdata/expressions.golden
@@ -647,3 +647,18 @@ func _() {
 		a...,
 	)
 }
+
+// Literal function types in conversions must be parenthesized;
+// for now go/parser accepts the unparenthesized form where it
+// is non-ambiguous.
+func _() {
+	// these conversions should be rewritten to look
+	// the same as the parenthesized conversions below
+	_ = (func())(nil)
+	_ = (func(x int) float)(nil)
+	_ = (func() func() func())(nil)
+
+	_ = (func())(nil)
+	_ = (func(x int) float)(nil)
+	_ = (func() func() func())(nil)
+}
diff --git a/src/pkg/go/printer/testdata/expressions.input b/src/pkg/go/printer/testdata/expressions.input
index f545c66..1ec12a0 100644
--- a/src/pkg/go/printer/testdata/expressions.input
+++ b/src/pkg/go/printer/testdata/expressions.input
@@ -676,3 +676,18 @@ func _() {
 		a...,
 	)
 }
+
+// Literal function types in conversions must be parenthesized;
+// for now go/parser accepts the unparenthesized form where it
+// is non-ambiguous.
+func _() {
+	// these conversions should be rewritten to look
+	// the same as the parenthesized conversions below
+	_ = func()()(nil)
+	_ = func(x int)(float)(nil)
+	_ = func() func() func()()(nil)
+
+	_ = (func()())(nil)
+	_ = (func(x int)(float))(nil)
+	_ = (func() func() func()())(nil)
+}
diff --git a/src/pkg/go/printer/testdata/expressions.raw b/src/pkg/go/printer/testdata/expressions.raw
index 87a4b00..062900e 100644
--- a/src/pkg/go/printer/testdata/expressions.raw
+++ b/src/pkg/go/printer/testdata/expressions.raw
@@ -647,3 +647,18 @@ func _() {
 		a...,
 	)
 }
+
+// Literal function types in conversions must be parenthesized;
+// for now go/parser accepts the unparenthesized form where it
+// is non-ambiguous.
+func _() {
+	// these conversions should be rewritten to look
+	// the same as the parenthesized conversions below
+	_ = (func())(nil)
+	_ = (func(x int) float)(nil)
+	_ = (func() func() func())(nil)
+
+	_ = (func())(nil)
+	_ = (func(x int) float)(nil)
+	_ = (func() func() func())(nil)
+}
diff --git a/src/pkg/go/printer/testdata/statements.golden b/src/pkg/go/printer/testdata/statements.golden
index 4d70617..3b298f9 100644
--- a/src/pkg/go/printer/testdata/statements.golden
+++ b/src/pkg/go/printer/testdata/statements.golden
@@ -241,7 +241,7 @@ func _() {
 	}
 }
 
-// Formatting of for-statement headers.
+// Formatting of for-statement headers for single-line for-loops.
 func _() {
 	for {
 	}
@@ -279,6 +279,86 @@ func _() {
 	}	// no parens printed
 }
 
+// Formatting of for-statement headers for multi-line for-loops.
+func _() {
+	for {
+	}
+	for expr {
+	}
+	for expr {
+	}	// no parens printed
+	for {
+	}	// no semicolons printed
+	for x := expr; ; {
+		use(x)
+	}
+	for expr {
+	}	// no semicolons printed
+	for expr {
+	}	// no semicolons and parens printed
+	for ; ; expr = false {
+	}
+	for x := expr; expr; {
+		use(x)
+	}
+	for x := expr; ; expr = false {
+		use(x)
+	}
+	for ; expr; expr = false {
+	}
+	for x := expr; expr; expr = false {
+		use(x)
+	}
+	for x := range []int{} {
+		use(x)
+	}
+	for x := range []int{} {
+		use(x)
+	}	// no parens printed
+}
+
+// Formatting of selected short single- and multi-line statements.
+func _() {
+	if cond {
+	}
+	if cond {
+	}	// multiple lines
+	if cond {
+	} else {
+	}	// else clause always requires multiple lines
+
+	for {
+	}
+	for i := 0; i < len(a); 1++ {
+	}
+	for i := 0; i < len(a); 1++ {
+		a[i] = i
+	}
+	for i := 0; i < len(a); 1++ {
+		a[i] = i
+	}	// multiple lines
+
+	for i := range a {
+	}
+	for i := range a {
+		a[i] = i
+	}
+	for i := range a {
+		a[i] = i
+	}	// multiple lines
+
+	go func() {
+		for {
+			a <- <-b
+		}
+	}()
+	defer func() {
+		if x := recover(); x != nil {
+			err = fmt.Sprintf("error: %s", x.msg)
+		}
+	}()
+}
+
 // Don't remove mandatory parentheses around composite literals in control clauses.
 func _() {
 	// strip parentheses - no composite literals or composite literals don't start with a type name
@@ -527,3 +607,29 @@ AVeryLongLabelThatShouldNotAffectFormatting:
 	// There should be a single empty line before this comment.
 	MoreCode()
 }
+
+// Formatting of empty statements.
+func _() {
+
+}
+
+func _() {
+}
+
+func _() {
+}
+
+func _() {
+	f()
+}
+
+func _() {
+L:
+	;
+}
+
+func _() {
+L:
+	;
+	f()
+}
diff --git a/src/pkg/go/printer/testdata/statements.input b/src/pkg/go/printer/testdata/statements.input
index bd03bc9..e7fcc0e 100644
--- a/src/pkg/go/printer/testdata/statements.input
+++ b/src/pkg/go/printer/testdata/statements.input
@@ -223,7 +223,7 @@ func _() {
 }
 
 
-// Formatting of for-statement headers.
+// Formatting of for-statement headers for single-line for-loops.
 func _() {
 	for{}
 	for expr {}
@@ -235,14 +235,70 @@ func _() {
 	for; ; expr = false {}
 	for x :=expr; expr; {use(x)}
 	for x := expr;; expr=false {use(x)}
-	for;expr;expr =false {
-	}
+	for;expr;expr =false {}
 	for x := expr;expr;expr = false { use(x) }
 	for x := range []int{} { use(x) }
 	for x := range (([]int{})) { use(x) }  // no parens printed
 }
 
 
+// Formatting of for-statement headers for multi-line for-loops.
+func _() {
+	for{
+	}
+	for expr {
+	}
+	for (expr) {
+	}  // no parens printed
+	for;;{
+	}  // no semicolons printed
+	for x :=expr;; {use( x)
+	}
+	for; expr;{
+	}  // no semicolons printed
+	for; ((expr));{
+	}  // no semicolons and parens printed
+	for; ; expr = false {
+	}
+	for x :=expr; expr; {use(x)
+	}
+	for x := expr;; expr=false {use(x)
+	}
+	for;expr;expr =false {
+	}
+	for x := expr;expr;expr = false {
+	use(x)
+	}
+	for x := range []int{} {
+	use(x) }
+	for x := range (([]int{})) {
+	use(x) }  // no parens printed
+}
+
+
+// Formatting of selected short single- and multi-line statements.
+func _() {
+	if cond {}
+	if cond {
+	} // multiple lines
+	if cond {} else {} // else clause always requires multiple lines
+
+	for {}
+	for i := 0; i < len(a); 1++ {}
+	for i := 0; i < len(a); 1++ { a[i] = i }
+	for i := 0; i < len(a); 1++ { a[i] = i
+	} // multiple lines
+
+	for i := range a {}
+	for i := range a { a[i] = i }
+	for i := range a { a[i] = i
+	} // multiple lines
+
+	go func() { for { a <- <-b } }()
+	defer func() { if x := recover(); x != nil { err = fmt.Sprintf("error: %s", x.msg) } }()
+}
+
+
 // Don't remove mandatory parentheses around composite literals in control clauses.
 func _() {
 	// strip parentheses - no composite literals or composite literals don't start with a type name
@@ -468,3 +524,27 @@ AVeryLongLabelThatShouldNotAffectFormatting:
 	// There should be a single empty line before this comment.
 	MoreCode()
 }
+
+
+// Formatting of empty statements.
+func _() {
+	;;;;;;;;;;;;;;;;;;;;;;;;;
+}
+
+func _() {;;;;;;;;;;;;;;;;;;;;;;;;;
+}
+
+func _() {;;;;;;;;;;;;;;;;;;;;;;;;;}
+
+func _() {
+f();;;;;;;;;;;;;;;;;;;;;;;;;
+}
+
+func _() {
+L:;;;;;;;;;;;;
+}
+
+func _() {
+L:;;;;;;;;;;;;
+	f()
+}
diff --git a/src/pkg/go/scanner/errors.go b/src/pkg/go/scanner/errors.go
index 8a75a96..22de69c 100644
--- a/src/pkg/go/scanner/errors.go
+++ b/src/pkg/go/scanner/errors.go
@@ -120,7 +120,7 @@ func PrintError(w io.Writer, err error) {
 		for _, e := range list {
 			fmt.Fprintf(w, "%s\n", e)
 		}
-	} else {
+	} else if err != nil {
 		fmt.Fprintf(w, "%s\n", err)
 	}
 }
diff --git a/src/pkg/go/scanner/scanner.go b/src/pkg/go/scanner/scanner.go
index da50874..3322c58 100644
--- a/src/pkg/go/scanner/scanner.go
+++ b/src/pkg/go/scanner/scanner.go
@@ -81,7 +81,7 @@ func (s *Scanner) next() {
 	}
 }
 
-// A mode value is set of flags (or 0).
+// A mode value is a set of flags (or 0).
 // They control scanner behavior.
 //
 type Mode uint
@@ -125,6 +125,9 @@ func (s *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode
 	s.ErrorCount = 0
 
 	s.next()
+	if s.ch == '\uFEFF' {
+		s.next() // ignore BOM
+	}
 }
 
 func (s *Scanner) error(offs int, msg string) {
@@ -157,11 +160,15 @@ func (s *Scanner) interpretLineComment(text []byte) {
 func (s *Scanner) scanComment() string {
 	// initial '/' already consumed; s.ch == '/' || s.ch == '*'
 	offs := s.offset - 1 // position of initial '/'
+	hasCR := false
 
 	if s.ch == '/' {
 		//-style comment
 		s.next()
 		for s.ch != '\n' && s.ch >= 0 {
+			if s.ch == '\r' {
+				hasCR = true
+			}
 			s.next()
 		}
 		if offs == s.lineOffset {
@@ -175,6 +182,9 @@ func (s *Scanner) scanComment() string {
 	s.next()
 	for s.ch >= 0 {
 		ch := s.ch
+		if ch == '\r' {
+			hasCR = true
+		}
 		s.next()
 		if ch == '*' && s.ch == '/' {
 			s.next()
@@ -185,7 +195,12 @@ func (s *Scanner) scanComment() string {
 	s.error(offs, "comment not terminated")
 
 exit:
-	return string(s.src[offs:s.offset])
+	lit := s.src[offs:s.offset]
+	if hasCR {
+		lit = stripCR(lit)
+	}
+
+	return string(lit)
 }
 
 func (s *Scanner) findLineEnd() bool {
@@ -378,7 +393,7 @@ func (s *Scanner) scanEscape(quote rune) {
 	for ; i > 0 && s.ch != quote && s.ch >= 0; i-- {
 		s.next()
 	}
-	if x > max || 0xd800 <= x && x < 0xe000 {
+	if x > max || 0xD800 <= x && x < 0xE000 {
 		s.error(offs, "escape sequence is invalid Unicode code point")
 	}
 }
@@ -527,6 +542,8 @@ func (s *Scanner) switch4(tok0, tok1 token.Token, ch2 rune, tok2, tok3 token.Tok
 // token.IMAG, token.CHAR, token.STRING) or token.COMMENT, the literal string
 // has the corresponding value.
 //
+// If the returned token is a keyword, the literal string is the keyword.
+//
 // If the returned token is token.SEMICOLON, the corresponding
 // literal string is ";" if the semicolon was present in the source,
 // and "\n" if the semicolon was inserted because of a newline or
@@ -560,12 +577,18 @@ scanAgain:
 	switch ch := s.ch; {
 	case isLetter(ch):
 		lit = s.scanIdentifier()
-		tok = token.Lookup(lit)
-		switch tok {
-		case token.IDENT, token.BREAK, token.CONTINUE, token.FALLTHROUGH, token.RETURN:
+		if len(lit) > 1 {
+			// keywords are longer than one letter - avoid lookup otherwise
+			tok = token.Lookup(lit)
+			switch tok {
+			case token.IDENT, token.BREAK, token.CONTINUE, token.FALLTHROUGH, token.RETURN:
+				insertSemi = true
+			}
+		} else {
 			insertSemi = true
+			tok = token.IDENT
 		}
-	case digitVal(ch) < 10:
+	case '0' <= ch && ch <= '9':
 		insertSemi = true
 		tok, lit = s.scanNumber(false)
 	default:
@@ -598,7 +621,7 @@ scanAgain:
 		case ':':
 			tok = s.switch2(token.COLON, token.DEFINE)
 		case '.':
-			if digitVal(s.ch) < 10 {
+			if '0' <= s.ch && s.ch <= '9' {
 				insertSemi = true
 				tok, lit = s.scanNumber(true)
 			} else if s.ch == '.' {
diff --git a/src/pkg/go/scanner/scanner_test.go b/src/pkg/go/scanner/scanner_test.go
index 06223e2..1c19053 100644
--- a/src/pkg/go/scanner/scanner_test.go
+++ b/src/pkg/go/scanner/scanner_test.go
@@ -6,6 +6,7 @@ package scanner
 
 import (
 	"go/token"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"runtime"
@@ -43,12 +44,16 @@ var tokens = [...]elt{
 	// Special tokens
 	{token.COMMENT, "/* a comment */", special},
 	{token.COMMENT, "// a comment \n", special},
+	{token.COMMENT, "/*\r*/", special},
+	{token.COMMENT, "//\r\n", special},
 
 	// Identifiers and basic type literals
 	{token.IDENT, "foobar", literal},
 	{token.IDENT, "a۰۱۸", literal},
 	{token.IDENT, "foo६४", literal},
 	{token.IDENT, "bar9876", literal},
+	{token.IDENT, "ŝ", literal},    // was bug (issue 4000)
+	{token.IDENT, "ŝfoo", literal}, // was bug (issue 4000)
 	{token.INT, "0", literal},
 	{token.INT, "1", literal},
 	{token.INT, "123456789012345678890", literal},
@@ -214,8 +219,6 @@ func checkPos(t *testing.T, lit string, p token.Pos, expected token.Position) {
 
 // Verify that calling Scan() provides the correct results.
 func TestScan(t *testing.T) {
-	// make source
-	src_linecount := newlineCount(string(source))
 	whitespace_linecount := newlineCount(whitespace)
 
 	// error handler
@@ -226,59 +229,81 @@ func TestScan(t *testing.T) {
 	// verify scan
 	var s Scanner
 	s.Init(fset.AddFile("", fset.Base(), len(source)), source, eh, ScanComments|dontInsertSemis)
-	index := 0
-	// epos is the expected position
+
+	// set up expected position
 	epos := token.Position{
 		Filename: "",
 		Offset:   0,
 		Line:     1,
 		Column:   1,
 	}
+
+	index := 0
 	for {
 		pos, tok, lit := s.Scan()
-		if lit == "" {
-			// no literal value for non-literal tokens
-			lit = tok.String()
+
+		// check position
+		if tok == token.EOF {
+			// correction for EOF
+			epos.Line = newlineCount(string(source))
+			epos.Column = 2
 		}
+		checkPos(t, lit, pos, epos)
+
+		// check token
 		e := elt{token.EOF, "", special}
 		if index < len(tokens) {
 			e = tokens[index]
+			index++
 		}
-		if tok == token.EOF {
-			lit = "<EOF>"
-			epos.Line = src_linecount
-			epos.Column = 2
-		}
-		checkPos(t, lit, pos, epos)
 		if tok != e.tok {
 			t.Errorf("bad token for %q: got %s, expected %s", lit, tok, e.tok)
 		}
-		if e.tok.IsLiteral() {
-			// no CRs in raw string literals
-			elit := e.lit
-			if elit[0] == '`' {
-				elit = string(stripCR([]byte(elit)))
-				epos.Offset += len(e.lit) - len(lit) // correct position
-			}
-			if lit != elit {
-				t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, elit)
-			}
-		}
+
+		// check token class
 		if tokenclass(tok) != e.class {
 			t.Errorf("bad class for %q: got %d, expected %d", lit, tokenclass(tok), e.class)
 		}
-		epos.Offset += len(lit) + len(whitespace)
-		epos.Line += newlineCount(lit) + whitespace_linecount
-		if tok == token.COMMENT && lit[1] == '/' {
-			// correct for unaccounted '/n' in //-style comment
-			epos.Offset++
-			epos.Line++
+
+		// check literal
+		elit := ""
+		switch e.tok {
+		case token.COMMENT:
+			// no CRs in comments
+			elit = string(stripCR([]byte(e.lit)))
+			//-style comment literal doesn't contain newline
+			if elit[1] == '/' {
+				elit = elit[0 : len(elit)-1]
+			}
+		case token.IDENT:
+			elit = e.lit
+		case token.SEMICOLON:
+			elit = ";"
+		default:
+			if e.tok.IsLiteral() {
+				// no CRs in raw string literals
+				elit = e.lit
+				if elit[0] == '`' {
+					elit = string(stripCR([]byte(elit)))
+				}
+			} else if e.tok.IsKeyword() {
+				elit = e.lit
+			}
+		}
+		if lit != elit {
+			t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, elit)
 		}
-		index++
+
 		if tok == token.EOF {
 			break
 		}
+
+		// update position
+		epos.Offset += len(e.lit) + len(whitespace)
+		epos.Line += newlineCount(e.lit) + whitespace_linecount
+
 	}
+
 	if s.ErrorCount != 0 {
 		t.Errorf("found %d errors", s.ErrorCount)
 	}
@@ -321,6 +346,7 @@ var lines = []string{
 	// # indicates a semicolon present in the source
 	// $ indicates an automatically inserted semicolon
 	"",
+	"\ufeff#;", // first BOM is ignored
 	"#;",
 	"foo$\n",
 	"123$\n",
@@ -521,7 +547,7 @@ func TestLineComments(t *testing.T) {
 	}
 }
 
-// Verify that initializing the same scanner more then once works correctly.
+// Verify that initializing the same scanner more than once works correctly.
 func TestInit(t *testing.T) {
 	var s Scanner
 
@@ -669,6 +695,7 @@ var errors = []struct {
 	{"0X", token.INT, 0, "illegal hexadecimal number"},
 	{"\"abc\x00def\"", token.STRING, 4, "illegal character NUL"},
 	{"\"abc\x80def\"", token.STRING, 4, "illegal UTF-8 encoding"},
+	{"\ufeff\ufeff", token.ILLEGAL, 3, "illegal character U+FEFF"}, // only first BOM is ignored
 }
 
 func TestScanErrors(t *testing.T) {
@@ -683,7 +710,7 @@ func BenchmarkScan(b *testing.B) {
 	file := fset.AddFile("", fset.Base(), len(source))
 	var s Scanner
 	b.StartTimer()
-	for i := b.N - 1; i >= 0; i-- {
+	for i := 0; i < b.N; i++ {
 		s.Init(file, source, nil, ScanComments)
 		for {
 			_, tok, _ := s.Scan()
@@ -693,3 +720,26 @@ func BenchmarkScan(b *testing.B) {
 		}
 	}
 }
+
+func BenchmarkScanFile(b *testing.B) {
+	b.StopTimer()
+	const filename = "scanner.go"
+	src, err := ioutil.ReadFile(filename)
+	if err != nil {
+		panic(err)
+	}
+	fset := token.NewFileSet()
+	file := fset.AddFile(filename, fset.Base(), len(src))
+	b.SetBytes(int64(len(src)))
+	var s Scanner
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		s.Init(file, src, nil, ScanComments)
+		for {
+			_, tok, _ := s.Scan()
+			if tok == token.EOF {
+				break
+			}
+		}
+	}
+}
diff --git a/src/pkg/go/token/position.go b/src/pkg/go/token/position.go
index 647d1b7..f5d9995 100644
--- a/src/pkg/go/token/position.go
+++ b/src/pkg/go/token/position.go
@@ -76,7 +76,7 @@ type Pos int
 // associated with it, and NoPos().IsValid() is false. NoPos is always
 // smaller than any other Pos value. The corresponding Position value
 // for NoPos is the zero value for Position.
-// 
+//
 const NoPos Pos = 0
 
 // IsValid returns true if the position is valid.
@@ -295,9 +295,9 @@ type FileSet struct {
 
 // NewFileSet creates a new file set.
 func NewFileSet() *FileSet {
-	s := new(FileSet)
-	s.base = 1 // 0 == NoPos
-	return s
+	return &FileSet{
+		base: 1, // 0 == NoPos
+	}
 }
 
 // Base returns the minimum base offset that must be provided to
@@ -347,7 +347,7 @@ func (s *FileSet) AddFile(filename string, base, size int) *File {
 
 // Iterate calls f for the files in the file set in the order they were added
 // until f returns false.
-// 
+//
 func (s *FileSet) Iterate(f func(*File) bool) {
 	for i := 0; ; i++ {
 		var file *File
@@ -367,8 +367,10 @@ func searchFiles(a []*File, x int) int {
 }
 
 func (s *FileSet) file(p Pos) *File {
+	s.mutex.RLock()
 	// common case: p is in last file
 	if f := s.last; f != nil && f.base <= int(p) && int(p) <= f.base+f.size {
+		s.mutex.RUnlock()
 		return f
 	}
 	// p is not in last file - search all files
@@ -376,10 +378,14 @@ func (s *FileSet) file(p Pos) *File {
 		f := s.files[i]
 		// f.base <= int(p) by definition of searchFiles
 		if int(p) <= f.base+f.size {
-			s.last = f
+			s.mutex.RUnlock()
+			s.mutex.Lock()
+			s.last = f // race is ok - s.last is only a cache
+			s.mutex.Unlock()
 			return f
 		}
 	}
+	s.mutex.RUnlock()
 	return nil
 }
 
@@ -389,9 +395,7 @@ func (s *FileSet) file(p Pos) *File {
 //
 func (s *FileSet) File(p Pos) (f *File) {
 	if p != NoPos {
-		s.mutex.RLock()
 		f = s.file(p)
-		s.mutex.RUnlock()
 	}
 	return
 }
@@ -399,11 +403,9 @@ func (s *FileSet) File(p Pos) (f *File) {
 // Position converts a Pos in the fileset into a general Position.
 func (s *FileSet) Position(p Pos) (pos Position) {
 	if p != NoPos {
-		s.mutex.RLock()
 		if f := s.file(p); f != nil {
 			pos = f.position(p)
 		}
-		s.mutex.RUnlock()
 	}
 	return
 }
diff --git a/src/pkg/go/token/position_test.go b/src/pkg/go/token/position_test.go
index 160107d..1d36c22 100644
--- a/src/pkg/go/token/position_test.go
+++ b/src/pkg/go/token/position_test.go
@@ -6,6 +6,8 @@ package token
 
 import (
 	"fmt"
+	"math/rand"
+	"sync"
 	"testing"
 )
 
@@ -179,3 +181,52 @@ func TestFiles(t *testing.T) {
 		}
 	}
 }
+
+// FileSet.File should return nil if Pos is past the end of the FileSet.
+func TestFileSetPastEnd(t *testing.T) {
+	fset := NewFileSet()
+	for _, test := range tests {
+		fset.AddFile(test.filename, fset.Base(), test.size)
+	}
+	if f := fset.File(Pos(fset.Base())); f != nil {
+		t.Errorf("expected nil, got %v", f)
+	}
+}
+
+func TestFileSetCacheUnlikely(t *testing.T) {
+	fset := NewFileSet()
+	offsets := make(map[string]int)
+	for _, test := range tests {
+		offsets[test.filename] = fset.Base()
+		fset.AddFile(test.filename, fset.Base(), test.size)
+	}
+	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())
+		}
+	}
+}
+
+// issue 4345. Test concurrent use of FileSet.Pos does not trigger a
+// race in the FileSet position cache.
+func TestFileSetRace(t *testing.T) {
+	fset := NewFileSet()
+	for i := 0; i < 100; i++ {
+		fset.AddFile(fmt.Sprintf("file-%d", i), fset.Base(), 1031)
+	}
+	max := int32(fset.Base())
+	var stop sync.WaitGroup
+	r := rand.New(rand.NewSource(7))
+	for i := 0; i < 2; i++ {
+		r := rand.New(rand.NewSource(r.Int63()))
+		stop.Add(1)
+		go func() {
+			for i := 0; i < 1000; i++ {
+				fset.Position(Pos(r.Int31n(max)))
+			}
+			stop.Done()
+		}()
+	}
+	stop.Wait()
+}
diff --git a/src/pkg/go/types/api.go b/src/pkg/go/types/api.go
new file mode 100644
index 0000000..13b453f
--- /dev/null
+++ b/src/pkg/go/types/api.go
@@ -0,0 +1,105 @@
+// 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 types declares the data structures for representing
+// Go types and implements typechecking of package files.
+//
+// WARNING: THE TYPES API IS SUBJECT TO CHANGE.
+//
+package types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// A Context specifies the supporting context for type checking.
+// An empty Context is a ready-to-use default context.
+type Context struct {
+	// If Error != nil, it is called with each error found
+	// during type checking. The error strings of errors with
+	// detailed position information are formatted as follows:
+	// filename:line:column: message
+	Error func(err error)
+
+	// If Ident != nil, it is called for each identifier id
+	// denoting an Object in the files provided to Check, and
+	// obj is the denoted object.
+	// Ident is not called for fields and methods in struct or
+	// interface types or composite literals, or for blank (_)
+	// or dot (.) identifiers in dot-imports.
+	// TODO(gri) Consider making Fields and Methods ordinary
+	// Objects - than we could lift this restriction.
+	Ident func(id *ast.Ident, obj Object)
+
+	// If Expr != nil, it is called exactly once for each expression x
+	// that is type-checked: typ is the expression type, and val is the
+	// value if x is constant, val is nil otherwise.
+	//
+	// If x is a literal value (constant, composite literal), typ is always
+	// the dynamic type of x (never an interface type). Otherwise, typ is x's
+	// static type (possibly an interface type).
+	//
+	// Constants are represented as follows:
+	//
+	//	bool     ->  bool
+	//	numeric  ->  int64, *big.Int, *big.Rat, Complex
+	//	string   ->  string
+	//	nil      ->  NilType
+	//
+	// Constant values are normalized, that is, they are represented
+	// using the "smallest" possible type that can represent the value.
+	// For instance, 1.0 is represented as an int64 because it can be
+	// represented accurately as an int64.
+	Expr func(x ast.Expr, typ Type, val interface{})
+
+	// If Import != nil, it is called for each imported package.
+	// Otherwise, GcImporter is called.
+	Import Importer
+
+	// If Alignof != nil, it is called to determine the alignment
+	// of the given type. Otherwise DefaultAlignmentof is called.
+	// Alignof must implement the alignment guarantees required by
+	// the spec.
+	Alignof func(Type) int64
+
+	// If Offsetsof != nil, it is called to determine the offsets
+	// of the given struct fields, in bytes. Otherwise DefaultOffsetsof
+	// is called. Offsetsof must implement the offset guarantees
+	// required by the spec.
+	Offsetsof func(fields []*Field) []int64
+
+	// If Sizeof != nil, it is called to determine the size of the
+	// given type. Otherwise, DefaultSizeof is called. Sizeof must
+	// implement the size guarantees required by the spec.
+	Sizeof func(Type) int64
+}
+
+// An Importer resolves import paths to Package objects.
+// The imports map records the packages already imported,
+// indexed by package id (canonical import path).
+// An Importer must determine the canonical import path and
+// check the map to see if it is already present in the imports map.
+// If so, the Importer can return the map entry.  Otherwise, the
+// Importer should load the package data for the given path into
+// a new *Package, record pkg in the imports map, and then
+// return pkg.
+type Importer func(imports map[string]*Package, path string) (pkg *Package, err error)
+
+// Check resolves and typechecks a set of package files within the given
+// context. It returns the package and the first error encountered, if
+// any. If the context's Error handler is nil, Check terminates as soon
+// as the first error is encountered; otherwise it continues until the
+// entire package is checked. If there are errors, the package may be
+// only partially type-checked, and the resulting package may be incomplete
+// (missing objects, imports, etc.).
+func (ctxt *Context) Check(fset *token.FileSet, files []*ast.File) (*Package, error) {
+	return check(ctxt, fset, files)
+}
+
+// Check is shorthand for ctxt.Check where ctxt is a default (empty) context.
+func Check(fset *token.FileSet, files []*ast.File) (*Package, error) {
+	var ctxt Context
+	return ctxt.Check(fset, files)
+}
diff --git a/src/pkg/go/types/builtins.go b/src/pkg/go/types/builtins.go
new file mode 100644
index 0000000..ad92591
--- /dev/null
+++ b/src/pkg/go/types/builtins.go
@@ -0,0 +1,455 @@
+// 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.
+
+// This file implements typechecking of builtin function calls.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// builtin typechecks a built-in call. The built-in type is bin, and iota is the current
+// value of iota or -1 if iota doesn't have a value in the current context. The result
+// of the call is returned via x. If the call has type errors, the returned x is marked
+// as invalid (x.mode == invalid).
+//
+func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *builtin, iota int) {
+	args := call.Args
+	id := bin.id
+
+	// declare before goto's
+	var arg0 ast.Expr // first argument, if present
+
+	// check argument count
+	n := len(args)
+	msg := ""
+	if n < bin.nargs {
+		msg = "not enough"
+	} else if !bin.isVariadic && n > bin.nargs {
+		msg = "too many"
+	}
+	if msg != "" {
+		check.invalidOp(call.Pos(), msg+" arguments for %s (expected %d, found %d)", call, bin.nargs, n)
+		goto Error
+	}
+
+	// common case: evaluate first argument if present;
+	// if it is an expression, x has the expression value
+	if n > 0 {
+		arg0 = args[0]
+		switch id {
+		case _Make, _New, _Print, _Println, _Offsetof, _Trace:
+			// respective cases below do the work
+		default:
+			// argument must be an expression
+			check.expr(x, arg0, nil, iota)
+			if x.mode == invalid {
+				goto Error
+			}
+		}
+	}
+
+	switch id {
+	case _Append:
+		if _, ok := underlying(x.typ).(*Slice); !ok {
+			check.invalidArg(x.pos(), "%s is not a typed slice", x)
+			goto Error
+		}
+		resultTyp := x.typ
+		for _, arg := range args[1:] {
+			check.expr(x, arg, nil, iota)
+			if x.mode == invalid {
+				goto Error
+			}
+			// TODO(gri) check assignability
+		}
+		x.mode = value
+		x.typ = resultTyp
+
+	case _Cap, _Len:
+		mode := invalid
+		var val interface{}
+		switch typ := implicitArrayDeref(underlying(x.typ)).(type) {
+		case *Basic:
+			if isString(typ) && id == _Len {
+				if x.mode == constant {
+					mode = constant
+					val = int64(len(x.val.(string)))
+				} else {
+					mode = value
+				}
+			}
+
+		case *Array:
+			mode = value
+			// spec: "The expressions len(s) and cap(s) are constants
+			// if the type of s is an array or pointer to an array and
+			// the expression s does not contain channel receives or
+			// function calls; in this case s is not evaluated."
+			if !check.containsCallsOrReceives(arg0) {
+				mode = constant
+				val = typ.Len
+			}
+
+		case *Slice, *Chan:
+			mode = value
+
+		case *Map:
+			if id == _Len {
+				mode = value
+			}
+		}
+
+		if mode == invalid {
+			check.invalidArg(x.pos(), "%s for %s", x, bin.name)
+			goto Error
+		}
+		x.mode = mode
+		x.typ = Typ[Int]
+		x.val = val
+
+	case _Close:
+		ch, ok := underlying(x.typ).(*Chan)
+		if !ok {
+			check.invalidArg(x.pos(), "%s is not a channel", x)
+			goto Error
+		}
+		if ch.Dir&ast.SEND == 0 {
+			check.invalidArg(x.pos(), "%s must not be a receive-only channel", x)
+			goto Error
+		}
+		x.mode = novalue
+
+	case _Complex:
+		if !check.complexArg(x) {
+			goto Error
+		}
+
+		var y operand
+		check.expr(&y, args[1], nil, iota)
+		if y.mode == invalid {
+			goto Error
+		}
+		if !check.complexArg(&y) {
+			goto Error
+		}
+
+		check.convertUntyped(x, y.typ)
+		if x.mode == invalid {
+			goto Error
+		}
+		check.convertUntyped(&y, x.typ)
+		if y.mode == invalid {
+			goto Error
+		}
+
+		if !IsIdentical(x.typ, y.typ) {
+			check.invalidArg(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
+			goto Error
+		}
+
+		typ := underlying(x.typ).(*Basic)
+		if x.mode == constant && y.mode == constant {
+			x.val = binaryOpConst(x.val, toImagConst(y.val), token.ADD, typ)
+		} else {
+			x.mode = value
+		}
+
+		switch typ.Kind {
+		case Float32:
+			x.typ = Typ[Complex64]
+		case Float64:
+			x.typ = Typ[Complex128]
+		case UntypedInt, UntypedRune, UntypedFloat:
+			x.typ = Typ[UntypedComplex]
+		default:
+			check.invalidArg(x.pos(), "float32 or float64 arguments expected")
+			goto Error
+		}
+
+	case _Copy:
+		var y operand
+		check.expr(&y, args[1], nil, iota)
+		if y.mode == invalid {
+			goto Error
+		}
+
+		var dst, src Type
+		if t, ok := underlying(x.typ).(*Slice); ok {
+			dst = t.Elt
+		}
+		switch t := underlying(y.typ).(type) {
+		case *Basic:
+			if isString(y.typ) {
+				src = Typ[Byte]
+			}
+		case *Slice:
+			src = t.Elt
+		}
+
+		if dst == nil || src == nil {
+			check.invalidArg(x.pos(), "copy expects slice arguments; found %s and %s", x, &y)
+			goto Error
+		}
+
+		if !IsIdentical(dst, src) {
+			check.invalidArg(x.pos(), "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
+			goto Error
+		}
+
+		x.mode = value
+		x.typ = Typ[Int]
+
+	case _Delete:
+		m, ok := underlying(x.typ).(*Map)
+		if !ok {
+			check.invalidArg(x.pos(), "%s is not a map", x)
+			goto Error
+		}
+		check.expr(x, args[1], nil, iota)
+		if x.mode == invalid {
+			goto Error
+		}
+		if !x.isAssignable(check.ctxt, m.Key) {
+			check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.Key)
+			goto Error
+		}
+		x.mode = novalue
+
+	case _Imag, _Real:
+		if !isComplex(x.typ) {
+			check.invalidArg(x.pos(), "%s must be a complex number", x)
+			goto Error
+		}
+		if x.mode == constant {
+			// nothing to do for x.val == 0
+			if !isZeroConst(x.val) {
+				c := x.val.(Complex)
+				if id == _Real {
+					x.val = c.Re
+				} else {
+					x.val = c.Im
+				}
+			}
+		} else {
+			x.mode = value
+		}
+		k := Invalid
+		switch underlying(x.typ).(*Basic).Kind {
+		case Complex64:
+			k = Float32
+		case Complex128:
+			k = Float64
+		case UntypedComplex:
+			k = UntypedFloat
+		default:
+			unreachable()
+		}
+		x.typ = Typ[k]
+
+	case _Make:
+		resultTyp := check.typ(arg0, false)
+		if resultTyp == Typ[Invalid] {
+			goto Error
+		}
+		var min int // minimum number of arguments
+		switch underlying(resultTyp).(type) {
+		case *Slice:
+			min = 2
+		case *Map, *Chan:
+			min = 1
+		default:
+			check.invalidArg(arg0.Pos(), "cannot make %s; type must be slice, map, or channel", arg0)
+			goto Error
+		}
+		if n := len(args); n < min || min+1 < n {
+			check.errorf(call.Pos(), "%s expects %d or %d arguments; found %d", call, min, min+1, n)
+			goto Error
+		}
+		var sizes []interface{} // constant integer arguments, if any
+		for _, arg := range args[1:] {
+			check.expr(x, arg, nil, iota)
+			if x.isInteger(check.ctxt) {
+				if x.mode == constant {
+					if isNegConst(x.val) {
+						check.invalidArg(x.pos(), "%s must not be negative", x)
+						// safe to continue
+					} else {
+						sizes = append(sizes, x.val) // x.val >= 0
+					}
+				}
+			} else {
+				check.invalidArg(x.pos(), "%s must be an integer", x)
+				// safe to continue
+			}
+		}
+		if len(sizes) == 2 && compareConst(sizes[0], sizes[1], token.GTR) {
+			check.invalidArg(args[1].Pos(), "length and capacity swapped")
+			// safe to continue
+		}
+		x.mode = variable
+		x.typ = resultTyp
+
+	case _New:
+		resultTyp := check.typ(arg0, false)
+		if resultTyp == Typ[Invalid] {
+			goto Error
+		}
+		x.mode = variable
+		x.typ = &Pointer{Base: resultTyp}
+
+	case _Panic:
+		x.mode = novalue
+
+	case _Print, _Println:
+		for _, arg := range args {
+			check.expr(x, arg, nil, -1)
+			if x.mode == invalid {
+				goto Error
+			}
+		}
+		x.mode = novalue
+
+	case _Recover:
+		x.mode = value
+		x.typ = new(Interface)
+
+	case _Alignof:
+		x.mode = constant
+		x.val = check.ctxt.alignof(x.typ)
+		x.typ = Typ[Uintptr]
+
+	case _Offsetof:
+		arg, ok := unparen(arg0).(*ast.SelectorExpr)
+		if !ok {
+			check.invalidArg(arg0.Pos(), "%s is not a selector expression", arg0)
+			goto Error
+		}
+		check.expr(x, arg.X, nil, -1)
+		if x.mode == invalid {
+			goto Error
+		}
+		sel := arg.Sel.Name
+		res := lookupField(x.typ, QualifiedName{check.pkg, arg.Sel.Name})
+		if res.index == nil {
+			check.invalidArg(x.pos(), "%s has no single field %s", x, sel)
+			goto Error
+		}
+		offs := check.ctxt.offsetof(deref(x.typ), res.index)
+		if offs < 0 {
+			check.invalidArg(x.pos(), "field %s is embedded via a pointer in %s", sel, x)
+			goto Error
+		}
+		x.mode = constant
+		x.val = offs
+		x.typ = Typ[Uintptr]
+
+	case _Sizeof:
+		x.mode = constant
+		x.val = check.ctxt.sizeof(x.typ)
+		x.typ = Typ[Uintptr]
+
+	case _Assert:
+		// assert(pred) causes a typechecker error if pred is false.
+		// The result of assert is the value of pred if there is no error.
+		// Note: assert is only available in self-test mode.
+		if x.mode != constant || !isBoolean(x.typ) {
+			check.invalidArg(x.pos(), "%s is not a boolean constant", x)
+			goto Error
+		}
+		pred, ok := x.val.(bool)
+		if !ok {
+			check.errorf(x.pos(), "internal error: value of %s should be a boolean constant", x)
+			goto Error
+		}
+		if !pred {
+			check.errorf(call.Pos(), "%s failed", call)
+			// compile-time assertion failure - safe to continue
+		}
+
+	case _Trace:
+		// trace(x, y, z, ...) dumps the positions, expressions, and
+		// values of its arguments. The result of trace is the value
+		// of the first argument.
+		// Note: trace is only available in self-test mode.
+		if len(args) == 0 {
+			check.dump("%s: trace() without arguments", call.Pos())
+			x.mode = novalue
+			x.expr = call
+			return
+		}
+		var t operand
+		x1 := x
+		for _, arg := range args {
+			check.rawExpr(x1, arg, nil, iota, true) // permit trace for types, e.g.: new(trace(T))
+			check.dump("%s: %s", x1.pos(), x1)
+			x1 = &t // use incoming x only for first argument
+		}
+
+	default:
+		check.invalidAST(call.Pos(), "unknown builtin id %d", id)
+		goto Error
+	}
+
+	x.expr = call
+	return
+
+Error:
+	x.mode = invalid
+	x.expr = call
+}
+
+// implicitArrayDeref returns A if typ is of the form *A and A is an array;
+// otherwise it returns typ.
+//
+func implicitArrayDeref(typ Type) Type {
+	if p, ok := typ.(*Pointer); ok {
+		if a, ok := underlying(p.Base).(*Array); ok {
+			return a
+		}
+	}
+	return typ
+}
+
+// containsCallsOrReceives reports if x contains function calls or channel receives.
+// Expects that x was type-checked already.
+//
+func (check *checker) containsCallsOrReceives(x ast.Expr) (found bool) {
+	ast.Inspect(x, func(x ast.Node) bool {
+		switch x := x.(type) {
+		case *ast.CallExpr:
+			// calls and conversions look the same
+			if !check.conversions[x] {
+				found = true
+			}
+		case *ast.UnaryExpr:
+			if x.Op == token.ARROW {
+				found = true
+			}
+		}
+		return !found // no need to continue if found
+	})
+	return
+}
+
+// unparen removes any parentheses surrounding an expression and returns
+// the naked expression.
+//
+func unparen(x ast.Expr) ast.Expr {
+	if p, ok := x.(*ast.ParenExpr); ok {
+		return unparen(p.X)
+	}
+	return x
+}
+
+func (check *checker) complexArg(x *operand) bool {
+	t, _ := underlying(x.typ).(*Basic)
+	if t != nil && (t.Info&IsFloat != 0 || t.Kind == UntypedInt || t.Kind == UntypedRune) {
+		return true
+	}
+	check.invalidArg(x.pos(), "%s must be a float32, float64, or an untyped non-complex numeric constant", x)
+	return false
+}
diff --git a/src/pkg/go/types/check.go b/src/pkg/go/types/check.go
new file mode 100644
index 0000000..f7b87e3
--- /dev/null
+++ b/src/pkg/go/types/check.go
@@ -0,0 +1,507 @@
+// 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 implements the Check function, which typechecks a package.
+
+package types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+)
+
+// debugging support
+const (
+	debug = true  // leave on during development
+	trace = false // turn on for detailed type resolution traces
+)
+
+type checker struct {
+	ctxt  *Context
+	fset  *token.FileSet
+	files []*ast.File
+
+	// lazily initialized
+	pkg         *Package                          // current package
+	firsterr    error                             // first error encountered
+	idents      map[*ast.Ident]Object             // maps identifiers to their unique object
+	objects     map[*ast.Object]Object            // maps *ast.Objects to their unique object
+	initspecs   map[*ast.ValueSpec]*ast.ValueSpec // "inherited" type and initialization expressions for constant declarations
+	methods     map[*TypeName]*Scope              // maps type names to associated methods
+	conversions map[*ast.CallExpr]bool            // set of type-checked conversions (to distinguish from calls)
+
+	// untyped expressions
+	// TODO(gri): Consider merging the untyped and constants map. Should measure
+	// the ratio between untyped non-constant and untyped constant expressions
+	// to make an informed decision.
+	untyped   map[ast.Expr]*Basic      // map of expressions of untyped type
+	constants map[ast.Expr]interface{} // map of untyped constant expressions; each key also appears in untyped
+	shiftOps  map[ast.Expr]bool        // map of lhs shift operands with delayed type-checking
+
+	// functions
+	funclist []function  // list of functions/methods with correct signatures and non-empty bodies
+	funcsig  *Signature  // signature of currently typechecked function
+	pos      []token.Pos // stack of expr positions; debugging support, used if trace is set
+}
+
+func (check *checker) register(id *ast.Ident, obj Object) {
+	// When an expression is evaluated more than once (happens
+	// in rare cases, e.g. for statement expressions, see
+	// comment in stmt.go), the object has been registered
+	// before. Don't do anything in that case.
+	if alt := check.idents[id]; alt != nil {
+		assert(alt == obj)
+		return
+	}
+	check.idents[id] = obj
+	if f := check.ctxt.Ident; f != nil {
+		f(id, obj)
+	}
+}
+
+// lookup returns the unique Object denoted by the identifier.
+// For identifiers without assigned *ast.Object, it uses the
+// checker.idents map; for identifiers with an *ast.Object it
+// uses the checker.objects map.
+//
+// TODO(gri) Once identifier resolution is done entirely by
+//           the typechecker, only the idents map is needed.
+//
+func (check *checker) lookup(ident *ast.Ident) Object {
+	obj := check.idents[ident]
+	astObj := ident.Obj
+
+	if obj != nil {
+		assert(astObj == nil || check.objects[astObj] == nil || check.objects[astObj] == obj)
+		return obj
+	}
+
+	if astObj == nil {
+		return nil
+	}
+
+	if obj = check.objects[astObj]; obj == nil {
+		obj = newObj(check.pkg, astObj)
+		check.objects[astObj] = obj
+	}
+	check.register(ident, obj)
+
+	return obj
+}
+
+type function struct {
+	obj  *Func // for debugging/tracing only
+	sig  *Signature
+	body *ast.BlockStmt
+}
+
+// later adds a function with non-empty body to the list of functions
+// that need to be processed after all package-level declarations
+// are typechecked.
+//
+func (check *checker) later(f *Func, sig *Signature, body *ast.BlockStmt) {
+	// functions implemented elsewhere (say in assembly) have no body
+	if body != nil {
+		check.funclist = append(check.funclist, function{f, sig, body})
+	}
+}
+
+func (check *checker) declareIdent(scope *Scope, ident *ast.Ident, obj Object) {
+	assert(check.lookup(ident) == nil) // identifier already declared or resolved
+	check.register(ident, obj)
+	if ident.Name != "_" {
+		if alt := scope.Insert(obj); alt != nil {
+			prevDecl := ""
+			if pos := alt.GetPos(); pos.IsValid() {
+				prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", check.fset.Position(pos))
+			}
+			check.errorf(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
+		}
+	}
+}
+
+func (check *checker) valueSpec(pos token.Pos, obj Object, lhs []*ast.Ident, spec *ast.ValueSpec, iota int) {
+	if len(lhs) == 0 {
+		check.invalidAST(pos, "missing lhs in declaration")
+		return
+	}
+
+	// determine type for all of lhs, if any
+	// (but only set it for the object we typecheck!)
+	var typ Type
+	if spec.Type != nil {
+		typ = check.typ(spec.Type, false)
+	}
+
+	// len(lhs) > 0
+	rhs := spec.Values
+	if len(lhs) == len(rhs) {
+		// check only lhs and rhs corresponding to obj
+		var l, r ast.Expr
+		for i, name := range lhs {
+			if check.lookup(name) == obj {
+				l = lhs[i]
+				r = rhs[i]
+				break
+			}
+		}
+		assert(l != nil)
+		switch obj := obj.(type) {
+		case *Const:
+			obj.Type = typ
+		case *Var:
+			obj.Type = typ
+		default:
+			unreachable()
+		}
+		check.assign1to1(l, r, nil, true, iota)
+		return
+	}
+
+	// there must be a type or initialization expressions
+	if typ == nil && len(rhs) == 0 {
+		check.invalidAST(pos, "missing type or initialization expression")
+		typ = Typ[Invalid]
+	}
+
+	// if we have a type, mark all of lhs
+	if typ != nil {
+		for _, name := range lhs {
+			switch obj := check.lookup(name).(type) {
+			case *Const:
+				obj.Type = typ
+			case *Var:
+				obj.Type = typ
+			default:
+				unreachable()
+			}
+		}
+	}
+
+	// check initial values, if any
+	if len(rhs) > 0 {
+		// TODO(gri) should try to avoid this conversion
+		lhx := make([]ast.Expr, len(lhs))
+		for i, e := range lhs {
+			lhx[i] = e
+		}
+		check.assignNtoM(lhx, rhs, true, iota)
+	}
+}
+
+// object typechecks an object by assigning it a type.
+//
+func (check *checker) object(obj Object, cycleOk bool) {
+	switch obj := obj.(type) {
+	case *Package:
+		// nothing to do
+	case *Const:
+		if obj.Type != nil {
+			return // already checked
+		}
+		// The obj.Val field for constants is initialized to its respective
+		// iota value by the parser.
+		// The object's fields can be in one of the following states:
+		// Type != nil  =>  the constant value is Val
+		// Type == nil  =>  the constant is not typechecked yet, and Val can be:
+		// Val  is int  =>  Val is the value of iota for this declaration
+		// Val  == nil  =>  the object's expression is being evaluated
+		if obj.Val == nil {
+			check.errorf(obj.GetPos(), "illegal cycle in initialization of %s", obj.Name)
+			obj.Type = Typ[Invalid]
+			return
+		}
+		spec := obj.spec
+		iota := obj.Val.(int)
+		obj.Val = nil // mark obj as "visited" for cycle detection
+		// determine spec for type and initialization expressions
+		init := spec
+		if len(init.Values) == 0 {
+			init = check.initspecs[spec]
+		}
+		check.valueSpec(spec.Pos(), obj, spec.Names, init, iota)
+
+	case *Var:
+		if obj.Type != nil {
+			return // already checked
+		}
+		if obj.visited {
+			check.errorf(obj.GetPos(), "illegal cycle in initialization of %s", obj.Name)
+			obj.Type = Typ[Invalid]
+			return
+		}
+		switch d := obj.decl.(type) {
+		case *ast.Field:
+			unreachable() // function parameters are always typed when collected
+		case *ast.ValueSpec:
+			obj.visited = true
+			check.valueSpec(d.Pos(), obj, d.Names, d, 0)
+		case *ast.AssignStmt:
+			// If we reach here, we have a short variable declaration
+			// where the rhs didn't typecheck and thus the lhs has no
+			// types.
+			obj.visited = true
+			obj.Type = Typ[Invalid]
+		default:
+			unreachable() // see also function newObj
+		}
+
+	case *TypeName:
+		if obj.Type != nil {
+			return // already checked
+		}
+		typ := &NamedType{Obj: obj}
+		obj.Type = typ // "mark" object so recursion terminates
+		typ.Underlying = underlying(check.typ(obj.spec.Type, cycleOk))
+		// typecheck associated method signatures
+		if scope := check.methods[obj]; scope != nil {
+			switch t := typ.Underlying.(type) {
+			case *Struct:
+				// struct fields must not conflict with methods
+				for _, f := range t.Fields {
+					if m := scope.Lookup(f.Name); m != nil {
+						check.errorf(m.GetPos(), "type %s has both field and method named %s", obj.Name, f.Name)
+						// ok to continue
+					}
+				}
+			case *Interface:
+				// methods cannot be associated with an interface type
+				for _, m := range scope.Entries {
+					recv := m.(*Func).decl.Recv.List[0].Type
+					check.errorf(recv.Pos(), "invalid receiver type %s (%s is an interface type)", obj.Name, obj.Name)
+					// ok to continue
+				}
+			}
+			// typecheck method signatures
+			var methods []*Method
+			for _, obj := range scope.Entries {
+				m := obj.(*Func)
+				sig := check.typ(m.decl.Type, cycleOk).(*Signature)
+				params, _ := check.collectParams(m.decl.Recv, false)
+				sig.Recv = params[0] // the parser/assocMethod ensure there is exactly one parameter
+				m.Type = sig
+				methods = append(methods, &Method{QualifiedName{check.pkg, m.Name}, sig})
+				check.later(m, sig, m.decl.Body)
+			}
+			typ.Methods = methods
+			delete(check.methods, obj) // we don't need this scope anymore
+		}
+
+	case *Func:
+		if obj.Type != nil {
+			return // already checked
+		}
+		fdecl := obj.decl
+		// methods are typechecked when their receivers are typechecked
+		if fdecl.Recv == nil {
+			sig := check.typ(fdecl.Type, cycleOk).(*Signature)
+			if obj.Name == "init" && (len(sig.Params) != 0 || len(sig.Results) != 0) {
+				check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
+				// ok to continue
+			}
+			obj.Type = sig
+			check.later(obj, sig, fdecl.Body)
+		}
+
+	default:
+		unreachable()
+	}
+}
+
+// assocInitvals associates "inherited" initialization expressions
+// with the corresponding *ast.ValueSpec in the check.initspecs map
+// for constant declarations without explicit initialization expressions.
+//
+func (check *checker) assocInitvals(decl *ast.GenDecl) {
+	var last *ast.ValueSpec
+	for _, s := range decl.Specs {
+		if s, ok := s.(*ast.ValueSpec); ok {
+			if len(s.Values) > 0 {
+				last = s
+			} else {
+				check.initspecs[s] = last
+			}
+		}
+	}
+	if last == nil {
+		check.invalidAST(decl.Pos(), "no initialization values provided")
+	}
+}
+
+// assocMethod associates a method declaration with the respective
+// receiver base type. meth.Recv must exist.
+//
+func (check *checker) assocMethod(meth *ast.FuncDecl) {
+	// The receiver type is one of the following (enforced by parser):
+	// - *ast.Ident
+	// - *ast.StarExpr{*ast.Ident}
+	// - *ast.BadExpr (parser error)
+	typ := meth.Recv.List[0].Type
+	if ptr, ok := typ.(*ast.StarExpr); ok {
+		typ = ptr.X
+	}
+	// determine receiver base type name
+	ident, ok := typ.(*ast.Ident)
+	if !ok {
+		// not an identifier - parser reported error already
+		return // ignore this method
+	}
+	// determine receiver base type object
+	var tname *TypeName
+	if obj := check.lookup(ident); obj != nil {
+		obj, ok := obj.(*TypeName)
+		if !ok {
+			check.errorf(ident.Pos(), "%s is not a type", ident.Name)
+			return // ignore this method
+		}
+		if obj.spec == nil {
+			check.errorf(ident.Pos(), "cannot define method on non-local type %s", ident.Name)
+			return // ignore this method
+		}
+		tname = obj
+	} else {
+		// identifier not declared/resolved - parser reported error already
+		return // ignore this method
+	}
+	// declare method in receiver base type scope
+	scope := check.methods[tname]
+	if scope == nil {
+		scope = new(Scope)
+		check.methods[tname] = scope
+	}
+	check.declareIdent(scope, meth.Name, &Func{Pkg: check.pkg, Name: meth.Name.Name, decl: meth})
+}
+
+func (check *checker) decl(decl ast.Decl) {
+	switch d := decl.(type) {
+	case *ast.BadDecl:
+		// ignore
+	case *ast.GenDecl:
+		for _, spec := range d.Specs {
+			switch s := spec.(type) {
+			case *ast.ImportSpec:
+				// nothing to do (handled by check.resolve)
+			case *ast.ValueSpec:
+				for _, name := range s.Names {
+					check.object(check.lookup(name), false)
+				}
+			case *ast.TypeSpec:
+				check.object(check.lookup(s.Name), false)
+			default:
+				check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
+			}
+		}
+	case *ast.FuncDecl:
+		// methods are checked when their respective base types are checked
+		if d.Recv != nil {
+			return
+		}
+		obj := check.lookup(d.Name)
+		// Initialization functions don't have an object associated with them
+		// since they are not in any scope. Create a dummy object for them.
+		if d.Name.Name == "init" {
+			assert(obj == nil) // all other functions should have an object
+			obj = &Func{Pkg: check.pkg, Name: d.Name.Name, decl: d}
+			check.register(d.Name, obj)
+		}
+		check.object(obj, false)
+	default:
+		check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
+	}
+}
+
+// A bailout panic is raised to indicate early termination.
+type bailout struct{}
+
+func check(ctxt *Context, fset *token.FileSet, files []*ast.File) (pkg *Package, err error) {
+	// initialize checker
+	check := checker{
+		ctxt:        ctxt,
+		fset:        fset,
+		files:       files,
+		idents:      make(map[*ast.Ident]Object),
+		objects:     make(map[*ast.Object]Object),
+		initspecs:   make(map[*ast.ValueSpec]*ast.ValueSpec),
+		methods:     make(map[*TypeName]*Scope),
+		conversions: make(map[*ast.CallExpr]bool),
+		untyped:     make(map[ast.Expr]*Basic),
+		constants:   make(map[ast.Expr]interface{}),
+		shiftOps:    make(map[ast.Expr]bool),
+	}
+
+	// set results and handle panics
+	defer func() {
+		pkg = check.pkg
+		switch p := recover().(type) {
+		case nil, bailout:
+			// normal return or early exit
+			err = check.firsterr
+		default:
+			// unexpected panic: don't crash clients
+			if debug {
+				check.dump("INTERNAL PANIC: %v", p)
+				panic(p)
+			}
+			// TODO(gri) add a test case for this scenario
+			err = fmt.Errorf("types internal error: %v", p)
+		}
+	}()
+
+	// resolve identifiers
+	imp := ctxt.Import
+	if imp == nil {
+		imp = GcImport
+	}
+	methods := check.resolve(imp)
+
+	// associate methods with types
+	for _, m := range methods {
+		check.assocMethod(m)
+	}
+
+	// typecheck all declarations
+	for _, f := range check.files {
+		for _, d := range f.Decls {
+			check.decl(d)
+		}
+	}
+
+	// typecheck all function/method bodies
+	// (funclist may grow when checking statements - do not use range clause!)
+	for i := 0; i < len(check.funclist); i++ {
+		f := check.funclist[i]
+		if trace {
+			s := "<function literal>"
+			if f.obj != nil {
+				s = f.obj.Name
+			}
+			fmt.Println("---", s)
+		}
+		check.funcsig = f.sig
+		check.stmtList(f.body.List)
+	}
+
+	// remaining untyped expressions must indeed be untyped
+	if debug {
+		for x, typ := range check.untyped {
+			if !isUntyped(typ) {
+				check.dump("%s: %s (type %s) is not untyped", x.Pos(), x, typ)
+				panic(0)
+			}
+		}
+	}
+
+	// notify client of any untyped types left
+	// TODO(gri) Consider doing this before and
+	// after function body checking for smaller
+	// map size and more immediate feedback.
+	if ctxt.Expr != nil {
+		for x, typ := range check.untyped {
+			ctxt.Expr(x, typ, check.constants[x])
+		}
+	}
+
+	return
+}
diff --git a/src/pkg/go/types/check_test.go b/src/pkg/go/types/check_test.go
new file mode 100644
index 0000000..470f3a1
--- /dev/null
+++ b/src/pkg/go/types/check_test.go
@@ -0,0 +1,259 @@
+// 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 implements a typechecker test harness. The packages specified
+// in tests are typechecked. Error messages reported by the typechecker are
+// compared against the error messages expected in the test files.
+//
+// Expected errors are indicated in the test files by putting a comment
+// of the form /* ERROR "rx" */ immediately following an offending token.
+// The harness will verify that an error matching the regular expression
+// rx is reported at that source position. Consecutive comments may be
+// used to indicate multiple errors for the same token position.
+//
+// For instance, the following test file indicates that a "not declared"
+// error should be reported for the undeclared variable x:
+//
+//	package p
+//	func f() {
+//		_ = x /* ERROR "not declared" */ + 1
+//	}
+
+package types
+
+import (
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"regexp"
+	"testing"
+)
+
+var listErrors = flag.Bool("list", false, "list errors")
+
+// The test filenames do not end in .go so that they are invisible
+// to gofmt since they contain comments that must not change their
+// positions relative to surrounding tokens.
+
+var tests = []struct {
+	name  string
+	files []string
+}{
+	{"decls0", []string{"testdata/decls0.src"}},
+	{"decls1", []string{"testdata/decls1.src"}},
+	{"decls2", []string{"testdata/decls2a.src", "testdata/decls2b.src"}},
+	{"decls3", []string{"testdata/decls3.src"}},
+	{"const0", []string{"testdata/const0.src"}},
+	{"expr0", []string{"testdata/expr0.src"}},
+	{"expr1", []string{"testdata/expr1.src"}},
+	{"expr2", []string{"testdata/expr2.src"}},
+	{"expr3", []string{"testdata/expr3.src"}},
+	{"builtins", []string{"testdata/builtins.src"}},
+	{"conversions", []string{"testdata/conversions.src"}},
+	{"stmt0", []string{"testdata/stmt0.src"}},
+}
+
+var fset = token.NewFileSet()
+
+func getFile(filename string) (file *token.File) {
+	fset.Iterate(func(f *token.File) bool {
+		if f.Name() == filename {
+			file = f
+			return false // end iteration
+		}
+		return true
+	})
+	return file
+}
+
+// Positioned errors are of the form filename:line:column: message .
+var posMsgRx = regexp.MustCompile(`^(.*:[0-9]+:[0-9]+): *(.*)`)
+
+// splitError splits an error's error message into a position string
+// and the actual error message. If there's no position information,
+// pos is the empty string, and msg is the entire error message.
+//
+func splitError(err error) (pos, msg string) {
+	msg = err.Error()
+	if m := posMsgRx.FindStringSubmatch(msg); len(m) == 3 {
+		pos = m[1]
+		msg = m[2]
+	}
+	return
+}
+
+func parseFiles(t *testing.T, testname string, filenames []string) ([]*ast.File, []error) {
+	var files []*ast.File
+	var errlist []error
+	for _, filename := range filenames {
+		file, err := parser.ParseFile(fset, filename, nil, parser.DeclarationErrors|parser.AllErrors)
+		if file == nil {
+			t.Fatalf("%s: could not parse file %s", testname, filename)
+		}
+		files = append(files, file)
+		if err != nil {
+			if list, _ := err.(scanner.ErrorList); len(list) > 0 {
+				for _, err := range list {
+					errlist = append(errlist, err)
+				}
+			} else {
+				errlist = append(errlist, err)
+			}
+		}
+	}
+	return files, errlist
+}
+
+// ERROR comments must be of the form /* ERROR "rx" */ and rx is
+// a regular expression that matches the expected error message.
+//
+var errRx = regexp.MustCompile(`^/\* *ERROR *"([^"]*)" *\*/$`)
+
+// errMap collects the regular expressions of ERROR comments found
+// in files and returns them as a map of error positions to error messages.
+//
+func errMap(t *testing.T, testname string, files []*ast.File) map[string][]string {
+	errmap := make(map[string][]string)
+
+	for _, file := range files {
+		filename := fset.Position(file.Package).Filename
+		src, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Fatalf("%s: could not read %s", testname, filename)
+		}
+
+		var s scanner.Scanner
+		// file was parsed already - do not add it again to the file
+		// set otherwise the position information returned here will
+		// not match the position information collected by the parser
+		s.Init(getFile(filename), src, nil, scanner.ScanComments)
+		var prev string // position string of last non-comment, non-semicolon token
+
+	scanFile:
+		for {
+			pos, tok, lit := s.Scan()
+			switch tok {
+			case token.EOF:
+				break scanFile
+			case token.COMMENT:
+				s := errRx.FindStringSubmatch(lit)
+				if len(s) == 2 {
+					errmap[prev] = append(errmap[prev], string(s[1]))
+				}
+			case token.SEMICOLON:
+				// ignore automatically inserted semicolon
+				if lit == "\n" {
+					continue scanFile
+				}
+				fallthrough
+			default:
+				prev = fset.Position(pos).String()
+			}
+		}
+	}
+
+	return errmap
+}
+
+func eliminate(t *testing.T, errmap map[string][]string, errlist []error) {
+	for _, err := range errlist {
+		pos, msg := splitError(err)
+		list := errmap[pos]
+		index := -1 // list index of matching message, if any
+		// we expect one of the messages in list to match the error at pos
+		for i, msg := range list {
+			rx, err := regexp.Compile(msg)
+			if err != nil {
+				t.Errorf("%s: %v", pos, err)
+				continue
+			}
+			if rx.MatchString(msg) {
+				index = i
+				break
+			}
+		}
+		if index >= 0 {
+			// eliminate from list
+			if n := len(list) - 1; n > 0 {
+				// not the last entry - swap in last element and shorten list by 1
+				list[index] = list[n]
+				errmap[pos] = list[:n]
+			} else {
+				// last entry - remove list from map
+				delete(errmap, pos)
+			}
+		} else {
+			t.Errorf("%s: no error expected: %q", pos, msg)
+		}
+
+	}
+}
+
+func checkFiles(t *testing.T, testname string, testfiles []string) {
+	// parse files and collect parser errors
+	files, errlist := parseFiles(t, testname, testfiles)
+
+	// typecheck and collect typechecker errors
+	var ctxt Context
+	ctxt.Error = func(err error) { errlist = append(errlist, err) }
+	ctxt.Check(fset, files)
+
+	if *listErrors {
+		t.Errorf("--- %s: %d errors found:", testname, len(errlist))
+		for _, err := range errlist {
+			t.Error(err)
+		}
+		return
+	}
+
+	// match and eliminate errors
+	// we are expecting the following errors
+	// (collect these after parsing the files so that
+	// they are found in the file set)
+	errmap := errMap(t, testname, files)
+	eliminate(t, errmap, errlist)
+
+	// there should be no expected errors left
+	if len(errmap) > 0 {
+		t.Errorf("--- %s: %d source positions with expected (but not reported) errors:", testname, len(errmap))
+		for pos, list := range errmap {
+			for _, rx := range list {
+				t.Errorf("%s: %q", pos, rx)
+			}
+		}
+	}
+}
+
+var testBuiltinsDeclared = false
+
+func TestCheck(t *testing.T) {
+	// Declare builtins for testing.
+	// Not done in an init func to avoid an init race with
+	// the construction of the Universe var.
+	if !testBuiltinsDeclared {
+		testBuiltinsDeclared = true
+		// Pkg == nil for Universe objects
+		def(&Func{Name: "assert", Type: &builtin{_Assert, "assert", 1, false, true}})
+		def(&Func{Name: "trace", Type: &builtin{_Trace, "trace", 0, true, true}})
+	}
+
+	// For easy debugging w/o changing the testing code,
+	// if there is a local test file, only test that file.
+	const testfile = "testdata/test.go"
+	if fi, err := os.Stat(testfile); err == nil && !fi.IsDir() {
+		fmt.Printf("WARNING: Testing only %s (remove it to run all tests)\n", testfile)
+		checkFiles(t, testfile, []string{testfile})
+		return
+	}
+
+	// Otherwise, run all the tests.
+	for _, test := range tests {
+		checkFiles(t, test.name, test.files)
+	}
+}
diff --git a/src/pkg/go/types/const.go b/src/pkg/go/types/const.go
new file mode 100644
index 0000000..503652e
--- /dev/null
+++ b/src/pkg/go/types/const.go
@@ -0,0 +1,718 @@
+// 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 implements operations on constant values.
+
+package types
+
+import (
+	"fmt"
+	"go/token"
+	"math/big"
+	"strconv"
+)
+
+// TODO(gri) At the moment, constants are different types
+// passed around as interface{} values. Introduce a Const
+// interface and use methods instead of xConst functions.
+
+// Representation of constant values.
+//
+// bool     ->  bool (true, false)
+// numeric  ->  int64, *big.Int, *big.Rat, Complex (ordered by increasing data structure "size")
+// string   ->  string
+// nil      ->  NilType (nilConst)
+//
+// Numeric constants are normalized after each operation such
+// that they are represented by the "smallest" data structure
+// required to represent the constant, independent of actual
+// type. Non-numeric constants are always normalized.
+
+// Representation of complex numbers.
+type Complex struct {
+	Re, Im *big.Rat
+}
+
+func (c Complex) String() string {
+	if c.Re.Sign() == 0 {
+		return fmt.Sprintf("%si", c.Im)
+	}
+	// normalized complex values always have an imaginary part
+	return fmt.Sprintf("(%s + %si)", c.Re, c.Im)
+}
+
+// Representation of nil.
+type NilType struct{}
+
+func (NilType) String() string {
+	return "nil"
+}
+
+// Frequently used values.
+var (
+	nilConst  = NilType{}
+	zeroConst = int64(0)
+)
+
+// int64 bounds
+var (
+	minInt64 = big.NewInt(-1 << 63)
+	maxInt64 = big.NewInt(1<<63 - 1)
+)
+
+// normalizeIntConst returns the smallest constant representation
+// for the specific value of x; either an int64 or a *big.Int value.
+//
+func normalizeIntConst(x *big.Int) interface{} {
+	if minInt64.Cmp(x) <= 0 && x.Cmp(maxInt64) <= 0 {
+		return x.Int64()
+	}
+	return x
+}
+
+// normalizeRatConst returns the smallest constant representation
+// for the specific value of x; either an int64, *big.Int,
+// or *big.Rat value.
+//
+func normalizeRatConst(x *big.Rat) interface{} {
+	if x.IsInt() {
+		return normalizeIntConst(x.Num())
+	}
+	return x
+}
+
+// newComplex returns the smallest constant representation
+// for the specific value re + im*i; either an int64, *big.Int,
+// *big.Rat, or complex value.
+//
+func newComplex(re, im *big.Rat) interface{} {
+	if im.Sign() == 0 {
+		return normalizeRatConst(re)
+	}
+	return Complex{re, im}
+}
+
+// makeRuneConst returns the int64 code point for the rune literal
+// lit. The result is nil if lit is not a correct rune literal.
+//
+func makeRuneConst(lit string) interface{} {
+	if n := len(lit); n >= 2 {
+		if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil {
+			return int64(code)
+		}
+	}
+	return nil
+}
+
+// makeRuneConst returns the smallest integer constant representation
+// (int64, *big.Int) for the integer literal lit. The result is nil if
+// lit is not a correct integer literal.
+//
+func makeIntConst(lit string) interface{} {
+	if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
+		return x
+	}
+	if x, ok := new(big.Int).SetString(lit, 0); ok {
+		return x
+	}
+	return nil
+}
+
+// makeFloatConst returns the smallest floating-point constant representation
+// (int64, *big.Int, *big.Rat) for the floating-point literal lit. The result
+// is nil if lit is not a correct floating-point literal.
+//
+func makeFloatConst(lit string) interface{} {
+	if x, ok := new(big.Rat).SetString(lit); ok {
+		return normalizeRatConst(x)
+	}
+	return nil
+}
+
+// makeComplexConst returns the complex constant representation (Complex) for
+// the imaginary literal lit. The result is nil if lit is not a correct imaginary
+// literal.
+//
+func makeComplexConst(lit string) interface{} {
+	n := len(lit)
+	if n > 0 && lit[n-1] == 'i' {
+		if im, ok := new(big.Rat).SetString(lit[0 : n-1]); ok {
+			return newComplex(big.NewRat(0, 1), im)
+		}
+	}
+	return nil
+}
+
+// makeStringConst returns the string constant representation (string) for
+// the string literal lit. The result is nil if lit is not a correct string
+// literal.
+//
+func makeStringConst(lit string) interface{} {
+	if s, err := strconv.Unquote(lit); err == nil {
+		return s
+	}
+	return nil
+}
+
+// toImagConst returns the constant Complex(0, x) for a non-complex x.
+func toImagConst(x interface{}) interface{} {
+	var im *big.Rat
+	switch x := x.(type) {
+	case int64:
+		im = big.NewRat(x, 1)
+	case *big.Int:
+		im = new(big.Rat).SetFrac(x, int1)
+	case *big.Rat:
+		im = x
+	default:
+		unreachable()
+	}
+	return Complex{rat0, im}
+}
+
+// isZeroConst reports whether the value of constant x is 0.
+// x must be normalized.
+//
+func isZeroConst(x interface{}) bool {
+	i, ok := x.(int64) // good enough since constants are normalized
+	return ok && i == 0
+}
+
+// isNegConst reports whether the value of constant x is < 0.
+// x must be a non-complex numeric value.
+//
+func isNegConst(x interface{}) bool {
+	switch x := x.(type) {
+	case int64:
+		return x < 0
+	case *big.Int:
+		return x.Sign() < 0
+	case *big.Rat:
+		return x.Sign() < 0
+	}
+	unreachable()
+	return false
+}
+
+// isRepresentableConst reports whether the value of constant x can
+// be represented as a value of the basic type Typ[as] without loss
+// of precision.
+//
+func isRepresentableConst(x interface{}, ctxt *Context, as BasicKind) bool {
+	switch x := x.(type) {
+	case bool:
+		return as == Bool || as == UntypedBool
+
+	case int64:
+		switch as {
+		case Int:
+			var s = uint(ctxt.sizeof(Typ[as])) * 8
+			return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1
+		case Int8:
+			const s = 8
+			return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+		case Int16:
+			const s = 16
+			return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+		case Int32:
+			const s = 32
+			return -1<<(s-1) <= x && x <= 1<<(s-1)-1
+		case Int64:
+			return true
+		case Uint, Uintptr:
+			var s = uint(ctxt.sizeof(Typ[as])) * 8
+			return 0 <= x && x <= int64(1)<<(s-1)-1
+		case Uint8:
+			const s = 8
+			return 0 <= x && x <= 1<<s-1
+		case Uint16:
+			const s = 16
+			return 0 <= x && x <= 1<<s-1
+		case Uint32:
+			const s = 32
+			return 0 <= x && x <= 1<<s-1
+		case Uint64:
+			return 0 <= x
+		case Float32:
+			return true // TODO(gri) fix this
+		case Float64:
+			return true // TODO(gri) fix this
+		case Complex64:
+			return true // TODO(gri) fix this
+		case Complex128:
+			return true // TODO(gri) fix this
+		case UntypedInt, UntypedFloat, UntypedComplex:
+			return true
+		}
+
+	case *big.Int:
+		switch as {
+		case Uint, Uintptr:
+			var s = uint(ctxt.sizeof(Typ[as])) * 8
+			return x.Sign() >= 0 && x.BitLen() <= int(s)
+		case Uint64:
+			return x.Sign() >= 0 && x.BitLen() <= 64
+		case Float32:
+			return true // TODO(gri) fix this
+		case Float64:
+			return true // TODO(gri) fix this
+		case Complex64:
+			return true // TODO(gri) fix this
+		case Complex128:
+			return true // TODO(gri) fix this
+		case UntypedInt, UntypedFloat, UntypedComplex:
+			return true
+		}
+
+	case *big.Rat:
+		switch as {
+		case Float32:
+			return true // TODO(gri) fix this
+		case Float64:
+			return true // TODO(gri) fix this
+		case Complex64:
+			return true // TODO(gri) fix this
+		case Complex128:
+			return true // TODO(gri) fix this
+		case UntypedFloat, UntypedComplex:
+			return true
+		}
+
+	case Complex:
+		switch as {
+		case Complex64:
+			return true // TODO(gri) fix this
+		case Complex128:
+			return true // TODO(gri) fix this
+		case UntypedComplex:
+			return true
+		}
+
+	case string:
+		return as == String || as == UntypedString
+
+	case NilType:
+		return as == UntypedNil || as == UnsafePointer
+
+	default:
+		unreachable()
+	}
+
+	return false
+}
+
+var (
+	int1 = big.NewInt(1)
+	rat0 = big.NewRat(0, 1)
+)
+
+// complexity returns a measure of representation complexity for constant x.
+func complexity(x interface{}) int {
+	switch x.(type) {
+	case bool, string, NilType:
+		return 1
+	case int64:
+		return 2
+	case *big.Int:
+		return 3
+	case *big.Rat:
+		return 4
+	case Complex:
+		return 5
+	}
+	unreachable()
+	return 0
+}
+
+// matchConst returns the matching representation (same type) with the
+// smallest complexity for two constant values x and y. They must be
+// of the same "kind" (boolean, numeric, string, or NilType).
+//
+func matchConst(x, y interface{}) (_, _ interface{}) {
+	if complexity(x) > complexity(y) {
+		y, x = matchConst(y, x)
+		return x, y
+	}
+	// complexity(x) <= complexity(y)
+
+	switch x := x.(type) {
+	case bool, Complex, string, NilType:
+		return x, y
+
+	case int64:
+		switch y := y.(type) {
+		case int64:
+			return x, y
+		case *big.Int:
+			return big.NewInt(x), y
+		case *big.Rat:
+			return big.NewRat(x, 1), y
+		case Complex:
+			return Complex{big.NewRat(x, 1), rat0}, y
+		}
+
+	case *big.Int:
+		switch y := y.(type) {
+		case *big.Int:
+			return x, y
+		case *big.Rat:
+			return new(big.Rat).SetFrac(x, int1), y
+		case Complex:
+			return Complex{new(big.Rat).SetFrac(x, int1), rat0}, y
+		}
+
+	case *big.Rat:
+		switch y := y.(type) {
+		case *big.Rat:
+			return x, y
+		case Complex:
+			return Complex{x, rat0}, y
+		}
+	}
+
+	unreachable()
+	return nil, nil
+}
+
+// is32bit reports whether x can be represented using 32 bits.
+func is32bit(x int64) bool {
+	return -1<<31 <= x && x <= 1<<31-1
+}
+
+// is63bit reports whether x can be represented using 63 bits.
+func is63bit(x int64) bool {
+	return -1<<62 <= x && x <= 1<<62-1
+}
+
+// unaryOpConst returns the result of the constant evaluation op x where x is of the given type.
+func unaryOpConst(x interface{}, ctxt *Context, op token.Token, typ *Basic) interface{} {
+	switch op {
+	case token.ADD:
+		return x // nothing to do
+	case token.SUB:
+		switch x := x.(type) {
+		case int64:
+			if z := -x; z != x {
+				return z // no overflow
+			}
+			// overflow - need to convert to big.Int
+			return normalizeIntConst(new(big.Int).Neg(big.NewInt(x)))
+		case *big.Int:
+			return normalizeIntConst(new(big.Int).Neg(x))
+		case *big.Rat:
+			return normalizeRatConst(new(big.Rat).Neg(x))
+		case Complex:
+			return newComplex(new(big.Rat).Neg(x.Re), new(big.Rat).Neg(x.Im))
+		}
+	case token.XOR:
+		var z big.Int
+		switch x := x.(type) {
+		case int64:
+			z.Not(big.NewInt(x))
+		case *big.Int:
+			z.Not(x)
+		default:
+			unreachable()
+		}
+		// For unsigned types, the result will be negative and
+		// thus "too large": We must limit the result size to
+		// the type's size.
+		if typ.Info&IsUnsigned != 0 {
+			s := uint(ctxt.sizeof(typ)) * 8
+			z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), s)) // z &^= (-1)<<s
+		}
+		return normalizeIntConst(&z)
+	case token.NOT:
+		return !x.(bool)
+	}
+	unreachable()
+	return nil
+}
+
+// binaryOpConst returns the result of the constant evaluation x op y;
+// both operands must be of the same constant "kind" (boolean, numeric, or string).
+// If typ is an integer type, division (op == token.QUO) is using integer division
+// (and the result is guaranteed to be integer) rather than floating-point
+// division. Division by zero leads to a run-time panic.
+//
+func binaryOpConst(x, y interface{}, op token.Token, typ *Basic) interface{} {
+	x, y = matchConst(x, y)
+
+	switch x := x.(type) {
+	case bool:
+		y := y.(bool)
+		switch op {
+		case token.LAND:
+			return x && y
+		case token.LOR:
+			return x || y
+		}
+
+	case int64:
+		y := y.(int64)
+		switch op {
+		case token.ADD:
+			// TODO(gri) can do better than this
+			if is63bit(x) && is63bit(y) {
+				return x + y
+			}
+			return normalizeIntConst(new(big.Int).Add(big.NewInt(x), big.NewInt(y)))
+		case token.SUB:
+			// TODO(gri) can do better than this
+			if is63bit(x) && is63bit(y) {
+				return x - y
+			}
+			return normalizeIntConst(new(big.Int).Sub(big.NewInt(x), big.NewInt(y)))
+		case token.MUL:
+			// TODO(gri) can do better than this
+			if is32bit(x) && is32bit(y) {
+				return x * y
+			}
+			return normalizeIntConst(new(big.Int).Mul(big.NewInt(x), big.NewInt(y)))
+		case token.REM:
+			return x % y
+		case token.QUO:
+			if typ.Info&IsInteger != 0 {
+				return x / y
+			}
+			return normalizeRatConst(new(big.Rat).SetFrac(big.NewInt(x), big.NewInt(y)))
+		case token.AND:
+			return x & y
+		case token.OR:
+			return x | y
+		case token.XOR:
+			return x ^ y
+		case token.AND_NOT:
+			return x &^ y
+		}
+
+	case *big.Int:
+		y := y.(*big.Int)
+		var z big.Int
+		switch op {
+		case token.ADD:
+			z.Add(x, y)
+		case token.SUB:
+			z.Sub(x, y)
+		case token.MUL:
+			z.Mul(x, y)
+		case token.REM:
+			z.Rem(x, y)
+		case token.QUO:
+			if typ.Info&IsInteger != 0 {
+				z.Quo(x, y)
+			} else {
+				return normalizeRatConst(new(big.Rat).SetFrac(x, y))
+			}
+		case token.AND:
+			z.And(x, y)
+		case token.OR:
+			z.Or(x, y)
+		case token.XOR:
+			z.Xor(x, y)
+		case token.AND_NOT:
+			z.AndNot(x, y)
+		default:
+			unreachable()
+		}
+		return normalizeIntConst(&z)
+
+	case *big.Rat:
+		y := y.(*big.Rat)
+		var z big.Rat
+		switch op {
+		case token.ADD:
+			z.Add(x, y)
+		case token.SUB:
+			z.Sub(x, y)
+		case token.MUL:
+			z.Mul(x, y)
+		case token.QUO:
+			z.Quo(x, y)
+		default:
+			unreachable()
+		}
+		return normalizeRatConst(&z)
+
+	case Complex:
+		y := y.(Complex)
+		a, b := x.Re, x.Im
+		c, d := y.Re, y.Im
+		var re, im big.Rat
+		switch op {
+		case token.ADD:
+			// (a+c) + i(b+d)
+			re.Add(a, c)
+			im.Add(b, d)
+		case token.SUB:
+			// (a-c) + i(b-d)
+			re.Sub(a, c)
+			im.Sub(b, d)
+		case token.MUL:
+			// (ac-bd) + i(bc+ad)
+			var ac, bd, bc, ad big.Rat
+			ac.Mul(a, c)
+			bd.Mul(b, d)
+			bc.Mul(b, c)
+			ad.Mul(a, d)
+			re.Sub(&ac, &bd)
+			im.Add(&bc, &ad)
+		case token.QUO:
+			// (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
+			var ac, bd, bc, ad, s big.Rat
+			ac.Mul(a, c)
+			bd.Mul(b, d)
+			bc.Mul(b, c)
+			ad.Mul(a, d)
+			s.Add(c.Mul(c, c), d.Mul(d, d))
+			re.Add(&ac, &bd)
+			re.Quo(&re, &s)
+			im.Sub(&bc, &ad)
+			im.Quo(&im, &s)
+		default:
+			unreachable()
+		}
+		return newComplex(&re, &im)
+
+	case string:
+		if op == token.ADD {
+			return x + y.(string)
+		}
+	}
+
+	unreachable()
+	return nil
+}
+
+// shiftConst returns the result of the constant evaluation x op s
+// where op is token.SHL or token.SHR (<< or >>). x must be an
+// integer constant.
+//
+func shiftConst(x interface{}, s uint, op token.Token) interface{} {
+	switch x := x.(type) {
+	case int64:
+		switch op {
+		case token.SHL:
+			z := big.NewInt(x)
+			return normalizeIntConst(z.Lsh(z, s))
+		case token.SHR:
+			return x >> s
+		}
+
+	case *big.Int:
+		var z big.Int
+		switch op {
+		case token.SHL:
+			return normalizeIntConst(z.Lsh(x, s))
+		case token.SHR:
+			return normalizeIntConst(z.Rsh(x, s))
+		}
+	}
+
+	unreachable()
+	return nil
+}
+
+// compareConst returns the result of the constant comparison x op y;
+// both operands must be of the same "kind" (boolean, numeric, string,
+// or NilType).
+//
+func compareConst(x, y interface{}, op token.Token) (z bool) {
+	x, y = matchConst(x, y)
+
+	// x == y  =>  x == y
+	// x != y  =>  x != y
+	// x >  y  =>  y <  x
+	// x >= y  =>  u <= x
+	swap := false
+	switch op {
+	case token.GTR:
+		swap = true
+		op = token.LSS
+	case token.GEQ:
+		swap = true
+		op = token.LEQ
+	}
+
+	// x == y  =>    x == y
+	// x != y  =>  !(x == y)
+	// x <  y  =>    x <  y
+	// x <= y  =>  !(y <  x)
+	negate := false
+	switch op {
+	case token.NEQ:
+		negate = true
+		op = token.EQL
+	case token.LEQ:
+		swap = !swap
+		negate = true
+		op = token.LSS
+	}
+
+	if negate {
+		defer func() { z = !z }()
+	}
+
+	if swap {
+		x, y = y, x
+	}
+
+	switch x := x.(type) {
+	case bool:
+		if op == token.EQL {
+			return x == y.(bool)
+		}
+
+	case int64:
+		y := y.(int64)
+		switch op {
+		case token.EQL:
+			return x == y
+		case token.LSS:
+			return x < y
+		}
+
+	case *big.Int:
+		s := x.Cmp(y.(*big.Int))
+		switch op {
+		case token.EQL:
+			return s == 0
+		case token.LSS:
+			return s < 0
+		}
+
+	case *big.Rat:
+		s := x.Cmp(y.(*big.Rat))
+		switch op {
+		case token.EQL:
+			return s == 0
+		case token.LSS:
+			return s < 0
+		}
+
+	case Complex:
+		y := y.(Complex)
+		if op == token.EQL {
+			return x.Re.Cmp(y.Re) == 0 && x.Im.Cmp(y.Im) == 0
+		}
+
+	case string:
+		y := y.(string)
+		switch op {
+		case token.EQL:
+			return x == y
+		case token.LSS:
+			return x < y
+		}
+
+	case NilType:
+		if op == token.EQL {
+			return x == y.(NilType)
+		}
+	}
+
+	fmt.Printf("x = %s (%T), y = %s (%T)\n", x, x, y, y)
+	unreachable()
+	return
+}
diff --git a/src/pkg/go/types/conversions.go b/src/pkg/go/types/conversions.go
new file mode 100644
index 0000000..fcbaf77
--- /dev/null
+++ b/src/pkg/go/types/conversions.go
@@ -0,0 +1,129 @@
+// 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.
+
+// This file implements typechecking of conversions.
+
+package types
+
+import (
+	"go/ast"
+)
+
+// conversion typechecks the type conversion conv to type typ. iota is the current
+// value of iota or -1 if iota doesn't have a value in the current context. The result
+// of the conversion is returned via x. If the conversion has type errors, the returned
+// x is marked as invalid (x.mode == invalid).
+//
+func (check *checker) conversion(x *operand, conv *ast.CallExpr, typ Type, iota int) {
+	// all conversions have one argument
+	if len(conv.Args) != 1 {
+		check.invalidOp(conv.Pos(), "%s conversion requires exactly one argument", conv)
+		goto Error
+	}
+
+	// evaluate argument
+	check.expr(x, conv.Args[0], nil, iota)
+	if x.mode == invalid {
+		goto Error
+	}
+
+	if x.mode == constant && isConstType(typ) {
+		// constant conversion
+		// TODO(gri) implement this
+	} else {
+		// non-constant conversion
+		if !x.isConvertible(check.ctxt, typ) {
+			check.invalidOp(conv.Pos(), "cannot convert %s to %s", x, typ)
+			goto Error
+		}
+		x.mode = value
+	}
+
+	check.conversions[conv] = true // for cap/len checking
+	x.expr = conv
+	x.typ = typ
+	return
+
+Error:
+	x.mode = invalid
+}
+
+func (x *operand) isConvertible(ctxt *Context, T Type) bool {
+	// "x is assignable to T"
+	if x.isAssignable(ctxt, T) {
+		return true
+	}
+
+	// "x's type and T have identical underlying types"
+	V := x.typ
+	Vu := underlying(V)
+	Tu := underlying(T)
+	if IsIdentical(Vu, Tu) {
+		return true
+	}
+
+	// "x's type and T are unnamed pointer types and their pointer base types have identical underlying types"
+	if V, ok := V.(*Pointer); ok {
+		if T, ok := T.(*Pointer); ok {
+			if IsIdentical(underlying(V.Base), underlying(T.Base)) {
+				return true
+			}
+		}
+	}
+
+	// "x's type and T are both integer or floating point types"
+	if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) {
+		return true
+	}
+
+	// "x's type and T are both complex types"
+	if isComplex(V) && isComplex(T) {
+		return true
+	}
+
+	// "x is an integer or a slice of bytes or runes and T is a string type"
+	if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) {
+		return true
+	}
+
+	// "x is a string and T is a slice of bytes or runes"
+	if isString(V) && isBytesOrRunes(Tu) {
+		return true
+	}
+
+	// package unsafe:
+	// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
+	if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) {
+		return true
+	}
+	// "and vice versa"
+	if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) {
+		return true
+	}
+
+	return false
+}
+
+func isUintptr(typ Type) bool {
+	t, ok := typ.(*Basic)
+	return ok && t.Kind == Uintptr
+}
+
+func isUnsafePointer(typ Type) bool {
+	t, ok := typ.(*Basic)
+	return ok && t.Kind == UnsafePointer
+}
+
+func isPointer(typ Type) bool {
+	_, ok := typ.(*Pointer)
+	return ok
+}
+
+func isBytesOrRunes(typ Type) bool {
+	if s, ok := typ.(*Slice); ok {
+		t, ok := underlying(s.Elt).(*Basic)
+		return ok && (t.Kind == Byte || t.Kind == Rune)
+	}
+	return false
+}
diff --git a/src/pkg/go/types/errors.go b/src/pkg/go/types/errors.go
new file mode 100644
index 0000000..62ee547
--- /dev/null
+++ b/src/pkg/go/types/errors.go
@@ -0,0 +1,335 @@
+// 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.
+
+// This file implements various error reporters.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+)
+
+// TODO(gri) eventually assert and unimplemented should disappear.
+func assert(p bool) {
+	if !p {
+		panic("assertion failed")
+	}
+}
+
+func unreachable() {
+	panic("unreachable")
+}
+
+func (check *checker) printTrace(format string, args []interface{}) {
+	const dots = ".  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  "
+	n := len(check.pos) - 1
+	i := 3 * n
+	for i > len(dots) {
+		fmt.Print(dots)
+		i -= len(dots)
+	}
+	// i <= len(dots)
+	fmt.Printf("%s:\t", check.fset.Position(check.pos[n]))
+	fmt.Print(dots[0:i])
+	fmt.Println(check.formatMsg(format, args))
+}
+
+func (check *checker) trace(pos token.Pos, format string, args ...interface{}) {
+	check.pos = append(check.pos, pos)
+	check.printTrace(format, args)
+}
+
+func (check *checker) untrace(format string, args ...interface{}) {
+	if len(format) > 0 {
+		check.printTrace(format, args)
+	}
+	check.pos = check.pos[:len(check.pos)-1]
+}
+
+func (check *checker) formatMsg(format string, args []interface{}) string {
+	for i, arg := range args {
+		switch a := arg.(type) {
+		case token.Pos:
+			args[i] = check.fset.Position(a).String()
+		case ast.Expr:
+			args[i] = exprString(a)
+		case Type:
+			args[i] = typeString(a)
+		case operand:
+			panic("internal error: should always pass *operand")
+		}
+	}
+	return fmt.Sprintf(format, args...)
+}
+
+// dump is only needed for debugging
+func (check *checker) dump(format string, args ...interface{}) {
+	fmt.Println(check.formatMsg(format, args))
+}
+
+func (check *checker) err(err error) {
+	if check.firsterr == nil {
+		check.firsterr = err
+	}
+	f := check.ctxt.Error
+	if f == nil {
+		panic(bailout{}) // report only first error
+	}
+	f(err)
+}
+
+func (check *checker) errorf(pos token.Pos, format string, args ...interface{}) {
+	check.err(fmt.Errorf("%s: %s", check.fset.Position(pos), check.formatMsg(format, args)))
+}
+
+func (check *checker) invalidAST(pos token.Pos, format string, args ...interface{}) {
+	check.errorf(pos, "invalid AST: "+format, args...)
+}
+
+func (check *checker) invalidArg(pos token.Pos, format string, args ...interface{}) {
+	check.errorf(pos, "invalid argument: "+format, args...)
+}
+
+func (check *checker) invalidOp(pos token.Pos, format string, args ...interface{}) {
+	check.errorf(pos, "invalid operation: "+format, args...)
+}
+
+// exprString returns a (simplified) string representation for an expression.
+func exprString(expr ast.Expr) string {
+	var buf bytes.Buffer
+	writeExpr(&buf, expr)
+	return buf.String()
+}
+
+// TODO(gri) Need to merge with typeString since some expressions are types (try: ([]int)(a))
+func writeExpr(buf *bytes.Buffer, expr ast.Expr) {
+	switch x := expr.(type) {
+	case *ast.Ident:
+		buf.WriteString(x.Name)
+
+	case *ast.BasicLit:
+		buf.WriteString(x.Value)
+
+	case *ast.FuncLit:
+		buf.WriteString("(func literal)")
+
+	case *ast.CompositeLit:
+		buf.WriteString("(composite literal)")
+
+	case *ast.ParenExpr:
+		buf.WriteByte('(')
+		writeExpr(buf, x.X)
+		buf.WriteByte(')')
+
+	case *ast.SelectorExpr:
+		writeExpr(buf, x.X)
+		buf.WriteByte('.')
+		buf.WriteString(x.Sel.Name)
+
+	case *ast.IndexExpr:
+		writeExpr(buf, x.X)
+		buf.WriteByte('[')
+		writeExpr(buf, x.Index)
+		buf.WriteByte(']')
+
+	case *ast.SliceExpr:
+		writeExpr(buf, x.X)
+		buf.WriteByte('[')
+		if x.Low != nil {
+			writeExpr(buf, x.Low)
+		}
+		buf.WriteByte(':')
+		if x.High != nil {
+			writeExpr(buf, x.High)
+		}
+		buf.WriteByte(']')
+
+	case *ast.TypeAssertExpr:
+		writeExpr(buf, x.X)
+		buf.WriteString(".(...)")
+
+	case *ast.CallExpr:
+		writeExpr(buf, x.Fun)
+		buf.WriteByte('(')
+		for i, arg := range x.Args {
+			if i > 0 {
+				buf.WriteString(", ")
+			}
+			writeExpr(buf, arg)
+		}
+		buf.WriteByte(')')
+
+	case *ast.StarExpr:
+		buf.WriteByte('*')
+		writeExpr(buf, x.X)
+
+	case *ast.UnaryExpr:
+		buf.WriteString(x.Op.String())
+		writeExpr(buf, x.X)
+
+	case *ast.BinaryExpr:
+		// The AST preserves source-level parentheses so there is
+		// no need to introduce parentheses here for correctness.
+		writeExpr(buf, x.X)
+		buf.WriteByte(' ')
+		buf.WriteString(x.Op.String())
+		buf.WriteByte(' ')
+		writeExpr(buf, x.Y)
+
+	default:
+		fmt.Fprintf(buf, "<expr %T>", x)
+	}
+}
+
+// typeString returns a string representation for typ.
+func typeString(typ Type) string {
+	var buf bytes.Buffer
+	writeType(&buf, typ)
+	return buf.String()
+}
+
+func writeParams(buf *bytes.Buffer, params []*Var, isVariadic bool) {
+	buf.WriteByte('(')
+	for i, par := range params {
+		if i > 0 {
+			buf.WriteString(", ")
+		}
+		if par.Name != "" {
+			buf.WriteString(par.Name)
+			buf.WriteByte(' ')
+		}
+		if isVariadic && i == len(params)-1 {
+			buf.WriteString("...")
+		}
+		writeType(buf, par.Type)
+	}
+	buf.WriteByte(')')
+}
+
+func writeSignature(buf *bytes.Buffer, sig *Signature) {
+	writeParams(buf, sig.Params, sig.IsVariadic)
+	if len(sig.Results) == 0 {
+		// no result
+		return
+	}
+
+	buf.WriteByte(' ')
+	if len(sig.Results) == 1 && sig.Results[0].Name == "" {
+		// single unnamed result
+		writeType(buf, sig.Results[0].Type.(Type))
+		return
+	}
+
+	// multiple or named result(s)
+	writeParams(buf, sig.Results, false)
+}
+
+func writeType(buf *bytes.Buffer, typ Type) {
+	switch t := typ.(type) {
+	case nil:
+		buf.WriteString("<nil>")
+
+	case *Basic:
+		buf.WriteString(t.Name)
+
+	case *Array:
+		fmt.Fprintf(buf, "[%d]", t.Len)
+		writeType(buf, t.Elt)
+
+	case *Slice:
+		buf.WriteString("[]")
+		writeType(buf, t.Elt)
+
+	case *Struct:
+		buf.WriteString("struct{")
+		for i, f := range t.Fields {
+			if i > 0 {
+				buf.WriteString("; ")
+			}
+			if !f.IsAnonymous {
+				buf.WriteString(f.Name)
+				buf.WriteByte(' ')
+			}
+			writeType(buf, f.Type)
+			if f.Tag != "" {
+				fmt.Fprintf(buf, " %q", f.Tag)
+			}
+		}
+		buf.WriteByte('}')
+
+	case *Pointer:
+		buf.WriteByte('*')
+		writeType(buf, t.Base)
+
+	case *Result:
+		writeParams(buf, t.Values, false)
+
+	case *Signature:
+		buf.WriteString("func")
+		writeSignature(buf, t)
+
+	case *builtin:
+		fmt.Fprintf(buf, "<type of %s>", t.name)
+
+	case *Interface:
+		buf.WriteString("interface{")
+		for i, m := range t.Methods {
+			if i > 0 {
+				buf.WriteString("; ")
+			}
+			buf.WriteString(m.Name)
+			writeSignature(buf, m.Type)
+		}
+		buf.WriteByte('}')
+
+	case *Map:
+		buf.WriteString("map[")
+		writeType(buf, t.Key)
+		buf.WriteByte(']')
+		writeType(buf, t.Elt)
+
+	case *Chan:
+		var s string
+		switch t.Dir {
+		case ast.SEND:
+			s = "chan<- "
+		case ast.RECV:
+			s = "<-chan "
+		default:
+			s = "chan "
+		}
+		buf.WriteString(s)
+		writeType(buf, t.Elt)
+
+	case *NamedType:
+		s := "<NamedType w/o object>"
+		if obj := t.Obj; obj != nil {
+			if obj.Pkg != nil && obj.Pkg.Path != "" {
+				buf.WriteString(obj.Pkg.Path)
+				buf.WriteString(".")
+			}
+			s = t.Obj.GetName()
+		}
+		buf.WriteString(s)
+
+	default:
+		fmt.Fprintf(buf, "<type %T>", t)
+	}
+}
+
+func (t *Array) String() string     { return typeString(t) }
+func (t *Basic) String() string     { return typeString(t) }
+func (t *Chan) String() string      { return typeString(t) }
+func (t *Interface) String() string { return typeString(t) }
+func (t *Map) String() string       { return typeString(t) }
+func (t *NamedType) String() string { return typeString(t) }
+func (t *Pointer) String() string   { return typeString(t) }
+func (t *Result) String() string    { return typeString(t) }
+func (t *Signature) String() string { return typeString(t) }
+func (t *Slice) String() string     { return typeString(t) }
+func (t *Struct) String() string    { return typeString(t) }
+func (t *builtin) String() string   { return typeString(t) }
diff --git a/src/pkg/go/types/exportdata.go b/src/pkg/go/types/exportdata.go
new file mode 100644
index 0000000..1f6a3c7
--- /dev/null
+++ b/src/pkg/go/types/exportdata.go
@@ -0,0 +1,111 @@
+// 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 implements FindGcExportData.
+
+package types
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+	"strconv"
+	"strings"
+)
+
+func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
+	// See $GOROOT/include/ar.h.
+	hdr := make([]byte, 16+12+6+6+8+10+2)
+	_, err = io.ReadFull(r, hdr)
+	if err != nil {
+		return
+	}
+	// leave for debugging
+	if false {
+		fmt.Printf("header: %s", hdr)
+	}
+	s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
+	size, err = strconv.Atoi(s)
+	if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
+		err = errors.New("invalid archive header")
+		return
+	}
+	name = strings.TrimSpace(string(hdr[:16]))
+	return
+}
+
+// FindGcExportData positions the reader r at the beginning of the
+// export data section of an underlying GC-created object/archive
+// file by reading from it. The reader must be positioned at the
+// start of the file before calling this function.
+//
+func FindGcExportData(r *bufio.Reader) (err error) {
+	// Read first line to make sure this is an object file.
+	line, err := r.ReadSlice('\n')
+	if err != nil {
+		return
+	}
+	if string(line) == "!<arch>\n" {
+		// Archive file.  Scan to __.PKGDEF, which should
+		// be second archive entry.
+		var name string
+		var size int
+
+		// First entry should be __.GOSYMDEF.
+		// Older archives used __.SYMDEF, so allow that too.
+		// Read and discard.
+		if name, size, err = readGopackHeader(r); err != nil {
+			return
+		}
+		if name != "__.SYMDEF" && name != "__.GOSYMDEF" {
+			err = errors.New("go archive does not begin with __.SYMDEF or __.GOSYMDEF")
+			return
+		}
+		const block = 4096
+		tmp := make([]byte, block)
+		for size > 0 {
+			n := size
+			if n > block {
+				n = block
+			}
+			if _, err = io.ReadFull(r, tmp[:n]); err != nil {
+				return
+			}
+			size -= n
+		}
+
+		// Second entry should be __.PKGDEF.
+		if name, size, err = readGopackHeader(r); err != nil {
+			return
+		}
+		if name != "__.PKGDEF" {
+			err = errors.New("go archive is missing __.PKGDEF")
+			return
+		}
+
+		// Read first line of __.PKGDEF data, so that line
+		// is once again the first line of the input.
+		if line, err = r.ReadSlice('\n'); err != nil {
+			return
+		}
+	}
+
+	// Now at __.PKGDEF in archive or still at beginning of file.
+	// Either way, line should begin with "go object ".
+	if !strings.HasPrefix(string(line), "go object ") {
+		err = errors.New("not a go object file")
+		return
+	}
+
+	// Skip over object header to export data.
+	// Begins after first line with $$.
+	for line[0] != '$' {
+		if line, err = r.ReadSlice('\n'); err != nil {
+			return
+		}
+	}
+
+	return
+}
diff --git a/src/pkg/go/types/expr.go b/src/pkg/go/types/expr.go
new file mode 100644
index 0000000..86d782d
--- /dev/null
+++ b/src/pkg/go/types/expr.go
@@ -0,0 +1,1520 @@
+// 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.
+
+// This file implements typechecking of expressions.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+	"strconv"
+)
+
+// TODO(gri) Cleanups
+// - don't print error messages referring to invalid types (they are likely spurious errors)
+// - simplify invalid handling: maybe just use Typ[Invalid] as marker, get rid of invalid Mode for values?
+// - rethink error handling: should all callers check if x.mode == valid after making a call?
+// - at the moment, iota is passed around almost everywhere - in many places we know it cannot be used
+// - use "" or "_" consistently for anonymous identifiers? (e.g. reeceivers that have no name)
+// - consider storing error messages in invalid operands for better error messages/debugging output
+
+// TODO(gri) API issues
+// - clients need access to builtins type information
+// - API tests are missing (e.g., identifiers should be handled as expressions in callbacks)
+
+func (check *checker) collectParams(list *ast.FieldList, variadicOk bool) (params []*Var, isVariadic bool) {
+	if list == nil {
+		return
+	}
+	var last *Var
+	for i, field := range list.List {
+		ftype := field.Type
+		if t, _ := ftype.(*ast.Ellipsis); t != nil {
+			ftype = t.Elt
+			if variadicOk && i == len(list.List)-1 {
+				isVariadic = true
+			} else {
+				check.invalidAST(field.Pos(), "... not permitted")
+				// ok to continue
+			}
+		}
+		// the parser ensures that f.Tag is nil and we don't
+		// care if a constructed AST contains a non-nil tag
+		typ := check.typ(ftype, true)
+		if len(field.Names) > 0 {
+			// named parameter
+			for _, name := range field.Names {
+				par := check.lookup(name).(*Var)
+				par.Type = typ
+				last = par
+				copy := *par
+				params = append(params, &copy)
+			}
+		} else {
+			// anonymous parameter
+			par := &Var{Type: typ}
+			last = nil // not accessible inside function
+			params = append(params, par)
+		}
+	}
+	// For a variadic function, change the last parameter's object type
+	// from T to []T (this is the type used inside the function), but
+	// keep the params list unchanged (this is the externally visible type).
+	if isVariadic && last != nil {
+		last.Type = &Slice{Elt: last.Type}
+	}
+	return
+}
+
+func (check *checker) collectMethods(list *ast.FieldList) (methods []*Method) {
+	if list == nil {
+		return
+	}
+	for _, f := range list.List {
+		typ := check.typ(f.Type, len(f.Names) > 0) // cycles are not ok for embedded interfaces
+		// the parser ensures that f.Tag is nil and we don't
+		// care if a constructed AST contains a non-nil tag
+		if len(f.Names) > 0 {
+			// methods (the parser ensures that there's only one
+			// and we don't care if a constructed AST has more)
+			sig, ok := typ.(*Signature)
+			if !ok {
+				check.invalidAST(f.Type.Pos(), "%s is not a method signature", typ)
+				continue
+			}
+			for _, name := range f.Names {
+				methods = append(methods, &Method{QualifiedName{check.pkg, name.Name}, sig})
+			}
+		} else {
+			// embedded interface
+			utyp := underlying(typ)
+			if ityp, ok := utyp.(*Interface); ok {
+				methods = append(methods, ityp.Methods...)
+			} else if utyp != Typ[Invalid] {
+				// if utyp is invalid, don't complain (the root cause was reported before)
+				check.errorf(f.Type.Pos(), "%s is not an interface type", typ)
+			}
+		}
+	}
+	// Check for double declarations.
+	// The parser inserts methods into an interface-local scope, so local
+	// double declarations are reported by the parser already. We need to
+	// check again for conflicts due to embedded interfaces. This will lead
+	// to a 2nd error message if the double declaration was reported before
+	// by the parser.
+	// TODO(gri) clean this up a bit
+	seen := make(map[string]bool)
+	for _, m := range methods {
+		if seen[m.Name] {
+			check.errorf(list.Pos(), "multiple methods named %s", m.Name)
+			return // keep multiple entries, lookup will only return the first entry
+		}
+		seen[m.Name] = true
+	}
+	return
+}
+
+func (check *checker) tag(t *ast.BasicLit) string {
+	if t != nil {
+		if t.Kind == token.STRING {
+			if val, err := strconv.Unquote(t.Value); err == nil {
+				return val
+			}
+		}
+		check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value)
+	}
+	return ""
+}
+
+func (check *checker) collectFields(list *ast.FieldList, cycleOk bool) (fields []*Field) {
+	if list == nil {
+		return
+	}
+
+	var typ Type   // current field typ
+	var tag string // current field tag
+	add := func(name string, isAnonymous bool) {
+		fields = append(fields, &Field{QualifiedName{check.pkg, name}, typ, tag, isAnonymous})
+	}
+
+	for _, f := range list.List {
+		typ = check.typ(f.Type, cycleOk)
+		tag = check.tag(f.Tag)
+		if len(f.Names) > 0 {
+			// named fields
+			for _, name := range f.Names {
+				add(name.Name, false)
+			}
+		} else {
+			// anonymous field
+			switch t := deref(typ).(type) {
+			case *Basic:
+				add(t.Name, true)
+			case *NamedType:
+				add(t.Obj.GetName(), true)
+			default:
+				if typ != Typ[Invalid] {
+					check.invalidAST(f.Type.Pos(), "anonymous field type %s must be named", typ)
+				}
+			}
+		}
+	}
+
+	return
+}
+
+type opPredicates map[token.Token]func(Type) bool
+
+var unaryOpPredicates = opPredicates{
+	token.ADD: isNumeric,
+	token.SUB: isNumeric,
+	token.XOR: isInteger,
+	token.NOT: isBoolean,
+}
+
+func (check *checker) op(m opPredicates, x *operand, op token.Token) bool {
+	if pred := m[op]; pred != nil {
+		if !pred(x.typ) {
+			check.invalidOp(x.pos(), "operator %s not defined for %s", op, x)
+			return false
+		}
+	} else {
+		check.invalidAST(x.pos(), "unknown operator %s", op)
+		return false
+	}
+	return true
+}
+
+func (check *checker) unary(x *operand, op token.Token) {
+	switch op {
+	case token.AND:
+		// spec: "As an exception to the addressability
+		// requirement x may also be a composite literal."
+		if _, ok := unparen(x.expr).(*ast.CompositeLit); ok {
+			x.mode = variable
+		}
+		if x.mode != variable {
+			check.invalidOp(x.pos(), "cannot take address of %s", x)
+			goto Error
+		}
+		x.typ = &Pointer{Base: x.typ}
+		return
+
+	case token.ARROW:
+		typ, ok := underlying(x.typ).(*Chan)
+		if !ok {
+			check.invalidOp(x.pos(), "cannot receive from non-channel %s", x)
+			goto Error
+		}
+		if typ.Dir&ast.RECV == 0 {
+			check.invalidOp(x.pos(), "cannot receive from send-only channel %s", x)
+			goto Error
+		}
+		x.mode = valueok
+		x.typ = typ.Elt
+		return
+	}
+
+	if !check.op(unaryOpPredicates, x, op) {
+		goto Error
+	}
+
+	if x.mode == constant {
+		typ := underlying(x.typ).(*Basic)
+		x.val = unaryOpConst(x.val, check.ctxt, op, typ)
+		// Typed constants must be representable in
+		// their type after each constant operation.
+		check.isRepresentable(x, typ)
+		return
+	}
+
+	x.mode = value
+	// x.typ remains unchanged
+	return
+
+Error:
+	x.mode = invalid
+}
+
+func isShift(op token.Token) bool {
+	return op == token.SHL || op == token.SHR
+}
+
+func isComparison(op token.Token) bool {
+	// Note: tokens are not ordered well to make this much easier
+	switch op {
+	case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ:
+		return true
+	}
+	return false
+}
+
+// isRepresentable checks that a constant operand is representable in the given type.
+func (check *checker) isRepresentable(x *operand, typ *Basic) {
+	if x.mode != constant || isUntyped(typ) {
+		return
+	}
+
+	if !isRepresentableConst(x.val, check.ctxt, typ.Kind) {
+		var msg string
+		if isNumeric(x.typ) && isNumeric(typ) {
+			msg = "%s overflows %s"
+		} else {
+			msg = "cannot convert %s to %s"
+		}
+		check.errorf(x.pos(), msg, x, typ)
+		x.mode = invalid
+	}
+}
+
+// updateExprType updates the type of all untyped nodes in the
+// expression tree of x to typ. If shiftOp is set, x is the lhs
+// of a shift expression. In that case, and if x is in the set
+// of shift operands with delayed type checking, and typ is not
+// an untyped type, updateExprType will check if typ is an
+// integer type.
+// If Context.Expr != nil, it is called for all nodes that are
+// now assigned their final (not untyped) type.
+func (check *checker) updateExprType(x ast.Expr, typ Type, shiftOp bool) {
+	switch x := x.(type) {
+	case *ast.BadExpr,
+		*ast.FuncLit,
+		*ast.CompositeLit,
+		*ast.SelectorExpr,
+		*ast.IndexExpr,
+		*ast.SliceExpr,
+		*ast.TypeAssertExpr,
+		*ast.CallExpr,
+		*ast.StarExpr,
+		*ast.KeyValueExpr,
+		*ast.ArrayType,
+		*ast.StructType,
+		*ast.FuncType,
+		*ast.InterfaceType,
+		*ast.MapType,
+		*ast.ChanType:
+		// these expression are never untyped - nothing to do
+		return
+
+	case *ast.Ident, *ast.BasicLit:
+		// update type
+
+	case *ast.ParenExpr:
+		check.updateExprType(x.X, typ, false)
+
+	case *ast.UnaryExpr:
+		check.updateExprType(x.X, typ, false)
+
+	case *ast.BinaryExpr:
+		if isComparison(x.Op) {
+			// result type is independent of operand types
+		} else if isShift(x.Op) {
+			// result type depends only on lhs operand
+			check.updateExprType(x.X, typ, true)
+		} else {
+			// operand types match result type
+			check.updateExprType(x.X, typ, false)
+			check.updateExprType(x.Y, typ, false)
+		}
+
+	case *ast.Ellipsis:
+		unreachable()
+	default:
+		unreachable()
+	}
+
+	// TODO(gri) t should always exist, shouldn't it?
+	if t := check.untyped[x]; t != nil {
+		if isUntyped(typ) {
+			check.untyped[x] = typ.(*Basic)
+		} else {
+			// notify clients of final type for x
+			if f := check.ctxt.Expr; f != nil {
+				f(x, typ, check.constants[x])
+			}
+			delete(check.untyped, x)
+			delete(check.constants, x)
+			// check delayed shift
+			// Note: Using shiftOp is an optimization: it prevents
+			// map lookups when we know x is not a shiftOp in the
+			// first place.
+			if shiftOp && check.shiftOps[x] {
+				if !isInteger(typ) {
+					check.invalidOp(x.Pos(), "shifted operand %s (type %s) must be integer", x, typ)
+				}
+				delete(check.shiftOps, x)
+			}
+		}
+	}
+}
+
+// convertUntyped attempts to set the type of an untyped value to the target type.
+func (check *checker) convertUntyped(x *operand, target Type) {
+	if x.mode == invalid || !isUntyped(x.typ) {
+		return
+	}
+
+	// TODO(gri) Sloppy code - clean up. This function is central
+	//           to assignment and expression checking.
+
+	if isUntyped(target) {
+		// both x and target are untyped
+		xkind := x.typ.(*Basic).Kind
+		tkind := target.(*Basic).Kind
+		if isNumeric(x.typ) && isNumeric(target) {
+			if xkind < tkind {
+				x.typ = target
+				check.updateExprType(x.expr, target, false)
+			}
+		} else if xkind != tkind {
+			goto Error
+		}
+		return
+	}
+
+	// typed target
+	switch t := underlying(target).(type) {
+	case nil:
+		// We may reach here due to previous type errors.
+		// Be conservative and don't crash.
+		x.mode = invalid
+		return
+	case *Basic:
+		check.isRepresentable(x, t)
+		if x.mode == invalid {
+			return // error already reported
+		}
+	case *Interface:
+		if !x.isNil() && len(t.Methods) > 0 /* empty interfaces are ok */ {
+			goto Error
+		}
+		// Update operand types to the default type rather then
+		// the target (interface) type: values must have concrete
+		// dynamic types. If the value is nil, keep it untyped
+		// (this is important for tools such as go vet which need
+		// the dynamic type for argument checking of say, print
+		// functions)
+		if x.isNil() {
+			target = Typ[UntypedNil]
+		} else {
+			// cannot assign untyped values to non-empty interfaces
+			if len(t.Methods) > 0 {
+				goto Error
+			}
+			target = defaultType(x.typ)
+		}
+	case *Pointer, *Signature, *Slice, *Map, *Chan:
+		if !x.isNil() {
+			goto Error
+		}
+		// keep nil untyped - see comment for interfaces, above
+		target = Typ[UntypedNil]
+	default:
+		if debug {
+			check.dump("convertUntyped(x = %v, target = %v)", x, target)
+		}
+		unreachable()
+	}
+
+	x.typ = target
+	check.updateExprType(x.expr, target, false)
+	return
+
+Error:
+	check.errorf(x.pos(), "cannot convert %s to %s", x, target)
+	x.mode = invalid
+}
+
+func (check *checker) comparison(x, y *operand, op token.Token) {
+	// TODO(gri) deal with interface vs non-interface comparison
+
+	valid := false
+	if x.isAssignable(check.ctxt, y.typ) || y.isAssignable(check.ctxt, x.typ) {
+		switch op {
+		case token.EQL, token.NEQ:
+			valid = isComparable(x.typ) ||
+				x.isNil() && hasNil(y.typ) ||
+				y.isNil() && hasNil(x.typ)
+		case token.LSS, token.LEQ, token.GTR, token.GEQ:
+			valid = isOrdered(x.typ)
+		default:
+			unreachable()
+		}
+	}
+
+	if !valid {
+		check.invalidOp(x.pos(), "cannot compare %s %s %s", x, op, y)
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant && y.mode == constant {
+		x.val = compareConst(x.val, y.val, op)
+	} else {
+		x.mode = value
+	}
+
+	x.typ = Typ[UntypedBool]
+}
+
+func (check *checker) shift(x, y *operand, op token.Token) {
+	// spec: "The right operand in a shift expression must have unsigned
+	// integer type or be an untyped constant that can be converted to
+	// unsigned integer type."
+	switch {
+	case isInteger(y.typ) && isUnsigned(y.typ):
+		// nothing to do
+	case y.mode == constant && isUntyped(y.typ):
+		check.convertUntyped(x, Typ[UntypedInt])
+	default:
+		check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y)
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant {
+		if y.mode == constant {
+			// constant shift - lhs must be (representable as) an integer
+			if isUntyped(x.typ) {
+				if !isRepresentableConst(x.val, check.ctxt, UntypedInt) {
+					check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
+					x.mode = invalid
+					return
+				}
+				x.typ = Typ[UntypedInt]
+			}
+			assert(x.isInteger(check.ctxt))
+
+			// rhs must be within reasonable bounds
+			const stupidShift = 1024
+			s, ok := y.val.(int64)
+			if !ok || s < 0 || s >= stupidShift {
+				check.invalidOp(y.pos(), "%s: stupid shift", y)
+				x.mode = invalid
+				return
+			}
+
+			// everything's ok
+			x.val = shiftConst(x.val, uint(s), op)
+			return
+		}
+
+		// non-constant shift with constant lhs
+		if isUntyped(x.typ) {
+			// spec: "If the left operand of a non-constant shift expression is
+			// an untyped constant, the type of the constant is what it would be
+			// if the shift expression were replaced by its left operand alone;
+			// the type is int if it cannot be determined from the context (for
+			// instance, if the shift expression is an operand in a comparison
+			// against an untyped constant)".
+
+			// delay operand checking until we know the type
+			check.shiftOps[x.expr] = true
+			x.mode = value
+			return
+		}
+	}
+
+	// non-constant shift - lhs must be an integer
+	if !isInteger(x.typ) {
+		check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
+		x.mode = invalid
+		return
+	}
+
+	// non-constant shift
+	x.mode = value
+}
+
+var binaryOpPredicates = opPredicates{
+	token.ADD: func(typ Type) bool { return isNumeric(typ) || isString(typ) },
+	token.SUB: isNumeric,
+	token.MUL: isNumeric,
+	token.QUO: isNumeric,
+	token.REM: isInteger,
+
+	token.AND:     isInteger,
+	token.OR:      isInteger,
+	token.XOR:     isInteger,
+	token.AND_NOT: isInteger,
+
+	token.LAND: isBoolean,
+	token.LOR:  isBoolean,
+}
+
+func (check *checker) binary(x *operand, lhs, rhs ast.Expr, op token.Token, iota int) {
+	var y operand
+
+	check.expr(x, lhs, nil, iota)
+	check.expr(&y, rhs, nil, iota)
+
+	if x.mode == invalid {
+		return
+	}
+	if y.mode == invalid {
+		x.mode = invalid
+		x.expr = y.expr
+		return
+	}
+
+	if isShift(op) {
+		check.shift(x, &y, op)
+		return
+	}
+
+	check.convertUntyped(x, y.typ)
+	if x.mode == invalid {
+		return
+	}
+	check.convertUntyped(&y, x.typ)
+	if y.mode == invalid {
+		x.mode = invalid
+		return
+	}
+
+	if isComparison(op) {
+		check.comparison(x, &y, op)
+		return
+	}
+
+	if !IsIdentical(x.typ, y.typ) {
+		check.invalidOp(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
+		x.mode = invalid
+		return
+	}
+
+	if !check.op(binaryOpPredicates, x, op) {
+		x.mode = invalid
+		return
+	}
+
+	if (op == token.QUO || op == token.REM) && y.mode == constant && isZeroConst(y.val) {
+		check.invalidOp(y.pos(), "division by zero")
+		x.mode = invalid
+		return
+	}
+
+	if x.mode == constant && y.mode == constant {
+		typ := underlying(x.typ).(*Basic)
+		x.val = binaryOpConst(x.val, y.val, op, typ)
+		// Typed constants must be representable in
+		// their type after each constant operation.
+		check.isRepresentable(x, typ)
+		return
+	}
+
+	x.mode = value
+	// x.typ is unchanged
+}
+
+// index checks an index expression for validity. If length >= 0, it is the upper
+// bound for the index. The result is a valid index >= 0, or a negative value.
+//
+func (check *checker) index(index ast.Expr, length int64, iota int) int64 {
+	var x operand
+
+	check.expr(&x, index, nil, iota)
+	if !x.isInteger(check.ctxt) {
+		check.errorf(x.pos(), "index %s must be integer", &x)
+		return -1
+	}
+	if x.mode != constant {
+		return -1 // we cannot check more
+	}
+	// The spec doesn't require int64 indices, but perhaps it should.
+	i, ok := x.val.(int64)
+	if !ok {
+		check.errorf(x.pos(), "stupid index %s", &x)
+		return -1
+	}
+	if i < 0 {
+		check.errorf(x.pos(), "index %s must not be negative", &x)
+		return -1
+	}
+	if length >= 0 && i >= length {
+		check.errorf(x.pos(), "index %s is out of bounds (>= %d)", &x, length)
+		return -1
+	}
+
+	return i
+}
+
+// compositeLitKey resolves unresolved composite literal keys.
+// For details, see comment in go/parser/parser.go, method parseElement.
+func (check *checker) compositeLitKey(key ast.Expr) {
+	if ident, ok := key.(*ast.Ident); ok && ident.Obj == nil {
+		if obj := check.pkg.Scope.Lookup(ident.Name); obj != nil {
+			check.register(ident, obj)
+		} else if obj := Universe.Lookup(ident.Name); obj != nil {
+			check.register(ident, obj)
+		} else {
+			check.errorf(ident.Pos(), "undeclared name: %s", ident.Name)
+		}
+	}
+}
+
+// indexElts checks the elements (elts) of an array or slice composite literal
+// against the literal's element type (typ), and the element indices against
+// the literal length if known (length >= 0). It returns the length of the
+// literal (maximum index value + 1).
+//
+func (check *checker) indexedElts(elts []ast.Expr, typ Type, length int64, iota int) int64 {
+	visited := make(map[int64]bool, len(elts))
+	var index, max int64
+	for _, e := range elts {
+		// determine and check index
+		validIndex := false
+		eval := e
+		if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+			check.compositeLitKey(kv.Key)
+			if i := check.index(kv.Key, length, iota); i >= 0 {
+				index = i
+				validIndex = true
+			}
+			eval = kv.Value
+		} else if length >= 0 && index >= length {
+			check.errorf(e.Pos(), "index %d is out of bounds (>= %d)", index, length)
+		} else {
+			validIndex = true
+		}
+
+		// if we have a valid index, check for duplicate entries
+		if validIndex {
+			if visited[index] {
+				check.errorf(e.Pos(), "duplicate index %d in array or slice literal", index)
+			}
+			visited[index] = true
+		}
+		index++
+		if index > max {
+			max = index
+		}
+
+		// check element against composite literal element type
+		var x operand
+		check.expr(&x, eval, typ, iota)
+		if !check.assignment(&x, typ) && x.mode != invalid {
+			check.errorf(x.pos(), "cannot use %s as %s value in array or slice literal", &x, typ)
+		}
+	}
+	return max
+}
+
+// argument typechecks passing an argument arg (if arg != nil) or
+// x (if arg == nil) to the i'th parameter of the given signature.
+// If passSlice is set, the argument is followed by ... in the call.
+//
+func (check *checker) argument(sig *Signature, i int, arg ast.Expr, x *operand, passSlice bool) {
+	// determine parameter
+	var par *Var
+	n := len(sig.Params)
+	if i < n {
+		par = sig.Params[i]
+	} else if sig.IsVariadic {
+		par = sig.Params[n-1]
+	} else {
+		check.errorf(arg.Pos(), "too many arguments")
+		return
+	}
+
+	// determine argument
+	var z operand
+	z.mode = variable
+	z.expr = nil // TODO(gri) can we do better here? (for good error messages)
+	z.typ = par.Type
+
+	if arg != nil {
+		check.expr(x, arg, z.typ, -1)
+	}
+	if x.mode == invalid {
+		return // ignore this argument
+	}
+
+	// check last argument of the form x...
+	if passSlice {
+		if i+1 != n {
+			check.errorf(x.pos(), "can only use ... with matching parameter")
+			return // ignore this argument
+		}
+		// spec: "If the final argument is assignable to a slice type []T,
+		// it may be passed unchanged as the value for a ...T parameter if
+		// the argument is followed by ..."
+		z.typ = &Slice{Elt: z.typ} // change final parameter type to []T
+	}
+
+	if !check.assignment(x, z.typ) && x.mode != invalid {
+		check.errorf(x.pos(), "cannot pass argument %s to %s", x, &z)
+	}
+}
+
+var emptyResult Result
+
+func (check *checker) callExpr(x *operand) {
+	var typ Type
+	var val interface{}
+	switch x.mode {
+	case invalid:
+		return // nothing to do
+	case novalue:
+		typ = &emptyResult
+	case constant:
+		typ = x.typ
+		val = x.val
+	default:
+		typ = x.typ
+	}
+
+	// if the operand is untyped, delay notification
+	// until it becomes typed or until the end of
+	// type checking
+	if isUntyped(typ) {
+		check.untyped[x.expr] = typ.(*Basic)
+		if val != nil {
+			check.constants[x.expr] = val
+		}
+		return
+	}
+
+	// TODO(gri) ensure that literals always report
+	// their dynamic (never interface) type.
+	// This is not the case yet.
+
+	if check.ctxt.Expr != nil {
+		check.ctxt.Expr(x.expr, typ, val)
+	}
+}
+
+// rawExpr typechecks expression e and initializes x with the expression
+// value or type. If an error occurred, x.mode is set to invalid.
+// If hint != nil, it is the type of a composite literal element.
+// iota >= 0 indicates that the expression is part of a constant declaration.
+// cycleOk indicates whether it is ok for a type expression to refer to itself.
+//
+func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycleOk bool) {
+	if trace {
+		c := ""
+		if cycleOk {
+			c = " ⨁"
+		}
+		check.trace(e.Pos(), "%s (%s, %d%s)", e, typeString(hint), iota, c)
+		defer check.untrace("=> %s", x)
+	}
+
+	defer check.callExpr(x)
+
+	switch e := e.(type) {
+	case *ast.BadExpr:
+		goto Error // error was reported before
+
+	case *ast.Ident:
+		if e.Name == "_" {
+			check.invalidOp(e.Pos(), "cannot use _ as value or type")
+			goto Error
+		}
+		obj := check.lookup(e)
+		if obj == nil {
+			goto Error // error was reported before
+		}
+		check.object(obj, cycleOk)
+		switch obj := obj.(type) {
+		case *Package:
+			check.errorf(e.Pos(), "use of package %s not in selector", obj.Name)
+			goto Error
+		case *Const:
+			if obj.Val == nil {
+				goto Error // cycle detected
+			}
+			x.mode = constant
+			if obj == universeIota {
+				if iota < 0 {
+					check.invalidAST(e.Pos(), "cannot use iota outside constant declaration")
+					goto Error
+				}
+				x.val = int64(iota)
+			} else {
+				x.val = obj.Val
+			}
+		case *TypeName:
+			x.mode = typexpr
+			if !cycleOk && underlying(obj.Type) == nil {
+				check.errorf(obj.spec.Pos(), "illegal cycle in declaration of %s", obj.Name)
+				x.expr = e
+				x.typ = Typ[Invalid]
+				return // don't goto Error - need x.mode == typexpr
+			}
+		case *Var:
+			x.mode = variable
+		case *Func:
+			x.mode = value
+		default:
+			unreachable()
+		}
+		x.typ = obj.GetType()
+
+	case *ast.Ellipsis:
+		// ellipses are handled explicitly where they are legal
+		// (array composite literals and parameter lists)
+		check.errorf(e.Pos(), "invalid use of '...'")
+		goto Error
+
+	case *ast.BasicLit:
+		x.setConst(e.Kind, e.Value)
+		if x.mode == invalid {
+			check.invalidAST(e.Pos(), "invalid literal %v", e.Value)
+			goto Error
+		}
+
+	case *ast.FuncLit:
+		if sig, ok := check.typ(e.Type, false).(*Signature); ok {
+			x.mode = value
+			x.typ = sig
+			check.later(nil, sig, e.Body)
+		} else {
+			check.invalidAST(e.Pos(), "invalid function literal %s", e)
+			goto Error
+		}
+
+	case *ast.CompositeLit:
+		typ := hint
+		openArray := false
+		if e.Type != nil {
+			// [...]T array types may only appear with composite literals.
+			// Check for them here so we don't have to handle ... in general.
+			typ = nil
+			if atyp, _ := e.Type.(*ast.ArrayType); atyp != nil && atyp.Len != nil {
+				if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip != nil && ellip.Elt == nil {
+					// We have an "open" [...]T array type.
+					// Create a new ArrayType with unknown length (-1)
+					// and finish setting it up after analyzing the literal.
+					typ = &Array{Len: -1, Elt: check.typ(atyp.Elt, cycleOk)}
+					openArray = true
+				}
+			}
+			if typ == nil {
+				typ = check.typ(e.Type, false)
+			}
+		}
+		if typ == nil {
+			check.errorf(e.Pos(), "missing type in composite literal")
+			goto Error
+		}
+
+		switch utyp := underlying(deref(typ)).(type) {
+		case *Struct:
+			if len(e.Elts) == 0 {
+				break
+			}
+			fields := utyp.Fields
+			if _, ok := e.Elts[0].(*ast.KeyValueExpr); ok {
+				// all elements must have keys
+				visited := make([]bool, len(fields))
+				for _, e := range e.Elts {
+					kv, _ := e.(*ast.KeyValueExpr)
+					if kv == nil {
+						check.errorf(e.Pos(), "mixture of field:value and value elements in struct literal")
+						continue
+					}
+					key, _ := kv.Key.(*ast.Ident)
+					if key == nil {
+						check.errorf(kv.Pos(), "invalid field name %s in struct literal", kv.Key)
+						continue
+					}
+					i := utyp.fieldIndex(QualifiedName{check.pkg, key.Name})
+					if i < 0 {
+						check.errorf(kv.Pos(), "unknown field %s in struct literal", key.Name)
+						continue
+					}
+					// 0 <= i < len(fields)
+					if visited[i] {
+						check.errorf(kv.Pos(), "duplicate field name %s in struct literal", key.Name)
+						continue
+					}
+					visited[i] = true
+					check.expr(x, kv.Value, nil, iota)
+					etyp := fields[i].Type
+					if !check.assignment(x, etyp) {
+						if x.mode != invalid {
+							check.errorf(x.pos(), "cannot use %s as %s value in struct literal", x, etyp)
+						}
+						continue
+					}
+				}
+			} else {
+				// no element must have a key
+				for i, e := range e.Elts {
+					if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+						check.errorf(kv.Pos(), "mixture of field:value and value elements in struct literal")
+						continue
+					}
+					check.expr(x, e, nil, iota)
+					if i >= len(fields) {
+						check.errorf(x.pos(), "too many values in struct literal")
+						break // cannot continue
+					}
+					// i < len(fields)
+					etyp := fields[i].Type
+					if !check.assignment(x, etyp) {
+						if x.mode != invalid {
+							check.errorf(x.pos(), "cannot use %s as %s value in struct literal", x, etyp)
+						}
+						continue
+					}
+				}
+				if len(e.Elts) < len(fields) {
+					check.errorf(e.Rbrace, "too few values in struct literal")
+					// ok to continue
+				}
+			}
+
+		case *Array:
+			n := check.indexedElts(e.Elts, utyp.Elt, utyp.Len, iota)
+			// if we have an "open" [...]T array, set the length now that we know it
+			if openArray {
+				utyp.Len = n
+			}
+
+		case *Slice:
+			check.indexedElts(e.Elts, utyp.Elt, -1, iota)
+
+		case *Map:
+			visited := make(map[interface{}]bool, len(e.Elts))
+			for _, e := range e.Elts {
+				kv, _ := e.(*ast.KeyValueExpr)
+				if kv == nil {
+					check.errorf(e.Pos(), "missing key in map literal")
+					continue
+				}
+				check.compositeLitKey(kv.Key)
+				check.expr(x, kv.Key, nil, iota)
+				if !check.assignment(x, utyp.Key) {
+					if x.mode != invalid {
+						check.errorf(x.pos(), "cannot use %s as %s key in map literal", x, utyp.Key)
+					}
+					continue
+				}
+				if x.mode == constant {
+					if visited[x.val] {
+						check.errorf(x.pos(), "duplicate key %s in map literal", x.val)
+						continue
+					}
+					visited[x.val] = true
+				}
+				check.expr(x, kv.Value, utyp.Elt, iota)
+				if !check.assignment(x, utyp.Elt) {
+					if x.mode != invalid {
+						check.errorf(x.pos(), "cannot use %s as %s value in map literal", x, utyp.Elt)
+					}
+					continue
+				}
+			}
+
+		default:
+			check.errorf(e.Pos(), "%s is not a valid composite literal type", typ)
+			goto Error
+		}
+
+		x.mode = value
+		x.typ = typ
+
+	case *ast.ParenExpr:
+		check.rawExpr(x, e.X, nil, iota, cycleOk)
+
+	case *ast.SelectorExpr:
+		sel := e.Sel.Name
+		// If the identifier refers to a package, handle everything here
+		// so we don't need a "package" mode for operands: package names
+		// can only appear in qualified identifiers which are mapped to
+		// selector expressions.
+		if ident, ok := e.X.(*ast.Ident); ok {
+			if pkg, ok := check.lookup(ident).(*Package); ok {
+				exp := pkg.Scope.Lookup(sel)
+				// gcimported package scopes contain non-exported
+				// objects such as types used in partially exported
+				// objects - do not accept them
+				if exp == nil || !ast.IsExported(exp.GetName()) {
+					check.errorf(e.Pos(), "cannot refer to unexported %s", e)
+					goto Error
+				}
+				check.register(e.Sel, exp)
+				// Simplified version of the code for *ast.Idents:
+				// - imported packages use types.Scope and types.Objects
+				// - imported objects are always fully initialized
+				switch exp := exp.(type) {
+				case *Const:
+					assert(exp.Val != nil)
+					x.mode = constant
+					x.typ = exp.Type
+					x.val = exp.Val
+				case *TypeName:
+					x.mode = typexpr
+					x.typ = exp.Type
+				case *Var:
+					x.mode = variable
+					x.typ = exp.Type
+				case *Func:
+					x.mode = value
+					x.typ = exp.Type
+				default:
+					unreachable()
+				}
+				x.expr = e
+				return
+			}
+		}
+
+		check.exprOrType(x, e.X, iota, false)
+		if x.mode == invalid {
+			goto Error
+		}
+		res := lookupField(x.typ, QualifiedName{check.pkg, sel})
+		if res.mode == invalid {
+			check.invalidOp(e.Pos(), "%s has no single field or method %s", x, sel)
+			goto Error
+		}
+		if x.mode == typexpr {
+			// method expression
+			sig, ok := res.typ.(*Signature)
+			if !ok {
+				check.invalidOp(e.Pos(), "%s has no method %s", x, sel)
+				goto Error
+			}
+			// the receiver type becomes the type of the first function
+			// argument of the method expression's function type
+			// TODO(gri) at the moment, method sets don't correctly track
+			// pointer vs non-pointer receivers => typechecker is too lenient
+			x.mode = value
+			x.typ = &Signature{
+				Params:     append([]*Var{{Type: x.typ}}, sig.Params...),
+				Results:    sig.Results,
+				IsVariadic: sig.IsVariadic,
+			}
+		} else {
+			// regular selector
+			x.mode = res.mode
+			x.typ = res.typ
+		}
+
+	case *ast.IndexExpr:
+		check.expr(x, e.X, nil, iota)
+		if x.mode == invalid {
+			goto Error
+		}
+
+		valid := false
+		length := int64(-1) // valid if >= 0
+		switch typ := underlying(x.typ).(type) {
+		case *Basic:
+			if isString(typ) {
+				valid = true
+				if x.mode == constant {
+					length = int64(len(x.val.(string)))
+				}
+				// an indexed string always yields a byte value
+				// (not a constant) even if the string and the
+				// index are constant
+				x.mode = value
+				x.typ = Typ[Byte]
+			}
+
+		case *Array:
+			valid = true
+			length = typ.Len
+			if x.mode != variable {
+				x.mode = value
+			}
+			x.typ = typ.Elt
+
+		case *Pointer:
+			if typ, _ := underlying(typ.Base).(*Array); typ != nil {
+				valid = true
+				length = typ.Len
+				x.mode = variable
+				x.typ = typ.Elt
+			}
+
+		case *Slice:
+			valid = true
+			x.mode = variable
+			x.typ = typ.Elt
+
+		case *Map:
+			var key operand
+			check.expr(&key, e.Index, nil, iota)
+			if !check.assignment(&key, typ.Key) {
+				if key.mode != invalid {
+					check.invalidOp(key.pos(), "cannot use %s as map index of type %s", &key, typ.Key)
+				}
+				goto Error
+			}
+			x.mode = valueok
+			x.typ = typ.Elt
+			x.expr = e
+			return
+		}
+
+		if !valid {
+			check.invalidOp(x.pos(), "cannot index %s", x)
+			goto Error
+		}
+
+		if e.Index == nil {
+			check.invalidAST(e.Pos(), "missing index expression for %s", x)
+			return
+		}
+
+		check.index(e.Index, length, iota)
+		// ok to continue
+
+	case *ast.SliceExpr:
+		check.expr(x, e.X, nil, iota)
+		if x.mode == invalid {
+			goto Error
+		}
+
+		valid := false
+		length := int64(-1) // valid if >= 0
+		switch typ := underlying(x.typ).(type) {
+		case *Basic:
+			if isString(typ) {
+				valid = true
+				if x.mode == constant {
+					length = int64(len(x.val.(string))) + 1 // +1 for slice
+				}
+				// a sliced string always yields a string value
+				// of the same type as the original string (not
+				// a constant) even if the string and the indices
+				// are constant
+				x.mode = value
+				// x.typ doesn't change, but if it is an untyped
+				// string it becomes string (see also issue 4913).
+				if typ.Kind == UntypedString {
+					x.typ = Typ[String]
+				}
+			}
+
+		case *Array:
+			valid = true
+			length = typ.Len + 1 // +1 for slice
+			if x.mode != variable {
+				check.invalidOp(x.pos(), "cannot slice %s (value not addressable)", x)
+				goto Error
+			}
+			x.typ = &Slice{Elt: typ.Elt}
+
+		case *Pointer:
+			if typ, _ := underlying(typ.Base).(*Array); typ != nil {
+				valid = true
+				length = typ.Len + 1 // +1 for slice
+				x.mode = variable
+				x.typ = &Slice{Elt: typ.Elt}
+			}
+
+		case *Slice:
+			valid = true
+			x.mode = variable
+			// x.typ doesn't change
+		}
+
+		if !valid {
+			check.invalidOp(x.pos(), "cannot slice %s", x)
+			goto Error
+		}
+
+		lo := int64(0)
+		if e.Low != nil {
+			lo = check.index(e.Low, length, iota)
+		}
+
+		hi := int64(-1)
+		if e.High != nil {
+			hi = check.index(e.High, length, iota)
+		} else if length >= 0 {
+			hi = length
+		}
+
+		if lo >= 0 && hi >= 0 && lo > hi {
+			check.errorf(e.Low.Pos(), "inverted slice range: %d > %d", lo, hi)
+			// ok to continue
+		}
+
+	case *ast.TypeAssertExpr:
+		check.expr(x, e.X, nil, iota)
+		if x.mode == invalid {
+			goto Error
+		}
+		var T *Interface
+		if T, _ = underlying(x.typ).(*Interface); T == nil {
+			check.invalidOp(x.pos(), "%s is not an interface", x)
+			goto Error
+		}
+		// x.(type) expressions are handled explicitly in type switches
+		if e.Type == nil {
+			check.errorf(e.Pos(), "use of .(type) outside type switch")
+			goto Error
+		}
+		typ := check.typ(e.Type, false)
+		if typ == Typ[Invalid] {
+			goto Error
+		}
+		if method, wrongType := missingMethod(typ, T); method != nil {
+			var msg string
+			if wrongType {
+				msg = "%s cannot have dynamic type %s (wrong type for method %s)"
+			} else {
+				msg = "%s cannot have dynamic type %s (missing method %s)"
+			}
+			check.errorf(e.Type.Pos(), msg, x, typ, method.Name)
+			// ok to continue
+		}
+		x.mode = valueok
+		x.expr = e
+		x.typ = typ
+
+	case *ast.CallExpr:
+		check.exprOrType(x, e.Fun, iota, false)
+		if x.mode == invalid {
+			goto Error
+		} else if x.mode == typexpr {
+			check.conversion(x, e, x.typ, iota)
+		} else if sig, ok := underlying(x.typ).(*Signature); ok {
+			// check parameters
+
+			// If we have a trailing ... at the end of the parameter
+			// list, the last argument must match the parameter type
+			// []T of a variadic function parameter x ...T.
+			passSlice := false
+			if e.Ellipsis.IsValid() {
+				if sig.IsVariadic {
+					passSlice = true
+				} else {
+					check.errorf(e.Ellipsis, "cannot use ... in call to %s", e.Fun)
+					// ok to continue
+				}
+			}
+
+			// If we have a single argument that is a function call
+			// we need to handle it separately. Determine if this
+			// is the case without checking the argument.
+			var call *ast.CallExpr
+			if len(e.Args) == 1 {
+				call, _ = unparen(e.Args[0]).(*ast.CallExpr)
+			}
+
+			n := 0 // parameter count
+			if call != nil {
+				// We have a single argument that is a function call.
+				check.expr(x, call, nil, -1)
+				if x.mode == invalid {
+					goto Error // TODO(gri): we can do better
+				}
+				if t, _ := x.typ.(*Result); t != nil {
+					// multiple result values
+					n = len(t.Values)
+					for i, obj := range t.Values {
+						x.mode = value
+						x.expr = nil // TODO(gri) can we do better here? (for good error messages)
+						x.typ = obj.Type
+						check.argument(sig, i, nil, x, passSlice && i+1 == n)
+					}
+				} else {
+					// single result value
+					n = 1
+					check.argument(sig, 0, nil, x, passSlice)
+				}
+
+			} else {
+				// We don't have a single argument or it is not a function call.
+				n = len(e.Args)
+				for i, arg := range e.Args {
+					check.argument(sig, i, arg, x, passSlice && i+1 == n)
+				}
+			}
+
+			// determine if we have enough arguments
+			if sig.IsVariadic {
+				// a variadic function accepts an "empty"
+				// last argument: count one extra
+				n++
+			}
+			if n < len(sig.Params) {
+				check.errorf(e.Fun.Pos(), "too few arguments in call to %s", e.Fun)
+				// ok to continue
+			}
+
+			// determine result
+			switch len(sig.Results) {
+			case 0:
+				x.mode = novalue
+			case 1:
+				x.mode = value
+				x.typ = sig.Results[0].Type
+			default:
+				x.mode = value
+				x.typ = &Result{Values: sig.Results}
+			}
+
+		} else if bin, ok := x.typ.(*builtin); ok {
+			check.builtin(x, e, bin, iota)
+
+		} else {
+			check.invalidOp(x.pos(), "cannot call non-function %s", x)
+			goto Error
+		}
+
+	case *ast.StarExpr:
+		check.exprOrType(x, e.X, iota, true)
+		switch x.mode {
+		case invalid:
+			goto Error
+		case typexpr:
+			x.typ = &Pointer{Base: x.typ}
+		default:
+			if typ, ok := underlying(x.typ).(*Pointer); ok {
+				x.mode = variable
+				x.typ = typ.Base
+			} else {
+				check.invalidOp(x.pos(), "cannot indirect %s", x)
+				goto Error
+			}
+		}
+
+	case *ast.UnaryExpr:
+		check.expr(x, e.X, nil, iota)
+		if x.mode == invalid {
+			goto Error
+		}
+		check.unary(x, e.Op)
+		if x.mode == invalid {
+			goto Error
+		}
+
+	case *ast.BinaryExpr:
+		check.binary(x, e.X, e.Y, e.Op, iota)
+		if x.mode == invalid {
+			goto Error
+		}
+
+	case *ast.KeyValueExpr:
+		// key:value expressions are handled in composite literals
+		check.invalidAST(e.Pos(), "no key:value expected")
+		goto Error
+
+	case *ast.ArrayType:
+		if e.Len != nil {
+			check.expr(x, e.Len, nil, iota)
+			if x.mode == invalid {
+				goto Error
+			}
+			if x.mode != constant {
+				if x.mode != invalid {
+					check.errorf(x.pos(), "array length %s must be constant", x)
+				}
+				goto Error
+			}
+			n, ok := x.val.(int64)
+			if !ok || n < 0 {
+				check.errorf(x.pos(), "invalid array length %s", x)
+				goto Error
+			}
+			x.typ = &Array{Len: n, Elt: check.typ(e.Elt, cycleOk)}
+		} else {
+			x.typ = &Slice{Elt: check.typ(e.Elt, true)}
+		}
+		x.mode = typexpr
+
+	case *ast.StructType:
+		x.mode = typexpr
+		x.typ = &Struct{Fields: check.collectFields(e.Fields, cycleOk)}
+
+	case *ast.FuncType:
+		params, isVariadic := check.collectParams(e.Params, true)
+		results, _ := check.collectParams(e.Results, false)
+		x.mode = typexpr
+		x.typ = &Signature{Recv: nil, Params: params, Results: results, IsVariadic: isVariadic}
+
+	case *ast.InterfaceType:
+		x.mode = typexpr
+		x.typ = &Interface{Methods: check.collectMethods(e.Methods)}
+
+	case *ast.MapType:
+		x.mode = typexpr
+		x.typ = &Map{Key: check.typ(e.Key, true), Elt: check.typ(e.Value, true)}
+
+	case *ast.ChanType:
+		x.mode = typexpr
+		x.typ = &Chan{Dir: e.Dir, Elt: check.typ(e.Value, true)}
+
+	default:
+		if debug {
+			check.dump("expr = %v (%T)", e, e)
+		}
+		unreachable()
+	}
+
+	// everything went well
+	x.expr = e
+	return
+
+Error:
+	x.mode = invalid
+	x.expr = e
+}
+
+// exprOrType is like rawExpr but reports an error if e doesn't represents a value or type.
+func (check *checker) exprOrType(x *operand, e ast.Expr, iota int, cycleOk bool) {
+	check.rawExpr(x, e, nil, iota, cycleOk)
+	if x.mode == novalue {
+		check.errorf(x.pos(), "%s used as value or type", x)
+		x.mode = invalid
+	}
+}
+
+// expr is like rawExpr but reports an error if e doesn't represents a value.
+func (check *checker) expr(x *operand, e ast.Expr, hint Type, iota int) {
+	check.rawExpr(x, e, hint, iota, false)
+	switch x.mode {
+	case novalue:
+		check.errorf(x.pos(), "%s used as value", x)
+		x.mode = invalid
+	case typexpr:
+		check.errorf(x.pos(), "%s is not an expression", x)
+		x.mode = invalid
+	}
+}
+
+func (check *checker) rawTyp(e ast.Expr, cycleOk, nilOk bool) Type {
+	var x operand
+	check.rawExpr(&x, e, nil, -1, cycleOk)
+	switch x.mode {
+	case invalid:
+		// ignore - error reported before
+	case novalue:
+		check.errorf(x.pos(), "%s used as type", &x)
+	case typexpr:
+		return x.typ
+	case constant:
+		if nilOk && x.isNil() {
+			return nil
+		}
+		fallthrough
+	default:
+		check.errorf(x.pos(), "%s is not a type", &x)
+	}
+	return Typ[Invalid]
+}
+
+// typOrNil is like rawExpr but reports an error if e doesn't represents a type or the predeclared value nil.
+// It returns e's type, nil, or Typ[Invalid] if an error occurred.
+//
+func (check *checker) typOrNil(e ast.Expr, cycleOk bool) Type {
+	return check.rawTyp(e, cycleOk, true)
+}
+
+// typ is like rawExpr but reports an error if e doesn't represents a type.
+// It returns e's type, or Typ[Invalid] if an error occurred.
+//
+func (check *checker) typ(e ast.Expr, cycleOk bool) Type {
+	return check.rawTyp(e, cycleOk, false)
+}
diff --git a/src/pkg/go/types/gcimporter.go b/src/pkg/go/types/gcimporter.go
new file mode 100644
index 0000000..7f968eb
--- /dev/null
+++ b/src/pkg/go/types/gcimporter.go
@@ -0,0 +1,950 @@
+// 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 implements an Importer for gc-generated object files.
+
+package types
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/token"
+	"io"
+	"math/big"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"text/scanner"
+)
+
+var pkgExts = [...]string{".a", ".5", ".6", ".8"}
+
+// FindPkg returns the filename and unique package id for an import
+// path based on package information provided by build.Import (using
+// the build.Default build.Context).
+// If no file was found, an empty filename is returned.
+//
+func FindPkg(path, srcDir string) (filename, id string) {
+	if len(path) == 0 {
+		return
+	}
+
+	id = path
+	var noext string
+	switch {
+	default:
+		// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
+		// Don't require the source files to be present.
+		bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
+		if bp.PkgObj == "" {
+			return
+		}
+		noext = strings.TrimSuffix(bp.PkgObj, ".a")
+
+	case build.IsLocalImport(path):
+		// "./x" -> "/this/directory/x.ext", "/this/directory/x"
+		noext = filepath.Join(srcDir, path)
+		id = noext
+
+	case filepath.IsAbs(path):
+		// for completeness only - go/build.Import
+		// does not support absolute imports
+		// "/x" -> "/x.ext", "/x"
+		noext = path
+	}
+
+	// try extensions
+	for _, ext := range pkgExts {
+		filename = noext + ext
+		if f, err := os.Stat(filename); err == nil && !f.IsDir() {
+			return
+		}
+	}
+
+	filename = "" // not found
+	return
+}
+
+// GcImportData imports a package by reading the gc-generated export data,
+// adds the corresponding package object to the imports map indexed by id,
+// and returns the object.
+//
+// The imports map must contains all packages already imported. The data
+// reader position must be the beginning of the export data section. The
+// filename is only used in error messages.
+//
+// If imports[id] contains the completely imported package, that package
+// can be used directly, and there is no need to call this function (but
+// there is also no harm but for extra time used).
+//
+func GcImportData(imports map[string]*Package, filename, id string, data *bufio.Reader) (pkg *Package, err error) {
+	// support for gcParser error handling
+	defer func() {
+		if r := recover(); r != nil {
+			err = r.(importError) // will re-panic if r is not an importError
+		}
+	}()
+
+	var p gcParser
+	p.init(filename, id, data, imports)
+	pkg = p.parseExport()
+
+	return
+}
+
+// GcImport imports a gc-generated package given its import path, adds the
+// corresponding package object to the imports map, and returns the object.
+// Local import paths are interpreted relative to the current working directory.
+// The imports map must contains all packages already imported.
+// GcImport satisfies the ast.Importer signature.
+//
+func GcImport(imports map[string]*Package, path string) (pkg *Package, err error) {
+	if path == "unsafe" {
+		return Unsafe, nil
+	}
+
+	srcDir := "."
+	if build.IsLocalImport(path) {
+		srcDir, err = os.Getwd()
+		if err != nil {
+			return
+		}
+	}
+
+	filename, id := FindPkg(path, srcDir)
+	if filename == "" {
+		err = errors.New("can't find import: " + id)
+		return
+	}
+
+	// no need to re-import if the package was imported completely before
+	if pkg = imports[id]; pkg != nil && pkg.Complete {
+		return
+	}
+
+	// open file
+	f, err := os.Open(filename)
+	if err != nil {
+		return
+	}
+	defer func() {
+		f.Close()
+		if err != nil {
+			// add file name to error
+			err = fmt.Errorf("reading export data: %s: %v", filename, err)
+		}
+	}()
+
+	buf := bufio.NewReader(f)
+	if err = FindGcExportData(buf); err != nil {
+		return
+	}
+
+	pkg, err = GcImportData(imports, filename, id, buf)
+
+	return
+}
+
+// ----------------------------------------------------------------------------
+// gcParser
+
+// gcParser parses the exports inside a gc compiler-produced
+// object/archive file and populates its scope with the results.
+type gcParser struct {
+	scanner scanner.Scanner
+	tok     rune                // current token
+	lit     string              // literal string; only valid for Ident, Int, String tokens
+	id      string              // package id of imported package
+	imports map[string]*Package // package id -> package object
+}
+
+func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*Package) {
+	p.scanner.Init(src)
+	p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
+	p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+	p.scanner.Whitespace = 1<<'\t' | 1<<' '
+	p.scanner.Filename = filename // for good error messages
+	p.next()
+	p.id = id
+	p.imports = imports
+	// leave for debugging
+	if false {
+		// check consistency of imports map
+		for _, pkg := range imports {
+			if pkg.Name == "" {
+				fmt.Printf("no package name for %s\n", pkg.Path)
+			}
+		}
+	}
+}
+
+func (p *gcParser) next() {
+	p.tok = p.scanner.Scan()
+	switch p.tok {
+	case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·':
+		p.lit = p.scanner.TokenText()
+	default:
+		p.lit = ""
+	}
+	// leave for debugging
+	if false {
+		fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
+	}
+}
+
+func declConst(pkg *Package, name string) *Const {
+	// the constant may have been imported before - if it exists
+	// already in the respective scope, return that constant
+	scope := pkg.Scope
+	if obj := scope.Lookup(name); obj != nil {
+		return obj.(*Const)
+	}
+	// otherwise create a new constant and insert it into the scope
+	obj := &Const{Pkg: pkg, Name: name}
+	scope.Insert(obj)
+	return obj
+}
+
+func declTypeName(pkg *Package, name string) *TypeName {
+	scope := pkg.Scope
+	if obj := scope.Lookup(name); obj != nil {
+		return obj.(*TypeName)
+	}
+	obj := &TypeName{Pkg: pkg, Name: name}
+	// a named type may be referred to before the underlying type
+	// is known - set it up
+	obj.Type = &NamedType{Obj: obj}
+	scope.Insert(obj)
+	return obj
+}
+
+func declVar(pkg *Package, name string) *Var {
+	scope := pkg.Scope
+	if obj := scope.Lookup(name); obj != nil {
+		return obj.(*Var)
+	}
+	obj := &Var{Pkg: pkg, Name: name}
+	scope.Insert(obj)
+	return obj
+}
+
+func declFunc(pkg *Package, name string) *Func {
+	scope := pkg.Scope
+	if obj := scope.Lookup(name); obj != nil {
+		return obj.(*Func)
+	}
+	obj := &Func{Pkg: pkg, Name: name}
+	scope.Insert(obj)
+	return obj
+}
+
+// ----------------------------------------------------------------------------
+// Error handling
+
+// Internal errors are boxed as importErrors.
+type importError struct {
+	pos scanner.Position
+	err error
+}
+
+func (e importError) Error() string {
+	return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
+}
+
+func (p *gcParser) error(err interface{}) {
+	if s, ok := err.(string); ok {
+		err = errors.New(s)
+	}
+	// panic with a runtime.Error if err is not an error
+	panic(importError{p.scanner.Pos(), err.(error)})
+}
+
+func (p *gcParser) errorf(format string, args ...interface{}) {
+	p.error(fmt.Sprintf(format, args...))
+}
+
+func (p *gcParser) expect(tok rune) string {
+	lit := p.lit
+	if p.tok != tok {
+		p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
+	}
+	p.next()
+	return lit
+}
+
+func (p *gcParser) expectSpecial(tok string) {
+	sep := 'x' // not white space
+	i := 0
+	for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
+		sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+		p.next()
+		i++
+	}
+	if i < len(tok) {
+		p.errorf("expected %q, got %q", tok, tok[0:i])
+	}
+}
+
+func (p *gcParser) expectKeyword(keyword string) {
+	lit := p.expect(scanner.Ident)
+	if lit != keyword {
+		p.errorf("expected keyword %s, got %q", keyword, lit)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Qualified and unqualified names
+
+// PackageId = string_lit .
+//
+func (p *gcParser) parsePackageId() string {
+	id, err := strconv.Unquote(p.expect(scanner.String))
+	if err != nil {
+		p.error(err)
+	}
+	// id == "" stands for the imported package id
+	// (only known at time of package installation)
+	if id == "" {
+		id = p.id
+	}
+	return id
+}
+
+// PackageName = ident .
+//
+func (p *gcParser) parsePackageName() string {
+	return p.expect(scanner.Ident)
+}
+
+// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
+func (p *gcParser) parseDotIdent() string {
+	ident := ""
+	if p.tok != scanner.Int {
+		sep := 'x' // not white space
+		for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
+			ident += p.lit
+			sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+			p.next()
+		}
+	}
+	if ident == "" {
+		p.expect(scanner.Ident) // use expect() for error handling
+	}
+	return ident
+}
+
+// QualifiedName = "@" PackageId "." dotIdentifier .
+//
+func (p *gcParser) parseQualifiedName() (id, name string) {
+	p.expect('@')
+	id = p.parsePackageId()
+	p.expect('.')
+	name = p.parseDotIdent()
+	return
+}
+
+// getPkg returns the package for a given id. If the package is
+// not found but we have a package name, create the package and
+// add it to the p.imports map.
+//
+func (p *gcParser) getPkg(id, name string) *Package {
+	// package unsafe is not in the imports map - handle explicitly
+	if id == "unsafe" {
+		return Unsafe
+	}
+	pkg := p.imports[id]
+	if pkg == nil && name != "" {
+		pkg = &Package{Name: name, Path: id, Scope: new(Scope)}
+		p.imports[id] = pkg
+	}
+	return pkg
+}
+
+// parseExportedName is like parseQualifiedName, but
+// the package id is resolved to an imported *Package.
+//
+func (p *gcParser) parseExportedName() (pkg *Package, name string) {
+	id, name := p.parseQualifiedName()
+	pkg = p.getPkg(id, "")
+	if pkg == nil {
+		p.errorf("%s package not found", id)
+	}
+	return
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+// BasicType = identifier .
+//
+func (p *gcParser) parseBasicType() Type {
+	id := p.expect(scanner.Ident)
+	obj := Universe.Lookup(id)
+	if obj, ok := obj.(*TypeName); ok {
+		return obj.Type
+	}
+	p.errorf("not a basic type: %s", id)
+	return nil
+}
+
+// ArrayType = "[" int_lit "]" Type .
+//
+func (p *gcParser) parseArrayType() Type {
+	// "[" already consumed and lookahead known not to be "]"
+	lit := p.expect(scanner.Int)
+	p.expect(']')
+	elt := p.parseType()
+	n, err := strconv.ParseInt(lit, 10, 64)
+	if err != nil {
+		p.error(err)
+	}
+	return &Array{Len: n, Elt: elt}
+}
+
+// MapType = "map" "[" Type "]" Type .
+//
+func (p *gcParser) parseMapType() Type {
+	p.expectKeyword("map")
+	p.expect('[')
+	key := p.parseType()
+	p.expect(']')
+	elt := p.parseType()
+	return &Map{Key: key, Elt: elt}
+}
+
+// Name = identifier | "?" | QualifiedName .
+//
+// If materializePkg is set, a package is returned for fully qualified names.
+// That package may be a fake package (without name, scope, and not in the
+// p.imports map), created for the sole purpose of providing a package path
+// for QualifiedNames. Fake packages are created when the package id is not
+// found in the p.imports map; we cannot create a real package in that case
+// because we don't have a package name.
+//
+// TODO(gri): consider changing QualifiedIdents to (path, name) pairs to
+// simplify this code.
+//
+func (p *gcParser) parseName(materializePkg bool) (pkg *Package, name string) {
+	switch p.tok {
+	case scanner.Ident:
+		name = p.lit
+		p.next()
+	case '?':
+		// anonymous
+		p.next()
+	case '@':
+		// exported name prefixed with package path
+		var id string
+		id, name = p.parseQualifiedName()
+		if materializePkg {
+			// we don't have a package name - if the package
+			// doesn't exist yet, create a fake package instead
+			pkg = p.getPkg(id, "")
+			if pkg == nil {
+				pkg = &Package{Path: id}
+			}
+		}
+	default:
+		p.error("name expected")
+	}
+	return
+}
+
+// Field = Name Type [ string_lit ] .
+//
+func (p *gcParser) parseField() *Field {
+	var f Field
+	f.Pkg, f.Name = p.parseName(true)
+	f.Type = p.parseType()
+	if p.tok == scanner.String {
+		f.Tag = p.expect(scanner.String)
+	}
+	if f.Name == "" {
+		// anonymous field - typ must be T or *T and T must be a type name
+		if typ, ok := deref(f.Type).(*NamedType); ok && typ.Obj != nil {
+			f.Name = typ.Obj.GetName()
+			f.IsAnonymous = true
+		} else {
+			p.errorf("anonymous field expected")
+		}
+	}
+	return &f
+}
+
+// StructType = "struct" "{" [ FieldList ] "}" .
+// FieldList  = Field { ";" Field } .
+//
+func (p *gcParser) parseStructType() Type {
+	var fields []*Field
+
+	p.expectKeyword("struct")
+	p.expect('{')
+	for p.tok != '}' {
+		if len(fields) > 0 {
+			p.expect(';')
+		}
+		fields = append(fields, p.parseField())
+	}
+	p.expect('}')
+
+	return &Struct{Fields: fields}
+}
+
+// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
+//
+func (p *gcParser) parseParameter() (par *Var, isVariadic bool) {
+	_, name := p.parseName(false)
+	if name == "" {
+		name = "_" // cannot access unnamed identifiers
+	}
+	if p.tok == '.' {
+		p.expectSpecial("...")
+		isVariadic = true
+	}
+	typ := p.parseType()
+	// ignore argument tag (e.g. "noescape")
+	if p.tok == scanner.String {
+		p.next()
+	}
+	par = &Var{Name: name, Type: typ} // Pkg == nil
+	return
+}
+
+// Parameters    = "(" [ ParameterList ] ")" .
+// ParameterList = { Parameter "," } Parameter .
+//
+func (p *gcParser) parseParameters() (list []*Var, isVariadic bool) {
+	p.expect('(')
+	for p.tok != ')' {
+		if len(list) > 0 {
+			p.expect(',')
+		}
+		par, variadic := p.parseParameter()
+		list = append(list, par)
+		if variadic {
+			if isVariadic {
+				p.error("... not on final argument")
+			}
+			isVariadic = true
+		}
+	}
+	p.expect(')')
+
+	return
+}
+
+// Signature = Parameters [ Result ] .
+// Result    = Type | Parameters .
+//
+func (p *gcParser) parseSignature() *Signature {
+	params, isVariadic := p.parseParameters()
+
+	// optional result type
+	var results []*Var
+	if p.tok == '(' {
+		var variadic bool
+		results, variadic = p.parseParameters()
+		if variadic {
+			p.error("... not permitted on result type")
+		}
+	}
+
+	return &Signature{Params: params, Results: results, IsVariadic: isVariadic}
+}
+
+// InterfaceType = "interface" "{" [ MethodList ] "}" .
+// MethodList    = Method { ";" Method } .
+// Method        = Name Signature .
+//
+// The methods of embedded interfaces are always "inlined"
+// by the compiler and thus embedded interfaces are never
+// visible in the export data.
+//
+func (p *gcParser) parseInterfaceType() Type {
+	var methods []*Method
+
+	p.expectKeyword("interface")
+	p.expect('{')
+	for p.tok != '}' {
+		if len(methods) > 0 {
+			p.expect(';')
+		}
+		pkg, name := p.parseName(true)
+		typ := p.parseSignature()
+		methods = append(methods, &Method{QualifiedName{pkg, name}, typ})
+	}
+	p.expect('}')
+
+	return &Interface{Methods: methods}
+}
+
+// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
+//
+func (p *gcParser) parseChanType() Type {
+	dir := ast.SEND | ast.RECV
+	if p.tok == scanner.Ident {
+		p.expectKeyword("chan")
+		if p.tok == '<' {
+			p.expectSpecial("<-")
+			dir = ast.SEND
+		}
+	} else {
+		p.expectSpecial("<-")
+		p.expectKeyword("chan")
+		dir = ast.RECV
+	}
+	elt := p.parseType()
+	return &Chan{Dir: dir, Elt: elt}
+}
+
+// Type =
+//	BasicType | TypeName | ArrayType | SliceType | StructType |
+//      PointerType | FuncType | InterfaceType | MapType | ChanType |
+//      "(" Type ")" .
+//
+// BasicType   = ident .
+// TypeName    = ExportedName .
+// SliceType   = "[" "]" Type .
+// PointerType = "*" Type .
+// FuncType    = "func" Signature .
+//
+func (p *gcParser) parseType() Type {
+	switch p.tok {
+	case scanner.Ident:
+		switch p.lit {
+		default:
+			return p.parseBasicType()
+		case "struct":
+			return p.parseStructType()
+		case "func":
+			// FuncType
+			p.next()
+			return p.parseSignature()
+		case "interface":
+			return p.parseInterfaceType()
+		case "map":
+			return p.parseMapType()
+		case "chan":
+			return p.parseChanType()
+		}
+	case '@':
+		// TypeName
+		pkg, name := p.parseExportedName()
+		return declTypeName(pkg, name).Type
+	case '[':
+		p.next() // look ahead
+		if p.tok == ']' {
+			// SliceType
+			p.next()
+			return &Slice{Elt: p.parseType()}
+		}
+		return p.parseArrayType()
+	case '*':
+		// PointerType
+		p.next()
+		return &Pointer{Base: p.parseType()}
+	case '<':
+		return p.parseChanType()
+	case '(':
+		// "(" Type ")"
+		p.next()
+		typ := p.parseType()
+		p.expect(')')
+		return typ
+	}
+	p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+	return nil
+}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+// ImportDecl = "import" PackageName PackageId .
+//
+func (p *gcParser) parseImportDecl() {
+	p.expectKeyword("import")
+	name := p.parsePackageName()
+	p.getPkg(p.parsePackageId(), name)
+}
+
+// int_lit = [ "+" | "-" ] { "0" ... "9" } .
+//
+func (p *gcParser) parseInt() (neg bool, val string) {
+	switch p.tok {
+	case '-':
+		neg = true
+		fallthrough
+	case '+':
+		p.next()
+	}
+	val = p.expect(scanner.Int)
+	return
+}
+
+// number = int_lit [ "p" int_lit ] .
+//
+func (p *gcParser) parseNumber() (x operand) {
+	x.mode = constant
+
+	// mantissa
+	neg, val := p.parseInt()
+	mant, ok := new(big.Int).SetString(val, 0)
+	assert(ok)
+	if neg {
+		mant.Neg(mant)
+	}
+
+	if p.lit == "p" {
+		// exponent (base 2)
+		p.next()
+		neg, val = p.parseInt()
+		exp64, err := strconv.ParseUint(val, 10, 0)
+		if err != nil {
+			p.error(err)
+		}
+		exp := uint(exp64)
+		if neg {
+			denom := big.NewInt(1)
+			denom.Lsh(denom, exp)
+			x.typ = Typ[UntypedFloat]
+			x.val = normalizeRatConst(new(big.Rat).SetFrac(mant, denom))
+			return
+		}
+		if exp > 0 {
+			mant.Lsh(mant, exp)
+		}
+		x.typ = Typ[UntypedFloat]
+		x.val = normalizeIntConst(mant)
+		return
+	}
+
+	x.typ = Typ[UntypedInt]
+	x.val = normalizeIntConst(mant)
+	return
+}
+
+// ConstDecl   = "const" ExportedName [ Type ] "=" Literal .
+// Literal     = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit .
+// bool_lit    = "true" | "false" .
+// complex_lit = "(" float_lit "+" float_lit "i" ")" .
+// rune_lit    = "(" int_lit "+" int_lit ")" .
+// string_lit  = `"` { unicode_char } `"` .
+//
+func (p *gcParser) parseConstDecl() {
+	p.expectKeyword("const")
+	pkg, name := p.parseExportedName()
+	obj := declConst(pkg, name)
+	var x operand
+	if p.tok != '=' {
+		obj.Type = p.parseType()
+	}
+	p.expect('=')
+	switch p.tok {
+	case scanner.Ident:
+		// bool_lit
+		if p.lit != "true" && p.lit != "false" {
+			p.error("expected true or false")
+		}
+		x.typ = Typ[UntypedBool]
+		x.val = p.lit == "true"
+		p.next()
+
+	case '-', scanner.Int:
+		// int_lit
+		x = p.parseNumber()
+
+	case '(':
+		// complex_lit or rune_lit
+		p.next()
+		if p.tok == scanner.Char {
+			p.next()
+			p.expect('+')
+			x = p.parseNumber()
+			x.typ = Typ[UntypedRune]
+			p.expect(')')
+			break
+		}
+		re := p.parseNumber()
+		p.expect('+')
+		im := p.parseNumber()
+		p.expectKeyword("i")
+		p.expect(')')
+		x.typ = Typ[UntypedComplex]
+		// TODO(gri) fix this
+		_, _ = re, im
+		x.val = zeroConst
+
+	case scanner.Char:
+		// rune_lit
+		x.setConst(token.CHAR, p.lit)
+		p.next()
+
+	case scanner.String:
+		// string_lit
+		x.setConst(token.STRING, p.lit)
+		p.next()
+
+	default:
+		p.errorf("expected literal got %s", scanner.TokenString(p.tok))
+	}
+	if obj.Type == nil {
+		obj.Type = x.typ
+	}
+	assert(x.val != nil)
+	obj.Val = x.val
+}
+
+// TypeDecl = "type" ExportedName Type .
+//
+func (p *gcParser) parseTypeDecl() {
+	p.expectKeyword("type")
+	pkg, name := p.parseExportedName()
+	obj := declTypeName(pkg, name)
+
+	// The type object may have been imported before and thus already
+	// have a type associated with it. We still need to parse the type
+	// structure, but throw it away if the object already has a type.
+	// This ensures that all imports refer to the same type object for
+	// a given type declaration.
+	typ := p.parseType()
+
+	if name := obj.Type.(*NamedType); name.Underlying == nil {
+		name.Underlying = typ
+	}
+}
+
+// VarDecl = "var" ExportedName Type .
+//
+func (p *gcParser) parseVarDecl() {
+	p.expectKeyword("var")
+	pkg, name := p.parseExportedName()
+	obj := declVar(pkg, name)
+	obj.Type = p.parseType()
+}
+
+// Func = Signature [ Body ] .
+// Body = "{" ... "}" .
+//
+func (p *gcParser) parseFunc() *Signature {
+	sig := p.parseSignature()
+	if p.tok == '{' {
+		p.next()
+		for i := 1; i > 0; p.next() {
+			switch p.tok {
+			case '{':
+				i++
+			case '}':
+				i--
+			}
+		}
+	}
+	return sig
+}
+
+// MethodDecl = "func" Receiver Name Func .
+// Receiver   = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
+//
+func (p *gcParser) parseMethodDecl() {
+	// "func" already consumed
+	p.expect('(')
+	recv, _ := p.parseParameter() // receiver
+	p.expect(')')
+
+	// determine receiver base type object
+	typ := recv.Type
+	if ptr, ok := typ.(*Pointer); ok {
+		typ = ptr.Base
+	}
+	base := typ.(*NamedType)
+
+	// parse method name, signature, and possibly inlined body
+	pkg, name := p.parseName(true) // unexported method names in imports are qualified with their package.
+	sig := p.parseFunc()
+	sig.Recv = recv
+
+	// add method to type unless type was imported before
+	// and method exists already
+	// TODO(gri) investigate if this can be avoided
+	for _, m := range base.Methods {
+		if m.Name == name {
+			return // method was added before
+		}
+	}
+	base.Methods = append(base.Methods, &Method{QualifiedName{pkg, name}, sig})
+}
+
+// FuncDecl = "func" ExportedName Func .
+//
+func (p *gcParser) parseFuncDecl() {
+	// "func" already consumed
+	pkg, name := p.parseExportedName()
+	typ := p.parseFunc()
+	declFunc(pkg, name).Type = typ
+}
+
+// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
+//
+func (p *gcParser) parseDecl() {
+	switch p.lit {
+	case "import":
+		p.parseImportDecl()
+	case "const":
+		p.parseConstDecl()
+	case "type":
+		p.parseTypeDecl()
+	case "var":
+		p.parseVarDecl()
+	case "func":
+		p.next() // look ahead
+		if p.tok == '(' {
+			p.parseMethodDecl()
+		} else {
+			p.parseFuncDecl()
+		}
+	}
+	p.expect('\n')
+}
+
+// ----------------------------------------------------------------------------
+// Export
+
+// Export        = "PackageClause { Decl } "$$" .
+// PackageClause = "package" PackageName [ "safe" ] "\n" .
+//
+func (p *gcParser) parseExport() *Package {
+	p.expectKeyword("package")
+	name := p.parsePackageName()
+	if p.tok != '\n' {
+		// A package is safe if it was compiled with the -u flag,
+		// which disables the unsafe package.
+		// TODO(gri) remember "safe" package
+		p.expectKeyword("safe")
+	}
+	p.expect('\n')
+
+	pkg := p.getPkg(p.id, name)
+
+	for p.tok != '$' && p.tok != scanner.EOF {
+		p.parseDecl()
+	}
+
+	if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
+		// don't call next()/expect() since reading past the
+		// export data may cause scanner errors (e.g. NUL chars)
+		p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
+	}
+
+	if n := p.scanner.ErrorCount; n != 0 {
+		p.errorf("expected no scanner errors, got %d", n)
+	}
+
+	// package was imported completely and without errors
+	pkg.Complete = true
+
+	return pkg
+}
diff --git a/src/pkg/go/types/gcimporter_test.go b/src/pkg/go/types/gcimporter_test.go
new file mode 100644
index 0000000..b793eb4
--- /dev/null
+++ b/src/pkg/go/types/gcimporter_test.go
@@ -0,0 +1,180 @@
+// 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 types
+
+import (
+	"go/ast"
+	"go/build"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+var gcPath string // Go compiler path
+
+func init() {
+	// determine compiler
+	var gc string
+	switch runtime.GOARCH {
+	case "386":
+		gc = "8g"
+	case "amd64":
+		gc = "6g"
+	case "arm":
+		gc = "5g"
+	default:
+		gcPath = "unknown-GOARCH-compiler"
+		return
+	}
+	gcPath = filepath.Join(build.ToolDir, gc)
+}
+
+func compile(t *testing.T, dirname, filename string) string {
+	cmd := exec.Command(gcPath, filename)
+	cmd.Dir = dirname
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Logf("%s", out)
+		t.Fatalf("%s %s failed: %s", gcPath, filename, err)
+	}
+	archCh, _ := build.ArchChar(runtime.GOARCH)
+	// filename should end with ".go"
+	return filepath.Join(dirname, filename[:len(filename)-2]+archCh)
+}
+
+// Use the same global imports map for all tests. The effect is
+// as if all tested packages were imported into a single package.
+var imports = make(map[string]*Package)
+
+func testPath(t *testing.T, path string) bool {
+	t0 := time.Now()
+	_, err := GcImport(imports, path)
+	if err != nil {
+		t.Errorf("testPath(%s): %s", path, err)
+		return false
+	}
+	t.Logf("testPath(%s): %v", path, time.Since(t0))
+	return true
+}
+
+const maxTime = 30 * time.Second
+
+func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
+	dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
+	list, err := ioutil.ReadDir(dirname)
+	if err != nil {
+		t.Fatalf("testDir(%s): %s", dirname, err)
+	}
+	for _, f := range list {
+		if time.Now().After(endTime) {
+			t.Log("testing time used up")
+			return
+		}
+		switch {
+		case !f.IsDir():
+			// try extensions
+			for _, ext := range pkgExts {
+				if strings.HasSuffix(f.Name(), ext) {
+					name := f.Name()[0 : len(f.Name())-len(ext)] // remove extension
+					if testPath(t, filepath.Join(dir, name)) {
+						nimports++
+					}
+				}
+			}
+		case f.IsDir():
+			nimports += testDir(t, filepath.Join(dir, f.Name()), endTime)
+		}
+	}
+	return
+}
+
+func TestGcImport(t *testing.T) {
+	// On cross-compile builds, the path will not exist.
+	// Need to use GOHOSTOS, which is not available.
+	if _, err := os.Stat(gcPath); err != nil {
+		t.Skipf("skipping test: %v", err)
+	}
+
+	if outFn := compile(t, "testdata", "exports.go"); outFn != "" {
+		defer os.Remove(outFn)
+	}
+
+	nimports := 0
+	if testPath(t, "./testdata/exports") {
+		nimports++
+	}
+	nimports += testDir(t, "", time.Now().Add(maxTime)) // installed packages
+	t.Logf("tested %d imports", nimports)
+}
+
+var importedObjectTests = []struct {
+	name string
+	kind ast.ObjKind
+	typ  string
+}{
+	{"unsafe.Pointer", ast.Typ, "Pointer"},
+	{"math.Pi", ast.Con, "untyped float"},
+	{"io.Reader", ast.Typ, "interface{Read(p []byte) (n int, err error)}"},
+	{"io.ReadWriter", ast.Typ, "interface{Read(p []byte) (n int, err error); Write(p []byte) (n int, err error)}"},
+	{"math.Sin", ast.Fun, "func(x·2 float64) (_ float64)"},
+	// TODO(gri) add more tests
+}
+
+func TestGcImportedTypes(t *testing.T) {
+	// This package does not yet know how to read gccgo export data.
+	if runtime.Compiler == "gccgo" {
+		return
+	}
+	for _, test := range importedObjectTests {
+		s := strings.Split(test.name, ".")
+		if len(s) != 2 {
+			t.Fatal("inconsistent test data")
+		}
+		importPath := s[0]
+		objName := s[1]
+
+		pkg, err := GcImport(imports, importPath)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		obj := pkg.Scope.Lookup(objName)
+
+		// TODO(gri) should define an accessor on Object
+		var kind ast.ObjKind
+		var typ Type
+		switch obj := obj.(type) {
+		case *Const:
+			kind = ast.Con
+			typ = obj.Type
+		case *TypeName:
+			kind = ast.Typ
+			typ = obj.Type
+		case *Var:
+			kind = ast.Var
+			typ = obj.Type
+		case *Func:
+			kind = ast.Fun
+			typ = obj.Type
+		default:
+			unreachable()
+		}
+
+		if kind != test.kind {
+			t.Errorf("%s: got kind = %q; want %q", test.name, kind, test.kind)
+		}
+
+		str := typeString(underlying(typ))
+		if str != test.typ {
+			t.Errorf("%s: got type = %q; want %q", test.name, typ, test.typ)
+		}
+	}
+}
diff --git a/src/pkg/go/types/objects.go b/src/pkg/go/types/objects.go
new file mode 100644
index 0000000..02291d3
--- /dev/null
+++ b/src/pkg/go/types/objects.go
@@ -0,0 +1,186 @@
+// 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 types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// An Object describes a named language entity such as a package,
+// constant, type, variable, function (incl. methods), or label.
+// All objects implement the Object interface.
+//
+type Object interface {
+	GetPkg() *Package
+	GetName() string
+	GetType() Type
+	GetPos() token.Pos
+
+	anObject()
+}
+
+// A Package represents the contents (objects) of a Go package.
+type Package struct {
+	Name     string
+	Path     string              // import path, "" for current (non-imported) package
+	Scope    *Scope              // package-level scope
+	Imports  map[string]*Package // map of import paths to imported packages
+	Complete bool                // if set, this package was imported completely
+
+	spec *ast.ImportSpec
+}
+
+// A Const represents a declared constant.
+type Const struct {
+	Pkg  *Package
+	Name string
+	Type Type
+	Val  interface{}
+
+	spec *ast.ValueSpec
+}
+
+// A TypeName represents a declared type.
+type TypeName struct {
+	Pkg  *Package
+	Name string
+	Type Type // *NamedType or *Basic
+
+	spec *ast.TypeSpec
+}
+
+// A Variable represents a declared variable (including function parameters and results).
+type Var struct {
+	Pkg  *Package // nil for parameters
+	Name string
+	Type Type
+
+	visited bool // for initialization cycle detection
+	decl    interface{}
+}
+
+// A Func represents a declared function.
+type Func struct {
+	Pkg  *Package
+	Name string
+	Type Type // *Signature or *Builtin
+
+	decl *ast.FuncDecl
+}
+
+func (obj *Package) GetPkg() *Package  { return obj }
+func (obj *Const) GetPkg() *Package    { return obj.Pkg }
+func (obj *TypeName) GetPkg() *Package { return obj.Pkg }
+func (obj *Var) GetPkg() *Package      { return obj.Pkg }
+func (obj *Func) GetPkg() *Package     { return obj.Pkg }
+
+func (obj *Package) GetName() string  { return obj.Name }
+func (obj *Const) GetName() string    { return obj.Name }
+func (obj *TypeName) GetName() string { return obj.Name }
+func (obj *Var) GetName() string      { return obj.Name }
+func (obj *Func) GetName() string     { return obj.Name }
+
+func (obj *Package) GetType() Type  { return Typ[Invalid] }
+func (obj *Const) GetType() Type    { return obj.Type }
+func (obj *TypeName) GetType() Type { return obj.Type }
+func (obj *Var) GetType() Type      { return obj.Type }
+func (obj *Func) GetType() Type     { return obj.Type }
+
+func (obj *Package) GetPos() token.Pos {
+	if obj.spec != nil {
+		return obj.spec.Pos()
+	}
+	return token.NoPos
+}
+
+func (obj *Const) GetPos() token.Pos {
+	for _, n := range obj.spec.Names {
+		if n.Name == obj.Name {
+			return n.Pos()
+		}
+	}
+	return token.NoPos
+}
+func (obj *TypeName) GetPos() token.Pos {
+	if obj.spec != nil {
+		return obj.spec.Pos()
+	}
+	return token.NoPos
+}
+
+func (obj *Var) GetPos() token.Pos {
+	switch d := obj.decl.(type) {
+	case *ast.Field:
+		for _, n := range d.Names {
+			if n.Name == obj.Name {
+				return n.Pos()
+			}
+		}
+	case *ast.ValueSpec:
+		for _, n := range d.Names {
+			if n.Name == obj.Name {
+				return n.Pos()
+			}
+		}
+	case *ast.AssignStmt:
+		for _, x := range d.Lhs {
+			if ident, isIdent := x.(*ast.Ident); isIdent && ident.Name == obj.Name {
+				return ident.Pos()
+			}
+		}
+	}
+	return token.NoPos
+}
+func (obj *Func) GetPos() token.Pos {
+	if obj.decl != nil && obj.decl.Name != nil {
+		return obj.decl.Name.Pos()
+	}
+	return token.NoPos
+}
+
+func (*Package) anObject()  {}
+func (*Const) anObject()    {}
+func (*TypeName) anObject() {}
+func (*Var) anObject()      {}
+func (*Func) anObject()     {}
+
+// newObj returns a new Object for a given *ast.Object.
+// It does not canonicalize them (it always returns a new one).
+// For canonicalization, see check.lookup.
+//
+// TODO(gri) Once we do identifier resolution completely in
+//           in the typechecker, this functionality can go.
+//
+func newObj(pkg *Package, astObj *ast.Object) Object {
+	assert(pkg != nil)
+	name := astObj.Name
+	typ, _ := astObj.Type.(Type)
+	switch astObj.Kind {
+	case ast.Bad:
+		// ignore
+	case ast.Pkg:
+		unreachable()
+	case ast.Con:
+		return &Const{Pkg: pkg, Name: name, Type: typ, Val: astObj.Data, spec: astObj.Decl.(*ast.ValueSpec)}
+	case ast.Typ:
+		return &TypeName{Pkg: pkg, Name: name, Type: typ, spec: astObj.Decl.(*ast.TypeSpec)}
+	case ast.Var:
+		switch astObj.Decl.(type) {
+		case *ast.Field: // function parameters
+		case *ast.ValueSpec: // proper variable declarations
+		case *ast.AssignStmt: // short variable declarations
+		default:
+			unreachable() // everything else is not ok
+		}
+		return &Var{Pkg: pkg, Name: name, Type: typ, decl: astObj.Decl}
+	case ast.Fun:
+		return &Func{Pkg: pkg, Name: name, Type: typ, decl: astObj.Decl.(*ast.FuncDecl)}
+	case ast.Lbl:
+		unreachable() // for now
+	}
+	unreachable()
+	return nil
+}
diff --git a/src/pkg/go/types/operand.go b/src/pkg/go/types/operand.go
new file mode 100644
index 0000000..982ffef
--- /dev/null
+++ b/src/pkg/go/types/operand.go
@@ -0,0 +1,411 @@
+// 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.
+
+// This file defines operands and associated operations.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+)
+
+// An operandMode specifies the (addressing) mode of an operand.
+type operandMode int
+
+const (
+	invalid  operandMode = iota // operand is invalid (due to an earlier error) - ignore
+	novalue                     // operand represents no value (result of a function call w/o result)
+	typexpr                     // operand is a type
+	constant                    // operand is a constant; the operand's typ is a Basic type
+	variable                    // operand is an addressable variable
+	value                       // operand is a computed value
+	valueok                     // like mode == value, but operand may be used in a comma,ok expression
+)
+
+var operandModeString = [...]string{
+	invalid:  "invalid",
+	novalue:  "no value",
+	typexpr:  "type",
+	constant: "constant",
+	variable: "variable",
+	value:    "value",
+	valueok:  "value,ok",
+}
+
+// An operand represents an intermediate value during type checking.
+// Operands have an (addressing) mode, the expression evaluating to
+// the operand, the operand's type, and for constants a constant value.
+//
+type operand struct {
+	mode operandMode
+	expr ast.Expr
+	typ  Type
+	val  interface{}
+}
+
+// pos returns the position of the expression corresponding to x.
+// If x is invalid the position is token.NoPos.
+//
+func (x *operand) pos() token.Pos {
+	// x.expr may not be set if x is invalid
+	if x.expr == nil {
+		return token.NoPos
+	}
+	return x.expr.Pos()
+}
+
+func (x *operand) String() string {
+	if x.mode == invalid {
+		return "invalid operand"
+	}
+	var buf bytes.Buffer
+	if x.expr != nil {
+		buf.WriteString(exprString(x.expr))
+		buf.WriteString(" (")
+	}
+	buf.WriteString(operandModeString[x.mode])
+	if x.mode == constant {
+		format := " %v"
+		if isString(x.typ) {
+			format = " %q"
+		}
+		fmt.Fprintf(&buf, format, x.val)
+	}
+	if x.mode != novalue && (x.mode != constant || !isUntyped(x.typ)) {
+		fmt.Fprintf(&buf, " of type %s", typeString(x.typ))
+	}
+	if x.expr != nil {
+		buf.WriteByte(')')
+	}
+	return buf.String()
+}
+
+// setConst sets x to the untyped constant for literal lit.
+func (x *operand) setConst(tok token.Token, lit string) {
+	x.mode = invalid
+
+	var kind BasicKind
+	var val interface{}
+	switch tok {
+	case token.INT:
+		kind = UntypedInt
+		val = makeIntConst(lit)
+
+	case token.FLOAT:
+		kind = UntypedFloat
+		val = makeFloatConst(lit)
+
+	case token.IMAG:
+		kind = UntypedComplex
+		val = makeComplexConst(lit)
+
+	case token.CHAR:
+		kind = UntypedRune
+		val = makeRuneConst(lit)
+
+	case token.STRING:
+		kind = UntypedString
+		val = makeStringConst(lit)
+	}
+
+	if val != nil {
+		x.mode = constant
+		x.typ = Typ[kind]
+		x.val = val
+	}
+}
+
+// isNil reports whether x is the predeclared nil constant.
+func (x *operand) isNil() bool {
+	return x.mode == constant && x.val == nilConst
+}
+
+// TODO(gri) The functions operand.isAssignable, checker.convertUntyped,
+//           checker.isRepresentable, and checker.assignOperand are
+//           overlapping in functionality. Need to simplify and clean up.
+
+// isAssignable reports whether x is assignable to a variable of type T.
+func (x *operand) isAssignable(ctxt *Context, T Type) bool {
+	if x.mode == invalid || T == Typ[Invalid] {
+		return true // avoid spurious errors
+	}
+
+	V := x.typ
+
+	// x's type is identical to T
+	if IsIdentical(V, T) {
+		return true
+	}
+
+	Vu := underlying(V)
+	Tu := underlying(T)
+
+	// x's type V and T have identical underlying types
+	// and at least one of V or T is not a named type
+	if IsIdentical(Vu, Tu) {
+		return !isNamed(V) || !isNamed(T)
+	}
+
+	// T is an interface type and x implements T
+	if Ti, ok := Tu.(*Interface); ok {
+		if m, _ := missingMethod(x.typ, Ti); m == nil {
+			return true
+		}
+	}
+
+	// x is a bidirectional channel value, T is a channel
+	// type, x's type V and T have identical element types,
+	// and at least one of V or T is not a named type
+	if Vc, ok := Vu.(*Chan); ok && Vc.Dir == ast.SEND|ast.RECV {
+		if Tc, ok := Tu.(*Chan); ok && IsIdentical(Vc.Elt, Tc.Elt) {
+			return !isNamed(V) || !isNamed(T)
+		}
+	}
+
+	// x is the predeclared identifier nil and T is a pointer,
+	// function, slice, map, channel, or interface type
+	if x.isNil() {
+		switch t := Tu.(type) {
+		case *Basic:
+			if t.Kind == UnsafePointer {
+				return true
+			}
+		case *Pointer, *Signature, *Slice, *Map, *Chan, *Interface:
+			return true
+		}
+		return false
+	}
+
+	// x is an untyped constant representable by a value of type T
+	// TODO(gri) This is borrowing from checker.convertUntyped and
+	//           checker.isRepresentable. Need to clean up.
+	if isUntyped(Vu) {
+		switch t := Tu.(type) {
+		case *Basic:
+			if x.mode == constant {
+				return isRepresentableConst(x.val, ctxt, t.Kind)
+			}
+			// The result of a comparison is an untyped boolean,
+			// but may not be a constant.
+			if Vb, _ := Vu.(*Basic); Vb != nil {
+				return Vb.Kind == UntypedBool && isBoolean(Tu)
+			}
+		case *Interface:
+			return x.isNil() || len(t.Methods) == 0
+		case *Pointer, *Signature, *Slice, *Map, *Chan:
+			return x.isNil()
+		}
+	}
+
+	return false
+}
+
+// isInteger reports whether x is a (typed or untyped) integer value.
+func (x *operand) isInteger(ctxt *Context) bool {
+	return x.mode == invalid ||
+		isInteger(x.typ) ||
+		x.mode == constant && isRepresentableConst(x.val, ctxt, UntypedInt)
+}
+
+// lookupResult represents the result of a struct field/method lookup.
+type lookupResult struct {
+	mode  operandMode
+	typ   Type
+	index []int // field index sequence; nil for methods
+}
+
+type embeddedType struct {
+	typ       *NamedType
+	index     []int // field index sequence
+	multiples bool  // if set, typ is embedded multiple times at the same level
+}
+
+// lookupFieldBreadthFirst searches all types in list for a single entry (field
+// or method) of the given name from the given package. If such a field is found,
+// the result describes the field mode and type; otherwise the result mode is invalid.
+// (This function is similar in structure to FieldByNameFunc in reflect/type.go)
+//
+func lookupFieldBreadthFirst(list []embeddedType, name QualifiedName) (res lookupResult) {
+	// visited records the types that have been searched already.
+	visited := make(map[*NamedType]bool)
+
+	// embedded types of the next lower level
+	var next []embeddedType
+
+	// potentialMatch is invoked every time a match is found.
+	potentialMatch := func(multiples bool, mode operandMode, typ Type) bool {
+		if multiples || res.mode != invalid {
+			// name appeared already at this level - annihilate
+			res.mode = invalid
+			return false
+		}
+		// first appearance of name
+		res.mode = mode
+		res.typ = typ
+		res.index = nil
+		return true
+	}
+
+	// Search the current level if there is any work to do and collect
+	// embedded types of the next lower level in the next list.
+	for len(list) > 0 {
+		// The res.mode indicates whether we have found a match already
+		// on this level (mode != invalid), or not (mode == invalid).
+		assert(res.mode == invalid)
+
+		// start with empty next list (don't waste underlying array)
+		next = next[:0]
+
+		// look for name in all types at this level
+		for _, e := range list {
+			typ := e.typ
+			if visited[typ] {
+				continue
+			}
+			visited[typ] = true
+
+			// look for a matching attached method
+			for _, m := range typ.Methods {
+				if name.IsSame(m.QualifiedName) {
+					assert(m.Type != nil)
+					if !potentialMatch(e.multiples, value, m.Type) {
+						return // name collision
+					}
+				}
+			}
+
+			switch t := typ.Underlying.(type) {
+			case *Struct:
+				// look for a matching field and collect embedded types
+				for i, f := range t.Fields {
+					if name.IsSame(f.QualifiedName) {
+						assert(f.Type != nil)
+						if !potentialMatch(e.multiples, variable, f.Type) {
+							return // name collision
+						}
+						var index []int
+						index = append(index, e.index...) // copy e.index
+						index = append(index, i)
+						res.index = index
+						continue
+					}
+					// Collect embedded struct fields for searching the next
+					// lower level, but only if we have not seen a match yet
+					// (if we have a match it is either the desired field or
+					// we have a name collision on the same level; in either
+					// case we don't need to look further).
+					// Embedded fields are always of the form T or *T where
+					// T is a named type. If typ appeared multiple times at
+					// this level, f.Type appears multiple times at the next
+					// level.
+					if f.IsAnonymous && res.mode == invalid {
+						// Ignore embedded basic types - only user-defined
+						// named types can have methods or have struct fields.
+						if t, _ := deref(f.Type).(*NamedType); t != nil {
+							var index []int
+							index = append(index, e.index...) // copy e.index
+							index = append(index, i)
+							next = append(next, embeddedType{t, index, e.multiples})
+						}
+					}
+				}
+
+			case *Interface:
+				// look for a matching method
+				for _, m := range t.Methods {
+					if name.IsSame(m.QualifiedName) {
+						assert(m.Type != nil)
+						if !potentialMatch(e.multiples, value, m.Type) {
+							return // name collision
+						}
+					}
+				}
+			}
+		}
+
+		if res.mode != invalid {
+			// we found a single match on this level
+			return
+		}
+
+		// No match and no collision so far.
+		// Compute the list to search for the next level.
+		list = list[:0] // don't waste underlying array
+		for _, e := range next {
+			// Instead of adding the same type multiple times, look for
+			// it in the list and mark it as multiple if it was added
+			// before.
+			// We use a sequential search (instead of a map for next)
+			// because the lists tend to be small, can easily be reused,
+			// and explicit search appears to be faster in this case.
+			if alt := findType(list, e.typ); alt != nil {
+				alt.multiples = true
+			} else {
+				list = append(list, e)
+			}
+		}
+
+	}
+
+	return
+}
+
+func findType(list []embeddedType, typ *NamedType) *embeddedType {
+	for i := range list {
+		if p := &list[i]; p.typ == typ {
+			return p
+		}
+	}
+	return nil
+}
+
+func lookupField(typ Type, name QualifiedName) lookupResult {
+	typ = deref(typ)
+
+	if t, ok := typ.(*NamedType); ok {
+		for _, m := range t.Methods {
+			if name.IsSame(m.QualifiedName) {
+				assert(m.Type != nil)
+				return lookupResult{value, m.Type, nil}
+			}
+		}
+		typ = t.Underlying
+	}
+
+	switch t := typ.(type) {
+	case *Struct:
+		var next []embeddedType
+		for i, f := range t.Fields {
+			if name.IsSame(f.QualifiedName) {
+				return lookupResult{variable, f.Type, []int{i}}
+			}
+			if f.IsAnonymous {
+				// Possible optimization: If the embedded type
+				// is a pointer to the current type we could
+				// ignore it.
+				// Ignore embedded basic types - only user-defined
+				// named types can have methods or have struct fields.
+				if t, _ := deref(f.Type).(*NamedType); t != nil {
+					next = append(next, embeddedType{t, []int{i}, false})
+				}
+			}
+		}
+		if len(next) > 0 {
+			return lookupFieldBreadthFirst(next, name)
+		}
+
+	case *Interface:
+		for _, m := range t.Methods {
+			if name.IsSame(m.QualifiedName) {
+				return lookupResult{value, m.Type, nil}
+			}
+		}
+	}
+
+	// not found
+	return lookupResult{mode: invalid}
+}
diff --git a/src/pkg/go/types/predicates.go b/src/pkg/go/types/predicates.go
new file mode 100644
index 0000000..a99c91a
--- /dev/null
+++ b/src/pkg/go/types/predicates.go
@@ -0,0 +1,303 @@
+// 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.
+
+// This file implements commonly used type predicates.
+
+package types
+
+func isNamed(typ Type) bool {
+	if _, ok := typ.(*Basic); ok {
+		return ok
+	}
+	_, ok := typ.(*NamedType)
+	return ok
+}
+
+func isBoolean(typ Type) bool {
+	t, ok := underlying(typ).(*Basic)
+	return ok && t.Info&IsBoolean != 0
+}
+
+func isInteger(typ Type) bool {
+	t, ok := underlying(typ).(*Basic)
+	return ok && t.Info&IsInteger != 0
+}
+
+func isUnsigned(typ Type) bool {
+	t, ok := underlying(typ).(*Basic)
+	return ok && t.Info&IsUnsigned != 0
+}
+
+func isFloat(typ Type) bool {
+	t, ok := underlying(typ).(*Basic)
+	return ok && t.Info&IsFloat != 0
+}
+
+func isComplex(typ Type) bool {
+	t, ok := underlying(typ).(*Basic)
+	return ok && t.Info&IsComplex != 0
+}
+
+func isNumeric(typ Type) bool {
+	t, ok := underlying(typ).(*Basic)
+	return ok && t.Info&IsNumeric != 0
+}
+
+func isString(typ Type) bool {
+	t, ok := underlying(typ).(*Basic)
+	return ok && t.Info&IsString != 0
+}
+
+func isUntyped(typ Type) bool {
+	t, ok := underlying(typ).(*Basic)
+	return ok && t.Info&IsUntyped != 0
+}
+
+func isOrdered(typ Type) bool {
+	t, ok := underlying(typ).(*Basic)
+	return ok && t.Info&IsOrdered != 0
+}
+
+func isConstType(typ Type) bool {
+	t, ok := underlying(typ).(*Basic)
+	return ok && t.Info&IsConstType != 0
+}
+
+func isComparable(typ Type) bool {
+	switch t := underlying(typ).(type) {
+	case *Basic:
+		return t.Kind != Invalid && t.Kind != UntypedNil
+	case *Pointer, *Interface, *Chan:
+		// assumes types are equal for pointers and channels
+		return true
+	case *Struct:
+		for _, f := range t.Fields {
+			if !isComparable(f.Type) {
+				return false
+			}
+		}
+		return true
+	case *Array:
+		return isComparable(t.Elt)
+	}
+	return false
+}
+
+func hasNil(typ Type) bool {
+	switch underlying(typ).(type) {
+	case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
+		return true
+	}
+	return false
+}
+
+// IsIdentical returns true if x and y are identical.
+func IsIdentical(x, y Type) bool {
+	if x == y {
+		return true
+	}
+
+	switch x := x.(type) {
+	case *Basic:
+		// Basic types are singletons except for the rune and byte
+		// aliases, thus we cannot solely rely on the x == y check
+		// above.
+		if y, ok := y.(*Basic); ok {
+			return x.Kind == y.Kind
+		}
+
+	case *Array:
+		// Two array types are identical if they have identical element types
+		// and the same array length.
+		if y, ok := y.(*Array); ok {
+			return x.Len == y.Len && IsIdentical(x.Elt, y.Elt)
+		}
+
+	case *Slice:
+		// Two slice types are identical if they have identical element types.
+		if y, ok := y.(*Slice); ok {
+			return IsIdentical(x.Elt, y.Elt)
+		}
+
+	case *Struct:
+		// Two struct types are identical if they have the same sequence of fields,
+		// and if corresponding fields have the same names, and identical types,
+		// and identical tags. Two anonymous fields are considered to have the same
+		// name. Lower-case field names from different packages are always different.
+		if y, ok := y.(*Struct); ok {
+			if len(x.Fields) == len(y.Fields) {
+				for i, f := range x.Fields {
+					g := y.Fields[i]
+					if !f.QualifiedName.IsSame(g.QualifiedName) ||
+						!IsIdentical(f.Type, g.Type) ||
+						f.Tag != g.Tag ||
+						f.IsAnonymous != g.IsAnonymous {
+						return false
+					}
+				}
+				return true
+			}
+		}
+
+	case *Pointer:
+		// Two pointer types are identical if they have identical base types.
+		if y, ok := y.(*Pointer); ok {
+			return IsIdentical(x.Base, y.Base)
+		}
+
+	case *Signature:
+		// Two function types are identical if they have the same number of parameters
+		// and result values, corresponding parameter and result types are identical,
+		// and either both functions are variadic or neither is. Parameter and result
+		// names are not required to match.
+		if y, ok := y.(*Signature); ok {
+			return identicalTypes(x.Params, y.Params) &&
+				identicalTypes(x.Results, y.Results) &&
+				x.IsVariadic == y.IsVariadic
+		}
+
+	case *Interface:
+		// Two interface types are identical if they have the same set of methods with
+		// the same names and identical function types. Lower-case method names from
+		// different packages are always different. The order of the methods is irrelevant.
+		if y, ok := y.(*Interface); ok {
+			return identicalMethods(x.Methods, y.Methods) // methods are sorted
+		}
+
+	case *Map:
+		// Two map types are identical if they have identical key and value types.
+		if y, ok := y.(*Map); ok {
+			return IsIdentical(x.Key, y.Key) && IsIdentical(x.Elt, y.Elt)
+		}
+
+	case *Chan:
+		// Two channel types are identical if they have identical value types
+		// and the same direction.
+		if y, ok := y.(*Chan); ok {
+			return x.Dir == y.Dir && IsIdentical(x.Elt, y.Elt)
+		}
+
+	case *NamedType:
+		// Two named types are identical if their type names originate
+		// in the same type declaration.
+		if y, ok := y.(*NamedType); ok {
+			return x.Obj == y.Obj
+		}
+	}
+
+	return false
+}
+
+// identicalTypes returns true if both lists a and b have the
+// same length and corresponding objects have identical types.
+func identicalTypes(a, b []*Var) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i, x := range a {
+		y := b[i]
+		if !IsIdentical(x.Type, y.Type) {
+			return false
+		}
+	}
+	return true
+}
+
+// identicalMethods returns true if both lists a and b have the
+// same length and corresponding methods have identical types.
+// TODO(gri) make this more efficient
+func identicalMethods(a, b []*Method) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	m := make(map[QualifiedName]*Method)
+	for _, x := range a {
+		assert(m[x.QualifiedName] == nil) // method list must not have duplicate entries
+		m[x.QualifiedName] = x
+	}
+	for _, y := range b {
+		if x := m[y.QualifiedName]; x == nil || !IsIdentical(x.Type, y.Type) {
+			return false
+		}
+	}
+	return true
+}
+
+// underlying returns the underlying type of typ.
+func underlying(typ Type) Type {
+	// Basic types are representing themselves directly even though they are named.
+	if typ, ok := typ.(*NamedType); ok {
+		return typ.Underlying // underlying types are never NamedTypes
+	}
+	return typ
+}
+
+// deref returns a pointer's base type; otherwise it returns typ.
+func deref(typ Type) Type {
+	if typ, ok := underlying(typ).(*Pointer); ok {
+		return typ.Base
+	}
+	return typ
+}
+
+// defaultType returns the default "typed" type for an "untyped" type;
+// it returns the incoming type for all other types. If there is no
+// corresponding untyped type, the result is Typ[Invalid].
+//
+func defaultType(typ Type) Type {
+	if t, ok := typ.(*Basic); ok {
+		k := Invalid
+		switch t.Kind {
+		// case UntypedNil:
+		//      There is no default type for nil. For a good error message,
+		//      catch this case before calling this function.
+		case UntypedBool:
+			k = Bool
+		case UntypedInt:
+			k = Int
+		case UntypedRune:
+			k = Rune
+		case UntypedFloat:
+			k = Float64
+		case UntypedComplex:
+			k = Complex128
+		case UntypedString:
+			k = String
+		}
+		typ = Typ[k]
+	}
+	return typ
+}
+
+// missingMethod returns (nil, false) if typ implements T, otherwise
+// it returns the first missing method required by T and whether it
+// is missing or simply has the wrong type.
+//
+func missingMethod(typ Type, T *Interface) (method *Method, wrongType bool) {
+	// TODO(gri): this needs to correctly compare method names (taking package into account)
+	// TODO(gri): distinguish pointer and non-pointer receivers
+	// an interface type implements T if it has no methods with conflicting signatures
+	// Note: This is stronger than the current spec. Should the spec require this?
+	if ityp, _ := underlying(typ).(*Interface); ityp != nil {
+		for _, m := range T.Methods {
+			res := lookupField(ityp, m.QualifiedName) // TODO(gri) no need to go via lookupField
+			if res.mode != invalid && !IsIdentical(res.typ, m.Type) {
+				return m, true
+			}
+		}
+		return
+	}
+
+	// a concrete type implements T if it implements all methods of T.
+	for _, m := range T.Methods {
+		res := lookupField(typ, m.QualifiedName)
+		if res.mode == invalid {
+			return m, false
+		}
+		if !IsIdentical(res.typ, m.Type) {
+			return m, true
+		}
+	}
+	return
+}
diff --git a/src/pkg/go/types/resolve.go b/src/pkg/go/types/resolve.go
new file mode 100644
index 0000000..43db607
--- /dev/null
+++ b/src/pkg/go/types/resolve.go
@@ -0,0 +1,197 @@
+// 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 types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"strconv"
+)
+
+func (check *checker) declareObj(scope, altScope *Scope, obj Object, dotImport token.Pos) {
+	alt := scope.Insert(obj)
+	if alt == nil && altScope != nil {
+		// see if there is a conflicting declaration in altScope
+		alt = altScope.Lookup(obj.GetName())
+	}
+	if alt != nil {
+		prevDecl := ""
+
+		// for dot-imports, local declarations are declared first - swap messages
+		if dotImport.IsValid() {
+			if pos := alt.GetPos(); pos.IsValid() {
+				check.errorf(pos, fmt.Sprintf("%s redeclared in this block by dot-import at %s",
+					obj.GetName(), check.fset.Position(dotImport)))
+				return
+			}
+
+			// get by w/o other position
+			check.errorf(dotImport, fmt.Sprintf("dot-import redeclares %s", obj.GetName()))
+			return
+		}
+
+		if pos := alt.GetPos(); pos.IsValid() {
+			prevDecl = fmt.Sprintf("\n\tother declaration at %s", check.fset.Position(pos))
+		}
+		check.errorf(obj.GetPos(), fmt.Sprintf("%s redeclared in this block%s", obj.GetName(), prevDecl))
+	}
+}
+
+func (check *checker) resolveIdent(scope *Scope, ident *ast.Ident) bool {
+	for ; scope != nil; scope = scope.Outer {
+		if obj := scope.Lookup(ident.Name); obj != nil {
+			check.register(ident, obj)
+			return true
+		}
+	}
+	return false
+}
+
+func (check *checker) resolve(importer Importer) (methods []*ast.FuncDecl) {
+	pkg := &Package{Scope: &Scope{Outer: Universe}, Imports: make(map[string]*Package)}
+	check.pkg = pkg
+
+	// complete package scope
+	i := 0
+	for _, file := range check.files {
+		// package names must match
+		switch name := file.Name.Name; {
+		case pkg.Name == "":
+			pkg.Name = name
+		case name != pkg.Name:
+			check.errorf(file.Package, "package %s; expected %s", name, pkg.Name)
+			continue // ignore this file
+		}
+
+		// keep this file
+		check.files[i] = file
+		i++
+
+		// the package identifier denotes the current package
+		check.register(file.Name, pkg)
+
+		// insert top-level file objects in package scope
+		// (the parser took care of declaration errors)
+		for _, decl := range file.Decls {
+			switch d := decl.(type) {
+			case *ast.BadDecl:
+				// ignore
+			case *ast.GenDecl:
+				if d.Tok == token.CONST {
+					check.assocInitvals(d)
+				}
+				for _, spec := range d.Specs {
+					switch s := spec.(type) {
+					case *ast.ImportSpec:
+						// handled separately below
+					case *ast.ValueSpec:
+						for _, name := range s.Names {
+							if name.Name == "_" {
+								continue
+							}
+							pkg.Scope.Insert(check.lookup(name))
+						}
+					case *ast.TypeSpec:
+						if s.Name.Name == "_" {
+							continue
+						}
+						pkg.Scope.Insert(check.lookup(s.Name))
+					default:
+						check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
+					}
+				}
+			case *ast.FuncDecl:
+				if d.Recv != nil {
+					// collect method
+					methods = append(methods, d)
+					continue
+				}
+				if d.Name.Name == "_" || d.Name.Name == "init" {
+					continue // blank (_) and init functions are inaccessible
+				}
+				pkg.Scope.Insert(check.lookup(d.Name))
+			default:
+				check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
+			}
+		}
+	}
+	check.files = check.files[0:i]
+
+	// complete file scopes with imports and resolve identifiers
+	for _, file := range check.files {
+		// build file scope by processing all imports
+		importErrors := false
+		fileScope := &Scope{Outer: pkg.Scope}
+		for _, spec := range file.Imports {
+			if importer == nil {
+				importErrors = true
+				continue
+			}
+			path, _ := strconv.Unquote(spec.Path.Value)
+			imp, err := importer(pkg.Imports, path)
+			if err != nil {
+				check.errorf(spec.Path.Pos(), "could not import %s (%s)", path, err)
+				importErrors = true
+				continue
+			}
+			// TODO(gri) If a local package name != "." is provided,
+			// global identifier resolution could proceed even if the
+			// import failed. Consider adjusting the logic here a bit.
+
+			// local name overrides imported package name
+			name := imp.Name
+			if spec.Name != nil {
+				name = spec.Name.Name
+			}
+
+			// add import to file scope
+			if name == "." {
+				// merge imported scope with file scope
+				for _, obj := range imp.Scope.Entries {
+					// gcimported package scopes contain non-exported
+					// objects such as types used in partially exported
+					// objects - do not accept them
+					if ast.IsExported(obj.GetName()) {
+						check.declareObj(fileScope, pkg.Scope, obj, spec.Pos())
+					}
+				}
+				// TODO(gri) consider registering the "." identifier
+				// if we have Context.Ident callbacks for say blank
+				// (_) identifiers
+				// check.register(spec.Name, pkg)
+			} else if name != "_" {
+				// declare imported package object in file scope
+				// (do not re-use imp in the file scope but create
+				// a new object instead; the Decl field is different
+				// for different files)
+				obj := &Package{Name: name, Scope: imp.Scope, spec: spec}
+				check.declareObj(fileScope, pkg.Scope, obj, token.NoPos)
+			}
+		}
+
+		// resolve identifiers
+		if importErrors {
+			// don't use the universe scope without correct imports
+			// (objects in the universe may be shadowed by imports;
+			// with missing imports, identifiers might get resolved
+			// incorrectly to universe objects)
+			pkg.Scope.Outer = nil
+		}
+		i := 0
+		for _, ident := range file.Unresolved {
+			if !check.resolveIdent(fileScope, ident) {
+				check.errorf(ident.Pos(), "undeclared name: %s", ident.Name)
+				file.Unresolved[i] = ident
+				i++
+			}
+
+		}
+		file.Unresolved = file.Unresolved[0:i]
+		pkg.Scope.Outer = Universe // reset outer scope (is nil if there were importErrors)
+	}
+
+	return
+}
diff --git a/src/pkg/go/types/resolver_test.go b/src/pkg/go/types/resolver_test.go
new file mode 100644
index 0000000..d4e3644
--- /dev/null
+++ b/src/pkg/go/types/resolver_test.go
@@ -0,0 +1,167 @@
+// 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 types
+
+import (
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"testing"
+)
+
+var sources = []string{
+	`
+	package p
+	import "fmt"
+	import "math"
+	const pi = math.Pi
+	func sin(x float64) float64 {
+		return math.Sin(x)
+	}
+	var Println = fmt.Println
+	`,
+	`
+	package p
+	import "fmt"
+	func f() string {
+		_ = "foo"
+		return fmt.Sprintf("%d", g())
+	}
+	func g() (x int) { return }
+	`,
+	`
+	package p
+	import . "go/parser"
+	import "sync"
+	func g() Mode { return ImportsOnly }
+	var _, x int = 1, 2
+	func init() {}
+	type T struct{ sync.Mutex; a, b, c int}
+	type I interface{ m() }
+	var _ = T{a: 1, b: 2, c: 3}
+	func (_ T) m() {}
+	`,
+}
+
+var pkgnames = []string{
+	"fmt",
+	"math",
+}
+
+func TestResolveQualifiedIdents(t *testing.T) {
+	// parse package files
+	fset := token.NewFileSet()
+	var files []*ast.File
+	for _, src := range sources {
+		f, err := parser.ParseFile(fset, "", src, parser.DeclarationErrors)
+		if err != nil {
+			t.Fatal(err)
+		}
+		files = append(files, f)
+	}
+
+	// resolve and type-check package AST
+	idents := make(map[*ast.Ident]Object)
+	var ctxt Context
+	ctxt.Ident = func(id *ast.Ident, obj Object) { idents[id] = obj }
+	pkg, err := ctxt.Check(fset, files)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// check that all packages were imported
+	for _, name := range pkgnames {
+		if pkg.Imports[name] == nil {
+			t.Errorf("package %s not imported", name)
+		}
+	}
+
+	// check that there are no top-level unresolved identifiers
+	for _, f := range files {
+		for _, x := range f.Unresolved {
+			t.Errorf("%s: unresolved global identifier %s", fset.Position(x.Pos()), x.Name)
+		}
+	}
+
+	// check that qualified identifiers are resolved
+	for _, f := range files {
+		ast.Inspect(f, func(n ast.Node) bool {
+			if s, ok := n.(*ast.SelectorExpr); ok {
+				if x, ok := s.X.(*ast.Ident); ok {
+					obj := idents[x]
+					if obj == nil {
+						t.Errorf("%s: unresolved qualified identifier %s", fset.Position(x.Pos()), x.Name)
+						return false
+					}
+					if _, ok := obj.(*Package); ok && idents[s.Sel] == nil {
+						t.Errorf("%s: unresolved selector %s", fset.Position(s.Sel.Pos()), s.Sel.Name)
+						return false
+					}
+					return false
+				}
+				return false
+			}
+			return true
+		})
+	}
+
+	// Currently, the Check API doesn't call Ident for fields, methods, and composite literal keys.
+	// Introduce them artifically so that we can run the check below.
+	for _, f := range files {
+		ast.Inspect(f, func(n ast.Node) bool {
+			switch x := n.(type) {
+			case *ast.StructType:
+				for _, list := range x.Fields.List {
+					for _, f := range list.Names {
+						assert(idents[f] == nil)
+						idents[f] = &Var{Pkg: pkg, Name: f.Name}
+					}
+				}
+			case *ast.InterfaceType:
+				for _, list := range x.Methods.List {
+					for _, f := range list.Names {
+						assert(idents[f] == nil)
+						idents[f] = &Func{Pkg: pkg, Name: f.Name}
+					}
+				}
+			case *ast.CompositeLit:
+				for _, e := range x.Elts {
+					if kv, ok := e.(*ast.KeyValueExpr); ok {
+						if k, ok := kv.Key.(*ast.Ident); ok {
+							assert(idents[k] == nil)
+							idents[k] = &Var{Pkg: pkg, Name: k.Name}
+						}
+					}
+				}
+			}
+			return true
+		})
+	}
+
+	// check that each identifier in the source is enumerated by the Context.Ident callback
+	for _, f := range files {
+		ast.Inspect(f, func(n ast.Node) bool {
+			if x, ok := n.(*ast.Ident); ok && x.Name != "_" && x.Name != "." {
+				obj := idents[x]
+				if obj == nil {
+					t.Errorf("%s: unresolved identifier %s", fset.Position(x.Pos()), x.Name)
+				} else {
+					delete(idents, x)
+				}
+				return false
+			}
+			return true
+		})
+	}
+
+	// TODO(gri) enable code below
+	// At the moment, the type checker introduces artifical identifiers which are not
+	// present in the source. Once it doesn't do that anymore, enable the checks below.
+	/*
+		for x := range idents {
+			t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name)
+		}
+	*/
+}
diff --git a/src/pkg/go/types/scope.go b/src/pkg/go/types/scope.go
new file mode 100644
index 0000000..463ee40
--- /dev/null
+++ b/src/pkg/go/types/scope.go
@@ -0,0 +1,78 @@
+// 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 types
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// A Scope maintains the set of named language entities declared
+// in the scope and a link to the immediately surrounding (outer)
+// scope.
+//
+type Scope struct {
+	Outer   *Scope
+	Entries []Object          // scope entries in insertion order
+	large   map[string]Object // for fast lookup - only used for larger scopes
+}
+
+// Lookup returns the object with the given name if it is
+// found in scope s, otherwise it returns nil. Outer scopes
+// are ignored.
+//
+func (s *Scope) Lookup(name string) Object {
+	if s.large != nil {
+		return s.large[name]
+	}
+	for _, obj := range s.Entries {
+		if obj.GetName() == name {
+			return obj
+		}
+	}
+	return nil
+}
+
+// Insert attempts to insert an object obj into scope s.
+// If s already contains an object with the same name,
+// Insert leaves s unchanged and returns that object.
+// Otherwise it inserts obj and returns nil.
+//
+func (s *Scope) Insert(obj Object) Object {
+	name := obj.GetName()
+	if alt := s.Lookup(name); alt != nil {
+		return alt
+	}
+	s.Entries = append(s.Entries, obj)
+
+	// If the scope size reaches a threshold, use a map for faster lookups.
+	const threshold = 20
+	if len(s.Entries) > threshold {
+		if s.large == nil {
+			m := make(map[string]Object, len(s.Entries))
+			for _, obj := range s.Entries {
+				m[obj.GetName()] = obj
+			}
+			s.large = m
+		}
+		s.large[name] = obj
+	}
+
+	return nil
+}
+
+// Debugging support
+func (s *Scope) String() string {
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "scope %p {", s)
+	if s != nil && len(s.Entries) > 0 {
+		fmt.Fprintln(&buf)
+		for _, obj := range s.Entries {
+			fmt.Fprintf(&buf, "\t%s\t%T\n", obj.GetName(), obj)
+		}
+	}
+	fmt.Fprintf(&buf, "}\n")
+	return buf.String()
+}
diff --git a/src/pkg/go/types/sizes.go b/src/pkg/go/types/sizes.go
new file mode 100644
index 0000000..ef6499b
--- /dev/null
+++ b/src/pkg/go/types/sizes.go
@@ -0,0 +1,162 @@
+// 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 implements support for (unsafe) Alignof, Offsetof, and Sizeof.
+
+package types
+
+func (ctxt *Context) alignof(typ Type) int64 {
+	if f := ctxt.Alignof; f != nil {
+		if a := f(typ); a >= 1 {
+			return a
+		}
+		panic("Context.Alignof returned an alignment < 1")
+	}
+	return DefaultAlignof(typ)
+}
+
+func (ctxt *Context) offsetsof(s *Struct) []int64 {
+	offsets := s.offsets
+	if offsets == nil {
+		// compute offsets on demand
+		if f := ctxt.Offsetsof; f != nil {
+			offsets = f(s.Fields)
+			// sanity checks
+			if len(offsets) != len(s.Fields) {
+				panic("Context.Offsetsof returned the wrong number of offsets")
+			}
+			for _, o := range offsets {
+				if o < 0 {
+					panic("Context.Offsetsof returned an offset < 0")
+				}
+			}
+		} else {
+			offsets = DefaultOffsetsof(s.Fields)
+		}
+		s.offsets = offsets
+	}
+	return offsets
+}
+
+// offsetof returns the offset of the field specified via
+// the index sequence relative to typ. It returns a value
+// < 0 if the field is in an embedded pointer type.
+func (ctxt *Context) offsetof(typ Type, index []int) int64 {
+	var o int64
+	for _, i := range index {
+		s, _ := underlying(typ).(*Struct)
+		if s == nil {
+			return -1
+		}
+		o += ctxt.offsetsof(s)[i]
+		typ = s.Fields[i].Type
+	}
+	return o
+}
+
+func (ctxt *Context) sizeof(typ Type) int64 {
+	if f := ctxt.Sizeof; f != nil {
+		if s := f(typ); s >= 0 {
+			return s
+		}
+		panic("Context.Sizeof returned a size < 0")
+	}
+	return DefaultSizeof(typ)
+}
+
+// DefaultMaxAlign is the default maximum alignment, in bytes,
+// used by DefaultAlignof.
+const DefaultMaxAlign = 8
+
+// DefaultAlignof implements the default alignment computation
+// for unsafe.Alignof. It is used if Context.Alignof == nil.
+func DefaultAlignof(typ Type) int64 {
+	// For arrays and structs, alignment is defined in terms
+	// of alignment of the elements and fields, respectively.
+	switch t := underlying(typ).(type) {
+	case *Array:
+		// spec: "For a variable x of array type: unsafe.Alignof(x)
+		// is the same as unsafe.Alignof(x[0]), but at least 1."
+		return DefaultAlignof(t.Elt)
+	case *Struct:
+		// spec: "For a variable x of struct type: unsafe.Alignof(x)
+		// is the largest of the values unsafe.Alignof(x.f) for each
+		// field f of x, but at least 1."
+		max := int64(1)
+		for _, f := range t.Fields {
+			if a := DefaultAlignof(f.Type); a > max {
+				max = a
+			}
+		}
+		return max
+	}
+	a := DefaultSizeof(typ) // may be 0
+	// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
+	if a < 1 {
+		return 1
+	}
+	if a > DefaultMaxAlign {
+		return DefaultMaxAlign
+	}
+	return a
+}
+
+// align returns the smallest y >= x such that y % a == 0.
+func align(x, a int64) int64 {
+	y := x + a - 1
+	return y - y%a
+}
+
+// DefaultOffsetsof implements the default field offset computation
+// for unsafe.Offsetof. It is used if Context.Offsetsof == nil.
+func DefaultOffsetsof(fields []*Field) []int64 {
+	offsets := make([]int64, len(fields))
+	var o int64
+	for i, f := range fields {
+		a := DefaultAlignof(f.Type)
+		o = align(o, a)
+		offsets[i] = o
+		o += DefaultSizeof(f.Type)
+	}
+	return offsets
+}
+
+// DefaultPtrSize is the default size of ints, uint, and pointers, in bytes,
+// used by DefaultSizeof.
+const DefaultPtrSize = 8
+
+// DefaultSizeof implements the default size computation
+// for unsafe.Sizeof. It is used if Context.Sizeof == nil.
+func DefaultSizeof(typ Type) int64 {
+	switch t := underlying(typ).(type) {
+	case *Basic:
+		if s := t.size; s > 0 {
+			return s
+		}
+		if t.Kind == String {
+			return DefaultPtrSize * 2
+		}
+	case *Array:
+		a := DefaultAlignof(t.Elt)
+		s := DefaultSizeof(t.Elt)
+		return align(s, a) * t.Len // may be 0
+	case *Slice:
+		return DefaultPtrSize * 3
+	case *Struct:
+		n := len(t.Fields)
+		if n == 0 {
+			return 0
+		}
+		offsets := t.offsets
+		if t.offsets == nil {
+			// compute offsets on demand
+			offsets = DefaultOffsetsof(t.Fields)
+			t.offsets = offsets
+		}
+		return offsets[n-1] + DefaultSizeof(t.Fields[n-1].Type)
+	case *Signature:
+		return DefaultPtrSize * 2
+	}
+	return DefaultPtrSize // catch-all
+}
diff --git a/src/pkg/go/types/stmt.go b/src/pkg/go/types/stmt.go
new file mode 100644
index 0000000..53c46a1
--- /dev/null
+++ b/src/pkg/go/types/stmt.go
@@ -0,0 +1,743 @@
+// 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.
+
+// This file implements typechecking of statements.
+
+package types
+
+import (
+	"go/ast"
+	"go/token"
+)
+
+// assigment reports whether x can be assigned to a variable of type 'to',
+// if necessary by attempting to convert untyped values to the appropriate
+// type. If x.mode == invalid upon return, then assignment has already
+// issued an error message and the caller doesn't have to report another.
+// TODO(gri) This latter behavior is for historic reasons and complicates
+// callers. Needs to be cleaned up.
+func (check *checker) assignment(x *operand, to Type) bool {
+	if x.mode == invalid {
+		return false
+	}
+
+	if t, ok := x.typ.(*Result); ok {
+		// TODO(gri) elsewhere we use "assignment count mismatch" (consolidate)
+		check.errorf(x.pos(), "%d-valued expression %s used as single value", len(t.Values), x)
+		x.mode = invalid
+		return false
+	}
+
+	check.convertUntyped(x, to)
+
+	return x.mode != invalid && x.isAssignable(check.ctxt, to)
+}
+
+// assign1to1 typechecks a single assignment of the form lhs = rhs (if rhs != nil),
+// or lhs = x (if rhs == nil). If decl is set, the lhs operand must be an identifier.
+// If its type is not set, it is deduced from the type or value of x. If lhs has a
+// type it is used as a hint when evaluating rhs, if present.
+//
+func (check *checker) assign1to1(lhs, rhs ast.Expr, x *operand, decl bool, iota int) {
+	ident, _ := lhs.(*ast.Ident)
+	if x == nil {
+		assert(rhs != nil)
+		x = new(operand)
+	}
+
+	if ident != nil && ident.Name == "_" {
+		// anything can be assigned to a blank identifier - check rhs only, if present
+		if rhs != nil {
+			check.expr(x, rhs, nil, iota)
+		}
+		return
+	}
+
+	if !decl {
+		// regular assignment - start with lhs to obtain a type hint
+		// TODO(gri) clean this up - we don't need type hints anymore
+		var z operand
+		check.expr(&z, lhs, nil, -1)
+		if z.mode == invalid {
+			z.typ = nil // so we can proceed with rhs
+		}
+
+		if rhs != nil {
+			check.expr(x, rhs, z.typ, -1)
+			if x.mode == invalid {
+				return
+			}
+		}
+
+		if x.mode == invalid || z.mode == invalid {
+			return
+		}
+
+		if !check.assignment(x, z.typ) {
+			if x.mode != invalid {
+				check.errorf(x.pos(), "cannot assign %s to %s", x, &z)
+			}
+			return
+		}
+		if z.mode == constant {
+			check.errorf(x.pos(), "cannot assign %s to %s", x, &z)
+		}
+		return
+	}
+
+	// declaration - lhs must be an identifier
+	if ident == nil {
+		check.errorf(lhs.Pos(), "cannot declare %s", lhs)
+		return
+	}
+
+	// lhs may or may not be typed yet
+	obj := check.lookup(ident)
+	var typ Type
+	if t := obj.GetType(); t != nil {
+		typ = t
+	}
+
+	if rhs != nil {
+		check.expr(x, rhs, typ, iota)
+		// continue even if x.mode == invalid
+	}
+
+	if typ == nil {
+		// determine lhs type from rhs expression;
+		// for variables, convert untyped types to
+		// default types
+		typ = Typ[Invalid]
+		if x.mode != invalid {
+			typ = x.typ
+			if _, ok := obj.(*Var); ok && isUntyped(typ) {
+				if x.isNil() {
+					check.errorf(x.pos(), "use of untyped nil")
+					x.mode = invalid
+				} else {
+					typ = defaultType(typ)
+				}
+			}
+		}
+		switch obj := obj.(type) {
+		case *Const:
+			obj.Type = typ
+		case *Var:
+			obj.Type = typ
+		default:
+			unreachable()
+		}
+	}
+
+	if x.mode != invalid {
+		if !check.assignment(x, typ) {
+			if x.mode != invalid {
+				switch obj.(type) {
+				case *Const:
+					check.errorf(x.pos(), "cannot assign %s to variable of type %s", x, typ)
+				case *Var:
+					check.errorf(x.pos(), "cannot initialize constant of type %s with %s", typ, x)
+				default:
+					unreachable()
+				}
+				x.mode = invalid
+			}
+		}
+	}
+
+	// for constants, set their value
+	if obj, ok := obj.(*Const); ok {
+		assert(obj.Val == nil)
+		if x.mode != invalid {
+			if x.mode == constant {
+				if isConstType(x.typ) {
+					obj.Val = x.val
+				} else {
+					check.errorf(x.pos(), "%s has invalid constant type", x)
+				}
+			} else {
+				check.errorf(x.pos(), "%s is not constant", x)
+			}
+		}
+		if obj.Val == nil {
+			// set the constant to its type's zero value to reduce spurious errors
+			switch typ := underlying(obj.Type); {
+			case typ == Typ[Invalid]:
+				// ignore
+			case isBoolean(typ):
+				obj.Val = false
+			case isNumeric(typ):
+				obj.Val = int64(0)
+			case isString(typ):
+				obj.Val = ""
+			case hasNil(typ):
+				obj.Val = nilConst
+			default:
+				// in all other cases just prevent use of the constant
+				// TODO(gri) re-evaluate this code
+				obj.Val = nilConst
+			}
+		}
+	}
+}
+
+// assignNtoM typechecks a general assignment. If decl is set, the lhs operands
+// must be identifiers. If their types are not set, they are deduced from the
+// types of the corresponding rhs expressions. iota >= 0 indicates that the
+// "assignment" is part of a constant/variable declaration.
+// Precondition: len(lhs) > 0 .
+//
+func (check *checker) assignNtoM(lhs, rhs []ast.Expr, decl bool, iota int) {
+	assert(len(lhs) > 0)
+
+	if len(lhs) == len(rhs) {
+		for i, e := range rhs {
+			check.assign1to1(lhs[i], e, nil, decl, iota)
+		}
+		return
+	}
+
+	if len(rhs) == 1 {
+		// len(lhs) > 1, therefore a correct rhs expression
+		// cannot be a shift and we don't need a type hint;
+		// ok to evaluate rhs first
+		var x operand
+		check.expr(&x, rhs[0], nil, iota)
+		if x.mode == invalid {
+			// If decl is set, this leaves the lhs identifiers
+			// untyped. We catch this when looking up the respective
+			// object.
+			return
+		}
+
+		if t, ok := x.typ.(*Result); ok && len(lhs) == len(t.Values) {
+			// function result
+			x.mode = value
+			for i, obj := range t.Values {
+				x.expr = nil // TODO(gri) should do better here
+				x.typ = obj.Type
+				check.assign1to1(lhs[i], nil, &x, decl, iota)
+			}
+			return
+		}
+
+		if x.mode == valueok && len(lhs) == 2 {
+			// comma-ok expression
+			x.mode = value
+			check.assign1to1(lhs[0], nil, &x, decl, iota)
+
+			x.mode = value
+			x.typ = Typ[UntypedBool]
+			check.assign1to1(lhs[1], nil, &x, decl, iota)
+			return
+		}
+	}
+
+	check.errorf(lhs[0].Pos(), "assignment count mismatch: %d = %d", len(lhs), len(rhs))
+
+	// avoid checking the same declaration over and over
+	// again for each lhs identifier that has no type yet
+	if iota >= 0 {
+		// declaration
+		for _, e := range lhs {
+			if name, ok := e.(*ast.Ident); ok {
+				switch obj := check.lookup(name).(type) {
+				case *Const:
+					obj.Type = Typ[Invalid]
+				case *Var:
+					obj.Type = Typ[Invalid]
+				default:
+					unreachable()
+				}
+			}
+		}
+	}
+}
+
+func (check *checker) optionalStmt(s ast.Stmt) {
+	if s != nil {
+		check.stmt(s)
+	}
+}
+
+func (check *checker) stmtList(list []ast.Stmt) {
+	for _, s := range list {
+		check.stmt(s)
+	}
+}
+
+func (check *checker) call(call *ast.CallExpr) {
+	var x operand
+	check.rawExpr(&x, call, nil, -1, false) // don't check if value is used
+	// TODO(gri) If a builtin is called, the builtin must be valid in statement context.
+}
+
+func (check *checker) multipleDefaults(list []ast.Stmt) {
+	var first ast.Stmt
+	for _, s := range list {
+		var d ast.Stmt
+		switch c := s.(type) {
+		case *ast.CaseClause:
+			if len(c.List) == 0 {
+				d = s
+			}
+		case *ast.CommClause:
+			if c.Comm == nil {
+				d = s
+			}
+		default:
+			check.invalidAST(s.Pos(), "case/communication clause expected")
+		}
+		if d != nil {
+			if first != nil {
+				check.errorf(d.Pos(), "multiple defaults (first at %s)", first.Pos())
+			} else {
+				first = d
+			}
+		}
+	}
+}
+
+// stmt typechecks statement s.
+func (check *checker) stmt(s ast.Stmt) {
+	switch s := s.(type) {
+	case *ast.BadStmt, *ast.EmptyStmt:
+		// ignore
+
+	case *ast.DeclStmt:
+		d, _ := s.Decl.(*ast.GenDecl)
+		if d == nil || (d.Tok != token.CONST && d.Tok != token.TYPE && d.Tok != token.VAR) {
+			check.invalidAST(token.NoPos, "const, type, or var declaration expected")
+			return
+		}
+		if d.Tok == token.CONST {
+			check.assocInitvals(d)
+		}
+		check.decl(d)
+
+	case *ast.LabeledStmt:
+		// TODO(gri) anything to do with label itself?
+		check.stmt(s.Stmt)
+
+	case *ast.ExprStmt:
+		var x operand
+		used := false
+		switch e := unparen(s.X).(type) {
+		case *ast.CallExpr:
+			// function calls are permitted
+			used = true
+			// but some builtins are excluded
+			// (Caution: This evaluates e.Fun twice, once here and once
+			//           below as part of s.X. This has consequences for
+			//           check.register. Perhaps this can be avoided.)
+			check.expr(&x, e.Fun, nil, -1)
+			if x.mode != invalid {
+				if b, ok := x.typ.(*builtin); ok && !b.isStatement {
+					used = false
+				}
+			}
+		case *ast.UnaryExpr:
+			// receive operations are permitted
+			if e.Op == token.ARROW {
+				used = true
+			}
+		}
+		if !used {
+			check.errorf(s.Pos(), "%s not used", s.X)
+			// ok to continue
+		}
+		check.rawExpr(&x, s.X, nil, -1, false)
+		if x.mode == typexpr {
+			check.errorf(x.pos(), "%s is not an expression", &x)
+		}
+
+	case *ast.SendStmt:
+		var ch, x operand
+		check.expr(&ch, s.Chan, nil, -1)
+		check.expr(&x, s.Value, nil, -1)
+		if ch.mode == invalid || x.mode == invalid {
+			return
+		}
+		if tch, ok := underlying(ch.typ).(*Chan); !ok || tch.Dir&ast.SEND == 0 || !check.assignment(&x, tch.Elt) {
+			if x.mode != invalid {
+				check.invalidOp(ch.pos(), "cannot send %s to channel %s", &x, &ch)
+			}
+		}
+
+	case *ast.IncDecStmt:
+		var op token.Token
+		switch s.Tok {
+		case token.INC:
+			op = token.ADD
+		case token.DEC:
+			op = token.SUB
+		default:
+			check.invalidAST(s.TokPos, "unknown inc/dec operation %s", s.Tok)
+			return
+		}
+		var x operand
+		Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position
+		check.binary(&x, s.X, Y, op, -1)
+		if x.mode == invalid {
+			return
+		}
+		check.assign1to1(s.X, nil, &x, false, -1)
+
+	case *ast.AssignStmt:
+		switch s.Tok {
+		case token.ASSIGN, token.DEFINE:
+			if len(s.Lhs) == 0 {
+				check.invalidAST(s.Pos(), "missing lhs in assignment")
+				return
+			}
+			check.assignNtoM(s.Lhs, s.Rhs, s.Tok == token.DEFINE, -1)
+		default:
+			// assignment operations
+			if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
+				check.errorf(s.TokPos, "assignment operation %s requires single-valued expressions", s.Tok)
+				return
+			}
+			// TODO(gri) make this conversion more efficient
+			var op token.Token
+			switch s.Tok {
+			case token.ADD_ASSIGN:
+				op = token.ADD
+			case token.SUB_ASSIGN:
+				op = token.SUB
+			case token.MUL_ASSIGN:
+				op = token.MUL
+			case token.QUO_ASSIGN:
+				op = token.QUO
+			case token.REM_ASSIGN:
+				op = token.REM
+			case token.AND_ASSIGN:
+				op = token.AND
+			case token.OR_ASSIGN:
+				op = token.OR
+			case token.XOR_ASSIGN:
+				op = token.XOR
+			case token.SHL_ASSIGN:
+				op = token.SHL
+			case token.SHR_ASSIGN:
+				op = token.SHR
+			case token.AND_NOT_ASSIGN:
+				op = token.AND_NOT
+			default:
+				check.invalidAST(s.TokPos, "unknown assignment operation %s", s.Tok)
+				return
+			}
+			var x operand
+			check.binary(&x, s.Lhs[0], s.Rhs[0], op, -1)
+			if x.mode == invalid {
+				return
+			}
+			check.assign1to1(s.Lhs[0], nil, &x, false, -1)
+		}
+
+	case *ast.GoStmt:
+		check.call(s.Call)
+
+	case *ast.DeferStmt:
+		check.call(s.Call)
+
+	case *ast.ReturnStmt:
+		sig := check.funcsig
+		if n := len(sig.Results); n > 0 {
+			// TODO(gri) should not have to compute lhs, named every single time - clean this up
+			lhs := make([]ast.Expr, n)
+			named := false // if set, function has named results
+			for i, res := range sig.Results {
+				if len(res.Name) > 0 {
+					// a blank (_) result parameter is a named result
+					named = true
+				}
+				name := ast.NewIdent(res.Name)
+				name.NamePos = s.Pos()
+				check.register(name, &Var{Name: res.Name, Type: res.Type}) // Pkg == nil
+				lhs[i] = name
+			}
+			if len(s.Results) > 0 || !named {
+				// TODO(gri) assignNtoM should perhaps not require len(lhs) > 0
+				check.assignNtoM(lhs, s.Results, false, -1)
+			}
+		} else if len(s.Results) > 0 {
+			check.errorf(s.Pos(), "no result values expected")
+		}
+
+	case *ast.BranchStmt:
+		// TODO(gri) implement this
+
+	case *ast.BlockStmt:
+		check.stmtList(s.List)
+
+	case *ast.IfStmt:
+		check.optionalStmt(s.Init)
+		var x operand
+		check.expr(&x, s.Cond, nil, -1)
+		if x.mode != invalid && !isBoolean(x.typ) {
+			check.errorf(s.Cond.Pos(), "non-boolean condition in if statement")
+		}
+		check.stmt(s.Body)
+		check.optionalStmt(s.Else)
+
+	case *ast.SwitchStmt:
+		check.optionalStmt(s.Init)
+		var x operand
+		tag := s.Tag
+		if tag == nil {
+			// use fake true tag value and position it at the opening { of the switch
+			ident := &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"}
+			check.register(ident, Universe.Lookup("true"))
+			tag = ident
+		}
+		check.expr(&x, tag, nil, -1)
+
+		check.multipleDefaults(s.Body.List)
+		seen := make(map[interface{}]token.Pos)
+		for _, s := range s.Body.List {
+			clause, _ := s.(*ast.CaseClause)
+			if clause == nil {
+				continue // error reported before
+			}
+			if x.mode != invalid {
+				for _, expr := range clause.List {
+					x := x // copy of x (don't modify original)
+					var y operand
+					check.expr(&y, expr, nil, -1)
+					if y.mode == invalid {
+						continue // error reported before
+					}
+					// If we have a constant case value, it must appear only
+					// once in the switch statement. Determine if there is a
+					// duplicate entry, but only report an error if there are
+					// no other errors.
+					var dupl token.Pos
+					var yy operand
+					if y.mode == constant {
+						// TODO(gri) This code doesn't work correctly for
+						//           large integer, floating point, or
+						//           complex values - the respective struct
+						//           comparisons are shallow. Need to use a
+						//           hash function to index the map.
+						dupl = seen[y.val]
+						seen[y.val] = y.pos()
+						yy = y // remember y
+					}
+					// TODO(gri) The convertUntyped call pair below appears in other places. Factor!
+					// Order matters: By comparing y against x, error positions are at the case values.
+					check.convertUntyped(&y, x.typ)
+					if y.mode == invalid {
+						continue // error reported before
+					}
+					check.convertUntyped(&x, y.typ)
+					if x.mode == invalid {
+						continue // error reported before
+					}
+					check.comparison(&y, &x, token.EQL)
+					if y.mode != invalid && dupl.IsValid() {
+						check.errorf(yy.pos(), "%s is duplicate case (previous at %s)",
+							&yy, check.fset.Position(dupl))
+					}
+				}
+			}
+			check.stmtList(clause.Body)
+		}
+
+	case *ast.TypeSwitchStmt:
+		check.optionalStmt(s.Init)
+
+		// A type switch guard must be of the form:
+		//
+		//     TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
+		//
+		// The parser is checking syntactic correctness;
+		// remaining syntactic errors are considered AST errors here.
+		// TODO(gri) better factoring of error handling (invalid ASTs)
+		//
+		var lhs *Var // lhs variable or nil
+		var rhs ast.Expr
+		switch guard := s.Assign.(type) {
+		case *ast.ExprStmt:
+			rhs = guard.X
+		case *ast.AssignStmt:
+			if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
+				check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+				return
+			}
+			ident, _ := guard.Lhs[0].(*ast.Ident)
+			if ident == nil {
+				check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+				return
+			}
+			lhs = check.lookup(ident).(*Var)
+			rhs = guard.Rhs[0]
+		default:
+			check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+			return
+		}
+
+		// rhs must be of the form: expr.(type) and expr must be an interface
+		expr, _ := rhs.(*ast.TypeAssertExpr)
+		if expr == nil || expr.Type != nil {
+			check.invalidAST(s.Pos(), "incorrect form of type switch guard")
+			return
+		}
+		var x operand
+		check.expr(&x, expr.X, nil, -1)
+		if x.mode == invalid {
+			return
+		}
+		var T *Interface
+		if T, _ = underlying(x.typ).(*Interface); T == nil {
+			check.errorf(x.pos(), "%s is not an interface", &x)
+			return
+		}
+
+		check.multipleDefaults(s.Body.List)
+		for _, s := range s.Body.List {
+			clause, _ := s.(*ast.CaseClause)
+			if clause == nil {
+				continue // error reported before
+			}
+			// Check each type in this type switch case.
+			var typ Type
+			for _, expr := range clause.List {
+				typ = check.typOrNil(expr, false)
+				if typ != nil && typ != Typ[Invalid] {
+					if method, wrongType := missingMethod(typ, T); method != nil {
+						var msg string
+						if wrongType {
+							msg = "%s cannot have dynamic type %s (wrong type for method %s)"
+						} else {
+							msg = "%s cannot have dynamic type %s (missing method %s)"
+						}
+						check.errorf(expr.Pos(), msg, &x, typ, method.Name)
+						// ok to continue
+					}
+				}
+			}
+			// If lhs exists, set its type for each clause.
+			if lhs != nil {
+				// In clauses with a case listing exactly one type, the variable has that type;
+				// otherwise, the variable has the type of the expression in the TypeSwitchGuard.
+				if len(clause.List) != 1 || typ == nil {
+					typ = x.typ
+				}
+				lhs.Type = typ
+			}
+			check.stmtList(clause.Body)
+		}
+
+		// There is only one object (lhs) associated with a lhs identifier, but that object
+		// assumes different types for different clauses. Set it back to the type of the
+		// TypeSwitchGuard expression so that that variable always has a valid type.
+		if lhs != nil {
+			lhs.Type = x.typ
+		}
+
+	case *ast.SelectStmt:
+		check.multipleDefaults(s.Body.List)
+		for _, s := range s.Body.List {
+			clause, _ := s.(*ast.CommClause)
+			if clause == nil {
+				continue // error reported before
+			}
+			check.optionalStmt(clause.Comm) // TODO(gri) check correctness of c.Comm (must be Send/RecvStmt)
+			check.stmtList(clause.Body)
+		}
+
+	case *ast.ForStmt:
+		check.optionalStmt(s.Init)
+		if s.Cond != nil {
+			var x operand
+			check.expr(&x, s.Cond, nil, -1)
+			if x.mode != invalid && !isBoolean(x.typ) {
+				check.errorf(s.Cond.Pos(), "non-boolean condition in for statement")
+			}
+		}
+		check.optionalStmt(s.Post)
+		check.stmt(s.Body)
+
+	case *ast.RangeStmt:
+		// check expression to iterate over
+		decl := s.Tok == token.DEFINE
+		var x operand
+		check.expr(&x, s.X, nil, -1)
+		if x.mode == invalid {
+			// if we don't have a declaration, we can still check the loop's body
+			if !decl {
+				check.stmt(s.Body)
+			}
+			return
+		}
+
+		// determine key/value types
+		var key, val Type
+		switch typ := underlying(x.typ).(type) {
+		case *Basic:
+			if isString(typ) {
+				key = Typ[UntypedInt]
+				val = Typ[UntypedRune]
+			}
+		case *Array:
+			key = Typ[UntypedInt]
+			val = typ.Elt
+		case *Slice:
+			key = Typ[UntypedInt]
+			val = typ.Elt
+		case *Pointer:
+			if typ, _ := underlying(typ.Base).(*Array); typ != nil {
+				key = Typ[UntypedInt]
+				val = typ.Elt
+			}
+		case *Map:
+			key = typ.Key
+			val = typ.Elt
+		case *Chan:
+			key = typ.Elt
+			if typ.Dir&ast.RECV == 0 {
+				check.errorf(x.pos(), "cannot range over send-only channel %s", &x)
+				// ok to continue
+			}
+			if s.Value != nil {
+				check.errorf(s.Value.Pos(), "iteration over %s permits only one iteration variable", &x)
+				// ok to continue
+			}
+		}
+
+		if key == nil {
+			check.errorf(x.pos(), "cannot range over %s", &x)
+			// if we don't have a declaration, we can still check the loop's body
+			if !decl {
+				check.stmt(s.Body)
+			}
+			return
+		}
+
+		// check assignment to/declaration of iteration variables
+		// TODO(gri) The error messages/positions are not great here,
+		//           they refer to the expression in the range clause.
+		//           Should give better messages w/o too much code
+		//           duplication (assignment checking).
+		x.mode = value
+		if s.Key != nil {
+			x.typ = key
+			x.expr = s.Key
+			check.assign1to1(s.Key, nil, &x, decl, -1)
+		} else {
+			check.invalidAST(s.Pos(), "range clause requires index iteration variable")
+			// ok to continue
+		}
+		if s.Value != nil {
+			x.typ = val
+			x.expr = s.Value
+			check.assign1to1(s.Value, nil, &x, decl, -1)
+		}
+
+		check.stmt(s.Body)
+
+	default:
+		check.errorf(s.Pos(), "invalid statement")
+	}
+}
diff --git a/src/pkg/go/types/testdata/builtins.src b/src/pkg/go/types/testdata/builtins.src
new file mode 100644
index 0000000..c08c442
--- /dev/null
+++ b/src/pkg/go/types/testdata/builtins.src
@@ -0,0 +1,401 @@
+// 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.
+
+// builtin calls
+
+package builtins
+
+import "unsafe"
+
+func _append() {
+	var x int
+	var s []byte
+	_0 := append /* ERROR "argument" */ ()
+	_1 := append("foo" /* ERROR "not a typed slice" */)
+	_2 := append(nil /* ERROR "not a typed slice" */, s)
+	_3 := append(x /* ERROR "not a typed slice" */, s)
+	_4 := append(s)
+	append /* ERROR "not used" */ (s)
+}
+
+func _cap() {
+	var a [10]bool
+	var p *[20]int
+	var s []int
+	var c chan string
+	_0 := cap /* ERROR "argument" */ ()
+	_1 := cap /* ERROR "argument" */ (1, 2)
+	_2 := cap(42 /* ERROR "invalid" */)
+	const _3 = cap(a)
+	assert(_3 == 10)
+	const _4 = cap(p)
+	assert(_4 == 20)
+	_5 := cap(c)
+	cap /* ERROR "not used" */ (c)
+
+	// issue 4744
+	type T struct{ a [10]int }
+	const _ = cap(((*T)(nil)).a)
+}
+
+func _close() {
+	var c chan int
+	var r <-chan int
+	close /* ERROR "argument" */ ()
+	close /* ERROR "argument" */ (1, 2)
+	close(42 /* ERROR "not a channel" */)
+	close(r /* ERROR "receive-only channel" */)
+	close(c)
+}
+
+func _complex() {
+	var i32 int32
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	_ = complex /* ERROR "argument" */ ()
+	_ = complex /* ERROR "argument" */ (1)
+	_ = complex(true /* ERROR "invalid argument" */ , 0)
+	_ = complex(i32 /* ERROR "invalid argument" */ , 0)
+	_ = complex("foo" /* ERROR "invalid argument" */ , 0)
+	_ = complex(c64 /* ERROR "invalid argument" */ , 0)
+	_ = complex(0, true /* ERROR "invalid argument" */ )
+	_ = complex(0, i32 /* ERROR "invalid argument" */ )
+	_ = complex(0, "foo" /* ERROR "invalid argument" */ )
+	_ = complex(0, c64 /* ERROR "invalid argument" */ )
+	_ = complex(f32, f32)
+	_ = complex(f32, 1)
+	_ = complex(f32, 1.0)
+	_ = complex(f32, 'a')
+	_ = complex(f64, f64)
+	_ = complex(f64, 1)
+	_ = complex(f64, 1.0)
+	_ = complex(f64, 'a')
+	_ = complex(f32 /* ERROR "mismatched types" */, f64)
+	_ = complex(f64 /* ERROR "mismatched types" */, f32)
+	_ = complex(1, 1)
+	_ = complex(1, 1.1)
+	_ = complex(1, 'a')
+	complex /* ERROR "not used" */ (1, 2)
+}
+
+func _copy() {
+	copy /* ERROR "not enough arguments" */ ()
+	copy /* ERROR "not enough arguments" */ ("foo")
+	copy([ /* ERROR "copy expects slice arguments" */ ...]int{}, []int{})
+	copy([ /* ERROR "copy expects slice arguments" */ ]int{}, [...]int{})
+	copy([ /* ERROR "different element types" */ ]int8{}, "foo")
+
+	// spec examples
+	var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
+	var s = make([]int, 6)
+	var b = make([]byte, 5)
+	n1 := copy(s, a[0:])            // n1 == 6, s == []int{0, 1, 2, 3, 4, 5}
+	n2 := copy(s, s[2:])            // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
+	n3 := copy(b, "Hello, World!")  // n3 == 5, b == []byte("Hello")
+}
+
+func _delete() {
+	var m map[string]int
+	var s string
+	delete /* ERROR "argument" */ ()
+	delete /* ERROR "argument" */ (1)
+	delete /* ERROR "argument" */ (1, 2, 3)
+	delete(m, 0 /* ERROR "not assignable" */)
+	delete(m, s)
+}
+
+func _imag() {
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	var c128 complex128
+	_ = imag /* ERROR "argument" */ ()
+	_ = imag /* ERROR "argument" */ (1, 2)
+	_ = imag(10 /* ERROR "must be a complex number" */)
+	_ = imag(2.7182818 /* ERROR "must be a complex number" */)
+	_ = imag("foo" /* ERROR "must be a complex number" */)
+	const _5 = imag(1 + 2i)
+	assert(_5 == 2)
+	f32 = _5
+	f64 = _5
+	const _6 = imag(0i)
+	assert(_6 == 0)
+	f32 = imag(c64)
+	f64 = imag(c128)
+	f32 = imag /* ERROR "cannot assign" */ (c128)
+	f64 = imag /* ERROR "cannot assign" */ (c64)
+	imag /* ERROR "not used" */ (c64)
+}
+
+func _len() {
+	const c = "foobar"
+	var a [10]bool
+	var p *[20]int
+	var s []int
+	var m map[string]complex128
+	_ = len /* ERROR "argument" */ ()
+	_ = len /* ERROR "argument" */ (1, 2)
+	_ = len(42 /* ERROR "invalid" */)
+	const _3 = len(c)
+	assert(_3 == 6)
+	const _4 = len(a)
+	assert(_4 == 10)
+	const _5 = len(p)
+	assert(_5 == 20)
+	_ = len(m)
+	len /* ERROR "not used" */ (c)
+
+	// esoteric case
+	var t string
+	var hash map[interface{}][]*[10]int
+	const n = len /* ERROR "not constant" */ (hash[recover()][len(t)])
+	assert /* ERROR "failed" */ (n == 10)
+	var ch <-chan int
+	const nn = len /* ERROR "not constant" */ (hash[<-ch][len(t)])
+	_ = nn // TODO(gri) remove this once unused constants get type-checked
+
+	// issue 4744
+	type T struct{ a [10]int }
+	const _ = len(((*T)(nil)).a)
+}
+
+func _make() {
+	n := 0
+
+	_ = make /* ERROR "argument" */ ()
+	_ = make(1 /* ERROR "not a type" */)
+	_ = make(int /* ERROR "cannot make" */)
+
+	// slices
+	_ = make/* ERROR "arguments" */ ([]int)
+	_ = make/* ERROR "arguments" */ ([]int, 2, 3, 4)
+	_ = make([]int, int /* ERROR "not an expression" */)
+	_ = make([]int, 10, float32 /* ERROR "not an expression" */)
+	_ = make([]int, "foo" /* ERROR "must be an integer" */)
+	_ = make([]int, 10, 2.3 /* ERROR "must be an integer" */)
+	_ = make([]int, 5, 10.0)
+	_ = make([]int, 0i)
+	_ = make([]int, - /* ERROR "must not be negative" */ 1, 10)
+	_ = make([]int, 0, - /* ERROR "must not be negative" */ 1)
+	_ = make([]int, - /* ERROR "must not be negative" */ 1, - /* ERROR "must not be negative" */ 1)
+	_ = make([]int, 1<<100, 1<<100)  // run-time panic
+	_ = make([]int, 1 /* ERROR "length and capacity swapped" */ <<100 + 1, 1<<100)
+	_ = make([]int, 1 /* ERROR "length and capacity swapped" */ <<100, 12345)
+
+	// maps
+	_ = make /* ERROR "arguments" */ (map[int]string, 10, 20)
+	_ = make(map[int]float32, int /* ERROR "not an expression" */)
+	_ = make(map[int]float32, "foo" /* ERROR "must be an integer" */)
+	_ = make(map[int]float32, 10)
+	_ = make(map[int]float32, n)
+	_ = make(map[int]float32, int64(n))
+
+	// channels
+	_ = make /* ERROR "arguments" */ (chan int, 10, 20)
+	_ = make(chan int, int /* ERROR "not an expression" */)
+	_ = make(chan<- int, "foo" /* ERROR "must be an integer" */)
+	_ = make(<-chan float64, 10)
+	_ = make(chan chan int, n)
+	_ = make(chan string, int64(n))
+
+	make /* ERROR "not used" */ ([]int, 10)
+}
+
+func _new() {
+	_ = new /* ERROR "argument" */ ()
+	_ = new /* ERROR "argument" */ (1, 2)
+	_ = new("foo" /* ERROR "not a type" */)
+	p := new(float64)
+	_ = new(struct{ x, y int })
+	q := new(*float64)
+	_ = *p == **q
+	new /* ERROR "not used" */ (int)
+}
+
+func _panic() {
+	panic /* ERROR "arguments" */ ()
+	panic /* ERROR "arguments" */ (1, 2)
+	panic(0)
+	panic("foo")
+	panic(false)
+}
+
+func _print() {
+	print()
+	print(1)
+	print(1, 2)
+	print("foo")
+	print(2.718281828)
+	print(false)
+}
+
+func _println() {
+	println()
+	println(1)
+	println(1, 2)
+	println("foo")
+	println(2.718281828)
+	println(false)
+}
+
+func _real() {
+	var f32 float32
+	var f64 float64
+	var c64 complex64
+	var c128 complex128
+	_ = real /* ERROR "argument" */ ()
+	_ = real /* ERROR "argument" */ (1, 2)
+	_ = real(10 /* ERROR "must be a complex number" */)
+	_ = real(2.7182818 /* ERROR "must be a complex number" */)
+	_ = real("foo" /* ERROR "must be a complex number" */)
+	const _5 = real(1 + 2i)
+	assert(_5 == 1)
+	f32 = _5
+	f64 = _5
+	const _6 = real(0i)
+	assert(_6 == 0)
+	f32 = real(c64)
+	f64 = real(c128)
+	f32 = real /* ERROR "cannot assign" */ (c128)
+	f64 = real /* ERROR "cannot assign" */ (c64)
+	real /* ERROR "not used" */ (c64)
+}
+
+func _recover() {
+	_ = recover()
+	_ = recover /* ERROR "argument" */ (10)
+	recover()
+}
+
+// assuming types.DefaultPtrSize == 8
+type S0 struct{      // offset
+	a bool       //  0
+	b rune       //  4
+	c *int       //  8
+	d bool       // 16
+	e complex128 // 24
+}                    // 40
+
+type S1 struct{   // offset
+	x float32 //  0
+	y string  //  8
+	z *S1     // 24
+	S0        // 32
+}                 // 72
+
+type S2 struct{ // offset
+	*S1     //  0
+}               //  8
+
+func _Alignof() {
+	var x int
+	_ = unsafe /* ERROR "argument" */ .Alignof()
+	_ = unsafe /* ERROR "argument" */ .Alignof(1, 2)
+	_ = unsafe.Alignof(int /* ERROR "not an expression" */)
+	_ = unsafe.Alignof(42)
+	_ = unsafe.Alignof(new(struct{}))
+	unsafe /* ERROR "not used" */ .Alignof(x)
+
+	var y S0
+	assert(unsafe.Alignof(y.a) == 1)
+	assert(unsafe.Alignof(y.b) == 4)
+	assert(unsafe.Alignof(y.c) == 8)
+	assert(unsafe.Alignof(y.d) == 1)
+	assert(unsafe.Alignof(y.e) == 8)
+}
+
+func _Offsetof() {
+	var x struct{ f int }
+	_ = unsafe /* ERROR "argument" */ .Offsetof()
+	_ = unsafe /* ERROR "argument" */ .Offsetof(1, 2)
+	_ = unsafe.Offsetof(int /* ERROR "not an expression" */)
+	_ = unsafe.Offsetof(x /* ERROR "not a selector" */)
+	_ = unsafe.Offsetof(x.f)
+	_ = unsafe.Offsetof((x.f))
+	_ = unsafe.Offsetof((((((((x))).f)))))
+	unsafe /* ERROR "not used" */ .Offsetof(x.f)
+
+	var y0 S0
+	assert(unsafe.Offsetof(y0.a) == 0)
+	assert(unsafe.Offsetof(y0.b) == 4)
+	assert(unsafe.Offsetof(y0.c) == 8)
+	assert(unsafe.Offsetof(y0.d) == 16)
+	assert(unsafe.Offsetof(y0.e) == 24)
+
+	var y1 S1
+	assert(unsafe.Offsetof(y1.x) == 0)
+	assert(unsafe.Offsetof(y1.y) == 8)
+	assert(unsafe.Offsetof(y1.z) == 24)
+	assert(unsafe.Offsetof(y1.S0) == 32)
+
+	assert(unsafe.Offsetof(y1.S0.a) == 0) // relative to S0
+	assert(unsafe.Offsetof(y1.a) == 32)   // relative to S1
+	assert(unsafe.Offsetof(y1.b) == 36)   // relative to S1
+	assert(unsafe.Offsetof(y1.c) == 40)   // relative to S1
+	assert(unsafe.Offsetof(y1.d) == 48)   // relative to S1
+	assert(unsafe.Offsetof(y1.e) == 56)   // relative to S1
+
+	var y2 S2
+	assert(unsafe.Offsetof(y2.S1) == 0)
+	_ = unsafe.Offsetof(y2 /* ERROR "embedded via pointer" */ .x)
+}
+
+func _Sizeof() {
+	var x int
+	_ = unsafe /* ERROR "argument" */ .Sizeof()
+	_ = unsafe /* ERROR "argument" */ .Sizeof(1, 2)
+	_ = unsafe.Sizeof(int /* ERROR "not an expression" */)
+	_ = unsafe.Sizeof(42)
+	_ = unsafe.Sizeof(new(complex128))
+	unsafe /* ERROR "not used" */ .Sizeof(x)
+
+	// basic types have size guarantees
+	assert(unsafe.Sizeof(byte(0)) == 1)
+	assert(unsafe.Sizeof(uint8(0)) == 1)
+	assert(unsafe.Sizeof(int8(0)) == 1)
+	assert(unsafe.Sizeof(uint16(0)) == 2)
+	assert(unsafe.Sizeof(int16(0)) == 2)
+	assert(unsafe.Sizeof(uint32(0)) == 4)
+	assert(unsafe.Sizeof(int32(0)) == 4)
+	assert(unsafe.Sizeof(float32(0)) == 4)
+	assert(unsafe.Sizeof(uint64(0)) == 8)
+	assert(unsafe.Sizeof(int64(0)) == 8)
+	assert(unsafe.Sizeof(float64(0)) == 8)
+	assert(unsafe.Sizeof(complex64(0)) == 8)
+	assert(unsafe.Sizeof(complex128(0)) == 16)
+
+	var y0 S0
+	assert(unsafe.Sizeof(y0.a) == 1)
+	assert(unsafe.Sizeof(y0.b) == 4)
+	assert(unsafe.Sizeof(y0.c) == 8)
+	assert(unsafe.Sizeof(y0.d) == 1)
+	assert(unsafe.Sizeof(y0.e) == 16)
+	assert(unsafe.Sizeof(y0) == 40)
+
+	var y1 S1
+	assert(unsafe.Sizeof(y1) == 72)
+
+	var y2 S2
+	assert(unsafe.Sizeof(y2) == 8)
+}
+
+// self-testing only
+func _assert() {
+	var x int
+	assert /* ERROR "argument" */ ()
+	assert /* ERROR "argument" */ (1, 2)
+	assert("foo" /* ERROR "boolean constant" */ )
+	assert(x /* ERROR "boolean constant" */)
+	assert(true)
+	assert /* ERROR "failed" */ (false) 
+}
+
+// self-testing only
+func _trace() {
+	// Uncomment the code below to test trace - will produce console output
+	// _ = trace /* ERROR "no value" */ ()
+	// _ = trace(1)
+	// _ = trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar")
+}
diff --git a/src/pkg/go/types/testdata/const0.src b/src/pkg/go/types/testdata/const0.src
new file mode 100644
index 0000000..a2ca344
--- /dev/null
+++ b/src/pkg/go/types/testdata/const0.src
@@ -0,0 +1,215 @@
+// 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.
+
+// constant declarations
+
+package const0
+
+// constants declarations must be initialized by constants
+var x = 0
+const c0 = x /* ERROR "not constant" */
+
+// untyped constants
+const (
+	// boolean values
+	ub0 = false
+	ub1 = true
+	ub2 = 2 < 1
+	ub3 = ui1 == uf1
+	ub4 = true /* ERROR "cannot convert" */ == 0
+
+	// integer values
+	ui0 = 0
+	ui1 = 1
+	ui2 = 42
+	ui3 = 3141592653589793238462643383279502884197169399375105820974944592307816406286
+	ui4 = -10
+
+	ui5 = ui0 + ui1
+	ui6 = ui1 - ui1
+	ui7 = ui2 * ui1
+	ui8 = ui3 / ui3
+	ui9 = ui3 % ui3
+
+	ui10 = 1 / 0 /* ERROR "division by zero" */
+	ui11 = ui1 / 0 /* ERROR "division by zero" */
+	ui12 = ui3 / ui0 /* ERROR "division by zero" */
+	ui13 = 1 % 0 /* ERROR "division by zero" */
+	ui14 = ui1 % 0 /* ERROR "division by zero" */
+	ui15 = ui3 % ui0 /* ERROR "division by zero" */
+
+	ui16 = ui2 & ui3
+	ui17 = ui2 | ui3
+	ui18 = ui2 ^ ui3
+
+	// floating point values
+	uf0 = 0.
+	uf1 = 1.
+	uf2 = 4.2e1
+	uf3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
+	uf4 = 1e-1
+
+	uf5 = uf0 + uf1
+	uf6 = uf1 - uf1
+	uf7 = uf2 * uf1
+	uf8 = uf3 / uf3
+	uf9 = uf3 /* ERROR "not defined" */ % uf3
+
+	uf10 = 1 / 0 /* ERROR "division by zero" */
+	uf11 = uf1 / 0 /* ERROR "division by zero" */
+	uf12 = uf3 / uf0 /* ERROR "division by zero" */
+
+	uf16 = uf2 /* ERROR "not defined" */ & uf3
+	uf17 = uf2 /* ERROR "not defined" */ | uf3
+	uf18 = uf2 /* ERROR "not defined" */ ^ uf3
+
+	// complex values
+	uc0 = 0.i
+	uc1 = 1.i
+	uc2 = 4.2e1i
+	uc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i
+	uc4 = 1e-1i
+
+	uc5 = uc0 + uc1
+	uc6 = uc1 - uc1
+	uc7 = uc2 * uc1
+	uc8 = uc3 / uc3
+	uc9 = uc3 /* ERROR "not defined" */ % uc3
+
+	uc10 = 1 / 0 /* ERROR "division by zero" */
+	uc11 = uc1 / 0 /* ERROR "division by zero" */
+	uc12 = uc3 / uc0 /* ERROR "division by zero" */
+
+	uc16 = uc2 /* ERROR "not defined" */ & uc3
+	uc17 = uc2 /* ERROR "not defined" */ | uc3
+	uc18 = uc2 /* ERROR "not defined" */ ^ uc3
+)
+
+type (
+	mybool bool
+	myint int
+	myfloat float64
+	mycomplex complex128
+)
+
+// typed constants
+const (
+	// boolean values
+	tb0 bool = false
+	tb1 bool = true
+	tb2 mybool = 2 < 1
+	tb3 mybool = ti1 /* ERROR "cannot compare" */ == tf1
+
+	// integer values
+	ti0 int8 = ui0
+	ti1 int32 = ui1
+	ti2 int64 = ui2
+	ti3 myint = ui3 /* ERROR "overflows" */
+	ti4 myint = ui4
+
+	ti5 = ti0 /* ERROR "mismatched types" */ + ti1
+	ti6 = ti1 - ti1
+	ti7 = ti2 /* ERROR "mismatched types" */ * ti1
+	//ti8 = ti3 / ti3 // TODO(gri) enable this
+	//ti9 = ti3 % ti3 // TODO(gri) enable this
+
+	ti10 = 1 / 0 /* ERROR "division by zero" */
+	ti11 = ti1 / 0 /* ERROR "division by zero" */
+	ti12 = ti3 /* ERROR "mismatched types" */ / ti0
+	ti13 = 1 % 0 /* ERROR "division by zero" */
+	ti14 = ti1 % 0 /* ERROR "division by zero" */
+	ti15 = ti3 /* ERROR "mismatched types" */ % ti0
+
+	ti16 = ti2 /* ERROR "mismatched types" */ & ti3
+	ti17 = ti2 /* ERROR "mismatched types" */ | ti4
+	ti18 = ti2 ^ ti5 // no mismatched types error because the type of ti5 is unknown
+
+	// floating point values
+	tf0 float32 = 0.
+	tf1 float32 = 1.
+	tf2 float64 = 4.2e1
+	tf3 myfloat = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
+	tf4 myfloat = 1e-1
+
+	tf5 = tf0 + tf1
+	tf6 = tf1 - tf1
+	tf7 = tf2 /* ERROR "mismatched types" */ * tf1
+	// tf8 = tf3 / tf3 // TODO(gri) enable this
+	tf9 = tf3 /* ERROR "not defined" */ % tf3
+
+	tf10 = 1 / 0 /* ERROR "division by zero" */
+	tf11 = tf1 / 0 /* ERROR "division by zero" */
+	tf12 = tf3 /* ERROR "mismatched types" */ / tf0
+
+	tf16 = tf2 /* ERROR "mismatched types" */ & tf3
+	tf17 = tf2 /* ERROR "mismatched types" */ | tf3
+	tf18 = tf2 /* ERROR "mismatched types" */ ^ tf3
+
+	// complex values
+	tc0 = 0.i
+	tc1 = 1.i
+	tc2 = 4.2e1i
+	tc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i
+	tc4 = 1e-1i
+
+	tc5 = tc0 + tc1
+	tc6 = tc1 - tc1
+	tc7 = tc2 * tc1
+	tc8 = tc3 / tc3
+	tc9 = tc3 /* ERROR "not defined" */ % tc3
+
+	tc10 = 1 / 0 /* ERROR "division by zero" */
+	tc11 = tc1 / 0 /* ERROR "division by zero" */
+	tc12 = tc3 / tc0 /* ERROR "division by zero" */
+
+	tc16 = tc2 /* ERROR "not defined" */ & tc3
+	tc17 = tc2 /* ERROR "not defined" */ | tc3
+	tc18 = tc2 /* ERROR "not defined" */ ^ tc3
+)
+
+// initialization cycles
+const (
+	a /* ERROR "cycle" */ = a
+	b /* ERROR "cycle" */ , c /* ERROR "cycle" */, d, e = e, d, c, b // TODO(gri) should only have one cycle error
+	f float64 = d
+)
+
+// multiple initialization
+const (
+	a1, a2, a3 = 7, 3.1415926, "foo"
+	b1, b2, b3 = b3, b1, 42
+	_p0 = assert(a1 == 7)
+	_p1 = assert(a2 == 3.1415926)
+	_p2 = assert(a3 == "foo")
+	_p3 = assert(b1 == 42)
+	_p4 = assert(b2 == 42)
+	_p5 = assert(b3 == 42)
+)
+
+// iota
+const (
+	iota0 = iota
+	iota1 = iota
+	iota2 = iota*2
+	_a0 = assert(iota0 == 0)
+	_a1 = assert(iota1 == 1)
+	_a2 = assert(iota2 == 4)
+	iota6 = iota*3
+
+	iota7
+	iota8
+	_a3 = assert(iota7 == 21)
+	_a4 = assert(iota8 == 24)
+)
+
+const (
+	_b0 = iota
+	_b1 = assert(iota + iota2 == 5)
+)
+
+// special cases
+const (
+	_n0 = nil /* ERROR "invalid constant type" */
+	_n1 = [ /* ERROR "not constant" */ ]int{}
+)
\ No newline at end of file
diff --git a/src/pkg/go/types/testdata/conversions.src b/src/pkg/go/types/testdata/conversions.src
new file mode 100644
index 0000000..1b15183
--- /dev/null
+++ b/src/pkg/go/types/testdata/conversions.src
@@ -0,0 +1,18 @@
+// 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.
+
+// conversions
+
+package conversions
+
+// argument count
+var (
+	_v0 = int /* ERROR "one argument" */ ()
+	_v1 = int /* ERROR "one argument" */ (1, 2)
+)
+
+//
+var (
+	_v2 = int8(0)
+)
\ No newline at end of file
diff --git a/src/pkg/go/types/testdata/decls0.src b/src/pkg/go/types/testdata/decls0.src
new file mode 100644
index 0000000..f0115bd
--- /dev/null
+++ b/src/pkg/go/types/testdata/decls0.src
@@ -0,0 +1,187 @@
+// 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.
+
+// type declarations
+
+package decls0
+
+import (
+	"unsafe"
+	// we can have multiple blank imports (was bug)
+	_ "math"
+	_ "net/rpc"
+	// reflect defines a type "flag" which shows up in the gc export data
+	"reflect"
+	. "reflect"
+)
+
+// reflect.flag must not be visible in this package
+type flag int
+type _ reflect /* ERROR "cannot refer to unexported" */ .flag
+
+// dot-imported exported objects may conflict with local objects
+type Value /* ERROR "redeclared in this block by dot-import" */ struct{}
+
+const pi = 3.1415
+
+type (
+	N undeclared /* ERROR "undeclared" */
+	B bool
+	I int32
+	A [10]P
+	T struct {
+		x, y P
+	}
+	P *T
+	R (*R)
+	F func(A) I
+	Y interface {
+		f(A) I
+	}
+	S [](((P)))
+	M map[I]F
+	C chan<- I
+
+	// blank types must be typechecked
+	_ pi /* ERROR "not a type" */
+	_ struct{}
+	_ struct{ pi /* ERROR "not a type" */ }
+)
+
+
+// invalid array types
+type (
+	iA0 [... /* ERROR "invalid use of '...'" */ ]byte
+	iA1 [1 /* ERROR "invalid array length" */ <<100]int
+	iA2 [- /* ERROR "invalid array length" */ 1]complex128
+	iA3 ["foo" /* ERROR "invalid array length" */ ]string
+)
+
+
+type (
+	p1 pi /* ERROR "no single field or method foo" */ .foo
+	p2 unsafe.Pointer
+)
+
+
+type (
+	Pi pi /* ERROR "not a type" */
+
+	a /* ERROR "illegal cycle" */ a
+	a /* ERROR "redeclared" */ int
+
+	// where the cycle error appears depends on the
+	// order in which declarations are processed
+	// (which depends on the order in which a map
+	// is iterated through)
+	b /* ERROR "illegal cycle" */ c
+	c d
+	d e
+	e b
+
+	t *t
+
+	U V
+	V *W
+	W U
+
+	P1 *S2
+	P2 P1
+
+	S0 struct {
+	}
+	S1 struct {
+		a, b, c int
+		u, v, a /* ERROR "redeclared" */ float32
+	}
+	S2 struct {
+		U // anonymous field
+		// TODO(gri) recognize double-declaration below
+		// U /* ERROR "redeclared" */ int
+	}
+	S3 struct {
+		x S2
+	}
+	S4/* ERROR "illegal cycle" */ struct {
+		S4
+	}
+	S5 /* ERROR "illegal cycle" */ struct {
+		S6
+	}
+	S6 struct {
+		field S7
+	}
+	S7 struct {
+		S5
+	}
+
+	L1 []L1
+	L2 []int
+
+	A1 [10.0]int
+	A2 /* ERROR "illegal cycle" */ [10]A2
+	A3 /* ERROR "illegal cycle" */ [10]struct {
+		x A4
+	}
+	A4 [10]A3
+
+	F1 func()
+	F2 func(x, y, z float32)
+	F3 func(x, y, x /* ERROR "redeclared" */ float32)
+	F4 func() (x, y, x /* ERROR "redeclared" */ float32)
+	F5 func(x int) (x /* ERROR "redeclared" */ float32)
+	F6 func(x ...int)
+
+	I1 interface{}
+	I2 interface {
+		m1()
+	}
+	I3 interface { /* ERROR "multiple methods named m1" */
+		m1()
+		m1 /* ERROR "redeclared" */ ()
+	}
+	I4 interface {
+		m1(x, y, x /* ERROR "redeclared" */ float32)
+		m2() (x, y, x /* ERROR "redeclared" */ float32)
+		m3(x int) (x /* ERROR "redeclared" */ float32)
+	}
+	I5 interface {
+		m1(I5)
+	}
+	I6 interface {
+		S0 /* ERROR "not an interface" */
+	}
+	I7 interface {
+		I1
+		I1
+	}
+	I8 /* ERROR "illegal cycle" */ interface {
+		I8
+	}
+	// Use I09 (rather than I9) because it appears lexically before
+	// I10 so that we get the illegal cycle here rather then in the
+	// declaration of I10. If the implementation sorts by position
+	// rather than name, the error message will still be here.
+	I09 /* ERROR "illegal cycle" */ interface {
+		I10
+	}
+	I10 interface {
+		I11
+	}
+	I11 interface {
+		I09
+	}
+
+	C1 chan int
+	C2 <-chan int
+	C3 chan<- C3
+	C4 chan C5
+	C5 chan C6
+	C6 chan C4
+
+	M1 map[Last]string
+	M2 map[string]M2
+
+	Last int
+)
diff --git a/src/pkg/go/types/testdata/decls1.src b/src/pkg/go/types/testdata/decls1.src
new file mode 100644
index 0000000..2251f45
--- /dev/null
+++ b/src/pkg/go/types/testdata/decls1.src
@@ -0,0 +1,132 @@
+// 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.
+
+// variable declarations
+
+package decls1
+
+import (
+	"math"
+)
+
+// Global variables without initialization
+var (
+	a, b bool
+	c byte
+	d uint8
+	r rune
+	i int
+	j, k, l int
+	x, y float32
+	xx, yy float64
+	u, v complex64
+	uu, vv complex128
+	s, t string
+	array []byte
+	iface interface{}
+	
+	blank _ /* ERROR "cannot use _" */
+)
+
+// Global variables with initialization
+var (
+	s1 = i + j
+	s2 = i /* ERROR "mismatched types" */ + x
+	s3 = c + d
+	s4 = s + t
+	s5 = s /* ERROR "invalid operation" */ / t
+	s6 = array[t1]
+	s7 = array[x /* ERROR "index" */]
+	s8 = &a
+	s10 = &42 /* ERROR "cannot take address" */
+	s11 = &v
+	s12 = -(u + *t11) / *&v
+	s13 = a /* ERROR "shifted operand" */ << d
+	s14 = i << j /* ERROR "must be unsigned" */ 
+	s18 = math.Pi * 10.0
+	s19 = s1 /* ERROR "cannot call" */ ()
+ 	s20 = f0 /* ERROR "no value" */ ()
+	s21 = f6(1, s1, i)
+	s22 = f6(1, s1, uu /* ERROR "cannot assign" */ )
+	
+	t1 int = i + j
+	t2 int = i /* ERROR "mismatched types" */ + x
+	t3 int = c /* ERROR "cannot assign" */ + d
+	t4 string = s + t
+	t5 string = s /* ERROR "invalid operation" */ / t
+	t6 byte = array[t1]
+	t7 byte = array[x /* ERROR "index" */]
+	t8 *int = & /* ERROR "cannot assign" */ a
+	t10 *int = &42 /* ERROR "cannot take address" */
+	t11 *complex64 = &v
+	t12 complex64 = -(u + *t11) / *&v
+	t13 int = a /* ERROR "shifted operand" */ << d
+	t14 int = i << j /* ERROR "must be unsigned" */ 
+	t15 math /* ERROR "not in selector" */
+	t16 math /* ERROR "unexported" */ .xxx
+	t17 math /* ERROR "not a type" */ .Pi
+	t18 float64 = math.Pi * 10.0
+	t19 int = t1 /* ERROR "cannot call" */ ()
+	t20 int = f0 /* ERROR "no value" */ ()
+)
+
+// Various more complex expressions
+var (
+	u1 = x /* ERROR "not an interface" */ .(int)
+	u2 = iface.([]int)
+	u3 = iface.(a /* ERROR "not a type" */ )
+	u4, ok = iface.(int)
+	u5 /* ERROR "assignment count mismatch" */ , ok2, ok3 = iface.(int)
+)
+
+// Constant expression initializations
+var (
+	v1 = 1 /* ERROR "cannot convert" */ + "foo"
+	v2 = c + 255
+	v3 = c + 256 /* ERROR "overflows" */
+	v4 = r + 2147483647
+	v5 = r + 2147483648 /* ERROR "overflows" */
+	v6 = 42
+	v7 = v6 + 9223372036854775807
+	v8 = v6 + 9223372036854775808 /* ERROR "overflows" */
+	v9 = i + 1 << 10
+	v10 byte = 1024 /* ERROR "overflows" */
+	v11 = xx/yy*yy - xx
+	v12 = true && false
+	v13 = nil /* ERROR "use of untyped nil" */
+)
+
+// Multiple assignment expressions
+var (
+	m1a, m1b = 1, 2
+	m2a /* ERROR "assignment count mismatch" */ , m2b, m2c = 1, 2
+	m3a /* ERROR "assignment count mismatch" */ , m3b = 1, 2, 3
+)
+
+// Declaration of parameters and results
+func f0() {}
+func f1(a /* ERROR "not a type" */) {}
+func f2(a, b, c d /* ERROR "not a type" */) {}
+
+func f3() int {}
+func f4() a /* ERROR "not a type" */ {}
+func f5() (a, b, c d /* ERROR "not a type" */) {}
+
+func f6(a, b, c int) complex128 { return 0 }
+
+// Declaration of receivers
+type T struct{}
+
+func (T) m0() {}
+func (*T) m1() {}
+func (x T) m2() {}
+func (x *T) m3() {}
+
+
+// Initialization functions
+func init() {}
+func /* ERROR "no arguments and no return values" */ init(int) {}
+func /* ERROR "no arguments and no return values" */ init() int { return 0 }
+func /* ERROR "no arguments and no return values" */ init(int) int {}
+func (T) init(int) int { return 0 }
diff --git a/src/pkg/go/types/testdata/decls2a.src b/src/pkg/go/types/testdata/decls2a.src
new file mode 100644
index 0000000..3867be7
--- /dev/null
+++ b/src/pkg/go/types/testdata/decls2a.src
@@ -0,0 +1,67 @@
+// 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.
+
+// method declarations
+
+package decls2
+
+import "time"
+
+// T1 declared before its methods.
+type T1 struct{
+	f int
+}
+
+func (T1) m() {}
+func (T1) m /* ERROR "redeclared" */ () {}
+func (x *T1) f /* ERROR "field and method" */ () {}
+
+// T2's method declared before the type.
+func (*T2) f /* ERROR "field and method" */ () {}
+
+type T2 struct {
+	f int
+}
+
+// Methods declared without a declared type.
+func (undeclared /* ERROR "undeclared" */) m() {}
+func (x *undeclared /* ERROR "undeclared" */) m() {}
+
+// TODO(gri) try to get rid of double error reporting here
+func (pi /* ERROR "not a type" */) m1() {}
+func (x pi /* ERROR "not a type" */) m2() {}
+func (x *pi /* ERROR "not a type" */ ) m3() {} // TODO(gri) not closing the last /* comment crashes the system
+
+// Blank types.
+type _ struct { m int }
+type _ struct { m int }
+
+// TODO(gri) blank idents not fully checked - disabled for now
+// func (_ /* ERROR "cannot use _" */) m() {}
+// func (_ /* ERROR "cannot use _" */) m() {}
+
+// Methods with receiver base type declared in another file.
+func (T3) m1() {}
+func (*T3) m2() {}
+func (x T3) m3() {}
+func (x *T3) f /* ERROR "field and method" */ () {}
+
+// Methods of non-struct type.
+type T4 func()
+
+func (self T4) m() func() { return self }
+
+// Methods associated with an interface.
+type T5 interface {
+	m() int
+}
+
+func (T5 /* ERROR "invalid receiver" */) m1() {}
+func (T5 /* ERROR "invalid receiver" */) m2() {}
+
+// Methods associated with non-local or unnamed types.
+func (int /* ERROR "non-local type" */ ) m() {}
+func ([ /* ERROR "expected" */ ]int) m() {}
+func (time /* ERROR "expected" */ .Time) m() {}
+func (x interface /* ERROR "expected" */ {}) m() {}
diff --git a/src/pkg/go/types/testdata/decls2b.src b/src/pkg/go/types/testdata/decls2b.src
new file mode 100644
index 0000000..c7f9ddf
--- /dev/null
+++ b/src/pkg/go/types/testdata/decls2b.src
@@ -0,0 +1,28 @@
+// 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.
+
+// method declarations
+
+package decls2
+
+const pi = 3.1415
+
+func (T1) m /* ERROR "redeclared" */ () {}
+
+type T3 struct {
+	f *T3
+}
+
+type T6 struct {
+	x int
+}
+
+func (t *T6) m1() int {
+	return t.x
+}
+
+func f() {
+	var t *T6
+	t.m1()
+}
\ No newline at end of file
diff --git a/src/pkg/go/types/testdata/decls3.src b/src/pkg/go/types/testdata/decls3.src
new file mode 100644
index 0000000..6aa9f90
--- /dev/null
+++ b/src/pkg/go/types/testdata/decls3.src
@@ -0,0 +1,253 @@
+// 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.
+
+// embedded types
+
+package decls3
+
+// fields with the same name at the same level cancel each other out
+
+func _() {
+	type (
+		T1 struct { X int }
+		T2 struct { X int }
+		T3 struct { T1; T2 } // X is embedded twice at the same level via T1->X, T2->X
+	)
+
+	var t T3
+	_ = t /* ERROR "no single field or method" */ .X
+}
+
+func _() {
+	type (
+		T1 struct { X int }
+		T2 struct { T1 }
+		T3 struct { T1 }
+		T4 struct { T2; T3 } // X is embedded twice at the same level via T2->T1->X, T3->T1->X
+	)
+
+	var t T4
+	_ = t /* ERROR "no single field or method" */ .X
+}
+
+func issue4355() {
+	type (
+	    T1 struct {X int}
+	    T2 struct {T1}
+	    T3 struct {T2}
+	    T4 struct {T2}
+	    T5 struct {T3; T4} // X is embedded twice at the same level via T3->T2->T1->X, T4->T2->T1->X
+	)	
+
+	var t T5
+	_ = t /* ERROR "no single field or method" */ .X
+}
+
+// Embedded fields can be predeclared types.
+
+func _() {
+	type T0 struct{
+		int
+		float32
+		f int
+	}
+	var x T0
+	_ = x.int
+	_ = x.float32
+	_ = x.f
+
+	type T1 struct{
+		T0
+	}
+	var y T1
+	_ = y.int
+	_ = y.float32
+	_ = y.f
+}
+
+// Borrowed from the FieldByName test cases in reflect/all_test.go.
+
+type D1 struct {
+	d int
+}
+type D2 struct {
+	d int
+}
+
+type S0 struct {
+	A, B, C int
+	D1
+	D2
+}
+
+type S1 struct {
+	B int
+	S0
+}
+
+type S2 struct {
+	A int
+	*S1
+}
+
+type S1x struct {
+	S1
+}
+
+type S1y struct {
+	S1
+}
+
+type S3 struct {
+	S1x
+	S2
+	D, E int
+	*S1y
+}
+
+type S4 struct {
+	*S4
+	A int
+}
+
+// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
+type S5 struct {
+	S6
+	S7
+	S8
+}
+
+type S6 struct {
+	X int
+}
+
+type S7 S6
+
+type S8 struct {
+	S9
+}
+
+type S9 struct {
+	X int
+	Y int
+}
+
+// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
+type S10 struct {
+	S11
+	S12
+	S13
+}
+
+type S11 struct {
+	S6
+}
+
+type S12 struct {
+	S6
+}
+
+type S13 struct {
+	S8
+}
+
+func _() {
+	_ = struct /* ERROR "no single field or method" */ {}{}.Foo
+	_ = S0{}.A
+	_ = S0 /* ERROR "no single field or method" */ {}.D
+	_ = S1{}.A
+	_ = S1{}.B
+	_ = S1{}.S0
+	_ = S1{}.C
+	_ = S2{}.A
+	_ = S2{}.S1
+	_ = S2{}.B
+	_ = S2{}.C
+	_ = S2 /* ERROR "no single field or method" */ {}.D
+	_ = S3 /* ERROR "no single field or method" */ {}.S1
+	_ = S3{}.A
+	_ = S3 /* ERROR "no single field or method" */ {}.B
+	_ = S3{}.D
+	_ = S3{}.E
+	_ = S4{}.A
+	_ = S4 /* ERROR "no single field or method" */ {}.B
+	_ = S5 /* ERROR "no single field or method" */ {}.X
+	_ = S5{}.Y
+	_ = S10 /* ERROR "no single field or method" */ {}.X
+	_ = S10{}.Y
+}
+
+// Borrowed from the FieldByName benchmark in reflect/all_test.go.
+
+type R0 struct {
+	*R1
+	*R2
+	*R3
+	*R4
+}
+
+type R1 struct {
+	*R5
+	*R6
+	*R7
+	*R8
+}
+
+type R2 R1
+type R3 R1
+type R4 R1
+
+type R5 struct {
+	*R9
+	*R10
+	*R11
+	*R12
+}
+
+type R6 R5
+type R7 R5
+type R8 R5
+
+type R9 struct {
+	*R13
+	*R14
+	*R15
+	*R16
+}
+
+type R10 R9
+type R11 R9
+type R12 R9
+
+type R13 struct {
+	*R17
+	*R18
+	*R19
+	*R20
+}
+
+type R14 R13
+type R15 R13
+type R16 R13
+
+type R17 struct {
+	*R21
+	*R22
+	*R23
+	*R24
+}
+
+type R18 R17
+type R19 R17
+type R20 R17
+
+type R21 struct {
+	X int
+}
+
+type R22 R21
+type R23 R21
+type R24 R21
+
+var _ = R0 /* ERROR "no single field or method" */ {}.X
\ No newline at end of file
diff --git a/src/pkg/go/types/testdata/exports.go b/src/pkg/go/types/testdata/exports.go
new file mode 100644
index 0000000..8ee28b0
--- /dev/null
+++ b/src/pkg/go/types/testdata/exports.go
@@ -0,0 +1,89 @@
+// 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 is used to generate an object file which
+// serves as test file for gcimporter_test.go.
+
+package exports
+
+import (
+	"go/ast"
+)
+
+// Issue 3682: Correctly read dotted identifiers from export data.
+const init1 = 0
+
+func init() {}
+
+const (
+	C0 int = 0
+	C1     = 3.14159265
+	C2     = 2.718281828i
+	C3     = -123.456e-789
+	C4     = +123.456E+789
+	C5     = 1234i
+	C6     = "foo\n"
+	C7     = `bar\n`
+)
+
+type (
+	T1  int
+	T2  [10]int
+	T3  []int
+	T4  *int
+	T5  chan int
+	T6a chan<- int
+	T6b chan (<-chan int)
+	T6c chan<- (chan int)
+	T7  <-chan *ast.File
+	T8  struct{}
+	T9  struct {
+		a    int
+		b, c float32
+		d    []string `go:"tag"`
+	}
+	T10 struct {
+		T8
+		T9
+		_ *T10
+	}
+	T11 map[int]string
+	T12 interface{}
+	T13 interface {
+		m1()
+		m2(int) float32
+	}
+	T14 interface {
+		T12
+		T13
+		m3(x ...struct{}) []T9
+	}
+	T15 func()
+	T16 func(int)
+	T17 func(x int)
+	T18 func() float32
+	T19 func() (x float32)
+	T20 func(...interface{})
+	T21 struct{ next *T21 }
+	T22 struct{ link *T23 }
+	T23 struct{ link *T22 }
+	T24 *T24
+	T25 *T26
+	T26 *T27
+	T27 *T25
+	T28 func(T28) T28
+)
+
+var (
+	V0 int
+	V1 = -991.0
+)
+
+func F1()         {}
+func F2(x int)    {}
+func F3() int     { return 0 }
+func F4() float32 { return 0 }
+func F5(a, b, c int, u, v, w struct{ x, y T1 }, more ...interface{}) (p, q, r chan<- T10)
+
+func (p *T1) M1()
diff --git a/src/pkg/go/types/testdata/expr0.src b/src/pkg/go/types/testdata/expr0.src
new file mode 100644
index 0000000..8d057f6
--- /dev/null
+++ b/src/pkg/go/types/testdata/expr0.src
@@ -0,0 +1,161 @@
+// 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.
+
+// unary expressions
+
+package expr0 
+
+var (
+	// bool
+	b0 = true
+	b1 bool = b0
+	b2 = !true
+	b3 = !b1
+	b4 bool = !true
+	b5 bool = !b4
+	b6 = +b0 /* ERROR "not defined" */
+	b7 = -b0 /* ERROR "not defined" */
+	b8 = ^b0 /* ERROR "not defined" */
+	b9 = *b0 /* ERROR "cannot indirect" */
+	b10 = &true /* ERROR "cannot take address" */
+	b11 = &b0
+	b12 = <-b0 /* ERROR "cannot receive" */
+
+	// int
+	i0 = 1
+	i1 int = i0
+	i2 = +1
+	i3 = +i0
+	i4 int = +1
+	i5 int = +i4
+	i6 = -1
+	i7 = -i0
+	i8 int = -1
+	i9 int = -i4
+	i10 = !i0 /* ERROR "not defined" */
+	i11 = ^1
+	i12 = ^i0
+	i13 int = ^1
+	i14 int = ^i4
+	i15 = *i0 /* ERROR "cannot indirect" */
+	i16 = &i0
+	i17 = *i16
+	i18 = <-i16 /* ERROR "cannot receive" */
+
+	// uint
+	u0 = uint(1)
+	u1 uint = u0
+	u2 = +1
+	u3 = +u0
+	u4 uint = +1
+	u5 uint = +u4
+	u6 = -1
+	u7 = -u0
+	u8 uint = - /* ERROR "overflows" */ 1
+	u9 uint = -u4
+	u10 = !u0 /* ERROR "not defined" */
+	u11 = ^1
+	u12 = ^i0
+	u13 uint = ^ /* ERROR "overflows" */ 1
+	u14 uint = ^u4
+	u15 = *u0 /* ERROR "cannot indirect" */
+	u16 = &u0
+	u17 = *u16
+	u18 = <-u16 /* ERROR "cannot receive" */
+	u19 = ^uint(0)
+
+	// float64
+	f0 = float64(1)
+	f1 float64 = f0
+	f2 = +1
+	f3 = +f0
+	f4 float64 = +1
+	f5 float64 = +f4 /* ERROR not defined */
+	f6 = -1
+	f7 = -f0
+	f8 float64 = -1
+	f9 float64 = -f4
+	f10 = !f0 /* ERROR "not defined" */
+	f11 = ^1
+	f12 = ^i0
+	f13 float64 = ^1
+	f14 float64 = ^f4 /* ERROR "not defined" */
+	f15 = *f0 /* ERROR "cannot indirect" */
+	f16 = &f0
+	f17 = *u16
+	f18 = <-u16 /* ERROR "cannot receive" */
+
+	// complex128
+	c0 = complex128(1)
+	c1 complex128 = c0
+	c2 = +1
+	c3 = +c0
+	c4 complex128 = +1
+	c5 complex128 = +c4 /* ERROR not defined */
+	c6 = -1
+	c7 = -c0
+	c8 complex128 = -1
+	c9 complex128 = -c4
+	c10 = !c0 /* ERROR "not defined" */
+	c11 = ^1
+	c12 = ^i0
+	c13 complex128 = ^1
+	c14 complex128 = ^c4 /* ERROR "not defined" */
+	c15 = *c0 /* ERROR "cannot indirect" */
+	c16 = &c0
+	c17 = *u16
+	c18 = <-u16 /* ERROR "cannot receive" */
+
+	// string
+	s0 = "foo"
+	s1 = +"foo" /* ERROR "not defined" */
+	s2 = -s0 /* ERROR "not defined" */
+	s3 = !s0 /* ERROR "not defined" */
+	s4 = ^s0 /* ERROR "not defined" */
+	s5 = *s4 /* ERROR "cannot indirect" */
+	s6 = &s4
+	s7 = *s6
+	s8 = <-s7  /* ERROR "cannot receive" */
+
+	// channel
+	ch chan int
+	rc <-chan float64
+	sc chan <- string
+	ch0 = +ch /* ERROR "not defined" */
+	ch1 = -ch /* ERROR "not defined" */
+	ch2 = !ch /* ERROR "not defined" */
+	ch3 = ^ch /* ERROR "not defined" */
+	ch4 = *ch /* ERROR "cannot indirect" */
+	ch5 = &ch
+	ch6 = *ch5
+	ch7 = <-ch
+	ch8 = <-rc
+	ch9 = <-sc /* ERROR "cannot receive" */
+)
+
+// address of composite literals
+type T struct{x, y int}
+
+func f() T { return T{} }
+
+var (
+	_ = &T{1, 2}
+	_ = &[...]int{}
+	_ = &[]int{}
+	_ = &[]int{}
+	_ = &map[string]T{}
+	_ = &(T{1, 2})
+	_ = &((((T{1, 2}))))
+	_ = &f /* ERROR "cannot take address" */ ()
+)
+
+// recursive pointer types
+type P *P
+
+var (
+	p1 P = new(P)
+	p2 P = *p1
+	p3 P = &p2
+)
+
diff --git a/src/pkg/go/types/testdata/expr1.src b/src/pkg/go/types/testdata/expr1.src
new file mode 100644
index 0000000..8ef0aed
--- /dev/null
+++ b/src/pkg/go/types/testdata/expr1.src
@@ -0,0 +1,7 @@
+// 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.
+
+// binary expressions
+
+package expr1
diff --git a/src/pkg/go/types/testdata/expr2.src b/src/pkg/go/types/testdata/expr2.src
new file mode 100644
index 0000000..674be40
--- /dev/null
+++ b/src/pkg/go/types/testdata/expr2.src
@@ -0,0 +1,23 @@
+// 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.
+
+// comparisons
+
+package expr2
+
+func _bool() {
+	const t = true == true
+	const f = true == false
+	_ = t /* ERROR "cannot compare" */ < f
+	_ = 0 /* ERROR "cannot convert" */ == t
+	var b bool
+	var x, y float32
+	b = x < y
+	_ = struct{b bool}{x < y}
+}
+
+// corner cases
+var (
+	v0 = nil /* ERROR "cannot compare" */ == nil
+)
\ No newline at end of file
diff --git a/src/pkg/go/types/testdata/expr3.src b/src/pkg/go/types/testdata/expr3.src
new file mode 100644
index 0000000..ff17f2e
--- /dev/null
+++ b/src/pkg/go/types/testdata/expr3.src
@@ -0,0 +1,463 @@
+// 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.
+
+// various expressions
+
+package expr3
+
+func shifts1() {
+	var (
+		i0 int
+		u0 uint
+	)
+
+	var (
+		v0 = 1<<0
+		v1 = 1<<i0 /* ERROR "must be unsigned" */
+		v2 = 1<<u0
+		v3 = 1<<"foo" /* ERROR "must be unsigned" */
+		v4 = 1<<- /* ERROR "stupid shift" */ 1
+		v5 = 1<<1025 /* ERROR "stupid shift" */
+		v6 = 1 /* ERROR "overflows" */ <<100
+
+		v10 uint = 1 << 0
+		v11 uint = 1 << u0
+		v12 float32 = 1 /* ERROR "must be integer" */ << u0
+	)
+}
+
+func shifts2() {
+	// from the spec
+	var (
+		s uint = 33
+		i = 1<<s           // 1 has type int
+		j int32 = 1<<s     // 1 has type int32; j == 0
+		k = uint64(1<<s)   // 1 has type uint64; k == 1<<33
+		m int = 1.0<<s     // 1.0 has type int
+		n = 1.0<<s != 0    // 1.0 has type int; n == false if ints are 32bits in size
+		o = 1<<s == 2<<s   // 1 and 2 have type int; o == true if ints are 32bits in size
+		p = 1<<s == 1<<33  // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
+		u = 1.0 /* ERROR "must be integer" */ <<s         // illegal: 1.0 has type float64, cannot shift
+		v float32 = 1 /* ERROR "must be integer" */ <<s   // illegal: 1 has type float32, cannot shift
+		w int64 = 1.0<<33  // 1.0<<33 is a constant shift expression
+	)
+}
+
+func shifts3(a int16, b float32) {
+	var (
+		s uint = 11
+		u = 1 /* ERROR "must be integer" */ <<s + 1.0
+		v complex128 = 1 /* ERROR "must be integer" */ << s + 1.0 /* ERROR "must be integer" */ << s + 1
+	)
+	x := 1.0 /* ERROR "must be integer" */ <<s + 1
+	shifts3(1.0 << s, 1 /* ERROR "must be integer" */ >> s)
+	// TODO(gri) add more tests (systematically)
+}
+
+func shifts4() {
+	// from src/pkg/compress/lzw/reader.go:90
+	{
+		var d struct {
+			bits     uint32
+			width    uint
+		}
+		_ = uint16(d.bits & (1<<d.width - 1))
+	}
+
+	// from src/pkg/debug/dwarf/buf.go:116
+	{
+		var ux uint64
+		var bits uint
+		x := int64(ux)
+		if x&(1<<(bits-1)) != 0 {}
+	}
+
+	// from src/pkg/encoding/asn1/asn1.go:160
+	{
+		var bytes []byte
+		if bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {}
+	}
+
+	// from src/pkg/math/big/rat.go:140
+	{
+		var exp int
+		var mantissa uint64
+		shift := uint64(-1022 - (exp - 1)) // [1..53)
+		_ = mantissa & (1<<shift - 1)
+	}
+
+	// from src/pkg/net/interface.go:51
+	{
+		type Flags uint
+		var f Flags
+		var i int
+		if f&(1<<uint(i)) != 0 {}
+	}
+
+	// from src/pkg/runtime/softfloat64.go:234
+	{
+		var gm uint64
+		var shift uint
+		_ = gm & (1<<shift - 1)
+	}
+
+	// from src/pkg/strconv/atof.go:326
+	{
+		var mant uint64
+		var mantbits uint
+		if mant == 2<<mantbits {}
+	}
+
+	// from src/pkg/syscall/route_bsd.go:82
+	{
+		var Addrs int32
+		const rtaRtMask = 1
+		var i uint
+		if Addrs&rtaRtMask&(1<<i) == 0 {}
+	}
+
+	// from src/pkg/text/scanner/scanner.go:540
+	{
+		var s struct { Whitespace uint64 }
+		var ch rune
+		for s.Whitespace&(1<<uint(ch)) != 0 {}
+	}
+}
+
+// TODO(gri) The error messages below depond on adjusting the spec
+//           to reflect what gc is doing at the moment (the spec
+//           asks for run-time errors at the moment - see issue 4231).
+//
+func indexes() {
+	_ = 1 /* ERROR "cannot index" */ [0]
+	_ = indexes /* ERROR "cannot index" */ [0]
+	_ = ( /* ERROR "cannot slice" */ 12 + 3)[1:2]
+
+	var a [10]int
+	_ = a[true /* ERROR "must be integer" */ ]
+	_ = a["foo" /* ERROR "must be integer" */ ]
+	_ = a[1.1 /* ERROR "must be integer" */ ]
+	_ = a[1.0]
+	_ = a[- /* ERROR "index .* negative" */ 1]
+	_ = a[- /* ERROR "index .* negative" */ 1 :]
+	_ = a[: - /* ERROR "index .* negative" */ 1]
+	var a0 int
+	a0 = a[0]
+	var a1 int32
+	a1 = a /* ERROR "cannot assign" */ [1] 
+	_ = a[9]
+	_ = a[10 /* ERROR "index .* out of bounds" */ ]
+	_ = a[1 /* ERROR "stupid index" */ <<100]
+	_ = a[10:]
+	_ = a[:10]
+	_ = a[10:10]
+	_ = a[11 /* ERROR "index .* out of bounds" */ :]
+	_ = a[: 11 /* ERROR "index .* out of bounds" */ ]
+	_ = a[: 1 /* ERROR "stupid index" */ <<100]
+
+	pa := &a
+	_ = pa[9]
+	_ = pa[10 /* ERROR "index .* out of bounds" */ ]
+	_ = pa[1 /* ERROR "stupid index" */ <<100]
+	_ = pa[10:]
+	_ = pa[:10]
+	_ = pa[10:10]
+	_ = pa[11 /* ERROR "index .* out of bounds" */ :]
+	_ = pa[: 11 /* ERROR "index .* out of bounds" */ ]
+	_ = pa[: 1 /* ERROR "stupid index" */ <<100]
+
+	var b [0]int
+	_ = b[0 /* ERROR "index .* out of bounds" */ ]
+	_ = b[:]
+	_ = b[0:]
+	_ = b[:0]
+	_ = b[0:0]
+
+	var s []int
+	_ = s[- /* ERROR "index .* negative" */ 1]
+	_ = s[- /* ERROR "index .* negative" */ 1 :]
+	_ = s[: - /* ERROR "index .* negative" */ 1]
+	_ = s[0]
+	_ = s[1 : 2]
+	_ = s[2 /* ERROR "inverted slice range" */ : 1]
+	_ = s[2 :]
+	_ = s[: 1 /* ERROR "stupid index" */ <<100]
+	_ = s[1 /* ERROR "stupid index" */ <<100 :]
+	_ = s[1 /* ERROR "stupid index" */ <<100 : 1 /* ERROR "stupid index" */ <<100]
+
+	var t string
+	_ = t[- /* ERROR "index .* negative" */ 1]
+	_ = t[- /* ERROR "index .* negative" */ 1 :]
+	_ = t[: - /* ERROR "index .* negative" */ 1]
+	var t0 byte
+	t0 = t[0]
+	var t1 rune
+	t1 = t /* ERROR "cannot assign" */ [2]
+	_ = ("foo" + "bar")[5]
+	_ = ("foo" + "bar")[6 /* ERROR "index .* out of bounds" */ ]
+
+	const c = "foo"
+	_ = c[- /* ERROR "index .* negative" */ 1]
+	_ = c[- /* ERROR "index .* negative" */ 1 :]
+	_ = c[: - /* ERROR "index .* negative" */ 1]
+	var c0 byte
+	c0 = c[0]
+	var c2 float32
+	c2 = c /* ERROR "cannot assign" */ [2]
+	_ = c[3 /* ERROR "index .* out of bounds" */ ]
+	_ = ""[0 /* ERROR "index .* out of bounds" */ ]
+
+	_ = s[1<<30] // no compile-time error here
+
+	// issue 4913
+	type mystring string
+	var ss string
+	var ms mystring
+	var i, j int
+	ss = "foo"[1:2]
+	ss = "foo"[i:j]
+	ms = "foo" /* ERROR "cannot assign" */ [1:2]
+	ms = "foo" /* ERROR "cannot assign" */ [i:j]
+}
+
+type T struct {
+	x int
+}
+
+func (*T) m() {}
+
+func method_expressions() {
+	_ = T /* ERROR "no single field or method" */ .a
+	_ = T /* ERROR "has no method" */ .x
+	_ = T.m
+	var f func(*T) = (*T).m
+	var g func(*T) = ( /* ERROR "cannot assign" */ T).m
+}
+
+func struct_literals() {
+	type T0 struct {
+		a, b, c int
+	}
+
+	type T1 struct {
+		T0
+		a, b int
+		u float64
+		s string
+	}
+
+	// keyed elements
+	_ = T1{}
+	_ = T1{a: 0, 1 /* ERROR "mixture of .* elements" */ }
+	_ = T1{aa /* ERROR "unknown field" */ : 0}
+	_ = T1{1 /* ERROR "invalid field name" */ : 0}
+	_ = T1{a: 0, s: "foo", u: 0, a /* ERROR "duplicate field" */: 10}
+	_ = T1{a: "foo" /* ERROR "cannot use" */ }
+	_ = T1{c /* ERROR "unknown field" */ : 0}
+	_ = T1{T0: { /* ERROR "missing type" */ }}
+	_ = T1{T0: T0{}}
+	_ = T1{T0 /* ERROR "invalid field name" */ .a: 0}
+
+	// unkeyed elements
+	_ = T0{1, 2, 3}
+	_ = T0{1, b /* ERROR "mixture" */ : 2, 3}
+	_ = T0{1, 2} /* ERROR "too few values" */
+	_ = T0{1, 2, 3, 4  /* ERROR "too many values" */ }
+	_ = T0{1, "foo" /* ERROR "cannot use" */, 3.4  /* ERROR "cannot use" */}
+}
+
+func array_literals() {
+	type A0 [0]int
+	_ = A0{}
+	_ = A0{0 /* ERROR "index .* out of bounds" */}
+	_ = A0{0 /* ERROR "index .* out of bounds" */ : 0}
+
+	type A1 [10]int
+	_ = A1{}
+	_ = A1{0, 1, 2}
+	_ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+	_ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /* ERROR "index .* out of bounds" */ }
+	_ = A1{- /* ERROR "index .* negative" */ 1: 0}
+	_ = A1{8: 8, 9}
+	_ = A1{8: 8, 9, 10 /* ERROR "index .* out of bounds" */ }
+	_ = A1{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	_ = A1{5: 5, 6, 7, 3: 3, 4}
+	_ = A1{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
+	_ = A1{10 /* ERROR "index .* out of bounds" */ : 10, 10 /* ERROR "index .* out of bounds" */ : 10}
+	_ = A1{5: 5, 6, 7, 3: 3, 1 /* ERROR "stupid index" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
+	_ = A1{5: 5, 6, 7, 4: 4, 1 /* ERROR "stupid index" */ <<100: 4}
+	_ = A1{2.0}
+	_ = A1{2.1 /* ERROR "cannot use" */ }
+	_ = A1{"foo" /* ERROR "cannot use" */ }
+
+	a0 := [...]int{}
+	assert(len(a0) == 0)
+	
+	a1 := [...]int{0, 1, 2}
+	assert(len(a1) == 3)
+	var a13 [3]int
+	var a14 [4]int
+	a13 = a1
+	a14 = a1 /* ERROR "cannot assign" */
+	
+	a2 := [...]int{- /* ERROR "index .* negative" */ 1: 0}
+
+	a3 := [...]int{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	assert(len(a3) == 5) // somewhat arbitrary
+
+	a4 := [...]complex128{0, 1, 2, 1<<10-2: -1i, 1i, 400: 10, 12, 14}
+	assert(len(a4) == 1024)
+
+	// from the spec
+	type Point struct { x, y float32 }
+	_ = [...]Point{Point{1.5, -3.5}, Point{0, 0}}
+	_ = [...]Point{{1.5, -3.5}, {0, 0}}
+	_ = [][]int{[]int{1, 2, 3}, []int{4, 5}}
+	_ = [][]int{{1, 2, 3}, {4, 5}}
+	_ = [...]*Point{&Point{1.5, -3.5}, &Point{0, 0}}
+	_ = [...]*Point{{1.5, -3.5}, {0, 0}}
+}
+
+func slice_literals() {
+	type S0 []int
+	_ = S0{}
+	_ = S0{0, 1, 2}
+	_ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
+	_ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+	_ = S0{- /* ERROR "index .* negative" */ 1: 0}
+	_ = S0{8: 8, 9}
+	_ = S0{8: 8, 9, 10}
+	_ = S0{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
+	_ = S0{5: 5, 6, 7, 3: 3, 4}
+	_ = S0{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
+	_ = S0{10: 10, 10 /* ERROR "duplicate index" */ : 10}
+	_ = S0{5: 5, 6, 7, 3: 3, 1 /* ERROR "stupid index" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
+	_ = S0{5: 5, 6, 7, 4: 4, 1 /* ERROR "stupid index" */ <<100: 4}
+	_ = S0{2.0}
+	_ = S0{2.1 /* ERROR "cannot use" */ }
+	_ = S0{"foo" /* ERROR "cannot use" */ }
+
+	// indices must be resolved correctly
+	// (for details, see comment in go/parser/parser.go, method parseElement)
+	index1 := 1
+	_ = S0{index1: 1}
+	_ = S0{index2: 2}
+	_ = S0{index3 /* ERROR "undeclared name" */ : 3}
+}
+
+var index2 int = 2
+
+func map_literals() {
+	type M0 map[string]int
+	type M1 map[bool]int
+	type M2 map[*int]int
+
+	_ = M0{}
+	_ = M0{1 /* ERROR "missing key" */ }
+	_ = M0{1 /* ERROR "cannot use .* as string key" */ : 2}
+	_ = M0{"foo": "bar" /* ERROR "cannot use .* as int value" */ }
+	_ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 }
+
+	// map keys must be resolved correctly
+	// (for details, see comment in go/parser/parser.go, method parseElement)
+	key1 := "foo"
+	_ = M0{key1: 1}
+	_ = M0{key2: 2}
+	_ = M0{key3 /* ERROR "undeclared name" */ : 2}
+
+	_ = M1{true: 1, false: 0}
+	_ = M2{nil: 0, &index2: 1}
+}
+
+var key2 string = "bar"
+
+type I interface {
+	m()
+}
+
+type I2 interface {
+	m(int)
+}
+
+type T1 struct{}
+type T2 struct{}
+
+func (T2) m(int) {}
+
+func type_asserts() {
+	var x int
+	_ = x /* ERROR "not an interface" */ .(int)
+
+	var e interface{}
+	var ok bool
+	x, ok = e.(int)
+
+	var t I
+	_ = t /* ERROR "use of .* outside type switch" */ .(type)
+	_ = t.(T)
+	_ = t.(T1 /* ERROR "missing method m" */ )
+	_ = t.(T2 /* ERROR "wrong type for method m" */ )
+	_ = t.(I2 /* ERROR "wrong type for method m" */ )
+}
+
+func f0() {}
+func f1(x int) {}
+func f2(u float32, s string) {}
+func fs(s []byte) {}
+func fv(x ...int) {}
+func fi(x ... interface{}) {}
+
+func g0() {}
+func g1() int { return 0}
+func g2() (u float32, s string) { return }
+func gs() []byte { return nil }
+
+func _calls() {
+	var x int
+	var y float32
+	var s []int
+
+	f0()
+	_ = f0 /* ERROR "used as value" */ ()
+	f0(g0 /* ERROR "too many arguments" */ )
+
+	f1(0)
+	f1(x)
+	f1(10.0)
+	f1 /* ERROR "too few arguments" */ ()
+	f1(x, y /* ERROR "too many arguments" */ )
+	f1(s /* ERROR "cannot assign" */ )
+	f1(x ... /* ERROR "cannot use ..." */ )
+	f1(g0 /* ERROR "used as value" */ ())
+	f1(g1())
+	// f1(g2()) // TODO(gri) missing position in error message
+
+	f2 /* ERROR "too few arguments" */ ()
+	f2 /* ERROR "too few arguments" */ (3.14)
+	f2(3.14, "foo")
+	f2(x /* ERROR "cannot assign" */ , "foo")
+	f2(g0 /* ERROR "used as value" */ ())
+	f2 /* ERROR "too few arguments" */ (g1 /* ERROR "cannot assign" */ ())
+	f2(g2())
+
+	fs /* ERROR "too few arguments" */ ()
+	fs(g0 /* ERROR "used as value" */ ())
+	fs(g1 /* ERROR "cannot assign" */ ())
+	// fs(g2()) // TODO(gri) missing position in error message
+	fs(gs())
+
+	fv()
+	fv(1, 2.0, x)
+	fv(s /* ERROR "cannot assign" */ )
+	fv(s...)
+	fv(1, s /* ERROR "can only use ... with matching parameter" */ ...)
+	fv(gs /* ERROR "cannot assign" */ ())
+	fv(gs /* ERROR "cannot assign" */ ()...)
+
+	fi()
+	fi(1, 2.0, x, 3.14, "foo")
+	fi(g2())
+	fi(0, g2)
+	fi(0, g2 /* ERROR "2-valued expression" */ ())
+}
diff --git a/src/pkg/go/types/testdata/stmt0.src b/src/pkg/go/types/testdata/stmt0.src
new file mode 100644
index 0000000..9d85de3
--- /dev/null
+++ b/src/pkg/go/types/testdata/stmt0.src
@@ -0,0 +1,288 @@
+// 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.
+
+// statements
+
+package stmt0
+
+func _() {
+	b, i, f, c, s := false, 1, 1.0, 1i, "foo"
+	b = i /* ERROR "cannot assign" */
+	i = f /* ERROR "cannot assign" */
+	f = c /* ERROR "cannot assign" */
+	c = s /* ERROR "cannot assign" */
+	s = b /* ERROR "cannot assign" */
+
+	v0 /* ERROR "mismatch" */, v1, v2 := 1, 2, 3, 4
+
+	b = true
+
+	i += 1
+	i += "foo" /* ERROR "cannot convert.*int" */
+
+	f -= 1
+	f -= "foo" /* ERROR "cannot convert.*float64" */
+
+	c *= 1
+	c /= 0 /* ERROR "division by zero" */
+
+	s += "bar"
+	s += 1 /* ERROR "cannot convert.*string" */
+
+	var u64 uint64
+	u64 += 1<<u64
+
+	undeclared /* ERROR "undeclared" */ = 991
+}
+
+func incdecs() {
+	const c = 3.14
+	c /* ERROR "cannot assign" */ ++
+	s := "foo"
+	s /* ERROR "cannot convert" */ --
+	3.14 /* ERROR "cannot assign" */ ++
+	var (
+		x int
+		y float32
+		z complex128
+	)
+	x++
+	y--
+	z++
+}
+
+func sends() {
+	var ch chan int
+	var rch <-chan int
+	var x int
+	x /* ERROR "cannot send" */ <- x
+	rch /* ERROR "cannot send" */ <- x
+	ch <- "foo" /* ERROR "cannot convert" */
+	ch <- x
+}
+
+func selects() {
+	select {}
+	var (
+		ch chan int
+		sc chan <- bool
+		x int
+	)
+	select {
+	case <-ch:
+		ch <- x
+	case t, ok := <-ch:
+		x = t
+	case <-sc /* ERROR "cannot receive from send-only channel" */ :
+	}
+	select {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+}
+
+func gos() {
+	go 1 /* ERROR "expected function/method call" */
+	go gos()
+	var c chan int
+	go close(c)
+	go len(c) // TODO(gri) this should not be legal
+}
+
+func defers() {
+	defer 1 /* ERROR "expected function/method call" */
+	defer defers()
+	var c chan int
+	defer close(c)
+	defer len(c) // TODO(gri) this should not be legal
+}
+
+func switches() {
+	var x int
+
+	switch x {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+
+	switch {
+	case 1  /* ERROR "cannot convert" */ :
+	}
+
+	switch int32(x) {
+	case 1, 2:
+	case x /* ERROR "cannot compare" */ :
+	}
+
+	switch x {
+	case 1 /* ERROR "overflows int" */ << 100:
+	}
+
+	switch x {
+	case 1:
+	case 1 /* ERROR "duplicate case" */ :
+	case 2, 3, 4:
+	case 1 /* ERROR "duplicate case" */ :
+	}
+
+	// TODO(gri) duplicate 64bit values that don't fit into an int64 are not yet detected
+	switch uint64(x) {
+	case 1<<64-1:
+	case 1<<64-1:
+	}
+}
+
+type I interface {
+	m()
+}
+
+type I2 interface {
+	m(int)
+}
+
+type T struct{}
+type T1 struct{}
+type T2 struct{}
+
+func (T) m() {}
+func (T2) m(int) {}
+
+func typeswitches() {
+	var i int
+	var x interface{}
+
+	switch x.(type) {}
+	switch (x /* ERROR "outside type switch" */ .(type)) {}
+
+	switch x.(type) {
+	default:
+	default /* ERROR "multiple defaults" */ :
+	}
+
+	switch x := x.(type) {}
+
+	switch x := x.(type) {
+	case int:
+		var y int = x
+	}
+
+	switch x := i /* ERROR "not an interface" */ .(type) {}
+
+	switch t := x.(type) {
+	case nil:
+		var v bool = t /* ERROR "cannot assign" */
+	case int:
+		var v int = t
+	case float32, complex64:
+		var v float32 = t /* ERROR "cannot assign" */
+	default:
+		var v float32 = t /* ERROR "cannot assign" */
+	}
+
+	var t I
+	switch t.(type) {
+	case T:
+	case T1 /* ERROR "missing method m" */ :
+	case T2 /* ERROR "wrong type for method m" */ :
+	case I2 /* ERROR "wrong type for method m" */ :
+	}
+}
+
+func typeswitch0() {
+	switch y := interface{}(nil).(type) {
+	case int:
+		// TODO(gri) y has the wrong type here (type-checking
+		// of captured variable is delayed)
+		// func() int { return y + 0 }()
+	}
+}
+
+func rangeloops() {
+	var (
+		x int
+		a [10]float32
+		b []string
+		p *[10]complex128
+		pp **[10]complex128
+		s string
+		m map[int]bool
+		c chan int
+		sc chan<- int
+		rc <-chan int
+	)
+
+	for _ = range x /* ERROR "cannot range over" */ {}
+	for i := range x /* ERROR "cannot range over" */ {}
+
+	for i := range a {
+		var ii int
+		ii = i
+	}
+	for i, x := range a {
+		var ii int
+		ii = i
+		var xx float64
+		xx = x /* ERROR "cannot assign" */
+	}
+	var ii int
+	var xx float32
+	for ii, xx := range a {}
+
+	for i := range b {
+		var ii int
+		ii = i
+	}
+	for i, x := range b {
+		var ii int
+		ii = i
+		var xx string
+		xx = x
+	}
+
+	for i := range s {
+		var ii int
+		ii = i
+	}
+	for i, x := range s {
+		var ii int
+		ii = i
+		var xx rune
+		xx = x
+	}
+
+	for _, x := range p {
+		var xx complex128
+		xx = x
+	}
+
+	for _, x := range pp /* ERROR "cannot range over" */ {}
+
+	for k := range m {
+		var kk int32
+		kk = k /* ERROR "cannot assign" */
+	}
+	for k, v := range m {
+		var kk int
+		kk = k
+		if v {}
+	}
+
+	for _, _ /* ERROR "only one iteration variable" */ = range c {}
+	for e := range c {
+		var ee int
+		ee = e
+	}
+	for _ = range sc /* ERROR "cannot range over send-only channel" */ {}
+	for _ = range rc {}
+
+	// constant strings
+	const cs = "foo"
+	for i, x := range cs {}
+	for i, x := range "" {
+		var ii int
+		ii = i
+		var xx rune
+		xx = x
+	}
+}
diff --git a/src/pkg/go/types/types.go b/src/pkg/go/types/types.go
new file mode 100644
index 0000000..2f2e579
--- /dev/null
+++ b/src/pkg/go/types/types.go
@@ -0,0 +1,236 @@
+// 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 types
+
+import "go/ast"
+
+// All types implement the Type interface.
+type Type interface {
+	String() string
+	aType()
+}
+
+// BasicKind describes the kind of basic type.
+type BasicKind int
+
+const (
+	Invalid BasicKind = iota // type is invalid
+
+	// predeclared types
+	Bool
+	Int
+	Int8
+	Int16
+	Int32
+	Int64
+	Uint
+	Uint8
+	Uint16
+	Uint32
+	Uint64
+	Uintptr
+	Float32
+	Float64
+	Complex64
+	Complex128
+	String
+	UnsafePointer
+
+	// types for untyped values
+	UntypedBool
+	UntypedInt
+	UntypedRune
+	UntypedFloat
+	UntypedComplex
+	UntypedString
+	UntypedNil
+
+	// aliases
+	Byte = Uint8
+	Rune = Int32
+)
+
+// BasicInfo is a set of flags describing properties of a basic type.
+type BasicInfo int
+
+// Properties of basic types.
+const (
+	IsBoolean BasicInfo = 1 << iota
+	IsInteger
+	IsUnsigned
+	IsFloat
+	IsComplex
+	IsString
+	IsUntyped
+
+	IsOrdered   = IsInteger | IsFloat | IsString
+	IsNumeric   = IsInteger | IsFloat | IsComplex
+	IsConstType = IsBoolean | IsNumeric | IsString
+)
+
+// A Basic represents a basic type.
+type Basic struct {
+	Kind BasicKind
+	Info BasicInfo
+	size int64 // use DefaultSizeof to get size
+	Name string
+}
+
+// An Array represents an array type [Len]Elt.
+type Array struct {
+	Len int64
+	Elt Type
+}
+
+// A Slice represents a slice type []Elt.
+type Slice struct {
+	Elt Type
+}
+
+// A QualifiedName is a name qualified with the package that declared the name.
+// Note: Pkg may be a fake package (no name, no scope) because the GC compiler's
+//       export information doesn't provide full information in some cases.
+// TODO(gri): Should change Pkg to PkgPath since it's the only thing we care about.
+type QualifiedName struct {
+	Pkg  *Package // nil only for predeclared error.Error (exported)
+	Name string   // unqualified type name for anonymous fields
+}
+
+// IsSame reports whether p and q are the same.
+func (p QualifiedName) IsSame(q QualifiedName) bool {
+	// spec:
+	// "Two identifiers are different if they are spelled differently,
+	// or if they appear in different packages and are not exported.
+	// Otherwise, they are the same."
+	if p.Name != q.Name {
+		return false
+	}
+	// p.Name == q.Name
+	return ast.IsExported(p.Name) || p.Pkg.Path == q.Pkg.Path
+}
+
+// A Field represents a field of a struct.
+type Field struct {
+	QualifiedName
+	Type        Type
+	Tag         string
+	IsAnonymous bool
+}
+
+// A Struct represents a struct type struct{...}.
+type Struct struct {
+	Fields  []*Field
+	offsets []int64 // field offsets in bytes, lazily computed
+}
+
+func (typ *Struct) fieldIndex(name QualifiedName) int {
+	for i, f := range typ.Fields {
+		if f.QualifiedName.IsSame(name) {
+			return i
+		}
+	}
+	return -1
+}
+
+// A Pointer represents a pointer type *Base.
+type Pointer struct {
+	Base Type
+}
+
+// A Result represents a (multi-value) function call result.
+type Result struct {
+	Values []*Var // Signature.Results of the function called
+}
+
+// A Signature represents a user-defined function type func(...) (...).
+type Signature struct {
+	Recv       *Var   // nil if not a method
+	Params     []*Var // (incoming) parameters from left to right; or nil
+	Results    []*Var // (outgoing) results from left to right; or nil
+	IsVariadic bool   // true if the last parameter's type is of the form ...T
+}
+
+// builtinId is an id of a builtin function.
+type builtinId int
+
+// Predeclared builtin functions.
+const (
+	// Universe scope
+	_Append builtinId = iota
+	_Cap
+	_Close
+	_Complex
+	_Copy
+	_Delete
+	_Imag
+	_Len
+	_Make
+	_New
+	_Panic
+	_Print
+	_Println
+	_Real
+	_Recover
+
+	// Unsafe package
+	_Alignof
+	_Offsetof
+	_Sizeof
+
+	// Testing support
+	_Assert
+	_Trace
+)
+
+// A builtin represents the type of a built-in function.
+type builtin struct {
+	id          builtinId
+	name        string
+	nargs       int // number of arguments (minimum if variadic)
+	isVariadic  bool
+	isStatement bool // true if the built-in is valid as an expression statement
+}
+
+// A Method represents a method.
+type Method struct {
+	QualifiedName
+	Type *Signature
+}
+
+// An Interface represents an interface type interface{...}.
+type Interface struct {
+	Methods []*Method // TODO(gri) consider keeping them in sorted order
+}
+
+// A Map represents a map type map[Key]Elt.
+type Map struct {
+	Key, Elt Type
+}
+
+// A Chan represents a channel type chan Elt, <-chan Elt, or chan<-Elt.
+type Chan struct {
+	Dir ast.ChanDir
+	Elt Type
+}
+
+// A NamedType represents a named type as declared in a type declaration.
+type NamedType struct {
+	Obj        *TypeName // corresponding declared object
+	Underlying Type      // nil if not fully declared yet; never a *NamedType
+	Methods    []*Method // TODO(gri) consider keeping them in sorted order
+}
+
+func (*Basic) aType()     {}
+func (*Array) aType()     {}
+func (*Slice) aType()     {}
+func (*Struct) aType()    {}
+func (*Pointer) aType()   {}
+func (*Result) aType()    {}
+func (*Signature) aType() {}
+func (*builtin) aType()   {}
+func (*Interface) aType() {}
+func (*Map) aType()       {}
+func (*Chan) aType()      {}
+func (*NamedType) aType() {}
diff --git a/src/pkg/go/types/types_test.go b/src/pkg/go/types/types_test.go
new file mode 100644
index 0000000..8e228fa
--- /dev/null
+++ b/src/pkg/go/types/types_test.go
@@ -0,0 +1,171 @@
+// 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.
+
+// This file contains tests verifying the types associated with an AST after
+// type checking.
+
+package types
+
+import (
+	"go/ast"
+	"go/parser"
+	"testing"
+)
+
+const filename = "<src>"
+
+func makePkg(t *testing.T, src string) (*Package, error) {
+	file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
+	if err != nil {
+		return nil, err
+	}
+	pkg, err := Check(fset, []*ast.File{file})
+	return pkg, err
+}
+
+type testEntry struct {
+	src, str string
+}
+
+// dup returns a testEntry where both src and str are the same.
+func dup(s string) testEntry {
+	return testEntry{s, s}
+}
+
+var testTypes = []testEntry{
+	// basic types
+	dup("int"),
+	dup("float32"),
+	dup("string"),
+
+	// arrays
+	dup("[10]int"),
+
+	// slices
+	dup("[]int"),
+	dup("[][]int"),
+
+	// structs
+	dup("struct{}"),
+	dup("struct{x int}"),
+	{`struct {
+		x, y int
+		z float32 "foo"
+	}`, `struct{x int; y int; z float32 "foo"}`},
+	{`struct {
+		string
+		elems []T
+	}`, `struct{string; elems []T}`},
+
+	// pointers
+	dup("*int"),
+	dup("***struct{}"),
+	dup("*struct{a int; b float32}"),
+
+	// functions
+	dup("func()"),
+	dup("func(x int)"),
+	{"func(x, y int)", "func(x int, y int)"},
+	{"func(x, y int, z string)", "func(x int, y int, z string)"},
+	dup("func(int)"),
+	{"func(int, string, byte)", "func(int, string, byte)"},
+
+	dup("func() int"),
+	{"func() (string)", "func() string"},
+	dup("func() (u int)"),
+	{"func() (u, v int, w string)", "func() (u int, v int, w string)"},
+
+	dup("func(int) string"),
+	dup("func(x int) string"),
+	dup("func(x int) (u string)"),
+	{"func(x, y int) (u string)", "func(x int, y int) (u string)"},
+
+	dup("func(...int) string"),
+	dup("func(x ...int) string"),
+	dup("func(x ...int) (u string)"),
+	{"func(x, y ...int) (u string)", "func(x int, y ...int) (u string)"},
+
+	// interfaces
+	dup("interface{}"),
+	dup("interface{m()}"),
+	dup(`interface{m(int) float32; String() string}`),
+	// TODO(gri) add test for interface w/ anonymous field
+
+	// maps
+	dup("map[string]int"),
+	{"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"},
+
+	// channels
+	dup("chan int"),
+	dup("chan<- func()"),
+	dup("<-chan []func() int"),
+}
+
+func TestTypes(t *testing.T) {
+	for _, test := range testTypes {
+		src := "package p; type T " + test.src
+		pkg, err := makePkg(t, src)
+		if err != nil {
+			t.Errorf("%s: %s", src, err)
+			continue
+		}
+		typ := underlying(pkg.Scope.Lookup("T").GetType())
+		str := typeString(typ)
+		if str != test.str {
+			t.Errorf("%s: got %s, want %s", test.src, str, test.str)
+		}
+	}
+}
+
+var testExprs = []testEntry{
+	// basic type literals
+	dup("x"),
+	dup("true"),
+	dup("42"),
+	dup("3.1415"),
+	dup("2.71828i"),
+	dup(`'a'`),
+	dup(`"foo"`),
+	dup("`bar`"),
+
+	// arbitrary expressions
+	dup("&x"),
+	dup("*&x"),
+	dup("(x)"),
+	dup("x + y"),
+	dup("x + y * 10"),
+	dup("t.foo"),
+	dup("s[0]"),
+	dup("s[x:y]"),
+	dup("s[:y]"),
+	dup("s[x:]"),
+	dup("s[:]"),
+	dup("f(1, 2.3)"),
+	dup("-f(10, 20)"),
+	dup("f(x + y, +3.1415)"),
+	{"func(a, b int) {}", "(func literal)"},
+	{"func(a, b int) []int {}(1, 2)[x]", "(func literal)(1, 2)[x]"},
+	{"[]int{1, 2, 3}", "(composite literal)"},
+	{"[]int{1, 2, 3}[x:]", "(composite literal)[x:]"},
+	{"i.([]string)", "i.(...)"},
+}
+
+func TestExprs(t *testing.T) {
+	for _, test := range testExprs {
+		src := "package p; var _ = " + test.src + "; var (x, y int; s []string; f func(int, float32) int; i interface{}; t interface { foo() })"
+		file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
+		if err != nil {
+			t.Errorf("%s: %s", src, err)
+			continue
+		}
+		// TODO(gri) writing the code below w/o the decl variable will
+		//           cause a 386 compiler error (out of fixed registers)
+		decl := file.Decls[0].(*ast.GenDecl)
+		expr := decl.Specs[0].(*ast.ValueSpec).Values[0]
+		str := exprString(expr)
+		if str != test.str {
+			t.Errorf("%s: got %s, want %s", test.src, str, test.str)
+		}
+	}
+}
diff --git a/src/pkg/go/types/universe.go b/src/pkg/go/types/universe.go
new file mode 100644
index 0000000..b218525
--- /dev/null
+++ b/src/pkg/go/types/universe.go
@@ -0,0 +1,146 @@
+// 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 implements the universe and unsafe package scopes.
+
+package types
+
+import (
+	"go/ast"
+	"strings"
+)
+
+var (
+	Universe     *Scope
+	Unsafe       *Package
+	universeIota *Const
+)
+
+// Predeclared types, indexed by BasicKind.
+var Typ = [...]*Basic{
+	Invalid: {Invalid, 0, 0, "invalid type"},
+
+	Bool:          {Bool, IsBoolean, 1, "bool"},
+	Int:           {Int, IsInteger, 0, "int"},
+	Int8:          {Int8, IsInteger, 1, "int8"},
+	Int16:         {Int16, IsInteger, 2, "int16"},
+	Int32:         {Int32, IsInteger, 4, "int32"},
+	Int64:         {Int64, IsInteger, 8, "int64"},
+	Uint:          {Uint, IsInteger | IsUnsigned, 0, "uint"},
+	Uint8:         {Uint8, IsInteger | IsUnsigned, 1, "uint8"},
+	Uint16:        {Uint16, IsInteger | IsUnsigned, 2, "uint16"},
+	Uint32:        {Uint32, IsInteger | IsUnsigned, 4, "uint32"},
+	Uint64:        {Uint64, IsInteger | IsUnsigned, 8, "uint64"},
+	Uintptr:       {Uintptr, IsInteger | IsUnsigned, 0, "uintptr"},
+	Float32:       {Float32, IsFloat, 4, "float32"},
+	Float64:       {Float64, IsFloat, 8, "float64"},
+	Complex64:     {Complex64, IsComplex, 8, "complex64"},
+	Complex128:    {Complex128, IsComplex, 16, "complex128"},
+	String:        {String, IsString, 0, "string"},
+	UnsafePointer: {UnsafePointer, 0, 0, "Pointer"},
+
+	UntypedBool:    {UntypedBool, IsBoolean | IsUntyped, 0, "untyped boolean"},
+	UntypedInt:     {UntypedInt, IsInteger | IsUntyped, 0, "untyped integer"},
+	UntypedRune:    {UntypedRune, IsInteger | IsUntyped, 0, "untyped rune"},
+	UntypedFloat:   {UntypedFloat, IsFloat | IsUntyped, 0, "untyped float"},
+	UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, 0, "untyped complex"},
+	UntypedString:  {UntypedString, IsString | IsUntyped, 0, "untyped string"},
+	UntypedNil:     {UntypedNil, IsUntyped, 0, "untyped nil"},
+}
+
+var aliases = [...]*Basic{
+	{Byte, IsInteger | IsUnsigned, 1, "byte"},
+	{Rune, IsInteger, 4, "rune"},
+}
+
+var predeclaredConstants = [...]*Const{
+	{nil, "true", Typ[UntypedBool], true, nil},
+	{nil, "false", Typ[UntypedBool], false, nil},
+	{nil, "iota", Typ[UntypedInt], zeroConst, nil},
+	{nil, "nil", Typ[UntypedNil], nilConst, nil},
+}
+
+var predeclaredFunctions = [...]*builtin{
+	{_Append, "append", 1, true, false},
+	{_Cap, "cap", 1, false, false},
+	{_Close, "close", 1, false, true},
+	{_Complex, "complex", 2, false, false},
+	{_Copy, "copy", 2, false, true},
+	{_Delete, "delete", 2, false, true},
+	{_Imag, "imag", 1, false, false},
+	{_Len, "len", 1, false, false},
+	{_Make, "make", 1, true, false},
+	{_New, "new", 1, false, false},
+	{_Panic, "panic", 1, false, true},
+	{_Print, "print", 0, true, true},
+	{_Println, "println", 0, true, true},
+	{_Real, "real", 1, false, false},
+	{_Recover, "recover", 0, false, true},
+
+	{_Alignof, "Alignof", 1, false, false},
+	{_Offsetof, "Offsetof", 1, false, false},
+	{_Sizeof, "Sizeof", 1, false, false},
+}
+
+func init() {
+	Universe = new(Scope)
+	Unsafe = &Package{Name: "unsafe", Scope: new(Scope)}
+
+	// predeclared types
+	for _, t := range Typ {
+		def(&TypeName{Name: t.Name, Type: t})
+	}
+	for _, t := range aliases {
+		def(&TypeName{Name: t.Name, Type: t})
+	}
+
+	// error type
+	{
+		// Error has a nil package in its qualified name since it is in no package
+		err := &Method{QualifiedName{nil, "Error"}, &Signature{Results: []*Var{{Name: "", Type: Typ[String]}}}}
+		def(&TypeName{Name: "error", Type: &NamedType{Underlying: &Interface{Methods: []*Method{err}}}})
+	}
+
+	for _, c := range predeclaredConstants {
+		def(c)
+	}
+
+	for _, f := range predeclaredFunctions {
+		def(&Func{Name: f.name, Type: f})
+	}
+
+	universeIota = Universe.Lookup("iota").(*Const)
+}
+
+// Objects with names containing blanks are internal and not entered into
+// a scope. Objects with exported names are inserted in the unsafe package
+// scope; other objects are inserted in the universe scope.
+//
+func def(obj Object) {
+	name := obj.GetName()
+	if strings.Index(name, " ") >= 0 {
+		return // nothing to do
+	}
+	// fix Obj link for named types
+	if typ, ok := obj.GetType().(*NamedType); ok {
+		typ.Obj = obj.(*TypeName)
+	}
+	// exported identifiers go into package unsafe
+	scope := Universe
+	if ast.IsExported(name) {
+		scope = Unsafe.Scope
+		// set Pkg field
+		switch obj := obj.(type) {
+		case *TypeName:
+			obj.Pkg = Unsafe
+		case *Func:
+			obj.Pkg = Unsafe
+		default:
+			unreachable()
+		}
+	}
+	if scope.Insert(obj) != nil {
+		panic("internal error: double declaration")
+	}
+}
diff --git a/src/pkg/hash/adler32/adler32.go b/src/pkg/hash/adler32/adler32.go
index 64fe68c..7c80796 100644
--- a/src/pkg/hash/adler32/adler32.go
+++ b/src/pkg/hash/adler32/adler32.go
@@ -3,7 +3,8 @@
 // license that can be found in the LICENSE file.
 
 // Package adler32 implements the Adler-32 checksum.
-// Defined in RFC 1950:
+//
+// It is defined in RFC 1950:
 //	Adler-32 is composed of two sums accumulated per byte: s1 is
 //	the sum of all bytes, s2 is the sum of all s1 values. Both sums
 //	are done modulo 65521. s1 is initialized to 1, s2 to zero.  The
@@ -14,20 +15,22 @@ package adler32
 import "hash"
 
 const (
+	// mod is the largest prime that is less than 65536.
 	mod = 65521
+	// nmax is the largest n such that
+	// 255 * n * (n+1) / 2 + (n+1) * (mod-1) <= 2^32-1.
+	// It is mentioned in RFC 1950 (search for "5552").
+	nmax = 5552
 )
 
 // The size of an Adler-32 checksum in bytes.
 const Size = 4
 
 // digest represents the partial evaluation of a checksum.
-type digest struct {
-	// invariant: (a < mod && b < mod) || a <= b
-	// invariant: a + b + 255 <= 0xffffffff
-	a, b uint32
-}
+// The low 16 bits are s1, the high 16 bits are s2.
+type digest uint32
 
-func (d *digest) Reset() { d.a, d.b = 1, 0 }
+func (d *digest) Reset() { *d = 1 }
 
 // New returns a new hash.Hash32 computing the Adler-32 checksum.
 func New() hash.Hash32 {
@@ -40,47 +43,36 @@ func (d *digest) Size() int { return Size }
 
 func (d *digest) BlockSize() int { return 1 }
 
-// Add p to the running checksum a, b.
-func update(a, b uint32, p []byte) (aa, bb uint32) {
-	for _, pi := range p {
-		a += uint32(pi)
-		b += a
-		// invariant: a <= b
-		if b > (0xffffffff-255)/2 {
-			a %= mod
-			b %= mod
-			// invariant: a < mod && b < mod
-		} else {
-			// invariant: a + b + 255 <= 2 * b + 255 <= 0xffffffff
+// Add p to the running checksum d.
+func update(d digest, p []byte) digest {
+	s1, s2 := uint32(d&0xffff), uint32(d>>16)
+	for len(p) > 0 {
+		var q []byte
+		if len(p) > nmax {
+			p, q = p[:nmax], p[nmax:]
 		}
+		for _, x := range p {
+			s1 += uint32(x)
+			s2 += s1
+		}
+		s1 %= mod
+		s2 %= mod
+		p = q
 	}
-	return a, b
-}
-
-// Return the 32-bit checksum corresponding to a, b.
-func finish(a, b uint32) uint32 {
-	if b >= mod {
-		a %= mod
-		b %= mod
-	}
-	return b<<16 | a
+	return digest(s2<<16 | s1)
 }
 
 func (d *digest) Write(p []byte) (nn int, err error) {
-	d.a, d.b = update(d.a, d.b, p)
+	*d = update(*d, p)
 	return len(p), nil
 }
 
-func (d *digest) Sum32() uint32 { return finish(d.a, d.b) }
+func (d *digest) Sum32() uint32 { return uint32(*d) }
 
 func (d *digest) Sum(in []byte) []byte {
-	s := d.Sum32()
-	in = append(in, byte(s>>24))
-	in = append(in, byte(s>>16))
-	in = append(in, byte(s>>8))
-	in = append(in, byte(s))
-	return in
+	s := uint32(*d)
+	return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
 }
 
 // Checksum returns the Adler-32 checksum of data.
-func Checksum(data []byte) uint32 { return finish(update(1, 0, data)) }
+func Checksum(data []byte) uint32 { return uint32(update(1, data)) }
diff --git a/src/pkg/hash/adler32/adler32_test.go b/src/pkg/hash/adler32/adler32_test.go
index 01f931c..0e9c938 100644
--- a/src/pkg/hash/adler32/adler32_test.go
+++ b/src/pkg/hash/adler32/adler32_test.go
@@ -5,26 +5,23 @@
 package adler32
 
 import (
-	"bytes"
-	"io"
+	"strings"
 	"testing"
 )
 
-type _Adler32Test struct {
+var golden = []struct {
 	out uint32
 	in  string
-}
-
-var golden = []_Adler32Test{
-	{0x1, ""},
-	{0x620062, "a"},
-	{0x12600c4, "ab"},
-	{0x24d0127, "abc"},
-	{0x3d8018b, "abcd"},
-	{0x5c801f0, "abcde"},
-	{0x81e0256, "abcdef"},
-	{0xadb02bd, "abcdefg"},
-	{0xe000325, "abcdefgh"},
+}{
+	{0x00000001, ""},
+	{0x00620062, "a"},
+	{0x012600c4, "ab"},
+	{0x024d0127, "abc"},
+	{0x03d8018b, "abcd"},
+	{0x05c801f0, "abcde"},
+	{0x081e0256, "abcdef"},
+	{0x0adb02bd, "abcdefg"},
+	{0x0e000325, "abcdefgh"},
 	{0x118e038e, "abcdefghi"},
 	{0x158603f8, "abcdefghij"},
 	{0x3f090f02, "Discard medicine more than two years old."},
@@ -48,30 +45,61 @@ var golden = []_Adler32Test{
 	{0x91dd304f, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
 	{0x2e5d1316, "How can you write a big system without C++?  -Paul Glick"},
 	{0xd0201df6, "'Invariant assertions' is the most elegant programming technique!  -Tom Szymanski"},
+	{0x211297c8, strings.Repeat("\xff", 5548) + "8"},
+	{0xbaa198c8, strings.Repeat("\xff", 5549) + "9"},
+	{0x553499be, strings.Repeat("\xff", 5550) + "0"},
+	{0xf0c19abe, strings.Repeat("\xff", 5551) + "1"},
+	{0x8d5c9bbe, strings.Repeat("\xff", 5552) + "2"},
+	{0x2af69cbe, strings.Repeat("\xff", 5553) + "3"},
+	{0xc9809dbe, strings.Repeat("\xff", 5554) + "4"},
+	{0x69189ebe, strings.Repeat("\xff", 5555) + "5"},
+	{0x86af0001, strings.Repeat("\x00", 1e5)},
+	{0x79660b4d, strings.Repeat("a", 1e5)},
+	{0x110588ee, strings.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1e4)},
+}
+
+// checksum is a slow but simple implementation of the Adler-32 checksum.
+// It is a straight port of the sample code in RFC 1950 section 9.
+func checksum(p []byte) uint32 {
+	s1, s2 := uint32(1), uint32(0)
+	for _, x := range p {
+		s1 = (s1 + uint32(x)) % mod
+		s2 = (s2 + s1) % mod
+	}
+	return s2<<16 | s1
 }
 
 func TestGolden(t *testing.T) {
-	for i := 0; i < len(golden); i++ {
-		g := golden[i]
-		c := New()
-		io.WriteString(c, g.in)
-		s := c.Sum32()
-		if s != g.out {
-			t.Errorf("adler32(%s) = 0x%x want 0x%x", g.in, s, g.out)
-			t.FailNow()
+	for _, g := range golden {
+		in := g.in
+		if len(in) > 220 {
+			in = in[:100] + "..." + in[len(in)-100:]
+		}
+		p := []byte(g.in)
+		if got := checksum(p); got != g.out {
+			t.Errorf("simple implementation: checksum(%q) = 0x%x want 0x%x", in, got, g.out)
+			continue
+		}
+		if got := Checksum(p); got != g.out {
+			t.Errorf("optimized implementation: Checksum(%q) = 0x%x want 0x%x", in, got, g.out)
+			continue
 		}
 	}
 }
 
-func BenchmarkGolden(b *testing.B) {
-	b.StopTimer()
-	c := New()
-	var buf bytes.Buffer
-	for _, g := range golden {
-		buf.Write([]byte(g.in))
+func BenchmarkAdler32KB(b *testing.B) {
+	b.SetBytes(1024)
+	data := make([]byte, 1024)
+	for i := range data {
+		data[i] = byte(i)
 	}
-	b.StartTimer()
+	h := New()
+	in := make([]byte, 0, h.Size())
+
+	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		c.Write(buf.Bytes())
+		h.Reset()
+		h.Write(data)
+		h.Sum(in)
 	}
 }
diff --git a/src/pkg/hash/crc32/crc32.go b/src/pkg/hash/crc32/crc32.go
index 236d778..a2a21a0 100644
--- a/src/pkg/hash/crc32/crc32.go
+++ b/src/pkg/hash/crc32/crc32.go
@@ -123,11 +123,7 @@ func (d *digest) Sum32() uint32 { return d.crc }
 
 func (d *digest) Sum(in []byte) []byte {
 	s := d.Sum32()
-	in = append(in, byte(s>>24))
-	in = append(in, byte(s>>16))
-	in = append(in, byte(s>>8))
-	in = append(in, byte(s))
-	return in
+	return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
 }
 
 // Checksum returns the CRC-32 checksum of data
diff --git a/src/pkg/hash/crc32/crc32_amd64.go b/src/pkg/hash/crc32/crc32_amd64.go
index 83349bc..b5bc6d3 100644
--- a/src/pkg/hash/crc32/crc32_amd64.go
+++ b/src/pkg/hash/crc32/crc32_amd64.go
@@ -13,7 +13,7 @@ func haveSSE42() bool
 
 // castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32
 // instruction.
-func castagnoliSSE42(uint32, []byte) uint32
+func castagnoliSSE42(crc uint32, p []byte) uint32
 
 var sse42 = haveSSE42()
 
diff --git a/src/pkg/hash/crc32/crc32_amd64.s b/src/pkg/hash/crc32/crc32_amd64.s
index a9e5317..6e6a364 100644
--- a/src/pkg/hash/crc32/crc32_amd64.s
+++ b/src/pkg/hash/crc32/crc32_amd64.s
@@ -6,12 +6,12 @@
 TEXT ·castagnoliSSE42(SB),7,$0
 	MOVL crc+0(FP), AX  // CRC value
 	MOVQ p+8(FP), SI  // data pointer
-	MOVL p+16(FP), CX  // len(p)
+	MOVQ p+16(FP), CX  // len(p)
 
 	NOTL AX
 
 	/* If there's less than 8 bytes to process, we do it byte-by-byte. */
-	CMPL CX, $8
+	CMPQ CX, $8
 	JL cleanup
 
 	/* Process individual bytes until the input is 8-byte aligned. */
@@ -21,13 +21,13 @@ startup:
 	JZ aligned
 
 	CRC32B (SI), AX
-	DECL CX
+	DECQ CX
 	INCQ SI
 	JMP startup
 
 aligned:
 	/* The input is now 8-byte aligned and we can process 8-byte chunks. */
-	CMPL CX, $8
+	CMPQ CX, $8
 	JL cleanup
 
 	CRC32Q (SI), AX
@@ -37,7 +37,7 @@ aligned:
 
 cleanup:
 	/* We may have some bytes left over that we process one at a time. */
-	CMPL CX, $0
+	CMPQ CX, $0
 	JE done
 
 	CRC32B (SI), AX
@@ -47,7 +47,7 @@ cleanup:
 
 done:
 	NOTL AX
-	MOVL AX, ret+24(FP)
+	MOVL AX, r+32(FP)
 	RET
 
 // func haveSSE42() bool
@@ -57,6 +57,6 @@ TEXT ·haveSSE42(SB),7,$0
 	CPUID
 	SHRQ $20, CX
 	ANDQ $1, CX
-	MOVB CX, ret+0(FP)
+	MOVB CX, r+0(FP)
 	RET
 
diff --git a/src/pkg/hash/crc32/crc32_test.go b/src/pkg/hash/crc32/crc32_test.go
index 7e82dd7..75dc26e 100644
--- a/src/pkg/hash/crc32/crc32_test.go
+++ b/src/pkg/hash/crc32/crc32_test.go
@@ -82,16 +82,18 @@ func TestGolden(t *testing.T) {
 }
 
 func BenchmarkCrc32KB(b *testing.B) {
-	b.StopTimer()
-	data := make([]uint8, 1024)
-	for i := 0; i < 1024; i++ {
-		data[i] = uint8(i)
+	b.SetBytes(1024)
+	data := make([]byte, 1024)
+	for i := range data {
+		data[i] = byte(i)
 	}
-	c := NewIEEE()
-	b.StartTimer()
-	b.SetBytes(int64(len(data)))
+	h := NewIEEE()
+	in := make([]byte, 0, h.Size())
 
+	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		c.Write(data)
+		h.Reset()
+		h.Write(data)
+		h.Sum(in)
 	}
 }
diff --git a/src/pkg/hash/crc64/crc64.go b/src/pkg/hash/crc64/crc64.go
index 5b64390..6925867 100644
--- a/src/pkg/hash/crc64/crc64.go
+++ b/src/pkg/hash/crc64/crc64.go
@@ -79,15 +79,7 @@ func (d *digest) Sum64() uint64 { return d.crc }
 
 func (d *digest) Sum(in []byte) []byte {
 	s := d.Sum64()
-	in = append(in, byte(s>>56))
-	in = append(in, byte(s>>48))
-	in = append(in, byte(s>>40))
-	in = append(in, byte(s>>32))
-	in = append(in, byte(s>>24))
-	in = append(in, byte(s>>16))
-	in = append(in, byte(s>>8))
-	in = append(in, byte(s))
-	return in
+	return append(in, byte(s>>56), byte(s>>48), byte(s>>40), byte(s>>32), byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
 }
 
 // Checksum returns the CRC-64 checksum of data
diff --git a/src/pkg/hash/crc64/crc64_test.go b/src/pkg/hash/crc64/crc64_test.go
index e932524..81a87b5 100644
--- a/src/pkg/hash/crc64/crc64_test.go
+++ b/src/pkg/hash/crc64/crc64_test.go
@@ -64,15 +64,18 @@ func TestGolden(t *testing.T) {
 }
 
 func BenchmarkCrc64KB(b *testing.B) {
-	b.StopTimer()
-	data := make([]uint8, 1024)
-	for i := 0; i < 1024; i++ {
-		data[i] = uint8(i)
+	b.SetBytes(1024)
+	data := make([]byte, 1024)
+	for i := range data {
+		data[i] = byte(i)
 	}
-	c := New(tab)
-	b.StartTimer()
+	h := New(tab)
+	in := make([]byte, 0, h.Size())
 
+	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		c.Write(data)
+		h.Reset()
+		h.Write(data)
+		h.Sum(in)
 	}
 }
diff --git a/src/pkg/hash/fnv/fnv.go b/src/pkg/hash/fnv/fnv.go
index ea50198..b5ecd4a 100644
--- a/src/pkg/hash/fnv/fnv.go
+++ b/src/pkg/hash/fnv/fnv.go
@@ -111,44 +111,20 @@ func (s *sum64a) BlockSize() int { return 1 }
 
 func (s *sum32) Sum(in []byte) []byte {
 	v := uint32(*s)
-	in = append(in, byte(v>>24))
-	in = append(in, byte(v>>16))
-	in = append(in, byte(v>>8))
-	in = append(in, byte(v))
-	return in
+	return append(in, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
 }
 
 func (s *sum32a) Sum(in []byte) []byte {
 	v := uint32(*s)
-	in = append(in, byte(v>>24))
-	in = append(in, byte(v>>16))
-	in = append(in, byte(v>>8))
-	in = append(in, byte(v))
-	return in
+	return append(in, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
 }
 
 func (s *sum64) Sum(in []byte) []byte {
 	v := uint64(*s)
-	in = append(in, byte(v>>56))
-	in = append(in, byte(v>>48))
-	in = append(in, byte(v>>40))
-	in = append(in, byte(v>>32))
-	in = append(in, byte(v>>24))
-	in = append(in, byte(v>>16))
-	in = append(in, byte(v>>8))
-	in = append(in, byte(v))
-	return in
+	return append(in, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
 }
 
 func (s *sum64a) Sum(in []byte) []byte {
 	v := uint64(*s)
-	in = append(in, byte(v>>56))
-	in = append(in, byte(v>>48))
-	in = append(in, byte(v>>40))
-	in = append(in, byte(v>>32))
-	in = append(in, byte(v>>24))
-	in = append(in, byte(v>>16))
-	in = append(in, byte(v>>8))
-	in = append(in, byte(v))
-	return in
+	return append(in, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
 }
diff --git a/src/pkg/hash/fnv/fnv_test.go b/src/pkg/hash/fnv/fnv_test.go
index 17454de..89d39b3 100644
--- a/src/pkg/hash/fnv/fnv_test.go
+++ b/src/pkg/hash/fnv/fnv_test.go
@@ -11,8 +11,6 @@ import (
 	"testing"
 )
 
-const testDataSize = 40
-
 type golden struct {
 	sum  []byte
 	text string
@@ -134,34 +132,34 @@ func testIntegrity(t *testing.T, h hash.Hash) {
 	}
 }
 
-func Benchmark32(b *testing.B) {
-	benchmark(b, New32())
+func BenchmarkFnv32KB(b *testing.B) {
+	benchmarkKB(b, New32())
 }
 
-func Benchmark32a(b *testing.B) {
-	benchmark(b, New32a())
+func BenchmarkFnv32aKB(b *testing.B) {
+	benchmarkKB(b, New32a())
 }
 
-func Benchmark64(b *testing.B) {
-	benchmark(b, New64())
+func BenchmarkFnv64KB(b *testing.B) {
+	benchmarkKB(b, New64())
 }
 
-func Benchmark64a(b *testing.B) {
-	benchmark(b, New64a())
+func BenchmarkFnv64aKB(b *testing.B) {
+	benchmarkKB(b, New64a())
 }
 
-func benchmark(b *testing.B, h hash.Hash) {
-	b.ResetTimer()
-	b.SetBytes(testDataSize)
-	data := make([]byte, testDataSize)
+func benchmarkKB(b *testing.B, h hash.Hash) {
+	b.SetBytes(1024)
+	data := make([]byte, 1024)
 	for i := range data {
-		data[i] = byte(i + 'a')
+		data[i] = byte(i)
 	}
+	in := make([]byte, 0, h.Size())
 
-	b.StartTimer()
-	for todo := b.N; todo != 0; todo-- {
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
 		h.Reset()
 		h.Write(data)
-		h.Sum(nil)
+		h.Sum(in)
 	}
 }
diff --git a/src/pkg/html/entity.go b/src/pkg/html/entity.go
index bd83075..af8a007 100644
--- a/src/pkg/html/entity.go
+++ b/src/pkg/html/entity.go
@@ -75,2083 +75,2083 @@ var entity = map[string]rune{
 	"Copf;":                            '\U00002102',
 	"Coproduct;":                       '\U00002210',
 	"CounterClockwiseContourIntegral;": '\U00002233',
-	"Cross;":                           '\U00002A2F',
-	"Cscr;":                            '\U0001D49E',
-	"Cup;":                             '\U000022D3',
-	"CupCap;":                          '\U0000224D',
-	"DD;":                              '\U00002145',
-	"DDotrahd;":                        '\U00002911',
-	"DJcy;":                            '\U00000402',
-	"DScy;":                            '\U00000405',
-	"DZcy;":                            '\U0000040F',
-	"Dagger;":                          '\U00002021',
-	"Darr;":                            '\U000021A1',
-	"Dashv;":                           '\U00002AE4',
-	"Dcaron;":                          '\U0000010E',
-	"Dcy;":                             '\U00000414',
-	"Del;":                             '\U00002207',
-	"Delta;":                           '\U00000394',
-	"Dfr;":                             '\U0001D507',
-	"DiacriticalAcute;":                '\U000000B4',
-	"DiacriticalDot;":                  '\U000002D9',
-	"DiacriticalDoubleAcute;":          '\U000002DD',
-	"DiacriticalGrave;":                '\U00000060',
-	"DiacriticalTilde;":                '\U000002DC',
-	"Diamond;":                         '\U000022C4',
-	"DifferentialD;":                   '\U00002146',
-	"Dopf;":                            '\U0001D53B',
-	"Dot;":                             '\U000000A8',
-	"DotDot;":                          '\U000020DC',
-	"DotEqual;":                        '\U00002250',
-	"DoubleContourIntegral;":           '\U0000222F',
-	"DoubleDot;":                       '\U000000A8',
-	"DoubleDownArrow;":                 '\U000021D3',
-	"DoubleLeftArrow;":                 '\U000021D0',
-	"DoubleLeftRightArrow;":            '\U000021D4',
-	"DoubleLeftTee;":                   '\U00002AE4',
-	"DoubleLongLeftArrow;":             '\U000027F8',
-	"DoubleLongLeftRightArrow;":        '\U000027FA',
-	"DoubleLongRightArrow;":            '\U000027F9',
-	"DoubleRightArrow;":                '\U000021D2',
-	"DoubleRightTee;":                  '\U000022A8',
-	"DoubleUpArrow;":                   '\U000021D1',
-	"DoubleUpDownArrow;":               '\U000021D5',
-	"DoubleVerticalBar;":               '\U00002225',
-	"DownArrow;":                       '\U00002193',
-	"DownArrowBar;":                    '\U00002913',
-	"DownArrowUpArrow;":                '\U000021F5',
-	"DownBreve;":                       '\U00000311',
-	"DownLeftRightVector;":             '\U00002950',
-	"DownLeftTeeVector;":               '\U0000295E',
-	"DownLeftVector;":                  '\U000021BD',
-	"DownLeftVectorBar;":               '\U00002956',
-	"DownRightTeeVector;":              '\U0000295F',
-	"DownRightVector;":                 '\U000021C1',
-	"DownRightVectorBar;":              '\U00002957',
-	"DownTee;":                         '\U000022A4',
-	"DownTeeArrow;":                    '\U000021A7',
-	"Downarrow;":                       '\U000021D3',
-	"Dscr;":                            '\U0001D49F',
-	"Dstrok;":                          '\U00000110',
-	"ENG;":                             '\U0000014A',
-	"ETH;":                             '\U000000D0',
-	"Eacute;":                          '\U000000C9',
-	"Ecaron;":                          '\U0000011A',
-	"Ecirc;":                           '\U000000CA',
-	"Ecy;":                             '\U0000042D',
-	"Edot;":                            '\U00000116',
-	"Efr;":                             '\U0001D508',
-	"Egrave;":                          '\U000000C8',
-	"Element;":                         '\U00002208',
-	"Emacr;":                           '\U00000112',
-	"EmptySmallSquare;":                '\U000025FB',
-	"EmptyVerySmallSquare;":            '\U000025AB',
-	"Eogon;":                           '\U00000118',
-	"Eopf;":                            '\U0001D53C',
-	"Epsilon;":                         '\U00000395',
-	"Equal;":                           '\U00002A75',
-	"EqualTilde;":                      '\U00002242',
-	"Equilibrium;":                     '\U000021CC',
-	"Escr;":                            '\U00002130',
-	"Esim;":                            '\U00002A73',
-	"Eta;":                             '\U00000397',
-	"Euml;":                            '\U000000CB',
-	"Exists;":                          '\U00002203',
-	"ExponentialE;":                    '\U00002147',
-	"Fcy;":                             '\U00000424',
-	"Ffr;":                             '\U0001D509',
-	"FilledSmallSquare;":               '\U000025FC',
-	"FilledVerySmallSquare;":           '\U000025AA',
-	"Fopf;":                            '\U0001D53D',
-	"ForAll;":                          '\U00002200',
-	"Fouriertrf;":                      '\U00002131',
-	"Fscr;":                            '\U00002131',
-	"GJcy;":                            '\U00000403',
-	"GT;":                              '\U0000003E',
-	"Gamma;":                           '\U00000393',
-	"Gammad;":                          '\U000003DC',
-	"Gbreve;":                          '\U0000011E',
-	"Gcedil;":                          '\U00000122',
-	"Gcirc;":                           '\U0000011C',
-	"Gcy;":                             '\U00000413',
-	"Gdot;":                            '\U00000120',
-	"Gfr;":                             '\U0001D50A',
-	"Gg;":                              '\U000022D9',
-	"Gopf;":                            '\U0001D53E',
-	"GreaterEqual;":                    '\U00002265',
-	"GreaterEqualLess;":                '\U000022DB',
-	"GreaterFullEqual;":                '\U00002267',
-	"GreaterGreater;":                  '\U00002AA2',
-	"GreaterLess;":                     '\U00002277',
-	"GreaterSlantEqual;":               '\U00002A7E',
-	"GreaterTilde;":                    '\U00002273',
-	"Gscr;":                            '\U0001D4A2',
-	"Gt;":                              '\U0000226B',
-	"HARDcy;":                          '\U0000042A',
-	"Hacek;":                           '\U000002C7',
-	"Hat;":                             '\U0000005E',
-	"Hcirc;":                           '\U00000124',
-	"Hfr;":                             '\U0000210C',
-	"HilbertSpace;":                    '\U0000210B',
-	"Hopf;":                            '\U0000210D',
-	"HorizontalLine;":                  '\U00002500',
-	"Hscr;":                            '\U0000210B',
-	"Hstrok;":                          '\U00000126',
-	"HumpDownHump;":                    '\U0000224E',
-	"HumpEqual;":                       '\U0000224F',
-	"IEcy;":                            '\U00000415',
-	"IJlig;":                           '\U00000132',
-	"IOcy;":                            '\U00000401',
-	"Iacute;":                          '\U000000CD',
-	"Icirc;":                           '\U000000CE',
-	"Icy;":                             '\U00000418',
-	"Idot;":                            '\U00000130',
-	"Ifr;":                             '\U00002111',
-	"Igrave;":                          '\U000000CC',
-	"Im;":                              '\U00002111',
-	"Imacr;":                           '\U0000012A',
-	"ImaginaryI;":                      '\U00002148',
-	"Implies;":                         '\U000021D2',
-	"Int;":                             '\U0000222C',
-	"Integral;":                        '\U0000222B',
-	"Intersection;":                    '\U000022C2',
-	"InvisibleComma;":                  '\U00002063',
-	"InvisibleTimes;":                  '\U00002062',
-	"Iogon;":                           '\U0000012E',
-	"Iopf;":                            '\U0001D540',
-	"Iota;":                            '\U00000399',
-	"Iscr;":                            '\U00002110',
-	"Itilde;":                          '\U00000128',
-	"Iukcy;":                           '\U00000406',
-	"Iuml;":                            '\U000000CF',
-	"Jcirc;":                           '\U00000134',
-	"Jcy;":                             '\U00000419',
-	"Jfr;":                             '\U0001D50D',
-	"Jopf;":                            '\U0001D541',
-	"Jscr;":                            '\U0001D4A5',
-	"Jsercy;":                          '\U00000408',
-	"Jukcy;":                           '\U00000404',
-	"KHcy;":                            '\U00000425',
-	"KJcy;":                            '\U0000040C',
-	"Kappa;":                           '\U0000039A',
-	"Kcedil;":                          '\U00000136',
-	"Kcy;":                             '\U0000041A',
-	"Kfr;":                             '\U0001D50E',
-	"Kopf;":                            '\U0001D542',
-	"Kscr;":                            '\U0001D4A6',
-	"LJcy;":                            '\U00000409',
-	"LT;":                              '\U0000003C',
-	"Lacute;":                          '\U00000139',
-	"Lambda;":                          '\U0000039B',
-	"Lang;":                            '\U000027EA',
-	"Laplacetrf;":                      '\U00002112',
-	"Larr;":                            '\U0000219E',
-	"Lcaron;":                          '\U0000013D',
-	"Lcedil;":                          '\U0000013B',
-	"Lcy;":                             '\U0000041B',
-	"LeftAngleBracket;":                '\U000027E8',
-	"LeftArrow;":                       '\U00002190',
-	"LeftArrowBar;":                    '\U000021E4',
-	"LeftArrowRightArrow;":             '\U000021C6',
-	"LeftCeiling;":                     '\U00002308',
-	"LeftDoubleBracket;":               '\U000027E6',
-	"LeftDownTeeVector;":               '\U00002961',
-	"LeftDownVector;":                  '\U000021C3',
-	"LeftDownVectorBar;":               '\U00002959',
-	"LeftFloor;":                       '\U0000230A',
-	"LeftRightArrow;":                  '\U00002194',
-	"LeftRightVector;":                 '\U0000294E',
-	"LeftTee;":                         '\U000022A3',
-	"LeftTeeArrow;":                    '\U000021A4',
-	"LeftTeeVector;":                   '\U0000295A',
-	"LeftTriangle;":                    '\U000022B2',
-	"LeftTriangleBar;":                 '\U000029CF',
-	"LeftTriangleEqual;":               '\U000022B4',
-	"LeftUpDownVector;":                '\U00002951',
-	"LeftUpTeeVector;":                 '\U00002960',
-	"LeftUpVector;":                    '\U000021BF',
-	"LeftUpVectorBar;":                 '\U00002958',
-	"LeftVector;":                      '\U000021BC',
-	"LeftVectorBar;":                   '\U00002952',
-	"Leftarrow;":                       '\U000021D0',
-	"Leftrightarrow;":                  '\U000021D4',
-	"LessEqualGreater;":                '\U000022DA',
-	"LessFullEqual;":                   '\U00002266',
-	"LessGreater;":                     '\U00002276',
-	"LessLess;":                        '\U00002AA1',
-	"LessSlantEqual;":                  '\U00002A7D',
-	"LessTilde;":                       '\U00002272',
-	"Lfr;":                             '\U0001D50F',
-	"Ll;":                              '\U000022D8',
-	"Lleftarrow;":                      '\U000021DA',
-	"Lmidot;":                          '\U0000013F',
-	"LongLeftArrow;":                   '\U000027F5',
-	"LongLeftRightArrow;":              '\U000027F7',
-	"LongRightArrow;":                  '\U000027F6',
-	"Longleftarrow;":                   '\U000027F8',
-	"Longleftrightarrow;":              '\U000027FA',
-	"Longrightarrow;":                  '\U000027F9',
-	"Lopf;":                            '\U0001D543',
-	"LowerLeftArrow;":                  '\U00002199',
-	"LowerRightArrow;":                 '\U00002198',
-	"Lscr;":                            '\U00002112',
-	"Lsh;":                             '\U000021B0',
-	"Lstrok;":                          '\U00000141',
-	"Lt;":                              '\U0000226A',
-	"Map;":                             '\U00002905',
-	"Mcy;":                             '\U0000041C',
-	"MediumSpace;":                     '\U0000205F',
-	"Mellintrf;":                       '\U00002133',
-	"Mfr;":                             '\U0001D510',
-	"MinusPlus;":                       '\U00002213',
-	"Mopf;":                            '\U0001D544',
-	"Mscr;":                            '\U00002133',
-	"Mu;":                              '\U0000039C',
-	"NJcy;":                            '\U0000040A',
-	"Nacute;":                          '\U00000143',
-	"Ncaron;":                          '\U00000147',
-	"Ncedil;":                          '\U00000145',
-	"Ncy;":                             '\U0000041D',
-	"NegativeMediumSpace;":             '\U0000200B',
-	"NegativeThickSpace;":              '\U0000200B',
-	"NegativeThinSpace;":               '\U0000200B',
-	"NegativeVeryThinSpace;":           '\U0000200B',
-	"NestedGreaterGreater;":            '\U0000226B',
-	"NestedLessLess;":                  '\U0000226A',
-	"NewLine;":                         '\U0000000A',
-	"Nfr;":                             '\U0001D511',
-	"NoBreak;":                         '\U00002060',
-	"NonBreakingSpace;":                '\U000000A0',
-	"Nopf;":                            '\U00002115',
-	"Not;":                             '\U00002AEC',
-	"NotCongruent;":                    '\U00002262',
-	"NotCupCap;":                       '\U0000226D',
-	"NotDoubleVerticalBar;":            '\U00002226',
-	"NotElement;":                      '\U00002209',
-	"NotEqual;":                        '\U00002260',
-	"NotExists;":                       '\U00002204',
-	"NotGreater;":                      '\U0000226F',
-	"NotGreaterEqual;":                 '\U00002271',
-	"NotGreaterLess;":                  '\U00002279',
-	"NotGreaterTilde;":                 '\U00002275',
-	"NotLeftTriangle;":                 '\U000022EA',
-	"NotLeftTriangleEqual;":            '\U000022EC',
-	"NotLess;":                         '\U0000226E',
-	"NotLessEqual;":                    '\U00002270',
-	"NotLessGreater;":                  '\U00002278',
-	"NotLessTilde;":                    '\U00002274',
-	"NotPrecedes;":                     '\U00002280',
-	"NotPrecedesSlantEqual;":           '\U000022E0',
-	"NotReverseElement;":               '\U0000220C',
-	"NotRightTriangle;":                '\U000022EB',
-	"NotRightTriangleEqual;":           '\U000022ED',
-	"NotSquareSubsetEqual;":            '\U000022E2',
-	"NotSquareSupersetEqual;":          '\U000022E3',
-	"NotSubsetEqual;":                  '\U00002288',
-	"NotSucceeds;":                     '\U00002281',
-	"NotSucceedsSlantEqual;":           '\U000022E1',
-	"NotSupersetEqual;":                '\U00002289',
-	"NotTilde;":                        '\U00002241',
-	"NotTildeEqual;":                   '\U00002244',
-	"NotTildeFullEqual;":               '\U00002247',
-	"NotTildeTilde;":                   '\U00002249',
-	"NotVerticalBar;":                  '\U00002224',
-	"Nscr;":                            '\U0001D4A9',
-	"Ntilde;":                          '\U000000D1',
-	"Nu;":                              '\U0000039D',
-	"OElig;":                           '\U00000152',
-	"Oacute;":                          '\U000000D3',
-	"Ocirc;":                           '\U000000D4',
-	"Ocy;":                             '\U0000041E',
-	"Odblac;":                          '\U00000150',
-	"Ofr;":                             '\U0001D512',
-	"Ograve;":                          '\U000000D2',
-	"Omacr;":                           '\U0000014C',
-	"Omega;":                           '\U000003A9',
-	"Omicron;":                         '\U0000039F',
-	"Oopf;":                            '\U0001D546',
-	"OpenCurlyDoubleQuote;":            '\U0000201C',
-	"OpenCurlyQuote;":                  '\U00002018',
-	"Or;":                              '\U00002A54',
-	"Oscr;":                            '\U0001D4AA',
-	"Oslash;":                          '\U000000D8',
-	"Otilde;":                          '\U000000D5',
-	"Otimes;":                          '\U00002A37',
-	"Ouml;":                            '\U000000D6',
-	"OverBar;":                         '\U0000203E',
-	"OverBrace;":                       '\U000023DE',
-	"OverBracket;":                     '\U000023B4',
-	"OverParenthesis;":                 '\U000023DC',
-	"PartialD;":                        '\U00002202',
-	"Pcy;":                             '\U0000041F',
-	"Pfr;":                             '\U0001D513',
-	"Phi;":                             '\U000003A6',
-	"Pi;":                              '\U000003A0',
-	"PlusMinus;":                       '\U000000B1',
-	"Poincareplane;":                   '\U0000210C',
-	"Popf;":                            '\U00002119',
-	"Pr;":                              '\U00002ABB',
-	"Precedes;":                        '\U0000227A',
-	"PrecedesEqual;":                   '\U00002AAF',
-	"PrecedesSlantEqual;":              '\U0000227C',
-	"PrecedesTilde;":                   '\U0000227E',
-	"Prime;":                           '\U00002033',
-	"Product;":                         '\U0000220F',
-	"Proportion;":                      '\U00002237',
-	"Proportional;":                    '\U0000221D',
-	"Pscr;":                            '\U0001D4AB',
-	"Psi;":                             '\U000003A8',
-	"QUOT;":                            '\U00000022',
-	"Qfr;":                             '\U0001D514',
-	"Qopf;":                            '\U0000211A',
-	"Qscr;":                            '\U0001D4AC',
-	"RBarr;":                           '\U00002910',
-	"REG;":                             '\U000000AE',
-	"Racute;":                          '\U00000154',
-	"Rang;":                            '\U000027EB',
-	"Rarr;":                            '\U000021A0',
-	"Rarrtl;":                          '\U00002916',
-	"Rcaron;":                          '\U00000158',
-	"Rcedil;":                          '\U00000156',
-	"Rcy;":                             '\U00000420',
-	"Re;":                              '\U0000211C',
-	"ReverseElement;":                  '\U0000220B',
-	"ReverseEquilibrium;":              '\U000021CB',
-	"ReverseUpEquilibrium;":            '\U0000296F',
-	"Rfr;":                             '\U0000211C',
-	"Rho;":                             '\U000003A1',
-	"RightAngleBracket;":               '\U000027E9',
-	"RightArrow;":                      '\U00002192',
-	"RightArrowBar;":                   '\U000021E5',
-	"RightArrowLeftArrow;":             '\U000021C4',
-	"RightCeiling;":                    '\U00002309',
-	"RightDoubleBracket;":              '\U000027E7',
-	"RightDownTeeVector;":              '\U0000295D',
-	"RightDownVector;":                 '\U000021C2',
-	"RightDownVectorBar;":              '\U00002955',
-	"RightFloor;":                      '\U0000230B',
-	"RightTee;":                        '\U000022A2',
-	"RightTeeArrow;":                   '\U000021A6',
-	"RightTeeVector;":                  '\U0000295B',
-	"RightTriangle;":                   '\U000022B3',
-	"RightTriangleBar;":                '\U000029D0',
-	"RightTriangleEqual;":              '\U000022B5',
-	"RightUpDownVector;":               '\U0000294F',
-	"RightUpTeeVector;":                '\U0000295C',
-	"RightUpVector;":                   '\U000021BE',
-	"RightUpVectorBar;":                '\U00002954',
-	"RightVector;":                     '\U000021C0',
-	"RightVectorBar;":                  '\U00002953',
-	"Rightarrow;":                      '\U000021D2',
-	"Ropf;":                            '\U0000211D',
-	"RoundImplies;":                    '\U00002970',
-	"Rrightarrow;":                     '\U000021DB',
-	"Rscr;":                            '\U0000211B',
-	"Rsh;":                             '\U000021B1',
-	"RuleDelayed;":                     '\U000029F4',
-	"SHCHcy;":                          '\U00000429',
-	"SHcy;":                            '\U00000428',
-	"SOFTcy;":                          '\U0000042C',
-	"Sacute;":                          '\U0000015A',
-	"Sc;":                              '\U00002ABC',
-	"Scaron;":                          '\U00000160',
-	"Scedil;":                          '\U0000015E',
-	"Scirc;":                           '\U0000015C',
-	"Scy;":                             '\U00000421',
-	"Sfr;":                             '\U0001D516',
-	"ShortDownArrow;":                  '\U00002193',
-	"ShortLeftArrow;":                  '\U00002190',
-	"ShortRightArrow;":                 '\U00002192',
-	"ShortUpArrow;":                    '\U00002191',
-	"Sigma;":                           '\U000003A3',
-	"SmallCircle;":                     '\U00002218',
-	"Sopf;":                            '\U0001D54A',
-	"Sqrt;":                            '\U0000221A',
-	"Square;":                          '\U000025A1',
-	"SquareIntersection;":              '\U00002293',
-	"SquareSubset;":                    '\U0000228F',
-	"SquareSubsetEqual;":               '\U00002291',
-	"SquareSuperset;":                  '\U00002290',
-	"SquareSupersetEqual;":             '\U00002292',
-	"SquareUnion;":                     '\U00002294',
-	"Sscr;":                            '\U0001D4AE',
-	"Star;":                            '\U000022C6',
-	"Sub;":                             '\U000022D0',
-	"Subset;":                          '\U000022D0',
-	"SubsetEqual;":                     '\U00002286',
-	"Succeeds;":                        '\U0000227B',
-	"SucceedsEqual;":                   '\U00002AB0',
-	"SucceedsSlantEqual;":              '\U0000227D',
-	"SucceedsTilde;":                   '\U0000227F',
-	"SuchThat;":                        '\U0000220B',
-	"Sum;":                             '\U00002211',
-	"Sup;":                             '\U000022D1',
-	"Superset;":                        '\U00002283',
-	"SupersetEqual;":                   '\U00002287',
-	"Supset;":                          '\U000022D1',
-	"THORN;":                           '\U000000DE',
-	"TRADE;":                           '\U00002122',
-	"TSHcy;":                           '\U0000040B',
-	"TScy;":                            '\U00000426',
-	"Tab;":                             '\U00000009',
-	"Tau;":                             '\U000003A4',
-	"Tcaron;":                          '\U00000164',
-	"Tcedil;":                          '\U00000162',
-	"Tcy;":                             '\U00000422',
-	"Tfr;":                             '\U0001D517',
-	"Therefore;":                       '\U00002234',
-	"Theta;":                           '\U00000398',
-	"ThinSpace;":                       '\U00002009',
-	"Tilde;":                           '\U0000223C',
-	"TildeEqual;":                      '\U00002243',
-	"TildeFullEqual;":                  '\U00002245',
-	"TildeTilde;":                      '\U00002248',
-	"Topf;":                            '\U0001D54B',
-	"TripleDot;":                       '\U000020DB',
-	"Tscr;":                            '\U0001D4AF',
-	"Tstrok;":                          '\U00000166',
-	"Uacute;":                          '\U000000DA',
-	"Uarr;":                            '\U0000219F',
-	"Uarrocir;":                        '\U00002949',
-	"Ubrcy;":                           '\U0000040E',
-	"Ubreve;":                          '\U0000016C',
-	"Ucirc;":                           '\U000000DB',
-	"Ucy;":                             '\U00000423',
-	"Udblac;":                          '\U00000170',
-	"Ufr;":                             '\U0001D518',
-	"Ugrave;":                          '\U000000D9',
-	"Umacr;":                           '\U0000016A',
-	"UnderBar;":                        '\U0000005F',
-	"UnderBrace;":                      '\U000023DF',
-	"UnderBracket;":                    '\U000023B5',
-	"UnderParenthesis;":                '\U000023DD',
-	"Union;":                           '\U000022C3',
-	"UnionPlus;":                       '\U0000228E',
-	"Uogon;":                           '\U00000172',
-	"Uopf;":                            '\U0001D54C',
-	"UpArrow;":                         '\U00002191',
-	"UpArrowBar;":                      '\U00002912',
-	"UpArrowDownArrow;":                '\U000021C5',
-	"UpDownArrow;":                     '\U00002195',
-	"UpEquilibrium;":                   '\U0000296E',
-	"UpTee;":                           '\U000022A5',
-	"UpTeeArrow;":                      '\U000021A5',
-	"Uparrow;":                         '\U000021D1',
-	"Updownarrow;":                     '\U000021D5',
-	"UpperLeftArrow;":                  '\U00002196',
-	"UpperRightArrow;":                 '\U00002197',
-	"Upsi;":                            '\U000003D2',
-	"Upsilon;":                         '\U000003A5',
-	"Uring;":                           '\U0000016E',
-	"Uscr;":                            '\U0001D4B0',
-	"Utilde;":                          '\U00000168',
-	"Uuml;":                            '\U000000DC',
-	"VDash;":                           '\U000022AB',
-	"Vbar;":                            '\U00002AEB',
-	"Vcy;":                             '\U00000412',
-	"Vdash;":                           '\U000022A9',
-	"Vdashl;":                          '\U00002AE6',
-	"Vee;":                             '\U000022C1',
-	"Verbar;":                          '\U00002016',
-	"Vert;":                            '\U00002016',
-	"VerticalBar;":                     '\U00002223',
-	"VerticalLine;":                    '\U0000007C',
-	"VerticalSeparator;":               '\U00002758',
-	"VerticalTilde;":                   '\U00002240',
-	"VeryThinSpace;":                   '\U0000200A',
-	"Vfr;":                             '\U0001D519',
-	"Vopf;":                            '\U0001D54D',
-	"Vscr;":                            '\U0001D4B1',
-	"Vvdash;":                          '\U000022AA',
-	"Wcirc;":                           '\U00000174',
-	"Wedge;":                           '\U000022C0',
-	"Wfr;":                             '\U0001D51A',
-	"Wopf;":                            '\U0001D54E',
-	"Wscr;":                            '\U0001D4B2',
-	"Xfr;":                             '\U0001D51B',
-	"Xi;":                              '\U0000039E',
-	"Xopf;":                            '\U0001D54F',
-	"Xscr;":                            '\U0001D4B3',
-	"YAcy;":                            '\U0000042F',
-	"YIcy;":                            '\U00000407',
-	"YUcy;":                            '\U0000042E',
-	"Yacute;":                          '\U000000DD',
-	"Ycirc;":                           '\U00000176',
-	"Ycy;":                             '\U0000042B',
-	"Yfr;":                             '\U0001D51C',
-	"Yopf;":                            '\U0001D550',
-	"Yscr;":                            '\U0001D4B4',
-	"Yuml;":                            '\U00000178',
-	"ZHcy;":                            '\U00000416',
-	"Zacute;":                          '\U00000179',
-	"Zcaron;":                          '\U0000017D',
-	"Zcy;":                             '\U00000417',
-	"Zdot;":                            '\U0000017B',
-	"ZeroWidthSpace;":                  '\U0000200B',
-	"Zeta;":                            '\U00000396',
-	"Zfr;":                             '\U00002128',
-	"Zopf;":                            '\U00002124',
-	"Zscr;":                            '\U0001D4B5',
-	"aacute;":                          '\U000000E1',
-	"abreve;":                          '\U00000103',
-	"ac;":                              '\U0000223E',
-	"acd;":                             '\U0000223F',
-	"acirc;":                           '\U000000E2',
-	"acute;":                           '\U000000B4',
-	"acy;":                             '\U00000430',
-	"aelig;":                           '\U000000E6',
-	"af;":                              '\U00002061',
-	"afr;":                             '\U0001D51E',
-	"agrave;":                          '\U000000E0',
-	"alefsym;":                         '\U00002135',
-	"aleph;":                           '\U00002135',
-	"alpha;":                           '\U000003B1',
-	"amacr;":                           '\U00000101',
-	"amalg;":                           '\U00002A3F',
-	"amp;":                             '\U00000026',
-	"and;":                             '\U00002227',
-	"andand;":                          '\U00002A55',
-	"andd;":                            '\U00002A5C',
-	"andslope;":                        '\U00002A58',
-	"andv;":                            '\U00002A5A',
-	"ang;":                             '\U00002220',
-	"ange;":                            '\U000029A4',
-	"angle;":                           '\U00002220',
-	"angmsd;":                          '\U00002221',
-	"angmsdaa;":                        '\U000029A8',
-	"angmsdab;":                        '\U000029A9',
-	"angmsdac;":                        '\U000029AA',
-	"angmsdad;":                        '\U000029AB',
-	"angmsdae;":                        '\U000029AC',
-	"angmsdaf;":                        '\U000029AD',
-	"angmsdag;":                        '\U000029AE',
-	"angmsdah;":                        '\U000029AF',
-	"angrt;":                           '\U0000221F',
-	"angrtvb;":                         '\U000022BE',
-	"angrtvbd;":                        '\U0000299D',
-	"angsph;":                          '\U00002222',
-	"angst;":                           '\U000000C5',
-	"angzarr;":                         '\U0000237C',
-	"aogon;":                           '\U00000105',
-	"aopf;":                            '\U0001D552',
-	"ap;":                              '\U00002248',
-	"apE;":                             '\U00002A70',
-	"apacir;":                          '\U00002A6F',
-	"ape;":                             '\U0000224A',
-	"apid;":                            '\U0000224B',
-	"apos;":                            '\U00000027',
-	"approx;":                          '\U00002248',
-	"approxeq;":                        '\U0000224A',
-	"aring;":                           '\U000000E5',
-	"ascr;":                            '\U0001D4B6',
-	"ast;":                             '\U0000002A',
-	"asymp;":                           '\U00002248',
-	"asympeq;":                         '\U0000224D',
-	"atilde;":                          '\U000000E3',
-	"auml;":                            '\U000000E4',
-	"awconint;":                        '\U00002233',
-	"awint;":                           '\U00002A11',
-	"bNot;":                            '\U00002AED',
-	"backcong;":                        '\U0000224C',
-	"backepsilon;":                     '\U000003F6',
-	"backprime;":                       '\U00002035',
-	"backsim;":                         '\U0000223D',
-	"backsimeq;":                       '\U000022CD',
-	"barvee;":                          '\U000022BD',
-	"barwed;":                          '\U00002305',
-	"barwedge;":                        '\U00002305',
-	"bbrk;":                            '\U000023B5',
-	"bbrktbrk;":                        '\U000023B6',
-	"bcong;":                           '\U0000224C',
-	"bcy;":                             '\U00000431',
-	"bdquo;":                           '\U0000201E',
-	"becaus;":                          '\U00002235',
-	"because;":                         '\U00002235',
-	"bemptyv;":                         '\U000029B0',
-	"bepsi;":                           '\U000003F6',
-	"bernou;":                          '\U0000212C',
-	"beta;":                            '\U000003B2',
-	"beth;":                            '\U00002136',
-	"between;":                         '\U0000226C',
-	"bfr;":                             '\U0001D51F',
-	"bigcap;":                          '\U000022C2',
-	"bigcirc;":                         '\U000025EF',
-	"bigcup;":                          '\U000022C3',
-	"bigodot;":                         '\U00002A00',
-	"bigoplus;":                        '\U00002A01',
-	"bigotimes;":                       '\U00002A02',
-	"bigsqcup;":                        '\U00002A06',
-	"bigstar;":                         '\U00002605',
-	"bigtriangledown;":                 '\U000025BD',
-	"bigtriangleup;":                   '\U000025B3',
-	"biguplus;":                        '\U00002A04',
-	"bigvee;":                          '\U000022C1',
-	"bigwedge;":                        '\U000022C0',
-	"bkarow;":                          '\U0000290D',
-	"blacklozenge;":                    '\U000029EB',
-	"blacksquare;":                     '\U000025AA',
-	"blacktriangle;":                   '\U000025B4',
-	"blacktriangledown;":               '\U000025BE',
-	"blacktriangleleft;":               '\U000025C2',
-	"blacktriangleright;":              '\U000025B8',
-	"blank;":                           '\U00002423',
-	"blk12;":                           '\U00002592',
-	"blk14;":                           '\U00002591',
-	"blk34;":                           '\U00002593',
-	"block;":                           '\U00002588',
-	"bnot;":                            '\U00002310',
-	"bopf;":                            '\U0001D553',
-	"bot;":                             '\U000022A5',
-	"bottom;":                          '\U000022A5',
-	"bowtie;":                          '\U000022C8',
-	"boxDL;":                           '\U00002557',
-	"boxDR;":                           '\U00002554',
-	"boxDl;":                           '\U00002556',
-	"boxDr;":                           '\U00002553',
-	"boxH;":                            '\U00002550',
-	"boxHD;":                           '\U00002566',
-	"boxHU;":                           '\U00002569',
-	"boxHd;":                           '\U00002564',
-	"boxHu;":                           '\U00002567',
-	"boxUL;":                           '\U0000255D',
-	"boxUR;":                           '\U0000255A',
-	"boxUl;":                           '\U0000255C',
-	"boxUr;":                           '\U00002559',
-	"boxV;":                            '\U00002551',
-	"boxVH;":                           '\U0000256C',
-	"boxVL;":                           '\U00002563',
-	"boxVR;":                           '\U00002560',
-	"boxVh;":                           '\U0000256B',
-	"boxVl;":                           '\U00002562',
-	"boxVr;":                           '\U0000255F',
-	"boxbox;":                          '\U000029C9',
-	"boxdL;":                           '\U00002555',
-	"boxdR;":                           '\U00002552',
-	"boxdl;":                           '\U00002510',
-	"boxdr;":                           '\U0000250C',
-	"boxh;":                            '\U00002500',
-	"boxhD;":                           '\U00002565',
-	"boxhU;":                           '\U00002568',
-	"boxhd;":                           '\U0000252C',
-	"boxhu;":                           '\U00002534',
-	"boxminus;":                        '\U0000229F',
-	"boxplus;":                         '\U0000229E',
-	"boxtimes;":                        '\U000022A0',
-	"boxuL;":                           '\U0000255B',
-	"boxuR;":                           '\U00002558',
-	"boxul;":                           '\U00002518',
-	"boxur;":                           '\U00002514',
-	"boxv;":                            '\U00002502',
-	"boxvH;":                           '\U0000256A',
-	"boxvL;":                           '\U00002561',
-	"boxvR;":                           '\U0000255E',
-	"boxvh;":                           '\U0000253C',
-	"boxvl;":                           '\U00002524',
-	"boxvr;":                           '\U0000251C',
-	"bprime;":                          '\U00002035',
-	"breve;":                           '\U000002D8',
-	"brvbar;":                          '\U000000A6',
-	"bscr;":                            '\U0001D4B7',
-	"bsemi;":                           '\U0000204F',
-	"bsim;":                            '\U0000223D',
-	"bsime;":                           '\U000022CD',
-	"bsol;":                            '\U0000005C',
-	"bsolb;":                           '\U000029C5',
-	"bsolhsub;":                        '\U000027C8',
-	"bull;":                            '\U00002022',
-	"bullet;":                          '\U00002022',
-	"bump;":                            '\U0000224E',
-	"bumpE;":                           '\U00002AAE',
-	"bumpe;":                           '\U0000224F',
-	"bumpeq;":                          '\U0000224F',
-	"cacute;":                          '\U00000107',
-	"cap;":                             '\U00002229',
-	"capand;":                          '\U00002A44',
-	"capbrcup;":                        '\U00002A49',
-	"capcap;":                          '\U00002A4B',
-	"capcup;":                          '\U00002A47',
-	"capdot;":                          '\U00002A40',
-	"caret;":                           '\U00002041',
-	"caron;":                           '\U000002C7',
-	"ccaps;":                           '\U00002A4D',
-	"ccaron;":                          '\U0000010D',
-	"ccedil;":                          '\U000000E7',
-	"ccirc;":                           '\U00000109',
-	"ccups;":                           '\U00002A4C',
-	"ccupssm;":                         '\U00002A50',
-	"cdot;":                            '\U0000010B',
-	"cedil;":                           '\U000000B8',
-	"cemptyv;":                         '\U000029B2',
-	"cent;":                            '\U000000A2',
-	"centerdot;":                       '\U000000B7',
-	"cfr;":                             '\U0001D520',
-	"chcy;":                            '\U00000447',
-	"check;":                           '\U00002713',
-	"checkmark;":                       '\U00002713',
-	"chi;":                             '\U000003C7',
-	"cir;":                             '\U000025CB',
-	"cirE;":                            '\U000029C3',
-	"circ;":                            '\U000002C6',
-	"circeq;":                          '\U00002257',
-	"circlearrowleft;":                 '\U000021BA',
-	"circlearrowright;":                '\U000021BB',
-	"circledR;":                        '\U000000AE',
-	"circledS;":                        '\U000024C8',
-	"circledast;":                      '\U0000229B',
-	"circledcirc;":                     '\U0000229A',
-	"circleddash;":                     '\U0000229D',
-	"cire;":                            '\U00002257',
-	"cirfnint;":                        '\U00002A10',
-	"cirmid;":                          '\U00002AEF',
-	"cirscir;":                         '\U000029C2',
-	"clubs;":                           '\U00002663',
-	"clubsuit;":                        '\U00002663',
-	"colon;":                           '\U0000003A',
-	"colone;":                          '\U00002254',
-	"coloneq;":                         '\U00002254',
-	"comma;":                           '\U0000002C',
-	"commat;":                          '\U00000040',
-	"comp;":                            '\U00002201',
-	"compfn;":                          '\U00002218',
-	"complement;":                      '\U00002201',
-	"complexes;":                       '\U00002102',
-	"cong;":                            '\U00002245',
-	"congdot;":                         '\U00002A6D',
-	"conint;":                          '\U0000222E',
-	"copf;":                            '\U0001D554',
-	"coprod;":                          '\U00002210',
-	"copy;":                            '\U000000A9',
-	"copysr;":                          '\U00002117',
-	"crarr;":                           '\U000021B5',
-	"cross;":                           '\U00002717',
-	"cscr;":                            '\U0001D4B8',
-	"csub;":                            '\U00002ACF',
-	"csube;":                           '\U00002AD1',
-	"csup;":                            '\U00002AD0',
-	"csupe;":                           '\U00002AD2',
-	"ctdot;":                           '\U000022EF',
-	"cudarrl;":                         '\U00002938',
-	"cudarrr;":                         '\U00002935',
-	"cuepr;":                           '\U000022DE',
-	"cuesc;":                           '\U000022DF',
-	"cularr;":                          '\U000021B6',
-	"cularrp;":                         '\U0000293D',
-	"cup;":                             '\U0000222A',
-	"cupbrcap;":                        '\U00002A48',
-	"cupcap;":                          '\U00002A46',
-	"cupcup;":                          '\U00002A4A',
-	"cupdot;":                          '\U0000228D',
-	"cupor;":                           '\U00002A45',
-	"curarr;":                          '\U000021B7',
-	"curarrm;":                         '\U0000293C',
-	"curlyeqprec;":                     '\U000022DE',
-	"curlyeqsucc;":                     '\U000022DF',
-	"curlyvee;":                        '\U000022CE',
-	"curlywedge;":                      '\U000022CF',
-	"curren;":                          '\U000000A4',
-	"curvearrowleft;":                  '\U000021B6',
-	"curvearrowright;":                 '\U000021B7',
-	"cuvee;":                           '\U000022CE',
-	"cuwed;":                           '\U000022CF',
-	"cwconint;":                        '\U00002232',
-	"cwint;":                           '\U00002231',
-	"cylcty;":                          '\U0000232D',
-	"dArr;":                            '\U000021D3',
-	"dHar;":                            '\U00002965',
-	"dagger;":                          '\U00002020',
-	"daleth;":                          '\U00002138',
-	"darr;":                            '\U00002193',
-	"dash;":                            '\U00002010',
-	"dashv;":                           '\U000022A3',
-	"dbkarow;":                         '\U0000290F',
-	"dblac;":                           '\U000002DD',
-	"dcaron;":                          '\U0000010F',
-	"dcy;":                             '\U00000434',
-	"dd;":                              '\U00002146',
-	"ddagger;":                         '\U00002021',
-	"ddarr;":                           '\U000021CA',
-	"ddotseq;":                         '\U00002A77',
-	"deg;":                             '\U000000B0',
-	"delta;":                           '\U000003B4',
-	"demptyv;":                         '\U000029B1',
-	"dfisht;":                          '\U0000297F',
-	"dfr;":                             '\U0001D521',
-	"dharl;":                           '\U000021C3',
-	"dharr;":                           '\U000021C2',
-	"diam;":                            '\U000022C4',
-	"diamond;":                         '\U000022C4',
-	"diamondsuit;":                     '\U00002666',
-	"diams;":                           '\U00002666',
-	"die;":                             '\U000000A8',
-	"digamma;":                         '\U000003DD',
-	"disin;":                           '\U000022F2',
-	"div;":                             '\U000000F7',
-	"divide;":                          '\U000000F7',
-	"divideontimes;":                   '\U000022C7',
-	"divonx;":                          '\U000022C7',
-	"djcy;":                            '\U00000452',
-	"dlcorn;":                          '\U0000231E',
-	"dlcrop;":                          '\U0000230D',
-	"dollar;":                          '\U00000024',
-	"dopf;":                            '\U0001D555',
-	"dot;":                             '\U000002D9',
-	"doteq;":                           '\U00002250',
-	"doteqdot;":                        '\U00002251',
-	"dotminus;":                        '\U00002238',
-	"dotplus;":                         '\U00002214',
-	"dotsquare;":                       '\U000022A1',
-	"doublebarwedge;":                  '\U00002306',
-	"downarrow;":                       '\U00002193',
-	"downdownarrows;":                  '\U000021CA',
-	"downharpoonleft;":                 '\U000021C3',
-	"downharpoonright;":                '\U000021C2',
-	"drbkarow;":                        '\U00002910',
-	"drcorn;":                          '\U0000231F',
-	"drcrop;":                          '\U0000230C',
-	"dscr;":                            '\U0001D4B9',
-	"dscy;":                            '\U00000455',
-	"dsol;":                            '\U000029F6',
-	"dstrok;":                          '\U00000111',
-	"dtdot;":                           '\U000022F1',
-	"dtri;":                            '\U000025BF',
-	"dtrif;":                           '\U000025BE',
-	"duarr;":                           '\U000021F5',
-	"duhar;":                           '\U0000296F',
-	"dwangle;":                         '\U000029A6',
-	"dzcy;":                            '\U0000045F',
-	"dzigrarr;":                        '\U000027FF',
-	"eDDot;":                           '\U00002A77',
-	"eDot;":                            '\U00002251',
-	"eacute;":                          '\U000000E9',
-	"easter;":                          '\U00002A6E',
-	"ecaron;":                          '\U0000011B',
-	"ecir;":                            '\U00002256',
-	"ecirc;":                           '\U000000EA',
-	"ecolon;":                          '\U00002255',
-	"ecy;":                             '\U0000044D',
-	"edot;":                            '\U00000117',
-	"ee;":                              '\U00002147',
-	"efDot;":                           '\U00002252',
-	"efr;":                             '\U0001D522',
-	"eg;":                              '\U00002A9A',
-	"egrave;":                          '\U000000E8',
-	"egs;":                             '\U00002A96',
-	"egsdot;":                          '\U00002A98',
-	"el;":                              '\U00002A99',
-	"elinters;":                        '\U000023E7',
-	"ell;":                             '\U00002113',
-	"els;":                             '\U00002A95',
-	"elsdot;":                          '\U00002A97',
-	"emacr;":                           '\U00000113',
-	"empty;":                           '\U00002205',
-	"emptyset;":                        '\U00002205',
-	"emptyv;":                          '\U00002205',
-	"emsp;":                            '\U00002003',
-	"emsp13;":                          '\U00002004',
-	"emsp14;":                          '\U00002005',
-	"eng;":                             '\U0000014B',
-	"ensp;":                            '\U00002002',
-	"eogon;":                           '\U00000119',
-	"eopf;":                            '\U0001D556',
-	"epar;":                            '\U000022D5',
-	"eparsl;":                          '\U000029E3',
-	"eplus;":                           '\U00002A71',
-	"epsi;":                            '\U000003B5',
-	"epsilon;":                         '\U000003B5',
-	"epsiv;":                           '\U000003F5',
-	"eqcirc;":                          '\U00002256',
-	"eqcolon;":                         '\U00002255',
-	"eqsim;":                           '\U00002242',
-	"eqslantgtr;":                      '\U00002A96',
-	"eqslantless;":                     '\U00002A95',
-	"equals;":                          '\U0000003D',
-	"equest;":                          '\U0000225F',
-	"equiv;":                           '\U00002261',
-	"equivDD;":                         '\U00002A78',
-	"eqvparsl;":                        '\U000029E5',
-	"erDot;":                           '\U00002253',
-	"erarr;":                           '\U00002971',
-	"escr;":                            '\U0000212F',
-	"esdot;":                           '\U00002250',
-	"esim;":                            '\U00002242',
-	"eta;":                             '\U000003B7',
-	"eth;":                             '\U000000F0',
-	"euml;":                            '\U000000EB',
-	"euro;":                            '\U000020AC',
-	"excl;":                            '\U00000021',
-	"exist;":                           '\U00002203',
-	"expectation;":                     '\U00002130',
-	"exponentiale;":                    '\U00002147',
-	"fallingdotseq;":                   '\U00002252',
-	"fcy;":                             '\U00000444',
-	"female;":                          '\U00002640',
-	"ffilig;":                          '\U0000FB03',
-	"fflig;":                           '\U0000FB00',
-	"ffllig;":                          '\U0000FB04',
-	"ffr;":                             '\U0001D523',
-	"filig;":                           '\U0000FB01',
-	"flat;":                            '\U0000266D',
-	"fllig;":                           '\U0000FB02',
-	"fltns;":                           '\U000025B1',
-	"fnof;":                            '\U00000192',
-	"fopf;":                            '\U0001D557',
-	"forall;":                          '\U00002200',
-	"fork;":                            '\U000022D4',
-	"forkv;":                           '\U00002AD9',
-	"fpartint;":                        '\U00002A0D',
-	"frac12;":                          '\U000000BD',
-	"frac13;":                          '\U00002153',
-	"frac14;":                          '\U000000BC',
-	"frac15;":                          '\U00002155',
-	"frac16;":                          '\U00002159',
-	"frac18;":                          '\U0000215B',
-	"frac23;":                          '\U00002154',
-	"frac25;":                          '\U00002156',
-	"frac34;":                          '\U000000BE',
-	"frac35;":                          '\U00002157',
-	"frac38;":                          '\U0000215C',
-	"frac45;":                          '\U00002158',
-	"frac56;":                          '\U0000215A',
-	"frac58;":                          '\U0000215D',
-	"frac78;":                          '\U0000215E',
-	"frasl;":                           '\U00002044',
-	"frown;":                           '\U00002322',
-	"fscr;":                            '\U0001D4BB',
-	"gE;":                              '\U00002267',
-	"gEl;":                             '\U00002A8C',
-	"gacute;":                          '\U000001F5',
-	"gamma;":                           '\U000003B3',
-	"gammad;":                          '\U000003DD',
-	"gap;":                             '\U00002A86',
-	"gbreve;":                          '\U0000011F',
-	"gcirc;":                           '\U0000011D',
-	"gcy;":                             '\U00000433',
-	"gdot;":                            '\U00000121',
-	"ge;":                              '\U00002265',
-	"gel;":                             '\U000022DB',
-	"geq;":                             '\U00002265',
-	"geqq;":                            '\U00002267',
-	"geqslant;":                        '\U00002A7E',
-	"ges;":                             '\U00002A7E',
-	"gescc;":                           '\U00002AA9',
-	"gesdot;":                          '\U00002A80',
-	"gesdoto;":                         '\U00002A82',
-	"gesdotol;":                        '\U00002A84',
-	"gesles;":                          '\U00002A94',
-	"gfr;":                             '\U0001D524',
-	"gg;":                              '\U0000226B',
-	"ggg;":                             '\U000022D9',
-	"gimel;":                           '\U00002137',
-	"gjcy;":                            '\U00000453',
-	"gl;":                              '\U00002277',
-	"glE;":                             '\U00002A92',
-	"gla;":                             '\U00002AA5',
-	"glj;":                             '\U00002AA4',
-	"gnE;":                             '\U00002269',
-	"gnap;":                            '\U00002A8A',
-	"gnapprox;":                        '\U00002A8A',
-	"gne;":                             '\U00002A88',
-	"gneq;":                            '\U00002A88',
-	"gneqq;":                           '\U00002269',
-	"gnsim;":                           '\U000022E7',
-	"gopf;":                            '\U0001D558',
-	"grave;":                           '\U00000060',
-	"gscr;":                            '\U0000210A',
-	"gsim;":                            '\U00002273',
-	"gsime;":                           '\U00002A8E',
-	"gsiml;":                           '\U00002A90',
-	"gt;":                              '\U0000003E',
-	"gtcc;":                            '\U00002AA7',
-	"gtcir;":                           '\U00002A7A',
-	"gtdot;":                           '\U000022D7',
-	"gtlPar;":                          '\U00002995',
-	"gtquest;":                         '\U00002A7C',
-	"gtrapprox;":                       '\U00002A86',
-	"gtrarr;":                          '\U00002978',
-	"gtrdot;":                          '\U000022D7',
-	"gtreqless;":                       '\U000022DB',
-	"gtreqqless;":                      '\U00002A8C',
-	"gtrless;":                         '\U00002277',
-	"gtrsim;":                          '\U00002273',
-	"hArr;":                            '\U000021D4',
-	"hairsp;":                          '\U0000200A',
-	"half;":                            '\U000000BD',
-	"hamilt;":                          '\U0000210B',
-	"hardcy;":                          '\U0000044A',
-	"harr;":                            '\U00002194',
-	"harrcir;":                         '\U00002948',
-	"harrw;":                           '\U000021AD',
-	"hbar;":                            '\U0000210F',
-	"hcirc;":                           '\U00000125',
-	"hearts;":                          '\U00002665',
-	"heartsuit;":                       '\U00002665',
-	"hellip;":                          '\U00002026',
-	"hercon;":                          '\U000022B9',
-	"hfr;":                             '\U0001D525',
-	"hksearow;":                        '\U00002925',
-	"hkswarow;":                        '\U00002926',
-	"hoarr;":                           '\U000021FF',
-	"homtht;":                          '\U0000223B',
-	"hookleftarrow;":                   '\U000021A9',
-	"hookrightarrow;":                  '\U000021AA',
-	"hopf;":                            '\U0001D559',
-	"horbar;":                          '\U00002015',
-	"hscr;":                            '\U0001D4BD',
-	"hslash;":                          '\U0000210F',
-	"hstrok;":                          '\U00000127',
-	"hybull;":                          '\U00002043',
-	"hyphen;":                          '\U00002010',
-	"iacute;":                          '\U000000ED',
-	"ic;":                              '\U00002063',
-	"icirc;":                           '\U000000EE',
-	"icy;":                             '\U00000438',
-	"iecy;":                            '\U00000435',
-	"iexcl;":                           '\U000000A1',
-	"iff;":                             '\U000021D4',
-	"ifr;":                             '\U0001D526',
-	"igrave;":                          '\U000000EC',
-	"ii;":                              '\U00002148',
-	"iiiint;":                          '\U00002A0C',
-	"iiint;":                           '\U0000222D',
-	"iinfin;":                          '\U000029DC',
-	"iiota;":                           '\U00002129',
-	"ijlig;":                           '\U00000133',
-	"imacr;":                           '\U0000012B',
-	"image;":                           '\U00002111',
-	"imagline;":                        '\U00002110',
-	"imagpart;":                        '\U00002111',
-	"imath;":                           '\U00000131',
-	"imof;":                            '\U000022B7',
-	"imped;":                           '\U000001B5',
-	"in;":                              '\U00002208',
-	"incare;":                          '\U00002105',
-	"infin;":                           '\U0000221E',
-	"infintie;":                        '\U000029DD',
-	"inodot;":                          '\U00000131',
-	"int;":                             '\U0000222B',
-	"intcal;":                          '\U000022BA',
-	"integers;":                        '\U00002124',
-	"intercal;":                        '\U000022BA',
-	"intlarhk;":                        '\U00002A17',
-	"intprod;":                         '\U00002A3C',
-	"iocy;":                            '\U00000451',
-	"iogon;":                           '\U0000012F',
-	"iopf;":                            '\U0001D55A',
-	"iota;":                            '\U000003B9',
-	"iprod;":                           '\U00002A3C',
-	"iquest;":                          '\U000000BF',
-	"iscr;":                            '\U0001D4BE',
-	"isin;":                            '\U00002208',
-	"isinE;":                           '\U000022F9',
-	"isindot;":                         '\U000022F5',
-	"isins;":                           '\U000022F4',
-	"isinsv;":                          '\U000022F3',
-	"isinv;":                           '\U00002208',
-	"it;":                              '\U00002062',
-	"itilde;":                          '\U00000129',
-	"iukcy;":                           '\U00000456',
-	"iuml;":                            '\U000000EF',
-	"jcirc;":                           '\U00000135',
-	"jcy;":                             '\U00000439',
-	"jfr;":                             '\U0001D527',
-	"jmath;":                           '\U00000237',
-	"jopf;":                            '\U0001D55B',
-	"jscr;":                            '\U0001D4BF',
-	"jsercy;":                          '\U00000458',
-	"jukcy;":                           '\U00000454',
-	"kappa;":                           '\U000003BA',
-	"kappav;":                          '\U000003F0',
-	"kcedil;":                          '\U00000137',
-	"kcy;":                             '\U0000043A',
-	"kfr;":                             '\U0001D528',
-	"kgreen;":                          '\U00000138',
-	"khcy;":                            '\U00000445',
-	"kjcy;":                            '\U0000045C',
-	"kopf;":                            '\U0001D55C',
-	"kscr;":                            '\U0001D4C0',
-	"lAarr;":                           '\U000021DA',
-	"lArr;":                            '\U000021D0',
-	"lAtail;":                          '\U0000291B',
-	"lBarr;":                           '\U0000290E',
-	"lE;":                              '\U00002266',
-	"lEg;":                             '\U00002A8B',
-	"lHar;":                            '\U00002962',
-	"lacute;":                          '\U0000013A',
-	"laemptyv;":                        '\U000029B4',
-	"lagran;":                          '\U00002112',
-	"lambda;":                          '\U000003BB',
-	"lang;":                            '\U000027E8',
-	"langd;":                           '\U00002991',
-	"langle;":                          '\U000027E8',
-	"lap;":                             '\U00002A85',
-	"laquo;":                           '\U000000AB',
-	"larr;":                            '\U00002190',
-	"larrb;":                           '\U000021E4',
-	"larrbfs;":                         '\U0000291F',
-	"larrfs;":                          '\U0000291D',
-	"larrhk;":                          '\U000021A9',
-	"larrlp;":                          '\U000021AB',
-	"larrpl;":                          '\U00002939',
-	"larrsim;":                         '\U00002973',
-	"larrtl;":                          '\U000021A2',
-	"lat;":                             '\U00002AAB',
-	"latail;":                          '\U00002919',
-	"late;":                            '\U00002AAD',
-	"lbarr;":                           '\U0000290C',
-	"lbbrk;":                           '\U00002772',
-	"lbrace;":                          '\U0000007B',
-	"lbrack;":                          '\U0000005B',
-	"lbrke;":                           '\U0000298B',
-	"lbrksld;":                         '\U0000298F',
-	"lbrkslu;":                         '\U0000298D',
-	"lcaron;":                          '\U0000013E',
-	"lcedil;":                          '\U0000013C',
-	"lceil;":                           '\U00002308',
-	"lcub;":                            '\U0000007B',
-	"lcy;":                             '\U0000043B',
-	"ldca;":                            '\U00002936',
-	"ldquo;":                           '\U0000201C',
-	"ldquor;":                          '\U0000201E',
-	"ldrdhar;":                         '\U00002967',
-	"ldrushar;":                        '\U0000294B',
-	"ldsh;":                            '\U000021B2',
-	"le;":                              '\U00002264',
-	"leftarrow;":                       '\U00002190',
-	"leftarrowtail;":                   '\U000021A2',
-	"leftharpoondown;":                 '\U000021BD',
-	"leftharpoonup;":                   '\U000021BC',
-	"leftleftarrows;":                  '\U000021C7',
-	"leftrightarrow;":                  '\U00002194',
-	"leftrightarrows;":                 '\U000021C6',
-	"leftrightharpoons;":               '\U000021CB',
-	"leftrightsquigarrow;":             '\U000021AD',
-	"leftthreetimes;":                  '\U000022CB',
-	"leg;":                             '\U000022DA',
-	"leq;":                             '\U00002264',
-	"leqq;":                            '\U00002266',
-	"leqslant;":                        '\U00002A7D',
-	"les;":                             '\U00002A7D',
-	"lescc;":                           '\U00002AA8',
-	"lesdot;":                          '\U00002A7F',
-	"lesdoto;":                         '\U00002A81',
-	"lesdotor;":                        '\U00002A83',
-	"lesges;":                          '\U00002A93',
-	"lessapprox;":                      '\U00002A85',
-	"lessdot;":                         '\U000022D6',
-	"lesseqgtr;":                       '\U000022DA',
-	"lesseqqgtr;":                      '\U00002A8B',
-	"lessgtr;":                         '\U00002276',
-	"lesssim;":                         '\U00002272',
-	"lfisht;":                          '\U0000297C',
-	"lfloor;":                          '\U0000230A',
-	"lfr;":                             '\U0001D529',
-	"lg;":                              '\U00002276',
-	"lgE;":                             '\U00002A91',
-	"lhard;":                           '\U000021BD',
-	"lharu;":                           '\U000021BC',
-	"lharul;":                          '\U0000296A',
-	"lhblk;":                           '\U00002584',
-	"ljcy;":                            '\U00000459',
-	"ll;":                              '\U0000226A',
-	"llarr;":                           '\U000021C7',
-	"llcorner;":                        '\U0000231E',
-	"llhard;":                          '\U0000296B',
-	"lltri;":                           '\U000025FA',
-	"lmidot;":                          '\U00000140',
-	"lmoust;":                          '\U000023B0',
-	"lmoustache;":                      '\U000023B0',
-	"lnE;":                             '\U00002268',
-	"lnap;":                            '\U00002A89',
-	"lnapprox;":                        '\U00002A89',
-	"lne;":                             '\U00002A87',
-	"lneq;":                            '\U00002A87',
-	"lneqq;":                           '\U00002268',
-	"lnsim;":                           '\U000022E6',
-	"loang;":                           '\U000027EC',
-	"loarr;":                           '\U000021FD',
-	"lobrk;":                           '\U000027E6',
-	"longleftarrow;":                   '\U000027F5',
-	"longleftrightarrow;":              '\U000027F7',
-	"longmapsto;":                      '\U000027FC',
-	"longrightarrow;":                  '\U000027F6',
-	"looparrowleft;":                   '\U000021AB',
-	"looparrowright;":                  '\U000021AC',
-	"lopar;":                           '\U00002985',
-	"lopf;":                            '\U0001D55D',
-	"loplus;":                          '\U00002A2D',
-	"lotimes;":                         '\U00002A34',
-	"lowast;":                          '\U00002217',
-	"lowbar;":                          '\U0000005F',
-	"loz;":                             '\U000025CA',
-	"lozenge;":                         '\U000025CA',
-	"lozf;":                            '\U000029EB',
-	"lpar;":                            '\U00000028',
-	"lparlt;":                          '\U00002993',
-	"lrarr;":                           '\U000021C6',
-	"lrcorner;":                        '\U0000231F',
-	"lrhar;":                           '\U000021CB',
-	"lrhard;":                          '\U0000296D',
-	"lrm;":                             '\U0000200E',
-	"lrtri;":                           '\U000022BF',
-	"lsaquo;":                          '\U00002039',
-	"lscr;":                            '\U0001D4C1',
-	"lsh;":                             '\U000021B0',
-	"lsim;":                            '\U00002272',
-	"lsime;":                           '\U00002A8D',
-	"lsimg;":                           '\U00002A8F',
-	"lsqb;":                            '\U0000005B',
-	"lsquo;":                           '\U00002018',
-	"lsquor;":                          '\U0000201A',
-	"lstrok;":                          '\U00000142',
-	"lt;":                              '\U0000003C',
-	"ltcc;":                            '\U00002AA6',
-	"ltcir;":                           '\U00002A79',
-	"ltdot;":                           '\U000022D6',
-	"lthree;":                          '\U000022CB',
-	"ltimes;":                          '\U000022C9',
-	"ltlarr;":                          '\U00002976',
-	"ltquest;":                         '\U00002A7B',
-	"ltrPar;":                          '\U00002996',
-	"ltri;":                            '\U000025C3',
-	"ltrie;":                           '\U000022B4',
-	"ltrif;":                           '\U000025C2',
-	"lurdshar;":                        '\U0000294A',
-	"luruhar;":                         '\U00002966',
-	"mDDot;":                           '\U0000223A',
-	"macr;":                            '\U000000AF',
-	"male;":                            '\U00002642',
-	"malt;":                            '\U00002720',
-	"maltese;":                         '\U00002720',
-	"map;":                             '\U000021A6',
-	"mapsto;":                          '\U000021A6',
-	"mapstodown;":                      '\U000021A7',
-	"mapstoleft;":                      '\U000021A4',
-	"mapstoup;":                        '\U000021A5',
-	"marker;":                          '\U000025AE',
-	"mcomma;":                          '\U00002A29',
-	"mcy;":                             '\U0000043C',
-	"mdash;":                           '\U00002014',
-	"measuredangle;":                   '\U00002221',
-	"mfr;":                             '\U0001D52A',
-	"mho;":                             '\U00002127',
-	"micro;":                           '\U000000B5',
-	"mid;":                             '\U00002223',
-	"midast;":                          '\U0000002A',
-	"midcir;":                          '\U00002AF0',
-	"middot;":                          '\U000000B7',
-	"minus;":                           '\U00002212',
-	"minusb;":                          '\U0000229F',
-	"minusd;":                          '\U00002238',
-	"minusdu;":                         '\U00002A2A',
-	"mlcp;":                            '\U00002ADB',
-	"mldr;":                            '\U00002026',
-	"mnplus;":                          '\U00002213',
-	"models;":                          '\U000022A7',
-	"mopf;":                            '\U0001D55E',
-	"mp;":                              '\U00002213',
-	"mscr;":                            '\U0001D4C2',
-	"mstpos;":                          '\U0000223E',
-	"mu;":                              '\U000003BC',
-	"multimap;":                        '\U000022B8',
-	"mumap;":                           '\U000022B8',
-	"nLeftarrow;":                      '\U000021CD',
-	"nLeftrightarrow;":                 '\U000021CE',
-	"nRightarrow;":                     '\U000021CF',
-	"nVDash;":                          '\U000022AF',
-	"nVdash;":                          '\U000022AE',
-	"nabla;":                           '\U00002207',
-	"nacute;":                          '\U00000144',
-	"nap;":                             '\U00002249',
-	"napos;":                           '\U00000149',
-	"napprox;":                         '\U00002249',
-	"natur;":                           '\U0000266E',
-	"natural;":                         '\U0000266E',
-	"naturals;":                        '\U00002115',
-	"nbsp;":                            '\U000000A0',
-	"ncap;":                            '\U00002A43',
-	"ncaron;":                          '\U00000148',
-	"ncedil;":                          '\U00000146',
-	"ncong;":                           '\U00002247',
-	"ncup;":                            '\U00002A42',
-	"ncy;":                             '\U0000043D',
-	"ndash;":                           '\U00002013',
-	"ne;":                              '\U00002260',
-	"neArr;":                           '\U000021D7',
-	"nearhk;":                          '\U00002924',
-	"nearr;":                           '\U00002197',
-	"nearrow;":                         '\U00002197',
-	"nequiv;":                          '\U00002262',
-	"nesear;":                          '\U00002928',
-	"nexist;":                          '\U00002204',
-	"nexists;":                         '\U00002204',
-	"nfr;":                             '\U0001D52B',
-	"nge;":                             '\U00002271',
-	"ngeq;":                            '\U00002271',
-	"ngsim;":                           '\U00002275',
-	"ngt;":                             '\U0000226F',
-	"ngtr;":                            '\U0000226F',
-	"nhArr;":                           '\U000021CE',
-	"nharr;":                           '\U000021AE',
-	"nhpar;":                           '\U00002AF2',
-	"ni;":                              '\U0000220B',
-	"nis;":                             '\U000022FC',
-	"nisd;":                            '\U000022FA',
-	"niv;":                             '\U0000220B',
-	"njcy;":                            '\U0000045A',
-	"nlArr;":                           '\U000021CD',
-	"nlarr;":                           '\U0000219A',
-	"nldr;":                            '\U00002025',
-	"nle;":                             '\U00002270',
-	"nleftarrow;":                      '\U0000219A',
-	"nleftrightarrow;":                 '\U000021AE',
-	"nleq;":                            '\U00002270',
-	"nless;":                           '\U0000226E',
-	"nlsim;":                           '\U00002274',
-	"nlt;":                             '\U0000226E',
-	"nltri;":                           '\U000022EA',
-	"nltrie;":                          '\U000022EC',
-	"nmid;":                            '\U00002224',
-	"nopf;":                            '\U0001D55F',
-	"not;":                             '\U000000AC',
-	"notin;":                           '\U00002209',
-	"notinva;":                         '\U00002209',
-	"notinvb;":                         '\U000022F7',
-	"notinvc;":                         '\U000022F6',
-	"notni;":                           '\U0000220C',
-	"notniva;":                         '\U0000220C',
-	"notnivb;":                         '\U000022FE',
-	"notnivc;":                         '\U000022FD',
-	"npar;":                            '\U00002226',
-	"nparallel;":                       '\U00002226',
-	"npolint;":                         '\U00002A14',
-	"npr;":                             '\U00002280',
-	"nprcue;":                          '\U000022E0',
-	"nprec;":                           '\U00002280',
-	"nrArr;":                           '\U000021CF',
-	"nrarr;":                           '\U0000219B',
-	"nrightarrow;":                     '\U0000219B',
-	"nrtri;":                           '\U000022EB',
-	"nrtrie;":                          '\U000022ED',
-	"nsc;":                             '\U00002281',
-	"nsccue;":                          '\U000022E1',
-	"nscr;":                            '\U0001D4C3',
-	"nshortmid;":                       '\U00002224',
-	"nshortparallel;":                  '\U00002226',
-	"nsim;":                            '\U00002241',
-	"nsime;":                           '\U00002244',
-	"nsimeq;":                          '\U00002244',
-	"nsmid;":                           '\U00002224',
-	"nspar;":                           '\U00002226',
-	"nsqsube;":                         '\U000022E2',
-	"nsqsupe;":                         '\U000022E3',
-	"nsub;":                            '\U00002284',
-	"nsube;":                           '\U00002288',
-	"nsubseteq;":                       '\U00002288',
-	"nsucc;":                           '\U00002281',
-	"nsup;":                            '\U00002285',
-	"nsupe;":                           '\U00002289',
-	"nsupseteq;":                       '\U00002289',
-	"ntgl;":                            '\U00002279',
-	"ntilde;":                          '\U000000F1',
-	"ntlg;":                            '\U00002278',
-	"ntriangleleft;":                   '\U000022EA',
-	"ntrianglelefteq;":                 '\U000022EC',
-	"ntriangleright;":                  '\U000022EB',
-	"ntrianglerighteq;":                '\U000022ED',
-	"nu;":                              '\U000003BD',
-	"num;":                             '\U00000023',
-	"numero;":                          '\U00002116',
-	"numsp;":                           '\U00002007',
-	"nvDash;":                          '\U000022AD',
-	"nvHarr;":                          '\U00002904',
-	"nvdash;":                          '\U000022AC',
-	"nvinfin;":                         '\U000029DE',
-	"nvlArr;":                          '\U00002902',
-	"nvrArr;":                          '\U00002903',
-	"nwArr;":                           '\U000021D6',
-	"nwarhk;":                          '\U00002923',
-	"nwarr;":                           '\U00002196',
-	"nwarrow;":                         '\U00002196',
-	"nwnear;":                          '\U00002927',
-	"oS;":                              '\U000024C8',
-	"oacute;":                          '\U000000F3',
-	"oast;":                            '\U0000229B',
-	"ocir;":                            '\U0000229A',
-	"ocirc;":                           '\U000000F4',
-	"ocy;":                             '\U0000043E',
-	"odash;":                           '\U0000229D',
-	"odblac;":                          '\U00000151',
-	"odiv;":                            '\U00002A38',
-	"odot;":                            '\U00002299',
-	"odsold;":                          '\U000029BC',
-	"oelig;":                           '\U00000153',
-	"ofcir;":                           '\U000029BF',
-	"ofr;":                             '\U0001D52C',
-	"ogon;":                            '\U000002DB',
-	"ograve;":                          '\U000000F2',
-	"ogt;":                             '\U000029C1',
-	"ohbar;":                           '\U000029B5',
-	"ohm;":                             '\U000003A9',
-	"oint;":                            '\U0000222E',
-	"olarr;":                           '\U000021BA',
-	"olcir;":                           '\U000029BE',
-	"olcross;":                         '\U000029BB',
-	"oline;":                           '\U0000203E',
-	"olt;":                             '\U000029C0',
-	"omacr;":                           '\U0000014D',
-	"omega;":                           '\U000003C9',
-	"omicron;":                         '\U000003BF',
-	"omid;":                            '\U000029B6',
-	"ominus;":                          '\U00002296',
-	"oopf;":                            '\U0001D560',
-	"opar;":                            '\U000029B7',
-	"operp;":                           '\U000029B9',
-	"oplus;":                           '\U00002295',
-	"or;":                              '\U00002228',
-	"orarr;":                           '\U000021BB',
-	"ord;":                             '\U00002A5D',
-	"order;":                           '\U00002134',
-	"orderof;":                         '\U00002134',
-	"ordf;":                            '\U000000AA',
-	"ordm;":                            '\U000000BA',
-	"origof;":                          '\U000022B6',
-	"oror;":                            '\U00002A56',
-	"orslope;":                         '\U00002A57',
-	"orv;":                             '\U00002A5B',
-	"oscr;":                            '\U00002134',
-	"oslash;":                          '\U000000F8',
-	"osol;":                            '\U00002298',
-	"otilde;":                          '\U000000F5',
-	"otimes;":                          '\U00002297',
-	"otimesas;":                        '\U00002A36',
-	"ouml;":                            '\U000000F6',
-	"ovbar;":                           '\U0000233D',
-	"par;":                             '\U00002225',
-	"para;":                            '\U000000B6',
-	"parallel;":                        '\U00002225',
-	"parsim;":                          '\U00002AF3',
-	"parsl;":                           '\U00002AFD',
-	"part;":                            '\U00002202',
-	"pcy;":                             '\U0000043F',
-	"percnt;":                          '\U00000025',
-	"period;":                          '\U0000002E',
-	"permil;":                          '\U00002030',
-	"perp;":                            '\U000022A5',
-	"pertenk;":                         '\U00002031',
-	"pfr;":                             '\U0001D52D',
-	"phi;":                             '\U000003C6',
-	"phiv;":                            '\U000003D5',
-	"phmmat;":                          '\U00002133',
-	"phone;":                           '\U0000260E',
-	"pi;":                              '\U000003C0',
-	"pitchfork;":                       '\U000022D4',
-	"piv;":                             '\U000003D6',
-	"planck;":                          '\U0000210F',
-	"planckh;":                         '\U0000210E',
-	"plankv;":                          '\U0000210F',
-	"plus;":                            '\U0000002B',
-	"plusacir;":                        '\U00002A23',
-	"plusb;":                           '\U0000229E',
-	"pluscir;":                         '\U00002A22',
-	"plusdo;":                          '\U00002214',
-	"plusdu;":                          '\U00002A25',
-	"pluse;":                           '\U00002A72',
-	"plusmn;":                          '\U000000B1',
-	"plussim;":                         '\U00002A26',
-	"plustwo;":                         '\U00002A27',
-	"pm;":                              '\U000000B1',
-	"pointint;":                        '\U00002A15',
-	"popf;":                            '\U0001D561',
-	"pound;":                           '\U000000A3',
-	"pr;":                              '\U0000227A',
-	"prE;":                             '\U00002AB3',
-	"prap;":                            '\U00002AB7',
-	"prcue;":                           '\U0000227C',
-	"pre;":                             '\U00002AAF',
-	"prec;":                            '\U0000227A',
-	"precapprox;":                      '\U00002AB7',
-	"preccurlyeq;":                     '\U0000227C',
-	"preceq;":                          '\U00002AAF',
-	"precnapprox;":                     '\U00002AB9',
-	"precneqq;":                        '\U00002AB5',
-	"precnsim;":                        '\U000022E8',
-	"precsim;":                         '\U0000227E',
-	"prime;":                           '\U00002032',
-	"primes;":                          '\U00002119',
-	"prnE;":                            '\U00002AB5',
-	"prnap;":                           '\U00002AB9',
-	"prnsim;":                          '\U000022E8',
-	"prod;":                            '\U0000220F',
-	"profalar;":                        '\U0000232E',
-	"profline;":                        '\U00002312',
-	"profsurf;":                        '\U00002313',
-	"prop;":                            '\U0000221D',
-	"propto;":                          '\U0000221D',
-	"prsim;":                           '\U0000227E',
-	"prurel;":                          '\U000022B0',
-	"pscr;":                            '\U0001D4C5',
-	"psi;":                             '\U000003C8',
-	"puncsp;":                          '\U00002008',
-	"qfr;":                             '\U0001D52E',
-	"qint;":                            '\U00002A0C',
-	"qopf;":                            '\U0001D562',
-	"qprime;":                          '\U00002057',
-	"qscr;":                            '\U0001D4C6',
-	"quaternions;":                     '\U0000210D',
-	"quatint;":                         '\U00002A16',
-	"quest;":                           '\U0000003F',
-	"questeq;":                         '\U0000225F',
-	"quot;":                            '\U00000022',
-	"rAarr;":                           '\U000021DB',
-	"rArr;":                            '\U000021D2',
-	"rAtail;":                          '\U0000291C',
-	"rBarr;":                           '\U0000290F',
-	"rHar;":                            '\U00002964',
-	"racute;":                          '\U00000155',
-	"radic;":                           '\U0000221A',
-	"raemptyv;":                        '\U000029B3',
-	"rang;":                            '\U000027E9',
-	"rangd;":                           '\U00002992',
-	"range;":                           '\U000029A5',
-	"rangle;":                          '\U000027E9',
-	"raquo;":                           '\U000000BB',
-	"rarr;":                            '\U00002192',
-	"rarrap;":                          '\U00002975',
-	"rarrb;":                           '\U000021E5',
-	"rarrbfs;":                         '\U00002920',
-	"rarrc;":                           '\U00002933',
-	"rarrfs;":                          '\U0000291E',
-	"rarrhk;":                          '\U000021AA',
-	"rarrlp;":                          '\U000021AC',
-	"rarrpl;":                          '\U00002945',
-	"rarrsim;":                         '\U00002974',
-	"rarrtl;":                          '\U000021A3',
-	"rarrw;":                           '\U0000219D',
-	"ratail;":                          '\U0000291A',
-	"ratio;":                           '\U00002236',
-	"rationals;":                       '\U0000211A',
-	"rbarr;":                           '\U0000290D',
-	"rbbrk;":                           '\U00002773',
-	"rbrace;":                          '\U0000007D',
-	"rbrack;":                          '\U0000005D',
-	"rbrke;":                           '\U0000298C',
-	"rbrksld;":                         '\U0000298E',
-	"rbrkslu;":                         '\U00002990',
-	"rcaron;":                          '\U00000159',
-	"rcedil;":                          '\U00000157',
-	"rceil;":                           '\U00002309',
-	"rcub;":                            '\U0000007D',
-	"rcy;":                             '\U00000440',
-	"rdca;":                            '\U00002937',
-	"rdldhar;":                         '\U00002969',
-	"rdquo;":                           '\U0000201D',
-	"rdquor;":                          '\U0000201D',
-	"rdsh;":                            '\U000021B3',
-	"real;":                            '\U0000211C',
-	"realine;":                         '\U0000211B',
-	"realpart;":                        '\U0000211C',
-	"reals;":                           '\U0000211D',
-	"rect;":                            '\U000025AD',
-	"reg;":                             '\U000000AE',
-	"rfisht;":                          '\U0000297D',
-	"rfloor;":                          '\U0000230B',
-	"rfr;":                             '\U0001D52F',
-	"rhard;":                           '\U000021C1',
-	"rharu;":                           '\U000021C0',
-	"rharul;":                          '\U0000296C',
-	"rho;":                             '\U000003C1',
-	"rhov;":                            '\U000003F1',
-	"rightarrow;":                      '\U00002192',
-	"rightarrowtail;":                  '\U000021A3',
-	"rightharpoondown;":                '\U000021C1',
-	"rightharpoonup;":                  '\U000021C0',
-	"rightleftarrows;":                 '\U000021C4',
-	"rightleftharpoons;":               '\U000021CC',
-	"rightrightarrows;":                '\U000021C9',
-	"rightsquigarrow;":                 '\U0000219D',
-	"rightthreetimes;":                 '\U000022CC',
-	"ring;":                            '\U000002DA',
-	"risingdotseq;":                    '\U00002253',
-	"rlarr;":                           '\U000021C4',
-	"rlhar;":                           '\U000021CC',
-	"rlm;":                             '\U0000200F',
-	"rmoust;":                          '\U000023B1',
-	"rmoustache;":                      '\U000023B1',
-	"rnmid;":                           '\U00002AEE',
-	"roang;":                           '\U000027ED',
-	"roarr;":                           '\U000021FE',
-	"robrk;":                           '\U000027E7',
-	"ropar;":                           '\U00002986',
-	"ropf;":                            '\U0001D563',
-	"roplus;":                          '\U00002A2E',
-	"rotimes;":                         '\U00002A35',
-	"rpar;":                            '\U00000029',
-	"rpargt;":                          '\U00002994',
-	"rppolint;":                        '\U00002A12',
-	"rrarr;":                           '\U000021C9',
-	"rsaquo;":                          '\U0000203A',
-	"rscr;":                            '\U0001D4C7',
-	"rsh;":                             '\U000021B1',
-	"rsqb;":                            '\U0000005D',
-	"rsquo;":                           '\U00002019',
-	"rsquor;":                          '\U00002019',
-	"rthree;":                          '\U000022CC',
-	"rtimes;":                          '\U000022CA',
-	"rtri;":                            '\U000025B9',
-	"rtrie;":                           '\U000022B5',
-	"rtrif;":                           '\U000025B8',
-	"rtriltri;":                        '\U000029CE',
-	"ruluhar;":                         '\U00002968',
-	"rx;":                              '\U0000211E',
-	"sacute;":                          '\U0000015B',
-	"sbquo;":                           '\U0000201A',
-	"sc;":                              '\U0000227B',
-	"scE;":                             '\U00002AB4',
-	"scap;":                            '\U00002AB8',
-	"scaron;":                          '\U00000161',
-	"sccue;":                           '\U0000227D',
-	"sce;":                             '\U00002AB0',
-	"scedil;":                          '\U0000015F',
-	"scirc;":                           '\U0000015D',
-	"scnE;":                            '\U00002AB6',
-	"scnap;":                           '\U00002ABA',
-	"scnsim;":                          '\U000022E9',
-	"scpolint;":                        '\U00002A13',
-	"scsim;":                           '\U0000227F',
-	"scy;":                             '\U00000441',
-	"sdot;":                            '\U000022C5',
-	"sdotb;":                           '\U000022A1',
-	"sdote;":                           '\U00002A66',
-	"seArr;":                           '\U000021D8',
-	"searhk;":                          '\U00002925',
-	"searr;":                           '\U00002198',
-	"searrow;":                         '\U00002198',
-	"sect;":                            '\U000000A7',
-	"semi;":                            '\U0000003B',
-	"seswar;":                          '\U00002929',
-	"setminus;":                        '\U00002216',
-	"setmn;":                           '\U00002216',
-	"sext;":                            '\U00002736',
-	"sfr;":                             '\U0001D530',
-	"sfrown;":                          '\U00002322',
-	"sharp;":                           '\U0000266F',
-	"shchcy;":                          '\U00000449',
-	"shcy;":                            '\U00000448',
-	"shortmid;":                        '\U00002223',
-	"shortparallel;":                   '\U00002225',
-	"shy;":                             '\U000000AD',
-	"sigma;":                           '\U000003C3',
-	"sigmaf;":                          '\U000003C2',
-	"sigmav;":                          '\U000003C2',
-	"sim;":                             '\U0000223C',
-	"simdot;":                          '\U00002A6A',
-	"sime;":                            '\U00002243',
-	"simeq;":                           '\U00002243',
-	"simg;":                            '\U00002A9E',
-	"simgE;":                           '\U00002AA0',
-	"siml;":                            '\U00002A9D',
-	"simlE;":                           '\U00002A9F',
-	"simne;":                           '\U00002246',
-	"simplus;":                         '\U00002A24',
-	"simrarr;":                         '\U00002972',
-	"slarr;":                           '\U00002190',
-	"smallsetminus;":                   '\U00002216',
-	"smashp;":                          '\U00002A33',
-	"smeparsl;":                        '\U000029E4',
-	"smid;":                            '\U00002223',
-	"smile;":                           '\U00002323',
-	"smt;":                             '\U00002AAA',
-	"smte;":                            '\U00002AAC',
-	"softcy;":                          '\U0000044C',
-	"sol;":                             '\U0000002F',
-	"solb;":                            '\U000029C4',
-	"solbar;":                          '\U0000233F',
-	"sopf;":                            '\U0001D564',
-	"spades;":                          '\U00002660',
-	"spadesuit;":                       '\U00002660',
-	"spar;":                            '\U00002225',
-	"sqcap;":                           '\U00002293',
-	"sqcup;":                           '\U00002294',
-	"sqsub;":                           '\U0000228F',
-	"sqsube;":                          '\U00002291',
-	"sqsubset;":                        '\U0000228F',
-	"sqsubseteq;":                      '\U00002291',
-	"sqsup;":                           '\U00002290',
-	"sqsupe;":                          '\U00002292',
-	"sqsupset;":                        '\U00002290',
-	"sqsupseteq;":                      '\U00002292',
-	"squ;":                             '\U000025A1',
-	"square;":                          '\U000025A1',
-	"squarf;":                          '\U000025AA',
-	"squf;":                            '\U000025AA',
-	"srarr;":                           '\U00002192',
-	"sscr;":                            '\U0001D4C8',
-	"ssetmn;":                          '\U00002216',
-	"ssmile;":                          '\U00002323',
-	"sstarf;":                          '\U000022C6',
-	"star;":                            '\U00002606',
-	"starf;":                           '\U00002605',
-	"straightepsilon;":                 '\U000003F5',
-	"straightphi;":                     '\U000003D5',
-	"strns;":                           '\U000000AF',
-	"sub;":                             '\U00002282',
-	"subE;":                            '\U00002AC5',
-	"subdot;":                          '\U00002ABD',
-	"sube;":                            '\U00002286',
-	"subedot;":                         '\U00002AC3',
-	"submult;":                         '\U00002AC1',
-	"subnE;":                           '\U00002ACB',
-	"subne;":                           '\U0000228A',
-	"subplus;":                         '\U00002ABF',
-	"subrarr;":                         '\U00002979',
-	"subset;":                          '\U00002282',
-	"subseteq;":                        '\U00002286',
-	"subseteqq;":                       '\U00002AC5',
-	"subsetneq;":                       '\U0000228A',
-	"subsetneqq;":                      '\U00002ACB',
-	"subsim;":                          '\U00002AC7',
-	"subsub;":                          '\U00002AD5',
-	"subsup;":                          '\U00002AD3',
-	"succ;":                            '\U0000227B',
-	"succapprox;":                      '\U00002AB8',
-	"succcurlyeq;":                     '\U0000227D',
-	"succeq;":                          '\U00002AB0',
-	"succnapprox;":                     '\U00002ABA',
-	"succneqq;":                        '\U00002AB6',
-	"succnsim;":                        '\U000022E9',
-	"succsim;":                         '\U0000227F',
-	"sum;":                             '\U00002211',
-	"sung;":                            '\U0000266A',
-	"sup;":                             '\U00002283',
-	"sup1;":                            '\U000000B9',
-	"sup2;":                            '\U000000B2',
-	"sup3;":                            '\U000000B3',
-	"supE;":                            '\U00002AC6',
-	"supdot;":                          '\U00002ABE',
-	"supdsub;":                         '\U00002AD8',
-	"supe;":                            '\U00002287',
-	"supedot;":                         '\U00002AC4',
-	"suphsol;":                         '\U000027C9',
-	"suphsub;":                         '\U00002AD7',
-	"suplarr;":                         '\U0000297B',
-	"supmult;":                         '\U00002AC2',
-	"supnE;":                           '\U00002ACC',
-	"supne;":                           '\U0000228B',
-	"supplus;":                         '\U00002AC0',
-	"supset;":                          '\U00002283',
-	"supseteq;":                        '\U00002287',
-	"supseteqq;":                       '\U00002AC6',
-	"supsetneq;":                       '\U0000228B',
-	"supsetneqq;":                      '\U00002ACC',
-	"supsim;":                          '\U00002AC8',
-	"supsub;":                          '\U00002AD4',
-	"supsup;":                          '\U00002AD6',
-	"swArr;":                           '\U000021D9',
-	"swarhk;":                          '\U00002926',
-	"swarr;":                           '\U00002199',
-	"swarrow;":                         '\U00002199',
-	"swnwar;":                          '\U0000292A',
-	"szlig;":                           '\U000000DF',
-	"target;":                          '\U00002316',
-	"tau;":                             '\U000003C4',
-	"tbrk;":                            '\U000023B4',
-	"tcaron;":                          '\U00000165',
-	"tcedil;":                          '\U00000163',
-	"tcy;":                             '\U00000442',
-	"tdot;":                            '\U000020DB',
-	"telrec;":                          '\U00002315',
-	"tfr;":                             '\U0001D531',
-	"there4;":                          '\U00002234',
-	"therefore;":                       '\U00002234',
-	"theta;":                           '\U000003B8',
-	"thetasym;":                        '\U000003D1',
-	"thetav;":                          '\U000003D1',
-	"thickapprox;":                     '\U00002248',
-	"thicksim;":                        '\U0000223C',
-	"thinsp;":                          '\U00002009',
-	"thkap;":                           '\U00002248',
-	"thksim;":                          '\U0000223C',
-	"thorn;":                           '\U000000FE',
-	"tilde;":                           '\U000002DC',
-	"times;":                           '\U000000D7',
-	"timesb;":                          '\U000022A0',
-	"timesbar;":                        '\U00002A31',
-	"timesd;":                          '\U00002A30',
-	"tint;":                            '\U0000222D',
-	"toea;":                            '\U00002928',
-	"top;":                             '\U000022A4',
-	"topbot;":                          '\U00002336',
-	"topcir;":                          '\U00002AF1',
-	"topf;":                            '\U0001D565',
-	"topfork;":                         '\U00002ADA',
-	"tosa;":                            '\U00002929',
-	"tprime;":                          '\U00002034',
-	"trade;":                           '\U00002122',
-	"triangle;":                        '\U000025B5',
-	"triangledown;":                    '\U000025BF',
-	"triangleleft;":                    '\U000025C3',
-	"trianglelefteq;":                  '\U000022B4',
-	"triangleq;":                       '\U0000225C',
-	"triangleright;":                   '\U000025B9',
-	"trianglerighteq;":                 '\U000022B5',
-	"tridot;":                          '\U000025EC',
-	"trie;":                            '\U0000225C',
-	"triminus;":                        '\U00002A3A',
-	"triplus;":                         '\U00002A39',
-	"trisb;":                           '\U000029CD',
-	"tritime;":                         '\U00002A3B',
-	"trpezium;":                        '\U000023E2',
-	"tscr;":                            '\U0001D4C9',
-	"tscy;":                            '\U00000446',
-	"tshcy;":                           '\U0000045B',
-	"tstrok;":                          '\U00000167',
-	"twixt;":                           '\U0000226C',
-	"twoheadleftarrow;":                '\U0000219E',
-	"twoheadrightarrow;":               '\U000021A0',
-	"uArr;":                            '\U000021D1',
-	"uHar;":                            '\U00002963',
-	"uacute;":                          '\U000000FA',
-	"uarr;":                            '\U00002191',
-	"ubrcy;":                           '\U0000045E',
-	"ubreve;":                          '\U0000016D',
-	"ucirc;":                           '\U000000FB',
-	"ucy;":                             '\U00000443',
-	"udarr;":                           '\U000021C5',
-	"udblac;":                          '\U00000171',
-	"udhar;":                           '\U0000296E',
-	"ufisht;":                          '\U0000297E',
-	"ufr;":                             '\U0001D532',
-	"ugrave;":                          '\U000000F9',
-	"uharl;":                           '\U000021BF',
-	"uharr;":                           '\U000021BE',
-	"uhblk;":                           '\U00002580',
-	"ulcorn;":                          '\U0000231C',
-	"ulcorner;":                        '\U0000231C',
-	"ulcrop;":                          '\U0000230F',
-	"ultri;":                           '\U000025F8',
-	"umacr;":                           '\U0000016B',
-	"uml;":                             '\U000000A8',
-	"uogon;":                           '\U00000173',
-	"uopf;":                            '\U0001D566',
-	"uparrow;":                         '\U00002191',
-	"updownarrow;":                     '\U00002195',
-	"upharpoonleft;":                   '\U000021BF',
-	"upharpoonright;":                  '\U000021BE',
-	"uplus;":                           '\U0000228E',
-	"upsi;":                            '\U000003C5',
-	"upsih;":                           '\U000003D2',
-	"upsilon;":                         '\U000003C5',
-	"upuparrows;":                      '\U000021C8',
-	"urcorn;":                          '\U0000231D',
-	"urcorner;":                        '\U0000231D',
-	"urcrop;":                          '\U0000230E',
-	"uring;":                           '\U0000016F',
-	"urtri;":                           '\U000025F9',
-	"uscr;":                            '\U0001D4CA',
-	"utdot;":                           '\U000022F0',
-	"utilde;":                          '\U00000169',
-	"utri;":                            '\U000025B5',
-	"utrif;":                           '\U000025B4',
-	"uuarr;":                           '\U000021C8',
-	"uuml;":                            '\U000000FC',
-	"uwangle;":                         '\U000029A7',
-	"vArr;":                            '\U000021D5',
-	"vBar;":                            '\U00002AE8',
-	"vBarv;":                           '\U00002AE9',
-	"vDash;":                           '\U000022A8',
-	"vangrt;":                          '\U0000299C',
-	"varepsilon;":                      '\U000003F5',
-	"varkappa;":                        '\U000003F0',
-	"varnothing;":                      '\U00002205',
-	"varphi;":                          '\U000003D5',
-	"varpi;":                           '\U000003D6',
-	"varpropto;":                       '\U0000221D',
-	"varr;":                            '\U00002195',
-	"varrho;":                          '\U000003F1',
-	"varsigma;":                        '\U000003C2',
-	"vartheta;":                        '\U000003D1',
-	"vartriangleleft;":                 '\U000022B2',
-	"vartriangleright;":                '\U000022B3',
-	"vcy;":                             '\U00000432',
-	"vdash;":                           '\U000022A2',
-	"vee;":                             '\U00002228',
-	"veebar;":                          '\U000022BB',
-	"veeeq;":                           '\U0000225A',
-	"vellip;":                          '\U000022EE',
-	"verbar;":                          '\U0000007C',
-	"vert;":                            '\U0000007C',
-	"vfr;":                             '\U0001D533',
-	"vltri;":                           '\U000022B2',
-	"vopf;":                            '\U0001D567',
-	"vprop;":                           '\U0000221D',
-	"vrtri;":                           '\U000022B3',
-	"vscr;":                            '\U0001D4CB',
-	"vzigzag;":                         '\U0000299A',
-	"wcirc;":                           '\U00000175',
-	"wedbar;":                          '\U00002A5F',
-	"wedge;":                           '\U00002227',
-	"wedgeq;":                          '\U00002259',
-	"weierp;":                          '\U00002118',
-	"wfr;":                             '\U0001D534',
-	"wopf;":                            '\U0001D568',
-	"wp;":                              '\U00002118',
-	"wr;":                              '\U00002240',
-	"wreath;":                          '\U00002240',
-	"wscr;":                            '\U0001D4CC',
-	"xcap;":                            '\U000022C2',
-	"xcirc;":                           '\U000025EF',
-	"xcup;":                            '\U000022C3',
-	"xdtri;":                           '\U000025BD',
-	"xfr;":                             '\U0001D535',
-	"xhArr;":                           '\U000027FA',
-	"xharr;":                           '\U000027F7',
-	"xi;":                              '\U000003BE',
-	"xlArr;":                           '\U000027F8',
-	"xlarr;":                           '\U000027F5',
-	"xmap;":                            '\U000027FC',
-	"xnis;":                            '\U000022FB',
-	"xodot;":                           '\U00002A00',
-	"xopf;":                            '\U0001D569',
-	"xoplus;":                          '\U00002A01',
-	"xotime;":                          '\U00002A02',
-	"xrArr;":                           '\U000027F9',
-	"xrarr;":                           '\U000027F6',
-	"xscr;":                            '\U0001D4CD',
-	"xsqcup;":                          '\U00002A06',
-	"xuplus;":                          '\U00002A04',
-	"xutri;":                           '\U000025B3',
-	"xvee;":                            '\U000022C1',
-	"xwedge;":                          '\U000022C0',
-	"yacute;":                          '\U000000FD',
-	"yacy;":                            '\U0000044F',
-	"ycirc;":                           '\U00000177',
-	"ycy;":                             '\U0000044B',
-	"yen;":                             '\U000000A5',
-	"yfr;":                             '\U0001D536',
-	"yicy;":                            '\U00000457',
-	"yopf;":                            '\U0001D56A',
-	"yscr;":                            '\U0001D4CE',
-	"yucy;":                            '\U0000044E',
-	"yuml;":                            '\U000000FF',
-	"zacute;":                          '\U0000017A',
-	"zcaron;":                          '\U0000017E',
-	"zcy;":                             '\U00000437',
-	"zdot;":                            '\U0000017C',
-	"zeetrf;":                          '\U00002128',
-	"zeta;":                            '\U000003B6',
-	"zfr;":                             '\U0001D537',
-	"zhcy;":                            '\U00000436',
-	"zigrarr;":                         '\U000021DD',
-	"zopf;":                            '\U0001D56B',
-	"zscr;":                            '\U0001D4CF',
-	"zwj;":                             '\U0000200D',
-	"zwnj;":                            '\U0000200C',
-	"AElig":                            '\U000000C6',
-	"AMP":                              '\U00000026',
-	"Aacute":                           '\U000000C1',
-	"Acirc":                            '\U000000C2',
-	"Agrave":                           '\U000000C0',
-	"Aring":                            '\U000000C5',
-	"Atilde":                           '\U000000C3',
-	"Auml":                             '\U000000C4',
-	"COPY":                             '\U000000A9',
-	"Ccedil":                           '\U000000C7',
-	"ETH":                              '\U000000D0',
-	"Eacute":                           '\U000000C9',
-	"Ecirc":                            '\U000000CA',
-	"Egrave":                           '\U000000C8',
-	"Euml":                             '\U000000CB',
-	"GT":                               '\U0000003E',
-	"Iacute":                           '\U000000CD',
-	"Icirc":                            '\U000000CE',
-	"Igrave":                           '\U000000CC',
-	"Iuml":                             '\U000000CF',
-	"LT":                               '\U0000003C',
-	"Ntilde":                           '\U000000D1',
-	"Oacute":                           '\U000000D3',
-	"Ocirc":                            '\U000000D4',
-	"Ograve":                           '\U000000D2',
-	"Oslash":                           '\U000000D8',
-	"Otilde":                           '\U000000D5',
-	"Ouml":                             '\U000000D6',
-	"QUOT":                             '\U00000022',
-	"REG":                              '\U000000AE',
-	"THORN":                            '\U000000DE',
-	"Uacute":                           '\U000000DA',
-	"Ucirc":                            '\U000000DB',
-	"Ugrave":                           '\U000000D9',
-	"Uuml":                             '\U000000DC',
-	"Yacute":                           '\U000000DD',
-	"aacute":                           '\U000000E1',
-	"acirc":                            '\U000000E2',
-	"acute":                            '\U000000B4',
-	"aelig":                            '\U000000E6',
-	"agrave":                           '\U000000E0',
-	"amp":                              '\U00000026',
-	"aring":                            '\U000000E5',
-	"atilde":                           '\U000000E3',
-	"auml":                             '\U000000E4',
-	"brvbar":                           '\U000000A6',
-	"ccedil":                           '\U000000E7',
-	"cedil":                            '\U000000B8',
-	"cent":                             '\U000000A2',
-	"copy":                             '\U000000A9',
-	"curren":                           '\U000000A4',
-	"deg":                              '\U000000B0',
-	"divide":                           '\U000000F7',
-	"eacute":                           '\U000000E9',
-	"ecirc":                            '\U000000EA',
-	"egrave":                           '\U000000E8',
-	"eth":                              '\U000000F0',
-	"euml":                             '\U000000EB',
-	"frac12":                           '\U000000BD',
-	"frac14":                           '\U000000BC',
-	"frac34":                           '\U000000BE',
-	"gt":                               '\U0000003E',
-	"iacute":                           '\U000000ED',
-	"icirc":                            '\U000000EE',
-	"iexcl":                            '\U000000A1',
-	"igrave":                           '\U000000EC',
-	"iquest":                           '\U000000BF',
-	"iuml":                             '\U000000EF',
-	"laquo":                            '\U000000AB',
-	"lt":                               '\U0000003C',
-	"macr":                             '\U000000AF',
-	"micro":                            '\U000000B5',
-	"middot":                           '\U000000B7',
-	"nbsp":                             '\U000000A0',
-	"not":                              '\U000000AC',
-	"ntilde":                           '\U000000F1',
-	"oacute":                           '\U000000F3',
-	"ocirc":                            '\U000000F4',
-	"ograve":                           '\U000000F2',
-	"ordf":                             '\U000000AA',
-	"ordm":                             '\U000000BA',
-	"oslash":                           '\U000000F8',
-	"otilde":                           '\U000000F5',
-	"ouml":                             '\U000000F6',
-	"para":                             '\U000000B6',
-	"plusmn":                           '\U000000B1',
-	"pound":                            '\U000000A3',
-	"quot":                             '\U00000022',
-	"raquo":                            '\U000000BB',
-	"reg":                              '\U000000AE',
-	"sect":                             '\U000000A7',
-	"shy":                              '\U000000AD',
-	"sup1":                             '\U000000B9',
-	"sup2":                             '\U000000B2',
-	"sup3":                             '\U000000B3',
-	"szlig":                            '\U000000DF',
-	"thorn":                            '\U000000FE',
-	"times":                            '\U000000D7',
-	"uacute":                           '\U000000FA',
-	"ucirc":                            '\U000000FB',
-	"ugrave":                           '\U000000F9',
-	"uml":                              '\U000000A8',
-	"uuml":                             '\U000000FC',
-	"yacute":                           '\U000000FD',
-	"yen":                              '\U000000A5',
-	"yuml":                             '\U000000FF',
+	"Cross;":                    '\U00002A2F',
+	"Cscr;":                     '\U0001D49E',
+	"Cup;":                      '\U000022D3',
+	"CupCap;":                   '\U0000224D',
+	"DD;":                       '\U00002145',
+	"DDotrahd;":                 '\U00002911',
+	"DJcy;":                     '\U00000402',
+	"DScy;":                     '\U00000405',
+	"DZcy;":                     '\U0000040F',
+	"Dagger;":                   '\U00002021',
+	"Darr;":                     '\U000021A1',
+	"Dashv;":                    '\U00002AE4',
+	"Dcaron;":                   '\U0000010E',
+	"Dcy;":                      '\U00000414',
+	"Del;":                      '\U00002207',
+	"Delta;":                    '\U00000394',
+	"Dfr;":                      '\U0001D507',
+	"DiacriticalAcute;":         '\U000000B4',
+	"DiacriticalDot;":           '\U000002D9',
+	"DiacriticalDoubleAcute;":   '\U000002DD',
+	"DiacriticalGrave;":         '\U00000060',
+	"DiacriticalTilde;":         '\U000002DC',
+	"Diamond;":                  '\U000022C4',
+	"DifferentialD;":            '\U00002146',
+	"Dopf;":                     '\U0001D53B',
+	"Dot;":                      '\U000000A8',
+	"DotDot;":                   '\U000020DC',
+	"DotEqual;":                 '\U00002250',
+	"DoubleContourIntegral;":    '\U0000222F',
+	"DoubleDot;":                '\U000000A8',
+	"DoubleDownArrow;":          '\U000021D3',
+	"DoubleLeftArrow;":          '\U000021D0',
+	"DoubleLeftRightArrow;":     '\U000021D4',
+	"DoubleLeftTee;":            '\U00002AE4',
+	"DoubleLongLeftArrow;":      '\U000027F8',
+	"DoubleLongLeftRightArrow;": '\U000027FA',
+	"DoubleLongRightArrow;":     '\U000027F9',
+	"DoubleRightArrow;":         '\U000021D2',
+	"DoubleRightTee;":           '\U000022A8',
+	"DoubleUpArrow;":            '\U000021D1',
+	"DoubleUpDownArrow;":        '\U000021D5',
+	"DoubleVerticalBar;":        '\U00002225',
+	"DownArrow;":                '\U00002193',
+	"DownArrowBar;":             '\U00002913',
+	"DownArrowUpArrow;":         '\U000021F5',
+	"DownBreve;":                '\U00000311',
+	"DownLeftRightVector;":      '\U00002950',
+	"DownLeftTeeVector;":        '\U0000295E',
+	"DownLeftVector;":           '\U000021BD',
+	"DownLeftVectorBar;":        '\U00002956',
+	"DownRightTeeVector;":       '\U0000295F',
+	"DownRightVector;":          '\U000021C1',
+	"DownRightVectorBar;":       '\U00002957',
+	"DownTee;":                  '\U000022A4',
+	"DownTeeArrow;":             '\U000021A7',
+	"Downarrow;":                '\U000021D3',
+	"Dscr;":                     '\U0001D49F',
+	"Dstrok;":                   '\U00000110',
+	"ENG;":                      '\U0000014A',
+	"ETH;":                      '\U000000D0',
+	"Eacute;":                   '\U000000C9',
+	"Ecaron;":                   '\U0000011A',
+	"Ecirc;":                    '\U000000CA',
+	"Ecy;":                      '\U0000042D',
+	"Edot;":                     '\U00000116',
+	"Efr;":                      '\U0001D508',
+	"Egrave;":                   '\U000000C8',
+	"Element;":                  '\U00002208',
+	"Emacr;":                    '\U00000112',
+	"EmptySmallSquare;":         '\U000025FB',
+	"EmptyVerySmallSquare;":     '\U000025AB',
+	"Eogon;":                    '\U00000118',
+	"Eopf;":                     '\U0001D53C',
+	"Epsilon;":                  '\U00000395',
+	"Equal;":                    '\U00002A75',
+	"EqualTilde;":               '\U00002242',
+	"Equilibrium;":              '\U000021CC',
+	"Escr;":                     '\U00002130',
+	"Esim;":                     '\U00002A73',
+	"Eta;":                      '\U00000397',
+	"Euml;":                     '\U000000CB',
+	"Exists;":                   '\U00002203',
+	"ExponentialE;":             '\U00002147',
+	"Fcy;":                      '\U00000424',
+	"Ffr;":                      '\U0001D509',
+	"FilledSmallSquare;":        '\U000025FC',
+	"FilledVerySmallSquare;":    '\U000025AA',
+	"Fopf;":                     '\U0001D53D',
+	"ForAll;":                   '\U00002200',
+	"Fouriertrf;":               '\U00002131',
+	"Fscr;":                     '\U00002131',
+	"GJcy;":                     '\U00000403',
+	"GT;":                       '\U0000003E',
+	"Gamma;":                    '\U00000393',
+	"Gammad;":                   '\U000003DC',
+	"Gbreve;":                   '\U0000011E',
+	"Gcedil;":                   '\U00000122',
+	"Gcirc;":                    '\U0000011C',
+	"Gcy;":                      '\U00000413',
+	"Gdot;":                     '\U00000120',
+	"Gfr;":                      '\U0001D50A',
+	"Gg;":                       '\U000022D9',
+	"Gopf;":                     '\U0001D53E',
+	"GreaterEqual;":             '\U00002265',
+	"GreaterEqualLess;":         '\U000022DB',
+	"GreaterFullEqual;":         '\U00002267',
+	"GreaterGreater;":           '\U00002AA2',
+	"GreaterLess;":              '\U00002277',
+	"GreaterSlantEqual;":        '\U00002A7E',
+	"GreaterTilde;":             '\U00002273',
+	"Gscr;":                     '\U0001D4A2',
+	"Gt;":                       '\U0000226B',
+	"HARDcy;":                   '\U0000042A',
+	"Hacek;":                    '\U000002C7',
+	"Hat;":                      '\U0000005E',
+	"Hcirc;":                    '\U00000124',
+	"Hfr;":                      '\U0000210C',
+	"HilbertSpace;":             '\U0000210B',
+	"Hopf;":                     '\U0000210D',
+	"HorizontalLine;":           '\U00002500',
+	"Hscr;":                     '\U0000210B',
+	"Hstrok;":                   '\U00000126',
+	"HumpDownHump;":             '\U0000224E',
+	"HumpEqual;":                '\U0000224F',
+	"IEcy;":                     '\U00000415',
+	"IJlig;":                    '\U00000132',
+	"IOcy;":                     '\U00000401',
+	"Iacute;":                   '\U000000CD',
+	"Icirc;":                    '\U000000CE',
+	"Icy;":                      '\U00000418',
+	"Idot;":                     '\U00000130',
+	"Ifr;":                      '\U00002111',
+	"Igrave;":                   '\U000000CC',
+	"Im;":                       '\U00002111',
+	"Imacr;":                    '\U0000012A',
+	"ImaginaryI;":               '\U00002148',
+	"Implies;":                  '\U000021D2',
+	"Int;":                      '\U0000222C',
+	"Integral;":                 '\U0000222B',
+	"Intersection;":             '\U000022C2',
+	"InvisibleComma;":           '\U00002063',
+	"InvisibleTimes;":           '\U00002062',
+	"Iogon;":                    '\U0000012E',
+	"Iopf;":                     '\U0001D540',
+	"Iota;":                     '\U00000399',
+	"Iscr;":                     '\U00002110',
+	"Itilde;":                   '\U00000128',
+	"Iukcy;":                    '\U00000406',
+	"Iuml;":                     '\U000000CF',
+	"Jcirc;":                    '\U00000134',
+	"Jcy;":                      '\U00000419',
+	"Jfr;":                      '\U0001D50D',
+	"Jopf;":                     '\U0001D541',
+	"Jscr;":                     '\U0001D4A5',
+	"Jsercy;":                   '\U00000408',
+	"Jukcy;":                    '\U00000404',
+	"KHcy;":                     '\U00000425',
+	"KJcy;":                     '\U0000040C',
+	"Kappa;":                    '\U0000039A',
+	"Kcedil;":                   '\U00000136',
+	"Kcy;":                      '\U0000041A',
+	"Kfr;":                      '\U0001D50E',
+	"Kopf;":                     '\U0001D542',
+	"Kscr;":                     '\U0001D4A6',
+	"LJcy;":                     '\U00000409',
+	"LT;":                       '\U0000003C',
+	"Lacute;":                   '\U00000139',
+	"Lambda;":                   '\U0000039B',
+	"Lang;":                     '\U000027EA',
+	"Laplacetrf;":               '\U00002112',
+	"Larr;":                     '\U0000219E',
+	"Lcaron;":                   '\U0000013D',
+	"Lcedil;":                   '\U0000013B',
+	"Lcy;":                      '\U0000041B',
+	"LeftAngleBracket;":         '\U000027E8',
+	"LeftArrow;":                '\U00002190',
+	"LeftArrowBar;":             '\U000021E4',
+	"LeftArrowRightArrow;":      '\U000021C6',
+	"LeftCeiling;":              '\U00002308',
+	"LeftDoubleBracket;":        '\U000027E6',
+	"LeftDownTeeVector;":        '\U00002961',
+	"LeftDownVector;":           '\U000021C3',
+	"LeftDownVectorBar;":        '\U00002959',
+	"LeftFloor;":                '\U0000230A',
+	"LeftRightArrow;":           '\U00002194',
+	"LeftRightVector;":          '\U0000294E',
+	"LeftTee;":                  '\U000022A3',
+	"LeftTeeArrow;":             '\U000021A4',
+	"LeftTeeVector;":            '\U0000295A',
+	"LeftTriangle;":             '\U000022B2',
+	"LeftTriangleBar;":          '\U000029CF',
+	"LeftTriangleEqual;":        '\U000022B4',
+	"LeftUpDownVector;":         '\U00002951',
+	"LeftUpTeeVector;":          '\U00002960',
+	"LeftUpVector;":             '\U000021BF',
+	"LeftUpVectorBar;":          '\U00002958',
+	"LeftVector;":               '\U000021BC',
+	"LeftVectorBar;":            '\U00002952',
+	"Leftarrow;":                '\U000021D0',
+	"Leftrightarrow;":           '\U000021D4',
+	"LessEqualGreater;":         '\U000022DA',
+	"LessFullEqual;":            '\U00002266',
+	"LessGreater;":              '\U00002276',
+	"LessLess;":                 '\U00002AA1',
+	"LessSlantEqual;":           '\U00002A7D',
+	"LessTilde;":                '\U00002272',
+	"Lfr;":                      '\U0001D50F',
+	"Ll;":                       '\U000022D8',
+	"Lleftarrow;":               '\U000021DA',
+	"Lmidot;":                   '\U0000013F',
+	"LongLeftArrow;":            '\U000027F5',
+	"LongLeftRightArrow;":       '\U000027F7',
+	"LongRightArrow;":           '\U000027F6',
+	"Longleftarrow;":            '\U000027F8',
+	"Longleftrightarrow;":       '\U000027FA',
+	"Longrightarrow;":           '\U000027F9',
+	"Lopf;":                     '\U0001D543',
+	"LowerLeftArrow;":           '\U00002199',
+	"LowerRightArrow;":          '\U00002198',
+	"Lscr;":                     '\U00002112',
+	"Lsh;":                      '\U000021B0',
+	"Lstrok;":                   '\U00000141',
+	"Lt;":                       '\U0000226A',
+	"Map;":                      '\U00002905',
+	"Mcy;":                      '\U0000041C',
+	"MediumSpace;":              '\U0000205F',
+	"Mellintrf;":                '\U00002133',
+	"Mfr;":                      '\U0001D510',
+	"MinusPlus;":                '\U00002213',
+	"Mopf;":                     '\U0001D544',
+	"Mscr;":                     '\U00002133',
+	"Mu;":                       '\U0000039C',
+	"NJcy;":                     '\U0000040A',
+	"Nacute;":                   '\U00000143',
+	"Ncaron;":                   '\U00000147',
+	"Ncedil;":                   '\U00000145',
+	"Ncy;":                      '\U0000041D',
+	"NegativeMediumSpace;":      '\U0000200B',
+	"NegativeThickSpace;":       '\U0000200B',
+	"NegativeThinSpace;":        '\U0000200B',
+	"NegativeVeryThinSpace;":    '\U0000200B',
+	"NestedGreaterGreater;":     '\U0000226B',
+	"NestedLessLess;":           '\U0000226A',
+	"NewLine;":                  '\U0000000A',
+	"Nfr;":                      '\U0001D511',
+	"NoBreak;":                  '\U00002060',
+	"NonBreakingSpace;":         '\U000000A0',
+	"Nopf;":                     '\U00002115',
+	"Not;":                      '\U00002AEC',
+	"NotCongruent;":             '\U00002262',
+	"NotCupCap;":                '\U0000226D',
+	"NotDoubleVerticalBar;":     '\U00002226',
+	"NotElement;":               '\U00002209',
+	"NotEqual;":                 '\U00002260',
+	"NotExists;":                '\U00002204',
+	"NotGreater;":               '\U0000226F',
+	"NotGreaterEqual;":          '\U00002271',
+	"NotGreaterLess;":           '\U00002279',
+	"NotGreaterTilde;":          '\U00002275',
+	"NotLeftTriangle;":          '\U000022EA',
+	"NotLeftTriangleEqual;":     '\U000022EC',
+	"NotLess;":                  '\U0000226E',
+	"NotLessEqual;":             '\U00002270',
+	"NotLessGreater;":           '\U00002278',
+	"NotLessTilde;":             '\U00002274',
+	"NotPrecedes;":              '\U00002280',
+	"NotPrecedesSlantEqual;":    '\U000022E0',
+	"NotReverseElement;":        '\U0000220C',
+	"NotRightTriangle;":         '\U000022EB',
+	"NotRightTriangleEqual;":    '\U000022ED',
+	"NotSquareSubsetEqual;":     '\U000022E2',
+	"NotSquareSupersetEqual;":   '\U000022E3',
+	"NotSubsetEqual;":           '\U00002288',
+	"NotSucceeds;":              '\U00002281',
+	"NotSucceedsSlantEqual;":    '\U000022E1',
+	"NotSupersetEqual;":         '\U00002289',
+	"NotTilde;":                 '\U00002241',
+	"NotTildeEqual;":            '\U00002244',
+	"NotTildeFullEqual;":        '\U00002247',
+	"NotTildeTilde;":            '\U00002249',
+	"NotVerticalBar;":           '\U00002224',
+	"Nscr;":                     '\U0001D4A9',
+	"Ntilde;":                   '\U000000D1',
+	"Nu;":                       '\U0000039D',
+	"OElig;":                    '\U00000152',
+	"Oacute;":                   '\U000000D3',
+	"Ocirc;":                    '\U000000D4',
+	"Ocy;":                      '\U0000041E',
+	"Odblac;":                   '\U00000150',
+	"Ofr;":                      '\U0001D512',
+	"Ograve;":                   '\U000000D2',
+	"Omacr;":                    '\U0000014C',
+	"Omega;":                    '\U000003A9',
+	"Omicron;":                  '\U0000039F',
+	"Oopf;":                     '\U0001D546',
+	"OpenCurlyDoubleQuote;":     '\U0000201C',
+	"OpenCurlyQuote;":           '\U00002018',
+	"Or;":                       '\U00002A54',
+	"Oscr;":                     '\U0001D4AA',
+	"Oslash;":                   '\U000000D8',
+	"Otilde;":                   '\U000000D5',
+	"Otimes;":                   '\U00002A37',
+	"Ouml;":                     '\U000000D6',
+	"OverBar;":                  '\U0000203E',
+	"OverBrace;":                '\U000023DE',
+	"OverBracket;":              '\U000023B4',
+	"OverParenthesis;":          '\U000023DC',
+	"PartialD;":                 '\U00002202',
+	"Pcy;":                      '\U0000041F',
+	"Pfr;":                      '\U0001D513',
+	"Phi;":                      '\U000003A6',
+	"Pi;":                       '\U000003A0',
+	"PlusMinus;":                '\U000000B1',
+	"Poincareplane;":            '\U0000210C',
+	"Popf;":                     '\U00002119',
+	"Pr;":                       '\U00002ABB',
+	"Precedes;":                 '\U0000227A',
+	"PrecedesEqual;":            '\U00002AAF',
+	"PrecedesSlantEqual;":       '\U0000227C',
+	"PrecedesTilde;":            '\U0000227E',
+	"Prime;":                    '\U00002033',
+	"Product;":                  '\U0000220F',
+	"Proportion;":               '\U00002237',
+	"Proportional;":             '\U0000221D',
+	"Pscr;":                     '\U0001D4AB',
+	"Psi;":                      '\U000003A8',
+	"QUOT;":                     '\U00000022',
+	"Qfr;":                      '\U0001D514',
+	"Qopf;":                     '\U0000211A',
+	"Qscr;":                     '\U0001D4AC',
+	"RBarr;":                    '\U00002910',
+	"REG;":                      '\U000000AE',
+	"Racute;":                   '\U00000154',
+	"Rang;":                     '\U000027EB',
+	"Rarr;":                     '\U000021A0',
+	"Rarrtl;":                   '\U00002916',
+	"Rcaron;":                   '\U00000158',
+	"Rcedil;":                   '\U00000156',
+	"Rcy;":                      '\U00000420',
+	"Re;":                       '\U0000211C',
+	"ReverseElement;":           '\U0000220B',
+	"ReverseEquilibrium;":       '\U000021CB',
+	"ReverseUpEquilibrium;":     '\U0000296F',
+	"Rfr;":                      '\U0000211C',
+	"Rho;":                      '\U000003A1',
+	"RightAngleBracket;":        '\U000027E9',
+	"RightArrow;":               '\U00002192',
+	"RightArrowBar;":            '\U000021E5',
+	"RightArrowLeftArrow;":      '\U000021C4',
+	"RightCeiling;":             '\U00002309',
+	"RightDoubleBracket;":       '\U000027E7',
+	"RightDownTeeVector;":       '\U0000295D',
+	"RightDownVector;":          '\U000021C2',
+	"RightDownVectorBar;":       '\U00002955',
+	"RightFloor;":               '\U0000230B',
+	"RightTee;":                 '\U000022A2',
+	"RightTeeArrow;":            '\U000021A6',
+	"RightTeeVector;":           '\U0000295B',
+	"RightTriangle;":            '\U000022B3',
+	"RightTriangleBar;":         '\U000029D0',
+	"RightTriangleEqual;":       '\U000022B5',
+	"RightUpDownVector;":        '\U0000294F',
+	"RightUpTeeVector;":         '\U0000295C',
+	"RightUpVector;":            '\U000021BE',
+	"RightUpVectorBar;":         '\U00002954',
+	"RightVector;":              '\U000021C0',
+	"RightVectorBar;":           '\U00002953',
+	"Rightarrow;":               '\U000021D2',
+	"Ropf;":                     '\U0000211D',
+	"RoundImplies;":             '\U00002970',
+	"Rrightarrow;":              '\U000021DB',
+	"Rscr;":                     '\U0000211B',
+	"Rsh;":                      '\U000021B1',
+	"RuleDelayed;":              '\U000029F4',
+	"SHCHcy;":                   '\U00000429',
+	"SHcy;":                     '\U00000428',
+	"SOFTcy;":                   '\U0000042C',
+	"Sacute;":                   '\U0000015A',
+	"Sc;":                       '\U00002ABC',
+	"Scaron;":                   '\U00000160',
+	"Scedil;":                   '\U0000015E',
+	"Scirc;":                    '\U0000015C',
+	"Scy;":                      '\U00000421',
+	"Sfr;":                      '\U0001D516',
+	"ShortDownArrow;":           '\U00002193',
+	"ShortLeftArrow;":           '\U00002190',
+	"ShortRightArrow;":          '\U00002192',
+	"ShortUpArrow;":             '\U00002191',
+	"Sigma;":                    '\U000003A3',
+	"SmallCircle;":              '\U00002218',
+	"Sopf;":                     '\U0001D54A',
+	"Sqrt;":                     '\U0000221A',
+	"Square;":                   '\U000025A1',
+	"SquareIntersection;":       '\U00002293',
+	"SquareSubset;":             '\U0000228F',
+	"SquareSubsetEqual;":        '\U00002291',
+	"SquareSuperset;":           '\U00002290',
+	"SquareSupersetEqual;":      '\U00002292',
+	"SquareUnion;":              '\U00002294',
+	"Sscr;":                     '\U0001D4AE',
+	"Star;":                     '\U000022C6',
+	"Sub;":                      '\U000022D0',
+	"Subset;":                   '\U000022D0',
+	"SubsetEqual;":              '\U00002286',
+	"Succeeds;":                 '\U0000227B',
+	"SucceedsEqual;":            '\U00002AB0',
+	"SucceedsSlantEqual;":       '\U0000227D',
+	"SucceedsTilde;":            '\U0000227F',
+	"SuchThat;":                 '\U0000220B',
+	"Sum;":                      '\U00002211',
+	"Sup;":                      '\U000022D1',
+	"Superset;":                 '\U00002283',
+	"SupersetEqual;":            '\U00002287',
+	"Supset;":                   '\U000022D1',
+	"THORN;":                    '\U000000DE',
+	"TRADE;":                    '\U00002122',
+	"TSHcy;":                    '\U0000040B',
+	"TScy;":                     '\U00000426',
+	"Tab;":                      '\U00000009',
+	"Tau;":                      '\U000003A4',
+	"Tcaron;":                   '\U00000164',
+	"Tcedil;":                   '\U00000162',
+	"Tcy;":                      '\U00000422',
+	"Tfr;":                      '\U0001D517',
+	"Therefore;":                '\U00002234',
+	"Theta;":                    '\U00000398',
+	"ThinSpace;":                '\U00002009',
+	"Tilde;":                    '\U0000223C',
+	"TildeEqual;":               '\U00002243',
+	"TildeFullEqual;":           '\U00002245',
+	"TildeTilde;":               '\U00002248',
+	"Topf;":                     '\U0001D54B',
+	"TripleDot;":                '\U000020DB',
+	"Tscr;":                     '\U0001D4AF',
+	"Tstrok;":                   '\U00000166',
+	"Uacute;":                   '\U000000DA',
+	"Uarr;":                     '\U0000219F',
+	"Uarrocir;":                 '\U00002949',
+	"Ubrcy;":                    '\U0000040E',
+	"Ubreve;":                   '\U0000016C',
+	"Ucirc;":                    '\U000000DB',
+	"Ucy;":                      '\U00000423',
+	"Udblac;":                   '\U00000170',
+	"Ufr;":                      '\U0001D518',
+	"Ugrave;":                   '\U000000D9',
+	"Umacr;":                    '\U0000016A',
+	"UnderBar;":                 '\U0000005F',
+	"UnderBrace;":               '\U000023DF',
+	"UnderBracket;":             '\U000023B5',
+	"UnderParenthesis;":         '\U000023DD',
+	"Union;":                    '\U000022C3',
+	"UnionPlus;":                '\U0000228E',
+	"Uogon;":                    '\U00000172',
+	"Uopf;":                     '\U0001D54C',
+	"UpArrow;":                  '\U00002191',
+	"UpArrowBar;":               '\U00002912',
+	"UpArrowDownArrow;":         '\U000021C5',
+	"UpDownArrow;":              '\U00002195',
+	"UpEquilibrium;":            '\U0000296E',
+	"UpTee;":                    '\U000022A5',
+	"UpTeeArrow;":               '\U000021A5',
+	"Uparrow;":                  '\U000021D1',
+	"Updownarrow;":              '\U000021D5',
+	"UpperLeftArrow;":           '\U00002196',
+	"UpperRightArrow;":          '\U00002197',
+	"Upsi;":                     '\U000003D2',
+	"Upsilon;":                  '\U000003A5',
+	"Uring;":                    '\U0000016E',
+	"Uscr;":                     '\U0001D4B0',
+	"Utilde;":                   '\U00000168',
+	"Uuml;":                     '\U000000DC',
+	"VDash;":                    '\U000022AB',
+	"Vbar;":                     '\U00002AEB',
+	"Vcy;":                      '\U00000412',
+	"Vdash;":                    '\U000022A9',
+	"Vdashl;":                   '\U00002AE6',
+	"Vee;":                      '\U000022C1',
+	"Verbar;":                   '\U00002016',
+	"Vert;":                     '\U00002016',
+	"VerticalBar;":              '\U00002223',
+	"VerticalLine;":             '\U0000007C',
+	"VerticalSeparator;":        '\U00002758',
+	"VerticalTilde;":            '\U00002240',
+	"VeryThinSpace;":            '\U0000200A',
+	"Vfr;":                      '\U0001D519',
+	"Vopf;":                     '\U0001D54D',
+	"Vscr;":                     '\U0001D4B1',
+	"Vvdash;":                   '\U000022AA',
+	"Wcirc;":                    '\U00000174',
+	"Wedge;":                    '\U000022C0',
+	"Wfr;":                      '\U0001D51A',
+	"Wopf;":                     '\U0001D54E',
+	"Wscr;":                     '\U0001D4B2',
+	"Xfr;":                      '\U0001D51B',
+	"Xi;":                       '\U0000039E',
+	"Xopf;":                     '\U0001D54F',
+	"Xscr;":                     '\U0001D4B3',
+	"YAcy;":                     '\U0000042F',
+	"YIcy;":                     '\U00000407',
+	"YUcy;":                     '\U0000042E',
+	"Yacute;":                   '\U000000DD',
+	"Ycirc;":                    '\U00000176',
+	"Ycy;":                      '\U0000042B',
+	"Yfr;":                      '\U0001D51C',
+	"Yopf;":                     '\U0001D550',
+	"Yscr;":                     '\U0001D4B4',
+	"Yuml;":                     '\U00000178',
+	"ZHcy;":                     '\U00000416',
+	"Zacute;":                   '\U00000179',
+	"Zcaron;":                   '\U0000017D',
+	"Zcy;":                      '\U00000417',
+	"Zdot;":                     '\U0000017B',
+	"ZeroWidthSpace;":           '\U0000200B',
+	"Zeta;":                     '\U00000396',
+	"Zfr;":                      '\U00002128',
+	"Zopf;":                     '\U00002124',
+	"Zscr;":                     '\U0001D4B5',
+	"aacute;":                   '\U000000E1',
+	"abreve;":                   '\U00000103',
+	"ac;":                       '\U0000223E',
+	"acd;":                      '\U0000223F',
+	"acirc;":                    '\U000000E2',
+	"acute;":                    '\U000000B4',
+	"acy;":                      '\U00000430',
+	"aelig;":                    '\U000000E6',
+	"af;":                       '\U00002061',
+	"afr;":                      '\U0001D51E',
+	"agrave;":                   '\U000000E0',
+	"alefsym;":                  '\U00002135',
+	"aleph;":                    '\U00002135',
+	"alpha;":                    '\U000003B1',
+	"amacr;":                    '\U00000101',
+	"amalg;":                    '\U00002A3F',
+	"amp;":                      '\U00000026',
+	"and;":                      '\U00002227',
+	"andand;":                   '\U00002A55',
+	"andd;":                     '\U00002A5C',
+	"andslope;":                 '\U00002A58',
+	"andv;":                     '\U00002A5A',
+	"ang;":                      '\U00002220',
+	"ange;":                     '\U000029A4',
+	"angle;":                    '\U00002220',
+	"angmsd;":                   '\U00002221',
+	"angmsdaa;":                 '\U000029A8',
+	"angmsdab;":                 '\U000029A9',
+	"angmsdac;":                 '\U000029AA',
+	"angmsdad;":                 '\U000029AB',
+	"angmsdae;":                 '\U000029AC',
+	"angmsdaf;":                 '\U000029AD',
+	"angmsdag;":                 '\U000029AE',
+	"angmsdah;":                 '\U000029AF',
+	"angrt;":                    '\U0000221F',
+	"angrtvb;":                  '\U000022BE',
+	"angrtvbd;":                 '\U0000299D',
+	"angsph;":                   '\U00002222',
+	"angst;":                    '\U000000C5',
+	"angzarr;":                  '\U0000237C',
+	"aogon;":                    '\U00000105',
+	"aopf;":                     '\U0001D552',
+	"ap;":                       '\U00002248',
+	"apE;":                      '\U00002A70',
+	"apacir;":                   '\U00002A6F',
+	"ape;":                      '\U0000224A',
+	"apid;":                     '\U0000224B',
+	"apos;":                     '\U00000027',
+	"approx;":                   '\U00002248',
+	"approxeq;":                 '\U0000224A',
+	"aring;":                    '\U000000E5',
+	"ascr;":                     '\U0001D4B6',
+	"ast;":                      '\U0000002A',
+	"asymp;":                    '\U00002248',
+	"asympeq;":                  '\U0000224D',
+	"atilde;":                   '\U000000E3',
+	"auml;":                     '\U000000E4',
+	"awconint;":                 '\U00002233',
+	"awint;":                    '\U00002A11',
+	"bNot;":                     '\U00002AED',
+	"backcong;":                 '\U0000224C',
+	"backepsilon;":              '\U000003F6',
+	"backprime;":                '\U00002035',
+	"backsim;":                  '\U0000223D',
+	"backsimeq;":                '\U000022CD',
+	"barvee;":                   '\U000022BD',
+	"barwed;":                   '\U00002305',
+	"barwedge;":                 '\U00002305',
+	"bbrk;":                     '\U000023B5',
+	"bbrktbrk;":                 '\U000023B6',
+	"bcong;":                    '\U0000224C',
+	"bcy;":                      '\U00000431',
+	"bdquo;":                    '\U0000201E',
+	"becaus;":                   '\U00002235',
+	"because;":                  '\U00002235',
+	"bemptyv;":                  '\U000029B0',
+	"bepsi;":                    '\U000003F6',
+	"bernou;":                   '\U0000212C',
+	"beta;":                     '\U000003B2',
+	"beth;":                     '\U00002136',
+	"between;":                  '\U0000226C',
+	"bfr;":                      '\U0001D51F',
+	"bigcap;":                   '\U000022C2',
+	"bigcirc;":                  '\U000025EF',
+	"bigcup;":                   '\U000022C3',
+	"bigodot;":                  '\U00002A00',
+	"bigoplus;":                 '\U00002A01',
+	"bigotimes;":                '\U00002A02',
+	"bigsqcup;":                 '\U00002A06',
+	"bigstar;":                  '\U00002605',
+	"bigtriangledown;":          '\U000025BD',
+	"bigtriangleup;":            '\U000025B3',
+	"biguplus;":                 '\U00002A04',
+	"bigvee;":                   '\U000022C1',
+	"bigwedge;":                 '\U000022C0',
+	"bkarow;":                   '\U0000290D',
+	"blacklozenge;":             '\U000029EB',
+	"blacksquare;":              '\U000025AA',
+	"blacktriangle;":            '\U000025B4',
+	"blacktriangledown;":        '\U000025BE',
+	"blacktriangleleft;":        '\U000025C2',
+	"blacktriangleright;":       '\U000025B8',
+	"blank;":                    '\U00002423',
+	"blk12;":                    '\U00002592',
+	"blk14;":                    '\U00002591',
+	"blk34;":                    '\U00002593',
+	"block;":                    '\U00002588',
+	"bnot;":                     '\U00002310',
+	"bopf;":                     '\U0001D553',
+	"bot;":                      '\U000022A5',
+	"bottom;":                   '\U000022A5',
+	"bowtie;":                   '\U000022C8',
+	"boxDL;":                    '\U00002557',
+	"boxDR;":                    '\U00002554',
+	"boxDl;":                    '\U00002556',
+	"boxDr;":                    '\U00002553',
+	"boxH;":                     '\U00002550',
+	"boxHD;":                    '\U00002566',
+	"boxHU;":                    '\U00002569',
+	"boxHd;":                    '\U00002564',
+	"boxHu;":                    '\U00002567',
+	"boxUL;":                    '\U0000255D',
+	"boxUR;":                    '\U0000255A',
+	"boxUl;":                    '\U0000255C',
+	"boxUr;":                    '\U00002559',
+	"boxV;":                     '\U00002551',
+	"boxVH;":                    '\U0000256C',
+	"boxVL;":                    '\U00002563',
+	"boxVR;":                    '\U00002560',
+	"boxVh;":                    '\U0000256B',
+	"boxVl;":                    '\U00002562',
+	"boxVr;":                    '\U0000255F',
+	"boxbox;":                   '\U000029C9',
+	"boxdL;":                    '\U00002555',
+	"boxdR;":                    '\U00002552',
+	"boxdl;":                    '\U00002510',
+	"boxdr;":                    '\U0000250C',
+	"boxh;":                     '\U00002500',
+	"boxhD;":                    '\U00002565',
+	"boxhU;":                    '\U00002568',
+	"boxhd;":                    '\U0000252C',
+	"boxhu;":                    '\U00002534',
+	"boxminus;":                 '\U0000229F',
+	"boxplus;":                  '\U0000229E',
+	"boxtimes;":                 '\U000022A0',
+	"boxuL;":                    '\U0000255B',
+	"boxuR;":                    '\U00002558',
+	"boxul;":                    '\U00002518',
+	"boxur;":                    '\U00002514',
+	"boxv;":                     '\U00002502',
+	"boxvH;":                    '\U0000256A',
+	"boxvL;":                    '\U00002561',
+	"boxvR;":                    '\U0000255E',
+	"boxvh;":                    '\U0000253C',
+	"boxvl;":                    '\U00002524',
+	"boxvr;":                    '\U0000251C',
+	"bprime;":                   '\U00002035',
+	"breve;":                    '\U000002D8',
+	"brvbar;":                   '\U000000A6',
+	"bscr;":                     '\U0001D4B7',
+	"bsemi;":                    '\U0000204F',
+	"bsim;":                     '\U0000223D',
+	"bsime;":                    '\U000022CD',
+	"bsol;":                     '\U0000005C',
+	"bsolb;":                    '\U000029C5',
+	"bsolhsub;":                 '\U000027C8',
+	"bull;":                     '\U00002022',
+	"bullet;":                   '\U00002022',
+	"bump;":                     '\U0000224E',
+	"bumpE;":                    '\U00002AAE',
+	"bumpe;":                    '\U0000224F',
+	"bumpeq;":                   '\U0000224F',
+	"cacute;":                   '\U00000107',
+	"cap;":                      '\U00002229',
+	"capand;":                   '\U00002A44',
+	"capbrcup;":                 '\U00002A49',
+	"capcap;":                   '\U00002A4B',
+	"capcup;":                   '\U00002A47',
+	"capdot;":                   '\U00002A40',
+	"caret;":                    '\U00002041',
+	"caron;":                    '\U000002C7',
+	"ccaps;":                    '\U00002A4D',
+	"ccaron;":                   '\U0000010D',
+	"ccedil;":                   '\U000000E7',
+	"ccirc;":                    '\U00000109',
+	"ccups;":                    '\U00002A4C',
+	"ccupssm;":                  '\U00002A50',
+	"cdot;":                     '\U0000010B',
+	"cedil;":                    '\U000000B8',
+	"cemptyv;":                  '\U000029B2',
+	"cent;":                     '\U000000A2',
+	"centerdot;":                '\U000000B7',
+	"cfr;":                      '\U0001D520',
+	"chcy;":                     '\U00000447',
+	"check;":                    '\U00002713',
+	"checkmark;":                '\U00002713',
+	"chi;":                      '\U000003C7',
+	"cir;":                      '\U000025CB',
+	"cirE;":                     '\U000029C3',
+	"circ;":                     '\U000002C6',
+	"circeq;":                   '\U00002257',
+	"circlearrowleft;":          '\U000021BA',
+	"circlearrowright;":         '\U000021BB',
+	"circledR;":                 '\U000000AE',
+	"circledS;":                 '\U000024C8',
+	"circledast;":               '\U0000229B',
+	"circledcirc;":              '\U0000229A',
+	"circleddash;":              '\U0000229D',
+	"cire;":                     '\U00002257',
+	"cirfnint;":                 '\U00002A10',
+	"cirmid;":                   '\U00002AEF',
+	"cirscir;":                  '\U000029C2',
+	"clubs;":                    '\U00002663',
+	"clubsuit;":                 '\U00002663',
+	"colon;":                    '\U0000003A',
+	"colone;":                   '\U00002254',
+	"coloneq;":                  '\U00002254',
+	"comma;":                    '\U0000002C',
+	"commat;":                   '\U00000040',
+	"comp;":                     '\U00002201',
+	"compfn;":                   '\U00002218',
+	"complement;":               '\U00002201',
+	"complexes;":                '\U00002102',
+	"cong;":                     '\U00002245',
+	"congdot;":                  '\U00002A6D',
+	"conint;":                   '\U0000222E',
+	"copf;":                     '\U0001D554',
+	"coprod;":                   '\U00002210',
+	"copy;":                     '\U000000A9',
+	"copysr;":                   '\U00002117',
+	"crarr;":                    '\U000021B5',
+	"cross;":                    '\U00002717',
+	"cscr;":                     '\U0001D4B8',
+	"csub;":                     '\U00002ACF',
+	"csube;":                    '\U00002AD1',
+	"csup;":                     '\U00002AD0',
+	"csupe;":                    '\U00002AD2',
+	"ctdot;":                    '\U000022EF',
+	"cudarrl;":                  '\U00002938',
+	"cudarrr;":                  '\U00002935',
+	"cuepr;":                    '\U000022DE',
+	"cuesc;":                    '\U000022DF',
+	"cularr;":                   '\U000021B6',
+	"cularrp;":                  '\U0000293D',
+	"cup;":                      '\U0000222A',
+	"cupbrcap;":                 '\U00002A48',
+	"cupcap;":                   '\U00002A46',
+	"cupcup;":                   '\U00002A4A',
+	"cupdot;":                   '\U0000228D',
+	"cupor;":                    '\U00002A45',
+	"curarr;":                   '\U000021B7',
+	"curarrm;":                  '\U0000293C',
+	"curlyeqprec;":              '\U000022DE',
+	"curlyeqsucc;":              '\U000022DF',
+	"curlyvee;":                 '\U000022CE',
+	"curlywedge;":               '\U000022CF',
+	"curren;":                   '\U000000A4',
+	"curvearrowleft;":           '\U000021B6',
+	"curvearrowright;":          '\U000021B7',
+	"cuvee;":                    '\U000022CE',
+	"cuwed;":                    '\U000022CF',
+	"cwconint;":                 '\U00002232',
+	"cwint;":                    '\U00002231',
+	"cylcty;":                   '\U0000232D',
+	"dArr;":                     '\U000021D3',
+	"dHar;":                     '\U00002965',
+	"dagger;":                   '\U00002020',
+	"daleth;":                   '\U00002138',
+	"darr;":                     '\U00002193',
+	"dash;":                     '\U00002010',
+	"dashv;":                    '\U000022A3',
+	"dbkarow;":                  '\U0000290F',
+	"dblac;":                    '\U000002DD',
+	"dcaron;":                   '\U0000010F',
+	"dcy;":                      '\U00000434',
+	"dd;":                       '\U00002146',
+	"ddagger;":                  '\U00002021',
+	"ddarr;":                    '\U000021CA',
+	"ddotseq;":                  '\U00002A77',
+	"deg;":                      '\U000000B0',
+	"delta;":                    '\U000003B4',
+	"demptyv;":                  '\U000029B1',
+	"dfisht;":                   '\U0000297F',
+	"dfr;":                      '\U0001D521',
+	"dharl;":                    '\U000021C3',
+	"dharr;":                    '\U000021C2',
+	"diam;":                     '\U000022C4',
+	"diamond;":                  '\U000022C4',
+	"diamondsuit;":              '\U00002666',
+	"diams;":                    '\U00002666',
+	"die;":                      '\U000000A8',
+	"digamma;":                  '\U000003DD',
+	"disin;":                    '\U000022F2',
+	"div;":                      '\U000000F7',
+	"divide;":                   '\U000000F7',
+	"divideontimes;":            '\U000022C7',
+	"divonx;":                   '\U000022C7',
+	"djcy;":                     '\U00000452',
+	"dlcorn;":                   '\U0000231E',
+	"dlcrop;":                   '\U0000230D',
+	"dollar;":                   '\U00000024',
+	"dopf;":                     '\U0001D555',
+	"dot;":                      '\U000002D9',
+	"doteq;":                    '\U00002250',
+	"doteqdot;":                 '\U00002251',
+	"dotminus;":                 '\U00002238',
+	"dotplus;":                  '\U00002214',
+	"dotsquare;":                '\U000022A1',
+	"doublebarwedge;":           '\U00002306',
+	"downarrow;":                '\U00002193',
+	"downdownarrows;":           '\U000021CA',
+	"downharpoonleft;":          '\U000021C3',
+	"downharpoonright;":         '\U000021C2',
+	"drbkarow;":                 '\U00002910',
+	"drcorn;":                   '\U0000231F',
+	"drcrop;":                   '\U0000230C',
+	"dscr;":                     '\U0001D4B9',
+	"dscy;":                     '\U00000455',
+	"dsol;":                     '\U000029F6',
+	"dstrok;":                   '\U00000111',
+	"dtdot;":                    '\U000022F1',
+	"dtri;":                     '\U000025BF',
+	"dtrif;":                    '\U000025BE',
+	"duarr;":                    '\U000021F5',
+	"duhar;":                    '\U0000296F',
+	"dwangle;":                  '\U000029A6',
+	"dzcy;":                     '\U0000045F',
+	"dzigrarr;":                 '\U000027FF',
+	"eDDot;":                    '\U00002A77',
+	"eDot;":                     '\U00002251',
+	"eacute;":                   '\U000000E9',
+	"easter;":                   '\U00002A6E',
+	"ecaron;":                   '\U0000011B',
+	"ecir;":                     '\U00002256',
+	"ecirc;":                    '\U000000EA',
+	"ecolon;":                   '\U00002255',
+	"ecy;":                      '\U0000044D',
+	"edot;":                     '\U00000117',
+	"ee;":                       '\U00002147',
+	"efDot;":                    '\U00002252',
+	"efr;":                      '\U0001D522',
+	"eg;":                       '\U00002A9A',
+	"egrave;":                   '\U000000E8',
+	"egs;":                      '\U00002A96',
+	"egsdot;":                   '\U00002A98',
+	"el;":                       '\U00002A99',
+	"elinters;":                 '\U000023E7',
+	"ell;":                      '\U00002113',
+	"els;":                      '\U00002A95',
+	"elsdot;":                   '\U00002A97',
+	"emacr;":                    '\U00000113',
+	"empty;":                    '\U00002205',
+	"emptyset;":                 '\U00002205',
+	"emptyv;":                   '\U00002205',
+	"emsp;":                     '\U00002003',
+	"emsp13;":                   '\U00002004',
+	"emsp14;":                   '\U00002005',
+	"eng;":                      '\U0000014B',
+	"ensp;":                     '\U00002002',
+	"eogon;":                    '\U00000119',
+	"eopf;":                     '\U0001D556',
+	"epar;":                     '\U000022D5',
+	"eparsl;":                   '\U000029E3',
+	"eplus;":                    '\U00002A71',
+	"epsi;":                     '\U000003B5',
+	"epsilon;":                  '\U000003B5',
+	"epsiv;":                    '\U000003F5',
+	"eqcirc;":                   '\U00002256',
+	"eqcolon;":                  '\U00002255',
+	"eqsim;":                    '\U00002242',
+	"eqslantgtr;":               '\U00002A96',
+	"eqslantless;":              '\U00002A95',
+	"equals;":                   '\U0000003D',
+	"equest;":                   '\U0000225F',
+	"equiv;":                    '\U00002261',
+	"equivDD;":                  '\U00002A78',
+	"eqvparsl;":                 '\U000029E5',
+	"erDot;":                    '\U00002253',
+	"erarr;":                    '\U00002971',
+	"escr;":                     '\U0000212F',
+	"esdot;":                    '\U00002250',
+	"esim;":                     '\U00002242',
+	"eta;":                      '\U000003B7',
+	"eth;":                      '\U000000F0',
+	"euml;":                     '\U000000EB',
+	"euro;":                     '\U000020AC',
+	"excl;":                     '\U00000021',
+	"exist;":                    '\U00002203',
+	"expectation;":              '\U00002130',
+	"exponentiale;":             '\U00002147',
+	"fallingdotseq;":            '\U00002252',
+	"fcy;":                      '\U00000444',
+	"female;":                   '\U00002640',
+	"ffilig;":                   '\U0000FB03',
+	"fflig;":                    '\U0000FB00',
+	"ffllig;":                   '\U0000FB04',
+	"ffr;":                      '\U0001D523',
+	"filig;":                    '\U0000FB01',
+	"flat;":                     '\U0000266D',
+	"fllig;":                    '\U0000FB02',
+	"fltns;":                    '\U000025B1',
+	"fnof;":                     '\U00000192',
+	"fopf;":                     '\U0001D557',
+	"forall;":                   '\U00002200',
+	"fork;":                     '\U000022D4',
+	"forkv;":                    '\U00002AD9',
+	"fpartint;":                 '\U00002A0D',
+	"frac12;":                   '\U000000BD',
+	"frac13;":                   '\U00002153',
+	"frac14;":                   '\U000000BC',
+	"frac15;":                   '\U00002155',
+	"frac16;":                   '\U00002159',
+	"frac18;":                   '\U0000215B',
+	"frac23;":                   '\U00002154',
+	"frac25;":                   '\U00002156',
+	"frac34;":                   '\U000000BE',
+	"frac35;":                   '\U00002157',
+	"frac38;":                   '\U0000215C',
+	"frac45;":                   '\U00002158',
+	"frac56;":                   '\U0000215A',
+	"frac58;":                   '\U0000215D',
+	"frac78;":                   '\U0000215E',
+	"frasl;":                    '\U00002044',
+	"frown;":                    '\U00002322',
+	"fscr;":                     '\U0001D4BB',
+	"gE;":                       '\U00002267',
+	"gEl;":                      '\U00002A8C',
+	"gacute;":                   '\U000001F5',
+	"gamma;":                    '\U000003B3',
+	"gammad;":                   '\U000003DD',
+	"gap;":                      '\U00002A86',
+	"gbreve;":                   '\U0000011F',
+	"gcirc;":                    '\U0000011D',
+	"gcy;":                      '\U00000433',
+	"gdot;":                     '\U00000121',
+	"ge;":                       '\U00002265',
+	"gel;":                      '\U000022DB',
+	"geq;":                      '\U00002265',
+	"geqq;":                     '\U00002267',
+	"geqslant;":                 '\U00002A7E',
+	"ges;":                      '\U00002A7E',
+	"gescc;":                    '\U00002AA9',
+	"gesdot;":                   '\U00002A80',
+	"gesdoto;":                  '\U00002A82',
+	"gesdotol;":                 '\U00002A84',
+	"gesles;":                   '\U00002A94',
+	"gfr;":                      '\U0001D524',
+	"gg;":                       '\U0000226B',
+	"ggg;":                      '\U000022D9',
+	"gimel;":                    '\U00002137',
+	"gjcy;":                     '\U00000453',
+	"gl;":                       '\U00002277',
+	"glE;":                      '\U00002A92',
+	"gla;":                      '\U00002AA5',
+	"glj;":                      '\U00002AA4',
+	"gnE;":                      '\U00002269',
+	"gnap;":                     '\U00002A8A',
+	"gnapprox;":                 '\U00002A8A',
+	"gne;":                      '\U00002A88',
+	"gneq;":                     '\U00002A88',
+	"gneqq;":                    '\U00002269',
+	"gnsim;":                    '\U000022E7',
+	"gopf;":                     '\U0001D558',
+	"grave;":                    '\U00000060',
+	"gscr;":                     '\U0000210A',
+	"gsim;":                     '\U00002273',
+	"gsime;":                    '\U00002A8E',
+	"gsiml;":                    '\U00002A90',
+	"gt;":                       '\U0000003E',
+	"gtcc;":                     '\U00002AA7',
+	"gtcir;":                    '\U00002A7A',
+	"gtdot;":                    '\U000022D7',
+	"gtlPar;":                   '\U00002995',
+	"gtquest;":                  '\U00002A7C',
+	"gtrapprox;":                '\U00002A86',
+	"gtrarr;":                   '\U00002978',
+	"gtrdot;":                   '\U000022D7',
+	"gtreqless;":                '\U000022DB',
+	"gtreqqless;":               '\U00002A8C',
+	"gtrless;":                  '\U00002277',
+	"gtrsim;":                   '\U00002273',
+	"hArr;":                     '\U000021D4',
+	"hairsp;":                   '\U0000200A',
+	"half;":                     '\U000000BD',
+	"hamilt;":                   '\U0000210B',
+	"hardcy;":                   '\U0000044A',
+	"harr;":                     '\U00002194',
+	"harrcir;":                  '\U00002948',
+	"harrw;":                    '\U000021AD',
+	"hbar;":                     '\U0000210F',
+	"hcirc;":                    '\U00000125',
+	"hearts;":                   '\U00002665',
+	"heartsuit;":                '\U00002665',
+	"hellip;":                   '\U00002026',
+	"hercon;":                   '\U000022B9',
+	"hfr;":                      '\U0001D525',
+	"hksearow;":                 '\U00002925',
+	"hkswarow;":                 '\U00002926',
+	"hoarr;":                    '\U000021FF',
+	"homtht;":                   '\U0000223B',
+	"hookleftarrow;":            '\U000021A9',
+	"hookrightarrow;":           '\U000021AA',
+	"hopf;":                     '\U0001D559',
+	"horbar;":                   '\U00002015',
+	"hscr;":                     '\U0001D4BD',
+	"hslash;":                   '\U0000210F',
+	"hstrok;":                   '\U00000127',
+	"hybull;":                   '\U00002043',
+	"hyphen;":                   '\U00002010',
+	"iacute;":                   '\U000000ED',
+	"ic;":                       '\U00002063',
+	"icirc;":                    '\U000000EE',
+	"icy;":                      '\U00000438',
+	"iecy;":                     '\U00000435',
+	"iexcl;":                    '\U000000A1',
+	"iff;":                      '\U000021D4',
+	"ifr;":                      '\U0001D526',
+	"igrave;":                   '\U000000EC',
+	"ii;":                       '\U00002148',
+	"iiiint;":                   '\U00002A0C',
+	"iiint;":                    '\U0000222D',
+	"iinfin;":                   '\U000029DC',
+	"iiota;":                    '\U00002129',
+	"ijlig;":                    '\U00000133',
+	"imacr;":                    '\U0000012B',
+	"image;":                    '\U00002111',
+	"imagline;":                 '\U00002110',
+	"imagpart;":                 '\U00002111',
+	"imath;":                    '\U00000131',
+	"imof;":                     '\U000022B7',
+	"imped;":                    '\U000001B5',
+	"in;":                       '\U00002208',
+	"incare;":                   '\U00002105',
+	"infin;":                    '\U0000221E',
+	"infintie;":                 '\U000029DD',
+	"inodot;":                   '\U00000131',
+	"int;":                      '\U0000222B',
+	"intcal;":                   '\U000022BA',
+	"integers;":                 '\U00002124',
+	"intercal;":                 '\U000022BA',
+	"intlarhk;":                 '\U00002A17',
+	"intprod;":                  '\U00002A3C',
+	"iocy;":                     '\U00000451',
+	"iogon;":                    '\U0000012F',
+	"iopf;":                     '\U0001D55A',
+	"iota;":                     '\U000003B9',
+	"iprod;":                    '\U00002A3C',
+	"iquest;":                   '\U000000BF',
+	"iscr;":                     '\U0001D4BE',
+	"isin;":                     '\U00002208',
+	"isinE;":                    '\U000022F9',
+	"isindot;":                  '\U000022F5',
+	"isins;":                    '\U000022F4',
+	"isinsv;":                   '\U000022F3',
+	"isinv;":                    '\U00002208',
+	"it;":                       '\U00002062',
+	"itilde;":                   '\U00000129',
+	"iukcy;":                    '\U00000456',
+	"iuml;":                     '\U000000EF',
+	"jcirc;":                    '\U00000135',
+	"jcy;":                      '\U00000439',
+	"jfr;":                      '\U0001D527',
+	"jmath;":                    '\U00000237',
+	"jopf;":                     '\U0001D55B',
+	"jscr;":                     '\U0001D4BF',
+	"jsercy;":                   '\U00000458',
+	"jukcy;":                    '\U00000454',
+	"kappa;":                    '\U000003BA',
+	"kappav;":                   '\U000003F0',
+	"kcedil;":                   '\U00000137',
+	"kcy;":                      '\U0000043A',
+	"kfr;":                      '\U0001D528',
+	"kgreen;":                   '\U00000138',
+	"khcy;":                     '\U00000445',
+	"kjcy;":                     '\U0000045C',
+	"kopf;":                     '\U0001D55C',
+	"kscr;":                     '\U0001D4C0',
+	"lAarr;":                    '\U000021DA',
+	"lArr;":                     '\U000021D0',
+	"lAtail;":                   '\U0000291B',
+	"lBarr;":                    '\U0000290E',
+	"lE;":                       '\U00002266',
+	"lEg;":                      '\U00002A8B',
+	"lHar;":                     '\U00002962',
+	"lacute;":                   '\U0000013A',
+	"laemptyv;":                 '\U000029B4',
+	"lagran;":                   '\U00002112',
+	"lambda;":                   '\U000003BB',
+	"lang;":                     '\U000027E8',
+	"langd;":                    '\U00002991',
+	"langle;":                   '\U000027E8',
+	"lap;":                      '\U00002A85',
+	"laquo;":                    '\U000000AB',
+	"larr;":                     '\U00002190',
+	"larrb;":                    '\U000021E4',
+	"larrbfs;":                  '\U0000291F',
+	"larrfs;":                   '\U0000291D',
+	"larrhk;":                   '\U000021A9',
+	"larrlp;":                   '\U000021AB',
+	"larrpl;":                   '\U00002939',
+	"larrsim;":                  '\U00002973',
+	"larrtl;":                   '\U000021A2',
+	"lat;":                      '\U00002AAB',
+	"latail;":                   '\U00002919',
+	"late;":                     '\U00002AAD',
+	"lbarr;":                    '\U0000290C',
+	"lbbrk;":                    '\U00002772',
+	"lbrace;":                   '\U0000007B',
+	"lbrack;":                   '\U0000005B',
+	"lbrke;":                    '\U0000298B',
+	"lbrksld;":                  '\U0000298F',
+	"lbrkslu;":                  '\U0000298D',
+	"lcaron;":                   '\U0000013E',
+	"lcedil;":                   '\U0000013C',
+	"lceil;":                    '\U00002308',
+	"lcub;":                     '\U0000007B',
+	"lcy;":                      '\U0000043B',
+	"ldca;":                     '\U00002936',
+	"ldquo;":                    '\U0000201C',
+	"ldquor;":                   '\U0000201E',
+	"ldrdhar;":                  '\U00002967',
+	"ldrushar;":                 '\U0000294B',
+	"ldsh;":                     '\U000021B2',
+	"le;":                       '\U00002264',
+	"leftarrow;":                '\U00002190',
+	"leftarrowtail;":            '\U000021A2',
+	"leftharpoondown;":          '\U000021BD',
+	"leftharpoonup;":            '\U000021BC',
+	"leftleftarrows;":           '\U000021C7',
+	"leftrightarrow;":           '\U00002194',
+	"leftrightarrows;":          '\U000021C6',
+	"leftrightharpoons;":        '\U000021CB',
+	"leftrightsquigarrow;":      '\U000021AD',
+	"leftthreetimes;":           '\U000022CB',
+	"leg;":                      '\U000022DA',
+	"leq;":                      '\U00002264',
+	"leqq;":                     '\U00002266',
+	"leqslant;":                 '\U00002A7D',
+	"les;":                      '\U00002A7D',
+	"lescc;":                    '\U00002AA8',
+	"lesdot;":                   '\U00002A7F',
+	"lesdoto;":                  '\U00002A81',
+	"lesdotor;":                 '\U00002A83',
+	"lesges;":                   '\U00002A93',
+	"lessapprox;":               '\U00002A85',
+	"lessdot;":                  '\U000022D6',
+	"lesseqgtr;":                '\U000022DA',
+	"lesseqqgtr;":               '\U00002A8B',
+	"lessgtr;":                  '\U00002276',
+	"lesssim;":                  '\U00002272',
+	"lfisht;":                   '\U0000297C',
+	"lfloor;":                   '\U0000230A',
+	"lfr;":                      '\U0001D529',
+	"lg;":                       '\U00002276',
+	"lgE;":                      '\U00002A91',
+	"lhard;":                    '\U000021BD',
+	"lharu;":                    '\U000021BC',
+	"lharul;":                   '\U0000296A',
+	"lhblk;":                    '\U00002584',
+	"ljcy;":                     '\U00000459',
+	"ll;":                       '\U0000226A',
+	"llarr;":                    '\U000021C7',
+	"llcorner;":                 '\U0000231E',
+	"llhard;":                   '\U0000296B',
+	"lltri;":                    '\U000025FA',
+	"lmidot;":                   '\U00000140',
+	"lmoust;":                   '\U000023B0',
+	"lmoustache;":               '\U000023B0',
+	"lnE;":                      '\U00002268',
+	"lnap;":                     '\U00002A89',
+	"lnapprox;":                 '\U00002A89',
+	"lne;":                      '\U00002A87',
+	"lneq;":                     '\U00002A87',
+	"lneqq;":                    '\U00002268',
+	"lnsim;":                    '\U000022E6',
+	"loang;":                    '\U000027EC',
+	"loarr;":                    '\U000021FD',
+	"lobrk;":                    '\U000027E6',
+	"longleftarrow;":            '\U000027F5',
+	"longleftrightarrow;":       '\U000027F7',
+	"longmapsto;":               '\U000027FC',
+	"longrightarrow;":           '\U000027F6',
+	"looparrowleft;":            '\U000021AB',
+	"looparrowright;":           '\U000021AC',
+	"lopar;":                    '\U00002985',
+	"lopf;":                     '\U0001D55D',
+	"loplus;":                   '\U00002A2D',
+	"lotimes;":                  '\U00002A34',
+	"lowast;":                   '\U00002217',
+	"lowbar;":                   '\U0000005F',
+	"loz;":                      '\U000025CA',
+	"lozenge;":                  '\U000025CA',
+	"lozf;":                     '\U000029EB',
+	"lpar;":                     '\U00000028',
+	"lparlt;":                   '\U00002993',
+	"lrarr;":                    '\U000021C6',
+	"lrcorner;":                 '\U0000231F',
+	"lrhar;":                    '\U000021CB',
+	"lrhard;":                   '\U0000296D',
+	"lrm;":                      '\U0000200E',
+	"lrtri;":                    '\U000022BF',
+	"lsaquo;":                   '\U00002039',
+	"lscr;":                     '\U0001D4C1',
+	"lsh;":                      '\U000021B0',
+	"lsim;":                     '\U00002272',
+	"lsime;":                    '\U00002A8D',
+	"lsimg;":                    '\U00002A8F',
+	"lsqb;":                     '\U0000005B',
+	"lsquo;":                    '\U00002018',
+	"lsquor;":                   '\U0000201A',
+	"lstrok;":                   '\U00000142',
+	"lt;":                       '\U0000003C',
+	"ltcc;":                     '\U00002AA6',
+	"ltcir;":                    '\U00002A79',
+	"ltdot;":                    '\U000022D6',
+	"lthree;":                   '\U000022CB',
+	"ltimes;":                   '\U000022C9',
+	"ltlarr;":                   '\U00002976',
+	"ltquest;":                  '\U00002A7B',
+	"ltrPar;":                   '\U00002996',
+	"ltri;":                     '\U000025C3',
+	"ltrie;":                    '\U000022B4',
+	"ltrif;":                    '\U000025C2',
+	"lurdshar;":                 '\U0000294A',
+	"luruhar;":                  '\U00002966',
+	"mDDot;":                    '\U0000223A',
+	"macr;":                     '\U000000AF',
+	"male;":                     '\U00002642',
+	"malt;":                     '\U00002720',
+	"maltese;":                  '\U00002720',
+	"map;":                      '\U000021A6',
+	"mapsto;":                   '\U000021A6',
+	"mapstodown;":               '\U000021A7',
+	"mapstoleft;":               '\U000021A4',
+	"mapstoup;":                 '\U000021A5',
+	"marker;":                   '\U000025AE',
+	"mcomma;":                   '\U00002A29',
+	"mcy;":                      '\U0000043C',
+	"mdash;":                    '\U00002014',
+	"measuredangle;":            '\U00002221',
+	"mfr;":                      '\U0001D52A',
+	"mho;":                      '\U00002127',
+	"micro;":                    '\U000000B5',
+	"mid;":                      '\U00002223',
+	"midast;":                   '\U0000002A',
+	"midcir;":                   '\U00002AF0',
+	"middot;":                   '\U000000B7',
+	"minus;":                    '\U00002212',
+	"minusb;":                   '\U0000229F',
+	"minusd;":                   '\U00002238',
+	"minusdu;":                  '\U00002A2A',
+	"mlcp;":                     '\U00002ADB',
+	"mldr;":                     '\U00002026',
+	"mnplus;":                   '\U00002213',
+	"models;":                   '\U000022A7',
+	"mopf;":                     '\U0001D55E',
+	"mp;":                       '\U00002213',
+	"mscr;":                     '\U0001D4C2',
+	"mstpos;":                   '\U0000223E',
+	"mu;":                       '\U000003BC',
+	"multimap;":                 '\U000022B8',
+	"mumap;":                    '\U000022B8',
+	"nLeftarrow;":               '\U000021CD',
+	"nLeftrightarrow;":          '\U000021CE',
+	"nRightarrow;":              '\U000021CF',
+	"nVDash;":                   '\U000022AF',
+	"nVdash;":                   '\U000022AE',
+	"nabla;":                    '\U00002207',
+	"nacute;":                   '\U00000144',
+	"nap;":                      '\U00002249',
+	"napos;":                    '\U00000149',
+	"napprox;":                  '\U00002249',
+	"natur;":                    '\U0000266E',
+	"natural;":                  '\U0000266E',
+	"naturals;":                 '\U00002115',
+	"nbsp;":                     '\U000000A0',
+	"ncap;":                     '\U00002A43',
+	"ncaron;":                   '\U00000148',
+	"ncedil;":                   '\U00000146',
+	"ncong;":                    '\U00002247',
+	"ncup;":                     '\U00002A42',
+	"ncy;":                      '\U0000043D',
+	"ndash;":                    '\U00002013',
+	"ne;":                       '\U00002260',
+	"neArr;":                    '\U000021D7',
+	"nearhk;":                   '\U00002924',
+	"nearr;":                    '\U00002197',
+	"nearrow;":                  '\U00002197',
+	"nequiv;":                   '\U00002262',
+	"nesear;":                   '\U00002928',
+	"nexist;":                   '\U00002204',
+	"nexists;":                  '\U00002204',
+	"nfr;":                      '\U0001D52B',
+	"nge;":                      '\U00002271',
+	"ngeq;":                     '\U00002271',
+	"ngsim;":                    '\U00002275',
+	"ngt;":                      '\U0000226F',
+	"ngtr;":                     '\U0000226F',
+	"nhArr;":                    '\U000021CE',
+	"nharr;":                    '\U000021AE',
+	"nhpar;":                    '\U00002AF2',
+	"ni;":                       '\U0000220B',
+	"nis;":                      '\U000022FC',
+	"nisd;":                     '\U000022FA',
+	"niv;":                      '\U0000220B',
+	"njcy;":                     '\U0000045A',
+	"nlArr;":                    '\U000021CD',
+	"nlarr;":                    '\U0000219A',
+	"nldr;":                     '\U00002025',
+	"nle;":                      '\U00002270',
+	"nleftarrow;":               '\U0000219A',
+	"nleftrightarrow;":          '\U000021AE',
+	"nleq;":                     '\U00002270',
+	"nless;":                    '\U0000226E',
+	"nlsim;":                    '\U00002274',
+	"nlt;":                      '\U0000226E',
+	"nltri;":                    '\U000022EA',
+	"nltrie;":                   '\U000022EC',
+	"nmid;":                     '\U00002224',
+	"nopf;":                     '\U0001D55F',
+	"not;":                      '\U000000AC',
+	"notin;":                    '\U00002209',
+	"notinva;":                  '\U00002209',
+	"notinvb;":                  '\U000022F7',
+	"notinvc;":                  '\U000022F6',
+	"notni;":                    '\U0000220C',
+	"notniva;":                  '\U0000220C',
+	"notnivb;":                  '\U000022FE',
+	"notnivc;":                  '\U000022FD',
+	"npar;":                     '\U00002226',
+	"nparallel;":                '\U00002226',
+	"npolint;":                  '\U00002A14',
+	"npr;":                      '\U00002280',
+	"nprcue;":                   '\U000022E0',
+	"nprec;":                    '\U00002280',
+	"nrArr;":                    '\U000021CF',
+	"nrarr;":                    '\U0000219B',
+	"nrightarrow;":              '\U0000219B',
+	"nrtri;":                    '\U000022EB',
+	"nrtrie;":                   '\U000022ED',
+	"nsc;":                      '\U00002281',
+	"nsccue;":                   '\U000022E1',
+	"nscr;":                     '\U0001D4C3',
+	"nshortmid;":                '\U00002224',
+	"nshortparallel;":           '\U00002226',
+	"nsim;":                     '\U00002241',
+	"nsime;":                    '\U00002244',
+	"nsimeq;":                   '\U00002244',
+	"nsmid;":                    '\U00002224',
+	"nspar;":                    '\U00002226',
+	"nsqsube;":                  '\U000022E2',
+	"nsqsupe;":                  '\U000022E3',
+	"nsub;":                     '\U00002284',
+	"nsube;":                    '\U00002288',
+	"nsubseteq;":                '\U00002288',
+	"nsucc;":                    '\U00002281',
+	"nsup;":                     '\U00002285',
+	"nsupe;":                    '\U00002289',
+	"nsupseteq;":                '\U00002289',
+	"ntgl;":                     '\U00002279',
+	"ntilde;":                   '\U000000F1',
+	"ntlg;":                     '\U00002278',
+	"ntriangleleft;":            '\U000022EA',
+	"ntrianglelefteq;":          '\U000022EC',
+	"ntriangleright;":           '\U000022EB',
+	"ntrianglerighteq;":         '\U000022ED',
+	"nu;":                       '\U000003BD',
+	"num;":                      '\U00000023',
+	"numero;":                   '\U00002116',
+	"numsp;":                    '\U00002007',
+	"nvDash;":                   '\U000022AD',
+	"nvHarr;":                   '\U00002904',
+	"nvdash;":                   '\U000022AC',
+	"nvinfin;":                  '\U000029DE',
+	"nvlArr;":                   '\U00002902',
+	"nvrArr;":                   '\U00002903',
+	"nwArr;":                    '\U000021D6',
+	"nwarhk;":                   '\U00002923',
+	"nwarr;":                    '\U00002196',
+	"nwarrow;":                  '\U00002196',
+	"nwnear;":                   '\U00002927',
+	"oS;":                       '\U000024C8',
+	"oacute;":                   '\U000000F3',
+	"oast;":                     '\U0000229B',
+	"ocir;":                     '\U0000229A',
+	"ocirc;":                    '\U000000F4',
+	"ocy;":                      '\U0000043E',
+	"odash;":                    '\U0000229D',
+	"odblac;":                   '\U00000151',
+	"odiv;":                     '\U00002A38',
+	"odot;":                     '\U00002299',
+	"odsold;":                   '\U000029BC',
+	"oelig;":                    '\U00000153',
+	"ofcir;":                    '\U000029BF',
+	"ofr;":                      '\U0001D52C',
+	"ogon;":                     '\U000002DB',
+	"ograve;":                   '\U000000F2',
+	"ogt;":                      '\U000029C1',
+	"ohbar;":                    '\U000029B5',
+	"ohm;":                      '\U000003A9',
+	"oint;":                     '\U0000222E',
+	"olarr;":                    '\U000021BA',
+	"olcir;":                    '\U000029BE',
+	"olcross;":                  '\U000029BB',
+	"oline;":                    '\U0000203E',
+	"olt;":                      '\U000029C0',
+	"omacr;":                    '\U0000014D',
+	"omega;":                    '\U000003C9',
+	"omicron;":                  '\U000003BF',
+	"omid;":                     '\U000029B6',
+	"ominus;":                   '\U00002296',
+	"oopf;":                     '\U0001D560',
+	"opar;":                     '\U000029B7',
+	"operp;":                    '\U000029B9',
+	"oplus;":                    '\U00002295',
+	"or;":                       '\U00002228',
+	"orarr;":                    '\U000021BB',
+	"ord;":                      '\U00002A5D',
+	"order;":                    '\U00002134',
+	"orderof;":                  '\U00002134',
+	"ordf;":                     '\U000000AA',
+	"ordm;":                     '\U000000BA',
+	"origof;":                   '\U000022B6',
+	"oror;":                     '\U00002A56',
+	"orslope;":                  '\U00002A57',
+	"orv;":                      '\U00002A5B',
+	"oscr;":                     '\U00002134',
+	"oslash;":                   '\U000000F8',
+	"osol;":                     '\U00002298',
+	"otilde;":                   '\U000000F5',
+	"otimes;":                   '\U00002297',
+	"otimesas;":                 '\U00002A36',
+	"ouml;":                     '\U000000F6',
+	"ovbar;":                    '\U0000233D',
+	"par;":                      '\U00002225',
+	"para;":                     '\U000000B6',
+	"parallel;":                 '\U00002225',
+	"parsim;":                   '\U00002AF3',
+	"parsl;":                    '\U00002AFD',
+	"part;":                     '\U00002202',
+	"pcy;":                      '\U0000043F',
+	"percnt;":                   '\U00000025',
+	"period;":                   '\U0000002E',
+	"permil;":                   '\U00002030',
+	"perp;":                     '\U000022A5',
+	"pertenk;":                  '\U00002031',
+	"pfr;":                      '\U0001D52D',
+	"phi;":                      '\U000003C6',
+	"phiv;":                     '\U000003D5',
+	"phmmat;":                   '\U00002133',
+	"phone;":                    '\U0000260E',
+	"pi;":                       '\U000003C0',
+	"pitchfork;":                '\U000022D4',
+	"piv;":                      '\U000003D6',
+	"planck;":                   '\U0000210F',
+	"planckh;":                  '\U0000210E',
+	"plankv;":                   '\U0000210F',
+	"plus;":                     '\U0000002B',
+	"plusacir;":                 '\U00002A23',
+	"plusb;":                    '\U0000229E',
+	"pluscir;":                  '\U00002A22',
+	"plusdo;":                   '\U00002214',
+	"plusdu;":                   '\U00002A25',
+	"pluse;":                    '\U00002A72',
+	"plusmn;":                   '\U000000B1',
+	"plussim;":                  '\U00002A26',
+	"plustwo;":                  '\U00002A27',
+	"pm;":                       '\U000000B1',
+	"pointint;":                 '\U00002A15',
+	"popf;":                     '\U0001D561',
+	"pound;":                    '\U000000A3',
+	"pr;":                       '\U0000227A',
+	"prE;":                      '\U00002AB3',
+	"prap;":                     '\U00002AB7',
+	"prcue;":                    '\U0000227C',
+	"pre;":                      '\U00002AAF',
+	"prec;":                     '\U0000227A',
+	"precapprox;":               '\U00002AB7',
+	"preccurlyeq;":              '\U0000227C',
+	"preceq;":                   '\U00002AAF',
+	"precnapprox;":              '\U00002AB9',
+	"precneqq;":                 '\U00002AB5',
+	"precnsim;":                 '\U000022E8',
+	"precsim;":                  '\U0000227E',
+	"prime;":                    '\U00002032',
+	"primes;":                   '\U00002119',
+	"prnE;":                     '\U00002AB5',
+	"prnap;":                    '\U00002AB9',
+	"prnsim;":                   '\U000022E8',
+	"prod;":                     '\U0000220F',
+	"profalar;":                 '\U0000232E',
+	"profline;":                 '\U00002312',
+	"profsurf;":                 '\U00002313',
+	"prop;":                     '\U0000221D',
+	"propto;":                   '\U0000221D',
+	"prsim;":                    '\U0000227E',
+	"prurel;":                   '\U000022B0',
+	"pscr;":                     '\U0001D4C5',
+	"psi;":                      '\U000003C8',
+	"puncsp;":                   '\U00002008',
+	"qfr;":                      '\U0001D52E',
+	"qint;":                     '\U00002A0C',
+	"qopf;":                     '\U0001D562',
+	"qprime;":                   '\U00002057',
+	"qscr;":                     '\U0001D4C6',
+	"quaternions;":              '\U0000210D',
+	"quatint;":                  '\U00002A16',
+	"quest;":                    '\U0000003F',
+	"questeq;":                  '\U0000225F',
+	"quot;":                     '\U00000022',
+	"rAarr;":                    '\U000021DB',
+	"rArr;":                     '\U000021D2',
+	"rAtail;":                   '\U0000291C',
+	"rBarr;":                    '\U0000290F',
+	"rHar;":                     '\U00002964',
+	"racute;":                   '\U00000155',
+	"radic;":                    '\U0000221A',
+	"raemptyv;":                 '\U000029B3',
+	"rang;":                     '\U000027E9',
+	"rangd;":                    '\U00002992',
+	"range;":                    '\U000029A5',
+	"rangle;":                   '\U000027E9',
+	"raquo;":                    '\U000000BB',
+	"rarr;":                     '\U00002192',
+	"rarrap;":                   '\U00002975',
+	"rarrb;":                    '\U000021E5',
+	"rarrbfs;":                  '\U00002920',
+	"rarrc;":                    '\U00002933',
+	"rarrfs;":                   '\U0000291E',
+	"rarrhk;":                   '\U000021AA',
+	"rarrlp;":                   '\U000021AC',
+	"rarrpl;":                   '\U00002945',
+	"rarrsim;":                  '\U00002974',
+	"rarrtl;":                   '\U000021A3',
+	"rarrw;":                    '\U0000219D',
+	"ratail;":                   '\U0000291A',
+	"ratio;":                    '\U00002236',
+	"rationals;":                '\U0000211A',
+	"rbarr;":                    '\U0000290D',
+	"rbbrk;":                    '\U00002773',
+	"rbrace;":                   '\U0000007D',
+	"rbrack;":                   '\U0000005D',
+	"rbrke;":                    '\U0000298C',
+	"rbrksld;":                  '\U0000298E',
+	"rbrkslu;":                  '\U00002990',
+	"rcaron;":                   '\U00000159',
+	"rcedil;":                   '\U00000157',
+	"rceil;":                    '\U00002309',
+	"rcub;":                     '\U0000007D',
+	"rcy;":                      '\U00000440',
+	"rdca;":                     '\U00002937',
+	"rdldhar;":                  '\U00002969',
+	"rdquo;":                    '\U0000201D',
+	"rdquor;":                   '\U0000201D',
+	"rdsh;":                     '\U000021B3',
+	"real;":                     '\U0000211C',
+	"realine;":                  '\U0000211B',
+	"realpart;":                 '\U0000211C',
+	"reals;":                    '\U0000211D',
+	"rect;":                     '\U000025AD',
+	"reg;":                      '\U000000AE',
+	"rfisht;":                   '\U0000297D',
+	"rfloor;":                   '\U0000230B',
+	"rfr;":                      '\U0001D52F',
+	"rhard;":                    '\U000021C1',
+	"rharu;":                    '\U000021C0',
+	"rharul;":                   '\U0000296C',
+	"rho;":                      '\U000003C1',
+	"rhov;":                     '\U000003F1',
+	"rightarrow;":               '\U00002192',
+	"rightarrowtail;":           '\U000021A3',
+	"rightharpoondown;":         '\U000021C1',
+	"rightharpoonup;":           '\U000021C0',
+	"rightleftarrows;":          '\U000021C4',
+	"rightleftharpoons;":        '\U000021CC',
+	"rightrightarrows;":         '\U000021C9',
+	"rightsquigarrow;":          '\U0000219D',
+	"rightthreetimes;":          '\U000022CC',
+	"ring;":                     '\U000002DA',
+	"risingdotseq;":             '\U00002253',
+	"rlarr;":                    '\U000021C4',
+	"rlhar;":                    '\U000021CC',
+	"rlm;":                      '\U0000200F',
+	"rmoust;":                   '\U000023B1',
+	"rmoustache;":               '\U000023B1',
+	"rnmid;":                    '\U00002AEE',
+	"roang;":                    '\U000027ED',
+	"roarr;":                    '\U000021FE',
+	"robrk;":                    '\U000027E7',
+	"ropar;":                    '\U00002986',
+	"ropf;":                     '\U0001D563',
+	"roplus;":                   '\U00002A2E',
+	"rotimes;":                  '\U00002A35',
+	"rpar;":                     '\U00000029',
+	"rpargt;":                   '\U00002994',
+	"rppolint;":                 '\U00002A12',
+	"rrarr;":                    '\U000021C9',
+	"rsaquo;":                   '\U0000203A',
+	"rscr;":                     '\U0001D4C7',
+	"rsh;":                      '\U000021B1',
+	"rsqb;":                     '\U0000005D',
+	"rsquo;":                    '\U00002019',
+	"rsquor;":                   '\U00002019',
+	"rthree;":                   '\U000022CC',
+	"rtimes;":                   '\U000022CA',
+	"rtri;":                     '\U000025B9',
+	"rtrie;":                    '\U000022B5',
+	"rtrif;":                    '\U000025B8',
+	"rtriltri;":                 '\U000029CE',
+	"ruluhar;":                  '\U00002968',
+	"rx;":                       '\U0000211E',
+	"sacute;":                   '\U0000015B',
+	"sbquo;":                    '\U0000201A',
+	"sc;":                       '\U0000227B',
+	"scE;":                      '\U00002AB4',
+	"scap;":                     '\U00002AB8',
+	"scaron;":                   '\U00000161',
+	"sccue;":                    '\U0000227D',
+	"sce;":                      '\U00002AB0',
+	"scedil;":                   '\U0000015F',
+	"scirc;":                    '\U0000015D',
+	"scnE;":                     '\U00002AB6',
+	"scnap;":                    '\U00002ABA',
+	"scnsim;":                   '\U000022E9',
+	"scpolint;":                 '\U00002A13',
+	"scsim;":                    '\U0000227F',
+	"scy;":                      '\U00000441',
+	"sdot;":                     '\U000022C5',
+	"sdotb;":                    '\U000022A1',
+	"sdote;":                    '\U00002A66',
+	"seArr;":                    '\U000021D8',
+	"searhk;":                   '\U00002925',
+	"searr;":                    '\U00002198',
+	"searrow;":                  '\U00002198',
+	"sect;":                     '\U000000A7',
+	"semi;":                     '\U0000003B',
+	"seswar;":                   '\U00002929',
+	"setminus;":                 '\U00002216',
+	"setmn;":                    '\U00002216',
+	"sext;":                     '\U00002736',
+	"sfr;":                      '\U0001D530',
+	"sfrown;":                   '\U00002322',
+	"sharp;":                    '\U0000266F',
+	"shchcy;":                   '\U00000449',
+	"shcy;":                     '\U00000448',
+	"shortmid;":                 '\U00002223',
+	"shortparallel;":            '\U00002225',
+	"shy;":                      '\U000000AD',
+	"sigma;":                    '\U000003C3',
+	"sigmaf;":                   '\U000003C2',
+	"sigmav;":                   '\U000003C2',
+	"sim;":                      '\U0000223C',
+	"simdot;":                   '\U00002A6A',
+	"sime;":                     '\U00002243',
+	"simeq;":                    '\U00002243',
+	"simg;":                     '\U00002A9E',
+	"simgE;":                    '\U00002AA0',
+	"siml;":                     '\U00002A9D',
+	"simlE;":                    '\U00002A9F',
+	"simne;":                    '\U00002246',
+	"simplus;":                  '\U00002A24',
+	"simrarr;":                  '\U00002972',
+	"slarr;":                    '\U00002190',
+	"smallsetminus;":            '\U00002216',
+	"smashp;":                   '\U00002A33',
+	"smeparsl;":                 '\U000029E4',
+	"smid;":                     '\U00002223',
+	"smile;":                    '\U00002323',
+	"smt;":                      '\U00002AAA',
+	"smte;":                     '\U00002AAC',
+	"softcy;":                   '\U0000044C',
+	"sol;":                      '\U0000002F',
+	"solb;":                     '\U000029C4',
+	"solbar;":                   '\U0000233F',
+	"sopf;":                     '\U0001D564',
+	"spades;":                   '\U00002660',
+	"spadesuit;":                '\U00002660',
+	"spar;":                     '\U00002225',
+	"sqcap;":                    '\U00002293',
+	"sqcup;":                    '\U00002294',
+	"sqsub;":                    '\U0000228F',
+	"sqsube;":                   '\U00002291',
+	"sqsubset;":                 '\U0000228F',
+	"sqsubseteq;":               '\U00002291',
+	"sqsup;":                    '\U00002290',
+	"sqsupe;":                   '\U00002292',
+	"sqsupset;":                 '\U00002290',
+	"sqsupseteq;":               '\U00002292',
+	"squ;":                      '\U000025A1',
+	"square;":                   '\U000025A1',
+	"squarf;":                   '\U000025AA',
+	"squf;":                     '\U000025AA',
+	"srarr;":                    '\U00002192',
+	"sscr;":                     '\U0001D4C8',
+	"ssetmn;":                   '\U00002216',
+	"ssmile;":                   '\U00002323',
+	"sstarf;":                   '\U000022C6',
+	"star;":                     '\U00002606',
+	"starf;":                    '\U00002605',
+	"straightepsilon;":          '\U000003F5',
+	"straightphi;":              '\U000003D5',
+	"strns;":                    '\U000000AF',
+	"sub;":                      '\U00002282',
+	"subE;":                     '\U00002AC5',
+	"subdot;":                   '\U00002ABD',
+	"sube;":                     '\U00002286',
+	"subedot;":                  '\U00002AC3',
+	"submult;":                  '\U00002AC1',
+	"subnE;":                    '\U00002ACB',
+	"subne;":                    '\U0000228A',
+	"subplus;":                  '\U00002ABF',
+	"subrarr;":                  '\U00002979',
+	"subset;":                   '\U00002282',
+	"subseteq;":                 '\U00002286',
+	"subseteqq;":                '\U00002AC5',
+	"subsetneq;":                '\U0000228A',
+	"subsetneqq;":               '\U00002ACB',
+	"subsim;":                   '\U00002AC7',
+	"subsub;":                   '\U00002AD5',
+	"subsup;":                   '\U00002AD3',
+	"succ;":                     '\U0000227B',
+	"succapprox;":               '\U00002AB8',
+	"succcurlyeq;":              '\U0000227D',
+	"succeq;":                   '\U00002AB0',
+	"succnapprox;":              '\U00002ABA',
+	"succneqq;":                 '\U00002AB6',
+	"succnsim;":                 '\U000022E9',
+	"succsim;":                  '\U0000227F',
+	"sum;":                      '\U00002211',
+	"sung;":                     '\U0000266A',
+	"sup;":                      '\U00002283',
+	"sup1;":                     '\U000000B9',
+	"sup2;":                     '\U000000B2',
+	"sup3;":                     '\U000000B3',
+	"supE;":                     '\U00002AC6',
+	"supdot;":                   '\U00002ABE',
+	"supdsub;":                  '\U00002AD8',
+	"supe;":                     '\U00002287',
+	"supedot;":                  '\U00002AC4',
+	"suphsol;":                  '\U000027C9',
+	"suphsub;":                  '\U00002AD7',
+	"suplarr;":                  '\U0000297B',
+	"supmult;":                  '\U00002AC2',
+	"supnE;":                    '\U00002ACC',
+	"supne;":                    '\U0000228B',
+	"supplus;":                  '\U00002AC0',
+	"supset;":                   '\U00002283',
+	"supseteq;":                 '\U00002287',
+	"supseteqq;":                '\U00002AC6',
+	"supsetneq;":                '\U0000228B',
+	"supsetneqq;":               '\U00002ACC',
+	"supsim;":                   '\U00002AC8',
+	"supsub;":                   '\U00002AD4',
+	"supsup;":                   '\U00002AD6',
+	"swArr;":                    '\U000021D9',
+	"swarhk;":                   '\U00002926',
+	"swarr;":                    '\U00002199',
+	"swarrow;":                  '\U00002199',
+	"swnwar;":                   '\U0000292A',
+	"szlig;":                    '\U000000DF',
+	"target;":                   '\U00002316',
+	"tau;":                      '\U000003C4',
+	"tbrk;":                     '\U000023B4',
+	"tcaron;":                   '\U00000165',
+	"tcedil;":                   '\U00000163',
+	"tcy;":                      '\U00000442',
+	"tdot;":                     '\U000020DB',
+	"telrec;":                   '\U00002315',
+	"tfr;":                      '\U0001D531',
+	"there4;":                   '\U00002234',
+	"therefore;":                '\U00002234',
+	"theta;":                    '\U000003B8',
+	"thetasym;":                 '\U000003D1',
+	"thetav;":                   '\U000003D1',
+	"thickapprox;":              '\U00002248',
+	"thicksim;":                 '\U0000223C',
+	"thinsp;":                   '\U00002009',
+	"thkap;":                    '\U00002248',
+	"thksim;":                   '\U0000223C',
+	"thorn;":                    '\U000000FE',
+	"tilde;":                    '\U000002DC',
+	"times;":                    '\U000000D7',
+	"timesb;":                   '\U000022A0',
+	"timesbar;":                 '\U00002A31',
+	"timesd;":                   '\U00002A30',
+	"tint;":                     '\U0000222D',
+	"toea;":                     '\U00002928',
+	"top;":                      '\U000022A4',
+	"topbot;":                   '\U00002336',
+	"topcir;":                   '\U00002AF1',
+	"topf;":                     '\U0001D565',
+	"topfork;":                  '\U00002ADA',
+	"tosa;":                     '\U00002929',
+	"tprime;":                   '\U00002034',
+	"trade;":                    '\U00002122',
+	"triangle;":                 '\U000025B5',
+	"triangledown;":             '\U000025BF',
+	"triangleleft;":             '\U000025C3',
+	"trianglelefteq;":           '\U000022B4',
+	"triangleq;":                '\U0000225C',
+	"triangleright;":            '\U000025B9',
+	"trianglerighteq;":          '\U000022B5',
+	"tridot;":                   '\U000025EC',
+	"trie;":                     '\U0000225C',
+	"triminus;":                 '\U00002A3A',
+	"triplus;":                  '\U00002A39',
+	"trisb;":                    '\U000029CD',
+	"tritime;":                  '\U00002A3B',
+	"trpezium;":                 '\U000023E2',
+	"tscr;":                     '\U0001D4C9',
+	"tscy;":                     '\U00000446',
+	"tshcy;":                    '\U0000045B',
+	"tstrok;":                   '\U00000167',
+	"twixt;":                    '\U0000226C',
+	"twoheadleftarrow;":         '\U0000219E',
+	"twoheadrightarrow;":        '\U000021A0',
+	"uArr;":                     '\U000021D1',
+	"uHar;":                     '\U00002963',
+	"uacute;":                   '\U000000FA',
+	"uarr;":                     '\U00002191',
+	"ubrcy;":                    '\U0000045E',
+	"ubreve;":                   '\U0000016D',
+	"ucirc;":                    '\U000000FB',
+	"ucy;":                      '\U00000443',
+	"udarr;":                    '\U000021C5',
+	"udblac;":                   '\U00000171',
+	"udhar;":                    '\U0000296E',
+	"ufisht;":                   '\U0000297E',
+	"ufr;":                      '\U0001D532',
+	"ugrave;":                   '\U000000F9',
+	"uharl;":                    '\U000021BF',
+	"uharr;":                    '\U000021BE',
+	"uhblk;":                    '\U00002580',
+	"ulcorn;":                   '\U0000231C',
+	"ulcorner;":                 '\U0000231C',
+	"ulcrop;":                   '\U0000230F',
+	"ultri;":                    '\U000025F8',
+	"umacr;":                    '\U0000016B',
+	"uml;":                      '\U000000A8',
+	"uogon;":                    '\U00000173',
+	"uopf;":                     '\U0001D566',
+	"uparrow;":                  '\U00002191',
+	"updownarrow;":              '\U00002195',
+	"upharpoonleft;":            '\U000021BF',
+	"upharpoonright;":           '\U000021BE',
+	"uplus;":                    '\U0000228E',
+	"upsi;":                     '\U000003C5',
+	"upsih;":                    '\U000003D2',
+	"upsilon;":                  '\U000003C5',
+	"upuparrows;":               '\U000021C8',
+	"urcorn;":                   '\U0000231D',
+	"urcorner;":                 '\U0000231D',
+	"urcrop;":                   '\U0000230E',
+	"uring;":                    '\U0000016F',
+	"urtri;":                    '\U000025F9',
+	"uscr;":                     '\U0001D4CA',
+	"utdot;":                    '\U000022F0',
+	"utilde;":                   '\U00000169',
+	"utri;":                     '\U000025B5',
+	"utrif;":                    '\U000025B4',
+	"uuarr;":                    '\U000021C8',
+	"uuml;":                     '\U000000FC',
+	"uwangle;":                  '\U000029A7',
+	"vArr;":                     '\U000021D5',
+	"vBar;":                     '\U00002AE8',
+	"vBarv;":                    '\U00002AE9',
+	"vDash;":                    '\U000022A8',
+	"vangrt;":                   '\U0000299C',
+	"varepsilon;":               '\U000003F5',
+	"varkappa;":                 '\U000003F0',
+	"varnothing;":               '\U00002205',
+	"varphi;":                   '\U000003D5',
+	"varpi;":                    '\U000003D6',
+	"varpropto;":                '\U0000221D',
+	"varr;":                     '\U00002195',
+	"varrho;":                   '\U000003F1',
+	"varsigma;":                 '\U000003C2',
+	"vartheta;":                 '\U000003D1',
+	"vartriangleleft;":          '\U000022B2',
+	"vartriangleright;":         '\U000022B3',
+	"vcy;":                      '\U00000432',
+	"vdash;":                    '\U000022A2',
+	"vee;":                      '\U00002228',
+	"veebar;":                   '\U000022BB',
+	"veeeq;":                    '\U0000225A',
+	"vellip;":                   '\U000022EE',
+	"verbar;":                   '\U0000007C',
+	"vert;":                     '\U0000007C',
+	"vfr;":                      '\U0001D533',
+	"vltri;":                    '\U000022B2',
+	"vopf;":                     '\U0001D567',
+	"vprop;":                    '\U0000221D',
+	"vrtri;":                    '\U000022B3',
+	"vscr;":                     '\U0001D4CB',
+	"vzigzag;":                  '\U0000299A',
+	"wcirc;":                    '\U00000175',
+	"wedbar;":                   '\U00002A5F',
+	"wedge;":                    '\U00002227',
+	"wedgeq;":                   '\U00002259',
+	"weierp;":                   '\U00002118',
+	"wfr;":                      '\U0001D534',
+	"wopf;":                     '\U0001D568',
+	"wp;":                       '\U00002118',
+	"wr;":                       '\U00002240',
+	"wreath;":                   '\U00002240',
+	"wscr;":                     '\U0001D4CC',
+	"xcap;":                     '\U000022C2',
+	"xcirc;":                    '\U000025EF',
+	"xcup;":                     '\U000022C3',
+	"xdtri;":                    '\U000025BD',
+	"xfr;":                      '\U0001D535',
+	"xhArr;":                    '\U000027FA',
+	"xharr;":                    '\U000027F7',
+	"xi;":                       '\U000003BE',
+	"xlArr;":                    '\U000027F8',
+	"xlarr;":                    '\U000027F5',
+	"xmap;":                     '\U000027FC',
+	"xnis;":                     '\U000022FB',
+	"xodot;":                    '\U00002A00',
+	"xopf;":                     '\U0001D569',
+	"xoplus;":                   '\U00002A01',
+	"xotime;":                   '\U00002A02',
+	"xrArr;":                    '\U000027F9',
+	"xrarr;":                    '\U000027F6',
+	"xscr;":                     '\U0001D4CD',
+	"xsqcup;":                   '\U00002A06',
+	"xuplus;":                   '\U00002A04',
+	"xutri;":                    '\U000025B3',
+	"xvee;":                     '\U000022C1',
+	"xwedge;":                   '\U000022C0',
+	"yacute;":                   '\U000000FD',
+	"yacy;":                     '\U0000044F',
+	"ycirc;":                    '\U00000177',
+	"ycy;":                      '\U0000044B',
+	"yen;":                      '\U000000A5',
+	"yfr;":                      '\U0001D536',
+	"yicy;":                     '\U00000457',
+	"yopf;":                     '\U0001D56A',
+	"yscr;":                     '\U0001D4CE',
+	"yucy;":                     '\U0000044E',
+	"yuml;":                     '\U000000FF',
+	"zacute;":                   '\U0000017A',
+	"zcaron;":                   '\U0000017E',
+	"zcy;":                      '\U00000437',
+	"zdot;":                     '\U0000017C',
+	"zeetrf;":                   '\U00002128',
+	"zeta;":                     '\U000003B6',
+	"zfr;":                      '\U0001D537',
+	"zhcy;":                     '\U00000436',
+	"zigrarr;":                  '\U000021DD',
+	"zopf;":                     '\U0001D56B',
+	"zscr;":                     '\U0001D4CF',
+	"zwj;":                      '\U0000200D',
+	"zwnj;":                     '\U0000200C',
+	"AElig":                     '\U000000C6',
+	"AMP":                       '\U00000026',
+	"Aacute":                    '\U000000C1',
+	"Acirc":                     '\U000000C2',
+	"Agrave":                    '\U000000C0',
+	"Aring":                     '\U000000C5',
+	"Atilde":                    '\U000000C3',
+	"Auml":                      '\U000000C4',
+	"COPY":                      '\U000000A9',
+	"Ccedil":                    '\U000000C7',
+	"ETH":                       '\U000000D0',
+	"Eacute":                    '\U000000C9',
+	"Ecirc":                     '\U000000CA',
+	"Egrave":                    '\U000000C8',
+	"Euml":                      '\U000000CB',
+	"GT":                        '\U0000003E',
+	"Iacute":                    '\U000000CD',
+	"Icirc":                     '\U000000CE',
+	"Igrave":                    '\U000000CC',
+	"Iuml":                      '\U000000CF',
+	"LT":                        '\U0000003C',
+	"Ntilde":                    '\U000000D1',
+	"Oacute":                    '\U000000D3',
+	"Ocirc":                     '\U000000D4',
+	"Ograve":                    '\U000000D2',
+	"Oslash":                    '\U000000D8',
+	"Otilde":                    '\U000000D5',
+	"Ouml":                      '\U000000D6',
+	"QUOT":                      '\U00000022',
+	"REG":                       '\U000000AE',
+	"THORN":                     '\U000000DE',
+	"Uacute":                    '\U000000DA',
+	"Ucirc":                     '\U000000DB',
+	"Ugrave":                    '\U000000D9',
+	"Uuml":                      '\U000000DC',
+	"Yacute":                    '\U000000DD',
+	"aacute":                    '\U000000E1',
+	"acirc":                     '\U000000E2',
+	"acute":                     '\U000000B4',
+	"aelig":                     '\U000000E6',
+	"agrave":                    '\U000000E0',
+	"amp":                       '\U00000026',
+	"aring":                     '\U000000E5',
+	"atilde":                    '\U000000E3',
+	"auml":                      '\U000000E4',
+	"brvbar":                    '\U000000A6',
+	"ccedil":                    '\U000000E7',
+	"cedil":                     '\U000000B8',
+	"cent":                      '\U000000A2',
+	"copy":                      '\U000000A9',
+	"curren":                    '\U000000A4',
+	"deg":                       '\U000000B0',
+	"divide":                    '\U000000F7',
+	"eacute":                    '\U000000E9',
+	"ecirc":                     '\U000000EA',
+	"egrave":                    '\U000000E8',
+	"eth":                       '\U000000F0',
+	"euml":                      '\U000000EB',
+	"frac12":                    '\U000000BD',
+	"frac14":                    '\U000000BC',
+	"frac34":                    '\U000000BE',
+	"gt":                        '\U0000003E',
+	"iacute":                    '\U000000ED',
+	"icirc":                     '\U000000EE',
+	"iexcl":                     '\U000000A1',
+	"igrave":                    '\U000000EC',
+	"iquest":                    '\U000000BF',
+	"iuml":                      '\U000000EF',
+	"laquo":                     '\U000000AB',
+	"lt":                        '\U0000003C',
+	"macr":                      '\U000000AF',
+	"micro":                     '\U000000B5',
+	"middot":                    '\U000000B7',
+	"nbsp":                      '\U000000A0',
+	"not":                       '\U000000AC',
+	"ntilde":                    '\U000000F1',
+	"oacute":                    '\U000000F3',
+	"ocirc":                     '\U000000F4',
+	"ograve":                    '\U000000F2',
+	"ordf":                      '\U000000AA',
+	"ordm":                      '\U000000BA',
+	"oslash":                    '\U000000F8',
+	"otilde":                    '\U000000F5',
+	"ouml":                      '\U000000F6',
+	"para":                      '\U000000B6',
+	"plusmn":                    '\U000000B1',
+	"pound":                     '\U000000A3',
+	"quot":                      '\U00000022',
+	"raquo":                     '\U000000BB',
+	"reg":                       '\U000000AE',
+	"sect":                      '\U000000A7',
+	"shy":                       '\U000000AD',
+	"sup1":                      '\U000000B9',
+	"sup2":                      '\U000000B2',
+	"sup3":                      '\U000000B3',
+	"szlig":                     '\U000000DF',
+	"thorn":                     '\U000000FE',
+	"times":                     '\U000000D7',
+	"uacute":                    '\U000000FA',
+	"ucirc":                     '\U000000FB',
+	"ugrave":                    '\U000000F9',
+	"uml":                       '\U000000A8',
+	"uuml":                      '\U000000FC',
+	"yacute":                    '\U000000FD',
+	"yen":                       '\U000000A5',
+	"yuml":                      '\U000000FF',
 }
 
 // HTML entities that are two unicode codepoints.
diff --git a/src/pkg/html/escape.go b/src/pkg/html/escape.go
index 24cb7af..eff0384 100644
--- a/src/pkg/html/escape.go
+++ b/src/pkg/html/escape.go
@@ -15,7 +15,7 @@ type writer interface {
 	WriteString(string) (int, error)
 }
 
-// These replacements permit compatibility with old numeric entities that 
+// These replacements permit compatibility with old numeric entities that
 // assumed Windows-1252 encoding.
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
 var replacementTable = [...]rune{
@@ -51,7 +51,7 @@ var replacementTable = [...]rune{
 	'\u009D',
 	'\u017E',
 	'\u0178', // Last entry is 0x9F.
-	// 0x00->'\uFFFD' is handled programmatically. 
+	// 0x00->'\uFFFD' is handled programmatically.
 	// 0x0D->'\u000D' is a no-op.
 }
 
diff --git a/src/pkg/html/template/content.go b/src/pkg/html/template/content.go
index c1bd2e4..9d1f74f 100644
--- a/src/pkg/html/template/content.go
+++ b/src/pkg/html/template/content.go
@@ -30,7 +30,7 @@ type (
 	HTMLAttr string
 
 	// JS encapsulates a known safe EcmaScript5 Expression, for example,
-	// `(x + y * z())`. 
+	// `(x + y * z())`.
 	// Template authors are responsible for ensuring that typed expressions
 	// do not break the intended precedence and that there is no
 	// statement/expression ambiguity as when passing an expression like
@@ -47,7 +47,7 @@ type (
 	// JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
 	JSStr string
 
-	// URL encapsulates a known safe URL as defined in RFC 3896.
+	// URL encapsulates a known safe URL or URL substring (see RFC 3986).
 	// A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()`
 	// from a trusted source should go in the page, but by default dynamic
 	// `javascript:` URLs are filtered out since they are a frequently
diff --git a/src/pkg/html/template/doc.go b/src/pkg/html/template/doc.go
index f470fac..d422ada 100644
--- a/src/pkg/html/template/doc.go
+++ b/src/pkg/html/template/doc.go
@@ -119,7 +119,7 @@ If {{.}} is the innocuous word, `left`, then it can appear more widely,
 Non-string values can be used in JavaScript contexts.
 If {{.}} is
 
-  []struct{A,B string}{ "foo", "bar" }
+  struct{A,B string}{ "foo", "bar" }
 
 in the escaped template
 
diff --git a/src/pkg/html/template/error.go b/src/pkg/html/template/error.go
index dcac748..46e49cc 100644
--- a/src/pkg/html/template/error.go
+++ b/src/pkg/html/template/error.go
@@ -102,7 +102,7 @@ const (
 	//
 	//   {{define "main"}} <script>{{template "helper"}}</script> {{end}}
 	//   {{define "helper"}} document.write(' <div title=" ') {{end}}
-	// 
+	//
 	//   "helper" does not produce a valid document fragment, so should
 	//   not be Executed directly.
 	ErrEndContext
@@ -161,7 +161,7 @@ const (
 	//   In the example, there is missing a quote, so it is not clear
 	//   whether {{.}} is meant to be inside a JS string or in a JS value
 	//   context.  The second iteration would produce something like
-	// 
+	//
 	//     <script>var x = ['firstValue,'secondValue]</script>
 	ErrRangeLoopReentry
 
diff --git a/src/pkg/html/template/escape.go b/src/pkg/html/template/escape.go
index 5f0e28e..4829bfc 100644
--- a/src/pkg/html/template/escape.go
+++ b/src/pkg/html/template/escape.go
@@ -220,10 +220,7 @@ func ensurePipelineContains(p *parse.PipeNode, s []string) {
 	idents := p.Cmds
 	for i := n - 1; i >= 0; i-- {
 		if cmd := p.Cmds[i]; len(cmd.Args) != 0 {
-			if id, ok := cmd.Args[0].(*parse.IdentifierNode); ok {
-				if id.Ident == "noescape" {
-					return
-				}
+			if _, ok := cmd.Args[0].(*parse.IdentifierNode); ok {
 				continue
 			}
 		}
@@ -242,10 +239,11 @@ func ensurePipelineContains(p *parse.PipeNode, s []string) {
 	copy(newCmds, p.Cmds)
 	// Merge existing identifier commands with the sanitizers needed.
 	for _, id := range idents {
+		pos := id.Args[0].Position()
 		i := indexOfStr((id.Args[0].(*parse.IdentifierNode)).Ident, s, escFnsEq)
 		if i != -1 {
 			for _, name := range s[:i] {
-				newCmds = appendCmd(newCmds, newIdentCmd(name))
+				newCmds = appendCmd(newCmds, newIdentCmd(name, pos))
 			}
 			s = s[i+1:]
 		}
@@ -253,7 +251,7 @@ func ensurePipelineContains(p *parse.PipeNode, s []string) {
 	}
 	// Create any remaining sanitizers.
 	for _, name := range s {
-		newCmds = appendCmd(newCmds, newIdentCmd(name))
+		newCmds = appendCmd(newCmds, newIdentCmd(name, p.Position()))
 	}
 	p.Cmds = newCmds
 }
@@ -315,10 +313,10 @@ func escFnsEq(a, b string) bool {
 }
 
 // newIdentCmd produces a command containing a single identifier node.
-func newIdentCmd(identifier string) *parse.CommandNode {
+func newIdentCmd(identifier string, pos parse.Pos) *parse.CommandNode {
 	return &parse.CommandNode{
 		NodeType: parse.NodeCommand,
-		Args:     []parse.Node{parse.NewIdentifier(identifier)},
+		Args:     []parse.Node{parse.NewIdentifier(identifier).SetPos(pos)},
 	}
 }
 
diff --git a/src/pkg/html/template/escape_test.go b/src/pkg/html/template/escape_test.go
index ce12c17..de3659b 100644
--- a/src/pkg/html/template/escape_test.go
+++ b/src/pkg/html/template/escape_test.go
@@ -551,11 +551,6 @@ func TestEscape(t *testing.T) {
 			"<textarea><a><b></textarea>",
 		},
 		{
-			"auditable exemption from escaping",
-			"{{range .A}}{{. | noescape}}{{end}}",
-			"<a><b>",
-		},
-		{
 			"No tag injection",
 			`{{"10$"}}<{{"script src,evil.org/pwnd.js"}}...`,
 			`10$<script src,evil.org/pwnd.js...`,
@@ -659,12 +654,6 @@ func TestEscape(t *testing.T) {
 
 	for _, test := range tests {
 		tmpl := New(test.name)
-		// TODO: Move noescape into template/func.go
-		tmpl.Funcs(FuncMap{
-			"noescape": func(a ...interface{}) string {
-				return fmt.Sprint(a...)
-			},
-		})
 		tmpl = Must(tmpl.Parse(test.input))
 		b := new(bytes.Buffer)
 		if err := tmpl.Execute(b, data); err != nil {
@@ -1539,6 +1528,11 @@ func TestEnsurePipelineContains(t *testing.T) {
 			".X | urlquery | html | print",
 			[]string{"urlquery", "html"},
 		},
+		{
+			"{{($).X | html | print}}",
+			"($).X | urlquery | html | print",
+			[]string{"urlquery", "html"},
+		},
 	}
 	for i, test := range tests {
 		tmpl := template.Must(template.New("test").Parse(test.input))
diff --git a/src/pkg/html/template/html.go b/src/pkg/html/template/html.go
index 36c88e2..f25f107 100644
--- a/src/pkg/html/template/html.go
+++ b/src/pkg/html/template/html.go
@@ -106,7 +106,7 @@ var htmlNospaceReplacementTable = []string{
 	'<':  "<",
 	'=':  "=",
 	'>':  ">",
-	// A parse error in the attribute value (unquoted) and 
+	// A parse error in the attribute value (unquoted) and
 	// before attribute value states.
 	// Treated as a quoting character by IE.
 	'`': "`",
@@ -128,7 +128,7 @@ var htmlNospaceNormReplacementTable = []string{
 	'<':  "<",
 	'=':  "=",
 	'>':  ">",
-	// A parse error in the attribute value (unquoted) and 
+	// A parse error in the attribute value (unquoted) and
 	// before attribute value states.
 	// Treated as a quoting character by IE.
 	'`': "`",
@@ -143,7 +143,7 @@ func htmlReplacer(s string, replacementTable []string, badRunes bool) string {
 			if repl := replacementTable[r]; len(repl) != 0 {
 				b.WriteString(s[written:i])
 				b.WriteString(repl)
-				// Valid as long as replacementTable doesn't 
+				// Valid as long as replacementTable doesn't
 				// include anything above 0x7f.
 				written = i + utf8.RuneLen(r)
 			}
diff --git a/src/pkg/html/template/js.go b/src/pkg/html/template/js.go
index a895a50..a974093 100644
--- a/src/pkg/html/template/js.go
+++ b/src/pkg/html/template/js.go
@@ -14,7 +14,7 @@ import (
 )
 
 // nextJSCtx returns the context that determines whether a slash after the
-// given run of tokens tokens starts a regular expression instead of a division
+// given run of tokens starts a regular expression instead of a division
 // operator: / or /=.
 //
 // This assumes that the token run does not include any string tokens, comment
diff --git a/src/pkg/html/template/template.go b/src/pkg/html/template/template.go
index edac733..768cee7 100644
--- a/src/pkg/html/template/template.go
+++ b/src/pkg/html/template/template.go
@@ -14,8 +14,8 @@ import (
 	"text/template/parse"
 )
 
-// Template is a specialized template.Template that produces a safe HTML
-// document fragment.
+// Template is a specialized Template from "text/template" that produces a safe
+// HTML document fragment.
 type Template struct {
 	escaped bool
 	// We could embed the text/template field, but it's safer not to because
@@ -238,7 +238,8 @@ func (t *Template) Name() string {
 // return values of which the second has type error. In that case, if the
 // second (error) argument evaluates to non-nil during execution, execution
 // terminates and Execute returns that error. FuncMap has the same base type
-// as template.FuncMap, copied here so clients need not import "text/template".
+// as FuncMap in "text/template", copied here so clients need not import
+// "text/template".
 type FuncMap map[string]interface{}
 
 // Funcs adds the elements of the argument map to the template's function map.
@@ -268,7 +269,10 @@ func (t *Template) Lookup(name string) *Template {
 	return t.set[name]
 }
 
-// Must panics if err is non-nil in the same way as template.Must.
+// Must is a helper that wraps a call to a function returning (*Template, error)
+// and panics if the error is non-nil. It is intended for use in variable initializations
+// such as
+//	var t = template.Must(template.New("name").Parse("html"))
 func Must(t *Template, err error) *Template {
 	if err != nil {
 		panic(err)
diff --git a/src/pkg/html/template/url.go b/src/pkg/html/template/url.go
index 454c791..2ca76bf 100644
--- a/src/pkg/html/template/url.go
+++ b/src/pkg/html/template/url.go
@@ -60,7 +60,7 @@ func urlProcessor(norm bool, args ...interface{}) string {
 		c := s[i]
 		switch c {
 		// Single quote and parens are sub-delims in RFC 3986, but we
-		// escape them so the output can be embedded in in single
+		// escape them so the output can be embedded in single
 		// quoted attributes and unquoted CSS url(...) constructs.
 		// Single quotes are reserved in URLs, but are only used in
 		// the obsolete "mark" rule in an appendix in RFC 3986
diff --git a/src/pkg/image/decode_test.go b/src/pkg/image/decode_test.go
index d659867..8dee57e 100644
--- a/src/pkg/image/decode_test.go
+++ b/src/pkg/image/decode_test.go
@@ -31,6 +31,7 @@ var imageTests = []imageTest{
 	{"testdata/video-001.png", "testdata/video-001.5bpp.gif", 128 << 8},
 	// JPEG is a lossy format and hence needs a non-zero tolerance.
 	{"testdata/video-001.png", "testdata/video-001.jpeg", 8 << 8},
+	{"testdata/video-001.png", "testdata/video-001.progressive.jpeg", 8 << 8},
 	// Grayscale images.
 	{"testdata/video-005.gray.png", "testdata/video-005.gray.jpeg", 8 << 8},
 	{"testdata/video-005.gray.png", "testdata/video-005.gray.png", 0},
diff --git a/src/pkg/image/draw/draw.go b/src/pkg/image/draw/draw.go
index bef325c..56d30dd 100644
--- a/src/pkg/image/draw/draw.go
+++ b/src/pkg/image/draw/draw.go
@@ -81,8 +81,9 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
 					drawNRGBAOver(dst0, r, src0, sp)
 					return
 				case *image.YCbCr:
-					drawYCbCr(dst0, r, src0, sp)
-					return
+					if drawYCbCr(dst0, r, src0, sp) {
+						return
+					}
 				}
 			} else if mask0, ok := mask.(*image.Alpha); ok {
 				switch src0 := src.(type) {
@@ -104,8 +105,9 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
 					drawNRGBASrc(dst0, r, src0, sp)
 					return
 				case *image.YCbCr:
-					drawYCbCr(dst0, r, src0, sp)
-					return
+					if drawYCbCr(dst0, r, src0, sp) {
+						return
+					}
 				}
 			}
 		}
@@ -345,7 +347,7 @@ func drawNRGBASrc(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image
 	}
 }
 
-func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) {
+func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) (ok bool) {
 	// An image.YCbCr is always fully opaque, and so if the mask is implicitly nil
 	// (i.e. fully opaque) then the op is effectively always Src.
 	x0 := (r.Min.X - dst.Rect.Min.X) * 4
@@ -353,6 +355,19 @@ func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po
 	y0 := r.Min.Y - dst.Rect.Min.Y
 	y1 := r.Max.Y - dst.Rect.Min.Y
 	switch src.SubsampleRatio {
+	case image.YCbCrSubsampleRatio444:
+		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
+			dpix := dst.Pix[y*dst.Stride:]
+			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
+			ci := (sy-src.Rect.Min.Y)*src.CStride + (sp.X - src.Rect.Min.X)
+			for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
+				rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
+				dpix[x+0] = rr
+				dpix[x+1] = gg
+				dpix[x+2] = bb
+				dpix[x+3] = 255
+			}
+		}
 	case image.YCbCrSubsampleRatio422:
 		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
 			dpix := dst.Pix[y*dst.Stride:]
@@ -381,12 +396,11 @@ func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po
 				dpix[x+3] = 255
 			}
 		}
-	default:
-		// Default to 4:4:4 subsampling.
+	case image.YCbCrSubsampleRatio440:
 		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
 			dpix := dst.Pix[y*dst.Stride:]
 			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
-			ci := (sy-src.Rect.Min.Y)*src.CStride + (sp.X - src.Rect.Min.X)
+			ci := (sy/2-src.Rect.Min.Y/2)*src.CStride + (sp.X - src.Rect.Min.X)
 			for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
 				rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
 				dpix[x+0] = rr
@@ -395,7 +409,10 @@ func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po
 				dpix[x+3] = 255
 			}
 		}
+	default:
+		return false
 	}
+	return true
 }
 
 func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) {
diff --git a/src/pkg/image/format.go b/src/pkg/image/format.go
index f93d356..36635bc 100644
--- a/src/pkg/image/format.go
+++ b/src/pkg/image/format.go
@@ -39,7 +39,7 @@ type reader interface {
 	Peek(int) ([]byte, error)
 }
 
-// AsReader converts an io.Reader to a reader.
+// asReader converts an io.Reader to a reader.
 func asReader(r io.Reader) reader {
 	if rr, ok := r.(reader); ok {
 		return rr
diff --git a/src/pkg/image/jpeg/dct_test.go b/src/pkg/image/jpeg/dct_test.go
new file mode 100644
index 0000000..7389f7e
--- /dev/null
+++ b/src/pkg/image/jpeg/dct_test.go
@@ -0,0 +1,299 @@
+// 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 jpeg
+
+import (
+	"bytes"
+	"fmt"
+	"math"
+	"math/rand"
+	"testing"
+)
+
+func benchmarkDCT(b *testing.B, f func(*block)) {
+	b.StopTimer()
+	blocks := make([]block, 0, b.N*len(testBlocks))
+	for i := 0; i < b.N; i++ {
+		blocks = append(blocks, testBlocks[:]...)
+	}
+	b.StartTimer()
+	for i := range blocks {
+		f(&blocks[i])
+	}
+}
+
+func BenchmarkFDCT(b *testing.B) {
+	benchmarkDCT(b, fdct)
+}
+
+func BenchmarkIDCT(b *testing.B) {
+	benchmarkDCT(b, idct)
+}
+
+func TestDCT(t *testing.T) {
+	blocks := make([]block, len(testBlocks))
+	copy(blocks, testBlocks[:])
+
+	// Append some randomly generated blocks of varying sparseness.
+	r := rand.New(rand.NewSource(123))
+	for i := 0; i < 100; i++ {
+		b := block{}
+		n := r.Int() % 64
+		for j := 0; j < n; j++ {
+			b[r.Int()%len(b)] = r.Int31() % 256
+		}
+		blocks = append(blocks, b)
+	}
+
+	// Check that the FDCT and IDCT functions are inverses, after a scale and
+	// level shift. Scaling reduces the rounding errors in the conversion from
+	// floats to ints.
+	for i, b := range blocks {
+		got, want := b, b
+		for j := range got {
+			got[j] = (got[j] - 128) * 8
+		}
+		slowFDCT(&got)
+		slowIDCT(&got)
+		for j := range got {
+			got[j] = got[j]/8 + 128
+		}
+		if differ(&got, &want) {
+			t.Errorf("i=%d: IDCT(FDCT)\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
+		}
+	}
+
+	// Check that the optimized and slow FDCT implementations agree.
+	// The fdct function already does a scale and level shift.
+	for i, b := range blocks {
+		got, want := b, b
+		fdct(&got)
+		for j := range want {
+			want[j] = (want[j] - 128) * 8
+		}
+		slowFDCT(&want)
+		if differ(&got, &want) {
+			t.Errorf("i=%d: FDCT\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
+		}
+	}
+
+	// Check that the optimized and slow IDCT implementations agree.
+	for i, b := range blocks {
+		got, want := b, b
+		idct(&got)
+		slowIDCT(&want)
+		if differ(&got, &want) {
+			t.Errorf("i=%d: IDCT\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
+		}
+	}
+}
+
+// differ returns whether any pair-wise elements in b0 and b1 differ by 2 or
+// more. That tolerance is because there isn't a single definitive decoding of
+// a given JPEG image, even before the YCbCr to RGB conversion; implementations
+// can have different IDCT rounding errors.
+func differ(b0, b1 *block) bool {
+	for i := range b0 {
+		delta := b0[i] - b1[i]
+		if delta < -2 || +2 < delta {
+			return true
+		}
+	}
+	return false
+}
+
+// alpha returns 1 if i is 0 and returns √2 otherwise.
+func alpha(i int) float64 {
+	if i == 0 {
+		return 1
+	}
+	return math.Sqrt2
+}
+
+var cosines [32]float64 // cosines[k] = cos(π/2 * k/8)
+
+func init() {
+	for k := range cosines {
+		cosines[k] = math.Cos(math.Pi * float64(k) / 16)
+	}
+}
+
+// slowFDCT performs the 8*8 2-dimensional forward discrete cosine transform:
+//
+//	dst[u,v] = (1/8) * Σ_x Σ_y alpha(u) * alpha(v) * src[x,y] *
+//		cos((π/2) * (2*x + 1) * u / 8) *
+//		cos((π/2) * (2*y + 1) * v / 8)
+//
+// x and y are in pixel space, and u and v are in transform space.
+//
+// b acts as both dst and src.
+func slowFDCT(b *block) {
+	var dst [blockSize]float64
+	for v := 0; v < 8; v++ {
+		for u := 0; u < 8; u++ {
+			sum := 0.0
+			for y := 0; y < 8; y++ {
+				for x := 0; x < 8; x++ {
+					sum += alpha(u) * alpha(v) * float64(b[8*y+x]) *
+						cosines[((2*x+1)*u)%32] *
+						cosines[((2*y+1)*v)%32]
+				}
+			}
+			dst[8*v+u] = sum / 8
+		}
+	}
+	// Convert from float64 to int32.
+	for i := range dst {
+		b[i] = int32(dst[i] + 0.5)
+	}
+}
+
+// slowIDCT performs the 8*8 2-dimensional inverse discrete cosine transform:
+//
+//	dst[x,y] = (1/8) * Σ_u Σ_v alpha(u) * alpha(v) * src[u,v] *
+//		cos((π/2) * (2*x + 1) * u / 8) *
+//		cos((π/2) * (2*y + 1) * v / 8)
+//
+// x and y are in pixel space, and u and v are in transform space.
+//
+// b acts as both dst and src.
+func slowIDCT(b *block) {
+	var dst [blockSize]float64
+	for y := 0; y < 8; y++ {
+		for x := 0; x < 8; x++ {
+			sum := 0.0
+			for v := 0; v < 8; v++ {
+				for u := 0; u < 8; u++ {
+					sum += alpha(u) * alpha(v) * float64(b[8*v+u]) *
+						cosines[((2*x+1)*u)%32] *
+						cosines[((2*y+1)*v)%32]
+				}
+			}
+			dst[8*y+x] = sum / 8
+		}
+	}
+	// Convert from float64 to int32.
+	for i := range dst {
+		b[i] = int32(dst[i] + 0.5)
+	}
+}
+
+func (b *block) String() string {
+	s := bytes.NewBuffer(nil)
+	fmt.Fprintf(s, "{\n")
+	for y := 0; y < 8; y++ {
+		fmt.Fprintf(s, "\t")
+		for x := 0; x < 8; x++ {
+			fmt.Fprintf(s, "0x%04x, ", uint16(b[8*y+x]))
+		}
+		fmt.Fprintln(s)
+	}
+	fmt.Fprintf(s, "}")
+	return s.String()
+}
+
+// testBlocks are the first 10 pre-IDCT blocks from ../testdata/video-001.jpeg.
+var testBlocks = [10]block{
+	{
+		0x7f, 0xf6, 0x01, 0x07, 0xff, 0x00, 0x00, 0x00,
+		0xf5, 0x01, 0xfa, 0x01, 0xfe, 0x00, 0x01, 0x00,
+		0x05, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0xff, 0xf8, 0x00, 0x01, 0xff, 0x00, 0x00,
+		0x00, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00,
+		0xff, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01,
+		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x01, 0xff, 0x01, 0x00, 0xfe,
+	},
+	{
+		0x29, 0x07, 0x00, 0xfc, 0x01, 0x01, 0x00, 0x00,
+		0x07, 0x00, 0x03, 0x00, 0x01, 0x00, 0xff, 0xff,
+		0xff, 0xfd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x04, 0x00, 0xff, 0x01, 0x00, 0x00,
+		0x01, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0xfa, 0x01, 0x00, 0x01, 0x00, 0x01, 0xff,
+		0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x02,
+	},
+	{
+		0xc5, 0xfa, 0x01, 0x00, 0x00, 0x01, 0x00, 0xff,
+		0x02, 0xff, 0x01, 0x00, 0x01, 0x00, 0xff, 0x00,
+		0xff, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00,
+		0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+		0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	},
+	{
+		0x86, 0x05, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00,
+		0xf2, 0x06, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
+		0xf6, 0xfa, 0xf9, 0x00, 0xff, 0x01, 0x00, 0x00,
+		0xf9, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
+		0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0x01, 0x00,
+		0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01,
+		0x00, 0x01, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00,
+	},
+	{
+		0x24, 0xfe, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
+		0x08, 0xfd, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00,
+		0x06, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00,
+		0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
+		0x01, 0x00, 0x01, 0xff, 0x00, 0x01, 0x00, 0x00,
+		0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x01,
+	},
+	{
+		0xcd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+		0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+		0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
+		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff,
+	},
+	{
+		0x81, 0xfe, 0x05, 0xff, 0x01, 0xff, 0x01, 0x00,
+		0xef, 0xf9, 0x00, 0xf9, 0x00, 0xff, 0x00, 0xff,
+		0x05, 0xf9, 0x00, 0xf8, 0x01, 0xff, 0x01, 0xff,
+		0x00, 0xff, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01,
+		0xff, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00,
+		0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
+	},
+	{
+		0x28, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x0b, 0x02, 0x01, 0x03, 0x00, 0xff, 0x00, 0x01,
+		0xfe, 0x02, 0x01, 0x03, 0xff, 0x00, 0x00, 0x00,
+		0x01, 0x00, 0xfd, 0x00, 0x01, 0x00, 0xff, 0x00,
+		0x01, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x00, 0xff,
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01,
+	},
+	{
+		0xdf, 0xf9, 0xfe, 0x00, 0x03, 0x01, 0xff, 0xff,
+		0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0xff, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01,
+		0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01,
+		0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+		0x00, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x01,
+		0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+	},
+	{
+		0x88, 0xfd, 0x00, 0x00, 0xff, 0x00, 0x01, 0xff,
+		0xe1, 0x06, 0x06, 0x01, 0xff, 0x00, 0x01, 0x00,
+		0x08, 0x00, 0xfa, 0x00, 0xff, 0xff, 0xff, 0xff,
+		0x08, 0x01, 0x00, 0xff, 0x01, 0xff, 0x00, 0x00,
+		0xf5, 0xff, 0x00, 0x01, 0xff, 0x01, 0x01, 0x00,
+		0xff, 0xff, 0x01, 0xff, 0x01, 0x00, 0x01, 0x00,
+		0x00, 0x01, 0x01, 0xff, 0x00, 0xff, 0x00, 0x01,
+		0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
+	},
+}
diff --git a/src/pkg/image/jpeg/huffman.go b/src/pkg/image/jpeg/huffman.go
index d238249..9b731fd 100644
--- a/src/pkg/image/jpeg/huffman.go
+++ b/src/pkg/image/jpeg/huffman.go
@@ -15,9 +15,9 @@ 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 int // accumulator.
-	n int // the number of unread bits in a.
-	m int // mask. m==1<<(n-1) when n>0, with m==0 when n==0.
+	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.
@@ -39,7 +39,7 @@ func (d *decoder) ensureNBits(n int) error {
 		if err != nil {
 			return err
 		}
-		d.b.a = d.b.a<<8 | int(c)
+		d.b.a = d.b.a<<8 | uint32(c)
 		d.b.n += 8
 		if d.b.m == 0 {
 			d.b.m = 1 << 7
@@ -61,15 +61,16 @@ func (d *decoder) ensureNBits(n int) error {
 }
 
 // The composition of RECEIVE and EXTEND, specified in section F.2.2.1.
-func (d *decoder) receiveExtend(t uint8) (int, error) {
-	err := d.ensureNBits(int(t))
-	if err != nil {
-		return 0, err
+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 := 1 << t
-	x := (d.b.a >> uint8(d.b.n)) & (s - 1)
+	s := int32(1) << t
+	x := int32(d.b.a>>uint8(d.b.n)) & (s - 1)
 	if x < s>>1 {
 		x += ((-1) << t) + 1
 	}
@@ -92,8 +93,7 @@ func (d *decoder) processDHT(n int) error {
 			return FormatError("bad Tc value")
 		}
 		th := d.tmp[0] & 0x0f
-		const isBaseline = true // Progressive mode is not yet supported.
-		if th > maxTh || isBaseline && th > 1 {
+		if th > maxTh || !d.progressive && th > 1 {
 			return FormatError("bad Th value")
 		}
 		h := &d.huff[tc][th]
@@ -163,15 +163,16 @@ func (d *decoder) processDHT(n int) error {
 
 // 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 at time, ought to be faster.
+// 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++ {
-		err := d.ensureNBits(1)
-		if err != nil {
-			return 0, err
+		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
@@ -185,3 +186,28 @@ func (d *decoder) decodeHuffman(h *huffman) (uint8, error) {
 	}
 	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/image/jpeg/idct.go b/src/pkg/image/jpeg/idct.go
index b387dfd..46fcaec 100644
--- a/src/pkg/image/jpeg/idct.go
+++ b/src/pkg/image/jpeg/idct.go
@@ -37,6 +37,10 @@ package jpeg
  *
  */
 
+const blockSize = 64 // A DCT block is 8x8.
+
+type block [blockSize]int32
+
 const (
 	w1 = 2841 // 2048*sqrt(2)*cos(1*pi/16)
 	w2 = 2676 // 2048*sqrt(2)*cos(2*pi/16)
@@ -55,9 +59,7 @@ const (
 	r2 = 181 // 256/sqrt(2)
 )
 
-// idct performs a 2-D Inverse Discrete Cosine Transformation, followed by a
-// +128 level shift and a clip to [0, 255], writing the results to dst.
-// stride is the number of elements between successive rows of dst.
+// idct performs a 2-D Inverse Discrete Cosine Transformation.
 //
 // The input coefficients should already have been multiplied by the
 // appropriate quantization table. We use fixed-point computation, with the
@@ -67,33 +69,34 @@ const (
 // For more on the actual algorithm, see Z. Wang, "Fast algorithms for the
 // discrete W transform and for the discrete Fourier transform", IEEE Trans. on
 // ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984.
-func idct(dst []byte, stride int, src *block) {
+func idct(src *block) {
 	// Horizontal 1-D IDCT.
 	for y := 0; y < 8; y++ {
+		y8 := y * 8
 		// If all the AC components are zero, then the IDCT is trivial.
-		if src[y*8+1] == 0 && src[y*8+2] == 0 && src[y*8+3] == 0 &&
-			src[y*8+4] == 0 && src[y*8+5] == 0 && src[y*8+6] == 0 && src[y*8+7] == 0 {
-			dc := src[y*8+0] << 3
-			src[y*8+0] = dc
-			src[y*8+1] = dc
-			src[y*8+2] = dc
-			src[y*8+3] = dc
-			src[y*8+4] = dc
-			src[y*8+5] = dc
-			src[y*8+6] = dc
-			src[y*8+7] = dc
+		if src[y8+1] == 0 && src[y8+2] == 0 && src[y8+3] == 0 &&
+			src[y8+4] == 0 && src[y8+5] == 0 && src[y8+6] == 0 && src[y8+7] == 0 {
+			dc := src[y8+0] << 3
+			src[y8+0] = dc
+			src[y8+1] = dc
+			src[y8+2] = dc
+			src[y8+3] = dc
+			src[y8+4] = dc
+			src[y8+5] = dc
+			src[y8+6] = dc
+			src[y8+7] = dc
 			continue
 		}
 
 		// Prescale.
-		x0 := (src[y*8+0] << 11) + 128
-		x1 := src[y*8+4] << 11
-		x2 := src[y*8+6]
-		x3 := src[y*8+2]
-		x4 := src[y*8+1]
-		x5 := src[y*8+7]
-		x6 := src[y*8+5]
-		x7 := src[y*8+3]
+		x0 := (src[y8+0] << 11) + 128
+		x1 := src[y8+4] << 11
+		x2 := src[y8+6]
+		x3 := src[y8+2]
+		x4 := src[y8+1]
+		x5 := src[y8+7]
+		x6 := src[y8+5]
+		x7 := src[y8+3]
 
 		// Stage 1.
 		x8 := w7 * (x4 + x5)
@@ -123,14 +126,14 @@ func idct(dst []byte, stride int, src *block) {
 		x4 = (r2*(x4-x5) + 128) >> 8
 
 		// Stage 4.
-		src[8*y+0] = (x7 + x1) >> 8
-		src[8*y+1] = (x3 + x2) >> 8
-		src[8*y+2] = (x0 + x4) >> 8
-		src[8*y+3] = (x8 + x6) >> 8
-		src[8*y+4] = (x8 - x6) >> 8
-		src[8*y+5] = (x0 - x4) >> 8
-		src[8*y+6] = (x3 - x2) >> 8
-		src[8*y+7] = (x7 - x1) >> 8
+		src[y8+0] = (x7 + x1) >> 8
+		src[y8+1] = (x3 + x2) >> 8
+		src[y8+2] = (x0 + x4) >> 8
+		src[y8+3] = (x8 + x6) >> 8
+		src[y8+4] = (x8 - x6) >> 8
+		src[y8+5] = (x0 - x4) >> 8
+		src[y8+6] = (x3 - x2) >> 8
+		src[y8+7] = (x7 - x1) >> 8
 	}
 
 	// Vertical 1-D IDCT.
@@ -186,19 +189,4 @@ func idct(dst []byte, stride int, src *block) {
 		src[8*6+x] = (y3 - y2) >> 14
 		src[8*7+x] = (y7 - y1) >> 14
 	}
-
-	// Level shift by +128, clip to [0, 255], and write to dst.
-	for y := 0; y < 8; y++ {
-		for x := 0; x < 8; x++ {
-			c := src[y*8+x]
-			if c < -128 {
-				c = 0
-			} else if c > 127 {
-				c = 255
-			} else {
-				c += 128
-			}
-			dst[y*stride+x] = uint8(c)
-		}
-	}
 }
diff --git a/src/pkg/image/jpeg/reader.go b/src/pkg/image/jpeg/reader.go
index d9adf6e..1ee6bbc 100644
--- a/src/pkg/image/jpeg/reader.go
+++ b/src/pkg/image/jpeg/reader.go
@@ -35,11 +35,7 @@ type component struct {
 	tq uint8 // Quantization table destination selector.
 }
 
-type block [blockSize]int
-
 const (
-	blockSize = 64 // A DCT block is 8x8.
-
 	dcTable = 0
 	acTable = 1
 	maxTc   = 1
@@ -51,7 +47,7 @@ const (
 	// A color JPEG image has Y, Cb and Cr components.
 	nColorComponent = 3
 
-	// We only support 4:4:4, 4:2:2 and 4:2:0 downsampling, and therefore the
+	// We only support 4:4:4, 4:4:0, 4:2:2 and 4:2:0 downsampling, and therefore the
 	// number of luma samples per chroma sample is at most 2 in the horizontal
 	// and 2 in the vertical direction.
 	maxH = 2
@@ -74,7 +70,9 @@ const (
 	comMarker   = 0xfe // COMment.
 )
 
-// Maps from the zig-zag ordering to the natural ordering.
+// unzig maps from the zig-zag ordering to the natural ordering. For example,
+// unzig[3] is the column and row of the fourth element in zig-zag order. The
+// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2).
 var unzig = [blockSize]int{
 	0, 1, 8, 16, 9, 2, 3, 10,
 	17, 24, 32, 25, 18, 11, 4, 5,
@@ -94,15 +92,18 @@ type Reader interface {
 
 type decoder struct {
 	r             Reader
+	b             bits
 	width, height int
 	img1          *image.Gray
 	img3          *image.YCbCr
 	ri            int // Restart Interval.
 	nComp         int
+	progressive   bool
+	eobRun        uint16 // End-of-Band run, specified in section G.1.2.2.
 	comp          [nColorComponent]component
+	progCoeffs    [nColorComponent][]block // Saved state between progressive-mode scans.
 	huff          [maxTc + 1][maxTh + 1]huffman
-	quant         [maxTq + 1]block
-	b             bits
+	quant         [maxTq + 1]block // Quantization tables, in zig-zag order.
 	tmp           [1024]byte
 }
 
@@ -146,20 +147,33 @@ func (d *decoder) processSOF(n int) error {
 		return UnsupportedError("SOF has wrong number of image components")
 	}
 	for i := 0; i < d.nComp; i++ {
-		hv := d.tmp[7+3*i]
-		d.comp[i].h = int(hv >> 4)
-		d.comp[i].v = int(hv & 0x0f)
 		d.comp[i].c = d.tmp[6+3*i]
 		d.comp[i].tq = d.tmp[8+3*i]
 		if d.nComp == nGrayComponent {
+			// If a JPEG image has only one component, section A.2 says "this data
+			// is non-interleaved by definition" and section A.2.2 says "[in this
+			// case...] the order of data units within a scan shall be left-to-right
+			// and top-to-bottom... regardless of the values of H_1 and V_1". Section
+			// 4.8.2 also says "[for non-interleaved data], the MCU is defined to be
+			// one data unit". Similarly, section A.1.1 explains that it is the ratio
+			// of H_i to max_j(H_j) that matters, and similarly for V. For grayscale
+			// images, H_1 is the maximum H_j for all components j, so that ratio is
+			// always 1. The component's (h, v) is effectively always (1, 1): even if
+			// the nominal (h, v) is (2, 1), a 20x5 image is encoded in three 8x8
+			// MCUs, not two 16x8 MCUs.
+			d.comp[i].h = 1
+			d.comp[i].v = 1
 			continue
 		}
-		// For color images, we only support 4:4:4, 4:2:2 or 4:2:0 chroma
+		hv := d.tmp[7+3*i]
+		d.comp[i].h = int(hv >> 4)
+		d.comp[i].v = int(hv & 0x0f)
+		// For color images, we only support 4:4:4, 4:4:0, 4:2:2 or 4:2:0 chroma
 		// downsampling ratios. This implies that the (h, v) values for the Y
-		// component are either (1, 1), (2, 1) or (2, 2), and the (h, v)
+		// component are either (1, 1), (1, 2), (2, 1) or (2, 2), and the (h, v)
 		// values for the Cr and Cb components must be (1, 1).
 		if i == 0 {
-			if hv != 0x11 && hv != 0x21 && hv != 0x22 {
+			if hv != 0x11 && hv != 0x21 && hv != 0x22 && hv != 0x12 {
 				return UnsupportedError("luma downsample ratio")
 			}
 		} else if hv != 0x11 {
@@ -186,7 +200,7 @@ func (d *decoder) processDQT(n int) error {
 			return FormatError("bad Tq value")
 		}
 		for i := range d.quant[tq] {
-			d.quant[tq][i] = int(d.tmp[i+1])
+			d.quant[tq][i] = int32(d.tmp[i+1])
 		}
 	}
 	if n != 0 {
@@ -195,161 +209,6 @@ func (d *decoder) processDQT(n int) error {
 	return nil
 }
 
-// makeImg allocates and initializes the destination image.
-func (d *decoder) makeImg(h0, v0, mxx, myy int) {
-	if d.nComp == nGrayComponent {
-		m := image.NewGray(image.Rect(0, 0, 8*mxx, 8*myy))
-		d.img1 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.Gray)
-		return
-	}
-	var subsampleRatio image.YCbCrSubsampleRatio
-	switch h0 * v0 {
-	case 1:
-		subsampleRatio = image.YCbCrSubsampleRatio444
-	case 2:
-		subsampleRatio = image.YCbCrSubsampleRatio422
-	case 4:
-		subsampleRatio = image.YCbCrSubsampleRatio420
-	default:
-		panic("unreachable")
-	}
-	m := image.NewYCbCr(image.Rect(0, 0, 8*h0*mxx, 8*v0*myy), subsampleRatio)
-	d.img3 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.YCbCr)
-}
-
-// Specified in section B.2.3.
-func (d *decoder) processSOS(n int) error {
-	if d.nComp == 0 {
-		return FormatError("missing SOF marker")
-	}
-	if n != 4+2*d.nComp {
-		return UnsupportedError("SOS has wrong length")
-	}
-	_, err := io.ReadFull(d.r, d.tmp[0:4+2*d.nComp])
-	if err != nil {
-		return err
-	}
-	if int(d.tmp[0]) != d.nComp {
-		return UnsupportedError("SOS has wrong number of image components")
-	}
-	var scan [nColorComponent]struct {
-		td uint8 // DC table selector.
-		ta uint8 // AC table selector.
-	}
-	for i := 0; i < d.nComp; i++ {
-		cs := d.tmp[1+2*i] // Component selector.
-		if cs != d.comp[i].c {
-			return UnsupportedError("scan components out of order")
-		}
-		scan[i].td = d.tmp[2+2*i] >> 4
-		scan[i].ta = d.tmp[2+2*i] & 0x0f
-	}
-	// mxx and myy are the number of MCUs (Minimum Coded Units) in the image.
-	h0, v0 := d.comp[0].h, d.comp[0].v // The h and v values from the Y components.
-	mxx := (d.width + 8*h0 - 1) / (8 * h0)
-	myy := (d.height + 8*v0 - 1) / (8 * v0)
-	if d.img1 == nil && d.img3 == nil {
-		d.makeImg(h0, v0, mxx, myy)
-	}
-
-	mcu, expectedRST := 0, uint8(rst0Marker)
-	var (
-		b  block
-		dc [nColorComponent]int
-	)
-	for my := 0; my < myy; my++ {
-		for mx := 0; mx < mxx; mx++ {
-			for i := 0; i < d.nComp; i++ {
-				qt := &d.quant[d.comp[i].tq]
-				for j := 0; j < d.comp[i].h*d.comp[i].v; j++ {
-					// TODO(nigeltao): make this a "var b block" once the compiler's escape
-					// analysis is good enough to allocate it on the stack, not the heap.
-					b = block{}
-
-					// Decode the DC coefficient, as specified in section F.2.2.1.
-					value, err := d.decodeHuffman(&d.huff[dcTable][scan[i].td])
-					if err != nil {
-						return err
-					}
-					if value > 16 {
-						return UnsupportedError("excessive DC component")
-					}
-					dcDelta, err := d.receiveExtend(value)
-					if err != nil {
-						return err
-					}
-					dc[i] += dcDelta
-					b[0] = dc[i] * qt[0]
-
-					// Decode the AC coefficients, as specified in section F.2.2.2.
-					for k := 1; k < blockSize; k++ {
-						value, err := d.decodeHuffman(&d.huff[acTable][scan[i].ta])
-						if err != nil {
-							return err
-						}
-						val0 := value >> 4
-						val1 := value & 0x0f
-						if val1 != 0 {
-							k += int(val0)
-							if k > blockSize {
-								return FormatError("bad DCT index")
-							}
-							ac, err := d.receiveExtend(val1)
-							if err != nil {
-								return err
-							}
-							b[unzig[k]] = ac * qt[k]
-						} else {
-							if val0 != 0x0f {
-								break
-							}
-							k += 0x0f
-						}
-					}
-
-					// Perform the inverse DCT and store the MCU component to the image.
-					if d.nComp == nGrayComponent {
-						idct(d.img1.Pix[8*(my*d.img1.Stride+mx):], d.img1.Stride, &b)
-					} else {
-						switch i {
-						case 0:
-							mx0 := h0*mx + (j % 2)
-							my0 := v0*my + (j / 2)
-							idct(d.img3.Y[8*(my0*d.img3.YStride+mx0):], d.img3.YStride, &b)
-						case 1:
-							idct(d.img3.Cb[8*(my*d.img3.CStride+mx):], d.img3.CStride, &b)
-						case 2:
-							idct(d.img3.Cr[8*(my*d.img3.CStride+mx):], d.img3.CStride, &b)
-						}
-					}
-				} // for j
-			} // for i
-			mcu++
-			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 {
-					return err
-				}
-				if d.tmp[0] != 0xff || d.tmp[1] != expectedRST {
-					return FormatError("bad RST marker")
-				}
-				expectedRST++
-				if expectedRST == rst7Marker+1 {
-					expectedRST = rst0Marker
-				}
-				// Reset the Huffman decoder.
-				d.b = bits{}
-				// Reset the DC components, as per section F.2.1.3.1.
-				dc = [nColorComponent]int{}
-			}
-		} // for mx
-	} // for my
-
-	return nil
-}
-
 // Specified in section B.2.4.4.
 func (d *decoder) processDRI(n int) error {
 	if n != 2 {
@@ -390,9 +249,26 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
 			return nil, FormatError("missing 0xff marker start")
 		}
 		marker := d.tmp[1]
+		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()
+			if err != nil {
+				return nil, err
+			}
+		}
 		if marker == eoiMarker { // End Of Image.
 			break
 		}
+		if rst0Marker <= marker && marker <= rst7Marker {
+			// Figures B.2 and B.16 of the specification suggest that restart markers should
+			// only occur between Entropy Coded Segments and not after the final ECS.
+			// However, some encoders may generate incorrect JPEGs with a final restart
+			// marker. That restart marker will be seen here instead of inside the processSOS
+			// method, and is ignored as a harmless error. Restart markers have no extra data,
+			// so we check for this before we read the 16-bit length of the segment.
+			continue
+		}
 
 		// 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.
@@ -406,13 +282,12 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
 		}
 
 		switch {
-		case marker == sof0Marker: // Start Of Frame (Baseline).
+		case marker == sof0Marker || marker == sof2Marker: // Start Of Frame.
+			d.progressive = marker == sof2Marker
 			err = d.processSOF(n)
 			if configOnly {
 				return nil, err
 			}
-		case marker == sof2Marker: // Start Of Frame (Progressive).
-			err = UnsupportedError("progressive mode")
 		case marker == dhtMarker: // Define Huffman Table.
 			err = d.processDHT(n)
 		case marker == dqtMarker: // Define Quantization Table.
@@ -421,7 +296,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
 			err = d.processSOS(n)
 		case marker == driMarker: // Define Restart Interval.
 			err = d.processDRI(n)
-		case marker >= app0Marker && marker <= app15Marker || marker == comMarker: // APPlication specific, or COMment.
+		case app0Marker <= marker && marker <= app15Marker || marker == comMarker: // APPlication specific, or COMment.
 			err = d.ignore(n)
 		default:
 			err = UnsupportedError("unknown marker")
diff --git a/src/pkg/image/jpeg/reader_test.go b/src/pkg/image/jpeg/reader_test.go
new file mode 100644
index 0000000..b520a8a
--- /dev/null
+++ b/src/pkg/image/jpeg/reader_test.go
@@ -0,0 +1,157 @@
+// 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 jpeg
+
+import (
+	"bytes"
+	"fmt"
+	"image"
+	"io/ioutil"
+	"os"
+	"testing"
+)
+
+// TestDecodeProgressive tests that decoding the baseline and progressive
+// versions of the same image result in exactly the same pixel data, in YCbCr
+// space for color images, and Y space for grayscale images.
+func TestDecodeProgressive(t *testing.T) {
+	testCases := []string{
+		"../testdata/video-001",
+		"../testdata/video-001.q50.420",
+		"../testdata/video-001.q50.422",
+		"../testdata/video-001.q50.440",
+		"../testdata/video-001.q50.444",
+		"../testdata/video-005.gray.q50",
+		"../testdata/video-005.gray.q50.2x2",
+	}
+	for _, tc := range testCases {
+		m0, err := decodeFile(tc + ".jpeg")
+		if err != nil {
+			t.Errorf("%s: %v", tc+".jpeg", err)
+			continue
+		}
+		m1, err := decodeFile(tc + ".progressive.jpeg")
+		if err != nil {
+			t.Errorf("%s: %v", tc+".progressive.jpeg", err)
+			continue
+		}
+		if m0.Bounds() != m1.Bounds() {
+			t.Errorf("%s: bounds differ: %v and %v", tc, m0.Bounds(), m1.Bounds())
+			continue
+		}
+		switch m0 := m0.(type) {
+		case *image.YCbCr:
+			m1 := m1.(*image.YCbCr)
+			if err := check(m0.Bounds(), m0.Y, m1.Y, m0.YStride, m1.YStride); err != nil {
+				t.Errorf("%s (Y): %v", tc, err)
+				continue
+			}
+			if err := check(m0.Bounds(), m0.Cb, m1.Cb, m0.CStride, m1.CStride); err != nil {
+				t.Errorf("%s (Cb): %v", tc, err)
+				continue
+			}
+			if err := check(m0.Bounds(), m0.Cr, m1.Cr, m0.CStride, m1.CStride); err != nil {
+				t.Errorf("%s (Cr): %v", tc, err)
+				continue
+			}
+		case *image.Gray:
+			m1 := m1.(*image.Gray)
+			if err := check(m0.Bounds(), m0.Pix, m1.Pix, m0.Stride, m1.Stride); err != nil {
+				t.Errorf("%s: %v", tc, err)
+				continue
+			}
+		default:
+			t.Errorf("%s: unexpected image type %T", tc, m0)
+			continue
+		}
+	}
+}
+
+func decodeFile(filename string) (image.Image, error) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+	return Decode(f)
+
+}
+
+// check checks that the two pix data are equal, within the given bounds.
+func check(bounds image.Rectangle, pix0, pix1 []byte, stride0, stride1 int) error {
+	if len(pix0) != len(pix1) {
+		return fmt.Errorf("len(pix) %d and %d differ", len(pix0), len(pix1))
+	}
+	if stride0 != stride1 {
+		return fmt.Errorf("strides %d and %d differ", stride0, stride1)
+	}
+	if stride0%8 != 0 {
+		return fmt.Errorf("stride %d is not a multiple of 8", stride0)
+	}
+	// Compare the two pix data, one 8x8 block at a time.
+	for y := 0; y < len(pix0)/stride0; y += 8 {
+		for x := 0; x < stride0; x += 8 {
+			if x >= bounds.Max.X || y >= bounds.Max.Y {
+				// We don't care if the two pix data differ if the 8x8 block is
+				// entirely outside of the image's bounds. For example, this can
+				// occur with a 4:2:0 chroma subsampling and a 1x1 image. Baseline
+				// decoding works on the one 16x16 MCU as a whole; progressive
+				// decoding's first pass works on that 16x16 MCU as a whole but
+				// refinement passes only process one 8x8 block within the MCU.
+				continue
+			}
+
+			for j := 0; j < 8; j++ {
+				for i := 0; i < 8; i++ {
+					index := (y+j)*stride0 + (x + i)
+					if pix0[index] != pix1[index] {
+						return fmt.Errorf("blocks at (%d, %d) differ:\n%sand\n%s", x, y,
+							pixString(pix0, stride0, x, y),
+							pixString(pix1, stride1, x, y),
+						)
+					}
+				}
+			}
+		}
+	}
+	return nil
+}
+
+func pixString(pix []byte, stride, x, y int) string {
+	s := bytes.NewBuffer(nil)
+	for j := 0; j < 8; j++ {
+		fmt.Fprintf(s, "\t")
+		for i := 0; i < 8; i++ {
+			fmt.Fprintf(s, "%02x ", pix[(y+j)*stride+(x+i)])
+		}
+		fmt.Fprintf(s, "\n")
+	}
+	return s.String()
+}
+
+func benchmarkDecode(b *testing.B, filename string) {
+	b.StopTimer()
+	data, err := ioutil.ReadFile(filename)
+	if err != nil {
+		b.Fatal(err)
+	}
+	cfg, err := DecodeConfig(bytes.NewReader(data))
+	if err != nil {
+		b.Fatal(err)
+	}
+	b.SetBytes(int64(cfg.Width * cfg.Height * 4))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Decode(bytes.NewReader(data))
+	}
+}
+
+func BenchmarkDecodeBaseline(b *testing.B) {
+	benchmarkDecode(b, "../testdata/video-001.jpeg")
+}
+
+func BenchmarkDecodeProgressive(b *testing.B) {
+	benchmarkDecode(b, "../testdata/video-001.progressive.jpeg")
+}
diff --git a/src/pkg/image/jpeg/scan.go b/src/pkg/image/jpeg/scan.go
new file mode 100644
index 0000000..e3ae8ae
--- /dev/null
+++ b/src/pkg/image/jpeg/scan.go
@@ -0,0 +1,432 @@
+// 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 jpeg
+
+import (
+	"image"
+	"io"
+)
+
+// makeImg allocates and initializes the destination image.
+func (d *decoder) makeImg(h0, v0, mxx, myy int) {
+	if d.nComp == nGrayComponent {
+		m := image.NewGray(image.Rect(0, 0, 8*mxx, 8*myy))
+		d.img1 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.Gray)
+		return
+	}
+	var subsampleRatio image.YCbCrSubsampleRatio
+	switch {
+	case h0 == 1 && v0 == 1:
+		subsampleRatio = image.YCbCrSubsampleRatio444
+	case h0 == 1 && v0 == 2:
+		subsampleRatio = image.YCbCrSubsampleRatio440
+	case h0 == 2 && v0 == 1:
+		subsampleRatio = image.YCbCrSubsampleRatio422
+	case h0 == 2 && v0 == 2:
+		subsampleRatio = image.YCbCrSubsampleRatio420
+	default:
+		panic("unreachable")
+	}
+	m := image.NewYCbCr(image.Rect(0, 0, 8*h0*mxx, 8*v0*myy), subsampleRatio)
+	d.img3 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.YCbCr)
+}
+
+// Specified in section B.2.3.
+func (d *decoder) processSOS(n int) error {
+	if d.nComp == 0 {
+		return FormatError("missing SOF marker")
+	}
+	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 {
+		return err
+	}
+	nComp := int(d.tmp[0])
+	if n != 4+2*nComp {
+		return FormatError("SOS length inconsistent with number of components")
+	}
+	var scan [nColorComponent]struct {
+		compIndex uint8
+		td        uint8 // DC table selector.
+		ta        uint8 // AC table selector.
+	}
+	for i := 0; i < nComp; i++ {
+		cs := d.tmp[1+2*i] // Component selector.
+		compIndex := -1
+		for j, comp := range d.comp {
+			if cs == comp.c {
+				compIndex = j
+			}
+		}
+		if compIndex < 0 {
+			return FormatError("unknown component selector")
+		}
+		scan[i].compIndex = uint8(compIndex)
+		scan[i].td = d.tmp[2+2*i] >> 4
+		scan[i].ta = d.tmp[2+2*i] & 0x0f
+	}
+
+	// zigStart and zigEnd are the spectral selection bounds.
+	// ah and al are the successive approximation high and low values.
+	// The spec calls these values Ss, Se, Ah and Al.
+	//
+	// For progressive JPEGs, these are the two more-or-less independent
+	// aspects of progression. Spectral selection progression is when not
+	// all of a block's 64 DCT coefficients are transmitted in one pass.
+	// For example, three passes could transmit coefficient 0 (the DC
+	// component), coefficients 1-5, and coefficients 6-63, in zig-zag
+	// order. Successive approximation is when not all of the bits of a
+	// band of coefficients are transmitted in one pass. For example,
+	// three passes could transmit the 6 most significant bits, followed
+	// by the second-least significant bit, followed by the least
+	// significant bit.
+	//
+	// For baseline JPEGs, these parameters are hard-coded to 0/63/0/0.
+	zigStart, zigEnd, ah, al := int32(0), int32(blockSize-1), uint32(0), uint32(0)
+	if d.progressive {
+		zigStart = int32(d.tmp[1+2*nComp])
+		zigEnd = int32(d.tmp[2+2*nComp])
+		ah = uint32(d.tmp[3+2*nComp] >> 4)
+		al = uint32(d.tmp[3+2*nComp] & 0x0f)
+		if (zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || blockSize <= zigEnd {
+			return FormatError("bad spectral selection bounds")
+		}
+		if zigStart != 0 && nComp != 1 {
+			return FormatError("progressive AC coefficients for more than one component")
+		}
+		if ah != 0 && ah != al+1 {
+			return FormatError("bad successive approximation values")
+		}
+	}
+
+	// mxx and myy are the number of MCUs (Minimum Coded Units) in the image.
+	h0, v0 := d.comp[0].h, d.comp[0].v // The h and v values from the Y components.
+	mxx := (d.width + 8*h0 - 1) / (8 * h0)
+	myy := (d.height + 8*v0 - 1) / (8 * v0)
+	if d.img1 == nil && d.img3 == nil {
+		d.makeImg(h0, v0, mxx, myy)
+		if d.progressive {
+			for i := 0; i < nComp; i++ {
+				compIndex := scan[i].compIndex
+				d.progCoeffs[compIndex] = make([]block, mxx*myy*d.comp[compIndex].h*d.comp[compIndex].v)
+			}
+		}
+	}
+
+	d.b = 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).
+		// 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
+		blockCount int
+	)
+	for my := 0; my < myy; my++ {
+		for mx := 0; mx < mxx; mx++ {
+			for i := 0; i < nComp; i++ {
+				compIndex := scan[i].compIndex
+				qt := &d.quant[d.comp[compIndex].tq]
+				for j := 0; j < d.comp[compIndex].h*d.comp[compIndex].v; j++ {
+					// The blocks are traversed one MCU at a time. For 4:2:0 chroma
+					// subsampling, there are four Y 8x8 blocks in every 16x16 MCU.
+					// For a baseline 32x16 pixel image, the Y blocks visiting order is:
+					//	0 1 4 5
+					//	2 3 6 7
+					//
+					// For progressive images, the DC data blocks (zigStart == 0) are traversed
+					// as above, but AC data blocks are traversed left to right, top to bottom:
+					//	0 1 2 3
+					//	4 5 6 7
+					//
+					// To further complicate matters, there is no AC data for any blocks that
+					// are inside the image at the MCU level but outside the image at the pixel
+					// level. For example, a 24x16 pixel 4:2:0 progressive image consists of
+					// two 16x16 MCUs. The earlier scans will process 8 Y blocks:
+					//	0 1 4 5
+					//	2 3 6 7
+					// The later scans will process only 6 Y blocks:
+					//	0 1 2
+					//	3 4 5
+					if zigStart == 0 {
+						mx0, my0 = d.comp[compIndex].h*mx, d.comp[compIndex].v*my
+						if h0 == 1 {
+							my0 += j
+						} else {
+							mx0 += j % 2
+							my0 += j / 2
+						}
+					} else {
+						q := mxx * d.comp[compIndex].h
+						mx0 = blockCount % q
+						my0 = blockCount / q
+						blockCount++
+						if mx0*8 >= d.width || my0*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]
+					} else {
+						b = block{}
+					}
+
+					if ah != 0 {
+						if err := d.refine(&b, &d.huff[acTable][scan[i].ta], zigStart, zigEnd, 1<<al); err != nil {
+							return err
+						}
+					} else {
+						zig := zigStart
+						if zig == 0 {
+							zig++
+							// Decode the DC coefficient, as specified in section F.2.2.1.
+							value, err := d.decodeHuffman(&d.huff[dcTable][scan[i].td])
+							if err != nil {
+								return err
+							}
+							if value > 16 {
+								return UnsupportedError("excessive DC component")
+							}
+							dcDelta, err := d.receiveExtend(value)
+							if err != nil {
+								return err
+							}
+							dc[compIndex] += dcDelta
+							b[0] = dc[compIndex] << al
+						}
+
+						if zig <= zigEnd && d.eobRun > 0 {
+							d.eobRun--
+						} else {
+							// Decode the AC coefficients, as specified in section F.2.2.2.
+							for ; zig <= zigEnd; zig++ {
+								value, err := d.decodeHuffman(&d.huff[acTable][scan[i].ta])
+								if err != nil {
+									return err
+								}
+								val0 := value >> 4
+								val1 := value & 0x0f
+								if val1 != 0 {
+									zig += int32(val0)
+									if zig > zigEnd {
+										break
+									}
+									ac, err := d.receiveExtend(val1)
+									if err != nil {
+										return err
+									}
+									b[unzig[zig]] = ac << al
+								} else {
+									if val0 != 0x0f {
+										d.eobRun = uint16(1 << val0)
+										if val0 != 0 {
+											bits, err := d.decodeBits(int(val0))
+											if err != nil {
+												return err
+											}
+											d.eobRun |= uint16(bits)
+										}
+										d.eobRun--
+										break
+									}
+									zig += 0x0f
+								}
+							}
+						}
+					}
+
+					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
+							// 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,
+							// the jpeg.Decode function does not return until the entire image is decoded,
+							// so we "continue" here to avoid wasted computation.
+							continue
+						}
+					}
+
+					// Dequantize, perform the inverse DCT and store the block to the image.
+					for zig := 0; zig < blockSize; zig++ {
+						b[unzig[zig]] *= qt[zig]
+					}
+					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
+					} else {
+						switch compIndex {
+						case 0:
+							dst, stride = d.img3.Y[8*(my0*d.img3.YStride+mx0):], d.img3.YStride
+						case 1:
+							dst, stride = d.img3.Cb[8*(my0*d.img3.CStride+mx0):], d.img3.CStride
+						case 2:
+							dst, stride = d.img3.Cr[8*(my0*d.img3.CStride+mx0):], d.img3.CStride
+						default:
+							return UnsupportedError("too many components")
+						}
+					}
+					// Level shift by +128, clip to [0, 255], and write to dst.
+					for y := 0; y < 8; y++ {
+						y8 := y * 8
+						yStride := y * stride
+						for x := 0; x < 8; x++ {
+							c := b[y8+x]
+							if c < -128 {
+								c = 0
+							} else if c > 127 {
+								c = 255
+							} else {
+								c += 128
+							}
+							dst[yStride+x] = uint8(c)
+						}
+					}
+				} // for j
+			} // for i
+			mcu++
+			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 {
+					return err
+				}
+				if d.tmp[0] != 0xff || d.tmp[1] != expectedRST {
+					return FormatError("bad RST marker")
+				}
+				expectedRST++
+				if expectedRST == rst7Marker+1 {
+					expectedRST = rst0Marker
+				}
+				// Reset the Huffman decoder.
+				d.b = 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.
+				d.eobRun = 0
+			}
+		} // for mx
+	} // for my
+
+	return nil
+}
+
+// refine decodes a successive approximation refinement block, as specified in
+// section G.1.2.
+func (d *decoder) refine(b *block, h *huffman, zigStart, zigEnd, delta int32) error {
+	// Refining a DC component is trivial.
+	if zigStart == 0 {
+		if zigEnd != 0 {
+			panic("unreachable")
+		}
+		bit, err := d.decodeBit()
+		if err != nil {
+			return err
+		}
+		if bit {
+			b[0] |= delta
+		}
+		return nil
+	}
+
+	// Refining AC components is more complicated; see sections G.1.2.2 and G.1.2.3.
+	zig := zigStart
+	if d.eobRun == 0 {
+	loop:
+		for ; zig <= zigEnd; zig++ {
+			z := int32(0)
+			value, err := d.decodeHuffman(h)
+			if err != nil {
+				return err
+			}
+			val0 := value >> 4
+			val1 := value & 0x0f
+
+			switch val1 {
+			case 0:
+				if val0 != 0x0f {
+					d.eobRun = uint16(1 << val0)
+					if val0 != 0 {
+						bits, err := d.decodeBits(int(val0))
+						if err != nil {
+							return err
+						}
+						d.eobRun |= uint16(bits)
+					}
+					break loop
+				}
+			case 1:
+				z = delta
+				bit, err := d.decodeBit()
+				if err != nil {
+					return err
+				}
+				if !bit {
+					z = -z
+				}
+			default:
+				return FormatError("unexpected Huffman code")
+			}
+
+			zig, err = d.refineNonZeroes(b, zig, zigEnd, int32(val0), delta)
+			if err != nil {
+				return err
+			}
+			if zig > zigEnd {
+				return FormatError("too many coefficients")
+			}
+			if z != 0 {
+				b[unzig[zig]] = z
+			}
+		}
+	}
+	if d.eobRun > 0 {
+		d.eobRun--
+		if _, err := d.refineNonZeroes(b, zig, zigEnd, -1, delta); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// refineNonZeroes refines non-zero entries of b in zig-zag order. If nz >= 0,
+// the first nz zero entries are skipped over.
+func (d *decoder) refineNonZeroes(b *block, zig, zigEnd, nz, delta int32) (int32, error) {
+	for ; zig <= zigEnd; zig++ {
+		u := unzig[zig]
+		if b[u] == 0 {
+			if nz == 0 {
+				break
+			}
+			nz--
+			continue
+		}
+		bit, err := d.decodeBit()
+		if err != nil {
+			return 0, err
+		}
+		if !bit {
+			continue
+		}
+		if b[u] >= 0 {
+			b[u] += delta
+		} else {
+			b[u] -= delta
+		}
+	}
+	return zig, nil
+}
diff --git a/src/pkg/image/jpeg/writer.go b/src/pkg/image/jpeg/writer.go
index 3322c09..c58fbf3 100644
--- a/src/pkg/image/jpeg/writer.go
+++ b/src/pkg/image/jpeg/writer.go
@@ -21,7 +21,7 @@ func min(x, y int) int {
 }
 
 // div returns a/b rounded to the nearest integer, instead of rounded to zero.
-func div(a int, b int) int {
+func div(a, b int32) int32 {
 	if a >= 0 {
 		return (a + (b >> 1)) / b
 	}
@@ -56,26 +56,28 @@ const (
 	nQuantIndex
 )
 
-// unscaledQuant are the unscaled quantization tables. Each encoder copies and
-// scales the tables according to its quality parameter.
+// unscaledQuant are the unscaled quantization tables in zig-zag order. Each
+// encoder copies and scales the tables according to its quality parameter.
+// The values are derived from section K.1 after converting from natural to
+// zig-zag order.
 var unscaledQuant = [nQuantIndex][blockSize]byte{
 	// Luminance.
 	{
-		16, 11, 10, 16, 24, 40, 51, 61,
-		12, 12, 14, 19, 26, 58, 60, 55,
-		14, 13, 16, 24, 40, 57, 69, 56,
-		14, 17, 22, 29, 51, 87, 80, 62,
-		18, 22, 37, 56, 68, 109, 103, 77,
-		24, 35, 55, 64, 81, 104, 113, 92,
-		49, 64, 78, 87, 103, 121, 120, 101,
-		72, 92, 95, 98, 112, 100, 103, 99,
+		16, 11, 12, 14, 12, 10, 16, 14,
+		13, 14, 18, 17, 16, 19, 24, 40,
+		26, 24, 22, 22, 24, 49, 35, 37,
+		29, 40, 58, 51, 61, 60, 57, 51,
+		56, 55, 64, 72, 92, 78, 64, 68,
+		87, 69, 55, 56, 80, 109, 81, 87,
+		95, 98, 103, 104, 103, 62, 77, 113,
+		121, 112, 100, 120, 92, 101, 103, 99,
 	},
 	// Chrominance.
 	{
-		17, 18, 24, 47, 99, 99, 99, 99,
-		18, 21, 26, 66, 99, 99, 99, 99,
-		24, 26, 56, 99, 99, 99, 99, 99,
-		47, 66, 99, 99, 99, 99, 99, 99,
+		17, 18, 18, 24, 21, 24, 47, 26,
+		26, 47, 99, 66, 56, 66, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
 		99, 99, 99, 99, 99, 99, 99, 99,
 		99, 99, 99, 99, 99, 99, 99, 99,
 		99, 99, 99, 99, 99, 99, 99, 99,
@@ -208,8 +210,8 @@ func init() {
 // writer is a buffered writer.
 type writer interface {
 	Flush() error
-	Write([]byte) (int, error)
-	WriteByte(byte) error
+	io.Writer
+	io.ByteWriter
 }
 
 // encoder encodes an image to the JPEG format.
@@ -222,7 +224,7 @@ type encoder struct {
 	buf [16]byte
 	// bits and nBits are accumulated bits to write to w.
 	bits, nBits uint32
-	// quant is the scaled quantization tables.
+	// quant is the scaled quantization tables, in zig-zag order.
 	quant [nQuantIndex][blockSize]byte
 }
 
@@ -266,14 +268,14 @@ func (e *encoder) emit(bits, nBits uint32) {
 }
 
 // emitHuff emits the given value with the given Huffman encoder.
-func (e *encoder) emitHuff(h huffIndex, value int) {
+func (e *encoder) emitHuff(h huffIndex, value int32) {
 	x := theHuffmanLUT[h][value]
 	e.emit(x&(1<<24-1), x>>24)
 }
 
 // emitHuffRLE emits a run of runLength copies of value encoded with the given
 // Huffman encoder.
-func (e *encoder) emitHuffRLE(h huffIndex, runLength, value int) {
+func (e *encoder) emitHuffRLE(h huffIndex, runLength, value int32) {
 	a, b := value, value
 	if a < 0 {
 		a, b = -value, value-1
@@ -284,7 +286,7 @@ func (e *encoder) emitHuffRLE(h huffIndex, runLength, value int) {
 	} else {
 		nBits = 8 + uint32(bitCount[a>>8])
 	}
-	e.emitHuff(h, runLength<<4|int(nBits))
+	e.emitHuff(h, runLength<<4|int32(nBits))
 	if nBits > 0 {
 		e.emit(uint32(b)&(1<<nBits-1), nBits)
 	}
@@ -301,7 +303,7 @@ func (e *encoder) writeMarkerHeader(marker uint8, markerlen int) {
 
 // writeDQT writes the Define Quantization Table marker.
 func (e *encoder) writeDQT() {
-	markerlen := 2 + int(nQuantIndex)*(1+blockSize)
+	const markerlen = 2 + int(nQuantIndex)*(1+blockSize)
 	e.writeMarkerHeader(dqtMarker, markerlen)
 	for i := range e.quant {
 		e.writeByte(uint8(i))
@@ -311,7 +313,7 @@ func (e *encoder) writeDQT() {
 
 // writeSOF0 writes the Start Of Frame (Baseline) marker.
 func (e *encoder) writeSOF0(size image.Point) {
-	markerlen := 8 + 3*nColorComponent
+	const markerlen = 8 + 3*nColorComponent
 	e.writeMarkerHeader(sof0Marker, markerlen)
 	e.buf[0] = 8 // 8-bit color.
 	e.buf[1] = uint8(size.Y >> 8)
@@ -344,15 +346,16 @@ 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.
-func (e *encoder) writeBlock(b *block, q quantIndex, prevDC int) int {
+// 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.
-	dc := div(b[0], (8 * int(e.quant[q][0])))
+	dc := div(b[0], 8*int32(e.quant[q][0]))
 	e.emitHuffRLE(huffIndex(2*q+0), 0, dc-prevDC)
 	// Emit the AC components.
-	h, runLength := huffIndex(2*q+1), 0
-	for k := 1; k < blockSize; k++ {
-		ac := div(b[unzig[k]], (8 * int(e.quant[q][k])))
+	h, runLength := huffIndex(2*q+1), int32(0)
+	for zig := 1; zig < blockSize; zig++ {
+		ac := div(b[unzig[zig]], 8*int32(e.quant[q][zig]))
 		if ac == 0 {
 			runLength++
 		} else {
@@ -380,9 +383,9 @@ func toYCbCr(m image.Image, p image.Point, yBlock, cbBlock, crBlock *block) {
 		for i := 0; i < 8; i++ {
 			r, g, b, _ := m.At(min(p.X+i, xmax), min(p.Y+j, ymax)).RGBA()
 			yy, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
-			yBlock[8*j+i] = int(yy)
-			cbBlock[8*j+i] = int(cb)
-			crBlock[8*j+i] = int(cr)
+			yBlock[8*j+i] = int32(yy)
+			cbBlock[8*j+i] = int32(cb)
+			crBlock[8*j+i] = int32(cr)
 		}
 	}
 }
@@ -405,9 +408,9 @@ func rgbaToYCbCr(m *image.RGBA, p image.Point, yBlock, cbBlock, crBlock *block)
 			}
 			pix := m.Pix[offset+sx*4:]
 			yy, cb, cr := color.RGBToYCbCr(pix[0], pix[1], pix[2])
-			yBlock[8*j+i] = int(yy)
-			cbBlock[8*j+i] = int(cb)
-			crBlock[8*j+i] = int(cr)
+			yBlock[8*j+i] = int32(yy)
+			cbBlock[8*j+i] = int32(cb)
+			crBlock[8*j+i] = int32(cr)
 		}
 	}
 }
@@ -433,10 +436,12 @@ func scale(dst *block, src *[4]block) {
 //	- component 1 uses DC table 0 and AC table 0 "\x01\x00",
 //	- component 2 uses DC table 1 and AC table 1 "\x02\x11",
 //	- component 3 uses DC table 1 and AC table 1 "\x03\x11",
-//	- padding "\x00\x00\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 sosHeader = []byte{
 	0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
-	0x11, 0x03, 0x11, 0x00, 0x00, 0x00,
+	0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
 }
 
 // writeSOS writes the StartOfScan marker.
@@ -444,12 +449,11 @@ func (e *encoder) writeSOS(m image.Image) {
 	e.write(sosHeader)
 	var (
 		// Scratch buffers to hold the YCbCr values.
-		yBlock  block
-		cbBlock [4]block
-		crBlock [4]block
-		cBlock  block
+		// The blocks are in natural (not zig-zag) order.
+		b      block
+		cb, cr [4]block
 		// DC components are delta-encoded.
-		prevDCY, prevDCCb, prevDCCr int
+		prevDCY, prevDCCb, prevDCCr int32
 	)
 	bounds := m.Bounds()
 	rgba, _ := m.(*image.RGBA)
@@ -460,16 +464,16 @@ func (e *encoder) writeSOS(m image.Image) {
 				yOff := (i & 2) * 4
 				p := image.Pt(x+xOff, y+yOff)
 				if rgba != nil {
-					rgbaToYCbCr(rgba, p, &yBlock, &cbBlock[i], &crBlock[i])
+					rgbaToYCbCr(rgba, p, &b, &cb[i], &cr[i])
 				} else {
-					toYCbCr(m, p, &yBlock, &cbBlock[i], &crBlock[i])
+					toYCbCr(m, p, &b, &cb[i], &cr[i])
 				}
-				prevDCY = e.writeBlock(&yBlock, 0, prevDCY)
+				prevDCY = e.writeBlock(&b, 0, prevDCY)
 			}
-			scale(&cBlock, &cbBlock)
-			prevDCCb = e.writeBlock(&cBlock, 1, prevDCCb)
-			scale(&cBlock, &crBlock)
-			prevDCCr = e.writeBlock(&cBlock, 1, prevDCCr)
+			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.
diff --git a/src/pkg/image/jpeg/writer_test.go b/src/pkg/image/jpeg/writer_test.go
index b8e8fa3..0b2143f 100644
--- a/src/pkg/image/jpeg/writer_test.go
+++ b/src/pkg/image/jpeg/writer_test.go
@@ -6,6 +6,7 @@ package jpeg
 
 import (
 	"bytes"
+	"fmt"
 	"image"
 	"image/color"
 	"image/png"
@@ -15,6 +16,87 @@ import (
 	"testing"
 )
 
+// zigzag maps from the natural ordering to the zig-zag ordering. For example,
+// zigzag[0*8 + 3] is the zig-zag sequence number of the element in the fourth
+// column and first row.
+var zigzag = [blockSize]int{
+	0, 1, 5, 6, 14, 15, 27, 28,
+	2, 4, 7, 13, 16, 26, 29, 42,
+	3, 8, 12, 17, 25, 30, 41, 43,
+	9, 11, 18, 24, 31, 40, 44, 53,
+	10, 19, 23, 32, 39, 45, 52, 54,
+	20, 22, 33, 38, 46, 51, 55, 60,
+	21, 34, 37, 47, 50, 56, 59, 61,
+	35, 36, 48, 49, 57, 58, 62, 63,
+}
+
+func TestZigUnzig(t *testing.T) {
+	for i := 0; i < blockSize; i++ {
+		if unzig[zigzag[i]] != i {
+			t.Errorf("unzig[zigzag[%d]] == %d", i, unzig[zigzag[i]])
+		}
+		if zigzag[unzig[i]] != i {
+			t.Errorf("zigzag[unzig[%d]] == %d", i, zigzag[unzig[i]])
+		}
+	}
+}
+
+// unscaledQuantInNaturalOrder are the unscaled quantization tables in
+// natural (not zig-zag) order, as specified in section K.1.
+var unscaledQuantInNaturalOrder = [nQuantIndex][blockSize]byte{
+	// Luminance.
+	{
+		16, 11, 10, 16, 24, 40, 51, 61,
+		12, 12, 14, 19, 26, 58, 60, 55,
+		14, 13, 16, 24, 40, 57, 69, 56,
+		14, 17, 22, 29, 51, 87, 80, 62,
+		18, 22, 37, 56, 68, 109, 103, 77,
+		24, 35, 55, 64, 81, 104, 113, 92,
+		49, 64, 78, 87, 103, 121, 120, 101,
+		72, 92, 95, 98, 112, 100, 103, 99,
+	},
+	// Chrominance.
+	{
+		17, 18, 24, 47, 99, 99, 99, 99,
+		18, 21, 26, 66, 99, 99, 99, 99,
+		24, 26, 56, 99, 99, 99, 99, 99,
+		47, 66, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+		99, 99, 99, 99, 99, 99, 99, 99,
+	},
+}
+
+func TestUnscaledQuant(t *testing.T) {
+	bad := false
+	for i := quantIndex(0); i < nQuantIndex; i++ {
+		for zig := 0; zig < blockSize; zig++ {
+			got := unscaledQuant[i][zig]
+			want := unscaledQuantInNaturalOrder[i][unzig[zig]]
+			if got != want {
+				t.Errorf("i=%d, zig=%d: got %d, want %d", i, zig, got, want)
+				bad = true
+			}
+		}
+	}
+	if bad {
+		names := [nQuantIndex]string{"Luminance", "Chrominance"}
+		buf := &bytes.Buffer{}
+		for i, name := range names {
+			fmt.Fprintf(buf, "// %s.\n{\n", name)
+			for zig := 0; zig < blockSize; zig++ {
+				fmt.Fprintf(buf, "%d, ", unscaledQuantInNaturalOrder[i][unzig[zig]])
+				if zig%8 == 7 {
+					buf.WriteString("\n")
+				}
+			}
+			buf.WriteString("},\n")
+		}
+		t.Logf("expected unscaledQuant values:\n%s", buf.String())
+	}
+}
+
 var testCase = []struct {
 	filename  string
 	quality   int
@@ -89,24 +171,21 @@ func TestWriter(t *testing.T) {
 	}
 }
 
-func BenchmarkEncodeRGBOpaque(b *testing.B) {
+func BenchmarkEncode(b *testing.B) {
 	b.StopTimer()
 	img := image.NewRGBA(image.Rect(0, 0, 640, 480))
-	// Set all pixels to 0xFF alpha to force opaque mode.
 	bo := img.Bounds()
 	rnd := rand.New(rand.NewSource(123))
 	for y := bo.Min.Y; y < bo.Max.Y; y++ {
 		for x := bo.Min.X; x < bo.Max.X; x++ {
-			img.Set(x, y, color.RGBA{
+			img.SetRGBA(x, y, color.RGBA{
 				uint8(rnd.Intn(256)),
 				uint8(rnd.Intn(256)),
 				uint8(rnd.Intn(256)),
-				255})
+				255,
+			})
 		}
 	}
-	if !img.Opaque() {
-		b.Fatal("expected image to be opaque")
-	}
 	b.SetBytes(640 * 480 * 4)
 	b.StartTimer()
 	options := &Options{Quality: 90}
diff --git a/src/pkg/image/names.go b/src/pkg/image/names.go
index 55f634c..04ee2cf 100644
--- a/src/pkg/image/names.go
+++ b/src/pkg/image/names.go
@@ -20,7 +20,7 @@ var (
 )
 
 // Uniform is an infinite-sized Image of uniform color.
-// It implements the color.Color, color.ColorModel, and Image interfaces.
+// It implements the color.Color, color.Model, and Image interfaces.
 type Uniform struct {
 	C color.Color
 }
diff --git a/src/pkg/image/png/paeth.go b/src/pkg/image/png/paeth.go
new file mode 100644
index 0000000..37978aa
--- /dev/null
+++ b/src/pkg/image/png/paeth.go
@@ -0,0 +1,70 @@
+// 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 png
+
+// 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.
+	// For example, the sample code starts with:
+	//	p := int(a) + int(b) - int(c)
+	//	pa := abs(p - int(a))
+	// but the optimized form uses fewer arithmetic operations:
+	//	pa := int(b) - int(c)
+	//	pa = abs(pa)
+	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
+	}
+	if pa <= pb && pa <= pc {
+		return a
+	} else if pb <= pc {
+		return b
+	}
+	return c
+}
+
+// filterPaeth applies the Paeth filter to the cdat slice.
+// cdat is the current row's data, pdat is the previous row's data.
+func filterPaeth(cdat, pdat []byte, bytesPerPixel int) {
+	var a, b, c, pa, pb, pc int
+	for i := 0; i < bytesPerPixel; i++ {
+		a, c = 0, 0
+		for j := i; j < len(cdat); j += bytesPerPixel {
+			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
+			}
+			if pa <= pb && pa <= pc {
+				// No-op.
+			} else if pb <= pc {
+				a = b
+			} else {
+				a = c
+			}
+			a += int(cdat[j])
+			a &= 0xff
+			cdat[j] = uint8(a)
+			c = b
+		}
+	}
+}
diff --git a/src/pkg/image/png/paeth_test.go b/src/pkg/image/png/paeth_test.go
new file mode 100644
index 0000000..bb08486
--- /dev/null
+++ b/src/pkg/image/png/paeth_test.go
@@ -0,0 +1,91 @@
+// 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 png
+
+import (
+	"bytes"
+	"math/rand"
+	"testing"
+)
+
+func abs(x int) int {
+	if x < 0 {
+		return -x
+	}
+	return x
+}
+
+// slowPaeth is a slow but simple implementation of the Paeth function.
+// 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))
+	if pa <= pb && pa <= pc {
+		return a
+	} else if pb <= pc {
+		return b
+	}
+	return c
+}
+
+// slowFilterPaeth is a slow but simple implementation of func filterPaeth.
+func slowFilterPaeth(cdat, pdat []byte, bytesPerPixel int) {
+	for i := 0; i < bytesPerPixel; i++ {
+		cdat[i] += paeth(0, pdat[i], 0)
+	}
+	for i := bytesPerPixel; i < len(cdat); i++ {
+		cdat[i] += paeth(cdat[i-bytesPerPixel], pdat[i], pdat[i-bytesPerPixel])
+	}
+}
+
+func TestPaeth(t *testing.T) {
+	for a := 0; a < 256; a += 15 {
+		for b := 0; b < 256; b += 15 {
+			for c := 0; c < 256; c += 15 {
+				got := paeth(uint8(a), uint8(b), uint8(c))
+				want := slowPaeth(uint8(a), uint8(b), uint8(c))
+				if got != want {
+					t.Errorf("a, b, c = %d, %d, %d: got %d, want %d", a, b, c, got, want)
+				}
+			}
+		}
+	}
+}
+
+func BenchmarkPaeth(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		paeth(uint8(i>>16), uint8(i>>8), uint8(i))
+	}
+}
+
+func TestPaethDecode(t *testing.T) {
+	pdat0 := make([]byte, 32)
+	pdat1 := make([]byte, 32)
+	pdat2 := make([]byte, 32)
+	cdat0 := make([]byte, 32)
+	cdat1 := make([]byte, 32)
+	cdat2 := make([]byte, 32)
+	r := rand.New(rand.NewSource(1))
+	for bytesPerPixel := 1; bytesPerPixel <= 8; bytesPerPixel++ {
+		for i := 0; i < 100; i++ {
+			for j := range pdat0 {
+				pdat0[j] = uint8(r.Uint32())
+				cdat0[j] = uint8(r.Uint32())
+			}
+			copy(pdat1, pdat0)
+			copy(pdat2, pdat0)
+			copy(cdat1, cdat0)
+			copy(cdat2, cdat0)
+			filterPaeth(cdat1, pdat1, bytesPerPixel)
+			slowFilterPaeth(cdat2, pdat2, bytesPerPixel)
+			if !bytes.Equal(cdat1, cdat2) {
+				t.Errorf("bytesPerPixel: %d\npdat0: % x\ncdat0: % x\ngot:   % x\nwant:  % x", bytesPerPixel, pdat0, cdat0, cdat1, cdat2)
+				break
+			}
+		}
+	}
+}
diff --git a/src/pkg/image/png/reader.go b/src/pkg/image/png/reader.go
index fe07d60..a6bf86e 100644
--- a/src/pkg/image/png/reader.go
+++ b/src/pkg/image/png/reader.go
@@ -98,13 +98,6 @@ type UnsupportedError string
 
 func (e UnsupportedError) Error() string { return "png: unsupported feature: " + string(e) }
 
-func abs(x int) int {
-	if x < 0 {
-		return -x
-	}
-	return x
-}
-
 func min(a, b int) int {
 	if a < b {
 		return a
@@ -200,10 +193,19 @@ func (d *decoder) parsePLTE(length uint32) error {
 	d.crc.Write(d.tmp[:n])
 	switch d.cb {
 	case cbP1, cbP2, cbP4, cbP8:
-		d.palette = color.Palette(make([]color.Color, np))
+		d.palette = make(color.Palette, 256)
 		for i := 0; i < np; i++ {
 			d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
 		}
+		for i := np; i < 256; i++ {
+			// Initialize the rest of the palette to opaque black. The spec (section
+			// 11.2.3) says that "any out-of-range pixel value found in the image data
+			// is an error", but some real-world PNG files have out-of-range pixel
+			// values. We fall back to opaque black, the same as libpng 1.5.13;
+			// ImageMagick 6.5.7 returns an error.
+			d.palette[i] = color.RGBA{0x00, 0x00, 0x00, 0xff}
+		}
+		d.palette = d.palette[:np]
 	case cbTC8, cbTCA8, cbTC16, cbTCA16:
 		// As per the PNG spec, a PLTE chunk is optional (and for practical purposes,
 		// ignorable) for the ctTrueColor and ctTrueColorAlpha color types (section 4.1.2).
@@ -228,12 +230,12 @@ func (d *decoder) parsetRNS(length uint32) error {
 	case cbTC8, cbTC16:
 		return UnsupportedError("truecolor transparency")
 	case cbP1, cbP2, cbP4, cbP8:
-		if n > len(d.palette) {
-			return FormatError("bad tRNS length")
+		if len(d.palette) < n {
+			d.palette = d.palette[:n]
 		}
 		for i := 0; i < n; i++ {
 			rgba := d.palette[i].(color.RGBA)
-			d.palette[i] = color.RGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
+			d.palette[i] = color.NRGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
 		}
 	case cbGA8, cbGA16, cbTCA8, cbTCA16:
 		return FormatError("tRNS, color type mismatch")
@@ -241,20 +243,6 @@ func (d *decoder) parsetRNS(length uint32) error {
 	return d.verifyChecksum()
 }
 
-// The Paeth filter function, as per the PNG specification.
-func paeth(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))
-	if pa <= pb && pa <= pc {
-		return a
-	} else if pb <= pc {
-		return b
-	}
-	return c
-}
-
 // Read presents one or more IDAT chunks as one continuous stream (minus the
 // intermediate chunk headers and footers). If the PNG data looked like:
 //   ... len0 IDAT xxx crc0 len1 IDAT yy crc1 len2 IEND crc2
@@ -300,7 +288,7 @@ func (d *decoder) decode() (image.Image, error) {
 	}
 	defer r.Close()
 	bitsPerPixel := 0
-	maxPalette := uint8(0)
+	pixOffset := 0
 	var (
 		gray     *image.Gray
 		rgba     *image.RGBA
@@ -328,7 +316,6 @@ func (d *decoder) decode() (image.Image, error) {
 		bitsPerPixel = d.depth
 		paletted = image.NewPaletted(image.Rect(0, 0, d.width, d.height), d.palette)
 		img = paletted
-		maxPalette = uint8(len(d.palette) - 1)
 	case cbTCA8:
 		bitsPerPixel = 32
 		nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
@@ -375,8 +362,8 @@ func (d *decoder) decode() (image.Image, error) {
 				cdat[i] += cdat[i-bytesPerPixel]
 			}
 		case ftUp:
-			for i := 0; i < len(cdat); i++ {
-				cdat[i] += pdat[i]
+			for i, p := range pdat {
+				cdat[i] += p
 			}
 		case ftAverage:
 			for i := 0; i < bytesPerPixel; i++ {
@@ -386,12 +373,7 @@ func (d *decoder) decode() (image.Image, error) {
 				cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2)
 			}
 		case ftPaeth:
-			for i := 0; i < bytesPerPixel; i++ {
-				cdat[i] += paeth(0, pdat[i], 0)
-			}
-			for i := bytesPerPixel; i < len(cdat); i++ {
-				cdat[i] += paeth(cdat[i-bytesPerPixel], pdat[i], pdat[i-bytesPerPixel])
-			}
+			filterPaeth(cdat, pdat, bytesPerPixel)
 		default:
 			return nil, FormatError("bad filter type")
 		}
@@ -423,25 +405,31 @@ func (d *decoder) decode() (image.Image, error) {
 				}
 			}
 		case cbG8:
-			for x := 0; x < d.width; x++ {
-				gray.SetGray(x, y, color.Gray{cdat[x]})
-			}
+			copy(gray.Pix[pixOffset:], cdat)
+			pixOffset += gray.Stride
 		case cbGA8:
 			for x := 0; x < d.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++ {
-				rgba.SetRGBA(x, y, color.RGBA{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
+				pix[i+0] = cdat[j+0]
+				pix[i+1] = cdat[j+1]
+				pix[i+2] = cdat[j+2]
+				pix[i+3] = 0xff
+				i += 4
+				j += 3
 			}
+			pixOffset += rgba.Stride
 		case cbP1:
 			for x := 0; x < d.width; x += 8 {
 				b := cdat[x/8]
 				for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
 					idx := b >> 7
-					if idx > maxPalette {
-						return nil, FormatError("palette index out of range")
+					if len(paletted.Palette) <= int(idx) {
+						paletted.Palette = paletted.Palette[:int(idx)+1]
 					}
 					paletted.SetColorIndex(x+x2, y, idx)
 					b <<= 1
@@ -452,8 +440,8 @@ func (d *decoder) decode() (image.Image, error) {
 				b := cdat[x/4]
 				for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
 					idx := b >> 6
-					if idx > maxPalette {
-						return nil, FormatError("palette index out of range")
+					if len(paletted.Palette) <= int(idx) {
+						paletted.Palette = paletted.Palette[:int(idx)+1]
 					}
 					paletted.SetColorIndex(x+x2, y, idx)
 					b <<= 2
@@ -464,24 +452,26 @@ func (d *decoder) decode() (image.Image, error) {
 				b := cdat[x/2]
 				for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
 					idx := b >> 4
-					if idx > maxPalette {
-						return nil, FormatError("palette index out of range")
+					if len(paletted.Palette) <= int(idx) {
+						paletted.Palette = paletted.Palette[:int(idx)+1]
 					}
 					paletted.SetColorIndex(x+x2, y, idx)
 					b <<= 4
 				}
 			}
 		case cbP8:
-			for x := 0; x < d.width; x++ {
-				if cdat[x] > maxPalette {
-					return nil, FormatError("palette index out of range")
+			if len(paletted.Palette) != 255 {
+				for x := 0; x < d.width; x++ {
+					if len(paletted.Palette) <= int(cdat[x]) {
+						paletted.Palette = paletted.Palette[:int(cdat[x])+1]
+					}
 				}
-				paletted.SetColorIndex(x, y, cdat[x])
 			}
+			copy(paletted.Pix[pixOffset:], cdat)
+			pixOffset += paletted.Stride
 		case cbTCA8:
-			for x := 0; x < d.width; x++ {
-				nrgba.SetNRGBA(x, y, color.NRGBA{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
-			}
+			copy(nrgba.Pix[pixOffset:], cdat)
+			pixOffset += nrgba.Stride
 		case cbG16:
 			for x := 0; x < d.width; x++ {
 				ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
@@ -662,10 +652,11 @@ func DecodeConfig(r io.Reader) (image.Config, error) {
 			}
 			return image.Config{}, err
 		}
-		if d.stage == dsSeenIHDR && d.cb != cbP8 {
+		paletted := d.cb == cbP8 || d.cb == cbP4 || d.cb == cbP2 || d.cb == cbP1
+		if d.stage == dsSeenIHDR && !paletted {
 			break
 		}
-		if d.stage == dsSeenPLTE && d.cb == cbP8 {
+		if d.stage == dsSeenPLTE && paletted {
 			break
 		}
 	}
diff --git a/src/pkg/image/png/reader_test.go b/src/pkg/image/png/reader_test.go
index 24c4ea4..ac0d949 100644
--- a/src/pkg/image/png/reader_test.go
+++ b/src/pkg/image/png/reader_test.go
@@ -10,6 +10,7 @@ import (
 	"image"
 	"image/color"
 	"io"
+	"io/ioutil"
 	"os"
 	"strings"
 	"testing"
@@ -37,6 +38,14 @@ var filenames = []string{
 	"basn6a16",
 }
 
+var filenamesPaletted = []string{
+	"basn3p01",
+	"basn3p02",
+	"basn3p04",
+	"basn3p08",
+	"basn3p08-trns",
+}
+
 var filenamesShort = []string{
 	"basn0g01",
 	"basn0g04-31",
@@ -106,13 +115,18 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
 		lastAlpha := -1
 		io.WriteString(w, "PLTE {\n")
 		for i, c := range cpm {
-			r, g, b, a := c.RGBA()
-			if a != 0xffff {
+			var r, g, b, a uint8
+			switch c := c.(type) {
+			case color.RGBA:
+				r, g, b, a = c.R, c.G, c.B, 0xff
+			case color.NRGBA:
+				r, g, b, a = c.R, c.G, c.B, c.A
+			default:
+				panic("unknown palette color type")
+			}
+			if a != 0xff {
 				lastAlpha = i
 			}
-			r >>= 8
-			g >>= 8
-			b >>= 8
 			fmt.Fprintf(w, "    (%3d,%3d,%3d)     # rgb = (0x%02x,0x%02x,0x%02x)\n", r, g, b, r, g, b)
 		}
 		io.WriteString(w, "}\n")
@@ -202,7 +216,7 @@ func TestReader(t *testing.T) {
 		}
 
 		piper, pipew := io.Pipe()
-		pb := bufio.NewReader(piper)
+		pb := bufio.NewScanner(piper)
 		go sng(pipew, fn, img)
 		defer piper.Close()
 
@@ -213,7 +227,7 @@ func TestReader(t *testing.T) {
 			continue
 		}
 		defer sf.Close()
-		sb := bufio.NewReader(sf)
+		sb := bufio.NewScanner(sf)
 		if err != nil {
 			t.Error(fn, err)
 			continue
@@ -221,24 +235,28 @@ func TestReader(t *testing.T) {
 
 		// Compare the two, in SNG format, line by line.
 		for {
-			ps, perr := pb.ReadString('\n')
-			ss, serr := sb.ReadString('\n')
-			if perr == io.EOF && serr == io.EOF {
+			pdone := pb.Scan()
+			sdone := sb.Scan()
+			if pdone && sdone {
 				break
 			}
-			if perr != nil {
-				t.Error(fn, perr)
-				break
-			}
-			if serr != nil {
-				t.Error(fn, serr)
+			if pdone || sdone {
+				t.Errorf("%s: Different sizes", fn)
 				break
 			}
+			ps := pb.Text()
+			ss := sb.Text()
 			if ps != ss {
 				t.Errorf("%s: Mismatch\n%sversus\n%s\n", fn, ps, ss)
 				break
 			}
 		}
+		if pb.Err() != nil {
+			t.Error(fn, pb.Err())
+		}
+		if sb.Err() != nil {
+			t.Error(fn, sb.Err())
+		}
 	}
 }
 
@@ -267,3 +285,66 @@ func TestReaderError(t *testing.T) {
 		}
 	}
 }
+
+func TestPalettedDecodeConfig(t *testing.T) {
+	for _, fn := range filenamesPaletted {
+		f, err := os.Open("testdata/pngsuite/" + fn + ".png")
+		if err != nil {
+			t.Errorf("%s: open failed: %v", fn, err)
+			continue
+		}
+		defer f.Close()
+		cfg, err := DecodeConfig(f)
+		if err != nil {
+			t.Errorf("%s: %v", fn, err)
+			continue
+		}
+		pal, ok := cfg.ColorModel.(color.Palette)
+		if !ok {
+			t.Errorf("%s: expected paletted color model", fn)
+			continue
+		}
+		if pal == nil {
+			t.Errorf("%s: palette not initialized", fn)
+			continue
+		}
+	}
+}
+
+func benchmarkDecode(b *testing.B, filename string, bytesPerPixel int) {
+	b.StopTimer()
+	data, err := ioutil.ReadFile(filename)
+	if err != nil {
+		b.Fatal(err)
+	}
+	s := string(data)
+	cfg, err := DecodeConfig(strings.NewReader(s))
+	if err != nil {
+		b.Fatal(err)
+	}
+	b.SetBytes(int64(cfg.Width * cfg.Height * bytesPerPixel))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Decode(strings.NewReader(s))
+	}
+}
+
+func BenchmarkDecodeGray(b *testing.B) {
+	benchmarkDecode(b, "testdata/benchGray.png", 1)
+}
+
+func BenchmarkDecodeNRGBAGradient(b *testing.B) {
+	benchmarkDecode(b, "testdata/benchNRGBA-gradient.png", 4)
+}
+
+func BenchmarkDecodeNRGBAOpaque(b *testing.B) {
+	benchmarkDecode(b, "testdata/benchNRGBA-opaque.png", 4)
+}
+
+func BenchmarkDecodePaletted(b *testing.B) {
+	benchmarkDecode(b, "testdata/benchPaletted.png", 1)
+}
+
+func BenchmarkDecodeRGB(b *testing.B) {
+	benchmarkDecode(b, "testdata/benchRGB.png", 4)
+}
diff --git a/src/pkg/image/png/testdata/benchGray.png b/src/pkg/image/png/testdata/benchGray.png
new file mode 100644
index 0000000..42bc6c3
Binary files /dev/null and b/src/pkg/image/png/testdata/benchGray.png differ
diff --git a/src/pkg/image/png/testdata/benchNRGBA-gradient.png b/src/pkg/image/png/testdata/benchNRGBA-gradient.png
new file mode 100644
index 0000000..961934c
Binary files /dev/null and b/src/pkg/image/png/testdata/benchNRGBA-gradient.png differ
diff --git a/src/pkg/image/png/testdata/benchNRGBA-opaque.png b/src/pkg/image/png/testdata/benchNRGBA-opaque.png
new file mode 100644
index 0000000..ca4f4a0
Binary files /dev/null and b/src/pkg/image/png/testdata/benchNRGBA-opaque.png differ
diff --git a/src/pkg/image/png/testdata/benchPaletted.png b/src/pkg/image/png/testdata/benchPaletted.png
new file mode 100644
index 0000000..4b4d5b9
Binary files /dev/null and b/src/pkg/image/png/testdata/benchPaletted.png differ
diff --git a/src/pkg/image/png/testdata/benchRGB.png b/src/pkg/image/png/testdata/benchRGB.png
new file mode 100644
index 0000000..31ac65a
Binary files /dev/null and b/src/pkg/image/png/testdata/benchRGB.png differ
diff --git a/src/pkg/image/png/writer.go b/src/pkg/image/png/writer.go
index 57c0379..093d471 100644
--- a/src/pkg/image/png/writer.go
+++ b/src/pkg/image/png/writer.go
@@ -21,7 +21,7 @@ type encoder struct {
 	err    error
 	header [8]byte
 	footer [4]byte
-	tmp    [3 * 256]byte
+	tmp    [4 * 256]byte
 }
 
 // Big-endian.
@@ -70,7 +70,7 @@ func (e *encoder) writeChunk(b []byte, name string) {
 		e.err = UnsupportedError(name + " chunk is too large: " + strconv.Itoa(len(b)))
 		return
 	}
-	writeUint32(e.header[0:4], n)
+	writeUint32(e.header[:4], n)
 	e.header[4] = name[0]
 	e.header[5] = name[1]
 	e.header[6] = name[2]
@@ -78,9 +78,9 @@ func (e *encoder) writeChunk(b []byte, name string) {
 	crc := crc32.NewIEEE()
 	crc.Write(e.header[4:8])
 	crc.Write(b)
-	writeUint32(e.footer[0:4], crc.Sum32())
+	writeUint32(e.footer[:4], crc.Sum32())
 
-	_, e.err = e.w.Write(e.header[0:8])
+	_, e.err = e.w.Write(e.header[:8])
 	if e.err != nil {
 		return
 	}
@@ -88,7 +88,7 @@ func (e *encoder) writeChunk(b []byte, name string) {
 	if e.err != nil {
 		return
 	}
-	_, e.err = e.w.Write(e.footer[0:4])
+	_, e.err = e.w.Write(e.footer[:4])
 }
 
 func (e *encoder) writeIHDR() {
@@ -122,36 +122,29 @@ func (e *encoder) writeIHDR() {
 	e.tmp[10] = 0 // default compression method
 	e.tmp[11] = 0 // default filter method
 	e.tmp[12] = 0 // non-interlaced
-	e.writeChunk(e.tmp[0:13], "IHDR")
+	e.writeChunk(e.tmp[:13], "IHDR")
 }
 
-func (e *encoder) writePLTE(p color.Palette) {
+func (e *encoder) writePLTEAndTRNS(p color.Palette) {
 	if len(p) < 1 || len(p) > 256 {
 		e.err = FormatError("bad palette length: " + strconv.Itoa(len(p)))
 		return
 	}
-	for i, c := range p {
-		r, g, b, _ := c.RGBA()
-		e.tmp[3*i+0] = uint8(r >> 8)
-		e.tmp[3*i+1] = uint8(g >> 8)
-		e.tmp[3*i+2] = uint8(b >> 8)
-	}
-	e.writeChunk(e.tmp[0:3*len(p)], "PLTE")
-}
-
-func (e *encoder) maybeWritetRNS(p color.Palette) {
 	last := -1
 	for i, c := range p {
-		_, _, _, a := c.RGBA()
-		if a != 0xffff {
+		c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
+		e.tmp[3*i+0] = c1.R
+		e.tmp[3*i+1] = c1.G
+		e.tmp[3*i+2] = c1.B
+		if c1.A != 0xff {
 			last = i
 		}
-		e.tmp[i] = uint8(a >> 8)
+		e.tmp[3*256+i] = c1.A
 	}
-	if last == -1 {
-		return
+	e.writeChunk(e.tmp[:3*len(p)], "PLTE")
+	if last != -1 {
+		e.writeChunk(e.tmp[3*256:3*256+1+last], "tRNS")
 	}
-	e.writeChunk(e.tmp[:last+1], "tRNS")
 }
 
 // An encoder is an io.Writer that satisfies writes by writing PNG IDAT chunks,
@@ -297,26 +290,42 @@ func writeImage(w io.Writer, m image.Image, cb int) error {
 	}
 	pr := make([]uint8, 1+bpp*b.Dx())
 
+	gray, _ := m.(*image.Gray)
+	rgba, _ := m.(*image.RGBA)
+	paletted, _ := m.(*image.Paletted)
+	nrgba, _ := m.(*image.NRGBA)
+
 	for y := b.Min.Y; y < b.Max.Y; y++ {
 		// Convert from colors to bytes.
 		i := 1
 		switch cb {
 		case cbG8:
-			for x := b.Min.X; x < b.Max.X; x++ {
-				c := color.GrayModel.Convert(m.At(x, y)).(color.Gray)
-				cr[0][i] = c.Y
-				i++
+			if gray != nil {
+				offset := (y - b.Min.Y) * gray.Stride
+				copy(cr[0][1:], gray.Pix[offset:offset+b.Dx()])
+			} else {
+				for x := b.Min.X; x < b.Max.X; x++ {
+					c := color.GrayModel.Convert(m.At(x, y)).(color.Gray)
+					cr[0][i] = c.Y
+					i++
+				}
 			}
 		case cbTC8:
 			// We have previously verified that the alpha value is fully opaque.
 			cr0 := cr[0]
-			if rgba, _ := m.(*image.RGBA); rgba != nil {
-				j0 := (y - b.Min.Y) * rgba.Stride
+			stride, pix := 0, []byte(nil)
+			if rgba != nil {
+				stride, pix = rgba.Stride, rgba.Pix
+			} else if nrgba != nil {
+				stride, pix = nrgba.Stride, nrgba.Pix
+			}
+			if stride != 0 {
+				j0 := (y - b.Min.Y) * stride
 				j1 := j0 + b.Dx()*4
 				for j := j0; j < j1; j += 4 {
-					cr0[i+0] = rgba.Pix[j+0]
-					cr0[i+1] = rgba.Pix[j+1]
-					cr0[i+2] = rgba.Pix[j+2]
+					cr0[i+0] = pix[j+0]
+					cr0[i+1] = pix[j+1]
+					cr0[i+2] = pix[j+2]
 					i += 3
 				}
 			} else {
@@ -329,9 +338,9 @@ func writeImage(w io.Writer, m image.Image, cb int) error {
 				}
 			}
 		case cbP8:
-			if p, _ := m.(*image.Paletted); p != nil {
-				offset := (y - b.Min.Y) * p.Stride
-				copy(cr[0][1:], p.Pix[offset:offset+b.Dx()])
+			if paletted != nil {
+				offset := (y - b.Min.Y) * paletted.Stride
+				copy(cr[0][1:], paletted.Pix[offset:offset+b.Dx()])
 			} else {
 				pi := m.(image.PalettedImage)
 				for x := b.Min.X; x < b.Max.X; x++ {
@@ -340,14 +349,19 @@ func writeImage(w io.Writer, m image.Image, cb int) error {
 				}
 			}
 		case cbTCA8:
-			// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
-			for x := b.Min.X; x < b.Max.X; x++ {
-				c := color.NRGBAModel.Convert(m.At(x, y)).(color.NRGBA)
-				cr[0][i+0] = c.R
-				cr[0][i+1] = c.G
-				cr[0][i+2] = c.B
-				cr[0][i+3] = c.A
-				i += 4
+			if nrgba != nil {
+				offset := (y - b.Min.Y) * nrgba.Stride
+				copy(cr[0][1:], nrgba.Pix[offset:offset+b.Dx()*4])
+			} else {
+				// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
+				for x := b.Min.X; x < b.Max.X; x++ {
+					c := color.NRGBAModel.Convert(m.At(x, y)).(color.NRGBA)
+					cr[0][i+0] = c.R
+					cr[0][i+1] = c.G
+					cr[0][i+2] = c.B
+					cr[0][i+3] = c.A
+					i += 4
+				}
 			}
 		case cbG16:
 			for x := b.Min.X; x < b.Max.X; x++ {
@@ -412,7 +426,7 @@ func (e *encoder) writeIDATs() {
 	e.err = bw.Flush()
 }
 
-func (e *encoder) writeIEND() { e.writeChunk(e.tmp[0:0], "IEND") }
+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.
@@ -460,8 +474,7 @@ func Encode(w io.Writer, m image.Image) error {
 	_, e.err = io.WriteString(w, pngHeader)
 	e.writeIHDR()
 	if pal != nil {
-		e.writePLTE(pal)
-		e.maybeWritetRNS(pal)
+		e.writePLTEAndTRNS(pal)
 	}
 	e.writeIDATs()
 	e.writeIEND()
diff --git a/src/pkg/image/png/writer_test.go b/src/pkg/image/png/writer_test.go
index 644c4fb..3116fc9 100644
--- a/src/pkg/image/png/writer_test.go
+++ b/src/pkg/image/png/writer_test.go
@@ -101,6 +101,49 @@ func TestSubImage(t *testing.T) {
 	}
 }
 
+func BenchmarkEncodeGray(b *testing.B) {
+	b.StopTimer()
+	img := image.NewGray(image.Rect(0, 0, 640, 480))
+	b.SetBytes(640 * 480 * 1)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img)
+	}
+}
+
+func BenchmarkEncodeNRGBOpaque(b *testing.B) {
+	b.StopTimer()
+	img := image.NewNRGBA(image.Rect(0, 0, 640, 480))
+	// Set all pixels to 0xFF alpha to force opaque mode.
+	bo := img.Bounds()
+	for y := bo.Min.Y; y < bo.Max.Y; y++ {
+		for x := bo.Min.X; x < bo.Max.X; x++ {
+			img.Set(x, y, color.NRGBA{0, 0, 0, 255})
+		}
+	}
+	if !img.Opaque() {
+		b.Fatal("expected image to be opaque")
+	}
+	b.SetBytes(640 * 480 * 4)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img)
+	}
+}
+
+func BenchmarkEncodeNRGBA(b *testing.B) {
+	b.StopTimer()
+	img := image.NewNRGBA(image.Rect(0, 0, 640, 480))
+	if img.Opaque() {
+		b.Fatal("expected image not to be opaque")
+	}
+	b.SetBytes(640 * 480 * 4)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		Encode(ioutil.Discard, img)
+	}
+}
+
 func BenchmarkEncodePaletted(b *testing.B) {
 	b.StopTimer()
 	img := image.NewPaletted(image.Rect(0, 0, 640, 480), color.Palette{
@@ -138,7 +181,7 @@ func BenchmarkEncodeRGBA(b *testing.B) {
 	b.StopTimer()
 	img := image.NewRGBA(image.Rect(0, 0, 640, 480))
 	if img.Opaque() {
-		b.Fatal("expected image to not be opaque")
+		b.Fatal("expected image not to be opaque")
 	}
 	b.SetBytes(640 * 480 * 4)
 	b.StartTimer()
diff --git a/src/pkg/image/testdata/video-001.progressive.jpeg b/src/pkg/image/testdata/video-001.progressive.jpeg
new file mode 100644
index 0000000..b8cae23
Binary files /dev/null and b/src/pkg/image/testdata/video-001.progressive.jpeg differ
diff --git a/src/pkg/image/testdata/video-001.q50.420.jpeg b/src/pkg/image/testdata/video-001.q50.420.jpeg
new file mode 100644
index 0000000..83fb0f8
Binary files /dev/null and b/src/pkg/image/testdata/video-001.q50.420.jpeg differ
diff --git a/src/pkg/image/testdata/video-001.q50.420.progressive.jpeg b/src/pkg/image/testdata/video-001.q50.420.progressive.jpeg
new file mode 100644
index 0000000..b048eb2
Binary files /dev/null and b/src/pkg/image/testdata/video-001.q50.420.progressive.jpeg differ
diff --git a/src/pkg/image/testdata/video-001.q50.422.jpeg b/src/pkg/image/testdata/video-001.q50.422.jpeg
new file mode 100644
index 0000000..60fff4f
Binary files /dev/null and b/src/pkg/image/testdata/video-001.q50.422.jpeg differ
diff --git a/src/pkg/image/testdata/video-001.q50.422.progressive.jpeg b/src/pkg/image/testdata/video-001.q50.422.progressive.jpeg
new file mode 100644
index 0000000..926d005
Binary files /dev/null and b/src/pkg/image/testdata/video-001.q50.422.progressive.jpeg differ
diff --git a/src/pkg/image/testdata/video-001.q50.440.jpeg b/src/pkg/image/testdata/video-001.q50.440.jpeg
new file mode 100644
index 0000000..32eeeae
Binary files /dev/null and b/src/pkg/image/testdata/video-001.q50.440.jpeg differ
diff --git a/src/pkg/image/testdata/video-001.q50.440.progressive.jpeg b/src/pkg/image/testdata/video-001.q50.440.progressive.jpeg
new file mode 100644
index 0000000..e641a3b
Binary files /dev/null and b/src/pkg/image/testdata/video-001.q50.440.progressive.jpeg differ
diff --git a/src/pkg/image/testdata/video-001.q50.444.jpeg b/src/pkg/image/testdata/video-001.q50.444.jpeg
new file mode 100644
index 0000000..7d57433
Binary files /dev/null and b/src/pkg/image/testdata/video-001.q50.444.jpeg differ
diff --git a/src/pkg/image/testdata/video-001.q50.444.progressive.jpeg b/src/pkg/image/testdata/video-001.q50.444.progressive.jpeg
new file mode 100644
index 0000000..ff7d5f9
Binary files /dev/null and b/src/pkg/image/testdata/video-001.q50.444.progressive.jpeg differ
diff --git a/src/pkg/image/testdata/video-005.gray.q50.2x2.jpeg b/src/pkg/image/testdata/video-005.gray.q50.2x2.jpeg
new file mode 100644
index 0000000..630b615
Binary files /dev/null and b/src/pkg/image/testdata/video-005.gray.q50.2x2.jpeg differ
diff --git a/src/pkg/image/testdata/video-005.gray.q50.2x2.progressive.jpeg b/src/pkg/image/testdata/video-005.gray.q50.2x2.progressive.jpeg
new file mode 100644
index 0000000..c6b9360
Binary files /dev/null and b/src/pkg/image/testdata/video-005.gray.q50.2x2.progressive.jpeg differ
diff --git a/src/pkg/image/testdata/video-005.gray.q50.jpeg b/src/pkg/image/testdata/video-005.gray.q50.jpeg
new file mode 100644
index 0000000..c65b5a7
Binary files /dev/null and b/src/pkg/image/testdata/video-005.gray.q50.jpeg differ
diff --git a/src/pkg/image/testdata/video-005.gray.q50.progressive.jpeg b/src/pkg/image/testdata/video-005.gray.q50.progressive.jpeg
new file mode 100644
index 0000000..24b70e8
Binary files /dev/null and b/src/pkg/image/testdata/video-005.gray.q50.progressive.jpeg differ
diff --git a/src/pkg/image/ycbcr.go b/src/pkg/image/ycbcr.go
index c1a0b66..5b73bef 100644
--- a/src/pkg/image/ycbcr.go
+++ b/src/pkg/image/ycbcr.go
@@ -15,6 +15,7 @@ const (
 	YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
 	YCbCrSubsampleRatio422
 	YCbCrSubsampleRatio420
+	YCbCrSubsampleRatio440
 )
 
 func (s YCbCrSubsampleRatio) String() string {
@@ -25,6 +26,8 @@ func (s YCbCrSubsampleRatio) String() string {
 		return "YCbCrSubsampleRatio422"
 	case YCbCrSubsampleRatio420:
 		return "YCbCrSubsampleRatio420"
+	case YCbCrSubsampleRatio440:
+		return "YCbCrSubsampleRatio440"
 	}
 	return "YCbCrSubsampleRatioUnknown"
 }
@@ -39,6 +42,7 @@ func (s YCbCrSubsampleRatio) String() string {
 //	For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1.
 //	For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2.
 //	For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4.
+//	For 4:4:0, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/2.
 type YCbCr struct {
 	Y, Cb, Cr      []uint8
 	YStride        int
@@ -82,6 +86,8 @@ func (p *YCbCr) COffset(x, y int) int {
 		return (y-p.Rect.Min.Y)*p.CStride + (x/2 - p.Rect.Min.X/2)
 	case YCbCrSubsampleRatio420:
 		return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2)
+	case YCbCrSubsampleRatio440:
+		return (y/2-p.Rect.Min.Y/2)*p.CStride + (x - p.Rect.Min.X)
 	}
 	// Default to 4:4:4 subsampling.
 	return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
@@ -126,6 +132,9 @@ func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
 	case YCbCrSubsampleRatio420:
 		cw = (r.Max.X+1)/2 - r.Min.X/2
 		ch = (r.Max.Y+1)/2 - r.Min.Y/2
+	case YCbCrSubsampleRatio440:
+		cw = w
+		ch = (r.Max.Y+1)/2 - r.Min.Y/2
 	default:
 		// Default to 4:4:4 subsampling.
 		cw = w
diff --git a/src/pkg/image/ycbcr_test.go b/src/pkg/image/ycbcr_test.go
index 5fa95be..a5f4482 100644
--- a/src/pkg/image/ycbcr_test.go
+++ b/src/pkg/image/ycbcr_test.go
@@ -36,6 +36,7 @@ func TestYCbCr(t *testing.T) {
 		YCbCrSubsampleRatio444,
 		YCbCrSubsampleRatio422,
 		YCbCrSubsampleRatio420,
+		YCbCrSubsampleRatio440,
 	}
 	deltas := []Point{
 		Pt(0, 0),
diff --git a/src/pkg/io/io.go b/src/pkg/io/io.go
index 54bf159..23d05e5 100644
--- a/src/pkg/io/io.go
+++ b/src/pkg/io/io.go
@@ -130,11 +130,23 @@ type ReadWriteSeeker interface {
 }
 
 // ReaderFrom is the interface that wraps the ReadFrom method.
+//
+// ReadFrom reads data from r until EOF or error.
+// The return value n is the number of bytes read.
+// Any error except io.EOF encountered during the read is also returned.
+//
+// The Copy function uses ReaderFrom if available.
 type ReaderFrom interface {
 	ReadFrom(r Reader) (n int64, err error)
 }
 
 // WriterTo is the interface that wraps the WriteTo method.
+//
+// WriteTo writes data to w until there's no more data to write or
+// when an error occurs. The return value n is the number of bytes
+// written. Any error encountered during the write is also returned.
+//
+// The Copy function uses WriterTo if available.
 type WriterTo interface {
 	WriteTo(w Writer) (n int64, err error)
 }
@@ -204,6 +216,11 @@ type ByteScanner interface {
 	UnreadByte() error
 }
 
+// ByteWriter is the interface that wraps the WriteByte method.
+type ByteWriter interface {
+	WriteByte(c byte) error
+}
+
 // RuneReader is the interface that wraps the ReadRune method.
 //
 // ReadRune reads a single UTF-8 encoded Unicode character
@@ -245,6 +262,7 @@ func WriteString(w Writer, s string) (n int, err error) {
 // If an EOF happens after reading fewer than min bytes,
 // ReadAtLeast returns ErrUnexpectedEOF.
 // If min is greater than the length of buf, ReadAtLeast returns ErrShortBuffer.
+// On return, n >= min if and only if err == nil.
 func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) {
 	if len(buf) < min {
 		return 0, ErrShortBuffer
@@ -254,12 +272,10 @@ func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) {
 		nn, err = r.Read(buf[n:])
 		n += nn
 	}
-	if err == EOF {
-		if n >= min {
-			err = nil
-		} else if n > 0 {
-			err = ErrUnexpectedEOF
-		}
+	if n >= min {
+		err = nil
+	} else if n > 0 && err == EOF {
+		err = ErrUnexpectedEOF
 	}
 	return
 }
@@ -269,56 +285,28 @@ func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) {
 // The error is EOF only if no bytes were read.
 // If an EOF happens after reading some but not all the bytes,
 // ReadFull returns ErrUnexpectedEOF.
+// On return, n == len(buf) if and only if err == nil.
 func ReadFull(r Reader, buf []byte) (n int, err error) {
 	return ReadAtLeast(r, buf, len(buf))
 }
 
 // CopyN copies n bytes (or until an error) from src to dst.
 // It returns the number of bytes copied and the earliest
-// error encountered while copying.  Because Read can
-// return the full amount requested as well as an error
-// (including EOF), so can CopyN.
+// error encountered while copying.
+// On return, written == n if and only if err == nil.
 //
 // If dst implements the ReaderFrom interface,
 // the copy is implemented using it.
 func CopyN(dst Writer, src Reader, n int64) (written int64, err error) {
-	// If the writer has a ReadFrom method, use it to do the copy.
-	// Avoids a buffer allocation and a copy.
-	if rt, ok := dst.(ReaderFrom); ok {
-		written, err = rt.ReadFrom(LimitReader(src, n))
-		if written < n && err == nil {
-			// rt stopped early; must have been EOF.
-			err = EOF
-		}
-		return
+	written, err = Copy(dst, LimitReader(src, n))
+	if written == n {
+		return n, nil
 	}
-	buf := make([]byte, 32*1024)
-	for written < n {
-		l := len(buf)
-		if d := n - written; d < int64(l) {
-			l = int(d)
-		}
-		nr, er := src.Read(buf[0:l])
-		if nr > 0 {
-			nw, ew := dst.Write(buf[0:nr])
-			if nw > 0 {
-				written += int64(nw)
-			}
-			if ew != nil {
-				err = ew
-				break
-			}
-			if nr != nw {
-				err = ErrShortWrite
-				break
-			}
-		}
-		if er != nil {
-			err = er
-			break
-		}
+	if written < n && err == nil {
+		// src stopped early; must have been EOF.
+		err = EOF
 	}
-	return written, err
+	return
 }
 
 // Copy copies from src to dst until either EOF is reached
@@ -451,6 +439,11 @@ func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error) {
 	off += s.base
 	if max := s.limit - off; int64(len(p)) > max {
 		p = p[0:max]
+		n, err = s.r.ReadAt(p, off)
+		if err == nil {
+			err = EOF
+		}
+		return n, err
 	}
 	return s.r.ReadAt(p, off)
 }
diff --git a/src/pkg/io/io_test.go b/src/pkg/io/io_test.go
index 1e671b5..1bc451e 100644
--- a/src/pkg/io/io_test.go
+++ b/src/pkg/io/io_test.go
@@ -6,6 +6,8 @@ package io_test
 
 import (
 	"bytes"
+	"errors"
+	"fmt"
 	. "io"
 	"strings"
 	"testing"
@@ -88,6 +90,12 @@ func (w *noReadFrom) Write(p []byte) (n int, err error) {
 	return w.w.Write(p)
 }
 
+type wantedAndErrReader struct{}
+
+func (wantedAndErrReader) Read(p []byte) (int, error) {
+	return len(p), errors.New("wantedAndErrReader error")
+}
+
 func TestCopyNEOF(t *testing.T) {
 	// Test that EOF behavior is the same regardless of whether
 	// argument to CopyN has ReadFrom.
@@ -113,6 +121,16 @@ func TestCopyNEOF(t *testing.T) {
 	if n != 3 || err != EOF {
 		t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err)
 	}
+
+	n, err = CopyN(b, wantedAndErrReader{}, 5)
+	if n != 5 || err != nil {
+		t.Errorf("CopyN(bytes.Buffer, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err)
+	}
+
+	n, err = CopyN(&noReadFrom{b}, wantedAndErrReader{}, 5)
+	if n != 5 || err != nil {
+		t.Errorf("CopyN(noReadFrom, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err)
+	}
 }
 
 func TestReadAtLeast(t *testing.T) {
@@ -120,22 +138,30 @@ func TestReadAtLeast(t *testing.T) {
 	testReadAtLeast(t, &rb)
 }
 
-// A version of bytes.Buffer that returns n > 0, EOF on Read
+// A version of bytes.Buffer that returns n > 0, err on Read
 // when the input is exhausted.
-type dataAndEOFBuffer struct {
+type dataAndErrorBuffer struct {
+	err error
 	bytes.Buffer
 }
 
-func (r *dataAndEOFBuffer) Read(p []byte) (n int, err error) {
+func (r *dataAndErrorBuffer) Read(p []byte) (n int, err error) {
 	n, err = r.Buffer.Read(p)
 	if n > 0 && r.Buffer.Len() == 0 && err == nil {
-		err = EOF
+		err = r.err
 	}
 	return
 }
 
 func TestReadAtLeastWithDataAndEOF(t *testing.T) {
-	var rb dataAndEOFBuffer
+	var rb dataAndErrorBuffer
+	rb.err = EOF
+	testReadAtLeast(t, &rb)
+}
+
+func TestReadAtLeastWithDataAndError(t *testing.T) {
+	var rb dataAndErrorBuffer
+	rb.err = fmt.Errorf("fake error")
 	testReadAtLeast(t, &rb)
 }
 
@@ -169,8 +195,12 @@ func testReadAtLeast(t *testing.T, rb ReadWriter) {
 	}
 	rb.Write([]byte("4"))
 	n, err = ReadAtLeast(rb, buf, 2)
-	if err != ErrUnexpectedEOF {
-		t.Errorf("expected ErrUnexpectedEOF, got %v", err)
+	want := ErrUnexpectedEOF
+	if rb, ok := rb.(*dataAndErrorBuffer); ok && rb.err != EOF {
+		want = rb.err
+	}
+	if err != want {
+		t.Errorf("expected %v, got %v", want, err)
 	}
 	if n != 1 {
 		t.Errorf("expected to have read 1 bytes, got %v", n)
@@ -203,3 +233,35 @@ func TestTeeReader(t *testing.T) {
 		t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err)
 	}
 }
+
+func TestSectionReader_ReadAt(tst *testing.T) {
+	dat := "a long sample data, 1234567890"
+	tests := []struct {
+		data   string
+		off    int
+		n      int
+		bufLen int
+		at     int
+		exp    string
+		err    error
+	}{
+		{data: "", off: 0, n: 10, bufLen: 2, at: 0, exp: "", err: EOF},
+		{data: dat, off: 0, n: len(dat), bufLen: 0, at: 0, exp: "", err: nil},
+		{data: dat, off: len(dat), n: 1, bufLen: 1, at: 0, exp: "", err: EOF},
+		{data: dat, off: 0, n: len(dat) + 2, bufLen: len(dat), at: 0, exp: dat, err: nil},
+		{data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 0, exp: dat[:len(dat)/2], err: nil},
+		{data: dat, off: 0, n: len(dat), bufLen: len(dat), at: 0, exp: dat, err: nil},
+		{data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[2 : 2+len(dat)/2], err: nil},
+		{data: dat, off: 3, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[5 : 5+len(dat)/2], err: nil},
+		{data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 - 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: nil},
+		{data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 + 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: EOF},
+	}
+	for i, t := range tests {
+		r := strings.NewReader(t.data)
+		s := NewSectionReader(r, int64(t.off), int64(t.n))
+		buf := make([]byte, t.bufLen)
+		if n, err := s.ReadAt(buf, int64(t.at)); n != len(t.exp) || string(buf[:n]) != t.exp || err != t.err {
+			tst.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i, t.at, buf[:n], err, t.exp, t.err)
+		}
+	}
+}
diff --git a/src/pkg/io/ioutil/blackhole.go b/src/pkg/io/ioutil/blackhole.go
new file mode 100644
index 0000000..101d2c1
--- /dev/null
+++ b/src/pkg/io/ioutil/blackhole.go
@@ -0,0 +1,23 @@
+// 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 ioutil
+
+var blackHoleBuf = make(chan []byte, 1)
+
+func blackHole() []byte {
+	select {
+	case b := <-blackHoleBuf:
+		return b
+	default:
+	}
+	return make([]byte, 8192)
+}
+
+func blackHolePut(p []byte) {
+	select {
+	case blackHoleBuf <- p:
+	default:
+	}
+}
diff --git a/src/pkg/io/ioutil/ioutil.go b/src/pkg/io/ioutil/ioutil.go
index f072b8c..0eb146c 100644
--- a/src/pkg/io/ioutil/ioutil.go
+++ b/src/pkg/io/ioutil/ioutil.go
@@ -130,12 +130,12 @@ func (devNull) Write(p []byte) (int, error) {
 	return len(p), nil
 }
 
-var blackHole = make([]byte, 8192)
-
 func (devNull) ReadFrom(r io.Reader) (n int64, err error) {
+	buf := blackHole()
+	defer blackHolePut(buf)
 	readSize := 0
 	for {
-		readSize, err = r.Read(blackHole)
+		readSize, err = r.Read(buf)
 		n += int64(readSize)
 		if err != nil {
 			if err == io.EOF {
diff --git a/src/pkg/io/ioutil/ioutil_test.go b/src/pkg/io/ioutil/ioutil_test.go
index d9c43be..c297847 100644
--- a/src/pkg/io/ioutil/ioutil_test.go
+++ b/src/pkg/io/ioutil/ioutil_test.go
@@ -2,10 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package ioutil_test
+package ioutil
 
 import (
-	. "io/ioutil"
 	"os"
 	"testing"
 )
diff --git a/src/pkg/io/ioutil/tempfile.go b/src/pkg/io/ioutil/tempfile.go
index 42d2e67..4a06e97 100644
--- a/src/pkg/io/ioutil/tempfile.go
+++ b/src/pkg/io/ioutil/tempfile.go
@@ -8,26 +8,30 @@ import (
 	"os"
 	"path/filepath"
 	"strconv"
+	"sync"
 	"time"
 )
 
-// Random number state, accessed without lock; racy but harmless.
+// Random number state.
 // We generate random temporary file names so that there's a good
 // chance the file doesn't exist yet - keeps the number of tries in
 // TempFile to a minimum.
 var rand uint32
+var randmu sync.Mutex
 
 func reseed() uint32 {
 	return uint32(time.Now().UnixNano() + int64(os.Getpid()))
 }
 
 func nextSuffix() string {
+	randmu.Lock()
 	r := rand
 	if r == 0 {
 		r = reseed()
 	}
 	r = r*1664525 + 1013904223 // constants from Numerical Recipes
 	rand = r
+	randmu.Unlock()
 	return strconv.Itoa(int(1e9 + r%1e9))[1:]
 }
 
@@ -38,8 +42,8 @@ func nextSuffix() string {
 // for temporary files (see os.TempDir).
 // Multiple programs calling TempFile simultaneously
 // will not choose the same file.  The caller can use f.Name()
-// to find the name of the file.  It is the caller's responsibility to
-// remove the file when no longer needed.
+// to find the pathname of the file.  It is the caller's responsibility
+// to remove the file when no longer needed.
 func TempFile(dir, prefix string) (f *os.File, err error) {
 	if dir == "" {
 		dir = os.TempDir()
diff --git a/src/pkg/io/ioutil/tempfile_test.go b/src/pkg/io/ioutil/tempfile_test.go
index 80c62f6..d2a132a 100644
--- a/src/pkg/io/ioutil/tempfile_test.go
+++ b/src/pkg/io/ioutil/tempfile_test.go
@@ -2,10 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package ioutil_test
+package ioutil
 
 import (
-	. "io/ioutil"
 	"os"
 	"path/filepath"
 	"regexp"
diff --git a/src/pkg/log/syslog/syslog.go b/src/pkg/log/syslog/syslog.go
index f53310c..8bdd982 100644
--- a/src/pkg/log/syslog/syslog.go
+++ b/src/pkg/log/syslog/syslog.go
@@ -4,9 +4,13 @@
 
 // +build !windows,!plan9
 
-// Package syslog provides a simple interface to the system log service. It
-// can send messages to the syslog daemon using UNIX domain sockets, UDP, or
-// TCP connections.
+// Package syslog provides a simple interface to the system log
+// service. It can send messages to the syslog daemon using UNIX
+// domain sockets, UDP or TCP.
+//
+// Only one call to Dial is necessary. On write failures,
+// the syslog client will attempt to reconnect to the server
+// and write again.
 package syslog
 
 import (
@@ -15,11 +19,23 @@ import (
 	"log"
 	"net"
 	"os"
+	"strings"
+	"sync"
+	"time"
 )
 
+// The Priority is a combination of the syslog facility and
+// severity. For example, LOG_ALERT | LOG_FTP sends an alert severity
+// message from the FTP facility. The default severity is LOG_EMERG;
+// the default facility is LOG_KERN.
 type Priority int
 
+const severityMask = 0x07
+const facilityMask = 0xf8
+
 const (
+	// Severity.
+
 	// From /usr/include/sys/syslog.h.
 	// These are the same on Linux, BSD, and OS X.
 	LOG_EMERG Priority = iota
@@ -32,129 +48,220 @@ const (
 	LOG_DEBUG
 )
 
+const (
+	// Facility.
+
+	// From /usr/include/sys/syslog.h.
+	// These are the same up to LOG_FTP on Linux, BSD, and OS X.
+	LOG_KERN Priority = iota << 3
+	LOG_USER
+	LOG_MAIL
+	LOG_DAEMON
+	LOG_AUTH
+	LOG_SYSLOG
+	LOG_LPR
+	LOG_NEWS
+	LOG_UUCP
+	LOG_CRON
+	LOG_AUTHPRIV
+	LOG_FTP
+	_ // unused
+	_ // unused
+	_ // unused
+	_ // unused
+	LOG_LOCAL0
+	LOG_LOCAL1
+	LOG_LOCAL2
+	LOG_LOCAL3
+	LOG_LOCAL4
+	LOG_LOCAL5
+	LOG_LOCAL6
+	LOG_LOCAL7
+)
+
 // A Writer is a connection to a syslog server.
 type Writer struct {
 	priority Priority
-	prefix   string
-	conn     serverConn
-}
+	tag      string
+	hostname string
+	network  string
+	raddr    string
 
-type serverConn interface {
-	writeBytes(p Priority, prefix string, b []byte) (int, error)
-	writeString(p Priority, prefix string, s string) (int, error)
-	close() error
+	mu   sync.Mutex // guards conn
+	conn net.Conn
 }
 
-type netConn struct {
-	conn net.Conn
+// New establishes a new connection to the system log daemon.  Each
+// write to the returned writer sends a log message with the given
+// priority and prefix.
+func New(priority Priority, tag string) (w *Writer, err error) {
+	return Dial("", "", priority, tag)
 }
 
-// New establishes a new connection to the system log daemon.
-// Each write to the returned writer sends a log message with
-// the given priority and prefix.
-func New(priority Priority, prefix string) (w *Writer, err error) {
-	return Dial("", "", priority, prefix)
+// Dial establishes a connection to a log daemon by connecting to
+// address raddr on the network net.  Each write to the returned
+// writer sends a log message with the given facility, severity and
+// tag.
+func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) {
+	if priority < 0 || priority > LOG_LOCAL7|LOG_DEBUG {
+		return nil, errors.New("log/syslog: invalid priority")
+	}
+
+	if tag == "" {
+		tag = os.Args[0]
+	}
+	hostname, _ := os.Hostname()
+
+	w := &Writer{
+		priority: priority,
+		tag:      tag,
+		hostname: hostname,
+		network:  network,
+		raddr:    raddr,
+	}
+
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	err := w.connect()
+	if err != nil {
+		return nil, err
+	}
+	return w, err
 }
 
-// Dial establishes a connection to a log daemon by connecting
-// to address raddr on the network net.
-// Each write to the returned writer sends a log message with
-// the given priority and prefix.
-func Dial(network, raddr string, priority Priority, prefix string) (w *Writer, err error) {
-	if prefix == "" {
-		prefix = os.Args[0]
+// connect makes a connection to the syslog server.
+// It must be called with w.mu held.
+func (w *Writer) connect() (err error) {
+	if w.conn != nil {
+		// ignore err from close, it makes sense to continue anyway
+		w.conn.Close()
+		w.conn = nil
 	}
-	var conn serverConn
-	if network == "" {
-		conn, err = unixSyslog()
+
+	if w.network == "" {
+		w.conn, err = unixSyslog()
+		if w.hostname == "" {
+			w.hostname = "localhost"
+		}
 	} else {
 		var c net.Conn
-		c, err = net.Dial(network, raddr)
-		conn = netConn{c}
+		c, err = net.Dial(w.network, w.raddr)
+		if err == nil {
+			w.conn = c
+			if w.hostname == "" {
+				w.hostname = c.LocalAddr().String()
+			}
+		}
 	}
-	return &Writer{priority, prefix, conn}, err
+	return
 }
 
 // Write sends a log message to the syslog daemon.
 func (w *Writer) Write(b []byte) (int, error) {
-	if w.priority > LOG_DEBUG || w.priority < LOG_EMERG {
-		return 0, errors.New("log/syslog: invalid priority")
-	}
-	return w.conn.writeBytes(w.priority, w.prefix, b)
+	return w.writeAndRetry(w.priority, string(b))
 }
 
-func (w *Writer) writeString(p Priority, s string) (int, error) {
-	return w.conn.writeString(p, w.prefix, s)
-}
+// Close closes a connection to the syslog daemon.
+func (w *Writer) Close() error {
+	w.mu.Lock()
+	defer w.mu.Unlock()
 
-func (w *Writer) Close() error { return w.conn.close() }
+	if w.conn != nil {
+		err := w.conn.Close()
+		w.conn = nil
+		return err
+	}
+	return nil
+}
 
-// Emerg logs a message using the LOG_EMERG priority.
+// Emerg logs a message with severity LOG_EMERG, ignoring the severity
+// passed to New.
 func (w *Writer) Emerg(m string) (err error) {
-	_, err = w.writeString(LOG_EMERG, m)
+	_, err = w.writeAndRetry(LOG_EMERG, m)
 	return err
 }
 
-// Alert logs a message using the LOG_ALERT priority.
+// Alert logs a message with severity LOG_ALERT, ignoring the severity
+// passed to New.
 func (w *Writer) Alert(m string) (err error) {
-	_, err = w.writeString(LOG_ALERT, m)
+	_, err = w.writeAndRetry(LOG_ALERT, m)
 	return err
 }
 
-// Crit logs a message using the LOG_CRIT priority.
+// Crit logs a message with severity LOG_CRIT, ignoring the severity
+// passed to New.
 func (w *Writer) Crit(m string) (err error) {
-	_, err = w.writeString(LOG_CRIT, m)
+	_, err = w.writeAndRetry(LOG_CRIT, m)
 	return err
 }
 
-// Err logs a message using the LOG_ERR priority.
+// Err logs a message with severity LOG_ERR, ignoring the severity
+// passed to New.
 func (w *Writer) Err(m string) (err error) {
-	_, err = w.writeString(LOG_ERR, m)
+	_, err = w.writeAndRetry(LOG_ERR, m)
 	return err
 }
 
-// Warning logs a message using the LOG_WARNING priority.
+// Wanring logs a message with severity LOG_WARNING, ignoring the
+// severity passed to New.
 func (w *Writer) Warning(m string) (err error) {
-	_, err = w.writeString(LOG_WARNING, m)
+	_, err = w.writeAndRetry(LOG_WARNING, m)
 	return err
 }
 
-// Notice logs a message using the LOG_NOTICE priority.
+// Notice logs a message with severity LOG_NOTICE, ignoring the
+// severity passed to New.
 func (w *Writer) Notice(m string) (err error) {
-	_, err = w.writeString(LOG_NOTICE, m)
+	_, err = w.writeAndRetry(LOG_NOTICE, m)
 	return err
 }
 
-// Info logs a message using the LOG_INFO priority.
+// Info logs a message with severity LOG_INFO, ignoring the severity
+// passed to New.
 func (w *Writer) Info(m string) (err error) {
-	_, err = w.writeString(LOG_INFO, m)
+	_, err = w.writeAndRetry(LOG_INFO, m)
 	return err
 }
 
-// Debug logs a message using the LOG_DEBUG priority.
+// Debug logs a message with severity LOG_DEBUG, ignoring the severity
+// passed to New.
 func (w *Writer) Debug(m string) (err error) {
-	_, err = w.writeString(LOG_DEBUG, m)
+	_, err = w.writeAndRetry(LOG_DEBUG, m)
 	return err
 }
 
-func (n netConn) writeBytes(p Priority, prefix string, b []byte) (int, error) {
-	_, err := fmt.Fprintf(n.conn, "<%d>%s: %s\n", p, prefix, b)
-	if err != nil {
+func (w *Writer) writeAndRetry(p Priority, s string) (int, error) {
+	pr := (w.priority & facilityMask) | (p & severityMask)
+
+	w.mu.Lock()
+	defer w.mu.Unlock()
+
+	if w.conn != nil {
+		if n, err := w.write(pr, s); err == nil {
+			return n, err
+		}
+	}
+	if err := w.connect(); err != nil {
 		return 0, err
 	}
-	return len(b), nil
+	return w.write(pr, s)
 }
 
-func (n netConn) writeString(p Priority, prefix string, s string) (int, error) {
-	_, err := fmt.Fprintf(n.conn, "<%d>%s: %s\n", p, prefix, s)
-	if err != nil {
-		return 0, err
+// write generates and writes a syslog formatted string. The
+// format is as follows: <PRI>TIMESTAMP HOSTNAME TAG[PID]: MSG
+func (w *Writer) write(p Priority, msg string) (int, error) {
+	// ensure it ends in a \n
+	nl := ""
+	if !strings.HasSuffix(msg, "\n") {
+		nl = "\n"
 	}
-	return len(s), nil
-}
 
-func (n netConn) close() error {
-	return n.conn.Close()
+	timestamp := time.Now().Format(time.RFC3339)
+	fmt.Fprintf(w.conn, "<%d>%s %s %s[%d]: %s%s",
+		p, timestamp, w.hostname,
+		w.tag, os.Getpid(), msg, nl)
+	return len(msg), nil
 }
 
 // NewLogger creates a log.Logger whose output is written to
diff --git a/src/pkg/log/syslog/syslog_plan9.go b/src/pkg/log/syslog/syslog_plan9.go
new file mode 100644
index 0000000..0c05f6f
--- /dev/null
+++ b/src/pkg/log/syslog/syslog_plan9.go
@@ -0,0 +1,8 @@
+// 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 syslog provides a simple interface to the system log service.
+package syslog
+
+// BUG(akumar): This package is not implemented on Plan 9 yet.
diff --git a/src/pkg/log/syslog/syslog_test.go b/src/pkg/log/syslog/syslog_test.go
index 0fd6239..ec45251 100644
--- a/src/pkg/log/syslog/syslog_test.go
+++ b/src/pkg/log/syslog/syslog_test.go
@@ -7,52 +7,181 @@
 package syslog
 
 import (
+	"bufio"
+	"fmt"
 	"io"
+	"io/ioutil"
 	"log"
 	"net"
+	"os"
+	"sync"
 	"testing"
 	"time"
 )
 
-var serverAddr string
-
-func runSyslog(c net.PacketConn, done chan<- string) {
+func runPktSyslog(c net.PacketConn, done chan<- string) {
 	var buf [4096]byte
-	var rcvd string = ""
+	var rcvd string
+	ct := 0
 	for {
-		n, _, err := c.ReadFrom(buf[0:])
-		if err != nil || n == 0 {
+		var n int
+		var err error
+
+		c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		n, _, err = c.ReadFrom(buf[:])
+		rcvd += string(buf[:n])
+		if err != nil {
+			if oe, ok := err.(*net.OpError); ok {
+				if ct < 3 && oe.Temporary() {
+					ct++
+					continue
+				}
+			}
 			break
 		}
-		rcvd += string(buf[0:n])
 	}
+	c.Close()
 	done <- rcvd
 }
 
-func startServer(done chan<- string) {
-	c, e := net.ListenPacket("udp", "127.0.0.1:0")
-	if e != nil {
-		log.Fatalf("net.ListenPacket failed udp :0 %v", e)
+var crashy = false
+
+func runStreamSyslog(l net.Listener, done chan<- string, wg *sync.WaitGroup) {
+	for {
+		var c net.Conn
+		var err error
+		if c, err = l.Accept(); err != nil {
+			return
+		}
+		wg.Add(1)
+		go func(c net.Conn) {
+			defer wg.Done()
+			c.SetReadDeadline(time.Now().Add(5 * time.Second))
+			b := bufio.NewReader(c)
+			for ct := 1; !crashy || ct&7 != 0; ct++ {
+				s, err := b.ReadString('\n')
+				if err != nil {
+					break
+				}
+				done <- s
+			}
+			c.Close()
+		}(c)
 	}
-	serverAddr = c.LocalAddr().String()
-	c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
-	go runSyslog(c, done)
 }
 
-func skipNetTest(t *testing.T) bool {
-	if testing.Short() {
-		// Depends on syslog daemon running, and sometimes it's not.
-		t.Logf("skipping syslog test during -short")
-		return true
+func startServer(n, la string, done chan<- string) (addr string, sock io.Closer, wg *sync.WaitGroup) {
+	if n == "udp" || n == "tcp" {
+		la = "127.0.0.1:0"
+	} else {
+		// unix and unixgram: choose an address if none given
+		if la == "" {
+			// use ioutil.TempFile to get a name that is unique
+			f, err := ioutil.TempFile("", "syslogtest")
+			if err != nil {
+				log.Fatal("TempFile: ", err)
+			}
+			f.Close()
+			la = f.Name()
+		}
+		os.Remove(la)
+	}
+
+	wg = new(sync.WaitGroup)
+	if n == "udp" || n == "unixgram" {
+		l, e := net.ListenPacket(n, la)
+		if e != nil {
+			log.Fatalf("startServer failed: %v", e)
+		}
+		addr = l.LocalAddr().String()
+		sock = l
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			runPktSyslog(l, done)
+		}()
+	} else {
+		l, e := net.Listen(n, la)
+		if e != nil {
+			log.Fatalf("startServer failed: %v", e)
+		}
+		addr = l.Addr().String()
+		sock = l
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			runStreamSyslog(l, done, wg)
+		}()
+	}
+	return
+}
+
+func TestWithSimulated(t *testing.T) {
+	msg := "Test 123"
+	transport := []string{"unix", "unixgram", "udp", "tcp"}
+
+	for _, tr := range transport {
+		done := make(chan string)
+		addr, _, _ := startServer(tr, "", done)
+		if tr == "unix" || tr == "unixgram" {
+			defer os.Remove(addr)
+		}
+		s, err := Dial(tr, addr, LOG_INFO|LOG_USER, "syslog_test")
+		if err != nil {
+			t.Fatalf("Dial() failed: %v", err)
+		}
+		err = s.Info(msg)
+		if err != nil {
+			t.Fatalf("log failed: %v", err)
+		}
+		check(t, msg, <-done)
+		s.Close()
+	}
+}
+
+func TestFlap(t *testing.T) {
+	net := "unix"
+	done := make(chan string)
+	addr, sock, _ := startServer(net, "", done)
+	defer os.Remove(addr)
+	defer sock.Close()
+
+	s, err := Dial(net, addr, LOG_INFO|LOG_USER, "syslog_test")
+	if err != nil {
+		t.Fatalf("Dial() failed: %v", err)
+	}
+	msg := "Moo 2"
+	err = s.Info(msg)
+	if err != nil {
+		t.Fatalf("log failed: %v", err)
+	}
+	check(t, msg, <-done)
+
+	// restart the server
+	_, sock2, _ := startServer(net, addr, done)
+	defer sock2.Close()
+
+	// and try retransmitting
+	msg = "Moo 3"
+	err = s.Info(msg)
+	if err != nil {
+		t.Fatalf("log failed: %v", err)
 	}
-	return false
+	check(t, msg, <-done)
+
+	s.Close()
 }
 
 func TestNew(t *testing.T) {
-	if skipNetTest(t) {
-		return
+	if LOG_LOCAL7 != 23<<3 {
+		t.Fatalf("LOG_LOCAL7 has wrong value")
+	}
+	if testing.Short() {
+		// Depends on syslog daemon running, and sometimes it's not.
+		t.Skip("skipping syslog test during -short")
 	}
-	s, err := New(LOG_INFO, "")
+
+	s, err := New(LOG_INFO|LOG_USER, "the_tag")
 	if err != nil {
 		t.Fatalf("New() failed: %s", err)
 	}
@@ -61,57 +190,159 @@ func TestNew(t *testing.T) {
 }
 
 func TestNewLogger(t *testing.T) {
-	if skipNetTest(t) {
-		return
+	if testing.Short() {
+		t.Skip("skipping syslog test during -short")
 	}
-	f, err := NewLogger(LOG_INFO, 0)
+	f, err := NewLogger(LOG_USER|LOG_INFO, 0)
 	if f == nil {
 		t.Error(err)
 	}
 }
 
 func TestDial(t *testing.T) {
-	if skipNetTest(t) {
-		return
+	if testing.Short() {
+		t.Skip("skipping syslog test during -short")
 	}
-	l, err := Dial("", "", LOG_ERR, "syslog_test")
+	f, err := Dial("", "", (LOG_LOCAL7|LOG_DEBUG)+1, "syslog_test")
+	if f != nil {
+		t.Fatalf("Should have trapped bad priority")
+	}
+	f, err = Dial("", "", -1, "syslog_test")
+	if f != nil {
+		t.Fatalf("Should have trapped bad priority")
+	}
+	l, err := Dial("", "", LOG_USER|LOG_ERR, "syslog_test")
 	if err != nil {
 		t.Fatalf("Dial() failed: %s", err)
 	}
 	l.Close()
 }
 
-func TestUDPDial(t *testing.T) {
-	done := make(chan string)
-	startServer(done)
-	l, err := Dial("udp", serverAddr, LOG_INFO, "syslog_test")
-	if err != nil {
-		t.Fatalf("syslog.Dial() failed: %s", err)
-	}
-	msg := "udp test"
-	l.Info(msg)
-	expected := "<6>syslog_test: udp test\n"
-	rcvd := <-done
-	if rcvd != expected {
-		t.Fatalf("s.Info() = '%q', but wanted '%q'", rcvd, expected)
+func check(t *testing.T, in, out string) {
+	tmpl := fmt.Sprintf("<%d>%%s %%s syslog_test[%%d]: %s\n", LOG_USER+LOG_INFO, in)
+	if hostname, err := os.Hostname(); err != nil {
+		t.Error("Error retrieving hostname")
+	} else {
+		var parsedHostname, timestamp string
+		var pid int
+		if n, err := fmt.Sscanf(out, tmpl, &timestamp, &parsedHostname, &pid); n != 3 || err != nil || hostname != parsedHostname {
+			t.Errorf("Got %q, does not match template %q (%d %s)", out, tmpl, n, err)
+		}
 	}
 }
 
 func TestWrite(t *testing.T) {
-	done := make(chan string)
-	startServer(done)
-	l, err := Dial("udp", serverAddr, LOG_ERR, "syslog_test")
-	if err != nil {
-		t.Fatalf("syslog.Dial() failed: %s", err)
+	tests := []struct {
+		pri Priority
+		pre string
+		msg string
+		exp string
+	}{
+		{LOG_USER | LOG_ERR, "syslog_test", "", "%s %s syslog_test[%d]: \n"},
+		{LOG_USER | LOG_ERR, "syslog_test", "write test", "%s %s syslog_test[%d]: write test\n"},
+		// Write should not add \n if there already is one
+		{LOG_USER | LOG_ERR, "syslog_test", "write test 2\n", "%s %s syslog_test[%d]: write test 2\n"},
 	}
-	msg := "write test"
-	_, err = io.WriteString(l, msg)
+
+	if hostname, err := os.Hostname(); err != nil {
+		t.Fatalf("Error retrieving hostname")
+	} else {
+		for _, test := range tests {
+			done := make(chan string)
+			addr, sock, _ := startServer("udp", "", done)
+			defer sock.Close()
+			l, err := Dial("udp", addr, test.pri, test.pre)
+			if err != nil {
+				t.Fatalf("syslog.Dial() failed: %v", err)
+			}
+			_, err = io.WriteString(l, test.msg)
+			if err != nil {
+				t.Fatalf("WriteString() failed: %v", err)
+			}
+			rcvd := <-done
+			test.exp = fmt.Sprintf("<%d>", test.pri) + test.exp
+			var parsedHostname, timestamp string
+			var pid int
+			if n, err := fmt.Sscanf(rcvd, test.exp, &timestamp, &parsedHostname, &pid); n != 3 || err != nil || hostname != parsedHostname {
+				t.Errorf("s.Info() = '%q', didn't match '%q' (%d %s)", rcvd, test.exp, n, err)
+			}
+		}
+	}
+}
+
+func TestConcurrentWrite(t *testing.T) {
+	addr, sock, _ := startServer("udp", "", make(chan string))
+	defer sock.Close()
+	w, err := Dial("udp", addr, LOG_USER|LOG_ERR, "how's it going?")
 	if err != nil {
-		t.Fatalf("WriteString() failed: %s", err)
+		t.Fatalf("syslog.Dial() failed: %v", err)
+	}
+	var wg sync.WaitGroup
+	for i := 0; i < 10; i++ {
+		wg.Add(1)
+		go func() {
+			err := w.Info("test")
+			if err != nil {
+				t.Errorf("Info() failed: %v", err)
+				return
+			}
+			wg.Done()
+		}()
 	}
-	expected := "<3>syslog_test: write test\n"
-	rcvd := <-done
-	if rcvd != expected {
-		t.Fatalf("s.Info() = '%q', but wanted '%q'", rcvd, expected)
+	wg.Wait()
+}
+
+func TestConcurrentReconnect(t *testing.T) {
+	crashy = true
+	defer func() { crashy = false }()
+
+	net := "unix"
+	done := make(chan string)
+	addr, sock, srvWG := startServer(net, "", done)
+	defer os.Remove(addr)
+
+	// count all the messages arriving
+	count := make(chan int)
+	go func() {
+		ct := 0
+		for _ = range done {
+			ct++
+			// we are looking for 500 out of 1000 events
+			// here because lots of log messages are lost
+			// in buffers (kernel and/or bufio)
+			if ct > 500 {
+				break
+			}
+		}
+		count <- ct
+	}()
+
+	var wg sync.WaitGroup
+	for i := 0; i < 10; i++ {
+		wg.Add(1)
+		go func() {
+			w, err := Dial(net, addr, LOG_USER|LOG_ERR, "tag")
+			if err != nil {
+				t.Fatalf("syslog.Dial() failed: %v", err)
+			}
+			for i := 0; i < 100; i++ {
+				err := w.Info("test")
+				if err != nil {
+					t.Errorf("Info() failed: %v", err)
+					return
+				}
+			}
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+	sock.Close()
+	srvWG.Wait()
+	close(done)
+
+	select {
+	case <-count:
+	case <-time.After(100 * time.Millisecond):
+		t.Error("timeout in concurrent reconnect")
 	}
 }
diff --git a/src/pkg/log/syslog/syslog_unix.go b/src/pkg/log/syslog/syslog_unix.go
index 46a164d..a0001cc 100644
--- a/src/pkg/log/syslog/syslog_unix.go
+++ b/src/pkg/log/syslog/syslog_unix.go
@@ -14,18 +14,16 @@ import (
 // unixSyslog opens a connection to the syslog daemon running on the
 // local machine using a Unix domain socket.
 
-func unixSyslog() (conn serverConn, err error) {
+func unixSyslog() (conn net.Conn, err error) {
 	logTypes := []string{"unixgram", "unix"}
 	logPaths := []string{"/dev/log", "/var/run/syslog"}
-	var raddr string
 	for _, network := range logTypes {
 		for _, path := range logPaths {
-			raddr = path
-			conn, err := net.Dial(network, raddr)
+			conn, err := net.Dial(network, path)
 			if err != nil {
 				continue
 			} else {
-				return netConn{conn}, nil
+				return conn, nil
 			}
 		}
 	}
diff --git a/src/pkg/math/abs_arm.s b/src/pkg/math/abs_arm.s
index 23f6a2a..37a1459 100644
--- a/src/pkg/math/abs_arm.s
+++ b/src/pkg/math/abs_arm.s
@@ -3,4 +3,9 @@
 // license that can be found in the LICENSE file.
 
 TEXT ·Abs(SB),7,$0
-	B ·abs(SB)
+	MOVW	x+0(FP), R0
+	MOVW	x+4(FP), R1
+	AND 	$((1<<31)-1), R1
+	MOVW	R0, r+8(FP)
+	MOVW	R1, r+12(FP)
+	RET
diff --git a/src/pkg/math/acosh.go b/src/pkg/math/acosh.go
index c6c8645..e394008 100644
--- a/src/pkg/math/acosh.go
+++ b/src/pkg/math/acosh.go
@@ -33,7 +33,7 @@ package math
 //	acosh(NaN) is NaN without signal.
 //
 
-// Acosh(x) calculates the inverse hyperbolic cosine of x.
+// Acosh returns the inverse hyperbolic cosine of x.
 //
 // Special cases are:
 //	Acosh(+Inf) = +Inf
diff --git a/src/pkg/math/all_test.go b/src/pkg/math/all_test.go
index ed66a42..0d8b10f 100644
--- a/src/pkg/math/all_test.go
+++ b/src/pkg/math/all_test.go
@@ -1128,11 +1128,11 @@ var vfgammaSC = []float64{
 	NaN(),
 }
 var gammaSC = []float64{
+	NaN(),
+	NaN(),
 	Inf(-1),
 	Inf(1),
 	Inf(1),
-	Inf(1),
-	Inf(1),
 	NaN(),
 }
 
@@ -1693,6 +1693,17 @@ func alike(a, b float64) bool {
 	return false
 }
 
+func TestNaN(t *testing.T) {
+	f64 := NaN()
+	if f64 == f64 {
+		t.Fatalf("NaN() returns %g, expected NaN", f64)
+	}
+	f32 := float32(f64)
+	if f32 == f32 {
+		t.Fatalf("float32(NaN()) is %g, expected NaN", f32)
+	}
+}
+
 func TestAcos(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
 		a := vf[i] / 10
@@ -2270,6 +2281,13 @@ func TestLog2(t *testing.T) {
 			t.Errorf("Log2(%g) = %g, want %g", vflogSC[i], f, logSC[i])
 		}
 	}
+	for i := -1074; i <= 1023; i++ {
+		f := Ldexp(1, i)
+		l := Log2(f)
+		if l != float64(i) {
+			t.Errorf("Log2(2**%d) = %g, want %d", i, l, i)
+		}
+	}
 }
 
 func TestModf(t *testing.T) {
diff --git a/src/pkg/math/asinh.go b/src/pkg/math/asinh.go
index 0defbb9..ff2de02 100644
--- a/src/pkg/math/asinh.go
+++ b/src/pkg/math/asinh.go
@@ -30,7 +30,7 @@ package math
 //	         := sign(x)*log1p(|x| + x**2/(1 + sqrt(1+x**2)))
 //
 
-// Asinh(x) calculates the inverse hyperbolic sine of x.
+// Asinh returns the inverse hyperbolic sine of x.
 //
 // Special cases are:
 //	Asinh(±0) = ±0
diff --git a/src/pkg/math/atan.go b/src/pkg/math/atan.go
index d424a2b..c107d38 100644
--- a/src/pkg/math/atan.go
+++ b/src/pkg/math/atan.go
@@ -6,51 +6,92 @@ package math
 
 /*
 	Floating-point arctangent.
-
-	Atan returns the value of the arctangent of its
-	argument in the range [-pi/2,pi/2].
-	There are no error returns.
-	Coefficients are #5077 from Hart & Cheney. (19.56D)
 */
 
-// xatan evaluates a series valid in the
-// range [-0.414...,+0.414...]. (tan(pi/8))
-func xatan(arg float64) float64 {
+// The original C code, the long comment, and the constants below were
+// from http://netlib.sandia.gov/cephes/cmath/atan.c, available from
+// http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a version of the original C.
+//
+// atan.c
+// Inverse circular tangent (arctangent)
+//
+// SYNOPSIS:
+// double x, y, atan();
+// y = atan( x );
+//
+// DESCRIPTION:
+// Returns radian angle between -pi/2 and +pi/2 whose tangent is x.
+//
+// Range reduction is from three intervals into the interval from zero to 0.66.
+// The approximant uses a rational function of degree 4/5 of the form
+// x + x**3 P(x)/Q(x).
+//
+// ACCURACY:
+//                      Relative error:
+// arithmetic   domain    # trials  peak     rms
+//    DEC       -10, 10   50000     2.4e-17  8.3e-18
+//    IEEE      -10, 10   10^6      1.8e-16  5.0e-17
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+
+// xatan evaluates a series valid in the range [0, 0.66].
+func xatan(x float64) float64 {
 	const (
-		P4 = .161536412982230228262e2
-		P3 = .26842548195503973794141e3
-		P2 = .11530293515404850115428136e4
-		P1 = .178040631643319697105464587e4
-		P0 = .89678597403663861959987488e3
-		Q4 = .5895697050844462222791e2
-		Q3 = .536265374031215315104235e3
-		Q2 = .16667838148816337184521798e4
-		Q1 = .207933497444540981287275926e4
-		Q0 = .89678597403663861962481162e3
+		P0 = -8.750608600031904122785e-01
+		P1 = -1.615753718733365076637e+01
+		P2 = -7.500855792314704667340e+01
+		P3 = -1.228866684490136173410e+02
+		P4 = -6.485021904942025371773e+01
+		Q0 = +2.485846490142306297962e+01
+		Q1 = +1.650270098316988542046e+02
+		Q2 = +4.328810604912902668951e+02
+		Q3 = +4.853903996359136964868e+02
+		Q4 = +1.945506571482613964425e+02
 	)
-	sq := arg * arg
-	value := ((((P4*sq+P3)*sq+P2)*sq+P1)*sq + P0)
-	value = value / (((((sq+Q4)*sq+Q3)*sq+Q2)*sq+Q1)*sq + Q0)
-	return value * arg
+	z := x * x
+	z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4)
+	z = x*z + x
+	return z
 }
 
 // satan reduces its argument (known to be positive)
-// to the range [0,0.414...] and calls xatan.
-func satan(arg float64) float64 {
-	if arg < Sqrt2-1 {
-		return xatan(arg)
+// to the range [0, 0.66] and calls xatan.
+func satan(x float64) float64 {
+	const (
+		Morebits = 6.123233995736765886130e-17 // pi/2 = PIO2 + Morebits
+		Tan3pio8 = 2.41421356237309504880      // tan(3*pi/8)
+	)
+	if x <= 0.66 {
+		return xatan(x)
 	}
-	if arg > Sqrt2+1 {
-		return Pi/2 - xatan(1/arg)
+	if x > Tan3pio8 {
+		return Pi/2 - xatan(1/x) + Morebits
 	}
-	return Pi/4 + xatan((arg-1)/(arg+1))
+	return Pi/4 + xatan((x-1)/(x+1)) + 0.5*Morebits
 }
 
 // Atan returns the arctangent of x.
 //
 // Special cases are:
-//	Atan(±0) = ±0
-//	Atan(±Inf) = ±Pi/2
+//      Atan(±0) = ±0
+//      Atan(±Inf) = ±Pi/2
 func Atan(x float64) float64
 
 func atan(x float64) float64 {
diff --git a/src/pkg/math/atanh.go b/src/pkg/math/atanh.go
index 5b5d468..113d5c1 100644
--- a/src/pkg/math/atanh.go
+++ b/src/pkg/math/atanh.go
@@ -36,7 +36,7 @@ package math
 //	atanh(+-1) is +-INF with signal.
 //
 
-// Atanh(x) calculates the inverse hyperbolic tangent of x.
+// Atanh returns the inverse hyperbolic tangent of x.
 //
 // Special cases are:
 //	Atanh(1) = +Inf
diff --git a/src/pkg/math/big/arith_386.s b/src/pkg/math/big/arith_386.s
index f1262c6..c624833 100644
--- a/src/pkg/math/big/arith_386.s
+++ b/src/pkg/math/big/arith_386.s
@@ -29,7 +29,7 @@ TEXT ·addVV(SB),7,$0
 	MOVL z+0(FP), DI
 	MOVL x+12(FP), SI
 	MOVL y+24(FP), CX
-	MOVL n+4(FP), BP
+	MOVL z+4(FP), BP
 	MOVL $0, BX		// i = 0
 	MOVL $0, DX		// c = 0
 	JMP E1
@@ -54,7 +54,7 @@ TEXT ·subVV(SB),7,$0
 	MOVL z+0(FP), DI
 	MOVL x+12(FP), SI
 	MOVL y+24(FP), CX
-	MOVL n+4(FP), BP
+	MOVL z+4(FP), BP
 	MOVL $0, BX		// i = 0
 	MOVL $0, DX		// c = 0
 	JMP E2
@@ -78,7 +78,7 @@ TEXT ·addVW(SB),7,$0
 	MOVL z+0(FP), DI
 	MOVL x+12(FP), SI
 	MOVL y+24(FP), AX	// c = y
-	MOVL n+4(FP), BP
+	MOVL z+4(FP), BP
 	MOVL $0, BX		// i = 0
 	JMP E3
 
@@ -100,7 +100,7 @@ TEXT ·subVW(SB),7,$0
 	MOVL z+0(FP), DI
 	MOVL x+12(FP), SI
 	MOVL y+24(FP), AX	// c = y
-	MOVL n+4(FP), BP
+	MOVL z+4(FP), BP
 	MOVL $0, BX		// i = 0
 	JMP E4
 
@@ -120,7 +120,7 @@ E4:	CMPL BX, BP		// i < n
 
 // func shlVU(z, x []Word, s uint) (c Word)
 TEXT ·shlVU(SB),7,$0
-	MOVL n+4(FP), BX	// i = n
+	MOVL z+4(FP), BX	// i = z
 	SUBL $1, BX		// i--
 	JL X8b			// i < 0	(n <= 0)
 
@@ -155,7 +155,7 @@ X8b:	MOVL $0, c+28(FP)
 
 // func shrVU(z, x []Word, s uint) (c Word)
 TEXT ·shrVU(SB),7,$0
-	MOVL n+4(FP), BP
+	MOVL z+4(FP), BP
 	SUBL $1, BP		// n--
 	JL X9b			// n < 0	(n <= 0)
 
@@ -196,7 +196,7 @@ TEXT ·mulAddVWW(SB),7,$0
 	MOVL x+12(FP), SI
 	MOVL y+24(FP), BP
 	MOVL r+28(FP), CX	// c = r
-	MOVL n+4(FP), BX
+	MOVL z+4(FP), BX
 	LEAL (DI)(BX*4), DI
 	LEAL (SI)(BX*4), SI
 	NEGL BX			// i = -n
@@ -222,7 +222,7 @@ TEXT ·addMulVVW(SB),7,$0
 	MOVL z+0(FP), DI
 	MOVL x+12(FP), SI
 	MOVL y+24(FP), BP
-	MOVL n+4(FP), BX
+	MOVL z+4(FP), BX
 	LEAL (DI)(BX*4), DI
 	LEAL (SI)(BX*4), SI
 	NEGL BX			// i = -n
@@ -251,7 +251,7 @@ TEXT ·divWVW(SB),7,$0
 	MOVL xn+12(FP), DX	// r = xn
 	MOVL x+16(FP), SI
 	MOVL y+28(FP), CX
-	MOVL n+4(FP), BX	// i = n
+	MOVL z+4(FP), BX	// i = z
 	JMP E7
 
 L7:	MOVL (SI)(BX*4), AX
diff --git a/src/pkg/math/big/arith_amd64.s b/src/pkg/math/big/arith_amd64.s
index 54f6473..d859645 100644
--- a/src/pkg/math/big/arith_amd64.s
+++ b/src/pkg/math/big/arith_amd64.s
@@ -5,7 +5,15 @@
 // This file provides fast assembly versions for the elementary
 // arithmetic operations on vectors implemented in arith.go.
 
-// TODO(gri) - experiment with unrolled loops for faster execution
+// Literal instruction for MOVQ $0, CX.
+// (MOVQ $0, reg is translated to XORQ reg, reg and clears CF.)
+#define ZERO_CX BYTE $0x48; \
+		BYTE $0xc7; \
+		BYTE $0xc1; \
+		BYTE $0x00; \
+		BYTE $0x00; \
+		BYTE $0x00; \
+		BYTE $0x00
 
 // func mulWW(x, y Word) (z1, z0 Word)
 TEXT ·mulWW(SB),7,$0
@@ -28,114 +36,231 @@ TEXT ·divWW(SB),7,$0
 
 // func addVV(z, x, y []Word) (c Word)
 TEXT ·addVV(SB),7,$0
+	MOVQ z+8(FP), DI
+	MOVQ x+24(FP), R8
+	MOVQ y+48(FP), R9
 	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), R9
-	MOVL n+8(FP), R11
-	MOVQ $0, BX		// i = 0
-	MOVQ $0, DX		// c = 0
-	JMP E1
-
-L1:	MOVQ (R8)(BX*8), AX
-	RCRQ $1, DX
-	ADCQ (R9)(BX*8), AX
-	RCLQ $1, DX
-	MOVQ AX, (R10)(BX*8)
-	ADDL $1, BX		// i++
 
-E1:	CMPQ BX, R11		// i < n
-	JL L1
-
-	MOVQ DX, c+48(FP)
+	MOVQ $0, CX		// c = 0
+	MOVQ $0, SI		// i = 0
+
+	// s/JL/JMP/ below to disable the unrolled loop
+	SUBQ $4, DI		// n -= 4
+	JL V1			// if n < 0 goto V1
+
+U1:	// n >= 0
+	// regular loop body unrolled 4x
+	RCRQ $1, CX		// CF = c
+	MOVQ 0(R8)(SI*8), R11
+	MOVQ 8(R8)(SI*8), R12
+	MOVQ 16(R8)(SI*8), R13
+	MOVQ 24(R8)(SI*8), R14
+	ADCQ 0(R9)(SI*8), R11
+	ADCQ 8(R9)(SI*8), R12
+	ADCQ 16(R9)(SI*8), R13
+	ADCQ 24(R9)(SI*8), R14
+	MOVQ R11, 0(R10)(SI*8)
+	MOVQ R12, 8(R10)(SI*8)
+	MOVQ R13, 16(R10)(SI*8)
+	MOVQ R14, 24(R10)(SI*8)
+	RCLQ $1, CX		// c = CF
+
+	ADDQ $4, SI		// i += 4
+	SUBQ $4, DI		// n -= 4
+	JGE U1			// if n >= 0 goto U1
+
+V1:	ADDQ $4, DI		// n += 4
+	JLE E1			// if n <= 0 goto E1
+
+L1:	// n > 0
+	RCRQ $1, CX		// CF = c
+	MOVQ 0(R8)(SI*8), R11
+	ADCQ 0(R9)(SI*8), R11
+	MOVQ R11, 0(R10)(SI*8)
+	RCLQ $1, CX		// c = CF
+
+	ADDQ $1, SI		// i++
+	SUBQ $1, DI		// n--
+	JG L1			// if n > 0 goto L1
+
+E1:	MOVQ CX, c+72(FP)	// return c
 	RET
 
 
 // func subVV(z, x, y []Word) (c Word)
-// (same as addVV_s except for SBBQ instead of ADCQ and label names)
+// (same as addVV except for SBBQ instead of ADCQ and label names)
 TEXT ·subVV(SB),7,$0
+	MOVQ z+8(FP), DI
+	MOVQ x+24(FP), R8
+	MOVQ y+48(FP), R9
 	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), R9
-	MOVL n+8(FP), R11
-	MOVQ $0, BX		// i = 0
-	MOVQ $0, DX		// c = 0
-	JMP E2
-
-L2:	MOVQ (R8)(BX*8), AX
-	RCRQ $1, DX
-	SBBQ (R9)(BX*8), AX
-	RCLQ $1, DX
-	MOVQ AX, (R10)(BX*8)
-	ADDL $1, BX		// i++
-
-E2:	CMPQ BX, R11		// i < n
-	JL L2
 
-	MOVQ DX, c+48(FP)
+	MOVQ $0, CX		// c = 0
+	MOVQ $0, SI		// i = 0
+
+	// s/JL/JMP/ below to disable the unrolled loop
+	SUBQ $4, DI		// n -= 4
+	JL V2			// if n < 0 goto V2
+
+U2:	// n >= 0
+	// regular loop body unrolled 4x
+	RCRQ $1, CX		// CF = c
+	MOVQ 0(R8)(SI*8), R11
+	MOVQ 8(R8)(SI*8), R12
+	MOVQ 16(R8)(SI*8), R13
+	MOVQ 24(R8)(SI*8), R14
+	SBBQ 0(R9)(SI*8), R11
+	SBBQ 8(R9)(SI*8), R12
+	SBBQ 16(R9)(SI*8), R13
+	SBBQ 24(R9)(SI*8), R14
+	MOVQ R11, 0(R10)(SI*8)
+	MOVQ R12, 8(R10)(SI*8)
+	MOVQ R13, 16(R10)(SI*8)
+	MOVQ R14, 24(R10)(SI*8)
+	RCLQ $1, CX		// c = CF
+
+	ADDQ $4, SI		// i += 4
+	SUBQ $4, DI		// n -= 4
+	JGE U2			// if n >= 0 goto U2
+
+V2:	ADDQ $4, DI		// n += 4
+	JLE E2			// if n <= 0 goto E2
+
+L2:	// n > 0
+	RCRQ $1, CX		// CF = c
+	MOVQ 0(R8)(SI*8), R11
+	SBBQ 0(R9)(SI*8), R11
+	MOVQ R11, 0(R10)(SI*8)
+	RCLQ $1, CX		// c = CF
+
+	ADDQ $1, SI		// i++
+	SUBQ $1, DI		// n--
+	JG L2			// if n > 0 goto L2
+
+E2:	MOVQ CX, c+72(FP)	// return c
 	RET
 
 
 // func addVW(z, x []Word, y Word) (c Word)
 TEXT ·addVW(SB),7,$0
+	MOVQ z+8(FP), DI
+	MOVQ x+24(FP), R8
+	MOVQ y+48(FP), CX	// c = y
 	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), AX	// c = y
-	MOVL n+8(FP), R11
-	MOVQ $0, BX		// i = 0
-	JMP E3
 
-L3:	ADDQ (R8)(BX*8), AX
-	MOVQ AX, (R10)(BX*8)
-	RCLQ $1, AX
-	ANDQ $1, AX
-	ADDL $1, BX		// i++
-
-E3:	CMPQ BX, R11		// i < n
-	JL L3
-
-	MOVQ AX, c+40(FP)
+	MOVQ $0, SI		// i = 0
+
+	// s/JL/JMP/ below to disable the unrolled loop
+	SUBQ $4, DI		// n -= 4
+	JL V3			// if n < 4 goto V3
+
+U3:	// n >= 0
+	// regular loop body unrolled 4x
+	MOVQ 0(R8)(SI*8), R11
+	MOVQ 8(R8)(SI*8), R12
+	MOVQ 16(R8)(SI*8), R13
+	MOVQ 24(R8)(SI*8), R14
+	ADDQ CX, R11
+	ZERO_CX
+	ADCQ $0, R12
+	ADCQ $0, R13
+	ADCQ $0, R14
+	SETCS CX		// c = CF
+	MOVQ R11, 0(R10)(SI*8)
+	MOVQ R12, 8(R10)(SI*8)
+	MOVQ R13, 16(R10)(SI*8)
+	MOVQ R14, 24(R10)(SI*8)
+
+	ADDQ $4, SI		// i += 4
+	SUBQ $4, DI		// n -= 4
+	JGE U3			// if n >= 0 goto U3
+
+V3:	ADDQ $4, DI		// n += 4
+	JLE E3			// if n <= 0 goto E3
+
+L3:	// n > 0
+	ADDQ 0(R8)(SI*8), CX
+	MOVQ CX, 0(R10)(SI*8)
+	ZERO_CX
+	RCLQ $1, CX		// c = CF
+
+	ADDQ $1, SI		// i++
+	SUBQ $1, DI		// n--
+	JG L3			// if n > 0 goto L3
+
+E3:	MOVQ CX, c+56(FP)	// return c
 	RET
 
 
 // func subVW(z, x []Word, y Word) (c Word)
+// (same as addVW except for SUBQ/SBBQ instead of ADDQ/ADCQ and label names)
 TEXT ·subVW(SB),7,$0
+	MOVQ z+8(FP), DI
+	MOVQ x+24(FP), R8
+	MOVQ y+48(FP), CX	// c = y
 	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), AX	// c = y
-	MOVL n+8(FP), R11
-	MOVQ $0, BX		// i = 0
-	JMP E4
-
-L4:	MOVQ (R8)(BX*8), DX	// TODO(gri) is there a reverse SUBQ?
-	SUBQ AX, DX
-	MOVQ DX, (R10)(BX*8)
-	RCLQ $1, AX
-	ANDQ $1, AX
-	ADDL $1, BX		// i++
-
-E4:	CMPQ BX, R11		// i < n
-	JL L4
-
-	MOVQ AX, c+40(FP)
+	
+	MOVQ $0, SI		// i = 0
+
+	// s/JL/JMP/ below to disable the unrolled loop
+	SUBQ $4, DI		// n -= 4
+	JL V4			// if n < 4 goto V4
+
+U4:	// n >= 0
+	// regular loop body unrolled 4x
+	MOVQ 0(R8)(SI*8), R11
+	MOVQ 8(R8)(SI*8), R12
+	MOVQ 16(R8)(SI*8), R13
+	MOVQ 24(R8)(SI*8), R14
+	SUBQ CX, R11
+	ZERO_CX
+	SBBQ $0, R12
+	SBBQ $0, R13
+	SBBQ $0, R14
+	SETCS CX		// c = CF
+	MOVQ R11, 0(R10)(SI*8)
+	MOVQ R12, 8(R10)(SI*8)
+	MOVQ R13, 16(R10)(SI*8)
+	MOVQ R14, 24(R10)(SI*8)
+
+	ADDQ $4, SI		// i += 4
+	SUBQ $4, DI		// n -= 4
+	JGE U4			// if n >= 0 goto U4
+
+V4:	ADDQ $4, DI		// n += 4
+	JLE E4			// if n <= 0 goto E4
+
+L4:	// n > 0
+	MOVQ 0(R8)(SI*8), R11
+	SUBQ CX, R11
+	MOVQ R11, 0(R10)(SI*8)
+	ZERO_CX
+	RCLQ $1, CX		// c = CF
+
+	ADDQ $1, SI		// i++
+	SUBQ $1, DI		// n--
+	JG L4			// if n > 0 goto L4
+
+E4:	MOVQ CX, c+56(FP)	// return c
 	RET
 
 
 // func shlVU(z, x []Word, s uint) (c Word)
 TEXT ·shlVU(SB),7,$0
-	MOVL n+8(FP), BX	// i = n
-	SUBL $1, BX		// i--
+	MOVQ z+8(FP), BX	// i = z
+	SUBQ $1, BX		// i--
 	JL X8b			// i < 0	(n <= 0)
 
 	// n > 0
 	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVL s+32(FP), CX
+	MOVQ x+24(FP), R8
+	MOVQ s+48(FP), CX
 	MOVQ (R8)(BX*8), AX	// w1 = x[n-1]
 	MOVQ $0, DX
 	SHLQ CX, DX:AX		// w1>>ŝ
-	MOVQ DX, c+40(FP)
+	MOVQ DX, c+56(FP)
 
-	CMPL BX, $0
+	CMPQ BX, $0
 	JLE X8a			// i <= 0
 
 	// i > 0
@@ -143,7 +268,7 @@ L8:	MOVQ AX, DX		// w = w1
 	MOVQ -8(R8)(BX*8), AX	// w1 = x[i-1]
 	SHLQ CX, DX:AX		// w<<s | w1>>ŝ
 	MOVQ DX, (R10)(BX*8)	// z[i] = w<<s | w1>>ŝ
-	SUBL $1, BX		// i--
+	SUBQ $1, BX		// i--
 	JG L8			// i > 0
 
 	// i <= 0
@@ -151,24 +276,24 @@ X8a:	SHLQ CX, AX		// w1<<s
 	MOVQ AX, (R10)		// z[0] = w1<<s
 	RET
 
-X8b:	MOVQ $0, c+40(FP)
+X8b:	MOVQ $0, c+56(FP)
 	RET
 
 
 // func shrVU(z, x []Word, s uint) (c Word)
 TEXT ·shrVU(SB),7,$0
-	MOVL n+8(FP), R11
-	SUBL $1, R11		// n--
+	MOVQ z+8(FP), R11
+	SUBQ $1, R11		// n--
 	JL X9b			// n < 0	(n <= 0)
 
 	// n > 0
 	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVL s+32(FP), CX
+	MOVQ x+24(FP), R8
+	MOVQ s+48(FP), CX
 	MOVQ (R8), AX		// w1 = x[0]
 	MOVQ $0, DX
 	SHRQ CX, DX:AX		// w1<<ŝ
-	MOVQ DX, c+40(FP)
+	MOVQ DX, c+56(FP)
 
 	MOVQ $0, BX		// i = 0
 	JMP E9
@@ -178,7 +303,7 @@ L9:	MOVQ AX, DX		// w = w1
 	MOVQ 8(R8)(BX*8), AX	// w1 = x[i+1]
 	SHRQ CX, DX:AX		// w>>s | w1<<ŝ
 	MOVQ DX, (R10)(BX*8)	// z[i] = w>>s | w1<<ŝ
-	ADDL $1, BX		// i++
+	ADDQ $1, BX		// i++
 	
 E9:	CMPQ BX, R11
 	JL L9			// i < n-1
@@ -188,17 +313,17 @@ X9a:	SHRQ CX, AX		// w1>>s
 	MOVQ AX, (R10)(R11*8)	// z[n-1] = w1>>s
 	RET
 
-X9b:	MOVQ $0, c+40(FP)
+X9b:	MOVQ $0, c+56(FP)
 	RET
 
 
 // func mulAddVWW(z, x []Word, y, r Word) (c Word)
 TEXT ·mulAddVWW(SB),7,$0
 	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), R9
-	MOVQ r+40(FP), CX	// c = r
-	MOVL n+8(FP), R11
+	MOVQ x+24(FP), R8
+	MOVQ y+48(FP), R9
+	MOVQ r+56(FP), CX	// c = r
+	MOVQ z+8(FP), R11
 	MOVQ $0, BX		// i = 0
 	JMP E5
 
@@ -208,21 +333,21 @@ L5:	MOVQ (R8)(BX*8), AX
 	ADCQ $0, DX
 	MOVQ AX, (R10)(BX*8)
 	MOVQ DX, CX
-	ADDL $1, BX		// i++
+	ADDQ $1, BX		// i++
 
 E5:	CMPQ BX, R11		// i < n
 	JL L5
 
-	MOVQ CX, c+48(FP)
+	MOVQ CX, c+64(FP)
 	RET
 
 
 // func addMulVVW(z, x []Word, y Word) (c Word)
 TEXT ·addMulVVW(SB),7,$0
 	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), R9
-	MOVL n+8(FP), R11
+	MOVQ x+24(FP), R8
+	MOVQ y+48(FP), R9
+	MOVQ z+8(FP), R11
 	MOVQ $0, BX		// i = 0
 	MOVQ $0, CX		// c = 0
 	JMP E6
@@ -234,41 +359,41 @@ L6:	MOVQ (R8)(BX*8), AX
 	ADDQ AX, (R10)(BX*8)
 	ADCQ $0, DX
 	MOVQ DX, CX
-	ADDL $1, BX		// i++
+	ADDQ $1, BX		// i++
 
 E6:	CMPQ BX, R11		// i < n
 	JL L6
 
-	MOVQ CX, c+40(FP)
+	MOVQ CX, c+56(FP)
 	RET
 
 
 // func divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
 TEXT ·divWVW(SB),7,$0
 	MOVQ z+0(FP), R10
-	MOVQ xn+16(FP), DX	// r = xn
-	MOVQ x+24(FP), R8
-	MOVQ y+40(FP), R9
-	MOVL n+8(FP), BX	// i = n
+	MOVQ xn+24(FP), DX	// r = xn
+	MOVQ x+32(FP), R8
+	MOVQ y+56(FP), R9
+	MOVQ z+8(FP), BX	// i = z
 	JMP E7
 
 L7:	MOVQ (R8)(BX*8), AX
 	DIVQ R9
 	MOVQ AX, (R10)(BX*8)
 
-E7:	SUBL $1, BX		// i--
+E7:	SUBQ $1, BX		// i--
 	JGE L7			// i >= 0
 
-	MOVQ DX, r+48(FP)
+	MOVQ DX, r+64(FP)
 	RET
 
 // func bitLen(x Word) (n int)
 TEXT ·bitLen(SB),7,$0
 	BSRQ x+0(FP), AX
 	JZ Z1
-	INCL AX
-	MOVL AX, n+8(FP)
+	ADDQ $1, AX
+	MOVQ AX, n+8(FP)
 	RET
 
-Z1:	MOVL $0, n+8(FP)
+Z1:	MOVQ $0, n+8(FP)
 	RET
diff --git a/src/pkg/math/big/arith_arm.s b/src/pkg/math/big/arith_arm.s
index dbf3360..64610f9 100644
--- a/src/pkg/math/big/arith_arm.s
+++ b/src/pkg/math/big/arith_arm.s
@@ -13,7 +13,7 @@ TEXT ·addVV(SB),7,$0
 	MOVW	z+0(FP), R1
 	MOVW	x+12(FP), R2
 	MOVW	y+24(FP), R3
-	MOVW	n+4(FP), R4
+	MOVW	z+4(FP), R4
 	MOVW	R4<<2, R4
 	ADD	R1, R4
 	B E1
@@ -41,7 +41,7 @@ TEXT ·subVV(SB),7,$0
 	MOVW	z+0(FP), R1
 	MOVW	x+12(FP), R2
 	MOVW	y+24(FP), R3
-	MOVW	n+4(FP), R4
+	MOVW	z+4(FP), R4
 	MOVW	R4<<2, R4
 	ADD	R1, R4
 	B E2
@@ -68,7 +68,7 @@ TEXT ·addVW(SB),7,$0
 	MOVW	z+0(FP), R1
 	MOVW	x+12(FP), R2
 	MOVW	y+24(FP), R3
-	MOVW	n+4(FP), R4
+	MOVW	z+4(FP), R4
 	MOVW	R4<<2, R4
 	ADD	R1, R4
 	CMP	R1, R4
@@ -102,7 +102,7 @@ TEXT ·subVW(SB),7,$0
 	MOVW	z+0(FP), R1
 	MOVW	x+12(FP), R2
 	MOVW	y+24(FP), R3
-	MOVW	n+4(FP), R4
+	MOVW	z+4(FP), R4
 	MOVW	R4<<2, R4
 	ADD	R1, R4
 	CMP	R1, R4
@@ -134,7 +134,7 @@ E4:
 
 // func shlVU(z, x []Word, s uint) (c Word)
 TEXT ·shlVU(SB),7,$0
-	MOVW	n+4(FP), R5
+	MOVW	z+4(FP), R5
 	CMP	$0, R5
 	BEQ	X7
 	
@@ -183,7 +183,7 @@ X7:
 
 // func shrVU(z, x []Word, s uint) (c Word)
 TEXT ·shrVU(SB),7,$0
-	MOVW	n+4(FP), R5
+	MOVW	z+4(FP), R5
 	CMP	$0, R5
 	BEQ	X6
 
@@ -238,7 +238,7 @@ TEXT ·mulAddVWW(SB),7,$0
 	MOVW	x+12(FP), R2
 	MOVW	y+24(FP), R3
 	MOVW	r+28(FP), R4
-	MOVW	n+4(FP), R5
+	MOVW	z+4(FP), R5
 	MOVW	R5<<2, R5
 	ADD	R1, R5
 	B E8
@@ -265,7 +265,7 @@ TEXT ·addMulVVW(SB),7,$0
 	MOVW	z+0(FP), R1
 	MOVW	x+12(FP), R2
 	MOVW	y+24(FP), R3
-	MOVW	n+4(FP), R5
+	MOVW	z+4(FP), R5
 	MOVW	R5<<2, R5
 	ADD	R1, R5
 	MOVW	$0, R4
@@ -314,7 +314,7 @@ TEXT ·mulWW(SB),7,$0
 // func bitLen(x Word) (n int)
 TEXT ·bitLen(SB),7,$0
 	MOVW	x+0(FP), R0
-	WORD	$0xe16f0f10 // CLZ R0, R0  (count leading zeros)
+	CLZ 	R0, R0
 	MOVW	$32, R1
 	SUB.S	R0, R1
 	MOVW	R1, n+4(FP)
diff --git a/src/pkg/math/big/arith_test.go b/src/pkg/math/big/arith_test.go
index c7e3d28..3615a65 100644
--- a/src/pkg/math/big/arith_test.go
+++ b/src/pkg/math/big/arith_test.go
@@ -4,7 +4,10 @@
 
 package big
 
-import "testing"
+import (
+	"math/rand"
+	"testing"
+)
 
 type funWW func(x, y, c Word) (z1, z0 Word)
 type argWW struct {
@@ -100,6 +103,43 @@ func TestFunVV(t *testing.T) {
 	}
 }
 
+// Always the same seed for reproducible results.
+var rnd = rand.New(rand.NewSource(0))
+
+func rndW() Word {
+	return Word(rnd.Int63()<<1 | rnd.Int63n(2))
+}
+
+func rndV(n int) []Word {
+	v := make([]Word, n)
+	for i := range v {
+		v[i] = rndW()
+	}
+	return v
+}
+
+func benchmarkFunVV(b *testing.B, f funVV, n int) {
+	x := rndV(n)
+	y := rndV(n)
+	z := make([]Word, n)
+	b.SetBytes(int64(n * _W))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		f(z, x, y)
+	}
+}
+
+func BenchmarkAddVV_1(b *testing.B)   { benchmarkFunVV(b, addVV, 1) }
+func BenchmarkAddVV_2(b *testing.B)   { benchmarkFunVV(b, addVV, 2) }
+func BenchmarkAddVV_3(b *testing.B)   { benchmarkFunVV(b, addVV, 3) }
+func BenchmarkAddVV_4(b *testing.B)   { benchmarkFunVV(b, addVV, 4) }
+func BenchmarkAddVV_5(b *testing.B)   { benchmarkFunVV(b, addVV, 5) }
+func BenchmarkAddVV_1e1(b *testing.B) { benchmarkFunVV(b, addVV, 1e1) }
+func BenchmarkAddVV_1e2(b *testing.B) { benchmarkFunVV(b, addVV, 1e2) }
+func BenchmarkAddVV_1e3(b *testing.B) { benchmarkFunVV(b, addVV, 1e3) }
+func BenchmarkAddVV_1e4(b *testing.B) { benchmarkFunVV(b, addVV, 1e4) }
+func BenchmarkAddVV_1e5(b *testing.B) { benchmarkFunVV(b, addVV, 1e5) }
+
 type funVW func(z, x []Word, y Word) (c Word)
 type argVW struct {
 	z, x nat
@@ -210,6 +250,28 @@ func TestFunVW(t *testing.T) {
 	}
 }
 
+func benchmarkFunVW(b *testing.B, f funVW, n int) {
+	x := rndV(n)
+	y := rndW()
+	z := make([]Word, n)
+	b.SetBytes(int64(n * _W))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		f(z, x, y)
+	}
+}
+
+func BenchmarkAddVW_1(b *testing.B)   { benchmarkFunVW(b, addVW, 1) }
+func BenchmarkAddVW_2(b *testing.B)   { benchmarkFunVW(b, addVW, 2) }
+func BenchmarkAddVW_3(b *testing.B)   { benchmarkFunVW(b, addVW, 3) }
+func BenchmarkAddVW_4(b *testing.B)   { benchmarkFunVW(b, addVW, 4) }
+func BenchmarkAddVW_5(b *testing.B)   { benchmarkFunVW(b, addVW, 5) }
+func BenchmarkAddVW_1e1(b *testing.B) { benchmarkFunVW(b, addVW, 1e1) }
+func BenchmarkAddVW_1e2(b *testing.B) { benchmarkFunVW(b, addVW, 1e2) }
+func BenchmarkAddVW_1e3(b *testing.B) { benchmarkFunVW(b, addVW, 1e3) }
+func BenchmarkAddVW_1e4(b *testing.B) { benchmarkFunVW(b, addVW, 1e4) }
+func BenchmarkAddVW_1e5(b *testing.B) { benchmarkFunVW(b, addVW, 1e5) }
+
 type funVWW func(z, x []Word, y, r Word) (c Word)
 type argVWW struct {
 	z, x nat
@@ -334,6 +396,28 @@ func TestMulAddWWW(t *testing.T) {
 	}
 }
 
+func benchmarkAddMulVVW(b *testing.B, n int) {
+	x := rndV(n)
+	y := rndW()
+	z := make([]Word, n)
+	b.SetBytes(int64(n * _W))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		addMulVVW(z, x, y)
+	}
+}
+
+func BenchmarkAddMulVVW_1(b *testing.B)   { benchmarkAddMulVVW(b, 1) }
+func BenchmarkAddMulVVW_2(b *testing.B)   { benchmarkAddMulVVW(b, 2) }
+func BenchmarkAddMulVVW_3(b *testing.B)   { benchmarkAddMulVVW(b, 3) }
+func BenchmarkAddMulVVW_4(b *testing.B)   { benchmarkAddMulVVW(b, 4) }
+func BenchmarkAddMulVVW_5(b *testing.B)   { benchmarkAddMulVVW(b, 5) }
+func BenchmarkAddMulVVW_1e1(b *testing.B) { benchmarkAddMulVVW(b, 1e1) }
+func BenchmarkAddMulVVW_1e2(b *testing.B) { benchmarkAddMulVVW(b, 1e2) }
+func BenchmarkAddMulVVW_1e3(b *testing.B) { benchmarkAddMulVVW(b, 1e3) }
+func BenchmarkAddMulVVW_1e4(b *testing.B) { benchmarkAddMulVVW(b, 1e4) }
+func BenchmarkAddMulVVW_1e5(b *testing.B) { benchmarkAddMulVVW(b, 1e5) }
+
 func testWordBitLen(t *testing.T, fname string, f func(Word) int) {
 	for i := 0; i <= _W; i++ {
 		x := Word(1) << uint(i-1) // i == 0 => x == 0
diff --git a/src/pkg/math/big/calibrate_test.go b/src/pkg/math/big/calibrate_test.go
index efe1837..f69ffbf 100644
--- a/src/pkg/math/big/calibrate_test.go
+++ b/src/pkg/math/big/calibrate_test.go
@@ -21,15 +21,17 @@ import (
 
 var calibrate = flag.Bool("calibrate", false, "run calibration test")
 
-// measure returns the time to run f
-func measure(f func()) time.Duration {
-	const N = 100
-	start := time.Now()
-	for i := N; i > 0; i-- {
-		f()
-	}
-	stop := time.Now()
-	return stop.Sub(start) / N
+func karatsubaLoad(b *testing.B) {
+	BenchmarkMul(b)
+}
+
+// measureKaratsuba returns the time to run a Karatsuba-relevant benchmark
+// given Karatsuba threshold th.
+func measureKaratsuba(th int) time.Duration {
+	th, karatsubaThreshold = karatsubaThreshold, th
+	res := testing.Benchmark(karatsubaLoad)
+	karatsubaThreshold = th
+	return time.Duration(res.NsPerOp())
 }
 
 func computeThresholds() {
@@ -37,35 +39,33 @@ func computeThresholds() {
 	fmt.Printf("(run repeatedly for good results)\n")
 
 	// determine Tk, the work load execution time using basic multiplication
-	karatsubaThreshold = 1e9 // disable karatsuba
-	Tb := measure(benchmarkMulLoad)
-	fmt.Printf("Tb = %dns\n", Tb)
+	Tb := measureKaratsuba(1e9) // th == 1e9 => Karatsuba multiplication disabled
+	fmt.Printf("Tb = %10s\n", Tb)
 
 	// thresholds
-	n := 8 // any lower values for the threshold lead to very slow multiplies
+	th := 4
 	th1 := -1
 	th2 := -1
 
 	var deltaOld time.Duration
-	for count := -1; count != 0; count-- {
+	for count := -1; count != 0 && th < 128; count-- {
 		// determine Tk, the work load execution time using Karatsuba multiplication
-		karatsubaThreshold = n // enable karatsuba
-		Tk := measure(benchmarkMulLoad)
+		Tk := measureKaratsuba(th)
 
 		// improvement over Tb
 		delta := (Tb - Tk) * 100 / Tb
 
-		fmt.Printf("n = %3d  Tk = %8dns  %4d%%", n, Tk, delta)
+		fmt.Printf("th = %3d  Tk = %10s  %4d%%", th, Tk, delta)
 
 		// determine break-even point
 		if Tk < Tb && th1 < 0 {
-			th1 = n
+			th1 = th
 			fmt.Print("  break-even point")
 		}
 
 		// determine diminishing return
 		if 0 < delta && delta < deltaOld && th2 < 0 {
-			th2 = n
+			th2 = th
 			fmt.Print("  diminishing return")
 		}
 		deltaOld = delta
@@ -74,10 +74,10 @@ func computeThresholds() {
 
 		// trigger counter
 		if th1 >= 0 && th2 >= 0 && count < 0 {
-			count = 20 // this many extra measurements after we got both thresholds
+			count = 10 // this many extra measurements after we got both thresholds
 		}
 
-		n++
+		th++
 	}
 }
 
diff --git a/src/pkg/math/big/gcd_test.go b/src/pkg/math/big/gcd_test.go
new file mode 100644
index 0000000..c0b9f58
--- /dev/null
+++ b/src/pkg/math/big/gcd_test.go
@@ -0,0 +1,47 @@
+// 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.
+
+// This file implements a GCD benchmark.
+// Usage: go test math/big -test.bench GCD
+
+package big
+
+import (
+	"math/rand"
+	"testing"
+)
+
+// randInt returns a pseudo-random Int in the range [1<<(size-1), (1<<size) - 1]
+func randInt(r *rand.Rand, size uint) *Int {
+	n := new(Int).Lsh(intOne, size-1)
+	x := new(Int).Rand(r, n)
+	return x.Add(x, n) // make sure result > 1<<(size-1)
+}
+
+func runGCD(b *testing.B, aSize, bSize uint) {
+	b.StopTimer()
+	var r = rand.New(rand.NewSource(1234))
+	aa := randInt(r, aSize)
+	bb := randInt(r, bSize)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		new(Int).GCD(nil, nil, aa, bb)
+	}
+}
+
+func BenchmarkGCD10x10(b *testing.B)         { runGCD(b, 10, 10) }
+func BenchmarkGCD10x100(b *testing.B)        { runGCD(b, 10, 100) }
+func BenchmarkGCD10x1000(b *testing.B)       { runGCD(b, 10, 1000) }
+func BenchmarkGCD10x10000(b *testing.B)      { runGCD(b, 10, 10000) }
+func BenchmarkGCD10x100000(b *testing.B)     { runGCD(b, 10, 100000) }
+func BenchmarkGCD100x100(b *testing.B)       { runGCD(b, 100, 100) }
+func BenchmarkGCD100x1000(b *testing.B)      { runGCD(b, 100, 1000) }
+func BenchmarkGCD100x10000(b *testing.B)     { runGCD(b, 100, 10000) }
+func BenchmarkGCD100x100000(b *testing.B)    { runGCD(b, 100, 100000) }
+func BenchmarkGCD1000x1000(b *testing.B)     { runGCD(b, 1000, 1000) }
+func BenchmarkGCD1000x10000(b *testing.B)    { runGCD(b, 1000, 10000) }
+func BenchmarkGCD1000x100000(b *testing.B)   { runGCD(b, 1000, 100000) }
+func BenchmarkGCD10000x10000(b *testing.B)   { runGCD(b, 10000, 10000) }
+func BenchmarkGCD10000x100000(b *testing.B)  { runGCD(b, 10000, 100000) }
+func BenchmarkGCD100000x100000(b *testing.B) { runGCD(b, 100000, 100000) }
diff --git a/src/pkg/math/big/int.go b/src/pkg/math/big/int.go
index cd2cd0e..bf2fd20 100644
--- a/src/pkg/math/big/int.go
+++ b/src/pkg/math/big/int.go
@@ -51,6 +51,13 @@ func (z *Int) SetInt64(x int64) *Int {
 	return z
 }
 
+// SetUint64 sets z to x and returns z.
+func (z *Int) SetUint64(x uint64) *Int {
+	z.abs = z.abs.setUint64(uint64(x))
+	z.neg = false
+	return z
+}
+
 // NewInt allocates and returns a new Int set to x.
 func NewInt(x int64) *Int {
 	return new(Int).SetInt64(x)
@@ -412,7 +419,7 @@ func (x *Int) Format(s fmt.State, ch rune) {
 	if precisionSet {
 		switch {
 		case len(digits) < precision:
-			zeroes = precision - len(digits) // count of zero padding 
+			zeroes = precision - len(digits) // count of zero padding
 		case digits == "0" && precision == 0:
 			return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
 		}
@@ -519,6 +526,19 @@ func (x *Int) Int64() int64 {
 	return v
 }
 
+// Uint64 returns the uint64 representation of x.
+// If x cannot be represented in an 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
+}
+
 // SetString sets z to the value of s, interpreted in the given base,
 // and returns z and a boolean indicating success. If SetString fails,
 // the value of z is undefined but the returned value is nil.
@@ -561,19 +581,18 @@ func (x *Int) BitLen() int {
 	return x.abs.bitLen()
 }
 
-// Exp sets z = x**y mod m and returns z. If m is nil, z = x**y.
+// Exp sets z = x**y mod |m| (i.e. the sign of m is ignored), and returns z.
+// If y <= 0, the result is 1; if m == nil or m == 0, z = x**y.
 // See Knuth, volume 2, section 4.6.3.
 func (z *Int) Exp(x, y, m *Int) *Int {
 	if y.neg || len(y.abs) == 0 {
-		neg := x.neg
-		z.SetInt64(1)
-		z.neg = neg
-		return z
+		return z.SetInt64(1)
 	}
+	// y > 0
 
 	var mWords nat
 	if m != nil {
-		mWords = m.abs
+		mWords = m.abs // m.abs may be nil for m == 0
 	}
 
 	z.abs = z.abs.expNN(x.abs, y.abs, mWords)
@@ -581,12 +600,12 @@ func (z *Int) Exp(x, y, m *Int) *Int {
 	return z
 }
 
-// GCD sets z to the greatest common divisor of a and b, which must be
-// positive numbers, and returns z.
+// GCD sets z to the greatest common divisor of a and b, which both must
+// be > 0, and returns z.
 // If x and y are not nil, GCD sets x and y such that z = a*x + b*y.
-// If either a or b is not positive, GCD sets z = x = y = 0.
+// If either a or b is <= 0, GCD sets z = x = y = 0.
 func (z *Int) GCD(x, y, a, b *Int) *Int {
-	if a.neg || b.neg {
+	if a.Sign() <= 0 || b.Sign() <= 0 {
 		z.SetInt64(0)
 		if x != nil {
 			x.SetInt64(0)
@@ -596,6 +615,9 @@ func (z *Int) GCD(x, y, a, b *Int) *Int {
 		}
 		return z
 	}
+	if x == nil && y == nil {
+		return z.binaryGCD(a, b)
+	}
 
 	A := new(Int).Set(a)
 	B := new(Int).Set(b)
@@ -640,6 +662,63 @@ func (z *Int) GCD(x, y, a, b *Int) *Int {
 	return z
 }
 
+// binaryGCD sets z to the greatest common divisor of a and b, which both must
+// be > 0, and returns z.
+// See Knuth, The Art of Computer Programming, Vol. 2, Section 4.5.2, Algorithm B.
+func (z *Int) binaryGCD(a, b *Int) *Int {
+	u := z
+	v := new(Int)
+
+	// use one Euclidean iteration to ensure that u and v are approx. the same size
+	switch {
+	case len(a.abs) > len(b.abs):
+		u.Set(b)
+		v.Rem(a, b)
+	case len(a.abs) < len(b.abs):
+		u.Set(a)
+		v.Rem(b, a)
+	default:
+		u.Set(a)
+		v.Set(b)
+	}
+
+	// v might be 0 now
+	if len(v.abs) == 0 {
+		return u
+	}
+	// u > 0 && v > 0
+
+	// determine largest k such that u = u' << k, v = v' << k
+	k := u.abs.trailingZeroBits()
+	if vk := v.abs.trailingZeroBits(); vk < k {
+		k = vk
+	}
+	u.Rsh(u, k)
+	v.Rsh(v, k)
+
+	// determine t (we know that u > 0)
+	t := new(Int)
+	if u.abs[0]&1 != 0 {
+		// u is odd
+		t.Neg(v)
+	} else {
+		t.Set(u)
+	}
+
+	for len(t.abs) > 0 {
+		// reduce t
+		t.Rsh(t, t.abs.trailingZeroBits())
+		if t.neg {
+			v.Neg(t)
+		} else {
+			u.Set(t)
+		}
+		t.Sub(u, v)
+	}
+
+	return u.Lsh(u, k)
+}
+
 // ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
 // If it returns true, x is prime with probability 1 - 1/4^n.
 // If it returns false, x is not prime.
@@ -697,6 +776,13 @@ func (z *Int) Rsh(x *Int, n uint) *Int {
 // Bit returns the value of the i'th bit of x. That is, it
 // returns (x>>i)&1. The bit index i must be >= 0.
 func (x *Int) Bit(i int) uint {
+	if i == 0 {
+		// optimization for common case: odd/even test of x
+		if len(x.abs) > 0 {
+			return uint(x.abs[0] & 1) // bit 0 is same for -x
+		}
+		return 0
+	}
 	if i < 0 {
 		panic("negative bit index")
 	}
@@ -894,3 +980,19 @@ func (z *Int) GobDecode(buf []byte) error {
 	z.abs = z.abs.setBytes(buf[1:])
 	return nil
 }
+
+// MarshalJSON implements the json.Marshaler interface.
+func (x *Int) MarshalJSON() ([]byte, error) {
+	// TODO(gri): get rid of the []byte/string conversions
+	return []byte(x.String()), nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (z *Int) UnmarshalJSON(x []byte) error {
+	// TODO(gri): get rid of the []byte/string conversions
+	_, ok := z.SetString(string(x), 0)
+	if !ok {
+		return fmt.Errorf("math/big: cannot unmarshal %s into a *big.Int", x)
+	}
+	return nil
+}
diff --git a/src/pkg/math/big/int_test.go b/src/pkg/math/big/int_test.go
index 9700a9b..6c981e7 100644
--- a/src/pkg/math/big/int_test.go
+++ b/src/pkg/math/big/int_test.go
@@ -8,6 +8,7 @@ import (
 	"bytes"
 	"encoding/gob"
 	"encoding/hex"
+	"encoding/json"
 	"fmt"
 	"math/rand"
 	"testing"
@@ -642,7 +643,7 @@ func TestSetBytes(t *testing.T) {
 
 func checkBytes(b []byte) bool {
 	b2 := new(Int).SetBytes(b).Bytes()
-	return bytes.Compare(b, b2) == 0
+	return bytes.Equal(b, b2)
 }
 
 func TestBytes(t *testing.T) {
@@ -766,8 +767,10 @@ var expTests = []struct {
 	x, y, m string
 	out     string
 }{
+	{"5", "-7", "", "1"},
+	{"-5", "-7", "", "1"},
 	{"5", "0", "", "1"},
-	{"-5", "0", "", "-1"},
+	{"-5", "0", "", "1"},
 	{"5", "1", "", "5"},
 	{"-5", "1", "", "-5"},
 	{"-2", "3", "2", "0"},
@@ -778,6 +781,7 @@ var expTests = []struct {
 	{"0x8000000000000000", "3", "6719", "5447"},
 	{"0x8000000000000000", "1000", "6719", "1603"},
 	{"0x8000000000000000", "1000000", "6719", "3199"},
+	{"0x8000000000000000", "-1000000", "6719", "1"},
 	{
 		"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
 		"298472983472983471903246121093472394872319615612417471234712061",
@@ -806,25 +810,33 @@ func TestExp(t *testing.T) {
 			continue
 		}
 
-		z := y.Exp(x, y, m)
-		if !isNormalized(z) {
-			t.Errorf("#%d: %v is not normalized", i, *z)
+		z1 := new(Int).Exp(x, y, m)
+		if !isNormalized(z1) {
+			t.Errorf("#%d: %v is not normalized", i, *z1)
 		}
-		if z.Cmp(out) != 0 {
-			t.Errorf("#%d: got %s want %s", i, z, out)
+		if z1.Cmp(out) != 0 {
+			t.Errorf("#%d: got %s want %s", i, z1, out)
+		}
+
+		if m == nil {
+			// 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)
+			}
 		}
 	}
 }
 
 func checkGcd(aBytes, bBytes []byte) bool {
-	a := new(Int).SetBytes(aBytes)
-	b := new(Int).SetBytes(bBytes)
-
 	x := new(Int)
 	y := new(Int)
-	d := new(Int)
+	a := new(Int).SetBytes(aBytes)
+	b := new(Int).SetBytes(bBytes)
 
-	d.GCD(x, y, a, b)
+	d := new(Int).GCD(x, y, a, b)
 	x.Mul(x, a)
 	y.Mul(y, b)
 	x.Add(x, y)
@@ -833,32 +845,70 @@ func checkGcd(aBytes, bBytes []byte) bool {
 }
 
 var gcdTests = []struct {
-	a, b    int64
-	d, x, y int64
+	d, x, y, a, b string
 }{
-	{120, 23, 1, -9, 47},
-}
-
-func TestGcd(t *testing.T) {
-	for i, test := range gcdTests {
-		a := NewInt(test.a)
-		b := NewInt(test.b)
+	// a <= 0 || b <= 0
+	{"0", "0", "0", "0", "0"},
+	{"0", "0", "0", "0", "7"},
+	{"0", "0", "0", "11", "0"},
+	{"0", "0", "0", "-77", "35"},
+	{"0", "0", "0", "64515", "-24310"},
+	{"0", "0", "0", "-64515", "-24310"},
+
+	{"1", "-9", "47", "120", "23"},
+	{"7", "1", "-2", "77", "35"},
+	{"935", "-3", "8", "64515", "24310"},
+	{"935000000000000000", "-3", "8", "64515000000000000000", "24310000000000000000"},
+	{"1", "-221", "22059940471369027483332068679400581064239780177629666810348940098015901108344", "98920366548084643601728869055592650835572950932266967461790948584315647051443", "991"},
+
+	// test early exit (after one Euclidean iteration) in binaryGCD
+	{"1", "", "", "1", "98920366548084643601728869055592650835572950932266967461790948584315647051443"},
+}
+
+func testGcd(t *testing.T, d, x, y, a, b *Int) {
+	var X *Int
+	if x != nil {
+		X = new(Int)
+	}
+	var Y *Int
+	if y != nil {
+		Y = new(Int)
+	}
 
-		x := new(Int)
-		y := new(Int)
-		d := new(Int)
+	D := new(Int).GCD(X, Y, a, b)
+	if D.Cmp(d) != 0 {
+		t.Errorf("GCD(%s, %s): got d = %s, want %s", a, b, D, d)
+	}
+	if x != nil && X.Cmp(x) != 0 {
+		t.Errorf("GCD(%s, %s): got x = %s, want %s", a, b, X, x)
+	}
+	if y != nil && Y.Cmp(y) != 0 {
+		t.Errorf("GCD(%s, %s): got y = %s, want %s", a, b, Y, y)
+	}
 
-		expectedX := NewInt(test.x)
-		expectedY := NewInt(test.y)
-		expectedD := NewInt(test.d)
+	// binaryGCD requires a > 0 && b > 0
+	if a.Sign() <= 0 || b.Sign() <= 0 {
+		return
+	}
 
-		d.GCD(x, y, a, b)
+	D.binaryGCD(a, b)
+	if D.Cmp(d) != 0 {
+		t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, D, d)
+	}
+}
 
-		if expectedX.Cmp(x) != 0 ||
-			expectedY.Cmp(y) != 0 ||
-			expectedD.Cmp(d) != 0 {
-			t.Errorf("#%d got (%s %s %s) want (%s %s %s)", i, x, y, d, expectedX, expectedY, expectedD)
-		}
+func TestGcd(t *testing.T) {
+	for _, test := range gcdTests {
+		d, _ := new(Int).SetString(test.d, 0)
+		x, _ := new(Int).SetString(test.x, 0)
+		y, _ := new(Int).SetString(test.y, 0)
+		a, _ := new(Int).SetString(test.a, 0)
+		b, _ := new(Int).SetString(test.b, 0)
+
+		testGcd(t, d, nil, nil, a, b)
+		testGcd(t, d, x, nil, a, b)
+		testGcd(t, d, nil, y, a, b)
+		testGcd(t, d, x, y, a, b)
 	}
 
 	quick.Check(checkGcd, nil)
@@ -1085,6 +1135,36 @@ func TestInt64(t *testing.T) {
 	}
 }
 
+var uint64Tests = []uint64{
+	0,
+	1,
+	4294967295,
+	4294967296,
+	8589934591,
+	8589934592,
+	9223372036854775807,
+	9223372036854775808,
+	18446744073709551615, // 1<<64 - 1
+}
+
+func TestUint64(t *testing.T) {
+	in := new(Int)
+	for i, testVal := range uint64Tests {
+		in.SetUint64(testVal)
+		out := in.Uint64()
+
+		if out != testVal {
+			t.Errorf("#%d got %d want %d", i, out, testVal)
+		}
+
+		str := fmt.Sprint(testVal)
+		strOut := in.String()
+		if strOut != str {
+			t.Errorf("#%d.String got %s want %s", i, strOut, str)
+		}
+	}
+}
+
 var bitwiseTests = []struct {
 	x, y                 string
 	and, or, xor, andNot string
@@ -1368,8 +1448,12 @@ func TestModInverse(t *testing.T) {
 	}
 }
 
-// used by TestIntGobEncoding and TestRatGobEncoding
-var gobEncodingTests = []string{
+var encodingTests = []string{
+	"-539345864568634858364538753846587364875430589374589",
+	"-678645873",
+	"-100",
+	"-2",
+	"-1",
 	"0",
 	"1",
 	"2",
@@ -1383,26 +1467,37 @@ func TestIntGobEncoding(t *testing.T) {
 	var medium bytes.Buffer
 	enc := gob.NewEncoder(&medium)
 	dec := gob.NewDecoder(&medium)
-	for i, test := range gobEncodingTests {
-		for j := 0; j < 2; j++ {
-			medium.Reset() // empty buffer for each test case (in case of failures)
-			stest := test
-			if j != 0 {
-				// negative numbers
-				stest = "-" + test
-			}
-			var tx Int
-			tx.SetString(stest, 10)
-			if err := enc.Encode(&tx); err != nil {
-				t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
-			}
-			var rx Int
-			if err := dec.Decode(&rx); err != nil {
-				t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
-			}
-			if rx.Cmp(&tx) != 0 {
-				t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
-			}
+	for _, test := range encodingTests {
+		medium.Reset() // empty buffer for each test case (in case of failures)
+		var tx Int
+		tx.SetString(test, 10)
+		if err := enc.Encode(&tx); err != nil {
+			t.Errorf("encoding of %s failed: %s", &tx, err)
+		}
+		var rx Int
+		if err := dec.Decode(&rx); err != nil {
+			t.Errorf("decoding of %s failed: %s", &tx, err)
+		}
+		if rx.Cmp(&tx) != 0 {
+			t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
+		}
+	}
+}
+
+func TestIntJSONEncoding(t *testing.T) {
+	for _, test := range encodingTests {
+		var tx Int
+		tx.SetString(test, 10)
+		b, err := json.Marshal(&tx)
+		if err != nil {
+			t.Errorf("marshaling of %s failed: %s", &tx, err)
+		}
+		var rx Int
+		if err := json.Unmarshal(b, &rx); err != nil {
+			t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+		}
+		if rx.Cmp(&tx) != 0 {
+			t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
 		}
 	}
 }
diff --git a/src/pkg/math/big/nat.go b/src/pkg/math/big/nat.go
index eaa6ff0..9d09f97 100644
--- a/src/pkg/math/big/nat.go
+++ b/src/pkg/math/big/nat.go
@@ -236,7 +236,7 @@ func karatsubaSub(z, x nat, n int) {
 // Operands that are shorter than karatsubaThreshold are multiplied using
 // "grade school" multiplication; for longer operands the Karatsuba algorithm
 // is used.
-var karatsubaThreshold int = 32 // computed by calibrate.go
+var karatsubaThreshold int = 40 // computed by calibrate.go
 
 // karatsuba multiplies x and y and leaves the result in z.
 // Both x and y must have the same length n and n must be a
@@ -342,7 +342,7 @@ func alias(x, y nat) bool {
 	return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
 }
 
-// addAt implements z += x*(1<<(_W*i)); z must be long enough.
+// addAt implements z += x<<(_W*i); z must be long enough.
 // (we don't use nat.add because we need z to stay the same
 // slice, and we don't need to normalize z after each addition)
 func addAt(z, x nat, i int) {
@@ -396,7 +396,7 @@ func (z nat) mul(x, y nat) nat {
 	}
 
 	// use basic multiplication if the numbers are small
-	if n < karatsubaThreshold || n < 2 {
+	if n < karatsubaThreshold {
 		z = z.make(m + n)
 		basicMul(z, x, y)
 		return z.norm()
@@ -405,8 +405,8 @@ func (z nat) mul(x, y nat) nat {
 
 	// determine Karatsuba length k such that
 	//
-	//   x = x1*b + x0
-	//   y = y1*b + y0  (and k <= len(y), which implies k <= len(x))
+	//   x = xh*b + x0  (0 <= x0 < b)
+	//   y = yh*b + y0  (0 <= y0 < b)
 	//   b = 1<<(_W*k)  ("base" of digits xi, yi)
 	//
 	k := karatsubaLen(n)
@@ -417,27 +417,44 @@ func (z nat) mul(x, y nat) nat {
 	y0 := y[0:k]              // y0 is not normalized
 	z = z.make(max(6*k, m+n)) // enough space for karatsuba of x0*y0 and full result of x*y
 	karatsuba(z, x0, y0)
-	z = z[0 : m+n] // z has final length but may be incomplete, upper portion is garbage
+	z = z[0 : m+n]  // z has final length but may be incomplete
+	z[2*k:].clear() // upper portion of z is garbage (and 2*k <= m+n since k <= n <= m)
 
-	// If x1 and/or y1 are not 0, add missing terms to z explicitly:
+	// If xh != 0 or yh != 0, add the missing terms to z. For
+	//
+	//   xh = xi*b^i + ... + x2*b^2 + x1*b (0 <= xi < b)
+	//   yh =                         y1*b (0 <= y1 < b)
+	//
+	// the missing terms are
+	//
+	//   x0*y1*b and xi*y0*b^i, xi*y1*b^(i+1) for i > 0
 	//
-	//     m+n       2*k       0
-	//   z = [   ...   | x0*y0 ]
-	//     +   [ x1*y1 ]
-	//     +   [ x1*y0 ]
-	//     +   [ x0*y1 ]
+	// since all the yi for i > 1 are 0 by choice of k: If any of them
+	// were > 0, then yh >= b^2 and thus y >= b^2. Then k' = k*2 would
+	// be a larger valid threshold contradicting the assumption about k.
 	//
 	if k < n || m != n {
-		x1 := x[k:] // x1 is normalized because x is
-		y1 := y[k:] // y1 is normalized because y is
 		var t nat
-		t = t.mul(x1, y1)
-		copy(z[2*k:], t)
-		z[2*k+len(t):].clear() // upper portion of z is garbage
-		t = t.mul(x1, y0.norm())
-		addAt(z, t, k)
-		t = t.mul(x0.norm(), y1)
+
+		// add x0*y1*b
+		x0 := x0.norm()
+		y1 := y[k:]       // y1 is normalized because y is
+		t = t.mul(x0, y1) // update t so we don't lose t's underlying array
 		addAt(z, t, k)
+
+		// add xi*y0<<i, xi*y1*b<<(i+k)
+		y0 := y0.norm()
+		for i := k; i < len(x); i += k {
+			xi := x[i:]
+			if len(xi) > k {
+				xi = xi[:k]
+			}
+			xi = xi.norm()
+			t = t.mul(xi, y0)
+			addAt(z, t, i)
+			t = t.mul(xi, y1)
+			addAt(z, t, i+k)
+		}
 	}
 
 	return z.norm()
@@ -493,14 +510,9 @@ func (z nat) div(z2, u, v nat) (q, r nat) {
 	}
 
 	if len(v) == 1 {
-		var rprime Word
-		q, rprime = z.divW(u, v[0])
-		if rprime > 0 {
-			r = z2.make(1)
-			r[0] = rprime
-		} else {
-			r = z2.make(0)
-		}
+		var r2 Word
+		q, r2 = z.divW(u, v[0])
+		r = z2.setWord(r2)
 		return
 	}
 
@@ -740,7 +752,7 @@ func (x nat) string(charset string) string {
 	// convert power of two and non power of two bases separately
 	if b == b&-b {
 		// shift is base-b digit size in bits
-		shift := uint(trailingZeroBits(b)) // shift > 0 because b >= 2
+		shift := trailingZeroBits(b) // shift > 0 because b >= 2
 		mask := Word(1)<<shift - 1
 		w := x[0]
 		nbits := uint(_W) // number of unprocessed bits in w
@@ -814,18 +826,18 @@ func (x nat) string(charset string) string {
 
 // Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
 // by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
-// repeated nat/Word divison.
+// repeated nat/Word division.
 //
-// The iterative method processes n Words by n divW() calls, each of which visits every Word in the 
-// incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s. 
-// Recursive conversion divides q by its approximate square root, yielding two parts, each half 
+// The iterative method processes n Words by n divW() calls, each of which visits every Word in the
+// incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s.
+// Recursive conversion divides q by its approximate square root, yielding two parts, each half
 // the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
 // plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
-// is made better by splitting the subblocks recursively. Best is to split blocks until one more 
-// split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the 
-// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the 
-// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and 
-// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for 
+// is made better by splitting the subblocks recursively. Best is to split blocks until one more
+// split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the
+// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
+// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
+// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
 // specific hardware.
 //
 func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
@@ -908,8 +920,10 @@ type divisor struct {
 	ndigits int // digit length of divisor in terms of output base digits
 }
 
-var cacheBase10 [64]divisor // cached divisors for base 10
-var cacheLock sync.Mutex    // protects cacheBase10
+var cacheBase10 struct {
+	sync.Mutex
+	table [64]divisor // cached divisors for base 10
+}
 
 // expWW computes x**y
 func (z nat) expWW(x, y Word) nat {
@@ -925,34 +939,28 @@ func divisors(m int, b Word, ndigits int, bb Word) []divisor {
 
 	// determine k where (bb**leafSize)**(2**k) >= sqrt(x)
 	k := 1
-	for words := leafSize; words < m>>1 && k < len(cacheBase10); words <<= 1 {
+	for words := leafSize; words < m>>1 && k < len(cacheBase10.table); words <<= 1 {
 		k++
 	}
 
-	// create new table of divisors or extend and reuse existing table as appropriate
-	var table []divisor
-	var cached bool
-	switch b {
-	case 10:
-		table = cacheBase10[0:k] // reuse old table for this conversion
-		cached = true
-	default:
-		table = make([]divisor, k) // new table for this conversion
+	// reuse and extend existing table of divisors or create new table as appropriate
+	var table []divisor // for b == 10, table overlaps with cacheBase10.table
+	if b == 10 {
+		cacheBase10.Lock()
+		table = cacheBase10.table[0:k] // reuse old table for this conversion
+	} else {
+		table = make([]divisor, k) // create new table for this conversion
 	}
 
 	// extend table
 	if table[k-1].ndigits == 0 {
-		if cached {
-			cacheLock.Lock() // begin critical section
-		}
-
 		// add new entries as needed
 		var larger nat
 		for i := 0; i < k; i++ {
 			if table[i].ndigits == 0 {
 				if i == 0 {
-					table[i].bbb = nat(nil).expWW(bb, Word(leafSize))
-					table[i].ndigits = ndigits * leafSize
+					table[0].bbb = nat(nil).expWW(bb, Word(leafSize))
+					table[0].ndigits = ndigits * leafSize
 				} else {
 					table[i].bbb = nat(nil).mul(table[i-1].bbb, table[i-1].bbb)
 					table[i].ndigits = 2 * table[i-1].ndigits
@@ -968,10 +976,10 @@ func divisors(m int, b Word, ndigits int, bb Word) []divisor {
 				table[i].nbits = table[i].bbb.bitLen()
 			}
 		}
+	}
 
-		if cached {
-			cacheLock.Unlock() // end critical section
-		}
+	if b == 10 {
+		cacheBase10.Unlock()
 	}
 
 	return table
@@ -993,10 +1001,9 @@ var deBruijn64Lookup = []byte{
 	54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
 }
 
-// trailingZeroBits returns the number of consecutive zero bits on the right
-// side of the given Word.
-// See Knuth, volume 4, section 7.3.1
-func trailingZeroBits(x Word) int {
+// trailingZeroBits returns the number of consecutive least significant zero
+// bits of x.
+func trailingZeroBits(x Word) uint {
 	// x & -x leaves only the right-most bit set in the word. Let k be the
 	// index of that bit. Since only a single bit is set, the value is two
 	// to the power of k. Multiplying by a power of two is equivalent to
@@ -1005,18 +1012,33 @@ func trailingZeroBits(x Word) int {
 	// Therefore, if we have a left shifted version of this constant we can
 	// find by how many bits it was shifted by looking at which six bit
 	// substring ended up at the top of the word.
+	// (Knuth, volume 4, section 7.3.1)
 	switch _W {
 	case 32:
-		return int(deBruijn32Lookup[((x&-x)*deBruijn32)>>27])
+		return uint(deBruijn32Lookup[((x&-x)*deBruijn32)>>27])
 	case 64:
-		return int(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58])
+		return uint(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58])
 	default:
-		panic("Unknown word size")
+		panic("unknown word size")
 	}
 
 	return 0
 }
 
+// trailingZeroBits returns the number of consecutive least significant zero
+// bits of x.
+func (x nat) trailingZeroBits() uint {
+	if len(x) == 0 {
+		return 0
+	}
+	var i uint
+	for x[i] == 0 {
+		i++
+	}
+	// x[i] != 0
+	return i*_W + trailingZeroBits(x[i])
+}
+
 // z = x << s
 func (z nat) shl(x nat, s uint) nat {
 	m := len(x)
@@ -1169,29 +1191,6 @@ func (x nat) modW(d Word) (r Word) {
 	return divWVW(q, 0, x, d)
 }
 
-// powersOfTwoDecompose finds q and k with x = q * 1<<k and q is odd, or q and k are 0.
-func (x nat) powersOfTwoDecompose() (q nat, k int) {
-	if len(x) == 0 {
-		return x, 0
-	}
-
-	// One of the words must be non-zero by definition,
-	// so this loop will terminate with i < len(x), and
-	// i is the number of 0 words.
-	i := 0
-	for x[i] == 0 {
-		i++
-	}
-	n := trailingZeroBits(x[i]) // x[i] != 0
-
-	q = make(nat, len(x)-i)
-	shrVU(q, x[i:], uint(n))
-
-	q = q.norm()
-	k = i*_W + n
-	return
-}
-
 // random creates a random integer in [0..limit), using the space in z if
 // possible. n is the bit length of limit.
 func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
@@ -1207,17 +1206,19 @@ func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
 	mask := Word((1 << bitLengthOfMSW) - 1)
 
 	for {
-		for i := range z {
-			switch _W {
-			case 32:
+		switch _W {
+		case 32:
+			for i := range z {
 				z[i] = Word(rand.Uint32())
-			case 64:
+			}
+		case 64:
+			for i := range z {
 				z[i] = Word(rand.Uint32()) | Word(rand.Uint32())<<32
 			}
+		default:
+			panic("unknown word size")
 		}
-
 		z[len(limit)-1] &= mask
-
 		if z.cmp(limit) < 0 {
 			break
 		}
@@ -1226,11 +1227,11 @@ func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
 	return z.norm()
 }
 
-// If m != nil, expNN calculates x**y mod m. Otherwise it calculates x**y. It
-// reuses the storage of z if possible.
+// If m != 0 (i.e., len(m) != 0), expNN sets z to x**y mod m;
+// otherwise it sets z to x**y. The result is the value of z.
 func (z nat) expNN(x, y, m nat) nat {
 	if alias(z, x) || alias(z, y) {
-		// We cannot allow in place modification of x or y.
+		// We cannot allow in-place modification of x or y.
 		z = nil
 	}
 
@@ -1239,15 +1240,24 @@ func (z nat) expNN(x, y, m nat) nat {
 		z[0] = 1
 		return z
 	}
+	// y > 0
 
-	if m != nil {
+	if len(m) != 0 {
 		// We likely end up being as long as the modulus.
 		z = z.make(len(m))
 	}
 	z = z.set(x)
-	v := y[len(y)-1]
-	// It's invalid for the most significant word to be zero, therefore we
-	// will find a one bit.
+
+	// If the base is non-trivial and the exponent is large, we use
+	// 4-bit, windowed exponentiation. This involves precomputing 14 values
+	// (x^2...x^15) but then reduces the number of multiply-reduces by a
+	// third. Even for a 32-bit exponent, this reduces the number of
+	// operations.
+	if len(x) > 1 && len(y) > 1 && len(m) > 0 {
+		return z.expNNWindowed(x, y, m)
+	}
+
+	v := y[len(y)-1] // v > 0 because y is normalized and y > 0
 	shift := leadingZeros(v) + 1
 	v <<= shift
 	var q nat
@@ -1259,15 +1269,21 @@ func (z nat) expNN(x, y, m nat) nat {
 	// we also multiply by x, thus adding one to the power.
 
 	w := _W - int(shift)
+	// zz and r are used to avoid allocating in mul and div as
+	// otherwise the arguments would alias.
+	var zz, r nat
 	for j := 0; j < w; j++ {
-		z = z.mul(z, z)
+		zz = zz.mul(z, z)
+		zz, z = z, zz
 
 		if v&mask != 0 {
-			z = z.mul(z, x)
+			zz = zz.mul(z, x)
+			zz, z = z, zz
 		}
 
-		if m != nil {
-			q, z = q.div(z, z, m)
+		if len(m) != 0 {
+			zz, r = zz.div(r, z, m)
+			zz, r, q, z = q, z, zz, r
 		}
 
 		v <<= 1
@@ -1277,14 +1293,17 @@ func (z nat) expNN(x, y, m nat) nat {
 		v = y[i]
 
 		for j := 0; j < _W; j++ {
-			z = z.mul(z, z)
+			zz = zz.mul(z, z)
+			zz, z = z, zz
 
 			if v&mask != 0 {
-				z = z.mul(z, x)
+				zz = zz.mul(z, x)
+				zz, z = z, zz
 			}
 
-			if m != nil {
-				q, z = q.div(z, z, m)
+			if len(m) != 0 {
+				zz, r = zz.div(r, z, m)
+				zz, r, q, z = q, z, zz, r
 			}
 
 			v <<= 1
@@ -1294,6 +1313,69 @@ func (z nat) expNN(x, y, m nat) nat {
 	return z.norm()
 }
 
+// expNNWindowed calculates x**y mod m using a fixed, 4-bit window.
+func (z nat) expNNWindowed(x, y, m nat) nat {
+	// zz and r are used to avoid allocating in mul and div as otherwise
+	// the arguments would alias.
+	var zz, r nat
+
+	const n = 4
+	// powers[i] contains x^i.
+	var powers [1 << n]nat
+	powers[0] = natOne
+	powers[1] = x
+	for i := 2; i < 1<<n; i += 2 {
+		p2, p, p1 := &powers[i/2], &powers[i], &powers[i+1]
+		*p = p.mul(*p2, *p2)
+		zz, r = zz.div(r, *p, m)
+		*p, r = r, *p
+		*p1 = p1.mul(*p, x)
+		zz, r = zz.div(r, *p1, m)
+		*p1, r = r, *p1
+	}
+
+	z = z.setWord(1)
+
+	for i := len(y) - 1; i >= 0; i-- {
+		yi := y[i]
+		for j := 0; j < _W; j += n {
+			if i != len(y)-1 || j != 0 {
+				// Unrolled loop for significant performance
+				// gain.  Use go test -bench=".*" in crypto/rsa
+				// to check performance before making changes.
+				zz = zz.mul(z, z)
+				zz, z = z, zz
+				zz, r = zz.div(r, z, m)
+				z, r = r, z
+
+				zz = zz.mul(z, z)
+				zz, z = z, zz
+				zz, r = zz.div(r, z, m)
+				z, r = r, z
+
+				zz = zz.mul(z, z)
+				zz, z = z, zz
+				zz, r = zz.div(r, z, m)
+				z, r = r, z
+
+				zz = zz.mul(z, z)
+				zz, z = z, zz
+				zz, r = zz.div(r, z, m)
+				z, r = r, z
+			}
+
+			zz = zz.mul(z, powers[yi>>(_W-n)])
+			zz, z = z, zz
+			zz, r = zz.div(r, z, m)
+			z, r = r, z
+
+			yi <<= n
+		}
+	}
+
+	return z.norm()
+}
+
 // probablyPrime performs reps Miller-Rabin tests to check whether n is prime.
 // If it returns true, n is prime with probability 1 - 1/4^reps.
 // If it returns false, n is not prime.
@@ -1343,8 +1425,9 @@ func (n nat) probablyPrime(reps int) bool {
 	}
 
 	nm1 := nat(nil).sub(n, natOne)
-	// 1<<k * q = nm1;
-	q, k := nm1.powersOfTwoDecompose()
+	// determine q, k such that nm1 = q << k
+	k := nm1.trailingZeroBits()
+	q := nat(nil).shr(nm1, k)
 
 	nm3 := nat(nil).sub(nm1, natTwo)
 	rand := rand.New(rand.NewSource(int64(n[0])))
@@ -1360,7 +1443,7 @@ NextRandom:
 		if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 {
 			continue
 		}
-		for j := 1; j < k; j++ {
+		for j := uint(1); j < k; j++ {
 			y = y.mul(y, y)
 			quotient, y = quotient.div(y, y, n)
 			if y.cmp(nm1) == 0 {
diff --git a/src/pkg/math/big/nat_test.go b/src/pkg/math/big/nat_test.go
index becde5d..2dd7bf6 100644
--- a/src/pkg/math/big/nat_test.go
+++ b/src/pkg/math/big/nat_test.go
@@ -6,6 +6,7 @@ package big
 
 import (
 	"io"
+	"runtime"
 	"strings"
 	"testing"
 )
@@ -62,6 +63,36 @@ var prodNN = []argNN{
 	{nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}},
 	{nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}},
 	{nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}},
+	// 3^100 * 3^28 = 3^128
+	{
+		natFromString("11790184577738583171520872861412518665678211592275841109096961"),
+		natFromString("515377520732011331036461129765621272702107522001"),
+		natFromString("22876792454961"),
+	},
+	// z = 111....1 (70000 digits)
+	// x = 10^(99*700) + ... + 10^1400 + 10^700 + 1
+	// y = 111....1 (700 digits, larger than Karatsuba threshold on 32-bit and 64-bit)
+	{
+		natFromString(strings.Repeat("1", 70000)),
+		natFromString("1" + strings.Repeat(strings.Repeat("0", 699)+"1", 99)),
+		natFromString(strings.Repeat("1", 700)),
+	},
+	// z = 111....1 (20000 digits)
+	// x = 10^10000 + 1
+	// y = 111....1 (10000 digits)
+	{
+		natFromString(strings.Repeat("1", 20000)),
+		natFromString("1" + strings.Repeat("0", 9999) + "1"),
+		natFromString(strings.Repeat("1", 10000)),
+	},
+}
+
+func natFromString(s string) nat {
+	x, _, err := nat(nil).scan(strings.NewReader(s), 0)
+	if err != nil {
+		panic(err)
+	}
+	return x
 }
 
 func TestSet(t *testing.T) {
@@ -135,26 +166,43 @@ func TestMulRangeN(t *testing.T) {
 	}
 }
 
-var mulArg, mulTmp nat
-
-func init() {
-	const n = 1000
-	mulArg = make(nat, n)
-	for i := 0; i < n; i++ {
-		mulArg[i] = _M
+// allocBytes returns the number of bytes allocated by invoking f.
+func allocBytes(f func()) uint64 {
+	var stats runtime.MemStats
+	runtime.ReadMemStats(&stats)
+	t := stats.TotalAlloc
+	f()
+	runtime.ReadMemStats(&stats)
+	return stats.TotalAlloc - t
+}
+
+// TestMulUnbalanced tests that multiplying numbers of different lengths
+// does not cause deep recursion and in turn allocate too much memory.
+// Test case for issue 3807.
+func TestMulUnbalanced(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
+	x := rndNat(50000)
+	y := rndNat(40)
+	allocSize := allocBytes(func() {
+		nat(nil).mul(x, y)
+	})
+	inputSize := uint64(len(x)+len(y)) * _S
+	if ratio := allocSize / uint64(inputSize); ratio > 10 {
+		t.Errorf("multiplication uses too much memory (%d > %d times the size of inputs)", allocSize, ratio)
 	}
 }
 
-func benchmarkMulLoad() {
-	for j := 1; j <= 10; j++ {
-		x := mulArg[0 : j*100]
-		mulTmp.mul(x, x)
-	}
+func rndNat(n int) nat {
+	return nat(rndV(n)).norm()
 }
 
 func BenchmarkMul(b *testing.B) {
+	mulx := rndNat(1e4)
+	muly := rndNat(1e4)
+	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		benchmarkMulLoad()
+		var z nat
+		z.mul(mulx, muly)
 	}
 }
 
@@ -362,6 +410,20 @@ func TestScanPi(t *testing.T) {
 	}
 }
 
+func TestScanPiParallel(t *testing.T) {
+	const n = 2
+	c := make(chan int)
+	for i := 0; i < n; i++ {
+		go func() {
+			TestScanPi(t)
+			c <- 0
+		}()
+	}
+	for i := 0; i < n; i++ {
+		<-c
+	}
+}
+
 func BenchmarkScanPi(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		var x nat
@@ -369,6 +431,28 @@ func BenchmarkScanPi(b *testing.B) {
 	}
 }
 
+func BenchmarkStringPiParallel(b *testing.B) {
+	var x nat
+	x, _, _ = x.scan(strings.NewReader(pi), 0)
+	if x.decimalString() != pi {
+		panic("benchmark incorrect: conversion failed")
+	}
+	n := runtime.GOMAXPROCS(0)
+	m := b.N / n // n*m <= b.N due to flooring, but the error is neglibible (n is not very large)
+	c := make(chan int, n)
+	for i := 0; i < n; i++ {
+		go func() {
+			for j := 0; j < m; j++ {
+				x.decimalString()
+			}
+			c <- 0
+		}()
+	}
+	for i := 0; i < n; i++ {
+		<-c
+	}
+}
+
 func BenchmarkScan10Base2(b *testing.B)     { ScanHelper(b, 2, 10, 10) }
 func BenchmarkScan100Base2(b *testing.B)    { ScanHelper(b, 2, 10, 100) }
 func BenchmarkScan1000Base2(b *testing.B)   { ScanHelper(b, 2, 10, 1000) }
@@ -463,13 +547,13 @@ func BenchmarkLeafSize13(b *testing.B) { LeafSizeHelper(b, 10, 13) }
 func BenchmarkLeafSize14(b *testing.B) { LeafSizeHelper(b, 10, 14) }
 func BenchmarkLeafSize15(b *testing.B) { LeafSizeHelper(b, 10, 15) }
 func BenchmarkLeafSize16(b *testing.B) { LeafSizeHelper(b, 10, 16) }
-func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths 
+func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths
 func BenchmarkLeafSize64(b *testing.B) { LeafSizeHelper(b, 10, 64) }
 
 func LeafSizeHelper(b *testing.B, base Word, size int) {
 	b.StopTimer()
 	originalLeafSize := leafSize
-	resetTable(cacheBase10[:])
+	resetTable(cacheBase10.table[:])
 	leafSize = size
 	b.StartTimer()
 
@@ -486,7 +570,7 @@ func LeafSizeHelper(b *testing.B, base Word, size int) {
 	}
 
 	b.StopTimer()
-	resetTable(cacheBase10[:])
+	resetTable(cacheBase10.table[:])
 	leafSize = originalLeafSize
 	b.StartTimer()
 }
@@ -616,14 +700,23 @@ func TestModW(t *testing.T) {
 }
 
 func TestTrailingZeroBits(t *testing.T) {
-	var x Word
-	x--
-	for i := 0; i < _W; i++ {
-		if trailingZeroBits(x) != i {
-			t.Errorf("Failed at step %d: x: %x got: %d", i, x, trailingZeroBits(x))
+	x := Word(1)
+	for i := uint(0); i <= _W; i++ {
+		n := trailingZeroBits(x)
+		if n != i%_W {
+			t.Errorf("got trailingZeroBits(%#x) = %d; want %d", x, n, i%_W)
 		}
 		x <<= 1
 	}
+
+	y := nat(nil).set(natOne)
+	for i := uint(0); i <= 3*_W; i++ {
+		n := y.trailingZeroBits()
+		if n != i {
+			t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.string(lowercaseDigits[0:16]), n, i)
+		}
+		y = y.shl(y, 1)
+	}
 }
 
 var expNNTests = []struct {
diff --git a/src/pkg/math/big/rat.go b/src/pkg/math/big/rat.go
index 7bd83fc..3e6473d 100644
--- a/src/pkg/math/big/rat.go
+++ b/src/pkg/math/big/rat.go
@@ -10,14 +10,17 @@ import (
 	"encoding/binary"
 	"errors"
 	"fmt"
+	"math"
 	"strings"
 )
 
 // A Rat represents a quotient a/b of arbitrary precision.
 // The zero value for a Rat represents the value 0.
 type Rat struct {
-	a Int
-	b nat // len(b) == 0 acts like b == 1
+	// To make zero values for Rat work w/o initialization,
+	// a zero value of b (len(b) == 0) acts like b == 1.
+	// a.neg determines the sign of the Rat, b.neg is ignored.
+	a, b Int
 }
 
 // NewRat creates a new Rat with numerator a and denominator b.
@@ -25,6 +28,156 @@ func NewRat(a, b int64) *Rat {
 	return new(Rat).SetFrac64(a, b)
 }
 
+// SetFloat64 sets z to exactly f and returns z.
+// If f is not finite, SetFloat returns nil.
+func (z *Rat) SetFloat64(f float64) *Rat {
+	const expMask = 1<<11 - 1
+	bits := math.Float64bits(f)
+	mantissa := bits & (1<<52 - 1)
+	exp := int((bits >> 52) & expMask)
+	switch exp {
+	case expMask: // non-finite
+		return nil
+	case 0: // denormal
+		exp -= 1022
+	default: // normal
+		mantissa |= 1 << 52
+		exp -= 1023
+	}
+
+	shift := 52 - exp
+
+	// Optimisation (?): partially pre-normalise.
+	for mantissa&1 == 0 && shift > 0 {
+		mantissa >>= 1
+		shift--
+	}
+
+	z.a.SetUint64(mantissa)
+	z.a.neg = f < 0
+	z.b.Set(intOne)
+	if shift > 0 {
+		z.b.Lsh(&z.b, uint(shift))
+	} else {
+		z.a.Lsh(&z.a, uint(-shift))
+	}
+	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
+}
+
+// low64 returns the least significant 64 bits of natural number z.
+func low64(z nat) uint64 {
+	if len(z) == 0 {
+		return 0
+	}
+	if _W == 32 && len(z) > 1 {
+		return uint64(z[1])<<32 | uint64(z[0])
+	}
+	return uint64(z[0])
+}
+
+// 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.
+// Preconditions: b is non-zero; a and b have no common factors.
+func quotToFloat(a, b nat) (f float64, exact bool) {
+	// TODO(adonovan): specialize common degenerate cases: 1.0, integers.
+	alen := a.bitLen()
+	if alen == 0 {
+		return 0, true
+	}
+	blen := b.bitLen()
+	if blen == 0 {
+		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:
+	// - the optional extra bit is shifted away in step 3 below.
+	// - the high-order 1 is omitted in float64 "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 {
+		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 := 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
+	// (in effect---we accomplish this incrementally).
+	if mantissa>>54 == 1 {
+		if mantissa&1 == 1 {
+			haveRem = true
+		}
+		mantissa >>= 1
+		exp++
+	}
+	if mantissa>>53 != 1 {
+		panic("expected exactly 54 bits of result")
+	}
+
+	// 4. Rounding.
+	if -1022-52 <= exp && exp <= -1022 {
+		// Denormal case; lose 'shift' bits of precision.
+		shift := uint64(-1022 - (exp - 1)) // [1..53)
+		lostbits := mantissa & (1<<shift - 1)
+		haveRem = haveRem || lostbits != 0
+		mantissa >>= shift
+		exp = -1023 + 2
+	}
+	// 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 {
+				// Complete rollover 11...1 => 100...0, so shift is safe
+				mantissa >>= 1
+				exp++
+			}
+		}
+	}
+	mantissa >>= 1 // discard rounding bit.  Mantissa now scaled by 2^53.
+
+	f = math.Ldexp(float64(mantissa), exp-53)
+	if math.IsInf(f, 0) {
+		exact = false
+	}
+	return
+}
+
+// Float64 returns the nearest float64 value to z.
+// If z is exactly representable as a float64, Float64 returns exact=true.
+// If z is negative, so too is f, even if f==0.
+func (z *Rat) Float64() (f float64, exact bool) {
+	b := z.b.abs
+	if len(b) == 0 {
+		b = b.set(natOne) // materialize denominator
+	}
+	f, exact = quotToFloat(z.a.abs, b)
+	if z.a.neg {
+		f = -f
+	}
+	return
+}
+
 // SetFrac sets z to a/b and returns z.
 func (z *Rat) SetFrac(a, b *Int) *Rat {
 	z.a.neg = a.neg != b.neg
@@ -36,7 +189,7 @@ func (z *Rat) SetFrac(a, b *Int) *Rat {
 		babs = nat(nil).set(babs) // make a copy
 	}
 	z.a.abs = z.a.abs.set(a.abs)
-	z.b = z.b.set(babs)
+	z.b.abs = z.b.abs.set(babs)
 	return z.norm()
 }
 
@@ -50,21 +203,21 @@ func (z *Rat) SetFrac64(a, b int64) *Rat {
 		b = -b
 		z.a.neg = !z.a.neg
 	}
-	z.b = z.b.setUint64(uint64(b))
+	z.b.abs = z.b.abs.setUint64(uint64(b))
 	return z.norm()
 }
 
 // SetInt sets z to x (by making a copy of x) and returns z.
 func (z *Rat) SetInt(x *Int) *Rat {
 	z.a.Set(x)
-	z.b = z.b.make(0)
+	z.b.abs = z.b.abs.make(0)
 	return z
 }
 
 // SetInt64 sets z to x and returns z.
 func (z *Rat) SetInt64(x int64) *Rat {
 	z.a.SetInt64(x)
-	z.b = z.b.make(0)
+	z.b.abs = z.b.abs.make(0)
 	return z
 }
 
@@ -72,7 +225,7 @@ func (z *Rat) SetInt64(x int64) *Rat {
 func (z *Rat) Set(x *Rat) *Rat {
 	if z != x {
 		z.a.Set(&x.a)
-		z.b = z.b.set(x.b)
+		z.b.Set(&x.b)
 	}
 	return z
 }
@@ -97,15 +250,15 @@ func (z *Rat) Inv(x *Rat) *Rat {
 		panic("division by zero")
 	}
 	z.Set(x)
-	a := z.b
+	a := z.b.abs
 	if len(a) == 0 {
-		a = a.setWord(1) // materialize numerator
+		a = a.set(natOne) // materialize numerator
 	}
 	b := z.a.abs
 	if b.cmp(natOne) == 0 {
 		b = b.make(0) // normalize denominator
 	}
-	z.a.abs, z.b = a, b // sign doesn't change
+	z.a.abs, z.b.abs = a, b // sign doesn't change
 	return z
 }
 
@@ -121,38 +274,26 @@ func (x *Rat) Sign() int {
 
 // IsInt returns true if the denominator of x is 1.
 func (x *Rat) IsInt() bool {
-	return len(x.b) == 0 || x.b.cmp(natOne) == 0
+	return len(x.b.abs) == 0 || x.b.abs.cmp(natOne) == 0
 }
 
 // Num returns the numerator of x; it may be <= 0.
 // The result is a reference to x's numerator; it
-// may change if a new value is assigned to x.
+// may change if a new value is assigned to x, and vice versa.
+// The sign of the numerator corresponds to the sign of x.
 func (x *Rat) Num() *Int {
 	return &x.a
 }
 
 // Denom returns the denominator of x; it is always > 0.
 // The result is a reference to x's denominator; it
-// may change if a new value is assigned to x.
+// may change if a new value is assigned to x, and vice versa.
 func (x *Rat) Denom() *Int {
-	if len(x.b) == 0 {
-		return &Int{abs: nat{1}}
+	x.b.neg = false // the result is always >= 0
+	if len(x.b.abs) == 0 {
+		x.b.abs = x.b.abs.set(natOne) // materialize denominator
 	}
-	return &Int{abs: x.b}
-}
-
-func gcd(x, y nat) nat {
-	// Euclidean algorithm.
-	var a, b nat
-	a = a.set(x)
-	b = b.set(y)
-	for len(b) != 0 {
-		var q, r nat
-		_, r = q.div(r, a, b)
-		a = b
-		b = r
-	}
-	return a
+	return &x.b
 }
 
 func (z *Rat) norm() *Rat {
@@ -160,17 +301,25 @@ func (z *Rat) norm() *Rat {
 	case len(z.a.abs) == 0:
 		// z == 0 - normalize sign and denominator
 		z.a.neg = false
-		z.b = z.b.make(0)
-	case len(z.b) == 0:
+		z.b.abs = z.b.abs.make(0)
+	case len(z.b.abs) == 0:
 		// z is normalized int - nothing to do
-	case z.b.cmp(natOne) == 0:
+	case z.b.abs.cmp(natOne) == 0:
 		// z is int - normalize denominator
-		z.b = z.b.make(0)
+		z.b.abs = z.b.abs.make(0)
 	default:
-		if f := gcd(z.a.abs, z.b); f.cmp(natOne) != 0 {
-			z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f)
-			z.b, _ = z.b.div(nil, z.b, f)
+		neg := z.a.neg
+		z.a.neg = false
+		z.b.neg = false
+		if f := NewInt(0).binaryGCD(&z.a, &z.b); f.Cmp(intOne) != 0 {
+			z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f.abs)
+			z.b.abs, _ = z.b.abs.div(nil, z.b.abs, f.abs)
+			if z.b.abs.cmp(natOne) == 0 {
+				// z is int - normalize denominator
+				z.b.abs = z.b.abs.make(0)
+			}
 		}
+		z.a.neg = neg
 	}
 	return z
 }
@@ -207,31 +356,31 @@ func scaleDenom(x *Int, f nat) *Int {
 //   +1 if x >  y
 //
 func (x *Rat) Cmp(y *Rat) int {
-	return scaleDenom(&x.a, y.b).Cmp(scaleDenom(&y.a, x.b))
+	return scaleDenom(&x.a, y.b.abs).Cmp(scaleDenom(&y.a, x.b.abs))
 }
 
 // Add sets z to the sum x+y and returns z.
 func (z *Rat) Add(x, y *Rat) *Rat {
-	a1 := scaleDenom(&x.a, y.b)
-	a2 := scaleDenom(&y.a, x.b)
+	a1 := scaleDenom(&x.a, y.b.abs)
+	a2 := scaleDenom(&y.a, x.b.abs)
 	z.a.Add(a1, a2)
-	z.b = mulDenom(z.b, x.b, y.b)
+	z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
 	return z.norm()
 }
 
 // Sub sets z to the difference x-y and returns z.
 func (z *Rat) Sub(x, y *Rat) *Rat {
-	a1 := scaleDenom(&x.a, y.b)
-	a2 := scaleDenom(&y.a, x.b)
+	a1 := scaleDenom(&x.a, y.b.abs)
+	a2 := scaleDenom(&y.a, x.b.abs)
 	z.a.Sub(a1, a2)
-	z.b = mulDenom(z.b, x.b, y.b)
+	z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
 	return z.norm()
 }
 
 // Mul sets z to the product x*y and returns z.
 func (z *Rat) Mul(x, y *Rat) *Rat {
 	z.a.Mul(&x.a, &y.a)
-	z.b = mulDenom(z.b, x.b, y.b)
+	z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
 	return z.norm()
 }
 
@@ -241,10 +390,10 @@ func (z *Rat) Quo(x, y *Rat) *Rat {
 	if len(y.a.abs) == 0 {
 		panic("division by zero")
 	}
-	a := scaleDenom(&x.a, y.b)
-	b := scaleDenom(&y.a, x.b)
+	a := scaleDenom(&x.a, y.b.abs)
+	b := scaleDenom(&y.a, x.b.abs)
 	z.a.abs = a.abs
-	z.b = b.abs
+	z.b.abs = b.abs
 	z.a.neg = a.neg != b.neg
 	return z.norm()
 }
@@ -286,7 +435,7 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
 		}
 		s = s[sep+1:]
 		var err error
-		if z.b, _, err = z.b.scan(strings.NewReader(s), 10); err != nil {
+		if z.b.abs, _, err = z.b.abs.scan(strings.NewReader(s), 10); err != nil {
 			return nil, false
 		}
 		return z.norm(), true
@@ -317,11 +466,11 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
 	}
 	powTen := nat(nil).expNN(natTen, exp.abs, nil)
 	if exp.neg {
-		z.b = powTen
+		z.b.abs = powTen
 		z.norm()
 	} else {
 		z.a.abs = z.a.abs.mul(z.a.abs, powTen)
-		z.b = z.b.make(0)
+		z.b.abs = z.b.abs.make(0)
 	}
 
 	return z, true
@@ -330,8 +479,8 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
 // String returns a string representation of z in the form "a/b" (even if b == 1).
 func (x *Rat) String() string {
 	s := "/1"
-	if len(x.b) != 0 {
-		s = "/" + x.b.decimalString()
+	if len(x.b.abs) != 0 {
+		s = "/" + x.b.abs.decimalString()
 	}
 	return x.a.String() + s
 }
@@ -355,9 +504,9 @@ func (x *Rat) FloatString(prec int) string {
 		}
 		return s
 	}
-	// x.b != 0
+	// x.b.abs != 0
 
-	q, r := nat(nil).div(nat(nil), x.a.abs, x.b)
+	q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
 
 	p := natOne
 	if prec > 0 {
@@ -365,11 +514,11 @@ func (x *Rat) FloatString(prec int) string {
 	}
 
 	r = r.mul(r, p)
-	r, r2 := r.div(nat(nil), r, x.b)
+	r, r2 := r.div(nat(nil), r, x.b.abs)
 
 	// see if we need to round up
 	r2 = r2.add(r2, r2)
-	if x.b.cmp(r2) <= 0 {
+	if x.b.abs.cmp(r2) <= 0 {
 		r = r.add(r, natOne)
 		if r.cmp(p) >= 0 {
 			q = nat(nil).add(q, natOne)
@@ -396,8 +545,8 @@ const ratGobVersion byte = 1
 
 // GobEncode implements the gob.GobEncoder interface.
 func (x *Rat) GobEncode() ([]byte, error) {
-	buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
-	i := x.b.bytes(buf)
+	buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
+	i := x.b.abs.bytes(buf)
 	j := x.a.abs.bytes(buf[0:i])
 	n := i - j
 	if int(uint32(n)) != n {
@@ -427,6 +576,6 @@ func (z *Rat) GobDecode(buf []byte) error {
 	i := j + binary.BigEndian.Uint32(buf[j-4:j])
 	z.a.neg = b&1 != 0
 	z.a.abs = z.a.abs.setBytes(buf[j:i])
-	z.b = z.b.setBytes(buf[i:])
+	z.b.abs = z.b.abs.setBytes(buf[i:])
 	return nil
 }
diff --git a/src/pkg/math/big/rat_test.go b/src/pkg/math/big/rat_test.go
index f7f31ae..462dfb7 100644
--- a/src/pkg/math/big/rat_test.go
+++ b/src/pkg/math/big/rat_test.go
@@ -8,6 +8,9 @@ import (
 	"bytes"
 	"encoding/gob"
 	"fmt"
+	"math"
+	"strconv"
+	"strings"
 	"testing"
 )
 
@@ -387,30 +390,19 @@ func TestRatGobEncoding(t *testing.T) {
 	var medium bytes.Buffer
 	enc := gob.NewEncoder(&medium)
 	dec := gob.NewDecoder(&medium)
-	for i, test := range gobEncodingTests {
-		for j := 0; j < 4; j++ {
-			medium.Reset() // empty buffer for each test case (in case of failures)
-			stest := test
-			if j&1 != 0 {
-				// negative numbers
-				stest = "-" + test
-			}
-			if j%2 != 0 {
-				// fractions
-				stest = stest + "." + test
-			}
-			var tx Rat
-			tx.SetString(stest)
-			if err := enc.Encode(&tx); err != nil {
-				t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
-			}
-			var rx Rat
-			if err := dec.Decode(&rx); err != nil {
-				t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
-			}
-			if rx.Cmp(&tx) != 0 {
-				t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
-			}
+	for _, test := range encodingTests {
+		medium.Reset() // empty buffer for each test case (in case of failures)
+		var tx Rat
+		tx.SetString(test + ".14159265")
+		if err := enc.Encode(&tx); err != nil {
+			t.Errorf("encoding of %s failed: %s", &tx, err)
+		}
+		var rx Rat
+		if err := dec.Decode(&rx); err != nil {
+			t.Errorf("decoding of %s failed: %s", &tx, err)
+		}
+		if rx.Cmp(&tx) != 0 {
+			t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
 		}
 	}
 }
@@ -454,3 +446,462 @@ func TestIssue2379(t *testing.T) {
 		t.Errorf("5) got %s want %s", x, q)
 	}
 }
+
+func TestIssue3521(t *testing.T) {
+	a := new(Int)
+	b := new(Int)
+	a.SetString("64375784358435883458348587", 0)
+	b.SetString("4789759874531", 0)
+
+	// 0) a raw zero value has 1 as denominator
+	zero := new(Rat)
+	one := NewInt(1)
+	if zero.Denom().Cmp(one) != 0 {
+		t.Errorf("0) got %s want %s", zero.Denom(), one)
+	}
+
+	// 1a) a zero value remains zero independent of denominator
+	x := new(Rat)
+	x.Denom().Set(new(Int).Neg(b))
+	if x.Cmp(zero) != 0 {
+		t.Errorf("1a) got %s want %s", x, zero)
+	}
+
+	// 1b) a zero value may have a denominator != 0 and != 1
+	x.Num().Set(a)
+	qab := new(Rat).SetFrac(a, b)
+	if x.Cmp(qab) != 0 {
+		t.Errorf("1b) got %s want %s", x, qab)
+	}
+
+	// 2a) an integral value becomes a fraction depending on denominator
+	x.SetFrac64(10, 2)
+	x.Denom().SetInt64(3)
+	q53 := NewRat(5, 3)
+	if x.Cmp(q53) != 0 {
+		t.Errorf("2a) got %s want %s", x, q53)
+	}
+
+	// 2b) an integral value becomes a fraction depending on denominator
+	x = NewRat(10, 2)
+	x.Denom().SetInt64(3)
+	if x.Cmp(q53) != 0 {
+		t.Errorf("2b) got %s want %s", x, q53)
+	}
+
+	// 3) changing the numerator/denominator of a Rat changes the Rat
+	x.SetFrac(a, b)
+	a = x.Num()
+	b = x.Denom()
+	a.SetInt64(5)
+	b.SetInt64(3)
+	if x.Cmp(q53) != 0 {
+		t.Errorf("3) got %s want %s", x, q53)
+	}
+}
+
+// Test inputs to Rat.SetString.  The prefix "long:" causes the test
+// to be skipped in --test.short mode.  (The threshold is about 500us.)
+var float64inputs = []string{
+	//
+	// Constants plundered from strconv/testfp.txt.
+	//
+
+	// Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
+	"5e+125",
+	"69e+267",
+	"999e-026",
+	"7861e-034",
+	"75569e-254",
+	"928609e-261",
+	"9210917e+080",
+	"84863171e+114",
+	"653777767e+273",
+	"5232604057e-298",
+	"27235667517e-109",
+	"653532977297e-123",
+	"3142213164987e-294",
+	"46202199371337e-072",
+	"231010996856685e-073",
+	"9324754620109615e+212",
+	"78459735791271921e+049",
+	"272104041512242479e+200",
+	"6802601037806061975e+198",
+	"20505426358836677347e-221",
+	"836168422905420598437e-234",
+	"4891559871276714924261e+222",
+
+	// Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
+	"9e-265",
+	"85e-037",
+	"623e+100",
+	"3571e+263",
+	"81661e+153",
+	"920657e-023",
+	"4603285e-024",
+	"87575437e-309",
+	"245540327e+122",
+	"6138508175e+120",
+	"83356057653e+193",
+	"619534293513e+124",
+	"2335141086879e+218",
+	"36167929443327e-159",
+	"609610927149051e-255",
+	"3743626360493413e-165",
+	"94080055902682397e-242",
+	"899810892172646163e+283",
+	"7120190517612959703e+120",
+	"25188282901709339043e-252",
+	"308984926168550152811e-052",
+	"6372891218502368041059e+064",
+
+	// Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
+	"5e-20",
+	"67e+14",
+	"985e+15",
+	"7693e-42",
+	"55895e-16",
+	"996622e-44",
+	"7038531e-32",
+	"60419369e-46",
+	"702990899e-20",
+	"6930161142e-48",
+	"25933168707e+13",
+	"596428896559e+20",
+
+	// Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
+	"3e-23",
+	"57e+18",
+	"789e-35",
+	"2539e-18",
+	"76173e+28",
+	"887745e-11",
+	"5382571e-37",
+	"82381273e-35",
+	"750486563e-38",
+	"3752432815e-39",
+	"75224575729e-45",
+	"459926601011e+15",
+
+	//
+	// Constants plundered from strconv/atof_test.go.
+	//
+
+	"0",
+	"1",
+	"+1",
+	"1e23",
+	"1E23",
+	"100000000000000000000000",
+	"1e-100",
+	"123456700",
+	"99999999999999974834176",
+	"100000000000000000000001",
+	"100000000000000008388608",
+	"100000000000000016777215",
+	"100000000000000016777216",
+	"-1",
+	"-0.1",
+	"-0", // NB: exception made for this input
+	"1e-20",
+	"625e-3",
+
+	// largest float64
+	"1.7976931348623157e308",
+	"-1.7976931348623157e308",
+	// next float64 - too large
+	"1.7976931348623159e308",
+	"-1.7976931348623159e308",
+	// the border is ...158079
+	// borderline - okay
+	"1.7976931348623158e308",
+	"-1.7976931348623158e308",
+	// borderline - too large
+	"1.797693134862315808e308",
+	"-1.797693134862315808e308",
+
+	// a little too large
+	"1e308",
+	"2e308",
+	"1e309",
+
+	// way too large
+	"1e310",
+	"-1e310",
+	"1e400",
+	"-1e400",
+	"long:1e400000",
+	"long:-1e400000",
+
+	// denormalized
+	"1e-305",
+	"1e-306",
+	"1e-307",
+	"1e-308",
+	"1e-309",
+	"1e-310",
+	"1e-322",
+	// smallest denormal
+	"5e-324",
+	"4e-324",
+	"3e-324",
+	// too small
+	"2e-324",
+	// way too small
+	"1e-350",
+	"long:1e-400000",
+	// way too small, negative
+	"-1e-350",
+	"long:-1e-400000",
+
+	// try to overflow exponent
+	// [Disabled: too slow and memory-hungry with rationals.]
+	// "1e-4294967296",
+	// "1e+4294967296",
+	// "1e-18446744073709551616",
+	// "1e+18446744073709551616",
+
+	// 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).
+	"4.630813248087435e+307",
+
+	// A different kind of very large number.
+	"22.222222222222222",
+	"long:2." + strings.Repeat("2", 4000) + "e+1",
+
+	// Exactly halfway between 1 and math.Nextafter(1, 2).
+	// Round to even (down).
+	"1.00000000000000011102230246251565404236316680908203125",
+	// Slightly lower; still round down.
+	"1.00000000000000011102230246251565404236316680908203124",
+	// Slightly higher; round up.
+	"1.00000000000000011102230246251565404236316680908203126",
+	// Slightly higher, but you have to read all the way to the end.
+	"long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
+
+	// Smallest denormal, 2^(-1022-52)
+	"4.940656458412465441765687928682213723651e-324",
+	// Half of smallest denormal, 2^(-1022-53)
+	"2.470328229206232720882843964341106861825e-324",
+	// A little more than the exact half of smallest denormal
+	// 2^-1075 + 2^-1100.  (Rounds to 1p-1074.)
+	"2.470328302827751011111470718709768633275e-324",
+	// The exact halfway between smallest normal and largest denormal:
+	// 2^-1022 - 2^-1075.  (Rounds to 2^-1022.)
+	"2.225073858507201136057409796709131975935e-308",
+
+	"1152921504606846975",  //   1<<60 - 1
+	"-1152921504606846975", // -(1<<60 - 1)
+	"1152921504606846977",  //   1<<60 + 1
+	"-1152921504606846977", // -(1<<60 + 1)
+
+	"1/3",
+}
+
+func TestFloat64SpecialCases(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.Float64()
+
+		// 1. Check string -> Rat -> float64 conversions are
+		// consistent with strconv.ParseFloat.
+		// Skip this check if the input uses "a/b" rational syntax.
+		if !strings.Contains(input, "/") {
+			e, _ := strconv.ParseFloat(input, 64)
+
+			// Careful: negative Rats too small for
+			// float64 become -0, but Rat obviously cannot
+			// preserve the sign from SetString("-0").
+			switch {
+			case math.Float64bits(e) == math.Float64bits(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(f) {
+			continue
+		}
+
+		// 2. Check f is best approximation to r.
+		if !checkIsBestApprox(t, f, r) {
+			// Append context information.
+			t.Errorf("(input was %q)", input)
+		}
+
+		// 3. Check f->R->f roundtrip is non-lossy.
+		checkNonLossyRoundtrip(t, f)
+
+		// 4. Check exactness using slow algorithm.
+		if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
+			t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
+		}
+	}
+}
+
+func TestFloat64Distribution(t *testing.T) {
+	// Generate a distribution of (sign, mantissa, exp) values
+	// broader than the float64 range, and check Rat.Float64()
+	// always picks the closest float64 approximation.
+	var add = []int64{
+		0,
+		1,
+		3,
+		5,
+		7,
+		9,
+		11,
+	}
+	var winc, einc = uint64(1), int(1) // soak test (~75s on x86-64)
+	if testing.Short() {
+		winc, einc = 10, 500 // quick test (~12ms on x86-64)
+	}
+
+	for _, sign := range "+-" {
+		for _, a := range add {
+			for wid := uint64(0); wid < 60; wid += winc {
+				b := int64(1<<wid + a)
+				if sign == '-' {
+					b = -b
+				}
+				for exp := -1100; exp < 1100; 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.Float64()
+
+					if !checkIsBestApprox(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)
+				}
+			}
+		}
+	}
+}
+
+// TestFloat64NonFinite 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)} {
+		var r Rat
+		if r2 := r.SetFloat64(f); r2 != nil {
+			t.Errorf("SetFloat64(%g) was %v, want nil", f, r2)
+		}
+	}
+}
+
+// checkNonLossyRoundtrip checks that a float->Rat->float roundtrip is
+// non-lossy for finite f.
+func checkNonLossyRoundtrip(t *testing.T, f float64) {
+	if !isFinite(f) {
+		return
+	}
+	r := new(Rat).SetFloat64(f)
+	if r == nil {
+		t.Errorf("Rat.SetFloat64(%g (%b)) == nil", f, f)
+		return
+	}
+	f2, exact := r.Float64()
+	if f != f2 || !exact {
+		t.Errorf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta=%b",
+			f, f2, f2, exact, f, f, true, f2-f)
+	}
+}
+
+// delta returns the absolute difference between r and f.
+func delta(r *Rat, f float64) *Rat {
+	d := new(Rat).Sub(r, new(Rat).SetFloat64(f))
+	return d.Abs(d)
+}
+
+// checkIsBestApprox 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 {
+	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.
+		return true
+	}
+
+	// r must be strictly between f0 and f1, the floats bracketing f.
+	f0 := math.Nextafter(f, math.Inf(-1))
+	f1 := math.Nextafter(f, math.Inf(+1))
+
+	// For f to be correct, r must be closer to f than to f0 or f1.
+	df := delta(r, f)
+	df0 := delta(r, f0)
+	df1 := delta(r, f1)
+	if df.Cmp(df0) > 0 {
+		t.Errorf("Rat(%v).Float64() = %g (%b), but previous float64 %g (%b) is closer", r, f, f, f0, f0)
+		return false
+	}
+	if df.Cmp(df1) > 0 {
+		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) {
+		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) {
+		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 TestIsFinite(t *testing.T) {
+	finites := []float64{
+		1.0 / 3,
+		4891559871276714924261e+222,
+		math.MaxFloat64,
+		math.SmallestNonzeroFloat64,
+		-math.MaxFloat64,
+		-math.SmallestNonzeroFloat64,
+	}
+	for _, f := range finites {
+		if !isFinite(f) {
+			t.Errorf("!IsFinite(%g (%b))", f, f)
+		}
+	}
+	nonfinites := []float64{
+		math.NaN(),
+		math.Inf(-1),
+		math.Inf(+1),
+	}
+	for _, f := range nonfinites {
+		if isFinite(f) {
+			t.Errorf("IsFinite(%g, (%b))", f, f)
+		}
+	}
+}
diff --git a/src/pkg/math/bits.go b/src/pkg/math/bits.go
index 1cf60ce..0df0b1c 100644
--- a/src/pkg/math/bits.go
+++ b/src/pkg/math/bits.go
@@ -5,7 +5,7 @@
 package math
 
 const (
-	uvnan    = 0x7FF0000000000001
+	uvnan    = 0x7FF8000000000001
 	uvinf    = 0x7FF0000000000000
 	uvneginf = 0xFFF0000000000000
 	mask     = 0x7FF
diff --git a/src/pkg/math/cbrt.go b/src/pkg/math/cbrt.go
index 8c43f0a..272e309 100644
--- a/src/pkg/math/cbrt.go
+++ b/src/pkg/math/cbrt.go
@@ -12,7 +12,7 @@ package math
 	(http://www.jstor.org/stable/2006387?seq=9, accessed 11-Feb-2010)
 */
 
-// Cbrt returns the cube root of its argument.
+// Cbrt returns the cube root of x.
 //
 // Special cases are:
 //	Cbrt(±0) = ±0
diff --git a/src/pkg/math/copysign.go b/src/pkg/math/copysign.go
index ee65456..719c64b 100644
--- a/src/pkg/math/copysign.go
+++ b/src/pkg/math/copysign.go
@@ -4,7 +4,7 @@
 
 package math
 
-// Copysign(x, y) returns a value with the magnitude
+// Copysign returns a value with the magnitude
 // of x and the sign of y.
 func Copysign(x, y float64) float64 {
 	const sign = 1 << 63
diff --git a/src/pkg/math/dim_amd64.s b/src/pkg/math/dim_amd64.s
index c867db5..a1505ce 100644
--- a/src/pkg/math/dim_amd64.s
+++ b/src/pkg/math/dim_amd64.s
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 #define PosInf 0x7FF0000000000000
-#define NaN    0x7FF0000000000001
+#define NaN    0x7FF8000000000001
 #define NegInf 0xFFF0000000000000
 
 // func Dim(x, y float64) float64
diff --git a/src/pkg/math/erf.go b/src/pkg/math/erf.go
index c6f32bd..4cd80f8 100644
--- a/src/pkg/math/erf.go
+++ b/src/pkg/math/erf.go
@@ -179,7 +179,7 @@ const (
 	sb7 = -2.24409524465858183362e+01 // 0xC03670E242712D62
 )
 
-// Erf(x) returns the error function of x.
+// Erf returns the error function of x.
 //
 // Special cases are:
 //	Erf(+Inf) = 1
@@ -256,7 +256,7 @@ func Erf(x float64) float64 {
 	return 1 - r/x
 }
 
-// Erfc(x) returns the complementary error function of x.
+// Erfc returns the complementary error function of x.
 //
 // Special cases are:
 //	Erfc(+Inf) = 0
diff --git a/src/pkg/math/floor_amd64.s b/src/pkg/math/floor_amd64.s
index 9fc49a5..e72cc3c 100644
--- a/src/pkg/math/floor_amd64.s
+++ b/src/pkg/math/floor_amd64.s
@@ -1,12 +1,74 @@
-// Copyright 2011 The Go Authors.  All rights reserved.
+// 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.
 
+#define Big		0x4330000000000000 // 2**52
+
+// func Floor(x float64) float64
 TEXT ·Floor(SB),7,$0
-	JMP	·floor(SB)
+	MOVQ	x+0(FP), AX
+	MOVQ	$~(1<<63), DX // sign bit mask
+	ANDQ	AX,DX // DX = |x|
+	SUBQ	$1,DX
+	MOVQ    $(Big - 1), CX // if |x| >= 2**52-1 or IsNaN(x) or |x| == 0, return x
+	CMPQ	DX,CX
+	JAE     isBig_floor
+	MOVQ	AX, X0 // X0 = x
+	CVTTSD2SQ	X0, AX
+	CVTSQ2SD	AX, X1 // X1 = float(int(x))
+	CMPSD	X1, X0, 1 // compare LT; X0 = 0xffffffffffffffff or 0
+	MOVSD	$(-1.0), X2
+	ANDPD	X2, X0 // if x < float(int(x)) {X0 = -1} else {X0 = 0}
+	ADDSD	X1, X0
+	MOVSD	X0, r+8(FP)
+	RET
+isBig_floor:
+	MOVQ    AX, r+8(FP) // return x
+	RET
 
+// func Ceil(x float64) float64
 TEXT ·Ceil(SB),7,$0
-	JMP	·ceil(SB)
+	MOVQ	x+0(FP), AX
+	MOVQ	$~(1<<63), DX // sign bit mask
+	MOVQ	AX, BX // BX = copy of x
+	ANDQ    DX, BX // BX = |x|
+	MOVQ    $Big, CX // if |x| >= 2**52 or IsNaN(x), return x
+	CMPQ    BX, CX
+	JAE     isBig_ceil
+	MOVQ	AX, X0 // X0 = x
+	MOVQ	DX, X2 // X2 = sign bit mask
+	CVTTSD2SQ	X0, AX
+	ANDNPD	X0, X2 // X2 = sign
+	CVTSQ2SD	AX, X1	// X1 = float(int(x))
+	CMPSD	X1, X0, 2 // compare LE; X0 = 0xffffffffffffffff or 0
+	ORPD	X2, X1 // if X1 = 0.0, incorporate sign
+	MOVSD	$1.0, X3
+	ANDNPD	X3, X0
+	ORPD	X2, X0 // if float(int(x)) <= x {X0 = 1} else {X0 = -0}
+	ADDSD	X1, X0
+	MOVSD	X0, r+8(FP)
+	RET
+isBig_ceil:
+	MOVQ	AX, r+8(FP)
+	RET
 
+// func Trunc(x float64) float64
 TEXT ·Trunc(SB),7,$0
-	JMP	·trunc(SB)
+	MOVQ	x+0(FP), AX
+	MOVQ	$~(1<<63), DX // sign bit mask
+	MOVQ	AX, BX // BX = copy of x
+	ANDQ    DX, BX // BX = |x|
+	MOVQ    $Big, CX // if |x| >= 2**52 or IsNaN(x), return x
+	CMPQ    BX, CX
+	JAE     isBig_trunc
+	MOVQ	AX, X0
+	MOVQ	DX, X2 // X2 = sign bit mask
+	CVTTSD2SQ	X0, AX
+	ANDNPD	X0, X2 // X2 = sign
+	CVTSQ2SD	AX, X0 // X0 = float(int(x))
+	ORPD	X2, X0 // if X0 = 0.0, incorporate sign
+	MOVSD	X0, r+8(FP)
+	RET
+isBig_trunc:
+	MOVQ    AX, r+8(FP) // return x
+	RET
diff --git a/src/pkg/math/frexp_386.s b/src/pkg/math/frexp_386.s
index 177c4b9..95e50de 100644
--- a/src/pkg/math/frexp_386.s
+++ b/src/pkg/math/frexp_386.s
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// func Frexp(x float64) (f float64, e int)
+// func Frexp(f float64) (frac float64, exp int)
 TEXT ·Frexp(SB),7,$0
-	FMOVD   x+0(FP), F0   // F0=x
+	FMOVD   f+0(FP), F0   // F0=f
 	FXAM
 	FSTSW   AX
 	SAHF
@@ -12,12 +12,12 @@ TEXT ·Frexp(SB),7,$0
 	JCS     nan_zero_inf
 	FXTRACT               // F0=f (0<=f<1), F1=e
 	FMULD  $(0.5), F0     // F0=f (0.5<=f<1), F1=e
-	FMOVDP  F0, f+8(FP)   // F0=e
+	FMOVDP  F0, frac+8(FP)   // F0=e
 	FLD1                  // F0=1, F1=e
 	FADDDP  F0, F1        // F0=e+1
-	FMOVLP  F0, e+16(FP)  // (int=int32)
+	FMOVLP  F0, exp+16(FP)  // (int=int32)
 	RET
 nan_zero_inf:
-	FMOVDP  F0, f+8(FP)   // F0=e
-	MOVL    $0, e+16(FP)  // e=0
+	FMOVDP  F0, frac+8(FP)   // F0=e
+	MOVL    $0, exp+16(FP)  // exp=0
 	RET
diff --git a/src/pkg/math/gamma.go b/src/pkg/math/gamma.go
index 7c6f421..164f54f 100644
--- a/src/pkg/math/gamma.go
+++ b/src/pkg/math/gamma.go
@@ -110,19 +110,26 @@ func stirling(x float64) float64 {
 	return y
 }
 
-// Gamma(x) returns the Gamma function of x.
+// Gamma returns the Gamma function of x.
 //
 // Special cases are:
-//	Gamma(±Inf) = ±Inf
+//	Gamma(+Inf) = +Inf
+//	Gamma(+0) = +Inf
+//	Gamma(-0) = -Inf
+//	Gamma(x) = NaN for integer x < 0
+//	Gamma(-Inf) = NaN
 //	Gamma(NaN) = NaN
-// Large values overflow to +Inf.
-// Zero and negative integer arguments return ±Inf.
 func Gamma(x float64) float64 {
 	const Euler = 0.57721566490153286060651209008240243104215933593992 // A001620
 	// special cases
 	switch {
-	case IsInf(x, -1) || IsNaN(x):
-		return x
+	case isNegInt(x) || IsInf(x, -1) || IsNaN(x):
+		return NaN()
+	case x == 0:
+		if Signbit(x) {
+			return Inf(-1)
+		}
+		return Inf(1)
 	case x < -170.5674972726612 || x > 171.61447887182298:
 		return Inf(1)
 	}
@@ -185,3 +192,11 @@ small:
 	}
 	return z / ((1 + Euler*x) * x)
 }
+
+func isNegInt(x float64) bool {
+	if x < 0 {
+		_, xf := Modf(x)
+		return xf == 0
+	}
+	return false
+}
diff --git a/src/pkg/math/hypot.go b/src/pkg/math/hypot.go
index df4d3eb..3846e6d 100644
--- a/src/pkg/math/hypot.go
+++ b/src/pkg/math/hypot.go
@@ -8,7 +8,7 @@ package math
 	Hypot -- sqrt(p*p + q*q), but overflows only if the result does.
 */
 
-// Hypot computes Sqrt(p*p + q*q), taking care to avoid
+// Hypot returns Sqrt(p*p + q*q), taking care to avoid
 // unnecessary overflow and underflow.
 //
 // Special cases are:
diff --git a/src/pkg/math/hypot_386.s b/src/pkg/math/hypot_386.s
index 70ff19a..51cd904 100644
--- a/src/pkg/math/hypot_386.s
+++ b/src/pkg/math/hypot_386.s
@@ -2,35 +2,35 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// func Hypot(x, y float64) float64
+// func Hypot(p, q float64) float64
 TEXT ·Hypot(SB),7,$0
 // test bits for not-finite
-	MOVL    xh+4(FP), AX   // high word x
+	MOVL    p+4(FP), AX   // high word p
 	ANDL    $0x7ff00000, AX
 	CMPL    AX, $0x7ff00000
 	JEQ     not_finite
-	MOVL    yh+12(FP), AX   // high word y
+	MOVL    q+12(FP), AX   // high word q
 	ANDL    $0x7ff00000, AX
 	CMPL    AX, $0x7ff00000
 	JEQ     not_finite
-	FMOVD   x+0(FP), F0  // F0=x
-	FABS                 // F0=|x|
-	FMOVD   y+8(FP), F0  // F0=y, F1=|x|
-	FABS                 // F0=|y|, F1=|x|
+	FMOVD   p+0(FP), F0  // F0=p
+	FABS                 // F0=|p|
+	FMOVD   q+8(FP), F0  // F0=q, F1=|p|
+	FABS                 // F0=|q|, F1=|p|
 	FUCOMI  F0, F1       // compare F0 to F1
 	JCC     2(PC)        // jump if F0 >= F1
-	FXCHD   F0, F1       // F0=|x| (larger), F1=|y| (smaller)
+	FXCHD   F0, F1       // F0=|p| (larger), F1=|q| (smaller)
 	FTST                 // compare F0 to 0
 	FSTSW	AX
 	ANDW    $0x4000, AX
 	JNE     10(PC)       // jump if F0 = 0
-	FXCHD   F0, F1       // F0=y (smaller), F1=x (larger)
-	FDIVD   F1, F0       // F0=y(=y/x), F1=x
-	FMULD   F0, F0       // F0=y*y, F1=x
-	FLD1                 // F0=1, F1=y*y, F2=x
-	FADDDP  F0, F1       // F0=1+y*y, F1=x
-	FSQRT                // F0=sqrt(1+y*y), F1=x
-	FMULDP  F0, F1       // F0=x*sqrt(1+y*y)
+	FXCHD   F0, F1       // F0=q (smaller), F1=p (larger)
+	FDIVD   F1, F0       // F0=q(=q/p), F1=p
+	FMULD   F0, F0       // F0=q*q, F1=p
+	FLD1                 // F0=1, F1=q*q, F2=p
+	FADDDP  F0, F1       // F0=1+q*q, F1=p
+	FSQRT                // F0=sqrt(1+q*q), F1=p
+	FMULDP  F0, F1       // F0=p*sqrt(1+q*q)
 	FMOVDP  F0, r+16(FP)
 	RET
 	FMOVDP  F0, F1       // F0=0
@@ -38,20 +38,20 @@ TEXT ·Hypot(SB),7,$0
 	RET
 not_finite:
 // test bits for -Inf or +Inf
-	MOVL    xh+4(FP), AX  // high word x
-	ORL     xl+0(FP), AX  // low word x
+	MOVL    p+4(FP), AX  // high word p
+	ORL     p+0(FP), AX  // low word p
 	ANDL    $0x7fffffff, AX
 	CMPL    AX, $0x7ff00000
 	JEQ     is_inf
-	MOVL    yh+12(FP), AX  // high word y
-	ORL     yl+8(FP), AX   // low word y
+	MOVL    q+12(FP), AX  // high word q
+	ORL     q+8(FP), AX   // low word q
 	ANDL    $0x7fffffff, AX
 	CMPL    AX, $0x7ff00000
 	JEQ     is_inf
-	MOVL    $0x7ff00000, rh+20(FP)  // return NaN = 0x7FF0000000000001
-	MOVL    $0x00000001, rl+16(FP)
+	MOVL    $0x7ff80000, r+20(FP)  // return NaN = 0x7FF8000000000001
+	MOVL    $0x00000001, r+16(FP)
 	RET
 is_inf:
-	MOVL    AX, rh+20(FP)  // return +Inf = 0x7FF0000000000000
-	MOVL    $0x00000000, rl+16(FP)
+	MOVL    AX, r+20(FP)  // return +Inf = 0x7FF0000000000000
+	MOVL    $0x00000000, r+16(FP)
 	RET
diff --git a/src/pkg/math/hypot_amd64.s b/src/pkg/math/hypot_amd64.s
index 1f691e7..02fff5b 100644
--- a/src/pkg/math/hypot_amd64.s
+++ b/src/pkg/math/hypot_amd64.s
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#define PosInf 0x7ff0000000000000
-#define NaN 0x7FF0000000000001
+#define PosInf 0x7FF0000000000000
+#define NaN 0x7FF8000000000001
 
-// func Hypot(x, y float64) float64
+// func Hypot(p, q float64) float64
 TEXT ·Hypot(SB),7,$0
 	// test bits for special cases
-	MOVQ    x+0(FP), BX
+	MOVQ    p+0(FP), BX
 	MOVQ    $~(1<<63), AX
-	ANDQ    AX, BX // x = |x|
-	MOVQ    y+8(FP), CX
-	ANDQ    AX, CX // y = |y|
+	ANDQ    AX, BX // p = |p|
+	MOVQ    q+8(FP), CX
+	ANDQ    AX, CX // q = |q|
 	MOVQ    $PosInf, AX
 	CMPQ    AX, BX
 	JLE     isInfOrNaN
diff --git a/src/pkg/math/ldexp_386.s b/src/pkg/math/ldexp_386.s
index ed91ffc..3a65629 100644
--- a/src/pkg/math/ldexp_386.s
+++ b/src/pkg/math/ldexp_386.s
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// func Ldexp(f float64, e int) float64
+// func Ldexp(frac float64, exp int) float64
 TEXT ·Ldexp(SB),7,$0
-	FMOVL   e+8(FP), F0   // F0=e
-	FMOVD   x+0(FP), F0   // F0=x, F1=e
+	FMOVL   exp+8(FP), F0   // F0=exp
+	FMOVD   frac+0(FP), F0   // F0=frac, F1=e
 	FSCALE                // F0=x*2**e, F1=e
 	FMOVDP  F0, F1        // F0=x*2**e
 	FMOVDP  F0, r+12(FP)
diff --git a/src/pkg/math/log10.go b/src/pkg/math/log10.go
index 67c163a..95cfbf4 100644
--- a/src/pkg/math/log10.go
+++ b/src/pkg/math/log10.go
@@ -17,5 +17,6 @@ func log10(x float64) float64 {
 func Log2(x float64) float64
 
 func log2(x float64) float64 {
-	return Log(x) * (1 / Ln2)
+	frac, exp := Frexp(x)
+	return Log(frac)*(1/Ln2) + float64(exp)
 }
diff --git a/src/pkg/math/log_amd64.s b/src/pkg/math/log_amd64.s
index 79e3590..75bc557 100644
--- a/src/pkg/math/log_amd64.s
+++ b/src/pkg/math/log_amd64.s
@@ -12,7 +12,7 @@
 #define L5     1.818357216161805012e-01   // 0x3FC7466496CB03DE
 #define L6     1.531383769920937332e-01   // 0x3FC39A09D078C69F
 #define L7     1.479819860511658591e-01   // 0x3FC2F112DF3E5244
-#define NaN    0x7FF0000000000001
+#define NaN    0x7FF8000000000001
 #define NegInf 0xFFF0000000000000
 #define PosInf 0x7FF0000000000000
 
@@ -54,13 +54,13 @@ TEXT ·Log(SB),7,$0
 	// s := f / (2 + f)
 	MOVSD   $2.0, X0
 	ADDSD   X2, X0
-	MOVSD   X2, X3
+	MOVAPD  X2, X3
 	DIVSD   X0, X3 // x1=k, x2= f, x3= s
 	// s2 := s * s
-	MOVSD   X3, X4 // x1= k, x2= f, x3= s
+	MOVAPD  X3, X4 // x1= k, x2= f, x3= s
 	MULSD   X4, X4 // x1= k, x2= f, x3= s, x4= s2
 	// s4 := s2 * s2
-	MOVSD   X4, X5 // x1= k, x2= f, x3= s, x4= s2
+	MOVAPD  X4, X5 // x1= k, x2= f, x3= s, x4= s2
 	MULSD   X5, X5 // x1= k, x2= f, x3= s, x4= s2, x5= s4
 	// t1 := s2 * (L1 + s4*(L3+s4*(L5+s4*L7)))
 	MOVSD   $L7, X6
diff --git a/src/pkg/math/logb.go b/src/pkg/math/logb.go
index d32f9f1..f2769d4 100644
--- a/src/pkg/math/logb.go
+++ b/src/pkg/math/logb.go
@@ -4,7 +4,7 @@
 
 package math
 
-// Logb(x) returns the binary exponent of x.
+// Logb returns the binary exponent of x.
 //
 // Special cases are:
 //	Logb(±Inf) = +Inf
@@ -23,7 +23,7 @@ func Logb(x float64) float64 {
 	return float64(ilogb(x))
 }
 
-// Ilogb(x) returns the binary exponent of x as an integer.
+// Ilogb returns the binary exponent of x as an integer.
 //
 // Special cases are:
 //	Ilogb(±Inf) = MaxInt32
diff --git a/src/pkg/math/modf_386.s b/src/pkg/math/modf_386.s
index 5ccab98..f5dc415 100644
--- a/src/pkg/math/modf_386.s
+++ b/src/pkg/math/modf_386.s
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// func Modf(x float64) (int float64, frac float64)
+// func Modf(f float64) (int float64, frac float64)
 TEXT ·Modf(SB),7,$0
-	FMOVD   x+0(FP), F0  // F0=x
-	FMOVD   F0, F1       // F0=x, F1=x
+	FMOVD   f+0(FP), F0  // F0=f
+	FMOVD   F0, F1       // F0=f, F1=f
 	FSTCW   -2(SP)       // save old Control Word
 	MOVW    -2(SP), AX
 	ORW     $0x0c00, AX  // Rounding Control set to truncate
 	MOVW    AX, -4(SP)   // store new Control Word
 	FLDCW   -4(SP)       // load new Control Word
-	FRNDINT              // F0=trunc(x), F1=x
+	FRNDINT              // F0=trunc(f), F1=f
 	FLDCW   -2(SP)       // load old Control Word
-	FSUBD   F0, F1       // F0=trunc(x), F1=x-trunc(x)
-	FMOVDP  F0, i+8(FP)  // F0=x-trunc(x)
-	FMOVDP  F0, f+16(FP)
+	FSUBD   F0, F1       // F0=trunc(f), F1=f-trunc(f)
+	FMOVDP  F0, int+8(FP)  // F0=f-trunc(f)
+	FMOVDP  F0, frac+16(FP)
 	RET
diff --git a/src/pkg/math/rand/example_test.go b/src/pkg/math/rand/example_test.go
new file mode 100644
index 0000000..4fe207d
--- /dev/null
+++ b/src/pkg/math/rand/example_test.go
@@ -0,0 +1,69 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rand_test
+
+import (
+	"fmt"
+	"math/rand"
+	"os"
+	"text/tabwriter"
+)
+
+// This test serves as an example but also makes sure we don't change
+// the output of the random number generator when given a fixed seed.
+
+// This example shows the use of each of the methods on a *Rand.
+// The use of the global functions is the same, without the receiver.
+func Example() {
+	// Create and seed the generator.
+	// Typically a non-fixed seed should be used, such as time.Now().UnixNano().
+	// Using a fixed seed will produce the same output on every run.
+	r := rand.New(rand.NewSource(99))
+
+	// The tabwriter here helps us generate aligned output.
+	w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
+	defer w.Flush()
+	show := func(name string, v1, v2, v3 interface{}) {
+		fmt.Fprintf(w, "%s\t%v\t%v\t%v\n", name, v1, v2, v3)
+	}
+
+	// Float32 and Float64 values are in [0, 1).
+	show("Float32", r.Float32(), r.Float32(), r.Float32())
+	show("Float64", r.Float64(), r.Float64(), r.Float64())
+
+	// ExpFloat64 values have an average of 1 but decay exponentially.
+	show("ExpFloat64", r.ExpFloat64(), r.ExpFloat64(), r.ExpFloat64())
+
+	// NormFloat64 values have an average of 0 and a standard deviation of 1.
+	show("NormFloat64", r.NormFloat64(), r.NormFloat64(), r.NormFloat64())
+
+	// Int31, Int63, and Uint32 generate values of the given width.
+	// The Int method (not shown) is like either Int31 or Int63
+	// depending on the size of 'int'.
+	show("Int31", r.Int31(), r.Int31(), r.Int31())
+	show("Int63", r.Int63(), r.Int63(), r.Int63())
+	show("Uint32", r.Int63(), r.Int63(), r.Int63())
+
+	// Intn, Int31n, and Int63n limit their output to be < n.
+	// They do so more carefully than using r.Int()%n.
+	show("Intn(10)", r.Intn(10), r.Intn(10), r.Intn(10))
+	show("Int31n(10)", r.Int31n(10), r.Int31n(10), r.Int31n(10))
+	show("Int63n(10)", r.Int63n(10), r.Int63n(10), r.Int63n(10))
+
+	// Perm generates a random permutation of the numbers [0, n).
+	show("Perm", r.Perm(5), r.Perm(5), r.Perm(5))
+	// Output:
+	// Float32     0.2635776           0.6358173           0.6718283
+	// Float64     0.628605430454327   0.4504798828572669  0.9562755949377957
+	// ExpFloat64  0.3362240648200941  1.4256072328483647  0.24354758816173044
+	// NormFloat64 0.17233959114940064 1.577014951434847   0.04259129641113857
+	// Int31       1501292890          1486668269          182840835
+	// Int63       3546343826724305832 5724354148158589552 5239846799706671610
+	// Uint32      5927547564735367388 637072299495207830  4128311955958246186
+	// Intn(10)    1                   2                   5
+	// Int31n(10)  4                   7                   8
+	// Int63n(10)  7                   6                   3
+	// Perm        [1 4 2 3 0]         [4 2 1 3 0]         [1 2 4 0 3]
+}
diff --git a/src/pkg/math/rand/rand_test.go b/src/pkg/math/rand/rand_test.go
index bbd44e3..4d3abdb 100644
--- a/src/pkg/math/rand/rand_test.go
+++ b/src/pkg/math/rand/rand_test.go
@@ -57,16 +57,13 @@ func (this *statsResults) checkSimilarDistribution(expected *statsResults) error
 
 func getStatsResults(samples []float64) *statsResults {
 	res := new(statsResults)
-	var sum float64
-	for i := range samples {
-		sum += samples[i]
+	var sum, squaresum float64
+	for _, s := range samples {
+		sum += s
+		squaresum += s * s
 	}
 	res.mean = sum / float64(len(samples))
-	var devsum float64
-	for i := range samples {
-		devsum += math.Pow(samples[i]-res.mean, 2)
-	}
-	res.stddev = math.Sqrt(devsum / float64(len(samples)))
+	res.stddev = math.Sqrt(squaresum/float64(len(samples)) - res.mean*res.mean)
 	return res
 }
 
diff --git a/src/pkg/math/remainder.go b/src/pkg/math/remainder.go
index 41efd79..9a4e415 100644
--- a/src/pkg/math/remainder.go
+++ b/src/pkg/math/remainder.go
@@ -4,7 +4,7 @@
 
 package math
 
-// The original C code and the the comment below are from
+// The original C code and the comment below are from
 // FreeBSD's /usr/src/lib/msun/src/e_remainder.c and came
 // with this notice.  The go code is a simplified version of
 // the original C.
diff --git a/src/pkg/math/sincos.go b/src/pkg/math/sincos.go
index 7300429..7180303 100644
--- a/src/pkg/math/sincos.go
+++ b/src/pkg/math/sincos.go
@@ -6,7 +6,7 @@ package math
 
 // Coefficients _sin[] and _cos[] are found in pkg/math/sin.go.
 
-// Sincos(x) returns Sin(x), Cos(x).
+// Sincos returns Sin(x), Cos(x).
 //
 // Special cases are:
 //	Sincos(±0) = ±0, 1
diff --git a/src/pkg/math/sincos_386.s b/src/pkg/math/sincos_386.s
index 9dd37a3..8f5e0f8 100644
--- a/src/pkg/math/sincos_386.s
+++ b/src/pkg/math/sincos_386.s
@@ -9,8 +9,8 @@ TEXT ·Sincos(SB),7,$0
 	FSTSW   AX           // AX=status word
 	ANDW    $0x0400, AX
 	JNE     4(PC)        // jump if x outside range
-	FMOVDP  F0, c+16(FP) // F0=sin(x)
-	FMOVDP  F0, s+8(FP)
+	FMOVDP  F0, cos+16(FP) // F0=sin(x)
+	FMOVDP  F0, sin+8(FP)
 	RET
 	FLDPI                // F0=Pi, F1=x
 	FADDD   F0, F0       // F0=2*Pi, F1=x
@@ -21,6 +21,6 @@ TEXT ·Sincos(SB),7,$0
 	JNE     -3(PC)       // jump if reduction incomplete
 	FMOVDP  F0, F1       // F0=reduced_x
 	FSINCOS              // F0=cos(reduced_x), F1=sin(reduced_x)
-	FMOVDP  F0, c+16(FP) // F0=sin(reduced_x)
-	FMOVDP  F0, s+8(FP)
+	FMOVDP  F0, cos+16(FP) // F0=sin(reduced_x)
+	FMOVDP  F0, sin+8(FP)
 	RET
diff --git a/src/pkg/math/sincos_amd64.s b/src/pkg/math/sincos_amd64.s
index 18c824e..c9dea09 100644
--- a/src/pkg/math/sincos_amd64.s
+++ b/src/pkg/math/sincos_amd64.s
@@ -19,7 +19,7 @@
 
 #define PosOne 0x3FF0000000000000
 #define PosInf 0x7FF0000000000000
-#define NaN    0x7FF0000000000001
+#define NaN    0x7FF8000000000001
 #define PI4A 0.7853981554508209228515625 // pi/4 split into three parts
 #define PI4B 0.794662735614792836713604629039764404296875e-8
 #define PI4C 0.306161699786838294306516483068750264552437361480769e-16
diff --git a/src/pkg/math/tanh.go b/src/pkg/math/tanh.go
index 03a641b..7305be6 100644
--- a/src/pkg/math/tanh.go
+++ b/src/pkg/math/tanh.go
@@ -4,12 +4,66 @@
 
 package math
 
-/*
-	Floating-point hyperbolic tangent.
+// The original C code, the long comment, and the constants
+// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
+// available from http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a simplified version of the original C.
+//      tanh.c
+//
+//      Hyperbolic tangent
+//
+// SYNOPSIS:
+//
+// double x, y, tanh();
+//
+// y = tanh( x );
+//
+// DESCRIPTION:
+//
+// Returns hyperbolic tangent of argument in the range MINLOG to MAXLOG.
+//      MAXLOG = 8.8029691931113054295988e+01 = log(2**127)
+//      MINLOG = -8.872283911167299960540e+01 = log(2**-128)
+//
+// A rational function is used for |x| < 0.625.  The form
+// x + x**3 P(x)/Q(x) of Cody & Waite is employed.
+// Otherwise,
+//      tanh(x) = sinh(x)/cosh(x) = 1  -  2/(exp(2x) + 1).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    IEEE      -2,2        30000       2.5e-16     5.8e-17
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+//
 
-	Sinh and Cosh are called except for large arguments, which
-	would cause overflow improperly.
-*/
+var tanhP = [...]float64{
+	-9.64399179425052238628E-1,
+	-9.92877231001918586564E1,
+	-1.61468768441708447952E3,
+}
+var tanhQ = [...]float64{
+	1.12811678491632931402E2,
+	2.23548839060100448583E3,
+	4.84406305325125486048E3,
+}
 
 // Tanh computes the hyperbolic tangent of x.
 //
@@ -18,15 +72,26 @@ package math
 //	Tanh(±Inf) = ±1
 //	Tanh(NaN) = NaN
 func Tanh(x float64) float64 {
-	if x < 0 {
-		x = -x
-		if x > 21 {
+	const MAXLOG = 8.8029691931113054295988e+01 // log(2**127)
+	z := Abs(x)
+	switch {
+	case z > 0.5*MAXLOG:
+		if x < 0 {
 			return -1
 		}
-		return -Sinh(x) / Cosh(x)
-	}
-	if x > 21 {
 		return 1
+	case z >= 0.625:
+		s := Exp(2 * z)
+		z = 1 - 2/(s+1)
+		if x < 0 {
+			z = -z
+		}
+	default:
+		if x == 0 {
+			return x
+		}
+		s := x * x
+		z = x + x*s*((tanhP[0]*s+tanhP[1])*s+tanhP[2])/(((s+tanhQ[0])*s+tanhQ[1])*s+tanhQ[2])
 	}
-	return Sinh(x) / Cosh(x)
+	return z
 }
diff --git a/src/pkg/mime/grammar.go b/src/pkg/mime/grammar.go
index 83cc411..09e941e 100644
--- a/src/pkg/mime/grammar.go
+++ b/src/pkg/mime/grammar.go
@@ -22,7 +22,7 @@ func isTokenChar(r rune) bool {
 	return r > 0x20 && r < 0x7f && !isTSpecial(r)
 }
 
-// isToken returns true if s is a 'token' as as defined by RFC 1521
+// isToken returns true if s is a 'token' as defined by RFC 1521
 // and RFC 2045.
 func isToken(s string) bool {
 	if s == "" {
diff --git a/src/pkg/mime/multipart/multipart.go b/src/pkg/mime/multipart/multipart.go
index e9e337b..77e969b 100644
--- a/src/pkg/mime/multipart/multipart.go
+++ b/src/pkg/mime/multipart/multipart.go
@@ -37,6 +37,11 @@ type Part struct {
 
 	disposition       string
 	dispositionParams map[string]string
+
+	// r is either a reader directly reading from mr, or it's a
+	// wrapper around such a reader, decoding the
+	// Content-Transfer-Encoding
+	r io.Reader
 }
 
 // FormName returns the name parameter if p has a Content-Disposition
@@ -71,7 +76,7 @@ func (p *Part) parseContentDisposition() {
 	}
 }
 
-// NewReader creates a new multipart Reader reading from r using the
+// NewReader creates a new multipart Reader reading from reader using the
 // given MIME boundary.
 func NewReader(reader io.Reader, boundary string) *Reader {
 	b := []byte("\r\n--" + boundary + "--")
@@ -94,6 +99,12 @@ func newPart(mr *Reader) (*Part, error) {
 	if err := bp.populateHeaders(); err != nil {
 		return nil, err
 	}
+	bp.r = partReader{bp}
+	const cte = "Content-Transfer-Encoding"
+	if bp.Header.Get(cte) == "quoted-printable" {
+		bp.Header.Del(cte)
+		bp.r = newQuotedPrintableReader(bp.r)
+	}
 	return bp, nil
 }
 
@@ -109,6 +120,17 @@ func (bp *Part) populateHeaders() error {
 // Read reads the body of a part, after its headers and before the
 // next part (if any) begins.
 func (p *Part) Read(d []byte) (n int, err error) {
+	return p.r.Read(d)
+}
+
+// partReader implements io.Reader by reading raw bytes directly from the
+// wrapped *Part, without doing any Transfer-Encoding decoding.
+type partReader struct {
+	p *Part
+}
+
+func (pr partReader) Read(d []byte) (n int, err error) {
+	p := pr.p
 	defer func() {
 		p.bytesRead += n
 	}()
diff --git a/src/pkg/mime/multipart/multipart_test.go b/src/pkg/mime/multipart/multipart_test.go
index cd65e17..d662e83 100644
--- a/src/pkg/mime/multipart/multipart_test.go
+++ b/src/pkg/mime/multipart/multipart_test.go
@@ -339,9 +339,10 @@ func TestLineContinuation(t *testing.T) {
 		if err != nil {
 			t.Fatalf("didn't get a part")
 		}
-		n, err := io.Copy(ioutil.Discard, part)
+		var buf bytes.Buffer
+		n, err := io.Copy(&buf, part)
 		if err != nil {
-			t.Errorf("error reading part: %v", err)
+			t.Errorf("error reading part: %v\nread so far: %q", err, buf.String())
 		}
 		if n <= 0 {
 			t.Errorf("read %d bytes; expected >0", n)
@@ -349,6 +350,29 @@ func TestLineContinuation(t *testing.T) {
 	}
 }
 
+func TestQuotedPrintableEncoding(t *testing.T) {
+	// From http://golang.org/issue/4411
+	body := "--0016e68ee29c5d515f04cedf6733\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=text\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nwords words words words words words words words words words words words wor=\r\nds words words words words words words words words words words words words =\r\nwords words words words words words words words words words words words wor=\r\nds words words words words words words words words words words words words =\r\nwords words words words words words words words words\r\n--0016e68ee29c5d515f04cedf6733\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=submit\r\n\r\nSubmit\r\n--0016e68ee29c5d515f04cedf6733--"
+	r := NewReader(strings.NewReader(body), "0016e68ee29c5d515f04cedf6733")
+	part, err := r.NextPart()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if te, ok := part.Header["Content-Transfer-Encoding"]; ok {
+		t.Errorf("unexpected Content-Transfer-Encoding of %q", te)
+	}
+	var buf bytes.Buffer
+	_, err = io.Copy(&buf, part)
+	if err != nil {
+		t.Error(err)
+	}
+	got := buf.String()
+	want := "words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words"
+	if got != want {
+		t.Errorf("wrong part value:\n got: %q\nwant: %q", got, want)
+	}
+}
+
 // Test parsing an image attachment from gmail, which previously failed.
 func TestNested(t *testing.T) {
 	// nested-mime is the body part of a multipart/mixed email
diff --git a/src/pkg/mime/multipart/quotedprintable.go b/src/pkg/mime/multipart/quotedprintable.go
new file mode 100644
index 0000000..9e18e1e
--- /dev/null
+++ b/src/pkg/mime/multipart/quotedprintable.go
@@ -0,0 +1,130 @@
+// 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.
+
+// The file define a quoted-printable decoder, as specified in RFC 2045.
+// Deviations:
+// 1. in addition to "=\r\n", "=\n" is also treated as soft line break.
+// 2. it will pass through a '\r' or '\n' not preceded by '=', consistent
+//    with other broken QP encoders & decoders.
+
+package multipart
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+)
+
+type qpReader struct {
+	br        *bufio.Reader
+	skipWhite bool
+	rerr      error  // last read error
+	line      []byte // to be consumed before more of br
+}
+
+func newQuotedPrintableReader(r io.Reader) io.Reader {
+	return &qpReader{
+		br:        bufio.NewReader(r),
+		skipWhite: true,
+	}
+}
+
+func fromHex(b byte) (byte, error) {
+	switch {
+	case b >= '0' && b <= '9':
+		return b - '0', nil
+	case b >= 'A' && b <= 'F':
+		return b - 'A' + 10, nil
+	}
+	return 0, fmt.Errorf("multipart: invalid quoted-printable hex byte 0x%02x", b)
+}
+
+func (q *qpReader) readHexByte(v []byte) (b byte, err error) {
+	if len(v) < 2 {
+		return 0, io.ErrUnexpectedEOF
+	}
+	var hb, lb byte
+	if hb, err = fromHex(v[0]); err != nil {
+		return 0, err
+	}
+	if lb, err = fromHex(v[1]); err != nil {
+		return 0, err
+	}
+	return hb<<4 | lb, nil
+}
+
+func isQPSkipWhiteByte(b byte) bool {
+	return b == ' ' || b == '\t'
+}
+
+func isQPDiscardWhitespace(r rune) bool {
+	switch r {
+	case '\n', '\r', ' ', '\t':
+		return true
+	}
+	return false
+}
+
+var (
+	crlf       = []byte("\r\n")
+	lf         = []byte("\n")
+	softSuffix = []byte("=")
+)
+
+func (q *qpReader) Read(p []byte) (n int, err error) {
+	for len(p) > 0 {
+		if len(q.line) == 0 {
+			if q.rerr != nil {
+				return n, q.rerr
+			}
+			q.skipWhite = true
+			q.line, q.rerr = q.br.ReadSlice('\n')
+
+			// Does the line end in CRLF instead of just LF?
+			hasLF := bytes.HasSuffix(q.line, lf)
+			hasCR := bytes.HasSuffix(q.line, crlf)
+			wholeLine := q.line
+			q.line = bytes.TrimRightFunc(wholeLine, isQPDiscardWhitespace)
+			if bytes.HasSuffix(q.line, softSuffix) {
+				rightStripped := wholeLine[len(q.line):]
+				q.line = q.line[:len(q.line)-1]
+				if !bytes.HasPrefix(rightStripped, lf) && !bytes.HasPrefix(rightStripped, crlf) {
+					q.rerr = fmt.Errorf("multipart: invalid bytes after =: %q", rightStripped)
+				}
+			} else if hasLF {
+				if hasCR {
+					q.line = append(q.line, '\r', '\n')
+				} else {
+					q.line = append(q.line, '\n')
+				}
+			}
+			continue
+		}
+		b := q.line[0]
+		if q.skipWhite && isQPSkipWhiteByte(b) {
+			q.line = q.line[1:]
+			continue
+		}
+		q.skipWhite = false
+
+		switch {
+		case b == '=':
+			b, err = q.readHexByte(q.line[1:])
+			if err != nil {
+				return n, err
+			}
+			q.line = q.line[2:] // 2 of the 3; other 1 is done below
+		case b == '\t' || b == '\r' || b == '\n':
+			break
+		case b < ' ' || b > '~':
+			return n, fmt.Errorf("multipart: invalid unescaped byte 0x%02x in quoted-printable body", b)
+		}
+		p[0] = b
+		p = p[1:]
+		q.line = q.line[1:]
+		n++
+	}
+	return n, nil
+}
diff --git a/src/pkg/mime/multipart/quotedprintable_test.go b/src/pkg/mime/multipart/quotedprintable_test.go
new file mode 100644
index 0000000..7bcf576
--- /dev/null
+++ b/src/pkg/mime/multipart/quotedprintable_test.go
@@ -0,0 +1,199 @@
+// 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 multipart
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"os/exec"
+	"regexp"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+)
+
+func TestQuotedPrintable(t *testing.T) {
+	tests := []struct {
+		in, want string
+		err      interface{}
+	}{
+		{in: "", want: ""},
+		{in: "foo bar", want: "foo bar"},
+		{in: "foo bar=3D", want: "foo bar="},
+		{in: "foo bar=\n", want: "foo bar"},
+		{in: "foo bar\n", want: "foo bar\n"}, // somewhat lax.
+		{in: "foo bar=0", want: "foo bar", err: io.ErrUnexpectedEOF},
+		{in: "foo bar=ab", want: "foo bar", err: "multipart: invalid quoted-printable hex byte 0x61"},
+		{in: "foo bar=0D=0A", want: "foo bar\r\n"},
+		{in: " A B =\r\n C ", want: "A B C"},
+		{in: " A B =\n C ", want: "A B C"}, // lax. treating LF as CRLF
+		{in: "foo=\nbar", want: "foobar"},
+		{in: "foo\x00bar", want: "foo", err: "multipart: invalid unescaped byte 0x00 in quoted-printable body"},
+		{in: "foo bar\xff", want: "foo bar", err: "multipart: invalid unescaped byte 0xff in quoted-printable body"},
+
+		// Equal sign.
+		{in: "=3D30\n", want: "=30\n"},
+		{in: "=00=FF0=\n", want: "\x00\xff0"},
+
+		// Trailing whitespace
+		{in: "foo  \n", want: "foo\n"},
+		{in: "foo  \n\nfoo =\n\nfoo=20\n\n", want: "foo\n\nfoo \nfoo \n\n"},
+
+		// Tests that we allow bare \n and \r through, despite it being strictly
+		// not permitted per RFC 2045, Section 6.7 Page 22 bullet (4).
+		{in: "foo\nbar", want: "foo\nbar"},
+		{in: "foo\rbar", want: "foo\rbar"},
+		{in: "foo\r\nbar", want: "foo\r\nbar"},
+
+		// Different types of soft line-breaks.
+		{in: "foo=\r\nbar", want: "foobar"},
+		{in: "foo=\nbar", want: "foobar"},
+		{in: "foo=\rbar", want: "foo", err: "multipart: invalid quoted-printable hex byte 0x0d"},
+		{in: "foo=\r\r\r \nbar", want: "foo", err: `multipart: invalid bytes after =: "\r\r\r \n"`},
+	}
+	for _, tt := range tests {
+		var buf bytes.Buffer
+		_, err := io.Copy(&buf, newQuotedPrintableReader(strings.NewReader(tt.in)))
+		if got := buf.String(); got != tt.want {
+			t.Errorf("for %q, got %q; want %q", tt.in, got, tt.want)
+		}
+		switch verr := tt.err.(type) {
+		case nil:
+			if err != nil {
+				t.Errorf("for %q, got unexpected error: %v", tt.in, err)
+			}
+		case string:
+			if got := fmt.Sprint(err); got != verr {
+				t.Errorf("for %q, got error %q; want %q", tt.in, got, verr)
+			}
+		case error:
+			if err != verr {
+				t.Errorf("for %q, got error %q; want %q", tt.in, err, verr)
+			}
+		}
+	}
+
+}
+
+func everySequence(base, alpha string, length int, fn func(string)) {
+	if len(base) == length {
+		fn(base)
+		return
+	}
+	for i := 0; i < len(alpha); i++ {
+		everySequence(base+alpha[i:i+1], alpha, length, fn)
+	}
+}
+
+var useQprint = flag.Bool("qprint", false, "Compare against the 'qprint' program.")
+
+var badSoftRx = regexp.MustCompile(`=([^\r\n]+?\n)|([^\r\n]+$)|(\r$)|(\r[^\n]+\n)|( \r\n)`)
+
+func TestQPExhaustive(t *testing.T) {
+	if *useQprint {
+		_, err := exec.LookPath("qprint")
+		if err != nil {
+			t.Fatalf("Error looking for qprint: %v", err)
+		}
+	}
+
+	var buf bytes.Buffer
+	res := make(map[string]int)
+	everySequence("", "0A \r\n=", 6, func(s string) {
+		if strings.HasSuffix(s, "=") || strings.Contains(s, "==") {
+			return
+		}
+		buf.Reset()
+		_, err := io.Copy(&buf, newQuotedPrintableReader(strings.NewReader(s)))
+		if err != nil {
+			errStr := err.Error()
+			if strings.Contains(errStr, "invalid bytes after =:") {
+				errStr = "invalid bytes after ="
+			}
+			res[errStr]++
+			if strings.Contains(errStr, "invalid quoted-printable hex byte ") {
+				if strings.HasSuffix(errStr, "0x20") && (strings.Contains(s, "=0 ") || strings.Contains(s, "=A ") || strings.Contains(s, "= ")) {
+					return
+				}
+				if strings.HasSuffix(errStr, "0x3d") && (strings.Contains(s, "=0=") || strings.Contains(s, "=A=")) {
+					return
+				}
+				if strings.HasSuffix(errStr, "0x0a") || strings.HasSuffix(errStr, "0x0d") {
+					// bunch of cases; since whitespace at the end of of a line before \n is removed.
+					return
+				}
+			}
+			if strings.Contains(errStr, "unexpected EOF") {
+				return
+			}
+			if errStr == "invalid bytes after =" && badSoftRx.MatchString(s) {
+				return
+			}
+			t.Errorf("decode(%q) = %v", s, err)
+			return
+		}
+		if *useQprint {
+			cmd := exec.Command("qprint", "-d")
+			cmd.Stdin = strings.NewReader(s)
+			stderr, err := cmd.StderrPipe()
+			if err != nil {
+				panic(err)
+			}
+			qpres := make(chan interface{}, 2)
+			go func() {
+				br := bufio.NewReader(stderr)
+				s, _ := br.ReadString('\n')
+				if s != "" {
+					qpres <- errors.New(s)
+					if cmd.Process != nil {
+						// It can get stuck on invalid input, like:
+						// echo -n "0000= " | qprint -d
+						cmd.Process.Kill()
+					}
+				}
+			}()
+			go func() {
+				want, err := cmd.Output()
+				if err == nil {
+					qpres <- want
+				}
+			}()
+			select {
+			case got := <-qpres:
+				if want, ok := got.([]byte); ok {
+					if string(want) != buf.String() {
+						t.Errorf("go decode(%q) = %q; qprint = %q", s, want, buf.String())
+					}
+				} else {
+					t.Logf("qprint -d(%q) = %v", s, got)
+				}
+			case <-time.After(5 * time.Second):
+				t.Logf("qprint timeout on %q", s)
+			}
+		}
+		res["OK"]++
+	})
+	var outcomes []string
+	for k, v := range res {
+		outcomes = append(outcomes, fmt.Sprintf("%v: %d", k, v))
+	}
+	sort.Strings(outcomes)
+	got := strings.Join(outcomes, "\n")
+	want := `OK: 21576
+invalid bytes after =: 3397
+multipart: invalid quoted-printable hex byte 0x0a: 1400
+multipart: invalid quoted-printable hex byte 0x0d: 2700
+multipart: invalid quoted-printable hex byte 0x20: 2490
+multipart: invalid quoted-printable hex byte 0x3d: 440
+unexpected EOF: 3122`
+	if got != want {
+		t.Errorf("Got:\n%s\nWant:\n%s", got, want)
+	}
+}
diff --git a/src/pkg/mime/multipart/testdata/nested-mime b/src/pkg/mime/multipart/testdata/nested-mime
old mode 100755
new mode 100644
diff --git a/src/pkg/mime/multipart/writer.go b/src/pkg/mime/multipart/writer.go
index ec70be4..e13a956 100644
--- a/src/pkg/mime/multipart/writer.go
+++ b/src/pkg/mime/multipart/writer.go
@@ -30,11 +30,38 @@ func NewWriter(w io.Writer) *Writer {
 	}
 }
 
-// Boundary returns the Writer's randomly selected boundary string.
+// Boundary returns the Writer's boundary.
 func (w *Writer) Boundary() string {
 	return w.boundary
 }
 
+// SetBoundary overrides the Writer's default randomly-generated
+// boundary separator with an explicit value.
+//
+// SetBoundary must be called before any parts are created, may only
+// contain certain ASCII characters, and must be 1-69 bytes long.
+func (w *Writer) SetBoundary(boundary string) error {
+	if w.lastpart != nil {
+		return errors.New("mime: SetBoundary called after write")
+	}
+	// rfc2046#section-5.1.1
+	if len(boundary) < 1 || len(boundary) > 69 {
+		return errors.New("mime: invalid boundary length")
+	}
+	for _, b := range boundary {
+		if 'A' <= b && b <= 'Z' || 'a' <= b && b <= 'z' || '0' <= b && b <= '9' {
+			continue
+		}
+		switch b {
+		case '\'', '(', ')', '+', '_', ',', '-', '.', '/', ':', '=', '?':
+			continue
+		}
+		return errors.New("mime: invalid boundary character")
+	}
+	w.boundary = boundary
+	return nil
+}
+
 // FormDataContentType returns the Content-Type for an HTTP
 // multipart/form-data with this Writer's Boundary.
 func (w *Writer) FormDataContentType() string {
diff --git a/src/pkg/mime/multipart/writer_test.go b/src/pkg/mime/multipart/writer_test.go
index 494e936..52d68bc 100644
--- a/src/pkg/mime/multipart/writer_test.go
+++ b/src/pkg/mime/multipart/writer_test.go
@@ -7,6 +7,7 @@ package multipart
 import (
 	"bytes"
 	"io/ioutil"
+	"strings"
 	"testing"
 )
 
@@ -76,3 +77,37 @@ func TestWriter(t *testing.T) {
 		t.Fatalf("expected end of parts; got %v, %v", part, err)
 	}
 }
+
+func TestWriterSetBoundary(t *testing.T) {
+	var b bytes.Buffer
+	w := NewWriter(&b)
+	tests := []struct {
+		b  string
+		ok bool
+	}{
+		{"abc", true},
+		{"", false},
+		{"ungültig", false},
+		{"!", false},
+		{strings.Repeat("x", 69), true},
+		{strings.Repeat("x", 70), false},
+		{"bad!ascii!", false},
+		{"my-separator", true},
+	}
+	for i, tt := range tests {
+		err := w.SetBoundary(tt.b)
+		got := err == nil
+		if got != tt.ok {
+			t.Errorf("%d. boundary %q = %v (%v); want %v", i, tt.b, got, err, tt.ok)
+		} else if tt.ok {
+			got := w.Boundary()
+			if got != tt.b {
+				t.Errorf("boundary = %q; want %q", got, tt.b)
+			}
+		}
+	}
+	w.Close()
+	if got := b.String(); !strings.Contains(got, "\r\n--my-separator--\r\n") {
+		t.Errorf("expected my-separator in output. got: %q", got)
+	}
+}
diff --git a/src/pkg/mime/test.types b/src/pkg/mime/testdata/test.types
similarity index 100%
rename from src/pkg/mime/test.types
rename to src/pkg/mime/testdata/test.types
diff --git a/src/pkg/mime/type_unix.go b/src/pkg/mime/type_unix.go
index 2dab1ea..857a0ab 100644
--- a/src/pkg/mime/type_unix.go
+++ b/src/pkg/mime/type_unix.go
@@ -23,15 +23,11 @@ func loadMimeFile(filename string) {
 	if err != nil {
 		return
 	}
+	defer f.Close()
 
-	reader := bufio.NewReader(f)
-	for {
-		line, err := reader.ReadString('\n')
-		if err != nil {
-			f.Close()
-			return
-		}
-		fields := strings.Fields(line)
+	scanner := bufio.NewScanner(f)
+	for scanner.Scan() {
+		fields := strings.Fields(scanner.Text())
 		if len(fields) <= 1 || fields[0][0] == '#' {
 			continue
 		}
@@ -43,6 +39,9 @@ func loadMimeFile(filename string) {
 			setExtensionType("."+ext, mimeType)
 		}
 	}
+	if err := scanner.Err(); err != nil {
+		panic(err)
+	}
 }
 
 func initMime() {
@@ -52,7 +51,7 @@ func initMime() {
 }
 
 func initMimeForTests() map[string]string {
-	typeFiles = []string{"test.types"}
+	typeFiles = []string{"testdata/test.types"}
 	return map[string]string{
 		".t1":  "application/test",
 		".t2":  "text/test; charset=utf-8",
diff --git a/src/pkg/mime/type_windows.go b/src/pkg/mime/type_windows.go
index bc38889..180f948 100644
--- a/src/pkg/mime/type_windows.go
+++ b/src/pkg/mime/type_windows.go
@@ -11,7 +11,8 @@ import (
 
 func initMime() {
 	var root syscall.Handle
-	if syscall.RegOpenKeyEx(syscall.HKEY_CLASSES_ROOT, syscall.StringToUTF16Ptr(`\`),
+	rootpathp, _ := syscall.UTF16PtrFromString(`\`)
+	if syscall.RegOpenKeyEx(syscall.HKEY_CLASSES_ROOT, rootpathp,
 		0, syscall.KEY_READ, &root) != nil {
 		return
 	}
@@ -31,15 +32,17 @@ func initMime() {
 			continue
 		}
 		var h syscall.Handle
+		extpathp, _ := syscall.UTF16PtrFromString(`\` + ext)
 		if syscall.RegOpenKeyEx(
-			syscall.HKEY_CLASSES_ROOT, syscall.StringToUTF16Ptr(`\`+ext),
+			syscall.HKEY_CLASSES_ROOT, extpathp,
 			0, syscall.KEY_READ, &h) != nil {
 			continue
 		}
 		var typ uint32
 		n = uint32(len(buf) * 2) // api expects array of bytes, not uint16
+		contenttypep, _ := syscall.UTF16PtrFromString("Content Type")
 		if syscall.RegQueryValueEx(
-			h, syscall.StringToUTF16Ptr("Content Type"),
+			h, contenttypep,
 			nil, &typ, (*byte)(unsafe.Pointer(&buf[0])), &n) != nil {
 			syscall.RegCloseKey(h)
 			continue
@@ -55,7 +58,6 @@ func initMime() {
 
 func initMimeForTests() map[string]string {
 	return map[string]string{
-		".bmp": "image/bmp",
 		".png": "image/png",
 	}
 }
diff --git a/src/pkg/net/cgo_bsd.go b/src/pkg/net/cgo_bsd.go
index 63750f7..3b38e3d 100644
--- a/src/pkg/net/cgo_bsd.go
+++ b/src/pkg/net/cgo_bsd.go
@@ -11,6 +11,6 @@ package net
 */
 import "C"
 
-func cgoAddrInfoMask() C.int {
-	return C.AI_MASK
+func cgoAddrInfoFlags() C.int {
+	return (C.AI_CANONNAME | C.AI_V4MAPPED | C.AI_ALL) & C.AI_MASK
 }
diff --git a/src/pkg/net/cgo_linux.go b/src/pkg/net/cgo_linux.go
index 8d4413d..f6cefa8 100644
--- a/src/pkg/net/cgo_linux.go
+++ b/src/pkg/net/cgo_linux.go
@@ -9,6 +9,12 @@ package net
 */
 import "C"
 
-func cgoAddrInfoMask() C.int {
+func cgoAddrInfoFlags() C.int {
+	// NOTE(rsc): In theory there are approximately balanced
+	// arguments for and against including AI_ADDRCONFIG
+	// in the flags (it includes IPv4 results only on IPv4 systems,
+	// and similarly for IPv6), but in practice setting it causes
+	// getaddrinfo to return the wrong canonical name on Linux.
+	// So definitely leave it out.
 	return C.AI_CANONNAME | C.AI_V4MAPPED | C.AI_ALL
 }
diff --git a/src/pkg/net/cgo_netbsd.go b/src/pkg/net/cgo_netbsd.go
new file mode 100644
index 0000000..aeaf8e5
--- /dev/null
+++ b/src/pkg/net/cgo_netbsd.go
@@ -0,0 +1,14 @@
+// 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 net
+
+/*
+#include <netdb.h>
+*/
+import "C"
+
+func cgoAddrInfoFlags() C.int {
+	return C.AI_CANONNAME
+}
diff --git a/src/pkg/net/cgo_openbsd.go b/src/pkg/net/cgo_openbsd.go
new file mode 100644
index 0000000..aeaf8e5
--- /dev/null
+++ b/src/pkg/net/cgo_openbsd.go
@@ -0,0 +1,14 @@
+// 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 net
+
+/*
+#include <netdb.h>
+*/
+import "C"
+
+func cgoAddrInfoFlags() C.int {
+	return C.AI_CANONNAME
+}
diff --git a/src/pkg/net/cgo_unix.go b/src/pkg/net/cgo_unix.go
index 36a3f3d..7476140 100644
--- a/src/pkg/net/cgo_unix.go
+++ b/src/pkg/net/cgo_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 freebsd linux
+// +build darwin freebsd linux netbsd openbsd
 
 package net
 
@@ -81,13 +81,7 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, complet
 	var res *C.struct_addrinfo
 	var hints C.struct_addrinfo
 
-	// NOTE(rsc): In theory there are approximately balanced
-	// arguments for and against including AI_ADDRCONFIG
-	// in the flags (it includes IPv4 results only on IPv4 systems,
-	// and similarly for IPv6), but in practice setting it causes
-	// getaddrinfo to return the wrong canonical name on Linux.
-	// So definitely leave it out.
-	hints.ai_flags = (C.AI_ALL | C.AI_V4MAPPED | C.AI_CANONNAME) & cgoAddrInfoMask()
+	hints.ai_flags = cgoAddrInfoFlags()
 
 	h := C.CString(name)
 	defer C.free(unsafe.Pointer(h))
diff --git a/src/pkg/net/conn_test.go b/src/pkg/net/conn_test.go
new file mode 100644
index 0000000..fdb9086
--- /dev/null
+++ b/src/pkg/net/conn_test.go
@@ -0,0 +1,114 @@
+// 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.
+
+// This file implements API tests across platforms and will never have a build
+// tag.
+
+package net
+
+import (
+	"os"
+	"runtime"
+	"testing"
+	"time"
+)
+
+var connTests = []struct {
+	net  string
+	addr string
+}{
+	{"tcp", "127.0.0.1:0"},
+	{"unix", testUnixAddr()},
+	{"unixpacket", testUnixAddr()},
+}
+
+// someTimeout is used just to test that net.Conn implementations
+// don't explode when their SetFooDeadline methods are called.
+// It isn't actually used for testing timeouts.
+const someTimeout = 10 * time.Second
+
+func TestConnAndListener(t *testing.T) {
+	for _, tt := range connTests {
+		switch tt.net {
+		case "unix", "unixpacket":
+			switch runtime.GOOS {
+			case "plan9", "windows":
+				continue
+			}
+			if tt.net == "unixpacket" && runtime.GOOS != "linux" {
+				continue
+			}
+		}
+
+		ln, err := Listen(tt.net, tt.addr)
+		if err != nil {
+			t.Fatalf("Listen failed: %v", err)
+		}
+		defer func(ln Listener, net, addr string) {
+			ln.Close()
+			switch net {
+			case "unix", "unixpacket":
+				os.Remove(addr)
+			}
+		}(ln, tt.net, tt.addr)
+		ln.Addr()
+
+		done := make(chan int)
+		go transponder(t, ln, done)
+
+		c, err := Dial(tt.net, ln.Addr().String())
+		if err != nil {
+			t.Fatalf("Dial failed: %v", err)
+		}
+		defer c.Close()
+		c.LocalAddr()
+		c.RemoteAddr()
+		c.SetDeadline(time.Now().Add(someTimeout))
+		c.SetReadDeadline(time.Now().Add(someTimeout))
+		c.SetWriteDeadline(time.Now().Add(someTimeout))
+
+		if _, err := c.Write([]byte("CONN TEST")); err != nil {
+			t.Fatalf("Conn.Write failed: %v", err)
+		}
+		rb := make([]byte, 128)
+		if _, err := c.Read(rb); err != nil {
+			t.Fatalf("Conn.Read failed: %v", err)
+		}
+
+		<-done
+	}
+}
+
+func transponder(t *testing.T, ln Listener, done chan<- int) {
+	defer func() { done <- 1 }()
+
+	switch ln := ln.(type) {
+	case *TCPListener:
+		ln.SetDeadline(time.Now().Add(someTimeout))
+	case *UnixListener:
+		ln.SetDeadline(time.Now().Add(someTimeout))
+	}
+	c, err := ln.Accept()
+	if err != nil {
+		t.Errorf("Listener.Accept failed: %v", err)
+		return
+	}
+	defer c.Close()
+	c.LocalAddr()
+	c.RemoteAddr()
+	c.SetDeadline(time.Now().Add(someTimeout))
+	c.SetReadDeadline(time.Now().Add(someTimeout))
+	c.SetWriteDeadline(time.Now().Add(someTimeout))
+
+	b := make([]byte, 128)
+	n, err := c.Read(b)
+	if err != nil {
+		t.Errorf("Conn.Read failed: %v", err)
+		return
+	}
+	if _, err := c.Write(b[:n]); err != nil {
+		t.Errorf("Conn.Write failed: %v", err)
+		return
+	}
+}
diff --git a/src/pkg/net/dial.go b/src/pkg/net/dial.go
index 10ca5fa..22e1e7d 100644
--- a/src/pkg/net/dial.go
+++ b/src/pkg/net/dial.go
@@ -5,15 +5,91 @@
 package net
 
 import (
+	"errors"
 	"time"
 )
 
-func parseDialNetwork(net string) (afnet string, proto int, err error) {
+// A DialOption modifies a DialOpt call.
+type DialOption interface {
+	dialOption()
+}
+
+var (
+	// TCP is a dial option to dial with TCP (over IPv4 or IPv6).
+	TCP = Network("tcp")
+
+	// UDP is a dial option to dial with UDP (over IPv4 or IPv6).
+	UDP = Network("udp")
+)
+
+// Network returns a DialOption to dial using the given network.
+//
+// Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
+// "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
+// (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and
+// "unixpacket".
+//
+// For IP networks, net must be "ip", "ip4" or "ip6" followed
+// by a colon and a protocol number or name, such as
+// "ipv4:1" or "ip6:ospf".
+func Network(net string) DialOption {
+	return dialNetwork(net)
+}
+
+type dialNetwork string
+
+func (dialNetwork) dialOption() {}
+
+// Deadline returns a DialOption to fail a dial that doesn't
+// complete before t.
+func Deadline(t time.Time) DialOption {
+	return dialDeadline(t)
+}
+
+// Timeout returns a DialOption to fail a dial that doesn't
+// complete within the provided duration.
+func Timeout(d time.Duration) DialOption {
+	return dialDeadline(time.Now().Add(d))
+}
+
+type dialDeadline time.Time
+
+func (dialDeadline) dialOption() {}
+
+type tcpFastOpen struct{}
+
+func (tcpFastOpen) dialOption() {}
+
+// TODO(bradfitz): implement this (golang.org/issue/4842) and unexport this.
+//
+// TCPFastTimeout returns an option to use TCP Fast Open (TFO) when
+// doing this dial. It is only valid for use with TCP connections.
+// Data sent over a TFO connection may be processed by the peer
+// multiple times, so should be used with caution.
+func todo_TCPFastTimeout() DialOption {
+	return tcpFastOpen{}
+}
+
+type localAddrOption struct {
+	la Addr
+}
+
+func (localAddrOption) dialOption() {}
+
+// LocalAddress returns a dial option to perform a dial with the
+// provided local address. The address must be of a compatible type
+// for the network being dialed.
+func LocalAddress(addr Addr) DialOption {
+	return localAddrOption{addr}
+}
+
+func parseNetwork(net string) (afnet string, proto int, err error) {
 	i := last(net, ':')
 	if i < 0 { // no colon
 		switch net {
 		case "tcp", "tcp4", "tcp6":
 		case "udp", "udp4", "udp6":
+		case "ip", "ip4", "ip6":
 		case "unix", "unixgram", "unixpacket":
 		default:
 			return "", 0, UnknownNetworkError(net)
@@ -36,40 +112,27 @@ func parseDialNetwork(net string) (afnet string, proto int, err error) {
 	return "", 0, UnknownNetworkError(net)
 }
 
-func resolveNetAddr(op, net, addr string) (afnet string, a Addr, err error) {
-	afnet, _, err = parseDialNetwork(net)
+func resolveAddr(op, net, addr string, deadline time.Time) (Addr, error) {
+	afnet, _, err := parseNetwork(net)
 	if err != nil {
-		return "", nil, &OpError{op, net, nil, err}
+		return nil, &OpError{op, net, nil, err}
 	}
 	if op == "dial" && addr == "" {
-		return "", nil, &OpError{op, net, nil, errMissingAddress}
+		return nil, &OpError{op, net, nil, errMissingAddress}
 	}
 	switch afnet {
-	case "tcp", "tcp4", "tcp6":
-		if addr != "" {
-			a, err = ResolveTCPAddr(afnet, addr)
-		}
-	case "udp", "udp4", "udp6":
-		if addr != "" {
-			a, err = ResolveUDPAddr(afnet, addr)
-		}
-	case "ip", "ip4", "ip6":
-		if addr != "" {
-			a, err = ResolveIPAddr(afnet, addr)
-		}
 	case "unix", "unixgram", "unixpacket":
-		if addr != "" {
-			a, err = ResolveUnixAddr(afnet, addr)
-		}
+		return ResolveUnixAddr(afnet, addr)
 	}
-	return
+	return resolveInternetAddr(afnet, addr, deadline)
 }
 
 // Dial connects to the address addr on the network net.
 //
 // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
 // "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
-// (IPv4-only), "ip6" (IPv6-only), "unix" and "unixpacket".
+// (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and
+// "unixpacket".
 //
 // For TCP and UDP networks, addresses have the form host:port.
 // If host is a literal IPv6 address, it must be enclosed
@@ -81,7 +144,7 @@ func resolveNetAddr(op, net, addr string) (afnet string, a Addr, err error) {
 //	Dial("tcp", "google.com:80")
 //	Dial("tcp", "[de:ad:be:ef::ca:fe]:80")
 //
-// For IP networks, addr must be "ip", "ip4" or "ip6" followed
+// For IP networks, net must be "ip", "ip4" or "ip6" followed
 // by a colon and a protocol number or name.
 //
 // Examples:
@@ -89,25 +152,71 @@ func resolveNetAddr(op, net, addr string) (afnet string, a Addr, err error) {
 //	Dial("ip6:ospf", "::1")
 //
 func Dial(net, addr string) (Conn, error) {
-	_, addri, err := resolveNetAddr("dial", net, addr)
+	return DialOpt(addr, dialNetwork(net))
+}
+
+func netFromOptions(opts []DialOption) string {
+	for _, opt := range opts {
+		if p, ok := opt.(dialNetwork); ok {
+			return string(p)
+		}
+	}
+	return "tcp"
+}
+
+func deadlineFromOptions(opts []DialOption) time.Time {
+	for _, opt := range opts {
+		if d, ok := opt.(dialDeadline); ok {
+			return time.Time(d)
+		}
+	}
+	return noDeadline
+}
+
+var noLocalAddr Addr // nil
+
+func localAddrFromOptions(opts []DialOption) Addr {
+	for _, opt := range opts {
+		if o, ok := opt.(localAddrOption); ok {
+			return o.la
+		}
+	}
+	return noLocalAddr
+}
+
+// DialOpt dials addr using the provided options.
+// If no options are provided, DialOpt(addr) is equivalent
+// to Dial("tcp", addr). See Dial for the syntax of addr.
+func DialOpt(addr string, opts ...DialOption) (Conn, error) {
+	net := netFromOptions(opts)
+	deadline := deadlineFromOptions(opts)
+	la := localAddrFromOptions(opts)
+	ra, err := resolveAddr("dial", net, addr, deadline)
 	if err != nil {
 		return nil, err
 	}
-	return dialAddr(net, addr, addri)
+	return dial(net, addr, la, ra, deadline)
 }
 
-func dialAddr(net, addr string, addri Addr) (c Conn, err error) {
-	switch ra := addri.(type) {
+func dial(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
+	if la != nil && la.Network() != ra.Network() {
+		return nil, &OpError{"dial", net, ra, errors.New("mismatched local addr type " + la.Network())}
+	}
+	switch ra := ra.(type) {
 	case *TCPAddr:
-		c, err = DialTCP(net, nil, ra)
+		la, _ := la.(*TCPAddr)
+		c, err = dialTCP(net, la, ra, deadline)
 	case *UDPAddr:
-		c, err = DialUDP(net, nil, ra)
+		la, _ := la.(*UDPAddr)
+		c, err = dialUDP(net, la, ra, deadline)
 	case *IPAddr:
-		c, err = DialIP(net, nil, ra)
+		la, _ := la.(*IPAddr)
+		c, err = dialIP(net, la, ra, deadline)
 	case *UnixAddr:
-		c, err = DialUnix(net, nil, ra)
+		la, _ := la.(*UnixAddr)
+		c, err = dialUnix(net, la, ra, deadline)
 	default:
-		err = &OpError{"dial", net + " " + addr, nil, UnknownNetworkError(net)}
+		err = &OpError{"dial", net + " " + addr, ra, UnknownNetworkError(net)}
 	}
 	if err != nil {
 		return nil, err
@@ -118,10 +227,14 @@ func dialAddr(net, addr string, addri Addr) (c Conn, err error) {
 // DialTimeout acts like Dial but takes a timeout.
 // The timeout includes name resolution, if required.
 func DialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
-	// TODO(bradfitz): the timeout should be pushed down into the
-	// net package's event loop, so on timeout to dead hosts we
-	// don't have a goroutine sticking around for the default of
-	// ~3 minutes.
+	return dialTimeout(net, addr, timeout)
+}
+
+// dialTimeoutRace is the old implementation of DialTimeout, still used
+// on operating systems where the deadline hasn't been pushed down
+// into the pollserver.
+// TODO: fix this on plan9.
+func dialTimeoutRace(net, addr string, timeout time.Duration) (Conn, error) {
 	t := time.NewTimer(timeout)
 	defer t.Stop()
 	type pair struct {
@@ -131,30 +244,30 @@ func DialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
 	ch := make(chan pair, 1)
 	resolvedAddr := make(chan Addr, 1)
 	go func() {
-		_, addri, err := resolveNetAddr("dial", net, addr)
+		ra, err := resolveAddr("dial", net, addr, noDeadline)
 		if err != nil {
 			ch <- pair{nil, err}
 			return
 		}
-		resolvedAddr <- addri // in case we need it for OpError
-		c, err := dialAddr(net, addr, addri)
+		resolvedAddr <- ra // in case we need it for OpError
+		c, err := dial(net, addr, noLocalAddr, ra, noDeadline)
 		ch <- pair{c, err}
 	}()
 	select {
 	case <-t.C:
 		// Try to use the real Addr in our OpError, if we resolved it
 		// before the timeout. Otherwise we just use stringAddr.
-		var addri Addr
+		var ra Addr
 		select {
 		case a := <-resolvedAddr:
-			addri = a
+			ra = a
 		default:
-			addri = &stringAddr{net, addr}
+			ra = &stringAddr{net, addr}
 		}
 		err := &OpError{
 			Op:   "dial",
 			Net:  net,
-			Addr: addri,
+			Addr: ra,
 			Err:  &timeoutError{},
 		}
 		return nil, err
@@ -173,24 +286,16 @@ func (a stringAddr) String() string  { return a.addr }
 
 // Listen announces on the local network address laddr.
 // The network string net must be a stream-oriented network:
-// "tcp", "tcp4", "tcp6", or "unix", or "unixpacket".
+// "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
 func Listen(net, laddr string) (Listener, error) {
-	afnet, a, err := resolveNetAddr("listen", net, laddr)
+	la, err := resolveAddr("listen", net, laddr, noDeadline)
 	if err != nil {
 		return nil, err
 	}
-	switch afnet {
-	case "tcp", "tcp4", "tcp6":
-		var la *TCPAddr
-		if a != nil {
-			la = a.(*TCPAddr)
-		}
+	switch la := la.(type) {
+	case *TCPAddr:
 		return ListenTCP(net, la)
-	case "unix", "unixpacket":
-		var la *UnixAddr
-		if a != nil {
-			la = a.(*UnixAddr)
-		}
+	case *UnixAddr:
 		return ListenUnix(net, la)
 	}
 	return nil, UnknownNetworkError(net)
@@ -199,30 +304,18 @@ func Listen(net, laddr string) (Listener, error) {
 // ListenPacket announces on the local network address laddr.
 // The network string net must be a packet-oriented network:
 // "udp", "udp4", "udp6", "ip", "ip4", "ip6" or "unixgram".
-func ListenPacket(net, addr string) (PacketConn, error) {
-	afnet, a, err := resolveNetAddr("listen", net, addr)
+func ListenPacket(net, laddr string) (PacketConn, error) {
+	la, err := resolveAddr("listen", net, laddr, noDeadline)
 	if err != nil {
 		return nil, err
 	}
-	switch afnet {
-	case "udp", "udp4", "udp6":
-		var la *UDPAddr
-		if a != nil {
-			la = a.(*UDPAddr)
-		}
+	switch la := la.(type) {
+	case *UDPAddr:
 		return ListenUDP(net, la)
-	case "ip", "ip4", "ip6":
-		var la *IPAddr
-		if a != nil {
-			la = a.(*IPAddr)
-		}
+	case *IPAddr:
 		return ListenIP(net, la)
-	case "unixgram":
-		var la *UnixAddr
-		if a != nil {
-			la = a.(*UnixAddr)
-		}
-		return DialUnix(net, la, nil)
+	case *UnixAddr:
+		return ListenUnixgram(net, la)
 	}
 	return nil, UnknownNetworkError(net)
 }
diff --git a/src/pkg/net/dial_test.go b/src/pkg/net/dial_test.go
index 7212087..2303e8f 100644
--- a/src/pkg/net/dial_test.go
+++ b/src/pkg/net/dial_test.go
@@ -7,6 +7,9 @@ package net
 import (
 	"flag"
 	"fmt"
+	"io"
+	"os"
+	"reflect"
 	"regexp"
 	"runtime"
 	"testing"
@@ -55,7 +58,7 @@ func TestDialTimeout(t *testing.T) {
 		// on our 386 builder, this Dial succeeds, connecting
 		// to an IIS web server somewhere.  The data center
 		// or VM or firewall must be stealing the TCP connection.
-		// 
+		//
 		// IANA Service Name and Transport Protocol Port Number Registry
 		// <http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml>
 		go func() {
@@ -72,8 +75,7 @@ func TestDialTimeout(t *testing.T) {
 		// by default. FreeBSD likely works, but is untested.
 		// TODO(rsc):
 		// The timeout never happens on Windows.  Why?  Issue 3016.
-		t.Logf("skipping test on %q; untested.", runtime.GOOS)
-		return
+		t.Skipf("skipping test on %q; untested.", runtime.GOOS)
 	}
 
 	connected := 0
@@ -105,8 +107,7 @@ func TestDialTimeout(t *testing.T) {
 func TestSelfConnect(t *testing.T) {
 	if runtime.GOOS == "windows" {
 		// TODO(brainman): do not know why it hangs.
-		t.Logf("skipping known-broken test on windows")
-		return
+		t.Skip("skipping known-broken test on windows")
 	}
 	// Test that Dial does not honor self-connects.
 	// See the comment in DialTCP.
@@ -130,7 +131,7 @@ func TestSelfConnect(t *testing.T) {
 		n = 1000
 	}
 	switch runtime.GOOS {
-	case "darwin", "freebsd", "openbsd", "windows":
+	case "darwin", "freebsd", "netbsd", "openbsd", "plan9", "windows":
 		// Non-Linux systems take a long time to figure
 		// out that there is nothing listening on localhost.
 		n = 100
@@ -222,3 +223,104 @@ func TestDialError(t *testing.T) {
 		}
 	}
 }
+
+var invalidDialAndListenArgTests = []struct {
+	net  string
+	addr string
+	err  error
+}{
+	{"foo", "bar", &OpError{Op: "dial", Net: "foo", Addr: nil, Err: UnknownNetworkError("foo")}},
+	{"baz", "", &OpError{Op: "listen", Net: "baz", Addr: nil, Err: UnknownNetworkError("baz")}},
+	{"tcp", "", &OpError{Op: "dial", Net: "tcp", Addr: nil, Err: errMissingAddress}},
+}
+
+func TestInvalidDialAndListenArgs(t *testing.T) {
+	for _, tt := range invalidDialAndListenArgTests {
+		var err error
+		switch tt.err.(*OpError).Op {
+		case "dial":
+			_, err = Dial(tt.net, tt.addr)
+		case "listen":
+			_, err = Listen(tt.net, tt.addr)
+		}
+		if !reflect.DeepEqual(tt.err, err) {
+			t.Fatalf("got %#v; expected %#v", err, tt.err)
+		}
+	}
+}
+
+func TestDialTimeoutFDLeak(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		// TODO(bradfitz): test on other platforms
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	type connErr struct {
+		conn Conn
+		err  error
+	}
+	dials := listenerBacklog + 100
+	// used to be listenerBacklog + 5, but was found to be unreliable, issue 4384.
+	maxGoodConnect := listenerBacklog + runtime.NumCPU()*10
+	resc := make(chan connErr)
+	for i := 0; i < dials; i++ {
+		go func() {
+			conn, err := DialTimeout("tcp", ln.Addr().String(), 500*time.Millisecond)
+			resc <- connErr{conn, err}
+		}()
+	}
+
+	var firstErr string
+	var ngood int
+	var toClose []io.Closer
+	for i := 0; i < dials; i++ {
+		ce := <-resc
+		if ce.err == nil {
+			ngood++
+			if ngood > maxGoodConnect {
+				t.Errorf("%d good connects; expected at most %d", ngood, maxGoodConnect)
+			}
+			toClose = append(toClose, ce.conn)
+			continue
+		}
+		err := ce.err
+		if firstErr == "" {
+			firstErr = err.Error()
+		} else if err.Error() != firstErr {
+			t.Fatalf("inconsistent error messages: first was %q, then later %q", firstErr, err)
+		}
+	}
+	for _, c := range toClose {
+		c.Close()
+	}
+	for i := 0; i < 100; i++ {
+		if got := numFD(); got < dials {
+			// Test passes.
+			return
+		}
+		time.Sleep(10 * time.Millisecond)
+	}
+	if got := numFD(); got >= dials {
+		t.Errorf("num fds after %d timeouts = %d; want <%d", dials, got, dials)
+	}
+}
+
+func numFD() int {
+	if runtime.GOOS == "linux" {
+		f, err := os.Open("/proc/self/fd")
+		if err != nil {
+			panic(err)
+		}
+		defer f.Close()
+		names, err := f.Readdirnames(0)
+		if err != nil {
+			panic(err)
+		}
+		return len(names)
+	}
+	// All tests using this should be skipped anyway, but:
+	panic("numFDs not implemented on " + runtime.GOOS)
+}
diff --git a/src/pkg/net/dialgoogle_test.go b/src/pkg/net/dialgoogle_test.go
index 03c4499..73a94f5 100644
--- a/src/pkg/net/dialgoogle_test.go
+++ b/src/pkg/net/dialgoogle_test.go
@@ -41,17 +41,6 @@ func doDial(t *testing.T, network, addr string) {
 	fd.Close()
 }
 
-func TestLookupCNAME(t *testing.T) {
-	if testing.Short() || !*testExternal {
-		t.Logf("skipping test to avoid external network")
-		return
-	}
-	cname, err := LookupCNAME("www.google.com")
-	if !strings.HasSuffix(cname, ".l.google.com.") || err != nil {
-		t.Errorf(`LookupCNAME("www.google.com.") = %q, %v, want "*.l.google.com.", nil`, cname, err)
-	}
-}
-
 var googleaddrsipv4 = []string{
 	"%d.%d.%d.%d:80",
 	"www.google.com:80",
@@ -67,8 +56,7 @@ var googleaddrsipv4 = []string{
 
 func TestDialGoogleIPv4(t *testing.T) {
 	if testing.Short() || !*testExternal {
-		t.Logf("skipping test to avoid external network")
-		return
+		t.Skip("skipping test to avoid external network")
 	}
 
 	// Insert an actual IPv4 address for google.com
@@ -123,12 +111,14 @@ var googleaddrsipv6 = []string{
 
 func TestDialGoogleIPv6(t *testing.T) {
 	if testing.Short() || !*testExternal {
-		t.Logf("skipping test to avoid external network")
-		return
+		t.Skip("skipping test to avoid external network")
 	}
 	// Only run tcp6 if the kernel will take it.
-	if !*testIPv6 || !supportsIPv6 {
-		return
+	if !supportsIPv6 {
+		t.Skip("skipping test; ipv6 is not supported")
+	}
+	if !*testIPv6 {
+		t.Skip("test disabled; use -ipv6 to enable")
 	}
 
 	// Insert an actual IPv6 address for ipv6.google.com
diff --git a/src/pkg/net/dnsclient.go b/src/pkg/net/dnsclient.go
index e69cb31..76b1926 100644
--- a/src/pkg/net/dnsclient.go
+++ b/src/pkg/net/dnsclient.go
@@ -183,7 +183,7 @@ func (s byPriorityWeight) Less(i, j int) bool {
 }
 
 // shuffleByWeight shuffles SRV records by weight using the algorithm
-// described in RFC 2782.  
+// described in RFC 2782.
 func (addrs byPriorityWeight) shuffleByWeight() {
 	sum := 0
 	for _, addr := range addrs {
@@ -244,3 +244,8 @@ func (s byPref) sort() {
 	}
 	sort.Sort(s)
 }
+
+// An NS represents a single DNS NS record.
+type NS struct {
+	Host string
+}
diff --git a/src/pkg/net/dnsclient_unix.go b/src/pkg/net/dnsclient_unix.go
index 18c3936..9e21bb4 100644
--- a/src/pkg/net/dnsclient_unix.go
+++ b/src/pkg/net/dnsclient_unix.go
@@ -237,24 +237,30 @@ func goLookupIP(name string) (addrs []IP, err error) {
 	}
 	var records []dnsRR
 	var cname string
-	cname, records, err = lookup(name, dnsTypeA)
-	if err != nil {
-		return
-	}
+	var err4, err6 error
+	cname, records, err4 = lookup(name, dnsTypeA)
 	addrs = convertRR_A(records)
 	if cname != "" {
 		name = cname
 	}
-	_, records, err = lookup(name, dnsTypeAAAA)
-	if err != nil && len(addrs) > 0 {
-		// Ignore error because A lookup succeeded.
-		err = nil
+	_, records, err6 = lookup(name, dnsTypeAAAA)
+	if err4 != nil && err6 == nil {
+		// Ignore A error because AAAA lookup succeeded.
+		err4 = nil
 	}
-	if err != nil {
-		return
+	if err6 != nil && len(addrs) > 0 {
+		// Ignore AAAA error because A lookup succeeded.
+		err6 = nil
 	}
+	if err4 != nil {
+		return nil, err4
+	}
+	if err6 != nil {
+		return nil, err6
+	}
+
 	addrs = append(addrs, convertRR_AAAA(records)...)
-	return
+	return addrs, nil
 }
 
 // goLookupCNAME is the native Go implementation of LookupCNAME.
diff --git a/src/pkg/net/dnsconfig.go b/src/pkg/net/dnsconfig_unix.go
similarity index 100%
rename from src/pkg/net/dnsconfig.go
rename to src/pkg/net/dnsconfig_unix.go
diff --git a/src/pkg/net/dnsmsg.go b/src/pkg/net/dnsmsg.go
index b6ebe11..161afb2 100644
--- a/src/pkg/net/dnsmsg.go
+++ b/src/pkg/net/dnsmsg.go
@@ -618,7 +618,7 @@ func printStruct(any dnsStruct) string {
 		s += name + "="
 		switch tag {
 		case "ipv4":
-			i := val.(uint32)
+			i := *val.(*uint32)
 			s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String()
 		case "ipv6":
 			i := val.([]byte)
diff --git a/src/pkg/net/doc.go b/src/pkg/net/doc.go
deleted file mode 100644
index 3a44e52..0000000
--- a/src/pkg/net/doc.go
+++ /dev/null
@@ -1,59 +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 net
-
-// LookupHost looks up the given host using the local resolver.
-// It returns an array of that host's addresses.
-func LookupHost(host string) (addrs []string, err error) {
-	return lookupHost(host)
-}
-
-// LookupIP looks up host using the local resolver.
-// It returns an array of that host's IPv4 and IPv6 addresses.
-func LookupIP(host string) (addrs []IP, err error) {
-	return lookupIP(host)
-}
-
-// LookupPort looks up the port for the given network and service.
-func LookupPort(network, service string) (port int, err error) {
-	return lookupPort(network, service)
-}
-
-// LookupCNAME returns the canonical DNS host for the given name.
-// Callers that do not care about the canonical name can call
-// LookupHost or LookupIP directly; both take care of resolving
-// the canonical name as part of the lookup.
-func LookupCNAME(name string) (cname string, err error) {
-	return lookupCNAME(name)
-}
-
-// LookupSRV tries to resolve an SRV query of the given service,
-// protocol, and domain name.  The proto is "tcp" or "udp".
-// The returned records are sorted by priority and randomized
-// by weight within a priority.
-//
-// LookupSRV constructs the DNS name to look up following RFC 2782.
-// That is, it looks up _service._proto.name.  To accommodate services
-// publishing SRV records under non-standard names, if both service
-// and proto are empty strings, LookupSRV looks up name directly.
-func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
-	return lookupSRV(service, proto, name)
-}
-
-// LookupMX returns the DNS MX records for the given domain name sorted by preference.
-func LookupMX(name string) (mx []*MX, err error) {
-	return lookupMX(name)
-}
-
-// LookupTXT returns the DNS TXT records for the given domain name.
-func LookupTXT(name string) (txt []string, err error) {
-	return lookupTXT(name)
-}
-
-// LookupAddr performs a reverse lookup for the given address, returning a list
-// of names mapping to that address.
-func LookupAddr(addr string) (name []string, err error) {
-	return lookupAddr(addr)
-}
diff --git a/src/pkg/net/example_test.go b/src/pkg/net/example_test.go
index 1a1c2ed..eefe84f 100644
--- a/src/pkg/net/example_test.go
+++ b/src/pkg/net/example_test.go
@@ -17,7 +17,7 @@ func ExampleListener() {
 		log.Fatal(err)
 	}
 	for {
-		// Wait for a connection. 
+		// Wait for a connection.
 		conn, err := l.Accept()
 		if err != nil {
 			log.Fatal(err)
diff --git a/src/pkg/net/fd.go b/src/pkg/net/fd.go
deleted file mode 100644
index 76c953b..0000000
--- a/src/pkg/net/fd.go
+++ /dev/null
@@ -1,663 +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 darwin freebsd linux netbsd openbsd
-
-package net
-
-import (
-	"errors"
-	"io"
-	"os"
-	"sync"
-	"syscall"
-	"time"
-)
-
-// Network file descriptor.
-type netFD struct {
-	// locking/lifetime of sysfd
-	sysmu  sync.Mutex
-	sysref int
-
-	// must lock both sysmu and pollserver to write
-	// can lock either to read
-	closing bool
-
-	// immutable until Close
-	sysfd       int
-	family      int
-	sotype      int
-	isConnected bool
-	sysfile     *os.File
-	cr          chan error
-	cw          chan error
-	net         string
-	laddr       Addr
-	raddr       Addr
-
-	// owned by client
-	rdeadline int64
-	rio       sync.Mutex
-	wdeadline int64
-	wio       sync.Mutex
-
-	// owned by fd wait server
-	ncr, ncw int
-}
-
-// A pollServer helps FDs determine when to retry a non-blocking
-// read or write after they get EAGAIN.  When an FD needs to wait,
-// send the fd on s.cr (for a read) or s.cw (for a write) to pass the
-// request to the poll server.  Then receive on fd.cr/fd.cw.
-// When the pollServer finds that i/o on FD should be possible
-// again, it will send fd on fd.cr/fd.cw to wake any waiting processes.
-// This protocol is implemented as s.WaitRead() and s.WaitWrite().
-//
-// There is one subtlety: when sending on s.cr/s.cw, the
-// poll server is probably in a system call, waiting for an fd
-// to become ready.  It's not looking at the request channels.
-// To resolve this, the poll server waits not just on the FDs it has
-// been given but also its own pipe.  After sending on the
-// buffered channel s.cr/s.cw, WaitRead/WaitWrite writes a
-// byte to the pipe, causing the pollServer's poll system call to
-// return.  In response to the pipe being readable, the pollServer
-// re-polls its request channels.
-//
-// Note that the ordering is "send request" and then "wake up server".
-// If the operations were reversed, there would be a race: the poll
-// server might wake up and look at the request channel, see that it
-// was empty, and go back to sleep, all before the requester managed
-// to send the request.  Because the send must complete before the wakeup,
-// the request channel must be buffered.  A buffer of size 1 is sufficient
-// for any request load.  If many processes are trying to submit requests,
-// one will succeed, the pollServer will read the request, and then the
-// channel will be empty for the next process's request.  A larger buffer
-// might help batch requests.
-//
-// To avoid races in closing, all fd operations are locked and
-// refcounted. when netFD.Close() is called, it calls syscall.Shutdown
-// and sets a closing flag. Only when the last reference is removed
-// will the fd be closed.
-
-type pollServer struct {
-	cr, cw     chan *netFD // buffered >= 1
-	pr, pw     *os.File
-	poll       *pollster // low-level OS hooks
-	sync.Mutex           // controls pending and deadline
-	pending    map[int]*netFD
-	deadline   int64 // next deadline (nsec since 1970)
-}
-
-func (s *pollServer) AddFD(fd *netFD, mode int) error {
-	s.Lock()
-	intfd := fd.sysfd
-	if intfd < 0 || fd.closing {
-		// fd closed underfoot
-		s.Unlock()
-		return errClosing
-	}
-
-	var t int64
-	key := intfd << 1
-	if mode == 'r' {
-		fd.ncr++
-		t = fd.rdeadline
-	} else {
-		fd.ncw++
-		key++
-		t = fd.wdeadline
-	}
-	s.pending[key] = fd
-	doWakeup := false
-	if t > 0 && (s.deadline == 0 || t < s.deadline) {
-		s.deadline = t
-		doWakeup = true
-	}
-
-	wake, err := s.poll.AddFD(intfd, mode, false)
-	if err != nil {
-		panic("pollServer AddFD " + err.Error())
-	}
-	if wake {
-		doWakeup = true
-	}
-	s.Unlock()
-
-	if doWakeup {
-		s.Wakeup()
-	}
-	return nil
-}
-
-// Evict evicts fd from the pending list, unblocking
-// any I/O running on fd.  The caller must have locked
-// pollserver.
-func (s *pollServer) Evict(fd *netFD) {
-	if s.pending[fd.sysfd<<1] == fd {
-		s.WakeFD(fd, 'r', errClosing)
-		s.poll.DelFD(fd.sysfd, 'r')
-		delete(s.pending, fd.sysfd<<1)
-	}
-	if s.pending[fd.sysfd<<1|1] == fd {
-		s.WakeFD(fd, 'w', errClosing)
-		s.poll.DelFD(fd.sysfd, 'w')
-		delete(s.pending, fd.sysfd<<1|1)
-	}
-}
-
-var wakeupbuf [1]byte
-
-func (s *pollServer) Wakeup() { s.pw.Write(wakeupbuf[0:]) }
-
-func (s *pollServer) LookupFD(fd int, mode int) *netFD {
-	key := fd << 1
-	if mode == 'w' {
-		key++
-	}
-	netfd, ok := s.pending[key]
-	if !ok {
-		return nil
-	}
-	delete(s.pending, key)
-	return netfd
-}
-
-func (s *pollServer) WakeFD(fd *netFD, mode int, err error) {
-	if mode == 'r' {
-		for fd.ncr > 0 {
-			fd.ncr--
-			fd.cr <- err
-		}
-	} else {
-		for fd.ncw > 0 {
-			fd.ncw--
-			fd.cw <- err
-		}
-	}
-}
-
-func (s *pollServer) Now() int64 {
-	return time.Now().UnixNano()
-}
-
-func (s *pollServer) CheckDeadlines() {
-	now := s.Now()
-	// TODO(rsc): This will need to be handled more efficiently,
-	// probably with a heap indexed by wakeup time.
-
-	var next_deadline int64
-	for key, fd := range s.pending {
-		var t int64
-		var mode int
-		if key&1 == 0 {
-			mode = 'r'
-		} else {
-			mode = 'w'
-		}
-		if mode == 'r' {
-			t = fd.rdeadline
-		} else {
-			t = fd.wdeadline
-		}
-		if t > 0 {
-			if t <= now {
-				delete(s.pending, key)
-				if mode == 'r' {
-					s.poll.DelFD(fd.sysfd, mode)
-					fd.rdeadline = -1
-				} else {
-					s.poll.DelFD(fd.sysfd, mode)
-					fd.wdeadline = -1
-				}
-				s.WakeFD(fd, mode, nil)
-			} else if next_deadline == 0 || t < next_deadline {
-				next_deadline = t
-			}
-		}
-	}
-	s.deadline = next_deadline
-}
-
-func (s *pollServer) Run() {
-	var scratch [100]byte
-	s.Lock()
-	defer s.Unlock()
-	for {
-		var t = s.deadline
-		if t > 0 {
-			t = t - s.Now()
-			if t <= 0 {
-				s.CheckDeadlines()
-				continue
-			}
-		}
-		fd, mode, err := s.poll.WaitFD(s, t)
-		if err != nil {
-			print("pollServer WaitFD: ", err.Error(), "\n")
-			return
-		}
-		if fd < 0 {
-			// Timeout happened.
-			s.CheckDeadlines()
-			continue
-		}
-		if fd == int(s.pr.Fd()) {
-			// Drain our wakeup pipe (we could loop here,
-			// but it's unlikely that there are more than
-			// len(scratch) wakeup calls).
-			s.pr.Read(scratch[0:])
-			s.CheckDeadlines()
-		} else {
-			netfd := s.LookupFD(fd, mode)
-			if netfd == nil {
-				// This can happen because the WaitFD runs without
-				// holding s's lock, so there might be a pending wakeup
-				// for an fd that has been evicted.  No harm done.
-				continue
-			}
-			s.WakeFD(netfd, mode, nil)
-		}
-	}
-}
-
-func (s *pollServer) WaitRead(fd *netFD) error {
-	err := s.AddFD(fd, 'r')
-	if err == nil {
-		err = <-fd.cr
-	}
-	return err
-}
-
-func (s *pollServer) WaitWrite(fd *netFD) error {
-	err := s.AddFD(fd, 'w')
-	if err == nil {
-		err = <-fd.cw
-	}
-	return err
-}
-
-// Network FD methods.
-// All the network FDs use a single pollServer.
-
-var pollserver *pollServer
-var onceStartServer sync.Once
-
-func startServer() {
-	p, err := newPollServer()
-	if err != nil {
-		print("Start pollServer: ", err.Error(), "\n")
-	}
-	pollserver = p
-}
-
-func newFD(fd, family, sotype int, net string) (*netFD, error) {
-	onceStartServer.Do(startServer)
-	if err := syscall.SetNonblock(fd, true); err != nil {
-		return nil, err
-	}
-	netfd := &netFD{
-		sysfd:  fd,
-		family: family,
-		sotype: sotype,
-		net:    net,
-	}
-	netfd.cr = make(chan error, 1)
-	netfd.cw = make(chan error, 1)
-	return netfd, nil
-}
-
-func (fd *netFD) setAddr(laddr, raddr Addr) {
-	fd.laddr = laddr
-	fd.raddr = raddr
-	var ls, rs string
-	if laddr != nil {
-		ls = laddr.String()
-	}
-	if raddr != nil {
-		rs = raddr.String()
-	}
-	fd.sysfile = os.NewFile(uintptr(fd.sysfd), fd.net+":"+ls+"->"+rs)
-}
-
-func (fd *netFD) connect(ra syscall.Sockaddr) error {
-	err := syscall.Connect(fd.sysfd, ra)
-	if err == syscall.EINPROGRESS {
-		if err = pollserver.WaitWrite(fd); err != nil {
-			return err
-		}
-		var e int
-		e, err = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
-		if err != nil {
-			return os.NewSyscallError("getsockopt", err)
-		}
-		if e != 0 {
-			err = syscall.Errno(e)
-		}
-	}
-	return err
-}
-
-var errClosing = errors.New("use of closed network connection")
-
-// Add a reference to this fd.
-// If closing==true, pollserver must be locked; mark the fd as closing.
-// Returns an error if the fd cannot be used.
-func (fd *netFD) incref(closing bool) error {
-	if fd == nil {
-		return errClosing
-	}
-	fd.sysmu.Lock()
-	if fd.closing {
-		fd.sysmu.Unlock()
-		return errClosing
-	}
-	fd.sysref++
-	if closing {
-		fd.closing = true
-	}
-	fd.sysmu.Unlock()
-	return nil
-}
-
-// Remove a reference to this FD and close if we've been asked to do so (and
-// there are no references left.
-func (fd *netFD) decref() {
-	if fd == nil {
-		return
-	}
-	fd.sysmu.Lock()
-	fd.sysref--
-	if fd.closing && fd.sysref == 0 && fd.sysfile != nil {
-		fd.sysfile.Close()
-		fd.sysfile = nil
-		fd.sysfd = -1
-	}
-	fd.sysmu.Unlock()
-}
-
-func (fd *netFD) Close() error {
-	pollserver.Lock() // needed for both fd.incref(true) and pollserver.Evict
-	defer pollserver.Unlock()
-	if err := fd.incref(true); err != nil {
-		return err
-	}
-	// Unblock any I/O.  Once it all unblocks and returns,
-	// so that it cannot be referring to fd.sysfd anymore,
-	// the final decref will close fd.sysfd.  This should happen
-	// fairly quickly, since all the I/O is non-blocking, and any
-	// attempts to block in the pollserver will return errClosing.
-	pollserver.Evict(fd)
-	fd.decref()
-	return nil
-}
-
-func (fd *netFD) shutdown(how int) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.Shutdown(fd.sysfd, how)
-	if err != nil {
-		return &OpError{"shutdown", fd.net, fd.laddr, err}
-	}
-	return nil
-}
-
-func (fd *netFD) CloseRead() error {
-	return fd.shutdown(syscall.SHUT_RD)
-}
-
-func (fd *netFD) CloseWrite() error {
-	return fd.shutdown(syscall.SHUT_WR)
-}
-
-func (fd *netFD) Read(p []byte) (n int, err error) {
-	fd.rio.Lock()
-	defer fd.rio.Unlock()
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	for {
-		n, err = syscall.Read(int(fd.sysfd), p)
-		if err == syscall.EAGAIN {
-			err = errTimeout
-			if fd.rdeadline >= 0 {
-				if err = pollserver.WaitRead(fd); err == nil {
-					continue
-				}
-			}
-		}
-		if err != nil {
-			n = 0
-		} else if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM {
-			err = io.EOF
-		}
-		break
-	}
-	if err != nil && err != io.EOF {
-		err = &OpError{"read", fd.net, fd.raddr, err}
-	}
-	return
-}
-
-func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
-	fd.rio.Lock()
-	defer fd.rio.Unlock()
-	if err := fd.incref(false); err != nil {
-		return 0, nil, err
-	}
-	defer fd.decref()
-	for {
-		n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
-		if err == syscall.EAGAIN {
-			err = errTimeout
-			if fd.rdeadline >= 0 {
-				if err = pollserver.WaitRead(fd); err == nil {
-					continue
-				}
-			}
-		}
-		if err != nil {
-			n = 0
-		}
-		break
-	}
-	if err != nil && err != io.EOF {
-		err = &OpError{"read", fd.net, fd.laddr, err}
-	}
-	return
-}
-
-func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
-	fd.rio.Lock()
-	defer fd.rio.Unlock()
-	if err := fd.incref(false); err != nil {
-		return 0, 0, 0, nil, err
-	}
-	defer fd.decref()
-	for {
-		n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
-		if err == syscall.EAGAIN {
-			err = errTimeout
-			if fd.rdeadline >= 0 {
-				if err = pollserver.WaitRead(fd); err == nil {
-					continue
-				}
-			}
-		}
-		if err == nil && n == 0 {
-			err = io.EOF
-		}
-		break
-	}
-	if err != nil && err != io.EOF {
-		err = &OpError{"read", fd.net, fd.laddr, err}
-		return
-	}
-	return
-}
-
-func (fd *netFD) Write(p []byte) (int, error) {
-	fd.wio.Lock()
-	defer fd.wio.Unlock()
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	if fd.sysfile == nil {
-		return 0, syscall.EINVAL
-	}
-
-	var err error
-	nn := 0
-	for {
-		var n int
-		n, err = syscall.Write(int(fd.sysfd), p[nn:])
-		if n > 0 {
-			nn += n
-		}
-		if nn == len(p) {
-			break
-		}
-		if err == syscall.EAGAIN {
-			err = errTimeout
-			if fd.wdeadline >= 0 {
-				if err = pollserver.WaitWrite(fd); err == nil {
-					continue
-				}
-			}
-		}
-		if err != nil {
-			n = 0
-			break
-		}
-		if n == 0 {
-			err = io.ErrUnexpectedEOF
-			break
-		}
-	}
-	if err != nil {
-		err = &OpError{"write", fd.net, fd.raddr, err}
-	}
-	return nn, err
-}
-
-func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
-	fd.wio.Lock()
-	defer fd.wio.Unlock()
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	for {
-		err = syscall.Sendto(fd.sysfd, p, 0, sa)
-		if err == syscall.EAGAIN {
-			err = errTimeout
-			if fd.wdeadline >= 0 {
-				if err = pollserver.WaitWrite(fd); err == nil {
-					continue
-				}
-			}
-		}
-		break
-	}
-	if err == nil {
-		n = len(p)
-	} else {
-		err = &OpError{"write", fd.net, fd.raddr, err}
-	}
-	return
-}
-
-func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
-	fd.wio.Lock()
-	defer fd.wio.Unlock()
-	if err := fd.incref(false); err != nil {
-		return 0, 0, err
-	}
-	defer fd.decref()
-	for {
-		err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
-		if err == syscall.EAGAIN {
-			err = errTimeout
-			if fd.wdeadline >= 0 {
-				if err = pollserver.WaitWrite(fd); err == nil {
-					continue
-				}
-			}
-		}
-		break
-	}
-	if err == nil {
-		n = len(p)
-		oobn = len(oob)
-	} else {
-		err = &OpError{"write", fd.net, fd.raddr, err}
-	}
-	return
-}
-
-func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
-	if err := fd.incref(false); err != nil {
-		return nil, err
-	}
-	defer fd.decref()
-
-	// See ../syscall/exec.go for description of ForkLock.
-	// It is okay to hold the lock across syscall.Accept
-	// because we have put fd.sysfd into non-blocking mode.
-	var s int
-	var rsa syscall.Sockaddr
-	for {
-		syscall.ForkLock.RLock()
-		s, rsa, err = syscall.Accept(fd.sysfd)
-		if err != nil {
-			syscall.ForkLock.RUnlock()
-			if err == syscall.EAGAIN {
-				err = errTimeout
-				if fd.rdeadline >= 0 {
-					if err = pollserver.WaitRead(fd); err == nil {
-						continue
-					}
-				}
-			} else if err == syscall.ECONNABORTED {
-				// This means that a socket on the listen queue was closed
-				// before we Accept()ed it; it's a silly error, so try again.
-				continue
-			}
-			return nil, &OpError{"accept", fd.net, fd.laddr, err}
-		}
-		break
-	}
-	syscall.CloseOnExec(s)
-	syscall.ForkLock.RUnlock()
-
-	if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
-		syscall.Close(s)
-		return nil, err
-	}
-	lsa, _ := syscall.Getsockname(netfd.sysfd)
-	netfd.setAddr(toAddr(lsa), toAddr(rsa))
-	return netfd, nil
-}
-
-func (fd *netFD) dup() (f *os.File, err error) {
-	ns, err := syscall.Dup(fd.sysfd)
-	if err != nil {
-		return nil, &OpError{"dup", fd.net, fd.laddr, err}
-	}
-
-	// We want blocking mode for the new fd, hence the double negative.
-	if err = syscall.SetNonblock(ns, false); err != nil {
-		return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
-	}
-
-	return os.NewFile(uintptr(ns), fd.sysfile.Name()), nil
-}
-
-func closesocket(s int) error {
-	return syscall.Close(s)
-}
diff --git a/src/pkg/net/fd_bsd.go b/src/pkg/net/fd_bsd.go
new file mode 100644
index 0000000..8bb1ae5
--- /dev/null
+++ b/src/pkg/net/fd_bsd.go
@@ -0,0 +1,123 @@
+// 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 freebsd netbsd openbsd
+
+// Waiting for FDs via kqueue/kevent.
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+type pollster struct {
+	kq       int
+	eventbuf [10]syscall.Kevent_t
+	events   []syscall.Kevent_t
+
+	// An event buffer for AddFD/DelFD.
+	// Must hold pollServer lock.
+	kbuf [1]syscall.Kevent_t
+}
+
+func newpollster() (p *pollster, err error) {
+	p = new(pollster)
+	if p.kq, err = syscall.Kqueue(); err != nil {
+		return nil, os.NewSyscallError("kqueue", err)
+	}
+	syscall.CloseOnExec(p.kq)
+	p.events = p.eventbuf[0:0]
+	return p, nil
+}
+
+// First return value is whether the pollServer should be woken up.
+// This version always returns false.
+func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
+	// pollServer is locked.
+
+	var kmode int
+	if mode == 'r' {
+		kmode = syscall.EVFILT_READ
+	} else {
+		kmode = syscall.EVFILT_WRITE
+	}
+	ev := &p.kbuf[0]
+	// EV_ADD - add event to kqueue list
+	// EV_ONESHOT - delete the event the first time it triggers
+	flags := syscall.EV_ADD
+	if !repeat {
+		flags |= syscall.EV_ONESHOT
+	}
+	syscall.SetKevent(ev, fd, kmode, flags)
+
+	n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
+	if err != nil {
+		return false, os.NewSyscallError("kevent", err)
+	}
+	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
+		return false, os.NewSyscallError("kqueue phase error", err)
+	}
+	if ev.Data != 0 {
+		return false, syscall.Errno(int(ev.Data))
+	}
+	return false, nil
+}
+
+// Return value is whether the pollServer should be woken up.
+// This version always returns false.
+func (p *pollster) DelFD(fd int, mode int) bool {
+	// pollServer is locked.
+
+	var kmode int
+	if mode == 'r' {
+		kmode = syscall.EVFILT_READ
+	} else {
+		kmode = syscall.EVFILT_WRITE
+	}
+	ev := &p.kbuf[0]
+	// EV_DELETE - delete event from kqueue list
+	syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)
+	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
+	return false
+}
+
+func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
+	var t *syscall.Timespec
+	for len(p.events) == 0 {
+		if nsec > 0 {
+			if t == nil {
+				t = new(syscall.Timespec)
+			}
+			*t = syscall.NsecToTimespec(nsec)
+		}
+
+		s.Unlock()
+		n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
+		s.Lock()
+
+		if err != nil {
+			if err == syscall.EINTR {
+				continue
+			}
+			return -1, 0, os.NewSyscallError("kevent", err)
+		}
+		if n == 0 {
+			return -1, 0, nil
+		}
+		p.events = p.eventbuf[:n]
+	}
+	ev := &p.events[0]
+	p.events = p.events[1:]
+	fd = int(ev.Ident)
+	if ev.Filter == syscall.EVFILT_READ {
+		mode = 'r'
+	} else {
+		mode = 'w'
+	}
+	return fd, mode, nil
+}
+
+func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/src/pkg/net/fd_darwin.go b/src/pkg/net/fd_darwin.go
index 3dd33ed..382465b 100644
--- a/src/pkg/net/fd_darwin.go
+++ b/src/pkg/net/fd_darwin.go
@@ -32,6 +32,8 @@ func newpollster() (p *pollster, err error) {
 	return p, nil
 }
 
+// First return value is whether the pollServer should be woken up.
+// This version always returns false.
 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
 	// pollServer is locked.
 
@@ -65,7 +67,9 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
 	return false, nil
 }
 
-func (p *pollster) DelFD(fd int, mode int) {
+// Return value is whether the pollServer should be woken up.
+// This version always returns false.
+func (p *pollster) DelFD(fd int, mode int) bool {
 	// pollServer is locked.
 
 	var kmode int
@@ -80,6 +84,7 @@ func (p *pollster) DelFD(fd int, mode int) {
 	//	rather than waiting for real event
 	syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE|syscall.EV_RECEIPT)
 	syscall.Kevent(p.kq, p.kbuf[0:], p.kbuf[0:], nil)
+	return false
 }
 
 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
diff --git a/src/pkg/net/fd_freebsd.go b/src/pkg/net/fd_freebsd.go
deleted file mode 100644
index 35d84c3..0000000
--- a/src/pkg/net/fd_freebsd.go
+++ /dev/null
@@ -1,116 +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.
-
-// Waiting for FDs via kqueue/kevent.
-
-package net
-
-import (
-	"os"
-	"syscall"
-)
-
-type pollster struct {
-	kq       int
-	eventbuf [10]syscall.Kevent_t
-	events   []syscall.Kevent_t
-
-	// An event buffer for AddFD/DelFD.
-	// Must hold pollServer lock.
-	kbuf [1]syscall.Kevent_t
-}
-
-func newpollster() (p *pollster, err error) {
-	p = new(pollster)
-	if p.kq, err = syscall.Kqueue(); err != nil {
-		return nil, os.NewSyscallError("kqueue", err)
-	}
-	syscall.CloseOnExec(p.kq)
-	p.events = p.eventbuf[0:0]
-	return p, nil
-}
-
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
-	// pollServer is locked.
-
-	var kmode int
-	if mode == 'r' {
-		kmode = syscall.EVFILT_READ
-	} else {
-		kmode = syscall.EVFILT_WRITE
-	}
-	ev := &p.kbuf[0]
-	// EV_ADD - add event to kqueue list
-	// EV_ONESHOT - delete the event the first time it triggers
-	flags := syscall.EV_ADD
-	if !repeat {
-		flags |= syscall.EV_ONESHOT
-	}
-	syscall.SetKevent(ev, fd, kmode, flags)
-
-	n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
-	if err != nil {
-		return false, os.NewSyscallError("kevent", err)
-	}
-	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
-		return false, os.NewSyscallError("kqueue phase error", err)
-	}
-	if ev.Data != 0 {
-		return false, syscall.Errno(int(ev.Data))
-	}
-	return false, nil
-}
-
-func (p *pollster) DelFD(fd int, mode int) {
-	// pollServer is locked.
-
-	var kmode int
-	if mode == 'r' {
-		kmode = syscall.EVFILT_READ
-	} else {
-		kmode = syscall.EVFILT_WRITE
-	}
-	ev := &p.kbuf[0]
-	// EV_DELETE - delete event from kqueue list
-	syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)
-	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
-}
-
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
-	var t *syscall.Timespec
-	for len(p.events) == 0 {
-		if nsec > 0 {
-			if t == nil {
-				t = new(syscall.Timespec)
-			}
-			*t = syscall.NsecToTimespec(nsec)
-		}
-
-		s.Unlock()
-		n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
-		s.Lock()
-
-		if err != nil {
-			if err == syscall.EINTR {
-				continue
-			}
-			return -1, 0, os.NewSyscallError("kevent", err)
-		}
-		if n == 0 {
-			return -1, 0, nil
-		}
-		p.events = p.eventbuf[:n]
-	}
-	ev := &p.events[0]
-	p.events = p.events[1:]
-	fd = int(ev.Ident)
-	if ev.Filter == syscall.EVFILT_READ {
-		mode = 'r'
-	} else {
-		mode = 'w'
-	}
-	return fd, mode, nil
-}
-
-func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/src/pkg/net/fd_linux.go b/src/pkg/net/fd_linux.go
index 085e423..0367919 100644
--- a/src/pkg/net/fd_linux.go
+++ b/src/pkg/net/fd_linux.go
@@ -51,6 +51,8 @@ func newpollster() (p *pollster, err error) {
 	return p, nil
 }
 
+// First return value is whether the pollServer should be woken up.
+// This version always returns false.
 func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
 	// pollServer is locked.
 
@@ -114,7 +116,9 @@ func (p *pollster) StopWaiting(fd int, bits uint) {
 	}
 }
 
-func (p *pollster) DelFD(fd int, mode int) {
+// Return value is whether the pollServer should be woken up.
+// This version always returns false.
+func (p *pollster) DelFD(fd int, mode int) bool {
 	// pollServer is locked.
 
 	if mode == 'r' {
@@ -133,6 +137,7 @@ func (p *pollster) DelFD(fd int, mode int) {
 			i++
 		}
 	}
+	return false
 }
 
 func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
diff --git a/src/pkg/net/fd_netbsd.go b/src/pkg/net/fd_netbsd.go
deleted file mode 100644
index 35d84c3..0000000
--- a/src/pkg/net/fd_netbsd.go
+++ /dev/null
@@ -1,116 +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.
-
-// Waiting for FDs via kqueue/kevent.
-
-package net
-
-import (
-	"os"
-	"syscall"
-)
-
-type pollster struct {
-	kq       int
-	eventbuf [10]syscall.Kevent_t
-	events   []syscall.Kevent_t
-
-	// An event buffer for AddFD/DelFD.
-	// Must hold pollServer lock.
-	kbuf [1]syscall.Kevent_t
-}
-
-func newpollster() (p *pollster, err error) {
-	p = new(pollster)
-	if p.kq, err = syscall.Kqueue(); err != nil {
-		return nil, os.NewSyscallError("kqueue", err)
-	}
-	syscall.CloseOnExec(p.kq)
-	p.events = p.eventbuf[0:0]
-	return p, nil
-}
-
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
-	// pollServer is locked.
-
-	var kmode int
-	if mode == 'r' {
-		kmode = syscall.EVFILT_READ
-	} else {
-		kmode = syscall.EVFILT_WRITE
-	}
-	ev := &p.kbuf[0]
-	// EV_ADD - add event to kqueue list
-	// EV_ONESHOT - delete the event the first time it triggers
-	flags := syscall.EV_ADD
-	if !repeat {
-		flags |= syscall.EV_ONESHOT
-	}
-	syscall.SetKevent(ev, fd, kmode, flags)
-
-	n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
-	if err != nil {
-		return false, os.NewSyscallError("kevent", err)
-	}
-	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
-		return false, os.NewSyscallError("kqueue phase error", err)
-	}
-	if ev.Data != 0 {
-		return false, syscall.Errno(int(ev.Data))
-	}
-	return false, nil
-}
-
-func (p *pollster) DelFD(fd int, mode int) {
-	// pollServer is locked.
-
-	var kmode int
-	if mode == 'r' {
-		kmode = syscall.EVFILT_READ
-	} else {
-		kmode = syscall.EVFILT_WRITE
-	}
-	ev := &p.kbuf[0]
-	// EV_DELETE - delete event from kqueue list
-	syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)
-	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
-}
-
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
-	var t *syscall.Timespec
-	for len(p.events) == 0 {
-		if nsec > 0 {
-			if t == nil {
-				t = new(syscall.Timespec)
-			}
-			*t = syscall.NsecToTimespec(nsec)
-		}
-
-		s.Unlock()
-		n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
-		s.Lock()
-
-		if err != nil {
-			if err == syscall.EINTR {
-				continue
-			}
-			return -1, 0, os.NewSyscallError("kevent", err)
-		}
-		if n == 0 {
-			return -1, 0, nil
-		}
-		p.events = p.eventbuf[:n]
-	}
-	ev := &p.events[0]
-	p.events = p.events[1:]
-	fd = int(ev.Ident)
-	if ev.Filter == syscall.EVFILT_READ {
-		mode = 'r'
-	} else {
-		mode = 'w'
-	}
-	return fd, mode, nil
-}
-
-func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/src/pkg/net/fd_openbsd.go b/src/pkg/net/fd_openbsd.go
deleted file mode 100644
index 35d84c3..0000000
--- a/src/pkg/net/fd_openbsd.go
+++ /dev/null
@@ -1,116 +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.
-
-// Waiting for FDs via kqueue/kevent.
-
-package net
-
-import (
-	"os"
-	"syscall"
-)
-
-type pollster struct {
-	kq       int
-	eventbuf [10]syscall.Kevent_t
-	events   []syscall.Kevent_t
-
-	// An event buffer for AddFD/DelFD.
-	// Must hold pollServer lock.
-	kbuf [1]syscall.Kevent_t
-}
-
-func newpollster() (p *pollster, err error) {
-	p = new(pollster)
-	if p.kq, err = syscall.Kqueue(); err != nil {
-		return nil, os.NewSyscallError("kqueue", err)
-	}
-	syscall.CloseOnExec(p.kq)
-	p.events = p.eventbuf[0:0]
-	return p, nil
-}
-
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
-	// pollServer is locked.
-
-	var kmode int
-	if mode == 'r' {
-		kmode = syscall.EVFILT_READ
-	} else {
-		kmode = syscall.EVFILT_WRITE
-	}
-	ev := &p.kbuf[0]
-	// EV_ADD - add event to kqueue list
-	// EV_ONESHOT - delete the event the first time it triggers
-	flags := syscall.EV_ADD
-	if !repeat {
-		flags |= syscall.EV_ONESHOT
-	}
-	syscall.SetKevent(ev, fd, kmode, flags)
-
-	n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
-	if err != nil {
-		return false, os.NewSyscallError("kevent", err)
-	}
-	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
-		return false, os.NewSyscallError("kqueue phase error", err)
-	}
-	if ev.Data != 0 {
-		return false, syscall.Errno(int(ev.Data))
-	}
-	return false, nil
-}
-
-func (p *pollster) DelFD(fd int, mode int) {
-	// pollServer is locked.
-
-	var kmode int
-	if mode == 'r' {
-		kmode = syscall.EVFILT_READ
-	} else {
-		kmode = syscall.EVFILT_WRITE
-	}
-	ev := &p.kbuf[0]
-	// EV_DELETE - delete event from kqueue list
-	syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)
-	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
-}
-
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
-	var t *syscall.Timespec
-	for len(p.events) == 0 {
-		if nsec > 0 {
-			if t == nil {
-				t = new(syscall.Timespec)
-			}
-			*t = syscall.NsecToTimespec(nsec)
-		}
-
-		s.Unlock()
-		n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
-		s.Lock()
-
-		if err != nil {
-			if err == syscall.EINTR {
-				continue
-			}
-			return -1, 0, os.NewSyscallError("kevent", err)
-		}
-		if n == 0 {
-			return -1, 0, nil
-		}
-		p.events = p.eventbuf[:n]
-	}
-	ev := &p.events[0]
-	p.events = p.events[1:]
-	fd = int(ev.Ident)
-	if ev.Filter == syscall.EVFILT_READ {
-		mode = 'r'
-	} else {
-		mode = 'w'
-	}
-	return fd, mode, nil
-}
-
-func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/src/pkg/net/fd_plan9.go b/src/pkg/net/fd_plan9.go
new file mode 100644
index 0000000..1690879
--- /dev/null
+++ b/src/pkg/net/fd_plan9.go
@@ -0,0 +1,129 @@
+// 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 (
+	"io"
+	"os"
+	"syscall"
+	"time"
+)
+
+// Network file descritor.
+type netFD struct {
+	proto, name, dir string
+	ctl, data        *os.File
+	laddr, raddr     Addr
+}
+
+var canCancelIO = true // used for testing current package
+
+func sysInit() {
+}
+
+func dialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
+	// On plan9, use the relatively inefficient
+	// goroutine-racing implementation.
+	return dialTimeoutRace(net, addr, timeout)
+}
+
+func newFD(proto, name string, ctl, data *os.File, laddr, raddr Addr) *netFD {
+	return &netFD{proto, name, "/net/" + proto + "/" + name, ctl, data, laddr, raddr}
+}
+
+func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil }
+
+func (fd *netFD) Read(b []byte) (n int, err error) {
+	if !fd.ok() || fd.data == nil {
+		return 0, syscall.EINVAL
+	}
+	n, err = fd.data.Read(b)
+	if fd.proto == "udp" && err == io.EOF {
+		n = 0
+		err = nil
+	}
+	return
+}
+
+func (fd *netFD) Write(b []byte) (n int, err error) {
+	if !fd.ok() || fd.data == nil {
+		return 0, syscall.EINVAL
+	}
+	return fd.data.Write(b)
+}
+
+func (fd *netFD) CloseRead() error {
+	if !fd.ok() {
+		return syscall.EINVAL
+	}
+	return syscall.EPLAN9
+}
+
+func (fd *netFD) CloseWrite() error {
+	if !fd.ok() {
+		return syscall.EINVAL
+	}
+	return syscall.EPLAN9
+}
+
+func (fd *netFD) Close() error {
+	if !fd.ok() {
+		return syscall.EINVAL
+	}
+	err := fd.ctl.Close()
+	if fd.data != nil {
+		if err1 := fd.data.Close(); err1 != nil && err == nil {
+			err = err1
+		}
+	}
+	fd.ctl = nil
+	fd.data = nil
+	return err
+}
+
+// This method is only called via Conn.
+func (fd *netFD) dup() (*os.File, error) {
+	if !fd.ok() || fd.data == nil {
+		return nil, syscall.EINVAL
+	}
+	return fd.file(fd.data, fd.dir+"/data")
+}
+
+func (l *TCPListener) dup() (*os.File, error) {
+	if !l.fd.ok() {
+		return nil, syscall.EINVAL
+	}
+	return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl")
+}
+
+func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
+	syscall.ForkLock.RLock()
+	dfd, err := syscall.Dup(int(f.Fd()), -1)
+	syscall.ForkLock.RUnlock()
+	if err != nil {
+		return nil, &OpError{"dup", s, fd.laddr, err}
+	}
+	return os.NewFile(uintptr(dfd), s), nil
+}
+
+func setDeadline(fd *netFD, t time.Time) error {
+	return syscall.EPLAN9
+}
+
+func setReadDeadline(fd *netFD, t time.Time) error {
+	return syscall.EPLAN9
+}
+
+func setWriteDeadline(fd *netFD, t time.Time) error {
+	return syscall.EPLAN9
+}
+
+func setReadBuffer(fd *netFD, bytes int) error {
+	return syscall.EPLAN9
+}
+
+func setWriteBuffer(fd *netFD, bytes int) error {
+	return syscall.EPLAN9
+}
diff --git a/src/pkg/net/fd_posix_test.go b/src/pkg/net/fd_posix_test.go
new file mode 100644
index 0000000..8be0335
--- /dev/null
+++ b/src/pkg/net/fd_posix_test.go
@@ -0,0 +1,57 @@
+// 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 freebsd linux netbsd openbsd windows
+
+package net
+
+import (
+	"testing"
+	"time"
+)
+
+var deadlineSetTimeTests = []struct {
+	input    time.Time
+	expected int64
+}{
+	{time.Time{}, 0},
+	{time.Date(2009, 11, 10, 23, 00, 00, 00, time.UTC), 1257894000000000000}, // 2009-11-10 23:00:00 +0000 UTC
+}
+
+func TestDeadlineSetTime(t *testing.T) {
+	for _, tt := range deadlineSetTimeTests {
+		var d deadline
+		d.setTime(tt.input)
+		actual := d.value()
+		expected := int64(0)
+		if !tt.input.IsZero() {
+			expected = tt.input.UnixNano()
+		}
+		if actual != expected {
+			t.Errorf("set/value failed: expected %v, actual %v", expected, actual)
+		}
+	}
+}
+
+var deadlineExpiredTests = []struct {
+	deadline time.Time
+	expired  bool
+}{
+	// note, times are relative to the start of the test run, not
+	// the start of TestDeadlineExpired
+	{time.Now().Add(5 * time.Minute), false},
+	{time.Now().Add(-5 * time.Minute), true},
+	{time.Time{}, false}, // no deadline set
+}
+
+func TestDeadlineExpired(t *testing.T) {
+	for _, tt := range deadlineExpiredTests {
+		var d deadline
+		d.set(tt.deadline.UnixNano())
+		expired := d.expired()
+		if expired != tt.expired {
+			t.Errorf("expire failed: expected %v, actual %v", tt.expired, expired)
+		}
+	}
+}
diff --git a/src/pkg/net/fd_unix.go b/src/pkg/net/fd_unix.go
new file mode 100644
index 0000000..0540df8
--- /dev/null
+++ b/src/pkg/net/fd_unix.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.
+
+// +build darwin freebsd linux netbsd openbsd
+
+package net
+
+import (
+	"io"
+	"os"
+	"runtime"
+	"sync"
+	"syscall"
+	"time"
+)
+
+// Network file descriptor.
+type netFD struct {
+	// locking/lifetime of sysfd
+	sysmu  sync.Mutex
+	sysref int
+
+	// must lock both sysmu and pollserver to write
+	// can lock either to read
+	closing bool
+
+	// immutable until Close
+	sysfd       int
+	family      int
+	sotype      int
+	isConnected bool
+	sysfile     *os.File
+	cr          chan error
+	cw          chan error
+	net         string
+	laddr       Addr
+	raddr       Addr
+
+	// serialize access to Read and Write methods
+	rio, wio sync.Mutex
+
+	// read and write deadlines
+	rdeadline, wdeadline deadline
+
+	// owned by fd wait server
+	ncr, ncw int
+
+	// wait server
+	pollServer *pollServer
+}
+
+// A pollServer helps FDs determine when to retry a non-blocking
+// read or write after they get EAGAIN.  When an FD needs to wait,
+// call s.WaitRead() or s.WaitWrite() to pass the request to the poll server.
+// When the pollServer finds that i/o on FD should be possible
+// again, it will send on fd.cr/fd.cw to wake any waiting goroutines.
+//
+// To avoid races in closing, all fd operations are locked and
+// refcounted. when netFD.Close() is called, it calls syscall.Shutdown
+// and sets a closing flag. Only when the last reference is removed
+// will the fd be closed.
+
+type pollServer struct {
+	pr, pw     *os.File
+	poll       *pollster // low-level OS hooks
+	sync.Mutex           // controls pending and deadline
+	pending    map[int]*netFD
+	deadline   int64 // next deadline (nsec since 1970)
+}
+
+func (s *pollServer) AddFD(fd *netFD, mode int) error {
+	s.Lock()
+	intfd := fd.sysfd
+	if intfd < 0 || fd.closing {
+		// fd closed underfoot
+		s.Unlock()
+		return errClosing
+	}
+
+	var t int64
+	key := intfd << 1
+	if mode == 'r' {
+		fd.ncr++
+		t = fd.rdeadline.value()
+	} else {
+		fd.ncw++
+		key++
+		t = fd.wdeadline.value()
+	}
+	s.pending[key] = fd
+	doWakeup := false
+	if t > 0 && (s.deadline == 0 || t < s.deadline) {
+		s.deadline = t
+		doWakeup = true
+	}
+
+	wake, err := s.poll.AddFD(intfd, mode, false)
+	s.Unlock()
+	if err != nil {
+		return &OpError{"addfd", fd.net, fd.laddr, err}
+	}
+	if wake || doWakeup {
+		s.Wakeup()
+	}
+	return nil
+}
+
+// Evict evicts fd from the pending list, unblocking
+// any I/O running on fd.  The caller must have locked
+// pollserver.
+// Return value is whether the pollServer should be woken up.
+func (s *pollServer) Evict(fd *netFD) bool {
+	doWakeup := false
+	if s.pending[fd.sysfd<<1] == fd {
+		s.WakeFD(fd, 'r', errClosing)
+		if s.poll.DelFD(fd.sysfd, 'r') {
+			doWakeup = true
+		}
+		delete(s.pending, fd.sysfd<<1)
+	}
+	if s.pending[fd.sysfd<<1|1] == fd {
+		s.WakeFD(fd, 'w', errClosing)
+		if s.poll.DelFD(fd.sysfd, 'w') {
+			doWakeup = true
+		}
+		delete(s.pending, fd.sysfd<<1|1)
+	}
+	return doWakeup
+}
+
+var wakeupbuf [1]byte
+
+func (s *pollServer) Wakeup() { s.pw.Write(wakeupbuf[0:]) }
+
+func (s *pollServer) LookupFD(fd int, mode int) *netFD {
+	key := fd << 1
+	if mode == 'w' {
+		key++
+	}
+	netfd, ok := s.pending[key]
+	if !ok {
+		return nil
+	}
+	delete(s.pending, key)
+	return netfd
+}
+
+func (s *pollServer) WakeFD(fd *netFD, mode int, err error) {
+	if mode == 'r' {
+		for fd.ncr > 0 {
+			fd.ncr--
+			fd.cr <- err
+		}
+	} else {
+		for fd.ncw > 0 {
+			fd.ncw--
+			fd.cw <- err
+		}
+	}
+}
+
+func (s *pollServer) CheckDeadlines() {
+	now := time.Now().UnixNano()
+	// TODO(rsc): This will need to be handled more efficiently,
+	// probably with a heap indexed by wakeup time.
+
+	var nextDeadline int64
+	for key, fd := range s.pending {
+		var t int64
+		var mode int
+		if key&1 == 0 {
+			mode = 'r'
+		} else {
+			mode = 'w'
+		}
+		if mode == 'r' {
+			t = fd.rdeadline.value()
+		} else {
+			t = fd.wdeadline.value()
+		}
+		if t > 0 {
+			if t <= now {
+				delete(s.pending, key)
+				s.poll.DelFD(fd.sysfd, mode)
+				s.WakeFD(fd, mode, errTimeout)
+			} else if nextDeadline == 0 || t < nextDeadline {
+				nextDeadline = t
+			}
+		}
+	}
+	s.deadline = nextDeadline
+}
+
+func (s *pollServer) Run() {
+	var scratch [100]byte
+	s.Lock()
+	defer s.Unlock()
+	for {
+		var timeout int64 // nsec to wait for or 0 for none
+		if s.deadline > 0 {
+			timeout = s.deadline - time.Now().UnixNano()
+			if timeout <= 0 {
+				s.CheckDeadlines()
+				continue
+			}
+		}
+		fd, mode, err := s.poll.WaitFD(s, timeout)
+		if err != nil {
+			print("pollServer WaitFD: ", err.Error(), "\n")
+			return
+		}
+		if fd < 0 {
+			// Timeout happened.
+			s.CheckDeadlines()
+			continue
+		}
+		if fd == int(s.pr.Fd()) {
+			// Drain our wakeup pipe (we could loop here,
+			// but it's unlikely that there are more than
+			// len(scratch) wakeup calls).
+			s.pr.Read(scratch[0:])
+			s.CheckDeadlines()
+		} else {
+			netfd := s.LookupFD(fd, mode)
+			if netfd == nil {
+				// This can happen because the WaitFD runs without
+				// holding s's lock, so there might be a pending wakeup
+				// for an fd that has been evicted.  No harm done.
+				continue
+			}
+			s.WakeFD(netfd, mode, nil)
+		}
+	}
+}
+
+func (s *pollServer) WaitRead(fd *netFD) error {
+	err := s.AddFD(fd, 'r')
+	if err == nil {
+		err = <-fd.cr
+	}
+	return err
+}
+
+func (s *pollServer) WaitWrite(fd *netFD) error {
+	err := s.AddFD(fd, 'w')
+	if err == nil {
+		err = <-fd.cw
+	}
+	return err
+}
+
+// Network FD methods.
+// Spread network FDs over several pollServers.
+
+var pollMaxN int
+var pollservers []*pollServer
+var startServersOnce []func()
+
+var canCancelIO = true // used for testing current package
+
+func sysInit() {
+	pollMaxN = runtime.NumCPU()
+	if pollMaxN > 8 {
+		pollMaxN = 8 // No improvement then.
+	}
+	pollservers = make([]*pollServer, pollMaxN)
+	startServersOnce = make([]func(), pollMaxN)
+	for i := 0; i < pollMaxN; i++ {
+		k := i
+		once := new(sync.Once)
+		startServersOnce[i] = func() { once.Do(func() { startServer(k) }) }
+	}
+}
+
+func startServer(k int) {
+	p, err := newPollServer()
+	if err != nil {
+		panic(err)
+	}
+	pollservers[k] = p
+}
+
+func server(fd int) *pollServer {
+	pollN := runtime.GOMAXPROCS(0)
+	if pollN > pollMaxN {
+		pollN = pollMaxN
+	}
+	k := fd % pollN
+	startServersOnce[k]()
+	return pollservers[k]
+}
+
+func dialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
+	deadline := time.Now().Add(timeout)
+	ra, err := resolveAddr("dial", net, addr, deadline)
+	if err != nil {
+		return nil, err
+	}
+	return dial(net, addr, noLocalAddr, ra, deadline)
+}
+
+func newFD(fd, family, sotype int, net string) (*netFD, error) {
+	netfd := &netFD{
+		sysfd:  fd,
+		family: family,
+		sotype: sotype,
+		net:    net,
+	}
+	netfd.cr = make(chan error, 1)
+	netfd.cw = make(chan error, 1)
+	netfd.pollServer = server(fd)
+	return netfd, nil
+}
+
+func (fd *netFD) setAddr(laddr, raddr Addr) {
+	fd.laddr = laddr
+	fd.raddr = raddr
+	fd.sysfile = os.NewFile(uintptr(fd.sysfd), fd.net)
+}
+
+func (fd *netFD) name() string {
+	var ls, rs string
+	if fd.laddr != nil {
+		ls = fd.laddr.String()
+	}
+	if fd.raddr != nil {
+		rs = fd.raddr.String()
+	}
+	return fd.net + ":" + ls + "->" + rs
+}
+
+func (fd *netFD) connect(ra syscall.Sockaddr) error {
+	err := syscall.Connect(fd.sysfd, ra)
+	if err == syscall.EINPROGRESS {
+		if err = fd.pollServer.WaitWrite(fd); err != nil {
+			return err
+		}
+		var e int
+		e, err = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
+		if err != nil {
+			return os.NewSyscallError("getsockopt", err)
+		}
+		if e != 0 {
+			err = syscall.Errno(e)
+		}
+	}
+	return err
+}
+
+// Add a reference to this fd.
+// If closing==true, pollserver must be locked; mark the fd as closing.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) incref(closing bool) error {
+	fd.sysmu.Lock()
+	if fd.closing {
+		fd.sysmu.Unlock()
+		return errClosing
+	}
+	fd.sysref++
+	if closing {
+		fd.closing = true
+	}
+	fd.sysmu.Unlock()
+	return nil
+}
+
+// Remove a reference to this FD and close if we've been asked to do so (and
+// there are no references left.
+func (fd *netFD) decref() {
+	fd.sysmu.Lock()
+	fd.sysref--
+	if fd.closing && fd.sysref == 0 && fd.sysfile != nil {
+		fd.sysfile.Close()
+		fd.sysfile = nil
+		fd.sysfd = -1
+	}
+	fd.sysmu.Unlock()
+}
+
+func (fd *netFD) Close() error {
+	fd.pollServer.Lock() // needed for both fd.incref(true) and pollserver.Evict
+	if err := fd.incref(true); err != nil {
+		fd.pollServer.Unlock()
+		return err
+	}
+	// Unblock any I/O.  Once it all unblocks and returns,
+	// so that it cannot be referring to fd.sysfd anymore,
+	// the final decref will close fd.sysfd.  This should happen
+	// fairly quickly, since all the I/O is non-blocking, and any
+	// attempts to block in the pollserver will return errClosing.
+	doWakeup := fd.pollServer.Evict(fd)
+	fd.pollServer.Unlock()
+	fd.decref()
+	if doWakeup {
+		fd.pollServer.Wakeup()
+	}
+	return nil
+}
+
+func (fd *netFD) shutdown(how int) error {
+	if err := fd.incref(false); err != nil {
+		return err
+	}
+	defer fd.decref()
+	err := syscall.Shutdown(fd.sysfd, how)
+	if err != nil {
+		return &OpError{"shutdown", fd.net, fd.laddr, err}
+	}
+	return nil
+}
+
+func (fd *netFD) CloseRead() error {
+	return fd.shutdown(syscall.SHUT_RD)
+}
+
+func (fd *netFD) CloseWrite() error {
+	return fd.shutdown(syscall.SHUT_WR)
+}
+
+func (fd *netFD) Read(p []byte) (n int, err error) {
+	fd.rio.Lock()
+	defer fd.rio.Unlock()
+	if err := fd.incref(false); err != nil {
+		return 0, err
+	}
+	defer fd.decref()
+	for {
+		if fd.rdeadline.expired() {
+			err = errTimeout
+			break
+		}
+		n, err = syscall.Read(int(fd.sysfd), p)
+		if err != nil {
+			n = 0
+			if err == syscall.EAGAIN {
+				if err = fd.pollServer.WaitRead(fd); err == nil {
+					continue
+				}
+			}
+		}
+		err = chkReadErr(n, err, fd)
+		break
+	}
+	if err != nil && err != io.EOF {
+		err = &OpError{"read", fd.net, fd.raddr, err}
+	}
+	return
+}
+
+func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
+	fd.rio.Lock()
+	defer fd.rio.Unlock()
+	if err := fd.incref(false); err != nil {
+		return 0, nil, err
+	}
+	defer fd.decref()
+	for {
+		if fd.rdeadline.expired() {
+			err = errTimeout
+			break
+		}
+		n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
+		if err != nil {
+			n = 0
+			if err == syscall.EAGAIN {
+				if err = fd.pollServer.WaitRead(fd); err == nil {
+					continue
+				}
+			}
+		}
+		err = chkReadErr(n, err, fd)
+		break
+	}
+	if err != nil && err != io.EOF {
+		err = &OpError{"read", fd.net, fd.laddr, err}
+	}
+	return
+}
+
+func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
+	fd.rio.Lock()
+	defer fd.rio.Unlock()
+	if err := fd.incref(false); err != nil {
+		return 0, 0, 0, nil, err
+	}
+	defer fd.decref()
+	for {
+		if fd.rdeadline.expired() {
+			err = errTimeout
+			break
+		}
+		n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
+		if err != nil {
+			// TODO(dfc) should n and oobn be set to 0
+			if err == syscall.EAGAIN {
+				if err = fd.pollServer.WaitRead(fd); err == nil {
+					continue
+				}
+			}
+		}
+		err = chkReadErr(n, err, fd)
+		break
+	}
+	if err != nil && err != io.EOF {
+		err = &OpError{"read", fd.net, fd.laddr, err}
+	}
+	return
+}
+
+func chkReadErr(n int, err error, fd *netFD) error {
+	if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM && fd.sotype != syscall.SOCK_RAW {
+		return io.EOF
+	}
+	return err
+}
+
+func (fd *netFD) Write(p []byte) (nn int, err error) {
+	fd.wio.Lock()
+	defer fd.wio.Unlock()
+	if err := fd.incref(false); err != nil {
+		return 0, err
+	}
+	defer fd.decref()
+	for {
+		if fd.wdeadline.expired() {
+			err = errTimeout
+			break
+		}
+		var n int
+		n, err = syscall.Write(int(fd.sysfd), p[nn:])
+		if n > 0 {
+			nn += n
+		}
+		if nn == len(p) {
+			break
+		}
+		if err == syscall.EAGAIN {
+			if err = fd.pollServer.WaitWrite(fd); err == nil {
+				continue
+			}
+		}
+		if err != nil {
+			n = 0
+			break
+		}
+		if n == 0 {
+			err = io.ErrUnexpectedEOF
+			break
+		}
+	}
+	if err != nil {
+		err = &OpError{"write", fd.net, fd.raddr, err}
+	}
+	return nn, err
+}
+
+func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
+	fd.wio.Lock()
+	defer fd.wio.Unlock()
+	if err := fd.incref(false); err != nil {
+		return 0, err
+	}
+	defer fd.decref()
+	for {
+		if fd.wdeadline.expired() {
+			err = errTimeout
+			break
+		}
+		err = syscall.Sendto(fd.sysfd, p, 0, sa)
+		if err == syscall.EAGAIN {
+			if err = fd.pollServer.WaitWrite(fd); err == nil {
+				continue
+			}
+		}
+		break
+	}
+	if err == nil {
+		n = len(p)
+	} else {
+		err = &OpError{"write", fd.net, fd.raddr, err}
+	}
+	return
+}
+
+func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
+	fd.wio.Lock()
+	defer fd.wio.Unlock()
+	if err := fd.incref(false); err != nil {
+		return 0, 0, err
+	}
+	defer fd.decref()
+	for {
+		if fd.wdeadline.expired() {
+			err = errTimeout
+			break
+		}
+		err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
+		if err == syscall.EAGAIN {
+			if err = fd.pollServer.WaitWrite(fd); err == nil {
+				continue
+			}
+		}
+		break
+	}
+	if err == nil {
+		n = len(p)
+		oobn = len(oob)
+	} else {
+		err = &OpError{"write", fd.net, fd.raddr, err}
+	}
+	return
+}
+
+func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
+	if err := fd.incref(false); err != nil {
+		return nil, err
+	}
+	defer fd.decref()
+
+	var s int
+	var rsa syscall.Sockaddr
+	for {
+		s, rsa, err = accept(fd.sysfd)
+		if err != nil {
+			if err == syscall.EAGAIN {
+				if err = fd.pollServer.WaitRead(fd); err == nil {
+					continue
+				}
+			} else if err == syscall.ECONNABORTED {
+				// This means that a socket on the listen queue was closed
+				// before we Accept()ed it; it's a silly error, so try again.
+				continue
+			}
+			return nil, &OpError{"accept", fd.net, fd.laddr, err}
+		}
+		break
+	}
+
+	if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
+		closesocket(s)
+		return nil, err
+	}
+	lsa, _ := syscall.Getsockname(netfd.sysfd)
+	netfd.setAddr(toAddr(lsa), toAddr(rsa))
+	return netfd, nil
+}
+
+func (fd *netFD) dup() (f *os.File, err error) {
+	syscall.ForkLock.RLock()
+	ns, err := syscall.Dup(fd.sysfd)
+	if err != nil {
+		syscall.ForkLock.RUnlock()
+		return nil, &OpError{"dup", fd.net, fd.laddr, err}
+	}
+	syscall.CloseOnExec(ns)
+	syscall.ForkLock.RUnlock()
+
+	// We want blocking mode for the new fd, hence the double negative.
+	// This also puts the old fd into blocking mode, meaning that
+	// I/O will block the thread instead of letting us use the epoll server.
+	// Everything will still work, just with more threads.
+	if err = syscall.SetNonblock(ns, false); err != nil {
+		return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
+	}
+
+	return os.NewFile(uintptr(ns), fd.name()), nil
+}
+
+func closesocket(s int) error {
+	return syscall.Close(s)
+}
diff --git a/src/pkg/net/fd_unix_test.go b/src/pkg/net/fd_unix_test.go
new file mode 100644
index 0000000..664ef1b
--- /dev/null
+++ b/src/pkg/net/fd_unix_test.go
@@ -0,0 +1,58 @@
+// 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 freebsd linux netbsd openbsd
+
+package net
+
+import (
+	"io"
+	"syscall"
+	"testing"
+)
+
+var chkReadErrTests = []struct {
+	n        int
+	err      error
+	fd       *netFD
+	expected error
+}{
+
+	{100, nil, &netFD{sotype: syscall.SOCK_STREAM}, nil},
+	{100, io.EOF, &netFD{sotype: syscall.SOCK_STREAM}, io.EOF},
+	{100, errClosing, &netFD{sotype: syscall.SOCK_STREAM}, errClosing},
+	{0, nil, &netFD{sotype: syscall.SOCK_STREAM}, io.EOF},
+	{0, io.EOF, &netFD{sotype: syscall.SOCK_STREAM}, io.EOF},
+	{0, errClosing, &netFD{sotype: syscall.SOCK_STREAM}, errClosing},
+
+	{100, nil, &netFD{sotype: syscall.SOCK_DGRAM}, nil},
+	{100, io.EOF, &netFD{sotype: syscall.SOCK_DGRAM}, io.EOF},
+	{100, errClosing, &netFD{sotype: syscall.SOCK_DGRAM}, errClosing},
+	{0, nil, &netFD{sotype: syscall.SOCK_DGRAM}, nil},
+	{0, io.EOF, &netFD{sotype: syscall.SOCK_DGRAM}, io.EOF},
+	{0, errClosing, &netFD{sotype: syscall.SOCK_DGRAM}, errClosing},
+
+	{100, nil, &netFD{sotype: syscall.SOCK_SEQPACKET}, nil},
+	{100, io.EOF, &netFD{sotype: syscall.SOCK_SEQPACKET}, io.EOF},
+	{100, errClosing, &netFD{sotype: syscall.SOCK_SEQPACKET}, errClosing},
+	{0, nil, &netFD{sotype: syscall.SOCK_SEQPACKET}, io.EOF},
+	{0, io.EOF, &netFD{sotype: syscall.SOCK_SEQPACKET}, io.EOF},
+	{0, errClosing, &netFD{sotype: syscall.SOCK_SEQPACKET}, errClosing},
+
+	{100, nil, &netFD{sotype: syscall.SOCK_RAW}, nil},
+	{100, io.EOF, &netFD{sotype: syscall.SOCK_RAW}, io.EOF},
+	{100, errClosing, &netFD{sotype: syscall.SOCK_RAW}, errClosing},
+	{0, nil, &netFD{sotype: syscall.SOCK_RAW}, nil},
+	{0, io.EOF, &netFD{sotype: syscall.SOCK_RAW}, io.EOF},
+	{0, errClosing, &netFD{sotype: syscall.SOCK_RAW}, errClosing},
+}
+
+func TestChkReadErr(t *testing.T) {
+	for _, tt := range chkReadErrTests {
+		actual := chkReadErr(tt.n, tt.err, tt.fd)
+		if actual != tt.expected {
+			t.Errorf("chkReadError(%v, %v, %v): expected %v, actual %v", tt.n, tt.err, tt.fd.sotype, tt.expected, actual)
+		}
+	}
+}
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index 45f5c2d..0e331b4 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -17,19 +17,58 @@ import (
 
 var initErr error
 
-func init() {
+// CancelIo Windows API cancels all outstanding IO for a particular
+// socket on current thread. To overcome that limitation, we run
+// special goroutine, locked to OS single thread, that both starts
+// and cancels IO. It means, there are 2 unavoidable thread switches
+// for every IO.
+// Some newer versions of Windows has new CancelIoEx API, that does
+// not have that limitation and can be used from any thread. This
+// package uses CancelIoEx API, if present, otherwise it fallback
+// to CancelIo.
+
+var canCancelIO bool // determines if CancelIoEx API is present
+
+func sysInit() {
 	var d syscall.WSAData
 	e := syscall.WSAStartup(uint32(0x202), &d)
 	if e != nil {
 		initErr = os.NewSyscallError("WSAStartup", e)
 	}
+	canCancelIO = syscall.LoadCancelIoEx() == nil
+	if syscall.LoadGetAddrInfo() == nil {
+		lookupPort = newLookupPort
+		lookupIP = newLookupIP
+	}
 }
 
 func closesocket(s syscall.Handle) error {
 	return syscall.Closesocket(s)
 }
 
-// Interface for all io operations.
+func canUseConnectEx(net string) bool {
+	if net == "udp" || net == "udp4" || net == "udp6" {
+		// ConnectEx windows API does not support connectionless sockets.
+		return false
+	}
+	return syscall.LoadConnectEx() == nil
+}
+
+func dialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
+	if !canUseConnectEx(net) {
+		// Use the relatively inefficient goroutine-racing
+		// implementation of DialTimeout.
+		return dialTimeoutRace(net, addr, timeout)
+	}
+	deadline := time.Now().Add(timeout)
+	ra, err := resolveAddr("dial", net, addr, deadline)
+	if err != nil {
+		return nil, err
+	}
+	return dial(net, addr, noLocalAddr, ra, deadline)
+}
+
+// Interface for all IO operations.
 type anOpIface interface {
 	Op() *anOp
 	Name() string
@@ -42,7 +81,7 @@ type ioResult struct {
 	err error
 }
 
-// anOp implements functionality common to all io operations.
+// anOp implements functionality common to all IO operations.
 type anOp struct {
 	// Used by IOCP interface, it must be first field
 	// of the struct, as our code rely on it.
@@ -75,7 +114,7 @@ func (o *anOp) Op() *anOp {
 	return o
 }
 
-// bufOp is used by io operations that read / write
+// bufOp is used by IO operations that read / write
 // data from / to client buffer.
 type bufOp struct {
 	anOp
@@ -92,7 +131,7 @@ func (o *bufOp) Init(fd *netFD, buf []byte, mode int) {
 	}
 }
 
-// resultSrv will retrieve all io completion results from
+// resultSrv will retrieve all IO completion results from
 // iocp and send them to the correspondent waiting client
 // goroutine via channel supplied in the request.
 type resultSrv struct {
@@ -107,7 +146,7 @@ func (s *resultSrv) Run() {
 		r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, syscall.INFINITE)
 		switch {
 		case r.err == nil:
-			// Dequeued successfully completed io packet.
+			// Dequeued successfully completed IO packet.
 		case r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil:
 			// Wait has timed out (should not happen now, but might be used in the future).
 			panic("GetQueuedCompletionStatus timed out")
@@ -115,22 +154,23 @@ func (s *resultSrv) Run() {
 			// Failed to dequeue anything -> report the error.
 			panic("GetQueuedCompletionStatus failed " + r.err.Error())
 		default:
-			// Dequeued failed io packet.
+			// Dequeued failed IO packet.
 		}
 		(*anOp)(unsafe.Pointer(o)).resultc <- r
 	}
 }
 
-// ioSrv executes net io requests.
+// ioSrv executes net IO requests.
 type ioSrv struct {
-	submchan chan anOpIface // submit io requests
-	canchan  chan anOpIface // cancel io requests
+	submchan chan anOpIface // submit IO requests
+	canchan  chan anOpIface // cancel IO requests
 }
 
-// ProcessRemoteIO will execute submit io requests on behalf
+// ProcessRemoteIO will execute submit IO requests on behalf
 // of other goroutines, all on a single os thread, so it can
 // cancel them later. Results of all operations will be sent
 // back to their requesters via channel supplied in request.
+// It is used only when the CancelIoEx API is unavailable.
 func (s *ioSrv) ProcessRemoteIO() {
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
@@ -144,20 +184,30 @@ func (s *ioSrv) ProcessRemoteIO() {
 	}
 }
 
-// ExecIO executes a single io operation. It either executes it
-// inline, or, if a deadline is employed, passes the request onto
+// ExecIO executes a single IO operation oi. It submits and cancels
+// IO in the current thread for systems where Windows CancelIoEx API
+// is available. Alternatively, it passes the request onto
 // a special goroutine and waits for completion or cancels request.
 // deadline is unix nanos.
 func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (int, error) {
 	var err error
 	o := oi.Op()
+	// Calculate timeout delta.
+	var delta int64
 	if deadline != 0 {
+		delta = deadline - time.Now().UnixNano()
+		if delta <= 0 {
+			return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, errTimeout}
+		}
+	}
+	// Start IO.
+	if canCancelIO {
+		err = oi.Submit()
+	} else {
 		// Send request to a special dedicated thread,
-		// so it can stop the io with CancelIO later.
+		// so it can stop the IO with CancelIO later.
 		s.submchan <- oi
 		err = <-o.errnoc
-	} else {
-		err = oi.Submit()
 	}
 	switch err {
 	case nil:
@@ -168,27 +218,46 @@ func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (int, error) {
 	default:
 		return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err}
 	}
+	// Setup timer, if deadline is given.
+	var timer <-chan time.Time
+	if delta > 0 {
+		t := time.NewTimer(time.Duration(delta) * time.Nanosecond)
+		defer t.Stop()
+		timer = t.C
+	}
 	// Wait for our request to complete.
 	var r ioResult
-	if deadline != 0 {
-		dt := deadline - time.Now().UnixNano()
-		if dt < 1 {
-			dt = 1
-		}
-		timer := time.NewTimer(time.Duration(dt) * time.Nanosecond)
-		defer timer.Stop()
-		select {
-		case r = <-o.resultc:
-		case <-timer.C:
+	var cancelled, timeout bool
+	select {
+	case r = <-o.resultc:
+	case <-timer:
+		cancelled = true
+		timeout = true
+	case <-o.fd.closec:
+		cancelled = true
+	}
+	if cancelled {
+		// Cancel it.
+		if canCancelIO {
+			err := syscall.CancelIoEx(syscall.Handle(o.Op().fd.sysfd), &o.o)
+			// Assuming ERROR_NOT_FOUND is returned, if IO is completed.
+			if err != nil && err != syscall.ERROR_NOT_FOUND {
+				// TODO(brainman): maybe do something else, but panic.
+				panic(err)
+			}
+		} else {
 			s.canchan <- oi
 			<-o.errnoc
-			r = <-o.resultc
-			if r.err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
-				r.err = syscall.EWOULDBLOCK
-			}
 		}
-	} else {
+		// Wait for IO to be canceled or complete successfully.
 		r = <-o.resultc
+		if r.err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
+			if timeout {
+				r.err = errTimeout
+			} else {
+				r.err = errClosing
+			}
+		}
 	}
 	if r.err != nil {
 		err = &OpError{oi.Name(), o.fd.net, o.fd.laddr, r.err}
@@ -211,9 +280,13 @@ func startServer() {
 	go resultsrv.Run()
 
 	iosrv = new(ioSrv)
-	iosrv.submchan = make(chan anOpIface)
-	iosrv.canchan = make(chan anOpIface)
-	go iosrv.ProcessRemoteIO()
+	if !canCancelIO {
+		// Only CancelIo API is available. Lets start special goroutine
+		// locked to an OS thread, that both starts and cancels IO.
+		iosrv.submchan = make(chan anOpIface)
+		iosrv.canchan = make(chan anOpIface)
+		go iosrv.ProcessRemoteIO()
+	}
 }
 
 // Network file descriptor.
@@ -233,12 +306,13 @@ type netFD struct {
 	raddr       Addr
 	resultc     [2]chan ioResult // read/write completion results
 	errnoc      [2]chan error    // read/write submit or cancel operation errors
+	closec      chan bool        // used by Close to cancel pending IO
+
+	// serialize access to Read and Write methods
+	rio, wio sync.Mutex
 
-	// owned by client
-	rdeadline int64
-	rio       sync.Mutex
-	wdeadline int64
-	wio       sync.Mutex
+	// read and write deadlines
+	rdeadline, wdeadline deadline
 }
 
 func allocFD(fd syscall.Handle, family, sotype int, net string) *netFD {
@@ -247,8 +321,8 @@ func allocFD(fd syscall.Handle, family, sotype int, net string) *netFD {
 		family: family,
 		sotype: sotype,
 		net:    net,
+		closec: make(chan bool),
 	}
-	runtime.SetFinalizer(netfd, (*netFD).Close)
 	return netfd
 }
 
@@ -267,13 +341,52 @@ func newFD(fd syscall.Handle, family, proto int, net string) (*netFD, error) {
 func (fd *netFD) setAddr(laddr, raddr Addr) {
 	fd.laddr = laddr
 	fd.raddr = raddr
+	runtime.SetFinalizer(fd, (*netFD).closesocket)
 }
 
-func (fd *netFD) connect(ra syscall.Sockaddr) error {
-	return syscall.Connect(fd.sysfd, ra)
+// Make new connection.
+
+type connectOp struct {
+	anOp
+	ra syscall.Sockaddr
+}
+
+func (o *connectOp) Submit() error {
+	return syscall.ConnectEx(o.fd.sysfd, o.ra, nil, 0, nil, &o.o)
 }
 
-var errClosing = errors.New("use of closed network connection")
+func (o *connectOp) Name() string {
+	return "ConnectEx"
+}
+
+func (fd *netFD) connect(ra syscall.Sockaddr) error {
+	if !canUseConnectEx(fd.net) {
+		return syscall.Connect(fd.sysfd, ra)
+	}
+	// ConnectEx windows API requires an unconnected, previously bound socket.
+	var la syscall.Sockaddr
+	switch ra.(type) {
+	case *syscall.SockaddrInet4:
+		la = &syscall.SockaddrInet4{}
+	case *syscall.SockaddrInet6:
+		la = &syscall.SockaddrInet6{}
+	default:
+		panic("unexpected type in connect")
+	}
+	if err := syscall.Bind(fd.sysfd, la); err != nil {
+		return err
+	}
+	// Call ConnectEx API.
+	var o connectOp
+	o.Init(fd, 'w')
+	o.ra = ra
+	_, err := iosrv.ExecIO(&o, fd.wdeadline.value())
+	if err != nil {
+		return err
+	}
+	// Refresh socket properties.
+	return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
+}
 
 // Add a reference to this fd.
 // If closing==true, mark the fd as closing.
@@ -299,24 +412,12 @@ func (fd *netFD) incref(closing bool) error {
 // Remove a reference to this FD and close if we've been asked to do so (and
 // there are no references left.
 func (fd *netFD) decref() {
+	if fd == nil {
+		return
+	}
 	fd.sysmu.Lock()
 	fd.sysref--
-	// NOTE(rsc): On Unix we check fd.sysref == 0 here before closing,
-	// but on Windows we have no way to wake up the blocked I/O other
-	// than closing the socket (or calling Shutdown, which breaks other
-	// programs that might have a reference to the socket).  So there is
-	// a small race here that we might close fd.sysfd and then some other
-	// goroutine might start a read of fd.sysfd (having read it before we
-	// write InvalidHandle to it), which might refer to some other file
-	// if the specific handle value gets reused.  I think handle values on
-	// Windows are not reused as aggressively as file descriptors on Unix,
-	// so this might be tolerable.
-	if fd.closing && fd.sysfd != syscall.InvalidHandle {
-		// In case the user has set linger, switch to blocking mode so
-		// the close blocks.  As long as this doesn't happen often, we
-		// can handle the extra OS processes.  Otherwise we'll need to
-		// use the resultsrv for Close too.  Sigh.
-		syscall.SetNonblock(fd.sysfd, false)
+	if fd.closing && fd.sysref == 0 && fd.sysfd != syscall.InvalidHandle {
 		closesocket(fd.sysfd)
 		fd.sysfd = syscall.InvalidHandle
 		// no need for a finalizer anymore
@@ -329,14 +430,22 @@ func (fd *netFD) Close() error {
 	if err := fd.incref(true); err != nil {
 		return err
 	}
-	fd.decref()
+	defer fd.decref()
+	// unblock pending reader and writer
+	close(fd.closec)
+	// wait for both reader and writer to exit
+	fd.rio.Lock()
+	defer fd.rio.Unlock()
+	fd.wio.Lock()
+	defer fd.wio.Unlock()
 	return nil
 }
 
 func (fd *netFD) shutdown(how int) error {
-	if fd == nil || fd.sysfd == syscall.InvalidHandle {
-		return syscall.EINVAL
+	if err := fd.incref(false); err != nil {
+		return err
 	}
+	defer fd.decref()
 	err := syscall.Shutdown(fd.sysfd, how)
 	if err != nil {
 		return &OpError{"shutdown", fd.net, fd.laddr, err}
@@ -352,6 +461,10 @@ func (fd *netFD) CloseWrite() error {
 	return fd.shutdown(syscall.SHUT_WR)
 }
 
+func (fd *netFD) closesocket() error {
+	return closesocket(fd.sysfd)
+}
+
 // Read from network.
 
 type readOp struct {
@@ -368,21 +481,15 @@ func (o *readOp) Name() string {
 }
 
 func (fd *netFD) Read(buf []byte) (int, error) {
-	if fd == nil {
-		return 0, syscall.EINVAL
-	}
-	fd.rio.Lock()
-	defer fd.rio.Unlock()
 	if err := fd.incref(false); err != nil {
 		return 0, err
 	}
 	defer fd.decref()
-	if fd.sysfd == syscall.InvalidHandle {
-		return 0, syscall.EINVAL
-	}
+	fd.rio.Lock()
+	defer fd.rio.Unlock()
 	var o readOp
 	o.Init(fd, buf, 'r')
-	n, err := iosrv.ExecIO(&o, fd.rdeadline)
+	n, err := iosrv.ExecIO(&o, fd.rdeadline.value())
 	if err == nil && n == 0 {
 		err = io.EOF
 	}
@@ -407,22 +514,19 @@ func (o *readFromOp) Name() string {
 }
 
 func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
-	if fd == nil {
-		return 0, nil, syscall.EINVAL
-	}
 	if len(buf) == 0 {
 		return 0, nil, nil
 	}
-	fd.rio.Lock()
-	defer fd.rio.Unlock()
 	if err := fd.incref(false); err != nil {
 		return 0, nil, err
 	}
 	defer fd.decref()
+	fd.rio.Lock()
+	defer fd.rio.Unlock()
 	var o readFromOp
 	o.Init(fd, buf, 'r')
 	o.rsan = int32(unsafe.Sizeof(o.rsa))
-	n, err = iosrv.ExecIO(&o, fd.rdeadline)
+	n, err = iosrv.ExecIO(&o, fd.rdeadline.value())
 	if err != nil {
 		return 0, nil, err
 	}
@@ -446,18 +550,15 @@ func (o *writeOp) Name() string {
 }
 
 func (fd *netFD) Write(buf []byte) (int, error) {
-	if fd == nil {
-		return 0, syscall.EINVAL
-	}
-	fd.wio.Lock()
-	defer fd.wio.Unlock()
 	if err := fd.incref(false); err != nil {
 		return 0, err
 	}
 	defer fd.decref()
+	fd.wio.Lock()
+	defer fd.wio.Unlock()
 	var o writeOp
 	o.Init(fd, buf, 'w')
-	return iosrv.ExecIO(&o, fd.wdeadline)
+	return iosrv.ExecIO(&o, fd.wdeadline.value())
 }
 
 // WriteTo to network.
@@ -477,25 +578,19 @@ func (o *writeToOp) Name() string {
 }
 
 func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
-	if fd == nil {
-		return 0, syscall.EINVAL
-	}
 	if len(buf) == 0 {
 		return 0, nil
 	}
-	fd.wio.Lock()
-	defer fd.wio.Unlock()
 	if err := fd.incref(false); err != nil {
 		return 0, err
 	}
 	defer fd.decref()
-	if fd.sysfd == syscall.InvalidHandle {
-		return 0, syscall.EINVAL
-	}
+	fd.wio.Lock()
+	defer fd.wio.Unlock()
 	var o writeToOp
 	o.Init(fd, buf, 'w')
 	o.sa = sa
-	return iosrv.ExecIO(&o, fd.wdeadline)
+	return iosrv.ExecIO(&o, fd.wdeadline.value())
 }
 
 // Accept new network connections.
@@ -524,19 +619,15 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
 	defer fd.decref()
 
 	// Get new socket.
-	// See ../syscall/exec.go for description of ForkLock.
-	syscall.ForkLock.RLock()
-	s, err := syscall.Socket(fd.family, fd.sotype, 0)
+	s, err := sysSocket(fd.family, fd.sotype, 0)
 	if err != nil {
-		syscall.ForkLock.RUnlock()
-		return nil, err
+		return nil, &OpError{"socket", fd.net, fd.laddr, err}
 	}
-	syscall.CloseOnExec(s)
-	syscall.ForkLock.RUnlock()
 
 	// Associate our new socket with IOCP.
 	onceStartServer.Do(startServer)
 	if _, err := syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); err != nil {
+		closesocket(s)
 		return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, err}
 	}
 
@@ -544,7 +635,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
 	var o acceptOp
 	o.Init(fd, 'r')
 	o.newsock = s
-	_, err = iosrv.ExecIO(&o, 0)
+	_, err = iosrv.ExecIO(&o, fd.rdeadline.value())
 	if err != nil {
 		closesocket(s)
 		return nil, err
@@ -554,7 +645,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
 	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
 	if err != nil {
 		closesocket(s)
-		return nil, err
+		return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
 	}
 
 	// Get local and peer addr out of AcceptEx buffer.
diff --git a/src/pkg/net/file.go b/src/pkg/net/file.go
deleted file mode 100644
index fc6c6fa..0000000
--- a/src/pkg/net/file.go
+++ /dev/null
@@ -1,126 +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 freebsd linux netbsd openbsd
-
-package net
-
-import (
-	"os"
-	"syscall"
-)
-
-func newFileFD(f *os.File) (*netFD, error) {
-	fd, err := syscall.Dup(int(f.Fd()))
-	if err != nil {
-		return nil, os.NewSyscallError("dup", err)
-	}
-
-	proto, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
-	if err != nil {
-		return nil, os.NewSyscallError("getsockopt", err)
-	}
-
-	family := syscall.AF_UNSPEC
-	toAddr := sockaddrToTCP
-	sa, _ := syscall.Getsockname(fd)
-	switch sa.(type) {
-	default:
-		closesocket(fd)
-		return nil, syscall.EINVAL
-	case *syscall.SockaddrInet4:
-		family = syscall.AF_INET
-		if proto == syscall.SOCK_DGRAM {
-			toAddr = sockaddrToUDP
-		} else if proto == syscall.SOCK_RAW {
-			toAddr = sockaddrToIP
-		}
-	case *syscall.SockaddrInet6:
-		family = syscall.AF_INET6
-		if proto == syscall.SOCK_DGRAM {
-			toAddr = sockaddrToUDP
-		} else if proto == syscall.SOCK_RAW {
-			toAddr = sockaddrToIP
-		}
-	case *syscall.SockaddrUnix:
-		family = syscall.AF_UNIX
-		toAddr = sockaddrToUnix
-		if proto == syscall.SOCK_DGRAM {
-			toAddr = sockaddrToUnixgram
-		} else if proto == syscall.SOCK_SEQPACKET {
-			toAddr = sockaddrToUnixpacket
-		}
-	}
-	laddr := toAddr(sa)
-	sa, _ = syscall.Getpeername(fd)
-	raddr := toAddr(sa)
-
-	netfd, err := newFD(fd, family, proto, laddr.Network())
-	if err != nil {
-		return nil, err
-	}
-	netfd.setAddr(laddr, raddr)
-	return netfd, nil
-}
-
-// 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) {
-	fd, err := newFileFD(f)
-	if err != nil {
-		return nil, err
-	}
-	switch fd.laddr.(type) {
-	case *TCPAddr:
-		return newTCPConn(fd), nil
-	case *UDPAddr:
-		return newUDPConn(fd), nil
-	case *UnixAddr:
-		return newUnixConn(fd), nil
-	case *IPAddr:
-		return newIPConn(fd), nil
-	}
-	fd.Close()
-	return nil, syscall.EINVAL
-}
-
-// 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) {
-	fd, err := newFileFD(f)
-	if err != nil {
-		return nil, err
-	}
-	switch laddr := fd.laddr.(type) {
-	case *TCPAddr:
-		return &TCPListener{fd}, nil
-	case *UnixAddr:
-		return &UnixListener{fd, laddr.Name}, nil
-	}
-	fd.Close()
-	return nil, syscall.EINVAL
-}
-
-// 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) {
-	fd, err := newFileFD(f)
-	if err != nil {
-		return nil, err
-	}
-	switch fd.laddr.(type) {
-	case *UDPAddr:
-		return newUDPConn(fd), nil
-	case *UnixAddr:
-		return newUnixConn(fd), nil
-	}
-	fd.Close()
-	return nil, syscall.EINVAL
-}
diff --git a/src/pkg/net/file_plan9.go b/src/pkg/net/file_plan9.go
index 04f7ee0..f6ee1c2 100644
--- a/src/pkg/net/file_plan9.go
+++ b/src/pkg/net/file_plan9.go
@@ -5,24 +5,147 @@
 package net
 
 import (
+	"errors"
+	"io"
 	"os"
 	"syscall"
 )
 
+func (fd *netFD) status(ln int) (string, error) {
+	if !fd.ok() {
+		return "", syscall.EINVAL
+	}
+
+	status, err := os.Open(fd.dir + "/status")
+	if err != nil {
+		return "", err
+	}
+	defer status.Close()
+	buf := make([]byte, ln)
+	n, err := io.ReadFull(status, buf[:])
+	if err != nil {
+		return "", err
+	}
+	return string(buf[:n]), nil
+}
+
+func newFileFD(f *os.File) (net *netFD, err error) {
+	var ctl *os.File
+	close := func(fd int) {
+		if err != nil {
+			syscall.Close(fd)
+		}
+	}
+
+	path, err := syscall.Fd2path(int(f.Fd()))
+	if err != nil {
+		return nil, os.NewSyscallError("fd2path", err)
+	}
+	comp := splitAtBytes(path, "/")
+	n := len(comp)
+	if n < 3 || comp[0] != "net" {
+		return nil, syscall.EPLAN9
+	}
+
+	name := comp[2]
+	switch file := comp[n-1]; file {
+	case "ctl", "clone":
+		syscall.ForkLock.RLock()
+		fd, err := syscall.Dup(int(f.Fd()), -1)
+		syscall.ForkLock.RUnlock()
+		if err != nil {
+			return nil, os.NewSyscallError("dup", err)
+		}
+		defer close(fd)
+
+		dir := "/net/" + comp[n-2]
+		ctl = os.NewFile(uintptr(fd), dir+"/"+file)
+		ctl.Seek(0, 0)
+		var buf [16]byte
+		n, err := ctl.Read(buf[:])
+		if err != nil {
+			return nil, err
+		}
+		name = string(buf[:n])
+	default:
+		if len(comp) < 4 {
+			return nil, errors.New("could not find control file for connection")
+		}
+		dir := "/net/" + comp[1] + "/" + name
+		ctl, err = os.OpenFile(dir+"/ctl", os.O_RDWR, 0)
+		if err != nil {
+			return nil, err
+		}
+		defer close(int(ctl.Fd()))
+	}
+	dir := "/net/" + comp[1] + "/" + name
+	laddr, err := readPlan9Addr(comp[1], dir+"/local")
+	if err != nil {
+		return nil, err
+	}
+	return newFD(comp[1], name, ctl, nil, laddr, nil), nil
+}
+
+func newFileConn(f *os.File) (c Conn, err error) {
+	fd, err := newFileFD(f)
+	if err != nil {
+		return nil, err
+	}
+	if !fd.ok() {
+		return nil, syscall.EINVAL
+	}
+
+	fd.data, err = os.OpenFile(fd.dir+"/data", os.O_RDWR, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	switch fd.laddr.(type) {
+	case *TCPAddr:
+		return newTCPConn(fd), nil
+	case *UDPAddr:
+		return newUDPConn(fd), nil
+	}
+	return nil, syscall.EPLAN9
+}
+
+func newFileListener(f *os.File) (l Listener, err error) {
+	fd, err := newFileFD(f)
+	if err != nil {
+		return nil, err
+	}
+	switch fd.laddr.(type) {
+	case *TCPAddr:
+	default:
+		return nil, syscall.EPLAN9
+	}
+
+	// check that file corresponds to a listener
+	s, err := fd.status(len("Listen"))
+	if err != nil {
+		return nil, err
+	}
+	if s != "Listen" {
+		return nil, errors.New("file does not represent a listener")
+	}
+
+	return &TCPListener{fd}, nil
+}
+
 // 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.EPLAN9
+	return newFileConn(f)
 }
 
 // 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 c does not affect l, and closing l does not
-// affect c.
+// 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.EPLAN9
+	return newFileListener(f)
 }
 
 // FilePacketConn returns a copy of the packet network connection
diff --git a/src/pkg/net/file_test.go b/src/pkg/net/file_test.go
index 95c0b66..acaf188 100644
--- a/src/pkg/net/file_test.go
+++ b/src/pkg/net/file_test.go
@@ -89,9 +89,8 @@ var fileListenerTests = []struct {
 
 func TestFileListener(t *testing.T) {
 	switch runtime.GOOS {
-	case "plan9", "windows":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
+	case "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 
 	for _, tt := range fileListenerTests {
@@ -181,8 +180,7 @@ var filePacketConnTests = []struct {
 func TestFilePacketConn(t *testing.T) {
 	switch runtime.GOOS {
 	case "plan9", "windows":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 
 	for _, tt := range filePacketConnTests {
diff --git a/src/pkg/net/file_unix.go b/src/pkg/net/file_unix.go
new file mode 100644
index 0000000..4c8403e
--- /dev/null
+++ b/src/pkg/net/file_unix.go
@@ -0,0 +1,136 @@
+// 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 freebsd linux netbsd openbsd
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func newFileFD(f *os.File) (*netFD, error) {
+	syscall.ForkLock.RLock()
+	fd, err := syscall.Dup(int(f.Fd()))
+	if err != nil {
+		syscall.ForkLock.RUnlock()
+		return nil, os.NewSyscallError("dup", err)
+	}
+	syscall.CloseOnExec(fd)
+	syscall.ForkLock.RUnlock()
+	if err = syscall.SetNonblock(fd, true); err != nil {
+		closesocket(fd)
+		return nil, err
+	}
+
+	sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
+	if err != nil {
+		closesocket(fd)
+		return nil, os.NewSyscallError("getsockopt", err)
+	}
+
+	family := syscall.AF_UNSPEC
+	toAddr := sockaddrToTCP
+	lsa, _ := syscall.Getsockname(fd)
+	switch lsa.(type) {
+	default:
+		closesocket(fd)
+		return nil, syscall.EINVAL
+	case *syscall.SockaddrInet4:
+		family = syscall.AF_INET
+		if sotype == syscall.SOCK_DGRAM {
+			toAddr = sockaddrToUDP
+		} else if sotype == syscall.SOCK_RAW {
+			toAddr = sockaddrToIP
+		}
+	case *syscall.SockaddrInet6:
+		family = syscall.AF_INET6
+		if sotype == syscall.SOCK_DGRAM {
+			toAddr = sockaddrToUDP
+		} else if sotype == syscall.SOCK_RAW {
+			toAddr = sockaddrToIP
+		}
+	case *syscall.SockaddrUnix:
+		family = syscall.AF_UNIX
+		toAddr = sockaddrToUnix
+		if sotype == syscall.SOCK_DGRAM {
+			toAddr = sockaddrToUnixgram
+		} else if sotype == syscall.SOCK_SEQPACKET {
+			toAddr = sockaddrToUnixpacket
+		}
+	}
+	laddr := toAddr(lsa)
+	rsa, _ := syscall.Getpeername(fd)
+	raddr := toAddr(rsa)
+
+	netfd, err := newFD(fd, family, sotype, laddr.Network())
+	if err != nil {
+		closesocket(fd)
+		return nil, err
+	}
+	netfd.setAddr(laddr, raddr)
+	return netfd, nil
+}
+
+// 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) {
+	fd, err := newFileFD(f)
+	if err != nil {
+		return nil, err
+	}
+	switch fd.laddr.(type) {
+	case *TCPAddr:
+		return newTCPConn(fd), nil
+	case *UDPAddr:
+		return newUDPConn(fd), nil
+	case *IPAddr:
+		return newIPConn(fd), nil
+	case *UnixAddr:
+		return newUnixConn(fd), nil
+	}
+	fd.Close()
+	return nil, syscall.EINVAL
+}
+
+// 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) {
+	fd, err := newFileFD(f)
+	if err != nil {
+		return nil, err
+	}
+	switch laddr := fd.laddr.(type) {
+	case *TCPAddr:
+		return &TCPListener{fd}, nil
+	case *UnixAddr:
+		return &UnixListener{fd, laddr.Name}, nil
+	}
+	fd.Close()
+	return nil, syscall.EINVAL
+}
+
+// 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) {
+	fd, err := newFileFD(f)
+	if err != nil {
+		return nil, err
+	}
+	switch fd.laddr.(type) {
+	case *UDPAddr:
+		return newUDPConn(fd), nil
+	case *UnixAddr:
+		return newUnixConn(fd), nil
+	}
+	fd.Close()
+	return nil, syscall.EINVAL
+}
diff --git a/src/pkg/net/http/cgi/child.go b/src/pkg/net/http/cgi/child.go
index 1ba7bec..100b8b7 100644
--- a/src/pkg/net/http/cgi/child.go
+++ b/src/pkg/net/http/cgi/child.go
@@ -91,10 +91,19 @@ func RequestFromMap(params map[string]string) (*http.Request, error) {
 
 	// TODO: cookies.  parsing them isn't exported, though.
 
+	uriStr := params["REQUEST_URI"]
+	if uriStr == "" {
+		// Fallback to SCRIPT_NAME, PATH_INFO and QUERY_STRING.
+		uriStr = params["SCRIPT_NAME"] + params["PATH_INFO"]
+		s := params["QUERY_STRING"]
+		if s != "" {
+			uriStr += "?" + s
+		}
+	}
 	if r.Host != "" {
 		// Hostname is provided, so we can reasonably construct a URL,
 		// even if we have to assume 'http' for the scheme.
-		rawurl := "http://" + r.Host + params["REQUEST_URI"]
+		rawurl := "http://" + r.Host + uriStr
 		url, err := url.Parse(rawurl)
 		if err != nil {
 			return nil, errors.New("cgi: failed to parse host and REQUEST_URI into a URL: " + rawurl)
@@ -104,7 +113,6 @@ func RequestFromMap(params map[string]string) (*http.Request, error) {
 	// Fallback logic if we don't have a Host header or the URL
 	// failed to parse
 	if r.URL == nil {
-		uriStr := params["REQUEST_URI"]
 		url, err := url.Parse(uriStr)
 		if err != nil {
 			return nil, errors.New("cgi: failed to parse REQUEST_URI into a URL: " + uriStr)
diff --git a/src/pkg/net/http/cgi/child_test.go b/src/pkg/net/http/cgi/child_test.go
index ec53ab8..74e0680 100644
--- a/src/pkg/net/http/cgi/child_test.go
+++ b/src/pkg/net/http/cgi/child_test.go
@@ -82,6 +82,28 @@ func TestRequestWithoutHost(t *testing.T) {
 		t.Fatalf("unexpected nil URL")
 	}
 	if g, e := req.URL.String(), "/path?a=b"; e != g {
-		t.Errorf("expected URL %q; got %q", e, g)
+		t.Errorf("URL = %q; want %q", g, e)
+	}
+}
+
+func TestRequestWithoutRequestURI(t *testing.T) {
+	env := map[string]string{
+		"SERVER_PROTOCOL": "HTTP/1.1",
+		"HTTP_HOST":       "example.com",
+		"REQUEST_METHOD":  "GET",
+		"SCRIPT_NAME":     "/dir/scriptname",
+		"PATH_INFO":       "/p1/p2",
+		"QUERY_STRING":    "a=1&b=2",
+		"CONTENT_LENGTH":  "123",
+	}
+	req, err := RequestFromMap(env)
+	if err != nil {
+		t.Fatalf("RequestFromMap: %v", err)
+	}
+	if req.URL == nil {
+		t.Fatalf("unexpected nil URL")
+	}
+	if g, e := req.URL.String(), "http://example.com/dir/scriptname/p1/p2?a=1&b=2"; e != g {
+		t.Errorf("URL = %q; want %q", g, e)
 	}
 }
diff --git a/src/pkg/net/http/cgi/host_test.go b/src/pkg/net/http/cgi/host_test.go
index 4db3d85..8c16e68 100644
--- a/src/pkg/net/http/cgi/host_test.go
+++ b/src/pkg/net/http/cgi/host_test.go
@@ -19,7 +19,6 @@ import (
 	"runtime"
 	"strconv"
 	"strings"
-	"syscall"
 	"testing"
 	"time"
 )
@@ -63,17 +62,25 @@ readlines:
 	}
 
 	for key, expected := range expectedMap {
-		if got := m[key]; got != expected {
+		got := m[key]
+		if key == "cwd" {
+			// For Windows. golang.org/issue/4645.
+			fi1, _ := os.Stat(got)
+			fi2, _ := os.Stat(expected)
+			if os.SameFile(fi1, fi2) {
+				got = expected
+			}
+		}
+		if got != expected {
 			t.Errorf("for key %q got %q; expected %q", key, got, expected)
 		}
 	}
 	return rw
 }
 
-var cgiTested = false
-var cgiWorks bool
+var cgiTested, cgiWorks bool
 
-func skipTest(t *testing.T) bool {
+func check(t *testing.T) {
 	if !cgiTested {
 		cgiTested = true
 		cgiWorks = exec.Command("./testdata/test.cgi").Run() == nil
@@ -81,16 +88,12 @@ func skipTest(t *testing.T) bool {
 	if !cgiWorks {
 		// No Perl on Windows, needed by test.cgi
 		// TODO: make the child process be Go, not Perl.
-		t.Logf("Skipping test: test.cgi failed.")
-		return true
+		t.Skip("Skipping test: test.cgi failed.")
 	}
-	return false
 }
 
 func TestCGIBasicGet(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
+	check(t)
 	h := &Handler{
 		Path: "testdata/test.cgi",
 		Root: "/test.cgi",
@@ -124,9 +127,7 @@ func TestCGIBasicGet(t *testing.T) {
 }
 
 func TestCGIBasicGetAbsPath(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
+	check(t)
 	pwd, err := os.Getwd()
 	if err != nil {
 		t.Fatalf("getwd error: %v", err)
@@ -144,9 +145,7 @@ func TestCGIBasicGetAbsPath(t *testing.T) {
 }
 
 func TestPathInfo(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
+	check(t)
 	h := &Handler{
 		Path: "testdata/test.cgi",
 		Root: "/test.cgi",
@@ -163,9 +162,7 @@ func TestPathInfo(t *testing.T) {
 }
 
 func TestPathInfoDirRoot(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
+	check(t)
 	h := &Handler{
 		Path: "testdata/test.cgi",
 		Root: "/myscript/",
@@ -181,9 +178,7 @@ func TestPathInfoDirRoot(t *testing.T) {
 }
 
 func TestDupHeaders(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
+	check(t)
 	h := &Handler{
 		Path: "testdata/test.cgi",
 	}
@@ -203,9 +198,7 @@ func TestDupHeaders(t *testing.T) {
 }
 
 func TestPathInfoNoRoot(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
+	check(t)
 	h := &Handler{
 		Path: "testdata/test.cgi",
 		Root: "",
@@ -221,9 +214,7 @@ func TestPathInfoNoRoot(t *testing.T) {
 }
 
 func TestCGIBasicPost(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
+	check(t)
 	postReq := `POST /test.cgi?a=b HTTP/1.0
 Host: example.com
 Content-Type: application/x-www-form-urlencoded
@@ -250,9 +241,7 @@ func chunk(s string) string {
 
 // The CGI spec doesn't allow chunked requests.
 func TestCGIPostChunked(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
+	check(t)
 	postReq := `POST /test.cgi?a=b HTTP/1.1
 Host: example.com
 Content-Type: application/x-www-form-urlencoded
@@ -273,9 +262,7 @@ Transfer-Encoding: chunked
 }
 
 func TestRedirect(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
+	check(t)
 	h := &Handler{
 		Path: "testdata/test.cgi",
 		Root: "/test.cgi",
@@ -290,9 +277,7 @@ func TestRedirect(t *testing.T) {
 }
 
 func TestInternalRedirect(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
+	check(t)
 	baseHandler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
 		fmt.Fprintf(rw, "basepath=%s\n", req.URL.Path)
 		fmt.Fprintf(rw, "remoteaddr=%s\n", req.RemoteAddr)
@@ -312,8 +297,9 @@ func TestInternalRedirect(t *testing.T) {
 // TestCopyError tests that we kill the process if there's an error copying
 // its output. (for example, from the client having gone away)
 func TestCopyError(t *testing.T) {
-	if skipTest(t) || runtime.GOOS == "windows" {
-		return
+	check(t)
+	if runtime.GOOS == "windows" {
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 	h := &Handler{
 		Path: "testdata/test.cgi",
@@ -353,11 +339,7 @@ func TestCopyError(t *testing.T) {
 	}
 
 	childRunning := func() bool {
-		p, err := os.FindProcess(pid)
-		if err != nil {
-			return false
-		}
-		return p.Signal(syscall.Signal(0)) == nil
+		return isProcessRunning(t, pid)
 	}
 
 	if !childRunning() {
@@ -376,10 +358,10 @@ func TestCopyError(t *testing.T) {
 }
 
 func TestDirUnix(t *testing.T) {
-	if skipTest(t) || runtime.GOOS == "windows" {
-		return
+	check(t)
+	if runtime.GOOS == "windows" {
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
-
 	cwd, _ := os.Getwd()
 	h := &Handler{
 		Path: "testdata/test.cgi",
@@ -404,8 +386,8 @@ func TestDirUnix(t *testing.T) {
 }
 
 func TestDirWindows(t *testing.T) {
-	if skipTest(t) || runtime.GOOS != "windows" {
-		return
+	if runtime.GOOS != "windows" {
+		t.Skip("Skipping windows specific test.")
 	}
 
 	cgifile, _ := filepath.Abs("testdata/test.cgi")
@@ -414,7 +396,7 @@ func TestDirWindows(t *testing.T) {
 	var err error
 	perl, err = exec.LookPath("perl")
 	if err != nil {
-		return
+		t.Skip("Skipping test: perl not found.")
 	}
 	perl, _ = filepath.Abs(perl)
 
@@ -456,7 +438,7 @@ func TestEnvOverride(t *testing.T) {
 	var err error
 	perl, err = exec.LookPath("perl")
 	if err != nil {
-		return
+		t.Skipf("Skipping test: perl not found.")
 	}
 	perl, _ = filepath.Abs(perl)
 
diff --git a/src/pkg/net/http/cgi/plan9_test.go b/src/pkg/net/http/cgi/plan9_test.go
new file mode 100644
index 0000000..c823583
--- /dev/null
+++ b/src/pkg/net/http/cgi/plan9_test.go
@@ -0,0 +1,18 @@
+// 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 plan9
+
+package cgi
+
+import (
+	"os"
+	"strconv"
+	"testing"
+)
+
+func isProcessRunning(t *testing.T, pid int) bool {
+	_, err := os.Stat("/proc/" + strconv.Itoa(pid))
+	return err == nil
+}
diff --git a/src/pkg/net/http/cgi/posix_test.go b/src/pkg/net/http/cgi/posix_test.go
new file mode 100644
index 0000000..5ff9e7d
--- /dev/null
+++ b/src/pkg/net/http/cgi/posix_test.go
@@ -0,0 +1,21 @@
+// 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 !plan9
+
+package cgi
+
+import (
+	"os"
+	"syscall"
+	"testing"
+)
+
+func isProcessRunning(t *testing.T, pid int) bool {
+	p, err := os.FindProcess(pid)
+	if err != nil {
+		return false
+	}
+	return p.Signal(syscall.Signal(0)) == nil
+}
diff --git a/src/pkg/net/http/cgi/testdata/test.cgi b/src/pkg/net/http/cgi/testdata/test.cgi
index b46b133..3214df6 100755
--- a/src/pkg/net/http/cgi/testdata/test.cgi
+++ b/src/pkg/net/http/cgi/testdata/test.cgi
@@ -8,6 +8,8 @@
 use strict;
 use Cwd;
 
+binmode STDOUT;
+
 my $q = MiniCGI->new;
 my $params = $q->Vars;
 
@@ -16,51 +18,44 @@ if ($params->{"loc"}) {
     exit(0);
 }
 
-my $NL = "\r\n";
-$NL = "\n" if $params->{mode} eq "NL";
-
-my $p = sub {
-  print "$_[0]$NL";
-};
-
-# With carriage returns
-$p->("Content-Type: text/html");
-$p->("X-CGI-Pid: $$");
-$p->("X-Test-Header: X-Test-Value");
-$p->("");
+print "Content-Type: text/html\r\n";
+print "X-CGI-Pid: $$\r\n";
+print "X-Test-Header: X-Test-Value\r\n";
+print "\r\n";
 
 if ($params->{"bigresponse"}) {
-    for (1..1024) {
-        print "A" x 1024, "\n";
+    # 17 MB, for OS X: golang.org/issue/4958
+    for (1..(17 * 1024)) {
+        print "A" x 1024, "\r\n";
     }
     exit 0;
 }
 
-print "test=Hello CGI\n";
+print "test=Hello CGI\r\n";
 
 foreach my $k (sort keys %$params) {
-  print "param-$k=$params->{$k}\n";
+    print "param-$k=$params->{$k}\r\n";
 }
 
 foreach my $k (sort keys %ENV) {
-  my $clean_env = $ENV{$k};
-  $clean_env =~ s/[\n\r]//g;
-  print "env-$k=$clean_env\n";
+    my $clean_env = $ENV{$k};
+    $clean_env =~ s/[\n\r]//g;
+    print "env-$k=$clean_env\r\n";
 }
 
-# NOTE: don't call getcwd() for windows.
-# msys return /c/go/src/... not C:\go\...
-my $dir;
+# NOTE: msys perl returns /c/go/src/... not C:\go\....
+my $dir = getcwd();
 if ($^O eq 'MSWin32' || $^O eq 'msys') {
-  my $cmd = $ENV{'COMSPEC'} || 'c:\\windows\\system32\\cmd.exe';
-  $cmd =~ s!\\!/!g;
-  $dir = `$cmd /c cd`;
-  chomp $dir;
-} else {
-  $dir = getcwd();
+    if ($dir =~ /^.:/) {
+        $dir =~ s!/!\\!g;
+    } else {
+        my $cmd = $ENV{'COMSPEC'} || 'c:\\windows\\system32\\cmd.exe';
+        $cmd =~ s!\\!/!g;
+        $dir = `$cmd /c cd`;
+        chomp $dir;
+    }
 }
-print "cwd=$dir\n";
-
+print "cwd=$dir\r\n";
 
 # A minimal version of CGI.pm, for people without the perl-modules
 # package installed.  (CGI.pm used to be part of the Perl core, but
diff --git a/src/pkg/net/http/chunked.go b/src/pkg/net/http/chunked.go
index 60a478f..91db017 100644
--- a/src/pkg/net/http/chunked.go
+++ b/src/pkg/net/http/chunked.go
@@ -11,10 +11,9 @@ package http
 
 import (
 	"bufio"
-	"bytes"
 	"errors"
+	"fmt"
 	"io"
-	"strconv"
 )
 
 const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
@@ -22,7 +21,7 @@ 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. 
+// 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
@@ -39,16 +38,17 @@ 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 string
+	var line []byte
 	line, cr.err = readLine(cr.r)
 	if cr.err != nil {
 		return
 	}
-	cr.n, cr.err = strconv.ParseUint(line, 16, 64)
+	cr.n, cr.err = parseHexUint(line)
 	if cr.err != nil {
 		return
 	}
@@ -74,9 +74,8 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
 	cr.n -= uint64(n)
 	if cr.n == 0 && cr.err == nil {
 		// end of chunk (CRLF)
-		b := make([]byte, 2)
-		if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
-			if b[0] != '\r' || b[1] != '\n' {
+		if _, cr.err = io.ReadFull(cr.r, cr.buf[:]); cr.err == nil {
+			if cr.buf[0] != '\r' || cr.buf[1] != '\n' {
 				cr.err = errors.New("malformed chunked encoding")
 			}
 		}
@@ -88,7 +87,7 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
 // 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 readLineBytes(b *bufio.Reader) (p []byte, err error) {
+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.
@@ -102,20 +101,18 @@ func readLineBytes(b *bufio.Reader) (p []byte, err error) {
 	if len(p) >= maxLineLength {
 		return nil, ErrLineTooLong
 	}
-
-	// Chop off trailing white space.
-	p = bytes.TrimRight(p, " \r\t\n")
-
-	return p, nil
+	return trimTrailingWhitespace(p), nil
 }
 
-// readLineBytes, but convert the bytes into a string.
-func readLine(b *bufio.Reader) (s string, err error) {
-	p, e := readLineBytes(b)
-	if e != nil {
-		return "", e
+func trimTrailingWhitespace(b []byte) []byte {
+	for len(b) > 0 && isASCIISpace(b[len(b)-1]) {
+		b = b[:len(b)-1]
 	}
-	return string(p), nil
+	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
@@ -147,9 +144,7 @@ func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
 		return 0, nil
 	}
 
-	head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
-
-	if _, err = io.WriteString(cw.Wire, head); err != 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 {
@@ -168,3 +163,21 @@ 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/chunked_test.go b/src/pkg/net/http/chunked_test.go
index b77ee2f..0b18c7b 100644
--- a/src/pkg/net/http/chunked_test.go
+++ b/src/pkg/net/http/chunked_test.go
@@ -9,7 +9,10 @@ package http
 
 import (
 	"bytes"
+	"fmt"
+	"io"
 	"io/ioutil"
+	"runtime"
 	"testing"
 )
 
@@ -37,3 +40,54 @@ func TestChunk(t *testing.T) {
 		t.Errorf("chunk reader read %q; want %q", g, e)
 	}
 }
+
+func TestChunkReaderAllocs(t *testing.T) {
+	// temporarily set GOMAXPROCS to 1 as we are testing memory allocations
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
+	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()
+
+	r := newChunkedReader(&buf)
+	readBuf := make([]byte, len(a)+len(b)+len(c)+1)
+
+	var ms runtime.MemStats
+	runtime.ReadMemStats(&ms)
+	m0 := ms.Mallocs
+
+	n, err := io.ReadFull(r, readBuf)
+
+	runtime.ReadMemStats(&ms)
+	mallocs := ms.Mallocs - m0
+	if mallocs > 1 {
+		t.Errorf("%d mallocs; want <= 1", mallocs)
+	}
+
+	if n != len(readBuf)-1 {
+		t.Errorf("read %d bytes; want %d", n, len(readBuf)-1)
+	}
+	if err != io.ErrUnexpectedEOF {
+		t.Errorf("read error = %v; want ErrUnexpectedEOF", err)
+	}
+}
+
+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/http/client.go b/src/pkg/net/http/client.go
index 54564e0..5ee0804 100644
--- a/src/pkg/net/http/client.go
+++ b/src/pkg/net/http/client.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // HTTP client. See RFC 2616.
-// 
+//
 // This is the high-level Client interface.
 // The low-level implementation is in transport.go.
 
@@ -14,6 +14,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"log"
 	"net/url"
 	"strings"
 )
@@ -32,17 +33,19 @@ type Client struct {
 
 	// CheckRedirect specifies the policy for handling redirects.
 	// If CheckRedirect is not nil, the client calls it before
-	// following an HTTP redirect. The arguments req and via
-	// are the upcoming request and the requests made already,
-	// oldest first. If CheckRedirect returns an error, the client
-	// returns that error instead of issue the Request req.
+	// following an HTTP redirect. The arguments req and via are
+	// the upcoming request and the requests made already, oldest
+	// first. If CheckRedirect returns an error, the Client's Get
+	// method returns both the previous Response and
+	// CheckRedirect's error (wrapped in a url.Error) instead of
+	// issuing the Request req.
 	//
 	// If CheckRedirect is nil, the Client uses its default policy,
 	// which is to stop after 10 consecutive requests.
 	CheckRedirect func(req *Request, via []*Request) error
 
-	// Jar specifies the cookie jar. 
-	// If Jar is nil, cookies are not sent in requests and ignored 
+	// Jar specifies the cookie jar.
+	// If Jar is nil, cookies are not sent in requests and ignored
 	// in responses.
 	Jar CookieJar
 }
@@ -84,10 +87,32 @@ type readClose struct {
 	io.Closer
 }
 
+func (c *Client) send(req *Request) (*Response, error) {
+	if c.Jar != nil {
+		for _, cookie := range c.Jar.Cookies(req.URL) {
+			req.AddCookie(cookie)
+		}
+	}
+	resp, err := send(req, c.Transport)
+	if err != nil {
+		return nil, err
+	}
+	if c.Jar != nil {
+		if rc := resp.Cookies(); len(rc) > 0 {
+			c.Jar.SetCookies(req.URL, rc)
+		}
+	}
+	return resp, err
+}
+
 // Do sends an HTTP request and returns an HTTP response, following
 // policy (e.g. redirects, cookies, auth) as configured on the client.
 //
-// A non-nil response always contains a non-nil resp.Body.
+// An error is returned if caused by client policy (such as
+// CheckRedirect), or if there was an HTTP protocol error.
+// A non-2xx response doesn't cause an error.
+//
+// When err is nil, resp always contains a non-nil resp.Body.
 //
 // Callers should close resp.Body when done reading from it. If
 // resp.Body is not closed, the Client's underlying RoundTripper
@@ -97,12 +122,16 @@ type readClose struct {
 // Generally Get, Post, or PostForm will be used instead of Do.
 func (c *Client) Do(req *Request) (resp *Response, err error) {
 	if req.Method == "GET" || req.Method == "HEAD" {
-		return c.doFollowingRedirects(req)
+		return c.doFollowingRedirects(req, shouldRedirectGet)
 	}
-	return send(req, c.Transport)
+	if req.Method == "POST" || req.Method == "PUT" {
+		return c.doFollowingRedirects(req, shouldRedirectPost)
+	}
+	return c.send(req)
 }
 
-// send issues an HTTP request.  Caller should close resp.Body when done reading from it.
+// send issues an HTTP request.
+// Caller should close resp.Body when done reading from it.
 func send(req *Request, t RoundTripper) (resp *Response, err error) {
 	if t == nil {
 		t = DefaultTransport
@@ -130,12 +159,19 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
 	if u := req.URL.User; u != nil {
 		req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(u.String())))
 	}
-	return t.RoundTrip(req)
+	resp, err = t.RoundTrip(req)
+	if err != nil {
+		if resp != nil {
+			log.Printf("RoundTripper returned a response & error; ignoring response")
+		}
+		return nil, err
+	}
+	return resp, nil
 }
 
 // True if the specified HTTP status code is one for which the Get utility should
 // automatically redirect.
-func shouldRedirect(statusCode int) bool {
+func shouldRedirectGet(statusCode int) bool {
 	switch statusCode {
 	case StatusMovedPermanently, StatusFound, StatusSeeOther, StatusTemporaryRedirect:
 		return true
@@ -143,6 +179,16 @@ func shouldRedirect(statusCode int) bool {
 	return false
 }
 
+// True if the specified HTTP status code is one for which the Post utility should
+// automatically redirect.
+func shouldRedirectPost(statusCode int) bool {
+	switch statusCode {
+	case StatusFound, StatusSeeOther:
+		return true
+	}
+	return false
+}
+
 // Get issues a GET to the specified URL.  If the response is one of the following
 // redirect codes, Get follows the redirect, up to a maximum of 10 redirects:
 //
@@ -151,10 +197,15 @@ func shouldRedirect(statusCode int) bool {
 //    303 (See Other)
 //    307 (Temporary Redirect)
 //
-// Caller should close r.Body when done reading from it.
+// An error is returned if there were too many redirects or if there
+// was an HTTP protocol error. A non-2xx response doesn't cause an
+// error.
+//
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
 //
 // Get is a wrapper around DefaultClient.Get.
-func Get(url string) (r *Response, err error) {
+func Get(url string) (resp *Response, err error) {
 	return DefaultClient.Get(url)
 }
 
@@ -167,18 +218,21 @@ func Get(url string) (r *Response, err error) {
 //    303 (See Other)
 //    307 (Temporary Redirect)
 //
-// Caller should close r.Body when done reading from it.
-func (c *Client) Get(url string) (r *Response, err error) {
+// An error is returned if the Client's CheckRedirect function fails
+// or if there was an HTTP protocol error. A non-2xx response doesn't
+// cause an error.
+//
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
+func (c *Client) Get(url string) (resp *Response, err error) {
 	req, err := NewRequest("GET", url, nil)
 	if err != nil {
 		return nil, err
 	}
-	return c.doFollowingRedirects(req)
+	return c.doFollowingRedirects(req, shouldRedirectGet)
 }
 
-func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) {
-	// TODO: if/when we add cookie support, the redirected request shouldn't
-	// necessarily supply the same cookies as the original.
+func (c *Client) doFollowingRedirects(ireq *Request, shouldRedirect func(int) bool) (resp *Response, err error) {
 	var base *url.URL
 	redirectChecker := c.CheckRedirect
 	if redirectChecker == nil {
@@ -190,17 +244,16 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) {
 		return nil, errors.New("http: nil Request.URL")
 	}
 
-	jar := c.Jar
-	if jar == nil {
-		jar = blackHoleJar{}
-	}
-
 	req := ireq
 	urlStr := "" // next relative or absolute URL to fetch (after first request)
+	redirectFailed := false
 	for redirect := 0; ; redirect++ {
 		if redirect != 0 {
 			req = new(Request)
 			req.Method = ireq.Method
+			if ireq.Method == "POST" || ireq.Method == "PUT" {
+				req.Method = "GET"
+			}
 			req.Header = make(Header)
 			req.URL, err = base.Parse(urlStr)
 			if err != nil {
@@ -215,26 +268,21 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) {
 
 				err = redirectChecker(req, via)
 				if err != nil {
+					redirectFailed = true
 					break
 				}
 			}
 		}
 
-		for _, cookie := range jar.Cookies(req.URL) {
-			req.AddCookie(cookie)
-		}
 		urlStr = req.URL.String()
-		if r, err = send(req, c.Transport); err != nil {
+		if resp, err = c.send(req); err != nil {
 			break
 		}
-		if c := r.Cookies(); len(c) > 0 {
-			jar.SetCookies(req.URL, c)
-		}
 
-		if shouldRedirect(r.StatusCode) {
-			r.Body.Close()
-			if urlStr = r.Header.Get("Location"); urlStr == "" {
-				err = errors.New(fmt.Sprintf("%d response missing Location header", r.StatusCode))
+		if shouldRedirect(resp.StatusCode) {
+			resp.Body.Close()
+			if urlStr = resp.Header.Get("Location"); urlStr == "" {
+				err = errors.New(fmt.Sprintf("%d response missing Location header", resp.StatusCode))
 				break
 			}
 			base = req.URL
@@ -245,12 +293,23 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) {
 	}
 
 	method := ireq.Method
-	err = &url.Error{
+	urlErr := &url.Error{
 		Op:  method[0:1] + strings.ToLower(method[1:]),
 		URL: urlStr,
 		Err: err,
 	}
-	return
+
+	if redirectFailed {
+		// Special case for Go 1 compatibility: return both the response
+		// and an error if the CheckRedirect function failed.
+		// See http://golang.org/issue/3795
+		return resp, urlErr
+	}
+
+	if resp != nil {
+		resp.Body.Close()
+	}
+	return nil, urlErr
 }
 
 func defaultCheckRedirect(req *Request, via []*Request) error {
@@ -262,49 +321,42 @@ func defaultCheckRedirect(req *Request, via []*Request) error {
 
 // Post issues a POST to the specified URL.
 //
-// Caller should close r.Body when done reading from it.
+// Caller should close resp.Body when done reading from it.
 //
 // Post is a wrapper around DefaultClient.Post
-func Post(url string, bodyType string, body io.Reader) (r *Response, err error) {
+func Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
 	return DefaultClient.Post(url, bodyType, body)
 }
 
 // Post issues a POST to the specified URL.
 //
-// Caller should close r.Body when done reading from it.
-func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err error) {
+// Caller should close resp.Body when done reading from it.
+func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
 	req, err := NewRequest("POST", url, body)
 	if err != nil {
 		return nil, err
 	}
 	req.Header.Set("Content-Type", bodyType)
-	if c.Jar != nil {
-		for _, cookie := range c.Jar.Cookies(req.URL) {
-			req.AddCookie(cookie)
-		}
-	}
-	r, err = send(req, c.Transport)
-	if err == nil && c.Jar != nil {
-		c.Jar.SetCookies(req.URL, r.Cookies())
-	}
-	return r, err
+	return c.doFollowingRedirects(req, shouldRedirectPost)
 }
 
-// PostForm issues a POST to the specified URL, 
-// with data's keys and values urlencoded as the request body.
+// PostForm issues a POST to the specified URL, with data's keys and
+// values URL-encoded as the request body.
 //
-// Caller should close r.Body when done reading from it.
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
 //
 // PostForm is a wrapper around DefaultClient.PostForm
-func PostForm(url string, data url.Values) (r *Response, err error) {
+func PostForm(url string, data url.Values) (resp *Response, err error) {
 	return DefaultClient.PostForm(url, data)
 }
 
-// PostForm issues a POST to the specified URL, 
+// PostForm issues a POST to the specified URL,
 // with data's keys and values urlencoded as the request body.
 //
-// Caller should close r.Body when done reading from it.
-func (c *Client) PostForm(url string, data url.Values) (r *Response, err error) {
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
+func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) {
 	return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
 }
 
@@ -318,7 +370,7 @@ func (c *Client) PostForm(url string, data url.Values) (r *Response, err error)
 //    307 (Temporary Redirect)
 //
 // Head is a wrapper around DefaultClient.Head
-func Head(url string) (r *Response, err error) {
+func Head(url string) (resp *Response, err error) {
 	return DefaultClient.Head(url)
 }
 
@@ -330,10 +382,10 @@ func Head(url string) (r *Response, err error) {
 //    302 (Found)
 //    303 (See Other)
 //    307 (Temporary Redirect)
-func (c *Client) Head(url string) (r *Response, err error) {
+func (c *Client) Head(url string) (resp *Response, err error) {
 	req, err := NewRequest("HEAD", url, nil)
 	if err != nil {
 		return nil, err
 	}
-	return c.doFollowingRedirects(req)
+	return c.doFollowingRedirects(req, shouldRedirectGet)
 }
diff --git a/src/pkg/net/http/client_test.go b/src/pkg/net/http/client_test.go
index 9b4261b..88649bb 100644
--- a/src/pkg/net/http/client_test.go
+++ b/src/pkg/net/http/client_test.go
@@ -7,7 +7,9 @@
 package http_test
 
 import (
+	"bytes"
 	"crypto/tls"
+	"crypto/x509"
 	"errors"
 	"fmt"
 	"io"
@@ -53,6 +55,7 @@ func pedanticReadAll(r io.Reader) (b []byte, err error) {
 }
 
 func TestClient(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(robotsTxtHandler)
 	defer ts.Close()
 
@@ -70,6 +73,7 @@ func TestClient(t *testing.T) {
 }
 
 func TestClientHead(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(robotsTxtHandler)
 	defer ts.Close()
 
@@ -92,6 +96,7 @@ func (t *recordingTransport) RoundTrip(req *Request) (resp *Response, err error)
 }
 
 func TestGetRequestFormat(t *testing.T) {
+	defer checkLeakedTransports(t)
 	tr := &recordingTransport{}
 	client := &Client{Transport: tr}
 	url := "http://dummy.faketld/"
@@ -108,6 +113,7 @@ func TestGetRequestFormat(t *testing.T) {
 }
 
 func TestPostRequestFormat(t *testing.T) {
+	defer checkLeakedTransports(t)
 	tr := &recordingTransport{}
 	client := &Client{Transport: tr}
 
@@ -134,6 +140,7 @@ func TestPostRequestFormat(t *testing.T) {
 }
 
 func TestPostFormRequestFormat(t *testing.T) {
+	defer checkLeakedTransports(t)
 	tr := &recordingTransport{}
 	client := &Client{Transport: tr}
 
@@ -175,6 +182,7 @@ func TestPostFormRequestFormat(t *testing.T) {
 }
 
 func TestRedirects(t *testing.T) {
+	defer checkLeakedTransports(t)
 	var ts *httptest.Server
 	ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		n, _ := strconv.Atoi(r.FormValue("n"))
@@ -218,6 +226,10 @@ func TestRedirects(t *testing.T) {
 		return checkErr
 	}}
 	res, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get error: %v", err)
+	}
+	res.Body.Close()
 	finalUrl := res.Request.URL.String()
 	if e, g := "<nil>", fmt.Sprintf("%v", err); e != g {
 		t.Errorf("with custom client, expected error %q, got %q", e, g)
@@ -231,9 +243,63 @@ func TestRedirects(t *testing.T) {
 
 	checkErr = errors.New("no redirects allowed")
 	res, err = c.Get(ts.URL)
-	finalUrl = res.Request.URL.String()
-	if e, g := "Get /?n=1: no redirects allowed", fmt.Sprintf("%v", err); e != g {
-		t.Errorf("with redirects forbidden, expected error %q, got %q", e, g)
+	if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr {
+		t.Errorf("with redirects forbidden, expected a *url.Error with our 'no redirects allowed' error inside; got %#v (%q)", err, err)
+	}
+	if res == nil {
+		t.Fatalf("Expected a non-nil Response on CheckRedirect failure (http://golang.org/issue/3795)")
+	}
+	res.Body.Close()
+	if res.Header.Get("Location") == "" {
+		t.Errorf("no Location header in Response")
+	}
+}
+
+func TestPostRedirects(t *testing.T) {
+	defer checkLeakedTransports(t)
+	var log struct {
+		sync.Mutex
+		bytes.Buffer
+	}
+	var ts *httptest.Server
+	ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		log.Lock()
+		fmt.Fprintf(&log.Buffer, "%s %s ", r.Method, r.RequestURI)
+		log.Unlock()
+		if v := r.URL.Query().Get("code"); v != "" {
+			code, _ := strconv.Atoi(v)
+			if code/100 == 3 {
+				w.Header().Set("Location", ts.URL)
+			}
+			w.WriteHeader(code)
+		}
+	}))
+	defer ts.Close()
+	tests := []struct {
+		suffix string
+		want   int // response code
+	}{
+		{"/", 200},
+		{"/?code=301", 301},
+		{"/?code=302", 200},
+		{"/?code=303", 200},
+		{"/?code=404", 404},
+	}
+	for _, tt := range tests {
+		res, err := Post(ts.URL+tt.suffix, "text/plain", strings.NewReader("Some content"))
+		if err != nil {
+			t.Fatal(err)
+		}
+		if res.StatusCode != tt.want {
+			t.Errorf("POST %s: status code = %d; want %d", tt.suffix, res.StatusCode, tt.want)
+		}
+	}
+	log.Lock()
+	got := log.String()
+	log.Unlock()
+	want := "POST / POST /?code=301 POST /?code=302 GET / POST /?code=303 GET / POST /?code=404 "
+	if got != want {
+		t.Errorf("Log differs.\n Got: %q\nWant: %q", got, want)
 	}
 }
 
@@ -279,6 +345,10 @@ func TestClientSendsCookieFromJar(t *testing.T) {
 	req, _ := NewRequest("GET", us, nil)
 	client.Do(req) // Note: doesn't hit network
 	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
+
+	req, _ = NewRequest("POST", us, nil)
+	client.Do(req) // Note: doesn't hit network
+	matchReturnedCookies(t, expectedCookies, tr.req.Cookies())
 }
 
 // Just enough correctness for our redirect tests. Uses the URL.Host as the
@@ -291,6 +361,9 @@ type TestJar struct {
 func (j *TestJar) SetCookies(u *url.URL, cookies []*Cookie) {
 	j.m.Lock()
 	defer j.m.Unlock()
+	if j.perURL == nil {
+		j.perURL = make(map[string][]*Cookie)
+	}
 	j.perURL[u.Host] = cookies
 }
 
@@ -301,6 +374,7 @@ func (j *TestJar) Cookies(u *url.URL) []*Cookie {
 }
 
 func TestRedirectCookiesOnRequest(t *testing.T) {
+	defer checkLeakedTransports(t)
 	var ts *httptest.Server
 	ts = httptest.NewServer(echoCookiesRedirectHandler)
 	defer ts.Close()
@@ -318,14 +392,20 @@ func TestRedirectCookiesOnRequest(t *testing.T) {
 }
 
 func TestRedirectCookiesJar(t *testing.T) {
+	defer checkLeakedTransports(t)
 	var ts *httptest.Server
 	ts = httptest.NewServer(echoCookiesRedirectHandler)
 	defer ts.Close()
-	c := &Client{}
-	c.Jar = &TestJar{perURL: make(map[string][]*Cookie)}
+	c := &Client{
+		Jar: new(TestJar),
+	}
 	u, _ := url.Parse(ts.URL)
 	c.Jar.SetCookies(u, []*Cookie{expectedCookies[0]})
-	resp, _ := c.Get(ts.URL)
+	resp, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	resp.Body.Close()
 	matchReturnedCookies(t, expectedCookies, resp.Cookies())
 }
 
@@ -348,7 +428,72 @@ func matchReturnedCookies(t *testing.T, expected, given []*Cookie) {
 	}
 }
 
+func TestJarCalls(t *testing.T) {
+	defer checkLeakedTransports(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		pathSuffix := r.RequestURI[1:]
+		if r.RequestURI == "/nosetcookie" {
+			return // dont set cookies for this path
+		}
+		SetCookie(w, &Cookie{Name: "name" + pathSuffix, Value: "val" + pathSuffix})
+		if r.RequestURI == "/" {
+			Redirect(w, r, "http://secondhost.fake/secondpath", 302)
+		}
+	}))
+	defer ts.Close()
+	jar := new(RecordingJar)
+	c := &Client{
+		Jar: jar,
+		Transport: &Transport{
+			Dial: func(_ string, _ string) (net.Conn, error) {
+				return net.Dial("tcp", ts.Listener.Addr().String())
+			},
+		},
+	}
+	_, err := c.Get("http://firsthost.fake/")
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = c.Get("http://firsthost.fake/nosetcookie")
+	if err != nil {
+		t.Fatal(err)
+	}
+	got := jar.log.String()
+	want := `Cookies("http://firsthost.fake/")
+SetCookie("http://firsthost.fake/", [name=val])
+Cookies("http://secondhost.fake/secondpath")
+SetCookie("http://secondhost.fake/secondpath", [namesecondpath=valsecondpath])
+Cookies("http://firsthost.fake/nosetcookie")
+`
+	if got != want {
+		t.Errorf("Got Jar calls:\n%s\nWant:\n%s", got, want)
+	}
+}
+
+// RecordingJar keeps a log of calls made to it, without
+// tracking any cookies.
+type RecordingJar struct {
+	mu  sync.Mutex
+	log bytes.Buffer
+}
+
+func (j *RecordingJar) SetCookies(u *url.URL, cookies []*Cookie) {
+	j.logf("SetCookie(%q, %v)\n", u, cookies)
+}
+
+func (j *RecordingJar) Cookies(u *url.URL) []*Cookie {
+	j.logf("Cookies(%q)\n", u)
+	return nil
+}
+
+func (j *RecordingJar) logf(format string, args ...interface{}) {
+	j.mu.Lock()
+	defer j.mu.Unlock()
+	fmt.Fprintf(&j.log, format, args...)
+}
+
 func TestStreamingGet(t *testing.T) {
+	defer checkLeakedTransports(t)
 	say := make(chan string)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.(Flusher).Flush()
@@ -399,6 +544,7 @@ func (c *writeCountingConn) Write(p []byte) (int, error) {
 // TestClientWrites verifies that client requests are buffered and we
 // don't send a TCP packet per line of the http request + body.
 func TestClientWrites(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 	}))
 	defer ts.Close()
@@ -432,6 +578,7 @@ func TestClientWrites(t *testing.T) {
 }
 
 func TestClientInsecureTransport(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Write([]byte("Hello"))
 	}))
@@ -446,15 +593,20 @@ func TestClientInsecureTransport(t *testing.T) {
 				InsecureSkipVerify: insecure,
 			},
 		}
+		defer tr.CloseIdleConnections()
 		c := &Client{Transport: tr}
-		_, err := c.Get(ts.URL)
+		res, err := c.Get(ts.URL)
 		if (err == nil) != insecure {
 			t.Errorf("insecure=%v: got unexpected err=%v", insecure, err)
 		}
+		if res != nil {
+			res.Body.Close()
+		}
 	}
 }
 
 func TestClientErrorWithRequestURI(t *testing.T) {
+	defer checkLeakedTransports(t)
 	req, _ := NewRequest("GET", "http://localhost:1234/", nil)
 	req.RequestURI = "/this/field/is/illegal/and/should/error/"
 	_, err := DefaultClient.Do(req)
@@ -465,3 +617,87 @@ func TestClientErrorWithRequestURI(t *testing.T) {
 		t.Errorf("wanted error mentioning RequestURI; got error: %v", err)
 	}
 }
+
+func newTLSTransport(t *testing.T, ts *httptest.Server) *Transport {
+	certs := x509.NewCertPool()
+	for _, c := range ts.TLS.Certificates {
+		roots, err := x509.ParseCertificates(c.Certificate[len(c.Certificate)-1])
+		if err != nil {
+			t.Fatalf("error parsing server's root cert: %v", err)
+		}
+		for _, root := range roots {
+			certs.AddCert(root)
+		}
+	}
+	return &Transport{
+		TLSClientConfig: &tls.Config{RootCAs: certs},
+	}
+}
+
+func TestClientWithCorrectTLSServerName(t *testing.T) {
+	defer checkLeakedTransports(t)
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.TLS.ServerName != "127.0.0.1" {
+			t.Errorf("expected client to set ServerName 127.0.0.1, got: %q", r.TLS.ServerName)
+		}
+	}))
+	defer ts.Close()
+
+	c := &Client{Transport: newTLSTransport(t, ts)}
+	if _, err := c.Get(ts.URL); err != nil {
+		t.Fatalf("expected successful TLS connection, got error: %v", err)
+	}
+}
+
+func TestClientWithIncorrectTLSServerName(t *testing.T) {
+	defer checkLeakedTransports(t)
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+	defer ts.Close()
+
+	trans := newTLSTransport(t, ts)
+	trans.TLSClientConfig.ServerName = "badserver"
+	c := &Client{Transport: trans}
+	_, err := c.Get(ts.URL)
+	if err == nil {
+		t.Fatalf("expected an error")
+	}
+	if !strings.Contains(err.Error(), "127.0.0.1") || !strings.Contains(err.Error(), "badserver") {
+		t.Errorf("wanted error mentioning 127.0.0.1 and badserver; got error: %v", err)
+	}
+}
+
+// Verify Response.ContentLength is populated. http://golang.org/issue/4126
+func TestClientHeadContentLength(t *testing.T) {
+	defer checkLeakedTransports(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if v := r.FormValue("cl"); v != "" {
+			w.Header().Set("Content-Length", v)
+		}
+	}))
+	defer ts.Close()
+	tests := []struct {
+		suffix string
+		want   int64
+	}{
+		{"/?cl=1234", 1234},
+		{"/?cl=0", 0},
+		{"", -1},
+	}
+	for _, tt := range tests {
+		req, _ := NewRequest("HEAD", ts.URL+tt.suffix, nil)
+		res, err := DefaultClient.Do(req)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if res.ContentLength != tt.want {
+			t.Errorf("Content-Length = %d; want %d", res.ContentLength, tt.want)
+		}
+		bs, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if len(bs) != 0 {
+			t.Errorf("Unexpected content: %q", bs)
+		}
+	}
+}
diff --git a/src/pkg/net/http/cookie.go b/src/pkg/net/http/cookie.go
index 2e30bbf..155b092 100644
--- a/src/pkg/net/http/cookie.go
+++ b/src/pkg/net/http/cookie.go
@@ -26,7 +26,7 @@ type Cookie struct {
 	Expires    time.Time
 	RawExpires string
 
-	// MaxAge=0 means no 'Max-Age' attribute specified. 
+	// MaxAge=0 means no 'Max-Age' attribute specified.
 	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
 	// MaxAge>0 means Max-Age attribute present and given in seconds
 	MaxAge   int
@@ -258,10 +258,5 @@ func parseCookieValueUsing(raw string, validByte func(byte) bool) (string, bool)
 }
 
 func isCookieNameValid(raw string) bool {
-	for _, c := range raw {
-		if !isToken(byte(c)) {
-			return false
-		}
-	}
-	return true
+	return strings.IndexFunc(raw, isNotToken) < 0
 }
diff --git a/src/pkg/net/http/cookie_test.go b/src/pkg/net/http/cookie_test.go
index 1e9186a..f84f739 100644
--- a/src/pkg/net/http/cookie_test.go
+++ b/src/pkg/net/http/cookie_test.go
@@ -217,7 +217,7 @@ var readCookiesTests = []struct {
 
 func TestReadCookies(t *testing.T) {
 	for i, tt := range readCookiesTests {
-		for n := 0; n < 2; n++ { // to verify readCookies doesn't mutate its input                                                  
+		for n := 0; n < 2; n++ { // to verify readCookies doesn't mutate its input
 			c := readCookies(tt.Header, tt.Filter)
 			if !reflect.DeepEqual(c, tt.Cookies) {
 				t.Errorf("#%d readCookies:\nhave: %s\nwant: %s\n", i, toJSON(c), toJSON(tt.Cookies))
diff --git a/src/pkg/net/http/cookiejar/jar.go b/src/pkg/net/http/cookiejar/jar.go
new file mode 100644
index 0000000..5d1aeb8
--- /dev/null
+++ b/src/pkg/net/http/cookiejar/jar.go
@@ -0,0 +1,494 @@
+// 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 cookiejar implements an in-memory RFC 6265-compliant http.CookieJar.
+package cookiejar
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"net/http"
+	"net/url"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+)
+
+// PublicSuffixList provides the public suffix of a domain. For example:
+//      - the public suffix of "example.com" is "com",
+//      - the public suffix of "foo1.foo2.foo3.co.uk" is "co.uk", and
+//      - the public suffix of "bar.pvt.k12.ma.us" is "pvt.k12.ma.us".
+//
+// Implementations of PublicSuffixList must be safe for concurrent use by
+// multiple goroutines.
+//
+// An implementation that always returns "" is valid and may be useful for
+// testing but it is not secure: it means that the HTTP server for foo.com can
+// set a cookie for bar.com.
+type PublicSuffixList interface {
+	// PublicSuffix returns the public suffix of domain.
+	//
+	// TODO: specify which of the caller and callee is responsible for IP
+	// addresses, for leading and trailing dots, for case sensitivity, and
+	// for IDN/Punycode.
+	PublicSuffix(domain string) string
+
+	// String returns a description of the source of this public suffix
+	// list. The description will typically contain something like a time
+	// stamp or version number.
+	String() string
+}
+
+// Options are the options for creating a new Jar.
+type Options struct {
+	// PublicSuffixList is the public suffix list that determines whether
+	// an HTTP server can set a cookie for a domain.
+	//
+	// A nil value is valid and may be useful for testing but it is not
+	// secure: it means that the HTTP server for foo.co.uk can set a cookie
+	// for bar.co.uk.
+	PublicSuffixList PublicSuffixList
+}
+
+// Jar implements the http.CookieJar interface from the net/http package.
+type Jar struct {
+	psList PublicSuffixList
+
+	// mu locks the remaining fields.
+	mu sync.Mutex
+
+	// entries is a set of entries, keyed by their eTLD+1 and subkeyed by
+	// their name/domain/path.
+	entries map[string]map[string]entry
+
+	// nextSeqNum is the next sequence number assigned to a new cookie
+	// created SetCookies.
+	nextSeqNum uint64
+}
+
+// New returns a new cookie jar. A nil *Options is equivalent to a zero
+// Options.
+func New(o *Options) (*Jar, error) {
+	jar := &Jar{
+		entries: make(map[string]map[string]entry),
+	}
+	if o != nil {
+		jar.psList = o.PublicSuffixList
+	}
+	return jar, nil
+}
+
+// entry is the internal representation of a cookie.
+//
+// This struct type is not used outside of this package per se, but the exported
+// fields are those of RFC 6265.
+type entry struct {
+	Name       string
+	Value      string
+	Domain     string
+	Path       string
+	Secure     bool
+	HttpOnly   bool
+	Persistent bool
+	HostOnly   bool
+	Expires    time.Time
+	Creation   time.Time
+	LastAccess time.Time
+
+	// seqNum is a sequence number so that Cookies returns cookies in a
+	// deterministic order, even for cookies that have equal Path length and
+	// equal Creation time. This simplifies testing.
+	seqNum uint64
+}
+
+// Id returns the domain;path;name triple of e as an id.
+func (e *entry) id() string {
+	return fmt.Sprintf("%s;%s;%s", e.Domain, e.Path, e.Name)
+}
+
+// shouldSend determines whether e's cookie qualifies to be included in a
+// request to host/path. It is the caller's responsibility to check if the
+// cookie is expired.
+func (e *entry) shouldSend(https bool, host, path string) bool {
+	return e.domainMatch(host) && e.pathMatch(path) && (https || !e.Secure)
+}
+
+// domainMatch implements "domain-match" of RFC 6265 section 5.1.3.
+func (e *entry) domainMatch(host string) bool {
+	if e.Domain == host {
+		return true
+	}
+	return !e.HostOnly && hasDotSuffix(host, e.Domain)
+}
+
+// pathMatch implements "path-match" according to RFC 6265 section 5.1.4.
+func (e *entry) pathMatch(requestPath string) bool {
+	if requestPath == e.Path {
+		return true
+	}
+	if strings.HasPrefix(requestPath, e.Path) {
+		if e.Path[len(e.Path)-1] == '/' {
+			return true // The "/any/" matches "/any/path" case.
+		} else if requestPath[len(e.Path)] == '/' {
+			return true // The "/any" matches "/any/path" case.
+		}
+	}
+	return false
+}
+
+// hasDotSuffix returns whether s ends in "."+suffix.
+func hasDotSuffix(s, suffix string) bool {
+	return len(s) > len(suffix) && s[len(s)-len(suffix)-1] == '.' && s[len(s)-len(suffix):] == suffix
+}
+
+// byPathLength is a []entry sort.Interface that sorts according to RFC 6265
+// section 5.4 point 2: by longest path and then by earliest creation time.
+type byPathLength []entry
+
+func (s byPathLength) Len() int { return len(s) }
+
+func (s byPathLength) Less(i, j int) bool {
+	if len(s[i].Path) != len(s[j].Path) {
+		return len(s[i].Path) > len(s[j].Path)
+	}
+	if !s[i].Creation.Equal(s[j].Creation) {
+		return s[i].Creation.Before(s[j].Creation)
+	}
+	return s[i].seqNum < s[j].seqNum
+}
+
+func (s byPathLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// Cookies implements the Cookies method of the http.CookieJar interface.
+//
+// It returns an empty slice if the URL's scheme is not HTTP or HTTPS.
+func (j *Jar) Cookies(u *url.URL) (cookies []*http.Cookie) {
+	return j.cookies(u, time.Now())
+}
+
+// cookies is like Cookies but takes the current time as a parameter.
+func (j *Jar) cookies(u *url.URL, now time.Time) (cookies []*http.Cookie) {
+	if u.Scheme != "http" && u.Scheme != "https" {
+		return cookies
+	}
+	host, err := canonicalHost(u.Host)
+	if err != nil {
+		return cookies
+	}
+	key := jarKey(host, j.psList)
+
+	j.mu.Lock()
+	defer j.mu.Unlock()
+
+	submap := j.entries[key]
+	if submap == nil {
+		return cookies
+	}
+
+	https := u.Scheme == "https"
+	path := u.Path
+	if path == "" {
+		path = "/"
+	}
+
+	modified := false
+	var selected []entry
+	for id, e := range submap {
+		if e.Persistent && !e.Expires.After(now) {
+			delete(submap, id)
+			modified = true
+			continue
+		}
+		if !e.shouldSend(https, host, path) {
+			continue
+		}
+		e.LastAccess = now
+		submap[id] = e
+		selected = append(selected, e)
+		modified = true
+	}
+	if modified {
+		if len(submap) == 0 {
+			delete(j.entries, key)
+		} else {
+			j.entries[key] = submap
+		}
+	}
+
+	sort.Sort(byPathLength(selected))
+	for _, e := range selected {
+		cookies = append(cookies, &http.Cookie{Name: e.Name, Value: e.Value})
+	}
+
+	return cookies
+}
+
+// SetCookies implements the SetCookies method of the http.CookieJar interface.
+//
+// It does nothing if the URL's scheme is not HTTP or HTTPS.
+func (j *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
+	j.setCookies(u, cookies, time.Now())
+}
+
+// setCookies is like SetCookies but takes the current time as parameter.
+func (j *Jar) setCookies(u *url.URL, cookies []*http.Cookie, now time.Time) {
+	if len(cookies) == 0 {
+		return
+	}
+	if u.Scheme != "http" && u.Scheme != "https" {
+		return
+	}
+	host, err := canonicalHost(u.Host)
+	if err != nil {
+		return
+	}
+	key := jarKey(host, j.psList)
+	defPath := defaultPath(u.Path)
+
+	j.mu.Lock()
+	defer j.mu.Unlock()
+
+	submap := j.entries[key]
+
+	modified := false
+	for _, cookie := range cookies {
+		e, remove, err := j.newEntry(cookie, now, defPath, host)
+		if err != nil {
+			continue
+		}
+		id := e.id()
+		if remove {
+			if submap != nil {
+				if _, ok := submap[id]; ok {
+					delete(submap, id)
+					modified = true
+				}
+			}
+			continue
+		}
+		if submap == nil {
+			submap = make(map[string]entry)
+		}
+
+		if old, ok := submap[id]; ok {
+			e.Creation = old.Creation
+			e.seqNum = old.seqNum
+		} else {
+			e.Creation = now
+			e.seqNum = j.nextSeqNum
+			j.nextSeqNum++
+		}
+		e.LastAccess = now
+		submap[id] = e
+		modified = true
+	}
+
+	if modified {
+		if len(submap) == 0 {
+			delete(j.entries, key)
+		} else {
+			j.entries[key] = submap
+		}
+	}
+}
+
+// canonicalHost strips port from host if present and returns the canonicalized
+// host name.
+func canonicalHost(host string) (string, error) {
+	var err error
+	host = strings.ToLower(host)
+	if hasPort(host) {
+		host, _, err = net.SplitHostPort(host)
+		if err != nil {
+			return "", err
+		}
+	}
+	if strings.HasSuffix(host, ".") {
+		// Strip trailing dot from fully qualified domain names.
+		host = host[:len(host)-1]
+	}
+	return toASCII(host)
+}
+
+// hasPort returns whether host contains a port number. host may be a host
+// name, an IPv4 or an IPv6 address.
+func hasPort(host string) bool {
+	colons := strings.Count(host, ":")
+	if colons == 0 {
+		return false
+	}
+	if colons == 1 {
+		return true
+	}
+	return host[0] == '[' && strings.Contains(host, "]:")
+}
+
+// jarKey returns the key to use for a jar.
+func jarKey(host string, psl PublicSuffixList) string {
+	if isIP(host) {
+		return host
+	}
+
+	var i int
+	if psl == nil {
+		i = strings.LastIndex(host, ".")
+		if i == -1 {
+			return host
+		}
+	} else {
+		suffix := psl.PublicSuffix(host)
+		if suffix == host {
+			return host
+		}
+		i = len(host) - len(suffix)
+		if i <= 0 || host[i-1] != '.' {
+			// The provided public suffix list psl is broken.
+			// Storing cookies under host is a safe stopgap.
+			return host
+		}
+	}
+	prevDot := strings.LastIndex(host[:i-1], ".")
+	return host[prevDot+1:]
+}
+
+// isIP returns whether host is an IP address.
+func isIP(host string) bool {
+	return net.ParseIP(host) != nil
+}
+
+// defaultPath returns the directory part of an URL's path according to
+// RFC 6265 section 5.1.4.
+func defaultPath(path string) string {
+	if len(path) == 0 || path[0] != '/' {
+		return "/" // Path is empty or malformed.
+	}
+
+	i := strings.LastIndex(path, "/") // Path starts with "/", so i != -1.
+	if i == 0 {
+		return "/" // Path has the form "/abc".
+	}
+	return path[:i] // Path is either of form "/abc/xyz" or "/abc/xyz/".
+}
+
+// newEntry creates an entry from a http.Cookie c. now is the current time and
+// is compared to c.Expires to determine deletion of c. defPath and host are the
+// default-path and the canonical host name of the URL c was received from.
+//
+// remove is whether the jar should delete this cookie, as it has already
+// expired with respect to now. In this case, e may be incomplete, but it will
+// be valid to call e.id (which depends on e's Name, Domain and Path).
+//
+// A malformed c.Domain will result in an error.
+func (j *Jar) newEntry(c *http.Cookie, now time.Time, defPath, host string) (e entry, remove bool, err error) {
+	e.Name = c.Name
+
+	if c.Path == "" || c.Path[0] != '/' {
+		e.Path = defPath
+	} else {
+		e.Path = c.Path
+	}
+
+	e.Domain, e.HostOnly, err = j.domainAndType(host, c.Domain)
+	if err != nil {
+		return e, false, err
+	}
+
+	// MaxAge takes precedence over Expires.
+	if c.MaxAge < 0 {
+		return e, true, nil
+	} else if c.MaxAge > 0 {
+		e.Expires = now.Add(time.Duration(c.MaxAge) * time.Second)
+		e.Persistent = true
+	} else {
+		if c.Expires.IsZero() {
+			e.Expires = endOfTime
+			e.Persistent = false
+		} else {
+			if !c.Expires.After(now) {
+				return e, true, nil
+			}
+			e.Expires = c.Expires
+			e.Persistent = true
+		}
+	}
+
+	e.Value = c.Value
+	e.Secure = c.Secure
+	e.HttpOnly = c.HttpOnly
+
+	return e, false, nil
+}
+
+var (
+	errIllegalDomain   = errors.New("cookiejar: illegal cookie domain attribute")
+	errMalformedDomain = errors.New("cookiejar: malformed cookie domain attribute")
+	errNoHostname      = errors.New("cookiejar: no host name available (IP only)")
+)
+
+// endOfTime is the time when session (non-persistent) cookies expire.
+// This instant is representable in most date/time formats (not just
+// Go's time.Time) and should be far enough in the future.
+var endOfTime = time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC)
+
+// domainAndType determines the cookie's domain and hostOnly attribute.
+func (j *Jar) domainAndType(host, domain string) (string, bool, error) {
+	if domain == "" {
+		// No domain attribute in the SetCookie header indicates a
+		// host cookie.
+		return host, true, nil
+	}
+
+	if isIP(host) {
+		// According to RFC 6265 domain-matching includes not being
+		// an IP address.
+		// TODO: This might be relaxed as in common browsers.
+		return "", false, errNoHostname
+	}
+
+	// From here on: If the cookie is valid, it is a domain cookie (with
+	// the one exception of a public suffix below).
+	// See RFC 6265 section 5.2.3.
+	if domain[0] == '.' {
+		domain = domain[1:]
+	}
+
+	if len(domain) == 0 || domain[0] == '.' {
+		// Received either "Domain=." or "Domain=..some.thing",
+		// both are illegal.
+		return "", false, errMalformedDomain
+	}
+	domain = strings.ToLower(domain)
+
+	if domain[len(domain)-1] == '.' {
+		// We received stuff like "Domain=www.example.com.".
+		// Browsers do handle such stuff (actually differently) but
+		// RFC 6265 seems to be clear here (e.g. section 4.1.2.3) in
+		// requiring a reject.  4.1.2.3 is not normative, but
+		// "Domain Matching" (5.1.3) and "Canonicalized Host Names"
+		// (5.1.2) are.
+		return "", false, errMalformedDomain
+	}
+
+	// See RFC 6265 section 5.3 #5.
+	if j.psList != nil {
+		if ps := j.psList.PublicSuffix(domain); ps != "" && !hasDotSuffix(domain, ps) {
+			if host == domain {
+				// This is the one exception in which a cookie
+				// with a domain attribute is a host cookie.
+				return host, true, nil
+			}
+			return "", false, errIllegalDomain
+		}
+	}
+
+	// The domain must domain-match host: www.mycompany.com cannot
+	// set cookies for .ourcompetitors.com.
+	if host != domain && !hasDotSuffix(host, domain) {
+		return "", false, errIllegalDomain
+	}
+
+	return domain, false, nil
+}
diff --git a/src/pkg/net/http/cookiejar/jar_test.go b/src/pkg/net/http/cookiejar/jar_test.go
new file mode 100644
index 0000000..3aa6015
--- /dev/null
+++ b/src/pkg/net/http/cookiejar/jar_test.go
@@ -0,0 +1,1267 @@
+// 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 cookiejar
+
+import (
+	"fmt"
+	"net/http"
+	"net/url"
+	"sort"
+	"strings"
+	"testing"
+	"time"
+)
+
+// tNow is the synthetic current time used as now during testing.
+var tNow = time.Date(2013, 1, 1, 12, 0, 0, 0, time.UTC)
+
+// testPSL implements PublicSuffixList with just two rules: "co.uk"
+// and the default rule "*".
+type testPSL struct{}
+
+func (testPSL) String() string {
+	return "testPSL"
+}
+func (testPSL) PublicSuffix(d string) string {
+	if d == "co.uk" || strings.HasSuffix(d, ".co.uk") {
+		return "co.uk"
+	}
+	return d[strings.LastIndex(d, ".")+1:]
+}
+
+// newTestJar creates an empty Jar with testPSL as the public suffix list.
+func newTestJar() *Jar {
+	jar, err := New(&Options{PublicSuffixList: testPSL{}})
+	if err != nil {
+		panic(err)
+	}
+	return jar
+}
+
+var hasDotSuffixTests = [...]struct {
+	s, suffix string
+}{
+	{"", ""},
+	{"", "."},
+	{"", "x"},
+	{".", ""},
+	{".", "."},
+	{".", ".."},
+	{".", "x"},
+	{".", "x."},
+	{".", ".x"},
+	{".", ".x."},
+	{"x", ""},
+	{"x", "."},
+	{"x", ".."},
+	{"x", "x"},
+	{"x", "x."},
+	{"x", ".x"},
+	{"x", ".x."},
+	{".x", ""},
+	{".x", "."},
+	{".x", ".."},
+	{".x", "x"},
+	{".x", "x."},
+	{".x", ".x"},
+	{".x", ".x."},
+	{"x.", ""},
+	{"x.", "."},
+	{"x.", ".."},
+	{"x.", "x"},
+	{"x.", "x."},
+	{"x.", ".x"},
+	{"x.", ".x."},
+	{"com", ""},
+	{"com", "m"},
+	{"com", "om"},
+	{"com", "com"},
+	{"com", ".com"},
+	{"com", "x.com"},
+	{"com", "xcom"},
+	{"com", "xorg"},
+	{"com", "org"},
+	{"com", "rg"},
+	{"foo.com", ""},
+	{"foo.com", "m"},
+	{"foo.com", "om"},
+	{"foo.com", "com"},
+	{"foo.com", ".com"},
+	{"foo.com", "o.com"},
+	{"foo.com", "oo.com"},
+	{"foo.com", "foo.com"},
+	{"foo.com", ".foo.com"},
+	{"foo.com", "x.foo.com"},
+	{"foo.com", "xfoo.com"},
+	{"foo.com", "xfoo.org"},
+	{"foo.com", "foo.org"},
+	{"foo.com", "oo.org"},
+	{"foo.com", "o.org"},
+	{"foo.com", ".org"},
+	{"foo.com", "org"},
+	{"foo.com", "rg"},
+}
+
+func TestHasDotSuffix(t *testing.T) {
+	for _, tc := range hasDotSuffixTests {
+		got := hasDotSuffix(tc.s, tc.suffix)
+		want := strings.HasSuffix(tc.s, "."+tc.suffix)
+		if got != want {
+			t.Errorf("s=%q, suffix=%q: got %v, want %v", tc.s, tc.suffix, got, want)
+		}
+	}
+}
+
+var canonicalHostTests = map[string]string{
+	"www.example.com":         "www.example.com",
+	"WWW.EXAMPLE.COM":         "www.example.com",
+	"wWw.eXAmple.CoM":         "www.example.com",
+	"www.example.com:80":      "www.example.com",
+	"192.168.0.10":            "192.168.0.10",
+	"192.168.0.5:8080":        "192.168.0.5",
+	"2001:4860:0:2001::68":    "2001:4860:0:2001::68",
+	"[2001:4860:0:::68]:8080": "2001:4860:0:::68",
+	"www.bücher.de":           "www.xn--bcher-kva.de",
+	"www.example.com.":        "www.example.com",
+	"[bad.unmatched.bracket:": "error",
+}
+
+func TestCanonicalHost(t *testing.T) {
+	for h, want := range canonicalHostTests {
+		got, err := canonicalHost(h)
+		if want == "error" {
+			if err == nil {
+				t.Errorf("%q: got nil error, want non-nil", h)
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("%q: %v", h, err)
+			continue
+		}
+		if got != want {
+			t.Errorf("%q: got %q, want %q", h, got, want)
+			continue
+		}
+	}
+}
+
+var hasPortTests = map[string]bool{
+	"www.example.com":      false,
+	"www.example.com:80":   true,
+	"127.0.0.1":            false,
+	"127.0.0.1:8080":       true,
+	"2001:4860:0:2001::68": false,
+	"[2001::0:::68]:80":    true,
+}
+
+func TestHasPort(t *testing.T) {
+	for host, want := range hasPortTests {
+		if got := hasPort(host); got != want {
+			t.Errorf("%q: got %t, want %t", host, got, want)
+		}
+	}
+}
+
+var jarKeyTests = map[string]string{
+	"foo.www.example.com": "example.com",
+	"www.example.com":     "example.com",
+	"example.com":         "example.com",
+	"com":                 "com",
+	"foo.www.bbc.co.uk":   "bbc.co.uk",
+	"www.bbc.co.uk":       "bbc.co.uk",
+	"bbc.co.uk":           "bbc.co.uk",
+	"co.uk":               "co.uk",
+	"uk":                  "uk",
+	"192.168.0.5":         "192.168.0.5",
+}
+
+func TestJarKey(t *testing.T) {
+	for host, want := range jarKeyTests {
+		if got := jarKey(host, testPSL{}); got != want {
+			t.Errorf("%q: got %q, want %q", host, got, want)
+		}
+	}
+}
+
+var jarKeyNilPSLTests = map[string]string{
+	"foo.www.example.com": "example.com",
+	"www.example.com":     "example.com",
+	"example.com":         "example.com",
+	"com":                 "com",
+	"foo.www.bbc.co.uk":   "co.uk",
+	"www.bbc.co.uk":       "co.uk",
+	"bbc.co.uk":           "co.uk",
+	"co.uk":               "co.uk",
+	"uk":                  "uk",
+	"192.168.0.5":         "192.168.0.5",
+}
+
+func TestJarKeyNilPSL(t *testing.T) {
+	for host, want := range jarKeyNilPSLTests {
+		if got := jarKey(host, nil); got != want {
+			t.Errorf("%q: got %q, want %q", host, got, want)
+		}
+	}
+}
+
+var isIPTests = map[string]bool{
+	"127.0.0.1":            true,
+	"1.2.3.4":              true,
+	"2001:4860:0:2001::68": true,
+	"example.com":          false,
+	"1.1.1.300":            false,
+	"www.foo.bar.net":      false,
+	"123.foo.bar.net":      false,
+}
+
+func TestIsIP(t *testing.T) {
+	for host, want := range isIPTests {
+		if got := isIP(host); got != want {
+			t.Errorf("%q: got %t, want %t", host, got, want)
+		}
+	}
+}
+
+var defaultPathTests = map[string]string{
+	"/":           "/",
+	"/abc":        "/",
+	"/abc/":       "/abc",
+	"/abc/xyz":    "/abc",
+	"/abc/xyz/":   "/abc/xyz",
+	"/a/b/c.html": "/a/b",
+	"":            "/",
+	"strange":     "/",
+	"//":          "/",
+	"/a//b":       "/a/",
+	"/a/./b":      "/a/.",
+	"/a/../b":     "/a/..",
+}
+
+func TestDefaultPath(t *testing.T) {
+	for path, want := range defaultPathTests {
+		if got := defaultPath(path); got != want {
+			t.Errorf("%q: got %q, want %q", path, got, want)
+		}
+	}
+}
+
+var domainAndTypeTests = [...]struct {
+	host         string // host Set-Cookie header was received from
+	domain       string // domain attribute in Set-Cookie header
+	wantDomain   string // expected domain of cookie
+	wantHostOnly bool   // expected host-cookie flag
+	wantErr      error  // expected error
+}{
+	{"www.example.com", "", "www.example.com", true, nil},
+	{"127.0.0.1", "", "127.0.0.1", true, nil},
+	{"2001:4860:0:2001::68", "", "2001:4860:0:2001::68", true, nil},
+	{"www.example.com", "example.com", "example.com", false, nil},
+	{"www.example.com", ".example.com", "example.com", false, nil},
+	{"www.example.com", "www.example.com", "www.example.com", false, nil},
+	{"www.example.com", ".www.example.com", "www.example.com", false, nil},
+	{"foo.sso.example.com", "sso.example.com", "sso.example.com", false, nil},
+	{"bar.co.uk", "bar.co.uk", "bar.co.uk", false, nil},
+	{"foo.bar.co.uk", ".bar.co.uk", "bar.co.uk", false, nil},
+	{"127.0.0.1", "127.0.0.1", "", false, errNoHostname},
+	{"2001:4860:0:2001::68", "2001:4860:0:2001::68", "2001:4860:0:2001::68", false, errNoHostname},
+	{"www.example.com", ".", "", false, errMalformedDomain},
+	{"www.example.com", "..", "", false, errMalformedDomain},
+	{"www.example.com", "other.com", "", false, errIllegalDomain},
+	{"www.example.com", "com", "", false, errIllegalDomain},
+	{"www.example.com", ".com", "", false, errIllegalDomain},
+	{"foo.bar.co.uk", ".co.uk", "", false, errIllegalDomain},
+	{"127.www.0.0.1", "127.0.0.1", "", false, errIllegalDomain},
+	{"com", "", "com", true, nil},
+	{"com", "com", "com", true, nil},
+	{"com", ".com", "com", true, nil},
+	{"co.uk", "", "co.uk", true, nil},
+	{"co.uk", "co.uk", "co.uk", true, nil},
+	{"co.uk", ".co.uk", "co.uk", true, nil},
+}
+
+func TestDomainAndType(t *testing.T) {
+	jar := newTestJar()
+	for _, tc := range domainAndTypeTests {
+		domain, hostOnly, err := jar.domainAndType(tc.host, tc.domain)
+		if err != tc.wantErr {
+			t.Errorf("%q/%q: got %q error, want %q",
+				tc.host, tc.domain, err, tc.wantErr)
+			continue
+		}
+		if err != nil {
+			continue
+		}
+		if domain != tc.wantDomain || hostOnly != tc.wantHostOnly {
+			t.Errorf("%q/%q: got %q/%t want %q/%t",
+				tc.host, tc.domain, domain, hostOnly,
+				tc.wantDomain, tc.wantHostOnly)
+		}
+	}
+}
+
+// expiresIn creates an expires attribute delta seconds from tNow.
+func expiresIn(delta int) string {
+	t := tNow.Add(time.Duration(delta) * time.Second)
+	return "expires=" + t.Format(time.RFC1123)
+}
+
+// mustParseURL parses s to an URL and panics on error.
+func mustParseURL(s string) *url.URL {
+	u, err := url.Parse(s)
+	if err != nil || u.Scheme == "" || u.Host == "" {
+		panic(fmt.Sprintf("Unable to parse URL %s.", s))
+	}
+	return u
+}
+
+// jarTest encapsulates the following actions on a jar:
+//   1. Perform SetCookies with fromURL and the cookies from setCookies.
+//      (Done at time tNow + 0 ms.)
+//   2. Check that the entries in the jar matches content.
+//      (Done at time tNow + 1001 ms.)
+//   3. For each query in tests: Check that Cookies with toURL yields the
+//      cookies in want.
+//      (Query n done at tNow + (n+2)*1001 ms.)
+type jarTest struct {
+	description string   // The description of what this test is supposed to test
+	fromURL     string   // The full URL of the request from which Set-Cookie headers where received
+	setCookies  []string // All the cookies received from fromURL
+	content     string   // The whole (non-expired) content of the jar
+	queries     []query  // Queries to test the Jar.Cookies method
+}
+
+// query contains one test of the cookies returned from Jar.Cookies.
+type query struct {
+	toURL string // the URL in the Cookies call
+	want  string // the expected list of cookies (order matters)
+}
+
+// run runs the jarTest.
+func (test jarTest) run(t *testing.T, jar *Jar) {
+	now := tNow
+
+	// Populate jar with cookies.
+	setCookies := make([]*http.Cookie, len(test.setCookies))
+	for i, cs := range test.setCookies {
+		cookies := (&http.Response{Header: http.Header{"Set-Cookie": {cs}}}).Cookies()
+		if len(cookies) != 1 {
+			panic(fmt.Sprintf("Wrong cookie line %q: %#v", cs, cookies))
+		}
+		setCookies[i] = cookies[0]
+	}
+	jar.setCookies(mustParseURL(test.fromURL), setCookies, now)
+	now = now.Add(1001 * time.Millisecond)
+
+	// Serialize non-expired entries in the form "name1=val1 name2=val2".
+	var cs []string
+	for _, submap := range jar.entries {
+		for _, cookie := range submap {
+			if !cookie.Expires.After(now) {
+				continue
+			}
+			cs = append(cs, cookie.Name+"="+cookie.Value)
+		}
+	}
+	sort.Strings(cs)
+	got := strings.Join(cs, " ")
+
+	// Make sure jar content matches our expectations.
+	if got != test.content {
+		t.Errorf("Test %q Content\ngot  %q\nwant %q",
+			test.description, got, test.content)
+	}
+
+	// Test different calls to Cookies.
+	for i, query := range test.queries {
+		now = now.Add(1001 * time.Millisecond)
+		var s []string
+		for _, c := range jar.cookies(mustParseURL(query.toURL), now) {
+			s = append(s, c.Name+"="+c.Value)
+		}
+		if got := strings.Join(s, " "); got != query.want {
+			t.Errorf("Test %q #%d\ngot  %q\nwant %q", test.description, i, got, query.want)
+		}
+	}
+}
+
+// basicsTests contains fundamental tests. Each jarTest has to be performed on
+// a fresh, empty Jar.
+var basicsTests = [...]jarTest{
+	{
+		"Retrieval of a plain host cookie.",
+		"http://www.host.test/",
+		[]string{"A=a"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", "A=a"},
+			{"http://www.host.test/", "A=a"},
+			{"http://www.host.test/some/path", "A=a"},
+			{"https://www.host.test", "A=a"},
+			{"https://www.host.test/", "A=a"},
+			{"https://www.host.test/some/path", "A=a"},
+			{"ftp://www.host.test", ""},
+			{"ftp://www.host.test/", ""},
+			{"ftp://www.host.test/some/path", ""},
+			{"http://www.other.org", ""},
+			{"http://sibling.host.test", ""},
+			{"http://deep.www.host.test", ""},
+		},
+	},
+	{
+		"Secure cookies are not returned to http.",
+		"http://www.host.test/",
+		[]string{"A=a; secure"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", ""},
+			{"http://www.host.test/", ""},
+			{"http://www.host.test/some/path", ""},
+			{"https://www.host.test", "A=a"},
+			{"https://www.host.test/", "A=a"},
+			{"https://www.host.test/some/path", "A=a"},
+		},
+	},
+	{
+		"Explicit path.",
+		"http://www.host.test/",
+		[]string{"A=a; path=/some/path"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", ""},
+			{"http://www.host.test/", ""},
+			{"http://www.host.test/some", ""},
+			{"http://www.host.test/some/", ""},
+			{"http://www.host.test/some/path", "A=a"},
+			{"http://www.host.test/some/paths", ""},
+			{"http://www.host.test/some/path/foo", "A=a"},
+			{"http://www.host.test/some/path/foo/", "A=a"},
+		},
+	},
+	{
+		"Implicit path #1: path is a directory.",
+		"http://www.host.test/some/path/",
+		[]string{"A=a"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", ""},
+			{"http://www.host.test/", ""},
+			{"http://www.host.test/some", ""},
+			{"http://www.host.test/some/", ""},
+			{"http://www.host.test/some/path", "A=a"},
+			{"http://www.host.test/some/paths", ""},
+			{"http://www.host.test/some/path/foo", "A=a"},
+			{"http://www.host.test/some/path/foo/", "A=a"},
+		},
+	},
+	{
+		"Implicit path #2: path is not a directory.",
+		"http://www.host.test/some/path/index.html",
+		[]string{"A=a"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", ""},
+			{"http://www.host.test/", ""},
+			{"http://www.host.test/some", ""},
+			{"http://www.host.test/some/", ""},
+			{"http://www.host.test/some/path", "A=a"},
+			{"http://www.host.test/some/paths", ""},
+			{"http://www.host.test/some/path/foo", "A=a"},
+			{"http://www.host.test/some/path/foo/", "A=a"},
+		},
+	},
+	{
+		"Implicit path #3: no path in URL at all.",
+		"http://www.host.test",
+		[]string{"A=a"},
+		"A=a",
+		[]query{
+			{"http://www.host.test", "A=a"},
+			{"http://www.host.test/", "A=a"},
+			{"http://www.host.test/some/path", "A=a"},
+		},
+	},
+	{
+		"Cookies are sorted by path length.",
+		"http://www.host.test/",
+		[]string{
+			"A=a; path=/foo/bar",
+			"B=b; path=/foo/bar/baz/qux",
+			"C=c; path=/foo/bar/baz",
+			"D=d; path=/foo"},
+		"A=a B=b C=c D=d",
+		[]query{
+			{"http://www.host.test/foo/bar/baz/qux", "B=b C=c A=a D=d"},
+			{"http://www.host.test/foo/bar/baz/", "C=c A=a D=d"},
+			{"http://www.host.test/foo/bar", "A=a D=d"},
+		},
+	},
+	{
+		"Creation time determines sorting on same length paths.",
+		"http://www.host.test/",
+		[]string{
+			"A=a; path=/foo/bar",
+			"X=x; path=/foo/bar",
+			"Y=y; path=/foo/bar/baz/qux",
+			"B=b; path=/foo/bar/baz/qux",
+			"C=c; path=/foo/bar/baz",
+			"W=w; path=/foo/bar/baz",
+			"Z=z; path=/foo",
+			"D=d; path=/foo"},
+		"A=a B=b C=c D=d W=w X=x Y=y Z=z",
+		[]query{
+			{"http://www.host.test/foo/bar/baz/qux", "Y=y B=b C=c W=w A=a X=x Z=z D=d"},
+			{"http://www.host.test/foo/bar/baz/", "C=c W=w A=a X=x Z=z D=d"},
+			{"http://www.host.test/foo/bar", "A=a X=x Z=z D=d"},
+		},
+	},
+	{
+		"Sorting of same-name cookies.",
+		"http://www.host.test/",
+		[]string{
+			"A=1; path=/",
+			"A=2; path=/path",
+			"A=3; path=/quux",
+			"A=4; path=/path/foo",
+			"A=5; domain=.host.test; path=/path",
+			"A=6; domain=.host.test; path=/quux",
+			"A=7; domain=.host.test; path=/path/foo",
+		},
+		"A=1 A=2 A=3 A=4 A=5 A=6 A=7",
+		[]query{
+			{"http://www.host.test/path", "A=2 A=5 A=1"},
+			{"http://www.host.test/path/foo", "A=4 A=7 A=2 A=5 A=1"},
+		},
+	},
+	{
+		"Disallow domain cookie on public suffix.",
+		"http://www.bbc.co.uk",
+		[]string{
+			"a=1",
+			"b=2; domain=co.uk",
+		},
+		"a=1",
+		[]query{{"http://www.bbc.co.uk", "a=1"}},
+	},
+	{
+		"Host cookie on IP.",
+		"http://192.168.0.10",
+		[]string{"a=1"},
+		"a=1",
+		[]query{{"http://192.168.0.10", "a=1"}},
+	},
+	{
+		"Port is ignored #1.",
+		"http://www.host.test/",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://www.host.test", "a=1"},
+			{"http://www.host.test:8080/", "a=1"},
+		},
+	},
+	{
+		"Port is ignored #2.",
+		"http://www.host.test:8080/",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://www.host.test", "a=1"},
+			{"http://www.host.test:8080/", "a=1"},
+			{"http://www.host.test:1234/", "a=1"},
+		},
+	},
+}
+
+func TestBasics(t *testing.T) {
+	for _, test := range basicsTests {
+		jar := newTestJar()
+		test.run(t, jar)
+	}
+}
+
+// updateAndDeleteTests contains jarTests which must be performed on the same
+// Jar.
+var updateAndDeleteTests = [...]jarTest{
+	{
+		"Set initial cookies.",
+		"http://www.host.test",
+		[]string{
+			"a=1",
+			"b=2; secure",
+			"c=3; httponly",
+			"d=4; secure; httponly"},
+		"a=1 b=2 c=3 d=4",
+		[]query{
+			{"http://www.host.test", "a=1 c=3"},
+			{"https://www.host.test", "a=1 b=2 c=3 d=4"},
+		},
+	},
+	{
+		"Update value via http.",
+		"http://www.host.test",
+		[]string{
+			"a=w",
+			"b=x; secure",
+			"c=y; httponly",
+			"d=z; secure; httponly"},
+		"a=w b=x c=y d=z",
+		[]query{
+			{"http://www.host.test", "a=w c=y"},
+			{"https://www.host.test", "a=w b=x c=y d=z"},
+		},
+	},
+	{
+		"Clear Secure flag from a http.",
+		"http://www.host.test/",
+		[]string{
+			"b=xx",
+			"d=zz; httponly"},
+		"a=w b=xx c=y d=zz",
+		[]query{{"http://www.host.test", "a=w b=xx c=y d=zz"}},
+	},
+	{
+		"Delete all.",
+		"http://www.host.test/",
+		[]string{
+			"a=1; max-Age=-1",                    // delete via MaxAge
+			"b=2; " + expiresIn(-10),             // delete via Expires
+			"c=2; max-age=-1; " + expiresIn(-10), // delete via both
+			"d=4; max-age=-1; " + expiresIn(10)}, // MaxAge takes precedence
+		"",
+		[]query{{"http://www.host.test", ""}},
+	},
+	{
+		"Refill #1.",
+		"http://www.host.test",
+		[]string{
+			"A=1",
+			"A=2; path=/foo",
+			"A=3; domain=.host.test",
+			"A=4; path=/foo; domain=.host.test"},
+		"A=1 A=2 A=3 A=4",
+		[]query{{"http://www.host.test/foo", "A=2 A=4 A=1 A=3"}},
+	},
+	{
+		"Refill #2.",
+		"http://www.google.com",
+		[]string{
+			"A=6",
+			"A=7; path=/foo",
+			"A=8; domain=.google.com",
+			"A=9; path=/foo; domain=.google.com"},
+		"A=1 A=2 A=3 A=4 A=6 A=7 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=4 A=1 A=3"},
+			{"http://www.google.com/foo", "A=7 A=9 A=6 A=8"},
+		},
+	},
+	{
+		"Delete A7.",
+		"http://www.google.com",
+		[]string{"A=; path=/foo; max-age=-1"},
+		"A=1 A=2 A=3 A=4 A=6 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=4 A=1 A=3"},
+			{"http://www.google.com/foo", "A=9 A=6 A=8"},
+		},
+	},
+	{
+		"Delete A4.",
+		"http://www.host.test",
+		[]string{"A=; path=/foo; domain=host.test; max-age=-1"},
+		"A=1 A=2 A=3 A=6 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=1 A=3"},
+			{"http://www.google.com/foo", "A=9 A=6 A=8"},
+		},
+	},
+	{
+		"Delete A6.",
+		"http://www.google.com",
+		[]string{"A=; max-age=-1"},
+		"A=1 A=2 A=3 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=1 A=3"},
+			{"http://www.google.com/foo", "A=9 A=8"},
+		},
+	},
+	{
+		"Delete A3.",
+		"http://www.host.test",
+		[]string{"A=; domain=host.test; max-age=-1"},
+		"A=1 A=2 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=1"},
+			{"http://www.google.com/foo", "A=9 A=8"},
+		},
+	},
+	{
+		"No cross-domain delete.",
+		"http://www.host.test",
+		[]string{
+			"A=; domain=google.com; max-age=-1",
+			"A=; path=/foo; domain=google.com; max-age=-1"},
+		"A=1 A=2 A=8 A=9",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=1"},
+			{"http://www.google.com/foo", "A=9 A=8"},
+		},
+	},
+	{
+		"Delete A8 and A9.",
+		"http://www.google.com",
+		[]string{
+			"A=; domain=google.com; max-age=-1",
+			"A=; path=/foo; domain=google.com; max-age=-1"},
+		"A=1 A=2",
+		[]query{
+			{"http://www.host.test/foo", "A=2 A=1"},
+			{"http://www.google.com/foo", ""},
+		},
+	},
+}
+
+func TestUpdateAndDelete(t *testing.T) {
+	jar := newTestJar()
+	for _, test := range updateAndDeleteTests {
+		test.run(t, jar)
+	}
+}
+
+func TestExpiration(t *testing.T) {
+	jar := newTestJar()
+	jarTest{
+		"Expiration.",
+		"http://www.host.test",
+		[]string{
+			"a=1",
+			"b=2; max-age=3",
+			"c=3; " + expiresIn(3),
+			"d=4; max-age=5",
+			"e=5; " + expiresIn(5),
+			"f=6; max-age=100",
+		},
+		"a=1 b=2 c=3 d=4 e=5 f=6", // executed at t0 + 1001 ms
+		[]query{
+			{"http://www.host.test", "a=1 b=2 c=3 d=4 e=5 f=6"}, // t0 + 2002 ms
+			{"http://www.host.test", "a=1 d=4 e=5 f=6"},         // t0 + 3003 ms
+			{"http://www.host.test", "a=1 d=4 e=5 f=6"},         // t0 + 4004 ms
+			{"http://www.host.test", "a=1 f=6"},                 // t0 + 5005 ms
+			{"http://www.host.test", "a=1 f=6"},                 // t0 + 6006 ms
+		},
+	}.run(t, jar)
+}
+
+//
+// Tests derived from Chromium's cookie_store_unittest.h.
+//
+
+// See http://src.chromium.org/viewvc/chrome/trunk/src/net/cookies/cookie_store_unittest.h?revision=159685&content-type=text/plain
+// Some of the original tests are in a bad condition (e.g.
+// DomainWithTrailingDotTest) or are not RFC 6265 conforming (e.g.
+// TestNonDottedAndTLD #1 and #6) and have not been ported.
+
+// chromiumBasicsTests contains fundamental tests. Each jarTest has to be
+// performed on a fresh, empty Jar.
+var chromiumBasicsTests = [...]jarTest{
+	{
+		"DomainWithTrailingDotTest.",
+		"http://www.google.com/",
+		[]string{
+			"a=1; domain=.www.google.com.",
+			"b=2; domain=.www.google.com.."},
+		"",
+		[]query{
+			{"http://www.google.com", ""},
+		},
+	},
+	{
+		"ValidSubdomainTest #1.",
+		"http://a.b.c.d.com",
+		[]string{
+			"a=1; domain=.a.b.c.d.com",
+			"b=2; domain=.b.c.d.com",
+			"c=3; domain=.c.d.com",
+			"d=4; domain=.d.com"},
+		"a=1 b=2 c=3 d=4",
+		[]query{
+			{"http://a.b.c.d.com", "a=1 b=2 c=3 d=4"},
+			{"http://b.c.d.com", "b=2 c=3 d=4"},
+			{"http://c.d.com", "c=3 d=4"},
+			{"http://d.com", "d=4"},
+		},
+	},
+	{
+		"ValidSubdomainTest #2.",
+		"http://a.b.c.d.com",
+		[]string{
+			"a=1; domain=.a.b.c.d.com",
+			"b=2; domain=.b.c.d.com",
+			"c=3; domain=.c.d.com",
+			"d=4; domain=.d.com",
+			"X=bcd; domain=.b.c.d.com",
+			"X=cd; domain=.c.d.com"},
+		"X=bcd X=cd a=1 b=2 c=3 d=4",
+		[]query{
+			{"http://b.c.d.com", "b=2 c=3 d=4 X=bcd X=cd"},
+			{"http://c.d.com", "c=3 d=4 X=cd"},
+		},
+	},
+	{
+		"InvalidDomainTest #1.",
+		"http://foo.bar.com",
+		[]string{
+			"a=1; domain=.yo.foo.bar.com",
+			"b=2; domain=.foo.com",
+			"c=3; domain=.bar.foo.com",
+			"d=4; domain=.foo.bar.com.net",
+			"e=5; domain=ar.com",
+			"f=6; domain=.",
+			"g=7; domain=/",
+			"h=8; domain=http://foo.bar.com",
+			"i=9; domain=..foo.bar.com",
+			"j=10; domain=..bar.com",
+			"k=11; domain=.foo.bar.com?blah",
+			"l=12; domain=.foo.bar.com/blah",
+			"m=12; domain=.foo.bar.com:80",
+			"n=14; domain=.foo.bar.com:",
+			"o=15; domain=.foo.bar.com#sup",
+		},
+		"", // Jar is empty.
+		[]query{{"http://foo.bar.com", ""}},
+	},
+	{
+		"InvalidDomainTest #2.",
+		"http://foo.com.com",
+		[]string{"a=1; domain=.foo.com.com.com"},
+		"",
+		[]query{{"http://foo.bar.com", ""}},
+	},
+	{
+		"DomainWithoutLeadingDotTest #1.",
+		"http://manage.hosted.filefront.com",
+		[]string{"a=1; domain=filefront.com"},
+		"a=1",
+		[]query{{"http://www.filefront.com", "a=1"}},
+	},
+	{
+		"DomainWithoutLeadingDotTest #2.",
+		"http://www.google.com",
+		[]string{"a=1; domain=www.google.com"},
+		"a=1",
+		[]query{
+			{"http://www.google.com", "a=1"},
+			{"http://sub.www.google.com", "a=1"},
+			{"http://something-else.com", ""},
+		},
+	},
+	{
+		"CaseInsensitiveDomainTest.",
+		"http://www.google.com",
+		[]string{
+			"a=1; domain=.GOOGLE.COM",
+			"b=2; domain=.www.gOOgLE.coM"},
+		"a=1 b=2",
+		[]query{{"http://www.google.com", "a=1 b=2"}},
+	},
+	{
+		"TestIpAddress #1.",
+		"http://1.2.3.4/foo",
+		[]string{"a=1; path=/"},
+		"a=1",
+		[]query{{"http://1.2.3.4/foo", "a=1"}},
+	},
+	{
+		"TestIpAddress #2.",
+		"http://1.2.3.4/foo",
+		[]string{
+			"a=1; domain=.1.2.3.4",
+			"b=2; domain=.3.4"},
+		"",
+		[]query{{"http://1.2.3.4/foo", ""}},
+	},
+	{
+		"TestIpAddress #3.",
+		"http://1.2.3.4/foo",
+		[]string{"a=1; domain=1.2.3.4"},
+		"",
+		[]query{{"http://1.2.3.4/foo", ""}},
+	},
+	{
+		"TestNonDottedAndTLD #2.",
+		"http://com./index.html",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://com./index.html", "a=1"},
+			{"http://no-cookies.com./index.html", ""},
+		},
+	},
+	{
+		"TestNonDottedAndTLD #3.",
+		"http://a.b",
+		[]string{
+			"a=1; domain=.b",
+			"b=2; domain=b"},
+		"",
+		[]query{{"http://bar.foo", ""}},
+	},
+	{
+		"TestNonDottedAndTLD #4.",
+		"http://google.com",
+		[]string{
+			"a=1; domain=.com",
+			"b=2; domain=com"},
+		"",
+		[]query{{"http://google.com", ""}},
+	},
+	{
+		"TestNonDottedAndTLD #5.",
+		"http://google.co.uk",
+		[]string{
+			"a=1; domain=.co.uk",
+			"b=2; domain=.uk"},
+		"",
+		[]query{
+			{"http://google.co.uk", ""},
+			{"http://else.co.com", ""},
+			{"http://else.uk", ""},
+		},
+	},
+	{
+		"TestHostEndsWithDot.",
+		"http://www.google.com",
+		[]string{
+			"a=1",
+			"b=2; domain=.www.google.com."},
+		"a=1",
+		[]query{{"http://www.google.com", "a=1"}},
+	},
+	{
+		"PathTest",
+		"http://www.google.izzle",
+		[]string{"a=1; path=/wee"},
+		"a=1",
+		[]query{
+			{"http://www.google.izzle/wee", "a=1"},
+			{"http://www.google.izzle/wee/", "a=1"},
+			{"http://www.google.izzle/wee/war", "a=1"},
+			{"http://www.google.izzle/wee/war/more/more", "a=1"},
+			{"http://www.google.izzle/weehee", ""},
+			{"http://www.google.izzle/", ""},
+		},
+	},
+}
+
+func TestChromiumBasics(t *testing.T) {
+	for _, test := range chromiumBasicsTests {
+		jar := newTestJar()
+		test.run(t, jar)
+	}
+}
+
+// chromiumDomainTests contains jarTests which must be executed all on the
+// same Jar.
+var chromiumDomainTests = [...]jarTest{
+	{
+		"Fill #1.",
+		"http://www.google.izzle",
+		[]string{"A=B"},
+		"A=B",
+		[]query{{"http://www.google.izzle", "A=B"}},
+	},
+	{
+		"Fill #2.",
+		"http://www.google.izzle",
+		[]string{"C=D; domain=.google.izzle"},
+		"A=B C=D",
+		[]query{{"http://www.google.izzle", "A=B C=D"}},
+	},
+	{
+		"Verify A is a host cookie and not accessible from subdomain.",
+		"http://unused.nil",
+		[]string{},
+		"A=B C=D",
+		[]query{{"http://foo.www.google.izzle", "C=D"}},
+	},
+	{
+		"Verify domain cookies are found on proper domain.",
+		"http://www.google.izzle",
+		[]string{"E=F; domain=.www.google.izzle"},
+		"A=B C=D E=F",
+		[]query{{"http://www.google.izzle", "A=B C=D E=F"}},
+	},
+	{
+		"Leading dots in domain attributes are optional.",
+		"http://www.google.izzle",
+		[]string{"G=H; domain=www.google.izzle"},
+		"A=B C=D E=F G=H",
+		[]query{{"http://www.google.izzle", "A=B C=D E=F G=H"}},
+	},
+	{
+		"Verify domain enforcement works #1.",
+		"http://www.google.izzle",
+		[]string{"K=L; domain=.bar.www.google.izzle"},
+		"A=B C=D E=F G=H",
+		[]query{{"http://bar.www.google.izzle", "C=D E=F G=H"}},
+	},
+	{
+		"Verify domain enforcement works #2.",
+		"http://unused.nil",
+		[]string{},
+		"A=B C=D E=F G=H",
+		[]query{{"http://www.google.izzle", "A=B C=D E=F G=H"}},
+	},
+}
+
+func TestChromiumDomain(t *testing.T) {
+	jar := newTestJar()
+	for _, test := range chromiumDomainTests {
+		test.run(t, jar)
+	}
+
+}
+
+// chromiumDeletionTests must be performed all on the same Jar.
+var chromiumDeletionTests = [...]jarTest{
+	{
+		"Create session cookie a1.",
+		"http://www.google.com",
+		[]string{"a=1"},
+		"a=1",
+		[]query{{"http://www.google.com", "a=1"}},
+	},
+	{
+		"Delete sc a1 via MaxAge.",
+		"http://www.google.com",
+		[]string{"a=1; max-age=-1"},
+		"",
+		[]query{{"http://www.google.com", ""}},
+	},
+	{
+		"Create session cookie b2.",
+		"http://www.google.com",
+		[]string{"b=2"},
+		"b=2",
+		[]query{{"http://www.google.com", "b=2"}},
+	},
+	{
+		"Delete sc b2 via Expires.",
+		"http://www.google.com",
+		[]string{"b=2; " + expiresIn(-10)},
+		"",
+		[]query{{"http://www.google.com", ""}},
+	},
+	{
+		"Create persistent cookie c3.",
+		"http://www.google.com",
+		[]string{"c=3; max-age=3600"},
+		"c=3",
+		[]query{{"http://www.google.com", "c=3"}},
+	},
+	{
+		"Delete pc c3 via MaxAge.",
+		"http://www.google.com",
+		[]string{"c=3; max-age=-1"},
+		"",
+		[]query{{"http://www.google.com", ""}},
+	},
+	{
+		"Create persistent cookie d4.",
+		"http://www.google.com",
+		[]string{"d=4; max-age=3600"},
+		"d=4",
+		[]query{{"http://www.google.com", "d=4"}},
+	},
+	{
+		"Delete pc d4 via Expires.",
+		"http://www.google.com",
+		[]string{"d=4; " + expiresIn(-10)},
+		"",
+		[]query{{"http://www.google.com", ""}},
+	},
+}
+
+func TestChromiumDeletion(t *testing.T) {
+	jar := newTestJar()
+	for _, test := range chromiumDeletionTests {
+		test.run(t, jar)
+	}
+}
+
+// domainHandlingTests tests and documents the rules for domain handling.
+// Each test must be performed on an empty new Jar.
+var domainHandlingTests = [...]jarTest{
+	{
+		"Host cookie",
+		"http://www.host.test",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://www.host.test", "a=1"},
+			{"http://host.test", ""},
+			{"http://bar.host.test", ""},
+			{"http://foo.www.host.test", ""},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Domain cookie #1",
+		"http://www.host.test",
+		[]string{"a=1; domain=host.test"},
+		"a=1",
+		[]query{
+			{"http://www.host.test", "a=1"},
+			{"http://host.test", "a=1"},
+			{"http://bar.host.test", "a=1"},
+			{"http://foo.www.host.test", "a=1"},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Domain cookie #2",
+		"http://www.host.test",
+		[]string{"a=1; domain=.host.test"},
+		"a=1",
+		[]query{
+			{"http://www.host.test", "a=1"},
+			{"http://host.test", "a=1"},
+			{"http://bar.host.test", "a=1"},
+			{"http://foo.www.host.test", "a=1"},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Host cookie on IDNA domain #1",
+		"http://www.bücher.test",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://www.bücher.test", "a=1"},
+			{"http://www.xn--bcher-kva.test", "a=1"},
+			{"http://bücher.test", ""},
+			{"http://xn--bcher-kva.test", ""},
+			{"http://bar.bücher.test", ""},
+			{"http://bar.xn--bcher-kva.test", ""},
+			{"http://foo.www.bücher.test", ""},
+			{"http://foo.www.xn--bcher-kva.test", ""},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Host cookie on IDNA domain #2",
+		"http://www.xn--bcher-kva.test",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://www.bücher.test", "a=1"},
+			{"http://www.xn--bcher-kva.test", "a=1"},
+			{"http://bücher.test", ""},
+			{"http://xn--bcher-kva.test", ""},
+			{"http://bar.bücher.test", ""},
+			{"http://bar.xn--bcher-kva.test", ""},
+			{"http://foo.www.bücher.test", ""},
+			{"http://foo.www.xn--bcher-kva.test", ""},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Domain cookie on IDNA domain #1",
+		"http://www.bücher.test",
+		[]string{"a=1; domain=xn--bcher-kva.test"},
+		"a=1",
+		[]query{
+			{"http://www.bücher.test", "a=1"},
+			{"http://www.xn--bcher-kva.test", "a=1"},
+			{"http://bücher.test", "a=1"},
+			{"http://xn--bcher-kva.test", "a=1"},
+			{"http://bar.bücher.test", "a=1"},
+			{"http://bar.xn--bcher-kva.test", "a=1"},
+			{"http://foo.www.bücher.test", "a=1"},
+			{"http://foo.www.xn--bcher-kva.test", "a=1"},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Domain cookie on IDNA domain #2",
+		"http://www.xn--bcher-kva.test",
+		[]string{"a=1; domain=xn--bcher-kva.test"},
+		"a=1",
+		[]query{
+			{"http://www.bücher.test", "a=1"},
+			{"http://www.xn--bcher-kva.test", "a=1"},
+			{"http://bücher.test", "a=1"},
+			{"http://xn--bcher-kva.test", "a=1"},
+			{"http://bar.bücher.test", "a=1"},
+			{"http://bar.xn--bcher-kva.test", "a=1"},
+			{"http://foo.www.bücher.test", "a=1"},
+			{"http://foo.www.xn--bcher-kva.test", "a=1"},
+			{"http://other.test", ""},
+			{"http://test", ""},
+		},
+	},
+	{
+		"Host cookie on TLD.",
+		"http://com",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://com", "a=1"},
+			{"http://any.com", ""},
+			{"http://any.test", ""},
+		},
+	},
+	{
+		"Domain cookie on TLD becomes a host cookie.",
+		"http://com",
+		[]string{"a=1; domain=com"},
+		"a=1",
+		[]query{
+			{"http://com", "a=1"},
+			{"http://any.com", ""},
+			{"http://any.test", ""},
+		},
+	},
+	{
+		"Host cookie on public suffix.",
+		"http://co.uk",
+		[]string{"a=1"},
+		"a=1",
+		[]query{
+			{"http://co.uk", "a=1"},
+			{"http://uk", ""},
+			{"http://some.co.uk", ""},
+			{"http://foo.some.co.uk", ""},
+			{"http://any.uk", ""},
+		},
+	},
+	{
+		"Domain cookie on public suffix is ignored.",
+		"http://some.co.uk",
+		[]string{"a=1; domain=co.uk"},
+		"",
+		[]query{
+			{"http://co.uk", ""},
+			{"http://uk", ""},
+			{"http://some.co.uk", ""},
+			{"http://foo.some.co.uk", ""},
+			{"http://any.uk", ""},
+		},
+	},
+}
+
+func TestDomainHandling(t *testing.T) {
+	for _, test := range domainHandlingTests {
+		jar := newTestJar()
+		test.run(t, jar)
+	}
+}
diff --git a/src/pkg/net/http/cookiejar/punycode.go b/src/pkg/net/http/cookiejar/punycode.go
new file mode 100644
index 0000000..ea7ceb5
--- /dev/null
+++ b/src/pkg/net/http/cookiejar/punycode.go
@@ -0,0 +1,159 @@
+// 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 cookiejar
+
+// This file implements the Punycode algorithm from RFC 3492.
+
+import (
+	"fmt"
+	"strings"
+	"unicode/utf8"
+)
+
+// These parameter values are specified in section 5.
+//
+// All computation is done with int32s, so that overflow behavior is identical
+// regardless of whether int is 32-bit or 64-bit.
+const (
+	base        int32 = 36
+	damp        int32 = 700
+	initialBias int32 = 72
+	initialN    int32 = 128
+	skew        int32 = 38
+	tmax        int32 = 26
+	tmin        int32 = 1
+)
+
+// encode encodes a string as specified in section 6.3 and prepends prefix to
+// the result.
+//
+// The "while h < length(input)" line in the specification becomes "for
+// remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes.
+func encode(prefix, s string) (string, error) {
+	output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
+	copy(output, prefix)
+	delta, n, bias := int32(0), initialN, initialBias
+	b, remaining := int32(0), int32(0)
+	for _, r := range s {
+		if r < 0x80 {
+			b++
+			output = append(output, byte(r))
+		} else {
+			remaining++
+		}
+	}
+	h := b
+	if b > 0 {
+		output = append(output, '-')
+	}
+	for remaining != 0 {
+		m := int32(0x7fffffff)
+		for _, r := range s {
+			if m > r && r >= n {
+				m = r
+			}
+		}
+		delta += (m - n) * (h + 1)
+		if delta < 0 {
+			return "", fmt.Errorf("cookiejar: invalid label %q", s)
+		}
+		n = m
+		for _, r := range s {
+			if r < n {
+				delta++
+				if delta < 0 {
+					return "", fmt.Errorf("cookiejar: invalid label %q", s)
+				}
+				continue
+			}
+			if r > n {
+				continue
+			}
+			q := delta
+			for k := base; ; k += base {
+				t := k - bias
+				if t < tmin {
+					t = tmin
+				} else if t > tmax {
+					t = tmax
+				}
+				if q < t {
+					break
+				}
+				output = append(output, encodeDigit(t+(q-t)%(base-t)))
+				q = (q - t) / (base - t)
+			}
+			output = append(output, encodeDigit(q))
+			bias = adapt(delta, h+1, h == b)
+			delta = 0
+			h++
+			remaining--
+		}
+		delta++
+		n++
+	}
+	return string(output), nil
+}
+
+func encodeDigit(digit int32) byte {
+	switch {
+	case 0 <= digit && digit < 26:
+		return byte(digit + 'a')
+	case 26 <= digit && digit < 36:
+		return byte(digit + ('0' - 26))
+	}
+	panic("cookiejar: internal error in punycode encoding")
+}
+
+// adapt is the bias adaptation function specified in section 6.1.
+func adapt(delta, numPoints int32, firstTime bool) int32 {
+	if firstTime {
+		delta /= damp
+	} else {
+		delta /= 2
+	}
+	delta += delta / numPoints
+	k := int32(0)
+	for delta > ((base-tmin)*tmax)/2 {
+		delta /= base - tmin
+		k += base
+	}
+	return k + (base-tmin+1)*delta/(delta+skew)
+}
+
+// Strictly speaking, the remaining code below deals with IDNA (RFC 5890 and
+// friends) and not Punycode (RFC 3492) per se.
+
+// acePrefix is the ASCII Compatible Encoding prefix.
+const acePrefix = "xn--"
+
+// toASCII converts a domain or domain label to its ASCII form. For example,
+// toASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
+// toASCII("golang") is "golang".
+func toASCII(s string) (string, error) {
+	if ascii(s) {
+		return s, nil
+	}
+	labels := strings.Split(s, ".")
+	for i, label := range labels {
+		if !ascii(label) {
+			a, err := encode(acePrefix, label)
+			if err != nil {
+				return "", err
+			}
+			labels[i] = a
+		}
+	}
+	return strings.Join(labels, "."), nil
+}
+
+func ascii(s string) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] >= utf8.RuneSelf {
+			return false
+		}
+	}
+	return true
+}
diff --git a/src/pkg/net/http/cookiejar/punycode_test.go b/src/pkg/net/http/cookiejar/punycode_test.go
new file mode 100644
index 0000000..0301de1
--- /dev/null
+++ b/src/pkg/net/http/cookiejar/punycode_test.go
@@ -0,0 +1,161 @@
+// 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 cookiejar
+
+import (
+	"testing"
+)
+
+var punycodeTestCases = [...]struct {
+	s, encoded string
+}{
+	{"", ""},
+	{"-", "--"},
+	{"-a", "-a-"},
+	{"-a-", "-a--"},
+	{"a", "a-"},
+	{"a-", "a--"},
+	{"a-b", "a-b-"},
+	{"books", "books-"},
+	{"bücher", "bcher-kva"},
+	{"Hello世界", "Hello-ck1hg65u"},
+	{"ü", "tda"},
+	{"üý", "tdac"},
+
+	// The test cases below come from RFC 3492 section 7.1 with Errata 3026.
+	{
+		// (A) Arabic (Egyptian).
+		"\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" +
+			"\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F",
+		"egbpdaj6bu4bxfgehfvwxn",
+	},
+	{
+		// (B) Chinese (simplified).
+		"\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587",
+		"ihqwcrb4cv8a8dqg056pqjye",
+	},
+	{
+		// (C) Chinese (traditional).
+		"\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587",
+		"ihqwctvzc91f659drss3x8bo0yb",
+	},
+	{
+		// (D) Czech.
+		"\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" +
+			"\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" +
+			"\u0065\u0073\u006B\u0079",
+		"Proprostnemluvesky-uyb24dma41a",
+	},
+	{
+		// (E) Hebrew.
+		"\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" +
+			"\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" +
+			"\u05D1\u05E8\u05D9\u05EA",
+		"4dbcagdahymbxekheh6e0a7fei0b",
+	},
+	{
+		// (F) Hindi (Devanagari).
+		"\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" +
+			"\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" +
+			"\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" +
+			"\u0939\u0948\u0902",
+		"i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd",
+	},
+	{
+		// (G) Japanese (kanji and hiragana).
+		"\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" +
+			"\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B",
+		"n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa",
+	},
+	{
+		// (H) Korean (Hangul syllables).
+		"\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" +
+			"\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" +
+			"\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C",
+		"989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5j" +
+			"psd879ccm6fea98c",
+	},
+	{
+		// (I) Russian (Cyrillic).
+		"\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" +
+			"\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" +
+			"\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" +
+			"\u0438",
+		"b1abfaaepdrnnbgefbadotcwatmq2g4l",
+	},
+	{
+		// (J) Spanish.
+		"\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" +
+			"\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" +
+			"\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" +
+			"\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" +
+			"\u0061\u00F1\u006F\u006C",
+		"PorqunopuedensimplementehablarenEspaol-fmd56a",
+	},
+	{
+		// (K) Vietnamese.
+		"\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" +
+			"\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" +
+			"\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" +
+			"\u0056\u0069\u1EC7\u0074",
+		"TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g",
+	},
+	{
+		// (L) 3<nen>B<gumi><kinpachi><sensei>.
+		"\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F",
+		"3B-ww4c5e180e575a65lsy2b",
+	},
+	{
+		// (M) <amuro><namie>-with-SUPER-MONKEYS.
+		"\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" +
+			"\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" +
+			"\u004F\u004E\u004B\u0045\u0059\u0053",
+		"-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n",
+	},
+	{
+		// (N) Hello-Another-Way-<sorezore><no><basho>.
+		"\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" +
+			"\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" +
+			"\u305D\u308C\u305E\u308C\u306E\u5834\u6240",
+		"Hello-Another-Way--fc4qua05auwb3674vfr0b",
+	},
+	{
+		// (O) <hitotsu><yane><no><shita>2.
+		"\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032",
+		"2-u9tlzr9756bt3uc0v",
+	},
+	{
+		// (P) Maji<de>Koi<suru>5<byou><mae>
+		"\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" +
+			"\u308B\u0035\u79D2\u524D",
+		"MajiKoi5-783gue6qz075azm5e",
+	},
+	{
+		// (Q) <pafii>de<runba>
+		"\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0",
+		"de-jg4avhby1noc0d",
+	},
+	{
+		// (R) <sono><supiido><de>
+		"\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067",
+		"d9juau41awczczp",
+	},
+	{
+		// (S) -> $1.00 <-
+		"\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" +
+			"\u003C\u002D",
+		"-> $1.00 <--",
+	},
+}
+
+func TestPunycode(t *testing.T) {
+	for _, tc := range punycodeTestCases {
+		if got, err := encode("", tc.s); err != nil {
+			t.Errorf(`encode("", %q): %v`, tc.s, err)
+		} else if got != tc.encoded {
+			t.Errorf(`encode("", %q): got %q, want %q`, tc.s, got, tc.encoded)
+		}
+	}
+}
diff --git a/src/pkg/net/http/example_test.go b/src/pkg/net/http/example_test.go
index ec81440..22073ea 100644
--- a/src/pkg/net/http/example_test.go
+++ b/src/pkg/net/http/example_test.go
@@ -43,10 +43,10 @@ func ExampleGet() {
 		log.Fatal(err)
 	}
 	robots, err := ioutil.ReadAll(res.Body)
+	res.Body.Close()
 	if err != nil {
 		log.Fatal(err)
 	}
-	res.Body.Close()
 	fmt.Printf("%s", robots)
 }
 
diff --git a/src/pkg/net/http/export_test.go b/src/pkg/net/http/export_test.go
index 13640ca..a7bca20 100644
--- a/src/pkg/net/http/export_test.go
+++ b/src/pkg/net/http/export_test.go
@@ -7,12 +7,25 @@
 
 package http
 
-import "time"
+import (
+	"net"
+	"time"
+)
+
+func NewLoggingConn(baseName string, c net.Conn) net.Conn {
+	return newLoggingConn(baseName, c)
+}
+
+func (t *Transport) NumPendingRequestsForTesting() int {
+	t.reqMu.Lock()
+	defer t.reqMu.Unlock()
+	return len(t.reqConn)
+}
 
 func (t *Transport) IdleConnKeysForTesting() (keys []string) {
 	keys = make([]string, 0)
-	t.lk.Lock()
-	defer t.lk.Unlock()
+	t.idleMu.Lock()
+	defer t.idleMu.Unlock()
 	if t.idleConn == nil {
 		return
 	}
@@ -23,8 +36,8 @@ func (t *Transport) IdleConnKeysForTesting() (keys []string) {
 }
 
 func (t *Transport) IdleConnCountForTesting(cacheKey string) int {
-	t.lk.Lock()
-	defer t.lk.Unlock()
+	t.idleMu.Lock()
+	defer t.idleMu.Unlock()
 	if t.idleConn == nil {
 		return 0
 	}
diff --git a/src/pkg/net/http/filetransport_test.go b/src/pkg/net/http/filetransport_test.go
index 039926b..6f1a537 100644
--- a/src/pkg/net/http/filetransport_test.go
+++ b/src/pkg/net/http/filetransport_test.go
@@ -2,11 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package http_test
+package http
 
 import (
 	"io/ioutil"
-	"net/http"
 	"os"
 	"path/filepath"
 	"testing"
@@ -32,9 +31,9 @@ func TestFileTransport(t *testing.T) {
 	defer os.Remove(dname)
 	defer os.Remove(fname)
 
-	tr := &http.Transport{}
-	tr.RegisterProtocol("file", http.NewFileTransport(http.Dir(dname)))
-	c := &http.Client{Transport: tr}
+	tr := &Transport{}
+	tr.RegisterProtocol("file", NewFileTransport(Dir(dname)))
+	c := &Client{Transport: tr}
 
 	fooURLs := []string{"file:///foo.txt", "file://../foo.txt"}
 	for _, urlstr := range fooURLs {
@@ -62,4 +61,5 @@ func TestFileTransport(t *testing.T) {
 	if res.StatusCode != 404 {
 		t.Errorf("for %s, StatusCode = %d, want 404", badURL, res.StatusCode)
 	}
+	res.Body.Close()
 }
diff --git a/src/pkg/net/http/fs.go b/src/pkg/net/http/fs.go
index f35dd32..b6bea0d 100644
--- a/src/pkg/net/http/fs.go
+++ b/src/pkg/net/http/fs.go
@@ -11,6 +11,8 @@ import (
 	"fmt"
 	"io"
 	"mime"
+	"mime/multipart"
+	"net/textproto"
 	"os"
 	"path"
 	"path/filepath"
@@ -26,7 +28,8 @@ import (
 type Dir string
 
 func (d Dir) Open(name string) (File, error) {
-	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 {
+	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
+		strings.Contains(name, "\x00") {
 		return nil, errors.New("http: invalid character in file path")
 	}
 	dir := string(d)
@@ -97,6 +100,9 @@ func dirList(w ResponseWriter, f File) {
 // The content's Seek method must work: ServeContent uses
 // a seek to the end of the content to determine its size.
 //
+// If the caller has set w's ETag header, ServeContent uses it to
+// handle requests using If-Range and If-None-Match.
+//
 // Note that *os.File implements the io.ReadSeeker interface.
 func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker) {
 	size, err := content.Seek(0, os.SEEK_END)
@@ -119,12 +125,17 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
 	if checkLastModified(w, r, modtime) {
 		return
 	}
+	rangeReq, done := checkETag(w, r)
+	if done {
+		return
+	}
 
 	code := StatusOK
 
 	// If Content-Type isn't set, use the file's extension to find it.
-	if w.Header().Get("Content-Type") == "" {
-		ctype := mime.TypeByExtension(filepath.Ext(name))
+	ctype := w.Header().Get("Content-Type")
+	if ctype == "" {
+		ctype = mime.TypeByExtension(filepath.Ext(name))
 		if ctype == "" {
 			// read a chunk to decide between utf-8 text and binary
 			var buf [1024]byte
@@ -141,18 +152,34 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
 	}
 
 	// handle Content-Range header.
-	// TODO(adg): handle multiple ranges
 	sendSize := size
+	var sendContent io.Reader = content
 	if size >= 0 {
-		ranges, err := parseRange(r.Header.Get("Range"), size)
-		if err == nil && len(ranges) > 1 {
-			err = errors.New("multiple ranges not supported")
-		}
+		ranges, err := parseRange(rangeReq, size)
 		if err != nil {
 			Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
 			return
 		}
-		if len(ranges) == 1 {
+		if sumRangesSize(ranges) >= size {
+			// The total number of bytes in all the ranges
+			// is larger than the size of the file by
+			// itself, so this is probably an attack, or a
+			// dumb client.  Ignore the range request.
+			ranges = nil
+		}
+		switch {
+		case len(ranges) == 1:
+			// RFC 2616, Section 14.16:
+			// "When an HTTP message includes the content of a single
+			// range (for example, a response to a request for a
+			// single range, or to a request for a set of ranges
+			// that overlap without any holes), this content is
+			// transmitted with a Content-Range header, and a
+			// Content-Length header showing the number of bytes
+			// actually transferred.
+			// ...
+			// A response to a request for a single range MUST NOT
+			// be sent using the multipart/byteranges media type."
 			ra := ranges[0]
 			if _, err := content.Seek(ra.start, os.SEEK_SET); err != nil {
 				Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
@@ -160,7 +187,41 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
 			}
 			sendSize = ra.length
 			code = StatusPartialContent
-			w.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", ra.start, ra.start+ra.length-1, size))
+			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
+
+			pr, pw := io.Pipe()
+			mw := multipart.NewWriter(pw)
+			w.Header().Set("Content-Type", "multipart/byteranges; boundary="+mw.Boundary())
+			sendContent = pr
+			defer pr.Close() // cause writing goroutine to fail and exit if CopyN doesn't finish.
+			go func() {
+				for _, ra := range ranges {
+					part, err := mw.CreatePart(ra.mimeHeader(ctype, size))
+					if err != nil {
+						pw.CloseWithError(err)
+						return
+					}
+					if _, err := content.Seek(ra.start, os.SEEK_SET); err != nil {
+						pw.CloseWithError(err)
+						return
+					}
+					if _, err := io.CopyN(part, content, ra.length); err != nil {
+						pw.CloseWithError(err)
+						return
+					}
+				}
+				mw.Close()
+				pw.Close()
+			}()
 		}
 
 		w.Header().Set("Accept-Ranges", "bytes")
@@ -172,11 +233,7 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
 	w.WriteHeader(code)
 
 	if r.Method != "HEAD" {
-		if sendSize == -1 {
-			io.Copy(w, content)
-		} else {
-			io.CopyN(w, content, sendSize)
-		}
+		io.CopyN(w, sendContent, sendSize)
 	}
 }
 
@@ -190,6 +247,9 @@ func checkLastModified(w ResponseWriter, r *Request, modtime time.Time) bool {
 	// The Date-Modified header truncates sub-second precision, so
 	// use mtime < t+1s instead of mtime <= t to check for unmodified.
 	if t, err := time.Parse(TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modtime.Before(t.Add(1*time.Second)) {
+		h := w.Header()
+		delete(h, "Content-Type")
+		delete(h, "Content-Length")
 		w.WriteHeader(StatusNotModified)
 		return true
 	}
@@ -197,6 +257,58 @@ func checkLastModified(w ResponseWriter, r *Request, modtime time.Time) bool {
 	return false
 }
 
+// checkETag implements If-None-Match and If-Range checks.
+// The ETag must have been previously set in the ResponseWriter's headers.
+//
+// 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) {
+	etag := w.Header().get("Etag")
+	rangeReq = r.Header.get("Range")
+
+	// Invalidate the range request if the entity doesn't match the one
+	// the client was expecting.
+	// "If-Range: version" means "ignore the Range: header unless version matches the
+	// current file."
+	// 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 = ""
+	}
+
+	if inm := r.Header.get("If-None-Match"); inm != "" {
+		// Must know ETag.
+		if etag == "" {
+			return rangeReq, false
+		}
+
+		// TODO(bradfitz): non-GET/HEAD requests require more work:
+		// sending a different status code on matches, and
+		// also can't use weak cache validators (those with a "W/
+		// prefix).  But most users of ServeContent will be using
+		// it on GET or HEAD, so only support those for now.
+		if r.Method != "GET" && r.Method != "HEAD" {
+			return rangeReq, false
+		}
+
+		// TODO(bradfitz): deal with comma-separated or multiple-valued
+		// list of If-None-match values.  For now just handle the common
+		// case of a single item.
+		if inm == etag || inm == "*" {
+			h := w.Header()
+			delete(h, "Content-Type")
+			delete(h, "Content-Length")
+			w.WriteHeader(StatusNotModified)
+			return "", true
+		}
+	}
+	return rangeReq, false
+}
+
 // name is '/'-separated, not filepath.Separator.
 func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {
 	const indexPage = "/index.html"
@@ -243,9 +355,6 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
 
 	// use contents of index.html for directory, if present
 	if d.IsDir() {
-		if checkLastModified(w, r, d.ModTime()) {
-			return
-		}
 		index := name + indexPage
 		ff, err := fs.Open(index)
 		if err == nil {
@@ -259,11 +368,16 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
 		}
 	}
 
+	// Still a directory? (we didn't find an index.html file)
 	if d.IsDir() {
+		if checkLastModified(w, r, d.ModTime()) {
+			return
+		}
 		dirList(w, f)
 		return
 	}
 
+	// serverContent will check modification time
 	serveContent(w, r, d.Name(), d.ModTime(), d.Size(), f)
 }
 
@@ -312,6 +426,17 @@ type httpRange struct {
 	start, length int64
 }
 
+func (r httpRange) contentRange(size int64) string {
+	return fmt.Sprintf("bytes %d-%d/%d", r.start, r.start+r.length-1, size)
+}
+
+func (r httpRange) mimeHeader(contentType string, size int64) textproto.MIMEHeader {
+	return textproto.MIMEHeader{
+		"Content-Range": {r.contentRange(size)},
+		"Content-Type":  {contentType},
+	}
+}
+
 // parseRange parses a Range header string as per RFC 2616.
 func parseRange(s string, size int64) ([]httpRange, error) {
 	if s == "" {
@@ -323,11 +448,15 @@ func parseRange(s string, size int64) ([]httpRange, error) {
 	}
 	var ranges []httpRange
 	for _, ra := range strings.Split(s[len(b):], ",") {
+		ra = strings.TrimSpace(ra)
+		if ra == "" {
+			continue
+		}
 		i := strings.Index(ra, "-")
 		if i < 0 {
 			return nil, errors.New("invalid range")
 		}
-		start, end := ra[:i], ra[i+1:]
+		start, end := strings.TrimSpace(ra[:i]), strings.TrimSpace(ra[i+1:])
 		var r httpRange
 		if start == "" {
 			// If no start is specified, end specifies the
@@ -365,3 +494,32 @@ func parseRange(s string, size int64) ([]httpRange, error) {
 	}
 	return ranges, nil
 }
+
+// countingWriter counts how many bytes have been written to it.
+type countingWriter int64
+
+func (w *countingWriter) Write(p []byte) (n int, err error) {
+	*w += countingWriter(len(p))
+	return len(p), nil
+}
+
+// rangesMIMESize returns the nunber of bytes it takes to encode the
+// provided ranges as a multipart response.
+func rangesMIMESize(ranges []httpRange, contentType string, contentSize int64) (encSize int64) {
+	var w countingWriter
+	mw := multipart.NewWriter(&w)
+	for _, ra := range ranges {
+		mw.CreatePart(ra.mimeHeader(contentType, contentSize))
+		encSize += ra.length
+	}
+	mw.Close()
+	encSize += int64(w)
+	return
+}
+
+func sumRangesSize(ranges []httpRange) (size int64) {
+	for _, ra := range ranges {
+		size += ra.length
+	}
+	return
+}
diff --git a/src/pkg/net/http/fs_test.go b/src/pkg/net/http/fs_test.go
index 5aa93ce..0dd6d0d 100644
--- a/src/pkg/net/http/fs_test.go
+++ b/src/pkg/net/http/fs_test.go
@@ -10,12 +10,15 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"mime"
+	"mime/multipart"
 	"net"
 	. "net/http"
 	"net/http/httptest"
 	"net/url"
 	"os"
 	"os/exec"
+	"path"
 	"path/filepath"
 	"regexp"
 	"runtime"
@@ -25,24 +28,33 @@ import (
 )
 
 const (
-	testFile       = "testdata/file"
-	testFileLength = 11
+	testFile    = "testdata/file"
+	testFileLen = 11
 )
 
+type wantRange struct {
+	start, end int64 // range [start,end)
+}
+
 var ServeFileRangeTests = []struct {
-	start, end int
-	r          string
-	code       int
+	r      string
+	code   int
+	ranges []wantRange
 }{
-	{0, testFileLength, "", StatusOK},
-	{0, 5, "0-4", StatusPartialContent},
-	{2, testFileLength, "2-", StatusPartialContent},
-	{testFileLength - 5, testFileLength, "-5", StatusPartialContent},
-	{3, 8, "3-7", StatusPartialContent},
-	{0, 0, "20-", StatusRequestedRangeNotSatisfiable},
+	{r: "", code: StatusOK},
+	{r: "bytes=0-4", code: StatusPartialContent, ranges: []wantRange{{0, 5}}},
+	{r: "bytes=2-", code: StatusPartialContent, ranges: []wantRange{{2, testFileLen}}},
+	{r: "bytes=-5", code: StatusPartialContent, ranges: []wantRange{{testFileLen - 5, testFileLen}}},
+	{r: "bytes=3-7", code: StatusPartialContent, ranges: []wantRange{{3, 8}}},
+	{r: "bytes=20-", code: StatusRequestedRangeNotSatisfiable},
+	{r: "bytes=0-0,-2", code: StatusPartialContent, ranges: []wantRange{{0, 1}, {testFileLen - 2, testFileLen}}},
+	{r: "bytes=0-1,5-8", code: StatusPartialContent, ranges: []wantRange{{0, 2}, {5, 9}}},
+	{r: "bytes=0-1,5-", code: StatusPartialContent, ranges: []wantRange{{0, 2}, {5, testFileLen}}},
+	{r: "bytes=0-,1-,2-,3-,4-", code: StatusOK}, // ignore wasteful range request
 }
 
 func TestServeFile(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		ServeFile(w, r, "testdata/file")
 	}))
@@ -65,33 +77,86 @@ func TestServeFile(t *testing.T) {
 
 	// straight GET
 	_, body := getBody(t, "straight get", req)
-	if !equal(body, file) {
+	if !bytes.Equal(body, file) {
 		t.Fatalf("body mismatch: got %q, want %q", body, file)
 	}
 
 	// Range tests
-	for i, rt := range ServeFileRangeTests {
-		req.Header.Set("Range", "bytes="+rt.r)
-		if rt.r == "" {
-			req.Header["Range"] = nil
+Cases:
+	for _, rt := range ServeFileRangeTests {
+		if rt.r != "" {
+			req.Header.Set("Range", rt.r)
 		}
-		r, body := getBody(t, fmt.Sprintf("test %d", i), req)
-		if r.StatusCode != rt.code {
-			t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, r.StatusCode, rt.code)
+		resp, body := getBody(t, fmt.Sprintf("range test %q", rt.r), req)
+		if resp.StatusCode != rt.code {
+			t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, resp.StatusCode, rt.code)
 		}
 		if rt.code == StatusRequestedRangeNotSatisfiable {
 			continue
 		}
-		h := fmt.Sprintf("bytes %d-%d/%d", rt.start, rt.end-1, testFileLength)
-		if rt.r == "" {
-			h = ""
+		wantContentRange := ""
+		if len(rt.ranges) == 1 {
+			rng := rt.ranges[0]
+			wantContentRange = fmt.Sprintf("bytes %d-%d/%d", rng.start, rng.end-1, testFileLen)
+		}
+		cr := resp.Header.Get("Content-Range")
+		if cr != wantContentRange {
+			t.Errorf("range=%q: Content-Range = %q, want %q", rt.r, cr, wantContentRange)
 		}
-		cr := r.Header.Get("Content-Range")
-		if cr != h {
-			t.Errorf("header mismatch: range=%q: got %q, want %q", rt.r, cr, h)
+		ct := resp.Header.Get("Content-Type")
+		if len(rt.ranges) == 1 {
+			rng := rt.ranges[0]
+			wantBody := file[rng.start:rng.end]
+			if !bytes.Equal(body, wantBody) {
+				t.Errorf("range=%q: body = %q, want %q", rt.r, body, wantBody)
+			}
+			if strings.HasPrefix(ct, "multipart/byteranges") {
+				t.Errorf("range=%q content-type = %q; unexpected multipart/byteranges", rt.r, ct)
+			}
 		}
-		if !equal(body, file[rt.start:rt.end]) {
-			t.Errorf("body mismatch: range=%q: got %q, want %q", rt.r, body, file[rt.start:rt.end])
+		if len(rt.ranges) > 1 {
+			typ, params, err := mime.ParseMediaType(ct)
+			if err != nil {
+				t.Errorf("range=%q content-type = %q; %v", rt.r, ct, err)
+				continue
+			}
+			if typ != "multipart/byteranges" {
+				t.Errorf("range=%q content-type = %q; want multipart/byteranges", rt.r, typ)
+				continue
+			}
+			if params["boundary"] == "" {
+				t.Errorf("range=%q content-type = %q; lacks boundary", rt.r, ct)
+				continue
+			}
+			if g, w := resp.ContentLength, int64(len(body)); g != w {
+				t.Errorf("range=%q Content-Length = %d; want %d", rt.r, g, w)
+				continue
+			}
+			mr := multipart.NewReader(bytes.NewReader(body), params["boundary"])
+			for ri, rng := range rt.ranges {
+				part, err := mr.NextPart()
+				if err != nil {
+					t.Errorf("range=%q, reading part index %d: %v", rt.r, ri, err)
+					continue Cases
+				}
+				wantContentRange = fmt.Sprintf("bytes %d-%d/%d", rng.start, rng.end-1, testFileLen)
+				if g, w := part.Header.Get("Content-Range"), wantContentRange; g != w {
+					t.Errorf("range=%q: part Content-Range = %q; want %q", rt.r, g, w)
+				}
+				body, err := ioutil.ReadAll(part)
+				if err != nil {
+					t.Errorf("range=%q, reading part index %d body: %v", rt.r, ri, err)
+					continue Cases
+				}
+				wantBody := file[rng.start:rng.end]
+				if !bytes.Equal(body, wantBody) {
+					t.Errorf("range=%q: body = %q, want %q", rt.r, body, wantBody)
+				}
+			}
+			_, err = mr.NextPart()
+			if err != io.EOF {
+				t.Errorf("range=%q; expected final error io.EOF; got %v", rt.r, err)
+			}
 		}
 	}
 }
@@ -105,6 +170,7 @@ var fsRedirectTestData = []struct {
 }
 
 func TestFSRedirect(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(StripPrefix("/test", FileServer(Dir("."))))
 	defer ts.Close()
 
@@ -129,6 +195,7 @@ func (fs *testFileSystem) Open(name string) (File, error) {
 }
 
 func TestFileServerCleans(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ch := make(chan string, 1)
 	fs := FileServer(&testFileSystem{func(name string) (File, error) {
 		ch <- name
@@ -160,6 +227,7 @@ func mustRemoveAll(dir string) {
 }
 
 func TestFileServerImplicitLeadingSlash(t *testing.T) {
+	defer checkLeakedTransports(t)
 	tempDir, err := ioutil.TempDir("", "")
 	if err != nil {
 		t.Fatalf("TempDir: %v", err)
@@ -193,8 +261,7 @@ func TestFileServerImplicitLeadingSlash(t *testing.T) {
 func TestDirJoin(t *testing.T) {
 	wfi, err := os.Stat("/etc/hosts")
 	if err != nil {
-		t.Logf("skipping test; no /etc/hosts file")
-		return
+		t.Skip("skipping test; no /etc/hosts file")
 	}
 	test := func(d Dir, name string) {
 		f, err := d.Open(name)
@@ -239,6 +306,7 @@ func TestEmptyDirOpenCWD(t *testing.T) {
 }
 
 func TestServeFileContentType(t *testing.T) {
+	defer checkLeakedTransports(t)
 	const ctype = "icecream/chocolate"
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		if r.FormValue("override") == "1" {
@@ -255,12 +323,14 @@ func TestServeFileContentType(t *testing.T) {
 		if h := resp.Header.Get("Content-Type"); h != want {
 			t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
 		}
+		resp.Body.Close()
 	}
 	get("0", "text/plain; charset=utf-8")
 	get("1", ctype)
 }
 
 func TestServeFileMimeType(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		ServeFile(w, r, "testdata/style.css")
 	}))
@@ -269,6 +339,7 @@ func TestServeFileMimeType(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
+	resp.Body.Close()
 	want := "text/css; charset=utf-8"
 	if h := resp.Header.Get("Content-Type"); h != want {
 		t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
@@ -276,6 +347,7 @@ func TestServeFileMimeType(t *testing.T) {
 }
 
 func TestServeFileFromCWD(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		ServeFile(w, r, "fs_test.go")
 	}))
@@ -284,12 +356,14 @@ func TestServeFileFromCWD(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
+	r.Body.Close()
 	if r.StatusCode != 200 {
 		t.Fatalf("expected 200 OK, got %s", r.Status)
 	}
 }
 
 func TestServeFileWithContentEncoding(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header().Set("Content-Encoding", "foo")
 		ServeFile(w, r, "testdata/file")
@@ -299,12 +373,14 @@ func TestServeFileWithContentEncoding(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
+	resp.Body.Close()
 	if g, e := resp.ContentLength, int64(-1); g != e {
 		t.Errorf("Content-Length mismatch: got %d, want %d", g, e)
 	}
 }
 
 func TestServeIndexHtml(t *testing.T) {
+	defer checkLeakedTransports(t)
 	const want = "index.html says hello\n"
 	ts := httptest.NewServer(FileServer(Dir(".")))
 	defer ts.Close()
@@ -325,64 +401,289 @@ func TestServeIndexHtml(t *testing.T) {
 	}
 }
 
-func TestServeContent(t *testing.T) {
-	type req struct {
-		name    string
-		modtime time.Time
-		content io.ReadSeeker
-	}
-	ch := make(chan req, 1)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		p := <-ch
-		ServeContent(w, r, p.name, p.modtime, p.content)
-	}))
+func TestFileServerZeroByte(t *testing.T) {
+	defer checkLeakedTransports(t)
+	ts := httptest.NewServer(FileServer(Dir(".")))
 	defer ts.Close()
 
-	css, err := os.Open("testdata/style.css")
+	res, err := Get(ts.URL + "/..\x00")
 	if err != nil {
 		t.Fatal(err)
 	}
-	defer css.Close()
+	b, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal("reading Body:", err)
+	}
+	if res.StatusCode == 200 {
+		t.Errorf("got status 200; want an error. Body is:\n%s", string(b))
+	}
+}
+
+type fakeFileInfo struct {
+	dir      bool
+	basename string
+	modtime  time.Time
+	ents     []*fakeFileInfo
+	contents string
+}
+
+func (f *fakeFileInfo) Name() string       { return f.basename }
+func (f *fakeFileInfo) Sys() interface{}   { return nil }
+func (f *fakeFileInfo) ModTime() time.Time { return f.modtime }
+func (f *fakeFileInfo) IsDir() bool        { return f.dir }
+func (f *fakeFileInfo) Size() int64        { return int64(len(f.contents)) }
+func (f *fakeFileInfo) Mode() os.FileMode {
+	if f.dir {
+		return 0755 | os.ModeDir
+	}
+	return 0644
+}
+
+type fakeFile struct {
+	io.ReadSeeker
+	fi   *fakeFileInfo
+	path string // as opened
+}
+
+func (f *fakeFile) Close() error               { return nil }
+func (f *fakeFile) Stat() (os.FileInfo, error) { return f.fi, nil }
+func (f *fakeFile) Readdir(count int) ([]os.FileInfo, error) {
+	if !f.fi.dir {
+		return nil, os.ErrInvalid
+	}
+	var fis []os.FileInfo
+	for _, fi := range f.fi.ents {
+		fis = append(fis, fi)
+	}
+	return fis, nil
+}
+
+type fakeFS map[string]*fakeFileInfo
+
+func (fs fakeFS) Open(name string) (File, error) {
+	name = path.Clean(name)
+	f, ok := fs[name]
+	if !ok {
+		println("fake filesystem didn't find file", name)
+		return nil, os.ErrNotExist
+	}
+	return &fakeFile{ReadSeeker: strings.NewReader(f.contents), fi: f, path: name}, nil
+}
+
+func TestDirectoryIfNotModified(t *testing.T) {
+	defer checkLeakedTransports(t)
+	const indexContents = "I am a fake index.html file"
+	fileMod := time.Unix(1000000000, 0).UTC()
+	fileModStr := fileMod.Format(TimeFormat)
+	dirMod := time.Unix(123, 0).UTC()
+	indexFile := &fakeFileInfo{
+		basename: "index.html",
+		modtime:  fileMod,
+		contents: indexContents,
+	}
+	fs := fakeFS{
+		"/": &fakeFileInfo{
+			dir:     true,
+			modtime: dirMod,
+			ents:    []*fakeFileInfo{indexFile},
+		},
+		"/index.html": indexFile,
+	}
+
+	ts := httptest.NewServer(FileServer(fs))
+	defer ts.Close()
 
-	ch <- req{"style.css", time.Time{}, css}
 	res, err := Get(ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
-	if g, e := res.Header.Get("Content-Type"), "text/css; charset=utf-8"; g != e {
-		t.Errorf("style.css: content type = %q, want %q", g, e)
+	b, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
 	}
-	if g := res.Header.Get("Last-Modified"); g != "" {
-		t.Errorf("want empty Last-Modified; got %q", g)
+	if string(b) != indexContents {
+		t.Fatalf("Got body %q; want %q", b, indexContents)
 	}
+	res.Body.Close()
+
+	lastMod := res.Header.Get("Last-Modified")
+	if lastMod != fileModStr {
+		t.Fatalf("initial Last-Modified = %q; want %q", lastMod, fileModStr)
+	}
+
+	req, _ := NewRequest("GET", ts.URL, nil)
+	req.Header.Set("If-Modified-Since", lastMod)
 
-	fi, err := css.Stat()
+	res, err = DefaultClient.Do(req)
 	if err != nil {
 		t.Fatal(err)
 	}
-	ch <- req{"style.html", fi.ModTime(), css}
-	res, err = Get(ts.URL)
+	if res.StatusCode != 304 {
+		t.Fatalf("Code after If-Modified-Since request = %v; want 304", res.StatusCode)
+	}
+	res.Body.Close()
+
+	// Advance the index.html file's modtime, but not the directory's.
+	indexFile.modtime = indexFile.modtime.Add(1 * time.Hour)
+
+	res, err = DefaultClient.Do(req)
 	if err != nil {
 		t.Fatal(err)
 	}
-	if g, e := res.Header.Get("Content-Type"), "text/html; charset=utf-8"; g != e {
-		t.Errorf("style.html: content type = %q, want %q", g, e)
+	if res.StatusCode != 200 {
+		t.Fatalf("Code after second If-Modified-Since request = %v; want 200; res is %#v", res.StatusCode, res)
 	}
-	if g := res.Header.Get("Last-Modified"); g == "" {
-		t.Errorf("want non-empty last-modified")
+	res.Body.Close()
+}
+
+func mustStat(t *testing.T, fileName string) os.FileInfo {
+	fi, err := os.Stat(fileName)
+	if err != nil {
+		t.Fatal(err)
+	}
+	return fi
+}
+
+func TestServeContent(t *testing.T) {
+	defer checkLeakedTransports(t)
+	type serveParam struct {
+		name        string
+		modtime     time.Time
+		content     io.ReadSeeker
+		contentType string
+		etag        string
+	}
+	servec := make(chan serveParam, 1)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		p := <-servec
+		if p.etag != "" {
+			w.Header().Set("ETag", p.etag)
+		}
+		if p.contentType != "" {
+			w.Header().Set("Content-Type", p.contentType)
+		}
+		ServeContent(w, r, p.name, p.modtime, p.content)
+	}))
+	defer ts.Close()
+
+	type testCase struct {
+		file             string
+		modtime          time.Time
+		serveETag        string // optional
+		serveContentType string // optional
+		reqHeader        map[string]string
+		wantLastMod      string
+		wantContentType  string
+		wantStatus       int
+	}
+	htmlModTime := mustStat(t, "testdata/index.html").ModTime()
+	tests := map[string]testCase{
+		"no_last_modified": {
+			file:            "testdata/style.css",
+			wantContentType: "text/css; charset=utf-8",
+			wantStatus:      200,
+		},
+		"with_last_modified": {
+			file:            "testdata/index.html",
+			wantContentType: "text/html; charset=utf-8",
+			modtime:         htmlModTime,
+			wantLastMod:     htmlModTime.UTC().Format(TimeFormat),
+			wantStatus:      200,
+		},
+		"not_modified_modtime": {
+			file:    "testdata/style.css",
+			modtime: htmlModTime,
+			reqHeader: map[string]string{
+				"If-Modified-Since": htmlModTime.UTC().Format(TimeFormat),
+			},
+			wantStatus: 304,
+		},
+		"not_modified_modtime_with_contenttype": {
+			file:             "testdata/style.css",
+			serveContentType: "text/css", // explicit content type
+			modtime:          htmlModTime,
+			reqHeader: map[string]string{
+				"If-Modified-Since": htmlModTime.UTC().Format(TimeFormat),
+			},
+			wantStatus: 304,
+		},
+		"not_modified_etag": {
+			file:      "testdata/style.css",
+			serveETag: `"foo"`,
+			reqHeader: map[string]string{
+				"If-None-Match": `"foo"`,
+			},
+			wantStatus: 304,
+		},
+		"range_good": {
+			file:      "testdata/style.css",
+			serveETag: `"A"`,
+			reqHeader: map[string]string{
+				"Range": "bytes=0-4",
+			},
+			wantStatus:      StatusPartialContent,
+			wantContentType: "text/css; charset=utf-8",
+		},
+		// An If-Range resource for entity "A", but entity "B" is now current.
+		// The Range request should be ignored.
+		"range_no_match": {
+			file:      "testdata/style.css",
+			serveETag: `"A"`,
+			reqHeader: map[string]string{
+				"Range":    "bytes=0-4",
+				"If-Range": `"B"`,
+			},
+			wantStatus:      200,
+			wantContentType: "text/css; charset=utf-8",
+		},
+	}
+	for testName, tt := range tests {
+		f, err := os.Open(tt.file)
+		if err != nil {
+			t.Fatalf("test %q: %v", testName, err)
+		}
+		defer f.Close()
+
+		servec <- serveParam{
+			name:        filepath.Base(tt.file),
+			content:     f,
+			modtime:     tt.modtime,
+			etag:        tt.serveETag,
+			contentType: tt.serveContentType,
+		}
+		req, err := NewRequest("GET", ts.URL, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		for k, v := range tt.reqHeader {
+			req.Header.Set(k, v)
+		}
+		res, err := DefaultClient.Do(req)
+		if err != nil {
+			t.Fatal(err)
+		}
+		io.Copy(ioutil.Discard, res.Body)
+		res.Body.Close()
+		if res.StatusCode != tt.wantStatus {
+			t.Errorf("test %q: status = %d; want %d", testName, res.StatusCode, tt.wantStatus)
+		}
+		if g, e := res.Header.Get("Content-Type"), tt.wantContentType; g != e {
+			t.Errorf("test %q: content-type = %q, want %q", testName, g, e)
+		}
+		if g, e := res.Header.Get("Last-Modified"), tt.wantLastMod; g != e {
+			t.Errorf("test %q: last-modified = %q, want %q", testName, g, e)
+		}
 	}
 }
 
 // verifies that sendfile is being used on Linux
 func TestLinuxSendfile(t *testing.T) {
+	defer checkLeakedTransports(t)
 	if runtime.GOOS != "linux" {
-		t.Logf("skipping; linux-only test")
-		return
+		t.Skip("skipping; linux-only test")
 	}
-	_, err := exec.LookPath("strace")
-	if err != nil {
-		t.Logf("skipping; strace not found in path")
-		return
+	if _, err := exec.LookPath("strace"); err != nil {
+		t.Skip("skipping; strace not found in path")
 	}
 
 	ln, err := net.Listen("tcp", "127.0.0.1:0")
@@ -401,10 +702,8 @@ func TestLinuxSendfile(t *testing.T) {
 	child.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
 	child.Stdout = &buf
 	child.Stderr = &buf
-	err = child.Start()
-	if err != nil {
-		t.Logf("skipping; failed to start straced child: %v", err)
-		return
+	if err := child.Start(); err != nil {
+		t.Skipf("skipping; failed to start straced child: %v", err)
 	}
 
 	res, err := Get(fmt.Sprintf("http://%s/", ln.Addr()))
@@ -464,15 +763,3 @@ func TestLinuxSendfileChild(*testing.T) {
 		panic(err)
 	}
 }
-
-func equal(a, b []byte) bool {
-	if len(a) != len(b) {
-		return false
-	}
-	for i := range a {
-		if a[i] != b[i] {
-			return false
-		}
-	}
-	return true
-}
diff --git a/src/pkg/net/http/header.go b/src/pkg/net/http/header.go
index b107c31..f479b7b 100644
--- a/src/pkg/net/http/header.go
+++ b/src/pkg/net/http/header.go
@@ -5,11 +5,11 @@
 package http
 
 import (
-	"fmt"
 	"io"
 	"net/textproto"
 	"sort"
 	"strings"
+	"time"
 )
 
 // A Header represents the key-value pairs in an HTTP header.
@@ -36,6 +36,14 @@ func (h Header) Get(key string) string {
 	return textproto.MIMEHeader(h).Get(key)
 }
 
+// get is like Get, but key must already be in CanonicalHeaderKey form.
+func (h Header) get(key string) string {
+	if v := h[key]; len(v) > 0 {
+		return v[0]
+	}
+	return ""
+}
+
 // Del deletes the values associated with key.
 func (h Header) Del(key string) {
 	textproto.MIMEHeader(h).Del(key)
@@ -46,24 +54,87 @@ func (h Header) Write(w io.Writer) error {
 	return h.WriteSubset(w, nil)
 }
 
+func (h Header) clone() Header {
+	h2 := make(Header, len(h))
+	for k, vv := range h {
+		vv2 := make([]string, len(vv))
+		copy(vv2, vv)
+		h2[k] = vv2
+	}
+	return h2
+}
+
+var timeFormats = []string{
+	TimeFormat,
+	time.RFC850,
+	time.ANSIC,
+}
+
+// ParseTime parses a time header (such as the Date: header),
+// trying each of the three formats allowed by HTTP/1.1:
+// TimeFormat, time.RFC850, and time.ANSIC.
+func ParseTime(text string) (t time.Time, err error) {
+	for _, layout := range timeFormats {
+		t, err = time.Parse(layout, text)
+		if err == nil {
+			return
+		}
+	}
+	return
+}
+
 var headerNewlineToSpace = strings.NewReplacer("\n", " ", "\r", " ")
 
+type writeStringer interface {
+	WriteString(string) (int, error)
+}
+
+// stringWriter implements WriteString on a Writer.
+type stringWriter struct {
+	w io.Writer
+}
+
+func (w stringWriter) WriteString(s string) (n int, err error) {
+	return w.w.Write([]byte(s))
+}
+
+type keyValues struct {
+	key    string
+	values []string
+}
+
+type byKey []keyValues
+
+func (s byKey) Len() int           { return len(s) }
+func (s byKey) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s byKey) Less(i, j int) bool { return s[i].key < s[j].key }
+
+func (h Header) sortedKeyValues(exclude map[string]bool) []keyValues {
+	kvs := make([]keyValues, 0, len(h))
+	for k, vv := range h {
+		if !exclude[k] {
+			kvs = append(kvs, keyValues{k, vv})
+		}
+	}
+	sort.Sort(byKey(kvs))
+	return kvs
+}
+
 // WriteSubset writes a header in wire format.
 // If exclude is not nil, keys where exclude[key] == true are not written.
 func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
-	keys := make([]string, 0, len(h))
-	for k := range h {
-		if exclude == nil || !exclude[k] {
-			keys = append(keys, k)
-		}
+	ws, ok := w.(writeStringer)
+	if !ok {
+		ws = stringWriter{w}
 	}
-	sort.Strings(keys)
-	for _, k := range keys {
-		for _, v := range h[k] {
+	for _, kv := range h.sortedKeyValues(exclude) {
+		for _, v := range kv.values {
 			v = headerNewlineToSpace.Replace(v)
-			v = strings.TrimSpace(v)
-			if _, err := fmt.Fprintf(w, "%s: %s\r\n", k, v); err != nil {
-				return err
+			v = textproto.TrimString(v)
+			for _, s := range []string{kv.key, ": ", v, "\r\n"} {
+				if _, err := ws.WriteString(s); err != nil {
+					return err
+				}
 			}
 		}
 	}
@@ -76,3 +147,43 @@ func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
 // the rest are converted to lowercase.  For example, the
 // canonical key for "accept-encoding" is "Accept-Encoding".
 func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
+
+// hasToken returns whether token appears with v, ASCII
+// case-insensitive, with space or comma boundaries.
+// token must be all lowercase.
+// v may contain mixed cased.
+func hasToken(v, token string) bool {
+	if len(token) > len(v) || token == "" {
+		return false
+	}
+	if v == token {
+		return true
+	}
+	for sp := 0; sp <= len(v)-len(token); sp++ {
+		// Check that first character is good.
+		// The token is ASCII, so checking only a single byte
+		// is sufficient.  We skip this potential starting
+		// position if both the first byte and its potential
+		// ASCII uppercase equivalent (b|0x20) don't match.
+		// False positives ('^' => '~') are caught by EqualFold.
+		if b := v[sp]; b != token[0] && b|0x20 != token[0] {
+			continue
+		}
+		// Check that start pos is on a valid token boundary.
+		if sp > 0 && !isTokenBoundary(v[sp-1]) {
+			continue
+		}
+		// Check that end pos is on a valid token boundary.
+		if endPos := sp + len(token); endPos != len(v) && !isTokenBoundary(v[endPos]) {
+			continue
+		}
+		if strings.EqualFold(v[sp:sp+len(token)], token) {
+			return true
+		}
+	}
+	return false
+}
+
+func isTokenBoundary(b byte) bool {
+	return b == ' ' || b == ',' || b == '\t'
+}
diff --git a/src/pkg/net/http/header_test.go b/src/pkg/net/http/header_test.go
index ccdee8a..2313b55 100644
--- a/src/pkg/net/http/header_test.go
+++ b/src/pkg/net/http/header_test.go
@@ -7,6 +7,7 @@ package http
 import (
 	"bytes"
 	"testing"
+	"time"
 )
 
 var headerWriteTests = []struct {
@@ -67,6 +68,24 @@ var headerWriteTests = []struct {
 		nil,
 		"Blank: \r\nDouble-Blank: \r\nDouble-Blank: \r\n",
 	},
+	// Tests header sorting when over the insertion sort threshold side:
+	{
+		Header{
+			"k1": {"1a", "1b"},
+			"k2": {"2a", "2b"},
+			"k3": {"3a", "3b"},
+			"k4": {"4a", "4b"},
+			"k5": {"5a", "5b"},
+			"k6": {"6a", "6b"},
+			"k7": {"7a", "7b"},
+			"k8": {"8a", "8b"},
+			"k9": {"9a", "9b"},
+		},
+		map[string]bool{"k5": true},
+		"k1: 1a\r\nk1: 1b\r\nk2: 2a\r\nk2: 2b\r\nk3: 3a\r\nk3: 3b\r\n" +
+			"k4: 4a\r\nk4: 4b\r\nk6: 6a\r\nk6: 6b\r\n" +
+			"k7: 7a\r\nk7: 7b\r\nk8: 8a\r\nk8: 8b\r\nk9: 9a\r\nk9: 9b\r\n",
+	},
 }
 
 func TestHeaderWrite(t *testing.T) {
@@ -79,3 +98,107 @@ func TestHeaderWrite(t *testing.T) {
 		buf.Reset()
 	}
 }
+
+var parseTimeTests = []struct {
+	h   Header
+	err bool
+}{
+	{Header{"Date": {""}}, true},
+	{Header{"Date": {"invalid"}}, true},
+	{Header{"Date": {"1994-11-06T08:49:37Z00:00"}}, true},
+	{Header{"Date": {"Sun, 06 Nov 1994 08:49:37 GMT"}}, false},
+	{Header{"Date": {"Sunday, 06-Nov-94 08:49:37 GMT"}}, false},
+	{Header{"Date": {"Sun Nov  6 08:49:37 1994"}}, false},
+}
+
+func TestParseTime(t *testing.T) {
+	expect := time.Date(1994, 11, 6, 8, 49, 37, 0, time.UTC)
+	for i, test := range parseTimeTests {
+		d, err := ParseTime(test.h.Get("Date"))
+		if err != nil {
+			if !test.err {
+				t.Errorf("#%d:\n got err: %v", i, err)
+			}
+			continue
+		}
+		if test.err {
+			t.Errorf("#%d:\n  should err", i)
+			continue
+		}
+		if !expect.Equal(d) {
+			t.Errorf("#%d:\n got: %v\nwant: %v", i, d, expect)
+		}
+	}
+}
+
+type hasTokenTest struct {
+	header string
+	token  string
+	want   bool
+}
+
+var hasTokenTests = []hasTokenTest{
+	{"", "", false},
+	{"", "foo", false},
+	{"foo", "foo", true},
+	{"foo ", "foo", true},
+	{" foo", "foo", true},
+	{" foo ", "foo", true},
+	{"foo,bar", "foo", true},
+	{"bar,foo", "foo", true},
+	{"bar, foo", "foo", true},
+	{"bar,foo, baz", "foo", true},
+	{"bar, foo,baz", "foo", true},
+	{"bar,foo, baz", "foo", true},
+	{"bar, foo, baz", "foo", true},
+	{"FOO", "foo", true},
+	{"FOO ", "foo", true},
+	{" FOO", "foo", true},
+	{" FOO ", "foo", true},
+	{"FOO,BAR", "foo", true},
+	{"BAR,FOO", "foo", true},
+	{"BAR, FOO", "foo", true},
+	{"BAR,FOO, baz", "foo", true},
+	{"BAR, FOO,BAZ", "foo", true},
+	{"BAR,FOO, BAZ", "foo", true},
+	{"BAR, FOO, BAZ", "foo", true},
+	{"foobar", "foo", false},
+	{"barfoo ", "foo", false},
+}
+
+func TestHasToken(t *testing.T) {
+	for _, tt := range hasTokenTests {
+		if hasToken(tt.header, tt.token) != tt.want {
+			t.Errorf("hasToken(%q, %q) = %v; want %v", tt.header, tt.token, !tt.want, tt.want)
+		}
+	}
+}
+
+var testHeader = Header{
+	"Content-Length": {"123"},
+	"Content-Type":   {"text/plain"},
+	"Date":           {"some date at some time Z"},
+	"Server":         {"Go http package"},
+}
+
+var buf bytes.Buffer
+
+func BenchmarkHeaderWriteSubset(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		buf.Reset()
+		testHeader.WriteSubset(&buf, nil)
+	}
+}
+
+func TestHeaderWriteSubsetMallocs(t *testing.T) {
+	n := testing.AllocsPerRun(100, func() {
+		buf.Reset()
+		testHeader.WriteSubset(&buf, nil)
+	})
+	if n > 1 {
+		// TODO(bradfitz,rsc): once we can sort without allocating,
+		// make this an error.  See http://golang.org/issue/3761
+		// t.Errorf("got %v allocs, want <= %v", n, 1)
+	}
+}
diff --git a/src/pkg/net/http/httptest/example_test.go b/src/pkg/net/http/httptest/example_test.go
new file mode 100644
index 0000000..239470d
--- /dev/null
+++ b/src/pkg/net/http/httptest/example_test.go
@@ -0,0 +1,50 @@
+// 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 httptest_test
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"net/http/httptest"
+)
+
+func ExampleRecorder() {
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		http.Error(w, "something failed", http.StatusInternalServerError)
+	}
+
+	req, err := http.NewRequest("GET", "http://example.com/foo", nil)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	w := httptest.NewRecorder()
+	handler(w, req)
+
+	fmt.Printf("%d - %s", w.Code, w.Body.String())
+	// Output: 500 - something failed
+}
+
+func ExampleServer() {
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		fmt.Fprintln(w, "Hello, client")
+	}))
+	defer ts.Close()
+
+	res, err := http.Get(ts.URL)
+	if err != nil {
+		log.Fatal(err)
+	}
+	greeting, err := ioutil.ReadAll(res.Body)
+	res.Body.Close()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("%s", greeting)
+	// Output: Hello, client
+}
diff --git a/src/pkg/net/http/httptest/recorder.go b/src/pkg/net/http/httptest/recorder.go
index 9aa0d51..5451f54 100644
--- a/src/pkg/net/http/httptest/recorder.go
+++ b/src/pkg/net/http/httptest/recorder.go
@@ -17,6 +17,8 @@ type ResponseRecorder struct {
 	HeaderMap http.Header   // the HTTP response headers
 	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
 	Flushed   bool
+
+	wroteHeader bool
 }
 
 // NewRecorder returns an initialized ResponseRecorder.
@@ -24,6 +26,7 @@ func NewRecorder() *ResponseRecorder {
 	return &ResponseRecorder{
 		HeaderMap: make(http.Header),
 		Body:      new(bytes.Buffer),
+		Code:      200,
 	}
 }
 
@@ -33,26 +36,37 @@ const DefaultRemoteAddr = "1.2.3.4"
 
 // Header returns the response headers.
 func (rw *ResponseRecorder) Header() http.Header {
-	return rw.HeaderMap
+	m := rw.HeaderMap
+	if m == nil {
+		m = make(http.Header)
+		rw.HeaderMap = m
+	}
+	return m
 }
 
 // Write always succeeds and writes to rw.Body, if not nil.
 func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
+	if !rw.wroteHeader {
+		rw.WriteHeader(200)
+	}
 	if rw.Body != nil {
 		rw.Body.Write(buf)
 	}
-	if rw.Code == 0 {
-		rw.Code = http.StatusOK
-	}
 	return len(buf), nil
 }
 
 // WriteHeader sets rw.Code.
 func (rw *ResponseRecorder) WriteHeader(code int) {
-	rw.Code = code
+	if !rw.wroteHeader {
+		rw.Code = code
+	}
+	rw.wroteHeader = true
 }
 
 // Flush sets rw.Flushed to true.
 func (rw *ResponseRecorder) Flush() {
+	if !rw.wroteHeader {
+		rw.WriteHeader(200)
+	}
 	rw.Flushed = true
 }
diff --git a/src/pkg/net/http/httptest/recorder_test.go b/src/pkg/net/http/httptest/recorder_test.go
new file mode 100644
index 0000000..2b56326
--- /dev/null
+++ b/src/pkg/net/http/httptest/recorder_test.go
@@ -0,0 +1,90 @@
+// 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 httptest
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+)
+
+func TestRecorder(t *testing.T) {
+	type checkFunc func(*ResponseRecorder) error
+	check := func(fns ...checkFunc) []checkFunc { return fns }
+
+	hasStatus := func(wantCode int) checkFunc {
+		return func(rec *ResponseRecorder) error {
+			if rec.Code != wantCode {
+				return fmt.Errorf("Status = %d; want %d", rec.Code, wantCode)
+			}
+			return nil
+		}
+	}
+	hasContents := func(want string) checkFunc {
+		return func(rec *ResponseRecorder) error {
+			if rec.Body.String() != want {
+				return fmt.Errorf("wrote = %q; want %q", rec.Body.String(), want)
+			}
+			return nil
+		}
+	}
+	hasFlush := func(want bool) checkFunc {
+		return func(rec *ResponseRecorder) error {
+			if rec.Flushed != want {
+				return fmt.Errorf("Flushed = %v; want %v", rec.Flushed, want)
+			}
+			return nil
+		}
+	}
+
+	tests := []struct {
+		name   string
+		h      func(w http.ResponseWriter, r *http.Request)
+		checks []checkFunc
+	}{
+		{
+			"200 default",
+			func(w http.ResponseWriter, r *http.Request) {},
+			check(hasStatus(200), hasContents("")),
+		},
+		{
+			"first code only",
+			func(w http.ResponseWriter, r *http.Request) {
+				w.WriteHeader(201)
+				w.WriteHeader(202)
+				w.Write([]byte("hi"))
+			},
+			check(hasStatus(201), hasContents("hi")),
+		},
+		{
+			"write sends 200",
+			func(w http.ResponseWriter, r *http.Request) {
+				w.Write([]byte("hi first"))
+				w.WriteHeader(201)
+				w.WriteHeader(202)
+			},
+			check(hasStatus(200), hasContents("hi first"), hasFlush(false)),
+		},
+		{
+			"flush",
+			func(w http.ResponseWriter, r *http.Request) {
+				w.(http.Flusher).Flush() // also sends a 200
+				w.WriteHeader(201)
+			},
+			check(hasStatus(200), hasFlush(true)),
+		},
+	}
+	r, _ := http.NewRequest("GET", "http://foo.com/", nil)
+	for _, tt := range tests {
+		h := http.HandlerFunc(tt.h)
+		rec := NewRecorder()
+		h.ServeHTTP(rec, r)
+		for _, check := range tt.checks {
+			if err := check(rec); err != nil {
+				t.Errorf("%s: %v", tt.name, err)
+			}
+		}
+	}
+}
diff --git a/src/pkg/net/http/httptest/server.go b/src/pkg/net/http/httptest/server.go
index 57cf0c9..7f26555 100644
--- a/src/pkg/net/http/httptest/server.go
+++ b/src/pkg/net/http/httptest/server.go
@@ -21,7 +21,11 @@ import (
 type Server struct {
 	URL      string // base URL of form http://ipaddr:port with no trailing slash
 	Listener net.Listener
-	TLS      *tls.Config // nil if not using using TLS
+
+	// TLS is the optional TLS configuration, populated with a new config
+	// after TLS is started. If set on an unstarted server before StartTLS
+	// is called, existing fields are copied into the new config.
+	TLS *tls.Config
 
 	// Config may be changed after calling NewUnstartedServer and
 	// before Start or StartTLS.
@@ -36,13 +40,16 @@ type Server struct {
 // accepted.
 type historyListener struct {
 	net.Listener
-	history []net.Conn
+	sync.Mutex // protects history
+	history    []net.Conn
 }
 
 func (hs *historyListener) Accept() (c net.Conn, err error) {
 	c, err = hs.Listener.Accept()
 	if err == nil {
+		hs.Lock()
 		hs.history = append(hs.history, c)
+		hs.Unlock()
 	}
 	return
 }
@@ -96,7 +103,7 @@ func (s *Server) Start() {
 	if s.URL != "" {
 		panic("Server already started")
 	}
-	s.Listener = &historyListener{s.Listener, make([]net.Conn, 0)}
+	s.Listener = &historyListener{Listener: s.Listener}
 	s.URL = "http://" + s.Listener.Addr().String()
 	s.wrapHandler()
 	go s.Config.Serve(s.Listener)
@@ -116,13 +123,20 @@ func (s *Server) StartTLS() {
 		panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
 	}
 
-	s.TLS = &tls.Config{
-		NextProtos:   []string{"http/1.1"},
-		Certificates: []tls.Certificate{cert},
+	existingConfig := s.TLS
+	s.TLS = new(tls.Config)
+	if existingConfig != nil {
+		*s.TLS = *existingConfig
+	}
+	if s.TLS.NextProtos == nil {
+		s.TLS.NextProtos = []string{"http/1.1"}
+	}
+	if len(s.TLS.Certificates) == 0 {
+		s.TLS.Certificates = []tls.Certificate{cert}
 	}
 	tlsListener := tls.NewListener(s.Listener, s.TLS)
 
-	s.Listener = &historyListener{tlsListener, make([]net.Conn, 0)}
+	s.Listener = &historyListener{Listener: tlsListener}
 	s.URL = "https://" + s.Listener.Addr().String()
 	s.wrapHandler()
 	go s.Config.Serve(s.Listener)
@@ -152,6 +166,10 @@ func NewTLSServer(handler http.Handler) *Server {
 func (s *Server) Close() {
 	s.Listener.Close()
 	s.wg.Wait()
+	s.CloseClientConnections()
+	if t, ok := http.DefaultTransport.(*http.Transport); ok {
+		t.CloseIdleConnections()
+	}
 }
 
 // CloseClientConnections closes any currently open HTTP connections
@@ -161,9 +179,11 @@ func (s *Server) CloseClientConnections() {
 	if !ok {
 		return
 	}
+	hl.Lock()
 	for _, conn := range hl.history {
 		conn.Close()
 	}
+	hl.Unlock()
 }
 
 // waitGroupHandler wraps a handler, incrementing and decrementing a
@@ -180,28 +200,29 @@ func (h *waitGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	h.h.ServeHTTP(w, r)
 }
 
-// localhostCert is a PEM-encoded TLS cert with SAN DNS names
+// 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:
+// 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-----
-MIIBOTCB5qADAgECAgEAMAsGCSqGSIb3DQEBBTAAMB4XDTcwMDEwMTAwMDAwMFoX
-DTQ5MTIzMTIzNTk1OVowADBaMAsGCSqGSIb3DQEBAQNLADBIAkEAsuA5mAFMj6Q7
-qoBzcvKzIq4kzuT5epSp2AkcQfyBHm7K13Ws7u+0b5Vb9gqTf5cAiIKcrtrXVqkL
-8i1UQF6AzwIDAQABo08wTTAOBgNVHQ8BAf8EBAMCACQwDQYDVR0OBAYEBAECAwQw
-DwYDVR0jBAgwBoAEAQIDBDAbBgNVHREEFDASggkxMjcuMC4wLjGCBVs6OjFdMAsG
-CSqGSIb3DQEBBQNBAJH30zjLWRztrWpOCgJL8RQWLaKzhK79pVhAx6q/3NrF16C7
-+l1BRZstTwIGdoGId8BRpErK1TXkniFb95ZMynM=
------END CERTIFICATE-----
-`)
+MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
+bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
+bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
+IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
+AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
+EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
+AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
+Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
+-----END CERTIFICATE-----`)
 
 // localhostKey is the private key for localhostCert.
 var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
-MIIBPQIBAAJBALLgOZgBTI+kO6qAc3LysyKuJM7k+XqUqdgJHEH8gR5uytd1rO7v
-tG+VW/YKk3+XAIiCnK7a11apC/ItVEBegM8CAwEAAQJBAI5sxq7naeR9ahyqRkJi
-SIv2iMxLuPEHaezf5CYOPWjSjBPyVhyRevkhtqEjF/WkgL7C2nWpYHsUcBDBQVF0
-3KECIQDtEGB2ulnkZAahl3WuJziXGLB+p8Wgx7wzSM6bHu1c6QIhAMEp++CaS+SJ
-/TrU0zwY/fW4SvQeb49BPZUF3oqR8Xz3AiEA1rAJHBzBgdOQKdE3ksMUPcnvNJSN
-poCcELmz2clVXtkCIQCLytuLV38XHToTipR4yMl6O+6arzAjZ56uq7m7ZRV0TwIh
-AM65XAOw8Dsg9Kq78aYXiOEDc5DL0sbFUu/SlmRcCg93
------END RSA PRIVATE KEY-----
-`)
+MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
+0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
+NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
+AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
+MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
+EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
+1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
+-----END RSA PRIVATE KEY-----`)
diff --git a/src/pkg/net/http/httputil/chunked.go b/src/pkg/net/http/httputil/chunked.go
index 29eaf34..b66d409 100644
--- a/src/pkg/net/http/httputil/chunked.go
+++ b/src/pkg/net/http/httputil/chunked.go
@@ -13,10 +13,9 @@ package httputil
 
 import (
 	"bufio"
-	"bytes"
 	"errors"
+	"fmt"
 	"io"
-	"strconv"
 )
 
 const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
@@ -24,7 +23,7 @@ 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. 
+// 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
@@ -41,16 +40,17 @@ 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 string
+	var line []byte
 	line, cr.err = readLine(cr.r)
 	if cr.err != nil {
 		return
 	}
-	cr.n, cr.err = strconv.ParseUint(line, 16, 64)
+	cr.n, cr.err = parseHexUint(line)
 	if cr.err != nil {
 		return
 	}
@@ -76,9 +76,8 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
 	cr.n -= uint64(n)
 	if cr.n == 0 && cr.err == nil {
 		// end of chunk (CRLF)
-		b := make([]byte, 2)
-		if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
-			if b[0] != '\r' || b[1] != '\n' {
+		if _, cr.err = io.ReadFull(cr.r, cr.buf[:]); cr.err == nil {
+			if cr.buf[0] != '\r' || cr.buf[1] != '\n' {
 				cr.err = errors.New("malformed chunked encoding")
 			}
 		}
@@ -90,7 +89,7 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
 // 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 readLineBytes(b *bufio.Reader) (p []byte, err error) {
+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.
@@ -104,20 +103,18 @@ func readLineBytes(b *bufio.Reader) (p []byte, err error) {
 	if len(p) >= maxLineLength {
 		return nil, ErrLineTooLong
 	}
-
-	// Chop off trailing white space.
-	p = bytes.TrimRight(p, " \r\t\n")
-
-	return p, nil
+	return trimTrailingWhitespace(p), nil
 }
 
-// readLineBytes, but convert the bytes into a string.
-func readLine(b *bufio.Reader) (s string, err error) {
-	p, e := readLineBytes(b)
-	if e != nil {
-		return "", e
+func trimTrailingWhitespace(b []byte) []byte {
+	for len(b) > 0 && isASCIISpace(b[len(b)-1]) {
+		b = b[:len(b)-1]
 	}
-	return string(p), nil
+	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
@@ -149,9 +146,7 @@ func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
 		return 0, nil
 	}
 
-	head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
-
-	if _, err = io.WriteString(cw.Wire, head); err != 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 {
@@ -170,3 +165,21 @@ 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
index 155a32b..a06bffa 100644
--- a/src/pkg/net/http/httputil/chunked_test.go
+++ b/src/pkg/net/http/httputil/chunked_test.go
@@ -11,7 +11,10 @@ package httputil
 
 import (
 	"bytes"
+	"fmt"
+	"io"
 	"io/ioutil"
+	"runtime"
 	"testing"
 )
 
@@ -39,3 +42,54 @@ func TestChunk(t *testing.T) {
 		t.Errorf("chunk reader read %q; want %q", g, e)
 	}
 }
+
+func TestChunkReaderAllocs(t *testing.T) {
+	// temporarily set GOMAXPROCS to 1 as we are testing memory allocations
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
+	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()
+
+	r := NewChunkedReader(&buf)
+	readBuf := make([]byte, len(a)+len(b)+len(c)+1)
+
+	var ms runtime.MemStats
+	runtime.ReadMemStats(&ms)
+	m0 := ms.Mallocs
+
+	n, err := io.ReadFull(r, readBuf)
+
+	runtime.ReadMemStats(&ms)
+	mallocs := ms.Mallocs - m0
+	if mallocs > 1 {
+		t.Errorf("%d mallocs; want <= 1", mallocs)
+	}
+
+	if n != len(readBuf)-1 {
+		t.Errorf("read %d bytes; want %d", n, len(readBuf)-1)
+	}
+	if err != io.ErrUnexpectedEOF {
+		t.Errorf("read error = %v; want ErrUnexpectedEOF", err)
+	}
+}
+
+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/http/httputil/dump.go b/src/pkg/net/http/httputil/dump.go
index 892ef4e..0b00356 100644
--- a/src/pkg/net/http/httputil/dump.go
+++ b/src/pkg/net/http/httputil/dump.go
@@ -75,7 +75,7 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
 
 	// Use the actual Transport code to record what we would send
 	// on the wire, but not using TCP.  Use a Transport with a
-	// customer dialer that returns a fake net.Conn that waits
+	// custom dialer that returns a fake net.Conn that waits
 	// for the full input (and recording it), and then responds
 	// with a dummy response.
 	var buf bytes.Buffer // records the output
@@ -89,7 +89,7 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
 
 	t := &http.Transport{
 		Dial: func(net, addr string) (net.Conn, error) {
-			return &dumpConn{io.MultiWriter(pw, &buf), dr}, nil
+			return &dumpConn{io.MultiWriter(&buf, pw), dr}, nil
 		},
 	}
 
diff --git a/src/pkg/net/http/httputil/reverseproxy.go b/src/pkg/net/http/httputil/reverseproxy.go
index 9c4bd6e..134c452 100644
--- a/src/pkg/net/http/httputil/reverseproxy.go
+++ b/src/pkg/net/http/httputil/reverseproxy.go
@@ -17,6 +17,10 @@ import (
 	"time"
 )
 
+// onExitFlushLoop is a callback set by tests to detect the state of the
+// flushLoop() goroutine.
+var onExitFlushLoop func()
+
 // ReverseProxy is an HTTP Handler that takes an incoming request and
 // sends it to another server, proxying the response back to the
 // client.
@@ -102,8 +106,14 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 		outreq.Header.Del("Connection")
 	}
 
-	if clientIp, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
-		outreq.Header.Set("X-Forwarded-For", clientIp)
+	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
+		// If we aren't the first proxy retain prior
+		// X-Forwarded-For information as a comma+space
+		// separated list and fold multiple headers into one.
+		if prior, ok := outreq.Header["X-Forwarded-For"]; ok {
+			clientIP = strings.Join(prior, ", ") + ", " + clientIP
+		}
+		outreq.Header.Set("X-Forwarded-For", clientIP)
 	}
 
 	res, err := transport.RoundTrip(outreq)
@@ -112,20 +122,29 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 		rw.WriteHeader(http.StatusInternalServerError)
 		return
 	}
+	defer res.Body.Close()
 
 	copyHeader(rw.Header(), res.Header)
 
 	rw.WriteHeader(res.StatusCode)
+	p.copyResponse(rw, res.Body)
+}
 
-	if res.Body != nil {
-		var dst io.Writer = rw
-		if p.FlushInterval != 0 {
-			if wf, ok := rw.(writeFlusher); ok {
-				dst = &maxLatencyWriter{dst: wf, latency: p.FlushInterval}
+func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader) {
+	if p.FlushInterval != 0 {
+		if wf, ok := dst.(writeFlusher); ok {
+			mlw := &maxLatencyWriter{
+				dst:     wf,
+				latency: p.FlushInterval,
+				done:    make(chan bool),
 			}
+			go mlw.flushLoop()
+			defer mlw.stop()
+			dst = mlw
 		}
-		io.Copy(dst, res.Body)
 	}
+
+	io.Copy(dst, src)
 }
 
 type writeFlusher interface {
@@ -137,22 +156,14 @@ type maxLatencyWriter struct {
 	dst     writeFlusher
 	latency time.Duration
 
-	lk   sync.Mutex // protects init of done, as well Write + Flush
+	lk   sync.Mutex // protects Write + Flush
 	done chan bool
 }
 
-func (m *maxLatencyWriter) Write(p []byte) (n int, err error) {
+func (m *maxLatencyWriter) Write(p []byte) (int, error) {
 	m.lk.Lock()
 	defer m.lk.Unlock()
-	if m.done == nil {
-		m.done = make(chan bool)
-		go m.flushLoop()
-	}
-	n, err = m.dst.Write(p)
-	if err != nil {
-		m.done <- true
-	}
-	return
+	return m.dst.Write(p)
 }
 
 func (m *maxLatencyWriter) flushLoop() {
@@ -160,13 +171,18 @@ func (m *maxLatencyWriter) flushLoop() {
 	defer t.Stop()
 	for {
 		select {
+		case <-m.done:
+			if onExitFlushLoop != nil {
+				onExitFlushLoop()
+			}
+			return
 		case <-t.C:
 			m.lk.Lock()
 			m.dst.Flush()
 			m.lk.Unlock()
-		case <-m.done:
-			return
 		}
 	}
 	panic("unreached")
 }
+
+func (m *maxLatencyWriter) stop() { m.done <- true }
diff --git a/src/pkg/net/http/httputil/reverseproxy_test.go b/src/pkg/net/http/httputil/reverseproxy_test.go
index 28e9c90..8639271 100644
--- a/src/pkg/net/http/httputil/reverseproxy_test.go
+++ b/src/pkg/net/http/httputil/reverseproxy_test.go
@@ -11,7 +11,9 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"net/url"
+	"strings"
 	"testing"
+	"time"
 )
 
 func TestReverseProxy(t *testing.T) {
@@ -70,6 +72,47 @@ func TestReverseProxy(t *testing.T) {
 	}
 }
 
+func TestXForwardedFor(t *testing.T) {
+	const prevForwardedFor = "client ip"
+	const backendResponse = "I am the backend"
+	const backendStatus = 404
+	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.Header.Get("X-Forwarded-For") == "" {
+			t.Errorf("didn't get X-Forwarded-For header")
+		}
+		if !strings.Contains(r.Header.Get("X-Forwarded-For"), prevForwardedFor) {
+			t.Errorf("X-Forwarded-For didn't contain prior data")
+		}
+		w.WriteHeader(backendStatus)
+		w.Write([]byte(backendResponse))
+	}))
+	defer backend.Close()
+	backendURL, err := url.Parse(backend.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	proxyHandler := NewSingleHostReverseProxy(backendURL)
+	frontend := httptest.NewServer(proxyHandler)
+	defer frontend.Close()
+
+	getReq, _ := http.NewRequest("GET", frontend.URL, nil)
+	getReq.Host = "some-name"
+	getReq.Header.Set("Connection", "close")
+	getReq.Header.Set("X-Forwarded-For", prevForwardedFor)
+	getReq.Close = true
+	res, err := http.DefaultClient.Do(getReq)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	if g, e := res.StatusCode, backendStatus; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	bodyBytes, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(bodyBytes), backendResponse; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+}
+
 var proxyQueryTests = []struct {
 	baseSuffix string // suffix to add to backend URL
 	reqSuffix  string // suffix to add to frontend's request URL
@@ -107,3 +150,44 @@ func TestReverseProxyQuery(t *testing.T) {
 		frontend.Close()
 	}
 }
+
+func TestReverseProxyFlushInterval(t *testing.T) {
+	const expected = "hi"
+	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Write([]byte(expected))
+	}))
+	defer backend.Close()
+
+	backendURL, err := url.Parse(backend.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	proxyHandler := NewSingleHostReverseProxy(backendURL)
+	proxyHandler.FlushInterval = time.Microsecond
+
+	done := make(chan bool)
+	onExitFlushLoop = func() { done <- true }
+	defer func() { onExitFlushLoop = nil }()
+
+	frontend := httptest.NewServer(proxyHandler)
+	defer frontend.Close()
+
+	req, _ := http.NewRequest("GET", frontend.URL, nil)
+	req.Close = true
+	res, err := http.DefaultClient.Do(req)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	defer res.Body.Close()
+	if bodyBytes, _ := ioutil.ReadAll(res.Body); string(bodyBytes) != expected {
+		t.Errorf("got body %q; expected %q", bodyBytes, expected)
+	}
+
+	select {
+	case <-done:
+		// OK
+	case <-time.After(5 * time.Second):
+		t.Error("maxLatencyWriter flushLoop() never exited")
+	}
+}
diff --git a/src/pkg/net/http/jar.go b/src/pkg/net/http/jar.go
index 2c2caa2..5c3de0d 100644
--- a/src/pkg/net/http/jar.go
+++ b/src/pkg/net/http/jar.go
@@ -8,23 +8,20 @@ import (
 	"net/url"
 )
 
-// A CookieJar manages storage and use of cookies in HTTP requests. 
+// A CookieJar manages storage and use of cookies in HTTP requests.
 //
 // Implementations of CookieJar must be safe for concurrent use by multiple
 // goroutines.
+//
+// The net/http/cookiejar package provides a CookieJar implementation.
 type CookieJar interface {
-	// SetCookies handles the receipt of the cookies in a reply for the 
-	// given URL.  It may or may not choose to save the cookies, depending 
-	// on the jar's policy and implementation. 
+	// SetCookies handles the receipt of the cookies in a reply for the
+	// given URL.  It may or may not choose to save the cookies, depending
+	// on the jar's policy and implementation.
 	SetCookies(u *url.URL, cookies []*Cookie)
 
 	// Cookies returns the cookies to send in a request for the given URL.
-	// It is up to the implementation to honor the standard cookie use 
-	// restrictions such as in RFC 6265. 
+	// It is up to the implementation to honor the standard cookie use
+	// restrictions such as in RFC 6265.
 	Cookies(u *url.URL) []*Cookie
 }
-
-type blackHoleJar struct{}
-
-func (blackHoleJar) SetCookies(u *url.URL, cookies []*Cookie) {}
-func (blackHoleJar) Cookies(u *url.URL) []*Cookie             { return nil }
diff --git a/src/pkg/net/http/lex.go b/src/pkg/net/http/lex.go
index ffb393c..cb33318 100644
--- a/src/pkg/net/http/lex.go
+++ b/src/pkg/net/http/lex.go
@@ -6,131 +6,91 @@ package http
 
 // This file deals with lexical matters of HTTP
 
-func isSeparator(c byte) bool {
-	switch c {
-	case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
-		return true
-	}
-	return false
+var isTokenTable = [127]bool{
+	'!':  true,
+	'#':  true,
+	'$':  true,
+	'%':  true,
+	'&':  true,
+	'\'': true,
+	'*':  true,
+	'+':  true,
+	'-':  true,
+	'.':  true,
+	'0':  true,
+	'1':  true,
+	'2':  true,
+	'3':  true,
+	'4':  true,
+	'5':  true,
+	'6':  true,
+	'7':  true,
+	'8':  true,
+	'9':  true,
+	'A':  true,
+	'B':  true,
+	'C':  true,
+	'D':  true,
+	'E':  true,
+	'F':  true,
+	'G':  true,
+	'H':  true,
+	'I':  true,
+	'J':  true,
+	'K':  true,
+	'L':  true,
+	'M':  true,
+	'N':  true,
+	'O':  true,
+	'P':  true,
+	'Q':  true,
+	'R':  true,
+	'S':  true,
+	'T':  true,
+	'U':  true,
+	'W':  true,
+	'V':  true,
+	'X':  true,
+	'Y':  true,
+	'Z':  true,
+	'^':  true,
+	'_':  true,
+	'`':  true,
+	'a':  true,
+	'b':  true,
+	'c':  true,
+	'd':  true,
+	'e':  true,
+	'f':  true,
+	'g':  true,
+	'h':  true,
+	'i':  true,
+	'j':  true,
+	'k':  true,
+	'l':  true,
+	'm':  true,
+	'n':  true,
+	'o':  true,
+	'p':  true,
+	'q':  true,
+	'r':  true,
+	's':  true,
+	't':  true,
+	'u':  true,
+	'v':  true,
+	'w':  true,
+	'x':  true,
+	'y':  true,
+	'z':  true,
+	'|':  true,
+	'~':  true,
 }
 
-func isCtl(c byte) bool { return (0 <= c && c <= 31) || c == 127 }
-
-func isChar(c byte) bool { return 0 <= c && c <= 127 }
-
-func isAnyText(c byte) bool { return !isCtl(c) }
-
-func isQdText(c byte) bool { return isAnyText(c) && c != '"' }
-
-func isToken(c byte) bool { return isChar(c) && !isCtl(c) && !isSeparator(c) }
-
-// Valid escaped sequences are not specified in RFC 2616, so for now, we assume
-// that they coincide with the common sense ones used by GO. Malformed
-// characters should probably not be treated as errors by a robust (forgiving)
-// parser, so we replace them with the '?' character.
-func httpUnquotePair(b byte) byte {
-	// skip the first byte, which should always be '\'
-	switch b {
-	case 'a':
-		return '\a'
-	case 'b':
-		return '\b'
-	case 'f':
-		return '\f'
-	case 'n':
-		return '\n'
-	case 'r':
-		return '\r'
-	case 't':
-		return '\t'
-	case 'v':
-		return '\v'
-	case '\\':
-		return '\\'
-	case '\'':
-		return '\''
-	case '"':
-		return '"'
-	}
-	return '?'
-}
-
-// raw must begin with a valid quoted string. Only the first quoted string is
-// parsed and is unquoted in result. eaten is the number of bytes parsed, or -1
-// upon failure.
-func httpUnquote(raw []byte) (eaten int, result string) {
-	buf := make([]byte, len(raw))
-	if raw[0] != '"' {
-		return -1, ""
-	}
-	eaten = 1
-	j := 0 // # of bytes written in buf
-	for i := 1; i < len(raw); i++ {
-		switch b := raw[i]; b {
-		case '"':
-			eaten++
-			buf = buf[0:j]
-			return i + 1, string(buf)
-		case '\\':
-			if len(raw) < i+2 {
-				return -1, ""
-			}
-			buf[j] = httpUnquotePair(raw[i+1])
-			eaten += 2
-			j++
-			i++
-		default:
-			if isQdText(b) {
-				buf[j] = b
-			} else {
-				buf[j] = '?'
-			}
-			eaten++
-			j++
-		}
-	}
-	return -1, ""
+func isToken(r rune) bool {
+	i := int(r)
+	return i < len(isTokenTable) && isTokenTable[i]
 }
 
-// This is a best effort parse, so errors are not returned, instead not all of
-// the input string might be parsed. result is always non-nil.
-func httpSplitFieldValue(fv string) (eaten int, result []string) {
-	result = make([]string, 0, len(fv))
-	raw := []byte(fv)
-	i := 0
-	chunk := ""
-	for i < len(raw) {
-		b := raw[i]
-		switch {
-		case b == '"':
-			eaten, unq := httpUnquote(raw[i:len(raw)])
-			if eaten < 0 {
-				return i, result
-			} else {
-				i += eaten
-				chunk += unq
-			}
-		case isSeparator(b):
-			if chunk != "" {
-				result = result[0 : len(result)+1]
-				result[len(result)-1] = chunk
-				chunk = ""
-			}
-			i++
-		case isToken(b):
-			chunk += string(b)
-			i++
-		case b == '\n' || b == '\r':
-			i++
-		default:
-			chunk += "?"
-			i++
-		}
-	}
-	if chunk != "" {
-		result = result[0 : len(result)+1]
-		result[len(result)-1] = chunk
-		chunk = ""
-	}
-	return i, result
+func isNotToken(r rune) bool {
+	return !isToken(r)
 }
diff --git a/src/pkg/net/http/lex_test.go b/src/pkg/net/http/lex_test.go
index 5386f75..6d9d294 100644
--- a/src/pkg/net/http/lex_test.go
+++ b/src/pkg/net/http/lex_test.go
@@ -8,63 +8,24 @@ import (
 	"testing"
 )
 
-type lexTest struct {
-	Raw    string
-	Parsed int // # of parsed characters
-	Result []string
-}
+func isChar(c rune) bool { return c <= 127 }
 
-var lexTests = []lexTest{
-	{
-		Raw:    `"abc"def,:ghi`,
-		Parsed: 13,
-		Result: []string{"abcdef", "ghi"},
-	},
-	// My understanding of the RFC is that escape sequences outside of
-	// quotes are not interpreted?
-	{
-		Raw:    `"\t"\t"\t"`,
-		Parsed: 10,
-		Result: []string{"\t", "t\t"},
-	},
-	{
-		Raw:    `"\yab"\r\n`,
-		Parsed: 10,
-		Result: []string{"?ab", "r", "n"},
-	},
-	{
-		Raw:    "ab\f",
-		Parsed: 3,
-		Result: []string{"ab?"},
-	},
-	{
-		Raw:    "\"ab \" c,de f, gh, ij\n\t\r",
-		Parsed: 23,
-		Result: []string{"ab ", "c", "de", "f", "gh", "ij"},
-	},
-}
+func isCtl(c rune) bool { return c <= 31 || c == 127 }
 
-func min(x, y int) int {
-	if x <= y {
-		return x
+func isSeparator(c rune) bool {
+	switch c {
+	case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
+		return true
 	}
-	return y
+	return false
 }
 
-func TestSplitFieldValue(t *testing.T) {
-	for k, l := range lexTests {
-		parsed, result := httpSplitFieldValue(l.Raw)
-		if parsed != l.Parsed {
-			t.Errorf("#%d: Parsed %d, expected %d", k, parsed, l.Parsed)
-		}
-		if len(result) != len(l.Result) {
-			t.Errorf("#%d: Result len  %d, expected %d", k, len(result), len(l.Result))
-		}
-		for i := 0; i < min(len(result), len(l.Result)); i++ {
-			if result[i] != l.Result[i] {
-				t.Errorf("#%d: %d-th entry mismatch. Have {%s}, expect {%s}",
-					k, i, result[i], l.Result[i])
-			}
+func TestIsToken(t *testing.T) {
+	for i := 0; i <= 130; i++ {
+		r := rune(i)
+		expected := isChar(r) && !isCtl(r) && !isSeparator(r)
+		if isToken(r) != expected {
+			t.Errorf("isToken(0x%x) = %v", r, !expected)
 		}
 	}
 }
diff --git a/src/pkg/net/http/npn_test.go b/src/pkg/net/http/npn_test.go
new file mode 100644
index 0000000..98b8930
--- /dev/null
+++ b/src/pkg/net/http/npn_test.go
@@ -0,0 +1,118 @@
+// 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 http_test
+
+import (
+	"bufio"
+	"crypto/tls"
+	"fmt"
+	"io"
+	"io/ioutil"
+	. "net/http"
+	"net/http/httptest"
+	"strings"
+	"testing"
+)
+
+func TestNextProtoUpgrade(t *testing.T) {
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "path=%s,proto=", r.URL.Path)
+		if r.TLS != nil {
+			w.Write([]byte(r.TLS.NegotiatedProtocol))
+		}
+		if r.RemoteAddr == "" {
+			t.Error("request with no RemoteAddr")
+		}
+		if r.Body == nil {
+			t.Errorf("request with nil Body")
+		}
+	}))
+	ts.TLS = &tls.Config{
+		NextProtos: []string{"unhandled-proto", "tls-0.9"},
+	}
+	ts.Config.TLSNextProto = map[string]func(*Server, *tls.Conn, Handler){
+		"tls-0.9": handleTLSProtocol09,
+	}
+	ts.StartTLS()
+	defer ts.Close()
+
+	tr := newTLSTransport(t, ts)
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	// Normal request, without NPN.
+	{
+		res, err := c.Get(ts.URL)
+		if err != nil {
+			t.Fatal(err)
+		}
+		body, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if want := "path=/,proto="; string(body) != want {
+			t.Errorf("plain request = %q; want %q", body, want)
+		}
+	}
+
+	// Request to an advertised but unhandled NPN protocol.
+	// Server will hang up.
+	{
+		tr.CloseIdleConnections()
+		tr.TLSClientConfig.NextProtos = []string{"unhandled-proto"}
+		_, err := c.Get(ts.URL)
+		if err == nil {
+			t.Errorf("expected error on unhandled-proto request")
+		}
+	}
+
+	// Request using the "tls-0.9" protocol, which we register here.
+	// It is HTTP/0.9 over TLS.
+	{
+		tlsConfig := newTLSTransport(t, ts).TLSClientConfig
+		tlsConfig.NextProtos = []string{"tls-0.9"}
+		conn, err := tls.Dial("tcp", ts.Listener.Addr().String(), tlsConfig)
+		if err != nil {
+			t.Fatal(err)
+		}
+		conn.Write([]byte("GET /foo\n"))
+		body, err := ioutil.ReadAll(conn)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if want := "path=/foo,proto=tls-0.9"; string(body) != want {
+			t.Errorf("plain request = %q; want %q", body, want)
+		}
+	}
+}
+
+// handleTLSProtocol09 implements the HTTP/0.9 protocol over TLS, for the
+// TestNextProtoUpgrade test.
+func handleTLSProtocol09(srv *Server, conn *tls.Conn, h Handler) {
+	br := bufio.NewReader(conn)
+	line, err := br.ReadString('\n')
+	if err != nil {
+		return
+	}
+	line = strings.TrimSpace(line)
+	path := strings.TrimPrefix(line, "GET ")
+	if path == line {
+		return
+	}
+	req, _ := NewRequest("GET", path, nil)
+	req.Proto = "HTTP/0.9"
+	req.ProtoMajor = 0
+	req.ProtoMinor = 9
+	rw := &http09Writer{conn, make(Header)}
+	h.ServeHTTP(rw, req)
+}
+
+type http09Writer struct {
+	io.Writer
+	h Header
+}
+
+func (w http09Writer) Header() Header  { return w.h }
+func (w http09Writer) WriteHeader(int) {} // no headers
diff --git a/src/pkg/net/http/pprof/pprof.go b/src/pkg/net/http/pprof/pprof.go
index 06fcde1..0c7548e 100644
--- a/src/pkg/net/http/pprof/pprof.go
+++ b/src/pkg/net/http/pprof/pprof.go
@@ -14,6 +14,14 @@
 // To use pprof, link this package into your program:
 //	import _ "net/http/pprof"
 //
+// If your application is not already running an http server, you
+// need to start one.  Add "net/http" and "log" to your imports and
+// the following code to your main function:
+//
+// 	go func() {
+// 		log.Println(http.ListenAndServe("localhost:6060", nil))
+// 	}()
+//
 // Then use the pprof tool to look at the heap profile:
 //
 //	go tool pprof http://localhost:6060/debug/pprof/heap
@@ -22,9 +30,12 @@
 //
 //	go tool pprof http://localhost:6060/debug/pprof/profile
 //
-// Or to view all available profiles:
+// Or to look at the goroutine blocking profile:
+//
+//	go tool pprof http://localhost:6060/debug/pprof/block
 //
-//	go tool pprof http://localhost:6060/debug/pprof/
+// To view all available profiles, open http://localhost:6060/debug/pprof/
+// in your browser.
 //
 // For a study of the facility in action, visit
 //
@@ -161,7 +172,7 @@ func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 // listing the available profiles.
 func Index(w http.ResponseWriter, r *http.Request) {
 	if strings.HasPrefix(r.URL.Path, "/debug/pprof/") {
-		name := r.URL.Path[len("/debug/pprof/"):]
+		name := strings.TrimPrefix(r.URL.Path, "/debug/pprof/")
 		if name != "" {
 			handler(name).ServeHTTP(w, r)
 			return
diff --git a/src/pkg/net/http/proxy_test.go b/src/pkg/net/http/proxy_test.go
index 5ecffaf..449ccae 100644
--- a/src/pkg/net/http/proxy_test.go
+++ b/src/pkg/net/http/proxy_test.go
@@ -25,13 +25,13 @@ var UseProxyTests = []struct {
 	{"[::2]", true}, // not a loopback address
 
 	{"barbaz.net", false},     // match as .barbaz.net
-	{"foobar.com", false},     // have a port but match 
+	{"foobar.com", false},     // have a port but match
 	{"foofoobar.com", true},   // not match as a part of foobar.com
 	{"baz.com", true},         // not match as a part of barbaz.com
 	{"localhost.net", true},   // not match as suffix of address
 	{"local.localhost", true}, // not match as prefix as address
 	{"barbarbaz.net", true},   // not match because NO_PROXY have a '.'
-	{"www.foobar.com", true},  // not match because NO_PROXY is not .foobar.com
+	{"www.foobar.com", false}, // match because NO_PROXY includes "foobar.com"
 }
 
 func TestUseProxy(t *testing.T) {
diff --git a/src/pkg/net/http/range_test.go b/src/pkg/net/http/range_test.go
index 5274a81..ef911af 100644
--- a/src/pkg/net/http/range_test.go
+++ b/src/pkg/net/http/range_test.go
@@ -14,15 +14,34 @@ var ParseRangeTests = []struct {
 	r      []httpRange
 }{
 	{"", 0, nil},
+	{"", 1000, nil},
 	{"foo", 0, nil},
 	{"bytes=", 0, nil},
+	{"bytes=7", 10, nil},
+	{"bytes= 7 ", 10, nil},
+	{"bytes=1-", 0, nil},
 	{"bytes=5-4", 10, nil},
 	{"bytes=0-2,5-4", 10, nil},
+	{"bytes=2-5,4-3", 10, nil},
+	{"bytes=--5,4--3", 10, nil},
+	{"bytes=A-", 10, nil},
+	{"bytes=A- ", 10, nil},
+	{"bytes=A-Z", 10, nil},
+	{"bytes= -Z", 10, nil},
+	{"bytes=5-Z", 10, nil},
+	{"bytes=Ran-dom, garbage", 10, nil},
+	{"bytes=0x01-0x02", 10, nil},
+	{"bytes=         ", 10, nil},
+	{"bytes= , , ,   ", 10, nil},
+
 	{"bytes=0-9", 10, []httpRange{{0, 10}}},
 	{"bytes=0-", 10, []httpRange{{0, 10}}},
 	{"bytes=5-", 10, []httpRange{{5, 5}}},
 	{"bytes=0-20", 10, []httpRange{{0, 10}}},
 	{"bytes=15-,0-5", 10, nil},
+	{"bytes=1-2,5-", 10, []httpRange{{1, 2}, {5, 5}}},
+	{"bytes=-2 , 7-", 11, []httpRange{{9, 2}, {7, 4}}},
+	{"bytes=0-0 ,2-2, 7-", 11, []httpRange{{0, 1}, {2, 1}, {7, 4}}},
 	{"bytes=-5", 10, []httpRange{{5, 5}}},
 	{"bytes=-15", 10, []httpRange{{0, 10}}},
 	{"bytes=0-499", 10000, []httpRange{{0, 500}}},
@@ -32,6 +51,9 @@ var ParseRangeTests = []struct {
 	{"bytes=0-0,-1", 10000, []httpRange{{0, 1}, {9999, 1}}},
 	{"bytes=500-600,601-999", 10000, []httpRange{{500, 101}, {601, 399}}},
 	{"bytes=500-700,601-999", 10000, []httpRange{{500, 201}, {601, 399}}},
+
+	// Match Apache laxity:
+	{"bytes=   1 -2   ,  4- 5, 7 - 8 , ,,", 11, []httpRange{{1, 2}, {4, 2}, {7, 2}}},
 }
 
 func TestParseRange(t *testing.T) {
diff --git a/src/pkg/net/http/readrequest_test.go b/src/pkg/net/http/readrequest_test.go
index 2e03c65..ffdd6a8 100644
--- a/src/pkg/net/http/readrequest_test.go
+++ b/src/pkg/net/http/readrequest_test.go
@@ -247,6 +247,54 @@ var reqTests = []reqTest{
 		noTrailer,
 		noError,
 	},
+
+	// SSDP Notify request. golang.org/issue/3692
+	{
+		"NOTIFY * HTTP/1.1\r\nServer: foo\r\n\r\n",
+		&Request{
+			Method: "NOTIFY",
+			URL: &url.URL{
+				Path: "*",
+			},
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"Server": []string{"foo"},
+			},
+			Close:         false,
+			ContentLength: 0,
+			RequestURI:    "*",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// OPTIONS request. Similar to golang.org/issue/3692
+	{
+		"OPTIONS * HTTP/1.1\r\nServer: foo\r\n\r\n",
+		&Request{
+			Method: "OPTIONS",
+			URL: &url.URL{
+				Path: "*",
+			},
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"Server": []string{"foo"},
+			},
+			Close:         false,
+			ContentLength: 0,
+			RequestURI:    "*",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
 }
 
 func TestReadRequest(t *testing.T) {
diff --git a/src/pkg/net/http/request.go b/src/pkg/net/http/request.go
index f5bc6eb..217f35b 100644
--- a/src/pkg/net/http/request.go
+++ b/src/pkg/net/http/request.go
@@ -19,6 +19,7 @@ import (
 	"mime/multipart"
 	"net/textproto"
 	"net/url"
+	"strconv"
 	"strings"
 )
 
@@ -70,7 +71,13 @@ var reqWriteExcludeHeader = map[string]bool{
 // or to be sent by a client.
 type Request struct {
 	Method string // GET, POST, PUT, etc.
-	URL    *url.URL
+
+	// URL is created from the URI supplied on the Request-Line
+	// as stored in RequestURI.
+	//
+	// For most requests, fields other than Path and RawQuery
+	// will be empty. (See RFC 2616, Section 5.1.2)
+	URL *url.URL
 
 	// The protocol version for incoming requests.
 	// Outgoing requests always use HTTP/1.1.
@@ -123,6 +130,7 @@ type Request struct {
 	// The host on which the URL is sought.
 	// Per RFC 2616, this is either the value of the Host: header
 	// or the host name given in the URL itself.
+	// It may be of the form "host:port".
 	Host string
 
 	// Form contains the parsed form data, including both the URL
@@ -131,6 +139,12 @@ type Request struct {
 	// The HTTP client ignores Form and uses Body instead.
 	Form url.Values
 
+	// PostForm contains the parsed form data from POST or PUT
+	// body parameters.
+	// This field is only available after ParseForm is called.
+	// The HTTP client ignores PostForm and uses Body instead.
+	PostForm url.Values
+
 	// MultipartForm is the parsed multipart form, including file uploads.
 	// This field is only available after ParseMultipartForm is called.
 	// The HTTP client ignores MultipartForm and uses Body instead.
@@ -317,11 +331,20 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
 	}
 	// TODO(bradfitz): escape at least newlines in ruri?
 
-	bw := bufio.NewWriter(w)
-	fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), ruri)
+	// Wrap the writer in a bufio Writer if it's not already buffered.
+	// Don't always call NewWriter, as that forces a bytes.Buffer
+	// and other small bufio Writers to have a minimum 4k buffer
+	// size.
+	var bw *bufio.Writer
+	if _, ok := w.(io.ByteWriter); !ok {
+		bw = bufio.NewWriter(w)
+		w = bw
+	}
+
+	fmt.Fprintf(w, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), ruri)
 
 	// Header lines
-	fmt.Fprintf(bw, "Host: %s\r\n", host)
+	fmt.Fprintf(w, "Host: %s\r\n", host)
 
 	// Use the defaultUserAgent unless the Header contains one, which
 	// may be blank to not send the header.
@@ -332,7 +355,7 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
 		}
 	}
 	if userAgent != "" {
-		fmt.Fprintf(bw, "User-Agent: %s\r\n", userAgent)
+		fmt.Fprintf(w, "User-Agent: %s\r\n", userAgent)
 	}
 
 	// Process Body,ContentLength,Close,Trailer
@@ -340,65 +363,61 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
 	if err != nil {
 		return err
 	}
-	err = tw.WriteHeader(bw)
+	err = tw.WriteHeader(w)
 	if err != nil {
 		return err
 	}
 
 	// TODO: split long values?  (If so, should share code with Conn.Write)
-	err = req.Header.WriteSubset(bw, reqWriteExcludeHeader)
+	err = req.Header.WriteSubset(w, reqWriteExcludeHeader)
 	if err != nil {
 		return err
 	}
 
 	if extraHeaders != nil {
-		err = extraHeaders.Write(bw)
+		err = extraHeaders.Write(w)
 		if err != nil {
 			return err
 		}
 	}
 
-	io.WriteString(bw, "\r\n")
+	io.WriteString(w, "\r\n")
 
 	// Write body and trailer
-	err = tw.WriteBody(bw)
+	err = tw.WriteBody(w)
 	if err != nil {
 		return err
 	}
 
-	return bw.Flush()
-}
-
-// Convert decimal at s[i:len(s)] to integer,
-// returning value, string position where the digits stopped,
-// and whether there was a valid number (digits, not too big).
-func atoi(s string, i int) (n, i1 int, ok bool) {
-	const Big = 1000000
-	if i >= len(s) || s[i] < '0' || s[i] > '9' {
-		return 0, 0, false
-	}
-	n = 0
-	for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
-		n = n*10 + int(s[i]-'0')
-		if n > Big {
-			return 0, 0, false
-		}
+	if bw != nil {
+		return bw.Flush()
 	}
-	return n, i, true
+	return nil
 }
 
 // ParseHTTPVersion parses a HTTP version string.
 // "HTTP/1.0" returns (1, 0, true).
 func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
-	if len(vers) < 5 || vers[0:5] != "HTTP/" {
+	const Big = 1000000 // arbitrary upper bound
+	switch vers {
+	case "HTTP/1.1":
+		return 1, 1, true
+	case "HTTP/1.0":
+		return 1, 0, true
+	}
+	if !strings.HasPrefix(vers, "HTTP/") {
 		return 0, 0, false
 	}
-	major, i, ok := atoi(vers, 5)
-	if !ok || i >= len(vers) || vers[i] != '.' {
+	dot := strings.Index(vers, ".")
+	if dot < 0 {
 		return 0, 0, false
 	}
-	minor, i, ok = atoi(vers, i+1)
-	if !ok || i != len(vers) {
+	major, err := strconv.Atoi(vers[5:dot])
+	if err != nil || major < 0 || major > Big {
+		return 0, 0, false
+	}
+	minor, err = strconv.Atoi(vers[dot+1:])
+	if err != nil || minor < 0 || minor > Big {
 		return 0, 0, false
 	}
 	return major, minor, true
@@ -426,10 +445,12 @@ func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
 	}
 	if body != nil {
 		switch v := body.(type) {
-		case *strings.Reader:
-			req.ContentLength = int64(v.Len())
 		case *bytes.Buffer:
 			req.ContentLength = int64(v.Len())
+		case *bytes.Reader:
+			req.ContentLength = int64(v.Len())
+		case *strings.Reader:
+			req.ContentLength = int64(v.Len())
 		}
 	}
 
@@ -513,9 +534,9 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) {
 	// the same.  In the second case, any Host line is ignored.
 	req.Host = req.URL.Host
 	if req.Host == "" {
-		req.Host = req.Header.Get("Host")
+		req.Host = req.Header.get("Host")
 	}
-	req.Header.Del("Host")
+	delete(req.Header, "Host")
 
 	fixPragmaCacheControl(req.Header)
 
@@ -594,66 +615,97 @@ func (l *maxBytesReader) Close() error {
 	return l.r.Close()
 }
 
-// ParseForm parses the raw query from the URL.
+func copyValues(dst, src url.Values) {
+	for k, vs := range src {
+		for _, value := range vs {
+			dst.Add(k, value)
+		}
+	}
+}
+
+func parsePostForm(r *Request) (vs url.Values, err error) {
+	if r.Body == nil {
+		err = errors.New("missing form body")
+		return
+	}
+	ct := r.Header.Get("Content-Type")
+	ct, _, err = mime.ParseMediaType(ct)
+	switch {
+	case ct == "application/x-www-form-urlencoded":
+		var reader io.Reader = r.Body
+		maxFormSize := int64(1<<63 - 1)
+		if _, ok := r.Body.(*maxBytesReader); !ok {
+			maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
+			reader = io.LimitReader(r.Body, maxFormSize+1)
+		}
+		b, e := ioutil.ReadAll(reader)
+		if e != nil {
+			if err == nil {
+				err = e
+			}
+			break
+		}
+		if int64(len(b)) > maxFormSize {
+			err = errors.New("http: POST too large")
+			return
+		}
+		vs, e = url.ParseQuery(string(b))
+		if err == nil {
+			err = e
+		}
+	case ct == "multipart/form-data":
+		// handled by ParseMultipartForm (which is calling us, or should be)
+		// TODO(bradfitz): there are too many possible
+		// orders to call too many functions here.
+		// Clean this up and write more tests.
+		// request_test.go contains the start of this,
+		// in TestRequestMultipartCallOrder.
+	}
+	return
+}
+
+// ParseForm parses the raw query from the URL and updates r.Form.
+//
+// For POST or PUT requests, it also parses the request body as a form and
+// put the results into both r.PostForm and r.Form.
+// POST and PUT body parameters take precedence over URL query string values
+// in r.Form.
 //
-// For POST or PUT requests, it also parses the request body as a form.
 // If the request Body's size has not already been limited by MaxBytesReader,
 // the size is capped at 10MB.
 //
 // ParseMultipartForm calls ParseForm automatically.
 // It is idempotent.
-func (r *Request) ParseForm() (err error) {
-	if r.Form != nil {
-		return
-	}
-	if r.URL != nil {
-		r.Form, err = url.ParseQuery(r.URL.RawQuery)
+func (r *Request) ParseForm() error {
+	var err error
+	if r.PostForm == nil {
+		if r.Method == "POST" || r.Method == "PUT" {
+			r.PostForm, err = parsePostForm(r)
+		}
+		if r.PostForm == nil {
+			r.PostForm = make(url.Values)
+		}
 	}
-	if r.Method == "POST" || r.Method == "PUT" {
-		if r.Body == nil {
-			return errors.New("missing form body")
+	if r.Form == nil {
+		if len(r.PostForm) > 0 {
+			r.Form = make(url.Values)
+			copyValues(r.Form, r.PostForm)
 		}
-		ct := r.Header.Get("Content-Type")
-		ct, _, err = mime.ParseMediaType(ct)
-		switch {
-		case ct == "application/x-www-form-urlencoded":
-			var reader io.Reader = r.Body
-			maxFormSize := int64(1<<63 - 1)
-			if _, ok := r.Body.(*maxBytesReader); !ok {
-				maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
-				reader = io.LimitReader(r.Body, maxFormSize+1)
-			}
-			b, e := ioutil.ReadAll(reader)
-			if e != nil {
-				if err == nil {
-					err = e
-				}
-				break
-			}
-			if int64(len(b)) > maxFormSize {
-				return errors.New("http: POST too large")
-			}
-			var newValues url.Values
-			newValues, e = url.ParseQuery(string(b))
+		var newValues url.Values
+		if r.URL != nil {
+			var e error
+			newValues, e = url.ParseQuery(r.URL.RawQuery)
 			if err == nil {
 				err = e
 			}
-			if r.Form == nil {
-				r.Form = make(url.Values)
-			}
-			// Copy values into r.Form. TODO: make this smoother.
-			for k, vs := range newValues {
-				for _, value := range vs {
-					r.Form.Add(k, value)
-				}
-			}
-		case ct == "multipart/form-data":
-			// handled by ParseMultipartForm (which is calling us, or should be)
-			// TODO(bradfitz): there are too many possible
-			// orders to call too many functions here.
-			// Clean this up and write more tests.
-			// request_test.go contains the start of this,
-			// in TestRequestMultipartCallOrder.
+		}
+		if newValues == nil {
+			newValues = make(url.Values)
+		}
+		if r.Form == nil {
+			r.Form = newValues
+		} else {
+			copyValues(r.Form, newValues)
 		}
 	}
 	return err
@@ -699,7 +751,9 @@ 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.
 func (r *Request) FormValue(key string) string {
 	if r.Form == nil {
 		r.ParseMultipartForm(defaultMaxMemory)
@@ -710,6 +764,19 @@ func (r *Request) FormValue(key string) string {
 	return ""
 }
 
+// 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.
+func (r *Request) PostFormValue(key string) string {
+	if r.PostForm == nil {
+		r.ParseMultipartForm(defaultMaxMemory)
+	}
+	if vs := r.PostForm[key]; len(vs) > 0 {
+		return vs[0]
+	}
+	return ""
+}
+
 // FormFile returns the first file for the provided form key.
 // FormFile calls ParseMultipartForm and ParseForm if necessary.
 func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error) {
@@ -732,12 +799,16 @@ func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, e
 }
 
 func (r *Request) expectsContinue() bool {
-	return strings.ToLower(r.Header.Get("Expect")) == "100-continue"
+	return hasToken(r.Header.get("Expect"), "100-continue")
 }
 
 func (r *Request) wantsHttp10KeepAlive() bool {
 	if r.ProtoMajor != 1 || r.ProtoMinor != 0 {
 		return false
 	}
-	return strings.Contains(strings.ToLower(r.Header.Get("Connection")), "keep-alive")
+	return hasToken(r.Header.get("Connection"), "keep-alive")
+}
+
+func (r *Request) wantsClose() bool {
+	return hasToken(r.Header.get("Connection"), "close")
 }
diff --git a/src/pkg/net/http/request_test.go b/src/pkg/net/http/request_test.go
index 6e00b9b..00ad791 100644
--- a/src/pkg/net/http/request_test.go
+++ b/src/pkg/net/http/request_test.go
@@ -30,8 +30,8 @@ func TestQuery(t *testing.T) {
 }
 
 func TestPostQuery(t *testing.T) {
-	req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x",
-		strings.NewReader("z=post&both=y"))
+	req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&empty=not",
+		strings.NewReader("z=post&both=y&prio=2&empty="))
 	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
 
 	if q := req.FormValue("q"); q != "foo" {
@@ -40,8 +40,23 @@ func TestPostQuery(t *testing.T) {
 	if z := req.FormValue("z"); z != "post" {
 		t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
 	}
-	if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"x", "y"}) {
-		t.Errorf(`req.FormValue("both") = %q, want ["x", "y"]`, both)
+	if bq, found := req.PostForm["q"]; found {
+		t.Errorf(`req.PostForm["q"] = %q, want no entry in map`, bq)
+	}
+	if bz := req.PostFormValue("z"); bz != "post" {
+		t.Errorf(`req.PostFormValue("z") = %q, want "post"`, bz)
+	}
+	if qs := req.Form["q"]; !reflect.DeepEqual(qs, []string{"foo", "bar"}) {
+		t.Errorf(`req.Form["q"] = %q, want ["foo", "bar"]`, qs)
+	}
+	if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"y", "x"}) {
+		t.Errorf(`req.Form["both"] = %q, want ["y", "x"]`, both)
+	}
+	if prio := req.FormValue("prio"); prio != "2" {
+		t.Errorf(`req.FormValue("prio") = %q, want "2" (from body)`, prio)
+	}
+	if empty := req.FormValue("empty"); empty != "" {
+		t.Errorf(`req.FormValue("empty") = %q, want "" (from body)`, empty)
 	}
 }
 
@@ -76,6 +91,23 @@ func TestParseFormUnknownContentType(t *testing.T) {
 	}
 }
 
+func TestParseFormInitializeOnError(t *testing.T) {
+	nilBody, _ := NewRequest("POST", "http://www.google.com/search?q=foo", nil)
+	tests := []*Request{
+		nilBody,
+		{Method: "GET", URL: nil},
+	}
+	for i, req := range tests {
+		err := req.ParseForm()
+		if req.Form == nil {
+			t.Errorf("%d. Form not initialized, error %v", i, err)
+		}
+		if req.PostForm == nil {
+			t.Errorf("%d. PostForm not initialized, error %v", i, err)
+		}
+	}
+}
+
 func TestMultipartReader(t *testing.T) {
 	req := &Request{
 		Method: "POST",
@@ -129,7 +161,7 @@ func TestSetBasicAuth(t *testing.T) {
 }
 
 func TestMultipartRequest(t *testing.T) {
-	// Test that we can read the values and files of a 
+	// Test that we can read the values and files of a
 	// multipart request with FormValue and FormFile,
 	// and that ParseMultipartForm can be called multiple times.
 	req := newTestMultipartRequest(t)
@@ -196,6 +228,75 @@ func TestReadRequestErrors(t *testing.T) {
 	}
 }
 
+func TestNewRequestHost(t *testing.T) {
+	req, err := NewRequest("GET", "http://localhost:1234/", nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if req.Host != "localhost:1234" {
+		t.Errorf("Host = %q; want localhost:1234", req.Host)
+	}
+}
+
+func TestNewRequestContentLength(t *testing.T) {
+	readByte := func(r io.Reader) io.Reader {
+		var b [1]byte
+		r.Read(b[:])
+		return r
+	}
+	tests := []struct {
+		r    io.Reader
+		want int64
+	}{
+		{bytes.NewReader([]byte("123")), 3},
+		{bytes.NewBuffer([]byte("1234")), 4},
+		{strings.NewReader("12345"), 5},
+		// Not detected:
+		{struct{ io.Reader }{strings.NewReader("xyz")}, 0},
+		{io.NewSectionReader(strings.NewReader("x"), 0, 6), 0},
+		{readByte(io.NewSectionReader(strings.NewReader("xy"), 0, 6)), 0},
+	}
+	for _, tt := range tests {
+		req, err := NewRequest("POST", "http://localhost/", tt.r)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if req.ContentLength != tt.want {
+			t.Errorf("ContentLength(%T) = %d; want %d", tt.r, req.ContentLength, tt.want)
+		}
+	}
+}
+
+type logWrites struct {
+	t   *testing.T
+	dst *[]string
+}
+
+func (l logWrites) WriteByte(c byte) error {
+	l.t.Fatalf("unexpected WriteByte call")
+	return nil
+}
+
+func (l logWrites) Write(p []byte) (n int, err error) {
+	*l.dst = append(*l.dst, string(p))
+	return len(p), nil
+}
+
+func TestRequestWriteBufferedWriter(t *testing.T) {
+	got := []string{}
+	req, _ := NewRequest("GET", "http://foo.com/", nil)
+	req.Write(logWrites{t, &got})
+	want := []string{
+		"GET / HTTP/1.1\r\n",
+		"Host: foo.com\r\n",
+		"User-Agent: Go http package\r\n",
+		"\r\n",
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Writes = %q\n  Want = %q", got, want)
+	}
+}
+
 func testMissingFile(t *testing.T, req *Request) {
 	f, fh, err := req.FormFile("missing")
 	if f != nil {
@@ -300,3 +401,81 @@ Content-Disposition: form-data; name="textb"
 ` + textbValue + `
 --MyBoundary--
 `
+
+func benchmarkReadRequest(b *testing.B, request string) {
+	request = request + "\n"                             // final \n
+	request = strings.Replace(request, "\n", "\r\n", -1) // expand \n to \r\n
+	b.SetBytes(int64(len(request)))
+	r := bufio.NewReader(&infiniteReader{buf: []byte(request)})
+	b.ReportAllocs()
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, err := ReadRequest(r)
+		if err != nil {
+			b.Fatalf("failed to read request: %v", err)
+		}
+	}
+}
+
+// infiniteReader satisfies Read requests as if the contents of buf
+// loop indefinitely.
+type infiniteReader struct {
+	buf    []byte
+	offset int
+}
+
+func (r *infiniteReader) Read(b []byte) (int, error) {
+	n := copy(b, r.buf[r.offset:])
+	r.offset = (r.offset + n) % len(r.buf)
+	return n, nil
+}
+
+func BenchmarkReadRequestChrome(b *testing.B) {
+	// https://github.com/felixge/node-http-perf/blob/master/fixtures/get.http
+	benchmarkReadRequest(b, `GET / HTTP/1.1
+Host: localhost:8080
+Connection: keep-alive
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
+Accept-Encoding: gzip,deflate,sdch
+Accept-Language: en-US,en;q=0.8
+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
+Cookie: __utma=1.1978842379.1323102373.1323102373.1323102373.1; EPi:NumberOfVisits=1,2012-02-28T13:42:18; CrmSession=5b707226b9563e1bc69084d07a107c98; plushContainerWidth=100%25; plushNoTopMenu=0; hudson_auto_refresh=false
+`)
+}
+
+func BenchmarkReadRequestCurl(b *testing.B) {
+	// curl http://localhost:8080/
+	benchmarkReadRequest(b, `GET / HTTP/1.1
+User-Agent: curl/7.27.0
+Host: localhost:8080
+Accept: */*
+`)
+}
+
+func BenchmarkReadRequestApachebench(b *testing.B) {
+	// ab -n 1 -c 1 http://localhost:8080/
+	benchmarkReadRequest(b, `GET / HTTP/1.0
+Host: localhost:8080
+User-Agent: ApacheBench/2.3
+Accept: */*
+`)
+}
+
+func BenchmarkReadRequestSiege(b *testing.B) {
+	// siege -r 1 -c 1 http://localhost:8080/
+	benchmarkReadRequest(b, `GET / HTTP/1.1
+Host: localhost:8080
+Accept: */*
+Accept-Encoding: gzip
+User-Agent: JoeDog/1.00 [en] (X11; I; Siege 2.70)
+Connection: keep-alive
+`)
+}
+
+func BenchmarkReadRequestWrk(b *testing.B) {
+	// wrk -t 1 -r 1 -c 1 http://localhost:8080/
+	benchmarkReadRequest(b, `GET / HTTP/1.1
+Host: localhost:8080
+`)
+}
diff --git a/src/pkg/net/http/requestwrite_test.go b/src/pkg/net/http/requestwrite_test.go
index fc3186f..bc637f1 100644
--- a/src/pkg/net/http/requestwrite_test.go
+++ b/src/pkg/net/http/requestwrite_test.go
@@ -328,6 +328,69 @@ var reqWriteTests = []reqWriteTest{
 			"User-Agent: Go http package\r\n" +
 			"X-Foo: X-Bar\r\n\r\n",
 	},
+
+	// If no Request.Host and no Request.URL.Host, we send
+	// an empty Host header, and don't use
+	// Request.Header["Host"]. This is just testing that
+	// we don't change Go 1.0 behavior.
+	{
+		Req: Request{
+			Method: "GET",
+			Host:   "",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "",
+				Path:   "/search",
+			},
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"Host": []string{"bad.example.com"},
+			},
+		},
+
+		WantWrite: "GET /search HTTP/1.1\r\n" +
+			"Host: \r\n" +
+			"User-Agent: Go http package\r\n\r\n",
+	},
+
+	// Opaque test #1 from golang.org/issue/4860
+	{
+		Req: Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Opaque: "/%2F/%2F/",
+			},
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header:     Header{},
+		},
+
+		WantWrite: "GET /%2F/%2F/ HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go http package\r\n\r\n",
+	},
+
+	// Opaque test #2 from golang.org/issue/4860
+	{
+		Req: Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "x.google.com",
+				Opaque: "//y.google.com/%2F/%2F/",
+			},
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header:     Header{},
+		},
+
+		WantWrite: "GET http://y.google.com/%2F/%2F/ HTTP/1.1\r\n" +
+			"Host: x.google.com\r\n" +
+			"User-Agent: Go http package\r\n\r\n",
+	},
 }
 
 func TestRequestWrite(t *testing.T) {
diff --git a/src/pkg/net/http/response.go b/src/pkg/net/http/response.go
index 945ecd8..391ebbf 100644
--- a/src/pkg/net/http/response.go
+++ b/src/pkg/net/http/response.go
@@ -49,7 +49,7 @@ type Response struct {
 	Body io.ReadCloser
 
 	// ContentLength records the length of the associated content.  The
-	// value -1 indicates that the length is unknown.  Unless RequestMethod
+	// value -1 indicates that the length is unknown.  Unless Request.Method
 	// is "HEAD", values >= 0 indicate that the given number of bytes may
 	// be read from Body.
 	ContentLength int64
@@ -107,7 +107,6 @@ func ReadResponse(r *bufio.Reader, req *Request) (resp *Response, err error) {
 	resp = new(Response)
 
 	resp.Request = req
-	resp.Request.Method = strings.ToUpper(resp.Request.Method)
 
 	// Parse the first line of the response.
 	line, err := tp.ReadLine()
@@ -179,7 +178,7 @@ func (r *Response) ProtoAtLeast(major, minor int) bool {
 //  StatusCode
 //  ProtoMajor
 //  ProtoMinor
-//  RequestMethod
+//  Request.Method
 //  TransferEncoding
 //  Trailer
 //  Body
@@ -188,11 +187,6 @@ func (r *Response) ProtoAtLeast(major, minor int) bool {
 //
 func (r *Response) Write(w io.Writer) error {
 
-	// RequestMethod should be upper-case
-	if r.Request != nil {
-		r.Request.Method = strings.ToUpper(r.Request.Method)
-	}
-
 	// Status line
 	text := r.Status
 	if text == "" {
@@ -204,9 +198,7 @@ func (r *Response) Write(w io.Writer) error {
 	}
 	protoMajor, protoMinor := strconv.Itoa(r.ProtoMajor), strconv.Itoa(r.ProtoMinor)
 	statusCode := strconv.Itoa(r.StatusCode) + " "
-	if strings.HasPrefix(text, statusCode) {
-		text = text[len(statusCode):]
-	}
+	text = strings.TrimPrefix(text, statusCode)
 	io.WriteString(w, "HTTP/"+protoMajor+"."+protoMinor+" "+statusCode+text+"\r\n")
 
 	// Process Body,ContentLength,Close,Trailer
diff --git a/src/pkg/net/http/response_test.go b/src/pkg/net/http/response_test.go
index 6eed488..2f5f773 100644
--- a/src/pkg/net/http/response_test.go
+++ b/src/pkg/net/http/response_test.go
@@ -124,7 +124,7 @@ var respTests = []respTest{
 
 	// Chunked response without Content-Length.
 	{
-		"HTTP/1.0 200 OK\r\n" +
+		"HTTP/1.1 200 OK\r\n" +
 			"Transfer-Encoding: chunked\r\n" +
 			"\r\n" +
 			"0a\r\n" +
@@ -137,12 +137,12 @@ var respTests = []respTest{
 		Response{
 			Status:           "200 OK",
 			StatusCode:       200,
-			Proto:            "HTTP/1.0",
+			Proto:            "HTTP/1.1",
 			ProtoMajor:       1,
-			ProtoMinor:       0,
+			ProtoMinor:       1,
 			Request:          dummyReq("GET"),
 			Header:           Header{},
-			Close:            true,
+			Close:            false,
 			ContentLength:    -1,
 			TransferEncoding: []string{"chunked"},
 		},
@@ -152,24 +152,24 @@ var respTests = []respTest{
 
 	// Chunked response with Content-Length.
 	{
-		"HTTP/1.0 200 OK\r\n" +
+		"HTTP/1.1 200 OK\r\n" +
 			"Transfer-Encoding: chunked\r\n" +
 			"Content-Length: 10\r\n" +
 			"\r\n" +
 			"0a\r\n" +
-			"Body here\n" +
+			"Body here\n\r\n" +
 			"0\r\n" +
 			"\r\n",
 
 		Response{
 			Status:           "200 OK",
 			StatusCode:       200,
-			Proto:            "HTTP/1.0",
+			Proto:            "HTTP/1.1",
 			ProtoMajor:       1,
-			ProtoMinor:       0,
+			ProtoMinor:       1,
 			Request:          dummyReq("GET"),
 			Header:           Header{},
-			Close:            true,
+			Close:            false,
 			ContentLength:    -1, // TODO(rsc): Fix?
 			TransferEncoding: []string{"chunked"},
 		},
@@ -177,23 +177,88 @@ var respTests = []respTest{
 		"Body here\n",
 	},
 
-	// Chunked response in response to a HEAD request (the "chunked" should
-	// be ignored, as HEAD responses never have bodies)
+	// Chunked response in response to a HEAD request
 	{
-		"HTTP/1.0 200 OK\r\n" +
+		"HTTP/1.1 200 OK\r\n" +
 			"Transfer-Encoding: chunked\r\n" +
 			"\r\n",
 
 		Response{
-			Status:        "200 OK",
-			StatusCode:    200,
-			Proto:         "HTTP/1.0",
-			ProtoMajor:    1,
-			ProtoMinor:    0,
-			Request:       dummyReq("HEAD"),
-			Header:        Header{},
-			Close:         true,
-			ContentLength: 0,
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.1",
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Request:          dummyReq("HEAD"),
+			Header:           Header{},
+			TransferEncoding: []string{"chunked"},
+			Close:            false,
+			ContentLength:    -1,
+		},
+
+		"",
+	},
+
+	// Content-Length in response to a HEAD request
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Content-Length: 256\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.0",
+			ProtoMajor:       1,
+			ProtoMinor:       0,
+			Request:          dummyReq("HEAD"),
+			Header:           Header{"Content-Length": {"256"}},
+			TransferEncoding: nil,
+			Close:            true,
+			ContentLength:    256,
+		},
+
+		"",
+	},
+
+	// Content-Length in response to a HEAD request with HTTP/1.1
+	{
+		"HTTP/1.1 200 OK\r\n" +
+			"Content-Length: 256\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.1",
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Request:          dummyReq("HEAD"),
+			Header:           Header{"Content-Length": {"256"}},
+			TransferEncoding: nil,
+			Close:            false,
+			ContentLength:    256,
+		},
+
+		"",
+	},
+
+	// No Content-Length or Chunked in response to a HEAD request
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.0",
+			ProtoMajor:       1,
+			ProtoMinor:       0,
+			Request:          dummyReq("HEAD"),
+			Header:           Header{},
+			TransferEncoding: nil,
+			Close:            true,
+			ContentLength:    -1,
 		},
 
 		"",
@@ -259,16 +324,37 @@ var respTests = []respTest{
 
 		"",
 	},
+
+	// golang.org/issue/4767: don't special-case multipart/byteranges responses
+	{
+		`HTTP/1.1 206 Partial Content
+Connection: close
+Content-Type: multipart/byteranges; boundary=18a75608c8f47cef
+
+some body`,
+		Response{
+			Status:     "206 Partial Content",
+			StatusCode: 206,
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Request:    dummyReq("GET"),
+			Header: Header{
+				"Content-Type": []string{"multipart/byteranges; boundary=18a75608c8f47cef"},
+			},
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"some body",
+	},
 }
 
 func TestReadResponse(t *testing.T) {
-	for i := range respTests {
-		tt := &respTests[i]
-		var braw bytes.Buffer
-		braw.WriteString(tt.Raw)
-		resp, err := ReadResponse(bufio.NewReader(&braw), tt.Resp.Request)
+	for i, tt := range respTests {
+		resp, err := ReadResponse(bufio.NewReader(strings.NewReader(tt.Raw)), tt.Resp.Request)
 		if err != nil {
-			t.Errorf("#%d: %s", i, err)
+			t.Errorf("#%d: %v", i, err)
 			continue
 		}
 		rbody := resp.Body
@@ -276,7 +362,11 @@ func TestReadResponse(t *testing.T) {
 		diff(t, fmt.Sprintf("#%d Response", i), resp, &tt.Resp)
 		var bout bytes.Buffer
 		if rbody != nil {
-			io.Copy(&bout, rbody)
+			_, err = io.Copy(&bout, rbody)
+			if err != nil {
+				t.Errorf("#%d: %v", i, err)
+				continue
+			}
 			rbody.Close()
 		}
 		body := bout.String()
@@ -286,6 +376,22 @@ func TestReadResponse(t *testing.T) {
 	}
 }
 
+func TestWriteResponse(t *testing.T) {
+	for i, tt := range respTests {
+		resp, err := ReadResponse(bufio.NewReader(strings.NewReader(tt.Raw)), tt.Resp.Request)
+		if err != nil {
+			t.Errorf("#%d: %v", i, err)
+			continue
+		}
+		bout := bytes.NewBuffer(nil)
+		err = resp.Write(bout)
+		if err != nil {
+			t.Errorf("#%d: %v", i, err)
+			continue
+		}
+	}
+}
+
 var readResponseCloseInMiddleTests = []struct {
 	chunked, compressed bool
 }{
diff --git a/src/pkg/net/http/responsewrite_test.go b/src/pkg/net/http/responsewrite_test.go
index f8e63ac..5c10e21 100644
--- a/src/pkg/net/http/responsewrite_test.go
+++ b/src/pkg/net/http/responsewrite_test.go
@@ -15,83 +15,83 @@ type respWriteTest struct {
 	Raw  string
 }
 
-var respWriteTests = []respWriteTest{
-	// HTTP/1.0, identity coding; no trailer
-	{
-		Response{
-			StatusCode:    503,
-			ProtoMajor:    1,
-			ProtoMinor:    0,
-			Request:       dummyReq("GET"),
-			Header:        Header{},
-			Body:          ioutil.NopCloser(bytes.NewBufferString("abcdef")),
-			ContentLength: 6,
-		},
+func TestResponseWrite(t *testing.T) {
+	respWriteTests := []respWriteTest{
+		// HTTP/1.0, identity coding; no trailer
+		{
+			Response{
+				StatusCode:    503,
+				ProtoMajor:    1,
+				ProtoMinor:    0,
+				Request:       dummyReq("GET"),
+				Header:        Header{},
+				Body:          ioutil.NopCloser(bytes.NewBufferString("abcdef")),
+				ContentLength: 6,
+			},
 
-		"HTTP/1.0 503 Service Unavailable\r\n" +
-			"Content-Length: 6\r\n\r\n" +
-			"abcdef",
-	},
-	// Unchunked response without Content-Length.
-	{
-		Response{
-			StatusCode:    200,
-			ProtoMajor:    1,
-			ProtoMinor:    0,
-			Request:       dummyReq("GET"),
-			Header:        Header{},
-			Body:          ioutil.NopCloser(bytes.NewBufferString("abcdef")),
-			ContentLength: -1,
+			"HTTP/1.0 503 Service Unavailable\r\n" +
+				"Content-Length: 6\r\n\r\n" +
+				"abcdef",
 		},
-		"HTTP/1.0 200 OK\r\n" +
-			"\r\n" +
-			"abcdef",
-	},
-	// HTTP/1.1, chunked coding; empty trailer; close
-	{
-		Response{
-			StatusCode:       200,
-			ProtoMajor:       1,
-			ProtoMinor:       1,
-			Request:          dummyReq("GET"),
-			Header:           Header{},
-			Body:             ioutil.NopCloser(bytes.NewBufferString("abcdef")),
-			ContentLength:    6,
-			TransferEncoding: []string{"chunked"},
-			Close:            true,
+		// Unchunked response without Content-Length.
+		{
+			Response{
+				StatusCode:    200,
+				ProtoMajor:    1,
+				ProtoMinor:    0,
+				Request:       dummyReq("GET"),
+				Header:        Header{},
+				Body:          ioutil.NopCloser(bytes.NewBufferString("abcdef")),
+				ContentLength: -1,
+			},
+			"HTTP/1.0 200 OK\r\n" +
+				"\r\n" +
+				"abcdef",
 		},
+		// HTTP/1.1, chunked coding; empty trailer; close
+		{
+			Response{
+				StatusCode:       200,
+				ProtoMajor:       1,
+				ProtoMinor:       1,
+				Request:          dummyReq("GET"),
+				Header:           Header{},
+				Body:             ioutil.NopCloser(bytes.NewBufferString("abcdef")),
+				ContentLength:    6,
+				TransferEncoding: []string{"chunked"},
+				Close:            true,
+			},
 
-		"HTTP/1.1 200 OK\r\n" +
-			"Connection: close\r\n" +
-			"Transfer-Encoding: chunked\r\n\r\n" +
-			"6\r\nabcdef\r\n0\r\n\r\n",
-	},
+			"HTTP/1.1 200 OK\r\n" +
+				"Connection: close\r\n" +
+				"Transfer-Encoding: chunked\r\n\r\n" +
+				"6\r\nabcdef\r\n0\r\n\r\n",
+		},
 
-	// Header value with a newline character (Issue 914).
-	// Also tests removal of leading and trailing whitespace.
-	{
-		Response{
-			StatusCode: 204,
-			ProtoMajor: 1,
-			ProtoMinor: 1,
-			Request:    dummyReq("GET"),
-			Header: Header{
-				"Foo": []string{" Bar\nBaz "},
+		// Header value with a newline character (Issue 914).
+		// Also tests removal of leading and trailing whitespace.
+		{
+			Response{
+				StatusCode: 204,
+				ProtoMajor: 1,
+				ProtoMinor: 1,
+				Request:    dummyReq("GET"),
+				Header: Header{
+					"Foo": []string{" Bar\nBaz "},
+				},
+				Body:             nil,
+				ContentLength:    0,
+				TransferEncoding: []string{"chunked"},
+				Close:            true,
 			},
-			Body:             nil,
-			ContentLength:    0,
-			TransferEncoding: []string{"chunked"},
-			Close:            true,
-		},
 
-		"HTTP/1.1 204 No Content\r\n" +
-			"Connection: close\r\n" +
-			"Foo: Bar Baz\r\n" +
-			"\r\n",
-	},
-}
+			"HTTP/1.1 204 No Content\r\n" +
+				"Connection: close\r\n" +
+				"Foo: Bar Baz\r\n" +
+				"\r\n",
+		},
+	}
 
-func TestResponseWrite(t *testing.T) {
 	for i := range respWriteTests {
 		tt := &respWriteTests[i]
 		var braw bytes.Buffer
diff --git a/src/pkg/net/http/serve_test.go b/src/pkg/net/http/serve_test.go
index b6a6b4c..3300fef 100644
--- a/src/pkg/net/http/serve_test.go
+++ b/src/pkg/net/http/serve_test.go
@@ -20,8 +20,13 @@ import (
 	"net/http/httputil"
 	"net/url"
 	"os"
+	"os/exec"
 	"reflect"
+	"runtime"
+	"strconv"
 	"strings"
+	"sync"
+	"sync/atomic"
 	"syscall"
 	"testing"
 	"time"
@@ -62,6 +67,7 @@ func (a dummyAddr) String() string {
 type testConn struct {
 	readBuf  bytes.Buffer
 	writeBuf bytes.Buffer
+	closec   chan bool // if non-nil, send value to it on close
 }
 
 func (c *testConn) Read(b []byte) (int, error) {
@@ -73,6 +79,10 @@ func (c *testConn) Write(b []byte) (int, error) {
 }
 
 func (c *testConn) Close() error {
+	select {
+	case c.closec <- true:
+	default:
+	}
 	return nil
 }
 
@@ -168,13 +178,18 @@ var vtests = []struct {
 	{"http://someHost.com/someDir/apage", "someHost.com/someDir"},
 	{"http://otherHost.com/someDir/apage", "someDir"},
 	{"http://otherHost.com/aDir/apage", "Default"},
+	// redirections for trees
+	{"http://localhost/someDir", "/someDir/"},
+	{"http://someHost.com/someDir", "/someDir/"},
 }
 
 func TestHostHandlers(t *testing.T) {
+	defer checkLeakedTransports(t)
+	mux := NewServeMux()
 	for _, h := range handlers {
-		Handle(h.pattern, stringHandler(h.msg))
+		mux.Handle(h.pattern, stringHandler(h.msg))
 	}
-	ts := httptest.NewServer(nil)
+	ts := httptest.NewServer(mux)
 	defer ts.Close()
 
 	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
@@ -199,9 +214,19 @@ func TestHostHandlers(t *testing.T) {
 			t.Errorf("reading response: %v", err)
 			continue
 		}
-		s := r.Header.Get("Result")
-		if s != vt.expected {
-			t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
+		switch r.StatusCode {
+		case StatusOK:
+			s := r.Header.Get("Result")
+			if s != vt.expected {
+				t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
+			}
+		case StatusMovedPermanently:
+			s := r.Header.Get("Location")
+			if s != vt.expected {
+				t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
+			}
+		default:
+			t.Errorf("Get(%q) unhandled status code %d", vt.url, r.StatusCode)
 		}
 	}
 }
@@ -232,28 +257,22 @@ func TestMuxRedirectLeadingSlashes(t *testing.T) {
 }
 
 func TestServerTimeouts(t *testing.T) {
-	// TODO(bradfitz): convert this to use httptest.Server
-	l, err := net.Listen("tcp", "127.0.0.1:0")
-	if err != nil {
-		t.Fatalf("listen error: %v", err)
-	}
-	addr, _ := l.Addr().(*net.TCPAddr)
-
+	defer checkLeakedTransports(t)
 	reqNum := 0
-	handler := HandlerFunc(func(res ResponseWriter, req *Request) {
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(res ResponseWriter, req *Request) {
 		reqNum++
 		fmt.Fprintf(res, "req=%d", reqNum)
-	})
-
-	server := &Server{Handler: handler, ReadTimeout: 250 * time.Millisecond, WriteTimeout: 250 * time.Millisecond}
-	go server.Serve(l)
-
-	url := fmt.Sprintf("http://%s/", addr)
+	}))
+	ts.Config.ReadTimeout = 250 * time.Millisecond
+	ts.Config.WriteTimeout = 250 * time.Millisecond
+	ts.Start()
+	defer ts.Close()
 
 	// Hit the HTTP server successfully.
 	tr := &Transport{DisableKeepAlives: true} // they interfere with this test
+	defer tr.CloseIdleConnections()
 	c := &Client{Transport: tr}
-	r, err := c.Get(url)
+	r, err := c.Get(ts.URL)
 	if err != nil {
 		t.Fatalf("http Get #1: %v", err)
 	}
@@ -266,13 +285,13 @@ func TestServerTimeouts(t *testing.T) {
 
 	// Slow client that should timeout.
 	t1 := time.Now()
-	conn, err := net.Dial("tcp", addr.String())
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
 	if err != nil {
 		t.Fatalf("Dial: %v", err)
 	}
 	buf := make([]byte, 1)
 	n, err := conn.Read(buf)
-	latency := time.Now().Sub(t1)
+	latency := time.Since(t1)
 	if n != 0 || err != io.EOF {
 		t.Errorf("Read = %v, %v, wanted %v, %v", n, err, 0, io.EOF)
 	}
@@ -283,7 +302,7 @@ func TestServerTimeouts(t *testing.T) {
 	// Hit the HTTP server successfully again, verifying that the
 	// previous slow connection didn't run our handler.  (that we
 	// get "req=2", not "req=3")
-	r, err = Get(url)
+	r, err = Get(ts.URL)
 	if err != nil {
 		t.Fatalf("http Get #2: %v", err)
 	}
@@ -293,11 +312,87 @@ func TestServerTimeouts(t *testing.T) {
 		t.Errorf("Get #2 got %q, want %q", string(got), expected)
 	}
 
-	l.Close()
+	if !testing.Short() {
+		conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatalf("Dial: %v", err)
+		}
+		defer conn.Close()
+		go io.Copy(ioutil.Discard, conn)
+		for i := 0; i < 5; i++ {
+			_, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"))
+			if err != nil {
+				t.Fatalf("on write %d: %v", i, err)
+			}
+			time.Sleep(ts.Config.ReadTimeout / 2)
+		}
+	}
+}
+
+// golang.org/issue/4741 -- setting only a write timeout that triggers
+// shouldn't cause a handler to block forever on reads (next HTTP
+// request) that will never happen.
+func TestOnlyWriteTimeout(t *testing.T) {
+	defer checkLeakedTransports(t)
+	var conn net.Conn
+	var afterTimeoutErrc = make(chan error, 1)
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, req *Request) {
+		buf := make([]byte, 512<<10)
+		_, err := w.Write(buf)
+		if err != nil {
+			t.Errorf("handler Write error: %v", err)
+			return
+		}
+		conn.SetWriteDeadline(time.Now().Add(-30 * time.Second))
+		_, err = w.Write(buf)
+		afterTimeoutErrc <- err
+	}))
+	ts.Listener = trackLastConnListener{ts.Listener, &conn}
+	ts.Start()
+	defer ts.Close()
+
+	tr := &Transport{DisableKeepAlives: false}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	errc := make(chan error)
+	go func() {
+		res, err := c.Get(ts.URL)
+		if err != nil {
+			errc <- err
+			return
+		}
+		_, err = io.Copy(ioutil.Discard, res.Body)
+		errc <- err
+	}()
+	select {
+	case err := <-errc:
+		if err == nil {
+			t.Errorf("expected an error from Get request")
+		}
+	case <-time.After(5 * time.Second):
+		t.Fatal("timeout waiting for Get error")
+	}
+	if err := <-afterTimeoutErrc; err == nil {
+		t.Error("expected write error after timeout")
+	}
+}
+
+// trackLastConnListener tracks the last net.Conn that was accepted.
+type trackLastConnListener struct {
+	net.Listener
+	last *net.Conn // destination
 }
 
-// TestIdentityResponse verifies that a handler can unset 
+func (l trackLastConnListener) Accept() (c net.Conn, err error) {
+	c, err = l.Listener.Accept()
+	*l.last = c
+	return
+}
+
+// TestIdentityResponse verifies that a handler can unset
 func TestIdentityResponse(t *testing.T) {
+	defer checkLeakedTransports(t)
 	handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
 		rw.Header().Set("Content-Length", "3")
 		rw.Header().Set("Transfer-Encoding", req.FormValue("te"))
@@ -343,10 +438,12 @@ func TestIdentityResponse(t *testing.T) {
 
 	// Verify that ErrContentLength is returned
 	url := ts.URL + "/?overwrite=1"
-	_, err := Get(url)
+	res, err := Get(url)
 	if err != nil {
 		t.Fatalf("error with Get of %s: %v", url, err)
 	}
+	res.Body.Close()
+
 	// Verify that the connection is closed when the declared Content-Length
 	// is larger than what the handler wrote.
 	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
@@ -370,7 +467,8 @@ func TestIdentityResponse(t *testing.T) {
 	})
 }
 
-func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
+func testTCPConnectionCloses(t *testing.T, req string, h Handler) {
+	defer checkLeakedTransports(t)
 	s := httptest.NewServer(h)
 	defer s.Close()
 
@@ -386,17 +484,18 @@ func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
 	}
 
 	r := bufio.NewReader(conn)
-	_, err = ReadResponse(r, &Request{Method: "GET"})
+	res, err := ReadResponse(r, &Request{Method: "GET"})
 	if err != nil {
 		t.Fatal("ReadResponse error:", err)
 	}
 
-	success := make(chan bool)
+	didReadAll := make(chan bool, 1)
 	go func() {
 		select {
 		case <-time.After(5 * time.Second):
-			t.Fatal("body not closed after 5s")
-		case <-success:
+			t.Error("body not closed after 5s")
+			return
+		case <-didReadAll:
 		}
 	}()
 
@@ -404,32 +503,43 @@ func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
 	if err != nil {
 		t.Fatal("read error:", err)
 	}
+	didReadAll <- true
 
-	success <- true
+	if !res.Close {
+		t.Errorf("Response.Close = false; want true")
+	}
 }
 
 // TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive.
 func TestServeHTTP10Close(t *testing.T) {
-	testTcpConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+	testTCPConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
 		ServeFile(w, r, "testdata/file")
 	}))
 }
 
+// TestClientCanClose verifies that clients can also force a connection to close.
+func TestClientCanClose(t *testing.T) {
+	testTCPConnectionCloses(t, "GET / HTTP/1.1\r\nConnection: close\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+		// Nothing.
+	}))
+}
+
 // TestHandlersCanSetConnectionClose verifies that handlers can force a connection to close,
 // even for HTTP/1.1 requests.
 func TestHandlersCanSetConnectionClose11(t *testing.T) {
-	testTcpConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+	testTCPConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header().Set("Connection", "close")
 	}))
 }
 
 func TestHandlersCanSetConnectionClose10(t *testing.T) {
-	testTcpConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+	testTCPConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header().Set("Connection", "close")
 	}))
 }
 
 func TestSetsRemoteAddr(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		fmt.Fprintf(w, "%s", r.RemoteAddr)
 	}))
@@ -450,11 +560,13 @@ func TestSetsRemoteAddr(t *testing.T) {
 }
 
 func TestChunkedResponseHeaders(t *testing.T) {
+	defer checkLeakedTransports(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("Content-Length", "intentional gibberish") // we check that this is deleted
+		w.(Flusher).Flush()
 		fmt.Fprintf(w, "I am a chunked response.")
 	}))
 	defer ts.Close()
@@ -463,6 +575,7 @@ func TestChunkedResponseHeaders(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Get error: %v", err)
 	}
+	defer res.Body.Close()
 	if g, e := res.ContentLength, int64(-1); g != e {
 		t.Errorf("expected ContentLength of %d; got %d", e, g)
 	}
@@ -478,6 +591,7 @@ func TestChunkedResponseHeaders(t *testing.T) {
 // chunking in their response headers and aren't allowed to produce
 // output.
 func Test304Responses(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.WriteHeader(StatusNotModified)
 		_, err := w.Write([]byte("illegal body"))
@@ -507,6 +621,7 @@ func Test304Responses(t *testing.T) {
 // allowed to produce output, and don't set a Content-Type since
 // the real type of the body data cannot be inferred.
 func TestHeadResponses(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		_, err := w.Write([]byte("Ignored body"))
 		if err != ErrBodyNotAllowed {
@@ -541,6 +656,7 @@ func TestHeadResponses(t *testing.T) {
 }
 
 func TestTLSHandshakeTimeout(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
 	ts.Config.ReadTimeout = 250 * time.Millisecond
 	ts.StartTLS()
@@ -560,6 +676,7 @@ func TestTLSHandshakeTimeout(t *testing.T) {
 }
 
 func TestTLSServer(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		if r.TLS != nil {
 			w.Header().Set("X-TLS-Set", "true")
@@ -642,6 +759,7 @@ var serverExpectTests = []serverExpectTest{
 // Tests that the server responds to the "Expect" request header
 // correctly.
 func TestServerExpect(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		// Note using r.FormValue("readbody") because for POST
 		// requests that would read from r.Body, which we only
@@ -661,30 +779,51 @@ func TestServerExpect(t *testing.T) {
 			t.Fatalf("Dial: %v", err)
 		}
 		defer conn.Close()
-		sendf := func(format string, args ...interface{}) {
-			_, err := fmt.Fprintf(conn, format, args...)
-			if err != nil {
-				t.Fatalf("On test %#v, error writing %q: %v", test, format, err)
-			}
-		}
+
+		// Only send the body immediately if we're acting like an HTTP client
+		// that doesn't send 100-continue expectations.
+		writeBody := test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue"
+
 		go func() {
-			sendf("POST /?readbody=%v HTTP/1.1\r\n"+
+			_, err := fmt.Fprintf(conn, "POST /?readbody=%v HTTP/1.1\r\n"+
 				"Connection: close\r\n"+
 				"Content-Length: %d\r\n"+
 				"Expect: %s\r\nHost: foo\r\n\r\n",
 				test.readBody, test.contentLength, test.expectation)
-			if test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue" {
+			if err != nil {
+				t.Errorf("On test %#v, error writing request headers: %v", test, err)
+				return
+			}
+			if writeBody {
 				body := strings.Repeat("A", test.contentLength)
-				sendf(body)
+				_, err = fmt.Fprint(conn, body)
+				if err != nil {
+					if !test.readBody {
+						// Server likely already hung up on us.
+						// See larger comment below.
+						t.Logf("On test %#v, acceptable error writing request body: %v", test, err)
+						return
+					}
+					t.Errorf("On test %#v, error writing request body: %v", test, err)
+				}
 			}
 		}()
 		bufr := bufio.NewReader(conn)
 		line, err := bufr.ReadString('\n')
 		if err != nil {
-			t.Fatalf("ReadString: %v", err)
+			if writeBody && !test.readBody {
+				// This is an acceptable failure due to a possible TCP race:
+				// We were still writing data and the server hung up on us. A TCP
+				// implementation may send a RST if our request body data was known
+				// to be lost, which may trigger our reads to fail.
+				// See RFC 1122 page 88.
+				t.Logf("On test %#v, acceptable error from ReadString: %v", test, err)
+				return
+			}
+			t.Fatalf("On test %#v, ReadString: %v", test, err)
 		}
 		if !strings.Contains(line, test.expectedResponse) {
-			t.Errorf("for test %#v got first line=%q", test, line)
+			t.Errorf("On test %#v, got first line = %q; want %q", test, line, test.expectedResponse)
 		}
 	}
 
@@ -714,6 +853,7 @@ func TestServerUnreadRequestBodyLittle(t *testing.T) {
 			t.Errorf("on request, read buffer length is %d; expected about 100 KB", conn.readBuf.Len())
 		}
 		rw.WriteHeader(200)
+		rw.(Flusher).Flush()
 		if g, e := conn.readBuf.Len(), 0; g != e {
 			t.Errorf("after WriteHeader, read buffer length is %d; want %d", g, e)
 		}
@@ -736,27 +876,28 @@ func TestServerUnreadRequestBodyLarge(t *testing.T) {
 			"Content-Length: %d\r\n"+
 			"\r\n", len(body))))
 	conn.readBuf.Write([]byte(body))
-
-	done := make(chan bool)
+	conn.closec = make(chan bool, 1)
 
 	ls := &oneConnListener{conn}
 	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
-		defer close(done)
 		if conn.readBuf.Len() < len(body)/2 {
 			t.Errorf("on request, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
 		}
 		rw.WriteHeader(200)
+		rw.(Flusher).Flush()
 		if conn.readBuf.Len() < len(body)/2 {
 			t.Errorf("post-WriteHeader, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
 		}
-		if c := rw.Header().Get("Connection"); c != "close" {
-			t.Errorf(`Connection header = %q; want "close"`, c)
-		}
 	}))
-	<-done
+	<-conn.closec
+
+	if res := conn.writeBuf.String(); !strings.Contains(res, "Connection: close") {
+		t.Errorf("Expected a Connection: close header; got response: %s", res)
+	}
 }
 
 func TestTimeoutHandler(t *testing.T) {
+	defer checkLeakedTransports(t)
 	sendHi := make(chan bool, 1)
 	writeErrors := make(chan error, 1)
 	sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -831,6 +972,7 @@ func TestRedirectMunging(t *testing.T) {
 // the previous request's body, which is not optimal for zero-lengthed bodies,
 // as the client would then see http.ErrBodyReadAfterClose and not 0, io.EOF.
 func TestZeroLengthPostAndResponse(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
 		all, err := ioutil.ReadAll(r.Body)
 		if err != nil {
@@ -868,15 +1010,20 @@ func TestZeroLengthPostAndResponse(t *testing.T) {
 	}
 }
 
+func TestHandlerPanicNil(t *testing.T) {
+	testHandlerPanic(t, false, nil)
+}
+
 func TestHandlerPanic(t *testing.T) {
-	testHandlerPanic(t, false)
+	testHandlerPanic(t, false, "intentional death for testing")
 }
 
 func TestHandlerPanicWithHijack(t *testing.T) {
-	testHandlerPanic(t, true)
+	testHandlerPanic(t, true, "intentional death for testing")
 }
 
-func testHandlerPanic(t *testing.T, withHijack bool) {
+func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
+	defer checkLeakedTransports(t)
 	// Unlike the other tests that set the log output to ioutil.Discard
 	// to quiet the output, this test uses a pipe.  The pipe serves three
 	// purposes:
@@ -896,6 +1043,7 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
 	pr, pw := io.Pipe()
 	log.SetOutput(pw)
 	defer log.SetOutput(os.Stderr)
+	defer pw.Close()
 
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		if withHijack {
@@ -905,7 +1053,7 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
 			}
 			defer rwc.Close()
 		}
-		panic("intentional death for testing")
+		panic(panicValue)
 	}))
 	defer ts.Close()
 
@@ -917,8 +1065,8 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
 		buf := make([]byte, 4<<10)
 		_, err := pr.Read(buf)
 		pr.Close()
-		if err != nil {
-			t.Fatal(err)
+		if err != nil && err != io.EOF {
+			t.Error(err)
 		}
 		done <- true
 	}()
@@ -928,6 +1076,10 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
 		t.Logf("expected an error")
 	}
 
+	if panicValue == nil {
+		return
+	}
+
 	select {
 	case <-done:
 		return
@@ -937,6 +1089,7 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
 }
 
 func TestNoDate(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header()["Date"] = nil
 	}))
@@ -952,6 +1105,7 @@ func TestNoDate(t *testing.T) {
 }
 
 func TestStripPrefix(t *testing.T) {
+	defer checkLeakedTransports(t)
 	h := HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header().Set("X-Path", r.URL.Path)
 	})
@@ -965,6 +1119,7 @@ func TestStripPrefix(t *testing.T) {
 	if g, e := res.Header.Get("X-Path"), "/bar"; g != e {
 		t.Errorf("test 1: got %s, want %s", g, e)
 	}
+	res.Body.Close()
 
 	res, err = Get(ts.URL + "/bar")
 	if err != nil {
@@ -973,9 +1128,11 @@ func TestStripPrefix(t *testing.T) {
 	if g, e := res.StatusCode, 404; g != e {
 		t.Errorf("test 2: got status %v, want %v", g, e)
 	}
+	res.Body.Close()
 }
 
 func TestRequestLimit(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		t.Fatalf("didn't expect to get request in Handler")
 	}))
@@ -992,6 +1149,7 @@ func TestRequestLimit(t *testing.T) {
 		// we do support it (at least currently), so we expect a response below.
 		t.Fatalf("Do: %v", err)
 	}
+	defer res.Body.Close()
 	if res.StatusCode != 413 {
 		t.Fatalf("expected 413 response status; got: %d %s", res.StatusCode, res.Status)
 	}
@@ -1013,11 +1171,12 @@ type countReader struct {
 
 func (cr countReader) Read(p []byte) (n int, err error) {
 	n, err = cr.r.Read(p)
-	*cr.n += int64(n)
+	atomic.AddInt64(cr.n, int64(n))
 	return
 }
 
 func TestRequestBodyLimit(t *testing.T) {
+	defer checkLeakedTransports(t)
 	const limit = 1 << 20
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		r.Body = MaxBytesReader(w, r.Body, limit)
@@ -1031,8 +1190,8 @@ func TestRequestBodyLimit(t *testing.T) {
 	}))
 	defer ts.Close()
 
-	nWritten := int64(0)
-	req, _ := NewRequest("POST", ts.URL, io.LimitReader(countReader{neverEnding('a'), &nWritten}, limit*200))
+	nWritten := new(int64)
+	req, _ := NewRequest("POST", ts.URL, io.LimitReader(countReader{neverEnding('a'), nWritten}, limit*200))
 
 	// Send the POST, but don't care it succeeds or not.  The
 	// remote side is going to reply and then close the TCP
@@ -1045,7 +1204,7 @@ func TestRequestBodyLimit(t *testing.T) {
 	// the remote side hung up on us before we wrote too much.
 	_, _ = DefaultClient.Do(req)
 
-	if nWritten > limit*100 {
+	if atomic.LoadInt64(nWritten) > limit*100 {
 		t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d",
 			limit, nWritten)
 	}
@@ -1054,6 +1213,7 @@ func TestRequestBodyLimit(t *testing.T) {
 // TestClientWriteShutdown tests that if the client shuts down the write
 // side of their TCP connection, the server doesn't send a 400 Bad Request.
 func TestClientWriteShutdown(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
 	defer ts.Close()
 	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
@@ -1086,28 +1246,207 @@ func TestClientWriteShutdown(t *testing.T) {
 // Tests that chunked server responses that write 1 byte at a time are
 // buffered before chunk headers are added, not after chunk headers.
 func TestServerBufferedChunking(t *testing.T) {
-	if true {
-		t.Logf("Skipping known broken test; see Issue 2357")
-		return
-	}
 	conn := new(testConn)
 	conn.readBuf.Write([]byte("GET / HTTP/1.1\r\n\r\n"))
-	done := make(chan bool)
+	conn.closec = make(chan bool, 1)
 	ls := &oneConnListener{conn}
 	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
-		defer close(done)
-		rw.Header().Set("Content-Type", "text/plain") // prevent sniffing, which buffers
+		rw.(Flusher).Flush() // force the Header to be sent, in chunking mode, not counting the length
 		rw.Write([]byte{'x'})
 		rw.Write([]byte{'y'})
 		rw.Write([]byte{'z'})
 	}))
-	<-done
+	<-conn.closec
 	if !bytes.HasSuffix(conn.writeBuf.Bytes(), []byte("\r\n\r\n3\r\nxyz\r\n0\r\n\r\n")) {
 		t.Errorf("response didn't end with a single 3 byte 'xyz' chunk; got:\n%q",
 			conn.writeBuf.Bytes())
 	}
 }
 
+// Tests that the server flushes its response headers out when it's
+// ignoring the response body and waits a bit before forcefully
+// closing the TCP connection, causing the client to get a RST.
+// See http://golang.org/issue/3595
+func TestServerGracefulClose(t *testing.T) {
+	defer checkLeakedTransports(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		Error(w, "bye", StatusUnauthorized)
+	}))
+	defer ts.Close()
+
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer conn.Close()
+	const bodySize = 5 << 20
+	req := []byte(fmt.Sprintf("POST / HTTP/1.1\r\nHost: foo.com\r\nContent-Length: %d\r\n\r\n", bodySize))
+	for i := 0; i < bodySize; i++ {
+		req = append(req, 'x')
+	}
+	writeErr := make(chan error)
+	go func() {
+		_, err := conn.Write(req)
+		writeErr <- err
+	}()
+	br := bufio.NewReader(conn)
+	lineNum := 0
+	for {
+		line, err := br.ReadString('\n')
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			t.Fatalf("ReadLine: %v", err)
+		}
+		lineNum++
+		if lineNum == 1 && !strings.Contains(line, "401 Unauthorized") {
+			t.Errorf("Response line = %q; want a 401", line)
+		}
+	}
+	// Wait for write to finish. This is a broken pipe on both
+	// Darwin and Linux, but checking this isn't the point of
+	// the test.
+	<-writeErr
+}
+
+func TestCaseSensitiveMethod(t *testing.T) {
+	defer checkLeakedTransports(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.Method != "get" {
+			t.Errorf(`Got method %q; want "get"`, r.Method)
+		}
+	}))
+	defer ts.Close()
+	req, _ := NewRequest("get", ts.URL, nil)
+	res, err := DefaultClient.Do(req)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	res.Body.Close()
+}
+
+// TestContentLengthZero tests that for both an HTTP/1.0 and HTTP/1.1
+// request (both keep-alive), when a Handler never writes any
+// response, the net/http package adds a "Content-Length: 0" response
+// header.
+func TestContentLengthZero(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {}))
+	defer ts.Close()
+
+	for _, version := range []string{"HTTP/1.0", "HTTP/1.1"} {
+		conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatalf("error dialing: %v", err)
+		}
+		_, err = fmt.Fprintf(conn, "GET / %v\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n", version)
+		if err != nil {
+			t.Fatalf("error writing: %v", err)
+		}
+		req, _ := NewRequest("GET", "/", nil)
+		res, err := ReadResponse(bufio.NewReader(conn), req)
+		if err != nil {
+			t.Fatalf("error reading response: %v", err)
+		}
+		if te := res.TransferEncoding; len(te) > 0 {
+			t.Errorf("For version %q, Transfer-Encoding = %q; want none", version, te)
+		}
+		if cl := res.ContentLength; cl != 0 {
+			t.Errorf("For version %q, Content-Length = %v; want 0", version, cl)
+		}
+		conn.Close()
+	}
+}
+
+func TestCloseNotifier(t *testing.T) {
+	gotReq := make(chan bool, 1)
+	sawClose := make(chan bool, 1)
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		gotReq <- true
+		cc := rw.(CloseNotifier).CloseNotify()
+		<-cc
+		sawClose <- true
+	}))
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("error dialing: %v", err)
+	}
+	diec := make(chan bool)
+	go func() {
+		_, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n")
+		if err != nil {
+			t.Fatal(err)
+		}
+		<-diec
+		conn.Close()
+	}()
+For:
+	for {
+		select {
+		case <-gotReq:
+			diec <- true
+		case <-sawClose:
+			break For
+		case <-time.After(5 * time.Second):
+			t.Fatal("timeout")
+		}
+	}
+	ts.Close()
+}
+
+func TestOptions(t *testing.T) {
+	uric := make(chan string, 2) // only expect 1, but leave space for 2
+	mux := NewServeMux()
+	mux.HandleFunc("/", func(w ResponseWriter, r *Request) {
+		uric <- r.RequestURI
+	})
+	ts := httptest.NewServer(mux)
+	defer ts.Close()
+
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer conn.Close()
+
+	// An OPTIONS * request should succeed.
+	_, err = conn.Write([]byte("OPTIONS * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	br := bufio.NewReader(conn)
+	res, err := ReadResponse(br, &Request{Method: "OPTIONS"})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != 200 {
+		t.Errorf("Got non-200 response to OPTIONS *: %#v", res)
+	}
+
+	// A GET * request on a ServeMux should fail.
+	_, err = conn.Write([]byte("GET * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	res, err = ReadResponse(br, &Request{Method: "GET"})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != 400 {
+		t.Errorf("Got non-400 response to GET *: %#v", res)
+	}
+
+	res, err = Get(ts.URL + "/second")
+	if err != nil {
+		t.Fatal(err)
+	}
+	res.Body.Close()
+	if got := <-uric; got != "/second" {
+		t.Errorf("Handler saw request for %q; want /second", got)
+	}
+}
+
 // goTimeout runs f, failing t if f takes more than ns to complete.
 func goTimeout(t *testing.T, d time.Duration, f func()) {
 	ch := make(chan bool, 2)
@@ -1184,3 +1523,100 @@ func BenchmarkClientServer(b *testing.B) {
 
 	b.StopTimer()
 }
+
+func BenchmarkClientServerParallel4(b *testing.B) {
+	benchmarkClientServerParallel(b, 4)
+}
+
+func BenchmarkClientServerParallel64(b *testing.B) {
+	benchmarkClientServerParallel(b, 64)
+}
+
+func benchmarkClientServerParallel(b *testing.B, conc int) {
+	b.StopTimer()
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+		fmt.Fprintf(rw, "Hello world.\n")
+	}))
+	defer ts.Close()
+	b.StartTimer()
+
+	numProcs := runtime.GOMAXPROCS(-1) * conc
+	var wg sync.WaitGroup
+	wg.Add(numProcs)
+	n := int32(b.N)
+	for p := 0; p < numProcs; p++ {
+		go func() {
+			for atomic.AddInt32(&n, -1) >= 0 {
+				res, err := Get(ts.URL)
+				if err != nil {
+					b.Logf("Get: %v", err)
+					continue
+				}
+				all, err := ioutil.ReadAll(res.Body)
+				if err != nil {
+					b.Logf("ReadAll: %v", err)
+					continue
+				}
+				body := string(all)
+				if body != "Hello world.\n" {
+					panic("Got body: " + body)
+				}
+			}
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+
+// A benchmark for profiling the server without the HTTP client code.
+// The client code runs in a subprocess.
+//
+// For use like:
+//   $ go test -c
+//   $ ./http.test -test.run=XX -test.bench=BenchmarkServer -test.benchtime=15s -test.cpuprofile=http.prof
+//   $ go tool pprof http.test http.prof
+//   (pprof) web
+func BenchmarkServer(b *testing.B) {
+	// Child process mode;
+	if url := os.Getenv("TEST_BENCH_SERVER_URL"); url != "" {
+		n, err := strconv.Atoi(os.Getenv("TEST_BENCH_CLIENT_N"))
+		if err != nil {
+			panic(err)
+		}
+		for i := 0; i < n; i++ {
+			res, err := Get(url)
+			if err != nil {
+				log.Panicf("Get: %v", err)
+			}
+			all, err := ioutil.ReadAll(res.Body)
+			if err != nil {
+				log.Panicf("ReadAll: %v", err)
+			}
+			body := string(all)
+			if body != "Hello world.\n" {
+				log.Panicf("Got body: %q", body)
+			}
+		}
+		os.Exit(0)
+		return
+	}
+
+	var res = []byte("Hello world.\n")
+	b.StopTimer()
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+		rw.Header().Set("Content-Type", "text/html; charset=utf-8")
+		rw.Write(res)
+	}))
+	defer ts.Close()
+	b.StartTimer()
+
+	cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkServer")
+	cmd.Env = append([]string{
+		fmt.Sprintf("TEST_BENCH_CLIENT_N=%d", b.N),
+		fmt.Sprintf("TEST_BENCH_SERVER_URL=%s", ts.URL),
+	}, os.Environ()...)
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		b.Errorf("Test failure: %v, with output: %s", err, out)
+	}
+}
diff --git a/src/pkg/net/http/server.go b/src/pkg/net/http/server.go
index 0572b4a..b6ab782 100644
--- a/src/pkg/net/http/server.go
+++ b/src/pkg/net/http/server.go
@@ -11,7 +11,6 @@ package http
 
 import (
 	"bufio"
-	"bytes"
 	"crypto/tls"
 	"errors"
 	"fmt"
@@ -21,7 +20,7 @@ import (
 	"net"
 	"net/url"
 	"path"
-	"runtime/debug"
+	"runtime"
 	"strconv"
 	"strings"
 	"sync"
@@ -94,30 +93,188 @@ type Hijacker interface {
 	Hijack() (net.Conn, *bufio.ReadWriter, error)
 }
 
+// The CloseNotifier interface is implemented by ResponseWriters which
+// allow detecting when the underlying connection has gone away.
+//
+// This mechanism can be used to cancel long operations on the server
+// if the client has disconnected before the response is ready.
+type CloseNotifier interface {
+	// CloseNotify returns a channel that receives a single value
+	// when the client connection has gone away.
+	CloseNotify() <-chan bool
+}
+
 // A conn represents the server side of an HTTP connection.
 type conn struct {
 	remoteAddr string               // network address of remote side
 	server     *Server              // the Server on which the connection arrived
 	rwc        net.Conn             // i/o connection
-	lr         *io.LimitedReader    // io.LimitReader(rwc)
-	buf        *bufio.ReadWriter    // buffered(lr,rwc), reading from bufio->limitReader->rwc
-	hijacked   bool                 // connection has been hijacked by handler
+	sr         switchReader         // where the LimitReader reads from; usually the rwc
+	lr         *io.LimitedReader    // io.LimitReader(sr)
+	buf        *bufio.ReadWriter    // buffered(lr,rwc), reading from bufio->limitReader->sr->rwc
 	tlsState   *tls.ConnectionState // or nil when not using TLS
-	body       []byte
+
+	mu           sync.Mutex // guards the following
+	clientGone   bool       // if client has disconnected mid-request
+	closeNotifyc chan bool  // made lazily
+	hijackedv    bool       // connection has been hijacked by handler
+}
+
+func (c *conn) hijacked() bool {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	return c.hijackedv
+}
+
+func (c *conn) hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.hijackedv {
+		return nil, nil, ErrHijacked
+	}
+	if c.closeNotifyc != nil {
+		return nil, nil, errors.New("http: Hijack is incompatible with use of CloseNotifier")
+	}
+	c.hijackedv = true
+	rwc = c.rwc
+	buf = c.buf
+	c.rwc = nil
+	c.buf = nil
+	return
+}
+
+func (c *conn) closeNotify() <-chan bool {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.closeNotifyc == nil {
+		c.closeNotifyc = make(chan bool)
+		if c.hijackedv {
+			// to obey the function signature, even though
+			// it'll never receive a value.
+			return c.closeNotifyc
+		}
+		pr, pw := io.Pipe()
+
+		readSource := c.sr.r
+		c.sr.Lock()
+		c.sr.r = pr
+		c.sr.Unlock()
+		go func() {
+			_, err := io.Copy(pw, readSource)
+			if err == nil {
+				err = io.EOF
+			}
+			pw.CloseWithError(err)
+			c.noteClientGone()
+		}()
+	}
+	return c.closeNotifyc
+}
+
+func (c *conn) noteClientGone() {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.closeNotifyc != nil && !c.clientGone {
+		c.closeNotifyc <- true
+	}
+	c.clientGone = true
+}
+
+type switchReader struct {
+	sync.Mutex
+	r io.Reader
+}
+
+func (sr *switchReader) Read(p []byte) (n int, err error) {
+	sr.Lock()
+	r := sr.r
+	sr.Unlock()
+	return r.Read(p)
+}
+
+// This should be >= 512 bytes for DetectContentType,
+// but otherwise it's somewhat arbitrary.
+const bufferBeforeChunkingSize = 2048
+
+// chunkWriter writes to a response's conn buffer, and is the writer
+// wrapped by the response.bufw buffered writer.
+//
+// chunkWriter also is responsible for finalizing the Header, including
+// conditionally setting the Content-Type and setting a Content-Length
+// in cases where the handler's final output is smaller than the buffer
+// size. It also conditionally adds chunk headers, when in chunking mode.
+//
+// See the comment above (*response).Write for the entire write flow.
+type chunkWriter struct {
+	res         *response
+	header      Header // a deep copy of r.Header, once WriteHeader is called
+	wroteHeader bool   // whether the header's been sent
+
+	// set by the writeHeader method:
+	chunking bool // using chunked transfer encoding for reply body
+}
+
+var crlf = []byte("\r\n")
+
+func (cw *chunkWriter) Write(p []byte) (n int, err error) {
+	if !cw.wroteHeader {
+		cw.writeHeader(p)
+	}
+	if cw.chunking {
+		_, err = fmt.Fprintf(cw.res.conn.buf, "%x\r\n", len(p))
+		if err != nil {
+			cw.res.conn.rwc.Close()
+			return
+		}
+	}
+	n, err = cw.res.conn.buf.Write(p)
+	if cw.chunking && err == nil {
+		_, err = cw.res.conn.buf.Write(crlf)
+	}
+	if err != nil {
+		cw.res.conn.rwc.Close()
+	}
+	return
+}
+
+func (cw *chunkWriter) flush() {
+	if !cw.wroteHeader {
+		cw.writeHeader(nil)
+	}
+	cw.res.conn.buf.Flush()
+}
+
+func (cw *chunkWriter) close() {
+	if !cw.wroteHeader {
+		cw.writeHeader(nil)
+	}
+	if cw.chunking {
+		// zero EOF chunk, trailer key/value pairs (currently
+		// unsupported in Go's server), followed by a blank
+		// line.
+		io.WriteString(cw.res.conn.buf, "0\r\n\r\n")
+	}
 }
 
 // A response represents the server side of an HTTP response.
 type response struct {
 	conn          *conn
 	req           *Request // request for this response
-	chunking      bool     // using chunked transfer encoding for reply body
-	wroteHeader   bool     // reply header has been written
+	wroteHeader   bool     // reply header has been (logically) written
 	wroteContinue bool     // 100 Continue response was written
-	header        Header   // reply header parameters
-	written       int64    // number of bytes written in body
-	contentLength int64    // explicitly-declared Content-Length; or -1
-	status        int      // status code passed to WriteHeader
-	needSniff     bool     // need to sniff to find Content-Type
+
+	w  *bufio.Writer // buffers output in chunks to chunkWriter
+	cw *chunkWriter
+
+	// handlerHeader is the Header that Handlers get access to,
+	// which may be retained and mutated even after WriteHeader.
+	// handlerHeader is copied into cw.header at WriteHeader
+	// time, and privately mutated thereafter.
+	handlerHeader Header
+
+	written       int64 // number of bytes written in body
+	contentLength int64 // explicitly-declared Content-Length; or -1
+	status        int   // status code passed to WriteHeader
 
 	// close connection after this reply.  set on request and
 	// updated after response from handler if there's a
@@ -127,12 +284,14 @@ type response struct {
 
 	// requestBodyLimitHit is set by requestTooLarge when
 	// maxBytesReader hits its max size. It is checked in
-	// WriteHeader, to make sure we don't consume the the
+	// WriteHeader, to make sure we don't consume the
 	// remaining request body to try to advance to the next HTTP
-	// request. Instead, when this is set, we stop doing
+	// request. Instead, when this is set, we stop reading
 	// subsequent requests on this connection and stop reading
 	// input from it.
 	requestBodyLimitHit bool
+
+	handlerDone bool // set true when the handler exits
 }
 
 // requestTooLarge is called by maxBytesReader when too much input has
@@ -145,42 +304,68 @@ func (w *response) requestTooLarge() {
 	}
 }
 
+// needsSniff returns whether a Content-Type still needs to be sniffed.
+func (w *response) needsSniff() bool {
+	return !w.cw.wroteHeader && w.handlerHeader.Get("Content-Type") == "" && w.written < sniffLen
+}
+
 type writerOnly struct {
 	io.Writer
 }
 
 func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
-	// Call WriteHeader before checking w.chunking if it hasn't
-	// been called yet, since WriteHeader is what sets w.chunking.
 	if !w.wroteHeader {
 		w.WriteHeader(StatusOK)
 	}
-	if !w.chunking && w.bodyAllowed() && !w.needSniff {
-		w.Flush()
+
+	if w.needsSniff() {
+		n0, err := io.Copy(writerOnly{w}, io.LimitReader(src, sniffLen))
+		n += n0
+		if err != nil {
+			return n, err
+		}
+	}
+
+	w.w.Flush()  // get rid of any previous writes
+	w.cw.flush() // make sure Header is written; flush data to rwc
+
+	// Now that cw has been flushed, its chunking field is guaranteed initialized.
+	if !w.cw.chunking && w.bodyAllowed() {
 		if rf, ok := w.conn.rwc.(io.ReaderFrom); ok {
-			n, err = rf.ReadFrom(src)
-			w.written += n
-			return
+			n0, err := rf.ReadFrom(src)
+			n += n0
+			w.written += n0
+			return n, err
 		}
 	}
+
 	// Fall back to default io.Copy implementation.
 	// Use wrapper to hide w.ReadFrom from io.Copy.
-	return io.Copy(writerOnly{w}, src)
+	n0, err := io.Copy(writerOnly{w}, src)
+	n += n0
+	return n, err
 }
 
 // noLimit is an effective infinite upper bound for io.LimitedReader
 const noLimit int64 = (1 << 63) - 1
 
+// debugServerConnections controls whether all server connections are wrapped
+// with a verbose logging wrapper.
+const debugServerConnections = false
+
 // Create new connection from rwc.
 func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
 	c = new(conn)
 	c.remoteAddr = rwc.RemoteAddr().String()
 	c.server = srv
 	c.rwc = rwc
-	c.body = make([]byte, sniffLen)
-	c.lr = io.LimitReader(rwc, noLimit).(*io.LimitedReader)
+	if debugServerConnections {
+		c.rwc = newLoggingConn("server", c.rwc)
+	}
+	c.sr = switchReader{r: c.rwc}
+	c.lr = io.LimitReader(&c.sr, noLimit).(*io.LimitedReader)
 	br := bufio.NewReader(c.lr)
-	bw := bufio.NewWriter(rwc)
+	bw := bufio.NewWriter(c.rwc)
 	c.buf = bufio.NewReadWriter(br, bw)
 	return c, nil
 }
@@ -207,9 +392,9 @@ type expectContinueReader struct {
 
 func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
 	if ecr.closed {
-		return 0, errors.New("http: Read after Close on request Body")
+		return 0, ErrBodyReadAfterClose
 	}
-	if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked {
+	if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked() {
 		ecr.resp.wroteContinue = true
 		io.WriteString(ecr.resp.conn.buf, "HTTP/1.1 100 Continue\r\n\r\n")
 		ecr.resp.conn.buf.Flush()
@@ -232,9 +417,19 @@ var errTooLarge = errors.New("http: request too large")
 
 // Read next request from connection.
 func (c *conn) readRequest() (w *response, err error) {
-	if c.hijacked {
+	if c.hijacked() {
 		return nil, ErrHijacked
 	}
+
+	if d := c.server.ReadTimeout; d != 0 {
+		c.rwc.SetReadDeadline(time.Now().Add(d))
+	}
+	if d := c.server.WriteTimeout; d != 0 {
+		defer func() {
+			c.rwc.SetWriteDeadline(time.Now().Add(d))
+		}()
+	}
+
 	c.lr.N = int64(c.server.maxHeaderBytes()) + 4096 /* bufio slop */
 	var req *Request
 	if req, err = ReadRequest(c.buf.Reader); err != nil {
@@ -248,17 +443,20 @@ func (c *conn) readRequest() (w *response, err error) {
 	req.RemoteAddr = c.remoteAddr
 	req.TLS = c.tlsState
 
-	w = new(response)
-	w.conn = c
-	w.req = req
-	w.header = make(Header)
-	w.contentLength = -1
-	c.body = c.body[:0]
+	w = &response{
+		conn:          c,
+		req:           req,
+		handlerHeader: make(Header),
+		contentLength: -1,
+		cw:            new(chunkWriter),
+	}
+	w.cw.res = w
+	w.w = bufio.NewWriterSize(w.cw, bufferBeforeChunkingSize)
 	return w, nil
 }
 
 func (w *response) Header() Header {
-	return w.header
+	return w.handlerHeader
 }
 
 // maxPostHandlerReadBytes is the max number of Request.Body bytes not
@@ -273,7 +471,7 @@ func (w *response) Header() Header {
 const maxPostHandlerReadBytes = 256 << 10
 
 func (w *response) WriteHeader(code int) {
-	if w.conn.hijacked {
+	if w.conn.hijacked() {
 		log.Print("http: response.WriteHeader on hijacked connection")
 		return
 	}
@@ -284,31 +482,68 @@ func (w *response) WriteHeader(code int) {
 	w.wroteHeader = true
 	w.status = code
 
-	// Check for a explicit (and valid) Content-Length header.
-	var hasCL bool
-	var contentLength int64
-	if clenStr := w.header.Get("Content-Length"); clenStr != "" {
-		var err error
-		contentLength, err = strconv.ParseInt(clenStr, 10, 64)
-		if err == nil {
-			hasCL = true
+	w.cw.header = w.handlerHeader.clone()
+
+	if cl := w.cw.header.get("Content-Length"); cl != "" {
+		v, err := strconv.ParseInt(cl, 10, 64)
+		if err == nil && v >= 0 {
+			w.contentLength = v
 		} else {
-			log.Printf("http: invalid Content-Length of %q sent", clenStr)
-			w.header.Del("Content-Length")
+			log.Printf("http: invalid Content-Length of %q", cl)
+			w.cw.header.Del("Content-Length")
+		}
+	}
+}
+
+// writeHeader finalizes the header sent to the client and writes it
+// to cw.res.conn.buf.
+//
+// p is not written by writeHeader, but is the first chunk of the body
+// that will be written.  It is sniffed for a Content-Type if none is
+// set explicitly.  It's also used to set the Content-Length, if the
+// total body size was small and the handler has already finished
+// running.
+func (cw *chunkWriter) writeHeader(p []byte) {
+	if cw.wroteHeader {
+		return
+	}
+	cw.wroteHeader = true
+
+	w := cw.res
+	code := w.status
+	done := w.handlerDone
+
+	// If the handler is done but never sent a Content-Length
+	// response header and this is our first (and last) write, set
+	// it, even to zero. This helps HTTP/1.0 clients keep their
+	// "keep-alive" connections alive.
+	if done && cw.header.get("Content-Length") == "" && w.req.Method != "HEAD" {
+		w.contentLength = int64(len(p))
+		cw.header.Set("Content-Length", strconv.Itoa(len(p)))
+	}
+
+	// If this was an HTTP/1.0 request with keep-alive and we sent a
+	// Content-Length back, we can make this a keep-alive response ...
+	if w.req.wantsHttp10KeepAlive() {
+		sentLength := cw.header.get("Content-Length") != ""
+		if sentLength && cw.header.get("Connection") == "keep-alive" {
+			w.closeAfterReply = false
 		}
 	}
 
+	// Check for a explicit (and valid) Content-Length header.
+	hasCL := w.contentLength != -1
+
 	if w.req.wantsHttp10KeepAlive() && (w.req.Method == "HEAD" || hasCL) {
-		_, connectionHeaderSet := w.header["Connection"]
+		_, connectionHeaderSet := cw.header["Connection"]
 		if !connectionHeaderSet {
-			w.header.Set("Connection", "keep-alive")
+			cw.header.Set("Connection", "keep-alive")
 		}
-	} else if !w.req.ProtoAtLeast(1, 1) {
-		// Client did not ask to keep connection alive.
+	} else if !w.req.ProtoAtLeast(1, 1) || w.req.wantsClose() {
 		w.closeAfterReply = true
 	}
 
-	if w.header.Get("Connection") == "close" {
+	if cw.header.get("Connection") == "close" {
 		w.closeAfterReply = true
 	}
 
@@ -322,7 +557,7 @@ func (w *response) WriteHeader(code int) {
 			n, _ := io.CopyN(ioutil.Discard, w.req.Body, maxPostHandlerReadBytes+1)
 			if n >= maxPostHandlerReadBytes {
 				w.requestTooLarge()
-				w.header.Set("Connection", "close")
+				cw.header.Set("Connection", "close")
 			} else {
 				w.req.Body.Close()
 			}
@@ -332,64 +567,67 @@ func (w *response) WriteHeader(code int) {
 	if code == StatusNotModified {
 		// Must not have body.
 		for _, header := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} {
-			if w.header.Get(header) != "" {
-				// TODO: return an error if WriteHeader gets a return parameter
-				// or set a flag on w to make future Writes() write an error page?
-				// for now just log and drop the header.
-				log.Printf("http: StatusNotModified response with header %q defined", header)
-				w.header.Del(header)
+			// RFC 2616 section 10.3.5: "the response MUST NOT include other entity-headers"
+			if cw.header.get(header) != "" {
+				cw.header.Del(header)
 			}
 		}
 	} else {
 		// If no content type, apply sniffing algorithm to body.
-		if w.header.Get("Content-Type") == "" && w.req.Method != "HEAD" {
-			w.needSniff = true
+		if cw.header.get("Content-Type") == "" && w.req.Method != "HEAD" {
+			cw.header.Set("Content-Type", DetectContentType(p))
 		}
 	}
 
-	if _, ok := w.header["Date"]; !ok {
-		w.Header().Set("Date", time.Now().UTC().Format(TimeFormat))
+	if _, ok := cw.header["Date"]; !ok {
+		cw.header.Set("Date", time.Now().UTC().Format(TimeFormat))
 	}
 
-	te := w.header.Get("Transfer-Encoding")
+	te := cw.header.get("Transfer-Encoding")
 	hasTE := te != ""
 	if hasCL && hasTE && te != "identity" {
 		// TODO: return an error if WriteHeader gets a return parameter
 		// For now just ignore the Content-Length.
 		log.Printf("http: WriteHeader called with both Transfer-Encoding of %q and a Content-Length of %d",
-			te, contentLength)
-		w.header.Del("Content-Length")
+			te, w.contentLength)
+		cw.header.Del("Content-Length")
 		hasCL = false
 	}
 
 	if w.req.Method == "HEAD" || code == StatusNotModified {
 		// do nothing
+	} else if code == StatusNoContent {
+		cw.header.Del("Transfer-Encoding")
 	} else if hasCL {
-		w.contentLength = contentLength
-		w.header.Del("Transfer-Encoding")
+		cw.header.Del("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.
-		w.chunking = true
-		w.header.Set("Transfer-Encoding", "chunked")
+		cw.chunking = true
+		cw.header.Set("Transfer-Encoding", "chunked")
 	} else {
 		// HTTP version < 1.1: cannot do chunked transfer
 		// encoding and we don't know the Content-Length so
 		// signal EOF by closing connection.
 		w.closeAfterReply = true
-		w.header.Del("Transfer-Encoding") // in case already set
+		cw.header.Del("Transfer-Encoding") // in case already set
 	}
 
 	// Cannot use Content-Length with non-identity Transfer-Encoding.
-	if w.chunking {
-		w.header.Del("Content-Length")
+	if cw.chunking {
+		cw.header.Del("Content-Length")
 	}
 	if !w.req.ProtoAtLeast(1, 0) {
 		return
 	}
+
+	if w.closeAfterReply && !hasToken(cw.header.get("Connection"), "close") {
+		cw.header.Set("Connection", "close")
+	}
+
 	proto := "HTTP/1.0"
 	if w.req.ProtoAtLeast(1, 1) {
 		proto = "HTTP/1.1"
@@ -400,37 +638,8 @@ func (w *response) WriteHeader(code int) {
 		text = "status code " + codestring
 	}
 	io.WriteString(w.conn.buf, proto+" "+codestring+" "+text+"\r\n")
-	w.header.Write(w.conn.buf)
-
-	// If we need to sniff the body, leave the header open.
-	// Otherwise, end it here.
-	if !w.needSniff {
-		io.WriteString(w.conn.buf, "\r\n")
-	}
-}
-
-// sniff uses the first block of written data,
-// stored in w.conn.body, to decide the Content-Type
-// for the HTTP body.
-func (w *response) sniff() {
-	if !w.needSniff {
-		return
-	}
-	w.needSniff = false
-
-	data := w.conn.body
-	fmt.Fprintf(w.conn.buf, "Content-Type: %s\r\n\r\n", DetectContentType(data))
-
-	if len(data) == 0 {
-		return
-	}
-	if w.chunking {
-		fmt.Fprintf(w.conn.buf, "%x\r\n", len(data))
-	}
-	_, err := w.conn.buf.Write(data)
-	if w.chunking && err == nil {
-		io.WriteString(w.conn.buf, "\r\n")
-	}
+	cw.header.Write(w.conn.buf)
+	w.conn.buf.Write(crlf)
 }
 
 // bodyAllowed returns true if a Write is allowed for this response type.
@@ -442,8 +651,40 @@ func (w *response) bodyAllowed() bool {
 	return w.status != StatusNotModified && w.req.Method != "HEAD"
 }
 
+// The Life Of A Write is like this:
+//
+// Handler starts. No header has been sent. The handler can either
+// write a header, or just start writing.  Writing before sending a header
+// sends an implicity empty 200 OK header.
+//
+// If the handler didn't declare a Content-Length up front, we either
+// go into chunking mode or, if the handler finishes running before
+// the chunking buffer size, we compute a Content-Length and send that
+// in the header instead.
+//
+// Likewise, if the handler didn't set a Content-Type, we sniff that
+// from the initial chunk of output.
+//
+// The Writers are wired together like:
+//
+// 1. *response (the ResponseWriter) ->
+// 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.
+//
+// TODO(bradfitz): short-circuit some of the buffering when the
+// initial header contains both a Content-Type and Content-Length.
+// Also short-circuit in (1) when the header's been sent and not in
+// chunking mode, writing directly to (4) instead, if (2) has no
+// buffered data.  More generally, we could short-circuit from (1) to
+// (3) even in chunking mode if the write size from (1) is over some
+// threshold and nothing is in (2).  The answer might be mostly making
+// bufferBeforeChunkingSize smaller and having bufio's fast-paths deal
+// with this instead.
 func (w *response) Write(data []byte) (n int, err error) {
-	if w.conn.hijacked {
+	if w.conn.hijacked() {
 		log.Print("http: response.Write on hijacked connection")
 		return 0, ErrHijacked
 	}
@@ -461,73 +702,20 @@ func (w *response) Write(data []byte) (n int, err error) {
 	if w.contentLength != -1 && w.written > w.contentLength {
 		return 0, ErrContentLength
 	}
-
-	var m int
-	if w.needSniff {
-		// We need to sniff the beginning of the output to
-		// determine the content type.  Accumulate the
-		// initial writes in w.conn.body.
-		// Cap m so that append won't allocate.
-		m = cap(w.conn.body) - len(w.conn.body)
-		if m > len(data) {
-			m = len(data)
-		}
-		w.conn.body = append(w.conn.body, data[:m]...)
-		data = data[m:]
-		if len(data) == 0 {
-			// Copied everything into the buffer.
-			// Wait for next write.
-			return m, nil
-		}
-
-		// Filled the buffer; more data remains.
-		// Sniff the content (flushes the buffer)
-		// and then proceed with the remainder
-		// of the data as a normal Write.
-		// Calling sniff clears needSniff.
-		w.sniff()
-	}
-
-	// TODO(rsc): if chunking happened after the buffering,
-	// then there would be fewer chunk headers.
-	// On the other hand, it would make hijacking more difficult.
-	if w.chunking {
-		fmt.Fprintf(w.conn.buf, "%x\r\n", len(data)) // TODO(rsc): use strconv not fmt
-	}
-	n, err = w.conn.buf.Write(data)
-	if err == nil && w.chunking {
-		if n != len(data) {
-			err = io.ErrShortWrite
-		}
-		if err == nil {
-			io.WriteString(w.conn.buf, "\r\n")
-		}
-	}
-
-	return m + n, err
+	return w.w.Write(data)
 }
 
 func (w *response) finishRequest() {
-	// If this was an HTTP/1.0 request with keep-alive and we sent a Content-Length
-	// back, we can make this a keep-alive response ...
-	if w.req.wantsHttp10KeepAlive() {
-		sentLength := w.header.Get("Content-Length") != ""
-		if sentLength && w.header.Get("Connection") == "keep-alive" {
-			w.closeAfterReply = false
-		}
-	}
+	w.handlerDone = true
+
 	if !w.wroteHeader {
 		w.WriteHeader(StatusOK)
 	}
-	if w.needSniff {
-		w.sniff()
-	}
-	if w.chunking {
-		io.WriteString(w.conn.buf, "0\r\n")
-		// trailer key/value pairs, followed by blank line
-		io.WriteString(w.conn.buf, "\r\n")
-	}
+
+	w.w.Flush()
+	w.cw.close()
 	w.conn.buf.Flush()
+
 	// Close the body, unless we're about to close the whole TCP connection
 	// anyway.
 	if !w.closeAfterReply {
@@ -537,7 +725,7 @@ func (w *response) finishRequest() {
 		w.req.MultipartForm.RemoveAll()
 	}
 
-	if w.contentLength != -1 && w.contentLength != w.written {
+	if w.contentLength != -1 && w.bodyAllowed() && w.contentLength != w.written {
 		// Did not write enough. Avoid getting out of sync.
 		w.closeAfterReply = true
 	}
@@ -547,66 +735,114 @@ func (w *response) Flush() {
 	if !w.wroteHeader {
 		w.WriteHeader(StatusOK)
 	}
-	w.sniff()
-	w.conn.buf.Flush()
+	w.w.Flush()
+	w.cw.flush()
 }
 
-// Close the connection.
-func (c *conn) close() {
+func (c *conn) finalFlush() {
 	if c.buf != nil {
 		c.buf.Flush()
 		c.buf = nil
 	}
+}
+
+// Close the connection.
+func (c *conn) close() {
+	c.finalFlush()
 	if c.rwc != nil {
 		c.rwc.Close()
 		c.rwc = nil
 	}
 }
 
+// rstAvoidanceDelay is the amount of time we sleep after closing the
+// write side of a TCP connection before closing the entire socket.
+// By sleeping, we increase the chances that the client sees our FIN
+// and processes its final data before they process the subsequent RST
+// from closing a connection with known unread data.
+// This RST seems to occur mostly on BSD systems. (And Windows?)
+// This timeout is somewhat arbitrary (~latency around the planet).
+const rstAvoidanceDelay = 500 * time.Millisecond
+
+// 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
+// subsequent RST.
+//
+// See http://golang.org/issue/3595
+func (c *conn) closeWriteAndWait() {
+	c.finalFlush()
+	if tcp, ok := c.rwc.(*net.TCPConn); ok {
+		tcp.CloseWrite()
+	}
+	time.Sleep(rstAvoidanceDelay)
+}
+
+// validNPN returns whether the proto is not a blacklisted Next
+// Protocol Negotiation protocol.  Empty and built-in protocol types
+// are blacklisted and can't be overridden with alternate
+// implementations.
+func validNPN(proto string) bool {
+	switch proto {
+	case "", "http/1.1", "http/1.0":
+		return false
+	}
+	return true
+}
+
 // Serve a new connection.
 func (c *conn) serve() {
 	defer func() {
-		err := recover()
-		if err == nil {
-			return
+		if err := recover(); err != nil {
+			const size = 4096
+			buf := make([]byte, size)
+			buf = buf[:runtime.Stack(buf, false)]
+			log.Printf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
 		}
-
-		var buf bytes.Buffer
-		fmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err)
-		buf.Write(debug.Stack())
-		log.Print(buf.String())
-
-		if c.rwc != nil { // may be nil if connection hijacked
-			c.rwc.Close()
+		if !c.hijacked() {
+			c.close()
 		}
 	}()
 
 	if tlsConn, ok := c.rwc.(*tls.Conn); ok {
+		if d := c.server.ReadTimeout; d != 0 {
+			c.rwc.SetReadDeadline(time.Now().Add(d))
+		}
+		if d := c.server.WriteTimeout; d != 0 {
+			c.rwc.SetWriteDeadline(time.Now().Add(d))
+		}
 		if err := tlsConn.Handshake(); err != nil {
-			c.close()
 			return
 		}
 		c.tlsState = new(tls.ConnectionState)
 		*c.tlsState = tlsConn.ConnectionState()
+		if proto := c.tlsState.NegotiatedProtocol; validNPN(proto) {
+			if fn := c.server.TLSNextProto[proto]; fn != nil {
+				h := initNPNRequest{tlsConn, serverHandler{c.server}}
+				fn(c.server, tlsConn, h)
+			}
+			return
+		}
 	}
 
 	for {
 		w, err := c.readRequest()
 		if err != nil {
-			msg := "400 Bad Request"
 			if err == errTooLarge {
 				// Their HTTP client may or may not be
 				// able to read this if we're
 				// responding to them and hanging up
 				// while they're still writing their
 				// request.  Undefined behavior.
-				msg = "413 Request Entity Too Large"
+				io.WriteString(c.rwc, "HTTP/1.1 413 Request Entity Too Large\r\n\r\n")
+				c.closeWriteAndWait()
+				break
 			} else if err == io.EOF {
 				break // Don't reply
 			} else if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
 				break // Don't reply
 			}
-			fmt.Fprintf(c.rwc, "HTTP/1.1 %s\r\n\r\n", msg)
+			io.WriteString(c.rwc, "HTTP/1.1 400 Bad Request\r\n\r\n")
 			break
 		}
 
@@ -624,59 +860,59 @@ func (c *conn) serve() {
 				break
 			}
 			req.Header.Del("Expect")
-		} else if req.Header.Get("Expect") != "" {
-			// TODO(bradfitz): let ServeHTTP handlers handle
-			// requests with non-standard expectation[s]? Seems
-			// theoretical at best, and doesn't fit into the
-			// current ServeHTTP model anyway.  We'd need to
-			// make the ResponseWriter an optional
-			// "ExpectReplier" interface or something.
-			//
-			// For now we'll just obey RFC 2616 14.20 which says
-			// "If a server receives a request containing an
-			// Expect field that includes an expectation-
-			// extension that it does not support, it MUST
-			// respond with a 417 (Expectation Failed) status."
-			w.Header().Set("Connection", "close")
-			w.WriteHeader(StatusExpectationFailed)
-			w.finishRequest()
+		} else if req.Header.get("Expect") != "" {
+			w.sendExpectationFailed()
 			break
 		}
 
-		handler := c.server.Handler
-		if handler == nil {
-			handler = DefaultServeMux
-		}
-
 		// HTTP cannot have multiple simultaneous active requests.[*]
 		// Until the server replies to this request, it can't read another,
 		// so we might as well run the handler in this goroutine.
 		// [*] Not strictly true: HTTP pipelining.  We could let them all process
 		// in parallel even if their responses need to be serialized.
-		handler.ServeHTTP(w, w.req)
-		if c.hijacked {
+		serverHandler{c.server}.ServeHTTP(w, w.req)
+		if c.hijacked() {
 			return
 		}
 		w.finishRequest()
 		if w.closeAfterReply {
+			if w.requestBodyLimitHit {
+				c.closeWriteAndWait()
+			}
 			break
 		}
 	}
-	c.close()
+}
+
+func (w *response) sendExpectationFailed() {
+	// TODO(bradfitz): let ServeHTTP handlers handle
+	// requests with non-standard expectation[s]? Seems
+	// theoretical at best, and doesn't fit into the
+	// current ServeHTTP model anyway.  We'd need to
+	// make the ResponseWriter an optional
+	// "ExpectReplier" interface or something.
+	//
+	// For now we'll just obey RFC 2616 14.20 which says
+	// "If a server receives a request containing an
+	// Expect field that includes an expectation-
+	// extension that it does not support, it MUST
+	// respond with a 417 (Expectation Failed) status."
+	w.Header().Set("Connection", "close")
+	w.WriteHeader(StatusExpectationFailed)
+	w.finishRequest()
 }
 
 // Hijack implements the Hijacker.Hijack method. Our response is both a ResponseWriter
 // and a Hijacker.
 func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
-	if w.conn.hijacked {
-		return nil, nil, ErrHijacked
+	if w.wroteHeader {
+		w.cw.flush()
 	}
-	w.conn.hijacked = true
-	rwc = w.conn.rwc
-	buf = w.conn.buf
-	w.conn.rwc = nil
-	w.conn.buf = nil
-	return
+	return w.conn.hijack()
+}
+
+func (w *response) CloseNotify() <-chan bool {
+	return w.conn.closeNotify()
 }
 
 // The HandlerFunc type is an adapter to allow the use of
@@ -817,13 +1053,13 @@ func RedirectHandler(url string, code int) Handler {
 // patterns and calls the handler for the pattern that
 // most closely matches the URL.
 //
-// Patterns named fixed, rooted paths, like "/favicon.ico",
+// Patterns name fixed, rooted paths, like "/favicon.ico",
 // or rooted subtrees, like "/images/" (note the trailing slash).
 // Longer patterns take precedence over shorter ones, so that
 // if there are handlers registered for both "/images/"
 // and "/images/thumbnails/", the latter handler will be
 // called for paths beginning "/images/thumbnails/" and the
-// former will receiver requests for any other paths in the
+// former will receive requests for any other paths in the
 // "/images/" subtree.
 //
 // Patterns may optionally begin with a host name, restricting matches to
@@ -836,13 +1072,15 @@ func RedirectHandler(url string, code int) Handler {
 // redirecting any request containing . or .. elements to an
 // equivalent .- and ..-free URL.
 type ServeMux struct {
-	mu sync.RWMutex
-	m  map[string]muxEntry
+	mu    sync.RWMutex
+	m     map[string]muxEntry
+	hosts bool // whether any patterns contain hostnames
 }
 
 type muxEntry struct {
 	explicit bool
 	h        Handler
+	pattern  string
 }
 
 // NewServeMux allocates and returns a new ServeMux.
@@ -883,8 +1121,7 @@ func cleanPath(p string) string {
 
 // Find a handler on a handler map given a path string
 // Most-specific (longest) pattern wins
-func (mux *ServeMux) match(path string) Handler {
-	var h Handler
+func (mux *ServeMux) match(path string) (h Handler, pattern string) {
 	var n = 0
 	for k, v := range mux.m {
 		if !pathMatch(k, path) {
@@ -893,37 +1130,64 @@ func (mux *ServeMux) match(path string) Handler {
 		if h == nil || len(k) > n {
 			n = len(k)
 			h = v.h
+			pattern = v.pattern
+		}
+	}
+	return
+}
+
+// Handler returns the handler to use for the given request,
+// consulting r.Method, r.Host, and r.URL.Path. It always returns
+// a non-nil handler. If the path is not in its canonical form, the
+// handler will be an internally-generated handler that redirects
+// to the canonical path.
+//
+// Handler also returns the registered pattern that matches the
+// request or, in the case of internally-generated redirects,
+// the pattern that will match after following the redirect.
+//
+// If there is no registered handler that applies to the request,
+// Handler returns a ``page not found'' handler and an empty pattern.
+func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
+	if r.Method != "CONNECT" {
+		if p := cleanPath(r.URL.Path); p != r.URL.Path {
+			_, pattern = mux.handler(r.Host, p)
+			return RedirectHandler(p, StatusMovedPermanently), pattern
 		}
 	}
-	return h
+
+	return mux.handler(r.Host, r.URL.Path)
 }
 
-// handler returns the handler to use for the request r.
-func (mux *ServeMux) handler(r *Request) Handler {
+// handler is the main implementation of Handler.
+// The path is known to be in canonical form, except for CONNECT methods.
+func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
 	mux.mu.RLock()
 	defer mux.mu.RUnlock()
 
 	// Host-specific pattern takes precedence over generic ones
-	h := mux.match(r.Host + r.URL.Path)
+	if mux.hosts {
+		h, pattern = mux.match(host + path)
+	}
 	if h == nil {
-		h = mux.match(r.URL.Path)
+		h, pattern = mux.match(path)
 	}
 	if h == nil {
-		h = NotFoundHandler()
+		h, pattern = NotFoundHandler(), ""
 	}
-	return h
+	return
 }
 
 // ServeHTTP dispatches the request to the handler whose
 // pattern most closely matches the request URL.
 func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
-	// Clean path to canonical form and redirect.
-	if p := cleanPath(r.URL.Path); p != r.URL.Path {
-		w.Header().Set("Location", p)
-		w.WriteHeader(StatusMovedPermanently)
+	if r.RequestURI == "*" {
+		w.Header().Set("Connection", "close")
+		w.WriteHeader(StatusBadRequest)
 		return
 	}
-	mux.handler(r).ServeHTTP(w, r)
+	h, _ := mux.Handler(r)
+	h.ServeHTTP(w, r)
 }
 
 // Handle registers the handler for the given pattern.
@@ -942,14 +1206,26 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
 		panic("http: multiple registrations for " + pattern)
 	}
 
-	mux.m[pattern] = muxEntry{explicit: true, h: handler}
+	mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}
+
+	if pattern[0] != '/' {
+		mux.hosts = true
+	}
 
 	// Helpful behavior:
 	// If pattern is /tree/, insert an implicit permanent redirect for /tree.
 	// It can be overridden by an explicit registration.
 	n := len(pattern)
 	if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {
-		mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(pattern, StatusMovedPermanently)}
+		// If pattern contains a host name, strip it and use remaining
+		// path for redirect.
+		path := pattern
+		if pattern[0] != '/' {
+			// In pattern, at least the last character is a '/', so
+			// strings.Index can't be -1.
+			path = pattern[strings.Index(pattern, "/"):]
+		}
+		mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(path, StatusMovedPermanently), pattern: pattern}
 	}
 }
 
@@ -971,7 +1247,7 @@ func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
 }
 
 // Serve accepts incoming HTTP connections on the listener l,
-// creating a new service thread for each.  The service threads
+// creating a new service goroutine for each.  The service goroutines
 // read requests and then call handler to reply to them.
 // Handler is typically nil, in which case the DefaultServeMux is used.
 func Serve(l net.Listener, handler Handler) error {
@@ -987,6 +1263,32 @@ type Server struct {
 	WriteTimeout   time.Duration // maximum duration before timing out write of the response
 	MaxHeaderBytes int           // maximum size of request headers, DefaultMaxHeaderBytes if 0
 	TLSConfig      *tls.Config   // optional TLS config, used by ListenAndServeTLS
+
+	// TLSNextProto optionally specifies a function to take over
+	// ownership of the provided TLS connection when an NPN
+	// protocol upgrade has occured.  The map key is the protocol
+	// name negotiated. The Handler argument should be used to
+	// handle HTTP requests and will initialize the Request's TLS
+	// and RemoteAddr if not already set.  The connection is
+	// automatically closed when the function returns.
+	TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
+}
+
+// serverHandler delegates to either the server's Handler or
+// DefaultServeMux and also handles "OPTIONS *" requests.
+type serverHandler struct {
+	srv *Server
+}
+
+func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
+	handler := sh.srv.Handler
+	if handler == nil {
+		handler = DefaultServeMux
+	}
+	if req.RequestURI == "*" && req.Method == "OPTIONS" {
+		handler = globalOptionsHandler{}
+	}
+	handler.ServeHTTP(rw, req)
 }
 
 // ListenAndServe listens on the TCP network address srv.Addr and then
@@ -1005,7 +1307,7 @@ func (srv *Server) ListenAndServe() error {
 }
 
 // Serve accepts incoming connections on the Listener l, creating a
-// new service thread for each.  The service threads read requests and
+// new service goroutine for each.  The service goroutines read requests and
 // then call srv.Handler to reply to them.
 func (srv *Server) Serve(l net.Listener) error {
 	defer l.Close()
@@ -1029,12 +1331,6 @@ func (srv *Server) Serve(l net.Listener) error {
 			return e
 		}
 		tempDelay = 0
-		if srv.ReadTimeout != 0 {
-			rw.SetReadDeadline(time.Now().Add(srv.ReadTimeout))
-		}
-		if srv.WriteTimeout != 0 {
-			rw.SetWriteDeadline(time.Now().Add(srv.WriteTimeout))
-		}
 		c, err := srv.newConn(rw)
 		if err != nil {
 			continue
@@ -1150,7 +1446,7 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
 // TimeoutHandler returns a Handler that runs h with the given time limit.
 //
 // The new Handler calls h.ServeHTTP to handle each request, but if a
-// call runs for more than ns nanoseconds, the handler responds with
+// call runs for longer than its time limit, the handler responds with
 // a 503 Service Unavailable error and the given message in its body.
 // (If msg is empty, a suitable default message will be sent.)
 // After such a timeout, writes by h to its ResponseWriter will return
@@ -1180,7 +1476,7 @@ func (h *timeoutHandler) errorBody() string {
 }
 
 func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
-	done := make(chan bool)
+	done := make(chan bool, 1)
 	tw := &timeoutWriter{w: w}
 	go func() {
 		h.handler.ServeHTTP(tw, r)
@@ -1232,3 +1528,86 @@ func (tw *timeoutWriter) WriteHeader(code int) {
 	tw.mu.Unlock()
 	tw.w.WriteHeader(code)
 }
+
+// globalOptionsHandler responds to "OPTIONS *" requests.
+type globalOptionsHandler struct{}
+
+func (globalOptionsHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	w.Header().Set("Content-Length", "0")
+	if r.ContentLength != 0 {
+		// Read up to 4KB of OPTIONS body (as mentioned in the
+		// spec as being reserved for future use), but anything
+		// over that is considered a waste of server resources
+		// (or an attack) and we abort and close the connection,
+		// courtesy of MaxBytesReader's EOF behavior.
+		mb := MaxBytesReader(w, r.Body, 4<<10)
+		io.Copy(ioutil.Discard, mb)
+	}
+}
+
+// eofReader is a non-nil io.ReadCloser that always returns EOF.
+var eofReader = ioutil.NopCloser(strings.NewReader(""))
+
+// initNPNRequest is an HTTP handler that initializes certain
+// uninitialized fields in its *Request. Such partially-initialized
+// Requests come from NPN protocol handlers.
+type initNPNRequest struct {
+	c *tls.Conn
+	h serverHandler
+}
+
+func (h initNPNRequest) ServeHTTP(rw ResponseWriter, req *Request) {
+	if req.TLS == nil {
+		req.TLS = &tls.ConnectionState{}
+		*req.TLS = h.c.ConnectionState()
+	}
+	if req.Body == nil {
+		req.Body = eofReader
+	}
+	if req.RemoteAddr == "" {
+		req.RemoteAddr = h.c.RemoteAddr().String()
+	}
+	h.h.ServeHTTP(rw, req)
+}
+
+// loggingConn is used for debugging.
+type loggingConn struct {
+	name string
+	net.Conn
+}
+
+var (
+	uniqNameMu   sync.Mutex
+	uniqNameNext = make(map[string]int)
+)
+
+func newLoggingConn(baseName string, c net.Conn) net.Conn {
+	uniqNameMu.Lock()
+	defer uniqNameMu.Unlock()
+	uniqNameNext[baseName]++
+	return &loggingConn{
+		name: fmt.Sprintf("%s-%d", baseName, uniqNameNext[baseName]),
+		Conn: c,
+	}
+}
+
+func (c *loggingConn) Write(p []byte) (n int, err error) {
+	log.Printf("%s.Write(%d) = ....", c.name, len(p))
+	n, err = c.Conn.Write(p)
+	log.Printf("%s.Write(%d) = %d, %v", c.name, len(p), n, err)
+	return
+}
+
+func (c *loggingConn) Read(p []byte) (n int, err error) {
+	log.Printf("%s.Read(%d) = ....", c.name, len(p))
+	n, err = c.Conn.Read(p)
+	log.Printf("%s.Read(%d) = %d, %v", c.name, len(p), n, err)
+	return
+}
+
+func (c *loggingConn) Close() (err error) {
+	log.Printf("%s.Close() = ...", c.name)
+	err = c.Conn.Close()
+	log.Printf("%s.Close() = %v", c.name, err)
+	return
+}
diff --git a/src/pkg/net/http/server_test.go b/src/pkg/net/http/server_test.go
new file mode 100644
index 0000000..8b4e8c6
--- /dev/null
+++ b/src/pkg/net/http/server_test.go
@@ -0,0 +1,95 @@
+// 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 http
+
+import (
+	"net/url"
+	"testing"
+)
+
+var serveMuxRegister = []struct {
+	pattern string
+	h       Handler
+}{
+	{"/dir/", serve(200)},
+	{"/search", serve(201)},
+	{"codesearch.google.com/search", serve(202)},
+	{"codesearch.google.com/", serve(203)},
+}
+
+// serve returns a handler that sends a response with the given code.
+func serve(code int) HandlerFunc {
+	return func(w ResponseWriter, r *Request) {
+		w.WriteHeader(code)
+	}
+}
+
+var serveMuxTests = []struct {
+	method  string
+	host    string
+	path    string
+	code    int
+	pattern string
+}{
+	{"GET", "google.com", "/", 404, ""},
+	{"GET", "google.com", "/dir", 301, "/dir/"},
+	{"GET", "google.com", "/dir/", 200, "/dir/"},
+	{"GET", "google.com", "/dir/file", 200, "/dir/"},
+	{"GET", "google.com", "/search", 201, "/search"},
+	{"GET", "google.com", "/search/", 404, ""},
+	{"GET", "google.com", "/search/foo", 404, ""},
+	{"GET", "codesearch.google.com", "/search", 202, "codesearch.google.com/search"},
+	{"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"},
+	{"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"},
+	{"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"},
+	{"GET", "images.google.com", "/search", 201, "/search"},
+	{"GET", "images.google.com", "/search/", 404, ""},
+	{"GET", "images.google.com", "/search/foo", 404, ""},
+	{"GET", "google.com", "/../search", 301, "/search"},
+	{"GET", "google.com", "/dir/..", 301, ""},
+	{"GET", "google.com", "/dir/..", 301, ""},
+	{"GET", "google.com", "/dir/./file", 301, "/dir/"},
+
+	// The /foo -> /foo/ redirect applies to CONNECT requests
+	// but the path canonicalization does not.
+	{"CONNECT", "google.com", "/dir", 301, "/dir/"},
+	{"CONNECT", "google.com", "/../search", 404, ""},
+	{"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
+	{"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
+	{"CONNECT", "google.com", "/dir/./file", 200, "/dir/"},
+}
+
+func TestServeMuxHandler(t *testing.T) {
+	mux := NewServeMux()
+	for _, e := range serveMuxRegister {
+		mux.Handle(e.pattern, e.h)
+	}
+
+	for _, tt := range serveMuxTests {
+		r := &Request{
+			Method: tt.method,
+			Host:   tt.host,
+			URL: &url.URL{
+				Path: tt.path,
+			},
+		}
+		h, pattern := mux.Handler(r)
+		cs := &codeSaver{h: Header{}}
+		h.ServeHTTP(cs, r)
+		if pattern != tt.pattern || cs.code != tt.code {
+			t.Errorf("%s %s %s = %d, %q, want %d, %q", tt.method, tt.host, tt.path, cs.code, pattern, tt.code, tt.pattern)
+		}
+	}
+}
+
+// A codeSaver is a ResponseWriter that saves the code passed to WriteHeader.
+type codeSaver struct {
+	h    Header
+	code int
+}
+
+func (cs *codeSaver) Header() Header              { return cs.h }
+func (cs *codeSaver) Write(p []byte) (int, error) { return len(p), nil }
+func (cs *codeSaver) WriteHeader(code int)        { cs.code = code }
diff --git a/src/pkg/net/http/transfer.go b/src/pkg/net/http/transfer.go
index 9e9d841..43c6023 100644
--- a/src/pkg/net/http/transfer.go
+++ b/src/pkg/net/http/transfer.go
@@ -87,10 +87,8 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
 	// Sanitize Body,ContentLength,TransferEncoding
 	if t.ResponseToHEAD {
 		t.Body = nil
-		t.TransferEncoding = nil
-		// ContentLength is expected to hold Content-Length
-		if t.ContentLength < 0 {
-			return nil, ErrMissingContentLength
+		if chunked(t.TransferEncoding) {
+			t.ContentLength = -1
 		}
 	} else {
 		if !atLeastHTTP11 || t.Body == nil {
@@ -122,9 +120,6 @@ func (t *transferWriter) shouldSendContentLength() bool {
 	if t.ContentLength > 0 {
 		return true
 	}
-	if t.ResponseToHEAD {
-		return true
-	}
 	// Many servers expect a Content-Length for these methods
 	if t.Method == "POST" || t.Method == "PUT" {
 		return true
@@ -199,10 +194,11 @@ func (t *transferWriter) WriteBody(w io.Writer) (err error) {
 			ncopy, err = io.Copy(w, t.Body)
 		} else {
 			ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
-			nextra, err := io.Copy(ioutil.Discard, t.Body)
 			if err != nil {
 				return err
 			}
+			var nextra int64
+			nextra, err = io.Copy(ioutil.Discard, t.Body)
 			ncopy += nextra
 		}
 		if err != nil {
@@ -213,7 +209,7 @@ func (t *transferWriter) WriteBody(w io.Writer) (err error) {
 		}
 	}
 
-	if t.ContentLength != -1 && t.ContentLength != ncopy {
+	if !t.ResponseToHEAD && t.ContentLength != -1 && t.ContentLength != ncopy {
 		return fmt.Errorf("http: Request.ContentLength=%d with Body length %d",
 			t.ContentLength, ncopy)
 	}
@@ -294,10 +290,19 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
 		return err
 	}
 
-	t.ContentLength, err = fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
+	realLength, err := fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
 	if err != nil {
 		return err
 	}
+	if isResponse && t.RequestMethod == "HEAD" {
+		if n, err := parseContentLength(t.Header.get("Content-Length")); err != nil {
+			return err
+		} else {
+			t.ContentLength = n
+		}
+	} else {
+		t.ContentLength = realLength
+	}
 
 	// Trailer
 	t.Trailer, err = fixTrailer(t.Header, t.TransferEncoding)
@@ -310,7 +315,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
 	// See RFC2616, section 4.4.
 	switch msg.(type) {
 	case *Response:
-		if t.ContentLength == -1 &&
+		if realLength == -1 &&
 			!chunked(t.TransferEncoding) &&
 			bodyAllowedForStatus(t.StatusCode) {
 			// Unbounded body.
@@ -322,12 +327,16 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
 	// or close connection when finished, since multipart is not supported yet
 	switch {
 	case chunked(t.TransferEncoding):
-		t.Body = &body{Reader: newChunkedReader(r), hdr: msg, r: r, closing: t.Close}
-	case t.ContentLength >= 0:
+		if noBodyExpected(t.RequestMethod) {
+			t.Body = &body{Reader: io.LimitReader(r, 0), closing: t.Close}
+		} else {
+			t.Body = &body{Reader: newChunkedReader(r), hdr: msg, r: r, closing: t.Close}
+		}
+	case realLength >= 0:
 		// TODO: limit the Content-Length. This is an easy DoS vector.
-		t.Body = &body{Reader: io.LimitReader(r, t.ContentLength), closing: t.Close}
+		t.Body = &body{Reader: io.LimitReader(r, realLength), closing: t.Close}
 	default:
-		// t.ContentLength < 0, i.e. "Content-Length" not mentioned in header
+		// realLength < 0, i.e. "Content-Length" not mentioned in header
 		if t.Close {
 			// Close semantics (i.e. HTTP/1.0)
 			t.Body = &body{Reader: r, closing: t.Close}
@@ -371,12 +380,6 @@ func fixTransferEncoding(requestMethod string, header Header) ([]string, error)
 
 	delete(header, "Transfer-Encoding")
 
-	// Head responses have no bodies, so the transfer encoding
-	// should be ignored.
-	if requestMethod == "HEAD" {
-		return nil, nil
-	}
-
 	encodings := strings.Split(raw[0], ",")
 	te := make([]string, 0, len(encodings))
 	// TODO: Even though we only support "identity" and "chunked"
@@ -432,11 +435,11 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
 	}
 
 	// Logic based on Content-Length
-	cl := strings.TrimSpace(header.Get("Content-Length"))
+	cl := strings.TrimSpace(header.get("Content-Length"))
 	if cl != "" {
-		n, err := strconv.ParseInt(cl, 10, 64)
-		if err != nil || n < 0 {
-			return -1, &badStringError{"bad Content-Length", cl}
+		n, err := parseContentLength(cl)
+		if err != nil {
+			return -1, err
 		}
 		return n, nil
 	} else {
@@ -451,13 +454,6 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
 		return 0, nil
 	}
 
-	// Logic based on media type. The purpose of the following code is just
-	// to detect whether the unsupported "multipart/byteranges" is being
-	// used. A proper Content-Type parser is needed in the future.
-	if strings.Contains(strings.ToLower(header.Get("Content-Type")), "multipart/byteranges") {
-		return -1, ErrNotSupported
-	}
-
 	// Body-EOF logic based on other methods (like closing, or chunked coding)
 	return -1, nil
 }
@@ -469,14 +465,14 @@ func shouldClose(major, minor int, header Header) bool {
 	if major < 1 {
 		return true
 	} else if major == 1 && minor == 0 {
-		if !strings.Contains(strings.ToLower(header.Get("Connection")), "keep-alive") {
+		if !strings.Contains(strings.ToLower(header.get("Connection")), "keep-alive") {
 			return true
 		}
 		return false
 	} else {
 		// TODO: Should split on commas, toss surrounding white space,
 		// and check each field.
-		if strings.ToLower(header.Get("Connection")) == "close" {
+		if strings.ToLower(header.get("Connection")) == "close" {
 			header.Del("Connection")
 			return true
 		}
@@ -486,7 +482,7 @@ func shouldClose(major, minor int, header Header) bool {
 
 // Parse the trailer header
 func fixTrailer(header Header, te []string) (Header, error) {
-	raw := header.Get("Trailer")
+	raw := header.get("Trailer")
 	if raw == "" {
 		return nil, nil
 	}
@@ -525,11 +521,11 @@ type body struct {
 	res *response // response writer for server requests, else nil
 }
 
-// ErrBodyReadAfterClose is returned when reading a Request Body after
-// the body has been closed. This typically happens when the body is
+// ErrBodyReadAfterClose is returned when reading a Request or Response
+// Body after the body has been closed. This typically happens when the body is
 // read after an HTTP Handler calls WriteHeader or Write on its
 // ResponseWriter.
-var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed request Body")
+var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
 
 func (b *body) Read(p []byte) (n int, err error) {
 	if b.closed {
@@ -567,14 +563,22 @@ func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
 	return false
 }
 
+var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
+
 func (b *body) readTrailer() error {
 	// The common case, since nobody uses trailers.
-	buf, _ := b.r.Peek(2)
+	buf, err := b.r.Peek(2)
 	if bytes.Equal(buf, singleCRLF) {
 		b.r.ReadByte()
 		b.r.ReadByte()
 		return nil
 	}
+	if len(buf) < 2 {
+		return errTrailerEOF
+	}
+	if err != nil {
+		return err
+	}
 
 	// Make sure there's a header terminator coming up, to prevent
 	// a DoS with an unbounded size Trailer.  It's not easy to
@@ -590,6 +594,9 @@ func (b *body) readTrailer() error {
 
 	hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
 	if err != nil {
+		if err == io.EOF {
+			return errTrailerEOF
+		}
 		return err
 	}
 	switch rr := b.hdr.(type) {
@@ -630,3 +637,18 @@ func (b *body) Close() error {
 	}
 	return nil
 }
+
+// parseContentLength trims whitespace from s and returns -1 if no value
+// is set, or the value if it's >= 0.
+func parseContentLength(cl string) (int64, error) {
+	cl = strings.TrimSpace(cl)
+	if cl == "" {
+		return -1, nil
+	}
+	n, err := strconv.ParseInt(cl, 10, 64)
+	if err != nil || n < 0 {
+		return 0, &badStringError{"bad Content-Length", cl}
+	}
+	return n, nil
+
+}
diff --git a/src/pkg/net/http/transfer_test.go b/src/pkg/net/http/transfer_test.go
new file mode 100644
index 0000000..8627a37
--- /dev/null
+++ b/src/pkg/net/http/transfer_test.go
@@ -0,0 +1,37 @@
+// 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 http
+
+import (
+	"bufio"
+	"strings"
+	"testing"
+)
+
+func TestBodyReadBadTrailer(t *testing.T) {
+	b := &body{
+		Reader: strings.NewReader("foobar"),
+		hdr:    true, // force reading the trailer
+		r:      bufio.NewReader(strings.NewReader("")),
+	}
+	buf := make([]byte, 7)
+	n, err := b.Read(buf[:3])
+	got := string(buf[:n])
+	if got != "foo" || err != nil {
+		t.Fatalf(`first Read = %d (%q), %v; want 3 ("foo")`, n, got, err)
+	}
+
+	n, err = b.Read(buf[:])
+	got = string(buf[:n])
+	if got != "bar" || err != nil {
+		t.Fatalf(`second Read = %d (%q), %v; want 3 ("bar")`, n, got, err)
+	}
+
+	n, err = b.Read(buf[:])
+	got = string(buf[:n])
+	if err == nil {
+		t.Errorf("final Read was successful (%q), expected error from trailer read", got)
+	}
+}
diff --git a/src/pkg/net/http/transport.go b/src/pkg/net/http/transport.go
index 6efe191..685d7d5 100644
--- a/src/pkg/net/http/transport.go
+++ b/src/pkg/net/http/transport.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // HTTP client implementation. See RFC 2616.
-// 
+//
 // This is the low-level Transport implementation of RoundTripper.
 // The high-level interface is in client.go.
 
@@ -24,13 +24,14 @@ import (
 	"os"
 	"strings"
 	"sync"
+	"time"
 )
 
 // DefaultTransport is the default implementation of Transport and is
-// used by DefaultClient.  It establishes a new network connection for
-// each call to Do and uses HTTP proxies as directed by the
-// $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy)
-// environment variables.
+// used by DefaultClient. It establishes network connections as needed
+// and caches them for reuse by subsequent calls. It uses HTTP proxies
+// as directed by the $HTTP_PROXY and $NO_PROXY (or $http_proxy and
+// $no_proxy) environment variables.
 var DefaultTransport RoundTripper = &Transport{Proxy: ProxyFromEnvironment}
 
 // DefaultMaxIdleConnsPerHost is the default value of Transport's
@@ -41,8 +42,11 @@ const DefaultMaxIdleConnsPerHost = 2
 // https, and http proxies (for either http or https with CONNECT).
 // Transport can also cache connections for future re-use.
 type Transport struct {
-	lk       sync.Mutex
+	idleMu   sync.Mutex
 	idleConn map[string][]*persistConn
+	reqMu    sync.Mutex
+	reqConn  map[*Request]*persistConn
+	altMu    sync.RWMutex
 	altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
 
 	// TODO: tunable on global max cached connections
@@ -68,9 +72,15 @@ type Transport struct {
 	DisableCompression bool
 
 	// MaxIdleConnsPerHost, if non-zero, controls the maximum idle
-	// (keep-alive) to keep to keep per-host.  If zero,
+	// (keep-alive) to keep per-host.  If zero,
 	// DefaultMaxIdleConnsPerHost is used.
 	MaxIdleConnsPerHost int
+
+	// ResponseHeaderTimeout, if non-zero, specifies the amount of
+	// time to wait for a server's response headers after fully
+	// writing the request (including its body, if any). This
+	// time does not include the time to read the response body.
+	ResponseHeaderTimeout time.Duration
 }
 
 // ProxyFromEnvironment returns the URL of the proxy to use for a
@@ -88,7 +98,7 @@ func ProxyFromEnvironment(req *Request) (*url.URL, error) {
 		return nil, nil
 	}
 	proxyURL, err := url.Parse(proxy)
-	if err != nil || proxyURL.Scheme == "" {
+	if err != nil || !strings.HasPrefix(proxyURL.Scheme, "http") {
 		if u, err := url.Parse("http://" + proxy); err == nil {
 			proxyURL = u
 			err = nil
@@ -131,17 +141,20 @@ func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) {
 		return nil, errors.New("http: nil Request.Header")
 	}
 	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
-		t.lk.Lock()
+		t.altMu.RLock()
 		var rt RoundTripper
 		if t.altProto != nil {
 			rt = t.altProto[req.URL.Scheme]
 		}
-		t.lk.Unlock()
+		t.altMu.RUnlock()
 		if rt == nil {
 			return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
 		}
 		return rt.RoundTrip(req)
 	}
+	if req.URL.Host == "" {
+		return nil, errors.New("http: no Host in request URL")
+	}
 	treq := &transportRequest{Request: req}
 	cm, err := t.connectMethodForRequest(treq)
 	if err != nil {
@@ -170,8 +183,8 @@ func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
 	if scheme == "http" || scheme == "https" {
 		panic("protocol " + scheme + " already registered")
 	}
-	t.lk.Lock()
-	defer t.lk.Unlock()
+	t.altMu.Lock()
+	defer t.altMu.Unlock()
 	if t.altProto == nil {
 		t.altProto = make(map[string]RoundTripper)
 	}
@@ -186,17 +199,29 @@ func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
 // a "keep-alive" state. It does not interrupt any connections currently
 // in use.
 func (t *Transport) CloseIdleConnections() {
-	t.lk.Lock()
-	defer t.lk.Unlock()
-	if t.idleConn == nil {
+	t.idleMu.Lock()
+	m := t.idleConn
+	t.idleConn = nil
+	t.idleMu.Unlock()
+	if m == nil {
 		return
 	}
-	for _, conns := range t.idleConn {
+	for _, conns := range m {
 		for _, pconn := range conns {
 			pconn.close()
 		}
 	}
-	t.idleConn = make(map[string][]*persistConn)
+}
+
+// CancelRequest cancels an in-flight request by closing its
+// connection.
+func (t *Transport) CancelRequest(req *Request) {
+	t.reqMu.Lock()
+	pc := t.reqConn[req]
+	t.reqMu.Unlock()
+	if pc != nil {
+		pc.conn.Close()
+	}
 }
 
 //
@@ -242,8 +267,6 @@ func (cm *connectMethod) proxyAuth() string {
 // If pconn is no longer needed or not in a good state, putIdleConn
 // returns false.
 func (t *Transport) putIdleConn(pconn *persistConn) bool {
-	t.lk.Lock()
-	defer t.lk.Unlock()
 	if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
 		pconn.close()
 		return false
@@ -256,21 +279,32 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
 	if max == 0 {
 		max = DefaultMaxIdleConnsPerHost
 	}
+	t.idleMu.Lock()
+	if t.idleConn == nil {
+		t.idleConn = make(map[string][]*persistConn)
+	}
 	if len(t.idleConn[key]) >= max {
+		t.idleMu.Unlock()
 		pconn.close()
 		return false
 	}
+	for _, exist := range t.idleConn[key] {
+		if exist == pconn {
+			log.Fatalf("dup idle pconn %p in freelist", pconn)
+		}
+	}
 	t.idleConn[key] = append(t.idleConn[key], pconn)
+	t.idleMu.Unlock()
 	return true
 }
 
 func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
-	t.lk.Lock()
-	defer t.lk.Unlock()
+	key := cm.String()
+	t.idleMu.Lock()
+	defer t.idleMu.Unlock()
 	if t.idleConn == nil {
-		t.idleConn = make(map[string][]*persistConn)
+		return nil
 	}
-	key := cm.String()
 	for {
 		pconns, ok := t.idleConn[key]
 		if !ok {
@@ -289,7 +323,20 @@ func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
 			return
 		}
 	}
-	return
+	panic("unreachable")
+}
+
+func (t *Transport) setReqConn(r *Request, pc *persistConn) {
+	t.reqMu.Lock()
+	defer t.reqMu.Unlock()
+	if t.reqConn == nil {
+		t.reqConn = make(map[*Request]*persistConn)
+	}
+	if pc != nil {
+		t.reqConn[r] = pc
+	} else {
+		delete(t.reqConn, r)
+	}
 }
 
 func (t *Transport) dial(network, addr string) (c net.Conn, err error) {
@@ -323,6 +370,8 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
 		cacheKey: cm.String(),
 		conn:     conn,
 		reqch:    make(chan requestAndChan, 50),
+		writech:  make(chan writeRequest, 50),
+		closech:  make(chan struct{}),
 	}
 
 	switch {
@@ -365,7 +414,18 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
 
 	if cm.targetScheme == "https" {
 		// Initiate TLS and check remote host name against certificate.
-		conn = tls.Client(conn, t.TLSClientConfig)
+		cfg := t.TLSClientConfig
+		if cfg == nil || cfg.ServerName == "" {
+			host := cm.tlsHost()
+			if cfg == nil {
+				cfg = &tls.Config{ServerName: host}
+			} else {
+				clone := *cfg // shallow clone
+				clone.ServerName = host
+				cfg = &clone
+			}
+		}
+		conn = tls.Client(conn, cfg)
 		if err = conn.(*tls.Conn).Handshake(); err != nil {
 			return nil, err
 		}
@@ -380,6 +440,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
 	pconn.br = bufio.NewReader(pconn.conn)
 	pconn.bw = bufio.NewWriter(pconn.conn)
 	go pconn.readLoop()
+	go pconn.writeLoop()
 	return pconn, nil
 }
 
@@ -421,7 +482,15 @@ func useProxy(addr string) bool {
 		if hasPort(p) {
 			p = p[:strings.LastIndex(p, ":")]
 		}
-		if addr == p || (p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:])) {
+		if addr == p {
+			return false
+		}
+		if p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:]) {
+			// no_proxy ".foo.com" matches "bar.foo.com" or "foo.com"
+			return false
+		}
+		if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' {
+			// no_proxy "foo.com" matches "bar.foo.com"
 			return false
 		}
 	}
@@ -484,25 +553,28 @@ type persistConn struct {
 	t        *Transport
 	cacheKey string // its connectMethod.String()
 	conn     net.Conn
+	closed   bool                // whether conn has been closed
 	br       *bufio.Reader       // from conn
 	bw       *bufio.Writer       // to conn
-	reqch    chan requestAndChan // written by roundTrip(); read by readLoop()
+	reqch    chan requestAndChan // written by roundTrip; read by readLoop
+	writech  chan writeRequest   // written by roundTrip; read by writeLoop
+	closech  chan struct{}       // broadcast close when readLoop (TCP connection) closes
 	isProxy  bool
 
+	lk                   sync.Mutex // guards following 3 fields
+	numExpectedResponses int
+	broken               bool // an error has happened on this connection; marked broken so it's not reused.
 	// mutateHeaderFunc is an optional func to modify extra
 	// headers on each outbound request before it's written. (the
 	// original Request given to RoundTrip is not modified)
 	mutateHeaderFunc func(Header)
-
-	lk                   sync.Mutex // guards numExpectedResponses and broken
-	numExpectedResponses int
-	broken               bool // an error has happened on this connection; marked broken so it's not reused.
 }
 
 func (pc *persistConn) isBroken() bool {
 	pc.lk.Lock()
-	defer pc.lk.Unlock()
-	return pc.broken
+	b := pc.broken
+	pc.lk.Unlock()
+	return b
 }
 
 var remoteSideClosedFunc func(error) bool // or nil to use default
@@ -518,6 +590,7 @@ func remoteSideClosed(err error) bool {
 }
 
 func (pc *persistConn) readLoop() {
+	defer close(pc.closech)
 	alive := true
 	var lastbody io.ReadCloser // last response body, if any, read on this connection
 
@@ -544,12 +617,16 @@ func (pc *persistConn) readLoop() {
 			lastbody.Close() // assumed idempotent
 			lastbody = nil
 		}
-		resp, err := ReadResponse(pc.br, rc.req)
+
+		var resp *Response
+		if err == nil {
+			resp, err = ReadResponse(pc.br, rc.req)
+		}
+		hasBody := resp != nil && rc.req.Method != "HEAD" && resp.ContentLength != 0
 
 		if err != nil {
 			pc.close()
 		} else {
-			hasBody := rc.req.Method != "HEAD" && resp.ContentLength != 0
 			if rc.addedGzip && hasBody && resp.Header.Get("Content-Encoding") == "gzip" {
 				resp.Header.Del("Content-Encoding")
 				resp.Header.Del("Content-Length")
@@ -569,31 +646,37 @@ func (pc *persistConn) readLoop() {
 			alive = false
 		}
 
-		hasBody := resp != nil && resp.ContentLength != 0
 		var waitForBodyRead chan bool
-		if alive {
-			if hasBody {
-				lastbody = resp.Body
-				waitForBodyRead = make(chan bool)
-				resp.Body.(*bodyEOFSignal).fn = func() {
-					if !pc.t.putIdleConn(pc) {
-						alive = false
-					}
-					waitForBodyRead <- true
+		if hasBody {
+			lastbody = resp.Body
+			waitForBodyRead = make(chan bool, 1)
+			resp.Body.(*bodyEOFSignal).fn = func(err error) {
+				alive1 := alive
+				if err != nil {
+					alive1 = false
 				}
-			} else {
-				// When there's no response body, we immediately
-				// reuse the TCP connection (putIdleConn), but
-				// we need to prevent ClientConn.Read from
-				// closing the Response.Body on the next
-				// loop, otherwise it might close the body
-				// before the client code has had a chance to
-				// read it (even though it'll just be 0, EOF).
-				lastbody = nil
-
-				if !pc.t.putIdleConn(pc) {
-					alive = false
+				if alive1 && !pc.t.putIdleConn(pc) {
+					alive1 = false
+				}
+				if !alive1 || pc.isBroken() {
+					pc.close()
 				}
+				waitForBodyRead <- alive1
+			}
+		}
+
+		if alive && !hasBody {
+			// When there's no response body, we immediately
+			// reuse the TCP connection (putIdleConn), but
+			// we need to prevent ClientConn.Read from
+			// closing the Response.Body on the next
+			// loop, otherwise it might close the body
+			// before the client code has had a chance to
+			// read it (even though it'll just be 0, EOF).
+			lastbody = nil
+
+			if !pc.t.putIdleConn(pc) {
+				alive = false
 			}
 		}
 
@@ -602,7 +685,35 @@ func (pc *persistConn) readLoop() {
 		// Wait for the just-returned response body to be fully consumed
 		// before we race and peek on the underlying bufio reader.
 		if waitForBodyRead != nil {
-			<-waitForBodyRead
+			alive = <-waitForBodyRead
+		}
+
+		pc.t.setReqConn(rc.req, nil)
+
+		if !alive {
+			pc.close()
+		}
+	}
+}
+
+func (pc *persistConn) writeLoop() {
+	for {
+		select {
+		case wr := <-pc.writech:
+			if pc.isBroken() {
+				wr.ch <- errors.New("http: can't write HTTP request on broken connection")
+				continue
+			}
+			err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra)
+			if err == nil {
+				err = pc.bw.Flush()
+			}
+			if err != nil {
+				pc.markBroken()
+			}
+			wr.ch <- err
+		case <-pc.closech:
+			return
 		}
 	}
 }
@@ -622,9 +733,24 @@ type requestAndChan struct {
 	addedGzip bool
 }
 
+// A writeRequest is sent by the readLoop's goroutine to the
+// writeLoop's goroutine to write a request while the read loop
+// concurrently waits on both the write response and the server's
+// reply.
+type writeRequest struct {
+	req *transportRequest
+	ch  chan<- error
+}
+
 func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) {
-	if pc.mutateHeaderFunc != nil {
-		pc.mutateHeaderFunc(req.extraHeaders())
+	pc.t.setReqConn(req.Request, pc)
+	pc.lk.Lock()
+	pc.numExpectedResponses++
+	headerFn := pc.mutateHeaderFunc
+	pc.lk.Unlock()
+
+	if headerFn != nil {
+		headerFn(req.extraHeaders())
 	}
 
 	// Ask for a compressed version if the caller didn't set their
@@ -633,34 +759,84 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
 	// requested it.
 	requestedGzip := false
 	if !pc.t.DisableCompression && req.Header.Get("Accept-Encoding") == "" {
-		// Request gzip only, not deflate. Deflate is ambiguous and 
+		// Request gzip only, not deflate. Deflate is ambiguous and
 		// not as universally supported anyway.
 		// See: http://www.gzip.org/zlib/zlib_faq.html#faq38
 		requestedGzip = true
 		req.extraHeaders().Set("Accept-Encoding", "gzip")
 	}
 
-	pc.lk.Lock()
-	pc.numExpectedResponses++
-	pc.lk.Unlock()
+	// Write the request concurrently with waiting for a response,
+	// in case the server decides to reply before reading our full
+	// request body.
+	writeErrCh := make(chan error, 1)
+	pc.writech <- writeRequest{req, writeErrCh}
 
-	err = req.Request.write(pc.bw, pc.isProxy, req.extra)
-	if err != nil {
-		pc.close()
-		return
+	resc := make(chan responseAndError, 1)
+	pc.reqch <- requestAndChan{req.Request, resc, requestedGzip}
+
+	var re responseAndError
+	var pconnDeadCh = pc.closech
+	var failTicker <-chan time.Time
+	var respHeaderTimer <-chan time.Time
+WaitResponse:
+	for {
+		select {
+		case err := <-writeErrCh:
+			if err != nil {
+				re = responseAndError{nil, err}
+				pc.close()
+				break WaitResponse
+			}
+			if d := pc.t.ResponseHeaderTimeout; d > 0 {
+				respHeaderTimer = time.After(d)
+			}
+		case <-pconnDeadCh:
+			// The persist connection is dead. This shouldn't
+			// usually happen (only with Connection: close responses
+			// with no response bodies), but if it does happen it
+			// means either a) the remote server hung up on us
+			// prematurely, or b) the readLoop sent us a response &
+			// closed its closech at roughly the same time, and we
+			// selected this case first, in which case a response
+			// might still be coming soon.
+			//
+			// We can't avoid the select race in b) by using a unbuffered
+			// resc channel instead, because then goroutines can
+			// leak if we exit due to other errors.
+			pconnDeadCh = nil                               // avoid spinning
+			failTicker = time.After(100 * time.Millisecond) // arbitrary time to wait for resc
+		case <-failTicker:
+			re = responseAndError{err: errors.New("net/http: transport closed before response was received")}
+			break WaitResponse
+		case <-respHeaderTimer:
+			pc.close()
+			re = responseAndError{err: errors.New("net/http: timeout awaiting response headers")}
+			break WaitResponse
+		case re = <-resc:
+			break WaitResponse
+		}
 	}
-	pc.bw.Flush()
 
-	ch := make(chan responseAndError, 1)
-	pc.reqch <- requestAndChan{req.Request, ch, requestedGzip}
-	re := <-ch
 	pc.lk.Lock()
 	pc.numExpectedResponses--
 	pc.lk.Unlock()
 
+	if re.err != nil {
+		pc.t.setReqConn(req.Request, nil)
+	}
 	return re.res, re.err
 }
 
+// markBroken marks a connection as broken (so it's not reused).
+// It differs from close in that it doesn't close the underlying
+// connection for use when it's still being read.
+func (pc *persistConn) markBroken() {
+	pc.lk.Lock()
+	defer pc.lk.Unlock()
+	pc.broken = true
+}
+
 func (pc *persistConn) close() {
 	pc.lk.Lock()
 	defer pc.lk.Unlock()
@@ -669,7 +845,10 @@ func (pc *persistConn) close() {
 
 func (pc *persistConn) closeLocked() {
 	pc.broken = true
-	pc.conn.Close()
+	if !pc.closed {
+		pc.conn.Close()
+		pc.closed = true
+	}
 	pc.mutateHeaderFunc = nil
 }
 
@@ -687,43 +866,62 @@ func canonicalAddr(url *url.URL) string {
 	return addr
 }
 
-func responseIsKeepAlive(res *Response) bool {
-	// TODO: implement.  for now just always shutting down the connection.
-	return false
-}
-
 // bodyEOFSignal wraps a ReadCloser but runs fn (if non-nil) at most
-// once, right before the final Read() or Close() call returns, but after
-// EOF has been seen.
+// once, right before its final (error-producing) Read or Close call
+// returns.
 type bodyEOFSignal struct {
-	body     io.ReadCloser
-	fn       func()
-	isClosed bool
+	body   io.ReadCloser
+	mu     sync.Mutex  // guards closed, rerr and fn
+	closed bool        // whether Close has been called
+	rerr   error       // sticky Read error
+	fn     func(error) // error will be nil on Read io.EOF
 }
 
 func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
-	n, err = es.body.Read(p)
-	if es.isClosed && n > 0 {
-		panic("http: unexpected bodyEOFSignal Read after Close; see issue 1725")
+	es.mu.Lock()
+	closed, rerr := es.closed, es.rerr
+	es.mu.Unlock()
+	if closed {
+		return 0, errors.New("http: read on closed response body")
+	}
+	if rerr != nil {
+		return 0, rerr
 	}
-	if err == io.EOF && es.fn != nil {
-		es.fn()
-		es.fn = nil
+
+	n, err = es.body.Read(p)
+	if err != nil {
+		es.mu.Lock()
+		defer es.mu.Unlock()
+		if es.rerr == nil {
+			es.rerr = err
+		}
+		es.condfn(err)
 	}
 	return
 }
 
-func (es *bodyEOFSignal) Close() (err error) {
-	if es.isClosed {
+func (es *bodyEOFSignal) Close() error {
+	es.mu.Lock()
+	defer es.mu.Unlock()
+	if es.closed {
 		return nil
 	}
-	es.isClosed = true
-	err = es.body.Close()
-	if err == nil && es.fn != nil {
-		es.fn()
-		es.fn = nil
+	es.closed = true
+	err := es.body.Close()
+	es.condfn(err)
+	return err
+}
+
+// caller must hold es.mu.
+func (es *bodyEOFSignal) condfn(err error) {
+	if es.fn == nil {
+		return
 	}
-	return
+	if err == io.EOF {
+		err = nil
+	}
+	es.fn(err)
+	es.fn = nil
 }
 
 type readFirstCloseBoth struct {
diff --git a/src/pkg/net/http/transport_test.go b/src/pkg/net/http/transport_test.go
index a9e401d..68010e6 100644
--- a/src/pkg/net/http/transport_test.go
+++ b/src/pkg/net/http/transport_test.go
@@ -13,6 +13,7 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"net"
 	. "net/http"
 	"net/http/httptest"
 	"net/url"
@@ -20,6 +21,7 @@ import (
 	"runtime"
 	"strconv"
 	"strings"
+	"sync"
 	"testing"
 	"time"
 )
@@ -35,14 +37,78 @@ var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
 	w.Write([]byte(r.RemoteAddr))
 })
 
+// testCloseConn is a net.Conn tracked by a testConnSet.
+type testCloseConn struct {
+	net.Conn
+	set *testConnSet
+}
+
+func (c *testCloseConn) Close() error {
+	c.set.remove(c)
+	return c.Conn.Close()
+}
+
+// testConnSet tracks a set of TCP connections and whether they've
+// been closed.
+type testConnSet struct {
+	t      *testing.T
+	closed map[net.Conn]bool
+	list   []net.Conn // in order created
+	mutex  sync.Mutex
+}
+
+func (tcs *testConnSet) insert(c net.Conn) {
+	tcs.mutex.Lock()
+	defer tcs.mutex.Unlock()
+	tcs.closed[c] = false
+	tcs.list = append(tcs.list, c)
+}
+
+func (tcs *testConnSet) remove(c net.Conn) {
+	tcs.mutex.Lock()
+	defer tcs.mutex.Unlock()
+	tcs.closed[c] = true
+}
+
+// some tests use this to manage raw tcp connections for later inspection
+func makeTestDial(t *testing.T) (*testConnSet, func(n, addr string) (net.Conn, error)) {
+	connSet := &testConnSet{
+		t:      t,
+		closed: make(map[net.Conn]bool),
+	}
+	dial := func(n, addr string) (net.Conn, error) {
+		c, err := net.Dial(n, addr)
+		if err != nil {
+			return nil, err
+		}
+		tc := &testCloseConn{c, connSet}
+		connSet.insert(tc)
+		return tc, nil
+	}
+	return connSet, dial
+}
+
+func (tcs *testConnSet) check(t *testing.T) {
+	tcs.mutex.Lock()
+	defer tcs.mutex.Unlock()
+
+	for i, c := range tcs.list {
+		if !tcs.closed[c] {
+			t.Errorf("TCP connection #%d, %p (of %d total) was not closed", i+1, c, len(tcs.list))
+		}
+	}
+}
+
 // Two subsequent requests and verify their response is the same.
 // The response from the server is our own IP:port
 func TestTransportKeepAlives(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(hostPortHandler)
 	defer ts.Close()
 
 	for _, disableKeepAlive := range []bool{false, true} {
 		tr := &Transport{DisableKeepAlives: disableKeepAlive}
+		defer tr.CloseIdleConnections()
 		c := &Client{Transport: tr}
 
 		fetch := func(n int) string {
@@ -69,11 +135,16 @@ func TestTransportKeepAlives(t *testing.T) {
 }
 
 func TestTransportConnectionCloseOnResponse(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(hostPortHandler)
 	defer ts.Close()
 
+	connSet, testDial := makeTestDial(t)
+
 	for _, connectionClose := range []bool{false, true} {
-		tr := &Transport{}
+		tr := &Transport{
+			Dial: testDial,
+		}
 		c := &Client{Transport: tr}
 
 		fetch := func(n int) string {
@@ -92,8 +163,8 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
 			if err != nil {
 				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
 			}
-			body, err := ioutil.ReadAll(res.Body)
 			defer res.Body.Close()
+			body, err := ioutil.ReadAll(res.Body)
 			if err != nil {
 				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
 			}
@@ -107,15 +178,24 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
 			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
 				connectionClose, bodiesDiffer, body1, body2)
 		}
+
+		tr.CloseIdleConnections()
 	}
+
+	connSet.check(t)
 }
 
 func TestTransportConnectionCloseOnRequest(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(hostPortHandler)
 	defer ts.Close()
 
+	connSet, testDial := makeTestDial(t)
+
 	for _, connectionClose := range []bool{false, true} {
-		tr := &Transport{}
+		tr := &Transport{
+			Dial: testDial,
+		}
 		c := &Client{Transport: tr}
 
 		fetch := func(n int) string {
@@ -149,10 +229,15 @@ func TestTransportConnectionCloseOnRequest(t *testing.T) {
 			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
 				connectionClose, bodiesDiffer, body1, body2)
 		}
+
+		tr.CloseIdleConnections()
 	}
+
+	connSet.check(t)
 }
 
 func TestTransportIdleCacheKeys(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(hostPortHandler)
 	defer ts.Close()
 
@@ -185,6 +270,7 @@ func TestTransportIdleCacheKeys(t *testing.T) {
 }
 
 func TestTransportMaxPerHostIdleConns(t *testing.T) {
+	defer checkLeakedTransports(t)
 	resch := make(chan string)
 	gotReq := make(chan bool)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -201,7 +287,7 @@ func TestTransportMaxPerHostIdleConns(t *testing.T) {
 	c := &Client{Transport: tr}
 
 	// Start 3 outstanding requests and wait for the server to get them.
-	// Their responses will hang until we we write to resch, though.
+	// Their responses will hang until we write to resch, though.
 	donech := make(chan bool)
 	doReq := func() {
 		resp, err := c.Get(ts.URL)
@@ -253,6 +339,7 @@ func TestTransportMaxPerHostIdleConns(t *testing.T) {
 }
 
 func TestTransportServerClosingUnexpectedly(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(hostPortHandler)
 	defer ts.Close()
 
@@ -309,9 +396,9 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) {
 // Test for http://golang.org/issue/2616 (appropriate issue number)
 // This fails pretty reliably with GOMAXPROCS=100 or something high.
 func TestStressSurpriseServerCloses(t *testing.T) {
+	defer checkLeakedTransports(t)
 	if testing.Short() {
-		t.Logf("skipping test in short mode")
-		return
+		t.Skip("skipping test in short mode")
 	}
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header().Set("Content-Length", "5")
@@ -365,6 +452,7 @@ func TestStressSurpriseServerCloses(t *testing.T) {
 // TestTransportHeadResponses verifies that we deal with Content-Lengths
 // with no bodies properly
 func TestTransportHeadResponses(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		if r.Method != "HEAD" {
 			panic("expected HEAD; got " + r.Method)
@@ -384,7 +472,7 @@ func TestTransportHeadResponses(t *testing.T) {
 		if e, g := "123", res.Header.Get("Content-Length"); e != g {
 			t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g)
 		}
-		if e, g := int64(0), res.ContentLength; e != g {
+		if e, g := int64(123), res.ContentLength; e != g {
 			t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g)
 		}
 	}
@@ -393,6 +481,7 @@ func TestTransportHeadResponses(t *testing.T) {
 // TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
 // on responses to HEAD requests.
 func TestTransportHeadChunkedResponse(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		if r.Method != "HEAD" {
 			panic("expected HEAD; got " + r.Method)
@@ -434,6 +523,7 @@ var roundTripTests = []struct {
 
 // Test that the modification made to the Request by the RoundTripper is cleaned up
 func TestRoundTripGzip(t *testing.T) {
+	defer checkLeakedTransports(t)
 	const responseBody = "test response body"
 	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
 		accept := req.Header.Get("Accept-Encoding")
@@ -490,6 +580,7 @@ func TestRoundTripGzip(t *testing.T) {
 }
 
 func TestTransportGzip(t *testing.T) {
+	defer checkLeakedTransports(t)
 	const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
 	const nRandBytes = 1024 * 1024
 	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
@@ -582,6 +673,7 @@ func TestTransportGzip(t *testing.T) {
 }
 
 func TestTransportProxy(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ch := make(chan string, 1)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		ch <- "real server"
@@ -610,6 +702,7 @@ func TestTransportProxy(t *testing.T) {
 // but checks that we don't recurse forever, and checks that
 // Content-Encoding is removed.
 func TestTransportGzipRecursive(t *testing.T) {
+	defer checkLeakedTransports(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header().Set("Content-Encoding", "gzip")
 		w.Write(rgz)
@@ -636,6 +729,7 @@ func TestTransportGzipRecursive(t *testing.T) {
 
 // tests that persistent goroutine connections shut down when no longer desired.
 func TestTransportPersistConnLeak(t *testing.T) {
+	defer checkLeakedTransports(t)
 	gotReqCh := make(chan bool)
 	unblockCh := make(chan bool)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -698,8 +792,49 @@ func TestTransportPersistConnLeak(t *testing.T) {
 	}
 }
 
+// golang.org/issue/4531: Transport leaks goroutines when
+// request.ContentLength is explicitly short
+func TestTransportPersistConnLeakShortBody(t *testing.T) {
+	defer checkLeakedTransports(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	}))
+	defer ts.Close()
+
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+
+	n0 := runtime.NumGoroutine()
+	body := []byte("Hello")
+	for i := 0; i < 20; i++ {
+		req, err := NewRequest("POST", ts.URL, bytes.NewReader(body))
+		if err != nil {
+			t.Fatal(err)
+		}
+		req.ContentLength = int64(len(body) - 2) // explicitly short
+		_, err = c.Do(req)
+		if err == nil {
+			t.Fatal("Expect an error from writing too long of a body.")
+		}
+	}
+	nhigh := runtime.NumGoroutine()
+	tr.CloseIdleConnections()
+	time.Sleep(50 * time.Millisecond)
+	runtime.GC()
+	nfinal := runtime.NumGoroutine()
+
+	growth := nfinal - n0
+
+	// We expect 0 or 1 extra goroutine, empirically.  Allow up to 5.
+	// Previously we were leaking one per numReq.
+	t.Logf("goroutine growth: %d -> %d -> %d (delta: %d)", n0, nhigh, nfinal, growth)
+	if int(growth) > 5 {
+		t.Error("too many new goroutines")
+	}
+}
+
 // This used to crash; http://golang.org/issue/3266
 func TestTransportIdleConnCrash(t *testing.T) {
+	defer checkLeakedTransports(t)
 	tr := &Transport{}
 	c := &Client{Transport: tr}
 
@@ -724,6 +859,361 @@ func TestTransportIdleConnCrash(t *testing.T) {
 	<-didreq
 }
 
+// Test that the transport doesn't close the TCP connection early,
+// before the response body has been read.  This was a regression
+// which sadly lacked a triggering test.  The large response body made
+// the old race easier to trigger.
+func TestIssue3644(t *testing.T) {
+	defer checkLeakedTransports(t)
+	const numFoos = 5000
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Connection", "close")
+		for i := 0; i < numFoos; i++ {
+			w.Write([]byte("foo "))
+		}
+	}))
+	defer ts.Close()
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+	res, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer res.Body.Close()
+	bs, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(bs) != numFoos*len("foo ") {
+		t.Errorf("unexpected response length")
+	}
+}
+
+// Test that a client receives a server's reply, even if the server doesn't read
+// the entire request body.
+func TestIssue3595(t *testing.T) {
+	defer checkLeakedTransports(t)
+	const deniedMsg = "sorry, denied."
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		Error(w, deniedMsg, StatusUnauthorized)
+	}))
+	defer ts.Close()
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+	res, err := c.Post(ts.URL, "application/octet-stream", neverEnding('a'))
+	if err != nil {
+		t.Errorf("Post: %v", err)
+		return
+	}
+	got, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatalf("Body ReadAll: %v", err)
+	}
+	if !strings.Contains(string(got), deniedMsg) {
+		t.Errorf("Known bug: response %q does not contain %q", got, deniedMsg)
+	}
+}
+
+// From http://golang.org/issue/4454 ,
+// "client fails to handle requests with no body and chunked encoding"
+func TestChunkedNoContent(t *testing.T) {
+	defer checkLeakedTransports(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.WriteHeader(StatusNoContent)
+	}))
+	defer ts.Close()
+
+	for _, closeBody := range []bool{true, false} {
+		c := &Client{Transport: &Transport{}}
+		const n = 4
+		for i := 1; i <= n; i++ {
+			res, err := c.Get(ts.URL)
+			if err != nil {
+				t.Errorf("closingBody=%v, req %d/%d: %v", closeBody, i, n, err)
+			} else {
+				if closeBody {
+					res.Body.Close()
+				}
+			}
+		}
+	}
+}
+
+func TestTransportConcurrency(t *testing.T) {
+	defer checkLeakedTransports(t)
+	const maxProcs = 16
+	const numReqs = 500
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "%v", r.FormValue("echo"))
+	}))
+	defer ts.Close()
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+	reqs := make(chan string)
+	defer close(reqs)
+
+	var wg sync.WaitGroup
+	wg.Add(numReqs)
+	for i := 0; i < maxProcs*2; i++ {
+		go func() {
+			for req := range reqs {
+				res, err := c.Get(ts.URL + "/?echo=" + req)
+				if err != nil {
+					t.Errorf("error on req %s: %v", req, err)
+					wg.Done()
+					continue
+				}
+				all, err := ioutil.ReadAll(res.Body)
+				if err != nil {
+					t.Errorf("read error on req %s: %v", req, err)
+					wg.Done()
+					continue
+				}
+				if string(all) != req {
+					t.Errorf("body of req %s = %q; want %q", req, all, req)
+				}
+				wg.Done()
+				res.Body.Close()
+			}
+		}()
+	}
+	for i := 0; i < numReqs; i++ {
+		reqs <- fmt.Sprintf("request-%d", i)
+	}
+	wg.Wait()
+}
+
+func TestIssue4191_InfiniteGetTimeout(t *testing.T) {
+	defer checkLeakedTransports(t)
+	const debug = false
+	mux := NewServeMux()
+	mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
+		io.Copy(w, neverEnding('a'))
+	})
+	ts := httptest.NewServer(mux)
+	timeout := 100 * time.Millisecond
+
+	client := &Client{
+		Transport: &Transport{
+			Dial: func(n, addr string) (net.Conn, error) {
+				conn, err := net.Dial(n, addr)
+				if err != nil {
+					return nil, err
+				}
+				conn.SetDeadline(time.Now().Add(timeout))
+				if debug {
+					conn = NewLoggingConn("client", conn)
+				}
+				return conn, nil
+			},
+			DisableKeepAlives: true,
+		},
+	}
+
+	getFailed := false
+	nRuns := 5
+	if testing.Short() {
+		nRuns = 1
+	}
+	for i := 0; i < nRuns; i++ {
+		if debug {
+			println("run", i+1, "of", nRuns)
+		}
+		sres, err := client.Get(ts.URL + "/get")
+		if err != nil {
+			if !getFailed {
+				// Make the timeout longer, once.
+				getFailed = true
+				t.Logf("increasing timeout")
+				i--
+				timeout *= 10
+				continue
+			}
+			t.Errorf("Error issuing GET: %v", err)
+			break
+		}
+		_, err = io.Copy(ioutil.Discard, sres.Body)
+		if err == nil {
+			t.Errorf("Unexpected successful copy")
+			break
+		}
+	}
+	if debug {
+		println("tests complete; waiting for handlers to finish")
+	}
+	ts.Close()
+}
+
+func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) {
+	defer checkLeakedTransports(t)
+	const debug = false
+	mux := NewServeMux()
+	mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
+		io.Copy(w, neverEnding('a'))
+	})
+	mux.HandleFunc("/put", func(w ResponseWriter, r *Request) {
+		defer r.Body.Close()
+		io.Copy(ioutil.Discard, r.Body)
+	})
+	ts := httptest.NewServer(mux)
+	timeout := 100 * time.Millisecond
+
+	client := &Client{
+		Transport: &Transport{
+			Dial: func(n, addr string) (net.Conn, error) {
+				conn, err := net.Dial(n, addr)
+				if err != nil {
+					return nil, err
+				}
+				conn.SetDeadline(time.Now().Add(timeout))
+				if debug {
+					conn = NewLoggingConn("client", conn)
+				}
+				return conn, nil
+			},
+			DisableKeepAlives: true,
+		},
+	}
+
+	getFailed := false
+	nRuns := 5
+	if testing.Short() {
+		nRuns = 1
+	}
+	for i := 0; i < nRuns; i++ {
+		if debug {
+			println("run", i+1, "of", nRuns)
+		}
+		sres, err := client.Get(ts.URL + "/get")
+		if err != nil {
+			if !getFailed {
+				// Make the timeout longer, once.
+				getFailed = true
+				t.Logf("increasing timeout")
+				i--
+				timeout *= 10
+				continue
+			}
+			t.Errorf("Error issuing GET: %v", err)
+			break
+		}
+		req, _ := NewRequest("PUT", ts.URL+"/put", sres.Body)
+		_, err = client.Do(req)
+		if err == nil {
+			sres.Body.Close()
+			t.Errorf("Unexpected successful PUT")
+			break
+		}
+		sres.Body.Close()
+	}
+	if debug {
+		println("tests complete; waiting for handlers to finish")
+	}
+	ts.Close()
+}
+
+func TestTransportResponseHeaderTimeout(t *testing.T) {
+	defer checkLeakedTransports(t)
+	if testing.Short() {
+		t.Skip("skipping timeout test in -short mode")
+	}
+	mux := NewServeMux()
+	mux.HandleFunc("/fast", func(w ResponseWriter, r *Request) {})
+	mux.HandleFunc("/slow", func(w ResponseWriter, r *Request) {
+		time.Sleep(2 * time.Second)
+	})
+	ts := httptest.NewServer(mux)
+	defer ts.Close()
+
+	tr := &Transport{
+		ResponseHeaderTimeout: 500 * time.Millisecond,
+	}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	tests := []struct {
+		path    string
+		want    int
+		wantErr string
+	}{
+		{path: "/fast", want: 200},
+		{path: "/slow", wantErr: "timeout awaiting response headers"},
+		{path: "/fast", want: 200},
+	}
+	for i, tt := range tests {
+		res, err := c.Get(ts.URL + tt.path)
+		if err != nil {
+			if strings.Contains(err.Error(), tt.wantErr) {
+				continue
+			}
+			t.Errorf("%d. unexpected error: %v", i, err)
+			continue
+		}
+		if tt.wantErr != "" {
+			t.Errorf("%d. no error. expected error: %v", i, tt.wantErr)
+			continue
+		}
+		if res.StatusCode != tt.want {
+			t.Errorf("%d for path %q status = %d; want %d", i, tt.path, res.StatusCode, tt.want)
+		}
+	}
+}
+
+func TestTransportCancelRequest(t *testing.T) {
+	defer checkLeakedTransports(t)
+	if testing.Short() {
+		t.Skip("skipping test in -short mode")
+	}
+	unblockc := make(chan bool)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "Hello")
+		w.(Flusher).Flush() // send headers and some body
+		<-unblockc
+	}))
+	defer ts.Close()
+	defer close(unblockc)
+
+	tr := &Transport{}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr}
+
+	req, _ := NewRequest("GET", ts.URL, nil)
+	res, err := c.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	go func() {
+		time.Sleep(1 * time.Second)
+		tr.CancelRequest(req)
+	}()
+	t0 := time.Now()
+	body, err := ioutil.ReadAll(res.Body)
+	d := time.Since(t0)
+
+	if err == nil {
+		t.Error("expected an error reading the body")
+	}
+	if string(body) != "Hello" {
+		t.Errorf("Body = %q; want Hello", body)
+	}
+	if d < 500*time.Millisecond {
+		t.Errorf("expected ~1 second delay; got %v", d)
+	}
+	// Verify no outstanding requests after readLoop/writeLoop
+	// goroutines shut down.
+	for tries := 3; tries > 0; tries-- {
+		n := tr.NumPendingRequestsForTesting()
+		if n == 0 {
+			break
+		}
+		time.Sleep(100 * time.Millisecond)
+		if tries == 1 {
+			t.Errorf("pending requests = %d; want 0", n)
+		}
+	}
+}
+
 type fooProto struct{}
 
 func (fooProto) RoundTrip(req *Request) (*Response, error) {
@@ -737,6 +1227,7 @@ func (fooProto) RoundTrip(req *Request) (*Response, error) {
 }
 
 func TestTransportAltProto(t *testing.T) {
+	defer checkLeakedTransports(t)
 	tr := &Transport{}
 	c := &Client{Transport: tr}
 	tr.RegisterProtocol("foo", fooProto{})
@@ -754,15 +1245,58 @@ func TestTransportAltProto(t *testing.T) {
 	}
 }
 
-var proxyFromEnvTests = []struct {
+func TestTransportNoHost(t *testing.T) {
+	defer checkLeakedTransports(t)
+	tr := &Transport{}
+	_, err := tr.RoundTrip(&Request{
+		Header: make(Header),
+		URL: &url.URL{
+			Scheme: "http",
+		},
+	})
+	want := "http: no Host in request URL"
+	if got := fmt.Sprint(err); got != want {
+		t.Errorf("error = %v; want %q", err, want)
+	}
+}
+
+type proxyFromEnvTest struct {
+	req     string // URL to fetch; blank means "http://example.com"
 	env     string
-	wanturl string
+	noenv   string
+	want    string
 	wanterr error
-}{
-	{"127.0.0.1:8080", "http://127.0.0.1:8080", nil},
-	{"http://127.0.0.1:8080", "http://127.0.0.1:8080", nil},
-	{"https://127.0.0.1:8080", "https://127.0.0.1:8080", nil},
-	{"", "<nil>", nil},
+}
+
+func (t proxyFromEnvTest) String() string {
+	var buf bytes.Buffer
+	if t.env != "" {
+		fmt.Fprintf(&buf, "http_proxy=%q", t.env)
+	}
+	if t.noenv != "" {
+		fmt.Fprintf(&buf, " no_proxy=%q", t.noenv)
+	}
+	req := "http://example.com"
+	if t.req != "" {
+		req = t.req
+	}
+	fmt.Fprintf(&buf, " req=%q", req)
+	return strings.TrimSpace(buf.String())
+}
+
+var proxyFromEnvTests = []proxyFromEnvTest{
+	{env: "127.0.0.1:8080", want: "http://127.0.0.1:8080"},
+	{env: "cache.corp.example.com:1234", want: "http://cache.corp.example.com:1234"},
+	{env: "cache.corp.example.com", want: "http://cache.corp.example.com"},
+	{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"},
+	{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"},
+	{noenv: "example.com", req: "http://foo.example.com/", env: "proxy", want: "<nil>"},
+	{noenv: ".foo.com", req: "http://example.com/", env: "proxy", want: "http://proxy"},
 }
 
 func TestProxyFromEnvironment(t *testing.T) {
@@ -770,16 +1304,21 @@ func TestProxyFromEnvironment(t *testing.T) {
 	os.Setenv("http_proxy", "")
 	os.Setenv("NO_PROXY", "")
 	os.Setenv("no_proxy", "")
-	for i, tt := range proxyFromEnvTests {
+	for _, tt := range proxyFromEnvTests {
 		os.Setenv("HTTP_PROXY", tt.env)
-		req, _ := NewRequest("GET", "http://example.com", nil)
+		os.Setenv("NO_PROXY", tt.noenv)
+		reqURL := tt.req
+		if reqURL == "" {
+			reqURL = "http://example.com"
+		}
+		req, _ := NewRequest("GET", reqURL, nil)
 		url, err := ProxyFromEnvironment(req)
 		if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
-			t.Errorf("%d. got error = %q, want %q", i, g, e)
+			t.Errorf("%v: got error = %q, want %q", tt, g, e)
 			continue
 		}
-		if got := fmt.Sprintf("%s", url); got != tt.wanturl {
-			t.Errorf("%d. got URL = %q, want %q", i, url, tt.wanturl)
+		if got := fmt.Sprintf("%s", url); got != tt.want {
+			t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
 		}
 	}
 }
diff --git a/src/pkg/net/http/z_last_test.go b/src/pkg/net/http/z_last_test.go
new file mode 100644
index 0000000..44095a8
--- /dev/null
+++ b/src/pkg/net/http/z_last_test.go
@@ -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.
+
+package http_test
+
+import (
+	"net/http"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+// 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) {
+	n := runtime.NumGoroutine()
+	t.Logf("num goroutines = %d", n)
+	if n > 20 {
+		// Currently 14 on Linux (blocked in epoll_wait,
+		// waiting for on fds that are closed?), but give some
+		// slop for now.
+		buf := make([]byte, 1<<20)
+		buf = buf[:runtime.Stack(buf, true)]
+		t.Errorf("Too many goroutines:\n%s", buf)
+	}
+}
+
+func checkLeakedTransports(t *testing.T) {
+	http.DefaultTransport.(*http.Transport).CloseIdleConnections()
+	if testing.Short() {
+		return
+	}
+	buf := make([]byte, 1<<20)
+	var stacks string
+	var bad string
+	badSubstring := map[string]string{
+		").readLoop(":                                  "a Transport",
+		").writeLoop(":                                 "a Transport",
+		"created by net/http/httptest.(*Server).Start": "an httptest.Server",
+		"timeoutHandler":                               "a TimeoutHandler",
+	}
+	for i := 0; i < 4; i++ {
+		bad = ""
+		stacks = string(buf[:runtime.Stack(buf, true)])
+		for substr, what := range badSubstring {
+			if strings.Contains(stacks, substr) {
+				bad = what
+			}
+		}
+		if bad == "" {
+			return
+		}
+		// Bad stuff found, but goroutines might just still be
+		// shutting down, so give it some time.
+		time.Sleep(250 * time.Millisecond)
+	}
+	t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks)
+}
diff --git a/src/pkg/net/interface.go b/src/pkg/net/interface.go
index ee23570..0713e9c 100644
--- a/src/pkg/net/interface.go
+++ b/src/pkg/net/interface.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.
 
-// Network interface identification
-
 package net
 
 import "errors"
@@ -66,7 +64,7 @@ func (ifi *Interface) Addrs() ([]Addr, error) {
 	if ifi == nil {
 		return nil, errInvalidInterface
 	}
-	return interfaceAddrTable(ifi.Index)
+	return interfaceAddrTable(ifi)
 }
 
 // MulticastAddrs returns multicast, joined group addresses for
@@ -75,7 +73,7 @@ func (ifi *Interface) MulticastAddrs() ([]Addr, error) {
 	if ifi == nil {
 		return nil, errInvalidInterface
 	}
-	return interfaceMulticastAddrTable(ifi.Index)
+	return interfaceMulticastAddrTable(ifi)
 }
 
 // Interfaces returns a list of the system's network interfaces.
@@ -86,7 +84,7 @@ func Interfaces() ([]Interface, error) {
 // InterfaceAddrs returns a list of the system's network interface
 // addresses.
 func InterfaceAddrs() ([]Addr, error) {
-	return interfaceAddrTable(0)
+	return interfaceAddrTable(nil)
 }
 
 // InterfaceByIndex returns the interface specified by index.
@@ -98,8 +96,14 @@ func InterfaceByIndex(index int) (*Interface, error) {
 	if err != nil {
 		return nil, err
 	}
+	return interfaceByIndex(ift, index)
+}
+
+func interfaceByIndex(ift []Interface, index int) (*Interface, error) {
 	for _, ifi := range ift {
-		return &ifi, nil
+		if index == ifi.Index {
+			return &ifi, nil
+		}
 	}
 	return nil, errNoSuchInterface
 }
diff --git a/src/pkg/net/interface_bsd.go b/src/pkg/net/interface_bsd.go
index 7f090d8..f58065a 100644
--- a/src/pkg/net/interface_bsd.go
+++ b/src/pkg/net/interface_bsd.go
@@ -4,8 +4,6 @@
 
 // +build darwin freebsd netbsd openbsd
 
-// Network interface identification for BSD variants
-
 package net
 
 import (
@@ -22,57 +20,60 @@ func interfaceTable(ifindex int) ([]Interface, error) {
 	if err != nil {
 		return nil, os.NewSyscallError("route rib", err)
 	}
-
 	msgs, err := syscall.ParseRoutingMessage(tab)
 	if err != nil {
 		return nil, os.NewSyscallError("route message", err)
 	}
+	return parseInterfaceTable(ifindex, msgs)
+}
 
+func parseInterfaceTable(ifindex int, msgs []syscall.RoutingMessage) ([]Interface, error) {
 	var ift []Interface
+loop:
 	for _, m := range msgs {
-		switch v := m.(type) {
+		switch m := m.(type) {
 		case *syscall.InterfaceMessage:
-			if ifindex == 0 || ifindex == int(v.Header.Index) {
-				ifi, err := newLink(v)
+			if ifindex == 0 || ifindex == int(m.Header.Index) {
+				ifi, err := newLink(m)
 				if err != nil {
 					return nil, err
 				}
-				ift = append(ift, ifi...)
+				ift = append(ift, *ifi)
+				if ifindex == int(m.Header.Index) {
+					break loop
+				}
 			}
 		}
 	}
 	return ift, nil
 }
 
-func newLink(m *syscall.InterfaceMessage) ([]Interface, error) {
+func newLink(m *syscall.InterfaceMessage) (*Interface, error) {
 	sas, err := syscall.ParseRoutingSockaddr(m)
 	if err != nil {
 		return nil, os.NewSyscallError("route sockaddr", err)
 	}
-
-	var ift []Interface
-	for _, s := range sas {
-		switch v := s.(type) {
+	ifi := &Interface{Index: int(m.Header.Index), Flags: linkFlags(m.Header.Flags)}
+	for _, sa := range sas {
+		switch sa := sa.(type) {
 		case *syscall.SockaddrDatalink:
 			// NOTE: SockaddrDatalink.Data is minimum work area,
 			// can be larger.
-			m.Data = m.Data[unsafe.Offsetof(v.Data):]
-			ifi := Interface{Index: int(m.Header.Index), Flags: linkFlags(m.Header.Flags)}
+			m.Data = m.Data[unsafe.Offsetof(sa.Data):]
 			var name [syscall.IFNAMSIZ]byte
-			for i := 0; i < int(v.Nlen); i++ {
+			for i := 0; i < int(sa.Nlen); i++ {
 				name[i] = byte(m.Data[i])
 			}
-			ifi.Name = string(name[:v.Nlen])
+			ifi.Name = string(name[:sa.Nlen])
 			ifi.MTU = int(m.Header.Data.Mtu)
-			addr := make([]byte, v.Alen)
-			for i := 0; i < int(v.Alen); i++ {
-				addr[i] = byte(m.Data[int(v.Nlen)+i])
+			addr := make([]byte, sa.Alen)
+			for i := 0; i < int(sa.Alen); i++ {
+				addr[i] = byte(m.Data[int(sa.Nlen)+i])
 			}
-			ifi.HardwareAddr = addr[:v.Alen]
-			ift = append(ift, ifi)
+			ifi.HardwareAddr = addr[:sa.Alen]
 		}
 	}
-	return ift, nil
+	return ifi, nil
 }
 
 func linkFlags(rawFlags int32) Flags {
@@ -95,68 +96,87 @@ func linkFlags(rawFlags int32) Flags {
 	return f
 }
 
-// If the ifindex is zero, interfaceAddrTable returns addresses
-// for all network interfaces.  Otherwise it returns addresses
-// for a specific interface.
-func interfaceAddrTable(ifindex int) ([]Addr, error) {
-	tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
+// If the ifi is nil, interfaceAddrTable returns addresses for all
+// network interfaces.  Otherwise it returns addresses for a specific
+// interface.
+func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
+	index := 0
+	if ifi != nil {
+		index = ifi.Index
+	}
+	tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, index)
 	if err != nil {
 		return nil, os.NewSyscallError("route rib", err)
 	}
-
 	msgs, err := syscall.ParseRoutingMessage(tab)
 	if err != nil {
 		return nil, os.NewSyscallError("route message", err)
 	}
-
+	var ift []Interface
+	if index == 0 {
+		ift, err = parseInterfaceTable(index, msgs)
+		if err != nil {
+			return nil, err
+		}
+	}
 	var ifat []Addr
 	for _, m := range msgs {
-		switch v := m.(type) {
+		switch m := m.(type) {
 		case *syscall.InterfaceAddrMessage:
-			if ifindex == 0 || ifindex == int(v.Header.Index) {
-				ifa, err := newAddr(v)
+			if index == 0 || index == int(m.Header.Index) {
+				if index == 0 {
+					var err error
+					ifi, err = interfaceByIndex(ift, int(m.Header.Index))
+					if err != nil {
+						return nil, err
+					}
+				}
+				ifa, err := newAddr(ifi, m)
 				if err != nil {
 					return nil, err
 				}
-				ifat = append(ifat, ifa)
+				if ifa != nil {
+					ifat = append(ifat, ifa)
+				}
 			}
 		}
 	}
 	return ifat, nil
 }
 
-func newAddr(m *syscall.InterfaceAddrMessage) (Addr, error) {
+func newAddr(ifi *Interface, m *syscall.InterfaceAddrMessage) (Addr, error) {
 	sas, err := syscall.ParseRoutingSockaddr(m)
 	if err != nil {
 		return nil, os.NewSyscallError("route sockaddr", err)
 	}
-
 	ifa := &IPNet{}
-	for i, s := range sas {
-		switch v := s.(type) {
+	for i, sa := range sas {
+		switch sa := sa.(type) {
 		case *syscall.SockaddrInet4:
 			switch i {
 			case 0:
-				ifa.Mask = IPv4Mask(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
+				ifa.Mask = IPv4Mask(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
 			case 1:
-				ifa.IP = IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
+				ifa.IP = IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
 			}
 		case *syscall.SockaddrInet6:
 			switch i {
 			case 0:
 				ifa.Mask = make(IPMask, IPv6len)
-				copy(ifa.Mask, v.Addr[:])
+				copy(ifa.Mask, sa.Addr[:])
 			case 1:
 				ifa.IP = make(IP, IPv6len)
-				copy(ifa.IP, v.Addr[:])
+				copy(ifa.IP, sa.Addr[:])
 				// NOTE: KAME based IPv6 protcol stack usually embeds
 				// the interface index in the interface-local or link-
 				// local address as the kernel-internal form.
 				if ifa.IP.IsLinkLocalUnicast() {
-					// remove embedded scope zone ID
+					ifa.Zone = ifi.Name
 					ifa.IP[2], ifa.IP[3] = 0, 0
 				}
 			}
+		default: // Sockaddrs contain syscall.SockaddrDatalink on NetBSD
+			return nil, nil
 		}
 	}
 	return ifa, nil
diff --git a/src/pkg/net/interface_bsd_test.go b/src/pkg/net/interface_bsd_test.go
new file mode 100644
index 0000000..aa11419
--- /dev/null
+++ b/src/pkg/net/interface_bsd_test.go
@@ -0,0 +1,52 @@
+// 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 freebsd netbsd openbsd
+
+package net
+
+import (
+	"fmt"
+	"os/exec"
+)
+
+func (ti *testInterface) setBroadcast(suffix int) error {
+	ti.name = fmt.Sprintf("vlan%d", suffix)
+	xname, err := exec.LookPath("ifconfig")
+	if err != nil {
+		return err
+	}
+	ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+		Path: xname,
+		Args: []string{"ifconfig", ti.name, "create"},
+	})
+	ti.teardownCmds = append(ti.teardownCmds, &exec.Cmd{
+		Path: xname,
+		Args: []string{"ifconfig", ti.name, "destroy"},
+	})
+	return nil
+}
+
+func (ti *testInterface) setPointToPoint(suffix int, local, remote string) error {
+	ti.name = fmt.Sprintf("gif%d", suffix)
+	ti.local = local
+	ti.remote = remote
+	xname, err := exec.LookPath("ifconfig")
+	if err != nil {
+		return err
+	}
+	ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+		Path: xname,
+		Args: []string{"ifconfig", ti.name, "create"},
+	})
+	ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+		Path: xname,
+		Args: []string{"ifconfig", ti.name, "inet", ti.local, ti.remote},
+	})
+	ti.teardownCmds = append(ti.teardownCmds, &exec.Cmd{
+		Path: xname,
+		Args: []string{"ifconfig", ti.name, "destroy"},
+	})
+	return nil
+}
diff --git a/src/pkg/net/interface_darwin.go b/src/pkg/net/interface_darwin.go
index 0b5fb5f..83e483b 100644
--- a/src/pkg/net/interface_darwin.go
+++ b/src/pkg/net/interface_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.
 
-// Network interface identification for Darwin
-
 package net
 
 import (
@@ -11,26 +9,23 @@ import (
 	"syscall"
 )
 
-// If the ifindex is zero, interfaceMulticastAddrTable returns
-// addresses for all network interfaces.  Otherwise it returns
-// addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
-	tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifindex)
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifi.Index)
 	if err != nil {
 		return nil, os.NewSyscallError("route rib", err)
 	}
-
 	msgs, err := syscall.ParseRoutingMessage(tab)
 	if err != nil {
 		return nil, os.NewSyscallError("route message", err)
 	}
-
 	var ifmat []Addr
 	for _, m := range msgs {
-		switch v := m.(type) {
+		switch m := m.(type) {
 		case *syscall.InterfaceMulticastAddrMessage:
-			if ifindex == 0 || ifindex == int(v.Header.Index) {
-				ifma, err := newMulticastAddr(v)
+			if ifi.Index == int(m.Header.Index) {
+				ifma, err := newMulticastAddr(ifi, m)
 				if err != nil {
 					return nil, err
 				}
@@ -41,27 +36,25 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
 	return ifmat, nil
 }
 
-func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) {
+func newMulticastAddr(ifi *Interface, m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) {
 	sas, err := syscall.ParseRoutingSockaddr(m)
 	if err != nil {
 		return nil, os.NewSyscallError("route sockaddr", err)
 	}
-
 	var ifmat []Addr
-	for _, s := range sas {
-		switch v := s.(type) {
+	for _, sa := range sas {
+		switch sa := sa.(type) {
 		case *syscall.SockaddrInet4:
-			ifma := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])}
+			ifma := &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])}
 			ifmat = append(ifmat, ifma.toAddr())
 		case *syscall.SockaddrInet6:
 			ifma := &IPAddr{IP: make(IP, IPv6len)}
-			copy(ifma.IP, v.Addr[:])
+			copy(ifma.IP, sa.Addr[:])
 			// NOTE: KAME based IPv6 protcol stack usually embeds
 			// the interface index in the interface-local or link-
 			// local address as the kernel-internal form.
-			if ifma.IP.IsInterfaceLocalMulticast() ||
-				ifma.IP.IsLinkLocalMulticast() {
-				// remove embedded scope zone ID
+			if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
+				ifma.Zone = ifi.Name
 				ifma.IP[2], ifma.IP[3] = 0, 0
 			}
 			ifmat = append(ifmat, ifma.toAddr())
diff --git a/src/pkg/net/interface_freebsd.go b/src/pkg/net/interface_freebsd.go
index 3cba28f..1bf5ae7 100644
--- a/src/pkg/net/interface_freebsd.go
+++ b/src/pkg/net/interface_freebsd.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.
 
-// Network interface identification for FreeBSD
-
 package net
 
 import (
@@ -11,26 +9,23 @@ import (
 	"syscall"
 )
 
-// If the ifindex is zero, interfaceMulticastAddrTable returns
-// addresses for all network interfaces.  Otherwise it returns
-// addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
-	tab, err := syscall.RouteRIB(syscall.NET_RT_IFMALIST, ifindex)
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	tab, err := syscall.RouteRIB(syscall.NET_RT_IFMALIST, ifi.Index)
 	if err != nil {
 		return nil, os.NewSyscallError("route rib", err)
 	}
-
 	msgs, err := syscall.ParseRoutingMessage(tab)
 	if err != nil {
 		return nil, os.NewSyscallError("route message", err)
 	}
-
 	var ifmat []Addr
 	for _, m := range msgs {
-		switch v := m.(type) {
+		switch m := m.(type) {
 		case *syscall.InterfaceMulticastAddrMessage:
-			if ifindex == 0 || ifindex == int(v.Header.Index) {
-				ifma, err := newMulticastAddr(v)
+			if ifi.Index == int(m.Header.Index) {
+				ifma, err := newMulticastAddr(ifi, m)
 				if err != nil {
 					return nil, err
 				}
@@ -41,27 +36,25 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
 	return ifmat, nil
 }
 
-func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) {
+func newMulticastAddr(ifi *Interface, m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) {
 	sas, err := syscall.ParseRoutingSockaddr(m)
 	if err != nil {
 		return nil, os.NewSyscallError("route sockaddr", err)
 	}
-
 	var ifmat []Addr
-	for _, s := range sas {
-		switch v := s.(type) {
+	for _, sa := range sas {
+		switch sa := sa.(type) {
 		case *syscall.SockaddrInet4:
-			ifma := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])}
+			ifma := &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])}
 			ifmat = append(ifmat, ifma.toAddr())
 		case *syscall.SockaddrInet6:
 			ifma := &IPAddr{IP: make(IP, IPv6len)}
-			copy(ifma.IP, v.Addr[:])
+			copy(ifma.IP, sa.Addr[:])
 			// NOTE: KAME based IPv6 protcol stack usually embeds
 			// the interface index in the interface-local or link-
 			// local address as the kernel-internal form.
-			if ifma.IP.IsInterfaceLocalMulticast() ||
-				ifma.IP.IsLinkLocalMulticast() {
-				// remove embedded scope zone ID
+			if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
+				ifma.Zone = ifi.Name
 				ifma.IP[2], ifma.IP[3] = 0, 0
 			}
 			ifmat = append(ifmat, ifma.toAddr())
diff --git a/src/pkg/net/interface_linux.go b/src/pkg/net/interface_linux.go
index 825b202..e66daef 100644
--- a/src/pkg/net/interface_linux.go
+++ b/src/pkg/net/interface_linux.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.
 
-// Network interface identification for Linux
-
 package net
 
 import (
@@ -20,17 +18,16 @@ func interfaceTable(ifindex int) ([]Interface, error) {
 	if err != nil {
 		return nil, os.NewSyscallError("netlink rib", err)
 	}
-
 	msgs, err := syscall.ParseNetlinkMessage(tab)
 	if err != nil {
 		return nil, os.NewSyscallError("netlink message", err)
 	}
-
 	var ift []Interface
+loop:
 	for _, m := range msgs {
 		switch m.Header.Type {
 		case syscall.NLMSG_DONE:
-			goto done
+			break loop
 		case syscall.RTM_NEWLINK:
 			ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
 			if ifindex == 0 || ifindex == int(ifim.Index) {
@@ -38,17 +35,18 @@ func interfaceTable(ifindex int) ([]Interface, error) {
 				if err != nil {
 					return nil, os.NewSyscallError("netlink routeattr", err)
 				}
-				ifi := newLink(ifim, attrs)
-				ift = append(ift, ifi)
+				ift = append(ift, *newLink(ifim, attrs))
+				if ifindex == int(ifim.Index) {
+					break loop
+				}
 			}
 		}
 	}
-done:
 	return ift, nil
 }
 
-func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) Interface {
-	ifi := Interface{Index: int(ifim.Index), Flags: linkFlags(ifim.Flags)}
+func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) *Interface {
+	ifi := &Interface{Index: int(ifim.Index), Flags: linkFlags(ifim.Flags)}
 	for _, a := range attrs {
 		switch a.Attr.Type {
 		case syscall.IFLA_ADDRESS:
@@ -64,7 +62,7 @@ func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) Interfac
 		case syscall.IFLA_IFNAME:
 			ifi.Name = string(a.Value[:len(a.Value)-1])
 		case syscall.IFLA_MTU:
-			ifi.MTU = int(uint32(a.Value[3])<<24 | uint32(a.Value[2])<<16 | uint32(a.Value[1])<<8 | uint32(a.Value[0]))
+			ifi.MTU = int(*(*uint32)(unsafe.Pointer(&a.Value[:4][0])))
 		}
 	}
 	return ifi
@@ -90,81 +88,87 @@ func linkFlags(rawFlags uint32) Flags {
 	return f
 }
 
-// If the ifindex is zero, interfaceAddrTable returns addresses
-// for all network interfaces.  Otherwise it returns addresses
-// for a specific interface.
-func interfaceAddrTable(ifindex int) ([]Addr, error) {
+// If the ifi is nil, interfaceAddrTable returns addresses for all
+// network interfaces.  Otherwise it returns addresses for a specific
+// interface.
+func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
 	tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
 	if err != nil {
 		return nil, os.NewSyscallError("netlink rib", err)
 	}
-
 	msgs, err := syscall.ParseNetlinkMessage(tab)
 	if err != nil {
 		return nil, os.NewSyscallError("netlink message", err)
 	}
-
-	ifat, err := addrTable(msgs, ifindex)
+	var ift []Interface
+	if ifi == nil {
+		var err error
+		ift, err = interfaceTable(0)
+		if err != nil {
+			return nil, err
+		}
+	}
+	ifat, err := addrTable(ift, ifi, msgs)
 	if err != nil {
 		return nil, err
 	}
 	return ifat, nil
 }
 
-func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) {
+func addrTable(ift []Interface, ifi *Interface, msgs []syscall.NetlinkMessage) ([]Addr, error) {
 	var ifat []Addr
+loop:
 	for _, m := range msgs {
 		switch m.Header.Type {
 		case syscall.NLMSG_DONE:
-			goto done
+			break loop
 		case syscall.RTM_NEWADDR:
 			ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
-			if ifindex == 0 || ifindex == int(ifam.Index) {
+			if len(ift) != 0 || ifi.Index == int(ifam.Index) {
+				if len(ift) != 0 {
+					var err error
+					ifi, err = interfaceByIndex(ift, int(ifam.Index))
+					if err != nil {
+						return nil, err
+					}
+				}
 				attrs, err := syscall.ParseNetlinkRouteAttr(&m)
 				if err != nil {
 					return nil, os.NewSyscallError("netlink routeattr", err)
 				}
-				ifat = append(ifat, newAddr(attrs, int(ifam.Family), int(ifam.Prefixlen)))
+				ifa := newAddr(ifi, ifam, attrs)
+				if ifa != nil {
+					ifat = append(ifat, ifa)
+				}
 			}
 		}
 	}
-done:
 	return ifat, nil
 }
 
-func newAddr(attrs []syscall.NetlinkRouteAttr, family, pfxlen int) Addr {
-	ifa := &IPNet{}
+func newAddr(ifi *Interface, ifam *syscall.IfAddrmsg, attrs []syscall.NetlinkRouteAttr) Addr {
 	for _, a := range attrs {
-		switch a.Attr.Type {
-		case syscall.IFA_ADDRESS:
-			switch family {
+		if ifi.Flags&FlagPointToPoint != 0 && a.Attr.Type == syscall.IFA_LOCAL ||
+			ifi.Flags&FlagPointToPoint == 0 && a.Attr.Type == syscall.IFA_ADDRESS {
+			switch ifam.Family {
 			case syscall.AF_INET:
-				ifa.IP = IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3])
-				ifa.Mask = CIDRMask(pfxlen, 8*IPv4len)
+				return &IPNet{IP: IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3]), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv4len)}
 			case syscall.AF_INET6:
-				ifa.IP = make(IP, IPv6len)
+				ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv6len)}
 				copy(ifa.IP, a.Value[:])
-				ifa.Mask = CIDRMask(pfxlen, 8*IPv6len)
+				if ifam.Scope == syscall.RT_SCOPE_HOST || ifam.Scope == syscall.RT_SCOPE_LINK {
+					ifa.Zone = ifi.Name
+				}
+				return ifa
 			}
 		}
 	}
-	return ifa
+	return nil
 }
 
-// If the ifindex is zero, interfaceMulticastAddrTable returns
-// addresses for all network interfaces.  Otherwise it returns
-// addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
-	var (
-		err error
-		ifi *Interface
-	)
-	if ifindex > 0 {
-		ifi, err = InterfaceByIndex(ifindex)
-		if err != nil {
-			return nil, err
-		}
-	}
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
 	ifmat4 := parseProcNetIGMP("/proc/net/igmp", ifi)
 	ifmat6 := parseProcNetIGMP6("/proc/net/igmp6", ifi)
 	return append(ifmat4, ifmat6...), nil
@@ -176,7 +180,6 @@ func parseProcNetIGMP(path string, ifi *Interface) []Addr {
 		return nil
 	}
 	defer fd.close()
-
 	var (
 		ifmat []Addr
 		name  string
@@ -193,10 +196,14 @@ func parseProcNetIGMP(path string, ifi *Interface) []Addr {
 			name = f[1]
 		case len(f[0]) == 8:
 			if ifi == nil || name == ifi.Name {
+				// The Linux kernel puts the IP
+				// address in /proc/net/igmp in native
+				// endianness.
 				for i := 0; i+1 < len(f[0]); i += 2 {
 					b[i/2], _ = xtoi2(f[0][i:i+2], 0)
 				}
-				ifma := IPAddr{IP: IPv4(b[3], b[2], b[1], b[0])}
+				i := *(*uint32)(unsafe.Pointer(&b[:4][0]))
+				ifma := IPAddr{IP: IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i))}
 				ifmat = append(ifmat, ifma.toAddr())
 			}
 		}
@@ -210,7 +217,6 @@ func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
 		return nil
 	}
 	defer fd.close()
-
 	var ifmat []Addr
 	b := make([]byte, IPv6len)
 	for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
@@ -223,6 +229,9 @@ func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
 				b[i/2], _ = xtoi2(f[2][i:i+2], 0)
 			}
 			ifma := IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}}
+			if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
+				ifma.Zone = ifi.Name
+			}
 			ifmat = append(ifmat, ifma.toAddr())
 		}
 	}
diff --git a/src/pkg/net/interface_linux_test.go b/src/pkg/net/interface_linux_test.go
index f14d1fe..085d3de 100644
--- a/src/pkg/net/interface_linux_test.go
+++ b/src/pkg/net/interface_linux_test.go
@@ -4,7 +4,55 @@
 
 package net
 
-import "testing"
+import (
+	"fmt"
+	"os/exec"
+	"testing"
+)
+
+func (ti *testInterface) setBroadcast(suffix int) error {
+	ti.name = fmt.Sprintf("gotest%d", suffix)
+	xname, err := exec.LookPath("ip")
+	if err != nil {
+		return err
+	}
+	ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+		Path: xname,
+		Args: []string{"ip", "link", "add", ti.name, "type", "dummy"},
+	})
+	ti.teardownCmds = append(ti.teardownCmds, &exec.Cmd{
+		Path: xname,
+		Args: []string{"ip", "link", "delete", ti.name, "type", "dummy"},
+	})
+	return nil
+}
+
+func (ti *testInterface) setPointToPoint(suffix int, local, remote string) error {
+	ti.name = fmt.Sprintf("gotest%d", suffix)
+	ti.local = local
+	ti.remote = remote
+	xname, err := exec.LookPath("ip")
+	if err != nil {
+		return err
+	}
+	ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+		Path: xname,
+		Args: []string{"ip", "tunnel", "add", ti.name, "mode", "gre", "local", local, "remote", remote},
+	})
+	ti.teardownCmds = append(ti.teardownCmds, &exec.Cmd{
+		Path: xname,
+		Args: []string{"ip", "tunnel", "del", ti.name, "mode", "gre", "local", local, "remote", remote},
+	})
+	xname, err = exec.LookPath("ifconfig")
+	if err != nil {
+		return err
+	}
+	ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+		Path: xname,
+		Args: []string{"ifconfig", ti.name, "inet", local, "dstaddr", remote},
+	})
+	return nil
+}
 
 const (
 	numOfTestIPv4MCAddrs = 14
diff --git a/src/pkg/net/interface_netbsd.go b/src/pkg/net/interface_netbsd.go
index 4150e9a..c9ce5a7 100644
--- a/src/pkg/net/interface_netbsd.go
+++ b/src/pkg/net/interface_netbsd.go
@@ -2,13 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Network interface identification for NetBSD
-
 package net
 
-// If the ifindex is zero, interfaceMulticastAddrTable returns
-// addresses for all network interfaces.  Otherwise it returns
-// addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	// TODO(mikio): Implement this like other platforms.
 	return nil, nil
 }
diff --git a/src/pkg/net/interface_openbsd.go b/src/pkg/net/interface_openbsd.go
index d8adb46..c9ce5a7 100644
--- a/src/pkg/net/interface_openbsd.go
+++ b/src/pkg/net/interface_openbsd.go
@@ -2,13 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Network interface identification for OpenBSD
-
 package net
 
-// If the ifindex is zero, interfaceMulticastAddrTable returns
-// addresses for all network interfaces.  Otherwise it returns
-// addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	// TODO(mikio): Implement this like other platforms.
 	return nil, nil
 }
diff --git a/src/pkg/net/interface_stub.go b/src/pkg/net/interface_stub.go
index d4d7ce9..a4eb731 100644
--- a/src/pkg/net/interface_stub.go
+++ b/src/pkg/net/interface_stub.go
@@ -4,8 +4,6 @@
 
 // +build plan9
 
-// Network interface identification
-
 package net
 
 // If the ifindex is zero, interfaceTable returns mappings of all
@@ -15,16 +13,15 @@ func interfaceTable(ifindex int) ([]Interface, error) {
 	return nil, nil
 }
 
-// If the ifindex is zero, interfaceAddrTable returns addresses
-// for all network interfaces.  Otherwise it returns addresses
-// for a specific interface.
-func interfaceAddrTable(ifindex int) ([]Addr, error) {
+// If the ifi is nil, interfaceAddrTable returns addresses for all
+// network interfaces.  Otherwise it returns addresses for a specific
+// interface.
+func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
 	return nil, nil
 }
 
-// If the ifindex is zero, interfaceMulticastAddrTable returns
-// addresses for all network interfaces.  Otherwise it returns
-// addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
 	return nil, nil
 }
diff --git a/src/pkg/net/interface_test.go b/src/pkg/net/interface_test.go
index 0a33bfd..7fb3428 100644
--- a/src/pkg/net/interface_test.go
+++ b/src/pkg/net/interface_test.go
@@ -5,18 +5,24 @@
 package net
 
 import (
-	"bytes"
+	"reflect"
 	"testing"
 )
 
-func sameInterface(i, j *Interface) bool {
-	if i == nil || j == nil {
-		return false
+// loopbackInterface returns an available logical network interface
+// for loopback tests.  It returns nil if no suitable interface is
+// found.
+func loopbackInterface() *Interface {
+	ift, err := Interfaces()
+	if err != nil {
+		return nil
 	}
-	if i.Index == j.Index && i.Name == j.Name && bytes.Equal(i.HardwareAddr, j.HardwareAddr) {
-		return true
+	for _, ifi := range ift {
+		if ifi.Flags&FlagLoopback != 0 && ifi.Flags&FlagUp != 0 {
+			return &ifi
+		}
 	}
-	return false
+	return nil
 }
 
 func TestInterfaces(t *testing.T) {
@@ -24,24 +30,24 @@ func TestInterfaces(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Interfaces failed: %v", err)
 	}
-	t.Logf("table: len/cap = %v/%v\n", len(ift), cap(ift))
+	t.Logf("table: len/cap = %v/%v", len(ift), cap(ift))
 
 	for _, ifi := range ift {
 		ifxi, err := InterfaceByIndex(ifi.Index)
 		if err != nil {
-			t.Fatalf("InterfaceByIndex(%q) failed: %v", ifi.Index, err)
+			t.Fatalf("InterfaceByIndex(%v) failed: %v", ifi.Index, err)
 		}
-		if !sameInterface(ifxi, &ifi) {
-			t.Fatalf("InterfaceByIndex(%q) = %v, want %v", ifi.Index, *ifxi, ifi)
+		if !reflect.DeepEqual(ifxi, &ifi) {
+			t.Fatalf("InterfaceByIndex(%v) = %v, want %v", ifi.Index, ifxi, ifi)
 		}
 		ifxn, err := InterfaceByName(ifi.Name)
 		if err != nil {
 			t.Fatalf("InterfaceByName(%q) failed: %v", ifi.Name, err)
 		}
-		if !sameInterface(ifxn, &ifi) {
-			t.Fatalf("InterfaceByName(%q) = %v, want %v", ifi.Name, *ifxn, ifi)
+		if !reflect.DeepEqual(ifxn, &ifi) {
+			t.Fatalf("InterfaceByName(%q) = %v, want %v", ifi.Name, ifxn, ifi)
 		}
-		t.Logf("%q: flags %q, ifindex %v, mtu %v\n", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
+		t.Logf("%q: flags %q, ifindex %v, mtu %v", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
 		t.Logf("\thardware address %q", ifi.HardwareAddr.String())
 		testInterfaceAddrs(t, &ifi)
 		testInterfaceMulticastAddrs(t, &ifi)
@@ -53,7 +59,7 @@ func TestInterfaceAddrs(t *testing.T) {
 	if err != nil {
 		t.Fatalf("InterfaceAddrs failed: %v", err)
 	}
-	t.Logf("table: len/cap = %v/%v\n", len(ifat), cap(ifat))
+	t.Logf("table: len/cap = %v/%v", len(ifat), cap(ifat))
 	testAddrs(t, ifat)
 }
 
@@ -75,9 +81,13 @@ func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) {
 
 func testAddrs(t *testing.T, ifat []Addr) {
 	for _, ifa := range ifat {
-		switch ifa.(type) {
+		switch v := ifa.(type) {
 		case *IPAddr, *IPNet:
-			t.Logf("\tinterface address %q\n", ifa.String())
+			if v == nil {
+				t.Errorf("\tunexpected value: %v", ifa)
+			} else {
+				t.Logf("\tinterface address %q", ifa.String())
+			}
 		default:
 			t.Errorf("\tunexpected type: %T", ifa)
 		}
@@ -86,11 +96,79 @@ func testAddrs(t *testing.T, ifat []Addr) {
 
 func testMulticastAddrs(t *testing.T, ifmat []Addr) {
 	for _, ifma := range ifmat {
-		switch ifma.(type) {
+		switch v := ifma.(type) {
 		case *IPAddr:
-			t.Logf("\tjoined group address %q\n", ifma.String())
+			if v == nil {
+				t.Errorf("\tunexpected value: %v", ifma)
+			} else {
+				t.Logf("\tjoined group address %q", ifma.String())
+			}
 		default:
 			t.Errorf("\tunexpected type: %T", ifma)
 		}
 	}
 }
+
+func BenchmarkInterfaces(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		if _, err := Interfaces(); err != nil {
+			b.Fatalf("Interfaces failed: %v", err)
+		}
+	}
+}
+
+func BenchmarkInterfaceByIndex(b *testing.B) {
+	ifi := loopbackInterface()
+	if ifi == nil {
+		b.Skip("loopback interface not found")
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := InterfaceByIndex(ifi.Index); err != nil {
+			b.Fatalf("InterfaceByIndex failed: %v", err)
+		}
+	}
+}
+
+func BenchmarkInterfaceByName(b *testing.B) {
+	ifi := loopbackInterface()
+	if ifi == nil {
+		b.Skip("loopback interface not found")
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := InterfaceByName(ifi.Name); err != nil {
+			b.Fatalf("InterfaceByName failed: %v", err)
+		}
+	}
+}
+
+func BenchmarkInterfaceAddrs(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		if _, err := InterfaceAddrs(); err != nil {
+			b.Fatalf("InterfaceAddrs failed: %v", err)
+		}
+	}
+}
+
+func BenchmarkInterfacesAndAddrs(b *testing.B) {
+	ifi := loopbackInterface()
+	if ifi == nil {
+		b.Skip("loopback interface not found")
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := ifi.Addrs(); err != nil {
+			b.Fatalf("Interface.Addrs failed: %v", err)
+		}
+	}
+}
+
+func BenchmarkInterfacesAndMulticastAddrs(b *testing.B) {
+	ifi := loopbackInterface()
+	if ifi == nil {
+		b.Skip("loopback interface not found")
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := ifi.MulticastAddrs(); err != nil {
+			b.Fatalf("Interface.MulticastAddrs failed: %v", err)
+		}
+	}
+}
diff --git a/src/pkg/net/interface_unix_test.go b/src/pkg/net/interface_unix_test.go
new file mode 100644
index 0000000..6dbd6e6
--- /dev/null
+++ b/src/pkg/net/interface_unix_test.go
@@ -0,0 +1,145 @@
+// 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 freebsd linux netbsd openbsd
+
+package net
+
+import (
+	"os"
+	"os/exec"
+	"runtime"
+	"testing"
+	"time"
+)
+
+type testInterface struct {
+	name         string
+	local        string
+	remote       string
+	setupCmds    []*exec.Cmd
+	teardownCmds []*exec.Cmd
+}
+
+func (ti *testInterface) setup() error {
+	for _, cmd := range ti.setupCmds {
+		if err := cmd.Run(); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (ti *testInterface) teardown() error {
+	for _, cmd := range ti.teardownCmds {
+		if err := cmd.Run(); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func TestPointToPointInterface(t *testing.T) {
+	switch runtime.GOOS {
+	case "darwin":
+		t.Skipf("skipping read test on %q", runtime.GOOS)
+	}
+	if os.Getuid() != 0 {
+		t.Skip("skipping test; must be root")
+	}
+
+	local, remote := "169.254.0.1", "169.254.0.254"
+	ip := ParseIP(remote)
+	for i := 0; i < 3; i++ {
+		ti := &testInterface{}
+		if err := ti.setPointToPoint(5963+i, local, remote); err != nil {
+			t.Skipf("test requries external command: %v", err)
+		}
+		if err := ti.setup(); err != nil {
+			t.Fatalf("testInterface.setup failed: %v", err)
+		} else {
+			time.Sleep(3 * time.Millisecond)
+		}
+		ift, err := Interfaces()
+		if err != nil {
+			ti.teardown()
+			t.Fatalf("Interfaces failed: %v", err)
+		}
+		for _, ifi := range ift {
+			if ti.name == ifi.Name {
+				ifat, err := ifi.Addrs()
+				if err != nil {
+					ti.teardown()
+					t.Fatalf("Interface.Addrs failed: %v", err)
+				}
+				for _, ifa := range ifat {
+					if ip.Equal(ifa.(*IPNet).IP) {
+						ti.teardown()
+						t.Fatalf("got %v; want %v", ip, local)
+					}
+				}
+			}
+		}
+		if err := ti.teardown(); err != nil {
+			t.Fatalf("testInterface.teardown failed: %v", err)
+		} else {
+			time.Sleep(3 * time.Millisecond)
+		}
+	}
+}
+
+func TestInterfaceArrivalAndDeparture(t *testing.T) {
+	if os.Getuid() != 0 {
+		t.Skip("skipping test; must be root")
+	}
+
+	for i := 0; i < 3; i++ {
+		ift1, err := Interfaces()
+		if err != nil {
+			t.Fatalf("Interfaces failed: %v", err)
+		}
+		ti := &testInterface{}
+		if err := ti.setBroadcast(5682 + i); err != nil {
+			t.Skipf("test requires external command: %v", err)
+		}
+		if err := ti.setup(); err != nil {
+			t.Fatalf("testInterface.setup failed: %v", err)
+		} else {
+			time.Sleep(3 * time.Millisecond)
+		}
+		ift2, err := Interfaces()
+		if err != nil {
+			ti.teardown()
+			t.Fatalf("Interfaces failed: %v", err)
+		}
+		if len(ift2) <= len(ift1) {
+			for _, ifi := range ift1 {
+				t.Logf("before: %v", ifi)
+			}
+			for _, ifi := range ift2 {
+				t.Logf("after: %v", ifi)
+			}
+			ti.teardown()
+			t.Fatalf("got %v; want gt %v", len(ift2), len(ift1))
+		}
+		if err := ti.teardown(); err != nil {
+			t.Fatalf("testInterface.teardown failed: %v", err)
+		} else {
+			time.Sleep(3 * time.Millisecond)
+		}
+		ift3, err := Interfaces()
+		if err != nil {
+			t.Fatalf("Interfaces failed: %v", err)
+		}
+		if len(ift3) >= len(ift2) {
+			for _, ifi := range ift2 {
+				t.Logf("before: %v", ifi)
+			}
+			for _, ifi := range ift3 {
+				t.Logf("after: %v", ifi)
+			}
+			t.Fatalf("got %v; want lt %v", len(ift3), len(ift2))
+		}
+	}
+}
diff --git a/src/pkg/net/interface_windows.go b/src/pkg/net/interface_windows.go
index 4368b33..0759dc2 100644
--- a/src/pkg/net/interface_windows.go
+++ b/src/pkg/net/interface_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.
 
-// Network interface identification for Windows
-
 package net
 
 import (
@@ -25,6 +23,9 @@ func getAdapterList() (*syscall.IpAdapterInfo, error) {
 	b := make([]byte, 1000)
 	l := uint32(len(b))
 	a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
+	// TODO(mikio): GetAdaptersInfo returns IP_ADAPTER_INFO that
+	// contains IPv4 address list only. We should use another API
+	// for fetching IPv6 stuff from the kernel.
 	err := syscall.GetAdaptersInfo(a, &l)
 	if err == syscall.ERROR_BUFFER_OVERFLOW {
 		b = make([]byte, l)
@@ -38,7 +39,7 @@ func getAdapterList() (*syscall.IpAdapterInfo, error) {
 }
 
 func getInterfaceList() ([]syscall.InterfaceInfo, error) {
-	s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
+	s, err := sysSocket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
 	if err != nil {
 		return nil, os.NewSyscallError("Socket", err)
 	}
@@ -126,10 +127,10 @@ func interfaceTable(ifindex int) ([]Interface, error) {
 	return ift, nil
 }
 
-// If the ifindex is zero, interfaceAddrTable returns addresses
-// for all network interfaces.  Otherwise it returns addresses
-// for a specific interface.
-func interfaceAddrTable(ifindex int) ([]Addr, error) {
+// If the ifi is nil, interfaceAddrTable returns addresses for all
+// network interfaces.  Otherwise it returns addresses for a specific
+// interface.
+func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
 	ai, err := getAdapterList()
 	if err != nil {
 		return nil, err
@@ -138,11 +139,10 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) {
 	var ifat []Addr
 	for ; ai != nil; ai = ai.Next {
 		index := ai.Index
-		if ifindex == 0 || ifindex == int(index) {
+		if ifi == nil || ifi.Index == int(index) {
 			ipl := &ai.IpAddressList
 			for ; ipl != nil; ipl = ipl.Next {
-				ifa := IPAddr{}
-				ifa.IP = parseIPv4(bytePtrToString(&ipl.IpAddress.String[0]))
+				ifa := IPAddr{IP: parseIPv4(bytePtrToString(&ipl.IpAddress.String[0]))}
 				ifat = append(ifat, ifa.toAddr())
 			}
 		}
@@ -150,9 +150,9 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) {
 	return ifat, nil
 }
 
-// If the ifindex is zero, interfaceMulticastAddrTable returns
-// addresses for all network interfaces.  Otherwise it returns
-// addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+	// TODO(mikio): Implement this like other platforms.
 	return nil, nil
 }
diff --git a/src/pkg/net/ip.go b/src/pkg/net/ip.go
index 979d7ac..d588e3a 100644
--- a/src/pkg/net/ip.go
+++ b/src/pkg/net/ip.go
@@ -7,7 +7,7 @@
 // IPv4 addresses are 4 bytes; IPv6 addresses are 16 bytes.
 // An IPv4 address can be converted to an IPv6 address by
 // adding a canonical prefix (10 zeros, 2 0xFFs).
-// This library accepts either size of byte array but always
+// This library accepts either size of byte slice but always
 // returns 16-byte addresses.
 
 package net
@@ -18,14 +18,14 @@ const (
 	IPv6len = 16
 )
 
-// An IP is a single IP address, an array of bytes.
+// An IP is a single IP address, a slice of bytes.
 // Functions in this package accept either 4-byte (IPv4)
-// or 16-byte (IPv6) arrays as input.
+// or 16-byte (IPv6) slices as input.
 //
 // Note that in this documentation, referring to an
 // IP address as an IPv4 address or an IPv6 address
 // is a semantic property of the address, not just the
-// length of the byte array: a 16-byte array can still
+// length of the byte slice: a 16-byte slice can still
 // be an IPv4 address.
 type IP []byte
 
@@ -36,6 +36,7 @@ type IPMask []byte
 type IPNet struct {
 	IP   IP     // network number
 	Mask IPMask // network mask
+	Zone string // IPv6 scoped addressing zone
 }
 
 // IPv4 returns the IP address (in 16-byte form) of the
@@ -645,5 +646,5 @@ func ParseCIDR(s string) (IP, *IPNet, error) {
 		return nil, nil, &ParseError{"CIDR address", s}
 	}
 	m := CIDRMask(n, 8*iplen)
-	return ip, &IPNet{ip.Mask(m), m}, nil
+	return ip, &IPNet{IP: ip.Mask(m), Mask: m}, nil
 }
diff --git a/src/pkg/net/ip_test.go b/src/pkg/net/ip_test.go
index df647ef..f8b7f06 100644
--- a/src/pkg/net/ip_test.go
+++ b/src/pkg/net/ip_test.go
@@ -114,23 +114,23 @@ var parsecidrtests = []struct {
 	net *IPNet
 	err error
 }{
-	{"135.104.0.0/32", IPv4(135, 104, 0, 0), &IPNet{IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 255)}, nil},
-	{"0.0.0.0/24", IPv4(0, 0, 0, 0), &IPNet{IPv4(0, 0, 0, 0), IPv4Mask(255, 255, 255, 0)}, nil},
-	{"135.104.0.0/24", IPv4(135, 104, 0, 0), &IPNet{IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 0)}, nil},
-	{"135.104.0.1/32", IPv4(135, 104, 0, 1), &IPNet{IPv4(135, 104, 0, 1), IPv4Mask(255, 255, 255, 255)}, nil},
-	{"135.104.0.1/24", IPv4(135, 104, 0, 1), &IPNet{IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 0)}, nil},
-	{"::1/128", ParseIP("::1"), &IPNet{ParseIP("::1"), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))}, nil},
-	{"abcd:2345::/127", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"))}, nil},
-	{"abcd:2345::/65", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff:8000::"))}, nil},
-	{"abcd:2345::/64", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff::"))}, nil},
-	{"abcd:2345::/63", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:fffe::"))}, nil},
-	{"abcd:2345::/33", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:8000::"))}, nil},
-	{"abcd:2345::/32", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff::"))}, nil},
-	{"abcd:2344::/31", ParseIP("abcd:2344::"), &IPNet{ParseIP("abcd:2344::"), IPMask(ParseIP("ffff:fffe::"))}, nil},
-	{"abcd:2300::/24", ParseIP("abcd:2300::"), &IPNet{ParseIP("abcd:2300::"), IPMask(ParseIP("ffff:ff00::"))}, nil},
-	{"abcd:2345::/24", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2300::"), IPMask(ParseIP("ffff:ff00::"))}, nil},
-	{"2001:DB8::/48", ParseIP("2001:DB8::"), &IPNet{ParseIP("2001:DB8::"), IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
-	{"2001:DB8::1/48", ParseIP("2001:DB8::1"), &IPNet{ParseIP("2001:DB8::"), IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
+	{"135.104.0.0/32", IPv4(135, 104, 0, 0), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 255)}, nil},
+	{"0.0.0.0/24", IPv4(0, 0, 0, 0), &IPNet{IP: IPv4(0, 0, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
+	{"135.104.0.0/24", IPv4(135, 104, 0, 0), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
+	{"135.104.0.1/32", IPv4(135, 104, 0, 1), &IPNet{IP: IPv4(135, 104, 0, 1), Mask: IPv4Mask(255, 255, 255, 255)}, nil},
+	{"135.104.0.1/24", IPv4(135, 104, 0, 1), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
+	{"::1/128", ParseIP("::1"), &IPNet{IP: ParseIP("::1"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))}, nil},
+	{"abcd:2345::/127", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"))}, nil},
+	{"abcd:2345::/65", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:8000::"))}, nil},
+	{"abcd:2345::/64", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff::"))}, nil},
+	{"abcd:2345::/63", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:fffe::"))}, nil},
+	{"abcd:2345::/33", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:8000::"))}, nil},
+	{"abcd:2345::/32", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff::"))}, nil},
+	{"abcd:2344::/31", ParseIP("abcd:2344::"), &IPNet{IP: ParseIP("abcd:2344::"), Mask: IPMask(ParseIP("ffff:fffe::"))}, nil},
+	{"abcd:2300::/24", ParseIP("abcd:2300::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil},
+	{"abcd:2345::/24", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil},
+	{"2001:DB8::/48", ParseIP("2001:DB8::"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
+	{"2001:DB8::1/48", ParseIP("2001:DB8::1"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
 	{"192.168.1.1/255.255.255.0", nil, nil, &ParseError{"CIDR address", "192.168.1.1/255.255.255.0"}},
 	{"192.168.1.1/35", nil, nil, &ParseError{"CIDR address", "192.168.1.1/35"}},
 	{"2001:db8::1/-1", nil, nil, &ParseError{"CIDR address", "2001:db8::1/-1"}},
@@ -154,14 +154,14 @@ var ipnetcontainstests = []struct {
 	net *IPNet
 	ok  bool
 }{
-	{IPv4(172, 16, 1, 1), &IPNet{IPv4(172, 16, 0, 0), CIDRMask(12, 32)}, true},
-	{IPv4(172, 24, 0, 1), &IPNet{IPv4(172, 16, 0, 0), CIDRMask(13, 32)}, false},
-	{IPv4(192, 168, 0, 3), &IPNet{IPv4(192, 168, 0, 0), IPv4Mask(0, 0, 255, 252)}, true},
-	{IPv4(192, 168, 0, 4), &IPNet{IPv4(192, 168, 0, 0), IPv4Mask(0, 255, 0, 252)}, false},
-	{ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:1::"), CIDRMask(47, 128)}, true},
-	{ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:2::"), CIDRMask(47, 128)}, false},
-	{ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:1::"), IPMask(ParseIP("ffff:0:ffff::"))}, true},
-	{ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:1::"), IPMask(ParseIP("0:0:0:ffff::"))}, false},
+	{IPv4(172, 16, 1, 1), &IPNet{IP: IPv4(172, 16, 0, 0), Mask: CIDRMask(12, 32)}, true},
+	{IPv4(172, 24, 0, 1), &IPNet{IP: IPv4(172, 16, 0, 0), Mask: CIDRMask(13, 32)}, false},
+	{IPv4(192, 168, 0, 3), &IPNet{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(0, 0, 255, 252)}, true},
+	{IPv4(192, 168, 0, 4), &IPNet{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(0, 255, 0, 252)}, false},
+	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: CIDRMask(47, 128)}, true},
+	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:2::"), Mask: CIDRMask(47, 128)}, false},
+	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: IPMask(ParseIP("ffff:0:ffff::"))}, true},
+	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: IPMask(ParseIP("0:0:0:ffff::"))}, false},
 }
 
 func TestIPNetContains(t *testing.T) {
@@ -176,10 +176,10 @@ var ipnetstringtests = []struct {
 	in  *IPNet
 	out string
 }{
-	{&IPNet{IPv4(192, 168, 1, 0), CIDRMask(26, 32)}, "192.168.1.0/26"},
-	{&IPNet{IPv4(192, 168, 1, 0), IPv4Mask(255, 0, 255, 0)}, "192.168.1.0/ff00ff00"},
-	{&IPNet{ParseIP("2001:db8::"), CIDRMask(55, 128)}, "2001:db8::/55"},
-	{&IPNet{ParseIP("2001:db8::"), IPMask(ParseIP("8000:f123:0:cafe::"))}, "2001:db8::/8000f1230000cafe0000000000000000"},
+	{&IPNet{IP: IPv4(192, 168, 1, 0), Mask: CIDRMask(26, 32)}, "192.168.1.0/26"},
+	{&IPNet{IP: IPv4(192, 168, 1, 0), Mask: IPv4Mask(255, 0, 255, 0)}, "192.168.1.0/ff00ff00"},
+	{&IPNet{IP: ParseIP("2001:db8::"), Mask: CIDRMask(55, 128)}, "2001:db8::/55"},
+	{&IPNet{IP: ParseIP("2001:db8::"), Mask: IPMask(ParseIP("8000:f123:0:cafe::"))}, "2001:db8::/8000f1230000cafe0000000000000000"},
 }
 
 func TestIPNetString(t *testing.T) {
@@ -233,27 +233,27 @@ var networknumberandmasktests = []struct {
 	in  IPNet
 	out IPNet
 }{
-	{IPNet{v4addr, v4mask}, IPNet{v4addr, v4mask}},
-	{IPNet{v4addr, v4mappedv6mask}, IPNet{v4addr, v4mask}},
-	{IPNet{v4mappedv6addr, v4mappedv6mask}, IPNet{v4addr, v4mask}},
-	{IPNet{v4mappedv6addr, v6mask}, IPNet{v4addr, v4maskzero}},
-	{IPNet{v4addr, v6mask}, IPNet{v4addr, v4maskzero}},
-	{IPNet{v6addr, v6mask}, IPNet{v6addr, v6mask}},
-	{IPNet{v6addr, v4mappedv6mask}, IPNet{v6addr, v4mappedv6mask}},
-	{in: IPNet{v6addr, v4mask}},
-	{in: IPNet{v4addr, badmask}},
-	{in: IPNet{v4mappedv6addr, badmask}},
-	{in: IPNet{v6addr, badmask}},
-	{in: IPNet{badaddr, v4mask}},
-	{in: IPNet{badaddr, v4mappedv6mask}},
-	{in: IPNet{badaddr, v6mask}},
-	{in: IPNet{badaddr, badmask}},
+	{IPNet{IP: v4addr, Mask: v4mask}, IPNet{IP: v4addr, Mask: v4mask}},
+	{IPNet{IP: v4addr, Mask: v4mappedv6mask}, IPNet{IP: v4addr, Mask: v4mask}},
+	{IPNet{IP: v4mappedv6addr, Mask: v4mappedv6mask}, IPNet{IP: v4addr, Mask: v4mask}},
+	{IPNet{IP: v4mappedv6addr, Mask: v6mask}, IPNet{IP: v4addr, Mask: v4maskzero}},
+	{IPNet{IP: v4addr, Mask: v6mask}, IPNet{IP: v4addr, Mask: v4maskzero}},
+	{IPNet{IP: v6addr, Mask: v6mask}, IPNet{IP: v6addr, Mask: v6mask}},
+	{IPNet{IP: v6addr, Mask: v4mappedv6mask}, IPNet{IP: v6addr, Mask: v4mappedv6mask}},
+	{in: IPNet{IP: v6addr, Mask: v4mask}},
+	{in: IPNet{IP: v4addr, Mask: badmask}},
+	{in: IPNet{IP: v4mappedv6addr, Mask: badmask}},
+	{in: IPNet{IP: v6addr, Mask: badmask}},
+	{in: IPNet{IP: badaddr, Mask: v4mask}},
+	{in: IPNet{IP: badaddr, Mask: v4mappedv6mask}},
+	{in: IPNet{IP: badaddr, Mask: v6mask}},
+	{in: IPNet{IP: badaddr, Mask: badmask}},
 }
 
 func TestNetworkNumberAndMask(t *testing.T) {
 	for _, tt := range networknumberandmasktests {
 		ip, m := networkNumberAndMask(&tt.in)
-		out := &IPNet{ip, m}
+		out := &IPNet{IP: ip, Mask: m}
 		if !reflect.DeepEqual(&tt.out, out) {
 			t.Errorf("networkNumberAndMask(%v) = %v; want %v", tt.in, out, &tt.out)
 		}
@@ -268,6 +268,29 @@ var splitjointests = []struct {
 	{"www.google.com", "80", "www.google.com:80"},
 	{"127.0.0.1", "1234", "127.0.0.1:1234"},
 	{"::1", "80", "[::1]:80"},
+	{"google.com", "https%foo", "google.com:https%foo"}, // Go 1.0 behavior
+	{"", "0", ":0"},
+	{"127.0.0.1", "", "127.0.0.1:"},           // Go 1.0 behaviour
+	{"www.google.com", "", "www.google.com:"}, // Go 1.0 behaviour
+}
+
+var splitfailuretests = []struct {
+	HostPort string
+	Err      string
+}{
+	{"www.google.com", "missing port in address"},
+	{"127.0.0.1", "missing port in address"},
+	{"[::1]", "missing port in address"},
+	{"::1", "too many colons in address"},
+
+	// Test cases that didn't fail in Go 1.0
+	{"[foo:bar]", "missing port in address"},
+	{"[foo:bar]baz", "missing port in address"},
+	{"[foo]:[bar]:baz", "too many colons in address"},
+	{"[foo]bar:baz", "missing port in address"},
+	{"[foo]:[bar]baz", "unexpected '[' in address"},
+	{"foo[bar]:baz", "unexpected '[' in address"},
+	{"foo]bar:baz", "unexpected ']' in address"},
 }
 
 func TestSplitHostPort(t *testing.T) {
@@ -276,6 +299,16 @@ func TestSplitHostPort(t *testing.T) {
 			t.Errorf("SplitHostPort(%q) = %q, %q, %v; want %q, %q, nil", tt.Join, host, port, err, tt.Host, tt.Port)
 		}
 	}
+	for _, tt := range splitfailuretests {
+		if _, _, err := SplitHostPort(tt.HostPort); err == nil {
+			t.Errorf("SplitHostPort(%q) should have failed", tt.HostPort)
+		} else {
+			e := err.(*AddrError)
+			if e.Err != tt.Err {
+				t.Errorf("SplitHostPort(%q) = _, _, %q; want %q", tt.HostPort, e.Err, tt.Err)
+			}
+		}
+	}
 }
 
 func TestJoinHostPort(t *testing.T) {
diff --git a/src/pkg/net/ipraw_test.go b/src/pkg/net/ipraw_test.go
index 6136202..65defc7 100644
--- a/src/pkg/net/ipraw_test.go
+++ b/src/pkg/net/ipraw_test.go
@@ -2,205 +2,340 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !plan9
+
 package net
 
 import (
 	"bytes"
+	"errors"
 	"os"
-	"syscall"
+	"reflect"
 	"testing"
 	"time"
 )
 
-var icmpTests = []struct {
+var resolveIPAddrTests = []struct {
+	net     string
+	litAddr string
+	addr    *IPAddr
+	err     error
+}{
+	{"ip", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+	{"ip4", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+	{"ip4:icmp", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+
+	{"ip", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
+	{"ip6", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
+	{"ip6:icmp", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
+
+	{"", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil}, // Go 1.0 behavior
+	{"", "::1", &IPAddr{IP: ParseIP("::1")}, nil},           // Go 1.0 behavior
+
+	{"l2tp", "127.0.0.1", nil, UnknownNetworkError("l2tp")},
+	{"l2tp:gre", "127.0.0.1", nil, UnknownNetworkError("l2tp:gre")},
+	{"tcp", "1.2.3.4:123", nil, UnknownNetworkError("tcp")},
+}
+
+func TestResolveIPAddr(t *testing.T) {
+	for _, tt := range resolveIPAddrTests {
+		addr, err := ResolveIPAddr(tt.net, tt.litAddr)
+		if err != tt.err {
+			t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
+		}
+		if !reflect.DeepEqual(addr, tt.addr) {
+			t.Fatalf("got %#v; expected %#v", addr, tt.addr)
+		}
+	}
+}
+
+var icmpEchoTests = []struct {
 	net   string
 	laddr string
 	raddr string
-	ipv6  bool // test with underlying AF_INET6 socket
 }{
-	{"ip4:icmp", "", "127.0.0.1", false},
-	{"ip6:icmp", "", "::1", true},
+	{"ip4:icmp", "0.0.0.0", "127.0.0.1"},
+	{"ip6:ipv6-icmp", "::", "::1"},
 }
 
-func TestICMP(t *testing.T) {
+func TestConnICMPEcho(t *testing.T) {
 	if os.Getuid() != 0 {
-		t.Logf("test disabled; must be root")
-		return
+		t.Skip("skipping test; must be root")
 	}
 
-	seqnum := 61455
-	for _, tt := range icmpTests {
-		if tt.ipv6 && !supportsIPv6 {
+	for i, tt := range icmpEchoTests {
+		net, _, err := parseNetwork(tt.net)
+		if err != nil {
+			t.Fatalf("parseNetwork failed: %v", err)
+		}
+		if net == "ip6" && !supportsIPv6 {
 			continue
 		}
-		id := os.Getpid() & 0xffff
-		seqnum++
-		echo := newICMPEchoRequest(tt.net, id, seqnum, 128, []byte("Go Go Gadget Ping!!!"))
-		exchangeICMPEcho(t, tt.net, tt.laddr, tt.raddr, echo)
-	}
-}
-
-func exchangeICMPEcho(t *testing.T, net, laddr, raddr string, echo []byte) {
-	c, err := ListenPacket(net, laddr)
-	if err != nil {
-		t.Errorf("ListenPacket(%q, %q) failed: %v", net, laddr, err)
-		return
-	}
-	c.SetDeadline(time.Now().Add(100 * time.Millisecond))
-	defer c.Close()
-
-	ra, err := ResolveIPAddr(net, raddr)
-	if err != nil {
-		t.Errorf("ResolveIPAddr(%q, %q) failed: %v", net, raddr, err)
-		return
-	}
 
-	waitForReady := make(chan bool)
-	go icmpEchoTransponder(t, net, raddr, waitForReady)
-	<-waitForReady
-
-	_, err = c.WriteTo(echo, ra)
-	if err != nil {
-		t.Errorf("WriteTo failed: %v", err)
-		return
-	}
+		c, err := Dial(tt.net, tt.raddr)
+		if err != nil {
+			t.Fatalf("Dial failed: %v", err)
+		}
+		c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		defer c.Close()
 
-	reply := make([]byte, 256)
-	for {
-		_, _, err := c.ReadFrom(reply)
+		typ := icmpv4EchoRequest
+		if net == "ip6" {
+			typ = icmpv6EchoRequest
+		}
+		xid, xseq := os.Getpid()&0xffff, i+1
+		b, err := (&icmpMessage{
+			Type: typ, Code: 0,
+			Body: &icmpEcho{
+				ID: xid, Seq: xseq,
+				Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
+			},
+		}).Marshal()
 		if err != nil {
-			t.Errorf("ReadFrom failed: %v", err)
-			return
+			t.Fatalf("icmpMessage.Marshal failed: %v", err)
 		}
-		switch c.(*IPConn).fd.family {
-		case syscall.AF_INET:
-			if reply[0] != ICMP4_ECHO_REPLY {
-				continue
+		if _, err := c.Write(b); err != nil {
+			t.Fatalf("Conn.Write failed: %v", err)
+		}
+		var m *icmpMessage
+		for {
+			if _, err := c.Read(b); err != nil {
+				t.Fatalf("Conn.Read failed: %v", err)
+			}
+			if net == "ip4" {
+				b = ipv4Payload(b)
 			}
-		case syscall.AF_INET6:
-			if reply[0] != ICMP6_ECHO_REPLY {
+			if m, err = parseICMPMessage(b); err != nil {
+				t.Fatalf("parseICMPMessage failed: %v", err)
+			}
+			switch m.Type {
+			case icmpv4EchoRequest, icmpv6EchoRequest:
 				continue
 			}
+			break
 		}
-		xid, xseqnum := parseICMPEchoReply(echo)
-		rid, rseqnum := parseICMPEchoReply(reply)
-		if rid != xid || rseqnum != xseqnum {
-			t.Errorf("ID = %v, Seqnum = %v, want ID = %v, Seqnum = %v", rid, rseqnum, xid, xseqnum)
-			return
+		switch p := m.Body.(type) {
+		case *icmpEcho:
+			if p.ID != xid || p.Seq != xseq {
+				t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
+			}
+		default:
+			t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
 		}
-		break
 	}
 }
 
-func icmpEchoTransponder(t *testing.T, net, raddr string, waitForReady chan bool) {
-	c, err := Dial(net, raddr)
-	if err != nil {
-		waitForReady <- true
-		t.Errorf("Dial(%q, %q) failed: %v", net, raddr, err)
-		return
+func TestPacketConnICMPEcho(t *testing.T) {
+	if os.Getuid() != 0 {
+		t.Skip("skipping test; must be root")
 	}
-	c.SetDeadline(time.Now().Add(100 * time.Millisecond))
-	defer c.Close()
-	waitForReady <- true
 
-	echo := make([]byte, 256)
-	var nr int
-	for {
-		nr, err = c.Read(echo)
+	for i, tt := range icmpEchoTests {
+		net, _, err := parseNetwork(tt.net)
 		if err != nil {
-			t.Errorf("Read failed: %v", err)
-			return
+			t.Fatalf("parseNetwork failed: %v", err)
 		}
-		switch c.(*IPConn).fd.family {
-		case syscall.AF_INET:
-			if echo[0] != ICMP4_ECHO_REQUEST {
-				continue
+		if net == "ip6" && !supportsIPv6 {
+			continue
+		}
+
+		c, err := ListenPacket(tt.net, tt.laddr)
+		if err != nil {
+			t.Fatalf("ListenPacket failed: %v", err)
+		}
+		c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		defer c.Close()
+
+		ra, err := ResolveIPAddr(tt.net, tt.raddr)
+		if err != nil {
+			t.Fatalf("ResolveIPAddr failed: %v", err)
+		}
+		typ := icmpv4EchoRequest
+		if net == "ip6" {
+			typ = icmpv6EchoRequest
+		}
+		xid, xseq := os.Getpid()&0xffff, i+1
+		b, err := (&icmpMessage{
+			Type: typ, Code: 0,
+			Body: &icmpEcho{
+				ID: xid, Seq: xseq,
+				Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
+			},
+		}).Marshal()
+		if err != nil {
+			t.Fatalf("icmpMessage.Marshal failed: %v", err)
+		}
+		if _, err := c.WriteTo(b, ra); err != nil {
+			t.Fatalf("PacketConn.WriteTo failed: %v", err)
+		}
+		var m *icmpMessage
+		for {
+			if _, _, err := c.ReadFrom(b); err != nil {
+				t.Fatalf("PacketConn.ReadFrom failed: %v", err)
 			}
-		case syscall.AF_INET6:
-			if echo[0] != ICMP6_ECHO_REQUEST {
+			// TODO: fix issue 3944
+			//if net == "ip4" {
+			//	b = ipv4Payload(b)
+			//}
+			if m, err = parseICMPMessage(b); err != nil {
+				t.Fatalf("parseICMPMessage failed: %v", err)
+			}
+			switch m.Type {
+			case icmpv4EchoRequest, icmpv6EchoRequest:
 				continue
 			}
+			break
+		}
+		switch p := m.Body.(type) {
+		case *icmpEcho:
+			if p.ID != xid || p.Seq != xseq {
+				t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
+			}
+		default:
+			t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
 		}
-		break
-	}
-
-	switch c.(*IPConn).fd.family {
-	case syscall.AF_INET:
-		echo[0] = ICMP4_ECHO_REPLY
-	case syscall.AF_INET6:
-		echo[0] = ICMP6_ECHO_REPLY
 	}
+}
 
-	_, err = c.Write(echo[:nr])
-	if err != nil {
-		t.Errorf("Write failed: %v", err)
-		return
+func ipv4Payload(b []byte) []byte {
+	if len(b) < 20 {
+		return b
 	}
+	hdrlen := int(b[0]&0x0f) << 2
+	return b[hdrlen:]
 }
 
 const (
-	ICMP4_ECHO_REQUEST = 8
-	ICMP4_ECHO_REPLY   = 0
-	ICMP6_ECHO_REQUEST = 128
-	ICMP6_ECHO_REPLY   = 129
+	icmpv4EchoRequest = 8
+	icmpv4EchoReply   = 0
+	icmpv6EchoRequest = 128
+	icmpv6EchoReply   = 129
 )
 
-func newICMPEchoRequest(net string, id, seqnum, msglen int, filler []byte) []byte {
-	afnet, _, _ := parseDialNetwork(net)
-	switch afnet {
-	case "ip4":
-		return newICMPv4EchoRequest(id, seqnum, msglen, filler)
-	case "ip6":
-		return newICMPv6EchoRequest(id, seqnum, msglen, filler)
-	}
-	return nil
+// icmpMessage represents an ICMP message.
+type icmpMessage struct {
+	Type     int             // type
+	Code     int             // code
+	Checksum int             // checksum
+	Body     icmpMessageBody // body
 }
 
-func newICMPv4EchoRequest(id, seqnum, msglen int, filler []byte) []byte {
-	b := newICMPInfoMessage(id, seqnum, msglen, filler)
-	b[0] = ICMP4_ECHO_REQUEST
+// icmpMessageBody represents an ICMP message body.
+type icmpMessageBody interface {
+	Len() int
+	Marshal() ([]byte, error)
+}
 
-	// calculate ICMP checksum
-	cklen := len(b)
+// Marshal returns the binary enconding of the ICMP echo request or
+// reply message m.
+func (m *icmpMessage) Marshal() ([]byte, error) {
+	b := []byte{byte(m.Type), byte(m.Code), 0, 0}
+	if m.Body != nil && m.Body.Len() != 0 {
+		mb, err := m.Body.Marshal()
+		if err != nil {
+			return nil, err
+		}
+		b = append(b, mb...)
+	}
+	switch m.Type {
+	case icmpv6EchoRequest, icmpv6EchoReply:
+		return b, nil
+	}
+	csumcv := len(b) - 1 // checksum coverage
 	s := uint32(0)
-	for i := 0; i < cklen-1; i += 2 {
+	for i := 0; i < csumcv; i += 2 {
 		s += uint32(b[i+1])<<8 | uint32(b[i])
 	}
-	if cklen&1 == 1 {
-		s += uint32(b[cklen-1])
+	if csumcv&1 == 0 {
+		s += uint32(b[csumcv])
 	}
-	s = (s >> 16) + (s & 0xffff)
-	s = s + (s >> 16)
-	// place checksum back in header; using ^= avoids the
-	// assumption the checksum bytes are zero
-	b[2] ^= uint8(^s & 0xff)
-	b[3] ^= uint8(^s >> 8)
+	s = s>>16 + s&0xffff
+	s = s + s>>16
+	// Place checksum back in header; using ^= avoids the
+	// assumption the checksum bytes are zero.
+	b[2] ^= byte(^s & 0xff)
+	b[3] ^= byte(^s >> 8)
+	return b, nil
+}
 
-	return b
+// parseICMPMessage parses b as an ICMP message.
+func parseICMPMessage(b []byte) (*icmpMessage, error) {
+	msglen := len(b)
+	if msglen < 4 {
+		return nil, errors.New("message too short")
+	}
+	m := &icmpMessage{Type: int(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
+	if msglen > 4 {
+		var err error
+		switch m.Type {
+		case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply:
+			m.Body, err = parseICMPEcho(b[4:])
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+	return m, nil
+}
+
+// imcpEcho represenets an ICMP echo request or reply message body.
+type icmpEcho struct {
+	ID   int    // identifier
+	Seq  int    // sequence number
+	Data []byte // data
+}
+
+func (p *icmpEcho) Len() int {
+	if p == nil {
+		return 0
+	}
+	return 4 + len(p.Data)
 }
 
-func newICMPv6EchoRequest(id, seqnum, msglen int, filler []byte) []byte {
-	b := newICMPInfoMessage(id, seqnum, msglen, filler)
-	b[0] = ICMP6_ECHO_REQUEST
-	return b
+// Marshal returns the binary enconding of the ICMP echo request or
+// reply message body p.
+func (p *icmpEcho) Marshal() ([]byte, error) {
+	b := make([]byte, 4+len(p.Data))
+	b[0], b[1] = byte(p.ID>>8), byte(p.ID&0xff)
+	b[2], b[3] = byte(p.Seq>>8), byte(p.Seq&0xff)
+	copy(b[4:], p.Data)
+	return b, nil
 }
 
-func newICMPInfoMessage(id, seqnum, msglen int, filler []byte) []byte {
-	b := make([]byte, msglen)
-	copy(b[8:], bytes.Repeat(filler, (msglen-8)/len(filler)+1))
-	b[0] = 0                    // type
-	b[1] = 0                    // code
-	b[2] = 0                    // checksum
-	b[3] = 0                    // checksum
-	b[4] = uint8(id >> 8)       // identifier
-	b[5] = uint8(id & 0xff)     // identifier
-	b[6] = uint8(seqnum >> 8)   // sequence number
-	b[7] = uint8(seqnum & 0xff) // sequence number
-	return b
+// parseICMPEcho parses b as an ICMP echo request or reply message
+// body.
+func parseICMPEcho(b []byte) (*icmpEcho, error) {
+	bodylen := len(b)
+	p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
+	if bodylen > 4 {
+		p.Data = make([]byte, bodylen-4)
+		copy(p.Data, b[4:])
+	}
+	return p, nil
 }
 
-func parseICMPEchoReply(b []byte) (id, seqnum int) {
-	id = int(b[4])<<8 | int(b[5])
-	seqnum = int(b[6])<<8 | int(b[7])
-	return
+var ipConnLocalNameTests = []struct {
+	net   string
+	laddr *IPAddr
+}{
+	{"ip4:icmp", &IPAddr{IP: IPv4(127, 0, 0, 1)}},
+	{"ip4:icmp", &IPAddr{}},
+	{"ip4:icmp", nil},
+}
+
+func TestIPConnLocalName(t *testing.T) {
+	if os.Getuid() != 0 {
+		t.Skip("skipping test; must be root")
+	}
+
+	for _, tt := range ipConnLocalNameTests {
+		c, err := ListenIP(tt.net, tt.laddr)
+		if err != nil {
+			t.Fatalf("ListenIP failed: %v", err)
+		}
+		defer c.Close()
+		if la := c.LocalAddr(); la == nil {
+			t.Fatal("IPConn.LocalAddr failed")
+		}
+	}
 }
diff --git a/src/pkg/net/iprawsock.go b/src/pkg/net/iprawsock.go
index b23213e..daccba3 100644
--- a/src/pkg/net/iprawsock.go
+++ b/src/pkg/net/iprawsock.go
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// (Raw) IP sockets
+// Raw IP sockets
 
 package net
 
-// IPAddr represents the address of a IP end point.
+// IPAddr represents the address of an IP end point.
 type IPAddr struct {
-	IP IP
+	IP   IP
+	Zone string // IPv6 scoped addressing zone
 }
 
 // Network returns the address's network name, "ip".
@@ -21,45 +22,25 @@ func (a *IPAddr) String() string {
 	return a.IP.String()
 }
 
-// ResolveIPAddr parses addr as a IP address and resolves domain
+// ResolveIPAddr parses addr as an IP address and resolves domain
 // names to numeric addresses on the network net, which must be
-// "ip", "ip4" or "ip6".  A literal IPv6 host address must be
-// enclosed in square brackets, as in "[::]".
+// "ip", "ip4" or "ip6".
 func ResolveIPAddr(net, addr string) (*IPAddr, error) {
-	ip, err := hostToIP(net, addr)
+	if net == "" { // a hint wildcard for Go 1.0 undocumented behavior
+		net = "ip"
+	}
+	afnet, _, err := parseNetwork(net)
 	if err != nil {
 		return nil, err
 	}
-	return &IPAddr{ip}, nil
-}
-
-// Convert "host" into IP address.
-func hostToIP(net, host string) (ip IP, err error) {
-	var addr IP
-	// Try as an IP address.
-	addr = ParseIP(host)
-	if addr == nil {
-		filter := anyaddr
-		if net != "" && net[len(net)-1] == '4' {
-			filter = ipv4only
-		}
-		if net != "" && net[len(net)-1] == '6' {
-			filter = ipv6only
-		}
-		// Not an IP address.  Try as a DNS name.
-		addrs, err1 := LookupHost(host)
-		if err1 != nil {
-			err = err1
-			goto Error
-		}
-		addr = firstFavoriteAddr(filter, addrs)
-		if addr == nil {
-			// should not happen
-			err = &AddrError{"LookupHost returned no suitable address", addrs[0]}
-			goto Error
-		}
+	switch afnet {
+	case "ip", "ip4", "ip6":
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	a, err := resolveInternetAddr(afnet, addr, noDeadline)
+	if err != nil {
+		return nil, err
 	}
-	return addr, nil
-Error:
-	return nil, err
+	return a.(*IPAddr), nil
 }
diff --git a/src/pkg/net/iprawsock_plan9.go b/src/pkg/net/iprawsock_plan9.go
index 43719fc..88e3b2c 100644
--- a/src/pkg/net/iprawsock_plan9.go
+++ b/src/pkg/net/iprawsock_plan9.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.
 
-// (Raw) IP sockets stubs for Plan 9
+// Raw IP sockets for Plan 9
 
 package net
 
@@ -11,55 +11,13 @@ import (
 	"time"
 )
 
-// IPConn is the implementation of the Conn and PacketConn
-// interfaces for IP network connections.
-type IPConn bool
-
-// SetDeadline implements the Conn SetDeadline method.
-func (c *IPConn) SetDeadline(t time.Time) error {
-	return syscall.EPLAN9
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *IPConn) SetReadDeadline(t time.Time) error {
-	return syscall.EPLAN9
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *IPConn) SetWriteDeadline(t time.Time) error {
-	return syscall.EPLAN9
-}
-
-// Implementation of the Conn interface - see Conn for documentation.
-
-// Read implements the Conn Read method.
-func (c *IPConn) Read(b []byte) (int, error) {
-	return 0, syscall.EPLAN9
-}
-
-// Write implements the Conn Write method.
-func (c *IPConn) Write(b []byte) (int, error) {
-	return 0, syscall.EPLAN9
-}
-
-// Close closes the IP connection.
-func (c *IPConn) Close() error {
-	return syscall.EPLAN9
-}
-
-// LocalAddr returns the local network address.
-func (c *IPConn) LocalAddr() Addr {
-	return nil
+// IPConn is the implementation of the Conn and PacketConn interfaces
+// for IP network connections.
+type IPConn struct {
+	conn
 }
 
-// RemoteAddr returns the remote network address, a *IPAddr.
-func (c *IPConn) RemoteAddr() Addr {
-	return nil
-}
-
-// IP-specific methods.
-
-// ReadFromIP reads a IP packet from c, copying the payload into b.
+// ReadFromIP reads an IP packet from c, copying the payload into b.
 // It returns the number of bytes copied into b and the return address
 // that was on the packet.
 //
@@ -75,12 +33,21 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
 	return 0, nil, syscall.EPLAN9
 }
 
-// WriteToIP writes a IP packet to addr via c, copying the payload from b.
+// ReadMsgIP reads a packet from c, copying the payload into b and the
+// associdated out-of-band data into oob.  It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet and the source address of the packet.
+func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
+	return 0, 0, 0, nil, syscall.EPLAN9
+}
+
+// WriteToIP writes an IP packet to addr via c, copying the payload
+// from b.
 //
-// WriteToIP can be made to time out and return
-// an error with Timeout() == true after a fixed time limit;
-// see SetDeadline and SetWriteDeadline.
-// On packet-oriented connections, write timeouts are rare.
+// WriteToIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
 func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
 	return 0, syscall.EPLAN9
 }
@@ -90,16 +57,28 @@ func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
 	return 0, syscall.EPLAN9
 }
 
-// DialIP connects to the remote address raddr on the network protocol netProto,
-// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
+// WriteMsgIP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob.  It returns the
+// number of payload and out-of-band bytes written.
+func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
+	return 0, 0, syscall.EPLAN9
+}
+
+// DialIP connects to the remote address raddr on the network protocol
+// netProto, which must be "ip", "ip4", or "ip6" followed by a colon
+// and a protocol number or name.
 func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
+	return dialIP(netProto, laddr, raddr, noDeadline)
+}
+
+func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
 	return nil, syscall.EPLAN9
 }
 
-// ListenIP listens for incoming IP packets addressed to the
-// local address laddr.  The returned connection c's ReadFrom
-// and WriteTo methods can be used to receive and send IP
-// packets with per-packet addressing.
+// ListenIP listens for incoming IP packets addressed to the local
+// address laddr.  The returned connection c's ReadFrom and WriteTo
+// methods can be used to receive and send IP packets with per-packet
+// addressing.
 func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
 	return nil, syscall.EPLAN9
 }
diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go
index 9fc7ecd..2ef4db1 100644
--- a/src/pkg/net/iprawsock_posix.go
+++ b/src/pkg/net/iprawsock_posix.go
@@ -4,12 +4,11 @@
 
 // +build darwin freebsd linux netbsd openbsd windows
 
-// (Raw) IP sockets
+// Raw IP sockets for POSIX
 
 package net
 
 import (
-	"os"
 	"syscall"
 	"time"
 )
@@ -17,9 +16,9 @@ import (
 func sockaddrToIP(sa syscall.Sockaddr) Addr {
 	switch sa := sa.(type) {
 	case *syscall.SockaddrInet4:
-		return &IPAddr{sa.Addr[0:]}
+		return &IPAddr{IP: sa.Addr[0:]}
 	case *syscall.SockaddrInet6:
-		return &IPAddr{sa.Addr[0:]}
+		return &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
 	}
 	return nil
 }
@@ -42,7 +41,7 @@ func (a *IPAddr) isWildcard() bool {
 }
 
 func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
-	return ipToSockaddr(family, a.IP, 0)
+	return ipToSockaddr(family, a.IP, 0, a.Zone)
 }
 
 func (a *IPAddr) toAddr() sockaddr {
@@ -55,98 +54,12 @@ func (a *IPAddr) toAddr() sockaddr {
 // IPConn is the implementation of the Conn and PacketConn
 // interfaces for IP network connections.
 type IPConn struct {
-	fd *netFD
+	conn
 }
 
-func newIPConn(fd *netFD) *IPConn { return &IPConn{fd} }
+func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
 
-func (c *IPConn) ok() bool { return c != nil && c.fd != nil }
-
-// Implementation of the Conn interface - see Conn for documentation.
-
-// Read implements the Conn Read method.
-func (c *IPConn) Read(b []byte) (int, error) {
-	n, _, err := c.ReadFrom(b)
-	return n, err
-}
-
-// Write implements the Conn Write method.
-func (c *IPConn) Write(b []byte) (int, error) {
-	if !c.ok() {
-		return 0, syscall.EINVAL
-	}
-	return c.fd.Write(b)
-}
-
-// Close closes the IP connection.
-func (c *IPConn) Close() error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return c.fd.Close()
-}
-
-// LocalAddr returns the local network address.
-func (c *IPConn) LocalAddr() Addr {
-	if !c.ok() {
-		return nil
-	}
-	return c.fd.laddr
-}
-
-// RemoteAddr returns the remote network address, a *IPAddr.
-func (c *IPConn) RemoteAddr() Addr {
-	if !c.ok() {
-		return nil
-	}
-	return c.fd.raddr
-}
-
-// SetDeadline implements the Conn SetDeadline method.
-func (c *IPConn) SetDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setDeadline(c.fd, t)
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *IPConn) SetReadDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setReadDeadline(c.fd, t)
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *IPConn) SetWriteDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setWriteDeadline(c.fd, t)
-}
-
-// SetReadBuffer sets the size of the operating system's
-// receive buffer associated with the connection.
-func (c *IPConn) SetReadBuffer(bytes int) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setReadBuffer(c.fd, bytes)
-}
-
-// SetWriteBuffer sets the size of the operating system's
-// transmit buffer associated with the connection.
-func (c *IPConn) SetWriteBuffer(bytes int) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setWriteBuffer(c.fd, bytes)
-}
-
-// IP-specific methods.
-
-// ReadFromIP reads a IP packet from c, copying the payload into b.
+// ReadFromIP reads an IP packet from c, copying the payload into b.
 // It returns the number of bytes copied into b and the return address
 // that was on the packet.
 //
@@ -163,14 +76,14 @@ func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
 	n, sa, err := c.fd.ReadFrom(b)
 	switch sa := sa.(type) {
 	case *syscall.SockaddrInet4:
-		addr = &IPAddr{sa.Addr[0:]}
+		addr = &IPAddr{IP: sa.Addr[0:]}
 		if len(b) >= IPv4len { // discard ipv4 header
 			hsize := (int(b[0]) & 0xf) * 4
 			copy(b, b[hsize:])
 			n -= hsize
 		}
 	case *syscall.SockaddrInet6:
-		addr = &IPAddr{sa.Addr[0:]}
+		addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
 	}
 	return n, addr, err
 }
@@ -180,11 +93,30 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
 	if !c.ok() {
 		return 0, nil, syscall.EINVAL
 	}
-	n, uaddr, err := c.ReadFromIP(b)
-	return n, uaddr.toAddr(), err
+	n, addr, err := c.ReadFromIP(b)
+	return n, addr.toAddr(), err
+}
+
+// ReadMsgIP reads a packet from c, copying the payload into b and the
+// associdated out-of-band data into oob.  It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet and the source address of the packet.
+func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
+	if !c.ok() {
+		return 0, 0, 0, nil, syscall.EINVAL
+	}
+	var sa syscall.Sockaddr
+	n, oobn, flags, sa, err = c.fd.ReadMsg(b, oob)
+	switch sa := sa.(type) {
+	case *syscall.SockaddrInet4:
+		addr = &IPAddr{IP: sa.Addr[0:]}
+	case *syscall.SockaddrInet6:
+		addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
+	}
+	return
 }
 
-// WriteToIP writes a IP packet to addr via c, copying the payload from b.
+// WriteToIP writes an IP packet to addr via c, copying the payload from b.
 //
 // WriteToIP can be made to time out and return
 // an error with Timeout() == true after a fixed time limit;
@@ -213,22 +145,40 @@ func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
 	return c.WriteToIP(b, a)
 }
 
+// WriteMsgIP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob.  It returns the
+// number of payload and out-of-band bytes written.
+func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
+	if !c.ok() {
+		return 0, 0, syscall.EINVAL
+	}
+	sa, err := addr.sockaddr(c.fd.family)
+	if err != nil {
+		return 0, 0, &OpError{"write", c.fd.net, addr, err}
+	}
+	return c.fd.WriteMsg(b, oob, sa)
+}
+
 // DialIP connects to the remote address raddr on the network protocol netProto,
 // which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
 func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
-	net, proto, err := parseDialNetwork(netProto)
+	return dialIP(netProto, laddr, raddr, noDeadline)
+}
+
+func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
+	net, proto, err := parseNetwork(netProto)
 	if err != nil {
 		return nil, err
 	}
 	switch net {
 	case "ip", "ip4", "ip6":
 	default:
-		return nil, UnknownNetworkError(net)
+		return nil, UnknownNetworkError(netProto)
 	}
 	if raddr == nil {
 		return nil, &OpError{"dial", netProto, nil, errMissingAddress}
 	}
-	fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
+	fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
 	if err != nil {
 		return nil, err
 	}
@@ -240,23 +190,18 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
 // and WriteTo methods can be used to receive and send IP
 // packets with per-packet addressing.
 func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
-	net, proto, err := parseDialNetwork(netProto)
+	net, proto, err := parseNetwork(netProto)
 	if err != nil {
 		return nil, err
 	}
 	switch net {
 	case "ip", "ip4", "ip6":
 	default:
-		return nil, UnknownNetworkError(net)
+		return nil, UnknownNetworkError(netProto)
 	}
-	fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
+	fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
 	if err != nil {
 		return nil, err
 	}
 	return newIPConn(fd), nil
 }
-
-// File returns a copy of the underlying os.File, set to blocking mode.
-// 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 (c *IPConn) File() (f *os.File, err error) { return c.fd.dup() }
diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go
index bfbce18..1ef4892 100644
--- a/src/pkg/net/ipsock.go
+++ b/src/pkg/net/ipsock.go
@@ -2,11 +2,18 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// IP sockets
+// Internet protocol family sockets
 
 package net
 
-var supportsIPv6, supportsIPv4map = probeIPv6Stack()
+import "time"
+
+var supportsIPv6, supportsIPv4map bool
+
+func init() {
+	sysInit()
+	supportsIPv6, supportsIPv4map = probeIPv6Stack()
+}
 
 func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) {
 	if filter == nil {
@@ -65,25 +72,67 @@ func (e InvalidAddrError) Temporary() bool { return false }
 // "host:port" or "[host]:port" into host and port.
 // The latter form must be used when host contains a colon.
 func SplitHostPort(hostport string) (host, port string, err error) {
+	host, port, _, err = splitHostPort(hostport)
+	return
+}
+
+func splitHostPort(hostport string) (host, port, zone string, err error) {
+	j, k := 0, 0
+
 	// The port starts after the last colon.
 	i := last(hostport, ':')
 	if i < 0 {
-		err = &AddrError{"missing port in address", hostport}
-		return
+		goto missingPort
 	}
 
-	host, port = hostport[0:i], hostport[i+1:]
-
-	// Can put brackets around host ...
-	if len(host) > 0 && host[0] == '[' && host[len(host)-1] == ']' {
-		host = host[1 : len(host)-1]
+	if hostport[0] == '[' {
+		// Expect the first ']' just before the last ':'.
+		end := byteIndex(hostport, ']')
+		if end < 0 {
+			err = &AddrError{"missing ']' in address", hostport}
+			return
+		}
+		switch end + 1 {
+		case len(hostport):
+			// There can't be a ':' behind the ']' now.
+			goto missingPort
+		case i:
+			// The expected result.
+		default:
+			// Either ']' isn't followed by a colon, or it is
+			// followed by a colon that is not the last one.
+			if hostport[end+1] == ':' {
+				goto tooManyColons
+			}
+			goto missingPort
+		}
+		host = hostport[1:end]
+		j, k = 1, end+1 // there can't be a '[' resp. ']' before these positions
 	} else {
-		// ... but if there are no brackets, no colons.
+		host = hostport[:i]
+
 		if byteIndex(host, ':') >= 0 {
-			err = &AddrError{"too many colons in address", hostport}
-			return
+			goto tooManyColons
 		}
 	}
+	if byteIndex(hostport[j:], '[') >= 0 {
+		err = &AddrError{"unexpected '[' in address", hostport}
+		return
+	}
+	if byteIndex(hostport[k:], ']') >= 0 {
+		err = &AddrError{"unexpected ']' in address", hostport}
+		return
+	}
+
+	port = hostport[i+1:]
+	return
+
+missingPort:
+	err = &AddrError{"missing port in address", hostport}
+	return
+
+tooManyColons:
+	err = &AddrError{"too many colons in address", hostport}
 	return
 }
 
@@ -97,49 +146,84 @@ func JoinHostPort(host, port string) string {
 	return host + ":" + port
 }
 
-// Convert "host:port" into IP address and port.
-func hostPortToIP(net, hostport string) (ip IP, iport int, err error) {
-	host, port, err := SplitHostPort(hostport)
-	if err != nil {
-		return nil, 0, err
-	}
-
-	var addr IP
-	if host != "" {
-		// Try as an IP address.
-		addr = ParseIP(host)
-		if addr == nil {
-			var filter func(IP) IP
-			if net != "" && net[len(net)-1] == '4' {
-				filter = ipv4only
+func resolveInternetAddr(net, addr string, deadline time.Time) (Addr, error) {
+	var (
+		err              error
+		host, port, zone string
+		portnum          int
+	)
+	switch net {
+	case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
+		if addr != "" {
+			if host, port, zone, err = splitHostPort(addr); err != nil {
+				return nil, err
 			}
-			if net != "" && net[len(net)-1] == '6' {
-				filter = ipv6only
-			}
-			// Not an IP address.  Try as a DNS name.
-			addrs, err := LookupHost(host)
-			if err != nil {
-				return nil, 0, err
-			}
-			addr = firstFavoriteAddr(filter, addrs)
-			if addr == nil {
-				// should not happen
-				return nil, 0, &AddrError{"LookupHost returned no suitable address", addrs[0]}
+			if portnum, err = parsePort(net, port); err != nil {
+				return nil, err
 			}
 		}
+	case "ip", "ip4", "ip6":
+		if addr != "" {
+			host = addr
+		}
+	default:
+		return nil, UnknownNetworkError(net)
 	}
-
-	p, i, ok := dtoi(port, 0)
-	if !ok || i != len(port) {
-		p, err = LookupPort(net, port)
-		if err != nil {
-			return nil, 0, err
+	inetaddr := func(net string, ip IP, port int, zone string) Addr {
+		switch net {
+		case "tcp", "tcp4", "tcp6":
+			return &TCPAddr{IP: ip, Port: port, Zone: zone}
+		case "udp", "udp4", "udp6":
+			return &UDPAddr{IP: ip, Port: port, Zone: zone}
+		case "ip", "ip4", "ip6":
+			return &IPAddr{IP: ip, Zone: zone}
 		}
+		return nil
+	}
+	if host == "" {
+		return inetaddr(net, nil, portnum, zone), nil
 	}
-	if p < 0 || p > 0xFFFF {
-		return nil, 0, &AddrError{"invalid port", port}
+	// Try as an IP address.
+	if ip := ParseIP(host); ip != nil {
+		return inetaddr(net, ip, portnum, zone), nil
 	}
+	var filter func(IP) IP
+	if net != "" && net[len(net)-1] == '4' {
+		filter = ipv4only
+	}
+	if net != "" && net[len(net)-1] == '6' {
+		filter = ipv6only
+	}
+	// Try as a DNS name.
+	addrs, err := lookupHostDeadline(host, deadline)
+	if err != nil {
+		return nil, err
+	}
+	ip := firstFavoriteAddr(filter, addrs)
+	if ip == nil {
+		// should not happen
+		return nil, &AddrError{"LookupHost returned no suitable address", addrs[0]}
+	}
+	return inetaddr(net, ip, portnum, zone), nil
+}
 
-	return addr, p, nil
+func zoneToString(zone int) string {
+	if zone == 0 {
+		return ""
+	}
+	if ifi, err := InterfaceByIndex(zone); err == nil {
+		return ifi.Name
+	}
+	return itod(uint(zone))
+}
 
+func zoneToInt(zone string) int {
+	if zone == "" {
+		return 0
+	}
+	if ifi, err := InterfaceByName(zone); err == nil {
+		return ifi.Index
+	}
+	n, _, _ := dtoi(zone, 0)
+	return n
 }
diff --git a/src/pkg/net/ipsock_plan9.go b/src/pkg/net/ipsock_plan9.go
index eab0bf3..c7d542d 100644
--- a/src/pkg/net/ipsock_plan9.go
+++ b/src/pkg/net/ipsock_plan9.go
@@ -2,21 +2,22 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// IP sockets stubs for Plan 9
+// Internet protocol family sockets for Plan 9
 
 package net
 
 import (
 	"errors"
-	"io"
 	"os"
 	"syscall"
-	"time"
 )
 
-// probeIPv6Stack returns two boolean values.  If the first boolean value is
-// true, kernel supports basic IPv6 functionality.  If the second
-// boolean value is true, kernel supports IPv6 IPv4-mapping.
+// /sys/include/ape/sys/socket.h:/SOMAXCONN
+var listenerBacklog = 5
+
+// probeIPv6Stack returns two boolean values.  If the first boolean
+// value is true, kernel supports basic IPv6 functionality.  If the
+// second boolean value is true, kernel supports IPv6 IPv4-mapping.
 func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
 	return false, false
 }
@@ -48,6 +49,7 @@ func readPlan9Addr(proto, filename string) (addr Addr, err error) {
 	if err != nil {
 		return
 	}
+	defer f.Close()
 	n, err := f.Read(buf[:])
 	if err != nil {
 		return
@@ -58,110 +60,15 @@ func readPlan9Addr(proto, filename string) (addr Addr, err error) {
 	}
 	switch proto {
 	case "tcp":
-		addr = &TCPAddr{ip, port}
+		addr = &TCPAddr{IP: ip, Port: port}
 	case "udp":
-		addr = &UDPAddr{ip, port}
+		addr = &UDPAddr{IP: ip, Port: port}
 	default:
 		return nil, errors.New("unknown protocol " + proto)
 	}
 	return addr, nil
 }
 
-type plan9Conn struct {
-	proto, name, dir string
-	ctl, data        *os.File
-	laddr, raddr     Addr
-}
-
-func newPlan9Conn(proto, name string, ctl *os.File, laddr, raddr Addr) *plan9Conn {
-	return &plan9Conn{proto, name, "/net/" + proto + "/" + name, ctl, nil, laddr, raddr}
-}
-
-func (c *plan9Conn) ok() bool { return c != nil && c.ctl != nil }
-
-// Implementation of the Conn interface - see Conn for documentation.
-
-// Read implements the Conn Read method.
-func (c *plan9Conn) Read(b []byte) (n int, err error) {
-	if !c.ok() {
-		return 0, syscall.EINVAL
-	}
-	if c.data == nil {
-		c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
-		if err != nil {
-			return 0, err
-		}
-	}
-	n, err = c.data.Read(b)
-	if c.proto == "udp" && err == io.EOF {
-		n = 0
-		err = nil
-	}
-	return
-}
-
-// Write implements the Conn Write method.
-func (c *plan9Conn) Write(b []byte) (n int, err error) {
-	if !c.ok() {
-		return 0, syscall.EINVAL
-	}
-	if c.data == nil {
-		c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
-		if err != nil {
-			return 0, err
-		}
-	}
-	return c.data.Write(b)
-}
-
-// Close closes the connection.
-func (c *plan9Conn) Close() error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	err := c.ctl.Close()
-	if err != nil {
-		return err
-	}
-	if c.data != nil {
-		err = c.data.Close()
-	}
-	c.ctl = nil
-	c.data = nil
-	return err
-}
-
-// LocalAddr returns the local network address.
-func (c *plan9Conn) LocalAddr() Addr {
-	if !c.ok() {
-		return nil
-	}
-	return c.laddr
-}
-
-// RemoteAddr returns the remote network address.
-func (c *plan9Conn) RemoteAddr() Addr {
-	if !c.ok() {
-		return nil
-	}
-	return c.raddr
-}
-
-// SetDeadline implements the Conn SetDeadline method.
-func (c *plan9Conn) SetDeadline(t time.Time) error {
-	return syscall.EPLAN9
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *plan9Conn) SetReadDeadline(t time.Time) error {
-	return syscall.EPLAN9
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *plan9Conn) SetWriteDeadline(t time.Time) error {
-	return syscall.EPLAN9
-}
-
 func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err error) {
 	var (
 		ip   IP
@@ -192,98 +99,95 @@ func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string,
 	var buf [16]byte
 	n, err := f.Read(buf[:])
 	if err != nil {
+		f.Close()
 		return
 	}
 	return f, dest, proto, string(buf[:n]), nil
 }
 
-func dialPlan9(net string, laddr, raddr Addr) (c *plan9Conn, err error) {
+func netErr(e error) {
+	oe, ok := e.(*OpError)
+	if !ok {
+		return
+	}
+	if pe, ok := oe.Err.(*os.PathError); ok {
+		if _, ok = pe.Err.(syscall.ErrorString); ok {
+			oe.Err = pe.Err
+		}
+	}
+}
+
+func dialPlan9(net string, laddr, raddr Addr) (fd *netFD, err error) {
+	defer func() { netErr(err) }()
 	f, dest, proto, name, err := startPlan9(net, raddr)
 	if err != nil {
-		return
+		return nil, &OpError{"dial", net, raddr, err}
 	}
 	_, err = f.WriteString("connect " + dest)
 	if err != nil {
-		return
+		f.Close()
+		return nil, &OpError{"dial", f.Name(), raddr, err}
 	}
-	laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
+	data, err := os.OpenFile("/net/"+proto+"/"+name+"/data", os.O_RDWR, 0)
 	if err != nil {
-		return
+		f.Close()
+		return nil, &OpError{"dial", net, raddr, err}
 	}
-	raddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/remote")
+	laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
 	if err != nil {
-		return
+		data.Close()
+		f.Close()
+		return nil, &OpError{"dial", proto, raddr, err}
 	}
-	return newPlan9Conn(proto, name, f, laddr, raddr), nil
-}
-
-type plan9Listener struct {
-	proto, name, dir string
-	ctl              *os.File
-	laddr            Addr
+	return newFD(proto, name, f, data, laddr, raddr), nil
 }
 
-func listenPlan9(net string, laddr Addr) (l *plan9Listener, err error) {
+func listenPlan9(net string, laddr Addr) (fd *netFD, err error) {
+	defer func() { netErr(err) }()
 	f, dest, proto, name, err := startPlan9(net, laddr)
 	if err != nil {
-		return
+		return nil, &OpError{"listen", net, laddr, err}
 	}
 	_, err = f.WriteString("announce " + dest)
 	if err != nil {
-		return
+		f.Close()
+		return nil, &OpError{"announce", proto, laddr, err}
 	}
 	laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
 	if err != nil {
-		return
+		f.Close()
+		return nil, &OpError{Op: "listen", Net: net, Err: err}
 	}
-	l = new(plan9Listener)
-	l.proto = proto
-	l.name = name
-	l.dir = "/net/" + proto + "/" + name
-	l.ctl = f
-	l.laddr = laddr
-	return l, nil
+	return newFD(proto, name, f, nil, laddr, nil), nil
 }
 
-func (l *plan9Listener) plan9Conn() *plan9Conn {
-	return newPlan9Conn(l.proto, l.name, l.ctl, l.laddr, nil)
+func (l *netFD) netFD() *netFD {
+	return newFD(l.proto, l.name, l.ctl, l.data, l.laddr, l.raddr)
 }
 
-func (l *plan9Listener) acceptPlan9() (c *plan9Conn, err error) {
+func (l *netFD) acceptPlan9() (fd *netFD, err error) {
+	defer func() { netErr(err) }()
 	f, err := os.Open(l.dir + "/listen")
 	if err != nil {
-		return
+		return nil, &OpError{"accept", l.dir + "/listen", l.laddr, err}
 	}
 	var buf [16]byte
 	n, err := f.Read(buf[:])
 	if err != nil {
-		return
+		f.Close()
+		return nil, &OpError{"accept", l.dir + "/listen", l.laddr, err}
 	}
 	name := string(buf[:n])
-	laddr, err := readPlan9Addr(l.proto, l.dir+"/local")
-	if err != nil {
-		return
-	}
-	raddr, err := readPlan9Addr(l.proto, l.dir+"/remote")
+	data, err := os.OpenFile("/net/"+l.proto+"/"+name+"/data", os.O_RDWR, 0)
 	if err != nil {
-		return
+		f.Close()
+		return nil, &OpError{"accept", l.proto, l.laddr, err}
 	}
-	return newPlan9Conn(l.proto, name, f, laddr, raddr), nil
-}
-
-func (l *plan9Listener) Accept() (c Conn, err error) {
-	c1, err := l.acceptPlan9()
+	raddr, err := readPlan9Addr(l.proto, "/net/"+l.proto+"/"+name+"/remote")
 	if err != nil {
-		return
+		data.Close()
+		f.Close()
+		return nil, &OpError{"accept", l.proto, l.laddr, err}
 	}
-	return c1, nil
+	return newFD(l.proto, name, f, data, l.laddr, raddr), nil
 }
-
-func (l *plan9Listener) Close() error {
-	if l == nil || l.ctl == nil {
-		return syscall.EINVAL
-	}
-	return l.ctl.Close()
-}
-
-func (l *plan9Listener) Addr() Addr { return l.laddr }
diff --git a/src/pkg/net/ipsock_posix.go b/src/pkg/net/ipsock_posix.go
index ed31319..4c37616 100644
--- a/src/pkg/net/ipsock_posix.go
+++ b/src/pkg/net/ipsock_posix.go
@@ -4,9 +4,14 @@
 
 // +build darwin freebsd linux netbsd openbsd windows
 
+// Internet protocol family sockets for POSIX
+
 package net
 
-import "syscall"
+import (
+	"syscall"
+	"time"
+)
 
 // Should we try to use the IPv4 socket interface if we're
 // only dealing with IPv4 sockets?  As long as the host system
@@ -97,10 +102,13 @@ func favoriteAddrFamily(net string, laddr, raddr sockaddr, mode string) (family
 		return syscall.AF_INET6, true
 	}
 
-	if mode == "listen" && laddr.isWildcard() {
+	if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
 		if supportsIPv4map {
 			return syscall.AF_INET6, false
 		}
+		if laddr == nil {
+			return syscall.AF_INET, false
+		}
 		return laddr.family(), false
 	}
 
@@ -122,7 +130,7 @@ type sockaddr interface {
 	sockaddr(family int) (syscall.Sockaddr, error)
 }
 
-func internetSocket(net string, laddr, raddr sockaddr, 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, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
 	var la, ra syscall.Sockaddr
 	family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
 	if laddr != nil {
@@ -135,7 +143,7 @@ func internetSocket(net string, laddr, raddr sockaddr, sotype, proto int, mode s
 			goto Error
 		}
 	}
-	fd, err = socket(net, family, sotype, proto, ipv6only, la, ra, toAddr)
+	fd, err = socket(net, family, sotype, proto, ipv6only, la, ra, deadline, toAddr)
 	if err != nil {
 		goto Error
 	}
@@ -149,7 +157,7 @@ Error:
 	return nil, &OpError{mode, net, addr, err}
 }
 
-func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, error) {
+func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
 	switch family {
 	case syscall.AF_INET:
 		if len(ip) == 0 {
@@ -158,12 +166,12 @@ func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, error) {
 		if ip = ip.To4(); ip == nil {
 			return nil, InvalidAddrError("non-IPv4 address")
 		}
-		s := new(syscall.SockaddrInet4)
+		sa := new(syscall.SockaddrInet4)
 		for i := 0; i < IPv4len; i++ {
-			s.Addr[i] = ip[i]
+			sa.Addr[i] = ip[i]
 		}
-		s.Port = port
-		return s, nil
+		sa.Port = port
+		return sa, nil
 	case syscall.AF_INET6:
 		if len(ip) == 0 {
 			ip = IPv6zero
@@ -177,12 +185,13 @@ func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, error) {
 		if ip = ip.To16(); ip == nil {
 			return nil, InvalidAddrError("non-IPv6 address")
 		}
-		s := new(syscall.SockaddrInet6)
+		sa := new(syscall.SockaddrInet6)
 		for i := 0; i < IPv6len; i++ {
-			s.Addr[i] = ip[i]
+			sa.Addr[i] = ip[i]
 		}
-		s.Port = port
-		return s, nil
+		sa.Port = port
+		sa.ZoneId = uint32(zoneToInt(zone))
+		return sa, nil
 	}
 	return nil, InvalidAddrError("unexpected socket family")
 }
diff --git a/src/pkg/net/lookup.go b/src/pkg/net/lookup.go
new file mode 100644
index 0000000..bec93ec
--- /dev/null
+++ b/src/pkg/net/lookup.go
@@ -0,0 +1,105 @@
+// 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 net
+
+import (
+	"time"
+)
+
+// LookupHost looks up the given host using the local resolver.
+// It returns an array of that host's addresses.
+func LookupHost(host string) (addrs []string, err error) {
+	return lookupHost(host)
+}
+
+func lookupHostDeadline(host string, deadline time.Time) (addrs []string, err error) {
+	if deadline.IsZero() {
+		return lookupHost(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.
+	timeout := deadline.Sub(time.Now())
+	if timeout <= 0 {
+		err = errTimeout
+		return
+	}
+	t := time.NewTimer(timeout)
+	defer t.Stop()
+	type res struct {
+		addrs []string
+		err   error
+	}
+	resc := make(chan res, 1)
+	go func() {
+		a, err := lookupHost(host)
+		resc <- res{a, err}
+	}()
+	select {
+	case <-t.C:
+		err = errTimeout
+	case r := <-resc:
+		addrs, err = r.addrs, r.err
+	}
+	return
+}
+
+// LookupIP looks up host using the local resolver.
+// It returns an array of that host's IPv4 and IPv6 addresses.
+func LookupIP(host string) (addrs []IP, err error) {
+	return lookupIP(host)
+}
+
+// LookupPort looks up the port for the given network and service.
+func LookupPort(network, service string) (port int, err error) {
+	return lookupPort(network, service)
+}
+
+// LookupCNAME returns the canonical DNS host for the given name.
+// Callers that do not care about the canonical name can call
+// LookupHost or LookupIP directly; both take care of resolving
+// the canonical name as part of the lookup.
+func LookupCNAME(name string) (cname string, err error) {
+	return lookupCNAME(name)
+}
+
+// LookupSRV tries to resolve an SRV query of the given service,
+// protocol, and domain name.  The proto is "tcp" or "udp".
+// The returned records are sorted by priority and randomized
+// by weight within a priority.
+//
+// LookupSRV constructs the DNS name to look up following RFC 2782.
+// That is, it looks up _service._proto.name.  To accommodate services
+// publishing SRV records under non-standard names, if both service
+// and proto are empty strings, LookupSRV looks up name directly.
+func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+	return lookupSRV(service, proto, name)
+}
+
+// LookupMX returns the DNS MX records for the given domain name sorted by preference.
+func LookupMX(name string) (mx []*MX, err error) {
+	return lookupMX(name)
+}
+
+// LookupNS returns the DNS NS records for the given domain name.
+func LookupNS(name string) (ns []*NS, err error) {
+	return lookupNS(name)
+}
+
+// LookupTXT returns the DNS TXT records for the given domain name.
+func LookupTXT(name string) (txt []string, err error) {
+	return lookupTXT(name)
+}
+
+// LookupAddr performs a reverse lookup for the given address, returning a list
+// of names mapping to that address.
+func LookupAddr(addr string) (name []string, err error) {
+	return lookupAddr(addr)
+}
diff --git a/src/pkg/net/lookup_plan9.go b/src/pkg/net/lookup_plan9.go
index 2c69830..ae7cf79 100644
--- a/src/pkg/net/lookup_plan9.go
+++ b/src/pkg/net/lookup_plan9.go
@@ -201,6 +201,21 @@ func lookupMX(name string) (mx []*MX, err error) {
 	return
 }
 
+func lookupNS(name string) (ns []*NS, err error) {
+	lines, err := queryDNS(name, "ns")
+	if err != nil {
+		return
+	}
+	for _, line := range lines {
+		f := getFields(line)
+		if len(f) < 4 {
+			continue
+		}
+		ns = append(ns, &NS{f[3]})
+	}
+	return
+}
+
 func lookupTXT(name string) (txt []string, err error) {
 	lines, err := queryDNS(name, "txt")
 	if err != nil {
diff --git a/src/pkg/net/lookup_test.go b/src/pkg/net/lookup_test.go
index 3a61dfb..3355e46 100644
--- a/src/pkg/net/lookup_test.go
+++ b/src/pkg/net/lookup_test.go
@@ -9,6 +9,7 @@ package net
 
 import (
 	"flag"
+	"strings"
 	"testing"
 )
 
@@ -16,8 +17,7 @@ var testExternal = flag.Bool("external", true, "allow use of external networks d
 
 func TestGoogleSRV(t *testing.T) {
 	if testing.Short() || !*testExternal {
-		t.Logf("skipping test to avoid external network")
-		return
+		t.Skip("skipping test to avoid external network")
 	}
 	_, addrs, err := LookupSRV("xmpp-server", "tcp", "google.com")
 	if err != nil {
@@ -39,8 +39,7 @@ func TestGoogleSRV(t *testing.T) {
 
 func TestGmailMX(t *testing.T) {
 	if testing.Short() || !*testExternal {
-		t.Logf("skipping test to avoid external network")
-		return
+		t.Skip("skipping test to avoid external network")
 	}
 	mx, err := LookupMX("gmail.com")
 	if err != nil {
@@ -51,10 +50,22 @@ func TestGmailMX(t *testing.T) {
 	}
 }
 
+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.Logf("skipping test to avoid external network")
-		return
+		t.Skip("skipping test to avoid external network")
 	}
 	txt, err := LookupTXT("gmail.com")
 	if err != nil {
@@ -67,8 +78,7 @@ func TestGmailTXT(t *testing.T) {
 
 func TestGoogleDNSAddr(t *testing.T) {
 	if testing.Short() || !*testExternal {
-		t.Logf("skipping test to avoid external network")
-		return
+		t.Skip("skipping test to avoid external network")
 	}
 	names, err := LookupAddr("8.8.8.8")
 	if err != nil {
@@ -79,6 +89,16 @@ func TestGoogleDNSAddr(t *testing.T) {
 	}
 }
 
+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
diff --git a/src/pkg/net/lookup_unix.go b/src/pkg/net/lookup_unix.go
index d500a12..fa98eed 100644
--- a/src/pkg/net/lookup_unix.go
+++ b/src/pkg/net/lookup_unix.go
@@ -119,6 +119,19 @@ func lookupMX(name string) (mx []*MX, err error) {
 	return
 }
 
+func lookupNS(name string) (ns []*NS, err error) {
+	_, records, err := lookup(name, dnsTypeNS)
+	if err != nil {
+		return
+	}
+	ns = make([]*NS, len(records))
+	for i, r := range records {
+		r := r.(*dnsRR_NS)
+		ns[i] = &NS{r.Ns}
+	}
+	return
+}
+
 func lookupTXT(name string) (txt []string, err error) {
 	_, records, err := lookup(name, dnsTypeTXT)
 	if err != nil {
diff --git a/src/pkg/net/lookup_windows.go b/src/pkg/net/lookup_windows.go
index 99783e9..3b29724 100644
--- a/src/pkg/net/lookup_windows.go
+++ b/src/pkg/net/lookup_windows.go
@@ -6,21 +6,17 @@ package net
 
 import (
 	"os"
-	"sync"
+	"runtime"
 	"syscall"
 	"unsafe"
 )
 
 var (
-	protoentLock sync.Mutex
-	hostentLock  sync.Mutex
-	serventLock  sync.Mutex
+	lookupPort = oldLookupPort
+	lookupIP   = oldLookupIP
 )
 
-// lookupProtocol looks up IP protocol name and returns correspondent protocol number.
-func lookupProtocol(name string) (proto int, err error) {
-	protoentLock.Lock()
-	defer protoentLock.Unlock()
+func getprotobyname(name string) (proto int, err error) {
 	p, err := syscall.GetProtoByName(name)
 	if err != nil {
 		return 0, os.NewSyscallError("GetProtoByName", err)
@@ -28,6 +24,25 @@ func lookupProtocol(name string) (proto int, err error) {
 	return int(p.Proto), nil
 }
 
+// lookupProtocol looks up IP protocol name and returns correspondent protocol number.
+func lookupProtocol(name string) (proto int, err error) {
+	// GetProtoByName return value is stored in thread local storage.
+	// Start new os thread before the call to prevent races.
+	type result struct {
+		proto int
+		err   error
+	}
+	ch := make(chan result)
+	go func() {
+		runtime.LockOSThread()
+		defer runtime.UnlockOSThread()
+		proto, err := getprotobyname(name)
+		ch <- result{proto: proto, err: err}
+	}()
+	r := <-ch
+	return r.proto, r.err
+}
+
 func lookupHost(name string) (addrs []string, err error) {
 	ips, err := LookupIP(name)
 	if err != nil {
@@ -40,9 +55,7 @@ func lookupHost(name string) (addrs []string, err error) {
 	return
 }
 
-func lookupIP(name string) (addrs []IP, err error) {
-	hostentLock.Lock()
-	defer hostentLock.Unlock()
+func gethostbyname(name string) (addrs []IP, err error) {
 	h, err := syscall.GetHostByName(name)
 	if err != nil {
 		return nil, os.NewSyscallError("GetHostByName", err)
@@ -56,20 +69,65 @@ func lookupIP(name string) (addrs []IP, err error) {
 		}
 		addrs = addrs[0:i]
 	default: // TODO(vcc): Implement non IPv4 address lookups.
-		return nil, os.NewSyscallError("LookupHost", syscall.EWINDOWS)
+		return nil, os.NewSyscallError("LookupIP", syscall.EWINDOWS)
 	}
 	return addrs, nil
 }
 
-func lookupPort(network, service string) (port int, err error) {
+func oldLookupIP(name string) (addrs []IP, err error) {
+	// GetHostByName return value is stored in thread local storage.
+	// Start new os thread before the call to prevent races.
+	type result struct {
+		addrs []IP
+		err   error
+	}
+	ch := make(chan result)
+	go func() {
+		runtime.LockOSThread()
+		defer runtime.UnlockOSThread()
+		addrs, err := gethostbyname(name)
+		ch <- result{addrs: addrs, err: err}
+	}()
+	r := <-ch
+	return r.addrs, r.err
+}
+
+func newLookupIP(name string) (addrs []IP, err error) {
+	hints := syscall.AddrinfoW{
+		Family:   syscall.AF_UNSPEC,
+		Socktype: syscall.SOCK_STREAM,
+		Protocol: syscall.IPPROTO_IP,
+	}
+	var result *syscall.AddrinfoW
+	e := syscall.GetAddrInfoW(syscall.StringToUTF16Ptr(name), nil, &hints, &result)
+	if e != nil {
+		return nil, os.NewSyscallError("GetAddrInfoW", e)
+	}
+	defer syscall.FreeAddrInfoW(result)
+	addrs = make([]IP, 0, 5)
+	for ; result != nil; result = result.Next {
+		addr := unsafe.Pointer(result.Addr)
+		switch result.Family {
+		case syscall.AF_INET:
+			a := (*syscall.RawSockaddrInet4)(addr).Addr
+			addrs = append(addrs, IPv4(a[0], a[1], a[2], a[3]))
+		case syscall.AF_INET6:
+			a := (*syscall.RawSockaddrInet6)(addr).Addr
+			addrs = append(addrs, IP{a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]})
+		default:
+			return nil, os.NewSyscallError("LookupIP", syscall.EWINDOWS)
+		}
+	}
+	return addrs, nil
+}
+
+func getservbyname(network, service string) (port int, err error) {
 	switch network {
 	case "tcp4", "tcp6":
 		network = "tcp"
 	case "udp4", "udp6":
 		network = "udp"
 	}
-	serventLock.Lock()
-	defer serventLock.Unlock()
 	s, err := syscall.GetServByName(service, network)
 	if err != nil {
 		return 0, os.NewSyscallError("GetServByName", err)
@@ -77,6 +135,58 @@ func lookupPort(network, service string) (port int, err error) {
 	return int(syscall.Ntohs(s.Port)), nil
 }
 
+func oldLookupPort(network, service string) (port int, err error) {
+	// GetServByName return value is stored in thread local storage.
+	// Start new os thread before the call to prevent races.
+	type result struct {
+		port int
+		err  error
+	}
+	ch := make(chan result)
+	go func() {
+		runtime.LockOSThread()
+		defer runtime.UnlockOSThread()
+		port, err := getservbyname(network, service)
+		ch <- result{port: port, err: err}
+	}()
+	r := <-ch
+	return r.port, r.err
+}
+
+func newLookupPort(network, service string) (port int, err error) {
+	var stype int32
+	switch network {
+	case "tcp4", "tcp6":
+		stype = syscall.SOCK_STREAM
+	case "udp4", "udp6":
+		stype = syscall.SOCK_DGRAM
+	}
+	hints := syscall.AddrinfoW{
+		Family:   syscall.AF_UNSPEC,
+		Socktype: stype,
+		Protocol: syscall.IPPROTO_IP,
+	}
+	var result *syscall.AddrinfoW
+	e := syscall.GetAddrInfoW(nil, syscall.StringToUTF16Ptr(service), &hints, &result)
+	if e != nil {
+		return 0, os.NewSyscallError("GetAddrInfoW", e)
+	}
+	defer syscall.FreeAddrInfoW(result)
+	if result == nil {
+		return 0, os.NewSyscallError("LookupPort", syscall.EINVAL)
+	}
+	addr := unsafe.Pointer(result.Addr)
+	switch result.Family {
+	case syscall.AF_INET:
+		a := (*syscall.RawSockaddrInet4)(addr)
+		return int(syscall.Ntohs(a.Port)), nil
+	case syscall.AF_INET6:
+		a := (*syscall.RawSockaddrInet6)(addr)
+		return int(syscall.Ntohs(a.Port)), nil
+	}
+	return 0, os.NewSyscallError("LookupPort", syscall.EINVAL)
+}
+
 func lookupCNAME(name string) (cname string, err error) {
 	var r *syscall.DNSRecord
 	e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
@@ -129,6 +239,21 @@ func lookupMX(name string) (mx []*MX, err error) {
 	return mx, nil
 }
 
+func lookupNS(name string) (ns []*NS, err error) {
+	var r *syscall.DNSRecord
+	e := syscall.DnsQuery(name, syscall.DNS_TYPE_NS, 0, nil, &r, nil)
+	if e != nil {
+		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 {
+		v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
+		ns = append(ns, &NS{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]) + "."})
+	}
+	return ns, nil
+}
+
 func lookupTXT(name string) (txt []string, err error) {
 	var r *syscall.DNSRecord
 	e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil)
diff --git a/src/pkg/net/mail/message.go b/src/pkg/net/mail/message.go
index b610ccf..96c796e 100644
--- a/src/pkg/net/mail/message.go
+++ b/src/pkg/net/mail/message.go
@@ -47,7 +47,8 @@ type Message struct {
 }
 
 // ReadMessage reads a message from r.
-// The headers are parsed, and the body of the message will be reading from r.
+// The headers are parsed, and the body of the message will be available
+// for reading from r.
 func ReadMessage(r io.Reader) (msg *Message, err error) {
 	tp := textproto.NewReader(bufio.NewReader(r))
 
@@ -126,7 +127,7 @@ func (h Header) AddressList(key string) ([]*Address, error) {
 	if hdr == "" {
 		return nil, ErrHeaderNotPresent
 	}
-	return newAddrParser(hdr).parseAddressList()
+	return ParseAddressList(hdr)
 }
 
 // Address represents a single mail address.
@@ -137,6 +138,16 @@ type Address struct {
 	Address string // user at domain
 }
 
+// Parses a single RFC 5322 address, e.g. "Barry Gibbs <bg at example.com>"
+func ParseAddress(address string) (*Address, error) {
+	return newAddrParser(address).parseAddress()
+}
+
+// ParseAddressList parses the given string as a list of addresses.
+func ParseAddressList(list string) ([]*Address, error) {
+	return newAddrParser(list).parseAddressList()
+}
+
 // String formats the address as a valid RFC 5322 address.
 // If the address's name contains non-ASCII characters
 // the name will be rendered according to RFC 2047.
diff --git a/src/pkg/net/mail/message_test.go b/src/pkg/net/mail/message_test.go
index fd17eb4..2e746f4 100644
--- a/src/pkg/net/mail/message_test.go
+++ b/src/pkg/net/mail/message_test.go
@@ -227,13 +227,24 @@ func TestAddressParsing(t *testing.T) {
 		},
 	}
 	for _, test := range tests {
-		addrs, err := newAddrParser(test.addrsStr).parseAddressList()
+		if len(test.exp) == 1 {
+			addr, err := ParseAddress(test.addrsStr)
+			if err != nil {
+				t.Errorf("Failed parsing (single) %q: %v", test.addrsStr, err)
+				continue
+			}
+			if !reflect.DeepEqual([]*Address{addr}, test.exp) {
+				t.Errorf("Parse (single) of %q: got %+v, want %+v", test.addrsStr, addr, test.exp)
+			}
+		}
+
+		addrs, err := ParseAddressList(test.addrsStr)
 		if err != nil {
-			t.Errorf("Failed parsing %q: %v", test.addrsStr, err)
+			t.Errorf("Failed parsing (list) %q: %v", test.addrsStr, err)
 			continue
 		}
 		if !reflect.DeepEqual(addrs, test.exp) {
-			t.Errorf("Parse of %q: got %+v, want %+v", test.addrsStr, addrs, test.exp)
+			t.Errorf("Parse (list) of %q: got %+v, want %+v", test.addrsStr, addrs, test.exp)
 		}
 	}
 }
diff --git a/src/pkg/net/multicast_posix_test.go b/src/pkg/net/multicast_posix_test.go
new file mode 100644
index 0000000..ff1edaf
--- /dev/null
+++ b/src/pkg/net/multicast_posix_test.go
@@ -0,0 +1,180 @@
+// 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 !plan9
+
+package net
+
+import (
+	"errors"
+	"os"
+	"runtime"
+	"testing"
+)
+
+var multicastListenerTests = []struct {
+	net   string
+	gaddr *UDPAddr
+	flags Flags
+	ipv6  bool // test with underlying AF_INET6 socket
+}{
+	// cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers
+
+	{"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, FlagUp | FlagLoopback, false},
+	{"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, 0, false},
+	{"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+	{"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, 0, true},
+
+	{"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, FlagUp | FlagLoopback, false},
+	{"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, 0, false},
+
+	{"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}, 0, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}, 0, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}, 0, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}, 0, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}, 0, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+	{"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, 0, true},
+}
+
+// TestMulticastListener tests both single and double listen to a test
+// listener with same address family, same group address and same port.
+func TestMulticastListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "netbsd", "openbsd", "plan9", "solaris", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	case "linux":
+		if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
+			t.Skipf("skipping test on %q/%q", runtime.GOOS, runtime.GOARCH)
+		}
+	}
+
+	for _, tt := range multicastListenerTests {
+		if tt.ipv6 && (!*testIPv6 || !supportsIPv6 || os.Getuid() != 0) {
+			continue
+		}
+		ifi, err := availMulticastInterface(t, tt.flags)
+		if err != nil {
+			continue
+		}
+		c1, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
+		if err != nil {
+			t.Fatalf("First ListenMulticastUDP failed: %v", err)
+		}
+		checkMulticastListener(t, err, c1, tt.gaddr)
+		c2, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
+		if err != nil {
+			t.Fatalf("Second ListenMulticastUDP failed: %v", err)
+		}
+		checkMulticastListener(t, err, c2, tt.gaddr)
+		c2.Close()
+		c1.Close()
+	}
+}
+
+func TestSimpleMulticastListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	case "windows":
+		if testing.Short() || !*testExternal {
+			t.Skip("skipping test on windows to avoid firewall")
+		}
+	}
+
+	for _, tt := range multicastListenerTests {
+		if tt.ipv6 {
+			continue
+		}
+		tt.flags = FlagUp | FlagMulticast // for windows testing
+		ifi, err := availMulticastInterface(t, tt.flags)
+		if err != nil {
+			continue
+		}
+		c1, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
+		if err != nil {
+			t.Fatalf("First ListenMulticastUDP failed: %v", err)
+		}
+		checkSimpleMulticastListener(t, err, c1, tt.gaddr)
+		c2, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
+		if err != nil {
+			t.Fatalf("Second ListenMulticastUDP failed: %v", err)
+		}
+		checkSimpleMulticastListener(t, err, c2, tt.gaddr)
+		c2.Close()
+		c1.Close()
+	}
+}
+
+func checkMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) {
+	if !multicastRIBContains(t, gaddr.IP) {
+		t.Errorf("%q not found in RIB", gaddr.String())
+		return
+	}
+	la := c.LocalAddr()
+	if la == nil {
+		t.Error("LocalAddr failed")
+		return
+	}
+	if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
+		t.Errorf("got %v; expected a proper address with non-zero port number", la)
+		return
+	}
+}
+
+func checkSimpleMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) {
+	la := c.LocalAddr()
+	if la == nil {
+		t.Error("LocalAddr failed")
+		return
+	}
+	if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
+		t.Errorf("got %v; expected a proper address with non-zero port number", la)
+		return
+	}
+}
+
+func availMulticastInterface(t *testing.T, flags Flags) (*Interface, error) {
+	var ifi *Interface
+	if flags != Flags(0) {
+		ift, err := Interfaces()
+		if err != nil {
+			t.Fatalf("Interfaces failed: %v", err)
+		}
+		for _, x := range ift {
+			if x.Flags&flags == flags {
+				ifi = &x
+				break
+			}
+		}
+		if ifi == nil {
+			return nil, errors.New("an appropriate multicast interface not found")
+		}
+	}
+	return ifi, nil
+}
+
+func multicastRIBContains(t *testing.T, ip IP) bool {
+	ift, err := Interfaces()
+	if err != nil {
+		t.Fatalf("Interfaces failed: %v", err)
+	}
+	for _, ifi := range ift {
+		ifmat, err := ifi.MulticastAddrs()
+		if err != nil {
+			t.Fatalf("MulticastAddrs failed: %v", err)
+		}
+		for _, ifma := range ifmat {
+			if ifma.(*IPAddr).IP.Equal(ip) {
+				return true
+			}
+		}
+	}
+	return false
+}
diff --git a/src/pkg/net/multicast_test.go b/src/pkg/net/multicast_test.go
deleted file mode 100644
index 67261b1..0000000
--- a/src/pkg/net/multicast_test.go
+++ /dev/null
@@ -1,234 +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 net
-
-import (
-	"errors"
-	"os"
-	"runtime"
-	"syscall"
-	"testing"
-)
-
-var multicastListenerTests = []struct {
-	net   string
-	gaddr *UDPAddr
-	flags Flags
-	ipv6  bool // test with underlying AF_INET6 socket
-}{
-	// cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers
-
-	{"udp", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false},
-	{"udp", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, 0, false},
-	{"udp", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, true},
-	{"udp", &UDPAddr{ParseIP("ff0e::114"), 12345}, 0, true},
-
-	{"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false},
-	{"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, 0, false},
-
-	{"udp6", &UDPAddr{ParseIP("ff01::114"), 12345}, FlagUp | FlagLoopback, true},
-	{"udp6", &UDPAddr{ParseIP("ff01::114"), 12345}, 0, true},
-	{"udp6", &UDPAddr{ParseIP("ff02::114"), 12345}, FlagUp | FlagLoopback, true},
-	{"udp6", &UDPAddr{ParseIP("ff02::114"), 12345}, 0, true},
-	{"udp6", &UDPAddr{ParseIP("ff04::114"), 12345}, FlagUp | FlagLoopback, true},
-	{"udp6", &UDPAddr{ParseIP("ff04::114"), 12345}, 0, true},
-	{"udp6", &UDPAddr{ParseIP("ff05::114"), 12345}, FlagUp | FlagLoopback, true},
-	{"udp6", &UDPAddr{ParseIP("ff05::114"), 12345}, 0, true},
-	{"udp6", &UDPAddr{ParseIP("ff08::114"), 12345}, FlagUp | FlagLoopback, true},
-	{"udp6", &UDPAddr{ParseIP("ff08::114"), 12345}, 0, true},
-	{"udp6", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, true},
-	{"udp6", &UDPAddr{ParseIP("ff0e::114"), 12345}, 0, true},
-}
-
-// TestMulticastListener tests both single and double listen to a test
-// listener with same address family, same group address and same port.
-func TestMulticastListener(t *testing.T) {
-	switch runtime.GOOS {
-	case "netbsd", "openbsd", "plan9", "windows":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
-	case "linux":
-		if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
-			t.Logf("skipping test on %q/%q", runtime.GOOS, runtime.GOARCH)
-			return
-		}
-	}
-
-	for _, tt := range multicastListenerTests {
-		if tt.ipv6 && (!supportsIPv6 || os.Getuid() != 0) {
-			continue
-		}
-		ifi, err := availMulticastInterface(t, tt.flags)
-		if err != nil {
-			continue
-		}
-		c1, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
-		if err != nil {
-			t.Fatalf("First ListenMulticastUDP failed: %v", err)
-		}
-		checkMulticastListener(t, err, c1, tt.gaddr)
-		c2, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
-		if err != nil {
-			t.Fatalf("Second ListenMulticastUDP failed: %v", err)
-		}
-		checkMulticastListener(t, err, c2, tt.gaddr)
-		c2.Close()
-		switch c1.fd.family {
-		case syscall.AF_INET:
-			testIPv4MulticastSocketOptions(t, c1.fd, ifi)
-		case syscall.AF_INET6:
-			testIPv6MulticastSocketOptions(t, c1.fd, ifi)
-		}
-		c1.Close()
-	}
-}
-
-func TestSimpleMulticastListener(t *testing.T) {
-	switch runtime.GOOS {
-	case "plan9":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
-	case "windows":
-		if testing.Short() || !*testExternal {
-			t.Logf("skipping test on windows to avoid firewall")
-			return
-		}
-	}
-
-	for _, tt := range multicastListenerTests {
-		if tt.ipv6 {
-			continue
-		}
-		tt.flags = FlagUp | FlagMulticast // for windows testing
-		ifi, err := availMulticastInterface(t, tt.flags)
-		if err != nil {
-			continue
-		}
-		c1, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
-		if err != nil {
-			t.Fatalf("First ListenMulticastUDP failed: %v", err)
-		}
-		checkSimpleMulticastListener(t, err, c1, tt.gaddr)
-		c2, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
-		if err != nil {
-			t.Fatalf("Second ListenMulticastUDP failed: %v", err)
-		}
-		checkSimpleMulticastListener(t, err, c2, tt.gaddr)
-		c2.Close()
-		c1.Close()
-	}
-}
-
-func checkMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) {
-	if !multicastRIBContains(t, gaddr.IP) {
-		t.Fatalf("%q not found in RIB", gaddr.String())
-	}
-	if c.LocalAddr().String() != gaddr.String() {
-		t.Fatalf("LocalAddr returns %q, expected %q", c.LocalAddr().String(), gaddr.String())
-	}
-}
-
-func checkSimpleMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) {
-	if c.LocalAddr().String() != gaddr.String() {
-		t.Fatalf("LocalAddr returns %q, expected %q", c.LocalAddr().String(), gaddr.String())
-	}
-}
-
-func availMulticastInterface(t *testing.T, flags Flags) (*Interface, error) {
-	var ifi *Interface
-	if flags != Flags(0) {
-		ift, err := Interfaces()
-		if err != nil {
-			t.Fatalf("Interfaces failed: %v", err)
-		}
-		for _, x := range ift {
-			if x.Flags&flags == flags {
-				ifi = &x
-				break
-			}
-		}
-		if ifi == nil {
-			return nil, errors.New("an appropriate multicast interface not found")
-		}
-	}
-	return ifi, nil
-}
-
-func multicastRIBContains(t *testing.T, ip IP) bool {
-	ift, err := Interfaces()
-	if err != nil {
-		t.Fatalf("Interfaces failed: %v", err)
-	}
-	for _, ifi := range ift {
-		ifmat, err := ifi.MulticastAddrs()
-		if err != nil {
-			t.Fatalf("MulticastAddrs failed: %v", err)
-		}
-		for _, ifma := range ifmat {
-			if ifma.(*IPAddr).IP.Equal(ip) {
-				return true
-			}
-		}
-	}
-	return false
-}
-
-func testIPv4MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
-	_, err := ipv4MulticastInterface(fd)
-	if err != nil {
-		t.Fatalf("ipv4MulticastInterface failed: %v", err)
-	}
-	if ifi != nil {
-		err = setIPv4MulticastInterface(fd, ifi)
-		if err != nil {
-			t.Fatalf("setIPv4MulticastInterface failed: %v", err)
-		}
-	}
-	_, err = ipv4MulticastTTL(fd)
-	if err != nil {
-		t.Fatalf("ipv4MulticastTTL failed: %v", err)
-	}
-	err = setIPv4MulticastTTL(fd, 1)
-	if err != nil {
-		t.Fatalf("setIPv4MulticastTTL failed: %v", err)
-	}
-	_, err = ipv4MulticastLoopback(fd)
-	if err != nil {
-		t.Fatalf("ipv4MulticastLoopback failed: %v", err)
-	}
-	err = setIPv4MulticastLoopback(fd, false)
-	if err != nil {
-		t.Fatalf("setIPv4MulticastLoopback failed: %v", err)
-	}
-}
-
-func testIPv6MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
-	_, err := ipv6MulticastInterface(fd)
-	if err != nil {
-		t.Fatalf("ipv6MulticastInterface failed: %v", err)
-	}
-	if ifi != nil {
-		err = setIPv6MulticastInterface(fd, ifi)
-		if err != nil {
-			t.Fatalf("setIPv6MulticastInterface failed: %v", err)
-		}
-	}
-	_, err = ipv6MulticastHopLimit(fd)
-	if err != nil {
-		t.Fatalf("ipv6MulticastHopLimit failed: %v", err)
-	}
-	err = setIPv6MulticastHopLimit(fd, 1)
-	if err != nil {
-		t.Fatalf("setIPv6MulticastHopLimit failed: %v", err)
-	}
-	_, err = ipv6MulticastLoopback(fd)
-	if err != nil {
-		t.Fatalf("ipv6MulticastLoopback failed: %v", err)
-	}
-	err = setIPv6MulticastLoopback(fd, false)
-	if err != nil {
-		t.Fatalf("setIPv6MulticastLoopback failed: %v", err)
-	}
-}
diff --git a/src/pkg/net/net.go b/src/pkg/net/net.go
index 9ebcdbe..72b2b64 100644
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -44,6 +44,10 @@ package net
 
 import (
 	"errors"
+	"io"
+	"os"
+	"sync"
+	"syscall"
 	"time"
 )
 
@@ -103,6 +107,105 @@ type Conn interface {
 	SetWriteDeadline(t time.Time) error
 }
 
+type conn struct {
+	fd *netFD
+}
+
+func (c *conn) ok() bool { return c != nil && c.fd != nil }
+
+// Implementation of the Conn interface.
+
+// Read implements the Conn Read method.
+func (c *conn) Read(b []byte) (int, error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	return c.fd.Read(b)
+}
+
+// Write implements the Conn Write method.
+func (c *conn) Write(b []byte) (int, error) {
+	if !c.ok() {
+		return 0, syscall.EINVAL
+	}
+	return c.fd.Write(b)
+}
+
+// Close closes the connection.
+func (c *conn) Close() error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.Close()
+}
+
+// LocalAddr returns the local network address.
+func (c *conn) LocalAddr() Addr {
+	if !c.ok() {
+		return nil
+	}
+	return c.fd.laddr
+}
+
+// RemoteAddr returns the remote network address.
+func (c *conn) RemoteAddr() Addr {
+	if !c.ok() {
+		return nil
+	}
+	return c.fd.raddr
+}
+
+// SetDeadline implements the Conn SetDeadline method.
+func (c *conn) SetDeadline(t time.Time) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setDeadline(c.fd, t)
+}
+
+// SetReadDeadline implements the Conn SetReadDeadline method.
+func (c *conn) SetReadDeadline(t time.Time) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setReadDeadline(c.fd, t)
+}
+
+// SetWriteDeadline implements the Conn SetWriteDeadline method.
+func (c *conn) SetWriteDeadline(t time.Time) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setWriteDeadline(c.fd, t)
+}
+
+// SetReadBuffer sets the size of the operating system's
+// receive buffer associated with the connection.
+func (c *conn) SetReadBuffer(bytes int) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setReadBuffer(c.fd, bytes)
+}
+
+// SetWriteBuffer sets the size of the operating system's
+// transmit buffer associated with the connection.
+func (c *conn) SetWriteBuffer(bytes int) error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return setWriteBuffer(c.fd, bytes)
+}
+
+// File sets the underlying os.File to blocking mode and returns a copy.
+// It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+//
+// The returned os.File's file descriptor is different from the connection's.
+// Attempting to change properties of the original using this duplicate
+// may or may not have the desired effect.
+func (c *conn) File() (f *os.File, err error) { return c.fd.dup() }
+
 // An Error represents a network error.
 type Error interface {
 	error
@@ -173,11 +276,23 @@ type Listener interface {
 
 var errMissingAddress = errors.New("missing address")
 
+// OpError is the error type usually returned by functions in the net
+// package. It describes the operation, network type, and address of
+// an error.
 type OpError struct {
-	Op   string
-	Net  string
+	// Op is the operation which caused the error, such as
+	// "read" or "write".
+	Op string
+
+	// Net is the network type on which this error occurred,
+	// such as "tcp" or "udp6".
+	Net string
+
+	// Addr is the network address on which this error occurred.
 	Addr Addr
-	Err  error
+
+	// Err is the error that occurred during the operation.
+	Err error
 }
 
 func (e *OpError) Error() string {
@@ -204,6 +319,8 @@ func (e *OpError) Temporary() bool {
 	return ok && t.Temporary()
 }
 
+var noDeadline = time.Time{}
+
 type timeout interface {
 	Timeout() bool
 }
@@ -221,6 +338,8 @@ func (e *timeoutError) Temporary() bool { return true }
 
 var errTimeout error = &timeoutError{}
 
+var errClosing = errors.New("use of closed network connection")
+
 type AddrError struct {
 	Err  string
 	Addr string
@@ -262,3 +381,47 @@ func (e *DNSConfigError) Error() string {
 
 func (e *DNSConfigError) Timeout() bool   { return false }
 func (e *DNSConfigError) Temporary() bool { return false }
+
+type writerOnly struct {
+	io.Writer
+}
+
+// Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
+// applicable.
+func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) {
+	// Use wrapper to hide existing r.ReadFrom from io.Copy.
+	return io.Copy(writerOnly{w}, r)
+}
+
+// deadline is an atomically-accessed number of nanoseconds since 1970
+// or 0, if no deadline is set.
+type deadline struct {
+	sync.Mutex
+	val int64
+}
+
+func (d *deadline) expired() bool {
+	t := d.value()
+	return t > 0 && time.Now().UnixNano() >= t
+}
+
+func (d *deadline) value() (v int64) {
+	d.Lock()
+	v = d.val
+	d.Unlock()
+	return
+}
+
+func (d *deadline) set(v int64) {
+	d.Lock()
+	d.val = v
+	d.Unlock()
+}
+
+func (d *deadline) setTime(t time.Time) {
+	if t.IsZero() {
+		d.set(0)
+	} else {
+		d.set(t.UnixNano())
+	}
+}
diff --git a/src/pkg/net/net_test.go b/src/pkg/net/net_test.go
index fd145e1..1a512a5 100644
--- a/src/pkg/net/net_test.go
+++ b/src/pkg/net/net_test.go
@@ -6,6 +6,8 @@ package net
 
 import (
 	"io"
+	"io/ioutil"
+	"os"
 	"runtime"
 	"testing"
 	"time"
@@ -13,18 +15,17 @@ import (
 
 func TestShutdown(t *testing.T) {
 	if runtime.GOOS == "plan9" {
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
-	l, err := Listen("tcp", "127.0.0.1:0")
+	ln, err := Listen("tcp", "127.0.0.1:0")
 	if err != nil {
-		if l, err = Listen("tcp6", "[::1]:0"); err != nil {
+		if ln, err = Listen("tcp6", "[::1]:0"); err != nil {
 			t.Fatalf("ListenTCP on :0: %v", err)
 		}
 	}
 
 	go func() {
-		c, err := l.Accept()
+		c, err := ln.Accept()
 		if err != nil {
 			t.Fatalf("Accept: %v", err)
 		}
@@ -37,7 +38,7 @@ func TestShutdown(t *testing.T) {
 		c.Close()
 	}()
 
-	c, err := Dial("tcp", l.Addr().String())
+	c, err := Dial("tcp", ln.Addr().String())
 	if err != nil {
 		t.Fatalf("Dial: %v", err)
 	}
@@ -58,8 +59,61 @@ func TestShutdown(t *testing.T) {
 	}
 }
 
+func TestShutdownUnix(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows", "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	f, err := ioutil.TempFile("", "go_net_unixtest")
+	if err != nil {
+		t.Fatalf("TempFile: %s", err)
+	}
+	f.Close()
+	tmpname := f.Name()
+	os.Remove(tmpname)
+	ln, err := Listen("unix", tmpname)
+	if err != nil {
+		t.Fatalf("ListenUnix on %s: %s", tmpname, err)
+	}
+	defer os.Remove(tmpname)
+
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Fatalf("Accept: %v", err)
+		}
+		var buf [10]byte
+		n, err := c.Read(buf[:])
+		if n != 0 || err != io.EOF {
+			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
+		}
+		c.Write([]byte("response"))
+		c.Close()
+	}()
+
+	c, err := Dial("unix", tmpname)
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+
+	err = c.(*UnixConn).CloseWrite()
+	if err != nil {
+		t.Fatalf("CloseWrite: %v", err)
+	}
+	var buf [10]byte
+	n, err := c.Read(buf[:])
+	if err != nil {
+		t.Fatalf("client Read: %d, %v", n, err)
+	}
+	got := string(buf[:n])
+	if got != "response" {
+		t.Errorf("read = %q, want \"response\"", got)
+	}
+}
+
 func TestTCPListenClose(t *testing.T) {
-	l, err := Listen("tcp", "127.0.0.1:0")
+	ln, err := Listen("tcp", "127.0.0.1:0")
 	if err != nil {
 		t.Fatalf("Listen failed: %v", err)
 	}
@@ -67,11 +121,12 @@ func TestTCPListenClose(t *testing.T) {
 	done := make(chan bool, 1)
 	go func() {
 		time.Sleep(100 * time.Millisecond)
-		l.Close()
+		ln.Close()
 	}()
 	go func() {
-		_, err = l.Accept()
+		c, err := ln.Accept()
 		if err == nil {
+			c.Close()
 			t.Error("Accept succeeded")
 		} else {
 			t.Logf("Accept timeout error: %s (any error is fine)", err)
@@ -86,7 +141,11 @@ func TestTCPListenClose(t *testing.T) {
 }
 
 func TestUDPListenClose(t *testing.T) {
-	l, err := ListenPacket("udp", "127.0.0.1:0")
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	ln, err := ListenPacket("udp", "127.0.0.1:0")
 	if err != nil {
 		t.Fatalf("Listen failed: %v", err)
 	}
@@ -95,10 +154,10 @@ func TestUDPListenClose(t *testing.T) {
 	done := make(chan bool, 1)
 	go func() {
 		time.Sleep(100 * time.Millisecond)
-		l.Close()
+		ln.Close()
 	}()
 	go func() {
-		_, _, err = l.ReadFrom(buf)
+		_, _, err = ln.ReadFrom(buf)
 		if err == nil {
 			t.Error("ReadFrom succeeded")
 		} else {
@@ -112,3 +171,46 @@ func TestUDPListenClose(t *testing.T) {
 		t.Fatal("timeout waiting for UDP close")
 	}
 }
+
+func TestTCPClose(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	l, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer l.Close()
+
+	read := func(r io.Reader) error {
+		var m [1]byte
+		_, err := r.Read(m[:])
+		return err
+	}
+
+	go func() {
+		c, err := Dial("tcp", l.Addr().String())
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		go read(c)
+
+		time.Sleep(10 * time.Millisecond)
+		c.Close()
+	}()
+
+	c, err := l.Accept()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer c.Close()
+
+	for err == nil {
+		err = read(c)
+	}
+	if err != nil && err != io.EOF {
+		t.Fatal(err)
+	}
+}
diff --git a/src/pkg/net/newpollserver.go b/src/pkg/net/newpollserver.go
deleted file mode 100644
index d34bb51..0000000
--- a/src/pkg/net/newpollserver.go
+++ /dev/null
@@ -1,48 +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.
-
-// +build darwin freebsd linux netbsd openbsd
-
-package net
-
-import (
-	"os"
-	"syscall"
-)
-
-func newPollServer() (s *pollServer, err error) {
-	s = new(pollServer)
-	s.cr = make(chan *netFD, 1)
-	s.cw = make(chan *netFD, 1)
-	if s.pr, s.pw, err = os.Pipe(); err != nil {
-		return nil, err
-	}
-	if err = syscall.SetNonblock(int(s.pr.Fd()), true); err != nil {
-		goto Errno
-	}
-	if err = syscall.SetNonblock(int(s.pw.Fd()), true); err != nil {
-		goto Errno
-	}
-	if s.poll, err = newpollster(); err != nil {
-		goto Error
-	}
-	if _, err = s.poll.AddFD(int(s.pr.Fd()), 'r', true); err != nil {
-		s.poll.Close()
-		goto Error
-	}
-	s.pending = make(map[int]*netFD)
-	go s.Run()
-	return s, nil
-
-Errno:
-	err = &os.PathError{
-		Op:   "setnonblock",
-		Path: s.pr.Name(),
-		Err:  err,
-	}
-Error:
-	s.pr.Close()
-	s.pw.Close()
-	return nil, err
-}
diff --git a/src/pkg/net/newpollserver_unix.go b/src/pkg/net/newpollserver_unix.go
new file mode 100644
index 0000000..618b5b1
--- /dev/null
+++ b/src/pkg/net/newpollserver_unix.go
@@ -0,0 +1,46 @@
+// 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.
+
+// +build darwin freebsd linux netbsd openbsd
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func newPollServer() (s *pollServer, err error) {
+	s = new(pollServer)
+	if s.pr, s.pw, err = os.Pipe(); err != nil {
+		return nil, err
+	}
+	if err = syscall.SetNonblock(int(s.pr.Fd()), true); err != nil {
+		goto Errno
+	}
+	if err = syscall.SetNonblock(int(s.pw.Fd()), true); err != nil {
+		goto Errno
+	}
+	if s.poll, err = newpollster(); err != nil {
+		goto Error
+	}
+	if _, err = s.poll.AddFD(int(s.pr.Fd()), 'r', true); err != nil {
+		s.poll.Close()
+		goto Error
+	}
+	s.pending = make(map[int]*netFD)
+	go s.Run()
+	return s, nil
+
+Errno:
+	err = &os.PathError{
+		Op:   "setnonblock",
+		Path: s.pr.Name(),
+		Err:  err,
+	}
+Error:
+	s.pr.Close()
+	s.pw.Close()
+	return nil, err
+}
diff --git a/src/pkg/net/packetconn_test.go b/src/pkg/net/packetconn_test.go
new file mode 100644
index 0000000..93c7a64
--- /dev/null
+++ b/src/pkg/net/packetconn_test.go
@@ -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.
+
+// This file implements API tests across platforms and will never have a build
+// tag.
+
+package net
+
+import (
+	"os"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+var packetConnTests = []struct {
+	net   string
+	addr1 string
+	addr2 string
+}{
+	{"udp", "127.0.0.1:0", "127.0.0.1:0"},
+	{"ip:icmp", "127.0.0.1", "127.0.0.1"},
+	{"unixgram", testUnixAddr(), testUnixAddr()},
+}
+
+func TestPacketConn(t *testing.T) {
+	closer := func(c PacketConn, net, addr1, addr2 string) {
+		c.Close()
+		switch net {
+		case "unixgram":
+			os.Remove(addr1)
+			os.Remove(addr2)
+		}
+	}
+
+	for i, tt := range packetConnTests {
+		var wb []byte
+		netstr := strings.Split(tt.net, ":")
+		switch netstr[0] {
+		case "udp":
+			wb = []byte("UDP PACKETCONN TEST")
+		case "ip":
+			switch runtime.GOOS {
+			case "plan9":
+				continue
+			}
+			if os.Getuid() != 0 {
+				continue
+			}
+			var err error
+			wb, err = (&icmpMessage{
+				Type: icmpv4EchoRequest, Code: 0,
+				Body: &icmpEcho{
+					ID: os.Getpid() & 0xffff, Seq: i + 1,
+					Data: []byte("IP PACKETCONN TEST"),
+				},
+			}).Marshal()
+			if err != nil {
+				t.Fatalf("icmpMessage.Marshal failed: %v", err)
+			}
+		case "unixgram":
+			switch runtime.GOOS {
+			case "plan9", "windows":
+				continue
+			}
+			wb = []byte("UNIXGRAM PACKETCONN TEST")
+		default:
+			continue
+		}
+
+		c1, err := ListenPacket(tt.net, tt.addr1)
+		if err != nil {
+			t.Fatalf("ListenPacket failed: %v", err)
+		}
+		defer closer(c1, netstr[0], tt.addr1, tt.addr2)
+		c1.LocalAddr()
+		c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+
+		c2, err := ListenPacket(tt.net, tt.addr2)
+		if err != nil {
+			t.Fatalf("ListenPacket failed: %v", err)
+		}
+		defer closer(c2, netstr[0], tt.addr1, tt.addr2)
+		c2.LocalAddr()
+		c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+
+		if _, err := c1.WriteTo(wb, c2.LocalAddr()); err != nil {
+			t.Fatalf("PacketConn.WriteTo failed: %v", err)
+		}
+		rb2 := make([]byte, 128)
+		if _, _, err := c2.ReadFrom(rb2); err != nil {
+			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
+		}
+		if _, err := c2.WriteTo(wb, c1.LocalAddr()); err != nil {
+			t.Fatalf("PacketConn.WriteTo failed: %v", err)
+		}
+		rb1 := make([]byte, 128)
+		if _, _, err := c1.ReadFrom(rb1); err != nil {
+			t.Fatalf("PacketConn.ReadFrom failed: %v", err)
+		}
+	}
+}
+
+func TestConnAndPacketConn(t *testing.T) {
+	closer := func(c PacketConn, net, addr1, addr2 string) {
+		c.Close()
+		switch net {
+		case "unixgram":
+			os.Remove(addr1)
+			os.Remove(addr2)
+		}
+	}
+
+	for i, tt := range packetConnTests {
+		var wb []byte
+		netstr := strings.Split(tt.net, ":")
+		switch netstr[0] {
+		case "udp":
+			wb = []byte("UDP PACKETCONN TEST")
+		case "ip":
+			switch runtime.GOOS {
+			case "plan9":
+				continue
+			}
+			if os.Getuid() != 0 {
+				continue
+			}
+			var err error
+			wb, err = (&icmpMessage{
+				Type: icmpv4EchoRequest, Code: 0,
+				Body: &icmpEcho{
+					ID: os.Getpid() & 0xffff, Seq: i + 1,
+					Data: []byte("IP PACKETCONN TEST"),
+				},
+			}).Marshal()
+			if err != nil {
+				t.Fatalf("icmpMessage.Marshal failed: %v", err)
+			}
+		case "unixgram":
+			switch runtime.GOOS {
+			case "plan9", "windows":
+				continue
+			}
+			wb = []byte("UNIXGRAM PACKETCONN TEST")
+		default:
+			continue
+		}
+
+		c1, err := ListenPacket(tt.net, tt.addr1)
+		if err != nil {
+			t.Fatalf("ListenPacket failed: %v", err)
+		}
+		defer closer(c1, netstr[0], tt.addr1, tt.addr2)
+		c1.LocalAddr()
+		c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+
+		c2, err := Dial(tt.net, c1.LocalAddr().String())
+		if err != nil {
+			t.Fatalf("Dial failed: %v", err)
+		}
+		defer c2.Close()
+		c2.LocalAddr()
+		c2.RemoteAddr()
+		c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
+		c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+
+		if _, err := c2.Write(wb); err != nil {
+			t.Fatalf("Conn.Write failed: %v", err)
+		}
+		rb1 := make([]byte, 128)
+		if _, _, err := c1.ReadFrom(rb1); err != nil {
+			t.Fatalf("PacetConn.ReadFrom failed: %v", err)
+		}
+		var dst Addr
+		switch netstr[0] {
+		case "ip":
+			dst = &IPAddr{IP: IPv4(127, 0, 0, 1)}
+		case "unixgram":
+			continue
+		default:
+			dst = c2.LocalAddr()
+		}
+		if _, err := c1.WriteTo(wb, dst); err != nil {
+			t.Fatalf("PacketConn.WriteTo failed: %v", err)
+		}
+		rb2 := make([]byte, 128)
+		if _, err := c2.Read(rb2); err != nil {
+			t.Fatalf("Conn.Read failed: %v", err)
+		}
+	}
+}
diff --git a/src/pkg/net/parse_test.go b/src/pkg/net/parse_test.go
index 30fda45..9df0c53 100644
--- a/src/pkg/net/parse_test.go
+++ b/src/pkg/net/parse_test.go
@@ -15,8 +15,7 @@ func TestReadLine(t *testing.T) {
 	// /etc/services file does not exist on windows and Plan 9.
 	switch runtime.GOOS {
 	case "plan9", "windows":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 	filename := "/etc/services" // a nice big file
 
diff --git a/src/pkg/net/port.go b/src/pkg/net/port.go
index 16780da..c24f4ed 100644
--- a/src/pkg/net/port.go
+++ b/src/pkg/net/port.go
@@ -1,69 +1,24 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// 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 freebsd linux netbsd openbsd
-
-// Read system port mappings from /etc/services
+// Network service port manipulations
 
 package net
 
-import "sync"
-
-var services map[string]map[string]int
-var servicesError error
-var onceReadServices sync.Once
-
-func readServices() {
-	services = make(map[string]map[string]int)
-	var file *file
-	if file, servicesError = open("/etc/services"); servicesError != nil {
-		return
-	}
-	for line, ok := file.readLine(); ok; line, ok = file.readLine() {
-		// "http 80/tcp www www-http # World Wide Web HTTP"
-		if i := byteIndex(line, '#'); i >= 0 {
-			line = line[0:i]
-		}
-		f := getFields(line)
-		if len(f) < 2 {
-			continue
-		}
-		portnet := f[1] // "tcp/80"
-		port, j, ok := dtoi(portnet, 0)
-		if !ok || port <= 0 || j >= len(portnet) || portnet[j] != '/' {
-			continue
-		}
-		netw := portnet[j+1:] // "tcp"
-		m, ok1 := services[netw]
-		if !ok1 {
-			m = make(map[string]int)
-			services[netw] = m
-		}
-		for i := 0; i < len(f); i++ {
-			if i != 1 { // f[1] was port/net
-				m[f[i]] = port
-			}
+// parsePort parses port as a network service port number for both
+// TCP and UDP.
+func parsePort(net, port string) (int, error) {
+	p, i, ok := dtoi(port, 0)
+	if !ok || i != len(port) {
+		var err error
+		p, err = LookupPort(net, port)
+		if err != nil {
+			return 0, err
 		}
 	}
-	file.close()
-}
-
-// goLookupPort is the native Go implementation of LookupPort.
-func goLookupPort(network, service string) (port int, err error) {
-	onceReadServices.Do(readServices)
-
-	switch network {
-	case "tcp4", "tcp6":
-		network = "tcp"
-	case "udp4", "udp6":
-		network = "udp"
-	}
-
-	if m, ok := services[network]; ok {
-		if port, ok = m[service]; ok {
-			return
-		}
+	if p < 0 || p > 0xFFFF {
+		return 0, &AddrError{"invalid port", port}
 	}
-	return 0, &AddrError{"unknown port", network + "/" + service}
+	return p, nil
 }
diff --git a/src/pkg/net/port_test.go b/src/pkg/net/port_test.go
index 329b169..9e8968f 100644
--- a/src/pkg/net/port_test.go
+++ b/src/pkg/net/port_test.go
@@ -46,7 +46,7 @@ func TestLookupPort(t *testing.T) {
 	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 {
-			t.Errorf("LookupPort(%q, %q) = %v, %s; want %v",
+			t.Errorf("LookupPort(%q, %q) = %v, %v; want %v",
 				tt.netw, tt.name, port, err, tt.port)
 		}
 	}
diff --git a/src/pkg/net/port.go b/src/pkg/net/port_unix.go
similarity index 100%
copy from src/pkg/net/port.go
copy to src/pkg/net/port_unix.go
diff --git a/src/pkg/net/protoconn_test.go b/src/pkg/net/protoconn_test.go
new file mode 100644
index 0000000..2fe7d1d
--- /dev/null
+++ b/src/pkg/net/protoconn_test.go
@@ -0,0 +1,358 @@
+// 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.
+
+// This file implements API tests across platforms and will never have a build
+// tag.
+
+package net
+
+import (
+	"io/ioutil"
+	"os"
+	"runtime"
+	"testing"
+	"time"
+)
+
+// testUnixAddr uses ioutil.TempFile to get a name that is unique.
+func testUnixAddr() string {
+	f, err := ioutil.TempFile("", "nettest")
+	if err != nil {
+		panic(err)
+	}
+	addr := f.Name()
+	f.Close()
+	os.Remove(addr)
+	return addr
+}
+
+var condFatalf = func() func(*testing.T, string, ...interface{}) {
+	// A few APIs are not implemented yet on both Plan 9 and Windows.
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		return (*testing.T).Logf
+	}
+	return (*testing.T).Fatalf
+}()
+
+func TestTCPListenerSpecificMethods(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	la, err := ResolveTCPAddr("tcp4", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ResolveTCPAddr failed: %v", err)
+	}
+	ln, err := ListenTCP("tcp4", la)
+	if err != nil {
+		t.Fatalf("ListenTCP failed: %v", err)
+	}
+	defer ln.Close()
+	ln.Addr()
+	ln.SetDeadline(time.Now().Add(30 * time.Nanosecond))
+
+	if c, err := ln.Accept(); err != nil {
+		if !err.(Error).Timeout() {
+			t.Fatalf("TCPListener.Accept failed: %v", err)
+		}
+	} else {
+		c.Close()
+	}
+	if c, err := ln.AcceptTCP(); err != nil {
+		if !err.(Error).Timeout() {
+			t.Fatalf("TCPListener.AcceptTCP failed: %v", err)
+		}
+	} else {
+		c.Close()
+	}
+
+	if f, err := ln.File(); err != nil {
+		condFatalf(t, "TCPListener.File failed: %v", err)
+	} else {
+		f.Close()
+	}
+}
+
+func TestTCPConnSpecificMethods(t *testing.T) {
+	la, err := ResolveTCPAddr("tcp4", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ResolveTCPAddr failed: %v", err)
+	}
+	ln, err := ListenTCP("tcp4", la)
+	if err != nil {
+		t.Fatalf("ListenTCP failed: %v", err)
+	}
+	defer ln.Close()
+	ln.Addr()
+
+	done := make(chan int)
+	go transponder(t, ln, done)
+
+	ra, err := ResolveTCPAddr("tcp4", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("ResolveTCPAddr failed: %v", err)
+	}
+	c, err := DialTCP("tcp4", nil, ra)
+	if err != nil {
+		t.Fatalf("DialTCP failed: %v", err)
+	}
+	defer c.Close()
+	c.SetKeepAlive(false)
+	c.SetLinger(0)
+	c.SetNoDelay(false)
+	c.LocalAddr()
+	c.RemoteAddr()
+	c.SetDeadline(time.Now().Add(someTimeout))
+	c.SetReadDeadline(time.Now().Add(someTimeout))
+	c.SetWriteDeadline(time.Now().Add(someTimeout))
+
+	if _, err := c.Write([]byte("TCPCONN TEST")); err != nil {
+		t.Fatalf("TCPConn.Write failed: %v", err)
+	}
+	rb := make([]byte, 128)
+	if _, err := c.Read(rb); err != nil {
+		t.Fatalf("TCPConn.Read failed: %v", err)
+	}
+
+	<-done
+}
+
+func TestUDPConnSpecificMethods(t *testing.T) {
+	la, err := ResolveUDPAddr("udp4", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ResolveUDPAddr failed: %v", err)
+	}
+	c, err := ListenUDP("udp4", la)
+	if err != nil {
+		t.Fatalf("ListenUDP failed: %v", err)
+	}
+	defer c.Close()
+	c.LocalAddr()
+	c.RemoteAddr()
+	c.SetDeadline(time.Now().Add(someTimeout))
+	c.SetReadDeadline(time.Now().Add(someTimeout))
+	c.SetWriteDeadline(time.Now().Add(someTimeout))
+	c.SetReadBuffer(2048)
+	c.SetWriteBuffer(2048)
+
+	wb := []byte("UDPCONN TEST")
+	rb := make([]byte, 128)
+	if _, err := c.WriteToUDP(wb, c.LocalAddr().(*UDPAddr)); err != nil {
+		t.Fatalf("UDPConn.WriteToUDP failed: %v", err)
+	}
+	if _, _, err := c.ReadFromUDP(rb); err != nil {
+		t.Fatalf("UDPConn.ReadFromUDP failed: %v", err)
+	}
+	if _, _, err := c.WriteMsgUDP(wb, nil, c.LocalAddr().(*UDPAddr)); err != nil {
+		condFatalf(t, "UDPConn.WriteMsgUDP failed: %v", err)
+	}
+	if _, _, _, _, err := c.ReadMsgUDP(rb, nil); err != nil {
+		condFatalf(t, "UDPConn.ReadMsgUDP failed: %v", err)
+	}
+
+	if f, err := c.File(); err != nil {
+		condFatalf(t, "UDPConn.File failed: %v", err)
+	} else {
+		f.Close()
+	}
+}
+
+func TestIPConnSpecificMethods(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping read test on %q", runtime.GOOS)
+	}
+	if os.Getuid() != 0 {
+		t.Skipf("skipping test; must be root")
+	}
+
+	la, err := ResolveIPAddr("ip4", "127.0.0.1")
+	if err != nil {
+		t.Fatalf("ResolveIPAddr failed: %v", err)
+	}
+	c, err := ListenIP("ip4:icmp", la)
+	if err != nil {
+		t.Fatalf("ListenIP failed: %v", err)
+	}
+	defer c.Close()
+	c.LocalAddr()
+	c.RemoteAddr()
+	c.SetDeadline(time.Now().Add(someTimeout))
+	c.SetReadDeadline(time.Now().Add(someTimeout))
+	c.SetWriteDeadline(time.Now().Add(someTimeout))
+	c.SetReadBuffer(2048)
+	c.SetWriteBuffer(2048)
+
+	wb, err := (&icmpMessage{
+		Type: icmpv4EchoRequest, Code: 0,
+		Body: &icmpEcho{
+			ID: os.Getpid() & 0xffff, Seq: 1,
+			Data: []byte("IPCONN TEST "),
+		},
+	}).Marshal()
+	if err != nil {
+		t.Fatalf("icmpMessage.Marshal failed: %v", err)
+	}
+	rb := make([]byte, 20+128)
+	if _, err := c.WriteToIP(wb, c.LocalAddr().(*IPAddr)); err != nil {
+		t.Fatalf("IPConn.WriteToIP failed: %v", err)
+	}
+	if _, _, err := c.ReadFromIP(rb); err != nil {
+		t.Fatalf("IPConn.ReadFromIP failed: %v", err)
+	}
+	if _, _, err := c.WriteMsgIP(wb, nil, c.LocalAddr().(*IPAddr)); err != nil {
+		condFatalf(t, "IPConn.WriteMsgIP failed: %v", err)
+	}
+	if _, _, _, _, err := c.ReadMsgIP(rb, nil); err != nil {
+		condFatalf(t, "IPConn.ReadMsgIP failed: %v", err)
+	}
+
+	if f, err := c.File(); err != nil {
+		condFatalf(t, "IPConn.File failed: %v", err)
+	} else {
+		f.Close()
+	}
+}
+
+func TestUnixListenerSpecificMethods(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skipf("skipping read test on %q", runtime.GOOS)
+	}
+
+	addr := testUnixAddr()
+	la, err := ResolveUnixAddr("unix", addr)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	ln, err := ListenUnix("unix", la)
+	if err != nil {
+		t.Fatalf("ListenUnix failed: %v", err)
+	}
+	defer ln.Close()
+	defer os.Remove(addr)
+	ln.Addr()
+	ln.SetDeadline(time.Now().Add(30 * time.Nanosecond))
+
+	if c, err := ln.Accept(); err != nil {
+		if !err.(Error).Timeout() {
+			t.Fatalf("UnixListener.Accept failed: %v", err)
+		}
+	} else {
+		c.Close()
+	}
+	if c, err := ln.AcceptUnix(); err != nil {
+		if !err.(Error).Timeout() {
+			t.Fatalf("UnixListener.AcceptUnix failed: %v", err)
+		}
+	} else {
+		c.Close()
+	}
+
+	if f, err := ln.File(); err != nil {
+		t.Fatalf("UnixListener.File failed: %v", err)
+	} else {
+		f.Close()
+	}
+}
+
+func TestUnixConnSpecificMethods(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	addr1, addr2, addr3 := testUnixAddr(), testUnixAddr(), testUnixAddr()
+
+	a1, err := ResolveUnixAddr("unixgram", addr1)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c1, err := DialUnix("unixgram", a1, nil)
+	if err != nil {
+		t.Fatalf("DialUnix failed: %v", err)
+	}
+	defer c1.Close()
+	defer os.Remove(addr1)
+	c1.LocalAddr()
+	c1.RemoteAddr()
+	c1.SetDeadline(time.Now().Add(someTimeout))
+	c1.SetReadDeadline(time.Now().Add(someTimeout))
+	c1.SetWriteDeadline(time.Now().Add(someTimeout))
+	c1.SetReadBuffer(2048)
+	c1.SetWriteBuffer(2048)
+
+	a2, err := ResolveUnixAddr("unixgram", addr2)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c2, err := DialUnix("unixgram", a2, nil)
+	if err != nil {
+		t.Fatalf("DialUnix failed: %v", err)
+	}
+	defer c2.Close()
+	defer os.Remove(addr2)
+	c2.LocalAddr()
+	c2.RemoteAddr()
+	c2.SetDeadline(time.Now().Add(someTimeout))
+	c2.SetReadDeadline(time.Now().Add(someTimeout))
+	c2.SetWriteDeadline(time.Now().Add(someTimeout))
+	c2.SetReadBuffer(2048)
+	c2.SetWriteBuffer(2048)
+
+	a3, err := ResolveUnixAddr("unixgram", addr3)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c3, err := ListenUnixgram("unixgram", a3)
+	if err != nil {
+		t.Fatalf("ListenUnixgram failed: %v", err)
+	}
+	defer c3.Close()
+	defer os.Remove(addr3)
+	c3.LocalAddr()
+	c3.RemoteAddr()
+	c3.SetDeadline(time.Now().Add(someTimeout))
+	c3.SetReadDeadline(time.Now().Add(someTimeout))
+	c3.SetWriteDeadline(time.Now().Add(someTimeout))
+	c3.SetReadBuffer(2048)
+	c3.SetWriteBuffer(2048)
+
+	wb := []byte("UNIXCONN TEST")
+	rb1 := make([]byte, 128)
+	rb2 := make([]byte, 128)
+	rb3 := make([]byte, 128)
+	if _, _, err := c1.WriteMsgUnix(wb, nil, a2); err != nil {
+		t.Fatalf("UnixConn.WriteMsgUnix failed: %v", err)
+	}
+	if _, _, _, _, err := c2.ReadMsgUnix(rb2, nil); err != nil {
+		t.Fatalf("UnixConn.ReadMsgUnix failed: %v", err)
+	}
+	if _, err := c2.WriteToUnix(wb, a1); err != nil {
+		t.Fatalf("UnixConn.WriteToUnix failed: %v", err)
+	}
+	if _, _, err := c1.ReadFromUnix(rb1); err != nil {
+		t.Fatalf("UnixConn.ReadFromUnix failed: %v", err)
+	}
+	if _, err := c3.WriteToUnix(wb, a1); err != nil {
+		t.Fatalf("UnixConn.WriteToUnix failed: %v", err)
+	}
+	if _, _, err := c1.ReadFromUnix(rb1); err != nil {
+		t.Fatalf("UnixConn.ReadFromUnix failed: %v", err)
+	}
+	if _, err := c2.WriteToUnix(wb, a3); err != nil {
+		t.Fatalf("UnixConn.WriteToUnix failed: %v", err)
+	}
+	if _, _, err := c3.ReadFromUnix(rb3); err != nil {
+		t.Fatalf("UnixConn.ReadFromUnix failed: %v", err)
+	}
+
+	if f, err := c1.File(); err != nil {
+		t.Fatalf("UnixConn.File failed: %v", err)
+	} else {
+		f.Close()
+	}
+}
diff --git a/src/pkg/net/rpc/client.go b/src/pkg/net/rpc/client.go
index db2da8e..4b0c9c3 100644
--- a/src/pkg/net/rpc/client.go
+++ b/src/pkg/net/rpc/client.go
@@ -71,7 +71,7 @@ func (client *Client) send(call *Call) {
 
 	// Register this call.
 	client.mutex.Lock()
-	if client.shutdown {
+	if client.shutdown || client.closing {
 		call.Error = ErrShutdown
 		client.mutex.Unlock()
 		call.done()
@@ -88,10 +88,13 @@ func (client *Client) send(call *Call) {
 	err := client.codec.WriteRequest(&client.request, call.Args)
 	if err != nil {
 		client.mutex.Lock()
+		call = client.pending[seq]
 		delete(client.pending, seq)
 		client.mutex.Unlock()
-		call.Error = err
-		call.done()
+		if call != nil {
+			call.Error = err
+			call.done()
+		}
 	}
 }
 
@@ -102,9 +105,6 @@ func (client *Client) input() {
 		response = Response{}
 		err = client.codec.ReadResponseHeader(&response)
 		if err != nil {
-			if err == io.EOF && !client.closing {
-				err = io.ErrUnexpectedEOF
-			}
 			break
 		}
 		seq := response.Seq
@@ -113,12 +113,18 @@ func (client *Client) input() {
 		delete(client.pending, seq)
 		client.mutex.Unlock()
 
-		if response.Error == "" {
-			err = client.codec.ReadResponseBody(call.Reply)
+		switch {
+		case call == nil:
+			// We've got no pending call. That usually means that
+			// WriteRequest partially failed, and call was already
+			// removed; response is a server telling us about an
+			// error reading request body. We should still attempt
+			// to read error body, but there's no one to give it to.
+			err = client.codec.ReadResponseBody(nil)
 			if err != nil {
-				call.Error = errors.New("reading body " + err.Error())
+				err = errors.New("reading error body: " + err.Error())
 			}
-		} else {
+		case response.Error != "":
 			// We've got an error response. Give this to the request;
 			// any subsequent requests will get the ReadResponseBody
 			// error if there is one.
@@ -127,14 +133,27 @@ func (client *Client) input() {
 			if err != nil {
 				err = errors.New("reading error body: " + err.Error())
 			}
+			call.done()
+		default:
+			err = client.codec.ReadResponseBody(call.Reply)
+			if err != nil {
+				call.Error = errors.New("reading body " + err.Error())
+			}
+			call.done()
 		}
-		call.done()
 	}
 	// Terminate pending calls.
 	client.sending.Lock()
 	client.mutex.Lock()
 	client.shutdown = true
 	closing := client.closing
+	if err == io.EOF {
+		if closing {
+			err = ErrShutdown
+		} else {
+			err = io.ErrUnexpectedEOF
+		}
+	}
 	for _, call := range client.pending {
 		call.Error = err
 		call.done()
@@ -213,7 +232,7 @@ func DialHTTP(network, address string) (*Client, error) {
 	return DialHTTPPath(network, address, DefaultRPCPath)
 }
 
-// DialHTTPPath connects to an HTTP RPC server 
+// DialHTTPPath connects to an HTTP RPC server
 // at the specified network address and path.
 func DialHTTPPath(network, address, path string) (*Client, error) {
 	var err error
diff --git a/src/pkg/net/rpc/jsonrpc/all_test.go b/src/pkg/net/rpc/jsonrpc/all_test.go
index e6c7441..3c7c4d4 100644
--- a/src/pkg/net/rpc/jsonrpc/all_test.go
+++ b/src/pkg/net/rpc/jsonrpc/all_test.go
@@ -24,6 +24,12 @@ type Reply struct {
 
 type Arith int
 
+type ArithAddResp struct {
+	Id     interface{} `json:"id"`
+	Result Reply       `json:"result"`
+	Error  interface{} `json:"error"`
+}
+
 func (t *Arith) Add(args *Args, reply *Reply) error {
 	reply.C = args.A + args.B
 	return nil
@@ -50,13 +56,39 @@ func init() {
 	rpc.Register(new(Arith))
 }
 
-func TestServer(t *testing.T) {
-	type addResp struct {
-		Id     interface{} `json:"id"`
-		Result Reply       `json:"result"`
-		Error  interface{} `json:"error"`
+func TestServerNoParams(t *testing.T) {
+	cli, srv := net.Pipe()
+	defer cli.Close()
+	go ServeConn(srv)
+	dec := json.NewDecoder(cli)
+
+	fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "123"}`)
+	var resp ArithAddResp
+	if err := dec.Decode(&resp); err != nil {
+		t.Fatalf("Decode after no params: %s", err)
+	}
+	if resp.Error == nil {
+		t.Fatalf("Expected error, got nil")
+	}
+}
+
+func TestServerEmptyMessage(t *testing.T) {
+	cli, srv := net.Pipe()
+	defer cli.Close()
+	go ServeConn(srv)
+	dec := json.NewDecoder(cli)
+
+	fmt.Fprintf(cli, "{}")
+	var resp ArithAddResp
+	if err := dec.Decode(&resp); err != nil {
+		t.Fatalf("Decode after empty: %s", err)
 	}
+	if resp.Error == nil {
+		t.Fatalf("Expected error, got nil")
+	}
+}
 
+func TestServer(t *testing.T) {
 	cli, srv := net.Pipe()
 	defer cli.Close()
 	go ServeConn(srv)
@@ -65,7 +97,7 @@ func TestServer(t *testing.T) {
 	// Send hand-coded requests to server, parse responses.
 	for i := 0; i < 10; i++ {
 		fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "\u%04d", "params": [{"A": %d, "B": %d}]}`, i, i, i+1)
-		var resp addResp
+		var resp ArithAddResp
 		err := dec.Decode(&resp)
 		if err != nil {
 			t.Fatalf("Decode: %s", err)
@@ -80,15 +112,6 @@ func TestServer(t *testing.T) {
 			t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C)
 		}
 	}
-
-	fmt.Fprintf(cli, "{}\n")
-	var resp addResp
-	if err := dec.Decode(&resp); err != nil {
-		t.Fatalf("Decode after empty: %s", err)
-	}
-	if resp.Error == nil {
-		t.Fatalf("Expected error, got nil")
-	}
 }
 
 func TestClient(t *testing.T) {
@@ -108,7 +131,7 @@ func TestClient(t *testing.T) {
 		t.Errorf("Add: expected no error but got string %q", err.Error())
 	}
 	if reply.C != args.A+args.B {
-		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+		t.Errorf("Add: got %d expected %d", reply.C, args.A+args.B)
 	}
 
 	args = &Args{7, 8}
@@ -118,7 +141,7 @@ func TestClient(t *testing.T) {
 		t.Errorf("Mul: expected no error but got string %q", err.Error())
 	}
 	if reply.C != args.A*args.B {
-		t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
+		t.Errorf("Mul: got %d expected %d", reply.C, args.A*args.B)
 	}
 
 	// Out of order.
@@ -133,7 +156,7 @@ func TestClient(t *testing.T) {
 		t.Errorf("Add: expected no error but got string %q", addCall.Error.Error())
 	}
 	if addReply.C != args.A+args.B {
-		t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
+		t.Errorf("Add: got %d expected %d", addReply.C, args.A+args.B)
 	}
 
 	mulCall = <-mulCall.Done
@@ -141,7 +164,7 @@ func TestClient(t *testing.T) {
 		t.Errorf("Mul: expected no error but got string %q", mulCall.Error.Error())
 	}
 	if mulReply.C != args.A*args.B {
-		t.Errorf("Mul: expected %d got %d", mulReply.C, args.A*args.B)
+		t.Errorf("Mul: got %d expected %d", mulReply.C, args.A*args.B)
 	}
 
 	// Error test
diff --git a/src/pkg/net/rpc/jsonrpc/server.go b/src/pkg/net/rpc/jsonrpc/server.go
index 4c54553..5bc05fd 100644
--- a/src/pkg/net/rpc/jsonrpc/server.go
+++ b/src/pkg/net/rpc/jsonrpc/server.go
@@ -12,6 +12,8 @@ import (
 	"sync"
 )
 
+var errMissingParams = errors.New("jsonrpc: request body missing params")
+
 type serverCodec struct {
 	dec *json.Decoder // for reading JSON values
 	enc *json.Encoder // for writing JSON values
@@ -50,12 +52,8 @@ type serverRequest struct {
 
 func (r *serverRequest) reset() {
 	r.Method = ""
-	if r.Params != nil {
-		*r.Params = (*r.Params)[0:0]
-	}
-	if r.Id != nil {
-		*r.Id = (*r.Id)[0:0]
-	}
+	r.Params = nil
+	r.Id = nil
 }
 
 type serverResponse struct {
@@ -88,6 +86,9 @@ func (c *serverCodec) ReadRequestBody(x interface{}) error {
 	if x == nil {
 		return nil
 	}
+	if c.req.Params == nil {
+		return errMissingParams
+	}
 	// JSON params is array value.
 	// RPC params is struct.
 	// Unmarshal into array containing struct for now.
diff --git a/src/pkg/net/rpc/server.go b/src/pkg/net/rpc/server.go
index 1680e2f..e71b6fb 100644
--- a/src/pkg/net/rpc/server.go
+++ b/src/pkg/net/rpc/server.go
@@ -24,12 +24,13 @@
 
 	where T, T1 and T2 can be marshaled by encoding/gob.
 	These requirements apply even if a different codec is used.
-	(In future, these requirements may soften for custom codecs.)
+	(In the future, these requirements may soften for custom codecs.)
 
 	The method's first argument represents the arguments provided by the caller; the
 	second argument represents the result parameters to be returned to the caller.
 	The method's return value, if non-nil, is passed back as a string that the client
-	sees as if created by errors.New.
+	sees as if created by errors.New.  If an error is returned, the reply parameter
+	will not be sent back to the client.
 
 	The server may handle requests on a single connection by calling ServeConn.  More
 	typically it will create a network listener and call Accept or, for an HTTP
@@ -111,7 +112,7 @@
 
 		// Asynchronous call
 		quotient := new(Quotient)
-		divCall := client.Go("Arith.Divide", args, &quotient, nil)
+		divCall := client.Go("Arith.Divide", args, quotient, nil)
 		replyCall := <-divCall.Done	// will be equal to divCall
 		// check errors, print, etc.
 
@@ -181,7 +182,7 @@ type Response struct {
 
 // Server represents an RPC Server.
 type Server struct {
-	mu         sync.Mutex // protects the serviceMap
+	mu         sync.RWMutex // protects the serviceMap
 	serviceMap map[string]*service
 	reqLock    sync.Mutex // protects freeReq
 	freeReq    *Request
@@ -218,15 +219,15 @@ func isExportedOrBuiltinType(t reflect.Type) bool {
 //	- exported method
 //	- two arguments, both pointers to exported structs
 //	- one return value, of type error
-// It returns an error if the receiver is not an exported type or has no
-// suitable methods.
+// It returns an error if the receiver is not an exported type or has
+// no methods or unsuitable methods. It also logs the error using package log.
 // The client accesses each method using a string of the form "Type.Method",
 // where Type is the receiver's concrete type.
 func (server *Server) Register(rcvr interface{}) error {
 	return server.register(rcvr, "", false)
 }
 
-// RegisterName is like Register but uses the provided name for the type 
+// RegisterName is like Register but uses the provided name for the type
 // instead of the receiver's concrete type.
 func (server *Server) RegisterName(name string, rcvr interface{}) error {
 	return server.register(rcvr, name, true)
@@ -260,8 +261,30 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro
 	s.method = make(map[string]*methodType)
 
 	// Install the methods
-	for m := 0; m < s.typ.NumMethod(); m++ {
-		method := s.typ.Method(m)
+	s.method = suitableMethods(s.typ, true)
+
+	if len(s.method) == 0 {
+		str := ""
+		// To help the user, see if a pointer receiver would work.
+		method := suitableMethods(reflect.PtrTo(s.typ), false)
+		if len(method) != 0 {
+			str = "rpc.Register: type " + sname + " has no exported methods of suitable type (hint: pass a pointer to value of that type)"
+		} else {
+			str = "rpc.Register: type " + sname + " has no exported methods of suitable type"
+		}
+		log.Print(str)
+		return errors.New(str)
+	}
+	server.serviceMap[s.name] = s
+	return nil
+}
+
+// suitableMethods returns suitable Rpc methods of typ, it will report
+// error using log if reportErr is true.
+func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
+	methods := make(map[string]*methodType)
+	for m := 0; m < typ.NumMethod(); m++ {
+		method := typ.Method(m)
 		mtype := method.Type
 		mname := method.Name
 		// Method must be exported.
@@ -270,46 +293,51 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro
 		}
 		// Method needs three ins: receiver, *args, *reply.
 		if mtype.NumIn() != 3 {
-			log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
+			if reportErr {
+				log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
+			}
 			continue
 		}
 		// First arg need not be a pointer.
 		argType := mtype.In(1)
 		if !isExportedOrBuiltinType(argType) {
-			log.Println(mname, "argument type not exported:", argType)
+			if reportErr {
+				log.Println(mname, "argument type not exported:", argType)
+			}
 			continue
 		}
 		// Second arg must be a pointer.
 		replyType := mtype.In(2)
 		if replyType.Kind() != reflect.Ptr {
-			log.Println("method", mname, "reply type not a pointer:", replyType)
+			if reportErr {
+				log.Println("method", mname, "reply type not a pointer:", replyType)
+			}
 			continue
 		}
 		// Reply type must be exported.
 		if !isExportedOrBuiltinType(replyType) {
-			log.Println("method", mname, "reply type not exported:", replyType)
+			if reportErr {
+				log.Println("method", mname, "reply type not exported:", replyType)
+			}
 			continue
 		}
 		// Method needs one out.
 		if mtype.NumOut() != 1 {
-			log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
+			if reportErr {
+				log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
+			}
 			continue
 		}
 		// The return type of the method must be error.
 		if returnType := mtype.Out(0); returnType != typeOfError {
-			log.Println("method", mname, "returns", returnType.String(), "not error")
+			if reportErr {
+				log.Println("method", mname, "returns", returnType.String(), "not error")
+			}
 			continue
 		}
-		s.method[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
+		methods[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
 	}
-
-	if len(s.method) == 0 {
-		s := "rpc Register: type " + sname + " has no exported methods of suitable type"
-		log.Print(s)
-		return errors.New(s)
-	}
-	server.serviceMap[s.name] = s
-	return nil
+	return methods
 }
 
 // A value sent as a placeholder for the server's response value when the server
@@ -538,9 +566,9 @@ func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mt
 		return
 	}
 	// Look up the request.
-	server.mu.Lock()
+	server.mu.RLock()
 	service = server.serviceMap[serviceMethod[0]]
-	server.mu.Unlock()
+	server.mu.RUnlock()
 	if service == nil {
 		err = errors.New("rpc: can't find service " + req.ServiceMethod)
 		return
@@ -568,7 +596,7 @@ func (server *Server) Accept(lis net.Listener) {
 // Register publishes the receiver's methods in the DefaultServer.
 func Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) }
 
-// RegisterName is like Register but uses the provided name for the type 
+// RegisterName is like Register but uses the provided name for the type
 // instead of the receiver's concrete type.
 func RegisterName(name string, rcvr interface{}) error {
 	return DefaultServer.RegisterName(name, rcvr)
@@ -611,7 +639,7 @@ func ServeRequest(codec ServerCodec) error {
 }
 
 // Accept accepts connections on the listener and serves requests
-// to DefaultServer for each incoming connection.  
+// to DefaultServer for each incoming connection.
 // Accept blocks; the caller typically invokes it in a go statement.
 func Accept(lis net.Listener) { DefaultServer.Accept(lis) }
 
diff --git a/src/pkg/net/rpc/server_test.go b/src/pkg/net/rpc/server_test.go
index 62c7b1e..8a15306 100644
--- a/src/pkg/net/rpc/server_test.go
+++ b/src/pkg/net/rpc/server_test.go
@@ -349,6 +349,7 @@ func testServeRequest(t *testing.T, server *Server) {
 type ReplyNotPointer int
 type ArgNotPublic int
 type ReplyNotPublic int
+type NeedsPtrType int
 type local struct{}
 
 func (t *ReplyNotPointer) ReplyNotPointer(args *Args, reply Reply) error {
@@ -363,19 +364,29 @@ func (t *ReplyNotPublic) ReplyNotPublic(args *Args, reply *local) error {
 	return nil
 }
 
+func (t *NeedsPtrType) NeedsPtrType(args *Args, reply *Reply) error {
+	return nil
+}
+
 // Check that registration handles lots of bad methods and a type with no suitable methods.
 func TestRegistrationError(t *testing.T) {
 	err := Register(new(ReplyNotPointer))
 	if err == nil {
-		t.Errorf("expected error registering ReplyNotPointer")
+		t.Error("expected error registering ReplyNotPointer")
 	}
 	err = Register(new(ArgNotPublic))
 	if err == nil {
-		t.Errorf("expected error registering ArgNotPublic")
+		t.Error("expected error registering ArgNotPublic")
 	}
 	err = Register(new(ReplyNotPublic))
 	if err == nil {
-		t.Errorf("expected error registering ReplyNotPublic")
+		t.Error("expected error registering ReplyNotPublic")
+	}
+	err = Register(NeedsPtrType(0))
+	if err == nil {
+		t.Error("expected error registering NeedsPtrType")
+	} else if !strings.Contains(err.Error(), "pointer") {
+		t.Error("expected hint when registering NeedsPtrType")
 	}
 }
 
@@ -434,7 +445,7 @@ func dialHTTP() (*Client, error) {
 	return DialHTTP("tcp", httpServerAddr)
 }
 
-func countMallocs(dial func() (*Client, error), t *testing.T) uint64 {
+func countMallocs(dial func() (*Client, error), t *testing.T) float64 {
 	once.Do(startServer)
 	client, err := dial()
 	if err != nil {
@@ -442,11 +453,7 @@ func countMallocs(dial func() (*Client, error), t *testing.T) uint64 {
 	}
 	args := &Args{7, 8}
 	reply := new(Reply)
-	memstats := new(runtime.MemStats)
-	runtime.ReadMemStats(memstats)
-	mallocs := 0 - memstats.Mallocs
-	const count = 100
-	for i := 0; i < count; i++ {
+	return testing.AllocsPerRun(100, func() {
 		err := client.Call("Arith.Add", args, reply)
 		if err != nil {
 			t.Errorf("Add: expected no error but got string %q", err.Error())
@@ -454,18 +461,15 @@ func countMallocs(dial func() (*Client, error), t *testing.T) uint64 {
 		if reply.C != args.A+args.B {
 			t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
 		}
-	}
-	runtime.ReadMemStats(memstats)
-	mallocs += memstats.Mallocs
-	return mallocs / count
+	})
 }
 
 func TestCountMallocs(t *testing.T) {
-	fmt.Printf("mallocs per rpc round trip: %d\n", countMallocs(dialDirect, t))
+	fmt.Printf("mallocs per rpc round trip: %v\n", countMallocs(dialDirect, t))
 }
 
 func TestCountMallocsOverHTTP(t *testing.T) {
-	fmt.Printf("mallocs per HTTP rpc round trip: %d\n", countMallocs(dialHTTP, t))
+	fmt.Printf("mallocs per HTTP rpc round trip: %v\n", countMallocs(dialHTTP, t))
 }
 
 type writeCrasher struct {
@@ -499,6 +503,44 @@ func TestClientWriteError(t *testing.T) {
 	w.done <- true
 }
 
+func TestTCPClose(t *testing.T) {
+	once.Do(startServer)
+
+	client, err := dialHTTP()
+	if err != nil {
+		t.Fatalf("dialing: %v", err)
+	}
+	defer client.Close()
+
+	args := Args{17, 8}
+	var reply Reply
+	err = client.Call("Arith.Mul", args, &reply)
+	if err != nil {
+		t.Fatal("arith error:", err)
+	}
+	t.Logf("Arith: %d*%d=%d\n", args.A, args.B, reply)
+	if reply.C != args.A*args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A*args.B)
+	}
+}
+
+func TestErrorAfterClientClose(t *testing.T) {
+	once.Do(startServer)
+
+	client, err := dialHTTP()
+	if err != nil {
+		t.Fatalf("dialing: %v", err)
+	}
+	err = client.Close()
+	if err != nil {
+		t.Fatal("close error:", err)
+	}
+	err = client.Call("Arith.Add", &Args{7, 9}, new(Reply))
+	if err != ErrShutdown {
+		t.Errorf("Forever: expected ErrShutdown got %v", err)
+	}
+}
+
 func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
 	b.StopTimer()
 	once.Do(startServer)
diff --git a/src/pkg/net/sendfile_freebsd.go b/src/pkg/net/sendfile_freebsd.go
new file mode 100644
index 0000000..8008bc3
--- /dev/null
+++ b/src/pkg/net/sendfile_freebsd.go
@@ -0,0 +1,105 @@
+// 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 net
+
+import (
+	"io"
+	"os"
+	"syscall"
+)
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// sendFile copies the contents of r to c using the sendfile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
+	// FreeBSD uses 0 as the "until EOF" value. If you pass in more bytes than the
+	// file contains, it will loop back to the beginning ad nauseum until it's sent
+	// exactly the number of bytes told to. As such, we need to know exactly how many
+	// bytes to send.
+	var remain int64 = 0
+
+	lr, ok := r.(*io.LimitedReader)
+	if ok {
+		remain, r = lr.N, lr.R
+		if remain <= 0 {
+			return 0, nil, true
+		}
+	}
+	f, ok := r.(*os.File)
+	if !ok {
+		return 0, nil, false
+	}
+
+	if remain == 0 {
+		fi, err := f.Stat()
+		if err != nil {
+			return 0, err, false
+		}
+
+		remain = fi.Size()
+	}
+
+	// The other quirk with FreeBSD's sendfile implementation is that it doesn't
+	// use the current position of the file -- if you pass it offset 0, it starts
+	// from offset 0. There's no way to tell it "start from current position", so
+	// we have to manage that explicitly.
+	pos, err := f.Seek(0, os.SEEK_CUR)
+	if err != nil {
+		return 0, err, false
+	}
+
+	c.wio.Lock()
+	defer c.wio.Unlock()
+	if err := c.incref(false); err != nil {
+		return 0, err, true
+	}
+	defer c.decref()
+
+	dst := c.sysfd
+	src := int(f.Fd())
+	for remain > 0 {
+		n := maxSendfileSize
+		if int64(n) > remain {
+			n = int(remain)
+		}
+		pos1 := pos
+		n, err1 := syscall.Sendfile(dst, src, &pos1, n)
+		if n > 0 {
+			pos += int64(n)
+			written += int64(n)
+			remain -= int64(n)
+		}
+		if n == 0 && err1 == nil {
+			break
+		}
+		if err1 == syscall.EAGAIN {
+			if err1 = c.pollServer.WaitWrite(c); err1 == nil {
+				continue
+			}
+		}
+		if err1 == syscall.EINTR {
+			continue
+		}
+		if err1 != nil {
+			// This includes syscall.ENOSYS (no kernel
+			// support) and syscall.EINVAL (fd types which
+			// don't implement sendfile together)
+			err = &OpError{"sendfile", c.net, c.raddr, err1}
+			break
+		}
+	}
+	if lr != nil {
+		lr.N = remain
+	}
+	return written, err, written > 0
+}
diff --git a/src/pkg/net/sendfile_linux.go b/src/pkg/net/sendfile_linux.go
index a0d5303..3357e65 100644
--- a/src/pkg/net/sendfile_linux.go
+++ b/src/pkg/net/sendfile_linux.go
@@ -58,8 +58,8 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
 		if n == 0 && err1 == nil {
 			break
 		}
-		if err1 == syscall.EAGAIN && c.wdeadline >= 0 {
-			if err1 = pollserver.WaitWrite(c); err1 == nil {
+		if err1 == syscall.EAGAIN {
+			if err1 = c.pollServer.WaitWrite(c); err1 == nil {
 				continue
 			}
 		}
diff --git a/src/pkg/net/sendfile_stub.go b/src/pkg/net/sendfile_stub.go
index ff76ab9..3660849 100644
--- a/src/pkg/net/sendfile_stub.go
+++ b/src/pkg/net/sendfile_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 darwin freebsd netbsd openbsd
+// +build darwin netbsd openbsd
 
 package net
 
diff --git a/src/pkg/net/sendfile_windows.go b/src/pkg/net/sendfile_windows.go
index f5a6d88..2d64f2f 100644
--- a/src/pkg/net/sendfile_windows.go
+++ b/src/pkg/net/sendfile_windows.go
@@ -48,12 +48,12 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
 		return 0, nil, false
 	}
 
-	c.wio.Lock()
-	defer c.wio.Unlock()
 	if err := c.incref(false); err != nil {
 		return 0, err, true
 	}
 	defer c.decref()
+	c.wio.Lock()
+	defer c.wio.Unlock()
 
 	var o sendfileOp
 	o.Init(c, 'w')
diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go
index 158b947..25c2be5 100644
--- a/src/pkg/net/server_test.go
+++ b/src/pkg/net/server_test.go
@@ -113,8 +113,7 @@ func TestStreamConnServer(t *testing.T) {
 		case "tcp", "tcp4", "tcp6":
 			_, port, err := SplitHostPort(taddr)
 			if err != nil {
-				t.Errorf("SplitHostPort(%q) failed: %v", taddr, err)
-				return
+				t.Fatalf("SplitHostPort(%q) failed: %v", taddr, err)
 			}
 			taddr = tt.caddr + ":" + port
 		}
@@ -142,8 +141,7 @@ var seqpacketConnServerTests = []struct {
 
 func TestSeqpacketConnServer(t *testing.T) {
 	if runtime.GOOS != "linux" {
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 
 	for _, tt := range seqpacketConnServerTests {
@@ -170,11 +168,11 @@ func TestSeqpacketConnServer(t *testing.T) {
 }
 
 func runStreamConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
+	defer close(done)
 	l, err := Listen(net, laddr)
 	if err != nil {
 		t.Errorf("Listen(%q, %q) failed: %v", net, laddr, err)
 		listening <- "<nil>"
-		done <- 1
 		return
 	}
 	defer l.Close()
@@ -189,13 +187,14 @@ func runStreamConnServer(t *testing.T, net, laddr string, listening chan<- strin
 			}
 			rw.Write(buf[0:n])
 		}
-		done <- 1
+		close(done)
 	}
 
 run:
 	for {
 		c, err := l.Accept()
 		if err != nil {
+			t.Logf("Accept failed: %v", err)
 			continue run
 		}
 		echodone := make(chan int)
@@ -204,14 +203,12 @@ run:
 		c.Close()
 		break run
 	}
-	done <- 1
 }
 
 func runStreamConnClient(t *testing.T, net, taddr string, isEmpty bool) {
 	c, err := Dial(net, taddr)
 	if err != nil {
-		t.Errorf("Dial(%q, %q) failed: %v", net, taddr, err)
-		return
+		t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
 	}
 	defer c.Close()
 	c.SetReadDeadline(time.Now().Add(1 * time.Second))
@@ -221,14 +218,12 @@ func runStreamConnClient(t *testing.T, net, taddr string, isEmpty bool) {
 		wb = []byte("StreamConnClient by Dial\n")
 	}
 	if n, err := c.Write(wb); err != nil || n != len(wb) {
-		t.Errorf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
-		return
+		t.Fatalf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
 	}
 
 	rb := make([]byte, 1024)
 	if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
-		t.Errorf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
-		return
+		t.Fatalf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
 	}
 
 	// Send explicit ending for unixpacket.
@@ -334,8 +329,7 @@ func TestDatagramPacketConnServer(t *testing.T) {
 		case "udp", "udp4", "udp6":
 			_, port, err := SplitHostPort(taddr)
 			if err != nil {
-				t.Errorf("SplitHostPort(%q) failed: %v", taddr, err)
-				return
+				t.Fatalf("SplitHostPort(%q) failed: %v", taddr, err)
 			}
 			taddr = tt.caddr + ":" + port
 			tt.caddr += ":0"
@@ -398,14 +392,12 @@ func runDatagramConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool)
 	case "udp", "udp4", "udp6":
 		c, err = Dial(net, taddr)
 		if err != nil {
-			t.Errorf("Dial(%q, %q) failed: %v", net, taddr, err)
-			return
+			t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
 		}
 	case "unixgram":
 		c, err = DialUnix(net, &UnixAddr{laddr, net}, &UnixAddr{taddr, net})
 		if err != nil {
-			t.Errorf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err)
-			return
+			t.Fatalf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err)
 		}
 	}
 	defer c.Close()
@@ -416,14 +408,12 @@ func runDatagramConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool)
 		wb = []byte("DatagramConnClient by Dial\n")
 	}
 	if n, err := c.Write(wb[0:]); err != nil || n != len(wb) {
-		t.Errorf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
-		return
+		t.Fatalf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
 	}
 
 	rb := make([]byte, 1024)
 	if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
-		t.Errorf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
-		return
+		t.Fatalf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
 	}
 }
 
@@ -434,20 +424,17 @@ func runDatagramPacketConnClient(t *testing.T, net, laddr, taddr string, isEmpty
 	case "udp", "udp4", "udp6":
 		ra, err = ResolveUDPAddr(net, taddr)
 		if err != nil {
-			t.Errorf("ResolveUDPAddr(%q, %q) failed: %v", net, taddr, err)
-			return
+			t.Fatalf("ResolveUDPAddr(%q, %q) failed: %v", net, taddr, err)
 		}
 	case "unixgram":
 		ra, err = ResolveUnixAddr(net, taddr)
 		if err != nil {
-			t.Errorf("ResolveUxixAddr(%q, %q) failed: %v", net, taddr, err)
-			return
+			t.Fatalf("ResolveUxixAddr(%q, %q) failed: %v", net, taddr, err)
 		}
 	}
 	c, err := ListenPacket(net, laddr)
 	if err != nil {
-		t.Errorf("ListenPacket(%q, %q) faild: %v", net, laddr, err)
-		return
+		t.Fatalf("ListenPacket(%q, %q) faild: %v", net, laddr, err)
 	}
 	defer c.Close()
 	c.SetReadDeadline(time.Now().Add(1 * time.Second))
@@ -457,13 +444,11 @@ func runDatagramPacketConnClient(t *testing.T, net, laddr, taddr string, isEmpty
 		wb = []byte("DatagramPacketConnClient by ListenPacket\n")
 	}
 	if n, err := c.WriteTo(wb[0:], ra); err != nil || n != len(wb) {
-		t.Errorf("WriteTo(%v) failed: %v, %v; want %v, <nil>", ra, n, err, len(wb))
-		return
+		t.Fatalf("WriteTo(%v) failed: %v, %v; want %v, <nil>", ra, n, err, len(wb))
 	}
 
 	rb := make([]byte, 1024)
 	if n, _, err := c.ReadFrom(rb[0:]); err != nil || n != len(wb) {
-		t.Errorf("ReadFrom failed: %v, %v; want %v, <nil>", n, err, len(wb))
-		return
+		t.Fatalf("ReadFrom failed: %v, %v; want %v, <nil>", n, err, len(wb))
 	}
 }
diff --git a/src/pkg/net/smtp/smtp.go b/src/pkg/net/smtp/smtp.go
index 59f6449..4b91778 100644
--- a/src/pkg/net/smtp/smtp.go
+++ b/src/pkg/net/smtp/smtp.go
@@ -13,6 +13,7 @@ package smtp
 import (
 	"crypto/tls"
 	"encoding/base64"
+	"errors"
 	"io"
 	"net"
 	"net/textproto"
@@ -33,7 +34,10 @@ type Client struct {
 	// map of supported extensions
 	ext map[string]string
 	// supported auth mechanisms
-	auth []string
+	auth       []string
+	localName  string // the name to use in HELO/EHLO
+	didHello   bool   // whether we've said HELO/EHLO
+	helloError error  // the error from the hello
 }
 
 // Dial returns a new Client connected to an SMTP server at addr.
@@ -55,12 +59,33 @@ func NewClient(conn net.Conn, host string) (*Client, error) {
 		text.Close()
 		return nil, err
 	}
-	c := &Client{Text: text, conn: conn, serverName: host}
-	err = c.ehlo()
-	if err != nil {
-		err = c.helo()
+	c := &Client{Text: text, conn: conn, serverName: host, localName: "localhost"}
+	return c, nil
+}
+
+// hello runs a hello exchange if needed.
+func (c *Client) hello() error {
+	if !c.didHello {
+		c.didHello = true
+		err := c.ehlo()
+		if err != nil {
+			c.helloError = c.helo()
+		}
+	}
+	return c.helloError
+}
+
+// Hello sends a HELO or EHLO to the server as the given host name.
+// Calling this method is only necessary if the client needs control
+// over the host name used.  The client will introduce itself as "localhost"
+// automatically otherwise.  If Hello is called, it must be called before
+// any of the other methods.
+func (c *Client) Hello(localName string) error {
+	if c.didHello {
+		return errors.New("smtp: Hello called after other methods")
 	}
-	return c, err
+	c.localName = localName
+	return c.hello()
 }
 
 // cmd is a convenience function that sends a command and returns the response
@@ -79,14 +104,14 @@ func (c *Client) cmd(expectCode int, format string, args ...interface{}) (int, s
 // server does not support ehlo.
 func (c *Client) helo() error {
 	c.ext = nil
-	_, _, err := c.cmd(250, "HELO localhost")
+	_, _, err := c.cmd(250, "HELO %s", c.localName)
 	return err
 }
 
 // ehlo sends the EHLO (extended hello) greeting to the server. It
 // should be the preferred greeting for servers that support it.
 func (c *Client) ehlo() error {
-	_, msg, err := c.cmd(250, "EHLO localhost")
+	_, msg, err := c.cmd(250, "EHLO %s", c.localName)
 	if err != nil {
 		return err
 	}
@@ -113,6 +138,9 @@ func (c *Client) ehlo() error {
 // StartTLS sends the STARTTLS command and encrypts all further communication.
 // Only servers that advertise the STARTTLS extension support this function.
 func (c *Client) StartTLS(config *tls.Config) error {
+	if err := c.hello(); err != nil {
+		return err
+	}
 	_, _, err := c.cmd(220, "STARTTLS")
 	if err != nil {
 		return err
@@ -128,6 +156,9 @@ func (c *Client) StartTLS(config *tls.Config) error {
 // does not necessarily indicate an invalid address. Many servers
 // will not verify addresses for security reasons.
 func (c *Client) Verify(addr string) error {
+	if err := c.hello(); err != nil {
+		return err
+	}
 	_, _, err := c.cmd(250, "VRFY %s", addr)
 	return err
 }
@@ -136,6 +167,9 @@ func (c *Client) Verify(addr string) error {
 // A failed authentication closes the connection.
 // Only servers that advertise the AUTH extension support this function.
 func (c *Client) Auth(a Auth) error {
+	if err := c.hello(); err != nil {
+		return err
+	}
 	encoding := base64.StdEncoding
 	mech, resp, err := a.Start(&ServerInfo{c.serverName, c.tls, c.auth})
 	if err != nil {
@@ -178,6 +212,9 @@ func (c *Client) Auth(a Auth) error {
 // parameter.
 // This initiates a mail transaction and is followed by one or more Rcpt calls.
 func (c *Client) Mail(from string) error {
+	if err := c.hello(); err != nil {
+		return err
+	}
 	cmdStr := "MAIL FROM:<%s>"
 	if c.ext != nil {
 		if _, ok := c.ext["8BITMIME"]; ok {
@@ -227,6 +264,9 @@ func SendMail(addr string, a Auth, from string, to []string, msg []byte) error {
 	if err != nil {
 		return err
 	}
+	if err := c.hello(); err != nil {
+		return err
+	}
 	if ok, _ := c.Extension("STARTTLS"); ok {
 		if err = c.StartTLS(nil); err != nil {
 			return err
@@ -267,6 +307,9 @@ func SendMail(addr string, a Auth, from string, to []string, msg []byte) error {
 // Extension also returns a string that contains any parameters the
 // server specifies for the extension.
 func (c *Client) Extension(ext string) (bool, string) {
+	if err := c.hello(); err != nil {
+		return false, ""
+	}
 	if c.ext == nil {
 		return false, ""
 	}
@@ -278,12 +321,18 @@ func (c *Client) Extension(ext string) (bool, string) {
 // Reset sends the RSET command to the server, aborting the current mail
 // transaction.
 func (c *Client) Reset() error {
+	if err := c.hello(); err != nil {
+		return err
+	}
 	_, _, err := c.cmd(250, "RSET")
 	return err
 }
 
 // Quit sends the QUIT command and closes the connection to the server.
 func (c *Client) Quit() error {
+	if err := c.hello(); err != nil {
+		return err
+	}
 	_, _, err := c.cmd(221, "QUIT")
 	if err != nil {
 		return err
diff --git a/src/pkg/net/smtp/smtp_test.go b/src/pkg/net/smtp/smtp_test.go
index c315d18..8317428 100644
--- a/src/pkg/net/smtp/smtp_test.go
+++ b/src/pkg/net/smtp/smtp_test.go
@@ -69,14 +69,14 @@ func (f faker) SetReadDeadline(time.Time) error  { return nil }
 func (f faker) SetWriteDeadline(time.Time) error { return nil }
 
 func TestBasic(t *testing.T) {
-	basicServer = strings.Join(strings.Split(basicServer, "\n"), "\r\n")
-	basicClient = strings.Join(strings.Split(basicClient, "\n"), "\r\n")
+	server := strings.Join(strings.Split(basicServer, "\n"), "\r\n")
+	client := strings.Join(strings.Split(basicClient, "\n"), "\r\n")
 
 	var cmdbuf bytes.Buffer
 	bcmdbuf := bufio.NewWriter(&cmdbuf)
 	var fake faker
-	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(basicServer)), bcmdbuf)
-	c := &Client{Text: textproto.NewConn(fake)}
+	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
+	c := &Client{Text: textproto.NewConn(fake), localName: "localhost"}
 
 	if err := c.helo(); err != nil {
 		t.Fatalf("HELO failed: %s", err)
@@ -88,6 +88,7 @@ func TestBasic(t *testing.T) {
 		t.Fatalf("Second EHLO failed: %s", err)
 	}
 
+	c.didHello = true
 	if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" {
 		t.Fatalf("Expected AUTH supported")
 	}
@@ -143,8 +144,8 @@ Goodbye.`
 
 	bcmdbuf.Flush()
 	actualcmds := cmdbuf.String()
-	if basicClient != actualcmds {
-		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, basicClient)
+	if client != actualcmds {
+		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client)
 	}
 }
 
@@ -187,8 +188,8 @@ QUIT
 `
 
 func TestNewClient(t *testing.T) {
-	newClientServer = strings.Join(strings.Split(newClientServer, "\n"), "\r\n")
-	newClientClient = strings.Join(strings.Split(newClientClient, "\n"), "\r\n")
+	server := strings.Join(strings.Split(newClientServer, "\n"), "\r\n")
+	client := strings.Join(strings.Split(newClientClient, "\n"), "\r\n")
 
 	var cmdbuf bytes.Buffer
 	bcmdbuf := bufio.NewWriter(&cmdbuf)
@@ -197,7 +198,7 @@ func TestNewClient(t *testing.T) {
 		return cmdbuf.String()
 	}
 	var fake faker
-	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(newClientServer)), bcmdbuf)
+	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
 	c, err := NewClient(fake, "fake.host")
 	if err != nil {
 		t.Fatalf("NewClient: %v\n(after %v)", err, out())
@@ -213,8 +214,8 @@ func TestNewClient(t *testing.T) {
 	}
 
 	actualcmds := out()
-	if newClientClient != actualcmds {
-		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, newClientClient)
+	if client != actualcmds {
+		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client)
 	}
 }
 
@@ -231,13 +232,13 @@ QUIT
 `
 
 func TestNewClient2(t *testing.T) {
-	newClient2Server = strings.Join(strings.Split(newClient2Server, "\n"), "\r\n")
-	newClient2Client = strings.Join(strings.Split(newClient2Client, "\n"), "\r\n")
+	server := strings.Join(strings.Split(newClient2Server, "\n"), "\r\n")
+	client := strings.Join(strings.Split(newClient2Client, "\n"), "\r\n")
 
 	var cmdbuf bytes.Buffer
 	bcmdbuf := bufio.NewWriter(&cmdbuf)
 	var fake faker
-	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(newClient2Server)), bcmdbuf)
+	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
 	c, err := NewClient(fake, "fake.host")
 	if err != nil {
 		t.Fatalf("NewClient: %v", err)
@@ -251,8 +252,8 @@ func TestNewClient2(t *testing.T) {
 
 	bcmdbuf.Flush()
 	actualcmds := cmdbuf.String()
-	if newClient2Client != actualcmds {
-		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, newClient2Client)
+	if client != actualcmds {
+		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client)
 	}
 }
 
@@ -269,3 +270,199 @@ var newClient2Client = `EHLO localhost
 HELO localhost
 QUIT
 `
+
+func TestHello(t *testing.T) {
+
+	if len(helloServer) != len(helloClient) {
+		t.Fatalf("Hello server and client size mismatch")
+	}
+
+	for i := 0; i < len(helloServer); i++ {
+		server := strings.Join(strings.Split(baseHelloServer+helloServer[i], "\n"), "\r\n")
+		client := strings.Join(strings.Split(baseHelloClient+helloClient[i], "\n"), "\r\n")
+		var cmdbuf bytes.Buffer
+		bcmdbuf := bufio.NewWriter(&cmdbuf)
+		var fake faker
+		fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
+		c, err := NewClient(fake, "fake.host")
+		if err != nil {
+			t.Fatalf("NewClient: %v", err)
+		}
+		c.localName = "customhost"
+		err = nil
+
+		switch i {
+		case 0:
+			err = c.Hello("customhost")
+		case 1:
+			err = c.StartTLS(nil)
+			if err.Error() == "502 Not implemented" {
+				err = nil
+			}
+		case 2:
+			err = c.Verify("test at example.com")
+		case 3:
+			c.tls = true
+			c.serverName = "smtp.google.com"
+			err = c.Auth(PlainAuth("", "user", "pass", "smtp.google.com"))
+		case 4:
+			err = c.Mail("test at example.com")
+		case 5:
+			ok, _ := c.Extension("feature")
+			if ok {
+				t.Errorf("Expected FEATURE not to be supported")
+			}
+		case 6:
+			err = c.Reset()
+		case 7:
+			err = c.Quit()
+		case 8:
+			err = c.Verify("test at example.com")
+			if err != nil {
+				err = c.Hello("customhost")
+				if err != nil {
+					t.Errorf("Want error, got none")
+				}
+			}
+		default:
+			t.Fatalf("Unhandled command")
+		}
+
+		if err != nil {
+			t.Errorf("Command %d failed: %v", i, err)
+		}
+
+		bcmdbuf.Flush()
+		actualcmds := cmdbuf.String()
+		if client != actualcmds {
+			t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client)
+		}
+	}
+}
+
+var baseHelloServer = `220 hello world
+502 EH?
+250-mx.google.com at your service
+250 FEATURE
+`
+
+var helloServer = []string{
+	"",
+	"502 Not implemented\n",
+	"250 User is valid\n",
+	"235 Accepted\n",
+	"250 Sender ok\n",
+	"",
+	"250 Reset ok\n",
+	"221 Goodbye\n",
+	"250 Sender ok\n",
+}
+
+var baseHelloClient = `EHLO customhost
+HELO customhost
+`
+
+var helloClient = []string{
+	"",
+	"STARTTLS\n",
+	"VRFY test at example.com\n",
+	"AUTH PLAIN AHVzZXIAcGFzcw==\n",
+	"MAIL FROM:<test at example.com>\n",
+	"",
+	"RSET\n",
+	"QUIT\n",
+	"VRFY test at example.com\n",
+}
+
+func TestSendMail(t *testing.T) {
+	server := strings.Join(strings.Split(sendMailServer, "\n"), "\r\n")
+	client := strings.Join(strings.Split(sendMailClient, "\n"), "\r\n")
+	var cmdbuf bytes.Buffer
+	bcmdbuf := bufio.NewWriter(&cmdbuf)
+	l, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Unable to to create listener: %v", err)
+	}
+	defer l.Close()
+
+	// prevent data race on bcmdbuf
+	var done = make(chan struct{})
+	go func(data []string) {
+
+		defer close(done)
+
+		conn, err := l.Accept()
+		if err != nil {
+			t.Errorf("Accept error: %v", err)
+			return
+		}
+		defer conn.Close()
+
+		tc := textproto.NewConn(conn)
+		for i := 0; i < len(data) && data[i] != ""; i++ {
+			tc.PrintfLine(data[i])
+			for len(data[i]) >= 4 && data[i][3] == '-' {
+				i++
+				tc.PrintfLine(data[i])
+			}
+			if data[i] == "221 Goodbye" {
+				return
+			}
+			read := false
+			for !read || data[i] == "354 Go ahead" {
+				msg, err := tc.ReadLine()
+				bcmdbuf.Write([]byte(msg + "\r\n"))
+				read = true
+				if err != nil {
+					t.Errorf("Read error: %v", err)
+					return
+				}
+				if data[i] == "354 Go ahead" && msg == "." {
+					break
+				}
+			}
+		}
+	}(strings.Split(server, "\r\n"))
+
+	err = SendMail(l.Addr().String(), nil, "test at example.com", []string{"other at example.com"}, []byte(strings.Replace(`From: test at example.com
+To: other at example.com
+Subject: SendMail test
+
+SendMail is working for me.
+`, "\n", "\r\n", -1)))
+
+	if err != nil {
+		t.Errorf("%v", err)
+	}
+
+	<-done
+	bcmdbuf.Flush()
+	actualcmds := cmdbuf.String()
+	if client != actualcmds {
+		t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client)
+	}
+}
+
+var sendMailServer = `220 hello world
+502 EH?
+250 mx.google.com at your service
+250 Sender ok
+250 Receiver ok
+354 Go ahead
+250 Data ok
+221 Goodbye
+`
+
+var sendMailClient = `EHLO localhost
+HELO localhost
+MAIL FROM:<test at example.com>
+RCPT TO:<other at example.com>
+DATA
+From: test at example.com
+To: other at example.com
+Subject: SendMail test
+
+SendMail is working for me.
+.
+QUIT
+`
diff --git a/src/pkg/net/sock.go b/src/pkg/net/sock.go
deleted file mode 100644
index 3ae1605..0000000
--- a/src/pkg/net/sock.go
+++ /dev/null
@@ -1,87 +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 darwin freebsd linux netbsd openbsd windows
-
-// Sockets
-
-package net
-
-import (
-	"io"
-	"syscall"
-)
-
-var listenerBacklog = maxListenerBacklog()
-
-// Generic socket creation.
-func socket(net string, f, t, p int, ipv6only bool, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
-	// See ../syscall/exec.go for description of ForkLock.
-	syscall.ForkLock.RLock()
-	s, err := syscall.Socket(f, t, p)
-	if err != nil {
-		syscall.ForkLock.RUnlock()
-		return nil, err
-	}
-	syscall.CloseOnExec(s)
-	syscall.ForkLock.RUnlock()
-
-	err = setDefaultSockopts(s, f, t, ipv6only)
-	if err != nil {
-		closesocket(s)
-		return nil, err
-	}
-
-	var bla syscall.Sockaddr
-	if la != nil {
-		bla, err = listenerSockaddr(s, f, la, toAddr)
-		if err != nil {
-			closesocket(s)
-			return nil, err
-		}
-		err = syscall.Bind(s, bla)
-		if err != nil {
-			closesocket(s)
-			return nil, err
-		}
-	}
-
-	if fd, err = newFD(s, f, t, net); err != nil {
-		closesocket(s)
-		return nil, err
-	}
-
-	if ra != nil {
-		if err = fd.connect(ra); err != nil {
-			closesocket(s)
-			fd.Close()
-			return nil, err
-		}
-		fd.isConnected = true
-	}
-
-	sa, _ := syscall.Getsockname(s)
-	var laddr Addr
-	if la != nil && bla != la {
-		laddr = toAddr(la)
-	} else {
-		laddr = toAddr(sa)
-	}
-	sa, _ = syscall.Getpeername(s)
-	raddr := toAddr(sa)
-
-	fd.setAddr(laddr, raddr)
-	return fd, nil
-}
-
-type writerOnly struct {
-	io.Writer
-}
-
-// Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
-// applicable.
-func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) {
-	// Use wrapper to hide existing r.ReadFrom from io.Copy.
-	return io.Copy(writerOnly{w}, r)
-}
diff --git a/src/pkg/net/sock_bsd.go b/src/pkg/net/sock_bsd.go
index 2607b04..3205f94 100644
--- a/src/pkg/net/sock_bsd.go
+++ b/src/pkg/net/sock_bsd.go
@@ -4,8 +4,6 @@
 
 // +build darwin freebsd netbsd openbsd
 
-// Sockets for BSD variants
-
 package net
 
 import (
@@ -31,32 +29,3 @@ func maxListenerBacklog() int {
 	}
 	return int(n)
 }
-
-func listenerSockaddr(s, f int, la syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (syscall.Sockaddr, error) {
-	a := toAddr(la)
-	if a == nil {
-		return la, nil
-	}
-	switch v := a.(type) {
-	case *TCPAddr, *UnixAddr:
-		err := setDefaultListenerSockopts(s)
-		if err != nil {
-			return nil, err
-		}
-	case *UDPAddr:
-		if v.IP.IsMulticast() {
-			err := setDefaultMulticastSockopts(s)
-			if err != nil {
-				return nil, err
-			}
-			switch f {
-			case syscall.AF_INET:
-				v.IP = IPv4zero
-			case syscall.AF_INET6:
-				v.IP = IPv6unspecified
-			}
-			return v.sockaddr(f)
-		}
-	}
-	return la, nil
-}
diff --git a/src/pkg/net/sock_cloexec.go b/src/pkg/net/sock_cloexec.go
new file mode 100644
index 0000000..12d0f34
--- /dev/null
+++ b/src/pkg/net/sock_cloexec.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.
+
+// This file implements sysSocket and accept for platforms that
+// provide a fast path for setting SetNonblock and CloseOnExec.
+
+// +build linux
+
+package net
+
+import "syscall"
+
+// Wrapper around the socket system call that marks the returned file
+// descriptor as nonblocking and close-on-exec.
+func sysSocket(f, t, p int) (int, error) {
+	s, err := syscall.Socket(f, t|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, p)
+	// The SOCK_NONBLOCK and SOCK_CLOEXEC flags were introduced in
+	// Linux 2.6.27.  If we get an EINVAL error, fall back to
+	// using socket without them.
+	if err == nil || err != syscall.EINVAL {
+		return s, err
+	}
+
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	syscall.ForkLock.RLock()
+	s, err = syscall.Socket(f, t, p)
+	if err == nil {
+		syscall.CloseOnExec(s)
+	}
+	syscall.ForkLock.RUnlock()
+	if err != nil {
+		return -1, err
+	}
+	if err = syscall.SetNonblock(s, true); err != nil {
+		syscall.Close(s)
+		return -1, err
+	}
+	return s, nil
+}
+
+// Wrapper around the accept system call that marks the returned file
+// descriptor as nonblocking and close-on-exec.
+func accept(fd int) (int, syscall.Sockaddr, error) {
+	nfd, sa, err := syscall.Accept4(fd, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
+	// The accept4 system call was introduced in Linux 2.6.28.  If
+	// we get an ENOSYS error, fall back to using accept.
+	if err == nil || err != syscall.ENOSYS {
+		return nfd, sa, err
+	}
+
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	// It is probably okay to hold the lock across syscall.Accept
+	// because we have put fd.sysfd into non-blocking mode.
+	// However, a call to the File method will put it back into
+	// blocking mode. We can't take that risk, so no use of ForkLock here.
+	nfd, sa, err = syscall.Accept(fd)
+	if err == nil {
+		syscall.CloseOnExec(nfd)
+	}
+	if err != nil {
+		return -1, nil, err
+	}
+	if err = syscall.SetNonblock(nfd, true); err != nil {
+		syscall.Close(nfd)
+		return -1, nil, err
+	}
+	return nfd, sa, nil
+}
diff --git a/src/pkg/net/sock_linux.go b/src/pkg/net/sock_linux.go
index e509d93..8bbd74d 100644
--- a/src/pkg/net/sock_linux.go
+++ b/src/pkg/net/sock_linux.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.
 
-// Sockets for Linux
-
 package net
 
 import "syscall"
@@ -25,32 +23,3 @@ func maxListenerBacklog() int {
 	}
 	return n
 }
-
-func listenerSockaddr(s, f int, la syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (syscall.Sockaddr, error) {
-	a := toAddr(la)
-	if a == nil {
-		return la, nil
-	}
-	switch v := a.(type) {
-	case *TCPAddr, *UnixAddr:
-		err := setDefaultListenerSockopts(s)
-		if err != nil {
-			return nil, err
-		}
-	case *UDPAddr:
-		if v.IP.IsMulticast() {
-			err := setDefaultMulticastSockopts(s)
-			if err != nil {
-				return nil, err
-			}
-			switch f {
-			case syscall.AF_INET:
-				v.IP = IPv4zero
-			case syscall.AF_INET6:
-				v.IP = IPv6unspecified
-			}
-			return v.sockaddr(f)
-		}
-	}
-	return la, nil
-}
diff --git a/src/pkg/net/sock_posix.go b/src/pkg/net/sock_posix.go
new file mode 100644
index 0000000..b50a892
--- /dev/null
+++ b/src/pkg/net/sock_posix.go
@@ -0,0 +1,67 @@
+// 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 darwin freebsd linux netbsd openbsd windows
+
+package net
+
+import (
+	"syscall"
+	"time"
+)
+
+var listenerBacklog = maxListenerBacklog()
+
+// Generic POSIX socket creation.
+func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
+	s, err := sysSocket(f, t, p)
+	if err != nil {
+		return nil, err
+	}
+
+	if err = setDefaultSockopts(s, f, t, ipv6only); err != nil {
+		closesocket(s)
+		return nil, err
+	}
+
+	if ulsa != nil {
+		// We provide a socket that listens to a wildcard
+		// address with reusable UDP port when the given ulsa
+		// is an appropriate UDP multicast address prefix.
+		// This makes it possible for a single UDP listener
+		// to join multiple different group addresses, for
+		// multiple UDP listeners that listen on the same UDP
+		// port to join the same group address.
+		if ulsa, err = listenerSockaddr(s, f, ulsa, toAddr); err != nil {
+			closesocket(s)
+			return nil, err
+		}
+		if err = syscall.Bind(s, ulsa); err != nil {
+			closesocket(s)
+			return nil, err
+		}
+	}
+
+	if fd, err = newFD(s, f, t, net); err != nil {
+		closesocket(s)
+		return nil, err
+	}
+
+	if ursa != nil {
+		fd.wdeadline.setTime(deadline)
+		if err = fd.connect(ursa); err != nil {
+			closesocket(s)
+			return nil, err
+		}
+		fd.isConnected = true
+		fd.wdeadline.set(0)
+	}
+
+	lsa, _ := syscall.Getsockname(s)
+	laddr := toAddr(lsa)
+	rsa, _ := syscall.Getpeername(s)
+	raddr := toAddr(rsa)
+	fd.setAddr(laddr, raddr)
+	return fd, nil
+}
diff --git a/src/pkg/net/sock_unix.go b/src/pkg/net/sock_unix.go
new file mode 100644
index 0000000..b0d6d49
--- /dev/null
+++ b/src/pkg/net/sock_unix.go
@@ -0,0 +1,36 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd
+
+package net
+
+import "syscall"
+
+func listenerSockaddr(s, f int, la syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (syscall.Sockaddr, error) {
+	a := toAddr(la)
+	if a == nil {
+		return la, nil
+	}
+	switch a := a.(type) {
+	case *TCPAddr, *UnixAddr:
+		if err := setDefaultListenerSockopts(s); err != nil {
+			return nil, err
+		}
+	case *UDPAddr:
+		if a.IP.IsMulticast() {
+			if err := setDefaultMulticastSockopts(s); err != nil {
+				return nil, err
+			}
+			switch f {
+			case syscall.AF_INET:
+				a.IP = IPv4zero
+			case syscall.AF_INET6:
+				a.IP = IPv6unspecified
+			}
+			return a.sockaddr(f)
+		}
+	}
+	return la, nil
+}
diff --git a/src/pkg/net/sock_windows.go b/src/pkg/net/sock_windows.go
index cce6181..a77c484 100644
--- a/src/pkg/net/sock_windows.go
+++ b/src/pkg/net/sock_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.
 
-// Sockets for Windows
-
 package net
 
 import "syscall"
@@ -18,26 +16,35 @@ func listenerSockaddr(s syscall.Handle, f int, la syscall.Sockaddr, toAddr func(
 	if a == nil {
 		return la, nil
 	}
-	switch v := a.(type) {
+	switch a := a.(type) {
 	case *TCPAddr, *UnixAddr:
-		err := setDefaultListenerSockopts(s)
-		if err != nil {
+		if err := setDefaultListenerSockopts(s); err != nil {
 			return nil, err
 		}
 	case *UDPAddr:
-		if v.IP.IsMulticast() {
-			err := setDefaultMulticastSockopts(s)
-			if err != nil {
+		if a.IP.IsMulticast() {
+			if err := setDefaultMulticastSockopts(s); err != nil {
 				return nil, err
 			}
 			switch f {
 			case syscall.AF_INET:
-				v.IP = IPv4zero
+				a.IP = IPv4zero
 			case syscall.AF_INET6:
-				v.IP = IPv6unspecified
+				a.IP = IPv6unspecified
 			}
-			return v.sockaddr(f)
+			return a.sockaddr(f)
 		}
 	}
 	return la, nil
 }
+
+func sysSocket(f, t, p int) (syscall.Handle, error) {
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	syscall.ForkLock.RLock()
+	s, err := syscall.Socket(f, t, p)
+	if err == nil {
+		syscall.CloseOnExec(s)
+	}
+	syscall.ForkLock.RUnlock()
+	return s, err
+}
diff --git a/src/pkg/net/sockopt.go b/src/pkg/net/sockopt.go
deleted file mode 100644
index 0cd1926..0000000
--- a/src/pkg/net/sockopt.go
+++ /dev/null
@@ -1,193 +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 darwin freebsd linux netbsd openbsd windows
-
-// Socket options
-
-package net
-
-import (
-	"os"
-	"syscall"
-	"time"
-)
-
-// Boolean to int.
-func boolint(b bool) int {
-	if b {
-		return 1
-	}
-	return 0
-}
-
-func ipv4AddrToInterface(ip IP) (*Interface, error) {
-	ift, err := Interfaces()
-	if err != nil {
-		return nil, err
-	}
-	for _, ifi := range ift {
-		ifat, err := ifi.Addrs()
-		if err != nil {
-			return nil, err
-		}
-		for _, ifa := range ifat {
-			switch v := ifa.(type) {
-			case *IPAddr:
-				if ip.Equal(v.IP) {
-					return &ifi, nil
-				}
-			case *IPNet:
-				if ip.Equal(v.IP) {
-					return &ifi, nil
-				}
-			}
-		}
-	}
-	if ip.Equal(IPv4zero) {
-		return nil, nil
-	}
-	return nil, errNoSuchInterface
-}
-
-func interfaceToIPv4Addr(ifi *Interface) (IP, error) {
-	if ifi == nil {
-		return IPv4zero, nil
-	}
-	ifat, err := ifi.Addrs()
-	if err != nil {
-		return nil, err
-	}
-	for _, ifa := range ifat {
-		switch v := ifa.(type) {
-		case *IPAddr:
-			if v.IP.To4() != nil {
-				return v.IP, nil
-			}
-		case *IPNet:
-			if v.IP.To4() != nil {
-				return v.IP, nil
-			}
-		}
-	}
-	return nil, errNoSuchInterface
-}
-
-func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error {
-	if ifi == nil {
-		return nil
-	}
-	ifat, err := ifi.Addrs()
-	if err != nil {
-		return err
-	}
-	for _, ifa := range ifat {
-		switch v := ifa.(type) {
-		case *IPAddr:
-			if a := v.IP.To4(); a != nil {
-				copy(mreq.Interface[:], a)
-				goto done
-			}
-		case *IPNet:
-			if a := v.IP.To4(); a != nil {
-				copy(mreq.Interface[:], a)
-				goto done
-			}
-		}
-	}
-done:
-	if bytesEqual(mreq.Multiaddr[:], IPv4zero.To4()) {
-		return errNoSuchMulticastInterface
-	}
-	return nil
-}
-
-func setReadBuffer(fd *netFD, bytes int) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes))
-}
-
-func setWriteBuffer(fd *netFD, bytes int) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
-}
-
-func setReadDeadline(fd *netFD, t time.Time) error {
-	if t.IsZero() {
-		fd.rdeadline = 0
-	} else {
-		fd.rdeadline = t.UnixNano()
-	}
-	return nil
-}
-
-func setWriteDeadline(fd *netFD, t time.Time) error {
-	if t.IsZero() {
-		fd.wdeadline = 0
-	} else {
-		fd.wdeadline = t.UnixNano()
-	}
-	return nil
-}
-
-func setDeadline(fd *netFD, t time.Time) error {
-	if err := setReadDeadline(fd, t); err != nil {
-		return err
-	}
-	return setWriteDeadline(fd, t)
-}
-
-func setReuseAddr(fd *netFD, reuse bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse)))
-}
-
-func setDontRoute(fd *netFD, dontroute bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute)))
-}
-
-func setKeepAlive(fd *netFD, keepalive bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive)))
-}
-
-func setNoDelay(fd *netFD, noDelay bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay)))
-}
-
-func setLinger(fd *netFD, sec int) error {
-	var l syscall.Linger
-	if sec >= 0 {
-		l.Onoff = 1
-		l.Linger = int32(sec)
-	} else {
-		l.Onoff = 0
-		l.Linger = 0
-	}
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l))
-}
diff --git a/src/pkg/net/sockopt_posix.go b/src/pkg/net/sockopt_posix.go
new file mode 100644
index 0000000..fe371fe
--- /dev/null
+++ b/src/pkg/net/sockopt_posix.go
@@ -0,0 +1,170 @@
+// 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 darwin freebsd linux netbsd openbsd windows
+
+// Socket options
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"time"
+)
+
+// Boolean to int.
+func boolint(b bool) int {
+	if b {
+		return 1
+	}
+	return 0
+}
+
+func ipv4AddrToInterface(ip IP) (*Interface, error) {
+	ift, err := Interfaces()
+	if err != nil {
+		return nil, err
+	}
+	for _, ifi := range ift {
+		ifat, err := ifi.Addrs()
+		if err != nil {
+			return nil, err
+		}
+		for _, ifa := range ifat {
+			switch v := ifa.(type) {
+			case *IPAddr:
+				if ip.Equal(v.IP) {
+					return &ifi, nil
+				}
+			case *IPNet:
+				if ip.Equal(v.IP) {
+					return &ifi, nil
+				}
+			}
+		}
+	}
+	if ip.Equal(IPv4zero) {
+		return nil, nil
+	}
+	return nil, errNoSuchInterface
+}
+
+func interfaceToIPv4Addr(ifi *Interface) (IP, error) {
+	if ifi == nil {
+		return IPv4zero, nil
+	}
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		return nil, err
+	}
+	for _, ifa := range ifat {
+		switch v := ifa.(type) {
+		case *IPAddr:
+			if v.IP.To4() != nil {
+				return v.IP, nil
+			}
+		case *IPNet:
+			if v.IP.To4() != nil {
+				return v.IP, nil
+			}
+		}
+	}
+	return nil, errNoSuchInterface
+}
+
+func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error {
+	if ifi == nil {
+		return nil
+	}
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		return err
+	}
+	for _, ifa := range ifat {
+		switch v := ifa.(type) {
+		case *IPAddr:
+			if a := v.IP.To4(); a != nil {
+				copy(mreq.Interface[:], a)
+				goto done
+			}
+		case *IPNet:
+			if a := v.IP.To4(); a != nil {
+				copy(mreq.Interface[:], a)
+				goto done
+			}
+		}
+	}
+done:
+	if bytesEqual(mreq.Multiaddr[:], IPv4zero.To4()) {
+		return errNoSuchMulticastInterface
+	}
+	return nil
+}
+
+func setReadBuffer(fd *netFD, bytes int) error {
+	if err := fd.incref(false); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes))
+}
+
+func setWriteBuffer(fd *netFD, bytes int) error {
+	if err := fd.incref(false); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
+}
+
+// TODO(dfc) these unused error returns could be removed
+
+func setReadDeadline(fd *netFD, t time.Time) error {
+	fd.rdeadline.setTime(t)
+	return nil
+}
+
+func setWriteDeadline(fd *netFD, t time.Time) error {
+	fd.wdeadline.setTime(t)
+	return nil
+}
+
+func setDeadline(fd *netFD, t time.Time) error {
+	setReadDeadline(fd, t)
+	setWriteDeadline(fd, t)
+	return nil
+}
+
+func setKeepAlive(fd *netFD, keepalive bool) error {
+	if err := fd.incref(false); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive)))
+}
+
+func setNoDelay(fd *netFD, noDelay bool) error {
+	if err := fd.incref(false); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay)))
+}
+
+func setLinger(fd *netFD, sec int) error {
+	var l syscall.Linger
+	if sec >= 0 {
+		l.Onoff = 1
+		l.Linger = int32(sec)
+	} else {
+		l.Onoff = 0
+		l.Linger = 0
+	}
+	if err := fd.incref(false); err != nil {
+		return err
+	}
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l))
+}
diff --git a/src/pkg/net/sockoptip.go b/src/pkg/net/sockoptip.go
deleted file mode 100644
index 1fcad40..0000000
--- a/src/pkg/net/sockoptip.go
+++ /dev/null
@@ -1,219 +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 freebsd linux netbsd openbsd windows
-
-// IP-level socket options
-
-package net
-
-import (
-	"os"
-	"syscall"
-)
-
-func ipv4TOS(fd *netFD) (int, error) {
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS)
-	if err != nil {
-		return 0, os.NewSyscallError("getsockopt", err)
-	}
-	return v, nil
-}
-
-func setIPv4TOS(fd *netFD, v int) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS, v)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv4TTL(fd *netFD) (int, error) {
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL)
-	if err != nil {
-		return 0, os.NewSyscallError("getsockopt", err)
-	}
-	return v, nil
-}
-
-func setIPv4TTL(fd *netFD, v int) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL, v)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
-	mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
-	if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
-		return err
-	}
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
-}
-
-func leaveIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
-	mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
-	if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
-		return err
-	}
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
-}
-
-func ipv6HopLimit(fd *netFD) (int, error) {
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS)
-	if err != nil {
-		return 0, os.NewSyscallError("getsockopt", err)
-	}
-	return v, nil
-}
-
-func setIPv6HopLimit(fd *netFD, v int) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, v)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv6MulticastInterface(fd *netFD) (*Interface, error) {
-	if err := fd.incref(false); err != nil {
-		return nil, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF)
-	if err != nil {
-		return nil, os.NewSyscallError("getsockopt", err)
-	}
-	if v == 0 {
-		return nil, nil
-	}
-	ifi, err := InterfaceByIndex(v)
-	if err != nil {
-		return nil, err
-	}
-	return ifi, nil
-}
-
-func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
-	var v int
-	if ifi != nil {
-		v = ifi.Index
-	}
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv6MulticastHopLimit(fd *netFD) (int, error) {
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS)
-	if err != nil {
-		return 0, os.NewSyscallError("getsockopt", err)
-	}
-	return v, nil
-}
-
-func setIPv6MulticastHopLimit(fd *netFD, v int) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS, v)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv6MulticastLoopback(fd *netFD) (bool, error) {
-	if err := fd.incref(false); err != nil {
-		return false, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv6MulticastLoopback(fd *netFD, v bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v))
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
-	mreq := &syscall.IPv6Mreq{}
-	copy(mreq.Multiaddr[:], ip)
-	if ifi != nil {
-		mreq.Interface = uint32(ifi.Index)
-	}
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq))
-}
-
-func leaveIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
-	mreq := &syscall.IPv6Mreq{}
-	copy(mreq.Multiaddr[:], ip)
-	if ifi != nil {
-		mreq.Interface = uint32(ifi.Index)
-	}
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_LEAVE_GROUP, mreq))
-}
diff --git a/src/pkg/net/sockoptip_bsd.go b/src/pkg/net/sockoptip_bsd.go
index 19e2b14..263f855 100644
--- a/src/pkg/net/sockoptip_bsd.go
+++ b/src/pkg/net/sockoptip_bsd.go
@@ -4,8 +4,6 @@
 
 // +build darwin freebsd netbsd openbsd
 
-// IP-level socket options for BSD variants
-
 package net
 
 import (
@@ -13,48 +11,30 @@ import (
 	"syscall"
 )
 
-func ipv4MulticastTTL(fd *netFD) (int, error) {
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+	ip, err := interfaceToIPv4Addr(ifi)
 	if err != nil {
-		return 0, os.NewSyscallError("getsockopt", err)
+		return os.NewSyscallError("setsockopt", err)
 	}
-	return int(v), nil
-}
-
-func setIPv4MulticastTTL(fd *netFD, v int) error {
+	var a [4]byte
+	copy(a[:], ip.To4())
 	if err := fd.incref(false); err != nil {
 		return err
 	}
 	defer fd.decref()
-	err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, byte(v))
+	err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, a)
 	if err != nil {
 		return os.NewSyscallError("setsockopt", err)
 	}
 	return nil
 }
 
-func ipv6TrafficClass(fd *netFD) (int, error) {
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
-	if err != nil {
-		return 0, os.NewSyscallError("getsockopt", err)
-	}
-	return v, nil
-}
-
-func setIPv6TrafficClass(fd *netFD, v int) error {
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
 	if err := fd.incref(false); err != nil {
 		return err
 	}
 	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
+	err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
 	if err != nil {
 		return os.NewSyscallError("setsockopt", err)
 	}
diff --git a/src/pkg/net/sockoptip_darwin.go b/src/pkg/net/sockoptip_darwin.go
deleted file mode 100644
index 52b237c..0000000
--- a/src/pkg/net/sockoptip_darwin.go
+++ /dev/null
@@ -1,90 +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.
-
-// IP-level socket options for Darwin
-
-package net
-
-import (
-	"os"
-	"syscall"
-)
-
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
-	if err := fd.incref(false); err != nil {
-		return nil, err
-	}
-	defer fd.decref()
-	a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
-	if err != nil {
-		return nil, os.NewSyscallError("getsockopt", err)
-	}
-	return ipv4AddrToInterface(IPv4(a[0], a[1], a[2], a[3]))
-}
-
-func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
-	ip, err := interfaceToIPv4Addr(ifi)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	var x [4]byte
-	copy(x[:], ip.To4())
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
-	if err := fd.incref(false); err != nil {
-		return false, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv4MulticastLoopback(fd *netFD, v bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
-	if err := fd.incref(false); err != nil {
-		return false, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
diff --git a/src/pkg/net/sockoptip_freebsd.go b/src/pkg/net/sockoptip_freebsd.go
deleted file mode 100644
index 4a3bc2e..0000000
--- a/src/pkg/net/sockoptip_freebsd.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.
-
-// IP-level socket options for FreeBSD
-
-package net
-
-import (
-	"os"
-	"syscall"
-)
-
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
-	if err := fd.incref(false); err != nil {
-		return nil, err
-	}
-	defer fd.decref()
-	mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
-	if err != nil {
-		return nil, os.NewSyscallError("getsockopt", err)
-	}
-	if int(mreq.Ifindex) == 0 {
-		return nil, nil
-	}
-	return InterfaceByIndex(int(mreq.Ifindex))
-}
-
-func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
-	var v int32
-	if ifi != nil {
-		v = int32(ifi.Index)
-	}
-	mreq := &syscall.IPMreqn{Ifindex: v}
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
-	if err := fd.incref(false); err != nil {
-		return false, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv4MulticastLoopback(fd *netFD, v bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
-	if err := fd.incref(false); err != nil {
-		return false, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
diff --git a/src/pkg/net/sockoptip_linux.go b/src/pkg/net/sockoptip_linux.go
index 169718f..225fb0c 100644
--- a/src/pkg/net/sockoptip_linux.go
+++ b/src/pkg/net/sockoptip_linux.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.
 
-// IP-level socket options for Linux
-
 package net
 
 import (
@@ -11,21 +9,6 @@ import (
 	"syscall"
 )
 
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
-	if err := fd.incref(false); err != nil {
-		return nil, err
-	}
-	defer fd.decref()
-	mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
-	if err != nil {
-		return nil, os.NewSyscallError("getsockopt", err)
-	}
-	if int(mreq.Ifindex) == 0 {
-		return nil, nil
-	}
-	return InterfaceByIndex(int(mreq.Ifindex))
-}
-
 func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
 	var v int32
 	if ifi != nil {
@@ -43,42 +26,6 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
 	return nil
 }
 
-func ipv4MulticastTTL(fd *netFD) (int, error) {
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
-	if err != nil {
-		return -1, os.NewSyscallError("getsockopt", err)
-	}
-	return v, nil
-}
-
-func setIPv4MulticastTTL(fd *netFD, v int) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
-	if err := fd.incref(false); err != nil {
-		return false, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
 func setIPv4MulticastLoopback(fd *netFD, v bool) error {
 	if err := fd.incref(false); err != nil {
 		return err
@@ -90,51 +37,3 @@ func setIPv4MulticastLoopback(fd *netFD, v bool) error {
 	}
 	return nil
 }
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
-	if err := fd.incref(false); err != nil {
-		return false, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO, boolint(v))
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv6TrafficClass(fd *netFD) (int, error) {
-	if err := fd.incref(false); err != nil {
-		return 0, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
-	if err != nil {
-		return 0, os.NewSyscallError("getsockopt", err)
-	}
-	return v, nil
-}
-
-func setIPv6TrafficClass(fd *netFD, v int) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
diff --git a/src/pkg/net/sockoptip_netbsd.go b/src/pkg/net/sockoptip_netbsd.go
deleted file mode 100644
index 446d92a..0000000
--- a/src/pkg/net/sockoptip_netbsd.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2012 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// IP-level socket options for NetBSD
-
-package net
-
-import "syscall"
-
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
-	// TODO: Implement this
-	return nil, syscall.EAFNOSUPPORT
-}
-
-func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
-	// TODO: Implement this
-	return syscall.EAFNOSUPPORT
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
-	// TODO: Implement this
-	return false, syscall.EAFNOSUPPORT
-}
-
-func setIPv4MulticastLoopback(fd *netFD, v bool) error {
-	// TODO: Implement this
-	return syscall.EAFNOSUPPORT
-}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
-	// TODO: Implement this
-	return false, syscall.EAFNOSUPPORT
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
-	// TODO: Implement this
-	return syscall.EAFNOSUPPORT
-}
diff --git a/src/pkg/net/sockoptip_openbsd.go b/src/pkg/net/sockoptip_openbsd.go
deleted file mode 100644
index f3e42f1..0000000
--- a/src/pkg/net/sockoptip_openbsd.go
+++ /dev/null
@@ -1,90 +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.
-
-// IP-level socket options for OpenBSD
-
-package net
-
-import (
-	"os"
-	"syscall"
-)
-
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
-	if err := fd.incref(false); err != nil {
-		return nil, err
-	}
-	defer fd.decref()
-	a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
-	if err != nil {
-		return nil, os.NewSyscallError("getsockopt", err)
-	}
-	return ipv4AddrToInterface(IPv4(a[0], a[1], a[2], a[3]))
-}
-
-func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
-	ip, err := interfaceToIPv4Addr(ifi)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	var x [4]byte
-	copy(x[:], ip.To4())
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
-	if err := fd.incref(false); err != nil {
-		return false, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv4MulticastLoopback(fd *netFD, v bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
-	if err := fd.incref(false); err != nil {
-		return false, err
-	}
-	defer fd.decref()
-	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
-	if err != nil {
-		return false, os.NewSyscallError("getsockopt", err)
-	}
-	return v == 1, nil
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-}
diff --git a/src/pkg/net/sockoptip_posix.go b/src/pkg/net/sockoptip_posix.go
new file mode 100644
index 0000000..e4c56a0
--- /dev/null
+++ b/src/pkg/net/sockoptip_posix.go
@@ -0,0 +1,73 @@
+// 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 freebsd linux netbsd openbsd windows
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
+	mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+	if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
+		return err
+	}
+	if err := fd.incref(false); err != nil {
+		return err
+	}
+	defer fd.decref()
+	err := syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
+	var v int
+	if ifi != nil {
+		v = ifi.Index
+	}
+	if err := fd.incref(false); err != nil {
+		return err
+	}
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func setIPv6MulticastLoopback(fd *netFD, v bool) error {
+	if err := fd.incref(false); err != nil {
+		return err
+	}
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
+	mreq := &syscall.IPv6Mreq{}
+	copy(mreq.Multiaddr[:], ip)
+	if ifi != nil {
+		mreq.Interface = uint32(ifi.Index)
+	}
+	if err := fd.incref(false); err != nil {
+		return err
+	}
+	defer fd.decref()
+	err := syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
diff --git a/src/pkg/net/sockoptip_windows.go b/src/pkg/net/sockoptip_windows.go
index b9db333..3e24844 100644
--- a/src/pkg/net/sockoptip_windows.go
+++ b/src/pkg/net/sockoptip_windows.go
@@ -2,90 +2,41 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// IP-level socket options for Windows
-
 package net
 
 import (
 	"os"
 	"syscall"
+	"unsafe"
 )
 
-func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
-	// TODO: Implement this
-	return nil, syscall.EWINDOWS
-}
-
 func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
 	ip, err := interfaceToIPv4Addr(ifi)
 	if err != nil {
 		return os.NewSyscallError("setsockopt", err)
 	}
-	var x [4]byte
-	copy(x[:], ip.To4())
+	var a [4]byte
+	copy(a[:], ip.To4())
 	if err := fd.incref(false); err != nil {
 		return err
 	}
 	defer fd.decref()
-	err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
+	err = syscall.Setsockopt(fd.sysfd, int32(syscall.IPPROTO_IP), int32(syscall.IP_MULTICAST_IF), (*byte)(unsafe.Pointer(&a[0])), 4)
 	if err != nil {
 		return os.NewSyscallError("setsockopt", err)
 	}
 	return nil
 }
 
-func ipv4MulticastTTL(fd *netFD) (int, error) {
-	// TODO: Implement this
-	return -1, syscall.EWINDOWS
-}
-
-func setIPv4MulticastTTL(fd *netFD, v int) error {
-	if err := fd.incref(false); err != nil {
-		return err
-	}
-	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v)
-	if err != nil {
-		return os.NewSyscallError("setsockopt", err)
-	}
-	return nil
-
-}
-
-func ipv4MulticastLoopback(fd *netFD) (bool, error) {
-	// TODO: Implement this
-	return false, syscall.EWINDOWS
-}
-
 func setIPv4MulticastLoopback(fd *netFD, v bool) error {
 	if err := fd.incref(false); err != nil {
 		return err
 	}
 	defer fd.decref()
-	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
+	vv := int32(boolint(v))
+	err := syscall.Setsockopt(fd.sysfd, int32(syscall.IPPROTO_IP), int32(syscall.IP_MULTICAST_LOOP), (*byte)(unsafe.Pointer(&vv)), 4)
 	if err != nil {
 		return os.NewSyscallError("setsockopt", err)
 	}
 	return nil
-
-}
-
-func ipv4ReceiveInterface(fd *netFD) (bool, error) {
-	// TODO: Implement this
-	return false, syscall.EWINDOWS
-}
-
-func setIPv4ReceiveInterface(fd *netFD, v bool) error {
-	// TODO: Implement this
-	return syscall.EWINDOWS
-}
-
-func ipv6TrafficClass(fd *netFD) (int, error) {
-	// TODO: Implement this
-	return 0, syscall.EWINDOWS
-}
-
-func setIPv6TrafficClass(fd *netFD, v int) error {
-	// TODO: Implement this
-	return syscall.EWINDOWS
 }
diff --git a/src/pkg/net/sys_cloexec.go b/src/pkg/net/sys_cloexec.go
new file mode 100644
index 0000000..17e8749
--- /dev/null
+++ b/src/pkg/net/sys_cloexec.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.
+
+// This file implements sysSocket and accept for platforms that do not
+// provide a fast path for setting SetNonblock and CloseOnExec.
+
+// +build darwin freebsd netbsd openbsd
+
+package net
+
+import "syscall"
+
+// Wrapper around the socket system call that marks the returned file
+// descriptor as nonblocking and close-on-exec.
+func sysSocket(f, t, p int) (int, error) {
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	syscall.ForkLock.RLock()
+	s, err := syscall.Socket(f, t, p)
+	if err == nil {
+		syscall.CloseOnExec(s)
+	}
+	syscall.ForkLock.RUnlock()
+	if err != nil {
+		return -1, err
+	}
+	if err = syscall.SetNonblock(s, true); err != nil {
+		syscall.Close(s)
+		return -1, err
+	}
+	return s, nil
+}
+
+// Wrapper around the accept system call that marks the returned file
+// descriptor as nonblocking and close-on-exec.
+func accept(fd int) (int, syscall.Sockaddr, error) {
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	// It is probably okay to hold the lock across syscall.Accept
+	// because we have put fd.sysfd into non-blocking mode.
+	// However, a call to the File method will put it back into
+	// blocking mode. We can't take that risk, so no use of ForkLock here.
+	nfd, sa, err := syscall.Accept(fd)
+	if err == nil {
+		syscall.CloseOnExec(nfd)
+	}
+	if err != nil {
+		return -1, nil, err
+	}
+	if err = syscall.SetNonblock(nfd, true); err != nil {
+		syscall.Close(nfd)
+		return -1, nil, err
+	}
+	return nfd, sa, nil
+}
diff --git a/src/pkg/net/tcp_test.go b/src/pkg/net/tcp_test.go
new file mode 100644
index 0000000..6c4485a
--- /dev/null
+++ b/src/pkg/net/tcp_test.go
@@ -0,0 +1,206 @@
+// 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 net
+
+import (
+	"reflect"
+	"runtime"
+	"testing"
+	"time"
+)
+
+func BenchmarkTCP4OneShot(b *testing.B) {
+	benchmarkTCP(b, false, false, "127.0.0.1:0")
+}
+
+func BenchmarkTCP4OneShotTimeout(b *testing.B) {
+	benchmarkTCP(b, false, true, "127.0.0.1:0")
+}
+
+func BenchmarkTCP4Persistent(b *testing.B) {
+	benchmarkTCP(b, true, false, "127.0.0.1:0")
+}
+
+func BenchmarkTCP4PersistentTimeout(b *testing.B) {
+	benchmarkTCP(b, true, true, "127.0.0.1:0")
+}
+
+func BenchmarkTCP6OneShot(b *testing.B) {
+	if !supportsIPv6 {
+		b.Skip("ipv6 is not supported")
+	}
+	benchmarkTCP(b, false, false, "[::1]:0")
+}
+
+func BenchmarkTCP6OneShotTimeout(b *testing.B) {
+	if !supportsIPv6 {
+		b.Skip("ipv6 is not supported")
+	}
+	benchmarkTCP(b, false, true, "[::1]:0")
+}
+
+func BenchmarkTCP6Persistent(b *testing.B) {
+	if !supportsIPv6 {
+		b.Skip("ipv6 is not supported")
+	}
+	benchmarkTCP(b, true, false, "[::1]:0")
+}
+
+func BenchmarkTCP6PersistentTimeout(b *testing.B) {
+	if !supportsIPv6 {
+		b.Skip("ipv6 is not supported")
+	}
+	benchmarkTCP(b, true, true, "[::1]:0")
+}
+
+func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
+	const msgLen = 512
+	conns := b.N
+	numConcurrent := runtime.GOMAXPROCS(-1) * 16
+	msgs := 1
+	if persistent {
+		conns = numConcurrent
+		msgs = b.N / conns
+		if msgs == 0 {
+			msgs = 1
+		}
+		if conns > b.N {
+			conns = b.N
+		}
+	}
+	sendMsg := func(c Conn, buf []byte) bool {
+		n, err := c.Write(buf)
+		if n != len(buf) || err != nil {
+			b.Logf("Write failed: %v", err)
+			return false
+		}
+		return true
+	}
+	recvMsg := func(c Conn, buf []byte) bool {
+		for read := 0; read != len(buf); {
+			n, err := c.Read(buf)
+			read += n
+			if err != nil {
+				b.Logf("Read failed: %v", err)
+				return false
+			}
+		}
+		return true
+	}
+	ln, err := Listen("tcp", laddr)
+	if err != nil {
+		b.Fatalf("Listen failed: %v", err)
+	}
+	defer ln.Close()
+	// Acceptor.
+	go func() {
+		for {
+			c, err := ln.Accept()
+			if err != nil {
+				break
+			}
+			// Server connection.
+			go func(c Conn) {
+				defer c.Close()
+				if timeout {
+					c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
+				}
+				var buf [msgLen]byte
+				for m := 0; m < msgs; m++ {
+					if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
+						break
+					}
+				}
+			}(c)
+		}
+	}()
+	sem := make(chan bool, numConcurrent)
+	for i := 0; i < conns; i++ {
+		sem <- true
+		// Client connection.
+		go func() {
+			defer func() {
+				<-sem
+			}()
+			c, err := Dial("tcp", ln.Addr().String())
+			if err != nil {
+				b.Logf("Dial failed: %v", err)
+				return
+			}
+			defer c.Close()
+			if timeout {
+				c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
+			}
+			var buf [msgLen]byte
+			for m := 0; m < msgs; m++ {
+				if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
+					break
+				}
+			}
+		}()
+	}
+	for i := 0; i < cap(sem); i++ {
+		sem <- true
+	}
+}
+
+var resolveTCPAddrTests = []struct {
+	net     string
+	litAddr string
+	addr    *TCPAddr
+	err     error
+}{
+	{"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
+	{"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
+
+	{"tcp", "[::1]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1}, nil},
+	{"tcp6", "[::1]:65534", &TCPAddr{IP: ParseIP("::1"), Port: 65534}, nil},
+
+	{"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
+	{"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior
+
+	{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
+}
+
+func TestResolveTCPAddr(t *testing.T) {
+	for _, tt := range resolveTCPAddrTests {
+		addr, err := ResolveTCPAddr(tt.net, tt.litAddr)
+		if err != tt.err {
+			t.Fatalf("ResolveTCPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
+		}
+		if !reflect.DeepEqual(addr, tt.addr) {
+			t.Fatalf("got %#v; expected %#v", addr, tt.addr)
+		}
+	}
+}
+
+var tcpListenerNameTests = []struct {
+	net   string
+	laddr *TCPAddr
+}{
+	{"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}},
+	{"tcp4", &TCPAddr{}},
+	{"tcp4", nil},
+}
+
+func TestTCPListenerName(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	for _, tt := range tcpListenerNameTests {
+		ln, err := ListenTCP(tt.net, tt.laddr)
+		if err != nil {
+			t.Errorf("ListenTCP failed: %v", err)
+			return
+		}
+		defer ln.Close()
+		la := ln.Addr()
+		if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
+			t.Errorf("got %v; expected a proper address with non-zero port number", la)
+			return
+		}
+	}
+}
diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go
index 47fbf29..d5158b2 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/pkg/net/tcpsock.go
@@ -10,6 +10,7 @@ package net
 type TCPAddr struct {
 	IP   IP
 	Port int
+	Zone string // IPv6 scoped addressing zone
 }
 
 // Network returns the address's network name, "tcp".
@@ -28,9 +29,16 @@ func (a *TCPAddr) String() string {
 // "tcp4" or "tcp6".  A literal IPv6 host address must be
 // enclosed in square brackets, as in "[::]:80".
 func ResolveTCPAddr(net, addr string) (*TCPAddr, error) {
-	ip, port, err := hostPortToIP(net, addr)
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+	case "": // a hint wildcard for Go 1.0 undocumented behavior
+		net = "tcp"
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	a, err := resolveInternetAddr(net, addr, noDeadline)
 	if err != nil {
 		return nil, err
 	}
-	return &TCPAddr{ip, port}, nil
+	return a.(*TCPAddr), nil
 }
diff --git a/src/pkg/net/tcpsock_plan9.go b/src/pkg/net/tcpsock_plan9.go
index 35f5696..ed36646 100644
--- a/src/pkg/net/tcpsock_plan9.go
+++ b/src/pkg/net/tcpsock_plan9.go
@@ -2,34 +2,30 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// TCP for Plan 9
+// TCP sockets for Plan 9
 
 package net
 
 import (
+	"io"
+	"os"
 	"syscall"
 	"time"
 )
 
-// TCPConn is an implementation of the Conn interface
-// for TCP network connections.
+// TCPConn is an implementation of the Conn interface for TCP network
+// connections.
 type TCPConn struct {
-	plan9Conn
+	conn
 }
 
-// SetDeadline implements the Conn SetDeadline method.
-func (c *TCPConn) SetDeadline(t time.Time) error {
-	return syscall.EPLAN9
+func newTCPConn(fd *netFD) *TCPConn {
+	return &TCPConn{conn{fd}}
 }
 
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *TCPConn) SetReadDeadline(t time.Time) error {
-	return syscall.EPLAN9
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *TCPConn) SetWriteDeadline(t time.Time) error {
-	return syscall.EPLAN9
+// ReadFrom implements the io.ReaderFrom ReadFrom method.
+func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
+	return genericReadFrom(c, r)
 }
 
 // CloseRead shuts down the reading side of the TCP connection.
@@ -38,7 +34,7 @@ func (c *TCPConn) CloseRead() error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
-	return syscall.EPLAN9
+	return c.fd.CloseRead()
 }
 
 // CloseWrite shuts down the writing side of the TCP connection.
@@ -47,51 +43,142 @@ func (c *TCPConn) CloseWrite() error {
 	if !c.ok() {
 		return syscall.EINVAL
 	}
+	return c.fd.CloseWrite()
+}
+
+// SetLinger sets the behavior of Close() on a connection which still
+// has data waiting to be sent or to be acknowledged.
+//
+// If sec < 0 (the default), Close returns immediately and the
+// operating system finishes sending the data in the background.
+//
+// If sec == 0, Close returns immediately and the operating system
+// discards any unsent or unacknowledged data.
+//
+// If sec > 0, Close blocks for at most sec seconds waiting for data
+// to be sent and acknowledged.
+func (c *TCPConn) SetLinger(sec int) error {
+	return syscall.EPLAN9
+}
+
+// SetKeepAlive sets whether the operating system should send
+// keepalive messages on the connection.
+func (c *TCPConn) SetKeepAlive(keepalive bool) error {
+	return syscall.EPLAN9
+}
+
+// SetNoDelay controls whether the operating system should delay
+// packet transmission in hopes of sending fewer packets (Nagle's
+// algorithm).  The default is true (no delay), meaning that data is
+// sent as soon as possible after a Write.
+func (c *TCPConn) SetNoDelay(noDelay bool) error {
 	return syscall.EPLAN9
 }
 
 // DialTCP connects to the remote address raddr on the network net,
-// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is used
-// as the local address for the connection.
-func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) {
+// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is
+// used as the local address for the connection.
+func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
+	return dialTCP(net, laddr, raddr, noDeadline)
+}
+
+func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
+	if !deadline.IsZero() {
+		panic("net.dialTCP: deadline not implemented on Plan 9")
+	}
 	switch net {
 	case "tcp", "tcp4", "tcp6":
 	default:
-		return nil, UnknownNetworkError(net)
+		return nil, &OpError{"dial", net, raddr, UnknownNetworkError(net)}
 	}
 	if raddr == nil {
 		return nil, &OpError{"dial", net, nil, errMissingAddress}
 	}
-	c1, err := dialPlan9(net, laddr, raddr)
+	fd, err := dialPlan9(net, laddr, raddr)
 	if err != nil {
-		return
+		return nil, err
 	}
-	return &TCPConn{*c1}, nil
+	return newTCPConn(fd), nil
 }
 
-// TCPListener is a TCP network listener.
-// Clients should typically use variables of type Listener
-// instead of assuming TCP.
+// TCPListener is a TCP network listener.  Clients should typically
+// use variables of type Listener instead of assuming TCP.
 type TCPListener struct {
-	plan9Listener
+	fd *netFD
+}
+
+// AcceptTCP accepts the next incoming call and returns the new
+// connection and the remote address.
+func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
+	if l == nil || l.fd == nil || l.fd.ctl == nil {
+		return nil, syscall.EINVAL
+	}
+	fd, err := l.fd.acceptPlan9()
+	if err != nil {
+		return nil, err
+	}
+	return newTCPConn(fd), nil
+}
+
+// Accept implements the Accept method in the Listener interface; it
+// waits for the next call and returns a generic Conn.
+func (l *TCPListener) Accept() (Conn, error) {
+	if l == nil || l.fd == nil || l.fd.ctl == nil {
+		return nil, syscall.EINVAL
+	}
+	c, err := l.AcceptTCP()
+	if err != nil {
+		return nil, err
+	}
+	return c, nil
 }
 
-// ListenTCP announces on the TCP address laddr and returns a TCP listener.
-// Net must be "tcp", "tcp4", or "tcp6".
-// If laddr has a port of 0, it means to listen on some available port.
-// The caller can use l.Addr() to retrieve the chosen address.
-func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) {
+// Close stops listening on the TCP address.
+// Already Accepted connections are not closed.
+func (l *TCPListener) Close() error {
+	if l == nil || l.fd == nil || l.fd.ctl == nil {
+		return syscall.EINVAL
+	}
+	if _, err := l.fd.ctl.WriteString("hangup"); err != nil {
+		l.fd.ctl.Close()
+		return &OpError{"close", l.fd.ctl.Name(), l.fd.laddr, err}
+	}
+	return l.fd.ctl.Close()
+}
+
+// Addr returns the listener's network address, a *TCPAddr.
+func (l *TCPListener) Addr() Addr { return l.fd.laddr }
+
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *TCPListener) SetDeadline(t time.Time) error {
+	if l == nil || l.fd == nil || l.fd.ctl == nil {
+		return syscall.EINVAL
+	}
+	return setDeadline(l.fd, t)
+}
+
+// File returns a copy of the underlying os.File, set to blocking
+// mode.  It is the caller's responsibility to close f when finished.
+// Closing l does not affect f, and closing f does not affect l.
+func (l *TCPListener) File() (f *os.File, err error) { return l.dup() }
+
+// ListenTCP announces on the TCP address laddr and returns a TCP
+// listener.  Net must be "tcp", "tcp4", or "tcp6".  If laddr has a
+// port of 0, it means to listen on some available port.  The caller
+// can use l.Addr() to retrieve the chosen address.
+func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
 	switch net {
 	case "tcp", "tcp4", "tcp6":
 	default:
-		return nil, UnknownNetworkError(net)
+		return nil, &OpError{"listen", net, laddr, UnknownNetworkError(net)}
 	}
 	if laddr == nil {
-		return nil, &OpError{"listen", net, nil, errMissingAddress}
+		laddr = &TCPAddr{}
 	}
-	l1, err := listenPlan9(net, laddr)
+	fd, err := listenPlan9(net, laddr)
 	if err != nil {
-		return
+		return nil, err
 	}
-	return &TCPListener{*l1}, nil
+	return &TCPListener{fd}, nil
 }
diff --git a/src/pkg/net/tcpsock_posix.go b/src/pkg/net/tcpsock_posix.go
index e6b1937..bd5a2a2 100644
--- a/src/pkg/net/tcpsock_posix.go
+++ b/src/pkg/net/tcpsock_posix.go
@@ -23,14 +23,9 @@ import (
 func sockaddrToTCP(sa syscall.Sockaddr) Addr {
 	switch sa := sa.(type) {
 	case *syscall.SockaddrInet4:
-		return &TCPAddr{sa.Addr[0:], sa.Port}
+		return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port}
 	case *syscall.SockaddrInet6:
-		return &TCPAddr{sa.Addr[0:], sa.Port}
-	default:
-		if sa != nil {
-			// Diagnose when we will turn a non-nil sockaddr into a nil.
-			panic("unexpected type in sockaddrToTCP")
-		}
+		return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
 	}
 	return nil
 }
@@ -53,7 +48,7 @@ func (a *TCPAddr) isWildcard() bool {
 }
 
 func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
-	return ipToSockaddr(family, a.IP, a.Port)
+	return ipToSockaddr(family, a.IP, a.Port, a.Zone)
 }
 
 func (a *TCPAddr) toAddr() sockaddr {
@@ -66,27 +61,15 @@ func (a *TCPAddr) toAddr() sockaddr {
 // TCPConn is an implementation of the Conn interface
 // for TCP network connections.
 type TCPConn struct {
-	fd *netFD
+	conn
 }
 
 func newTCPConn(fd *netFD) *TCPConn {
-	c := &TCPConn{fd}
+	c := &TCPConn{conn{fd}}
 	c.SetNoDelay(true)
 	return c
 }
 
-func (c *TCPConn) ok() bool { return c != nil && c.fd != nil }
-
-// Implementation of the Conn interface - see Conn for documentation.
-
-// Read implements the Conn Read method.
-func (c *TCPConn) Read(b []byte) (n int, err error) {
-	if !c.ok() {
-		return 0, syscall.EINVAL
-	}
-	return c.fd.Read(b)
-}
-
 // ReadFrom implements the io.ReaderFrom ReadFrom method.
 func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
 	if n, err, handled := sendFile(c.fd, r); handled {
@@ -95,22 +78,6 @@ func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
 	return genericReadFrom(c, r)
 }
 
-// Write implements the Conn Write method.
-func (c *TCPConn) Write(b []byte) (n int, err error) {
-	if !c.ok() {
-		return 0, syscall.EINVAL
-	}
-	return c.fd.Write(b)
-}
-
-// Close closes the TCP connection.
-func (c *TCPConn) Close() error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return c.fd.Close()
-}
-
 // CloseRead shuts down the reading side of the TCP connection.
 // Most callers should just use Close.
 func (c *TCPConn) CloseRead() error {
@@ -129,64 +96,6 @@ func (c *TCPConn) CloseWrite() error {
 	return c.fd.CloseWrite()
 }
 
-// LocalAddr returns the local network address, a *TCPAddr.
-func (c *TCPConn) LocalAddr() Addr {
-	if !c.ok() {
-		return nil
-	}
-	return c.fd.laddr
-}
-
-// RemoteAddr returns the remote network address, a *TCPAddr.
-func (c *TCPConn) RemoteAddr() Addr {
-	if !c.ok() {
-		return nil
-	}
-	return c.fd.raddr
-}
-
-// SetDeadline implements the Conn SetDeadline method.
-func (c *TCPConn) SetDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setDeadline(c.fd, t)
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *TCPConn) SetReadDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setReadDeadline(c.fd, t)
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *TCPConn) SetWriteDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setWriteDeadline(c.fd, t)
-}
-
-// SetReadBuffer sets the size of the operating system's
-// receive buffer associated with the connection.
-func (c *TCPConn) SetReadBuffer(bytes int) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setReadBuffer(c.fd, bytes)
-}
-
-// SetWriteBuffer sets the size of the operating system's
-// transmit buffer associated with the connection.
-func (c *TCPConn) SetWriteBuffer(bytes int) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setWriteBuffer(c.fd, bytes)
-}
-
 // SetLinger sets the behavior of Close() on a connection
 // which still has data waiting to be sent or to be acknowledged.
 //
@@ -225,20 +134,23 @@ func (c *TCPConn) SetNoDelay(noDelay bool) error {
 	return setNoDelay(c.fd, noDelay)
 }
 
-// File returns a copy of the underlying os.File, set to blocking mode.
-// 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 (c *TCPConn) File() (f *os.File, err error) { return c.fd.dup() }
-
 // DialTCP connects to the remote address raddr on the network net,
 // which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is used
 // as the local address for the connection.
 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+	default:
+		return nil, UnknownNetworkError(net)
+	}
 	if raddr == nil {
 		return nil, &OpError{"dial", net, nil, errMissingAddress}
 	}
+	return dialTCP(net, laddr, raddr, noDeadline)
+}
 
-	fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
+func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
+	fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
 
 	// TCP has a rarely used mechanism called a 'simultaneous connection' in
 	// which Dial("tcp", addr1, addr2) run on the machine at addr1 can
@@ -257,9 +169,18 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
 	// use the result.  See also:
 	//	http://golang.org/issue/2690
 	//	http://stackoverflow.com/questions/4949858/
-	for i := 0; i < 2 && err == nil && laddr == nil && selfConnect(fd); i++ {
-		fd.Close()
-		fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
+	//
+	// The opposite can also happen: if we ask the kernel to pick an appropriate
+	// originating local address, sometimes it picks one that is already in use.
+	// So if the error is EADDRNOTAVAIL, we have to try again too, just for
+	// a different reason.
+	//
+	// The kernel socket code is no doubt enjoying watching us squirm.
+	for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(fd, err) || spuriousENOTAVAIL(err)); i++ {
+		if err == nil {
+			fd.Close()
+		}
+		fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
 	}
 
 	if err != nil {
@@ -268,7 +189,12 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
 	return newTCPConn(fd), nil
 }
 
-func selfConnect(fd *netFD) bool {
+func selfConnect(fd *netFD, err error) bool {
+	// If the connect failed, we clearly didn't connect to ourselves.
+	if err != nil {
+		return false
+	}
+
 	// The socket constructor can return an fd with raddr nil under certain
 	// unknown conditions. The errors in the calls there to Getpeername
 	// are discarded, but we can't catch the problem there because those
@@ -285,6 +211,11 @@ func selfConnect(fd *netFD) bool {
 	return l.Port == r.Port && l.IP.Equal(r.IP)
 }
 
+func spuriousENOTAVAIL(err error) bool {
+	e, ok := err.(*OpError)
+	return ok && e.Err == syscall.EADDRNOTAVAIL
+}
+
 // TCPListener is a TCP network listener.
 // Clients should typically use variables of type Listener
 // instead of assuming TCP.
@@ -292,29 +223,10 @@ type TCPListener struct {
 	fd *netFD
 }
 
-// ListenTCP announces on the TCP address laddr and returns a TCP listener.
-// Net must be "tcp", "tcp4", or "tcp6".
-// If laddr has a port of 0, it means to listen on some available port.
-// The caller can use l.Addr() to retrieve the chosen address.
-func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
-	fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP)
-	if err != nil {
-		return nil, err
-	}
-	err = syscall.Listen(fd.sysfd, listenerBacklog)
-	if err != nil {
-		closesocket(fd.sysfd)
-		return nil, &OpError{"listen", net, laddr, err}
-	}
-	l := new(TCPListener)
-	l.fd = fd
-	return l, nil
-}
-
 // AcceptTCP accepts the next incoming call and returns the new connection
 // and the remote address.
 func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) {
-	if l == nil || l.fd == nil || l.fd.sysfd < 0 {
+	if l == nil || l.fd == nil {
 		return nil, syscall.EINVAL
 	}
 	fd, err := l.fd.accept(sockaddrToTCP)
@@ -359,3 +271,28 @@ func (l *TCPListener) SetDeadline(t time.Time) error {
 // It is the caller's responsibility to close f when finished.
 // Closing l does not affect f, and closing f does not affect l.
 func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }
+
+// ListenTCP announces on the TCP address laddr and returns a TCP listener.
+// Net must be "tcp", "tcp4", or "tcp6".
+// If laddr has a port of 0, it means to listen on some available port.
+// The caller can use l.Addr() to retrieve the chosen address.
+func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	if laddr == nil {
+		laddr = &TCPAddr{}
+	}
+	fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP)
+	if err != nil {
+		return nil, err
+	}
+	err = syscall.Listen(fd.sysfd, listenerBacklog)
+	if err != nil {
+		closesocket(fd.sysfd)
+		return nil, &OpError{"listen", net, laddr, err}
+	}
+	return &TCPListener{fd}, nil
+}
diff --git a/src/pkg/net/textproto/reader.go b/src/pkg/net/textproto/reader.go
index 125feb3..b61bea8 100644
--- a/src/pkg/net/textproto/reader.go
+++ b/src/pkg/net/textproto/reader.go
@@ -128,6 +128,17 @@ func (r *Reader) readContinuedLineSlice() ([]byte, error) {
 		return line, nil
 	}
 
+	// Optimistically assume that we have started to buffer the next line
+	// and it starts with an ASCII letter (the next header key), so we can
+	// avoid copying that buffered data around in memory and skipping over
+	// non-existent whitespace.
+	if r.R.Buffered() > 1 {
+		peek, err := r.R.Peek(1)
+		if err == nil && isASCIILetter(peek[0]) {
+			return trim(line), nil
+		}
+	}
+
 	// ReadByte or the next readLineSlice will flush the read buffer;
 	// copy the slice into buf.
 	r.buf = append(r.buf[:0], trim(line)...)
@@ -445,23 +456,25 @@ func (r *Reader) ReadDotLines() ([]string, error) {
 //	}
 //
 func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
-	m := make(MIMEHeader)
+	m := make(MIMEHeader, 4)
 	for {
 		kv, err := r.readContinuedLineSlice()
 		if len(kv) == 0 {
 			return m, err
 		}
 
-		// Key ends at first colon; must not have spaces.
+		// Key ends at first colon; should not have spaces but
+		// they appear in the wild, violating specs, so we
+		// remove them if present.
 		i := bytes.IndexByte(kv, ':')
 		if i < 0 {
 			return m, ProtocolError("malformed MIME header line: " + string(kv))
 		}
-		key := string(kv[0:i])
-		if strings.Index(key, " ") >= 0 {
-			key = strings.TrimRight(key, " ")
+		endKey := i
+		for endKey > 0 && kv[endKey-1] == ' ' {
+			endKey--
 		}
-		key = CanonicalMIMEHeaderKey(key)
+		key := canonicalMIMEHeaderKey(kv[:endKey])
 
 		// Skip initial spaces in value.
 		i++ // skip colon
@@ -484,41 +497,107 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
 // letter and any letter following a hyphen to upper case;
 // the rest are converted to lowercase.  For example, the
 // canonical key for "accept-encoding" is "Accept-Encoding".
+// MIME header keys are assumed to be ASCII only.
 func CanonicalMIMEHeaderKey(s string) string {
 	// Quick check for canonical encoding.
-	needUpper := true
+	upper := true
 	for i := 0; i < len(s); i++ {
 		c := s[i]
-		if needUpper && 'a' <= c && c <= 'z' {
-			goto MustRewrite
+		if upper && 'a' <= c && c <= 'z' {
+			return canonicalMIMEHeaderKey([]byte(s))
 		}
-		if !needUpper && 'A' <= c && c <= 'Z' {
-			goto MustRewrite
+		if !upper && 'A' <= c && c <= 'Z' {
+			return canonicalMIMEHeaderKey([]byte(s))
 		}
-		needUpper = c == '-'
+		upper = c == '-'
 	}
 	return s
+}
+
+const toLower = 'a' - 'A'
 
-MustRewrite:
-	// Canonicalize: first letter upper case
-	// and upper case after each dash.
-	// (Host, User-Agent, If-Modified-Since).
-	// MIME headers are ASCII only, so no Unicode issues.
-	a := []byte(s)
+// canonicalMIMEHeaderKey is like CanonicalMIMEHeaderKey but is
+// allowed to mutate the provided byte slice before returning the
+// string.
+func canonicalMIMEHeaderKey(a []byte) string {
+	// Look for it in commonHeaders , so that we can avoid an
+	// allocation by sharing the strings among all users
+	// of textproto. If we don't find it, a has been canonicalized
+	// so just return string(a).
 	upper := true
-	for i, v := range a {
-		if v == ' ' {
+	lo := 0
+	hi := len(commonHeaders)
+	for i := 0; i < len(a); i++ {
+		// Canonicalize: first letter upper case
+		// and upper case after each dash.
+		// (Host, User-Agent, If-Modified-Since).
+		// MIME headers are ASCII only, so no Unicode issues.
+		if a[i] == ' ' {
 			a[i] = '-'
 			upper = true
 			continue
 		}
-		if upper && 'a' <= v && v <= 'z' {
-			a[i] = v + 'A' - 'a'
+		c := a[i]
+		if upper && 'a' <= c && c <= 'z' {
+			c -= toLower
+		} else if !upper && 'A' <= c && c <= 'Z' {
+			c += toLower
 		}
-		if !upper && 'A' <= v && v <= 'Z' {
-			a[i] = v + 'a' - 'A'
+		a[i] = c
+		upper = c == '-' // for next time
+
+		if lo < hi {
+			for lo < hi && (len(commonHeaders[lo]) <= i || commonHeaders[lo][i] < c) {
+				lo++
+			}
+			for hi > lo && commonHeaders[hi-1][i] > c {
+				hi--
+			}
 		}
-		upper = v == '-'
+	}
+	if lo < hi && len(commonHeaders[lo]) == len(a) {
+		return commonHeaders[lo]
 	}
 	return string(a)
 }
+
+var commonHeaders = []string{
+	"Accept",
+	"Accept-Charset",
+	"Accept-Encoding",
+	"Accept-Language",
+	"Accept-Ranges",
+	"Cache-Control",
+	"Cc",
+	"Connection",
+	"Content-Id",
+	"Content-Language",
+	"Content-Length",
+	"Content-Transfer-Encoding",
+	"Content-Type",
+	"Date",
+	"Dkim-Signature",
+	"Etag",
+	"Expires",
+	"From",
+	"Host",
+	"If-Modified-Since",
+	"If-None-Match",
+	"In-Reply-To",
+	"Last-Modified",
+	"Location",
+	"Message-Id",
+	"Mime-Version",
+	"Pragma",
+	"Received",
+	"Return-Path",
+	"Server",
+	"Set-Cookie",
+	"Subject",
+	"To",
+	"User-Agent",
+	"Via",
+	"X-Forwarded-For",
+	"X-Imforwards",
+	"X-Powered-By",
+}
diff --git a/src/pkg/net/textproto/reader_test.go b/src/pkg/net/textproto/reader_test.go
index 7c5d162..26987f6 100644
--- a/src/pkg/net/textproto/reader_test.go
+++ b/src/pkg/net/textproto/reader_test.go
@@ -6,6 +6,7 @@ package textproto
 
 import (
 	"bufio"
+	"bytes"
 	"io"
 	"reflect"
 	"strings"
@@ -23,6 +24,7 @@ var canonicalHeaderKeyTests = []canonicalHeaderKeyTest{
 	{"uSER-aGENT", "User-Agent"},
 	{"user-agent", "User-Agent"},
 	{"USER-AGENT", "User-Agent"},
+	{"üser-agenT", "üser-Agent"}, // non-ASCII unchanged
 }
 
 func TestCanonicalMIMEHeaderKey(t *testing.T) {
@@ -239,3 +241,95 @@ func TestRFC959Lines(t *testing.T) {
 		}
 	}
 }
+
+func TestCommonHeaders(t *testing.T) {
+	// need to disable the commonHeaders-based optimization
+	// during this check, or we'd not be testing anything
+	oldch := commonHeaders
+	commonHeaders = []string{}
+	defer func() { commonHeaders = oldch }()
+
+	last := ""
+	for _, h := range oldch {
+		if last > h {
+			t.Errorf("%v is out of order", h)
+		}
+		if last == h {
+			t.Errorf("%v is duplicated", h)
+		}
+		if canon := CanonicalMIMEHeaderKey(h); h != canon {
+			t.Errorf("%v is not canonical", h)
+		}
+		last = h
+	}
+}
+
+var clientHeaders = strings.Replace(`Host: golang.org
+Connection: keep-alive
+Cache-Control: max-age=0
+Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
+User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3
+Accept-Encoding: gzip,deflate,sdch
+Accept-Language: en-US,en;q=0.8,fr-CH;q=0.6
+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
+COOKIE: __utma=000000000.0000000000.0000000000.0000000000.0000000000.00; __utmb=000000000.0.00.0000000000; __utmc=000000000; __utmz=000000000.0000000000.00.0.utmcsr=code.google.com|utmccn=(referral)|utmcmd=referral|utmcct=/p/go/issues/detail
+Non-Interned: test
+
+`, "\n", "\r\n", -1)
+
+var serverHeaders = strings.Replace(`Content-Type: text/html; charset=utf-8
+Content-Encoding: gzip
+Date: Thu, 27 Sep 2012 09:03:33 GMT
+Server: Google Frontend
+Cache-Control: private
+Content-Length: 2298
+VIA: 1.1 proxy.example.com:80 (XXX/n.n.n-nnn)
+Connection: Close
+Non-Interned: test
+
+`, "\n", "\r\n", -1)
+
+func BenchmarkReadMIMEHeader(b *testing.B) {
+	var buf bytes.Buffer
+	br := bufio.NewReader(&buf)
+	r := NewReader(br)
+	for i := 0; i < b.N; i++ {
+		var want int
+		var find string
+		if (i & 1) == 1 {
+			buf.WriteString(clientHeaders)
+			want = 10
+			find = "Cookie"
+		} else {
+			buf.WriteString(serverHeaders)
+			want = 9
+			find = "Via"
+		}
+		h, err := r.ReadMIMEHeader()
+		if err != nil {
+			b.Fatal(err)
+		}
+		if len(h) != want {
+			b.Fatalf("wrong number of headers: got %d, want %d", len(h), want)
+		}
+		if _, ok := h[find]; !ok {
+			b.Fatalf("did not find key %s", find)
+		}
+	}
+}
+
+func BenchmarkUncommon(b *testing.B) {
+	var buf bytes.Buffer
+	br := bufio.NewReader(&buf)
+	r := NewReader(br)
+	for i := 0; i < b.N; i++ {
+		buf.WriteString("uncommon-header-for-benchmark: foo\r\n\r\n")
+		h, err := r.ReadMIMEHeader()
+		if err != nil {
+			b.Fatal(err)
+		}
+		if _, ok := h["Uncommon-Header-For-Benchmark"]; !ok {
+			b.Fatal("Missing result header.")
+		}
+	}
+}
diff --git a/src/pkg/net/textproto/textproto.go b/src/pkg/net/textproto/textproto.go
index ad5840c..eb6ced1 100644
--- a/src/pkg/net/textproto/textproto.go
+++ b/src/pkg/net/textproto/textproto.go
@@ -121,3 +121,34 @@ func (c *Conn) Cmd(format string, args ...interface{}) (id uint, err error) {
 	}
 	return id, nil
 }
+
+// TrimString returns s without leading and trailing ASCII space.
+func TrimString(s string) string {
+	for len(s) > 0 && isASCIISpace(s[0]) {
+		s = s[1:]
+	}
+	for len(s) > 0 && isASCIISpace(s[len(s)-1]) {
+		s = s[:len(s)-1]
+	}
+	return s
+}
+
+// TrimBytes returns b without leading and trailing ASCII space.
+func TrimBytes(b []byte) []byte {
+	for len(b) > 0 && isASCIISpace(b[0]) {
+		b = b[1:]
+	}
+	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'
+}
+
+func isASCIILetter(b byte) bool {
+	b |= 0x20 // make lower case
+	return 'a' <= b && b <= 'z'
+}
diff --git a/src/pkg/net/timeout_test.go b/src/pkg/net/timeout_test.go
index 672fb72..0260efc 100644
--- a/src/pkg/net/timeout_test.go
+++ b/src/pkg/net/timeout_test.go
@@ -6,11 +6,187 @@ package net
 
 import (
 	"fmt"
+	"io"
+	"io/ioutil"
 	"runtime"
 	"testing"
 	"time"
 )
 
+func isTimeout(err error) bool {
+	e, ok := err.(Error)
+	return ok && e.Timeout()
+}
+
+type copyRes struct {
+	n   int64
+	err error
+	d   time.Duration
+}
+
+func TestAcceptTimeout(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t).(*TCPListener)
+	defer ln.Close()
+	ln.SetDeadline(time.Now().Add(-1 * time.Second))
+	if _, err := ln.Accept(); !isTimeout(err) {
+		t.Fatalf("Accept: expected err %v, got %v", errTimeout, err)
+	}
+	if _, err := ln.Accept(); !isTimeout(err) {
+		t.Fatalf("Accept: expected err %v, got %v", errTimeout, err)
+	}
+	ln.SetDeadline(time.Now().Add(100 * time.Millisecond))
+	if _, err := ln.Accept(); !isTimeout(err) {
+		t.Fatalf("Accept: expected err %v, got %v", errTimeout, err)
+	}
+	if _, err := ln.Accept(); !isTimeout(err) {
+		t.Fatalf("Accept: expected err %v, got %v", errTimeout, err)
+	}
+	ln.SetDeadline(noDeadline)
+	errc := make(chan error)
+	go func() {
+		_, err := ln.Accept()
+		errc <- err
+	}()
+	time.Sleep(100 * time.Millisecond)
+	select {
+	case err := <-errc:
+		t.Fatalf("Expected Accept() to not return, but it returned with %v\n", err)
+	default:
+	}
+	ln.Close()
+	switch nerr := <-errc; err := nerr.(type) {
+	case *OpError:
+		if err.Err != errClosing {
+			t.Fatalf("Accept: expected err %v, got %v", errClosing, err)
+		}
+	default:
+		if err != errClosing {
+			t.Fatalf("Accept: expected err %v, got %v", errClosing, err)
+		}
+	}
+}
+
+func TestReadTimeout(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+	c, err := DialTCP("tcp", nil, ln.Addr().(*TCPAddr))
+	if err != nil {
+		t.Fatalf("Connect: %v", err)
+	}
+	defer c.Close()
+	c.SetDeadline(time.Now().Add(time.Hour))
+	c.SetReadDeadline(time.Now().Add(-1 * time.Second))
+	buf := make([]byte, 1)
+	if _, err = c.Read(buf); !isTimeout(err) {
+		t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
+	}
+	if _, err = c.Read(buf); !isTimeout(err) {
+		t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
+	}
+	c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+	if _, err = c.Read(buf); !isTimeout(err) {
+		t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
+	}
+	if _, err = c.Read(buf); !isTimeout(err) {
+		t.Fatalf("Read: expected err %v, got %v", errTimeout, err)
+	}
+	c.SetReadDeadline(noDeadline)
+	c.SetWriteDeadline(time.Now().Add(-1 * time.Second))
+	errc := make(chan error)
+	go func() {
+		_, err := c.Read(buf)
+		errc <- err
+	}()
+	time.Sleep(100 * time.Millisecond)
+	select {
+	case err := <-errc:
+		t.Fatalf("Expected Read() to not return, but it returned with %v\n", err)
+	default:
+	}
+	c.Close()
+	switch nerr := <-errc; err := nerr.(type) {
+	case *OpError:
+		if err.Err != errClosing {
+			t.Fatalf("Read: expected err %v, got %v", errClosing, err)
+		}
+	default:
+		if err != errClosing {
+			t.Fatalf("Read: expected err %v, got %v", errClosing, err)
+		}
+	}
+}
+
+func TestWriteTimeout(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+	c, err := DialTCP("tcp", nil, ln.Addr().(*TCPAddr))
+	if err != nil {
+		t.Fatalf("Connect: %v", err)
+	}
+	defer c.Close()
+	c.SetDeadline(time.Now().Add(time.Hour))
+	c.SetWriteDeadline(time.Now().Add(-1 * time.Second))
+	buf := make([]byte, 4096)
+	writeUntilTimeout := func() {
+		for {
+			_, err := c.Write(buf)
+			if err != nil {
+				if isTimeout(err) {
+					return
+				}
+				t.Fatalf("Write: expected err %v, got %v", errTimeout, err)
+			}
+		}
+	}
+	writeUntilTimeout()
+	c.SetDeadline(time.Now().Add(10 * time.Millisecond))
+	writeUntilTimeout()
+	writeUntilTimeout()
+	c.SetWriteDeadline(noDeadline)
+	c.SetReadDeadline(time.Now().Add(-1 * time.Second))
+	errc := make(chan error)
+	go func() {
+		for {
+			_, err := c.Write(buf)
+			if err != nil {
+				errc <- err
+			}
+		}
+	}()
+	time.Sleep(100 * time.Millisecond)
+	select {
+	case err := <-errc:
+		t.Fatalf("Expected Write() to not return, but it returned with %v\n", err)
+	default:
+	}
+	c.Close()
+	switch nerr := <-errc; err := nerr.(type) {
+	case *OpError:
+		if err.Err != errClosing {
+			t.Fatalf("Write: expected err %v, got %v", errClosing, err)
+		}
+	default:
+		if err != errClosing {
+			t.Fatalf("Write: expected err %v, got %v", errClosing, err)
+		}
+	}
+}
+
 func testTimeout(t *testing.T, net, addr string, readFrom bool) {
 	c, err := Dial(net, addr)
 	if err != nil {
@@ -59,8 +235,7 @@ func testTimeout(t *testing.T, net, addr string, readFrom bool) {
 func TestTimeoutUDP(t *testing.T) {
 	switch runtime.GOOS {
 	case "plan9":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 
 	// set up a listener that won't talk back
@@ -77,8 +252,7 @@ func TestTimeoutUDP(t *testing.T) {
 func TestTimeoutTCP(t *testing.T) {
 	switch runtime.GOOS {
 	case "plan9":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 
 	// set up a listener that won't talk back
@@ -94,8 +268,7 @@ func TestTimeoutTCP(t *testing.T) {
 func TestDeadlineReset(t *testing.T) {
 	switch runtime.GOOS {
 	case "plan9":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 	ln, err := Listen("tcp", "127.0.0.1:0")
 	if err != nil {
@@ -104,7 +277,7 @@ func TestDeadlineReset(t *testing.T) {
 	defer ln.Close()
 	tl := ln.(*TCPListener)
 	tl.SetDeadline(time.Now().Add(1 * time.Minute))
-	tl.SetDeadline(time.Time{}) // reset it
+	tl.SetDeadline(noDeadline) // reset it
 	errc := make(chan error, 1)
 	go func() {
 		_, err := ln.Accept()
@@ -119,3 +292,356 @@ func TestDeadlineReset(t *testing.T) {
 		t.Errorf("unexpected return from Accept; err=%v", err)
 	}
 }
+
+func TestTimeoutAccept(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln.Close()
+	tl := ln.(*TCPListener)
+	tl.SetDeadline(time.Now().Add(100 * time.Millisecond))
+	errc := make(chan error, 1)
+	go func() {
+		_, err := ln.Accept()
+		errc <- err
+	}()
+	select {
+	case <-time.After(1 * time.Second):
+		// Accept shouldn't block indefinitely
+		t.Errorf("Accept didn't return in an expected time")
+	case <-errc:
+		// Pass.
+	}
+}
+
+func TestReadWriteDeadline(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	if !canCancelIO {
+		t.Skip("skipping test on this system")
+	}
+	const (
+		readTimeout  = 50 * time.Millisecond
+		writeTimeout = 250 * time.Millisecond
+	)
+	checkTimeout := func(command string, start time.Time, should time.Duration) {
+		is := time.Now().Sub(start)
+		d := is - should
+		if d < -30*time.Millisecond || !testing.Short() && 150*time.Millisecond < d {
+			t.Errorf("%s timeout test failed: is=%v should=%v\n", command, is, should)
+		}
+	}
+
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ListenTCP on :0: %v", err)
+	}
+	defer ln.Close()
+
+	lnquit := make(chan bool)
+
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Fatalf("Accept: %v", err)
+		}
+		defer c.Close()
+		lnquit <- true
+	}()
+
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+
+	start := time.Now()
+	err = c.SetReadDeadline(start.Add(readTimeout))
+	if err != nil {
+		t.Fatalf("SetReadDeadline: %v", err)
+	}
+	err = c.SetWriteDeadline(start.Add(writeTimeout))
+	if err != nil {
+		t.Fatalf("SetWriteDeadline: %v", err)
+	}
+
+	quit := make(chan bool)
+
+	go func() {
+		var buf [10]byte
+		_, err := c.Read(buf[:])
+		if err == nil {
+			t.Errorf("Read should not succeed")
+		}
+		checkTimeout("Read", start, readTimeout)
+		quit <- true
+	}()
+
+	go func() {
+		var buf [10000]byte
+		for {
+			_, err := c.Write(buf[:])
+			if err != nil {
+				break
+			}
+		}
+		checkTimeout("Write", start, writeTimeout)
+		quit <- true
+	}()
+
+	<-quit
+	<-quit
+	<-lnquit
+}
+
+type neverEnding byte
+
+func (b neverEnding) Read(p []byte) (n int, err error) {
+	for i := range p {
+		p[i] = byte(b)
+	}
+	return len(p), nil
+}
+
+func TestVariousDeadlines1Proc(t *testing.T) {
+	testVariousDeadlines(t, 1)
+}
+
+func TestVariousDeadlines4Proc(t *testing.T) {
+	testVariousDeadlines(t, 4)
+}
+
+func testVariousDeadlines(t *testing.T, maxProcs int) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
+	ln := newLocalListener(t)
+	defer ln.Close()
+	acceptc := make(chan error, 1)
+
+	// The server, with no timeouts of its own, sending bytes to clients
+	// as fast as it can.
+	servec := make(chan copyRes)
+	go func() {
+		for {
+			c, err := ln.Accept()
+			if err != nil {
+				acceptc <- err
+				return
+			}
+			go func() {
+				t0 := time.Now()
+				n, err := io.Copy(c, neverEnding('a'))
+				d := time.Since(t0)
+				c.Close()
+				servec <- copyRes{n, err, d}
+			}()
+		}
+	}()
+
+	for _, timeout := range []time.Duration{
+		1 * time.Nanosecond,
+		2 * time.Nanosecond,
+		5 * time.Nanosecond,
+		50 * time.Nanosecond,
+		100 * time.Nanosecond,
+		200 * time.Nanosecond,
+		500 * time.Nanosecond,
+		750 * time.Nanosecond,
+		1 * time.Microsecond,
+		5 * time.Microsecond,
+		25 * time.Microsecond,
+		250 * time.Microsecond,
+		500 * time.Microsecond,
+		1 * time.Millisecond,
+		5 * time.Millisecond,
+		100 * time.Millisecond,
+		250 * time.Millisecond,
+		500 * time.Millisecond,
+		1 * time.Second,
+	} {
+		numRuns := 3
+		if testing.Short() {
+			numRuns = 1
+			if timeout > 500*time.Microsecond {
+				continue
+			}
+		}
+		for run := 0; run < numRuns; run++ {
+			name := fmt.Sprintf("%v run %d/%d", timeout, run+1, numRuns)
+			t.Log(name)
+
+			c, err := Dial("tcp", ln.Addr().String())
+			if err != nil {
+				t.Fatalf("Dial: %v", err)
+			}
+			clientc := make(chan copyRes)
+			go func() {
+				t0 := time.Now()
+				c.SetDeadline(t0.Add(timeout))
+				n, err := io.Copy(ioutil.Discard, c)
+				d := time.Since(t0)
+				c.Close()
+				clientc <- copyRes{n, err, d}
+			}()
+
+			const tooLong = 2000 * time.Millisecond
+			select {
+			case res := <-clientc:
+				if isTimeout(res.err) {
+					t.Logf("for %v, good client timeout after %v, reading %d bytes", name, res.d, res.n)
+				} else {
+					t.Fatalf("for %v: client Copy = %d, %v (want timeout)", name, res.n, res.err)
+				}
+			case <-time.After(tooLong):
+				t.Fatalf("for %v: timeout (%v) waiting for client to timeout (%v) reading", name, tooLong, timeout)
+			}
+
+			select {
+			case res := <-servec:
+				t.Logf("for %v: server in %v wrote %d, %v", name, res.d, res.n, res.err)
+			case err := <-acceptc:
+				t.Fatalf("for %v: server Accept = %v", name, err)
+			case <-time.After(tooLong):
+				t.Fatalf("for %v, timeout waiting for server to finish writing", name)
+			}
+		}
+	}
+}
+
+// TestReadDeadlineDataAvailable tests that read deadlines work, even
+// if there's data ready to be read.
+func TestReadDeadlineDataAvailable(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	servec := make(chan copyRes)
+	const msg = "data client shouldn't read, even though it it'll be waiting"
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Fatalf("Accept: %v", err)
+		}
+		defer c.Close()
+		n, err := c.Write([]byte(msg))
+		servec <- copyRes{n: int64(n), err: err}
+	}()
+
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+	if res := <-servec; res.err != nil || res.n != int64(len(msg)) {
+		t.Fatalf("unexpected server Write: n=%d, err=%d; want n=%d, err=nil", res.n, res.err, len(msg))
+	}
+	c.SetReadDeadline(time.Now().Add(-5 * time.Second)) // in the psat.
+	buf := make([]byte, len(msg)/2)
+	n, err := c.Read(buf)
+	if n > 0 || !isTimeout(err) {
+		t.Fatalf("client read = %d (%q) err=%v; want 0, timeout", n, buf[:n], err)
+	}
+}
+
+// TestWriteDeadlineBufferAvailable tests that write deadlines work, even
+// if there's buffer space available to write.
+func TestWriteDeadlineBufferAvailable(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	servec := make(chan copyRes)
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Fatalf("Accept: %v", err)
+		}
+		defer c.Close()
+		c.SetWriteDeadline(time.Now().Add(-5 * time.Second)) // in the past
+		n, err := c.Write([]byte{'x'})
+		servec <- copyRes{n: int64(n), err: err}
+	}()
+
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+	res := <-servec
+	if res.n != 0 {
+		t.Errorf("Write = %d; want 0", res.n)
+	}
+	if !isTimeout(res.err) {
+		t.Errorf("Write error = %v; want timeout", res.err)
+	}
+}
+
+// TestProlongTimeout tests concurrent deadline modification.
+// Known to cause data races in the past.
+func TestProlongTimeout(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	ln := newLocalListener(t)
+	defer ln.Close()
+	connected := make(chan bool)
+	go func() {
+		s, err := ln.Accept()
+		connected <- true
+		if err != nil {
+			t.Fatalf("ln.Accept: %v", err)
+		}
+		defer s.Close()
+		s.SetDeadline(time.Now().Add(time.Hour))
+		go func() {
+			var buf [4096]byte
+			for {
+				_, err := s.Write(buf[:])
+				if err != nil {
+					break
+				}
+				s.SetDeadline(time.Now().Add(time.Hour))
+			}
+		}()
+		buf := make([]byte, 1)
+		for {
+			_, err := s.Read(buf)
+			if err != nil {
+				break
+			}
+			s.SetDeadline(time.Now().Add(time.Hour))
+		}
+	}()
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("DialTCP: %v", err)
+	}
+	defer c.Close()
+	<-connected
+	for i := 0; i < 1024; i++ {
+		var buf [1]byte
+		c.Write(buf[:])
+	}
+}
diff --git a/src/pkg/net/udp_test.go b/src/pkg/net/udp_test.go
index f80d3b5..220422e 100644
--- a/src/pkg/net/udp_test.go
+++ b/src/pkg/net/udp_test.go
@@ -5,15 +5,45 @@
 package net
 
 import (
+	"reflect"
 	"runtime"
 	"testing"
 )
 
+var resolveUDPAddrTests = []struct {
+	net     string
+	litAddr string
+	addr    *UDPAddr
+	err     error
+}{
+	{"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
+	{"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
+
+	{"udp", "[::1]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1}, nil},
+	{"udp6", "[::1]:65534", &UDPAddr{IP: ParseIP("::1"), Port: 65534}, nil},
+
+	{"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
+	{"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior
+
+	{"sip", "127.0.0.1:0", nil, UnknownNetworkError("sip")},
+}
+
+func TestResolveUDPAddr(t *testing.T) {
+	for _, tt := range resolveUDPAddrTests {
+		addr, err := ResolveUDPAddr(tt.net, tt.litAddr)
+		if err != tt.err {
+			t.Fatalf("ResolveUDPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
+		}
+		if !reflect.DeepEqual(addr, tt.addr) {
+			t.Fatalf("got %#v; expected %#v", addr, tt.addr)
+		}
+	}
+}
+
 func TestWriteToUDP(t *testing.T) {
 	switch runtime.GOOS {
 	case "plan9":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
+		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 
 	l, err := ListenPacket("udp", "127.0.0.1:0")
@@ -87,3 +117,32 @@ func testWriteToPacketConn(t *testing.T, raddr string) {
 		t.Fatal("Write should fail")
 	}
 }
+
+var udpConnLocalNameTests = []struct {
+	net   string
+	laddr *UDPAddr
+}{
+	{"udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}},
+	{"udp4", &UDPAddr{}},
+	{"udp4", nil},
+}
+
+func TestUDPConnLocalName(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	for _, tt := range udpConnLocalNameTests {
+		c, err := ListenUDP(tt.net, tt.laddr)
+		if err != nil {
+			t.Errorf("ListenUDP failed: %v", err)
+			return
+		}
+		defer c.Close()
+		la := c.LocalAddr()
+		if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
+			t.Errorf("got %v; expected a proper address with non-zero port number", la)
+			return
+		}
+	}
+}
diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go
index b3520cf..6e5e902 100644
--- a/src/pkg/net/udpsock.go
+++ b/src/pkg/net/udpsock.go
@@ -6,10 +6,15 @@
 
 package net
 
+import "errors"
+
+var ErrWriteToConnected = errors.New("use of WriteTo with pre-connected UDP")
+
 // UDPAddr represents the address of a UDP end point.
 type UDPAddr struct {
 	IP   IP
 	Port int
+	Zone string // IPv6 scoped addressing zone
 }
 
 // Network returns the address's network name, "udp".
@@ -28,9 +33,16 @@ func (a *UDPAddr) String() string {
 // "udp4" or "udp6".  A literal IPv6 host address must be
 // enclosed in square brackets, as in "[::]:80".
 func ResolveUDPAddr(net, addr string) (*UDPAddr, error) {
-	ip, port, err := hostPortToIP(net, addr)
+	switch net {
+	case "udp", "udp4", "udp6":
+	case "": // a hint wildcard for Go 1.0 undocumented behavior
+		net = "udp"
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	a, err := resolveInternetAddr(net, addr, noDeadline)
 	if err != nil {
 		return nil, err
 	}
-	return &UDPAddr{ip, port}, nil
+	return a.(*UDPAddr), nil
 }
diff --git a/src/pkg/net/udpsock_plan9.go b/src/pkg/net/udpsock_plan9.go
index 4f298a4..2a7e3d1 100644
--- a/src/pkg/net/udpsock_plan9.go
+++ b/src/pkg/net/udpsock_plan9.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.
 
-// UDP for Plan 9
+// UDP sockets for Plan 9
 
 package net
 
@@ -16,44 +16,26 @@ import (
 // UDPConn is the implementation of the Conn and PacketConn
 // interfaces for UDP network connections.
 type UDPConn struct {
-	plan9Conn
+	conn
 }
 
-// SetDeadline implements the Conn SetDeadline method.
-func (c *UDPConn) SetDeadline(t time.Time) error {
-	return syscall.EPLAN9
+func newUDPConn(fd *netFD) *UDPConn {
+	return &UDPConn{conn{fd}}
 }
 
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *UDPConn) SetReadDeadline(t time.Time) error {
-	return syscall.EPLAN9
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *UDPConn) SetWriteDeadline(t time.Time) error {
-	return syscall.EPLAN9
-}
-
-// UDP-specific methods.
-
 // ReadFromUDP reads a UDP packet from c, copying the payload into b.
 // It returns the number of bytes copied into b and the return address
 // that was on the packet.
 //
-// ReadFromUDP can be made to time out and return an error with Timeout() == true
-// after a fixed time limit; see SetDeadline and SetReadDeadline.
+// ReadFromUDP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
 func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
-	if !c.ok() {
+	if !c.ok() || c.fd.data == nil {
 		return 0, nil, syscall.EINVAL
 	}
-	if c.data == nil {
-		c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
-		if err != nil {
-			return 0, nil, err
-		}
-	}
 	buf := make([]byte, udpHeaderSize+len(b))
-	m, err := c.data.Read(buf)
+	m, err := c.fd.data.Read(buf)
 	if err != nil {
 		return
 	}
@@ -64,62 +46,80 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
 
 	h, buf := unmarshalUDPHeader(buf)
 	n = copy(b, buf)
-	return n, &UDPAddr{h.raddr, int(h.rport)}, nil
+	return n, &UDPAddr{IP: h.raddr, Port: int(h.rport)}, nil
 }
 
 // ReadFrom implements the PacketConn ReadFrom method.
-func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
+func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
 	if !c.ok() {
 		return 0, nil, syscall.EINVAL
 	}
 	return c.ReadFromUDP(b)
 }
 
-// WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
+// ReadMsgUDP reads a packet from c, copying the payload into b and
+// the associdated out-of-band data into oob.  It returns the number
+// of bytes copied into b, the number of bytes copied into oob, the
+// flags that were set on the packet and the source address of the
+// packet.
+func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
+	return 0, 0, 0, nil, syscall.EPLAN9
+}
+
+// WriteToUDP writes a UDP packet to addr via c, copying the payload
+// from b.
 //
-// WriteToUDP can be made to time out and return
-// an error with Timeout() == true after a fixed time limit;
-// see SetDeadline and SetWriteDeadline.
-// On packet-oriented connections, write timeouts are rare.
-func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) {
-	if !c.ok() {
+// WriteToUDP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
+func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
+	if !c.ok() || c.fd.data == nil {
 		return 0, syscall.EINVAL
 	}
-	if c.data == nil {
-		c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
-		if err != nil {
-			return 0, err
-		}
-	}
 	h := new(udpHeader)
 	h.raddr = addr.IP.To16()
-	h.laddr = c.laddr.(*UDPAddr).IP.To16()
+	h.laddr = c.fd.laddr.(*UDPAddr).IP.To16()
 	h.ifcaddr = IPv6zero // ignored (receive only)
 	h.rport = uint16(addr.Port)
-	h.lport = uint16(c.laddr.(*UDPAddr).Port)
+	h.lport = uint16(c.fd.laddr.(*UDPAddr).Port)
 
 	buf := make([]byte, udpHeaderSize+len(b))
 	i := copy(buf, h.Bytes())
 	copy(buf[i:], b)
-	return c.data.Write(buf)
+	return c.fd.data.Write(buf)
 }
 
 // WriteTo implements the PacketConn WriteTo method.
-func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
+func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
 	if !c.ok() {
 		return 0, syscall.EINVAL
 	}
 	a, ok := addr.(*UDPAddr)
 	if !ok {
-		return 0, &OpError{"write", c.dir, addr, syscall.EINVAL}
+		return 0, &OpError{"write", c.fd.dir, addr, syscall.EINVAL}
 	}
 	return c.WriteToUDP(b, a)
 }
 
+// WriteMsgUDP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob.  It returns the
+// number of payload and out-of-band bytes written.
+func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
+	return 0, 0, syscall.EPLAN9
+}
+
 // DialUDP connects to the remote address raddr on the network net,
-// which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is used
-// as the local address for the connection.
-func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
+// which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is
+// used as the local address for the connection.
+func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
+	return dialUDP(net, laddr, raddr, noDeadline)
+}
+
+func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
+	if !deadline.IsZero() {
+		panic("net.dialUDP: deadline not implemented on Plan 9")
+	}
 	switch net {
 	case "udp", "udp4", "udp6":
 	default:
@@ -128,11 +128,11 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
 	if raddr == nil {
 		return nil, &OpError{"dial", net, nil, errMissingAddress}
 	}
-	c1, err := dialPlan9(net, laddr, raddr)
+	fd, err := dialPlan9(net, laddr, raddr)
 	if err != nil {
-		return
+		return nil, err
 	}
-	return &UDPConn{*c1}, nil
+	return newUDPConn(fd), nil
 }
 
 const udpHeaderSize = 16*3 + 2*2
@@ -163,34 +163,38 @@ func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {
 	return h, b
 }
 
-// ListenUDP listens for incoming UDP packets addressed to the
-// local address laddr.  The returned connection c's ReadFrom
-// and WriteTo methods can be used to receive and send UDP
-// packets with per-packet addressing.
-func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
+// ListenUDP listens for incoming UDP packets addressed to the local
+// address laddr.  The returned connection c's ReadFrom and WriteTo
+// methods can be used to receive and send UDP packets with per-packet
+// addressing.
+func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
 	switch net {
 	case "udp", "udp4", "udp6":
 	default:
 		return nil, UnknownNetworkError(net)
 	}
 	if laddr == nil {
-		return nil, &OpError{"listen", net, nil, errMissingAddress}
+		laddr = &UDPAddr{}
 	}
 	l, err := listenPlan9(net, laddr)
 	if err != nil {
-		return
+		return nil, err
 	}
 	_, err = l.ctl.WriteString("headers")
 	if err != nil {
-		return
+		return nil, err
+	}
+	l.data, err = os.OpenFile(l.dir+"/data", os.O_RDWR, 0)
+	if err != nil {
+		return nil, err
 	}
-	return &UDPConn{*l.plan9Conn()}, nil
+	return newUDPConn(l.netFD()), nil
 }
 
 // ListenMulticastUDP listens for incoming multicast UDP packets
-// addressed to the group address gaddr on ifi, which specifies
-// the interface to join.  ListenMulticastUDP uses default
-// multicast interface if ifi is nil.
+// addressed to the group address gaddr on ifi, which specifies the
+// interface to join.  ListenMulticastUDP uses default multicast
+// interface if ifi is nil.
 func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
 	return nil, syscall.EPLAN9
 }
diff --git a/src/pkg/net/udpsock_posix.go b/src/pkg/net/udpsock_posix.go
index 9c6b6d3..385cd90 100644
--- a/src/pkg/net/udpsock_posix.go
+++ b/src/pkg/net/udpsock_posix.go
@@ -4,25 +4,21 @@
 
 // +build darwin freebsd linux netbsd openbsd windows
 
-// UDP sockets
+// UDP sockets for POSIX
 
 package net
 
 import (
-	"errors"
-	"os"
 	"syscall"
 	"time"
 )
 
-var ErrWriteToConnected = errors.New("use of WriteTo with pre-connected UDP")
-
 func sockaddrToUDP(sa syscall.Sockaddr) Addr {
 	switch sa := sa.(type) {
 	case *syscall.SockaddrInet4:
-		return &UDPAddr{sa.Addr[0:], sa.Port}
+		return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
 	case *syscall.SockaddrInet6:
-		return &UDPAddr{sa.Addr[0:], sa.Port}
+		return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
 	}
 	return nil
 }
@@ -45,7 +41,7 @@ func (a *UDPAddr) isWildcard() bool {
 }
 
 func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
-	return ipToSockaddr(family, a.IP, a.Port)
+	return ipToSockaddr(family, a.IP, a.Port, a.Zone)
 }
 
 func (a *UDPAddr) toAddr() sockaddr {
@@ -58,98 +54,10 @@ func (a *UDPAddr) toAddr() sockaddr {
 // UDPConn is the implementation of the Conn and PacketConn
 // interfaces for UDP network connections.
 type UDPConn struct {
-	fd *netFD
-}
-
-func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{fd} }
-
-func (c *UDPConn) ok() bool { return c != nil && c.fd != nil }
-
-// Implementation of the Conn interface - see Conn for documentation.
-
-// Read implements the Conn Read method.
-func (c *UDPConn) Read(b []byte) (int, error) {
-	if !c.ok() {
-		return 0, syscall.EINVAL
-	}
-	return c.fd.Read(b)
-}
-
-// Write implements the Conn Write method.
-func (c *UDPConn) Write(b []byte) (int, error) {
-	if !c.ok() {
-		return 0, syscall.EINVAL
-	}
-	return c.fd.Write(b)
-}
-
-// Close closes the UDP connection.
-func (c *UDPConn) Close() error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return c.fd.Close()
-}
-
-// LocalAddr returns the local network address.
-func (c *UDPConn) LocalAddr() Addr {
-	if !c.ok() {
-		return nil
-	}
-	return c.fd.laddr
-}
-
-// RemoteAddr returns the remote network address, a *UDPAddr.
-func (c *UDPConn) RemoteAddr() Addr {
-	if !c.ok() {
-		return nil
-	}
-	return c.fd.raddr
-}
-
-// SetDeadline implements the Conn SetDeadline method.
-func (c *UDPConn) SetDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setDeadline(c.fd, t)
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *UDPConn) SetReadDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setReadDeadline(c.fd, t)
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *UDPConn) SetWriteDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setWriteDeadline(c.fd, t)
-}
-
-// SetReadBuffer sets the size of the operating system's
-// receive buffer associated with the connection.
-func (c *UDPConn) SetReadBuffer(bytes int) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setReadBuffer(c.fd, bytes)
-}
-
-// SetWriteBuffer sets the size of the operating system's
-// transmit buffer associated with the connection.
-func (c *UDPConn) SetWriteBuffer(bytes int) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setWriteBuffer(c.fd, bytes)
+	conn
 }
 
-// UDP-specific methods.
+func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
 
 // ReadFromUDP reads a UDP packet from c, copying the payload into b.
 // It returns the number of bytes copied into b and the return address
@@ -164,9 +72,9 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
 	n, sa, err := c.fd.ReadFrom(b)
 	switch sa := sa.(type) {
 	case *syscall.SockaddrInet4:
-		addr = &UDPAddr{sa.Addr[0:], sa.Port}
+		addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
 	case *syscall.SockaddrInet6:
-		addr = &UDPAddr{sa.Addr[0:], sa.Port}
+		addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
 	}
 	return
 }
@@ -176,8 +84,28 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
 	if !c.ok() {
 		return 0, nil, syscall.EINVAL
 	}
-	n, uaddr, err := c.ReadFromUDP(b)
-	return n, uaddr.toAddr(), err
+	n, addr, err := c.ReadFromUDP(b)
+	return n, addr.toAddr(), err
+}
+
+// ReadMsgUDP reads a packet from c, copying the payload into b and
+// the associdated out-of-band data into oob.  It returns the number
+// of bytes copied into b, the number of bytes copied into oob, the
+// flags that were set on the packet and the source address of the
+// packet.
+func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
+	if !c.ok() {
+		return 0, 0, 0, nil, syscall.EINVAL
+	}
+	var sa syscall.Sockaddr
+	n, oobn, flags, sa, err = c.fd.ReadMsg(b, oob)
+	switch sa := sa.(type) {
+	case *syscall.SockaddrInet4:
+		addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
+	case *syscall.SockaddrInet6:
+		addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
+	}
+	return
 }
 
 // WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
@@ -212,15 +140,31 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
 	return c.WriteToUDP(b, a)
 }
 
-// File returns a copy of the underlying os.File, set to blocking mode.
-// 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 (c *UDPConn) File() (f *os.File, err error) { return c.fd.dup() }
+// WriteMsgUDP writes a packet to addr via c, copying the payload from
+// b and the associated out-of-band data from oob.  It returns the
+// number of payload and out-of-band bytes written.
+func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
+	if !c.ok() {
+		return 0, 0, syscall.EINVAL
+	}
+	if c.fd.isConnected {
+		return 0, 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
+	}
+	sa, err := addr.sockaddr(c.fd.family)
+	if err != nil {
+		return 0, 0, &OpError{"write", c.fd.net, addr, err}
+	}
+	return c.fd.WriteMsg(b, oob, sa)
+}
 
 // DialUDP connects to the remote address raddr on the network net,
 // which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is used
 // as the local address for the connection.
 func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
+	return dialUDP(net, laddr, raddr, noDeadline)
+}
+
+func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
 	switch net {
 	case "udp", "udp4", "udp6":
 	default:
@@ -229,7 +173,7 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
 	if raddr == nil {
 		return nil, &OpError{"dial", net, nil, errMissingAddress}
 	}
-	fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
+	fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
 	if err != nil {
 		return nil, err
 	}
@@ -247,9 +191,9 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
 		return nil, UnknownNetworkError(net)
 	}
 	if laddr == nil {
-		return nil, &OpError{"listen", net, nil, errMissingAddress}
+		laddr = &UDPAddr{}
 	}
-	fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
+	fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
 	if err != nil {
 		return nil, err
 	}
@@ -267,25 +211,22 @@ func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, e
 		return nil, UnknownNetworkError(net)
 	}
 	if gaddr == nil || gaddr.IP == nil {
-		return nil, &OpError{"listenmulticast", net, nil, errMissingAddress}
+		return nil, &OpError{"listen", net, nil, errMissingAddress}
 	}
-	fd, err := internetSocket(net, gaddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
+	fd, err := internetSocket(net, gaddr.toAddr(), nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
 	if err != nil {
 		return nil, err
 	}
 	c := newUDPConn(fd)
-	ip4 := gaddr.IP.To4()
-	if ip4 != nil {
-		err := listenIPv4MulticastUDP(c, ifi, ip4)
-		if err != nil {
+	if ip4 := gaddr.IP.To4(); ip4 != nil {
+		if err := listenIPv4MulticastUDP(c, ifi, ip4); err != nil {
 			c.Close()
-			return nil, err
+			return nil, &OpError{"listen", net, &IPAddr{IP: ip4}, err}
 		}
 	} else {
-		err := listenIPv6MulticastUDP(c, ifi, gaddr.IP)
-		if err != nil {
+		if err := listenIPv6MulticastUDP(c, ifi, gaddr.IP); err != nil {
 			c.Close()
-			return nil, err
+			return nil, &OpError{"listen", net, &IPAddr{IP: gaddr.IP}, err}
 		}
 	}
 	return c, nil
@@ -293,17 +234,14 @@ func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, e
 
 func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
 	if ifi != nil {
-		err := setIPv4MulticastInterface(c.fd, ifi)
-		if err != nil {
+		if err := setIPv4MulticastInterface(c.fd, ifi); err != nil {
 			return err
 		}
 	}
-	err := setIPv4MulticastLoopback(c.fd, false)
-	if err != nil {
+	if err := setIPv4MulticastLoopback(c.fd, false); err != nil {
 		return err
 	}
-	err = joinIPv4GroupUDP(c, ifi, ip)
-	if err != nil {
+	if err := joinIPv4Group(c.fd, ifi, ip); err != nil {
 		return err
 	}
 	return nil
@@ -311,50 +249,15 @@ func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
 
 func listenIPv6MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
 	if ifi != nil {
-		err := setIPv6MulticastInterface(c.fd, ifi)
-		if err != nil {
+		if err := setIPv6MulticastInterface(c.fd, ifi); err != nil {
 			return err
 		}
 	}
-	err := setIPv6MulticastLoopback(c.fd, false)
-	if err != nil {
+	if err := setIPv6MulticastLoopback(c.fd, false); err != nil {
 		return err
 	}
-	err = joinIPv6GroupUDP(c, ifi, ip)
-	if err != nil {
+	if err := joinIPv6Group(c.fd, ifi, ip); err != nil {
 		return err
 	}
 	return nil
 }
-
-func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
-	err := joinIPv4Group(c.fd, ifi, ip)
-	if err != nil {
-		return &OpError{"joinipv4group", c.fd.net, &IPAddr{ip}, err}
-	}
-	return nil
-}
-
-func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
-	err := leaveIPv4Group(c.fd, ifi, ip)
-	if err != nil {
-		return &OpError{"leaveipv4group", c.fd.net, &IPAddr{ip}, err}
-	}
-	return nil
-}
-
-func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
-	err := joinIPv6Group(c.fd, ifi, ip)
-	if err != nil {
-		return &OpError{"joinipv6group", c.fd.net, &IPAddr{ip}, err}
-	}
-	return nil
-}
-
-func leaveIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
-	err := leaveIPv6Group(c.fd, ifi, ip)
-	if err != nil {
-		return &OpError{"leaveipv6group", c.fd.net, &IPAddr{ip}, err}
-	}
-	return nil
-}
diff --git a/src/pkg/net/unicast_posix_test.go b/src/pkg/net/unicast_posix_test.go
new file mode 100644
index 0000000..a8855ca
--- /dev/null
+++ b/src/pkg/net/unicast_posix_test.go
@@ -0,0 +1,516 @@
+// 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 !plan9
+
+package net
+
+import (
+	"runtime"
+	"syscall"
+	"testing"
+)
+
+var listenerTests = []struct {
+	net      string
+	laddr    string
+	ipv6     bool // test with underlying AF_INET6 socket
+	wildcard bool // test with wildcard address
+}{
+	{net: "tcp", laddr: "", wildcard: true},
+	{net: "tcp", laddr: "0.0.0.0", wildcard: true},
+	{net: "tcp", laddr: "[::ffff:0.0.0.0]", wildcard: true},
+	{net: "tcp", laddr: "[::]", ipv6: true, wildcard: true},
+
+	{net: "tcp", laddr: "127.0.0.1"},
+	{net: "tcp", laddr: "[::ffff:127.0.0.1]"},
+	{net: "tcp", laddr: "[::1]", ipv6: true},
+
+	{net: "tcp4", laddr: "", wildcard: true},
+	{net: "tcp4", laddr: "0.0.0.0", wildcard: true},
+	{net: "tcp4", laddr: "[::ffff:0.0.0.0]", wildcard: true},
+
+	{net: "tcp4", laddr: "127.0.0.1"},
+	{net: "tcp4", laddr: "[::ffff:127.0.0.1]"},
+
+	{net: "tcp6", laddr: "", ipv6: true, wildcard: true},
+	{net: "tcp6", laddr: "[::]", ipv6: true, wildcard: true},
+
+	{net: "tcp6", laddr: "[::1]", ipv6: true},
+}
+
+// TestTCPListener tests both single and double listen to a test
+// listener with same address family, same listening address and
+// same port.
+func TestTCPListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	for _, tt := range listenerTests {
+		if tt.wildcard && (testing.Short() || !*testExternal) {
+			continue
+		}
+		if tt.ipv6 && !supportsIPv6 {
+			continue
+		}
+		l1, port := usableListenPort(t, tt.net, tt.laddr)
+		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
+		l2, err := Listen(tt.net, tt.laddr+":"+port)
+		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
+		l1.Close()
+	}
+}
+
+// TestUDPListener tests both single and double listen to a test
+// listener with same address family, same listening address and
+// same port.
+func TestUDPListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	toudpnet := func(net string) string {
+		switch net {
+		case "tcp":
+			return "udp"
+		case "tcp4":
+			return "udp4"
+		case "tcp6":
+			return "udp6"
+		}
+		return "<nil>"
+	}
+
+	for _, tt := range listenerTests {
+		if tt.wildcard && (testing.Short() || !*testExternal) {
+			continue
+		}
+		if tt.ipv6 && !supportsIPv6 {
+			continue
+		}
+		tt.net = toudpnet(tt.net)
+		l1, port := usableListenPacketPort(t, tt.net, tt.laddr)
+		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
+		l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
+		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
+		l1.Close()
+	}
+}
+
+func TestSimpleTCPListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+		return
+	}
+
+	for _, tt := range listenerTests {
+		if tt.wildcard && (testing.Short() || !*testExternal) {
+			continue
+		}
+		if tt.ipv6 {
+			continue
+		}
+		l1, port := usableListenPort(t, tt.net, tt.laddr)
+		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
+		l2, err := Listen(tt.net, tt.laddr+":"+port)
+		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
+		l1.Close()
+	}
+}
+
+func TestSimpleUDPListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+		return
+	}
+
+	toudpnet := func(net string) string {
+		switch net {
+		case "tcp":
+			return "udp"
+		case "tcp4":
+			return "udp4"
+		case "tcp6":
+			return "udp6"
+		}
+		return "<nil>"
+	}
+
+	for _, tt := range listenerTests {
+		if tt.wildcard && (testing.Short() || !*testExternal) {
+			continue
+		}
+		if tt.ipv6 {
+			continue
+		}
+		tt.net = toudpnet(tt.net)
+		l1, port := usableListenPacketPort(t, tt.net, tt.laddr)
+		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
+		l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
+		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
+		l1.Close()
+	}
+}
+
+var dualStackListenerTests = []struct {
+	net1     string // first listener
+	laddr1   string
+	net2     string // second listener
+	laddr2   string
+	wildcard bool  // test with wildcard address
+	xerr     error // expected error value, nil or other
+}{
+	// Test cases and expected results for the attemping 2nd listen on the same port
+	// 1st listen                2nd listen                 darwin  freebsd  linux  openbsd
+	// ------------------------------------------------------------------------------------
+	// "tcp"  ""                 "tcp"  ""                    -        -       -       -
+	// "tcp"  ""                 "tcp"  "0.0.0.0"             -        -       -       -
+	// "tcp"  "0.0.0.0"          "tcp"  ""                    -        -       -       -
+	// ------------------------------------------------------------------------------------
+	// "tcp"  ""                 "tcp"  "[::]"                -        -       -       ok
+	// "tcp"  "[::]"             "tcp"  ""                    -        -       -       ok
+	// "tcp"  "0.0.0.0"          "tcp"  "[::]"                -        -       -       ok
+	// "tcp"  "[::]"             "tcp"  "0.0.0.0"             -        -       -       ok
+	// "tcp"  "[::ffff:0.0.0.0]" "tcp"  "[::]"                -        -       -       ok
+	// "tcp"  "[::]"             "tcp"  "[::ffff:0.0.0.0]"    -        -       -       ok
+	// ------------------------------------------------------------------------------------
+	// "tcp4" ""                 "tcp6" ""                    ok       ok      ok      ok
+	// "tcp6" ""                 "tcp4" ""                    ok       ok      ok      ok
+	// "tcp4" "0.0.0.0"          "tcp6" "[::]"                ok       ok      ok      ok
+	// "tcp6" "[::]"             "tcp4" "0.0.0.0"             ok       ok      ok      ok
+	// ------------------------------------------------------------------------------------
+	// "tcp"  "127.0.0.1"        "tcp"  "[::1]"               ok       ok      ok      ok
+	// "tcp"  "[::1]"            "tcp"  "127.0.0.1"           ok       ok      ok      ok
+	// "tcp4" "127.0.0.1"        "tcp6" "[::1]"               ok       ok      ok      ok
+	// "tcp6" "[::1]"            "tcp4" "127.0.0.1"           ok       ok      ok      ok
+	//
+	// Platform default configurations:
+	// darwin, kernel version 11.3.0
+	//	net.inet6.ip6.v6only=0 (overridable by sysctl or IPV6_V6ONLY option)
+	// freebsd, kernel version 8.2
+	//	net.inet6.ip6.v6only=1 (overridable by sysctl or IPV6_V6ONLY option)
+	// linux, kernel version 3.0.0
+	//	net.ipv6.bindv6only=0 (overridable by sysctl or IPV6_V6ONLY option)
+	// openbsd, kernel version 5.0
+	//	net.inet6.ip6.v6only=1 (overriding is prohibited)
+
+	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "0.0.0.0", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "0.0.0.0", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
+
+	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "0.0.0.0", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "0.0.0.0", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "[::ffff:0.0.0.0]", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
+	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "[::ffff:0.0.0.0]", wildcard: true, xerr: syscall.EADDRINUSE},
+
+	{net1: "tcp4", laddr1: "", net2: "tcp6", laddr2: "", wildcard: true},
+	{net1: "tcp6", laddr1: "", net2: "tcp4", laddr2: "", wildcard: true},
+	{net1: "tcp4", laddr1: "0.0.0.0", net2: "tcp6", laddr2: "[::]", wildcard: true},
+	{net1: "tcp6", laddr1: "[::]", net2: "tcp4", laddr2: "0.0.0.0", wildcard: true},
+
+	{net1: "tcp", laddr1: "127.0.0.1", net2: "tcp", laddr2: "[::1]"},
+	{net1: "tcp", laddr1: "[::1]", net2: "tcp", laddr2: "127.0.0.1"},
+	{net1: "tcp4", laddr1: "127.0.0.1", net2: "tcp6", laddr2: "[::1]"},
+	{net1: "tcp6", laddr1: "[::1]", net2: "tcp4", laddr2: "127.0.0.1"},
+}
+
+// TestDualStackTCPListener tests both single and double listen
+// to a test listener with various address families, differnet
+// listening address and same port.
+func TestDualStackTCPListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	if !supportsIPv6 {
+		return
+	}
+
+	for _, tt := range dualStackListenerTests {
+		if tt.wildcard && (testing.Short() || !*testExternal) {
+			continue
+		}
+		switch runtime.GOOS {
+		case "openbsd":
+			if tt.wildcard && differentWildcardAddr(tt.laddr1, tt.laddr2) {
+				tt.xerr = nil
+			}
+		}
+		l1, port := usableListenPort(t, tt.net1, tt.laddr1)
+		laddr := tt.laddr1 + ":" + port
+		checkFirstListener(t, tt.net1, laddr, l1)
+		laddr = tt.laddr2 + ":" + port
+		l2, err := Listen(tt.net2, laddr)
+		checkDualStackSecondListener(t, tt.net2, laddr, tt.xerr, err, l2)
+		l1.Close()
+	}
+}
+
+// TestDualStackUDPListener tests both single and double listen
+// to a test listener with various address families, differnet
+// listening address and same port.
+func TestDualStackUDPListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	if !supportsIPv6 {
+		return
+	}
+
+	toudpnet := func(net string) string {
+		switch net {
+		case "tcp":
+			return "udp"
+		case "tcp4":
+			return "udp4"
+		case "tcp6":
+			return "udp6"
+		}
+		return "<nil>"
+	}
+
+	for _, tt := range dualStackListenerTests {
+		if tt.wildcard && (testing.Short() || !*testExternal) {
+			continue
+		}
+		tt.net1 = toudpnet(tt.net1)
+		tt.net2 = toudpnet(tt.net2)
+		switch runtime.GOOS {
+		case "openbsd":
+			if tt.wildcard && differentWildcardAddr(tt.laddr1, tt.laddr2) {
+				tt.xerr = nil
+			}
+		}
+		l1, port := usableListenPacketPort(t, tt.net1, tt.laddr1)
+		laddr := tt.laddr1 + ":" + port
+		checkFirstListener(t, tt.net1, laddr, l1)
+		laddr = tt.laddr2 + ":" + port
+		l2, err := ListenPacket(tt.net2, laddr)
+		checkDualStackSecondListener(t, tt.net2, laddr, tt.xerr, err, l2)
+		l1.Close()
+	}
+}
+
+func usableListenPort(t *testing.T, net, laddr string) (l Listener, port string) {
+	var nladdr string
+	var err error
+	switch net {
+	default:
+		panic("usableListenPort net=" + net)
+	case "tcp", "tcp4", "tcp6":
+		l, err = Listen(net, laddr+":0")
+		if err != nil {
+			t.Fatalf("Probe Listen(%q, %q) failed: %v", net, laddr, err)
+		}
+		nladdr = l.(*TCPListener).Addr().String()
+	}
+	_, port, err = SplitHostPort(nladdr)
+	if err != nil {
+		t.Fatalf("SplitHostPort failed: %v", err)
+	}
+	return l, port
+}
+
+func usableListenPacketPort(t *testing.T, net, laddr string) (l PacketConn, port string) {
+	var nladdr string
+	var err error
+	switch net {
+	default:
+		panic("usableListenPacketPort net=" + net)
+	case "udp", "udp4", "udp6":
+		l, err = ListenPacket(net, laddr+":0")
+		if err != nil {
+			t.Fatalf("Probe ListenPacket(%q, %q) failed: %v", net, laddr, err)
+		}
+		nladdr = l.(*UDPConn).LocalAddr().String()
+	}
+	_, port, err = SplitHostPort(nladdr)
+	if err != nil {
+		t.Fatalf("SplitHostPort failed: %v", err)
+	}
+	return l, port
+}
+
+func differentWildcardAddr(i, j string) bool {
+	if (i == "" || i == "0.0.0.0" || i == "::ffff:0.0.0.0") && (j == "" || j == "0.0.0.0" || j == "::ffff:0.0.0.0") {
+		return false
+	}
+	if i == "[::]" && j == "[::]" {
+		return false
+	}
+	return true
+}
+
+func checkFirstListener(t *testing.T, net, laddr string, l interface{}) {
+	switch net {
+	case "tcp":
+		fd := l.(*TCPListener).fd
+		checkDualStackAddrFamily(t, net, laddr, fd)
+	case "tcp4":
+		fd := l.(*TCPListener).fd
+		if fd.family != syscall.AF_INET {
+			t.Fatalf("First Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET)
+		}
+	case "tcp6":
+		fd := l.(*TCPListener).fd
+		if fd.family != syscall.AF_INET6 {
+			t.Fatalf("First Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
+		}
+	case "udp":
+		fd := l.(*UDPConn).fd
+		checkDualStackAddrFamily(t, net, laddr, fd)
+	case "udp4":
+		fd := l.(*UDPConn).fd
+		if fd.family != syscall.AF_INET {
+			t.Fatalf("First ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET)
+		}
+	case "udp6":
+		fd := l.(*UDPConn).fd
+		if fd.family != syscall.AF_INET6 {
+			t.Fatalf("First ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
+		}
+	default:
+		t.Fatalf("Unexpected network: %q", net)
+	}
+}
+
+func checkSecondListener(t *testing.T, net, laddr string, err error, l interface{}) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+		if err == nil {
+			l.(*TCPListener).Close()
+			t.Fatalf("Second Listen(%q, %q) should fail", net, laddr)
+		}
+	case "udp", "udp4", "udp6":
+		if err == nil {
+			l.(*UDPConn).Close()
+			t.Fatalf("Second ListenPacket(%q, %q) should fail", net, laddr)
+		}
+	default:
+		t.Fatalf("Unexpected network: %q", net)
+	}
+}
+
+func checkDualStackSecondListener(t *testing.T, net, laddr string, xerr, err error, l interface{}) {
+	switch net {
+	case "tcp", "tcp4", "tcp6":
+		if xerr == nil && err != nil || xerr != nil && err == nil {
+			t.Fatalf("Second Listen(%q, %q) returns %v, expected %v", net, laddr, err, xerr)
+		}
+		l.(*TCPListener).Close()
+	case "udp", "udp4", "udp6":
+		if xerr == nil && err != nil || xerr != nil && err == nil {
+			t.Fatalf("Second ListenPacket(%q, %q) returns %v, expected %v", net, laddr, err, xerr)
+		}
+		l.(*UDPConn).Close()
+	default:
+		t.Fatalf("Unexpected network: %q", net)
+	}
+}
+
+func checkDualStackAddrFamily(t *testing.T, net, laddr string, fd *netFD) {
+	switch a := fd.laddr.(type) {
+	case *TCPAddr:
+		// If a node under test supports both IPv6 capability
+		// and IPv6 IPv4-mapping capability, we can assume
+		// that the node listens on a wildcard address with an
+		// AF_INET6 socket.
+		if supportsIPv4map && fd.laddr.(*TCPAddr).isWildcard() {
+			if fd.family != syscall.AF_INET6 {
+				t.Fatalf("Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
+			}
+		} else {
+			if fd.family != a.family() {
+				t.Fatalf("Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, a.family())
+			}
+		}
+	case *UDPAddr:
+		// If a node under test supports both IPv6 capability
+		// and IPv6 IPv4-mapping capability, we can assume
+		// that the node listens on a wildcard address with an
+		// AF_INET6 socket.
+		if supportsIPv4map && fd.laddr.(*UDPAddr).isWildcard() {
+			if fd.family != syscall.AF_INET6 {
+				t.Fatalf("ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
+			}
+		} else {
+			if fd.family != a.family() {
+				t.Fatalf("ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, a.family())
+			}
+		}
+	default:
+		t.Fatalf("Unexpected protocol address type: %T", a)
+	}
+}
+
+var prohibitionaryDialArgTests = []struct {
+	net  string
+	addr string
+}{
+	{"tcp6", "127.0.0.1"},
+	{"tcp6", "[::ffff:127.0.0.1]"},
+}
+
+func TestProhibitionaryDialArgs(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+	// This test requires both IPv6 and IPv6 IPv4-mapping functionality.
+	if !supportsIPv4map || testing.Short() || !*testExternal {
+		return
+	}
+
+	l, port := usableListenPort(t, "tcp", "[::]")
+	defer l.Close()
+
+	for _, tt := range prohibitionaryDialArgTests {
+		c, err := Dial(tt.net, tt.addr+":"+port)
+		if err == nil {
+			c.Close()
+			t.Fatalf("Dial(%q, %q) should fail", tt.net, tt.addr)
+		}
+	}
+}
+
+func TestWildWildcardListener(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9":
+		t.Skipf("skipping test on %q", runtime.GOOS)
+	}
+
+	if testing.Short() || !*testExternal {
+		t.Skip("skipping test to avoid external network")
+	}
+
+	defer func() {
+		if recover() != nil {
+			t.Fatalf("panicked")
+		}
+	}()
+
+	if ln, err := Listen("tcp", ""); err == nil {
+		ln.Close()
+	}
+	if ln, err := ListenPacket("udp", ""); err == nil {
+		ln.Close()
+	}
+	if ln, err := ListenTCP("tcp", nil); err == nil {
+		ln.Close()
+	}
+	if ln, err := ListenUDP("udp", nil); err == nil {
+		ln.Close()
+	}
+	if ln, err := ListenIP("ip:icmp", nil); err == nil {
+		ln.Close()
+	}
+}
diff --git a/src/pkg/net/unicast_test.go b/src/pkg/net/unicast_test.go
deleted file mode 100644
index e5dd013..0000000
--- a/src/pkg/net/unicast_test.go
+++ /dev/null
@@ -1,538 +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 net
-
-import (
-	"runtime"
-	"syscall"
-	"testing"
-)
-
-var listenerTests = []struct {
-	net      string
-	laddr    string
-	ipv6     bool // test with underlying AF_INET6 socket
-	wildcard bool // test with wildcard address
-}{
-	{net: "tcp", laddr: "", wildcard: true},
-	{net: "tcp", laddr: "0.0.0.0", wildcard: true},
-	{net: "tcp", laddr: "[::ffff:0.0.0.0]", wildcard: true},
-	{net: "tcp", laddr: "[::]", ipv6: true, wildcard: true},
-
-	{net: "tcp", laddr: "127.0.0.1"},
-	{net: "tcp", laddr: "[::ffff:127.0.0.1]"},
-	{net: "tcp", laddr: "[::1]", ipv6: true},
-
-	{net: "tcp4", laddr: "", wildcard: true},
-	{net: "tcp4", laddr: "0.0.0.0", wildcard: true},
-	{net: "tcp4", laddr: "[::ffff:0.0.0.0]", wildcard: true},
-
-	{net: "tcp4", laddr: "127.0.0.1"},
-	{net: "tcp4", laddr: "[::ffff:127.0.0.1]"},
-
-	{net: "tcp6", laddr: "", ipv6: true, wildcard: true},
-	{net: "tcp6", laddr: "[::]", ipv6: true, wildcard: true},
-
-	{net: "tcp6", laddr: "[::1]", ipv6: true},
-}
-
-// TestTCPListener tests both single and double listen to a test
-// listener with same address family, same listening address and
-// same port.
-func TestTCPListener(t *testing.T) {
-	switch runtime.GOOS {
-	case "plan9", "windows":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
-	}
-
-	for _, tt := range listenerTests {
-		if tt.wildcard && (testing.Short() || !*testExternal) {
-			continue
-		}
-		if tt.ipv6 && !supportsIPv6 {
-			continue
-		}
-		l1, port := usableListenPort(t, tt.net, tt.laddr)
-		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
-		l2, err := Listen(tt.net, tt.laddr+":"+port)
-		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
-		fd := l1.(*TCPListener).fd
-		switch fd.family {
-		case syscall.AF_INET:
-			testIPv4UnicastSocketOptions(t, fd)
-		case syscall.AF_INET6:
-			testIPv6UnicastSocketOptions(t, fd)
-		}
-		l1.Close()
-	}
-}
-
-// TestUDPListener tests both single and double listen to a test
-// listener with same address family, same listening address and
-// same port.
-func TestUDPListener(t *testing.T) {
-	switch runtime.GOOS {
-	case "plan9", "windows":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
-	}
-
-	toudpnet := func(net string) string {
-		switch net {
-		case "tcp":
-			return "udp"
-		case "tcp4":
-			return "udp4"
-		case "tcp6":
-			return "udp6"
-		}
-		return "<nil>"
-	}
-
-	for _, tt := range listenerTests {
-		if tt.wildcard && (testing.Short() || !*testExternal) {
-			continue
-		}
-		if tt.ipv6 && !supportsIPv6 {
-			continue
-		}
-		tt.net = toudpnet(tt.net)
-		l1, port := usableListenPacketPort(t, tt.net, tt.laddr)
-		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
-		l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
-		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
-		fd := l1.(*UDPConn).fd
-		switch fd.family {
-		case syscall.AF_INET:
-			testIPv4UnicastSocketOptions(t, fd)
-		case syscall.AF_INET6:
-			testIPv6UnicastSocketOptions(t, fd)
-		}
-		l1.Close()
-	}
-}
-
-func TestSimpleTCPListener(t *testing.T) {
-	switch runtime.GOOS {
-	case "plan9":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
-	}
-
-	for _, tt := range listenerTests {
-		if tt.wildcard && (testing.Short() || !*testExternal) {
-			continue
-		}
-		if tt.ipv6 {
-			continue
-		}
-		l1, port := usableListenPort(t, tt.net, tt.laddr)
-		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
-		l2, err := Listen(tt.net, tt.laddr+":"+port)
-		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
-		l1.Close()
-	}
-}
-
-func TestSimpleUDPListener(t *testing.T) {
-	switch runtime.GOOS {
-	case "plan9":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
-	}
-
-	toudpnet := func(net string) string {
-		switch net {
-		case "tcp":
-			return "udp"
-		case "tcp4":
-			return "udp4"
-		case "tcp6":
-			return "udp6"
-		}
-		return "<nil>"
-	}
-
-	for _, tt := range listenerTests {
-		if tt.wildcard && (testing.Short() || !*testExternal) {
-			continue
-		}
-		if tt.ipv6 {
-			continue
-		}
-		tt.net = toudpnet(tt.net)
-		l1, port := usableListenPacketPort(t, tt.net, tt.laddr)
-		checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
-		l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
-		checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
-		l1.Close()
-	}
-}
-
-var dualStackListenerTests = []struct {
-	net1     string // first listener
-	laddr1   string
-	net2     string // second listener
-	laddr2   string
-	wildcard bool  // test with wildcard address
-	xerr     error // expected error value, nil or other
-}{
-	// Test cases and expected results for the attemping 2nd listen on the same port
-	// 1st listen                2nd listen                 darwin  freebsd  linux  openbsd
-	// ------------------------------------------------------------------------------------
-	// "tcp"  ""                 "tcp"  ""                    -        -       -       - 
-	// "tcp"  ""                 "tcp"  "0.0.0.0"             -        -       -       - 
-	// "tcp"  "0.0.0.0"          "tcp"  ""                    -        -       -       - 
-	// ------------------------------------------------------------------------------------
-	// "tcp"  ""                 "tcp"  "[::]"                -        -       -       ok
-	// "tcp"  "[::]"             "tcp"  ""                    -        -       -       ok
-	// "tcp"  "0.0.0.0"          "tcp"  "[::]"                -        -       -       ok
-	// "tcp"  "[::]"             "tcp"  "0.0.0.0"             -        -       -       ok
-	// "tcp"  "[::ffff:0.0.0.0]" "tcp"  "[::]"                -        -       -       ok
-	// "tcp"  "[::]"             "tcp"  "[::ffff:0.0.0.0]"    -        -       -       ok
-	// ------------------------------------------------------------------------------------
-	// "tcp4" ""                 "tcp6" ""                    ok       ok      ok      ok
-	// "tcp6" ""                 "tcp4" ""                    ok       ok      ok      ok
-	// "tcp4" "0.0.0.0"          "tcp6" "[::]"                ok       ok      ok      ok
-	// "tcp6" "[::]"             "tcp4" "0.0.0.0"             ok       ok      ok      ok
-	// ------------------------------------------------------------------------------------
-	// "tcp"  "127.0.0.1"        "tcp"  "[::1]"               ok       ok      ok      ok
-	// "tcp"  "[::1]"            "tcp"  "127.0.0.1"           ok       ok      ok      ok
-	// "tcp4" "127.0.0.1"        "tcp6" "[::1]"               ok       ok      ok      ok
-	// "tcp6" "[::1]"            "tcp4" "127.0.0.1"           ok       ok      ok      ok
-	//
-	// Platform default configurations:
-	// darwin, kernel version 11.3.0
-	//	net.inet6.ip6.v6only=0 (overridable by sysctl or IPV6_V6ONLY option)
-	// freebsd, kernel version 8.2
-	//	net.inet6.ip6.v6only=1 (overridable by sysctl or IPV6_V6ONLY option)
-	// linux, kernel version 3.0.0
-	//	net.ipv6.bindv6only=0 (overridable by sysctl or IPV6_V6ONLY option)
-	// openbsd, kernel version 5.0
-	//	net.inet6.ip6.v6only=1 (overriding is prohibited)
-
-	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
-	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "0.0.0.0", wildcard: true, xerr: syscall.EADDRINUSE},
-	{net1: "tcp", laddr1: "0.0.0.0", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
-
-	{net1: "tcp", laddr1: "", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
-	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "", wildcard: true, xerr: syscall.EADDRINUSE},
-	{net1: "tcp", laddr1: "0.0.0.0", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
-	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "0.0.0.0", wildcard: true, xerr: syscall.EADDRINUSE},
-	{net1: "tcp", laddr1: "[::ffff:0.0.0.0]", net2: "tcp", laddr2: "[::]", wildcard: true, xerr: syscall.EADDRINUSE},
-	{net1: "tcp", laddr1: "[::]", net2: "tcp", laddr2: "[::ffff:0.0.0.0]", wildcard: true, xerr: syscall.EADDRINUSE},
-
-	{net1: "tcp4", laddr1: "", net2: "tcp6", laddr2: "", wildcard: true},
-	{net1: "tcp6", laddr1: "", net2: "tcp4", laddr2: "", wildcard: true},
-	{net1: "tcp4", laddr1: "0.0.0.0", net2: "tcp6", laddr2: "[::]", wildcard: true},
-	{net1: "tcp6", laddr1: "[::]", net2: "tcp4", laddr2: "0.0.0.0", wildcard: true},
-
-	{net1: "tcp", laddr1: "127.0.0.1", net2: "tcp", laddr2: "[::1]"},
-	{net1: "tcp", laddr1: "[::1]", net2: "tcp", laddr2: "127.0.0.1"},
-	{net1: "tcp4", laddr1: "127.0.0.1", net2: "tcp6", laddr2: "[::1]"},
-	{net1: "tcp6", laddr1: "[::1]", net2: "tcp4", laddr2: "127.0.0.1"},
-}
-
-// TestDualStackTCPListener tests both single and double listen
-// to a test listener with various address families, differnet
-// listening address and same port.
-func TestDualStackTCPListener(t *testing.T) {
-	switch runtime.GOOS {
-	case "plan9":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
-	}
-	if !supportsIPv6 {
-		return
-	}
-
-	for _, tt := range dualStackListenerTests {
-		if tt.wildcard && (testing.Short() || !*testExternal) {
-			continue
-		}
-		switch runtime.GOOS {
-		case "openbsd":
-			if tt.wildcard && differentWildcardAddr(tt.laddr1, tt.laddr2) {
-				tt.xerr = nil
-			}
-		}
-		l1, port := usableListenPort(t, tt.net1, tt.laddr1)
-		laddr := tt.laddr1 + ":" + port
-		checkFirstListener(t, tt.net1, laddr, l1)
-		laddr = tt.laddr2 + ":" + port
-		l2, err := Listen(tt.net2, laddr)
-		checkDualStackSecondListener(t, tt.net2, laddr, tt.xerr, err, l2)
-		l1.Close()
-	}
-}
-
-// TestDualStackUDPListener tests both single and double listen
-// to a test listener with various address families, differnet
-// listening address and same port.
-func TestDualStackUDPListener(t *testing.T) {
-	switch runtime.GOOS {
-	case "plan9":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
-	}
-	if !supportsIPv6 {
-		return
-	}
-
-	toudpnet := func(net string) string {
-		switch net {
-		case "tcp":
-			return "udp"
-		case "tcp4":
-			return "udp4"
-		case "tcp6":
-			return "udp6"
-		}
-		return "<nil>"
-	}
-
-	for _, tt := range dualStackListenerTests {
-		if tt.wildcard && (testing.Short() || !*testExternal) {
-			continue
-		}
-		tt.net1 = toudpnet(tt.net1)
-		tt.net2 = toudpnet(tt.net2)
-		switch runtime.GOOS {
-		case "openbsd":
-			if tt.wildcard && differentWildcardAddr(tt.laddr1, tt.laddr2) {
-				tt.xerr = nil
-			}
-		}
-		l1, port := usableListenPacketPort(t, tt.net1, tt.laddr1)
-		laddr := tt.laddr1 + ":" + port
-		checkFirstListener(t, tt.net1, laddr, l1)
-		laddr = tt.laddr2 + ":" + port
-		l2, err := ListenPacket(tt.net2, laddr)
-		checkDualStackSecondListener(t, tt.net2, laddr, tt.xerr, err, l2)
-		l1.Close()
-	}
-}
-
-func usableListenPort(t *testing.T, net, laddr string) (l Listener, port string) {
-	var nladdr string
-	var err error
-	switch net {
-	default:
-		panic("usableListenPort net=" + net)
-	case "tcp", "tcp4", "tcp6":
-		l, err = Listen(net, laddr+":0")
-		if err != nil {
-			t.Fatalf("Probe Listen(%q, %q) failed: %v", net, laddr, err)
-		}
-		nladdr = l.(*TCPListener).Addr().String()
-	}
-	_, port, err = SplitHostPort(nladdr)
-	if err != nil {
-		t.Fatalf("SplitHostPort failed: %v", err)
-	}
-	return l, port
-}
-
-func usableListenPacketPort(t *testing.T, net, laddr string) (l PacketConn, port string) {
-	var nladdr string
-	var err error
-	switch net {
-	default:
-		panic("usableListenPacketPort net=" + net)
-	case "udp", "udp4", "udp6":
-		l, err = ListenPacket(net, laddr+":0")
-		if err != nil {
-			t.Fatalf("Probe ListenPacket(%q, %q) failed: %v", net, laddr, err)
-		}
-		nladdr = l.(*UDPConn).LocalAddr().String()
-	}
-	_, port, err = SplitHostPort(nladdr)
-	if err != nil {
-		t.Fatalf("SplitHostPort failed: %v", err)
-	}
-	return l, port
-}
-
-func differentWildcardAddr(i, j string) bool {
-	if (i == "" || i == "0.0.0.0" || i == "::ffff:0.0.0.0") && (j == "" || j == "0.0.0.0" || j == "::ffff:0.0.0.0") {
-		return false
-	}
-	if i == "[::]" && j == "[::]" {
-		return false
-	}
-	return true
-}
-
-func checkFirstListener(t *testing.T, net, laddr string, l interface{}) {
-	switch net {
-	case "tcp":
-		fd := l.(*TCPListener).fd
-		checkDualStackAddrFamily(t, net, laddr, fd)
-	case "tcp4":
-		fd := l.(*TCPListener).fd
-		if fd.family != syscall.AF_INET {
-			t.Fatalf("First Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET)
-		}
-	case "tcp6":
-		fd := l.(*TCPListener).fd
-		if fd.family != syscall.AF_INET6 {
-			t.Fatalf("First Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
-		}
-	case "udp":
-		fd := l.(*UDPConn).fd
-		checkDualStackAddrFamily(t, net, laddr, fd)
-	case "udp4":
-		fd := l.(*UDPConn).fd
-		if fd.family != syscall.AF_INET {
-			t.Fatalf("First ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET)
-		}
-	case "udp6":
-		fd := l.(*UDPConn).fd
-		if fd.family != syscall.AF_INET6 {
-			t.Fatalf("First ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
-		}
-	default:
-		t.Fatalf("Unexpected network: %q", net)
-	}
-}
-
-func checkSecondListener(t *testing.T, net, laddr string, err error, l interface{}) {
-	switch net {
-	case "tcp", "tcp4", "tcp6":
-		if err == nil {
-			l.(*TCPListener).Close()
-			t.Fatalf("Second Listen(%q, %q) should fail", net, laddr)
-		}
-	case "udp", "udp4", "udp6":
-		if err == nil {
-			l.(*UDPConn).Close()
-			t.Fatalf("Second ListenPacket(%q, %q) should fail", net, laddr)
-		}
-	default:
-		t.Fatalf("Unexpected network: %q", net)
-	}
-}
-
-func checkDualStackSecondListener(t *testing.T, net, laddr string, xerr, err error, l interface{}) {
-	switch net {
-	case "tcp", "tcp4", "tcp6":
-		if xerr == nil && err != nil || xerr != nil && err == nil {
-			t.Fatalf("Second Listen(%q, %q) returns %v, expected %v", net, laddr, err, xerr)
-		}
-		l.(*TCPListener).Close()
-	case "udp", "udp4", "udp6":
-		if xerr == nil && err != nil || xerr != nil && err == nil {
-			t.Fatalf("Second ListenPacket(%q, %q) returns %v, expected %v", net, laddr, err, xerr)
-		}
-		l.(*UDPConn).Close()
-	default:
-		t.Fatalf("Unexpected network: %q", net)
-	}
-}
-
-func checkDualStackAddrFamily(t *testing.T, net, laddr string, fd *netFD) {
-	switch a := fd.laddr.(type) {
-	case *TCPAddr:
-		// If a node under test supports both IPv6 capability
-		// and IPv6 IPv4-mapping capability, we can assume
-		// that the node listens on a wildcard address with an
-		// AF_INET6 socket.
-		if supportsIPv4map && fd.laddr.(*TCPAddr).isWildcard() {
-			if fd.family != syscall.AF_INET6 {
-				t.Fatalf("Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
-			}
-		} else {
-			if fd.family != a.family() {
-				t.Fatalf("Listen(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, a.family())
-			}
-		}
-	case *UDPAddr:
-		// If a node under test supports both IPv6 capability
-		// and IPv6 IPv4-mapping capability, we can assume
-		// that the node listens on a wildcard address with an
-		// AF_INET6 socket.
-		if supportsIPv4map && fd.laddr.(*UDPAddr).isWildcard() {
-			if fd.family != syscall.AF_INET6 {
-				t.Fatalf("ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, syscall.AF_INET6)
-			}
-		} else {
-			if fd.family != a.family() {
-				t.Fatalf("ListenPacket(%q, %q) returns address family %v, expected %v", net, laddr, fd.family, a.family())
-			}
-		}
-	default:
-		t.Fatalf("Unexpected protocol address type: %T", a)
-	}
-}
-
-func testIPv4UnicastSocketOptions(t *testing.T, fd *netFD) {
-	_, err := ipv4TOS(fd)
-	if err != nil {
-		t.Fatalf("ipv4TOS failed: %v", err)
-	}
-	err = setIPv4TOS(fd, 1)
-	if err != nil {
-		t.Fatalf("setIPv4TOS failed: %v", err)
-	}
-	_, err = ipv4TTL(fd)
-	if err != nil {
-		t.Fatalf("ipv4TTL failed: %v", err)
-	}
-	err = setIPv4TTL(fd, 1)
-	if err != nil {
-		t.Fatalf("setIPv4TTL failed: %v", err)
-	}
-}
-
-func testIPv6UnicastSocketOptions(t *testing.T, fd *netFD) {
-	_, err := ipv6TrafficClass(fd)
-	if err != nil {
-		t.Fatalf("ipv6TrafficClass failed: %v", err)
-	}
-	err = setIPv6TrafficClass(fd, 1)
-	if err != nil {
-		t.Fatalf("setIPv6TrafficClass failed: %v", err)
-	}
-	_, err = ipv6HopLimit(fd)
-	if err != nil {
-		t.Fatalf("ipv6HopLimit failed: %v", err)
-	}
-	err = setIPv6HopLimit(fd, 1)
-	if err != nil {
-		t.Fatalf("setIPv6HopLimit failed: %v", err)
-	}
-}
-
-var prohibitionaryDialArgTests = []struct {
-	net  string
-	addr string
-}{
-	{"tcp6", "127.0.0.1"},
-	{"tcp6", "[::ffff:127.0.0.1]"},
-}
-
-func TestProhibitionaryDialArgs(t *testing.T) {
-	switch runtime.GOOS {
-	case "plan9":
-		t.Logf("skipping test on %q", runtime.GOOS)
-		return
-	}
-	// This test requires both IPv6 and IPv6 IPv4-mapping functionality.
-	if !supportsIPv4map || testing.Short() || !*testExternal {
-		return
-	}
-
-	l, port := usableListenPort(t, "tcp", "[::]")
-	defer l.Close()
-
-	for _, tt := range prohibitionaryDialArgTests {
-		c, err := Dial(tt.net, tt.addr+":"+port)
-		if err == nil {
-			c.Close()
-			t.Fatalf("Dial(%q, %q) should fail", tt.net, tt.addr)
-		}
-	}
-}
diff --git a/src/pkg/net/unix_test.go b/src/pkg/net/unix_test.go
new file mode 100644
index 0000000..2eaabe8
--- /dev/null
+++ b/src/pkg/net/unix_test.go
@@ -0,0 +1,144 @@
+// 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 !plan9,!windows
+
+package net
+
+import (
+	"bytes"
+	"os"
+	"reflect"
+	"runtime"
+	"syscall"
+	"testing"
+	"time"
+)
+
+func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
+	addr := testUnixAddr()
+	la, err := ResolveUnixAddr("unixgram", addr)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c, err := ListenUnixgram("unixgram", la)
+	if err != nil {
+		t.Fatalf("ListenUnixgram failed: %v", err)
+	}
+	defer func() {
+		c.Close()
+		os.Remove(addr)
+	}()
+
+	off := make(chan bool)
+	data := [5]byte{1, 2, 3, 4, 5}
+
+	go func() {
+		defer func() { off <- true }()
+		s, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
+		if err != nil {
+			t.Errorf("syscall.Socket failed: %v", err)
+			return
+		}
+		defer syscall.Close(s)
+		rsa := &syscall.SockaddrUnix{Name: addr}
+		if err := syscall.Sendto(s, data[:], 0, rsa); err != nil {
+			t.Errorf("syscall.Sendto failed: %v", err)
+			return
+		}
+	}()
+
+	<-off
+	b := make([]byte, 64)
+	c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+	n, from, err := c.ReadFrom(b)
+	if err != nil {
+		t.Errorf("UnixConn.ReadFrom failed: %v", err)
+		return
+	}
+	if from != nil {
+		t.Errorf("neighbor address is %v", from)
+	}
+	if !bytes.Equal(b[:n], data[:]) {
+		t.Errorf("got %v, want %v", b[:n], data[:])
+		return
+	}
+}
+
+func TestReadUnixgramWithZeroBytesBuffer(t *testing.T) {
+	// issue 4352: Recvfrom failed with "address family not
+	// supported by protocol family" if zero-length buffer provided
+
+	addr := testUnixAddr()
+	la, err := ResolveUnixAddr("unixgram", addr)
+	if err != nil {
+		t.Fatalf("ResolveUnixAddr failed: %v", err)
+	}
+	c, err := ListenUnixgram("unixgram", la)
+	if err != nil {
+		t.Fatalf("ListenUnixgram failed: %v", err)
+	}
+	defer func() {
+		c.Close()
+		os.Remove(addr)
+	}()
+
+	off := make(chan bool)
+	go func() {
+		defer func() { off <- true }()
+		c, err := DialUnix("unixgram", nil, la)
+		if err != nil {
+			t.Errorf("DialUnix failed: %v", err)
+			return
+		}
+		defer c.Close()
+		if _, err := c.Write([]byte{1, 2, 3, 4, 5}); err != nil {
+			t.Errorf("UnixConn.Write failed: %v", err)
+			return
+		}
+	}()
+
+	<-off
+	c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+	var peer Addr
+	if _, peer, err = c.ReadFrom(nil); err != nil {
+		t.Errorf("UnixConn.ReadFrom failed: %v", err)
+		return
+	}
+	if peer != nil {
+		t.Errorf("peer adddress is %v", peer)
+	}
+}
+
+func TestUnixAutobind(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("skipping: autobind is linux only")
+	}
+
+	laddr := &UnixAddr{Name: "", Net: "unixgram"}
+	c1, err := ListenUnixgram("unixgram", laddr)
+	if err != nil {
+		t.Fatalf("ListenUnixgram failed: %v", err)
+	}
+	defer c1.Close()
+
+	// retrieve the autobind address
+	autoAddr := c1.LocalAddr().(*UnixAddr)
+	if len(autoAddr.Name) <= 1 {
+		t.Fatalf("Invalid autobind address: %v", autoAddr)
+	}
+	if autoAddr.Name[0] != '@' {
+		t.Fatalf("Invalid autobind address: %v", autoAddr)
+	}
+
+	c2, err := DialUnix("unixgram", nil, autoAddr)
+	if err != nil {
+		t.Fatalf("DialUnix failed: %v", err)
+	}
+	defer c2.Close()
+
+	if !reflect.DeepEqual(c1.LocalAddr(), c2.RemoteAddr()) {
+		t.Fatalf("Expected autobind address %v, got %v", c1.LocalAddr(), c2.RemoteAddr())
+	}
+}
diff --git a/src/pkg/net/unixsock_plan9.go b/src/pkg/net/unixsock_plan9.go
index 7b4ae6b..00a0be5 100644
--- a/src/pkg/net/unixsock_plan9.go
+++ b/src/pkg/net/unixsock_plan9.go
@@ -7,100 +7,135 @@
 package net
 
 import (
+	"os"
 	"syscall"
 	"time"
 )
 
-// UnixConn is an implementation of the Conn interface
-// for connections to Unix domain sockets.
-type UnixConn bool
-
-// Implementation of the Conn interface - see Conn for documentation.
+// UnixConn is an implementation of the Conn interface for connections
+// to Unix domain sockets.
+type UnixConn struct {
+	conn
+}
 
-// Read implements the Conn Read method.
-func (c *UnixConn) Read(b []byte) (n int, err error) {
-	return 0, syscall.EPLAN9
+// ReadFromUnix reads a packet from c, copying the payload into b.  It
+// returns the number of bytes copied into b and the source address of
+// the packet.
+//
+// ReadFromUnix can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
+	return 0, nil, syscall.EPLAN9
 }
 
-// Write implements the Conn Write method.
-func (c *UnixConn) Write(b []byte) (n int, err error) {
-	return 0, syscall.EPLAN9
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
+	return 0, nil, syscall.EPLAN9
 }
 
-// Close closes the Unix domain connection.
-func (c *UnixConn) Close() error {
-	return syscall.EPLAN9
+// ReadMsgUnix reads a packet from c, copying the payload into b and
+// the associated out-of-band data into oob.  It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet, and the source address of the packet.
+func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
+	return 0, 0, 0, nil, syscall.EPLAN9
 }
 
-// LocalAddr returns the local network address, a *UnixAddr.
-// Unlike in other protocols, LocalAddr is usually nil for dialed connections.
-func (c *UnixConn) LocalAddr() Addr {
-	return nil
+// WriteToUnix writes a packet to addr via c, copying the payload from b.
+//
+// WriteToUnix can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
+func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
+	return 0, syscall.EPLAN9
 }
 
-// RemoteAddr returns the remote network address, a *UnixAddr.
-// Unlike in other protocols, RemoteAddr is usually nil for connections
-// accepted by a listener.
-func (c *UnixConn) RemoteAddr() Addr {
-	return nil
+// WriteTo implements the PacketConn WriteTo method.
+func (c *UnixConn) WriteTo(b []byte, addr Addr) (int, error) {
+	return 0, syscall.EPLAN9
 }
 
-// SetDeadline implements the Conn SetDeadline method.
-func (c *UnixConn) SetDeadline(t time.Time) error {
-	return syscall.EPLAN9
+// WriteMsgUnix writes a packet to addr via c, copying the payload
+// from b and the associated out-of-band data from oob.  It returns
+// the number of payload and out-of-band bytes written.
+func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
+	return 0, 0, syscall.EPLAN9
 }
 
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *UnixConn) SetReadDeadline(t time.Time) error {
+// CloseRead shuts down the reading side of the Unix domain connection.
+// Most callers should just use Close.
+func (c *UnixConn) CloseRead() error {
 	return syscall.EPLAN9
 }
 
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *UnixConn) SetWriteDeadline(t time.Time) error {
+// CloseWrite shuts down the writing side of the Unix domain connection.
+// Most callers should just use Close.
+func (c *UnixConn) CloseWrite() error {
 	return syscall.EPLAN9
 }
 
-// ReadFrom implements the PacketConn ReadFrom method.
-func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
-	err = syscall.EPLAN9
-	return
+// DialUnix connects to the remote address raddr on the network net,
+// which must be "unix", "unixgram" or "unixpacket".  If laddr is not
+// nil, it is used as the local address for the connection.
+func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
+	return dialUnix(net, laddr, raddr, noDeadline)
 }
 
-// WriteTo implements the PacketConn WriteTo method.
-func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
-	err = syscall.EPLAN9
-	return
+func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
+	return nil, syscall.EPLAN9
 }
 
-// DialUnix connects to the remote address raddr on the network net,
-// which must be "unix" or "unixgram".  If laddr is not nil, it is used
-// as the local address for the connection.
-func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err error) {
+// UnixListener is a Unix domain socket listener.  Clients should
+// typically use variables of type Listener instead of assuming Unix
+// domain sockets.
+type UnixListener struct{}
+
+// ListenUnix announces on the Unix domain socket laddr and returns a
+// Unix listener.  The network net must be "unix" or "unixpacket".
+func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
 	return nil, syscall.EPLAN9
 }
 
-// UnixListener is a Unix domain socket listener.
-// Clients should typically use variables of type Listener
-// instead of assuming Unix domain sockets.
-type UnixListener bool
-
-// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
-// Net must be "unix" (stream sockets).
-func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err error) {
+// AcceptUnix accepts the next incoming call and returns the new
+// connection and the remote address.
+func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
 	return nil, syscall.EPLAN9
 }
 
-// Accept implements the Accept method in the Listener interface;
-// it waits for the next call and returns a generic Conn.
-func (l *UnixListener) Accept() (c Conn, err error) {
+// Accept implements the Accept method in the Listener interface; it
+// waits for the next call and returns a generic Conn.
+func (l *UnixListener) Accept() (Conn, error) {
 	return nil, syscall.EPLAN9
 }
 
-// Close stops listening on the Unix address.
-// Already accepted connections are not closed.
+// Close stops listening on the Unix address.  Already accepted
+// connections are not closed.
 func (l *UnixListener) Close() error {
 	return syscall.EPLAN9
 }
 
 // Addr returns the listener's network address.
 func (l *UnixListener) Addr() Addr { return nil }
+
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *UnixListener) SetDeadline(t time.Time) error {
+	return syscall.EPLAN9
+}
+
+// File returns a copy of the underlying os.File, set to blocking
+// mode.  It is the caller's responsibility to close f when finished.
+// Closing l does not affect f, and closing f does not affect l.
+func (l *UnixListener) File() (*os.File, error) {
+	return nil, syscall.EPLAN9
+}
+
+// ListenUnixgram listens for incoming Unix datagram packets addressed
+// to the local address laddr.  The returned connection c's ReadFrom
+// and WriteTo methods can be used to receive and send packets with
+// per-packet addressing.  The network net must be "unixgram".
+func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
+	return nil, syscall.EPLAN9
+}
diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go
index 57d784c..6d6ce3f 100644
--- a/src/pkg/net/unixsock_posix.go
+++ b/src/pkg/net/unixsock_posix.go
@@ -9,29 +9,27 @@
 package net
 
 import (
+	"errors"
 	"os"
 	"syscall"
 	"time"
 )
 
-func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err error) {
+func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.Time) (*netFD, error) {
 	var sotype int
 	switch net {
-	default:
-		return nil, UnknownNetworkError(net)
 	case "unix":
 		sotype = syscall.SOCK_STREAM
 	case "unixgram":
 		sotype = syscall.SOCK_DGRAM
 	case "unixpacket":
 		sotype = syscall.SOCK_SEQPACKET
+	default:
+		return nil, UnknownNetworkError(net)
 	}
 
 	var la, ra syscall.Sockaddr
 	switch mode {
-	default:
-		panic("unixSocket mode " + mode)
-
 	case "dial":
 		if laddr != nil {
 			la = &syscall.SockaddrUnix{Name: laddr.Name}
@@ -41,15 +39,10 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err
 		} else if sotype != syscall.SOCK_DGRAM || laddr == nil {
 			return nil, &OpError{Op: mode, Net: net, Err: errMissingAddress}
 		}
-
 	case "listen":
-		if laddr == nil {
-			return nil, &OpError{mode, net, nil, errMissingAddress}
-		}
 		la = &syscall.SockaddrUnix{Name: laddr.Name}
-		if raddr != nil {
-			return nil, &OpError{Op: mode, Net: net, Addr: raddr, Err: &AddrError{Err: "unexpected remote address", Addr: raddr.String()}}
-		}
+	default:
+		return nil, errors.New("unknown mode: " + mode)
 	}
 
 	f := sockaddrToUnix
@@ -59,15 +52,16 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err
 		f = sockaddrToUnixpacket
 	}
 
-	fd, err = socket(net, syscall.AF_UNIX, sotype, 0, false, la, ra, f)
+	fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, la, ra, deadline, f)
 	if err != nil {
-		goto Error
+		goto error
 	}
 	return fd, nil
 
-Error:
+error:
 	addr := raddr
-	if mode == "listen" {
+	switch mode {
+	case "listen":
 		addr = laddr
 	}
 	return nil, &OpError{Op: mode, Net: net, Addr: addr, Err: err}
@@ -108,110 +102,21 @@ func sotypeToNet(sotype int) string {
 	return ""
 }
 
-// UnixConn is an implementation of the Conn interface
-// for connections to Unix domain sockets.
+// UnixConn is an implementation of the Conn interface for connections
+// to Unix domain sockets.
 type UnixConn struct {
-	fd *netFD
-}
-
-func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{fd} }
-
-func (c *UnixConn) ok() bool { return c != nil && c.fd != nil }
-
-// Implementation of the Conn interface - see Conn for documentation.
-
-// Read implements the Conn Read method.
-func (c *UnixConn) Read(b []byte) (n int, err error) {
-	if !c.ok() {
-		return 0, syscall.EINVAL
-	}
-	return c.fd.Read(b)
-}
-
-// Write implements the Conn Write method.
-func (c *UnixConn) Write(b []byte) (n int, err error) {
-	if !c.ok() {
-		return 0, syscall.EINVAL
-	}
-	return c.fd.Write(b)
-}
-
-// Close closes the Unix domain connection.
-func (c *UnixConn) Close() error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return c.fd.Close()
-}
-
-// LocalAddr returns the local network address, a *UnixAddr.
-// Unlike in other protocols, LocalAddr is usually nil for dialed connections.
-func (c *UnixConn) LocalAddr() Addr {
-	if !c.ok() {
-		return nil
-	}
-	return c.fd.laddr
+	conn
 }
 
-// RemoteAddr returns the remote network address, a *UnixAddr.
-// Unlike in other protocols, RemoteAddr is usually nil for connections
-// accepted by a listener.
-func (c *UnixConn) RemoteAddr() Addr {
-	if !c.ok() {
-		return nil
-	}
-	return c.fd.raddr
-}
+func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
 
-// SetDeadline implements the Conn SetDeadline method.
-func (c *UnixConn) SetDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setDeadline(c.fd, t)
-}
-
-// SetReadDeadline implements the Conn SetReadDeadline method.
-func (c *UnixConn) SetReadDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setReadDeadline(c.fd, t)
-}
-
-// SetWriteDeadline implements the Conn SetWriteDeadline method.
-func (c *UnixConn) SetWriteDeadline(t time.Time) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setWriteDeadline(c.fd, t)
-}
-
-// SetReadBuffer sets the size of the operating system's
-// receive buffer associated with the connection.
-func (c *UnixConn) SetReadBuffer(bytes int) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setReadBuffer(c.fd, bytes)
-}
-
-// SetWriteBuffer sets the size of the operating system's
-// transmit buffer associated with the connection.
-func (c *UnixConn) SetWriteBuffer(bytes int) error {
-	if !c.ok() {
-		return syscall.EINVAL
-	}
-	return setWriteBuffer(c.fd, bytes)
-}
-
-// ReadFromUnix reads a packet from c, copying the payload into b.
-// It returns the number of bytes copied into b and the source address
-// of the packet.
+// ReadFromUnix reads a packet from c, copying the payload into b.  It
+// returns the number of bytes copied into b and the source address of
+// the packet.
 //
-// ReadFromUnix can be made to time out and return
-// an error with Timeout() == true after a fixed time limit;
-// see SetDeadline and SetReadDeadline.
+// ReadFromUnix can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
 func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
 	if !c.ok() {
 		return 0, nil, syscall.EINVAL
@@ -219,26 +124,46 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
 	n, sa, err := c.fd.ReadFrom(b)
 	switch sa := sa.(type) {
 	case *syscall.SockaddrUnix:
-		addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
+		if sa.Name != "" {
+			addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
+		}
 	}
 	return
 }
 
 // ReadFrom implements the PacketConn ReadFrom method.
-func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
+func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
 	if !c.ok() {
 		return 0, nil, syscall.EINVAL
 	}
-	n, uaddr, err := c.ReadFromUnix(b)
-	return n, uaddr.toAddr(), err
+	n, addr, err := c.ReadFromUnix(b)
+	return n, addr.toAddr(), err
+}
+
+// ReadMsgUnix reads a packet from c, copying the payload into b and
+// the associated out-of-band data into oob.  It returns the number of
+// bytes copied into b, the number of bytes copied into oob, the flags
+// that were set on the packet, and the source address of the packet.
+func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
+	if !c.ok() {
+		return 0, 0, 0, nil, syscall.EINVAL
+	}
+	n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
+	switch sa := sa.(type) {
+	case *syscall.SockaddrUnix:
+		if sa.Name != "" {
+			addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
+		}
+	}
+	return
 }
 
 // WriteToUnix writes a packet to addr via c, copying the payload from b.
 //
-// WriteToUnix can be made to time out and return
-// an error with Timeout() == true after a fixed time limit;
-// see SetDeadline and SetWriteDeadline.
-// On packet-oriented connections, write timeouts are rare.
+// WriteToUnix can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetWriteDeadline.  On packet-oriented connections, write timeouts
+// are rare.
 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) {
 	if !c.ok() {
 		return 0, syscall.EINVAL
@@ -262,26 +187,9 @@ func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
 	return c.WriteToUnix(b, a)
 }
 
-// ReadMsgUnix reads a packet from c, copying the payload into b
-// and the associated out-of-band data into oob.
-// It returns the number of bytes copied into b, the number of
-// bytes copied into oob, the flags that were set on the packet,
-// and the source address of the packet.
-func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
-	if !c.ok() {
-		return 0, 0, 0, nil, syscall.EINVAL
-	}
-	n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
-	switch sa := sa.(type) {
-	case *syscall.SockaddrUnix:
-		addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
-	}
-	return
-}
-
-// WriteMsgUnix writes a packet to addr via c, copying the payload from b
-// and the associated out-of-band data from oob.  It returns the number
-// of payload and out-of-band bytes written.
+// WriteMsgUnix writes a packet to addr via c, copying the payload
+// from b and the associated out-of-band data from oob.  It returns
+// the number of payload and out-of-band bytes written.
 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
 	if !c.ok() {
 		return 0, 0, syscall.EINVAL
@@ -296,40 +204,64 @@ func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err
 	return c.fd.WriteMsg(b, oob, nil)
 }
 
-// File returns a copy of the underlying os.File, set to blocking mode.
-// 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 (c *UnixConn) File() (f *os.File, err error) { return c.fd.dup() }
+// CloseRead shuts down the reading side of the Unix domain connection.
+// Most callers should just use Close.
+func (c *UnixConn) CloseRead() error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.CloseRead()
+}
+
+// CloseWrite shuts down the writing side of the Unix domain connection.
+// Most callers should just use Close.
+func (c *UnixConn) CloseWrite() error {
+	if !c.ok() {
+		return syscall.EINVAL
+	}
+	return c.fd.CloseWrite()
+}
 
 // DialUnix connects to the remote address raddr on the network net,
-// which must be "unix" or "unixgram".  If laddr is not nil, it is used
-// as the local address for the connection.
+// which must be "unix", "unixgram" or "unixpacket".  If laddr is not
+// nil, it is used as the local address for the connection.
 func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
-	fd, err := unixSocket(net, laddr, raddr, "dial")
+	return dialUnix(net, laddr, raddr, noDeadline)
+}
+
+func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
+	switch net {
+	case "unix", "unixgram", "unixpacket":
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	fd, err := unixSocket(net, laddr, raddr, "dial", deadline)
 	if err != nil {
 		return nil, err
 	}
 	return newUnixConn(fd), nil
 }
 
-// UnixListener is a Unix domain socket listener.
-// Clients should typically use variables of type Listener
-// instead of assuming Unix domain sockets.
+// UnixListener is a Unix domain socket listener.  Clients should
+// typically use variables of type Listener instead of assuming Unix
+// domain sockets.
 type UnixListener struct {
 	fd   *netFD
 	path string
 }
 
-// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
-// Net must be "unix" (stream sockets).
+// ListenUnix announces on the Unix domain socket laddr and returns a
+// Unix listener.  The network net must be "unix" or "unixpacket".
 func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
-	if net != "unix" && net != "unixgram" && net != "unixpacket" {
+	switch net {
+	case "unix", "unixpacket":
+	default:
 		return nil, UnknownNetworkError(net)
 	}
-	if laddr != nil {
-		laddr = &UnixAddr{laddr.Name, net} // make our own copy
+	if laddr == nil {
+		return nil, &OpError{"listen", net, nil, errMissingAddress}
 	}
-	fd, err := unixSocket(net, laddr, nil, "listen")
+	fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
 	if err != nil {
 		return nil, err
 	}
@@ -341,8 +273,8 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
 	return &UnixListener{fd, laddr.Name}, nil
 }
 
-// AcceptUnix accepts the next incoming call and returns the new connection
-// and the remote address.
+// AcceptUnix accepts the next incoming call and returns the new
+// connection and the remote address.
 func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
 	if l == nil || l.fd == nil {
 		return nil, syscall.EINVAL
@@ -355,8 +287,8 @@ func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
 	return c, nil
 }
 
-// Accept implements the Accept method in the Listener interface;
-// it waits for the next call and returns a generic Conn.
+// Accept implements the Accept method in the Listener interface; it
+// waits for the next call and returns a generic Conn.
 func (l *UnixListener) Accept() (c Conn, err error) {
 	c1, err := l.AcceptUnix()
 	if err != nil {
@@ -365,8 +297,8 @@ func (l *UnixListener) Accept() (c Conn, err error) {
 	return c1, nil
 }
 
-// Close stops listening on the Unix address.
-// Already accepted connections are not closed.
+// Close stops listening on the Unix address.  Already accepted
+// connections are not closed.
 func (l *UnixListener) Close() error {
 	if l == nil || l.fd == nil {
 		return syscall.EINVAL
@@ -385,9 +317,7 @@ func (l *UnixListener) Close() error {
 	if l.path[0] != '@' {
 		syscall.Unlink(l.path)
 	}
-	err := l.fd.Close()
-	l.fd = nil
-	return err
+	return l.fd.Close()
 }
 
 // Addr returns the listener's network address.
@@ -402,16 +332,16 @@ func (l *UnixListener) SetDeadline(t time.Time) (err error) {
 	return setDeadline(l.fd, t)
 }
 
-// File returns a copy of the underlying os.File, set to blocking mode.
-// It is the caller's responsibility to close f when finished.
+// File returns a copy of the underlying os.File, set to blocking
+// mode.  It is the caller's responsibility to close f when finished.
 // Closing l does not affect f, and closing f does not affect l.
 func (l *UnixListener) File() (f *os.File, err error) { return l.fd.dup() }
 
-// ListenUnixgram listens for incoming Unix datagram packets addressed to the
-// local address laddr.  The returned connection c's ReadFrom
-// and WriteTo methods can be used to receive and send UDP
-// packets with per-packet addressing.  The network net must be "unixgram".
-func ListenUnixgram(net string, laddr *UnixAddr) (*UDPConn, error) {
+// ListenUnixgram listens for incoming Unix datagram packets addressed
+// to the local address laddr.  The returned connection c's ReadFrom
+// and WriteTo methods can be used to receive and send packets with
+// per-packet addressing.  The network net must be "unixgram".
+func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
 	switch net {
 	case "unixgram":
 	default:
@@ -420,9 +350,9 @@ func ListenUnixgram(net string, laddr *UnixAddr) (*UDPConn, error) {
 	if laddr == nil {
 		return nil, &OpError{"listen", net, nil, errMissingAddress}
 	}
-	fd, err := unixSocket(net, laddr, nil, "listen")
+	fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
 	if err != nil {
 		return nil, err
 	}
-	return newUDPConn(fd), nil
+	return newUnixConn(fd), nil
 }
diff --git a/src/pkg/net/url/url.go b/src/pkg/net/url/url.go
index 17bf0d3..a39964e 100644
--- a/src/pkg/net/url/url.go
+++ b/src/pkg/net/url/url.go
@@ -7,7 +7,9 @@
 package url
 
 import (
+	"bytes"
 	"errors"
+	"sort"
 	"strconv"
 	"strings"
 )
@@ -218,11 +220,18 @@ func escape(s string, mode encoding) string {
 //
 //	scheme:opaque[?query][#fragment]
 //
+// Note that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.
+// A consequence is that it is impossible to tell which slashes in the Path were
+// slashes in the raw URL and which were %2f. This distinction is rarely important,
+// but when it is a client must use other routines to parse the raw URL or construct
+// the parsed URL. For example, an HTTP server can consult req.RequestURI, and
+// an HTTP client can use URL{Host: "example.com", Opaque: "//example.com/Go%2f"}
+// instead of URL{Host: "example.com", Path: "/Go/"}.
 type URL struct {
 	Scheme   string
 	Opaque   string    // encoded opaque data
 	User     *Userinfo // username and password information
-	Host     string
+	Host     string    // host or host:port
 	Path     string
 	RawQuery string // encoded query values, without '?'
 	Fragment string // fragment for references, without '#'
@@ -359,11 +368,17 @@ func parse(rawurl string, viaRequest bool) (url *URL, err error) {
 	}
 	url = new(URL)
 
+	if rawurl == "*" {
+		url.Path = "*"
+		return
+	}
+
 	// Split off possible leading "http:", "mailto:", etc.
 	// Cannot contain escaped characters.
 	if url.Scheme, rest, err = getscheme(rawurl); err != nil {
 		goto Error
 	}
+	url.Scheme = strings.ToLower(url.Scheme)
 
 	rest, url.RawQuery = split(rest, '?', true)
 
@@ -379,7 +394,7 @@ func parse(rawurl string, viaRequest bool) (url *URL, err error) {
 		}
 	}
 
-	if (url.Scheme != "" || !viaRequest) && strings.HasPrefix(rest, "//") && !strings.HasPrefix(rest, "///") {
+	if (url.Scheme != "" || !viaRequest && !strings.HasPrefix(rest, "///")) && strings.HasPrefix(rest, "//") {
 		var authority string
 		authority, rest = split(rest[2:], '/', false)
 		url.User, url.Host, err = parseAuthority(authority)
@@ -427,30 +442,35 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
 
 // String reassembles the URL into a valid URL string.
 func (u *URL) String() string {
-	// TODO: Rewrite to use bytes.Buffer
-	result := ""
+	var buf bytes.Buffer
 	if u.Scheme != "" {
-		result += u.Scheme + ":"
+		buf.WriteString(u.Scheme)
+		buf.WriteByte(':')
 	}
 	if u.Opaque != "" {
-		result += u.Opaque
+		buf.WriteString(u.Opaque)
 	} else {
-		if u.Host != "" || u.User != nil {
-			result += "//"
+		if u.Scheme != "" || u.Host != "" || u.User != nil {
+			buf.WriteString("//")
 			if u := u.User; u != nil {
-				result += u.String() + "@"
+				buf.WriteString(u.String())
+				buf.WriteByte('@')
+			}
+			if h := u.Host; h != "" {
+				buf.WriteString(h)
 			}
-			result += u.Host
 		}
-		result += escape(u.Path, encodePath)
+		buf.WriteString(escape(u.Path, encodePath))
 	}
 	if u.RawQuery != "" {
-		result += "?" + u.RawQuery
+		buf.WriteByte('?')
+		buf.WriteString(u.RawQuery)
 	}
 	if u.Fragment != "" {
-		result += "#" + escape(u.Fragment, encodeFragment)
+		buf.WriteByte('#')
+		buf.WriteString(escape(u.Fragment, encodeFragment))
 	}
-	return result
+	return buf.String()
 }
 
 // Values maps a string key to a list of values.
@@ -519,12 +539,16 @@ func parseQuery(m Values, query string) (err error) {
 		}
 		key, err1 := QueryUnescape(key)
 		if err1 != nil {
-			err = err1
+			if err == nil {
+				err = err1
+			}
 			continue
 		}
 		value, err1 = QueryUnescape(value)
 		if err1 != nil {
-			err = err1
+			if err == nil {
+				err = err1
+			}
 			continue
 		}
 		m[key] = append(m[key], value)
@@ -538,14 +562,24 @@ func (v Values) Encode() string {
 	if v == nil {
 		return ""
 	}
-	parts := make([]string, 0, len(v)) // will be large enough for most uses
-	for k, vs := range v {
+	var buf bytes.Buffer
+	keys := make([]string, 0, len(v))
+	for k := range v {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+	for _, k := range keys {
+		vs := v[k]
 		prefix := QueryEscape(k) + "="
 		for _, v := range vs {
-			parts = append(parts, prefix+QueryEscape(v))
+			if buf.Len() > 0 {
+				buf.WriteByte('&')
+			}
+			buf.WriteString(prefix)
+			buf.WriteString(QueryEscape(v))
 		}
 	}
-	return strings.Join(parts, "&")
+	return buf.String()
 }
 
 // resolvePath applies special path segments from refs and applies
@@ -556,23 +590,33 @@ func resolvePath(basepath string, refpath string) string {
 	if len(base) == 0 {
 		base = []string{""}
 	}
+
+	rm := true
 	for idx, ref := range refs {
 		switch {
 		case ref == ".":
-			base[len(base)-1] = ""
+			if idx == 0 {
+				base[len(base)-1] = ""
+				rm = true
+			} else {
+				rm = false
+			}
 		case ref == "..":
 			newLen := len(base) - 1
 			if newLen < 1 {
 				newLen = 1
 			}
 			base = base[0:newLen]
-			base[len(base)-1] = ""
+			if rm {
+				base[len(base)-1] = ""
+			}
 		default:
 			if idx == 0 || base[len(base)-1] == "" {
 				base[len(base)-1] = ref
 			} else {
 				base = append(base, ref)
 			}
+			rm = false
 		}
 	}
 	return strings.Join(base, "/")
@@ -650,6 +694,10 @@ func (u *URL) RequestURI() string {
 		if result == "" {
 			result = "/"
 		}
+	} else {
+		if strings.HasPrefix(result, "//") {
+			result = u.Scheme + ":" + result
+		}
 	}
 	if u.RawQuery != "" {
 		result += "?" + u.RawQuery
diff --git a/src/pkg/net/url/url_test.go b/src/pkg/net/url/url_test.go
index 75e8abe..4c4f406 100644
--- a/src/pkg/net/url/url_test.go
+++ b/src/pkg/net/url/url_test.go
@@ -7,6 +7,7 @@ package url
 import (
 	"fmt"
 	"reflect"
+	"strings"
 	"testing"
 )
 
@@ -121,14 +122,14 @@ var urltests = []URLTest{
 		},
 		"http:%2f%2fwww.google.com/?q=go+language",
 	},
-	// non-authority
+	// non-authority with path
 	{
 		"mailto:/webmaster at golang.org",
 		&URL{
 			Scheme: "mailto",
 			Path:   "/webmaster at golang.org",
 		},
-		"",
+		"mailto:///webmaster@golang.org", // unfortunate compromise
 	},
 	// non-authority
 	{
@@ -241,6 +242,24 @@ var urltests = []URLTest{
 		},
 		"http://www.google.com/?q=go+language#foo&bar",
 	},
+	{
+		"file:///home/adg/rabbits",
+		&URL{
+			Scheme: "file",
+			Host:   "",
+			Path:   "/home/adg/rabbits",
+		},
+		"file:///home/adg/rabbits",
+	},
+	// case-insensitive scheme
+	{
+		"MaIlTo:webmaster at golang.org",
+		&URL{
+			Scheme: "mailto",
+			Opaque: "webmaster at golang.org",
+		},
+		"mailto:webmaster at golang.org",
+	},
 }
 
 // more useful string for debugging than fmt's struct printer
@@ -270,13 +289,37 @@ func DoTest(t *testing.T, parse func(string) (*URL, error), name string, tests [
 	}
 }
 
+func BenchmarkString(b *testing.B) {
+	b.StopTimer()
+	b.ReportAllocs()
+	for _, tt := range urltests {
+		u, err := Parse(tt.in)
+		if err != nil {
+			b.Errorf("Parse(%q) returned error %s", tt.in, err)
+			continue
+		}
+		if tt.roundtrip == "" {
+			continue
+		}
+		b.StartTimer()
+		var g string
+		for i := 0; i < b.N; i++ {
+			g = u.String()
+		}
+		b.StopTimer()
+		if w := tt.roundtrip; g != w {
+			b.Errorf("Parse(%q).String() == %q, want %q", tt.in, g, w)
+		}
+	}
+}
+
 func TestParse(t *testing.T) {
 	DoTest(t, Parse, "Parse", urltests)
 }
 
 const pathThatLooksSchemeRelative = "//not.a.user at not.a.host/just/a/path"
 
-var parseRequestUrlTests = []struct {
+var parseRequestURLTests = []struct {
 	url           string
 	expectedValid bool
 }{
@@ -288,10 +331,11 @@ var parseRequestUrlTests = []struct {
 	{"//not.a.user@%66%6f%6f.com/just/a/path/also", true},
 	{"foo.html", false},
 	{"../dir/", false},
+	{"*", true},
 }
 
 func TestParseRequestURI(t *testing.T) {
-	for _, test := range parseRequestUrlTests {
+	for _, test := range parseRequestURLTests {
 		_, err := ParseRequestURI(test.url)
 		valid := err == nil
 		if valid != test.expectedValid {
@@ -453,20 +497,24 @@ func TestEscape(t *testing.T) {
 //}
 
 type EncodeQueryTest struct {
-	m         Values
-	expected  string
-	expected1 string
+	m        Values
+	expected string
 }
 
 var encodeQueryTests = []EncodeQueryTest{
-	{nil, "", ""},
-	{Values{"q": {"puppies"}, "oe": {"utf8"}}, "q=puppies&oe=utf8", "oe=utf8&q=puppies"},
-	{Values{"q": {"dogs", "&", "7"}}, "q=dogs&q=%26&q=7", "q=dogs&q=%26&q=7"},
+	{nil, ""},
+	{Values{"q": {"puppies"}, "oe": {"utf8"}}, "oe=utf8&q=puppies"},
+	{Values{"q": {"dogs", "&", "7"}}, "q=dogs&q=%26&q=7"},
+	{Values{
+		"a": {"a1", "a2", "a3"},
+		"b": {"b1", "b2", "b3"},
+		"c": {"c1", "c2", "c3"},
+	}, "a=a1&a=a2&a=a3&b=b1&b=b2&b=b3&c=c1&c=c2&c=c3"},
 }
 
 func TestEncodeQuery(t *testing.T) {
 	for _, tt := range encodeQueryTests {
-		if q := tt.m.Encode(); q != tt.expected && q != tt.expected1 {
+		if q := tt.m.Encode(); q != tt.expected {
 			t.Errorf(`EncodeQuery(%+v) = %q, want %q`, tt.m, q, tt.expected)
 		}
 	}
@@ -531,6 +579,15 @@ var resolveReferenceTests = []struct {
 	{"http://foo.com/bar/baz", "../../../../../quux", "http://foo.com/quux"},
 	{"http://foo.com/bar", "..", "http://foo.com/"},
 	{"http://foo.com/bar/baz", "./..", "http://foo.com/"},
+	// ".." in the middle (issue 3560)
+	{"http://foo.com/bar/baz", "quux/dotdot/../tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/../tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/.././tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/./../tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/dotdot/././../../tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/dotdot/./.././../tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/dotdot/dotdot/./../../.././././tail", "http://foo.com/bar/quux/tail"},
+	{"http://foo.com/bar/baz", "quux/./dotdot/../dotdot/../dot/./tail/..", "http://foo.com/bar/quux/dot"},
 
 	// "." and ".." in the base aren't special
 	{"http://foo.com/dot/./dotdot/../foo/bar", "../baz", "http://foo.com/dot/./dotdot/../baz"},
@@ -741,6 +798,24 @@ var requritests = []RequestURITest{
 		},
 		"/a%20b",
 	},
+	// golang.org/issue/4860 variant 1
+	{
+		&URL{
+			Scheme: "http",
+			Host:   "example.com",
+			Opaque: "/%2F/%2F/",
+		},
+		"/%2F/%2F/",
+	},
+	// golang.org/issue/4860 variant 2
+	{
+		&URL{
+			Scheme: "http",
+			Host:   "example.com",
+			Opaque: "//other.example.com/%2F/%2F/",
+		},
+		"http://other.example.com/%2F/%2F/",
+	},
 	{
 		&URL{
 			Scheme:   "http",
@@ -775,3 +850,13 @@ func TestRequestURI(t *testing.T) {
 		}
 	}
 }
+
+func TestParseFailure(t *testing.T) {
+	// Test that the first parse error is returned.
+	const url = "%gh&%ij"
+	_, err := ParseQuery(url)
+	errStr := fmt.Sprint(err)
+	if !strings.Contains(errStr, "%gh") {
+		t.Errorf(`ParseQuery(%q) returned error %q, want something containing %q"`, url, errStr, "%gh")
+	}
+}
diff --git a/src/pkg/os/dir_plan9.go b/src/pkg/os/dir_plan9.go
index 7fa4c7f..8195c02 100644
--- a/src/pkg/os/dir_plan9.go
+++ b/src/pkg/os/dir_plan9.go
@@ -5,15 +5,11 @@
 package os
 
 import (
-	"errors"
 	"io"
 	"syscall"
 )
 
-var errShortStat = errors.New("short stat message")
-var errBadStat = errors.New("bad stat message format")
-
-func (file *File) readdir(n int) (fi []FileInfo, err error) {
+func (file *File) readdir(n int) ([]FileInfo, error) {
 	// If this file has no dirinfo, create one.
 	if file.dirinfo == nil {
 		file.dirinfo = new(dirInfo)
@@ -24,44 +20,47 @@ func (file *File) readdir(n int) (fi []FileInfo, err error) {
 		size = 100
 		n = -1
 	}
-	result := make([]FileInfo, 0, size) // Empty with room to grow.
+	fi := make([]FileInfo, 0, size) // Empty with room to grow.
 	for n != 0 {
-		// Refill the buffer if necessary
+		// Refill the buffer if necessary.
 		if d.bufp >= d.nbuf {
-			d.bufp = 0
-			var e error
-			d.nbuf, e = file.Read(d.buf[:])
-			if e != nil && e != io.EOF {
-				return result, &PathError{"readdir", file.name, e}
-			}
-			if e == io.EOF {
-				break
+			nb, err := file.Read(d.buf[:])
+
+			// Update the buffer state before checking for errors.
+			d.bufp, d.nbuf = 0, nb
+
+			if err != nil {
+				if err == io.EOF {
+					break
+				}
+				return fi, &PathError{"readdir", file.name, err}
 			}
-			if d.nbuf < syscall.STATFIXLEN {
-				return result, &PathError{"readdir", file.name, errShortStat}
+			if nb < syscall.STATFIXLEN {
+				return fi, &PathError{"readdir", file.name, syscall.ErrShortStat}
 			}
 		}
 
-		// Get a record from buffer
-		m, _ := gbit16(d.buf[d.bufp:])
-		m += 2
+		// Get a record from the buffer.
+		b := d.buf[d.bufp:]
+		m := int(uint16(b[0])|uint16(b[1])<<8) + 2
 		if m < syscall.STATFIXLEN {
-			return result, &PathError{"readdir", file.name, errShortStat}
+			return fi, &PathError{"readdir", file.name, syscall.ErrShortStat}
 		}
-		dir, e := UnmarshalDir(d.buf[d.bufp : d.bufp+int(m)])
-		if e != nil {
-			return result, &PathError{"readdir", file.name, e}
+
+		dir, err := syscall.UnmarshalDir(b[:m])
+		if err != nil {
+			return fi, &PathError{"readdir", file.name, err}
 		}
-		result = append(result, fileInfoFromStat(dir))
+		fi = append(fi, fileInfoFromStat(dir))
 
-		d.bufp += int(m)
+		d.bufp += m
 		n--
 	}
 
-	if n >= 0 && len(result) == 0 {
-		return result, io.EOF
+	if n >= 0 && len(fi) == 0 {
+		return fi, io.EOF
 	}
-	return result, nil
+	return fi, nil
 }
 
 func (file *File) readdirnames(n int) (names []string, err error) {
@@ -72,205 +71,3 @@ func (file *File) readdirnames(n int) (names []string, err error) {
 	}
 	return
 }
-
-type Dir struct {
-	// system-modified data
-	Type uint16 // server type
-	Dev  uint32 // server subtype
-	// file data
-	Qid    Qid    // unique id from server
-	Mode   uint32 // permissions
-	Atime  uint32 // last read time
-	Mtime  uint32 // last write time
-	Length uint64 // file length
-	Name   string // last element of path
-	Uid    string // owner name
-	Gid    string // group name
-	Muid   string // last modifier name
-}
-
-type Qid struct {
-	Path uint64 // the file server's unique identification for the file
-	Vers uint32 // version number for given Path
-	Type uint8  // the type of the file (syscall.QTDIR for example)
-}
-
-var nullDir = Dir{
-	^uint16(0),
-	^uint32(0),
-	Qid{^uint64(0), ^uint32(0), ^uint8(0)},
-	^uint32(0),
-	^uint32(0),
-	^uint32(0),
-	^uint64(0),
-	"",
-	"",
-	"",
-	"",
-}
-
-// Null assigns members of d with special "don't care" values indicating
-// they should not be written by syscall.Wstat. 
-func (d *Dir) Null() {
-	*d = nullDir
-}
-
-// pdir appends a 9P Stat message based on the contents of Dir d to a byte slice b.
-func pdir(b []byte, d *Dir) []byte {
-	n := len(b)
-	b = pbit16(b, 0) // length, filled in later	
-	b = pbit16(b, d.Type)
-	b = pbit32(b, d.Dev)
-	b = pqid(b, d.Qid)
-	b = pbit32(b, d.Mode)
-	b = pbit32(b, d.Atime)
-	b = pbit32(b, d.Mtime)
-	b = pbit64(b, d.Length)
-	b = pstring(b, d.Name)
-	b = pstring(b, d.Uid)
-	b = pstring(b, d.Gid)
-	b = pstring(b, d.Muid)
-	pbit16(b[0:n], uint16(len(b)-(n+2)))
-	return b
-}
-
-// UnmarshalDir reads a 9P Stat message from a 9P protocol message stored in b,
-// returning the corresponding Dir struct.
-func UnmarshalDir(b []byte) (d *Dir, err error) {
-	n := uint16(0)
-	n, b = gbit16(b)
-
-	if int(n) != len(b) {
-		return nil, errBadStat
-	}
-
-	d = new(Dir)
-	d.Type, b = gbit16(b)
-	d.Dev, b = gbit32(b)
-	d.Qid, b = gqid(b)
-	d.Mode, b = gbit32(b)
-	d.Atime, b = gbit32(b)
-	d.Mtime, b = gbit32(b)
-	d.Length, b = gbit64(b)
-	d.Name, b = gstring(b)
-	d.Uid, b = gstring(b)
-	d.Gid, b = gstring(b)
-	d.Muid, b = gstring(b)
-
-	if len(b) != 0 {
-		return nil, errBadStat
-	}
-
-	return d, nil
-}
-
-// gqid reads the qid part of a 9P Stat message from a 9P protocol message stored in b,
-// returning the corresponding Qid struct and the remaining slice of b.
-func gqid(b []byte) (Qid, []byte) {
-	var q Qid
-	q.Path, b = gbit64(b)
-	q.Vers, b = gbit32(b)
-	q.Type, b = gbit8(b)
-	return q, b
-}
-
-// pqid appends a Qid struct q to a 9P message b.
-func pqid(b []byte, q Qid) []byte {
-	b = pbit64(b, q.Path)
-	b = pbit32(b, q.Vers)
-	b = pbit8(b, q.Type)
-	return b
-}
-
-// gbit8 reads a byte-sized numeric value from a 9P protocol message stored in b,
-// returning the value and the remaining slice of b.
-func gbit8(b []byte) (uint8, []byte) {
-	return uint8(b[0]), b[1:]
-}
-
-// gbit16 reads a 16-bit numeric value from a 9P protocol message stored in b,
-// returning the value and the remaining slice of b.
-func gbit16(b []byte) (uint16, []byte) {
-	return uint16(b[0]) | uint16(b[1])<<8, b[2:]
-}
-
-// gbit32 reads a 32-bit numeric value from a 9P protocol message stored in b,
-// returning the value and the remaining slice of b.
-func gbit32(b []byte) (uint32, []byte) {
-	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
-}
-
-// gbit64 reads a 64-bit numeric value from a 9P protocol message stored in b,
-// returning the value and the remaining slice of b.
-func gbit64(b []byte) (uint64, []byte) {
-	lo, b := gbit32(b)
-	hi, b := gbit32(b)
-	return uint64(hi)<<32 | uint64(lo), b
-}
-
-// gstring reads a string from a 9P protocol message stored in b,
-// returning the value as a Go string and the remaining slice of b.
-func gstring(b []byte) (string, []byte) {
-	n, b := gbit16(b)
-	return string(b[0:n]), b[n:]
-}
-
-// pbit8 appends a byte-sized numeric value x to a 9P message b.
-func pbit8(b []byte, x uint8) []byte {
-	n := len(b)
-	if n+1 > cap(b) {
-		nb := make([]byte, n, 100+2*cap(b))
-		copy(nb, b)
-		b = nb
-	}
-	b = b[0 : n+1]
-	b[n] = x
-	return b
-}
-
-// pbit16 appends a 16-bit numeric value x to a 9P message b.
-func pbit16(b []byte, x uint16) []byte {
-	n := len(b)
-	if n+2 > cap(b) {
-		nb := make([]byte, n, 100+2*cap(b))
-		copy(nb, b)
-		b = nb
-	}
-	b = b[0 : n+2]
-	b[n] = byte(x)
-	b[n+1] = byte(x >> 8)
-	return b
-}
-
-// pbit32 appends a 32-bit numeric value x to a 9P message b.
-func pbit32(b []byte, x uint32) []byte {
-	n := len(b)
-	if n+4 > cap(b) {
-		nb := make([]byte, n, 100+2*cap(b))
-		copy(nb, b)
-		b = nb
-	}
-	b = b[0 : n+4]
-	b[n] = byte(x)
-	b[n+1] = byte(x >> 8)
-	b[n+2] = byte(x >> 16)
-	b[n+3] = byte(x >> 24)
-	return b
-}
-
-// pbit64 appends a 64-bit numeric value x to a 9P message b.
-func pbit64(b []byte, x uint64) []byte {
-	b = pbit32(b, uint32(x))
-	b = pbit32(b, uint32(x>>32))
-	return b
-}
-
-// pstring appends a Go string s to a 9P message b.
-func pstring(b []byte, s string) []byte {
-	if len(s) >= 1<<16 {
-		panic(errors.New("string too long"))
-	}
-	b = pbit16(b, uint16(len(s)))
-	b = append(b, s...)
-	return b
-}
diff --git a/src/pkg/os/doc.go b/src/pkg/os/doc.go
index 6a531e0..2cc1753 100644
--- a/src/pkg/os/doc.go
+++ b/src/pkg/os/doc.go
@@ -79,6 +79,8 @@ func (p *ProcessState) Sys() interface{} {
 // SysUsage returns system-dependent resource usage information about
 // the exited process.  Convert it to the appropriate underlying
 // type, such as *syscall.Rusage on Unix, to access its contents.
+// (On Unix, *syscall.Rusage matches struct rusage as defined in the
+// getrusage(2) manual page.)
 func (p *ProcessState) SysUsage() interface{} {
 	return p.sysUsage()
 }
@@ -89,7 +91,7 @@ func Hostname() (name string, err error) {
 }
 
 // Readdir reads the contents of the directory associated with file and
-// returns an array of up to n FileInfo values, as would be returned
+// returns a slice of up to n FileInfo values, as would be returned
 // by Lstat, in directory order. Subsequent calls on the same file will yield
 // further FileInfos.
 //
diff --git a/src/pkg/os/env.go b/src/pkg/os/env.go
index eb265f2..db7fc72 100644
--- a/src/pkg/os/env.go
+++ b/src/pkg/os/env.go
@@ -9,7 +9,7 @@ package os
 import "syscall"
 
 // Expand replaces ${var} or $var in the string based on the mapping function.
-// Invocations of undefined variables are replaced with the empty string.
+// For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv).
 func Expand(s string, mapping func(string) string) string {
 	buf := make([]byte, 0, 2*len(s))
 	// ${} is all ASCII, so bytes are fine for this operation.
diff --git a/src/pkg/os/env_unix_test.go b/src/pkg/os/env_unix_test.go
new file mode 100644
index 0000000..7eb4dc0
--- /dev/null
+++ b/src/pkg/os/env_unix_test.go
@@ -0,0 +1,30 @@
+// 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 freebsd linux netbsd openbsd
+
+package os_test
+
+import (
+	. "os"
+	"testing"
+)
+
+var setenvEinvalTests = []struct {
+	k, v string
+}{
+	{"", ""},      // empty key
+	{"k=v", ""},   // '=' in key
+	{"\x00", ""},  // '\x00' in key
+	{"k", "\x00"}, // '\x00' in value
+}
+
+func TestSetenvUnixEinval(t *testing.T) {
+	for _, tt := range setenvEinvalTests {
+		err := Setenv(tt.k, tt.v)
+		if err == nil {
+			t.Errorf(`Setenv(%q, %q) == nil, want error`, tt.k, tt.v)
+		}
+	}
+}
diff --git a/src/pkg/os/error.go b/src/pkg/os/error.go
index b88e494..a7977ff 100644
--- a/src/pkg/os/error.go
+++ b/src/pkg/os/error.go
@@ -43,7 +43,7 @@ func NewSyscallError(syscall string, err error) error {
 	return &SyscallError{syscall, err}
 }
 
-// IsExist returns whether the error is known to report that a file or directory 
+// IsExist returns whether the error is known to report that a file or directory
 // already exists. It is satisfied by ErrExist as well as some syscall errors.
 func IsExist(err error) bool {
 	return isExist(err)
diff --git a/src/pkg/os/error_plan9.go b/src/pkg/os/error_plan9.go
index 3c9dfb0..85260c8 100644
--- a/src/pkg/os/error_plan9.go
+++ b/src/pkg/os/error_plan9.go
@@ -5,21 +5,36 @@
 package os
 
 func isExist(err error) bool {
-	if pe, ok := err.(*PathError); ok {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
 		err = pe.Err
 	}
 	return contains(err.Error(), " exists")
 }
 
 func isNotExist(err error) bool {
-	if pe, ok := err.(*PathError); ok {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
 		err = pe.Err
 	}
 	return contains(err.Error(), "does not exist")
 }
 
 func isPermission(err error) bool {
-	if pe, ok := err.(*PathError); ok {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
 		err = pe.Err
 	}
 	return contains(err.Error(), "permission denied")
diff --git a/src/pkg/os/error_posix.go b/src/pkg/os/error_posix.go
index 1685c1f..81b626a 100644
--- a/src/pkg/os/error_posix.go
+++ b/src/pkg/os/error_posix.go
@@ -9,21 +9,36 @@ package os
 import "syscall"
 
 func isExist(err error) bool {
-	if pe, ok := err.(*PathError); ok {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
 		err = pe.Err
 	}
 	return err == syscall.EEXIST || err == ErrExist
 }
 
 func isNotExist(err error) bool {
-	if pe, ok := err.(*PathError); ok {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
 		err = pe.Err
 	}
 	return err == syscall.ENOENT || err == ErrNotExist
 }
 
 func isPermission(err error) bool {
-	if pe, ok := err.(*PathError); ok {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
 		err = pe.Err
 	}
 	return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission
diff --git a/src/pkg/os/error_test.go b/src/pkg/os/error_test.go
index 42f846f..02ed235 100644
--- a/src/pkg/os/error_test.go
+++ b/src/pkg/os/error_test.go
@@ -79,3 +79,54 @@ func checkErrorPredicate(predName string, pred func(error) bool, err error) stri
 	}
 	return ""
 }
+
+var isExistTests = []struct {
+	err   error
+	is    bool
+	isnot bool
+}{
+	{&os.PathError{Err: os.ErrInvalid}, false, false},
+	{&os.PathError{Err: os.ErrPermission}, false, false},
+	{&os.PathError{Err: os.ErrExist}, true, false},
+	{&os.PathError{Err: os.ErrNotExist}, false, true},
+	{&os.LinkError{Err: os.ErrInvalid}, false, false},
+	{&os.LinkError{Err: os.ErrPermission}, false, false},
+	{&os.LinkError{Err: os.ErrExist}, true, false},
+	{&os.LinkError{Err: os.ErrNotExist}, false, true},
+	{nil, false, false},
+}
+
+func TestIsExist(t *testing.T) {
+	for _, tt := range isExistTests {
+		if is := os.IsExist(tt.err); is != tt.is {
+			t.Errorf("os.IsExist(%T %v) = %v, want %v", tt.err, tt.err, is, tt.is)
+		}
+		if isnot := os.IsNotExist(tt.err); isnot != tt.isnot {
+			t.Errorf("os.IsNotExist(%T %v) = %v, want %v", tt.err, tt.err, isnot, tt.isnot)
+		}
+	}
+}
+
+func TestErrPathNUL(t *testing.T) {
+	f, err := ioutil.TempFile("", "_Go_ErrPathNUL\x00")
+	if err == nil {
+		f.Close()
+		t.Fatal("TempFile should have failed")
+	}
+	f, err = ioutil.TempFile("", "_Go_ErrPathNUL")
+	if err != nil {
+		t.Fatalf("open ErrPathNUL tempfile: %s", err)
+	}
+	defer os.Remove(f.Name())
+	defer f.Close()
+	f2, err := os.OpenFile(f.Name(), os.O_RDWR, 0600)
+	if err != nil {
+		t.Fatalf("open ErrPathNUL: %s", err)
+	}
+	f2.Close()
+	f2, err = os.OpenFile(f.Name()+"\x00", os.O_RDWR, 0600)
+	if err == nil {
+		f2.Close()
+		t.Fatal("Open should have failed")
+	}
+}
diff --git a/src/pkg/os/error_windows.go b/src/pkg/os/error_windows.go
index fbb0d4f..83db6c0 100644
--- a/src/pkg/os/error_windows.go
+++ b/src/pkg/os/error_windows.go
@@ -7,7 +7,12 @@ package os
 import "syscall"
 
 func isExist(err error) bool {
-	if pe, ok := err.(*PathError); ok {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
 		err = pe.Err
 	}
 	return err == syscall.ERROR_ALREADY_EXISTS ||
@@ -15,7 +20,12 @@ func isExist(err error) bool {
 }
 
 func isNotExist(err error) bool {
-	if pe, ok := err.(*PathError); ok {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
 		err = pe.Err
 	}
 	return err == syscall.ERROR_FILE_NOT_FOUND ||
@@ -23,7 +33,12 @@ func isNotExist(err error) bool {
 }
 
 func isPermission(err error) bool {
-	if pe, ok := err.(*PathError); ok {
+	switch pe := err.(type) {
+	case nil:
+		return false
+	case *PathError:
+		err = pe.Err
+	case *LinkError:
 		err = pe.Err
 	}
 	return err == syscall.ERROR_ACCESS_DENIED || err == ErrPermission
diff --git a/src/pkg/os/error_windows_test.go b/src/pkg/os/error_windows_test.go
new file mode 100644
index 0000000..3e6504f
--- /dev/null
+++ b/src/pkg/os/error_windows_test.go
@@ -0,0 +1,47 @@
+// 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 os_test
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"testing"
+)
+
+func TestErrIsExistAfterRename(t *testing.T) {
+	dir, err := ioutil.TempDir("", "go-build")
+	if err != nil {
+		t.Fatalf("Create temp directory: %v", err)
+	}
+	defer os.RemoveAll(dir)
+
+	src := filepath.Join(dir, "src")
+	dest := filepath.Join(dir, "dest")
+
+	f, err := os.Create(src)
+	if err != nil {
+		t.Fatalf("Create file %v: %v", src, err)
+	}
+	f.Close()
+	err = os.Rename(src, dest)
+	if err != nil {
+		t.Fatalf("Rename %v to %v: %v", src, dest, err)
+	}
+
+	f, err = os.Create(src)
+	if err != nil {
+		t.Fatalf("Create file %v: %v", src, err)
+	}
+	f.Close()
+	err = os.Rename(src, dest)
+	if err == nil {
+		t.Fatal("Rename should have failed")
+	}
+	if s := checkErrorPredicate("os.IsExist", os.IsExist, err); s != "" {
+		t.Fatal(s)
+		return
+	}
+}
diff --git a/src/pkg/os/exec.go b/src/pkg/os/exec.go
index 531b87c..5aea309 100644
--- a/src/pkg/os/exec.go
+++ b/src/pkg/os/exec.go
@@ -6,6 +6,7 @@ package os
 
 import (
 	"runtime"
+	"sync/atomic"
 	"syscall"
 )
 
@@ -13,7 +14,7 @@ import (
 type Process struct {
 	Pid    int
 	handle uintptr
-	done   bool // process has been successfully waited on
+	isdone uint32 // process has been successfully waited on, non zero if true
 }
 
 func newProcess(pid int, handle uintptr) *Process {
@@ -22,6 +23,14 @@ func newProcess(pid int, handle uintptr) *Process {
 	return p
 }
 
+func (p *Process) setDone() {
+	atomic.StoreUint32(&p.isdone, 1)
+}
+
+func (p *Process) done() bool {
+	return atomic.LoadUint32(&p.isdone) > 0
+}
+
 // ProcAttr holds the attributes that will be applied to a new process
 // started by StartProcess.
 type ProcAttr struct {
@@ -54,14 +63,6 @@ type Signal interface {
 	Signal() // to distinguish from other Stringers
 }
 
-// The only signal values guaranteed to be present on all systems
-// are Interrupt (send the process an interrupt) and
-// Kill (force the process to exit).
-var (
-	Interrupt Signal = syscall.SIGINT
-	Kill      Signal = syscall.SIGKILL
-)
-
 // Getpid returns the process id of the caller.
 func Getpid() int { return syscall.Getpid() }
 
diff --git a/src/pkg/os/exec/exec.go b/src/pkg/os/exec/exec.go
index 9a8e181..8368491 100644
--- a/src/pkg/os/exec/exec.go
+++ b/src/pkg/os/exec/exec.go
@@ -16,7 +16,7 @@ import (
 	"syscall"
 )
 
-// Error records the name of a binary that failed to be be executed
+// Error records the name of a binary that failed to be executed
 // and the reason it failed.
 type Error struct {
 	Name string
@@ -37,7 +37,7 @@ type Cmd struct {
 
 	// Args holds command line arguments, including the command as Args[0].
 	// If the Args field is empty or nil, Run uses {Path}.
-	// 
+	//
 	// In typical use, both Path and Args are set by calling Command.
 	Args []string
 
@@ -143,6 +143,9 @@ func (c *Cmd) argv() []string {
 func (c *Cmd) stdin() (f *os.File, err error) {
 	if c.Stdin == nil {
 		f, err = os.Open(os.DevNull)
+		if err != nil {
+			return
+		}
 		c.closeAfterStart = append(c.closeAfterStart, f)
 		return
 	}
@@ -182,6 +185,9 @@ func (c *Cmd) stderr() (f *os.File, err error) {
 func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) {
 	if w == nil {
 		f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
+		if err != nil {
+			return
+		}
 		c.closeAfterStart = append(c.closeAfterStart, f)
 		return
 	}
diff --git a/src/pkg/os/exec/exec_test.go b/src/pkg/os/exec/exec_test.go
index 52f4bce..611ac02 100644
--- a/src/pkg/os/exec/exec_test.go
+++ b/src/pkg/os/exec/exec_test.go
@@ -14,6 +14,7 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"os"
+	"path/filepath"
 	"runtime"
 	"strconv"
 	"strings"
@@ -83,10 +84,16 @@ func TestNoExistBinary(t *testing.T) {
 
 func TestExitStatus(t *testing.T) {
 	// Test that exit values are returned correctly
-	err := helperCommand("exit", "42").Run()
+	cmd := helperCommand("exit", "42")
+	err := cmd.Run()
+	want := "exit status 42"
+	switch runtime.GOOS {
+	case "plan9":
+		want = fmt.Sprintf("exit status: '%s %d: 42'", filepath.Base(cmd.Path), cmd.ProcessState.Pid())
+	}
 	if werr, ok := err.(*ExitError); ok {
-		if s, e := werr.Error(), "exit status 42"; s != e {
-			t.Errorf("from exit 42 got exit %q, want %q", s, e)
+		if s := werr.Error(); s != want {
+			t.Errorf("from exit 42 got exit %q, want %q", s, want)
 		}
 	} else {
 		t.Fatalf("expected *ExitError from exit 42; got %T: %v", err, err)
@@ -144,18 +151,36 @@ func TestPipes(t *testing.T) {
 	check("Wait", err)
 }
 
+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
+}
+
 func TestExtraFiles(t *testing.T) {
 	if runtime.GOOS == "windows" {
-		t.Logf("no operating system support; skipping")
-		return
+		t.Skip("no operating system support; skipping")
 	}
 
 	// Ensure that file descriptors have not already been leaked into
 	// our environment.
-	for fd := os.Stderr.Fd() + 1; fd <= 101; fd++ {
-		err := os.NewFile(fd, "").Close()
-		if err == nil {
-			t.Logf("Something already leaked - closed fd %d", fd)
+	if !testedAlreadyLeaked {
+		testedAlreadyLeaked = true
+		for fd := basefds(); fd <= 101; fd++ {
+			err := os.NewFile(fd, "").Close()
+			if err == nil {
+				t.Logf("Something already leaked - closed fd %d", fd)
+			}
 		}
 	}
 
@@ -167,6 +192,18 @@ func TestExtraFiles(t *testing.T) {
 	}
 	defer ln.Close()
 
+	// Make sure duplicated fds don't leak to the child.
+	f, err := ln.(*net.TCPListener).File()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer f.Close()
+	ln2, err := net.FileListener(f)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln2.Close()
+
 	// Force TLS root certs to be loaded (which might involve
 	// cgo), to make sure none of that potential C code leaks fds.
 	ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -193,13 +230,65 @@ func TestExtraFiles(t *testing.T) {
 	}
 
 	c := helperCommand("read3")
+	var stdout, stderr bytes.Buffer
+	c.Stdout = &stdout
+	c.Stderr = &stderr
 	c.ExtraFiles = []*os.File{tf}
-	bs, err := c.CombinedOutput()
+	err = c.Run()
 	if err != nil {
-		t.Fatalf("CombinedOutput: %v; output %q", err, bs)
+		t.Fatalf("Run: %v; stdout %q, stderr %q", err, stdout.Bytes(), stderr.Bytes())
 	}
-	if string(bs) != text {
-		t.Errorf("got %q; want %q", string(bs), text)
+	if stdout.String() != text {
+		t.Errorf("got stdout %q, stderr %q; want %q on stdout", stdout.String(), stderr.String(), text)
+	}
+}
+
+func TestExtraFilesRace(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		t.Skip("no operating system support; skipping")
+	}
+	listen := func() net.Listener {
+		ln, err := net.Listen("tcp", "127.0.0.1:0")
+		if err != nil {
+			t.Fatal(err)
+		}
+		return ln
+	}
+	listenerFile := func(ln net.Listener) *os.File {
+		f, err := ln.(*net.TCPListener).File()
+		if err != nil {
+			t.Fatal(err)
+		}
+		return f
+	}
+	runCommand := func(c *Cmd, out chan<- string) {
+		bout, err := c.CombinedOutput()
+		if err != nil {
+			out <- "ERROR:" + err.Error()
+		} else {
+			out <- string(bout)
+		}
+	}
+
+	for i := 0; i < 10; i++ {
+		la := listen()
+		ca := helperCommand("describefiles")
+		ca.ExtraFiles = []*os.File{listenerFile(la)}
+		lb := listen()
+		cb := helperCommand("describefiles")
+		cb.ExtraFiles = []*os.File{listenerFile(lb)}
+		ares := make(chan string)
+		bres := make(chan string)
+		go runCommand(ca, ares)
+		go runCommand(cb, bres)
+		if got, want := <-ares, fmt.Sprintf("fd3: listener %s\n", la.Addr()); got != want {
+			t.Errorf("iteration %d, process A got:\n%s\nwant:\n%s\n", i, got, want)
+		}
+		if got, want := <-bres, fmt.Sprintf("fd3: listener %s\n", lb.Addr()); got != want {
+			t.Errorf("iteration %d, process B got:\n%s\nwant:\n%s\n", i, got, want)
+		}
+		la.Close()
+		lb.Close()
 	}
 }
 
@@ -287,10 +376,15 @@ func TestHelperProcess(*testing.T) {
 			// TODO(bradfitz): broken? Sometimes.
 			// http://golang.org/issue/2603
 			// Skip this additional part of the test for now.
+		case "netbsd":
+			// TODO(jsing): This currently fails on NetBSD due to
+			// the cloned file descriptors that result from opening
+			// /dev/urandom.
+			// http://golang.org/issue/3955
 		default:
 			// Now verify that there are no other open fds.
 			var files []*os.File
-			for wantfd := os.Stderr.Fd() + 2; wantfd <= 100; wantfd++ {
+			for wantfd := basefds() + 1; wantfd <= 100; wantfd++ {
 				f, err := os.Open(os.Args[0])
 				if err != nil {
 					fmt.Printf("error opening file with expected fd %d: %v", wantfd, err)
@@ -314,10 +408,20 @@ func TestHelperProcess(*testing.T) {
 		// what we do with fd3 as long as we refer to it;
 		// closing it is the easy choice.
 		fd3.Close()
-		os.Stderr.Write(bs)
+		os.Stdout.Write(bs)
 	case "exit":
 		n, _ := strconv.Atoi(args[0])
 		os.Exit(n)
+	case "describefiles":
+		for fd := uintptr(3); fd < 25; fd++ {
+			f := os.NewFile(fd, fmt.Sprintf("fd-%d", fd))
+			ln, err := net.FileListener(f)
+			if err == nil {
+				fmt.Printf("fd%d: listener %s\n", fd, ln.Addr())
+				ln.Close()
+			}
+		}
+		os.Exit(0)
 	default:
 		fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
 		os.Exit(2)
diff --git a/src/pkg/os/exec/lp_plan9.go b/src/pkg/os/exec/lp_plan9.go
index 0e229e0..6846a35 100644
--- a/src/pkg/os/exec/lp_plan9.go
+++ b/src/pkg/os/exec/lp_plan9.go
@@ -8,7 +8,6 @@ import (
 	"errors"
 	"os"
 	"strings"
-	"syscall"
 )
 
 // ErrNotFound is the error resulting if a path search failed to find an executable file.
@@ -22,7 +21,7 @@ func findExecutable(file string) error {
 	if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
 		return nil
 	}
-	return syscall.EPERM
+	return os.ErrPermission
 }
 
 // LookPath searches for an executable binary named file
diff --git a/src/pkg/os/exec/lp_unix.go b/src/pkg/os/exec/lp_unix.go
index 2163221..1d1ec07 100644
--- a/src/pkg/os/exec/lp_unix.go
+++ b/src/pkg/os/exec/lp_unix.go
@@ -42,6 +42,9 @@ func LookPath(file string) (string, error) {
 		return "", &Error{file, err}
 	}
 	pathenv := os.Getenv("PATH")
+	if pathenv == "" {
+		return "", &Error{file, ErrNotFound}
+	}
 	for _, dir := range strings.Split(pathenv, ":") {
 		if dir == "" {
 			// Unix shell semantics: path element "" means "."
diff --git a/src/pkg/os/exec/lp_unix_test.go b/src/pkg/os/exec/lp_unix_test.go
new file mode 100644
index 0000000..625d784
--- /dev/null
+++ b/src/pkg/os/exec/lp_unix_test.go
@@ -0,0 +1,55 @@
+// 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 freebsd linux netbsd openbsd
+
+package exec
+
+import (
+	"io/ioutil"
+	"os"
+	"testing"
+)
+
+func TestLookPathUnixEmptyPath(t *testing.T) {
+	tmp, err := ioutil.TempDir("", "TestLookPathUnixEmptyPath")
+	if err != nil {
+		t.Fatal("TempDir failed: ", err)
+	}
+	defer os.RemoveAll(tmp)
+	wd, err := os.Getwd()
+	if err != nil {
+		t.Fatal("Getwd failed: ", err)
+	}
+	err = os.Chdir(tmp)
+	if err != nil {
+		t.Fatal("Chdir failed: ", err)
+	}
+	defer os.Chdir(wd)
+
+	f, err := os.OpenFile("exec_me", os.O_CREATE|os.O_EXCL, 0700)
+	if err != nil {
+		t.Fatal("OpenFile failed: ", err)
+	}
+	err = f.Close()
+	if err != nil {
+		t.Fatal("Close failed: ", err)
+	}
+
+	pathenv := os.Getenv("PATH")
+	defer os.Setenv("PATH", pathenv)
+
+	err = os.Setenv("PATH", "")
+	if err != nil {
+		t.Fatal("Setenv failed: ", err)
+	}
+
+	path, err := LookPath("exec_me")
+	if err == nil {
+		t.Fatal("LookPath found exec_me in empty $PATH")
+	}
+	if path != "" {
+		t.Fatalf("LookPath path == %q when err != nil", path)
+	}
+}
diff --git a/src/pkg/os/exec/lp_windows.go b/src/pkg/os/exec/lp_windows.go
index d8351d7..7c7289b 100644
--- a/src/pkg/os/exec/lp_windows.go
+++ b/src/pkg/os/exec/lp_windows.go
@@ -72,7 +72,7 @@ func LookPath(file string) (f string, err error) {
 		return
 	}
 	if pathenv := os.Getenv(`PATH`); pathenv != `` {
-		for _, dir := range strings.Split(pathenv, `;`) {
+		for _, dir := range splitList(pathenv) {
 			if f, err = findExecutable(dir+`\`+file, exts); err == nil {
 				return
 			}
@@ -80,3 +80,36 @@ func LookPath(file string) (f string, err error) {
 	}
 	return ``, &Error{file, ErrNotFound}
 }
+
+func splitList(path string) []string {
+	// The same implementation is used in SplitList in path/filepath;
+	// consider changing path/filepath when changing this.
+
+	if path == "" {
+		return []string{}
+	}
+
+	// Split path, respecting but preserving quotes.
+	list := []string{}
+	start := 0
+	quo := false
+	for i := 0; i < len(path); i++ {
+		switch c := path[i]; {
+		case c == '"':
+			quo = !quo
+		case c == os.PathListSeparator && !quo:
+			list = append(list, path[start:i])
+			start = i + 1
+		}
+	}
+	list = append(list, path[start:])
+
+	// Remove quotes.
+	for i, s := range list {
+		if strings.Contains(s, `"`) {
+			list[i] = strings.Replace(s, `"`, ``, -1)
+		}
+	}
+
+	return list
+}
diff --git a/src/pkg/os/exec_plan9.go b/src/pkg/os/exec_plan9.go
index 41cc8c2..2bd5b68 100644
--- a/src/pkg/os/exec_plan9.go
+++ b/src/pkg/os/exec_plan9.go
@@ -11,6 +11,14 @@ import (
 	"time"
 )
 
+// The only signal values guaranteed to be present on all systems
+// are Interrupt (send the process an interrupt) and Kill (force
+// the process to exit).
+var (
+	Interrupt Signal = syscall.Note("interrupt")
+	Kill      Signal = syscall.Note("kill")
+)
+
 func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
 	sysattr := &syscall.ProcAttr{
 		Dir: attr.Dir,
@@ -30,35 +38,35 @@ func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e
 	return newProcess(pid, h), nil
 }
 
-// Plan9Note implements the Signal interface on Plan 9.
-type Plan9Note string
-
-func (note Plan9Note) String() string {
-	return string(note)
+func (p *Process) writeProcFile(file string, data string) error {
+	f, e := OpenFile("/proc/"+itoa(p.Pid)+"/"+file, O_WRONLY, 0)
+	if e != nil {
+		return e
+	}
+	defer f.Close()
+	_, e = f.Write([]byte(data))
+	return e
 }
 
 func (p *Process) signal(sig Signal) error {
-	if p.done {
+	if p.done() {
 		return errors.New("os: process already finished")
 	}
-
-	f, e := OpenFile("/proc/"+itoa(p.Pid)+"/note", O_WRONLY, 0)
-	if e != nil {
+	if sig == Kill {
+		// Special-case the kill signal since it doesn't use /proc/$pid/note.
+		return p.Kill()
+	}
+	if e := p.writeProcFile("note", sig.String()); e != nil {
 		return NewSyscallError("signal", e)
 	}
-	defer f.Close()
-	_, e = f.Write([]byte(sig.String()))
-	return e
+	return nil
 }
 
 func (p *Process) kill() error {
-	f, e := OpenFile("/proc/"+itoa(p.Pid)+"/ctl", O_WRONLY, 0)
-	if e != nil {
+	if e := p.writeProcFile("ctl", "kill"); e != nil {
 		return NewSyscallError("kill", e)
 	}
-	defer f.Close()
-	_, e = f.Write([]byte("kill"))
-	return e
+	return nil
 }
 
 func (p *Process) wait() (ps *ProcessState, err error) {
@@ -67,20 +75,12 @@ func (p *Process) wait() (ps *ProcessState, err error) {
 	if p.Pid == -1 {
 		return nil, ErrInvalid
 	}
-
-	for true {
-		err = syscall.Await(&waitmsg)
-
-		if err != nil {
-			return nil, NewSyscallError("wait", err)
-		}
-
-		if waitmsg.Pid == p.Pid {
-			p.done = true
-			break
-		}
+	err = syscall.WaitProcess(p.Pid, &waitmsg)
+	if err != nil {
+		return nil, NewSyscallError("wait", err)
 	}
 
+	p.setDone()
 	ps = &ProcessState{
 		pid:    waitmsg.Pid,
 		status: &waitmsg,
diff --git a/src/pkg/os/exec_posix.go b/src/pkg/os/exec_posix.go
index 70351cf..f7b10f3 100644
--- a/src/pkg/os/exec_posix.go
+++ b/src/pkg/os/exec_posix.go
@@ -10,10 +10,19 @@ import (
 	"syscall"
 )
 
+// The only signal values guaranteed to be present on all systems
+// are Interrupt (send the process an interrupt) and Kill (force
+// the process to exit).
+var (
+	Interrupt Signal = syscall.SIGINT
+	Kill      Signal = syscall.SIGKILL
+)
+
 func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
-	// Double-check existence of the directory we want
+	// If there is no SysProcAttr (ie. no Chroot or changed
+	// UID/GID), double-check existence of the directory we want
 	// to chdir into.  We can make the error clearer this way.
-	if attr != nil && attr.Dir != "" {
+	if attr != nil && attr.Sys == nil && attr.Dir != "" {
 		if _, err := Stat(attr.Dir); err != nil {
 			pe := err.(*PathError)
 			pe.Op = "chdir"
@@ -109,9 +118,9 @@ func (p *ProcessState) String() string {
 	case status.Exited():
 		res = "exit status " + itod(status.ExitStatus())
 	case status.Signaled():
-		res = "signal " + itod(int(status.Signal()))
+		res = "signal: " + status.Signal().String()
 	case status.Stopped():
-		res = "stop signal " + itod(int(status.StopSignal()))
+		res = "stop signal: " + status.StopSignal().String()
 		if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 {
 			res += " (trap " + itod(status.TrapCause()) + ")"
 		}
diff --git a/src/pkg/os/exec_unix.go b/src/pkg/os/exec_unix.go
index ecfe535..fa3ba8a 100644
--- a/src/pkg/os/exec_unix.go
+++ b/src/pkg/os/exec_unix.go
@@ -24,7 +24,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
 		return nil, NewSyscallError("wait", e)
 	}
 	if pid1 != 0 {
-		p.done = true
+		p.setDone()
 	}
 	ps = &ProcessState{
 		pid:    pid1,
@@ -35,7 +35,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
 }
 
 func (p *Process) signal(sig Signal) error {
-	if p.done {
+	if p.done() {
 		return errors.New("os: process already finished")
 	}
 	s, ok := sig.(syscall.Signal)
diff --git a/src/pkg/os/exec_windows.go b/src/pkg/os/exec_windows.go
index 5beca4a..4aa2ade 100644
--- a/src/pkg/os/exec_windows.go
+++ b/src/pkg/os/exec_windows.go
@@ -32,7 +32,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
 	if e != nil {
 		return nil, NewSyscallError("GetProcessTimes", e)
 	}
-	p.done = true
+	p.setDone()
 	// NOTE(brainman): It seems that sometimes process is not dead
 	// when WaitForSingleObject returns. But we do not know any
 	// other way to wait for it. Sleeping for a while seems to do
@@ -43,7 +43,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
 }
 
 func (p *Process) signal(sig Signal) error {
-	if p.done {
+	if p.done() {
 		return errors.New("os: process already finished")
 	}
 	if sig == Kill {
diff --git a/src/pkg/os/file.go b/src/pkg/os/file.go
index 4acf35d..32cac6d 100644
--- a/src/pkg/os/file.go
+++ b/src/pkg/os/file.go
@@ -9,7 +9,7 @@
 // if a call that takes a file name fails, such as Open or Stat, the error
 // will include the failing file name when printed and will be of type
 // *PathError, which may be unpacked for more information.
-// 
+//
 // The os interface is intended to be uniform across all operating systems.
 // Features not generally available appear in the system-specific package syscall.
 //
@@ -185,7 +185,7 @@ func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
 }
 
 // WriteString is like Write, but writes the contents of string s rather than
-// an array of bytes.
+// a slice of bytes.
 func (f *File) WriteString(s string) (ret int, err error) {
 	if f == nil {
 		return 0, ErrInvalid
diff --git a/src/pkg/os/file_plan9.go b/src/pkg/os/file_plan9.go
index cb0e9ef..d6d39a8 100644
--- a/src/pkg/os/file_plan9.go
+++ b/src/pkg/os/file_plan9.go
@@ -5,14 +5,11 @@
 package os
 
 import (
-	"errors"
 	"runtime"
 	"syscall"
 	"time"
 )
 
-var ErrPlan9 = errors.New("unimplemented on Plan 9")
-
 // File represents an open file descriptor.
 type File struct {
 	*file
@@ -107,7 +104,6 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
 		append = true
 	}
 
-	syscall.ForkLock.RLock()
 	if (create && trunc) || excl {
 		fd, e = syscall.Create(name, flag, syscallMode(perm))
 	} else {
@@ -120,7 +116,6 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
 			}
 		}
 	}
-	syscall.ForkLock.RUnlock()
 
 	if e != nil {
 		return nil, &PathError{"open", name, e}
@@ -137,8 +132,8 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
 
 // Close closes the File, rendering it unusable for I/O.
 // It returns an error, if any.
-func (file *File) Close() error {
-	return file.file.close()
+func (f *File) Close() error {
+	return f.file.close()
 }
 
 func (file *file) close() error {
@@ -159,8 +154,8 @@ func (file *file) close() error {
 }
 
 // Stat returns the FileInfo structure describing file.
-// It returns the FileInfo and an error, if any.
-func (f *File) Stat() (FileInfo, error) {
+// If there is an error, it will be of type *PathError.
+func (f *File) Stat() (fi FileInfo, err error) {
 	d, err := dirstat(f)
 	if err != nil {
 		return nil, err
@@ -170,14 +165,20 @@ func (f *File) Stat() (FileInfo, error) {
 
 // Truncate changes the size of the file.
 // It does not change the I/O offset.
+// If there is an error, it will be of type *PathError.
 func (f *File) Truncate(size int64) error {
-	var d Dir
-	d.Null()
+	var d syscall.Dir
 
-	d.Length = uint64(size)
+	d.Null()
+	d.Length = size
 
-	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil {
-		return &PathError{"truncate", f.name, e}
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"truncate", f.name, err}
+	}
+	if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
+		return &PathError{"truncate", f.name, err}
 	}
 	return nil
 }
@@ -187,7 +188,7 @@ const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | Mod
 // Chmod changes the mode of the file to mode.
 // If there is an error, it will be of type *PathError.
 func (f *File) Chmod(mode FileMode) error {
-	var d Dir
+	var d syscall.Dir
 
 	odir, e := dirstat(f)
 	if e != nil {
@@ -195,8 +196,14 @@ func (f *File) Chmod(mode FileMode) error {
 	}
 	d.Null()
 	d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
-	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil {
-		return &PathError{"chmod", f.name, e}
+
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"chmod", f.name, err}
+	}
+	if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
+		return &PathError{"chmod", f.name, err}
 	}
 	return nil
 }
@@ -208,12 +215,16 @@ func (f *File) Sync() (err error) {
 	if f == nil {
 		return ErrInvalid
 	}
-
-	var d Dir
+	var d syscall.Dir
 	d.Null()
 
-	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil {
-		return NewSyscallError("fsync", e)
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return NewSyscallError("fsync", err)
+	}
+	if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
+		return NewSyscallError("fsync", err)
 	}
 	return nil
 }
@@ -233,13 +244,23 @@ func (f *File) pread(b []byte, off int64) (n int, err error) {
 
 // write writes len(b) bytes to the File.
 // It returns the number of bytes written and an error, if any.
+// Since Plan 9 preserves message boundaries, never allow
+// a zero-byte write.
 func (f *File) write(b []byte) (n int, err error) {
+	if len(b) == 0 {
+		return 0, nil
+	}
 	return syscall.Write(f.fd, b)
 }
 
 // pwrite writes len(b) bytes to the File starting at byte offset off.
 // It returns the number of bytes written and an error, if any.
+// Since Plan 9 preserves message boundaries, never allow
+// a zero-byte write.
 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)
 }
 
@@ -255,13 +276,18 @@ func (f *File) seek(offset int64, whence int) (ret int64, err error) {
 // If the file is a symbolic link, it changes the size of the link's target.
 // If there is an error, it will be of type *PathError.
 func Truncate(name string, size int64) error {
-	var d Dir
-	d.Null()
+	var d syscall.Dir
 
-	d.Length = uint64(size)
+	d.Null()
+	d.Length = size
 
-	if e := syscall.Wstat(name, pdir(nil, &d)); e != nil {
-		return &PathError{"truncate", name, e}
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"truncate", name, err}
+	}
+	if err = syscall.Wstat(name, buf[:n]); err != nil {
+		return &PathError{"truncate", name, err}
 	}
 	return nil
 }
@@ -277,21 +303,27 @@ func Remove(name string) error {
 
 // Rename renames a file.
 func Rename(oldname, newname string) error {
-	var d Dir
-	d.Null()
+	var d syscall.Dir
 
+	d.Null()
 	d.Name = newname
 
-	if e := syscall.Wstat(oldname, pdir(nil, &d)); e != nil {
-		return &PathError{"rename", oldname, e}
+	buf := make([]byte, syscall.STATFIXLEN+len(d.Name))
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"rename", oldname, err}
+	}
+	if err = syscall.Wstat(oldname, buf[:n]); err != nil {
+		return &PathError{"rename", oldname, err}
 	}
 	return nil
 }
 
 // Chmod changes the mode of the named file to mode.
+// If the file is a symbolic link, it changes the mode of the link's target.
 // If there is an error, it will be of type *PathError.
 func Chmod(name string, mode FileMode) error {
-	var d Dir
+	var d syscall.Dir
 
 	odir, e := dirstat(name)
 	if e != nil {
@@ -299,8 +331,14 @@ func Chmod(name string, mode FileMode) error {
 	}
 	d.Null()
 	d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
-	if e := syscall.Wstat(name, pdir(nil, &d)); e != nil {
-		return &PathError{"chmod", name, e}
+
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"chmod", name, err}
+	}
+	if err = syscall.Wstat(name, buf[:n]); err != nil {
+		return &PathError{"chmod", name, err}
 	}
 	return nil
 }
@@ -310,19 +348,27 @@ func Chmod(name string, mode FileMode) error {
 //
 // The underlying filesystem may truncate or round the values to a
 // less precise time unit.
+// If there is an error, it will be of type *PathError.
 func Chtimes(name string, atime time.Time, mtime time.Time) error {
-	var d Dir
-	d.Null()
+	var d syscall.Dir
 
+	d.Null()
 	d.Atime = uint32(atime.Unix())
 	d.Mtime = uint32(mtime.Unix())
 
-	if e := syscall.Wstat(name, pdir(nil, &d)); e != nil {
-		return &PathError{"chtimes", name, e}
+	var buf [syscall.STATFIXLEN]byte
+	n, err := d.Marshal(buf[:])
+	if err != nil {
+		return &PathError{"chtimes", name, err}
+	}
+	if err = syscall.Wstat(name, buf[:n]); err != nil {
+		return &PathError{"chtimes", name, err}
 	}
 	return nil
 }
 
+// Pipe returns a connected pair of Files; reads from r return bytes
+// written to w. It returns the files and an error, if any.
 func Pipe() (r *File, w *File, err error) {
 	var p [2]int
 
@@ -338,32 +384,42 @@ func Pipe() (r *File, w *File, err error) {
 
 // not supported on Plan 9
 
-// Link creates a hard link.
+// 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 {
-	return &LinkError{"link", oldname, newname, ErrPlan9}
+	return &LinkError{"link", oldname, newname, syscall.EPLAN9}
 }
 
 // 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 {
-	return &LinkError{"symlink", oldname, newname, ErrPlan9}
+	return &LinkError{"symlink", oldname, newname, syscall.EPLAN9}
 }
 
+// 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) {
-	return "", ErrPlan9
+	return "", &PathError{"readlink", name, syscall.EPLAN9}
 }
 
+// Chown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link's target.
+// If there is an error, it will be of type *PathError.
 func Chown(name string, uid, gid int) error {
-	return ErrPlan9
+	return &PathError{"chown", name, syscall.EPLAN9}
 }
 
+// Lchown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link itself.
+// If there is an error, it will be of type *PathError.
 func Lchown(name string, uid, gid int) error {
-	return ErrPlan9
+	return &PathError{"lchown", name, syscall.EPLAN9}
 }
 
+// Chown changes the numeric uid and gid of the named file.
+// If there is an error, it will be of type *PathError.
 func (f *File) Chown(uid, gid int) error {
-	return ErrPlan9
+	return &PathError{"chown", f.name, syscall.EPLAN9}
 }
 
 // TempDir returns the default directory to use for temporary files.
diff --git a/src/pkg/os/file_posix.go b/src/pkg/os/file_posix.go
index 073bd56..b979fed 100644
--- a/src/pkg/os/file_posix.go
+++ b/src/pkg/os/file_posix.go
@@ -13,17 +13,6 @@ import (
 
 func sigpipe() // implemented in package runtime
 
-func epipecheck(file *File, e error) {
-	if e == syscall.EPIPE {
-		file.nepipe++
-		if file.nepipe >= 10 {
-			sigpipe()
-		}
-	} else {
-		file.nepipe = 0
-	}
-}
-
 // 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 {
@@ -164,12 +153,10 @@ func (f *File) Sync() (err error) {
 // less precise time unit.
 // If there is an error, it will be of type *PathError.
 func Chtimes(name string, atime time.Time, mtime time.Time) error {
-	var utimes [2]syscall.Timeval
-	atime_ns := atime.Unix()*1e9 + int64(atime.Nanosecond())
-	mtime_ns := mtime.Unix()*1e9 + int64(mtime.Nanosecond())
-	utimes[0] = syscall.NsecToTimeval(atime_ns)
-	utimes[1] = syscall.NsecToTimeval(mtime_ns)
-	if e := syscall.Utimes(name, utimes[0:]); e != nil {
+	var utimes [2]syscall.Timespec
+	utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
+	utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())
+	if e := syscall.UtimesNano(name, utimes[0:]); e != nil {
 		return &PathError{"chtimes", name, e}
 	}
 	return nil
diff --git a/src/pkg/os/file_unix.go b/src/pkg/os/file_unix.go
index 6271c31..4f59c94 100644
--- a/src/pkg/os/file_unix.go
+++ b/src/pkg/os/file_unix.go
@@ -8,6 +8,7 @@ package os
 
 import (
 	"runtime"
+	"sync/atomic"
 	"syscall"
 )
 
@@ -24,7 +25,7 @@ type file struct {
 	fd      int
 	name    string
 	dirinfo *dirInfo // nil unless directory being read
-	nepipe  int      // number of consecutive EPIPE in Write
+	nepipe  int32    // number of consecutive EPIPE in Write
 }
 
 // Fd returns the integer Unix file descriptor referencing the open file.
@@ -53,6 +54,16 @@ type dirInfo struct {
 	bufp int    // location of next record in buf.
 }
 
+func epipecheck(file *File, e error) {
+	if e == syscall.EPIPE {
+		if atomic.AddInt32(&file.nepipe, 1) >= 10 {
+			sigpipe()
+		}
+	} else {
+		atomic.StoreInt32(&file.nepipe, 0)
+	}
+}
+
 // DevNull is the name of the operating system's ``null device.''
 // On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
 const DevNull = "/dev/null"
@@ -263,25 +274,6 @@ func basename(name string) string {
 	return name
 }
 
-// Pipe returns a connected pair of Files; reads from r return bytes written to w.
-// It returns the files and an error, if any.
-func Pipe() (r *File, w *File, err error) {
-	var p [2]int
-
-	// See ../syscall/exec.go for description of lock.
-	syscall.ForkLock.RLock()
-	e := syscall.Pipe(p[0:])
-	if e != nil {
-		syscall.ForkLock.RUnlock()
-		return nil, nil, NewSyscallError("pipe", e)
-	}
-	syscall.CloseOnExec(p[0])
-	syscall.CloseOnExec(p[1])
-	syscall.ForkLock.RUnlock()
-
-	return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
-}
-
 // TempDir returns the default directory to use for temporary files.
 func TempDir() string {
 	dir := Getenv("TMPDIR")
diff --git a/src/pkg/os/file_windows.go b/src/pkg/os/file_windows.go
index 88fa77b..2eba7a4 100644
--- a/src/pkg/os/file_windows.go
+++ b/src/pkg/os/file_windows.go
@@ -10,6 +10,8 @@ import (
 	"sync"
 	"syscall"
 	"unicode/utf16"
+	"unicode/utf8"
+	"unsafe"
 )
 
 // File represents an open file descriptor.
@@ -25,8 +27,12 @@ type file struct {
 	fd      syscall.Handle
 	name    string
 	dirinfo *dirInfo   // nil unless directory being read
-	nepipe  int        // number of consecutive EPIPE in Write
 	l       sync.Mutex // used to implement windows pread/pwrite
+
+	// only for console io
+	isConsole bool
+	lastbits  []byte // first few bytes of the last incomplete rune in last write
+	readbuf   []rune // input console buffer
 }
 
 // Fd returns the Windows handle referencing the open file.
@@ -37,15 +43,25 @@ func (file *File) Fd() uintptr {
 	return uintptr(file.fd)
 }
 
+// newFile returns a new File with the given file handle and name.
+// Unlike NewFile, it does not check that h is syscall.InvalidHandle.
+func newFile(h syscall.Handle, name string) *File {
+	f := &File{&file{fd: h, name: name}}
+	var m uint32
+	if syscall.GetConsoleMode(f.fd, &m) == nil {
+		f.isConsole = true
+	}
+	runtime.SetFinalizer(f.file, (*file).close)
+	return f
+}
+
 // NewFile returns a new File with the given file descriptor and name.
 func NewFile(fd uintptr, name string) *File {
 	h := syscall.Handle(fd)
 	if h == syscall.InvalidHandle {
 		return nil
 	}
-	f := &File{&file{fd: h, name: name}}
-	runtime.SetFinalizer(f.file, (*file).close)
-	return f
+	return newFile(h, name)
 }
 
 // Auxiliary information if the File describes a directory
@@ -53,6 +69,10 @@ type dirInfo struct {
 	data     syscall.Win32finddata
 	needdata bool
 	path     string
+	isempty  bool // set if FindFirstFile returns ERROR_FILE_NOT_FOUND
+}
+
+func epipecheck(file *File, e error) {
 }
 
 const DevNull = "NUL"
@@ -62,30 +82,45 @@ func (f *file) isdir() bool { return f != nil && f.dirinfo != nil }
 func openFile(name string, flag int, perm FileMode) (file *File, err error) {
 	r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
 	if e != nil {
-		return nil, &PathError{"open", name, e}
-	}
-
-	// There's a race here with fork/exec, which we are
-	// content to live with.  See ../syscall/exec.go
-	if syscall.O_CLOEXEC == 0 { // O_CLOEXEC not supported
-		syscall.CloseOnExec(r)
+		return nil, e
 	}
-
 	return NewFile(uintptr(r), name), nil
 }
 
 func openDir(name string) (file *File, err error) {
+	maskp, e := syscall.UTF16PtrFromString(name + `\*`)
+	if e != nil {
+		return nil, e
+	}
 	d := new(dirInfo)
-	r, e := syscall.FindFirstFile(syscall.StringToUTF16Ptr(name+`\*`), &d.data)
+	r, e := syscall.FindFirstFile(maskp, &d.data)
 	if e != nil {
-		return nil, &PathError{"open", name, e}
+		// FindFirstFile returns ERROR_FILE_NOT_FOUND when
+		// no matching files can be found. Then, if directory
+		// exists, we should proceed.
+		if e != syscall.ERROR_FILE_NOT_FOUND {
+			return nil, e
+		}
+		var fa syscall.Win32FileAttributeData
+		namep, e := syscall.UTF16PtrFromString(name)
+		if e != nil {
+			return nil, e
+		}
+		e = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fa)))
+		if e != nil {
+			return nil, e
+		}
+		if fa.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY == 0 {
+			return nil, e
+		}
+		d.isempty = true
 	}
 	d.path = name
 	if !isAbs(d.path) {
 		cwd, _ := Getwd()
 		d.path = cwd + `\` + d.path
 	}
-	f := NewFile(uintptr(r), name)
+	f := newFile(r, name)
 	f.dirinfo = d
 	return f, nil
 }
@@ -112,7 +147,7 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
 	if e == nil {
 		return r, nil
 	}
-	return nil, e
+	return nil, &PathError{"open", name, e}
 }
 
 // Close closes the File, rendering it unusable for I/O.
@@ -122,7 +157,14 @@ func (file *File) Close() error {
 }
 
 func (file *file) close() error {
-	if file == nil || file.fd == syscall.InvalidHandle {
+	if file == nil {
+		return syscall.EINVAL
+	}
+	if file.isdir() && file.dirinfo.isempty {
+		// "special" empty directories
+		return nil
+	}
+	if file.fd == syscall.InvalidHandle {
 		return syscall.EINVAL
 	}
 	var e error
@@ -143,12 +185,15 @@ func (file *file) close() error {
 }
 
 func (file *File) readdir(n int) (fi []FileInfo, err error) {
-	if file == nil || file.fd == syscall.InvalidHandle {
+	if file == nil {
 		return nil, syscall.EINVAL
 	}
 	if !file.isdir() {
 		return nil, &PathError{"Readdir", file.name, syscall.ENOTDIR}
 	}
+	if !file.dirinfo.isempty && file.fd == syscall.InvalidHandle {
+		return nil, syscall.EINVAL
+	}
 	wantAll := n <= 0
 	size := n
 	if wantAll {
@@ -157,7 +202,7 @@ func (file *File) readdir(n int) (fi []FileInfo, err error) {
 	}
 	fi = make([]FileInfo, 0, size) // Empty with room to grow.
 	d := &file.dirinfo.data
-	for n != 0 {
+	for n != 0 && !file.dirinfo.isempty {
 		if file.dirinfo.needdata {
 			e := syscall.FindNextFile(syscall.Handle(file.fd), d)
 			if e != nil {
@@ -178,11 +223,16 @@ func (file *File) readdir(n int) (fi []FileInfo, err error) {
 			continue
 		}
 		f := &fileStat{
-			name:    name,
-			size:    mkSize(d.FileSizeHigh, d.FileSizeLow),
-			modTime: mkModTime(d.LastWriteTime),
-			mode:    mkMode(d.FileAttributes),
-			sys:     mkSys(file.dirinfo.path+`\`+name, d.LastAccessTime, d.CreationTime),
+			name: name,
+			sys: syscall.Win32FileAttributeData{
+				FileAttributes: d.FileAttributes,
+				CreationTime:   d.CreationTime,
+				LastAccessTime: d.LastAccessTime,
+				LastWriteTime:  d.LastWriteTime,
+				FileSizeHigh:   d.FileSizeHigh,
+				FileSizeLow:    d.FileSizeLow,
+			},
+			path: file.dirinfo.path + `\` + name,
 		}
 		n--
 		fi = append(fi, f)
@@ -193,11 +243,48 @@ func (file *File) readdir(n int) (fi []FileInfo, err error) {
 	return fi, nil
 }
 
+// readConsole reads utf16 charcters from console File,
+// encodes them into utf8 and stores them in buffer b.
+// It returns the number of utf8 bytes read and an error, if any.
+func (f *File) readConsole(b []byte) (n int, err error) {
+	if len(b) == 0 {
+		return 0, nil
+	}
+	if len(f.readbuf) == 0 {
+		// get more input data from os
+		wchars := make([]uint16, len(b))
+		var p *uint16
+		if len(b) > 0 {
+			p = &wchars[0]
+		}
+		var nw uint32
+		err := syscall.ReadConsole(f.fd, p, uint32(len(wchars)), &nw, nil)
+		if err != nil {
+			return 0, err
+		}
+		f.readbuf = utf16.Decode(wchars[:nw])
+	}
+	for i, r := range f.readbuf {
+		if utf8.RuneLen(r) > len(b) {
+			f.readbuf = f.readbuf[i:]
+			return n, nil
+		}
+		nr := utf8.EncodeRune(b, r)
+		b = b[nr:]
+		n += nr
+	}
+	f.readbuf = nil
+	return n, nil
+}
+
 // 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) {
 	f.l.Lock()
 	defer f.l.Unlock()
+	if f.isConsole {
+		return f.readConsole(b)
+	}
 	return syscall.Read(f.fd, b)
 }
 
@@ -224,11 +311,57 @@ func (f *File) pread(b []byte, off int64) (n int, err error) {
 	return int(done), nil
 }
 
+// writeConsole writes len(b) bytes to the console File.
+// It returns the number of bytes written and an error, if any.
+func (f *File) writeConsole(b []byte) (n int, err error) {
+	n = len(b)
+	runes := make([]rune, 0, 256)
+	if len(f.lastbits) > 0 {
+		b = append(f.lastbits, b...)
+		f.lastbits = nil
+
+	}
+	for len(b) >= utf8.UTFMax || utf8.FullRune(b) {
+		r, l := utf8.DecodeRune(b)
+		runes = append(runes, r)
+		b = b[l:]
+	}
+	if len(b) > 0 {
+		f.lastbits = make([]byte, len(b))
+		copy(f.lastbits, b)
+	}
+	// syscall.WriteConsole seems to fail, if given large buffer.
+	// So limit the buffer to 16000 characters. This number was
+	// discovered by experimenting with syscall.WriteConsole.
+	const maxWrite = 16000
+	for len(runes) > 0 {
+		m := len(runes)
+		if m > maxWrite {
+			m = maxWrite
+		}
+		chunk := runes[:m]
+		runes = runes[m:]
+		uint16s := utf16.Encode(chunk)
+		for len(uint16s) > 0 {
+			var written uint32
+			err = syscall.WriteConsole(f.fd, &uint16s[0], uint32(len(uint16s)), &written, nil)
+			if err != nil {
+				return 0, nil
+			}
+			uint16s = uint16s[written:]
+		}
+	}
+	return n, nil
+}
+
 // write writes len(b) bytes to the File.
 // It returns the number of bytes written and an error, if any.
 func (f *File) write(b []byte) (n int, err error) {
 	f.l.Lock()
 	defer f.l.Unlock()
+	if f.isConsole {
+		return f.writeConsole(b)
+	}
 	return syscall.Write(f.fd, b)
 }
 
@@ -282,11 +415,14 @@ func Truncate(name string, size int64) error {
 // Remove removes the named file or directory.
 // If there is an error, it will be of type *PathError.
 func Remove(name string) error {
-	p := &syscall.StringToUTF16(name)[0]
+	p, e := syscall.UTF16PtrFromString(name)
+	if e != nil {
+		return &PathError{"remove", name, e}
+	}
 
 	// Go file interface forces us to know whether
 	// name is a file or directory. Try both.
-	e := syscall.DeleteFile(p)
+	e = syscall.DeleteFile(p)
 	if e == nil {
 		return nil
 	}
diff --git a/src/pkg/os/getwd.go b/src/pkg/os/getwd.go
index 81d8fed..1b22123 100644
--- a/src/pkg/os/getwd.go
+++ b/src/pkg/os/getwd.go
@@ -5,9 +5,15 @@
 package os
 
 import (
+	"sync"
 	"syscall"
 )
 
+var getwdCache struct {
+	sync.Mutex
+	dir string
+}
+
 // Getwd returns a rooted path name corresponding to the
 // current directory.  If the current directory can be
 // reached via multiple paths (due to symbolic links),
@@ -35,6 +41,17 @@ func Getwd() (pwd string, err error) {
 		}
 	}
 
+	// Apply same kludge but to cached dir instead of $PWD.
+	getwdCache.Lock()
+	pwd = getwdCache.dir
+	getwdCache.Unlock()
+	if len(pwd) > 0 {
+		d, err := Stat(pwd)
+		if err == nil && SameFile(dot, d) {
+			return pwd, nil
+		}
+	}
+
 	// Root is a special case because it has no parent
 	// and ends in a slash.
 	root, err := Stat("/")
@@ -88,5 +105,11 @@ func Getwd() (pwd string, err error) {
 		// Set up for next round.
 		dot = pd
 	}
+
+	// Save answer as hint to avoid the expensive path next time.
+	getwdCache.Lock()
+	getwdCache.dir = pwd
+	getwdCache.Unlock()
+
 	return pwd, nil
 }
diff --git a/src/pkg/os/os_test.go b/src/pkg/os/os_test.go
index dec80cc..2970601 100644
--- a/src/pkg/os/os_test.go
+++ b/src/pkg/os/os_test.go
@@ -6,6 +6,7 @@ package os_test
 
 import (
 	"bytes"
+	"flag"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -40,7 +41,6 @@ var sysdir = func() (sd *sysDir) {
 		sd = &sysDir{
 			Getenv("SystemRoot") + "\\system32\\drivers\\etc",
 			[]string{
-				"hosts",
 				"networks",
 				"protocol",
 				"services",
@@ -69,10 +69,10 @@ var sysdir = func() (sd *sysDir) {
 
 func size(name string, t *testing.T) int64 {
 	file, err := Open(name)
-	defer file.Close()
 	if err != nil {
 		t.Fatal("open failed:", err)
 	}
+	defer file.Close()
 	var buf [100]byte
 	len := 0
 	for {
@@ -134,10 +134,10 @@ func TestStat(t *testing.T) {
 func TestFstat(t *testing.T) {
 	path := sfdir + "/" + sfname
 	file, err1 := Open(path)
-	defer file.Close()
 	if err1 != nil {
 		t.Fatal("open failed:", err1)
 	}
+	defer file.Close()
 	dir, err2 := file.Stat()
 	if err2 != nil {
 		t.Fatal("fstat failed:", err2)
@@ -189,10 +189,10 @@ func TestRead0(t *testing.T) {
 
 func testReaddirnames(dir string, contents []string, t *testing.T) {
 	file, err := Open(dir)
-	defer file.Close()
 	if err != nil {
 		t.Fatalf("open %q failed: %v", dir, err)
 	}
+	defer file.Close()
 	s, err2 := file.Readdirnames(-1)
 	if err2 != nil {
 		t.Fatalf("readdirnames %q failed: %v", dir, err2)
@@ -218,10 +218,10 @@ func testReaddirnames(dir string, contents []string, t *testing.T) {
 
 func testReaddir(dir string, contents []string, t *testing.T) {
 	file, err := Open(dir)
-	defer file.Close()
 	if err != nil {
 		t.Fatalf("open %q failed: %v", dir, err)
 	}
+	defer file.Close()
 	s, err2 := file.Readdir(-1)
 	if err2 != nil {
 		t.Fatalf("readdir %q failed: %v", dir, err2)
@@ -285,10 +285,10 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
 		dir = "/bin"
 	}
 	file, err := Open(dir)
-	defer file.Close()
 	if err != nil {
 		t.Fatalf("open %q failed: %v", dir, err)
 	}
+	defer file.Close()
 	all, err1 := file.Readdirnames(-1)
 	if err1 != nil {
 		t.Fatalf("readdirnames %q failed: %v", dir, err1)
@@ -310,8 +310,7 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
 
 func TestReaddirNValues(t *testing.T) {
 	if testing.Short() {
-		t.Logf("test.short; skipping")
-		return
+		t.Skip("test.short; skipping")
 	}
 	dir, err := ioutil.TempDir("", "")
 	if err != nil {
@@ -535,8 +534,10 @@ func exec(t *testing.T, dir, cmd string, args []string, expect string) {
 	var b bytes.Buffer
 	io.Copy(&b, r)
 	output := b.String()
-	// Accept /usr prefix because Solaris /bin is symlinked to /usr/bin.
-	if output != expect && output != "/usr"+expect {
+
+	fi1, _ := Stat(strings.TrimSpace(output))
+	fi2, _ := Stat(expect)
+	if !SameFile(fi1, fi2) {
 		t.Errorf("exec %q returned %q wanted %q",
 			strings.Join(append([]string{cmd}, args...), " "), output, expect)
 	}
@@ -544,15 +545,13 @@ func exec(t *testing.T, dir, cmd string, args []string, expect string) {
 }
 
 func TestStartProcess(t *testing.T) {
-	var dir, cmd, le string
+	var dir, cmd string
 	var args []string
 	if runtime.GOOS == "windows" {
-		le = "\r\n"
 		cmd = Getenv("COMSPEC")
 		dir = Getenv("SystemRoot")
 		args = []string{"/c", "cd"}
 	} else {
-		le = "\n"
 		cmd = "/bin/pwd"
 		dir = "/"
 		args = []string{}
@@ -560,9 +559,9 @@ func TestStartProcess(t *testing.T) {
 	cmddir, cmdbase := filepath.Split(cmd)
 	args = append([]string{cmdbase}, args...)
 	// Test absolute executable path.
-	exec(t, dir, cmd, args, dir+le)
+	exec(t, dir, cmd, args, dir)
 	// Test relative executable path.
-	exec(t, cmddir, cmdbase, args, filepath.Clean(cmddir)+le)
+	exec(t, cmddir, cmdbase, args, cmddir)
 }
 
 func checkMode(t *testing.T, path string, mode FileMode) {
@@ -1066,3 +1065,52 @@ func TestDevNullFile(t *testing.T) {
 		t.Fatalf("wrong file size have %d want 0", fi.Size())
 	}
 }
+
+var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
+
+func TestLargeWriteToConsole(t *testing.T) {
+	if !*testLargeWrite {
+		t.Skip("skipping console-flooding test; enable with -large_write")
+	}
+	b := make([]byte, 32000)
+	for i := range b {
+		b[i] = '.'
+	}
+	b[len(b)-1] = '\n'
+	n, err := Stdout.Write(b)
+	if err != nil {
+		t.Fatalf("Write to os.Stdout failed: %v", err)
+	}
+	if n != len(b) {
+		t.Errorf("Write to os.Stdout should return %d; got %d", len(b), n)
+	}
+	n, err = Stderr.Write(b)
+	if err != nil {
+		t.Fatalf("Write to os.Stderr failed: %v", err)
+	}
+	if n != len(b) {
+		t.Errorf("Write to os.Stderr should return %d; got %d", len(b), n)
+	}
+}
+
+func TestStatDirModeExec(t *testing.T) {
+	const mode = 0111
+
+	path, err := ioutil.TempDir("", "go-build")
+	if err != nil {
+		t.Fatalf("Failed to create temp directory: %v", err)
+	}
+	defer RemoveAll(path)
+
+	if err := Chmod(path, 0777); err != nil {
+		t.Fatalf("Chmod %q 0777: %v", path, err)
+	}
+
+	dir, err := Stat(path)
+	if err != nil {
+		t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
+	}
+	if dir.Mode()&mode != mode {
+		t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode()&mode, mode)
+	}
+}
diff --git a/src/pkg/os/path_plan9.go b/src/pkg/os/path_plan9.go
index 3121b7b..64bad50 100644
--- a/src/pkg/os/path_plan9.go
+++ b/src/pkg/os/path_plan9.go
@@ -5,8 +5,8 @@
 package os
 
 const (
-	PathSeparator     = '/' // OS-specific path separator
-	PathListSeparator = 0   // OS-specific path list separator
+	PathSeparator     = '/'    // OS-specific path separator
+	PathListSeparator = '\000' // OS-specific path list separator
 )
 
 // IsPathSeparator returns true if c is a directory separator character.
diff --git a/src/pkg/os/path_test.go b/src/pkg/os/path_test.go
index c1e3fb3..16c4120 100644
--- a/src/pkg/os/path_test.go
+++ b/src/pkg/os/path_test.go
@@ -5,6 +5,7 @@
 package os_test
 
 import (
+	"io/ioutil"
 	. "os"
 	"path/filepath"
 	"runtime"
@@ -167,24 +168,26 @@ func TestRemoveAll(t *testing.T) {
 
 func TestMkdirAllWithSymlink(t *testing.T) {
 	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
-		t.Log("Skipping test: symlinks don't exist under Windows/Plan 9")
-		return
+		t.Skip("Skipping test: symlinks don't exist under Windows/Plan 9")
 	}
 
-	tmpDir := TempDir()
+	tmpDir, err := ioutil.TempDir("", "TestMkdirAllWithSymlink-")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer RemoveAll(tmpDir)
+
 	dir := tmpDir + "/dir"
-	err := Mkdir(dir, 0755)
+	err = Mkdir(dir, 0755)
 	if err != nil {
 		t.Fatalf("Mkdir %s: %s", dir, err)
 	}
-	defer RemoveAll(dir)
 
 	link := tmpDir + "/link"
 	err = Symlink("dir", link)
 	if err != nil {
 		t.Fatalf("Symlink %s: %s", link, err)
 	}
-	defer RemoveAll(link)
 
 	path := link + "/foo"
 	err = MkdirAll(path, 0755)
diff --git a/src/pkg/os/pipe_bsd.go b/src/pkg/os/pipe_bsd.go
new file mode 100644
index 0000000..a2ce9a3
--- /dev/null
+++ b/src/pkg/os/pipe_bsd.go
@@ -0,0 +1,28 @@
+// 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 darwin freebsd netbsd openbsd
+
+package os
+
+import "syscall"
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an error, if any.
+func Pipe() (r *File, w *File, err error) {
+	var p [2]int
+
+	// See ../syscall/exec.go for description of lock.
+	syscall.ForkLock.RLock()
+	e := syscall.Pipe(p[0:])
+	if e != nil {
+		syscall.ForkLock.RUnlock()
+		return nil, nil, NewSyscallError("pipe", e)
+	}
+	syscall.CloseOnExec(p[0])
+	syscall.CloseOnExec(p[1])
+	syscall.ForkLock.RUnlock()
+
+	return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
+}
diff --git a/src/pkg/os/pipe_linux.go b/src/pkg/os/pipe_linux.go
new file mode 100644
index 0000000..9bafad8
--- /dev/null
+++ b/src/pkg/os/pipe_linux.go
@@ -0,0 +1,33 @@
+// 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 os
+
+import "syscall"
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an error, if any.
+func Pipe() (r *File, w *File, err error) {
+	var p [2]int
+
+	e := syscall.Pipe2(p[0:], syscall.O_CLOEXEC)
+	// pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so it
+	// might not be implemented.
+	if e == syscall.ENOSYS {
+		// See ../syscall/exec.go for description of lock.
+		syscall.ForkLock.RLock()
+		e = syscall.Pipe(p[0:])
+		if e != nil {
+			syscall.ForkLock.RUnlock()
+			return nil, nil, NewSyscallError("pipe", e)
+		}
+		syscall.CloseOnExec(p[0])
+		syscall.CloseOnExec(p[1])
+		syscall.ForkLock.RUnlock()
+	} else if e != nil {
+		return nil, nil, NewSyscallError("pipe2", e)
+	}
+
+	return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
+}
diff --git a/src/pkg/os/proc.go b/src/pkg/os/proc.go
index 61545f4..38c436e 100644
--- a/src/pkg/os/proc.go
+++ b/src/pkg/os/proc.go
@@ -31,4 +31,6 @@ func Getgroups() ([]int, error) {
 
 // Exit causes the current program to exit with the given status code.
 // Conventionally, code zero indicates success, non-zero an error.
+// The program terminates immediately; deferred functions are
+// not run.
 func Exit(code int) { syscall.Exit(code) }
diff --git a/src/pkg/os/signal/example_test.go b/src/pkg/os/signal/example_test.go
new file mode 100644
index 0000000..600ed31
--- /dev/null
+++ b/src/pkg/os/signal/example_test.go
@@ -0,0 +1,19 @@
+package signal_test
+
+import (
+	"fmt"
+	"os"
+	"os/signal"
+)
+
+func ExampleNotify() {
+	// Set up channel on which to send signal notifications.
+	// We must use a buffered channel or risk missing the signal
+	// if we're not ready to receive when the signal is sent.
+	c := make(chan os.Signal, 1)
+	signal.Notify(c, os.Interrupt, os.Kill)
+
+	// Block until a signal is received.
+	s := <-c
+	fmt.Println("Got signal:", s)
+}
diff --git a/src/pkg/os/signal/signal_test.go b/src/pkg/os/signal/signal_test.go
index 3494f8c..509b273 100644
--- a/src/pkg/os/signal/signal_test.go
+++ b/src/pkg/os/signal/signal_test.go
@@ -8,6 +8,7 @@ package signal
 
 import (
 	"os"
+	"runtime"
 	"syscall"
 	"testing"
 	"time"
@@ -58,3 +59,43 @@ func TestSignal(t *testing.T) {
 	// The first SIGHUP should be waiting for us on c.
 	waitSig(t, c, syscall.SIGHUP)
 }
+
+func TestStress(t *testing.T) {
+	dur := 3 * time.Second
+	if testing.Short() {
+		dur = 100 * time.Millisecond
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	done := make(chan bool)
+	finished := make(chan bool)
+	go func() {
+		sig := make(chan os.Signal, 1)
+		Notify(sig, syscall.SIGUSR1)
+	Loop:
+		for {
+			select {
+			case <-sig:
+			case <-done:
+				break Loop
+			}
+		}
+		finished <- true
+	}()
+	go func() {
+	Loop:
+		for {
+			select {
+			case <-done:
+				break Loop
+			default:
+				syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
+				runtime.Gosched()
+			}
+		}
+		finished <- true
+	}()
+	time.Sleep(dur)
+	close(done)
+	<-finished
+	<-finished
+}
diff --git a/src/pkg/os/signal/signal_windows_test.go b/src/pkg/os/signal/signal_windows_test.go
index 8d807ff..26712f3 100644
--- a/src/pkg/os/signal/signal_windows_test.go
+++ b/src/pkg/os/signal/signal_windows_test.go
@@ -5,16 +5,16 @@
 package signal
 
 import (
-	"flag"
+	"bytes"
 	"os"
+	"os/exec"
+	"path/filepath"
 	"syscall"
 	"testing"
 	"time"
 )
 
-var runCtrlBreakTest = flag.Bool("run_ctlbrk_test", false, "force to run Ctrl+Break test")
-
-func sendCtrlBreak(t *testing.T) {
+func sendCtrlBreak(t *testing.T, pid int) {
 	d, e := syscall.LoadDLL("kernel32.dll")
 	if e != nil {
 		t.Fatalf("LoadDLL: %v\n", e)
@@ -23,29 +23,74 @@ func sendCtrlBreak(t *testing.T) {
 	if e != nil {
 		t.Fatalf("FindProc: %v\n", e)
 	}
-	r, _, e := p.Call(0, 0)
+	r, _, e := p.Call(syscall.CTRL_BREAK_EVENT, uintptr(pid))
 	if r == 0 {
 		t.Fatalf("GenerateConsoleCtrlEvent: %v\n", e)
 	}
 }
 
 func TestCtrlBreak(t *testing.T) {
-	if !*runCtrlBreakTest {
-		t.Logf("test disabled; use -run_ctlbrk_test to enable")
-		return
-	}
-	go func() {
-		time.Sleep(1 * time.Second)
-		sendCtrlBreak(t)
-	}()
+	// create source file
+	const source = `
+package main
+
+import (
+	"log"
+	"os"
+	"os/signal"
+	"time"
+)
+
+
+func main() {
 	c := make(chan os.Signal, 10)
-	Notify(c)
+	signal.Notify(c)
 	select {
 	case s := <-c:
 		if s != os.Interrupt {
-			t.Fatalf("Wrong signal received: got %q, want %q\n", s, os.Interrupt)
+			log.Fatalf("Wrong signal received: got %q, want %q\n", s, os.Interrupt)
 		}
 	case <-time.After(3 * time.Second):
-		t.Fatalf("Timeout waiting for Ctrl+Break\n")
+		log.Fatalf("Timeout waiting for Ctrl+Break\n")
+	}
+}
+`
+	name := filepath.Join(os.TempDir(), "ctlbreak")
+	src := name + ".go"
+	defer os.Remove(src)
+	f, err := os.Create(src)
+	if err != nil {
+		t.Fatalf("Failed to create %v: %v", src, err)
+	}
+	defer f.Close()
+	f.Write([]byte(source))
+
+	// compile it
+	exe := name + ".exe"
+	defer os.Remove(exe)
+	o, err := exec.Command("go", "build", "-o", exe, src).CombinedOutput()
+	if err != nil {
+		t.Fatalf("Failed to compile: %v\n%v", err, string(o))
+	}
+
+	// run it
+	cmd := exec.Command(exe)
+	var b bytes.Buffer
+	cmd.Stdout = &b
+	cmd.Stderr = &b
+	cmd.SysProcAttr = &syscall.SysProcAttr{
+		CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP,
+	}
+	err = cmd.Start()
+	if err != nil {
+		t.Fatalf("Start failed: %v", err)
+	}
+	go func() {
+		time.Sleep(1 * time.Second)
+		sendCtrlBreak(t, cmd.Process.Pid)
+	}()
+	err = cmd.Wait()
+	if err != nil {
+		t.Fatalf("Program exited with error: %v\n%v", err, string(b.Bytes()))
 	}
 }
diff --git a/src/pkg/os/stat_darwin.go b/src/pkg/os/stat_darwin.go
index 2e5967d..0eea522 100644
--- a/src/pkg/os/stat_darwin.go
+++ b/src/pkg/os/stat_darwin.go
@@ -9,9 +9,9 @@ import (
 	"time"
 )
 
-func sameFile(sys1, sys2 interface{}) bool {
-	stat1 := sys1.(*syscall.Stat_t)
-	stat2 := sys2.(*syscall.Stat_t)
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
 	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
 }
 
diff --git a/src/pkg/os/stat_freebsd.go b/src/pkg/os/stat_freebsd.go
index 6ba84f4..2ffb60f 100644
--- a/src/pkg/os/stat_freebsd.go
+++ b/src/pkg/os/stat_freebsd.go
@@ -9,9 +9,9 @@ import (
 	"time"
 )
 
-func sameFile(sys1, sys2 interface{}) bool {
-	stat1 := sys1.(*syscall.Stat_t)
-	stat2 := sys2.(*syscall.Stat_t)
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
 	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
 }
 
diff --git a/src/pkg/os/stat_linux.go b/src/pkg/os/stat_linux.go
index 00506b2..605c1d9 100644
--- a/src/pkg/os/stat_linux.go
+++ b/src/pkg/os/stat_linux.go
@@ -9,9 +9,9 @@ import (
 	"time"
 )
 
-func sameFile(sys1, sys2 interface{}) bool {
-	stat1 := sys1.(*syscall.Stat_t)
-	stat2 := sys2.(*syscall.Stat_t)
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
 	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
 }
 
diff --git a/src/pkg/os/stat_netbsd.go b/src/pkg/os/stat_netbsd.go
index 00506b2..2ffb60f 100644
--- a/src/pkg/os/stat_netbsd.go
+++ b/src/pkg/os/stat_netbsd.go
@@ -9,9 +9,9 @@ import (
 	"time"
 )
 
-func sameFile(sys1, sys2 interface{}) bool {
-	stat1 := sys1.(*syscall.Stat_t)
-	stat2 := sys2.(*syscall.Stat_t)
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
 	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
 }
 
@@ -19,7 +19,7 @@ func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
 	fs := &fileStat{
 		name:    basename(name),
 		size:    int64(st.Size),
-		modTime: timespecToTime(st.Mtim),
+		modTime: timespecToTime(st.Mtimespec),
 		sys:     st,
 	}
 	fs.mode = FileMode(st.Mode & 0777)
@@ -57,5 +57,5 @@ func timespecToTime(ts syscall.Timespec) time.Time {
 
 // For testing.
 func atime(fi FileInfo) time.Time {
-	return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim)
+	return timespecToTime(fi.Sys().(*syscall.Stat_t).Atimespec)
 }
diff --git a/src/pkg/os/stat_openbsd.go b/src/pkg/os/stat_openbsd.go
index 00506b2..605c1d9 100644
--- a/src/pkg/os/stat_openbsd.go
+++ b/src/pkg/os/stat_openbsd.go
@@ -9,9 +9,9 @@ import (
 	"time"
 )
 
-func sameFile(sys1, sys2 interface{}) bool {
-	stat1 := sys1.(*syscall.Stat_t)
-	stat2 := sys2.(*syscall.Stat_t)
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
 	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
 }
 
diff --git a/src/pkg/os/stat_plan9.go b/src/pkg/os/stat_plan9.go
index a7990a3..25c9a8c 100644
--- a/src/pkg/os/stat_plan9.go
+++ b/src/pkg/os/stat_plan9.go
@@ -9,13 +9,13 @@ import (
 	"time"
 )
 
-func sameFile(sys1, sys2 interface{}) bool {
-	a := sys1.(*Dir)
-	b := sys2.(*Dir)
+func sameFile(fs1, fs2 *fileStat) bool {
+	a := fs1.sys.(*syscall.Dir)
+	b := fs2.sys.(*syscall.Dir)
 	return a.Qid.Path == b.Qid.Path && a.Type == b.Type && a.Dev == b.Dev
 }
 
-func fileInfoFromStat(d *Dir) FileInfo {
+func fileInfoFromStat(d *syscall.Dir) FileInfo {
 	fs := &fileStat{
 		name:    d.Name,
 		size:    int64(d.Length),
@@ -38,8 +38,8 @@ func fileInfoFromStat(d *Dir) FileInfo {
 	return fs
 }
 
-// arg is an open *File or a path string. 
-func dirstat(arg interface{}) (d *Dir, err error) {
+// arg is an open *File or a path string.
+func dirstat(arg interface{}) (*syscall.Dir, error) {
 	var name string
 
 	// This is big enough for most stat messages
@@ -50,41 +50,45 @@ func dirstat(arg interface{}) (d *Dir, err error) {
 		buf := make([]byte, size)
 
 		var n int
+		var err error
 		switch a := arg.(type) {
 		case *File:
 			name = a.name
 			n, err = syscall.Fstat(a.fd, buf)
 		case string:
 			name = a
-			n, err = syscall.Stat(name, buf)
+			n, err = syscall.Stat(a, buf)
+		default:
+			panic("phase error in dirstat")
 		}
 		if err != nil {
 			return nil, &PathError{"stat", name, err}
 		}
 		if n < syscall.STATFIXLEN {
-			return nil, &PathError{"stat", name, errShortStat}
+			return nil, &PathError{"stat", name, syscall.ErrShortStat}
 		}
 
 		// Pull the real size out of the stat message.
-		s, _ := gbit16(buf)
-		size = int(s)
+		size = int(uint16(buf[0]) | uint16(buf[1])<<8)
 
 		// If the stat message is larger than our buffer we will
 		// go around the loop and allocate one that is big enough.
-		if size <= n {
-			d, err = UnmarshalDir(buf[:n])
-			if err != nil {
-				return nil, &PathError{"stat", name, err}
-			}
-			return
+		if size > n {
+			continue
 		}
+
+		d, err := syscall.UnmarshalDir(buf[:n])
+		if err != nil {
+			return nil, &PathError{"stat", name, err}
+		}
+		return d, nil
 	}
-	return nil, &PathError{"stat", name, errBadStat}
+	return nil, &PathError{"stat", name, syscall.ErrBadStat}
 }
 
-// Stat returns a FileInfo structure describing the named file.
+// Stat returns a FileInfo describing the named file.
 // If there is an error, it will be of type *PathError.
-func Stat(name string) (FileInfo, error) {
+func Stat(name string) (fi FileInfo, err error) {
 	d, err := dirstat(name)
 	if err != nil {
 		return nil, err
@@ -92,15 +96,15 @@ func Stat(name string) (FileInfo, error) {
 	return fileInfoFromStat(d), nil
 }
 
-// Lstat returns the FileInfo structure describing the named file.
-// If the file is a symbolic link (though Plan 9 does not have symbolic links), 
-// the returned FileInfo describes the symbolic link.  Lstat makes no attempt to follow the link.
+// Lstat returns a FileInfo 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) (FileInfo, error) {
+func Lstat(name string) (fi FileInfo, err error) {
 	return Stat(name)
 }
 
 // For testing.
 func atime(fi FileInfo) time.Time {
-	return time.Unix(int64(fi.Sys().(*Dir).Atime), 0)
+	return time.Unix(int64(fi.Sys().(*syscall.Dir).Atime), 0)
 }
diff --git a/src/pkg/os/stat_windows.go b/src/pkg/os/stat_windows.go
index 75351c8..8394c2b 100644
--- a/src/pkg/os/stat_windows.go
+++ b/src/pkg/os/stat_windows.go
@@ -5,9 +5,7 @@
 package os
 
 import (
-	"sync"
 	"syscall"
-	"time"
 	"unsafe"
 )
 
@@ -22,7 +20,7 @@ func (file *File) Stat() (fi FileInfo, err error) {
 		return Stat(file.name)
 	}
 	if file.name == DevNull {
-		return statDevNull()
+		return &devNullStat, nil
 	}
 	var d syscall.ByHandleFileInformation
 	e := syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &d)
@@ -30,11 +28,18 @@ func (file *File) Stat() (fi FileInfo, err error) {
 		return nil, &PathError{"GetFileInformationByHandle", file.name, e}
 	}
 	return &fileStat{
-		name:    basename(file.name),
-		size:    mkSize(d.FileSizeHigh, d.FileSizeLow),
-		modTime: mkModTime(d.LastWriteTime),
-		mode:    mkMode(d.FileAttributes),
-		sys:     mkSysFromFI(&d),
+		name: basename(file.name),
+		sys: syscall.Win32FileAttributeData{
+			FileAttributes: d.FileAttributes,
+			CreationTime:   d.CreationTime,
+			LastAccessTime: d.LastAccessTime,
+			LastWriteTime:  d.LastWriteTime,
+			FileSizeHigh:   d.FileSizeHigh,
+			FileSizeLow:    d.FileSizeLow,
+		},
+		vol:   d.VolumeSerialNumber,
+		idxhi: d.FileIndexHigh,
+		idxlo: d.FileIndexLow,
 	}, nil
 }
 
@@ -45,25 +50,23 @@ func Stat(name string) (fi FileInfo, err error) {
 		return nil, &PathError{"Stat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
 	}
 	if name == DevNull {
-		return statDevNull()
+		return &devNullStat, nil
+	}
+	fs := &fileStat{name: basename(name)}
+	namep, e := syscall.UTF16PtrFromString(name)
+	if e != nil {
+		return nil, &PathError{"Stat", name, e}
 	}
-	var d syscall.Win32FileAttributeData
-	e := syscall.GetFileAttributesEx(syscall.StringToUTF16Ptr(name), syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&d)))
+	e = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fs.sys)))
 	if e != nil {
 		return nil, &PathError{"GetFileAttributesEx", name, e}
 	}
-	path := name
-	if !isAbs(path) {
+	fs.path = name
+	if !isAbs(fs.path) {
 		cwd, _ := Getwd()
-		path = cwd + `\` + path
+		fs.path = cwd + `\` + fs.path
 	}
-	return &fileStat{
-		name:    basename(name),
-		size:    mkSize(d.FileSizeHigh, d.FileSizeLow),
-		modTime: mkModTime(d.LastWriteTime),
-		mode:    mkMode(d.FileAttributes),
-		sys:     mkSys(path, d.LastAccessTime, d.CreationTime),
-	}, nil
+	return fs, nil
 }
 
 // Lstat returns the FileInfo structure describing the named file.
@@ -75,22 +78,6 @@ func Lstat(name string) (fi FileInfo, err error) {
 	return Stat(name)
 }
 
-// statDevNull return FileInfo structure describing DevNull file ("NUL").
-// It creates invented data, since none of windows api will return
-// that information.
-func statDevNull() (fi FileInfo, err error) {
-	return &fileStat{
-		name: DevNull,
-		mode: ModeDevice | ModeCharDevice | 0666,
-		sys: &winSys{
-			// hopefully this will work for SameFile
-			vol:   0,
-			idxhi: 0,
-			idxlo: 0,
-		},
-	}, nil
-}
-
 // basename removes trailing slashes and the leading
 // directory name and drive letter from path name.
 func basename(name string) string {
@@ -168,91 +155,3 @@ func volumeName(path string) (v string) {
 	}
 	return ""
 }
-
-type winSys struct {
-	sync.Mutex
-	path              string
-	atime, ctime      syscall.Filetime
-	vol, idxhi, idxlo uint32
-}
-
-func mkSize(hi, lo uint32) int64 {
-	return int64(hi)<<32 + int64(lo)
-}
-
-func mkModTime(mtime syscall.Filetime) time.Time {
-	return time.Unix(0, mtime.Nanoseconds())
-}
-
-func mkMode(fa uint32) (m FileMode) {
-	if fa&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
-		m |= ModeDir
-	}
-	if fa&syscall.FILE_ATTRIBUTE_READONLY != 0 {
-		m |= 0444
-	} else {
-		m |= 0666
-	}
-	return m
-}
-
-func mkSys(path string, atime, ctime syscall.Filetime) *winSys {
-	return &winSys{
-		path:  path,
-		atime: atime,
-		ctime: ctime,
-	}
-}
-
-func mkSysFromFI(i *syscall.ByHandleFileInformation) *winSys {
-	return &winSys{
-		atime: i.LastAccessTime,
-		ctime: i.CreationTime,
-		vol:   i.VolumeSerialNumber,
-		idxhi: i.FileIndexHigh,
-		idxlo: i.FileIndexLow,
-	}
-}
-
-func (s *winSys) loadFileId() error {
-	if s.path == "" {
-		// already done
-		return nil
-	}
-	s.Lock()
-	defer s.Unlock()
-	h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(s.path), 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
-	if e != nil {
-		return e
-	}
-	defer syscall.CloseHandle(h)
-	var i syscall.ByHandleFileInformation
-	e = syscall.GetFileInformationByHandle(syscall.Handle(h), &i)
-	if e != nil {
-		return e
-	}
-	s.path = ""
-	s.vol = i.VolumeSerialNumber
-	s.idxhi = i.FileIndexHigh
-	s.idxlo = i.FileIndexLow
-	return nil
-}
-
-func sameFile(sys1, sys2 interface{}) bool {
-	s1 := sys1.(*winSys)
-	s2 := sys2.(*winSys)
-	e := s1.loadFileId()
-	if e != nil {
-		panic(e)
-	}
-	e = s2.loadFileId()
-	if e != nil {
-		panic(e)
-	}
-	return s1.vol == s2.vol && s1.idxhi == s2.idxhi && s1.idxlo == s2.idxlo
-}
-
-// For testing.
-func atime(fi FileInfo) time.Time {
-	return time.Unix(0, fi.Sys().(*winSys).atime.Nanoseconds())
-}
diff --git a/src/pkg/os/types.go b/src/pkg/os/types.go
index 0c95c9c..473d431 100644
--- a/src/pkg/os/types.go
+++ b/src/pkg/os/types.go
@@ -12,7 +12,7 @@ import (
 // Getpagesize returns the underlying system's memory page size.
 func Getpagesize() int { return syscall.Getpagesize() }
 
-// A FileInfo describes a file and is returned by Stat and Lstat
+// A FileInfo describes a file and is returned by Stat and Lstat.
 type FileInfo interface {
 	Name() string       // base name of the file
 	Size() int64        // length in bytes for regular files; system-dependent for others
@@ -88,26 +88,19 @@ func (m FileMode) IsDir() bool {
 	return m&ModeDir != 0
 }
 
+// IsRegular reports whether m describes a regular file.
+// That is, it tests that no mode type bits are set.
+func (m FileMode) IsRegular() bool {
+	return m&ModeType == 0
+}
+
 // Perm returns the Unix permission bits in m.
 func (m FileMode) Perm() FileMode {
 	return m & ModePerm
 }
 
-// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
-type fileStat struct {
-	name    string
-	size    int64
-	mode    FileMode
-	modTime time.Time
-	sys     interface{}
-}
-
-func (fs *fileStat) Name() string       { return fs.name }
-func (fs *fileStat) Size() int64        { return fs.size }
-func (fs *fileStat) Mode() FileMode     { return fs.mode }
-func (fs *fileStat) ModTime() time.Time { return fs.modTime }
-func (fs *fileStat) IsDir() bool        { return fs.mode.IsDir() }
-func (fs *fileStat) Sys() interface{}   { return fs.sys }
+func (fs *fileStat) Name() string { return fs.name }
+func (fs *fileStat) IsDir() bool  { return fs.Mode().IsDir() }
 
 // SameFile reports whether fi1 and fi2 describe the same file.
 // For example, on Unix this means that the device and inode fields
@@ -121,5 +114,5 @@ func SameFile(fi1, fi2 FileInfo) bool {
 	if !ok1 || !ok2 {
 		return false
 	}
-	return sameFile(fs1.sys, fs2.sys)
+	return sameFile(fs1, fs2)
 }
diff --git a/src/pkg/os/types_notwin.go b/src/pkg/os/types_notwin.go
new file mode 100644
index 0000000..ea1a073
--- /dev/null
+++ b/src/pkg/os/types_notwin.go
@@ -0,0 +1,25 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !windows
+
+package os
+
+import (
+	"time"
+)
+
+// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
+type fileStat struct {
+	name    string
+	size    int64
+	mode    FileMode
+	modTime time.Time
+	sys     interface{}
+}
+
+func (fs *fileStat) Size() int64        { return fs.size }
+func (fs *fileStat) Mode() FileMode     { return fs.mode }
+func (fs *fileStat) ModTime() time.Time { return fs.modTime }
+func (fs *fileStat) Sys() interface{}   { return fs.sys }
diff --git a/src/pkg/os/types_windows.go b/src/pkg/os/types_windows.go
new file mode 100644
index 0000000..3890168
--- /dev/null
+++ b/src/pkg/os/types_windows.go
@@ -0,0 +1,104 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+	"sync"
+	"syscall"
+	"time"
+)
+
+// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
+type fileStat struct {
+	name string
+	sys  syscall.Win32FileAttributeData
+
+	// used to implement SameFile
+	sync.Mutex
+	path  string
+	vol   uint32
+	idxhi uint32
+	idxlo uint32
+}
+
+func (fs *fileStat) Size() int64 {
+	return int64(fs.sys.FileSizeHigh)<<32 + int64(fs.sys.FileSizeLow)
+}
+
+func (fs *fileStat) Mode() (m FileMode) {
+	if fs == &devNullStat {
+		return ModeDevice | ModeCharDevice | 0666
+	}
+	if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
+		m |= ModeDir | 0111
+	}
+	if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY != 0 {
+		m |= 0444
+	} else {
+		m |= 0666
+	}
+	return m
+}
+
+func (fs *fileStat) ModTime() time.Time {
+	return time.Unix(0, fs.sys.LastWriteTime.Nanoseconds())
+}
+
+// Sys returns syscall.Win32FileAttributeData for file fs.
+func (fs *fileStat) Sys() interface{} { return &fs.sys }
+
+func (fs *fileStat) loadFileId() error {
+	fs.Lock()
+	defer fs.Unlock()
+	if fs.path == "" {
+		// already done
+		return nil
+	}
+	pathp, err := syscall.UTF16PtrFromString(fs.path)
+	if err != nil {
+		return err
+	}
+	h, err := syscall.CreateFile(pathp, 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
+	if err != nil {
+		return err
+	}
+	defer syscall.CloseHandle(h)
+	var i syscall.ByHandleFileInformation
+	err = syscall.GetFileInformationByHandle(syscall.Handle(h), &i)
+	if err != nil {
+		return err
+	}
+	fs.path = ""
+	fs.vol = i.VolumeSerialNumber
+	fs.idxhi = i.FileIndexHigh
+	fs.idxlo = i.FileIndexLow
+	return nil
+}
+
+// devNullStat is fileStat structure describing DevNull file ("NUL").
+var devNullStat = fileStat{
+	name: DevNull,
+	// hopefully this will work for SameFile
+	vol:   0,
+	idxhi: 0,
+	idxlo: 0,
+}
+
+func sameFile(fs1, fs2 *fileStat) bool {
+	e := fs1.loadFileId()
+	if e != nil {
+		return false
+	}
+	e = fs2.loadFileId()
+	if e != nil {
+		return false
+	}
+	return fs1.vol == fs2.vol && fs1.idxhi == fs2.idxhi && fs1.idxlo == fs2.idxlo
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return time.Unix(0, fi.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
+}
diff --git a/src/pkg/os/user/lookup.go b/src/pkg/os/user/lookup.go
new file mode 100644
index 0000000..09f00c7
--- /dev/null
+++ b/src/pkg/os/user/lookup.go
@@ -0,0 +1,22 @@
+// 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 user
+
+// Current returns the current user.
+func Current() (*User, error) {
+	return current()
+}
+
+// Lookup looks up a user by username. If the user cannot be found, the
+// returned error is of type UnknownUserError.
+func Lookup(username string) (*User, error) {
+	return lookup(username)
+}
+
+// LookupId looks up a user by userid. If the user cannot be found, the
+// returned error is of type UnknownUserIdError.
+func LookupId(uid string) (*User, error) {
+	return lookupId(uid)
+}
diff --git a/src/pkg/os/user/lookup_stubs.go b/src/pkg/os/user/lookup_stubs.go
index 415f869..ad06907 100644
--- a/src/pkg/os/user/lookup_stubs.go
+++ b/src/pkg/os/user/lookup_stubs.go
@@ -15,14 +15,14 @@ func init() {
 	implemented = false
 }
 
-func Current() (*User, error) {
+func current() (*User, error) {
 	return nil, fmt.Errorf("user: Current not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
 }
 
-func Lookup(username string) (*User, error) {
+func lookup(username string) (*User, error) {
 	return nil, fmt.Errorf("user: Lookup not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
 }
 
-func LookupId(string) (*User, error) {
+func lookupId(uid string) (*User, error) {
 	return nil, fmt.Errorf("user: LookupId not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
 }
diff --git a/src/pkg/os/user/lookup_unix.go b/src/pkg/os/user/lookup_unix.go
index 241957c..6095422 100644
--- a/src/pkg/os/user/lookup_unix.go
+++ b/src/pkg/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 freebsd linux
+// +build darwin freebsd linux netbsd openbsd
 // +build cgo
 
 package user
@@ -29,28 +29,23 @@ static int mygetpwuid_r(int uid, struct passwd *pwd,
 */
 import "C"
 
-// Current returns the current user. 
-func Current() (*User, error) {
-	return lookup(syscall.Getuid(), "", false)
+func current() (*User, error) {
+	return lookupUnix(syscall.Getuid(), "", false)
 }
 
-// Lookup looks up a user by username. If the user cannot be found,
-// the returned error is of type UnknownUserError.
-func Lookup(username string) (*User, error) {
-	return lookup(-1, username, true)
+func lookup(username string) (*User, error) {
+	return lookupUnix(-1, username, true)
 }
 
-// LookupId looks up a user by userid. If the user cannot be found,
-// the returned error is of type UnknownUserIdError.
-func LookupId(uid string) (*User, error) {
+func lookupId(uid string) (*User, error) {
 	i, e := strconv.Atoi(uid)
 	if e != nil {
 		return nil, e
 	}
-	return lookup(i, "", false)
+	return lookupUnix(i, "", false)
 }
 
-func lookup(uid int, username string, lookupByName bool) (*User, error) {
+func lookupUnix(uid int, username string, lookupByName bool) (*User, error) {
 	var pwd C.struct_passwd
 	var result *C.struct_passwd
 
diff --git a/src/pkg/os/user/lookup_windows.go b/src/pkg/os/user/lookup_windows.go
index 9936871..a0a8a4e 100644
--- a/src/pkg/os/user/lookup_windows.go
+++ b/src/pkg/os/user/lookup_windows.go
@@ -16,13 +16,21 @@ func lookupFullName(domain, username, domainAndUser string) (string, error) {
 		syscall.NameSamCompatible, syscall.NameDisplay, 50)
 	if e != nil {
 		// domain lookup failed, perhaps this pc is not part of domain
-		d := syscall.StringToUTF16Ptr(domain)
-		u := syscall.StringToUTF16Ptr(username)
-		var p *byte
-		e := syscall.NetUserGetInfo(d, u, 10, &p)
+		d, e := syscall.UTF16PtrFromString(domain)
+		if e != nil {
+			return "", e
+		}
+		u, e := syscall.UTF16PtrFromString(username)
 		if e != nil {
 			return "", e
 		}
+		var p *byte
+		e = syscall.NetUserGetInfo(d, u, 10, &p)
+		if e != nil {
+			// path executed when a domain user is disconnected from the domain
+			// pretend username is fullname
+			return username, nil
+		}
 		defer syscall.NetApiBufferFree(p)
 		i := (*syscall.UserInfo10)(unsafe.Pointer(p))
 		if i.FullName == nil {
@@ -60,8 +68,7 @@ func newUser(usid *syscall.SID, gid, dir string) (*User, error) {
 	return u, nil
 }
 
-// Current returns the current user.
-func Current() (*User, error) {
+func current() (*User, error) {
 	t, e := syscall.OpenCurrentProcessToken()
 	if e != nil {
 		return nil, e
@@ -95,8 +102,7 @@ func newUserFromSid(usid *syscall.SID) (*User, error) {
 	return newUser(usid, gid, dir)
 }
 
-// Lookup looks up a user by username.
-func Lookup(username string) (*User, error) {
+func lookup(username string) (*User, error) {
 	sid, _, t, e := syscall.LookupSID("", username)
 	if e != nil {
 		return nil, e
@@ -107,8 +113,7 @@ func Lookup(username string) (*User, error) {
 	return newUserFromSid(sid)
 }
 
-// LookupId looks up a user by userid.
-func LookupId(uid string) (*User, error) {
+func lookupId(uid string) (*User, error) {
 	sid, e := syscall.StringToSid(uid)
 	if e != nil {
 		return nil, e
diff --git a/src/pkg/os/user/user_test.go b/src/pkg/os/user/user_test.go
index b812ebc..444a9aa 100644
--- a/src/pkg/os/user/user_test.go
+++ b/src/pkg/os/user/user_test.go
@@ -5,41 +5,34 @@
 package user
 
 import (
-	"os"
 	"runtime"
 	"testing"
 )
 
-func skip(t *testing.T) bool {
+func check(t *testing.T) {
 	if !implemented {
-		t.Logf("user: not implemented; skipping tests")
-		return true
+		t.Skip("user: not implemented; skipping tests")
 	}
-
 	switch runtime.GOOS {
 	case "linux", "freebsd", "darwin", "windows":
-		return false
+		// test supported
+	default:
+		t.Skipf("user: Lookup not implemented on %q; skipping test", runtime.GOOS)
 	}
-
-	t.Logf("user: Lookup not implemented on %s; skipping test", runtime.GOOS)
-	return true
 }
 
 func TestCurrent(t *testing.T) {
-	if skip(t) {
-		return
-	}
+	check(t)
 
 	u, err := Current()
 	if err != nil {
 		t.Fatalf("Current: %v", err)
 	}
-	fi, err := os.Stat(u.HomeDir)
-	if err != nil || !fi.IsDir() {
-		t.Errorf("expected a valid HomeDir; stat(%q): err=%v", u.HomeDir, err)
+	if u.HomeDir == "" {
+		t.Errorf("didn't get a HomeDir")
 	}
 	if u.Username == "" {
-		t.Fatalf("didn't get a username")
+		t.Errorf("didn't get a username")
 	}
 }
 
@@ -55,8 +48,7 @@ func compare(t *testing.T, want, got *User) {
 	}
 	// TODO(brainman): fix it once we know how.
 	if runtime.GOOS == "windows" {
-		t.Log("skipping Gid and HomeDir comparisons")
-		return
+		t.Skip("skipping Gid and HomeDir comparisons")
 	}
 	if want.Gid != got.Gid {
 		t.Errorf("got Gid=%q; want %q", got.Gid, want.Gid)
@@ -67,9 +59,7 @@ func compare(t *testing.T, want, got *User) {
 }
 
 func TestLookup(t *testing.T) {
-	if skip(t) {
-		return
-	}
+	check(t)
 
 	want, err := Current()
 	if err != nil {
@@ -83,9 +73,7 @@ func TestLookup(t *testing.T) {
 }
 
 func TestLookupId(t *testing.T) {
-	if skip(t) {
-		return
-	}
+	check(t)
 
 	want, err := Current()
 	if err != nil {
diff --git a/src/pkg/path/filepath/example_unix_test.go b/src/pkg/path/filepath/example_unix_test.go
new file mode 100644
index 0000000..f3fe076
--- /dev/null
+++ b/src/pkg/path/filepath/example_unix_test.go
@@ -0,0 +1,39 @@
+// 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 !windows,!plan9
+
+package filepath_test
+
+import (
+	"fmt"
+	"path/filepath"
+)
+
+func ExampleSplitList() {
+	fmt.Println("On Unix:", filepath.SplitList("/a/b/c:/usr/bin"))
+	// Output:
+	// On Unix: [/a/b/c /usr/bin]
+}
+
+func ExampleRel() {
+	paths := []string{
+		"/a/b/c",
+		"/b/c",
+		"./b/c",
+	}
+	base := "/a"
+
+	fmt.Println("On Unix:")
+	for _, p := range paths {
+		rel, err := filepath.Rel(base, p)
+		fmt.Printf("%q: %q %v\n", p, rel, err)
+	}
+
+	// Output:
+	// On Unix:
+	// "/a/b/c": "b/c" <nil>
+	// "/b/c": "../b/c" <nil>
+	// "./b/c": "" Rel: can't make b/c relative to /a
+}
diff --git a/src/pkg/path/filepath/match_test.go b/src/pkg/path/filepath/match_test.go
index 7b0ea80..f1bc60e 100644
--- a/src/pkg/path/filepath/match_test.go
+++ b/src/pkg/path/filepath/match_test.go
@@ -2,10 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package filepath_test
+package filepath
 
 import (
-	. "path/filepath"
 	"runtime"
 	"strings"
 	"testing"
diff --git a/src/pkg/path/filepath/path.go b/src/pkg/path/filepath/path.go
index 815021b..f8c7e4b 100644
--- a/src/pkg/path/filepath/path.go
+++ b/src/pkg/path/filepath/path.go
@@ -13,6 +13,45 @@ import (
 	"strings"
 )
 
+// A lazybuf is a lazily constructed path buffer.
+// It supports append, reading previously appended bytes,
+// and retrieving the final string. It does not allocate a buffer
+// to hold the output until that output diverges from s.
+type lazybuf struct {
+	path       string
+	buf        []byte
+	w          int
+	volAndPath string
+	volLen     int
+}
+
+func (b *lazybuf) index(i int) byte {
+	if b.buf != nil {
+		return b.buf[i]
+	}
+	return b.path[i]
+}
+
+func (b *lazybuf) append(c byte) {
+	if b.buf == nil {
+		if b.w < len(b.path) && b.path[b.w] == c {
+			b.w++
+			return
+		}
+		b.buf = make([]byte, len(b.path))
+		copy(b.buf, b.path[:b.w])
+	}
+	b.buf[b.w] = c
+	b.w++
+}
+
+func (b *lazybuf) string() string {
+	if b.buf == nil {
+		return b.volAndPath[:b.volLen+b.w]
+	}
+	return b.volAndPath[:b.volLen] + string(b.buf[:b.w])
+}
+
 const (
 	Separator     = os.PathSeparator
 	ListSeparator = os.PathListSeparator
@@ -40,14 +79,15 @@ const (
 // Getting Dot-Dot Right,''
 // http://plan9.bell-labs.com/sys/doc/lexnames.html
 func Clean(path string) string {
-	vol := VolumeName(path)
-	path = path[len(vol):]
+	originalPath := path
+	volLen := volumeNameLen(path)
+	path = path[volLen:]
 	if path == "" {
-		if len(vol) > 1 && vol[1] != ':' {
+		if volLen > 1 && originalPath[1] != ':' {
 			// should be UNC
-			return FromSlash(vol)
+			return FromSlash(originalPath)
 		}
-		return vol + "."
+		return originalPath + "."
 	}
 	rooted := os.IsPathSeparator(path[0])
 
@@ -57,11 +97,11 @@ func Clean(path string) string {
 	//	dotdot is index in buf where .. must stop, either because
 	//		it is the leading slash or it is a leading ../../.. prefix.
 	n := len(path)
-	buf := []byte(path)
-	r, w, dotdot := 0, 0, 0
+	out := lazybuf{path: path, volAndPath: originalPath, volLen: volLen}
+	r, dotdot := 0, 0
 	if rooted {
-		buf[0] = Separator
-		r, w, dotdot = 1, 1, 1
+		out.append(Separator)
+		r, dotdot = 1, 1
 	}
 
 	for r < n {
@@ -76,46 +116,40 @@ func Clean(path string) string {
 			// .. element: remove to last separator
 			r += 2
 			switch {
-			case w > dotdot:
+			case out.w > dotdot:
 				// can backtrack
-				w--
-				for w > dotdot && !os.IsPathSeparator(buf[w]) {
-					w--
+				out.w--
+				for out.w > dotdot && !os.IsPathSeparator(out.index(out.w)) {
+					out.w--
 				}
 			case !rooted:
 				// cannot backtrack, but not rooted, so append .. element.
-				if w > 0 {
-					buf[w] = Separator
-					w++
+				if out.w > 0 {
+					out.append(Separator)
 				}
-				buf[w] = '.'
-				w++
-				buf[w] = '.'
-				w++
-				dotdot = w
+				out.append('.')
+				out.append('.')
+				dotdot = out.w
 			}
 		default:
 			// real path element.
 			// add slash if needed
-			if rooted && w != 1 || !rooted && w != 0 {
-				buf[w] = Separator
-				w++
+			if rooted && out.w != 1 || !rooted && out.w != 0 {
+				out.append(Separator)
 			}
 			// copy element
 			for ; r < n && !os.IsPathSeparator(path[r]); r++ {
-				buf[w] = path[r]
-				w++
+				out.append(path[r])
 			}
 		}
 	}
 
 	// Turn empty string into "."
-	if w == 0 {
-		buf[w] = '.'
-		w++
+	if out.w == 0 {
+		out.append('.')
 	}
 
-	return FromSlash(vol + string(buf[0:w]))
+	return FromSlash(out.string())
 }
 
 // ToSlash returns the result of replacing each separator character
@@ -142,10 +176,7 @@ func FromSlash(path string) string {
 // usually found in PATH or GOPATH environment variables.
 // Unlike strings.Split, SplitList returns an empty slice when passed an empty string.
 func SplitList(path string) []string {
-	if path == "" {
-		return []string{}
-	}
-	return strings.Split(path, string(ListSeparator))
+	return splitList(path)
 }
 
 // Split splits path immediately following the final Separator,
@@ -291,13 +322,18 @@ func Rel(basepath, targpath string) (string, error) {
 var SkipDir = errors.New("skip this directory")
 
 // WalkFunc is the type of the function called for each file or directory
-// visited by Walk.  If there was a problem walking to the file or directory
-// named by path, the incoming error will describe the problem and the
-// function can decide how to handle that error (and Walk will not descend
-// into that directory).  If an error is returned, processing stops.  The
-// sole exception is that if path is a directory and the function returns the
-// special value SkipDir, the contents of the directory are skipped
-// and processing continues as usual on the next file.
+// visited by Walk. The path argument contains the argument to Walk as a
+// prefix; that is, if Walk is called with "dir", which is a directory
+// containing the file "a", the walk function will be called with argument
+// "dir/a". The info argument is the os.FileInfo for the named path.
+//
+// If there was a problem walking to the file or directory named by path, the
+// incoming error will describe the problem and the function can decide how
+// to handle that error (and Walk will not descend into that directory). If
+// an error is returned, processing stops. The sole exception is that if path
+// is a directory and the function returns the special value SkipDir, the
+// contents of the directory are skipped and processing continues as usual on
+// the next file.
 type WalkFunc func(path string, info os.FileInfo, err error) error
 
 // walk recursively descends path, calling w.
@@ -335,6 +371,7 @@ func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
 // and directories are filtered by walkFn. The files are walked in lexical
 // order, which makes the output deterministic but means that for very
 // large directories Walk can be inefficient.
+// Walk does not follow symbolic links.
 func Walk(root string, walkFn WalkFunc) error {
 	info, err := os.Lstat(root)
 	if err != nil {
@@ -397,7 +434,8 @@ func Base(path string) string {
 }
 
 // Dir returns all but the last element of path, typically the path's directory.
-// Trailing path separators are removed before processing.
+// After dropping the final element, the path is Cleaned and trailing
+// slashes are removed.
 // If the path is empty, Dir returns ".".
 // If the path consists entirely of separators, Dir returns a single separator.
 // The returned path does not end in a separator unless it is the root directory.
@@ -417,3 +455,11 @@ func Dir(path string) string {
 	}
 	return vol + dir
 }
+
+// VolumeName returns leading volume name.
+// Given "C:\foo\bar" it returns "C:" under windows.
+// Given "\\host\share\foo" it returns "\\host\share".
+// On other platforms it returns "".
+func VolumeName(path string) (v string) {
+	return path[:volumeNameLen(path)]
+}
diff --git a/src/pkg/path/filepath/path_plan9.go b/src/pkg/path/filepath/path_plan9.go
index 59a5812..12e85aa 100644
--- a/src/pkg/path/filepath/path_plan9.go
+++ b/src/pkg/path/filepath/path_plan9.go
@@ -11,13 +11,20 @@ func IsAbs(path string) bool {
 	return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "#")
 }
 
-// VolumeName returns the leading volume name on Windows.
-// It returns "" elsewhere.
-func VolumeName(path string) string {
-	return ""
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
+	return 0
 }
 
 // HasPrefix exists for historical compatibility and should not be used.
 func HasPrefix(p, prefix string) bool {
 	return strings.HasPrefix(p, prefix)
 }
+
+func splitList(path string) []string {
+	if path == "" {
+		return []string{}
+	}
+	return strings.Split(path, string(ListSeparator))
+}
diff --git a/src/pkg/path/filepath/path_test.go b/src/pkg/path/filepath/path_test.go
index 070905f..e768ad3 100644
--- a/src/pkg/path/filepath/path_test.go
+++ b/src/pkg/path/filepath/path_test.go
@@ -20,7 +20,6 @@ type PathTest struct {
 
 var cleantests = []PathTest{
 	// Already clean
-	{"", "."},
 	{"abc", "abc"},
 	{"abc/def", "abc/def"},
 	{"a/b/c", "a/b/c"},
@@ -31,6 +30,9 @@ var cleantests = []PathTest{
 	{"/abc", "/abc"},
 	{"/", "/"},
 
+	// Empty is current dir
+	{"", "."},
+
 	// Remove trailing slash
 	{"abc/", "abc"},
 	{"abc/def/", "abc/def"},
@@ -61,6 +63,7 @@ var cleantests = []PathTest{
 	{"abc/def/../../..", ".."},
 	{"/abc/def/../../..", "/"},
 	{"abc/def/../../../ghi/jkl/../../../mno", "../../mno"},
+	{"/../abc", "/abc"},
 
 	// Combinations
 	{"abc/./../def", "def"},
@@ -99,6 +102,16 @@ func TestClean(t *testing.T) {
 		if s := filepath.Clean(test.path); s != test.result {
 			t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.result)
 		}
+		if s := filepath.Clean(test.result); s != test.result {
+			t.Errorf("Clean(%q) = %q, want %q", test.result, s, test.result)
+		}
+	}
+
+	for _, test := range tests {
+		allocs := testing.AllocsPerRun(100, func() { filepath.Clean(test.result) })
+		if allocs > 0 {
+			t.Errorf("Clean(%q): %v allocs, want zero", test.result, allocs)
+		}
 	}
 }
 
@@ -135,10 +148,36 @@ var splitlisttests = []SplitListTest{
 	{string([]byte{lsep, 'a', lsep, 'b'}), []string{"", "a", "b"}},
 }
 
+var winsplitlisttests = []SplitListTest{
+	// quoted
+	{`"a"`, []string{`a`}},
+
+	// semicolon
+	{`";"`, []string{`;`}},
+	{`"a;b"`, []string{`a;b`}},
+	{`";";`, []string{`;`, ``}},
+	{`;";"`, []string{``, `;`}},
+
+	// partially quoted
+	{`a";"b`, []string{`a;b`}},
+	{`a; ""b`, []string{`a`, ` b`}},
+	{`"a;b`, []string{`a;b`}},
+	{`""a;b`, []string{`a`, `b`}},
+	{`"""a;b`, []string{`a;b`}},
+	{`""""a;b`, []string{`a`, `b`}},
+	{`a";b`, []string{`a;b`}},
+	{`a;b";c`, []string{`a`, `b;c`}},
+	{`"a";b";c`, []string{`a`, `b;c`}},
+}
+
 func TestSplitList(t *testing.T) {
-	for _, test := range splitlisttests {
+	tests := splitlisttests
+	if runtime.GOOS == "windows" {
+		tests = append(tests, winsplitlisttests...)
+	}
+	for _, test := range tests {
 		if l := filepath.SplitList(test.list); !reflect.DeepEqual(l, test.result) {
-			t.Errorf("SplitList(%q) = %s, want %s", test.list, l, test.result)
+			t.Errorf("SplitList(%#q) = %#q, want %#q", test.list, l, test.result)
 		}
 	}
 }
@@ -684,10 +723,15 @@ func TestAbs(t *testing.T) {
 	}
 	defer os.RemoveAll(root)
 
+	wd, err := os.Getwd()
+	if err != nil {
+		t.Fatal("getwd failed: ", err)
+	}
 	err = os.Chdir(root)
 	if err != nil {
 		t.Fatal("chdir failed: ", err)
 	}
+	defer os.Chdir(wd)
 
 	for _, dir := range absTestDirs {
 		err = os.Mkdir(dir, 0777)
@@ -871,7 +915,7 @@ func TestDriveLetterInEvalSymlinks(t *testing.T) {
 }
 
 func TestBug3486(t *testing.T) { // http://code.google.com/p/go/issues/detail?id=3486
-	root, err := filepath.EvalSymlinks(os.Getenv("GOROOT"))
+	root, err := filepath.EvalSymlinks(runtime.GOROOT())
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/src/pkg/path/filepath/path_unix.go b/src/pkg/path/filepath/path_unix.go
index 305e307..cff7b2c 100644
--- a/src/pkg/path/filepath/path_unix.go
+++ b/src/pkg/path/filepath/path_unix.go
@@ -13,13 +13,20 @@ func IsAbs(path string) bool {
 	return strings.HasPrefix(path, "/")
 }
 
-// VolumeName returns the leading volume name on Windows.
-// It returns "" elsewhere.
-func VolumeName(path string) string {
-	return ""
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
+	return 0
 }
 
 // HasPrefix exists for historical compatibility and should not be used.
 func HasPrefix(p, prefix string) bool {
 	return strings.HasPrefix(p, prefix)
 }
+
+func splitList(path string) []string {
+	if path == "" {
+		return []string{}
+	}
+	return strings.Split(path, string(ListSeparator))
+}
diff --git a/src/pkg/path/filepath/path_windows.go b/src/pkg/path/filepath/path_windows.go
index 3dcd030..e999972 100644
--- a/src/pkg/path/filepath/path_windows.go
+++ b/src/pkg/path/filepath/path_windows.go
@@ -14,29 +14,27 @@ func isSlash(c uint8) bool {
 
 // IsAbs returns true if the path is absolute.
 func IsAbs(path string) (b bool) {
-	v := VolumeName(path)
-	if v == "" {
+	l := volumeNameLen(path)
+	if l == 0 {
 		return false
 	}
-	path = path[len(v):]
+	path = path[l:]
 	if path == "" {
 		return false
 	}
 	return isSlash(path[0])
 }
 
-// VolumeName returns leading volume name.  
-// Given "C:\foo\bar" it returns "C:" under windows.
-// Given "\\host\share\foo" it returns "\\host\share".
-// On other platforms it returns "".
-func VolumeName(path string) (v string) {
+// volumeNameLen returns length of the leading volume name on Windows.
+// It returns 0 elsewhere.
+func volumeNameLen(path string) int {
 	if len(path) < 2 {
-		return ""
+		return 0
 	}
 	// with drive letter
 	c := path[0]
 	if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
-		return path[:2]
+		return 2
 	}
 	// is it UNC
 	if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&
@@ -56,13 +54,13 @@ func VolumeName(path string) (v string) {
 							break
 						}
 					}
-					return path[:n]
+					return n
 				}
 				break
 			}
 		}
 	}
-	return ""
+	return 0
 }
 
 // HasPrefix exists for historical compatibility and should not be used.
@@ -72,3 +70,36 @@ func HasPrefix(p, prefix string) bool {
 	}
 	return strings.HasPrefix(strings.ToLower(p), strings.ToLower(prefix))
 }
+
+func splitList(path string) []string {
+	// The same implementation is used in LookPath in os/exec;
+	// consider changing os/exec when changing this.
+
+	if path == "" {
+		return []string{}
+	}
+
+	// Split path, respecting but preserving quotes.
+	list := []string{}
+	start := 0
+	quo := false
+	for i := 0; i < len(path); i++ {
+		switch c := path[i]; {
+		case c == '"':
+			quo = !quo
+		case c == ListSeparator && !quo:
+			list = append(list, path[start:i])
+			start = i + 1
+		}
+	}
+	list = append(list, path[start:])
+
+	// Remove quotes.
+	for i, s := range list {
+		if strings.Contains(s, `"`) {
+			list[i] = strings.Replace(s, `"`, ``, -1)
+		}
+	}
+
+	return list
+}
diff --git a/src/pkg/path/filepath/path_windows_test.go b/src/pkg/path/filepath/path_windows_test.go
new file mode 100644
index 0000000..d8926ad
--- /dev/null
+++ b/src/pkg/path/filepath/path_windows_test.go
@@ -0,0 +1,89 @@
+package filepath_test
+
+import (
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"reflect"
+	"testing"
+)
+
+func TestWinSplitListTestsAreValid(t *testing.T) {
+	comspec := os.Getenv("ComSpec")
+	if comspec == "" {
+		t.Fatal("%ComSpec% must be set")
+	}
+
+	for ti, tt := range winsplitlisttests {
+		testWinSplitListTestIsValid(t, ti, tt, comspec)
+	}
+}
+
+func testWinSplitListTestIsValid(t *testing.T, ti int, tt SplitListTest,
+	comspec string) {
+
+	const (
+		cmdfile             = `printdir.cmd`
+		perm    os.FileMode = 0700
+	)
+
+	tmp, err := ioutil.TempDir("", "testWinSplitListTestIsValid")
+	if err != nil {
+		t.Fatalf("TempDir failed: %v", err)
+	}
+	defer os.RemoveAll(tmp)
+
+	for i, d := range tt.result {
+		if d == "" {
+			continue
+		}
+		if cd := filepath.Clean(d); filepath.VolumeName(cd) != "" ||
+			cd[0] == '\\' || cd == ".." || (len(cd) >= 3 && cd[0:3] == `..\`) {
+			t.Errorf("%d,%d: %#q refers outside working directory", ti, i, d)
+			return
+		}
+		dd := filepath.Join(tmp, d)
+		if _, err := os.Stat(dd); err == nil {
+			t.Errorf("%d,%d: %#q already exists", ti, i, d)
+			return
+		}
+		if err = os.MkdirAll(dd, perm); err != nil {
+			t.Errorf("%d,%d: MkdirAll(%#q) failed: %v", ti, i, dd, err)
+			return
+		}
+		fn, data := filepath.Join(dd, cmdfile), []byte("@echo "+d+"\r\n")
+		if err = ioutil.WriteFile(fn, data, perm); err != nil {
+			t.Errorf("%d,%d: WriteFile(%#q) failed: %v", ti, i, fn, err)
+			return
+		}
+	}
+
+	for i, d := range tt.result {
+		if d == "" {
+			continue
+		}
+		exp := []byte(d + "\r\n")
+		cmd := &exec.Cmd{
+			Path: comspec,
+			Args: []string{`/c`, cmdfile},
+			Env:  []string{`Path=` + tt.list},
+			Dir:  tmp,
+		}
+		out, err := cmd.CombinedOutput()
+		switch {
+		case err != nil:
+			t.Errorf("%d,%d: execution error %v\n%q", ti, i, err, out)
+			return
+		case !reflect.DeepEqual(out, exp):
+			t.Errorf("%d,%d: expected %#q, got %#q", ti, i, exp, out)
+			return
+		default:
+			// unshadow cmdfile in next directory
+			err = os.Remove(filepath.Join(tmp, d, cmdfile))
+			if err != nil {
+				t.Fatalf("Remove test command failed: %v", err)
+			}
+		}
+	}
+}
diff --git a/src/pkg/path/filepath/symlink_windows.go b/src/pkg/path/filepath/symlink_windows.go
index 1ee9399..9adc8a4 100644
--- a/src/pkg/path/filepath/symlink_windows.go
+++ b/src/pkg/path/filepath/symlink_windows.go
@@ -9,7 +9,10 @@ import (
 )
 
 func toShort(path string) (string, error) {
-	p := syscall.StringToUTF16(path)
+	p, err := syscall.UTF16FromString(path)
+	if err != nil {
+		return "", err
+	}
 	b := p // GetShortPathName says we can reuse buffer
 	n, err := syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
 	if err != nil {
@@ -26,7 +29,10 @@ func toShort(path string) (string, error) {
 }
 
 func toLong(path string) (string, error) {
-	p := syscall.StringToUTF16(path)
+	p, err := syscall.UTF16FromString(path)
+	if err != nil {
+		return "", err
+	}
 	b := p // GetLongPathName says we can reuse buffer
 	n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b)))
 	if err != nil {
diff --git a/src/pkg/path/path.go b/src/pkg/path/path.go
index a7e0415..bdb85c6 100644
--- a/src/pkg/path/path.go
+++ b/src/pkg/path/path.go
@@ -10,6 +10,43 @@ import (
 	"strings"
 )
 
+// A lazybuf is a lazily constructed path buffer.
+// It supports append, reading previously appended bytes,
+// and retrieving the final string. It does not allocate a buffer
+// to hold the output until that output diverges from s.
+type lazybuf struct {
+	s   string
+	buf []byte
+	w   int
+}
+
+func (b *lazybuf) index(i int) byte {
+	if b.buf != nil {
+		return b.buf[i]
+	}
+	return b.s[i]
+}
+
+func (b *lazybuf) append(c byte) {
+	if b.buf == nil {
+		if b.w < len(b.s) && b.s[b.w] == c {
+			b.w++
+			return
+		}
+		b.buf = make([]byte, len(b.s))
+		copy(b.buf, b.s[:b.w])
+	}
+	b.buf[b.w] = c
+	b.w++
+}
+
+func (b *lazybuf) string() string {
+	if b.buf == nil {
+		return b.s[:b.w]
+	}
+	return string(b.buf[:b.w])
+}
+
 // Clean returns the shortest path name equivalent to path
 // by purely lexical processing.  It applies the following rules
 // iteratively until no further processing can be done:
@@ -42,10 +79,11 @@ func Clean(path string) string {
 	//	writing to buf; w is index of next byte to write.
 	//	dotdot is index in buf where .. must stop, either because
 	//		it is the leading slash or it is a leading ../../.. prefix.
-	buf := []byte(path)
-	r, w, dotdot := 0, 0, 0
+	out := lazybuf{s: path}
+	r, dotdot := 0, 0
 	if rooted {
-		r, w, dotdot = 1, 1, 1
+		out.append('/')
+		r, dotdot = 1, 1
 	}
 
 	for r < n {
@@ -60,46 +98,40 @@ func Clean(path string) string {
 			// .. element: remove to last /
 			r += 2
 			switch {
-			case w > dotdot:
+			case out.w > dotdot:
 				// can backtrack
-				w--
-				for w > dotdot && buf[w] != '/' {
-					w--
+				out.w--
+				for out.w > dotdot && out.index(out.w) != '/' {
+					out.w--
 				}
 			case !rooted:
 				// cannot backtrack, but not rooted, so append .. element.
-				if w > 0 {
-					buf[w] = '/'
-					w++
+				if out.w > 0 {
+					out.append('/')
 				}
-				buf[w] = '.'
-				w++
-				buf[w] = '.'
-				w++
-				dotdot = w
+				out.append('.')
+				out.append('.')
+				dotdot = out.w
 			}
 		default:
 			// real path element.
 			// add slash if needed
-			if rooted && w != 1 || !rooted && w != 0 {
-				buf[w] = '/'
-				w++
+			if rooted && out.w != 1 || !rooted && out.w != 0 {
+				out.append('/')
 			}
 			// copy element
 			for ; r < n && path[r] != '/'; r++ {
-				buf[w] = path[r]
-				w++
+				out.append(path[r])
 			}
 		}
 	}
 
 	// Turn empty string into "."
-	if w == 0 {
-		buf[w] = '.'
-		w++
+	if out.w == 0 {
+		return "."
 	}
 
-	return string(buf[0:w])
+	return out.string()
 }
 
 // Split splits path immediately following the final slash.
@@ -166,7 +198,8 @@ func IsAbs(path string) bool {
 }
 
 // Dir returns all but the last element of path, typically the path's directory.
-// The path is Cleaned and trailing slashes are removed before processing.
+// After dropping the final element using Split, the path is Cleaned and trailing
+// slashes are removed.
 // If the path is empty, Dir returns ".".
 // If the path consists entirely of slashes followed by non-slash bytes, Dir
 // returns a single slash. In any other case, the returned path does not end in a
diff --git a/src/pkg/path/path_test.go b/src/pkg/path/path_test.go
index 77f0804..220ec1a 100644
--- a/src/pkg/path/path_test.go
+++ b/src/pkg/path/path_test.go
@@ -67,6 +67,16 @@ func TestClean(t *testing.T) {
 		if s := Clean(test.path); s != test.result {
 			t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.result)
 		}
+		if s := Clean(test.result); s != test.result {
+			t.Errorf("Clean(%q) = %q, want %q", test.result, s, test.result)
+		}
+	}
+
+	for _, test := range cleantests {
+		allocs := testing.AllocsPerRun(100, func() { Clean(test.result) })
+		if allocs > 0 {
+			t.Errorf("Clean(%q): %v allocs, want zero", test.result, allocs)
+		}
 	}
 }
 
@@ -181,6 +191,7 @@ var dirtests = []PathTest{
 	{"x/", "x"},
 	{"abc", "."},
 	{"abc/def", "abc"},
+	{"abc////def", "abc"},
 	{"a/b/.x", "a/b"},
 	{"a/b/c.", "a/b"},
 	{"a/b/c.x", "a/b"},
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go
index e331405..6f006db 100644
--- a/src/pkg/reflect/all_test.go
+++ b/src/pkg/reflect/all_test.go
@@ -7,12 +7,15 @@ package reflect_test
 import (
 	"bytes"
 	"encoding/base64"
+	"flag"
 	"fmt"
 	"io"
+	"math/rand"
 	"os"
 	. "reflect"
-	"runtime"
+	"sync"
 	"testing"
+	"time"
 	"unsafe"
 )
 
@@ -1053,26 +1056,393 @@ func TestChan(t *testing.T) {
 	if l, m := cv.Len(), cv.Cap(); l != len(c) || m != cap(c) {
 		t.Errorf("Len/Cap = %d/%d want %d/%d", l, m, len(c), cap(c))
 	}
+}
 
+// caseInfo describes a single case in a select test.
+type caseInfo struct {
+	desc      string
+	canSelect bool
+	recv      Value
+	closed    bool
+	helper    func()
+	panic     bool
 }
 
+var allselect = flag.Bool("allselect", false, "exhaustive select test")
+
+func TestSelect(t *testing.T) {
+	selectWatch.once.Do(func() { go selectWatcher() })
+
+	var x exhaustive
+	nch := 0
+	newop := func(n int, cap int) (ch, val Value) {
+		nch++
+		if nch%101%2 == 1 {
+			c := make(chan int, cap)
+			ch = ValueOf(c)
+			val = ValueOf(n)
+		} else {
+			c := make(chan string, cap)
+			ch = ValueOf(c)
+			val = ValueOf(fmt.Sprint(n))
+		}
+		return
+	}
+
+	for n := 0; x.Next(); n++ {
+		if testing.Short() && n >= 1000 {
+			break
+		}
+		if n >= 100000 && !*allselect {
+			break
+		}
+		if n%100000 == 0 && testing.Verbose() {
+			println("TestSelect", n)
+		}
+		var cases []SelectCase
+		var info []caseInfo
+
+		// Ready send.
+		if x.Maybe() {
+			ch, val := newop(len(cases), 1)
+			cases = append(cases, SelectCase{
+				Dir:  SelectSend,
+				Chan: ch,
+				Send: val,
+			})
+			info = append(info, caseInfo{desc: "ready send", canSelect: true})
+		}
+
+		// Ready recv.
+		if x.Maybe() {
+			ch, val := newop(len(cases), 1)
+			ch.Send(val)
+			cases = append(cases, SelectCase{
+				Dir:  SelectRecv,
+				Chan: ch,
+			})
+			info = append(info, caseInfo{desc: "ready recv", canSelect: true, recv: val})
+		}
+
+		// Blocking send.
+		if x.Maybe() {
+			ch, val := newop(len(cases), 0)
+			cases = append(cases, SelectCase{
+				Dir:  SelectSend,
+				Chan: ch,
+				Send: val,
+			})
+			// Let it execute?
+			if x.Maybe() {
+				f := func() { ch.Recv() }
+				info = append(info, caseInfo{desc: "blocking send", helper: f})
+			} else {
+				info = append(info, caseInfo{desc: "blocking send"})
+			}
+		}
+
+		// Blocking recv.
+		if x.Maybe() {
+			ch, val := newop(len(cases), 0)
+			cases = append(cases, SelectCase{
+				Dir:  SelectRecv,
+				Chan: ch,
+			})
+			// Let it execute?
+			if x.Maybe() {
+				f := func() { ch.Send(val) }
+				info = append(info, caseInfo{desc: "blocking recv", recv: val, helper: f})
+			} else {
+				info = append(info, caseInfo{desc: "blocking recv"})
+			}
+		}
+
+		// Zero Chan send.
+		if x.Maybe() {
+			// Maybe include value to send.
+			var val Value
+			if x.Maybe() {
+				val = ValueOf(100)
+			}
+			cases = append(cases, SelectCase{
+				Dir:  SelectSend,
+				Send: val,
+			})
+			info = append(info, caseInfo{desc: "zero Chan send"})
+		}
+
+		// Zero Chan receive.
+		if x.Maybe() {
+			cases = append(cases, SelectCase{
+				Dir: SelectRecv,
+			})
+			info = append(info, caseInfo{desc: "zero Chan recv"})
+		}
+
+		// nil Chan send.
+		if x.Maybe() {
+			cases = append(cases, SelectCase{
+				Dir:  SelectSend,
+				Chan: ValueOf((chan int)(nil)),
+				Send: ValueOf(101),
+			})
+			info = append(info, caseInfo{desc: "nil Chan send"})
+		}
+
+		// nil Chan recv.
+		if x.Maybe() {
+			cases = append(cases, SelectCase{
+				Dir:  SelectRecv,
+				Chan: ValueOf((chan int)(nil)),
+			})
+			info = append(info, caseInfo{desc: "nil Chan recv"})
+		}
+
+		// closed Chan send.
+		if x.Maybe() {
+			ch := make(chan int)
+			close(ch)
+			cases = append(cases, SelectCase{
+				Dir:  SelectSend,
+				Chan: ValueOf(ch),
+				Send: ValueOf(101),
+			})
+			info = append(info, caseInfo{desc: "closed Chan send", canSelect: true, panic: true})
+		}
+
+		// closed Chan recv.
+		if x.Maybe() {
+			ch, val := newop(len(cases), 0)
+			ch.Close()
+			val = Zero(val.Type())
+			cases = append(cases, SelectCase{
+				Dir:  SelectRecv,
+				Chan: ch,
+			})
+			info = append(info, caseInfo{desc: "closed Chan recv", canSelect: true, closed: true, recv: val})
+		}
+
+		var helper func() // goroutine to help the select complete
+
+		// Add default? Must be last case here, but will permute.
+		// Add the default if the select would otherwise
+		// block forever, and maybe add it anyway.
+		numCanSelect := 0
+		canProceed := false
+		canBlock := true
+		canPanic := false
+		helpers := []int{}
+		for i, c := range info {
+			if c.canSelect {
+				canProceed = true
+				canBlock = false
+				numCanSelect++
+				if c.panic {
+					canPanic = true
+				}
+			} else if c.helper != nil {
+				canProceed = true
+				helpers = append(helpers, i)
+			}
+		}
+		if !canProceed || x.Maybe() {
+			cases = append(cases, SelectCase{
+				Dir: SelectDefault,
+			})
+			info = append(info, caseInfo{desc: "default", canSelect: canBlock})
+			numCanSelect++
+		} else if canBlock {
+			// Select needs to communicate with another goroutine.
+			cas := &info[helpers[x.Choose(len(helpers))]]
+			helper = cas.helper
+			cas.canSelect = true
+			numCanSelect++
+		}
+
+		// Permute cases and case info.
+		// Doing too much here makes the exhaustive loop
+		// too exhausting, so just do two swaps.
+		for loop := 0; loop < 2; loop++ {
+			i := x.Choose(len(cases))
+			j := x.Choose(len(cases))
+			cases[i], cases[j] = cases[j], cases[i]
+			info[i], info[j] = info[j], info[i]
+		}
+
+		if helper != nil {
+			// We wait before kicking off a goroutine to satisfy a blocked select.
+			// The pause needs to be big enough to let the select block before
+			// we run the helper, but if we lose that race once in a while it's okay: the
+			// select will just proceed immediately. Not a big deal.
+			// For short tests we can grow [sic] the timeout a bit without fear of taking too long
+			pause := 10 * time.Microsecond
+			if testing.Short() {
+				pause = 100 * time.Microsecond
+			}
+			time.AfterFunc(pause, helper)
+		}
+
+		// Run select.
+		i, recv, recvOK, panicErr := runSelect(cases, info)
+		if panicErr != nil && !canPanic {
+			t.Fatalf("%s\npanicked unexpectedly: %v", fmtSelect(info), panicErr)
+		}
+		if panicErr == nil && canPanic && numCanSelect == 1 {
+			t.Fatalf("%s\nselected #%d incorrectly (should panic)", fmtSelect(info), i)
+		}
+		if panicErr != nil {
+			continue
+		}
+
+		cas := info[i]
+		if !cas.canSelect {
+			recvStr := ""
+			if recv.IsValid() {
+				recvStr = fmt.Sprintf(", received %v, %v", recv.Interface(), recvOK)
+			}
+			t.Fatalf("%s\nselected #%d incorrectly%s", fmtSelect(info), i, recvStr)
+			continue
+		}
+		if cas.panic {
+			t.Fatalf("%s\nselected #%d incorrectly (case should panic)", fmtSelect(info), i)
+			continue
+		}
+
+		if cases[i].Dir == SelectRecv {
+			if !recv.IsValid() {
+				t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, cas.recv.Interface(), !cas.closed)
+			}
+			if !cas.recv.IsValid() {
+				t.Fatalf("%s\nselected #%d but internal error: missing recv value", fmtSelect(info), i)
+			}
+			if recv.Interface() != cas.recv.Interface() || recvOK != !cas.closed {
+				if recv.Interface() == cas.recv.Interface() && recvOK == !cas.closed {
+					t.Fatalf("%s\nselected #%d, got %#v, %v, and DeepEqual is broken on %T", fmtSelect(info), i, recv.Interface(), recvOK, recv.Interface())
+				}
+				t.Fatalf("%s\nselected #%d but got %#v, %v, want %#v, %v", fmtSelect(info), i, recv.Interface(), recvOK, cas.recv.Interface(), !cas.closed)
+			}
+		} else {
+			if recv.IsValid() || recvOK {
+				t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, Value{}, false)
+			}
+		}
+	}
+}
+
+// selectWatch and the selectWatcher are a watchdog mechanism for running Select.
+// If the selectWatcher notices that the select has been blocked for >1 second, it prints
+// an error describing the select and panics the entire test binary.
+var selectWatch struct {
+	sync.Mutex
+	once sync.Once
+	now  time.Time
+	info []caseInfo
+}
+
+func selectWatcher() {
+	for {
+		time.Sleep(1 * time.Second)
+		selectWatch.Lock()
+		if selectWatch.info != nil && time.Since(selectWatch.now) > 1*time.Second {
+			fmt.Fprintf(os.Stderr, "TestSelect:\n%s blocked indefinitely\n", fmtSelect(selectWatch.info))
+			panic("select stuck")
+		}
+		selectWatch.Unlock()
+	}
+}
+
+// runSelect runs a single select test.
+// It returns the values returned by Select but also returns
+// a panic value if the Select panics.
+func runSelect(cases []SelectCase, info []caseInfo) (chosen int, recv Value, recvOK bool, panicErr interface{}) {
+	defer func() {
+		panicErr = recover()
+
+		selectWatch.Lock()
+		selectWatch.info = nil
+		selectWatch.Unlock()
+	}()
+
+	selectWatch.Lock()
+	selectWatch.now = time.Now()
+	selectWatch.info = info
+	selectWatch.Unlock()
+
+	chosen, recv, recvOK = Select(cases)
+	return
+}
+
+// fmtSelect formats the information about a single select test.
+func fmtSelect(info []caseInfo) string {
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "\nselect {\n")
+	for i, cas := range info {
+		fmt.Fprintf(&buf, "%d: %s", i, cas.desc)
+		if cas.recv.IsValid() {
+			fmt.Fprintf(&buf, " val=%#v", cas.recv.Interface())
+		}
+		if cas.canSelect {
+			fmt.Fprintf(&buf, " canselect")
+		}
+		if cas.panic {
+			fmt.Fprintf(&buf, " panic")
+		}
+		fmt.Fprintf(&buf, "\n")
+	}
+	fmt.Fprintf(&buf, "}")
+	return buf.String()
+}
+
+type two [2]uintptr
+
 // Difficult test for function call because of
 // implicit padding between arguments.
-func dummy(b byte, c int, d byte) (i byte, j int, k byte) {
-	return b, c, d
+func dummy(b byte, c int, d byte, e two, f byte, g float32, h byte) (i byte, j int, k byte, l two, m byte, n float32, o byte) {
+	return b, c, d, e, f, g, h
 }
 
 func TestFunc(t *testing.T) {
-	ret := ValueOf(dummy).Call([]Value{ValueOf(byte(10)), ValueOf(20), ValueOf(byte(30))})
-	if len(ret) != 3 {
-		t.Fatalf("Call returned %d values, want 3", len(ret))
+	ret := ValueOf(dummy).Call([]Value{
+		ValueOf(byte(10)),
+		ValueOf(20),
+		ValueOf(byte(30)),
+		ValueOf(two{40, 50}),
+		ValueOf(byte(60)),
+		ValueOf(float32(70)),
+		ValueOf(byte(80)),
+	})
+	if len(ret) != 7 {
+		t.Fatalf("Call returned %d values, want 7", len(ret))
 	}
 
 	i := byte(ret[0].Uint())
 	j := int(ret[1].Int())
 	k := byte(ret[2].Uint())
-	if i != 10 || j != 20 || k != 30 {
-		t.Errorf("Call returned %d, %d, %d; want 10, 20, 30", i, j, k)
+	l := ret[3].Interface().(two)
+	m := byte(ret[4].Uint())
+	n := float32(ret[5].Float())
+	o := byte(ret[6].Uint())
+
+	if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
+		t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
+	}
+}
+
+func TestMakeFunc(t *testing.T) {
+	f := dummy
+	fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })
+	ValueOf(&f).Elem().Set(fv)
+
+	// Call g with small arguments so that there is
+	// something predictable (and different from the
+	// correct results) in those positions on the stack.
+	g := dummy
+	g(1, 2, 3, two{4, 5}, 6, 7, 8)
+
+	// Call constructed function f.
+	i, j, k, l, m, n, o := f(10, 20, 30, two{40, 50}, 60, 70, 80)
+	if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
+		t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
 	}
 }
 
@@ -1123,7 +1493,7 @@ func TestMethod(t *testing.T) {
 	}
 
 	// Curried method of value.
-	tfunc := TypeOf(func(int) int(nil))
+	tfunc := TypeOf((func(int) int)(nil))
 	v := ValueOf(p).Method(1)
 	if tt := v.Type(); tt != tfunc {
 		t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
@@ -1225,7 +1595,7 @@ func TestAnonymousFields(t *testing.T) {
 	var t1 T1
 	type1 := TypeOf(t1)
 	if field, ok = type1.FieldByName("int"); !ok {
-		t.Error("no field 'int'")
+		t.Fatal("no field 'int'")
 	}
 	if field.Index[0] != 1 {
 		t.Error("field index should be 1; is", field.Index)
@@ -1282,6 +1652,61 @@ type S4 struct {
 	A int
 }
 
+// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
+type S5 struct {
+	S6
+	S7
+	S8
+}
+
+type S6 struct {
+	X int
+}
+
+type S7 S6
+
+type S8 struct {
+	S9
+}
+
+type S9 struct {
+	X int
+	Y int
+}
+
+// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
+type S10 struct {
+	S11
+	S12
+	S13
+}
+
+type S11 struct {
+	S6
+}
+
+type S12 struct {
+	S6
+}
+
+type S13 struct {
+	S8
+}
+
+// The X in S15.S11.S1 and S16.S11.S1 annihilate.
+type S14 struct {
+	S15
+	S16
+}
+
+type S15 struct {
+	S11
+}
+
+type S16 struct {
+	S11
+}
+
 var fieldTests = []FTest{
 	{struct{}{}, "", nil, 0},
 	{struct{}{}, "Foo", nil, 0},
@@ -1303,6 +1728,11 @@ var fieldTests = []FTest{
 	{S3{E: 'e'}, "E", []int{3}, 'e'},
 	{S4{A: 'a'}, "A", []int{1}, 'a'},
 	{S4{}, "B", nil, 0},
+	{S5{}, "X", nil, 0},
+	{S5{}, "Y", []int{2, 0, 1}, 0},
+	{S10{}, "X", nil, 0},
+	{S10{}, "Y", []int{2, 0, 0, 1}, 0},
+	{S14{}, "X", nil, 0},
 }
 
 func TestFieldByIndex(t *testing.T) {
@@ -1346,7 +1776,7 @@ func TestFieldByName(t *testing.T) {
 			if test.index != nil {
 				// Verify field depth and index.
 				if len(f.Index) != len(test.index) {
-					t.Errorf("%s.%s depth %d; want %d", s.Name(), test.name, len(f.Index), len(test.index))
+					t.Errorf("%s.%s depth %d; want %d: %v vs %v", s.Name(), test.name, len(f.Index), len(test.index), f.Index, test.index)
 				} else {
 					for i, x := range f.Index {
 						if x != test.index[i] {
@@ -1384,7 +1814,30 @@ func TestImportPath(t *testing.T) {
 		path string
 	}{
 		{TypeOf(&base64.Encoding{}).Elem(), "encoding/base64"},
+		{TypeOf(int(0)), ""},
+		{TypeOf(int8(0)), ""},
+		{TypeOf(int16(0)), ""},
+		{TypeOf(int32(0)), ""},
+		{TypeOf(int64(0)), ""},
 		{TypeOf(uint(0)), ""},
+		{TypeOf(uint8(0)), ""},
+		{TypeOf(uint16(0)), ""},
+		{TypeOf(uint32(0)), ""},
+		{TypeOf(uint64(0)), ""},
+		{TypeOf(uintptr(0)), ""},
+		{TypeOf(float32(0)), ""},
+		{TypeOf(float64(0)), ""},
+		{TypeOf(complex64(0)), ""},
+		{TypeOf(complex128(0)), ""},
+		{TypeOf(byte(0)), ""},
+		{TypeOf(rune(0)), ""},
+		{TypeOf([]byte(nil)), ""},
+		{TypeOf([]rune(nil)), ""},
+		{TypeOf(string("")), ""},
+		{TypeOf((*interface{})(nil)).Elem(), ""},
+		{TypeOf((*byte)(nil)), ""},
+		{TypeOf((*rune)(nil)), ""},
+		{TypeOf((*int64)(nil)), ""},
 		{TypeOf(map[string]int{}), ""},
 		{TypeOf((*error)(nil)).Elem(), ""},
 	}
@@ -1558,21 +2011,13 @@ func TestAddr(t *testing.T) {
 }
 
 func noAlloc(t *testing.T, n int, f func(int)) {
-	// once to prime everything
-	f(-1)
-	memstats := new(runtime.MemStats)
-	runtime.ReadMemStats(memstats)
-	oldmallocs := memstats.Mallocs
-
-	for j := 0; j < n; j++ {
-		f(j)
-	}
-	// A few allocs may happen in the testing package when GOMAXPROCS > 1, so don't
-	// require zero mallocs.
-	runtime.ReadMemStats(memstats)
-	mallocs := memstats.Mallocs - oldmallocs
-	if mallocs > 5 {
-		t.Fatalf("%d mallocs after %d iterations", mallocs, n)
+	i := -1
+	allocs := testing.AllocsPerRun(n, func() {
+		f(i)
+		i++
+	})
+	if allocs > 0 {
+		t.Errorf("%d iterations: got %v mallocs, want 0", n, allocs)
 	}
 }
 
@@ -1596,6 +2041,24 @@ func TestSmallNegativeInt(t *testing.T) {
 	}
 }
 
+func TestIndex(t *testing.T) {
+	xs := []byte{1, 2, 3, 4, 5, 6, 7, 8}
+	v := ValueOf(xs).Index(3).Interface().(byte)
+	if v != xs[3] {
+		t.Errorf("xs.Index(3) = %v; expected %v", v, xs[3])
+	}
+	xa := [8]byte{10, 20, 30, 40, 50, 60, 70, 80}
+	v = ValueOf(xa).Index(2).Interface().(byte)
+	if v != xa[2] {
+		t.Errorf("xa.Index(2) = %v; expected %v", v, xa[2])
+	}
+	s := "0123456789"
+	v = ValueOf(s).Index(3).Interface().(byte)
+	if v != s[3] {
+		t.Errorf("s.Index(3) = %v; expected %v", v, s[3])
+	}
+}
+
 func TestSlice(t *testing.T) {
 	xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
 	v := ValueOf(xs).Slice(3, 5).Interface().([]int)
@@ -1608,7 +2071,6 @@ func TestSlice(t *testing.T) {
 	if !DeepEqual(v[0:5], xs[3:]) {
 		t.Errorf("xs.Slice(3, 5)[0:5] = %v", v[0:5])
 	}
-
 	xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
 	v = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int)
 	if len(v) != 3 {
@@ -1620,6 +2082,11 @@ func TestSlice(t *testing.T) {
 	if !DeepEqual(v[0:6], xa[2:]) {
 		t.Errorf("xs.Slice(2, 5)[0:6] = %v", v[0:6])
 	}
+	s := "0123456789"
+	vs := ValueOf(s).Slice(3, 5).Interface().(string)
+	if vs != s[3:5] {
+		t.Errorf("s.Slice(3, 5) = %q; expected %q", vs, s[3:5])
+	}
 }
 
 func TestVariadic(t *testing.T) {
@@ -1760,3 +2227,761 @@ func TestAlias(t *testing.T) {
 		t.Errorf("aliasing: old=%q new=%q, want hello, world", oldvalue, newvalue)
 	}
 }
+
+var V = ValueOf
+
+func EmptyInterfaceV(x interface{}) Value {
+	return ValueOf(&x).Elem()
+}
+
+func ReaderV(x io.Reader) Value {
+	return ValueOf(&x).Elem()
+}
+
+func ReadWriterV(x io.ReadWriter) Value {
+	return ValueOf(&x).Elem()
+}
+
+type Empty struct{}
+type MyString string
+type MyBytes []byte
+type MyRunes []int32
+type MyFunc func()
+type MyByte byte
+
+var convertTests = []struct {
+	in  Value
+	out Value
+}{
+	// numbers
+	/*
+		Edit .+1,/\*\//-1>cat >/tmp/x.go && go run /tmp/x.go
+
+		package main
+
+		import "fmt"
+
+		var numbers = []string{
+			"int8", "uint8", "int16", "uint16",
+			"int32", "uint32", "int64", "uint64",
+			"int", "uint", "uintptr",
+			"float32", "float64",
+		}
+
+		func main() {
+			// all pairs but in an unusual order,
+			// to emit all the int8, uint8 cases
+			// before n grows too big.
+			n := 1
+			for i, f := range numbers {
+				for _, g := range numbers[i:] {
+					fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", f, n, g, n)
+					n++
+					if f != g {
+						fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", g, n, f, n)
+						n++
+					}
+				}
+			}
+		}
+	*/
+	{V(int8(1)), V(int8(1))},
+	{V(int8(2)), V(uint8(2))},
+	{V(uint8(3)), V(int8(3))},
+	{V(int8(4)), V(int16(4))},
+	{V(int16(5)), V(int8(5))},
+	{V(int8(6)), V(uint16(6))},
+	{V(uint16(7)), V(int8(7))},
+	{V(int8(8)), V(int32(8))},
+	{V(int32(9)), V(int8(9))},
+	{V(int8(10)), V(uint32(10))},
+	{V(uint32(11)), V(int8(11))},
+	{V(int8(12)), V(int64(12))},
+	{V(int64(13)), V(int8(13))},
+	{V(int8(14)), V(uint64(14))},
+	{V(uint64(15)), V(int8(15))},
+	{V(int8(16)), V(int(16))},
+	{V(int(17)), V(int8(17))},
+	{V(int8(18)), V(uint(18))},
+	{V(uint(19)), V(int8(19))},
+	{V(int8(20)), V(uintptr(20))},
+	{V(uintptr(21)), V(int8(21))},
+	{V(int8(22)), V(float32(22))},
+	{V(float32(23)), V(int8(23))},
+	{V(int8(24)), V(float64(24))},
+	{V(float64(25)), V(int8(25))},
+	{V(uint8(26)), V(uint8(26))},
+	{V(uint8(27)), V(int16(27))},
+	{V(int16(28)), V(uint8(28))},
+	{V(uint8(29)), V(uint16(29))},
+	{V(uint16(30)), V(uint8(30))},
+	{V(uint8(31)), V(int32(31))},
+	{V(int32(32)), V(uint8(32))},
+	{V(uint8(33)), V(uint32(33))},
+	{V(uint32(34)), V(uint8(34))},
+	{V(uint8(35)), V(int64(35))},
+	{V(int64(36)), V(uint8(36))},
+	{V(uint8(37)), V(uint64(37))},
+	{V(uint64(38)), V(uint8(38))},
+	{V(uint8(39)), V(int(39))},
+	{V(int(40)), V(uint8(40))},
+	{V(uint8(41)), V(uint(41))},
+	{V(uint(42)), V(uint8(42))},
+	{V(uint8(43)), V(uintptr(43))},
+	{V(uintptr(44)), V(uint8(44))},
+	{V(uint8(45)), V(float32(45))},
+	{V(float32(46)), V(uint8(46))},
+	{V(uint8(47)), V(float64(47))},
+	{V(float64(48)), V(uint8(48))},
+	{V(int16(49)), V(int16(49))},
+	{V(int16(50)), V(uint16(50))},
+	{V(uint16(51)), V(int16(51))},
+	{V(int16(52)), V(int32(52))},
+	{V(int32(53)), V(int16(53))},
+	{V(int16(54)), V(uint32(54))},
+	{V(uint32(55)), V(int16(55))},
+	{V(int16(56)), V(int64(56))},
+	{V(int64(57)), V(int16(57))},
+	{V(int16(58)), V(uint64(58))},
+	{V(uint64(59)), V(int16(59))},
+	{V(int16(60)), V(int(60))},
+	{V(int(61)), V(int16(61))},
+	{V(int16(62)), V(uint(62))},
+	{V(uint(63)), V(int16(63))},
+	{V(int16(64)), V(uintptr(64))},
+	{V(uintptr(65)), V(int16(65))},
+	{V(int16(66)), V(float32(66))},
+	{V(float32(67)), V(int16(67))},
+	{V(int16(68)), V(float64(68))},
+	{V(float64(69)), V(int16(69))},
+	{V(uint16(70)), V(uint16(70))},
+	{V(uint16(71)), V(int32(71))},
+	{V(int32(72)), V(uint16(72))},
+	{V(uint16(73)), V(uint32(73))},
+	{V(uint32(74)), V(uint16(74))},
+	{V(uint16(75)), V(int64(75))},
+	{V(int64(76)), V(uint16(76))},
+	{V(uint16(77)), V(uint64(77))},
+	{V(uint64(78)), V(uint16(78))},
+	{V(uint16(79)), V(int(79))},
+	{V(int(80)), V(uint16(80))},
+	{V(uint16(81)), V(uint(81))},
+	{V(uint(82)), V(uint16(82))},
+	{V(uint16(83)), V(uintptr(83))},
+	{V(uintptr(84)), V(uint16(84))},
+	{V(uint16(85)), V(float32(85))},
+	{V(float32(86)), V(uint16(86))},
+	{V(uint16(87)), V(float64(87))},
+	{V(float64(88)), V(uint16(88))},
+	{V(int32(89)), V(int32(89))},
+	{V(int32(90)), V(uint32(90))},
+	{V(uint32(91)), V(int32(91))},
+	{V(int32(92)), V(int64(92))},
+	{V(int64(93)), V(int32(93))},
+	{V(int32(94)), V(uint64(94))},
+	{V(uint64(95)), V(int32(95))},
+	{V(int32(96)), V(int(96))},
+	{V(int(97)), V(int32(97))},
+	{V(int32(98)), V(uint(98))},
+	{V(uint(99)), V(int32(99))},
+	{V(int32(100)), V(uintptr(100))},
+	{V(uintptr(101)), V(int32(101))},
+	{V(int32(102)), V(float32(102))},
+	{V(float32(103)), V(int32(103))},
+	{V(int32(104)), V(float64(104))},
+	{V(float64(105)), V(int32(105))},
+	{V(uint32(106)), V(uint32(106))},
+	{V(uint32(107)), V(int64(107))},
+	{V(int64(108)), V(uint32(108))},
+	{V(uint32(109)), V(uint64(109))},
+	{V(uint64(110)), V(uint32(110))},
+	{V(uint32(111)), V(int(111))},
+	{V(int(112)), V(uint32(112))},
+	{V(uint32(113)), V(uint(113))},
+	{V(uint(114)), V(uint32(114))},
+	{V(uint32(115)), V(uintptr(115))},
+	{V(uintptr(116)), V(uint32(116))},
+	{V(uint32(117)), V(float32(117))},
+	{V(float32(118)), V(uint32(118))},
+	{V(uint32(119)), V(float64(119))},
+	{V(float64(120)), V(uint32(120))},
+	{V(int64(121)), V(int64(121))},
+	{V(int64(122)), V(uint64(122))},
+	{V(uint64(123)), V(int64(123))},
+	{V(int64(124)), V(int(124))},
+	{V(int(125)), V(int64(125))},
+	{V(int64(126)), V(uint(126))},
+	{V(uint(127)), V(int64(127))},
+	{V(int64(128)), V(uintptr(128))},
+	{V(uintptr(129)), V(int64(129))},
+	{V(int64(130)), V(float32(130))},
+	{V(float32(131)), V(int64(131))},
+	{V(int64(132)), V(float64(132))},
+	{V(float64(133)), V(int64(133))},
+	{V(uint64(134)), V(uint64(134))},
+	{V(uint64(135)), V(int(135))},
+	{V(int(136)), V(uint64(136))},
+	{V(uint64(137)), V(uint(137))},
+	{V(uint(138)), V(uint64(138))},
+	{V(uint64(139)), V(uintptr(139))},
+	{V(uintptr(140)), V(uint64(140))},
+	{V(uint64(141)), V(float32(141))},
+	{V(float32(142)), V(uint64(142))},
+	{V(uint64(143)), V(float64(143))},
+	{V(float64(144)), V(uint64(144))},
+	{V(int(145)), V(int(145))},
+	{V(int(146)), V(uint(146))},
+	{V(uint(147)), V(int(147))},
+	{V(int(148)), V(uintptr(148))},
+	{V(uintptr(149)), V(int(149))},
+	{V(int(150)), V(float32(150))},
+	{V(float32(151)), V(int(151))},
+	{V(int(152)), V(float64(152))},
+	{V(float64(153)), V(int(153))},
+	{V(uint(154)), V(uint(154))},
+	{V(uint(155)), V(uintptr(155))},
+	{V(uintptr(156)), V(uint(156))},
+	{V(uint(157)), V(float32(157))},
+	{V(float32(158)), V(uint(158))},
+	{V(uint(159)), V(float64(159))},
+	{V(float64(160)), V(uint(160))},
+	{V(uintptr(161)), V(uintptr(161))},
+	{V(uintptr(162)), V(float32(162))},
+	{V(float32(163)), V(uintptr(163))},
+	{V(uintptr(164)), V(float64(164))},
+	{V(float64(165)), V(uintptr(165))},
+	{V(float32(166)), V(float32(166))},
+	{V(float32(167)), V(float64(167))},
+	{V(float64(168)), V(float32(168))},
+	{V(float64(169)), V(float64(169))},
+
+	// truncation
+	{V(float64(1.5)), V(int(1))},
+
+	// complex
+	{V(complex64(1i)), V(complex64(1i))},
+	{V(complex64(2i)), V(complex128(2i))},
+	{V(complex128(3i)), V(complex64(3i))},
+	{V(complex128(4i)), V(complex128(4i))},
+
+	// string
+	{V(string("hello")), V(string("hello"))},
+	{V(string("bytes1")), V([]byte("bytes1"))},
+	{V([]byte("bytes2")), V(string("bytes2"))},
+	{V([]byte("bytes3")), V([]byte("bytes3"))},
+	{V(string("runes♝")), V([]rune("runes♝"))},
+	{V([]rune("runes♕")), V(string("runes♕"))},
+	{V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
+	{V(int('a')), V(string("a"))},
+	{V(int8('a')), V(string("a"))},
+	{V(int16('a')), V(string("a"))},
+	{V(int32('a')), V(string("a"))},
+	{V(int64('a')), V(string("a"))},
+	{V(uint('a')), V(string("a"))},
+	{V(uint8('a')), V(string("a"))},
+	{V(uint16('a')), V(string("a"))},
+	{V(uint32('a')), V(string("a"))},
+	{V(uint64('a')), V(string("a"))},
+	{V(uintptr('a')), V(string("a"))},
+	{V(int(-1)), V(string("\uFFFD"))},
+	{V(int8(-2)), V(string("\uFFFD"))},
+	{V(int16(-3)), V(string("\uFFFD"))},
+	{V(int32(-4)), V(string("\uFFFD"))},
+	{V(int64(-5)), V(string("\uFFFD"))},
+	{V(uint(0x110001)), V(string("\uFFFD"))},
+	{V(uint32(0x110002)), V(string("\uFFFD"))},
+	{V(uint64(0x110003)), V(string("\uFFFD"))},
+	{V(uintptr(0x110004)), V(string("\uFFFD"))},
+
+	// named string
+	{V(MyString("hello")), V(string("hello"))},
+	{V(string("hello")), V(MyString("hello"))},
+	{V(string("hello")), V(string("hello"))},
+	{V(MyString("hello")), V(MyString("hello"))},
+	{V(MyString("bytes1")), V([]byte("bytes1"))},
+	{V([]byte("bytes2")), V(MyString("bytes2"))},
+	{V([]byte("bytes3")), V([]byte("bytes3"))},
+	{V(MyString("runes♝")), V([]rune("runes♝"))},
+	{V([]rune("runes♕")), V(MyString("runes♕"))},
+	{V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
+	{V([]rune("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
+	{V(MyRunes("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
+	{V(int('a')), V(MyString("a"))},
+	{V(int8('a')), V(MyString("a"))},
+	{V(int16('a')), V(MyString("a"))},
+	{V(int32('a')), V(MyString("a"))},
+	{V(int64('a')), V(MyString("a"))},
+	{V(uint('a')), V(MyString("a"))},
+	{V(uint8('a')), V(MyString("a"))},
+	{V(uint16('a')), V(MyString("a"))},
+	{V(uint32('a')), V(MyString("a"))},
+	{V(uint64('a')), V(MyString("a"))},
+	{V(uintptr('a')), V(MyString("a"))},
+	{V(int(-1)), V(MyString("\uFFFD"))},
+	{V(int8(-2)), V(MyString("\uFFFD"))},
+	{V(int16(-3)), V(MyString("\uFFFD"))},
+	{V(int32(-4)), V(MyString("\uFFFD"))},
+	{V(int64(-5)), V(MyString("\uFFFD"))},
+	{V(uint(0x110001)), V(MyString("\uFFFD"))},
+	{V(uint32(0x110002)), V(MyString("\uFFFD"))},
+	{V(uint64(0x110003)), V(MyString("\uFFFD"))},
+	{V(uintptr(0x110004)), V(MyString("\uFFFD"))},
+
+	// named []byte
+	{V(string("bytes1")), V(MyBytes("bytes1"))},
+	{V(MyBytes("bytes2")), V(string("bytes2"))},
+	{V(MyBytes("bytes3")), V(MyBytes("bytes3"))},
+	{V(MyString("bytes1")), V(MyBytes("bytes1"))},
+	{V(MyBytes("bytes2")), V(MyString("bytes2"))},
+
+	// named []rune
+	{V(string("runes♝")), V(MyRunes("runes♝"))},
+	{V(MyRunes("runes♕")), V(string("runes♕"))},
+	{V(MyRunes("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
+	{V(MyString("runes♝")), V(MyRunes("runes♝"))},
+	{V(MyRunes("runes♕")), V(MyString("runes♕"))},
+
+	// named types and equal underlying types
+	{V(new(int)), V(new(integer))},
+	{V(new(integer)), V(new(int))},
+	{V(Empty{}), V(struct{}{})},
+	{V(new(Empty)), V(new(struct{}))},
+	{V(struct{}{}), V(Empty{})},
+	{V(new(struct{})), V(new(Empty))},
+	{V(Empty{}), V(Empty{})},
+	{V(MyBytes{}), V([]byte{})},
+	{V([]byte{}), V(MyBytes{})},
+	{V((func())(nil)), V(MyFunc(nil))},
+	{V((MyFunc)(nil)), V((func())(nil))},
+
+	// can convert *byte and *MyByte
+	{V((*byte)(nil)), V((*MyByte)(nil))},
+	{V((*MyByte)(nil)), V((*byte)(nil))},
+
+	// cannot convert mismatched array sizes
+	{V([2]byte{}), V([2]byte{})},
+	{V([3]byte{}), V([3]byte{})},
+
+	// cannot convert other instances
+	{V((**byte)(nil)), V((**byte)(nil))},
+	{V((**MyByte)(nil)), V((**MyByte)(nil))},
+	{V((chan byte)(nil)), V((chan byte)(nil))},
+	{V((chan MyByte)(nil)), V((chan MyByte)(nil))},
+	{V(([]byte)(nil)), V(([]byte)(nil))},
+	{V(([]MyByte)(nil)), V(([]MyByte)(nil))},
+	{V((map[int]byte)(nil)), V((map[int]byte)(nil))},
+	{V((map[int]MyByte)(nil)), V((map[int]MyByte)(nil))},
+	{V((map[byte]int)(nil)), V((map[byte]int)(nil))},
+	{V((map[MyByte]int)(nil)), V((map[MyByte]int)(nil))},
+	{V([2]byte{}), V([2]byte{})},
+	{V([2]MyByte{}), V([2]MyByte{})},
+
+	// other
+	{V((***int)(nil)), V((***int)(nil))},
+	{V((***byte)(nil)), V((***byte)(nil))},
+	{V((***int32)(nil)), V((***int32)(nil))},
+	{V((***int64)(nil)), V((***int64)(nil))},
+	{V((chan int)(nil)), V((<-chan int)(nil))},
+	{V((chan int)(nil)), V((chan<- int)(nil))},
+	{V((chan string)(nil)), V((<-chan string)(nil))},
+	{V((chan string)(nil)), V((chan<- string)(nil))},
+	{V((chan byte)(nil)), V((chan byte)(nil))},
+	{V((chan MyByte)(nil)), V((chan MyByte)(nil))},
+	{V((map[int]bool)(nil)), V((map[int]bool)(nil))},
+	{V((map[int]byte)(nil)), V((map[int]byte)(nil))},
+	{V((map[uint]bool)(nil)), V((map[uint]bool)(nil))},
+	{V([]uint(nil)), V([]uint(nil))},
+	{V([]int(nil)), V([]int(nil))},
+	{V(new(interface{})), V(new(interface{}))},
+	{V(new(io.Reader)), V(new(io.Reader))},
+	{V(new(io.Writer)), V(new(io.Writer))},
+
+	// interfaces
+	{V(int(1)), EmptyInterfaceV(int(1))},
+	{V(string("hello")), EmptyInterfaceV(string("hello"))},
+	{V(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))},
+	{ReadWriterV(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))},
+	{V(new(bytes.Buffer)), ReadWriterV(new(bytes.Buffer))},
+}
+
+func TestConvert(t *testing.T) {
+	canConvert := map[[2]Type]bool{}
+	all := map[Type]bool{}
+
+	for _, tt := range convertTests {
+		t1 := tt.in.Type()
+		if !t1.ConvertibleTo(t1) {
+			t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t1)
+			continue
+		}
+
+		t2 := tt.out.Type()
+		if !t1.ConvertibleTo(t2) {
+			t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t2)
+			continue
+		}
+
+		all[t1] = true
+		all[t2] = true
+		canConvert[[2]Type{t1, t2}] = true
+
+		v1 := tt.in
+		vout1 := v1.Convert(t1)
+		out1 := vout1.Interface()
+		if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
+			t.Errorf("ValueOf(%T(%v)).Convert(%s) = %T(%v), want %T(%v)", tt.in.Interface(), tt.in.Interface(), t1, out1, out1, tt.in.Interface(), tt.in.Interface())
+		}
+
+		vout := v1.Convert(t2)
+		out := vout.Interface()
+		if vout.Type() != tt.out.Type() || !DeepEqual(out, tt.out.Interface()) {
+			t.Errorf("ValueOf(%T(%v)).Convert(%s) = %T(%v), want %T(%v)", tt.in.Interface(), tt.in.Interface(), t2, out, out, tt.out.Interface(), tt.out.Interface())
+		}
+
+		if IsRO(v1) {
+			t.Errorf("table entry %v is RO, should not be", v1)
+		}
+		if IsRO(vout1) {
+			t.Errorf("self-conversion output %v is RO, should not be", vout1)
+		}
+		if IsRO(vout) {
+			t.Errorf("conversion output %v is RO, should not be", vout)
+		}
+		if !IsRO(MakeRO(v1).Convert(t1)) {
+			t.Errorf("RO self-conversion output %v is not RO, should be", v1)
+		}
+		if !IsRO(MakeRO(v1).Convert(t2)) {
+			t.Errorf("RO conversion output %v is not RO, should be", v1)
+		}
+	}
+
+	// Assume that of all the types we saw during the tests,
+	// if there wasn't an explicit entry for a conversion between
+	// a pair of types, then it's not to be allowed. This checks for
+	// things like 'int64' converting to '*int'.
+	for t1 := range all {
+		for t2 := range all {
+			expectOK := t1 == t2 || canConvert[[2]Type{t1, t2}] || t2.Kind() == Interface && t2.NumMethod() == 0
+			if ok := t1.ConvertibleTo(t2); ok != expectOK {
+				t.Errorf("(%s).ConvertibleTo(%s) = %v, want %v", t1, t2, ok, expectOK)
+			}
+		}
+	}
+}
+
+func TestOverflow(t *testing.T) {
+	if ovf := V(float64(0)).OverflowFloat(1e300); ovf {
+		t.Errorf("%v wrongly overflows float64", 1e300)
+	}
+
+	maxFloat32 := float64((1<<24 - 1) << (127 - 23))
+	if ovf := V(float32(0)).OverflowFloat(maxFloat32); ovf {
+		t.Errorf("%v wrongly overflows float32", maxFloat32)
+	}
+	ovfFloat32 := float64((1<<24-1)<<(127-23) + 1<<(127-52))
+	if ovf := V(float32(0)).OverflowFloat(ovfFloat32); !ovf {
+		t.Errorf("%v should overflow float32", ovfFloat32)
+	}
+	if ovf := V(float32(0)).OverflowFloat(-ovfFloat32); !ovf {
+		t.Errorf("%v should overflow float32", -ovfFloat32)
+	}
+
+	maxInt32 := int64(0x7fffffff)
+	if ovf := V(int32(0)).OverflowInt(maxInt32); ovf {
+		t.Errorf("%v wrongly overflows int32", maxInt32)
+	}
+	if ovf := V(int32(0)).OverflowInt(-1 << 31); ovf {
+		t.Errorf("%v wrongly overflows int32", -int64(1)<<31)
+	}
+	ovfInt32 := int64(1 << 31)
+	if ovf := V(int32(0)).OverflowInt(ovfInt32); !ovf {
+		t.Errorf("%v should overflow int32", ovfInt32)
+	}
+
+	maxUint32 := uint64(0xffffffff)
+	if ovf := V(uint32(0)).OverflowUint(maxUint32); ovf {
+		t.Errorf("%v wrongly overflows uint32", maxUint32)
+	}
+	ovfUint32 := uint64(1 << 32)
+	if ovf := V(uint32(0)).OverflowUint(ovfUint32); !ovf {
+		t.Errorf("%v should overflow uint32", ovfUint32)
+	}
+}
+
+func checkSameType(t *testing.T, x, y interface{}) {
+	if TypeOf(x) != TypeOf(y) {
+		t.Errorf("did not find preexisting type for %s (vs %s)", TypeOf(x), TypeOf(y))
+	}
+}
+
+func TestArrayOf(t *testing.T) {
+	// check construction and use of type not in binary
+	type T int
+	at := ArrayOf(10, TypeOf(T(1)))
+	v := New(at).Elem()
+	for i := 0; i < v.Len(); i++ {
+		v.Index(i).Set(ValueOf(T(i)))
+	}
+	s := fmt.Sprint(v.Interface())
+	want := "[0 1 2 3 4 5 6 7 8 9]"
+	if s != want {
+		t.Errorf("constructed array = %s, want %s", s, want)
+	}
+
+	// check that type already in binary is found
+	checkSameType(t, Zero(ArrayOf(5, TypeOf(T(1)))).Interface(), [5]T{})
+}
+
+func TestSliceOf(t *testing.T) {
+	// check construction and use of type not in binary
+	type T int
+	st := SliceOf(TypeOf(T(1)))
+	v := MakeSlice(st, 10, 10)
+	for i := 0; i < v.Len(); i++ {
+		v.Index(i).Set(ValueOf(T(i)))
+	}
+	s := fmt.Sprint(v.Interface())
+	want := "[0 1 2 3 4 5 6 7 8 9]"
+	if s != want {
+		t.Errorf("constructed slice = %s, want %s", s, want)
+	}
+
+	// check that type already in binary is found
+	type T1 int
+	checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{})
+}
+
+func TestChanOf(t *testing.T) {
+	// check construction and use of type not in binary
+	type T string
+	ct := ChanOf(BothDir, TypeOf(T("")))
+	v := MakeChan(ct, 2)
+	v.Send(ValueOf(T("hello")))
+	v.Send(ValueOf(T("world")))
+
+	sv1, _ := v.Recv()
+	sv2, _ := v.Recv()
+	s1 := sv1.String()
+	s2 := sv2.String()
+	if s1 != "hello" || s2 != "world" {
+		t.Errorf("constructed chan: have %q, %q, want %q, %q", s1, s2, "hello", "world")
+	}
+
+	// check that type already in binary is found
+	type T1 int
+	checkSameType(t, Zero(ChanOf(BothDir, TypeOf(T1(1)))).Interface(), (chan T1)(nil))
+}
+
+func TestMapOf(t *testing.T) {
+	// check construction and use of type not in binary
+	type K string
+	type V float64
+
+	v := MakeMap(MapOf(TypeOf(K("")), TypeOf(V(0))))
+	v.SetMapIndex(ValueOf(K("a")), ValueOf(V(1)))
+
+	s := fmt.Sprint(v.Interface())
+	want := "map[a:1]"
+	if s != want {
+		t.Errorf("constructed map = %s, want %s", s, want)
+	}
+
+	// check that type already in binary is found
+	checkSameType(t, Zero(MapOf(TypeOf(V(0)), TypeOf(K("")))).Interface(), map[V]K(nil))
+}
+
+type B1 struct {
+	X int
+	Y int
+	Z int
+}
+
+func BenchmarkFieldByName1(b *testing.B) {
+	t := TypeOf(B1{})
+	for i := 0; i < b.N; i++ {
+		t.FieldByName("Z")
+	}
+}
+
+func BenchmarkFieldByName2(b *testing.B) {
+	t := TypeOf(S3{})
+	for i := 0; i < b.N; i++ {
+		t.FieldByName("B")
+	}
+}
+
+type R0 struct {
+	*R1
+	*R2
+	*R3
+	*R4
+}
+
+type R1 struct {
+	*R5
+	*R6
+	*R7
+	*R8
+}
+
+type R2 R1
+type R3 R1
+type R4 R1
+
+type R5 struct {
+	*R9
+	*R10
+	*R11
+	*R12
+}
+
+type R6 R5
+type R7 R5
+type R8 R5
+
+type R9 struct {
+	*R13
+	*R14
+	*R15
+	*R16
+}
+
+type R10 R9
+type R11 R9
+type R12 R9
+
+type R13 struct {
+	*R17
+	*R18
+	*R19
+	*R20
+}
+
+type R14 R13
+type R15 R13
+type R16 R13
+
+type R17 struct {
+	*R21
+	*R22
+	*R23
+	*R24
+}
+
+type R18 R17
+type R19 R17
+type R20 R17
+
+type R21 struct {
+	X int
+}
+
+type R22 R21
+type R23 R21
+type R24 R21
+
+func TestEmbed(t *testing.T) {
+	typ := TypeOf(R0{})
+	f, ok := typ.FieldByName("X")
+	if ok {
+		t.Fatalf(`FieldByName("X") should fail, returned %v`, f.Index)
+	}
+}
+
+func BenchmarkFieldByName3(b *testing.B) {
+	t := TypeOf(R0{})
+	for i := 0; i < b.N; i++ {
+		t.FieldByName("X")
+	}
+}
+
+// An exhaustive is a mechanism for writing exhaustive or stochastic tests.
+// The basic usage is:
+//
+//	for x.Next() {
+//		... code using x.Maybe() or x.Choice(n) to create test cases ...
+//	}
+//
+// Each iteration of the loop returns a different set of results, until all
+// possible result sets have been explored. It is okay for different code paths
+// to make different method call sequences on x, but there must be no
+// other source of non-determinism in the call sequences.
+//
+// When faced with a new decision, x chooses randomly. Future explorations
+// of that path will choose successive values for the result. Thus, stopping
+// the loop after a fixed number of iterations gives somewhat stochastic
+// testing.
+//
+// Example:
+//
+//	for x.Next() {
+//		v := make([]bool, x.Choose(4))
+//		for i := range v {
+//			v[i] = x.Maybe()
+//		}
+//		fmt.Println(v)
+//	}
+//
+// prints (in some order):
+//
+//	[]
+//	[false]
+//	[true]
+//	[false false]
+//	[false true]
+//	...
+//	[true true]
+//	[false false false]
+//	...
+//	[true true true]
+//	[false false false false]
+//	...
+//	[true true true true]
+//
+type exhaustive struct {
+	r    *rand.Rand
+	pos  int
+	last []choice
+}
+
+type choice struct {
+	off int
+	n   int
+	max int
+}
+
+func (x *exhaustive) Next() bool {
+	if x.r == nil {
+		x.r = rand.New(rand.NewSource(time.Now().UnixNano()))
+	}
+	x.pos = 0
+	if x.last == nil {
+		x.last = []choice{}
+		return true
+	}
+	for i := len(x.last) - 1; i >= 0; i-- {
+		c := &x.last[i]
+		if c.n+1 < c.max {
+			c.n++
+			x.last = x.last[:i+1]
+			return true
+		}
+	}
+	return false
+}
+
+func (x *exhaustive) Choose(max int) int {
+	if x.pos >= len(x.last) {
+		x.last = append(x.last, choice{x.r.Intn(max), 0, max})
+	}
+	c := &x.last[x.pos]
+	x.pos++
+	if c.max != max {
+		panic("inconsistent use of exhaustive tester")
+	}
+	return (c.n + c.off) % max
+}
+
+func (x *exhaustive) Maybe() bool {
+	return x.Choose(2) == 1
+}
diff --git a/src/pkg/reflect/asm_386.s b/src/pkg/reflect/asm_386.s
new file mode 100644
index 0000000..27d3fa2
--- /dev/null
+++ b/src/pkg/reflect/asm_386.s
@@ -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.
+
+// makeFuncStub is the code half of the function returned by MakeFunc.
+// See the comment on the declaration of makeFuncStub in value.go
+// for more details.
+TEXT ·makeFuncStub(SB),7,$8
+	MOVL	DX, 0(SP)
+	LEAL	arg+0(FP), CX
+	MOVL	CX, 4(SP)
+	CALL	·callReflect(SB)
+	RET
diff --git a/src/pkg/reflect/asm_amd64.s b/src/pkg/reflect/asm_amd64.s
new file mode 100644
index 0000000..d51d982
--- /dev/null
+++ b/src/pkg/reflect/asm_amd64.s
@@ -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.
+
+// makeFuncStub is the code half of the function returned by MakeFunc.
+// See the comment on the declaration of makeFuncStub in value.go
+// for more details.
+TEXT ·makeFuncStub(SB),7,$16
+	MOVQ	DX, 0(SP)
+	LEAQ	arg+0(FP), CX
+	MOVQ	CX, 8(SP)
+	CALL	·callReflect(SB)
+	RET
diff --git a/src/pkg/reflect/asm_arm.s b/src/pkg/reflect/asm_arm.s
new file mode 100644
index 0000000..db487f8
--- /dev/null
+++ b/src/pkg/reflect/asm_arm.s
@@ -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.
+
+// makeFuncStub is jumped to by the code generated by MakeFunc.
+// See the comment on the declaration of makeFuncStub in value.go
+// for more details.
+TEXT ·makeFuncStub(SB),7,$8
+	MOVW	R7, 4(R13)
+	MOVW	$arg+0(FP), R1
+	MOVW	R1, 8(R13)
+	BL	·callReflect(SB)
+	RET
diff --git a/src/pkg/reflect/deepequal.go b/src/pkg/reflect/deepequal.go
index c12e90f..db04796 100644
--- a/src/pkg/reflect/deepequal.go
+++ b/src/pkg/reflect/deepequal.go
@@ -122,9 +122,12 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
 	panic("Not reached")
 }
 
-// DeepEqual tests for deep equality. It uses normal == equality where possible
-// but will scan members of arrays, slices, maps, and fields of structs. It correctly
-// handles recursive types. Functions are equal only if they are both nil.
+// DeepEqual tests for deep equality. It uses normal == equality where
+// possible but will scan elements of arrays, slices, maps, and fields of
+// structs. In maps, keys are compared with == but elements use deep
+// equality. DeepEqual correctly handles recursive types. Functions are equal
+// only if they are both nil.
+// An empty slice is not equal to a nil slice.
 func DeepEqual(a1, a2 interface{}) bool {
 	if a1 == nil || a2 == nil {
 		return a1 == a2
diff --git a/src/pkg/reflect/example_test.go b/src/pkg/reflect/example_test.go
new file mode 100644
index 0000000..62455c0
--- /dev/null
+++ b/src/pkg/reflect/example_test.go
@@ -0,0 +1,52 @@
+// 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_test
+
+import (
+	"fmt"
+	"reflect"
+)
+
+func ExampleMakeFunc() {
+	// swap is the implementation passed to MakeFunc.
+	// It must work in terms of reflect.Values so that it is possible
+	// to write code without knowing beforehand what the types
+	// will be.
+	swap := func(in []reflect.Value) []reflect.Value {
+		return []reflect.Value{in[1], in[0]}
+	}
+
+	// makeSwap expects fptr to be a pointer to a nil function.
+	// It sets that pointer to a new function created with MakeFunc.
+	// When the function is invoked, reflect turns the arguments
+	// into Values, calls swap, and then turns swap's result slice
+	// into the values returned by the new function.
+	makeSwap := func(fptr interface{}) {
+		// fptr is a pointer to a function.
+		// Obtain the function value itself (likely nil) as a reflect.Value
+		// so that we can query its type and then set the value.
+		fn := reflect.ValueOf(fptr).Elem()
+
+		// Make a function of the right type.
+		v := reflect.MakeFunc(fn.Type(), swap)
+
+		// Assign it to the value fn represents.
+		fn.Set(v)
+	}
+
+	// Make and call a swap function for ints.
+	var intSwap func(int, int) (int, int)
+	makeSwap(&intSwap)
+	fmt.Println(intSwap(0, 1))
+
+	// Make and call a swap function for float64s.
+	var floatSwap func(float64, float64) (float64, float64)
+	makeSwap(&floatSwap)
+	fmt.Println(floatSwap(2.72, 3.14))
+
+	// Output:
+	// 1 0
+	// 3.14 2.72
+}
diff --git a/src/pkg/reflect/export_test.go b/src/pkg/reflect/export_test.go
new file mode 100644
index 0000000..cd8cf2c
--- /dev/null
+++ b/src/pkg/reflect/export_test.go
@@ -0,0 +1,18 @@
+// 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
diff --git a/src/pkg/reflect/makefunc.go b/src/pkg/reflect/makefunc.go
new file mode 100644
index 0000000..024f938
--- /dev/null
+++ b/src/pkg/reflect/makefunc.go
@@ -0,0 +1,67 @@
+// 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.
+
+// MakeFunc implementation.
+
+package reflect
+
+import (
+	"unsafe"
+)
+
+// makeFuncImpl is the closure value implementing the function
+// returned by MakeFunc.
+type makeFuncImpl struct {
+	code uintptr
+	typ  *funcType
+	fn   func([]Value) []Value
+}
+
+// MakeFunc returns a new function of the given Type
+// that wraps the function fn. When called, that new function
+// does the following:
+//
+//	- converts its arguments to a list of Values args.
+//	- runs results := fn(args).
+//	- returns the results as a slice of Values, one per formal result.
+//
+// The implementation fn can assume that the argument Value slice
+// has the number and type of arguments given by typ.
+// If typ describes a variadic function, the final Value is itself
+// a slice representing the variadic arguments, as in the
+// body of a variadic function. The result Value slice returned by fn
+// must have the number and type of results given by typ.
+//
+// The Value.Call method allows the caller to invoke a typed function
+// in terms of Values; in contrast, MakeFunc allows the caller to implement
+// a typed function in terms of Values.
+//
+// The Examples section of the documentation includes an illustration
+// of how to use MakeFunc to build a swap function for different types.
+//
+func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
+	if typ.Kind() != Func {
+		panic("reflect: call of MakeFunc with non-Func type")
+	}
+
+	t := typ.common()
+	ftyp := (*funcType)(unsafe.Pointer(t))
+
+	// indirect Go func value (dummy) to obtain
+	// actual code address. (A Go func is a pointer
+	// to a C function pointer. http://golang.org/s/go11func.)
+	dummy := makeFuncStub
+	code := **(**uintptr)(unsafe.Pointer(&dummy))
+
+	impl := &makeFuncImpl{code: code, typ: ftyp, fn: fn}
+
+	return Value{t, unsafe.Pointer(impl), flag(Func) << flagKindShift}
+}
+
+// makeFuncStub is an assembly function that is the code half of
+// the function returned from MakeFunc. It expects a *callReflectFunc
+// as its context register, and its job is to invoke callReflect(ctxt, frame)
+// where ctxt is the context register and frame is a pointer to the first
+// word in the passed-in argument frame.
+func makeFuncStub()
diff --git a/src/pkg/reflect/set_test.go b/src/pkg/reflect/set_test.go
index 8135a4c..85dc55e 100644
--- a/src/pkg/reflect/set_test.go
+++ b/src/pkg/reflect/set_test.go
@@ -81,11 +81,11 @@ func TestImplicitMapConversion(t *testing.T) {
 			t.Errorf("#5 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
 		}
 		if p := mv.MapIndex(ValueOf(b1)).Elem().Pointer(); p != uintptr(unsafe.Pointer(b2)) {
-			t.Errorf("#5 MapIndex(b1) = %p want %p", p, b2)
+			t.Errorf("#5 MapIndex(b1) = %#x want %p", p, b2)
 		}
 	}
 	{
-		// convert channel direction	
+		// convert channel direction
 		m := make(map[<-chan int]chan int)
 		mv := ValueOf(m)
 		c1 := make(chan int)
@@ -96,7 +96,7 @@ func TestImplicitMapConversion(t *testing.T) {
 			t.Errorf("#6 after SetMapIndex(c1, c2): %p (!= %p), %t (map=%v)", x, c2, ok, m)
 		}
 		if p := mv.MapIndex(ValueOf(c1)).Pointer(); p != ValueOf(c2).Pointer() {
-			t.Errorf("#6 MapIndex(c1) = %p want %p", p, c2)
+			t.Errorf("#6 MapIndex(c1) = %#x want %p", p, c2)
 		}
 	}
 	{
@@ -115,7 +115,7 @@ func TestImplicitMapConversion(t *testing.T) {
 			t.Errorf("#7 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
 		}
 		if p := mv.MapIndex(ValueOf(b1)).Pointer(); p != uintptr(unsafe.Pointer(b2)) {
-			t.Errorf("#7 MapIndex(b1) = %p want %p", p, b2)
+			t.Errorf("#7 MapIndex(b1) = %#x want %p", p, b2)
 		}
 	}
 
diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go
index 060bde3..94a7521 100644
--- a/src/pkg/reflect/type.go
+++ b/src/pkg/reflect/type.go
@@ -92,6 +92,9 @@ type Type interface {
 	// AssignableTo returns true if a value of the type is assignable to type u.
 	AssignableTo(u Type) bool
 
+	// ConvertibleTo returns true if a value of the type is convertible to type u.
+	ConvertibleTo(u Type) bool
+
 	// Methods applicable only to some types, depending on Kind.
 	// The methods allowed for each kind are:
 	//
@@ -181,11 +184,16 @@ type Type interface {
 	// It panics if i is not in the range [0, NumOut()).
 	Out(i int) Type
 
-	runtimeType() *runtimeType
-	common() *commonType
+	common() *rtype
 	uncommon() *uncommonType
 }
 
+/*
+ * These data structures are known to the compiler (../../cmd/gc/reflect.c).
+ * A few are known to ../runtime/type.go to convey to debuggers.
+ * They are also known to ../runtime/type.h.
+ */
+
 // A Kind represents the specific kind of type that a Type represents.
 // The zero Kind is not a valid kind.
 type Kind uint
@@ -220,41 +228,30 @@ const (
 	UnsafePointer
 )
 
-/*
- * These data structures are known to the compiler (../../cmd/gc/reflect.c).
- * A few are known to ../runtime/type.go to convey to debuggers.
- */
-
-// The compiler can only construct empty interface values at
-// compile time; non-empty interface values get created
-// during initialization.  Type is an empty interface
-// so that the compiler can lay out references as data.
-// The underlying type is *reflect.ArrayType and so on.
-type runtimeType interface{}
-
-// commonType is the common implementation of most values.
+// rtype is the common implementation of most values.
 // It is embedded in other, public struct types, but always
 // with a unique tag like `reflect:"array"` or `reflect:"ptr"`
 // so that code cannot convert from, say, *arrayType to *ptrType.
-type commonType 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)
-	string        *string      // string form; unnecessary but undeniably useful
-	*uncommonType              // (relatively) uncommon fields
-	ptrToThis     *runtimeType // pointer to this type, if used in binary or has methods
+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            uintptr  // 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
 }
 
 // Method on non-interface type
 type method struct {
 	name    *string        // name of method
 	pkgPath *string        // nil for exported Names; otherwise import path
-	mtyp    *runtimeType   // method type (without receiver)
-	typ     *runtimeType   // .(*FuncType) underneath (with receiver)
+	mtyp    *rtype         // method type (without receiver)
+	typ     *rtype         // .(*FuncType) underneath (with receiver)
 	ifn     unsafe.Pointer // fn used in interface call (one-word receiver)
 	tfn     unsafe.Pointer // fn used for normal method call
 }
@@ -280,72 +277,72 @@ const (
 
 // arrayType represents a fixed array type.
 type arrayType struct {
-	commonType `reflect:"array"`
-	elem       *runtimeType // array element type
-	slice      *runtimeType // slice type
-	len        uintptr
+	rtype `reflect:"array"`
+	elem  *rtype // array element type
+	slice *rtype // slice type
+	len   uintptr
 }
 
 // chanType represents a channel type.
 type chanType struct {
-	commonType `reflect:"chan"`
-	elem       *runtimeType // channel element type
-	dir        uintptr      // channel direction (ChanDir)
+	rtype `reflect:"chan"`
+	elem  *rtype  // channel element type
+	dir   uintptr // channel direction (ChanDir)
 }
 
 // funcType represents a function type.
 type funcType struct {
-	commonType `reflect:"func"`
-	dotdotdot  bool           // last input parameter is ...
-	in         []*runtimeType // input parameter types
-	out        []*runtimeType // output parameter types
+	rtype     `reflect:"func"`
+	dotdotdot bool     // last input parameter is ...
+	in        []*rtype // input parameter types
+	out       []*rtype // output parameter types
 }
 
 // imethod represents a method on an interface type
 type imethod struct {
-	name    *string      // name of method
-	pkgPath *string      // nil for exported Names; otherwise import path
-	typ     *runtimeType // .(*FuncType) underneath
+	name    *string // name of method
+	pkgPath *string // nil for exported Names; otherwise import path
+	typ     *rtype  // .(*FuncType) underneath
 }
 
 // interfaceType represents an interface type.
 type interfaceType struct {
-	commonType `reflect:"interface"`
-	methods    []imethod // sorted by hash
+	rtype   `reflect:"interface"`
+	methods []imethod // sorted by hash
 }
 
 // mapType represents a map type.
 type mapType struct {
-	commonType `reflect:"map"`
-	key        *runtimeType // map key type
-	elem       *runtimeType // map element (value) type
+	rtype `reflect:"map"`
+	key   *rtype // map key type
+	elem  *rtype // map element (value) type
 }
 
 // ptrType represents a pointer type.
 type ptrType struct {
-	commonType `reflect:"ptr"`
-	elem       *runtimeType // pointer element (pointed at) type
+	rtype `reflect:"ptr"`
+	elem  *rtype // pointer element (pointed at) type
 }
 
 // sliceType represents a slice type.
 type sliceType struct {
-	commonType `reflect:"slice"`
-	elem       *runtimeType // slice element type
+	rtype `reflect:"slice"`
+	elem  *rtype // slice element type
 }
 
 // Struct field
 type structField struct {
-	name    *string      // nil for embedded fields
-	pkgPath *string      // nil for exported Names; otherwise import path
-	typ     *runtimeType // type of field
-	tag     *string      // nil if no tag
-	offset  uintptr      // byte offset of field within struct
+	name    *string // nil for embedded fields
+	pkgPath *string // nil for exported Names; otherwise import path
+	typ     *rtype  // type of field
+	tag     *string // nil if no tag
+	offset  uintptr // byte offset of field within struct
 }
 
 // structType represents a struct type.
 type structType struct {
-	commonType `reflect:"struct"`
-	fields     []structField // sorted by offset
+	rtype  `reflect:"struct"`
+	fields []structField // sorted by offset
 }
 
 /*
@@ -359,7 +356,7 @@ type Method struct {
 	// PkgPath is the package path that qualifies a lower case (unexported)
 	// method name.  It is empty for upper case (exported) method names.
 	// The combination of PkgPath and Name uniquely identifies a method
-	// in a method set. 
+	// in a method set.
 	// See http://golang.org/ref/spec#Uniqueness_of_identifiers
 	Name    string
 	PkgPath string
@@ -428,18 +425,11 @@ func (t *uncommonType) Name() string {
 	return *t.name
 }
 
-func (t *commonType) toType() Type {
-	if t == nil {
-		return nil
-	}
-	return t
-}
-
-func (t *commonType) String() string { return *t.string }
+func (t *rtype) String() string { return *t.string }
 
-func (t *commonType) Size() uintptr { return t.size }
+func (t *rtype) Size() uintptr { return t.size }
 
-func (t *commonType) Bits() int {
+func (t *rtype) Bits() int {
 	if t == nil {
 		panic("reflect: Bits of nil Type")
 	}
@@ -450,13 +440,13 @@ func (t *commonType) Bits() int {
 	return int(t.size) * 8
 }
 
-func (t *commonType) Align() int { return int(t.align) }
+func (t *rtype) Align() int { return int(t.align) }
 
-func (t *commonType) FieldAlign() int { return int(t.fieldAlign) }
+func (t *rtype) FieldAlign() int { return int(t.fieldAlign) }
 
-func (t *commonType) Kind() Kind { return Kind(t.kind & kindMask) }
+func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
 
-func (t *commonType) common() *commonType { return t }
+func (t *rtype) common() *rtype { return t }
 
 func (t *uncommonType) Method(i int) (m Method) {
 	if t == nil || i < 0 || i >= len(t.methods) {
@@ -471,9 +461,9 @@ func (t *uncommonType) Method(i int) (m Method) {
 		m.PkgPath = *p.pkgPath
 		fl |= flagRO
 	}
-	mt := toCommonType(p.typ)
+	mt := p.typ
 	m.Type = mt
-	fn := p.tfn
+	fn := unsafe.Pointer(&p.tfn)
 	m.Func = Value{mt, fn, fl}
 	m.Index = i
 	return
@@ -502,8 +492,8 @@ func (t *uncommonType) MethodByName(name string) (m Method, ok bool) {
 
 // TODO(rsc): 6g supplies these, but they are not
 // as efficient as they could be: they have commonType
-// as the receiver instead of *commonType.
-func (t *commonType) NumMethod() int {
+// as the receiver instead of *rtype.
+func (t *rtype) NumMethod() int {
 	if t.Kind() == Interface {
 		tt := (*interfaceType)(unsafe.Pointer(t))
 		return tt.NumMethod()
@@ -511,7 +501,7 @@ func (t *commonType) NumMethod() int {
 	return t.uncommonType.NumMethod()
 }
 
-func (t *commonType) Method(i int) (m Method) {
+func (t *rtype) Method(i int) (m Method) {
 	if t.Kind() == Interface {
 		tt := (*interfaceType)(unsafe.Pointer(t))
 		return tt.Method(i)
@@ -519,7 +509,7 @@ func (t *commonType) Method(i int) (m Method) {
 	return t.uncommonType.Method(i)
 }
 
-func (t *commonType) MethodByName(name string) (m Method, ok bool) {
+func (t *rtype) MethodByName(name string) (m Method, ok bool) {
 	if t.Kind() == Interface {
 		tt := (*interfaceType)(unsafe.Pointer(t))
 		return tt.MethodByName(name)
@@ -527,15 +517,15 @@ func (t *commonType) MethodByName(name string) (m Method, ok bool) {
 	return t.uncommonType.MethodByName(name)
 }
 
-func (t *commonType) PkgPath() string {
+func (t *rtype) PkgPath() string {
 	return t.uncommonType.PkgPath()
 }
 
-func (t *commonType) Name() string {
+func (t *rtype) Name() string {
 	return t.uncommonType.Name()
 }
 
-func (t *commonType) ChanDir() ChanDir {
+func (t *rtype) ChanDir() ChanDir {
 	if t.Kind() != Chan {
 		panic("reflect: ChanDir of non-chan type")
 	}
@@ -543,7 +533,7 @@ func (t *commonType) ChanDir() ChanDir {
 	return ChanDir(tt.dir)
 }
 
-func (t *commonType) IsVariadic() bool {
+func (t *rtype) IsVariadic() bool {
 	if t.Kind() != Func {
 		panic("reflect: IsVariadic of non-func type")
 	}
@@ -551,7 +541,7 @@ func (t *commonType) IsVariadic() bool {
 	return tt.dotdotdot
 }
 
-func (t *commonType) Elem() Type {
+func (t *rtype) Elem() Type {
 	switch t.Kind() {
 	case Array:
 		tt := (*arrayType)(unsafe.Pointer(t))
@@ -572,7 +562,7 @@ func (t *commonType) Elem() Type {
 	panic("reflect: Elem of invalid type")
 }
 
-func (t *commonType) Field(i int) StructField {
+func (t *rtype) Field(i int) StructField {
 	if t.Kind() != Struct {
 		panic("reflect: Field of non-struct type")
 	}
@@ -580,7 +570,7 @@ func (t *commonType) Field(i int) StructField {
 	return tt.Field(i)
 }
 
-func (t *commonType) FieldByIndex(index []int) StructField {
+func (t *rtype) FieldByIndex(index []int) StructField {
 	if t.Kind() != Struct {
 		panic("reflect: FieldByIndex of non-struct type")
 	}
@@ -588,7 +578,7 @@ func (t *commonType) FieldByIndex(index []int) StructField {
 	return tt.FieldByIndex(index)
 }
 
-func (t *commonType) FieldByName(name string) (StructField, bool) {
+func (t *rtype) FieldByName(name string) (StructField, bool) {
 	if t.Kind() != Struct {
 		panic("reflect: FieldByName of non-struct type")
 	}
@@ -596,7 +586,7 @@ func (t *commonType) FieldByName(name string) (StructField, bool) {
 	return tt.FieldByName(name)
 }
 
-func (t *commonType) FieldByNameFunc(match func(string) bool) (StructField, bool) {
+func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
 	if t.Kind() != Struct {
 		panic("reflect: FieldByNameFunc of non-struct type")
 	}
@@ -604,7 +594,7 @@ func (t *commonType) FieldByNameFunc(match func(string) bool) (StructField, bool
 	return tt.FieldByNameFunc(match)
 }
 
-func (t *commonType) In(i int) Type {
+func (t *rtype) In(i int) Type {
 	if t.Kind() != Func {
 		panic("reflect: In of non-func type")
 	}
@@ -612,7 +602,7 @@ func (t *commonType) In(i int) Type {
 	return toType(tt.in[i])
 }
 
-func (t *commonType) Key() Type {
+func (t *rtype) Key() Type {
 	if t.Kind() != Map {
 		panic("reflect: Key of non-map type")
 	}
@@ -620,7 +610,7 @@ func (t *commonType) Key() Type {
 	return toType(tt.key)
 }
 
-func (t *commonType) Len() int {
+func (t *rtype) Len() int {
 	if t.Kind() != Array {
 		panic("reflect: Len of non-array type")
 	}
@@ -628,7 +618,7 @@ func (t *commonType) Len() int {
 	return int(tt.len)
 }
 
-func (t *commonType) NumField() int {
+func (t *rtype) NumField() int {
 	if t.Kind() != Struct {
 		panic("reflect: NumField of non-struct type")
 	}
@@ -636,7 +626,7 @@ func (t *commonType) NumField() int {
 	return len(tt.fields)
 }
 
-func (t *commonType) NumIn() int {
+func (t *rtype) NumIn() int {
 	if t.Kind() != Func {
 		panic("reflect: NumIn of non-func type")
 	}
@@ -644,7 +634,7 @@ func (t *commonType) NumIn() int {
 	return len(tt.in)
 }
 
-func (t *commonType) NumOut() int {
+func (t *rtype) NumOut() int {
 	if t.Kind() != Func {
 		panic("reflect: NumOut of non-func type")
 	}
@@ -652,7 +642,7 @@ func (t *commonType) NumOut() int {
 	return len(tt.out)
 }
 
-func (t *commonType) Out(i int) Type {
+func (t *rtype) Out(i int) Type {
 	if t.Kind() != Func {
 		panic("reflect: Out of non-func type")
 	}
@@ -718,7 +708,7 @@ type StructField struct {
 	Tag       StructTag // field tag string
 	Offset    uintptr   // offset within struct, in bytes
 	Index     []int     // index sequence for Type.FieldByIndex
-	Anonymous bool      // is an anonymous field
+	Anonymous bool      // is an embedded field
 }
 
 // A StructTag is the tag string in a struct field.
@@ -822,7 +812,7 @@ func (t *structType) Field(i int) (f StructField) {
 
 // FieldByIndex returns the nested field corresponding to index.
 func (t *structType) FieldByIndex(index []int) (f StructField) {
-	f.Type = Type(t.toType())
+	f.Type = toType(&t.rtype)
 	for i, x := range index {
 		if i > 0 {
 			ft := f.Type
@@ -836,107 +826,143 @@ func (t *structType) FieldByIndex(index []int) (f StructField) {
 	return
 }
 
-const inf = 1 << 30 // infinity - no struct has that many nesting levels
-
-func (t *structType) fieldByNameFunc(match func(string) bool, mark map[*structType]bool, depth int) (ff StructField, fd int) {
-	fd = inf // field depth
+// A fieldScan represents an item on the fieldByNameFunc scan work list.
+type fieldScan struct {
+	typ   *structType
+	index []int
+}
 
-	if mark[t] {
-		// Struct already seen.
-		return
-	}
-	mark[t] = true
-
-	var fi int // field index
-	n := 0     // number of matching fields at depth fd
-L:
-	for i := range t.fields {
-		f := t.Field(i)
-		d := inf
-		switch {
-		case match(f.Name):
-			// Matching top-level field.
-			d = depth
-		case f.Anonymous:
-			ft := f.Type
-			if ft.Kind() == Ptr {
-				ft = ft.Elem()
+// FieldByNameFunc returns the struct field with a name that satisfies the
+// match function and a boolean to indicate if the field was found.
+func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
+	// This uses the same condition that the Go language does: there must be a unique instance
+	// of the match at a given depth level. If there are multiple instances of a match at the
+	// same depth, they annihilate each other and inhibit any possible match at a lower level.
+	// The algorithm is breadth first search, one depth level at a time.
+
+	// The current and next slices are work queues:
+	// current lists the fields to visit on this depth level,
+	// and next lists the fields on the next lower level.
+	current := []fieldScan{}
+	next := []fieldScan{{typ: t}}
+
+	// nextCount records the number of times an embedded type has been
+	// encountered and considered for queueing in the 'next' slice.
+	// We only queue the first one, but we increment the count on each.
+	// If a struct type T can be reached more than once at a given depth level,
+	// then it annihilates itself and need not be considered at all when we
+	// process that next depth level.
+	var nextCount map[*structType]int
+
+	// visited records the structs that have been considered already.
+	// Embedded pointer fields can create cycles in the graph of
+	// reachable embedded types; visited avoids following those cycles.
+	// It also avoids duplicated effort: if we didn't find the field in an
+	// embedded type T at level 2, we won't find it in one at level 4 either.
+	visited := map[*structType]bool{}
+
+	for len(next) > 0 {
+		current, next = next, current[:0]
+		count := nextCount
+		nextCount = nil
+
+		// Process all the fields at this depth, now listed in 'current'.
+		// The loop queues embedded fields found in 'next', for processing during the next
+		// iteration. The multiplicity of the 'current' field counts is recorded
+		// in 'count'; the multiplicity of the 'next' field counts is recorded in 'nextCount'.
+		for _, scan := range current {
+			t := scan.typ
+			if visited[t] {
+				// We've looked through this type before, at a higher level.
+				// That higher level would shadow the lower level we're now at,
+				// so this one can't be useful to us. Ignore it.
+				continue
 			}
-			switch {
-			case match(ft.Name()):
-				// Matching anonymous top-level field.
-				d = depth
-			case fd > depth:
-				// No top-level field yet; look inside nested structs.
-				if ft.Kind() == Struct {
-					st := (*structType)(unsafe.Pointer(ft.(*commonType)))
-					f, d = st.fieldByNameFunc(match, mark, depth+1)
+			visited[t] = true
+			for i := range t.fields {
+				f := &t.fields[i]
+				// Find name and type for field f.
+				var fname string
+				var ntyp *rtype
+				if f.name != nil {
+					fname = *f.name
+				} else {
+					// Anonymous field of type T or *T.
+					// Name taken from type.
+					ntyp = f.typ
+					if ntyp.Kind() == Ptr {
+						ntyp = ntyp.Elem().common()
+					}
+					fname = ntyp.Name()
 				}
-			}
-		}
 
-		switch {
-		case d < fd:
-			// Found field at shallower depth.
-			ff, fi, fd = f, i, d
-			n = 1
-		case d == fd:
-			// More than one matching field at the same depth (or d, fd == inf).
-			// Same as no field found at this depth.
-			n++
-			if d == depth {
-				// Impossible to find a field at lower depth.
-				break L
-			}
-		}
-	}
+				// Does it match?
+				if match(fname) {
+					// Potential match
+					if count[t] > 1 || ok {
+						// Name appeared multiple times at this level: annihilate.
+						return StructField{}, false
+					}
+					result = t.Field(i)
+					result.Index = nil
+					result.Index = append(result.Index, scan.index...)
+					result.Index = append(result.Index, i)
+					ok = true
+					continue
+				}
 
-	if n == 1 {
-		// Found matching field.
-		if depth >= len(ff.Index) {
-			ff.Index = make([]int, depth+1)
+				// Queue embedded struct fields for processing with next level,
+				// but only if we haven't seen a match yet at this level and only
+				// if the embedded types haven't already been queued.
+				if ok || ntyp == nil || ntyp.Kind() != Struct {
+					continue
+				}
+				styp := (*structType)(unsafe.Pointer(ntyp))
+				if nextCount[styp] > 0 {
+					nextCount[styp] = 2 // exact multiple doesn't matter
+					continue
+				}
+				if nextCount == nil {
+					nextCount = map[*structType]int{}
+				}
+				nextCount[styp] = 1
+				if count[t] > 1 {
+					nextCount[styp] = 2 // exact multiple doesn't matter
+				}
+				var index []int
+				index = append(index, scan.index...)
+				index = append(index, i)
+				next = append(next, fieldScan{styp, index})
+			}
 		}
-		if len(ff.Index) > 1 {
-			ff.Index[depth] = fi
+		if ok {
+			break
 		}
-	} else {
-		// None or more than one matching field found.
-		fd = inf
 	}
-
-	delete(mark, t)
 	return
 }
 
 // FieldByName returns the struct field with the given name
 // and a boolean to indicate if the field was found.
 func (t *structType) FieldByName(name string) (f StructField, present bool) {
-	return t.FieldByNameFunc(func(s string) bool { return s == name })
-}
-
-// FieldByNameFunc returns the struct field with a name that satisfies the
-// match function and a boolean to indicate if the field was found.
-func (t *structType) FieldByNameFunc(match func(string) bool) (f StructField, present bool) {
-	if ff, fd := t.fieldByNameFunc(match, make(map[*structType]bool), 0); fd < inf {
-		ff.Index = ff.Index[0 : fd+1]
-		f, present = ff, true
-	}
-	return
-}
-
-// Convert runtime type to reflect type.
-func toCommonType(p *runtimeType) *commonType {
-	if p == nil {
-		return nil
+	// Quick check for top-level name, or struct without anonymous fields.
+	hasAnon := false
+	if name != "" {
+		for i := range t.fields {
+			tf := &t.fields[i]
+			if tf.name == nil {
+				hasAnon = true
+				continue
+			}
+			if *tf.name == name {
+				return t.Field(i), true
+			}
+		}
 	}
-	return (*p).(*commonType)
-}
-
-func toType(p *runtimeType) Type {
-	if p == nil {
-		return nil
+	if !hasAnon {
+		return
 	}
-	return (*p).(*commonType)
+	return t.FieldByNameFunc(func(s string) bool { return s == name })
 }
 
 // TypeOf returns the reflection Type of the value in the interface{}.
@@ -949,28 +975,18 @@ func TypeOf(i interface{}) Type {
 // ptrMap is the cache for PtrTo.
 var ptrMap struct {
 	sync.RWMutex
-	m map[*commonType]*ptrType
-}
-
-func (t *commonType) runtimeType() *runtimeType {
-	// The runtimeType always precedes the commonType in memory.
-	// Adjust pointer to find it.
-	var rt struct {
-		i  runtimeType
-		ct commonType
-	}
-	return (*runtimeType)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) - unsafe.Offsetof(rt.ct)))
+	m map[*rtype]*ptrType
 }
 
 // PtrTo returns the pointer type with element t.
 // For example, if t represents type Foo, PtrTo(t) represents *Foo.
 func PtrTo(t Type) Type {
-	return t.(*commonType).ptrTo()
+	return t.(*rtype).ptrTo()
 }
 
-func (ct *commonType) ptrTo() *commonType {
-	if p := ct.ptrToThis; p != nil {
-		return toCommonType(p)
+func (t *rtype) ptrTo() *rtype {
+	if p := t.ptrToThis; p != nil {
+		return p
 	}
 
 	// Otherwise, synthesize one.
@@ -980,36 +996,31 @@ func (ct *commonType) ptrTo() *commonType {
 	// the type structures in read-only memory.
 	ptrMap.RLock()
 	if m := ptrMap.m; m != nil {
-		if p := m[ct]; p != nil {
+		if p := m[t]; p != nil {
 			ptrMap.RUnlock()
-			return &p.commonType
+			return &p.rtype
 		}
 	}
 	ptrMap.RUnlock()
 	ptrMap.Lock()
 	if ptrMap.m == nil {
-		ptrMap.m = make(map[*commonType]*ptrType)
+		ptrMap.m = make(map[*rtype]*ptrType)
 	}
-	p := ptrMap.m[ct]
+	p := ptrMap.m[t]
 	if p != nil {
 		// some other goroutine won the race and created it
 		ptrMap.Unlock()
-		return &p.commonType
+		return &p.rtype
 	}
 
-	var rt struct {
-		i runtimeType
-		ptrType
-	}
-	rt.i = &rt.commonType
-
-	// initialize p using *byte's ptrType as a prototype.
-	p = &rt.ptrType
-	var ibyte interface{} = (*byte)(nil)
-	bp := (*ptrType)(unsafe.Pointer((**(**runtimeType)(unsafe.Pointer(&ibyte))).(*commonType)))
-	*p = *bp
+	// Create a new ptrType starting with the description
+	// of an *unsafe.Pointer.
+	p = new(ptrType)
+	var iptr interface{} = (*unsafe.Pointer)(nil)
+	prototype := *(**ptrType)(unsafe.Pointer(&iptr))
+	*p = *prototype
 
-	s := "*" + *ct.string
+	s := "*" + *t.string
 	p.string = &s
 
 	// For the type structures linked into the binary, the
@@ -1017,37 +1028,53 @@ func (ct *commonType) ptrTo() *commonType {
 	// Create a good hash for the new string by using
 	// the FNV-1 hash's mixing function to combine the
 	// old hash and the new "*".
-	p.hash = ct.hash*16777619 ^ '*'
+	p.hash = fnv1(t.hash, '*')
 
 	p.uncommonType = nil
 	p.ptrToThis = nil
-	p.elem = (*runtimeType)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - unsafe.Offsetof(rt.ptrType)))
+	p.elem = t
 
-	ptrMap.m[ct] = p
+	ptrMap.m[t] = p
 	ptrMap.Unlock()
-	return &p.commonType
+	return &p.rtype
+}
+
+// fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function.
+func fnv1(x uint32, list ...byte) uint32 {
+	for _, b := range list {
+		x = x*16777619 ^ uint32(b)
+	}
+	return x
 }
 
-func (t *commonType) Implements(u Type) bool {
+func (t *rtype) Implements(u Type) bool {
 	if u == nil {
 		panic("reflect: nil type passed to Type.Implements")
 	}
 	if u.Kind() != Interface {
 		panic("reflect: non-interface type passed to Type.Implements")
 	}
-	return implements(u.(*commonType), t)
+	return implements(u.(*rtype), t)
 }
 
-func (t *commonType) AssignableTo(u Type) bool {
+func (t *rtype) AssignableTo(u Type) bool {
 	if u == nil {
 		panic("reflect: nil type passed to Type.AssignableTo")
 	}
-	uu := u.(*commonType)
+	uu := u.(*rtype)
 	return directlyAssignable(uu, t) || implements(uu, t)
 }
 
+func (t *rtype) ConvertibleTo(u Type) bool {
+	if u == nil {
+		panic("reflect: nil type passed to Type.ConvertibleTo")
+	}
+	uu := u.(*rtype)
+	return convertOp(uu, t) != nil
+}
+
 // implements returns true if the type V implements the interface type T.
-func implements(T, V *commonType) bool {
+func implements(T, V *rtype) bool {
 	if T.Kind() != Interface {
 		return false
 	}
@@ -1105,7 +1132,7 @@ func implements(T, V *commonType) bool {
 // http://golang.org/doc/go_spec.html#Assignability
 // Ignoring the interface rules (implemented elsewhere)
 // and the ideal constant rules (no ideal constants at run time).
-func directlyAssignable(T, V *commonType) bool {
+func directlyAssignable(T, V *rtype) bool {
 	// x's type V is identical to T?
 	if T == V {
 		return true
@@ -1117,10 +1144,28 @@ func directlyAssignable(T, V *commonType) bool {
 		return false
 	}
 
-	// x's type T and V have identical underlying types.
-	// Since at least one is unnamed, only the composite types
-	// need to be considered.
-	switch T.Kind() {
+	// x's type T and V must  have identical underlying types.
+	return haveIdenticalUnderlyingType(T, V)
+}
+
+func haveIdenticalUnderlyingType(T, V *rtype) bool {
+	if T == V {
+		return true
+	}
+
+	kind := T.Kind()
+	if kind != V.Kind() {
+		return false
+	}
+
+	// Non-composite types of equal kind have same underlying type
+	// (the predefined instance of the type).
+	if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
+		return true
+	}
+
+	// Composite types.
+	switch kind {
 	case Array:
 		return T.Elem() == V.Elem() && T.Len() == V.Len()
 
@@ -1178,8 +1223,19 @@ func directlyAssignable(T, V *commonType) bool {
 		for i := range t.fields {
 			tf := &t.fields[i]
 			vf := &v.fields[i]
-			if tf.name != vf.name || tf.pkgPath != vf.pkgPath ||
-				tf.typ != vf.typ || tf.tag != vf.tag || tf.offset != vf.offset {
+			if tf.name != vf.name && (tf.name == nil || vf.name == nil || *tf.name != *vf.name) {
+				return false
+			}
+			if tf.pkgPath != vf.pkgPath && (tf.pkgPath == nil || vf.pkgPath == nil || *tf.pkgPath != *vf.pkgPath) {
+				return false
+			}
+			if tf.typ != vf.typ {
+				return false
+			}
+			if tf.tag != vf.tag && (tf.tag == nil || vf.tag == nil || *tf.tag != *vf.tag) {
+				return false
+			}
+			if tf.offset != vf.offset {
 				return false
 			}
 		}
@@ -1188,3 +1244,295 @@ func directlyAssignable(T, V *commonType) bool {
 
 	return false
 }
+
+// typelinks is implemented in package runtime.
+// It retuns a slice of all the 'typelink' information in the binary,
+// which is to say a slice of known types, sorted by string.
+// Note that strings are not unique identifiers for types:
+// there can be more than one with a given string.
+// Only types we might want to look up are included:
+// channels, maps, slices, and arrays.
+func typelinks() []*rtype
+
+// typesByString returns the subslice of typelinks() whose elements have
+// the given string representation.
+// It may be empty (no known types with that string) or may have
+// multiple elements (multiple types with that string).
+func typesByString(s string) []*rtype {
+	typ := typelinks()
+
+	// We are looking for the first index i where the string becomes >= s.
+	// This is a copy of sort.Search, with f(h) replaced by (*typ[h].string >= s).
+	i, j := 0, len(typ)
+	for i < j {
+		h := i + (j-i)/2 // avoid overflow when computing h
+		// i ≤ h < j
+		if !(*typ[h].string >= s) {
+			i = h + 1 // preserves f(i-1) == false
+		} else {
+			j = h // preserves f(j) == true
+		}
+	}
+	// i == j, f(i-1) == false, and f(j) (= f(i)) == true  =>  answer is i.
+
+	// Having found the first, linear scan forward to find the last.
+	// We could do a second binary search, but the caller is going
+	// to do a linear scan anyway.
+	j = i
+	for j < len(typ) && *typ[j].string == s {
+		j++
+	}
+
+	// This slice will be empty if the string is not found.
+	return typ[i:j]
+}
+
+// The lookupCache caches ChanOf, MapOf, and SliceOf lookups.
+var lookupCache struct {
+	sync.RWMutex
+	m map[cacheKey]*rtype
+}
+
+// A cacheKey is the key for use in the lookupCache.
+// Four values describe any of the types we are looking for:
+// type kind, one or two subtypes, and an extra integer.
+type cacheKey struct {
+	kind  Kind
+	t1    *rtype
+	t2    *rtype
+	extra uintptr
+}
+
+// cacheGet looks for a type under the key k in the lookupCache.
+// If it finds one, it returns that type.
+// If not, it returns nil with the cache locked.
+// The caller is expected to use cachePut to unlock the cache.
+func cacheGet(k cacheKey) Type {
+	lookupCache.RLock()
+	t := lookupCache.m[k]
+	lookupCache.RUnlock()
+	if t != nil {
+		return t
+	}
+
+	lookupCache.Lock()
+	t = lookupCache.m[k]
+	if t != nil {
+		lookupCache.Unlock()
+		return t
+	}
+
+	if lookupCache.m == nil {
+		lookupCache.m = make(map[cacheKey]*rtype)
+	}
+
+	return nil
+}
+
+// cachePut stores the given type in the cache, unlocks the cache,
+// and returns the type. It is expected that the cache is locked
+// because cacheGet returned nil.
+func cachePut(k cacheKey, t *rtype) Type {
+	lookupCache.m[k] = t
+	lookupCache.Unlock()
+	return t
+}
+
+// ChanOf returns the channel type with the given direction and element type.
+// For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int.
+//
+// The gc runtime imposes a limit of 64 kB on channel element types.
+// If t's size is equal to or exceeds this limit, ChanOf panics.
+func ChanOf(dir ChanDir, t Type) Type {
+	typ := t.(*rtype)
+
+	// Look in cache.
+	ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
+	if ch := cacheGet(ckey); ch != nil {
+		return ch
+	}
+
+	// This restriction is imposed by the gc compiler and the runtime.
+	if typ.size >= 1<<16 {
+		lookupCache.Unlock()
+		panic("reflect.ChanOf: element size too large")
+	}
+
+	// Look in known types.
+	// TODO: Precedence when constructing string.
+	var s string
+	switch dir {
+	default:
+		lookupCache.Unlock()
+		panic("reflect.ChanOf: invalid dir")
+	case SendDir:
+		s = "chan<- " + *typ.string
+	case RecvDir:
+		s = "<-chan " + *typ.string
+	case BothDir:
+		s = "chan " + *typ.string
+	}
+	for _, tt := range typesByString(s) {
+		ch := (*chanType)(unsafe.Pointer(tt))
+		if ch.elem == typ && ch.dir == uintptr(dir) {
+			return cachePut(ckey, tt)
+		}
+	}
+
+	// Make a channel type.
+	var ichan interface{} = (chan unsafe.Pointer)(nil)
+	prototype := *(**chanType)(unsafe.Pointer(&ichan))
+	ch := new(chanType)
+	*ch = *prototype
+	ch.string = &s
+	ch.hash = fnv1(typ.hash, 'c', byte(dir))
+	ch.elem = typ
+	ch.uncommonType = nil
+	ch.ptrToThis = nil
+
+	return cachePut(ckey, &ch.rtype)
+}
+
+// MapOf returns the map type with the given key and element types.
+// For example, if k represents int and e represents string,
+// MapOf(k, e) represents map[int]string.
+//
+// If the key type is not a valid map key type (that is, if it does
+// not implement Go's == operator), MapOf panics. TODO(rsc).
+func MapOf(key, elem Type) Type {
+	ktyp := key.(*rtype)
+	etyp := elem.(*rtype)
+
+	// TODO: Check for invalid key types.
+
+	// Look in cache.
+	ckey := cacheKey{Map, ktyp, etyp, 0}
+	if mt := cacheGet(ckey); mt != nil {
+		return mt
+	}
+
+	// Look in known types.
+	s := "map[" + *ktyp.string + "]" + *etyp.string
+	for _, tt := range typesByString(s) {
+		mt := (*mapType)(unsafe.Pointer(tt))
+		if mt.key == ktyp && mt.elem == etyp {
+			return cachePut(ckey, tt)
+		}
+	}
+
+	// Make a map type.
+	var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
+	prototype := *(**mapType)(unsafe.Pointer(&imap))
+	mt := new(mapType)
+	*mt = *prototype
+	mt.string = &s
+	mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
+	mt.key = ktyp
+	mt.elem = etyp
+	mt.uncommonType = nil
+	mt.ptrToThis = nil
+
+	return cachePut(ckey, &mt.rtype)
+}
+
+// SliceOf returns the slice type with element type t.
+// For example, if t represents int, SliceOf(t) represents []int.
+func SliceOf(t Type) Type {
+	typ := t.(*rtype)
+
+	// Look in cache.
+	ckey := cacheKey{Slice, typ, nil, 0}
+	if slice := cacheGet(ckey); slice != nil {
+		return slice
+	}
+
+	// Look in known types.
+	s := "[]" + *typ.string
+	for _, tt := range typesByString(s) {
+		slice := (*sliceType)(unsafe.Pointer(tt))
+		if slice.elem == typ {
+			return cachePut(ckey, tt)
+		}
+	}
+
+	// Make a slice type.
+	var islice interface{} = ([]unsafe.Pointer)(nil)
+	prototype := *(**sliceType)(unsafe.Pointer(&islice))
+	slice := new(sliceType)
+	*slice = *prototype
+	slice.string = &s
+	slice.hash = fnv1(typ.hash, '[')
+	slice.elem = typ
+	slice.uncommonType = nil
+	slice.ptrToThis = nil
+
+	return cachePut(ckey, &slice.rtype)
+}
+
+// ArrayOf returns the array type with the given count and element type.
+// For example, if t represents int, ArrayOf(5, t) represents [5]int.
+//
+// If the resulting type would be larger than the available address space,
+// ArrayOf panics.
+//
+// TODO(rsc): Unexported for now. Export once the alg field is set correctly
+// for the type. This may require significant work.
+func arrayOf(count int, elem Type) Type {
+	typ := elem.(*rtype)
+	slice := SliceOf(elem)
+
+	// Look in cache.
+	ckey := cacheKey{Array, typ, nil, uintptr(count)}
+	if slice := cacheGet(ckey); slice != nil {
+		return slice
+	}
+
+	// Look in known types.
+	s := "[" + strconv.Itoa(count) + "]" + *typ.string
+	for _, tt := range typesByString(s) {
+		slice := (*sliceType)(unsafe.Pointer(tt))
+		if slice.elem == typ {
+			return cachePut(ckey, tt)
+		}
+	}
+
+	// Make an array type.
+	var iarray interface{} = [1]unsafe.Pointer{}
+	prototype := *(**arrayType)(unsafe.Pointer(&iarray))
+	array := new(arrayType)
+	*array = *prototype
+	array.string = &s
+	array.hash = fnv1(typ.hash, '[')
+	for n := uint32(count); n > 0; n >>= 8 {
+		array.hash = fnv1(array.hash, byte(n))
+	}
+	array.hash = fnv1(array.hash, ']')
+	array.elem = typ
+	max := ^uintptr(0) / typ.size
+	if uintptr(count) > max {
+		panic("reflect.ArrayOf: array size would exceed virtual address space")
+	}
+	array.size = typ.size * uintptr(count)
+	array.align = typ.align
+	array.fieldAlign = typ.fieldAlign
+	// TODO: array.alg
+	// TODO: array.gc
+	array.uncommonType = nil
+	array.ptrToThis = nil
+	array.len = uintptr(count)
+	array.slice = slice.(*rtype)
+
+	return cachePut(ckey, &array.rtype)
+}
+
+// toType converts from a *rtype to a Type that can be returned
+// to the client of package reflect. In gc, the only concern is that
+// a nil *rtype must be replaced by a nil Type, but in gccgo this
+// function takes care of ensuring that multiple *rtype for the same
+// type are coalesced into a single Type.
+func toType(t *rtype) Type {
+	if t == nil {
+		return nil
+	}
+	return t
+}
diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go
index 79476ad..c87812c 100644
--- a/src/pkg/reflect/value.go
+++ b/src/pkg/reflect/value.go
@@ -60,7 +60,7 @@ func memmove(adst, asrc unsafe.Pointer, n uintptr) {
 // direct operations.
 type Value struct {
 	// typ holds the type of the value represented by a Value.
-	typ *commonType
+	typ *rtype
 
 	// val holds the 1-word representation of the value.
 	// If flag's flagIndir bit is set, then val is a pointer to the data.
@@ -211,7 +211,7 @@ func storeIword(p unsafe.Pointer, w iword, n uintptr) {
 
 // emptyInterface is the header for an interface{} value.
 type emptyInterface struct {
-	typ  *runtimeType
+	typ  *rtype
 	word iword
 }
 
@@ -219,8 +219,8 @@ type emptyInterface struct {
 type nonEmptyInterface struct {
 	// see ../runtime/iface.c:/Itab
 	itab *struct {
-		ityp   *runtimeType // static interface type
-		typ    *runtimeType // dynamic concrete type
+		ityp   *rtype // static interface type
+		typ    *rtype // dynamic concrete type
 		link   unsafe.Pointer
 		bad    int32
 		unused int32
@@ -302,6 +302,17 @@ func (v Value) Bytes() []byte {
 	return *(*[]byte)(v.val)
 }
 
+// runes returns v's underlying value.
+// It panics if v's underlying value is not a slice of runes (int32s).
+func (v Value) runes() []rune {
+	v.mustBe(Slice)
+	if v.typ.Elem().Kind() != Int32 {
+		panic("reflect.Value.Bytes of non-rune slice")
+	}
+	// Slice is always bigger than a word; assume flagIndir.
+	return *(*[]rune)(v.val)
+}
+
 // CanAddr returns true if the value's address can be obtained with Addr.
 // Such values are called addressable.  A value is addressable if it is
 // an element of a slice, an element of an addressable array,
@@ -335,7 +346,7 @@ func (v Value) Call(in []Value) []Value {
 }
 
 // CallSlice calls the variadic function v with the input arguments in,
-// assigning the slice in[len(in)-1] to v's final variadic argument.  
+// assigning the slice in[len(in)-1] to v's final variadic argument.
 // For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]...).
 // Call panics if v's Kind is not Func or if v is not variadic.
 // It returns the output results as Values.
@@ -365,12 +376,12 @@ func (v Value) call(method string, in []Value) []Value {
 			if m.pkgPath != nil {
 				panic(method + " of unexported method")
 			}
-			t = toCommonType(m.typ)
+			t = m.typ
 			iface := (*nonEmptyInterface)(v.val)
 			if iface.itab == nil {
 				panic(method + " of method on nil interface value")
 			}
-			fn = iface.itab.fun[i]
+			fn = unsafe.Pointer(&iface.itab.fun[i])
 			rcvr = iface.word
 		} else {
 			ut := v.typ.uncommon()
@@ -381,8 +392,8 @@ func (v Value) call(method string, in []Value) []Value {
 			if m.pkgPath != nil {
 				panic(method + " of unexported method")
 			}
-			fn = m.ifn
-			t = toCommonType(m.mtyp)
+			fn = unsafe.Pointer(&m.ifn)
+			t = m.mtyp
 			rcvr = v.iword()
 		}
 	} else if v.flag&flagIndir != 0 {
@@ -490,9 +501,9 @@ func (v Value) call(method string, in []Value) []Value {
 	// TODO(rsc): revisit when reference counting happens.
 	// The values are holding up the in references for us,
 	// but something must be done for the out references.
-	// For now make everything look like a pointer by pretending
-	// to allocate a []*int.
-	args := make([]*int, size/ptrSize)
+	// For now make everything look like a pointer by allocating
+	// a []unsafe.Pointer.
+	args := make([]unsafe.Pointer, size/ptrSize)
 	ptr := uintptr(unsafe.Pointer(&args[0]))
 	off := uintptr(0)
 	if v.flag&flagMethod != 0 {
@@ -502,7 +513,7 @@ func (v Value) call(method string, in []Value) []Value {
 	}
 	for i, v := range in {
 		v.mustBeExported()
-		targ := t.In(i).(*commonType)
+		targ := t.In(i).(*rtype)
 		a := uintptr(targ.align)
 		off = (off + a - 1) &^ (a - 1)
 		n := targ.size
@@ -536,6 +547,85 @@ func (v Value) call(method string, in []Value) []Value {
 	return ret
 }
 
+// callReflect is the call implementation used by a function
+// returned by MakeFunc. In many ways it is the opposite of the
+// method Value.call above. The method above converts a call using Values
+// into a call of a function with a concrete argument frame, while
+// callReflect converts a call of a function with a concrete argument
+// frame into a call using Values.
+// It is in this file so that it can be next to the call method above.
+// The remainder of the MakeFunc implementation is in makefunc.go.
+func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
+	ftyp := ctxt.typ
+	f := ctxt.fn
+
+	// Copy argument frame into Values.
+	ptr := frame
+	off := uintptr(0)
+	in := make([]Value, 0, len(ftyp.in))
+	for _, arg := range ftyp.in {
+		typ := arg
+		off += -off & uintptr(typ.align-1)
+		v := Value{typ, nil, flag(typ.Kind()) << flagKindShift}
+		if typ.size <= ptrSize {
+			// value fits in word.
+			v.val = unsafe.Pointer(loadIword(unsafe.Pointer(uintptr(ptr)+off), typ.size))
+		} else {
+			// value does not fit in word.
+			// 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.val = unsafe_New(typ)
+			memmove(v.val, unsafe.Pointer(uintptr(ptr)+off), typ.size)
+			v.flag |= flagIndir
+		}
+		in = append(in, v)
+		off += typ.size
+	}
+
+	// Call underlying function.
+	out := f(in)
+	if len(out) != len(ftyp.out) {
+		panic("reflect: wrong return count from function created by MakeFunc")
+	}
+
+	// Copy results back into argument frame.
+	if len(ftyp.out) > 0 {
+		off += -off & (ptrSize - 1)
+		for i, arg := range ftyp.out {
+			typ := arg
+			v := out[i]
+			if v.typ != typ {
+				panic("reflect: function created by MakeFunc using " + funcName(f) +
+					" returned wrong type: have " +
+					out[i].typ.String() + " for " + typ.String())
+			}
+			if v.flag&flagRO != 0 {
+				panic("reflect: function created by MakeFunc using " + funcName(f) +
+					" returned value obtained from unexported field")
+			}
+			off += -off & uintptr(typ.align-1)
+			addr := unsafe.Pointer(uintptr(ptr) + off)
+			if v.flag&flagIndir == 0 {
+				storeIword(addr, iword(v.val), typ.size)
+			} else {
+				memmove(addr, v.val, typ.size)
+			}
+			off += typ.size
+		}
+	}
+}
+
+// funcName returns the name of f, for use in error messages.
+func funcName(f func([]Value) []Value) string {
+	pc := *(*uintptr)(unsafe.Pointer(&f))
+	rf := runtime.FuncForPC(pc)
+	if rf != nil {
+		return rf.Name()
+	}
+	return "closure"
+}
+
 // Cap returns v's capacity.
 // It panics if v's Kind is not Array, Chan, or Slice.
 func (v Value) Cap() int {
@@ -586,7 +676,7 @@ func (v Value) Elem() Value {
 	switch k {
 	case Interface:
 		var (
-			typ *commonType
+			typ *rtype
 			val unsafe.Pointer
 		)
 		if v.typ.NumMethod() == 0 {
@@ -595,7 +685,7 @@ func (v Value) Elem() Value {
 				// nil interface value
 				return Value{}
 			}
-			typ = toCommonType(eface.typ)
+			typ = eface.typ
 			val = unsafe.Pointer(eface.word)
 		} else {
 			iface := (*nonEmptyInterface)(v.val)
@@ -603,7 +693,7 @@ func (v Value) Elem() Value {
 				// nil interface value
 				return Value{}
 			}
-			typ = toCommonType(iface.itab.typ)
+			typ = iface.itab.typ
 			val = unsafe.Pointer(iface.word)
 		}
 		fl := v.flag & flagRO
@@ -623,7 +713,7 @@ func (v Value) Elem() Value {
 			return Value{}
 		}
 		tt := (*ptrType)(unsafe.Pointer(v.typ))
-		typ := toCommonType(tt.elem)
+		typ := tt.elem
 		fl := v.flag&flagRO | flagIndir | flagAddr
 		fl |= flag(typ.Kind() << flagKindShift)
 		return Value{typ, val, fl}
@@ -640,7 +730,7 @@ func (v Value) Field(i int) Value {
 		panic("reflect: Field index out of range")
 	}
 	field := &tt.fields[i]
-	typ := toCommonType(field.typ)
+	typ := field.typ
 
 	// Inherit permission bits from v.
 	fl := v.flag & (flagRO | flagIndir | flagAddr)
@@ -723,8 +813,10 @@ func (v Value) Float() float64 {
 	panic(&ValueError{"reflect.Value.Float", k})
 }
 
+var uint8Type = TypeOf(uint8(0)).(*rtype)
+
 // Index returns v's i'th element.
-// It panics if v's Kind is not Array or Slice or i is out of range.
+// 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 {
@@ -733,7 +825,7 @@ func (v Value) Index(i int) Value {
 		if i < 0 || i > int(tt.len) {
 			panic("reflect: array index out of range")
 		}
-		typ := toCommonType(tt.elem)
+		typ := tt.elem
 		fl := v.flag & (flagRO | flagIndir | flagAddr) // bits same as overall array
 		fl |= flag(typ.Kind()) << flagKindShift
 		offset := uintptr(i) * typ.size
@@ -761,10 +853,19 @@ func (v Value) Index(i int) Value {
 			panic("reflect: slice index out of range")
 		}
 		tt := (*sliceType)(unsafe.Pointer(v.typ))
-		typ := toCommonType(tt.elem)
+		typ := tt.elem
 		fl |= flag(typ.Kind()) << flagKindShift
 		val := unsafe.Pointer(s.Data + uintptr(i)*typ.size)
 		return Value{typ, val, fl}
+
+	case String:
+		fl := v.flag&flagRO | flag(Uint8<<flagKindShift)
+		s := (*StringHeader)(v.val)
+		if i < 0 || i >= s.Len {
+			panic("reflect: string index out of range")
+		}
+		val := *(*byte)(unsafe.Pointer(s.Data + uintptr(i)))
+		return Value{uint8Type, unsafe.Pointer(uintptr(val)), fl}
 	}
 	panic(&ValueError{"reflect.Value.Index", k})
 }
@@ -826,7 +927,7 @@ func valueInterface(v Value, safe bool) interface{} {
 
 	if safe && v.flag&flagRO != 0 {
 		// Do not allow access to unexported values via Interface,
-		// because they might be pointers that should not be 
+		// because they might be pointers that should not be
 		// writable or methods or function that should not be callable.
 		panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
 	}
@@ -846,7 +947,7 @@ func valueInterface(v Value, safe bool) interface{} {
 
 	// Non-interface value.
 	var eface emptyInterface
-	eface.typ = v.typ.runtimeType()
+	eface.typ = v.typ
 	eface.word = v.iword()
 
 	if v.flag&flagIndir != 0 && v.typ.size > ptrSize {
@@ -919,9 +1020,9 @@ func (v Value) Len() int {
 		tt := (*arrayType)(unsafe.Pointer(v.typ))
 		return int(tt.len)
 	case Chan:
-		return int(chanlen(v.iword()))
+		return chanlen(v.iword())
 	case Map:
-		return int(maplen(v.iword()))
+		return maplen(v.iword())
 	case Slice:
 		// Slice is bigger than a word; assume flagIndir.
 		return (*SliceHeader)(v.val).Len
@@ -947,13 +1048,13 @@ func (v Value) MapIndex(key Value) Value {
 	// considered unexported.  This is consistent with the
 	// behavior for structs, which allow read but not write
 	// of unexported fields.
-	key = key.assignTo("reflect.Value.MapIndex", toCommonType(tt.key), nil)
+	key = key.assignTo("reflect.Value.MapIndex", tt.key, nil)
 
-	word, ok := mapaccess(v.typ.runtimeType(), v.iword(), key.iword())
+	word, ok := mapaccess(v.typ, v.iword(), key.iword())
 	if !ok {
 		return Value{}
 	}
-	typ := toCommonType(tt.elem)
+	typ := tt.elem
 	fl := (v.flag | key.flag) & flagRO
 	if typ.size > ptrSize {
 		fl |= flagIndir
@@ -969,7 +1070,7 @@ func (v Value) MapIndex(key Value) Value {
 func (v Value) MapKeys() []Value {
 	v.mustBe(Map)
 	tt := (*mapType)(unsafe.Pointer(v.typ))
-	keyType := toCommonType(tt.key)
+	keyType := tt.key
 
 	fl := v.flag & flagRO
 	fl |= flag(keyType.Kind()) << flagKindShift
@@ -978,11 +1079,11 @@ func (v Value) MapKeys() []Value {
 	}
 
 	m := v.iword()
-	mlen := int32(0)
+	mlen := int(0)
 	if m != nil {
 		mlen = maplen(m)
 	}
-	it := mapiterinit(v.typ.runtimeType(), m)
+	it := mapiterinit(v.typ, m)
 	a := make([]Value, mlen)
 	var i int
 	for i = 0; i < len(a); i++ {
@@ -1081,7 +1182,7 @@ func overflowFloat32(x float64) bool {
 	if x < 0 {
 		x = -x
 	}
-	return math.MaxFloat32 <= x && x <= math.MaxFloat64
+	return math.MaxFloat32 < x && x <= math.MaxFloat64
 }
 
 // OverflowInt returns true if the int64 x cannot be represented by v's type.
@@ -1115,18 +1216,35 @@ func (v Value) OverflowUint(x uint64) bool {
 // code using reflect cannot obtain unsafe.Pointers
 // without importing the unsafe package explicitly.
 // It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer.
+//
+// If v's Kind is Func, the returned pointer is an underlying
+// code pointer, but not necessarily enough to identify a
+// single function uniquely. The only guarantee is that the
+// result is zero if and only if v is a nil func Value.
 func (v Value) Pointer() uintptr {
 	k := v.kind()
 	switch k {
-	case Chan, Func, Map, Ptr, UnsafePointer:
-		if k == Func && v.flag&flagMethod != 0 {
+	case Chan, Map, Ptr, UnsafePointer:
+		p := v.val
+		if v.flag&flagIndir != 0 {
+			p = *(*unsafe.Pointer)(p)
+		}
+		return uintptr(p)
+	case Func:
+		if v.flag&flagMethod != 0 {
 			panic("reflect.Value.Pointer of method Value")
 		}
 		p := v.val
 		if v.flag&flagIndir != 0 {
 			p = *(*unsafe.Pointer)(p)
 		}
+		// Non-nil func value points at data block.
+		// First word of data block is actual code.
+		if p != nil {
+			p = *(*unsafe.Pointer)(p)
+		}
 		return uintptr(p)
+
 	case Slice:
 		return (*SliceHeader)(v.val).Data
 	}
@@ -1151,9 +1269,9 @@ func (v Value) recv(nb bool) (val Value, ok bool) {
 	if ChanDir(tt.dir)&RecvDir == 0 {
 		panic("recv on send-only channel")
 	}
-	word, selected, ok := chanrecv(v.typ.runtimeType(), v.iword(), nb)
+	word, selected, ok := chanrecv(v.typ, v.iword(), nb)
 	if selected {
-		typ := toCommonType(tt.elem)
+		typ := tt.elem
 		fl := flag(typ.Kind()) << flagKindShift
 		if typ.size > ptrSize {
 			fl |= flagIndir
@@ -1180,8 +1298,8 @@ func (v Value) send(x Value, nb bool) (selected bool) {
 		panic("send on recv-only channel")
 	}
 	x.mustBeExported()
-	x = x.assignTo("reflect.Value.Send", toCommonType(tt.elem), nil)
-	return chansend(v.typ.runtimeType(), v.iword(), x.iword(), nb)
+	x = x.assignTo("reflect.Value.Send", tt.elem, nil)
+	return chansend(v.typ, v.iword(), x.iword(), nb)
 }
 
 // Set assigns x to the value v.
@@ -1221,6 +1339,17 @@ func (v Value) SetBytes(x []byte) {
 	*(*[]byte)(v.val) = x
 }
 
+// setRunes sets v's underlying value.
+// It panics if v's underlying value is not a slice of runes (int32s).
+func (v Value) setRunes(x []rune) {
+	v.mustBeAssignable()
+	v.mustBe(Slice)
+	if v.typ.Elem().Kind() != Int32 {
+		panic("reflect.Value.setRunes of non-rune slice")
+	}
+	*(*[]rune)(v.val) = x
+}
+
 // SetComplex sets v's underlying value to x.
 // It panics if v's Kind is not Complex64 or Complex128, or if CanSet() is false.
 func (v Value) SetComplex(x complex128) {
@@ -1292,12 +1421,12 @@ func (v Value) SetMapIndex(key, val Value) {
 	v.mustBeExported()
 	key.mustBeExported()
 	tt := (*mapType)(unsafe.Pointer(v.typ))
-	key = key.assignTo("reflect.Value.SetMapIndex", toCommonType(tt.key), nil)
+	key = key.assignTo("reflect.Value.SetMapIndex", tt.key, nil)
 	if val.typ != nil {
 		val.mustBeExported()
-		val = val.assignTo("reflect.Value.SetMapIndex", toCommonType(tt.elem), nil)
+		val = val.assignTo("reflect.Value.SetMapIndex", tt.elem, nil)
 	}
-	mapassign(v.typ.runtimeType(), v.iword(), key.iword(), val.iword(), val.typ != nil)
+	mapassign(v.typ, v.iword(), key.iword(), val.iword(), val.typ != nil)
 }
 
 // SetUint sets v's underlying value to x.
@@ -1339,7 +1468,7 @@ func (v Value) SetString(x string) {
 }
 
 // Slice returns a slice of v.
-// It panics if v's Kind is not Array or Slice.
+// It panics if v's Kind is not Array, Slice or String, or if v is an unaddressable array.
 func (v Value) Slice(beg, end int) Value {
 	var (
 		cap  int
@@ -1349,31 +1478,44 @@ func (v Value) Slice(beg, end int) Value {
 	switch k := v.kind(); k {
 	default:
 		panic(&ValueError{"reflect.Value.Slice", k})
+
 	case Array:
 		if v.flag&flagAddr == 0 {
 			panic("reflect.Value.Slice: slice of unaddressable array")
 		}
 		tt := (*arrayType)(unsafe.Pointer(v.typ))
 		cap = int(tt.len)
-		typ = (*sliceType)(unsafe.Pointer(toCommonType(tt.slice)))
+		typ = (*sliceType)(unsafe.Pointer(tt.slice))
 		base = v.val
+
 	case Slice:
 		typ = (*sliceType)(unsafe.Pointer(v.typ))
 		s := (*SliceHeader)(v.val)
 		base = unsafe.Pointer(s.Data)
 		cap = s.Cap
 
+	case String:
+		s := (*StringHeader)(v.val)
+		if beg < 0 || end < beg || end > s.Len {
+			panic("reflect.Value.Slice: string slice index out of bounds")
+		}
+		var x string
+		val := (*StringHeader)(unsafe.Pointer(&x))
+		val.Data = s.Data + uintptr(beg)
+		val.Len = end - beg
+		return Value{v.typ, unsafe.Pointer(&x), v.flag}
 	}
+
 	if beg < 0 || end < beg || end > cap {
 		panic("reflect.Value.Slice: slice index out of bounds")
 	}
 
 	// Declare slice so that gc can see the base pointer in it.
-	var x []byte
+	var x []unsafe.Pointer
 
 	// Reinterpret as *SliceHeader to edit.
 	s := (*SliceHeader)(unsafe.Pointer(&x))
-	s.Data = uintptr(base) + uintptr(beg)*toCommonType(typ.elem).Size()
+	s.Data = uintptr(base) + uintptr(beg)*typ.elem.Size()
 	s.Len = end - beg
 	s.Cap = cap - beg
 
@@ -1439,7 +1581,7 @@ func (v Value) Type() Type {
 			panic("reflect: broken Value")
 		}
 		m := &tt.methods[i]
-		return toCommonType(m.typ)
+		return m.typ
 	}
 	// Method on concrete type.
 	ut := v.typ.uncommon()
@@ -1447,7 +1589,7 @@ func (v Value) Type() Type {
 		panic("reflect: broken Value")
 	}
 	m := &ut.methods[i]
-	return toCommonType(m.mtyp)
+	return m.mtyp
 }
 
 // Uint returns v's underlying value, as a uint64.
@@ -1618,13 +1760,148 @@ func Copy(dst, src Value) int {
 	return n
 }
 
+// A runtimeSelect is a single case passed to rselect.
+// This must match ../runtime/chan.c:/runtimeSelect
+type runtimeSelect struct {
+	dir uintptr // 0, SendDir, or RecvDir
+	typ *rtype  // channel type
+	ch  iword   // interface word for channel
+	val iword   // interface word for value (for SendDir)
+}
+
+// rselect runs a select. It returns the index of the chosen case,
+// and if the case was a receive, the interface word of the received
+// value and the conventional OK bool to indicate whether the receive
+// corresponds to a sent value.
+func rselect([]runtimeSelect) (chosen int, recv iword, recvOK bool)
+
+// A SelectDir describes the communication direction of a select case.
+type SelectDir int
+
+// NOTE: These values must match ../runtime/chan.c:/SelectDir.
+
+const (
+	_             SelectDir = iota
+	SelectSend              // case Chan <- Send
+	SelectRecv              // case <-Chan:
+	SelectDefault           // default
+)
+
+// A SelectCase describes a single case in a select operation.
+// The kind of case depends on Dir, the communication direction.
+//
+// If Dir is SelectDefault, the case represents a default case.
+// Chan and Send must be zero Values.
+//
+// If Dir is SelectSend, the case represents a send operation.
+// Normally Chan's underlying value must be a channel, and Send's underlying value must be
+// assignable to the channel's element type. As a special case, if Chan is a zero Value,
+// then the case is ignored, and the field Send will also be ignored and may be either zero
+// or non-zero.
+//
+// If Dir is SelectRecv, the case represents a receive operation.
+// Normally Chan's underlying value must be a channel and Send must be a zero Value.
+// If Chan is a zero Value, then the case is ignored, but Send must still be a zero Value.
+// When a receive operation is selected, the received Value is returned by Select.
+//
+type SelectCase struct {
+	Dir  SelectDir // direction of case
+	Chan Value     // channel to use (for send or receive)
+	Send Value     // value to send (for send)
+}
+
+// Select executes a select operation described by the list of cases.
+// Like the Go select statement, it blocks until at least one of the cases
+// can proceed, makes a uniform pseudo-random choice,
+// and then executes that case. It returns the index of the chosen case
+// and, if that case was a receive operation, the value received and a
+// boolean indicating whether the value corresponds to a send on the channel
+// (as opposed to a zero value received because the channel is closed).
+func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
+	// NOTE: Do not trust that caller is not modifying cases data underfoot.
+	// The range is safe because the caller cannot modify our copy of the len
+	// and each iteration makes its own copy of the value c.
+	runcases := make([]runtimeSelect, len(cases))
+	haveDefault := false
+	for i, c := range cases {
+		rc := &runcases[i]
+		rc.dir = uintptr(c.Dir)
+		switch c.Dir {
+		default:
+			panic("reflect.Select: invalid Dir")
+
+		case SelectDefault: // default
+			if haveDefault {
+				panic("reflect.Select: multiple default cases")
+			}
+			haveDefault = true
+			if c.Chan.IsValid() {
+				panic("reflect.Select: default case has Chan value")
+			}
+			if c.Send.IsValid() {
+				panic("reflect.Select: default case has Send value")
+			}
+
+		case SelectSend:
+			ch := c.Chan
+			if !ch.IsValid() {
+				break
+			}
+			ch.mustBe(Chan)
+			ch.mustBeExported()
+			tt := (*chanType)(unsafe.Pointer(ch.typ))
+			if ChanDir(tt.dir)&SendDir == 0 {
+				panic("reflect.Select: SendDir case using recv-only channel")
+			}
+			rc.ch = ch.iword()
+			rc.typ = &tt.rtype
+			v := c.Send
+			if !v.IsValid() {
+				panic("reflect.Select: SendDir case missing Send value")
+			}
+			v.mustBeExported()
+			v = v.assignTo("reflect.Select", tt.elem, nil)
+			rc.val = v.iword()
+
+		case SelectRecv:
+			if c.Send.IsValid() {
+				panic("reflect.Select: RecvDir case has Send value")
+			}
+			ch := c.Chan
+			if !ch.IsValid() {
+				break
+			}
+			ch.mustBe(Chan)
+			ch.mustBeExported()
+			tt := (*chanType)(unsafe.Pointer(ch.typ))
+			rc.typ = &tt.rtype
+			if ChanDir(tt.dir)&RecvDir == 0 {
+				panic("reflect.Select: RecvDir case using send-only channel")
+			}
+			rc.ch = ch.iword()
+		}
+	}
+
+	chosen, word, recvOK := rselect(runcases)
+	if runcases[chosen].dir == uintptr(SelectRecv) {
+		tt := (*chanType)(unsafe.Pointer(runcases[chosen].typ))
+		typ := tt.elem
+		fl := flag(typ.Kind()) << flagKindShift
+		if typ.size > ptrSize {
+			fl |= flagIndir
+		}
+		recv = Value{typ, unsafe.Pointer(word), fl}
+	}
+	return chosen, recv, recvOK
+}
+
 /*
  * constructors
  */
 
 // implemented in package runtime
-func unsafe_New(Type) unsafe.Pointer
-func unsafe_NewArray(Type, int) unsafe.Pointer
+func unsafe_New(*rtype) unsafe.Pointer
+func unsafe_NewArray(*rtype, int) unsafe.Pointer
 
 // MakeSlice creates a new zero-initialized slice value
 // for the specified slice type, length, and capacity.
@@ -1643,11 +1920,11 @@ func MakeSlice(typ Type, len, cap int) Value {
 	}
 
 	// Declare slice so that gc can see the base pointer in it.
-	var x []byte
+	var x []unsafe.Pointer
 
 	// Reinterpret as *SliceHeader to edit.
 	s := (*SliceHeader)(unsafe.Pointer(&x))
-	s.Data = uintptr(unsafe_NewArray(typ.Elem(), cap))
+	s.Data = uintptr(unsafe_NewArray(typ.Elem().(*rtype), cap))
 	s.Len = len
 	s.Cap = cap
 
@@ -1665,7 +1942,7 @@ func MakeChan(typ Type, buffer int) Value {
 	if typ.ChanDir() != BothDir {
 		panic("reflect.MakeChan: unidirectional channel type")
 	}
-	ch := makechan(typ.runtimeType(), uint32(buffer))
+	ch := makechan(typ.(*rtype), uint64(buffer))
 	return Value{typ.common(), unsafe.Pointer(ch), flag(Chan) << flagKindShift}
 }
 
@@ -1674,7 +1951,7 @@ func MakeMap(typ Type) Value {
 	if typ.Kind() != Map {
 		panic("reflect.MakeMap of non-map type")
 	}
-	m := makemap(typ.runtimeType())
+	m := makemap(typ.(*rtype))
 	return Value{typ.common(), unsafe.Pointer(m), flag(Map) << flagKindShift}
 }
 
@@ -1705,7 +1982,7 @@ func ValueOf(i interface{}) Value {
 	// For an interface value with the noAddr bit set,
 	// the representation is identical to an empty interface.
 	eface := *(*emptyInterface)(unsafe.Pointer(&i))
-	typ := toCommonType(eface.typ)
+	typ := eface.typ
 	fl := flag(typ.Kind()) << flagKindShift
 	if typ.size > ptrSize {
 		fl |= flagIndir
@@ -1713,10 +1990,11 @@ func ValueOf(i interface{}) Value {
 	return Value{typ, unsafe.Pointer(eface.word), fl}
 }
 
-// Zero returns a Value representing a zero value for the specified type.
+// Zero returns a Value representing the zero value for the specified type.
 // The result is different from the zero value of the Value struct,
 // which represents no value at all.
 // For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0.
+// The returned value is neither addressable nor settable.
 func Zero(typ Type) Value {
 	if typ == nil {
 		panic("reflect: Zero(nil)")
@@ -1726,7 +2004,7 @@ func Zero(typ Type) Value {
 	if t.size <= ptrSize {
 		return Value{t, nil, fl}
 	}
-	return Value{t, unsafe_New(typ), fl | flagIndir}
+	return Value{t, unsafe_New(typ.(*rtype)), fl | flagIndir}
 }
 
 // New returns a Value representing a pointer to a new zero value
@@ -1735,7 +2013,7 @@ func New(typ Type) Value {
 	if typ == nil {
 		panic("reflect: New(nil)")
 	}
-	ptr := unsafe_New(typ)
+	ptr := unsafe_New(typ.(*rtype))
 	fl := flag(Ptr) << flagKindShift
 	return Value{typ.common().ptrTo(), ptr, fl}
 }
@@ -1750,7 +2028,7 @@ func NewAt(typ Type, p unsafe.Pointer) Value {
 // 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 *commonType, target *interface{}) Value {
+func (v Value) assignTo(context string, dst *rtype, target *interface{}) Value {
 	if v.flag&flagMethod != 0 {
 		panic(context + ": cannot assign method value to type " + dst.String())
 	}
@@ -1772,7 +2050,7 @@ func (v Value) assignTo(context string, dst *commonType, target *interface{}) Va
 		if dst.NumMethod() == 0 {
 			*target = x
 		} else {
-			ifaceE2I(dst.runtimeType(), x, unsafe.Pointer(target))
+			ifaceE2I(dst, x, unsafe.Pointer(target))
 		}
 		return Value{dst, unsafe.Pointer(target), flagIndir | flag(Interface)<<flagKindShift}
 	}
@@ -1781,24 +2059,320 @@ func (v Value) assignTo(context string, dst *commonType, target *interface{}) Va
 	panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
 }
 
+// Convert returns the value v converted to type t.
+// If the usual Go conversion rules do not allow conversion
+// of the value v to type t, Convert panics.
+func (v Value) Convert(t Type) Value {
+	if v.flag&flagMethod != 0 {
+		panic("reflect.Value.Convert: cannot convert method values")
+	}
+	op := convertOp(t.common(), v.typ)
+	if op == nil {
+		panic("reflect.Value.Convert: value of type " + v.typ.String() + " cannot be converted to type " + t.String())
+	}
+	return op(v, t)
+}
+
+// convertOp returns the function to convert a value of type src
+// to a value of type dst. If the conversion is illegal, convertOp returns nil.
+func convertOp(dst, src *rtype) func(Value, Type) Value {
+	switch src.Kind() {
+	case Int, Int8, Int16, Int32, Int64:
+		switch dst.Kind() {
+		case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+			return cvtInt
+		case Float32, Float64:
+			return cvtIntFloat
+		case String:
+			return cvtIntString
+		}
+
+	case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+		switch dst.Kind() {
+		case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+			return cvtUint
+		case Float32, Float64:
+			return cvtUintFloat
+		case String:
+			return cvtUintString
+		}
+
+	case Float32, Float64:
+		switch dst.Kind() {
+		case Int, Int8, Int16, Int32, Int64:
+			return cvtFloatInt
+		case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+			return cvtFloatUint
+		case Float32, Float64:
+			return cvtFloat
+		}
+
+	case Complex64, Complex128:
+		switch dst.Kind() {
+		case Complex64, Complex128:
+			return cvtComplex
+		}
+
+	case String:
+		if dst.Kind() == Slice && dst.Elem().PkgPath() == "" {
+			switch dst.Elem().Kind() {
+			case Uint8:
+				return cvtStringBytes
+			case Int32:
+				return cvtStringRunes
+			}
+		}
+
+	case Slice:
+		if dst.Kind() == String && src.Elem().PkgPath() == "" {
+			switch src.Elem().Kind() {
+			case Uint8:
+				return cvtBytesString
+			case Int32:
+				return cvtRunesString
+			}
+		}
+	}
+
+	// dst and src have same underlying type.
+	if haveIdenticalUnderlyingType(dst, src) {
+		return cvtDirect
+	}
+
+	// dst and src are unnamed pointer types with same underlying base type.
+	if dst.Kind() == Ptr && dst.Name() == "" &&
+		src.Kind() == Ptr && src.Name() == "" &&
+		haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common()) {
+		return cvtDirect
+	}
+
+	if implements(dst, src) {
+		if src.Kind() == Interface {
+			return cvtI2I
+		}
+		return cvtT2I
+	}
+
+	return nil
+}
+
+// makeInt returns a Value of type t equal to bits (possibly truncated),
+// 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, f | flag(typ.Kind())<<flagKindShift}
+	}
+	var w iword
+	switch typ.size {
+	case 1:
+		*(*uint8)(unsafe.Pointer(&w)) = uint8(bits)
+	case 2:
+		*(*uint16)(unsafe.Pointer(&w)) = uint16(bits)
+	case 4:
+		*(*uint32)(unsafe.Pointer(&w)) = uint32(bits)
+	case 8:
+		*(*uint64)(unsafe.Pointer(&w)) = uint64(bits)
+	}
+	return Value{typ, unsafe.Pointer(w), f | flag(typ.Kind())<<flagKindShift}
+}
+
+// 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, f | flag(typ.Kind())<<flagKindShift}
+	}
+
+	var w iword
+	switch typ.size {
+	case 4:
+		*(*float32)(unsafe.Pointer(&w)) = float32(v)
+	case 8:
+		*(*float64)(unsafe.Pointer(&w)) = v
+	}
+	return Value{typ, unsafe.Pointer(w), f | flag(typ.Kind())<<flagKindShift}
+}
+
+// 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, f | flag(typ.Kind())<<flagKindShift}
+	}
+
+	// Assume ptrSize <= 8 so this must be complex64.
+	var w iword
+	*(*complex64)(unsafe.Pointer(&w)) = complex64(v)
+	return Value{typ, unsafe.Pointer(w), f | flag(typ.Kind())<<flagKindShift}
+}
+
+func makeString(f flag, v string, t Type) Value {
+	ret := New(t).Elem()
+	ret.SetString(v)
+	ret.flag = ret.flag&^flagAddr | f
+	return ret
+}
+
+func makeBytes(f flag, v []byte, t Type) Value {
+	ret := New(t).Elem()
+	ret.SetBytes(v)
+	ret.flag = ret.flag&^flagAddr | f
+	return ret
+}
+
+func makeRunes(f flag, v []rune, t Type) Value {
+	ret := New(t).Elem()
+	ret.setRunes(v)
+	ret.flag = ret.flag&^flagAddr | f
+	return ret
+}
+
+// These conversion functions are returned by convertOp
+// for classes of conversions. For example, the first function, cvtInt,
+// takes any value v of signed int type and returns the value converted
+// to type t, where t is any signed or unsigned int type.
+
+// convertOp: intXX -> [u]intXX
+func cvtInt(v Value, t Type) Value {
+	return makeInt(v.flag&flagRO, uint64(v.Int()), t)
+}
+
+// convertOp: uintXX -> [u]intXX
+func cvtUint(v Value, t Type) Value {
+	return makeInt(v.flag&flagRO, v.Uint(), t)
+}
+
+// convertOp: floatXX -> intXX
+func cvtFloatInt(v Value, t Type) Value {
+	return makeInt(v.flag&flagRO, uint64(int64(v.Float())), t)
+}
+
+// convertOp: floatXX -> uintXX
+func cvtFloatUint(v Value, t Type) Value {
+	return makeInt(v.flag&flagRO, uint64(v.Float()), t)
+}
+
+// convertOp: intXX -> floatXX
+func cvtIntFloat(v Value, t Type) Value {
+	return makeFloat(v.flag&flagRO, float64(v.Int()), t)
+}
+
+// convertOp: uintXX -> floatXX
+func cvtUintFloat(v Value, t Type) Value {
+	return makeFloat(v.flag&flagRO, float64(v.Uint()), t)
+}
+
+// convertOp: floatXX -> floatXX
+func cvtFloat(v Value, t Type) Value {
+	return makeFloat(v.flag&flagRO, v.Float(), t)
+}
+
+// convertOp: complexXX -> complexXX
+func cvtComplex(v Value, t Type) Value {
+	return makeComplex(v.flag&flagRO, v.Complex(), t)
+}
+
+// convertOp: intXX -> string
+func cvtIntString(v Value, t Type) Value {
+	return makeString(v.flag&flagRO, string(v.Int()), t)
+}
+
+// convertOp: uintXX -> string
+func cvtUintString(v Value, t Type) Value {
+	return makeString(v.flag&flagRO, string(v.Uint()), t)
+}
+
+// convertOp: []byte -> string
+func cvtBytesString(v Value, t Type) Value {
+	return makeString(v.flag&flagRO, string(v.Bytes()), t)
+}
+
+// convertOp: string -> []byte
+func cvtStringBytes(v Value, t Type) Value {
+	return makeBytes(v.flag&flagRO, []byte(v.String()), t)
+}
+
+// convertOp: []rune -> string
+func cvtRunesString(v Value, t Type) Value {
+	return makeString(v.flag&flagRO, string(v.runes()), t)
+}
+
+// convertOp: string -> []rune
+func cvtStringRunes(v Value, t Type) Value {
+	return makeRunes(v.flag&flagRO, []rune(v.String()), t)
+}
+
+// convertOp: direct copy
+func cvtDirect(v Value, typ Type) Value {
+	f := v.flag
+	t := typ.common()
+	val := v.val
+	if f&flagAddr != 0 {
+		// indirect, mutable word - make a copy
+		ptr := unsafe_New(t)
+		memmove(ptr, val, t.size)
+		val = ptr
+		f &^= flagAddr
+	}
+	return Value{t, val, v.flag&flagRO | f}
+}
+
+// convertOp: concrete -> interface
+func cvtT2I(v Value, typ Type) Value {
+	target := new(interface{})
+	x := valueInterface(v, false)
+	if typ.NumMethod() == 0 {
+		*target = x
+	} else {
+		ifaceE2I(typ.(*rtype), x, unsafe.Pointer(target))
+	}
+	return Value{typ.common(), unsafe.Pointer(target), v.flag&flagRO | flagIndir | flag(Interface)<<flagKindShift}
+}
+
+// convertOp: interface -> interface
+func cvtI2I(v Value, typ Type) Value {
+	if v.IsNil() {
+		ret := Zero(typ)
+		ret.flag |= v.flag & flagRO
+		return ret
+	}
+	return cvtT2I(v.Elem(), typ)
+}
+
 // implemented in ../pkg/runtime
-func chancap(ch iword) int32
+func chancap(ch iword) int
 func chanclose(ch iword)
-func chanlen(ch iword) int32
-func chanrecv(t *runtimeType, ch iword, nb bool) (val iword, selected, received bool)
-func chansend(t *runtimeType, ch iword, val iword, nb bool) bool
-
-func makechan(typ *runtimeType, size uint32) (ch iword)
-func makemap(t *runtimeType) (m iword)
-func mapaccess(t *runtimeType, m iword, key iword) (val iword, ok bool)
-func mapassign(t *runtimeType, m iword, key, val iword, ok bool)
-func mapiterinit(t *runtimeType, m iword) *byte
+func chanlen(ch iword) int
+func chanrecv(t *rtype, ch iword, nb bool) (val iword, selected, received bool)
+func chansend(t *rtype, ch iword, val iword, nb bool) bool
+
+func makechan(typ *rtype, size uint64) (ch iword)
+func makemap(t *rtype) (m iword)
+func mapaccess(t *rtype, m iword, key iword) (val iword, ok bool)
+func mapassign(t *rtype, m iword, key, val iword, ok bool)
+func mapiterinit(t *rtype, m iword) *byte
 func mapiterkey(it *byte) (key iword, ok bool)
 func mapiternext(it *byte)
-func maplen(m iword) int32
+func maplen(m iword) int
 
 func call(fn, arg unsafe.Pointer, n uint32)
-func ifaceE2I(t *runtimeType, src interface{}, dst unsafe.Pointer)
+func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
 
 // Dummy annotation marking that the value x escapes,
 // for use in cases where the reflect code is so clever that
diff --git a/src/pkg/regexp/all_test.go b/src/pkg/regexp/all_test.go
index f7b41a6..9c4d64f 100644
--- a/src/pkg/regexp/all_test.go
+++ b/src/pkg/regexp/all_test.go
@@ -5,6 +5,7 @@
 package regexp
 
 import (
+	"reflect"
 	"strings"
 	"testing"
 )
@@ -29,53 +30,52 @@ var good_re = []string{
 	`\!\\`,
 }
 
-/*
 type stringError struct {
 	re  string
-	err error
+	err string
 }
 
 var bad_re = []stringError{
-	{`*`, ErrBareClosure},
-	{`+`, ErrBareClosure},
-	{`?`, ErrBareClosure},
-	{`(abc`, ErrUnmatchedLpar},
-	{`abc)`, ErrUnmatchedRpar},
-	{`x[a-z`, ErrUnmatchedLbkt},
-	{`abc]`, ErrUnmatchedRbkt},
-	{`[z-a]`, ErrBadRange},
-	{`abc\`, ErrExtraneousBackslash},
-	{`a**`, ErrBadClosure},
-	{`a*+`, ErrBadClosure},
-	{`a??`, ErrBadClosure},
-	{`\x`, ErrBadBackslash},
-}
-*/
-
-func compileTest(t *testing.T, expr string, error error) *Regexp {
+	{`*`, "missing argument to repetition operator: `*`"},
+	{`+`, "missing argument to repetition operator: `+`"},
+	{`?`, "missing argument to repetition operator: `?`"},
+	{`(abc`, "missing closing ): `(abc`"},
+	{`abc)`, "unexpected ): `abc)`"},
+	{`x[a-z`, "missing closing ]: `[a-z`"},
+	{`[z-a]`, "invalid character class range: `z-a`"},
+	{`abc\`, "trailing backslash at end of expression"},
+	{`a**`, "invalid nested repetition operator: `**`"},
+	{`a*+`, "invalid nested repetition operator: `*+`"},
+	{`\x`, "invalid escape sequence: `\\x`"},
+}
+
+func compileTest(t *testing.T, expr string, error string) *Regexp {
 	re, err := Compile(expr)
-	if err != error {
+	if error == "" && err != nil {
 		t.Error("compiling `", expr, "`; unexpected error: ", err.Error())
 	}
+	if error != "" && err == nil {
+		t.Error("compiling `", expr, "`; missing error")
+	} else if error != "" && !strings.Contains(err.Error(), error) {
+		t.Error("compiling `", expr, "`; wrong error: ", err.Error(), "; want ", error)
+	}
 	return re
 }
 
 func TestGoodCompile(t *testing.T) {
 	for i := 0; i < len(good_re); i++ {
-		compileTest(t, good_re[i], nil)
+		compileTest(t, good_re[i], "")
 	}
 }
 
-/*
 func TestBadCompile(t *testing.T) {
 	for i := 0; i < len(bad_re); i++ {
 		compileTest(t, bad_re[i].re, bad_re[i].err)
 	}
 }
-*/
 
 func matchTest(t *testing.T, test *FindTest) {
-	re := compileTest(t, test.pat, nil)
+	re := compileTest(t, test.pat, "")
 	if re == nil {
 		return
 	}
@@ -196,6 +196,10 @@ var replaceTests = []ReplaceTest{
 	{"a+", "${oops", "aaa", "${oops"},
 	{"a+", "$$", "aaa", "$"},
 	{"a+", "$", "aaa", "$"},
+
+	// Substitution when subexpression isn't found
+	{"(x)?", "$1", "123", "123"},
+	{"abc", "$1", "123", "123"},
 }
 
 var replaceLiteralTests = []ReplaceTest{
@@ -416,6 +420,59 @@ func TestSubexp(t *testing.T) {
 	}
 }
 
+var splitTests = []struct {
+	s   string
+	r   string
+	n   int
+	out []string
+}{
+	{"foo:and:bar", ":", -1, []string{"foo", "and", "bar"}},
+	{"foo:and:bar", ":", 1, []string{"foo:and:bar"}},
+	{"foo:and:bar", ":", 2, []string{"foo", "and:bar"}},
+	{"foo:and:bar", "foo", -1, []string{"", ":and:bar"}},
+	{"foo:and:bar", "bar", -1, []string{"foo:and:", ""}},
+	{"foo:and:bar", "baz", -1, []string{"foo:and:bar"}},
+	{"baabaab", "a", -1, []string{"b", "", "b", "", "b"}},
+	{"baabaab", "a*", -1, []string{"b", "b", "b"}},
+	{"baabaab", "ba*", -1, []string{"", "", "", ""}},
+	{"foobar", "f*b*", -1, []string{"", "o", "o", "a", "r"}},
+	{"foobar", "f+.*b+", -1, []string{"", "ar"}},
+	{"foobooboar", "o{2}", -1, []string{"f", "b", "boar"}},
+	{"a,b,c,d,e,f", ",", 3, []string{"a", "b", "c,d,e,f"}},
+	{"a,b,c,d,e,f", ",", 0, nil},
+	{",", ",", -1, []string{"", ""}},
+	{",,,", ",", -1, []string{"", "", "", ""}},
+	{"", ",", -1, []string{""}},
+	{"", ".*", -1, []string{""}},
+	{"", ".+", -1, []string{""}},
+	{"", "", -1, []string{}},
+	{"foobar", "", -1, []string{"f", "o", "o", "b", "a", "r"}},
+	{"abaabaccadaaae", "a*", 5, []string{"", "b", "b", "c", "cadaaae"}},
+	{":x:y:z:", ":", -1, []string{"", "x", "y", "z", ""}},
+}
+
+func TestSplit(t *testing.T) {
+	for i, test := range splitTests {
+		re, err := Compile(test.r)
+		if err != nil {
+			t.Errorf("#%d: %q: compile error: %s", i, test.r, err.Error())
+			continue
+		}
+
+		split := re.Split(test.s, test.n)
+		if !reflect.DeepEqual(split, test.out) {
+			t.Errorf("#%d: %q: got %q; want %q", i, test.r, split, test.out)
+		}
+
+		if QuoteMeta(test.r) == test.r {
+			strsplit := strings.SplitN(test.s, test.r, test.n)
+			if !reflect.DeepEqual(split, strsplit) {
+				t.Errorf("#%d: Split(%q, %q, %d): regexp vs strings mismatch\nregexp=%q\nstrings=%q", i, test.s, test.r, test.n, split, strsplit)
+			}
+		}
+	}
+}
+
 func BenchmarkLiteral(b *testing.B) {
 	x := strings.Repeat("x", 50) + "y"
 	b.StopTimer()
diff --git a/src/pkg/regexp/example_test.go b/src/pkg/regexp/example_test.go
new file mode 100644
index 0000000..b0ad9d3
--- /dev/null
+++ b/src/pkg/regexp/example_test.go
@@ -0,0 +1,144 @@
+package regexp_test
+
+import (
+	"fmt"
+	"regexp"
+)
+
+func Example() {
+	// Compile the expression once, usually at init time.
+	// Use raw strings to avoid having to quote the backslashes.
+	var validID = regexp.MustCompile(`^[a-z]+\[[0-9]+\]$`)
+
+	fmt.Println(validID.MatchString("adam[23]"))
+	fmt.Println(validID.MatchString("eve[7]"))
+	fmt.Println(validID.MatchString("Job[48]"))
+	fmt.Println(validID.MatchString("snakey"))
+	// Output:
+	// true
+	// true
+	// false
+	// false
+}
+
+func ExampleMatchString() {
+	matched, err := regexp.MatchString("foo.*", "seafood")
+	fmt.Println(matched, err)
+	matched, err = regexp.MatchString("bar.*", "seafood")
+	fmt.Println(matched, err)
+	matched, err = regexp.MatchString("a(b", "seafood")
+	fmt.Println(matched, err)
+	// Output:
+	// true <nil>
+	// false <nil>
+	// false error parsing regexp: missing closing ): `a(b`
+}
+
+func ExampleRegexp_FindString() {
+	re := regexp.MustCompile("fo.?")
+	fmt.Printf("%q\n", re.FindString("seafood"))
+	fmt.Printf("%q\n", re.FindString("meat"))
+	// Output:
+	// "foo"
+	// ""
+}
+
+func ExampleRegexp_FindStringIndex() {
+	re := regexp.MustCompile("ab?")
+	fmt.Println(re.FindStringIndex("tablett"))
+	fmt.Println(re.FindStringIndex("foo") == nil)
+	// Output:
+	// [1 3]
+	// true
+}
+
+func ExampleRegexp_FindStringSubmatch() {
+	re := regexp.MustCompile("a(x*)b(y|z)c")
+	fmt.Printf("%q\n", re.FindStringSubmatch("-axxxbyc-"))
+	fmt.Printf("%q\n", re.FindStringSubmatch("-abzc-"))
+	// Output:
+	// ["axxxbyc" "xxx" "y"]
+	// ["abzc" "" "z"]
+}
+
+func ExampleRegexp_FindAllString() {
+	re := regexp.MustCompile("a.")
+	fmt.Println(re.FindAllString("paranormal", -1))
+	fmt.Println(re.FindAllString("paranormal", 2))
+	fmt.Println(re.FindAllString("graal", -1))
+	fmt.Println(re.FindAllString("none", -1))
+	// Output:
+	// [ar an al]
+	// [ar an]
+	// [aa]
+	// []
+}
+
+func ExampleRegexp_FindAllStringSubmatch() {
+	re := regexp.MustCompile("a(x*)b")
+	fmt.Printf("%q\n", re.FindAllStringSubmatch("-ab-", -1))
+	fmt.Printf("%q\n", re.FindAllStringSubmatch("-axxb-", -1))
+	fmt.Printf("%q\n", re.FindAllStringSubmatch("-ab-axb-", -1))
+	fmt.Printf("%q\n", re.FindAllStringSubmatch("-axxb-ab-", -1))
+	// Output:
+	// [["ab" ""]]
+	// [["axxb" "xx"]]
+	// [["ab" ""] ["axb" "x"]]
+	// [["axxb" "xx"] ["ab" ""]]
+}
+
+func ExampleRegexp_FindAllStringSubmatchIndex() {
+	re := regexp.MustCompile("a(x*)b")
+	// Indices:
+	//    01234567   012345678
+	//    -ab-axb-   -axxb-ab-
+	fmt.Println(re.FindAllStringSubmatchIndex("-ab-", -1))
+	fmt.Println(re.FindAllStringSubmatchIndex("-axxb-", -1))
+	fmt.Println(re.FindAllStringSubmatchIndex("-ab-axb-", -1))
+	fmt.Println(re.FindAllStringSubmatchIndex("-axxb-ab-", -1))
+	fmt.Println(re.FindAllStringSubmatchIndex("-foo-", -1))
+	// Output:
+	// [[1 3 2 2]]
+	// [[1 5 2 4]]
+	// [[1 3 2 2] [4 7 5 6]]
+	// [[1 5 2 4] [6 8 7 7]]
+	// []
+}
+
+func ExampleRegexp_ReplaceAllLiteralString() {
+	re := regexp.MustCompile("a(x*)b")
+	fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-", "T"))
+	fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-", "$1"))
+	fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-", "${1}"))
+	// Output:
+	// -T-T-
+	// -$1-$1-
+	// -${1}-${1}-
+}
+
+func ExampleRegexp_ReplaceAllString() {
+	re := regexp.MustCompile("a(x*)b")
+	fmt.Println(re.ReplaceAllString("-ab-axxb-", "T"))
+	fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1"))
+	fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1W"))
+	fmt.Println(re.ReplaceAllString("-ab-axxb-", "${1}W"))
+	// Output:
+	// -T-T-
+	// --xx-
+	// ---
+	// -W-xxW-
+}
+
+func ExampleRegexp_SubexpNames() {
+	re := regexp.MustCompile("(?P<first>[a-zA-Z]+) (?P<last>[a-zA-Z]+)")
+	fmt.Println(re.MatchString("Alan Turing"))
+	fmt.Printf("%q\n", re.SubexpNames())
+	reversed := fmt.Sprintf("${%s} ${%s}", re.SubexpNames()[2], re.SubexpNames()[1])
+	fmt.Println(reversed)
+	fmt.Println(re.ReplaceAllString("Alan Turing", reversed))
+	// Output:
+	// true
+	// ["" "first" "last"]
+	// ${last} ${first}
+	// Turing Alan
+}
diff --git a/src/pkg/regexp/exec_test.go b/src/pkg/regexp/exec_test.go
index e668574..9dfaed7 100644
--- a/src/pkg/regexp/exec_test.go
+++ b/src/pkg/regexp/exec_test.go
@@ -69,8 +69,7 @@ func TestRE2Search(t *testing.T) {
 
 func TestRE2Exhaustive(t *testing.T) {
 	if testing.Short() {
-		t.Log("skipping TestRE2Exhaustive during short test")
-		return
+		t.Skip("skipping TestRE2Exhaustive during short test")
 	}
 	testRE2(t, "testdata/re2-exhaustive.txt.bz2")
 }
@@ -90,7 +89,7 @@ func testRE2(t *testing.T, file string) {
 		txt = f
 	}
 	lineno := 0
-	r := bufio.NewReader(txt)
+	scanner := bufio.NewScanner(txt)
 	var (
 		str       []string
 		input     []string
@@ -100,16 +99,8 @@ func testRE2(t *testing.T, file string) {
 		nfail     int
 		ncase     int
 	)
-	for {
-		line, err := r.ReadString('\n')
-		if err != nil {
-			if err == io.EOF {
-				break
-			}
-			t.Fatalf("%s:%d: %v", file, lineno, err)
-		}
-		line = line[:len(line)-1] // chop \n
-		lineno++
+	for lineno := 1; scanner.Scan(); lineno++ {
+		line := scanner.Text()
 		switch {
 		case line == "":
 			t.Fatalf("%s:%d: unexpected blank line", file, lineno)
@@ -205,6 +196,9 @@ func testRE2(t *testing.T, file string) {
 			t.Fatalf("%s:%d: out of sync: %s\n", file, lineno, line)
 		}
 	}
+	if err := scanner.Err(); err != nil {
+		t.Fatalf("%s:%d: %v", file, lineno, err)
+	}
 	if len(input) != 0 {
 		t.Fatalf("%s:%d: out of sync: have %d strings left at EOF", file, lineno, len(input))
 	}
@@ -405,14 +399,14 @@ Reading:
 		//   implementation. If the first character is not [BEASKLP] then the
 		//   specification is a global control line. One or more of [BEASKLP] may be
 		//   specified; the test will be repeated for each mode.
-		// 
+		//
 		//     B 	basic			BRE	(grep, ed, sed)
 		//     E 	REG_EXTENDED		ERE	(egrep)
 		//     A	REG_AUGMENTED		ARE	(egrep with negation)
 		//     S	REG_SHELL		SRE	(sh glob)
 		//     K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)
 		//     L	REG_LITERAL		LRE	(fgrep)
-		// 
+		//
 		//     a	REG_LEFT|REG_RIGHT	implicit ^...$
 		//     b	REG_NOTBOL		lhs does not match ^
 		//     c	REG_COMMENT		ignore space and #...\n
@@ -442,23 +436,23 @@ Reading:
 		//     $	                        expand C \c escapes in fields 2 and 3
 		//     /	                        field 2 is a regsubcomp() expression
 		//     =	                        field 3 is a regdecomp() expression
-		// 
+		//
 		//   Field 1 control lines:
-		// 
+		//
 		//     C		set LC_COLLATE and LC_CTYPE to locale in field 2
-		// 
+		//
 		//     ?test ...	output field 5 if passed and != EXPECTED, silent otherwise
 		//     &test ...	output field 5 if current and previous passed
 		//     |test ...	output field 5 if current passed and previous failed
 		//     ; ...	output field 2 if previous failed
 		//     {test ...	skip if failed until }
 		//     }		end of skip
-		// 
+		//
 		//     : comment		comment copied as output NOTE
 		//     :comment:test	:comment: ignored
 		//     N[OTE] comment	comment copied as output NOTE
 		//     T[EST] comment	comment
-		// 
+		//
 		//     number		use number for nmatch (20 by default)
 		flag := field[0]
 		switch flag[0] {
@@ -501,7 +495,7 @@ Reading:
 
 		//   Field 2: the regular expression pattern; SAME uses the pattern from
 		//     the previous specification.
-		// 
+		//
 		if field[1] == "SAME" {
 			field[1] = lastRegexp
 		}
@@ -707,3 +701,17 @@ func BenchmarkMatchHard_1K(b *testing.B)    { benchmark(b, hard, 1<<10) }
 func BenchmarkMatchHard_32K(b *testing.B)   { benchmark(b, hard, 32<<10) }
 func BenchmarkMatchHard_1M(b *testing.B)    { benchmark(b, hard, 1<<20) }
 func BenchmarkMatchHard_32M(b *testing.B)   { benchmark(b, hard, 32<<20) }
+
+func TestLongest(t *testing.T) {
+	re, err := Compile(`a(|b)`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, w := re.FindString("ab"), "a"; g != w {
+		t.Errorf("first match was %q, want %q", g, w)
+	}
+	re.Longest()
+	if g, w := re.FindString("ab"), "ab"; g != w {
+		t.Errorf("longest match was %q, want %q", g, w)
+	}
+}
diff --git a/src/pkg/regexp/regexp.go b/src/pkg/regexp/regexp.go
index 87e6b1c..3aa16de 100644
--- a/src/pkg/regexp/regexp.go
+++ b/src/pkg/regexp/regexp.go
@@ -130,6 +130,14 @@ func CompilePOSIX(expr string) (*Regexp, error) {
 	return compile(expr, syntax.POSIX, true)
 }
 
+// Longest makes future searches prefer the leftmost-longest match.
+// That is, when matching against text, the regexp returns a match that
+// begins as early as possible in the input (leftmost), and among those
+// it chooses a match that is as long as possible.
+func (re *Regexp) Longest() {
+	re.longest = true
+}
+
 func compile(expr string, mode syntax.Flags, longest bool) (*Regexp, error) {
 	re, err := syntax.Parse(expr, mode)
 	if err != nil {
@@ -441,7 +449,7 @@ func (re *Regexp) ReplaceAllLiteralString(src, repl string) string {
 }
 
 // ReplaceAllStringFunc returns a copy of src in which all matches of the
-// Regexp have been replaced by the return value of of function repl applied
+// Regexp have been replaced by the return value of function repl applied
 // to the matched substring.  The replacement returned by repl is substituted
 // directly, without using Expand.
 func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
@@ -539,7 +547,7 @@ func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte {
 }
 
 // ReplaceAllFunc returns a copy of src in which all matches of the
-// Regexp have been replaced by the return value of of function repl applied
+// Regexp have been replaced by the return value of function repl applied
 // to the matched byte slice.  The replacement returned by repl is substituted
 // directly, without using Expand.
 func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
@@ -686,8 +694,9 @@ func (re *Regexp) FindStringIndex(s string) (loc []int) {
 
 // FindReaderIndex returns a two-element slice of integers defining the
 // location of the leftmost match of the regular expression in text read from
-// the RuneReader.  The match itself is at s[loc[0]:loc[1]].  A return
-// value of nil indicates no match.
+// the RuneReader.  The match text was found in the input stream at
+// byte offset loc[0] through loc[1]-1.
+// A return value of nil indicates no match.
 func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) {
 	a := re.doExecute(r, nil, "", 0, 2)
 	if a == nil {
@@ -719,7 +728,7 @@ func (re *Regexp) FindSubmatch(b []byte) [][]byte {
 // append, Expand replaces variables in the template with corresponding
 // matches drawn from src.  The match slice should have been returned by
 // FindSubmatchIndex.
-// 
+//
 // In the template, a variable is denoted by a substring of the form
 // $name or ${name}, where name is a non-empty sequence of letters,
 // digits, and underscores.  A purely numeric name like $1 refers to
@@ -727,10 +736,10 @@ func (re *Regexp) FindSubmatch(b []byte) [][]byte {
 // capturing parentheses named with the (?P<name>...) syntax.  A
 // reference to an out of range or unmatched index or a name that is not
 // present in the regular expression is replaced with an empty slice.
-// 
+//
 // In the $name form, name is taken to be as long as possible: $1x is
 // equivalent to ${1x}, not ${1}x, and, $10 is equivalent to ${10}, not ${1}0.
-// 
+//
 // To insert a literal $ in the output, use $$ in the template.
 func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte {
 	return re.expand(dst, string(template), src, "", match)
@@ -766,7 +775,7 @@ func (re *Regexp) expand(dst []byte, template string, bsrc []byte, src string, m
 		}
 		template = rest
 		if num >= 0 {
-			if 2*num+1 < len(match) {
+			if 2*num+1 < len(match) && match[2*num] >= 0 {
 				if bsrc != nil {
 					dst = append(dst, bsrc[match[2*num]:match[2*num+1]]...)
 				} else {
@@ -1047,3 +1056,52 @@ func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int {
 	}
 	return result
 }
+
+// Split slices s into substrings separated by the expression and returns a slice of
+// the substrings between those expression matches.
+//
+// The slice returned by this method consists of all the substrings of s
+// not contained in the slice returned by FindAllString. When called on an expression
+// that contains no metacharacters, it is equivalent to strings.SplitN.
+//
+// Example:
+//   s := regexp.MustCompile("a*").Split("abaabaccadaaae", 5)
+//   // s: ["", "b", "b", "c", "cadaaae"]
+//
+// The count determines the number of substrings to return:
+//   n > 0: at most n substrings; the last substring will be the unsplit remainder.
+//   n == 0: the result is nil (zero substrings)
+//   n < 0: all substrings
+func (re *Regexp) Split(s string, n int) []string {
+
+	if n == 0 {
+		return nil
+	}
+
+	if len(re.expr) > 0 && len(s) == 0 {
+		return []string{""}
+	}
+
+	matches := re.FindAllStringIndex(s, n)
+	strings := make([]string, 0, len(matches))
+
+	beg := 0
+	end := 0
+	for _, match := range matches {
+		if n > 0 && len(strings) >= n-1 {
+			break
+		}
+
+		end = match[0]
+		if match[1] != 0 {
+			strings = append(strings, s[beg:end])
+		}
+		beg = match[1]
+	}
+
+	if end != len(s) {
+		strings = append(strings, s[beg:])
+	}
+
+	return strings
+}
diff --git a/src/pkg/regexp/syntax/compile.go b/src/pkg/regexp/syntax/compile.go
index 41955bf..95f6f15 100644
--- a/src/pkg/regexp/syntax/compile.go
+++ b/src/pkg/regexp/syntax/compile.go
@@ -10,10 +10,10 @@ import "unicode"
 // Because the pointers haven't been filled in yet, we can reuse their storage
 // to hold the list.  It's kind of sleazy, but works well in practice.
 // See http://swtch.com/~rsc/regexp/regexp1.html for inspiration.
-// 
+//
 // These aren't really pointers: they're integers, so we can reinterpret them
 // this way without using package unsafe.  A value l denotes
-// p.inst[l>>1].Out (l&1==0) or .Arg (l&1==1). 
+// p.inst[l>>1].Out (l&1==0) or .Arg (l&1==1).
 // l == 0 denotes the empty list, okay because we start every program
 // with a fail instruction, so we'll never want to point at its output link.
 type patchList uint32
diff --git a/src/pkg/regexp/syntax/doc.go b/src/pkg/regexp/syntax/doc.go
new file mode 100644
index 0000000..843a6f6
--- /dev/null
+++ b/src/pkg/regexp/syntax/doc.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.
+
+// DO NOT EDIT. This file is generated by mksyntaxgo from the RE2 distribution.
+
+/*
+Package syntax parses regular expressions into parse trees and compiles
+parse trees into programs. Most clients of regular expressions will use the
+facilities of package regexp (such as Compile and Match) instead of this package.
+
+Syntax
+
+The regular expression syntax understood by this package when parsing with the Perl flag is as follows.
+Parts of the syntax can be disabled by passing alternate flags to Parse.
+
+
+Single characters:
+  .              any character, possibly including newline (flag s=true)
+  [xyz]          character class
+  [^xyz]         negated character class
+  \d             Perl character class
+  \D             negated Perl 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)
+  \P{Greek}      negated Unicode character class
+
+Composites:
+  xy             x followed by y
+  x|y            x or y (prefer x)
+
+Repetitions:
+  x*             zero or more x, prefer more
+  x+             one or more x, prefer more
+  x?             zero or one x, prefer one
+  x{n,m}         n or n+1 or ... or m x, prefer more
+  x{n,}          n or more x, prefer more
+  x{n}           exactly n x
+  x*?            zero or more x, prefer fewer
+  x+?            one or more x, prefer fewer
+  x??            zero or one x, prefer zero
+  x{n,m}?        n or n+1 or ... or m x, prefer fewer
+  x{n,}?         n or more x, prefer fewer
+  x{n}?          exactly n x
+
+Grouping:
+  (re)           numbered capturing group
+  (?P<name>re)   named & numbered capturing group
+  (?:re)         non-capturing group
+  (?flags)       set flags within current group; non-capturing
+  (?flags:re)    set flags during re; non-capturing
+
+  Flag syntax is xyz (set) or -xyz (clear) or xy-z (set xy, clear z). The flags are:
+
+  i              case-insensitive (default false)
+  m              multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false)
+  s              let . match \n (default false)
+  U              ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false)
+
+Empty strings:
+  ^              at beginning of text or line (flag m=true)
+  $              at end of text (like \z not \Z) or line (flag m=true)
+  \A             at beginning of text
+  \b             at word boundary (\w on one side and \W, \A, or \z on the other)
+  \B             not a word boundary
+  \z             at end of text
+
+Escape sequences:
+  \a             bell (== \007)
+  \f             form feed (== \014)
+  \t             horizontal tab (== \011)
+  \n             newline (== \012)
+  \r             carriage return (== \015)
+  \v             vertical tab character (== \013)
+  \*             literal *, for any punctuation character *
+  \123           octal character code (up to three digits)
+  \x7F           hex character code (exactly two digits)
+  \x{10FFFF}     hex character code
+  \Q...\E        literal text ... even if ... has punctuation
+
+Character class elements:
+  x              single character
+  A-Z            character range (inclusive)
+  \d             Perl character class
+  [:foo:]        ASCII character class foo
+  \p{Foo}        Unicode character class Foo
+  \pF            Unicode character class F (one-letter name)
+
+Named character classes as character class elements:
+  [\d]           digits (== \d)
+  [^\d]          not digits (== \D)
+  [\D]           not digits (== \D)
+  [^\D]          not not digits (== \d)
+  [[:name:]]     named ASCII class inside character class (== [:name:])
+  [^[:name:]]    named ASCII class inside negated character class (== [:^name:])
+  [\p{Name}]     named Unicode property inside character class (== \p{Name})
+  [^\p{Name}]    named Unicode property inside negated character class (== \P{Name})
+
+Perl character classes:
+  \d             digits (== [0-9])
+  \D             not digits (== [^0-9])
+  \s             whitespace (== [\t\n\f\r ])
+  \S             not whitespace (== [^\t\n\f\r ])
+  \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])
+
+*/
+package syntax
diff --git a/src/pkg/regexp/syntax/parse.go b/src/pkg/regexp/syntax/parse.go
index 4924e94..30e0e8b 100644
--- a/src/pkg/regexp/syntax/parse.go
+++ b/src/pkg/regexp/syntax/parse.go
@@ -2,10 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package syntax parses regular expressions into parse trees and compiles
-// parse trees into programs. Most clients of regular expressions will use
-// the facilities of package regexp (such as Compile and Match) instead of
-// this package.
 package syntax
 
 import (
@@ -46,11 +42,9 @@ const (
 	ErrMissingParen          ErrorCode = "missing closing )"
 	ErrMissingRepeatArgument ErrorCode = "missing argument to repetition operator"
 	ErrTrailingBackslash     ErrorCode = "trailing backslash at end of expression"
+	ErrUnexpectedParen       ErrorCode = "unexpected )"
 )
 
-// TODO: Export for Go 1.1.
-const errUnexpectedParen ErrorCode = "unexpected )"
-
 func (e ErrorCode) String() string {
 	return string(e)
 }
@@ -470,7 +464,7 @@ func (p *parser) factor(sub []*Regexp, flags Flags) []*Regexp {
 			// Construct factored form: prefix(suffix1|suffix2|...)
 			prefix := first
 			for j := start; j < i; j++ {
-				reuse := j != start // prefix came from sub[start] 
+				reuse := j != start // prefix came from sub[start]
 				sub[j] = p.removeLeadingRegexp(sub[j], reuse)
 			}
 			suffix := p.collapse(sub[start:i], OpAlternate) // recurse
@@ -1171,13 +1165,13 @@ func (p *parser) parseRightParen() error {
 
 	n := len(p.stack)
 	if n < 2 {
-		return &Error{errUnexpectedParen, p.wholeRegexp}
+		return &Error{ErrUnexpectedParen, p.wholeRegexp}
 	}
 	re1 := p.stack[n-1]
 	re2 := p.stack[n-2]
 	p.stack = p.stack[:n-2]
 	if re2.Op != opLeftParen {
-		return &Error{errUnexpectedParen, p.wholeRegexp}
+		return &Error{ErrUnexpectedParen, p.wholeRegexp}
 	}
 	// Restore flags at time of paren.
 	p.flags = re2.Flags
diff --git a/src/pkg/runtime/alg.c b/src/pkg/runtime/alg.c
index 36973eb..ad85b43 100644
--- a/src/pkg/runtime/alg.c
+++ b/src/pkg/runtime/alg.c
@@ -19,13 +19,13 @@ runtime·memhash(uintptr *h, uintptr s, void *a)
 	uintptr hash;
 
 	b = a;
-	hash = M0;
+	hash = M0 ^ *h;
 	while(s > 0) {
 		hash = (hash ^ *b) * M1;
 		b++;
 		s--;
 	}
-	*h = (*h ^ hash) * M1;
+	*h = hash;
 }
 
 void
@@ -316,7 +316,7 @@ runtime·strhash(uintptr *h, uintptr s, void *a)
 void
 runtime·strequal(bool *eq, uintptr s, void *a, void *b)
 {
-	int32 alen;
+	intgo alen;
 
 	USED(s);
 	alen = ((String*)a)->len;
@@ -324,6 +324,10 @@ runtime·strequal(bool *eq, uintptr s, void *a, void *b)
 		*eq = false;
 		return;
 	}
+	if(((String*)a)->str == ((String*)b)->str) {
+		*eq = true;
+		return;
+	}
 	runtime·memequal(eq, alen, ((String*)a)->str, ((String*)b)->str);
 }
 
@@ -351,7 +355,7 @@ void
 runtime·interhash(uintptr *h, uintptr s, void *a)
 {
 	USED(s);
-	*h = (*h ^ runtime·ifacehash(*(Iface*)a)) * M1;
+	*h = runtime·ifacehash(*(Iface*)a, *h ^ M0) * M1;
 }
 
 void
@@ -385,7 +389,7 @@ void
 runtime·nilinterhash(uintptr *h, uintptr s, void *a)
 {
 	USED(s);
-	*h = (*h ^ runtime·efacehash(*(Eface*)a)) * M1;
+	*h = runtime·efacehash(*(Eface*)a, *h ^ M0) * M1;
 }
 
 void
@@ -469,10 +473,11 @@ void
 runtime·equal(Type *t, ...)
 {
 	byte *x, *y;
-	bool *ret;
+	uintptr ret;
 	
 	x = (byte*)(&t+1);
 	y = x + t->size;
-	ret = (bool*)(y + t->size);
-	t->alg->equal(ret, t->size, x, y);
+	ret = (uintptr)(y + t->size);
+	ret = ROUND(ret, Structrnd);
+	t->alg->equal((bool*)ret, t->size, x, y);
 }
diff --git a/src/pkg/runtime/append_test.go b/src/pkg/runtime/append_test.go
index b855222..3639018 100644
--- a/src/pkg/runtime/append_test.go
+++ b/src/pkg/runtime/append_test.go
@@ -19,6 +19,67 @@ func BenchmarkAppend(b *testing.B) {
 	}
 }
 
+func benchmarkAppendBytes(b *testing.B, length int) {
+	b.StopTimer()
+	x := make([]byte, 0, N)
+	y := make([]byte, length)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		x = x[0:0]
+		x = append(x, y...)
+	}
+}
+
+func BenchmarkAppend1Byte(b *testing.B) {
+	benchmarkAppendBytes(b, 1)
+}
+
+func BenchmarkAppend4Bytes(b *testing.B) {
+	benchmarkAppendBytes(b, 4)
+}
+
+func BenchmarkAppend8Bytes(b *testing.B) {
+	benchmarkAppendBytes(b, 8)
+}
+
+func BenchmarkAppend16Bytes(b *testing.B) {
+	benchmarkAppendBytes(b, 16)
+}
+
+func BenchmarkAppend32Bytes(b *testing.B) {
+	benchmarkAppendBytes(b, 32)
+}
+
+func benchmarkAppendStr(b *testing.B, str string) {
+	b.StopTimer()
+	x := make([]byte, 0, N)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		x = x[0:0]
+		x = append(x, str...)
+	}
+}
+
+func BenchmarkAppendStr1Byte(b *testing.B) {
+	benchmarkAppendStr(b, "1")
+}
+
+func BenchmarkAppendStr4Bytes(b *testing.B) {
+	benchmarkAppendStr(b, "1234")
+}
+
+func BenchmarkAppendStr8Bytes(b *testing.B) {
+	benchmarkAppendStr(b, "12345678")
+}
+
+func BenchmarkAppendStr16Bytes(b *testing.B) {
+	benchmarkAppendStr(b, "1234567890123456")
+}
+
+func BenchmarkAppendStr32Bytes(b *testing.B) {
+	benchmarkAppendStr(b, "12345678901234567890123456789012")
+}
+
 func BenchmarkAppendSpecialCase(b *testing.B) {
 	b.StopTimer()
 	x := make([]int, 0, N)
@@ -50,3 +111,13 @@ func TestSideEffectOrder(t *testing.T) {
 		t.Error("append failed: ", x[0], x[1])
 	}
 }
+
+func TestAppendOverlap(t *testing.T) {
+	x := []byte("1234")
+	x = append(x[1:], x...) // p > q in runtime·appendslice.
+	got := string(x)
+	want := "2341234"
+	if got != want {
+		t.Errorf("overlap failed: got %q want %q", got, want)
+	}
+}
diff --git a/src/pkg/runtime/arch_386.h b/src/pkg/runtime/arch_386.h
index a0798f9..4df795f 100644
--- a/src/pkg/runtime/arch_386.h
+++ b/src/pkg/runtime/arch_386.h
@@ -1,4 +1,6 @@
 enum {
 	thechar = '8',
-	CacheLineSize = 64
+	BigEndian = 0,
+	CacheLineSize = 64,
+	appendCrossover = 16
 };
diff --git a/src/pkg/runtime/arch_amd64.h b/src/pkg/runtime/arch_amd64.h
index dd1cfc1..e83dc91 100644
--- a/src/pkg/runtime/arch_amd64.h
+++ b/src/pkg/runtime/arch_amd64.h
@@ -1,4 +1,6 @@
 enum {
 	thechar = '6',
-	CacheLineSize = 64
+	BigEndian = 0,
+	CacheLineSize = 64,
+	appendCrossover = 16
 };
diff --git a/src/pkg/runtime/arch_arm.h b/src/pkg/runtime/arch_arm.h
index c1a7a0f..f6af585 100644
--- a/src/pkg/runtime/arch_arm.h
+++ b/src/pkg/runtime/arch_arm.h
@@ -1,4 +1,6 @@
 enum {
 	thechar = '5',
-	CacheLineSize = 32
+	BigEndian = 0,
+	CacheLineSize = 32,
+	appendCrossover = 16
 };
diff --git a/src/pkg/runtime/asm_386.s b/src/pkg/runtime/asm_386.s
index 21bd293..96f04e0 100644
--- a/src/pkg/runtime/asm_386.s
+++ b/src/pkg/runtime/asm_386.s
@@ -14,22 +14,22 @@ TEXT _rt0_386(SB),7,$0
 	MOVL	BX, 124(SP)
 
 	// set default stack bounds.
-	// initcgo may update stackguard.
+	// _cgo_init may update stackguard.
 	MOVL	$runtime·g0(SB), BP
 	LEAL	(-64*1024+104)(SP), BX
 	MOVL	BX, g_stackguard(BP)
 	MOVL	SP, g_stackbase(BP)
 	
-	// if there is an initcgo, call it to let it
+	// if there is an _cgo_init, call it to let it
 	// initialize and to set up GS.  if not,
 	// we set up GS ourselves.
-	MOVL	initcgo(SB), AX
+	MOVL	_cgo_init(SB), AX
 	TESTL	AX, AX
 	JZ	needtls
 	PUSHL	BP
 	CALL	AX
 	POPL	BP
-	// skip runtime·ldt0setup(SB) and tls test after initcgo for non-windows
+	// skip runtime·ldt0setup(SB) and tls test after _cgo_init for non-windows
 	CMPL runtime·iswindows(SB), $0
 	JEQ ok
 needtls:
@@ -75,7 +75,7 @@ ok:
 	CALL	runtime·schedinit(SB)
 
 	// create a new goroutine to start program
-	PUSHL	$runtime·main(SB)	// entry
+	PUSHL	$runtime·main·f(SB)	// entry
 	PUSHL	$0	// arg size
 	CALL	runtime·newproc(SB)
 	POPL	AX
@@ -87,6 +87,9 @@ ok:
 	INT $3
 	RET
 
+DATA	runtime·main·f+0(SB)/4,$runtime·main(SB)
+GLOBL	runtime·main·f(SB),8,$4
+
 TEXT runtime·breakpoint(SB),7,$0
 	INT $3
 	RET
@@ -131,22 +134,40 @@ TEXT runtime·gogo(SB), 7, $0
 	MOVL	gobuf_pc(BX), BX
 	JMP	BX
 
-// void gogocall(Gobuf*, void (*fn)(void))
+// void gogocall(Gobuf*, void (*fn)(void), uintptr r0)
 // restore state from Gobuf but then call fn.
 // (call fn, returning to state in Gobuf)
 TEXT runtime·gogocall(SB), 7, $0
+	MOVL	12(SP), DX	// context
 	MOVL	8(SP), AX		// fn
 	MOVL	4(SP), BX		// gobuf
-	MOVL	gobuf_g(BX), DX
+	MOVL	gobuf_g(BX), DI
 	get_tls(CX)
-	MOVL	DX, g(CX)
-	MOVL	0(DX), CX		// make sure g != nil
+	MOVL	DI, g(CX)
+	MOVL	0(DI), CX		// make sure g != nil
 	MOVL	gobuf_sp(BX), SP	// restore SP
 	MOVL	gobuf_pc(BX), BX
 	PUSHL	BX
 	JMP	AX
 	POPL	BX	// not reached
 
+// void gogocallfn(Gobuf*, FuncVal*)
+// restore state from Gobuf but then call fn.
+// (call fn, returning to state in Gobuf)
+TEXT runtime·gogocallfn(SB), 7, $0
+	MOVL	8(SP), DX		// fn
+	MOVL	4(SP), BX		// gobuf
+	MOVL	gobuf_g(BX), DI
+	get_tls(CX)
+	MOVL	DI, g(CX)
+	MOVL	0(DI), CX		// make sure g != nil
+	MOVL	gobuf_sp(BX), SP	// restore SP
+	MOVL	gobuf_pc(BX), BX
+	PUSHL	BX
+	MOVL	0(DX), BX
+	JMP	BX
+	POPL	BX	// not reached
+
 // void mcall(void (*fn)(G*))
 // Switch to m->g0's stack, call fn(g).
 // Fn must never return.  It should gogo(&g->sched)
@@ -189,11 +210,13 @@ TEXT runtime·morestack(SB),7,$0
 	CMPL	g(CX), SI
 	JNE	2(PC)
 	INT	$3
+	
+	MOVL	DX, m_cret(BX)
 
-	// frame size in DX
+	// frame size in DI
 	// arg size in AX
 	// Save in m.
-	MOVL	DX, m_moreframesize(BX)
+	MOVL	DI, m_moreframesize(BX)
 	MOVL	AX, m_moreargsize(BX)
 
 	// Called from f.
@@ -299,6 +322,33 @@ TEXT runtime·cas(SB), 7, $0
 	MOVL	$1, AX
 	RET
 
+// bool runtime·cas64(uint64 *val, uint64 *old, uint64 new)
+// Atomically:
+//	if(*val == *old){
+//		*val = new;
+//		return 1;
+//	} else {
+//		*old = *val
+//		return 0;
+//	}
+TEXT runtime·cas64(SB), 7, $0
+	MOVL	4(SP), BP
+	MOVL	8(SP), SI
+	MOVL	0(SI), AX
+	MOVL	4(SI), DX
+	MOVL	12(SP), BX
+	MOVL	16(SP), CX
+	LOCK
+	CMPXCHG8B	0(BP)
+	JNZ	cas64_fail
+	MOVL	$1, AX
+	RET
+cas64_fail:
+	MOVL	AX, 0(SI)
+	MOVL	DX, 4(SI)
+	MOVL	$0, AX
+	RET
+
 // bool casp(void **p, void *old, void *new)
 // Atomically:
 //	if(*p == old){
@@ -357,17 +407,49 @@ TEXT runtime·atomicstore(SB), 7, $0
 	XCHGL	AX, 0(BX)
 	RET
 
+// uint64 atomicload64(uint64 volatile* addr);
+// so actually
+// void atomicload64(uint64 *res, uint64 volatile *addr);
+TEXT runtime·atomicload64(SB), 7, $0
+	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
+	RET
+
+// void runtime·atomicstore64(uint64 volatile* addr, uint64 v);
+TEXT runtime·atomicstore64(SB), 7, $0
+	MOVL	4(SP), AX
+	// MOVQ and EMMS were introduced on the Pentium MMX.
+	// MOVQ 0x8(%ESP), %MM0
+	BYTE $0x0f; BYTE $0x6f; BYTE $0x44; BYTE $0x24; BYTE $0x08
+	// MOVQ %MM0, (%EAX)
+	BYTE $0x0f; BYTE $0x7f; BYTE $0x00 
+	// EMMS
+	BYTE $0x0F; BYTE $0x77
+	// This is essentially a no-op, but it provides required memory fencing.
+	// It can be replaced with MFENCE, but MFENCE was introduced only on the Pentium4 (SSE2).
+	MOVL	$0, AX
+	LOCK
+	XADDL	AX, (SP)
+	RET
+
 // void 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), 7, $0
-	MOVL	4(SP), AX	// fn
+	MOVL	4(SP), DX	// fn
 	MOVL	8(SP), BX	// caller sp
 	LEAL	-4(BX), SP	// caller sp after CALL
 	SUBL	$5, (SP)	// return to CALL again
-	JMP	AX	// but first run the deferred function
+	MOVL	0(DX), BX
+	JMP	BX	// but first run the deferred function
 
 // Dummy function to use in saved gobuf.PC,
 // to match SP pointing at a return address.
@@ -416,23 +498,49 @@ TEXT runtime·asmcgocall(SB),7,$0
 	RET
 
 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
-// See cgocall.c for more details.
+// Turn the fn into a Go func (by taking its address) and call
+// cgocallback_gofunc.
 TEXT runtime·cgocallback(SB),7,$12
-	MOVL	fn+0(FP), AX
-	MOVL	frame+4(FP), BX
-	MOVL	framesize+8(FP), DX
+	LEAL	fn+0(FP), AX
+	MOVL	AX, 0(SP)
+	MOVL	frame+4(FP), AX
+	MOVL	AX, 4(SP)
+	MOVL	framesize+8(FP), AX
+	MOVL	AX, 8(SP)
+	MOVL	$runtime·cgocallback_gofunc(SB), AX
+	CALL	AX
+	RET
 
-	// Save current m->g0->sched.sp on stack and then set it to SP.
+// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
+// See cgocall.c for more details.
+TEXT runtime·cgocallback_gofunc(SB),7,$12
+	// If m 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 through AX.
 	get_tls(CX)
+#ifdef GOOS_windows
+	CMPL	CX, $0
+	JNE	3(PC)
+	PUSHL	$0
+	JMP needm
+#endif
 	MOVL	m(CX), BP
-
-	// If m is nil, it is almost certainly because we have been called
-	// on a thread that Go did not create.  We're going to crash as
-	// soon as we try to use m; instead, try to print a nice error and exit.
+	PUSHL	BP
 	CMPL	BP, $0
-	JNE 2(PC)
-	CALL	runtime·badcallback(SB)
+	JNE	havem
+needm:
+	MOVL	$runtime·needm(SB), AX
+	CALL	AX
+	get_tls(CX)
+	MOVL	m(CX), BP
 
+havem:
+	// Now there's a valid m, and we're running on its m->g0.
+	// Save current m->g0->sched.sp on stack and then set it to SP.
+	// Save current sp in m->g0->sched.sp in preparation for
+	// switch back to m->curg stack.
 	MOVL	m_g0(BP), SI
 	PUSHL	(g_sched+gobuf_sp)(SI)
 	MOVL	SP, (g_sched+gobuf_sp)(SI)
@@ -451,6 +559,10 @@ TEXT runtime·cgocallback(SB),7,$12
 	// a frame size of 12, the same amount that we use below),
 	// so that the traceback will seamlessly trace back into
 	// the earlier calls.
+	MOVL	fn+0(FP), AX
+	MOVL	frame+4(FP), BX
+	MOVL	framesize+8(FP), DX
+
 	MOVL	m_curg(BP), SI
 	MOVL	SI, g(CX)
 	MOVL	(g_sched+gobuf_sp)(SI), DI  // prepare stack as DI
@@ -488,10 +600,38 @@ TEXT runtime·cgocallback(SB),7,$12
 	MOVL	SI, g(CX)
 	MOVL	(g_sched+gobuf_sp)(SI), SP
 	POPL	(g_sched+gobuf_sp)(SI)
+	
+	// If the m on entry was nil, we called needm above to borrow an m
+	// for the duration of the call. Since the call is over, return it with dropm.
+	POPL	BP
+	CMPL	BP, $0
+	JNE 3(PC)
+	MOVL	$runtime·dropm(SB), AX
+	CALL	AX
 
 	// Done!
 	RET
 
+// void setmg(M*, G*); set m and g. for use by needm.
+TEXT runtime·setmg(SB), 7, $0
+#ifdef GOOS_windows
+	MOVL	mm+0(FP), AX
+	CMPL	AX, $0
+	JNE	settls
+	MOVL	$0, 0x14(FS)
+	RET
+settls:
+	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
+
 // check that SP is in range [g->stackbase, g->stackguard)
 TEXT runtime·stackcheck(SB), 7, $0
 	get_tls(CX)
diff --git a/src/pkg/runtime/asm_amd64.s b/src/pkg/runtime/asm_amd64.s
index d41ab96..9879584 100644
--- a/src/pkg/runtime/asm_amd64.s
+++ b/src/pkg/runtime/asm_amd64.s
@@ -14,14 +14,14 @@ TEXT _rt0_amd64(SB),7,$-8
 	MOVQ	BX, 24(SP)
 	
 	// create istack out of the given (operating system) stack.
-	// initcgo may update stackguard.
+	// _cgo_init may update stackguard.
 	MOVQ	$runtime·g0(SB), DI
 	LEAQ	(-64*1024+104)(SP), BX
 	MOVQ	BX, g_stackguard(DI)
 	MOVQ	SP, g_stackbase(DI)
 
-	// if there is an initcgo, call it.
-	MOVQ	initcgo(SB), AX
+	// if there is an _cgo_init, call it.
+	MOVQ	_cgo_init(SB), AX
 	TESTQ	AX, AX
 	JZ	needtls
 	// g0 already in DI
@@ -31,6 +31,10 @@ TEXT _rt0_amd64(SB),7,$-8
 	JEQ ok
 
 needtls:
+	// skip TLS setup on Plan 9
+	CMPL	runtime·isplan9(SB), $1
+	JEQ ok
+
 	LEAQ	runtime·tls0(SB), DI
 	CALL	runtime·settls(SB)
 
@@ -64,7 +68,7 @@ ok:
 	CALL	runtime·schedinit(SB)
 
 	// create a new goroutine to start program
-	PUSHQ	$runtime·main(SB)		// entry
+	PUSHQ	$runtime·main·f(SB)		// entry
 	PUSHQ	$0			// arg size
 	CALL	runtime·newproc(SB)
 	POPQ	AX
@@ -76,6 +80,9 @@ ok:
 	MOVL	$0xf1, 0xf1  // crash
 	RET
 
+DATA	runtime·main·f+0(SB)/8,$runtime·main(SB)
+GLOBL	runtime·main·f(SB),8,$8
+
 TEXT runtime·breakpoint(SB),7,$0
 	BYTE	$0xcc
 	RET
@@ -114,22 +121,40 @@ TEXT runtime·gogo(SB), 7, $0
 	MOVQ	gobuf_pc(BX), BX
 	JMP	BX
 
-// void gogocall(Gobuf*, void (*fn)(void))
+// void gogocall(Gobuf*, void (*fn)(void), uintptr r0)
 // restore state from Gobuf but then call fn.
 // (call fn, returning to state in Gobuf)
 TEXT runtime·gogocall(SB), 7, $0
+	MOVQ	24(SP), DX	// context
 	MOVQ	16(SP), AX		// fn
 	MOVQ	8(SP), BX		// gobuf
-	MOVQ	gobuf_g(BX), DX
+	MOVQ	gobuf_g(BX), DI
 	get_tls(CX)
-	MOVQ	DX, g(CX)
-	MOVQ	0(DX), CX	// make sure g != nil
+	MOVQ	DI, g(CX)
+	MOVQ	0(DI), CX	// make sure g != nil
 	MOVQ	gobuf_sp(BX), SP	// restore SP
 	MOVQ	gobuf_pc(BX), BX
 	PUSHQ	BX
 	JMP	AX
 	POPQ	BX	// not reached
 
+// void gogocallfn(Gobuf*, FuncVal*)
+// restore state from Gobuf but then call fn.
+// (call fn, returning to state in Gobuf)
+TEXT runtime·gogocallfn(SB), 7, $0
+	MOVQ	16(SP), DX		// fn
+	MOVQ	8(SP), BX		// gobuf
+	MOVQ	gobuf_g(BX), AX
+	get_tls(CX)
+	MOVQ	AX, g(CX)
+	MOVQ	0(AX), CX	// make sure g != nil
+	MOVQ	gobuf_sp(BX), SP	// restore SP
+	MOVQ	gobuf_pc(BX), BX
+	PUSHQ	BX
+	MOVQ	0(DX), BX
+	JMP	BX
+	POPQ	BX	// not reached
+
 // void mcall(void (*fn)(G*))
 // Switch to m->g0's stack, call fn(g).
 // Fn must never return.  It should gogo(&g->sched)
@@ -171,6 +196,8 @@ TEXT runtime·morestack(SB),7,$0
 	CMPQ	g(CX), SI
 	JNE	2(PC)
 	INT	$3
+	
+	MOVQ	DX, m_cret(BX)
 
 	// Called from f.
 	// Set m->morebuf to f's caller.
@@ -344,6 +371,30 @@ TEXT runtime·cas(SB), 7, $0
 	MOVL	$1, AX
 	RET
 
+// bool	runtime·cas64(uint64 *val, uint64 *old, uint64 new)
+// Atomically:
+//	if(*val == *old){
+//		*val = new;
+//		return 1;
+//	} else {
+//		*old = *val
+//		return 0;
+//	}
+TEXT runtime·cas64(SB), 7, $0
+	MOVQ	8(SP), BX
+	MOVQ	16(SP), BP
+	MOVQ	0(BP), AX
+	MOVQ	24(SP), CX
+	LOCK
+	CMPXCHGQ	CX, 0(BX)
+	JNZ	cas64_fail
+	MOVL	$1, AX
+	RET
+cas64_fail:
+	MOVQ	AX, 0(BP)
+	MOVL	$0, AX
+	RET
+
 // bool casp(void **val, void *old, void *new)
 // Atomically:
 //	if(*val == old){
@@ -376,6 +427,15 @@ TEXT runtime·xadd(SB), 7, $0
 	ADDL	CX, AX
 	RET
 
+TEXT runtime·xadd64(SB), 7, $0
+	MOVQ	8(SP), BX
+	MOVQ	16(SP), AX
+	MOVQ	AX, CX
+	LOCK
+	XADDQ	AX, 0(BX)
+	ADDQ	CX, AX
+	RET
+
 TEXT runtime·xchg(SB), 7, $0
 	MOVQ	8(SP), BX
 	MOVL	16(SP), AX
@@ -402,17 +462,24 @@ TEXT runtime·atomicstore(SB), 7, $0
 	XCHGL	AX, 0(BX)
 	RET
 
+TEXT runtime·atomicstore64(SB), 7, $0
+	MOVQ	8(SP), BX
+	MOVQ	16(SP), AX
+	XCHGQ	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), 7, $0
-	MOVQ	8(SP), AX	// fn
+	MOVQ	8(SP), DX	// fn
 	MOVQ	16(SP), BX	// caller sp
 	LEAQ	-8(BX), SP	// caller sp after CALL
 	SUBQ	$5, (SP)	// return to CALL again
-	JMP	AX	// but first run the deferred function
+	MOVQ	0(DX), BX
+	JMP	BX	// but first run the deferred function
 
 // Dummy function to use in saved gobuf.PC,
 // to match SP pointing at a return address.
@@ -446,39 +513,67 @@ TEXT runtime·asmcgocall(SB),7,$0
 	MOVQ	(g_sched+gobuf_sp)(SI), SP
 
 	// Now on a scheduling stack (a pthread-created stack).
-	SUBQ	$48, SP
+	// Make sure we have enough room for 4 stack-backed fast-call
+	// registers as per windows amd64 calling convention.
+	SUBQ	$64, SP
 	ANDQ	$~15, SP	// alignment for gcc ABI
-	MOVQ	DI, 32(SP)	// save g
-	MOVQ	DX, 24(SP)	// save SP
+	MOVQ	DI, 48(SP)	// save g
+	MOVQ	DX, 40(SP)	// save SP
 	MOVQ	BX, DI		// DI = first argument in AMD64 ABI
 	MOVQ	BX, CX		// CX = first argument in Win64
 	CALL	AX
 
 	// Restore registers, g, stack pointer.
 	get_tls(CX)
-	MOVQ	32(SP), DI
+	MOVQ	48(SP), DI
 	MOVQ	DI, g(CX)
-	MOVQ	24(SP), SP
+	MOVQ	40(SP), SP
 	RET
 
 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
-// See cgocall.c for more details.
+// Turn the fn into a Go func (by taking its address) and call
+// cgocallback_gofunc.
 TEXT runtime·cgocallback(SB),7,$24
-	MOVQ	fn+0(FP), AX
-	MOVQ	frame+8(FP), BX
-	MOVQ	framesize+16(FP), DX
+	LEAQ	fn+0(FP), AX
+	MOVQ	AX, 0(SP)
+	MOVQ	frame+8(FP), AX
+	MOVQ	AX, 8(SP)
+	MOVQ	framesize+16(FP), AX
+	MOVQ	AX, 16(SP)
+	MOVQ	$runtime·cgocallback_gofunc(SB), AX
+	CALL	AX
+	RET
 
-	// Save current m->g0->sched.sp on stack and then set it to SP.
+// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
+// See cgocall.c for more details.
+TEXT runtime·cgocallback_gofunc(SB),7,$24
+	// If m 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 through AX.
 	get_tls(CX)
+#ifdef GOOS_windows
+	CMPQ	CX, $0
+	JNE	3(PC)
+	PUSHQ	$0
+	JMP	needm
+#endif
 	MOVQ	m(CX), BP
-	
-	// If m is nil, it is almost certainly because we have been called
-	// on a thread that Go did not create.  We're going to crash as
-	// soon as we try to use m; instead, try to print a nice error and exit.
+	PUSHQ	BP
 	CMPQ	BP, $0
-	JNE 2(PC)
-	CALL	runtime·badcallback(SB)
+	JNE	havem
+needm:
+	MOVQ	$runtime·needm(SB), AX
+	CALL	AX
+	get_tls(CX)
+	MOVQ	m(CX), BP
 
+havem:
+	// Now there's a valid m, and we're running on its m->g0.
+	// Save current m->g0->sched.sp on stack and then set it to SP.
+	// Save current sp in m->g0->sched.sp in preparation for
+	// switch back to m->curg stack.
 	MOVQ	m_g0(BP), SI
 	PUSHQ	(g_sched+gobuf_sp)(SI)
 	MOVQ	SP, (g_sched+gobuf_sp)(SI)
@@ -497,6 +592,10 @@ TEXT runtime·cgocallback(SB),7,$24
 	// a frame size of 24, the same amount that we use below),
 	// so that the traceback will seamlessly trace back into
 	// the earlier calls.
+	MOVQ	fn+0(FP), AX
+	MOVQ	frame+8(FP), BX
+	MOVQ	framesize+16(FP), DX
+
 	MOVQ	m_curg(BP), SI
 	MOVQ	SI, g(CX)
 	MOVQ	(g_sched+gobuf_sp)(SI), DI  // prepare stack as DI
@@ -534,10 +633,37 @@ TEXT runtime·cgocallback(SB),7,$24
 	MOVQ	SI, g(CX)
 	MOVQ	(g_sched+gobuf_sp)(SI), SP
 	POPQ	(g_sched+gobuf_sp)(SI)
+	
+	// If the m on entry was nil, we called needm above to borrow an m
+	// for the duration of the call. Since the call is over, return it with dropm.
+	POPQ	BP
+	CMPQ	BP, $0
+	JNE 3(PC)
+	MOVQ	$runtime·dropm(SB), AX
+	CALL	AX
 
 	// Done!
 	RET
 
+// void setmg(M*, G*); set m and g. for use by needm.
+TEXT runtime·setmg(SB), 7, $0
+	MOVQ	mm+0(FP), AX
+#ifdef GOOS_windows
+	CMPQ	AX, $0
+	JNE	settls
+	MOVQ	$0, 0x28(GS)
+	RET
+settls:
+	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
+
 // check that SP is in range [g->stackbase, g->stackguard)
 TEXT runtime·stackcheck(SB), 7, $0
 	get_tls(CX)
diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s
index 423fda7..45b5354 100644
--- a/src/pkg/runtime/asm_arm.s
+++ b/src/pkg/runtime/asm_arm.s
@@ -31,6 +31,13 @@ TEXT _rt0_arm(SB),7,$-4
 	MOVW	R13, g_stackbase(g)
 	BL	runtime·emptyfunc(SB)	// fault if stack check is wrong
 
+	// if there is an _cgo_init, call it.
+	MOVW	_cgo_init(SB), R2
+	CMP	$0, R2
+	MOVW.NE	g, R0 // first argument of _cgo_init is g
+	BL.NE	(R2) // will clobber R0-R3
+
+	BL	runtime·checkgoarm(SB)
 	BL	runtime·check(SB)
 
 	// saved argc, argv
@@ -43,7 +50,7 @@ TEXT _rt0_arm(SB),7,$-4
 	BL	runtime·schedinit(SB)
 
 	// create a new goroutine to start program
-	MOVW	$runtime·main(SB), R0
+	MOVW	$runtime·main·f(SB), R0
 	MOVW.W	R0, -4(R13)
 	MOVW	$8, R0
 	MOVW.W	R0, -4(R13)
@@ -58,24 +65,25 @@ TEXT _rt0_arm(SB),7,$-4
 	MOVW	$1234, R0
 	MOVW	$1000, R1
 	MOVW	R0, (R1)	// fail hard
-	B	runtime·_dep_dummy(SB)	// Never reached
-
-// TODO(kaib): remove these once i actually understand how the linker removes symbols
-// pull in dummy dependencies
-TEXT runtime·_dep_dummy(SB),7,$0
-	BL	_div(SB)
-	BL	_divu(SB)
-	BL	_mod(SB)
-	BL	_modu(SB)
-	BL	_modu(SB)
-	BL	_sfloat(SB)
+
+DATA	runtime·main·f+0(SB)/4,$runtime·main(SB)
+GLOBL	runtime·main·f(SB),8,$4
 
 TEXT runtime·breakpoint(SB),7,$0
-	// no breakpoint yet; let program exit
+	// gdb won't skip this breakpoint instruction automatically,
+	// so you must manually "set $pc+=4" to skip it and continue.
+	WORD    $0xe1200071 // BKPT 0x0001
 	RET
 
+GLOBL runtime·goarm(SB), $4
 TEXT runtime·asminit(SB),7,$0
-	// No per-thread init.
+	// disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5
+	MOVW runtime·goarm(SB), R11
+	CMP $5, R11
+	BLE 4(PC)
+	WORD $0xeef1ba10	// vmrs r11, fpscr
+	BIC $(1<<24), R11
+	WORD $0xeee1ba10	// vmsr fpscr, r11
 	RET
 
 /*
@@ -95,26 +103,49 @@ TEXT runtime·gosave(SB), 7, $-4
 // restore state from Gobuf; longjmp
 TEXT runtime·gogo(SB), 7, $-4
 	MOVW	0(FP), R1		// gobuf
-	MOVW	4(FP), R0		// return 2nd arg
 	MOVW	gobuf_g(R1), g
 	MOVW	0(g), R2		// make sure g != nil
+	MOVW	_cgo_save_gm(SB), R2
+	CMP 	$0, R2 // if in Cgo, we have to save g and m
+	BL.NE	(R2) // this call will clobber R0
+	MOVW	4(FP), R0		// return 2nd arg
 	MOVW	gobuf_sp(R1), SP	// restore SP
 	MOVW	gobuf_pc(R1), PC
 
-// void gogocall(Gobuf*, void (*fn)(void))
+// void gogocall(Gobuf*, void (*fn)(void), uintptr r7)
 // restore state from Gobuf but then call fn.
 // (call fn, returning to state in Gobuf)
 // using frame size $-4 means do not save LR on stack.
 TEXT runtime·gogocall(SB), 7, $-4
-	MOVW	0(FP), R0		// gobuf
+	MOVW	0(FP), R3		// gobuf
 	MOVW	4(FP), R1		// fn
-	MOVW	8(FP), R2		// fp offset
-	MOVW	gobuf_g(R0), g
-	MOVW	0(g), R3		// make sure g != nil
-	MOVW	gobuf_sp(R0), SP	// restore SP
-	MOVW	gobuf_pc(R0), LR
+	MOVW	gobuf_g(R3), g
+	MOVW	0(g), R0		// make sure g != nil
+	MOVW	_cgo_save_gm(SB), R0
+	CMP 	$0, R0 // if in Cgo, we have to save g and m
+	BL.NE	(R0) // this call will clobber R0
+	MOVW	8(FP), R7	// context
+	MOVW	gobuf_sp(R3), SP	// restore SP
+	MOVW	gobuf_pc(R3), LR
 	MOVW	R1, PC
 
+// void gogocallfn(Gobuf*, FuncVal*)
+// restore state from Gobuf but then call fn.
+// (call fn, returning to state in Gobuf)
+// using frame size $-4 means do not save LR on stack.
+TEXT runtime·gogocallfn(SB), 7, $-4
+	MOVW	0(FP), R3		// gobuf
+	MOVW	4(FP), R1		// fn
+	MOVW	gobuf_g(R3), g
+	MOVW	0(g), R0		// make sure g != nil
+	MOVW	_cgo_save_gm(SB), R0
+	CMP 	$0, R0 // if in Cgo, we have to save g and m
+	BL.NE	(R0) // this call will clobber R0
+	MOVW	gobuf_sp(R3), SP	// restore SP
+	MOVW	gobuf_pc(R3), LR
+	MOVW	R1, R7
+	MOVW	0(R1), PC
+
 // void mcall(void (*fn)(G*))
 // Switch to m->g0's stack, call fn(g).
 // Fn must never return.  It should gogo(&g->sched)
@@ -157,6 +188,7 @@ TEXT runtime·morestack(SB),7,$-4
 	BL.EQ	runtime·abort(SB)
 
 	// Save in m.
+	MOVW	R7, m_cret(m) // function context
 	MOVW	R1, m_moreframesize(m)
 	MOVW	R2, m_moreargsize(m)
 
@@ -228,28 +260,175 @@ TEXT runtime·lessstack(SB), 7, $-4
 TEXT runtime·jmpdefer(SB), 7, $0
 	MOVW	0(SP), LR
 	MOVW	$-4(LR), LR	// BL deferreturn
-	MOVW	fn+0(FP), R0
+	MOVW	fn+0(FP), R7
 	MOVW	argp+4(FP), SP
 	MOVW	$-4(SP), SP	// SP is 4 below argp, due to saved LR
-	B		(R0)
+	MOVW	0(R7), R1
+	B	(R1)
+
+// Dummy function to use in saved gobuf.PC,
+// to match SP pointing at a return address.
+// The gobuf.PC is unused by the contortions here
+// but setting it to return will make the traceback code work.
+TEXT return<>(SB),7,$0
+	RET
 
+// asmcgocall(void(*fn)(void*), void *arg)
+// Call fn(arg) on the scheduler stack,
+// aligned appropriately for the gcc ABI.
+// See cgocall.c for more details.
 TEXT	runtime·asmcgocall(SB),7,$0
-	B	runtime·cgounimpl(SB)
+	MOVW	fn+0(FP), R1
+	MOVW	arg+4(FP), R0
+	MOVW	R13, R2
+	MOVW	g, R5
+
+	// 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
+	CMP	R3, g
+	BEQ	7(PC)
+	MOVW	R13, (g_sched + gobuf_sp)(g)
+	MOVW	$return<>(SB), R4
+	MOVW	R4, (g_sched+gobuf_pc)(g)
+	MOVW	g, (g_sched+gobuf_g)(g)
+	MOVW	R3, g
+	MOVW	(g_sched+gobuf_sp)(g), R13
+
+	// Now on a scheduling stack (a pthread-created stack).
+	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
+	BL	(R1)
+
+	// Restore registers, g, stack pointer.
+	MOVW	20(R13), g
+	MOVW	16(R13), R13
+	RET
 
-TEXT	runtime·cgocallback(SB),7,$0
-	B	runtime·cgounimpl(SB)
+// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+// Turn the fn into a Go func (by taking its address) and call
+// cgocallback_gofunc.
+TEXT runtime·cgocallback(SB),7,$12
+	MOVW	$fn+0(FP), R0
+	MOVW	R0, 4(R13)
+	MOVW	frame+4(FP), R0
+	MOVW	R0, 8(R13)
+	MOVW	framesize+8(FP), R0
+	MOVW	R0, 12(R13)
+	MOVW	$runtime·cgocallback_gofunc(SB), R0
+	BL	(R0)
+	RET
+
+// cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize)
+// See cgocall.c for more details.
+TEXT	runtime·cgocallback_gofunc(SB),7,$16
+	// Load m and g from thread-local storage.
+	MOVW	_cgo_load_gm(SB), R0
+	CMP	$0, R0
+	BL.NE	(R0)
+
+	// If m 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-16(SP)
+	CMP	$0, m
+	B.NE havem
+	MOVW	$runtime·needm(SB), R0
+	BL	(R0)
+
+havem:
+	// Now there's a valid m, and we're running on its m->g0.
+	// Save current m->g0->sched.sp on stack and then set it to SP.
+	// Save current sp in m->g0->sched.sp in preparation for
+	// switch back to m->curg stack.
+	MOVW	fn+0(FP), R0
+	MOVW	frame+4(FP), R1
+	MOVW	framesize+8(FP), R2
+
+	MOVW	m_g0(m), R3
+	MOVW	(g_sched+gobuf_sp)(R3), R4
+	MOVW.W	R4, -4(R13)
+	MOVW	R13, (g_sched+gobuf_sp)(R3)
+
+	// Switch to m->curg stack and call runtime.cgocallbackg
+	// with the three arguments.  Because we are taking over
+	// the execution of m->curg but *not* resuming what had
+	// been running, we need to save that information (m->curg->gobuf)
+	// so that we can restore it when we're done. 
+	// We can restore m->curg->gobuf.sp easily, because calling
+	// runtime.cgocallbackg leaves SP unchanged upon return.
+	// To save m->curg->gobuf.pc, we push it onto the stack.
+	// This has the added benefit that it looks to the traceback
+	// routine like cgocallbackg is going to return to that
+	// PC (because we defined cgocallbackg to have
+	// a frame size of 16, the same amount that we use below),
+	// so that the traceback will seamlessly trace back into
+	// the earlier calls.
+
+	// Save current m->g0->sched.sp on stack and then set it to SP.
+	MOVW	m_curg(m), g
+	MOVW	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
+
+	// Push gobuf.pc
+	MOVW	(g_sched+gobuf_pc)(g), R5
+	SUB	$4, R4
+	MOVW	R5, 0(R4)
+
+	// Push arguments to cgocallbackg.
+	// Frame size here must match the frame size above
+	// to trick traceback routines into doing the right thing.
+	SUB	$16, R4
+	MOVW	R0, 4(R4)
+	MOVW	R1, 8(R4)
+	MOVW	R2, 12(R4)
+	
+	// Switch stack and make the call.
+	MOVW	R4, R13
+	BL	runtime·cgocallbackg(SB)
+
+	// Restore g->gobuf (== m->curg->gobuf) from saved values.
+	MOVW	16(R13), R5
+	MOVW	R5, (g_sched+gobuf_pc)(g)
+	ADD	$(16+4), R13 // SP clobbered! It is ok!
+	MOVW	R13, (g_sched+gobuf_sp)(g)
+
+	// Switch back to m->g0's stack and restore m->g0->sched.sp.
+	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
+	// so we do not have to restore it.)
+	MOVW	m_g0(m), g
+	MOVW	(g_sched+gobuf_sp)(g), R13
+	// POP R6
+	MOVW	0(R13), R6
+	ADD	$4, R13
+	MOVW	R6, (g_sched+gobuf_sp)(g)
+
+	// If the m on entry was nil, we called needm above to borrow an m
+	// for the duration of the call. Since the call is over, return it with dropm.
+	MOVW	savedm-16(SP), R6
+	CMP	$0, R6
+	B.NE	3(PC)
+	MOVW	$runtime·dropm(SB), R0
+	BL	(R0)
+
+	// Done!
+	RET
+
+// void setmg(M*, G*); set m and g. for use by needm.
+TEXT runtime·setmg(SB), 7, $-4
+	MOVW	mm+0(FP), m
+	MOVW	gg+4(FP), g
+
+	// Save m and g to thread-local storage.
+	MOVW	_cgo_save_gm(SB), R0
+	CMP	$0, R0
+	BL.NE	(R0)
 
-TEXT runtime·memclr(SB),7,$20
-	MOVW	0(FP), R0
-	MOVW	$0, R1		// c = 0
-	MOVW	R1, -16(SP)
-	MOVW	4(FP), R1	// n
-	MOVW	R1, -12(SP)
-	MOVW	m, -8(SP)	// Save m and g
-	MOVW	g, -4(SP)
-	BL	runtime·memset(SB)
-	MOVW	-8(SP), m	// Restore m and g, memset clobbers them
-	MOVW	-4(SP), g
 	RET
 
 TEXT runtime·getcallerpc(SB),7,$-4
@@ -269,16 +448,6 @@ TEXT runtime·getcallersp(SB),7,$-4
 TEXT runtime·emptyfunc(SB),0,$0
 	RET
 
-// int64 runtime·cputicks(), so really
-// void runtime·cputicks(int64 *ticks)
-// stubbed: return int64(0)
-TEXT runtime·cputicks(SB),7,$0
-	MOVW    0(FP), R1
-	MOVW	$0, R0
-	MOVW    R0, 0(R1)
-	MOVW    R0, 4(R1)
-	RET
-
 TEXT runtime·abort(SB),7,$-4
 	MOVW	$0, R0
 	MOVW	(R0), R1
diff --git a/src/pkg/runtime/atomic_386.c b/src/pkg/runtime/atomic_386.c
index a4f2a11..79b7cbf 100644
--- a/src/pkg/runtime/atomic_386.c
+++ b/src/pkg/runtime/atomic_386.c
@@ -17,3 +17,16 @@ runtime·atomicloadp(void* volatile* addr)
 {
 	return *addr;
 }
+
+#pragma textflag 7
+uint64
+runtime·xadd64(uint64 volatile* addr, int64 v)
+{
+	uint64 old;
+
+	old = *addr;
+	while(!runtime·cas64(addr, &old, old+v)) {
+		// nothing
+	}
+	return old+v;
+}
diff --git a/src/pkg/runtime/atomic_amd64.c b/src/pkg/runtime/atomic_amd64.c
index a4f2a11..e92d8ec 100644
--- a/src/pkg/runtime/atomic_amd64.c
+++ b/src/pkg/runtime/atomic_amd64.c
@@ -12,6 +12,13 @@ runtime·atomicload(uint32 volatile* addr)
 }
 
 #pragma textflag 7
+uint64
+runtime·atomicload64(uint64 volatile* addr)
+{
+	return *addr;
+}
+
+#pragma textflag 7
 void*
 runtime·atomicloadp(void* volatile* addr)
 {
diff --git a/src/pkg/runtime/atomic_arm.c b/src/pkg/runtime/atomic_arm.c
index 52e4059..0b54840 100644
--- a/src/pkg/runtime/atomic_arm.c
+++ b/src/pkg/runtime/atomic_arm.c
@@ -3,6 +3,14 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
+
+static union {
+	Lock l;
+	byte pad [CacheLineSize];
+} locktab[57];
+
+#define LOCK(addr) (&locktab[((uintptr)(addr)>>3)%nelem(locktab)].l)
 
 // Atomic add and return new value.
 #pragma textflag 7
@@ -80,4 +88,56 @@ runtime·atomicstore(uint32 volatile* addr, uint32 v)
 		if(runtime·cas(addr, old, v))
 			return;
 	}
-}
\ No newline at end of file
+}
+
+#pragma textflag 7
+bool
+runtime·cas64(uint64 volatile *addr, uint64 *old, uint64 new)
+{
+	bool res;
+	
+	runtime·lock(LOCK(addr));
+	if(*addr == *old) {
+		*addr = new;
+		res = true;
+	} else {
+		*old = *addr;
+		res = false;
+	}
+	runtime·unlock(LOCK(addr));
+	return res;
+}
+
+#pragma textflag 7
+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 7
+uint64
+runtime·atomicload64(uint64 volatile *addr)
+{
+	uint64 res;
+	
+	runtime·lock(LOCK(addr));
+	res = *addr;
+	runtime·unlock(LOCK(addr));
+	return res;
+}
+
+#pragma textflag 7
+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_386.c b/src/pkg/runtime/callback_windows_386.c
index fcd292f..880588d 100644
--- a/src/pkg/runtime/callback_windows_386.c
+++ b/src/pkg/runtime/callback_windows_386.c
@@ -4,6 +4,7 @@
 
 #include "runtime.h"
 #include "type.h"
+#include "typekind.h"
 #include "defs_GOOS_GOARCH.h"
 #include "os_GOOS.h"
 
@@ -79,7 +80,7 @@ runtime·compilecallback(Eface fn, bool cleanstack)
 
 	// MOVL fn, AX
 	*p++ = 0xb8;
-	*(uint32*)p = (uint32)fn.data;
+	*(uint32*)p = (uint32)(fn.data);
 	p += 4;
 
 	// MOVL argsize, DX
diff --git a/src/pkg/runtime/callback_windows_amd64.c b/src/pkg/runtime/callback_windows_amd64.c
index 99d7cb9..1a47792 100644
--- a/src/pkg/runtime/callback_windows_amd64.c
+++ b/src/pkg/runtime/callback_windows_amd64.c
@@ -4,6 +4,7 @@
 
 #include "runtime.h"
 #include "type.h"
+#include "typekind.h"
 #include "defs_GOOS_GOARCH.h"
 #include "os_GOOS.h"
 
@@ -77,7 +78,7 @@ runtime·compilecallback(Eface fn, bool /*cleanstack*/)
 	// MOVQ fn, AX
 	*p++ = 0x48;
 	*p++ = 0xb8;
-	*(uint64*)p = (uint64)fn.data;
+	*(uint64*)p = (uint64)(fn.data);
 	p += 8;
 	// PUSH AX
 	*p++ = 0x50;
diff --git a/src/pkg/runtime/cgo/asm_386.s b/src/pkg/runtime/cgo/asm_386.s
new file mode 100644
index 0000000..7faaa40
--- /dev/null
+++ b/src/pkg/runtime/cgo/asm_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+ * void crosscall2(void (*fn)(void*, int32), void*, int32)
+ * Save registers and call fn with two arguments.
+ */
+TEXT crosscall2(SB),7,$0
+	PUSHL	BP
+	MOVL	SP, BP
+	PUSHL	BX
+	PUSHL	SI
+	PUSHL	DI
+	
+	SUBL	$8, SP
+	MOVL	16(BP), AX
+	MOVL	AX, 4(SP)
+	MOVL	12(BP), AX
+	MOVL	AX, 0(SP)
+	MOVL	8(BP), AX
+	CALL	AX
+	ADDL	$8, SP
+	
+	POPL	DI
+	POPL	SI
+	POPL	BX
+	POPL	BP
+	RET
diff --git a/src/pkg/runtime/cgo/asm_amd64.s b/src/pkg/runtime/cgo/asm_amd64.s
new file mode 100644
index 0000000..53f7148
--- /dev/null
+++ b/src/pkg/runtime/cgo/asm_amd64.s
@@ -0,0 +1,45 @@
+// 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.
+
+/*
+ * void crosscall2(void (*fn)(void*, int32), void*, int32)
+ * Save registers and call fn with two arguments.
+ */
+TEXT crosscall2(SB),7,$0
+	SUBQ	$0x58, SP	/* keeps stack pointer 32-byte aligned */
+	MOVQ	BX, 0x10(SP)
+	MOVQ	BP, 0x18(SP)
+	MOVQ	R12, 0x20(SP)
+	MOVQ	R13, 0x28(SP)
+	MOVQ	R14, 0x30(SP)
+	MOVQ	R15, 0x38(SP)
+
+#ifdef GOOS_windows
+	// Win64 save RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15
+	MOVQ	DI, 0x40(SP)
+	MOVQ	SI, 0x48(SP)
+
+	MOVQ	DX, 0(SP)	/* arg */
+	MOVQ	R8, 8(SP)	/* argsize (includes padding) */
+	
+	CALL	CX	/* fn */
+	
+	MOVQ	0x40(SP), DI
+	MOVQ	0x48(SP), SI
+#else
+	MOVQ	SI, 0(SP)	/* arg */
+	MOVQ	DX, 8(SP)	/* argsize (includes padding) */
+
+	CALL	DI	/* fn */
+#endif
+
+	MOVQ	0x10(SP), BX
+	MOVQ	0x18(SP), BP
+	MOVQ	0x20(SP), R12
+	MOVQ	0x28(SP), R13
+	MOVQ	0x30(SP), R14
+	MOVQ	0x38(SP), R15
+	
+	ADDQ	$0x58, SP
+	RET
diff --git a/src/pkg/runtime/cgo/asm_arm.s b/src/pkg/runtime/cgo/asm_arm.s
new file mode 100644
index 0000000..a6ea0dc
--- /dev/null
+++ b/src/pkg/runtime/cgo/asm_arm.s
@@ -0,0 +1,23 @@
+// 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.
+
+/*
+ * void crosscall2(void (*fn)(void*, int32), void*, int32)
+ * Save registers and call fn with two arguments.
+ */
+TEXT crosscall2(SB),7,$-4
+	/* 
+	 * We still need to save all callee save register as before, and then
+	 *  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, cgo_tls_set_gm will clobber R0, so we need to save R0
+	 *  nevertheless.
+	 */
+	MOVM.WP	[R0, R1, R2, R4, R5, R6, R7, R8, R9, R10, R11, R12, R14], (R13)
+	MOVW	_cgo_load_gm(SB), R0
+	BL	(R0)
+	MOVW	PC, R14
+	MOVW	0(R13), PC
+	MOVM.IAW	(R13), [R0, R1, R2, R4, R5, R6, R7, R8, R9, R10, R11, R12, PC]
diff --git a/src/pkg/runtime/cgo/callbacks.c b/src/pkg/runtime/cgo/callbacks.c
index f36fb3f..51bd529 100644
--- a/src/pkg/runtime/cgo/callbacks.c
+++ b/src/pkg/runtime/cgo/callbacks.c
@@ -33,7 +33,13 @@
 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);
 }
 
@@ -71,3 +77,19 @@ _cgo_panic(void *a, int32 n)
 {
 	runtime·cgocallback((void(*)(void))_cgo_panic_internal, a, n);
 }
+
+#pragma cgo_import_static x_cgo_init
+extern void x_cgo_init(G*);
+void (*_cgo_init)(G*) = x_cgo_init;
+
+#pragma cgo_import_static x_cgo_malloc
+extern void x_cgo_malloc(void*);
+void (*_cgo_malloc)(void*) = x_cgo_malloc;
+
+#pragma cgo_import_static x_cgo_free
+extern void x_cgo_free(void*);
+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;
diff --git a/src/pkg/runtime/cgo/cgo.go b/src/pkg/runtime/cgo/cgo.go
index 414f3da..e0d5386 100644
--- a/src/pkg/runtime/cgo/cgo.go
+++ b/src/pkg/runtime/cgo/cgo.go
@@ -18,6 +18,8 @@ package cgo
 #cgo openbsd LDFLAGS: -lpthread
 #cgo windows LDFLAGS: -lm -mthreads
 
+#cgo CFLAGS: -Wall -Werror
+
 */
 import "C"
 
diff --git a/src/pkg/runtime/cgo/cgo_arm.c b/src/pkg/runtime/cgo/cgo_arm.c
new file mode 100644
index 0000000..d23f53e
--- /dev/null
+++ b/src/pkg/runtime/cgo/cgo_arm.c
@@ -0,0 +1,12 @@
+// 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.
+
+#pragma cgo_import_static x_cgo_load_gm
+extern void x_cgo_load_gm(void);
+void (*_cgo_load_gm)(void) = x_cgo_load_gm;
+
+#pragma cgo_import_static x_cgo_save_gm
+extern void x_cgo_save_gm(void);
+void (*_cgo_save_gm)(void) = x_cgo_save_gm;
+
diff --git a/src/pkg/runtime/cgo/gcc_386.S b/src/pkg/runtime/cgo/gcc_386.S
index 9abab7e..94ba584 100644
--- a/src/pkg/runtime/cgo/gcc_386.S
+++ b/src/pkg/runtime/cgo/gcc_386.S
@@ -35,31 +35,6 @@ EXT(crosscall_386):
 	popl %ebp
 	ret
 
-/*
- * void crosscall2(void (*fn)(void*, int32), void*, int32)
- *
- * Save registers and call fn with two arguments.
- */
-.globl EXT(crosscall2)
-EXT(crosscall2):
-	pushl %ebp
-	movl %esp, %ebp
-	pushl %ebx
-	pushl %esi
-	pushl %edi
-
-	pushl 16(%ebp)
-	pushl 12(%ebp)
-	mov 8(%ebp), %eax
-	call *%eax
-	addl $8,%esp
-
-	popl %edi
-	popl %esi
-	popl %ebx
-	popl %ebp
-	ret
-
 .globl EXT(__stack_chk_fail_local)
 EXT(__stack_chk_fail_local):
 1:
diff --git a/src/pkg/runtime/cgo/gcc_amd64.S b/src/pkg/runtime/cgo/gcc_amd64.S
index 706ee6b..81b2701 100644
--- a/src/pkg/runtime/cgo/gcc_amd64.S
+++ b/src/pkg/runtime/cgo/gcc_amd64.S
@@ -19,9 +19,6 @@
  * are callee-save so they must be saved explicitly.
  * The standard x86-64 ABI passes the three arguments m, g, fn
  * in %rdi, %rsi, %rdx.
- *
- * Also need to set %r15 to g and %r14 to m (see ../pkg/runtime/mkasmh.sh)
- * during the call.
  */
 .globl EXT(crosscall_amd64)
 EXT(crosscall_amd64):
@@ -45,48 +42,3 @@ EXT(crosscall_amd64):
 	popq %rbp
 	popq %rbx
 	ret
-
-/*
- * void crosscall2(void (*fn)(void*, int32), void *arg, int32 argsize)
- *
- * Save registers and call fn with two arguments.  fn is a Go function
- * which takes parameters on the stack rather than in registers.
- */
-.globl EXT(crosscall2)
-EXT(crosscall2):
-	subq  $0x58, %rsp	/* keeps stack pointer 32-byte aligned */
-	movq  %rbx, 0x10(%rsp)
-	movq  %rbp, 0x18(%rsp)
-	movq  %r12, 0x20(%rsp)
-	movq  %r13, 0x28(%rsp)
-	movq  %r14, 0x30(%rsp)
-	movq  %r15, 0x38(%rsp)
-
-#if defined(_WIN64)
-	// Win64 save RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15
-	movq	%rdi, 0x40(%rsp)
-	movq	%rsi, 0x48(%rsp)
-
-	movq  %rdx, 0(%rsp)	/* arg */
-	movq  %r8, 8(%rsp)	/* argsize (includes padding) */
-	
-	call *%rcx	/* fn */
-#else
-	movq  %rsi, 0(%rsp)	/* arg */
-	movq  %rdx, 8(%rsp)	/* argsize (includes padding) */
-
-	call *%rdi	/* fn */
-#endif
-
-	movq  0x10(%rsp), %rbx
-	movq  0x18(%rsp), %rbp
-	movq  0x20(%rsp), %r12
-	movq  0x28(%rsp), %r13
-	movq  0x30(%rsp), %r14
-	movq  0x38(%rsp), %r15
-#if defined(__WIN64)
-	movq	0x40(%rsp), %rdi
-	movq	0x48(%rsp), %rsi
-#endif	
-	addq  $0x58, %rsp
-	ret
diff --git a/src/pkg/runtime/cgo/gcc_arm.S b/src/pkg/runtime/cgo/gcc_arm.S
index 32d8629..809fcb9 100644
--- a/src/pkg/runtime/cgo/gcc_arm.S
+++ b/src/pkg/runtime/cgo/gcc_arm.S
@@ -1 +1,36 @@
-/* unimplemented */
+// 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.
+
+/*
+ * Apple still insists on underscore prefixes for C function names.
+ */
+#if defined(__APPLE__)
+#define EXT(s) _##s
+#else
+#define EXT(s) s
+#endif
+
+/*
+ * void crosscall_arm2(void (*fn)(void), void *g, void *m)
+ *
+ * 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):
+	push {r4, r5, r6, r7, r8, r9, r10, r11, ip, lr}
+	mov r10, r1 // g
+	mov r9, r2 // m
+	mov r3, r0 // save r0, cgo_tls_set_gm will clobber it
+	bl EXT(x_cgo_save_gm) // save current g and m into TLS variable
+	mov lr, pc
+	mov pc, r3
+	pop {r4, r5, r6, r7, r8, r9, r10, r11, ip, pc}
+
+.globl EXT(__stack_chk_fail_local)
+EXT(__stack_chk_fail_local):
+1:
+	b 1b
+
diff --git a/src/pkg/runtime/cgo/gcc_darwin_386.c b/src/pkg/runtime/cgo/gcc_darwin_386.c
index 2c30c66..ad9fb5a 100644
--- a/src/pkg/runtime/cgo/gcc_darwin_386.c
+++ b/src/pkg/runtime/cgo/gcc_darwin_386.c
@@ -101,8 +101,8 @@ inittls(void)
 		pthread_key_delete(tofree[i]);
 }
 
-static void
-xinitcgo(G *g)
+void
+x_cgo_init(G *g)
 {
 	pthread_attr_t attr;
 	size_t size;
@@ -115,10 +115,9 @@ xinitcgo(G *g)
 	inittls();
 }
 
-void (*initcgo)(G*) = xinitcgo;
 
 void
-libcgo_sys_thread_start(ThreadStart *ts)
+_cgo_sys_thread_start(ThreadStart *ts)
 {
 	pthread_attr_t attr;
 	sigset_t ign, oset;
@@ -127,14 +126,14 @@ libcgo_sys_thread_start(ThreadStart *ts)
 	int err;
 
 	sigfillset(&ign);
-	sigprocmask(SIG_SETMASK, &ign, &oset);
+	pthread_sigmask(SIG_SETMASK, &ign, &oset);
 
 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	ts->g->stackguard = size;
 	err = pthread_create(&p, &attr, threadentry, ts);
 
-	sigprocmask(SIG_SETMASK, &oset, nil);
+	pthread_sigmask(SIG_SETMASK, &oset, nil);
 
 	if (err != 0) {
 		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
@@ -153,7 +152,7 @@ threadentry(void *v)
 	ts.g->stackbase = (uintptr)&ts;
 
 	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * _cgo_sys_thread_start set stackguard to stack size;
 	 * change to actual guard pointer.
 	 */
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
diff --git a/src/pkg/runtime/cgo/gcc_darwin_amd64.c b/src/pkg/runtime/cgo/gcc_darwin_amd64.c
index 89dc7a4..65d3816 100644
--- a/src/pkg/runtime/cgo/gcc_darwin_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_darwin_amd64.c
@@ -72,7 +72,7 @@ inittls(void)
 }
 
 void
-xinitcgo(G *g)
+x_cgo_init(G *g)
 {
 	pthread_attr_t attr;
 	size_t size;
@@ -85,10 +85,9 @@ xinitcgo(G *g)
 	inittls();
 }
 
-void (*initcgo)(G*) = xinitcgo;
 
 void
-libcgo_sys_thread_start(ThreadStart *ts)
+_cgo_sys_thread_start(ThreadStart *ts)
 {
 	pthread_attr_t attr;
 	sigset_t ign, oset;
@@ -97,14 +96,14 @@ libcgo_sys_thread_start(ThreadStart *ts)
 	int err;
 
 	sigfillset(&ign);
-	sigprocmask(SIG_SETMASK, &ign, &oset);
+	pthread_sigmask(SIG_SETMASK, &ign, &oset);
 
 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	ts->g->stackguard = size;
 	err = pthread_create(&p, &attr, threadentry, ts);
 
-	sigprocmask(SIG_SETMASK, &oset, nil);
+	pthread_sigmask(SIG_SETMASK, &oset, nil);
 
 	if (err != 0) {
 		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
@@ -123,7 +122,7 @@ threadentry(void *v)
 	ts.g->stackbase = (uintptr)&ts;
 
 	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * _cgo_sys_thread_start set stackguard to stack size;
 	 * change to actual guard pointer.
 	 */
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_386.c b/src/pkg/runtime/cgo/gcc_freebsd_386.c
index 2c97e2a..7c62a1b 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_386.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_386.c
@@ -6,12 +6,13 @@
 #include <sys/signalvar.h>
 #include <pthread.h>
 #include <signal.h>
+#include <string.h>
 #include "libcgo.h"
 
 static void* threadentry(void*);
 
-static void
-xinitcgo(G *g)
+void
+x_cgo_init(G *g)
 {
 	pthread_attr_t attr;
 	size_t size;
@@ -22,10 +23,9 @@ xinitcgo(G *g)
 	pthread_attr_destroy(&attr);
 }
 
-void (*initcgo)(G*) = xinitcgo;
 
 void
-libcgo_sys_thread_start(ThreadStart *ts)
+_cgo_sys_thread_start(ThreadStart *ts)
 {
 	pthread_attr_t attr;
 	sigset_t ign, oset;
@@ -60,7 +60,7 @@ threadentry(void *v)
 	ts.g->stackbase = (uintptr)&ts;
 
 	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * _cgo_sys_thread_start set stackguard to stack size;
 	 * change to actual guard pointer.
 	 */
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_amd64.c b/src/pkg/runtime/cgo/gcc_freebsd_amd64.c
index 3beb4d7..6be8bd2 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_amd64.c
@@ -6,12 +6,13 @@
 #include <sys/signalvar.h>
 #include <pthread.h>
 #include <signal.h>
+#include <string.h>
 #include "libcgo.h"
 
 static void* threadentry(void*);
 
-static void
-xinitcgo(G *g)
+void
+x_cgo_init(G *g)
 {
 	pthread_attr_t attr;
 	size_t size;
@@ -22,10 +23,9 @@ xinitcgo(G *g)
 	pthread_attr_destroy(&attr);
 }
 
-void (*initcgo)(G*) = xinitcgo;
 
 void
-libcgo_sys_thread_start(ThreadStart *ts)
+_cgo_sys_thread_start(ThreadStart *ts)
 {
 	pthread_attr_t attr;
 	sigset_t ign, oset;
@@ -61,7 +61,7 @@ threadentry(void *v)
 	ts.g->stackbase = (uintptr)&ts;
 
 	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * _cgo_sys_thread_start set stackguard to stack size;
 	 * change to actual guard pointer.
 	 */
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_arm.c b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
new file mode 100644
index 0000000..3bcb0b2
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
@@ -0,0 +1,114 @@
+// 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 <pthread.h>
+#include <string.h>
+#include "libcgo.h"
+
+static void *threadentry(void*);
+
+// 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.
+void __aeabi_read_tp(void) __attribute__((naked));
+void x_cgo_save_gm(void) __attribute__((naked));
+void x_cgo_load_gm(void) __attribute__((naked));
+
+void
+__aeabi_read_tp(void)
+{
+	// read @ 0xffff1000
+	__asm__ __volatile__ (
+		"ldr r0, =0xffff1000\n\t"
+		"ldr r0, [r0]\n\t"
+		"mov pc, lr\n\t"
+	);
+}
+
+// g (R10) at 8(TP), m (R9) at 12(TP)
+void
+x_cgo_load_gm(void)
+{
+	__asm__ __volatile__ (
+		"push {lr}\n\t"
+		"bl __aeabi_read_tp\n\t"
+		"ldr r10, [r0, #8]\n\t"
+		"ldr r9, [r0, #12]\n\t"
+		"pop {pc}\n\t"
+	);
+}
+
+void
+x_cgo_save_gm(void)
+{
+	__asm__ __volatile__ (
+		"push {lr}\n\t"
+		"bl __aeabi_read_tp\n\t"
+		"str r10, [r0, #8]\n\t"
+		"str r9, [r0, #12]\n\t"
+		"pop {pc}\n\t"
+	);
+}
+
+void
+x_cgo_init(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+	x_cgo_save_gm(); // save g and m for the initial thread
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+}
+
+
+void
+_cgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	// Not sure why the memset is necessary here,
+	// but without it, we get a bogus stack size
+	// out of pthread_attr_getstacksize.  C'est la Linux.
+	memset(&attr, 0, sizeof attr);
+	pthread_attr_init(&attr);
+	size = 0;
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+extern void crosscall_arm2(void (*fn)(void), void *g, void *m);
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	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, (void *)ts.g, (void *)ts.m);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_linux_386.c b/src/pkg/runtime/cgo/gcc_linux_386.c
index 7d84acc..9357a63 100644
--- a/src/pkg/runtime/cgo/gcc_linux_386.c
+++ b/src/pkg/runtime/cgo/gcc_linux_386.c
@@ -9,8 +9,8 @@
 
 static void *threadentry(void*);
 
-static void
-xinitcgo(G *g)
+void
+x_cgo_init(G *g)
 {
 	pthread_attr_t attr;
 	size_t size;
@@ -21,10 +21,9 @@ xinitcgo(G *g)
 	pthread_attr_destroy(&attr);
 }
 
-void (*initcgo)(G*) = xinitcgo;
 
 void
-libcgo_sys_thread_start(ThreadStart *ts)
+_cgo_sys_thread_start(ThreadStart *ts)
 {
 	pthread_attr_t attr;
 	sigset_t ign, oset;
@@ -64,7 +63,7 @@ threadentry(void *v)
 	ts.g->stackbase = (uintptr)&ts;
 
 	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * _cgo_sys_thread_start set stackguard to stack size;
 	 * change to actual guard pointer.
 	 */
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
diff --git a/src/pkg/runtime/cgo/gcc_linux_amd64.c b/src/pkg/runtime/cgo/gcc_linux_amd64.c
index 28cbf78..bc76117 100644
--- a/src/pkg/runtime/cgo/gcc_linux_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_linux_amd64.c
@@ -10,7 +10,7 @@
 static void* threadentry(void*);
 
 void
-xinitcgo(G* g)
+x_cgo_init(G* g)
 {
 	pthread_attr_t attr;
 	size_t size;
@@ -21,10 +21,9 @@ xinitcgo(G* g)
 	pthread_attr_destroy(&attr);
 }
 
-void (*initcgo)(G*) = xinitcgo;
 
 void
-libcgo_sys_thread_start(ThreadStart *ts)
+_cgo_sys_thread_start(ThreadStart *ts)
 {
 	pthread_attr_t attr;
 	sigset_t ign, oset;
@@ -59,7 +58,7 @@ threadentry(void *v)
 	ts.g->stackbase = (uintptr)&ts;
 
 	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * _cgo_sys_thread_start set stackguard to stack size;
 	 * change to actual guard pointer.
 	 */
 	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
diff --git a/src/pkg/runtime/cgo/gcc_linux_arm.c b/src/pkg/runtime/cgo/gcc_linux_arm.c
index 8397c75..46a1126 100644
--- a/src/pkg/runtime/cgo/gcc_linux_arm.c
+++ b/src/pkg/runtime/cgo/gcc_linux_arm.c
@@ -2,19 +2,113 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+#include <pthread.h>
+#include <string.h>
 #include "libcgo.h"
 
-static void
-xinitcgo(G *g)
+static void *threadentry(void*);
+
+// 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.
+void __aeabi_read_tp(void) __attribute__((naked));
+void x_cgo_save_gm(void) __attribute__((naked));
+void x_cgo_load_gm(void) __attribute__((naked));
+
+void
+__aeabi_read_tp(void)
+{
+	// b __kuser_get_tls @ 0xffff0fe0
+	__asm__ __volatile__ (
+		"mvn r0, #0xf000\n\t"
+		"sub pc, r0, #31\n\t"
+		"nop\n\tnop\n\t"
+	);
+}
+
+// g (R10) at 8(TP), m (R9) at 12(TP)
+void
+x_cgo_load_gm(void)
+{
+	__asm__ __volatile__ (
+		"push {lr}\n\t"
+		"bl __aeabi_read_tp\n\t"
+		"ldr r10, [r0, #8]\n\t"
+		"ldr r9, [r0, #12]\n\t"
+		"pop {pc}\n\t"
+	);
+}
+
+void
+x_cgo_save_gm(void)
+{
+	__asm__ __volatile__ (
+		"push {lr}\n\t"
+		"bl __aeabi_read_tp\n\t"
+		"str r10, [r0, #8]\n\t"
+		"str r9, [r0, #12]\n\t"
+		"pop {pc}\n\t"
+	);
+}
+
+void
+x_cgo_init(G *g)
 {
-	// unimplemented
+	pthread_attr_t attr;
+	size_t size;
+	x_cgo_save_gm(); // save g and m for the initial thread
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
 }
 
-void (*initcgo)(G*) = xinitcgo;
 
 void
-libcgo_sys_thread_start(ThreadStart *ts)
+_cgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	// Not sure why the memset is necessary here,
+	// but without it, we get a bogus stack size
+	// out of pthread_attr_getstacksize.  C'est la Linux.
+	memset(&attr, 0, sizeof attr);
+	pthread_attr_init(&attr);
+	size = 0;
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+extern void crosscall_arm2(void (*fn)(void), void *g, void *m);
+static void*
+threadentry(void *v)
 {
-	// unimplemented
-	*(int*)0 = 0;
+	ThreadStart ts;
+
+	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, (void *)ts.g, (void *)ts.m);
+	return nil;
 }
diff --git a/src/pkg/runtime/cgo/gcc_netbsd_386.c b/src/pkg/runtime/cgo/gcc_netbsd_386.c
new file mode 100644
index 0000000..09b271d
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_netbsd_386.c
@@ -0,0 +1,80 @@
+// 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 <sys/types.h>
+#include <pthread.h>
+#include <signal.h>
+#include <string.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+
+void
+x_cgo_init(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+}
+
+
+void
+_cgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	sigset_t ign, oset;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	sigfillset(&ign);
+	sigprocmask(SIG_SETMASK, &ign, &oset);
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+
+	sigprocmask(SIG_SETMASK, &oset, nil);
+
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	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.  On NetBSD/ELF, the thread local storage
+	 * is just before %gs:0.  Our dynamic 8.out's reserve 8 bytes
+	 * for the two words g and m at %gs:-8 and %gs:-4.
+	 */
+	asm volatile (
+		"movl %0, %%gs:-8\n"	// MOVL g, -8(GS)
+		"movl %1, %%gs:-4\n"	// MOVL m, -4(GS)
+		:: "r"(ts.g), "r"(ts.m)
+	);
+
+	crosscall_386(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_netbsd_amd64.c b/src/pkg/runtime/cgo/gcc_netbsd_amd64.c
new file mode 100644
index 0000000..080c59b
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_netbsd_amd64.c
@@ -0,0 +1,80 @@
+// 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 <sys/types.h>
+#include <pthread.h>
+#include <signal.h>
+#include <string.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+
+void
+x_cgo_init(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+}
+
+
+void
+_cgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	sigset_t ign, oset;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	sigfillset(&ign);
+	sigprocmask(SIG_SETMASK, &ign, &oset);
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+
+	sigprocmask(SIG_SETMASK, &oset, nil);
+
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	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.  On NetBSD/ELF, the thread local storage
+	 * is just before %fs:0.  Our dynamic 6.out's reserve 16 bytes
+	 * for the two words g and m at %fs:-16 and %fs:-8.
+	 */
+	asm volatile (
+		"movq %0, %%fs:-16\n"	// MOVL g, -16(FS)
+		"movq %1, %%fs:-8\n"	// MOVL m, -8(FS)
+		:: "r"(ts.g), "r"(ts.m)
+	);
+	crosscall_amd64(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_netbsd_arm.c b/src/pkg/runtime/cgo/gcc_netbsd_arm.c
new file mode 100644
index 0000000..d93b531
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_netbsd_arm.c
@@ -0,0 +1,122 @@
+// 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 <sys/types.h>
+#include <pthread.h>
+#include <signal.h>
+#include <string.h>
+#include "libcgo.h"
+
+static void *threadentry(void*);
+
+// 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.
+void __aeabi_read_tp(void) __attribute__((naked));
+void x_cgo_save_gm(void) __attribute__((naked));
+void x_cgo_load_gm(void) __attribute__((naked));
+
+void
+__aeabi_read_tp(void)
+{
+	// this function is only allowed to clobber r0
+	__asm__ __volatile__ (
+		"mrc p15, 0, r0, c13, c0, 3\n\t"
+		"cmp r0, #0\n\t"
+		"movne pc, lr\n\t"
+		"push {r1,r2,r3,r12}\n\t"
+		"svc 0x00a0013c\n\t" // _lwp_getprivate
+		"pop {r1,r2,r3,r12}\n\t"
+		"mov pc, lr\n\t"
+	);
+}
+
+// g (R10) at 8(TP), m (R9) at 12(TP)
+void
+x_cgo_load_gm(void)
+{
+	__asm__ __volatile__ (
+		"push {lr}\n\t"
+		"bl __aeabi_read_tp\n\t"
+		"ldr r10, [r0, #8]\n\t"
+		"ldr r9, [r0, #12]\n\t"
+		"pop {pc}\n\t"
+	);
+}
+
+void
+x_cgo_save_gm(void)
+{
+	__asm__ __volatile__ (
+		"push {lr}\n\t"
+		"bl __aeabi_read_tp\n\t"
+		"str r10, [r0, #8]\n\t"
+		"str r9, [r0, #12]\n\t"
+		"pop {pc}\n\t"
+	);
+}
+
+void
+x_cgo_init(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+	x_cgo_save_gm(); // save g and m for the initial thread
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+}
+
+
+void
+_cgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	sigset_t ign, oset;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	sigfillset(&ign);
+	sigprocmask(SIG_SETMASK, &ign, &oset);
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+
+	sigprocmask(SIG_SETMASK, &oset, nil);
+
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+extern void crosscall_arm2(void (*fn)(void), void *g, void *m);
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	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, (void *)ts.g, (void *)ts.m);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_openbsd_386.c b/src/pkg/runtime/cgo/gcc_openbsd_386.c
new file mode 100644
index 0000000..86c1365
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_openbsd_386.c
@@ -0,0 +1,169 @@
+// 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 <sys/types.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <string.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+
+// TCB_SIZE is sizeof(struct thread_control_block),
+// as defined in /usr/src/lib/librthread/tcb.h
+#define TCB_SIZE (4 * sizeof(void *))
+#define TLS_SIZE (2 * sizeof(void *))
+
+void *__get_tcb(void);
+void __set_tcb(void *);
+
+static int (*sys_pthread_create)(pthread_t *thread, const pthread_attr_t *attr,
+	void *(*start_routine)(void *), void *arg);
+
+struct thread_args {
+	void *(*func)(void *);
+	void *arg;
+};
+
+static void
+tcb_fixup(int mainthread)
+{
+	void *newtcb, *oldtcb;
+
+	// The OpenBSD ld.so(1) does not currently support PT_TLS. As a result,
+	// we need to allocate our own TLS space while preserving the existing
+	// TCB that has been setup via librthread.
+
+	newtcb = malloc(TCB_SIZE + TLS_SIZE);
+	if(newtcb == NULL)
+		abort();
+
+	// The signal trampoline expects the TLS slots to be zeroed.
+	bzero(newtcb, TLS_SIZE);
+
+	oldtcb = __get_tcb();
+	bcopy(oldtcb, newtcb + TLS_SIZE, TCB_SIZE);
+	__set_tcb(newtcb + TLS_SIZE);
+
+	// The main thread TCB is a static allocation - do not try to free it.
+	if(!mainthread)
+		free(oldtcb);
+}
+
+static void *
+thread_start_wrapper(void *arg)
+{
+	struct thread_args args = *(struct thread_args *)arg;
+
+	free(arg);
+	tcb_fixup(0);
+
+	return args.func(args.arg);
+}
+
+int
+pthread_create(pthread_t *thread, const pthread_attr_t *attr,
+	void *(*start_routine)(void *), void *arg)
+{
+	struct thread_args *p;
+
+	p = malloc(sizeof(*p));
+	if(p == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
+	p->func = start_routine;
+	p->arg = arg;
+
+	return sys_pthread_create(thread, attr, thread_start_wrapper, p);
+}
+
+void
+x_cgo_init(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+	void *handle;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+
+	// Locate symbol for the system pthread_create function.
+	handle = dlopen("libpthread.so", RTLD_LAZY);
+	if(handle == NULL) {
+		fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror());
+		abort();
+	}
+	sys_pthread_create = dlsym(handle, "pthread_create");
+	if(sys_pthread_create == NULL) {
+		fprintf(stderr, "dlsym: failed to find pthread_create: %s\n", dlerror());
+		abort();
+	}
+	dlclose(handle);
+
+	tcb_fixup(1);
+}
+
+
+void
+_cgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	sigset_t ign, oset;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	sigfillset(&ign);
+	sigprocmask(SIG_SETMASK, &ign, &oset);
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = sys_pthread_create(&p, &attr, threadentry, ts);
+
+	sigprocmask(SIG_SETMASK, &oset, nil);
+
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	tcb_fixup(0);
+
+	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.  On OpenBSD/ELF, the thread local storage
+	 * is just before %gs:0.  Our dynamic 8.out's reserve 8 bytes
+	 * for the two words g and m at %gs:-8 and %gs:-4.
+	 */
+	asm volatile (
+		"movl %0, %%gs:-8\n"	// MOVL g, -8(GS)
+		"movl %1, %%gs:-4\n"	// MOVL m, -4(GS)
+		:: "r"(ts.g), "r"(ts.m)
+	);
+
+	crosscall_386(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_openbsd_amd64.c b/src/pkg/runtime/cgo/gcc_openbsd_amd64.c
new file mode 100644
index 0000000..d3a5e36
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_openbsd_amd64.c
@@ -0,0 +1,169 @@
+// 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 <sys/types.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <string.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+
+// TCB_SIZE is sizeof(struct thread_control_block),
+// as defined in /usr/src/lib/librthread/tcb.h
+#define TCB_SIZE (4 * sizeof(void *))
+#define TLS_SIZE (2 * sizeof(void *))
+
+void *__get_tcb(void);
+void __set_tcb(void *);
+
+static int (*sys_pthread_create)(pthread_t *thread, const pthread_attr_t *attr,
+	void *(*start_routine)(void *), void *arg);
+
+struct thread_args {
+	void *(*func)(void *);
+	void *arg;
+};
+
+static void
+tcb_fixup(int mainthread)
+{
+	void *newtcb, *oldtcb;
+
+	// The OpenBSD ld.so(1) does not currently support PT_TLS. As a result,
+	// we need to allocate our own TLS space while preserving the existing
+	// TCB that has been setup via librthread.
+
+	newtcb = malloc(TCB_SIZE + TLS_SIZE);
+	if(newtcb == NULL)
+		abort();
+
+	// The signal trampoline expects the TLS slots to be zeroed.
+	bzero(newtcb, TLS_SIZE);
+
+	oldtcb = __get_tcb();
+	bcopy(oldtcb, newtcb + TLS_SIZE, TCB_SIZE);
+	__set_tcb(newtcb + TLS_SIZE);
+
+	// The main thread TCB is a static allocation - do not try to free it.
+	if(!mainthread)
+		free(oldtcb);
+}
+
+static void *
+thread_start_wrapper(void *arg)
+{
+	struct thread_args args = *(struct thread_args *)arg;
+
+	free(arg);
+	tcb_fixup(0);
+
+	return args.func(args.arg);
+}
+
+int
+pthread_create(pthread_t *thread, const pthread_attr_t *attr,
+	void *(*start_routine)(void *), void *arg)
+{
+	struct thread_args *p;
+
+	p = malloc(sizeof(*p));
+	if(p == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
+	p->func = start_routine;
+	p->arg = arg;
+
+	return sys_pthread_create(thread, attr, thread_start_wrapper, p);
+}
+
+void
+x_cgo_init(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+	void *handle;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+
+	// Locate symbol for the system pthread_create function.
+	handle = dlopen("libpthread.so", RTLD_LAZY);
+	if(handle == NULL) {
+		fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror());
+		abort();
+	}
+	sys_pthread_create = dlsym(handle, "pthread_create");
+	if(sys_pthread_create == NULL) {
+		fprintf(stderr, "dlsym: failed to find pthread_create: %s\n", dlerror());
+		abort();
+	}
+	dlclose(handle);
+
+	tcb_fixup(1);
+}
+
+
+void
+_cgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	sigset_t ign, oset;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	sigfillset(&ign);
+	sigprocmask(SIG_SETMASK, &ign, &oset);
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+
+	ts->g->stackguard = size;
+	err = sys_pthread_create(&p, &attr, threadentry, ts);
+
+	sigprocmask(SIG_SETMASK, &oset, nil);
+
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	tcb_fixup(0);
+
+	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.  On OpenBSD/ELF, the thread local storage
+	 * is just before %fs:0.  Our dynamic 6.out's reserve 16 bytes
+	 * for the two words g and m at %fs:-16 and %fs:-8.
+	 */
+	asm volatile (
+		"movq %0, %%fs:-16\n"	// MOVL g, -16(FS)
+		"movq %1, %%fs:-8\n"	// MOVL m, -8(FS)
+		:: "r"(ts.g), "r"(ts.m)
+	);
+	crosscall_amd64(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_setenv.c b/src/pkg/runtime/cgo/gcc_setenv.c
index 7da4ad9..a093816 100644
--- a/src/pkg/runtime/cgo/gcc_setenv.c
+++ b/src/pkg/runtime/cgo/gcc_setenv.c
@@ -1,4 +1,4 @@
-// Copyright 20111 The Go Authors.  All rights reserved.
+// 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.
 
@@ -9,10 +9,8 @@
 #include <stdlib.h>
 
 /* Stub for calling setenv */
-static void
-xlibcgo_setenv(char **arg)
+void
+x_cgo_setenv(char **arg)
 {
 	setenv(arg[0], arg[1], 1);
 }
-
-void (*libcgo_setenv)(char**) = xlibcgo_setenv;
diff --git a/src/pkg/runtime/cgo/gcc_util.c b/src/pkg/runtime/cgo/gcc_util.c
index e06b6f6..20913d7 100644
--- a/src/pkg/runtime/cgo/gcc_util.c
+++ b/src/pkg/runtime/cgo/gcc_util.c
@@ -5,7 +5,7 @@
 #include "libcgo.h"
 
 /* Stub for calling malloc from Go */
-static void
+void
 x_cgo_malloc(void *p)
 {
 	struct a {
@@ -16,10 +16,8 @@ x_cgo_malloc(void *p)
 	a->ret = malloc(a->n);
 }
 
-void (*_cgo_malloc)(void*) = x_cgo_malloc;
-
 /* Stub for calling free from Go */
-static void
+void
 x_cgo_free(void *p)
 {
 	struct a {
@@ -29,11 +27,9 @@ x_cgo_free(void *p)
 	free(a->arg);
 }
 
-void (*_cgo_free)(void*) = x_cgo_free;
-
 /* Stub for creating a new thread */
-static void
-xlibcgo_thread_start(ThreadStart *arg)
+void
+x_cgo_thread_start(ThreadStart *arg)
 {
 	ThreadStart *ts;
 
@@ -45,7 +41,5 @@ xlibcgo_thread_start(ThreadStart *arg)
 	}
 	*ts = *arg;
 
-	libcgo_sys_thread_start(ts);	/* OS-dependent half */
+	_cgo_sys_thread_start(ts);	/* OS-dependent half */
 }
-
-void (*libcgo_thread_start)(ThreadStart*) = xlibcgo_thread_start;
diff --git a/src/pkg/runtime/cgo/gcc_windows_386.c b/src/pkg/runtime/cgo/gcc_windows_386.c
index 2b940d3..02eab12 100644
--- a/src/pkg/runtime/cgo/gcc_windows_386.c
+++ b/src/pkg/runtime/cgo/gcc_windows_386.c
@@ -4,31 +4,31 @@
 
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
+#include <process.h>
 #include "libcgo.h"
 
-static void *threadentry(void*);
+static void threadentry(void*);
 
 /* 1MB is default stack size for 32-bit Windows.
    Allocation granularity on Windows is typically 64 KB.
    The constant is also hardcoded in cmd/ld/pe.c (keep synchronized). */
 #define STACKSIZE (1*1024*1024)
 
-static void
-xinitcgo(G *g)
+void
+x_cgo_init(G *g)
 {
 	int tmp;
 	g->stackguard = (uintptr)&tmp - STACKSIZE + 8*1024;
 }
 
-void (*initcgo)(G*) = xinitcgo;
 
 void
-libcgo_sys_thread_start(ThreadStart *ts)
+_cgo_sys_thread_start(ThreadStart *ts)
 {
 	_beginthread(threadentry, 0, ts);
 }
 
-static void*
+static void
 threadentry(void *v)
 {
 	ThreadStart ts;
@@ -55,5 +55,4 @@ threadentry(void *v)
 	crosscall_386(ts.fn);
 	
 	LocalFree(tls0);
-	return nil;
 }
diff --git a/src/pkg/runtime/cgo/gcc_windows_amd64.c b/src/pkg/runtime/cgo/gcc_windows_amd64.c
index 0d2f5d2..f7695a1 100644
--- a/src/pkg/runtime/cgo/gcc_windows_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_windows_amd64.c
@@ -4,31 +4,31 @@
 
 #define WIN64_LEAN_AND_MEAN
 #include <windows.h>
+#include <process.h>
 #include "libcgo.h"
 
-static void *threadentry(void*);
+static void threadentry(void*);
 
 /* 2MB is default stack size for 64-bit Windows.
    Allocation granularity on Windows is typically 64 KB.
    The constant is also hardcoded in cmd/ld/pe.c (keep synchronized). */
 #define STACKSIZE (2*1024*1024)
 
-static void
-xinitcgo(G *g)
+void
+x_cgo_init(G *g)
 {
 	int tmp;
 	g->stackguard = (uintptr)&tmp - STACKSIZE + 8*1024;
 }
 
-void (*initcgo)(G*) = xinitcgo;
 
 void
-libcgo_sys_thread_start(ThreadStart *ts)
+_cgo_sys_thread_start(ThreadStart *ts)
 {
 	_beginthread(threadentry, 0, ts);
 }
 
-static void*
+static void
 threadentry(void *v)
 {
 	ThreadStart ts;
@@ -53,5 +53,4 @@ threadentry(void *v)
 	);
 
 	crosscall_amd64(ts.fn);
-	return nil;
 }
diff --git a/src/pkg/runtime/cgo/libcgo.h b/src/pkg/runtime/cgo/libcgo.h
index c31d19d..41a371c 100644
--- a/src/pkg/runtime/cgo/libcgo.h
+++ b/src/pkg/runtime/cgo/libcgo.h
@@ -26,7 +26,7 @@ struct G
 };
 
 /*
- * Arguments to the libcgo_thread_start call.
+ * Arguments to the _cgo_thread_start call.
  * Also known to ../pkg/runtime/runtime.h.
  */
 typedef struct ThreadStart ThreadStart;
@@ -40,14 +40,14 @@ struct ThreadStart
 /*
  * Called by 5c/6c/8c world.
  * Makes a local copy of the ThreadStart and
- * calls libcgo_sys_thread_start(ts).
+ * calls _cgo_sys_thread_start(ts).
  */
-extern void (*libcgo_thread_start)(ThreadStart *ts);
+extern void (*_cgo_thread_start)(ThreadStart *ts);
 
 /*
  * Creates the new operating system thread (OS, arch dependent).
  */
-void libcgo_sys_thread_start(ThreadStart *ts);
+void _cgo_sys_thread_start(ThreadStart *ts);
 
 /*
  * Call fn in the 6c world.
diff --git a/src/pkg/runtime/cgo/netbsd.c b/src/pkg/runtime/cgo/netbsd.c
new file mode 100644
index 0000000..b6403f6
--- /dev/null
+++ b/src/pkg/runtime/cgo/netbsd.c
@@ -0,0 +1,13 @@
+// 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.
+
+// Supply environ and __progname, because we don't
+// link against the standard NetBSD crt0.o and the
+// libc dynamic library needs them.
+
+char *environ[1];
+char *__progname;
+
+#pragma dynexport environ environ
+#pragma dynexport __progname __progname
diff --git a/src/pkg/runtime/cgo/openbsd.c b/src/pkg/runtime/cgo/openbsd.c
new file mode 100644
index 0000000..84e9f9e
--- /dev/null
+++ b/src/pkg/runtime/cgo/openbsd.c
@@ -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.
+
+// Supply environ, __progname and __guard_local, because
+// we don't link against the standard OpenBSD crt0.o and
+// the libc dynamic library needs them.
+
+char *environ[1];
+char *__progname;
+long __guard_local;
+
+#pragma dynexport environ environ
+#pragma dynexport __progname __progname
+
+// This is normally marked as hidden and placed in the
+// .openbsd.randomdata section.
+#pragma dynexport __guard_local __guard_local
+
+// We override pthread_create to support PT_TLS.
+#pragma dynexport pthread_create pthread_create
diff --git a/src/pkg/runtime/cgo/setenv.c b/src/pkg/runtime/cgo/setenv.c
new file mode 100644
index 0000000..4c47cdb
--- /dev/null
+++ b/src/pkg/runtime/cgo/setenv.c
@@ -0,0 +1,10 @@
+// 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 freebsd linux netbsd openbsd
+
+#pragma cgo_import_static x_cgo_setenv
+
+void x_cgo_setenv(char**);
+void (*_cgo_setenv)(char**) = x_cgo_setenv;
diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c
index 7a26538..590bf9b 100644
--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -6,6 +6,7 @@
 #include "arch_GOARCH.h"
 #include "stack.h"
 #include "cgocall.h"
+#include "race.h"
 
 // Cgo call and callback support.
 //
@@ -41,7 +42,7 @@
 // know about packages).  The gcc-compiled C function f calls GoF.
 //
 // GoF calls crosscall2(_cgoexp_GoF, frame, framesize).  Crosscall2
-// (in cgo/$GOOS.S, a gcc-compiled assembly file) is a two-argument
+// (in cgo/gcc_$GOARCH.S, a gcc-compiled assembly file) is a two-argument
 // adapter from the gcc function call ABI to the 6c function call ABI.
 // It is called from gcc to call 6c functions.  In this case it calls
 // _cgoexp_GoF(frame, framesize), still running on m->g0's stack
@@ -82,43 +83,55 @@
 // _cgoexp_GoF immediately returns to crosscall2, which restores the
 // callee-save registers for gcc and returns to GoF, which returns to f.
 
-void *initcgo;	/* filled in by dynamic linker when Cgo is available */
+void *_cgo_init;	/* filled in by dynamic linker when Cgo is available */
+static int64 cgosync;  /* represents possible synchronization in C code */
+
+// These two are only used by the architecture where TLS based storage isn't
+// the default for g and m (e.g., ARM)
+void *_cgo_load_gm; /* filled in by dynamic linker when Cgo is available */
+void *_cgo_save_gm; /* filled in by dynamic linker when Cgo is available */
 
-static void unlockm(void);
 static void unwindm(void);
 
 // Call from Go to C.
 
+static FuncVal unlockOSThread = { runtime·unlockOSThread };
+
 void
 runtime·cgocall(void (*fn)(void*), void *arg)
 {
 	Defer d;
 
+	if(m->racecall) {
+		runtime·asmcgocall(fn, arg);
+		return;
+	}
+
 	if(!runtime·iscgo && !Windows)
 		runtime·throw("cgocall unavailable");
 
 	if(fn == 0)
 		runtime·throw("cgocall nil");
 
+	if(raceenabled)
+		runtime·racereleasemerge(&cgosync);
+
 	m->ncgocall++;
 
 	/*
 	 * Lock g to m to ensure we stay on the same stack if we do a
-	 * cgo callback.
+	 * cgo callback. Add entry to defer stack in case of panic.
 	 */
-	d.nofree = false;
-	if(m->lockedg == nil) {
-		m->lockedg = g;
-		g->lockedm = m;
-
-		// Add entry to defer stack in case of panic.
-		d.fn = (byte*)unlockm;
-		d.siz = 0;
-		d.link = g->defer;
-		d.argp = (void*)-1;  // unused because unlockm never recovers
-		d.nofree = true;
-		g->defer = &d;
-	}
+	runtime·lockOSThread();
+	d.fn = &unlockOSThread;
+	d.siz = 0;
+	d.link = g->defer;
+	d.argp = (void*)-1;  // unused because unlockm never recovers
+	d.special = true;
+	d.free = false;
+	g->defer = &d;
+
+	m->ncgo++;
 
 	/*
 	 * Announce we are entering a system call
@@ -135,29 +148,31 @@ runtime·cgocall(void (*fn)(void*), void *arg)
 	runtime·asmcgocall(fn, arg);
 	runtime·exitsyscall();
 
-	if(d.nofree) {
-		if(g->defer != &d || d.fn != (byte*)unlockm)
-			runtime·throw("runtime: bad defer entry in cgocallback");
-		g->defer = d.link;
-		unlockm();
+	m->ncgo--;
+	if(m->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;
 	}
-}
 
-static void
-unlockm(void)
-{
-	m->lockedg = nil;
-	g->lockedm = nil;
+	if(g->defer != &d || d.fn != &unlockOSThread)
+		runtime·throw("runtime: bad defer entry in cgocallback");
+	g->defer = d.link;
+	runtime·unlockOSThread();
+
+	if(raceenabled)
+		runtime·raceacquire(&cgosync);
 }
 
 void
 runtime·NumCgoCall(int64 ret)
 {
-	M *m;
+	M *mp;
 
 	ret = 0;
-	for(m=runtime·atomicloadp(&runtime·allm); m; m=m->alllink)
-		ret += m->ncgocall;
+	for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink)
+		ret += mp->ncgocall;
 	FLUSH(&ret);
 }
 
@@ -188,31 +203,50 @@ runtime·cfree(void *p)
 
 // Call from C back to Go.
 
+static FuncVal unwindmf = {unwindm};
+
 void
-runtime·cgocallbackg(void (*fn)(void), void *arg, uintptr argsize)
+runtime·cgocallbackg(FuncVal *fn, void *arg, uintptr argsize)
 {
 	Defer d;
 
+	if(m->racecall) {
+		reflect·call(fn, arg, argsize);
+		return;
+	}
+
 	if(g != m->curg)
 		runtime·throw("runtime: bad g in cgocallback");
 
 	runtime·exitsyscall();	// coming out of cgo call
 
+	if(m->needextram) {
+		m->needextram = 0;
+		runtime·newextram();
+	}
+
 	// Add entry to defer stack in case of panic.
-	d.fn = (byte*)unwindm;
+	d.fn = &unwindmf;
 	d.siz = 0;
 	d.link = g->defer;
 	d.argp = (void*)-1;  // unused because unwindm never recovers
-	d.nofree = true;
+	d.special = true;
+	d.free = false;
 	g->defer = &d;
 
+	if(raceenabled)
+		runtime·raceacquire(&cgosync);
+
 	// Invoke callback.
-	reflect·call((byte*)fn, arg, argsize);
+	reflect·call(fn, arg, argsize);
+
+	if(raceenabled)
+		runtime·racereleasemerge(&cgosync);
 
 	// Pop defer.
 	// Do not unwind m->g0->sched.sp.
 	// Our caller, cgocallback, will do that.
-	if(g->defer != &d || d.fn != (byte*)unwindm)
+	if(g->defer != &d || d.fn != &unwindmf)
 		runtime·throw("runtime: bad defer entry in cgocallback");
 	g->defer = d.link;
 
@@ -229,7 +263,8 @@ unwindm(void)
 		runtime·throw("runtime: unwindm not implemented");
 	case '8':
 	case '6':
-		m->g0->sched.sp = *(void**)m->g0->sched.sp;
+	case '5':
+		m->g0->sched.sp = *(uintptr*)m->g0->sched.sp;
 		break;
 	}
 }
diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c
index ef27144..32995c6 100644
--- a/src/pkg/runtime/chan.c
+++ b/src/pkg/runtime/chan.c
@@ -3,7 +3,10 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "type.h"
+#include "race.h"
+#include "malloc.h"
 
 #define	MAXALIGN	7
 #define	NOSELGEN	1
@@ -20,6 +23,7 @@ struct	SudoG
 	G*	g;		// g and selgen constitute
 	uint32	selgen;		// a weak pointer to g
 	SudoG*	link;
+	int64	releasetime;
 	byte*	elem;		// data element
 };
 
@@ -29,21 +33,25 @@ struct	WaitQ
 	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
 {
-	uint32	qcount;			// total data in the q
-	uint32	dataqsiz;		// size of the circular q
+	uintgo	qcount;			// total data in the q
+	uintgo	dataqsiz;		// size of the circular q
 	uint16	elemsize;
 	bool	closed;
 	uint8	elemalign;
 	Alg*	elemalg;		// interface for element type
-	uint32	sendx;			// send index
-	uint32	recvx;			// receive index
+	uintgo	sendx;			// send index
+	uintgo	recvx;			// receive index
 	WaitQ	recvq;			// list of recv waiters
 	WaitQ	sendq;			// list of send waiters
 	Lock;
 };
 
+uint32 runtime·Hchansize = sizeof(Hchan);
+
 // 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))
@@ -79,17 +87,22 @@ static	void	dequeueg(WaitQ*);
 static	SudoG*	dequeue(WaitQ*);
 static	void	enqueue(WaitQ*, SudoG*);
 static	void	destroychan(Hchan*);
+static	void	racesync(Hchan*, SudoG*);
 
 Hchan*
 runtime·makechan_c(ChanType *t, int64 hint)
 {
 	Hchan *c;
-	int32 n;
+	uintptr n;
 	Type *elem;
-	
+
 	elem = t->elem;
 
-	if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size))
+	// compiler checks this but be safe.
+	if(elem->size >= (1<<16))
+		runtime·throw("makechan: invalid channel element type");
+
+	if(hint < 0 || (intgo)hint != hint || (elem->size > 0 && hint > MaxMem / elem->size))
 		runtime·panicstring("makechan: size out of range");
 
 	// calculate rounded size of Hchan
@@ -103,18 +116,19 @@ runtime·makechan_c(ChanType *t, int64 hint)
 	c->elemalg = elem->alg;
 	c->elemalign = elem->align;
 	c->dataqsiz = hint;
+	runtime·settype(c, (uintptr)t | TypeInfo_Chan);
 
 	if(debug)
-		runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; elemalign=%d; dataqsiz=%d\n",
-			c, (int64)elem->size, elem->alg, elem->align, c->dataqsiz);
+		runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; elemalign=%d; dataqsiz=%D\n",
+			c, (int64)elem->size, elem->alg, elem->align, (int64)c->dataqsiz);
 
 	return c;
 }
 
 // For reflect
-//	func makechan(typ *ChanType, size uint32) (chan)
+//	func makechan(typ *ChanType, size uint64) (chan)
 void
-reflect·makechan(ChanType *t, uint32 size, Hchan *c)
+reflect·makechan(ChanType *t, uint64 size, Hchan *c)
 {
 	c = runtime·makechan_c(t, size);
 	FLUSH(&c);
@@ -143,11 +157,12 @@ runtime·makechan(ChanType *t, int64 hint, Hchan *ret)
  * the operation; we'll see that it's now closed.
  */
 void
-runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
+runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres, void *pc)
 {
 	SudoG *sg;
 	SudoG mysg;
 	G* gp;
+	int64 t0;
 
 	if(c == nil) {
 		USED(t);
@@ -155,9 +170,7 @@ runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
 			*pres = false;
 			return;
 		}
-		g->status = Gwaiting;
-		g->waitreason = "chan send (nil chan)";
-		runtime·gosched();
+		runtime·park(nil, nil, "chan send (nil chan)");
 		return;  // not reached
 	}
 
@@ -170,7 +183,17 @@ runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
 		runtime·prints("\n");
 	}
 
+	t0 = 0;
+	mysg.releasetime = 0;
+	if(runtime·blockprofilerate > 0) {
+		t0 = runtime·cputicks();
+		mysg.releasetime = -1;
+	}
+
 	runtime·lock(c);
+	// TODO(dvyukov): add similar instrumentation to select.
+	if(raceenabled)
+		runtime·racereadpc(c, pc, runtime·chansend);
 	if(c->closed)
 		goto closed;
 
@@ -179,12 +202,16 @@ runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
 
 	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->elemalg->copy(c->elemsize, sg->elem, ep);
+		if(sg->releasetime)
+			sg->releasetime = runtime·cputicks();
 		runtime·ready(gp);
 
 		if(pres != nil)
@@ -202,11 +229,8 @@ runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
 	mysg.g = g;
 	mysg.selgen = NOSELGEN;
 	g->param = nil;
-	g->status = Gwaiting;
-	g->waitreason = "chan send";
 	enqueue(&c->sendq, &mysg);
-	runtime·unlock(c);
-	runtime·gosched();
+	runtime·park(runtime·unlock, c, "chan send");
 
 	if(g->param == nil) {
 		runtime·lock(c);
@@ -215,6 +239,9 @@ runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
 		goto closed;
 	}
 
+	if(mysg.releasetime > 0)
+		runtime·blockevent(mysg.releasetime - t0, 2);
+
 	return;
 
 asynch:
@@ -230,15 +257,16 @@ asynch:
 		mysg.g = g;
 		mysg.elem = nil;
 		mysg.selgen = NOSELGEN;
-		g->status = Gwaiting;
-		g->waitreason = "chan send";
 		enqueue(&c->sendq, &mysg);
-		runtime·unlock(c);
-		runtime·gosched();
+		runtime·park(runtime·unlock, c, "chan send");
 
 		runtime·lock(c);
 		goto asynch;
 	}
+
+	if(raceenabled)
+		runtime·racerelease(chanbuf(c, c->sendx));
+
 	c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), ep);
 	if(++c->sendx == c->dataqsiz)
 		c->sendx = 0;
@@ -248,11 +276,15 @@ asynch:
 	if(sg != nil) {
 		gp = sg->g;
 		runtime·unlock(c);
+		if(sg->releasetime)
+			sg->releasetime = runtime·cputicks();
 		runtime·ready(gp);
 	} else
 		runtime·unlock(c);
 	if(pres != nil)
 		*pres = true;
+	if(mysg.releasetime > 0)
+		runtime·blockevent(mysg.releasetime - t0, 2);
 	return;
 
 closed:
@@ -267,6 +299,7 @@ runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *receive
 	SudoG *sg;
 	SudoG mysg;
 	G *gp;
+	int64 t0;
 
 	if(runtime·gcwaiting)
 		runtime·gosched();
@@ -280,12 +313,17 @@ runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *receive
 			*selected = false;
 			return;
 		}
-		g->status = Gwaiting;
-		g->waitreason = "chan receive (nil chan)";
-		runtime·gosched();
+		runtime·park(nil, nil, "chan receive (nil chan)");
 		return;  // 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;
@@ -295,12 +333,16 @@ runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *receive
 
 	sg = dequeue(&c->sendq);
 	if(sg != nil) {
+		if(raceenabled)
+			racesync(c, sg);
 		runtime·unlock(c);
 
 		if(ep != nil)
 			c->elemalg->copy(c->elemsize, ep, sg->elem);
 		gp = sg->g;
 		gp->param = sg;
+		if(sg->releasetime)
+			sg->releasetime = runtime·cputicks();
 		runtime·ready(gp);
 
 		if(selected != nil)
@@ -320,11 +362,8 @@ runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *receive
 	mysg.g = g;
 	mysg.selgen = NOSELGEN;
 	g->param = nil;
-	g->status = Gwaiting;
-	g->waitreason = "chan receive";
 	enqueue(&c->recvq, &mysg);
-	runtime·unlock(c);
-	runtime·gosched();
+	runtime·park(runtime·unlock, c, "chan receive");
 
 	if(g->param == nil) {
 		runtime·lock(c);
@@ -335,6 +374,8 @@ runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *receive
 
 	if(received != nil)
 		*received = true;
+	if(mysg.releasetime > 0)
+		runtime·blockevent(mysg.releasetime - t0, 2);
 	return;
 
 asynch:
@@ -352,15 +393,16 @@ asynch:
 		mysg.g = g;
 		mysg.elem = nil;
 		mysg.selgen = NOSELGEN;
-		g->status = Gwaiting;
-		g->waitreason = "chan receive";
 		enqueue(&c->recvq, &mysg);
-		runtime·unlock(c);
-		runtime·gosched();
+		runtime·park(runtime·unlock, c, "chan receive");
 
 		runtime·lock(c);
 		goto asynch;
 	}
+
+	if(raceenabled)
+		runtime·raceacquire(chanbuf(c, c->recvx));
+
 	if(ep != nil)
 		c->elemalg->copy(c->elemsize, ep, chanbuf(c, c->recvx));
 	c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil);
@@ -372,6 +414,8 @@ asynch:
 	if(sg != nil) {
 		gp = sg->g;
 		runtime·unlock(c);
+		if(sg->releasetime)
+			sg->releasetime = runtime·cputicks();
 		runtime·ready(gp);
 	} else
 		runtime·unlock(c);
@@ -380,6 +424,8 @@ asynch:
 		*selected = true;
 	if(received != nil)
 		*received = true;
+	if(mysg.releasetime > 0)
+		runtime·blockevent(mysg.releasetime - t0, 2);
 	return;
 
 closed:
@@ -389,7 +435,11 @@ closed:
 		*selected = true;
 	if(received != nil)
 		*received = false;
+	if(raceenabled)
+		runtime·raceacquire(c);
 	runtime·unlock(c);
+	if(mysg.releasetime > 0)
+		runtime·blockevent(mysg.releasetime - t0, 2);
 }
 
 // chansend1(hchan *chan any, elem any);
@@ -397,7 +447,7 @@ closed:
 void
 runtime·chansend1(ChanType *t, Hchan* c, ...)
 {
-	runtime·chansend(t, c, (byte*)(&c+1), nil);
+	runtime·chansend(t, c, (byte*)(&c+1), nil, runtime·getcallerpc(&t));
 }
 
 // chanrecv1(hchan *chan any) (elem any);
@@ -446,8 +496,8 @@ runtime·selectnbsend(ChanType *t, Hchan *c, ...)
 	byte *ae, *ap;
 
 	ae = (byte*)(&c + 1);
-	ap = ae + runtime·rnd(t->elem->size, Structrnd);
-	runtime·chansend(t, c, ae, ap);
+	ap = ae + ROUND(t->elem->size, Structrnd);
+	runtime·chansend(t, c, ae, ap, runtime·getcallerpc(&t));
 }
 
 // func selectnbrecv(elem *any, c chan any) bool
@@ -474,7 +524,7 @@ void
 runtime·selectnbrecv(ChanType *t, byte *v, Hchan *c, bool selected)
 {
 	runtime·chanrecv(t, c, v, &selected, nil);
-}	
+}
 
 // func selectnbrecv2(elem *any, ok *bool, c chan any) bool
 //
@@ -500,7 +550,7 @@ void
 runtime·selectnbrecv2(ChanType *t, byte *v, bool *received, Hchan *c, bool selected)
 {
 	runtime·chanrecv(t, c, v, &selected, received);
-}	
+}
 
 // For reflect:
 //	func chansend(c chan, val iword, nb bool) (selected bool)
@@ -509,12 +559,13 @@ runtime·selectnbrecv2(ChanType *t, byte *v, bool *received, Hchan *c, bool sele
 //
 // The "uintptr selected" is really "bool selected" but saying
 // uintptr gets us the right alignment for the output parameter block.
+#pragma textflag 7
 void
 reflect·chansend(ChanType *t, Hchan *c, uintptr val, bool nb, uintptr selected)
 {
 	bool *sp;
 	byte *vp;
-	
+
 	if(nb) {
 		selected = false;
 		sp = (bool*)&selected;
@@ -527,7 +578,7 @@ reflect·chansend(ChanType *t, Hchan *c, uintptr val, bool nb, uintptr selected)
 		vp = (byte*)&val;
 	else
 		vp = (byte*)val;
-	runtime·chansend(t, c, vp, sp);
+	runtime·chansend(t, c, vp, sp, runtime·getcallerpc(&t));
 }
 
 // For reflect:
@@ -571,7 +622,7 @@ runtime·newselect(int32 size, ...)
 	int32 o;
 	Select **selp;
 
-	o = runtime·rnd(sizeof(size), Structrnd);
+	o = ROUND(sizeof(size), Structrnd);
 	selp = (Select**)((byte*)&size + o);
 	newselect(size, selp);
 }
@@ -619,7 +670,7 @@ runtime·selectsend(Select *sel, Hchan *c, void *elem, bool selected)
 	// nil cases do not compete
 	if(c == nil)
 		return;
-	
+
 	selectsend(sel, c, runtime·getcallerpc(&sel), elem, (byte*)&selected - (byte*)&sel);
 }
 
@@ -628,7 +679,7 @@ 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");
@@ -774,9 +825,7 @@ selunlock(Select *sel)
 void
 runtime·block(void)
 {
-	g->status = Gwaiting;	// forever
-	g->waitreason = "select (no cases)";
-	runtime·gosched();
+	runtime·park(nil, nil, "select (no cases)");	// forever
 }
 
 static void* selectgo(Select**);
@@ -796,7 +845,7 @@ static void*
 selectgo(Select **selp)
 {
 	Select *sel;
-	uint32 o, i, j;
+	uint32 o, i, j, k;
 	Scase *cas, *dfl;
 	Hchan *c;
 	SudoG *sg;
@@ -830,12 +879,42 @@ selectgo(Select **selp)
 	}
 
 	// 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++) {
-		c = sel->scase[i].chan;
-		for(j=i; j>0 && sel->lockorder[j-1] >= c; j--)
-			sel->lockorder[j] = sel->lockorder[j-1];
+		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:
@@ -899,7 +978,7 @@ loop:
 		case CaseRecv:
 			enqueue(&c->recvq, sg);
 			break;
-		
+
 		case CaseSend:
 			enqueue(&c->sendq, sg);
 			break;
@@ -907,10 +986,7 @@ loop:
 	}
 
 	g->param = nil;
-	g->status = Gwaiting;
-	g->waitreason = "select";
-	selunlock(sel);
-	runtime·gosched();
+	runtime·park((void(*)(Lock*))selunlock, (Lock*)sel, "select");
 
 	sellock(sel);
 	sg = g->param;
@@ -951,6 +1027,8 @@ loop:
 
 asyncrecv:
 	// can receive from buffer
+	if(raceenabled)
+		runtime·raceacquire(chanbuf(c, c->recvx));
 	if(cas->receivedp != nil)
 		*cas->receivedp = true;
 	if(cas->sg.elem != nil)
@@ -971,6 +1049,8 @@ asyncrecv:
 
 asyncsend:
 	// can send to buffer
+	if(raceenabled)
+		runtime·racerelease(chanbuf(c, c->sendx));
 	c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), cas->sg.elem);
 	if(++c->sendx == c->dataqsiz)
 		c->sendx = 0;
@@ -987,6 +1067,8 @@ asyncsend:
 
 syncrecv:
 	// can receive from sleeping sender (sg)
+	if(raceenabled)
+		racesync(c, sg);
 	selunlock(sel);
 	if(debug)
 		runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
@@ -1006,10 +1088,14 @@ rclose:
 		*cas->receivedp = false;
 	if(cas->sg.elem != nil)
 		c->elemalg->copy(c->elemsize, cas->sg.elem, nil);
+	if(raceenabled)
+		runtime·raceacquire(c);
 	goto retc;
 
 syncsend:
 	// can send to sleeping receiver (sg)
+	if(raceenabled)
+		racesync(c, sg);
 	selunlock(sel);
 	if(debug)
 		runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
@@ -1020,11 +1106,17 @@ syncsend:
 	runtime·ready(gp);
 
 retc:
-	// return to pc corresponding to chosen case
+	// 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;
-	as = (byte*)selp + cas->so;
+	if(cas->so > 0) {
+		as = (byte*)selp + cas->so;
+		*as = true;
+	}
 	runtime·free(sel);
-	*as = true;
 	return pc;
 
 sclose:
@@ -1034,7 +1126,89 @@ sclose:
 	return nil;  // not reached
 }
 
+// This struct must match ../reflect/value.go:/runtimeSelect.
+typedef struct runtimeSelect runtimeSelect;
+struct runtimeSelect
+{
+	uintptr dir;
+	ChanType *typ;
+	Hchan *ch;
+	uintptr val;
+};
+
+// This enum must match ../reflect/value.go:/SelectDir.
+enum SelectDir {
+	SelectSend = 1,
+	SelectRecv,
+	SelectDefault,
+};
+
+// func rselect(cases []runtimeSelect) (chosen int, word uintptr, recvOK bool)
+void
+reflect·rselect(Slice cases, intgo chosen, uintptr word, bool recvOK)
+{
+	int32 i;
+	Select *sel;
+	runtimeSelect* rcase, *rc;
+	void *elem;
+	void *recvptr;
+	uintptr maxsize;
+
+	chosen = -1;
+	word = 0;
+	recvOK = false;
+
+	maxsize = 0;
+	rcase = (runtimeSelect*)cases.array;
+	for(i=0; i<cases.len; i++) {
+		rc = &rcase[i];
+		if(rc->dir == SelectRecv && rc->ch != nil && maxsize < rc->typ->elem->size)
+			maxsize = rc->typ->elem->size;
+	}
+
+	recvptr = nil;
+	if(maxsize > sizeof(void*))
+		recvptr = runtime·mal(maxsize);
+
+	newselect(cases.len, &sel);
+	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;
+			if(rc->typ->elem->size > sizeof(void*))
+				elem = (void*)rc->val;
+			else
+				elem = (void*)&rc->val;
+			selectsend(sel, rc->ch, (void*)i, elem, 0);
+			break;
+		case SelectRecv:
+			if(rc->ch == nil)
+				break;
+			if(rc->typ->elem->size > sizeof(void*))
+				elem = recvptr;
+			else
+				elem = &word;
+			selectrecv(sel, rc->ch, (void*)i, elem, &recvOK, 0);
+			break;
+		}
+	}
+
+	chosen = (intgo)(uintptr)selectgo(&sel);
+	if(rcase[chosen].dir == SelectRecv && rcase[chosen].typ->elem->size > sizeof(void*))
+		word = (uintptr)recvptr;
+
+	FLUSH(&chosen);
+	FLUSH(&word);
+	FLUSH(&recvOK);
+}
+
 // closechan(sel *byte);
+#pragma textflag 7
 void
 runtime·closechan(Hchan *c)
 {
@@ -1053,6 +1227,11 @@ runtime·closechan(Hchan *c)
 		runtime·panicstring("close of closed channel");
 	}
 
+	if(raceenabled) {
+		runtime·racewritepc(c, runtime·getcallerpc(&c), runtime·closechan);
+		runtime·racerelease(c);
+	}
+
 	c->closed = true;
 
 	// release all readers
@@ -1087,9 +1266,9 @@ reflect·chanclose(Hchan *c)
 }
 
 // For reflect
-//	func chanlen(c chan) (len int32)
+//	func chanlen(c chan) (len int)
 void
-reflect·chanlen(Hchan *c, int32 len)
+reflect·chanlen(Hchan *c, intgo len)
 {
 	if(c == nil)
 		len = 0;
@@ -1099,9 +1278,9 @@ reflect·chanlen(Hchan *c, int32 len)
 }
 
 // For reflect
-//	func chancap(c chan) (cap int32)
+//	func chancap(c chan) int
 void
-reflect·chancap(Hchan *c, int32 cap)
+reflect·chancap(Hchan *c, intgo cap)
 {
 	if(c == nil)
 		cap = 0;
@@ -1160,3 +1339,12 @@ enqueue(WaitQ *q, SudoG *sgp)
 	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/closure_386.c b/src/pkg/runtime/closure_386.c
deleted file mode 100644
index b4d8677..0000000
--- a/src/pkg/runtime/closure_386.c
+++ /dev/null
@@ -1,105 +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"
-
-#pragma textflag 7
-// func closure(siz int32,
-//	fn func(arg0, arg1, arg2 *ptr, callerpc uintptr, xxx) yyy,
-//	arg0, arg1, arg2 *ptr) (func(xxx) yyy)
-void
-runtime·closure(int32 siz, byte *fn, byte *arg0)
-{
-	byte *p, *q, **ret;
-	int32 i, n;
-	int32 pcrel;
-
-	if(siz < 0 || siz%4 != 0)
-		runtime·throw("bad closure size");
-
-	ret = (byte**)((byte*)&arg0 + siz);
-
-	if(siz > 100) {
-		// TODO(rsc): implement stack growth preamble?
-		runtime·throw("closure too big");
-	}
-
-	// compute size of new fn.
-	// must match code laid out below.
-	n = 6+5+2+1;	// SUBL MOVL MOVL CLD
-	if(siz <= 4*4)
-		n += 1*siz/4;	// MOVSL MOVSL...
-	else
-		n += 6+2;	// MOVL REP MOVSL
-	n += 5;	// CALL
-	n += 6+1;	// ADDL RET
-
-	// store args aligned after code, so gc can find them.
-	n += siz;
-	if(n%4)
-		n += 4 - n%4;
-
-	p = runtime·mal(n);
-	*ret = p;
-	q = p + n - siz;
-
-	if(siz > 0) {
-		runtime·memmove(q, (byte*)&arg0, siz);
-
-		// SUBL $siz, SP
-		*p++ = 0x81;
-		*p++ = 0xec;
-		*(uint32*)p = siz;
-		p += 4;
-
-		// MOVL $q, SI
-		*p++ = 0xbe;
-		*(byte**)p = q;
-		p += 4;
-
-		// MOVL SP, DI
-		*p++ = 0x89;
-		*p++ = 0xe7;
-
-		// CLD
-		*p++ = 0xfc;
-
-		if(siz <= 4*4) {
-			for(i=0; i<siz; i+=4) {
-				// MOVSL
-				*p++ = 0xa5;
-			}
-		} else {
-			// MOVL $(siz/4), CX  [32-bit immediate siz/4]
-			*p++ = 0xc7;
-			*p++ = 0xc1;
-			*(uint32*)p = siz/4;
-			p += 4;
-
-			// REP; MOVSL
-			*p++ = 0xf3;
-			*p++ = 0xa5;
-		}
-	}
-
-	// call fn
-	pcrel = fn - (p+5);
-	// direct call with pc-relative offset
-	// CALL fn
-	*p++ = 0xe8;
-	*(int32*)p = pcrel;
-	p += 4;
-
-	// ADDL $siz, SP
-	*p++ = 0x81;
-	*p++ = 0xc4;
-	*(uint32*)p = siz;
-	p += 4;
-
-	// RET
-	*p++ = 0xc3;
-
-	if(p > q)
-		runtime·throw("bad math in sys.closure");
-}
diff --git a/src/pkg/runtime/closure_amd64.c b/src/pkg/runtime/closure_amd64.c
deleted file mode 100644
index 481b4a8..0000000
--- a/src/pkg/runtime/closure_amd64.c
+++ /dev/null
@@ -1,123 +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"
-
-#pragma textflag 7
-// func closure(siz int32,
-//	fn func(arg0, arg1, arg2 *ptr, callerpc uintptr, xxx) yyy,
-//	arg0, arg1, arg2 *ptr) (func(xxx) yyy)
-void
-runtime·closure(int32 siz, byte *fn, byte *arg0)
-{
-	byte *p, *q, **ret;
-	int32 i, n;
-	int64 pcrel;
-
-	if(siz < 0 || siz%8 != 0)
-		runtime·throw("bad closure size");
-
-	ret = (byte**)((byte*)&arg0 + siz);
-
-	if(siz > 100) {
-		// TODO(rsc): implement stack growth preamble?
-		runtime·throw("closure too big");
-	}
-
-	// compute size of new fn.
-	// must match code laid out below.
-	n = 7+10+3;	// SUBQ MOVQ MOVQ
-	if(siz <= 4*8)
-		n += 2*siz/8;	// MOVSQ MOVSQ...
-	else
-		n += 7+3;	// MOVQ REP MOVSQ
-	n += 12;	// CALL worst case; sometimes only 5
-	n += 7+1;	// ADDQ RET
-
-	// store args aligned after code, so gc can find them.
-	n += siz;
-	if(n%8)
-		n += 8 - n%8;
-
-	p = runtime·mal(n);
-	*ret = p;
-	q = p + n - siz;
-
-	if(siz > 0) {
-		runtime·memmove(q, (byte*)&arg0, siz);
-
-		// SUBQ $siz, SP
-		*p++ = 0x48;
-		*p++ = 0x81;
-		*p++ = 0xec;
-		*(uint32*)p = siz;
-		p += 4;
-
-		// MOVQ $q, SI
-		*p++ = 0x48;
-		*p++ = 0xbe;
-		*(byte**)p = q;
-		p += 8;
-
-		// MOVQ SP, DI
-		*p++ = 0x48;
-		*p++ = 0x89;
-		*p++ = 0xe7;
-
-		if(siz <= 4*8) {
-			for(i=0; i<siz; i+=8) {
-				// MOVSQ
-				*p++ = 0x48;
-				*p++ = 0xa5;
-			}
-		} else {
-			// MOVQ $(siz/8), CX  [32-bit immediate siz/8]
-			*p++ = 0x48;
-			*p++ = 0xc7;
-			*p++ = 0xc1;
-			*(uint32*)p = siz/8;
-			p += 4;
-
-			// REP; MOVSQ
-			*p++ = 0xf3;
-			*p++ = 0x48;
-			*p++ = 0xa5;
-		}
-	}
-
-	// call fn
-	pcrel = fn - (p+5);
-	if((int32)pcrel == pcrel) {
-		// can use direct call with pc-relative offset
-		// CALL fn
-		*p++ = 0xe8;
-		*(int32*)p = pcrel;
-		p += 4;
-	} else {
-		// MOVQ $fn, CX  [64-bit immediate fn]
-		*p++ = 0x48;
-		*p++ = 0xb9;
-		*(byte**)p = fn;
-		p += 8;
-
-		// CALL *CX
-		*p++ = 0xff;
-		*p++ = 0xd1;
-	}
-
-	// ADDQ $siz, SP
-	*p++ = 0x48;
-	*p++ = 0x81;
-	*p++ = 0xc4;
-	*(uint32*)p = siz;
-	p += 4;
-
-	// RET
-	*p++ = 0xc3;
-
-	if(p > q)
-		runtime·throw("bad math in sys.closure");
-}
-
-
diff --git a/src/pkg/runtime/closure_arm.c b/src/pkg/runtime/closure_arm.c
deleted file mode 100644
index 119e91b..0000000
--- a/src/pkg/runtime/closure_arm.c
+++ /dev/null
@@ -1,129 +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"
-
-/*
-	There are two bits of magic:
-	- The signature of the compiler generated function uses two stack frames
-	as arguments (callerpc separates these frames)
-	- size determines how many arguments runtime.closure actually has
-	starting at arg0.
-
-	Example closure with 3 captured variables:
-	func closure(siz int32,
-	fn func(arg0, arg1, arg2 *ptr, callerpc uintptr, xxx) yyy,
-		arg0, arg1, arg2 *ptr) (func(xxx) yyy)
-
-	Code generated:
-	src R0
-	dst R1
-	end R3
-	tmp R4
-	frame = siz+4
-
-//skip loop for 0 size closures
-		MOVW.W	R14,-frame(R13)
-
-		MOVW	$vars(PC), R0
-		MOVW	$4(SP), R1
-		MOVW	$siz(R0), R3
-loop:		MOVW.P	4(R0), R4
-		MOVW.P	R4, 4(R1)
-		CMP		R0, R3
-		BNE		loop
-
-		MOVW	8(PC), R0
-		BL		(R0)			// 2 words
-		MOVW.P	frame(R13),R15
-fptr:		WORD	*fn
-vars:		WORD	arg0
-		WORD	arg1
-		WORD	arg2
-*/
-
-extern void runtime·cacheflush(byte* start, byte* end);
-
-#pragma textflag 7
-void
-runtime·closure(int32 siz, byte *fn, byte *arg0)
-{
-	byte *p, *q, **ret;
-	uint32 *pc;
-	int32 n;
-
-	if(siz < 0 || siz%4 != 0)
-		runtime·throw("bad closure size");
-
-	ret = (byte**)((byte*)&arg0 + siz);
-
-	if(siz > 100) {
-		// TODO(kaib): implement stack growth preamble?
-		runtime·throw("closure too big");
-	}
-
-	// size of new fn.
-	// must match code laid out below.
-	if (siz > 0)
-		n = 6 * 4 + 7 * 4;
-	else
-		n = 6 * 4;
-
-	// store args aligned after code, so gc can find them.
-	n += siz;
-
-	p = runtime·mal(n);
-	*ret = p;
-	q = p + n - siz;
-
-	pc = (uint32*)p;
-
-	//	MOVW.W	R14,-frame(R13)
-	*pc++ = 0xe52de000 | (siz + 4);
-
-	if(siz > 0) {
-		runtime·memmove(q, (byte*)&arg0, siz);
-
-		//	MOVW	$vars(PC), R0
-		*pc = 0xe28f0000 | (int32)(q - (byte*)pc - 8);
-		pc++;
-
-		//	MOVW	$4(SP), R1
-		*pc++ = 0xe28d1004;
-
-		//	MOVW	$siz(R0), R3
-		*pc++ = 0xe2803000 | siz;
-
-		//	MOVW.P	4(R0), R4
-		*pc++ = 0xe4904004;
-		//	MOVW.P	R4, 4(R1)
-		*pc++ = 0xe4814004;
-		//	CMP		R0, R3
-		*pc++ = 0xe1530000;
-		//	BNE		loop
-		*pc++ = 0x1afffffb;
-	}
-
-	//	MOVW	fptr(PC), R0
-	*pc = 0xe59f0008 | (int32)((q - 4) -(byte*) pc - 8);
-	pc++;
-
-	//	BL		(R0)
-	*pc++ = 0xe28fe000;
-	*pc++ = 0xe280f000;
-
-	//	MOVW.P	frame(R13),R15
-	*pc++ = 0xe49df000 | (siz + 4);
-
-	//	WORD	*fn
-	*pc++ = (uint32)fn;
-
-	p = (byte*)pc;
-
-	if(p > q)
-		runtime·throw("bad math in sys.closure");
-
-	runtime·cacheflush(*ret, q+siz);
-}
-
diff --git a/src/pkg/runtime/complex.c b/src/pkg/runtime/complex.c
index eeb9439..395e70f 100644
--- a/src/pkg/runtime/complex.c
+++ b/src/pkg/runtime/complex.c
@@ -13,28 +13,30 @@ runtime·complex128div(Complex128 n, Complex128 d, Complex128 q)
 	float64 a, b, ratio, denom;
 
 	// Special cases as in C99.
-	ninf = runtime·isInf(n.real, 0) || runtime·isInf(n.imag, 0);
-	dinf = runtime·isInf(d.real, 0) || runtime·isInf(d.imag, 0);
+	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 && (runtime·isNaN(n.real) || runtime·isNaN(n.imag));
-	dnan = !dinf && (runtime·isNaN(d.real) || runtime·isNaN(d.imag));
+	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 && !dnan) {
-		q.real = runtime·Inf(0);
-		q.imag = runtime·Inf(0);
-	} else if(!ninf && !nnan && dinf) {
+		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();
+			q.real = runtime·nan;
+			q.imag = runtime·nan;
 		} else {
-			q.real = runtime·Inf(0);
-			q.imag = runtime·Inf(0);
+			q.real = runtime·posinf;
+			q.imag = runtime·posinf;
 		}
 	} else {
 		// Standard complex arithmetic, factored to avoid unnecessary overflow.
diff --git a/src/pkg/runtime/complex_test.go b/src/pkg/runtime/complex_test.go
new file mode 100644
index 0000000..f41e6a3
--- /dev/null
+++ b/src/pkg/runtime/complex_test.go
@@ -0,0 +1,67 @@
+// 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 (
+	"math/cmplx"
+	"testing"
+)
+
+var result complex128
+
+func BenchmarkComplex128DivNormal(b *testing.B) {
+	d := 15 + 2i
+	n := 32 + 3i
+	res := 0i
+	for i := 0; i < b.N; i++ {
+		n += 0.1i
+		res += n / d
+	}
+	result = res
+}
+
+func BenchmarkComplex128DivNisNaN(b *testing.B) {
+	d := cmplx.NaN()
+	n := 32 + 3i
+	res := 0i
+	for i := 0; i < b.N; i++ {
+		n += 0.1i
+		res += n / d
+	}
+	result = res
+}
+
+func BenchmarkComplex128DivDisNaN(b *testing.B) {
+	d := 15 + 2i
+	n := cmplx.NaN()
+	res := 0i
+	for i := 0; i < b.N; i++ {
+		d += 0.1i
+		res += n / d
+	}
+	result = res
+}
+
+func BenchmarkComplex128DivNisInf(b *testing.B) {
+	d := 15 + 2i
+	n := cmplx.Inf()
+	res := 0i
+	for i := 0; i < b.N; i++ {
+		d += 0.1i
+		res += n / d
+	}
+	result = res
+}
+
+func BenchmarkComplex128DivDisInf(b *testing.B) {
+	d := cmplx.Inf()
+	n := 32 + 3i
+	res := 0i
+	for i := 0; i < b.N; i++ {
+		n += 0.1i
+		res += n / d
+	}
+	result = res
+}
diff --git a/src/pkg/runtime/cpuprof.c b/src/pkg/runtime/cpuprof.c
index 05fa0cf..9a0606a 100644
--- a/src/pkg/runtime/cpuprof.c
+++ b/src/pkg/runtime/cpuprof.c
@@ -99,6 +99,7 @@ struct Profile {
 	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;
@@ -109,16 +110,20 @@ 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) {
+static void
+LostProfileData(void)
+{
 }
 
 // SetCPUProfileRate sets the CPU profiling rate.
 // The user documentation is in debug.go.
 void
-runtime·SetCPUProfileRate(int32 hz)
+runtime·SetCPUProfileRate(intgo hz)
 {
 	uintptr *p;
 	uintptr n;
@@ -163,6 +168,7 @@ runtime·SetCPUProfileRate(int32 hz)
 		prof->wholding = false;
 		prof->wtoggle = 0;
 		prof->flushing = false;
+		prof->eod_sent = false;
 		runtime·noteclear(&prof->wait);
 
 		runtime·setcpuprofilerate(tick, hz);
@@ -356,7 +362,7 @@ getprofile(Profile *p)
 		return ret;
 
 	// Wait for new log.
-	runtime·entersyscall();
+	runtime·entersyscallblock();
 	runtime·notesleep(&p->wait);
 	runtime·exitsyscall();
 	runtime·noteclear(&p->wait);
@@ -409,6 +415,16 @@ breakflush:
 	}
 
 	// 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))
diff --git a/src/pkg/runtime/crash_cgo_test.go b/src/pkg/runtime/crash_cgo_test.go
new file mode 100644
index 0000000..8ccea8f
--- /dev/null
+++ b/src/pkg/runtime/crash_cgo_test.go
@@ -0,0 +1,88 @@
+// 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 cgo
+
+package runtime_test
+
+import (
+	"testing"
+)
+
+func TestCgoCrashHandler(t *testing.T) {
+	testCrashHandler(t, true)
+}
+
+func TestCgoSignalDeadlock(t *testing.T) {
+	got := executeTest(t, cgoSignalDeadlockSource, nil)
+	want := "OK\n"
+	if got != want {
+		t.Fatalf("expected %q, but got %q", want, got)
+	}
+}
+
+const cgoSignalDeadlockSource = `
+package main
+
+import "C"
+
+import (
+	"fmt"
+	"runtime"
+	"time"
+)
+
+func main() {
+	runtime.GOMAXPROCS(100)
+	ping := make(chan bool)
+	go func() {
+		for i := 0; ; i++ {
+			runtime.Gosched()
+			select {
+			case done := <-ping:
+				if done {
+					ping <- true
+					return
+				}
+				ping <- true
+			default:
+			}
+			func() {
+				defer func() {
+					recover()
+				}()
+				var s *string
+				*s = ""
+			}()
+		}
+	}()
+	time.Sleep(time.Millisecond)
+	for i := 0; i < 64; i++ {
+		go func() {
+			runtime.LockOSThread()
+			select {}
+		}()
+		go func() {
+			runtime.LockOSThread()
+			select {}
+		}()
+		time.Sleep(time.Millisecond)
+		ping <- false
+		select {
+		case <-ping:
+		case <-time.After(time.Second):
+			fmt.Printf("HANG\n")
+			return
+		}
+	}
+	ping <- true
+	select {
+	case <-ping:
+	case <-time.After(time.Second):
+		fmt.Printf("HANG\n")
+		return
+	}
+	fmt.Printf("OK\n")
+}
+`
diff --git a/src/pkg/runtime/crash_test.go b/src/pkg/runtime/crash_test.go
new file mode 100644
index 0000000..5f84cb5
--- /dev/null
+++ b/src/pkg/runtime/crash_test.go
@@ -0,0 +1,177 @@
+// 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 (
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"testing"
+	"text/template"
+)
+
+func executeTest(t *testing.T, templ string, data interface{}) string {
+	checkStaleRuntime(t)
+
+	st := template.Must(template.New("crashSource").Parse(templ))
+
+	dir, err := ioutil.TempDir("", "go-build")
+	if err != nil {
+		t.Fatalf("failed to create temp directory: %v", err)
+	}
+	defer os.RemoveAll(dir)
+
+	src := filepath.Join(dir, "main.go")
+	f, err := os.Create(src)
+	if err != nil {
+		t.Fatalf("failed to create %v: %v", src, err)
+	}
+	err = st.Execute(f, data)
+	if err != nil {
+		f.Close()
+		t.Fatalf("failed to execute template: %v", err)
+	}
+	f.Close()
+
+	got, _ := exec.Command("go", "run", src).CombinedOutput()
+	return string(got)
+}
+
+func checkStaleRuntime(t *testing.T) {
+	// 'go run' uses the installed copy of runtime.a, which may be out of date.
+	out, err := exec.Command("go", "list", "-f", "{{.Stale}}", "runtime").CombinedOutput()
+	if err != nil {
+		t.Fatalf("failed to execute 'go list': %v\n%v", err, string(out))
+	}
+	if string(out) != "false\n" {
+		t.Fatalf("Stale runtime.a. Run 'go install runtime'.")
+	}
+}
+
+func testCrashHandler(t *testing.T, cgo bool) {
+	type crashTest struct {
+		Cgo bool
+	}
+	got := executeTest(t, crashSource, &crashTest{Cgo: cgo})
+	want := "main: recovered done\nnew-thread: recovered done\nsecond-new-thread: recovered done\nmain-again: recovered done\n"
+	if got != want {
+		t.Fatalf("expected %q, but got %q", want, got)
+	}
+}
+
+func TestCrashHandler(t *testing.T) {
+	testCrashHandler(t, false)
+}
+
+func testDeadlock(t *testing.T, source string) {
+	got := executeTest(t, source, nil)
+	want := "fatal error: all goroutines are asleep - deadlock!\n"
+	if !strings.HasPrefix(got, want) {
+		t.Fatalf("expected %q, but got %q", want, got)
+	}
+}
+
+func TestSimpleDeadlock(t *testing.T) {
+	testDeadlock(t, simpleDeadlockSource)
+}
+
+func TestInitDeadlock(t *testing.T) {
+	testDeadlock(t, initDeadlockSource)
+}
+
+func TestLockedDeadlock(t *testing.T) {
+	testDeadlock(t, lockedDeadlockSource)
+}
+
+func TestLockedDeadlock2(t *testing.T) {
+	testDeadlock(t, lockedDeadlockSource2)
+}
+
+const crashSource = `
+package main
+
+import (
+	"fmt"
+	"runtime"
+)
+
+{{if .Cgo}}
+import "C"
+{{end}}
+
+func test(name string) {
+	defer func() {
+		if x := recover(); x != nil {
+			fmt.Printf(" recovered")
+		}
+		fmt.Printf(" done\n")
+	}()
+	fmt.Printf("%s:", name)
+	var s *string
+	_ = *s
+	fmt.Print("SHOULD NOT BE HERE")
+}
+
+func testInNewThread(name string) {
+	c := make(chan bool)
+	go func() {
+		runtime.LockOSThread()
+		test(name)
+		c <- true
+	}()
+	<-c
+}
+
+func main() {
+	runtime.LockOSThread()
+	test("main")
+	testInNewThread("new-thread")
+	testInNewThread("second-new-thread")
+	test("main-again")
+}
+`
+
+const simpleDeadlockSource = `
+package main
+func main() {
+	select {}
+}
+`
+
+const initDeadlockSource = `
+package main
+func init() {
+	select {}
+}
+func main() {
+}
+`
+
+const lockedDeadlockSource = `
+package main
+import "runtime"
+func main() {
+	runtime.LockOSThread()
+	select {}
+}
+`
+
+const lockedDeadlockSource2 = `
+package main
+import (
+	"runtime"
+	"time"
+)
+func main() {
+	go func() {
+		runtime.LockOSThread()
+		select {}
+	}()
+	time.Sleep(time.Millisecond)
+	select {}
+}
+`
diff --git a/src/pkg/runtime/debug.go b/src/pkg/runtime/debug.go
index b802fc6..d82afb0 100644
--- a/src/pkg/runtime/debug.go
+++ b/src/pkg/runtime/debug.go
@@ -4,7 +4,7 @@
 
 package runtime
 
-// Breakpoint() executes a breakpoint trap.
+// Breakpoint executes a breakpoint trap.
 func Breakpoint()
 
 // LockOSThread wires the calling goroutine to its current operating system thread.
@@ -125,6 +125,7 @@ func GoroutineProfile(p []StackRecord) (n int, ok bool)
 // 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.
@@ -133,11 +134,37 @@ 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
diff --git a/src/pkg/runtime/debug/debug.c b/src/pkg/runtime/debug/debug.c
new file mode 100644
index 0000000..a7292c4
--- /dev/null
+++ b/src/pkg/runtime/debug/debug.c
@@ -0,0 +1,9 @@
+// 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.
+
+// Nothing to see here.
+// This file exists so that the go command knows that parts of the
+// package are implemented in C, so that it does not instruct the
+// Go compiler to complain about extern declarations.
+// The actual implementations are in package runtime.
diff --git a/src/pkg/runtime/debug/garbage.go b/src/pkg/runtime/debug/garbage.go
new file mode 100644
index 0000000..8f30264
--- /dev/null
+++ b/src/pkg/runtime/debug/garbage.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.
+
+package debug
+
+import (
+	"runtime"
+	"sort"
+	"time"
+)
+
+// GCStats collect information about recent garbage collections.
+type GCStats struct {
+	LastGC         time.Time       // time of last collection
+	NumGC          int64           // number of garbage collections
+	PauseTotal     time.Duration   // total pause for all collections
+	Pause          []time.Duration // pause 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()
+
+// 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.
+// ReadGCStats may use the full capacity of the stats.Pause slice.
+// If stats.PauseQuantiles is non-empty, ReadGCStats fills it with quantiles
+// summarizing the distribution of pause time. For example, if
+// len(stats.PauseQuantiles) is 5, it will be filled with the minimum,
+// 25%, 50%, 75%, and maximum pause times.
+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.
+	const maxPause = len(((*runtime.MemStats)(nil)).PauseNs)
+	if cap(stats.Pause) < 2*maxPause {
+		stats.Pause = make([]time.Duration, 2*maxPause)
+	}
+
+	// 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(&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]
+	stats.Pause = stats.Pause[:n]
+
+	if len(stats.PauseQuantiles) > 0 {
+		if n == 0 {
+			for i := range stats.PauseQuantiles {
+				stats.PauseQuantiles[i] = 0
+			}
+		} else {
+			// There's room for a second copy of the data in stats.Pause.
+			// See the allocation at the top of the function.
+			sorted := stats.Pause[n : n+n]
+			copy(sorted, stats.Pause)
+			sort.Sort(byDuration(sorted))
+			nq := len(stats.PauseQuantiles) - 1
+			for i := 0; i < nq; i++ {
+				stats.PauseQuantiles[i] = sorted[len(sorted)*i/nq]
+			}
+			stats.PauseQuantiles[nq] = sorted[len(sorted)-1]
+		}
+	}
+}
+
+type byDuration []time.Duration
+
+func (x byDuration) Len() int           { return len(x) }
+func (x byDuration) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byDuration) Less(i, j int) bool { return x[i] < x[j] }
+
+// SetGCPercent sets the garbage collection target percentage:
+// a collection is triggered when the ratio of freshly allocated data
+// to live data remaining after the previous collection reaches this percentage.
+// SetGCPercent returns the previous setting.
+// The initial setting is the value of the GOGC environment variable
+// at startup, or 100 if the variable is not set.
+// A negative percentage disables garbage collection.
+func SetGCPercent(percent int) int {
+	return setGCPercent(percent)
+}
+
+// FreeOSMemory forces a garbage collection followed by an
+// attempt to return as much memory to the operating system
+// as possible. (Even if this is not called, the runtime gradually
+// returns memory to the operating system in a background task.)
+func FreeOSMemory() {
+	freeOSMemory()
+}
diff --git a/src/pkg/runtime/debug/garbage_test.go b/src/pkg/runtime/debug/garbage_test.go
new file mode 100644
index 0000000..b93cfee
--- /dev/null
+++ b/src/pkg/runtime/debug/garbage_test.go
@@ -0,0 +1,100 @@
+// 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 debug
+
+import (
+	"runtime"
+	"testing"
+	"time"
+)
+
+func TestReadGCStats(t *testing.T) {
+	var stats GCStats
+	var mstats runtime.MemStats
+	var min, max time.Duration
+
+	// First ReadGCStats will allocate, second should not,
+	// especially if we follow up with an explicit garbage collection.
+	stats.PauseQuantiles = make([]time.Duration, 10)
+	ReadGCStats(&stats)
+	runtime.GC()
+
+	// Assume these will return same data: no GC during ReadGCStats.
+	ReadGCStats(&stats)
+	runtime.ReadMemStats(&mstats)
+
+	if stats.NumGC != int64(mstats.NumGC) {
+		t.Errorf("stats.NumGC = %d, but mstats.NumGC = %d", stats.NumGC, mstats.NumGC)
+	}
+	if stats.PauseTotal != time.Duration(mstats.PauseTotalNs) {
+		t.Errorf("stats.PauseTotal = %d, but mstats.PauseTotalNs = %d", stats.PauseTotal, mstats.PauseTotalNs)
+	}
+	if stats.LastGC.UnixNano() != int64(mstats.LastGC) {
+		t.Errorf("stats.LastGC.UnixNano = %d, but mstats.LastGC = %d", stats.LastGC.UnixNano(), mstats.LastGC)
+	}
+	n := int(mstats.NumGC)
+	if n > len(mstats.PauseNs) {
+		n = len(mstats.PauseNs)
+	}
+	if len(stats.Pause) != n {
+		t.Errorf("len(stats.Pause) = %d, want %d", len(stats.Pause), n)
+	} else {
+		off := (int(mstats.NumGC) + len(mstats.PauseNs) - 1) % len(mstats.PauseNs)
+		for i := 0; i < n; i++ {
+			dt := stats.Pause[i]
+			if dt != time.Duration(mstats.PauseNs[off]) {
+				t.Errorf("stats.Pause[%d] = %d, want %d", i, dt, mstats.PauseNs[off])
+			}
+			if max < dt {
+				max = dt
+			}
+			if min > dt || i == 0 {
+				min = dt
+			}
+			off = (off + len(mstats.PauseNs) - 1) % len(mstats.PauseNs)
+		}
+	}
+
+	q := stats.PauseQuantiles
+	nq := len(q)
+	if q[0] != min || q[nq-1] != max {
+		t.Errorf("stats.PauseQuantiles = [%d, ..., %d], want [%d, ..., %d]", q[0], q[nq-1], min, max)
+	}
+
+	for i := 0; i < nq-1; i++ {
+		if q[i] > q[i+1] {
+			t.Errorf("stats.PauseQuantiles[%d]=%d > stats.PauseQuantiles[%d]=%d", i, q[i], i+1, q[i+1])
+		}
+	}
+}
+
+var big = make([]byte, 1<<20)
+
+func TestFreeOSMemory(t *testing.T) {
+	var ms1, ms2 runtime.MemStats
+
+	if big == nil {
+		t.Skip("test is not reliable when run multiple times")
+	}
+	big = nil
+	runtime.GC()
+	runtime.ReadMemStats(&ms1)
+	FreeOSMemory()
+	runtime.ReadMemStats(&ms2)
+	if ms1.HeapReleased >= ms2.HeapReleased {
+		t.Errorf("released before=%d; released after=%d; did not go up", ms1.HeapReleased, ms2.HeapReleased)
+	}
+}
+
+func TestSetGCPercent(t *testing.T) {
+	// Test that the variable is being set and returned correctly.
+	// Assume the percentage itself is implemented fine during GC,
+	// which is harder to test.
+	old := SetGCPercent(123)
+	new := SetGCPercent(old)
+	if new != 123 {
+		t.Errorf("SetGCPercent(123); SetGCPercent(x) = %d, want 123", new)
+	}
+}
diff --git a/src/pkg/runtime/debug/stack.go b/src/pkg/runtime/debug/stack.go
index a533a5c..2896b21 100644
--- a/src/pkg/runtime/debug/stack.go
+++ b/src/pkg/runtime/debug/stack.go
@@ -29,6 +29,8 @@ func PrintStack() {
 // For each routine, it includes the source line information and PC value,
 // then attempts to discover, for Go functions, the calling function or
 // method and the text of the line containing the invocation.
+//
+// This function is deprecated. Use package runtime's Stack instead.
 func Stack() []byte {
 	return stack()
 }
diff --git a/src/pkg/runtime/debug/stack_test.go b/src/pkg/runtime/debug/stack_test.go
index f33f507..bbd6626 100644
--- a/src/pkg/runtime/debug/stack_test.go
+++ b/src/pkg/runtime/debug/stack_test.go
@@ -36,7 +36,7 @@ func (t T) method() []byte {
 func TestStack(t *testing.T) {
 	b := T(0).method()
 	lines := strings.Split(string(b), "\n")
-	if len(lines) <= 6 {
+	if len(lines) < 6 {
 		t.Fatal("too few lines")
 	}
 	n := 0
diff --git a/src/pkg/runtime/defs_freebsd.go b/src/pkg/runtime/defs_freebsd.go
index 306e321..0840227 100644
--- a/src/pkg/runtime/defs_freebsd.go
+++ b/src/pkg/runtime/defs_freebsd.go
@@ -7,8 +7,9 @@
 /*
 Input to cgo.
 
-GOARCH=amd64 cgo -cdefs defs.go >amd64/defs.h
-GOARCH=386 cgo -cdefs defs.go >386/defs.h
+GOARCH=amd64 go tool cgo -cdefs defs_freebsd.go >defs_freebsd_amd64.h
+GOARCH=386 go tool cgo -cdefs defs_freebsd.go >defs_freebsd_386.h
+GOARCH=arm go tool cgo -cdefs defs_freebsd.go >defs_freebsd_arm.h
 */
 
 package runtime
@@ -38,6 +39,8 @@ const (
 	MAP_PRIVATE = C.MAP_PRIVATE
 	MAP_FIXED   = C.MAP_FIXED
 
+	MADV_FREE = C.MADV_FREE
+
 	SA_SIGINFO = C.SA_SIGINFO
 	SA_RESTART = C.SA_RESTART
 	SA_ONSTACK = C.SA_ONSTACK
@@ -104,7 +107,6 @@ type Rtprio C.struct_rtprio
 type ThrParam C.struct_thr_param
 type Sigaltstack C.struct_sigaltstack
 type Sigset C.struct___sigset
-type Sigval C.union_sigval
 type StackT C.stack_t
 
 type Siginfo C.siginfo_t
diff --git a/src/pkg/runtime/defs_freebsd_386.h b/src/pkg/runtime/defs_freebsd_386.h
index 29fcb8b..d00c852 100644
--- a/src/pkg/runtime/defs_freebsd_386.h
+++ b/src/pkg/runtime/defs_freebsd_386.h
@@ -1,193 +1,190 @@
-// godefs -f -m32 defs.c
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_freebsd.go
 
-// MACHINE GENERATED - DO NOT EDIT.
 
-// Constants
 enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	UMTX_OP_WAIT = 0x2,
-	UMTX_OP_WAKE = 0x3,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x2,
-	FPE_INTOVF = 0x1,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x1000,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
+
+	MADV_FREE	= 0x5,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x2,
+	SA_ONSTACK	= 0x1,
+
+	UMTX_OP_WAIT	= 0x2,
+	UMTX_OP_WAKE	= 0x3,
+
+	EINTR	= 0x4,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGEMT		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x10,
+	SIGSTOP		= 0x11,
+	SIGTSTP		= 0x12,
+	SIGCONT		= 0x13,
+	SIGCHLD		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGIO		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGINFO		= 0x1d,
+	SIGUSR1		= 0x1e,
+	SIGUSR2		= 0x1f,
+
+	FPE_INTDIV	= 0x2,
+	FPE_INTOVF	= 0x1,
+	FPE_FLTDIV	= 0x3,
+	FPE_FLTOVF	= 0x4,
+	FPE_FLTUND	= 0x5,
+	FPE_FLTRES	= 0x6,
+	FPE_FLTINV	= 0x7,
+	FPE_FLTSUB	= 0x8,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
+
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
+
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
 };
 
-// Types
+typedef struct Rtprio Rtprio;
+typedef struct ThrParam ThrParam;
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigset Sigset;
+typedef struct StackT StackT;
+typedef struct Siginfo Siginfo;
+typedef struct Mcontext Mcontext;
+typedef struct Ucontext Ucontext;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+
 #pragma pack on
 
-typedef struct Rtprio Rtprio;
 struct Rtprio {
-	uint16 type;
-	uint16 prio;
+	uint16	type;
+	uint16	prio;
 };
-
-typedef struct ThrParam ThrParam;
 struct ThrParam {
-	void *start_func;
-	void *arg;
-	int8 *stack_base;
-	uint32 stack_size;
-	int8 *tls_base;
-	uint32 tls_size;
-	int32 *child_tid;
-	int32 *parent_tid;
-	int32 flags;
-	Rtprio *rtp;
-	void* spare[3];
+	void	*start_func;
+	byte	*arg;
+	int8	*stack_base;
+	uint32	stack_size;
+	int8	*tls_base;
+	uint32	tls_size;
+	int32	*child_tid;
+	int32	*parent_tid;
+	int32	flags;
+	Rtprio	*rtp;
+	void	*spare[3];
 };
-
-typedef struct Sigaltstack Sigaltstack;
 struct Sigaltstack {
-	int8 *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
+	int8	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
 };
-
-typedef struct Sigset Sigset;
 struct Sigset {
-	uint32 __bits[4];
-};
-
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
-	int32 sigval_int;
-	void *sigval_ptr;
+	uint32	__bits[4];
 };
-
-typedef struct StackT StackT;
 struct StackT {
-	int8 *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
+	int8	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
 };
 
-typedef struct Siginfo Siginfo;
 struct Siginfo {
-	int32 si_signo;
-	int32 si_errno;
-	int32 si_code;
-	int32 si_pid;
-	uint32 si_uid;
-	int32 si_status;
-	void *si_addr;
-	Sigval si_value;
-	byte _reason[32];
+	int32	si_signo;
+	int32	si_errno;
+	int32	si_code;
+	int32	si_pid;
+	uint32	si_uid;
+	int32	si_status;
+	byte	*si_addr;
+	byte	si_value[4];
+	byte	_reason[32];
 };
 
-typedef struct Mcontext Mcontext;
 struct Mcontext {
-	int32 mc_onstack;
-	int32 mc_gs;
-	int32 mc_fs;
-	int32 mc_es;
-	int32 mc_ds;
-	int32 mc_edi;
-	int32 mc_esi;
-	int32 mc_ebp;
-	int32 mc_isp;
-	int32 mc_ebx;
-	int32 mc_edx;
-	int32 mc_ecx;
-	int32 mc_eax;
-	int32 mc_trapno;
-	int32 mc_err;
-	int32 mc_eip;
-	int32 mc_cs;
-	int32 mc_eflags;
-	int32 mc_esp;
-	int32 mc_ss;
-	int32 mc_len;
-	int32 mc_fpformat;
-	int32 mc_ownedfp;
-	int32 mc_spare1[1];
-	int32 mc_fpstate[128];
-	int32 mc_fsbase;
-	int32 mc_gsbase;
-	int32 mc_spare2[6];
+	int32	mc_onstack;
+	int32	mc_gs;
+	int32	mc_fs;
+	int32	mc_es;
+	int32	mc_ds;
+	int32	mc_edi;
+	int32	mc_esi;
+	int32	mc_ebp;
+	int32	mc_isp;
+	int32	mc_ebx;
+	int32	mc_edx;
+	int32	mc_ecx;
+	int32	mc_eax;
+	int32	mc_trapno;
+	int32	mc_err;
+	int32	mc_eip;
+	int32	mc_cs;
+	int32	mc_eflags;
+	int32	mc_esp;
+	int32	mc_ss;
+	int32	mc_len;
+	int32	mc_fpformat;
+	int32	mc_ownedfp;
+	int32	mc_spare1[1];
+	int32	mc_fpstate[128];
+	int32	mc_fsbase;
+	int32	mc_gsbase;
+	int32	mc_spare2[6];
 };
-
-typedef struct Ucontext Ucontext;
 struct Ucontext {
-	Sigset uc_sigmask;
-	Mcontext uc_mcontext;
-	Ucontext *uc_link;
-	StackT uc_stack;
-	int32 uc_flags;
-	int32 __spare__[4];
-	byte pad_godefs_0[12];
+	Sigset	uc_sigmask;
+	Mcontext	uc_mcontext;
+	Ucontext	*uc_link;
+	StackT	uc_stack;
+	int32	uc_flags;
+	int32	__spare__[4];
+	byte	Pad_cgo_0[12];
 };
 
-typedef struct Timespec Timespec;
 struct Timespec {
-	int32 tv_sec;
-	int32 tv_nsec;
+	int32	tv_sec;
+	int32	tv_nsec;
 };
-
-typedef struct Timeval Timeval;
 struct Timeval {
-	int32 tv_sec;
-	int32 tv_usec;
+	int32	tv_sec;
+	int32	tv_usec;
 };
-
-typedef struct Itimerval Itimerval;
 struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
+	Timeval	it_interval;
+	Timeval	it_value;
 };
+
+
 #pragma pack off
diff --git a/src/pkg/runtime/defs_freebsd_amd64.h b/src/pkg/runtime/defs_freebsd_amd64.h
index 8a222dc..6348c04 100644
--- a/src/pkg/runtime/defs_freebsd_amd64.h
+++ b/src/pkg/runtime/defs_freebsd_amd64.h
@@ -1,204 +1,201 @@
-// godefs -f -m64 defs.c
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_freebsd.go
 
-// MACHINE GENERATED - DO NOT EDIT.
 
-// Constants
 enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	UMTX_OP_WAIT = 0x2,
-	UMTX_OP_WAKE = 0x3,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x2,
-	FPE_INTOVF = 0x1,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x1000,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
+
+	MADV_FREE	= 0x5,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x2,
+	SA_ONSTACK	= 0x1,
+
+	UMTX_OP_WAIT	= 0x2,
+	UMTX_OP_WAKE	= 0x3,
+
+	EINTR	= 0x4,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGEMT		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x10,
+	SIGSTOP		= 0x11,
+	SIGTSTP		= 0x12,
+	SIGCONT		= 0x13,
+	SIGCHLD		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGIO		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGINFO		= 0x1d,
+	SIGUSR1		= 0x1e,
+	SIGUSR2		= 0x1f,
+
+	FPE_INTDIV	= 0x2,
+	FPE_INTOVF	= 0x1,
+	FPE_FLTDIV	= 0x3,
+	FPE_FLTOVF	= 0x4,
+	FPE_FLTUND	= 0x5,
+	FPE_FLTRES	= 0x6,
+	FPE_FLTINV	= 0x7,
+	FPE_FLTSUB	= 0x8,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
+
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
+
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
 };
 
-// Types
+typedef struct Rtprio Rtprio;
+typedef struct ThrParam ThrParam;
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigset Sigset;
+typedef struct StackT StackT;
+typedef struct Siginfo Siginfo;
+typedef struct Mcontext Mcontext;
+typedef struct Ucontext Ucontext;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+
 #pragma pack on
 
-typedef struct Rtprio Rtprio;
 struct Rtprio {
-	uint16 type;
-	uint16 prio;
+	uint16	type;
+	uint16	prio;
 };
-
-typedef struct ThrParam ThrParam;
 struct ThrParam {
-	void *start_func;
-	void *arg;
-	int8 *stack_base;
-	uint64 stack_size;
-	int8 *tls_base;
-	uint64 tls_size;
-	int64 *child_tid;
-	int64 *parent_tid;
-	int32 flags;
-	byte pad_godefs_0[4];
-	Rtprio *rtp;
-	void* spare[3];
+	void	*start_func;
+	byte	*arg;
+	int8	*stack_base;
+	uint64	stack_size;
+	int8	*tls_base;
+	uint64	tls_size;
+	int64	*child_tid;
+	int64	*parent_tid;
+	int32	flags;
+	byte	Pad_cgo_0[4];
+	Rtprio	*rtp;
+	void	*spare[3];
 };
-
-typedef struct Sigaltstack Sigaltstack;
 struct Sigaltstack {
-	int8 *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
+	int8	*ss_sp;
+	uint64	ss_size;
+	int32	ss_flags;
+	byte	Pad_cgo_0[4];
 };
-
-typedef struct Sigset Sigset;
 struct Sigset {
-	uint32 __bits[4];
-};
-
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
-	int32 sigval_int;
-	void *sigval_ptr;
+	uint32	__bits[4];
 };
-
-typedef struct StackT StackT;
 struct StackT {
-	int8 *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
+	int8	*ss_sp;
+	uint64	ss_size;
+	int32	ss_flags;
+	byte	Pad_cgo_0[4];
 };
 
-typedef struct Siginfo Siginfo;
 struct Siginfo {
-	int32 si_signo;
-	int32 si_errno;
-	int32 si_code;
-	int32 si_pid;
-	uint32 si_uid;
-	int32 si_status;
-	void *si_addr;
-	Sigval si_value;
-	byte _reason[40];
+	int32	si_signo;
+	int32	si_errno;
+	int32	si_code;
+	int32	si_pid;
+	uint32	si_uid;
+	int32	si_status;
+	byte	*si_addr;
+	byte	si_value[8];
+	byte	_reason[40];
 };
 
-typedef struct Mcontext Mcontext;
 struct Mcontext {
-	int64 mc_onstack;
-	int64 mc_rdi;
-	int64 mc_rsi;
-	int64 mc_rdx;
-	int64 mc_rcx;
-	int64 mc_r8;
-	int64 mc_r9;
-	int64 mc_rax;
-	int64 mc_rbx;
-	int64 mc_rbp;
-	int64 mc_r10;
-	int64 mc_r11;
-	int64 mc_r12;
-	int64 mc_r13;
-	int64 mc_r14;
-	int64 mc_r15;
-	uint32 mc_trapno;
-	uint16 mc_fs;
-	uint16 mc_gs;
-	int64 mc_addr;
-	uint32 mc_flags;
-	uint16 mc_es;
-	uint16 mc_ds;
-	int64 mc_err;
-	int64 mc_rip;
-	int64 mc_cs;
-	int64 mc_rflags;
-	int64 mc_rsp;
-	int64 mc_ss;
-	int64 mc_len;
-	int64 mc_fpformat;
-	int64 mc_ownedfp;
-	int64 mc_fpstate[64];
-	int64 mc_fsbase;
-	int64 mc_gsbase;
-	int64 mc_spare[6];
+	int64	mc_onstack;
+	int64	mc_rdi;
+	int64	mc_rsi;
+	int64	mc_rdx;
+	int64	mc_rcx;
+	int64	mc_r8;
+	int64	mc_r9;
+	int64	mc_rax;
+	int64	mc_rbx;
+	int64	mc_rbp;
+	int64	mc_r10;
+	int64	mc_r11;
+	int64	mc_r12;
+	int64	mc_r13;
+	int64	mc_r14;
+	int64	mc_r15;
+	uint32	mc_trapno;
+	uint16	mc_fs;
+	uint16	mc_gs;
+	int64	mc_addr;
+	uint32	mc_flags;
+	uint16	mc_es;
+	uint16	mc_ds;
+	int64	mc_err;
+	int64	mc_rip;
+	int64	mc_cs;
+	int64	mc_rflags;
+	int64	mc_rsp;
+	int64	mc_ss;
+	int64	mc_len;
+	int64	mc_fpformat;
+	int64	mc_ownedfp;
+	int64	mc_fpstate[64];
+	int64	mc_fsbase;
+	int64	mc_gsbase;
+	int64	mc_spare[6];
 };
-
-typedef struct Ucontext Ucontext;
 struct Ucontext {
-	Sigset uc_sigmask;
-	Mcontext uc_mcontext;
-	Ucontext *uc_link;
-	StackT uc_stack;
-	int32 uc_flags;
-	int32 __spare__[4];
-	byte pad_godefs_0[12];
+	Sigset	uc_sigmask;
+	Mcontext	uc_mcontext;
+	Ucontext	*uc_link;
+	StackT	uc_stack;
+	int32	uc_flags;
+	int32	__spare__[4];
+	byte	Pad_cgo_0[12];
 };
 
-typedef struct Timespec Timespec;
 struct Timespec {
-	int64 tv_sec;
-	int64 tv_nsec;
+	int64	tv_sec;
+	int64	tv_nsec;
 };
-
-typedef struct Timeval Timeval;
 struct Timeval {
-	int64 tv_sec;
-	int64 tv_usec;
+	int64	tv_sec;
+	int64	tv_usec;
 };
-
-typedef struct Itimerval Itimerval;
 struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
+	Timeval	it_interval;
+	Timeval	it_value;
 };
+
+
 #pragma pack off
diff --git a/src/pkg/runtime/defs_freebsd_arm.h b/src/pkg/runtime/defs_freebsd_arm.h
new file mode 100644
index 0000000..a744b80
--- /dev/null
+++ b/src/pkg/runtime/defs_freebsd_arm.h
@@ -0,0 +1,163 @@
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_freebsd.go
+
+
+enum {
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x1000,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
+
+	MADV_FREE	= 0x5,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x2,
+	SA_ONSTACK	= 0x1,
+
+	UMTX_OP_WAIT	= 0x2,
+	UMTX_OP_WAKE	= 0x3,
+
+	EINTR	= 0x4,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGEMT		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x10,
+	SIGSTOP		= 0x11,
+	SIGTSTP		= 0x12,
+	SIGCONT		= 0x13,
+	SIGCHLD		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGIO		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGINFO		= 0x1d,
+	SIGUSR1		= 0x1e,
+	SIGUSR2		= 0x1f,
+
+	FPE_INTDIV	= 0x2,
+	FPE_INTOVF	= 0x1,
+	FPE_FLTDIV	= 0x3,
+	FPE_FLTOVF	= 0x4,
+	FPE_FLTUND	= 0x5,
+	FPE_FLTRES	= 0x6,
+	FPE_FLTINV	= 0x7,
+	FPE_FLTSUB	= 0x8,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
+
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
+
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
+};
+
+typedef struct Rtprio Rtprio;
+typedef struct ThrParam ThrParam;
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigset Sigset;
+typedef struct StackT StackT;
+typedef struct Siginfo Siginfo;
+typedef struct Mcontext Mcontext;
+typedef struct Ucontext Ucontext;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+
+#pragma pack on
+
+struct Rtprio {
+	uint16	type;
+	uint16	prio;
+};
+struct ThrParam {
+	void	*start_func;
+	byte	*arg;
+	uint8	*stack_base;
+	uint32	stack_size;
+	uint8	*tls_base;
+	uint32	tls_size;
+	int32	*child_tid;
+	int32	*parent_tid;
+	int32	flags;
+	Rtprio	*rtp;
+	void	*spare[3];
+};
+struct Sigaltstack {
+	uint8	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
+};
+struct Sigset {
+	uint32	__bits[4];
+};
+struct StackT {
+	uint8	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
+};
+
+struct Siginfo {
+	int32	si_signo;
+	int32	si_errno;
+	int32	si_code;
+	int32	si_pid;
+	uint32	si_uid;
+	int32	si_status;
+	byte	*si_addr;
+	byte	si_value[4];
+	byte	_reason[32];
+};
+
+struct Mcontext {
+	uint32	__gregs[17];
+	byte	__fpu[140];
+};
+struct Ucontext {
+	Sigset	uc_sigmask;
+	Mcontext	uc_mcontext;
+	Ucontext	*uc_link;
+	StackT	uc_stack;
+	int32	uc_flags;
+	int32	__spare__[4];
+};
+
+struct Timespec {
+	int64	tv_sec;
+	int32	tv_nsec;
+};
+struct Timeval {
+	int64	tv_sec;
+	int32	tv_usec;
+};
+struct Itimerval {
+	Timeval	it_interval;
+	Timeval	it_value;
+};
+
+
+#pragma pack off
diff --git a/src/pkg/runtime/defs_linux_386.h b/src/pkg/runtime/defs_linux_386.h
index 02760f9..e257a6f 100644
--- a/src/pkg/runtime/defs_linux_386.h
+++ b/src/pkg/runtime/defs_linux_386.h
@@ -132,7 +132,7 @@ struct Sigaction {
 	void	*k_sa_handler;
 	uint32	sa_flags;
 	void	*sa_restorer;
-	uint32	sa_mask;
+	uint64	sa_mask;
 };
 struct Siginfo {
 	int32	si_signo;
diff --git a/src/pkg/runtime/defs_linux_arm.h b/src/pkg/runtime/defs_linux_arm.h
index 9e5c83a..f72ec3d 100644
--- a/src/pkg/runtime/defs_linux_arm.h
+++ b/src/pkg/runtime/defs_linux_arm.h
@@ -143,6 +143,6 @@ struct Sigaction {
 	void *sa_handler;
 	uint32 sa_flags;
 	void *sa_restorer;
-	uint32 sa_mask;
+	uint64 sa_mask;
 };
 #pragma pack off
diff --git a/src/pkg/runtime/defs_netbsd.go b/src/pkg/runtime/defs_netbsd.go
index 47c30cf..53e0610 100644
--- a/src/pkg/runtime/defs_netbsd.go
+++ b/src/pkg/runtime/defs_netbsd.go
@@ -7,18 +7,21 @@
 /*
 Input to cgo.
 
-GOARCH=amd64 cgo -cdefs defs.go >amd64/defs.h
-GOARCH=386 cgo -cdefs defs.go >386/defs.h
+GOARCH=amd64 go tool cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go >defs_netbsd_amd64.h
+GOARCH=386 go tool cgo -cdefs defs_netbsd.go defs_netbsd_386.go >defs_netbsd_386.h
 */
 
+// +godefs map __fpregset_t [644]byte
+
 package runtime
 
 /*
 #include <sys/types.h>
 #include <sys/mman.h>
+#include <sys/signal.h>
 #include <sys/time.h>
+#include <sys/ucontext.h>
 #include <sys/unistd.h>
-#include <sys/signal.h>
 #include <errno.h>
 #include <signal.h>
 */
@@ -34,6 +37,8 @@ const (
 	MAP_PRIVATE = C.MAP_PRIVATE
 	MAP_FIXED   = C.MAP_FIXED
 
+	MADV_FREE = C.MADV_FREE
+
 	SA_SIGINFO = C.SA_SIGINFO
 	SA_RESTART = C.SA_RESTART
 	SA_ONSTACK = C.SA_ONSTACK
@@ -95,8 +100,7 @@ const (
 
 type Sigaltstack C.struct_sigaltstack
 type Sigset C.sigset_t
-type Siginfo C.siginfo_t
-type Sigval C.union_sigval
+type Siginfo C.struct__ksiginfo
 
 type StackT C.stack_t
 
@@ -104,8 +108,5 @@ type Timespec C.struct_timespec
 type Timeval C.struct_timeval
 type Itimerval C.struct_itimerval
 
-// This is a hack to avoid pulling in machine/fpu.h.
-type sfxsave64 struct{}
-type usavefpu struct{}
-
-type Sigcontext C.struct_sigcontext
+type McontextT C.mcontext_t
+type UcontextT C.ucontext_t
diff --git a/src/pkg/runtime/defs_netbsd_386.go b/src/pkg/runtime/defs_netbsd_386.go
new file mode 100644
index 0000000..e9e3660
--- /dev/null
+++ b/src/pkg/runtime/defs_netbsd_386.go
@@ -0,0 +1,42 @@
+// 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
+
+/*
+Input to cgo.
+
+GOARCH=amd64 go tool cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go >defs_netbsd_amd64.h
+GOARCH=386 go tool cgo -cdefs defs_netbsd.go defs_netbsd_386.go >defs_netbsd_386.h
+*/
+
+package runtime
+
+/*
+#include <sys/types.h>
+#include <machine/mcontext.h>
+*/
+import "C"
+
+const (
+	REG_GS     = C._REG_GS
+	REG_FS     = C._REG_FS
+	REG_ES     = C._REG_ES
+	REG_DS     = C._REG_DS
+	REG_EDI    = C._REG_EDI
+	REG_ESI    = C._REG_ESI
+	REG_EBP    = C._REG_EBP
+	REG_ESP    = C._REG_ESP
+	REG_EBX    = C._REG_EBX
+	REG_EDX    = C._REG_EDX
+	REG_ECX    = C._REG_ECX
+	REG_EAX    = C._REG_EAX
+	REG_TRAPNO = C._REG_TRAPNO
+	REG_ERR    = C._REG_ERR
+	REG_EIP    = C._REG_EIP
+	REG_CS     = C._REG_CS
+	REG_EFL    = C._REG_EFL
+	REG_UESP   = C._REG_UESP
+	REG_SS     = C._REG_SS
+)
diff --git a/src/pkg/runtime/defs_netbsd_386.h b/src/pkg/runtime/defs_netbsd_386.h
index aff87fb..04c380e 100644
--- a/src/pkg/runtime/defs_netbsd_386.h
+++ b/src/pkg/runtime/defs_netbsd_386.h
@@ -1,146 +1,163 @@
-// godefs -f -m32 defs.c
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_netbsd.go defs_netbsd_386.go
 
-// MACHINE GENERATED - DO NOT EDIT.
 
-// Constants
 enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x1,
-	FPE_INTOVF = 0x2,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x1000,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
+
+	MADV_FREE	= 0x6,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x2,
+	SA_ONSTACK	= 0x1,
+
+	EINTR	= 0x4,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGEMT		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x10,
+	SIGSTOP		= 0x11,
+	SIGTSTP		= 0x12,
+	SIGCONT		= 0x13,
+	SIGCHLD		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGIO		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGINFO		= 0x1d,
+	SIGUSR1		= 0x1e,
+	SIGUSR2		= 0x1f,
+
+	FPE_INTDIV	= 0x1,
+	FPE_INTOVF	= 0x2,
+	FPE_FLTDIV	= 0x3,
+	FPE_FLTOVF	= 0x4,
+	FPE_FLTUND	= 0x5,
+	FPE_FLTRES	= 0x6,
+	FPE_FLTINV	= 0x7,
+	FPE_FLTSUB	= 0x8,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
+
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
+
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
 };
 
-// Types
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigset Sigset;
+typedef struct Siginfo Siginfo;
+typedef struct StackT StackT;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+typedef struct McontextT McontextT;
+typedef struct UcontextT UcontextT;
+
 #pragma pack on
 
-typedef struct Sigaltstack Sigaltstack;
 struct Sigaltstack {
-	void *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
+	byte	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
 };
-
-typedef uint32 Sigset;
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_code;
-	int32 si_errno;
-	byte _data[116];
+struct Sigset {
+	uint32	__bits[4];
 };
-
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
+struct Siginfo {
+	int32	_signo;
+	int32	_code;
+	int32	_errno;
+	byte	_reason[20];
 };
 
-typedef struct StackT StackT;
 struct StackT {
-	void *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
+	byte	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
 };
 
-typedef struct Timespec Timespec;
 struct Timespec {
-	int32 tv_sec;
-	int32 tv_nsec;
+	int64	tv_sec;
+	int32	tv_nsec;
 };
-
-typedef struct Timeval Timeval;
 struct Timeval {
-	int32 tv_sec;
-	int32 tv_usec;
+	int64	tv_sec;
+	int32	tv_usec;
 };
-
-typedef struct Itimerval Itimerval;
 struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
+	Timeval	it_interval;
+	Timeval	it_value;
 };
 
-typedef void sfxsave64;
-
-typedef void usavefpu;
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
-	int32 sc_gs;
-	int32 sc_fs;
-	int32 sc_es;
-	int32 sc_ds;
-	int32 sc_edi;
-	int32 sc_esi;
-	int32 sc_ebp;
-	int32 sc_ebx;
-	int32 sc_edx;
-	int32 sc_ecx;
-	int32 sc_eax;
-	int32 sc_eip;
-	int32 sc_cs;
-	int32 sc_eflags;
-	int32 sc_esp;
-	int32 sc_ss;
-	int32 sc_onstack;
-	int32 sc_mask;
-	int32 sc_trapno;
-	int32 sc_err;
-	usavefpu *sc_fpstate;
+struct McontextT {
+	int32	__gregs[19];
+	byte	__fpregs[644];
+	int32	_mc_tlsbase;
+};
+struct UcontextT {
+	uint32	uc_flags;
+	UcontextT	*uc_link;
+	Sigset	uc_sigmask;
+	StackT	uc_stack;
+	McontextT	uc_mcontext;
+	int32	__uc_pad[4];
 };
+
+
 #pragma pack off
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_netbsd.go defs_netbsd_386.go
+
+
+enum {
+	REG_GS		= 0x0,
+	REG_FS		= 0x1,
+	REG_ES		= 0x2,
+	REG_DS		= 0x3,
+	REG_EDI		= 0x4,
+	REG_ESI		= 0x5,
+	REG_EBP		= 0x6,
+	REG_ESP		= 0x7,
+	REG_EBX		= 0x8,
+	REG_EDX		= 0x9,
+	REG_ECX		= 0xa,
+	REG_EAX		= 0xb,
+	REG_TRAPNO	= 0xc,
+	REG_ERR		= 0xd,
+	REG_EIP		= 0xe,
+	REG_CS		= 0xf,
+	REG_EFL		= 0x10,
+	REG_UESP	= 0x11,
+	REG_SS		= 0x12,
+};
+
diff --git a/src/pkg/runtime/defs_netbsd_amd64.go b/src/pkg/runtime/defs_netbsd_amd64.go
new file mode 100644
index 0000000..68f586b
--- /dev/null
+++ b/src/pkg/runtime/defs_netbsd_amd64.go
@@ -0,0 +1,49 @@
+// 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
+
+/*
+Input to cgo.
+
+GOARCH=amd64 go tool cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go >defs_netbsd_amd64.h
+GOARCH=386 go tool cgo -cdefs defs_netbsd.go defs_netbsd_386.go >defs_netbsd_386.h
+*/
+
+package runtime
+
+/*
+#include <sys/types.h>
+#include <machine/mcontext.h>
+*/
+import "C"
+
+const (
+	REG_RDI    = C._REG_RDI
+	REG_RSI    = C._REG_RSI
+	REG_RDX    = C._REG_RDX
+	REG_RCX    = C._REG_RCX
+	REG_R8     = C._REG_R8
+	REG_R9     = C._REG_R9
+	REG_R10    = C._REG_R10
+	REG_R11    = C._REG_R11
+	REG_R12    = C._REG_R12
+	REG_R13    = C._REG_R13
+	REG_R14    = C._REG_R14
+	REG_R15    = C._REG_R15
+	REG_RBP    = C._REG_RBP
+	REG_RBX    = C._REG_RBX
+	REG_RAX    = C._REG_RAX
+	REG_GS     = C._REG_GS
+	REG_FS     = C._REG_FS
+	REG_ES     = C._REG_ES
+	REG_DS     = C._REG_DS
+	REG_TRAPNO = C._REG_TRAPNO
+	REG_ERR    = C._REG_ERR
+	REG_RIP    = C._REG_RIP
+	REG_CS     = C._REG_CS
+	REG_RFLAGS = C._REG_RFLAGS
+	REG_RSP    = C._REG_RSP
+	REG_SS     = C._REG_SS
+)
diff --git a/src/pkg/runtime/defs_netbsd_amd64.h b/src/pkg/runtime/defs_netbsd_amd64.h
index 27bf4b9..3d3f576 100644
--- a/src/pkg/runtime/defs_netbsd_amd64.h
+++ b/src/pkg/runtime/defs_netbsd_amd64.h
@@ -1,158 +1,174 @@
-// godefs -f -m64 defs.c
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go
 
-// MACHINE GENERATED - DO NOT EDIT.
 
-// Constants
 enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x1,
-	FPE_INTOVF = 0x2,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x1000,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
+
+	MADV_FREE	= 0x6,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x2,
+	SA_ONSTACK	= 0x1,
+
+	EINTR	= 0x4,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGEMT		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x10,
+	SIGSTOP		= 0x11,
+	SIGTSTP		= 0x12,
+	SIGCONT		= 0x13,
+	SIGCHLD		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGIO		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGINFO		= 0x1d,
+	SIGUSR1		= 0x1e,
+	SIGUSR2		= 0x1f,
+
+	FPE_INTDIV	= 0x1,
+	FPE_INTOVF	= 0x2,
+	FPE_FLTDIV	= 0x3,
+	FPE_FLTOVF	= 0x4,
+	FPE_FLTUND	= 0x5,
+	FPE_FLTRES	= 0x6,
+	FPE_FLTINV	= 0x7,
+	FPE_FLTSUB	= 0x8,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
+
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
+
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
 };
 
-// Types
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigset Sigset;
+typedef struct Siginfo Siginfo;
+typedef struct StackT StackT;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+typedef struct McontextT McontextT;
+typedef struct UcontextT UcontextT;
+
 #pragma pack on
 
-typedef struct Sigaltstack Sigaltstack;
 struct Sigaltstack {
-	void *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
+	byte	*ss_sp;
+	uint64	ss_size;
+	int32	ss_flags;
+	byte	Pad_cgo_0[4];
 };
-
-typedef uint32 Sigset;
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_code;
-	int32 si_errno;
-	byte pad_godefs_0[4];
-	byte _data[120];
+struct Sigset {
+	uint32	__bits[4];
 };
-
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
+struct Siginfo {
+	int32	_signo;
+	int32	_code;
+	int32	_errno;
+	int32	_pad;
+	byte	_reason[24];
 };
 
-typedef struct StackT StackT;
 struct StackT {
-	void *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
+	byte	*ss_sp;
+	uint64	ss_size;
+	int32	ss_flags;
+	byte	Pad_cgo_0[4];
 };
 
-typedef struct Timespec Timespec;
 struct Timespec {
-	int32 tv_sec;
-	byte pad_godefs_0[4];
-	int64 tv_nsec;
+	int64	tv_sec;
+	int64	tv_nsec;
 };
-
-typedef struct Timeval Timeval;
 struct Timeval {
-	int64 tv_sec;
-	int64 tv_usec;
+	int64	tv_sec;
+	int32	tv_usec;
+	byte	Pad_cgo_0[4];
 };
-
-typedef struct Itimerval Itimerval;
 struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
+	Timeval	it_interval;
+	Timeval	it_value;
 };
 
-typedef void sfxsave64;
-
-typedef void usavefpu;
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
-	int64 sc_rdi;
-	int64 sc_rsi;
-	int64 sc_rdx;
-	int64 sc_rcx;
-	int64 sc_r8;
-	int64 sc_r9;
-	int64 sc_r10;
-	int64 sc_r11;
-	int64 sc_r12;
-	int64 sc_r13;
-	int64 sc_r14;
-	int64 sc_r15;
-	int64 sc_rbp;
-	int64 sc_rbx;
-	int64 sc_rax;
-	int64 sc_gs;
-	int64 sc_fs;
-	int64 sc_es;
-	int64 sc_ds;
-	int64 sc_trapno;
-	int64 sc_err;
-	int64 sc_rip;
-	int64 sc_cs;
-	int64 sc_rflags;
-	int64 sc_rsp;
-	int64 sc_ss;
-	sfxsave64 *sc_fpstate;
-	int32 sc_onstack;
-	int32 sc_mask;
+struct McontextT {
+	uint64	__gregs[26];
+	uint64	_mc_tlsbase;
+	int8	__fpregs[512];
+};
+struct UcontextT {
+	uint32	uc_flags;
+	byte	Pad_cgo_0[4];
+	UcontextT	*uc_link;
+	Sigset	uc_sigmask;
+	StackT	uc_stack;
+	McontextT	uc_mcontext;
 };
+
+
 #pragma pack off
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go
+
+
+enum {
+	REG_RDI		= 0x0,
+	REG_RSI		= 0x1,
+	REG_RDX		= 0x2,
+	REG_RCX		= 0x3,
+	REG_R8		= 0x4,
+	REG_R9		= 0x5,
+	REG_R10		= 0x6,
+	REG_R11		= 0x7,
+	REG_R12		= 0x8,
+	REG_R13		= 0x9,
+	REG_R14		= 0xa,
+	REG_R15		= 0xb,
+	REG_RBP		= 0xc,
+	REG_RBX		= 0xd,
+	REG_RAX		= 0xe,
+	REG_GS		= 0xf,
+	REG_FS		= 0x10,
+	REG_ES		= 0x11,
+	REG_DS		= 0x12,
+	REG_TRAPNO	= 0x13,
+	REG_ERR		= 0x14,
+	REG_RIP		= 0x15,
+	REG_CS		= 0x16,
+	REG_RFLAGS	= 0x17,
+	REG_RSP		= 0x18,
+	REG_SS		= 0x19,
+};
+
diff --git a/src/pkg/runtime/defs_netbsd_arm.h b/src/pkg/runtime/defs_netbsd_arm.h
new file mode 100644
index 0000000..f67475c
--- /dev/null
+++ b/src/pkg/runtime/defs_netbsd_arm.h
@@ -0,0 +1,140 @@
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_netbsd.go
+
+
+enum {
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x1000,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
+
+	MADV_FREE	= 0x6,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x2,
+	SA_ONSTACK	= 0x1,
+
+	EINTR	= 0x4,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGEMT		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x10,
+	SIGSTOP		= 0x11,
+	SIGTSTP		= 0x12,
+	SIGCONT		= 0x13,
+	SIGCHLD		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGIO		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGINFO		= 0x1d,
+	SIGUSR1		= 0x1e,
+	SIGUSR2		= 0x1f,
+
+	FPE_INTDIV	= 0x1,
+	FPE_INTOVF	= 0x2,
+	FPE_FLTDIV	= 0x3,
+	FPE_FLTOVF	= 0x4,
+	FPE_FLTUND	= 0x5,
+	FPE_FLTRES	= 0x6,
+	FPE_FLTINV	= 0x7,
+	FPE_FLTSUB	= 0x8,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
+
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
+
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
+};
+
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigset Sigset;
+typedef struct Siginfo Siginfo;
+typedef struct StackT StackT;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+typedef struct McontextT McontextT;
+typedef struct UcontextT UcontextT;
+
+#pragma pack on
+
+struct Sigaltstack {
+	byte	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
+};
+struct Sigset {
+	uint32	__bits[4];
+};
+struct Siginfo {
+	int32	_signo;
+	int32	_code;
+	int32	_errno;
+	byte	_reason[20];
+};
+
+struct StackT {
+	byte	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
+};
+
+struct Timespec {
+	int64	tv_sec;
+	int32	tv_nsec;
+};
+struct Timeval {
+	int64	tv_sec;
+	int32	tv_usec;
+};
+struct Itimerval {
+	Timeval	it_interval;
+	Timeval	it_value;
+};
+
+struct McontextT {
+	uint32	__gregs[17];
+#ifdef __ARM_EABI__
+	byte	__fpu[4+8*32+4];
+#else
+	byte	__fpu[4+4*33+4];
+#endif
+	uint32	_mc_tlsbase;
+};
+struct UcontextT {
+	uint32	uc_flags;
+	UcontextT	*uc_link;
+	Sigset	uc_sigmask;
+	StackT	uc_stack;
+	McontextT	uc_mcontext;
+	int32	__uc_pad[2];
+};
+
+#pragma pack off
diff --git a/src/pkg/runtime/defs_openbsd.go b/src/pkg/runtime/defs_openbsd.go
index 47c30cf..ff94b94 100644
--- a/src/pkg/runtime/defs_openbsd.go
+++ b/src/pkg/runtime/defs_openbsd.go
@@ -7,8 +7,8 @@
 /*
 Input to cgo.
 
-GOARCH=amd64 cgo -cdefs defs.go >amd64/defs.h
-GOARCH=386 cgo -cdefs defs.go >386/defs.h
+GOARCH=amd64 go tool cgo -cdefs defs_openbsd.go >defs_openbsd_amd64.h
+GOARCH=386 go tool cgo -cdefs defs_openbsd.go >defs_openbsd_386.h
 */
 
 package runtime
@@ -34,6 +34,8 @@ const (
 	MAP_PRIVATE = C.MAP_PRIVATE
 	MAP_FIXED   = C.MAP_FIXED
 
+	MADV_FREE = C.MADV_FREE
+
 	SA_SIGINFO = C.SA_SIGINFO
 	SA_RESTART = C.SA_RESTART
 	SA_ONSTACK = C.SA_ONSTACK
@@ -93,9 +95,12 @@ const (
 	ITIMER_PROF    = C.ITIMER_PROF
 )
 
+type Tfork C.struct___tfork
+
 type Sigaltstack C.struct_sigaltstack
-type Sigset C.sigset_t
+type Sigcontext C.struct_sigcontext
 type Siginfo C.siginfo_t
+type Sigset C.sigset_t
 type Sigval C.union_sigval
 
 type StackT C.stack_t
@@ -103,9 +108,3 @@ type StackT C.stack_t
 type Timespec C.struct_timespec
 type Timeval C.struct_timeval
 type Itimerval C.struct_itimerval
-
-// This is a hack to avoid pulling in machine/fpu.h.
-type sfxsave64 struct{}
-type usavefpu struct{}
-
-type Sigcontext C.struct_sigcontext
diff --git a/src/pkg/runtime/defs_openbsd_386.h b/src/pkg/runtime/defs_openbsd_386.h
index aff87fb..323bb08 100644
--- a/src/pkg/runtime/defs_openbsd_386.h
+++ b/src/pkg/runtime/defs_openbsd_386.h
@@ -1,146 +1,150 @@
-// godefs -f -m32 defs.c
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_openbsd.go
 
-// MACHINE GENERATED - DO NOT EDIT.
 
-// Constants
 enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x1,
-	FPE_INTOVF = 0x2,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-};
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
 
-// Types
-#pragma pack on
+	MAP_ANON	= 0x1000,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
 
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
-	void *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
-};
+	MADV_FREE	= 0x6,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x2,
+	SA_ONSTACK	= 0x1,
+
+	EINTR	= 0x4,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGEMT		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x10,
+	SIGSTOP		= 0x11,
+	SIGTSTP		= 0x12,
+	SIGCONT		= 0x13,
+	SIGCHLD		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGIO		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGINFO		= 0x1d,
+	SIGUSR1		= 0x1e,
+	SIGUSR2		= 0x1f,
+
+	FPE_INTDIV	= 0x1,
+	FPE_INTOVF	= 0x2,
+	FPE_FLTDIV	= 0x3,
+	FPE_FLTOVF	= 0x4,
+	FPE_FLTUND	= 0x5,
+	FPE_FLTRES	= 0x6,
+	FPE_FLTINV	= 0x7,
+	FPE_FLTSUB	= 0x8,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
 
-typedef uint32 Sigset;
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
 
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
+};
+
+typedef struct Tfork Tfork;
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigcontext Sigcontext;
 typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_code;
-	int32 si_errno;
-	byte _data[116];
+typedef struct StackT StackT;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+
+#pragma pack on
+
+struct Tfork {
+	byte	*tf_tcb;
+	int32	*tf_tid;
+	byte	*tf_stack;
 };
 
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
+struct Sigaltstack {
+	byte	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
 };
+struct Sigcontext {
+	int32	sc_gs;
+	int32	sc_fs;
+	int32	sc_es;
+	int32	sc_ds;
+	int32	sc_edi;
+	int32	sc_esi;
+	int32	sc_ebp;
+	int32	sc_ebx;
+	int32	sc_edx;
+	int32	sc_ecx;
+	int32	sc_eax;
+	int32	sc_eip;
+	int32	sc_cs;
+	int32	sc_eflags;
+	int32	sc_esp;
+	int32	sc_ss;
+	int32	sc_onstack;
+	int32	sc_mask;
+	int32	sc_trapno;
+	int32	sc_err;
+	void	*sc_fpstate;
+};
+struct Siginfo {
+	int32	si_signo;
+	int32	si_code;
+	int32	si_errno;
+	byte	_data[116];
+};
+typedef	uint32	Sigset;
+typedef	byte	Sigval[4];
 
-typedef struct StackT StackT;
 struct StackT {
-	void *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
+	byte	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
 };
 
-typedef struct Timespec Timespec;
 struct Timespec {
-	int32 tv_sec;
-	int32 tv_nsec;
+	int32	tv_sec;
+	int32	tv_nsec;
 };
-
-typedef struct Timeval Timeval;
 struct Timeval {
-	int32 tv_sec;
-	int32 tv_usec;
+	int32	tv_sec;
+	int32	tv_usec;
 };
-
-typedef struct Itimerval Itimerval;
 struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
+	Timeval	it_interval;
+	Timeval	it_value;
 };
 
-typedef void sfxsave64;
 
-typedef void usavefpu;
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
-	int32 sc_gs;
-	int32 sc_fs;
-	int32 sc_es;
-	int32 sc_ds;
-	int32 sc_edi;
-	int32 sc_esi;
-	int32 sc_ebp;
-	int32 sc_ebx;
-	int32 sc_edx;
-	int32 sc_ecx;
-	int32 sc_eax;
-	int32 sc_eip;
-	int32 sc_cs;
-	int32 sc_eflags;
-	int32 sc_esp;
-	int32 sc_ss;
-	int32 sc_onstack;
-	int32 sc_mask;
-	int32 sc_trapno;
-	int32 sc_err;
-	usavefpu *sc_fpstate;
-};
 #pragma pack off
diff --git a/src/pkg/runtime/defs_openbsd_amd64.h b/src/pkg/runtime/defs_openbsd_amd64.h
index 27bf4b9..429cc99 100644
--- a/src/pkg/runtime/defs_openbsd_amd64.h
+++ b/src/pkg/runtime/defs_openbsd_amd64.h
@@ -1,158 +1,162 @@
-// godefs -f -m64 defs.c
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_openbsd.go
 
-// MACHINE GENERATED - DO NOT EDIT.
 
-// Constants
 enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x1,
-	FPE_INTOVF = 0x2,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-};
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
 
-// Types
-#pragma pack on
+	MAP_ANON	= 0x1000,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
 
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
-	void *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
-};
+	MADV_FREE	= 0x6,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x2,
+	SA_ONSTACK	= 0x1,
+
+	EINTR	= 0x4,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGEMT		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x10,
+	SIGSTOP		= 0x11,
+	SIGTSTP		= 0x12,
+	SIGCONT		= 0x13,
+	SIGCHLD		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGIO		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGINFO		= 0x1d,
+	SIGUSR1		= 0x1e,
+	SIGUSR2		= 0x1f,
+
+	FPE_INTDIV	= 0x1,
+	FPE_INTOVF	= 0x2,
+	FPE_FLTDIV	= 0x3,
+	FPE_FLTOVF	= 0x4,
+	FPE_FLTUND	= 0x5,
+	FPE_FLTRES	= 0x6,
+	FPE_FLTINV	= 0x7,
+	FPE_FLTSUB	= 0x8,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
 
-typedef uint32 Sigset;
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
 
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
+};
+
+typedef struct Tfork Tfork;
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigcontext Sigcontext;
 typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_code;
-	int32 si_errno;
-	byte pad_godefs_0[4];
-	byte _data[120];
+typedef struct StackT StackT;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+
+#pragma pack on
+
+struct Tfork {
+	byte	*tf_tcb;
+	int32	*tf_tid;
+	byte	*tf_stack;
 };
 
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
+struct Sigaltstack {
+	byte	*ss_sp;
+	uint64	ss_size;
+	int32	ss_flags;
+	byte	Pad_cgo_0[4];
 };
+struct Sigcontext {
+	int64	sc_rdi;
+	int64	sc_rsi;
+	int64	sc_rdx;
+	int64	sc_rcx;
+	int64	sc_r8;
+	int64	sc_r9;
+	int64	sc_r10;
+	int64	sc_r11;
+	int64	sc_r12;
+	int64	sc_r13;
+	int64	sc_r14;
+	int64	sc_r15;
+	int64	sc_rbp;
+	int64	sc_rbx;
+	int64	sc_rax;
+	int64	sc_gs;
+	int64	sc_fs;
+	int64	sc_es;
+	int64	sc_ds;
+	int64	sc_trapno;
+	int64	sc_err;
+	int64	sc_rip;
+	int64	sc_cs;
+	int64	sc_rflags;
+	int64	sc_rsp;
+	int64	sc_ss;
+	void	*sc_fpstate;
+	int32	sc_onstack;
+	int32	sc_mask;
+};
+struct Siginfo {
+	int32	si_signo;
+	int32	si_code;
+	int32	si_errno;
+	byte	Pad_cgo_0[4];
+	byte	_data[120];
+};
+typedef	uint32	Sigset;
+typedef	byte	Sigval[8];
 
-typedef struct StackT StackT;
 struct StackT {
-	void *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
+	byte	*ss_sp;
+	uint64	ss_size;
+	int32	ss_flags;
+	byte	Pad_cgo_0[4];
 };
 
-typedef struct Timespec Timespec;
 struct Timespec {
-	int32 tv_sec;
-	byte pad_godefs_0[4];
-	int64 tv_nsec;
+	int32	tv_sec;
+	byte	Pad_cgo_0[4];
+	int64	tv_nsec;
 };
-
-typedef struct Timeval Timeval;
 struct Timeval {
-	int64 tv_sec;
-	int64 tv_usec;
+	int64	tv_sec;
+	int64	tv_usec;
 };
-
-typedef struct Itimerval Itimerval;
 struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
+	Timeval	it_interval;
+	Timeval	it_value;
 };
 
-typedef void sfxsave64;
 
-typedef void usavefpu;
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
-	int64 sc_rdi;
-	int64 sc_rsi;
-	int64 sc_rdx;
-	int64 sc_rcx;
-	int64 sc_r8;
-	int64 sc_r9;
-	int64 sc_r10;
-	int64 sc_r11;
-	int64 sc_r12;
-	int64 sc_r13;
-	int64 sc_r14;
-	int64 sc_r15;
-	int64 sc_rbp;
-	int64 sc_rbx;
-	int64 sc_rax;
-	int64 sc_gs;
-	int64 sc_fs;
-	int64 sc_es;
-	int64 sc_ds;
-	int64 sc_trapno;
-	int64 sc_err;
-	int64 sc_rip;
-	int64 sc_cs;
-	int64 sc_rflags;
-	int64 sc_rsp;
-	int64 sc_ss;
-	sfxsave64 *sc_fpstate;
-	int32 sc_onstack;
-	int32 sc_mask;
-};
 #pragma pack off
diff --git a/src/pkg/runtime/defs_plan9_386.h b/src/pkg/runtime/defs_plan9_386.h
index 58fd9d9..bde299d 100644
--- a/src/pkg/runtime/defs_plan9_386.h
+++ b/src/pkg/runtime/defs_plan9_386.h
@@ -1,2 +1,29 @@
-// nothing to see here
-#define tos_pid 48
+#define PAGESIZE 0x1000
+
+typedef struct Ureg Ureg;
+
+struct Ureg
+{
+	uint32	di;		/* general registers */
+	uint32	si;		/* ... */
+	uint32	bp;		/* ... */
+	uint32	nsp;
+	uint32	bx;		/* ... */
+	uint32	dx;		/* ... */
+	uint32	cx;		/* ... */
+	uint32	ax;		/* ... */
+	uint32	gs;		/* data segments */
+	uint32	fs;		/* ... */
+	uint32	es;		/* ... */
+	uint32	ds;		/* ... */
+	uint32	trap;		/* trap type */
+	uint32	ecode;		/* error code (or zero) */
+	uint32	pc;		/* pc */
+	uint32	cs;		/* old context */
+	uint32	flags;		/* old flags */
+	union {
+		uint32	usp;
+		uint32	sp;
+	};
+	uint32	ss;		/* old stack segment */
+};
diff --git a/src/pkg/runtime/defs_plan9_amd64.h b/src/pkg/runtime/defs_plan9_amd64.h
new file mode 100644
index 0000000..d8fec67
--- /dev/null
+++ b/src/pkg/runtime/defs_plan9_amd64.h
@@ -0,0 +1,34 @@
+#define PAGESIZE 0x200000ULL
+
+typedef struct Ureg Ureg;
+
+struct Ureg {
+	uint64	ax;
+	uint64	bx;
+	uint64	cx;
+	uint64	dx;
+	uint64	si;
+	uint64	di;
+	uint64	bp;
+	uint64	r8;
+	uint64	r9;
+	uint64	r10;
+	uint64	r11;
+	uint64	r12;
+	uint64	r13;
+	uint64	r14;
+	uint64	r15;
+
+	uint16	ds;
+	uint16	es;
+	uint16	fs;
+	uint16	gs;
+
+	uint64	type;
+	uint64	error;				/* error code (or zero) */
+	uint64	ip;				/* pc */
+	uint64	cs;				/* old context */
+	uint64	flags;				/* old flags */
+	uint64	sp;				/* sp */
+	uint64	ss;				/* old stack segment */
+};
diff --git a/src/pkg/runtime/env_plan9.c b/src/pkg/runtime/env_plan9.c
new file mode 100644
index 0000000..848d733
--- /dev/null
+++ b/src/pkg/runtime/env_plan9.c
@@ -0,0 +1,33 @@
+// 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, len, n, r;
+	byte file[128];
+	byte *p;
+
+	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(file, OREAD);
+	if(fd < 0)
+		return nil;
+	n = runtime·seek(fd, 0, 2);
+	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
new file mode 100644
index 0000000..8333811
--- /dev/null
+++ b/src/pkg/runtime/env_posix.c
@@ -0,0 +1,61 @@
+// 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 freebsd linux netbsd openbsd windows
+
+#include "runtime.h"
+
+Slice syscall·envs;
+
+byte*
+runtime·getenv(int8 *s)
+{
+	int32 i, j, 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];
+
+	if(_cgo_setenv == nil)
+		return;
+
+	arg[0] = runtime·malloc(k.len + 1);
+	runtime·memmove(arg[0], k.str, k.len);
+	arg[0][k.len] = 0;
+
+	arg[1] = runtime·malloc(v.len + 1);
+	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
index 5192113..062aea2 100644
--- a/src/pkg/runtime/export_test.go
+++ b/src/pkg/runtime/export_test.go
@@ -25,3 +25,45 @@ var Entersyscall = entersyscall
 var Exitsyscall = exitsyscall
 var LockedOSThread = golockedOSThread
 var Stackguard = stackguard
+
+type LFNode struct {
+	Next    *LFNode
+	Pushcnt uintptr
+}
+
+func lfstackpush(head *uint64, node *LFNode)
+func lfstackpop2(head *uint64) *LFNode
+
+var LFStackPush = lfstackpush
+var LFStackPop = lfstackpop2
+
+type ParFor struct {
+	body    *byte
+	done    uint32
+	Nthr    uint32
+	nthrmax uint32
+	thrseq  uint32
+	Cnt     uint32
+	Ctx     *byte
+	wait    bool
+}
+
+func parforalloc2(nthrmax uint32) *ParFor
+func parforsetup2(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 = parforalloc2
+var ParForSetup = parforsetup2
+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
diff --git a/src/pkg/runtime/extern.go b/src/pkg/runtime/extern.go
index d93259d..fbaffd1 100644
--- a/src/pkg/runtime/extern.go
+++ b/src/pkg/runtime/extern.go
@@ -42,8 +42,8 @@ type Func struct { // Keep in sync with runtime.h:struct Func
 	pc0    uintptr // starting pc, ln for table
 	ln0    int32
 	frame  int32 // stack frame size
-	args   int32 // number of 32-bit in/out args
-	locals int32 // number of 32-bit locals
+	args   int32 // in/out args size
+	locals int32 // locals size
 }
 
 // FuncForPC returns a *Func describing the function that contains the
@@ -67,7 +67,7 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
 // implemented in symtab.c
 func funcline_go(*Func, uintptr) (string, int)
 
-// mid returns the current os thread (m) id.
+// mid returns the current OS thread (m) id.
 func mid() uint32
 
 // SetFinalizer sets the finalizer associated with x to f.
diff --git a/src/pkg/runtime/float.c b/src/pkg/runtime/float.c
index f481519..42082e4 100644
--- a/src/pkg/runtime/float.c
+++ b/src/pkg/runtime/float.c
@@ -4,170 +4,7 @@
 
 #include "runtime.h"
 
-static	uint64	uvnan		= 0x7FF0000000000001ULL;
-static	uint64	uvinf		= 0x7FF0000000000000ULL;
-static	uint64	uvneginf	= 0xFFF0000000000000ULL;
-
-uint32
-runtime·float32tobits(float32 f)
-{
-	// The obvious cast-and-pointer code is technically
-	// not valid, and gcc miscompiles it.  Use a union instead.
-	union {
-		float32 f;
-		uint32 i;
-	} u;
-	u.f = f;
-	return u.i;
-}
-
-uint64
-runtime·float64tobits(float64 f)
-{
-	// The obvious cast-and-pointer code is technically
-	// not valid, and gcc miscompiles it.  Use a union instead.
-	union {
-		float64 f;
-		uint64 i;
-	} u;
-	u.f = f;
-	return u.i;
-}
-
-float64
-runtime·float64frombits(uint64 i)
-{
-	// The obvious cast-and-pointer code is technically
-	// not valid, and gcc miscompiles it.  Use a union instead.
-	union {
-		float64 f;
-		uint64 i;
-	} u;
-	u.i = i;
-	return u.f;
-}
-
-float32
-runtime·float32frombits(uint32 i)
-{
-	// The obvious cast-and-pointer code is technically
-	// not valid, and gcc miscompiles it.  Use a union instead.
-	union {
-		float32 f;
-		uint32 i;
-	} u;
-	u.i = i;
-	return u.f;
-}
-
-bool
-runtime·isInf(float64 f, int32 sign)
-{
-	uint64 x;
-
-	x = runtime·float64tobits(f);
-	if(sign == 0)
-		return x == uvinf || x == uvneginf;
-	if(sign > 0)
-		return x == uvinf;
-	return x == uvneginf;
-}
-
-float64
-runtime·NaN(void)
-{
-	return runtime·float64frombits(uvnan);
-}
-
-bool
-runtime·isNaN(float64 f)
-{
-	uint64 x;
-
-	x = runtime·float64tobits(f);
-	return ((uint32)(x>>52) & 0x7FF) == 0x7FF && !runtime·isInf(f, 0);
-}
-
-float64
-runtime·Inf(int32 sign)
-{
-	if(sign >= 0)
-		return runtime·float64frombits(uvinf);
-	else
-		return runtime·float64frombits(uvneginf);
-}
-
-enum
-{
-	MASK	= 0x7ffL,
-	SHIFT	= 64-11-1,
-	BIAS	= 1022L,
-};
-
-float64
-runtime·frexp(float64 d, int32 *ep)
-{
-	uint64 x;
-
-	if(d == 0) {
-		*ep = 0;
-		return 0;
-	}
-	x = runtime·float64tobits(d);
-	*ep = (int32)((x >> SHIFT) & MASK) - BIAS;
-	x &= ~((uint64)MASK << SHIFT);
-	x |= (uint64)BIAS << SHIFT;
-	return runtime·float64frombits(x);
-}
-
-float64
-runtime·ldexp(float64 d, int32 e)
-{
-	uint64 x;
-
-	if(d == 0)
-		return 0;
-	x = runtime·float64tobits(d);
-	e += (int32)(x >> SHIFT) & MASK;
-	if(e <= 0)
-		return 0;	/* underflow */
-	if(e >= MASK){		/* overflow */
-		if(d < 0)
-			return runtime·Inf(-1);
-		return runtime·Inf(1);
-	}
-	x &= ~((uint64)MASK << SHIFT);
-	x |= (uint64)e << SHIFT;
-	return runtime·float64frombits(x);
-}
-
-float64
-runtime·modf(float64 d, float64 *ip)
-{
-	float64 dd;
-	uint64 x;
-	int32 e;
-
-	if(d < 1) {
-		if(d < 0) {
-			d = runtime·modf(-d, ip);
-			*ip = -*ip;
-			return -d;
-		}
-		*ip = 0;
-		return d;
-	}
-
-	x = runtime·float64tobits(d);
-	e = (int32)((x >> SHIFT) & MASK) - BIAS;
-
-	/*
-	 * Keep the top 11+e bits; clear the rest.
-	 */
-	if(e <= 64-11)
-		x &= ~(((uint64)1 << (64LL-11LL-e))-1);
-	dd = runtime·float64frombits(x);
-	*ip = dd;
-	return d - dd;
-}
-
+// used as float64 via runtime· names
+uint64	·nan		= 0x7FF8000000000001ULL;
+uint64	·posinf	= 0x7FF0000000000000ULL;
+uint64	·neginf	= 0xFFF0000000000000ULL;
diff --git a/src/pkg/runtime/gc_test.go b/src/pkg/runtime/gc_test.go
index 65894a6..e1e1b1d 100644
--- a/src/pkg/runtime/gc_test.go
+++ b/src/pkg/runtime/gc_test.go
@@ -5,37 +5,80 @@
 package runtime_test
 
 import (
+	"os"
 	"runtime"
 	"testing"
 )
 
 func TestGcSys(t *testing.T) {
+	if os.Getenv("GOGC") == "off" {
+		t.Fatalf("GOGC=off in environment; test cannot pass")
+	}
+	data := struct{ Short bool }{testing.Short()}
+	got := executeTest(t, testGCSysSource, &data)
+	want := "OK\n"
+	if got != want {
+		t.Fatalf("expected %q, but got %q", want, got)
+	}
+}
+
+const testGCSysSource = `
+package main
+
+import (
+	"fmt"
+	"runtime"
+)
+
+func main() {
+	runtime.GOMAXPROCS(1)
 	memstats := new(runtime.MemStats)
 	runtime.GC()
 	runtime.ReadMemStats(memstats)
 	sys := memstats.Sys
 
+	runtime.MemProfileRate = 0 // disable profiler
+
 	itercount := 1000000
-	if testing.Short() {
-		itercount = 100000
-	}
+{{if .Short}}
+	itercount = 100000
+{{end}}
 	for i := 0; i < itercount; i++ {
 		workthegc()
 	}
 
 	// Should only be using a few MB.
+	// We allocated 100 MB or (if not short) 1 GB.
 	runtime.ReadMemStats(memstats)
 	if sys > memstats.Sys {
 		sys = 0
 	} else {
 		sys = memstats.Sys - sys
 	}
-	t.Logf("used %d extra bytes", sys)
-	if sys > 4<<20 {
-		t.Fatalf("using too much memory: %d bytes", sys)
+	if sys > 16<<20 {
+		fmt.Printf("using too much memory: %d bytes\n", sys)
+		return
 	}
+	fmt.Printf("OK\n")
 }
 
 func workthegc() []byte {
 	return make([]byte, 1029)
 }
+`
+
+func TestGcDeepNesting(t *testing.T) {
+	type T [2][2][2][2][2][2][2][2][2][2]*int
+	a := new(T)
+
+	// Prevent the compiler from applying escape analysis.
+	// This makes sure new(T) is allocated on heap, not on the stack.
+	t.Logf("%p", a)
+
+	a[0][0][0][0][0][0][0][0][0][0] = new(int)
+	*a[0][0][0][0][0][0][0][0][0][0] = 13
+	runtime.GC()
+	if *a[0][0][0][0][0][0][0][0][0][0] != 13 {
+		t.Fail()
+	}
+}
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c
index 63ed4e2..37111da 100644
--- a/src/pkg/runtime/hashmap.c
+++ b/src/pkg/runtime/hashmap.c
@@ -3,8 +3,11 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
 #include "hashmap.h"
 #include "type.h"
+#include "race.h"
 
 /* Hmap flag values */
 #define IndirectVal  (1<<0)	/* storing pointers to values */
@@ -13,7 +16,7 @@
 #define CanFreeKey (1<<3)	/* okay to free pointers to keys */
 
 struct Hmap {	   /* a hash table; initialize with hash_init() */
-	uint32 count;	  /* elements in table - must be first */
+	uintgo count;	  /* elements in table - must be first */
 	uint8 datasize;   /* amount of data to store in entry */
 	uint8 flag;
 	uint8 valoff;	/* offset of value in key+value data block */
@@ -78,7 +81,7 @@ hash_subtable_new (Hmap *h, int32 power, int32 used)
 		max_probes = 1 << power;
 	}
 	bytes += limit_bytes - elemsize;
-	st = malloc (offsetof (struct hash_subtable, entry[0]) + bytes);
+	st = runtime·mallocgc(offsetof (struct hash_subtable, entry[0]) + bytes, UseSpanType ? FlagNoPointers : 0, 1, 1);
 	st->power = power;
 	st->used = used;
 	st->datasize = h->datasize;
@@ -115,7 +118,7 @@ hash_init (Hmap *h, int32 datasize, int64 hint)
 
 	if(datasize < sizeof (void *))
 		datasize = sizeof (void *);
-	datasize = runtime·rnd(datasize, sizeof (void *));
+	datasize = ROUND(datasize, sizeof (void *));
 	init_sizes (hint, &init_power);
 	h->datasize = datasize;
 	assert (h->datasize == datasize);
@@ -273,7 +276,7 @@ hash_lookup (MapType *t, Hmap *h, void *data, void **pres)
 	struct hash_entry *end_e;
 	void *key;
 	bool eq;
-	
+
 	hash = h->hash0;
 	(*t->key->alg->hash) (&hash, t->key->size, data);
 	hash &= ~HASH_MASK;
@@ -416,8 +419,12 @@ hash_insert_internal (MapType *t, struct hash_subtable **pst, int32 flags, hash_
 					*pres = ins_e->data;
 					return (1);
 				}
-				assert (e_hash != hash || (flags & HASH_REHASH) == 0);
-				hash += (e_hash == hash);	   /* adjust hash if it collides */
+				if (e_hash == hash) {	   /* adjust hash if it collides */
+					assert ((flags & HASH_REHASH) == 0);
+					hash++;
+					if ((hash & HASH_MASK) == HASH_SUBHASH)
+						runtime·throw("runtime: map hash collision overflow");
+				}
 				ins_e = HASH_OFFSET (ins_e, elemsize);
 				ins_i++;
 				if (e_hash <= hash) {	       /* set e to insertion point */
@@ -462,7 +469,7 @@ hash_insert (MapType *t, Hmap *h, void *data, void **pres)
 {
 	uintptr hash;
 	int32 rc;
-	
+
 	hash = h->hash0;
 	(*t->key->alg->hash) (&hash, t->key->size, data);
 	rc = hash_insert_internal (t, &h->st, 0, hash, h, data, pres);
@@ -618,7 +625,7 @@ hash_iter_init (MapType *t, Hmap *h, struct hash_iter *it)
 	it->subtable_state[0].e = h->st->entry;
 	it->subtable_state[0].start = h->st->entry;
 	it->subtable_state[0].last = h->st->last;
-	
+
 	// fastrand1 returns 31 useful bits.
 	// We don't care about not having a bottom bit but we
 	// do want top bits.
@@ -700,6 +707,82 @@ hash_visit (Hmap *h, void (*data_visit) (void *arg, int32 level, void *data), vo
 	hash_visit_internal (h->st, 0, 0, data_visit, arg);
 }
 
+// Initialize the iterator.
+// Returns false if Hmap contains no pointers (in which case the iterator is not initialized).
+bool
+hash_gciter_init (Hmap *h, struct hash_gciter *it)
+{
+	// GC during map initialization
+	if(h->st == nil)
+		return false;
+
+	it->elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
+	it->flag = h->flag;
+	it->valoff = h->valoff;
+	it->i = 0;
+	it->st = h->st;
+	it->subtable_state[it->i].e = h->st->entry;
+	it->subtable_state[it->i].last = h->st->last;
+	return true;
+}
+
+// Returns true and fills *data with subtable/key/value data,
+// or returns false if the iterator has terminated.
+bool
+hash_gciter_next (struct hash_gciter *it, struct hash_gciter_data *data)
+{
+	struct hash_entry *e;
+	struct hash_gciter_sub *sub;
+
+	data->st = nil;
+	data->key_data = nil;
+	data->val_data = nil;
+
+	// pointer to the first-level table
+	if(it->st != nil) {
+		data->st = it->st;
+		it->st = nil;
+		return true;
+	}
+
+popped:
+	sub = &it->subtable_state[it->i];
+	e = sub->e;
+	while (e <= sub->last) {
+		if ((e->hash & HASH_MASK) == HASH_SUBHASH) {
+			struct hash_subtable *st = *(struct hash_subtable **)e->data;
+			data->st = st;
+			sub->e = HASH_OFFSET (e, it->elemsize);
+
+			// push
+			it->i++;
+			assert (it->i < nelem(it->subtable_state));
+			sub++;
+			sub->e = st->entry;
+			sub->last = st->last;
+
+			return true;
+		}
+		if(e->hash != HASH_NIL) {
+			void *key_data = e->data;
+			void *val_data = (byte*)e->data + it->valoff;
+			data->key_data = key_data;
+			data->val_data = val_data;
+			data->indirectkey = (it->flag & IndirectKey) != 0;
+			data->indirectval = (it->flag & IndirectVal) != 0;
+			sub->e = HASH_OFFSET (e, it->elemsize);
+			return true;
+		}
+		e = HASH_OFFSET (e, it->elemsize);
+	}
+	if(it->i != 0) {
+		// pop
+		it->i--;
+		goto popped;
+	}
+	return false;
+}
+
 //
 /// interfaces to go runtime
 //
@@ -724,14 +807,13 @@ hash_keyptr(Hmap *h, void *p)
 
 static	int32	debug	= 0;
 
-// makemap(typ *Type, hint uint32) (hmap *map[any]any);
 Hmap*
 runtime·makemap_c(MapType *typ, int64 hint)
 {
 	Hmap *h;
 	Type *key, *val;
 	uintptr ksize, vsize;
-	
+
 	key = typ->key;
 	val = typ->elem;
 
@@ -744,8 +826,15 @@ runtime·makemap_c(MapType *typ, int64 hint)
 	h = runtime·mal(sizeof(*h));
 	h->flag |= CanFreeTable;  /* until reflect gets involved, free is okay */
 
-	ksize = runtime·rnd(key->size, sizeof(void*));
-	vsize = runtime·rnd(val->size, sizeof(void*));
+	if(UseSpanType) {
+		if(false) {
+			runtime·printf("makemap %S: %p\n", *typ->string, h);
+		}
+		runtime·settype(h, (uintptr)typ | TypeInfo_Map);
+	}
+
+	ksize = ROUND(key->size, sizeof(void*));
+	vsize = ROUND(val->size, sizeof(void*));
 	if(ksize > MaxData || vsize > MaxData || ksize+vsize > MaxData) {
 		// Either key is too big, or value is, or combined they are.
 		// Prefer to keep the key if possible, because we look at
@@ -828,8 +917,11 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...)
 	byte *ak, *av;
 	bool pres;
 
+	if(raceenabled && h != nil)
+		runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess1);
+
 	ak = (byte*)(&h + 1);
-	av = ak + runtime·rnd(t->key->size, Structrnd);
+	av = ak + ROUND(t->key->size, Structrnd);
 
 	runtime·mapaccess(t, h, ak, av, &pres);
 
@@ -853,8 +945,11 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...)
 {
 	byte *ak, *av, *ap;
 
+	if(raceenabled && h != nil)
+		runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess2);
+
 	ak = (byte*)(&h + 1);
-	av = ak + runtime·rnd(t->key->size, Structrnd);
+	av = ak + ROUND(t->key->size, Structrnd);
 	ap = av + t->elem->size;
 
 	runtime·mapaccess(t, h, ak, av, ap);
@@ -881,6 +976,9 @@ reflect·mapaccess(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
 {
 	byte *ak, *av;
 
+	if(raceenabled && h != nil)
+		runtime·racereadpc(h, runtime·getcallerpc(&t), reflect·mapaccess);
+
 	if(t->key->size <= sizeof(key))
 		ak = (byte*)&key;
 	else
@@ -951,8 +1049,10 @@ runtime·mapassign1(MapType *t, Hmap *h, ...)
 	if(h == nil)
 		runtime·panicstring("assignment to entry in nil map");
 
+	if(raceenabled)
+		runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapassign1);
 	ak = (byte*)(&h + 1);
-	av = ak + runtime·rnd(t->key->size, t->elem->align);
+	av = ak + ROUND(t->key->size, t->elem->align);
 
 	runtime·mapassign(t, h, ak, av);
 }
@@ -965,8 +1065,10 @@ runtime·mapdelete(MapType *t, Hmap *h, ...)
 	byte *ak;
 
 	if(h == nil)
-		runtime·panicstring("deletion of entry in nil map");
+		return;
 
+	if(raceenabled)
+		runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapdelete);
 	ak = (byte*)(&h + 1);
 	runtime·mapassign(t, h, ak, nil);
 
@@ -990,6 +1092,8 @@ reflect·mapassign(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
 
 	if(h == nil)
 		runtime·panicstring("assignment to entry in nil map");
+	if(raceenabled)
+		runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign);
 	if(t->key->size <= sizeof(key))
 		ak = (byte*)&key;
 	else
@@ -1011,6 +1115,8 @@ runtime·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it)
 		it->data = nil;
 		return;
 	}
+	if(raceenabled)
+		runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapiterinit);
 	hash_iter_init(t, h, it);
 	it->data = hash_next(it);
 	if(debug) {
@@ -1054,6 +1160,8 @@ reflect·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it)
 void
 runtime·mapiternext(struct hash_iter *it)
 {
+	if(raceenabled)
+		runtime·racereadpc(it->h, runtime·getcallerpc(&it), runtime·mapiternext);
 	if(runtime·gcwaiting)
 		runtime·gosched();
 
@@ -1148,15 +1256,18 @@ reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok)
 }
 
 // For reflect:
-//	func maplen(h map) (len int32)
+//	func maplen(h map) (len int)
 // Like len(m) in the actual language, we treat the nil map as length 0.
 void
-reflect·maplen(Hmap *h, int32 len)
+reflect·maplen(Hmap *h, intgo len)
 {
 	if(h == nil)
 		len = 0;
-	else
+	else {
 		len = h->count;
+		if(raceenabled)
+			runtime·racereadpc(h, runtime·getcallerpc(&h), reflect·maplen);
+	}
 	FLUSH(&len);
 }
 
@@ -1171,7 +1282,7 @@ runtime·mapiter2(struct hash_iter *it, ...)
 
 	t = it->t;
 	ak = (byte*)(&it + 1);
-	av = ak + runtime·rnd(t->key->size, t->elem->align);
+	av = ak + ROUND(t->key->size, t->elem->align);
 
 	res = it->data;
 	if(res == nil)
diff --git a/src/pkg/runtime/hashmap.h b/src/pkg/runtime/hashmap.h
index 4c10cf6..9b82f29 100644
--- a/src/pkg/runtime/hashmap.h
+++ b/src/pkg/runtime/hashmap.h
@@ -63,7 +63,6 @@
 	}
  */
 
-#define	malloc		runtime·mal
 #define	memset(a,b,c)	runtime·memclr((byte*)(a), (uint32)(c))
 #define	memcpy(a,b,c)	runtime·memmove((byte*)(a),(byte*)(b),(uint32)(c))
 #define	assert(a)	if(!(a)) runtime·throw("hashmap assert")
@@ -143,7 +142,7 @@ struct hash_iter {
    Remove all sub-tables associated with *h.
    This undoes the effects of hash_init().
    If other memory pointed to by user data must be freed, the caller is
-   responsible for doiing do by iterating over *h first; see
+   responsible for doing so by iterating over *h first; see
    hash_iter_init()/hash_next().  */
 // void hash_destroy (struct hash *h);
 
@@ -152,7 +151,7 @@ struct hash_iter {
 /* Initialize *it from *h. */
 // void hash_iter_init (struct hash *h, struct hash_iter *it);
 
-/* Return the next used entry in the table which which *it was initialized. */
+/* Return the next used entry in the table with which *it was initialized. */
 // void *hash_next (struct hash_iter *it);
 
 /*---- test interface ----*/
@@ -160,3 +159,27 @@ struct hash_iter {
    whether used or not.   "level" is the subtable level, 0 means first level. */
 /* TESTING ONLY: DO NOT USE THIS ROUTINE IN NORMAL CODE */
 // void hash_visit (struct hash *h, void (*data_visit) (void *arg, int32 level, void *data), void *arg);
+
+/* Used by the garbage collector */
+struct hash_gciter
+{
+	int32	elemsize;
+	uint8	flag;
+	uint8	valoff;
+	uint32	i;		/* stack pointer in subtable_state */
+	struct hash_subtable *st;
+	struct hash_gciter_sub {
+		struct hash_entry *e;		/* pointer into subtable */
+		struct hash_entry *last;	/* last entry in subtable */
+	} subtable_state[4];
+};
+struct hash_gciter_data
+{
+	struct hash_subtable *st;	/* subtable pointer, or nil */
+	uint8 *key_data;		/* key data, or nil */
+	uint8 *val_data;		/* value data, or nil */
+	bool indirectkey;		/* storing pointers to keys */
+	bool indirectval;		/* storing pointers to values */
+};
+bool hash_gciter_init (struct Hmap *h, struct hash_gciter *it);
+bool hash_gciter_next (struct hash_gciter *it, struct hash_gciter_data *data);
diff --git a/src/pkg/runtime/iface.c b/src/pkg/runtime/iface.c
index 2b60c4f..370edff 100644
--- a/src/pkg/runtime/iface.c
+++ b/src/pkg/runtime/iface.c
@@ -5,6 +5,7 @@
 #include "runtime.h"
 #include "arch_GOARCH.h"
 #include "type.h"
+#include "typekind.h"
 #include "malloc.h"
 
 void
@@ -19,19 +20,6 @@ runtime·printeface(Eface e)
 	runtime·printf("(%p,%p)", e.type, e.data);
 }
 
-/*
- * layout of Itab known to compilers
- */
-struct Itab
-{
-	InterfaceType*	inter;
-	Type*	type;
-	Itab*	link;
-	int32	bad;
-	int32	unused;
-	void	(*fun[])(void);
-};
-
 static	Itab*	hash[1009];
 static	Lock	ifacelock;
 
@@ -182,19 +170,37 @@ copyout(Type *t, void **src, void *dst)
 		alg->copy(size, dst, *src);
 }
 
-// func convT2I(typ *byte, typ2 *byte, elem any) (ret any)
 #pragma textflag 7
 void
-runtime·convT2I(Type *t, InterfaceType *inter, ...)
+runtime·typ2Itab(Type *t, InterfaceType *inter, Itab **cache, Itab *ret)
+{
+	Itab *tab;
+
+	tab = itab(inter, t, 0);
+	runtime·atomicstorep(cache, tab);
+	ret = tab;
+	FLUSH(&ret);
+}
+
+// func convT2I(typ *byte, typ2 *byte, cache **byte, elem any) (ret any)
+#pragma textflag 7
+void
+runtime·convT2I(Type *t, InterfaceType *inter, Itab **cache, ...)
 {
 	byte *elem;
 	Iface *ret;
+	Itab *tab;
 	int32 wid;
 
-	elem = (byte*)(&inter+1);
+	elem = (byte*)(&cache+1);
 	wid = t->size;
-	ret = (Iface*)(elem + runtime·rnd(wid, Structrnd));
-	ret->tab = itab(inter, t, 0);
+	ret = (Iface*)(elem + ROUND(wid, Structrnd));
+	tab = runtime·atomicloadp(cache);
+	if(!tab) {
+		tab = itab(inter, t, 0);
+		runtime·atomicstorep(cache, tab);
+	}
+	ret->tab = tab;
 	copyin(t, elem, &ret->data);
 }
 
@@ -209,7 +215,7 @@ runtime·convT2E(Type *t, ...)
 
 	elem = (byte*)(&t+1);
 	wid = t->size;
-	ret = (Eface*)(elem + runtime·rnd(wid, Structrnd));
+	ret = (Eface*)(elem + ROUND(wid, Structrnd));
 	ret->type = t;
 	copyin(t, elem, &ret->data);
 }
@@ -272,6 +278,13 @@ runtime·assertI2T2(Type *t, Iface i, ...)
 	copyout(t, &i.data, ret);
 }
 
+void
+runtime·assertI2TOK(Type *t, Iface i, bool ok)
+{
+	ok = i.tab!=nil && i.tab->type==t;
+	FLUSH(&ok);
+}
+
 static void assertE2Tret(Type *t, Eface e, byte *ret);
 
 // func ifaceE2T(typ *byte, iface any) (ret any)
@@ -328,6 +341,13 @@ runtime·assertE2T2(Type *t, Eface e, ...)
 	copyout(t, &e.data, ret);
 }
 
+void
+runtime·assertE2TOK(Type *t, Eface e, bool ok)
+{
+	ok = t==e.type;
+	FLUSH(&ok);
+}
+
 // func convI2E(elem any) (ret any)
 void
 runtime·convI2E(Iface i, Eface ret)
@@ -387,7 +407,7 @@ void
 runtime·convI2I(InterfaceType* inter, Iface i, Iface ret)
 {
 	Itab *tab;
-	
+
 	ret.data = i.data;
 	if((tab = i.tab) == nil)
 		ret.tab = nil;
@@ -526,10 +546,10 @@ runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok)
 }
 
 static uintptr
-ifacehash1(void *data, Type *t)
+ifacehash1(void *data, Type *t, uintptr h)
 {
 	Alg *alg;
-	uintptr size, h;
+	uintptr size;
 	Eface err;
 
 	if(t == nil)
@@ -543,7 +563,6 @@ ifacehash1(void *data, Type *t)
 		runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"hash of unhashable type "), *t->string), &err);
 		runtime·panic(err);
 	}
-	h = 0;
 	if(size <= sizeof(data))
 		alg->hash(&h, size, &data);
 	else
@@ -552,17 +571,17 @@ ifacehash1(void *data, Type *t)
 }
 
 uintptr
-runtime·ifacehash(Iface a)
+runtime·ifacehash(Iface a, uintptr h)
 {
 	if(a.tab == nil)
-		return 0;
-	return ifacehash1(a.data, a.tab->type);
+		return h;
+	return ifacehash1(a.data, a.tab->type, h);
 }
 
 uintptr
-runtime·efacehash(Eface a)
+runtime·efacehash(Eface a, uintptr h)
 {
-	return ifacehash1(a.data, a.type);
+	return ifacehash1(a.data, a.type, h);
 }
 
 static bool
@@ -666,39 +685,54 @@ reflect·unsafe_Typeof(Eface e, Eface ret)
 }
 
 void
-reflect·unsafe_New(Eface typ, void *ret)
+reflect·unsafe_New(Type *t, void *ret)
 {
-	Type *t;
+	uint32 flag;
 
-	// Reflect library has reinterpreted typ
-	// as its own kind of type structure.
-	// We know that the pointer to the original
-	// type structure sits before the data pointer.
-	t = (Type*)((Eface*)typ.data-1);
+	flag = t->kind&KindNoPointers ? FlagNoPointers : 0;
+	ret = runtime·mallocgc(t->size, flag, 1, 1);
+
+	if(UseSpanType && !flag) {
+		if(false) {
+			runtime·printf("unsafe_New %S: %p\n", *t->string, ret);
+		}
+		runtime·settype(ret, (uintptr)t | TypeInfo_SingleObject);
+	}
 
-	if(t->kind&KindNoPointers)
-		ret = runtime·mallocgc(t->size, FlagNoPointers, 1, 1);
-	else
-		ret = runtime·mal(t->size);
 	FLUSH(&ret);
 }
 
 void
-reflect·unsafe_NewArray(Eface typ, uint32 n, void *ret)
+reflect·unsafe_NewArray(Type *t, intgo n, void *ret)
 {
 	uint64 size;
-	Type *t;
 
-	// Reflect library has reinterpreted typ
-	// as its own kind of type structure.
-	// We know that the pointer to the original
-	// type structure sits before the data pointer.
-	t = (Type*)((Eface*)typ.data-1);
-	
 	size = n*t->size;
-	if(t->kind&KindNoPointers)
+	if(size == 0)
+		ret = (byte*)&runtime·zerobase;
+	else if(t->kind&KindNoPointers)
 		ret = runtime·mallocgc(size, FlagNoPointers, 1, 1);
-	else
-		ret = runtime·mal(size);
+	else {
+		ret = runtime·mallocgc(size, 0, 1, 1);
+
+		if(UseSpanType) {
+			if(false) {
+				runtime·printf("unsafe_NewArray [%D]%S: %p\n", (int64)n, *t->string, ret);
+			}
+			runtime·settype(ret, (uintptr)t | TypeInfo_Array);
+		}
+	}
+
+	FLUSH(&ret);
+}
+
+void
+reflect·typelinks(Slice ret)
+{
+	extern Type *typelink[], *etypelink[];
+	static int32 first = 1;
+	ret.array = (byte*)typelink;
+	ret.len = etypelink - typelink;
+	ret.cap = ret.len;
 	FLUSH(&ret);
 }
diff --git a/src/pkg/runtime/iface_test.go b/src/pkg/runtime/iface_test.go
new file mode 100644
index 0000000..bca0ea0
--- /dev/null
+++ b/src/pkg/runtime/iface_test.go
@@ -0,0 +1,138 @@
+// 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"
+)
+
+type I1 interface {
+	Method1()
+}
+
+type I2 interface {
+	Method1()
+	Method2()
+}
+
+type TS uint16
+type TM uintptr
+type TL [2]uintptr
+
+func (TS) Method1() {}
+func (TS) Method2() {}
+func (TM) Method1() {}
+func (TM) Method2() {}
+func (TL) Method1() {}
+func (TL) Method2() {}
+
+var (
+	e  interface{}
+	e_ interface{}
+	i1 I1
+	i2 I2
+	ts TS
+	tm TM
+	tl TL
+)
+
+func BenchmarkConvT2ESmall(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		e = ts
+	}
+}
+
+func BenchmarkConvT2EUintptr(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		e = tm
+	}
+}
+
+func BenchmarkConvT2ELarge(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		e = tl
+	}
+}
+
+func BenchmarkConvT2ISmall(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		i1 = ts
+	}
+}
+
+func BenchmarkConvT2IUintptr(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		i1 = tm
+	}
+}
+
+func BenchmarkConvT2ILarge(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		i1 = tl
+	}
+}
+
+func BenchmarkConvI2E(b *testing.B) {
+	i2 = tm
+	for i := 0; i < b.N; i++ {
+		e = i2
+	}
+}
+
+func BenchmarkConvI2I(b *testing.B) {
+	i2 = tm
+	for i := 0; i < b.N; i++ {
+		i1 = i2
+	}
+}
+
+func BenchmarkAssertE2T(b *testing.B) {
+	e = tm
+	for i := 0; i < b.N; i++ {
+		tm = e.(TM)
+	}
+}
+
+func BenchmarkAssertE2TLarge(b *testing.B) {
+	e = tl
+	for i := 0; i < b.N; i++ {
+		tl = e.(TL)
+	}
+}
+
+func BenchmarkAssertE2I(b *testing.B) {
+	e = tm
+	for i := 0; i < b.N; i++ {
+		i1 = e.(I1)
+	}
+}
+
+func BenchmarkAssertI2T(b *testing.B) {
+	i1 = tm
+	for i := 0; i < b.N; i++ {
+		tm = i1.(TM)
+	}
+}
+
+func BenchmarkAssertI2I(b *testing.B) {
+	i1 = tm
+	for i := 0; i < b.N; i++ {
+		i2 = i1.(I2)
+	}
+}
+
+func BenchmarkAssertI2E(b *testing.B) {
+	i1 = tm
+	for i := 0; i < b.N; i++ {
+		e = i1.(interface{})
+	}
+}
+
+func BenchmarkAssertE2E(b *testing.B) {
+	e = tm
+	for i := 0; i < b.N; i++ {
+		e_ = e
+	}
+}
diff --git a/src/pkg/runtime/lfstack.c b/src/pkg/runtime/lfstack.c
new file mode 100644
index 0000000..1d48491
--- /dev/null
+++ b/src/pkg/runtime/lfstack.c
@@ -0,0 +1,65 @@
+// 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.
+
+// Lock-free stack.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+
+#ifdef _64BIT
+// Amd64 uses 48-bit virtual addresses, 47-th bit is used as kernel/user flag.
+// So we use 17msb of pointers as ABA counter.
+# define PTR_BITS 47
+#else
+# define PTR_BITS 32
+#endif
+#define PTR_MASK ((1ull<<PTR_BITS)-1)
+#define CNT_MASK (0ull-1)
+
+void
+runtime·lfstackpush(uint64 *head, LFNode *node)
+{
+	uint64 old, new;
+
+	if((uintptr)node != ((uintptr)node&PTR_MASK)) {
+		runtime·printf("p=%p\n", node);
+		runtime·throw("runtime·lfstackpush: invalid pointer");
+	}
+
+	node->pushcnt++;
+	new = (uint64)(uintptr)node|(((uint64)node->pushcnt&CNT_MASK)<<PTR_BITS);
+	old = runtime·atomicload64(head);
+	for(;;) {
+		node->next = (LFNode*)(uintptr)(old&PTR_MASK);
+		if(runtime·cas64(head, &old, new))
+			break;
+	}
+}
+
+LFNode*
+runtime·lfstackpop(uint64 *head)
+{
+	LFNode *node, *node2;
+	uint64 old, new;
+
+	old = runtime·atomicload64(head);
+	for(;;) {
+		if(old == 0)
+			return nil;
+		node = (LFNode*)(uintptr)(old&PTR_MASK);
+		node2 = runtime·atomicloadp(&node->next);
+		new = 0;
+		if(node2 != nil)
+			new = (uint64)(uintptr)node2|(((uint64)node2->pushcnt&CNT_MASK)<<PTR_BITS);
+		if(runtime·cas64(head, &old, new))
+			return node;
+	}
+}
+
+void
+runtime·lfstackpop2(uint64 *head, LFNode *node)
+{
+	node = runtime·lfstackpop(head);
+	FLUSH(&node);
+}
diff --git a/src/pkg/runtime/lfstack_test.go b/src/pkg/runtime/lfstack_test.go
new file mode 100644
index 0000000..505aae6
--- /dev/null
+++ b/src/pkg/runtime/lfstack_test.go
@@ -0,0 +1,130 @@
+// 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 (
+	"math/rand"
+	. "runtime"
+	"testing"
+	"unsafe"
+)
+
+type MyNode struct {
+	LFNode
+	data int
+}
+
+func fromMyNode(node *MyNode) *LFNode {
+	return (*LFNode)(unsafe.Pointer(node))
+}
+
+func toMyNode(node *LFNode) *MyNode {
+	return (*MyNode)(unsafe.Pointer(node))
+}
+
+func TestLFStack(t *testing.T) {
+	stack := new(uint64)
+	// Need to keep additional referenfces to nodes, the stack is not all that type-safe.
+	var nodes []*MyNode
+
+	// Check the stack is initially empty.
+	if LFStackPop(stack) != nil {
+		t.Fatalf("stack is not empty")
+	}
+
+	// Push one element.
+	node := &MyNode{data: 42}
+	nodes = append(nodes, node)
+	LFStackPush(stack, fromMyNode(node))
+
+	// Push another.
+	node = &MyNode{data: 43}
+	nodes = append(nodes, node)
+	LFStackPush(stack, fromMyNode(node))
+
+	// Pop one element.
+	node = toMyNode(LFStackPop(stack))
+	if node == nil {
+		t.Fatalf("stack is empty")
+	}
+	if node.data != 43 {
+		t.Fatalf("no lifo")
+	}
+
+	// Pop another.
+	node = toMyNode(LFStackPop(stack))
+	if node == nil {
+		t.Fatalf("stack is empty")
+	}
+	if node.data != 42 {
+		t.Fatalf("no lifo")
+	}
+
+	// Check the stack is empty again.
+	if LFStackPop(stack) != nil {
+		t.Fatalf("stack is not empty")
+	}
+	if *stack != 0 {
+		t.Fatalf("stack is not empty")
+	}
+}
+
+func TestLFStackStress(t *testing.T) {
+	const K = 100
+	P := 4 * GOMAXPROCS(-1)
+	N := 100000
+	if testing.Short() {
+		N /= 10
+	}
+	// Create 2 stacks.
+	stacks := [2]*uint64{new(uint64), new(uint64)}
+	// Need to keep additional referenfces to nodes, the stack is not all that type-safe.
+	var nodes []*MyNode
+	// Push K elements randomly onto the stacks.
+	sum := 0
+	for i := 0; i < K; i++ {
+		sum += i
+		node := &MyNode{data: i}
+		nodes = append(nodes, node)
+		LFStackPush(stacks[i%2], fromMyNode(node))
+	}
+	c := make(chan bool, P)
+	for p := 0; p < P; p++ {
+		go func() {
+			r := rand.New(rand.NewSource(rand.Int63()))
+			// Pop a node from a random stack, then push it onto a random stack.
+			for i := 0; i < N; i++ {
+				node := toMyNode(LFStackPop(stacks[r.Intn(2)]))
+				if node != nil {
+					LFStackPush(stacks[r.Intn(2)], fromMyNode(node))
+				}
+			}
+			c <- true
+		}()
+	}
+	for i := 0; i < P; i++ {
+		<-c
+	}
+	// Pop all elements from both stacks, and verify that nothing lost.
+	sum2 := 0
+	cnt := 0
+	for i := 0; i < 2; i++ {
+		for {
+			node := toMyNode(LFStackPop(stacks[i]))
+			if node == nil {
+				break
+			}
+			cnt++
+			sum2 += node.data
+			node.Next = nil
+		}
+	}
+	if cnt != K {
+		t.Fatalf("Wrong number of nodes %d/%d", cnt, K)
+	}
+	if sum2 != sum {
+		t.Fatalf("Wrong sum %d/%d", sum2, sum)
+	}
+}
diff --git a/src/pkg/runtime/lock_futex.c b/src/pkg/runtime/lock_futex.c
index b4465bf..9b1f5f6 100644
--- a/src/pkg/runtime/lock_futex.c
+++ b/src/pkg/runtime/lock_futex.c
@@ -111,7 +111,8 @@ runtime·noteclear(Note *n)
 void
 runtime·notewakeup(Note *n)
 {
-	runtime·xchg(&n->key, 1);
+	if(runtime·xchg(&n->key, 1))
+		runtime·throw("notewakeup - double wakeup");
 	runtime·futexwakeup(&n->key, 1);
 }
 
diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc
index 9ae3a9d..ac131b3 100644
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -9,17 +9,18 @@
 package runtime
 #include "runtime.h"
 #include "arch_GOARCH.h"
-#include "stack.h"
 #include "malloc.h"
-#include "defs_GOOS_GOARCH.h"
 #include "type.h"
+#include "typekind.h"
+#include "race.h"
 
-#pragma dataflag 16 /* mark mheap as 'no pointers', hiding from garbage collector */
-MHeap runtime·mheap;
+MHeap *runtime·mheap;
 
-extern MStats mstats;	// defined in extern.go
+int32	runtime·checking;
 
-extern volatile int32 runtime·MemProfileRate;
+extern MStats mstats;	// defined in zruntime_def_$GOOS_$GOARCH.go
+
+extern volatile intgo runtime·MemProfileRate;
 
 // Allocate an object of at least size bytes.
 // Small objects are allocated from the per-thread cache's free lists.
@@ -27,7 +28,8 @@ extern volatile int32 runtime·MemProfileRate;
 void*
 runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
 {
-	int32 sizeclass, rate;
+	int32 sizeclass;
+	intgo rate;
 	MCache *c;
 	uintptr npages;
 	MSpan *s;
@@ -41,6 +43,9 @@ runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
 	if(size == 0)
 		size = 1;
 
+	if(DebugTypeAtBlockEnd)
+		size += sizeof(uintptr);
+
 	c = m->mcache;
 	c->local_nmalloc++;
 	if(size <= MaxSmallSize) {
@@ -60,7 +65,7 @@ runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
 		npages = size >> PageShift;
 		if((size & PageMask) != 0)
 			npages++;
-		s = runtime·MHeap_Alloc(&runtime·mheap, npages, 0, 1);
+		s = runtime·MHeap_Alloc(runtime·mheap, npages, 0, 1, zeroed);
 		if(s == nil)
 			runtime·throw("out of memory");
 		size = npages<<PageShift;
@@ -71,9 +76,20 @@ runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
 		// setup for mark sweep
 		runtime·markspan(v, 0, 0, true);
 	}
+
+	if (sizeof(void*) == 4 && c->local_total_alloc >= (1<<30)) {
+		// purge cache stats to prevent overflow
+		runtime·lock(runtime·mheap);
+		runtime·purgecachedstats(c);
+		runtime·unlock(runtime·mheap);
+	}
+
 	if(!(flag & FlagNoGC))
 		runtime·markallocated(v, size, (flag&FlagNoPointers) != 0);
 
+	if(DebugTypeAtBlockEnd)
+		*(uintptr*)((uintptr)v+size-sizeof(uintptr)) = 0;
+
 	m->mallocing = 0;
 
 	if(!(flag & FlagNoProfiling) && (rate = runtime·MemProfileRate) > 0) {
@@ -95,6 +111,11 @@ runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
 
 	if(dogc && mstats.heap_alloc >= mstats.next_gc)
 		runtime·gc(0);
+
+	if(raceenabled) {
+		runtime·racemalloc(v, size, m->racepc);
+		m->racepc = nil;
+	}
 	return v;
 }
 
@@ -130,6 +151,9 @@ runtime·free(void *v)
 	}
 	prof = runtime·blockspecial(v);
 
+	if(raceenabled)
+		runtime·racefree(v);
+
 	// Find size class for v.
 	sizeclass = s->sizeclass;
 	c = m->mcache;
@@ -141,7 +165,7 @@ runtime·free(void *v)
 		// they might coalesce v into other spans and change the bitmap further.
 		runtime·markfreed(v, size);
 		runtime·unmarkspan(v, 1<<PageShift);
-		runtime·MHeap_Free(&runtime·mheap, s, 1);
+		runtime·MHeap_Free(runtime·mheap, s, 1);
 	} else {
 		// Small object.
 		size = runtime·class_to_size[sizeclass];
@@ -169,7 +193,14 @@ runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
 	MSpan *s;
 
 	m->mcache->local_nlookup++;
-	s = runtime·MHeap_LookupMaybe(&runtime·mheap, v);
+	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) {
@@ -196,7 +227,7 @@ runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
 		return 0;
 	}
 
-	n = runtime·class_to_size[s->sizeclass];
+	n = s->elemsize;
 	if(base) {
 		i = ((byte*)v - p)/n;
 		*base = p + i*n;
@@ -210,14 +241,15 @@ runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
 MCache*
 runtime·allocmcache(void)
 {
-	int32 rate;
+	intgo rate;
 	MCache *c;
 
-	runtime·lock(&runtime·mheap);
-	c = runtime·FixAlloc_Alloc(&runtime·mheap.cachealloc);
-	mstats.mcache_inuse = runtime·mheap.cachealloc.inuse;
-	mstats.mcache_sys = runtime·mheap.cachealloc.sys;
-	runtime·unlock(&runtime·mheap);
+	runtime·lock(runtime·mheap);
+	c = runtime·FixAlloc_Alloc(&runtime·mheap->cachealloc);
+	mstats.mcache_inuse = runtime·mheap->cachealloc.inuse;
+	mstats.mcache_sys = runtime·mheap->cachealloc.sys;
+	runtime·unlock(runtime·mheap);
+	runtime·memclr((byte*)c, sizeof(*c));
 
 	// Set first allocation sample size.
 	rate = runtime·MemProfileRate;
@@ -230,12 +262,19 @@ runtime·allocmcache(void)
 }
 
 void
-runtime·purgecachedstats(M* m)
+runtime·freemcache(MCache *c)
 {
-	MCache *c;
+	runtime·MCache_ReleaseAll(c);
+	runtime·lock(runtime·mheap);
+	runtime·purgecachedstats(c);
+	runtime·FixAlloc_Free(&runtime·mheap->cachealloc, c);
+	runtime·unlock(runtime·mheap);
+}
 
+void
+runtime·purgecachedstats(MCache *c)
+{
 	// Protected by either heap or GC lock.
-	c = m->mcache;
 	mstats.heap_alloc += c->local_cachealloc;
 	c->local_cachealloc = 0;
 	mstats.heap_objects += c->local_objects;
@@ -274,6 +313,9 @@ runtime·mallocinit(void)
 	USED(arena_size);
 	USED(bitmap_size);
 
+	if((runtime·mheap = runtime·SysAlloc(sizeof(*runtime·mheap))) == nil)
+		runtime·throw("runtime: cannot allocate heap metadata");
+
 	runtime·InitSizes();
 
 	limit = runtime·memlimit();
@@ -283,32 +325,30 @@ runtime·mallocinit(void)
 	// 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.
-		// 16 GB should be big enough for now.
+		// 128 GB (MaxMem) should be big enough for now.
 		//
 		// The code will work with the reservation at any address, but ask
-		// SysReserve to use 0x000000f800000000 if possible.
-		// Allocating a 16 GB region takes away 36 bits, and the amd64
+		// SysReserve to use 0x000000c000000000 if possible.
+		// 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 0x00f8 for us to choose.  Choosing 0x00f8 means
-		// that the valid memory addresses will begin 0x00f8, 0x00f9, 0x00fa, 0x00fb.
-		// None of the bytes f8 f9 fa fb can appear in valid UTF-8, and
-		// they are otherwise as far from ff (likely a common byte) as possible.
-		// Choosing 0x00 for the leading 6 bits was more arbitrary, but it
-		// is not a common ASCII code point either.  Using 0x11f8 instead
+		// in the middle of 0x00c0 for us to choose.  Choosing 0x00c0 means
+		// that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x0x00df.
+		// 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. An earlier attempt to use 0x11f8 
 		// caused out of memory errors on OS X during thread allocations.
 		// 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 17 GB (because the bitmap ends up being 1 GB)
-		// but it hardly matters: fc is not valid UTF-8 either, and we have to
-		// allocate 15 GB before we get that far.
+		// 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 = 16LL<<30;
+		arena_size = MaxMem;
 		bitmap_size = arena_size / (sizeof(void*)*8/4);
-		p = runtime·SysReserve((void*)(0x00f8ULL<<32), bitmap_size + arena_size);
+		p = runtime·SysReserve((void*)(0x00c0ULL<<32), bitmap_size + arena_size);
 	}
 	if (p == nil) {
 		// On a 32-bit machine, we can't typically get away
@@ -354,13 +394,13 @@ runtime·mallocinit(void)
 	if((uintptr)p & (((uintptr)1<<PageShift)-1))
 		runtime·throw("runtime: SysReserve returned unaligned address");
 
-	runtime·mheap.bitmap = p;
-	runtime·mheap.arena_start = p + bitmap_size;
-	runtime·mheap.arena_used = runtime·mheap.arena_start;
-	runtime·mheap.arena_end = runtime·mheap.arena_start + arena_size;
+	runtime·mheap->bitmap = p;
+	runtime·mheap->arena_start = p + bitmap_size;
+	runtime·mheap->arena_used = runtime·mheap->arena_start;
+	runtime·mheap->arena_end = runtime·mheap->arena_start + arena_size;
 
 	// Initialize the rest of the allocator.	
-	runtime·MHeap_Init(&runtime·mheap, runtime·SysAlloc);
+	runtime·MHeap_Init(runtime·mheap, runtime·SysAlloc);
 	m->mcache = runtime·allocmcache();
 
 	// See if it works.
@@ -394,6 +434,8 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
 		runtime·SysMap(p, n);
 		h->arena_used += n;
 		runtime·MHeap_MapBits(h);
+		if(raceenabled)
+			runtime·racemapshadow(p, n);
 		return p;
 	}
 	
@@ -420,11 +462,231 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
 		if(h->arena_used > h->arena_end)
 			h->arena_end = h->arena_used;
 		runtime·MHeap_MapBits(h);
+		if(raceenabled)
+			runtime·racemapshadow(p, n);
 	}
 	
 	return p;
 }
 
+static Lock settype_lock;
+
+void
+runtime·settype_flush(M *mp, bool sysalloc)
+{
+	uintptr *buf, *endbuf;
+	uintptr size, ofs, j, t;
+	uintptr ntypes, nbytes2, nbytes3;
+	uintptr *data2;
+	byte *data3;
+	bool sysalloc3;
+	void *v;
+	uintptr typ, p;
+	MSpan *s;
+
+	buf = mp->settype_buf;
+	endbuf = buf + mp->settype_bufsize;
+
+	runtime·lock(&settype_lock);
+	while(buf < endbuf) {
+		v = (void*)*buf;
+		*buf = 0;
+		buf++;
+		typ = *buf;
+		buf++;
+
+		// (Manually inlined copy of runtime·MHeap_Lookup)
+		p = (uintptr)v>>PageShift;
+		if(sizeof(void*) == 8)
+			p -= (uintptr)runtime·mheap->arena_start >> PageShift;
+		s = runtime·mheap->map[p];
+
+		if(s->sizeclass == 0) {
+			s->types.compression = MTypes_Single;
+			s->types.data = typ;
+			continue;
+		}
+
+		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;
+
+			if(!sysalloc) {
+				data3 = runtime·mallocgc(nbytes3, FlagNoPointers, 0, 1);
+			} else {
+				data3 = runtime·SysAlloc(nbytes3);
+				if(data3 == nil)
+					runtime·throw("runtime: cannot allocate memory");
+				if(0) runtime·printf("settype(0->3): SysAlloc(%x) --> %p\n", (uint32)nbytes3, data3);
+			}
+
+			s->types.compression = MTypes_Bytes;
+			s->types.sysalloc = sysalloc;
+			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);
+
+				if(!sysalloc) {
+					data2 = runtime·mallocgc(nbytes2, FlagNoPointers, 0, 1);
+				} else {
+					data2 = runtime·SysAlloc(nbytes2);
+					if(data2 == nil)
+						runtime·throw("runtime: cannot allocate memory");
+					if(0) runtime·printf("settype.(3->2): SysAlloc(%x) --> %p\n", (uint32)nbytes2, data2);
+				}
+
+				sysalloc3 = s->types.sysalloc;
+
+				s->types.compression = MTypes_Words;
+				s->types.sysalloc = sysalloc;
+				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;
+				}
+				if(sysalloc3) {
+					nbytes3 = 8*sizeof(uintptr) + 1*ntypes;
+					if(0) runtime·printf("settype.(3->2): SysFree(%p,%x)\n", data3, (uint32)nbytes3);
+					runtime·SysFree(data3, nbytes3);
+				}
+
+				data2[ofs] = typ;
+			}
+			break;
+		}
+	}
+	runtime·unlock(&settype_lock);
+
+	mp->settype_bufsize = 0;
+}
+
+// It is forbidden to use this function if it is possible that
+// explicit deallocation via calling runtime·free(v) may happen.
+void
+runtime·settype(void *v, uintptr t)
+{
+	M *mp;
+	uintptr *buf;
+	uintptr i;
+	MSpan *s;
+
+	if(t == 0)
+		runtime·throw("settype: zero type");
+
+	mp = m;
+	buf = mp->settype_buf;
+	i = mp->settype_bufsize;
+	buf[i+0] = (uintptr)v;
+	buf[i+1] = t;
+	i += 2;
+	mp->settype_bufsize = i;
+
+	if(i == nelem(mp->settype_buf)) {
+		runtime·settype_flush(mp, false);
+	}
+
+	if(DebugTypeAtBlockEnd) {
+		s = runtime·MHeap_Lookup(runtime·mheap, v);
+		*(uintptr*)((uintptr)v+s->elemsize-sizeof(uintptr)) = t;
+	}
+}
+
+void
+runtime·settype_sysfree(MSpan *s)
+{
+	uintptr ntypes, nbytes;
+
+	if(!s->types.sysalloc)
+		return;
+
+	nbytes = (uintptr)-1;
+
+	switch (s->types.compression) {
+	case MTypes_Words:
+		ntypes = (s->npages << PageShift) / s->elemsize;
+		nbytes = ntypes * sizeof(uintptr);
+		break;
+	case MTypes_Bytes:
+		ntypes = (s->npages << PageShift) / s->elemsize;
+		nbytes = 8*sizeof(uintptr) + 1*ntypes;
+		break;
+	}
+
+	if(nbytes != (uintptr)-1) {
+		if(0) runtime·printf("settype: SysFree(%p,%x)\n", (void*)s->types.data, (uint32)nbytes);
+		runtime·SysFree((void*)s->types.data, nbytes);
+	}
+}
+
+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·lock(&settype_lock);
+			runtime·printf("%p -> %d,%X\n", v, (int32)s->types.compression, (int64)t);
+			runtime·unlock(&settype_lock);
+		}
+		return t;
+	}
+	return 0;
+}
+
 // Runtime stubs.
 
 void*
@@ -433,46 +695,63 @@ runtime·mal(uintptr n)
 	return runtime·mallocgc(n, 0, 1, 1);
 }
 
-func new(typ *Type) (ret *uint8) {
-	uint32 flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
-	ret = runtime·mallocgc(typ->size, flag, 1, 1);
+#pragma textflag 7
+void
+runtime·new(Type *typ, uint8 *ret)
+{
+	uint32 flag;
+
+	if(raceenabled)
+		m->racepc = runtime·getcallerpc(&typ);
+
+	if(typ->size == 0) {
+		// All 0-length allocations use this pointer.
+		// The language does not require the allocations to
+		// have distinct values.
+		ret = (uint8*)&runtime·zerobase;
+	} else {
+		flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
+		ret = runtime·mallocgc(typ->size, flag, 1, 1);
+
+		if(UseSpanType && !flag) {
+			if(false) {
+				runtime·printf("new %S: %p\n", *typ->string, ret);
+			}
+			runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject);
+		}
+	}
+
 	FLUSH(&ret);
 }
 
+// same as runtime·new, but callable from C
 void*
-runtime·stackalloc(uint32 n)
+runtime·cnew(Type *typ)
 {
-	// 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");
-
-	// Stack allocator uses malloc/free most of the time,
-	// but if we're in the middle of malloc and need stack,
-	// we have to do something else to avoid deadlock.
-	// In that case, we fall back on a fixed-size free-list
-	// allocator, assuming that inside malloc all the stack
-	// frames are small, so that all the stack allocations
-	// will be a single size, the minimum (right now, 5k).
-	if(m->mallocing || m->gcing || n == FixedStack) {
-		if(n != FixedStack) {
-			runtime·printf("stackalloc: in malloc, size=%d want %d", FixedStack, n);
-			runtime·throw("stackalloc");
+	uint32 flag;
+	void *ret;
+
+	if(raceenabled)
+		m->racepc = runtime·getcallerpc(&typ);
+
+	if(typ->size == 0) {
+		// All 0-length allocations use this pointer.
+		// The language does not require the allocations to
+		// have distinct values.
+		ret = (uint8*)&runtime·zerobase;
+	} else {
+		flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
+		ret = runtime·mallocgc(typ->size, flag, 1, 1);
+
+		if(UseSpanType && !flag) {
+			if(false) {
+				runtime·printf("new %S: %p\n", *typ->string, ret);
+			}
+			runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject);
 		}
-		return runtime·FixAlloc_Alloc(m->stackalloc);
 	}
-	return runtime·mallocgc(n, FlagNoProfiling|FlagNoGC, 0, 0);
-}
 
-void
-runtime·stackfree(void *v, uintptr n)
-{
-	if(m->mallocing || m->gcing || n == FixedStack) {
-		runtime·FixAlloc_Free(m->stackalloc, v);
-		return;
-	}
-	runtime·free(v);
+	return ret;
 }
 
 func GC() {
@@ -483,7 +762,8 @@ func SetFinalizer(obj Eface, finalizer Eface) {
 	byte *base;
 	uintptr size;
 	FuncType *ft;
-	int32 i, nret;
+	int32 i;
+	uintptr nret;
 	Type *t;
 
 	if(obj.type == nil) {
diff --git a/src/pkg/runtime/malloc.h b/src/pkg/runtime/malloc.h
index d846f68..38122bf 100644
--- a/src/pkg/runtime/malloc.h
+++ b/src/pkg/runtime/malloc.h
@@ -85,6 +85,8 @@ 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
 {
@@ -113,21 +115,30 @@ enum
 	HeapAllocChunk = 1<<20,		// Chunk size for heap growth
 
 	// Number of bits in page to span calculations (4k pages).
-	// On 64-bit, we limit the arena to 16G, so 22 bits suffices.
-	// On 32-bit, we don't bother limiting anything: 20 bits for 4G.
+	// On 64-bit, we limit the arena to 128GB, or 37 bits.
+	// On 32-bit, we don't bother limiting anything, so we use the full 32-bit address.
 #ifdef _64BIT
-	MHeapMap_Bits = 22,
+	MHeapMap_Bits = 37 - PageShift,
 #else
-	MHeapMap_Bits = 20,
+	MHeapMap_Bits = 32 - PageShift,
 #endif
 
 	// 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 4 cpus.
-	MaxGcproc = 4,
+	// collector scales well to 8 cpus.
+	MaxGcproc = 8,
 };
 
+// Maximum memory allocation size, a hint for callers.
+// This must be a #define instead of an enum because it
+// is so large.
+#ifdef _64BIT
+#define	MaxMem	(1ULL<<(MHeapMap_Bits+PageShift))	/* 128 GB */
+#else
+#define	MaxMem	((uintptr)-1)
+#endif
+
 // A generic linked list of blocks.  (Typically the block is bigger than sizeof(MLink).)
 struct MLink
 {
@@ -188,7 +199,7 @@ void	runtime·FixAlloc_Free(FixAlloc *f, void *p);
 
 
 // Statistics.
-// Shared with Go: if you edit this structure, also edit extern.go.
+// Shared with Go: if you edit this structure, also edit type MemStats in mem.go.
 struct MStats
 {
 	// General statistics.
@@ -219,7 +230,7 @@ struct MStats
 	uint64	buckhash_sys;	// profiling bucket hash table
 
 	// Statistics about garbage collector.
-	// Protected by stopping the world during GC.
+	// Protected by mheap or stopping the world during GC.
 	uint64	next_gc;	// next GC (in heap_alloc time)
 	uint64  last_gc;	// last GC (in absolute time)
 	uint64	pause_total_ns;
@@ -239,7 +250,6 @@ struct MStats
 #define mstats runtime·memStats	/* name shared with Go */
 extern MStats mstats;
 
-
 // Size classes.  Computed and initialized by InitSizes.
 //
 // SizeToClass(0 <= n <= MaxSmallSize) returns the size class,
@@ -273,19 +283,19 @@ struct MCacheList
 struct MCache
 {
 	MCacheList list[NumSizeClasses];
-	uint64 size;
-	int64 local_cachealloc;	// bytes allocated (or freed) from cache since last lock of heap
-	int64 local_objects;	// objects allocated (or freed) from cache since last lock of heap
-	int64 local_alloc;	// bytes allocated (or freed) since last lock of heap
-	int64 local_total_alloc;	// bytes allocated (even if freed) since last lock of heap
-	int64 local_nmalloc;	// number of mallocs since last lock of heap
-	int64 local_nfree;	// number of frees since last lock of heap
-	int64 local_nlookup;	// number of pointer lookups since last lock of heap
+	uintptr size;
+	intptr local_cachealloc;	// bytes allocated (or freed) from cache since last lock of heap
+	intptr local_objects;	// objects allocated (or freed) from cache since last lock of heap
+	intptr local_alloc;	// bytes allocated (or freed) since last lock of heap
+	uintptr local_total_alloc;	// bytes allocated (even if freed) since last lock of heap
+	uintptr local_nmalloc;	// number of mallocs since last lock of heap
+	uintptr local_nfree;	// number of frees since last lock of heap
+	uintptr local_nlookup;	// number of pointer lookups since last lock of heap
 	int32 next_sample;	// trigger heap sample after allocating this many bytes
 	// Statistics about allocation size classes since last lock of heap
 	struct {
-		int64 nmalloc;
-		int64 nfree;
+		uintptr nmalloc;
+		uintptr nfree;
 	} local_by_size[NumSizeClasses];
 
 };
@@ -294,6 +304,44 @@ void*	runtime·MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zero
 void	runtime·MCache_Free(MCache *c, void *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_*
+	bool	sysalloc;	// whether (void*)data is from runtime·SysAlloc
+	uintptr	data;
+};
+
 // An MSpan is a run of pages.
 enum
 {
@@ -306,16 +354,17 @@ struct MSpan
 {
 	MSpan	*next;		// in a span linked list
 	MSpan	*prev;		// in a span linked list
-	MSpan	*allnext;	// in the list of all spans
 	PageID	start;		// starting page number
 	uintptr	npages;		// number of pages in span
 	MLink	*freelist;	// list of free objects
 	uint32	ref;		// number of allocated objects in this span
-	uint32	sizeclass;	// size class
+	int32	sizeclass;	// size class
+	uintptr	elemsize;	// computed from sizeclass or from npages
 	uint32	state;		// MSpanInUse etc
 	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
 };
 
 void	runtime·MSpan_Init(MSpan *span, PageID start, uintptr npages);
@@ -342,6 +391,7 @@ struct MCentral
 void	runtime·MCentral_Init(MCentral *c, int32 sizeclass);
 int32	runtime·MCentral_AllocList(MCentral *c, int32 n, MLink **first);
 void	runtime·MCentral_FreeList(MCentral *c, int32 n, MLink *first);
+void	runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end);
 
 // Main malloc heap.
 // The heap itself is the "free[]" and "large" arrays,
@@ -351,7 +401,9 @@ struct MHeap
 	Lock;
 	MSpan free[MaxMHeapList];	// free lists of given length
 	MSpan large;			// free lists length >= MaxMHeapList
-	MSpan *allspans;
+	MSpan **allspans;
+	uint32	nspan;
+	uint32	nspancap;
 
 	// span lookup
 	MSpan *map[1<<MHeapMap_Bits];
@@ -375,10 +427,10 @@ struct MHeap
 	FixAlloc spanalloc;	// allocator for Span*
 	FixAlloc cachealloc;	// allocator for MCache*
 };
-extern MHeap runtime·mheap;
+extern MHeap *runtime·mheap;
 
 void	runtime·MHeap_Init(MHeap *h, void *(*allocator)(uintptr));
-MSpan*	runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct);
+MSpan*	runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32 zeroed);
 void	runtime·MHeap_Free(MHeap *h, MSpan *s, int32 acct);
 MSpan*	runtime·MHeap_Lookup(MHeap *h, void *v);
 MSpan*	runtime·MHeap_LookupMaybe(MHeap *h, void *v);
@@ -394,12 +446,18 @@ void	runtime·markallocated(void *v, uintptr n, bool noptr);
 void	runtime·checkallocated(void *v, uintptr n);
 void	runtime·markfreed(void *v, uintptr n);
 void	runtime·checkfreed(void *v, uintptr n);
-int32	runtime·checking;
+extern	int32	runtime·checking;
 void	runtime·markspan(void *v, uintptr size, uintptr n, bool leftover);
 void	runtime·unmarkspan(void *v, uintptr size);
 bool	runtime·blockspecial(void*);
 void	runtime·setblockspecial(void*, bool);
-void	runtime·purgecachedstats(M*);
+void	runtime·purgecachedstats(MCache*);
+void*	runtime·cnew(Type*);
+
+void	runtime·settype(void*, uintptr);
+void	runtime·settype_flush(M*, bool);
+void	runtime·settype_sysfree(MSpan*);
+uintptr	runtime·gettype(void*);
 
 enum
 {
@@ -412,8 +470,26 @@ enum
 void	runtime·MProf_Malloc(void*, uintptr);
 void	runtime·MProf_Free(void*, uintptr);
 void	runtime·MProf_GC(void);
-int32	runtime·helpgc(bool*);
+int32	runtime·gcprocs(void);
+void	runtime·helpgc(int32 nproc);
 void	runtime·gchelper(void);
 
-bool	runtime·getfinalizer(void *p, bool del, void (**fn)(void*), int32 *nret);
+bool	runtime·getfinalizer(void *p, bool del, FuncVal **fn, uintptr *nret);
 void	runtime·walkfintab(void (*fn)(void*));
+
+enum
+{
+	TypeInfo_SingleObject = 0,
+	TypeInfo_Array = 1,
+	TypeInfo_Map = 2,
+	TypeInfo_Chan = 3,
+
+	// Enables type information at the end of blocks allocated from heap	
+	DebugTypeAtBlockEnd = 0,
+};
+
+// defined in mgc0.go
+void	runtime·gc_m_ptr(Eface*);
+void	runtime·gc_itab_ptr(Eface*);
+
+void	runtime·memorydump(void);
diff --git a/src/pkg/runtime/mallocrep1.go b/src/pkg/runtime/mallocrep1.go
index 41c104c..bc33e3a 100644
--- a/src/pkg/runtime/mallocrep1.go
+++ b/src/pkg/runtime/mallocrep1.go
@@ -39,6 +39,7 @@ func OkAmount(size, n uintptr) bool {
 }
 
 func AllocAndFree(size, count int) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
 	if *chatty {
 		fmt.Printf("size=%d count=%d ...\n", size, count)
 	}
diff --git a/src/pkg/runtime/mcache.c b/src/pkg/runtime/mcache.c
index 518e00c..64803e7 100644
--- a/src/pkg/runtime/mcache.c
+++ b/src/pkg/runtime/mcache.c
@@ -21,7 +21,7 @@ runtime·MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed)
 	l = &c->list[sizeclass];
 	if(l->list == nil) {
 		// Replenish using central lists.
-		n = runtime·MCentral_AllocList(&runtime·mheap.central[sizeclass],
+		n = runtime·MCentral_AllocList(&runtime·mheap->central[sizeclass],
 			runtime·class_to_transfercount[sizeclass], &first);
 		if(n == 0)
 			runtime·throw("out of memory");
@@ -43,11 +43,6 @@ runtime·MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed)
 		// block is zeroed iff second word is zero ...
 		if(size > sizeof(uintptr) && ((uintptr*)v)[1] != 0)
 			runtime·memclr((byte*)v, size);
-		else {
-			// ... except for the link pointer
-			// that we used above; zero that.
-			v->next = nil;
-		}
 	}
 	c->local_cachealloc += size;
 	c->local_objects++;
@@ -74,7 +69,7 @@ ReleaseN(MCache *c, MCacheList *l, int32 n, int32 sizeclass)
 	c->size -= n*runtime·class_to_size[sizeclass];
 
 	// Return them to central free list.
-	runtime·MCentral_FreeList(&runtime·mheap.central[sizeclass], n, first);
+	runtime·MCentral_FreeList(&runtime·mheap->central[sizeclass], n, first);
 }
 
 void
diff --git a/src/pkg/runtime/mcentral.c b/src/pkg/runtime/mcentral.c
index ff0c2d1..ac8b5aa 100644
--- a/src/pkg/runtime/mcentral.c
+++ b/src/pkg/runtime/mcentral.c
@@ -34,12 +34,13 @@ runtime·MCentral_Init(MCentral *c, int32 sizeclass)
 // Allocate up to n objects from the central free list.
 // Return the number of objects allocated.
 // The objects are linked together by their first words.
-// On return, *pstart points at the first object and *pend at the last.
+// On return, *pstart points at the first object.
 int32
 runtime·MCentral_AllocList(MCentral *c, int32 n, MLink **pfirst)
 {
-	MLink *first, *last, *v;
-	int32 i;
+	MSpan *s;
+	MLink *first, *last;
+	int32 cap, avail, i;
 
 	runtime·lock(c);
 	// Replenish central list if empty.
@@ -50,47 +51,37 @@ runtime·MCentral_AllocList(MCentral *c, int32 n, MLink **pfirst)
 			return 0;
 		}
 	}
+	s = c->nonempty.next;
+	cap = (s->npages << PageShift) / s->elemsize;
+	avail = cap - s->ref;
+	if(avail < n)
+		n = avail;
 
-	// Copy from list, up to n.
 	// First one is guaranteed to work, because we just grew the list.
-	first = MCentral_Alloc(c);
+	first = s->freelist;
 	last = first;
-	for(i=1; i<n && (v = MCentral_Alloc(c)) != nil; i++) {
-		last->next = v;
-		last = v;
+	for(i=1; i<n; i++) {
+		last = last->next;
 	}
+	s->freelist = last->next;
 	last->next = nil;
-	c->nfree -= i;
-
-	runtime·unlock(c);
-	*pfirst = first;
-	return i;
-}
+	s->ref += n;
+	c->nfree -= n;
 
-// Helper: allocate one object from the central free list.
-static void*
-MCentral_Alloc(MCentral *c)
-{
-	MSpan *s;
-	MLink *v;
-
-	if(runtime·MSpanList_IsEmpty(&c->nonempty))
-		return nil;
-	s = c->nonempty.next;
-	s->ref++;
-	v = s->freelist;
-	s->freelist = v->next;
-	if(s->freelist == nil) {
+	if(n == avail) {
+		if(s->freelist != nil || s->ref != cap) {
+			runtime·throw("invalid freelist");
+		}
 		runtime·MSpanList_Remove(s);
 		runtime·MSpanList_Insert(&c->empty, s);
 	}
-	return v;
+
+	runtime·unlock(c);
+	*pfirst = first;
+	return n;
 }
 
 // Free n objects back into the central free list.
-// Return the number of objects allocated.
-// The objects are linked together by their first words.
-// On return, *pstart points at the first object and *pend at the last.
 void
 runtime·MCentral_FreeList(MCentral *c, int32 n, MLink *start)
 {
@@ -118,7 +109,7 @@ MCentral_Free(MCentral *c, void *v)
 	int32 size;
 
 	// Find span for v.
-	s = runtime·MHeap_Lookup(&runtime·mheap, v);
+	s = runtime·MHeap_Lookup(runtime·mheap, v);
 	if(s == nil || s->ref == 0)
 		runtime·throw("invalid free");
 
@@ -143,11 +134,47 @@ MCentral_Free(MCentral *c, void *v)
 		s->freelist = nil;
 		c->nfree -= (s->npages << PageShift) / size;
 		runtime·unlock(c);
-		runtime·MHeap_Free(&runtime·mheap, s, 0);
+		runtime·MHeap_Free(runtime·mheap, s, 0);
 		runtime·lock(c);
 	}
 }
 
+// Free n objects from a span s back into the central free list c.
+// Called from GC.
+void
+runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end)
+{
+	int32 size;
+
+	runtime·lock(c);
+
+	// Move to nonempty if necessary.
+	if(s->freelist == nil) {
+		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;
+
+	// If s is completely freed, return it to the heap.
+	if(s->ref == 0) {
+		size = runtime·class_to_size[c->sizeclass];
+		runtime·MSpanList_Remove(s);
+		*(uintptr*)(s->start<<PageShift) = 1;  // needs zeroing
+		s->freelist = nil;
+		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);
+	} else {
+		runtime·unlock(c);
+	}
+}
+
 void
 runtime·MGetSizeClassInfo(int32 sizeclass, uintptr *sizep, int32 *npagesp, int32 *nobj)
 {
@@ -174,7 +201,7 @@ MCentral_Grow(MCentral *c)
 
 	runtime·unlock(c);
 	runtime·MGetSizeClassInfo(c->sizeclass, &size, &npages, &n);
-	s = runtime·MHeap_Alloc(&runtime·mheap, npages, c->sizeclass, 0);
+	s = runtime·MHeap_Alloc(runtime·mheap, npages, c->sizeclass, 0, 1);
 	if(s == nil) {
 		// TODO(rsc): Log out of memory
 		runtime·lock(c);
diff --git a/src/pkg/runtime/mem.go b/src/pkg/runtime/mem.go
index 7668008..79edc5a 100644
--- a/src/pkg/runtime/mem.go
+++ b/src/pkg/runtime/mem.go
@@ -6,6 +6,9 @@ package runtime
 
 import "unsafe"
 
+// Note: the MemStats struct should be kept in sync with
+// struct MStats in malloc.h
+
 // A MemStats records statistics about the memory allocator.
 type MemStats struct {
 	// General statistics.
@@ -39,7 +42,7 @@ type MemStats struct {
 	NextGC       uint64 // next run in HeapAlloc time (bytes)
 	LastGC       uint64 // last run in absolute time (ns)
 	PauseTotalNs uint64
-	PauseNs      [256]uint64 // most recent GC pause times
+	PauseNs      [256]uint64 // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
 	NumGC        uint32
 	EnableGC     bool
 	DebugGC      bool
diff --git a/src/pkg/runtime/mem_darwin.c b/src/pkg/runtime/mem_darwin.c
index cde5601..04e7193 100644
--- a/src/pkg/runtime/mem_darwin.c
+++ b/src/pkg/runtime/mem_darwin.c
@@ -14,7 +14,7 @@ runtime·SysAlloc(uintptr n)
 	void *v;
 
 	mstats.sys += n;
-	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
 	if(v < (void*)4096)
 		return nil;
 	return v;
@@ -51,7 +51,7 @@ runtime·SysMap(void *v, uintptr n)
 	void *p;
 	
 	mstats.sys += n;
-	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
 	if(p == (void*)-ENOMEM)
 		runtime·throw("runtime: out of memory");
 	if(p != v)
diff --git a/src/pkg/runtime/mem_freebsd.c b/src/pkg/runtime/mem_freebsd.c
index d1c2258..f217e9d 100644
--- a/src/pkg/runtime/mem_freebsd.c
+++ b/src/pkg/runtime/mem_freebsd.c
@@ -14,7 +14,7 @@ runtime·SysAlloc(uintptr n)
 	void *v;
 
 	mstats.sys += n;
-	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
 	if(v < (void*)4096)
 		return nil;
 	return v;
@@ -23,9 +23,7 @@ runtime·SysAlloc(uintptr n)
 void
 runtime·SysUnused(void *v, uintptr n)
 {
-	USED(v);
-	USED(n);
-	// TODO(rsc): call madvise MADV_DONTNEED
+	runtime·madvise(v, n, MADV_FREE);
 }
 
 void
@@ -61,7 +59,7 @@ runtime·SysMap(void *v, uintptr n)
 
 	// On 64-bit, we don't actually have v reserved, so tread carefully.
 	if(sizeof(void*) == 8) {
-		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
 		if(p == (void*)-ENOMEM)
 			runtime·throw("runtime: out of memory");
 		if(p != v) {
@@ -71,7 +69,7 @@ runtime·SysMap(void *v, uintptr n)
 		return;
 	}
 
-	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
 	if(p == (void*)-ENOMEM)
 		runtime·throw("runtime: out of memory");
 	if(p != v)
diff --git a/src/pkg/runtime/mem_linux.c b/src/pkg/runtime/mem_linux.c
index b3e79cc..ebcec1e 100644
--- a/src/pkg/runtime/mem_linux.c
+++ b/src/pkg/runtime/mem_linux.c
@@ -10,6 +10,7 @@
 
 enum
 {
+	EAGAIN = 11,
 	ENOMEM = 12,
 	_PAGE_SIZE = 4096,
 };
@@ -56,13 +57,17 @@ runtime·SysAlloc(uintptr n)
 	void *p;
 
 	mstats.sys += n;
-	p = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+	p = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
 	if(p < (void*)4096) {
 		if(p == (void*)EACCES) {
 			runtime·printf("runtime: mmap: access denied\n");
 			runtime·printf("if you're running SELinux, enable execmem for this process.\n");
 			runtime·exit(2);
 		}
+		if(p == (void*)EAGAIN) {
+			runtime·printf("runtime: mmap: too much locked memory (check 'ulimit -l').\n");
+			runtime·exit(2);
+		}
 		return nil;
 	}
 	return p;
@@ -113,7 +118,7 @@ runtime·SysMap(void *v, uintptr n)
 
 	// On 64-bit, we don't actually have v reserved, so tread carefully.
 	if(sizeof(void*) == 8 && (uintptr)v >= 0xffffffffU) {
-		p = mmap_fixed(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+		p = mmap_fixed(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
 		if(p == (void*)ENOMEM)
 			runtime·throw("runtime: out of memory");
 		if(p != v) {
@@ -123,7 +128,7 @@ runtime·SysMap(void *v, uintptr n)
 		return;
 	}
 
-	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
 	if(p == (void*)ENOMEM)
 		runtime·throw("runtime: out of memory");
 	if(p != v)
diff --git a/src/pkg/runtime/mem_netbsd.c b/src/pkg/runtime/mem_netbsd.c
index 34ff31d..77ce04c 100644
--- a/src/pkg/runtime/mem_netbsd.c
+++ b/src/pkg/runtime/mem_netbsd.c
@@ -19,7 +19,7 @@ runtime·SysAlloc(uintptr n)
 	void *v;
 
 	mstats.sys += n;
-	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
 	if(v < (void*)4096)
 		return nil;
 	return v;
@@ -28,9 +28,7 @@ runtime·SysAlloc(uintptr n)
 void
 runtime·SysUnused(void *v, uintptr n)
 {
-	USED(v);
-	USED(n);
-	// TODO(rsc): call madvise MADV_DONTNEED
+	runtime·madvise(v, n, MADV_FREE);
 }
 
 void
@@ -67,7 +65,7 @@ runtime·SysMap(void *v, uintptr n)
 
 	// On 64-bit, we don't actually have v reserved, so tread carefully.
 	if(sizeof(void*) == 8) {
-		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
 		if(p == (void*)-ENOMEM)
 			runtime·throw("runtime: out of memory");
 		if(p != v) {
@@ -77,7 +75,7 @@ runtime·SysMap(void *v, uintptr n)
 		return;
 	}
 
-	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
 	if(p == (void*)-ENOMEM)
 		runtime·throw("runtime: out of memory");
 	if(p != v)
diff --git a/src/pkg/runtime/mem_openbsd.c b/src/pkg/runtime/mem_openbsd.c
index 34ff31d..77ce04c 100644
--- a/src/pkg/runtime/mem_openbsd.c
+++ b/src/pkg/runtime/mem_openbsd.c
@@ -19,7 +19,7 @@ runtime·SysAlloc(uintptr n)
 	void *v;
 
 	mstats.sys += n;
-	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
 	if(v < (void*)4096)
 		return nil;
 	return v;
@@ -28,9 +28,7 @@ runtime·SysAlloc(uintptr n)
 void
 runtime·SysUnused(void *v, uintptr n)
 {
-	USED(v);
-	USED(n);
-	// TODO(rsc): call madvise MADV_DONTNEED
+	runtime·madvise(v, n, MADV_FREE);
 }
 
 void
@@ -67,7 +65,7 @@ runtime·SysMap(void *v, uintptr n)
 
 	// On 64-bit, we don't actually have v reserved, so tread carefully.
 	if(sizeof(void*) == 8) {
-		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
 		if(p == (void*)-ENOMEM)
 			runtime·throw("runtime: out of memory");
 		if(p != v) {
@@ -77,7 +75,7 @@ runtime·SysMap(void *v, uintptr n)
 		return;
 	}
 
-	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
 	if(p == (void*)-ENOMEM)
 		runtime·throw("runtime: out of memory");
 	if(p != v)
diff --git a/src/pkg/runtime/mem_plan9.c b/src/pkg/runtime/mem_plan9.c
index 15cbc17..26ca367 100644
--- a/src/pkg/runtime/mem_plan9.c
+++ b/src/pkg/runtime/mem_plan9.c
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
 #include "arch_GOARCH.h"
 #include "malloc.h"
 #include "os_GOOS.h"
@@ -13,14 +14,14 @@ static Lock memlock;
 
 enum
 {
-	Round = 4095
+	Round = PAGESIZE-1
 };
 
 void*
 runtime·SysAlloc(uintptr nbytes)
 {
 	uintptr bl;
-	
+
 	runtime·lock(&memlock);
 	mstats.sys += nbytes;
 	// Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c
diff --git a/src/pkg/runtime/memclr_arm.s b/src/pkg/runtime/memclr_arm.s
new file mode 100644
index 0000000..afc529d
--- /dev/null
+++ b/src/pkg/runtime/memclr_arm.s
@@ -0,0 +1,91 @@
+// Inferno's libkern/memset-arm.s
+// http://code.google.com/p/inferno-os/source/browse/libkern/memset-arm.s
+//
+//         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.
+
+TO = 8
+TOE = 11
+N = 12
+TMP = 12				/* N and TMP don't overlap */
+
+TEXT runtime·memclr(SB),7,$0
+	MOVW	ptr+0(FP), R(TO)
+	MOVW	n+4(FP), R(N)
+	MOVW	$0, R(0)
+
+	ADD	R(N), R(TO), R(TOE)	/* to end pointer */
+
+	CMP	$4, R(N)		/* need at least 4 bytes to copy */
+	BLT	_1tail
+
+	AND	$0xFF, R(0)		/* it's a byte */
+	SLL	$8, R(0), R(TMP)	/* replicate to a word */
+	ORR	R(TMP), R(0)
+	SLL	$16, R(0), R(TMP)
+	ORR	R(TMP), R(0)
+
+_4align:				/* align on 4 */
+	AND.S	$3, R(TO), R(TMP)
+	BEQ	_4aligned
+
+	MOVBU.P	R(0), 1(R(TO))		/* implicit write back */
+	B	_4align
+
+_4aligned:
+	SUB	$31, R(TOE), R(TMP)	/* do 32-byte chunks if possible */
+	CMP	R(TMP), R(TO)
+	BHS	_4tail
+
+	MOVW	R0, R1			/* replicate */
+	MOVW	R0, R2
+	MOVW	R0, R3
+	MOVW	R0, R4
+	MOVW	R0, R5
+	MOVW	R0, R6
+	MOVW	R0, R7
+
+_f32loop:
+	CMP	R(TMP), R(TO)
+	BHS	_4tail
+
+	MOVM.IA.W [R0-R7], (R(TO))
+	B	_f32loop
+
+_4tail:
+	SUB	$3, R(TOE), R(TMP)	/* do remaining words if possible */
+_4loop:
+	CMP	R(TMP), R(TO)
+	BHS	_1tail
+
+	MOVW.P	R(0), 4(R(TO))		/* implicit write back */
+	B	_4loop
+
+_1tail:
+	CMP	R(TO), R(TOE)
+	BEQ	_return
+
+	MOVBU.P	R(0), 1(R(TO))		/* implicit write back */
+	B	_1tail
+
+_return:
+	RET
diff --git a/src/pkg/runtime/memmove_arm.s b/src/pkg/runtime/memmove_arm.s
index 5c0e574..c5d7e9d 100644
--- a/src/pkg/runtime/memmove_arm.s
+++ b/src/pkg/runtime/memmove_arm.s
@@ -23,19 +23,40 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
+// TE or TS are spilled to the stack during bulk register moves.
 TS = 0
-TE = 1
-FROM = 2
-N = 3
-TMP = 3					/* N and TMP don't overlap */
-TMP1 = 4
-
-// TODO(kaib): This can be done with the existing registers of LR is re-used. Same for memset.
-TEXT runtime·memmove(SB), 7, $8
-	// save g and m
-	MOVW	R9, 4(R13)
-	MOVW	R10, 8(R13)
-
+TE = 8
+
+// Warning: the linker will use R11 to synthesize certain instructions. Please
+// take care and double check with objdump.
+FROM = 11
+N = 12
+TMP = 12				/* N and TMP don't overlap */
+TMP1 = 5
+
+RSHIFT = 5
+LSHIFT = 6
+OFFSET = 7
+
+BR0 = 0					/* shared with TS */
+BW0 = 1
+BR1 = 1
+BW1 = 2
+BR2 = 2
+BW2 = 3
+BR3 = 3
+BW3 = 4
+
+FW0 = 1
+FR0 = 2
+FW1 = 2
+FR1 = 3
+FW2 = 3
+FR2 = 4
+FW3 = 4
+FR3 = 8					/* shared with TE */
+
+TEXT runtime·memmove(SB), 7, $4
 _memmove:
 	MOVW	to+0(FP), R(TS)
 	MOVW	from+4(FP), R(FROM)
@@ -64,15 +85,17 @@ _b4aligned:				/* is source now aligned? */
 	BNE	_bunaligned
 
 	ADD	$31, R(TS), R(TMP)	/* do 32-byte chunks if possible */
+	MOVW	R(TS), savedts+4(SP)
 _b32loop:
 	CMP	R(TMP), R(TE)
 	BLS	_b4tail
 
-	MOVM.DB.W (R(FROM)), [R4-R11]
-	MOVM.DB.W [R4-R11], (R(TE))
+	MOVM.DB.W (R(FROM)), [R0-R7]
+	MOVM.DB.W [R0-R7], (R(TE))
 	B	_b32loop
 
 _b4tail:				/* do remaining words if possible */
+	MOVW	savedts+4(SP), R(TS)
 	ADD	$3, R(TS), R(TMP)
 _b4loop:
 	CMP	R(TMP), R(TE)
@@ -107,22 +130,24 @@ _f4aligned:				/* is source now aligned? */
 	BNE	_funaligned
 
 	SUB	$31, R(TE), R(TMP)	/* do 32-byte chunks if possible */
+	MOVW	R(TE), savedte+4(SP)
 _f32loop:
 	CMP	R(TMP), R(TS)
 	BHS	_f4tail
 
-	MOVM.IA.W (R(FROM)), [R4-R11] 
-	MOVM.IA.W [R4-R11], (R(TS))
+	MOVM.IA.W (R(FROM)), [R1-R8] 
+	MOVM.IA.W [R1-R8], (R(TS))
 	B	_f32loop
 
 _f4tail:
+	MOVW	savedte+4(SP), R(TE)
 	SUB	$3, R(TE), R(TMP)	/* do remaining words if possible */
 _f4loop:
 	CMP	R(TMP), R(TS)
 	BHS	_f1tail
 
 	MOVW.P	4(R(FROM)), R(TMP1)	/* implicit write back */
-	MOVW.P	R4, 4(R(TS))		/* implicit write back */
+	MOVW.P	R(TMP1), 4(R(TS))	/* implicit write back */
 	B	_f4loop
 
 _f1tail:
@@ -134,25 +159,9 @@ _f1tail:
 	B	_f1tail
 
 _return:
-	// restore g and m
-	MOVW	4(R13), R9
-	MOVW	8(R13), R10
 	MOVW	to+0(FP), R0
 	RET
 
-RSHIFT = 4
-LSHIFT = 5
-OFFSET = 6
-
-BR0 = 7
-BW0 = 8
-BR1 = 8
-BW1 = 9
-BR2 = 9
-BW2 = 10
-BR3 = 10
-BW3 = 11
-
 _bunaligned:
 	CMP	$2, R(TMP)		/* is R(TMP) < 2 ? */
 
@@ -172,7 +181,8 @@ _bunaligned:
 	CMP	R(TMP), R(TE)
 	BLS	_b1tail
 
-	AND	$~0x03, R(FROM)		/* align source */
+	BIC	$3, R(FROM)		/* align source */
+	MOVW	R(TS), savedts+4(SP)
 	MOVW	(R(FROM)), R(BR0)	/* prime first block register */
 
 _bu16loop:
@@ -196,18 +206,10 @@ _bu16loop:
 	B	_bu16loop
 
 _bu1tail:
+	MOVW	savedts+4(SP), R(TS)
 	ADD	R(OFFSET), R(FROM)
 	B	_b1tail
 
-FW0 = 7
-FR0 = 8
-FW1 = 8
-FR1 = 9
-FW2 = 9
-FR2 = 10
-FW3 = 10
-FR3 = 11
-
 _funaligned:
 	CMP	$2, R(TMP)
 
@@ -227,7 +229,8 @@ _funaligned:
 	CMP	R(TMP), R(TS)
 	BHS	_f1tail
 
-	AND	$~0x03, R(FROM)		/* align source */
+	BIC	$3, R(FROM)		/* align source */
+	MOVW	R(TE), savedte+4(SP)
 	MOVW.P	4(R(FROM)), R(FR3)	/* prime last block register, implicit write back */
 
 _fu16loop:
@@ -235,7 +238,7 @@ _fu16loop:
 	BHS	_fu1tail
 
 	MOVW	R(FR3)>>R(RSHIFT), R(FW0)
-	MOVM.IA.W (R(FROM)), [R(FR0)-R(FR3)]
+	MOVM.IA.W (R(FROM)), [R(FR0),R(FR1),R(FR2),R(FR3)]
 	ORR	R(FR0)<<R(LSHIFT), R(FW0)
 
 	MOVW	R(FR0)>>R(RSHIFT), R(FW1)
@@ -247,9 +250,10 @@ _fu16loop:
 	MOVW	R(FR2)>>R(RSHIFT), R(FW3)
 	ORR	R(FR3)<<R(LSHIFT), R(FW3)
 
-	MOVM.IA.W [R(FW0)-R(FW3)], (R(TS))
+	MOVM.IA.W [R(FW0),R(FW1),R(FW2),R(FW3)], (R(TS))
 	B	_fu16loop
 
 _fu1tail:
+	MOVW	savedte+4(SP), R(TE)
 	SUB	R(OFFSET), R(FROM)
 	B	_f1tail
diff --git a/src/pkg/runtime/memset_arm.s b/src/pkg/runtime/memset_arm.s
deleted file mode 100644
index 974b8da..0000000
--- a/src/pkg/runtime/memset_arm.s
+++ /dev/null
@@ -1,94 +0,0 @@
-// Inferno's libkern/memset-arm.s
-// http://code.google.com/p/inferno-os/source/browse/libkern/memset-arm.s
-//
-//         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.
-
-TO = 1
-TOE = 2
-N = 3
-TMP = 3					/* N and TMP don't overlap */
-
-// TODO(kaib): memset clobbers R9 and R10 (m and g). This makes the
-// registers unpredictable if (when) memset SIGSEGV's. Fix it by
-// moving the R4-R11 register bank.
-TEXT runtime·memset(SB), $0
-	MOVW	R0, R(TO)
-	MOVW	data+4(FP), R(4)
-	MOVW	n+8(FP), R(N)
-
-	ADD	R(N), R(TO), R(TOE)	/* to end pointer */
-
-	CMP	$4, R(N)		/* need at least 4 bytes to copy */
-	BLT	_1tail
-
-	AND	$0xFF, R(4)		/* it's a byte */
-	SLL	$8, R(4), R(TMP)	/* replicate to a word */
-	ORR	R(TMP), R(4)
-	SLL	$16, R(4), R(TMP)
-	ORR	R(TMP), R(4)
-
-_4align:				/* align on 4 */
-	AND.S	$3, R(TO), R(TMP)
-	BEQ	_4aligned
-
-	MOVBU.P	R(4), 1(R(TO))		/* implicit write back */
-	B	_4align
-
-_4aligned:
-	SUB	$31, R(TOE), R(TMP)	/* do 32-byte chunks if possible */
-	CMP	R(TMP), R(TO)
-	BHS	_4tail
-
-	MOVW	R4, R5			/* replicate */
-	MOVW	R4, R6
-	MOVW	R4, R7
-	MOVW	R4, R8
-	MOVW	R4, R9
-	MOVW	R4, R10
-	MOVW	R4, R11
-
-_f32loop:
-	CMP	R(TMP), R(TO)
-	BHS	_4tail
-
-	MOVM.IA.W [R4-R11], (R(TO))
-	B	_f32loop
-
-_4tail:
-	SUB	$3, R(TOE), R(TMP)	/* do remaining words if possible */
-_4loop:
-	CMP	R(TMP), R(TO)
-	BHS	_1tail
-
-	MOVW.P	R(4), 4(R(TO))		/* implicit write back */
-	B	_4loop
-
-_1tail:
-	CMP	R(TO), R(TOE)
-	BEQ	_return
-
-	MOVBU.P	R(4), 1(R(TO))		/* implicit write back */
-	B	_1tail
-
-_return:
-	RET
diff --git a/src/pkg/runtime/mfinal.c b/src/pkg/runtime/mfinal.c
index 1fa5ea4..2f5e427 100644
--- a/src/pkg/runtime/mfinal.c
+++ b/src/pkg/runtime/mfinal.c
@@ -11,8 +11,8 @@ enum { debug = 0 };
 typedef struct Fin Fin;
 struct Fin
 {
-	void (*fn)(void*);
-	int32 nret;
+	FuncVal *fn;
+	uintptr nret;
 };
 
 // Finalizer hash table.  Direct hash, linear scan, at most 3/4 full.
@@ -42,7 +42,7 @@ static struct {
 } fintab[TABSZ];
 
 static void
-addfintab(Fintab *t, void *k, void (*fn)(void*), int32 nret)
+addfintab(Fintab *t, void *k, FuncVal *fn, uintptr nret)
 {
 	int32 i, j;
 
@@ -137,7 +137,7 @@ resizefintab(Fintab *tab)
 }
 
 bool
-runtime·addfinalizer(void *p, void (*f)(void*), int32 nret)
+runtime·addfinalizer(void *p, FuncVal *f, uintptr nret)
 {
 	Fintab *tab;
 	byte *base;
@@ -175,7 +175,7 @@ runtime·addfinalizer(void *p, void (*f)(void*), int32 nret)
 // get finalizer; if del, delete finalizer.
 // caller is responsible for updating RefHasFinalizer (special) bit.
 bool
-runtime·getfinalizer(void *p, bool del, void (**fn)(void*), int32 *nret)
+runtime·getfinalizer(void *p, bool del, FuncVal **fn, uintptr *nret)
 {
 	Fintab *tab;
 	bool res;
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index e8fb266..010f9cd 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -8,15 +8,28 @@
 #include "arch_GOARCH.h"
 #include "malloc.h"
 #include "stack.h"
+#include "mgc0.h"
+#include "race.h"
+#include "type.h"
+#include "typekind.h"
+#include "hashmap.h"
 
 enum {
 	Debug = 0,
-	PtrSize = sizeof(void*),
 	DebugMark = 0,  // run second pass to check mark
+	CollectStats = 0,
 
 	// Four bits per word (see #defines below).
 	wordsPerBitmapWord = sizeof(void*)*8/4,
 	bitShift = sizeof(void*)*8/4,
+
+	handoffThreshold = 4,
+	IntermediateBufferCapacity = 64,
+
+	// Bits in type information
+	PRECISE = 1,
+	LOOP = 2,
+	PC_BITS = PRECISE | LOOP,
 };
 
 // Bits in per-word bitmap.
@@ -67,25 +80,34 @@ enum {
 //
 uint32 runtime·worldsema = 1;
 
-// TODO: Make these per-M.
-static uint64 nhandoff;
-
 static int32 gctrace;
 
+typedef struct Obj Obj;
+struct Obj
+{
+	byte	*p;	// data pointer
+	uintptr	n;	// size of data in bytes
+	uintptr	ti;	// type info
+};
+
+// The size of Workbuf is N*PageSize.
 typedef struct Workbuf Workbuf;
 struct Workbuf
 {
-	Workbuf *next;
+#define SIZE (2*PageSize-sizeof(LFNode)-sizeof(uintptr))
+	LFNode  node; // must be first
 	uintptr nobj;
-	byte *obj[512-2];
+	Obj     obj[SIZE/sizeof(Obj) - 1];
+	uint8   _padding[SIZE%sizeof(Obj) + sizeof(Obj)];
+#undef SIZE
 };
 
 typedef struct Finalizer Finalizer;
 struct Finalizer
 {
-	void (*fn)(void*);
+	FuncVal *fn;
 	void *arg;
-	int32 nret;
+	uintptr nret;
 };
 
 typedef struct FinBlock FinBlock;
@@ -99,9 +121,13 @@ struct FinBlock
 };
 
 extern byte data[];
-extern byte etext[];
+extern byte edata[];
+extern byte bss[];
 extern byte ebss[];
 
+extern byte gcdata[];
+extern byte gcbss[];
+
 static G *fing;
 static FinBlock *finq; // list of finalizers that are to be executed
 static FinBlock *finc; // cache of free blocks
@@ -116,89 +142,244 @@ static void	putempty(Workbuf*);
 static Workbuf* handoff(Workbuf*);
 
 static struct {
-	Lock fmu;
-	Workbuf	*full;
-	Lock emu;
-	Workbuf	*empty;
+	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;
 	volatile uint32	nwait;
 	volatile uint32	ndone;
+	volatile uint32 debugmarkdone;
 	Note	alldone;
-	Lock	markgate;
-	Lock	sweepgate;
-	MSpan	*spans;
+	ParFor	*markfor;
+	ParFor	*sweepfor;
 
 	Lock;
 	byte	*chunk;
 	uintptr	nchunk;
+
+	Obj	*roots;
+	uint32	nroot;
+	uint32	rootcap;
 } work;
 
-// 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.
+enum {
+	GC_DEFAULT_PTR = GC_NUM_INSTR,
+	GC_MAP_NEXT,
+	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;
+} gcstats;
+
+// markonly marks an object. It returns true if the object
+// has been marked by this function, false otherwise.
+// This function isn't thread-safe and doesn't append the object to any buffer.
+static bool
+markonly(void *obj)
+{
+	byte *p;
+	uintptr *bitp, bits, shift, x, xbits, off;
+	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)
+		goto found;
+
+	// Otherwise consult span table to find beginning.
+	// (Manually inlined copy of MHeap_LookupMaybe.)
+	k = (uintptr)obj>>PageShift;
+	x = k;
+	if(sizeof(void*) == 8)
+		x -= (uintptr)runtime·mheap->arena_start>>PageShift;
+	s = runtime·mheap->map[x];
+	if(s == nil || k < s->start || k - s->start >= s->npages || s->state != MSpanInUse)
+		return false;
+	p = (byte*)((uintptr)s->start<<PageShift);
+	if(s->sizeclass == 0) {
+		obj = p;
+	} else {
+		if((byte*)obj >= (byte*)s->limit)
+			return false;
+		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;
+
+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;
+	*bitp |= bitMarked<<shift;
+
+	// The object is now marked
+	return true;
+}
+
+// PtrTarget and BitTarget are structures 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 BitTarget BitTarget;
+struct BitTarget
+{
+	void *p;
+	uintptr ti;
+	uintptr *bitp, shift;
+};
+
+typedef struct BufferList BufferList;
+struct BufferList
+{
+	PtrTarget ptrtarget[IntermediateBufferCapacity];
+	BitTarget bittarget[IntermediateBufferCapacity];
+	Obj obj[IntermediateBufferCapacity];
+	BufferList *next;
+};
+static BufferList *bufferList;
+
+static Lock lock;
+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.
+// bitbuf holds temporary data generated by this function.
+//
+// A simplified drawing explaining how the todo-list moves from a structure to another:
+//
+//     scanblock
+//  (find pointers)
+//    Obj ------> PtrTarget (pointer targets)
+//     ↑          |
+//     |          | flushptrbuf (1st part,
+//     |          | find block start)
+//     |          ↓
+//     `--------- BitTarget (pointer targets and the corresponding locations in bitmap)
+//  flushptrbuf
+//  (2nd part, mark and enqueue)
 static void
-scanblock(byte *b, int64 n)
+flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf, uintptr *_nobj, BitTarget *bitbuf)
 {
-	byte *obj, *arena_start, *arena_used, *p;
-	void **vp;
-	uintptr size, *bitp, bits, shift, i, j, x, xbits, off, nobj, nproc;
+	byte *p, *arena_start, *obj;
+	uintptr size, *bitp, bits, shift, j, x, xbits, off, nobj, ti, n;
 	MSpan *s;
 	PageID k;
-	void **wp;
+	Obj *wp;
 	Workbuf *wbuf;
-	bool keepworking;
+	PtrTarget *ptrbuf_end;
+	BitTarget *bitbufpos, *bt;
 
-	if((int64)(uintptr)n != n || n < 0) {
-		runtime·printf("scanblock %p %D\n", b, n);
-		runtime·throw("scanblock");
-	}
+	arena_start = runtime·mheap->arena_start;
 
-	// Memory arena parameters.
-	arena_start = runtime·mheap.arena_start;
-	arena_used = runtime·mheap.arena_used;
-	nproc = work.nproc;
+	wp = *_wp;
+	wbuf = *_wbuf;
+	nobj = *_nobj;
 
-	wbuf = nil;  // current work buffer
-	wp = nil;  // storage for next queued pointer (write pointer)
-	nobj = 0;  // number of queued objects
+	ptrbuf_end = *ptrbufpos;
+	n = ptrbuf_end - ptrbuf;
+	*ptrbufpos = ptrbuf;
 
-	// Scanblock helpers pass b==nil.
-	// The main proc needs to return to make more
-	// calls to scanblock.  But if work.nproc==1 then
-	// might as well process blocks as soon as we
-	// have them.
-	keepworking = b == nil || work.nproc == 1;
+	if(CollectStats) {
+		runtime·xadd64(&gcstats.ptr.sum, n);
+		runtime·xadd64(&gcstats.ptr.cnt, 1);
+	}
 
-	// Align b to a word boundary.
-	off = (uintptr)b & (PtrSize-1);
-	if(off != 0) {
-		b += PtrSize - off;
-		n -= PtrSize - off;
+	// 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");
 	}
 
-	for(;;) {
-		// Each iteration scans the block b of length n, queueing pointers in
-		// the work buffer.
-		if(Debug > 1)
-			runtime·printf("scanblock %p %D\n", b, n);
+	// TODO(atom): This block is a branch of an if-then-else statement.
+	//             The single-threaded branch may be added in a next CL.
+	{
+		// Multi-threaded version.
 
-		vp = (void**)b;
-		n >>= (2+PtrSize/8);  /* n /= PtrSize (4 or 8) */
-		for(i=0; i<n; i++) {
-			obj = (byte*)vp[i];
+		bitbufpos = bitbuf;
 
-			// Words outside the arena cannot be pointers.
-			if((byte*)obj < arena_start || (byte*)obj >= arena_used)
-				continue;
+		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.
-			obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
+			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;
@@ -211,6 +392,8 @@ scanblock(byte *b, int64 n)
 			if((bits & (bitAllocated|bitBlockBoundary)) != 0)
 				goto found;
 
+			ti = 0;
+
 			// Pointing just past the beginning?
 			// Scan backward a little to find a block boundary.
 			for(j=shift; j-->0; ) {
@@ -228,16 +411,16 @@ scanblock(byte *b, int64 n)
 			x = k;
 			if(sizeof(void*) == 8)
 				x -= (uintptr)arena_start>>PageShift;
-			s = runtime·mheap.map[x];
+			s = runtime·mheap->map[x];
 			if(s == nil || k < s->start || k - s->start >= s->npages || s->state != MSpanInUse)
 				continue;
-			p =  (byte*)((uintptr)s->start<<PageShift);
+			p = (byte*)((uintptr)s->start<<PageShift);
 			if(s->sizeclass == 0) {
 				obj = p;
 			} else {
 				if((byte*)obj >= (byte*)s->limit)
 					continue;
-				size = runtime·class_to_size[s->sizeclass];
+				size = s->elemsize;
 				int32 i = ((byte*)obj - p)/size;
 				obj = p+i*size;
 			}
@@ -255,80 +438,606 @@ scanblock(byte *b, int64 n)
 			// Only care about allocated and not marked.
 			if((bits & (bitAllocated|bitMarked)) != bitAllocated)
 				continue;
-			if(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;
-				}
-			}
+
+			*bitbufpos++ = (BitTarget){obj, ti, bitp, shift};
+		}
+
+		runtime·lock(&lock);
+		for(bt=bitbuf; bt<bitbufpos; bt++){
+			xbits = *bt->bitp;
+			bits = xbits >> bt->shift;
+			if((bits & bitMarked) != 0)
+				continue;
+
+			// Mark the block
+			*bt->bitp = xbits | (bitMarked << bt->shift);
 
 			// If object has no pointers, don't need to scan further.
 			if((bits & bitNoPointers) != 0)
 				continue;
 
-			// If another proc wants a pointer, give it some.
-			if(nobj > 4 && work.nwait > 0 && work.full == nil) {
+			obj = bt->p;
+
+			// Ask span about size class.
+			// (Manually inlined copy of MHeap_Lookup.)
+			x = (uintptr)obj >> PageShift;
+			if(sizeof(void*) == 8)
+				x -= (uintptr)arena_start>>PageShift;
+			s = runtime·mheap->map[x];
+
+			PREFETCH(obj);
+
+			*wp = (Obj){obj, s->elemsize, bt->ti};
+			wp++;
+			nobj++;
+		}
+		runtime·unlock(&lock);
+
+		// 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;
+		}
+	}
+
+	*_wp = wp;
+	*_wbuf = wbuf;
+	*_nobj = nobj;
+}
+
+static void
+flushobjbuf(Obj *objbuf, Obj **objbufpos, Obj **_wp, Workbuf **_wbuf, uintptr *_nobj)
+{
+	uintptr nobj, off;
+	Obj *wp, obj;
+	Workbuf *wbuf;
+	Obj *objbuf_end;
+
+	wp = *_wp;
+	wbuf = *_wbuf;
+	nobj = *_nobj;
+
+	objbuf_end = *objbufpos;
+	*objbufpos = objbuf;
+
+	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 = handoff(wbuf);
-				nobj = wbuf->nobj;
-				wp = wbuf->obj + 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;
+	}
+
+	*_wp = wp;
+	*_wbuf = wbuf;
+	*_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};
+
+// Hashmap iterator program
+static uintptr mapProg[2] = {0, GC_MAP_NEXT};
+
+// 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;
+};
+
+// 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.
+//
+// wbuf: current work buffer
+// wp:   storage for next queued pointer (write pointer)
+// nobj: number of queued objects
+static void
+scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
+{
+	byte *b, *arena_start, *arena_used;
+	uintptr n, i, end_b, elemsize, size, ti, objti, count, type;
+	uintptr *pc, precise_type, nominal_size;
+	uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti;
+	void *obj;
+	Type *t;
+	Slice *sliceptr;
+	Frame *stack_ptr, stack_top, stack[GC_STACK_CAPACITY+4];
+	BufferList *scanbuffers;
+	PtrTarget *ptrbuf, *ptrbuf_end, *ptrbufpos;
+	BitTarget *bitbuf;
+	Obj *objbuf, *objbuf_end, *objbufpos;
+	Eface *eface;
+	Iface *iface;
+	Hmap *hmap;
+	MapType *maptype;
+	bool didmark, mapkey_kind, mapval_kind;
+	struct hash_gciter map_iter;
+	struct hash_gciter_data d;
+	Hchan *chan;
+	ChanType *chantype;
+
+	if(sizeof(Workbuf) % PageSize != 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;
+
+	// Allocate ptrbuf, bitbuf
+	{
+		runtime·lock(&lock);
+
+		if(bufferList == nil) {
+			bufferList = runtime·SysAlloc(sizeof(*bufferList));
+			if(bufferList == nil)
+				runtime·throw("runtime: cannot allocate memory");
+			bufferList->next = nil;
+		}
+		scanbuffers = bufferList;
+		bufferList = bufferList->next;
+
+		ptrbuf = &scanbuffers->ptrtarget[0];
+		ptrbuf_end = &scanbuffers->ptrtarget[0] + nelem(scanbuffers->ptrtarget);
+		bitbuf = &scanbuffers->bittarget[0];
+		objbuf = &scanbuffers->obj[0];
+		objbuf_end = &scanbuffers->obj[0] + nelem(scanbuffers->obj);
+
+		runtime·unlock(&lock);
+	}
+
+	ptrbufpos = ptrbuf;
+	objbufpos = objbuf;
+
+	// (Silence the compiler)
+	map_ret = nil;
+	mapkey_size = mapval_size = 0;
+	mapkey_kind = mapval_kind = false;
+	mapkey_ti = mapval_ti = 0;
+	chan = nil;
+	chantype = nil;
+
+	goto next_block;
+
+	for(;;) {
+		// Each iteration scans the block b of length n, queueing pointers in
+		// the work buffer.
+		if(Debug > 1) {
+			runtime·printf("scanblock %p %D\n", b, (int64)n);
+		}
+
+		if(CollectStats) {
+			runtime·xadd64(&gcstats.nbytes, n);
+			runtime·xadd64(&gcstats.obj.sum, nobj);
+			runtime·xadd64(&gcstats.obj.cnt, 1);
+		}
+
+		if(ti != 0) {
+			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;
 			}
+		} 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_Map:
+					hmap = (Hmap*)b;
+					maptype = (MapType*)t;
+					if(hash_gciter_init(hmap, &map_iter)) {
+						mapkey_size = maptype->key->size;
+						mapkey_kind = maptype->key->kind;
+						mapkey_ti   = (uintptr)maptype->key->gc | PRECISE;
+						mapval_size = maptype->elem->size;
+						mapval_kind = maptype->elem->kind;
+						mapval_ti   = (uintptr)maptype->elem->gc | PRECISE;
+
+						map_ret = 0;
+						pc = mapProg;
+					} else {
+						goto next_block;
+					}
+					break;
+				case TypeInfo_Chan:
+					chan = (Hchan*)b;
+					chantype = (ChanType*)t;
+					pc = chanProg;
+					break;
+				default:
+					runtime·throw("scanblock: invalid type");
+					return;
+				}
+			} else {
+				pc = defaultProg;
+			}
+		} else {
+			pc = defaultProg;
+		}
+
+		pc++;
+		stack_top.b = (uintptr)b;
 
-			// 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;
+		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];
+			pc += 3;
+			break;
+
+		case GC_SLICE:
+			sliceptr = (Slice*)(stack_top.b + pc[1]);
+			if(sliceptr->cap != 0) {
+				obj = sliceptr->array;
+				objti = pc[2] | PRECISE | LOOP;
 			}
-			*wp++ = obj;
-			nobj++;
-		continue_obj:;
+			pc += 3;
+			break;
+
+		case GC_APTR:
+			obj = *(void**)(stack_top.b + pc[1]);
+			pc += 2;
+			break;
+
+		case GC_STRING:
+			obj = *(void**)(stack_top.b + pc[1]);
+			pc += 2;
+			break;
+
+		case GC_EFACE:
+			eface = (Eface*)(stack_top.b + pc[1]);
+			pc += 2;
+			if(eface->type != nil && (eface->data >= arena_start && eface->data < arena_used)) {
+				t = eface->type;
+				if(t->size <= sizeof(void*)) {
+					if((t->kind & KindNoPointers))
+						break;
+
+					obj = eface->data;
+					if((t->kind & ~KindNoPointers) == KindPtr)
+						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(iface->tab == nil)
+				break;
+			
+			// iface->tab
+			if((void*)iface->tab >= arena_start && (void*)iface->tab < arena_used) {
+				*ptrbufpos++ = (PtrTarget){iface->tab, (uintptr)itabtype->gc};
+				if(ptrbufpos == ptrbuf_end)
+					flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf);
+			}
+
+			// iface->data
+			if(iface->data >= arena_start && iface->data < arena_used) {
+				t = iface->tab->type;
+				if(t->size <= sizeof(void*)) {
+					if((t->kind & KindNoPointers))
+						break;
+
+					obj = iface->data;
+					if((t->kind & ~KindNoPointers) == KindPtr)
+						objti = (uintptr)((PtrType*)t)->elem->gc;
+				} else {
+					obj = iface->data;
+					objti = (uintptr)t->gc;
+				}
+			}
+			break;
+
+		case GC_DEFAULT_PTR:
+			while((i = stack_top.b) <= end_b) {
+				stack_top.b += PtrSize;
+				obj = *(byte**)i;
+				if(obj >= arena_start && obj < arena_used) {
+					*ptrbufpos++ = (PtrTarget){obj, 0};
+					if(ptrbufpos == ptrbuf_end)
+						flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf);
+				}
+			}
+			goto next_block;
+
+		case GC_END:
+			if(--stack_top.count != 0) {
+				// Next iteration of a loop if possible.
+				elemsize = stack_top.elemsize;
+				stack_top.b += elemsize;
+				if(stack_top.b + 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}, &wbuf, &wp, &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_MAP_PTR:
+			hmap = *(Hmap**)(stack_top.b + pc[1]);
+			if(hmap == nil) {
+				pc += 3;
+				continue;
+			}
+			runtime·lock(&lock);
+			didmark = markonly(hmap);
+			runtime·unlock(&lock);
+			if(didmark) {
+				maptype = (MapType*)pc[2];
+				if(hash_gciter_init(hmap, &map_iter)) {
+					mapkey_size = maptype->key->size;
+					mapkey_kind = maptype->key->kind;
+					mapkey_ti   = (uintptr)maptype->key->gc | PRECISE;
+					mapval_size = maptype->elem->size;
+					mapval_kind = maptype->elem->kind;
+					mapval_ti   = (uintptr)maptype->elem->gc | PRECISE;
+
+					// Start mapProg.
+					map_ret = pc+3;
+					pc = mapProg+1;
+				} else {
+					pc += 3;
+				}
+			} else {
+				pc += 3;
+			}
+			continue;
+
+		case GC_MAP_NEXT:
+			// Add all keys and values to buffers, mark all subtables.
+			while(hash_gciter_next(&map_iter, &d)) {
+				// buffers: reserve space for 2 objects.
+				if(ptrbufpos+2 >= ptrbuf_end)
+					flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf);
+				if(objbufpos+2 >= objbuf_end)
+					flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);
+
+				if(d.st != nil) {
+					runtime·lock(&lock);
+					markonly(d.st);
+					runtime·unlock(&lock);
+				}
+				if(d.key_data != nil) {
+					if(!(mapkey_kind & KindNoPointers) || d.indirectkey) {
+						if(!d.indirectkey)
+							*objbufpos++ = (Obj){d.key_data, mapkey_size, mapkey_ti};
+						else
+							*ptrbufpos++ = (PtrTarget){*(void**)d.key_data, mapkey_ti};
+					}
+					if(!(mapval_kind & KindNoPointers) || d.indirectval) {
+						if(!d.indirectval)
+							*objbufpos++ = (Obj){d.val_data, mapval_size, mapval_ti};
+						else
+							*ptrbufpos++ = (PtrTarget){*(void**)d.val_data, mapval_ti};
+					}
+				}
+			}
+			if(map_ret == 0)
+				goto next_block;
+			pc = map_ret;
+			continue;
+
+		case GC_REGION:
+			obj = (void*)(stack_top.b + pc[1]);
+			size = pc[2];
+			objti = pc[3];
+			pc += 4;
+
+			*objbufpos++ = (Obj){obj, size, objti};
+			if(objbufpos == objbuf_end)
+				flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);
+			break;
+
+		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.
+				n = ((uintgo*)chan)[1];
+				if(n > 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.)
+					*objbufpos++ = (Obj){(byte*)chan+runtime·Hchansize, n*chantype->elem->size,
+						(uintptr)chantype->elem->gc | PRECISE | LOOP};
+					if(objbufpos == objbuf_end)
+						flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);
+				}
+			}
+			goto next_block;
+
+		default:
+			runtime·throw("scanblock: invalid GC instruction");
+			return;
 		}
 
+		if(obj >= arena_start && obj < arena_used) {
+			*ptrbufpos++ = (PtrTarget){obj, objti};
+			if(ptrbufpos == ptrbuf_end)
+				flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf);
+		}
+	}
+
+	next_block:
 		// Done scanning [b, b+n).  Prepare for the next iteration of
-		// the loop by setting b and n to the parameters for the next block.
+		// the loop by setting b, n, ti to the parameters for the next block.
 
-		// Fetch b from the work buffer.
 		if(nobj == 0) {
-			if(!keepworking) {
-				putempty(wbuf);
-				return;
+			flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf);
+			flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);
+
+			if(nobj == 0) {
+				if(!keepworking) {
+					if(wbuf)
+						putempty(wbuf);
+					goto endscan;
+				}
+				// Emptied our buffer: refill.
+				wbuf = getfull(wbuf);
+				if(wbuf == nil)
+					goto endscan;
+				nobj = wbuf->nobj;
+				wp = wbuf->obj + wbuf->nobj;
 			}
-			// Emptied our buffer: refill.
-			wbuf = getfull(wbuf);
-			if(wbuf == nil)
-				return;
-			nobj = wbuf->nobj;
-			wp = wbuf->obj + wbuf->nobj;
 		}
-		b = *--wp;
-		nobj--;
 
-		// Ask span about size class.
-		// (Manually inlined copy of MHeap_Lookup.)
-		x = (uintptr)b>>PageShift;
-		if(sizeof(void*) == 8)
-			x -= (uintptr)arena_start>>PageShift;
-		s = runtime·mheap.map[x];
-		if(s->sizeclass == 0)
-			n = s->npages<<PageShift;
-		else
-			n = runtime·class_to_size[s->sizeclass];
+		// Fetch b from the work buffer.
+		--wp;
+		b = wp->p;
+		n = wp->n;
+		ti = wp->ti;
+		nobj--;
 	}
+
+endscan:
+	runtime·lock(&lock);
+	scanbuffers->next = bufferList;
+	bufferList = scanbuffers;
+	runtime·unlock(&lock);
 }
 
 // debug_scanblock is the debug copy of scanblock.
 // it is simpler, slower, single-threaded, recursive,
 // and uses bitSpecial as the mark bit.
 static void
-debug_scanblock(byte *b, int64 n)
+debug_scanblock(byte *b, uintptr n)
 {
 	byte *obj, *p;
 	void **vp;
@@ -338,8 +1047,8 @@ debug_scanblock(byte *b, int64 n)
 	if(!DebugMark)
 		runtime·throw("debug_scanblock without DebugMark");
 
-	if((int64)(uintptr)n != n || n < 0) {
-		runtime·printf("debug_scanblock %p %D\n", b, n);
+	if((intptr)n < 0) {
+		runtime·printf("debug_scanblock %p %D\n", b, (int64)n);
 		runtime·throw("debug_scanblock");
 	}
 
@@ -356,33 +1065,31 @@ debug_scanblock(byte *b, int64 n)
 		obj = (byte*)vp[i];
 
 		// Words outside the arena cannot be pointers.
-		if((byte*)obj < runtime·mheap.arena_start || (byte*)obj >= runtime·mheap.arena_used)
+		if((byte*)obj < runtime·mheap->arena_start || (byte*)obj >= runtime·mheap->arena_used)
 			continue;
 
 		// Round down to word boundary.
 		obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
 
 		// Consult span table to find beginning.
-		s = runtime·MHeap_LookupMaybe(&runtime·mheap, obj);
+		s = runtime·MHeap_LookupMaybe(runtime·mheap, obj);
 		if(s == nil)
 			continue;
 
-
 		p =  (byte*)((uintptr)s->start<<PageShift);
+		size = s->elemsize;
 		if(s->sizeclass == 0) {
 			obj = p;
-			size = (uintptr)s->npages<<PageShift;
 		} else {
 			if((byte*)obj >= (byte*)s->limit)
 				continue;
-			size = runtime·class_to_size[s->sizeclass];
 			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;
+		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;
@@ -404,53 +1111,98 @@ debug_scanblock(byte *b, int64 n)
 	}
 }
 
+// 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
+markroot(ParFor *desc, uint32 i)
+{
+	Obj *wp;
+	Workbuf *wbuf;
+	uintptr nobj;
+
+	USED(&desc);
+	wp = nil;
+	wbuf = nil;
+	nobj = 0;
+	enqueue(work.roots[i], &wbuf, &wp, &nobj);
+	scanblock(wbuf, wp, nobj, false);
+}
+
 // Get an empty work buffer off the work.empty list,
 // allocating new buffers as needed.
 static Workbuf*
 getempty(Workbuf *b)
 {
-	if(work.nproc == 1) {
-		// Put b on full list.
-		if(b != nil) {
-			b->next = work.full;
-			work.full = 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);
+			if(work.chunk == nil)
+				runtime·throw("runtime: cannot allocate memory");
 		}
-		// Grab from empty list if possible.
-		b = work.empty;
-		if(b != nil) {
-			work.empty = b->next;
-			goto haveb;
-		}
-	} else {
-		// Put b on full list.
-		if(b != nil) {
-			runtime·lock(&work.fmu);
-			b->next = work.full;
-			work.full = b;
-			runtime·unlock(&work.fmu);
-		}
-		// Grab from empty list if possible.
-		runtime·lock(&work.emu);
-		b = work.empty;
-		if(b != nil)
-			work.empty = b->next;
-		runtime·unlock(&work.emu);
-		if(b != nil)
-			goto haveb;
+		b = (Workbuf*)work.chunk;
+		work.chunk += sizeof *b;
+		work.nchunk -= sizeof *b;
+		runtime·unlock(&work);
 	}
-
-	// Need to allocate.
-	runtime·lock(&work);
-	if(work.nchunk < sizeof *b) {
-		work.nchunk = 1<<20;
-		work.chunk = runtime·SysAlloc(work.nchunk);
-	}
-	b = (Workbuf*)work.chunk;
-	work.chunk += sizeof *b;
-	work.nchunk -= sizeof *b;
-	runtime·unlock(&work);
-
-haveb:
 	b->nobj = 0;
 	return b;
 }
@@ -458,19 +1210,10 @@ haveb:
 static void
 putempty(Workbuf *b)
 {
-	if(b == nil)
-		return;
+	if(CollectStats)
+		runtime·xadd64(&gcstats.putempty, 1);
 
-	if(work.nproc == 1) {
-		b->next = work.empty;
-		work.empty = b;
-		return;
-	}
-
-	runtime·lock(&work.emu);
-	b->next = work.empty;
-	work.empty = b;
-	runtime·unlock(&work.emu);
+	runtime·lfstackpush(&work.empty, &b->node);
 }
 
 // Get a full work buffer off the work.full list, or return nil.
@@ -478,63 +1221,37 @@ static Workbuf*
 getfull(Workbuf *b)
 {
 	int32 i;
-	Workbuf *b1;
-
-	if(work.nproc == 1) {
-		// Put b on empty list.
-		if(b != nil) {
-			b->next = work.empty;
-			work.empty = b;
-		}
-		// Grab from full list if possible.
-		// Since work.nproc==1, no one else is
-		// going to give us work.
-		b = work.full;
-		if(b != nil)
-			work.full = b->next;
-		return b;
-	}
 
-	putempty(b);
+	if(CollectStats)
+		runtime·xadd64(&gcstats.getfull, 1);
 
-	// Grab buffer from full list if possible.
-	for(;;) {
-		b1 = work.full;
-		if(b1 == nil)
-			break;
-		runtime·lock(&work.fmu);
-		if(work.full != nil) {
-			b1 = work.full;
-			work.full = b1->next;
-			runtime·unlock(&work.fmu);
-			return b1;
-		}
-		runtime·unlock(&work.fmu);
-	}
+	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++) {
-		b1 = work.full;
-		if(b1 != nil) {
-			runtime·lock(&work.fmu);
-			if(work.full != nil) {
-				runtime·xadd(&work.nwait, -1);
-				b1 = work.full;
-				work.full = b1->next;
-				runtime·unlock(&work.fmu);
-				return b1;
-			}
-			runtime·unlock(&work.fmu);
-			continue;
+		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)
+		if(i < 10) {
+			m->gcstats.nprocyield++;
 			runtime·procyield(20);
-		else if(i < 20)
+		} else if(i < 20) {
+			m->gcstats.nosyield++;
 			runtime·osyield();
-		else
+		} else {
+			m->gcstats.nsleep++;
 			runtime·usleep(100);
+		}
 	}
 }
 
@@ -550,20 +1267,40 @@ handoff(Workbuf *b)
 	b->nobj -= n;
 	b1->nobj = n;
 	runtime·memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]);
-	nhandoff += n;
+	m->gcstats.nhandoff++;
+	m->gcstats.nhandoffcnt += n;
 
 	// Put b on full list - let first half of b get stolen.
-	runtime·lock(&work.fmu);
-	b->next = work.full;
-	work.full = b;
-	runtime·unlock(&work.fmu);
-
+	runtime·lfstackpush(&work.full, &b->node);
 	return b1;
 }
 
-// Scanstack calls scanblock on each of gp's stack segments.
 static void
-scanstack(void (*scanblock)(byte*, int64), G *gp)
+addroot(Obj obj)
+{
+	uint32 cap;
+	Obj *new;
+
+	if(work.nroot >= work.rootcap) {
+		cap = PageSize/sizeof(Obj);
+		if(cap < 2*work.rootcap)
+			cap = 2*work.rootcap;
+		new = (Obj*)runtime·SysAlloc(cap*sizeof(Obj));
+		if(new == nil)
+			runtime·throw("runtime: cannot allocate memory");
+		if(work.roots != nil) {
+			runtime·memmove(new, work.roots, work.rootcap*sizeof(Obj));
+			runtime·SysFree(work.roots, work.rootcap*sizeof(Obj));
+		}
+		work.roots = new;
+		work.rootcap = cap;
+	}
+	work.roots[work.nroot] = obj;
+	work.nroot++;
+}
+
+static void
+addstackroots(G *gp)
 {
 	M *mp;
 	int32 n;
@@ -571,7 +1308,7 @@ scanstack(void (*scanblock)(byte*, int64), G *gp)
 	byte *sp, *guard;
 
 	stk = (Stktop*)gp->stackbase;
-	guard = gp->stackguard;
+	guard = (byte*)gp->stackguard;
 
 	if(gp == g) {
 		// Scanning our own stack: start at &gp.
@@ -582,72 +1319,82 @@ scanstack(void (*scanblock)(byte*, int64), G *gp)
 	} else {
 		// Scanning another goroutine's stack.
 		// The goroutine is usually asleep (the world is stopped).
-		sp = gp->sched.sp;
+		sp = (byte*)gp->sched.sp;
 
 		// The exception is that if the goroutine 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.
-		if(gp->gcstack != nil) {
+		if(gp->gcstack != (uintptr)nil) {
 			stk = (Stktop*)gp->gcstack;
-			sp = gp->gcsp;
-			guard = gp->gcguard;
+			sp = (byte*)gp->gcsp;
+			guard = (byte*)gp->gcguard;
 		}
 	}
 
-	if(Debug > 1)
-		runtime·printf("scanstack %d %p\n", gp->goid, sp);
 	n = 0;
 	while(stk) {
 		if(sp < guard-StackGuard || (byte*)stk < sp) {
-			runtime·printf("scanstack inconsistent: g%d#%d sp=%p not in [%p,%p]\n", gp->goid, n, sp, guard-StackGuard, stk);
+			runtime·printf("scanstack inconsistent: g%D#%d sp=%p not in [%p,%p]\n", gp->goid, n, sp, guard-StackGuard, stk);
 			runtime·throw("scanstack");
 		}
-		scanblock(sp, (byte*)stk - sp);
-		sp = stk->gobuf.sp;
+		addroot((Obj){sp, (byte*)stk - sp, 0});
+		sp = (byte*)stk->gobuf.sp;
 		guard = stk->stackguard;
 		stk = (Stktop*)stk->stackbase;
 		n++;
 	}
 }
 
-// Markfin calls scanblock on the blocks that have finalizers:
-// the things pointed at cannot be freed until the finalizers have run.
 static void
-markfin(void *v)
+addfinroots(void *v)
 {
 	uintptr size;
+	void *base;
 
 	size = 0;
-	if(!runtime·mlookup(v, &v, &size, nil) || !runtime·blockspecial(v))
+	if(!runtime·mlookup(v, &base, &size, nil) || !runtime·blockspecial(base))
 		runtime·throw("mark - finalizer inconsistency");
 
 	// do not mark the finalizer block itself.  just mark the things it points at.
-	scanblock(v, size);
+	addroot((Obj){base, size, 0});
 }
 
 static void
-debug_markfin(void *v)
-{
-	uintptr size;
-
-	if(!runtime·mlookup(v, &v, &size, nil))
-		runtime·throw("debug_mark - finalizer inconsistency");
-	debug_scanblock(v, size);
-}
-
-// Mark
-static void
-mark(void (*scan)(byte*, int64))
+addroots(void)
 {
 	G *gp;
 	FinBlock *fb;
+	MSpan *s, **allspans;
+	uint32 spanidx;
+
+	work.nroot = 0;
+
+	// data & bss
+	// TODO(atom): load balancing
+	addroot((Obj){data, edata - data, (uintptr)gcdata});
+	addroot((Obj){bss, ebss - bss, (uintptr)gcbss});
+
+	// MSpan.types
+	allspans = runtime·mheap->allspans;
+	for(spanidx=0; spanidx<runtime·mheap->nspan; spanidx++) {
+		s = allspans[spanidx];
+		if(s->state == MSpanInUse) {
+			switch(s->types.compression) {
+			case MTypes_Empty:
+			case MTypes_Single:
+				break;
+			case MTypes_Words:
+			case MTypes_Bytes:
+				// TODO(atom): consider using defaultProg instead of 0
+				addroot((Obj){(byte*)&s->types.data, sizeof(void*), 0});
+				break;
+			}
+		}
+	}
 
-	// mark data+bss.
-	scan(data, ebss - data);
-
-	// mark stacks
+	// stacks
 	for(gp=runtime·allg; gp!=nil; gp=gp->alllink) {
 		switch(gp->status){
 		default:
@@ -658,37 +1405,30 @@ mark(void (*scan)(byte*, int64))
 		case Grunning:
 			if(gp != g)
 				runtime·throw("mark - world not stopped");
-			scanstack(scan, gp);
+			addstackroots(gp);
 			break;
 		case Grunnable:
 		case Gsyscall:
 		case Gwaiting:
-			scanstack(scan, gp);
+			addstackroots(gp);
 			break;
 		}
 	}
 
-	// mark things pointed at by objects with finalizers
-	if(scan == debug_scanblock)
-		runtime·walkfintab(debug_markfin);
-	else
-		runtime·walkfintab(markfin);
+	runtime·walkfintab(addfinroots);
 
 	for(fb=allfin; fb; fb=fb->alllink)
-		scanblock((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]));
-
-	// in multiproc mode, join in the queued work.
-	scan(nil, 0);
+		addroot((Obj){(byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]), 0});
 }
 
 static bool
 handlespecial(byte *p, uintptr size)
 {
-	void (*fn)(void*);
-	int32 nret;
+	FuncVal *fn;
+	uintptr nret;
 	FinBlock *block;
 	Finalizer *f;
-	
+
 	if(!runtime·getfinalizer(p, true, &fn, &nret)) {
 		runtime·setblockspecial(p, false);
 		runtime·MProf_Free(p, size);
@@ -699,6 +1439,8 @@ handlespecial(byte *p, uintptr size)
 	if(finq == nil || finq->cnt == finq->cap) {
 		if(finc == nil) {
 			finc = runtime·SysAlloc(PageSize);
+			if(finc == nil)
+				runtime·throw("runtime: cannot allocate memory");
 			finc->cap = (PageSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1;
 			finc->alllink = allfin;
 			allfin = finc;
@@ -713,124 +1455,225 @@ handlespecial(byte *p, uintptr size)
 	f->fn = fn;
 	f->nret = nret;
 	f->arg = p;
-	runtime·unlock(&finlock); 
+	runtime·unlock(&finlock);
 	return true;
 }
 
 // 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.
 static void
-sweep(void)
+sweepspan(ParFor *desc, uint32 idx)
 {
-	MSpan *s;
 	int32 cl, n, npages;
 	uintptr size;
 	byte *p;
 	MCache *c;
 	byte *arena_start;
-	int64 now;
+	MLink head, *end;
+	int32 nfree;
+	byte *type_data;
+	byte compression;
+	uintptr type_data_inc;
+	MSpan *s;
 
-	arena_start = runtime·mheap.arena_start;
-	now = runtime·nanotime();
+	USED(&desc);
+	s = runtime·mheap->allspans[idx];
+	if(s->state != MSpanInUse)
+		return;
+	arena_start = runtime·mheap->arena_start;
+	p = (byte*)(s->start << PageShift);
+	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;
+	}
+	nfree = 0;
+	end = &head;
+	c = m->mcache;
+	
+	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;
+	}
 
-	for(;;) {
-		s = work.spans;
-		if(s == nil)
-			break;
-		if(!runtime·casp(&work.spans, s, s->allnext))
-			continue;
+	// 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.
+	for(; n > 0; n--, p += size, type_data+=type_data_inc) {
+		uintptr off, *bitp, shift, bits;
 
-		// Stamp newly unused spans. The scavenger will use that
-		// info to potentially give back some pages to the OS.
-		if(s->state == MSpanFree && s->unusedsince == 0)
-			s->unusedsince = now;
+		off = (uintptr*)p - (uintptr*)arena_start;
+		bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		bits = *bitp>>shift;
 
-		if(s->state != MSpanInUse)
+		if((bits & bitAllocated) == 0)
 			continue;
 
-		p = (byte*)(s->start << PageShift);
-		cl = s->sizeclass;
+		if((bits & bitMarked) != 0) {
+			if(DebugMark) {
+				if(!(bits & bitSpecial))
+					runtime·printf("found spurious mark on %p\n", p);
+				*bitp &= ~(bitSpecial<<shift);
+			}
+			*bitp &= ~(bitMarked<<shift);
+			continue;
+		}
+
+		// Special means it has a finalizer or is being profiled.
+		// In DebugMark mode, the bit has been coopted so
+		// we have to assume all blocks are special.
+		if(DebugMark || (bits & bitSpecial) != 0) {
+			if(handlespecial(p, size))
+				continue;
+		}
+
+		// Mark freed; restore block boundary bit.
+		*bitp = (*bitp & ~(bitMask<<shift)) | (bitBlockBoundary<<shift);
+
 		if(cl == 0) {
-			size = s->npages<<PageShift;
-			n = 1;
+			// Free large span.
+			runtime·unmarkspan(p, 1<<PageShift);
+			*(uintptr*)p = 1;	// needs zeroing
+			runtime·MHeap_Free(runtime·mheap, s, 1);
+			c->local_alloc -= size;
+			c->local_nfree++;
 		} else {
-			// Chunk full of small blocks.
-			size = runtime·class_to_size[cl];
-			npages = runtime·class_to_allocnpages[cl];
-			n = (npages << PageShift) / size;
+			// Free small object.
+			switch(compression) {
+			case MTypes_Words:
+				*(uintptr*)type_data = 0;
+				break;
+			case MTypes_Bytes:
+				*(byte*)type_data = 0;
+				break;
+			}
+			if(size > sizeof(uintptr))
+				((uintptr*)p)[1] = 1;	// mark as "needs to be zeroed"
+			
+			end->next = (MLink*)p;
+			end = (MLink*)p;
+			nfree++;
 		}
+	}
 
-		// 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.
-		for(; n > 0; n--, p += size) {
-			uintptr off, *bitp, shift, bits;
+	if(nfree) {
+		c->local_by_size[cl].nfree += nfree;
+		c->local_alloc -= size * nfree;
+		c->local_nfree += nfree;
+		c->local_cachealloc -= nfree * size;
+		c->local_objects -= nfree;
+		runtime·MCentral_FreeSpan(&runtime·mheap->central[cl], s, nfree, head.next, end);
+	}
+}
 
-			off = (uintptr*)p - (uintptr*)arena_start;
-			bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
-			shift = off % wordsPerBitmapWord;
-			bits = *bitp>>shift;
+static void
+dumpspan(uint32 idx)
+{
+	int32 sizeclass, n, npages, i, column;
+	uintptr size;
+	byte *p;
+	byte *arena_start;
+	MSpan *s;
+	bool allocated, special;
 
-			if((bits & bitAllocated) == 0)
-				continue;
+	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;
 
-			if((bits & bitMarked) != 0) {
-				if(DebugMark) {
-					if(!(bits & bitSpecial))
-						runtime·printf("found spurious mark on %p\n", p);
-					*bitp &= ~(bitSpecial<<shift);
-				}
-				*bitp &= ~(bitMarked<<shift);
-				continue;
-			}
+		off = (uintptr*)p - (uintptr*)arena_start;
+		bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		bits = *bitp>>shift;
 
-			// Special means it has a finalizer or is being profiled.
-			// In DebugMark mode, the bit has been coopted so
-			// we have to assume all blocks are special.
-			if(DebugMark || (bits & bitSpecial) != 0) {
-				if(handlespecial(p, size))
-					continue;
+		allocated = ((bits & bitAllocated) != 0);
+		special = ((bits & bitSpecial) != 0);
+
+		for(i=0; i<size; i+=sizeof(void*)) {
+			if(column == 0) {
+				runtime·printf("\t");
+			}
+			if(i == 0) {
+				runtime·printf(allocated ? "(" : "[");
+				runtime·printf(special ? "@" : "");
+				runtime·printf("%p: ", p+i);
+			} else {
+				runtime·printf(" ");
 			}
 
-			// Mark freed; restore block boundary bit.
-			*bitp = (*bitp & ~(bitMask<<shift)) | (bitBlockBoundary<<shift);
+			runtime·printf("%p", *(void**)(p+i));
 
-			c = m->mcache;
-			if(s->sizeclass == 0) {
-				// Free large span.
-				runtime·unmarkspan(p, 1<<PageShift);
-				*(uintptr*)p = 1;	// needs zeroing
-				runtime·MHeap_Free(&runtime·mheap, s, 1);
-			} else {
-				// Free small object.
-				if(size > sizeof(uintptr))
-					((uintptr*)p)[1] = 1;	// mark as "needs to be zeroed"
-				c->local_by_size[s->sizeclass].nfree++;
-				runtime·MCache_Free(c, p, s->sizeclass, size);
+			if(i+sizeof(void*) >= size) {
+				runtime·printf(allocated ? ") " : "] ");
+			}
+
+			column++;
+			if(column == 8) {
+				runtime·printf("\n");
+				column = 0;
 			}
-			c->local_alloc -= size;
-			c->local_nfree++;
 		}
 	}
+	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)
 {
-	// Wait until main proc is ready for mark help.
-	runtime·lock(&work.markgate);
-	runtime·unlock(&work.markgate);
-	scanblock(nil, 0);
+	// parallel mark for over gc roots
+	runtime·parfordo(work.markfor);
+
+	// help other threads scan secondary blocks
+	scanblock(nil, nil, 0, true);
 
-	// Wait until main proc is ready for sweep help.
-	runtime·lock(&work.sweepgate);
-	runtime·unlock(&work.sweepgate);
-	sweep();
+	if(DebugMark) {
+		// wait while the main thread executes mark(debug_scanblock)
+		while(runtime·atomicload(&work.debugmarkdone) == 0)
+			runtime·usleep(10);
+	}
 
+	runtime·parfordo(work.sweepfor);
 	if(runtime·xadd(&work.ndone, +1) == work.nproc-1)
 		runtime·notewakeup(&work.alldone);
 }
 
+#define GcpercentUnknown (-2)
+
 // Initialized from $GOGC.  GOGC=off means no gc.
 //
 // Next gc is after we've allocated an extra amount of
@@ -840,33 +1683,36 @@ runtime·gchelper(void)
 // proportion to the allocation cost.  Adjusting gcpercent
 // just changes the linear constant (and also the amount of
 // extra memory used).
-static int32 gcpercent = -2;
+static int32 gcpercent = GcpercentUnknown;
 
 static void
-stealcache(void)
+cachestats(GCStats *stats)
 {
-	M *m;
-
-	for(m=runtime·allm; m; m=m->alllink)
-		runtime·MCache_ReleaseAll(m->mcache);
-}
-
-static void
-cachestats(void)
-{
-	M *m;
+	M *mp;
 	MCache *c;
+	P *p, **pp;
 	int32 i;
 	uint64 stacks_inuse;
-	uint64 stacks_sys;
+	uint64 *src, *dst;
 
+	if(stats)
+		runtime·memclr((byte*)stats, sizeof(*stats));
 	stacks_inuse = 0;
-	stacks_sys = 0;
-	for(m=runtime·allm; m; m=m->alllink) {
-		runtime·purgecachedstats(m);
-		stacks_inuse += m->stackalloc->inuse;
-		stacks_sys += m->stackalloc->sys;
-		c = m->mcache;
+	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));
+		}
+	}
+	for(pp=runtime·allp; p=*pp; pp++) {
+		c = p->mcache;
+		if(c==nil)
+			continue;
+		runtime·purgecachedstats(c);
 		for(i=0; i<nelem(c->local_by_size); i++) {
 			mstats.by_size[i].nmalloc += c->local_by_size[i].nmalloc;
 			c->local_by_size[i].nmalloc = 0;
@@ -875,16 +1721,42 @@ cachestats(void)
 		}
 	}
 	mstats.stacks_inuse = stacks_inuse;
-	mstats.stacks_sys = stacks_sys;
+}
+
+// Structure of arguments passed to function gc().
+// This allows the arguments to be passed via reflect·call.
+struct gc_args
+{
+	int32 force;
+};
+
+static void gc(struct gc_args *args);
+
+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);
 }
 
 void
 runtime·gc(int32 force)
 {
-	int64 t0, t1, t2, t3;
-	uint64 heap0, heap1, obj0, obj1;
 	byte *p;
-	bool extra;
+	struct gc_args a, *ap;
+	FuncVal gcv;
+
+	// 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");
 
 	// The gc is turned off (via enablegc) until
 	// the bootstrap has completed.
@@ -897,14 +1769,8 @@ runtime·gc(int32 force)
 	if(!mstats.enablegc || m->locks > 0 || runtime·panicking)
 		return;
 
-	if(gcpercent == -2) {	// first time through
-		p = runtime·getenv("GOGC");
-		if(p == nil || p[0] == '\0')
-			gcpercent = 100;
-		else if(runtime·strcmp(p, (byte*)"off") == 0)
-			gcpercent = -1;
-		else
-			gcpercent = runtime·atoi(p);
+	if(gcpercent == GcpercentUnknown) {	// first time through
+		gcpercent = readgogc();
 
 		p = runtime·getenv("GOGCTRACE");
 		if(p != nil)
@@ -913,103 +1779,171 @@ runtime·gc(int32 force)
 	if(gcpercent < 0)
 		return;
 
+	// Run gc on a bigger stack to eliminate
+	// a potentially large number of calls to runtime·morestack.
+	a.force = force;
+	ap = &a;
+	m->moreframesize_minalloc = StackBig;
+	gcv.fn = (void*)gc;
+	reflect·call(&gcv, (byte*)&ap, sizeof(ap));
+
+	if(gctrace > 1 && !force) {
+		a.force = 1;
+		gc(&a);
+	}
+}
+
+static FuncVal runfinqv = {runfinq};
+
+static void
+gc(struct gc_args *args)
+{
+	int64 t0, t1, t2, t3, t4;
+	uint64 heap0, heap1, obj0, obj1, ninstr;
+	GCStats stats;
+	M *mp;
+	uint32 i;
+	Eface eface;
+
 	runtime·semacquire(&runtime·worldsema);
-	if(!force && mstats.heap_alloc < mstats.next_gc) {
+	if(!args->force && mstats.heap_alloc < mstats.next_gc) {
 		runtime·semrelease(&runtime·worldsema);
 		return;
 	}
 
 	t0 = runtime·nanotime();
-	nhandoff = 0;
 
 	m->gcing = 1;
 	runtime·stoptheworld();
 
-	cachestats();
-	heap0 = mstats.heap_alloc;
-	obj0 = mstats.nmalloc - mstats.nfree;
+	if(CollectStats)
+		runtime·memclr((byte*)&gcstats, sizeof(gcstats));
 
-	runtime·lock(&work.markgate);
-	runtime·lock(&work.sweepgate);
+	for(mp=runtime·allm; mp; mp=mp->alllink)
+		runtime·settype_flush(mp, false);
 
-	extra = false;
-	work.nproc = 1;
-	if(runtime·gomaxprocs > 1 && runtime·ncpu > 1) {
-		runtime·noteclear(&work.alldone);
-		work.nproc += runtime·helpgc(&extra);
+	heap0 = 0;
+	obj0 = 0;
+	if(gctrace) {
+		cachestats(nil);
+		heap0 = mstats.heap_alloc;
+		obj0 = mstats.nmalloc - mstats.nfree;
 	}
+
+	m->locks++;	// disable gc during mallocs in parforalloc
+	if(work.markfor == nil)
+		work.markfor = runtime·parforalloc(MaxGcproc);
+	if(work.sweepfor == nil)
+		work.sweepfor = 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;
+	}
+
 	work.nwait = 0;
 	work.ndone = 0;
+	work.debugmarkdone = 0;
+	work.nproc = runtime·gcprocs();
+	addroots();
+	runtime·parforsetup(work.markfor, work.nproc, work.nroot, nil, false, markroot);
+	runtime·parforsetup(work.sweepfor, work.nproc, runtime·mheap->nspan, nil, true, sweepspan);
+	if(work.nproc > 1) {
+		runtime·noteclear(&work.alldone);
+		runtime·helpgc(work.nproc);
+	}
 
-	runtime·unlock(&work.markgate);  // let the helpers in
-	mark(scanblock);
-	if(DebugMark)
-		mark(debug_scanblock);
 	t1 = runtime·nanotime();
 
-	work.spans = runtime·mheap.allspans;
-	runtime·unlock(&work.sweepgate);  // let the helpers in
-	sweep();
+	runtime·parfordo(work.markfor);
+	scanblock(nil, nil, 0, true);
+
+	if(DebugMark) {
+		for(i=0; i<work.nroot; i++)
+			debug_scanblock(work.roots[i].p, work.roots[i].n);
+		runtime·atomicstore(&work.debugmarkdone, 1);
+	}
+	t2 = runtime·nanotime();
+
+	runtime·parfordo(work.sweepfor);
+	t3 = runtime·nanotime();
+
 	if(work.nproc > 1)
 		runtime·notesleep(&work.alldone);
-	t2 = runtime·nanotime();
 
-	stealcache();
-	cachestats();
+	cachestats(&stats);
+
+	stats.nprocyield += work.sweepfor->nprocyield;
+	stats.nosyield += work.sweepfor->nosyield;
+	stats.nsleep += work.sweepfor->nsleep;
 
 	mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/100;
 	m->gcing = 0;
 
-	m->locks++;	// disable gc during the mallocs in newproc
 	if(finq != nil) {
+		m->locks++;	// disable gc during the mallocs in newproc
 		// kick off or wake up goroutine to run queued finalizers
 		if(fing == nil)
-			fing = runtime·newproc1((byte*)runfinq, nil, 0, 0, runtime·gc);
+			fing = runtime·newproc1(&runfinqv, nil, 0, 0, runtime·gc);
 		else if(fingwait) {
 			fingwait = 0;
 			runtime·ready(fing);
 		}
+		m->locks--;
 	}
-	m->locks--;
 
-	cachestats();
 	heap1 = mstats.heap_alloc;
 	obj1 = mstats.nmalloc - mstats.nfree;
 
-	t3 = runtime·nanotime();
-	mstats.last_gc = t3;
-	mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = t3 - t0;
-	mstats.pause_total_ns += t3 - t0;
+	t4 = runtime·nanotime();
+	mstats.last_gc = t4;
+	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", t3-t0);
+		runtime·printf("pause %D\n", t4-t0);
 
 	if(gctrace) {
-		runtime·printf("gc%d(%d): %D+%D+%D ms %D -> %D MB %D -> %D (%D-%D) objects %D handoff\n",
-			mstats.numgc, work.nproc, (t1-t0)/1000000, (t2-t1)/1000000, (t3-t2)/1000000,
+		runtime·printf("gc%d(%d): %D+%D+%D ms, %D -> %D MB %D -> %D (%D-%D) objects,"
+				" %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\n",
+			mstats.numgc, work.nproc, (t2-t1)/1000000, (t3-t2)/1000000, (t1-t0+t4-t3)/1000000,
 			heap0>>20, heap1>>20, obj0, obj1,
 			mstats.nmalloc, mstats.nfree,
-			nhandoff);
+			stats.nhandoff, stats.nhandoffcnt,
+			work.sweepfor->nsteal, work.sweepfor->nstealcnt,
+			stats.nprocyield, stats.nosyield, stats.nsleep);
+		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·MProf_GC();
 	runtime·semrelease(&runtime·worldsema);
+	runtime·starttheworld();
 
-	// If we could have used another helper proc, start one now,
-	// in the hope that it will be available next time.
-	// It would have been even better to start it before the collection,
-	// but doing so requires allocating memory, so it's tricky to
-	// coordinate.  This lazy approach works out in practice:
-	// we don't mind if the first couple gc rounds don't have quite
-	// the maximum number of procs.
-	runtime·starttheworld(extra);
-
-	// give the queued finalizers, if any, a chance to run	
-	if(finq != nil)	
+	// give the queued finalizers, if any, a chance to run
+	if(finq != nil)
 		runtime·gosched();
-
-	if(gctrace > 1 && !force)
-		runtime·gc(1);
 }
 
 void
@@ -1022,11 +1956,56 @@ runtime·ReadMemStats(MStats *stats)
 	runtime·semacquire(&runtime·worldsema);
 	m->gcing = 1;
 	runtime·stoptheworld();
-	cachestats();
+	cachestats(nil);
 	*stats = mstats;
 	m->gcing = 0;
 	runtime·semrelease(&runtime·worldsema);
-	runtime·starttheworld(false);
+	runtime·starttheworld();
+}
+
+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;
+}
+
+void
+runtime∕debug·setGCPercent(intgo in, intgo out)
+{
+	runtime·lock(runtime·mheap);
+	if(gcpercent == GcpercentUnknown)
+		gcpercent = readgogc();
+	out = gcpercent;
+	if(in < 0)
+		in = -1;
+	gcpercent = in;
+	runtime·unlock(runtime·mheap);
+	FLUSH(&out);
 }
 
 static void
@@ -1050,11 +2029,11 @@ runfinq(void)
 		finq = nil;
 		if(fb == nil) {
 			fingwait = 1;
-			g->status = Gwaiting;
-			g->waitreason = "finalizer wait";
-			runtime·gosched();
+			runtime·park(nil, nil, "finalizer wait");
 			continue;
 		}
+		if(raceenabled)
+			runtime·racefingo();
 		for(; fb; fb=next) {
 			next = fb->next;
 			for(i=0; i<fb->cnt; i++) {
@@ -1066,7 +2045,7 @@ runfinq(void)
 					framecap = framesz;
 				}
 				*(void**)frame = f->arg;
-				reflect·call((byte*)f->fn, frame, sizeof(uintptr) + f->nret);
+				reflect·call(f->fn, frame, sizeof(uintptr) + f->nret);
 				f->fn = nil;
 				f->arg = nil;
 			}
@@ -1088,11 +2067,11 @@ runtime·markallocated(void *v, uintptr n, bool noptr)
 	if(0)
 		runtime·printf("markallocated %p+%p\n", v, n);
 
-	if((byte*)v+n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
+	if((byte*)v+n > (byte*)runtime·mheap->arena_used || (byte*)v < runtime·mheap->arena_start)
 		runtime·throw("markallocated: bad pointer");
 
-	off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start;  // word offset
-	b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
+	off = (uintptr*)v - (uintptr*)runtime·mheap->arena_start;  // word offset
+	b = (uintptr*)runtime·mheap->arena_start - off/wordsPerBitmapWord - 1;
 	shift = off % wordsPerBitmapWord;
 
 	for(;;) {
@@ -1120,11 +2099,11 @@ runtime·markfreed(void *v, uintptr n)
 	if(0)
 		runtime·printf("markallocated %p+%p\n", v, n);
 
-	if((byte*)v+n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
+	if((byte*)v+n > (byte*)runtime·mheap->arena_used || (byte*)v < runtime·mheap->arena_start)
 		runtime·throw("markallocated: bad pointer");
 
-	off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start;  // word offset
-	b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
+	off = (uintptr*)v - (uintptr*)runtime·mheap->arena_start;  // word offset
+	b = (uintptr*)runtime·mheap->arena_start - off/wordsPerBitmapWord - 1;
 	shift = off % wordsPerBitmapWord;
 
 	for(;;) {
@@ -1150,11 +2129,11 @@ runtime·checkfreed(void *v, uintptr n)
 	if(!runtime·checking)
 		return;
 
-	if((byte*)v+n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
+	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;
+	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;
@@ -1173,7 +2152,7 @@ runtime·markspan(void *v, uintptr size, uintptr n, bool leftover)
 	uintptr *b, off, shift;
 	byte *p;
 
-	if((byte*)v+size*n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
+	if((byte*)v+size*n > (byte*)runtime·mheap->arena_used || (byte*)v < runtime·mheap->arena_start)
 		runtime·throw("markspan: bad pointer");
 
 	p = v;
@@ -1184,8 +2163,8 @@ runtime·markspan(void *v, uintptr size, uintptr n, bool leftover)
 		// 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;
+		off = (uintptr*)p - (uintptr*)runtime·mheap->arena_start;  // word offset
+		b = (uintptr*)runtime·mheap->arena_start - off/wordsPerBitmapWord - 1;
 		shift = off % wordsPerBitmapWord;
 		*b = (*b & ~(bitMask<<shift)) | (bitBlockBoundary<<shift);
 	}
@@ -1197,14 +2176,14 @@ 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)
+	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
+	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;
+	b = (uintptr*)runtime·mheap->arena_start - off/wordsPerBitmapWord - 1;
 	n /= PtrSize;
 	if(n%wordsPerBitmapWord != 0)
 		runtime·throw("unmarkspan: unaligned length");
@@ -1225,8 +2204,8 @@ runtime·blockspecial(void *v)
 	if(DebugMark)
 		return true;
 
-	off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start;
-	b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
+	off = (uintptr*)v - (uintptr*)runtime·mheap->arena_start;
+	b = (uintptr*)runtime·mheap->arena_start - off/wordsPerBitmapWord - 1;
 	shift = off % wordsPerBitmapWord;
 
 	return (*b & (bitSpecial<<shift)) != 0;
@@ -1240,8 +2219,8 @@ runtime·setblockspecial(void *v, bool s)
 	if(DebugMark)
 		return;
 
-	off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start;
-	b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
+	off = (uintptr*)v - (uintptr*)runtime·mheap->arena_start;
+	b = (uintptr*)runtime·mheap->arena_start - off/wordsPerBitmapWord - 1;
 	shift = off % wordsPerBitmapWord;
 
 	for(;;) {
diff --git a/src/pkg/runtime/mgc0.go b/src/pkg/runtime/mgc0.go
new file mode 100644
index 0000000..b150546
--- /dev/null
+++ b/src/pkg/runtime/mgc0.go
@@ -0,0 +1,15 @@
+// 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 *itab.
+func gc_itab_ptr(ret *interface{}) {
+	*ret = (*itab)(nil)
+}
diff --git a/src/pkg/runtime/mgc0.h b/src/pkg/runtime/mgc0.h
new file mode 100644
index 0000000..87b604a
--- /dev/null
+++ b/src/pkg/runtime/mgc0.h
@@ -0,0 +1,43 @@
+// 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)
+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_MAP_PTR,     // Go map. Args: (off, MapType*)
+	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,	
+};
diff --git a/src/pkg/runtime/mheap.c b/src/pkg/runtime/mheap.c
index c877bfc..f45149d 100644
--- a/src/pkg/runtime/mheap.c
+++ b/src/pkg/runtime/mheap.c
@@ -27,11 +27,26 @@ RecordSpan(void *vh, byte *p)
 {
 	MHeap *h;
 	MSpan *s;
+	MSpan **all;
+	uint32 cap;
 
 	h = vh;
 	s = (MSpan*)p;
-	s->allnext = h->allspans;
-	h->allspans = s;
+	if(h->nspan >= h->nspancap) {
+		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]));
+		if(all == nil)
+			runtime·throw("runtime: cannot allocate memory");
+		if(h->allspans) {
+			runtime·memmove(all, h->allspans, h->nspancap*sizeof(all[0]));
+			runtime·SysFree(h->allspans, h->nspancap*sizeof(all[0]));
+		}
+		h->allspans = all;
+		h->nspancap = cap;
+	}
+	h->allspans[h->nspan++] = s;
 }
 
 // Initialize the heap; fetch memory using alloc.
@@ -53,12 +68,12 @@ runtime·MHeap_Init(MHeap *h, void *(*alloc)(uintptr))
 // Allocate a new span of npage pages from the heap
 // and record its size class in the HeapMap and HeapMapCache.
 MSpan*
-runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct)
+runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32 zeroed)
 {
 	MSpan *s;
 
 	runtime·lock(h);
-	runtime·purgecachedstats(m);
+	runtime·purgecachedstats(m->mcache);
 	s = MHeap_AllocLocked(h, npage, sizeclass);
 	if(s != nil) {
 		mstats.heap_inuse += npage<<PageShift;
@@ -68,6 +83,8 @@ runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct)
 		}
 	}
 	runtime·unlock(h);
+	if(s != nil && *(uintptr*)(s->start<<PageShift) != 0 && zeroed)
+		runtime·memclr((byte*)(s->start<<PageShift), s->npages<<PageShift);
 	return s;
 }
 
@@ -123,14 +140,15 @@ HaveSpan:
 		*(uintptr*)(t->start<<PageShift) = *(uintptr*)(s->start<<PageShift);  // copy "needs zeroing" mark
 		t->state = MSpanInUse;
 		MHeap_FreeLocked(h, t);
+		t->unusedsince = s->unusedsince; // preserve age
 	}
-
-	if(*(uintptr*)(s->start<<PageShift) != 0)
-		runtime·memclr((byte*)(s->start<<PageShift), s->npages<<PageShift);
+	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;
 	if(sizeof(void*) == 8)
 		p -= ((uintptr)h->arena_start>>PageShift);
@@ -259,7 +277,7 @@ void
 runtime·MHeap_Free(MHeap *h, MSpan *s, int32 acct)
 {
 	runtime·lock(h);
-	runtime·purgecachedstats(m);
+	runtime·purgecachedstats(m->mcache);
 	mstats.heap_inuse -= s->npages<<PageShift;
 	if(acct) {
 		mstats.heap_alloc -= s->npages<<PageShift;
@@ -276,16 +294,22 @@ MHeap_FreeLocked(MHeap *h, MSpan *s)
 	MSpan *t;
 	PageID p;
 
+	if(s->types.sysalloc)
+		runtime·settype_sysfree(s);
+	s->types.compression = MTypes_Empty;
+
 	if(s->state != MSpanInUse || s->ref != 0) {
 		runtime·printf("MHeap_FreeLocked - span %p ptr %p state %d ref %d\n", s, s->start<<PageShift, s->state, s->ref);
 		runtime·throw("MHeap_FreeLocked - invalid free");
 	}
 	mstats.heap_idle += s->npages<<PageShift;
 	s->state = MSpanFree;
-	s->unusedsince = 0;
-	s->npreleased = 0;
 	runtime·MSpanList_Remove(s);
 	sp = (uintptr*)(s->start<<PageShift);
+	// Stamp newly unused spans. The scavenger will use that
+	// info to potentially give back some pages to the OS.
+	s->unusedsince = runtime·nanotime();
+	s->npreleased = 0;
 
 	// Coalesce with earlier, later spans.
 	p = s->start;
@@ -325,6 +349,52 @@ MHeap_FreeLocked(MHeap *h, MSpan *s)
 		runtime·MSpanList_Insert(&h->large, s);
 }
 
+static void
+forcegchelper(Note *note)
+{
+	runtime·gc(1);
+	runtime·notewakeup(note);
+}
+
+static uintptr
+scavengelist(MSpan *list, uint64 now, uint64 limit)
+{
+	uintptr released, sumreleased;
+	MSpan *s;
+
+	if(runtime·MSpanList_IsEmpty(list))
+		return 0;
+
+	sumreleased = 0;
+	for(s=list->next; s != list; s=s->next) {
+		if((now - s->unusedsince) > limit) {
+			released = (s->npages - s->npreleased) << PageShift;
+			mstats.heap_released += released;
+			sumreleased += released;
+			s->npreleased = s->npages;
+			runtime·SysUnused((void*)(s->start << PageShift), s->npages << PageShift);
+		}
+	}
+	return sumreleased;
+}
+
+static uintptr
+scavenge(uint64 now, uint64 limit)
+{
+	uint32 i;
+	uintptr sumreleased;
+	MHeap *h;
+	
+	h = runtime·mheap;
+	sumreleased = 0;
+	for(i=0; i < nelem(h->free); i++)
+		sumreleased += scavengelist(&h->free[i], now, limit);
+	sumreleased += scavengelist(&h->large, now, limit);
+	return sumreleased;
+}
+
+static FuncVal forcegchelperv = {(void(*)(void))forcegchelper};
+
 // Release (part of) unused memory to OS.
 // Goroutine created at startup.
 // Loop forever.
@@ -332,13 +402,12 @@ void
 runtime·MHeap_Scavenger(void)
 {
 	MHeap *h;
-	MSpan *s, *list;
 	uint64 tick, now, forcegc, limit;
-	uint32 k, i;
-	uintptr released, sumreleased;
+	uint32 k;
+	uintptr sumreleased;
 	byte *env;
 	bool trace;
-	Note note;
+	Note note, *notep;
 
 	// If we go two minutes without a garbage collection, force one to run.
 	forcegc = 2*60*1e9;
@@ -356,10 +425,10 @@ runtime·MHeap_Scavenger(void)
 	if(env != nil)
 		trace = runtime·atoi(env) > 0;
 
-	h = &runtime·mheap;
+	h = runtime·mheap;
 	for(k=0;; k++) {
 		runtime·noteclear(&note);
-		runtime·entersyscall();
+		runtime·entersyscallblock();
 		runtime·notetsleep(&note, tick);
 		runtime·exitsyscall();
 
@@ -367,30 +436,21 @@ runtime·MHeap_Scavenger(void)
 		now = runtime·nanotime();
 		if(now - mstats.last_gc > forcegc) {
 			runtime·unlock(h);
-			runtime·gc(1);
+			// 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 = ¬e;
+			runtime·newproc1(&forcegchelperv, (byte*)&notep, sizeof(notep), 0, runtime·MHeap_Scavenger);
+			runtime·entersyscallblock();
+			runtime·notesleep(&note);
+			runtime·exitsyscall();
+			if(trace)
+				runtime·printf("scvg%d: GC forced\n", k);
 			runtime·lock(h);
 			now = runtime·nanotime();
-			if (trace)
-				runtime·printf("scvg%d: GC forced\n", k);
-		}
-		sumreleased = 0;
-		for(i=0; i < nelem(h->free)+1; i++) {
-			if(i < nelem(h->free))
-				list = &h->free[i];
-			else
-				list = &h->large;
-			if(runtime·MSpanList_IsEmpty(list))
-				continue;
-			for(s=list->next; s != list; s=s->next) {
-				if(s->unusedsince != 0 && (now - s->unusedsince) > limit) {
-					released = (s->npages - s->npreleased) << PageShift;
-					mstats.heap_released += released;
-					sumreleased += released;
-					s->npreleased = s->npages;
-					runtime·SysUnused((void*)(s->start << PageShift), s->npages << PageShift);
-				}
-			}
 		}
+		sumreleased = scavenge(now, limit);
 		runtime·unlock(h);
 
 		if(trace) {
@@ -403,6 +463,15 @@ runtime·MHeap_Scavenger(void)
 	}
 }
 
+void
+runtime∕debug·freeOSMemory(void)
+{
+	runtime·gc(1);
+	runtime·lock(runtime·mheap);
+	scavenge(~(uintptr)0, 0);
+	runtime·unlock(runtime·mheap);
+}
+
 // Initialize a new span with the given start and npages.
 void
 runtime·MSpan_Init(MSpan *span, PageID start, uintptr npages)
@@ -414,9 +483,11 @@ runtime·MSpan_Init(MSpan *span, PageID start, uintptr npages)
 	span->freelist = nil;
 	span->ref = 0;
 	span->sizeclass = 0;
+	span->elemsize = 0;
 	span->state = 0;
 	span->unusedsince = 0;
 	span->npreleased = 0;
+	span->types.compression = MTypes_Empty;
 }
 
 // Initialize an empty doubly-linked list.
diff --git a/src/pkg/runtime/mprof.goc b/src/pkg/runtime/mprof.goc
index 0bbce85..ebc1e3e 100644
--- a/src/pkg/runtime/mprof.goc
+++ b/src/pkg/runtime/mprof.goc
@@ -13,23 +13,73 @@ package runtime
 #include "type.h"
 
 // NOTE(rsc): Everything here could use cas if contention became an issue.
-static Lock proflock;
+static Lock proflock, alloclock;
 
-// Per-call-stack allocation information.
+// All memory allocations are local and do not escape outside of the profiler.
+// The profiler is forbidden from referring to garbage-collected memory.
+
+static byte *pool;        // memory allocation pool
+static uintptr poolfree;  // number of bytes left in the pool
+enum {
+	Chunk = 32*PageSize,  // initial size of the pool
+};
+
+// Memory allocation local to this file.
+// There is no way to return the allocated memory back to the OS.
+static void*
+allocate(uintptr size)
+{
+	void *v;
+
+	if(size == 0)
+		return nil;
+
+	if(size >= Chunk/2)
+		return runtime·SysAlloc(size);
+
+	runtime·lock(&alloclock);
+	if(size > poolfree) {
+		pool = runtime·SysAlloc(Chunk);
+		if(pool == nil)
+			runtime·throw("runtime: cannot allocate memory");
+		poolfree = Chunk;
+	}
+	v = pool;
+	pool += size;
+	poolfree -= size;
+	runtime·unlock(&alloclock);
+	return v;
+}
+
+enum { MProf, BProf };  // profile types
+
+// Per-call-stack profiling information.
 // Lookup by hashing call stack into a linked-list hash table.
 typedef struct Bucket Bucket;
 struct Bucket
 {
 	Bucket	*next;	// next in hash list
-	Bucket	*allnext;	// next in list of all buckets
-	uintptr	allocs;
-	uintptr	frees;
-	uintptr	alloc_bytes;
-	uintptr	free_bytes;
-	uintptr	recent_allocs;  // since last gc
-	uintptr	recent_frees;
-	uintptr	recent_alloc_bytes;
-	uintptr	recent_free_bytes;
+	Bucket	*allnext;	// next in list of all mbuckets/bbuckets
+	int32	typ;
+	union
+	{
+		struct  // typ == MProf
+		{
+			uintptr	allocs;
+			uintptr	frees;
+			uintptr	alloc_bytes;
+			uintptr	free_bytes;
+			uintptr	recent_allocs;  // since last gc
+			uintptr	recent_frees;
+			uintptr	recent_alloc_bytes;
+			uintptr	recent_free_bytes;
+		};
+		struct  // typ == BProf
+		{
+			int64	count;
+			int64	cycles;
+		};
+	};
 	uintptr	hash;
 	uintptr	nstk;
 	uintptr	stk[1];
@@ -38,12 +88,13 @@ enum {
 	BuckHashSize = 179999,
 };
 static Bucket **buckhash;
-static Bucket *buckets;
+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(uintptr *stk, int32 nstk, bool alloc)
+stkbucket(int32 typ, uintptr *stk, int32 nstk, bool alloc)
 {
 	int32 i;
 	uintptr h;
@@ -51,6 +102,8 @@ stkbucket(uintptr *stk, int32 nstk, bool alloc)
 
 	if(buckhash == nil) {
 		buckhash = runtime·SysAlloc(BuckHashSize*sizeof buckhash[0]);
+		if(buckhash == nil)
+			runtime·throw("runtime: cannot allocate memory");
 		mstats.buckhash_sys += BuckHashSize*sizeof buckhash[0];
 	}
 
@@ -66,33 +119,39 @@ stkbucket(uintptr *stk, int32 nstk, bool alloc)
 
 	i = h%BuckHashSize;
 	for(b = buckhash[i]; b; b=b->next)
-		if(b->hash == h && b->nstk == nstk &&
+		if(b->typ == typ && b->hash == h && b->nstk == nstk &&
 		   runtime·mcmp((byte*)b->stk, (byte*)stk, nstk*sizeof stk[0]) == 0)
 			return b;
 
 	if(!alloc)
 		return nil;
 
-	b = runtime·mallocgc(sizeof *b + nstk*sizeof stk[0], FlagNoProfiling, 0, 1);
+	b = allocate(sizeof *b + nstk*sizeof stk[0]);
+	if(b == nil)
+		runtime·throw("runtime: cannot allocate memory");
 	bucketmem += sizeof *b + nstk*sizeof stk[0];
 	runtime·memmove(b->stk, stk, nstk*sizeof stk[0]);
+	b->typ = typ;
 	b->hash = h;
 	b->nstk = nstk;
 	b->next = buckhash[i];
 	buckhash[i] = b;
-	b->allnext = buckets;
-	buckets = b;
+	if(typ == MProf) {
+		b->allnext = mbuckets;
+		mbuckets = b;
+	} else {
+		b->allnext = bbuckets;
+		bbuckets = b;
+	}
 	return b;
 }
 
-// Record that a gc just happened: all the 'recent' statistics are now real.
-void
-runtime·MProf_GC(void)
+static void
+MProf_GC(void)
 {
 	Bucket *b;
-	
-	runtime·lock(&proflock);
-	for(b=buckets; b; b=b->allnext) {
+
+	for(b=mbuckets; b; b=b->allnext) {
 		b->allocs += b->recent_allocs;
 		b->frees += b->recent_frees;
 		b->alloc_bytes += b->recent_alloc_bytes;
@@ -102,25 +161,39 @@ runtime·MProf_GC(void)
 		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);
 }
 
 // Map from pointer to Bucket* that allocated it.
 // Three levels:
-//	Linked-list hash table for top N-20 bits.
-//	Array index for next 13 bits.
-//	Linked list for next 7 bits.
+//	Linked-list hash table for top N-AddrHashShift bits.
+//	Array index for next AddrDenseBits bits.
+//	Linked list for next AddrHashShift-AddrDenseBits bits.
 // This is more efficient than using a general map,
 // because of the typical clustering of the pointer keys.
 
 typedef struct AddrHash AddrHash;
 typedef struct AddrEntry AddrEntry;
 
+enum {
+	AddrHashBits = 12,	// good for 4GB of used address space
+	AddrHashShift = 20,	// each AddrHash knows about 1MB of address space
+	AddrDenseBits = 8,	// good for a profiling rate of 4096 bytes
+};
+
 struct AddrHash
 {
 	AddrHash *next;	// next in top-level hash table linked list
 	uintptr addr;	// addr>>20
-	AddrEntry *dense[1<<13];
+	AddrEntry *dense[1<<AddrDenseBits];
 };
 
 struct AddrEntry
@@ -130,10 +203,7 @@ struct AddrEntry
 	Bucket *b;
 };
 
-enum {
-	AddrHashBits = 12	// 1MB per entry, so good for 4GB of used address space
-};
-static AddrHash *addrhash[1<<AddrHashBits];
+static AddrHash **addrhash;	// points to (AddrHash*)[1<<AddrHashBits]
 static AddrEntry *addrfree;
 static uintptr addrmem;
 
@@ -155,29 +225,29 @@ setaddrbucket(uintptr addr, Bucket *b)
 	AddrHash *ah;
 	AddrEntry *e;
 
-	h = (uint32)((addr>>20)*HashMultiplier) >> (32-AddrHashBits);
+	h = (uint32)((addr>>AddrHashShift)*HashMultiplier) >> (32-AddrHashBits);
 	for(ah=addrhash[h]; ah; ah=ah->next)
-		if(ah->addr == (addr>>20))
+		if(ah->addr == (addr>>AddrHashShift))
 			goto found;
 
-	ah = runtime·mallocgc(sizeof *ah, FlagNoProfiling, 0, 1);
+	ah = allocate(sizeof *ah);
 	addrmem += sizeof *ah;
 	ah->next = addrhash[h];
-	ah->addr = addr>>20;
+	ah->addr = addr>>AddrHashShift;
 	addrhash[h] = ah;
 
 found:
 	if((e = addrfree) == nil) {
-		e = runtime·mallocgc(64*sizeof *e, FlagNoProfiling, 0, 0);
+		e = allocate(64*sizeof *e);
 		addrmem += 64*sizeof *e;
 		for(i=0; i+1<64; i++)
 			e[i].next = &e[i+1];
 		e[63].next = nil;
 	}
 	addrfree = e->next;
-	e->addr = (uint32)~(addr & ((1<<20)-1));
+	e->addr = (uint32)~(addr & ((1<<AddrHashShift)-1));
 	e->b = b;
-	h = (addr>>7)&(nelem(ah->dense)-1);	// entry in dense is top 13 bits of low 20.
+	h = (addr>>(AddrHashShift-AddrDenseBits))&(nelem(ah->dense)-1);	// entry in dense is top 8 bits of low 20.
 	e->next = ah->dense[h];
 	ah->dense[h] = e;
 }
@@ -191,16 +261,16 @@ getaddrbucket(uintptr addr)
 	AddrEntry *e, **l;
 	Bucket *b;
 
-	h = (uint32)((addr>>20)*HashMultiplier) >> (32-AddrHashBits);
+	h = (uint32)((addr>>AddrHashShift)*HashMultiplier) >> (32-AddrHashBits);
 	for(ah=addrhash[h]; ah; ah=ah->next)
-		if(ah->addr == (addr>>20))
+		if(ah->addr == (addr>>AddrHashShift))
 			goto found;
 	return nil;
 
 found:
-	h = (addr>>7)&(nelem(ah->dense)-1);	// entry in dense is top 13 bits of low 20.
+	h = (addr>>(AddrHashShift-AddrDenseBits))&(nelem(ah->dense)-1);	// entry in dense is top 8 bits of low 20.
 	for(l=&ah->dense[h]; (e=*l) != nil; l=&e->next) {
-		if(e->addr == (uint32)~(addr & ((1<<20)-1))) {
+		if(e->addr == (uint32)~(addr & ((1<<AddrHashShift)-1))) {
 			*l = e->next;
 			b = e->b;
 			e->next = addrfree;
@@ -225,7 +295,7 @@ runtime·MProf_Malloc(void *p, uintptr size)
 	m->nomemprof++;
 	nstk = runtime·callers(1, stk, 32);
 	runtime·lock(&proflock);
-	b = stkbucket(stk, nstk, true);
+	b = stkbucket(MProf, stk, nstk, true);
 	b->recent_allocs++;
 	b->recent_alloc_bytes += size;
 	setaddrbucket((uintptr)p, b);
@@ -253,9 +323,37 @@ runtime·MProf_Free(void *p, uintptr size)
 	m->nomemprof--;
 }
 
+int64 runtime·blockprofilerate;  // in CPU ticks
+
+void
+runtime·SetBlockProfileRate(intgo rate)
+{
+	runtime·atomicstore64((uint64*)&runtime·blockprofilerate, rate * runtime·tickspersecond() / (1000*1000*1000));
+}
+
+void
+runtime·blockevent(int64 cycles, int32 skip)
+{
+	int32 nstk;
+	int64 rate;
+	uintptr stk[32];
+	Bucket *b;
 
-// Go interface to profile data.  (Declared in extern.go)
-// Assumes Go sizeof(int) == sizeof(int32)
+	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, 32);
+	runtime·lock(&proflock);
+	b = stkbucket(BProf, 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;
@@ -281,52 +379,101 @@ record(Record *r, Bucket *b)
 		r->stk[i] = 0;
 }
 
-func MemProfile(p Slice, include_inuse_zero bool) (n int32, ok bool) {
+func MemProfile(p Slice, include_inuse_zero bool) (n int, ok bool) {
 	Bucket *b;
 	Record *r;
+	bool clear;
 
 	runtime·lock(&proflock);
 	n = 0;
-	for(b=buckets; b; b=b->allnext)
+	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();
+		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=buckets; b; b=b->allnext)
+		for(b=mbuckets; b; b=b->allnext)
 			if(include_inuse_zero || b->alloc_bytes != b->free_bytes)
 				record(r++, b);
 	}
 	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 int32, ok bool) {
+func ThreadCreateProfile(p Slice) (n int, ok bool) {
 	TRecord *r;
-	M *first, *m;
+	M *first, *mp;
 	
 	first = runtime·atomicloadp(&runtime·allm);
 	n = 0;
-	for(m=first; m; m=m->alllink)
+	for(mp=first; mp; mp=mp->alllink)
 		n++;
 	ok = false;
 	if(n <= p.len) {
 		ok = true;
 		r = (TRecord*)p.array;
-		for(m=first; m; m=m->alllink) {
-			runtime·memmove(r->stk, m->createstack, sizeof r->stk);
+		for(mp=first; mp; mp=mp->alllink) {
+			runtime·memmove(r->stk, mp->createstack, sizeof r->stk);
 			r++;
 		}
 	}
 }
 
-func Stack(b Slice, all bool) (n int32) {
+func Stack(b Slice, all bool) (n int) {
 	byte *pc, *sp;
 	
 	sp = runtime·getcallersp(&b);
@@ -355,21 +502,21 @@ func Stack(b Slice, all bool) (n int32) {
 	if(all) {
 		m->gcing = 0;
 		runtime·semrelease(&runtime·worldsema);
-		runtime·starttheworld(false);
+		runtime·starttheworld();
 	}
 }
 
 static void
-saveg(byte *pc, byte *sp, G *g, TRecord *r)
+saveg(byte *pc, byte *sp, G *gp, TRecord *r)
 {
 	int32 n;
 	
-	n = runtime·gentraceback(pc, sp, 0, g, 0, r->stk, nelem(r->stk));
+	n = runtime·gentraceback(pc, sp, 0, gp, 0, r->stk, nelem(r->stk));
 	if(n < nelem(r->stk))
 		r->stk[n] = 0;
 }
 
-func GoroutineProfile(b Slice) (n int32, ok bool) {
+func GoroutineProfile(b Slice) (n int, ok bool) {
 	byte *pc, *sp;
 	TRecord *r;
 	G *gp;
@@ -392,13 +539,18 @@ func GoroutineProfile(b Slice) (n int32, ok bool) {
 			for(gp = runtime·allg; gp != nil; gp = gp->alllink) {
 				if(gp == g || gp->status == Gdead)
 					continue;
-				saveg(gp->sched.pc, gp->sched.sp, gp, r++);
+				saveg(gp->sched.pc, (byte*)gp->sched.sp, gp, r++);
 			}
 		}
 	
 		m->gcing = 0;
 		runtime·semrelease(&runtime·worldsema);
-		runtime·starttheworld(false);
+		runtime·starttheworld();
 	}
 }
 
+void
+runtime·mprofinit(void)
+{
+	addrhash = allocate((1<<AddrHashBits)*sizeof *addrhash);
+}
diff --git a/src/pkg/runtime/os_darwin.h b/src/pkg/runtime/os_darwin.h
index eb5d2da..5fcb717 100644
--- a/src/pkg/runtime/os_darwin.h
+++ b/src/pkg/runtime/os_darwin.h
@@ -4,9 +4,11 @@
 
 #define SIG_DFL ((void*)0)
 #define SIG_IGN ((void*)1)
+#define SIGHUP 1
+#define SS_DISABLE 4
 
 int32	runtime·bsdthread_create(void*, M*, G*, void(*)(void));
-void	runtime·bsdthread_register(void);
+int32	runtime·bsdthread_register(void);
 int32	runtime·mach_msg_trap(MachHeader*, int32, uint32, uint32, uint32, uint32, uint32);
 uint32	runtime·mach_reply_port(void);
 int32	runtime·mach_semacquire(uint32, int64);
diff --git a/src/pkg/runtime/os_freebsd.h b/src/pkg/runtime/os_freebsd.h
index 5e8de54..a37ad7c 100644
--- a/src/pkg/runtime/os_freebsd.h
+++ b/src/pkg/runtime/os_freebsd.h
@@ -1,5 +1,7 @@
 #define SIG_DFL ((void*)0)
 #define SIG_IGN ((void*)1)
+#define SIGHUP 1
+#define SS_DISABLE 4
 
 int32	runtime·thr_new(ThrParam*, int32);
 void	runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
@@ -15,7 +17,7 @@ int32	runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
 void	runtime·raisesigpipe(void);
 
 #define	NSIG 33
-#define	SI_USER	0
+#define	SI_USER	0x10001
 
 #define RLIMIT_AS 10
 typedef struct Rlimit Rlimit;
diff --git a/src/pkg/runtime/os_linux.h b/src/pkg/runtime/os_linux.h
index 87daa3b..a23fe0f 100644
--- a/src/pkg/runtime/os_linux.h
+++ b/src/pkg/runtime/os_linux.h
@@ -4,13 +4,15 @@
 
 #define SIG_DFL ((void*)0)
 #define SIG_IGN ((void*)1)
+#define SIGHUP 1
+#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;
-void	runtime·rt_sigaction(uintptr, struct Sigaction*, void*, uintptr);
+int32	runtime·rt_sigaction(uintptr, struct Sigaction*, void*, uintptr);
 void	runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
 void	runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
 
diff --git a/src/pkg/runtime/os_netbsd.h b/src/pkg/runtime/os_netbsd.h
index 4ecf78d..19d72fd 100644
--- a/src/pkg/runtime/os_netbsd.h
+++ b/src/pkg/runtime/os_netbsd.h
@@ -4,18 +4,29 @@
 
 #define SIG_DFL ((void*)0)
 #define SIG_IGN ((void*)1)
+#define SIGHUP 1
+#define SS_DISABLE 4
+
+#define SIG_BLOCK 1
+#define SIG_UNBLOCK 2
+#define SIG_SETMASK 3
 
 struct sigaction;
 
-void	runtime·sigpanic(void);
-void	runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
-void	runtime·sigaction(int32, struct sigaction*, struct sigaction*);
+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);
+
 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*);
 int32	runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
 
-void	runtime·raisesigpipe(void);
-
 #define	NSIG 33
 #define	SI_USER	0
+
+// From NetBSD's <sys/ucontext.h>
+#define _UC_SIGMASK	0x01
+#define _UC_CPU		0x04
diff --git a/src/pkg/runtime/os_openbsd.h b/src/pkg/runtime/os_openbsd.h
index 4ecf78d..a599aad 100644
--- a/src/pkg/runtime/os_openbsd.h
+++ b/src/pkg/runtime/os_openbsd.h
@@ -4,18 +4,25 @@
 
 #define SIG_DFL ((void*)0)
 #define SIG_IGN ((void*)1)
+#define SIGHUP 1
+#define SS_DISABLE 4
+
+#define SIG_BLOCK 1
+#define SIG_UNBLOCK 2
+#define SIG_SETMASK 3
 
 struct sigaction;
 
+void	runtime·raisesigpipe(void);
+void	runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
 void	runtime·sigpanic(void);
-void	runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
+
+void	runtime·setitimer(int32, Itimerval*, Itimerval*);
 void	runtime·sigaction(int32, struct sigaction*, struct sigaction*);
-void	runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
+void	runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
 void	runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
-void	runtime·setitimer(int32, Itimerval*, Itimerval*);
+Sigset	runtime·sigprocmask(int32, Sigset);
 int32	runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
 
-void	runtime·raisesigpipe(void);
-
 #define	NSIG 33
 #define	SI_USER	0
diff --git a/src/pkg/runtime/os_plan9.h b/src/pkg/runtime/os_plan9.h
index cc6343c..c2cdf5b 100644
--- a/src/pkg/runtime/os_plan9.h
+++ b/src/pkg/runtime/os_plan9.h
@@ -7,13 +7,22 @@ int32	runtime·open(uint8 *file, int32 mode);
 int32	runtime·pread(int32 fd, void *buf, int32 nbytes, int64 offset);
 int32	runtime·pwrite(int32 fd, void *buf, int32 nbytes, int64 offset);
 int32	runtime·read(int32 fd, void *buf, int32 nbytes);
+int64	runtime·seek(int32 fd, int64 offset, int32 whence);
 int32	runtime·close(int32 fd);
 void	runtime·exits(int8* msg);
-int32	runtime·brk_(void*);
+intptr	runtime·brk_(void*);
 int32	runtime·sleep(int32 ms);
-int32	runtime·rfork(int32 flags, void *stk, M *m, G *g, void (*fn)(void));
+int32	runtime·rfork(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
 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);
+void	runtime·sigtramp(void*, int8*);
+int32	runtime·sighandler(void*, int8*, G*);
+void	runtime·sigpanic(void);
+void	runtime·goexitsall(int8*);
+void	runtime·setfpmasks(void);
 
 /* open */
 enum
@@ -45,6 +54,13 @@ enum
 	RFNOMNT         = (1<<14)
 };
 
+/* notify */
+enum
+{
+	NCONT	= 0,
+	NDFLT	= 1
+};
+
 typedef struct Tos Tos;
 typedef intptr Plink;
 
@@ -66,4 +82,5 @@ struct Tos {
 	/* top of stack is here */
 };
 
-#define	NSIG 1
+#define	NSIG	5	/* number of signals in runtime·SigTab array */
+#define	ERRMAX	128	/* max length of note string */
diff --git a/src/pkg/runtime/os_windows.h b/src/pkg/runtime/os_windows.h
index 9d387b7..cf0ecb6 100644
--- a/src/pkg/runtime/os_windows.h
+++ b/src/pkg/runtime/os_windows.h
@@ -28,5 +28,8 @@ uint32 runtime·ctrlhandler(uint32 type);
 byte *runtime·compilecallback(Eface fn, bool cleanstack);
 void *runtime·callbackasm(void);
 
+void runtime·install_exception_handler(void);
+void runtime·remove_exception_handler(void);
+
 // TODO(brainman): should not need those
 #define	NSIG	65
diff --git a/src/pkg/runtime/panic.c b/src/pkg/runtime/panic.c
new file mode 100644
index 0000000..2f553f4
--- /dev/null
+++ b/src/pkg/runtime/panic.c
@@ -0,0 +1,487 @@
+// 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"
+
+// Code related to defer, panic and recover.
+
+uint32 runtime·panicking;
+static Lock paniclk;
+
+enum
+{
+	DeferChunkSize = 2048
+};
+
+// Allocate a Defer, usually as part of the larger frame of deferred functions.
+// Each defer must be released with both popdefer and freedefer.
+static Defer*
+newdefer(int32 siz)
+{
+	int32 total;
+	DeferChunk *c;
+	Defer *d;
+	
+	c = g->dchunk;
+	total = sizeof(*d) + ROUND(siz, sizeof(uintptr)) - sizeof(d->args);
+	if(c == nil || total > DeferChunkSize - c->off) {
+		if(total > DeferChunkSize / 2) {
+			// Not worth putting in any chunk.
+			// Allocate a separate block.
+			d = runtime·malloc(total);
+			d->siz = siz;
+			d->special = 1;
+			d->free = 1;
+			d->link = g->defer;
+			g->defer = d;
+			return d;
+		}
+
+		// Cannot fit in current chunk.
+		// Switch to next chunk, allocating if necessary.
+		c = g->dchunknext;
+		if(c == nil)
+			c = runtime·malloc(DeferChunkSize);
+		c->prev = g->dchunk;
+		c->off = sizeof(*c);
+		g->dchunk = c;
+		g->dchunknext = nil;
+	}
+
+	d = (Defer*)((byte*)c + c->off);
+	c->off += total;
+	d->siz = siz;
+	d->special = 0;
+	d->free = 0;
+	d->link = g->defer;
+	g->defer = d;
+	return d;	
+}
+
+// Pop the current defer from the defer stack.
+// Its contents are still valid until the goroutine begins executing again.
+// In particular it is safe to call reflect.call(d->fn, d->argp, d->siz) after
+// popdefer returns.
+static void
+popdefer(void)
+{
+	Defer *d;
+	DeferChunk *c;
+	int32 total;
+	
+	d = g->defer;
+	if(d == nil)
+		runtime·throw("runtime: popdefer nil");
+	g->defer = d->link;
+	if(d->special) {
+		// Nothing else to do.
+		return;
+	}
+	total = sizeof(*d) + ROUND(d->siz, sizeof(uintptr)) - sizeof(d->args);
+	c = g->dchunk;
+	if(c == nil || (byte*)d+total != (byte*)c+c->off)
+		runtime·throw("runtime: popdefer phase error");
+	c->off -= total;
+	if(c->off == sizeof(*c)) {
+		// Chunk now empty, so pop from stack.
+		// Save in dchunknext both to help with pingponging between frames
+		// and to make sure d is still valid on return.
+		if(g->dchunknext != nil)
+			runtime·free(g->dchunknext);
+		g->dchunknext = c;
+		g->dchunk = c->prev;
+	}
+}
+
+// Free the given defer.
+// For defers in the per-goroutine chunk this just clears the saved arguments.
+// For large defers allocated on the heap, this frees them.
+// The defer cannot be used after this call.
+static void
+freedefer(Defer *d)
+{
+	if(d->special) {
+		if(d->free)
+			runtime·free(d);
+	} else {
+		runtime·memclr((byte*)d->args, d->siz);
+	}
+}
+
+// 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 7
+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.
+#pragma textflag 7
+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;
+	runtime·memmove(argp, d->args, d->siz);
+	fn = d->fn;
+	popdefer();
+	freedefer(d);
+	runtime·jmpdefer(fn, argp);
+}
+
+// Run all deferred functions for the current goroutine.
+static void
+rundefer(void)
+{
+	Defer *d;
+
+	while((d = g->defer) != nil) {
+		popdefer();
+		reflect·call(d->fn, (byte*)d->args, 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*);
+
+// The implementation of the predeclared function panic.
+void
+runtime·panic(Eface e)
+{
+	Defer *d;
+	Panic *p;
+	void *pc, *argp;
+	
+	p = runtime·mal(sizeof *p);
+	p->arg = e;
+	p->link = g->panic;
+	p->stackbase = (byte*)g->stackbase;
+	g->panic = p;
+
+	for(;;) {
+		d = g->defer;
+		if(d == nil)
+			break;
+		// take defer off list in case of recursive panic
+		popdefer();
+		g->ispanic = true;	// rock for newstack, where reflect.call ends up
+		argp = d->argp;
+		pc = d->pc;
+		reflect·call(d->fn, (byte*)d->args, d->siz);
+		freedefer(d);
+		if(p->recovered) {
+			g->panic = p->link;
+			if(g->panic == nil)	// must be done with signal
+				g->sig = 0;
+			runtime·free(p);
+			// 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);
+}
+
+// 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;
+	void *pc;
+	
+	// Info about defer passed in G struct.
+	argp = (void*)gp->sigcode0;
+	pc = (void*)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;
+	runtime·gogo(&gp->sched, 1);
+}
+
+// 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) != nil && top->stackbase != nil) {
+		stk = (byte*)gp->stackguard - StackGuard;
+		if(stk <= sp && sp < (byte*)gp->stackbase)
+			break;
+		gp->stackbase = (uintptr)top->stackbase;
+		gp->stackguard = (uintptr)top->stackguard;
+		if(top->free != 0)
+			runtime·stackfree(stk, top->free);
+	}
+
+	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 7
+void
+runtime·recover(byte *argp, Eface ret)
+{
+	Stktop *top, *oldtop;
+	Panic *p;
+
+	// Must be a panic going on.
+	if((p = g->panic) == nil || p->recovered)
+		goto nomatch;
+
+	// Frame must be at the top of the stack segment,
+	// because each deferred call starts a new stack
+	// segment as a side effect of using reflect.call.
+	// (There has to be some way to remember the
+	// variable argument frame size, and the segment
+	// code already takes care of that for us, so we
+	// reuse it.)
+	//
+	// As usual closures complicate things: the fp that
+	// the closure implementation function claims to have
+	// is where the explicit arguments start, after the
+	// implicit pointer arguments and PC slot.
+	// If we're on the first new segment for a closure,
+	// then fp == top - top->args is correct, but if
+	// the closure has its own big argument frame and
+	// allocated a second segment (see below),
+	// the fp is slightly above top - top->args.
+	// That condition can't happen normally though
+	// (stack pointers go down, not up), so we can accept
+	// any fp between top and top - top->args as
+	// indicating the top of the segment.
+	top = (Stktop*)g->stackbase;
+	if(argp < (byte*)top - top->argsize || (byte*)top < argp)
+		goto nomatch;
+
+	// The deferred call makes a new segment big enough
+	// for the argument frame but not necessarily big
+	// enough for the function's local frame (size unknown
+	// at the time of the call), so the function might have
+	// made its own segment immediately.  If that's the
+	// case, back top up to the older one, the one that
+	// reflect.call would have made for the panic.
+	//
+	// The fp comparison here checks that the argument
+	// frame that was copied during the split (the top->args
+	// bytes above top->fp) abuts the old top of stack.
+	// This is a correct test for both closure and non-closure code.
+	oldtop = (Stktop*)top->stackbase;
+	if(oldtop != nil && top->argp == (byte*)oldtop - top->argsize)
+		top = oldtop;
+
+	// Now we have the segment that was created to
+	// run this call.  It must have been marked as a panic segment.
+	if(!top->panic)
+		goto nomatch;
+
+	// Okay, this is the top frame of a deferred call
+	// in response to a panic.  It can see the panic argument.
+	p->recovered = 1;
+	ret = p->arg;
+	FLUSH(&ret);
+	return;
+
+nomatch:
+	ret.type = nil;
+	ret.data = nil;
+	FLUSH(&ret);
+}
+
+void
+runtime·startpanic(void)
+{
+	if(m->mcache == nil)  // can happen if called from signal handler or throw
+		m->mcache = runtime·allocmcache();
+	if(m->dying) {
+		runtime·printf("panic during panic\n");
+		runtime·exit(3);
+	}
+	m->dying = 1;
+	runtime·xadd(&runtime·panicking, 1);
+	runtime·lock(&paniclk);
+}
+
+void
+runtime·dopanic(int32 unused)
+{
+	static bool didothers;
+
+	if(g->sig != 0)
+		runtime·printf("[signal %x code=%p addr=%p pc=%p]\n",
+			g->sig, g->sigcode0, g->sigcode1, g->sigpc);
+
+	if(runtime·gotraceback()){
+		if(g != m->g0) {
+			runtime·printf("\n");
+			runtime·goroutineheader(g);
+			runtime·traceback(runtime·getcallerpc(&unused), 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);
+	}
+
+	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");
+}
+
+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;
+
+	if(m->gcing) {
+		runtime·printf("panic: %s\n", s);
+		runtime·throw("panic during gc");
+	}
+	runtime·newErrorString(runtime·gostringnocopy((byte*)s), &err);
+	runtime·panic(err);
+}
+
+void
+runtime·Goexit(void)
+{
+	rundefer();
+	runtime·goexit();
+}
diff --git a/src/pkg/runtime/parfor.c b/src/pkg/runtime/parfor.c
new file mode 100644
index 0000000..aa5537d
--- /dev/null
+++ b/src/pkg/runtime/parfor.c
@@ -0,0 +1,215 @@
+// 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.
+
+// Parallel for algorithm.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+
+struct ParForThread
+{
+	// the thread's iteration space [32lsb, 32msb)
+	uint64 pos;
+	// stats
+	uint64 nsteal;
+	uint64 nstealcnt;
+	uint64 nprocyield;
+	uint64 nosyield;
+	uint64 nsleep;
+	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;
+}
+
+// For testing from Go
+// func parforalloc2(nthrmax uint32) *ParFor
+void
+runtime·parforalloc2(uint32 nthrmax, ParFor *desc)
+{
+	desc = runtime·parforalloc(nthrmax);
+	FLUSH(&desc);
+}
+
+void
+runtime·parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32))
+{
+	uint32 i, begin, end;
+
+	if(desc == nil || nthr == 0 || nthr > desc->nthrmax || body == nil) {
+		runtime·printf("desc=%p nthr=%d count=%d body=%p\n", desc, nthr, n, body);
+		runtime·throw("parfor: invalid args");
+	}
+
+	desc->body = body;
+	desc->done = 0;
+	desc->nthr = nthr;
+	desc->thrseq = 0;
+	desc->cnt = n;
+	desc->ctx = ctx;
+	desc->wait = wait;
+	desc->nsteal = 0;
+	desc->nstealcnt = 0;
+	desc->nprocyield = 0;
+	desc->nosyield = 0;
+	desc->nsleep = 0;
+	for(i=0; i<nthr; i++) {
+		begin = (uint64)n*i / nthr;
+		end = (uint64)n*(i+1) / nthr;
+		desc->thr[i].pos = (uint64)begin | (((uint64)end)<<32);
+	}
+}
+
+// For testing from Go
+// func parforsetup2(desc *ParFor, nthr, n uint32, ctx *byte, wait bool, body func(*ParFor, uint32))
+void
+runtime·parforsetup2(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void *body)
+{
+	runtime·parforsetup(desc, nthr, n, ctx, wait, *(void(**)(ParFor*, uint32))body);
+}
+
+void
+runtime·parfordo(ParFor *desc)
+{
+	ParForThread *me;
+	uint32 tid, begin, end, begin2, try, victim, i;
+	uint64 *mypos, *victimpos, pos, newpos;
+	void (*body)(ParFor*, uint32);
+	bool idle;
+
+	// Obtain 0-based thread index.
+	tid = runtime·xadd(&desc->thrseq, 1) - 1;
+	if(tid >= desc->nthr) {
+		runtime·printf("tid=%d nthr=%d\n", tid, desc->nthr);
+		runtime·throw("parfor: invalid tid");
+	}
+
+	// If single-threaded, just execute the for serially.
+	if(desc->nthr==1) {
+		for(i=0; i<desc->cnt; i++)
+			desc->body(desc, i);
+		return;
+	}
+
+	body = desc->body;
+	me = &desc->thr[tid];
+	mypos = &me->pos;
+	for(;;) {
+		for(;;) {
+			// While there is local work,
+			// bump low index and execute the iteration.
+			pos = runtime·xadd64(mypos, 1);
+			begin = (uint32)pos-1;
+			end = (uint32)(pos>>32);
+			if(begin < end) {
+				body(desc, begin);
+				continue;
+			}
+			break;
+		}
+
+		// Out of work, need to steal something.
+		idle = false;
+		for(try=0;; try++) {
+			// If we don't see any work for long enough,
+			// increment the done counter...
+			if(try > desc->nthr*4 && !idle) {
+				idle = true;
+				runtime·xadd(&desc->done, 1);
+			}
+			// ...if all threads have incremented the counter,
+			// we are done.
+			if(desc->done + !idle == desc->nthr) {
+				if(!idle)
+					runtime·xadd(&desc->done, 1);
+				goto exit;
+			}
+			// Choose a random victim for stealing.
+			victim = runtime·fastrand1() % (desc->nthr-1);
+			if(victim >= tid)
+				victim++;
+			victimpos = &desc->thr[victim].pos;
+			pos = runtime·atomicload64(victimpos);
+			for(;;) {
+				// See if it has any work.
+				begin = (uint32)pos;
+				end = (uint32)(pos>>32);
+				if(begin+1 >= end) {
+					begin = end = 0;
+					break;
+				}
+				if(idle) {
+					runtime·xadd(&desc->done, -1);
+					idle = false;
+				}
+				begin2 = begin + (end-begin)/2;
+				newpos = (uint64)begin | (uint64)begin2<<32;
+				if(runtime·cas64(victimpos, &pos, newpos)) {
+					begin = begin2;
+					break;
+				}
+			}
+			if(begin < end) {
+				// Has successfully stolen some work.
+				if(idle)
+					runtime·throw("parfor: should not be idle");
+				runtime·atomicstore64(mypos, (uint64)begin | (uint64)end<<32);
+				me->nsteal++;
+				me->nstealcnt += end-begin;
+				break;
+			}
+			// Backoff.
+			if(try < desc->nthr) {
+				// nothing
+			} else if (try < 4*desc->nthr) {
+				me->nprocyield++;
+				runtime·procyield(20);
+			// If a caller asked not to wait for the others, exit now
+			// (assume that most work is already done at this point).
+			} else if (!desc->wait) {
+				if(!idle)
+					runtime·xadd(&desc->done, 1);
+				goto exit;
+			} else if (try < 6*desc->nthr) {
+				me->nosyield++;
+				runtime·osyield();
+			} else {
+				me->nsleep++;
+				runtime·usleep(1);
+			}
+		}
+	}
+exit:
+	runtime·xadd64(&desc->nsteal, me->nsteal);
+	runtime·xadd64(&desc->nstealcnt, me->nstealcnt);
+	runtime·xadd64(&desc->nprocyield, me->nprocyield);
+	runtime·xadd64(&desc->nosyield, me->nosyield);
+	runtime·xadd64(&desc->nsleep, me->nsleep);
+	me->nsteal = 0;
+	me->nstealcnt = 0;
+	me->nprocyield = 0;
+	me->nosyield = 0;
+	me->nsleep = 0;
+}
+
+// For testing from Go
+// func parforiters(desc *ParFor, tid uintptr) (uintptr, uintptr)
+void
+runtime·parforiters(ParFor *desc, uintptr tid, uintptr start, uintptr end)
+{
+	start = (uint32)desc->thr[tid].pos;
+	end = (uint32)(desc->thr[tid].pos>>32);
+	FLUSH(&start);
+	FLUSH(&end);
+}
diff --git a/src/pkg/runtime/parfor_test.go b/src/pkg/runtime/parfor_test.go
new file mode 100644
index 0000000..4c69a68
--- /dev/null
+++ b/src/pkg/runtime/parfor_test.go
@@ -0,0 +1,144 @@
+// 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.
+
+// The race detector does not understand ParFor synchronization.
+// +build !race
+
+package runtime_test
+
+import (
+	. "runtime"
+	"testing"
+	"unsafe"
+)
+
+var gdata []uint64
+
+// Simple serial sanity test for parallelfor.
+func TestParFor(t *testing.T) {
+	const P = 1
+	const N = 20
+	data := make([]uint64, N)
+	for i := uint64(0); i < N; i++ {
+		data[i] = i
+	}
+	desc := NewParFor(P)
+	// Avoid making func a closure: parfor cannot invoke them.
+	// Since it doesn't happen in the C code, it's not worth doing
+	// just for the test.
+	gdata = data
+	ParForSetup(desc, P, N, nil, true, func(desc *ParFor, i uint32) {
+		data := gdata
+		data[i] = data[i]*data[i] + 1
+	})
+	ParForDo(desc)
+	for i := uint64(0); i < N; i++ {
+		if data[i] != i*i+1 {
+			t.Fatalf("Wrong element %d: %d", i, data[i])
+		}
+	}
+}
+
+// Test that nonblocking parallelfor does not block.
+func TestParFor2(t *testing.T) {
+	const P = 7
+	const N = 1003
+	data := make([]uint64, N)
+	for i := uint64(0); i < N; i++ {
+		data[i] = i
+	}
+	desc := NewParFor(P)
+	ParForSetup(desc, P, N, (*byte)(unsafe.Pointer(&data)), false, func(desc *ParFor, i uint32) {
+		d := *(*[]uint64)(unsafe.Pointer(desc.Ctx))
+		d[i] = d[i]*d[i] + 1
+	})
+	for p := 0; p < P; p++ {
+		ParForDo(desc)
+	}
+	for i := uint64(0); i < N; i++ {
+		if data[i] != i*i+1 {
+			t.Fatalf("Wrong element %d: %d", i, data[i])
+		}
+	}
+}
+
+// Test that iterations are properly distributed.
+func TestParForSetup(t *testing.T) {
+	const P = 11
+	const N = 101
+	desc := NewParFor(P)
+	for n := uint32(0); n < N; n++ {
+		for p := uint32(1); p <= P; p++ {
+			ParForSetup(desc, p, n, nil, true, func(desc *ParFor, i uint32) {})
+			sum := uint32(0)
+			size0 := uint32(0)
+			end0 := uint32(0)
+			for i := uint32(0); i < p; i++ {
+				begin, end := ParForIters(desc, i)
+				size := end - begin
+				sum += size
+				if i == 0 {
+					size0 = size
+					if begin != 0 {
+						t.Fatalf("incorrect begin: %d (n=%d, p=%d)", begin, n, p)
+					}
+				} else {
+					if size != size0 && size != size0+1 {
+						t.Fatalf("incorrect size: %d/%d (n=%d, p=%d)", size, size0, n, p)
+					}
+					if begin != end0 {
+						t.Fatalf("incorrect begin/end: %d/%d (n=%d, p=%d)", begin, end0, n, p)
+					}
+				}
+				end0 = end
+			}
+			if sum != n {
+				t.Fatalf("incorrect sum: %d/%d (p=%d)", sum, n, p)
+			}
+		}
+	}
+}
+
+// Test parallel parallelfor.
+func TestParForParallel(t *testing.T) {
+	if GOARCH != "amd64" {
+		t.Log("temporarily disabled, see http://golang.org/issue/4155")
+		return
+	}
+
+	N := uint64(1e7)
+	if testing.Short() {
+		N /= 10
+	}
+	data := make([]uint64, N)
+	for i := uint64(0); i < N; i++ {
+		data[i] = i
+	}
+	P := GOMAXPROCS(-1)
+	c := make(chan bool, P)
+	desc := NewParFor(uint32(P))
+	gdata = data
+	ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) {
+		data := gdata
+		data[i] = data[i]*data[i] + 1
+	})
+	for p := 1; p < P; p++ {
+		go func() {
+			ParForDo(desc)
+			c <- true
+		}()
+	}
+	ParForDo(desc)
+	for p := 1; p < P; p++ {
+		<-c
+	}
+	for i := uint64(0); i < N; i++ {
+		if data[i] != i*i+1 {
+			t.Fatalf("Wrong element %d: %d", i, data[i])
+		}
+	}
+
+	data, desc = nil, nil
+	GC()
+}
diff --git a/src/pkg/runtime/pprof/pprof.go b/src/pkg/runtime/pprof/pprof.go
index f67e8a8..32c1098 100644
--- a/src/pkg/runtime/pprof/pprof.go
+++ b/src/pkg/runtime/pprof/pprof.go
@@ -36,8 +36,9 @@ import (
 //	goroutine    - stack traces of all current goroutines
 //	heap         - a sampling of all heap allocations
 //	threadcreate - stack traces that led to the creation of new OS threads
+//	block        - stack traces that led to blocking on synchronization primitives
 //
-// These predefine profiles maintain themselves and panic on an explicit
+// These predefined profiles maintain themselves and panic on an explicit
 // Add or Remove method call.
 //
 // The CPU profile is not available as a Profile.  It has a special API,
@@ -76,6 +77,12 @@ var heapProfile = &Profile{
 	write: writeHeap,
 }
 
+var blockProfile = &Profile{
+	name:  "block",
+	count: countBlock,
+	write: writeBlock,
+}
+
 func lockProfiles() {
 	profiles.mu.Lock()
 	if profiles.m == nil {
@@ -84,6 +91,7 @@ func lockProfiles() {
 			"goroutine":    goroutineProfile,
 			"threadcreate": threadcreateProfile,
 			"heap":         heapProfile,
+			"block":        blockProfile,
 		}
 	}
 }
@@ -310,21 +318,33 @@ func printCountProfile(w io.Writer, debug int, name string, p countProfile) erro
 // for a single stack trace.
 func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) {
 	show := allFrames
-	for _, pc := range stk {
+	wasPanic := false
+	for i, pc := range stk {
 		f := runtime.FuncForPC(pc)
 		if f == nil {
 			show = true
 			fmt.Fprintf(w, "#\t%#x\n", pc)
+			wasPanic = false
 		} else {
-			file, line := f.FileLine(pc)
+			tracepc := pc
+			// Back up to call instruction.
+			if i > 0 && pc > f.Entry() && !wasPanic {
+				if runtime.GOARCH == "386" || runtime.GOARCH == "amd64" {
+					tracepc--
+				} else {
+					tracepc -= 4 // arm, etc
+				}
+			}
+			file, line := f.FileLine(tracepc)
 			name := f.Name()
 			// Hide runtime.goexit and any runtime functions at the beginning.
 			// This is useful mainly for allocation traces.
+			wasPanic = name == "runtime.panic"
 			if name == "runtime.goexit" || !show && strings.HasPrefix(name, "runtime.") {
 				continue
 			}
 			show = true
-			fmt.Fprintf(w, "#\t%#x\t%s+%#x\t%s:%d\n", pc, f.Name(), pc-f.Entry(), file, line)
+			fmt.Fprintf(w, "#\t%#x\t%s+%#x\t%s:%d\n", pc, name, pc-f.Entry(), file, line)
 		}
 	}
 	if !show {
@@ -352,26 +372,26 @@ func WriteHeapProfile(w io.Writer) error {
 
 // countHeap returns the number of records in the heap profile.
 func countHeap() int {
-	n, _ := runtime.MemProfile(nil, false)
+	n, _ := runtime.MemProfile(nil, true)
 	return n
 }
 
-// writeHeapProfile writes the current runtime heap profile to w.
+// writeHeap writes the current runtime heap profile to w.
 func writeHeap(w io.Writer, debug int) error {
-	// Find out how many records there are (MemProfile(nil, false)),
+	// Find out how many records there are (MemProfile(nil, true)),
 	// allocate that many records, and get the data.
 	// There's a race—more records might be added between
 	// the two calls—so allocate a few extra records for safety
 	// and also try again if we're very unlucky.
 	// The loop should only execute one iteration in the common case.
 	var p []runtime.MemProfileRecord
-	n, ok := runtime.MemProfile(nil, false)
+	n, ok := runtime.MemProfile(nil, true)
 	for {
 		// Allocate room for a slightly bigger profile,
 		// in case a few more entries have been added
 		// since the call to MemProfile.
 		p = make([]runtime.MemProfileRecord, n+50)
-		n, ok = runtime.MemProfile(p, false)
+		n, ok = runtime.MemProfile(p, true)
 		if ok {
 			p = p[0:n]
 			break
@@ -431,11 +451,14 @@ func writeHeap(w io.Writer, debug int) error {
 		fmt.Fprintf(w, "# Sys = %d\n", s.Sys)
 		fmt.Fprintf(w, "# Lookups = %d\n", s.Lookups)
 		fmt.Fprintf(w, "# Mallocs = %d\n", s.Mallocs)
+		fmt.Fprintf(w, "# Frees = %d\n", s.Frees)
 
 		fmt.Fprintf(w, "# HeapAlloc = %d\n", s.HeapAlloc)
 		fmt.Fprintf(w, "# HeapSys = %d\n", s.HeapSys)
 		fmt.Fprintf(w, "# HeapIdle = %d\n", s.HeapIdle)
 		fmt.Fprintf(w, "# HeapInuse = %d\n", s.HeapInuse)
+		fmt.Fprintf(w, "# HeapReleased = %d\n", s.HeapReleased)
+		fmt.Fprintf(w, "# HeapObjects = %d\n", s.HeapObjects)
 
 		fmt.Fprintf(w, "# Stack = %d / %d\n", s.StackInuse, s.StackSys)
 		fmt.Fprintf(w, "# MSpan = %d / %d\n", s.MSpanInuse, s.MSpanSys)
@@ -597,3 +620,60 @@ func StopCPUProfile() {
 	runtime.SetCPUProfileRate(0)
 	<-cpu.done
 }
+
+type byCycles []runtime.BlockProfileRecord
+
+func (x byCycles) Len() int           { return len(x) }
+func (x byCycles) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byCycles) Less(i, j int) bool { return x[i].Cycles > x[j].Cycles }
+
+// countBlock returns the number of records in the blocking profile.
+func countBlock() int {
+	n, _ := runtime.BlockProfile(nil)
+	return n
+}
+
+// writeBlock writes the current blocking profile to w.
+func writeBlock(w io.Writer, debug int) error {
+	var p []runtime.BlockProfileRecord
+	n, ok := runtime.BlockProfile(nil)
+	for {
+		p = make([]runtime.BlockProfileRecord, n+50)
+		n, ok = runtime.BlockProfile(p)
+		if ok {
+			p = p[:n]
+			break
+		}
+	}
+
+	sort.Sort(byCycles(p))
+
+	b := bufio.NewWriter(w)
+	var tw *tabwriter.Writer
+	w = b
+	if debug > 0 {
+		tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
+		w = tw
+	}
+
+	fmt.Fprintf(w, "--- contention:\n")
+	fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
+	for i := range p {
+		r := &p[i]
+		fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
+		for _, pc := range r.Stack() {
+			fmt.Fprintf(w, " %#x", pc)
+		}
+		fmt.Fprint(w, "\n")
+		if debug > 0 {
+			printStackRecord(w, r.Stack(), false)
+		}
+	}
+
+	if tw != nil {
+		tw.Flush()
+	}
+	return b.Flush()
+}
+
+func runtime_cyclesPerSecond() int64
diff --git a/src/pkg/runtime/pprof/pprof_test.go b/src/pkg/runtime/pprof/pprof_test.go
index 82bb2a2..6d5764f 100644
--- a/src/pkg/runtime/pprof/pprof_test.go
+++ b/src/pkg/runtime/pprof/pprof_test.go
@@ -26,8 +26,7 @@ func TestCPUProfile(t *testing.T) {
 		t.Logf("uname -a: %v", vers)
 		// Lion uses "Darwin Kernel Version 11".
 		if strings.Contains(vers, "Darwin Kernel Version 10") && strings.Contains(vers, "RELEASE_X86_64") {
-			t.Logf("skipping test on known-broken kernel (64-bit Leopard / Snow Leopard)")
-			return
+			t.Skip("skipping test on known-broken kernel (64-bit Leopard / Snow Leopard)")
 		}
 	case "plan9":
 		// unimplemented
@@ -49,19 +48,25 @@ func TestCPUProfile(t *testing.T) {
 
 	// Convert []byte to []uintptr.
 	bytes := prof.Bytes()
+	l := len(bytes) / int(unsafe.Sizeof(uintptr(0)))
 	val := *(*[]uintptr)(unsafe.Pointer(&bytes))
-	val = val[:len(bytes)/int(unsafe.Sizeof(uintptr(0)))]
+	val = val[:l]
 
-	if len(val) < 10 {
+	if l < 13 {
 		t.Fatalf("profile too short: %#x", val)
 	}
-	if val[0] != 0 || val[1] != 3 || val[2] != 0 || val[3] != 1e6/100 || val[4] != 0 {
-		t.Fatalf("unexpected header %#x", val[:5])
+
+	hd, val, tl := val[:5], val[5:l-3], val[l-3:]
+	if hd[0] != 0 || hd[1] != 3 || hd[2] != 0 || hd[3] != 1e6/100 || hd[4] != 0 {
+		t.Fatalf("unexpected header %#x", hd)
+	}
+
+	if tl[0] != 0 || tl[1] != 1 || tl[2] != 0 {
+		t.Fatalf("malformed end-of-data marker %#x", tl)
 	}
 
 	// Check that profile is well formed and contains ChecksumIEEE.
 	found := false
-	val = val[5:]
 	for len(val) > 0 {
 		if len(val) < 2 || val[0] < 1 || val[1] < 1 || uintptr(len(val)) < 2+val[1] {
 			t.Fatalf("malformed profile.  leftover: %#x", val)
diff --git a/src/pkg/runtime/print.c b/src/pkg/runtime/print.c
index 6702c3c..5b60159 100644
--- a/src/pkg/runtime/print.c
+++ b/src/pkg/runtime/print.c
@@ -18,10 +18,10 @@ gwrite(void *v, int32 n)
 		runtime·write(2, v, n);
 		return;
 	}
-	
+
 	if(g->writenbuf == 0)
 		return;
-	
+
 	if(n > g->writenbuf)
 		n = g->writenbuf;
 	runtime·memmove(g->writebuf, v, n);
@@ -84,40 +84,41 @@ vprintf(int8 *s, byte *base)
 		narg = 0;
 		switch(*p) {
 		case 't':
+		case 'c':
 			narg = arg + 1;
 			break;
 		case 'd':	// 32-bit
 		case 'x':
-			arg = runtime·rnd(arg, 4);
+			arg = ROUND(arg, 4);
 			narg = arg + 4;
 			break;
 		case 'D':	// 64-bit
 		case 'U':
 		case 'X':
 		case 'f':
-			arg = runtime·rnd(arg, sizeof(uintptr));
+			arg = ROUND(arg, sizeof(uintptr));
 			narg = arg + 8;
 			break;
 		case 'C':
-			arg = runtime·rnd(arg, sizeof(uintptr));
+			arg = ROUND(arg, sizeof(uintptr));
 			narg = arg + 16;
 			break;
 		case 'p':	// pointer-sized
 		case 's':
-			arg = runtime·rnd(arg, sizeof(uintptr));
+			arg = ROUND(arg, sizeof(uintptr));
 			narg = arg + sizeof(uintptr);
 			break;
 		case 'S':	// pointer-aligned but bigger
-			arg = runtime·rnd(arg, sizeof(uintptr));
+			arg = ROUND(arg, sizeof(uintptr));
 			narg = arg + sizeof(String);
 			break;
 		case 'a':	// pointer-aligned but bigger
-			arg = runtime·rnd(arg, sizeof(uintptr));
+			arg = ROUND(arg, sizeof(uintptr));
 			narg = arg + sizeof(Slice);
 			break;
 		case 'i':	// pointer-aligned but bigger
 		case 'e':
-			arg = runtime·rnd(arg, sizeof(uintptr));
+			arg = ROUND(arg, sizeof(uintptr));
 			narg = arg + sizeof(Eface);
 			break;
 		}
@@ -126,6 +127,9 @@ vprintf(int8 *s, byte *base)
 		case 'a':
 			runtime·printslice(*(Slice*)v);
 			break;
+		case 'c':
+			runtime·printbyte(*(int8*)v);
+			break;
 		case 'd':
 			runtime·printint(*(int32*)v);
 			break;
@@ -203,21 +207,27 @@ runtime·printbool(bool v)
 }
 
 void
+runtime·printbyte(int8 c)
+{
+	gwrite(&c, 1);
+}
+
+void
 runtime·printfloat(float64 v)
 {
 	byte buf[20];
 	int32 e, s, i, n;
 	float64 h;
 
-	if(runtime·isNaN(v)) {
+	if(ISNAN(v)) {
 		gwrite("NaN", 3);
 		return;
 	}
-	if(runtime·isInf(v, 1)) {
+	if(v == runtime·posinf) {
 		gwrite("+Inf", 4);
 		return;
 	}
-	if(runtime·isInf(v, -1)) {
+	if(v == runtime·neginf) {
 		gwrite("-Inf", 4);
 		return;
 	}
@@ -343,7 +353,7 @@ runtime·printstring(String v)
 	extern uint32 runtime·maxstring;
 
 	if(v.len > runtime·maxstring) {
-		gwrite("[invalid string]", 16);
+		gwrite("[string too long]", 17);
 		return;
 	}
 	if(v.len > 0)
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 04a9926..4ce0a71 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -4,169 +4,112 @@
 
 #include "runtime.h"
 #include "arch_GOARCH.h"
-#include "defs_GOOS_GOARCH.h"
 #include "malloc.h"
-#include "os_GOOS.h"
 #include "stack.h"
+#include "race.h"
+#include "type.h"
 
-bool	runtime·iscgo;
-
-static void unwindstack(G*, byte*);
-static void schedule(G*);
-
-typedef struct Sched Sched;
-
-M	runtime·m0;
-G	runtime·g0;	// idle goroutine for m0
-
-static	int32	debug	= 0;
-
-int32	runtime·gcwaiting;
-
-// Go scheduler
-//
-// The go scheduler's job is to match ready-to-run goroutines (`g's)
-// with waiting-for-work schedulers (`m's).  If there are ready g's
-// and no waiting m's, ready() will start a new m running in a new
-// OS thread, so that all ready g's can run simultaneously, up to a limit.
-// For now, m's never go away.
-//
-// By default, Go keeps only one kernel thread (m) running user code
-// at a single time; other threads may be blocked in the operating system.
-// Setting the environment variable $GOMAXPROCS or calling
-// runtime.GOMAXPROCS() will change the number of user threads
-// allowed to execute simultaneously.  $GOMAXPROCS is thus an
-// approximation of the maximum number of cores to use.
+// Goroutine scheduler
+// The scheduler's job is to distribute ready-to-run goroutines over worker threads.
 //
-// Even a program that can run without deadlock in a single process
-// might use more m's if given the chance.  For example, the prime
-// sieve will use as many m's as there are primes (up to runtime·sched.mmax),
-// allowing different stages of the pipeline to execute in parallel.
-// We could revisit this choice, only kicking off new m's for blocking
-// system calls, but that would limit the amount of parallel computation
-// that go would try to do.
+// The main concepts are:
+// G - goroutine.
+// M - worker thread, or machine.
+// P - processor, a resource that is required to execute Go code.
+//     M must have an associated P to execute Go code, however it can be
+//     blocked or in a syscall w/o an associated P.
 //
-// In general, one could imagine all sorts of refinements to the
-// scheduler, but the goal now is just to get something working on
-// Linux and OS X.
+// Design doc at http://golang.org/s/go11sched.
 
+typedef struct Sched Sched;
 struct Sched {
 	Lock;
 
-	G *gfree;	// available g's (status == Gdead)
-	int32 goidgen;
-
-	G *ghead;	// g's waiting to run
-	G *gtail;
-	int32 gwait;	// number of g's waiting to run
-	int32 gcount;	// number of g's that are alive
-	int32 grunning;	// number of g's running on cpu or in syscall
+	uint64	goidgen;
 
-	M *mhead;	// m's waiting for work
-	int32 mwait;	// number of m's waiting for work
-	int32 mcount;	// number of m's that have been created
+	M*	midle;	 // idle m's waiting for work
+	int32	nmidle;	 // number of idle m's waiting for work
+	int32	mlocked; // number of locked m's waiting for work
+	int32	mcount;	 // number of m's that have been created
 
-	volatile uint32 atomic;	// atomic scheduling word (see below)
+	P*	pidle;  // idle P's
+	uint32	npidle;
+	uint32	nmspinning;
 
-	int32 profilehz;	// cpu profiling rate
+	// Global runnable queue.
+	G*	runqhead;
+	G*	runqtail;
+	int32	runqsize;
 
-	bool init;  // running initialization
-	bool lockmain;  // init called runtime.LockOSThread
+	// Global cache of dead G's.
+	Lock	gflock;
+	G*	gfree;
 
-	Note	stopped;	// one g can set waitstop and wait here for m's to stop
-};
+	int32	stopwait;
+	Note	stopnote;
+	uint32	sysmonwait;
+	Note	sysmonnote;
 
-// The atomic word in sched is an atomic uint32 that
-// holds these fields.
-//
-//	[15 bits] mcpu		number of m's executing on cpu
-//	[15 bits] mcpumax	max number of m's allowed on cpu
-//	[1 bit] waitstop	some g is waiting on stopped
-//	[1 bit] gwaiting	gwait != 0
-//
-// These fields are the information needed by entersyscall
-// and exitsyscall to decide whether to coordinate with the
-// scheduler.  Packing them into a single machine word lets
-// them use a fast path with a single atomic read/write and
-// no lock/unlock.  This greatly reduces contention in
-// syscall- or cgo-heavy multithreaded programs.
-//
-// Except for entersyscall and exitsyscall, the manipulations
-// to these fields only happen while holding the schedlock,
-// so the routines holding schedlock only need to worry about
-// what entersyscall and exitsyscall do, not the other routines
-// (which also use the schedlock).
-//
-// In particular, entersyscall and exitsyscall only read mcpumax,
-// waitstop, and gwaiting.  They never write them.  Thus, writes to those
-// fields can be done (holding schedlock) without fear of write conflicts.
-// There may still be logic conflicts: for example, the set of waitstop must
-// be conditioned on mcpu >= mcpumax or else the wait may be a
-// spurious sleep.  The Promela model in proc.p verifies these accesses.
-enum {
-	mcpuWidth = 15,
-	mcpuMask = (1<<mcpuWidth) - 1,
-	mcpuShift = 0,
-	mcpumaxShift = mcpuShift + mcpuWidth,
-	waitstopShift = mcpumaxShift + mcpuWidth,
-	gwaitingShift = waitstopShift+1,
-
-	// The max value of GOMAXPROCS is constrained
-	// by the max value we can store in the bit fields
-	// of the atomic word.  Reserve a few high values
-	// so that we can detect accidental decrement
-	// beyond zero.
-	maxgomaxprocs = mcpuMask - 10,
+	int32	profilehz;	// cpu profiling rate
 };
 
-#define atomic_mcpu(v)		(((v)>>mcpuShift)&mcpuMask)
-#define atomic_mcpumax(v)	(((v)>>mcpumaxShift)&mcpuMask)
-#define atomic_waitstop(v)	(((v)>>waitstopShift)&1)
-#define atomic_gwaiting(v)	(((v)>>gwaitingShift)&1)
-
-Sched runtime·sched;
-int32 runtime·gomaxprocs;
-bool runtime·singleproc;
-
-static bool canaddmcpu(void);
-
-// An m that is waiting for notewakeup(&m->havenextg).  This may
-// only be accessed while the scheduler lock is held.  This is used to
-// minimize the number of times we call notewakeup while the scheduler
-// lock is held, since the m will normally move quickly to lock the
-// scheduler itself, producing lock contention.
-static M* mwakeup;
-
-// Scheduling helpers.  Sched must be locked.
-static void gput(G*);	// put/get on ghead/gtail
-static G* gget(void);
-static void mput(M*);	// put/get on mhead
-static M* mget(G*);
-static void gfput(G*);	// put/get on gfree
-static G* gfget(void);
-static void matchmg(void);	// match m's to g's
-static void readylocked(G*);	// ready, but sched is locked
-static void mnextg(M*, G*);
-static void mcommoninit(M*);
-
-void
-setmcpumax(uint32 n)
-{
-	uint32 v, w;
-
-	for(;;) {
-		v = runtime·sched.atomic;
-		w = v;
-		w &= ~(mcpuMask<<mcpumaxShift);
-		w |= n<<mcpumaxShift;
-		if(runtime·cas(&runtime·sched.atomic, v, w))
-			break;
-	}
-}
+// The max value of GOMAXPROCS.
+// There are no fundamental restrictions on the value.
+enum { MaxGomaxprocs = 1<<8 };
 
+Sched	runtime·sched;
+int32	runtime·gomaxprocs;
+bool	runtime·singleproc;
+bool	runtime·iscgo;
+uint32	runtime·gcwaiting;
+M	runtime·m0;
+G	runtime·g0;	 // idle goroutine for m0
+G*	runtime·allg;
+G*	runtime·lastg;
+M*	runtime·allm;
+M*	runtime·extram;
+int8*	runtime·goos;
+int32	runtime·ncpu;
+static int32	newprocs;
 // Keep trace of scavenger's goroutine for deadlock detection.
 static G *scvg;
 
+void runtime·mstart(void);
+static void runqput(P*, G*);
+static G* runqget(P*);
+static void runqgrow(P*);
+static G* runqsteal(P*, P*);
+static void mput(M*);
+static M* mget(void);
+static void mcommoninit(M*);
+static void schedule(void);
+static void procresize(int32);
+static void acquirep(P*);
+static P* releasep(void);
+static void newm(void(*)(void), P*);
+static void goidle(void);
+static void stopm(void);
+static void startm(P*, bool);
+static void handoffp(P*);
+static void wakep(void);
+static void stoplockedm(void);
+static void startlockedm(G*);
+static void sysmon(void);
+static uint32 retake(uint32*);
+static void inclocked(int32);
+static void checkdead(void);
+static void exitsyscall0(G*);
+static void park0(G*);
+static void gosched0(G*);
+static void goexit0(G*);
+static void gfput(P*, G*);
+static G* gfget(P*);
+static void gfpurge(P*);
+static void globrunqput(G*);
+static G* globrunqget(P*);
+static P* pidleget(void);
+static void pidleput(P*);
+
 // The bootstrap sequence is:
 //
 //	call osinit
@@ -178,10 +121,11 @@ static G *scvg;
 void
 runtime·schedinit(void)
 {
-	int32 n;
+	int32 n, procs;
 	byte *p;
 
 	m->nomemprof++;
+	runtime·mprofinit();
 	runtime·mallocinit();
 	mcommoninit(m);
 
@@ -193,93 +137,70 @@ runtime·schedinit(void)
 	// so that we don't need to call malloc when we crash.
 	// runtime·findfunc(0);
 
-	runtime·gomaxprocs = 1;
+	procs = 1;
 	p = runtime·getenv("GOMAXPROCS");
-	if(p != nil && (n = runtime·atoi(p)) != 0) {
-		if(n > maxgomaxprocs)
-			n = maxgomaxprocs;
-		runtime·gomaxprocs = n;
+	if(p != nil && (n = runtime·atoi(p)) > 0) {
+		if(n > MaxGomaxprocs)
+			n = MaxGomaxprocs;
+		procs = n;
 	}
-	// wait for the main goroutine to start before taking
-	// GOMAXPROCS into account.
-	setmcpumax(1);
-	runtime·singleproc = runtime·gomaxprocs == 1;
-
-	canaddmcpu();	// mcpu++ to account for bootstrap m
-	m->helpgc = 1;	// flag to tell schedule() to mcpu--
-	runtime·sched.grunning++;
+	runtime·allp = runtime·malloc((MaxGomaxprocs+1)*sizeof(runtime·allp[0]));
+	procresize(procs);
 
 	mstats.enablegc = 1;
 	m->nomemprof--;
+
+	if(raceenabled)
+		g->racectx = runtime·raceinit();
 }
 
 extern void main·init(void);
 extern void main·main(void);
 
+static FuncVal scavenger = {runtime·MHeap_Scavenger};
+
 // The main goroutine.
 void
 runtime·main(void)
 {
+	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();
-	// From now on, newgoroutines may use non-main threads.
-	setmcpumax(runtime·gomaxprocs);
-	runtime·sched.init = true;
-	scvg = runtime·newproc1((byte*)runtime·MHeap_Scavenger, nil, 0, 0, runtime·main);
+	runtime·lockOSThread();
+	if(m != &runtime·m0)
+		runtime·throw("runtime·main not on m0");
+	scvg = runtime·newproc1(&scavenger, nil, 0, 0, runtime·main);
+	scvg->issystem = true;
 	main·init();
-	runtime·sched.init = false;
-	if(!runtime·sched.lockmain)
-		runtime·UnlockOSThread();
-
-	// The deadlock detection has false negatives.
-	// Let scvg start up, to eliminate the false negative
-	// for the trivial program func main() { select{} }.
-	runtime·gosched();
+	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;
 }
 
-// Lock the scheduler.
-static void
-schedlock(void)
-{
-	runtime·lock(&runtime·sched);
-}
-
-// Unlock the scheduler.
-static void
-schedunlock(void)
-{
-	M *m;
-
-	m = mwakeup;
-	mwakeup = nil;
-	runtime·unlock(&runtime·sched);
-	if(m != nil)
-		runtime·notewakeup(&m->havenextg);
-}
-
-void
-runtime·goexit(void)
-{
-	g->status = Gmoribund;
-	runtime·gosched();
-}
-
 void
-runtime·goroutineheader(G *g)
+runtime·goroutineheader(G *gp)
 {
 	int8 *status;
 
-	switch(g->status) {
+	switch(gp->status) {
 	case Gidle:
 		status = "idle";
 		break;
@@ -293,609 +214,748 @@ runtime·goroutineheader(G *g)
 		status = "syscall";
 		break;
 	case Gwaiting:
-		if(g->waitreason)
-			status = g->waitreason;
+		if(gp->waitreason)
+			status = gp->waitreason;
 		else
 			status = "waiting";
 		break;
-	case Gmoribund:
-		status = "moribund";
-		break;
 	default:
 		status = "???";
 		break;
 	}
-	runtime·printf("goroutine %d [%s]:\n", g->goid, status);
+	runtime·printf("goroutine %D [%s]:\n", gp->goid, status);
 }
 
 void
 runtime·tracebackothers(G *me)
 {
-	G *g;
+	G *gp;
+	int32 traceback;
 
-	for(g = runtime·allg; g != nil; g = g->alllink) {
-		if(g == me || g->status == Gdead)
+	traceback = runtime·gotraceback();
+	for(gp = runtime·allg; gp != nil; gp = gp->alllink) {
+		if(gp == me || gp->status == Gdead)
+			continue;
+		if(gp->issystem && traceback < 2)
 			continue;
 		runtime·printf("\n");
-		runtime·goroutineheader(g);
-		runtime·traceback(g->sched.pc, g->sched.sp, 0, g);
+		runtime·goroutineheader(gp);
+		runtime·traceback(gp->sched.pc, (byte*)gp->sched.sp, 0, gp);
 	}
 }
 
-// Mark this g as m's idle goroutine.
-// This functionality might be used in environments where programs
-// are limited to a single thread, to simulate a select-driven
-// network server.  It is not exposed via the standard runtime API.
-void
-runtime·idlegoroutine(void)
-{
-	if(g->idlem != nil)
-		runtime·throw("g is already an idle goroutine");
-	g->idlem = m;
-}
-
 static void
-mcommoninit(M *m)
+mcommoninit(M *mp)
 {
-	m->id = runtime·sched.mcount++;
-	m->fastrand = 0x49f6428aUL + m->id + runtime·cputicks();
-	m->stackalloc = runtime·malloc(sizeof(*m->stackalloc));
-	runtime·FixAlloc_Init(m->stackalloc, FixedStack, runtime·SysAlloc, nil, nil);
+	// 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)
+		runtime·callers(1, mp->createstack, nelem(mp->createstack));
 
-	if(m->mcache == nil)
-		m->mcache = runtime·allocmcache();
+	mp->fastrand = 0x49f6428aUL + mp->id + runtime·cputicks();
 
-	runtime·callers(1, m->createstack, nelem(m->createstack));
+	runtime·lock(&runtime·sched);
+	mp->id = runtime·sched.mcount++;
+
+	runtime·mpreinit(mp);
 
 	// Add to runtime·allm so garbage collector doesn't free m
 	// when it is just in a register or thread-local storage.
-	m->alllink = runtime·allm;
+	mp->alllink = runtime·allm;
 	// runtime·NumCgoCall() iterates over allm w/o schedlock,
 	// so we need to publish it safely.
-	runtime·atomicstorep(&runtime·allm, m);
+	runtime·atomicstorep(&runtime·allm, mp);
+	runtime·unlock(&runtime·sched);
 }
 
-// Try to increment mcpu.  Report whether succeeded.
-static bool
-canaddmcpu(void)
+// Mark gp ready to run.
+void
+runtime·ready(G *gp)
 {
-	uint32 v;
-
-	for(;;) {
-		v = runtime·sched.atomic;
-		if(atomic_mcpu(v) >= atomic_mcpumax(v))
-			return 0;
-		if(runtime·cas(&runtime·sched.atomic, v, v+(1<<mcpuShift)))
-			return 1;
+	// Mark runnable.
+	if(gp->status != Gwaiting) {
+		runtime·printf("goroutine %D has status %d\n", gp->goid, gp->status);
+		runtime·throw("bad g->status in ready");
 	}
+	gp->status = Grunnable;
+	runqput(m->p, gp);
+	if(runtime·atomicload(&runtime·sched.npidle) != 0 && runtime·atomicload(&runtime·sched.nmspinning) == 0)  // TODO: fast atomic
+		wakep();
 }
 
-// Put on `g' queue.  Sched must be locked.
-static void
-gput(G *g)
+int32
+runtime·gcprocs(void)
 {
-	M *m;
-
-	// If g is wired, hand it off directly.
-	if((m = g->lockedm) != nil && canaddmcpu()) {
-		mnextg(m, g);
-		return;
-	}
+	int32 n;
 
-	// If g is the idle goroutine for an m, hand it off.
-	if(g->idlem != nil) {
-		if(g->idlem->idleg != nil) {
-			runtime·printf("m%d idle out of sync: g%d g%d\n",
-				g->idlem->id,
-				g->idlem->idleg->goid, g->goid);
-			runtime·throw("runtime: double idle");
-		}
-		g->idlem->idleg = g;
-		return;
-	}
+	// Figure out how many CPUs to use during GC.
+	// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
+	runtime·lock(&runtime·sched);
+	n = runtime·gomaxprocs;
+	if(n > runtime·ncpu)
+		n = runtime·ncpu;
+	if(n > MaxGcproc)
+		n = MaxGcproc;
+	if(n > runtime·sched.nmidle+1) // one M is currently running
+		n = runtime·sched.nmidle+1;
+	runtime·unlock(&runtime·sched);
+	return n;
+}
 
-	g->schedlink = nil;
-	if(runtime·sched.ghead == nil)
-		runtime·sched.ghead = g;
-	else
-		runtime·sched.gtail->schedlink = g;
-	runtime·sched.gtail = g;
+static bool
+needaddgcproc(void)
+{
+	int32 n;
 
-	// increment gwait.
-	// if it transitions to nonzero, set atomic gwaiting bit.
-	if(runtime·sched.gwait++ == 0)
-		runtime·xadd(&runtime·sched.atomic, 1<<gwaitingShift);
+	runtime·lock(&runtime·sched);
+	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);
+	return n > 0;
 }
 
-// Report whether gget would return something.
-static bool
-haveg(void)
+void
+runtime·helpgc(int32 nproc)
 {
-	return runtime·sched.ghead != nil || m->idleg != nil;
+	M *mp;
+	int32 n, pos;
+
+	runtime·lock(&runtime·sched);
+	pos = 0;
+	for(n = 1; n < nproc; n++) {  // one M is currently running
+		if(runtime·allp[pos]->mcache == m->mcache)
+			pos++;
+		mp = mget();
+		if(mp == nil)
+			runtime·throw("runtime·gcprocs inconsistency");
+		mp->helpgc = 1;
+		mp->mcache = runtime·allp[pos]->mcache;
+		pos++;
+		runtime·notewakeup(&mp->park);
+	}
+	runtime·unlock(&runtime·sched);
 }
 
-// Get from `g' queue.  Sched must be locked.
-static G*
-gget(void)
+void
+runtime·stoptheworld(void)
 {
-	G *g;
+	int32 i;
+	uint32 s;
+	P *p;
+	bool wait;
 
-	g = runtime·sched.ghead;
-	if(g){
-		runtime·sched.ghead = g->schedlink;
-		if(runtime·sched.ghead == nil)
-			runtime·sched.gtail = nil;
-		// decrement gwait.
-		// if it transitions to zero, clear atomic gwaiting bit.
-		if(--runtime·sched.gwait == 0)
-			runtime·xadd(&runtime·sched.atomic, -1<<gwaitingShift);
-	} else if(m->idleg != nil) {
-		g = m->idleg;
-		m->idleg = nil;
+	runtime·lock(&runtime·sched);
+	runtime·sched.stopwait = runtime·gomaxprocs;
+	runtime·atomicstore((uint32*)&runtime·gcwaiting, 1);
+	// stop current P
+	m->p->status = Pgcstop;
+	runtime·sched.stopwait--;
+	// try to retake all P's in Psyscall status
+	for(i = 0; i < runtime·gomaxprocs; i++) {
+		p = runtime·allp[i];
+		s = p->status;
+		if(s == Psyscall && runtime·cas(&p->status, s, Pgcstop))
+			runtime·sched.stopwait--;
+	}
+	// stop idle P's
+	while(p = pidleget()) {
+		p->status = Pgcstop;
+		runtime·sched.stopwait--;
+	}
+	wait = runtime·sched.stopwait > 0;
+	runtime·unlock(&runtime·sched);
+
+	// wait for remaining P's to stop voluntary
+	if(wait) {
+		runtime·notesleep(&runtime·sched.stopnote);
+		runtime·noteclear(&runtime·sched.stopnote);
+	}
+	if(runtime·sched.stopwait)
+		runtime·throw("stoptheworld: not stopped");
+	for(i = 0; i < runtime·gomaxprocs; i++) {
+		p = runtime·allp[i];
+		if(p->status != Pgcstop)
+			runtime·throw("stoptheworld: not stopped");
 	}
-	return g;
 }
 
-// Put on `m' list.  Sched must be locked.
 static void
-mput(M *m)
+mhelpgc(void)
 {
-	m->schedlink = runtime·sched.mhead;
-	runtime·sched.mhead = m;
-	runtime·sched.mwait++;
+	m->helpgc = 1;
 }
 
-// Get an `m' to run `g'.  Sched must be locked.
-static M*
-mget(G *g)
+void
+runtime·starttheworld(void)
 {
-	M *m;
+	P *p;
+	M *mp;
+	bool add;
+
+	add = needaddgcproc();
+	runtime·lock(&runtime·sched);
+	if(newprocs) {
+		procresize(newprocs);
+		newprocs = 0;
+	} else
+		procresize(runtime·gomaxprocs);
+	runtime·gcwaiting = 0;
 
-	// if g has its own m, use it.
-	if(g && (m = g->lockedm) != nil)
-		return m;
+	while(p = pidleget()) {
+		// procresize() puts p's with work at the beginning of the list.
+		// Once we reach a p without a run queue, the rest don't have one either.
+		if(p->runqhead == p->runqtail) {
+			pidleput(p);
+			break;
+		}
+		mp = mget();
+		if(mp == nil) {
+			pidleput(p);
+			break;
+		}
+		if(mp->nextp)
+			runtime·throw("starttheworld: inconsistent mp->nextp");
+		mp->nextp = p;
+		runtime·notewakeup(&mp->park);
+	}
+	if(runtime·sched.sysmonwait) {
+		runtime·sched.sysmonwait = false;
+		runtime·notewakeup(&runtime·sched.sysmonnote);
+	}
+	runtime·unlock(&runtime·sched);
 
-	// otherwise use general m pool.
-	if((m = runtime·sched.mhead) != nil){
-		runtime·sched.mhead = m->schedlink;
-		runtime·sched.mwait--;
+	if(add) {
+		// If GC could have used another helper proc, start one now,
+		// in the hope that it will be available next time.
+		// It would have been even better to start it before the collection,
+		// but doing so requires allocating memory, so it's tricky to
+		// coordinate.  This lazy approach works out in practice:
+		// we don't mind if the first couple gc rounds don't have quite
+		// the maximum number of procs.
+		newm(mhelpgc, nil);
 	}
-	return m;
 }
 
-// Mark g ready to run.
+// Called to start an M.
 void
-runtime·ready(G *g)
+runtime·mstart(void)
 {
-	schedlock();
-	readylocked(g);
-	schedunlock();
-}
+	// It is used by windows-386 only. Unfortunately, seh needs
+	// to be located on os stack, and mstart runs on os stack
+	// for both m0 and m.
+	SEH seh;
 
-// Mark g ready to run.  Sched is already locked.
-// G might be running already and about to stop.
-// The sched lock protects g->status from changing underfoot.
-static void
-readylocked(G *g)
-{
-	if(g->m){
-		// Running on another machine.
-		// Ready it when it stops.
-		g->readyonstop = 1;
-		return;
+	if(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 = (void*)-1;  // make sure it is never used
+	m->seh = &seh;
+	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) {
+		runtime·initsig();
+		if(runtime·iscgo)
+			runtime·newextram();
 	}
+	
+	if(m->mstartfn)
+		m->mstartfn();
 
-	// Mark runnable.
-	if(g->status == Grunnable || g->status == Grunning) {
-		runtime·printf("goroutine %d has status %d\n", g->goid, g->status);
-		runtime·throw("bad g->status in ready");
+	if(m->helpgc) {
+		m->helpgc = false;
+		stopm();
+	} else if(m != &runtime·m0) {
+		acquirep(m->nextp);
+		m->nextp = nil;
 	}
-	g->status = Grunnable;
+	schedule();
 
-	gput(g);
-	matchmg();
+	// TODO(brainman): This point is never reached, because scheduler
+	// does not release os threads at the moment. But once this path
+	// is enabled, we must remove our seh here.
 }
 
-static void
-nop(void)
-{
-}
+// When running with cgo, we call _cgo_thread_start
+// to start threads for us so that we can play nicely with
+// foreign code.
+void (*_cgo_thread_start)(void*);
 
-// Same as readylocked but a different symbol so that
-// debuggers can set a breakpoint here and catch all
-// new goroutines.
-static void
-newprocreadylocked(G *g)
+typedef struct CgoThreadStart CgoThreadStart;
+struct CgoThreadStart
 {
-	nop();	// avoid inlining in 6l
-	readylocked(g);
-}
+	M *m;
+	G *g;
+	void (*fn)(void);
+};
 
-// Pass g to m for running.
-// Caller has already incremented mcpu.
-static void
-mnextg(M *m, G *g)
+// Allocate a new m unassociated with any thread.
+// Can use p for allocation context if needed.
+M*
+runtime·allocm(P *p)
 {
-	runtime·sched.grunning++;
-	m->nextg = g;
-	if(m->waitnextg) {
-		m->waitnextg = 0;
-		if(mwakeup != nil)
-			runtime·notewakeup(&mwakeup->havenextg);
-		mwakeup = m;
+	M *mp;
+	static Type *mtype;  // The Go type M
+
+	m->locks++;  // disable GC because it can be called from sysmon
+	if(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;
 	}
-}
 
-// Get the next goroutine that m should run.
-// Sched must be locked on entry, is unlocked on exit.
-// Makes sure that at most $GOMAXPROCS g's are
-// running on cpus (not in system calls) at any given time.
-static G*
-nextgandunlock(void)
-{
-	G *gp;
-	uint32 v;
+	mp = runtime·cnew(mtype);
+	mcommoninit(mp);
 
-top:
-	if(atomic_mcpu(runtime·sched.atomic) >= maxgomaxprocs)
-		runtime·throw("negative mcpu");
-
-	// If there is a g waiting as m->nextg, the mcpu++
-	// happened before it was passed to mnextg.
-	if(m->nextg != nil) {
-		gp = m->nextg;
-		m->nextg = nil;
-		schedunlock();
-		return gp;
-	}
+	// In case of cgo, pthread_create will make us a stack.
+	// Windows will layout sched stack on OS stack.
+	if(runtime·iscgo || Windows)
+		mp->g0 = runtime·malg(-1);
+	else
+		mp->g0 = runtime·malg(8192);
 
-	if(m->lockedg != nil) {
-		// We can only run one g, and it's not available.
-		// Make sure some other cpu is running to handle
-		// the ordinary run queue.
-		if(runtime·sched.gwait != 0) {
-			matchmg();
-			// m->lockedg might have been on the queue.
-			if(m->nextg != nil) {
-				gp = m->nextg;
-				m->nextg = nil;
-				schedunlock();
-				return gp;
-			}
-		}
-	} else {
-		// Look for work on global queue.
-		while(haveg() && canaddmcpu()) {
-			gp = gget();
-			if(gp == nil)
-				runtime·throw("gget inconsistency");
-
-			if(gp->lockedm) {
-				mnextg(gp->lockedm, gp);
-				continue;
-			}
-			runtime·sched.grunning++;
-			schedunlock();
-			return gp;
-		}
+	if(p == m->p)
+		releasep();
+	m->locks--;
 
-		// The while loop ended either because the g queue is empty
-		// or because we have maxed out our m procs running go
-		// code (mcpu >= mcpumax).  We need to check that
-		// concurrent actions by entersyscall/exitsyscall cannot
-		// invalidate the decision to end the loop.
-		//
-		// We hold the sched lock, so no one else is manipulating the
-		// g queue or changing mcpumax.  Entersyscall can decrement
-		// mcpu, but if does so when there is something on the g queue,
-		// the gwait bit will be set, so entersyscall will take the slow path
-		// and use the sched lock.  So it cannot invalidate our decision.
-		//
-		// Wait on global m queue.
-		mput(m);
-	}
-
-	// Look for deadlock situation.
-	// There is a race with the scavenger that causes false negatives:
-	// if the scavenger is just starting, then we have
-	//	scvg != nil && grunning == 0 && gwait == 0
-	// and we do not detect a deadlock.  It is possible that we should
-	// add that case to the if statement here, but it is too close to Go 1
-	// to make such a subtle change.  Instead, we work around the
-	// false negative in trivial programs by calling runtime.gosched
-	// from the main goroutine just before main.main.
-	// See runtime·main above.
-	//
-	// On a related note, it is also possible that the scvg == nil case is
-	// wrong and should include gwait, but that does not happen in
-	// standard Go programs, which all start the scavenger.
-	//
-	if((scvg == nil && runtime·sched.grunning == 0) ||
-	   (scvg != nil && runtime·sched.grunning == 1 && runtime·sched.gwait == 0 &&
-	    (scvg->status == Grunning || scvg->status == Gsyscall))) {
-		runtime·throw("all goroutines are asleep - deadlock!");
-	}
-
-	m->nextg = nil;
-	m->waitnextg = 1;
-	runtime·noteclear(&m->havenextg);
-
-	// Stoptheworld is waiting for all but its cpu to go to stop.
-	// Entersyscall might have decremented mcpu too, but if so
-	// it will see the waitstop and take the slow path.
-	// Exitsyscall never increments mcpu beyond mcpumax.
-	v = runtime·atomicload(&runtime·sched.atomic);
-	if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) {
-		// set waitstop = 0 (known to be 1)
-		runtime·xadd(&runtime·sched.atomic, -1<<waitstopShift);
-		runtime·notewakeup(&runtime·sched.stopped);
-	}
-	schedunlock();
-
-	runtime·notesleep(&m->havenextg);
-	if(m->helpgc) {
-		runtime·gchelper();
-		m->helpgc = 0;
-		runtime·lock(&runtime·sched);
-		goto top;
-	}
-	if((gp = m->nextg) == nil)
-		runtime·throw("bad m->nextg in nextgoroutine");
-	m->nextg = nil;
-	return gp;
+	return mp;
 }
 
-int32
-runtime·helpgc(bool *extra)
+static M* lockextra(bool nilokay);
+static void unlockextra(M*);
+
+// needm is called when a cgo callback happens on a
+// thread without an m (a thread not created by Go).
+// In this case, needm is expected to find an m to use
+// and return with m, g initialized correctly.
+// Since m and g are not set now (likely nil, but see below)
+// needm is limited in what routines it can call. In particular
+// it can only call nosplit functions (textflag 7) and cannot
+// do any scheduling that requires an m.
+//
+// In order to avoid needing heavy lifting here, we adopt
+// the following strategy: there is a stack of available m's
+// that can be stolen. Using compare-and-swap
+// to pop from the stack has ABA races, so we simulate
+// a lock by doing an exchange (via casp) to steal the stack
+// head and replace the top pointer with MLOCKED (1).
+// This serves as a simple spin lock that we can use even
+// without an m. The thread that locks the stack in this way
+// unlocks the stack by storing a valid stack head pointer.
+//
+// In order to make sure that there is always an m structure
+// available to be stolen, we maintain the invariant that there
+// is always one more than needed. At the beginning of the
+// program (if cgo is in use) the list is seeded with a single m.
+// If needm finds that it has taken the last m off the list, its job
+// is - once it has installed its own m so that it can do things like
+// allocate memory - to create a spare m and put it on the list.
+//
+// Each of these extra m's also has a g0 and a curg that are
+// pressed into service as the scheduling stack and current
+// goroutine for the duration of the cgo callback.
+//
+// When the callback is done with the m, it calls dropm to
+// put the m back on the list.
+#pragma textflag 7
+void
+runtime·needm(byte x)
 {
 	M *mp;
-	int32 n, max;
 
-	// Figure out how many CPUs to use.
-	// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
-	max = runtime·gomaxprocs;
-	if(max > runtime·ncpu)
-		max = runtime·ncpu;
-	if(max > MaxGcproc)
-		max = MaxGcproc;
+	// Lock extra list, take head, unlock popped list.
+	// nilokay=false is safe here because of the invariant above,
+	// that the extra list always contains or will soon contain
+	// at least one m.
+	mp = lockextra(false);
+
+	// Set needextram when we've just emptied the list,
+	// so that the eventual call into cgocallbackg will
+	// allocate a new m for the extra list. We delay the
+	// allocation until then so that it can be done
+	// after exitsyscall makes sure it is okay to be
+	// running at all (that is, there's no garbage collection
+	// running right now).
+	mp->needextram = mp->schedlink == nil;
+	unlockextra(mp->schedlink);
+
+	// Install m and 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);
+
+	// On windows/386, we need to put an SEH frame (two words)
+	// somewhere on the current stack. We are called
+	// from needm, and we know there is some available
+	// space one word into the argument frame. Use that.
+	m->seh = (SEH*)((uintptr*)&x + 1);
+
+	// Initialize this thread to use the m.
+	runtime·asminit();
+	runtime·minit();
+}
 
-	// We're going to use one CPU no matter what.
-	// Figure out the max number of additional CPUs.
-	max--;
+// newextram allocates an m and puts it on the extra list.
+// It is called with a working local m, so that it can do things
+// like call schedlock and allocate.
+void
+runtime·newextram(void)
+{
+	M *mp, *mnext;
+	G *gp;
 
+	// Create extra goroutine locked to extra m.
+	// The goroutine is the context in which the cgo callback will run.
+	// The sched.pc will never be returned to, but setting it to
+	// runtime.goexit makes clear to the traceback routines where
+	// the goroutine stack ends.
+	mp = runtime·allocm(nil);
+	gp = runtime·malg(4096);
+	gp->sched.pc = (void*)runtime·goexit;
+	gp->sched.sp = gp->stackbase;
+	gp->sched.g = gp;
+	gp->status = Gsyscall;
+	mp->curg = gp;
+	mp->locked = LockInternal;
+	mp->lockedg = gp;
+	gp->lockedm = mp;
+	// put on allg for garbage collector
 	runtime·lock(&runtime·sched);
-	n = 0;
-	while(n < max && (mp = mget(nil)) != nil) {
-		n++;
-		mp->helpgc = 1;
-		mp->waitnextg = 0;
-		runtime·notewakeup(&mp->havenextg);
-	}
+	if(runtime·lastg == nil)
+		runtime·allg = gp;
+	else
+		runtime·lastg->alllink = gp;
+	runtime·lastg = gp;
 	runtime·unlock(&runtime·sched);
-	if(extra)
-		*extra = n != max;
-	return n;
+	gp->goid = runtime·xadd64(&runtime·sched.goidgen, 1);
+	if(raceenabled)
+		gp->racectx = runtime·racegostart(runtime·newextram);
+
+	// Add m to the extra list.
+	mnext = lockextra(true);
+	mp->schedlink = mnext;
+	unlockextra(mp);
 }
 
+// dropm is called when a cgo callback has called needm but is now
+// done with the callback and returning back into the non-Go thread.
+// It puts the current m back onto the extra list.
+//
+// The main expense here is the call to signalstack to release the
+// m's signal stack, and then the call to needm on the next callback
+// from this thread. It is tempting to try to save the m for next time,
+// which would eliminate both these costs, but there might not be
+// a next time: the current thread (which Go does not control) might exit.
+// If we saved the m for that thread, there would be an m leak each time
+// such a thread exited. Instead, we acquire and release an m on each
+// call. These should typically not be scheduling operations, just a few
+// atomics, so the cost should be small.
+//
+// TODO(rsc): An alternative would be to allocate a dummy pthread per-thread
+// variable using pthread_key_create. Unlike the pthread keys we already use
+// on OS X, this dummy key would never be read by Go code. It would exist
+// only so that we could register at thread-exit-time destructor.
+// That destructor would put the m back onto the extra list.
+// This is purely a performance optimization. The current version,
+// in which dropm happens on each cgo call, is still correct too.
+// We may have to keep the current version on systems with cgo
+// but without pthreads, like Windows.
 void
-runtime·stoptheworld(void)
+runtime·dropm(void)
 {
-	uint32 v;
+	M *mp, *mnext;
 
-	schedlock();
-	runtime·gcwaiting = 1;
+	// Undo whatever initialization minit did during needm.
+	runtime·unminit();
 
-	setmcpumax(1);
+	// 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);
 
-	// while mcpu > 1
-	for(;;) {
-		v = runtime·sched.atomic;
-		if(atomic_mcpu(v) <= 1)
-			break;
+	mnext = lockextra(true);
+	mp->schedlink = mnext;
+	unlockextra(mp);
+}
 
-		// It would be unsafe for multiple threads to be using
-		// the stopped note at once, but there is only
-		// ever one thread doing garbage collection.
-		runtime·noteclear(&runtime·sched.stopped);
-		if(atomic_waitstop(v))
-			runtime·throw("invalid waitstop");
+#define MLOCKED ((M*)1)
 
-		// atomic { waitstop = 1 }, predicated on mcpu <= 1 check above
-		// still being true.
-		if(!runtime·cas(&runtime·sched.atomic, v, v+(1<<waitstopShift)))
-			continue;
+// lockextra locks the extra list and returns the list head.
+// The caller must unlock the list by storing a new list head
+// to runtime.extram. If nilokay is true, then lockextra will
+// return a nil list head if that's what it finds. If nilokay is false,
+// lockextra will keep waiting until the list head is no longer nil.
+#pragma textflag 7
+static M*
+lockextra(bool nilokay)
+{
+	M *mp;
+	void (*yield)(void);
 
-		schedunlock();
-		runtime·notesleep(&runtime·sched.stopped);
-		schedlock();
+	for(;;) {
+		mp = runtime·atomicloadp(&runtime·extram);
+		if(mp == MLOCKED) {
+			yield = runtime·osyield;
+			yield();
+			continue;
+		}
+		if(mp == nil && !nilokay) {
+			runtime·usleep(1);
+			continue;
+		}
+		if(!runtime·casp(&runtime·extram, mp, MLOCKED)) {
+			yield = runtime·osyield;
+			yield();
+			continue;
+		}
+		break;
 	}
-	runtime·singleproc = runtime·gomaxprocs == 1;
-	schedunlock();
+	return mp;
 }
 
-void
-runtime·starttheworld(bool extra)
+#pragma textflag 7
+static void
+unlockextra(M *mp)
 {
-	M *m;
-
-	schedlock();
-	runtime·gcwaiting = 0;
-	setmcpumax(runtime·gomaxprocs);
-	matchmg();
-	if(extra && canaddmcpu()) {
-		// Start a new m that will (we hope) be idle
-		// and so available to help when the next
-		// garbage collection happens.
-		// canaddmcpu above did mcpu++
-		// (necessary, because m will be doing various
-		// initialization work so is definitely running),
-		// but m is not running a specific goroutine,
-		// so set the helpgc flag as a signal to m's
-		// first schedule(nil) to mcpu-- and grunning--.
-		m = runtime·newm();
-		m->helpgc = 1;
-		runtime·sched.grunning++;
-	}
-	schedunlock();
+	runtime·atomicstorep(&runtime·extram, mp);
 }
 
-// Called to start an M.
-void
-runtime·mstart(void)
+
+// Create a new m.  It will start off with a call to fn, or else the scheduler.
+static void
+newm(void(*fn)(void), P *p)
 {
-	if(g != m->g0)
-		runtime·throw("bad runtime·mstart");
+	M *mp;
 
-	// 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 = (void*)-1;  // make sure it is never used
-	runtime·asminit();
-	runtime·minit();
+	mp = runtime·allocm(p);
+	mp->nextp = p;
+	mp->mstartfn = fn;
 
-	// Install signal handlers; after minit so that minit can
-	// prepare the thread to be able to handle the signals.
-	if(m == &runtime·m0)
-		runtime·initsig();
+	if(runtime·iscgo) {
+		CgoThreadStart ts;
 
-	schedule(nil);
+		if(_cgo_thread_start == nil)
+			runtime·throw("_cgo_thread_start missing");
+		ts.m = mp;
+		ts.g = mp->g0;
+		ts.fn = runtime·mstart;
+		runtime·asmcgocall(_cgo_thread_start, &ts);
+		return;
+	}
+	runtime·newosproc(mp, (byte*)mp->g0->stackbase);
 }
 
-// When running with cgo, we call libcgo_thread_start
-// to start threads for us so that we can play nicely with
-// foreign code.
-void (*libcgo_thread_start)(void*);
+// Stops execution of the current m until new work is available.
+// Returns with acquired P.
+static void
+stopm(void)
+{
+	if(m->locks)
+		runtime·throw("stopm holding locks");
+	if(m->p)
+		runtime·throw("stopm holding p");
+	if(m->spinning) {
+		m->spinning = false;
+		runtime·xadd(&runtime·sched.nmspinning, -1);
+	}
 
-typedef struct CgoThreadStart CgoThreadStart;
-struct CgoThreadStart
+retry:
+	runtime·lock(&runtime·sched);
+	mput(m);
+	runtime·unlock(&runtime·sched);
+	runtime·notesleep(&m->park);
+	runtime·noteclear(&m->park);
+	if(m->helpgc) {
+		m->helpgc = 0;
+		runtime·gchelper();
+		m->mcache = nil;
+		goto retry;
+	}
+	acquirep(m->nextp);
+	m->nextp = nil;
+}
+
+static void
+mspinning(void)
 {
-	M *m;
-	G *g;
-	void (*fn)(void);
-};
+	m->spinning = true;
+}
 
-// Kick off new m's as needed (up to mcpumax).
-// Sched is locked.
+// Schedules some M to run the p (creates an M if necessary).
+// If p==nil, tries to get an idle P, if no idle P's returns false.
 static void
-matchmg(void)
+startm(P *p, bool spinning)
 {
-	G *gp;
 	M *mp;
+	void (*fn)(void);
 
-	if(m->mallocing || m->gcing)
+	runtime·lock(&runtime·sched);
+	if(p == nil) {
+		p = pidleget();
+		if(p == nil) {
+			runtime·unlock(&runtime·sched);
+			if(spinning)
+				runtime·xadd(&runtime·sched.nmspinning, -1);
+			return;
+		}
+	}
+	mp = mget();
+	runtime·unlock(&runtime·sched);
+	if(mp == nil) {
+		fn = nil;
+		if(spinning)
+			fn = mspinning;
+		newm(fn, p);
 		return;
-
-	while(haveg() && canaddmcpu()) {
-		gp = gget();
-		if(gp == nil)
-			runtime·throw("gget inconsistency");
-
-		// Find the m that will run gp.
-		if((mp = mget(gp)) == nil)
-			mp = runtime·newm();
-		mnextg(mp, gp);
 	}
+	if(mp->spinning)
+		runtime·throw("startm: m is spinning");
+	if(mp->nextp)
+		runtime·throw("startm: m has p");
+	mp->spinning = spinning;
+	mp->nextp = p;
+	runtime·notewakeup(&mp->park);
 }
 
-// Create a new m.  It will start off with a call to runtime·mstart.
-M*
-runtime·newm(void)
+// Hands off P from syscall or locked M.
+static void
+handoffp(P *p)
 {
-	M *m;
+	// if it has local work, start it straight away
+	if(p->runqhead != p->runqtail || runtime·sched.runqsize) {
+		startm(p, false);
+		return;
+	}
+	// 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)) {
+		startm(p, true);
+		return;
+	}
+	runtime·lock(&runtime·sched);
+	if(runtime·gcwaiting) {
+		p->status = Pgcstop;
+		if(--runtime·sched.stopwait == 0)
+			runtime·notewakeup(&runtime·sched.stopnote);
+		runtime·unlock(&runtime·sched);
+		return;
+	}
+	if(runtime·sched.runqsize) {
+		runtime·unlock(&runtime·sched);
+		startm(p, false);
+		return;
+	}
+	pidleput(p);
+	runtime·unlock(&runtime·sched);
+}
 
-	m = runtime·malloc(sizeof(M));
-	mcommoninit(m);
+// Tries to add one more P to execute G's.
+// Called when a G is made runnable (newproc, ready).
+static void
+wakep(void)
+{
+	// be conservative about spinning threads
+	if(!runtime·cas(&runtime·sched.nmspinning, 0, 1))
+		return;
+	startm(nil, true);
+}
 
-	if(runtime·iscgo) {
-		CgoThreadStart ts;
+// Stops execution of the current m that is locked to a g until the g is runnable again.
+// Returns with acquired P.
+static void
+stoplockedm(void)
+{
+	P *p;
 
-		if(libcgo_thread_start == nil)
-			runtime·throw("libcgo_thread_start missing");
-		// pthread_create will make us a stack.
-		m->g0 = runtime·malg(-1);
-		ts.m = m;
-		ts.g = m->g0;
-		ts.fn = runtime·mstart;
-		runtime·asmcgocall(libcgo_thread_start, &ts);
-	} else {
-		if(Windows)
-			// windows will layout sched stack on os stack
-			m->g0 = runtime·malg(-1);
-		else
-			m->g0 = runtime·malg(8192);
-		runtime·newosproc(m, m->g0, m->g0->stackbase, runtime·mstart);
+	if(m->lockedg == nil || m->lockedg->lockedm != m)
+		runtime·throw("stoplockedm: inconsistent locking");
+	if(m->p) {
+		// Schedule another M to run this p.
+		p = releasep();
+		handoffp(p);
 	}
+	inclocked(1);
+	// Wait until another thread schedules lockedg again.
+	runtime·notesleep(&m->park);
+	runtime·noteclear(&m->park);
+	if(m->lockedg->status != Grunnable)
+		runtime·throw("stoplockedm: not runnable");
+	acquirep(m->nextp);
+	m->nextp = nil;
+}
 
-	return m;
+// Schedules the locked m to run the locked gp.
+static void
+startlockedm(G *gp)
+{
+	M *mp;
+	P *p;
+
+	mp = gp->lockedm;
+	if(mp == m)
+		runtime·throw("startlockedm: locked to me");
+	if(mp->nextp)
+		runtime·throw("startlockedm: m has p");
+	// directly handoff current P to the locked m
+	inclocked(-1);
+	p = releasep();
+	mp->nextp = p;
+	runtime·notewakeup(&mp->park);
+	stopm();
+}
+
+// Stops the current m for stoptheworld.
+// Returns when the world is restarted.
+static void
+gcstopm(void)
+{
+	P *p;
+
+	if(!runtime·gcwaiting)
+		runtime·throw("gcstopm: not waiting for gc");
+	if(m->spinning) {
+		m->spinning = false;
+		runtime·xadd(&runtime·sched.nmspinning, -1);
+	}
+	p = releasep();
+	runtime·lock(&runtime·sched);
+	p->status = Pgcstop;
+	if(--runtime·sched.stopwait == 0)
+		runtime·notewakeup(&runtime·sched.stopnote);
+	runtime·unlock(&runtime·sched);
+	stopm();
 }
 
-// One round of scheduler: find a goroutine and run it.
-// The argument is the goroutine that was running before
-// schedule was called, or nil if this is the first call.
+// Schedules gp to run on the current M.
 // Never returns.
 static void
-schedule(G *gp)
+execute(G *gp)
 {
 	int32 hz;
-	uint32 v;
-
-	schedlock();
-	if(gp != nil) {
-		// Just finished running gp.
-		gp->m = nil;
-		runtime·sched.grunning--;
-
-		// atomic { mcpu-- }
-		v = runtime·xadd(&runtime·sched.atomic, -1<<mcpuShift);
-		if(atomic_mcpu(v) > maxgomaxprocs)
-			runtime·throw("negative mcpu in scheduler");
-
-		switch(gp->status){
-		case Grunnable:
-		case Gdead:
-			// Shouldn't have been running!
-			runtime·throw("bad gp->status in sched");
-		case Grunning:
-			gp->status = Grunnable;
-			gput(gp);
-			break;
-		case Gmoribund:
-			gp->status = Gdead;
-			if(gp->lockedm) {
-				gp->lockedm = nil;
-				m->lockedg = nil;
-			}
-			gp->idlem = nil;
-			unwindstack(gp, nil);
-			gfput(gp);
-			if(--runtime·sched.gcount == 0)
-				runtime·exit(0);
-			break;
-		}
-		if(gp->readyonstop){
-			gp->readyonstop = 0;
-			readylocked(gp);
-		}
-	} else if(m->helpgc) {
-		// Bootstrap m or new m started by starttheworld.
-		// atomic { mcpu-- }
-		v = runtime·xadd(&runtime·sched.atomic, -1<<mcpuShift);
-		if(atomic_mcpu(v) > maxgomaxprocs)
-			runtime·throw("negative mcpu in scheduler");
-		// Compensate for increment in starttheworld().
-		runtime·sched.grunning--;
-		m->helpgc = 0;
-	} else if(m->nextg != nil) {
-		// New m started by matchmg.
-	} else {
-		runtime·throw("invalid m state in scheduler");
-	}
 
-	// Find (or wait for) g to run.  Unlocks runtime·sched.
-	gp = nextgandunlock();
-	gp->readyonstop = 0;
+	if(gp->status != Grunnable) {
+		runtime·printf("execute: bad g status %d\n", gp->status);
+		runtime·throw("execute: bad g status");
+	}
 	gp->status = Grunning;
+	m->p->tick++;
 	m->curg = gp;
 	gp->m = m;
 
@@ -904,27 +964,209 @@ schedule(G *gp)
 	if(m->profilehz != hz)
 		runtime·resetcpuprofiler(hz);
 
-	if(gp->sched.pc == (byte*)runtime·goexit) {	// kickoff
-		runtime·gogocall(&gp->sched, (void(*)(void))gp->entry);
-	}
+	if(gp->sched.pc == (byte*)runtime·goexit)  // kickoff
+		runtime·gogocallfn(&gp->sched, gp->fnstart);
 	runtime·gogo(&gp->sched, 0);
 }
 
-// Enter scheduler.  If g->status is Grunning,
-// re-queues g and runs everyone else who is waiting
-// before running g again.  If g->status is Gmoribund,
-// kills off g.
-// Cannot split stack because it is called from exitsyscall.
-// See comment below.
-#pragma textflag 7
+// Finds a runnable goroutine to execute.
+// Tries to steal from other P's and get g from global queue.
+static G*
+findrunnable(void)
+{
+	G *gp;
+	P *p;
+	int32 i;
+
+top:
+	if(runtime·gcwaiting) {
+		gcstopm();
+		goto top;
+	}
+	// local runq
+	gp = runqget(m->p);
+	if(gp)
+		return gp;
+	// global runq
+	if(runtime·sched.runqsize) {
+		runtime·lock(&runtime·sched);
+		gp = globrunqget(m->p);
+		runtime·unlock(&runtime·sched);
+		if(gp)
+			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
+		goto stop;
+	if(!m->spinning) {
+		m->spinning = true;
+		runtime·xadd(&runtime·sched.nmspinning, 1);
+	}
+	// random steal from other P's
+	for(i = 0; i < 2*runtime·gomaxprocs; i++) {
+		if(runtime·gcwaiting)
+			goto top;
+		p = runtime·allp[runtime·fastrand1()%runtime·gomaxprocs];
+		if(p == m->p)
+			gp = runqget(p);
+		else
+			gp = runqsteal(m->p, p);
+		if(gp)
+			return gp;
+	}
+stop:
+	// return P and block
+	runtime·lock(&runtime·sched);
+	if(runtime·gcwaiting) {
+		runtime·unlock(&runtime·sched);
+		goto top;
+	}
+	if(runtime·sched.runqsize) {
+		gp = globrunqget(m->p);
+		runtime·unlock(&runtime·sched);
+		return gp;
+	}
+	p = releasep();
+	pidleput(p);
+	runtime·unlock(&runtime·sched);
+	if(m->spinning) {
+		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);
+			p = pidleget();
+			runtime·unlock(&runtime·sched);
+			if(p) {
+				acquirep(p);
+				goto top;
+			}
+			break;
+		}
+	}
+	stopm();
+	goto top;
+}
+
+// One round of scheduler: find a runnable goroutine and execute it.
+// Never returns.
+static void
+schedule(void)
+{
+	G *gp;
+
+	if(m->locks)
+		runtime·throw("schedule: holding locks");
+
+top:
+	if(runtime·gcwaiting) {
+		gcstopm();
+		goto top;
+	}
+
+	gp = runqget(m->p);
+	if(gp == nil)
+		gp = findrunnable();
+
+	if(m->spinning) {
+		m->spinning = false;
+		runtime·xadd(&runtime·sched.nmspinning, -1);
+	}
+
+	// M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
+	// so see if we need to wakeup another M here.
+	if (m->p->runqhead != m->p->runqtail &&
+		runtime·atomicload(&runtime·sched.nmspinning) == 0 &&
+		runtime·atomicload(&runtime·sched.npidle) > 0)  // TODO: fast atomic
+		wakep();
+
+	if(gp->lockedm) {
+		startlockedm(gp);
+		goto top;
+	}
+
+	execute(gp);
+}
+
+// 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·park(void(*unlockf)(Lock*), Lock *lock, int8 *reason)
+{
+	m->waitlock = lock;
+	m->waitunlockf = unlockf;
+	g->waitreason = reason;
+	runtime·mcall(park0);
+}
+
+// runtime·park continuation on g0.
+static void
+park0(G *gp)
+{
+	gp->status = Gwaiting;
+	gp->m = nil;
+	m->curg = nil;
+	if(m->waitunlockf) {
+		m->waitunlockf(m->waitlock);
+		m->waitunlockf = nil;
+	}
+	if(m->lockedg) {
+		stoplockedm();
+		execute(gp);  // Never returns.
+	}
+	schedule();
+}
+
+// Scheduler yield.
 void
 runtime·gosched(void)
 {
-	if(m->locks != 0)
-		runtime·throw("gosched holding locks");
-	if(g == m->g0)
-		runtime·throw("gosched of g0");
-	runtime·mcall(schedule);
+	runtime·mcall(gosched0);
+}
+
+// runtime·gosched continuation on g0.
+static void
+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.
+	}
+	schedule();
+}
+
+// Finishes execution of the current goroutine.
+void
+runtime·goexit(void)
+{
+	if(raceenabled)
+		runtime·racegoend();
+	runtime·mcall(goexit0);
+}
+
+// runtime·goexit continuation on g0.
+static void
+goexit0(G *gp)
+{
+	gp->status = Gdead;
+	gp->m = nil;
+	gp->lockedm = nil;
+	m->curg = nil;
+	m->lockedg = nil;
+	runtime·unwindstack(gp, nil);
+	gfput(m->p, gp);
+	schedule();
 }
 
 // The goroutine g is about to enter a system call.
@@ -935,21 +1177,19 @@ runtime·gosched(void)
 // 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.
-// It's okay to call matchmg and notewakeup even after
-// decrementing mcpu, because we haven't released the
-// sched lock yet, so the garbage collector cannot be running.
 #pragma textflag 7
 void
-runtime·entersyscall(void)
+·entersyscall(int32 dummy)
 {
-	uint32 v;
-
 	if(m->profilehz > 0)
 		runtime·setprof(false);
 
 	// Leave SP around for gc and traceback.
-	runtime·gosave(&g->sched);
+	g->sched.sp = (uintptr)runtime·getcallersp(&dummy);
+	g->sched.pc = runtime·getcallerpc(&dummy);
+	g->sched.g = g;
 	g->gcsp = g->sched.sp;
+	g->gcpc = g->sched.pc;
 	g->gcstack = g->stackbase;
 	g->gcguard = g->stackguard;
 	g->status = Gsyscall;
@@ -959,34 +1199,61 @@ runtime·entersyscall(void)
 		runtime·throw("entersyscall");
 	}
 
-	// Fast path.
-	// The slow path inside the schedlock/schedunlock will get
-	// through without stopping if it does:
-	//	mcpu--
-	//	gwait not true
-	//	waitstop && mcpu <= mcpumax not true
-	// If we can do the same with a single atomic add,
-	// then we can skip the locks.
-	v = runtime·xadd(&runtime·sched.atomic, -1<<mcpuShift);
-	if(!atomic_gwaiting(v) && (!atomic_waitstop(v) || atomic_mcpu(v) > atomic_mcpumax(v)))
-		return;
-
-	schedlock();
-	v = runtime·atomicload(&runtime·sched.atomic);
-	if(atomic_gwaiting(v)) {
-		matchmg();
-		v = runtime·atomicload(&runtime·sched.atomic);
+	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);
+		runtime·gosave(&g->sched);  // re-save for traceback
 	}
-	if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) {
-		runtime·xadd(&runtime·sched.atomic, -1<<waitstopShift);
-		runtime·notewakeup(&runtime·sched.stopped);
+
+	m->mcache = nil;
+	m->p->tick++;
+	m->p->m = nil;
+	runtime·atomicstore(&m->p->status, Psyscall);
+	if(runtime·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);
+		runtime·gosave(&g->sched);  // re-save for traceback
 	}
+}
+
+// The same as runtime·entersyscall(), but with a hint that the syscall is blocking.
+#pragma textflag 7
+void
+·entersyscallblock(int32 dummy)
+{
+	P *p;
 
-	// Re-save sched in case one of the calls
-	// (notewakeup, matchmg) triggered something using it.
-	runtime·gosave(&g->sched);
+	if(m->profilehz > 0)
+		runtime·setprof(false);
 
-	schedunlock();
+	// Leave SP around for gc and traceback.
+	g->sched.sp = (uintptr)runtime·getcallersp(&dummy);
+	g->sched.pc = runtime·getcallerpc(&dummy);
+	g->sched.g = g;
+	g->gcsp = g->sched.sp;
+	g->gcpc = g->sched.pc;
+	g->gcstack = g->stackbase;
+	g->gcguard = g->stackguard;
+	g->status = Gsyscall;
+	if(g->gcsp < g->gcguard-StackGuard || g->gcstack < g->gcsp) {
+		// runtime·printf("entersyscallblock inconsistent %p [%p,%p]\n",
+		//	g->gcsp, g->gcguard-StackGuard, g->gcstack);
+		runtime·throw("entersyscallblock");
+	}
+
+	p = releasep();
+	handoffp(p);
+	if(g == scvg)  // do not consider blocked scavenger for deadlock detection
+		inclocked(1);
+	runtime·gosave(&g->sched);  // re-save for traceback
 }
 
 // The goroutine g exited its system call.
@@ -996,177 +1263,81 @@ runtime·entersyscall(void)
 void
 runtime·exitsyscall(void)
 {
-	uint32 v;
+	P *p;
 
-	// Fast path.
-	// If we can do the mcpu++ bookkeeping and
-	// find that we still have mcpu <= mcpumax, then we can
-	// start executing Go code immediately, without having to
-	// schedlock/schedunlock.
-	v = runtime·xadd(&runtime·sched.atomic, (1<<mcpuShift));
-	if(m->profilehz == runtime·sched.profilehz && atomic_mcpu(v) <= atomic_mcpumax(v)) {
+	// Check whether the profiler needs to be turned on.
+	if(m->profilehz > 0)
+		runtime·setprof(true);
+
+	// Try to re-acquire the last P.
+	if(m->p && m->p->status == Psyscall && runtime·cas(&m->p->status, Psyscall, Prunning)) {
 		// There's a cpu for us, so we can run.
+		m->mcache = m->p->mcache;
+		m->p->m = m;
+		m->p->tick++;
 		g->status = Grunning;
 		// Garbage collector isn't running (since we are),
-		// so okay to clear gcstack.
-		g->gcstack = nil;
-
-		if(m->profilehz > 0)
-			runtime·setprof(true);
+		// so okay to clear gcstack and gcsp.
+		g->gcstack = (uintptr)nil;
+		g->gcsp = (uintptr)nil;
 		return;
 	}
 
-	// Tell scheduler to put g back on the run queue:
-	// mostly equivalent to g->status = Grunning,
-	// but keeps the garbage collector from thinking
-	// that g is running right now, which it's not.
-	g->readyonstop = 1;
+	if(g == scvg)  // do not consider blocked scavenger for deadlock detection
+		inclocked(-1);
+	// Try to get any other idle P.
+	m->p = nil;
+	if(runtime·sched.pidle) {
+		runtime·lock(&runtime·sched);
+		p = pidleget();
+		runtime·unlock(&runtime·sched);
+		if(p) {
+			acquirep(p);
+			g->gcstack = (uintptr)nil;
+			g->gcsp = (uintptr)nil;
+			return;
+		}
+	}
+
+	// Call the scheduler.
+	runtime·mcall(exitsyscall0);
 
-	// All the cpus are taken.
-	// The scheduler will ready g and put this m to sleep.
-	// When the scheduler takes g away from m,
-	// it will undo the runtime·sched.mcpu++ above.
-	runtime·gosched();
-
-	// Gosched returned, so we're allowed to run now.
+	// Scheduler returned, so we're allowed to run now.
 	// Delete the gcstack 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->gcstack = nil;
+	g->gcstack = (uintptr)nil;
+	g->gcsp = (uintptr)nil;
 }
 
-// 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)
+// runtime·exitsyscall slow path on g0.
+// Failed to acquire P, enqueue gp as runnable.
+static void
+exitsyscall0(G *gp)
 {
-	Stktop *top, old;
-	uint32 argsize;
-	uintptr cret;
-	byte *sp;
-	G *g1;
-	int32 goid;
-
-//printf("oldstack m->cret=%p\n", m->cret);
-
-	g1 = m->curg;
-	top = (Stktop*)g1->stackbase;
-	sp = (byte*)top;
-	old = *top;
-	argsize = old.argsize;
-	if(argsize > 0) {
-		sp -= argsize;
-		runtime·memmove(top->argp, sp, argsize);
-	}
-	goid = old.gobuf.g->goid;	// fault if g is bad, before gogo
-	USED(goid);
-
-	if(old.free != 0)
-		runtime·stackfree(g1->stackguard - StackGuard, old.free);
-	g1->stackbase = old.stackbase;
-	g1->stackguard = old.stackguard;
-
-	cret = m->cret;
-	m->cret = 0;  // drop reference
-	runtime·gogo(&old.gobuf, cret);
-}
-
-// Called from reflect·call 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;
-	Stktop *top;
-	byte *stk, *sp;
-	G *g1;
-	Gobuf label;
-	bool reflectcall;
-	uintptr free;
-
-	framesize = m->moreframesize;
-	argsize = m->moreargsize;
-	g1 = m->curg;
-
-	if(m->morebuf.sp < g1->stackguard - StackGuard) {
-		runtime·printf("runtime: split stack overflow: %p < %p\n", m->morebuf.sp, g1->stackguard - StackGuard);
-		runtime·throw("runtime: split stack overflow");
-	}
-	if(argsize % sizeof(uintptr) != 0) {
-		runtime·printf("runtime: stack split with misaligned argsize %d\n", argsize);
-		runtime·throw("runtime: stack split argsize");
-	}
-
-	reflectcall = framesize==1;
-	if(reflectcall)
-		framesize = 0;
-
-	if(reflectcall && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > g1->stackguard) {
-		// special case: called from reflect.call (framesize==1)
-		// to call code with an arbitrary argument size,
-		// and we have enough space on the current stack.
-		// the new Stktop* is necessary to unwind, but
-		// we don't need to create a new segment.
-		top = (Stktop*)(m->morebuf.sp - sizeof(*top));
-		stk = g1->stackguard - StackGuard;
-		free = 0;
-	} else {
-		// allocate new segment.
-		framesize += argsize;
-		framesize += StackExtra;	// room for more functions, Stktop.
-		if(framesize < StackMin)
-			framesize = StackMin;
-		framesize += StackSystem;
-		stk = runtime·stackalloc(framesize);
-		top = (Stktop*)(stk+framesize-sizeof(*top));
-		free = framesize;
-	}
-
-//runtime·printf("newstack framesize=%d argsize=%d morepc=%p moreargp=%p gobuf=%p, %p top=%p old=%p\n",
-//framesize, argsize, m->morepc, m->moreargp, m->morebuf.pc, m->morebuf.sp, top, g1->stackbase);
-
-	top->stackbase = g1->stackbase;
-	top->stackguard = g1->stackguard;
-	top->gobuf = m->morebuf;
-	top->argp = m->moreargp;
-	top->argsize = argsize;
-	top->free = free;
-	m->moreargp = nil;
-	m->morebuf.pc = nil;
-	m->morebuf.sp = nil;
-
-	// copy flag from panic
-	top->panic = g1->ispanic;
-	g1->ispanic = false;
-
-	g1->stackbase = (byte*)top;
-	g1->stackguard = stk + StackGuard;
-
-	sp = (byte*)top;
-	if(argsize > 0) {
-		sp -= argsize;
-		runtime·memmove(sp, top->argp, argsize);
+	P *p;
+
+	gp->status = Grunnable;
+	gp->m = nil;
+	m->curg = nil;
+	runtime·lock(&runtime·sched);
+	p = pidleget();
+	if(p == nil)
+		globrunqput(gp);
+	runtime·unlock(&runtime·sched);
+	if(p) {
+		acquirep(p);
+		execute(gp);  // Never returns.
 	}
-	if(thechar == '5') {
-		// caller would have saved its LR below args.
-		sp -= sizeof(void*);
-		*(void**)sp = nil;
+	if(m->lockedg) {
+		// Wait until another thread schedules gp and so m again.
+		stoplockedm();
+		execute(gp);  // Never returns.
 	}
-
-	// Continue as if lessstack had just called m->morepc
-	// (the PC that decided to grow the stack).
-	label.sp = sp;
-	label.pc = (byte*)runtime·lessstack;
-	label.g = m->curg;
-	runtime·gogocall(&label, m->morepc);
-
-	*(int32*)345 = 123;	// never return
+	stopm();
+	schedule();  // Never returns.
 }
 
 // Hook used by runtime·malg to call runtime·stackalloc on the
@@ -1204,10 +1375,10 @@ runtime·malg(int32 stacksize)
 			stk = g->param;
 			g->param = nil;
 		}
-		newg->stack0 = stk;
-		newg->stackguard = stk + StackGuard;
-		newg->stackbase = stk + StackSystem + stacksize - sizeof(Stktop);
-		runtime·memclr(newg->stackbase, sizeof(Stktop));
+		newg->stack0 = (uintptr)stk;
+		newg->stackguard = (uintptr)stk + StackGuard;
+		newg->stackbase = (uintptr)stk + StackSystem + stacksize - sizeof(Stktop);
+		runtime·memclr((byte*)newg->stackbase, sizeof(Stktop));
 	}
 	return newg;
 }
@@ -1221,7 +1392,7 @@ runtime·malg(int32 stacksize)
 // functions that split the stack.
 #pragma textflag 7
 void
-runtime·newproc(int32 siz, byte* fn, ...)
+runtime·newproc(int32 siz, FuncVal* fn, ...)
 {
 	byte *argp;
 
@@ -1237,7 +1408,7 @@ runtime·newproc(int32 siz, byte* fn, ...)
 // address of the go statement that created this.  The new g is put
 // on the queue of g's waiting to run.
 G*
-runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc)
+runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerpc)
 {
 	byte *sp;
 	G *newg;
@@ -1254,23 +1425,21 @@ runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc)
 	if(siz > StackMin - 1024)
 		runtime·throw("runtime.newproc: function arguments too large for new goroutine");
 
-	schedlock();
-
-	if((newg = gfget()) != nil){
+	if((newg = gfget(m->p)) != nil) {
 		if(newg->stackguard - StackGuard != newg->stack0)
 			runtime·throw("invalid stack in newg");
 	} else {
 		newg = runtime·malg(StackMin);
+		runtime·lock(&runtime·sched);
 		if(runtime·lastg == nil)
 			runtime·allg = newg;
 		else
 			runtime·lastg->alllink = newg;
 		runtime·lastg = newg;
+		runtime·unlock(&runtime·sched);
 	}
-	newg->status = Gwaiting;
-	newg->waitreason = "new goroutine";
 
-	sp = newg->stackbase;
+	sp = (byte*)newg->stackbase;
 	sp -= siz;
 	runtime·memmove(sp, argp, narg);
 	if(thechar == '5') {
@@ -1279,318 +1448,88 @@ runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc)
 		*(void**)sp = nil;
 	}
 
-	newg->sched.sp = sp;
+	newg->sched.sp = (uintptr)sp;
 	newg->sched.pc = (byte*)runtime·goexit;
 	newg->sched.g = newg;
-	newg->entry = fn;
+	newg->fnstart = fn;
 	newg->gopc = (uintptr)callerpc;
-
-	runtime·sched.gcount++;
-	runtime·sched.goidgen++;
-	newg->goid = runtime·sched.goidgen;
-
-	newprocreadylocked(newg);
-	schedunlock();
-
+	newg->status = Grunnable;
+	newg->goid = runtime·xadd64(&runtime·sched.goidgen, 1);
+	if(raceenabled)
+		newg->racectx = runtime·racegostart(callerpc);
+	runqput(m->p, newg);
+
+	if(runtime·atomicload(&runtime·sched.npidle) != 0 && runtime·atomicload(&runtime·sched.nmspinning) == 0 && fn->fn != runtime·main)  // TODO: fast atomic
+		wakep();
 	return newg;
-//printf(" goid=%d\n", newg->goid);
-}
-
-// 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 7
-uintptr
-runtime·deferproc(int32 siz, byte* fn, ...)
-{
-	Defer *d;
-
-	d = runtime·malloc(sizeof(*d) + siz - sizeof(d->args));
-	d->fn = fn;
-	d->siz = siz;
-	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);
-
-	d->link = g->defer;
-	g->defer = d;
-
-	// 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.
-#pragma textflag 7
-void
-runtime·deferreturn(uintptr arg0)
-{
-	Defer *d;
-	byte *argp, *fn;
-
-	d = g->defer;
-	if(d == nil)
-		return;
-	argp = (byte*)&arg0;
-	if(d->argp != argp)
-		return;
-	runtime·memmove(argp, d->args, d->siz);
-	g->defer = d->link;
-	fn = d->fn;
-	if(!d->nofree)
-		runtime·free(d);
-	runtime·jmpdefer(fn, argp);
 }
 
-// Run all deferred functions for the current goroutine.
+// Put on gfree list.
+// If local list is too long, transfer a batch to the global list.
 static void
-rundefer(void)
+gfput(P *p, G *gp)
 {
-	Defer *d;
-
-	while((d = g->defer) != nil) {
-		g->defer = d->link;
-		reflect·call(d->fn, d->args, d->siz);
-		if(!d->nofree)
-			runtime·free(d);
+	if(gp->stackguard - StackGuard != gp->stack0)
+		runtime·throw("invalid stack in gfput");
+	gp->schedlink = p->gfree;
+	p->gfree = gp;
+	p->gfreecnt++;
+	if(p->gfreecnt >= 64) {
+		runtime·lock(&runtime·sched.gflock);
+		while(p->gfreecnt >= 32) {
+			p->gfreecnt--;
+			gp = p->gfree;
+			p->gfree = gp->schedlink;
+			gp->schedlink = runtime·sched.gfree;
+			runtime·sched.gfree = gp;
+		}
+		runtime·unlock(&runtime·sched.gflock);
 	}
 }
 
-// Free stack frames until we hit the last one
-// or until we find the one that contains the argp.
-static void
-unwindstack(G *gp, byte *sp)
+// Get from gfree list.
+// If local list is empty, grab a batch from global list.
+static G*
+gfget(P *p)
 {
-	Stktop *top;
-	byte *stk;
-
-	// Must be called from a different goroutine, usually m->g0.
-	if(g == gp)
-		runtime·throw("unwindstack on self");
+	G *gp;
 
-	while((top = (Stktop*)gp->stackbase) != nil && top->stackbase != nil) {
-		stk = gp->stackguard - StackGuard;
-		if(stk <= sp && sp < gp->stackbase)
-			break;
-		gp->stackbase = top->stackbase;
-		gp->stackguard = top->stackguard;
-		if(top->free != 0)
-			runtime·stackfree(stk, top->free);
+retry:
+	gp = p->gfree;
+	if(gp == nil && runtime·sched.gfree) {
+		runtime·lock(&runtime·sched.gflock);
+		while(p->gfreecnt < 32 && runtime·sched.gfree) {
+			p->gfreecnt++;
+			gp = runtime·sched.gfree;
+			runtime·sched.gfree = gp->schedlink;
+			gp->schedlink = p->gfree;
+			p->gfree = gp;
+		}
+		runtime·unlock(&runtime·sched.gflock);
+		goto retry;
 	}
-
-	if(sp != nil && (sp < gp->stackguard - StackGuard || gp->stackbase < sp)) {
-		runtime·printf("recover: %p not in [%p, %p]\n", sp, gp->stackguard - StackGuard, gp->stackbase);
-		runtime·throw("bad unwindstack");
+	if(gp) {
+		p->gfree = gp->schedlink;
+		p->gfreecnt--;
 	}
+	return gp;
 }
 
-// Print all currently active panics.  Used when crashing.
+// Purge all cached G's from gfree list to the global list.
 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*);
-
-// The implementation of the predeclared function panic.
-void
-runtime·panic(Eface e)
+gfpurge(P *p)
 {
-	Defer *d;
-	Panic *p;
-
-	p = runtime·mal(sizeof *p);
-	p->arg = e;
-	p->link = g->panic;
-	p->stackbase = g->stackbase;
-	g->panic = p;
+	G *gp;
 
-	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 newstack, where reflect.call ends up
-		reflect·call(d->fn, d->args, d->siz);
-		if(p->recovered) {
-			g->panic = p->link;
-			if(g->panic == nil)	// must be done with signal
-				g->sig = 0;
-			runtime·free(p);
-			// put recovering defer back on list
-			// for scheduler to find.
-			d->link = g->defer;
-			g->defer = d;
-			runtime·mcall(recovery);
-			runtime·throw("recovery failed"); // mcall should not return
-		}
-		if(!d->nofree)
-			runtime·free(d);
+	runtime·lock(&runtime·sched.gflock);
+	while(p->gfreecnt) {
+		p->gfreecnt--;
+		gp = p->gfree;
+		p->gfree = gp->schedlink;
+		gp->schedlink = runtime·sched.gfree;
+		runtime·sched.gfree = gp;
 	}
-
-	// ran out of deferred calls - old-school panic now
-	runtime·startpanic();
-	printpanics(g->panic);
-	runtime·dopanic(0);
-}
-
-// 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)
-{
-	Defer *d;
-
-	// Rewind gp's stack; we're running on m->g0's stack.
-	d = gp->defer;
-	gp->defer = d->link;
-
-	// Unwind to the stack frame with d's arguments in it.
-	unwindstack(gp, d->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 = (byte*)d->argp - 4*sizeof(uintptr);
-	else
-		gp->sched.sp = (byte*)d->argp - 2*sizeof(uintptr);
-	gp->sched.pc = d->pc;
-	if(!d->nofree)
-		runtime·free(d);
-	runtime·gogo(&gp->sched, 1);
-}
-
-// 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 7
-void
-runtime·recover(byte *argp, Eface ret)
-{
-	Stktop *top, *oldtop;
-	Panic *p;
-
-	// Must be a panic going on.
-	if((p = g->panic) == nil || p->recovered)
-		goto nomatch;
-
-	// Frame must be at the top of the stack segment,
-	// because each deferred call starts a new stack
-	// segment as a side effect of using reflect.call.
-	// (There has to be some way to remember the
-	// variable argument frame size, and the segment
-	// code already takes care of that for us, so we
-	// reuse it.)
-	//
-	// As usual closures complicate things: the fp that
-	// the closure implementation function claims to have
-	// is where the explicit arguments start, after the
-	// implicit pointer arguments and PC slot.
-	// If we're on the first new segment for a closure,
-	// then fp == top - top->args is correct, but if
-	// the closure has its own big argument frame and
-	// allocated a second segment (see below),
-	// the fp is slightly above top - top->args.
-	// That condition can't happen normally though
-	// (stack pointers go down, not up), so we can accept
-	// any fp between top and top - top->args as
-	// indicating the top of the segment.
-	top = (Stktop*)g->stackbase;
-	if(argp < (byte*)top - top->argsize || (byte*)top < argp)
-		goto nomatch;
-
-	// The deferred call makes a new segment big enough
-	// for the argument frame but not necessarily big
-	// enough for the function's local frame (size unknown
-	// at the time of the call), so the function might have
-	// made its own segment immediately.  If that's the
-	// case, back top up to the older one, the one that
-	// reflect.call would have made for the panic.
-	//
-	// The fp comparison here checks that the argument
-	// frame that was copied during the split (the top->args
-	// bytes above top->fp) abuts the old top of stack.
-	// This is a correct test for both closure and non-closure code.
-	oldtop = (Stktop*)top->stackbase;
-	if(oldtop != nil && top->argp == (byte*)oldtop - top->argsize)
-		top = oldtop;
-
-	// Now we have the segment that was created to
-	// run this call.  It must have been marked as a panic segment.
-	if(!top->panic)
-		goto nomatch;
-
-	// Okay, this is the top frame of a deferred call
-	// in response to a panic.  It can see the panic argument.
-	p->recovered = 1;
-	ret = p->arg;
-	FLUSH(&ret);
-	return;
-
-nomatch:
-	ret.type = nil;
-	ret.data = nil;
-	FLUSH(&ret);
-}
-
-
-// Put on gfree list.  Sched must be locked.
-static void
-gfput(G *g)
-{
-	if(g->stackguard - StackGuard != g->stack0)
-		runtime·throw("invalid stack in gfput");
-	g->schedlink = runtime·sched.gfree;
-	runtime·sched.gfree = g;
-}
-
-// Get from gfree list.  Sched must be locked.
-static G*
-gfget(void)
-{
-	G *g;
-
-	g = runtime·sched.gfree;
-	if(g)
-		runtime·sched.gfree = g->schedlink;
-	return g;
+	runtime·unlock(&runtime·sched.gflock);
 }
 
 void
@@ -1600,80 +1539,85 @@ runtime·Breakpoint(void)
 }
 
 void
-runtime·Goexit(void)
-{
-	rundefer();
-	runtime·goexit();
-}
-
-void
 runtime·Gosched(void)
 {
 	runtime·gosched();
 }
 
 // Implementation of runtime.GOMAXPROCS.
-// delete when scheduler is stronger
+// delete when scheduler is even stronger
 int32
 runtime·gomaxprocsfunc(int32 n)
 {
 	int32 ret;
-	uint32 v;
 
-	schedlock();
+	if(n > MaxGomaxprocs)
+		n = MaxGomaxprocs;
+	runtime·lock(&runtime·sched);
 	ret = runtime·gomaxprocs;
-	if(n <= 0)
-		n = ret;
-	if(n > maxgomaxprocs)
-		n = maxgomaxprocs;
-	runtime·gomaxprocs = n;
-	if(runtime·gomaxprocs > 1)
-		runtime·singleproc = false;
- 	if(runtime·gcwaiting != 0) {
- 		if(atomic_mcpumax(runtime·sched.atomic) != 1)
- 			runtime·throw("invalid mcpumax during gc");
-		schedunlock();
+	if(n <= 0 || n == ret) {
+		runtime·unlock(&runtime·sched);
 		return ret;
 	}
+	runtime·unlock(&runtime·sched);
 
-	setmcpumax(n);
+	runtime·semacquire(&runtime·worldsema);
+	m->gcing = 1;
+	runtime·stoptheworld();
+	newprocs = n;
+	m->gcing = 0;
+	runtime·semrelease(&runtime·worldsema);
+	runtime·starttheworld();
 
-	// If there are now fewer allowed procs
-	// than procs running, stop.
-	v = runtime·atomicload(&runtime·sched.atomic);
-	if(atomic_mcpu(v) > n) {
-		schedunlock();
-		runtime·gosched();
-		return ret;
-	}
-	// handle more procs
-	matchmg();
-	schedunlock();
 	return ret;
 }
 
-void
-runtime·LockOSThread(void)
+static void
+LockOSThread(void)
 {
-	if(m == &runtime·m0 && runtime·sched.init) {
-		runtime·sched.lockmain = true;
-		return;
-	}
 	m->lockedg = g;
 	g->lockedm = m;
 }
 
 void
-runtime·UnlockOSThread(void)
+runtime·LockOSThread(void)
+{
+	m->locked |= LockExternal;
+	LockOSThread();
+}
+
+void
+runtime·lockOSThread(void)
 {
-	if(m == &runtime·m0 && runtime·sched.init) {
-		runtime·sched.lockmain = false;
+	m->locked += LockInternal;
+	LockOSThread();
+}
+
+static void
+UnlockOSThread(void)
+{
+	if(m->locked != 0)
 		return;
-	}
 	m->lockedg = nil;
 	g->lockedm = nil;
 }
 
+void
+runtime·UnlockOSThread(void)
+{
+	m->locked &= ~LockExternal;
+	UnlockOSThread();
+}
+
+void
+runtime·unlockOSThread(void)
+{
+	if(m->locked < LockInternal)
+		runtime·throw("runtime: internal error: misuse of lockOSThread/unlockOSThread");
+	m->locked -= LockInternal;
+	UnlockOSThread();
+}
+
 bool
 runtime·lockedOSThread(void)
 {
@@ -1697,16 +1641,31 @@ runtime·mid(uint32 ret)
 }
 
 void
-runtime·NumGoroutine(int32 ret)
+runtime·NumGoroutine(intgo ret)
 {
-	ret = runtime·sched.gcount;
+	ret = runtime·gcount();
 	FLUSH(&ret);
 }
 
 int32
 runtime·gcount(void)
 {
-	return runtime·sched.gcount;
+	G *gp;
+	int32 n, s;
+
+	n = 0;
+	runtime·lock(&runtime·sched);
+	// 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(gp = runtime·allg; gp; gp = gp->alllink) {
+		s = gp->status;
+		if(s == Grunnable || s == Grunning || s == Gsyscall || s == Gwaiting)
+			n++;
+	}
+	runtime·unlock(&runtime·sched);
+	return n;
 }
 
 int32
@@ -1740,6 +1699,9 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
 {
 	int32 n;
 
+	// Windows does profiling in a dedicated thread w/o m.
+	if(!Windows && (m == nil || m->mcache == nil))
+		return;
 	if(prof.fn == nil || prof.hz == 0)
 		return;
 
@@ -1783,27 +1745,533 @@ runtime·setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
 		runtime·resetcpuprofiler(hz);
 }
 
-void (*libcgo_setenv)(byte**);
+// Change number of processors.  The world is stopped, sched is locked.
+static void
+procresize(int32 new)
+{
+	int32 i, old;
+	G *gp;
+	P *p;
+
+	old = runtime·gomaxprocs;
+	if(old < 0 || old > MaxGomaxprocs || new <= 0 || new >MaxGomaxprocs)
+		runtime·throw("procresize: invalid arg");
+	// initialize new P's
+	for(i = 0; i < new; i++) {
+		p = runtime·allp[i];
+		if(p == nil) {
+			p = (P*)runtime·mallocgc(sizeof(*p), 0, 0, 1);
+			p->status = Pgcstop;
+			runtime·atomicstorep(&runtime·allp[i], p);
+		}
+		if(p->mcache == nil) {
+			if(old==0 && i==0)
+				p->mcache = m->mcache;  // bootstrap
+			else
+				p->mcache = runtime·allocmcache();
+		}
+		if(p->runq == nil) {
+			p->runqsize = 128;
+			p->runq = (G**)runtime·mallocgc(p->runqsize*sizeof(G*), 0, 0, 1);
+		}
+	}
+
+	// redistribute runnable G's evenly
+	for(i = 0; i < old; i++) {
+		p = runtime·allp[i];
+		while(gp = runqget(p))
+			globrunqput(gp);
+	}
+	// start at 1 because current M already executes some G and will acquire allp[0] below,
+	// so if we have a spare G we want to put it into allp[1].
+	for(i = 1; runtime·sched.runqhead; i++) {
+		gp = runtime·sched.runqhead;
+		runtime·sched.runqhead = gp->schedlink;
+		runqput(runtime·allp[i%new], gp);
+	}
+	runtime·sched.runqtail = nil;
+	runtime·sched.runqsize = 0;
+
+	// free unused P's
+	for(i = new; i < old; i++) {
+		p = runtime·allp[i];
+		runtime·freemcache(p->mcache);
+		p->mcache = nil;
+		gfpurge(p);
+		p->status = Pdead;
+		// 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;
+	p = runtime·allp[0];
+	p->m = nil;
+	p->status = Pidle;
+	acquirep(p);
+	for(i = new-1; i > 0; i--) {
+		p = runtime·allp[i];
+		p->status = Pidle;
+		pidleput(p);
+	}
+	runtime·singleproc = new == 1;
+	runtime·atomicstore((uint32*)&runtime·gomaxprocs, new);
+}
+
+// Associate p and the current m.
+static void
+acquirep(P *p)
+{
+	if(m->p || 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;
+	p->status = Prunning;
+}
+
+// Disassociate p and the current m.
+static P*
+releasep(void)
+{
+	P *p;
 
-// Update the C environment if cgo is loaded.
-// Called from syscall.Setenv.
-void
-syscall·setenv_c(String k, String v)
+	if(m->p == nil || m->mcache == nil)
+		runtime·throw("releasep: invalid arg");
+	p = m->p;
+	if(p->m != m || p->mcache != 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);
+		runtime·throw("releasep: invalid p state");
+	}
+	m->p = nil;
+	m->mcache = nil;
+	p->m = nil;
+	p->status = Pidle;
+	return p;
+}
+
+static void
+inclocked(int32 v)
 {
-	byte *arg[2];
+	runtime·lock(&runtime·sched);
+	runtime·sched.mlocked += v;
+	if(v > 0)
+		checkdead();
+	runtime·unlock(&runtime·sched);
+}
+
+// Check for deadlock situation.
+// The check is based on number of running M's, if 0 -> deadlock.
+static void
+checkdead(void)
+{
+	G *gp;
+	int32 run, grunning, s;
 
-	if(libcgo_setenv == nil)
+	// -1 for sysmon
+	run = runtime·sched.mcount - runtime·sched.nmidle - runtime·sched.mlocked - 1;
+	if(run > 0)
 		return;
+	if(run < 0) {
+		runtime·printf("checkdead: nmidle=%d mlocked=%d mcount=%d\n",
+			runtime·sched.nmidle, runtime·sched.mlocked, runtime·sched.mcount);
+		runtime·throw("checkdead: inconsistent counts");
+	}
+	grunning = 0;
+	for(gp = runtime·allg; gp; gp = gp->alllink) {
+		if(gp == scvg)
+			continue;
+		s = gp->status;
+		if(s == Gwaiting)
+			grunning++;
+		else if(s == Grunnable || s == Grunning || s == Gsyscall) {
+			runtime·printf("checkdead: find g %D in status %d\n", gp->goid, s);
+			runtime·throw("checkdead: runnable g");
+		}
+	}
+	if(grunning == 0)  // possible if main goroutine calls runtime·Goexit()
+		runtime·exit(0);
+	m->throwing = -1;  // do not dump full stacks
+	runtime·throw("all goroutines are asleep - deadlock!");
+}
+
+static void
+sysmon(void)
+{
+	uint32 idle, delay;
+	uint32 ticks[MaxGomaxprocs];
+
+	idle = 0;  // how many cycles in succession we had not wokeup somebody
+	delay = 0;
+	for(;;) {
+		if(idle == 0)  // start with 20us sleep...
+			delay = 20;
+		else if(idle > 50)  // start doubling the sleep after 1ms...
+			delay *= 2;
+		if(delay > 10*1000)  // up to 10ms
+			delay = 10*1000;
+		runtime·usleep(delay);
+		if(runtime·gcwaiting || runtime·atomicload(&runtime·sched.npidle) == runtime·gomaxprocs) {  // TODO: fast atomic
+			runtime·lock(&runtime·sched);
+			if(runtime·atomicload(&runtime·gcwaiting) || runtime·atomicload(&runtime·sched.npidle) == runtime·gomaxprocs) {
+				runtime·atomicstore(&runtime·sched.sysmonwait, 1);
+				runtime·unlock(&runtime·sched);
+				runtime·notesleep(&runtime·sched.sysmonnote);
+				runtime·noteclear(&runtime·sched.sysmonnote);
+				idle = 0;
+				delay = 20;
+			} else
+				runtime·unlock(&runtime·sched);
+		}
+		if(retake(ticks))
+			idle = 0;
+		else
+			idle++;
+	}
+}
+
+static uint32
+retake(uint32 *ticks)
+{
+	uint32 i, s, n;
+	int64 t;
+	P *p;
+
+	n = 0;
+	for(i = 0; i < runtime·gomaxprocs; i++) {
+		p = runtime·allp[i];
+		if(p==nil)
+			continue;
+		t = p->tick;
+		if(ticks[i] != t) {
+			ticks[i] = t;
+			continue;
+		}
+		s = p->status;
+		if(s != Psyscall)
+			continue;
+		if(p->runqhead == p->runqtail && runtime·atomicload(&runtime·sched.nmspinning) + runtime·atomicload(&runtime·sched.npidle) > 0)  // TODO: fast atomic
+			continue;
+		// Need to increment number of locked M's before the CAS.
+		// Otherwise the M from which we retake can exit the syscall,
+		// increment nmidle and report deadlock.
+		inclocked(-1);
+		if(runtime·cas(&p->status, s, Pidle)) {
+			n++;
+			handoffp(p);
+		}
+		inclocked(1);
+	}
+	return n;
+}
+
+// Put mp on midle list.
+// Sched must be locked.
+static void
+mput(M *mp)
+{
+	mp->schedlink = runtime·sched.midle;
+	runtime·sched.midle = mp;
+	runtime·sched.nmidle++;
+	checkdead();
+}
+
+// Try to get an m from midle list.
+// Sched must be locked.
+static M*
+mget(void)
+{
+	M *mp;
+
+	if((mp = runtime·sched.midle) != nil){
+		runtime·sched.midle = mp->schedlink;
+		runtime·sched.nmidle--;
+	}
+	return mp;
+}
+
+// Put gp on the global runnable queue.
+// Sched must be locked.
+static void
+globrunqput(G *gp)
+{
+	gp->schedlink = nil;
+	if(runtime·sched.runqtail)
+		runtime·sched.runqtail->schedlink = gp;
+	else
+		runtime·sched.runqhead = gp;
+	runtime·sched.runqtail = gp;
+	runtime·sched.runqsize++;
+}
+
+// Try get a batch of G's from the global runnable queue.
+// Sched must be locked.
+static G*
+globrunqget(P *p)
+{
+	G *gp, *gp1;
+	int32 n;
+
+	if(runtime·sched.runqsize == 0)
+		return nil;
+	n = runtime·sched.runqsize/runtime·gomaxprocs+1;
+	if(n > runtime·sched.runqsize)
+		n = runtime·sched.runqsize;
+	runtime·sched.runqsize -= n;
+	if(runtime·sched.runqsize == 0)
+		runtime·sched.runqtail = nil;
+	gp = runtime·sched.runqhead;
+	runtime·sched.runqhead = gp->schedlink;
+	n--;
+	while(n--) {
+		gp1 = runtime·sched.runqhead;
+		runtime·sched.runqhead = gp1->schedlink;
+		runqput(p, gp1);
+	}
+	return gp;
+}
+
+// Put p to on pidle list.
+// Sched must be locked.
+static void
+pidleput(P *p)
+{
+	p->link = runtime·sched.pidle;
+	runtime·sched.pidle = p;
+	runtime·xadd(&runtime·sched.npidle, 1);  // TODO: fast atomic
+}
+
+// Try get a p from pidle list.
+// Sched must be locked.
+static P*
+pidleget(void)
+{
+	P *p;
+
+	p = runtime·sched.pidle;
+	if(p) {
+		runtime·sched.pidle = p->link;
+		runtime·xadd(&runtime·sched.npidle, -1);  // TODO: fast atomic
+	}
+	return p;
+}
+
+// Put g on local runnable queue.
+// TODO(dvyukov): consider using lock-free queue.
+static void
+runqput(P *p, G *gp)
+{
+	int32 h, t, s;
+
+	runtime·lock(p);
+retry:
+	h = p->runqhead;
+	t = p->runqtail;
+	s = p->runqsize;
+	if(t == h-1 || (h == 0 && t == s-1)) {
+		runqgrow(p);
+		goto retry;
+	}
+	p->runq[t++] = gp;
+	if(t == s)
+		t = 0;
+	p->runqtail = t;
+	runtime·unlock(p);
+}
+
+// Get g from local runnable queue.
+static G*
+runqget(P *p)
+{
+	G *gp;
+	int32 t, h, s;
+
+	if(p->runqhead == p->runqtail)
+		return nil;
+	runtime·lock(p);
+	h = p->runqhead;
+	t = p->runqtail;
+	s = p->runqsize;
+	if(t == h) {
+		runtime·unlock(p);
+		return nil;
+	}
+	gp = p->runq[h++];
+	if(h == s)
+		h = 0;
+	p->runqhead = h;
+	runtime·unlock(p);
+	return gp;
+}
+
+// Grow local runnable queue.
+// TODO(dvyukov): consider using fixed-size array
+// and transfer excess to the global list (local queue can grow way too big).
+static void
+runqgrow(P *p)
+{
+	G **q;
+	int32 s, t, h, t2;
+
+	h = p->runqhead;
+	t = p->runqtail;
+	s = p->runqsize;
+	t2 = 0;
+	q = runtime·malloc(2*s*sizeof(*q));
+	while(t != h) {
+		q[t2++] = p->runq[h++];
+		if(h == s)
+			h = 0;
+	}
+	runtime·free(p->runq);
+	p->runq = q;
+	p->runqhead = 0;
+	p->runqtail = t2;
+	p->runqsize = 2*s;
+}
 
-	arg[0] = runtime·malloc(k.len + 1);
-	runtime·memmove(arg[0], k.str, k.len);
-	arg[0][k.len] = 0;
+// Steal half of elements from local runnable queue of p2
+// and put onto local runnable queue of p.
+// Returns one of the stolen elements (or nil if failed).
+static G*
+runqsteal(P *p, P *p2)
+{
+	G *gp, *gp1;
+	int32 t, h, s, t2, h2, s2, c, i;
+
+	if(p2->runqhead == p2->runqtail)
+		return nil;
+	// sort locks to prevent deadlocks
+	if(p < p2)
+		runtime·lock(p);
+	runtime·lock(p2);
+	if(p2->runqhead == p2->runqtail) {
+		runtime·unlock(p2);
+		if(p < p2)
+			runtime·unlock(p);
+		return nil;
+	}
+	if(p >= p2)
+		runtime·lock(p);
+	// now we've locked both queues and know the victim is not empty
+	h = p->runqhead;
+	t = p->runqtail;
+	s = p->runqsize;
+	h2 = p2->runqhead;
+	t2 = p2->runqtail;
+	s2 = p2->runqsize;
+	gp = p2->runq[h2++];  // return value
+	if(h2 == s2)
+		h2 = 0;
+	// steal roughly half
+	if(t2 > h2)
+		c = (t2 - h2) / 2;
+	else
+		c = (s2 - h2 + t2) / 2;
+	// copy
+	for(i = 0; i != c; i++) {
+		// the target queue is full?
+		if(t == h-1 || (h == 0 && t == s-1))
+			break;
+		// the victim queue is empty?
+		if(t2 == h2)
+			break;
+		gp1 = p2->runq[h2++];
+		if(h2 == s2)
+			h2 = 0;
+		p->runq[t++] = gp1;
+		if(t == s)
+			t = 0;
+	}
+	p->runqtail = t;
+	p2->runqhead = h2;
+	runtime·unlock(p2);
+	runtime·unlock(p);
+	return gp;
+}
 
-	arg[1] = runtime·malloc(v.len + 1);
-	runtime·memmove(arg[1], v.str, v.len);
-	arg[1][v.len] = 0;
+void
+runtime·testSchedLocalQueue(void)
+{
+	P p;
+	G gs[1000];
+	int32 i, j;
+
+	runtime·memclr((byte*)&p, sizeof(p));
+	p.runqsize = 1;
+	p.runqhead = 0;
+	p.runqtail = 0;
+	p.runq = runtime·malloc(p.runqsize*sizeof(*p.runq));
+
+	for(i = 0; i < nelem(gs); i++) {
+		if(runqget(&p) != nil)
+			runtime·throw("runq is not empty initially");
+		for(j = 0; j < i; j++)
+			runqput(&p, &gs[i]);
+		for(j = 0; j < i; j++) {
+			if(runqget(&p) != &gs[i]) {
+				runtime·printf("bad element at iter %d/%d\n", i, j);
+				runtime·throw("bad element");
+			}
+		}
+		if(runqget(&p) != nil)
+			runtime·throw("runq is not empty afterwards");
+	}
+}
 
-	runtime·asmcgocall((void*)libcgo_setenv, arg);
-	runtime·free(arg[0]);
-	runtime·free(arg[1]);
+void
+runtime·testSchedLocalQueueSteal(void)
+{
+	P p1, p2;
+	G gs[1000], *gp;
+	int32 i, j, s;
+
+	runtime·memclr((byte*)&p1, sizeof(p1));
+	p1.runqsize = 1;
+	p1.runqhead = 0;
+	p1.runqtail = 0;
+	p1.runq = runtime·malloc(p1.runqsize*sizeof(*p1.runq));
+
+	runtime·memclr((byte*)&p2, sizeof(p2));
+	p2.runqsize = nelem(gs);
+	p2.runqhead = 0;
+	p2.runqtail = 0;
+	p2.runq = runtime·malloc(p2.runqsize*sizeof(*p2.runq));
+
+	for(i = 0; i < nelem(gs); i++) {
+		for(j = 0; j < i; j++) {
+			gs[j].sig = 0;
+			runqput(&p1, &gs[j]);
+		}
+		gp = runqsteal(&p2, &p1);
+		s = 0;
+		if(gp) {
+			s++;
+			gp->sig++;
+		}
+		while(gp = runqget(&p2)) {
+			s++;
+			gp->sig++;
+		}
+		while(gp = runqget(&p1))
+			gp->sig++;
+		for(j = 0; j < i; j++) {
+			if(gs[j].sig != 1) {
+				runtime·printf("bad element %d(%d) at iter %d\n", j, gs[j].sig, i);
+				runtime·throw("bad element");
+			}
+		}
+		if(s != i/2 && s != i/2+1) {
+			runtime·printf("bad steal %d, want %d or %d, iter %d\n",
+				s, i/2, i/2+1, i);
+			runtime·throw("bad steal");
+		}
+	}
 }
+
diff --git a/src/pkg/runtime/proc_test.go b/src/pkg/runtime/proc_test.go
index 3211108..21fb9c2 100644
--- a/src/pkg/runtime/proc_test.go
+++ b/src/pkg/runtime/proc_test.go
@@ -5,9 +5,11 @@
 package runtime_test
 
 import (
+	"math"
 	"runtime"
 	"sync/atomic"
 	"testing"
+	"time"
 )
 
 var stop = make(chan bool, 1)
@@ -22,8 +24,7 @@ func perpetuumMobile() {
 
 func TestStopTheWorldDeadlock(t *testing.T) {
 	if testing.Short() {
-		t.Logf("skipping during short test")
-		return
+		t.Skip("skipping during short test")
 	}
 	maxprocs := runtime.GOMAXPROCS(3)
 	compl := make(chan bool, 2)
@@ -46,6 +47,66 @@ func TestStopTheWorldDeadlock(t *testing.T) {
 	runtime.GOMAXPROCS(maxprocs)
 }
 
+func TestYieldProgress(t *testing.T) {
+	testYieldProgress(t, false)
+}
+
+func TestYieldLockedProgress(t *testing.T) {
+	testYieldProgress(t, true)
+}
+
+func testYieldProgress(t *testing.T, locked bool) {
+	c := make(chan bool)
+	cack := make(chan bool)
+	go func() {
+		if locked {
+			runtime.LockOSThread()
+		}
+		for {
+			select {
+			case <-c:
+				cack <- true
+				return
+			default:
+				runtime.Gosched()
+			}
+		}
+	}()
+	time.Sleep(10 * time.Millisecond)
+	c <- true
+	<-cack
+}
+
+func TestYieldLocked(t *testing.T) {
+	const N = 10
+	c := make(chan bool)
+	go func() {
+		runtime.LockOSThread()
+		for i := 0; i < N; i++ {
+			runtime.Gosched()
+			time.Sleep(time.Millisecond)
+		}
+		c <- true
+		// runtime.UnlockOSThread() is deliberately omitted
+	}()
+	<-c
+}
+
+func TestBlockLocked(t *testing.T) {
+	const N = 10
+	c := make(chan bool)
+	go func() {
+		runtime.LockOSThread()
+		for i := 0; i < N; i++ {
+			c <- true
+		}
+		runtime.UnlockOSThread()
+	}()
+	for i := 0; i < N; i++ {
+		<-c
+	}
+}
+
 func stackGrowthRecursive(i int) {
 	var pad [128]uint64
 	if i != 0 && pad[0] == 0 {
@@ -53,7 +114,15 @@ func stackGrowthRecursive(i int) {
 	}
 }
 
-func BenchmarkStackGrowth(b *testing.B) {
+func TestSchedLocalQueue(t *testing.T) {
+	runtime.TestSchedLocalQueue1()
+}
+
+func TestSchedLocalQueueSteal(t *testing.T) {
+	runtime.TestSchedLocalQueueSteal1()
+}
+
+func benchmarkStackGrowth(b *testing.B, rec int) {
 	const CallsPerSched = 1000
 	procs := runtime.GOMAXPROCS(-1)
 	N := int32(b.N / CallsPerSched)
@@ -63,7 +132,7 @@ func BenchmarkStackGrowth(b *testing.B) {
 			for atomic.AddInt32(&N, -1) >= 0 {
 				runtime.Gosched()
 				for g := 0; g < CallsPerSched; g++ {
-					stackGrowthRecursive(10)
+					stackGrowthRecursive(rec)
 				}
 			}
 			c <- true
@@ -74,32 +143,33 @@ func BenchmarkStackGrowth(b *testing.B) {
 	}
 }
 
+func BenchmarkStackGrowth(b *testing.B) {
+	benchmarkStackGrowth(b, 10)
+}
+
+func BenchmarkStackGrowthDeep(b *testing.B) {
+	benchmarkStackGrowth(b, 1024)
+}
+
 func BenchmarkSyscall(b *testing.B) {
-	const CallsPerSched = 1000
-	procs := runtime.GOMAXPROCS(-1)
-	N := int32(b.N / CallsPerSched)
-	c := make(chan bool, procs)
-	for p := 0; p < procs; p++ {
-		go func() {
-			for atomic.AddInt32(&N, -1) >= 0 {
-				runtime.Gosched()
-				for g := 0; g < CallsPerSched; g++ {
-					runtime.Entersyscall()
-					runtime.Exitsyscall()
-				}
-			}
-			c <- true
-		}()
-	}
-	for p := 0; p < procs; p++ {
-		<-c
-	}
+	benchmarkSyscall(b, 0, 1)
 }
 
 func BenchmarkSyscallWork(b *testing.B) {
+	benchmarkSyscall(b, 100, 1)
+}
+
+func BenchmarkSyscallExcess(b *testing.B) {
+	benchmarkSyscall(b, 0, 4)
+}
+
+func BenchmarkSyscallExcessWork(b *testing.B) {
+	benchmarkSyscall(b, 100, 4)
+}
+
+func benchmarkSyscall(b *testing.B, work, excess int) {
 	const CallsPerSched = 1000
-	const LocalWork = 100
-	procs := runtime.GOMAXPROCS(-1)
+	procs := runtime.GOMAXPROCS(-1) * excess
 	N := int32(b.N / CallsPerSched)
 	c := make(chan bool, procs)
 	for p := 0; p < procs; p++ {
@@ -109,7 +179,7 @@ func BenchmarkSyscallWork(b *testing.B) {
 				runtime.Gosched()
 				for g := 0; g < CallsPerSched; g++ {
 					runtime.Entersyscall()
-					for i := 0; i < LocalWork; i++ {
+					for i := 0; i < work; i++ {
 						foo *= 2
 						foo /= 2
 					}
@@ -123,3 +193,93 @@ func BenchmarkSyscallWork(b *testing.B) {
 		<-c
 	}
 }
+
+func BenchmarkCreateGoroutines(b *testing.B) {
+	benchmarkCreateGoroutines(b, 1)
+}
+
+func BenchmarkCreateGoroutinesParallel(b *testing.B) {
+	benchmarkCreateGoroutines(b, runtime.GOMAXPROCS(-1))
+}
+
+func benchmarkCreateGoroutines(b *testing.B, procs int) {
+	c := make(chan bool)
+	var f func(n int)
+	f = func(n int) {
+		if n == 0 {
+			c <- true
+			return
+		}
+		go f(n - 1)
+	}
+	for i := 0; i < procs; i++ {
+		go f(b.N / procs)
+	}
+	for i := 0; i < procs; i++ {
+		<-c
+	}
+}
+
+type Matrix [][]float64
+
+func BenchmarkMatmult(b *testing.B) {
+	b.StopTimer()
+	// matmult is O(N**3) but testing expects O(b.N),
+	// so we need to take cube root of b.N
+	n := int(math.Cbrt(float64(b.N))) + 1
+	A := makeMatrix(n)
+	B := makeMatrix(n)
+	C := makeMatrix(n)
+	b.StartTimer()
+	matmult(nil, A, B, C, 0, n, 0, n, 0, n, 8)
+}
+
+func makeMatrix(n int) Matrix {
+	m := make(Matrix, n)
+	for i := 0; i < n; i++ {
+		m[i] = make([]float64, n)
+		for j := 0; j < n; j++ {
+			m[i][j] = float64(i*n + j)
+		}
+	}
+	return m
+}
+
+func matmult(done chan<- struct{}, A, B, C Matrix, i0, i1, j0, j1, k0, k1, threshold int) {
+	di := i1 - i0
+	dj := j1 - j0
+	dk := k1 - k0
+	if di >= dj && di >= dk && di >= threshold {
+		// divide in two by y axis
+		mi := i0 + di/2
+		done1 := make(chan struct{}, 1)
+		go matmult(done1, A, B, C, i0, mi, j0, j1, k0, k1, threshold)
+		matmult(nil, A, B, C, mi, i1, j0, j1, k0, k1, threshold)
+		<-done1
+	} else if dj >= dk && dj >= threshold {
+		// divide in two by x axis
+		mj := j0 + dj/2
+		done1 := make(chan struct{}, 1)
+		go matmult(done1, A, B, C, i0, i1, j0, mj, k0, k1, threshold)
+		matmult(nil, A, B, C, i0, i1, mj, j1, k0, k1, threshold)
+		<-done1
+	} else if dk >= threshold {
+		// divide in two by "k" axis
+		// deliberately not parallel because of data races
+		mk := k0 + dk/2
+		matmult(nil, A, B, C, i0, i1, j0, j1, k0, mk, threshold)
+		matmult(nil, A, B, C, i0, i1, j0, j1, mk, k1, threshold)
+	} else {
+		// the matrices are small enough, compute directly
+		for i := i0; i < i1; i++ {
+			for j := j0; j < j1; j++ {
+				for k := k0; k < k1; k++ {
+					C[i][j] += A[i][k] * B[k][j]
+				}
+			}
+		}
+	}
+	if done != nil {
+		done <- struct{}{}
+	}
+}
diff --git a/src/pkg/runtime/race.c b/src/pkg/runtime/race.c
new file mode 100644
index 0000000..cfd9704
--- /dev/null
+++ b/src/pkg/runtime/race.c
@@ -0,0 +1,350 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Implementation of the race detector API.
+// +build race
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
+#include "race.h"
+
+void runtime∕race·Initialize(uintptr *racectx);
+void runtime∕race·MapShadow(void *addr, uintptr size);
+void runtime∕race·Finalize(void);
+void runtime∕race·FinalizerGoroutine(uintptr racectx);
+void runtime∕race·Read(uintptr racectx, void *addr, void *pc);
+void runtime∕race·Write(uintptr racectx, void *addr, void *pc);
+void runtime∕race·ReadRange(uintptr racectx, void *addr, uintptr sz, uintptr step, void *pc);
+void runtime∕race·WriteRange(uintptr racectx, void *addr, uintptr sz, uintptr step, void *pc);
+void runtime∕race·FuncEnter(uintptr racectx, void *pc);
+void runtime∕race·FuncExit(uintptr racectx);
+void runtime∕race·Malloc(uintptr racectx, void *p, uintptr sz, void *pc);
+void runtime∕race·Free(void *p);
+void runtime∕race·GoStart(uintptr racectx, uintptr *chracectx, void *pc);
+void runtime∕race·GoEnd(uintptr racectx);
+void runtime∕race·Acquire(uintptr racectx, void *addr);
+void runtime∕race·Release(uintptr racectx, void *addr);
+void runtime∕race·ReleaseMerge(uintptr racectx, void *addr);
+
+extern byte noptrdata[];
+extern byte enoptrbss[];
+
+static bool onstack(uintptr argp);
+
+uintptr
+runtime·raceinit(void)
+{
+	uintptr racectx;
+
+	m->racecall = true;
+	runtime∕race·Initialize(&racectx);
+	runtime∕race·MapShadow(noptrdata, enoptrbss - noptrdata);
+	m->racecall = false;
+	return racectx;
+}
+
+void
+runtime·racefini(void)
+{
+	m->racecall = true;
+	runtime∕race·Finalize();
+	m->racecall = false;
+}
+
+void
+runtime·racemapshadow(void *addr, uintptr size)
+{
+	m->racecall = true;
+	runtime∕race·MapShadow(addr, size);
+	m->racecall = false;
+}
+
+// Called from instrumented code.
+// If we split stack, getcallerpc() can return runtime·lessstack().
+#pragma textflag 7
+void
+runtime·racewrite(uintptr addr)
+{
+	if(!onstack(addr)) {
+		m->racecall = true;
+		runtime∕race·Write(g->racectx, (void*)addr, runtime·getcallerpc(&addr));
+		m->racecall = false;
+	}
+}
+
+// Called from instrumented code.
+// If we split stack, getcallerpc() can return runtime·lessstack().
+#pragma textflag 7
+void
+runtime·raceread(uintptr addr)
+{
+	if(!onstack(addr)) {
+		m->racecall = true;
+		runtime∕race·Read(g->racectx, (void*)addr, runtime·getcallerpc(&addr));
+		m->racecall = false;
+	}
+}
+
+// Called from runtime·racefuncenter (assembly).
+#pragma textflag 7
+void
+runtime·racefuncenter1(uintptr pc)
+{
+	// If the caller PC is lessstack, use slower runtime·callers
+	// to walk across the stack split to find the real caller.
+	if(pc == (uintptr)runtime·lessstack)
+		runtime·callers(2, &pc, 1);
+
+	m->racecall = true;
+	runtime∕race·FuncEnter(g->racectx, (void*)pc);
+	m->racecall = false;
+}
+
+// Called from instrumented code.
+#pragma textflag 7
+void
+runtime·racefuncexit(void)
+{
+	m->racecall = true;
+	runtime∕race·FuncExit(g->racectx);
+	m->racecall = false;
+}
+
+void
+runtime·racemalloc(void *p, uintptr sz, void *pc)
+{
+	// use m->curg because runtime·stackalloc() is called from g0
+	if(m->curg == nil)
+		return;
+	m->racecall = true;
+	runtime∕race·Malloc(m->curg->racectx, p, sz, pc);
+	m->racecall = false;
+}
+
+void
+runtime·racefree(void *p)
+{
+	m->racecall = true;
+	runtime∕race·Free(p);
+	m->racecall = false;
+}
+
+uintptr
+runtime·racegostart(void *pc)
+{
+	uintptr racectx;
+
+	m->racecall = true;
+	runtime∕race·GoStart(g->racectx, &racectx, pc);
+	m->racecall = false;
+	return racectx;
+}
+
+void
+runtime·racegoend(void)
+{
+	m->racecall = true;
+	runtime∕race·GoEnd(g->racectx);
+	m->racecall = false;
+}
+
+static void
+memoryaccess(void *addr, uintptr callpc, uintptr pc, bool write)
+{
+	uintptr racectx;
+
+	if(!onstack((uintptr)addr)) {
+		m->racecall = true;
+		racectx = g->racectx;
+		if(callpc) {
+			if(callpc == (uintptr)runtime·lessstack)
+				runtime·callers(3, &callpc, 1);
+			runtime∕race·FuncEnter(racectx, (void*)callpc);
+		}
+		if(write)
+			runtime∕race·Write(racectx, addr, (void*)pc);
+		else
+			runtime∕race·Read(racectx, addr, (void*)pc);
+		if(callpc)
+			runtime∕race·FuncExit(racectx);
+		m->racecall = false;
+	}
+}
+
+void
+runtime·racewritepc(void *addr, void *callpc, void *pc)
+{
+	memoryaccess(addr, (uintptr)callpc, (uintptr)pc, true);
+}
+
+void
+runtime·racereadpc(void *addr, void *callpc, void *pc)
+{
+	memoryaccess(addr, (uintptr)callpc, (uintptr)pc, false);
+}
+
+static void
+rangeaccess(void *addr, uintptr size, uintptr step, uintptr callpc, uintptr pc, bool write)
+{
+	uintptr racectx;
+
+	if(!onstack((uintptr)addr)) {
+		m->racecall = true;
+		racectx = g->racectx;
+		if(callpc) {
+			if(callpc == (uintptr)runtime·lessstack)
+				runtime·callers(3, &callpc, 1);
+			runtime∕race·FuncEnter(racectx, (void*)callpc);
+		}
+		if(write)
+			runtime∕race·WriteRange(racectx, addr, size, step, (void*)pc);
+		else
+			runtime∕race·ReadRange(racectx, addr, size, step, (void*)pc);
+		if(callpc)
+			runtime∕race·FuncExit(racectx);
+		m->racecall = false;
+	}
+}
+
+void
+runtime·racewriterangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc)
+{
+	rangeaccess(addr, sz, step, (uintptr)callpc, (uintptr)pc, true);
+}
+
+void
+runtime·racereadrangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc)
+{
+	rangeaccess(addr, sz, step, (uintptr)callpc, (uintptr)pc, false);
+}
+
+void
+runtime·raceacquire(void *addr)
+{
+	runtime·raceacquireg(g, addr);
+}
+
+void
+runtime·raceacquireg(G *gp, void *addr)
+{
+	if(g->raceignore)
+		return;
+	m->racecall = true;
+	runtime∕race·Acquire(gp->racectx, addr);
+	m->racecall = false;
+}
+
+void
+runtime·racerelease(void *addr)
+{
+	runtime·racereleaseg(g, addr);
+}
+
+void
+runtime·racereleaseg(G *gp, void *addr)
+{
+	if(g->raceignore)
+		return;
+	m->racecall = true;
+	runtime∕race·Release(gp->racectx, addr);
+	m->racecall = false;
+}
+
+void
+runtime·racereleasemerge(void *addr)
+{
+	runtime·racereleasemergeg(g, addr);
+}
+
+void
+runtime·racereleasemergeg(G *gp, void *addr)
+{
+	if(g->raceignore)
+		return;
+	m->racecall = true;
+	runtime∕race·ReleaseMerge(gp->racectx, addr);
+	m->racecall = false;
+}
+
+void
+runtime·racefingo(void)
+{
+	m->racecall = true;
+	runtime∕race·FinalizerGoroutine(g->racectx);
+	m->racecall = false;
+}
+
+// func RaceAcquire(addr unsafe.Pointer)
+void
+runtime·RaceAcquire(void *addr)
+{
+	runtime·raceacquire(addr);
+}
+
+// func RaceRelease(addr unsafe.Pointer)
+void
+runtime·RaceRelease(void *addr)
+{
+	runtime·racerelease(addr);
+}
+
+// func RaceReleaseMerge(addr unsafe.Pointer)
+void
+runtime·RaceReleaseMerge(void *addr)
+{
+	runtime·racereleasemerge(addr);
+}
+
+// func RaceSemacquire(s *uint32)
+void runtime·RaceSemacquire(uint32 *s)
+{
+	runtime·semacquire(s);
+}
+
+// func RaceSemrelease(s *uint32)
+void runtime·RaceSemrelease(uint32 *s)
+{
+	runtime·semrelease(s);
+}
+
+// func RaceRead(addr unsafe.Pointer)
+#pragma textflag 7
+void
+runtime·RaceRead(void *addr)
+{
+	memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), false);
+}
+
+// func RaceWrite(addr unsafe.Pointer)
+#pragma textflag 7
+void
+runtime·RaceWrite(void *addr)
+{
+	memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), true);
+}
+
+// func RaceDisable()
+void runtime·RaceDisable(void)
+{
+	g->raceignore++;
+}
+
+// func RaceEnable()
+void runtime·RaceEnable(void)
+{
+	g->raceignore--;
+}
+
+static bool
+onstack(uintptr argp)
+{
+	// noptrdata, data, bss, noptrbss
+	// the layout is in ../../cmd/ld/data.c
+	if((byte*)argp >= noptrdata && (byte*)argp < enoptrbss)
+		return false;
+	if((byte*)argp >= runtime·mheap->arena_start && (byte*)argp < runtime·mheap->arena_used)
+		return false;
+	return true;
+}
diff --git a/src/pkg/runtime/race.go b/src/pkg/runtime/race.go
new file mode 100644
index 0000000..1d64ba3
--- /dev/null
+++ b/src/pkg/runtime/race.go
@@ -0,0 +1,29 @@
+// 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 RaceSemacquire(s *uint32)
+func RaceSemrelease(s *uint32)
diff --git a/src/pkg/runtime/race.h b/src/pkg/runtime/race.h
new file mode 100644
index 0000000..432a8a9
--- /dev/null
+++ b/src/pkg/runtime/race.h
@@ -0,0 +1,33 @@
+// 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.
+
+// Definitions related to data race detection.
+
+#ifdef RACE
+enum { raceenabled = 1 };
+#else
+enum { raceenabled = 0 };
+#endif
+
+// Initialize race detection subsystem.
+uintptr	runtime·raceinit(void);
+// Finalize race detection subsystem, does not return.
+void	runtime·racefini(void);
+
+void	runtime·racemapshadow(void *addr, uintptr size);
+void	runtime·racemalloc(void *p, uintptr sz, void *pc);
+void	runtime·racefree(void *p);
+uintptr	runtime·racegostart(void *pc);
+void	runtime·racegoend(void);
+void	runtime·racewritepc(void *addr, void *callpc, void *pc);
+void	runtime·racereadpc(void *addr, void *callpc, void *pc);
+void	runtime·racewriterangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc);
+void	runtime·racereadrangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc);
+void	runtime·racefingo(void);
+void	runtime·raceacquire(void *addr);
+void	runtime·raceacquireg(G *gp, void *addr);
+void	runtime·racerelease(void *addr);
+void	runtime·racereleaseg(G *gp, void *addr);
+void	runtime·racereleasemerge(void *addr);
+void	runtime·racereleasemergeg(G *gp, void *addr);
diff --git a/src/pkg/runtime/race/README b/src/pkg/runtime/race/README
new file mode 100644
index 0000000..8bedb09
--- /dev/null
+++ b/src/pkg/runtime/race/README
@@ -0,0 +1,11 @@
+runtime/race package contains the data race detector runtime library.
+It is based on ThreadSanitizer race detector, that is currently a part of
+the LLVM project.
+
+To update the .syso files you need to:
+$ svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk
+$ cd compiler-rt/lib/tsan/go
+$ ./buildgo.sh
+
+Tested with gcc 4.6.1 and 4.7.0.  On Windows it's built with 64-bit MinGW.
+
diff --git a/src/pkg/runtime/race/race.go b/src/pkg/runtime/race/race.go
new file mode 100644
index 0000000..b0a5c9a
--- /dev/null
+++ b/src/pkg/runtime/race/race.go
@@ -0,0 +1,122 @@
+// 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,linux,amd64 race,darwin,amd64 race,windows,amd64
+
+// Package race provides low-level facilities for data race detection.
+package race
+
+/*
+void __tsan_init(void **racectx);
+void __tsan_fini(void);
+void __tsan_map_shadow(void *addr, void *size);
+void __tsan_go_start(void *racectx, void **chracectx, void *pc);
+void __tsan_go_end(void *racectx);
+void __tsan_read(void *racectx, void *addr, void *pc);
+void __tsan_write(void *racectx, void *addr, void *pc);
+void __tsan_read_range(void *racectx, void *addr, long sz, long step, void *pc);
+void __tsan_write_range(void *racectx, void *addr, long sz, long step, void *pc);
+void __tsan_func_enter(void *racectx, void *pc);
+void __tsan_func_exit(void *racectx);
+void __tsan_malloc(void *racectx, void *p, long sz, void *pc);
+void __tsan_free(void *p);
+void __tsan_acquire(void *racectx, void *addr);
+void __tsan_release(void *racectx, void *addr);
+void __tsan_release_merge(void *racectx, void *addr);
+void __tsan_finalizer_goroutine(void *racectx);
+*/
+import "C"
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+func Initialize(racectx *uintptr) {
+	C.__tsan_init((*unsafe.Pointer)(unsafe.Pointer(racectx)))
+}
+
+func Finalize() {
+	C.__tsan_fini()
+}
+
+func MapShadow(addr, size uintptr) {
+	C.__tsan_map_shadow(unsafe.Pointer(addr), unsafe.Pointer(size))
+}
+
+func FinalizerGoroutine(racectx uintptr) {
+	C.__tsan_finalizer_goroutine(unsafe.Pointer(racectx))
+}
+
+func Read(racectx uintptr, addr, pc uintptr) {
+	C.__tsan_read(unsafe.Pointer(racectx), unsafe.Pointer(addr), unsafe.Pointer(pc))
+}
+
+func Write(racectx uintptr, addr, pc uintptr) {
+	C.__tsan_write(unsafe.Pointer(racectx), unsafe.Pointer(addr), unsafe.Pointer(pc))
+}
+
+func ReadRange(racectx uintptr, addr, sz, step, pc uintptr) {
+	C.__tsan_read_range(unsafe.Pointer(racectx), unsafe.Pointer(addr),
+		C.long(sz), C.long(step), unsafe.Pointer(pc))
+}
+
+func WriteRange(racectx uintptr, addr, sz, step, pc uintptr) {
+	C.__tsan_write_range(unsafe.Pointer(racectx), unsafe.Pointer(addr),
+		C.long(sz), C.long(step), unsafe.Pointer(pc))
+}
+
+func FuncEnter(racectx uintptr, pc uintptr) {
+	C.__tsan_func_enter(unsafe.Pointer(racectx), unsafe.Pointer(pc))
+}
+
+func FuncExit(racectx uintptr) {
+	C.__tsan_func_exit(unsafe.Pointer(racectx))
+}
+
+func Malloc(racectx uintptr, p, sz, pc uintptr) {
+	C.__tsan_malloc(unsafe.Pointer(racectx), unsafe.Pointer(p), C.long(sz), unsafe.Pointer(pc))
+}
+
+func Free(p uintptr) {
+	C.__tsan_free(unsafe.Pointer(p))
+}
+
+func GoStart(racectx uintptr, chracectx *uintptr, pc uintptr) {
+	C.__tsan_go_start(unsafe.Pointer(racectx), (*unsafe.Pointer)(unsafe.Pointer(chracectx)), unsafe.Pointer(pc))
+}
+
+func GoEnd(racectx uintptr) {
+	C.__tsan_go_end(unsafe.Pointer(racectx))
+}
+
+func Acquire(racectx uintptr, addr uintptr) {
+	C.__tsan_acquire(unsafe.Pointer(racectx), unsafe.Pointer(addr))
+}
+
+func Release(racectx uintptr, addr uintptr) {
+	C.__tsan_release(unsafe.Pointer(racectx), unsafe.Pointer(addr))
+}
+
+func ReleaseMerge(racectx uintptr, addr uintptr) {
+	C.__tsan_release_merge(unsafe.Pointer(racectx), unsafe.Pointer(addr))
+}
+
+//export __tsan_symbolize
+func __tsan_symbolize(pc uintptr, fun, file **C.char, line, off *C.int) C.int {
+	f := runtime.FuncForPC(pc)
+	if f == nil {
+		*fun = C.CString("??")
+		*file = C.CString("-")
+		*line = 0
+		*off = C.int(pc)
+		return 1
+	}
+	fi, l := f.FileLine(pc)
+	*fun = C.CString(f.Name())
+	*file = C.CString(fi)
+	*line = C.int(l)
+	*off = C.int(pc - f.Entry())
+	return 1
+}
diff --git a/src/pkg/runtime/race/race_darwin_amd64.syso b/src/pkg/runtime/race/race_darwin_amd64.syso
new file mode 100644
index 0000000..24a0049
Binary files /dev/null and b/src/pkg/runtime/race/race_darwin_amd64.syso differ
diff --git a/src/pkg/runtime/race/race_linux_amd64.syso b/src/pkg/runtime/race/race_linux_amd64.syso
new file mode 100644
index 0000000..b15091b
Binary files /dev/null and b/src/pkg/runtime/race/race_linux_amd64.syso differ
diff --git a/src/pkg/runtime/race/race_test.go b/src/pkg/runtime/race/race_test.go
new file mode 100644
index 0000000..c77569c
--- /dev/null
+++ b/src/pkg/runtime/race/race_test.go
@@ -0,0 +1,157 @@
+// 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
+
+// This program is used to verify the race detector
+// by running the tests and parsing their output.
+// It does not check stack correctness, completeness or anything else:
+// it merely verifies that if a test is expected to be racy
+// then the race is detected.
+package race_test
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"testing"
+)
+
+var (
+	passedTests = 0
+	totalTests  = 0
+	falsePos    = 0
+	falseNeg    = 0
+	failingPos  = 0
+	failingNeg  = 0
+	failed      = false
+)
+
+const (
+	visibleLen = 40
+	testPrefix = "=== RUN Test"
+)
+
+func TestRace(t *testing.T) {
+	testOutput, err := runTests()
+	if err != nil {
+		t.Fatalf("Failed to run tests: %v\n%v", err, string(testOutput))
+	}
+	reader := bufio.NewReader(bytes.NewBuffer(testOutput))
+
+	funcName := ""
+	var tsanLog []string
+	for {
+		s, err := nextLine(reader)
+		if err != nil {
+			fmt.Printf("%s\n", processLog(funcName, tsanLog))
+			break
+		}
+		if strings.HasPrefix(s, testPrefix) {
+			fmt.Printf("%s\n", processLog(funcName, tsanLog))
+			tsanLog = make([]string, 0, 100)
+			funcName = s[len(testPrefix):]
+		} else {
+			tsanLog = append(tsanLog, s)
+		}
+	}
+
+	fmt.Printf("\nPassed %d of %d tests (%.02f%%, %d+, %d-)\n",
+		passedTests, totalTests, 100*float64(passedTests)/float64(totalTests), falsePos, falseNeg)
+	fmt.Printf("%d expected failures (%d has not fail)\n", failingPos+failingNeg, failingNeg)
+	if failed {
+		t.Fail()
+	}
+}
+
+// nextLine is a wrapper around bufio.Reader.ReadString.
+// It reads a line up to the next '\n' character. Error
+// is non-nil if there are no lines left, and nil
+// otherwise.
+func nextLine(r *bufio.Reader) (string, error) {
+	s, err := r.ReadString('\n')
+	if err != nil {
+		if err != io.EOF {
+			log.Fatalf("nextLine: expected EOF, received %v", err)
+		}
+		return s, err
+	}
+	return s[:len(s)-1], nil
+}
+
+// processLog verifies whether the given ThreadSanitizer's log
+// contains a race report, checks this information against
+// the name of the testcase and returns the result of this
+// comparison.
+func processLog(testName string, tsanLog []string) string {
+	if !strings.HasPrefix(testName, "Race") && !strings.HasPrefix(testName, "NoRace") {
+		return ""
+	}
+	gotRace := false
+	for _, s := range tsanLog {
+		if strings.Contains(s, "DATA RACE") {
+			gotRace = true
+			break
+		}
+	}
+
+	failing := strings.Contains(testName, "Failing")
+	expRace := !strings.HasPrefix(testName, "No")
+	for len(testName) < visibleLen {
+		testName += " "
+	}
+	if expRace == gotRace {
+		passedTests++
+		totalTests++
+		if failing {
+			failed = true
+			failingNeg++
+		}
+		return fmt.Sprintf("%s .", testName)
+	}
+	pos := ""
+	if expRace {
+		falseNeg++
+	} else {
+		falsePos++
+		pos = "+"
+	}
+	if failing {
+		failingPos++
+	} else {
+		failed = true
+	}
+	totalTests++
+	return fmt.Sprintf("%s %s%s", testName, "FAILED", pos)
+}
+
+// runTests assures that the package and its dependencies is
+// built with instrumentation enabled and returns the output of 'go test'
+// which includes possible data race reports from ThreadSanitizer.
+func runTests() ([]byte, error) {
+	tests, err := filepath.Glob("./testdata/*_test.go")
+	if err != nil {
+		return nil, err
+	}
+	args := []string{"test", "-race", "-v"}
+	args = append(args, tests...)
+	cmd := exec.Command("go", args...)
+	// The following flags turn off heuristics that suppress seemingly identical reports.
+	// It is required because the tests contain a lot of data races on the same addresses
+	// (the tests are simple and the memory is constantly reused).
+	for _, env := range os.Environ() {
+		if strings.HasPrefix(env, "GOMAXPROCS=") {
+			continue
+		}
+		cmd.Env = append(cmd.Env, env)
+	}
+	cmd.Env = append(cmd.Env, `GORACE="suppress_equal_stacks=0 suppress_equal_addresses=0 exitcode=0"`)
+	return cmd.CombinedOutput()
+}
diff --git a/src/pkg/runtime/race/race_windows_amd64.syso b/src/pkg/runtime/race/race_windows_amd64.syso
new file mode 100644
index 0000000..0a3a583
Binary files /dev/null and b/src/pkg/runtime/race/race_windows_amd64.syso differ
diff --git a/src/pkg/runtime/race/testdata/atomic_test.go b/src/pkg/runtime/race/testdata/atomic_test.go
new file mode 100644
index 0000000..0c5c2c0
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/atomic_test.go
@@ -0,0 +1,271 @@
+// 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 race_test
+
+import (
+	"runtime"
+	"sync/atomic"
+	"testing"
+	"unsafe"
+)
+
+func TestNoRaceAtomicAddInt64(t *testing.T) {
+	var x1, x2 int8
+	var s int64
+	ch := make(chan bool, 2)
+	go func() {
+		x1 = 1
+		if atomic.AddInt64(&s, 1) == 2 {
+			x2 = 1
+		}
+		ch <- true
+	}()
+	go func() {
+		x2 = 1
+		if atomic.AddInt64(&s, 1) == 2 {
+			x1 = 1
+		}
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestRaceAtomicAddInt64(t *testing.T) {
+	var x1, x2 int8
+	var s int64
+	ch := make(chan bool, 2)
+	go func() {
+		x1 = 1
+		if atomic.AddInt64(&s, 1) == 1 {
+			x2 = 1
+		}
+		ch <- true
+	}()
+	go func() {
+		x2 = 1
+		if atomic.AddInt64(&s, 1) == 1 {
+			x1 = 1
+		}
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestNoRaceAtomicAddInt32(t *testing.T) {
+	var x1, x2 int8
+	var s int32
+	ch := make(chan bool, 2)
+	go func() {
+		x1 = 1
+		if atomic.AddInt32(&s, 1) == 2 {
+			x2 = 1
+		}
+		ch <- true
+	}()
+	go func() {
+		x2 = 1
+		if atomic.AddInt32(&s, 1) == 2 {
+			x1 = 1
+		}
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestNoRaceAtomicLoadAddInt32(t *testing.T) {
+	var x int64
+	var s int32
+	go func() {
+		x = 2
+		atomic.AddInt32(&s, 1)
+	}()
+	for atomic.LoadInt32(&s) != 1 {
+		runtime.Gosched()
+	}
+	x = 1
+}
+
+func TestNoRaceAtomicLoadStoreInt32(t *testing.T) {
+	var x int64
+	var s int32
+	go func() {
+		x = 2
+		atomic.StoreInt32(&s, 1)
+	}()
+	for atomic.LoadInt32(&s) != 1 {
+		runtime.Gosched()
+	}
+	x = 1
+}
+
+func TestNoRaceAtomicStoreCASInt32(t *testing.T) {
+	var x int64
+	var s int32
+	go func() {
+		x = 2
+		atomic.StoreInt32(&s, 1)
+	}()
+	for !atomic.CompareAndSwapInt32(&s, 1, 0) {
+		runtime.Gosched()
+	}
+	x = 1
+}
+
+func TestNoRaceAtomicCASLoadInt32(t *testing.T) {
+	var x int64
+	var s int32
+	go func() {
+		x = 2
+		if !atomic.CompareAndSwapInt32(&s, 0, 1) {
+			panic("")
+		}
+	}()
+	for atomic.LoadInt32(&s) != 1 {
+		runtime.Gosched()
+	}
+	x = 1
+}
+
+func TestNoRaceAtomicCASCASInt32(t *testing.T) {
+	var x int64
+	var s int32
+	go func() {
+		x = 2
+		if !atomic.CompareAndSwapInt32(&s, 0, 1) {
+			panic("")
+		}
+	}()
+	for !atomic.CompareAndSwapInt32(&s, 1, 0) {
+		runtime.Gosched()
+	}
+	x = 1
+}
+
+func TestNoRaceAtomicCASCASInt32_2(t *testing.T) {
+	var x1, x2 int8
+	var s int32
+	ch := make(chan bool, 2)
+	go func() {
+		x1 = 1
+		if !atomic.CompareAndSwapInt32(&s, 0, 1) {
+			x2 = 1
+		}
+		ch <- true
+	}()
+	go func() {
+		x2 = 1
+		if !atomic.CompareAndSwapInt32(&s, 0, 1) {
+			x1 = 1
+		}
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestNoRaceAtomicLoadInt64(t *testing.T) {
+	var x int32
+	var s int64
+	go func() {
+		x = 2
+		atomic.AddInt64(&s, 1)
+	}()
+	for atomic.LoadInt64(&s) != 1 {
+		runtime.Gosched()
+	}
+	x = 1
+}
+
+func TestNoRaceAtomicCASCASUInt64(t *testing.T) {
+	var x int64
+	var s uint64
+	go func() {
+		x = 2
+		if !atomic.CompareAndSwapUint64(&s, 0, 1) {
+			panic("")
+		}
+	}()
+	for !atomic.CompareAndSwapUint64(&s, 1, 0) {
+		runtime.Gosched()
+	}
+	x = 1
+}
+
+func TestNoRaceAtomicLoadStorePointer(t *testing.T) {
+	var x int64
+	var s unsafe.Pointer
+	var y int = 2
+	var p unsafe.Pointer = unsafe.Pointer(&y)
+	go func() {
+		x = 2
+		atomic.StorePointer(&s, p)
+	}()
+	for atomic.LoadPointer(&s) != p {
+		runtime.Gosched()
+	}
+	x = 1
+}
+
+func TestNoRaceAtomicStoreCASUint64(t *testing.T) {
+	var x int64
+	var s uint64
+	go func() {
+		x = 2
+		atomic.StoreUint64(&s, 1)
+	}()
+	for !atomic.CompareAndSwapUint64(&s, 1, 0) {
+		runtime.Gosched()
+	}
+	x = 1
+}
+
+// Races with non-atomic loads are not detected.
+func TestRaceFailingAtomicStoreLoad(t *testing.T) {
+	c := make(chan bool)
+	var a uint64
+	go func() {
+		atomic.StoreUint64(&a, 1)
+		c <- true
+	}()
+	_ = a
+	<-c
+}
+
+func TestRaceAtomicLoadStore(t *testing.T) {
+	c := make(chan bool)
+	var a uint64
+	go func() {
+		_ = atomic.LoadUint64(&a)
+		c <- true
+	}()
+	a = 1
+	<-c
+}
+
+// Races with non-atomic loads are not detected.
+func TestRaceFailingAtomicAddLoad(t *testing.T) {
+	c := make(chan bool)
+	var a uint64
+	go func() {
+		atomic.AddUint64(&a, 1)
+		c <- true
+	}()
+	_ = a
+	<-c
+}
+
+func TestRaceAtomicAddStore(t *testing.T) {
+	c := make(chan bool)
+	var a uint64
+	go func() {
+		atomic.AddUint64(&a, 1)
+		c <- true
+	}()
+	a = 42
+	<-c
+}
diff --git a/src/pkg/runtime/race/testdata/cgo_test.go b/src/pkg/runtime/race/testdata/cgo_test.go
new file mode 100644
index 0000000..ba7e7b5
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/cgo_test.go
@@ -0,0 +1,20 @@
+// 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 race_test
+
+import (
+	"os"
+	"os/exec"
+	"testing"
+)
+
+func TestNoRaceCgoSync(t *testing.T) {
+	cmd := exec.Command("go", "run", "-race", "cgo_test_main.go")
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	if err := cmd.Run(); err != nil {
+		t.Fatalf("program exited with error: %v\n", err)
+	}
+}
diff --git a/src/pkg/runtime/race/testdata/cgo_test_main.go b/src/pkg/runtime/race/testdata/cgo_test_main.go
new file mode 100644
index 0000000..620cea1
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/cgo_test_main.go
@@ -0,0 +1,30 @@
+// 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 main
+
+/*
+int sync;
+
+void Notify(void)
+{
+	__sync_fetch_and_add(&sync, 1);
+}
+
+void Wait(void)
+{
+	while(__sync_fetch_and_add(&sync, 0) == 0) {}
+}
+*/
+import "C"
+
+func main() {
+	data := 0
+	go func() {
+		data = 1
+		C.Notify()
+	}()
+	C.Wait()
+	_ = data
+}
diff --git a/src/pkg/runtime/race/testdata/chan_test.go b/src/pkg/runtime/race/testdata/chan_test.go
new file mode 100644
index 0000000..2332f09
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/chan_test.go
@@ -0,0 +1,457 @@
+// 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 race_test
+
+import (
+	"runtime"
+	"testing"
+	"time"
+)
+
+func TestNoRaceChanSync(t *testing.T) {
+	v := 0
+	c := make(chan int)
+	go func() {
+		v = 1
+		c <- 0
+	}()
+	<-c
+	v = 2
+}
+
+func TestNoRaceChanSyncRev(t *testing.T) {
+	v := 0
+	c := make(chan int)
+	go func() {
+		c <- 0
+		v = 2
+	}()
+	v = 1
+	<-c
+}
+
+func TestNoRaceChanAsync(t *testing.T) {
+	v := 0
+	c := make(chan int, 10)
+	go func() {
+		v = 1
+		c <- 0
+	}()
+	<-c
+	v = 2
+}
+
+func TestRaceChanAsyncRev(t *testing.T) {
+	v := 0
+	c := make(chan int, 10)
+	go func() {
+		c <- 0
+		v = 1
+	}()
+	v = 2
+	<-c
+}
+
+func TestNoRaceChanAsyncCloseRecv(t *testing.T) {
+	v := 0
+	c := make(chan int, 10)
+	go func() {
+		v = 1
+		close(c)
+	}()
+	func() {
+		defer func() {
+			recover()
+			v = 2
+		}()
+		<-c
+	}()
+}
+
+func TestNoRaceChanAsyncCloseRecv2(t *testing.T) {
+	v := 0
+	c := make(chan int, 10)
+	go func() {
+		v = 1
+		close(c)
+	}()
+	_, _ = <-c
+	v = 2
+}
+
+func TestNoRaceChanAsyncCloseRecv3(t *testing.T) {
+	v := 0
+	c := make(chan int, 10)
+	go func() {
+		v = 1
+		close(c)
+	}()
+	for _ = range c {
+	}
+	v = 2
+}
+
+func TestNoRaceChanSyncCloseRecv(t *testing.T) {
+	v := 0
+	c := make(chan int)
+	go func() {
+		v = 1
+		close(c)
+	}()
+	func() {
+		defer func() {
+			recover()
+			v = 2
+		}()
+		<-c
+	}()
+}
+
+func TestNoRaceChanSyncCloseRecv2(t *testing.T) {
+	v := 0
+	c := make(chan int)
+	go func() {
+		v = 1
+		close(c)
+	}()
+	_, _ = <-c
+	v = 2
+}
+
+func TestNoRaceChanSyncCloseRecv3(t *testing.T) {
+	v := 0
+	c := make(chan int)
+	go func() {
+		v = 1
+		close(c)
+	}()
+	for _ = range c {
+	}
+	v = 2
+}
+
+func TestRaceChanSyncCloseSend(t *testing.T) {
+	v := 0
+	c := make(chan int)
+	go func() {
+		v = 1
+		close(c)
+	}()
+	func() {
+		defer func() {
+			recover()
+		}()
+		c <- 0
+	}()
+	v = 2
+}
+
+func TestRaceChanAsyncCloseSend(t *testing.T) {
+	v := 0
+	c := make(chan int, 10)
+	go func() {
+		v = 1
+		close(c)
+	}()
+	func() {
+		defer func() {
+			recover()
+		}()
+		for {
+			c <- 0
+		}
+	}()
+	v = 2
+}
+
+func TestRaceChanCloseClose(t *testing.T) {
+	compl := make(chan bool, 2)
+	v1 := 0
+	v2 := 0
+	c := make(chan int)
+	go func() {
+		defer func() {
+			if recover() != nil {
+				v2 = 2
+			}
+			compl <- true
+		}()
+		v1 = 1
+		close(c)
+	}()
+	go func() {
+		defer func() {
+			if recover() != nil {
+				v1 = 2
+			}
+			compl <- true
+		}()
+		v2 = 1
+		close(c)
+	}()
+	<-compl
+	<-compl
+}
+
+func TestRaceChanSendLen(t *testing.T) {
+	v := 0
+	c := make(chan int, 10)
+	go func() {
+		v = 1
+		c <- 1
+	}()
+	for len(c) == 0 {
+		runtime.Gosched()
+	}
+	v = 2
+}
+
+func TestRaceChanRecvLen(t *testing.T) {
+	v := 0
+	c := make(chan int, 10)
+	c <- 1
+	go func() {
+		v = 1
+		<-c
+	}()
+	for len(c) != 0 {
+		runtime.Gosched()
+	}
+	v = 2
+}
+
+func TestRaceChanSendSend(t *testing.T) {
+	compl := make(chan bool, 2)
+	v1 := 0
+	v2 := 0
+	c := make(chan int, 1)
+	go func() {
+		v1 = 1
+		select {
+		case c <- 1:
+		default:
+			v2 = 2
+		}
+		compl <- true
+	}()
+	go func() {
+		v2 = 1
+		select {
+		case c <- 1:
+		default:
+			v1 = 2
+		}
+		compl <- true
+	}()
+	<-compl
+	<-compl
+}
+
+func TestNoRaceChanPtr(t *testing.T) {
+	type msg struct {
+		x int
+	}
+	c := make(chan *msg)
+	go func() {
+		c <- &msg{1}
+	}()
+	m := <-c
+	m.x = 2
+}
+
+func TestRaceChanWrongSend(t *testing.T) {
+	v1 := 0
+	v2 := 0
+	c := make(chan int, 2)
+	go func() {
+		v1 = 1
+		c <- 1
+	}()
+	go func() {
+		v2 = 2
+		c <- 2
+	}()
+	time.Sleep(1e7)
+	if <-c == 1 {
+		v2 = 3
+	} else {
+		v1 = 3
+	}
+}
+
+func TestRaceChanWrongClose(t *testing.T) {
+	v1 := 0
+	v2 := 0
+	c := make(chan int, 1)
+	go func() {
+		defer func() {
+			recover()
+		}()
+		v1 = 1
+		c <- 1
+	}()
+	go func() {
+		time.Sleep(1e7)
+		v2 = 2
+		close(c)
+	}()
+	time.Sleep(2e7)
+	if _, who := <-c; who {
+		v2 = 2
+	} else {
+		v1 = 2
+	}
+}
+
+func TestRaceChanSendClose(t *testing.T) {
+	compl := make(chan bool, 2)
+	c := make(chan int, 1)
+	go func() {
+		defer func() {
+			recover()
+		}()
+		c <- 1
+		compl <- true
+	}()
+	go func() {
+		time.Sleep(1e7)
+		close(c)
+		compl <- true
+	}()
+	<-compl
+	<-compl
+}
+
+func TestNoRaceProducerConsumerUnbuffered(t *testing.T) {
+	type Task struct {
+		f    func()
+		done chan bool
+	}
+
+	queue := make(chan Task)
+
+	go func() {
+		t := <-queue
+		t.f()
+		t.done <- true
+	}()
+
+	doit := func(f func()) {
+		done := make(chan bool, 1)
+		queue <- Task{f, done}
+		<-done
+	}
+
+	x := 0
+	doit(func() {
+		x = 1
+	})
+	_ = x
+}
+
+func TestRaceChanItselfSend(t *testing.T) {
+	compl := make(chan bool, 1)
+	c := make(chan int, 10)
+	go func() {
+		c <- 0
+		compl <- true
+	}()
+	c = make(chan int, 20)
+	<-compl
+}
+
+func TestRaceChanItselfRecv(t *testing.T) {
+	compl := make(chan bool, 1)
+	c := make(chan int, 10)
+	c <- 1
+	go func() {
+		<-c
+		compl <- true
+	}()
+	time.Sleep(1e7)
+	c = make(chan int, 20)
+	<-compl
+}
+
+func TestRaceChanItselfNil(t *testing.T) {
+	c := make(chan int, 10)
+	go func() {
+		c <- 0
+	}()
+	time.Sleep(1e7)
+	c = nil
+	_ = c
+}
+
+func TestRaceChanItselfClose(t *testing.T) {
+	compl := make(chan bool, 1)
+	c := make(chan int)
+	go func() {
+		close(c)
+		compl <- true
+	}()
+	c = make(chan int)
+	<-compl
+}
+
+func TestRaceChanItselfLen(t *testing.T) {
+	compl := make(chan bool, 1)
+	c := make(chan int)
+	go func() {
+		_ = len(c)
+		compl <- true
+	}()
+	c = make(chan int)
+	<-compl
+}
+
+func TestRaceChanItselfCap(t *testing.T) {
+	compl := make(chan bool, 1)
+	c := make(chan int)
+	go func() {
+		_ = cap(c)
+		compl <- true
+	}()
+	c = make(chan int)
+	<-compl
+}
+
+func TestRaceChanCloseLen(t *testing.T) {
+	v := 0
+	c := make(chan int, 10)
+	c <- 0
+	go func() {
+		v = 1
+		close(c)
+	}()
+	time.Sleep(1e7)
+	_ = len(c)
+	v = 2
+}
+
+func TestRaceChanSameCell(t *testing.T) {
+	c := make(chan int, 1)
+	v := 0
+	go func() {
+		v = 1
+		c <- 42
+		<-c
+	}()
+	time.Sleep(1e7)
+	c <- 43
+	<-c
+	_ = v
+}
+
+func TestRaceChanCloseSend(t *testing.T) {
+	compl := make(chan bool, 1)
+	c := make(chan int, 10)
+	go func() {
+		close(c)
+		compl <- true
+	}()
+	c <- 0
+	<-compl
+}
diff --git a/src/pkg/runtime/race/testdata/comp_test.go b/src/pkg/runtime/race/testdata/comp_test.go
new file mode 100644
index 0000000..754e4db
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/comp_test.go
@@ -0,0 +1,132 @@
+// 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 race_test
+
+import (
+	"testing"
+)
+
+type P struct {
+	x, y int
+}
+
+type S struct {
+	s1, s2 P
+}
+
+func TestNoRaceComp(t *testing.T) {
+	c := make(chan bool, 1)
+	var s S
+	go func() {
+		s.s2.x = 1
+		c <- true
+	}()
+	s.s2.y = 2
+	<-c
+}
+
+func TestNoRaceComp2(t *testing.T) {
+	c := make(chan bool, 1)
+	var s S
+	go func() {
+		s.s1.x = 1
+		c <- true
+	}()
+	s.s1.y = 2
+	<-c
+}
+
+func TestRaceComp(t *testing.T) {
+	c := make(chan bool, 1)
+	var s S
+	go func() {
+		s.s2.y = 1
+		c <- true
+	}()
+	s.s2.y = 2
+	<-c
+}
+
+func TestRaceComp2(t *testing.T) {
+	c := make(chan bool, 1)
+	var s S
+	go func() {
+		s.s1.x = 1
+		c <- true
+	}()
+	s = S{}
+	<-c
+}
+
+func TestRaceComp3(t *testing.T) {
+	c := make(chan bool, 1)
+	var s S
+	go func() {
+		s.s2.y = 1
+		c <- true
+	}()
+	s = S{}
+	<-c
+}
+
+func TestRaceCompArray(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]S, 10)
+	x := 4
+	go func() {
+		s[x].s2.y = 1
+		c <- true
+	}()
+	x = 5
+	<-c
+}
+
+type Ptr struct {
+	s1, s2 *P
+}
+
+func TestNoRaceCompPtr(t *testing.T) {
+	c := make(chan bool, 1)
+	p := Ptr{&P{}, &P{}}
+	go func() {
+		p.s1.x = 1
+		c <- true
+	}()
+	p.s1.y = 2
+	<-c
+}
+
+func TestNoRaceCompPtr2(t *testing.T) {
+	c := make(chan bool, 1)
+	p := Ptr{&P{}, &P{}}
+	go func() {
+		p.s1.x = 1
+		c <- true
+	}()
+	_ = p
+	<-c
+}
+
+func TestRaceCompPtr(t *testing.T) {
+	c := make(chan bool, 1)
+	p := Ptr{&P{}, &P{}}
+	go func() {
+		p.s2.x = 1
+		c <- true
+	}()
+	p.s2.x = 2
+	<-c
+}
+
+func TestRaceCompPtr2(t *testing.T) {
+	c := make(chan bool, 1)
+	p := Ptr{&P{}, &P{}}
+	go func() {
+		p.s2.x = 1
+		c <- true
+	}()
+	p.s2 = &P{}
+	<-c
+}
diff --git a/src/pkg/runtime/race/testdata/finalizer_test.go b/src/pkg/runtime/race/testdata/finalizer_test.go
new file mode 100644
index 0000000..2b26076
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/finalizer_test.go
@@ -0,0 +1,67 @@
+// 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 race_test
+
+import (
+	"runtime"
+	"sync"
+	"testing"
+	"time"
+)
+
+func TestNoRaceFin(t *testing.T) {
+	c := make(chan bool)
+	go func() {
+		x := new(int)
+		runtime.SetFinalizer(x, func(x *int) {
+			*x = 42
+		})
+		*x = 66
+		c <- true
+	}()
+	<-c
+	runtime.GC()
+	time.Sleep(1e8)
+}
+
+var finVar struct {
+	sync.Mutex
+	cnt int
+}
+
+func TestNoRaceFinGlobal(t *testing.T) {
+	c := make(chan bool)
+	go func() {
+		x := new(int)
+		runtime.SetFinalizer(x, func(x *int) {
+			finVar.Lock()
+			finVar.cnt++
+			finVar.Unlock()
+		})
+		c <- true
+	}()
+	<-c
+	runtime.GC()
+	time.Sleep(1e8)
+	finVar.Lock()
+	finVar.cnt++
+	finVar.Unlock()
+}
+
+func TestRaceFin(t *testing.T) {
+	c := make(chan bool)
+	y := 0
+	go func() {
+		x := new(int)
+		runtime.SetFinalizer(x, func(x *int) {
+			y = 42
+		})
+		c <- true
+	}()
+	<-c
+	runtime.GC()
+	time.Sleep(1e8)
+	y = 66
+}
diff --git a/src/pkg/runtime/race/testdata/io_test.go b/src/pkg/runtime/race/testdata/io_test.go
new file mode 100644
index 0000000..9eb3552
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/io_test.go
@@ -0,0 +1,69 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package race_test
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"path/filepath"
+	"testing"
+	"time"
+)
+
+func TestNoRaceIOFile(t *testing.T) {
+	x := 0
+	path, _ := ioutil.TempDir("", "race_test")
+	fname := filepath.Join(path, "data")
+	go func() {
+		x = 42
+		f, _ := os.Create(fname)
+		f.Write([]byte("done"))
+		f.Close()
+	}()
+	for {
+		f, err := os.Open(fname)
+		if err != nil {
+			time.Sleep(1e6)
+			continue
+		}
+		buf := make([]byte, 100)
+		count, err := f.Read(buf)
+		if count == 0 {
+			time.Sleep(1e6)
+			continue
+		}
+		break
+	}
+	_ = x
+}
+
+func TestNoRaceIOHttp(t *testing.T) {
+	x := 0
+	go func() {
+		http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+			x = 41
+			fmt.Fprintf(w, "test")
+			x = 42
+		})
+		err := http.ListenAndServe(":23651", nil)
+		if err != nil {
+			t.Fatalf("http.ListenAndServe: %v", err)
+		}
+	}()
+	time.Sleep(1e7)
+	x = 1
+	_, err := http.Get("http://127.0.0.1:23651")
+	if err != nil {
+		t.Fatalf("http.Get: %v", err)
+	}
+	x = 2
+	_, err = http.Get("http://127.0.0.1:23651")
+	if err != nil {
+		t.Fatalf("http.Get: %v", err)
+	}
+	x = 3
+}
diff --git a/src/pkg/runtime/race/testdata/map_test.go b/src/pkg/runtime/race/testdata/map_test.go
new file mode 100644
index 0000000..6f86a50
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/map_test.go
@@ -0,0 +1,163 @@
+// 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 race_test
+
+import (
+	"testing"
+)
+
+func TestRaceMapRW(t *testing.T) {
+	m := make(map[int]int)
+	ch := make(chan bool, 1)
+	go func() {
+		_ = m[1]
+		ch <- true
+	}()
+	m[1] = 1
+	<-ch
+}
+
+func TestRaceMapRW2(t *testing.T) {
+	m := make(map[int]int)
+	ch := make(chan bool, 1)
+	go func() {
+		_, _ = m[1]
+		ch <- true
+	}()
+	m[1] = 1
+	<-ch
+}
+
+func TestRaceMapRWArray(t *testing.T) {
+	// Check instrumentation of unaddressable arrays (issue 4578).
+	m := make(map[int][2]int)
+	ch := make(chan bool, 1)
+	go func() {
+		_ = m[1][1]
+		ch <- true
+	}()
+	m[2] = [2]int{1, 2}
+	<-ch
+}
+
+func TestNoRaceMapRR(t *testing.T) {
+	m := make(map[int]int)
+	ch := make(chan bool, 1)
+	go func() {
+		_, _ = m[1]
+		ch <- true
+	}()
+	_ = m[1]
+	<-ch
+}
+
+func TestRaceMapRange(t *testing.T) {
+	m := make(map[int]int)
+	ch := make(chan bool, 1)
+	go func() {
+		for _ = range m {
+		}
+		ch <- true
+	}()
+	m[1] = 1
+	<-ch
+}
+
+func TestRaceMapRange2(t *testing.T) {
+	m := make(map[int]int)
+	ch := make(chan bool, 1)
+	go func() {
+		for _ = range m {
+		}
+		ch <- true
+	}()
+	m[1] = 1
+	<-ch
+}
+
+func TestNoRaceMapRangeRange(t *testing.T) {
+	m := make(map[int]int)
+	// now the map is not empty and range triggers an event
+	// should work without this (as in other tests)
+	// so it is suspicious if this test passes and others don't
+	m[0] = 0
+	ch := make(chan bool, 1)
+	go func() {
+		for _ = range m {
+		}
+		ch <- true
+	}()
+	for _ = range m {
+	}
+	<-ch
+}
+
+// Map len is not instrumented.
+func TestRaceFailingMapLen(t *testing.T) {
+	m := make(map[string]bool)
+	ch := make(chan bool, 1)
+	go func() {
+		_ = len(m)
+		ch <- true
+	}()
+	m[""] = true
+	<-ch
+}
+
+func TestRaceMapDelete(t *testing.T) {
+	m := make(map[string]bool)
+	ch := make(chan bool, 1)
+	go func() {
+		delete(m, "")
+		ch <- true
+	}()
+	m[""] = true
+	<-ch
+}
+
+// Map len is not instrumented.
+func TestRaceFailingMapLenDelete(t *testing.T) {
+	m := make(map[string]bool)
+	ch := make(chan bool, 1)
+	go func() {
+		delete(m, "a")
+		ch <- true
+	}()
+	_ = len(m)
+	<-ch
+}
+
+func TestRaceMapVariable(t *testing.T) {
+	ch := make(chan bool, 1)
+	m := make(map[int]int)
+	go func() {
+		m = make(map[int]int)
+		ch <- true
+	}()
+	m = make(map[int]int)
+	<-ch
+}
+
+func TestRaceMapVariable2(t *testing.T) {
+	ch := make(chan bool, 1)
+	m := make(map[int]int)
+	go func() {
+		m[1] = 1
+		ch <- true
+	}()
+	m = make(map[int]int)
+	<-ch
+}
+
+func TestRaceMapVariable3(t *testing.T) {
+	ch := make(chan bool, 1)
+	m := make(map[int]int)
+	go func() {
+		_ = m[1]
+		ch <- true
+	}()
+	m = make(map[int]int)
+	<-ch
+}
diff --git a/src/pkg/runtime/race/testdata/mop_test.go b/src/pkg/runtime/race/testdata/mop_test.go
new file mode 100644
index 0000000..f2daa37
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/mop_test.go
@@ -0,0 +1,1384 @@
+// 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 race_test
+
+import (
+	"errors"
+	"fmt"
+	"runtime"
+	"sync"
+	"testing"
+	"time"
+	"unsafe"
+)
+
+type Point struct {
+	x, y int
+}
+
+type NamedPoint struct {
+	name string
+	p    Point
+}
+
+type DummyWriter struct {
+	state int
+}
+type Writer interface {
+	Write(p []byte) (n int)
+}
+
+func (d DummyWriter) Write(p []byte) (n int) {
+	return 0
+}
+
+var GlobalX, GlobalY int = 0, 0
+var GlobalCh chan int = make(chan int, 2)
+
+func GlobalFunc1() {
+	GlobalY = GlobalX
+	GlobalCh <- 1
+}
+
+func GlobalFunc2() {
+	GlobalX = 1
+	GlobalCh <- 1
+}
+
+func TestRaceIntRWGlobalFuncs(t *testing.T) {
+	go GlobalFunc1()
+	go GlobalFunc2()
+	<-GlobalCh
+	<-GlobalCh
+}
+
+func TestRaceIntRWClosures(t *testing.T) {
+	var x, y int
+	ch := make(chan int, 2)
+
+	go func() {
+		y = x
+		ch <- 1
+	}()
+	go func() {
+		x = 1
+		ch <- 1
+	}()
+	<-ch
+	<-ch
+}
+
+func TestNoRaceIntRWClosures(t *testing.T) {
+	var x, y int
+	ch := make(chan int, 1)
+
+	go func() {
+		y = x
+		ch <- 1
+	}()
+	<-ch
+	go func() {
+		x = 1
+		ch <- 1
+	}()
+	<-ch
+
+}
+
+func TestRaceInt32RWClosures(t *testing.T) {
+	var x, y int32
+	ch := make(chan bool, 2)
+
+	go func() {
+		y = x
+		ch <- true
+	}()
+	go func() {
+		x = 1
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestNoRaceCase(t *testing.T) {
+	var y int
+	for x := -1; x <= 1; x++ {
+		switch {
+		case x < 0:
+			y = -1
+		case x == 0:
+			y = 0
+		case x > 0:
+			y = 1
+		}
+	}
+	y++
+}
+
+func TestRaceCaseCondition(t *testing.T) {
+	var x int = 0
+	ch := make(chan int, 2)
+
+	go func() {
+		x = 2
+		ch <- 1
+	}()
+	go func() {
+		switch x < 2 {
+		case true:
+			x = 1
+			//case false:
+			//	x = 5
+		}
+		ch <- 1
+	}()
+	<-ch
+	<-ch
+}
+
+func TestRaceCaseCondition2(t *testing.T) {
+	// switch body is rearranged by the compiler so the tests
+	// passes even if we don't instrument '<'
+	var x int = 0
+	ch := make(chan int, 2)
+
+	go func() {
+		x = 2
+		ch <- 1
+	}()
+	go func() {
+		switch x < 2 {
+		case true:
+			x = 1
+		case false:
+			x = 5
+		}
+		ch <- 1
+	}()
+	<-ch
+	<-ch
+}
+
+func TestRaceCaseBody(t *testing.T) {
+	var x, y int
+	ch := make(chan int, 2)
+
+	go func() {
+		y = x
+		ch <- 1
+	}()
+	go func() {
+		switch {
+		default:
+			x = 1
+		case x == 100:
+			x = -x
+		}
+		ch <- 1
+	}()
+	<-ch
+	<-ch
+}
+
+func TestNoRaceCaseFallthrough(t *testing.T) {
+	var x, y, z int
+	ch := make(chan int, 2)
+	z = 1
+
+	go func() {
+		y = x
+		ch <- 1
+	}()
+	go func() {
+		switch {
+		case z == 1:
+		case z == 2:
+			x = 2
+		}
+		ch <- 1
+	}()
+	<-ch
+	<-ch
+}
+
+func TestRaceCaseFallthrough(t *testing.T) {
+	var x, y, z int
+	ch := make(chan int, 2)
+	z = 1
+
+	go func() {
+		y = x
+		ch <- 1
+	}()
+	go func() {
+		switch {
+		case z == 1:
+			fallthrough
+		case z == 2:
+			x = 2
+		}
+		ch <- 1
+	}()
+
+	<-ch
+	<-ch
+}
+
+func TestNoRaceRange(t *testing.T) {
+	ch := make(chan int, 3)
+	a := [...]int{1, 2, 3}
+	for _, v := range a {
+		ch <- v
+	}
+	close(ch)
+}
+
+func TestRaceRange(t *testing.T) {
+	const N = 2
+	var a [N]int
+	var x, y int
+	done := make(chan bool, N)
+	for i, v := range a {
+		go func(i int) {
+			// we don't want a write-vs-write race
+			// so there is no array b here
+			if i == 0 {
+				x = v
+			} else {
+				y = v
+			}
+			done <- true
+		}(i)
+	}
+	for i := 0; i < N; i++ {
+		<-done
+	}
+}
+
+func TestRacePlus(t *testing.T) {
+	var x, y, z int
+	ch := make(chan int, 2)
+
+	go func() {
+		y = x + z
+		ch <- 1
+	}()
+	go func() {
+		y = x + z + z
+		ch <- 1
+	}()
+	<-ch
+	<-ch
+}
+
+func TestRacePlus2(t *testing.T) {
+	var x, y, z int
+	ch := make(chan int, 2)
+
+	go func() {
+		x = 1
+		ch <- 1
+	}()
+	go func() {
+		y = +x + z
+		ch <- 1
+	}()
+	<-ch
+	<-ch
+}
+
+func TestNoRacePlus(t *testing.T) {
+	var x, y, z, f int
+	ch := make(chan int, 2)
+
+	go func() {
+		y = x + z
+		ch <- 1
+	}()
+	go func() {
+		f = z + x
+		ch <- 1
+	}()
+	<-ch
+	<-ch
+}
+
+// May crash if the instrumentation is reckless.
+func TestNoRaceEnoughRegisters(t *testing.T) {
+	// from erf.go
+	const (
+		sa1 = 1
+		sa2 = 2
+		sa3 = 3
+		sa4 = 4
+		sa5 = 5
+		sa6 = 6
+		sa7 = 7
+		sa8 = 8
+	)
+	var s, S float64
+	s = 3.1415
+	S = 1 + s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+s*sa8)))))))
+	s = S
+}
+
+// emptyFunc should not be inlined.
+func emptyFunc(x int) {
+	if false {
+		fmt.Println(x)
+	}
+}
+
+func TestRaceFuncArgument(t *testing.T) {
+	var x int
+	ch := make(chan bool, 1)
+	go func() {
+		emptyFunc(x)
+		ch <- true
+	}()
+	x = 1
+	<-ch
+}
+
+func TestRaceFuncArgument2(t *testing.T) {
+	var x int
+	ch := make(chan bool, 2)
+	go func() {
+		x = 42
+		ch <- true
+	}()
+	go func(y int) {
+		ch <- true
+	}(x)
+	<-ch
+	<-ch
+}
+
+func TestRaceSprint(t *testing.T) {
+	var x int
+	ch := make(chan bool, 1)
+	go func() {
+		fmt.Sprint(x)
+		ch <- true
+	}()
+	x = 1
+	<-ch
+}
+
+// Not implemented.
+func TestRaceFailingArrayCopy(t *testing.T) {
+	ch := make(chan bool, 1)
+	var a [5]int
+	go func() {
+		a[3] = 1
+		ch <- true
+	}()
+	a = [5]int{1, 2, 3, 4, 5}
+	<-ch
+}
+
+func TestRaceStructRW(t *testing.T) {
+	p := Point{0, 0}
+	ch := make(chan bool, 1)
+	go func() {
+		p = Point{1, 1}
+		ch <- true
+	}()
+	q := p
+	<-ch
+	p = q
+}
+
+func TestRaceStructFieldRW1(t *testing.T) {
+	p := Point{0, 0}
+	ch := make(chan bool, 1)
+	go func() {
+		p.x = 1
+		ch <- true
+	}()
+	_ = p.x
+	<-ch
+}
+
+func TestNoRaceStructFieldRW1(t *testing.T) {
+	// Same struct, different variables, no
+	// pointers. The layout is known (at compile time?) ->
+	// no read on p
+	// writes on x and y
+	p := Point{0, 0}
+	ch := make(chan bool, 1)
+	go func() {
+		p.x = 1
+		ch <- true
+	}()
+	p.y = 1
+	<-ch
+	_ = p
+}
+
+func TestNoRaceStructFieldRW2(t *testing.T) {
+	// Same as NoRaceStructFieldRW1
+	// but p is a pointer, so there is a read on p
+	p := Point{0, 0}
+	ch := make(chan bool, 1)
+	go func() {
+		p.x = 1
+		ch <- true
+	}()
+	p.y = 1
+	<-ch
+	_ = p
+}
+
+func TestRaceStructFieldRW2(t *testing.T) {
+	p := &Point{0, 0}
+	ch := make(chan bool, 1)
+	go func() {
+		p.x = 1
+		ch <- true
+	}()
+	_ = p.x
+	<-ch
+}
+
+func TestRaceStructFieldRW3(t *testing.T) {
+	p := NamedPoint{name: "a", p: Point{0, 0}}
+	ch := make(chan bool, 1)
+	go func() {
+		p.p.x = 1
+		ch <- true
+	}()
+	_ = p.p.x
+	<-ch
+}
+
+func TestRaceEfaceWW(t *testing.T) {
+	var a, b interface{}
+	ch := make(chan bool, 1)
+	go func() {
+		a = 1
+		ch <- true
+	}()
+	a = 2
+	<-ch
+	_, _ = a, b
+}
+
+func TestRaceIfaceWW(t *testing.T) {
+	var a, b Writer
+	ch := make(chan bool, 1)
+	go func() {
+		a = DummyWriter{1}
+		ch <- true
+	}()
+	a = DummyWriter{2}
+	<-ch
+	b = a
+	a = b
+}
+
+func TestRaceEfaceConv(t *testing.T) {
+	c := make(chan bool)
+	v := 0
+	go func() {
+		go func(x interface{}) {
+		}(v)
+		c <- true
+	}()
+	v = 42
+	<-c
+}
+
+type OsFile struct{}
+
+func (*OsFile) Read() {
+}
+
+type IoReader interface {
+	Read()
+}
+
+func TestRaceIfaceConv(t *testing.T) {
+	c := make(chan bool)
+	f := &OsFile{}
+	go func() {
+		go func(x IoReader) {
+		}(f)
+		c <- true
+	}()
+	f = &OsFile{}
+	<-c
+}
+
+func TestRaceError(t *testing.T) {
+	ch := make(chan bool, 1)
+	var err error
+	go func() {
+		err = nil
+		ch <- true
+	}()
+	_ = err
+	<-ch
+}
+
+func TestRaceIntptrRW(t *testing.T) {
+	var x, y int
+	var p *int = &x
+	ch := make(chan bool, 1)
+	go func() {
+		*p = 5
+		ch <- true
+	}()
+	y = *p
+	x = y
+	<-ch
+}
+
+func TestRaceStringRW(t *testing.T) {
+	ch := make(chan bool, 1)
+	s := ""
+	go func() {
+		s = "abacaba"
+		ch <- true
+	}()
+	_ = s
+	<-ch
+}
+
+func TestRaceStringPtrRW(t *testing.T) {
+	ch := make(chan bool, 1)
+	var x string
+	p := &x
+	go func() {
+		*p = "a"
+		ch <- true
+	}()
+	_ = *p
+	<-ch
+}
+
+func TestRaceFloat64WW(t *testing.T) {
+	var x, y float64
+	ch := make(chan bool, 1)
+	go func() {
+		x = 1.0
+		ch <- true
+	}()
+	x = 2.0
+	<-ch
+
+	y = x
+	x = y
+}
+
+func TestRaceComplex128WW(t *testing.T) {
+	var x, y complex128
+	ch := make(chan bool, 1)
+	go func() {
+		x = 2 + 2i
+		ch <- true
+	}()
+	x = 4 + 4i
+	<-ch
+
+	y = x
+	x = y
+}
+
+func TestRaceUnsafePtrRW(t *testing.T) {
+	var x, y, z int
+	x, y, z = 1, 2, 3
+	var p unsafe.Pointer = unsafe.Pointer(&x)
+	ch := make(chan bool, 1)
+	go func() {
+		p = (unsafe.Pointer)(&z)
+		ch <- true
+	}()
+	y = *(*int)(p)
+	x = y
+	<-ch
+}
+
+func TestRaceFuncVariableRW(t *testing.T) {
+	var f func(x int) int
+	f = func(x int) int {
+		return x * x
+	}
+	ch := make(chan bool, 1)
+	go func() {
+		f = func(x int) int {
+			return x
+		}
+		ch <- true
+	}()
+	y := f(1)
+	<-ch
+	x := y
+	y = x
+}
+
+func TestRaceFuncVariableWW(t *testing.T) {
+	var f func(x int) int
+	ch := make(chan bool, 1)
+	go func() {
+		f = func(x int) int {
+			return x
+		}
+		ch <- true
+	}()
+	f = func(x int) int {
+		return x * x
+	}
+	<-ch
+}
+
+// This one should not belong to mop_test
+func TestRacePanic(t *testing.T) {
+	var x int
+	var zero int = 0
+	ch := make(chan bool, 2)
+	go func() {
+		defer func() {
+			err := recover()
+			if err == nil {
+				panic("should be panicking")
+			}
+			x = 1
+			ch <- true
+		}()
+		var y int = 1 / zero
+		zero = y
+	}()
+	go func() {
+		defer func() {
+			err := recover()
+			if err == nil {
+				panic("should be panicking")
+			}
+			x = 2
+			ch <- true
+		}()
+		var y int = 1 / zero
+		zero = y
+	}()
+
+	<-ch
+	<-ch
+	if zero != 0 {
+		panic("zero has changed")
+	}
+}
+
+func TestNoRaceBlank(t *testing.T) {
+	var a [5]int
+	ch := make(chan bool, 1)
+	go func() {
+		_, _ = a[0], a[1]
+		ch <- true
+	}()
+	_, _ = a[2], a[3]
+	<-ch
+	a[1] = a[0]
+}
+
+func TestRaceAppendRW(t *testing.T) {
+	a := make([]int, 10)
+	ch := make(chan bool)
+	go func() {
+		_ = append(a, 1)
+		ch <- true
+	}()
+	a[0] = 1
+	<-ch
+}
+
+func TestRaceAppendLenRW(t *testing.T) {
+	a := make([]int, 0)
+	ch := make(chan bool)
+	go func() {
+		a = append(a, 1)
+		ch <- true
+	}()
+	_ = len(a)
+	<-ch
+}
+
+func TestRaceAppendCapRW(t *testing.T) {
+	a := make([]int, 0)
+	ch := make(chan string)
+	go func() {
+		a = append(a, 1)
+		ch <- ""
+	}()
+	_ = cap(a)
+	<-ch
+}
+
+func TestNoRaceFuncArgsRW(t *testing.T) {
+	ch := make(chan byte, 1)
+	var x byte
+	go func(y byte) {
+		_ = y
+		ch <- 0
+	}(x)
+	x = 1
+	<-ch
+}
+
+func TestRaceFuncArgsRW(t *testing.T) {
+	ch := make(chan byte, 1)
+	var x byte
+	go func(y *byte) {
+		_ = *y
+		ch <- 0
+	}(&x)
+	x = 1
+	<-ch
+}
+
+// from the mailing list, slightly modified
+// unprotected concurrent access to seen[]
+func TestRaceCrawl(t *testing.T) {
+	url := "dummyurl"
+	depth := 3
+	seen := make(map[string]bool)
+	ch := make(chan int, 100)
+	var wg sync.WaitGroup
+	var crawl func(string, int)
+	crawl = func(u string, d int) {
+		nurl := 0
+		defer func() {
+			ch <- nurl
+		}()
+		seen[u] = true
+		if d <= 0 {
+			return
+		}
+		urls := [...]string{"a", "b", "c"}
+		for _, uu := range urls {
+			if _, ok := seen[uu]; !ok {
+				wg.Add(1)
+				go crawl(uu, d-1)
+				nurl++
+			}
+		}
+		wg.Done()
+	}
+	wg.Add(1)
+	go crawl(url, depth)
+	wg.Wait()
+}
+
+func TestRaceIndirection(t *testing.T) {
+	ch := make(chan struct{}, 1)
+	var y int
+	var x *int = &y
+	go func() {
+		*x = 1
+		ch <- struct{}{}
+	}()
+	*x = 2
+	<-ch
+	_ = *x
+}
+
+func TestRaceRune(t *testing.T) {
+	c := make(chan bool)
+	var x rune
+	go func() {
+		x = 1
+		c <- true
+	}()
+	_ = x
+	<-c
+}
+
+func TestRaceEmptyInterface1(t *testing.T) {
+	c := make(chan bool)
+	var x interface{}
+	go func() {
+		x = nil
+		c <- true
+	}()
+	_ = x
+	<-c
+}
+
+func TestRaceEmptyInterface2(t *testing.T) {
+	c := make(chan bool)
+	var x interface{}
+	go func() {
+		x = &Point{}
+		c <- true
+	}()
+	_ = x
+	<-c
+}
+
+func TestRaceTLS(t *testing.T) {
+	comm := make(chan *int)
+	done := make(chan bool, 2)
+	go func() {
+		var x int
+		comm <- &x
+		x = 1
+		x = *(<-comm)
+		done <- true
+	}()
+	go func() {
+		p := <-comm
+		*p = 2
+		comm <- p
+		done <- true
+	}()
+	<-done
+	<-done
+}
+
+func TestNoRaceHeapReallocation(t *testing.T) {
+	// It is possible that a future implementation
+	// of memory allocation will ruin this test.
+	// Increasing n might help in this case, so
+	// this test is a bit more generic than most of the
+	// others.
+	const n = 2
+	done := make(chan bool, n)
+	empty := func(p *int) {}
+	for i := 0; i < n; i++ {
+		ms := i
+		go func() {
+			<-time.After(time.Duration(ms) * time.Millisecond)
+			runtime.GC()
+			var x int
+			empty(&x) // x goes to the heap
+			done <- true
+		}()
+	}
+	for i := 0; i < n; i++ {
+		<-done
+	}
+}
+
+func TestRaceAnd(t *testing.T) {
+	c := make(chan bool)
+	x, y := 0, 0
+	go func() {
+		x = 1
+		c <- true
+	}()
+	if x == 1 && y == 1 {
+	}
+	<-c
+}
+
+// OANDAND is not instrumented in the compiler.
+func TestRaceFailingAnd2(t *testing.T) {
+	c := make(chan bool)
+	x, y := 0, 0
+	go func() {
+		x = 1
+		c <- true
+	}()
+	if y == 0 && x == 1 {
+	}
+	<-c
+}
+
+func TestNoRaceAnd(t *testing.T) {
+	c := make(chan bool)
+	x, y := 0, 0
+	go func() {
+		x = 1
+		c <- true
+	}()
+	if y == 1 && x == 1 {
+	}
+	<-c
+}
+
+func TestRaceOr(t *testing.T) {
+	c := make(chan bool)
+	x, y := 0, 0
+	go func() {
+		x = 1
+		c <- true
+	}()
+	if x == 1 || y == 1 {
+	}
+	<-c
+}
+
+// OOROR is not instrumented in the compiler.
+func TestRaceFailingOr2(t *testing.T) {
+	c := make(chan bool)
+	x, y := 0, 0
+	go func() {
+		x = 1
+		c <- true
+	}()
+	if y == 1 || x == 1 {
+	}
+	<-c
+}
+
+func TestNoRaceOr(t *testing.T) {
+	c := make(chan bool)
+	x, y := 0, 0
+	go func() {
+		x = 1
+		c <- true
+	}()
+	if y == 0 || x == 1 {
+	}
+	<-c
+}
+
+func TestNoRaceShortCalc(t *testing.T) {
+	c := make(chan bool)
+	x, y := 0, 0
+	go func() {
+		y = 1
+		c <- true
+	}()
+	if x == 0 || y == 0 {
+	}
+	<-c
+}
+
+func TestNoRaceShortCalc2(t *testing.T) {
+	c := make(chan bool)
+	x, y := 0, 0
+	go func() {
+		y = 1
+		c <- true
+	}()
+	if x == 1 && y == 0 {
+	}
+	<-c
+}
+
+func TestRaceFuncItself(t *testing.T) {
+	c := make(chan bool)
+	f := func() {}
+	go func() {
+		f()
+		c <- true
+	}()
+	f = func() {}
+	<-c
+}
+
+func TestNoRaceFuncUnlock(t *testing.T) {
+	ch := make(chan bool, 1)
+	var mu sync.Mutex
+	x := 0
+	go func() {
+		mu.Lock()
+		x = 42
+		mu.Unlock()
+		ch <- true
+	}()
+	x = func(mu *sync.Mutex) int {
+		mu.Lock()
+		return 43
+	}(&mu)
+	mu.Unlock()
+	<-ch
+}
+
+func TestRaceStructInit(t *testing.T) {
+	type X struct {
+		x, y int
+	}
+	c := make(chan bool, 1)
+	y := 0
+	go func() {
+		y = 42
+		c <- true
+	}()
+	x := X{x: y}
+	_ = x
+	<-c
+}
+
+func TestRaceArrayInit(t *testing.T) {
+	c := make(chan bool, 1)
+	y := 0
+	go func() {
+		y = 42
+		c <- true
+	}()
+	x := []int{0, y, 42}
+	_ = x
+	<-c
+}
+
+func TestRaceMapInit(t *testing.T) {
+	c := make(chan bool, 1)
+	y := 0
+	go func() {
+		y = 42
+		c <- true
+	}()
+	x := map[int]int{0: 42, y: 42}
+	_ = x
+	<-c
+}
+
+func TestRaceMapInit2(t *testing.T) {
+	c := make(chan bool, 1)
+	y := 0
+	go func() {
+		y = 42
+		c <- true
+	}()
+	x := map[int]int{0: 42, 42: y}
+	_ = x
+	<-c
+}
+
+type Inter interface {
+	Foo(x int)
+}
+type InterImpl struct {
+	x, y int
+}
+
+func (p InterImpl) Foo(x int) {
+	// prevent inlining
+	z := 42
+	x = 85
+	y := x / z
+	z = y * z
+	x = z * y
+	_, _, _ = x, y, z
+}
+
+func TestRaceInterCall(t *testing.T) {
+	c := make(chan bool, 1)
+	p := InterImpl{}
+	var x Inter = p
+	go func() {
+		p2 := InterImpl{}
+		x = p2
+		c <- true
+	}()
+	x.Foo(0)
+	<-c
+}
+
+func TestRaceInterCall2(t *testing.T) {
+	c := make(chan bool, 1)
+	p := InterImpl{}
+	var x Inter = p
+	z := 0
+	go func() {
+		z = 42
+		c <- true
+	}()
+	x.Foo(z)
+	<-c
+}
+
+func TestRaceFuncCall(t *testing.T) {
+	c := make(chan bool, 1)
+	f := func(x, y int) {}
+	x, y := 0, 0
+	go func() {
+		y = 42
+		c <- true
+	}()
+	f(x, y)
+	<-c
+}
+
+func TestRaceMethodCall(t *testing.T) {
+	c := make(chan bool, 1)
+	i := InterImpl{}
+	x := 0
+	go func() {
+		x = 42
+		c <- true
+	}()
+	i.Foo(x)
+	<-c
+}
+
+func TestRaceMethodCall2(t *testing.T) {
+	c := make(chan bool, 1)
+	i := &InterImpl{}
+	go func() {
+		i = &InterImpl{}
+		c <- true
+	}()
+	i.Foo(0)
+	<-c
+}
+
+func TestRacePanicArg(t *testing.T) {
+	c := make(chan bool, 1)
+	err := errors.New("err")
+	go func() {
+		err = errors.New("err2")
+		c <- true
+	}()
+	defer func() {
+		recover()
+		<-c
+	}()
+	panic(err)
+}
+
+func TestRaceDeferArg(t *testing.T) {
+	c := make(chan bool, 1)
+	x := 0
+	go func() {
+		x = 42
+		c <- true
+	}()
+	func() {
+		defer func(x int) {
+		}(x)
+	}()
+	<-c
+}
+
+type DeferT int
+
+func (d DeferT) Foo() {
+}
+
+func TestRaceDeferArg2(t *testing.T) {
+	c := make(chan bool, 1)
+	var x DeferT
+	go func() {
+		var y DeferT
+		x = y
+		c <- true
+	}()
+	func() {
+		defer x.Foo()
+	}()
+	<-c
+}
+
+func TestNoRaceAddrExpr(t *testing.T) {
+	c := make(chan bool, 1)
+	x := 0
+	go func() {
+		x = 42
+		c <- true
+	}()
+	_ = &x
+	<-c
+}
+
+type AddrT struct {
+	_ [256]byte
+	x int
+}
+
+type AddrT2 struct {
+	_ [512]byte
+	p *AddrT
+}
+
+func TestRaceAddrExpr(t *testing.T) {
+	c := make(chan bool, 1)
+	a := AddrT2{p: &AddrT{x: 42}}
+	go func() {
+		a.p = &AddrT{x: 43}
+		c <- true
+	}()
+	_ = &a.p.x
+	<-c
+}
+
+func TestRaceTypeAssert(t *testing.T) {
+	c := make(chan bool, 1)
+	x := 0
+	var i interface{} = x
+	go func() {
+		y := 0
+		i = y
+		c <- true
+	}()
+	_ = i.(int)
+	<-c
+}
+
+func TestRaceBlockAs(t *testing.T) {
+	c := make(chan bool, 1)
+	var x, y int
+	go func() {
+		x = 42
+		c <- true
+	}()
+	x, y = y, x
+	<-c
+}
+
+func TestRaceSliceSlice(t *testing.T) {
+	c := make(chan bool, 1)
+	x := make([]int, 10)
+	go func() {
+		x = make([]int, 20)
+		c <- true
+	}()
+	_ = x[2:3]
+	<-c
+}
+
+func TestRaceSliceSlice2(t *testing.T) {
+	c := make(chan bool, 1)
+	x := make([]int, 10)
+	i := 2
+	go func() {
+		i = 3
+		c <- true
+	}()
+	_ = x[i:4]
+	<-c
+}
+
+// http://golang.org/issue/4453
+func TestRaceFailingSliceStruct(t *testing.T) {
+	type X struct {
+		x, y int
+	}
+	c := make(chan bool, 1)
+	x := make([]X, 10)
+	go func() {
+		y := make([]X, 10)
+		copy(y, x)
+		c <- true
+	}()
+	x[1].y = 42
+	<-c
+}
+
+func TestRaceStructInd(t *testing.T) {
+	c := make(chan bool, 1)
+	type Item struct {
+		x, y int
+	}
+	i := Item{}
+	go func(p *Item) {
+		*p = Item{}
+		c <- true
+	}(&i)
+	i.y = 42
+	<-c
+}
+
+func TestRaceAsFunc1(t *testing.T) {
+	var s []byte
+	c := make(chan bool, 1)
+	go func() {
+		var err error
+		s, err = func() ([]byte, error) {
+			t := []byte("hello world")
+			return t, nil
+		}()
+		c <- true
+		_ = err
+	}()
+	_ = string(s)
+	<-c
+}
+
+func TestRaceAsFunc2(t *testing.T) {
+	c := make(chan bool, 1)
+	x := 0
+	go func() {
+		func(x int) {
+		}(x)
+		c <- true
+	}()
+	x = 42
+	<-c
+}
+
+func TestRaceAsFunc3(t *testing.T) {
+	c := make(chan bool, 1)
+	var mu sync.Mutex
+	x := 0
+	go func() {
+		func(x int) {
+			mu.Lock()
+		}(x) // Read of x must be outside of the mutex.
+		mu.Unlock()
+		c <- true
+	}()
+	mu.Lock()
+	x = 42
+	mu.Unlock()
+	<-c
+}
+
+func TestNoRaceAsFunc4(t *testing.T) {
+	c := make(chan bool, 1)
+	var mu sync.Mutex
+	x := 0
+	go func() {
+		x = func() int { // Write of x must be under the mutex.
+			mu.Lock()
+			return 42
+		}()
+		mu.Unlock()
+		c <- true
+	}()
+	mu.Lock()
+	x = 42
+	mu.Unlock()
+	<-c
+}
+
+func TestRaceHeapParam(t *testing.T) {
+	x := func() (x int) {
+		go func() {
+			x = 42
+		}()
+		return
+	}()
+	_ = x
+}
+
+func TestNoRaceEmptyStruct(t *testing.T) {
+	type Empty struct{}
+	type X struct {
+		y int64
+		Empty
+	}
+	type Y struct {
+		x X
+		y int64
+	}
+	c := make(chan X)
+	var y Y
+	go func() {
+		x := y.x
+		c <- x
+	}()
+	y.y = 42
+	<-c
+}
+
+func TestRaceNestedStruct(t *testing.T) {
+	type X struct {
+		x, y int
+	}
+	type Y struct {
+		x X
+	}
+	c := make(chan Y)
+	var y Y
+	go func() {
+		c <- y
+	}()
+	y.x.y = 42
+	<-c
+}
diff --git a/src/pkg/runtime/race/testdata/mutex_test.go b/src/pkg/runtime/race/testdata/mutex_test.go
new file mode 100644
index 0000000..3cf03ae
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/mutex_test.go
@@ -0,0 +1,138 @@
+// 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 race_test
+
+import (
+	"sync"
+	"testing"
+	"time"
+)
+
+func TestNoRaceMutex(t *testing.T) {
+	var mu sync.Mutex
+	var x int16 = 0
+	ch := make(chan bool, 2)
+	go func() {
+		mu.Lock()
+		defer mu.Unlock()
+		x = 1
+		ch <- true
+	}()
+	go func() {
+		mu.Lock()
+		x = 2
+		mu.Unlock()
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestRaceMutex(t *testing.T) {
+	var mu sync.Mutex
+	var x int16 = 0
+	ch := make(chan bool, 2)
+	go func() {
+		x = 1
+		mu.Lock()
+		defer mu.Unlock()
+		ch <- true
+	}()
+	go func() {
+		x = 2
+		mu.Lock()
+		mu.Unlock()
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestRaceMutex2(t *testing.T) {
+	var mu1 sync.Mutex
+	var mu2 sync.Mutex
+	var x int8 = 0
+	ch := make(chan bool, 2)
+	go func() {
+		mu1.Lock()
+		defer mu1.Unlock()
+		x = 1
+		ch <- true
+	}()
+	go func() {
+		mu2.Lock()
+		x = 2
+		mu2.Unlock()
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestNoRaceMutexPureHappensBefore(t *testing.T) {
+	var mu sync.Mutex
+	var x int16 = 0
+	ch := make(chan bool, 2)
+	go func() {
+		x = 1
+		mu.Lock()
+		mu.Unlock()
+		ch <- true
+	}()
+	go func() {
+		<-time.After(1e5)
+		mu.Lock()
+		mu.Unlock()
+		x = 1
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestNoRaceMutexSemaphore(t *testing.T) {
+	var mu sync.Mutex
+	ch := make(chan bool, 2)
+	x := 0
+	mu.Lock()
+	go func() {
+		x = 1
+		mu.Unlock()
+		ch <- true
+	}()
+	go func() {
+		mu.Lock()
+		x = 2
+		mu.Unlock()
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+// from doc/go_mem.html
+func TestNoRaceMutexExampleFromHtml(t *testing.T) {
+	var l sync.Mutex
+	a := ""
+
+	l.Lock()
+	go func() {
+		a = "hello, world"
+		l.Unlock()
+	}()
+	l.Lock()
+	_ = a
+}
+
+func TestRaceMutexOverwrite(t *testing.T) {
+	c := make(chan bool, 1)
+	var mu sync.Mutex
+	go func() {
+		mu = sync.Mutex{}
+		c <- true
+	}()
+	mu.Lock()
+	<-c
+}
diff --git a/src/pkg/runtime/race/testdata/regression_test.go b/src/pkg/runtime/race/testdata/regression_test.go
new file mode 100644
index 0000000..afe8cc5
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/regression_test.go
@@ -0,0 +1,150 @@
+// 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.
+
+// Code patterns that caused problems in the past.
+
+package race_test
+
+import (
+	"testing"
+)
+
+type LogImpl struct {
+	x int
+}
+
+func NewLog() (l LogImpl) {
+	c := make(chan bool)
+	go func() {
+		_ = l
+		c <- true
+	}()
+	l = LogImpl{}
+	<-c
+	return
+}
+
+var _ LogImpl = NewLog()
+
+func MakeMap() map[int]int {
+	return make(map[int]int)
+}
+
+func InstrumentMapLen() {
+	_ = len(MakeMap())
+}
+
+func InstrumentMapLen2() {
+	m := make(map[int]map[int]int)
+	_ = len(m[0])
+}
+
+func InstrumentMapLen3() {
+	m := make(map[int]*map[int]int)
+	_ = len(*m[0])
+}
+
+type Rect struct {
+	x, y int
+}
+
+type Image struct {
+	min, max Rect
+}
+
+func NewImage() Image {
+	var pleaseDoNotInlineMe stack
+	pleaseDoNotInlineMe.push(1)
+	_ = pleaseDoNotInlineMe.pop()
+	return Image{}
+}
+
+func AddrOfTemp() {
+	_ = NewImage().min
+}
+
+type TypeID int
+
+func (t *TypeID) encodeType(x int) (tt TypeID, err error) {
+	switch x {
+	case 0:
+		return t.encodeType(x * x)
+	}
+	return 0, nil
+}
+
+type stack []int
+
+func (s *stack) push(x int) {
+	*s = append(*s, x)
+}
+
+func (s *stack) pop() int {
+	i := len(*s)
+	n := (*s)[i-1]
+	*s = (*s)[:i-1]
+	return n
+}
+
+func TestNoRaceStackPushPop(t *testing.T) {
+	var s stack
+	go func(s *stack) {}(&s)
+	s.push(1)
+	x := s.pop()
+	_ = x
+}
+
+type RpcChan struct {
+	c chan bool
+}
+
+var makeChanCalls int
+
+func makeChan() *RpcChan {
+	var pleaseDoNotInlineMe stack
+	pleaseDoNotInlineMe.push(1)
+	_ = pleaseDoNotInlineMe.pop()
+
+	makeChanCalls++
+	c := &RpcChan{make(chan bool, 1)}
+	c.c <- true
+	return c
+}
+
+func call() bool {
+	x := <-makeChan().c
+	return x
+}
+
+func TestNoRaceRpcChan(t *testing.T) {
+	makeChanCalls = 0
+	_ = call()
+	if makeChanCalls != 1 {
+		t.Fatalf("makeChanCalls %d, expected 1\n", makeChanCalls)
+	}
+}
+
+func divInSlice() {
+	v := make([]int64, 10)
+	i := 1
+	_ = v[(i*4)/3]
+}
+
+func TestNoRaceReturn(t *testing.T) {
+	c := make(chan int)
+	noRaceReturn(c)
+	<-c
+}
+
+// Return used to do an implicit a = a, causing a read/write race
+// with the goroutine. Compiler has an optimization to avoid that now.
+// See issue 4014.
+func noRaceReturn(c chan int) (a, b int) {
+	a = 42
+	go func() {
+		_ = a
+		c <- 1
+	}()
+	return a, 10
+}
diff --git a/src/pkg/runtime/race/testdata/rwmutex_test.go b/src/pkg/runtime/race/testdata/rwmutex_test.go
new file mode 100644
index 0000000..85cb5df
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/rwmutex_test.go
@@ -0,0 +1,134 @@
+// 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 race_test
+
+import (
+	"sync"
+	"testing"
+	"time"
+)
+
+func TestRaceMutexRWMutex(t *testing.T) {
+	var mu1 sync.Mutex
+	var mu2 sync.RWMutex
+	var x int16 = 0
+	ch := make(chan bool, 2)
+	go func() {
+		mu1.Lock()
+		defer mu1.Unlock()
+		x = 1
+		ch <- true
+	}()
+	go func() {
+		mu2.Lock()
+		x = 2
+		mu2.Unlock()
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestNoRaceRWMutex(t *testing.T) {
+	var mu sync.RWMutex
+	var x, y int64 = 0, 1
+	ch := make(chan bool, 2)
+	go func() {
+		mu.Lock()
+		defer mu.Unlock()
+		x = 2
+		ch <- true
+	}()
+	go func() {
+		mu.RLock()
+		y = x
+		mu.RUnlock()
+		ch <- true
+	}()
+	<-ch
+	<-ch
+}
+
+func TestRaceRWMutexMultipleReaders(t *testing.T) {
+	var mu sync.RWMutex
+	var x, y int64 = 0, 1
+	ch := make(chan bool, 3)
+	go func() {
+		mu.Lock()
+		defer mu.Unlock()
+		x = 2
+		ch <- true
+	}()
+	go func() {
+		mu.RLock()
+		y = x + 1
+		mu.RUnlock()
+		ch <- true
+	}()
+	go func() {
+		mu.RLock()
+		y = x + 2
+		mu.RUnlock()
+		ch <- true
+	}()
+	<-ch
+	<-ch
+	<-ch
+	_ = y
+}
+
+func TestNoRaceRWMutexMultipleReaders(t *testing.T) {
+	var mu sync.RWMutex
+	x := int64(0)
+	ch := make(chan bool, 3)
+	go func() {
+		mu.Lock()
+		defer mu.Unlock()
+		x = 2
+		ch <- true
+	}()
+	go func() {
+		mu.RLock()
+		y := x + 1
+		_ = y
+		mu.RUnlock()
+		ch <- true
+	}()
+	go func() {
+		mu.RLock()
+		y := x + 2
+		_ = y
+		mu.RUnlock()
+		ch <- true
+	}()
+	<-ch
+	<-ch
+	<-ch
+}
+
+func TestNoRaceRWMutexTransitive(t *testing.T) {
+	var mu sync.RWMutex
+	x := int64(0)
+	ch := make(chan bool, 2)
+	go func() {
+		mu.RLock()
+		_ = x
+		mu.RUnlock()
+		ch <- true
+	}()
+	go func() {
+		time.Sleep(1e7)
+		mu.RLock()
+		_ = x
+		mu.RUnlock()
+		ch <- true
+	}()
+	time.Sleep(2e7)
+	mu.Lock()
+	x = 42
+	mu.Unlock()
+	<-ch
+	<-ch
+}
diff --git a/src/pkg/runtime/race/testdata/select_test.go b/src/pkg/runtime/race/testdata/select_test.go
new file mode 100644
index 0000000..4a3a236
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/select_test.go
@@ -0,0 +1,286 @@
+// 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 race_test
+
+import (
+	"runtime"
+	"testing"
+)
+
+func TestNoRaceSelect1(t *testing.T) {
+	var x int
+	compl := make(chan bool)
+	c := make(chan bool)
+	c1 := make(chan bool)
+
+	go func() {
+		x = 1
+		// At least two channels are needed because
+		// otherwise the compiler optimizes select out.
+		// See comment in runtime/chan.c:^selectgo.
+		select {
+		case c <- true:
+		case c1 <- true:
+		}
+		compl <- true
+	}()
+	select {
+	case <-c:
+	case c1 <- true:
+	}
+	x = 2
+	<-compl
+}
+
+func TestNoRaceSelect2(t *testing.T) {
+	var x int
+	compl := make(chan bool)
+	c := make(chan bool)
+	c1 := make(chan bool)
+	go func() {
+		select {
+		case <-c:
+		case <-c1:
+		}
+		x = 1
+		compl <- true
+	}()
+	x = 2
+	close(c)
+	runtime.Gosched()
+	<-compl
+}
+
+func TestNoRaceSelect3(t *testing.T) {
+	var x int
+	compl := make(chan bool)
+	c := make(chan bool, 10)
+	c1 := make(chan bool)
+	go func() {
+		x = 1
+		select {
+		case c <- true:
+		case <-c1:
+		}
+		compl <- true
+	}()
+	<-c
+	x = 2
+	<-compl
+}
+
+func TestNoRaceSelect4(t *testing.T) {
+	type Task struct {
+		f    func()
+		done chan bool
+	}
+
+	queue := make(chan Task)
+	dummy := make(chan bool)
+
+	go func() {
+		for {
+			select {
+			case t := <-queue:
+				t.f()
+				t.done <- true
+			}
+		}
+	}()
+
+	doit := func(f func()) {
+		done := make(chan bool, 1)
+		select {
+		case queue <- Task{f, done}:
+		case <-dummy:
+		}
+		select {
+		case <-done:
+		case <-dummy:
+		}
+	}
+
+	var x int
+	doit(func() {
+		x = 1
+	})
+	_ = x
+}
+
+func TestNoRaceSelect5(t *testing.T) {
+	test := func(sel, needSched bool) {
+		var x int
+		ch := make(chan bool)
+		c1 := make(chan bool)
+
+		done := make(chan bool, 2)
+		go func() {
+			if needSched {
+				runtime.Gosched()
+			}
+			// println(1)
+			x = 1
+			if sel {
+				select {
+				case ch <- true:
+				case <-c1:
+				}
+			} else {
+				ch <- true
+			}
+			done <- true
+		}()
+
+		go func() {
+			// println(2)
+			if sel {
+				select {
+				case <-ch:
+				case <-c1:
+				}
+			} else {
+				<-ch
+			}
+			x = 1
+			done <- true
+		}()
+		<-done
+		<-done
+	}
+
+	test(true, true)
+	test(true, false)
+	test(false, true)
+	test(false, false)
+}
+
+func TestRaceSelect1(t *testing.T) {
+	var x int
+	compl := make(chan bool, 2)
+	c := make(chan bool)
+	c1 := make(chan bool)
+
+	go func() {
+		<-c
+		<-c
+	}()
+	f := func() {
+		select {
+		case c <- true:
+		case c1 <- true:
+		}
+		x = 1
+		compl <- true
+	}
+	go f()
+	go f()
+	<-compl
+	<-compl
+}
+
+func TestRaceSelect2(t *testing.T) {
+	var x int
+	compl := make(chan bool)
+	c := make(chan bool)
+	c1 := make(chan bool)
+	go func() {
+		x = 1
+		select {
+		case <-c:
+		case <-c1:
+		}
+		compl <- true
+	}()
+	close(c)
+	x = 2
+	<-compl
+}
+
+func TestRaceSelect3(t *testing.T) {
+	var x int
+	compl := make(chan bool)
+	c := make(chan bool)
+	c1 := make(chan bool)
+	go func() {
+		x = 1
+		select {
+		case c <- true:
+		case c1 <- true:
+		}
+		compl <- true
+	}()
+	x = 2
+	select {
+	case <-c:
+	}
+	<-compl
+}
+
+func TestRaceSelect4(t *testing.T) {
+	done := make(chan bool, 1)
+	var x int
+	go func() {
+		select {
+		default:
+			x = 2
+		}
+		done <- true
+	}()
+	_ = x
+	<-done
+}
+
+// The idea behind this test:
+// there are two variables, access to one
+// of them is synchronized, access to the other
+// is not.
+// Select must (unconditionaly) choose the non-synchronized variable
+// thus causing exactly one race.
+// Currently this test doesn't look like it accomplishes
+// this goal.
+func TestRaceSelect5(t *testing.T) {
+	done := make(chan bool, 1)
+	c1 := make(chan bool, 1)
+	c2 := make(chan bool)
+	var x, y int
+	go func() {
+		select {
+		case c1 <- true:
+			x = 1
+		case c2 <- true:
+			y = 1
+		}
+		done <- true
+	}()
+	_ = x
+	_ = y
+	<-done
+}
+
+// select statements may introduce
+// flakiness: whether this test contains
+// a race depends on the scheduling
+// (some may argue that the code contains
+// this race by definition)
+/*
+func TestFlakyDefault(t *testing.T) {
+	var x int
+	c := make(chan bool, 1)
+	done := make(chan bool, 1)
+	go func() {
+		select {
+		case <-c:
+			x = 2
+		default:
+			x = 3
+		}
+		done <- true
+	}()
+	x = 1
+	c <- true
+	_ = x
+	<-done
+}
+*/
diff --git a/src/pkg/runtime/race/testdata/slice_test.go b/src/pkg/runtime/race/testdata/slice_test.go
new file mode 100644
index 0000000..7734636
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/slice_test.go
@@ -0,0 +1,465 @@
+// 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 race_test
+
+import (
+	"testing"
+)
+
+func TestRaceSliceRW(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]int, 2)
+	go func() {
+		a[1] = 1
+		ch <- true
+	}()
+	_ = a[1]
+	<-ch
+}
+
+func TestNoRaceSliceRW(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]int, 2)
+	go func() {
+		a[0] = 1
+		ch <- true
+	}()
+	_ = a[1]
+	<-ch
+}
+
+func TestRaceSliceWW(t *testing.T) {
+	a := make([]int, 10)
+	ch := make(chan bool, 1)
+	go func() {
+		a[1] = 1
+		ch <- true
+	}()
+	a[1] = 2
+	<-ch
+}
+
+func TestNoRaceArrayWW(t *testing.T) {
+	var a [5]int
+	ch := make(chan bool, 1)
+	go func() {
+		a[0] = 1
+		ch <- true
+	}()
+	a[1] = 2
+	<-ch
+}
+
+func TestRaceArrayWW(t *testing.T) {
+	var a [5]int
+	ch := make(chan bool, 1)
+	go func() {
+		a[1] = 1
+		ch <- true
+	}()
+	a[1] = 2
+	<-ch
+}
+
+func TestNoRaceSliceWriteLen(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]bool, 1)
+	go func() {
+		a[0] = true
+		ch <- true
+	}()
+	_ = len(a)
+	<-ch
+}
+
+func TestNoRaceSliceWriteCap(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]uint64, 100)
+	go func() {
+		a[50] = 123
+		ch <- true
+	}()
+	_ = cap(a)
+	<-ch
+}
+
+func TestRaceSliceCopyRead(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]int, 10)
+	b := make([]int, 10)
+	go func() {
+		_ = a[5]
+		ch <- true
+	}()
+	copy(a, b)
+	<-ch
+}
+
+func TestNoRaceSliceWriteCopy(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]int, 10)
+	b := make([]int, 10)
+	go func() {
+		a[5] = 1
+		ch <- true
+	}()
+	copy(a[:5], b[:5])
+	<-ch
+}
+
+func TestRaceSliceCopyWrite2(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]int, 10)
+	b := make([]int, 10)
+	go func() {
+		b[5] = 1
+		ch <- true
+	}()
+	copy(a, b)
+	<-ch
+}
+
+func TestRaceSliceCopyWrite3(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]byte, 10)
+	go func() {
+		a[7] = 1
+		ch <- true
+	}()
+	copy(a, "qwertyqwerty")
+	<-ch
+}
+
+func TestNoRaceSliceCopyRead(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]int, 10)
+	b := make([]int, 10)
+	go func() {
+		_ = b[5]
+		ch <- true
+	}()
+	copy(a, b)
+	<-ch
+}
+
+func TestNoRaceSliceWriteSlice2(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]float64, 10)
+	go func() {
+		a[2] = 1.0
+		ch <- true
+	}()
+	_ = a[0:5]
+	<-ch
+}
+
+func TestRaceSliceWriteSlice(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]float64, 10)
+	go func() {
+		a[2] = 1.0
+		ch <- true
+	}()
+	a = a[5:10]
+	<-ch
+}
+
+func TestNoRaceSliceWriteSlice(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]float64, 10)
+	go func() {
+		a[2] = 1.0
+		ch <- true
+	}()
+	_ = a[5:10]
+	<-ch
+}
+
+func TestNoRaceSliceLenCap(t *testing.T) {
+	ch := make(chan bool, 1)
+	a := make([]struct{}, 10)
+	go func() {
+		_ = len(a)
+		ch <- true
+	}()
+	_ = cap(a)
+	<-ch
+}
+
+func TestNoRaceStructSlicesRangeWrite(t *testing.T) {
+	type Str struct {
+		a []int
+		b []int
+	}
+	ch := make(chan bool, 1)
+	var s Str
+	s.a = make([]int, 10)
+	s.b = make([]int, 10)
+	go func() {
+		for _ = range s.a {
+		}
+		ch <- true
+	}()
+	s.b[5] = 5
+	<-ch
+}
+
+func TestRaceSliceDifferent(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	s2 := s
+	go func() {
+		s[3] = 3
+		c <- true
+	}()
+	// false negative because s2 is PAUTO w/o PHEAP
+	// so we do not instrument it
+	s2[3] = 3
+	<-c
+}
+
+func TestRaceSliceRangeWrite(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		s[3] = 3
+		c <- true
+	}()
+	for _, v := range s {
+		_ = v
+	}
+	<-c
+}
+
+func TestNoRaceSliceRangeWrite(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		s[3] = 3
+		c <- true
+	}()
+	for _ = range s {
+	}
+	<-c
+}
+
+func TestRaceSliceRangeAppend(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		s = append(s, 3)
+		c <- true
+	}()
+	for _ = range s {
+	}
+	<-c
+}
+
+func TestNoRaceSliceRangeAppend(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		_ = append(s, 3)
+		c <- true
+	}()
+	for _ = range s {
+	}
+	<-c
+}
+
+func TestRaceSliceVarWrite(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		s[3] = 3
+		c <- true
+	}()
+	s = make([]int, 20)
+	<-c
+}
+
+func TestRaceSliceVarRead(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		_ = s[3]
+		c <- true
+	}()
+	s = make([]int, 20)
+	<-c
+}
+
+func TestRaceSliceVarRange(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		for _ = range s {
+		}
+		c <- true
+	}()
+	s = make([]int, 20)
+	<-c
+}
+
+func TestRaceSliceVarAppend(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		_ = append(s, 10)
+		c <- true
+	}()
+	s = make([]int, 20)
+	<-c
+}
+
+func TestRaceSliceVarCopy(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		s2 := make([]int, 10)
+		copy(s, s2)
+		c <- true
+	}()
+	s = make([]int, 20)
+	<-c
+}
+
+func TestRaceSliceVarCopy2(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		s2 := make([]int, 10)
+		copy(s2, s)
+		c <- true
+	}()
+	s = make([]int, 20)
+	<-c
+}
+
+// Not implemented.
+func TestRaceFailingSliceAppend(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10, 20)
+	go func() {
+		_ = append(s, 1)
+		c <- true
+	}()
+	_ = append(s, 2)
+	<-c
+}
+
+func TestRaceSliceAppendWrite(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		_ = append(s, 1)
+		c <- true
+	}()
+	s[0] = 42
+	<-c
+}
+
+func TestRaceSliceAppendSlice(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	go func() {
+		s2 := make([]int, 10)
+		_ = append(s, s2...)
+		c <- true
+	}()
+	s[0] = 42
+	<-c
+}
+
+func TestRaceSliceAppendSlice2(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	s2foobar := make([]int, 10)
+	go func() {
+		_ = append(s, s2foobar...)
+		c <- true
+	}()
+	s2foobar[5] = 42
+	<-c
+}
+
+func TestRaceSliceAppendString(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]byte, 10)
+	go func() {
+		_ = append(s, "qwerty"...)
+		c <- true
+	}()
+	s[0] = 42
+	<-c
+}
+
+func TestNoRaceSliceIndexAccess(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	v := 0
+	go func() {
+		_ = v
+		c <- true
+	}()
+	s[v] = 1
+	<-c
+}
+
+func TestNoRaceSliceIndexAccess2(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	v := 0
+	go func() {
+		_ = v
+		c <- true
+	}()
+	_ = s[v]
+	<-c
+}
+
+func TestRaceSliceIndexAccess(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	v := 0
+	go func() {
+		v = 1
+		c <- true
+	}()
+	s[v] = 1
+	<-c
+}
+
+func TestRaceSliceIndexAccess2(t *testing.T) {
+	c := make(chan bool, 1)
+	s := make([]int, 10)
+	v := 0
+	go func() {
+		v = 1
+		c <- true
+	}()
+	_ = s[v]
+	<-c
+}
+
+func TestRaceSliceByteToString(t *testing.T) {
+	c := make(chan string)
+	s := make([]byte, 10)
+	go func() {
+		c <- string(s)
+	}()
+	s[0] = 42
+	<-c
+}
+
+func TestRaceSliceRuneToString(t *testing.T) {
+	c := make(chan string)
+	s := make([]rune, 10)
+	go func() {
+		c <- string(s)
+	}()
+	s[9] = 42
+	<-c
+}
diff --git a/src/pkg/runtime/race/testdata/sync_test.go b/src/pkg/runtime/race/testdata/sync_test.go
new file mode 100644
index 0000000..e80ba3b
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/sync_test.go
@@ -0,0 +1,197 @@
+// 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 race_test
+
+import (
+	"sync"
+	"testing"
+	"time"
+)
+
+func TestNoRaceCond(t *testing.T) { // tsan's test02
+	ch := make(chan bool, 1)
+	var x int = 0
+	var mu sync.Mutex
+	var cond *sync.Cond = sync.NewCond(&mu)
+	var condition int = 0
+	var waker func()
+	waker = func() {
+		x = 1
+		mu.Lock()
+		condition = 1
+		cond.Signal()
+		mu.Unlock()
+	}
+
+	var waiter func()
+	waiter = func() {
+		go waker()
+		cond.L.Lock()
+		for condition != 1 {
+			cond.Wait()
+		}
+		cond.L.Unlock()
+		x = 2
+		ch <- true
+	}
+	go waiter()
+	<-ch
+}
+
+func TestRaceCond(t *testing.T) { // tsan's test50
+	ch := make(chan bool, 2)
+
+	var x int = 0
+	var mu sync.Mutex
+	var condition int = 0
+	var cond *sync.Cond = sync.NewCond(&mu)
+
+	var waker func() = func() {
+		<-time.After(1e5)
+		x = 1
+		mu.Lock()
+		condition = 1
+		cond.Signal()
+		mu.Unlock()
+		<-time.After(1e5)
+		mu.Lock()
+		x = 3
+		mu.Unlock()
+		ch <- true
+	}
+
+	var waiter func() = func() {
+		mu.Lock()
+		for condition != 1 {
+			cond.Wait()
+		}
+		mu.Unlock()
+		x = 2
+		ch <- true
+	}
+	x = 0
+	go waker()
+	go waiter()
+	<-ch
+	<-ch
+}
+
+// We do not currently automatically
+// parse this test. It is intended that the creation
+// stack is observed manually not to contain
+// off-by-one errors
+func TestRaceAnnounceThreads(t *testing.T) {
+	const N = 7
+	allDone := make(chan bool, N)
+
+	var x int
+
+	var f, g, h func()
+	f = func() {
+		x = 1
+		go g()
+		go func() {
+			x = 1
+			allDone <- true
+		}()
+		x = 2
+		allDone <- true
+	}
+
+	g = func() {
+		for i := 0; i < 2; i++ {
+			go func() {
+				x = 1
+				allDone <- true
+			}()
+			allDone <- true
+		}
+	}
+
+	h = func() {
+		x = 1
+		x = 2
+		go f()
+		allDone <- true
+	}
+
+	go h()
+
+	for i := 0; i < N; i++ {
+		<-allDone
+	}
+}
+
+func TestNoRaceAfterFunc1(t *testing.T) {
+	i := 2
+	c := make(chan bool)
+	var f func()
+	f = func() {
+		i--
+		if i >= 0 {
+			time.AfterFunc(0, f)
+		} else {
+			c <- true
+		}
+	}
+
+	time.AfterFunc(0, f)
+	<-c
+}
+
+func TestNoRaceAfterFunc2(t *testing.T) {
+	var x int
+	timer := time.AfterFunc(10, func() {
+		x = 1
+	})
+	defer timer.Stop()
+	_ = x
+}
+
+func TestNoRaceAfterFunc3(t *testing.T) {
+	c := make(chan bool, 1)
+	x := 0
+	time.AfterFunc(1e7, func() {
+		x = 1
+		c <- true
+	})
+	<-c
+}
+
+func TestRaceAfterFunc3(t *testing.T) {
+	c := make(chan bool, 2)
+	x := 0
+	time.AfterFunc(1e7, func() {
+		x = 1
+		c <- true
+	})
+	time.AfterFunc(2e7, func() {
+		x = 2
+		c <- true
+	})
+	<-c
+	<-c
+}
+
+// This test's output is intended to be
+// observed manually. One should check
+// that goroutine creation stack is
+// comprehensible.
+func TestRaceGoroutineCreationStack(t *testing.T) {
+	var x int
+	var ch = make(chan bool, 1)
+
+	f1 := func() {
+		x = 1
+		ch <- true
+	}
+	f2 := func() { go f1() }
+	f3 := func() { go f2() }
+	f4 := func() { go f3() }
+
+	go f4()
+	x = 2
+	<-ch
+}
diff --git a/src/pkg/runtime/race/testdata/waitgroup_test.go b/src/pkg/runtime/race/testdata/waitgroup_test.go
new file mode 100644
index 0000000..7ea21fa
--- /dev/null
+++ b/src/pkg/runtime/race/testdata/waitgroup_test.go
@@ -0,0 +1,232 @@
+// 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 race_test
+
+import (
+	"runtime"
+	"sync"
+	"testing"
+	"time"
+)
+
+func TestNoRaceWaitGroup(t *testing.T) {
+	var x int
+	var wg sync.WaitGroup
+	n := 1
+	for i := 0; i < n; i++ {
+		wg.Add(1)
+		j := i
+		go func() {
+			x = j
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+
+func TestRaceWaitGroup(t *testing.T) {
+	var x int
+	var wg sync.WaitGroup
+	n := 2
+	for i := 0; i < n; i++ {
+		wg.Add(1)
+		j := i
+		go func() {
+			x = j
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+
+func TestNoRaceWaitGroup2(t *testing.T) {
+	var x int
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		x = 1
+		wg.Done()
+	}()
+	wg.Wait()
+	x = 2
+}
+
+// incrementing counter in Add and locking wg's mutex
+func TestRaceWaitGroupAsMutex(t *testing.T) {
+	var x int
+	var wg sync.WaitGroup
+	c := make(chan bool, 2)
+	go func() {
+		wg.Wait()
+		time.Sleep(100 * time.Millisecond)
+		wg.Add(+1)
+		x = 1
+		wg.Add(-1)
+		c <- true
+	}()
+	go func() {
+		wg.Wait()
+		time.Sleep(100 * time.Millisecond)
+		wg.Add(+1)
+		x = 2
+		wg.Add(-1)
+		c <- true
+	}()
+	<-c
+	<-c
+}
+
+// Incorrect usage: Add is too late.
+func TestRaceWaitGroupWrongWait(t *testing.T) {
+	c := make(chan bool, 2)
+	var x int
+	var wg sync.WaitGroup
+	go func() {
+		wg.Add(1)
+		runtime.Gosched()
+		x = 1
+		wg.Done()
+		c <- true
+	}()
+	go func() {
+		wg.Add(1)
+		runtime.Gosched()
+		x = 2
+		wg.Done()
+		c <- true
+	}()
+	wg.Wait()
+	<-c
+	<-c
+}
+
+// A common WaitGroup misuse that can potentially be caught be the race detector.
+// For this simple case we must emulate Add() as read on &wg and Wait() as write on &wg.
+// However it will have false positives if there are several concurrent Wait() calls.
+func TestRaceFailingWaitGroupWrongAdd(t *testing.T) {
+	c := make(chan bool, 2)
+	var wg sync.WaitGroup
+	go func() {
+		wg.Add(1)
+		wg.Done()
+		c <- true
+	}()
+	go func() {
+		wg.Add(1)
+		wg.Done()
+		c <- true
+	}()
+	wg.Wait()
+	<-c
+	<-c
+}
+
+func TestNoRaceWaitGroupMultipleWait(t *testing.T) {
+	c := make(chan bool, 2)
+	var wg sync.WaitGroup
+	go func() {
+		wg.Wait()
+		c <- true
+	}()
+	go func() {
+		wg.Wait()
+		c <- true
+	}()
+	wg.Wait()
+	<-c
+	<-c
+}
+
+func TestNoRaceWaitGroupMultipleWait2(t *testing.T) {
+	c := make(chan bool, 2)
+	var wg sync.WaitGroup
+	wg.Add(2)
+	go func() {
+		wg.Done()
+		wg.Wait()
+		c <- true
+	}()
+	go func() {
+		wg.Done()
+		wg.Wait()
+		c <- true
+	}()
+	wg.Wait()
+	<-c
+	<-c
+}
+
+// Correct usage but still a race
+func TestRaceWaitGroup2(t *testing.T) {
+	var x int
+	var wg sync.WaitGroup
+	wg.Add(2)
+	go func() {
+		x = 1
+		wg.Done()
+	}()
+	go func() {
+		x = 2
+		wg.Done()
+	}()
+	wg.Wait()
+}
+
+func TestNoRaceWaitGroupPanicRecover(t *testing.T) {
+	var x int
+	var wg sync.WaitGroup
+	defer func() {
+		err := recover()
+		if err != "sync: negative WaitGroup counter" {
+			t.Fatalf("Unexpected panic: %#v", err)
+		}
+		x = 2
+	}()
+	x = 1
+	wg.Add(-1)
+}
+
+// TODO: this is actually a panic-synchronization test, not a
+// WaitGroup test. Move it to another *_test file
+// Is it possible to get a race by synchronization via panic?
+func TestNoRaceWaitGroupPanicRecover2(t *testing.T) {
+	var x int
+	var wg sync.WaitGroup
+	ch := make(chan bool, 1)
+	var f func() = func() {
+		x = 2
+		ch <- true
+	}
+	go func() {
+		defer func() {
+			err := recover()
+			if err != "sync: negative WaitGroup counter" {
+			}
+			go f()
+		}()
+		x = 1
+		wg.Add(-1)
+	}()
+
+	<-ch
+}
+
+func TestNoRaceWaitGroupTransitive(t *testing.T) {
+	x, y := 0, 0
+	var wg sync.WaitGroup
+	wg.Add(2)
+	go func() {
+		x = 42
+		wg.Done()
+	}()
+	go func() {
+		time.Sleep(1e7)
+		y = 42
+		wg.Done()
+	}()
+	wg.Wait()
+	_ = x
+	_ = y
+}
diff --git a/src/pkg/runtime/race0.c b/src/pkg/runtime/race0.c
new file mode 100644
index 0000000..1c5f05a
--- /dev/null
+++ b/src/pkg/runtime/race0.c
@@ -0,0 +1,133 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// 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, uintptr step, void *callpc, void *pc)
+{
+	USED(addr);
+	USED(sz);
+	USED(step);
+	USED(callpc);
+	USED(pc);
+}
+
+void
+runtime·racereadrangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc)
+{
+	USED(addr);
+	USED(sz);
+	USED(step);
+	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, void *pc)
+{
+	USED(p);
+	USED(sz);
+	USED(pc);
+}
+
+void
+runtime·racefree(void *p)
+{
+	USED(p);
+}
+
+uintptr
+runtime·racegostart(void *pc)
+{
+	USED(pc);
+	return 0;
+}
+
+void
+runtime·racegoend(void)
+{
+}
diff --git a/src/pkg/runtime/race_amd64.s b/src/pkg/runtime/race_amd64.s
new file mode 100644
index 0000000..83e3009
--- /dev/null
+++ b/src/pkg/runtime/race_amd64.s
@@ -0,0 +1,14 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build race
+
+// func runtime·racefuncenter(pc uintptr)
+TEXT	runtime·racefuncenter(SB), 7, $16
+	MOVQ	DX, saved-8(SP) // save function entry context (for closures)
+	MOVQ	pc+0(FP), DX
+	MOVQ	DX, arg-16(SP)
+	CALL	runtime·racefuncenter1(SB)
+	MOVQ	saved-8(SP), DX
+	RET
diff --git a/src/pkg/runtime/rt0_freebsd_arm.s b/src/pkg/runtime/rt0_freebsd_arm.s
new file mode 100644
index 0000000..085fccf
--- /dev/null
+++ b/src/pkg/runtime/rt0_freebsd_arm.s
@@ -0,0 +1,8 @@
+// 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.
+
+// FreeBSD and Linux use the same linkage to main
+
+TEXT _rt0_arm_freebsd(SB),7,$-4
+	B	_rt0_arm(SB)
diff --git a/src/pkg/runtime/rt0_linux_arm.s b/src/pkg/runtime/rt0_linux_arm.s
index e08cf90..a648160 100644
--- a/src/pkg/runtime/rt0_linux_arm.s
+++ b/src/pkg/runtime/rt0_linux_arm.s
@@ -20,15 +20,27 @@ TEXT _rt0_arm_linux(SB),7,$-4
 	MOVM.DB.W [R0-R3], (R13)
 	MOVW	$4, R0 // SIGILL
 	MOVW	R13, R1 // sa
-	MOVW	$0, R2 // old_sa
+	SUB	$16, R13
+	MOVW	R13, R2 // old_sa
 	MOVW	$8, R3 // c
 	MOVW	$174, R7 // sys_sigaction
 	BL	oabi_syscall<>(SB)
-	ADD 	$16, R13
+
 	// do an EABI syscall
 	MOVW	$20, R7 // sys_getpid
-	SWI 	$0 // this will trigger SIGILL on OABI systems
+	SWI	$0 // this will trigger SIGILL on OABI systems
+	
+	MOVW	$4, R0  // SIGILL
+	MOVW	R13, R1 // sa
+	MOVW	$0, R2 // old_sa
+	MOVW	$8, R3 // c
+	MOVW	$174, R7 // sys_sigaction
+	SWI	$0 // restore signal handler
+	ADD	$32, R13
 
+	SUB	$4, R13 // fake a stack frame for runtime·setup_auxv
+	BL	runtime·setup_auxv(SB)
+	ADD	$4, R13
 	B	_rt0_arm(SB)
 
 TEXT bad_abi<>(SB),7,$-4
diff --git a/src/pkg/runtime/rt0_netbsd_arm.s b/src/pkg/runtime/rt0_netbsd_arm.s
new file mode 100644
index 0000000..8c1588f
--- /dev/null
+++ b/src/pkg/runtime/rt0_netbsd_arm.s
@@ -0,0 +1,8 @@
+// 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.
+
+// FreeBSD/NetBSD and Linux use the same linkage to main
+
+TEXT _rt0_arm_netbsd(SB),7,$-4
+	B _rt0_arm(SB)
diff --git a/src/pkg/runtime/rt0_plan9_386.s b/src/pkg/runtime/rt0_plan9_386.s
index b56c8b3..56f3a0f 100644
--- a/src/pkg/runtime/rt0_plan9_386.s
+++ b/src/pkg/runtime/rt0_plan9_386.s
@@ -25,6 +25,7 @@ argv_fix:
 	ADDL	$4, BP
 	LOOP	argv_fix
 	
+	CALL	runtime·asminit(SB)
 	JMP	_rt0_386(SB)
 
 DATA  runtime·isplan9(SB)/4, $1
diff --git a/src/pkg/runtime/rt0_plan9_amd64.s b/src/pkg/runtime/rt0_plan9_amd64.s
new file mode 100644
index 0000000..2b1fa2a
--- /dev/null
+++ b/src/pkg/runtime/rt0_plan9_amd64.s
@@ -0,0 +1,11 @@
+// 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.
+
+TEXT _rt0_amd64_plan9(SB),7, $0
+	MOVQ	$_rt0_amd64(SB), AX
+	MOVQ	SP, DI
+	JMP	AX
+
+DATA runtime·isplan9(SB)/4, $1
+GLOBL runtime·isplan9(SB), $4
diff --git a/src/pkg/runtime/rt0_windows_386.s b/src/pkg/runtime/rt0_windows_386.s
index 3b023de..a06aa78 100644
--- a/src/pkg/runtime/rt0_windows_386.s
+++ b/src/pkg/runtime/rt0_windows_386.s
@@ -3,11 +3,6 @@
 // license that can be found in the LICENSE file.
 
 TEXT _rt0_386_windows(SB),7,$0
-	// Set up SEH frame for bootstrap m
-	PUSHL	$runtime·sigtramp(SB)
-	PUSHL	0(FS)
-	MOVL	SP, 0(FS)
-
 	JMP	_rt0_386(SB)
 
 DATA  runtime·iswindows(SB)/4, $1
diff --git a/src/pkg/runtime/rune.c b/src/pkg/runtime/rune.c
index 86ee76d..ed86726 100644
--- a/src/pkg/runtime/rune.c
+++ b/src/pkg/runtime/rune.c
@@ -47,6 +47,9 @@ enum
 	Runeerror	= 0xFFFD,
 	Runeself	= 0x80,
 
+	SurrogateMin = 0xD800,
+	SurrogateMax = 0xDFFF,
+
 	Bad	= Runeerror,
 
 	Runemax	= 0x10FFFF,	/* maximum rune value */
@@ -128,6 +131,8 @@ runtime·charntorune(int32 *rune, uint8 *str, int32 length)
 		l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
 		if(l <= Rune2)
 			goto bad;
+		if (SurrogateMin <= l && l <= SurrogateMax)
+			goto bad;
 		*rune = l;
 		return 3;
 	}
@@ -193,13 +198,15 @@ runtime·runetochar(byte *str, int32 rune)  /* note: in original, arg2 was point
 	}
 
 	/*
-	 * If the Rune is out of range, convert it to the error rune.
+	 * 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
diff --git a/src/pkg/runtime/runtime-gdb.py b/src/pkg/runtime/runtime-gdb.py
index 629c39e..eff9a40 100644
--- a/src/pkg/runtime/runtime-gdb.py
+++ b/src/pkg/runtime/runtime-gdb.py
@@ -149,8 +149,8 @@ goobjfile.pretty_printers.extend([makematcher(k) for k in vars().values() if has
 
 #
 #  For reference, this is what we're trying to do:
-#  eface: p *(*(struct 'runtime.commonType'*)'main.e'->type_->data)->string
-#  iface: p *(*(struct 'runtime.commonType'*)'main.s'->tab->Type->data)->string
+#  eface: p *(*(struct 'runtime.rtype'*)'main.e'->type_->data)->string
+#  iface: p *(*(struct 'runtime.rtype'*)'main.s'->tab->Type->data)->string
 #
 # interface types can't be recognized by their name, instead we check
 # if they have the expected fields.  Unfortunately the mapping of
@@ -186,8 +186,7 @@ def lookup_type(name):
 	except:
 		pass
 
-_rctp_type = gdb.lookup_type("struct runtime.commonType").pointer()
-_rtp_type = gdb.lookup_type("struct runtime._type").pointer()
+_rctp_type = gdb.lookup_type("struct runtime.rtype").pointer()
 
 def iface_commontype(obj):
 	if is_iface(obj):
@@ -196,18 +195,13 @@ def iface_commontype(obj):
 		go_type_ptr = obj['_type']
 	else:
 		return
-
-	# sanity check: reflection type description ends in a loop.
-	tt = go_type_ptr['_type'].cast(_rtp_type).dereference()['_type']
-	if tt != tt.cast(_rtp_type).dereference()['_type']:
-		return
 	
-	return go_type_ptr['ptr'].cast(_rctp_type).dereference()
+	return go_type_ptr.cast(_rctp_type).dereference()
 	
 
 def iface_dtype(obj):
 	"Decode type of the data field of an eface or iface struct."
-	# known issue: dtype_name decoded from runtime.commonType is "nested.Foo"
+	# known issue: dtype_name decoded from runtime.rtype is "nested.Foo"
 	# but the dwarf table lists it as "full/path/to/nested.Foo"
 
 	dynamic_go_type = iface_commontype(obj)
@@ -381,6 +375,7 @@ class GoroutineCmd(gdb.Command):
 
 	def invoke(self, arg, from_tty):
 		goid, cmd = arg.split(None, 1)
+		goid = gdb.parse_and_eval(goid)
 		pc, sp = find_goroutine(int(goid))
 		if not pc:
 			print "No such goroutine: ", goid
diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c
index ebb5544..4d57cba 100644
--- a/src/pkg/runtime/runtime.c
+++ b/src/pkg/runtime/runtime.c
@@ -3,15 +3,12 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
-#include "stack.h"
+#include "arch_GOARCH.h"
 
 enum {
 	maxround = sizeof(uintptr),
 };
 
-uint32	runtime·panicking;
-void	(*runtime·destroylock)(Lock*);
-
 /*
  * We assume that all architectures turn faults and the like
  * into apparent calls to runtime.sigpanic.  If we see a "call"
@@ -31,103 +28,6 @@ runtime·gotraceback(void)
 	return runtime·atoi(p);
 }
 
-static Lock paniclk;
-
-void
-runtime·startpanic(void)
-{
-	if(m->dying) {
-		runtime·printf("panic during panic\n");
-		runtime·exit(3);
-	}
-	m->dying = 1;
-	runtime·xadd(&runtime·panicking, 1);
-	runtime·lock(&paniclk);
-}
-
-void
-runtime·dopanic(int32 unused)
-{
-	static bool didothers;
-
-	if(g->sig != 0)
-		runtime·printf("[signal %x code=%p addr=%p pc=%p]\n",
-			g->sig, g->sigcode0, g->sigcode1, g->sigpc);
-
-	if(runtime·gotraceback()){
-		if(g != m->g0) {
-			runtime·printf("\n");
-			runtime·goroutineheader(g);
-			runtime·traceback(runtime·getcallerpc(&unused), 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);
-	}
-
-	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");
-}
-
-void
-runtime·throw(int8 *s)
-{
-	runtime·startpanic();
-	runtime·printf("throw: %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;
-
-	if(m->gcing) {
-		runtime·printf("panic: %s\n", s);
-		runtime·throw("panic during gc");
-	}
-	runtime·newErrorString(runtime·gostringnocopy((byte*)s), &err);
-	runtime·panic(err);
-}
-
 int32
 runtime·mcmp(byte *s1, byte *s2, uint32 n)
 {
@@ -155,30 +55,21 @@ runtime·mchr(byte *p, byte c, byte *ep)
 	return nil;
 }
 
-uint32
-runtime·rnd(uint32 n, uint32 m)
-{
-	uint32 r;
-
-	if(m > maxround)
-		m = maxround;
-	r = n % m;
-	if(r)
-		n += m-r;
-	return n;
-}
-
 static int32	argc;
 static uint8**	argv;
 
 Slice os·Args;
 Slice syscall·envs;
 
+void (*runtime·sysargs)(int32, uint8**);
+
 void
 runtime·args(int32 c, uint8 **v)
 {
 	argc = c;
 	argv = v;
+	if(runtime·sysargs != nil)
+		runtime·sysargs(c, v);
 }
 
 int32 runtime·isplan9;
@@ -219,33 +110,6 @@ runtime·goenvs_unix(void)
 	syscall·envs.cap = n;
 }
 
-byte*
-runtime·getenv(int8 *s)
-{
-	int32 i, j, 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
 runtime·getgoroot(String out)
 {
@@ -267,6 +131,33 @@ runtime·atoi(byte *p)
 	return n;
 }
 
+static void
+TestAtomic64(void)
+{
+	uint64 z64, x64;
+
+	z64 = 42;
+	x64 = 0;
+	PREFETCH(&z64);
+	if(runtime·cas64(&z64, &x64, 1))
+		runtime·throw("cas64 failed");
+	if(x64 != 42)
+		runtime·throw("cas64 failed");
+	if(!runtime·cas64(&z64, &x64, 1))
+		runtime·throw("cas64 failed");
+	if(x64 != 42 || z64 != 1)
+		runtime·throw("cas64 failed");
+	if(runtime·atomicload64(&z64) != 1)
+		runtime·throw("load64 failed");
+	runtime·atomicstore64(&z64, (1ull<<40)+1);
+	if(runtime·atomicload64(&z64) != (1ull<<40)+1)
+		runtime·throw("store64 failed");
+	if(runtime·xadd64(&z64, (1ull<<40)+1) != (2ull<<40)+2)
+		runtime·throw("xadd64 failed");
+	if(runtime·atomicload64(&z64) != (2ull<<40)+2)
+		runtime·throw("xadd64 failed");
+}
+
 void
 runtime·check(void)
 {
@@ -342,10 +233,12 @@ runtime·check(void)
 		runtime·throw("float32nan2");
 	if(!(i != i1))
 		runtime·throw("float32nan3");
+
+	TestAtomic64();
 }
 
 void
-runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool)
+runtime·Caller(intgo skip, uintptr retpc, String retfile, intgo retline, bool retbool)
 {
 	Func *f, *g;
 	uintptr pc;
@@ -382,7 +275,7 @@ runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool r
 }
 
 void
-runtime·Callers(int32 skip, Slice pc, int32 retn)
+runtime·Callers(intgo skip, Slice pc, intgo retn)
 {
 	// runtime.callers uses pc.array==nil as a signal
 	// to print a stack trace.  Pick off 0-length pc here
@@ -413,3 +306,40 @@ runtime·fastrand1(void)
 	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;
+}
+
+void
+runtime∕pprof·runtime_cyclesPerSecond(int64 res)
+{
+	res = runtime·tickspersecond();
+	FLUSH(&res);
+}
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 6f5aea1..08f43a6 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -19,9 +19,13 @@ typedef	double			float64;
 #ifdef _64BIT
 typedef	uint64		uintptr;
 typedef	int64		intptr;
+typedef	int64		intgo; // Go's int
+typedef	uint64		uintgo; // Go's uint
 #else
 typedef	uint32		uintptr;
-typedef int32		intptr;
+typedef	int32		intptr;
+typedef	int32		intgo; // Go's int
+typedef	uint32		uintgo; // Go's uint
 #endif
 
 /*
@@ -48,44 +52,53 @@ typedef	struct	G		G;
 typedef	struct	Gobuf		Gobuf;
 typedef	union	Lock		Lock;
 typedef	struct	M		M;
+typedef	struct	P		P;
 typedef	struct	Mem		Mem;
 typedef	union	Note		Note;
 typedef	struct	Slice		Slice;
 typedef	struct	Stktop		Stktop;
 typedef	struct	String		String;
+typedef	struct	FuncVal		FuncVal;
 typedef	struct	SigTab		SigTab;
 typedef	struct	MCache		MCache;
 typedef	struct	FixAlloc	FixAlloc;
 typedef	struct	Iface		Iface;
 typedef	struct	Itab		Itab;
+typedef	struct	InterfaceType	InterfaceType;
 typedef	struct	Eface		Eface;
 typedef	struct	Type		Type;
 typedef	struct	ChanType		ChanType;
 typedef	struct	MapType		MapType;
 typedef	struct	Defer		Defer;
+typedef	struct	DeferChunk	DeferChunk;
 typedef	struct	Panic		Panic;
 typedef	struct	Hmap		Hmap;
 typedef	struct	Hchan		Hchan;
 typedef	struct	Complex64	Complex64;
 typedef	struct	Complex128	Complex128;
 typedef	struct	WinCall		WinCall;
+typedef	struct	SEH		SEH;
 typedef	struct	Timers		Timers;
 typedef	struct	Timer		Timer;
+typedef	struct	GCStats		GCStats;
+typedef	struct	LFNode		LFNode;
+typedef	struct	ParFor		ParFor;
+typedef	struct	ParForThread	ParForThread;
+typedef	struct	CgoMal		CgoMal;
 
 /*
- * per-cpu declaration.
- * "extern register" is a special storage class implemented by 6c, 8c, etc.
- * on machines with lots of registers, it allocates a register that will not be
- * used in generated code.  on the x86, it allocates a slot indexed by a
- * segment register.
+ * Per-CPU declaration.
  *
- * amd64: allocated downwards from R15
- * x86: allocated upwards from 0(GS)
- * arm: allocated downwards from R10
+ * "extern register" is a special storage class implemented by 6c, 8c, etc.
+ * On the ARM, it is an actual register; elsewhere it is a slot in thread-
+ * local storage indexed by a segment register. 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(GS) as -16(FS).
  *
- * every C file linked into a Go program must include runtime.h
- * so that the C compiler knows to avoid other uses of these registers.
- * the Go compilers know to avoid them.
+ * 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;
@@ -105,14 +118,34 @@ enum
 	Grunning,
 	Gsyscall,
 	Gwaiting,
-	Gmoribund,
+	Gmoribund_unused,  // currently unused, but hardcoded in gdb scripts
 	Gdead,
 };
 enum
 {
+	// P status
+	Pidle,
+	Prunning,
+	Psyscall,
+	Pgcstop,
+	Pdead,
+};
+enum
+{
 	true	= 1,
 	false	= 0,
 };
+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
@@ -130,7 +163,12 @@ union	Note
 struct String
 {
 	byte*	str;
-	int32	len;
+	intgo	len;
+};
+struct FuncVal
+{
+	void	(*fn)(void);
+	// variable-size, fn-specific data here
 };
 struct Iface
 {
@@ -156,47 +194,61 @@ struct Complex128
 struct	Slice
 {				// must not move anything
 	byte*	array;		// actual data
-	uint32	len;		// number of elements
-	uint32	cap;		// allocated number of elements
+	uintgo	len;		// number of elements
+	uintgo	cap;		// allocated number of elements
 };
 struct	Gobuf
 {
 	// The offsets of these fields are known to (hard-coded in) libmach.
-	byte*	sp;
+	uintptr	sp;
 	byte*	pc;
 	G*	g;
 };
+struct	GCStats
+{
+	// the struct must consist of only uint64's,
+	// because it is casted to uint64[].
+	uint64	nhandoff;
+	uint64	nhandoffcnt;
+	uint64	nprocyield;
+	uint64	nosyield;
+	uint64	nsleep;
+};
 struct	G
 {
-	byte*	stackguard;	// cannot move - also known to linker, libmach, runtime/cgo
-	byte*	stackbase;	// cannot move - also known to libmach, runtime/cgo
+	uintptr	stackguard;	// cannot move - also known to linker, libmach, runtime/cgo
+	uintptr	stackbase;	// cannot move - also known to libmach, runtime/cgo
 	Defer*	defer;
 	Panic*	panic;
 	Gobuf	sched;
-	byte*	gcstack;		// if status==Gsyscall, gcstack = stackbase to use during gc
-	byte*	gcsp;		// if status==Gsyscall, gcsp = sched.sp to use during gc
-	byte*	gcguard;		// if status==Gsyscall, gcguard = stackguard to use during gc
-	byte*	stack0;
-	byte*	entry;		// initial function
+	uintptr	gcstack;		// if status==Gsyscall, gcstack = stackbase to use during gc
+	uintptr	gcsp;		// if status==Gsyscall, gcsp = sched.sp to use during gc
+	byte*	gcpc;		// if status==Gsyscall, gcpc = sched.pc to use during gc
+	uintptr	gcguard;		// if status==Gsyscall, gcguard = stackguard to use during gc
+	uintptr	stack0;
+	FuncVal*	fnstart;		// initial function
 	G*	alllink;	// on allg
 	void*	param;		// passed parameter on wakeup
 	int16	status;
-	int32	goid;
+	int64	goid;
 	uint32	selgen;		// valid sudog pointer
 	int8*	waitreason;	// if status==Gwaiting
 	G*	schedlink;
-	bool	readyonstop;
 	bool	ispanic;
+	bool	issystem;
+	int8	raceignore; // ignore race detection events
 	M*	m;		// for debuggers, but offset not hard-coded
 	M*	lockedm;
-	M*	idlem;
 	int32	sig;
 	int32	writenbuf;
 	byte*	writebuf;
+	DeferChunk	*dchunk;
+	DeferChunk	*dchunknext;
 	uintptr	sigcode0;
 	uintptr	sigcode1;
 	uintptr	sigpc;
 	uintptr	gopc;	// pc of go statement that created this goroutine
+	uintptr	racectx;
 	uintptr	end[];
 };
 struct	M
@@ -213,43 +265,98 @@ struct	M
 	uintptr	cret;		// return value from C
 	uint64	procid;		// for debuggers, but offset not hard-coded
 	G*	gsignal;	// signal-handling G
-	uint32	tls[8];		// thread-local storage (for 386 extern register)
+	uintptr	tls[4];		// thread-local storage (for x86 extern register)
+	void	(*mstartfn)(void);
 	G*	curg;		// current running goroutine
+	P*	p;		// attached P for executing Go code (nil if not executing Go code)
+	P*	nextp;
 	int32	id;
 	int32	mallocing;
+	int32	throwing;
 	int32	gcing;
 	int32	locks;
 	int32	nomemprof;
-	int32	waitnextg;
 	int32	dying;
 	int32	profilehz;
 	int32	helpgc;
+	bool	blockingsyscall;
+	bool	spinning;
 	uint32	fastrand;
-	uint64	ncgocall;
-	Note	havenextg;
-	G*	nextg;
+	uint64	ncgocall;	// number of cgo calls in total
+	int32	ncgo;		// number of cgo calls currently in progress
+	CgoMal*	cgomal;
+	Note	park;
 	M*	alllink;	// on allm
 	M*	schedlink;
 	uint32	machport;	// Return address for Mach IPC (OS X)
 	MCache	*mcache;
-	FixAlloc	*stackalloc;
+	int32	stackinuse;
+	uint32	stackcachepos;
+	uint32	stackcachecnt;
+	void*	stackcache[StackCacheSize];
 	G*	lockedg;
-	G*	idleg;
 	uintptr	createstack[32];	// Stack that created this thread.
 	uint32	freglo[16];	// D[i] lsb and F[i]
 	uint32	freghi[16];	// D[i] msb and F[i+16]
 	uint32	fflag;		// floating point compare flags
+	uint32	locked;	// tracking for LockOSThread
 	M*	nextwaitm;	// next M waiting for lock
 	uintptr	waitsema;	// semaphore for parking on locks
 	uint32	waitsemacount;
 	uint32	waitsemalock;
+	GCStats	gcstats;
+	bool	racecall;
+	bool	needextram;
+	void*	racepc;
+	void	(*waitunlockf)(Lock*);
+	Lock*	waitlock;
+	uint32	moreframesize_minalloc;
+
+	uintptr	settype_buf[1024];
+	uintptr	settype_bufsize;
 
 #ifdef GOOS_windows
 	void*	thread;		// thread handle
 #endif
+#ifdef GOOS_plan9
+	int8*		notesig;
+#endif
+	SEH*	seh;
 	uintptr	end[];
 };
 
+struct P
+{
+	Lock;
+
+	uint32	status;  // one of Pidle/Prunning/...
+	P*	link;
+	uint32	tick;   // incremented on every scheduler or system call
+	M*	m;	// back-link to associated M (nil if idle)
+	MCache*	mcache;
+
+	// Queue of runnable goroutines.
+	G**	runq;
+	int32	runqhead;
+	int32	runqtail;
+	int32	runqsize;
+
+	// Available G's (status == Gdead)
+	G*	gfree;
+	int32	gfreecnt;
+
+	byte	pad[64];
+};
+
+// The m->locked word holds a single bit saying whether
+// external calls to LockOSThread are in effect, and then a counter
+// of the internal nesting depth of lockOSThread / unlockOSThread.
+enum
+{
+	LockExternal = 1,
+	LockInternal = 2,
+};
+
 struct	Stktop
 {
 	// The offsets of these fields are known to (hard-coded in) libmach.
@@ -288,8 +395,19 @@ struct	Func
 	uintptr	pc0;	// starting pc, ln for table
 	int32	ln0;
 	int32	frame;	// stack frame size
-	int32	args;	// number of 32-bit in/out args
-	int32	locals;	// number of 32-bit locals
+	int32	args;	// in/out args size
+	int32	locals;	// locals size
+};
+
+// layout of Itab known to compilers
+struct	Itab
+{
+	InterfaceType*	inter;
+	Type*	type;
+	Itab*	link;
+	int32	bad;
+	int32	unused;
+	void	(*fun[])(void);
 };
 
 struct	WinCall
@@ -301,6 +419,11 @@ struct	WinCall
 	uintptr	r2;
 	uintptr	err;	// error number
 };
+struct	SEH
+{
+	void*	prev;
+	void*	handler;
+};
 
 #ifdef GOOS_windows
 enum {
@@ -335,10 +458,46 @@ struct	Timer
 	// a well-behaved function and not block.
 	int64	when;
 	int64	period;
-	void	(*f)(int64, Eface);
+	FuncVal	*fv;
 	Eface	arg;
 };
 
+// Lock-free stack node.
+struct LFNode
+{
+	LFNode	*next;
+	uintptr	pushcnt;
+};
+
+// Parallel for descriptor.
+struct ParFor
+{
+	void (*body)(ParFor*, uint32);	// executed for each element
+	uint32 done;			// number of idle threads
+	uint32 nthr;			// total number of threads
+	uint32 nthrmax;			// maximum number of threads
+	uint32 thrseq;			// thread id sequencer
+	uint32 cnt;			// iteration space [0, cnt)
+	void *ctx;			// arbitrary user context
+	bool wait;			// if true, wait while all threads finish processing,
+					// otherwise parfor may return while other threads are still working
+	ParForThread *thr;		// array of thread descriptors
+	// stats
+	uint64 nsteal;
+	uint64 nstealcnt;
+	uint64 nprocyield;
+	uint64 nosyield;
+	uint64 nsleep;
+};
+
+// Track memory allocated by code not written in Go during a cgo call,
+// so that the garbage collector can see them.
+struct CgoMal
+{
+	CgoMal	*next;
+	byte	*alloc;
+};
+
 /*
  * defined macros
  *    you need super-gopher-guru privilege
@@ -347,6 +506,7 @@ struct	Timer
 #define	nelem(x)	(sizeof(x)/sizeof((x)[0]))
 #define	nil		((void*)0)
 #define	offsetof(s,m)	(uint32)(&(((s*)0)->m))
+#define	ROUND(x, n)	(((x)+(n)-1)&~((n)-1)) /* all-caps to mark as macro: it evaluates n twice */
 
 /*
  * known to compiler
@@ -430,12 +590,19 @@ void	runtime·nilintercopy(uintptr, void*, void*);
 struct Defer
 {
 	int32	siz;
-	bool	nofree;
+	bool	special; // not part of defer frame
+	bool	free; // if special, free when done
 	byte*	argp;  // where args were copied from
 	byte*	pc;
-	byte*	fn;
+	FuncVal*	fn;
 	Defer*	link;
-	byte	args[8];	// padded to actual size
+	void*	args[1];	// padded to actual size
+};
+
+struct DeferChunk
+{
+	DeferChunk	*prev;
+	uintptr	off;
 };
 
 /*
@@ -453,16 +620,21 @@ struct Panic
  * external data
  */
 extern	String	runtime·emptystring;
-G*	runtime·allg;
-G*	runtime·lastg;
-M*	runtime·allm;
+extern	uintptr runtime·zerobase;
+extern	G*	runtime·allg;
+extern	G*	runtime·lastg;
+extern	M*	runtime·allm;
+extern	P**	runtime·allp;
 extern	int32	runtime·gomaxprocs;
 extern	bool	runtime·singleproc;
 extern	uint32	runtime·panicking;
-extern	int32	runtime·gcwaiting;		// gc is waiting to run
-int8*	runtime·goos;
-int32	runtime·ncpu;
+extern	uint32	runtime·gcwaiting;		// gc is waiting to run
+extern	int8*	runtime·goos;
+extern	int32	runtime·ncpu;
 extern	bool	runtime·iscgo;
+extern 	void	(*runtime·sysargs)(int32, uint8**);
+extern	uint32	runtime·maxstring;
+extern	uint32	runtime·Hchansize;
 
 /*
  * common functions and data
@@ -481,7 +653,8 @@ int32	runtime·charntorune(int32*, uint8*, int32);
 #define FLUSH(x)	USED(x)
 
 void	runtime·gogo(Gobuf*, uintptr);
-void	runtime·gogocall(Gobuf*, void(*)(void));
+void	runtime·gogocall(Gobuf*, void(*)(void), uintptr);
+void	runtime·gogocallfn(Gobuf*, FuncVal*);
 void	runtime·gosave(Gobuf*);
 void	runtime·lessstack(void);
 void	runtime·goargs(void);
@@ -490,7 +663,6 @@ void	runtime·goenvs_unix(void);
 void*	runtime·getu(void);
 void	runtime·throw(int8*);
 void	runtime·panicstring(int8*);
-uint32	runtime·rnd(uint32, uint32);
 void	runtime·prints(int8*);
 void	runtime·printf(int8*, ...);
 byte*	runtime·mchr(byte*, byte, byte*);
@@ -499,8 +671,8 @@ void	runtime·memmove(void*, void*, uint32);
 void*	runtime·mal(uintptr);
 String	runtime·catstring(String, String);
 String	runtime·gostring(byte*);
-String  runtime·gostringn(byte*, int32);
-Slice	runtime·gobytes(byte*, int32);
+String  runtime·gostringn(byte*, intgo);
+Slice	runtime·gobytes(byte*, intgo);
 String	runtime·gostringnocopy(byte*);
 String	runtime·gostringw(uint16*);
 void	runtime·initsig(void);
@@ -512,38 +684,47 @@ void	runtime·tracebackothers(G*);
 int32	runtime·write(int32, void*, int32);
 int32	runtime·mincore(void*, uintptr, byte*);
 bool	runtime·cas(uint32*, uint32, uint32);
+bool	runtime·cas64(uint64*, uint64*, uint64);
 bool	runtime·casp(void**, void*, void*);
 // Don't confuse with XADD x86 instruction,
 // this one is actually 'addx', that is, add-and-fetch.
 uint32	runtime·xadd(uint32 volatile*, int32);
+uint64	runtime·xadd64(uint64 volatile*, int64);
 uint32	runtime·xchg(uint32 volatile*, uint32);
 uint32	runtime·atomicload(uint32 volatile*);
 void	runtime·atomicstore(uint32 volatile*, uint32);
+void	runtime·atomicstore64(uint64 volatile*, uint64);
+uint64	runtime·atomicload64(uint64 volatile*);
 void*	runtime·atomicloadp(void* volatile*);
 void	runtime·atomicstorep(void* volatile*, void*);
-void	runtime·jmpdefer(byte*, void*);
+void	runtime·jmpdefer(FuncVal*, void*);
 void	runtime·exit1(int32);
 void	runtime·ready(G*);
 byte*	runtime·getenv(int8*);
 int32	runtime·atoi(byte*);
-void	runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void));
-void	runtime·signalstack(byte*, int32);
+void	runtime·newosproc(M *mp, void *stk);
+void	runtime·mstart(void);
 G*	runtime·malg(int32);
 void	runtime·asminit(void);
+void	runtime·mpreinit(M*);
 void	runtime·minit(void);
+void	runtime·unminit(void);
+void	runtime·signalstack(byte*, int32);
 Func*	runtime·findfunc(uintptr);
 int32	runtime·funcline(Func*, uintptr);
 void*	runtime·stackalloc(uint32);
 void	runtime·stackfree(void*, uintptr);
 MCache*	runtime·allocmcache(void);
+void	runtime·freemcache(MCache*);
 void	runtime·mallocinit(void);
+void	runtime·mprofinit(void);
 bool	runtime·ifaceeq_c(Iface, Iface);
 bool	runtime·efaceeq_c(Eface, Eface);
-uintptr	runtime·ifacehash(Iface);
-uintptr	runtime·efacehash(Eface);
+uintptr	runtime·ifacehash(Iface, uintptr);
+uintptr	runtime·efacehash(Eface, uintptr);
 void*	runtime·malloc(uintptr size);
 void	runtime·free(void *v);
-bool	runtime·addfinalizer(void*, void(*fn)(void*), int32);
+bool	runtime·addfinalizer(void*, FuncVal *fn, uintptr);
 void	runtime·runpanic(Panic*);
 void*	runtime·getcallersp(void*);
 int32	runtime·mcount(void);
@@ -551,27 +732,35 @@ int32	runtime·gcount(void);
 void	runtime·mcall(void(*)(G*));
 uint32	runtime·fastrand1(void);
 
+void runtime·setmg(M*, G*);
+void runtime·newextram(void);
 void	runtime·exit(int32);
 void	runtime·breakpoint(void);
 void	runtime·gosched(void);
-void	runtime·tsleep(int64);
+void	runtime·park(void(*)(Lock*), Lock*, int8*);
+void	runtime·tsleep(int64, int8*);
 M*	runtime·newm(void);
 void	runtime·goexit(void);
 void	runtime·asmcgocall(void (*fn)(void*), void*);
 void	runtime·entersyscall(void);
+void	runtime·entersyscallblock(void);
 void	runtime·exitsyscall(void);
-G*	runtime·newproc1(byte*, byte*, int32, int32, void*);
+G*	runtime·newproc1(FuncVal*, byte*, int32, int32, void*);
 bool	runtime·sigsend(int32 sig);
 int32	runtime·callers(int32, uintptr*, int32);
 int32	runtime·gentraceback(byte*, byte*, byte*, G*, int32, uintptr*, int32);
 int64	runtime·nanotime(void);
 void	runtime·dopanic(int32);
 void	runtime·startpanic(void);
+void	runtime·unwindstack(G*, byte*);
 void	runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp);
 void	runtime·resetcpuprofiler(int32);
 void	runtime·setcpuprofilerate(void(*)(uintptr*, int32), int32);
 void	runtime·usleep(uint32);
 int64	runtime·cputicks(void);
+int64	runtime·tickspersecond(void);
+void	runtime·blockevent(int64, int32);
+extern int64 runtime·blockprofilerate;
 
 #pragma	varargck	argpos	runtime·printf	1
 #pragma	varargck	type	"d"	int32
@@ -589,7 +778,7 @@ int64	runtime·cputicks(void);
 #pragma	varargck	type	"S"	String
 
 void	runtime·stoptheworld(void);
-void	runtime·starttheworld(bool);
+void	runtime·starttheworld(void);
 extern uint32 runtime·worldsema;
 
 /*
@@ -636,6 +825,27 @@ void	runtime·futexsleep(uint32*, uint32, int64);
 void	runtime·futexwakeup(uint32*, uint32);
 
 /*
+ * Lock-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.
+ */
+void	runtime·lfstackpush(uint64 *head, LFNode *node);
+LFNode*	runtime·lfstackpop(uint64 *head);
+
+/*
+ * Parallel for over [0, n).
+ * body() is executed for each iteration.
+ * nthr - total number of worker threads.
+ * ctx - arbitrary user context.
+ * if wait=true, threads return from parfor() when all work is done;
+ * otherwise, threads can return while other threads are still finishing processing.
+ */
+ParFor*	runtime·parforalloc(uint32 nthrmax);
+void	runtime·parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32));
+void	runtime·parfordo(ParFor *desc);
+
+/*
  * This is consistent across Linux and BSD.
  * If a new OS is added that is different, move this to
  * $GOOS/$GOARCH/defs.h.
@@ -645,6 +855,9 @@ void	runtime·futexwakeup(uint32*, uint32);
 /*
  * low level C-called
  */
+// for mmap, we only pass the lower 32 bits of file offset to the 
+// assembly routine; the higher bits (if required), should be provided
+// by the assembly routine as 0.
 uint8*	runtime·mmap(byte*, uintptr, int32, int32, int32, uint32);
 void	runtime·munmap(byte*, uintptr);
 void	runtime·madvise(byte*, uintptr, int32);
@@ -656,6 +869,7 @@ void*	runtime·getcallerpc(void*);
  * runtime go-called
  */
 void	runtime·printbool(bool);
+void	runtime·printbyte(int8);
 void	runtime·printfloat(float64);
 void	runtime·printint(int64);
 void	runtime·printiface(Iface);
@@ -667,7 +881,7 @@ void	runtime·printuint(uint64);
 void	runtime·printhex(uint64);
 void	runtime·printslice(Slice);
 void	runtime·printcomplex(Complex128);
-void	reflect·call(byte*, byte*, uint32);
+void	reflect·call(FuncVal*, byte*, uint32);
 void	runtime·panic(Eface);
 void	runtime·panicindex(void);
 void	runtime·panicslice(void);
@@ -708,8 +922,8 @@ void	runtime·semrelease(uint32*);
 int32	runtime·gomaxprocsfunc(int32 n);
 void	runtime·procyield(uint32);
 void	runtime·osyield(void);
-void	runtime·LockOSThread(void);
-void	runtime·UnlockOSThread(void);
+void	runtime·lockOSThread(void);
+void	runtime·unlockOSThread(void);
 
 void	runtime·mapassign(MapType*, Hmap*, byte*, byte*);
 void	runtime·mapaccess(MapType*, Hmap*, byte*, byte*, bool*);
@@ -719,13 +933,11 @@ void	runtime·mapiterkeyvalue(struct hash_iter*, void*, void*);
 Hmap*	runtime·makemap_c(MapType*, int64);
 
 Hchan*	runtime·makechan_c(ChanType*, int64);
-void	runtime·chansend(ChanType*, Hchan*, byte*, bool*);
+void	runtime·chansend(ChanType*, Hchan*, byte*, bool*, void*);
 void	runtime·chanrecv(ChanType*, Hchan*, byte*, bool*, bool*);
-int32	runtime·chanlen(Hchan*);
-int32	runtime·chancap(Hchan*);
-bool	runtime·showframe(Func*);
+bool	runtime·showframe(Func*, bool);
 
-void	runtime·ifaceE2I(struct InterfaceType*, Eface, Iface*);
+void	runtime·ifaceE2I(InterfaceType*, Eface, Iface*);
 
 uintptr	runtime·memlimit(void);
 
@@ -738,3 +950,17 @@ uintptr	runtime·memlimit(void);
 // is forced to deliver the signal to a thread that's actually running.
 // This is a no-op on other systems.
 void	runtime·setprof(bool);
+
+// float.c
+extern float64 runtime·nan;
+extern float64 runtime·posinf;
+extern float64 runtime·neginf;
+extern uint64 ·nan;
+extern uint64 ·posinf;
+extern uint64 ·neginf;
+#define ISNAN(f) ((f) != (f))
+
+enum
+{
+	UseSpanType = 1,
+};
diff --git a/src/pkg/runtime/runtime1.goc b/src/pkg/runtime/runtime1.goc
index 667131c..d2c38df 100644
--- a/src/pkg/runtime/runtime1.goc
+++ b/src/pkg/runtime/runtime1.goc
@@ -5,10 +5,10 @@
 package runtime
 #include "runtime.h"
 
-func GOMAXPROCS(n int32) (ret int32) {
+func GOMAXPROCS(n int) (ret int) {
 	ret = runtime·gomaxprocsfunc(n);
 }
 
-func NumCPU() (ret int32) {
+func NumCPU() (ret int) {
 	ret = runtime·ncpu;
 }
diff --git a/src/pkg/runtime/runtime_test.go b/src/pkg/runtime/runtime_test.go
index d68b363..e458793 100644
--- a/src/pkg/runtime/runtime_test.go
+++ b/src/pkg/runtime/runtime_test.go
@@ -38,3 +38,44 @@ func BenchmarkIfaceCmpNil100(b *testing.B) {
 		}
 	}
 }
+
+func BenchmarkDefer(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		defer1()
+	}
+}
+
+func defer1() {
+	defer func(x, y, z int) {
+		if recover() != nil || x != 1 || y != 2 || z != 3 {
+			panic("bad recover")
+		}
+	}(1, 2, 3)
+	return
+}
+
+func BenchmarkDefer10(b *testing.B) {
+	for i := 0; i < b.N/10; i++ {
+		defer2()
+	}
+}
+
+func defer2() {
+	for i := 0; i < 10; i++ {
+		defer func(x, y, z int) {
+			if recover() != nil || x != 1 || y != 2 || z != 3 {
+				panic("bad recover")
+			}
+		}(1, 2, 3)
+	}
+}
+
+func BenchmarkDeferMany(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		defer func(x, y, z int) {
+			if recover() != nil || x != 1 || y != 2 || z != 3 {
+				panic("bad recover")
+			}
+		}(1, 2, 3)
+	}
+}
diff --git a/src/pkg/runtime/sema.goc b/src/pkg/runtime/sema.goc
index 2300c56..c4b5247 100644
--- a/src/pkg/runtime/sema.goc
+++ b/src/pkg/runtime/sema.goc
@@ -24,30 +24,33 @@ package sync
 typedef struct Sema Sema;
 struct Sema
 {
-	uint32 volatile *addr;
-	G *g;
-	Sema *prev;
-	Sema *next;
+	uint32 volatile*	addr;
+	G*	g;
+	int64	releasetime;
+	Sema*	prev;
+	Sema*	next;
 };
 
 typedef struct SemaRoot SemaRoot;
 struct SemaRoot
 {
-        Lock;
-	Sema *head;
-	Sema *tail;
+	Lock;
+	Sema*	head;
+	Sema*	tail;
 	// Number of waiters. Read w/o the lock.
-	uint32 volatile nwait;
+	uint32 volatile	nwait;
 };
 
 // Prime to not correlate with any user patterns.
 #define SEMTABLESZ 251
 
-static union
+union semtable
 {
 	SemaRoot;
 	uint8 pad[CacheLineSize];
-} semtable[SEMTABLESZ];
+};
+#pragma dataflag 16 /* mark semtable as 'no pointers', hiding from garbage collector */
+static union semtable semtable[SEMTABLESZ];
 
 static SemaRoot*
 semroot(uint32 *addr)
@@ -95,12 +98,13 @@ cansemacquire(uint32 *addr)
 	return 0;
 }
 
-void
-runtime·semacquire(uint32 volatile *addr)
+static void
+semacquireimpl(uint32 volatile *addr, int32 profile)
 {
-	Sema s;
+	Sema s;	// Needs to be allocated on stack, otherwise garbage collector could deallocate it
 	SemaRoot *root;
-
+	int64 t0;
+	
 	// Easy case.
 	if(cansemacquire(addr))
 		return;
@@ -112,6 +116,12 @@ runtime·semacquire(uint32 volatile *addr)
 	//	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.
@@ -125,16 +135,22 @@ runtime·semacquire(uint32 volatile *addr)
 		// Any semrelease after the cansemacquire knows we're waiting
 		// (we set nwait above), so go to sleep.
 		semqueue(root, addr, &s);
-		g->status = Gwaiting;
-		g->waitreason = "semacquire";
-		runtime·unlock(root);
-		runtime·gosched();
-		if(cansemacquire(addr))
+		runtime·park(runtime·unlock, root, "semacquire");
+		if(cansemacquire(addr)) {
+			if(t0)
+				runtime·blockevent(s.releasetime - t0, 3);
 			return;
+		}
 	}
 }
 
 void
+runtime·semacquire(uint32 volatile *addr)
+{
+	semacquireimpl(addr, 0);
+}
+
+void
 runtime·semrelease(uint32 volatile *addr)
 {
 	Sema *s;
@@ -165,12 +181,15 @@ runtime·semrelease(uint32 volatile *addr)
 		}
 	}
 	runtime·unlock(root);
-	if(s)
+	if(s) {
+		if(s->releasetime)
+			s->releasetime = runtime·cputicks();
 		runtime·ready(s->g);
+	}
 }
 
 func runtime_Semacquire(addr *uint32) {
-	runtime·semacquire(addr);
+	semacquireimpl(addr, 1);
 }
 
 func runtime_Semrelease(addr *uint32) {
diff --git a/src/pkg/runtime/signal_darwin_386.c b/src/pkg/runtime/signal_darwin_386.c
index 9e98635..132ca93 100644
--- a/src/pkg/runtime/signal_darwin_386.c
+++ b/src/pkg/runtime/signal_darwin_386.c
@@ -47,7 +47,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 
 	t = &runtime·sigtab[sig];
 	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// Work around Leopard bug that doesn't set FPE_INTDIV.
 		// Look at instruction to see if it is a divide.
@@ -101,7 +101,11 @@ Throw:
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 	}
 
-	runtime·printf("pc: %x\n", 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()){
@@ -121,6 +125,8 @@ runtime·signalstack(byte *p, int32 n)
 	st.ss_sp = p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -129,6 +135,15 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		runtime·sigaction(i, nil, &sa);
+		if(*(void**)sa.__sigaction_u == SIG_IGN)
+			return;
+	}
+
 	runtime·memclr((byte*)&sa, sizeof sa);
 	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
 	if(restart)
diff --git a/src/pkg/runtime/signal_darwin_amd64.c b/src/pkg/runtime/signal_darwin_amd64.c
index d9c5f48..4b7256b 100644
--- a/src/pkg/runtime/signal_darwin_amd64.c
+++ b/src/pkg/runtime/signal_darwin_amd64.c
@@ -55,7 +55,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 
 	t = &runtime·sigtab[sig];
 	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// Work around Leopard bug that doesn't set FPE_INTDIV.
 		// Look at instruction to see if it is a divide.
@@ -111,7 +111,11 @@ Throw:
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 	}
 
-	runtime·printf("pc: %X\n", 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()){
@@ -131,6 +135,8 @@ runtime·signalstack(byte *p, int32 n)
 	st.ss_sp = p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -139,6 +145,15 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		runtime·sigaction(i, nil, &sa);
+		if(*(void**)sa.__sigaction_u == SIG_IGN)
+			return;
+	}
+		
 	runtime·memclr((byte*)&sa, sizeof sa);
 	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
 	if(restart)
diff --git a/src/pkg/runtime/signal_freebsd_386.c b/src/pkg/runtime/signal_freebsd_386.c
index 80da95d..254e5e2 100644
--- a/src/pkg/runtime/signal_freebsd_386.c
+++ b/src/pkg/runtime/signal_freebsd_386.c
@@ -15,7 +15,7 @@ typedef struct sigaction {
 		void    (*__sa_sigaction)(int32, Siginfo*, void *);
 	} __sigaction_u;		/* signal handler */
 	int32	sa_flags;		/* see signal options below */
-	int64	sa_mask;		/* signal mask to apply */
+	Sigset	sa_mask;		/* signal mask to apply */
 } Sigaction;
 
 void
@@ -54,7 +54,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 
 	t = &runtime·sigtab[sig];
 	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// Make it look like a call to the signal func.
 		// Have to pass arguments out of band since
@@ -97,6 +97,10 @@ Throw:
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 
 	runtime·printf("PC=%X\n", r->mc_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()){
@@ -116,6 +120,8 @@ runtime·signalstack(byte *p, int32 n)
 	st.ss_sp = (int8*)p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -124,11 +130,23 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		runtime·sigaction(i, nil, &sa);
+		if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
+			return;
+	}
+
 	runtime·memclr((byte*)&sa, sizeof sa);
 	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
 	if(restart)
 		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
+	sa.sa_mask.__bits[0] = ~(uint32)0;
+	sa.sa_mask.__bits[1] = ~(uint32)0;
+	sa.sa_mask.__bits[2] = ~(uint32)0;
+	sa.sa_mask.__bits[3] = ~(uint32)0;
 	if (fn == runtime·sighandler)
 		fn = (void*)runtime·sigtramp;
 	sa.__sigaction_u.__sa_sigaction = (void*)fn;
diff --git a/src/pkg/runtime/signal_freebsd_amd64.c b/src/pkg/runtime/signal_freebsd_amd64.c
index e430768..7dbf360 100644
--- a/src/pkg/runtime/signal_freebsd_amd64.c
+++ b/src/pkg/runtime/signal_freebsd_amd64.c
@@ -15,7 +15,7 @@ typedef struct sigaction {
 		void    (*__sa_sigaction)(int32, Siginfo*, void *);
 	} __sigaction_u;		/* signal handler */
 	int32	sa_flags;		/* see signal options below */
-	int64	sa_mask;		/* signal mask to apply */
+	Sigset	sa_mask;		/* signal mask to apply */
 } Sigaction;
 
 void
@@ -62,7 +62,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 
 	t = &runtime·sigtab[sig];
 	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// Make it look like a call to the signal func.
 		// Have to pass arguments out of band since
@@ -105,6 +105,10 @@ Throw:
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 
 	runtime·printf("PC=%X\n", r->mc_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()){
@@ -124,6 +128,8 @@ runtime·signalstack(byte *p, int32 n)
 	st.ss_sp = (int8*)p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -132,11 +138,23 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		runtime·sigaction(i, nil, &sa);
+		if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
+			return;
+	}
+
 	runtime·memclr((byte*)&sa, sizeof sa);
 	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
 	if(restart)
 		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
+	sa.sa_mask.__bits[0] = ~(uint32)0;
+	sa.sa_mask.__bits[1] = ~(uint32)0;
+	sa.sa_mask.__bits[2] = ~(uint32)0;
+	sa.sa_mask.__bits[3] = ~(uint32)0;
 	if (fn == runtime·sighandler)
 		fn = (void*)runtime·sigtramp;
 	sa.__sigaction_u.__sa_sigaction = (void*)fn;
diff --git a/src/pkg/runtime/signal_freebsd_arm.c b/src/pkg/runtime/signal_freebsd_arm.c
new file mode 100644
index 0000000..50c3221
--- /dev/null
+++ b/src/pkg/runtime/signal_freebsd_arm.c
@@ -0,0 +1,193 @@
+// 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 "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+#define r0	__gregs[0]
+#define r1	__gregs[1]
+#define r2	__gregs[2]
+#define r3	__gregs[3]
+#define r4	__gregs[4]
+#define r5	__gregs[5]
+#define r6	__gregs[6]
+#define r7	__gregs[7]
+#define r8	__gregs[8]
+#define r9	__gregs[9]
+#define r10	__gregs[10]
+#define r11	__gregs[11]
+#define r12	__gregs[12]
+#define r13	__gregs[13]
+#define r14	__gregs[14]
+#define r15	__gregs[15]
+#define cpsr	__gregs[16]
+
+void
+runtime·dumpregs(Mcontext *r)
+{
+	runtime·printf("r0      %x\n", r->r0);
+	runtime·printf("r1      %x\n", r->r1);
+	runtime·printf("r2      %x\n", r->r2);
+	runtime·printf("r3      %x\n", r->r3);
+	runtime·printf("r4      %x\n", r->r4);
+	runtime·printf("r5      %x\n", r->r5);
+	runtime·printf("r6      %x\n", r->r6);
+	runtime·printf("r7      %x\n", r->r7);
+	runtime·printf("r8      %x\n", r->r8);
+	runtime·printf("r9      %x\n", r->r9);
+	runtime·printf("r10     %x\n", r->r10);
+	runtime·printf("fp      %x\n", r->r11);
+	runtime·printf("ip      %x\n", r->r12);
+	runtime·printf("sp      %x\n", r->r13);
+	runtime·printf("lr      %x\n", r->r14);
+	runtime·printf("pc      %x\n", r->r15);
+	runtime·printf("cpsr    %x\n", r->cpsr);
+}
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+	union {
+		void    (*__sa_handler)(int32);
+		void    (*__sa_sigaction)(int32, Siginfo*, void *);
+	} __sigaction_u;		/* signal handler */
+	int32	sa_flags;		/* see signal options below */
+	Sigset	sa_mask;		/* signal mask to apply */
+} Sigaction;
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Ucontext *uc;
+	Mcontext *r;
+	SigTab *t;
+
+	uc = context;
+	r = &uc->uc_mcontext;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->r15, (uint8*)r->r13, (uint8*)r->r14, gp);
+		return;
+	}
+
+	t = &runtime·sigtab[sig];
+	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
+		if(gp == nil || gp == m->g0)
+			goto Throw;
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = (uintptr)info->si_addr;
+		gp->sigpc = r->r15;
+
+		// Only push runtime·sigpanic if r->mc_rip != 0.
+		// If r->mc_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->r15 != 0)
+			r->r14 = r->r15;
+		// In case we are panicking from external C code
+		r->r10 = (uintptr)gp;
+		r->r9 = (uintptr)m;
+		r->r15 = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(info->si_code == SI_USER || (t->flags & SigNotify))
+		if(runtime·sigsend(sig))
+			return;
+	if(t->flags & SigKill)
+		runtime·exit(2);
+	if(!(t->flags & SigThrow))
+		return;
+
+Throw:
+	runtime·startpanic();
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%x\n", r->r15);
+	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()){
+		runtime·traceback((void*)r->r15, (void*)r->r13, (void*)r->r14, gp);
+		runtime·tracebackothers(gp);
+		runtime·printf("\n");
+		runtime·dumpregs(r);
+	}
+
+//	breakpoint();
+	runtime·exit(2);
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = (uint8*)p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
+	runtime·sigaltstack(&st, nil);
+}
+
+void
+runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		runtime·sigaction(i, nil, &sa);
+		if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
+			return;
+	}
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask.__bits[0] = ~(uint32)0;
+	sa.sa_mask.__bits[1] = ~(uint32)0;
+	sa.sa_mask.__bits[2] = ~(uint32)0;
+	sa.sa_mask.__bits[3] = ~(uint32)0;
+	if (fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa.__sigaction_u.__sa_sigaction = (void*)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·checkgoarm(void)
+{
+	// TODO(minux)
+}
+
+#pragma textflag 7
+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/signal_linux_386.c b/src/pkg/runtime/signal_linux_386.c
index b154ad8..9b45ec3 100644
--- a/src/pkg/runtime/signal_linux_386.c
+++ b/src/pkg/runtime/signal_linux_386.c
@@ -50,7 +50,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 
 	t = &runtime·sigtab[sig];
 	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// Make it look like a call to the signal func.
 		// Have to pass arguments out of band since
@@ -93,6 +93,10 @@ Throw:
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 
 	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()){
@@ -112,6 +116,8 @@ runtime·signalstack(byte *p, int32 n)
 	st.ss_sp = p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -120,6 +126,16 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
+			runtime·throw("rt_sigaction read failure");
+		if(sa.k_sa_handler == SIG_IGN)
+			return;
+	}
+
 	runtime·memclr((byte*)&sa, sizeof sa);
 	sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
 	if(restart)
@@ -129,7 +145,8 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 	if(fn == runtime·sighandler)
 		fn = (void*)runtime·sigtramp;
 	sa.k_sa_handler = fn;
-	runtime·rt_sigaction(i, &sa, nil, 8);
+	if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
+		runtime·throw("rt_sigaction failure");
 }
 
 #define AT_NULL		0
diff --git a/src/pkg/runtime/signal_linux_amd64.c b/src/pkg/runtime/signal_linux_amd64.c
index 14095ba..c4e39a6 100644
--- a/src/pkg/runtime/signal_linux_amd64.c
+++ b/src/pkg/runtime/signal_linux_amd64.c
@@ -60,7 +60,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 
 	t = &runtime·sigtab[sig];
 	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// Make it look like a call to the signal func.
 		// Have to pass arguments out of band since
@@ -103,6 +103,10 @@ Throw:
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 
 	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()){
@@ -122,6 +126,8 @@ runtime·signalstack(byte *p, int32 n)
 	st.ss_sp = p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -130,14 +136,27 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
+			runtime·throw("rt_sigaction read failure");
+		if(sa.sa_handler == SIG_IGN)
+			return;
+	}
+
 	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.
 	sa.sa_restorer = (void*)runtime·sigreturn;
 	if(fn == runtime·sighandler)
 		fn = (void*)runtime·sigtramp;
 	sa.sa_handler = fn;
-	runtime·rt_sigaction(i, &sa, nil, 8);
+	if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
+		runtime·throw("rt_sigaction failure");
 }
diff --git a/src/pkg/runtime/signal_linux_arm.c b/src/pkg/runtime/signal_linux_arm.c
index 176a4ce..c26caa7 100644
--- a/src/pkg/runtime/signal_linux_arm.c
+++ b/src/pkg/runtime/signal_linux_arm.c
@@ -57,7 +57,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 
 	t = &runtime·sigtab[sig];
 	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// Make it look like a call to the signal func.
 		// Have to pass arguments out of band since
@@ -68,13 +68,22 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 		gp->sigcode1 = r->fault_address;
 		gp->sigpc = r->arm_pc;
 
-		// If this is a leaf function, we do smash LR,
-		// but we're not going back there anyway.
-		// Don't bother smashing if r->arm_pc is 0,
-		// which is probably a call to a nil func: the
-		// old link register is more useful in the stack trace.
+		// We arrange lr, and pc to pretend the panicking
+		// function calls sigpanic directly.
+		// Always save LR to stack so that panics in leaf
+		// functions are correctly handled. This smashes
+		// the stack frame but we're not going back there
+		// anyway.
+		r->arm_sp -= 4;
+		*(uint32 *)r->arm_sp = r->arm_lr;
+		// Don't bother saving PC if it's zero, which is
+		// probably a call to a nil func: the old link register
+		// is more useful in the stack trace.
 		if(r->arm_pc != 0)
 			r->arm_lr = r->arm_pc;
+		// In case we are panicking from external C code
+		r->arm_r10 = (uintptr)gp;
+		r->arm_r9 = (uintptr)m;
 		r->arm_pc = (uintptr)runtime·sigpanic;
 		return;
 	}
@@ -98,6 +107,10 @@ Throw:
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 
 	runtime·printf("PC=%x\n", r->arm_pc);
+	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()){
@@ -119,6 +132,8 @@ runtime·signalstack(byte *p, int32 n)
 	st.ss_sp = p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -127,6 +142,16 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
+			runtime·throw("rt_sigaction read failure");
+		if(sa.sa_handler == SIG_IGN)
+			return;
+	}
+
 	runtime·memclr((byte*)&sa, sizeof sa);
 	sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
 	if(restart)
@@ -136,5 +161,81 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 	if(fn == runtime·sighandler)
 		fn = (void*)runtime·sigtramp;
 	sa.sa_handler = fn;
-	runtime·rt_sigaction(i, &sa, nil, 8);
+	if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
+		runtime·throw("rt_sigaction failure");
+}
+
+#define AT_NULL		0
+#define AT_PLATFORM	15 // introduced in at least 2.6.11
+#define AT_HWCAP	16 // introduced in at least 2.6.11
+#define AT_RANDOM	25 // introduced in 2.6.29
+#define HWCAP_VFP	(1 << 6) // introduced in at least 2.6.11
+#define HWCAP_VFPv3	(1 << 13) // introduced in 2.6.30
+static uint32 runtime·randomNumber;
+uint8  runtime·armArch = 6;	// we default to ARMv6
+uint32 runtime·hwcap;	// set by setup_auxv
+uint8  runtime·goarm;	// set by 5l
+
+void
+runtime·checkgoarm(void)
+{
+	if(runtime·goarm > 5 && !(runtime·hwcap & HWCAP_VFP)) {
+		runtime·printf("runtime: this CPU has no floating point hardware, so it cannot run\n");
+		runtime·printf("this GOARM=%d binary. Recompile using GOARM=5.\n", runtime·goarm);
+		runtime·exit(1);
+	}
+	if(runtime·goarm > 6 && !(runtime·hwcap & HWCAP_VFPv3)) {
+		runtime·printf("runtime: this CPU has no VFPv3 floating point hardware, so it cannot run\n");
+		runtime·printf("this GOARM=%d binary. Recompile using GOARM=6.\n", runtime·goarm);
+		runtime·exit(1);
+	}
+}
+
+#pragma textflag 7
+void
+runtime·setup_auxv(int32 argc, void *argv_list)
+{
+	byte **argv;
+	byte **envp;
+	byte *rnd;
+	uint32 *auxv;
+	uint32 t;
+
+	argv = &argv_list;
+
+	// skip envp to get to ELF auxiliary vector.
+	for(envp = &argv[argc+1]; *envp != nil; envp++)
+		;
+	envp++;
+	
+	for(auxv=(uint32*)envp; auxv[0] != AT_NULL; auxv += 2) {
+		switch(auxv[0]) {
+		case AT_RANDOM: // kernel provided 16-byte worth of random data
+			if(auxv[1]) {
+				rnd = (byte*)auxv[1];
+				runtime·randomNumber = rnd[4] | rnd[5]<<8 | rnd[6]<<16 | rnd[7]<<24;
+			}
+			break;
+		case AT_PLATFORM: // v5l, v6l, v7l
+			if(auxv[1]) {
+				t = *(uint8*)(auxv[1]+1);
+				if(t >= '5' && t <= '7')
+					runtime·armArch = t - '0';
+			}
+			break;
+		case AT_HWCAP: // CPU capability bit flags
+			runtime·hwcap = auxv[1];
+			break;
+		}
+	}
+}
+
+#pragma textflag 7
+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.
+	// runtime·randomNumber provides better seeding of fastrand1.
+	return runtime·nanotime() + runtime·randomNumber;
 }
diff --git a/src/pkg/runtime/signal_netbsd_386.c b/src/pkg/runtime/signal_netbsd_386.c
index 39d8294..08744c4 100644
--- a/src/pkg/runtime/signal_netbsd_386.c
+++ b/src/pkg/runtime/signal_netbsd_386.c
@@ -7,76 +7,79 @@
 #include "signals_GOOS.h"
 #include "os_GOOS.h"
 
+extern void runtime·lwp_tramp(void);
 extern void runtime·sigtramp(void);
 
 typedef struct sigaction {
 	union {
-		void    (*__sa_handler)(int32);
-		void    (*__sa_sigaction)(int32, Siginfo*, void *);
-	} __sigaction_u;		/* signal handler */
-	uint32	sa_mask;		/* signal mask to apply */
+		void    (*_sa_handler)(int32);
+		void    (*_sa_sigaction)(int32, Siginfo*, void *);
+	} _sa_u;			/* signal handler */
+	uint32	sa_mask[4];		/* signal mask to apply */
 	int32	sa_flags;		/* see signal options below */
 } Sigaction;
 
 void
-runtime·dumpregs(Sigcontext *r)
+runtime·dumpregs(McontextT *mc)
 {
-	runtime·printf("eax     %x\n", r->sc_eax);
-	runtime·printf("ebx     %x\n", r->sc_ebx);
-	runtime·printf("ecx     %x\n", r->sc_ecx);
-	runtime·printf("edx     %x\n", r->sc_edx);
-	runtime·printf("edi     %x\n", r->sc_edi);
-	runtime·printf("esi     %x\n", r->sc_esi);
-	runtime·printf("ebp     %x\n", r->sc_ebp);
-	runtime·printf("esp     %x\n", r->sc_esp);
-	runtime·printf("eip     %x\n", r->sc_eip);
-	runtime·printf("eflags  %x\n", r->sc_eflags);
-	runtime·printf("cs      %x\n", r->sc_cs);
-	runtime·printf("fs      %x\n", r->sc_fs);
-	runtime·printf("gs      %x\n", r->sc_gs);
+	runtime·printf("eax     %x\n", mc->__gregs[REG_EAX]);
+	runtime·printf("ebx     %x\n", mc->__gregs[REG_EBX]);
+	runtime·printf("ecx     %x\n", mc->__gregs[REG_ECX]);
+	runtime·printf("edx     %x\n", mc->__gregs[REG_EDX]);
+	runtime·printf("edi     %x\n", mc->__gregs[REG_EDI]);
+	runtime·printf("esi     %x\n", mc->__gregs[REG_ESI]);
+	runtime·printf("ebp     %x\n", mc->__gregs[REG_EBP]);
+	runtime·printf("esp     %x\n", mc->__gregs[REG_UESP]);
+	runtime·printf("eip     %x\n", mc->__gregs[REG_EIP]);
+	runtime·printf("eflags  %x\n", mc->__gregs[REG_EFL]);
+	runtime·printf("cs      %x\n", mc->__gregs[REG_CS]);
+	runtime·printf("fs      %x\n", mc->__gregs[REG_FS]);
+	runtime·printf("gs      %x\n", mc->__gregs[REG_GS]);
 }
 
 void
 runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 {
-	Sigcontext *r = context;
+	UcontextT *uc = context;
+	McontextT *mc = &uc->uc_mcontext;
 	uintptr *sp;
 	SigTab *t;
 
 	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->sc_eip, (uint8*)r->sc_esp, nil, gp);
+		runtime·sigprof((uint8*)mc->__gregs[REG_EIP],
+			(uint8*)mc->__gregs[REG_UESP], nil, gp);
 		return;
 	}
 
 	t = &runtime·sigtab[sig];
-	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+	if(info->_code != SI_USER && (t->flags & SigPanic)) {
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
+		// We need to pass arguments out of band since
 		// augmenting the stack frame would break
 		// the unwinding code.
 		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = *(uintptr*)((byte*)info + 12); /* si_addr */
-		gp->sigpc = r->sc_eip;
-
-		// Only push runtime·sigpanic if r->sc_eip != 0.
-		// If r->sc_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->sc_eip != 0) {
-			sp = (uintptr*)r->sc_esp;
-			*--sp = r->sc_eip;
-			r->sc_esp = (uintptr)sp;
+		gp->sigcode0 = info->_code;
+		gp->sigcode1 = *(uintptr*)&info->_reason[0]; /* _addr */
+		gp->sigpc = mc->__gregs[REG_EIP];
+
+		// Only push runtime·sigpanic if __gregs[REG_EIP] != 0.
+		// If __gregs[REG_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(mc->__gregs[REG_EIP] != 0) {
+			sp = (uintptr*)mc->__gregs[REG_UESP];
+			*--sp = mc->__gregs[REG_EIP];
+			mc->__gregs[REG_UESP] = (uintptr)sp;
 		}
-		r->sc_eip = (uintptr)runtime·sigpanic;
+		mc->__gregs[REG_EIP] = (uintptr)runtime·sigpanic;
 		return;
 	}
 
-	if(info->si_code == SI_USER || (t->flags & SigNotify))
+	if(info->_code == SI_USER || (t->flags & SigNotify))
 		if(runtime·sigsend(sig))
 			return;
 	if(t->flags & SigKill)
@@ -92,13 +95,18 @@ Throw:
 	else
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 
-	runtime·printf("PC=%X\n", r->sc_eip);
+	runtime·printf("PC=%X\n", mc->__gregs[REG_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()){
-		runtime·traceback((void*)r->sc_eip, (void*)r->sc_esp, 0, gp);
+		runtime·traceback((void*)mc->__gregs[REG_EIP],
+			(void*)mc->__gregs[REG_UESP], 0, gp);
 		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
+		runtime·dumpregs(mc);
 	}
 
 	runtime·exit(2);
@@ -109,9 +117,11 @@ runtime·signalstack(byte *p, int32 n)
 {
 	Sigaltstack st;
 
-	st.ss_sp = (int8*)p;
+	st.ss_sp = p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -120,13 +130,35 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		runtime·sigaction(i, nil, &sa);
+		if(sa._sa_u._sa_sigaction == SIG_IGN)
+			return;
+	}
+
 	runtime·memclr((byte*)&sa, sizeof sa);
 	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
 	if(restart)
 		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
+	sa.sa_mask[0] = ~0U;
+	sa.sa_mask[1] = ~0U;
+	sa.sa_mask[2] = ~0U;
+	sa.sa_mask[3] = ~0U;
 	if (fn == runtime·sighandler)
 		fn = (void*)runtime·sigtramp;
-	sa.__sigaction_u.__sa_sigaction = (void*)fn;
+	sa._sa_u._sa_sigaction = (void*)fn;
 	runtime·sigaction(i, &sa, nil);
 }
+
+void
+runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
+{
+	mc->__gregs[REG_EIP] = (uint32)runtime·lwp_tramp;
+	mc->__gregs[REG_UESP] = (uint32)stack;
+	mc->__gregs[REG_EBX] = (uint32)mp;
+	mc->__gregs[REG_EDX] = (uint32)gp;
+	mc->__gregs[REG_ESI] = (uint32)fn;
+}
diff --git a/src/pkg/runtime/signal_netbsd_amd64.c b/src/pkg/runtime/signal_netbsd_amd64.c
index 8b4f624..46afb68 100644
--- a/src/pkg/runtime/signal_netbsd_amd64.c
+++ b/src/pkg/runtime/signal_netbsd_amd64.c
@@ -7,85 +7,86 @@
 #include "signals_GOOS.h"
 #include "os_GOOS.h"
 
+extern void runtime·lwp_tramp(void);
 extern void runtime·sigtramp(void);
 
 typedef struct sigaction {
 	union {
-		void    (*__sa_handler)(int32);
-		void    (*__sa_sigaction)(int32, Siginfo*, void *);
-	} __sigaction_u;		/* signal handler */
-	uint32	sa_mask;		/* signal mask to apply */
+		void    (*_sa_handler)(int32);
+		void    (*_sa_sigaction)(int32, Siginfo*, void *);
+	} _sa_u;			/* signal handler */
+	uint32	sa_mask[4];		/* signal mask to apply */
 	int32	sa_flags;		/* see signal options below */
 } Sigaction;
 
 void
-runtime·dumpregs(Sigcontext *r)
+runtime·dumpregs(McontextT *mc)
 {
-	runtime·printf("rax     %X\n", r->sc_rax);
-	runtime·printf("rbx     %X\n", r->sc_rbx);
-	runtime·printf("rcx     %X\n", r->sc_rcx);
-	runtime·printf("rdx     %X\n", r->sc_rdx);
-	runtime·printf("rdi     %X\n", r->sc_rdi);
-	runtime·printf("rsi     %X\n", r->sc_rsi);
-	runtime·printf("rbp     %X\n", r->sc_rbp);
-	runtime·printf("rsp     %X\n", r->sc_rsp);
-	runtime·printf("r8      %X\n", r->sc_r8);
-	runtime·printf("r9      %X\n", r->sc_r9);
-	runtime·printf("r10     %X\n", r->sc_r10);
-	runtime·printf("r11     %X\n", r->sc_r11);
-	runtime·printf("r12     %X\n", r->sc_r12);
-	runtime·printf("r13     %X\n", r->sc_r13);
-	runtime·printf("r14     %X\n", r->sc_r14);
-	runtime·printf("r15     %X\n", r->sc_r15);
-	runtime·printf("rip     %X\n", r->sc_rip);
-	runtime·printf("rflags  %X\n", r->sc_rflags);
-	runtime·printf("cs      %X\n", r->sc_cs);
-	runtime·printf("fs      %X\n", r->sc_fs);
-	runtime·printf("gs      %X\n", r->sc_gs);
+	runtime·printf("rax     %X\n", mc->__gregs[REG_RAX]);
+	runtime·printf("rbx     %X\n", mc->__gregs[REG_RBX]);
+	runtime·printf("rcx     %X\n", mc->__gregs[REG_RCX]);
+	runtime·printf("rdx     %X\n", mc->__gregs[REG_RDX]);
+	runtime·printf("rdi     %X\n", mc->__gregs[REG_RDI]);
+	runtime·printf("rsi     %X\n", mc->__gregs[REG_RSI]);
+	runtime·printf("rbp     %X\n", mc->__gregs[REG_RBP]);
+	runtime·printf("rsp     %X\n", mc->__gregs[REG_RSP]);
+	runtime·printf("r8      %X\n", mc->__gregs[REG_R8]);
+	runtime·printf("r9      %X\n", mc->__gregs[REG_R9]);
+	runtime·printf("r10     %X\n", mc->__gregs[REG_R10]);
+	runtime·printf("r11     %X\n", mc->__gregs[REG_R11]);
+	runtime·printf("r12     %X\n", mc->__gregs[REG_R12]);
+	runtime·printf("r13     %X\n", mc->__gregs[REG_R13]);
+	runtime·printf("r14     %X\n", mc->__gregs[REG_R14]);
+	runtime·printf("r15     %X\n", mc->__gregs[REG_R15]);
+	runtime·printf("rip     %X\n", mc->__gregs[REG_RIP]);
+	runtime·printf("rflags  %X\n", mc->__gregs[REG_RFLAGS]);
+	runtime·printf("cs      %X\n", mc->__gregs[REG_CS]);
+	runtime·printf("fs      %X\n", mc->__gregs[REG_FS]);
+	runtime·printf("gs      %X\n", mc->__gregs[REG_GS]);
 }
 
 void
 runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 {
-	Sigcontext *r = context;
+	UcontextT *uc = context;
+	McontextT *mc = &uc->uc_mcontext;
 	uintptr *sp;
 	SigTab *t;
 
 	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->sc_rip,
-			(uint8*)r->sc_rsp, nil, gp);
+		runtime·sigprof((uint8*)mc->__gregs[REG_RIP],
+			(uint8*)mc->__gregs[REG_RSP], nil, gp);
 		return;
 	}
 
 	t = &runtime·sigtab[sig];
-	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+	if(info->_code != SI_USER && (t->flags & SigPanic)) {
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// 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.
+		// We need to pass arguments out of band since augmenting the
+		// stack frame would break the unwinding code.
 		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = *(uintptr*)((byte*)info + 16); /* si_addr */
-		gp->sigpc = r->sc_rip;
-
-		// Only push runtime·sigpanic if r->mc_rip != 0.
-		// If r->mc_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->sc_rip != 0) {
-			sp = (uintptr*)r->sc_rsp;
-			*--sp = r->sc_rip;
-			r->sc_rsp = (uintptr)sp;
+		gp->sigcode0 = info->_code;
+		gp->sigcode1 = *(uintptr*)&info->_reason[0]; /* _addr */
+		gp->sigpc = mc->__gregs[REG_RIP];
+
+		// Only push runtime·sigpanic if __gregs[REG_RIP] != 0.
+		// If __gregs[REG_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(mc->__gregs[REG_RIP] != 0) {
+			sp = (uintptr*)mc->__gregs[REG_RSP];
+			*--sp = mc->__gregs[REG_RIP];
+			mc->__gregs[REG_RSP] = (uintptr)sp;
 		}
-		r->sc_rip = (uintptr)runtime·sigpanic;
+		mc->__gregs[REG_RIP] = (uintptr)runtime·sigpanic;
 		return;
 	}
 
-	if(info->si_code == SI_USER || (t->flags & SigNotify))
+	if(info->_code == SI_USER || (t->flags & SigNotify))
 		if(runtime·sigsend(sig))
 			return;
 	if(t->flags & SigKill)
@@ -101,13 +102,18 @@ Throw:
 	else
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 
-	runtime·printf("PC=%X\n", r->sc_rip);
+	runtime·printf("PC=%X\n", mc->__gregs[REG_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()){
-		runtime·traceback((void*)r->sc_rip, (void*)r->sc_rsp, 0, gp);
+		runtime·traceback((void*)mc->__gregs[REG_RIP],
+			(void*)mc->__gregs[REG_RSP], 0, gp);
 		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
+		runtime·dumpregs(mc);
 	}
 
 	runtime·exit(2);
@@ -118,9 +124,11 @@ runtime·signalstack(byte *p, int32 n)
 {
 	Sigaltstack st;
 
-	st.ss_sp = (int8*)p;
+	st.ss_sp = p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -129,13 +137,36 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		runtime·sigaction(i, nil, &sa);
+		if(sa._sa_u._sa_sigaction == SIG_IGN)
+			return;
+	}
+
 	runtime·memclr((byte*)&sa, sizeof sa);
 	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
 	if(restart)
 		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
+	sa.sa_mask[0] = ~0U;
+	sa.sa_mask[1] = ~0U;
+	sa.sa_mask[2] = ~0U;
+	sa.sa_mask[3] = ~0U;
 	if (fn == runtime·sighandler)
 		fn = (void*)runtime·sigtramp;
-	sa.__sigaction_u.__sa_sigaction = (void*)fn;
+	sa._sa_u._sa_sigaction = (void*)fn;
 	runtime·sigaction(i, &sa, nil);
 }
+
+void
+runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
+{
+	// Machine dependent mcontext initialisation for LWP.
+	mc->__gregs[REG_RIP] = (uint64)runtime·lwp_tramp;
+	mc->__gregs[REG_RSP] = (uint64)stack;
+	mc->__gregs[REG_R8] = (uint64)mp;
+	mc->__gregs[REG_R9] = (uint64)gp;
+	mc->__gregs[REG_R12] = (uint64)fn;
+}
diff --git a/src/pkg/runtime/signal_netbsd_arm.c b/src/pkg/runtime/signal_netbsd_arm.c
new file mode 100644
index 0000000..97f6268
--- /dev/null
+++ b/src/pkg/runtime/signal_netbsd_arm.c
@@ -0,0 +1,208 @@
+// 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 "signals_GOOS.h"
+#include "os_GOOS.h"
+
+#define r0	__gregs[0]
+#define r1	__gregs[1]
+#define r2	__gregs[2]
+#define r3	__gregs[3]
+#define r4	__gregs[4]
+#define r5	__gregs[5]
+#define r6	__gregs[6]
+#define r7	__gregs[7]
+#define r8	__gregs[8]
+#define r9	__gregs[9]
+#define r10	__gregs[10]
+#define r11	__gregs[11]
+#define r12	__gregs[12]
+#define r13	__gregs[13]
+#define r14	__gregs[14]
+#define r15	__gregs[15]
+#define cpsr	__gregs[16]
+
+void
+runtime·dumpregs(McontextT *r)
+{
+	runtime·printf("r0      %x\n", r->r0);
+	runtime·printf("r1      %x\n", r->r1);
+	runtime·printf("r2      %x\n", r->r2);
+	runtime·printf("r3      %x\n", r->r3);
+	runtime·printf("r4      %x\n", r->r4);
+	runtime·printf("r5      %x\n", r->r5);
+	runtime·printf("r6      %x\n", r->r6);
+	runtime·printf("r7      %x\n", r->r7);
+	runtime·printf("r8      %x\n", r->r8);
+	runtime·printf("r9      %x\n", r->r9);
+	runtime·printf("r10     %x\n", r->r10);
+	runtime·printf("fp      %x\n", r->r11);
+	runtime·printf("ip      %x\n", r->r12);
+	runtime·printf("sp      %x\n", r->r13);
+	runtime·printf("lr      %x\n", r->r14);
+	runtime·printf("pc      %x\n", r->r15);
+	runtime·printf("cpsr    %x\n", r->cpsr);
+}
+
+extern void runtime·lwp_tramp(void);
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+	union {
+		void    (*_sa_handler)(int32);
+		void    (*_sa_sigaction)(int32, Siginfo*, void *);
+	} _sa_u;			/* signal handler */
+	uint32	sa_mask[4];		/* signal mask to apply */
+	int32	sa_flags;		/* see signal options below */
+} Sigaction;
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	UcontextT *uc;
+	McontextT *r;
+	SigTab *t;
+
+	uc = context;
+	r = &uc->uc_mcontext;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->r15, (uint8*)r->r13, (uint8*)r->r14, gp);
+		return;
+	}
+
+	t = &runtime·sigtab[sig];
+	if(info->_code != SI_USER && (t->flags & SigPanic)) {
+		if(gp == nil || gp == m->g0)
+			goto Throw;
+		// Make it look like a call to the signal func.
+		// We have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->_code;
+		gp->sigcode1 = *(uintptr*)&info->_reason[0]; /* _addr */
+		gp->sigpc = r->r15;
+
+		// We arrange lr, and pc to pretend the panicking
+		// function calls sigpanic directly.
+		// Always save LR to stack so that panics in leaf
+		// functions are correctly handled. This smashes
+		// the stack frame but we're not going back there
+		// anyway.
+		r->r13 -= 4;
+		*(uint32 *)r->r13 = r->r14;
+		// Don't bother saving PC if it's zero, which is
+		// probably a call to a nil func: the old link register
+		// is more useful in the stack trace.
+		if(r->r15 != 0)
+			r->r14 = r->r15;
+		// In case we are panicking from external C code
+		r->r10 = (uintptr)gp;
+		r->r9 = (uintptr)m;
+		r->r15 = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(info->_code == SI_USER || (t->flags & SigNotify))
+		if(runtime·sigsend(sig))
+			return;
+	if(t->flags & SigKill)
+		runtime·exit(2);
+	if(!(t->flags & SigThrow))
+		return;
+
+Throw:
+	runtime·startpanic();
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%x\n", r->r15);
+	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()){
+		runtime·traceback((void*)r->r15, (void*)r->r13, (void*)r->r14, gp);
+		runtime·tracebackothers(gp);
+		runtime·printf("\n");
+		runtime·dumpregs(r);
+	}
+
+//	breakpoint();
+	runtime·exit(2);
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = (uint8*)p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
+	runtime·sigaltstack(&st, nil);
+}
+
+void
+runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		runtime·sigaction(i, nil, &sa);
+		if(sa._sa_u._sa_sigaction == SIG_IGN)
+			return;
+	}
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask[0] = ~0U;
+	sa.sa_mask[1] = ~0U;
+	sa.sa_mask[2] = ~0U;
+	sa.sa_mask[3] = ~0U;
+	if (fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa._sa_u._sa_sigaction = (void*)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
+{
+	mc->r15 = (uint32)runtime·lwp_tramp;
+	mc->r13 = (uint32)stack;
+	mc->r0 = (uint32)mp;
+	mc->r1 = (uint32)gp;
+	mc->r2 = (uint32)fn;
+}
+
+void
+runtime·checkgoarm(void)
+{
+	// TODO(minux)
+}
+
+#pragma textflag 7
+int64
+runtime·cputicks() {
+	// 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/signal_openbsd_386.c b/src/pkg/runtime/signal_openbsd_386.c
index 39d8294..516797c 100644
--- a/src/pkg/runtime/signal_openbsd_386.c
+++ b/src/pkg/runtime/signal_openbsd_386.c
@@ -50,7 +50,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 
 	t = &runtime·sigtab[sig];
 	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// Make it look like a call to the signal func.
 		// Have to pass arguments out of band since
@@ -93,6 +93,10 @@ Throw:
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 
 	runtime·printf("PC=%X\n", r->sc_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()){
@@ -109,9 +113,11 @@ runtime·signalstack(byte *p, int32 n)
 {
 	Sigaltstack st;
 
-	st.ss_sp = (int8*)p;
+	st.ss_sp = p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -120,6 +126,15 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		runtime·sigaction(i, nil, &sa);
+		if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
+			return;
+	}
+
 	runtime·memclr((byte*)&sa, sizeof sa);
 	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
 	if(restart)
diff --git a/src/pkg/runtime/signal_openbsd_amd64.c b/src/pkg/runtime/signal_openbsd_amd64.c
index 8b4f624..0d0db77 100644
--- a/src/pkg/runtime/signal_openbsd_amd64.c
+++ b/src/pkg/runtime/signal_openbsd_amd64.c
@@ -59,7 +59,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 
 	t = &runtime·sigtab[sig];
 	if(info->si_code != SI_USER && (t->flags & SigPanic)) {
-		if(gp == nil)
+		if(gp == nil || gp == m->g0)
 			goto Throw;
 		// Make it look like a call to the signal func.
 		// Have to pass arguments out of band since
@@ -70,8 +70,8 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
 		gp->sigcode1 = *(uintptr*)((byte*)info + 16); /* si_addr */
 		gp->sigpc = r->sc_rip;
 
-		// Only push runtime·sigpanic if r->mc_rip != 0.
-		// If r->mc_rip == 0, probably panicked because of a
+		// Only push runtime·sigpanic if r->sc_rip != 0.
+		// If r->sc_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
@@ -102,6 +102,10 @@ Throw:
 		runtime·printf("%s\n", runtime·sigtab[sig].name);
 
 	runtime·printf("PC=%X\n", r->sc_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()){
@@ -118,9 +122,11 @@ runtime·signalstack(byte *p, int32 n)
 {
 	Sigaltstack st;
 
-	st.ss_sp = (int8*)p;
+	st.ss_sp = p;
 	st.ss_size = n;
 	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
 	runtime·sigaltstack(&st, nil);
 }
 
@@ -129,12 +135,21 @@ runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
 {
 	Sigaction sa;
 
+	// If SIGHUP handler is SIG_IGN, assume running
+	// under nohup and do not set explicit handler.
+	if(i == SIGHUP) {
+		runtime·memclr((byte*)&sa, sizeof sa);
+		runtime·sigaction(i, nil, &sa);
+		if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
+			return;
+	}
+
 	runtime·memclr((byte*)&sa, sizeof sa);
 	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
 	if(restart)
 		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
-	if (fn == runtime·sighandler)
+	sa.sa_mask = ~0U;
+	if(fn == runtime·sighandler)
 		fn = (void*)runtime·sigtramp;
 	sa.__sigaction_u.__sa_sigaction = (void*)fn;
 	runtime·sigaction(i, &sa, nil);
diff --git a/src/pkg/runtime/signal_plan9_386.c b/src/pkg/runtime/signal_plan9_386.c
index d266885..17bc117 100644
--- a/src/pkg/runtime/signal_plan9_386.c
+++ b/src/pkg/runtime/signal_plan9_386.c
@@ -3,6 +3,107 @@
 // license that can be found in the LICENSE file. 
 
 #include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "signals_GOOS.h"
+
+void
+runtime·dumpregs(Ureg *u)
+{
+	runtime·printf("ax	%X\n", u->ax);
+	runtime·printf("bx	%X\n", u->bx);
+	runtime·printf("cx	%X\n", u->cx);
+	runtime·printf("dx	%X\n", u->dx);
+	runtime·printf("di	%X\n", u->di);
+	runtime·printf("si	%X\n", u->si);
+	runtime·printf("bp	%X\n", u->bp);
+	runtime·printf("sp	%X\n", u->sp);
+	runtime·printf("pc	%X\n", u->pc);
+	runtime·printf("flags	%X\n", u->flags);
+	runtime·printf("cs	%X\n", u->cs);
+	runtime·printf("fs	%X\n", u->fs);
+	runtime·printf("gs	%X\n", u->gs);
+}
+
+int32
+runtime·sighandler(void *v, int8 *s, G *gp)
+{
+	Ureg *ureg;
+	uintptr *sp;
+	SigTab *sig, *nsig;
+	int32 len, i;
+
+	if(!s)
+		return NCONT;
+			
+	len = runtime·findnull((byte*)s);
+	if(len <= 4 || runtime·mcmp((byte*)s, (byte*)"sys:", 4) != 0)
+		return NDFLT;
+
+	nsig = nil;
+	sig = runtime·sigtab;
+	for(i=0; i < NSIG; i++) {
+		if(runtime·strstr((byte*)s, (byte*)sig->name)) {
+			nsig = sig;
+			break;
+		}
+		sig++;
+	}
+
+	if(nsig == nil)
+		return NDFLT;
+
+	ureg = v;
+	if(nsig->flags & SigPanic) {
+		if(gp == nil || m->notesig == 0)
+			goto Throw;
+
+		// Save error string from sigtramp's stack,
+		// into gsignal->sigcode0, so we can reliably
+		// access it from the panic routines.
+		if(len > ERRMAX)
+			len = ERRMAX;
+		runtime·memmove((void*)m->notesig, (void*)s, len);
+
+		gp->sig = i;
+		gp->sigpc = ureg->pc;
+
+		// Only push runtime·sigpanic if ureg->pc != 0.
+		// If ureg->pc == 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(ureg->pc != 0) {
+			sp = (uintptr*)ureg->sp;
+			*--sp = ureg->pc;
+			ureg->sp = (uint32)sp;
+		}
+		ureg->pc = (uintptr)runtime·sigpanic;
+		return NCONT;
+	}
+
+	if(!(nsig->flags & SigThrow))
+		return NDFLT;
+
+Throw:
+	runtime·startpanic();
+
+	runtime·printf("%s\n", s);
+	runtime·printf("PC=%X\n", ureg->pc);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()) {
+		runtime·traceback((void*)ureg->pc, (void*)ureg->sp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(ureg);
+	}
+	runtime·goexitsall("");
+	runtime·exits(s);
+
+	return 0;
+}
+
 
 void
 runtime·sigenable(uint32 sig)
diff --git a/src/pkg/runtime/signal_plan9_amd64.c b/src/pkg/runtime/signal_plan9_amd64.c
new file mode 100644
index 0000000..e4f946a
--- /dev/null
+++ b/src/pkg/runtime/signal_plan9_amd64.c
@@ -0,0 +1,127 @@
+// 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 "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "signals_GOOS.h"
+
+void
+runtime·dumpregs(Ureg *u)
+{
+	runtime·printf("ax	%X\n", u->ax);
+	runtime·printf("bx	%X\n", u->bx);
+	runtime·printf("cx	%X\n", u->cx);
+	runtime·printf("dx	%X\n", u->dx);
+	runtime·printf("di	%X\n", u->di);
+	runtime·printf("si	%X\n", u->si);
+	runtime·printf("bp	%X\n", u->bp);
+	runtime·printf("sp	%X\n", u->sp);
+	runtime·printf("r8	%X\n", u->r8);
+	runtime·printf("r9	%X\n", u->r9);
+	runtime·printf("r10	%X\n", u->r10);
+	runtime·printf("r11	%X\n", u->r11);
+	runtime·printf("r12	%X\n", u->r12);
+	runtime·printf("r13	%X\n", u->r13);
+	runtime·printf("r14	%X\n", u->r14);
+	runtime·printf("r15	%X\n", u->r15);
+	runtime·printf("ip	%X\n", u->ip);
+	runtime·printf("flags	%X\n", u->flags);
+	runtime·printf("cs	%X\n", (uint64)u->cs);
+	runtime·printf("fs	%X\n", (uint64)u->fs);
+	runtime·printf("gs	%X\n", (uint64)u->gs);
+}
+
+int32
+runtime·sighandler(void *v, int8 *s, G *gp)
+{
+	Ureg *ureg;
+	uintptr *sp;
+	SigTab *sig, *nsig;
+	int32 len, i;
+
+	if(!s)
+		return NCONT;
+			
+	len = runtime·findnull((byte*)s);
+	if(len <= 4 || runtime·mcmp((byte*)s, (byte*)"sys:", 4) != 0)
+		return NDFLT;
+
+	nsig = nil;
+	sig = runtime·sigtab;
+	for(i=0; i < NSIG; i++) {
+		if(runtime·strstr((byte*)s, (byte*)sig->name)) {
+			nsig = sig;
+			break;
+		}
+		sig++;
+	}
+
+	if(nsig == nil)
+		return NDFLT;
+
+	ureg = v;
+	if(nsig->flags & SigPanic) {
+		if(gp == nil || m->notesig == 0)
+			goto Throw;
+
+		// Save error string from sigtramp's stack,
+		// into gsignal->sigcode0, so we can reliably
+		// access it from the panic routines.
+		if(len > ERRMAX)
+			len = ERRMAX;
+		runtime·memmove((void*)m->notesig, (void*)s, len);
+
+		gp->sig = i;
+		gp->sigpc = ureg->ip;
+
+		// Only push runtime·sigpanic if ureg->ip != 0.
+		// If ureg->ip == 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(ureg->ip != 0) {
+			sp = (uintptr*)ureg->sp;
+			*--sp = ureg->ip;
+			ureg->sp = (uint64)sp;
+		}
+		ureg->ip = (uintptr)runtime·sigpanic;
+		return NCONT;
+	}
+
+	if(!(nsig->flags & SigThrow))
+		return NDFLT;
+
+Throw:
+	runtime·startpanic();
+
+	runtime·printf("%s\n", s);
+	runtime·printf("PC=%X\n", ureg->ip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()) {
+		runtime·traceback((void*)ureg->ip, (void*)ureg->sp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(ureg);
+	}
+	runtime·goexitsall("");
+	runtime·exits(s);
+
+	return 0;
+}
+
+void
+runtime·sigenable(uint32 sig)
+{
+	USED(sig);
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	// TODO: Enable profiling interrupts.
+	
+	m->profilehz = hz;
+}
diff --git a/src/pkg/runtime/signal_windows_386.c b/src/pkg/runtime/signal_windows_386.c
index a248374..d76d5bf 100644
--- a/src/pkg/runtime/signal_windows_386.c
+++ b/src/pkg/runtime/signal_windows_386.c
@@ -68,11 +68,15 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
 		info->ExceptionInformation[0], info->ExceptionInformation[1]);
 
 	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()){
-		runtime·traceback((void*)r->Eip, (void*)r->Esp, 0, m->curg);
-		runtime·tracebackothers(m->curg);
+		runtime·traceback((void*)r->Eip, (void*)r->Esp, 0, gp);
+		runtime·tracebackothers(gp);
 		runtime·dumpregs(r);
 	}
 
diff --git a/src/pkg/runtime/signal_windows_amd64.c b/src/pkg/runtime/signal_windows_amd64.c
index 1cdf1ca..3729aa5 100644
--- a/src/pkg/runtime/signal_windows_amd64.c
+++ b/src/pkg/runtime/signal_windows_amd64.c
@@ -75,6 +75,10 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
 		info->ExceptionInformation[0], info->ExceptionInformation[1]);
 
 	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()){
diff --git a/src/pkg/runtime/signals_linux.h b/src/pkg/runtime/signals_linux.h
index 345a6c5..9c35670 100644
--- a/src/pkg/runtime/signals_linux.h
+++ b/src/pkg/runtime/signals_linux.h
@@ -42,7 +42,7 @@ SigTab runtime·sigtab[] = {
 	/* 30 */	N, "SIGPWR: power failure restart",
 	/* 31 */	N, "SIGSYS: bad system call",
 	/* 32 */	N, "signal 32",
-	/* 33 */	N, "signal 33",
+	/* 33 */	0, "signal 33", /* SIGSETXID; see issue 3871 */
 	/* 34 */	N, "signal 34",
 	/* 35 */	N, "signal 35",
 	/* 36 */	N, "signal 36",
diff --git a/src/pkg/runtime/signals_netbsd.h b/src/pkg/runtime/signals_netbsd.h
index 4d27e05..7140de8 100644
--- a/src/pkg/runtime/signals_netbsd.h
+++ b/src/pkg/runtime/signals_netbsd.h
@@ -9,16 +9,16 @@
 #define D SigDefault
 
 SigTab runtime·sigtab[] = {
-	/* 0 */	0, "SIGNONE: no trap",
-	/* 1 */	N+K, "SIGHUP: terminal line hangup",
-	/* 2 */	N+K, "SIGINT: interrupt",
-	/* 3 */	N+T, "SIGQUIT: quit",
-	/* 4 */	T, "SIGILL: illegal instruction",
-	/* 5 */	T, "SIGTRAP: trace trap",
-	/* 6 */	N+T, "SIGABRT: abort",
-	/* 7 */	T, "SIGEMT: emulate instruction executed",
-	/* 8 */	P, "SIGFPE: floating-point exception",
-	/* 9 */	0, "SIGKILL: kill",
+	/*  0 */	0, "SIGNONE: no trap",
+	/*  1 */	N+K, "SIGHUP: terminal line hangup",
+	/*  2 */	N+K, "SIGINT: interrupt",
+	/*  3 */	N+T, "SIGQUIT: quit",
+	/*  4 */	T, "SIGILL: illegal instruction",
+	/*  5 */	T, "SIGTRAP: trace trap",
+	/*  6 */	N+T, "SIGABRT: abort",
+	/*  7 */	T, "SIGEMT: emulate instruction executed",
+	/*  8 */	P, "SIGFPE: floating-point exception",
+	/*  9 */	0, "SIGKILL: kill",
 	/* 10 */	P, "SIGBUS: bus error",
 	/* 11 */	P, "SIGSEGV: segmentation violation",
 	/* 12 */	T, "SIGSYS: bad system call",
diff --git a/src/pkg/runtime/signals_openbsd.h b/src/pkg/runtime/signals_openbsd.h
index 4d27e05..7140de8 100644
--- a/src/pkg/runtime/signals_openbsd.h
+++ b/src/pkg/runtime/signals_openbsd.h
@@ -9,16 +9,16 @@
 #define D SigDefault
 
 SigTab runtime·sigtab[] = {
-	/* 0 */	0, "SIGNONE: no trap",
-	/* 1 */	N+K, "SIGHUP: terminal line hangup",
-	/* 2 */	N+K, "SIGINT: interrupt",
-	/* 3 */	N+T, "SIGQUIT: quit",
-	/* 4 */	T, "SIGILL: illegal instruction",
-	/* 5 */	T, "SIGTRAP: trace trap",
-	/* 6 */	N+T, "SIGABRT: abort",
-	/* 7 */	T, "SIGEMT: emulate instruction executed",
-	/* 8 */	P, "SIGFPE: floating-point exception",
-	/* 9 */	0, "SIGKILL: kill",
+	/*  0 */	0, "SIGNONE: no trap",
+	/*  1 */	N+K, "SIGHUP: terminal line hangup",
+	/*  2 */	N+K, "SIGINT: interrupt",
+	/*  3 */	N+T, "SIGQUIT: quit",
+	/*  4 */	T, "SIGILL: illegal instruction",
+	/*  5 */	T, "SIGTRAP: trace trap",
+	/*  6 */	N+T, "SIGABRT: abort",
+	/*  7 */	T, "SIGEMT: emulate instruction executed",
+	/*  8 */	P, "SIGFPE: floating-point exception",
+	/*  9 */	0, "SIGKILL: kill",
 	/* 10 */	P, "SIGBUS: bus error",
 	/* 11 */	P, "SIGSEGV: segmentation violation",
 	/* 12 */	T, "SIGSYS: bad system call",
diff --git a/src/pkg/runtime/signals_plan9.h b/src/pkg/runtime/signals_plan9.h
index 5df7576..0f1165e 100644
--- a/src/pkg/runtime/signals_plan9.h
+++ b/src/pkg/runtime/signals_plan9.h
@@ -1 +1,24 @@
-// nothing to see here
+#define N SigNotify
+#define T SigThrow
+#define P SigPanic
+
+SigTab runtime·sigtab[] = {
+	P, "sys: fp:",
+
+	// Go libraries expect to be able
+	// to recover from memory
+	// read/write errors, so we flag
+	// those as panics. All other traps
+	// are generally more serious and
+	// should immediately throw an
+	// exception.
+	P, "sys: trap: fault read addr",
+	P, "sys: trap: fault write addr",
+	T, "sys: trap:",
+
+	N, "sys: bad sys call",
+};
+
+#undef N
+#undef T
+#undef P
diff --git a/src/pkg/runtime/sigqueue.goc b/src/pkg/runtime/sigqueue.goc
index b49fdba..ab5f312 100644
--- a/src/pkg/runtime/sigqueue.goc
+++ b/src/pkg/runtime/sigqueue.goc
@@ -5,36 +5,24 @@
 // This file implements runtime support for signal handling.
 //
 // Most synchronization primitives are not available from
-// the signal handler (it cannot block and cannot use locks)
+// the signal handler (it cannot block, allocate memory, or use locks)
 // so the handler communicates with a processing goroutine
 // via struct sig, below.
 //
-// Ownership for sig.Note passes back and forth between
-// the signal handler and the signal goroutine in rounds.
-// The initial state is that sig.note is cleared (setup by signal_enable).
-// At the beginning of each round, mask == 0.
-// The round goes through three stages:
-//
-// (In parallel)
-// 1a) One or more signals arrive and are handled
-// by sigsend using cas to set bits in sig.mask.
-// The handler that changes sig.mask from zero to non-zero
-// calls notewakeup(&sig).
-// 1b) Sigrecv calls notesleep(&sig) to wait for the wakeup.
-//
-// 2) Having received the wakeup, sigrecv knows that sigsend
-// will not send another wakeup, so it can noteclear(&sig)
-// to prepare for the next round. (Sigsend may still be adding
-// signals to sig.mask at this point, which is fine.)
-//
-// 3) Sigrecv uses cas to grab the current sig.mask and zero it,
-// triggering the next round.
-//
-// The signal handler takes ownership of the note by atomically
-// changing mask from a zero to non-zero value. It gives up
-// ownership by calling notewakeup. The signal goroutine takes
-// ownership by returning from notesleep (caused by the notewakeup)
-// and gives up ownership by clearing mask.
+// 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"
@@ -45,15 +33,20 @@ static struct {
 	Note;
 	uint32 mask[(NSIG+31)/32];
 	uint32 wanted[(NSIG+31)/32];
-	uint32 kick;
+	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;
+	uint32 bit, mask, old, new;
 
 	if(!sig.inuse || s < 0 || s >= 32*nelem(sig.wanted) || !(sig.wanted[s/32]&(1U<<(s&31))))
 		return false;
@@ -65,8 +58,20 @@ runtime·sigsend(int32 s)
 		if(runtime·cas(&sig.mask[s/32], mask, mask|bit)) {
 			// Added to queue.
 			// Only send a wakeup if the receiver needs a kick.
-			if(runtime·cas(&sig.kick, 1, 0))
-				runtime·notewakeup(&sig);
+			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;
 		}
 	}
@@ -77,7 +82,7 @@ runtime·sigsend(int32 s)
 // Must only be called from a single goroutine at a time.
 func signal_recv() (m uint32) {
 	static uint32 recv[nelem(sig.mask)];
-	int32 i, more;
+	uint32 i, old, new;
 	
 	for(;;) {
 		// Serve from local copy if there are bits left.
@@ -89,15 +94,27 @@ func signal_recv() (m uint32) {
 			}
 		}
 
-		// Get a new local copy.
-		// Ask for a kick if more signals come in
-		// during or after our check (before the sleep).
-		if(sig.kick == 0) {
-			runtime·noteclear(&sig);
-			runtime·cas(&sig.kick, 0, 1);
+		// 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·entersyscallblock();
+					runtime·notesleep(&sig);
+					runtime·exitsyscall();
+					runtime·noteclear(&sig);
+				}
+				break;
+			}
 		}
 
-		more = 0;
+		// Get a new local copy.
 		for(i=0; i<nelem(sig.mask); i++) {
 			for(;;) {
 				m = sig.mask[i];
@@ -105,16 +122,7 @@ func signal_recv() (m uint32) {
 					break;
 			}
 			recv[i] = m;
-			if(m != 0)
-				more = 1;
 		}
-		if(more)
-			continue;
-
-		// Sleep waiting for more.
-		runtime·entersyscall();
-		runtime·notesleep(&sig);
-		runtime·exitsyscall();
 	}
 
 done:;
diff --git a/src/pkg/runtime/slice.c b/src/pkg/runtime/slice.c
index e5726c9..354c54c 100644
--- a/src/pkg/runtime/slice.c
+++ b/src/pkg/runtime/slice.c
@@ -5,22 +5,30 @@
 #include "runtime.h"
 #include "arch_GOARCH.h"
 #include "type.h"
+#include "typekind.h"
 #include "malloc.h"
+#include "race.h"
 
-static	int32	debug	= 0;
+static	bool	debug	= 0;
 
-static	void	makeslice1(SliceType*, int32, int32, Slice*);
-static	void	growslice1(SliceType*, Slice, int32, Slice *);
-	void	runtime·copy(Slice to, Slice fm, uintptr width, int32 ret);
+static	void	makeslice1(SliceType*, intgo, intgo, Slice*);
+static	void	growslice1(SliceType*, Slice, intgo, Slice *);
+	void	runtime·copy(Slice to, Slice fm, uintptr width, intgo ret);
 
 // see also unsafe·NewArray
 // makeslice(typ *Type, len, cap int64) (ary []any);
 void
 runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
 {
-	if(len < 0 || (int32)len != len)
+	// 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 || (int32)cap != cap || t->elem->size > 0 && cap > ((uintptr)-1) / t->elem->size)
+
+	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);
@@ -35,10 +43,10 @@ runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice 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.
-static uintptr zerobase;
+uintptr runtime·zerobase;
 
 static void
-makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
+makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret)
 {
 	uintptr size;
 
@@ -47,22 +55,34 @@ makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
 	ret->len = len;
 	ret->cap = cap;
 
-	if(cap == 0)
-		ret->array = (byte*)&zerobase;
+	if(size == 0)
+		ret->array = (byte*)&runtime·zerobase;
 	else if((t->elem->kind&KindNoPointers))
 		ret->array = runtime·mallocgc(size, FlagNoPointers, 1, 1);
-	else
-		ret->array = runtime·mal(size);
+	else {
+		ret->array = runtime·mallocgc(size, 0, 1, 1);
+
+		if(UseSpanType) {
+			if(false) {
+				runtime·printf("new slice [%D]%S: %p\n", (int64)cap, *t->elem->string, ret->array);
+			}
+			runtime·settype(ret->array, (uintptr)t->elem | TypeInfo_Array);
+		}
+	}
 }
 
 // appendslice(type *Type, x, y, []T) []T
+#pragma textflag 7
 void
 runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
 {
-	int32 m;
+	intgo m;
 	uintptr w;
+	void *pc;
+	uint8 *p, *q;
 
 	m = x.len+y.len;
+	w = t->elem->size;
 
 	if(m < x.len)
 		runtime·throw("append: slice overflow");
@@ -72,30 +92,83 @@ runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
 	else
 		ret = x;
 
-	w = t->elem->size;
-	runtime·memmove(ret.array + ret.len*w, y.array, y.len*w);
+	if(raceenabled) {
+		// Don't mark read/writes on the newly allocated slice.
+		pc = runtime·getcallerpc(&t);
+		// read x[:len]
+		if(m > x.cap)
+			runtime·racereadrangepc(x.array, x.len*w, w, pc, runtime·appendslice);
+		// read y
+		runtime·racereadrangepc(y.array, y.len*w, w, pc, runtime·appendslice);
+		// write x[len(x):len(x)+len(y)]
+		if(m <= x.cap)
+			runtime·racewriterangepc(ret.array+ret.len*w, y.len*w, w, pc, runtime·appendslice);
+	}
+
+	// A very common case is appending bytes. Small appends can avoid the overhead of memmove.
+	// We can generalize a bit here, and just pick small-sized appends.
+	p = ret.array+ret.len*w;
+	q = y.array;
+	w *= y.len;
+	if(w <= appendCrossover) {
+		if(p <= q || w <= p-q) // No overlap.
+			while(w-- > 0)
+				*p++ = *q++;
+		else {
+			p += w;
+			q += w;
+			while(w-- > 0)
+				*--p = *--q;
+		}
+	} else {
+		runtime·memmove(p, q, w);
+	}
 	ret.len += y.len;
 	FLUSH(&ret);
 }
 
 
 // appendstr([]byte, string) []byte
+#pragma textflag 7
 void
 runtime·appendstr(SliceType *t, Slice x, String y, Slice ret)
 {
-	int32 m;
+	intgo m;
+	void *pc;
+	uintptr w;
+	uint8 *p, *q;
 
 	m = x.len+y.len;
 
 	if(m < x.len)
-		runtime·throw("append: slice overflow");
+		runtime·throw("append: string overflow");
 
 	if(m > x.cap)
 		growslice1(t, x, m, &ret);
 	else
 		ret = x;
 
-	runtime·memmove(ret.array + ret.len, y.str, y.len);
+	if(raceenabled) {
+		// Don't mark read/writes on the newly allocated slice.
+		pc = runtime·getcallerpc(&t);
+		// read x[:len]
+		if(m > x.cap)
+			runtime·racereadrangepc(x.array, x.len, 1, pc, runtime·appendstr);
+		// write x[len(x):len(x)+len(y)]
+		if(m <= x.cap)
+			runtime·racewriterangepc(ret.array+ret.len, y.len, 1, pc, runtime·appendstr);
+	}
+
+	// Small appends can avoid the overhead of memmove.
+	w = y.len;
+	p = ret.array+ret.len;
+	q = y.str;
+	if(w <= appendCrossover) {
+		while(w-- > 0)
+			*p++ = *q++;
+	} else {
+		runtime·memmove(p, q, w);
+	}
 	ret.len += y.len;
 	FLUSH(&ret);
 }
@@ -106,15 +179,21 @@ void
 runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
 {
 	int64 cap;
+	void *pc;
 
 	if(n < 1)
 		runtime·panicstring("growslice: invalid n");
 
 	cap = old.cap + n;
 
-	if((int32)cap != cap || cap > ((uintptr)-1) / t->elem->size)
+	if((intgo)cap != cap || cap < 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, t->elem->size, pc, runtime·growslice);
+	}
+
 	growslice1(t, old, cap, &ret);
 
 	FLUSH(&ret);
@@ -128,12 +207,17 @@ runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
 }
 
 static void
-growslice1(SliceType *t, Slice x, int32 newcap, Slice *ret)
+growslice1(SliceType *t, Slice x, intgo newcap, Slice *ret)
 {
-	int32 m;
+	intgo m;
 
 	m = x.cap;
-	if(m == 0)
+	
+	// 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(m+m < newcap)
 		m = newcap;
 	else {
 		do {
@@ -147,153 +231,13 @@ growslice1(SliceType *t, Slice x, int32 newcap, Slice *ret)
 	runtime·memmove(ret->array, x.array, ret->len * t->elem->size);
 }
 
-// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any);
-void
-runtime·sliceslice(Slice old, uint64 lb, uint64 hb, uint64 width, Slice ret)
-{
-	if(hb > old.cap || lb > hb) {
-		if(debug) {
-			runtime·prints("runtime.sliceslice: old=");
-			runtime·printslice(old);
-			runtime·prints("; lb=");
-			runtime·printint(lb);
-			runtime·prints("; hb=");
-			runtime·printint(hb);
-			runtime·prints("; width=");
-			runtime·printint(width);
-			runtime·prints("\n");
-
-			runtime·prints("oldarray: nel=");
-			runtime·printint(old.len);
-			runtime·prints("; cap=");
-			runtime·printint(old.cap);
-			runtime·prints("\n");
-		}
-		runtime·panicslice();
-	}
-
-	// new array is inside old array
-	ret.len = hb - lb;
-	ret.cap = old.cap - lb;
-	ret.array = old.array + lb*width;
-
-	FLUSH(&ret);
-
-	if(debug) {
-		runtime·prints("runtime.sliceslice: old=");
-		runtime·printslice(old);
-		runtime·prints("; lb=");
-		runtime·printint(lb);
-		runtime·prints("; hb=");
-		runtime·printint(hb);
-		runtime·prints("; width=");
-		runtime·printint(width);
-		runtime·prints("; ret=");
-		runtime·printslice(ret);
-		runtime·prints("\n");
-	}
-}
-
-// sliceslice1(old []any, lb uint64, width uint64) (ary []any);
-void
-runtime·sliceslice1(Slice old, uint64 lb, uint64 width, Slice ret)
-{
-	if(lb > old.len) {
-		if(debug) {
-			runtime·prints("runtime.sliceslice: old=");
-			runtime·printslice(old);
-			runtime·prints("; lb=");
-			runtime·printint(lb);
-			runtime·prints("; width=");
-			runtime·printint(width);
-			runtime·prints("\n");
-
-			runtime·prints("oldarray: nel=");
-			runtime·printint(old.len);
-			runtime·prints("; cap=");
-			runtime·printint(old.cap);
-			runtime·prints("\n");
-		}
-		runtime·panicslice();
-	}
-
-	// new array is inside old array
-	ret.len = old.len - lb;
-	ret.cap = old.cap - lb;
-	ret.array = old.array + lb*width;
-
-	FLUSH(&ret);
-
-	if(debug) {
-		runtime·prints("runtime.sliceslice: old=");
-		runtime·printslice(old);
-		runtime·prints("; lb=");
-		runtime·printint(lb);
-		runtime·prints("; width=");
-		runtime·printint(width);
-		runtime·prints("; ret=");
-		runtime·printslice(ret);
-		runtime·prints("\n");
-	}
-}
-
-// slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) (ary []any);
+// copy(to any, fr any, wid uintptr) int
+#pragma textflag 7
 void
-runtime·slicearray(byte* old, uint64 nel, uint64 lb, uint64 hb, uint64 width, Slice ret)
+runtime·copy(Slice to, Slice fm, uintptr width, intgo ret)
 {
-	if(nel > 0 && old == nil) {
-		// crash if old == nil.
-		// could give a better message
-		// but this is consistent with all the in-line checks
-		// that the compiler inserts for other uses.
-		*old = 0;
-	}
-
-	if(hb > nel || lb > hb) {
-		if(debug) {
-			runtime·prints("runtime.slicearray: old=");
-			runtime·printpointer(old);
-			runtime·prints("; nel=");
-			runtime·printint(nel);
-			runtime·prints("; lb=");
-			runtime·printint(lb);
-			runtime·prints("; hb=");
-			runtime·printint(hb);
-			runtime·prints("; width=");
-			runtime·printint(width);
-			runtime·prints("\n");
-		}
-		runtime·panicslice();
-	}
-
-	// new array is inside old array
-	ret.len = hb-lb;
-	ret.cap = nel-lb;
-	ret.array = old + lb*width;
-
-	FLUSH(&ret);
-
-	if(debug) {
-		runtime·prints("runtime.slicearray: old=");
-		runtime·printpointer(old);
-		runtime·prints("; nel=");
-		runtime·printint(nel);
-		runtime·prints("; lb=");
-		runtime·printint(lb);
-		runtime·prints("; hb=");
-		runtime·printint(hb);
-		runtime·prints("; width=");
-		runtime·printint(width);
-		runtime·prints("; ret=");
-		runtime·printslice(ret);
-		runtime·prints("\n");
-	}
-}
+	void *pc;
 
-// copy(to any, fr any, wid uint32) int
-void
-runtime·copy(Slice to, Slice fm, uintptr width, int32 ret)
-{
 	if(fm.len == 0 || to.len == 0 || width == 0) {
 		ret = 0;
 		goto out;
@@ -303,6 +247,12 @@ runtime·copy(Slice to, Slice fm, uintptr width, int32 ret)
 	if(to.len < ret)
 		ret = to.len;
 
+	if(raceenabled) {
+		pc = runtime·getcallerpc(&to);
+		runtime·racewriterangepc(to.array, ret*width, width, pc, runtime·copy);
+		runtime·racereadrangepc(fm.array, ret*width, 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 {
@@ -325,9 +275,12 @@ out:
 	}
 }
 
+#pragma textflag 7
 void
-runtime·slicestringcopy(Slice to, String fm, int32 ret)
+runtime·slicestringcopy(Slice to, String fm, intgo ret)
 {
+	void *pc;
+
 	if(fm.len == 0 || to.len == 0) {
 		ret = 0;
 		goto out;
@@ -337,6 +290,11 @@ runtime·slicestringcopy(Slice to, String fm, int32 ret)
 	if(to.len < ret)
 		ret = to.len;
 
+	if(raceenabled) {
+		pc = runtime·getcallerpc(&to);
+		runtime·racewriterangepc(to.array, ret, 1, pc, runtime·slicestringcopy);
+	}
+
 	runtime·memmove(to.array, fm.str, ret);
 
 out:
diff --git a/src/pkg/runtime/softfloat_arm.c b/src/pkg/runtime/softfloat_arm.c
index bd73cb1..9a54406 100644
--- a/src/pkg/runtime/softfloat_arm.c
+++ b/src/pkg/runtime/softfloat_arm.c
@@ -420,6 +420,23 @@ stage3:	// regd, regm are 4bit variables
 				regd, regm, m->freghi[regd], m->freglo[regd]);
 		break;
 
+	case 0xeeb00bc0:	// D[regd] = abs D[regm]
+		m->freglo[regd] = m->freglo[regm];
+		m->freghi[regd] = m->freghi[regm] & ((1<<31)-1);
+
+		if(trace)
+			runtime·printf("*** D[%d] = abs D[%d] %x-%x\n",
+					regd, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xeeb00ac0:	// F[regd] = abs F[regm]
+		m->freglo[regd] = m->freglo[regm] & ((1<<31)-1);
+
+		if(trace)
+			runtime·printf("*** F[%d] = abs F[%d] %x\n",
+					regd, regm, m->freglo[regd]);
+		break;
+
 	case 0xeeb40bc0:	// D[regd] :: D[regm] (CMPD)
 		runtime·fcmp64c(getd(regd), getd(regm), &cmp, &nan);
 		m->fflag = fstatus(nan, cmp);
diff --git a/src/pkg/runtime/stack.c b/src/pkg/runtime/stack.c
new file mode 100644
index 0000000..e9a3567
--- /dev/null
+++ b/src/pkg/runtime/stack.c
@@ -0,0 +1,282 @@
+// 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"
+
+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);
+		if(n == nil)
+			runtime·throw("out of memory (stackcacherefill)");
+		runtime·xadd64(&mstats.stacks_sys, FixedStack*StackCacheBatch);
+		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(uint32 n)
+{
+	uint32 pos;
+	void *v;
+
+	// 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");
+
+	// Stack allocator uses malloc/free most of the time,
+	// but if we're in the middle of malloc and need stack,
+	// we have to do something else to avoid deadlock.
+	// In that case, we fall back on a fixed-size free-list
+	// allocator, assuming that inside malloc all the stack
+	// frames are small, so that all the stack allocations
+	// will be a single size, the minimum (right now, 5k).
+	if(n == FixedStack || m->mallocing || m->gcing) {
+		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++;
+		return v;
+	}
+	return runtime·mallocgc(n, FlagNoProfiling|FlagNoGC, 0, 0);
+}
+
+void
+runtime·stackfree(void *v, uintptr n)
+{
+	uint32 pos;
+
+	if(n == FixedStack || m->mallocing || m->gcing) {
+		if(m->stackcachecnt == StackCacheSize)
+			stackcacherelease();
+		pos = m->stackcachepos;
+		m->stackcache[pos] = v;
+		m->stackcachepos = (pos + 1) % StackCacheSize;
+		m->stackcachecnt++;
+		m->stackinuse--;
+		return;
+	}
+	runtime·free(v);
+}
+
+// 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;
+	Gobuf label;
+	uint32 argsize;
+	uintptr cret;
+	byte *sp, *old;
+	uintptr *src, *dst, *dstend;
+	G *gp;
+	int64 goid;
+
+//printf("oldstack m->cret=%p\n", m->cret);
+
+	gp = m->curg;
+	top = (Stktop*)gp->stackbase;
+	old = (byte*)gp->stackguard - StackGuard;
+	sp = (byte*)top;
+	argsize = top->argsize;
+	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);
+
+	label = top->gobuf;
+	gp->stackbase = (uintptr)top->stackbase;
+	gp->stackguard = (uintptr)top->stackguard;
+	if(top->free != 0)
+		runtime·stackfree(old, top->free);
+
+	cret = m->cret;
+	m->cret = 0;  // drop reference
+	runtime·gogo(&label, cret);
+}
+
+// Called from reflect·call 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, minalloc, argsize;
+	Stktop *top;
+	byte *stk, *sp;
+	uintptr *src, *dst, *dstend;
+	G *gp;
+	Gobuf label;
+	bool reflectcall;
+	uintptr free;
+
+	framesize = m->moreframesize;
+	argsize = m->moreargsize;
+	gp = m->curg;
+
+	if(m->morebuf.sp < gp->stackguard - StackGuard) {
+		runtime·printf("runtime: split stack overflow: %p < %p\n", m->morebuf.sp, gp->stackguard - StackGuard);
+		runtime·throw("runtime: split stack overflow");
+	}
+	if(argsize % sizeof(uintptr) != 0) {
+		runtime·printf("runtime: stack split with misaligned argsize %d\n", argsize);
+		runtime·throw("runtime: stack split argsize");
+	}
+
+	minalloc = 0;
+	reflectcall = framesize==1;
+	if(reflectcall) {
+		framesize = 0;
+		// moreframesize_minalloc is only set in runtime·gc(),
+		// that calls newstack via reflect·call().
+		minalloc = m->moreframesize_minalloc;
+		m->moreframesize_minalloc = 0;
+		if(framesize < minalloc)
+			framesize = minalloc;
+	}
+
+	if(reflectcall && minalloc == 0 && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > gp->stackguard) {
+		// special case: called from reflect.call (framesize==1)
+		// to call code with an arbitrary argument size,
+		// and we have enough space on the current stack.
+		// the new Stktop* is necessary to unwind, but
+		// we don't need to create a new segment.
+		top = (Stktop*)(m->morebuf.sp - sizeof(*top));
+		stk = (byte*)gp->stackguard - StackGuard;
+		free = 0;
+	} else {
+		// allocate new segment.
+		framesize += argsize;
+		framesize += StackExtra;	// room for more functions, Stktop.
+		if(framesize < StackMin)
+			framesize = StackMin;
+		framesize += StackSystem;
+		stk = runtime·stackalloc(framesize);
+		top = (Stktop*)(stk+framesize-sizeof(*top));
+		free = framesize;
+	}
+
+	if(0) {
+		runtime·printf("newstack framesize=%d argsize=%d morepc=%p moreargp=%p gobuf=%p, %p top=%p old=%p\n",
+			framesize, argsize, m->morepc, m->moreargp, m->morebuf.pc, m->morebuf.sp, top, gp->stackbase);
+	}
+
+	top->stackbase = (byte*)gp->stackbase;
+	top->stackguard = (byte*)gp->stackguard;
+	top->gobuf = m->morebuf;
+	top->argp = m->moreargp;
+	top->argsize = argsize;
+	top->free = free;
+	m->moreargp = nil;
+	m->morebuf.pc = nil;
+	m->morebuf.sp = (uintptr)nil;
+
+	// copy flag from panic
+	top->panic = gp->ispanic;
+	gp->ispanic = false;
+
+	gp->stackbase = (uintptr)top;
+	gp->stackguard = (uintptr)stk + StackGuard;
+
+	sp = (byte*)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).
+	label.sp = (uintptr)sp;
+	label.pc = (byte*)runtime·lessstack;
+	label.g = m->curg;
+	if(reflectcall)
+		runtime·gogocallfn(&label, (FuncVal*)m->morepc);
+	else
+		runtime·gogocall(&label, m->morepc, m->cret);
+
+	*(int32*)345 = 123;	// never return
+}
diff --git a/src/pkg/runtime/stack.h b/src/pkg/runtime/stack.h
index d42385d..06b0c56 100644
--- a/src/pkg/runtime/stack.h
+++ b/src/pkg/runtime/stack.h
@@ -55,13 +55,19 @@ functions to make sure that this limit cannot be violated.
 enum {
 	// StackSystem is a number of additional bytes to add
 	// to each stack below the usual guard area for OS-specific
-	// purposes like signal handling. Used on Windows because
-	// it does not use a separate stack.
+	// purposes like signal handling. Used on Windows and on
+	// Plan 9 because they do not use a separate stack.
 #ifdef GOOS_windows
 	StackSystem = 512 * sizeof(uintptr),
 #else
+#ifdef GOOS_plan9
+	// The size of the note handler frame varies among architectures,
+	// but 512 bytes should be enough for every implementation.
+	StackSystem = 512,
+#else
 	StackSystem = 0,
-#endif
+#endif	// Plan 9
+#endif	// Windows
 
 	// The amount of extra stack to allocate beyond the size
 	// needed for the single frame that triggered the split.
diff --git a/src/pkg/runtime/stack_test.go b/src/pkg/runtime/stack_test.go
index 01c6b6e..759f7c4 100644
--- a/src/pkg/runtime/stack_test.go
+++ b/src/pkg/runtime/stack_test.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.
 
-// Test stack split logic by calling functions of every frame size 
+// 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
@@ -34,6 +34,7 @@ package runtime_test
 import (
 	. "runtime"
 	"testing"
+	"time"
 	"unsafe"
 )
 
@@ -1526,3 +1527,51 @@ func stack4988() (uintptr, uintptr) { var buf [4988]byte; use(buf[:]); return St
 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() }
+
+// 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     = 512
+		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
+		}
+	}
+	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)
+	}
+	if s1.StackInuse > 4<<20 {
+		t.Fatalf("Stack inuse: want %v, got %v", 4<<20, s1.StackInuse)
+	}
+}
diff --git a/src/pkg/runtime/string.goc b/src/pkg/runtime/string.goc
index 7e1f8a1..c0d3f2b 100644
--- a/src/pkg/runtime/string.goc
+++ b/src/pkg/runtime/string.goc
@@ -6,6 +6,7 @@ package runtime
 #include "runtime.h"
 #include "arch_GOARCH.h"
 #include "malloc.h"
+#include "race.h"
 
 String	runtime·emptystring;
 
@@ -33,10 +34,10 @@ runtime·findnullw(uint16 *s)
 	return l;
 }
 
-uint32 runtime·maxstring = 256;
+uint32 runtime·maxstring = 256; // a hint for print
 
 static String
-gostringsize(int32 l)
+gostringsize(intgo l)
 {
 	String s;
 	uint32 ms;
@@ -58,7 +59,7 @@ gostringsize(int32 l)
 String
 runtime·gostring(byte *str)
 {
-	int32 l;
+	intgo l;
 	String s;
 
 	l = runtime·findnull(str);
@@ -68,7 +69,7 @@ runtime·gostring(byte *str)
 }
 
 String
-runtime·gostringn(byte *str, int32 l)
+runtime·gostringn(byte *str, intgo l)
 {
 	String s;
 
@@ -78,7 +79,7 @@ runtime·gostringn(byte *str, int32 l)
 }
 
 Slice
-runtime·gobytes(byte *p, int32 n)
+runtime·gobytes(byte *p, intgo n)
 {
 	Slice sl;
 
@@ -102,7 +103,7 @@ runtime·gostringnocopy(byte *str)
 String
 runtime·gostringw(uint16 *str)
 {
-	int32 n1, n2, i;
+	intgo n1, n2, i;
 	byte buf[8];
 	String s;
 
@@ -139,17 +140,26 @@ runtime·catstring(String s1, String s2)
 }
 
 static String
-concatstring(int32 n, String *s)
+concatstring(intgo n, String *s)
 {
-	int32 i, l;
+	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;
@@ -163,14 +173,14 @@ concatstring(int32 n, String *s)
 #pragma textflag 7
 // s1 is the first of n strings.
 // the output string follows.
-func concatstring(n int32, s1 String) {
+func concatstring(n int, s1 String) {
 	(&s1)[n] = concatstring(n, &s1);
 }
 
 static int32
 cmpstring(String s1, String s2)
 {
-	uint32 i, l;
+	uintgo i, l;
 	byte c1, c2;
 
 	l = s1.len;
@@ -191,14 +201,34 @@ cmpstring(String s1, String s2)
 	return 0;
 }
 
-func cmpstring(s1 String, s2 String) (v int32) {
+func cmpstring(s1 String, s2 String) (v int) {
 	v = cmpstring(s1, s2);
 }
 
+func eqstring(s1 String, s2 String) (v bool) {
+	uintgo i, l;
+
+	if(s1.len != s2.len) {
+		v = false;
+		return;
+	}
+	if(s1.str == s2.str) {
+		v = true;
+		return;
+	}
+	l = s1.len;
+	for(i=0; i<l; i++)
+		if(s1.str[i] != s2.str[i]) {
+			v = false;
+			return;
+		}
+	v = true;
+}
+
 int32
 runtime·strcmp(byte *s1, byte *s2)
 {
-	uint32 i;
+	uintptr i;
 	byte c1, c2;
 
 	for(i=0;; i++) {
@@ -235,31 +265,6 @@ runtime·strstr(byte *s1, byte *s2)
 	return nil;
 }
 
-func slicestring(si String, lindex int32, hindex int32) (so String) {
-	int32 l;
-
-	if(lindex < 0 || lindex > si.len ||
-	   hindex < lindex || hindex > si.len) {
-	   	runtime·panicslice();
-	}
-
-	l = hindex-lindex;
-	so.str = si.str + lindex;
-	so.len = l;
-}
-
-func slicestring1(si String, lindex int32) (so String) {
-	int32 l;
-
-	if(lindex < 0 || lindex > si.len) {
-		runtime·panicslice();
-	}
-
-	l = si.len-lindex;
-	so.str = si.str + lindex;
-	so.len = l;
-}
-
 func intstring(v int64) (s String) {
 	s = gostringsize(8);
 	s.len = runtime·runetochar(s.str, v);
@@ -267,6 +272,12 @@ func intstring(v int64) (s String) {
 }
 
 func slicebytetostring(b Slice) (s String) {
+	void *pc;
+
+	if(raceenabled) {
+		pc = runtime·getcallerpc(&b);
+		runtime·racereadrangepc(b.array, b.len, 1, pc, runtime·slicebytetostring);
+	}
 	s = gostringsize(b.len);
 	runtime·memmove(s.str, b.array, s.len);
 }
@@ -279,10 +290,15 @@ func stringtoslicebyte(s String) (b Slice) {
 }
 
 func slicerunetostring(b Slice) (s String) {
-	int32 siz1, siz2, i;
+	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), sizeof(*a), pc, runtime·slicerunetostring);
+	}
 	a = (int32*)b.array;
 	siz1 = 0;
 	for(i=0; i<b.len; i++) {
@@ -302,7 +318,7 @@ func slicerunetostring(b Slice) (s String) {
 }
 
 func stringtoslicerune(s String) (b Slice) {
-	int32 n;
+	intgo n;
 	int32 dum, *r;
 	uint8 *p, *ep;
 
@@ -330,7 +346,7 @@ enum
 	Runeself	= 0x80,
 };
 
-func stringiter(s String, k int32) (retk int32) {
+func stringiter(s String, k int) (retk int) {
 	int32 l;
 
 	if(k >= s.len) {
@@ -351,7 +367,7 @@ func stringiter(s String, k int32) (retk int32) {
 out:
 }
 
-func stringiter2(s String, k int32) (retk int32, retv int32) {
+func stringiter2(s String, k int) (retk int, retv int32) {
 	if(k >= s.len) {
 		// retk=0 is end of iteration
 		retk = 0;
diff --git a/src/pkg/runtime/string_test.go b/src/pkg/runtime/string_test.go
new file mode 100644
index 0000000..8f13f0f
--- /dev/null
+++ b/src/pkg/runtime/string_test.go
@@ -0,0 +1,45 @@
+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")
+		}
+	}
+}
diff --git a/src/pkg/runtime/symtab.c b/src/pkg/runtime/symtab.c
index f29276b..d7221c4 100644
--- a/src/pkg/runtime/symtab.c
+++ b/src/pkg/runtime/symtab.c
@@ -2,20 +2,59 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Runtime symbol table access.  Work in progress.
-// The Plan 9 symbol table is not in a particularly convenient form.
-// The routines here massage it into a more usable form; eventually
-// we'll change 6l to do this for us, but it is easier to experiment
-// here than to change 6l and all the other tools.
+// Runtime symbol table parsing.
 //
-// The symbol table also needs to be better integrated with the type
-// strings table in the future.  This is just a quick way to get started
-// and figure out exactly what we want.
+// The Go tools use a symbol table derived from the Plan 9 symbol table
+// format. The symbol table is kept in its own section treated as
+// read-only memory when the binary is running: the binary consults the
+// table.
+// 
+// The format used by Go 1.0 was basically the Plan 9 format. Each entry
+// is variable sized but had this format:
+// 
+// 	4-byte value, big endian
+// 	1-byte type ([A-Za-z] + 0x80)
+// 	name, NUL terminated (or for 'z' and 'Z' entries, double-NUL terminated)
+// 	4-byte Go type address, big endian (new in Go)
+// 
+// In order to support greater interoperation with standard toolchains,
+// Go 1.1 uses a more flexible yet smaller encoding of the entries.
+// The overall structure is unchanged from Go 1.0 and, for that matter,
+// from Plan 9.
+// 
+// The Go 1.1 table is a re-encoding of the data in a Go 1.0 table.
+// To identify a new table as new, it begins one of two eight-byte
+// sequences:
+// 
+// 	FF FF FF FD 00 00 00 xx - big endian new table
+// 	FD FF FF FF 00 00 00 xx - little endian new table
+// 
+// This sequence was chosen because old tables stop at an entry with type
+// 0, so old code reading a new table will see only an empty table. The
+// first four bytes are the target-endian encoding of 0xfffffffd. The
+// final xx gives AddrSize, the width of a full-width address.
+// 
+// After that header, each entry is encoded as follows.
+// 
+// 	1-byte type (0-51 + two flag bits)
+// 	AddrSize-byte value, host-endian OR varint-encoded value
+// 	AddrSize-byte Go type address OR nothing
+// 	[n] name, terminated as before
+// 
+// The type byte comes first, but 'A' encodes as 0 and 'a' as 26, so that
+// the type itself is only in the low 6 bits. The upper two bits specify
+// the format of the next two fields. If the 0x40 bit is set, the value
+// is encoded as an full-width 4- or 8-byte target-endian word. Otherwise
+// the value is a varint-encoded number. If the 0x80 bit is set, the Go
+// type is present, again as a 4- or 8-byte target-endian word. If not,
+// there is no Go type in this entry. The NUL-terminated name ends the
+// entry.
 
 #include "runtime.h"
 #include "defs_GOOS_GOARCH.h"
 #include "os_GOOS.h"
 #include "arch_GOARCH.h"
+#include "malloc.h"
 
 extern byte pclntab[], epclntab[], symtab[], esymtab[];
 
@@ -28,24 +67,100 @@ struct Sym
 //	byte *gotype;
 };
 
+static uintptr mainoffset;
+
+// A dynamically allocated string containing multiple substrings.
+// Individual strings are slices of hugestring.
+static String hugestring;
+static int32 hugestring_len;
+
+extern void main·main(void);
+
+static uintptr
+readword(byte **pp, byte *ep)
+{
+	byte *p; 
+
+	p = *pp;
+	if(ep - p < sizeof(void*)) {
+		*pp = ep;
+		return 0;
+	}
+	*pp = p + sizeof(void*);
+
+	// Hairy, but only one of these four cases gets compiled.
+	if(sizeof(void*) == 8) {
+		if(BigEndian) {
+			return ((uint64)p[0]<<56) | ((uint64)p[1]<<48) | ((uint64)p[2]<<40) | ((uint64)p[3]<<32) |
+				((uint64)p[4]<<24) | ((uint64)p[5]<<16) | ((uint64)p[6]<<8) | ((uint64)p[7]);
+		}
+		return ((uint64)p[7]<<56) | ((uint64)p[6]<<48) | ((uint64)p[5]<<40) | ((uint64)p[4]<<32) |
+			((uint64)p[3]<<24) | ((uint64)p[2]<<16) | ((uint64)p[1]<<8) | ((uint64)p[0]);
+	}
+	if(BigEndian) {
+		return ((uint32)p[0]<<24) | ((uint32)p[1]<<16) | ((uint32)p[2]<<8) | ((uint32)p[3]);
+	}
+	return ((uint32)p[3]<<24) | ((uint32)p[2]<<16) | ((uint32)p[1]<<8) | ((uint32)p[0]);
+}
+
 // Walk over symtab, calling fn(&s) for each symbol.
 static void
 walksymtab(void (*fn)(Sym*))
 {
 	byte *p, *ep, *q;
 	Sym s;
+	int32 widevalue, havetype, shift;
 
 	p = symtab;
 	ep = esymtab;
+
+	// Table must begin with correct magic number.
+	if(ep - p < 8 || p[4] != 0x00 || p[5] != 0x00 || p[6] != 0x00 || p[7] != sizeof(void*))
+		return;
+	if(BigEndian) {
+		if(p[0] != 0xff || p[1] != 0xff || p[2] != 0xff || p[3] != 0xfd)
+			return;
+	} else {
+		if(p[0] != 0xfd || p[1] != 0xff || p[2] != 0xff || p[3] != 0xff)
+			return;
+	}
+	p += 8;
+
 	while(p < ep) {
-		if(p + 7 > ep)
-			break;
-		s.value = ((uint32)p[0]<<24) | ((uint32)p[1]<<16) | ((uint32)p[2]<<8) | ((uint32)p[3]);
+		s.symtype = p[0]&0x3F;
+		widevalue = p[0]&0x40;
+		havetype = p[0]&0x80;
+		if(s.symtype < 26)
+			s.symtype += 'A';
+		else
+			s.symtype += 'a' - 26;
+		p++;
+
+		// Value, either full-width or varint-encoded.
+		if(widevalue) {
+			s.value = readword(&p, ep);
+		} else {
+			s.value = 0;
+			shift = 0;
+			while(p < ep && (p[0]&0x80) != 0) {
+				s.value |= (uintptr)(p[0]&0x7F)<<shift;
+				shift += 7;
+				p++;
+			}
+			if(p >= ep)
+				break;
+			s.value |= (uintptr)p[0]<<shift;
+			p++;
+		}
+		
+		// Go type, if present. Ignored but must skip over.
+		if(havetype)
+			readword(&p, ep);
 
-		if(!(p[4]&0x80))
+		// Name.
+		if(ep - p < 2)
 			break;
-		s.symtype = p[4] & ~0x80;
-		p += 5;
+
 		s.name = p;
 		if(s.symtype == 'z' || s.symtype == 'Z') {
 			// path reference string - skip first byte,
@@ -65,7 +180,7 @@ walksymtab(void (*fn)(Sym*))
 				break;
 			p = q+1;
 		}
-		p += 4;	// go type
+	
 		fn(&s);
 	}
 }
@@ -80,12 +195,13 @@ static int32 nfname;
 
 static uint32 funcinit;
 static Lock funclock;
+static uintptr lastvalue;
 
 static void
 dofunc(Sym *sym)
 {
 	Func *f;
-
+	
 	switch(sym->symtype) {
 	case 't':
 	case 'T':
@@ -93,6 +209,11 @@ dofunc(Sym *sym)
 	case 'L':
 		if(runtime·strcmp(sym->name, (byte*)"etext") == 0)
 			break;
+		if(sym->value < lastvalue) {
+			runtime·printf("symbols out of order: %p before %p\n", lastvalue, sym->value);
+			runtime·throw("malformed symbol table");
+		}
+		lastvalue = sym->value;
 		if(func == nil) {
 			nfunc++;
 			break;
@@ -104,24 +225,24 @@ dofunc(Sym *sym)
 			f->frame = -sizeof(uintptr);
 		break;
 	case 'm':
-		if(nfunc > 0 && func != nil)
-			func[nfunc-1].frame += sym->value;
-		break;
-	case 'p':
-		if(nfunc > 0 && func != nil) {
-			f = &func[nfunc-1];
-			// args counts 32-bit words.
-			// sym->value is the arg's offset.
-			// don't know width of this arg, so assume it is 64 bits.
-			if(f->args < sym->value/4 + 2)
-				f->args = sym->value/4 + 2;
+		if(nfunc <= 0 || func == nil)
+			break;
+		if(runtime·strcmp(sym->name, (byte*)".frame") == 0)
+			func[nfunc-1].frame = sym->value;
+		else if(runtime·strcmp(sym->name, (byte*)".locals") == 0)
+			func[nfunc-1].locals = sym->value;
+		else if(runtime·strcmp(sym->name, (byte*)".args") == 0)
+			func[nfunc-1].args = sym->value;
+		else {
+			runtime·printf("invalid 'm' symbol named '%s'\n", sym->name);
+			runtime·throw("mangled symbol table");
 		}
 		break;
 	case 'f':
 		if(fname == nil) {
 			if(sym->value >= nfname) {
 				if(sym->value >= 0x10000) {
-					runtime·printf("invalid symbol file index %p\n", sym->value);
+					runtime·printf("runtime: invalid symbol file index %p\n", sym->value);
 					runtime·throw("mangled symbol table");
 				}
 				nfname = sym->value+1;
@@ -135,14 +256,15 @@ dofunc(Sym *sym)
 
 // put together the path name for a z entry.
 // the f entries have been accumulated into fname already.
-static void
+// returns the length of the path name.
+static int32
 makepath(byte *buf, int32 nbuf, byte *path)
 {
 	int32 n, len;
 	byte *p, *ep, *q;
 
 	if(nbuf <= 0)
-		return;
+		return 0;
 
 	p = buf;
 	ep = buf + nbuf;
@@ -163,6 +285,26 @@ makepath(byte *buf, int32 nbuf, byte *path)
 		runtime·memmove(p, q, len+1);
 		p += len;
 	}
+	return p - buf;
+}
+
+// appends p to hugestring
+static String
+gostringn(byte *p, int32 l)
+{
+	String s;
+
+	if(l == 0)
+		return runtime·emptystring;
+	if(hugestring.str == nil) {
+		hugestring_len += l;
+		return runtime·emptystring;
+	}
+	s.str = hugestring.str + hugestring.len;
+	s.len = l;
+	hugestring.len += s.len;
+	runtime·memmove(s.str, p, l);
+	return s;
 }
 
 // walk symtab accumulating path names for use by pc/ln table.
@@ -181,11 +323,13 @@ dosrcline(Sym *sym)
 	static int32 incstart;
 	static int32 nfunc, nfile, nhist;
 	Func *f;
-	int32 i;
+	int32 i, l;
 
 	switch(sym->symtype) {
 	case 't':
 	case 'T':
+		if(hugestring.str == nil)
+			break;
 		if(runtime·strcmp(sym->name, (byte*)"etext") == 0)
 			break;
 		f = &func[nfunc++];
@@ -200,23 +344,23 @@ dosrcline(Sym *sym)
 	case 'z':
 		if(sym->value == 1) {
 			// entry for main source file for a new object.
-			makepath(srcbuf, sizeof srcbuf, sym->name+1);
+			l = makepath(srcbuf, sizeof srcbuf, sym->name+1);
 			nhist = 0;
 			nfile = 0;
 			if(nfile == nelem(files))
 				return;
-			files[nfile].srcstring = runtime·gostring(srcbuf);
+			files[nfile].srcstring = gostringn(srcbuf, l);
 			files[nfile].aline = 0;
 			files[nfile++].delta = 0;
 		} else {
 			// push or pop of included file.
-			makepath(srcbuf, sizeof srcbuf, sym->name+1);
+			l = makepath(srcbuf, sizeof srcbuf, sym->name+1);
 			if(srcbuf[0] != '\0') {
 				if(nhist++ == 0)
 					incstart = sym->value;
 				if(nhist == 0 && nfile < nelem(files)) {
 					// new top-level file
-					files[nfile].srcstring = runtime·gostring(srcbuf);
+					files[nfile].srcstring = gostringn(srcbuf, l);
 					files[nfile].aline = sym->value;
 					// this is "line 0"
 					files[nfile++].delta = sym->value - 1;
@@ -275,7 +419,7 @@ splitpcln(void)
 			line += *p++;
 		else
 			line -= *p++ - 64;
-		
+
 		// pc, line now match.
 		// Because the state machine begins at pc==entry and line==0,
 		// it can happen - just at the beginning! - that the update may
@@ -297,7 +441,7 @@ splitpcln(void)
 			while(f < ef && pc >= (f+1)->entry);
 			f->pcln.array = p;
 			// pc0 and ln0 are the starting values for
-			// the loop over f->pcln, so pc must be 
+			// the loop over f->pcln, so pc must be
 			// adjusted by the same pcquant update
 			// that we're going to do as we continue our loop.
 			f->pc0 = pc + pcquant;
@@ -323,11 +467,11 @@ runtime·funcline(Func *f, uintptr targetpc)
 	uintptr pc;
 	int32 line;
 	int32 pcquant;
-	
+
 	enum {
 		debug = 0
 	};
-	
+
 	switch(thechar) {
 	case '5':
 		pcquant = 4;
@@ -354,7 +498,7 @@ runtime·funcline(Func *f, uintptr targetpc)
 
 		if(debug && !runtime·panicking)
 			runtime·printf("pc<%p targetpc=%p line=%d\n", pc, targetpc, line);
-		
+
 		// If the pc has advanced too far or we're out of data,
 		// stop and the last known line number.
 		if(pc > targetpc || p >= ep)
@@ -382,7 +526,7 @@ runtime·funcline(Func *f, uintptr targetpc)
 }
 
 void
-runtime·funcline_go(Func *f, uintptr targetpc, String retfile, int32 retline)
+runtime·funcline_go(Func *f, uintptr targetpc, String retfile, intgo retline)
 {
 	retfile = f->src;
 	retline = runtime·funcline(f, targetpc);
@@ -406,20 +550,30 @@ buildfuncs(void)
 	// count funcs, fnames
 	nfunc = 0;
 	nfname = 0;
+	lastvalue = 0;
 	walksymtab(dofunc);
 
-	// initialize tables
-	func = runtime·mal((nfunc+1)*sizeof func[0]);
+	// Initialize tables.
+	// Can use FlagNoPointers - all pointers either point into sections of the executable
+	// or point into hugestring.
+	func = runtime·mallocgc((nfunc+1)*sizeof func[0], FlagNoPointers, 0, 1);
 	func[nfunc].entry = (uint64)etext;
-	fname = runtime·mal(nfname*sizeof fname[0]);
+	fname = runtime·mallocgc(nfname*sizeof fname[0], FlagNoPointers, 0, 1);
 	nfunc = 0;
+	lastvalue = 0;
 	walksymtab(dofunc);
 
 	// split pc/ln table by func
 	splitpcln();
 
 	// record src file and line info for each func
-	walksymtab(dosrcline);
+	walksymtab(dosrcline);  // pass 1: determine hugestring_len
+	hugestring.str = runtime·mallocgc(hugestring_len, FlagNoPointers, 0, 0);
+	hugestring.len = 0;
+	walksymtab(dosrcline);  // pass 2: fill and use hugestring
+
+	if(hugestring.len != hugestring_len)
+		runtime·throw("buildfunc: problem in initialization procedure");
 
 	m->nomemprof--;
 }
@@ -482,7 +636,7 @@ static bool
 hasprefix(String s, int8 *p)
 {
 	int32 i;
-	
+
 	for(i=0; i<s.len; i++) {
 		if(p[i] == 0)
 			return 1;
@@ -496,7 +650,7 @@ static bool
 contains(String s, int8 *p)
 {
 	int32 i;
-	
+
 	if(p[0] == 0)
 		return 1;
 	for(i=0; i<s.len; i++) {
@@ -509,11 +663,13 @@ contains(String s, int8 *p)
 }
 
 bool
-runtime·showframe(Func *f)
+runtime·showframe(Func *f, bool current)
 {
 	static int32 traceback = -1;
-	
+
+	if(current && m->throwing > 0)
+		return 1;
 	if(traceback < 0)
 		traceback = runtime·gotraceback();
-	return traceback > 1 || contains(f->name, ".") && !hasprefix(f->name, "runtime.");
+	return traceback > 1 || f != nil && contains(f->name, ".") && !hasprefix(f->name, "runtime.");
 }
diff --git a/src/pkg/runtime/sys_darwin_386.s b/src/pkg/runtime/sys_darwin_386.s
index 3cf3506..8a938f9 100644
--- a/src/pkg/runtime/sys_darwin_386.s
+++ b/src/pkg/runtime/sys_darwin_386.s
@@ -47,8 +47,7 @@ TEXT runtime·mmap(SB),7,$0
 TEXT runtime·madvise(SB),7,$0
 	MOVL	$75, AX
 	INT	$0x80
-	JAE	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	// ignore failure - maybe pages are locked
 	RET
 
 TEXT runtime·munmap(SB),7,$0
@@ -63,40 +62,133 @@ TEXT runtime·setitimer(SB),7,$0
 	INT	$0x80
 	RET
 
-// func now() (sec int64, nsec int32)
-TEXT time·now(SB), 7, $32
-	LEAL	12(SP), AX	// must be non-nil, unused
-	MOVL	AX, 4(SP)
-	MOVL	$0, 8(SP)	// time zone pointer
-	MOVL	$116, AX
-	INT	$0x80
-	MOVL	DX, BX
+// OS X comm page time offsets
+// http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h
+#define	cpu_capabilities	0x20
+#define	nt_tsc_base	0x50
+#define	nt_scale	0x58
+#define	nt_shift	0x5c
+#define	nt_ns_base	0x60
+#define	nt_generation	0x68
+#define	gtod_generation	0x6c
+#define	gtod_ns_base	0x70
+#define	gtod_sec_base	0x78
+
+// called from assembly
+// 64-bit unix nanoseconds returned in DX:AX.
+// I'd much rather write this in C but we need
+// assembly for the 96-bit multiply and RDTSC.
+TEXT runtime·now(SB),7,$40
+	MOVL	$0xffff0000, BP /* comm page base */
+	
+	// Test for slow CPU. If so, the math is completely
+	// different, and unimplemented here, so use the
+	// system call.
+	MOVL	cpu_capabilities(BP), AX
+	TESTL	$0x4000, AX
+	JNZ	systime
+
+	// Loop trying to take a consistent snapshot
+	// of the time parameters.
+timeloop:
+	MOVL	gtod_generation(BP), BX
+	TESTL	BX, BX
+	JZ	systime
+	MOVL	nt_generation(BP), CX
+	TESTL	CX, CX
+	JZ	timeloop
+	RDTSC
+	MOVL	nt_tsc_base(BP), SI
+	MOVL	(nt_tsc_base+4)(BP), DI
+	MOVL	SI, 0(SP)
+	MOVL	DI, 4(SP)
+	MOVL	nt_scale(BP), SI
+	MOVL	SI, 8(SP)
+	MOVL	nt_ns_base(BP), SI
+	MOVL	(nt_ns_base+4)(BP), DI
+	MOVL	SI, 12(SP)
+	MOVL	DI, 16(SP)
+	CMPL	nt_generation(BP), CX
+	JNE	timeloop
+	MOVL	gtod_ns_base(BP), SI
+	MOVL	(gtod_ns_base+4)(BP), DI
+	MOVL	SI, 20(SP)
+	MOVL	DI, 24(SP)
+	MOVL	gtod_sec_base(BP), SI
+	MOVL	(gtod_sec_base+4)(BP), DI
+	MOVL	SI, 28(SP)
+	MOVL	DI, 32(SP)
+	CMPL	gtod_generation(BP), BX
+	JNE	timeloop
+
+	// Gathered all the data we need. Compute time.
+	//	((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base - gtod_ns_base + gtod_sec_base*1e9
+	// The multiply and shift extracts the top 64 bits of the 96-bit product.
+	SUBL	0(SP), AX // DX:AX = (tsc - nt_tsc_base)
+	SBBL	4(SP), DX
+
+	// We have x = tsc - nt_tsc_base - DX:AX to be
+	// multiplied by y = nt_scale = 8(SP), keeping the top 64 bits of the 96-bit product.
+	// x*y = (x&0xffffffff)*y + (x&0xffffffff00000000)*y
+	// (x*y)>>32 = ((x&0xffffffff)*y)>>32 + (x>>32)*y
+	MOVL	DX, CX // SI = (x&0xffffffff)*y >> 32
+	MOVL	$0, DX
+	MULL	8(SP)
+	MOVL	DX, SI
 
-	// sec is in AX, usec in BX
-	MOVL	AX, sec+0(FP)
-	MOVL	$0, sec+4(FP)
-	IMULL	$1000, BX
-	MOVL	BX, nsec+8(FP)
+	MOVL	CX, AX // DX:AX = (x>>32)*y
+	MOVL	$0, DX
+	MULL	8(SP)
+
+	ADDL	SI, AX	// DX:AX += (x&0xffffffff)*y >> 32
+	ADCL	$0, DX
+	
+	// DX:AX is now ((tsc - nt_tsc_base) * nt_scale) >> 32.
+	ADDL	12(SP), AX	// DX:AX += nt_ns_base
+	ADCL	16(SP), DX
+	SUBL	20(SP), AX	// DX:AX -= gtod_ns_base
+	SBBL	24(SP), DX
+	MOVL	AX, SI	// DI:SI = DX:AX
+	MOVL	DX, DI
+	MOVL	28(SP), AX	// DX:AX = gtod_sec_base*1e9
+	MOVL	32(SP), DX
+	MOVL	$1000000000, CX
+	MULL	CX
+	ADDL	SI, AX	// DX:AX += DI:SI
+	ADCL	DI, DX
 	RET
 
-// int64 nanotime(void) so really
-// void nanotime(int64 *nsec)
-TEXT runtime·nanotime(SB), 7, $32
+systime:
+	// Fall back to system call (usually first call in this thread)
 	LEAL	12(SP), AX	// must be non-nil, unused
 	MOVL	AX, 4(SP)
 	MOVL	$0, 8(SP)	// time zone pointer
 	MOVL	$116, AX
 	INT	$0x80
-	MOVL	DX, BX
-
-	// sec is in AX, usec in BX
+	// sec is in AX, usec in DX
 	// convert to DX:AX nsec
+	MOVL	DX, BX
 	MOVL	$1000000000, CX
 	MULL	CX
 	IMULL	$1000, BX
 	ADDL	BX, AX
 	ADCL	$0, DX
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),7,$0
+	CALL	runtime·now(SB)
+	MOVL	$1000000000, CX
+	DIVL	CX
+	MOVL	AX, sec+0(FP)
+	MOVL	$0, sec+4(FP)
+	MOVL	DX, nsec+8(FP)
+	RET
 
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB),7,$0
+	CALL	runtime·now(SB)
 	MOVL	ret+0(FP), DI
 	MOVL	AX, 0(DI)
 	MOVL	DX, 4(DI)
@@ -120,8 +212,8 @@ TEXT runtime·sigaction(SB),7,$0
 // It is called with the following arguments on the stack:
 //	0(FP)	"return address" - ignored
 //	4(FP)	actual handler
-//	8(FP)	siginfo style - ignored
-//	12(FP)	signal number
+//	8(FP)	signal number
+//	12(FP)	siginfo style
 //	16(FP)	siginfo
 //	20(FP)	context
 TEXT runtime·sigtramp(SB),7,$40
@@ -130,8 +222,11 @@ TEXT runtime·sigtramp(SB),7,$40
 	// check that m exists
 	MOVL	m(CX), BP
 	CMPL	BP, $0
-	JNE	2(PC)
+	JNE	5(PC)
+	MOVL	sig+8(FP), BX
+	MOVL	BX, 0(SP)
 	CALL	runtime·badsignal(SB)
+	RET
 
 	// save g
 	MOVL	g(CX), DI
@@ -196,7 +291,7 @@ TEXT runtime·usleep(SB),7,$32
 	INT	$0x80
 	RET
 
-// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
+// void bsdthread_create(void *stk, M *mp, G *gp, void (*fn)(void))
 // System call args are: func arg stack pthread flags.
 TEXT runtime·bsdthread_create(SB),7,$32
 	MOVL	$360, AX
@@ -268,8 +363,10 @@ TEXT runtime·bsdthread_register(SB),7,$40
 	MOVL	$0, 20(SP)	// targetconc_ptr
 	MOVL	$0, 24(SP)	// dispatchqueue_offset
 	INT	$0x80
-	JAE	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	JAE	3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
 	RET
 
 // Invoke Mach system call.
diff --git a/src/pkg/runtime/sys_darwin_amd64.s b/src/pkg/runtime/sys_darwin_amd64.s
index 90571ba..4e43a76 100644
--- a/src/pkg/runtime/sys_darwin_amd64.s
+++ b/src/pkg/runtime/sys_darwin_amd64.s
@@ -61,30 +61,63 @@ TEXT runtime·madvise(SB), 7, $0
 	MOVL	24(SP), DX		// arg 3 advice
 	MOVL	$(0x2000000+75), AX	// syscall entry madvise
 	SYSCALL
-	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	// ignore failure - maybe pages are locked
 	RET
 
-// func now() (sec int64, nsec int32)
-TEXT time·now(SB), 7, $32
-	MOVQ	SP, DI	// must be non-nil, unused
-	MOVQ	$0, SI
-	MOVL	$(0x2000000+116), AX
-	SYSCALL
-
-	// sec is in AX, usec in DX
-	MOVQ	AX, sec+0(FP)
-	IMULQ	$1000, DX
-	MOVL	DX, nsec+8(FP)
-	RET
+// OS X comm page time offsets
+// http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h
+#define	nt_tsc_base	0x50
+#define	nt_scale	0x58
+#define	nt_shift	0x5c
+#define	nt_ns_base	0x60
+#define	nt_generation	0x68
+#define	gtod_generation	0x6c
+#define	gtod_ns_base	0x70
+#define	gtod_sec_base	0x78
 
 // int64 nanotime(void)
 TEXT runtime·nanotime(SB), 7, $32
+	MOVQ	$0x7fffffe00000, BP	/* comm page base */
+	// Loop trying to take a consistent snapshot
+	// of the time parameters.
+timeloop:
+	MOVL	gtod_generation(BP), R8
+	TESTL	R8, R8
+	JZ	systime
+	MOVL	nt_generation(BP), R9
+	TESTL	R9, R9
+	JZ	timeloop
+	RDTSC
+	MOVQ	nt_tsc_base(BP), R10
+	MOVL	nt_scale(BP), R11
+	MOVQ	nt_ns_base(BP), R12
+	CMPL	nt_generation(BP), R9
+	JNE	timeloop
+	MOVQ	gtod_ns_base(BP), R13
+	MOVQ	gtod_sec_base(BP), R14
+	CMPL	gtod_generation(BP), R8
+	JNE	timeloop
+
+	// Gathered all the data we need. Compute time.
+	//	((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base - gtod_ns_base + gtod_sec_base*1e9
+	// The multiply and shift extracts the top 64 bits of the 96-bit product.
+	SHLQ	$32, DX
+	ADDQ	DX, AX
+	SUBQ	R10, AX
+	MULQ	R11
+	SHRQ	$32, AX:DX
+	ADDQ	R12, AX
+	SUBQ	R13, AX
+	IMULQ	$1000000000, R14
+	ADDQ	R14, AX
+	RET
+
+systime:
+	// Fall back to system call (usually first call in this thread).
 	MOVQ	SP, DI	// must be non-nil, unused
 	MOVQ	$0, SI
 	MOVL	$(0x2000000+116), AX
 	SYSCALL
-
 	// sec is in AX, usec in DX
 	// return nsec in AX
 	IMULQ	$1000000000, AX
@@ -92,6 +125,25 @@ TEXT runtime·nanotime(SB), 7, $32
 	ADDQ	DX, AX
 	RET
 
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),7,$0
+	CALL	runtime·nanotime(SB)
+
+	// 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·sigprocmask(SB),7,$0
 	MOVL	8(SP), DI
 	MOVQ	16(SP), SI
@@ -120,8 +172,10 @@ TEXT runtime·sigtramp(SB),7,$64
 	// check that m exists
 	MOVQ	m(BX), BP
 	CMPQ	BP, $0
-	JNE	2(PC)
+	JNE	4(PC)
+	MOVL	DX, 0(SP)
 	CALL	runtime·badsignal(SB)
+	RET
 
 	// save g
 	MOVQ	g(BX), R10
@@ -199,7 +253,7 @@ TEXT runtime·usleep(SB),7,$16
 	SYSCALL
 	RET
 
-// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
+// void bsdthread_create(void *stk, M *mp, G *gp, void (*fn)(void))
 TEXT runtime·bsdthread_create(SB),7,$0
 	// Set up arguments to bsdthread_create system call.
 	// The ones in quotes pass through to the thread callback
@@ -265,8 +319,10 @@ TEXT runtime·bsdthread_register(SB),7,$0
 	MOVQ	$0, R9	// dispatchqueue_offset
 	MOVQ	$(0x2000000+366), AX	// bsdthread_register
 	SYSCALL
-	JCC 2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	JCC 3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
 	RET
 
 // Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
diff --git a/src/pkg/runtime/sys_freebsd_386.s b/src/pkg/runtime/sys_freebsd_386.s
index a72d897..d537026 100644
--- a/src/pkg/runtime/sys_freebsd_386.s
+++ b/src/pkg/runtime/sys_freebsd_386.s
@@ -39,6 +39,7 @@ TEXT runtime·thr_start(SB),7,$0
 	MOVL	AX, m(CX)
 	CALL	runtime·stackcheck(SB)		// smashes AX
 	CALL	runtime·mstart(SB)
+
 	MOVL	0, AX			// crash (not reached)
 
 // Exit the entire program (like C exit)
@@ -89,7 +90,7 @@ TEXT runtime·mmap(SB),7,$32
 	MOVSL
 	MOVSL
 	MOVSL
-	MOVL	$0, AX	// top 64 bits of file offset
+	MOVL	$0, AX	// top 32 bits of file offset
 	STOSL
 	MOVL	$477, AX
 	INT	$0x80
@@ -102,6 +103,12 @@ TEXT runtime·munmap(SB),7,$-4
 	MOVL	$0xf1, 0xf1  // crash
 	RET
 
+TEXT runtime·madvise(SB),7,$-4
+	MOVL	$75, AX	// madvise
+	INT	$0x80
+	// ignore failure - maybe pages are locked
+	RET
+
 TEXT runtime·setitimer(SB), 7, $-4
 	MOVL	$83, AX
 	INT	$0x80
@@ -109,40 +116,38 @@ TEXT runtime·setitimer(SB), 7, $-4
 
 // func now() (sec int64, nsec int32)
 TEXT time·now(SB), 7, $32
-	MOVL	$116, AX
+	MOVL	$232, AX
 	LEAL	12(SP), BX
-	MOVL	BX, 4(SP)
-	MOVL	$0, 8(SP)
+	MOVL	$0, 4(SP)
+	MOVL	BX, 8(SP)
 	INT	$0x80
 	MOVL	12(SP), AX	// sec
-	MOVL	16(SP), BX	// usec
+	MOVL	16(SP), BX	// nsec
 
-	// sec is in AX, usec in BX
+	// sec is in AX, nsec in BX
 	MOVL	AX, sec+0(FP)
 	MOVL	$0, sec+4(FP)
-	IMULL	$1000, BX
 	MOVL	BX, nsec+8(FP)
 	RET
 
 // int64 nanotime(void) so really
 // void nanotime(int64 *nsec)
 TEXT runtime·nanotime(SB), 7, $32
-	MOVL	$116, AX
+	MOVL	$232, AX
 	LEAL	12(SP), BX
-	MOVL	BX, 4(SP)
-	MOVL	$0, 8(SP)
+	MOVL	$0, 4(SP)
+	MOVL	BX, 8(SP)
 	INT	$0x80
 	MOVL	12(SP), AX	// sec
-	MOVL	16(SP), BX	// usec
+	MOVL	16(SP), BX	// nsec
 
-	// sec is in AX, usec in BX
+	// sec is in AX, nsec in BX
 	// convert to DX:AX nsec
 	MOVL	$1000000000, CX
 	MULL	CX
-	IMULL	$1000, BX
 	ADDL	BX, AX
 	ADCL	$0, DX
-	
+
 	MOVL	ret+0(FP), DI
 	MOVL	AX, 0(DI)
 	MOVL	DX, 4(DI)
@@ -162,8 +167,11 @@ TEXT runtime·sigtramp(SB),7,$44
 	// check that m exists
 	MOVL	m(CX), BX
 	CMPL	BX, $0
-	JNE	2(PC)
+	JNE	5(PC)
+	MOVL	signo+0(FP), BX
+	MOVL	BX, 0(SP)
 	CALL	runtime·badsignal(SB)
+	RET
 
 	// save g
 	MOVL	g(CX), DI
diff --git a/src/pkg/runtime/sys_freebsd_amd64.s b/src/pkg/runtime/sys_freebsd_amd64.s
index 36e034a..40c6237 100644
--- a/src/pkg/runtime/sys_freebsd_amd64.s
+++ b/src/pkg/runtime/sys_freebsd_amd64.s
@@ -38,8 +38,9 @@ TEXT runtime·thr_start(SB),7,$0
 	MOVQ	m_g0(R13), DI
 	MOVQ	DI, g(CX)
 
-	CALL runtime·stackcheck(SB)
-	CALL runtime·mstart(SB)
+	CALL	runtime·stackcheck(SB)
+	CALL	runtime·mstart(SB)
+
 	MOVQ 0, AX			// crash (not reached)
 
 // Exit the entire program (like C exit)
@@ -94,31 +95,29 @@ TEXT runtime·setitimer(SB), 7, $-8
 
 // func now() (sec int64, nsec int32)
 TEXT time·now(SB), 7, $32
-	MOVL	$116, AX
-	LEAQ	8(SP), DI
-	MOVQ	$0, SI
+	MOVL	$232, AX
+	MOVQ	$0, DI
+	LEAQ	8(SP), SI
 	SYSCALL
 	MOVQ	8(SP), AX	// sec
-	MOVL	16(SP), DX	// usec
+	MOVQ	16(SP), DX	// nsec
 
-	// sec is in AX, usec in DX
+	// sec is in AX, nsec in DX
 	MOVQ	AX, sec+0(FP)
-	IMULQ	$1000, DX
 	MOVL	DX, nsec+8(FP)
 	RET
 
 TEXT runtime·nanotime(SB), 7, $32
-	MOVL	$116, AX
-	LEAQ	8(SP), DI
-	MOVQ	$0, SI
+	MOVL	$232, AX
+	MOVQ	$0, DI
+	LEAQ	8(SP), SI
 	SYSCALL
 	MOVQ	8(SP), AX	// sec
-	MOVL	16(SP), DX	// usec
+	MOVQ	16(SP), DX	// nsec
 
-	// sec is in AX, usec in DX
+	// sec is in AX, nsec in DX
 	// return nsec in AX
 	IMULQ	$1000000000, AX
-	IMULQ	$1000, DX
 	ADDQ	DX, AX
 	RET
 
@@ -138,8 +137,10 @@ TEXT runtime·sigtramp(SB),7,$64
 	// check that m exists
 	MOVQ	m(BX), BP
 	CMPQ	BP, $0
-	JNE	2(PC)
+	JNE	4(PC)
+	MOVQ	DI, 0(SP)
 	CALL	runtime·badsignal(SB)
+	RET
 
 	// save g
 	MOVQ	g(BX), R10
@@ -182,6 +183,15 @@ TEXT runtime·munmap(SB),7,$0
 	MOVL	$0xf1, 0xf1  // crash
 	RET
 
+TEXT runtime·madvise(SB),7,$0
+	MOVQ	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVQ	24(SP), DX
+	MOVQ	$75, AX	// madvise
+	SYSCALL
+	// ignore failure - maybe pages are locked
+	RET
+	
 TEXT runtime·sigaltstack(SB),7,$-8
 	MOVQ	new+8(SP), DI
 	MOVQ	old+16(SP), SI
diff --git a/src/pkg/runtime/sys_freebsd_arm.s b/src/pkg/runtime/sys_freebsd_arm.s
new file mode 100644
index 0000000..77050e8
--- /dev/null
+++ b/src/pkg/runtime/sys_freebsd_arm.s
@@ -0,0 +1,260 @@
+// 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.
+//
+// System calls and other sys.stuff for ARM, FreeBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+	
+TEXT runtime·sys_umtx_op(SB),7,$0
+	MOVW 0(FP), R0
+	MOVW 4(FP), R1
+	MOVW 8(FP), R2
+	MOVW 12(FP), R3
+	ADD $20, R13 // arg 5 is passed on stack
+	SWI $454
+	SUB $20, R13
+	// BCS error
+	RET
+
+TEXT runtime·thr_new(SB),7,$0
+	MOVW 0(FP), R0
+	MOVW 4(FP), R1
+	SWI $455
+	RET
+
+TEXT runtime·thr_start(SB),7,$0
+	MOVW R0, R9 // m
+
+	// TODO(minux): set up TLS?
+
+	// set up g
+	MOVW m_g0(R9), R10
+	BL runtime·emptyfunc(SB) // fault if stack check is wrong
+	BL runtime·mstart(SB)
+
+	MOVW $2, R9  // crash (not reached)
+	MOVW R9, (R9)
+	RET
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$-8
+	MOVW 0(FP), R0	// arg 1 exit status
+	SWI $1
+	MOVW.CS $0, R9 // crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·exit1(SB),7,$-8
+	MOVW 0(FP), R0	// arg 1 exit status
+	SWI $431
+	MOVW.CS $0, R9 // crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·write(SB),7,$-8
+	MOVW 0(FP), R0	// arg 1 fd
+	MOVW 4(FP), R1	// arg 2 buf
+	MOVW 8(FP), R2	// arg 3 count
+	SWI $4
+	RET
+
+TEXT runtime·getrlimit(SB),7,$-8
+	MOVW 0(FP), R0
+	MOVW 4(FP), R1
+	MOVW 8(FP), R2
+	SWI $194
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$8
+	// thr_self(&4(R13))
+	MOVW $4(R13), R0 // arg 1 &4(R13)
+	SWI $432
+	// thr_kill(self, SIGPIPE)
+	MOVW 4(R13), R0	// arg 1 id
+	MOVW $13, R1	// arg 2 SIGPIPE
+	SWI $433
+	RET
+
+TEXT runtime·setitimer(SB), 7, $-8
+	MOVW 0(FP), R0
+	MOVW 4(FP), R1
+	MOVW 8(FP), R2
+	SWI $83
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	MOVW $0, R0 // CLOCK_REALTIME
+	MOVW $8(R13), R1
+	SWI $232 // clock_gettime
+
+	MOVW 8(R13), R0 // sec.low
+	MOVW 12(R13), R1 // sec.high
+	MOVW 16(R13), R2 // nsec
+
+	MOVW R0, 0(FP)
+	MOVW R1, 4(FP)
+	MOVW R2, 8(FP)
+	RET
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB), 7, $32
+	MOVW $0, R0 // CLOCK_REALTIME
+	MOVW $8(R13), R1
+	SWI $232 // clock_gettime
+
+	MOVW 8(R13), R0 // sec.low
+	MOVW 12(R13), R4 // sec.high
+	MOVW 16(R13), R2 // nsec
+
+	MOVW $1000000000, R3
+	MULLU R0, R3, (R1, R0)
+	MUL R3, R4
+	ADD.S R2, R0
+	ADC R4, R1
+
+	MOVW 0(FP), R3
+	MOVW R0, 0(R3)
+	MOVW R1, 4(R3)
+	RET
+
+TEXT runtime·sigaction(SB),7,$-8
+	MOVW 0(FP), R0		// arg 1 sig
+	MOVW 4(FP), R1		// arg 2 act
+	MOVW 8(FP), R2		// arg 3 oact
+	SWI $416
+	MOVW.CS $0, R9 // crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$24
+	// this might be called in external code context,
+	// where g and m are not set.
+	// first save R0, because _cgo_load_gm will clobber it
+	// TODO(adonovan): call runtime·badsignal if m=0, like other platforms?
+	MOVW	R0, 4(R13) // signum
+	MOVW	_cgo_load_gm(SB), R0
+	CMP 	$0, R0
+	BL.NE	(R0)
+
+	// save g
+	MOVW R10, R4
+	MOVW R10, 20(R13)
+
+	// g = m->signal
+	MOVW m_gsignal(R9), R10
+
+	// R0 is already saved
+	MOVW R1, 8(R13) // info
+	MOVW R2, 12(R13) // context
+	MOVW R4, 16(R13) // oldg
+
+	BL runtime·sighandler(SB)
+
+	// restore g
+	MOVW 20(R13), R10
+	RET
+
+TEXT runtime·mmap(SB),7,$12
+	MOVW 0(FP), R0		// arg 1 addr
+	MOVW 4(FP), R1		// arg 2 len
+	MOVW 8(FP), R2		// arg 3 prot
+	MOVW 12(FP), R3		// arg 4 flags
+	// arg 5 (fid) and arg6 (offset_lo, offset_hi) are passed on stack
+	// note the C runtime only passes the 32-bit offset_lo to us
+	MOVW 16(FP), R4		// arg 5
+	MOVW R4, 4(R13)
+	MOVW 20(FP), R5		// arg 6 lower 32-bit
+	MOVW R5, 8(R13)
+	MOVW $0, R6 // higher 32-bit for arg 6
+	MOVW R6, 12(R13)
+	ADD $4, R13 // pass arg 5 and arg 6 on stack
+	SWI $477
+	SUB $4, R13
+	RET
+
+TEXT runtime·munmap(SB),7,$0
+	MOVW 0(FP), R0		// arg 1 addr
+	MOVW 4(FP), R1		// arg 2 len
+	SWI $73
+	MOVW.CS $0, R9 // crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·madvise(SB),7,$0
+	MOVW 0(FP), R0		// arg 1 addr
+	MOVW 4(FP), R1		// arg 2 len
+	MOVW 8(FP), R2		// arg 3 flags
+	SWI $75
+	// ignore failure - maybe pages are locked
+	RET
+	
+TEXT runtime·sigaltstack(SB),7,$-8
+	MOVW new+0(FP), R0
+	MOVW old+4(FP), R1
+	SWI $53
+	MOVW.CS $0, R9 // crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·usleep(SB),7,$16
+	MOVW usec+0(FP), R0
+	MOVW R0, R2
+	MOVW $1000000, R1
+	DIV R1, R0
+	// 0(R13) is the saved LR, don't use it
+	MOVW R0, 4(R13) // tv_sec.low
+	MOVW $0, R0
+	MOVW R0, 8(R13) // tv_sec.high
+	MOD R1, R2
+	MOVW $1000, R1
+	MUL R1, R2
+	MOVW R2, 12(R13) // tv_nsec
+
+	MOVW $4(R13), R0 // arg 1 - rqtp
+	MOVW $0, R1      // arg 2 - rmtp
+	SWI $240 // sys_nanosleep
+	RET
+
+TEXT runtime·sysctl(SB),7,$0
+	MOVW 0(FP), R0	// arg 1 - name
+	MOVW 4(FP), R1	// arg 2 - namelen
+	MOVW 8(FP), R2	// arg 3 - oldp
+	MOVW 12(FP), R3	// arg 4 - oldlenp
+	// arg 5 (newp) and arg 6 (newlen) are passed on stack
+	ADD $20, R13
+	SWI $202 // sys___sysctl
+	SUB.CS $0, R0, R0
+	SUB $20, R13
+	RET
+
+TEXT runtime·osyield(SB),7,$-4
+	SWI $331	// sys_sched_yield
+	RET
+
+TEXT runtime·sigprocmask(SB),7,$0
+	MOVW $3, R0	// arg 1 - how (SIG_SETMASK)
+	MOVW 0(FP), R1	// arg 2 - set
+	MOVW 4(FP), R2	// arg 3 - oset
+	SWI $340	// sys_sigprocmask
+	MOVW.CS $0, R9 // crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·casp(SB),7,$0
+	B	runtime·cas(SB)
+
+// TODO(minux): this is only valid for ARMv6+
+// bool armcas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	}else
+//		return 0;
+TEXT runtime·cas(SB),7,$0
+	B runtime·armcas(SB)
diff --git a/src/pkg/runtime/sys_linux_386.s b/src/pkg/runtime/sys_linux_386.s
index 602d9dd..f27fd47 100644
--- a/src/pkg/runtime/sys_linux_386.s
+++ b/src/pkg/runtime/sys_linux_386.s
@@ -104,40 +104,38 @@ TEXT runtime·mincore(SB),7,$0-24
 
 // func now() (sec int64, nsec int32)
 TEXT time·now(SB), 7, $32
-	MOVL	$78, AX			// syscall - gettimeofday
-	LEAL	8(SP), BX
-	MOVL	$0, CX
+	MOVL	$265, AX			// syscall - clock_gettime
+	MOVL	$0, BX
+	LEAL	8(SP), CX
 	MOVL	$0, DX
 	CALL	*runtime·_vdso(SB)
 	MOVL	8(SP), AX	// sec
-	MOVL	12(SP), BX	// usec
+	MOVL	12(SP), BX	// nsec
 
-	// sec is in AX, usec in BX
+	// sec is in AX, nsec in BX
 	MOVL	AX, sec+0(FP)
 	MOVL	$0, sec+4(FP)
-	IMULL	$1000, BX
 	MOVL	BX, nsec+8(FP)
 	RET
 
 // int64 nanotime(void) so really
 // void nanotime(int64 *nsec)
 TEXT runtime·nanotime(SB), 7, $32
-	MOVL	$78, AX			// syscall - gettimeofday
-	LEAL	8(SP), BX
-	MOVL	$0, CX
+	MOVL	$265, AX			// syscall - clock_gettime
+	MOVL	$0, BX
+	LEAL	8(SP), CX
 	MOVL	$0, DX
 	CALL	*runtime·_vdso(SB)
 	MOVL	8(SP), AX	// sec
-	MOVL	12(SP), BX	// usec
+	MOVL	12(SP), BX	// nsec
 
-	// sec is in AX, usec in BX
+	// sec is in AX, nsec in BX
 	// convert to DX:AX nsec
 	MOVL	$1000000000, CX
 	MULL	CX
-	IMULL	$1000, BX
 	ADDL	BX, AX
 	ADCL	$0, DX
-	
+
 	MOVL	ret+0(FP), DI
 	MOVL	AX, 0(DI)
 	MOVL	DX, 4(DI)
@@ -170,8 +168,11 @@ TEXT runtime·sigtramp(SB),7,$44
 	// check that m exists
 	MOVL	m(CX), BX
 	CMPL	BX, $0
-	JNE	2(PC)
+	JNE	5(PC)
+	MOVL	sig+0(FP), BX
+	MOVL	BX, 0(SP)
 	CALL	runtime·badsignal(SB)
+	RET
 
 	// save g
 	MOVL	g(CX), DI
@@ -240,9 +241,7 @@ TEXT runtime·madvise(SB),7,$0
 	MOVL	8(SP), CX
 	MOVL	12(SP), DX
 	CALL	*runtime·_vdso(SB)
-	CMPL	AX, $0xfffff001
-	JLS	2(PC)
-	INT $3
+	// ignore failure - maybe pages are locked
 	RET
 
 // int32 futex(int32 *uaddr, int32 op, int32 val,
@@ -258,7 +257,7 @@ TEXT runtime·futex(SB),7,$0
 	CALL	*runtime·_vdso(SB)
 	RET
 
-// int32 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+// int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
 TEXT runtime·clone(SB),7,$0
 	MOVL	$120, AX	// clone
 	MOVL	flags+4(SP), BX
@@ -266,7 +265,7 @@ TEXT runtime·clone(SB),7,$0
 	MOVL	$0, DX	// parent tid ptr
 	MOVL	$0, DI	// child tid ptr
 
-	// Copy m, g, fn off parent stack for use by child.
+	// Copy mp, gp, fn off parent stack for use by child.
 	SUBL	$16, CX
 	MOVL	mm+12(SP), SI
 	MOVL	SI, 0(CX)
@@ -423,3 +422,11 @@ TEXT runtime·osyield(SB),7,$0
 	MOVL	$158, AX
 	CALL	*runtime·_vdso(SB)
 	RET
+
+TEXT runtime·sched_getaffinity(SB),7,$0
+	MOVL	$242, AX		// syscall - sched_getaffinity
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	MOVL	12(SP), DX
+	CALL	*runtime·_vdso(SB)
+	RET
diff --git a/src/pkg/runtime/sys_linux_amd64.s b/src/pkg/runtime/sys_linux_amd64.s
index 657ab7e..e459437 100644
--- a/src/pkg/runtime/sys_linux_amd64.s
+++ b/src/pkg/runtime/sys_linux_amd64.s
@@ -101,32 +101,61 @@ TEXT runtime·mincore(SB),7,$0-24
 	RET
 
 // func now() (sec int64, nsec int32)
-TEXT time·now(SB), 7, $32
-	LEAQ	8(SP), DI
-	MOVQ	$0, SI
-	MOVQ	$0xffffffffff600000, AX
+TEXT time·now(SB),7,$16
+	// Be careful. We're calling a function with gcc calling convention here.
+	// We're guaranteed 128 bytes on entry, and we've taken 16, and the
+	// call uses another 8.
+	// That leaves 104 for the gettime code to use. Hope that's enough!
+	MOVQ	runtime·__vdso_clock_gettime_sym(SB), AX
+	CMPQ	AX, $0
+	JEQ	fallback_gtod
+	MOVL	$0, DI // CLOCK_REALTIME
+	LEAQ	0(SP), SI
 	CALL	AX
-	MOVQ	8(SP), AX	// sec
-	MOVL	16(SP), DX	// usec
-
-	// sec is in AX, usec in DX
+	MOVQ	0(SP), AX	// sec
+	MOVQ	8(SP), DX	// nsec
 	MOVQ	AX, sec+0(FP)
-	IMULQ	$1000, DX
 	MOVL	DX, nsec+8(FP)
 	RET
-
-TEXT runtime·nanotime(SB), 7, $32
-	LEAQ	8(SP), DI
+fallback_gtod:
+	LEAQ	0(SP), DI
 	MOVQ	$0, SI
-	MOVQ	$0xffffffffff600000, AX
+	MOVQ	runtime·__vdso_gettimeofday_sym(SB), AX
 	CALL	AX
-	MOVQ	8(SP), AX	// sec
-	MOVL	16(SP), DX	// usec
+	MOVQ	0(SP), AX	// sec
+	MOVL	8(SP), DX	// usec
+	IMULQ	$1000, DX
+	MOVQ	AX, sec+0(FP)
+	MOVL	DX, nsec+8(FP)
+	RET
 
-	// sec is in AX, usec in DX
+TEXT runtime·nanotime(SB),7,$16
+	// Duplicate time.now here to avoid using up precious stack space.
+	// See comment above in time.now.
+	MOVQ	runtime·__vdso_clock_gettime_sym(SB), AX
+	CMPQ	AX, $0
+	JEQ	fallback_gtod_nt
+	MOVL	$0, DI // CLOCK_REALTIME
+	LEAQ	0(SP), SI
+	CALL	AX
+	MOVQ	0(SP), AX	// sec
+	MOVQ	8(SP), DX	// nsec
+	// sec is in AX, nsec in DX
 	// return nsec in AX
 	IMULQ	$1000000000, AX
+	ADDQ	DX, AX
+	RET
+fallback_gtod_nt:
+	LEAQ	0(SP), DI
+	MOVQ	$0, SI
+	MOVQ	runtime·__vdso_gettimeofday_sym(SB), AX
+	CALL	AX
+	MOVQ	0(SP), AX	// sec
+	MOVL	8(SP), DX	// usec
 	IMULQ	$1000, DX
+	// sec is in AX, nsec in DX
+	// return nsec in AX
+	IMULQ	$1000000000, AX
 	ADDQ	DX, AX
 	RET
 
@@ -157,8 +186,10 @@ TEXT runtime·sigtramp(SB),7,$64
 	// check that m exists
 	MOVQ	m(BX), BP
 	CMPQ	BP, $0
-	JNE	2(PC)
+	JNE	4(PC)
+	MOVQ	DI, 0(SP)
 	CALL	runtime·badsignal(SB)
+	RET
 
 	// save g
 	MOVQ	g(BX), R10
@@ -219,9 +250,7 @@ TEXT runtime·madvise(SB),7,$0
 	MOVQ	24(SP), DX
 	MOVQ	$28, AX	// madvise
 	SYSCALL
-	CMPQ	AX, $0xfffffffffffff001
-	JLS	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	// ignore failure - maybe pages are locked
 	RET
 
 // int64 futex(int32 *uaddr, int32 op, int32 val,
@@ -237,12 +266,12 @@ TEXT runtime·futex(SB),7,$0
 	SYSCALL
 	RET
 
-// int64 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+// int64 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
 TEXT runtime·clone(SB),7,$0
 	MOVL	flags+8(SP), DI
 	MOVQ	stack+16(SP), SI
 
-	// Copy m, g, fn off parent stack for use by child.
+	// Copy mp, gp, fn off parent stack for use by child.
 	// Careful: Linux system call clobbers CX and R11.
 	MOVQ	mm+24(SP), R8
 	MOVQ	gg+32(SP), R9
@@ -310,3 +339,11 @@ TEXT runtime·osyield(SB),7,$0
 	MOVL	$24, AX
 	SYSCALL
 	RET
+
+TEXT runtime·sched_getaffinity(SB),7,$0
+	MOVQ	8(SP), DI
+	MOVL	16(SP), SI
+	MOVQ	24(SP), DX
+	MOVL	$204, AX			// syscall entry
+	SYSCALL
+	RET
diff --git a/src/pkg/runtime/sys_linux_arm.s b/src/pkg/runtime/sys_linux_arm.s
index 03e173d..8bae293 100644
--- a/src/pkg/runtime/sys_linux_arm.s
+++ b/src/pkg/runtime/sys_linux_arm.s
@@ -34,9 +34,10 @@
 #define SYS_sched_yield (SYS_BASE + 158)
 #define SYS_select (SYS_BASE + 142) // newselect
 #define SYS_ugetrlimit (SYS_BASE + 191)
+#define SYS_sched_getaffinity (SYS_BASE + 242)
+#define SYS_clock_gettime (SYS_BASE + 263)
 
 #define ARM_BASE (SYS_BASE + 0x0f0000)
-#define SYS_ARM_cacheflush (ARM_BASE + 2)
 
 TEXT runtime·open(SB),7,$0
 	MOVW	0(FP), R0
@@ -131,10 +132,7 @@ TEXT runtime·madvise(SB),7,$0
 	MOVW	8(FP), R2
 	MOVW	$SYS_madvise, R7
 	SWI	$0
-	MOVW	$0xfffff001, R6
-	CMP 	R6, R0
-	MOVW.HI	$0, R9  // crash on syscall failure
-	MOVW.HI	R9, (R9)
+	// ignore failure - maybe pages are locked
 	RET
 
 TEXT runtime·setitimer(SB),7,$0
@@ -154,41 +152,37 @@ TEXT runtime·mincore(SB),7,$0
 	RET
 
 TEXT time·now(SB), 7, $32
-	MOVW	$8(R13), R0  // timeval
-	MOVW	$0, R1  // zone
-	MOVW	$SYS_gettimeofday, R7
+	MOVW	$0, R0  // CLOCK_REALTIME
+	MOVW	$8(R13), R1  // timespec
+	MOVW	$SYS_clock_gettime, R7
 	SWI	$0
 	
 	MOVW	8(R13), R0  // sec
-	MOVW	12(R13), R2  // usec
+	MOVW	12(R13), R2  // nsec
 	
 	MOVW	R0, 0(FP)
 	MOVW	$0, R1
 	MOVW	R1, 4(FP)
-	MOVW	$1000, R3
-	MUL	R3, R2
 	MOVW	R2, 8(FP)
 	RET	
 
 // int64 nanotime(void) so really
 // void nanotime(int64 *nsec)
 TEXT runtime·nanotime(SB),7,$32
-	MOVW	$8(R13), R0  // timeval
-	MOVW	$0, R1  // zone
-	MOVW	$SYS_gettimeofday, R7
+	MOVW	$0, R0  // CLOCK_REALTIME
+	MOVW	$8(R13), R1  // timespec
+	MOVW	$SYS_clock_gettime, R7
 	SWI	$0
 	
 	MOVW	8(R13), R0  // sec
-	MOVW	12(R13), R2  // usec
+	MOVW	12(R13), R2  // nsec
 	
 	MOVW	$1000000000, R3
 	MULLU	R0, R3, (R1, R0)
-	MOVW	$1000, R3
 	MOVW	$0, R4
-	MUL	R3, R2
 	ADD.S	R2, R0
 	ADC	R4, R1
-	
+
 	MOVW	0(FP), R3
 	MOVW	R0, 0(R3)
 	MOVW	R1, 4(R3)
@@ -208,7 +202,7 @@ TEXT runtime·futex(SB),7,$0
 	RET
 
 
-// int32 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+// int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
 TEXT runtime·clone(SB),7,$0
 	MOVW	flags+0(FP), R0
 	MOVW	stack+4(FP), R1
@@ -217,7 +211,7 @@ TEXT runtime·clone(SB),7,$0
 	MOVW	$0, R4	// child tid ptr
 	MOVW	$0, R5
 
-	// Copy m, g, fn off parent stack for use by child.
+	// Copy mp, gp, fn off parent stack for use by child.
 	// TODO(kaib): figure out which registers are clobbered by clone and avoid stack copying
 	MOVW	$-16(R1), R1
 	MOVW	mm+8(FP), R6
@@ -272,15 +266,6 @@ TEXT runtime·clone(SB),7,$0
 	MOVW	$1005, R1
 	MOVW	R0, (R1)
 
-
-TEXT runtime·cacheflush(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	$0, R2
-	MOVW	$SYS_ARM_cacheflush, R7
-	SWI	$0
-	RET
-
 TEXT runtime·sigaltstack(SB),7,$0
 	MOVW	0(FP), R0
 	MOVW	4(FP), R1
@@ -293,6 +278,15 @@ TEXT runtime·sigaltstack(SB),7,$0
 	RET
 
 TEXT runtime·sigtramp(SB),7,$24
+	// this might be called in external code context,
+	// where g and m are not set.
+	// first save R0, because _cgo_load_gm will clobber it
+	// TODO(adonovan): call runtime·badsignal if m=0, like other platforms?
+	MOVW	R0, 4(R13)
+	MOVW	_cgo_load_gm(SB), R0
+	CMP 	$0, R0
+	BL.NE	(R0)
+
 	// save g
 	MOVW	g, R3
 	MOVW	g, 20(R13)
@@ -301,7 +295,7 @@ TEXT runtime·sigtramp(SB),7,$24
 	MOVW	m_gsignal(m), g
 
 	// copy arguments for call to sighandler
-	MOVW	R0, 4(R13)
+	// R0 is already saved above
 	MOVW	R1, 8(R13)
 	MOVW	R2, 12(R13)
 	MOVW	R3, 16(R13)
@@ -385,3 +379,11 @@ TEXT runtime·osyield(SB),7,$0
 	MOVW	$SYS_sched_yield, R7
 	SWI	$0
 	RET
+
+TEXT runtime·sched_getaffinity(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	8(FP), R2
+	MOVW	$SYS_sched_getaffinity, R7
+	SWI	$0
+	RET
diff --git a/src/pkg/runtime/sys_netbsd_386.s b/src/pkg/runtime/sys_netbsd_386.s
index 11f8c7a..3d3d312 100644
--- a/src/pkg/runtime/sys_netbsd_386.s
+++ b/src/pkg/runtime/sys_netbsd_386.s
@@ -12,14 +12,14 @@
 TEXT runtime·exit(SB),7,$-4
 	MOVL	$1, AX
 	INT	$0x80
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·exit1(SB),7,$-4
-	MOVL	$302, AX		// sys_threxit
+	MOVL	$310, AX		// sys__lwp_exit
 	INT	$0x80
 	JAE	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·write(SB),7,$-4
@@ -27,31 +27,32 @@ TEXT runtime·write(SB),7,$-4
 	INT	$0x80
 	RET
 
-TEXT runtime·usleep(SB),7,$20
+TEXT runtime·usleep(SB),7,$24
 	MOVL	$0, DX
 	MOVL	usec+0(FP), AX
 	MOVL	$1000000, CX
 	DIVL	CX
-	MOVL	AX, 12(SP)		// tv_sec
+	MOVL	AX, 12(SP)		// tv_sec - l32
+	MOVL	$0, 16(SP)		// tv_sec - h32
 	MOVL	$1000, AX
 	MULL	DX
-	MOVL	AX, 16(SP)		// tv_nsec
+	MOVL	AX, 20(SP)		// tv_nsec
 
 	MOVL	$0, 0(SP)
 	LEAL	12(SP), AX
 	MOVL	AX, 4(SP)		// arg 1 - rqtp
 	MOVL	$0, 8(SP)		// arg 2 - rmtp
-	MOVL	$240, AX		// sys_nanosleep
+	MOVL	$430, AX		// sys_nanosleep
 	INT	$0x80
 	RET
 
 TEXT runtime·raisesigpipe(SB),7,$12
-	MOVL	$299, AX		// sys_getthrid
+	MOVL	$311, AX		// sys__lwp_self
 	INT	$0x80
 	MOVL	$0, 0(SP)
-	MOVL	AX, 4(SP)		// arg 1 - pid
-	MOVL	$13, 8(SP)		// arg 2 - signum == SIGPIPE
-	MOVL	$37, AX			// sys_kill
+	MOVL	AX, 4(SP)		// arg 1 - target
+	MOVL	$13, 8(SP)		// arg 2 - signo == SIGPIPE
+	MOVL	$318, AX		// sys__lwp_kill
 	INT	$0x80
 	RET
 
@@ -67,7 +68,7 @@ TEXT runtime·mmap(SB),7,$36
 	MOVL	$0, AX
 	STOSL				// arg 6 - pad
 	MOVSL				// arg 7 - offset
-	MOVL	$0, AX			// top 64 bits of file offset
+	MOVL	$0, AX			// top 32 bits of file offset
 	STOSL
 	MOVL	$197, AX		// sys_mmap
 	INT	$0x80
@@ -79,60 +80,100 @@ TEXT runtime·munmap(SB),7,$-4
 	MOVL	$73, AX			// sys_munmap
 	INT	$0x80
 	JAE	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
+	RET
+
+TEXT runtime·madvise(SB),7,$-4
+	MOVL	$75, AX			// sys_madvise
+	INT	$0x80
+	// ignore failure - maybe pages are locked
 	RET
 
 TEXT runtime·setitimer(SB),7,$-4
-	MOVL	$83, AX
+	MOVL	$425, AX		// sys_setitimer
 	INT	$0x80
 	RET
 
 // func now() (sec int64, nsec int32)
 TEXT time·now(SB), 7, $32
-	MOVL	$116, AX
 	LEAL	12(SP), BX
-	MOVL	BX, 4(SP)
-	MOVL	$0, 8(SP)
+	MOVL	$0, 4(SP)		// arg 1 - clock_id
+	MOVL	BX, 8(SP)		// arg 2 - tp
+	MOVL	$427, AX		// sys_clock_gettime
 	INT	$0x80
-	MOVL	12(SP), AX		// sec
-	MOVL	16(SP), BX		// usec
 
-	// sec is in AX, usec in BX
+	MOVL	12(SP), AX		// sec - l32
 	MOVL	AX, sec+0(FP)
-	MOVL	$0, sec+4(FP)
-	IMULL	$1000, BX
+	MOVL	16(SP), AX		// sec - h32
+	MOVL	AX, sec+4(FP)
+
+	MOVL	20(SP), BX		// nsec
 	MOVL	BX, nsec+8(FP)
 	RET
 
 // int64 nanotime(void) so really
 // void nanotime(int64 *nsec)
 TEXT runtime·nanotime(SB),7,$32
-	MOVL	$116, AX
 	LEAL	12(SP), BX
-	MOVL	BX, 4(SP)
-	MOVL	$0, 8(SP)
+	MOVL	$0, 4(SP)		// arg 1 - clock_id
+	MOVL	BX, 8(SP)		// arg 2 - tp
+	MOVL	$427, AX		// sys_clock_gettime
 	INT	$0x80
-	MOVL	12(SP), AX		// sec
-	MOVL	16(SP), BX		// usec
-
-	// sec is in AX, usec in BX
-	// convert to DX:AX nsec
-	MOVL	$1000000000, CX
-	MULL	CX
-	IMULL	$1000, BX
+
+	MOVL	16(SP), CX		// sec - h32
+	IMULL	$1000000000, CX
+
+	MOVL	12(SP), AX		// sec - l32
+	MOVL	$1000000000, BX
+	MULL	BX			// result in dx:ax
+
+	MOVL	20(SP), BX		// nsec
 	ADDL	BX, AX
-	ADCL	$0, DX
-	
+	ADCL	CX, DX			// add high bits with carry
+
 	MOVL	ret+0(FP), DI
 	MOVL	AX, 0(DI)
 	MOVL	DX, 4(DI)
 	RET
 
-TEXT runtime·sigaction(SB),7,$-4
-	MOVL	$46, AX			// sys_sigaction
+TEXT runtime·getcontext(SB),7,$-4
+	MOVL	$307, AX		// sys_getcontext
+	INT	$0x80
+	JAE	2(PC)
+	MOVL	$0xf1, 0xf1		// crash
+	RET
+
+TEXT runtime·sigprocmask(SB),7,$-4
+	MOVL	$293, AX		// sys_sigprocmask
+	INT	$0x80
+	JAE	2(PC)
+	MOVL	$0xf1, 0xf1		// crash
+	RET
+
+TEXT runtime·sigreturn_tramp(SB),7,$0
+	LEAL	140(SP), AX		// Load address of ucontext
+	MOVL	AX, 4(SP)
+	MOVL	$308, AX		// sys_setcontext
+	INT	$0x80
+	MOVL	$-1, 4(SP)		// Something failed...
+	MOVL	$1, AX			// sys_exit
+	INT	$0x80
+
+TEXT runtime·sigaction(SB),7,$24
+	LEAL	arg0+0(FP), SI
+	LEAL	4(SP), DI
+	CLD
+	MOVSL				// arg 1 - sig
+	MOVSL				// arg 2 - act
+	MOVSL				// arg 3 - oact
+	LEAL	runtime·sigreturn_tramp(SB), AX
+	STOSL				// arg 4 - tramp
+	MOVL	$2, AX
+	STOSL				// arg 5 - vers
+	MOVL	$340, AX		// sys___sigaction_sigtramp
 	INT	$0x80
 	JAE	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·sigtramp(SB),7,$44
@@ -141,13 +182,16 @@ TEXT runtime·sigtramp(SB),7,$44
 	// check that m exists
 	MOVL	m(CX), BX
 	CMPL	BX, $0
-	JNE	2(PC)
+	JNE	5(PC)
+	MOVL	signo+0(FP), BX
+	MOVL	BX, 0(SP)
 	CALL	runtime·badsignal(SB)
+	RET
 
 	// save g
 	MOVL	g(CX), DI
 	MOVL	DI, 20(SP)
-	
+
 	// g = m->gsignal
 	MOVL	m_gsignal(BX), BX
 	MOVL	BX, g(CX)
@@ -167,67 +211,24 @@ TEXT runtime·sigtramp(SB),7,$44
 	get_tls(CX)
 	MOVL	20(SP), BX
 	MOVL	BX, g(CX)
-	
-	// call sigreturn
-	MOVL	context+8(FP), AX
-	MOVL	$0, 0(SP)		// syscall gap
-	MOVL	AX, 4(SP)		// arg 1 - sigcontext
-	MOVL	$103, AX		// sys_sigreturn
-	INT	$0x80
-	MOVL	$0xf1, 0xf1  // crash
 	RET
 
-// int32 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT runtime·rfork_thread(SB),7,$8
-	MOVL	flags+8(SP), AX
-	MOVL	stack+12(SP), CX
-
-	// Copy m, g, fn off parent stack for use by child.
-	SUBL	$16, CX
-	MOVL	mm+16(SP), SI
-	MOVL	SI, 0(CX)
-	MOVL	gg+20(SP), SI
-	MOVL	SI, 4(CX)
-	MOVL	fn+24(SP), SI
-	MOVL	SI, 8(CX)
-	MOVL	$1234, 12(CX)
-	MOVL	CX, SI
-
-	MOVL	$0, 0(SP)		// syscall gap
-	MOVL	AX, 4(SP)		// arg 1 - flags
-	MOVL	$251, AX		// sys_rfork
+// int32 lwp_create(void *context, uintptr flags, void *lwpid);
+TEXT runtime·lwp_create(SB),7,$16
+	MOVL	$0, 0(SP)
+	MOVL	context+0(FP), AX
+	MOVL	AX, 4(SP)		// arg 1 - context
+	MOVL	flags+4(FP), AX
+	MOVL	AX, 8(SP)		// arg 2 - flags
+	MOVL	lwpid+8(FP), AX
+	MOVL	AX, 12(SP)		// arg 3 - lwpid
+	MOVL	$309, AX		// sys__lwp_create
 	INT	$0x80
-
-	// Return if rfork syscall failed
-	JCC	4(PC)
+	JCC	2(PC)
 	NEGL	AX
-	MOVL	AX, 48(SP)
 	RET
 
-	// In parent, return.
-	CMPL	AX, $0
-	JEQ	3(PC)
-	MOVL	AX, 48(SP)
-	RET
-
-	// In child, on new stack.
-	MOVL    SI, SP
-
-	// Paranoia: check that SP is as we expect.
-	MOVL	12(SP), BP
-	CMPL	BP, $1234
-	JEQ	2(PC)
-	INT	$3
-
-	// Reload registers
-	MOVL	0(SP), BX		// m
-	MOVL	4(SP), DX		// g
-	MOVL	8(SP), SI		// fn
-
-	// Initialize m->procid to thread ID
-	MOVL	$299, AX		// sys_getthrid
-	INT	$0x80
-	MOVL	AX, m_procid(BX)
+TEXT runtime·lwp_tramp(SB),7,$0
 
 	// Set FS to point at m->tls
 	LEAL	m_tls(BX), BP
@@ -236,7 +237,7 @@ TEXT runtime·rfork_thread(SB),7,$8
 	CALL	runtime·settls(SB)
 	POPL	AX
 	POPAL
-	
+
 	// Now segment is established.  Initialize m, g.
 	get_tls(AX)
 	MOVL	DX, g(AX)
@@ -259,7 +260,7 @@ TEXT runtime·rfork_thread(SB),7,$8
 	RET
 
 TEXT runtime·sigaltstack(SB),7,$-8
-	MOVL	$288, AX		// sys_sigaltstack
+	MOVL	$281, AX		// sys___sigaltstack14
 	MOVL	new+4(SP), BX
 	MOVL	old+8(SP), CX
 	INT	$0x80
@@ -277,30 +278,33 @@ TEXT runtime·setldt(SB),7,$8
 
 TEXT runtime·settls(SB),7,$16
 	// adjust for ELF: wants to use -8(GS) and -4(GS) for g and m
-	MOVL	20(SP), CX
+	MOVL	base+0(FP), CX
 	ADDL	$8, CX
-	MOVL	CX, 0(CX)
 	MOVL	$0, 0(SP)		// syscall gap
-	MOVL	$9, 4(SP)		// I386_SET_GSBASE (machine/sysarch.h)
-	MOVL	CX, 8(SP)		// pointer to base
-	MOVL	$165, AX		// sys_sysarch
+	MOVL	CX, 4(SP)		// arg 1 - ptr
+	MOVL	$317, AX		// sys__lwp_setprivate
 	INT	$0x80
 	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·osyield(SB),7,$-4
-	MOVL	$298, AX		// sys_sched_yield
+	MOVL	$350, AX		// sys_sched_yield
+	INT	$0x80
+	RET
+
+TEXT runtime·lwp_park(SB),7,$-4
+	MOVL	$434, AX		// sys__lwp_park
 	INT	$0x80
 	RET
 
-TEXT runtime·thrsleep(SB),7,$-4
-	MOVL	$300, AX		// sys_thrsleep
+TEXT runtime·lwp_unpark(SB),7,$-4
+	MOVL	$321, AX		// sys__lwp_unpark
 	INT	$0x80
 	RET
 
-TEXT runtime·thrwakeup(SB),7,$-4
-	MOVL	$301, AX		// sys_thrwakeup
+TEXT runtime·lwp_self(SB),7,$-4
+	MOVL	$311, AX		// sys__lwp_self
 	INT	$0x80
 	RET
 
diff --git a/src/pkg/runtime/sys_netbsd_amd64.s b/src/pkg/runtime/sys_netbsd_amd64.s
index 0b83cd4..e73e83d 100644
--- a/src/pkg/runtime/sys_netbsd_amd64.s
+++ b/src/pkg/runtime/sys_netbsd_amd64.s
@@ -8,42 +8,24 @@
 
 #include "zasm_GOOS_GOARCH.h"
 
-// int64 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT runtime·rfork_thread(SB),7,$0
-	MOVL	flags+8(SP), DI
-	MOVQ	stack+16(SP), SI
-
-	// Copy m, g, fn off parent stack for use by child.
-	MOVQ	mm+24(SP), R8
-	MOVQ	gg+32(SP), R9
-	MOVQ	fn+40(SP), R12
-
-	MOVL	$251, AX		// sys_rfork
+// int32 lwp_create(void *context, uintptr flags, void *lwpid)
+TEXT runtime·lwp_create(SB),7,$0
+	MOVQ	context+0(FP), DI
+	MOVQ	flags+8(FP), SI
+	MOVQ	lwpid+16(FP), DX
+	MOVL	$309, AX		// sys__lwp_create
 	SYSCALL
-
-	// Return if rfork syscall failed
-	JCC	3(PC)
+	JCC	2(PC)
 	NEGL	AX
 	RET
 
-	// In parent, return.
-	CMPL	AX, $0
-	JEQ	2(PC)
-	RET
-
-	// In child, on new stack.
-	MOVQ	SI, SP
-
-	// Initialize m->procid to thread ID
-	MOVL	$299, AX		// sys_getthrid
-	SYSCALL
-	MOVQ	AX, m_procid(R8)
-
+TEXT runtime·lwp_tramp(SB),7,$0
+	
 	// Set FS to point at m->tls.
 	LEAQ	m_tls(R8), DI
 	CALL	runtime·settls(SB)
 
-	// In child, set up new stack
+	// Set up new stack.
 	get_tls(CX)
 	MOVQ	R8, m(CX)
 	MOVQ	R9, g(CX)
@@ -52,29 +34,34 @@ TEXT runtime·rfork_thread(SB),7,$0
 	// Call fn
 	CALL	R12
 
-	// It shouldn't return.  If it does, exit
-	MOVL	$302, AX		// sys_threxit
+	// It shouldn't return.  If it does, exit.
+	MOVL	$310, AX		// sys__lwp_exit
 	SYSCALL
 	JMP	-3(PC)			// keep exiting
 
 TEXT runtime·osyield(SB),7,$0
-	MOVL $298, AX			// sys_sched_yield
+	MOVL	$350, AX		// sys_sched_yield
 	SYSCALL
 	RET
 
-TEXT runtime·thrsleep(SB),7,$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
-	MOVL	$300, AX		// sys_thrsleep
+TEXT runtime·lwp_park(SB),7,$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
+	MOVL	$434, AX		// sys__lwp_park
 	SYSCALL
 	RET
 
-TEXT runtime·thrwakeup(SB),7,$0
-	MOVQ	8(SP), DI		// arg 1 - ident
-	MOVL	16(SP), SI		// arg 2 - n
-	MOVL	$301, AX		// sys_thrwakeup
+TEXT runtime·lwp_unpark(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - lwp
+	MOVL	16(SP), SI		// arg 2 - hint
+	MOVL	$321, AX		// sys__lwp_unpark
+	SYSCALL
+	RET
+
+TEXT runtime·lwp_self(SB),7,$0
+	MOVL	$311, AX		// sys__lwp_self
 	SYSCALL
 	RET
 
@@ -83,13 +70,13 @@ TEXT runtime·exit(SB),7,$-8
 	MOVL	8(SP), DI		// arg 1 - exit status
 	MOVL	$1, AX			// sys_exit
 	SYSCALL
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·exit1(SB),7,$-8
-	MOVL	$302, AX		// sys_threxit
+	MOVL	$310, AX		// sys__lwp_exit
 	SYSCALL
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·write(SB),7,$-8
@@ -112,16 +99,16 @@ TEXT runtime·usleep(SB),7,$16
 
 	MOVQ	SP, DI			// arg 1 - rqtp
 	MOVQ	$0, SI			// arg 2 - rmtp
-	MOVL	$240, AX		// sys_nanosleep
+	MOVL	$430, AX		// sys_nanosleep
 	SYSCALL
 	RET
 
 TEXT runtime·raisesigpipe(SB),7,$16
-	MOVL	$299, AX		// sys_getthrid
+	MOVL	$311, AX		// sys__lwp_self
 	SYSCALL
-	MOVQ	AX, DI			// arg 1 - pid
-	MOVQ	$13, SI			// arg 2 - signum == SIGPIPE
-	MOVL	$37, AX			// sys_kill
+	MOVQ	AX, DI			// arg 1 - target
+	MOVQ	$13, SI			// arg 2 - signo == SIGPIPE
+	MOVL	$318, AX		// sys__lwp_kill
 	SYSCALL
 	RET
 
@@ -129,72 +116,101 @@ TEXT runtime·setitimer(SB),7,$-8
 	MOVL	8(SP), DI		// arg 1 - which
 	MOVQ	16(SP), SI		// arg 2 - itv
 	MOVQ	24(SP), DX		// arg 3 - oitv
-	MOVL	$83, AX			// sys_setitimer
+	MOVL	$425, AX		// sys_setitimer
 	SYSCALL
 	RET
 
 // func now() (sec int64, nsec int32)
 TEXT time·now(SB), 7, $32
-	LEAQ	8(SP), DI		// arg 1 - tp
-	MOVQ	$0, SI			// arg 2 - tzp
-	MOVL	$116, AX		// sys_gettimeofday
+	MOVQ	$0, DI			// arg 1 - clock_id
+	LEAQ	8(SP), SI		// arg 2 - tp
+	MOVL	$427, AX		// sys_clock_gettime
 	SYSCALL
 	MOVQ	8(SP), AX		// sec
-	MOVL	16(SP), DX	// usec
+	MOVL	16(SP), DX		// nsec
 
-	// sec is in AX, usec in DX
+	// sec is in AX, nsec in DX
 	MOVQ	AX, sec+0(FP)
-	IMULQ	$1000, DX
 	MOVL	DX, nsec+8(FP)
 	RET
 
 TEXT runtime·nanotime(SB),7,$32
-	LEAQ	8(SP), DI		// arg 1 - tp
-	MOVQ	$0, SI			// arg 2 - tzp
-	MOVL	$116, AX		// sys_gettimeofday
+	MOVQ	$0, DI			// arg 1 - clock_id
+	LEAQ	8(SP), SI		// arg 2 - tp
+	MOVL	$427, AX		// sys_clock_gettime
 	SYSCALL
 	MOVQ	8(SP), AX		// sec
-	MOVL	16(SP), DX	// usec
+	MOVL	16(SP), DX		// nsec
 
-	// sec is in AX, usec in DX
+	// sec is in AX, nsec in DX
 	// return nsec in AX
 	IMULQ	$1000000000, AX
-	IMULQ	$1000, DX
 	ADDQ	DX, AX
 	RET
 
+TEXT runtime·getcontext(SB),7,$-8
+	MOVQ	8(SP), DI		// arg 1 - context
+	MOVL	$307, AX		// sys_getcontext
+	SYSCALL
+	JCC	2(PC)
+	MOVL	$0xf1, 0xf1		// crash
+	RET
+
+TEXT runtime·sigprocmask(SB),7,$0
+	MOVL	8(SP), DI		// arg 1 - how
+	MOVQ	16(SP), SI		// arg 2 - set
+	MOVQ	24(SP), DX		// arg 3 - oset
+	MOVL	$293, AX		// sys_sigprocmask
+	SYSCALL
+	JCC	2(PC)
+	MOVL	$0xf1, 0xf1		// crash
+	RET
+
+TEXT runtime·sigreturn_tramp(SB),7,$-8
+	MOVQ	R15, DI			// Load address of ucontext
+	MOVQ	$308, AX		// sys_setcontext
+	SYSCALL
+	MOVQ	$-1, DI			// Something failed...
+	MOVL	$1, AX			// sys_exit
+	SYSCALL
+
 TEXT runtime·sigaction(SB),7,$-8
 	MOVL	8(SP), DI		// arg 1 - signum
 	MOVQ	16(SP), SI		// arg 2 - nsa
 	MOVQ	24(SP), DX		// arg 3 - osa
-	MOVL	$46, AX
+					// arg 4 - tramp
+	LEAQ	runtime·sigreturn_tramp(SB), R10
+	MOVQ	$2, R8			// arg 5 - vers
+	MOVL	$340, AX		// sys___sigaction_sigtramp
 	SYSCALL
 	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·sigtramp(SB),7,$64
 	get_tls(BX)
-	
+
 	// check that m exists
 	MOVQ	m(BX), BP
 	CMPQ	BP, $0
-	JNE	2(PC)
+	JNE	4(PC)
+	MOVQ	DI, 0(SP)
 	CALL	runtime·badsignal(SB)
+	RET
 
 	// save g
 	MOVQ	g(BX), R10
 	MOVQ	R10, 40(SP)
-	
+
 	// g = m->signal
 	MOVQ	m_gsignal(BP), BP
 	MOVQ	BP, g(BX)
-	
+
 	MOVQ	DI, 0(SP)
 	MOVQ	SI, 8(SP)
 	MOVQ	DX, 16(SP)
 	MOVQ	R10, 24(SP)
-	
+
 	CALL	runtime·sighandler(SB)
 
 	// restore g
@@ -213,7 +229,7 @@ TEXT runtime·mmap(SB),7,$0
 	SUBQ	$16, SP
 	MOVQ	R9, 8(SP)		// arg 7 - offset (passed on stack)
 	MOVQ	$0, R9			// arg 6 - pad
-	MOVL	$197, AX
+	MOVL	$197, AX		// sys_mmap
 	SYSCALL
 	JCC	2(PC)
 	NEGL	AX
@@ -226,29 +242,36 @@ TEXT runtime·munmap(SB),7,$0
 	MOVL	$73, AX			// sys_munmap
 	SYSCALL
 	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
+	RET
+
+
+TEXT runtime·madvise(SB),7,$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	$75, AX			// sys_madvise
+	SYSCALL
+	// ignore failure - maybe pages are locked
 	RET
 
 TEXT runtime·sigaltstack(SB),7,$-8
 	MOVQ	new+8(SP), DI		// arg 1 - nss
 	MOVQ	old+16(SP), SI		// arg 2 - oss
-	MOVQ	$288, AX		// sys_sigaltstack
+	MOVQ	$281, AX		// sys___sigaltstack14
 	SYSCALL
 	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 // set tls base to DI
 TEXT runtime·settls(SB),7,$8
 	// adjust for ELF: wants to use -16(FS) and -8(FS) for g and m
-	ADDQ	$16, DI
-	MOVQ	DI, 0(SP)
-	MOVQ	SP, SI
-	MOVQ	$12, DI			// AMD64_SET_FSBASE (machine/sysarch.h)
-	MOVQ	$165, AX		// sys_sysarch
+	ADDQ	$16, DI			// arg 1 - ptr
+	MOVQ	$317, AX		// sys__lwp_setprivate
 	SYSCALL
 	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·sysctl(SB),7,$0
diff --git a/src/pkg/runtime/sys_netbsd_arm.s b/src/pkg/runtime/sys_netbsd_arm.s
new file mode 100644
index 0000000..4a119c5
--- /dev/null
+++ b/src/pkg/runtime/sys_netbsd_arm.s
@@ -0,0 +1,280 @@
+// 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.
+//
+// System calls and other sys.stuff for ARM, NetBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$-4
+	MOVW 0(FP), R0	// arg 1 exit status
+	SWI $0xa00001
+	MOVW.CS $0, R9	// crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·exit1(SB),7,$-4
+	SWI $0xa00136	// sys__lwp_exit
+	MOVW $1, R9	// crash
+	MOVW R9, (R9)
+	RET
+
+TEXT runtime·write(SB),7,$-4
+	MOVW	0(FP), R0	// arg 1 - fd
+	MOVW	4(FP), R1	// arg 2 - buf
+	MOVW	8(FP), R2	// arg 3 - nbyte
+	SWI $0xa00004	// sys_write
+	RET
+
+// int32 lwp_create(void *context, uintptr flags, void *lwpid)
+TEXT runtime·lwp_create(SB),7,$0
+	MOVW context+0(FP), R0
+	MOVW flags+4(FP), R1
+	MOVW lwpid+8(FP), R2
+	SWI $0xa00135	// sys__lwp_create
+	RET
+
+TEXT runtime·osyield(SB),7,$0
+	SWI $0xa0015e	// sys_sched_yield
+	RET
+
+TEXT runtime·lwp_park(SB),7,$0
+	MOVW 0(FP), R0	// arg 1 - abstime
+	MOVW 4(FP), R1	// arg 2 - unpark
+	MOVW 8(FP), R2	// arg 3 - hint
+	MOVW 12(FP), R3	// arg 4 - unparkhint
+	SWI $0xa001b2	// sys__lwp_park
+	RET
+
+TEXT runtime·lwp_unpark(SB),7,$0
+	MOVW	0(FP), R0	// arg 1 - lwp
+	MOVW	4(FP), R1	// arg 2 - hint
+	SWI $0xa00141 // sys__lwp_unpark
+	RET
+
+TEXT runtime·lwp_self(SB),7,$0
+	SWI $0xa00137	// sys__lwp_self
+	RET
+
+TEXT runtime·lwp_tramp(SB),7,$0
+	MOVW R0, R9 // m
+	MOVW R1, R10 // g
+
+	BL runtime·emptyfunc(SB) // fault if stack check is wrong
+	BL (R2)
+	MOVW $2, R9  // crash (not reached)
+	MOVW R9, (R9)
+	RET
+
+TEXT runtime·usleep(SB),7,$16
+	MOVW usec+0(FP), R0
+	MOVW R0, R2
+	MOVW $1000000, R1
+	DIV R1, R0
+	// 0(R13) is the saved LR, don't use it
+	MOVW R0, 4(R13) // tv_sec.low
+	MOVW $0, R0
+	MOVW R0, 8(R13) // tv_sec.high
+	MOD R1, R2
+	MOVW $1000, R1
+	MUL R1, R2
+	MOVW R2, 12(R13) // tv_nsec
+
+	MOVW $4(R13), R0 // arg 1 - rqtp
+	MOVW $0, R1      // arg 2 - rmtp
+	SWI $0xa001ae	// sys_nanosleep
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$16
+	SWI $0xa00137	// sys__lwp_self, the returned R0 is arg 1
+	MOVW $13, R1	// arg 2 - signo == SIGPIPE
+	SWI $0xa0013e	// sys__lwp_kill
+	RET
+
+TEXT runtime·setitimer(SB),7,$-4
+	MOVW 0(FP), R0	// arg 1 - which
+	MOVW 4(FP), R1	// arg 2 - itv
+	MOVW 8(FP), R2	// arg 3 - oitv
+	SWI $0xa001a9	// sys_setitimer
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	MOVW $0, R0	// CLOCK_REALTIME
+	MOVW $8(R13), R1
+	SWI $0xa001ab	// clock_gettime
+
+	MOVW 8(R13), R0	// sec.low
+	MOVW 12(R13), R1 // sec.high
+	MOVW 16(R13), R2 // nsec
+
+	MOVW R0, 0(FP)
+	MOVW R1, 4(FP)
+	MOVW R2, 8(FP)
+	RET
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB), 7, $32
+	MOVW $0, R0 // CLOCK_REALTIME
+	MOVW $8(R13), R1
+	SWI $0xa001ab	// clock_gettime
+
+	MOVW 8(R13), R0 // sec.low
+	MOVW 12(R13), R4 // sec.high
+	MOVW 16(R13), R2 // nsec
+
+	MOVW $1000000000, R3
+	MULLU R0, R3, (R1, R0)
+	MUL R3, R4
+	ADD.S R2, R0
+	ADC R4, R1
+
+	MOVW 0(FP), R3
+	MOVW R0, 0(R3)
+	MOVW R1, 4(R3)
+	RET
+
+TEXT runtime·getcontext(SB),7,$-4
+	MOVW 0(FP), R0	// arg 1 - context
+	SWI $0xa00133	// sys_getcontext
+	MOVW.CS $0, R9	// crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·sigprocmask(SB),7,$0
+	MOVW 0(FP), R0	// arg 1 - how
+	MOVW 4(FP), R1	// arg 2 - set
+	MOVW 8(FP), R2	// arg 3 - oset
+	SWI $0xa00125	// sys_sigprocmask
+	MOVW.CS $0, R9	// crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·sigreturn_tramp(SB),7,$-4
+	// in runtime·sigtramp, we saved ucontext into m->tls[0],
+	// here we just load it and call sys_setcontext
+	MOVW m_tls(m), R0
+	SWI $0xa00134	// sys_setcontext
+	// something failed, we have to exit
+	MOVW $0x4242, R0 // magic return number
+	SWI $0xa00001	// sys_exit
+	B -2(PC)	// continue exit
+
+TEXT runtime·sigaction(SB),7,$4
+	MOVW 0(FP), R0	// arg 1 - signum
+	MOVW 4(FP), R1	// arg 2 - nsa
+	MOVW 8(FP), R2	// arg 3 - osa
+	MOVW $runtime·sigreturn_tramp(SB), R3	// arg 4 - tramp
+	MOVW $2, R4	// arg 5 - vers
+	MOVW R4, 4(R13)
+	ADD $4, R13	// pass arg 5 on stack
+	SWI $0xa00154	// sys___sigaction_sigtramp
+	SUB $4, R13
+	MOVW.CS $3, R9	// crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$24
+	// this might be called in external code context,
+	// where g and m are not set.
+	// first save R0, because _cgo_load_gm will clobber it
+	// TODO(adonovan): call runtime·badsignal if m=0, like other platforms?
+	MOVW	R0, 4(R13) // signum
+	MOVW	_cgo_load_gm(SB), R0
+	CMP 	$0, R0
+	BL.NE	(R0)
+
+	// save g
+	MOVW R10, R4
+	MOVW R10, 20(R13)
+
+	// g = m->signal
+	MOVW m_gsignal(R9), R10
+
+	// R0 is already saved
+	MOVW R1, 8(R13) // info
+	MOVW R2, 12(R13) // context
+	MOVW R4, 16(R13) // gp
+	// we also save the ucontext into m->tls[0] for easy
+	// signal return
+	MOVW R2, m_tls(m)
+
+	BL runtime·sighandler(SB)
+
+	// restore g
+	MOVW 20(R13), R10
+	RET
+
+TEXT runtime·mmap(SB),7,$12
+	MOVW 0(FP), R0	// arg 1 - addr
+	MOVW 4(FP), R1	// arg 2 - len
+	MOVW 8(FP), R2	// arg 3 - prot
+	MOVW 12(FP), R3	// arg 4 - flags
+	// arg 5 (fid) and arg6 (offset_lo, offset_hi) are passed on stack
+	// note the C runtime only passes the 32-bit offset_lo to us
+	MOVW 16(FP), R4		// arg 5
+	MOVW R4, 4(R13)
+	MOVW 20(FP), R5		// arg 6 lower 32-bit
+	MOVW R5, 8(R13)
+	MOVW $0, R6 // higher 32-bit for arg 6
+	MOVW R6, 12(R13)
+	ADD $4, R13 // pass arg 5 and arg 6 on stack
+	SWI $0xa000c5	// sys_mmap
+	SUB $4, R13
+	RET
+
+TEXT runtime·munmap(SB),7,$0
+	MOVW 0(FP), R0	// arg 1 - addr
+	MOVW 4(FP), R1	// arg 2 - len
+	SWI $0xa00049	// sys_munmap
+	MOVW.CS $0, R9	// crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·madvise(SB),7,$0
+	MOVW 0(FP), R0	// arg 1 - addr
+	MOVW 4(FP), R1	// arg 2 - len
+	MOVW 8(FP), R2	// arg 3 - behav
+	SWI $0xa0004b	// sys_madvise
+	// ignore failure - maybe pages are locked
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$-4
+	MOVW 0(FP), R0	// arg 1 - nss
+	MOVW 4(FP), R1	// arg 2 - oss
+	SWI $0xa00119	// sys___sigaltstack14
+	MOVW.CS $0, R9	// crash on syscall failure
+	MOVW.CS R9, (R9)
+	RET
+
+TEXT runtime·sysctl(SB),7,$8
+	MOVW 0(FP), R0	// arg 1 - name
+	MOVW 4(FP), R1	// arg 2 - namelen
+	MOVW 8(FP), R2	// arg 3 - oldp
+	MOVW 12(FP), R3	// arg 4 - oldlenp
+	MOVW 16(FP), R4	// arg 5 - newp
+	MOVW R4, 4(R13)
+	MOVW 20(FP), R4	// arg 6 - newlen
+	MOVW R4, 8(R13)
+	ADD $4, R13	// pass arg 5 and 6 on stack
+	SWI $0xa000ca	// sys___sysctl
+	SUB $4, R13
+	RET
+
+TEXT runtime·casp(SB),7,$0
+	B	runtime·cas(SB)
+
+// TODO(minux): this is only valid for ARMv6+
+// bool armcas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	}else
+//		return 0;
+TEXT runtime·cas(SB),7,$0
+	B runtime·armcas(SB)
diff --git a/src/pkg/runtime/sys_openbsd_386.s b/src/pkg/runtime/sys_openbsd_386.s
index 593b4a9..c62e0f9 100644
--- a/src/pkg/runtime/sys_openbsd_386.s
+++ b/src/pkg/runtime/sys_openbsd_386.s
@@ -12,14 +12,16 @@
 TEXT runtime·exit(SB),7,$-4
 	MOVL	$1, AX
 	INT	$0x80
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
-TEXT runtime·exit1(SB),7,$-4
-	MOVL	$302, AX		// sys_threxit
+TEXT runtime·exit1(SB),7,$8
+	MOVL	$0, 0(SP)
+	MOVL	$0, 4(SP)		// arg 1 - notdead
+	MOVL	$302, AX		// sys___threxit
 	INT	$0x80
 	JAE	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·write(SB),7,$-4
@@ -67,7 +69,7 @@ TEXT runtime·mmap(SB),7,$36
 	MOVL	$0, AX
 	STOSL				// arg 6 - pad
 	MOVSL				// arg 7 - offset
-	MOVL	$0, AX			// top 64 bits of file offset
+	MOVL	$0, AX			// top 32 bits of file offset
 	STOSL
 	MOVL	$197, AX		// sys_mmap
 	INT	$0x80
@@ -79,7 +81,14 @@ TEXT runtime·munmap(SB),7,$-4
 	MOVL	$73, AX			// sys_munmap
 	INT	$0x80
 	JAE	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
+	RET
+
+TEXT runtime·madvise(SB),7,$-4
+	MOVL	$75, AX			// sys_madvise
+	INT	$0x80
+	JAE	2(PC)
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·setitimer(SB),7,$-4
@@ -89,40 +98,38 @@ TEXT runtime·setitimer(SB),7,$-4
 
 // func now() (sec int64, nsec int32)
 TEXT time·now(SB), 7, $32
-	MOVL	$116, AX
+	MOVL	$232, AX
 	LEAL	12(SP), BX
-	MOVL	BX, 4(SP)
-	MOVL	$0, 8(SP)
+	MOVL	$0, 4(SP)
+	MOVL	BX, 8(SP)
 	INT	$0x80
 	MOVL	12(SP), AX		// sec
-	MOVL	16(SP), BX		// usec
+	MOVL	16(SP), BX		// nsec
 
-	// sec is in AX, usec in BX
+	// sec is in AX, nsec in BX
 	MOVL	AX, sec+0(FP)
 	MOVL	$0, sec+4(FP)
-	IMULL	$1000, BX
 	MOVL	BX, nsec+8(FP)
 	RET
 
 // int64 nanotime(void) so really
 // void nanotime(int64 *nsec)
 TEXT runtime·nanotime(SB),7,$32
-	MOVL	$116, AX
+	MOVL	$232, AX
 	LEAL	12(SP), BX
-	MOVL	BX, 4(SP)
-	MOVL	$0, 8(SP)
+	MOVL	$0, 4(SP)
+	MOVL	BX, 8(SP)
 	INT	$0x80
 	MOVL	12(SP), AX		// sec
-	MOVL	16(SP), BX		// usec
+	MOVL	16(SP), BX		// nsec
 
-	// sec is in AX, usec in BX
+	// sec is in AX, nsec in BX
 	// convert to DX:AX nsec
 	MOVL	$1000000000, CX
 	MULL	CX
-	IMULL	$1000, BX
 	ADDL	BX, AX
 	ADCL	$0, DX
-	
+
 	MOVL	ret+0(FP), DI
 	MOVL	AX, 0(DI)
 	MOVL	DX, 4(DI)
@@ -132,7 +139,15 @@ TEXT runtime·sigaction(SB),7,$-4
 	MOVL	$46, AX			// sys_sigaction
 	INT	$0x80
 	JAE	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
+	RET
+
+TEXT runtime·sigprocmask(SB),7,$-4
+	MOVL	$48, AX			// sys_sigprocmask
+	INT	$0x80
+	JAE	2(PC)
+	MOVL	$0xf1, 0xf1		// crash
+	MOVL	AX, oset+0(FP)
 	RET
 
 TEXT runtime·sigtramp(SB),7,$44
@@ -141,8 +156,11 @@ TEXT runtime·sigtramp(SB),7,$44
 	// check that m exists
 	MOVL	m(CX), BX
 	CMPL	BX, $0
-	JNE	2(PC)
+	JNE	5(PC)
+	MOVL	signo+0(FP), BX
+	MOVL	BX, 0(SP)
 	CALL	runtime·badsignal(SB)
+	RET
 
 	// save g
 	MOVL	g(CX), DI
@@ -174,62 +192,59 @@ TEXT runtime·sigtramp(SB),7,$44
 	MOVL	AX, 4(SP)		// arg 1 - sigcontext
 	MOVL	$103, AX		// sys_sigreturn
 	INT	$0x80
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
-// int32 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT runtime·rfork_thread(SB),7,$8
-	MOVL	flags+8(SP), AX
-	MOVL	stack+12(SP), CX
+// int32 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
+TEXT runtime·tfork(SB),7,$12
 
-	// Copy m, g, fn off parent stack for use by child.
+	// Copy mp, gp and fn from the parent stack onto the child stack.
+	MOVL	params+4(FP), AX
+	MOVL	8(AX), CX		// tf_stack
 	SUBL	$16, CX
-	MOVL	mm+16(SP), SI
+	MOVL	CX, 8(AX)
+	MOVL	mm+12(FP), SI
 	MOVL	SI, 0(CX)
-	MOVL	gg+20(SP), SI
+	MOVL	gg+16(FP), SI
 	MOVL	SI, 4(CX)
-	MOVL	fn+24(SP), SI
+	MOVL	fn+20(FP), SI
 	MOVL	SI, 8(CX)
 	MOVL	$1234, 12(CX)
-	MOVL	CX, SI
 
 	MOVL	$0, 0(SP)		// syscall gap
-	MOVL	AX, 4(SP)		// arg 1 - flags
-	MOVL	$251, AX		// sys_rfork
+	MOVL	params+4(FP), AX
+	MOVL	AX, 4(SP)		// arg 1 - param
+	MOVL	psize+8(FP), AX
+	MOVL	AX, 8(SP)		// arg 2 - psize
+	MOVL	$8, AX			// sys___tfork
 	INT	$0x80
 
-	// Return if rfork syscall failed
-	JCC	4(PC)
+	// Return if tfork syscall failed.
+	JCC	5(PC)
 	NEGL	AX
-	MOVL	AX, 48(SP)
+	MOVL	ret+0(FP), DX
+	MOVL	AX, 0(DX)
 	RET
 
 	// In parent, return.
 	CMPL	AX, $0
-	JEQ	3(PC)
-	MOVL	AX, 48(SP)
+	JEQ	4(PC)
+	MOVL	ret+0(FP), DX
+	MOVL	AX, 0(DX)
 	RET
 
-	// In child, on new stack.
-	MOVL    SI, SP
-
 	// Paranoia: check that SP is as we expect.
 	MOVL	12(SP), BP
 	CMPL	BP, $1234
 	JEQ	2(PC)
 	INT	$3
 
-	// Reload registers
+	// Reload registers.
 	MOVL	0(SP), BX		// m
 	MOVL	4(SP), DX		// g
 	MOVL	8(SP), SI		// fn
 
-	// Initialize m->procid to thread ID
-	MOVL	$299, AX		// sys_getthrid
-	INT	$0x80
-	MOVL	AX, m_procid(BX)
-
-	// Set FS to point at m->tls
+	// Set FS to point at m->tls.
 	LEAL	m_tls(BX), BP
 	PUSHAL				// save registers
 	PUSHL	BP
@@ -246,12 +261,12 @@ TEXT runtime·rfork_thread(SB),7,$8
 	MOVL	0(DX), DX		// paranoia; check they are not nil
 	MOVL	0(BX), BX
 
-	// more paranoia; check that stack splitting code works
+	// More paranoia; check that stack splitting code works.
 	PUSHAL
 	CALL	runtime·emptyfunc(SB)
 	POPAL
 
-	// Call fn
+	// Call fn.
 	CALL	SI
 
 	CALL	runtime·exit1(SB)
@@ -268,25 +283,23 @@ TEXT runtime·sigaltstack(SB),7,$-8
 	INT	$3
 	RET
 
-TEXT runtime·setldt(SB),7,$8
+TEXT runtime·setldt(SB),7,$4
 	// Under OpenBSD we set the GS base instead of messing with the LDT.
-	MOVL	16(SP), AX		// tls0
+	MOVL	tls0+4(FP), AX
 	MOVL	AX, 0(SP)
 	CALL	runtime·settls(SB)
 	RET
 
-TEXT runtime·settls(SB),7,$16
+TEXT runtime·settls(SB),7,$8
 	// adjust for ELF: wants to use -8(GS) and -4(GS) for g and m
-	MOVL	20(SP), CX
+	MOVL	tlsbase+0(FP), CX
 	ADDL	$8, CX
-	MOVL	CX, 0(CX)
 	MOVL	$0, 0(SP)		// syscall gap
-	MOVL	$9, 4(SP)		// I386_SET_GSBASE (machine/sysarch.h)
-	MOVL	CX, 8(SP)		// pointer to base
-	MOVL	$165, AX		// sys_sysarch
+	MOVL	CX, 4(SP)		// arg 1 - tcb
+	MOVL	$329, AX		// sys___set_tcb
 	INT	$0x80
 	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·osyield(SB),7,$-4
@@ -295,12 +308,12 @@ TEXT runtime·osyield(SB),7,$-4
 	RET
 
 TEXT runtime·thrsleep(SB),7,$-4
-	MOVL	$300, AX		// sys_thrsleep
+	MOVL	$300, AX		// sys___thrsleep
 	INT	$0x80
 	RET
 
 TEXT runtime·thrwakeup(SB),7,$-4
-	MOVL	$301, AX		// sys_thrwakeup
+	MOVL	$301, AX		// sys___thrwakeup
 	INT	$0x80
 	RET
 
diff --git a/src/pkg/runtime/sys_openbsd_amd64.s b/src/pkg/runtime/sys_openbsd_amd64.s
index d2d48e6..8a73650 100644
--- a/src/pkg/runtime/sys_openbsd_amd64.s
+++ b/src/pkg/runtime/sys_openbsd_amd64.s
@@ -8,20 +8,20 @@
 
 #include "zasm_GOOS_GOARCH.h"
 
-// int64 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT runtime·rfork_thread(SB),7,$0
-	MOVL	flags+8(SP), DI
-	MOVQ	stack+16(SP), SI
+// int64 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
+TEXT runtime·tfork(SB),7,$32
 
-	// Copy m, g, fn off parent stack for use by child.
-	MOVQ	mm+24(SP), R8
-	MOVQ	gg+32(SP), R9
-	MOVQ	fn+40(SP), R12
+	// Copy mp, gp and fn off parent stack for use by child.
+	MOVQ	mm+16(FP), R8
+	MOVQ	gg+24(FP), R9
+	MOVQ	fn+32(FP), R12
 
-	MOVL	$251, AX		// sys_rfork
+	MOVQ	param+0(FP), DI
+	MOVQ	psize+8(FP), SI
+	MOVL	$8, AX			// sys___tfork
 	SYSCALL
 
-	// Return if rfork syscall failed
+	// Return if tfork syscall failed.
 	JCC	3(PC)
 	NEGL	AX
 	RET
@@ -31,19 +31,11 @@ TEXT runtime·rfork_thread(SB),7,$0
 	JEQ	2(PC)
 	RET
 
-	// In child, on new stack.
-	MOVQ	SI, SP
-
-	// Initialize m->procid to thread ID
-	MOVL	$299, AX		// sys_getthrid
-	SYSCALL
-	MOVQ	AX, m_procid(R8)
-
 	// Set FS to point at m->tls.
 	LEAQ	m_tls(R8), DI
 	CALL	runtime·settls(SB)
 
-	// In child, set up new stack
+	// In child, set up new stack.
 	get_tls(CX)
 	MOVQ	R8, m(CX)
 	MOVQ	R9, g(CX)
@@ -53,12 +45,13 @@ TEXT runtime·rfork_thread(SB),7,$0
 	CALL	R12
 
 	// It shouldn't return.  If it does, exit
-	MOVL	$302, AX		// sys_threxit
+	MOVQ	$0, DI			// arg 1 - notdead
+	MOVL	$302, AX		// sys___threxit
 	SYSCALL
 	JMP	-3(PC)			// keep exiting
 
 TEXT runtime·osyield(SB),7,$0
-	MOVL $298, AX			// sys_sched_yield
+	MOVL	$298, AX		// sys_sched_yield
 	SYSCALL
 	RET
 
@@ -67,14 +60,15 @@ TEXT runtime·thrsleep(SB),7,$0
 	MOVL	16(SP), SI		// arg 2 - clock_id
 	MOVQ	24(SP), DX		// arg 3 - tp
 	MOVQ	32(SP), R10		// arg 4 - lock
-	MOVL	$300, AX		// sys_thrsleep
+	MOVQ	40(SP), R8		// arg 5 - abort
+	MOVL	$300, AX		// sys___thrsleep
 	SYSCALL
 	RET
 
 TEXT runtime·thrwakeup(SB),7,$0
 	MOVQ	8(SP), DI		// arg 1 - ident
 	MOVL	16(SP), SI		// arg 2 - n
-	MOVL	$301, AX		// sys_thrwakeup
+	MOVL	$301, AX		// sys___thrwakeup
 	SYSCALL
 	RET
 
@@ -83,13 +77,14 @@ TEXT runtime·exit(SB),7,$-8
 	MOVL	8(SP), DI		// arg 1 - exit status
 	MOVL	$1, AX			// sys_exit
 	SYSCALL
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·exit1(SB),7,$-8
-	MOVL	$302, AX		// sys_threxit
+	MOVQ	$0, DI			// arg 1 - notdead
+	MOVL	$302, AX		// sys___threxit
 	SYSCALL
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·write(SB),7,$-8
@@ -135,31 +130,29 @@ TEXT runtime·setitimer(SB),7,$-8
 
 // func now() (sec int64, nsec int32)
 TEXT time·now(SB), 7, $32
-	LEAQ	8(SP), DI		// arg 1 - tp
-	MOVQ	$0, SI			// arg 2 - tzp
-	MOVL	$116, AX		// sys_gettimeofday
+	MOVQ	$0, DI			// arg 1 - clock_id
+	LEAQ	8(SP), SI		// arg 2 - tp
+	MOVL	$232, AX		// sys_clock_gettime
 	SYSCALL
-	MOVQ	8(SP), AX		// sec
-	MOVL	16(SP), DX	// usec
+	MOVL	8(SP), AX		// sec
+	MOVQ	16(SP), DX		// nsec
 
-	// sec is in AX, usec in DX
+	// sec is in AX, nsec in DX
 	MOVQ	AX, sec+0(FP)
-	IMULQ	$1000, DX
 	MOVL	DX, nsec+8(FP)
 	RET
 
 TEXT runtime·nanotime(SB),7,$32
-	LEAQ	8(SP), DI		// arg 1 - tp
-	MOVQ	$0, SI			// arg 2 - tzp
-	MOVL	$116, AX		// sys_gettimeofday
+	MOVQ	$0, DI			// arg 1 - clock_id
+	LEAQ	8(SP), SI		// arg 2 - tp
+	MOVL	$232, AX		// sys_clock_gettime
 	SYSCALL
-	MOVQ	8(SP), AX		// sec
-	MOVL	16(SP), DX	// usec
+	MOVL	8(SP), AX		// sec
+	MOVQ	16(SP), DX		// nsec
 
-	// sec is in AX, usec in DX
+	// sec is in AX, nsec in DX
 	// return nsec in AX
 	IMULQ	$1000000000, AX
-	IMULQ	$1000, DX
 	ADDQ	DX, AX
 	RET
 
@@ -170,7 +163,17 @@ TEXT runtime·sigaction(SB),7,$-8
 	MOVL	$46, AX
 	SYSCALL
 	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
+	RET
+
+TEXT runtime·sigprocmask(SB),7,$0
+	MOVL	8(SP), DI		// arg 1 - how
+	MOVL	12(SP), SI		// arg 2 - set
+	MOVL	$48, AX			// sys_sigprocmask
+	SYSCALL
+	JCC	2(PC)
+	MOVL	$0xf1, 0xf1		// crash
+	MOVL	AX, oset+0(FP)		// Return oset
 	RET
 
 TEXT runtime·sigtramp(SB),7,$64
@@ -179,8 +182,10 @@ TEXT runtime·sigtramp(SB),7,$64
 	// check that m exists
 	MOVQ	m(BX), BP
 	CMPQ	BP, $0
-	JNE	2(PC)
+	JNE	4(PC)
+	MOVQ	DI, 0(SP)
 	CALL	runtime·badsignal(SB)
+	RET
 
 	// save g
 	MOVQ	g(BX), R10
@@ -226,7 +231,16 @@ TEXT runtime·munmap(SB),7,$0
 	MOVL	$73, AX			// sys_munmap
 	SYSCALL
 	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
+	RET
+
+TEXT runtime·madvise(SB),7,$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	$75, AX			// sys_madvise
+	SYSCALL
+	// ignore failure - maybe pages are locked
 	RET
 
 TEXT runtime·sigaltstack(SB),7,$-8
@@ -235,20 +249,17 @@ TEXT runtime·sigaltstack(SB),7,$-8
 	MOVQ	$288, AX		// sys_sigaltstack
 	SYSCALL
 	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 // set tls base to DI
-TEXT runtime·settls(SB),7,$8
+TEXT runtime·settls(SB),7,$0
 	// adjust for ELF: wants to use -16(FS) and -8(FS) for g and m
 	ADDQ	$16, DI
-	MOVQ	DI, 0(SP)
-	MOVQ	SP, SI
-	MOVQ	$12, DI			// AMD64_SET_FSBASE (machine/sysarch.h)
-	MOVQ	$165, AX		// sys_sysarch
+	MOVQ	$329, AX		// sys___settcb
 	SYSCALL
 	JCC	2(PC)
-	MOVL	$0xf1, 0xf1  // crash
+	MOVL	$0xf1, 0xf1		// crash
 	RET
 
 TEXT runtime·sysctl(SB),7,$0
@@ -260,7 +271,7 @@ TEXT runtime·sysctl(SB),7,$0
 	MOVQ	48(SP), R9		// arg 6 - newlen
 	MOVQ	$202, AX		// sys___sysctl
 	SYSCALL
-	JCC 3(PC)
+	JCC	3(PC)
 	NEGL	AX
 	RET
 	MOVL	$0, AX
diff --git a/src/pkg/runtime/sys_plan9_386.s b/src/pkg/runtime/sys_plan9_386.s
index 94c36aa..3385b08 100644
--- a/src/pkg/runtime/sys_plan9_386.s
+++ b/src/pkg/runtime/sys_plan9_386.s
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "defs_GOOS_GOARCH.h"
 #include "zasm_GOOS_GOARCH.h"
 
 // setldt(int entry, int address, int limit)
@@ -24,9 +23,19 @@ TEXT runtime·pwrite(SB),7,$0
 	INT     $64
 	RET
 
+TEXT runtime·seek(SB),7,$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·close(SB),7,$0
 	MOVL	$4, AX
-	INT		$64
+	INT	$64
 	RET
 
 TEXT runtime·exits(SB),7,$0
@@ -48,6 +57,21 @@ TEXT runtime·plan9_semacquire(SB),7,$0
 	MOVL	$37, AX
 	INT	$64
 	RET
+
+TEXT runtime·plan9_tsemacquire(SB),7,$0
+	MOVL	$52, AX
+	INT	$64
+	RET
+
+TEXT runtime·notify(SB),7,$0
+	MOVL	$28, AX
+	INT	$64
+	RET
+
+TEXT runtime·noted(SB),7,$0
+	MOVL	$29, AX
+	INT	$64
+	RET
 	
 TEXT runtime·plan9_semrelease(SB),7,$0
 	MOVL	$38, AX
@@ -77,9 +101,8 @@ TEXT runtime·rfork(SB),7,$0
 	MOVL	DX, g(AX)
 	MOVL	BX, m(AX)
 
-	// Initialize AX from _tos->pid
-	MOVL	_tos(SB), AX
-	MOVL	tos_pid(AX), AX
+	// Initialize AX from TOS struct.
+	MOVL	procid(AX), AX
 	MOVL	AX, m_procid(BX)	// save pid as m->procid
 	
 	CALL	runtime·stackcheck(SB)	// smashes AX, CX
@@ -95,3 +118,55 @@ TEXT runtime·rfork(SB),7,$0
 	CALL	SI	// fn()
 	CALL	runtime·exit(SB)
 	RET
+
+// void sigtramp(void *ureg, int8 *note)
+TEXT runtime·sigtramp(SB),7,$0
+	get_tls(AX)
+
+	// check that m exists
+	MOVL	m(AX), BX
+	CMPL	BX, $0
+	JNE	3(PC)
+	CALL	runtime·badsignal(SB) // will exit
+	RET
+
+	// save args
+	MOVL	ureg+4(SP), CX
+	MOVL	note+8(SP), DX
+
+	// change stack
+	MOVL	m_gsignal(BX), BP
+	MOVL	g_stackbase(BP), BP
+	MOVL	BP, SP
+
+	// make room for args and g
+	SUBL	$16, SP
+
+	// save g
+	MOVL	g(AX), BP
+	MOVL	BP, 12(SP)
+
+	// g = m->gsignal
+	MOVL	m_gsignal(BX), DI
+	MOVL	DI, g(AX)
+
+	// load args and call sighandler
+	MOVL	CX, 0(SP)
+	MOVL	DX, 4(SP)
+	MOVL	BP, 8(SP)
+
+	CALL	runtime·sighandler(SB)
+
+	// restore g
+	get_tls(BX)
+	MOVL	12(SP), BP
+	MOVL	BP, g(BX)
+
+	// call noted(AX)
+	MOVL	AX, 0(SP)
+	CALL	runtime·noted(SB)
+	RET
+
+// Only used by the 64-bit runtime.
+TEXT runtime·setfpmasks(SB),7,$0
+	RET
diff --git a/src/pkg/runtime/sys_plan9_amd64.s b/src/pkg/runtime/sys_plan9_amd64.s
new file mode 100644
index 0000000..b34f98a
--- /dev/null
+++ b/src/pkg/runtime/sys_plan9_amd64.s
@@ -0,0 +1,208 @@
+// 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 "zasm_GOOS_GOARCH.h"
+
+// setldt(int entry, int address, int limit)
+TEXT runtime·setldt(SB),7,$0
+	RET
+
+TEXT runtime·open(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$14, BP
+	SYSCALL
+	RET
+
+TEXT runtime·pread(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$50, BP
+	SYSCALL
+	RET
+
+TEXT runtime·pwrite(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$51, BP
+	SYSCALL
+	RET
+
+// int32 _seek(int64*, int32, int64, int32)
+TEXT _seek<>(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$39, BP
+	SYSCALL
+	RET
+
+// int64 seek(int32, int64, int32)
+TEXT runtime·seek(SB),7,$56
+	LEAQ	new+48(SP), CX
+	MOVQ	CX, 0(SP)
+	MOVQ	fd+0(FP), CX
+	MOVQ	CX, 8(SP)
+	MOVQ	off+8(FP), CX
+	MOVQ	CX, 16(SP)
+	MOVQ	whence+16(FP), CX
+	MOVQ	CX, 24(SP)
+	CALL	_seek<>(SB)
+	CMPL	AX, $0
+	JGE	2(PC)
+	MOVQ	$-1, new+48(SP)
+	MOVQ	new+48(SP), AX
+	RET
+
+TEXT runtime·close(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$4, BP
+	SYSCALL
+	RET
+
+TEXT runtime·exits(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$8, BP
+	SYSCALL
+	RET
+
+TEXT runtime·brk_(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$24, BP
+	SYSCALL
+	RET
+
+TEXT runtime·sleep(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$17, BP
+	SYSCALL
+	RET
+
+TEXT runtime·plan9_semacquire(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$37, BP
+	SYSCALL
+	RET
+
+TEXT runtime·plan9_tsemacquire(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$52, BP
+	SYSCALL
+	RET
+
+TEXT runtime·notify(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$28, BP
+	SYSCALL
+	RET
+
+TEXT runtime·noted(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$29, BP
+	SYSCALL
+	RET
+	
+TEXT runtime·plan9_semrelease(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$38, BP
+	SYSCALL
+	RET
+
+TEXT runtime·nanotime(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$60, BP
+	SYSCALL
+	RET
+
+TEXT runtime·rfork(SB),7,$0
+	MOVQ	$0x8000, AX
+	MOVQ	$19, BP // rfork
+	SYSCALL
+
+	// In parent, return.
+	CMPQ	AX, $0
+	JEQ	2(PC)
+	RET
+
+	// In child on forked stack.
+	MOVQ	mm+24(SP), BX	// m
+	MOVQ	gg+32(SP), DX	// g
+	MOVQ	fn+40(SP), SI	// fn
+
+	// set SP to be on the new child stack
+	MOVQ	stack+16(SP), CX
+	MOVQ	CX, SP
+
+	// Initialize m, g.
+	get_tls(AX)
+	MOVQ	DX, g(AX)
+	MOVQ	BX, m(AX)
+
+	// Initialize AX from pid in TLS.
+	MOVQ	procid(AX), 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)
+	RET
+
+// This is needed by asm_amd64.s
+TEXT runtime·settls(SB),7,$0
+	RET
+
+// void sigtramp(void *ureg, int8 *note)
+TEXT runtime·sigtramp(SB),7,$0
+	get_tls(AX)
+
+	// check that m exists
+	MOVQ	m(AX), BX
+	CMPQ	BX, $0
+	JNE	3(PC)
+	CALL	runtime·badsignal(SB) // will exit
+	RET
+
+	// save args
+	MOVQ	ureg+8(SP), CX
+	MOVQ	note+16(SP), DX
+
+	// change stack
+	MOVQ	m_gsignal(BX), R10
+	MOVQ	g_stackbase(R10), BP
+	MOVQ	BP, SP
+
+	// make room for args and g
+	SUBQ	$32, SP
+
+	// save g
+	MOVQ	g(AX), BP
+	MOVQ	BP, 24(SP)
+
+	// g = m->gsignal
+	MOVQ	R10, g(AX)
+
+	// load args and call sighandler
+	MOVQ	CX, 0(SP)
+	MOVQ	DX, 8(SP)
+	MOVQ	BP, 16(SP)
+
+	CALL	runtime·sighandler(SB)
+
+	// restore g
+	get_tls(BX)
+	MOVQ	24(SP), R10
+	MOVQ	R10, g(BX)
+
+	// call noted(AX)
+	MOVQ	AX, 0(SP)
+	CALL	runtime·noted(SB)
+	RET
+
+TEXT runtime·setfpmasks(SB),7,$8
+	STMXCSR	0(SP)
+	MOVL	0(SP), AX
+	ANDL	$~0x3F, AX
+	ORL	$(0x3F<<7), AX
+	MOVL	AX, 0(SP)
+	LDMXCSR	0(SP)
+	RET
diff --git a/src/pkg/runtime/sys_windows_386.s b/src/pkg/runtime/sys_windows_386.s
index d5646bf..ca59f0a 100644
--- a/src/pkg/runtime/sys_windows_386.s
+++ b/src/pkg/runtime/sys_windows_386.s
@@ -216,7 +216,7 @@ TEXT runtime·callbackasm+0(SB),7,$0
 
 	CLD
 
-	CALL	runtime·cgocallback(SB)
+	CALL	runtime·cgocallback_gofunc(SB)
 
 	POPL	AX
 	POPL	CX
@@ -243,11 +243,6 @@ TEXT runtime·tstart(SB),7,$0
 	MOVL	newm+4(SP), CX		// m
 	MOVL	m_g0(CX), DX		// g
 
-	// Set up SEH frame
-	PUSHL	$runtime·sigtramp(SB)
-	PUSHL	0(FS)
-	MOVL	SP, 0(FS)
-
 	// Layout new m scheduler stack on os stack.
 	MOVL	SP, AX
 	MOVL	AX, g_stackbase(DX)
@@ -264,14 +259,8 @@ TEXT runtime·tstart(SB),7,$0
 	CLD
 
 	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
-
 	CALL	runtime·mstart(SB)
 
-	// Pop SEH frame
-	MOVL	0(FS), SP
-	POPL	0(FS)
-	POPL	CX
-
 	RET
 
 // uint32 tstart_stdcall(M *newm);
@@ -296,3 +285,32 @@ TEXT runtime·setldt(SB),7,$0
 	MOVL	address+4(FP), CX
 	MOVL	CX, 0x14(FS)
 	RET
+
+// void install_exception_handler()
+TEXT runtime·install_exception_handler(SB),7,$0
+	get_tls(CX)
+	MOVL	m(CX), CX		// m
+
+	// Set up SEH frame
+	MOVL	m_seh(CX), DX
+	MOVL	$runtime·sigtramp(SB), AX
+	MOVL	AX, seh_handler(DX)
+	MOVL	0(FS), AX
+	MOVL	AX, seh_prev(DX)
+
+	// Install it
+	MOVL	DX, 0(FS)
+
+	RET
+
+// void remove_exception_handler()
+TEXT runtime·remove_exception_handler(SB),7,$0
+	get_tls(CX)
+	MOVL	m(CX), CX		// m
+
+	// Remove SEH frame
+	MOVL	m_seh(CX), DX
+	MOVL	seh_prev(DX), AX
+	MOVL	AX, 0(FS)
+
+	RET
diff --git a/src/pkg/runtime/sys_windows_amd64.s b/src/pkg/runtime/sys_windows_amd64.s
index 11909cd..fe88f3b 100644
--- a/src/pkg/runtime/sys_windows_amd64.s
+++ b/src/pkg/runtime/sys_windows_amd64.s
@@ -272,13 +272,13 @@ TEXT runtime·callbackasm(SB),7,$0
 	MOVQ	R15, 0(SP)
 
 	// prepare call stack.  use SUBQ to hide from stack frame checks
-	// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+	// cgocallback(Go func, void *frame, uintptr framesize)
 	SUBQ	$24, SP
 	MOVQ	DX, 16(SP)	// uintptr framesize
 	MOVQ	CX, 8(SP)   // void *frame
-	MOVQ	AX, 0(SP)    // void (*fn)(void*)
+	MOVQ	AX, 0(SP)    // Go func
 	CLD
-	CALL  runtime·cgocallback(SB)
+	CALL  runtime·cgocallback_gofunc(SB)
 	MOVQ	0(SP), AX
 	MOVQ	8(SP), CX
 	MOVQ	16(SP), DX
@@ -328,7 +328,6 @@ TEXT runtime·tstart_stdcall(SB),7,$0
 	// Someday the convention will be D is always cleared.
 	CLD
 
-	CALL	runtime·setstacklimits(SB)
 	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
 	CALL	runtime·mstart(SB)
 
@@ -337,6 +336,13 @@ TEXT runtime·tstart_stdcall(SB),7,$0
 
 // set tls base to DI
 TEXT runtime·settls(SB),7,$0
-	CALL	runtime·setstacklimits(SB)
 	MOVQ	DI, 0x28(GS)
 	RET
+
+// void install_exception_handler()
+TEXT runtime·install_exception_handler(SB),7,$0
+	CALL	runtime·setstacklimits(SB)
+	RET
+
+TEXT runtime·remove_exception_handler(SB),7,$0
+	RET
diff --git a/src/pkg/runtime/syscall_windows_test.go b/src/pkg/runtime/syscall_windows_test.go
index c8327fd..f04d2cd 100644
--- a/src/pkg/runtime/syscall_windows_test.go
+++ b/src/pkg/runtime/syscall_windows_test.go
@@ -112,9 +112,10 @@ func Test64BitReturnStdCall(t *testing.T) {
 
 func TestCDecl(t *testing.T) {
 	var buf [50]byte
+	fmtp, _ := syscall.BytePtrFromString("%d %d %d")
 	a, _, _ := GetDLL(t, "user32.dll").Proc("wsprintfA").Call(
 		uintptr(unsafe.Pointer(&buf[0])),
-		uintptr(unsafe.Pointer(syscall.StringBytePtr("%d %d %d"))),
+		uintptr(unsafe.Pointer(fmtp)),
 		1000, 2000, 3000)
 	if string(buf[:a]) != "1000 2000 3000" {
 		t.Error("cdecl USER32.wsprintfA returns", a, "buf=", buf[:a])
diff --git a/src/pkg/runtime/thread_darwin.c b/src/pkg/runtime/thread_darwin.c
index 6a83e48..adb1ffe 100644
--- a/src/pkg/runtime/thread_darwin.c
+++ b/src/pkg/runtime/thread_darwin.c
@@ -9,8 +9,8 @@
 
 extern SigTab runtime·sigtab[];
 
-static Sigset sigset_all = ~(Sigset)0;
 static Sigset sigset_none;
+static Sigset sigset_all = ~(Sigset)0;
 static Sigset sigset_prof = 1<<(SIGPROF-1);
 
 static void
@@ -50,11 +50,8 @@ runtime·semacreate(void)
 void
 runtime·osinit(void)
 {
-	// Register our thread-creation callback (see sys_darwin_{amd64,386}.s)
-	// but only if we're not using cgo.  If we are using cgo we need
-	// to let the C pthread libary install its own thread-creation callback.
-	if(!runtime·iscgo)
-		runtime·bsdthread_register();
+	// bsdthread_register delayed until end of goenvs so that we
+	// can look at the environment first.
 
 	// Use sysctl to fetch hw.ncpu.
 	uint32 mib[2];
@@ -75,22 +72,34 @@ void
 runtime·goenvs(void)
 {
 	runtime·goenvs_unix();
+
+	// Register our thread-creation callback (see sys_darwin_{amd64,386}.s)
+	// but only if we're not using cgo.  If we are using cgo we need
+	// to let the C pthread libary install its own thread-creation callback.
+	if(!runtime·iscgo) {
+		if(runtime·bsdthread_register() != 0) {
+			if(runtime·getenv("DYLD_INSERT_LIBRARIES"))
+				runtime·throw("runtime: bsdthread_register error (unset DYLD_INSERT_LIBRARIES)");
+			runtime·throw("runtime: bsdthread_register error");
+		}
+	}
+
 }
 
 void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
 {
 	int32 errno;
 	Sigset oset;
 
-	m->tls[0] = m->id;	// so 386 asm can find it
+	mp->tls[0] = mp->id;	// so 386 asm can find it
 	if(0){
-		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, m->id, m->tls[0], &m);
+		runtime·printf("newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n",
+			stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp);
 	}
 
 	runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset);
-	errno = runtime·bsdthread_create(stk, m, g, fn);
+	errno = runtime·bsdthread_create(stk, mp, mp->g0, runtime·mstart);
 	runtime·sigprocmask(SIG_SETMASK, &oset, nil);
 
 	if(errno < 0) {
@@ -100,17 +109,30 @@ runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
 }
 
 // Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+void
+runtime·mpreinit(M *mp)
+{
+	mp->gsignal = runtime·malg(32*1024);	// OS X wants >=8K, Linux >=2K
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
 void
 runtime·minit(void)
 {
 	// Initialize signal handling.
-	m->gsignal = runtime·malg(32*1024);	// OS X wants >=8K, Linux >=2K
-	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
+	runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
 
-	if(m->profilehz > 0)
-		runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
-	else
-		runtime·sigprocmask(SIG_SETMASK, &sigset_prof, nil);
+	runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
+	runtime·setprof(m->profilehz > 0);
+}
+
+// Called from dropm to undo the effect of an minit.
+void
+runtime·unminit(void)
+{
+	runtime·signalstack(nil, 0);
 }
 
 // Mach IPC, to get at semaphores
@@ -431,10 +453,11 @@ runtime·sigpanic(void)
 	runtime·panicstring(runtime·sigtab[g->sig].name);
 }
 
-// TODO(rsc): place holder to fix build.
+#pragma textflag 7
 void
 runtime·osyield(void)
 {
+	runtime·usleep(1);
 }
 
 uintptr
@@ -488,12 +511,22 @@ runtime·badcallback(void)
 	runtime·write(2, badcallback, sizeof badcallback - 1);
 }
 
-static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
+static int8 badsignal[] = "runtime: signal received on thread not created by Go: ";
 
 // This runs on a foreign stack, without an m or a g.  No stack split.
 #pragma textflag 7
 void
-runtime·badsignal(void)
+runtime·badsignal(int32 sig)
 {
+	if (sig == SIGPROF) {
+		return;  // Ignore SIGPROFs intended for a non-Go thread.
+	}
 	runtime·write(2, badsignal, sizeof badsignal - 1);
+	if (0 <= sig && sig < NSIG) {
+		// Call runtime·findnull dynamically to circumvent static stack size check.
+		static int32 (*findnull)(byte*) = runtime·findnull;
+		runtime·write(2, runtime·sigtab[sig].name, findnull((byte*)runtime·sigtab[sig].name));
+	}
+	runtime·write(2, "\n", 1);
+	runtime·exit(1);
 }
diff --git a/src/pkg/runtime/thread_freebsd.c b/src/pkg/runtime/thread_freebsd.c
index 4c54617..3ae14ee 100644
--- a/src/pkg/runtime/thread_freebsd.c
+++ b/src/pkg/runtime/thread_freebsd.c
@@ -13,8 +13,8 @@ extern int32 runtime·sys_umtx_op(uint32*, int32, uint32, void*, void*);
 #define	CTL_HW	6
 #define	HW_NCPU	3
 
+static Sigset sigset_none;
 static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, };
-static Sigset sigset_none = { 0, 0, 0, 0, };
 
 static int32
 getncpu(void)
@@ -77,32 +77,33 @@ runtime·futexwakeup(uint32 *addr, uint32 cnt)
 void runtime·thr_start(void*);
 
 void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
 {
 	ThrParam param;
 	Sigset oset;
 
-	USED(fn);	// thr_start assumes fn == mstart
-	USED(g);	// thr_start assumes g == m->g0
-
 	if(0){
-		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, m->id, m->tls[0], &m);
+		runtime·printf("newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n",
+			stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp);
 	}
 
 	runtime·sigprocmask(&sigset_all, &oset);
 	runtime·memclr((byte*)&param, sizeof param);
 
 	param.start_func = runtime·thr_start;
-	param.arg = m;
-	param.stack_base = (int8*)g->stackbase;
-	param.stack_size = (byte*)stk - (byte*)g->stackbase;
-	param.child_tid = (intptr*)&m->procid;
+	param.arg = (byte*)mp;
+	
+	// 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.child_tid = (intptr*)&mp->procid;
 	param.parent_tid = nil;
-	param.tls_base = (int8*)&m->tls[0];
-	param.tls_size = sizeof m->tls;
+	param.tls_base = (void*)&mp->tls[0];
+	param.tls_size = sizeof mp->tls;
 
-	m->tls[0] = m->id;	// so 386 asm can find it
+	mp->tls[0] = mp->id;	// so 386 asm can find it
 
 	runtime·thr_new(&param, sizeof param);
 	runtime·sigprocmask(&oset, nil);
@@ -121,15 +122,30 @@ runtime·goenvs(void)
 }
 
 // Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+void
+runtime·mpreinit(M *mp)
+{
+	mp->gsignal = runtime·malg(32*1024);
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
 void
 runtime·minit(void)
 {
 	// Initialize signal handling
-	m->gsignal = runtime·malg(32*1024);
-	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
+	runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
 	runtime·sigprocmask(&sigset_none, nil);
 }
 
+// Called from dropm to undo the effect of an minit.
+void
+runtime·unminit(void)
+{
+	runtime·signalstack(nil, 0);
+}
+
 void
 runtime·sigpanic(void)
 {
@@ -206,12 +222,22 @@ runtime·badcallback(void)
 	runtime·write(2, badcallback, sizeof badcallback - 1);
 }
 
-static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
+static int8 badsignal[] = "runtime: signal received on thread not created by Go: ";
 
 // This runs on a foreign stack, without an m or a g.  No stack split.
 #pragma textflag 7
 void
-runtime·badsignal(void)
+runtime·badsignal(int32 sig)
 {
+	if (sig == SIGPROF) {
+		return;  // Ignore SIGPROFs intended for a non-Go thread.
+	}
 	runtime·write(2, badsignal, sizeof badsignal - 1);
+	if (0 <= sig && sig < NSIG) {
+		// Call runtime·findnull dynamically to circumvent static stack size check.
+		static int32 (*findnull)(byte*) = runtime·findnull;
+		runtime·write(2, runtime·sigtab[sig].name, findnull((byte*)runtime·sigtab[sig].name));
+	}
+	runtime·write(2, "\n", 1);
+	runtime·exit(1);
 }
diff --git a/src/pkg/runtime/thread_linux.c b/src/pkg/runtime/thread_linux.c
index 858be70..78ddef8 100644
--- a/src/pkg/runtime/thread_linux.c
+++ b/src/pkg/runtime/thread_linux.c
@@ -13,8 +13,8 @@ int32 runtime·open(uint8*, int32, int32);
 int32 runtime·close(int32);
 int32 runtime·read(int32, void*, int32);
 
-static Sigset sigset_all = { ~(uint32)0, ~(uint32)0 };
 static Sigset sigset_none;
+static Sigset sigset_all = { ~(uint32)0, ~(uint32)0 };
 
 // Linux futex.
 //
@@ -80,33 +80,23 @@ runtime·futexwakeup(uint32 *addr, uint32 cnt)
 	*(int32*)0x1006 = 0x1006;
 }
 
+extern runtime·sched_getaffinity(uintptr pid, uintptr len, uintptr *buf);
 static int32
 getproccount(void)
 {
-	int32 fd, rd, cnt, cpustrlen;
-	byte *cpustr, *pos, *bufpos;
-	byte buf[256];
+	uintptr buf[16], t;
+	int32 r, cnt, i;
 
-	fd = runtime·open((byte*)"/proc/stat", O_RDONLY|O_CLOEXEC, 0);
-	if(fd == -1)
-		return 1;
 	cnt = 0;
-	bufpos = buf;
-	cpustr = (byte*)"\ncpu";
-	cpustrlen = runtime·findnull(cpustr);
-	for(;;) {
-		rd = runtime·read(fd, bufpos, sizeof(buf)-cpustrlen);
-		if(rd == -1)
-			break;
-		bufpos[rd] = 0;
-		for(pos=buf; pos=runtime·strstr(pos, cpustr); cnt++, pos++) {
-		}
-		if(rd < cpustrlen)
-			break;
-		runtime·memmove(buf, bufpos+rd-cpustrlen+1, cpustrlen-1);
-		bufpos = buf+cpustrlen-1;
+	r = runtime·sched_getaffinity(0, sizeof(buf), buf);
+	if(r > 0)
+	for(i = 0; i < r/sizeof(buf[0]); i++) {
+		t = buf[i];
+		t = t - ((t >> 1) & 0x5555555555555555ULL);
+		t = (t & 0x3333333333333333ULL) + ((t >> 2) & 0x3333333333333333ULL);
+		cnt += (int32)((((t + (t >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56);
 	}
-	runtime·close(fd);
+
 	return cnt ? cnt : 1;
 }
 
@@ -134,7 +124,7 @@ enum
 };
 
 void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
 {
 	int32 ret;
 	int32 flags;
@@ -150,16 +140,16 @@ runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
 		| CLONE_THREAD	/* revisit - okay for now */
 		;
 
-	m->tls[0] = m->id;	// so 386 asm can find it
+	mp->tls[0] = mp->id;	// so 386 asm can find it
 	if(0){
-		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p clone=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, runtime·clone, m->id, m->tls[0], &m);
+		runtime·printf("newosproc stk=%p m=%p g=%p clone=%p id=%d/%d ostk=%p\n",
+			stk, mp, mp->g0, runtime·clone, mp->id, (int32)mp->tls[0], &mp);
 	}
 
 	// Disable signals during clone, so that the new thread starts
 	// with signals disabled.  It will enable them in minit.
 	runtime·rtsigprocmask(SIG_SETMASK, &sigset_all, &oset, sizeof oset);
-	ret = runtime·clone(flags, stk, m, g, fn);
+	ret = runtime·clone(flags, stk, mp, mp->g0, runtime·mstart);
 	runtime·rtsigprocmask(SIG_SETMASK, &oset, nil, sizeof oset);
 
 	if(ret < 0) {
@@ -181,13 +171,28 @@ runtime·goenvs(void)
 }
 
 // Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+void
+runtime·mpreinit(M *mp)
+{
+	mp->gsignal = runtime·malg(32*1024);	// OS X wants >=8K, Linux >=2K
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
 void
 runtime·minit(void)
 {
 	// Initialize signal handling.
-	m->gsignal = runtime·malg(32*1024);	// OS X wants >=8K, Linux >=2K
-	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
-	runtime·rtsigprocmask(SIG_SETMASK, &sigset_none, nil, sizeof sigset_none);
+	runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+	runtime·rtsigprocmask(SIG_SETMASK, &sigset_none, nil, sizeof(Sigset));
+}
+
+// Called from dropm to undo the effect of an minit.
+void
+runtime·unminit(void)
+{
+	runtime·signalstack(nil, 0);
 }
 
 void
@@ -266,12 +271,22 @@ runtime·badcallback(void)
 	runtime·write(2, badcallback, sizeof badcallback - 1);
 }
 
-static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
+static int8 badsignal[] = "runtime: signal received on thread not created by Go: ";
 
 // This runs on a foreign stack, without an m or a g.  No stack split.
 #pragma textflag 7
 void
-runtime·badsignal(void)
+runtime·badsignal(int32 sig)
 {
+	if (sig == SIGPROF) {
+		return;  // Ignore SIGPROFs intended for a non-Go thread.
+	}
 	runtime·write(2, badsignal, sizeof badsignal - 1);
+	if (0 <= sig && sig < NSIG) {
+		// Call runtime·findnull dynamically to circumvent static stack size check.
+		static int32 (*findnull)(byte*) = runtime·findnull;
+		runtime·write(2, runtime·sigtab[sig].name, findnull((byte*)runtime·sigtab[sig].name));
+	}
+	runtime·write(2, "\n", 1);
+	runtime·exit(1);
 }
diff --git a/src/pkg/runtime/thread_netbsd.c b/src/pkg/runtime/thread_netbsd.c
index 1b2df85..f333c6d 100644
--- a/src/pkg/runtime/thread_netbsd.c
+++ b/src/pkg/runtime/thread_netbsd.c
@@ -11,7 +11,7 @@ enum
 	ESRCH = 3,
 	ENOTSUP = 91,
 
-	// From NetBSD's sys/time.h
+	// From NetBSD's <sys/time.h>
 	CLOCK_REALTIME = 0,
 	CLOCK_VIRTUAL = 1,
 	CLOCK_PROF = 2,
@@ -20,9 +20,15 @@ enum
 
 extern SigTab runtime·sigtab[];
 
-extern int64 runtime·rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-extern int32 runtime·thrsleep(void *ident, int32 clock_id, void *tsp, void *lock);
-extern int32 runtime·thrwakeup(void *ident, int32 n);
+static Sigset sigset_none;
+static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, };
+
+extern void runtime·getcontext(UcontextT *context);
+extern int32 runtime·lwp_create(UcontextT *context, uintptr flags, void *lwpid);
+extern void runtime·lwp_mcontext_init(void *mc, void *stack, M *mp, G *gp, void (*fn)(void));
+extern int32 runtime·lwp_park(Timespec *abstime, int32 unpark, void *hint, void *unparkhint);
+extern int32 runtime·lwp_unpark(int32 lwp, void *hint);
+extern int32 runtime·lwp_self(void);
 
 // From NetBSD's <sys/sysctl.h>
 #define	CTL_HW	6
@@ -68,13 +74,30 @@ runtime·semasleep(int64 ns)
 		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);
-			else {
+			if(ns < 0) {
+				// TODO(jsing) - potential deadlock!
+				//
+				// There is a potential deadlock here since we
+				// have to release the waitsemalock mutex
+				// before we call lwp_park() to suspend the
+				// thread. This allows another thread to
+				// release the lock and call lwp_unpark()
+				// before the thread is actually suspended.
+				// If this occurs the current thread will end
+				// up sleeping indefinitely. Unfortunately
+				// 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);
+			} else {
 				ns += runtime·nanotime();
 				ts.tv_sec = ns/1000000000LL;
 				ts.tv_nsec = ns%1000000000LL;
-				runtime·thrsleep(&m->waitsemacount, CLOCK_REALTIME, &ts, &m->waitsemalock);
+				// TODO(jsing) - potential deadlock!
+				// See above for details.
+				runtime·atomicstore(&m->waitsemalock, 0);
+				runtime·lwp_park(&ts, 0, &m->waitsemacount, nil);
 			}
 			// reacquire lock
 			while(runtime·xchg(&m->waitsemalock, 1))
@@ -112,39 +135,41 @@ runtime·semawakeup(M *mp)
 	while(runtime·xchg(&mp->waitsemalock, 1))
 		runtime·osyield();
 	mp->waitsemacount++;
-	ret = runtime·thrwakeup(&mp->waitsemacount, 1);
+	// 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);
 	// spin-mutex unlock
 	runtime·atomicstore(&mp->waitsemalock, 0);
 }
 
-// From NetBSD's sys/param.h
-#define	RFPROC		(1<<4)	/* change child (else changes curproc) */
-#define	RFMEM		(1<<5)	/* share `address space' */
-#define	RFNOWAIT	(1<<6)	/* parent need not wait() on child */
-#define	RFTHREAD	(1<<13)	/* create a thread, not a process */
-
 void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
 {
-	int32 flags;
+	UcontextT uc;
 	int32 ret;
 
-	flags = RFPROC | RFTHREAD | RFMEM | RFNOWAIT;
-
-	if (0) {
+	if(0) {
 		runtime·printf(
-			"newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, m->id, m->tls[0], &m);
+			"newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n",
+			stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp);
 	}
 
-	m->tls[0] = m->id;	// so 386 asm can find it
+	mp->tls[0] = mp->id;	// so 386 asm can find it
+
+	runtime·getcontext(&uc);
+	
+	uc.uc_flags = _UC_SIGMASK | _UC_CPU;
+	uc.uc_link = nil;
+	uc.uc_sigmask = sigset_all;
+
+	runtime·lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp->g0, runtime·mstart);
 
-	if((ret = runtime·rfork_thread(flags, stk, m, g, fn)) < 0) {
+	ret = runtime·lwp_create(&uc, 0, &mp->procid);
+
+	if(ret < 0) {
 		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret);
-		if (ret == -ENOTSUP)
-			runtime·printf("runtime: is kern.rthreads disabled?\n");
 		runtime·throw("runtime.newosproc");
 	}
 }
@@ -162,12 +187,30 @@ runtime·goenvs(void)
 }
 
 // Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+void
+runtime·mpreinit(M *mp)
+{
+	mp->gsignal = runtime·malg(32*1024);
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
 void
 runtime·minit(void)
 {
+	m->procid = runtime·lwp_self();
+
 	// Initialize signal handling
-	m->gsignal = runtime·malg(32*1024);
-	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
+	runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+	runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
+}
+
+// Called from dropm to undo the effect of an minit.
+void
+runtime·unminit(void)
+{
+	runtime·signalstack(nil, 0);
 }
 
 void
@@ -224,12 +267,22 @@ runtime·badcallback(void)
 	runtime·write(2, badcallback, sizeof badcallback - 1);
 }
 
-static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
+static int8 badsignal[] = "runtime: signal received on thread not created by Go: ";
 
 // This runs on a foreign stack, without an m or a g.  No stack split.
 #pragma textflag 7
 void
-runtime·badsignal(void)
+runtime·badsignal(int32 sig)
 {
+	if (sig == SIGPROF) {
+		return;  // Ignore SIGPROFs intended for a non-Go thread.
+	}
 	runtime·write(2, badsignal, sizeof badsignal - 1);
+	if (0 <= sig && sig < NSIG) {
+		// Call runtime·findnull dynamically to circumvent static stack size check.
+		static int32 (*findnull)(byte*) = runtime·findnull;
+		runtime·write(2, runtime·sigtab[sig].name, findnull((byte*)runtime·sigtab[sig].name));
+	}
+	runtime·write(2, "\n", 1);
+	runtime·exit(1);
 }
diff --git a/src/pkg/runtime/thread_openbsd.c b/src/pkg/runtime/thread_openbsd.c
index d0f9472..700c481 100644
--- a/src/pkg/runtime/thread_openbsd.c
+++ b/src/pkg/runtime/thread_openbsd.c
@@ -20,8 +20,11 @@ enum
 
 extern SigTab runtime·sigtab[];
 
-extern int64 runtime·rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-extern int32 runtime·thrsleep(void *ident, int32 clock_id, void *tsp, void *lock);
+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·thrsleep(void *ident, int32 clock_id, void *tsp, void *lock, const int32 *abort);
 extern int32 runtime·thrwakeup(void *ident, int32 n);
 
 // From OpenBSD's <sys/sysctl.h>
@@ -69,12 +72,12 @@ runtime·semasleep(int64 ns)
 			// sleep until semaphore != 0 or timeout.
 			// thrsleep unlocks m->waitsemalock.
 			if(ns < 0)
-				runtime·thrsleep(&m->waitsemacount, 0, nil, &m->waitsemalock);
+				runtime·thrsleep(&m->waitsemacount, 0, nil, &m->waitsemalock, nil);
 			else {
 				ns += runtime·nanotime();
 				ts.tv_sec = ns/1000000000LL;
 				ts.tv_nsec = ns%1000000000LL;
-				runtime·thrsleep(&m->waitsemacount, CLOCK_REALTIME, &ts, &m->waitsemalock);
+				runtime·thrsleep(&m->waitsemacount, CLOCK_REALTIME, &ts, &m->waitsemalock, nil);
 			}
 			// reacquire lock
 			while(runtime·xchg(&m->waitsemalock, 1))
@@ -119,29 +122,30 @@ runtime·semawakeup(M *mp)
 	runtime·atomicstore(&mp->waitsemalock, 0);
 }
 
-// From OpenBSD's sys/param.h
-#define	RFPROC		(1<<4)	/* change child (else changes curproc) */
-#define	RFMEM		(1<<5)	/* share `address space' */
-#define	RFNOWAIT	(1<<6)	/* parent need not wait() on child */
-#define	RFTHREAD	(1<<13)	/* create a thread, not a process */
-
 void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
 {
-	int32 flags;
+	Tfork param;
+	Sigset oset;
 	int32 ret;
 
-	flags = RFPROC | RFTHREAD | RFMEM | RFNOWAIT;
-
-	if (0) {
+	if(0) {
 		runtime·printf(
-			"newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, m->id, m->tls[0], &m);
+			"newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n",
+			stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp);
 	}
 
-	m->tls[0] = m->id;	// so 386 asm can find it
+	mp->tls[0] = mp->id;	// so 386 asm can find it
+
+	param.tf_tcb = (byte*)&mp->tls[0];
+	param.tf_tid = (int32*)&mp->procid;
+	param.tf_stack = stk;
 
-	if((ret = runtime·rfork_thread(flags, stk, m, g, fn)) < 0) {
+	oset = runtime·sigprocmask(SIG_SETMASK, sigset_all);
+	ret = runtime·tfork((byte*)&param, sizeof(param), mp, mp->g0, runtime·mstart);
+	runtime·sigprocmask(SIG_SETMASK, oset);
+
+	if(ret < 0) {
 		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret);
 		if (ret == -ENOTSUP)
 			runtime·printf("runtime: is kern.rthreads disabled?\n");
@@ -162,12 +166,28 @@ runtime·goenvs(void)
 }
 
 // Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+void
+runtime·mpreinit(M *mp)
+{
+	mp->gsignal = runtime·malg(32*1024);
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
 void
 runtime·minit(void)
 {
 	// Initialize signal handling
-	m->gsignal = runtime·malg(32*1024);
-	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
+	runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
+	runtime·sigprocmask(SIG_SETMASK, sigset_none);
+}
+
+// Called from dropm to undo the effect of an minit.
+void
+runtime·unminit(void)
+{
+	runtime·signalstack(nil, 0);
 }
 
 void
@@ -224,12 +244,22 @@ runtime·badcallback(void)
 	runtime·write(2, badcallback, sizeof badcallback - 1);
 }
 
-static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
+static int8 badsignal[] = "runtime: signal received on thread not created by Go: ";
 
 // This runs on a foreign stack, without an m or a g.  No stack split.
 #pragma textflag 7
 void
-runtime·badsignal(void)
+runtime·badsignal(int32 sig)
 {
+	if (sig == SIGPROF) {
+		return;  // Ignore SIGPROFs intended for a non-Go thread.
+	}
 	runtime·write(2, badsignal, sizeof badsignal - 1);
+	if (0 <= sig && sig < NSIG) {
+		// Call runtime·findnull dynamically to circumvent static stack size check.
+		static int32 (*findnull)(byte*) = runtime·findnull;
+		runtime·write(2, runtime·sigtab[sig].name, findnull((byte*)runtime·sigtab[sig].name));
+	}
+	runtime·write(2, "\n", 1);
+	runtime·exit(1);
 }
diff --git a/src/pkg/runtime/thread_plan9.c b/src/pkg/runtime/thread_plan9.c
index 3b0dca6..7f94623 100644
--- a/src/pkg/runtime/thread_plan9.c
+++ b/src/pkg/runtime/thread_plan9.c
@@ -7,12 +7,37 @@
 #include "arch_GOARCH.h"
 
 int8 *goos = "plan9";
+extern SigTab runtime·sigtab[];
 
+int32 runtime·postnote(int32, int8*);
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+void
+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));
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
 void
 runtime·minit(void)
 {
+	// Mask all SSE floating-point exceptions
+	// when running on the 64-bit kernel.
+	runtime·setfpmasks();
+}
+
+// Called from dropm to undo the effect of an minit.
+void
+runtime·unminit(void)
+{
 }
 
+
 static int32
 getproccount(void)
 {
@@ -36,10 +61,30 @@ getproccount(void)
 	return ncpu > 0 ? ncpu : 1;
 }
 
+static int32
+getpid(void)
+{
+	byte b[20], *c;
+	int32 fd;
+
+	runtime·memclr(b, sizeof(b));
+	fd = runtime·open((byte*)"#c/pid", 0);
+	if(fd >= 0) {
+		runtime·read(fd, b, sizeof(b));
+		runtime·close(fd);
+	}
+	c = b;
+	while(*c == ' ' || *c == '\t')
+		c++;
+	return runtime·atoi(c);
+}
+
 void
 runtime·osinit(void)
 {
 	runtime·ncpu = getproccount();
+	m->procid = getpid();
+	runtime·notify(runtime·sigtramp);
 }
 
 void
@@ -52,6 +97,7 @@ runtime·initsig(void)
 {
 }
 
+#pragma textflag 7
 void
 runtime·osyield(void)
 {
@@ -69,34 +115,6 @@ runtime·usleep(uint32 µs)
 	runtime·sleep(ms);
 }
 
-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((byte*)"/dev/bintime", OREAD|OCEXEC)) < 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;
-}
-
 void
 time·now(int64 sec, int32 nsec)
 {
@@ -109,48 +127,111 @@ time·now(int64 sec, int32 nsec)
 	FLUSH(&nsec);
 }
 
-extern Tos *_tos;
 void
-runtime·exit(int32)
+runtime·itoa(int32 n, byte *p, uint32 len)
 {
-	int32 fd;
+	byte *q, c;
+	uint32 i;
+
+	if(len <= 1)
+		return;
+
+	runtime·memclr(p, len);
+	q = p;
+
+	if(n==0) {
+		*q++ = '0';
+		USED(q);
+		return;
+	}
+	if(n < 0) {
+		*q++ = '-';
+		p++;
+		n = -n;
+	}
+	for(i=0; n > 0 && i < len; i++) {
+		*q++ = '0' + (n%10);
+		n = n/10;
+	}
+	for(q--; q >= p; ) {
+		c = *p;
+		*p++ = *q;
+		*q-- = c;
+	}
+}
+
+void
+runtime·goexitsall(int8 *status)
+{
+	M *mp;
+	int32 pid;
+
+	pid = getpid();
+	for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink)
+		if(mp->procid != pid)
+			runtime·postnote(mp->procid, status);
+}
+
+int32
+runtime·postnote(int32 pid, int8* msg)
+{
+	int32 fd, len;
 	uint8 buf[128];
 	uint8 tmp[16];
 	uint8 *p, *q;
-	int32 pid;
 
 	runtime·memclr(buf, sizeof buf);
-	runtime·memclr(tmp, sizeof tmp);
-	pid = _tos->pid;
 
-	/* build path string /proc/pid/notepg */
-	for(q=tmp; pid > 0;) {
-		*q++ = '0' + (pid%10);
-		pid = pid/10;
-	}
+	/* build path string /proc/pid/note */
+	q = tmp;
 	p = buf;
+	runtime·itoa(pid, tmp, sizeof tmp);
 	runtime·memmove((void*)p, (void*)"/proc/", 6);
-	p += 6;
-	for(q--; q >= tmp;)
-		*p++ = *q--;
-	runtime·memmove((void*)p, (void*)"/notepg", 7);
+	for(p += 6; *p++ = *q++; );
+	p--;
+	runtime·memmove((void*)p, (void*)"/note", 5);
 
-	/* post interrupt note */
 	fd = runtime·open(buf, OWRITE);
-	runtime·write(fd, "interrupt", 9);
-	runtime·exits(nil);
+	if(fd < 0)
+		return -1;
+
+	len = runtime·findnull((byte*)msg);
+	if(runtime·write(fd, msg, len) != len) {
+		runtime·close(fd);
+		return -1;
+	}
+	runtime·close(fd);
+	return 0;
 }
 
 void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+runtime·exit(int32 e)
 {
-	m->tls[0] = m->id;	// so 386 asm can find it
+	byte tmp[16];
+	int8 *status;
+ 
+	if(e == 0)
+		status = "";
+	else {
+		/* build error string */
+		runtime·itoa(e, tmp, sizeof tmp);
+		status = (int8*)tmp;
+	}
+
+	runtime·goexitsall(status);
+	runtime·exits(status);
+}
+
+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 fn=%p rfork=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, runtime·rfork, m->id, m->tls[0], &m);
+		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);
 	}
 
-	if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0)
+	if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, mp, mp->g0, runtime·mstart) < 0)
 		runtime·throw("newosproc: rfork failed");
 }
 
@@ -167,36 +248,18 @@ runtime·semasleep(int64 ns)
 	int32 ms;
 
 	if(ns >= 0) {
-		// TODO: Plan 9 needs a new system call, tsemacquire.
-		// The kernel implementation is the same as semacquire
-		// except with a tsleep and check for timeout.
-		// It would be great if the implementation returned the
-		// value that was added to the semaphore, so that on
-		// timeout the return value would be 0, on success 1.
-		// Then the error string does not have to be parsed
-		// to detect timeout.
-		//
-		// If a negative time indicates no timeout, then
-		// semacquire can be implemented (in the kernel)
-		// as tsemacquire(p, v, -1).
-		runtime·throw("semasleep: timed sleep not implemented on Plan 9");
-
-		/*
-		if(ns < 0)
-			ms = -1;
-		else if(ns/1000 > 0x7fffffffll)
+		if(ns/1000000 > 0x7fffffffll)
 			ms = 0x7fffffff;
 		else
-			ms = ns/1000;
-		ret = runtime·plan9_tsemacquire(&m->waitsemacount, 1, ms);
+			ms = ns/1000000;
+		ret = runtime·plan9_tsemacquire(&m->waitsemacount, ms);
 		if(ret == 1)
 			return 0;  // success
 		return -1;  // timeout or interrupted
-		*/
 	}
 
 	while(runtime·plan9_semacquire(&m->waitsemacount, 1) < 0) {
-		/* interrupted; try again */
+		/* interrupted; try again (c.f. lock_sema.c) */
 	}
 	return 0;  // success
 }
@@ -213,15 +276,15 @@ os·sigpipe(void)
 	runtime·throw("too many writes on closed pipe");
 }
 
-/*
- * placeholder - once notes are implemented,
- * a signal generating a panic must appear as
- * a call to this function for correct handling by
- * traceback.
- */
 void
 runtime·sigpanic(void)
 {
+	if(g->sigpc == 0)
+		runtime·panicstring("call of nil func value");
+	runtime·panicstring(m->notesig);
+
+	if(g->sig == 1 || g->sig == 2)
+		runtime·throw("fault");
 }
 
 int32
@@ -266,4 +329,5 @@ void
 runtime·badsignal(void)
 {
 	runtime·pwrite(2, badsignal, sizeof badsignal - 1, -1LL);
+	runtime·exits(badsignal);
 }
diff --git a/src/pkg/runtime/thread_windows.c b/src/pkg/runtime/thread_windows.c
index f684d37..ae4e82e 100644
--- a/src/pkg/runtime/thread_windows.c
+++ b/src/pkg/runtime/thread_windows.c
@@ -135,6 +135,7 @@ runtime·write(int32 fd, void *buf, int32 n)
 	return written;
 }
 
+#pragma textflag 7
 void
 runtime·osyield(void)
 {
@@ -186,28 +187,43 @@ runtime·semacreate(void)
 #define STACK_SIZE_PARAM_IS_A_RESERVATION ((uintptr)0x00010000)
 
 void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+runtime·newosproc(M *mp, void *stk)
 {
 	void *thandle;
 
 	USED(stk);
-	USED(g);	// assuming g = m->g0
-	USED(fn);	// assuming fn = mstart
 
 	thandle = runtime·stdcall(runtime·CreateThread, 6,
-		nil, (uintptr)0x20000, runtime·tstart_stdcall, m,
+		nil, (uintptr)0x20000, runtime·tstart_stdcall, mp,
 		STACK_SIZE_PARAM_IS_A_RESERVATION, 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");
 	}
-	runtime·atomicstorep(&m->thread, thandle);
+	runtime·atomicstorep(&mp->thread, thandle);
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+void
+runtime·mpreinit(M *mp)
+{
+	USED(mp);
 }
 
 // Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
 void
 runtime·minit(void)
 {
+	runtime·install_exception_handler();
+}
+
+// Called from dropm to undo the effect of an minit.
+void
+runtime·unminit(void)
+{
+	runtime·remove_exception_handler();
 }
 
 int64
diff --git a/src/pkg/runtime/time.goc b/src/pkg/runtime/time.goc
index b18902f..2babb17 100644
--- a/src/pkg/runtime/time.goc
+++ b/src/pkg/runtime/time.goc
@@ -11,6 +11,7 @@ package time
 #include "os_GOOS.h"
 #include "arch_GOARCH.h"
 #include "malloc.h"
+#include "race.h"
 
 static Timers timers;
 static void addtimer(Timer*);
@@ -23,14 +24,16 @@ static bool deltimer(Timer*);
 
 // Sleep puts the current goroutine to sleep for at least ns nanoseconds.
 func Sleep(ns int64) {
-	g->status = Gwaiting;
-	g->waitreason = "sleep";
-	runtime·tsleep(ns);
+	runtime·tsleep(ns, "sleep");
 }
 
 // startTimer adds t to the timer heap.
 func startTimer(t *Timer) {
+	if(raceenabled)
+		runtime·racerelease(t);
+	runtime·lock(&timers);
 	addtimer(t);
+	runtime·unlock(&timers);
 }
 
 // stopTimer removes t from the timer heap if it is there.
@@ -54,27 +57,28 @@ ready(int64 now, Eface e)
 	runtime·ready(e.data);
 }
 
+static FuncVal readyv = {(void(*)(void))ready};
+
 // Put the current goroutine to sleep for ns nanoseconds.
-// The caller must have set g->status and g->waitreason.
 void
-runtime·tsleep(int64 ns)
+runtime·tsleep(int64 ns, int8 *reason)
 {
 	Timer t;
 
-	if(ns <= 0) {
-		g->status = Grunning;
-		g->waitreason = nil;
+	if(ns <= 0)
 		return;
-	}
 
 	t.when = runtime·nanotime() + ns;
 	t.period = 0;
-	t.f = ready;
+	t.fv = &readyv;
 	t.arg.data = g;
+	runtime·lock(&timers);
 	addtimer(&t);
-	runtime·gosched();
+	runtime·park(runtime·unlock, &timers, reason);
 }
 
+static FuncVal timerprocv = {timerproc};
+
 // 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
@@ -83,7 +87,6 @@ addtimer(Timer *t)
 	int32 n;
 	Timer **nt;
 
-	runtime·lock(&timers);
 	if(timers.len >= timers.cap) {
 		// Grow slice.
 		n = 16;
@@ -109,9 +112,10 @@ addtimer(Timer *t)
 			runtime·ready(timers.timerproc);
 		}
 	}
-	if(timers.timerproc == nil)
-		timers.timerproc = runtime·newproc1((byte*)timerproc, nil, 0, 0, addtimer);
-	runtime·unlock(&timers);
+	if(timers.timerproc == nil) {
+		timers.timerproc = runtime·newproc1(&timerprocv, nil, 0, 0, addtimer);
+		timers.timerproc->issystem = true;
+	}
 }
 
 // Delete timer t from the heap.
@@ -182,26 +186,25 @@ timerproc(void)
 				siftdown(0);
 				t->i = -1;  // mark as removed
 			}
-			f = t->f;
+			f = (void*)t->fv->fn;
 			arg = t->arg;
 			runtime·unlock(&timers);
+			if(raceenabled)
+				runtime·raceacquire(t);
 			f(now, arg);
 			runtime·lock(&timers);
 		}
 		if(delta < 0) {
 			// No timers left - put goroutine to sleep.
 			timers.rescheduling = true;
-			g->status = Gwaiting;
-			g->waitreason = "timer goroutine (idle)";
-			runtime·unlock(&timers);
-			runtime·gosched();
+			runtime·park(runtime·unlock, &timers, "timer goroutine (idle)");
 			continue;
 		}
 		// At least one timer pending.  Sleep until then.
 		timers.sleeping = true;
 		runtime·noteclear(&timers.waitnote);
 		runtime·unlock(&timers);
-		runtime·entersyscall();
+		runtime·entersyscallblock();
 		runtime·notetsleep(&timers.waitnote, delta);
 		runtime·exitsyscall();
 	}
diff --git a/src/pkg/runtime/time_plan9_386.c b/src/pkg/runtime/time_plan9_386.c
new file mode 100644
index 0000000..a29d457
--- /dev/null
+++ b/src/pkg/runtime/time_plan9_386.c
@@ -0,0 +1,34 @@
+// 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"
+
+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((byte*)"/dev/bintime", OREAD|OCEXEC)) < 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
index 22e0bc3..dd85cc0 100644
--- a/src/pkg/runtime/traceback_arm.c
+++ b/src/pkg/runtime/traceback_arm.c
@@ -17,23 +17,23 @@ void _divu(void);
 void _modu(void);
 
 int32
-runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, int32 max)
+runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max)
 {
 	int32 i, n, iter;
 	uintptr pc, lr, tracepc, x;
-	byte *fp, *p;
+	byte *fp;
 	bool waspanic;
 	Stktop *stk;
 	Func *f;
-	
+
 	pc = (uintptr)pc0;
 	lr = (uintptr)lr0;
 	fp = nil;
 	waspanic = false;
 
 	// If the PC is goexit, the goroutine hasn't started yet.
-	if(pc == (uintptr)runtime·goexit) {
-		pc = (uintptr)g->entry;
+	if(pc == (uintptr)runtime·goexit && gp->fnstart != nil) {
+		pc = (uintptr)gp->fnstart->fn;
 		lr = (uintptr)runtime·goexit;
 	}
 
@@ -45,7 +45,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 	}
 
 	n = 0;
-	stk = (Stktop*)g->stackbase;
+	stk = (Stktop*)gp->stackbase;
 	for(iter = 0; iter < 100 && n < max; iter++) {	// iter avoids looping forever
 		// Typically:
 		//	pc is the PC of the running function.
@@ -57,52 +57,17 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 		if(pc == (uintptr)runtime·lessstack) {
 			// Hit top of stack segment.  Unwind to next segment.
 			pc = (uintptr)stk->gobuf.pc;
-			sp = stk->gobuf.sp;
+			sp = (byte*)stk->gobuf.sp;
 			lr = 0;
 			fp = nil;
-			if(pcbuf == nil)
+			if(pcbuf == nil && runtime·showframe(nil, gp == m->curg))
 				runtime·printf("----- stack segment boundary -----\n");
 			stk = (Stktop*)stk->stackbase;
 			continue;
 		}
 		
-		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) {
-			// Dangerous, but worthwhile: see if this is a closure by
-			// decoding the instruction stream.
-			//
-			// We check p < p+4 to avoid wrapping and faulting if
-			// we have lost track of where we are.
-			p = (byte*)pc;
-			if((pc&3) == 0 && p < p+4 &&
-			   runtime·mheap.arena_start < p &&
-			   p+4 < runtime·mheap.arena_used) {
-			   	x = *(uintptr*)p;
-				if((x&0xfffff000) == 0xe49df000) {
-					// End of closure:
-					// MOVW.P frame(R13), R15
-					pc = *(uintptr*)sp;
-					lr = 0;
-					sp += x & 0xfff;
-					fp = nil;
-					continue;
-				}
-				if((x&0xfffff000) == 0xe52de000 && lr == (uintptr)runtime·goexit) {
-					// Beginning of closure.
-					// Closure at top of stack, not yet started.
-					p += 5*4;
-					if((x&0xfff) != 4) {
-						// argument copying
-						p += 7*4;
-					}
-					if((byte*)pc < p && p < p+4 && p+4 < runtime·mheap.arena_used) {
-						pc = *(uintptr*)p;
-						fp = nil;
-						continue;
-					}
-				}
-			}
+		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil)
 			break;
-		}
 		
 		// Found an actual function.
 		if(lr == 0)
@@ -118,15 +83,17 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 		else if(pcbuf != nil)
 			pcbuf[n++] = pc;
 		else {
-			if(runtime·showframe(f)) {
+			if(runtime·showframe(f, gp == m->curg)) {
 				// Print during crash.
 				//	main(0x1, 0x2, 0x3)
 				//		/home/rsc/go/src/runtime/x.go:23 +0xf
 				tracepc = pc;	// back up to CALL instruction for funcline.
 				if(n > 0 && pc > f->entry && !waspanic)
 					tracepc -= sizeof(uintptr);
+				if(m->throwing && gp == m->curg)
+					runtime·printf("[fp=%p] ", fp);
 				runtime·printf("%S(", f->name);
-				for(i = 0; i < f->args; i++) {
+				for(i = 0; i < f->args/sizeof(uintptr); i++) {
 					if(i != 0)
 						runtime·prints(", ");
 					runtime·printhex(((uintptr*)fp)[1+i]);
@@ -146,22 +113,22 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 		
 		waspanic = f->entry == (uintptr)runtime·sigpanic;
 
-		if(pcbuf == nil && f->entry == (uintptr)runtime·newstack && g == m->g0) {
-			runtime·printf("----- newstack called from goroutine %d -----\n", m->curg->goid);
+		if(pcbuf == nil && f->entry == (uintptr)runtime·newstack && gp == m->g0) {
+			runtime·printf("----- newstack called from goroutine %D -----\n", m->curg->goid);
 			pc = (uintptr)m->morepc;
 			sp = (byte*)m->moreargp - sizeof(void*);
 			lr = (uintptr)m->morebuf.pc;
-			fp = m->morebuf.sp;
-			g = m->curg;
-			stk = (Stktop*)g->stackbase;
+			fp = (byte*)m->morebuf.sp;
+			gp = m->curg;
+			stk = (Stktop*)gp->stackbase;
 			continue;
 		}
 		
-		if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && g == m->g0) {
-			runtime·printf("----- lessstack called from goroutine %d -----\n", m->curg->goid);
-			g = m->curg;
-			stk = (Stktop*)g->stackbase;
-			sp = stk->gobuf.sp;
+		if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) {
+			runtime·printf("----- lessstack called from goroutine %D -----\n", m->curg->goid);
+			gp = m->curg;
+			stk = (Stktop*)gp->stackbase;
+			sp = (byte*)stk->gobuf.sp;
 			pc = (uintptr)stk->gobuf.pc;
 			fp = nil;
 			lr = 0;
@@ -182,9 +149,21 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 		// If this was deferproc or newproc, the caller had an extra 12.
 		if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
 			sp += 12;
+
+		// sighandler saves the lr on stack before faking a call to sigpanic
+		if(waspanic) {
+			x = *(uintptr *)sp;
+			sp += 4;
+			f = runtime·findfunc(pc);
+			if (f == nil) {
+				pc = x;
+			} else if (f->frame == 0)
+				lr = x;
+		}
 	}
 	
-	if(pcbuf == nil && (pc = g->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && g->goid != 1) {
+	if(pcbuf == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
+			&& runtime·showframe(f, gp == m->curg) && gp->goid != 1) {
 		runtime·printf("created by %S\n", f->name);
 		tracepc = pc;	// back up to CALL instruction for funcline.
 		if(n > 0 && pc > f->entry)
@@ -199,9 +178,15 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 }
 
 void
-runtime·traceback(byte *pc0, byte *sp, byte *lr, G *g)
+runtime·traceback(byte *pc0, byte *sp, byte *lr, G *gp)
 {
-	runtime·gentraceback(pc0, sp, lr, g, 0, nil, 100);
+	if(gp->status == Gsyscall) {
+		// Override signal registers if blocked in system call.
+		pc0 = gp->sched.pc;
+		sp = (byte*)gp->sched.sp;
+		lr = nil;
+	}
+	runtime·gentraceback(pc0, sp, lr, gp, 0, nil, 100);
 }
 
 // func caller(n int) (pc uintptr, file string, line int, ok bool)
diff --git a/src/pkg/runtime/traceback_x86.c b/src/pkg/runtime/traceback_x86.c
index be35bab..72603ae 100644
--- a/src/pkg/runtime/traceback_x86.c
+++ b/src/pkg/runtime/traceback_x86.c
@@ -8,7 +8,6 @@
 #include "arch_GOARCH.h"
 #include "malloc.h"
 
-static uintptr isclosureentry(uintptr);
 void runtime·deferproc(void);
 void runtime·newproc(void);
 void runtime·newstack(void);
@@ -23,9 +22,8 @@ void runtime·sigpanic(void);
 // A little clunky to merge the two but avoids duplicating
 // the code and all its subtlety.
 int32
-runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, int32 max)
+runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max)
 {
-	byte *p;
 	int32 i, n, iter, sawnewstack;
 	uintptr pc, lr, tracepc;
 	byte *fp;
@@ -40,29 +38,22 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 	waspanic = false;
 	
 	// If the PC is goexit, the goroutine hasn't started yet.
-	if(pc0 == g->sched.pc && sp == g->sched.sp && pc0 == (byte*)runtime·goexit) {
+	if(pc0 == gp->sched.pc && sp == (byte*)gp->sched.sp && pc0 == (byte*)runtime·goexit && gp->fnstart != nil) {
 		fp = sp;
 		lr = pc;
-		pc = (uintptr)g->entry;
+		pc = (uintptr)gp->fnstart->fn;
 	}
 	
 	// If the PC is zero, it's likely a nil function call.
 	// Start in the caller's frame.
 	if(pc == 0) {
-		pc = lr;
-		lr = 0;
-	}
-
-	// If the PC is zero, it's likely a nil function call.
-	// Start in the caller's frame.
-	if(pc == 0) {
 		pc = *(uintptr*)sp;
 		sp += sizeof(uintptr);
 	}
 
 	n = 0;
 	sawnewstack = 0;
-	stk = (Stktop*)g->stackbase;
+	stk = (Stktop*)gp->stackbase;
 	for(iter = 0; iter < 100 && n < max; iter++) {	// iter avoids looping forever
 		// Typically:
 		//	pc is the PC of the running function.
@@ -74,41 +65,16 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 		if(pc == (uintptr)runtime·lessstack) {
 			// Hit top of stack segment.  Unwind to next segment.
 			pc = (uintptr)stk->gobuf.pc;
-			sp = stk->gobuf.sp;
+			sp = (byte*)stk->gobuf.sp;
 			lr = 0;
 			fp = nil;
-			if(pcbuf == nil)
+			if(pcbuf == nil && runtime·showframe(nil, gp == m->curg))
 				runtime·printf("----- stack segment boundary -----\n");
 			stk = (Stktop*)stk->stackbase;
 			continue;
 		}
-		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) {
-			// Dangerous, but worthwhile: see if this is a closure:
-			//	ADDQ $wwxxyyzz, SP; RET
-			//	[48] 81 c4 zz yy xx ww c3
-			// The 0x48 byte is only on amd64.
-			p = (byte*)pc;
-			// We check p < p+8 to avoid wrapping and faulting if we lose track.
-			if(runtime·mheap.arena_start < p && p < p+8 && p+8 < runtime·mheap.arena_used &&  // pointer in allocated memory
-			   (sizeof(uintptr) != 8 || *p++ == 0x48) &&  // skip 0x48 byte on amd64
-			   p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) {
-				sp += *(uint32*)(p+2);
-				pc = *(uintptr*)sp;
-				sp += sizeof(uintptr);
-				lr = 0;
-				fp = nil;
-				continue;
-			}
-			
-			// Closure at top of stack, not yet started.
-			if(lr == (uintptr)runtime·goexit && (pc = isclosureentry(pc)) != 0) {
-				fp = sp;
-				continue;
-			}
-
-			// Unknown pc: stop.
+		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil)
 			break;
-		}
 
 		// Found an actual function.
 		if(fp == nil) {
@@ -126,7 +92,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 		else if(pcbuf != nil)
 			pcbuf[n++] = pc;
 		else {
-			if(runtime·showframe(f)) {
+			if(runtime·showframe(f, gp == m->curg)) {
 				// Print during crash.
 				//	main(0x1, 0x2, 0x3)
 				//		/home/rsc/go/src/runtime/x.go:23 +0xf
@@ -134,8 +100,10 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 				tracepc = pc;	// back up to CALL instruction for funcline.
 				if(n > 0 && pc > f->entry && !waspanic)
 					tracepc--;
+				if(m->throwing && gp == m->curg)
+					runtime·printf("[fp=%p] ", fp);
 				runtime·printf("%S(", f->name);
-				for(i = 0; i < f->args; i++) {
+				for(i = 0; i < f->args/sizeof(uintptr); i++) {
 					if(i != 0)
 						runtime·prints(", ");
 					runtime·printhex(((uintptr*)fp)[i]);
@@ -161,27 +129,27 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 		if(f->entry == (uintptr)runtime·newstack)
 			sawnewstack = 1;
 
-		if(pcbuf == nil && f->entry == (uintptr)runtime·morestack && g == m->g0 && sawnewstack) {
+		if(pcbuf == nil && f->entry == (uintptr)runtime·morestack && gp == m->g0 && sawnewstack) {
 			// The fact that we saw newstack means that morestack
 			// has managed to record its information in m, so we can
 			// use it to keep unwinding the stack.
-			runtime·printf("----- morestack called from goroutine %d -----\n", m->curg->goid);
+			runtime·printf("----- morestack called from goroutine %D -----\n", m->curg->goid);
 			pc = (uintptr)m->morepc;
-			sp = m->morebuf.sp - sizeof(void*);
+			sp = (byte*)m->morebuf.sp - sizeof(void*);
 			lr = (uintptr)m->morebuf.pc;
-			fp = m->morebuf.sp;
+			fp = (byte*)m->morebuf.sp;
 			sawnewstack = 0;
-			g = m->curg;
-			stk = (Stktop*)g->stackbase;
+			gp = m->curg;
+			stk = (Stktop*)gp->stackbase;
 			continue;
 		}
 
-		if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && g == m->g0) {
+		if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && gp == m->g0) {
 			// Lessstack is running on scheduler stack.  Switch to original goroutine.
-			runtime·printf("----- lessstack called from goroutine %d -----\n", m->curg->goid);
-			g = m->curg;
-			stk = (Stktop*)g->stackbase;
-			sp = stk->gobuf.sp;
+			runtime·printf("----- lessstack called from goroutine %D -----\n", m->curg->goid);
+			gp = m->curg;
+			stk = (Stktop*)gp->stackbase;
+			sp = (byte*)stk->gobuf.sp;
 			pc = (uintptr)stk->gobuf.pc;
 			fp = nil;
 			lr = 0;
@@ -196,7 +164,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 	}
 	
 	// Show what created goroutine, except main goroutine (goid 1).
-	if(pcbuf == nil && (pc = g->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && g->goid != 1) {
+	if(pcbuf == nil && (pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil
+			&& runtime·showframe(f, gp == m->curg) && gp->goid != 1) {
 		runtime·printf("created by %S\n", f->name);
 		tracepc = pc;	// back up to CALL instruction for funcline.
 		if(n > 0 && pc > f->entry)
@@ -211,9 +180,14 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
 }
 
 void
-runtime·traceback(byte *pc0, byte *sp, byte*, G *g)
+runtime·traceback(byte *pc0, byte *sp, byte*, G *gp)
 {
-	runtime·gentraceback(pc0, sp, nil, g, 0, nil, 100);
+	if(gp->status == Gsyscall) {
+		// Override signal registers if blocked in system call.
+		pc0 = gp->sched.pc;
+		sp = (byte*)gp->sched.sp;
+	}
+	runtime·gentraceback(pc0, sp, nil, gp, 0, nil, 100);
 }
 
 int32
@@ -227,77 +201,3 @@ runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
 
 	return runtime·gentraceback(pc, sp, nil, g, skip, pcbuf, m);
 }
-
-static uintptr
-isclosureentry(uintptr pc)
-{
-	byte *p;
-	int32 i, siz;
-	
-	p = (byte*)pc;
-	if(p < runtime·mheap.arena_start || p+32 > runtime·mheap.arena_used)
-		return 0;
-
-	if(*p == 0xe8) {
-		// CALL fn
-		return pc+5+*(int32*)(p+1);
-	}
-	
-	if(sizeof(uintptr) == 8 && p[0] == 0x48 && p[1] == 0xb9 && p[10] == 0xff && p[11] == 0xd1) {
-		// MOVQ $fn, CX; CALL *CX
-		return *(uintptr*)(p+2);
-	}
-
-	// SUBQ $siz, SP
-	if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0x81 || *p++ != 0xec)
-		return 0;
-	siz = *(uint32*)p;
-	p += 4;
-	
-	// MOVQ $q, SI
-	if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xbe)
-		return 0;
-	p += sizeof(uintptr);
-
-	// MOVQ SP, DI
-	if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0x89 || *p++ != 0xe7)
-		return 0;
-
-	// CLD on 32-bit
-	if(sizeof(uintptr) == 4 && *p++ != 0xfc)
-		return 0;
-
-	if(siz <= 4*sizeof(uintptr)) {
-		// MOVSQ...
-		for(i=0; i<siz; i+=sizeof(uintptr))
-			if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xa5)
-				return 0;
-	} else {
-		// MOVQ $(siz/8), CX  [32-bit immediate siz/8]
-		if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xc7 || *p++ != 0xc1)
-			return 0;
-		p += 4;
-		
-		// REP MOVSQ
-		if(*p++ != 0xf3 || (sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xa5)
-			return 0;
-	}
-	
-	// CALL fn
-	if(*p == 0xe8) {
-		p++;
-		return (uintptr)p+4 + *(int32*)p;
-	}
-	
-	// MOVQ $fn, CX; CALL *CX
-	if(sizeof(uintptr) != 8 || *p++ != 0x48 || *p++ != 0xb9)
-		return 0;
-
-	pc = *(uintptr*)p;
-	p += 8;
-	
-	if(*p++ != 0xff || *p != 0xd1)
-		return 0;
-
-	return pc;
-}
diff --git a/src/pkg/runtime/type.go b/src/pkg/runtime/type.go
index 6af6b23..374754a 100644
--- a/src/pkg/runtime/type.go
+++ b/src/pkg/runtime/type.go
@@ -14,24 +14,25 @@ package runtime
 
 import "unsafe"
 
-type commonType struct {
+type rtype struct {
 	size       uintptr
 	hash       uint32
 	_          uint8
 	align      uint8
 	fieldAlign uint8
 	kind       uint8
-	alg        *uintptr
+	alg        unsafe.Pointer
+	gc         unsafe.Pointer
 	string     *string
 	*uncommonType
-	ptrToThis *interface{}
+	ptrToThis *rtype
 }
 
 type _method struct {
 	name    *string
 	pkgPath *string
-	mtyp    *interface{}
-	typ     *interface{}
+	mtyp    *rtype
+	typ     *rtype
 	ifn     unsafe.Pointer
 	tfn     unsafe.Pointer
 }
@@ -45,10 +46,10 @@ type uncommonType struct {
 type _imethod struct {
 	name    *string
 	pkgPath *string
-	typ     *interface{}
+	typ     *rtype
 }
 
 type interfaceType struct {
-	commonType
+	rtype
 	methods []_imethod
 }
diff --git a/src/pkg/runtime/type.h b/src/pkg/runtime/type.h
index c1d9fac..769a807 100644
--- a/src/pkg/runtime/type.h
+++ b/src/pkg/runtime/type.h
@@ -5,21 +5,20 @@
 /*
  * Runtime type representation; master is type.go
  *
- * The *Types here correspond 1-1 to type.go's *Type's, but are
- * prefixed with an extra header of 2 pointers, corresponding to the
- * interface{} structure, which itself is called type Type again on
- * the Go side.
+ * The Type*s here correspond 1-1 to type.go's *rtype.
  */
 
-typedef struct CommonType CommonType;
+typedef struct Type Type;
 typedef struct UncommonType UncommonType;
 typedef struct InterfaceType InterfaceType;
 typedef struct Method Method;
 typedef struct IMethod IMethod;
 typedef struct SliceType SliceType;
 typedef struct FuncType FuncType;
+typedef struct PtrType PtrType;
 
-struct CommonType
+// Needs to be in sync with typekind.h/CommonSize
+struct Type
 {
 	uintptr size;
 	uint32 hash;
@@ -28,42 +27,12 @@ struct CommonType
 	uint8 fieldAlign;
 	uint8 kind;
 	Alg *alg;
+	void *gc;
 	String *string;
 	UncommonType *x;
 	Type *ptrto;
 };
 
-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,
-};
-
 struct Method
 {
 	String *name;
@@ -82,13 +51,6 @@ struct UncommonType
 	Method m[];
 };
 
-struct Type
-{
-	void *type;	// interface{} value
-	void *ptr;
-	CommonType;
-};
-
 struct IMethod
 {
 	String *name;
@@ -130,3 +92,9 @@ struct FuncType
 	Slice in;
 	Slice out;
 };
+
+struct PtrType
+{
+	Type;
+	Type *elem;
+};
diff --git a/src/pkg/runtime/typekind.h b/src/pkg/runtime/typekind.h
new file mode 100644
index 0000000..9bae2a8
--- /dev/null
+++ b/src/pkg/runtime/typekind.h
@@ -0,0 +1,41 @@
+// 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.
+
+// 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,
+	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,
+
+	// size of Type structure.
+	CommonSize = 6*PtrSize + 8,
+};
+
diff --git a/src/pkg/runtime/vdso_linux_amd64.c b/src/pkg/runtime/vdso_linux_amd64.c
new file mode 100644
index 0000000..ab68c23
--- /dev/null
+++ b/src/pkg/runtime/vdso_linux_amd64.c
@@ -0,0 +1,331 @@
+// 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"
+
+#define AT_SYSINFO_EHDR 33
+#define AT_NULL	0    /* End of vector */
+#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_STRTAB 5  /* Address of string table */
+#define DT_SYMTAB 6  /* Address of symbol table */
+#define DT_VERSYM 0x6ffffff0
+#define	DT_VERDEF 0x6ffffffc
+
+#define VER_FLG_BASE 0x1 /* Version definition of file itself */
+#define SHN_UNDEF 0      /* Undefined section */
+#define SHT_DYNSYM 11    /* Dynamic linker symbol table */
+#define STT_FUNC 2       /* Symbol is a code object */
+#define STB_GLOBAL 1     /* Global symbol */
+#define STB_WEAK 2       /* Weak symbol */
+
+/* How to extract and insert information held in the st_info field.  */
+#define ELF64_ST_BIND(val) (((byte) (val)) >> 4)
+#define ELF64_ST_TYPE(val) ((val) & 0xf)
+
+#define EI_NIDENT (16)
+
+typedef uint16 Elf64_Half;
+typedef uint32 Elf64_Word;
+typedef	int32  Elf64_Sword;
+typedef uint64 Elf64_Xword;
+typedef	int64  Elf64_Sxword;
+typedef uint64 Elf64_Addr;
+typedef uint64 Elf64_Off;
+typedef uint16 Elf64_Section;
+typedef Elf64_Half Elf64_Versym;
+
+
+typedef struct
+{
+	Elf64_Word st_name;
+	byte st_info;
+	byte st_other;
+	Elf64_Section st_shndx;
+	Elf64_Addr st_value;
+	Elf64_Xword st_size;
+} Elf64_Sym;
+
+typedef struct
+{
+	Elf64_Half vd_version; /* Version revision */
+	Elf64_Half vd_flags;   /* Version information */
+	Elf64_Half vd_ndx;     /* Version Index */
+	Elf64_Half vd_cnt;     /* Number of associated aux entries */
+	Elf64_Word vd_hash;    /* Version name hash value */
+	Elf64_Word vd_aux;     /* Offset in bytes to verdaux array */
+	Elf64_Word vd_next;    /* Offset in bytes to next verdef entry */
+} Elf64_Verdef;
+
+typedef struct
+{
+	byte e_ident[EI_NIDENT]; /* Magic number and other info */
+	Elf64_Half e_type;       /* Object file type */
+	Elf64_Half e_machine;    /* Architecture */
+	Elf64_Word e_version;    /* Object file version */
+	Elf64_Addr e_entry;      /* Entry point virtual address */
+	Elf64_Off e_phoff;       /* Program header table file offset */
+	Elf64_Off e_shoff;       /* Section header table file offset */
+	Elf64_Word e_flags;      /* Processor-specific flags */
+	Elf64_Half e_ehsize;     /* ELF header size in bytes */
+	Elf64_Half e_phentsize;  /* Program header table entry size */
+	Elf64_Half e_phnum;      /* Program header table entry count */
+	Elf64_Half e_shentsize;  /* Section header table entry size */
+	Elf64_Half e_shnum;      /* Section header table entry count */
+	Elf64_Half e_shstrndx;   /* Section header string table index */
+} Elf64_Ehdr;
+
+typedef struct
+{
+	Elf64_Word p_type;    /* Segment type */
+	Elf64_Word p_flags;   /* Segment flags */
+	Elf64_Off p_offset;   /* Segment file offset */
+	Elf64_Addr p_vaddr;   /* Segment virtual address */
+	Elf64_Addr p_paddr;   /* Segment physical address */
+	Elf64_Xword p_filesz; /* Segment size in file */
+	Elf64_Xword p_memsz;  /* Segment size in memory */
+	Elf64_Xword p_align;  /* Segment alignment */
+} Elf64_Phdr;
+
+typedef struct
+{
+	Elf64_Word sh_name;       /* Section name (string tbl index) */
+	Elf64_Word sh_type;       /* Section type */
+	Elf64_Xword sh_flags;     /* Section flags */
+	Elf64_Addr sh_addr;       /* Section virtual addr at execution */
+	Elf64_Off sh_offset;      /* Section file offset */
+	Elf64_Xword sh_size;      /* Section size in bytes */
+	Elf64_Word sh_link;       /* Link to another section */
+	Elf64_Word sh_info;       /* Additional section information */
+	Elf64_Xword sh_addralign; /* Section alignment */
+	Elf64_Xword sh_entsize;   /* Entry size if section holds table */
+} Elf64_Shdr;
+
+typedef struct
+{
+	Elf64_Sxword d_tag; /* Dynamic entry type */
+	union
+	{
+		Elf64_Xword d_val;  /* Integer value */
+		Elf64_Addr d_ptr;   /* Address value */
+	} d_un;
+} Elf64_Dyn;
+
+typedef struct
+{
+	Elf64_Word vda_name; /* Version or dependency names */
+	Elf64_Word vda_next; /* Offset in bytes to next verdaux entry */
+} Elf64_Verdaux;
+
+typedef struct
+{
+	uint64 a_type;        /* Entry type */
+	union
+	{
+		uint64 a_val; /* Integer value */
+	} a_un;
+} Elf64_auxv_t;
+
+
+typedef struct {
+	byte* name;
+	void** var_ptr;
+} symbol_key;
+
+typedef struct {
+	byte* version;
+	int32 ver_hash;
+} version_key;
+
+struct vdso_info {
+	bool valid;
+
+	/* Load information */
+	uintptr load_addr;
+	uintptr load_offset;  /* load_addr - recorded vaddr */
+
+	/* Symbol table */
+	int32 num_sym;
+	Elf64_Sym *symtab;
+	const byte *symstrings;
+
+	/* Version table */
+	Elf64_Versym *versym;
+	Elf64_Verdef *verdef;
+};
+
+static version_key linux26 = { (byte*)"LINUX_2.6", 0x3ae75f6 };
+
+// initialize with vsyscall fallbacks
+void* runtime·__vdso_time_sym = (void*)0xffffffffff600400ULL;
+void* runtime·__vdso_gettimeofday_sym = (void*)0xffffffffff600000ULL;
+void* runtime·__vdso_clock_gettime_sym = (void*)0;
+
+#define SYM_KEYS_COUNT 3
+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 },
+};
+
+static void
+vdso_init_from_sysinfo_ehdr(struct vdso_info *vdso_info, Elf64_Ehdr* hdr)
+{
+	uint64 i;
+	bool found_vaddr = 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);
+		}
+	}
+
+	// We need two things from the segment table: the load offset
+	// and the dynamic table.
+	for(i=0; i<hdr->e_phnum; i++) {
+		if(pt[i].p_type == PT_LOAD && found_vaddr == false) {
+			found_vaddr = true;
+			vdso_info->load_offset =	(uintptr)hdr
+				+ (uintptr)pt[i].p_offset
+				- (uintptr)pt[i].p_vaddr;
+		} else if(pt[i].p_type == PT_DYNAMIC) {
+			dyn = (Elf64_Dyn*)((uintptr)hdr + pt[i].p_offset);
+		}
+	}
+
+	if(found_vaddr == false || dyn == nil)
+		return;  // Failed
+
+	// Fish out the useful bits of the dynamic table.
+	for(i=0; dyn[i].d_tag!=DT_NULL; i++) {
+		switch(dyn[i].d_tag) {
+		case DT_STRTAB:
+			vdso_info->symstrings = (const byte *)
+				((uintptr)dyn[i].d_un.d_ptr
+				 + vdso_info->load_offset);
+			break;
+		case DT_SYMTAB:
+			vdso_info->symtab = (Elf64_Sym *)
+				((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
+				 + vdso_info->load_offset);
+			break;
+		case DT_VERDEF:
+			vdso_info->verdef = (Elf64_Verdef *)
+				((uintptr)dyn[i].d_un.d_ptr
+				 + vdso_info->load_offset);
+			break;
+		}
+	}
+	if(vdso_info->symstrings == nil || vdso_info->symtab == nil)
+		return;  // Failed
+
+	if(vdso_info->verdef == nil)
+		vdso_info->versym = 0;
+
+	// That's all we need.
+	vdso_info->valid = true;
+}
+
+static int32
+vdso_find_version(struct vdso_info *vdso_info, version_key* ver)
+{
+	if(vdso_info->valid == false) {
+		return 0;
+	}
+	Elf64_Verdef *def = vdso_info->verdef;
+	while(true) {
+		if((def->vd_flags & VER_FLG_BASE) == 0) {
+			Elf64_Verdaux *aux = (Elf64_Verdaux*)((byte *)def + def->vd_aux);
+			if(def->vd_hash == ver->ver_hash &&
+				runtime·strcmp(ver->version, vdso_info->symstrings + aux->vda_name) == 0) {
+				return def->vd_ndx & 0x7fff;
+			}
+		}
+
+		if(def->vd_next == 0) {
+			break;
+		}
+		def = (Elf64_Verdef *)((byte *)def + def->vd_next);
+	}
+	return 0;
+}
+
+static void
+vdso_parse_symbols(struct vdso_info *vdso_info, int32 version)
+{
+	int32 i, j;
+
+	if(vdso_info->valid == false)
+		return;
+
+	for(i=0; i<vdso_info->num_sym; i++) {
+		Elf64_Sym *sym = &vdso_info->symtab[i];
+
+		// 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)
+				continue;
+
+			// Check symbol version.
+			if(vdso_info->versym != nil && version != 0
+				&& vdso_info->versym[i] & 0x7fff != version)
+				continue;
+
+			*sym_keys[j].var_ptr = (void *)(vdso_info->load_offset + sym->st_value);
+		}
+	}
+}
+
+static void
+runtime·linux_setup_vdso(int32 argc, uint8** argv)
+{
+	struct vdso_info vdso_info;
+
+	// skip argvc
+	byte **p = argv;
+	p = &p[argc+1];
+
+	// skip envp to get to ELF auxiliary vector.
+	for(; *p!=0; p++) {}
+
+	// skip NULL separator
+	p++;
+
+	// now, p points to auxv
+	Elf64_auxv_t *elf_auxv = (Elf64_auxv_t*) p;
+
+	for(int32 i=0; elf_auxv[i].a_type!=AT_NULL; i++) {
+		if(elf_auxv[i].a_type == AT_SYSINFO_EHDR) {
+			if(elf_auxv[i].a_un.a_val == 0) {
+				// Something went wrong
+				return;
+			}
+			vdso_init_from_sysinfo_ehdr(&vdso_info, (Elf64_Ehdr*)elf_auxv[i].a_un.a_val);
+			vdso_parse_symbols(&vdso_info, vdso_find_version(&vdso_info, &linux26));
+			return;
+		}
+	}
+}
+
+void (*runtime·sysargs)(int32, uint8**) = runtime·linux_setup_vdso;
diff --git a/src/pkg/runtime/vlop_arm.s b/src/pkg/runtime/vlop_arm.s
index fc679f0..0dedc31 100644
--- a/src/pkg/runtime/vlop_arm.s
+++ b/src/pkg/runtime/vlop_arm.s
@@ -23,9 +23,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#define UMULL(Rs,Rm,Rhi,Rlo,S)  WORD	 $((14<<28)|(4<<21)|(S<<20)|(Rhi<<16)|(Rlo<<12)|(Rs<<8)|(9<<4)|Rm)
-#define UMLAL(Rs,Rm,Rhi,Rlo,S)  WORD	 $((14<<28)|(5<<21)|(S<<20)|(Rhi<<16)|(Rlo<<12)|(Rs<<8)|(9<<4)|Rm)
-#define MUL(Rs,Rm,Rd,S) WORD	 $((14<<28)|(0<<21)|(S<<20)|(Rd<<16)|(Rs<<8)|(9<<4)|Rm)
 arg=0
 
 /* replaced use of R10 by R11 because the former can be the data segment base register */
@@ -36,136 +33,15 @@ TEXT _mulv(SB), $0
 	MOVW	8(FP), R11	/* h0 */
 	MOVW	12(FP), R4	/* l1 */
 	MOVW	16(FP), R5	/* h1 */
-	UMULL(4, 2, 7, 6, 0)
-	MUL(11, 4, 8, 0)
+	MULLU	R4, R2, (R7,R6)
+	MUL	R11, R4, R8
 	ADD	R8, R7
-	MUL(2, 5, 8, 0)
+	MUL	R2, R5, R8
 	ADD	R8, R7
 	MOVW	R6, 0(R(arg))
 	MOVW	R7, 4(R(arg))
 	RET
 
-
-Q	= 0
-N	= 1
-D	= 2
-CC	= 3
-TMP	= 11
-
-TEXT save<>(SB), 7, $0
-	MOVW	R(Q), 0(FP)
-	MOVW	R(N), 4(FP)
-	MOVW	R(D), 8(FP)
-	MOVW	R(CC), 12(FP)
-
-	MOVW	R(TMP), R(Q)		/* numerator */
-	MOVW	20(FP), R(D)		/* denominator */
-	CMP	$0, R(D)
-	BNE	s1
-	BL	runtime·panicdivide(SB)
-/*	  MOVW	-1(R(D)), R(TMP)	/* divide by zero fault */
-s1:	 RET
-
-TEXT rest<>(SB), 7, $0
-	MOVW	0(FP), R(Q)
-	MOVW	4(FP), R(N)
-	MOVW	8(FP), R(D)
-	MOVW	12(FP), R(CC)
-/*
- * return to caller
- * of rest<>
- */
-	MOVW	0(R13), R14
-	ADD	$20, R13
-	B	(R14)
-
-TEXT div<>(SB), 7, $0
-	MOVW	$32, R(CC)
-/*
- * skip zeros 8-at-a-time
- */
-e1:
-	AND.S	$(0xff<<24),R(Q), R(N)
-	BNE	e2
-	SLL	$8, R(Q)
-	SUB.S	$8, R(CC)
-	BNE	e1
-	RET
-e2:
-	MOVW	$0, R(N)
-
-loop:
-/*
- * shift R(N||Q) left one
- */
-	SLL	$1, R(N)
-	CMP	$0, R(Q)
-	ORR.LT  $1, R(N)
-	SLL	$1, R(Q)
-
-/*
- * compare numerator to denominator
- * if less, subtract and set quotient bit
- */
-	CMP	R(D), R(N)
-	ORR.HS  $1, R(Q)
-	SUB.HS  R(D), R(N)
-	SUB.S	$1, R(CC)
-	BNE	loop
-	RET
-
-TEXT _div(SB), 7, $16
-	BL	save<>(SB)
-	CMP	$0, R(Q)
-	BGE	d1
-	RSB	$0, R(Q), R(Q)
-	CMP	$0, R(D)
-	BGE	d2
-	RSB	$0, R(D), R(D)
-d0:
-	BL	div<>(SB)			/* none/both neg */
-	MOVW	R(Q), R(TMP)
-	B	out
-d1:
-	CMP	$0, R(D)
-	BGE	d0
-	RSB	$0, R(D), R(D)
-d2:
-	BL	div<>(SB)			/* one neg */
-	RSB	$0, R(Q), R(TMP)
-	B	out
-
-TEXT _mod(SB), 7, $16
-	BL	save<>(SB)
-	CMP	$0, R(D)
-	RSB.LT	$0, R(D), R(D)
-	CMP	$0, R(Q)
-	BGE	m1
-	RSB	$0, R(Q), R(Q)
-	BL	div<>(SB)			/* neg numerator */
-	RSB	$0, R(N), R(TMP)
-	B	out
-m1:
-	BL	div<>(SB)			/* pos numerator */
-	MOVW	R(N), R(TMP)
-	B	out
-
-TEXT _divu(SB), 7, $16
-	BL	save<>(SB)
-	BL	div<>(SB)
-	MOVW	R(Q), R(TMP)
-	B	out
-
-TEXT _modu(SB), 7, $16
-	BL	save<>(SB)
-	BL	div<>(SB)
-	MOVW	R(N), R(TMP)
-	B	out
-
-out:
-	BL	rest<>(SB)
-	B	out
-
 // 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.
@@ -186,5 +62,189 @@ TEXT _sfloat(SB), 7, $64 // 4 arg + 14*4 saved regs + cpsr
 	MOVM.IA.W	(R0), [R1-R12]
 	MOVW	8(R13), R0
 	RET
-			
 
+// func udiv(n, d uint32) (q, r uint32)
+// Reference: 
+// Sloss, Andrew et. al; ARM System Developer's Guide: Designing and Optimizing System Software
+// Morgan Kaufmann; 1 edition (April 8, 2004), ISBN 978-1558608740
+q = 0 // input d, output q
+r = 1 // input n, output r
+s = 2 // three temporary variables
+m = 3
+a = 11
+// Please be careful when changing this, it is pretty fragile:
+// 1, don't use unconditional branch as the linker is free to reorder the blocks;
+// 2. if a == 11, beware that the linker will use R11 if you use certain instructions.
+TEXT udiv<>(SB),7,$-4
+	CLZ 	R(q), R(s) // find normalizing shift
+	MOVW.S	R(q)<<R(s), R(a)
+	ADD 	R(a)>>25, PC, R(a) // most significant 7 bits of divisor
+	MOVBU.NE	(4*36-64)(R(a)), R(a) // 36 == number of inst. between fast_udiv_tab and begin
+
+begin:
+	SUB.S	$7, R(s)
+	RSB 	$0, R(q), R(m) // m = -q
+	MOVW.PL	R(a)<<R(s), R(q)
+
+	// 1st Newton iteration
+	MUL.PL	R(m), R(q), R(a) // a = -q*d
+	BMI 	udiv_by_large_d
+	MULAWT	R(a), R(q), R(q), R(q) // q approx q-(q*q*d>>32)
+	TEQ 	R(m)->1, R(m) // check for d=0 or d=1
+
+	// 2nd Newton iteration
+	MUL.NE	R(m), R(q), R(a)
+	MOVW.NE	$0, R(s)
+	MULAL.NE R(q), R(a), (R(q),R(s))
+	BEQ 	udiv_by_0_or_1
+
+	// q now accurate enough for a remainder r, 0<=r<3*d
+	MULLU	R(q), R(r), (R(q),R(s)) // q = (r * q) >> 32	
+	ADD 	R(m), R(r), R(r) // r = n - d
+	MULA	R(m), R(q), R(r), R(r) // r = n - (q+1)*d
+
+	// since 0 <= n-q*d < 3*d; thus -d <= r < 2*d
+	CMN 	R(m), R(r) // t = r-d
+	SUB.CS	R(m), R(r), R(r) // if (t<-d || t>=0) r=r+d
+	ADD.CC	$1, R(q)
+	ADD.PL	R(m)<<1, R(r)
+	ADD.PL	$2, R(q)
+
+	// return, can't use RET here or fast_udiv_tab will be dropped during linking
+	MOVW	R14, R15
+
+udiv_by_large_d:
+	// at this point we know d>=2^(31-6)=2^25
+	SUB 	$4, R(a), R(a)
+	RSB 	$0, R(s), R(s)
+	MOVW	R(a)>>R(s), R(q)
+	MULLU	R(q), R(r), (R(q),R(s))
+	MULA	R(m), R(q), R(r), R(r)
+
+	// q now accurate enough for a remainder r, 0<=r<4*d
+	CMN 	R(r)>>1, R(m) // if(r/2 >= d)
+	ADD.CS	R(m)<<1, R(r)
+	ADD.CS	$2, R(q)
+	CMN 	R(r), R(m)
+	ADD.CS	R(m), R(r)
+	ADD.CS	$1, R(q)
+
+	// return, can't use RET here or fast_udiv_tab will be dropped during linking
+	MOVW	R14, R15
+
+udiv_by_0_or_1:
+	// carry set if d==1, carry clear if d==0
+	MOVW.CS	R(r), R(q)
+	MOVW.CS	$0, R(r)
+	BL.CC 	runtime·panicdivide(SB) // no way back
+
+	// return, can't use RET here or fast_udiv_tab will be dropped during linking
+	MOVW	R14, R15
+
+fast_udiv_tab:
+	// 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
+
+// The linker will pass numerator in R(TMP), and it also
+// expects the result in R(TMP)
+TMP = 11
+
+TEXT _divu(SB), 7, $16
+	MOVW	R(q), 4(R13)
+	MOVW	R(r), 8(R13)
+	MOVW	R(s), 12(R13)
+	MOVW	R(m), 16(R13)
+
+	MOVW	R(TMP), R(r)		/* numerator */
+	MOVW	0(FP), R(q) 		/* denominator */
+	BL  	udiv<>(SB)
+	MOVW	R(q), R(TMP)
+	MOVW	4(R13), R(q)
+	MOVW	8(R13), R(r)
+	MOVW	12(R13), R(s)
+	MOVW	16(R13), R(m)
+	RET
+
+TEXT _modu(SB), 7, $16
+	MOVW	R(q), 4(R13)
+	MOVW	R(r), 8(R13)
+	MOVW	R(s), 12(R13)
+	MOVW	R(m), 16(R13)
+
+	MOVW	R(TMP), R(r)		/* numerator */
+	MOVW	0(FP), R(q) 		/* denominator */
+	BL  	udiv<>(SB)
+	MOVW	R(r), R(TMP)
+	MOVW	4(R13), R(q)
+	MOVW	8(R13), R(r)
+	MOVW	12(R13), R(s)
+	MOVW	16(R13), R(m)
+	RET
+
+TEXT _div(SB),7,$16
+	MOVW	R(q), 4(R13)
+	MOVW	R(r), 8(R13)
+	MOVW	R(s), 12(R13)
+	MOVW	R(m), 16(R13)
+	MOVW	R(TMP), R(r)		/* numerator */
+	MOVW	0(FP), R(q) 		/* denominator */
+	CMP 	$0, R(r)
+	BGE 	d1
+	RSB 	$0, R(r), R(r)
+	CMP 	$0, R(q)
+	BGE 	d2
+	RSB 	$0, R(q), R(q)
+d0:
+	BL  	udiv<>(SB)  		/* none/both neg */
+	MOVW	R(q), R(TMP)
+	B		out
+d1:
+	CMP 	$0, R(q)
+	BGE 	d0
+	RSB 	$0, R(q), R(q)
+d2:
+	BL  	udiv<>(SB)  		/* one neg */
+	RSB		$0, R(q), R(TMP)
+	B   	out
+
+TEXT _mod(SB),7,$16
+	MOVW	R(q), 4(R13)
+	MOVW	R(r), 8(R13)
+	MOVW	R(s), 12(R13)
+	MOVW	R(m), 16(R13)
+	MOVW	R(TMP), R(r)		/* numerator */
+	MOVW	0(FP), R(q) 		/* denominator */
+	CMP 	$0, R(q)
+	RSB.LT	$0, R(q), R(q)
+	CMP 	$0, R(r)
+	BGE 	m1
+	RSB 	$0, R(r), R(r)
+	BL  	udiv<>(SB)  		/* neg numerator */
+	RSB 	$0, R(r), R(TMP)
+	B   	out
+m1:
+	BL  	udiv<>(SB)  		/* pos numerator */
+	MOVW	R(r), R(TMP)
+out:
+	MOVW	4(R13), R(q)
+	MOVW	8(R13), R(r)
+	MOVW	12(R13), R(s)
+	MOVW	16(R13), R(m)
+	RET
diff --git a/src/pkg/runtime/vlop_arm_test.go b/src/pkg/runtime/vlop_arm_test.go
new file mode 100644
index 0000000..cd28419
--- /dev/null
+++ b/src/pkg/runtime/vlop_arm_test.go
@@ -0,0 +1,70 @@
+// 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"
+
+// arm soft division benchmarks adapted from
+// http://ridiculousfish.com/files/division_benchmarks.tar.gz
+
+const numeratorsSize = 1 << 21
+
+var numerators = randomNumerators()
+
+type randstate struct {
+	hi, lo uint32
+}
+
+func (r *randstate) rand() uint32 {
+	r.hi = r.hi<<16 + r.hi>>16
+	r.hi += r.lo
+	r.lo += r.hi
+	return r.hi
+}
+
+func randomNumerators() []uint32 {
+	numerators := make([]uint32, numeratorsSize)
+	random := &randstate{2147483563, 2147483563 ^ 0x49616E42}
+	for i := range numerators {
+		numerators[i] = random.rand()
+	}
+	return numerators
+}
+
+func bmUint32Div(divisor uint32, b *testing.B) {
+	var sum uint32
+	for i := 0; i < b.N; i++ {
+		sum += numerators[i&(numeratorsSize-1)] / divisor
+	}
+}
+
+func BenchmarkUint32Div7(b *testing.B)         { bmUint32Div(7, b) }
+func BenchmarkUint32Div37(b *testing.B)        { bmUint32Div(37, b) }
+func BenchmarkUint32Div123(b *testing.B)       { bmUint32Div(123, b) }
+func BenchmarkUint32Div763(b *testing.B)       { bmUint32Div(763, b) }
+func BenchmarkUint32Div1247(b *testing.B)      { bmUint32Div(1247, b) }
+func BenchmarkUint32Div9305(b *testing.B)      { bmUint32Div(9305, b) }
+func BenchmarkUint32Div13307(b *testing.B)     { bmUint32Div(13307, b) }
+func BenchmarkUint32Div52513(b *testing.B)     { bmUint32Div(52513, b) }
+func BenchmarkUint32Div60978747(b *testing.B)  { bmUint32Div(60978747, b) }
+func BenchmarkUint32Div106956295(b *testing.B) { bmUint32Div(106956295, b) }
+
+func bmUint32Mod(divisor uint32, b *testing.B) {
+	var sum uint32
+	for i := 0; i < b.N; i++ {
+		sum += numerators[i&(numeratorsSize-1)] % divisor
+	}
+}
+
+func BenchmarkUint32Mod7(b *testing.B)         { bmUint32Mod(7, b) }
+func BenchmarkUint32Mod37(b *testing.B)        { bmUint32Mod(37, b) }
+func BenchmarkUint32Mod123(b *testing.B)       { bmUint32Mod(123, b) }
+func BenchmarkUint32Mod763(b *testing.B)       { bmUint32Mod(763, b) }
+func BenchmarkUint32Mod1247(b *testing.B)      { bmUint32Mod(1247, b) }
+func BenchmarkUint32Mod9305(b *testing.B)      { bmUint32Mod(9305, b) }
+func BenchmarkUint32Mod13307(b *testing.B)     { bmUint32Mod(13307, b) }
+func BenchmarkUint32Mod52513(b *testing.B)     { bmUint32Mod(52513, b) }
+func BenchmarkUint32Mod60978747(b *testing.B)  { bmUint32Mod(60978747, b) }
+func BenchmarkUint32Mod106956295(b *testing.B) { bmUint32Mod(106956295, b) }
diff --git a/src/pkg/sort/example_keys_test.go b/src/pkg/sort/example_keys_test.go
new file mode 100644
index 0000000..a8e47e4
--- /dev/null
+++ b/src/pkg/sort/example_keys_test.go
@@ -0,0 +1,96 @@
+// 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 sort_test
+
+import (
+	"fmt"
+	"sort"
+)
+
+// A couple of type definitions to make the units clear.
+type earthMass float64
+type au float64
+
+// A Planet defines the properties of a solar system object.
+type Planet struct {
+	name     string
+	mass     earthMass
+	distance au
+}
+
+// By is the type of a "less" function that defines the ordering of its Planet arguments.
+type By func(p1, p2 *Planet) bool
+
+// Sort is a method on the function type, By, that sorts the argument slice according to the function.
+func (by By) Sort(planets []Planet) {
+	ps := &planetSorter{
+		planets: planets,
+		by:      by, // The Sort method's receiver is the function (closure) that defines the sort order.
+	}
+	sort.Sort(ps)
+}
+
+// planetSorter joins a By function and a slice of Planets to be sorted.
+type planetSorter struct {
+	planets []Planet
+	by      func(p1, p2 *Planet) bool // Closure used in the Less method.
+}
+
+// Len is part of sort.Interface.
+func (s *planetSorter) Len() int {
+	return len(s.planets)
+}
+
+// Swap is part of sort.Interface.
+func (s *planetSorter) Swap(i, j int) {
+	s.planets[i], s.planets[j] = s.planets[j], s.planets[i]
+}
+
+// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
+func (s *planetSorter) Less(i, j int) bool {
+	return s.by(&s.planets[i], &s.planets[j])
+}
+
+var planets = []Planet{
+	{"Mercury", 0.055, 0.4},
+	{"Venus", 0.815, 0.7},
+	{"Earth", 1.0, 1.0},
+	{"Mars", 0.107, 1.5},
+}
+
+// ExampleSortKeys demonstrates a technique for sorting a struct type using programmable sort criteria.
+func Example_sortKeys() {
+	// Closures that order the Planet structure.
+	name := func(p1, p2 *Planet) bool {
+		return p1.name < p2.name
+	}
+	mass := func(p1, p2 *Planet) bool {
+		return p1.mass < p2.mass
+	}
+	distance := func(p1, p2 *Planet) bool {
+		return p1.distance < p2.distance
+	}
+	decreasingDistance := func(p1, p2 *Planet) bool {
+		return !distance(p1, p2)
+	}
+
+	// Sort the planets by the various criteria.
+	By(name).Sort(planets)
+	fmt.Println("By name:", planets)
+
+	By(mass).Sort(planets)
+	fmt.Println("By mass:", planets)
+
+	By(distance).Sort(planets)
+	fmt.Println("By distance:", planets)
+
+	By(decreasingDistance).Sort(planets)
+	fmt.Println("By decreasing distance:", planets)
+
+	// Output: By name: [{Earth 1 1} {Mars 0.107 1.5} {Mercury 0.055 0.4} {Venus 0.815 0.7}]
+	// By mass: [{Mercury 0.055 0.4} {Mars 0.107 1.5} {Venus 0.815 0.7} {Earth 1 1}]
+	// By distance: [{Mercury 0.055 0.4} {Venus 0.815 0.7} {Earth 1 1} {Mars 0.107 1.5}]
+	// By decreasing distance: [{Mars 0.107 1.5} {Earth 1 1} {Venus 0.815 0.7} {Mercury 0.055 0.4}]
+}
diff --git a/src/pkg/sort/example_reverse_test.go b/src/pkg/sort/example_reverse_test.go
deleted file mode 100644
index 7c7f05b..0000000
--- a/src/pkg/sort/example_reverse_test.go
+++ /dev/null
@@ -1,30 +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 sort_test
-
-import (
-	"fmt"
-	"sort"
-)
-
-// Reverse embeds a sort.Interface value and implements a reverse sort over
-// that value.
-type Reverse struct {
-	// This embedded Interface permits Reverse to use the methods of
-	// another Interface implementation.
-	sort.Interface
-}
-
-// Less returns the opposite of the embedded implementation's Less method.
-func (r Reverse) Less(i, j int) bool {
-	return r.Interface.Less(j, i)
-}
-
-func ExampleInterface_reverse() {
-	s := []int{5, 2, 6, 3, 1, 4} // unsorted
-	sort.Sort(Reverse{sort.IntSlice(s)})
-	fmt.Println(s)
-	// Output: [6 5 4 3 2 1]
-}
diff --git a/src/pkg/sort/example_test.go b/src/pkg/sort/example_test.go
index f57d025..f7372be 100644
--- a/src/pkg/sort/example_test.go
+++ b/src/pkg/sort/example_test.go
@@ -15,3 +15,10 @@ func ExampleInts() {
 	fmt.Println(s)
 	// Output: [1 2 3 4 5 6]
 }
+
+func ExampleReverse() {
+	s := []int{5, 2, 6, 3, 1, 4} // unsorted
+	sort.Sort(sort.Reverse(sort.IntSlice(s)))
+	fmt.Println(s)
+	// Output: [6 5 4 3 2 1]
+}
diff --git a/src/pkg/sort/search.go b/src/pkg/sort/search.go
index 4f0ce55..8a2c1c3 100644
--- a/src/pkg/sort/search.go
+++ b/src/pkg/sort/search.go
@@ -7,11 +7,13 @@
 package sort
 
 // Search uses binary search to find and return the smallest index i
-// in [0, n) at which f(i) is true, assuming that on the range [0, n), 
+// in [0, n) at which f(i) is true, assuming that on the range [0, n),
 // f(i) == true implies f(i+1) == true.  That is, Search requires that
 // f is false for some (possibly empty) prefix of the input range [0, n)
 // and then true for the (possibly empty) remainder; Search returns
 // the first true index.  If there is no such index, Search returns n.
+// (Note that the "not found" return value is not -1 as in, for instance,
+// strings.Index).
 // Search calls f(i) only for i in the range [0, n).
 //
 // A common use of Search is to find the index i for a value x in
@@ -74,22 +76,28 @@ func Search(n int, f func(int) bool) int {
 // Convenience wrappers for common cases.
 
 // SearchInts searches for x in a sorted slice of ints and returns the index
-// as specified by Search. The slice must be sorted in ascending order.
+// as specified by Search. The return value is the index to insert x if x is
+// not present (it could be len(a)).
+// The slice must be sorted in ascending order.
 //
 func SearchInts(a []int, x int) int {
 	return Search(len(a), func(i int) bool { return a[i] >= x })
 }
 
 // SearchFloat64s searches for x in a sorted slice of float64s and returns the index
-// as specified by Search. The slice must be sorted in ascending order.
-// 
+// as specified by Search.  The return value is the index to insert x if x is not
+// present (it could be len(a)).
+// The slice must be sorted in ascending order.
+//
 func SearchFloat64s(a []float64, x float64) int {
 	return Search(len(a), func(i int) bool { return a[i] >= x })
 }
 
-// SearchStrings searches for x slice a sorted slice of strings and returns the index
-// as specified by Search. The slice must be sorted in ascending order.
-// 
+// SearchStrings searches for x in a sorted slice of strings and returns the index
+// as specified by Search.  The return value is the index to insert x if x is not
+// present (it could be len(a)).
+// The slice must be sorted in ascending order.
+//
 func SearchStrings(a []string, x string) int {
 	return Search(len(a), func(i int) bool { return a[i] >= x })
 }
diff --git a/src/pkg/sort/search_test.go b/src/pkg/sort/search_test.go
index 07295ff..4d8d6d9 100644
--- a/src/pkg/sort/search_test.go
+++ b/src/pkg/sort/search_test.go
@@ -117,6 +117,28 @@ func TestSearchWrappers(t *testing.T) {
 	}
 }
 
+func runSearchWrappers() {
+	SearchInts(data, 11)
+	SearchFloat64s(fdata, 2.1)
+	SearchStrings(sdata, "")
+	IntSlice(data).Search(0)
+	Float64Slice(fdata).Search(2.0)
+	StringSlice(sdata).Search("x")
+}
+
+func TestSearchWrappersDontAlloc(t *testing.T) {
+	allocs := testing.AllocsPerRun(100, runSearchWrappers)
+	if allocs != 0 {
+		t.Errorf("expected no allocs for runSearchWrappers, got %v", allocs)
+	}
+}
+
+func BenchmarkSearchWrappers(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		runSearchWrappers()
+	}
+}
+
 // Abstract exhaustive test: all sizes up to 100,
 // all possible return values.  If there are any small
 // corner cases, this test exercises them.
diff --git a/src/pkg/sort/sort.go b/src/pkg/sort/sort.go
index 62a4d55..e109619 100644
--- a/src/pkg/sort/sort.go
+++ b/src/pkg/sort/sort.go
@@ -124,26 +124,31 @@ func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
 	// into the middle of the slice.
 	pivot := lo
 	a, b, c, d := lo+1, lo+1, hi, hi
-	for b < c {
-		if data.Less(b, pivot) { // data[b] < pivot
-			b++
-			continue
-		}
-		if !data.Less(pivot, b) { // data[b] = pivot
-			data.Swap(a, b)
-			a++
-			b++
-			continue
+	for {
+		for b < c {
+			if data.Less(b, pivot) { // data[b] < pivot
+				b++
+			} else if !data.Less(pivot, b) { // data[b] = pivot
+				data.Swap(a, b)
+				a++
+				b++
+			} else {
+				break
+			}
 		}
-		if data.Less(pivot, c-1) { // data[c-1] > pivot
-			c--
-			continue
+		for b < c {
+			if data.Less(pivot, c-1) { // data[c-1] > pivot
+				c--
+			} else if !data.Less(c-1, pivot) { // data[c-1] = pivot
+				data.Swap(c-1, d-1)
+				c--
+				d--
+			} else {
+				break
+			}
 		}
-		if !data.Less(c-1, pivot) { // data[c-1] = pivot
-			data.Swap(c-1, d-1)
-			c--
-			d--
-			continue
+		if b >= c {
+			break
 		}
 		// data[b] > pivot; data[c-1] < pivot
 		data.Swap(b, c-1)
@@ -197,6 +202,22 @@ func Sort(data Interface) {
 	quickSort(data, 0, n, maxDepth)
 }
 
+type reverse struct {
+	// This embedded Interface permits Reverse to use the methods of
+	// another Interface implementation.
+	Interface
+}
+
+// Less returns the opposite of the embedded implementation's Less method.
+func (r reverse) Less(i, j int) bool {
+	return r.Interface.Less(j, i)
+}
+
+// Reverse returns the reverse order for data.
+func Reverse(data Interface) Interface {
+	return &reverse{data}
+}
+
 // IsSorted reports whether data is sorted.
 func IsSorted(data Interface) bool {
 	n := data.Len()
diff --git a/src/pkg/sort/sort_test.go b/src/pkg/sort/sort_test.go
index ee8a9d0..5daf848 100644
--- a/src/pkg/sort/sort_test.go
+++ b/src/pkg/sort/sort_test.go
@@ -92,6 +92,23 @@ func TestSortLarge_Random(t *testing.T) {
 	}
 }
 
+func TestReverseSortIntSlice(t *testing.T) {
+	data := ints
+	data1 := ints
+	a := IntSlice(data[0:])
+	Sort(a)
+	r := IntSlice(data1[0:])
+	Sort(Reverse(r))
+	for i := 0; i < len(data); i++ {
+		if a[i] != r[len(data)-1-i] {
+			t.Errorf("reverse sort didn't sort")
+		}
+		if i > len(data)/2 {
+			break
+		}
+	}
+}
+
 func BenchmarkSortString1K(b *testing.B) {
 	b.StopTimer()
 	for i := 0; i < b.N; i++ {
@@ -151,15 +168,18 @@ const (
 )
 
 type testingData struct {
-	desc    string
-	t       *testing.T
-	data    []int
-	maxswap int // number of swaps allowed
-	nswap   int
+	desc        string
+	t           *testing.T
+	data        []int
+	maxswap     int // number of swaps allowed
+	ncmp, nswap int
 }
 
-func (d *testingData) Len() int           { return len(d.data) }
-func (d *testingData) Less(i, j int) bool { return d.data[i] < d.data[j] }
+func (d *testingData) Len() int { return len(d.data) }
+func (d *testingData) Less(i, j int) bool {
+	d.ncmp++
+	return d.data[i] < d.data[j]
+}
 func (d *testingData) Swap(i, j int) {
 	if d.nswap >= d.maxswap {
 		d.t.Errorf("%s: used %d swaps sorting slice of %d", d.desc, d.nswap, len(d.data))
@@ -192,8 +212,7 @@ func testBentleyMcIlroy(t *testing.T, sort func(Interface)) {
 	dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"}
 	modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"}
 	var tmp1, tmp2 [1025]int
-	for ni := 0; ni < len(sizes); ni++ {
-		n := sizes[ni]
+	for _, n := range sizes {
 		for m := 1; m < 2*n; m *= 2 {
 			for dist := 0; dist < _NDist; dist++ {
 				j := 0
@@ -259,8 +278,10 @@ func testBentleyMcIlroy(t *testing.T, sort func(Interface)) {
 					}
 
 					desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode])
-					d := &testingData{desc, t, mdata[0:n], n * lg(n) * 12 / 10, 0}
+					d := &testingData{desc: desc, t: t, data: mdata[0:n], maxswap: n * lg(n) * 12 / 10}
 					sort(d)
+					// Uncomment if you are trying to improve the number of compares/swaps.
+					//t.Logf("%s: ncmp=%d, nswp=%d", desc, d.ncmp, d.nswap)
 
 					// If we were testing C qsort, we'd have to make a copy
 					// of the slice and sort it ourselves and then compare
diff --git a/src/pkg/strconv/atof.go b/src/pkg/strconv/atof.go
index cd3031b..b4fe97d 100644
--- a/src/pkg/strconv/atof.go
+++ b/src/pkg/strconv/atof.go
@@ -37,17 +37,28 @@ func equalIgnoreCase(s1, s2 string) bool {
 }
 
 func special(s string) (f float64, ok bool) {
-	switch {
-	case equalIgnoreCase(s, "nan"):
-		return math.NaN(), true
-	case equalIgnoreCase(s, "-inf"),
-		equalIgnoreCase(s, "-infinity"):
-		return math.Inf(-1), true
-	case equalIgnoreCase(s, "+inf"),
-		equalIgnoreCase(s, "+infinity"),
-		equalIgnoreCase(s, "inf"),
-		equalIgnoreCase(s, "infinity"):
-		return math.Inf(1), true
+	if len(s) == 0 {
+		return
+	}
+	switch s[0] {
+	default:
+		return
+	case '+':
+		if equalIgnoreCase(s, "+inf") || equalIgnoreCase(s, "+infinity") {
+			return math.Inf(1), true
+		}
+	case '-':
+		if equalIgnoreCase(s, "-inf") || equalIgnoreCase(s, "-infinity") {
+			return math.Inf(-1), true
+		}
+	case 'n', 'N':
+		if equalIgnoreCase(s, "nan") {
+			return math.NaN(), true
+		}
+	case 'i', 'I':
+		if equalIgnoreCase(s, "inf") || equalIgnoreCase(s, "infinity") {
+			return math.Inf(1), true
+		}
 	}
 	return
 }
@@ -142,6 +153,105 @@ func (b *decimal) set(s string) (ok bool) {
 	return
 }
 
+// readFloat reads a decimal mantissa and exponent from a float
+// string representation. It sets ok to false if the number could
+// not fit return types or is invalid.
+func readFloat(s string) (mantissa uint64, exp int, neg, trunc, ok bool) {
+	const uint64digits = 19
+	i := 0
+
+	// optional sign
+	if i >= len(s) {
+		return
+	}
+	switch {
+	case s[i] == '+':
+		i++
+	case s[i] == '-':
+		neg = true
+		i++
+	}
+
+	// digits
+	sawdot := false
+	sawdigits := false
+	nd := 0
+	ndMant := 0
+	dp := 0
+	for ; i < len(s); i++ {
+		switch c := s[i]; true {
+		case c == '.':
+			if sawdot {
+				return
+			}
+			sawdot = true
+			dp = nd
+			continue
+
+		case '0' <= c && c <= '9':
+			sawdigits = true
+			if c == '0' && nd == 0 { // ignore leading zeros
+				dp--
+				continue
+			}
+			nd++
+			if ndMant < uint64digits {
+				mantissa *= 10
+				mantissa += uint64(c - '0')
+				ndMant++
+			} else if s[i] != '0' {
+				trunc = true
+			}
+			continue
+		}
+		break
+	}
+	if !sawdigits {
+		return
+	}
+	if !sawdot {
+		dp = nd
+	}
+
+	// optional exponent moves decimal point.
+	// if we read a very large, very long number,
+	// just be sure to move the decimal point by
+	// a lot (say, 100000).  it doesn't matter if it's
+	// not the exact number.
+	if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
+		i++
+		if i >= len(s) {
+			return
+		}
+		esign := 1
+		if s[i] == '+' {
+			i++
+		} else if s[i] == '-' {
+			i++
+			esign = -1
+		}
+		if i >= len(s) || s[i] < '0' || s[i] > '9' {
+			return
+		}
+		e := 0
+		for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
+			if e < 10000 {
+				e = e*10 + int(s[i]) - '0'
+			}
+		}
+		dp += e * esign
+	}
+
+	if i != len(s) {
+		return
+	}
+
+	exp = dp - ndMant
+	ok = true
+	return
+
+}
+
 // decimal power of ten to binary power of two.
 var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26}
 
@@ -243,19 +353,6 @@ out:
 	return bits, overflow
 }
 
-// Compute exact floating-point integer from d's digits.
-// Caller is responsible for avoiding overflow.
-func (d *decimal) atof64int() float64 {
-	f := 0.0
-	for i := 0; i < d.nd; i++ {
-		f = f*10 + float64(d.d[i]-'0')
-	}
-	if d.neg {
-		f = -f
-	}
-	return f
-}
-
 func (d *decimal) atof32int() float32 {
 	f := float32(0)
 	for i := 0; i < d.nd; i++ {
@@ -267,18 +364,6 @@ func (d *decimal) atof32int() float32 {
 	return f
 }
 
-// Reads a uint64 decimal mantissa, which might be truncated.
-func (d *decimal) atou64() (mant uint64, digits int) {
-	const uint64digits = 19
-	for i, c := range d.d[:d.nd] {
-		if i == uint64digits {
-			return mant, i
-		}
-		mant = 10*mant + uint64(c-'0')
-	}
-	return mant, d.nd
-}
-
 // Exact powers of 10.
 var float64pow10 = []float64{
 	1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
@@ -287,69 +372,74 @@ var float64pow10 = []float64{
 }
 var float32pow10 = []float32{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10}
 
-// If possible to convert decimal d to 64-bit float f exactly,
+// If possible to convert decimal representation to 64-bit float f exactly,
 // entirely in floating-point math, do so, avoiding the expense of decimalToFloatBits.
 // Three common cases:
 //	value is exact integer
 //	value is exact integer * exact power of ten
 //	value is exact integer / exact power of ten
 // These all produce potentially inexact but correctly rounded answers.
-func (d *decimal) atof64() (f float64, ok bool) {
-	// Exact integers are <= 10^15.
-	// Exact powers of ten are <= 10^22.
-	if d.nd > 15 {
+func atof64exact(mantissa uint64, exp int, neg bool) (f float64, ok bool) {
+	if mantissa>>float64info.mantbits != 0 {
 		return
 	}
+	f = float64(mantissa)
+	if neg {
+		f = -f
+	}
 	switch {
-	case d.dp == d.nd: // int
-		f := d.atof64int()
+	case exp == 0:
+		// an integer.
 		return f, true
-
-	case d.dp > d.nd && d.dp <= 15+22: // int * 10^k
-		f := d.atof64int()
-		k := d.dp - d.nd
+	// Exact integers are <= 10^15.
+	// Exact powers of ten are <= 10^22.
+	case exp > 0 && exp <= 15+22: // int * 10^k
 		// If exponent is big but number of digits is not,
 		// can move a few zeros into the integer part.
-		if k > 22 {
-			f *= float64pow10[k-22]
-			k = 22
+		if exp > 22 {
+			f *= float64pow10[exp-22]
+			exp = 22
 		}
-		return f * float64pow10[k], true
-
-	case d.dp < d.nd && d.nd-d.dp <= 22: // int / 10^k
-		f := d.atof64int()
-		return f / float64pow10[d.nd-d.dp], true
+		if f > 1e15 || f < -1e15 {
+			// the exponent was really too large.
+			return
+		}
+		return f * float64pow10[exp], true
+	case exp < 0 && exp >= -22: // int / 10^k
+		return f / float64pow10[-exp], true
 	}
 	return
 }
 
-// If possible to convert decimal d to 32-bit float f exactly,
+// If possible to compute mantissa*10^exp to 32-bit float f exactly,
 // entirely in floating-point math, do so, avoiding the machinery above.
-func (d *decimal) atof32() (f float32, ok bool) {
-	// Exact integers are <= 10^7.
-	// Exact powers of ten are <= 10^10.
-	if d.nd > 7 {
+func atof32exact(mantissa uint64, exp int, neg bool) (f float32, ok bool) {
+	if mantissa>>float32info.mantbits != 0 {
 		return
 	}
+	f = float32(mantissa)
+	if neg {
+		f = -f
+	}
 	switch {
-	case d.dp == d.nd: // int
-		f := d.atof32int()
+	case exp == 0:
 		return f, true
-
-	case d.dp > d.nd && d.dp <= 7+10: // int * 10^k
-		f := d.atof32int()
-		k := d.dp - d.nd
+	// Exact integers are <= 10^7.
+	// Exact powers of ten are <= 10^10.
+	case exp > 0 && exp <= 7+10: // int * 10^k
 		// If exponent is big but number of digits is not,
 		// can move a few zeros into the integer part.
-		if k > 10 {
-			f *= float32pow10[k-10]
-			k = 10
+		if exp > 10 {
+			f *= float32pow10[exp-10]
+			exp = 10
 		}
-		return f * float32pow10[k], true
-
-	case d.dp < d.nd && d.nd-d.dp <= 10: // int / 10^k
-		f := d.atof32int()
-		return f / float32pow10[d.nd-d.dp], true
+		if f > 1e7 || f < -1e7 {
+			// the exponent was really too large.
+			return
+		}
+		return f * float32pow10[exp], true
+	case exp < 0 && exp >= -10: // int / 10^k
+		return f / float32pow10[-exp], true
 	}
 	return
 }
@@ -361,15 +451,32 @@ func atof32(s string) (f float32, err error) {
 		return float32(val), nil
 	}
 
+	if optimize {
+		// Parse mantissa and exponent.
+		mantissa, exp, neg, trunc, ok := readFloat(s)
+		if ok {
+			// Try pure floating-point arithmetic conversion.
+			if !trunc {
+				if f, ok := atof32exact(mantissa, exp, neg); ok {
+					return f, nil
+				}
+			}
+			// Try another fast path.
+			ext := new(extFloat)
+			if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float32info); ok {
+				b, ovf := ext.floatBits(&float32info)
+				f = math.Float32frombits(uint32(b))
+				if ovf {
+					err = rangeError(fnParseFloat, s)
+				}
+				return f, err
+			}
+		}
+	}
 	var d decimal
 	if !d.set(s) {
 		return 0, syntaxError(fnParseFloat, s)
 	}
-	if optimize {
-		if f, ok := d.atof32(); ok {
-			return f, nil
-		}
-	}
 	b, ovf := d.floatBits(&float32info)
 	f = math.Float32frombits(uint32(b))
 	if ovf {
@@ -383,26 +490,32 @@ func atof64(s string) (f float64, err error) {
 		return val, nil
 	}
 
-	var d decimal
-	if !d.set(s) {
-		return 0, syntaxError(fnParseFloat, s)
-	}
 	if optimize {
-		if f, ok := d.atof64(); ok {
-			return f, nil
-		}
-
-		// Try another fast path.
-		ext := new(extFloat)
-		if ok := ext.AssignDecimal(&d); ok {
-			b, ovf := ext.floatBits()
-			f = math.Float64frombits(b)
-			if ovf {
-				err = rangeError(fnParseFloat, s)
+		// Parse mantissa and exponent.
+		mantissa, exp, neg, trunc, ok := readFloat(s)
+		if ok {
+			// Try pure floating-point arithmetic conversion.
+			if !trunc {
+				if f, ok := atof64exact(mantissa, exp, neg); ok {
+					return f, nil
+				}
+			}
+			// Try another fast path.
+			ext := new(extFloat)
+			if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float64info); ok {
+				b, ovf := ext.floatBits(&float64info)
+				f = math.Float64frombits(b)
+				if ovf {
+					err = rangeError(fnParseFloat, s)
+				}
+				return f, err
 			}
-			return f, err
 		}
 	}
+	var d decimal
+	if !d.set(s) {
+		return 0, syntaxError(fnParseFloat, s)
+	}
 	b, ovf := d.floatBits(&float64info)
 	f = math.Float64frombits(b)
 	if ovf {
diff --git a/src/pkg/strconv/atof_test.go b/src/pkg/strconv/atof_test.go
index 5995023..ba49332 100644
--- a/src/pkg/strconv/atof_test.go
+++ b/src/pkg/strconv/atof_test.go
@@ -110,6 +110,7 @@ var atoftests = []atofTest{
 	{"1e", "0", ErrSyntax},
 	{"1e-", "0", ErrSyntax},
 	{".e-1", "0", ErrSyntax},
+	{"1\x00.2", "0", ErrSyntax},
 
 	// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
 	{"2.2250738585072012e-308", "2.2250738585072014e-308", nil},
@@ -134,6 +135,54 @@ var atoftests = []atofTest{
 	{"1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1", "1.0000000000000002", nil},
 }
 
+var atof32tests = []atofTest{
+	// Exactly halfway between 1 and the next float32.
+	// Round to even (down).
+	{"1.000000059604644775390625", "1", nil},
+	// Slightly lower.
+	{"1.000000059604644775390624", "1", nil},
+	// Slightly higher.
+	{"1.000000059604644775390626", "1.0000001", nil},
+	// Slightly higher, but you have to read all the way to the end.
+	{"1.000000059604644775390625" + strings.Repeat("0", 10000) + "1", "1.0000001", nil},
+
+	// largest float32: (1<<128) * (1 - 2^-24)
+	{"340282346638528859811704183484516925440", "3.4028235e+38", nil},
+	{"-340282346638528859811704183484516925440", "-3.4028235e+38", nil},
+	// next float32 - too large
+	{"3.4028236e38", "+Inf", ErrRange},
+	{"-3.4028236e38", "-Inf", ErrRange},
+	// the border is 3.40282356779...e+38
+	// borderline - okay
+	{"3.402823567e38", "3.4028235e+38", nil},
+	{"-3.402823567e38", "-3.4028235e+38", nil},
+	// borderline - too large
+	{"3.4028235678e38", "+Inf", ErrRange},
+	{"-3.4028235678e38", "-Inf", ErrRange},
+
+	// Denormals: less than 2^-126
+	{"1e-38", "1e-38", nil},
+	{"1e-39", "1e-39", nil},
+	{"1e-40", "1e-40", nil},
+	{"1e-41", "1e-41", nil},
+	{"1e-42", "1e-42", nil},
+	{"1e-43", "1e-43", nil},
+	{"1e-44", "1e-44", nil},
+	{"6e-45", "6e-45", nil}, // 4p-149 = 5.6e-45
+	{"5e-45", "6e-45", nil},
+	// Smallest denormal
+	{"1e-45", "1e-45", nil}, // 1p-149 = 1.4e-45
+	{"2e-45", "1e-45", nil},
+
+	// 2^92 = 8388608p+69 = 4951760157141521099596496896 (4.9517602e27)
+	// is an exact power of two that needs 8 decimal digits to be correctly
+	// parsed back.
+	// The float32 before is 16777215p+68 = 4.95175986e+27
+	// The halfway is 4.951760009. A bad algorithm that thinks the previous
+	// float32 is 8388607p+69 will shorten incorrectly to 4.95176e+27.
+	{"4951760157141521099596496896", "4.9517602e+27", nil},
+}
+
 type atofSimpleTest struct {
 	x float64
 	s string
@@ -154,6 +203,12 @@ func init() {
 			test.err = &NumError{"ParseFloat", test.in, test.err}
 		}
 	}
+	for i := range atof32tests {
+		test := &atof32tests[i]
+		if test.err != nil {
+			test.err = &NumError{"ParseFloat", test.in, test.err}
+		}
+	}
 
 	// Generate random inputs for tests and benchmarks
 	rand.Seed(time.Now().UnixNano())
@@ -206,6 +261,19 @@ func testAtof(t *testing.T, opt bool) {
 			}
 		}
 	}
+	for _, test := range atof32tests {
+		out, err := ParseFloat(test.in, 32)
+		out32 := float32(out)
+		if float64(out32) != out {
+			t.Errorf("ParseFloat(%v, 32) = %v, not a float32 (closest is %v)", test.in, out, float64(out32))
+			continue
+		}
+		outs := FormatFloat(float64(out32), 'g', -1, 32)
+		if outs != test.out || !reflect.DeepEqual(err, test.err) {
+			t.Errorf("ParseFloat(%v, 32) = %v, %v want %v, %v  # %v",
+				test.in, out32, err, test.out, test.err, out)
+		}
+	}
 	SetOptimize(oldopt)
 }
 
@@ -264,6 +332,35 @@ func TestRoundTrip(t *testing.T) {
 	}
 }
 
+// TestRoundTrip32 tries a fraction of all finite positive float32 values.
+func TestRoundTrip32(t *testing.T) {
+	step := uint32(997)
+	if testing.Short() {
+		step = 99991
+	}
+	count := 0
+	for i := uint32(0); i < 0xff<<23; i += step {
+		f := math.Float32frombits(i)
+		if i&1 == 1 {
+			f = -f // negative
+		}
+		s := FormatFloat(float64(f), 'g', -1, 32)
+
+		parsed, err := ParseFloat(s, 32)
+		parsed32 := float32(parsed)
+		switch {
+		case err != nil:
+			t.Errorf("ParseFloat(%q, 32) gave error %s", s, err)
+		case float64(parsed32) != parsed:
+			t.Errorf("ParseFloat(%q, 32) = %v, not a float32 (nearest is %v)", s, parsed, parsed32)
+		case parsed32 != f:
+			t.Errorf("ParseFloat(%q, 32) = %b (expected %b)", s, parsed32, f)
+		}
+		count++
+	}
+	t.Logf("tested %d float32's", count)
+}
+
 func BenchmarkAtof64Decimal(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		ParseFloat("33909", 64)
@@ -299,3 +396,35 @@ func BenchmarkAtof64RandomFloats(b *testing.B) {
 		ParseFloat(benchmarksRandomNormal[i%1024], 64)
 	}
 }
+
+func BenchmarkAtof32Decimal(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat("33909", 32)
+	}
+}
+
+func BenchmarkAtof32Float(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat("339.778", 32)
+	}
+}
+
+func BenchmarkAtof32FloatExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat("12.3456e32", 32)
+	}
+}
+
+var float32strings [4096]string
+
+func BenchmarkAtof32Random(b *testing.B) {
+	n := uint32(997)
+	for i := range float32strings {
+		n = (99991*n + 42) % (0xff << 23)
+		float32strings[i] = FormatFloat(float64(math.Float32frombits(n)), 'g', -1, 32)
+	}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		ParseFloat(float32strings[i%4096], 32)
+	}
+}
diff --git a/src/pkg/strconv/atoi.go b/src/pkg/strconv/atoi.go
index 59ef264..21c6900 100644
--- a/src/pkg/strconv/atoi.go
+++ b/src/pkg/strconv/atoi.go
@@ -20,7 +20,7 @@ type NumError struct {
 }
 
 func (e *NumError) Error() string {
-	return "strconv." + e.Func + ": " + `parsing "` + e.Num + `": ` + e.Err.Error()
+	return "strconv." + e.Func + ": " + "parsing " + Quote(e.Num) + ": " + e.Err.Error()
 }
 
 func syntaxError(fn, str string) *NumError {
@@ -44,7 +44,7 @@ func cutoff64(base int) uint64 {
 }
 
 // ParseUint is like ParseInt but for unsigned numbers.
-func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
+func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
 	var cutoff, maxVal uint64
 
 	if bitSize == 0 {
@@ -57,32 +57,32 @@ func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
 		err = ErrSyntax
 		goto Error
 
-	case 2 <= b && b <= 36:
+	case 2 <= base && base <= 36:
 		// valid base; nothing to do
 
-	case b == 0:
+	case base == 0:
 		// Look for octal, hex prefix.
 		switch {
 		case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
-			b = 16
+			base = 16
 			s = s[2:]
 			if len(s) < 1 {
 				err = ErrSyntax
 				goto Error
 			}
 		case s[0] == '0':
-			b = 8
+			base = 8
 		default:
-			b = 10
+			base = 10
 		}
 
 	default:
-		err = errors.New("invalid base " + Itoa(b))
+		err = errors.New("invalid base " + Itoa(base))
 		goto Error
 	}
 
 	n = 0
-	cutoff = cutoff64(b)
+	cutoff = cutoff64(base)
 	maxVal = 1<<uint(bitSize) - 1
 
 	for i := 0; i < len(s); i++ {
@@ -100,19 +100,19 @@ func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
 			err = ErrSyntax
 			goto Error
 		}
-		if int(v) >= b {
+		if int(v) >= base {
 			n = 0
 			err = ErrSyntax
 			goto Error
 		}
 
 		if n >= cutoff {
-			// n*b overflows
+			// n*base overflows
 			n = 1<<64 - 1
 			err = ErrRange
 			goto Error
 		}
-		n *= uint64(b)
+		n *= uint64(base)
 
 		n1 := n + uint64(v)
 		if n1 < n || n1 > maxVal {
diff --git a/src/pkg/strconv/atoi_test.go b/src/pkg/strconv/atoi_test.go
index d0e7b61..9407573 100644
--- a/src/pkg/strconv/atoi_test.go
+++ b/src/pkg/strconv/atoi_test.go
@@ -5,6 +5,7 @@
 package strconv_test
 
 import (
+	"errors"
 	"reflect"
 	. "strconv"
 	"testing"
@@ -146,6 +147,16 @@ var atoi32tests = []atoi32Test{
 	{"-2147483649", -1 << 31, ErrRange},
 }
 
+type numErrorTest struct {
+	num, want string
+}
+
+var numErrorTests = []numErrorTest{
+	{"0", `strconv.ParseFloat: parsing "0": failed`},
+	{"`", "strconv.ParseFloat: parsing \"`\": failed"},
+	{"1\x00.2", `strconv.ParseFloat: parsing "1\x00.2": failed`},
+}
+
 func init() {
 	// The atoi routines return NumErrors wrapping
 	// the error and the string.  Convert the tables above.
@@ -277,6 +288,19 @@ func TestParseInt(t *testing.T) {
 	}
 }
 
+func TestNumError(t *testing.T) {
+	for _, test := range numErrorTests {
+		err := &NumError{
+			Func: "ParseFloat",
+			Num:  test.num,
+			Err:  errors.New("failed"),
+		}
+		if got := err.Error(); got != test.want {
+			t.Errorf(`(&NumError{"ParseFloat", %q, "failed"}).Error() = %v, want %v`, test.num, got, test.want)
+		}
+	}
+}
+
 func BenchmarkAtoi(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		ParseInt("12345678", 10, 0)
diff --git a/src/pkg/strconv/decimal.go b/src/pkg/strconv/decimal.go
index a75071d..4260128 100644
--- a/src/pkg/strconv/decimal.go
+++ b/src/pkg/strconv/decimal.go
@@ -79,7 +79,7 @@ func trim(a *decimal) {
 
 // Assign v to a.
 func (a *decimal) Assign(v uint64) {
-	var buf [50]byte
+	var buf [24]byte
 
 	// Write reversed decimal in buf.
 	n := 0
diff --git a/src/pkg/strconv/extfloat.go b/src/pkg/strconv/extfloat.go
index aa5e560..b7eaaa6 100644
--- a/src/pkg/strconv/extfloat.go
+++ b/src/pkg/strconv/extfloat.go
@@ -4,8 +4,6 @@
 
 package strconv
 
-import "math"
-
 // An extFloat represents an extended floating-point number, with more
 // precision than a float64. It does not try to save bits: the
 // number represented by the structure is mant*(2^exp), with a negative
@@ -127,8 +125,7 @@ var powersOfTen = [...]extFloat{
 // floatBits returns the bits of the float64 that best approximates
 // the extFloat passed as receiver. Overflow is set to true if
 // the resulting float64 is ±Inf.
-func (f *extFloat) floatBits() (bits uint64, overflow bool) {
-	flt := &float64info
+func (f *extFloat) floatBits(flt *floatInfo) (bits uint64, overflow bool) {
 	f.Normalize()
 
 	exp := f.exp + 63
@@ -140,7 +137,7 @@ func (f *extFloat) floatBits() (bits uint64, overflow bool) {
 		exp += n
 	}
 
-	// Extract 1+flt.mantbits bits.
+	// Extract 1+flt.mantbits bits from the 64-bit mantissa.
 	mant := f.mant >> (63 - flt.mantbits)
 	if f.mant&(1<<(62-flt.mantbits)) != 0 {
 		// Round up.
@@ -155,22 +152,14 @@ func (f *extFloat) floatBits() (bits uint64, overflow bool) {
 
 	// Infinities.
 	if exp-flt.bias >= 1<<flt.expbits-1 {
-		goto overflow
-	}
-
-	// Denormalized?
-	if mant&(1<<flt.mantbits) == 0 {
+		// ±Inf
+		mant = 0
+		exp = 1<<flt.expbits - 1 + flt.bias
+		overflow = true
+	} else if mant&(1<<flt.mantbits) == 0 {
+		// Denormalized?
 		exp = flt.bias
 	}
-	goto out
-
-overflow:
-	// ±Inf
-	mant = 0
-	exp = 1<<flt.expbits - 1 + flt.bias
-	overflow = true
-
-out:
 	// Assemble bits.
 	bits = mant & (uint64(1)<<flt.mantbits - 1)
 	bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
@@ -180,40 +169,24 @@ out:
 	return
 }
 
-// Assign sets f to the value of x.
-func (f *extFloat) Assign(x float64) {
-	if x < 0 {
-		x = -x
-		f.neg = true
-	}
-	x, f.exp = math.Frexp(x)
-	f.mant = uint64(x * float64(1<<64))
-	f.exp -= 64
-}
-
-// AssignComputeBounds sets f to the value of x and returns
+// AssignComputeBounds sets f to the floating point value
+// defined by mant, exp and precision given by flt. It returns
 // lower, upper such that any number in the closed interval
-// [lower, upper] is converted back to x.
-func (f *extFloat) AssignComputeBounds(x float64) (lower, upper extFloat) {
-	// Special cases.
-	bits := math.Float64bits(x)
-	flt := &float64info
-	neg := bits>>(flt.expbits+flt.mantbits) != 0
-	expBiased := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
-	mant := bits & (uint64(1)<<flt.mantbits - 1)
-
-	if expBiased == 0 {
-		// denormalized.
-		f.mant = mant
-		f.exp = 1 + flt.bias - int(flt.mantbits)
-	} else {
-		f.mant = mant | 1<<flt.mantbits
-		f.exp = expBiased + flt.bias - int(flt.mantbits)
-	}
+// [lower, upper] is converted back to the same floating point number.
+func (f *extFloat) AssignComputeBounds(mant uint64, exp int, neg bool, flt *floatInfo) (lower, upper extFloat) {
+	f.mant = mant
+	f.exp = exp - int(flt.mantbits)
 	f.neg = neg
+	if f.exp <= 0 && mant == (mant>>uint(-f.exp))<<uint(-f.exp) {
+		// An exact integer
+		f.mant >>= uint(-f.exp)
+		f.exp = 0
+		return *f, *f
+	}
+	expBiased := exp - flt.bias
 
 	upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg}
-	if mant != 0 || expBiased == 1 {
+	if mant != 1<<flt.mantbits || expBiased == 1 {
 		lower = extFloat{mant: 2*f.mant - 1, exp: f.exp - 1, neg: f.neg}
 	} else {
 		lower = extFloat{mant: 4*f.mant - 1, exp: f.exp - 2, neg: f.neg}
@@ -223,20 +196,38 @@ func (f *extFloat) AssignComputeBounds(x float64) (lower, upper extFloat) {
 
 // Normalize normalizes f so that the highest bit of the mantissa is
 // set, and returns the number by which the mantissa was left-shifted.
-func (f *extFloat) Normalize() uint {
-	if f.mant == 0 {
+func (f *extFloat) Normalize() (shift uint) {
+	mant, exp := f.mant, f.exp
+	if mant == 0 {
 		return 0
 	}
-	exp_before := f.exp
-	for f.mant < (1 << 55) {
-		f.mant <<= 8
-		f.exp -= 8
+	if mant>>(64-32) == 0 {
+		mant <<= 32
+		exp -= 32
+	}
+	if mant>>(64-16) == 0 {
+		mant <<= 16
+		exp -= 16
 	}
-	for f.mant < (1 << 63) {
-		f.mant <<= 1
-		f.exp -= 1
+	if mant>>(64-8) == 0 {
+		mant <<= 8
+		exp -= 8
 	}
-	return uint(exp_before - f.exp)
+	if mant>>(64-4) == 0 {
+		mant <<= 4
+		exp -= 4
+	}
+	if mant>>(64-2) == 0 {
+		mant <<= 2
+		exp -= 2
+	}
+	if mant>>(64-1) == 0 {
+		mant <<= 1
+		exp -= 1
+	}
+	shift = uint(f.exp - exp)
+	f.mant, f.exp = mant, exp
+	return
 }
 
 // Multiply sets f to the product f*g: the result is correctly rounded,
@@ -264,24 +255,22 @@ var uint64pow10 = [...]uint64{
 	1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
 }
 
-// AssignDecimal sets f to an approximate value of the decimal d. It
+// AssignDecimal sets f to an approximate value mantissa*10^exp. It
 // returns true if the value represented by f is guaranteed to be the
-// best approximation of d after being rounded to a float64. 
-func (f *extFloat) AssignDecimal(d *decimal) (ok bool) {
+// best approximation of d after being rounded to a float64 or
+// float32 depending on flt.
+func (f *extFloat) AssignDecimal(mantissa uint64, exp10 int, neg bool, trunc bool, flt *floatInfo) (ok bool) {
 	const uint64digits = 19
 	const errorscale = 8
-	mant10, digits := d.atou64()
-	exp10 := d.dp - digits
 	errors := 0 // An upper bound for error, computed in errorscale*ulp.
-
-	if digits < d.nd {
+	if trunc {
 		// the decimal number was truncated.
 		errors += errorscale / 2
 	}
 
-	f.mant = mant10
+	f.mant = mantissa
 	f.exp = 0
-	f.neg = d.neg
+	f.neg = neg
 
 	// Multiply by powers of ten.
 	i := (exp10 - firstPowerOfTen) / stepPowerOfTen
@@ -291,9 +280,9 @@ func (f *extFloat) AssignDecimal(d *decimal) (ok bool) {
 	adjExp := (exp10 - firstPowerOfTen) % stepPowerOfTen
 
 	// We multiply by exp%step
-	if digits+adjExp <= uint64digits {
-		// We can multiply the mantissa
-		f.mant *= uint64(float64pow10[adjExp])
+	if adjExp < uint64digits && mantissa < uint64pow10[uint64digits-adjExp] {
+		// We can multiply the mantissa exactly.
+		f.mant *= uint64pow10[adjExp]
 		f.Normalize()
 	} else {
 		f.Normalize()
@@ -318,10 +307,10 @@ func (f *extFloat) AssignDecimal(d *decimal) (ok bool) {
 	// The 64 bits mantissa is 1 + 52 bits for float64 + 11 extra bits.
 	//
 	// In many cases the approximation will be good enough.
-	const denormalExp = -1023 - 63
-	flt := &float64info
+	denormalExp := flt.bias - 63
 	var extrabits uint
 	if f.exp <= denormalExp {
+		// f.mant * 2^f.exp is smaller than 2^(flt.bias+1).
 		extrabits = uint(63 - flt.mantbits + 1 + uint(denormalExp-f.exp))
 	} else {
 		extrabits = uint(63 - flt.mantbits)
@@ -344,16 +333,17 @@ func (f *extFloat) AssignDecimal(d *decimal) (ok bool) {
 // f by an approximate power of ten 10^-exp, and returns exp10, so
 // that f*10^exp10 has the same value as the old f, up to an ulp,
 // as well as the index of 10^-exp in the powersOfTen table.
-// The arguments expMin and expMax constrain the final value of the
-// binary exponent of f.
-func (f *extFloat) frexp10(expMin, expMax int) (exp10, index int) {
-	// it is illegal to call this function with a too restrictive exponent range.
-	if expMax-expMin <= 25 {
-		panic("strconv: invalid exponent range")
-	}
+func (f *extFloat) frexp10() (exp10, index int) {
+	// The constants expMin and expMax constrain the final value of the
+	// binary exponent of f. We want a small integral part in the result
+	// because finding digits of an integer requires divisions, whereas
+	// digits of the fractional part can be found by repeatedly multiplying
+	// by 10.
+	const expMin = -60
+	const expMax = -32
 	// Find power of ten such that x * 10^n has a binary exponent
-	// between expMin and expMax
-	approxExp10 := -(f.exp + 100) * 28 / 93 // log(10)/log(2) is close to 93/28.
+	// between expMin and expMax.
+	approxExp10 := ((expMin+expMax)/2 - f.exp) * 28 / 93 // log(10)/log(2) is close to 93/28.
 	i := (approxExp10 - firstPowerOfTen) / stepPowerOfTen
 Loop:
 	for {
@@ -375,26 +365,202 @@ Loop:
 }
 
 // frexp10Many applies a common shift by a power of ten to a, b, c.
-func frexp10Many(expMin, expMax int, a, b, c *extFloat) (exp10 int) {
-	exp10, i := c.frexp10(expMin, expMax)
+func frexp10Many(a, b, c *extFloat) (exp10 int) {
+	exp10, i := c.frexp10()
 	a.Multiply(powersOfTen[i])
 	b.Multiply(powersOfTen[i])
 	return
 }
 
+// FixedDecimal stores in d the first n significant digits
+// of the decimal representation of f. It returns false
+// if it cannot be sure of the answer.
+func (f *extFloat) FixedDecimal(d *decimalSlice, n int) bool {
+	if f.mant == 0 {
+		d.nd = 0
+		d.dp = 0
+		d.neg = f.neg
+		return true
+	}
+	if n == 0 {
+		panic("strconv: internal error: extFloat.FixedDecimal called with n == 0")
+	}
+	// Multiply by an appropriate power of ten to have a reasonable
+	// number to process.
+	f.Normalize()
+	exp10, _ := f.frexp10()
+
+	shift := uint(-f.exp)
+	integer := uint32(f.mant >> shift)
+	fraction := f.mant - (uint64(integer) << shift)
+	ε := uint64(1) // ε is the uncertainty we have on the mantissa of f.
+
+	// Write exactly n digits to d.
+	needed := n        // how many digits are left to write.
+	integerDigits := 0 // the number of decimal digits of integer.
+	pow10 := uint64(1) // the power of ten by which f was scaled.
+	for i, pow := 0, uint64(1); i < 20; i++ {
+		if pow > uint64(integer) {
+			integerDigits = i
+			break
+		}
+		pow *= 10
+	}
+	rest := integer
+	if integerDigits > needed {
+		// the integral part is already large, trim the last digits.
+		pow10 = uint64pow10[integerDigits-needed]
+		integer /= uint32(pow10)
+		rest -= integer * uint32(pow10)
+	} else {
+		rest = 0
+	}
+
+	// Write the digits of integer: the digits of rest are omitted.
+	var buf [32]byte
+	pos := len(buf)
+	for v := integer; v > 0; {
+		v1 := v / 10
+		v -= 10 * v1
+		pos--
+		buf[pos] = byte(v + '0')
+		v = v1
+	}
+	for i := pos; i < len(buf); i++ {
+		d.d[i-pos] = buf[i]
+	}
+	nd := len(buf) - pos
+	d.nd = nd
+	d.dp = integerDigits + exp10
+	needed -= nd
+
+	if needed > 0 {
+		if rest != 0 || pow10 != 1 {
+			panic("strconv: internal error, rest != 0 but needed > 0")
+		}
+		// Emit digits for the fractional part. Each time, 10*fraction
+		// fits in a uint64 without overflow.
+		for needed > 0 {
+			fraction *= 10
+			ε *= 10 // the uncertainty scales as we multiply by ten.
+			if 2*ε > 1<<shift {
+				// the error is so large it could modify which digit to write, abort.
+				return false
+			}
+			digit := fraction >> shift
+			d.d[nd] = byte(digit + '0')
+			fraction -= digit << shift
+			nd++
+			needed--
+		}
+		d.nd = nd
+	}
+
+	// We have written a truncation of f (a numerator / 10^d.dp). The remaining part
+	// can be interpreted as a small number (< 1) to be added to the last digit of the
+	// numerator.
+	//
+	// If rest > 0, the amount is:
+	//    (rest<<shift | fraction) / (pow10 << shift)
+	//    fraction being known with a ±ε uncertainty.
+	//    The fact that n > 0 guarantees that pow10 << shift does not overflow a uint64.
+	//
+	// If rest = 0, pow10 == 1 and the amount is
+	//    fraction / (1 << shift)
+	//    fraction being known with a ±ε uncertainty.
+	//
+	// We pass this information to the rounding routine for adjustment.
+
+	ok := adjustLastDigitFixed(d, uint64(rest)<<shift|fraction, pow10, shift, ε)
+	if !ok {
+		return false
+	}
+	// Trim trailing zeros.
+	for i := d.nd - 1; i >= 0; i-- {
+		if d.d[i] != '0' {
+			d.nd = i + 1
+			break
+		}
+	}
+	return true
+}
+
+// adjustLastDigitFixed assumes d contains the representation of the integral part
+// of some number, whose fractional part is num / (den << shift). The numerator
+// num is only known up to an uncertainty of size ε, assumed to be less than
+// (den << shift)/2.
+//
+// It will increase the last digit by one to account for correct rounding, typically
+// when the fractional part is greater than 1/2, and will return false if ε is such
+// that no correct answer can be given.
+func adjustLastDigitFixed(d *decimalSlice, num, den uint64, shift uint, ε uint64) bool {
+	if num > den<<shift {
+		panic("strconv: num > den<<shift in adjustLastDigitFixed")
+	}
+	if 2*ε > den<<shift {
+		panic("strconv: ε > (den<<shift)/2")
+	}
+	if 2*(num+ε) < den<<shift {
+		return true
+	}
+	if 2*(num-ε) > den<<shift {
+		// increment d by 1.
+		i := d.nd - 1
+		for ; i >= 0; i-- {
+			if d.d[i] == '9' {
+				d.nd--
+			} else {
+				break
+			}
+		}
+		if i < 0 {
+			d.d[0] = '1'
+			d.nd = 1
+			d.dp++
+		} else {
+			d.d[i]++
+		}
+		return true
+	}
+	return false
+}
+
 // ShortestDecimal stores in d the shortest decimal representation of f
 // which belongs to the open interval (lower, upper), where f is supposed
 // to lie. It returns false whenever the result is unsure. The implementation
 // uses the Grisu3 algorithm.
-func (f *extFloat) ShortestDecimal(d *decimal, lower, upper *extFloat) bool {
+func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool {
 	if f.mant == 0 {
-		d.d[0] = '0'
-		d.nd = 1
+		d.nd = 0
 		d.dp = 0
 		d.neg = f.neg
+		return true
+	}
+	if f.exp == 0 && *lower == *f && *lower == *upper {
+		// an exact integer.
+		var buf [24]byte
+		n := len(buf) - 1
+		for v := f.mant; v > 0; {
+			v1 := v / 10
+			v -= 10 * v1
+			buf[n] = byte(v + '0')
+			n--
+			v = v1
+		}
+		nd := len(buf) - n - 1
+		for i := 0; i < nd; i++ {
+			d.d[i] = buf[n+1+i]
+		}
+		d.nd, d.dp = nd, nd
+		for d.nd > 0 && d.d[d.nd-1] == '0' {
+			d.nd--
+		}
+		if d.nd == 0 {
+			d.dp = 0
+		}
+		d.neg = f.neg
+		return true
 	}
-	const minExp = -60
-	const maxExp = -32
 	upper.Normalize()
 	// Uniformize exponents.
 	if f.exp > upper.exp {
@@ -406,7 +572,7 @@ func (f *extFloat) ShortestDecimal(d *decimal, lower, upper *extFloat) bool {
 		lower.exp = upper.exp
 	}
 
-	exp10 := frexp10Many(minExp, maxExp, lower, f, upper)
+	exp10 := frexp10Many(lower, f, upper)
 	// Take a safety margin due to rounding in frexp10Many, but we lose precision.
 	upper.mant++
 	lower.mant--
@@ -424,10 +590,12 @@ func (f *extFloat) ShortestDecimal(d *decimal, lower, upper *extFloat) bool {
 
 	// Count integral digits: there are at most 10.
 	var integerDigits int
-	for i, pow := range uint64pow10 {
-		if uint64(integer) >= pow {
-			integerDigits = i + 1
+	for i, pow := 0, uint64(1); i < 20; i++ {
+		if pow > uint64(integer) {
+			integerDigits = i
+			break
 		}
+		pow *= 10
 	}
 	for i := 0; i < integerDigits; i++ {
 		pow := uint64pow10[integerDigits-i-1]
@@ -471,11 +639,11 @@ func (f *extFloat) ShortestDecimal(d *decimal, lower, upper *extFloat) bool {
 	return false
 }
 
-// adjustLastDigit modifies d = x-currentDiff*ε, to get closest to 
+// adjustLastDigit modifies d = x-currentDiff*ε, to get closest to
 // d = x-targetDiff*ε, without becoming smaller than x-maxDiff*ε.
 // It assumes that a decimal digit is worth ulpDecimal*ε, and that
 // all data is known with a error estimate of ulpBinary*ε.
-func adjustLastDigit(d *decimal, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool {
+func adjustLastDigit(d *decimalSlice, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool {
 	if ulpDecimal < 2*ulpBinary {
 		// Approximation is too wide.
 		return false
diff --git a/src/pkg/strconv/fp_test.go b/src/pkg/strconv/fp_test.go
index 171defa..6de2f8b 100644
--- a/src/pkg/strconv/fp_test.go
+++ b/src/pkg/strconv/fp_test.go
@@ -7,7 +7,6 @@ package strconv_test
 import (
 	"bufio"
 	"fmt"
-	"io"
 	"os"
 	"strconv"
 	"strings"
@@ -96,31 +95,22 @@ func myatof32(s string) (f float32, ok bool) {
 }
 
 func TestFp(t *testing.T) {
-	f, err := os.Open("testfp.txt")
+	f, err := os.Open("testdata/testfp.txt")
 	if err != nil {
-		t.Fatal("testfp: open testfp.txt:", err)
+		t.Fatal("testfp: open testdata/testfp.txt:", err)
 	}
 	defer f.Close()
 
-	b := bufio.NewReader(f)
+	s := bufio.NewScanner(f)
 
-	lineno := 0
-	for {
-		line, err2 := b.ReadString('\n')
-		if err2 == io.EOF {
-			break
-		}
-		if err2 != nil {
-			t.Fatal("testfp: read testfp.txt: " + err2.Error())
-		}
-		line = line[0 : len(line)-1]
-		lineno++
+	for lineno := 1; s.Scan(); lineno++ {
+		line := s.Text()
 		if len(line) == 0 || line[0] == '#' {
 			continue
 		}
 		a := strings.Split(line, " ")
 		if len(a) != 4 {
-			t.Error("testfp.txt:", lineno, ": wrong field count")
+			t.Error("testdata/testfp.txt:", lineno, ": wrong field count")
 			continue
 		}
 		var s string
@@ -130,22 +120,25 @@ func TestFp(t *testing.T) {
 			var ok bool
 			v, ok = myatof64(a[2])
 			if !ok {
-				t.Error("testfp.txt:", lineno, ": cannot atof64 ", a[2])
+				t.Error("testdata/testfp.txt:", lineno, ": cannot atof64 ", a[2])
 				continue
 			}
 			s = fmt.Sprintf(a[1], v)
 		case "float32":
 			v1, ok := myatof32(a[2])
 			if !ok {
-				t.Error("testfp.txt:", lineno, ": cannot atof32 ", a[2])
+				t.Error("testdata/testfp.txt:", lineno, ": cannot atof32 ", a[2])
 				continue
 			}
 			s = fmt.Sprintf(a[1], v1)
 			v = float64(v1)
 		}
 		if s != a[3] {
-			t.Error("testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ",
+			t.Error("testdata/testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ",
 				"want ", a[3], " got ", s)
 		}
 	}
+	if s.Err() != nil {
+		t.Fatal("testfp: read testdata/testfp.txt: ", s.Err())
+	}
 }
diff --git a/src/pkg/strconv/ftoa.go b/src/pkg/strconv/ftoa.go
index 8eefbee..1a9c41b 100644
--- a/src/pkg/strconv/ftoa.go
+++ b/src/pkg/strconv/ftoa.go
@@ -98,42 +98,79 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
 		return fmtB(dst, neg, mant, exp, flt)
 	}
 
+	if !optimize {
+		return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
+	}
+
+	var digs decimalSlice
+	ok := false
 	// Negative precision means "only as much as needed to be exact."
 	shortest := prec < 0
-
-	d := new(decimal)
 	if shortest {
-		ok := false
-		if optimize && bitSize == 64 {
-			// Try Grisu3 algorithm.
-			f := new(extFloat)
-			lower, upper := f.AssignComputeBounds(val)
-			ok = f.ShortestDecimal(d, &lower, &upper)
-		}
+		// Try Grisu3 algorithm.
+		f := new(extFloat)
+		lower, upper := f.AssignComputeBounds(mant, exp, neg, flt)
+		var buf [32]byte
+		digs.d = buf[:]
+		ok = f.ShortestDecimal(&digs, &lower, &upper)
 		if !ok {
-			// Create exact decimal representation.
-			// The shift is exp - flt.mantbits because mant is a 1-bit integer
-			// followed by a flt.mantbits fraction, and we are treating it as
-			// a 1+flt.mantbits-bit integer.
-			d.Assign(mant)
-			d.Shift(exp - int(flt.mantbits))
-			roundShortest(d, mant, exp, flt)
+			return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
 		}
 		// Precision for shortest representation mode.
-		if prec < 0 {
-			switch fmt {
-			case 'e', 'E':
-				prec = d.nd - 1
-			case 'f':
-				prec = max(d.nd-d.dp, 0)
-			case 'g', 'G':
-				prec = d.nd
+		switch fmt {
+		case 'e', 'E':
+			prec = digs.nd - 1
+		case 'f':
+			prec = max(digs.nd-digs.dp, 0)
+		case 'g', 'G':
+			prec = digs.nd
+		}
+	} else if fmt != 'f' {
+		// Fixed number of digits.
+		digits := prec
+		switch fmt {
+		case 'e', 'E':
+			digits++
+		case 'g', 'G':
+			if prec == 0 {
+				prec = 1
 			}
+			digits = prec
+		}
+		if digits <= 15 {
+			// try fast algorithm when the number of digits is reasonable.
+			var buf [24]byte
+			digs.d = buf[:]
+			f := extFloat{mant, exp - int(flt.mantbits), neg}
+			ok = f.FixedDecimal(&digs, digits)
+		}
+	}
+	if !ok {
+		return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
+	}
+	return formatDigits(dst, shortest, neg, digs, prec, fmt)
+}
+
+// bigFtoa uses multiprecision computations to format a float.
+func bigFtoa(dst []byte, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {
+	d := new(decimal)
+	d.Assign(mant)
+	d.Shift(exp - int(flt.mantbits))
+	var digs decimalSlice
+	shortest := prec < 0
+	if shortest {
+		roundShortest(d, mant, exp, flt)
+		digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
+		// Precision for shortest representation mode.
+		switch fmt {
+		case 'e', 'E':
+			prec = digs.nd - 1
+		case 'f':
+			prec = max(digs.nd-digs.dp, 0)
+		case 'g', 'G':
+			prec = digs.nd
 		}
 	} else {
-		// Create exact decimal representation.
-		d.Assign(mant)
-		d.Shift(exp - int(flt.mantbits))
 		// Round appropriately.
 		switch fmt {
 		case 'e', 'E':
@@ -146,18 +183,22 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
 			}
 			d.Round(prec)
 		}
+		digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
 	}
+	return formatDigits(dst, shortest, neg, digs, prec, fmt)
+}
 
+func formatDigits(dst []byte, shortest bool, neg bool, digs decimalSlice, prec int, fmt byte) []byte {
 	switch fmt {
 	case 'e', 'E':
-		return fmtE(dst, neg, d, prec, fmt)
+		return fmtE(dst, neg, digs, prec, fmt)
 	case 'f':
-		return fmtF(dst, neg, d, prec)
+		return fmtF(dst, neg, digs, prec)
 	case 'g', 'G':
 		// trailing fractional zeros in 'e' form will be trimmed.
 		eprec := prec
-		if eprec > d.nd && d.nd >= d.dp {
-			eprec = d.nd
+		if eprec > digs.nd && digs.nd >= digs.dp {
+			eprec = digs.nd
 		}
 		// %e is used if the exponent from the conversion
 		// is less than -4 or greater than or equal to the precision.
@@ -165,17 +206,17 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
 		if shortest {
 			eprec = 6
 		}
-		exp := d.dp - 1
+		exp := digs.dp - 1
 		if exp < -4 || exp >= eprec {
-			if prec > d.nd {
-				prec = d.nd
+			if prec > digs.nd {
+				prec = digs.nd
 			}
-			return fmtE(dst, neg, d, prec-1, fmt+'e'-'g')
+			return fmtE(dst, neg, digs, prec-1, fmt+'e'-'g')
 		}
-		if prec > d.dp {
-			prec = d.nd
+		if prec > digs.dp {
+			prec = digs.nd
 		}
-		return fmtF(dst, neg, d, max(prec-d.dp, 0))
+		return fmtF(dst, neg, digs, max(prec-digs.dp, 0))
 	}
 
 	// unknown format
@@ -214,7 +255,7 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
 
 	// d = mant << (exp - mantbits)
 	// Next highest floating point number is mant+1 << exp-mantbits.
-	// Our upper bound is halfway inbetween, mant*2+1 << exp-mantbits-1.
+	// Our upper bound is halfway between, mant*2+1 << exp-mantbits-1.
 	upper := new(decimal)
 	upper.Assign(mant*2 + 1)
 	upper.Shift(exp - int(flt.mantbits) - 1)
@@ -224,7 +265,7 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
 	// unless mant-1 drops the significant bit and exp is not the minimum exp,
 	// in which case the next lowest is mant*2-1 << exp-mantbits-1.
 	// Either way, call it mantlo << explo-mantbits.
-	// Our lower bound is halfway inbetween, mantlo*2+1 << explo-mantbits-1.
+	// Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1.
 	var mantlo uint64
 	var explo int
 	if mant > 1<<flt.mantbits || exp == minexp {
@@ -283,8 +324,14 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
 	}
 }
 
+type decimalSlice struct {
+	d      []byte
+	nd, dp int
+	neg    bool
+}
+
 // %e: -d.ddddde±dd
-func fmtE(dst []byte, neg bool, d *decimal, prec int, fmt byte) []byte {
+func fmtE(dst []byte, neg bool, d decimalSlice, prec int, fmt byte) []byte {
 	// sign
 	if neg {
 		dst = append(dst, '-')
@@ -300,12 +347,15 @@ func fmtE(dst []byte, neg bool, d *decimal, prec int, fmt byte) []byte {
 	// .moredigits
 	if prec > 0 {
 		dst = append(dst, '.')
-		for i := 1; i <= prec; i++ {
-			ch = '0'
-			if i < d.nd {
-				ch = d.d[i]
-			}
-			dst = append(dst, ch)
+		i := 1
+		m := d.nd + prec + 1 - max(d.nd, prec+1)
+		for i < m {
+			dst = append(dst, d.d[i])
+			i++
+		}
+		for i <= prec {
+			dst = append(dst, '0')
+			i++
 		}
 	}
 
@@ -335,17 +385,20 @@ func fmtE(dst []byte, neg bool, d *decimal, prec int, fmt byte) []byte {
 	i--
 	buf[i] = byte(exp + '0')
 
-	// leading zeroes
-	if i > len(buf)-2 {
-		i--
-		buf[i] = '0'
+	switch i {
+	case 0:
+		dst = append(dst, buf[0], buf[1], buf[2])
+	case 1:
+		dst = append(dst, buf[1], buf[2])
+	case 2:
+		// leading zeroes
+		dst = append(dst, '0', buf[2])
 	}
-
-	return append(dst, buf[i:]...)
+	return dst
 }
 
 // %f: -ddddddd.ddddd
-func fmtF(dst []byte, neg bool, d *decimal, prec int) []byte {
+func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte {
 	// sign
 	if neg {
 		dst = append(dst, '-')
diff --git a/src/pkg/strconv/ftoa_test.go b/src/pkg/strconv/ftoa_test.go
index 7d8617a..39b8615 100644
--- a/src/pkg/strconv/ftoa_test.go
+++ b/src/pkg/strconv/ftoa_test.go
@@ -163,6 +163,7 @@ func TestFtoaRandom(t *testing.T) {
 	for i := 0; i < N; i++ {
 		bits := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
 		x := math.Float64frombits(bits)
+
 		shortFast := FormatFloat(x, 'g', -1, 64)
 		SetOptimize(false)
 		shortSlow := FormatFloat(x, 'g', -1, 64)
@@ -170,23 +171,15 @@ func TestFtoaRandom(t *testing.T) {
 		if shortSlow != shortFast {
 			t.Errorf("%b printed as %s, want %s", x, shortFast, shortSlow)
 		}
-	}
-}
 
-func TestAppendFloatDoesntAllocate(t *testing.T) {
-	n := numAllocations(func() {
-		var buf [64]byte
-		AppendFloat(buf[:0], 1.23, 'g', 5, 64)
-	})
-	want := 1 // TODO(bradfitz): this might be 0, once escape analysis is better
-	if n != want {
-		t.Errorf("with local buffer, did %d allocations, want %d", n, want)
-	}
-	n = numAllocations(func() {
-		AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64)
-	})
-	if n != 0 {
-		t.Errorf("with reused buffer, did %d allocations, want 0", n)
+		prec := rand.Intn(12) + 5
+		shortFast = FormatFloat(x, 'e', prec, 64)
+		SetOptimize(false)
+		shortSlow = FormatFloat(x, 'e', prec, 64)
+		SetOptimize(true)
+		if shortSlow != shortFast {
+			t.Errorf("%b printed as %s, want %s", x, shortFast, shortSlow)
+		}
 	}
 }
 
@@ -220,37 +213,28 @@ func BenchmarkFormatFloatBig(b *testing.B) {
 	}
 }
 
-func BenchmarkAppendFloatDecimal(b *testing.B) {
-	dst := make([]byte, 0, 30)
+func benchmarkAppendFloat(b *testing.B, f float64, fmt byte, prec, bitSize int) {
+	dst := make([]byte, 30)
 	for i := 0; i < b.N; i++ {
-		AppendFloat(dst, 33909, 'g', -1, 64)
+		AppendFloat(dst[:0], f, fmt, prec, bitSize)
 	}
 }
 
-func BenchmarkAppendFloat(b *testing.B) {
-	dst := make([]byte, 0, 30)
-	for i := 0; i < b.N; i++ {
-		AppendFloat(dst, 339.7784, 'g', -1, 64)
-	}
-}
-
-func BenchmarkAppendFloatExp(b *testing.B) {
-	dst := make([]byte, 0, 30)
-	for i := 0; i < b.N; i++ {
-		AppendFloat(dst, -5.09e75, 'g', -1, 64)
-	}
+func BenchmarkAppendFloatDecimal(b *testing.B) { benchmarkAppendFloat(b, 33909, 'g', -1, 64) }
+func BenchmarkAppendFloat(b *testing.B)        { benchmarkAppendFloat(b, 339.7784, 'g', -1, 64) }
+func BenchmarkAppendFloatExp(b *testing.B)     { benchmarkAppendFloat(b, -5.09e75, 'g', -1, 64) }
+func BenchmarkAppendFloatNegExp(b *testing.B)  { benchmarkAppendFloat(b, -5.11e-95, 'g', -1, 64) }
+func BenchmarkAppendFloatBig(b *testing.B) {
+	benchmarkAppendFloat(b, 123456789123456789123456789, 'g', -1, 64)
 }
 
-func BenchmarkAppendFloatNegExp(b *testing.B) {
-	dst := make([]byte, 0, 30)
-	for i := 0; i < b.N; i++ {
-		AppendFloat(dst, -5.11e-95, 'g', -1, 64)
-	}
-}
+func BenchmarkAppendFloat32Integer(b *testing.B)       { benchmarkAppendFloat(b, 33909, 'g', -1, 32) }
+func BenchmarkAppendFloat32ExactFraction(b *testing.B) { benchmarkAppendFloat(b, 3.375, 'g', -1, 32) }
+func BenchmarkAppendFloat32Point(b *testing.B)         { benchmarkAppendFloat(b, 339.7784, 'g', -1, 32) }
+func BenchmarkAppendFloat32Exp(b *testing.B)           { benchmarkAppendFloat(b, -5.09e25, 'g', -1, 32) }
+func BenchmarkAppendFloat32NegExp(b *testing.B)        { benchmarkAppendFloat(b, -5.11e-25, 'g', -1, 32) }
 
-func BenchmarkAppendFloatBig(b *testing.B) {
-	dst := make([]byte, 0, 30)
-	for i := 0; i < b.N; i++ {
-		AppendFloat(dst, 123456789123456789123456789, 'g', -1, 64)
-	}
-}
+func BenchmarkAppendFloat64Fixed1(b *testing.B) { benchmarkAppendFloat(b, 123456, 'e', 3, 64) }
+func BenchmarkAppendFloat64Fixed2(b *testing.B) { benchmarkAppendFloat(b, 123.456, 'e', 3, 64) }
+func BenchmarkAppendFloat64Fixed3(b *testing.B) { benchmarkAppendFloat(b, 1.23456e+78, 'e', 3, 64) }
+func BenchmarkAppendFloat64Fixed4(b *testing.B) { benchmarkAppendFloat(b, 1.23456e-78, 'e', 3, 64) }
diff --git a/src/pkg/strconv/isprint.go b/src/pkg/strconv/isprint.go
index a03a07b..db5f0fb 100644
--- a/src/pkg/strconv/isprint.go
+++ b/src/pkg/strconv/isprint.go
@@ -3,7 +3,7 @@
 
 package strconv
 
-// (474+134+42)*2 + (180)*4 = 2020 bytes
+// (470+136+60)*2 + (218)*4 = 2204 bytes
 
 var isPrint16 = []uint16{
 	0x0020, 0x007e,
@@ -12,7 +12,7 @@ var isPrint16 = []uint16{
 	0x0384, 0x0527,
 	0x0531, 0x0556,
 	0x0559, 0x058a,
-	0x0591, 0x05c7,
+	0x058f, 0x05c7,
 	0x05d0, 0x05ea,
 	0x05f0, 0x05f4,
 	0x0606, 0x061b,
@@ -23,7 +23,8 @@ var isPrint16 = []uint16{
 	0x0800, 0x082d,
 	0x0830, 0x085b,
 	0x085e, 0x085e,
-	0x0900, 0x098c,
+	0x08a0, 0x08ac,
+	0x08e4, 0x098c,
 	0x098f, 0x0990,
 	0x0993, 0x09b2,
 	0x09b6, 0x09b9,
@@ -99,12 +100,12 @@ var isPrint16 = []uint16{
 	0x0eaa, 0x0ebd,
 	0x0ec0, 0x0ecd,
 	0x0ed0, 0x0ed9,
-	0x0edc, 0x0edd,
+	0x0edc, 0x0edf,
 	0x0f00, 0x0f6c,
 	0x0f71, 0x0fda,
-	0x1000, 0x10c5,
-	0x10d0, 0x10fc,
-	0x1100, 0x124d,
+	0x1000, 0x10c7,
+	0x10cd, 0x10cd,
+	0x10d0, 0x124d,
 	0x1250, 0x125d,
 	0x1260, 0x128d,
 	0x1290, 0x12b5,
@@ -120,8 +121,7 @@ var isPrint16 = []uint16{
 	0x1720, 0x1736,
 	0x1740, 0x1753,
 	0x1760, 0x1773,
-	0x1780, 0x17b3,
-	0x17b6, 0x17dd,
+	0x1780, 0x17dd,
 	0x17e0, 0x17e9,
 	0x17f0, 0x17f9,
 	0x1800, 0x180d,
@@ -145,13 +145,12 @@ var isPrint16 = []uint16{
 	0x1aa0, 0x1aad,
 	0x1b00, 0x1b4b,
 	0x1b50, 0x1b7c,
-	0x1b80, 0x1baa,
-	0x1bae, 0x1bb9,
-	0x1bc0, 0x1bf3,
+	0x1b80, 0x1bf3,
 	0x1bfc, 0x1c37,
 	0x1c3b, 0x1c49,
 	0x1c4d, 0x1c7f,
-	0x1cd0, 0x1cf2,
+	0x1cc0, 0x1cc7,
+	0x1cd0, 0x1cf6,
 	0x1d00, 0x1de6,
 	0x1dfc, 0x1f15,
 	0x1f18, 0x1f1d,
@@ -165,7 +164,7 @@ var isPrint16 = []uint16{
 	0x2030, 0x205e,
 	0x2070, 0x2071,
 	0x2074, 0x209c,
-	0x20a0, 0x20b9,
+	0x20a0, 0x20ba,
 	0x20d0, 0x20f0,
 	0x2100, 0x2189,
 	0x2190, 0x23f3,
@@ -173,12 +172,13 @@ var isPrint16 = []uint16{
 	0x2440, 0x244a,
 	0x2460, 0x2b4c,
 	0x2b50, 0x2b59,
-	0x2c00, 0x2cf1,
-	0x2cf9, 0x2d25,
-	0x2d30, 0x2d65,
+	0x2c00, 0x2cf3,
+	0x2cf9, 0x2d27,
+	0x2d2d, 0x2d2d,
+	0x2d30, 0x2d67,
 	0x2d6f, 0x2d70,
 	0x2d7f, 0x2d96,
-	0x2da0, 0x2e31,
+	0x2da0, 0x2e3b,
 	0x2e80, 0x2ef3,
 	0x2f00, 0x2fd5,
 	0x2ff0, 0x2ffb,
@@ -188,16 +188,15 @@ var isPrint16 = []uint16{
 	0x3131, 0x31ba,
 	0x31c0, 0x31e3,
 	0x31f0, 0x4db5,
-	0x4dc0, 0x9fcb,
+	0x4dc0, 0x9fcc,
 	0xa000, 0xa48c,
 	0xa490, 0xa4c6,
 	0xa4d0, 0xa62b,
-	0xa640, 0xa673,
-	0xa67c, 0xa697,
-	0xa6a0, 0xa6f7,
-	0xa700, 0xa791,
-	0xa7a0, 0xa7a9,
-	0xa7fa, 0xa82b,
+	0xa640, 0xa697,
+	0xa69f, 0xa6f7,
+	0xa700, 0xa793,
+	0xa7a0, 0xa7aa,
+	0xa7f8, 0xa82b,
 	0xa830, 0xa839,
 	0xa840, 0xa877,
 	0xa880, 0xa8c4,
@@ -212,7 +211,7 @@ var isPrint16 = []uint16{
 	0xaa50, 0xaa59,
 	0xaa5c, 0xaa7b,
 	0xaa80, 0xaac2,
-	0xaadb, 0xaadf,
+	0xaadb, 0xaaf6,
 	0xab01, 0xab06,
 	0xab09, 0xab0e,
 	0xab11, 0xab16,
@@ -222,8 +221,7 @@ var isPrint16 = []uint16{
 	0xac00, 0xd7a3,
 	0xd7b0, 0xd7c6,
 	0xd7cb, 0xd7fb,
-	0xf900, 0xfa2d,
-	0xfa30, 0xfa6d,
+	0xf900, 0xfa6d,
 	0xfa70, 0xfad9,
 	0xfb00, 0xfb06,
 	0xfb13, 0xfb17,
@@ -252,8 +250,11 @@ var isNotPrint16 = []uint16{
 	0x03a2,
 	0x0560,
 	0x0588,
+	0x0590,
 	0x06dd,
 	0x083f,
+	0x08a1,
+	0x08ff,
 	0x0978,
 	0x0980,
 	0x0984,
@@ -275,7 +276,6 @@ var isNotPrint16 = []uint16{
 	0x0ab4,
 	0x0ac6,
 	0x0aca,
-	0x0af0,
 	0x0b04,
 	0x0b29,
 	0x0b31,
@@ -327,6 +327,7 @@ var isNotPrint16 = []uint16{
 	0x0f98,
 	0x0fbd,
 	0x0fcd,
+	0x10c6,
 	0x1249,
 	0x1257,
 	0x1259,
@@ -351,10 +352,9 @@ var isNotPrint16 = []uint16{
 	0x1ff5,
 	0x208f,
 	0x2700,
-	0x27cb,
-	0x27cd,
 	0x2c2f,
 	0x2c5f,
+	0x2d26,
 	0x2da7,
 	0x2daf,
 	0x2db7,
@@ -406,6 +406,8 @@ var isPrint32 = []uint32{
 	0x010900, 0x01091b,
 	0x01091f, 0x010939,
 	0x01093f, 0x01093f,
+	0x010980, 0x0109b7,
+	0x0109be, 0x0109bf,
 	0x010a00, 0x010a06,
 	0x010a0c, 0x010a33,
 	0x010a38, 0x010a3a,
@@ -421,11 +423,21 @@ var isPrint32 = []uint32{
 	0x011000, 0x01104d,
 	0x011052, 0x01106f,
 	0x011080, 0x0110c1,
+	0x0110d0, 0x0110e8,
+	0x0110f0, 0x0110f9,
+	0x011100, 0x011143,
+	0x011180, 0x0111c8,
+	0x0111d0, 0x0111d9,
+	0x011680, 0x0116b7,
+	0x0116c0, 0x0116c9,
 	0x012000, 0x01236e,
 	0x012400, 0x012462,
 	0x012470, 0x012473,
 	0x013000, 0x01342e,
 	0x016800, 0x016a38,
+	0x016f00, 0x016f44,
+	0x016f50, 0x016f7e,
+	0x016f8f, 0x016f9f,
 	0x01b000, 0x01b001,
 	0x01d000, 0x01d0f5,
 	0x01d100, 0x01d126,
@@ -442,13 +454,21 @@ var isPrint32 = []uint32{
 	0x01d54a, 0x01d6a5,
 	0x01d6a8, 0x01d7cb,
 	0x01d7ce, 0x01d7ff,
+	0x01ee00, 0x01ee24,
+	0x01ee27, 0x01ee3b,
+	0x01ee42, 0x01ee42,
+	0x01ee47, 0x01ee54,
+	0x01ee57, 0x01ee64,
+	0x01ee67, 0x01ee9b,
+	0x01eea1, 0x01eebb,
+	0x01eef0, 0x01eef1,
 	0x01f000, 0x01f02b,
 	0x01f030, 0x01f093,
 	0x01f0a0, 0x01f0ae,
 	0x01f0b1, 0x01f0be,
 	0x01f0c1, 0x01f0df,
 	0x01f100, 0x01f10a,
-	0x01f110, 0x01f169,
+	0x01f110, 0x01f16b,
 	0x01f170, 0x01f19a,
 	0x01f1e6, 0x01f202,
 	0x01f210, 0x01f23a,
@@ -461,10 +481,9 @@ var isPrint32 = []uint32{
 	0x01f3e0, 0x01f3f0,
 	0x01f400, 0x01f4fc,
 	0x01f500, 0x01f53d,
+	0x01f540, 0x01f543,
 	0x01f550, 0x01f567,
-	0x01f5fb, 0x01f625,
-	0x01f628, 0x01f62d,
-	0x01f630, 0x01f640,
+	0x01f5fb, 0x01f640,
 	0x01f645, 0x01f64f,
 	0x01f680, 0x01f6c5,
 	0x01f700, 0x01f773,
@@ -489,6 +508,7 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry
 	0x0a14,
 	0x0a18,
 	0x10bd,
+	0x1135,
 	0xd455,
 	0xd49d,
 	0xd4ad,
@@ -502,6 +522,32 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry
 	0xd53f,
 	0xd545,
 	0xd551,
+	0xee04,
+	0xee20,
+	0xee23,
+	0xee28,
+	0xee33,
+	0xee38,
+	0xee3a,
+	0xee48,
+	0xee4a,
+	0xee4c,
+	0xee50,
+	0xee53,
+	0xee58,
+	0xee5a,
+	0xee5c,
+	0xee5e,
+	0xee60,
+	0xee63,
+	0xee6b,
+	0xee73,
+	0xee78,
+	0xee7d,
+	0xee7f,
+	0xee8a,
+	0xeea4,
+	0xeeaa,
 	0xf0d0,
 	0xf12f,
 	0xf336,
@@ -509,13 +555,4 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry
 	0xf43f,
 	0xf441,
 	0xf4f8,
-	0xf600,
-	0xf611,
-	0xf615,
-	0xf617,
-	0xf619,
-	0xf61b,
-	0xf61f,
-	0xf62c,
-	0xf634,
 }
diff --git a/src/pkg/strconv/itoa_test.go b/src/pkg/strconv/itoa_test.go
index 1486ee2..e0213ae 100644
--- a/src/pkg/strconv/itoa_test.go
+++ b/src/pkg/strconv/itoa_test.go
@@ -5,7 +5,6 @@
 package strconv_test
 
 import (
-	"runtime"
 	. "strconv"
 	"testing"
 )
@@ -126,35 +125,6 @@ func TestUitoa(t *testing.T) {
 	}
 }
 
-func numAllocations(f func()) int {
-	runtime.GC()
-	memstats := new(runtime.MemStats)
-	runtime.ReadMemStats(memstats)
-	n0 := memstats.Mallocs
-	f()
-	runtime.ReadMemStats(memstats)
-	return int(memstats.Mallocs - n0)
-}
-
-var globalBuf [64]byte
-
-func TestAppendUintDoesntAllocate(t *testing.T) {
-	n := numAllocations(func() {
-		var buf [64]byte
-		AppendInt(buf[:0], 123, 10)
-	})
-	want := 1 // TODO(bradfitz): this might be 0, once escape analysis is better
-	if n != want {
-		t.Errorf("with local buffer, did %d allocations, want %d", n, want)
-	}
-	n = numAllocations(func() {
-		AppendInt(globalBuf[:0], 123, 10)
-	})
-	if n != 0 {
-		t.Errorf("with reused buffer, did %d allocations, want 0", n)
-	}
-}
-
 func BenchmarkFormatInt(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		for _, test := range itob64tests {
diff --git a/src/pkg/strconv/quote.go b/src/pkg/strconv/quote.go
index 8a73f9d..8cbef88 100644
--- a/src/pkg/strconv/quote.go
+++ b/src/pkg/strconv/quote.go
@@ -139,8 +139,9 @@ func AppendQuoteRuneToASCII(dst []byte, r rune) []byte {
 	return append(dst, QuoteRuneToASCII(r)...)
 }
 
-// CanBackquote returns whether the string s would be
-// a valid Go string literal if enclosed in backquotes.
+// CanBackquote reports whether the string s can be represented
+// unchanged as a single-line backquoted string without control
+// characters other than space and tab.
 func CanBackquote(s string) bool {
 	for i := 0; i < len(s); i++ {
 		if (s[i] < ' ' && s[i] != '\t') || s[i] == '`' {
diff --git a/src/pkg/strconv/strconv_test.go b/src/pkg/strconv/strconv_test.go
new file mode 100644
index 0000000..c3c5389
--- /dev/null
+++ b/src/pkg/strconv/strconv_test.go
@@ -0,0 +1,52 @@
+// 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 strconv_test
+
+import (
+	. "strconv"
+	"strings"
+	"testing"
+)
+
+var (
+	globalBuf [64]byte
+	nextToOne = "1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1"
+
+	mallocTest = []struct {
+		count int
+		desc  string
+		fn    func()
+	}{
+		// TODO(bradfitz): this might be 0, once escape analysis is better
+		{1, `AppendInt(localBuf[:0], 123, 10)`, func() {
+			var localBuf [64]byte
+			AppendInt(localBuf[:0], 123, 10)
+		}},
+		{0, `AppendInt(globalBuf[:0], 123, 10)`, func() { AppendInt(globalBuf[:0], 123, 10) }},
+		// TODO(bradfitz): this might be 0, once escape analysis is better
+		{1, `AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)`, func() {
+			var localBuf [64]byte
+			AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)
+		}},
+		{0, `AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64)`, func() { AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64) }},
+		{0, `ParseFloat("123.45", 64)`, func() { ParseFloat("123.45", 64) }},
+		{0, `ParseFloat("123.456789123456789", 64)`, func() { ParseFloat("123.456789123456789", 64) }},
+		{0, `ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64)`, func() {
+			ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64)
+		}},
+		{0, `ParseFloat("1.0000000000000001110223024625156540423631668090820312500...001", 64)`, func() {
+			ParseFloat(nextToOne, 64)
+		}},
+	}
+)
+
+func TestCountMallocs(t *testing.T) {
+	for _, mt := range mallocTest {
+		allocs := testing.AllocsPerRun(100, mt.fn)
+		if max := float64(mt.count); allocs > max {
+			t.Errorf("%s: %v allocs, want <=%v", mt.desc, allocs, max)
+		}
+	}
+}
diff --git a/src/pkg/strconv/testfp.txt b/src/pkg/strconv/testdata/testfp.txt
similarity index 100%
rename from src/pkg/strconv/testfp.txt
rename to src/pkg/strconv/testdata/testfp.txt
diff --git a/src/pkg/strings/example_test.go b/src/pkg/strings/example_test.go
index 733caf5..36e0a42 100644
--- a/src/pkg/strings/example_test.go
+++ b/src/pkg/strings/example_test.go
@@ -179,3 +179,19 @@ func ExampleToLower() {
 	fmt.Println(strings.ToLower("Gopher"))
 	// Output: gopher
 }
+
+func ExampleTrimSuffix() {
+	var s = "Hello, goodbye, etc!"
+	s = strings.TrimSuffix(s, "goodbye, etc!")
+	s = strings.TrimSuffix(s, "planet")
+	fmt.Print(s, "world!")
+	// Output: Hello, world!
+}
+
+func ExampleTrimPrefix() {
+	var s = "Goodbye,, world!"
+	s = strings.TrimPrefix(s, "Goodbye,")
+	s = strings.TrimPrefix(s, "Howdy,")
+	fmt.Print("Hello" + s)
+	// Output: Hello, world!
+}
diff --git a/src/pkg/strings/export_test.go b/src/pkg/strings/export_test.go
index dcfec51..17c806a 100644
--- a/src/pkg/strings/export_test.go
+++ b/src/pkg/strings/export_test.go
@@ -7,3 +7,39 @@ package strings
 func (r *Replacer) Replacer() interface{} {
 	return r.r
 }
+
+func (r *Replacer) PrintTrie() string {
+	gen := r.r.(*genericReplacer)
+	return gen.printNode(&gen.root, 0)
+}
+
+func (r *genericReplacer) printNode(t *trieNode, depth int) (s string) {
+	if t.priority > 0 {
+		s += "+"
+	} else {
+		s += "-"
+	}
+	s += "\n"
+
+	if t.prefix != "" {
+		s += Repeat(".", depth) + t.prefix
+		s += r.printNode(t.next, depth+len(t.prefix))
+	} else if t.table != nil {
+		for b, m := range r.mapping {
+			if int(m) != r.tableSize && t.table[m] != nil {
+				s += Repeat(".", depth) + string([]byte{byte(b)})
+				s += r.printNode(t.table[m], depth+1)
+			}
+		}
+	}
+	return
+}
+
+func StringFind(pattern, text string) int {
+	return makeStringFinder(pattern).next(text)
+}
+
+func DumpTables(pattern string) ([]int, []int) {
+	finder := makeStringFinder(pattern)
+	return finder.badCharSkip[:], finder.goodSuffixSkip
+}
diff --git a/src/pkg/strings/reader.go b/src/pkg/strings/reader.go
index 8569805..11240ef 100644
--- a/src/pkg/strings/reader.go
+++ b/src/pkg/strings/reader.go
@@ -10,7 +10,7 @@ import (
 	"unicode/utf8"
 )
 
-// A Reader implements the io.Reader, io.ReaderAt, io.Seeker,
+// A Reader implements the io.Reader, io.ReaderAt, io.Seeker, io.WriterTo,
 // io.ByteScanner, and io.RuneScanner interfaces by reading
 // from a string.
 type Reader struct {
@@ -120,6 +120,25 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) {
 	return abs, nil
 }
 
+// WriteTo implements the io.WriterTo interface.
+func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
+	r.prevRune = -1
+	if r.i >= len(r.s) {
+		return 0, nil
+	}
+	s := r.s[r.i:]
+	m, err := io.WriteString(w, s)
+	if m > len(s) {
+		panic("strings.Reader.WriteTo: invalid WriteString count")
+	}
+	r.i += m
+	n = int64(m)
+	if m != len(s) && err == nil {
+		err = io.ErrShortWrite
+	}
+	return
+}
+
 // NewReader returns a new Reader reading from s.
 // It is similar to bytes.NewBufferString but more efficient and read-only.
 func NewReader(s string) *Reader { return &Reader{s, 0, -1} }
diff --git a/src/pkg/strings/reader_test.go b/src/pkg/strings/reader_test.go
index a99ae2a..4fdddcd 100644
--- a/src/pkg/strings/reader_test.go
+++ b/src/pkg/strings/reader_test.go
@@ -5,6 +5,7 @@
 package strings_test
 
 import (
+	"bytes"
 	"fmt"
 	"io"
 	"os"
@@ -86,3 +87,25 @@ func TestReaderAt(t *testing.T) {
 		}
 	}
 }
+
+func TestWriteTo(t *testing.T) {
+	const str = "0123456789"
+	for i := 0; i <= len(str); i++ {
+		s := str[i:]
+		r := strings.NewReader(s)
+		var b bytes.Buffer
+		n, err := r.WriteTo(&b)
+		if expect := int64(len(s)); n != expect {
+			t.Errorf("got %v; want %v", n, expect)
+		}
+		if err != nil {
+			t.Errorf("for length %d: got error = %v; want nil", len(s), err)
+		}
+		if b.String() != s {
+			t.Errorf("got string %q; want %q", b.String(), s)
+		}
+		if r.Len() != 0 {
+			t.Errorf("reader contains %v bytes; want 0", r.Len())
+		}
+	}
+}
diff --git a/src/pkg/strings/replace.go b/src/pkg/strings/replace.go
index f53a96e..f63b179 100644
--- a/src/pkg/strings/replace.go
+++ b/src/pkg/strings/replace.go
@@ -33,47 +33,45 @@ func NewReplacer(oldnew ...string) *Replacer {
 		panic("strings.NewReplacer: odd argument count")
 	}
 
-	// Possible implementations.
-	var (
-		bb  byteReplacer
-		bs  byteStringReplacer
-		gen genericReplacer
-	)
-
-	allOldBytes, allNewBytes := true, true
-	for len(oldnew) > 0 {
-		old, new := oldnew[0], oldnew[1]
-		oldnew = oldnew[2:]
-		if len(old) != 1 {
-			allOldBytes = false
+	if len(oldnew) == 2 && len(oldnew[0]) > 1 {
+		return &Replacer{r: makeSingleStringReplacer(oldnew[0], oldnew[1])}
+	}
+
+	allNewBytes := true
+	for i := 0; i < len(oldnew); i += 2 {
+		if len(oldnew[i]) != 1 {
+			return &Replacer{r: makeGenericReplacer(oldnew)}
 		}
-		if len(new) != 1 {
+		if len(oldnew[i+1]) != 1 {
 			allNewBytes = false
 		}
+	}
 
-		// generic
-		gen.p = append(gen.p, pair{old, new})
-
-		// byte -> string
-		if allOldBytes {
-			bs.old.set(old[0])
-			bs.new[old[0]] = []byte(new)
-		}
-
-		// byte -> byte
-		if allOldBytes && allNewBytes {
-			bb.old.set(old[0])
-			bb.new[old[0]] = new[0]
+	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
 		}
+		return &Replacer{r: bb}
 	}
 
-	if allOldBytes && allNewBytes {
-		return &Replacer{r: &bb}
-	}
-	if allOldBytes {
-		return &Replacer{r: &bs}
+	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)
 	}
-	return &Replacer{r: &gen}
+	return &Replacer{r: bs}
 }
 
 // Replace returns a copy of s with all replacements performed.
@@ -86,79 +84,326 @@ func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error) {
 	return r.r.WriteString(w, s)
 }
 
-// genericReplacer is the fully generic (and least optimized) algorithm.
+// trieNode is a node in a lookup trie for prioritized key/value pairs. Keys
+// and values may be empty. For example, the trie containing keys "ax", "ay",
+// "bcbc", "x" and "xy" could have eight nodes:
+//
+//  n0  -
+//  n1  a-
+//  n2  .x+
+//  n3  .y+
+//  n4  b-
+//  n5  .cbc+
+//  n6  x+
+//  n7  .y+
+//
+// n0 is the root node, and its children are n1, n4 and n6; n1's children are
+// n2 and n3; n4's child is n5; n6's child is n7. Nodes n0, n1 and n4 (marked
+// with a trailing "-") are partial keys, and nodes n2, n3, n5, n6 and n7
+// (marked with a trailing "+") are complete keys.
+type trieNode struct {
+	// value is the value of the trie node's key/value pair. It is empty if
+	// this node is not a complete key.
+	value string
+	// priority is the priority (higher is more important) of the trie node's
+	// key/value pair; keys are not necessarily matched shortest- or longest-
+	// first. Priority is positive if this node is a complete key, and zero
+	// otherwise. In the example above, positive/zero priorities are marked
+	// with a trailing "+" or "-".
+	priority int
+
+	// A trie node may have zero, one or more child nodes:
+	//  * if the remaining fields are zero, there are no children.
+	//  * if prefix and next are non-zero, there is one child in next.
+	//  * if table is non-zero, it defines all the children.
+	//
+	// Prefixes are preferred over tables when there is one child, but the
+	// root node always uses a table for lookup efficiency.
+
+	// prefix is the difference in keys between this trie node and the next.
+	// In the example above, node n4 has prefix "cbc" and n4's next node is n5.
+	// Node n5 has no children and so has zero prefix, next and table fields.
+	prefix string
+	next   *trieNode
+
+	// table is a lookup table indexed by the next byte in the key, after
+	// remapping that byte through genericReplacer.mapping to create a dense
+	// index. In the example above, the keys only use 'a', 'b', 'c', 'x' and
+	// 'y', which remap to 0, 1, 2, 3 and 4. All other bytes remap to 5, and
+	// genericReplacer.tableSize will be 5. Node n0's table will be
+	// []*trieNode{ 0:n1, 1:n4, 3:n6 }, where the 0, 1 and 3 are the remapped
+	// 'a', 'b' and 'x'.
+	table []*trieNode
+}
+
+func (t *trieNode) add(key, val string, priority int, r *genericReplacer) {
+	if key == "" {
+		if t.priority == 0 {
+			t.value = val
+			t.priority = priority
+		}
+		return
+	}
+
+	if t.prefix != "" {
+		// Need to split the prefix among multiple nodes.
+		var n int // length of the longest common prefix
+		for ; n < len(t.prefix) && n < len(key); n++ {
+			if t.prefix[n] != key[n] {
+				break
+			}
+		}
+		if n == len(t.prefix) {
+			t.next.add(key[n:], val, priority, r)
+		} else if n == 0 {
+			// First byte differs, start a new lookup table here. Looking up
+			// what is currently t.prefix[0] will lead to prefixNode, and
+			// looking up key[0] will lead to keyNode.
+			var prefixNode *trieNode
+			if len(t.prefix) == 1 {
+				prefixNode = t.next
+			} else {
+				prefixNode = &trieNode{
+					prefix: t.prefix[1:],
+					next:   t.next,
+				}
+			}
+			keyNode := new(trieNode)
+			t.table = make([]*trieNode, r.tableSize)
+			t.table[r.mapping[t.prefix[0]]] = prefixNode
+			t.table[r.mapping[key[0]]] = keyNode
+			t.prefix = ""
+			t.next = nil
+			keyNode.add(key[1:], val, priority, r)
+		} else {
+			// Insert new node after the common section of the prefix.
+			next := &trieNode{
+				prefix: t.prefix[n:],
+				next:   t.next,
+			}
+			t.prefix = t.prefix[:n]
+			t.next = next
+			next.add(key[n:], val, priority, r)
+		}
+	} else if t.table != nil {
+		// Insert into existing table.
+		m := r.mapping[key[0]]
+		if t.table[m] == nil {
+			t.table[m] = new(trieNode)
+		}
+		t.table[m].add(key[1:], val, priority, r)
+	} else {
+		t.prefix = key
+		t.next = new(trieNode)
+		t.next.add("", val, priority, r)
+	}
+}
+
+func (r *genericReplacer) lookup(s string, ignoreRoot bool) (val string, keylen int, found bool) {
+	// Iterate down the trie to the end, and grab the value and keylen with
+	// the highest priority.
+	bestPriority := 0
+	node := &r.root
+	n := 0
+	for node != nil {
+		if node.priority > bestPriority && !(ignoreRoot && node == &r.root) {
+			bestPriority = node.priority
+			val = node.value
+			keylen = n
+			found = true
+		}
+
+		if s == "" {
+			break
+		}
+		if node.table != nil {
+			index := r.mapping[s[0]]
+			if int(index) == r.tableSize {
+				break
+			}
+			node = node.table[index]
+			s = s[1:]
+			n++
+		} else if node.prefix != "" && HasPrefix(s, node.prefix) {
+			n += len(node.prefix)
+			s = s[len(node.prefix):]
+			node = node.next
+		} else {
+			break
+		}
+	}
+	return
+}
+
+// genericReplacer is the fully generic algorithm.
 // It's used as a fallback when nothing faster can be used.
 type genericReplacer struct {
-	p []pair
+	root trieNode
+	// tableSize is the size of a trie node's lookup table. It is the number
+	// of unique key bytes.
+	tableSize int
+	// mapping maps from key bytes to a dense index for trieNode.table.
+	mapping [256]byte
 }
 
-type pair struct{ old, new string }
+func makeGenericReplacer(oldnew []string) *genericReplacer {
+	r := new(genericReplacer)
+	// Find each byte used, then assign them each an index.
+	for i := 0; i < len(oldnew); i += 2 {
+		key := oldnew[i]
+		for j := 0; j < len(key); j++ {
+			r.mapping[key[j]] = 1
+		}
+	}
+
+	for _, b := range r.mapping {
+		r.tableSize += int(b)
+	}
+
+	var index byte
+	for i, b := range r.mapping {
+		if b == 0 {
+			r.mapping[i] = byte(r.tableSize)
+		} else {
+			r.mapping[i] = index
+			index++
+		}
+	}
+	// Ensure root node uses a lookup table (for performance).
+	r.root.table = make([]*trieNode, r.tableSize)
 
-type appendSliceWriter struct {
-	b []byte
+	for i := 0; i < len(oldnew); i += 2 {
+		r.root.add(oldnew[i], oldnew[i+1], len(oldnew)-i, r)
+	}
+	return r
 }
 
+type appendSliceWriter []byte
+
+// Write writes to the buffer to satisfy io.Writer.
 func (w *appendSliceWriter) Write(p []byte) (int, error) {
-	w.b = append(w.b, p...)
+	*w = append(*w, p...)
 	return len(p), nil
 }
 
+// WriteString writes to the buffer without string->[]byte->string allocations.
+func (w *appendSliceWriter) WriteString(s string) (int, error) {
+	*w = append(*w, s...)
+	return len(s), nil
+}
+
+type stringWriterIface interface {
+	WriteString(string) (int, error)
+}
+
+type stringWriter struct {
+	w io.Writer
+}
+
+func (w stringWriter) WriteString(s string) (int, error) {
+	return w.w.Write([]byte(s))
+}
+
+func getStringWriter(w io.Writer) stringWriterIface {
+	sw, ok := w.(stringWriterIface)
+	if !ok {
+		sw = stringWriter{w}
+	}
+	return sw
+}
+
 func (r *genericReplacer) Replace(s string) string {
-	// TODO(bradfitz): optimized version
-	n, _ := r.WriteString(discard, s)
-	w := appendSliceWriter{make([]byte, 0, n)}
-	r.WriteString(&w, s)
-	return string(w.b)
+	buf := make(appendSliceWriter, 0, len(s))
+	r.WriteString(&buf, s)
+	return string(buf)
 }
 
 func (r *genericReplacer) WriteString(w io.Writer, s string) (n int, err error) {
-	lastEmpty := false // the last replacement was of the empty string
-Input:
-	// TODO(bradfitz): optimized version
-	for i := 0; i < len(s); {
-		for _, p := range r.p {
-			if p.old == "" && lastEmpty {
-				// Don't let old match twice in a row.
-				// (it doesn't advance the input and
-				// would otherwise loop forever)
-				continue
+	sw := getStringWriter(w)
+	var last, wn int
+	var prevMatchEmpty bool
+	for i := 0; i <= len(s); {
+		// Ignore the empty match iff the previous loop found the empty match.
+		val, keylen, match := r.lookup(s[i:], prevMatchEmpty)
+		prevMatchEmpty = match && keylen == 0
+		if match {
+			wn, err = sw.WriteString(s[last:i])
+			n += wn
+			if err != nil {
+				return
 			}
-			if HasPrefix(s[i:], p.old) {
-				if p.new != "" {
-					wn, err := w.Write([]byte(p.new))
-					n += wn
-					if err != nil {
-						return n, err
-					}
-				}
-				i += len(p.old)
-				lastEmpty = p.old == ""
-				continue Input
+			wn, err = sw.WriteString(val)
+			n += wn
+			if err != nil {
+				return
 			}
-		}
-		wn, err := w.Write([]byte{s[i]})
-		n += wn
-		if err != nil {
-			return n, err
+			i += keylen
+			last = i
+			continue
 		}
 		i++
 	}
+	if last != len(s) {
+		wn, err = sw.WriteString(s[last:])
+		n += wn
+	}
+	return
+}
 
-	// Final empty match at end.
-	for _, p := range r.p {
-		if p.old == "" {
-			if p.new != "" {
-				wn, err := w.Write([]byte(p.new))
-				n += wn
-				if err != nil {
-					return n, err
-				}
-			}
+// singleStringReplacer is the implementation that's used when there is only
+// one string to replace (and that string has more than one byte).
+type singleStringReplacer struct {
+	finder *stringFinder
+	// value is the new string that replaces that pattern when it's found.
+	value string
+}
+
+func makeSingleStringReplacer(pattern string, value string) *singleStringReplacer {
+	return &singleStringReplacer{finder: makeStringFinder(pattern), value: value}
+}
+
+func (r *singleStringReplacer) Replace(s string) string {
+	var buf []byte
+	i := 0
+	for {
+		match := r.finder.next(s[i:])
+		if match == -1 {
 			break
 		}
+		buf = append(buf, s[i:i+match]...)
+		buf = append(buf, r.value...)
+		i += match + len(r.finder.pattern)
+	}
+	if buf == nil {
+		return s
 	}
+	buf = append(buf, s[i:]...)
+	return string(buf)
+}
 
-	return n, nil
+func (r *singleStringReplacer) WriteString(w io.Writer, s string) (n int, err error) {
+	sw := getStringWriter(w)
+	var i, wn int
+	for {
+		match := r.finder.next(s[i:])
+		if match == -1 {
+			break
+		}
+		wn, err = sw.WriteString(s[i : i+match])
+		n += wn
+		if err != nil {
+			return
+		}
+		wn, err = sw.WriteString(r.value)
+		n += wn
+		if err != nil {
+			return
+		}
+		i += match + len(r.finder.pattern)
+	}
+	wn, err = sw.WriteString(s[i:])
+	n += wn
+	return
 }
 
 // byteReplacer is the implementation that's used when all the "old"
@@ -301,12 +546,3 @@ func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err erro
 	}
 	return n, nil
 }
-
-// strings is too low-level to import io/ioutil
-var discard io.Writer = devNull(0)
-
-type devNull int
-
-func (devNull) Write(p []byte) (int, error) {
-	return len(p), nil
-}
diff --git a/src/pkg/strings/replace_test.go b/src/pkg/strings/replace_test.go
index 23c7e2e..d33dea9 100644
--- a/src/pkg/strings/replace_test.go
+++ b/src/pkg/strings/replace_test.go
@@ -7,105 +7,390 @@ package strings_test
 import (
 	"bytes"
 	"fmt"
-	"log"
 	. "strings"
 	"testing"
 )
 
-var _ = log.Printf
-
-type ReplacerTest struct {
-	r   *Replacer
-	in  string
-	out string
-}
+var htmlEscaper = NewReplacer(
+	"&", "&",
+	"<", "<",
+	">", ">",
+	`"`, """,
+	"'", "'",
+)
 
-var htmlEscaper = NewReplacer("&", "&", "<", "<", ">", ">", "\"", """)
+var htmlUnescaper = NewReplacer(
+	"&", "&",
+	"<", "<",
+	">", ">",
+	""", `"`,
+	"'", "'",
+)
 
 // The http package's old HTML escaping function.
-func oldhtmlEscape(s string) string {
+func oldHTMLEscape(s string) string {
 	s = Replace(s, "&", "&", -1)
 	s = Replace(s, "<", "<", -1)
 	s = Replace(s, ">", ">", -1)
-	s = Replace(s, "\"", """, -1)
+	s = Replace(s, `"`, """, -1)
 	s = Replace(s, "'", "'", -1)
 	return s
 }
 
-var replacer = NewReplacer("aaa", "3[aaa]", "aa", "2[aa]", "a", "1[a]", "i", "i",
-	"longerst", "most long", "longer", "medium", "long", "short",
-	"X", "Y", "Y", "Z")
-
 var capitalLetters = NewReplacer("a", "A", "b", "B")
 
-var blankToXReplacer = NewReplacer("", "X", "o", "O")
+// TestReplacer tests the replacer implementations.
+func TestReplacer(t *testing.T) {
+	type testCase struct {
+		r       *Replacer
+		in, out string
+	}
+	var testCases []testCase
 
-var ReplacerTests = []ReplacerTest{
-	// byte->string
-	{htmlEscaper, "No changes", "No changes"},
-	{htmlEscaper, "I <3 escaping & stuff", "I <3 escaping & stuff"},
-	{htmlEscaper, "&&&", "&&&"},
+	// str converts 0xff to "\xff". This isn't just string(b) since that converts to UTF-8.
+	str := func(b byte) string {
+		return string([]byte{b})
+	}
+	var s []string
 
-	// generic
-	{replacer, "fooaaabar", "foo3[aaa]b1[a]r"},
-	{replacer, "long, longerst, longer", "short, most long, medium"},
-	{replacer, "XiX", "YiY"},
+	// inc maps "\x00"->"\x01", ..., "a"->"b", "b"->"c", ..., "\xff"->"\x00".
+	s = nil
+	for i := 0; i < 256; i++ {
+		s = append(s, str(byte(i)), str(byte(i+1)))
+	}
+	inc := NewReplacer(s...)
 
-	// byte->byte
-	{capitalLetters, "brad", "BrAd"},
-	{capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)},
+	// Test cases with 1-byte old strings, 1-byte new strings.
+	testCases = append(testCases,
+		testCase{capitalLetters, "brad", "BrAd"},
+		testCase{capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)},
+		testCase{capitalLetters, "", ""},
 
-	// hitting "" special case
-	{blankToXReplacer, "oo", "XOXOX"},
-}
+		testCase{inc, "brad", "csbe"},
+		testCase{inc, "\x00\xff", "\x01\x00"},
+		testCase{inc, "", ""},
 
-func TestReplacer(t *testing.T) {
-	for i, tt := range ReplacerTests {
-		if s := tt.r.Replace(tt.in); s != tt.out {
-			t.Errorf("%d. Replace(%q) = %q, want %q", i, tt.in, s, tt.out)
+		testCase{NewReplacer("a", "1", "a", "2"), "brad", "br1d"},
+	)
+
+	// repeat maps "a"->"a", "b"->"bb", "c"->"ccc", ...
+	s = nil
+	for i := 0; i < 256; i++ {
+		n := i + 1 - 'a'
+		if n < 1 {
+			n = 1
+		}
+		s = append(s, str(byte(i)), Repeat(str(byte(i)), n))
+	}
+	repeat := NewReplacer(s...)
+
+	// Test cases with 1-byte old strings, variable length new strings.
+	testCases = append(testCases,
+		testCase{htmlEscaper, "No changes", "No changes"},
+		testCase{htmlEscaper, "I <3 escaping & stuff", "I <3 escaping & stuff"},
+		testCase{htmlEscaper, "&&&", "&&&"},
+		testCase{htmlEscaper, "", ""},
+
+		testCase{repeat, "brad", "bbrrrrrrrrrrrrrrrrrradddd"},
+		testCase{repeat, "abba", "abbbba"},
+		testCase{repeat, "", ""},
+
+		testCase{NewReplacer("a", "11", "a", "22"), "brad", "br11d"},
+	)
+
+	// The remaining test cases have variable length old strings.
+
+	testCases = append(testCases,
+		testCase{htmlUnescaper, "&amp;", "&"},
+		testCase{htmlUnescaper, "<b>HTML's neat</b>", "<b>HTML's neat</b>"},
+		testCase{htmlUnescaper, "", ""},
+
+		testCase{NewReplacer("a", "1", "a", "2", "xxx", "xxx"), "brad", "br1d"},
+
+		testCase{NewReplacer("a", "1", "aa", "2", "aaa", "3"), "aaaa", "1111"},
+
+		testCase{NewReplacer("aaa", "3", "aa", "2", "a", "1"), "aaaa", "31"},
+	)
+
+	// gen1 has multiple old strings of variable length. There is no
+	// overall non-empty common prefix, but some pairwise common prefixes.
+	gen1 := NewReplacer(
+		"aaa", "3[aaa]",
+		"aa", "2[aa]",
+		"a", "1[a]",
+		"i", "i",
+		"longerst", "most long",
+		"longer", "medium",
+		"long", "short",
+		"xx", "xx",
+		"x", "X",
+		"X", "Y",
+		"Y", "Z",
+	)
+	testCases = append(testCases,
+		testCase{gen1, "fooaaabar", "foo3[aaa]b1[a]r"},
+		testCase{gen1, "long, longerst, longer", "short, most long, medium"},
+		testCase{gen1, "xxxxx", "xxxxX"},
+		testCase{gen1, "XiX", "YiY"},
+		testCase{gen1, "", ""},
+	)
+
+	// gen2 has multiple old strings with no pairwise common prefix.
+	gen2 := NewReplacer(
+		"roses", "red",
+		"violets", "blue",
+		"sugar", "sweet",
+	)
+	testCases = append(testCases,
+		testCase{gen2, "roses are red, violets are blue...", "red are red, blue are blue..."},
+		testCase{gen2, "", ""},
+	)
+
+	// gen3 has multiple old strings with an overall common prefix.
+	gen3 := NewReplacer(
+		"abracadabra", "poof",
+		"abracadabrakazam", "splat",
+		"abraham", "lincoln",
+		"abrasion", "scrape",
+		"abraham", "isaac",
+	)
+	testCases = append(testCases,
+		testCase{gen3, "abracadabrakazam abraham", "poofkazam lincoln"},
+		testCase{gen3, "abrasion abracad", "scrape abracad"},
+		testCase{gen3, "abba abram abrasive", "abba abram abrasive"},
+		testCase{gen3, "", ""},
+	)
+
+	// foo{1,2,3,4} have multiple old strings with an overall common prefix
+	// and 1- or 2- byte extensions from the common prefix.
+	foo1 := NewReplacer(
+		"foo1", "A",
+		"foo2", "B",
+		"foo3", "C",
+	)
+	foo2 := NewReplacer(
+		"foo1", "A",
+		"foo2", "B",
+		"foo31", "C",
+		"foo32", "D",
+	)
+	foo3 := NewReplacer(
+		"foo11", "A",
+		"foo12", "B",
+		"foo31", "C",
+		"foo32", "D",
+	)
+	foo4 := NewReplacer(
+		"foo12", "B",
+		"foo32", "D",
+	)
+	testCases = append(testCases,
+		testCase{foo1, "fofoofoo12foo32oo", "fofooA2C2oo"},
+		testCase{foo1, "", ""},
+
+		testCase{foo2, "fofoofoo12foo32oo", "fofooA2Doo"},
+		testCase{foo2, "", ""},
+
+		testCase{foo3, "fofoofoo12foo32oo", "fofooBDoo"},
+		testCase{foo3, "", ""},
+
+		testCase{foo4, "fofoofoo12foo32oo", "fofooBDoo"},
+		testCase{foo4, "", ""},
+	)
+
+	// genAll maps "\x00\x01\x02...\xfe\xff" to "[all]", amongst other things.
+	allBytes := make([]byte, 256)
+	for i := range allBytes {
+		allBytes[i] = byte(i)
+	}
+	allString := string(allBytes)
+	genAll := NewReplacer(
+		allString, "[all]",
+		"\xff", "[ff]",
+		"\x00", "[00]",
+	)
+	testCases = append(testCases,
+		testCase{genAll, allString, "[all]"},
+		testCase{genAll, "a\xff" + allString + "\x00", "a[ff][all][00]"},
+		testCase{genAll, "", ""},
+	)
+
+	// Test cases with empty old strings.
+
+	blankToX1 := NewReplacer("", "X")
+	blankToX2 := NewReplacer("", "X", "", "")
+	blankHighPriority := NewReplacer("", "X", "o", "O")
+	blankLowPriority := NewReplacer("o", "O", "", "X")
+	blankNoOp1 := NewReplacer("", "")
+	blankNoOp2 := NewReplacer("", "", "", "A")
+	blankFoo := NewReplacer("", "X", "foobar", "R", "foobaz", "Z")
+	testCases = append(testCases,
+		testCase{blankToX1, "foo", "XfXoXoX"},
+		testCase{blankToX1, "", "X"},
+
+		testCase{blankToX2, "foo", "XfXoXoX"},
+		testCase{blankToX2, "", "X"},
+
+		testCase{blankHighPriority, "oo", "XOXOX"},
+		testCase{blankHighPriority, "ii", "XiXiX"},
+		testCase{blankHighPriority, "oiio", "XOXiXiXOX"},
+		testCase{blankHighPriority, "iooi", "XiXOXOXiX"},
+		testCase{blankHighPriority, "", "X"},
+
+		testCase{blankLowPriority, "oo", "OOX"},
+		testCase{blankLowPriority, "ii", "XiXiX"},
+		testCase{blankLowPriority, "oiio", "OXiXiOX"},
+		testCase{blankLowPriority, "iooi", "XiOOXiX"},
+		testCase{blankLowPriority, "", "X"},
+
+		testCase{blankNoOp1, "foo", "foo"},
+		testCase{blankNoOp1, "", ""},
+
+		testCase{blankNoOp2, "foo", "foo"},
+		testCase{blankNoOp2, "", ""},
+
+		testCase{blankFoo, "foobarfoobaz", "XRXZX"},
+		testCase{blankFoo, "foobar-foobaz", "XRX-XZX"},
+		testCase{blankFoo, "", "X"},
+	)
+
+	// single string replacer
+
+	abcMatcher := NewReplacer("abc", "[match]")
+
+	testCases = append(testCases,
+		testCase{abcMatcher, "", ""},
+		testCase{abcMatcher, "ab", "ab"},
+		testCase{abcMatcher, "abcd", "[match]d"},
+		testCase{abcMatcher, "cabcabcdabca", "c[match][match]d[match]a"},
+	)
+
+	// No-arg test cases.
+
+	nop := NewReplacer()
+	testCases = append(testCases,
+		testCase{nop, "abc", "abc"},
+		testCase{nop, "", ""},
+	)
+
+	// Run the test cases.
+
+	for i, tc := range testCases {
+		if s := tc.r.Replace(tc.in); s != tc.out {
+			t.Errorf("%d. Replace(%q) = %q, want %q", i, tc.in, s, tc.out)
 		}
 		var buf bytes.Buffer
-		n, err := tt.r.WriteString(&buf, tt.in)
+		n, err := tc.r.WriteString(&buf, tc.in)
 		if err != nil {
 			t.Errorf("%d. WriteString: %v", i, err)
 			continue
 		}
 		got := buf.String()
-		if got != tt.out {
-			t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tt.in, got, tt.out)
+		if got != tc.out {
+			t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tc.in, got, tc.out)
 			continue
 		}
-		if n != len(tt.out) {
+		if n != len(tc.out) {
 			t.Errorf("%d. WriteString(%q) wrote correct string but reported %d bytes; want %d (%q)",
-				i, tt.in, n, len(tt.out), tt.out)
+				i, tc.in, n, len(tc.out), tc.out)
 		}
 	}
 }
 
-// pickAlgorithmTest is a test that verifies that given input for a
-// Replacer that we pick the correct algorithm.
-type pickAlgorithmTest struct {
-	r    *Replacer
-	want string // name of algorithm
+// 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 {
+		got := fmt.Sprintf("%T", tc.r.Replacer())
+		if got != tc.want {
+			t.Errorf("%d. algorithm = %s, want %s", i, got, tc.want)
+		}
+	}
 }
 
-var pickAlgorithmTests = []pickAlgorithmTest{
-	{capitalLetters, "*strings.byteReplacer"},
-	{NewReplacer("12", "123"), "*strings.genericReplacer"},
-	{NewReplacer("1", "12"), "*strings.byteStringReplacer"},
-	{htmlEscaper, "*strings.byteStringReplacer"},
-}
+// 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 "+".
+func TestGenericTrieBuilding(t *testing.T) {
+	testCases := []struct{ in, out string }{
+		{"abc;abdef;abdefgh;xx;xy;z", `-
+			a-
+			.b-
+			..c+
+			..d-
+			...ef+
+			.....gh+
+			x-
+			.x+
+			.y+
+			z+
+			`},
+		{"abracadabra;abracadabrakazam;abraham;abrasion", `-
+			a-
+			.bra-
+			....c-
+			.....adabra+
+			...........kazam+
+			....h-
+			.....am+
+			....s-
+			.....ion+
+			`},
+		{"aaa;aa;a;i;longerst;longer;long;xx;x;X;Y", `-
+			X+
+			Y+
+			a+
+			.a+
+			..a+
+			i+
+			l-
+			.ong+
+			....er+
+			......st+
+			x+
+			.x+
+			`},
+		{"foo;;foo;foo1", `+
+			f-
+			.oo+
+			...1+
+			`},
+	}
 
-func TestPickAlgorithm(t *testing.T) {
-	for i, tt := range pickAlgorithmTests {
-		got := fmt.Sprintf("%T", tt.r.Replacer())
-		if got != tt.want {
-			t.Errorf("%d. algorithm = %s, want %s", i, got, tt.want)
+	for _, tc := range testCases {
+		keys := Split(tc.in, ";")
+		args := make([]string, len(keys)*2)
+		for i, key := range keys {
+			args[i*2] = key
+		}
+
+		got := NewReplacer(args...).PrintTrie()
+		// Remove tabs from tc.out
+		wantbuf := make([]byte, 0, len(tc.out))
+		for i := 0; i < len(tc.out); i++ {
+			if tc.out[i] != '\t' {
+				wantbuf = append(wantbuf, tc.out[i])
+			}
+		}
+		want := string(wantbuf)
+
+		if got != want {
+			t.Errorf("PrintTrie(%q)\ngot\n%swant\n%s", tc.in, got, want)
 		}
 	}
 }
 
-func BenchmarkGenericMatch(b *testing.B) {
+func BenchmarkGenericNoMatch(b *testing.B) {
 	str := Repeat("A", 100) + Repeat("B", 100)
 	generic := NewReplacer("a", "A", "b", "B", "12", "123") // varying lengths forces generic
 	for i := 0; i < b.N; i++ {
@@ -113,6 +398,42 @@ func BenchmarkGenericMatch(b *testing.B) {
 	}
 }
 
+func BenchmarkGenericMatch1(b *testing.B) {
+	str := Repeat("a", 100) + Repeat("b", 100)
+	generic := NewReplacer("a", "A", "b", "B", "12", "123")
+	for i := 0; i < b.N; i++ {
+		generic.Replace(str)
+	}
+}
+
+func BenchmarkGenericMatch2(b *testing.B) {
+	str := Repeat("It's <b>HTML</b>!", 100)
+	for i := 0; i < b.N; i++ {
+		htmlUnescaper.Replace(str)
+	}
+}
+
+func benchmarkSingleString(b *testing.B, pattern, text string) {
+	r := NewReplacer(pattern, "[match]")
+	b.SetBytes(int64(len(text)))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		r.Replace(text)
+	}
+}
+
+func BenchmarkSingleMaxSkipping(b *testing.B) {
+	benchmarkSingleString(b, Repeat("b", 25), Repeat("a", 10000))
+}
+
+func BenchmarkSingleLongSuffixFail(b *testing.B) {
+	benchmarkSingleString(b, "b"+Repeat("a", 500), Repeat("a", 1002))
+}
+
+func BenchmarkSingleMatch(b *testing.B) {
+	benchmarkSingleString(b, "abcdef", Repeat("abcdefghijklmno", 1000))
+}
+
 func BenchmarkByteByteNoMatch(b *testing.B) {
 	str := Repeat("A", 100) + Repeat("B", 100)
 	for i := 0; i < b.N; i++ {
@@ -144,7 +465,7 @@ func BenchmarkHTMLEscapeNew(b *testing.B) {
 func BenchmarkHTMLEscapeOld(b *testing.B) {
 	str := "I <3 to escape HTML & other text too."
 	for i := 0; i < b.N; i++ {
-		oldhtmlEscape(str)
+		oldHTMLEscape(str)
 	}
 }
 
diff --git a/src/pkg/strings/search.go b/src/pkg/strings/search.go
new file mode 100644
index 0000000..f77c879
--- /dev/null
+++ b/src/pkg/strings/search.go
@@ -0,0 +1,124 @@
+// 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 strings
+
+// stringFinder efficiently finds strings in a source text. It's implemented
+// using the Boyer-Moore string search algorithm:
+// http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm
+// http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf (note: this aged
+// document uses 1-based indexing)
+type stringFinder struct {
+	// pattern is the string that we are searching for in the text.
+	pattern string
+
+	// badCharSkip[b] contains the distance between the last byte of pattern
+	// and the rightmost occurrence of b in pattern. If b is not in pattern,
+	// badCharSkip[b] is len(pattern).
+	//
+	// Whenever a mismatch is found with byte b in the text, we can safely
+	// shift the matching frame at least badCharSkip[b] until the next time
+	// the matching char could be in alignment.
+	badCharSkip [256]int
+
+	// goodSuffixSkip[i] defines how far we can shift the matching frame given
+	// that the suffix pattern[i+1:] matches, but the byte pattern[i] does
+	// not. There are two cases to consider:
+	//
+	// 1. The matched suffix occurs elsewhere in pattern (with a different
+	// byte preceding it that we might possibly match). In this case, we can
+	// shift the matching frame to align with the next suffix chunk. For
+	// example, the pattern "mississi" has the suffix "issi" next occurring
+	// (in right-to-left order) at index 1, so goodSuffixSkip[3] ==
+	// shift+len(suffix) == 3+4 == 7.
+	//
+	// 2. If the matched suffix does not occur elsewhere in pattern, then the
+	// matching frame may share part of its prefix with the end of the
+	// matching suffix. In this case, goodSuffixSkip[i] will contain how far
+	// to shift the frame to align this portion of the prefix to the
+	// suffix. For example, in the pattern "abcxxxabc", when the first
+	// mismatch from the back is found to be in position 3, the matching
+	// suffix "xxabc" is not found elsewhere in the pattern. However, its
+	// rightmost "abc" (at position 6) is a prefix of the whole pattern, so
+	// goodSuffixSkip[3] == shift+len(suffix) == 6+5 == 11.
+	goodSuffixSkip []int
+}
+
+func makeStringFinder(pattern string) *stringFinder {
+	f := &stringFinder{
+		pattern:        pattern,
+		goodSuffixSkip: make([]int, len(pattern)),
+	}
+	// last is the index of the last character in the pattern.
+	last := len(pattern) - 1
+
+	// Build bad character table.
+	// Bytes not in the pattern can skip one pattern's length.
+	for i := range f.badCharSkip {
+		f.badCharSkip[i] = len(pattern)
+	}
+	// The loop condition is < instead of <= so that the last byte does not
+	// have a zero distance to itself. Finding this byte out of place implies
+	// that it is not in the last position.
+	for i := 0; i < last; i++ {
+		f.badCharSkip[pattern[i]] = last - i
+	}
+
+	// Build good suffix table.
+	// First pass: set each value to the next index which starts a prefix of
+	// pattern.
+	lastPrefix := last
+	for i := last; i >= 0; i-- {
+		if HasPrefix(pattern, pattern[i+1:]) {
+			lastPrefix = i + 1
+		}
+		// lastPrefix is the shift, and (last-i) is len(suffix).
+		f.goodSuffixSkip[i] = lastPrefix + last - i
+	}
+	// Second pass: find repeats of pattern's suffix starting from the front.
+	for i := 0; i < last; i++ {
+		lenSuffix := longestCommonSuffix(pattern, pattern[1:i+1])
+		if pattern[i-lenSuffix] != pattern[last-lenSuffix] {
+			// (last-i) is the shift, and lenSuffix is len(suffix).
+			f.goodSuffixSkip[last-lenSuffix] = lenSuffix + last - i
+		}
+	}
+
+	return f
+}
+
+func longestCommonSuffix(a, b string) (i int) {
+	for ; i < len(a) && i < len(b); i++ {
+		if a[len(a)-1-i] != b[len(b)-1-i] {
+			break
+		}
+	}
+	return
+}
+
+// next returns the index in text of the first occurrence of the pattern. If
+// the pattern is not found, it returns -1.
+func (f *stringFinder) next(text string) int {
+	i := len(f.pattern) - 1
+	for i < len(text) {
+		// Compare backwards from the end until the first unmatching character.
+		j := len(f.pattern) - 1
+		for j >= 0 && text[i] == f.pattern[j] {
+			i--
+			j--
+		}
+		if j < 0 {
+			return i + 1 // match
+		}
+		i += max(f.badCharSkip[text[i]], f.goodSuffixSkip[j])
+	}
+	return -1
+}
+
+func max(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}
diff --git a/src/pkg/strings/search_test.go b/src/pkg/strings/search_test.go
new file mode 100644
index 0000000..966c05e
--- /dev/null
+++ b/src/pkg/strings/search_test.go
@@ -0,0 +1,90 @@
+// 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 strings_test
+
+import (
+	"reflect"
+	. "strings"
+	"testing"
+)
+
+func TestFinderNext(t *testing.T) {
+	testCases := []struct {
+		pat, text string
+		index     int
+	}{
+		{"", "", 0},
+		{"", "abc", 0},
+		{"abc", "", -1},
+		{"abc", "abc", 0},
+		{"d", "abcdefg", 3},
+		{"nan", "banana", 2},
+		{"pan", "anpanman", 2},
+		{"nnaaman", "anpanmanam", -1},
+		{"abcd", "abc", -1},
+		{"abcd", "bcd", -1},
+		{"bcd", "abcd", 1},
+		{"abc", "acca", -1},
+		{"aa", "aaa", 0},
+		{"baa", "aaaaa", -1},
+		{"at that", "which finally halts.  at that point", 22},
+	}
+
+	for _, tc := range testCases {
+		got := StringFind(tc.pat, tc.text)
+		want := tc.index
+		if got != want {
+			t.Errorf("stringFind(%q, %q) got %d, want %d\n", tc.pat, tc.text, got, want)
+		}
+	}
+}
+
+func TestFinderCreation(t *testing.T) {
+	testCases := []struct {
+		pattern string
+		bad     [256]int
+		suf     []int
+	}{
+		{
+			"abc",
+			[256]int{'a': 2, 'b': 1, 'c': 3},
+			[]int{5, 4, 1},
+		},
+		{
+			"mississi",
+			[256]int{'i': 3, 'm': 7, 's': 1},
+			[]int{15, 14, 13, 7, 11, 10, 7, 1},
+		},
+		// From http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf
+		{
+			"abcxxxabc",
+			[256]int{'a': 2, 'b': 1, 'c': 6, 'x': 3},
+			[]int{14, 13, 12, 11, 10, 9, 11, 10, 1},
+		},
+		{
+			"abyxcdeyx",
+			[256]int{'a': 8, 'b': 7, 'c': 4, 'd': 3, 'e': 2, 'y': 1, 'x': 5},
+			[]int{17, 16, 15, 14, 13, 12, 7, 10, 1},
+		},
+	}
+
+	for _, tc := range testCases {
+		bad, good := DumpTables(tc.pattern)
+
+		for i, got := range bad {
+			want := tc.bad[i]
+			if want == 0 {
+				want = len(tc.pattern)
+			}
+			if got != want {
+				t.Errorf("boyerMoore(%q) bad['%c']: got %d want %d", tc.pattern, i, got, want)
+			}
+		}
+
+		if !reflect.DeepEqual(good, tc.suf) {
+			t.Errorf("boyerMoore(%q) got %v want %v", tc.pattern, good, tc.suf)
+		}
+	}
+}
diff --git a/src/pkg/strings/strings.go b/src/pkg/strings/strings.go
index b411ba5..ccf415e 100644
--- a/src/pkg/strings/strings.go
+++ b/src/pkg/strings/strings.go
@@ -36,27 +36,69 @@ func explode(s string, n int) []string {
 	return a
 }
 
+// primeRK is the prime base used in Rabin-Karp algorithm.
+const primeRK = 16777619
+
+// hashstr returns the hash and the appropriate multiplicative
+// factor for use in Rabin-Karp algorithm.
+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
+}
+
 // Count counts the number of non-overlapping instances of sep in s.
 func Count(s, sep string) int {
-	if sep == "" {
-		return utf8.RuneCountInString(s) + 1
-	}
-	c := sep[0]
-	l := len(sep)
 	n := 0
-	if l == 1 {
+	// special cases
+	switch {
+	case len(sep) == 0:
+		return utf8.RuneCountInString(s) + 1
+	case len(sep) == 1:
 		// special case worth making fast
+		c := sep[0]
 		for i := 0; i < len(s); i++ {
 			if s[i] == c {
 				n++
 			}
 		}
 		return n
+	case len(sep) > len(s):
+		return 0
+	case len(sep) == len(s):
+		if sep == s {
+			return 1
+		}
+		return 0
 	}
-	for i := 0; i+l <= len(s); i++ {
-		if s[i] == c && s[i:i+l] == sep {
+	hashsep, pow := hashstr(sep)
+	h := uint32(0)
+	for i := 0; i < len(sep); i++ {
+		h = h*primeRK + uint32(s[i])
+	}
+	lastmatch := 0
+	if h == hashsep && s[:len(sep)] == sep {
+		n++
+		lastmatch = len(sep)
+	}
+	for i := len(sep); i < len(s); {
+		h *= primeRK
+		h += uint32(s[i])
+		h -= pow * uint32(s[i-len(sep)])
+		i++
+		if h == hashsep && lastmatch <= i-len(sep) && s[i-len(sep):i] == sep {
 			n++
-			i += l - 1
+			lastmatch = i
 		}
 	}
 	return n
@@ -80,11 +122,11 @@ func ContainsRune(s string, r rune) bool {
 // Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
 func Index(s, sep string) int {
 	n := len(sep)
-	if n == 0 {
+	switch {
+	case n == 0:
 		return 0
-	}
-	c := sep[0]
-	if n == 1 {
+	case n == 1:
+		c := sep[0]
 		// special case worth making fast
 		for i := 0; i < len(s); i++ {
 			if s[i] == c {
@@ -92,11 +134,30 @@ func Index(s, sep string) int {
 			}
 		}
 		return -1
+	case n == len(s):
+		if sep == s {
+			return 0
+		}
+		return -1
+	case n > len(s):
+		return -1
 	}
-	// n > 1
-	for i := 0; i+n <= len(s); i++ {
-		if s[i] == c && s[i:i+n] == sep {
-			return i
+	// Hash sep.
+	hashsep, pow := hashstr(sep)
+	var h uint32
+	for i := 0; i < n; i++ {
+		h = h*primeRK + uint32(s[i])
+	}
+	if h == hashsep && s[:n] == sep {
+		return 0
+	}
+	for i := n; i < len(s); {
+		h *= primeRK
+		h += uint32(s[i])
+		h -= pow * uint32(s[i-n])
+		i++
+		if h == hashsep && s[i-n:i] == sep {
+			return i - n
 		}
 	}
 	return -1
@@ -244,7 +305,8 @@ func SplitAfter(s, sep string) []string {
 }
 
 // Fields splits the string s around each instance of one or more consecutive white space
-// characters, returning an array of substrings of s or an empty list if s contains only white space.
+// characters, as defined by unicode.IsSpace, returning an array of substrings of s or an
+// empty list if s contains only white space.
 func Fields(s string) []string {
 	return FieldsFunc(s, unicode.IsSpace)
 }
@@ -558,6 +620,24 @@ func TrimSpace(s string) string {
 	return TrimFunc(s, unicode.IsSpace)
 }
 
+// TrimPrefix returns s without the provided leading prefix string.
+// If s doesn't start with prefix, s is returned unchanged.
+func TrimPrefix(s, prefix string) string {
+	if HasPrefix(s, prefix) {
+		return s[len(prefix):]
+	}
+	return s
+}
+
+// TrimSuffix returns s without the provided trailing suffix string.
+// If s doesn't end with suffix, s is returned unchanged.
+func TrimSuffix(s, suffix string) string {
+	if HasSuffix(s, suffix) {
+		return s[:len(s)-len(suffix)]
+	}
+	return s
+}
+
 // Replace returns a copy of the string s with the first n
 // non-overlapping instances of old replaced by new.
 // If n < 0, there is no limit on the number of replacements.
diff --git a/src/pkg/strings/strings_test.go b/src/pkg/strings/strings_test.go
index 54046d6..09de49e 100644
--- a/src/pkg/strings/strings_test.go
+++ b/src/pkg/strings/strings_test.go
@@ -7,6 +7,7 @@ package strings_test
 import (
 	"bytes"
 	"io"
+	"math/rand"
 	"reflect"
 	. "strings"
 	"testing"
@@ -311,6 +312,13 @@ var FieldsFuncTests = []FieldsTest{
 }
 
 func TestFieldsFunc(t *testing.T) {
+	for _, tt := range fieldstests {
+		a := FieldsFunc(tt.s, unicode.IsSpace)
+		if !eq(a, tt.a) {
+			t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a)
+			continue
+		}
+	}
 	pred := func(c rune) bool { return c == 'X' }
 	for _, tt := range FieldsFuncTests {
 		a := FieldsFunc(tt.s, pred)
@@ -488,8 +496,8 @@ func TestSpecialCase(t *testing.T) {
 func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
 
 var trimTests = []struct {
-	f               string
-	in, cutset, out string
+	f            string
+	in, arg, out string
 }{
 	{"Trim", "abba", "a", "bb"},
 	{"Trim", "abba", "ab", ""},
@@ -512,6 +520,10 @@ var trimTests = []struct {
 	{"TrimRight", "", "123", ""},
 	{"TrimRight", "", "", ""},
 	{"TrimRight", "☺\xc0", "☺", "☺\xc0"},
+	{"TrimPrefix", "aabb", "a", "abb"},
+	{"TrimPrefix", "aabb", "b", "aabb"},
+	{"TrimSuffix", "aabb", "a", "aabb"},
+	{"TrimSuffix", "aabb", "b", "aab"},
 }
 
 func TestTrim(t *testing.T) {
@@ -525,12 +537,16 @@ func TestTrim(t *testing.T) {
 			f = TrimLeft
 		case "TrimRight":
 			f = TrimRight
+		case "TrimPrefix":
+			f = TrimPrefix
+		case "TrimSuffix":
+			f = TrimSuffix
 		default:
 			t.Errorf("Undefined trim function %s", name)
 		}
-		actual := f(tc.in, tc.cutset)
+		actual := f(tc.in, tc.arg)
 		if actual != tc.out {
-			t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
+			t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
 		}
 	}
 }
@@ -951,7 +967,7 @@ var ContainsRuneTests = []struct {
 func TestContainsRune(t *testing.T) {
 	for _, ct := range ContainsRuneTests {
 		if ContainsRune(ct.str, ct.r) != ct.expected {
-			t.Errorf("ContainsRune(%s, %s) = %v, want %v",
+			t.Errorf("ContainsRune(%q, %q) = %v, want %v",
 				ct.str, ct.r, !ct.expected, ct.expected)
 		}
 	}
@@ -984,3 +1000,98 @@ func TestEqualFold(t *testing.T) {
 		}
 	}
 }
+
+func makeBenchInputHard() string {
+	tokens := [...]string{
+		"<a>", "<p>", "<b>", "<strong>",
+		"</a>", "</p>", "</b>", "</strong>",
+		"hello", "world",
+	}
+	x := make([]byte, 0, 1<<20)
+	for len(x) < 1<<20 {
+		i := rand.Intn(len(tokens))
+		x = append(x, tokens[i]...)
+	}
+	return string(x)
+}
+
+var benchInputHard = makeBenchInputHard()
+
+func benchmarkIndexHard(b *testing.B, sep string) {
+	for i := 0; i < b.N; i++ {
+		Index(benchInputHard, sep)
+	}
+}
+
+func benchmarkCountHard(b *testing.B, sep string) {
+	for i := 0; i < b.N; i++ {
+		Count(benchInputHard, sep)
+	}
+}
+
+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 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>") }
+
+var benchInputTorture = Repeat("ABC", 1<<10) + "123" + Repeat("ABC", 1<<10)
+var benchNeedleTorture = Repeat("ABC", 1<<10+1)
+
+func BenchmarkIndexTorture(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Index(benchInputTorture, benchNeedleTorture)
+	}
+}
+
+func BenchmarkCountTorture(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Count(benchInputTorture, benchNeedleTorture)
+	}
+}
+
+func BenchmarkCountTortureOverlapping(b *testing.B) {
+	A := Repeat("ABC", 1<<20)
+	B := Repeat("ABC", 1<<10)
+	for i := 0; i < b.N; i++ {
+		Count(A, B)
+	}
+}
+
+var makeFieldsInput = func() string {
+	x := make([]byte, 1<<20)
+	// Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
+	for i := range x {
+		switch rand.Intn(10) {
+		case 0:
+			x[i] = ' '
+		case 1:
+			if i > 0 && x[i-1] == 'x' {
+				copy(x[i-1:], "χ")
+				break
+			}
+			fallthrough
+		default:
+			x[i] = 'x'
+		}
+	}
+	return string(x)
+}
+
+var fieldsInput = makeFieldsInput()
+
+func BenchmarkFields(b *testing.B) {
+	b.SetBytes(int64(len(fieldsInput)))
+	for i := 0; i < b.N; i++ {
+		Fields(fieldsInput)
+	}
+}
+
+func BenchmarkFieldsFunc(b *testing.B) {
+	b.SetBytes(int64(len(fieldsInput)))
+	for i := 0; i < b.N; i++ {
+		FieldsFunc(fieldsInput, unicode.IsSpace)
+	}
+}
diff --git a/src/pkg/sync/atomic/64bit_arm.go b/src/pkg/sync/atomic/64bit_arm.go
new file mode 100644
index 0000000..f070e78
--- /dev/null
+++ b/src/pkg/sync/atomic/64bit_arm.go
@@ -0,0 +1,36 @@
+// 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 atomic
+
+func loadUint64(addr *uint64) (val uint64) {
+	for {
+		val = *addr
+		if CompareAndSwapUint64(addr, val, val) {
+			break
+		}
+	}
+	return
+}
+
+func storeUint64(addr *uint64, val uint64) {
+	for {
+		old := *addr
+		if CompareAndSwapUint64(addr, old, val) {
+			break
+		}
+	}
+	return
+}
+
+func addUint64(val *uint64, delta uint64) (new uint64) {
+	for {
+		old := *val
+		new = old + delta
+		if CompareAndSwapUint64(val, old, new) {
+			break
+		}
+	}
+	return
+}
diff --git a/src/pkg/sync/atomic/asm_386.s b/src/pkg/sync/atomic/asm_386.s
index a406852..7a98a61 100644
--- a/src/pkg/sync/atomic/asm_386.s
+++ b/src/pkg/sync/atomic/asm_386.s
@@ -2,17 +2,19 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !race
+
 TEXT ·CompareAndSwapInt32(SB),7,$0
 	JMP	·CompareAndSwapUint32(SB)
 
 TEXT ·CompareAndSwapUint32(SB),7,$0
-	MOVL	valptr+0(FP), BP
+	MOVL	addr+0(FP), BP
 	MOVL	old+4(FP), AX
 	MOVL	new+8(FP), CX
 	// CMPXCHGL was introduced on the 486.
 	LOCK
 	CMPXCHGL	CX, 0(BP)
-	SETEQ	ret+12(FP)
+	SETEQ	swapped+12(FP)
 	RET
 
 TEXT ·CompareAndSwapUintptr(SB),7,$0
@@ -25,29 +27,29 @@ TEXT ·CompareAndSwapInt64(SB),7,$0
 	JMP	·CompareAndSwapUint64(SB)
 
 TEXT ·CompareAndSwapUint64(SB),7,$0
-	MOVL	valptr+0(FP), BP
-	MOVL	oldlo+4(FP), AX
-	MOVL	oldhi+8(FP), DX
-	MOVL	newlo+12(FP), BX
-	MOVL	newhi+16(FP), CX
+	MOVL	addr+0(FP), BP
+	MOVL	old+4(FP), AX
+	MOVL	old+8(FP), DX
+	MOVL	new+12(FP), BX
+	MOVL	new+16(FP), CX
 	// CMPXCHG8B was introduced on the Pentium.
 	LOCK
 	CMPXCHG8B	0(BP)
-	SETEQ	ret+20(FP)
+	SETEQ	swapped+20(FP)
 	RET
 
 TEXT ·AddInt32(SB),7,$0
 	JMP	·AddUint32(SB)
 
 TEXT ·AddUint32(SB),7,$0
-	MOVL	valptr+0(FP), BP
+	MOVL	addr+0(FP), BP
 	MOVL	delta+4(FP), AX
 	MOVL	AX, CX
 	// XADD was introduced on the 486.
 	LOCK
 	XADDL	AX, 0(BP)
 	ADDL	AX, CX
-	MOVL	CX, ret+8(FP)
+	MOVL	CX, new+8(FP)
 	RET
 
 TEXT ·AddUintptr(SB),7,$0
@@ -58,24 +60,24 @@ TEXT ·AddInt64(SB),7,$0
 
 TEXT ·AddUint64(SB),7,$0
 	// no XADDQ so use CMPXCHG8B loop
-	MOVL	valptr+0(FP), BP
+	MOVL	addr+0(FP), BP
 	// DI:SI = delta
-	MOVL	deltalo+4(FP), SI
-	MOVL	deltahi+8(FP), DI
-	// DX:AX = *valptr
+	MOVL	delta+4(FP), SI
+	MOVL	delta+8(FP), DI
+	// DX:AX = *addr
 	MOVL	0(BP), AX
 	MOVL	4(BP), DX
 addloop:
-	// CX:BX = DX:AX (*valptr) + DI:SI (delta)
+	// CX:BX = DX:AX (*addr) + DI:SI (delta)
 	MOVL	AX, BX
 	MOVL	DX, CX
 	ADDL	SI, BX
 	ADCL	DI, CX
 
-	// if *valptr == DX:AX {
-	//	*valptr = CX:BX
+	// if *addr == DX:AX {
+	//	*addr = CX:BX
 	// } else {
-	//	DX:AX = *valptr
+	//	DX:AX = *addr
 	// }
 	// all in one instruction
 	LOCK
@@ -85,24 +87,24 @@ addloop:
 
 	// success
 	// return CX:BX
-	MOVL	BX, retlo+12(FP)
-	MOVL	CX, rethi+16(FP)
+	MOVL	BX, new+12(FP)
+	MOVL	CX, new+16(FP)
 	RET
 
 TEXT ·LoadInt32(SB),7,$0
 	JMP	·LoadUint32(SB)
 
 TEXT ·LoadUint32(SB),7,$0
-	MOVL	addrptr+0(FP), AX
+	MOVL	addr+0(FP), AX
 	MOVL	0(AX), AX
-	MOVL	AX, ret+4(FP)
+	MOVL	AX, val+4(FP)
 	RET
 
 TEXT ·LoadInt64(SB),7,$0
 	JMP	·LoadUint64(SB)
 
 TEXT ·LoadUint64(SB),7,$0
-	MOVL	addrptr+0(FP), AX
+	MOVL	addr+0(FP), AX
 	// MOVQ and EMMS were introduced on the Pentium MMX.
 	// MOVQ (%EAX), %MM0
 	BYTE $0x0f; BYTE $0x6f; BYTE $0x00
@@ -121,7 +123,7 @@ TEXT ·StoreInt32(SB),7,$0
 	JMP	·StoreUint32(SB)
 
 TEXT ·StoreUint32(SB),7,$0
-	MOVL	addrptr+0(FP), BP
+	MOVL	addr+0(FP), BP
 	MOVL	val+4(FP), AX
 	XCHGL	AX, 0(BP)
 	RET
@@ -130,7 +132,7 @@ TEXT ·StoreInt64(SB),7,$0
 	JMP	·StoreUint64(SB)
 
 TEXT ·StoreUint64(SB),7,$0
-	MOVL	addrptr+0(FP), AX
+	MOVL	addr+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
diff --git a/src/pkg/sync/atomic/asm_amd64.s b/src/pkg/sync/atomic/asm_amd64.s
index 6f8bde0..58bda9e 100644
--- a/src/pkg/sync/atomic/asm_amd64.s
+++ b/src/pkg/sync/atomic/asm_amd64.s
@@ -2,16 +2,18 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !race
+
 TEXT ·CompareAndSwapInt32(SB),7,$0
 	JMP	·CompareAndSwapUint32(SB)
 
 TEXT ·CompareAndSwapUint32(SB),7,$0
-	MOVQ	valptr+0(FP), BP
+	MOVQ	addr+0(FP), BP
 	MOVL	old+8(FP), AX
 	MOVL	new+12(FP), CX
 	LOCK
 	CMPXCHGL	CX, 0(BP)
-	SETEQ	ret+16(FP)
+	SETEQ	swapped+16(FP)
 	RET
 
 TEXT ·CompareAndSwapUintptr(SB),7,$0
@@ -24,25 +26,25 @@ TEXT ·CompareAndSwapInt64(SB),7,$0
 	JMP	·CompareAndSwapUint64(SB)
 
 TEXT ·CompareAndSwapUint64(SB),7,$0
-	MOVQ	valptr+0(FP), BP
+	MOVQ	addr+0(FP), BP
 	MOVQ	old+8(FP), AX
 	MOVQ	new+16(FP), CX
 	LOCK
 	CMPXCHGQ	CX, 0(BP)
-	SETEQ	ret+24(FP)
+	SETEQ	swapped+24(FP)
 	RET
 
 TEXT ·AddInt32(SB),7,$0
 	JMP	·AddUint32(SB)
 
 TEXT ·AddUint32(SB),7,$0
-	MOVQ	valptr+0(FP), BP
+	MOVQ	addr+0(FP), BP
 	MOVL	delta+8(FP), AX
 	MOVL	AX, CX
 	LOCK
 	XADDL	AX, 0(BP)
 	ADDL	AX, CX
-	MOVL	CX, ret+16(FP)
+	MOVL	CX, new+16(FP)
 	RET
 
 TEXT ·AddUintptr(SB),7,$0
@@ -52,47 +54,47 @@ TEXT ·AddInt64(SB),7,$0
 	JMP	·AddUint64(SB)
 
 TEXT ·AddUint64(SB),7,$0
-	MOVQ	valptr+0(FP), BP
+	MOVQ	addr+0(FP), BP
 	MOVQ	delta+8(FP), AX
 	MOVQ	AX, CX
 	LOCK
 	XADDQ	AX, 0(BP)
 	ADDQ	AX, CX
-	MOVQ	CX, ret+16(FP)
+	MOVQ	CX, new+16(FP)
 	RET
 
 TEXT ·LoadInt32(SB),7,$0
 	JMP	·LoadUint32(SB)
 
 TEXT ·LoadUint32(SB),7,$0
-	MOVQ	addrptr+0(FP), AX
+	MOVQ	addr+0(FP), AX
 	MOVL	0(AX), AX
-	MOVL	AX, ret+8(FP)
+	MOVL	AX, val+8(FP)
 	RET
 
 TEXT ·LoadInt64(SB),7,$0
 	JMP	·LoadUint64(SB)
 
 TEXT ·LoadUint64(SB),7,$0
-	MOVQ	addrptr+0(FP), AX
+	MOVQ	addr+0(FP), AX
 	MOVQ	0(AX), AX
-	MOVQ	AX, ret+8(FP)
+	MOVQ	AX, val+8(FP)
 	RET
 
 TEXT ·LoadUintptr(SB),7,$0
 	JMP	·LoadPointer(SB)
 
 TEXT ·LoadPointer(SB),7,$0
-	MOVQ	addrptr+0(FP), AX
+	MOVQ	addr+0(FP), AX
 	MOVQ	0(AX), AX
-	MOVQ	AX, ret+8(FP)
+	MOVQ	AX, val+8(FP)
 	RET
 
 TEXT ·StoreInt32(SB),7,$0
 	JMP	·StoreUint32(SB)
 
 TEXT ·StoreUint32(SB),7,$0
-	MOVQ	addrptr+0(FP), BP
+	MOVQ	addr+0(FP), BP
 	MOVL	val+8(FP), AX
 	XCHGL	AX, 0(BP)
 	RET
@@ -101,7 +103,7 @@ TEXT ·StoreInt64(SB),7,$0
 	JMP	·StoreUint64(SB)
 
 TEXT ·StoreUint64(SB),7,$0
-	MOVQ	addrptr+0(FP), BP
+	MOVQ	addr+0(FP), BP
 	MOVQ	val+8(FP), AX
 	XCHGQ	AX, 0(BP)
 	RET
@@ -110,7 +112,7 @@ TEXT ·StoreUintptr(SB),7,$0
 	JMP	·StorePointer(SB)
 
 TEXT ·StorePointer(SB),7,$0
-	MOVQ	addrptr+0(FP), BP
+	MOVQ	addr+0(FP), BP
 	MOVQ	val+8(FP), AX
 	XCHGQ	AX, 0(BP)
 	RET
diff --git a/src/pkg/sync/atomic/asm_arm.s b/src/pkg/sync/atomic/asm_arm.s
index 2d10a92..4faf5b5 100644
--- a/src/pkg/sync/atomic/asm_arm.s
+++ b/src/pkg/sync/atomic/asm_arm.s
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !race
+
 // ARM atomic operations, for use by asm_$(GOOS)_arm.s.
 
 TEXT ·armCompareAndSwapUint32(SB),7,$0
-	MOVW	valptr+0(FP), R1
+	MOVW	addr+0(FP), R1
 	MOVW	old+4(FP), R2
 	MOVW	new+8(FP), R3
 casloop:
@@ -26,7 +28,7 @@ casfail:
 
 TEXT ·armCompareAndSwapUint64(SB),7,$0
 	BL	fastCheck64<>(SB)
-	MOVW	valptr+0(FP), R1
+	MOVW	addr+0(FP), R1
 	MOVW	oldlo+4(FP), R2
 	MOVW	oldhi+8(FP), R3
 	MOVW	newlo+12(FP), R4
@@ -50,7 +52,7 @@ cas64fail:
 	RET
 
 TEXT ·armAddUint32(SB),7,$0
-	MOVW	valptr+0(FP), R1
+	MOVW	addr+0(FP), R1
 	MOVW	delta+4(FP), R2
 addloop:
 	// LDREX and STREX were introduced in ARM 6.
@@ -64,7 +66,7 @@ addloop:
 
 TEXT ·armAddUint64(SB),7,$0
 	BL	fastCheck64<>(SB)
-	MOVW	valptr+0(FP), R1
+	MOVW	addr+0(FP), R1
 	MOVW	deltalo+4(FP), R2
 	MOVW	deltahi+8(FP), R3
 add64loop:
@@ -81,7 +83,7 @@ add64loop:
 
 TEXT ·armLoadUint64(SB),7,$0
 	BL	fastCheck64<>(SB)
-	MOVW	addrptr+0(FP), R1
+	MOVW	addr+0(FP), R1
 load64loop:
 	LDREXD	(R1), R2	// loads R2 and R3
 	STREXD	R2, (R1), R0	// stores R2 and R3
@@ -93,7 +95,7 @@ load64loop:
 
 TEXT ·armStoreUint64(SB),7,$0
 	BL	fastCheck64<>(SB)
-	MOVW	addrptr+0(FP), R1
+	MOVW	addr+0(FP), R1
 	MOVW	vallo+4(FP), R2
 	MOVW	valhi+8(FP), R3
 store64loop:
diff --git a/src/pkg/sync/atomic/asm_freebsd_arm.s b/src/pkg/sync/atomic/asm_freebsd_arm.s
new file mode 100644
index 0000000..6590921
--- /dev/null
+++ b/src/pkg/sync/atomic/asm_freebsd_arm.s
@@ -0,0 +1,89 @@
+// 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.
+
+// FreeBSD/ARM atomic operations.
+// TODO(minux): this only supports ARMv6K or higher.
+
+TEXT ·CompareAndSwapInt32(SB),7,$0
+	B ·CompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapUint32(SB),7,$0
+	B ·armCompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapUintptr(SB),7,$0
+	B ·CompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapPointer(SB),7,$0
+	B ·CompareAndSwapUint32(SB)
+
+TEXT ·AddInt32(SB),7,$0
+	B ·AddUint32(SB)
+
+TEXT ·AddUint32(SB),7,$0
+	B ·armAddUint32(SB)
+
+TEXT ·AddUintptr(SB),7,$0
+	B ·AddUint32(SB)
+
+TEXT ·CompareAndSwapInt64(SB),7,$0
+	B ·CompareAndSwapUint64(SB)
+
+TEXT ·CompareAndSwapUint64(SB),7,$-4
+	B ·armCompareAndSwapUint64(SB)
+
+TEXT ·AddInt64(SB),7,$0
+	B ·addUint64(SB)
+
+TEXT ·AddUint64(SB),7,$0
+	B ·addUint64(SB)
+
+TEXT ·LoadInt32(SB),7,$0
+	B ·LoadUint32(SB)
+
+TEXT ·LoadUint32(SB),7,$0
+	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),7,$0
+	B ·loadUint64(SB)
+
+TEXT ·LoadUint64(SB),7,$0
+	B ·loadUint64(SB)
+
+TEXT ·LoadUintptr(SB),7,$0
+	B ·LoadUint32(SB)
+
+TEXT ·LoadPointer(SB),7,$0
+	B ·LoadUint32(SB)
+
+TEXT ·StoreInt32(SB),7,$0
+	B ·StoreUint32(SB)
+
+TEXT ·StoreUint32(SB),7,$0
+	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),7,$0
+	B ·storeUint64(SB)
+
+TEXT ·StoreUint64(SB),7,$0
+	B ·storeUint64(SB)
+
+TEXT ·StoreUintptr(SB),7,$0
+	B ·StoreUint32(SB)
+
+TEXT ·StorePointer(SB),7,$0
+	B ·StoreUint32(SB)
diff --git a/src/pkg/sync/atomic/asm_linux_arm.s b/src/pkg/sync/atomic/asm_linux_arm.s
index 25dc858..098acf3 100644
--- a/src/pkg/sync/atomic/asm_linux_arm.s
+++ b/src/pkg/sync/atomic/asm_linux_arm.s
@@ -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 !race
+
 // Linux/ARM atomic operations.
 
 // Because there is so much variation in ARM devices,
@@ -9,7 +11,7 @@
 // implementation at address 0xffff0fc0.  Caller sets:
 //	R0 = old value
 //	R1 = new value
-//	R2 = valptr
+//	R2 = addr
 //	LR = return address
 // The function returns with CS true if the swap happened.
 // http://lxr.linux.no/linux+v2.6.37.2/arch/arm/kernel/entry-armv.S#L850
@@ -27,7 +29,7 @@ TEXT ·CompareAndSwapInt32(SB),7,$0
 
 // Implement using kernel cas for portability.
 TEXT ·CompareAndSwapUint32(SB),7,$0
-	MOVW	valptr+0(FP), R2
+	MOVW	addr+0(FP), R2
 	MOVW	old+4(FP), R0
 casagain:
 	MOVW	new+8(FP), R1
@@ -39,7 +41,7 @@ casret:
 	RET
 cascheck:
 	// Kernel lies; double-check.
-	MOVW	valptr+0(FP), R2
+	MOVW	addr+0(FP), R2
 	MOVW	old+4(FP), R0
 	MOVW	0(R2), R3
 	CMP	R0, R3
@@ -58,7 +60,7 @@ TEXT ·AddInt32(SB),7,$0
 
 // Implement using kernel cas for portability.
 TEXT ·AddUint32(SB),7,$0
-	MOVW	valptr+0(FP), R2
+	MOVW	addr+0(FP), R2
 	MOVW	delta+4(FP), R4
 addloop1:
 	MOVW	0(R2), R0
@@ -72,26 +74,75 @@ addloop1:
 TEXT ·AddUintptr(SB),7,$0
 	B	·AddUint32(SB)
 
-// The kernel provides no 64-bit compare-and-swap,
-// so use native ARM instructions, which will only work on
-// ARM 11 and later devices.
+TEXT cas64<>(SB),7,$0
+	MOVW	$0xffff0f60, PC // __kuser_cmpxchg64: Linux-3.1 and above
+
+TEXT kernelCAS64<>(SB),7,$0
+	// int (*__kuser_cmpxchg64_t)(const int64_t *oldval, const int64_t *newval, volatile int64_t *ptr);
+	MOVW	addr+0(FP), R2 // ptr
+	MOVW	$4(FP), R0 // oldval
+	MOVW	$12(FP), R1 // newval
+	BL		cas64<>(SB)
+	MOVW.CS	$1, R0 // C is set if the kernel has changed *ptr
+	MOVW.CC	$0, R0
+	MOVW	R0, 20(FP)
+	RET
+
+TEXT generalCAS64<>(SB),7,$20
+	// bool runtime·cas64(uint64 volatile *addr, uint64 *old, uint64 new)
+	MOVW	addr+0(FP), R0
+	MOVW	R0, 4(R13)
+	MOVW	$4(FP), R1 // oldval
+	MOVW	R1, 8(R13)
+	MOVW	newlo+12(FP), R2
+	MOVW	R2, 12(R13)
+	MOVW	newhi+16(FP), R3
+	MOVW	R3, 16(R13)
+	BL  	runtime·cas64(SB)
+	MOVW	R0, 20(FP)
+	RET
+
+GLOBL armCAS64(SB), $4
+
+TEXT setupAndCallCAS64<>(SB),7,$-4
+	MOVW	$0xffff0ffc, R0 // __kuser_helper_version
+	MOVW	(R0), R0
+	// __kuser_cmpxchg64 only present if helper version >= 5
+	CMP 	$5, R0
+	MOVW.CS	$kernelCAS64<>(SB), R1
+	MOVW.CS	R1, armCAS64(SB)
+	MOVW.CS	R1, PC
+	MOVB	runtime·armArch(SB), R0
+	// LDREXD, STREXD only present on ARMv6K or higher
+	CMP		$6, R0 // TODO(minux): how to differentiate ARMv6 with ARMv6K?
+	MOVW.CS	$·armCompareAndSwapUint64(SB), R1
+	MOVW.CS	R1, armCAS64(SB)
+	MOVW.CS	R1, PC
+	// we are out of luck, can only use runtime's emulated 64-bit cas
+	MOVW	$generalCAS64<>(SB), R1
+	MOVW	R1, armCAS64(SB)
+	MOVW	R1, PC
+
 TEXT ·CompareAndSwapInt64(SB),7,$0
-	B	·armCompareAndSwapUint64(SB)
+	B   	·CompareAndSwapUint64(SB)
 
-TEXT ·CompareAndSwapUint64(SB),7,$0
-	B	·armCompareAndSwapUint64(SB)
+TEXT ·CompareAndSwapUint64(SB),7,$-4
+	MOVW	armCAS64(SB), R0
+	CMP 	$0, R0
+	MOVW.NE	R0, PC
+	B		setupAndCallCAS64<>(SB)
 
 TEXT ·AddInt64(SB),7,$0
-	B	·armAddUint64(SB)
+	B	·addUint64(SB)
 
 TEXT ·AddUint64(SB),7,$0
-	B	·armAddUint64(SB)
+	B	·addUint64(SB)
 
 TEXT ·LoadInt32(SB),7,$0
 	B	·LoadUint32(SB)
 
 TEXT ·LoadUint32(SB),7,$0
-	MOVW	addrptr+0(FP), R2
+	MOVW	addr+0(FP), R2
 loadloop1:
 	MOVW	0(R2), R0
 	MOVW	R0, R1
@@ -101,10 +152,10 @@ loadloop1:
 	RET
 
 TEXT ·LoadInt64(SB),7,$0
-	B	·armLoadUint64(SB)
+	B	·loadUint64(SB)
 
 TEXT ·LoadUint64(SB),7,$0
-	B	·armLoadUint64(SB)
+	B	·loadUint64(SB)
 
 TEXT ·LoadUintptr(SB),7,$0
 	B	·LoadUint32(SB)
@@ -116,7 +167,7 @@ TEXT ·StoreInt32(SB),7,$0
 	B	·StoreUint32(SB)
 
 TEXT ·StoreUint32(SB),7,$0
-	MOVW	addrptr+0(FP), R2
+	MOVW	addr+0(FP), R2
 	MOVW	val+4(FP), R1
 storeloop1:
 	MOVW	0(R2), R0
@@ -125,10 +176,10 @@ storeloop1:
 	RET
 
 TEXT ·StoreInt64(SB),7,$0
-	B	·armStoreUint64(SB)
+	B	·storeUint64(SB)
 
 TEXT ·StoreUint64(SB),7,$0
-	B	·armStoreUint64(SB)
+	B	·storeUint64(SB)
 
 TEXT ·StoreUintptr(SB),7,$0
 	B	·StoreUint32(SB)
diff --git a/src/pkg/sync/atomic/asm_netbsd_arm.s b/src/pkg/sync/atomic/asm_netbsd_arm.s
new file mode 100644
index 0000000..677f3da
--- /dev/null
+++ b/src/pkg/sync/atomic/asm_netbsd_arm.s
@@ -0,0 +1,89 @@
+// 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.
+
+// NetBSD/ARM atomic operations.
+// TODO(minux): this only supports ARMv6K or higher.
+
+TEXT ·CompareAndSwapInt32(SB),7,$0
+	B ·CompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapUint32(SB),7,$0
+	B ·armCompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapUintptr(SB),7,$0
+	B ·CompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapPointer(SB),7,$0
+	B ·CompareAndSwapUint32(SB)
+
+TEXT ·AddInt32(SB),7,$0
+	B ·AddUint32(SB)
+
+TEXT ·AddUint32(SB),7,$0
+	B ·armAddUint32(SB)
+
+TEXT ·AddUintptr(SB),7,$0
+	B ·AddUint32(SB)
+
+TEXT ·CompareAndSwapInt64(SB),7,$0
+	B ·CompareAndSwapUint64(SB)
+
+TEXT ·CompareAndSwapUint64(SB),7,$-4
+	B ·armCompareAndSwapUint64(SB)
+
+TEXT ·AddInt64(SB),7,$0
+	B ·addUint64(SB)
+
+TEXT ·AddUint64(SB),7,$0
+	B ·addUint64(SB)
+
+TEXT ·LoadInt32(SB),7,$0
+	B ·LoadUint32(SB)
+
+TEXT ·LoadUint32(SB),7,$0
+	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),7,$0
+	B ·loadUint64(SB)
+
+TEXT ·LoadUint64(SB),7,$0
+	B ·loadUint64(SB)
+
+TEXT ·LoadUintptr(SB),7,$0
+	B ·LoadUint32(SB)
+
+TEXT ·LoadPointer(SB),7,$0
+	B ·LoadUint32(SB)
+
+TEXT ·StoreInt32(SB),7,$0
+	B ·StoreUint32(SB)
+
+TEXT ·StoreUint32(SB),7,$0
+	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),7,$0
+	B ·storeUint64(SB)
+
+TEXT ·StoreUint64(SB),7,$0
+	B ·storeUint64(SB)
+
+TEXT ·StoreUintptr(SB),7,$0
+	B ·StoreUint32(SB)
+
+TEXT ·StorePointer(SB),7,$0
+	B ·StoreUint32(SB)
diff --git a/src/pkg/sync/atomic/atomic_test.go b/src/pkg/sync/atomic/atomic_test.go
index f60d997..3e10556 100644
--- a/src/pkg/sync/atomic/atomic_test.go
+++ b/src/pkg/sync/atomic/atomic_test.go
@@ -82,8 +82,7 @@ func TestAddUint32(t *testing.T) {
 
 func TestAddInt64(t *testing.T) {
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	var x struct {
 		before int64
@@ -107,8 +106,7 @@ func TestAddInt64(t *testing.T) {
 
 func TestAddUint64(t *testing.T) {
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	var x struct {
 		before uint64
@@ -213,8 +211,7 @@ func TestCompareAndSwapUint32(t *testing.T) {
 
 func TestCompareAndSwapInt64(t *testing.T) {
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	var x struct {
 		before int64
@@ -246,8 +243,7 @@ func TestCompareAndSwapInt64(t *testing.T) {
 
 func TestCompareAndSwapUint64(t *testing.T) {
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	var x struct {
 		before uint64
@@ -381,8 +377,7 @@ func TestLoadUint32(t *testing.T) {
 
 func TestLoadInt64(t *testing.T) {
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	var x struct {
 		before int64
@@ -405,8 +400,7 @@ func TestLoadInt64(t *testing.T) {
 
 func TestLoadUint64(t *testing.T) {
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	var x struct {
 		before uint64
@@ -515,8 +509,7 @@ func TestStoreUint32(t *testing.T) {
 
 func TestStoreInt64(t *testing.T) {
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	var x struct {
 		before int64
@@ -540,8 +533,7 @@ func TestStoreInt64(t *testing.T) {
 
 func TestStoreUint64(t *testing.T) {
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	var x struct {
 		before uint64
@@ -640,73 +632,73 @@ func init() {
 	}
 }
 
-func hammerAddInt32(uval *uint32, count int) {
-	val := (*int32)(unsafe.Pointer(uval))
+func hammerAddInt32(uaddr *uint32, count int) {
+	addr := (*int32)(unsafe.Pointer(uaddr))
 	for i := 0; i < count; i++ {
-		AddInt32(val, 1)
+		AddInt32(addr, 1)
 	}
 }
 
-func hammerAddUint32(val *uint32, count int) {
+func hammerAddUint32(addr *uint32, count int) {
 	for i := 0; i < count; i++ {
-		AddUint32(val, 1)
+		AddUint32(addr, 1)
 	}
 }
 
-func hammerAddUintptr32(uval *uint32, count int) {
+func hammerAddUintptr32(uaddr *uint32, count int) {
 	// only safe when uintptr is 32-bit.
 	// not called on 64-bit systems.
-	val := (*uintptr)(unsafe.Pointer(uval))
+	addr := (*uintptr)(unsafe.Pointer(uaddr))
 	for i := 0; i < count; i++ {
-		AddUintptr(val, 1)
+		AddUintptr(addr, 1)
 	}
 }
 
-func hammerCompareAndSwapInt32(uval *uint32, count int) {
-	val := (*int32)(unsafe.Pointer(uval))
+func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
+	addr := (*int32)(unsafe.Pointer(uaddr))
 	for i := 0; i < count; i++ {
 		for {
-			v := *val
-			if CompareAndSwapInt32(val, v, v+1) {
+			v := *addr
+			if CompareAndSwapInt32(addr, v, v+1) {
 				break
 			}
 		}
 	}
 }
 
-func hammerCompareAndSwapUint32(val *uint32, count int) {
+func hammerCompareAndSwapUint32(addr *uint32, count int) {
 	for i := 0; i < count; i++ {
 		for {
-			v := *val
-			if CompareAndSwapUint32(val, v, v+1) {
+			v := *addr
+			if CompareAndSwapUint32(addr, v, v+1) {
 				break
 			}
 		}
 	}
 }
 
-func hammerCompareAndSwapUintptr32(uval *uint32, count int) {
+func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
 	// only safe when uintptr is 32-bit.
 	// not called on 64-bit systems.
-	val := (*uintptr)(unsafe.Pointer(uval))
+	addr := (*uintptr)(unsafe.Pointer(uaddr))
 	for i := 0; i < count; i++ {
 		for {
-			v := *val
-			if CompareAndSwapUintptr(val, v, v+1) {
+			v := *addr
+			if CompareAndSwapUintptr(addr, v, v+1) {
 				break
 			}
 		}
 	}
 }
 
-func hammerCompareAndSwapPointer32(uval *uint32, count int) {
+func hammerCompareAndSwapPointer32(uaddr *uint32, count int) {
 	// only safe when uintptr is 32-bit.
 	// not called on 64-bit systems.
-	val := (*unsafe.Pointer)(unsafe.Pointer(uval))
+	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
 	for i := 0; i < count; i++ {
 		for {
-			v := *val
-			if CompareAndSwapPointer(val, v, unsafe.Pointer(uintptr(v)+1)) {
+			v := *addr
+			if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
 				break
 			}
 		}
@@ -765,73 +757,73 @@ func init() {
 	}
 }
 
-func hammerAddInt64(uval *uint64, count int) {
-	val := (*int64)(unsafe.Pointer(uval))
+func hammerAddInt64(uaddr *uint64, count int) {
+	addr := (*int64)(unsafe.Pointer(uaddr))
 	for i := 0; i < count; i++ {
-		AddInt64(val, 1)
+		AddInt64(addr, 1)
 	}
 }
 
-func hammerAddUint64(val *uint64, count int) {
+func hammerAddUint64(addr *uint64, count int) {
 	for i := 0; i < count; i++ {
-		AddUint64(val, 1)
+		AddUint64(addr, 1)
 	}
 }
 
-func hammerAddUintptr64(uval *uint64, count int) {
+func hammerAddUintptr64(uaddr *uint64, count int) {
 	// only safe when uintptr is 64-bit.
 	// not called on 32-bit systems.
-	val := (*uintptr)(unsafe.Pointer(uval))
+	addr := (*uintptr)(unsafe.Pointer(uaddr))
 	for i := 0; i < count; i++ {
-		AddUintptr(val, 1)
+		AddUintptr(addr, 1)
 	}
 }
 
-func hammerCompareAndSwapInt64(uval *uint64, count int) {
-	val := (*int64)(unsafe.Pointer(uval))
+func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
+	addr := (*int64)(unsafe.Pointer(uaddr))
 	for i := 0; i < count; i++ {
 		for {
-			v := *val
-			if CompareAndSwapInt64(val, v, v+1) {
+			v := *addr
+			if CompareAndSwapInt64(addr, v, v+1) {
 				break
 			}
 		}
 	}
 }
 
-func hammerCompareAndSwapUint64(val *uint64, count int) {
+func hammerCompareAndSwapUint64(addr *uint64, count int) {
 	for i := 0; i < count; i++ {
 		for {
-			v := *val
-			if CompareAndSwapUint64(val, v, v+1) {
+			v := *addr
+			if CompareAndSwapUint64(addr, v, v+1) {
 				break
 			}
 		}
 	}
 }
 
-func hammerCompareAndSwapUintptr64(uval *uint64, count int) {
+func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
 	// only safe when uintptr is 64-bit.
 	// not called on 32-bit systems.
-	val := (*uintptr)(unsafe.Pointer(uval))
+	addr := (*uintptr)(unsafe.Pointer(uaddr))
 	for i := 0; i < count; i++ {
 		for {
-			v := *val
-			if CompareAndSwapUintptr(val, v, v+1) {
+			v := *addr
+			if CompareAndSwapUintptr(addr, v, v+1) {
 				break
 			}
 		}
 	}
 }
 
-func hammerCompareAndSwapPointer64(uval *uint64, count int) {
+func hammerCompareAndSwapPointer64(uaddr *uint64, count int) {
 	// only safe when uintptr is 64-bit.
 	// not called on 32-bit systems.
-	val := (*unsafe.Pointer)(unsafe.Pointer(uval))
+	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
 	for i := 0; i < count; i++ {
 		for {
-			v := *val
-			if CompareAndSwapPointer(val, v, unsafe.Pointer(uintptr(v)+1)) {
+			v := *addr
+			if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
 				break
 			}
 		}
@@ -840,8 +832,7 @@ func hammerCompareAndSwapPointer64(uval *uint64, count int) {
 
 func TestHammer64(t *testing.T) {
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	const p = 4
 	n := 100000
@@ -871,9 +862,9 @@ func TestHammer64(t *testing.T) {
 	}
 }
 
-func hammerStoreLoadInt32(t *testing.T, valp unsafe.Pointer) {
-	val := (*int32)(valp)
-	v := LoadInt32(val)
+func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*int32)(paddr)
+	v := LoadInt32(addr)
 	vlo := v & ((1 << 16) - 1)
 	vhi := v >> 16
 	if vlo != vhi {
@@ -883,12 +874,12 @@ func hammerStoreLoadInt32(t *testing.T, valp unsafe.Pointer) {
 	if vlo == 1e4 {
 		new = 0
 	}
-	StoreInt32(val, new)
+	StoreInt32(addr, new)
 }
 
-func hammerStoreLoadUint32(t *testing.T, valp unsafe.Pointer) {
-	val := (*uint32)(valp)
-	v := LoadUint32(val)
+func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*uint32)(paddr)
+	v := LoadUint32(addr)
 	vlo := v & ((1 << 16) - 1)
 	vhi := v >> 16
 	if vlo != vhi {
@@ -898,38 +889,38 @@ func hammerStoreLoadUint32(t *testing.T, valp unsafe.Pointer) {
 	if vlo == 1e4 {
 		new = 0
 	}
-	StoreUint32(val, new)
+	StoreUint32(addr, new)
 }
 
-func hammerStoreLoadInt64(t *testing.T, valp unsafe.Pointer) {
-	val := (*int64)(valp)
-	v := LoadInt64(val)
+func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*int64)(paddr)
+	v := LoadInt64(addr)
 	vlo := v & ((1 << 32) - 1)
 	vhi := v >> 32
 	if vlo != vhi {
 		t.Fatalf("Int64: %#x != %#x", vlo, vhi)
 	}
 	new := v + 1 + 1<<32
-	StoreInt64(val, new)
+	StoreInt64(addr, new)
 }
 
-func hammerStoreLoadUint64(t *testing.T, valp unsafe.Pointer) {
-	val := (*uint64)(valp)
-	v := LoadUint64(val)
+func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*uint64)(paddr)
+	v := LoadUint64(addr)
 	vlo := v & ((1 << 32) - 1)
 	vhi := v >> 32
 	if vlo != vhi {
 		t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
 	}
 	new := v + 1 + 1<<32
-	StoreUint64(val, new)
+	StoreUint64(addr, new)
 }
 
-func hammerStoreLoadUintptr(t *testing.T, valp unsafe.Pointer) {
-	val := (*uintptr)(valp)
+func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*uintptr)(paddr)
 	var test64 uint64 = 1 << 50
 	arch32 := uintptr(test64) == 0
-	v := LoadUintptr(val)
+	v := LoadUintptr(addr)
 	new := v
 	if arch32 {
 		vlo := v & ((1 << 16) - 1)
@@ -950,14 +941,14 @@ func hammerStoreLoadUintptr(t *testing.T, valp unsafe.Pointer) {
 		inc := uint64(1 + 1<<32)
 		new = v + uintptr(inc)
 	}
-	StoreUintptr(val, new)
+	StoreUintptr(addr, new)
 }
 
-func hammerStoreLoadPointer(t *testing.T, valp unsafe.Pointer) {
-	val := (*unsafe.Pointer)(valp)
+func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
+	addr := (*unsafe.Pointer)(paddr)
 	var test64 uint64 = 1 << 50
 	arch32 := uintptr(test64) == 0
-	v := uintptr(LoadPointer(val))
+	v := uintptr(LoadPointer(addr))
 	new := v
 	if arch32 {
 		vlo := v & ((1 << 16) - 1)
@@ -978,7 +969,7 @@ func hammerStoreLoadPointer(t *testing.T, valp unsafe.Pointer) {
 		inc := uint64(1 + 1<<32)
 		new = v + uintptr(inc)
 	}
-	StorePointer(val, unsafe.Pointer(new))
+	StorePointer(addr, unsafe.Pointer(new))
 }
 
 func TestHammerStoreLoad(t *testing.T) {
@@ -1013,8 +1004,7 @@ func TestHammerStoreLoad(t *testing.T) {
 
 func TestStoreLoadSeqCst32(t *testing.T) {
 	if runtime.NumCPU() == 1 {
-		t.Logf("Skipping test on %v processor machine", runtime.NumCPU())
-		return
+		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
 	}
 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
 	N := int32(1e3)
@@ -1054,12 +1044,10 @@ func TestStoreLoadSeqCst32(t *testing.T) {
 
 func TestStoreLoadSeqCst64(t *testing.T) {
 	if runtime.NumCPU() == 1 {
-		t.Logf("Skipping test on %v processor machine", runtime.NumCPU())
-		return
+		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
 	}
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
 	N := int64(1e3)
@@ -1099,8 +1087,7 @@ func TestStoreLoadSeqCst64(t *testing.T) {
 
 func TestStoreLoadRelAcq32(t *testing.T) {
 	if runtime.NumCPU() == 1 {
-		t.Logf("Skipping test on %v processor machine", runtime.NumCPU())
-		return
+		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
 	}
 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
 	N := int32(1e3)
@@ -1132,7 +1119,7 @@ func TestStoreLoadRelAcq32(t *testing.T) {
 					d1 := X.data1
 					d2 := X.data2
 					if d1 != i || d2 != float32(i) {
-						t.Fatalf("incorrect data: %d/%d (%d)", d1, d2, i)
+						t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
 					}
 				}
 			}
@@ -1145,12 +1132,10 @@ func TestStoreLoadRelAcq32(t *testing.T) {
 
 func TestStoreLoadRelAcq64(t *testing.T) {
 	if runtime.NumCPU() == 1 {
-		t.Logf("Skipping test on %v processor machine", runtime.NumCPU())
-		return
+		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
 	}
 	if test64err != nil {
-		t.Logf("Skipping 64-bit tests: %v", test64err)
-		return
+		t.Skipf("Skipping 64-bit tests: %v", test64err)
 	}
 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
 	N := int64(1e3)
@@ -1182,7 +1167,7 @@ func TestStoreLoadRelAcq64(t *testing.T) {
 					d1 := X.data1
 					d2 := X.data2
 					if d1 != i || d2 != float64(i) {
-						t.Fatalf("incorrect data: %d/%d (%d)", d1, d2, i)
+						t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
 					}
 				}
 			}
diff --git a/src/pkg/sync/atomic/doc.go b/src/pkg/sync/atomic/doc.go
index ecb4808..27a12c9 100644
--- a/src/pkg/sync/atomic/doc.go
+++ b/src/pkg/sync/atomic/doc.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 !race
+
 // Package atomic provides low-level atomic memory primitives
 // useful for implementing synchronization algorithms.
 //
@@ -14,54 +16,67 @@
 // The compare-and-swap operation, implemented by the CompareAndSwapT
 // functions, is the atomic equivalent of:
 //
-//	if *val == old {
-//		*val = new
+//	if *addr == old {
+//		*addr = new
 //		return true
 //	}
 //	return false
 //
+// The add operation, implemented by the AddT functions, is the atomic
+// equivalent of:
+//
+//	*addr += delta
+//	return *addr
+//
+// The load and store operations, implemented by the LoadT and StoreT
+// functions, are the atomic equivalents of "return *addr" and
+// "*addr = val".
+//
 package atomic
 
 import (
 	"unsafe"
 )
 
-// BUG(rsc): On ARM, the 64-bit functions use instructions unavailable before ARM 11.
+// BUG(rsc): On x86-32, the 64-bit functions use instructions unavailable before the Pentium MMX.
 //
-// On x86-32, the 64-bit functions use instructions unavailable before the Pentium MMX.
+// On both ARM and x86-32, it is the caller's responsibility to arrange for 64-bit
+// alignment of 64-bit words accessed atomically. The first word in a global
+// variable or in an allocated struct or slice can be relied upon to be
+// 64-bit aligned.
 
 // CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value.
-func CompareAndSwapInt32(val *int32, old, new int32) (swapped bool)
+func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
 
 // CompareAndSwapInt64 executes the compare-and-swap operation for an int64 value.
-func CompareAndSwapInt64(val *int64, old, new int64) (swapped bool)
+func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
 
 // CompareAndSwapUint32 executes the compare-and-swap operation for a uint32 value.
-func CompareAndSwapUint32(val *uint32, old, new uint32) (swapped bool)
+func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)
 
 // CompareAndSwapUint64 executes the compare-and-swap operation for a uint64 value.
-func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool)
+func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool)
 
 // CompareAndSwapUintptr executes the compare-and-swap operation for a uintptr value.
-func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool)
+func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool)
 
 // CompareAndSwapPointer executes the compare-and-swap operation for a unsafe.Pointer value.
-func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
+func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
 
-// AddInt32 atomically adds delta to *val and returns the new value.
-func AddInt32(val *int32, delta int32) (new int32)
+// AddInt32 atomically adds delta to *addr and returns the new value.
+func AddInt32(addr *int32, delta int32) (new int32)
 
-// AddUint32 atomically adds delta to *val and returns the new value.
-func AddUint32(val *uint32, delta uint32) (new uint32)
+// AddUint32 atomically adds delta to *addr and returns the new value.
+func AddUint32(addr *uint32, delta uint32) (new uint32)
 
-// AddInt64 atomically adds delta to *val and returns the new value.
-func AddInt64(val *int64, delta int64) (new int64)
+// AddInt64 atomically adds delta to *addr and returns the new value.
+func AddInt64(addr *int64, delta int64) (new int64)
 
-// AddUint64 atomically adds delta to *val and returns the new value.
-func AddUint64(val *uint64, delta uint64) (new uint64)
+// AddUint64 atomically adds delta to *addr and returns the new value.
+func AddUint64(addr *uint64, delta uint64) (new uint64)
 
-// AddUintptr atomically adds delta to *val and returns the new value.
-func AddUintptr(val *uintptr, delta uintptr) (new uintptr)
+// AddUintptr atomically adds delta to *addr and returns the new value.
+func AddUintptr(addr *uintptr, delta uintptr) (new uintptr)
 
 // LoadInt32 atomically loads *addr.
 func LoadInt32(addr *int32) (val int32)
diff --git a/src/pkg/sync/atomic/race.go b/src/pkg/sync/atomic/race.go
new file mode 100644
index 0000000..242bbf2
--- /dev/null
+++ b/src/pkg/sync/atomic/race.go
@@ -0,0 +1,213 @@
+// 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 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) {
+	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) {
+	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) {
+	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) {
+	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) {
+	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) {
+	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) {
+	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) {
+	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) {
+	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) {
+	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) {
+	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) {
+	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) {
+	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) {
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	*addr = val
+	runtime.RaceRelease(unsafe.Pointer(addr))
+	runtime.RaceSemrelease(&mtx)
+}
+
+func StoreUintptr(addr *uintptr, val uintptr) {
+	runtime.RaceSemacquire(&mtx)
+	runtime.RaceRead(unsafe.Pointer(addr))
+	*addr = val
+	runtime.RaceRelease(unsafe.Pointer(addr))
+	runtime.RaceSemrelease(&mtx)
+}
diff --git a/src/pkg/sync/cond.go b/src/pkg/sync/cond.go
index 1fc3dea..491b985 100644
--- a/src/pkg/sync/cond.go
+++ b/src/pkg/sync/cond.go
@@ -56,6 +56,9 @@ func NewCond(l Locker) *Cond {
 //    c.L.Unlock()
 //
 func (c *Cond) Wait() {
+	if raceenabled {
+		raceDisable()
+	}
 	c.m.Lock()
 	if c.newSema == nil {
 		c.newSema = new(uint32)
@@ -63,6 +66,9 @@ func (c *Cond) Wait() {
 	s := c.newSema
 	c.newWaiters++
 	c.m.Unlock()
+	if raceenabled {
+		raceEnable()
+	}
 	c.L.Unlock()
 	runtime_Semacquire(s)
 	c.L.Lock()
@@ -73,6 +79,9 @@ func (c *Cond) Wait() {
 // It is allowed but not required for the caller to hold c.L
 // during the call.
 func (c *Cond) Signal() {
+	if raceenabled {
+		raceDisable()
+	}
 	c.m.Lock()
 	if c.oldWaiters == 0 && c.newWaiters > 0 {
 		// Retire old generation; rename new to old.
@@ -86,6 +95,9 @@ func (c *Cond) Signal() {
 		runtime_Semrelease(c.oldSema)
 	}
 	c.m.Unlock()
+	if raceenabled {
+		raceEnable()
+	}
 }
 
 // Broadcast wakes all goroutines waiting on c.
@@ -93,6 +105,9 @@ func (c *Cond) Signal() {
 // It is allowed but not required for the caller to hold c.L
 // during the call.
 func (c *Cond) Broadcast() {
+	if raceenabled {
+		raceDisable()
+	}
 	c.m.Lock()
 	// Wake both generations.
 	if c.oldWaiters > 0 {
@@ -109,4 +124,7 @@ func (c *Cond) Broadcast() {
 		c.newSema = nil
 	}
 	c.m.Unlock()
+	if raceenabled {
+		raceEnable()
+	}
 }
diff --git a/src/pkg/sync/example_test.go b/src/pkg/sync/example_test.go
index 1564924..031c87f 100644
--- a/src/pkg/sync/example_test.go
+++ b/src/pkg/sync/example_test.go
@@ -24,10 +24,10 @@ func ExampleWaitGroup() {
 		wg.Add(1)
 		// Launch a goroutine to fetch the URL.
 		go func(url string) {
+			// Decrement the counter when the goroutine completes.
+			defer wg.Done()
 			// Fetch the URL.
 			http.Get(url)
-			// Decrement the counter.
-			wg.Done()
 		}(url)
 	}
 	// Wait for all HTTP fetches to complete.
@@ -37,7 +37,7 @@ func ExampleWaitGroup() {
 func ExampleOnce() {
 	var once sync.Once
 	onceBody := func() {
-		fmt.Printf("Only once\n")
+		fmt.Println("Only once")
 	}
 	done := make(chan bool)
 	for i := 0; i < 10; i++ {
diff --git a/src/pkg/sync/mutex.go b/src/pkg/sync/mutex.go
index 9494cc3..b4629eb 100644
--- a/src/pkg/sync/mutex.go
+++ b/src/pkg/sync/mutex.go
@@ -10,7 +10,10 @@
 // Values containing the types defined in this package should not be copied.
 package sync
 
-import "sync/atomic"
+import (
+	"sync/atomic"
+	"unsafe"
+)
 
 // A Mutex is a mutual exclusion lock.
 // Mutexes can be created as part of other structures;
@@ -38,6 +41,9 @@ const (
 func (m *Mutex) Lock() {
 	// Fast path: grab unlocked mutex.
 	if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {
+		if raceenabled {
+			raceAcquire(unsafe.Pointer(m))
+		}
 		return
 	}
 
@@ -61,6 +67,10 @@ func (m *Mutex) Lock() {
 			awoke = true
 		}
 	}
+
+	if raceenabled {
+		raceAcquire(unsafe.Pointer(m))
+	}
 }
 
 // Unlock unlocks m.
@@ -70,6 +80,10 @@ func (m *Mutex) Lock() {
 // It is allowed for one goroutine to lock a Mutex and then
 // arrange for another goroutine to unlock it.
 func (m *Mutex) Unlock() {
+	if raceenabled {
+		raceRelease(unsafe.Pointer(m))
+	}
+
 	// Fast path: drop lock bit.
 	new := atomic.AddInt32(&m.state, -mutexLocked)
 	if (new+mutexLocked)&mutexLocked == 0 {
diff --git a/src/pkg/sync/once.go b/src/pkg/sync/once.go
index 04b714a..1699e86 100644
--- a/src/pkg/sync/once.go
+++ b/src/pkg/sync/once.go
@@ -38,6 +38,6 @@ func (o *Once) Do(f func()) {
 	defer o.m.Unlock()
 	if o.done == 0 {
 		f()
-		atomic.CompareAndSwapUint32(&o.done, 0, 1)
+		atomic.StoreUint32(&o.done, 1)
 	}
 }
diff --git a/src/pkg/sync/once_test.go b/src/pkg/sync/once_test.go
index 37075af..183069a 100644
--- a/src/pkg/sync/once_test.go
+++ b/src/pkg/sync/once_test.go
@@ -17,8 +17,11 @@ func (o *one) Increment() {
 	*o++
 }
 
-func run(once *Once, o *one, c chan bool) {
+func run(t *testing.T, once *Once, o *one, c chan bool) {
 	once.Do(func() { o.Increment() })
+	if v := *o; v != 1 {
+		t.Errorf("once failed inside run: %d is not 1", v)
+	}
 	c <- true
 }
 
@@ -28,14 +31,34 @@ func TestOnce(t *testing.T) {
 	c := make(chan bool)
 	const N = 10
 	for i := 0; i < N; i++ {
-		go run(once, o, c)
+		go run(t, once, o, c)
 	}
 	for i := 0; i < N; i++ {
 		<-c
 	}
 	if *o != 1 {
-		t.Errorf("once failed: %d is not 1", *o)
+		t.Errorf("once failed outside run: %d is not 1", *o)
+	}
+}
+
+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")
+			})
+		}()
 	}
+	once.Do(func() {})
+	once.Do(func() {
+		t.Fatalf("Once called twice")
+	})
 }
 
 func BenchmarkOnce(b *testing.B) {
diff --git a/src/pkg/sync/race.go b/src/pkg/sync/race.go
new file mode 100644
index 0000000..d9431af
--- /dev/null
+++ b/src/pkg/sync/race.go
@@ -0,0 +1,34 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build race
+
+package sync
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+const raceenabled = true
+
+func raceAcquire(addr unsafe.Pointer) {
+	runtime.RaceAcquire(addr)
+}
+
+func raceRelease(addr unsafe.Pointer) {
+	runtime.RaceRelease(addr)
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+	runtime.RaceReleaseMerge(addr)
+}
+
+func raceDisable() {
+	runtime.RaceDisable()
+}
+
+func raceEnable() {
+	runtime.RaceEnable()
+}
diff --git a/src/pkg/sync/race0.go b/src/pkg/sync/race0.go
new file mode 100644
index 0000000..bef14f9
--- /dev/null
+++ b/src/pkg/sync/race0.go
@@ -0,0 +1,28 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !race
+
+package sync
+
+import (
+	"unsafe"
+)
+
+const raceenabled = false
+
+func raceAcquire(addr unsafe.Pointer) {
+}
+
+func raceRelease(addr unsafe.Pointer) {
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+}
+
+func raceDisable() {
+}
+
+func raceEnable() {
+}
diff --git a/src/pkg/sync/rwmutex.go b/src/pkg/sync/rwmutex.go
index 782a9c3..b494c64 100644
--- a/src/pkg/sync/rwmutex.go
+++ b/src/pkg/sync/rwmutex.go
@@ -4,7 +4,10 @@
 
 package sync
 
-import "sync/atomic"
+import (
+	"sync/atomic"
+	"unsafe"
+)
 
 // An RWMutex is a reader/writer mutual exclusion lock.
 // The lock can be held by an arbitrary number of readers
@@ -24,10 +27,17 @@ const rwmutexMaxReaders = 1 << 30
 
 // RLock locks rw for reading.
 func (rw *RWMutex) RLock() {
+	if raceenabled {
+		raceDisable()
+	}
 	if atomic.AddInt32(&rw.readerCount, 1) < 0 {
 		// A writer is pending, wait for it.
 		runtime_Semacquire(&rw.readerSem)
 	}
+	if raceenabled {
+		raceEnable()
+		raceAcquire(unsafe.Pointer(&rw.readerSem))
+	}
 }
 
 // RUnlock undoes a single RLock call;
@@ -35,6 +45,10 @@ func (rw *RWMutex) RLock() {
 // It is a run-time error if rw is not locked for reading
 // on entry to RUnlock.
 func (rw *RWMutex) RUnlock() {
+	if raceenabled {
+		raceReleaseMerge(unsafe.Pointer(&rw.writerSem))
+		raceDisable()
+	}
 	if atomic.AddInt32(&rw.readerCount, -1) < 0 {
 		// A writer is pending.
 		if atomic.AddInt32(&rw.readerWait, -1) == 0 {
@@ -42,6 +56,9 @@ func (rw *RWMutex) RUnlock() {
 			runtime_Semrelease(&rw.writerSem)
 		}
 	}
+	if raceenabled {
+		raceEnable()
+	}
 }
 
 // Lock locks rw for writing.
@@ -51,6 +68,9 @@ func (rw *RWMutex) RUnlock() {
 // a blocked Lock call excludes new readers from acquiring
 // the lock.
 func (rw *RWMutex) Lock() {
+	if raceenabled {
+		raceDisable()
+	}
 	// First, resolve competition with other writers.
 	rw.w.Lock()
 	// Announce to readers there is a pending writer.
@@ -59,6 +79,11 @@ func (rw *RWMutex) Lock() {
 	if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
 		runtime_Semacquire(&rw.writerSem)
 	}
+	if raceenabled {
+		raceEnable()
+		raceAcquire(unsafe.Pointer(&rw.readerSem))
+		raceAcquire(unsafe.Pointer(&rw.writerSem))
+	}
 }
 
 // Unlock unlocks rw for writing.  It is a run-time error if rw is
@@ -68,6 +93,12 @@ func (rw *RWMutex) Lock() {
 // goroutine.  One goroutine may RLock (Lock) an RWMutex and then
 // arrange for another goroutine to RUnlock (Unlock) it.
 func (rw *RWMutex) Unlock() {
+	if raceenabled {
+		raceRelease(unsafe.Pointer(&rw.readerSem))
+		raceRelease(unsafe.Pointer(&rw.writerSem))
+		raceDisable()
+	}
+
 	// Announce to readers there is no active writer.
 	r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
 	// Unblock blocked readers, if any.
@@ -76,6 +107,9 @@ func (rw *RWMutex) Unlock() {
 	}
 	// Allow other writers to proceed.
 	rw.w.Unlock()
+	if raceenabled {
+		raceEnable()
+	}
 }
 
 // RLocker returns a Locker interface that implements
diff --git a/src/pkg/sync/waitgroup.go b/src/pkg/sync/waitgroup.go
index 0165b1f..1277f1c 100644
--- a/src/pkg/sync/waitgroup.go
+++ b/src/pkg/sync/waitgroup.go
@@ -4,7 +4,10 @@
 
 package sync
 
-import "sync/atomic"
+import (
+	"sync/atomic"
+	"unsafe"
+)
 
 // A WaitGroup waits for a collection of goroutines to finish.
 // The main goroutine calls Add to set the number of
@@ -31,11 +34,22 @@ type WaitGroup struct {
 // G3: Wait() // G1 still hasn't run, G3 finds sema == 1, unblocked! Bug.
 
 // Add adds delta, which may be negative, to the WaitGroup counter.
-// If the counter becomes zero, all goroutines blocked on Wait() are released.
+// 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.
 func (wg *WaitGroup) Add(delta int) {
+	if raceenabled {
+		raceReleaseMerge(unsafe.Pointer(wg))
+		raceDisable()
+		defer raceEnable()
+	}
 	v := atomic.AddInt32(&wg.counter, int32(delta))
 	if v < 0 {
-		panic("sync: negative WaitGroup count")
+		panic("sync: negative WaitGroup counter")
 	}
 	if v > 0 || atomic.LoadInt32(&wg.waiters) == 0 {
 		return
@@ -56,7 +70,14 @@ func (wg *WaitGroup) Done() {
 
 // Wait blocks until the WaitGroup counter is zero.
 func (wg *WaitGroup) Wait() {
+	if raceenabled {
+		raceDisable()
+	}
 	if atomic.LoadInt32(&wg.counter) == 0 {
+		if raceenabled {
+			raceEnable()
+			raceAcquire(unsafe.Pointer(wg))
+		}
 		return
 	}
 	wg.m.Lock()
@@ -67,7 +88,15 @@ func (wg *WaitGroup) Wait() {
 	// to avoid missing an Add.
 	if atomic.LoadInt32(&wg.counter) == 0 {
 		atomic.AddInt32(&wg.waiters, -1)
+		if raceenabled {
+			raceEnable()
+			raceAcquire(unsafe.Pointer(wg))
+			raceDisable()
+		}
 		wg.m.Unlock()
+		if raceenabled {
+			raceEnable()
+		}
 		return
 	}
 	if wg.sema == nil {
@@ -76,4 +105,8 @@ func (wg *WaitGroup) Wait() {
 	s := wg.sema
 	wg.m.Unlock()
 	runtime_Semacquire(s)
+	if raceenabled {
+		raceEnable()
+		raceAcquire(unsafe.Pointer(wg))
+	}
 }
diff --git a/src/pkg/sync/waitgroup_test.go b/src/pkg/sync/waitgroup_test.go
index 34430fc..84c4cfc 100644
--- a/src/pkg/sync/waitgroup_test.go
+++ b/src/pkg/sync/waitgroup_test.go
@@ -50,7 +50,7 @@ func TestWaitGroup(t *testing.T) {
 func TestWaitGroupMisuse(t *testing.T) {
 	defer func() {
 		err := recover()
-		if err != "sync: negative WaitGroup count" {
+		if err != "sync: negative WaitGroup counter" {
 			t.Fatalf("Unexpected panic: %#v", err)
 		}
 	}()
diff --git a/src/pkg/syscall/asm_freebsd_amd64.s b/src/pkg/syscall/asm_freebsd_amd64.s
index 022db69..fbf9178 100644
--- a/src/pkg/syscall/asm_freebsd_amd64.s
+++ b/src/pkg/syscall/asm_freebsd_amd64.s
@@ -8,6 +8,7 @@
 
 // func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
 // func Syscall6(trap int64, a1, a2, a3, a4, a5, a6 int64) (r1, r2, err int64);
+// func Syscall9(trap int64, a1, a2, a3, a4, a5, a6, a7, a8, a9 int64) (r1, r2, err int64)
 // Trap # in AX, args in DI SI DX, return in AX DX
 
 TEXT	·Syscall(SB),7,$0
@@ -56,6 +57,39 @@ ok6:
 	CALL	runtime·exitsyscall(SB)
 	RET
 
+TEXT	·Syscall9(SB),7,$0
+	CALL	runtime·entersyscall(SB)
+	MOVQ	8(SP), AX
+	MOVQ	16(SP), DI
+	MOVQ	24(SP), SI
+	MOVQ	32(SP), DX
+	MOVQ	40(SP),	R10
+	MOVQ	48(SP), R8
+	MOVQ	56(SP), R9
+
+	// shift around the last three arguments so they're at the
+	// top of the stack when the syscall is called.
+	MOVQ	64(SP), R11 // arg 7
+	MOVQ	R11, 8(SP)
+	MOVQ	72(SP), R11 // arg 8
+	MOVQ	R11, 16(SP)
+	MOVQ	80(SP), R11 // arg 9
+	MOVQ	R11, 24(SP)
+
+	SYSCALL
+	JCC	ok9
+	MOVQ	$-1, 88(SP)	// r1
+	MOVQ	$0, 96(SP)	// r2
+	MOVQ	AX, 104(SP)  // errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+ok9:
+	MOVQ	AX, 88(SP)	// r1
+	MOVQ	DX, 96(SP)	// r2
+	MOVQ	$0, 104(SP)	// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+
 TEXT ·RawSyscall(SB),7,$0
 	MOVQ	16(SP), DI
 	MOVQ	24(SP), SI
diff --git a/src/pkg/syscall/asm_freebsd_arm.s b/src/pkg/syscall/asm_freebsd_arm.s
new file mode 100644
index 0000000..ab08ab5
--- /dev/null
+++ b/src/pkg/syscall/asm_freebsd_arm.s
@@ -0,0 +1,124 @@
+// 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.
+
+//
+// System call support for ARM, FreeBSD
+//
+
+// func Syscall(trap int32, a1, a2, a3 int32) (r1, r2, err int32);
+// func Syscall6(trap int32, a1, a2, a3, a4, a5, a6 int32) (r1, r2, err int32);
+// func Syscall9(trap int32, a1, a2, a3, a4, a5, a6, a7, a8, a9 int64) (r1, r2, err int32)
+
+TEXT	·Syscall(SB),7,$0
+	BL runtime·entersyscall(SB)
+	MOVW 0(FP), R0 // sigcall num
+	MOVW 4(FP), R1 // a1
+	MOVW 8(FP), R2 // a2
+	MOVW 12(FP), R3 // a3
+	SWI $0 // syscall
+	MOVW $0, R2
+	BCS error
+	MOVW R0, 16(FP) // r1
+	MOVW R1, 20(FP) // r2
+	MOVW R2, 24(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+error:
+	MOVW $-1, R3
+	MOVW R3, 16(FP) // r1
+	MOVW R2, 20(FP) // r2
+	MOVW R0, 24(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+
+TEXT	·Syscall6(SB),7,$0
+	BL runtime·entersyscall(SB)
+	MOVW 0(FP), R0 // sigcall num
+	MOVW 4(FP), R1 // a1
+	MOVW 8(FP), R2 // a2
+	MOVW 12(FP), R3 // a3
+	MOVW R13, R4
+	MOVW $16(FP), R13 // a4 to a6 are passed on stack
+	SWI $0 // syscall
+	MOVW R4, R13
+	MOVW $0, R2
+	BCS error6
+	MOVW R0, 28(FP) // r1
+	MOVW R1, 32(FP) // r2
+	MOVW R2, 36(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+error6:
+	MOVW $-1, R3
+	MOVW R3, 28(FP) // r1
+	MOVW R2, 32(FP) // r2
+	MOVW R0, 36(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+
+TEXT	·Syscall9(SB),7,$0
+	BL runtime·entersyscall(SB)
+	MOVW 0(FP), R0 // sigcall num
+	MOVW 4(FP), R1 // a1
+	MOVW 8(FP), R2 // a2
+	MOVW 12(FP), R3 // a3
+	MOVW R13, R4
+	MOVW $16(FP), R13 // a4 to a9 are passed on stack
+	SWI $0 // syscall
+	MOVW R4, R13
+	MOVW $0, R2
+	BCS error9
+	MOVW R0, 40(FP) // r1
+	MOVW R1, 44(FP) // r2
+	MOVW R2, 48(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+error9:
+	MOVW $-1, R3
+	MOVW R3, 40(FP) // r1
+	MOVW R2, 44(FP) // r2
+	MOVW R0, 48(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+
+TEXT	·RawSyscall(SB),7,$0
+	MOVW 0(FP), R0 // sigcall num
+	MOVW 4(FP), R1 // a1
+	MOVW 8(FP), R2 // a2
+	MOVW 12(FP), R3 // a3
+	SWI $0 // syscall
+	MOVW $0, R2
+	BCS errorr
+	MOVW R0, 16(FP) // r1
+	MOVW R1, 20(FP) // r2
+	MOVW R2, 24(FP) // err
+	RET
+errorr:
+	MOVW $-1, R3
+	MOVW R3, 16(FP) // r1
+	MOVW R2, 20(FP) // r2
+	MOVW R0, 24(FP) // err
+	RET
+
+TEXT	·RawSyscall6(SB),7,$0
+	MOVW 0(FP), R0 // sigcall num
+	MOVW 4(FP), R1 // a1
+	MOVW 8(FP), R2 // a2
+	MOVW 12(FP), R3 // a3
+	MOVW R13, R4
+	MOVW $16(FP), R13 // a4 to a9 are passed on stack
+	SWI $0 // syscall
+	MOVW R4, R13
+	MOVW $0, R2
+	BCS errorr6
+	MOVW R0, 28(FP) // r1
+	MOVW R1, 32(FP) // r2
+	MOVW R2, 36(FP) // err
+	RET
+errorr6:
+	MOVW $-1, R3
+	MOVW R3, 28(FP) // r1
+	MOVW R2, 32(FP) // r2
+	MOVW R0, 36(FP) // err
+	RET
diff --git a/src/pkg/syscall/asm_linux_amd64.s b/src/pkg/syscall/asm_linux_amd64.s
index fdc233c..1a1fdb0 100644
--- a/src/pkg/syscall/asm_linux_amd64.s
+++ b/src/pkg/syscall/asm_linux_amd64.s
@@ -108,7 +108,7 @@ ok2:
 TEXT ·Gettimeofday(SB),7,$0
 	MOVQ	8(SP), DI
 	MOVQ	$0, SI
-	MOVQ	$0xffffffffff600000, AX
+	MOVQ	runtime·__vdso_gettimeofday_sym(SB), AX
 	CALL	AX
 
 	CMPQ	AX, $0xfffffffffffff001
@@ -122,7 +122,7 @@ ok7:
 
 TEXT ·Time(SB),7,$0
 	MOVQ	8(SP), DI
-	MOVQ	$0xffffffffff600400, AX
+	MOVQ	runtime·__vdso_time_sym(SB), AX
 	CALL	AX
 	MOVQ	AX, 16(SP)  // tt
 	MOVQ	$0, 24(SP)  // errno
diff --git a/src/pkg/syscall/asm_netbsd_arm.s b/src/pkg/syscall/asm_netbsd_arm.s
new file mode 100644
index 0000000..e42da33
--- /dev/null
+++ b/src/pkg/syscall/asm_netbsd_arm.s
@@ -0,0 +1,124 @@
+// 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.
+
+//
+// System call support for ARM, NetBSD
+//
+
+// func Syscall(trap int32, a1, a2, a3 int32) (r1, r2, err int32);
+// func Syscall6(trap int32, a1, a2, a3, a4, a5, a6 int32) (r1, r2, err int32);
+// func Syscall9(trap int32, a1, a2, a3, a4, a5, a6, a7, a8, a9 int64) (r1, r2, err int32)
+
+TEXT	·Syscall(SB),7,$0
+	BL runtime·entersyscall(SB)
+	MOVW 0(FP), R0 // sigcall num
+	MOVW 4(FP), R1 // a1
+	MOVW 8(FP), R2 // a2
+	MOVW 12(FP), R3 // a3
+	SWI $0 // syscall
+	MOVW $0, R2
+	BCS error
+	MOVW R0, 16(FP) // r1
+	MOVW R1, 20(FP) // r2
+	MOVW R2, 24(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+error:
+	MOVW $-1, R3
+	MOVW R3, 16(FP) // r1
+	MOVW R2, 20(FP) // r2
+	MOVW R0, 24(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+
+TEXT	·Syscall6(SB),7,$0
+	BL runtime·entersyscall(SB)
+	MOVW 0(FP), R0 // sigcall num
+	MOVW 4(FP), R1 // a1
+	MOVW 8(FP), R2 // a2
+	MOVW 12(FP), R3 // a3
+	MOVW R13, R4
+	MOVW $16(FP), R13 // a4 to a6 are passed on stack
+	SWI $0 // syscall
+	MOVW R4, R13
+	MOVW $0, R2
+	BCS error6
+	MOVW R0, 28(FP) // r1
+	MOVW R1, 32(FP) // r2
+	MOVW R2, 36(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+error6:
+	MOVW $-1, R3
+	MOVW R3, 28(FP) // r1
+	MOVW R2, 32(FP) // r2
+	MOVW R0, 36(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+
+TEXT	·Syscall9(SB),7,$0
+	BL runtime·entersyscall(SB)
+	MOVW 0(FP), R0 // sigcall num
+	MOVW 4(FP), R1 // a1
+	MOVW 8(FP), R2 // a2
+	MOVW 12(FP), R3 // a3
+	MOVW R13, R4
+	MOVW $16(FP), R13 // a4 to a9 are passed on stack
+	SWI $0 // syscall
+	MOVW R4, R13
+	MOVW $0, R2
+	BCS error9
+	MOVW R0, 40(FP) // r1
+	MOVW R1, 44(FP) // r2
+	MOVW R2, 48(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+error9:
+	MOVW $-1, R3
+	MOVW R3, 40(FP) // r1
+	MOVW R2, 44(FP) // r2
+	MOVW R0, 48(FP) // err
+	BL runtime·exitsyscall(SB)
+	RET
+
+TEXT	·RawSyscall(SB),7,$0
+	MOVW 0(FP), R0 // sigcall num
+	MOVW 4(FP), R1 // a1
+	MOVW 8(FP), R2 // a2
+	MOVW 12(FP), R3 // a3
+	SWI $0 // syscall
+	MOVW $0, R2
+	BCS errorr
+	MOVW R0, 16(FP) // r1
+	MOVW R1, 20(FP) // r2
+	MOVW R2, 24(FP) // err
+	RET
+errorr:
+	MOVW $-1, R3
+	MOVW R3, 16(FP) // r1
+	MOVW R2, 20(FP) // r2
+	MOVW R0, 24(FP) // err
+	RET
+
+TEXT	·RawSyscall6(SB),7,$0
+	MOVW 0(FP), R0 // sigcall num
+	MOVW 4(FP), R1 // a1
+	MOVW 8(FP), R2 // a2
+	MOVW 12(FP), R3 // a3
+	MOVW R13, R4
+	MOVW $16(FP), R13 // a4 to a9 are passed on stack
+	SWI $0 // syscall
+	MOVW R4, R13
+	MOVW $0, R2
+	BCS errorr6
+	MOVW R0, 28(FP) // r1
+	MOVW R1, 32(FP) // r2
+	MOVW R2, 36(FP) // err
+	RET
+errorr6:
+	MOVW $-1, R3
+	MOVW R3, 28(FP) // r1
+	MOVW R2, 32(FP) // r2
+	MOVW R0, 36(FP) // err
+	RET
diff --git a/src/pkg/syscall/asm_plan9_386.s b/src/pkg/syscall/asm_plan9_386.s
index 86ebedc..2ba1376 100644
--- a/src/pkg/syscall/asm_plan9_386.s
+++ b/src/pkg/syscall/asm_plan9_386.s
@@ -149,3 +149,11 @@ copyresult6:
 	MOVSL
 	MOVSL
 	RET
+
+//func exit(code int)
+// Import runtime·exit for cleanly exiting.
+TEXT ·exit(SB),7,$4
+	MOVL	code+0(FP), AX
+	MOVL	AX, 0(SP)
+	CALL	runtime·exit(SB)
+	RET
diff --git a/src/pkg/syscall/asm_plan9_amd64.s b/src/pkg/syscall/asm_plan9_amd64.s
new file mode 100644
index 0000000..e363b74
--- /dev/null
+++ b/src/pkg/syscall/asm_plan9_amd64.s
@@ -0,0 +1,165 @@
+// 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 call support for Plan 9
+//
+
+//func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err string)
+//func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err string)
+//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),7,$0
+	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
+	LEAQ	8(SP), DI
+	CLD
+	MOVSQ
+	MOVSQ
+	MOVSQ
+	SYSCALL
+	MOVQ	AX, r1+40(SP)
+	MOVQ	$0, r2+48(SP)
+	CMPL	AX, $-1
+	JNE	ok3
+
+	SUBQ	$16, SP
+	CALL	syscall·errstr(SB)
+	MOVQ	SP, SI
+	ADDQ	$16, SP
+	JMP	copyresult3
+	
+ok3:
+	LEAQ	runtime·emptystring(SB), SI	
+	
+copyresult3:
+	LEAQ	err+56(SP), DI
+
+	CLD
+	MOVSQ
+	MOVSQ
+
+	CALL	runtime·exitsyscall(SB)
+	RET
+
+TEXT	·Syscall6(SB),7,$0
+	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
+	LEAQ		8(SP), DI
+	CLD
+	MOVSQ
+	MOVSQ
+	MOVSQ
+	MOVSQ
+	MOVSQ
+	MOVSQ
+	SYSCALL
+	MOVQ	AX, r1+64(SP)
+	MOVQ	$0, r2+72(SP)
+	CMPL	AX, $-1
+	JNE	ok4
+	
+	SUBQ	$16, SP
+	CALL	syscall·errstr(SB)
+	MOVQ	SP, SI
+	ADDQ	$16, SP
+	JMP	copyresult4
+	
+ok4:
+	LEAQ	runtime·emptystring(SB), SI
+	
+copyresult4:
+	LEAQ	err+80(SP), DI
+
+	CLD
+	MOVSQ
+	MOVSQ
+
+	CALL	runtime·exitsyscall(SB)
+	RET
+
+TEXT ·RawSyscall(SB),7,$0
+	MOVQ	$0x8000, AX	// for NxM
+	MOVQ	8(SP), BP	// syscall entry
+	// slide args down on top of system call number
+	LEAQ		16(SP), SI
+	LEAQ		8(SP), DI
+	CLD
+	MOVSQ
+	MOVSQ
+	MOVSQ
+	SYSCALL
+	MOVQ	AX, r1+40(SP)
+	MOVQ	AX, r2+48(SP)
+	MOVQ	AX, err+56(SP)
+	RET
+
+TEXT	·RawSyscall6(SB),7,$0
+	MOVQ	$0x8000, AX	// for NxM
+	MOVQ	8(SP), BP	// syscall entry
+	// slide args down on top of system call number
+	LEAQ		16(SP), SI
+	LEAQ		8(SP), DI
+	CLD
+	MOVSQ
+	MOVSQ
+	MOVSQ
+	MOVSQ
+	MOVSQ
+	MOVSQ
+	SYSCALL
+	MOVQ	AX, r1+64(SP)
+	MOVQ	AX, r2+72(SP)
+	MOVQ	AX, err+80(SP)		
+	RET
+
+#define SYS_SEEK 39	/* from zsysnum_plan9_amd64.go */
+
+//func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
+TEXT ·seek(SB),7,$0
+	LEAQ	newoffset+40(SP), AX
+	MOVQ	AX, placeholder+8(SP)
+	
+	MOVQ	$0x8000, AX	// for NxM
+	MOVQ	$SYS_SEEK, BP	// syscall entry
+	SYSCALL
+	
+	CMPL	AX, $-1
+	JNE	ok6
+	MOVQ	$-1, newoffset+40(SP)
+	
+	SUBQ	$16, SP
+	CALL	syscall·errstr(SB)
+	MOVQ	SP, SI
+	ADDQ	$16, SP	
+	JMP	copyresult6
+	
+ok6:
+	LEAQ	runtime·emptystring(SB), SI
+	
+copyresult6:
+	LEAQ	err+48(SP), DI
+
+	CLD
+	MOVSQ
+	MOVSQ
+	RET
+
+//func exit(code int)
+// Import runtime·exit for cleanly exiting.
+TEXT ·exit(SB),7,$8
+	MOVQ	code+0(FP), AX
+	MOVQ	AX, 0(SP)
+	CALL	runtime·exit(SB)
+	RET
diff --git a/src/pkg/syscall/asm_windows_386.s b/src/pkg/syscall/asm_windows_386.s
index a7b9564..8b52fa9 100644
--- a/src/pkg/syscall/asm_windows_386.s
+++ b/src/pkg/syscall/asm_windows_386.s
@@ -3,5 +3,5 @@
 // license that can be found in the LICENSE file.
 
 //
-// System calls for 386, Windows are implemented in ../runtime/windows/syscall.goc
+// 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
index 8b38710..5813404 100644
--- a/src/pkg/syscall/asm_windows_amd64.s
+++ b/src/pkg/syscall/asm_windows_amd64.s
@@ -3,5 +3,5 @@
 // license that can be found in the LICENSE file.
 
 //
-// System calls for amd64, Windows are implemented in ../runtime/windows/syscall.goc
+// System calls for amd64, Windows are implemented in ../runtime/syscall_windows.goc
 //
diff --git a/src/pkg/syscall/creds_test.go b/src/pkg/syscall/creds_test.go
new file mode 100644
index 0000000..b1894c6
--- /dev/null
+++ b/src/pkg/syscall/creds_test.go
@@ -0,0 +1,113 @@
+// 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 linux
+
+package syscall_test
+
+import (
+	"bytes"
+	"net"
+	"os"
+	"syscall"
+	"testing"
+)
+
+// TestSCMCredentials tests the sending and receiving of credentials
+// (PID, UID, GID) in an ancillary message between two UNIX
+// sockets. The SO_PASSCRED socket option is enabled on the sending
+// socket for this to work.
+func TestSCMCredentials(t *testing.T) {
+	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
+	if err != nil {
+		t.Fatalf("Socketpair: %v", err)
+	}
+	defer syscall.Close(fds[0])
+	defer syscall.Close(fds[1])
+
+	err = syscall.SetsockoptInt(fds[0], syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1)
+	if err != nil {
+		t.Fatalf("SetsockoptInt: %v", err)
+	}
+
+	srvFile := os.NewFile(uintptr(fds[0]), "server")
+	defer srvFile.Close()
+	srv, err := net.FileConn(srvFile)
+	if err != nil {
+		t.Errorf("FileConn: %v", err)
+		return
+	}
+	defer srv.Close()
+
+	cliFile := os.NewFile(uintptr(fds[1]), "client")
+	defer cliFile.Close()
+	cli, err := net.FileConn(cliFile)
+	if err != nil {
+		t.Errorf("FileConn: %v", err)
+		return
+	}
+	defer cli.Close()
+
+	var ucred syscall.Ucred
+	if os.Getuid() != 0 {
+		ucred.Pid = int32(os.Getpid())
+		ucred.Uid = 0
+		ucred.Gid = 0
+		oob := syscall.UnixCredentials(&ucred)
+		_, _, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+		if err.(*net.OpError).Err != syscall.EPERM {
+			t.Fatalf("WriteMsgUnix failed with %v, want EPERM", err)
+		}
+	}
+
+	ucred.Pid = int32(os.Getpid())
+	ucred.Uid = uint32(os.Getuid())
+	ucred.Gid = uint32(os.Getgid())
+	oob := syscall.UnixCredentials(&ucred)
+
+	// this is going to send a dummy byte
+	n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+	if err != nil {
+		t.Fatalf("WriteMsgUnix: %v", err)
+	}
+	if n != 0 {
+		t.Fatalf("WriteMsgUnix n = %d, want 0", n)
+	}
+	if oobn != len(oob) {
+		t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob))
+	}
+
+	oob2 := make([]byte, 10*len(oob))
+	n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2)
+	if err != nil {
+		t.Fatalf("ReadMsgUnix: %v", err)
+	}
+	if flags != 0 {
+		t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
+	}
+	if n != 1 {
+		t.Fatalf("ReadMsgUnix n = %d, want 1 (dummy byte)", n)
+	}
+	if oobn2 != oobn {
+		// without SO_PASSCRED set on the socket, ReadMsgUnix will
+		// return zero oob bytes
+		t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn)
+	}
+	oob2 = oob2[:oobn2]
+	if !bytes.Equal(oob, oob2) {
+		t.Fatal("ReadMsgUnix oob bytes don't match")
+	}
+
+	scm, err := syscall.ParseSocketControlMessage(oob2)
+	if err != nil {
+		t.Fatalf("ParseSocketControlMessage: %v", err)
+	}
+	newUcred, err := syscall.ParseUnixCredentials(&scm[0])
+	if err != nil {
+		t.Fatalf("ParseUnixCredentials: %v", err)
+	}
+	if *newUcred != ucred {
+		t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
+	}
+}
diff --git a/src/pkg/syscall/dir_plan9.go b/src/pkg/syscall/dir_plan9.go
new file mode 100644
index 0000000..b7ab4cd
--- /dev/null
+++ b/src/pkg/syscall/dir_plan9.go
@@ -0,0 +1,205 @@
+// 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.
+
+// Plan 9 directory marshalling. See intro(5).
+
+package syscall
+
+import "errors"
+
+var (
+	ErrShortStat = errors.New("stat buffer too short")
+	ErrBadStat   = errors.New("malformed stat buffer")
+)
+
+// A Qid represents a 9P server's unique identification for a file.
+type Qid struct {
+	Path uint64 // the file server's unique identification for the file
+	Vers uint32 // version number for given Path
+	Type uint8  // the type of the file (syscall.QTDIR for example)
+}
+
+// A Dir contains the metadata for a file.
+type Dir struct {
+	// system-modified data
+	Type uint16 // server type
+	Dev  uint32 // server subtype
+
+	// file data
+	Qid    Qid    // unique id from server
+	Mode   uint32 // permissions
+	Atime  uint32 // last read time
+	Mtime  uint32 // last write time
+	Length int64  // file length
+	Name   string // last element of path
+	Uid    string // owner name
+	Gid    string // group name
+	Muid   string // last modifier name
+}
+
+var nullDir = Dir{
+	Type: ^uint16(0),
+	Dev:  ^uint32(0),
+	Qid: Qid{
+		Path: ^uint64(0),
+		Vers: ^uint32(0),
+		Type: ^uint8(0),
+	},
+	Mode:   ^uint32(0),
+	Atime:  ^uint32(0),
+	Mtime:  ^uint32(0),
+	Length: ^int64(0),
+}
+
+// Null assigns special "don't touch" values to members of d to
+// avoid modifiying them during syscall.Wstat.
+func (d *Dir) Null() { *d = nullDir }
+
+// Marshal encodes a 9P stat message corresponding to d into b
+//
+// If there isn't enough space in b for a stat message, ErrShortStat is returned.
+func (d *Dir) Marshal(b []byte) (n int, err error) {
+	n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid)
+	if n > len(b) {
+		return n, ErrShortStat
+	}
+
+	b = pbit16(b, uint16(n)-2)
+	b = pbit16(b, d.Type)
+	b = pbit32(b, d.Dev)
+	b = pbit8(b, d.Qid.Type)
+	b = pbit32(b, d.Qid.Vers)
+	b = pbit64(b, d.Qid.Path)
+	b = pbit32(b, d.Mode)
+	b = pbit32(b, d.Atime)
+	b = pbit32(b, d.Mtime)
+	b = pbit64(b, uint64(d.Length))
+	b = pstring(b, d.Name)
+	b = pstring(b, d.Uid)
+	b = pstring(b, d.Gid)
+	b = pstring(b, d.Muid)
+
+	return n, nil
+}
+
+// UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
+//
+// If b is too small to hold a valid stat message, ErrShortStat is returned.
+//
+// If the stat message itself is invalid, ErrBadStat is returned.
+func UnmarshalDir(b []byte) (*Dir, error) {
+	if len(b) < STATFIXLEN {
+		return nil, ErrShortStat
+	}
+	size, buf := gbit16(b)
+	if len(b) != int(size)+2 {
+		return nil, ErrBadStat
+	}
+	b = buf
+
+	var d Dir
+	d.Type, b = gbit16(b)
+	d.Dev, b = gbit32(b)
+	d.Qid.Type, b = gbit8(b)
+	d.Qid.Vers, b = gbit32(b)
+	d.Qid.Path, b = gbit64(b)
+	d.Mode, b = gbit32(b)
+	d.Atime, b = gbit32(b)
+	d.Mtime, b = gbit32(b)
+
+	n, b := gbit64(b)
+	d.Length = int64(n)
+
+	var ok bool
+	if d.Name, b, ok = gstring(b); !ok {
+		return nil, ErrBadStat
+	}
+	if d.Uid, b, ok = gstring(b); !ok {
+		return nil, ErrBadStat
+	}
+	if d.Gid, b, ok = gstring(b); !ok {
+		return nil, ErrBadStat
+	}
+	if d.Muid, b, ok = gstring(b); !ok {
+		return nil, ErrBadStat
+	}
+
+	return &d, nil
+}
+
+// pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
+func pbit8(b []byte, v uint8) []byte {
+	b[0] = byte(v)
+	return b[1:]
+}
+
+// pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
+func pbit16(b []byte, v uint16) []byte {
+	b[0] = byte(v)
+	b[1] = byte(v >> 8)
+	return b[2:]
+}
+
+// pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
+func pbit32(b []byte, v uint32) []byte {
+	b[0] = byte(v)
+	b[1] = byte(v >> 8)
+	b[2] = byte(v >> 16)
+	b[3] = byte(v >> 24)
+	return b[4:]
+}
+
+// pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
+func pbit64(b []byte, v uint64) []byte {
+	b[0] = byte(v)
+	b[1] = byte(v >> 8)
+	b[2] = byte(v >> 16)
+	b[3] = byte(v >> 24)
+	b[4] = byte(v >> 32)
+	b[5] = byte(v >> 40)
+	b[6] = byte(v >> 48)
+	b[7] = byte(v >> 56)
+	return b[8:]
+}
+
+// pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
+// returning the remaining slice of b..
+func pstring(b []byte, s string) []byte {
+	b = pbit16(b, uint16(len(s)))
+	n := copy(b, s)
+	return b[n:]
+}
+
+// gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
+func gbit8(b []byte) (uint8, []byte) {
+	return uint8(b[0]), b[1:]
+}
+
+// gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
+func gbit16(b []byte) (uint16, []byte) {
+	return uint16(b[0]) | uint16(b[1])<<8, b[2:]
+}
+
+// gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
+func gbit32(b []byte) (uint32, []byte) {
+	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
+}
+
+// gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
+func gbit64(b []byte) (uint64, []byte) {
+	lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+	hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
+	return uint64(lo) | uint64(hi)<<32, b[8:]
+}
+
+// gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
+// It returns the string with the remaining slice of b and a boolean. If the length is
+// greater than the number of bytes in b, the boolean will be false.
+func gstring(b []byte) (string, []byte, bool) {
+	n, b := gbit16(b)
+	if int(n) > len(b) {
+		return "", b, false
+	}
+	return string(b[:n]), b[n:], true
+}
diff --git a/src/pkg/syscall/dll_windows.go b/src/pkg/syscall/dll_windows.go
index 2a45991..d29e992 100644
--- a/src/pkg/syscall/dll_windows.go
+++ b/src/pkg/syscall/dll_windows.go
@@ -6,6 +6,8 @@ package syscall
 
 import (
 	"sync"
+	"sync/atomic"
+	"unsafe"
 )
 
 // DLLError describes reasons for DLL load failures.
@@ -17,13 +19,13 @@ type DLLError struct {
 
 func (e *DLLError) Error() string { return e.Msg }
 
-// Implemented in ../runtime/windows/syscall.goc.
+// Implemented in ../runtime/syscall_windows.goc.
 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)
 func Syscall12(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2 uintptr, err Errno)
 func Syscall15(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2 uintptr, err Errno)
-func loadlibrary(filename *uint16) (handle, err Errno)
+func loadlibrary(filename *uint16) (handle uintptr, err Errno)
 func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err Errno)
 
 // A DLL implements access to a single DLL.
@@ -34,7 +36,11 @@ type DLL struct {
 
 // LoadDLL loads DLL file into memory.
 func LoadDLL(name string) (dll *DLL, err error) {
-	h, e := loadlibrary(StringToUTF16Ptr(name))
+	namep, err := UTF16PtrFromString(name)
+	if err != nil {
+		return nil, err
+	}
+	h, e := loadlibrary(namep)
 	if e != 0 {
 		return nil, &DLLError{
 			Err:     e,
@@ -61,7 +67,11 @@ func MustLoadDLL(name string) *DLL {
 // FindProc searches DLL d for procedure named name and returns *Proc
 // if found. It returns an error if search fails.
 func (d *DLL) FindProc(name string) (proc *Proc, err error) {
-	a, e := getprocaddress(uintptr(d.Handle), StringBytePtr(name))
+	namep, err := BytePtrFromString(name)
+	if err != nil {
+		return nil, err
+	}
+	a, e := getprocaddress(uintptr(d.Handle), namep)
 	if e != 0 {
 		return nil, &DLLError{
 			Err:     e,
@@ -104,8 +114,14 @@ func (p *Proc) Addr() uintptr {
 	return p.addr
 }
 
-// Call executes procedure p with arguments a.
-func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, err error) {
+// Call executes procedure p with arguments a. It will panic, if more then 15 arguments
+// are supplied.
+//
+// The returned error is always non-nil, constructed from the result of GetLastError.
+// Callers must inspect the primary return value to decide whether an error occurred
+// (according to the semantics of the specific function being called) before consulting
+// the error. The error will be guaranteed to contain syscall.Errno.
+func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
 	switch len(a) {
 	case 0:
 		return Syscall(p.Addr(), uintptr(len(a)), 0, 0, 0)
@@ -158,7 +174,9 @@ type LazyDLL struct {
 // Load loads DLL file d.Name into memory. It returns an error if fails.
 // Load will not try to load DLL, if it is already loaded into memory.
 func (d *LazyDLL) Load() error {
-	if d.dll == nil {
+	// Non-racy version of:
+	// if d.dll == nil {
+	if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll))) == nil {
 		d.mu.Lock()
 		defer d.mu.Unlock()
 		if d.dll == nil {
@@ -166,7 +184,9 @@ func (d *LazyDLL) Load() error {
 			if e != nil {
 				return e
 			}
-			d.dll = dll
+			// Non-racy version of:
+			// d.dll = dll
+			atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)), unsafe.Pointer(dll))
 		}
 	}
 	return nil
@@ -209,7 +229,9 @@ type LazyProc struct {
 // an error if search fails. Find will not search procedure,
 // if it is already found and loaded into memory.
 func (p *LazyProc) Find() error {
-	if p.proc == nil {
+	// Non-racy version of:
+	// if p.proc == nil {
+	if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
 		p.mu.Lock()
 		defer p.mu.Unlock()
 		if p.proc == nil {
@@ -221,7 +243,9 @@ func (p *LazyProc) Find() error {
 			if e != nil {
 				return e
 			}
-			p.proc = proc
+			// Non-racy version of:
+			// p.proc = proc
+			atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
 		}
 	}
 	return nil
@@ -242,8 +266,14 @@ func (p *LazyProc) Addr() uintptr {
 	return p.proc.Addr()
 }
 
-// Call executes procedure p with arguments a.
-func (p *LazyProc) Call(a ...uintptr) (r1, r2 uintptr, err error) {
+// Call executes procedure p with arguments a. It will panic, if more then 15 arguments
+// are supplied.
+//
+// The returned error is always non-nil, constructed from the result of GetLastError.
+// Callers must inspect the primary return value to decide whether an error occurred
+// (according to the semantics of the specific function being called) before consulting
+// the error. The error will be guaranteed to contain syscall.Errno.
+func (p *LazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
 	p.mustFind()
 	return p.proc.Call(a...)
 }
diff --git a/src/pkg/syscall/env_plan9.go b/src/pkg/syscall/env_plan9.go
index 2848d9b..9587ab5 100644
--- a/src/pkg/syscall/env_plan9.go
+++ b/src/pkg/syscall/env_plan9.go
@@ -12,14 +12,20 @@ import (
 )
 
 var (
-	// envOnce guards initialization by copyenv, which populates env.
+	// envOnce guards copyenv, which populates env.
 	envOnce sync.Once
 
-	// envLock guards env.
+	// envLock guards env and envs.
 	envLock sync.RWMutex
 
 	// env maps from an environment variable to its value.
-	env map[string]string
+	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")
 )
 
 func readenv(key string) (string, error) {
@@ -47,12 +53,18 @@ func writeenv(key, value string) error {
 		return err
 	}
 	defer Close(fd)
-	_, err = Write(fd, []byte(value))
-	return err
+	b := []byte(value)
+	n, err := Write(fd, b)
+	if err != nil {
+		return err
+	}
+	if n != len(b) {
+		return errShortWrite
+	}
+	return nil
 }
 
 func copyenv() {
-	env = make(map[string]string)
 	fd, err := Open("/env", O_RDONLY)
 	if err != nil {
 		return
@@ -62,17 +74,20 @@ func copyenv() {
 	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) {
-	envOnce.Do(copyenv)
 	if len(key) == 0 {
 		return "", false
 	}
@@ -80,17 +95,21 @@ func Getenv(key string) (value string, found bool) {
 	envLock.RLock()
 	defer envLock.RUnlock()
 
-	v, ok := env[key]
-	if !ok {
+	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
 }
 
 func Setenv(key, value string) error {
-	envOnce.Do(copyenv)
 	if len(key) == 0 {
-		return errors.New("zero length key")
+		return errZeroLengthKey
 	}
 
 	envLock.Lock()
@@ -101,28 +120,23 @@ func Setenv(key, value string) error {
 		return err
 	}
 	env[key] = value
+	envs = append(envs, key+"="+value)
 	return nil
 }
 
 func Clearenv() {
-	envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
-
 	envLock.Lock()
 	defer envLock.Unlock()
 
 	env = make(map[string]string)
+	envs = []string{}
 	RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
 }
 
 func Environ() []string {
-	envOnce.Do(copyenv)
 	envLock.RLock()
 	defer envLock.RUnlock()
-	a := make([]string, len(env))
-	i := 0
-	for k, v := range env {
-		a[i] = k + "=" + v
-		i++
-	}
-	return a
+
+	envOnce.Do(copyenv)
+	return append([]string(nil), envs...)
 }
diff --git a/src/pkg/syscall/env_unix.go b/src/pkg/syscall/env_unix.go
index 8b1868c..8573d79 100644
--- a/src/pkg/syscall/env_unix.go
+++ b/src/pkg/syscall/env_unix.go
@@ -71,6 +71,16 @@ func Setenv(key, value string) error {
 	if len(key) == 0 {
 		return EINVAL
 	}
+	for i := 0; i < len(key); i++ {
+		if key[i] == '=' || key[i] == 0 {
+			return EINVAL
+		}
+	}
+	for i := 0; i < len(value); i++ {
+		if value[i] == 0 {
+			return EINVAL
+		}
+	}
 
 	envLock.Lock()
 	defer envLock.Unlock()
diff --git a/src/pkg/syscall/env_windows.go b/src/pkg/syscall/env_windows.go
index 8308f10..39bd502 100644
--- a/src/pkg/syscall/env_windows.go
+++ b/src/pkg/syscall/env_windows.go
@@ -12,14 +12,18 @@ import (
 )
 
 func Getenv(key string) (value string, found bool) {
+	keyp, err := UTF16PtrFromString(key)
+	if err != nil {
+		return "", false
+	}
 	b := make([]uint16, 100)
-	n, e := GetEnvironmentVariable(StringToUTF16Ptr(key), &b[0], uint32(len(b)))
+	n, e := GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
 	if n == 0 && e == ERROR_ENVVAR_NOT_FOUND {
 		return "", false
 	}
 	if n > uint32(len(b)) {
 		b = make([]uint16, n)
-		n, e = GetEnvironmentVariable(StringToUTF16Ptr(key), &b[0], uint32(len(b)))
+		n, e = GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
 		if n > uint32(len(b)) {
 			n = 0
 		}
@@ -32,10 +36,18 @@ func Getenv(key string) (value string, found bool) {
 
 func Setenv(key, value string) error {
 	var v *uint16
+	var err error
 	if len(value) > 0 {
-		v = StringToUTF16Ptr(value)
+		v, err = UTF16PtrFromString(value)
+		if err != nil {
+			return err
+		}
+	}
+	keyp, err := UTF16PtrFromString(key)
+	if err != nil {
+		return err
 	}
-	e := SetEnvironmentVariable(StringToUTF16Ptr(key), v)
+	e := SetEnvironmentVariable(keyp, v)
 	if e != nil {
 		return e
 	}
diff --git a/src/pkg/syscall/exec_bsd.go b/src/pkg/syscall/exec_bsd.go
index 9c3af5e..318cbc0 100644
--- a/src/pkg/syscall/exec_bsd.go
+++ b/src/pkg/syscall/exec_bsd.go
@@ -221,3 +221,17 @@ childerror:
 	// and this shuts up the compiler.
 	panic("unreached")
 }
+
+// Try to open a pipe with O_CLOEXEC set on both file descriptors.
+func forkExecPipe(p []int) error {
+	err := Pipe(p)
+	if err != nil {
+		return err
+	}
+	_, err = fcntl(p[0], F_SETFD, FD_CLOEXEC)
+	if err != nil {
+		return err
+	}
+	_, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
+	return err
+}
diff --git a/src/pkg/syscall/exec_linux.go b/src/pkg/syscall/exec_linux.go
index 70f3e62..a8dc672 100644
--- a/src/pkg/syscall/exec_linux.go
+++ b/src/pkg/syscall/exec_linux.go
@@ -16,8 +16,9 @@ type SysProcAttr struct {
 	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 0
+	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)
 }
 
@@ -206,9 +207,9 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
 		}
 	}
 
-	// Make fd 0 the tty
-	if sys.Setctty {
-		_, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCSCTTY), 0)
+	// Set the controlling TTY to Ctty
+	if sys.Setctty && sys.Ctty >= 0 {
+		_, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0)
 		if err1 != 0 {
 			goto childerror
 		}
@@ -232,3 +233,20 @@ childerror:
 	// and this shuts up the compiler.
 	panic("unreached")
 }
+
+// Try to open a pipe with O_CLOEXEC set on both file descriptors.
+func forkExecPipe(p []int) (err error) {
+	err = Pipe2(p, O_CLOEXEC)
+	// pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so it
+	// might not be implemented.
+	if err == ENOSYS {
+		if err = Pipe(p); err != nil {
+			return
+		}
+		if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != nil {
+			return
+		}
+		_, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
+	}
+	return
+}
diff --git a/src/pkg/syscall/exec_plan9.go b/src/pkg/syscall/exec_plan9.go
index 7e4e180..ebd57f3 100644
--- a/src/pkg/syscall/exec_plan9.go
+++ b/src/pkg/syscall/exec_plan9.go
@@ -7,6 +7,7 @@
 package syscall
 
 import (
+	"runtime"
 	"sync"
 	"unsafe"
 )
@@ -60,8 +61,9 @@ import (
 
 var ForkLock sync.RWMutex
 
-// Convert array of string to array
-// of NUL-terminated byte pointer.
+// StringSlicePtr is deprecated. Use SlicePtrFromStrings instead.
+// If any string contains a NUL byte this function panics instead
+// of returning an error.
 func StringSlicePtr(ss []string) []*byte {
 	bb := make([]*byte, len(ss)+1)
 	for i := 0; i < len(ss); i++ {
@@ -71,81 +73,81 @@ func StringSlicePtr(ss []string) []*byte {
 	return bb
 }
 
-// gbit16 reads a 16-bit numeric value from a 9P protocol message stored in b,
-// returning the value and the remaining slice of b.
-func gbit16(b []byte) (uint16, []byte) {
-	return uint16(b[0]) | uint16(b[1])<<8, b[2:]
-}
-
-// gstring reads a string from a 9P protocol message stored in b,
-// returning the value as a Go string and the remaining slice of b.
-func gstring(b []byte) (string, []byte) {
-	n, b := gbit16(b)
-	return string(b[0:n]), b[n:]
+// SlicePtrFromStrings converts a slice of strings to a slice of
+// pointers to NUL-terminated byte slices. If any string contains
+// a NUL byte, it returns (nil, EINVAL).
+func SlicePtrFromStrings(ss []string) ([]*byte, error) {
+	var err error
+	bb := make([]*byte, len(ss)+1)
+	for i := 0; i < len(ss); i++ {
+		bb[i], err = BytePtrFromString(ss[i])
+		if err != nil {
+			return nil, err
+		}
+	}
+	bb[len(ss)] = nil
+	return bb, nil
 }
 
 // readdirnames returns the names of files inside the directory represented by dirfd.
 func readdirnames(dirfd int) (names []string, err error) {
-	result := make([]string, 0, 100)
+	names = make([]string, 0, 100)
 	var buf [STATMAX]byte
 
 	for {
 		n, e := Read(dirfd, buf[:])
 		if e != nil {
-			return []string{}, e
+			return nil, e
 		}
 		if n == 0 {
 			break
 		}
-
 		for i := 0; i < n; {
 			m, _ := gbit16(buf[i:])
 			m += 2
 
 			if m < STATFIXLEN {
-				return []string{}, NewError("malformed stat buffer")
+				return nil, ErrBadStat
 			}
 
-			name, _ := gstring(buf[i+41:])
-			result = append(result, name)
-
+			s, _, ok := gstring(buf[i+41:])
+			if !ok {
+				return nil, ErrBadStat
+			}
+			names = append(names, s)
 			i += int(m)
 		}
 	}
-	return []string{}, nil
+	return
 }
 
 // readdupdevice returns a list of currently opened fds (excluding stdin, stdout, stderr) from the dup device #d.
 // ForkLock should be write locked before calling, so that no new fds would be created while the fd list is being read.
 func readdupdevice() (fds []int, err error) {
 	dupdevfd, err := Open("#d", O_RDONLY)
-
 	if err != nil {
 		return
 	}
 	defer Close(dupdevfd)
 
-	fileNames, err := readdirnames(dupdevfd)
+	names, err := readdirnames(dupdevfd)
 	if err != nil {
 		return
 	}
 
-	fds = make([]int, 0, len(fileNames)>>1)
-	for _, fdstr := range fileNames {
-		if l := len(fdstr); l > 2 && fdstr[l-3] == 'c' && fdstr[l-2] == 't' && fdstr[l-1] == 'l' {
+	fds = make([]int, 0, len(names)/2)
+	for _, name := range names {
+		if n := len(name); n > 3 && name[n-3:n] == "ctl" {
 			continue
 		}
-
-		fd := int(atoi([]byte(fdstr)))
-
-		if fd == 0 || fd == 1 || fd == 2 || fd == dupdevfd {
+		fd := int(atoi([]byte(name)))
+		switch fd {
+		case 0, 1, 2, dupdevfd:
 			continue
 		}
-
 		fds = append(fds, fd)
 	}
-
-	return fds[0:len(fds)], nil
+	return
 }
 
 var startupFds []int
@@ -196,7 +198,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
 	r1, _, _ = RawSyscall(SYS_RFORK, uintptr(RFPROC|RFFDG|RFREND|clearenv|rflag), 0, 0)
 
 	if r1 != 0 {
-		if int(r1) == -1 {
+		if int32(r1) == -1 {
 			return 0, NewError(errstr())
 		}
 		// parent; return PID
@@ -208,7 +210,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
 	// Close fds we don't need.
 	for i = 0; i < len(fdsToClose); i++ {
 		r1, _, _ = RawSyscall(SYS_CLOSE, uintptr(fdsToClose[i]), 0, 0)
-		if int(r1) == -1 {
+		if int32(r1) == -1 {
 			goto childerror
 		}
 	}
@@ -218,7 +220,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
 		for i = 0; i < len(envv); i++ {
 			r1, _, _ = RawSyscall(SYS_CREATE, uintptr(unsafe.Pointer(envv[i].name)), uintptr(O_WRONLY), uintptr(0666))
 
-			if int(r1) == -1 {
+			if int32(r1) == -1 {
 				goto childerror
 			}
 
@@ -227,13 +229,13 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
 			r1, _, _ = RawSyscall6(SYS_PWRITE, uintptr(envfd), uintptr(unsafe.Pointer(envv[i].value)), uintptr(envv[i].nvalue),
 				^uintptr(0), ^uintptr(0), 0)
 
-			if int(r1) == -1 || int(r1) != envv[i].nvalue {
+			if int32(r1) == -1 || int(r1) != envv[i].nvalue {
 				goto childerror
 			}
 
 			r1, _, _ = RawSyscall(SYS_CLOSE, uintptr(envfd), 0, 0)
 
-			if int(r1) == -1 {
+			if int32(r1) == -1 {
 				goto childerror
 			}
 		}
@@ -242,7 +244,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
 	// Chdir
 	if dir != nil {
 		r1, _, _ = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
-		if int(r1) == -1 {
+		if int32(r1) == -1 {
 			goto childerror
 		}
 	}
@@ -252,7 +254,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
 	nextfd = int(len(fd))
 	if pipe < nextfd {
 		r1, _, _ = RawSyscall(SYS_DUP, uintptr(pipe), uintptr(nextfd), 0)
-		if int(r1) == -1 {
+		if int32(r1) == -1 {
 			goto childerror
 		}
 		pipe = nextfd
@@ -261,7 +263,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
 	for i = 0; i < len(fd); i++ {
 		if fd[i] >= 0 && fd[i] < int(i) {
 			r1, _, _ = RawSyscall(SYS_DUP, uintptr(fd[i]), uintptr(nextfd), 0)
-			if int(r1) == -1 {
+			if int32(r1) == -1 {
 				goto childerror
 			}
 
@@ -282,12 +284,17 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
 		if fd[i] == int(i) {
 			continue
 		}
-
 		r1, _, _ = RawSyscall(SYS_DUP, uintptr(fd[i]), uintptr(i), 0)
-		if int(r1) == -1 {
+		if int32(r1) == -1 {
 			goto childerror
 		}
-		RawSyscall(SYS_CLOSE, uintptr(fd[i]), 0, 0)
+	}
+
+	// Pass 3: close fd[i] if it was moved in the previous pass.
+	for i = 0; i < len(fd); i++ {
+		if fd[i] >= 0 && fd[i] != int(i) {
+			RawSyscall(SYS_CLOSE, uintptr(fd[i]), 0, 0)
+		}
 	}
 
 	// Time to exec.
@@ -374,12 +381,21 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
 	p[1] = -1
 
 	// Convert args to C form.
-	argv0p := StringBytePtr(argv0)
-	argvp := StringSlicePtr(argv)
+	argv0p, err := BytePtrFromString(argv0)
+	if err != nil {
+		return 0, err
+	}
+	argvp, err := SlicePtrFromStrings(argv)
+	if err != nil {
+		return 0, err
+	}
 
 	var dir *byte
 	if attr.Dir != "" {
-		dir = StringBytePtr(attr.Dir)
+		dir, err = BytePtrFromString(attr.Dir)
+		if err != nil {
+			return 0, err
+		}
 	}
 	var envvParsed []envItem
 	if attr.Env != nil {
@@ -390,7 +406,13 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
 				i++
 			}
 
-			envvParsed = append(envvParsed, envItem{StringBytePtr("/env/" + v[:i]), StringBytePtr(v[i+1:]), len(v) - i})
+			envname, err := BytePtrFromString("/env/" + v[:i])
+			if err != nil {
+				return 0, err
+			}
+			envvalue := make([]byte, len(v)-i)
+			copy(envvalue, v[i+1:])
+			envvParsed = append(envvParsed, envItem{envname, &envvalue[0], len(v) - i})
 		}
 	}
 
@@ -400,44 +422,37 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
 	// get a list of open fds, excluding stdin,stdout and stderr that need to be closed in the child.
 	// no new fds can be created while we hold the ForkLock for writing.
 	openFds, e := readdupdevice()
-
 	if e != nil {
 		ForkLock.Unlock()
 		return 0, e
 	}
 
 	fdsToClose := make([]int, 0, len(openFds))
-	// exclude fds opened from startup from the list of fds to be closed.
 	for _, fd := range openFds {
-		isReserved := false
-		for _, reservedFd := range startupFds {
-			if fd == reservedFd {
-				isReserved = true
+		doClose := true
+
+		// exclude files opened at startup.
+		for _, sfd := range startupFds {
+			if fd == sfd {
+				doClose = false
 				break
 			}
 		}
 
-		if !isReserved {
-			fdsToClose = append(fdsToClose, fd)
-		}
-	}
-
-	// exclude fds requested by the caller from the list of fds to be closed.
-	for _, fd := range openFds {
-		isReserved := false
-		for _, reservedFd := range attr.Files {
-			if fd == int(reservedFd) {
-				isReserved = true
+		// exclude files explicitly requested by the caller.
+		for _, rfd := range attr.Files {
+			if fd == int(rfd) {
+				doClose = false
 				break
 			}
 		}
 
-		if !isReserved {
+		if doClose {
 			fdsToClose = append(fdsToClose, fd)
 		}
 	}
 
-	// Allocate child status pipe close on exec.	
+	// Allocate child status pipe close on exec.
 	e = cexecPipe(p[:])
 
 	if e != nil {
@@ -480,14 +495,75 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
 	return pid, nil
 }
 
+type waitErr struct {
+	Waitmsg
+	err error
+}
+
+var procs struct {
+	sync.Mutex
+	waits map[int]chan *waitErr
+}
+
+// startProcess starts a new goroutine, tied to the OS
+// thread, which runs the process and subsequently waits
+// for it to finish, communicating the process stats back
+// to any goroutines that may have been waiting on it.
+//
+// Such a dedicated goroutine is needed because on
+// Plan 9, only the parent thread can wait for a child,
+// whereas goroutines tend to jump OS threads (e.g.,
+// between starting a process and running Wait(), the
+// goroutine may have been rescheduled).
+func startProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
+	type forkRet struct {
+		pid int
+		err error
+	}
+
+	forkc := make(chan forkRet, 1)
+	go func() {
+		runtime.LockOSThread()
+		var ret forkRet
+
+		ret.pid, ret.err = forkExec(argv0, argv, attr)
+		// If fork fails there is nothing to wait for.
+		if ret.err != nil || ret.pid == 0 {
+			forkc <- ret
+			return
+		}
+
+		waitc := make(chan *waitErr, 1)
+
+		// Mark that the process is running.
+		procs.Lock()
+		if procs.waits == nil {
+			procs.waits = make(map[int]chan *waitErr)
+		}
+		procs.waits[ret.pid] = waitc
+		procs.Unlock()
+
+		forkc <- ret
+
+		var w waitErr
+		for w.err == nil && w.Pid != ret.pid {
+			w.err = Await(&w.Waitmsg)
+		}
+		waitc <- &w
+		close(waitc)
+	}()
+	ret := <-forkc
+	return ret.pid, ret.err
+}
+
 // Combination of fork and exec, careful to be thread safe.
 func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
-	return forkExec(argv0, argv, attr)
+	return startProcess(argv0, argv, attr)
 }
 
 // StartProcess wraps ForkExec for package os.
 func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
-	pid, err = forkExec(argv0, argv, attr)
+	pid, err = startProcess(argv0, argv, attr)
 	return pid, 0, err
 }
 
@@ -495,7 +571,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
 func Exec(argv0 string, argv []string, envv []string) (err error) {
 	if envv != nil {
 		r1, _, _ := RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
-		if int(r1) == -1 {
+		if int32(r1) == -1 {
 			return NewError(errstr())
 		}
 
@@ -519,10 +595,50 @@ func Exec(argv0 string, argv []string, envv []string) (err error) {
 		}
 	}
 
+	argv0p, err := BytePtrFromString(argv0)
+	if err != nil {
+		return err
+	}
+	argvp, err := SlicePtrFromStrings(argv)
+	if err != nil {
+		return err
+	}
 	_, _, e1 := Syscall(SYS_EXEC,
-		uintptr(unsafe.Pointer(StringBytePtr(argv0))),
-		uintptr(unsafe.Pointer(&StringSlicePtr(argv)[0])),
+		uintptr(unsafe.Pointer(argv0p)),
+		uintptr(unsafe.Pointer(&argvp[0])),
 		0)
 
 	return e1
 }
+
+// WaitProcess waits until the pid of a
+// running process is found in the queue of
+// wait messages. It is used in conjunction
+// with ForkExec/StartProcess to wait for a
+// running process to exit.
+func WaitProcess(pid int, w *Waitmsg) (err error) {
+	procs.Lock()
+	ch := procs.waits[pid]
+	procs.Unlock()
+
+	var wmsg *waitErr
+	if ch != nil {
+		wmsg = <-ch
+		procs.Lock()
+		if procs.waits[pid] == ch {
+			delete(procs.waits, pid)
+		}
+		procs.Unlock()
+	}
+	if wmsg == nil {
+		// ch was missing or ch is closed
+		return NewError("process not found")
+	}
+	if wmsg.err != nil {
+		return wmsg.err
+	}
+	if w != nil {
+		*w = wmsg.Waitmsg
+	}
+	return nil
+}
diff --git a/src/pkg/syscall/exec_unix.go b/src/pkg/syscall/exec_unix.go
index dfaa037..01b76c1 100644
--- a/src/pkg/syscall/exec_unix.go
+++ b/src/pkg/syscall/exec_unix.go
@@ -63,8 +63,9 @@ import (
 
 var ForkLock sync.RWMutex
 
-// Convert array of string to array
-// of NUL-terminated byte pointer.
+// StringSlicePtr is deprecated. Use SlicePtrFromStrings instead.
+// If any string contains a NUL byte this function panics instead
+// of returning an error.
 func StringSlicePtr(ss []string) []*byte {
 	bb := make([]*byte, len(ss)+1)
 	for i := 0; i < len(ss); i++ {
@@ -74,6 +75,22 @@ func StringSlicePtr(ss []string) []*byte {
 	return bb
 }
 
+// SlicePtrFromStrings converts a slice of strings to a slice of
+// pointers to NUL-terminated byte slices. If any string contains
+// a NUL byte, it returns (nil, EINVAL).
+func SlicePtrFromStrings(ss []string) ([]*byte, error) {
+	var err error
+	bb := make([]*byte, len(ss)+1)
+	for i := 0; i < len(ss); i++ {
+		bb[i], err = BytePtrFromString(ss[i])
+		if err != nil {
+			return nil, err
+		}
+	}
+	bb[len(ss)] = nil
+	return bb, nil
+}
+
 func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
 
 func SetNonblock(fd int, nonblocking bool) (err error) {
@@ -128,9 +145,18 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
 	p[1] = -1
 
 	// Convert args to C form.
-	argv0p := StringBytePtr(argv0)
-	argvp := StringSlicePtr(argv)
-	envvp := StringSlicePtr(attr.Env)
+	argv0p, err := BytePtrFromString(argv0)
+	if err != nil {
+		return 0, err
+	}
+	argvp, err := SlicePtrFromStrings(argv)
+	if err != nil {
+		return 0, err
+	}
+	envvp, err := SlicePtrFromStrings(attr.Env)
+	if err != nil {
+		return 0, err
+	}
 
 	if runtime.GOOS == "freebsd" && len(argv[0]) > len(argv0) {
 		argvp[0] = argv0p
@@ -138,11 +164,17 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
 
 	var chroot *byte
 	if sys.Chroot != "" {
-		chroot = StringBytePtr(sys.Chroot)
+		chroot, err = BytePtrFromString(sys.Chroot)
+		if err != nil {
+			return 0, err
+		}
 	}
 	var dir *byte
 	if attr.Dir != "" {
-		dir = StringBytePtr(attr.Dir)
+		dir, err = BytePtrFromString(attr.Dir)
+		if err != nil {
+			return 0, err
+		}
 	}
 
 	// Acquire the fork lock so that no other threads
@@ -151,13 +183,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
 	ForkLock.Lock()
 
 	// Allocate child status pipe close on exec.
-	if err = Pipe(p[0:]); err != nil {
-		goto error
-	}
-	if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != nil {
-		goto error
-	}
-	if _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != nil {
+	if err = forkExecPipe(p[:]); err != nil {
 		goto error
 	}
 
@@ -171,7 +197,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
 
 	// Read child error status from pipe.
 	Close(p[1])
-	n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+	n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
 	Close(p[0])
 	if err != nil || n != 0 {
 		if n == int(unsafe.Sizeof(err1)) {
@@ -215,9 +241,21 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
 
 // Ordinary exec.
 func Exec(argv0 string, argv []string, envv []string) (err error) {
+	argv0p, err := BytePtrFromString(argv0)
+	if err != nil {
+		return err
+	}
+	argvp, err := SlicePtrFromStrings(argv)
+	if err != nil {
+		return err
+	}
+	envvp, err := SlicePtrFromStrings(envv)
+	if err != nil {
+		return err
+	}
 	_, _, err1 := RawSyscall(SYS_EXECVE,
-		uintptr(unsafe.Pointer(StringBytePtr(argv0))),
-		uintptr(unsafe.Pointer(&StringSlicePtr(argv)[0])),
-		uintptr(unsafe.Pointer(&StringSlicePtr(envv)[0])))
+		uintptr(unsafe.Pointer(argv0p)),
+		uintptr(unsafe.Pointer(&argvp[0])),
+		uintptr(unsafe.Pointer(&envvp[0])))
 	return Errno(err1)
 }
diff --git a/src/pkg/syscall/exec_windows.go b/src/pkg/syscall/exec_windows.go
index 4dc4d05..82abc07 100644
--- a/src/pkg/syscall/exec_windows.go
+++ b/src/pkg/syscall/exec_windows.go
@@ -132,7 +132,10 @@ func SetNonblock(fd Handle, nonblocking bool) (err error) {
 // getFullPath retrieves the full path of the specified file.
 // Just a wrapper for Windows GetFullPathName api.
 func getFullPath(name string) (path string, err error) {
-	p := StringToUTF16Ptr(name)
+	p, err := UTF16PtrFromString(name)
+	if err != nil {
+		return "", err
+	}
 	buf := make([]uint16, 100)
 	n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
 	if err != nil {
@@ -225,8 +228,9 @@ type ProcAttr struct {
 }
 
 type SysProcAttr struct {
-	HideWindow bool
-	CmdLine    string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
+	HideWindow    bool
+	CmdLine       string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
+	CreationFlags uint32
 }
 
 var zeroProcAttr ProcAttr
@@ -261,7 +265,10 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
 			return 0, 0, err
 		}
 	}
-	argv0p := StringToUTF16Ptr(argv0)
+	argv0p, err := UTF16PtrFromString(argv0)
+	if err != nil {
+		return 0, 0, err
+	}
 
 	var cmdline string
 	// Windows CreateProcess takes the command line as a single string:
@@ -275,12 +282,18 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
 
 	var argvp *uint16
 	if len(cmdline) != 0 {
-		argvp = StringToUTF16Ptr(cmdline)
+		argvp, err = UTF16PtrFromString(cmdline)
+		if err != nil {
+			return 0, 0, err
+		}
 	}
 
 	var dirp *uint16
 	if len(attr.Dir) != 0 {
-		dirp = StringToUTF16Ptr(attr.Dir)
+		dirp, err = UTF16PtrFromString(attr.Dir)
+		if err != nil {
+			return 0, 0, err
+		}
 	}
 
 	// Acquire the fork lock so that no other threads
@@ -313,7 +326,8 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
 
 	pi := new(ProcessInformation)
 
-	err = CreateProcess(argv0p, argvp, nil, nil, true, CREATE_UNICODE_ENVIRONMENT, createEnvBlock(attr.Env), dirp, si, pi)
+	flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT
+	err = CreateProcess(argv0p, argvp, nil, nil, true, flags, createEnvBlock(attr.Env), dirp, si, pi)
 	if err != nil {
 		return 0, 0, err
 	}
diff --git a/src/pkg/syscall/mkall.sh b/src/pkg/syscall/mkall.sh
index 9e2d98f..3900a93 100755
--- a/src/pkg/syscall/mkall.sh
+++ b/src/pkg/syscall/mkall.sh
@@ -87,7 +87,8 @@ case "$1" in
 -syscalls)
 	for i in zsyscall*go
 	do
-		sed 1q $i | sed 's;^// ;;' | sh | gofmt >_$i && mv _$i $i
+		sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
+		rm _$i
 	done
 	exit 0
 	;;
@@ -131,6 +132,12 @@ freebsd_amd64)
 	mksysnum="curl -s 'http://svn.freebsd.org/base/head/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
 	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 	;;
+freebsd_arm)
+	mkerrors="$mkerrors"
+	mksyscall="./mksyscall.pl -l32 -arm"
+	mksysnum="curl -s 'http://svn.freebsd.org/base/head/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+	;;
 linux_386)
 	mkerrors="$mkerrors -m32"
 	mksyscall="./mksyscall.pl -l32"
@@ -138,8 +145,13 @@ linux_386)
 	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 	;;
 linux_amd64)
+	unistd_h=$(ls -1 /usr/include/asm/unistd_64.h /usr/include/x86_64-linux-gnu/asm/unistd_64.h 2>/dev/null | head -1)
+	if [ "$unistd_h" = "" ]; then
+		echo >&2 cannot find unistd_64.h
+		exit 1
+	fi
 	mkerrors="$mkerrors -m64"
-	mksysnum="./mksysnum_linux.pl /usr/include/asm/unistd_64.h"
+	mksysnum="./mksysnum_linux.pl $unistd_h"
 	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 	;;
 linux_arm)
diff --git a/src/pkg/syscall/mkerrors.sh b/src/pkg/syscall/mkerrors.sh
index 9aacec2..e8abb67 100755
--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -83,6 +83,10 @@ includes_Linux='
 #include <net/if_arp.h>
 #include <net/route.h>
 #include <netpacket/packet.h>
+
+#ifndef MSG_FASTOPEN
+#define MSG_FASTOPEN    0x20000000
+#endif
 '
 
 includes_NetBSD='
@@ -104,6 +108,9 @@ includes_NetBSD='
 #include <netinet/ip.h>
 #include <netinet/ip_mroute.h>
 #include <netinet/if_ether.h>
+
+// Needed since <sys/param.h> refers to it...
+#define schedppq 1
 '
 
 includes_OpenBSD='
@@ -174,22 +181,37 @@ ccflags="$@"
 		$2 !~ /^EQUIV_/ &&
 		$2 !~ /^EXPR_/ &&
 		$2 ~ /^E[A-Z0-9_]+$/ ||
+		$2 ~ /^B[0-9_]+$/ ||
+		$2 ~ /^V[A-Z0-9]+$/ ||
+		$2 ~ /^CS[A-Z0-9]/ ||
+		$2 ~ /^I(SIG|CANON|CRNL|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
+		$2 ~ /^IGN/ ||
+		$2 ~ /^IX(ON|ANY|OFF)$/ ||
+		$2 ~ /^IN(LCR|PCK)$/ ||
+		$2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
+		$2 ~ /^C(LOCAL|READ)$/ ||
+		$2 == "BRKINT" ||
+		$2 == "HUPCL" ||
+		$2 == "PENDIN" ||
+		$2 == "TOSTOP" ||
+		$2 ~ /^PAR/ ||
 		$2 ~ /^SIG[^_]/ ||
+		$2 ~ /^O[CNPFP][A-Z]+[^_][A-Z]+$/ ||
 		$2 ~ /^IN_/ ||
 		$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
 		$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
 		$2 == "SOMAXCONN" ||
 		$2 == "NAME_MAX" ||
 		$2 == "IFNAMSIZ" ||
-		$2 == "CTL_NET" ||
-		$2 == "CTL_MAXNAME" ||
+		$2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ ||
+		$2 ~ /^SYSCTL_VERS/ ||
 		$2 ~ /^(MS|MNT)_/ ||
 		$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
 		$2 ~ /^(O|F|FD|NAME|S|PTRACE|PT)_/ ||
 		$2 ~ /^LINUX_REBOOT_CMD_/ ||
 		$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
 		$2 !~ "NLA_TYPE_MASK" &&
-		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
+		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
 		$2 ~ /^SIOC/ ||
 		$2 ~ /^TIOC/ ||
 		$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
diff --git a/src/pkg/syscall/mksyscall.pl b/src/pkg/syscall/mksyscall.pl
index 0994968..df47958 100755
--- a/src/pkg/syscall/mksyscall.pl
+++ b/src/pkg/syscall/mksyscall.pl
@@ -110,6 +110,16 @@ while(<>) {
 	my $out_decl = @out ? sprintf(" (%s)", join(', ', @out)) : "";
 	$text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out_decl;
 
+	# Check if err return available
+	my $errvar = "";
+	foreach my $p (@out) {
+		my ($name, $type) = parseparam($p);
+		if($type eq "error") {
+			$errvar = $name;
+			last;
+		}
+	}
+
 	# Prepare arguments to Syscall.
 	my @args = ();
 	my $n = 0;
@@ -117,8 +127,18 @@ while(<>) {
 		my ($name, $type) = parseparam($p);
 		if($type =~ /^\*/) {
 			push @args, "uintptr(unsafe.Pointer($name))";
+		} elsif($type eq "string" && $errvar ne "") {
+			$text .= "\tvar _p$n *byte\n";
+			$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))";
+			$n++;
 		} elsif($type eq "string") {
-			push @args, "uintptr(unsafe.Pointer(StringBytePtr($name)))";
+			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))";
+			$n++;
 		} elsif($type =~ /^\[\](.*)/) {
 			# Convert slice into pointer, length.
 			# Have to be careful not to take address of &a[0] if len == 0:
@@ -237,7 +257,7 @@ while(<>) {
 	$text .= $body;
 	
 	if ($plan9 && $ret[2] eq "e1") {
-		$text .= "\tif int(r0) == -1 {\n";
+		$text .= "\tif int32(r0) == -1 {\n";
 		$text .= "\t\terr = e1\n";
 		$text .= "\t}\n";
 	} elsif ($do_errno) {
diff --git a/src/pkg/syscall/mksyscall_windows.pl b/src/pkg/syscall/mksyscall_windows.pl
index 1fb5112..0e015cb 100755
--- a/src/pkg/syscall/mksyscall_windows.pl
+++ b/src/pkg/syscall/mksyscall_windows.pl
@@ -118,7 +118,8 @@ while(<>) {
 	}
 
 	# Decide which version of api is used: ascii or unicode.
-	my $strconvfunc = $sysname !~ /W$/ ? "StringBytePtr" : "StringToUTF16Ptr";
+	my $strconvfunc = $sysname !~ /W$/ ? "BytePtrFromString" : "UTF16PtrFromString";
+	my $strconvtype = $sysname !~ /W$/ ? "*byte" : "*uint16";
 
 	# Winapi proc address variable.
 	$vars .= "\t$sysvarname = $modvname.NewProc(\"$sysname\")\n";
@@ -133,6 +134,16 @@ while(<>) {
 	}
 	$text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out;
 
+	# Check if err return available
+	my $errvar = "";
+	foreach my $p (@out) {
+		my ($name, $type) = parseparam($p);
+		if($type eq "error") {
+			$errvar = $name;
+			last;
+		}
+	}
+
 	# Prepare arguments to Syscall.
 	my @args = ();
 	my $n = 0;
@@ -141,8 +152,18 @@ while(<>) {
 		my ($name, $type) = parseparam($p);
 		if($type =~ /^\*/) {
 			push @args, "uintptr(unsafe.Pointer($name))";
+		} elsif($type eq "string" && $errvar ne "") {
+			$text .= "\tvar _p$n $strconvtype\n";
+			$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))";
+			$n++;
 		} elsif($type eq "string") {
-			push @args, "uintptr(unsafe.Pointer($strconvfunc($name)))";
+			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))";
+			$n++;
 		} elsif($type =~ /^\[\](.*)/) {
 			# Convert slice into pointer, length.
 			# Have to be careful not to take address of &a[0] if len == 0:
@@ -245,7 +266,7 @@ while(<>) {
 				$failexpr = "!$name";
 			} elsif($name eq "err") {
 				$ret[$i] = "r1";
-				$failexpr = "int(r1) $failcond";
+				$failexpr = "r1 $failcond";
 			} else {
 				$failexpr = "$name $failcond";
 			}
diff --git a/src/pkg/syscall/netlink_linux.go b/src/pkg/syscall/netlink_linux.go
index dc0f684..49550ea 100644
--- a/src/pkg/syscall/netlink_linux.go
+++ b/src/pkg/syscall/netlink_linux.go
@@ -6,9 +6,7 @@
 
 package syscall
 
-import (
-	"unsafe"
-)
+import "unsafe"
 
 // Round the length of a netlink message up to align it properly.
 func nlmAlignOf(msglen int) int {
@@ -21,8 +19,8 @@ func rtaAlignOf(attrlen int) int {
 	return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1)
 }
 
-// NetlinkRouteRequest represents the request message to receive
-// routing and link states from the kernel.
+// NetlinkRouteRequest represents a request message to receive routing
+// and link states from the kernel.
 type NetlinkRouteRequest struct {
 	Header NlMsghdr
 	Data   RtGenmsg
@@ -30,29 +28,18 @@ type NetlinkRouteRequest struct {
 
 func (rr *NetlinkRouteRequest) toWireFormat() []byte {
 	b := make([]byte, rr.Header.Len)
-	b[0] = byte(rr.Header.Len)
-	b[1] = byte(rr.Header.Len >> 8)
-	b[2] = byte(rr.Header.Len >> 16)
-	b[3] = byte(rr.Header.Len >> 24)
-	b[4] = byte(rr.Header.Type)
-	b[5] = byte(rr.Header.Type >> 8)
-	b[6] = byte(rr.Header.Flags)
-	b[7] = byte(rr.Header.Flags >> 8)
-	b[8] = byte(rr.Header.Seq)
-	b[9] = byte(rr.Header.Seq >> 8)
-	b[10] = byte(rr.Header.Seq >> 16)
-	b[11] = byte(rr.Header.Seq >> 24)
-	b[12] = byte(rr.Header.Pid)
-	b[13] = byte(rr.Header.Pid >> 8)
-	b[14] = byte(rr.Header.Pid >> 16)
-	b[15] = byte(rr.Header.Pid >> 24)
+	*(*uint32)(unsafe.Pointer(&b[0:4][0])) = rr.Header.Len
+	*(*uint16)(unsafe.Pointer(&b[4:6][0])) = rr.Header.Type
+	*(*uint16)(unsafe.Pointer(&b[6:8][0])) = rr.Header.Flags
+	*(*uint32)(unsafe.Pointer(&b[8:12][0])) = rr.Header.Seq
+	*(*uint32)(unsafe.Pointer(&b[12:16][0])) = rr.Header.Pid
 	b[16] = byte(rr.Data.Family)
 	return b
 }
 
 func newNetlinkRouteRequest(proto, seq, family int) []byte {
 	rr := &NetlinkRouteRequest{}
-	rr.Header.Len = NLMSG_HDRLEN + SizeofRtGenmsg
+	rr.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg)
 	rr.Header.Type = uint16(proto)
 	rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST
 	rr.Header.Seq = uint32(seq)
@@ -60,167 +47,131 @@ func newNetlinkRouteRequest(proto, seq, family int) []byte {
 	return rr.toWireFormat()
 }
 
-// NetlinkRIB returns routing information base, as known as RIB,
-// which consists of network facility information, states and
-// parameters.
+// NetlinkRIB returns routing information base, as known as RIB, which
+// consists of network facility information, states and parameters.
 func NetlinkRIB(proto, family int) ([]byte, error) {
-	var (
-		lsanl SockaddrNetlink
-		tab   []byte
-	)
-
-	s, e := Socket(AF_NETLINK, SOCK_RAW, 0)
-	if e != nil {
-		return nil, e
+	s, err := Socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)
+	if err != nil {
+		return nil, err
 	}
 	defer Close(s)
-
-	lsanl.Family = AF_NETLINK
-	e = Bind(s, &lsanl)
-	if e != nil {
-		return nil, e
+	lsa := &SockaddrNetlink{Family: AF_NETLINK}
+	if err := Bind(s, lsa); err != nil {
+		return nil, err
 	}
-
-	seq := 1
-	wb := newNetlinkRouteRequest(proto, seq, family)
-	e = Sendto(s, wb, 0, &lsanl)
-	if e != nil {
-		return nil, e
+	wb := newNetlinkRouteRequest(proto, 1, family)
+	if err := Sendto(s, wb, 0, lsa); err != nil {
+		return nil, err
 	}
-
+	var tab []byte
+done:
 	for {
-		var (
-			rb  []byte
-			nr  int
-			lsa Sockaddr
-		)
-
-		rb = make([]byte, Getpagesize())
-		nr, _, e = Recvfrom(s, rb, 0)
-		if e != nil {
-			return nil, e
+		rb := make([]byte, Getpagesize())
+		nr, _, err := Recvfrom(s, rb, 0)
+		if err != nil {
+			return nil, err
 		}
 		if nr < NLMSG_HDRLEN {
 			return nil, EINVAL
 		}
 		rb = rb[:nr]
 		tab = append(tab, rb...)
-
-		msgs, _ := ParseNetlinkMessage(rb)
+		msgs, err := ParseNetlinkMessage(rb)
+		if err != nil {
+			return nil, err
+		}
 		for _, m := range msgs {
-			if lsa, e = Getsockname(s); e != nil {
-				return nil, e
+			lsa, err := Getsockname(s)
+			if err != nil {
+				return nil, err
 			}
 			switch v := lsa.(type) {
 			case *SockaddrNetlink:
-				if m.Header.Seq != uint32(seq) || m.Header.Pid != v.Pid {
+				if m.Header.Seq != 1 || m.Header.Pid != v.Pid {
 					return nil, EINVAL
 				}
 			default:
 				return nil, EINVAL
 			}
 			if m.Header.Type == NLMSG_DONE {
-				goto done
+				break done
 			}
 			if m.Header.Type == NLMSG_ERROR {
 				return nil, EINVAL
 			}
 		}
 	}
-
-done:
 	return tab, nil
 }
 
-// NetlinkMessage represents the netlink message.
+// NetlinkMessage represents a netlink message.
 type NetlinkMessage struct {
 	Header NlMsghdr
 	Data   []byte
 }
 
-// ParseNetlinkMessage parses buf as netlink messages and returns
-// the slice containing the NetlinkMessage structs.
-func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, error) {
-	var (
-		h    *NlMsghdr
-		dbuf []byte
-		dlen int
-		e    error
-		msgs []NetlinkMessage
-	)
-
-	for len(buf) >= NLMSG_HDRLEN {
-		h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf)
-		if e != nil {
-			break
+// ParseNetlinkMessage parses b as an array of netlink messages and
+// returns the slice containing the NetlinkMessage structures.
+func ParseNetlinkMessage(b []byte) ([]NetlinkMessage, error) {
+	var msgs []NetlinkMessage
+	for len(b) >= NLMSG_HDRLEN {
+		h, dbuf, dlen, err := netlinkMessageHeaderAndData(b)
+		if err != nil {
+			return nil, err
 		}
-		m := NetlinkMessage{}
-		m.Header = *h
-		m.Data = dbuf[:h.Len-NLMSG_HDRLEN]
+		m := NetlinkMessage{Header: *h, Data: dbuf[:int(h.Len)-NLMSG_HDRLEN]}
 		msgs = append(msgs, m)
-		buf = buf[dlen:]
+		b = b[dlen:]
 	}
-
-	return msgs, e
+	return msgs, nil
 }
 
-func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, error) {
-	h := (*NlMsghdr)(unsafe.Pointer(&buf[0]))
-	if h.Len < NLMSG_HDRLEN || int(h.Len) > len(buf) {
+func netlinkMessageHeaderAndData(b []byte) (*NlMsghdr, []byte, int, error) {
+	h := (*NlMsghdr)(unsafe.Pointer(&b[0]))
+	if int(h.Len) < NLMSG_HDRLEN || int(h.Len) > len(b) {
 		return nil, nil, 0, EINVAL
 	}
-	return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), nil
+	return h, b[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), nil
 }
 
-// NetlinkRouteAttr represents the netlink route attribute.
+// NetlinkRouteAttr represents a netlink route attribute.
 type NetlinkRouteAttr struct {
 	Attr  RtAttr
 	Value []byte
 }
 
-// ParseNetlinkRouteAttr parses msg's payload as netlink route
-// attributes and returns the slice containing the NetlinkRouteAttr
-// structs.
-func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, error) {
-	var (
-		buf   []byte
-		a     *RtAttr
-		alen  int
-		vbuf  []byte
-		e     error
-		attrs []NetlinkRouteAttr
-	)
-
-	switch msg.Header.Type {
+// ParseNetlinkRouteAttr parses m's payload as an array of netlink
+// route attributes and returns the slice containing the
+// NetlinkRouteAttr structures.
+func ParseNetlinkRouteAttr(m *NetlinkMessage) ([]NetlinkRouteAttr, error) {
+	var b []byte
+	switch m.Header.Type {
 	case RTM_NEWLINK, RTM_DELLINK:
-		buf = msg.Data[SizeofIfInfomsg:]
+		b = m.Data[SizeofIfInfomsg:]
 	case RTM_NEWADDR, RTM_DELADDR:
-		buf = msg.Data[SizeofIfAddrmsg:]
+		b = m.Data[SizeofIfAddrmsg:]
 	case RTM_NEWROUTE, RTM_DELROUTE:
-		buf = msg.Data[SizeofRtMsg:]
+		b = m.Data[SizeofRtMsg:]
 	default:
 		return nil, EINVAL
 	}
-
-	for len(buf) >= SizeofRtAttr {
-		a, vbuf, alen, e = netlinkRouteAttrAndValue(buf)
-		if e != nil {
-			break
+	var attrs []NetlinkRouteAttr
+	for len(b) >= SizeofRtAttr {
+		a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
+		if err != nil {
+			return nil, err
 		}
-		ra := NetlinkRouteAttr{}
-		ra.Attr = *a
-		ra.Value = vbuf[:a.Len-SizeofRtAttr]
+		ra := NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-SizeofRtAttr]}
 		attrs = append(attrs, ra)
-		buf = buf[alen:]
+		b = b[alen:]
 	}
-
 	return attrs, nil
 }
 
-func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, error) {
-	h := (*RtAttr)(unsafe.Pointer(&buf[0]))
-	if h.Len < SizeofRtAttr || int(h.Len) > len(buf) {
+func netlinkRouteAttrAndValue(b []byte) (*RtAttr, []byte, int, error) {
+	a := (*RtAttr)(unsafe.Pointer(&b[0]))
+	if int(a.Len) < SizeofRtAttr || int(a.Len) > len(b) {
 		return nil, nil, 0, EINVAL
 	}
-	return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), nil
+	return a, b[SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
 }
diff --git a/src/pkg/syscall/passfd_test.go b/src/pkg/syscall/passfd_test.go
new file mode 100644
index 0000000..079c930
--- /dev/null
+++ b/src/pkg/syscall/passfd_test.go
@@ -0,0 +1,201 @@
+// 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 linux darwin freebsd netbsd openbsd
+
+package syscall_test
+
+import (
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"net"
+	"os"
+	"os/exec"
+	"runtime"
+	"syscall"
+	"testing"
+	"time"
+)
+
+// TestPassFD tests passing a file descriptor over a Unix socket.
+//
+// This test involved both a parent and child process. The parent
+// process is invoked as a normal test, with "go test", which then
+// runs the child process by running the current test binary with args
+// "-test.run=^TestPassFD$" and an environment variable used to signal
+// that the test should become the child process instead.
+func TestPassFD(t *testing.T) {
+	if runtime.GOOS == "openbsd" {
+		t.Skip("issue 4956")
+	}
+	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
+		passFDChild()
+		return
+	}
+
+	tempDir, err := ioutil.TempDir("", "TestPassFD")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tempDir)
+
+	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
+	if err != nil {
+		t.Fatalf("Socketpair: %v", err)
+	}
+	defer syscall.Close(fds[0])
+	defer syscall.Close(fds[1])
+	writeFile := os.NewFile(uintptr(fds[0]), "child-writes")
+	readFile := os.NewFile(uintptr(fds[1]), "parent-reads")
+	defer writeFile.Close()
+	defer readFile.Close()
+
+	cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir)
+	cmd.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
+	cmd.ExtraFiles = []*os.File{writeFile}
+
+	out, err := cmd.CombinedOutput()
+	if len(out) > 0 || err != nil {
+		t.Fatalf("child process: %q, %v", out, err)
+	}
+
+	c, err := net.FileConn(readFile)
+	if err != nil {
+		t.Fatalf("FileConn: %v", err)
+	}
+	defer c.Close()
+
+	uc, ok := c.(*net.UnixConn)
+	if !ok {
+		t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c)
+	}
+
+	buf := make([]byte, 32) // expect 1 byte
+	oob := make([]byte, 32) // expect 24 bytes
+	closeUnix := time.AfterFunc(5*time.Second, func() {
+		t.Logf("timeout reading from unix socket")
+		uc.Close()
+	})
+	_, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
+	closeUnix.Stop()
+
+	scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
+	if err != nil {
+		t.Fatalf("ParseSocketControlMessage: %v", err)
+	}
+	if len(scms) != 1 {
+		t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms)
+	}
+	scm := scms[0]
+	gotFds, err := syscall.ParseUnixRights(&scm)
+	if err != nil {
+		t.Fatalf("syscall.ParseUnixRights: %v", err)
+	}
+	if len(gotFds) != 1 {
+		t.Fatalf("wanted 1 fd; got %#v", gotFds)
+	}
+
+	f := os.NewFile(uintptr(gotFds[0]), "fd-from-child")
+	defer f.Close()
+
+	got, err := ioutil.ReadAll(f)
+	want := "Hello from child process!\n"
+	if string(got) != want {
+		t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want)
+	}
+}
+
+// passFDChild is the child process used by TestPassFD.
+func passFDChild() {
+	defer os.Exit(0)
+
+	// Look for our fd. It should be fd 3, but we work around an fd leak
+	// bug here (http://golang.org/issue/2603) to let it be elsewhere.
+	var uc *net.UnixConn
+	for fd := uintptr(3); fd <= 10; fd++ {
+		f := os.NewFile(fd, "unix-conn")
+		var ok bool
+		netc, _ := net.FileConn(f)
+		uc, ok = netc.(*net.UnixConn)
+		if ok {
+			break
+		}
+	}
+	if uc == nil {
+		fmt.Println("failed to find unix fd")
+		return
+	}
+
+	// Make a file f to send to our parent process on uc.
+	// We make it in tempDir, which our parent will clean up.
+	flag.Parse()
+	tempDir := flag.Arg(0)
+	f, err := ioutil.TempFile(tempDir, "")
+	if err != nil {
+		fmt.Printf("TempFile: %v", err)
+		return
+	}
+
+	f.Write([]byte("Hello from child process!\n"))
+	f.Seek(0, 0)
+
+	rights := syscall.UnixRights(int(f.Fd()))
+	dummyByte := []byte("x")
+	n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil)
+	if err != nil {
+		fmt.Printf("WriteMsgUnix: %v", err)
+		return
+	}
+	if n != 1 || oobn != len(rights) {
+		fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights))
+		return
+	}
+}
+
+// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage,
+// and ParseUnixRights are able to successfully round-trip lists of file descriptors.
+func TestUnixRightsRoundtrip(t *testing.T) {
+	testCases := [...][][]int{
+		{{42}},
+		{{1, 2}},
+		{{3, 4, 5}},
+		{{}},
+		{{1, 2}, {3, 4, 5}, {}, {7}},
+	}
+	for _, testCase := range testCases {
+		b := []byte{}
+		var n int
+		for _, fds := range testCase {
+			// Last assignment to n wins
+			n = len(b) + syscall.CmsgLen(4*len(fds))
+			b = append(b, syscall.UnixRights(fds...)...)
+		}
+		// Truncate b
+		b = b[:n]
+
+		scms, err := syscall.ParseSocketControlMessage(b)
+		if err != nil {
+			t.Fatalf("ParseSocketControlMessage: %v", err)
+		}
+		if len(scms) != len(testCase) {
+			t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms)
+		}
+		for i, scm := range scms {
+			gotFds, err := syscall.ParseUnixRights(&scm)
+			if err != nil {
+				t.Fatalf("ParseUnixRights: %v", err)
+			}
+			wantFds := testCase[i]
+			if len(gotFds) != len(wantFds) {
+				t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds)
+			}
+			for j, fd := range gotFds {
+				if fd != wantFds[j] {
+					t.Fatalf("expected fd %v, got %v", wantFds[j], fd)
+				}
+			}
+		}
+	}
+}
diff --git a/src/pkg/syscall/race.go b/src/pkg/syscall/race.go
new file mode 100644
index 0000000..8177884
--- /dev/null
+++ b/src/pkg/syscall/race.go
@@ -0,0 +1,22 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build race
+
+package syscall
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+const raceenabled = true
+
+func raceAcquire(addr unsafe.Pointer) {
+	runtime.RaceAcquire(addr)
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+	runtime.RaceReleaseMerge(addr)
+}
diff --git a/src/pkg/syscall/race0.go b/src/pkg/syscall/race0.go
new file mode 100644
index 0000000..e94fb47
--- /dev/null
+++ b/src/pkg/syscall/race0.go
@@ -0,0 +1,19 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !race
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+const raceenabled = false
+
+func raceAcquire(addr unsafe.Pointer) {
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+}
diff --git a/src/pkg/syscall/route_bsd.go b/src/pkg/syscall/route_bsd.go
index e17d976..62c5ce1 100644
--- a/src/pkg/syscall/route_bsd.go
+++ b/src/pkg/syscall/route_bsd.go
@@ -8,9 +8,7 @@
 
 package syscall
 
-import (
-	"unsafe"
-)
+import "unsafe"
 
 // Round the length of a raw sockaddr up to align it properly.
 func rsaAlignOf(salen int) int {
@@ -31,7 +29,6 @@ func rsaAlignOf(salen int) int {
 // parameters.
 func RouteRIB(facility, param int) ([]byte, error) {
 	mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
-
 	// Find size.
 	n := uintptr(0)
 	if err := sysctl(mib, nil, &n, nil, 0); err != nil {
@@ -40,12 +37,10 @@ func RouteRIB(facility, param int) ([]byte, error) {
 	if n == 0 {
 		return nil, nil
 	}
-
 	tab := make([]byte, n)
 	if err := sysctl(mib, &tab[0], &n, nil, 0); err != nil {
 		return nil, err
 	}
-
 	return tab[:n], nil
 }
 
@@ -76,13 +71,12 @@ func (m *RouteMessage) sockaddr() []Sockaddr {
 		af  int
 		sas [4]Sockaddr
 	)
-
-	buf := m.Data[:]
+	b := m.Data[:]
 	for i := uint(0); i < RTAX_MAX; i++ {
 		if m.Header.Addrs&rtaRtMask&(1<<i) == 0 {
 			continue
 		}
-		rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
 		switch i {
 		case RTAX_DST, RTAX_GATEWAY:
 			sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
@@ -96,14 +90,14 @@ func (m *RouteMessage) sockaddr() []Sockaddr {
 		case RTAX_NETMASK, RTAX_GENMASK:
 			switch af {
 			case AF_INET:
-				rsa4 := (*RawSockaddrInet4)(unsafe.Pointer(&buf[0]))
+				rsa4 := (*RawSockaddrInet4)(unsafe.Pointer(&b[0]))
 				sa := new(SockaddrInet4)
 				for j := 0; rsa4.Len > 0 && j < int(rsa4.Len)-int(unsafe.Offsetof(rsa4.Addr)); j++ {
 					sa.Addr[j] = rsa4.Addr[j]
 				}
 				sas[i] = sa
 			case AF_INET6:
-				rsa6 := (*RawSockaddrInet6)(unsafe.Pointer(&buf[0]))
+				rsa6 := (*RawSockaddrInet6)(unsafe.Pointer(&b[0]))
 				sa := new(SockaddrInet6)
 				for j := 0; rsa6.Len > 0 && j < int(rsa6.Len)-int(unsafe.Offsetof(rsa6.Addr)); j++ {
 					sa.Addr[j] = rsa6.Addr[j]
@@ -111,9 +105,8 @@ func (m *RouteMessage) sockaddr() []Sockaddr {
 				sas[i] = sa
 			}
 		}
-		buf = buf[rsaAlignOf(int(rsa.Len)):]
+		b = b[rsaAlignOf(int(rsa.Len)):]
 	}
-
 	return sas[:]
 }
 
@@ -148,13 +141,12 @@ func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
 	if m.Header.Addrs&rtaIfaMask == 0 {
 		return nil
 	}
-
-	buf := m.Data[:]
+	b := m.Data[:]
 	for i := uint(0); i < RTAX_MAX; i++ {
 		if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 {
 			continue
 		}
-		rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
 		switch i {
 		case RTAX_IFA:
 			sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
@@ -174,22 +166,21 @@ func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
 		case RTAX_BRD:
 			// nothing to do
 		}
-		buf = buf[rsaAlignOf(int(rsa.Len)):]
+		b = b[rsaAlignOf(int(rsa.Len)):]
 	}
-
 	return sas
 }
 
-// ParseRoutingMessage parses buf as routing messages and returns
-// the slice containing the RoutingMessage interfaces.
-func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, err error) {
-	for len(buf) >= anyMessageLen {
-		any := (*anyMessage)(unsafe.Pointer(&buf[0]))
+// ParseRoutingMessage parses b as routing messages and returns the
+// slice containing the RoutingMessage interfaces.
+func ParseRoutingMessage(b []byte) (msgs []RoutingMessage, err error) {
+	for len(b) >= anyMessageLen {
+		any := (*anyMessage)(unsafe.Pointer(&b[0]))
 		if any.Version != RTM_VERSION {
 			return nil, EINVAL
 		}
-		msgs = append(msgs, any.toRoutingMessage(buf))
-		buf = buf[any.Msglen:]
+		msgs = append(msgs, any.toRoutingMessage(b))
+		b = b[any.Msglen:]
 	}
 	return msgs, nil
 }
diff --git a/src/pkg/syscall/route_darwin.go b/src/pkg/syscall/route_darwin.go
index 410e70a..ad27907 100644
--- a/src/pkg/syscall/route_darwin.go
+++ b/src/pkg/syscall/route_darwin.go
@@ -6,36 +6,22 @@
 
 package syscall
 
-import (
-	"unsafe"
-)
+import "unsafe"
 
-func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
 	switch any.Type {
 	case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
 		p := (*RouteMessage)(unsafe.Pointer(any))
-		rtm := &RouteMessage{}
-		rtm.Header = p.Header
-		rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
-		return rtm
+		return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
 	case RTM_IFINFO:
 		p := (*InterfaceMessage)(unsafe.Pointer(any))
-		ifm := &InterfaceMessage{}
-		ifm.Header = p.Header
-		ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
-		return ifm
+		return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
 	case RTM_NEWADDR, RTM_DELADDR:
 		p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
-		ifam := &InterfaceAddrMessage{}
-		ifam.Header = p.Header
-		ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
-		return ifam
+		return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
 	case RTM_NEWMADDR2, RTM_DELMADDR:
 		p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
-		ifmam := &InterfaceMulticastAddrMessage{}
-		ifmam.Header = p.Header
-		ifmam.Data = buf[SizeofIfmaMsghdr2:any.Msglen]
-		return ifmam
+		return &InterfaceMulticastAddrMessage{Header: p.Header, Data: b[SizeofIfmaMsghdr2:any.Msglen]}
 	}
 	return nil
 }
@@ -53,13 +39,12 @@ func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
 	if m.Header.Addrs&rtaIfmaMask == 0 {
 		return nil
 	}
-
-	buf := m.Data[:]
+	b := m.Data[:]
 	for i := uint(0); i < RTAX_MAX; i++ {
 		if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
 			continue
 		}
-		rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
 		switch i {
 		case RTAX_IFA:
 			sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
@@ -70,8 +55,7 @@ func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
 		case RTAX_GATEWAY, RTAX_IFP:
 			// nothing to do
 		}
-		buf = buf[rsaAlignOf(int(rsa.Len)):]
+		b = b[rsaAlignOf(int(rsa.Len)):]
 	}
-
 	return sas
 }
diff --git a/src/pkg/syscall/route_freebsd.go b/src/pkg/syscall/route_freebsd.go
index 094e170..d8f8031 100644
--- a/src/pkg/syscall/route_freebsd.go
+++ b/src/pkg/syscall/route_freebsd.go
@@ -6,40 +6,37 @@
 
 package syscall
 
-import (
-	"unsafe"
-)
+import "unsafe"
 
-func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
 	switch any.Type {
 	case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
 		p := (*RouteMessage)(unsafe.Pointer(any))
-		rtm := &RouteMessage{}
-		rtm.Header = p.Header
-		rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
-		return rtm
+		return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
 	case RTM_IFINFO:
 		p := (*InterfaceMessage)(unsafe.Pointer(any))
-		ifm := &InterfaceMessage{}
-		ifm.Header = p.Header
-		ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
-		return ifm
+		return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+	case RTM_IFANNOUNCE:
+		p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
+		return &InterfaceAnnounceMessage{Header: p.Header}
 	case RTM_NEWADDR, RTM_DELADDR:
 		p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
-		ifam := &InterfaceAddrMessage{}
-		ifam.Header = p.Header
-		ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
-		return ifam
+		return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
 	case RTM_NEWMADDR, RTM_DELMADDR:
 		p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
-		ifmam := &InterfaceMulticastAddrMessage{}
-		ifmam.Header = p.Header
-		ifmam.Data = buf[SizeofIfmaMsghdr:any.Msglen]
-		return ifmam
+		return &InterfaceMulticastAddrMessage{Header: p.Header, Data: b[SizeofIfmaMsghdr:any.Msglen]}
 	}
 	return nil
 }
 
+// InterfaceAnnounceMessage represents a routing message containing
+// network interface arrival and depature information.
+type InterfaceAnnounceMessage struct {
+	Header IfAnnounceMsghdr
+}
+
+func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
+
 // InterfaceMulticastAddrMessage represents a routing message
 // containing network interface address entries.
 type InterfaceMulticastAddrMessage struct {
@@ -53,13 +50,12 @@ func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
 	if m.Header.Addrs&rtaIfmaMask == 0 {
 		return nil
 	}
-
-	buf := m.Data[:]
+	b := m.Data[:]
 	for i := uint(0); i < RTAX_MAX; i++ {
 		if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
 			continue
 		}
-		rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
 		switch i {
 		case RTAX_IFA:
 			sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
@@ -70,8 +66,7 @@ func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
 		case RTAX_GATEWAY, RTAX_IFP:
 			// nothing to do
 		}
-		buf = buf[rsaAlignOf(int(rsa.Len)):]
+		b = b[rsaAlignOf(int(rsa.Len)):]
 	}
-
 	return sas
 }
diff --git a/src/pkg/syscall/route_netbsd.go b/src/pkg/syscall/route_netbsd.go
index d6d9031..a6baa02 100644
--- a/src/pkg/syscall/route_netbsd.go
+++ b/src/pkg/syscall/route_netbsd.go
@@ -6,30 +6,30 @@
 
 package syscall
 
-import (
-	"unsafe"
-)
+import "unsafe"
 
-func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
 	switch any.Type {
 	case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
 		p := (*RouteMessage)(unsafe.Pointer(any))
-		rtm := &RouteMessage{}
-		rtm.Header = p.Header
-		rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
-		return rtm
+		return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
 	case RTM_IFINFO:
 		p := (*InterfaceMessage)(unsafe.Pointer(any))
-		ifm := &InterfaceMessage{}
-		ifm.Header = p.Header
-		ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
-		return ifm
+		return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+	case RTM_IFANNOUNCE:
+		p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
+		return &InterfaceAnnounceMessage{Header: p.Header}
 	case RTM_NEWADDR, RTM_DELADDR:
 		p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
-		ifam := &InterfaceAddrMessage{}
-		ifam.Header = p.Header
-		ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
-		return ifam
+		return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
 	}
 	return nil
 }
+
+// InterfaceAnnounceMessage represents a routing message containing
+// network interface arrival and depature information.
+type InterfaceAnnounceMessage struct {
+	Header IfAnnounceMsghdr
+}
+
+func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
diff --git a/src/pkg/syscall/route_openbsd.go b/src/pkg/syscall/route_openbsd.go
index 30e1cac..223c157 100644
--- a/src/pkg/syscall/route_openbsd.go
+++ b/src/pkg/syscall/route_openbsd.go
@@ -6,30 +6,30 @@
 
 package syscall
 
-import (
-	"unsafe"
-)
+import "unsafe"
 
-func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
 	switch any.Type {
 	case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
 		p := (*RouteMessage)(unsafe.Pointer(any))
-		rtm := &RouteMessage{}
-		rtm.Header = p.Header
-		rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
-		return rtm
+		return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
 	case RTM_IFINFO:
 		p := (*InterfaceMessage)(unsafe.Pointer(any))
-		ifm := &InterfaceMessage{}
-		ifm.Header = p.Header
-		ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
-		return ifm
+		return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+	case RTM_IFANNOUNCE:
+		p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
+		return &InterfaceAnnounceMessage{Header: p.Header}
 	case RTM_NEWADDR, RTM_DELADDR:
 		p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
-		ifam := &InterfaceAddrMessage{}
-		ifam.Header = p.Header
-		ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
-		return ifam
+		return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
 	}
 	return nil
 }
+
+// InterfaceAnnounceMessage represents a routing message containing
+// network interface arrival and depature information.
+type InterfaceAnnounceMessage struct {
+	Header IfAnnounceMsghdr
+}
+
+func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
diff --git a/src/pkg/syscall/security_windows.go b/src/pkg/syscall/security_windows.go
index bd40fe5..017b270 100644
--- a/src/pkg/syscall/security_windows.go
+++ b/src/pkg/syscall/security_windows.go
@@ -37,10 +37,13 @@ const (
 // TranslateAccountName converts a directory service
 // object name from one format to another.
 func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
-	u := StringToUTF16Ptr(username)
+	u, e := UTF16PtrFromString(username)
+	if e != nil {
+		return "", e
+	}
 	b := make([]uint16, 50)
 	n := uint32(len(b))
-	e := TranslateName(u, from, to, &b[0], &n)
+	e = TranslateName(u, from, to, &b[0], &n)
 	if e != nil {
 		if e != ERROR_INSUFFICIENT_BUFFER {
 			return "", e
@@ -67,7 +70,7 @@ type UserInfo10 struct {
 
 const (
 	// do not reorder
-	SidTypeUser = 1 << iota
+	SidTypeUser = 1 + iota
 	SidTypeGroup
 	SidTypeDomain
 	SidTypeAlias
@@ -94,7 +97,11 @@ type SID struct{}
 // sid into a valid, functional sid.
 func StringToSid(s string) (*SID, error) {
 	var sid *SID
-	e := ConvertStringSidToSid(StringToUTF16Ptr(s), &sid)
+	p, e := UTF16PtrFromString(s)
+	if e != nil {
+		return nil, e
+	}
+	e = ConvertStringSidToSid(p, &sid)
 	if e != nil {
 		return nil, e
 	}
@@ -109,17 +116,23 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32,
 	if len(account) == 0 {
 		return nil, "", 0, EINVAL
 	}
-	acc := StringToUTF16Ptr(account)
+	acc, e := UTF16PtrFromString(account)
+	if e != nil {
+		return nil, "", 0, e
+	}
 	var sys *uint16
 	if len(system) > 0 {
-		sys = StringToUTF16Ptr(system)
+		sys, e = UTF16PtrFromString(system)
+		if e != nil {
+			return nil, "", 0, e
+		}
 	}
 	db := make([]uint16, 50)
 	dn := uint32(len(db))
 	b := make([]byte, 50)
 	n := uint32(len(b))
 	sid = (*SID)(unsafe.Pointer(&b[0]))
-	e := LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
+	e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
 	if e != nil {
 		if e != ERROR_INSUFFICIENT_BUFFER {
 			return nil, "", 0, e
@@ -170,7 +183,10 @@ func (sid *SID) Copy() (*SID, error) {
 func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
 	var sys *uint16
 	if len(system) > 0 {
-		sys = StringToUTF16Ptr(system)
+		sys, err = UTF16PtrFromString(system)
+		if err != nil {
+			return "", "", 0, err
+		}
 	}
 	b := make([]uint16, 50)
 	n := uint32(len(b))
diff --git a/src/pkg/syscall/sockcmsg_linux.go b/src/pkg/syscall/sockcmsg_linux.go
index 0b4caa1..a2e26a1 100644
--- a/src/pkg/syscall/sockcmsg_linux.go
+++ b/src/pkg/syscall/sockcmsg_linux.go
@@ -6,33 +6,31 @@
 
 package syscall
 
-import (
-	"unsafe"
-)
+import "unsafe"
 
 // UnixCredentials encodes credentials into a socket control message
 // for sending to another process. This can be used for
 // authentication.
 func UnixCredentials(ucred *Ucred) []byte {
-	buf := make([]byte, CmsgSpace(SizeofUcred))
-	cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
-	cmsg.Level = SOL_SOCKET
-	cmsg.Type = SCM_CREDENTIALS
-	cmsg.SetLen(CmsgLen(SizeofUcred))
-	*((*Ucred)(cmsgData(cmsg))) = *ucred
-	return buf
+	b := make([]byte, CmsgSpace(SizeofUcred))
+	h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
+	h.Level = SOL_SOCKET
+	h.Type = SCM_CREDENTIALS
+	h.SetLen(CmsgLen(SizeofUcred))
+	*((*Ucred)(cmsgData(h))) = *ucred
+	return b
 }
 
 // ParseUnixCredentials decodes a socket control message that contains
 // credentials in a Ucred structure. To receive such a message, the
 // SO_PASSCRED option must be enabled on the socket.
-func ParseUnixCredentials(msg *SocketControlMessage) (*Ucred, error) {
-	if msg.Header.Level != SOL_SOCKET {
+func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
+	if m.Header.Level != SOL_SOCKET {
 		return nil, EINVAL
 	}
-	if msg.Header.Type != SCM_CREDENTIALS {
+	if m.Header.Type != SCM_CREDENTIALS {
 		return nil, EINVAL
 	}
-	ucred := *(*Ucred)(unsafe.Pointer(&msg.Data[0]))
+	ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
 	return &ucred, nil
 }
diff --git a/src/pkg/syscall/sockcmsg_unix.go b/src/pkg/syscall/sockcmsg_unix.go
index d279dec..bc7cf20 100644
--- a/src/pkg/syscall/sockcmsg_unix.go
+++ b/src/pkg/syscall/sockcmsg_unix.go
@@ -8,11 +8,9 @@
 
 package syscall
 
-import (
-	"unsafe"
-)
+import "unsafe"
 
-// Round the length of a raw sockaddr up to align it propery.
+// Round the length of a raw sockaddr up to align it properly.
 func cmsgAlignOf(salen int) int {
 	salign := sizeofPtr
 	// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
@@ -20,9 +18,6 @@ func cmsgAlignOf(salen int) int {
 	if darwinAMD64 {
 		salign = 4
 	}
-	if salen == 0 {
-		return salign
-	}
 	return (salen + salign - 1) & ^(salign - 1)
 }
 
@@ -38,77 +33,70 @@ func CmsgSpace(datalen int) int {
 	return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen)
 }
 
-func cmsgData(cmsg *Cmsghdr) unsafe.Pointer {
-	return unsafe.Pointer(uintptr(unsafe.Pointer(cmsg)) + SizeofCmsghdr)
+func cmsgData(h *Cmsghdr) unsafe.Pointer {
+	return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(SizeofCmsghdr)))
 }
 
+// SocketControlMessage represents a socket control message.
 type SocketControlMessage struct {
 	Header Cmsghdr
 	Data   []byte
 }
 
-func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, error) {
-	var (
-		h     *Cmsghdr
-		dbuf  []byte
-		e     error
-		cmsgs []SocketControlMessage
-	)
-
-	for len(buf) >= CmsgLen(0) {
-		h, dbuf, e = socketControlMessageHeaderAndData(buf)
-		if e != nil {
-			break
+// ParseSocketControlMessage parses b as an array of socket control
+// messages.
+func ParseSocketControlMessage(b []byte) ([]SocketControlMessage, error) {
+	var msgs []SocketControlMessage
+	i := 0
+	for i+CmsgLen(0) <= len(b) {
+		h, dbuf, err := socketControlMessageHeaderAndData(b[i:])
+		if err != nil {
+			return nil, err
 		}
-		m := SocketControlMessage{}
-		m.Header = *h
-		m.Data = dbuf[:int(h.Len)-cmsgAlignOf(SizeofCmsghdr)]
-		cmsgs = append(cmsgs, m)
-		buf = buf[cmsgAlignOf(int(h.Len)):]
+		m := SocketControlMessage{Header: *h, Data: dbuf}
+		msgs = append(msgs, m)
+		i += cmsgAlignOf(int(h.Len))
 	}
-
-	return cmsgs, e
+	return msgs, nil
 }
 
-func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, error) {
-	h := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
-	if h.Len < SizeofCmsghdr || int(h.Len) > len(buf) {
+func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) {
+	h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
+	if h.Len < SizeofCmsghdr || int(h.Len) > len(b) {
 		return nil, nil, EINVAL
 	}
-	return h, buf[cmsgAlignOf(SizeofCmsghdr):], nil
+	return h, b[cmsgAlignOf(SizeofCmsghdr):h.Len], nil
 }
 
 // UnixRights encodes a set of open file descriptors into a socket
 // control message for sending to another process.
 func UnixRights(fds ...int) []byte {
 	datalen := len(fds) * 4
-	buf := make([]byte, CmsgSpace(datalen))
-	cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
-	cmsg.Level = SOL_SOCKET
-	cmsg.Type = SCM_RIGHTS
-	cmsg.SetLen(CmsgLen(datalen))
-
-	data := uintptr(cmsgData(cmsg))
+	b := make([]byte, CmsgSpace(datalen))
+	h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
+	h.Level = SOL_SOCKET
+	h.Type = SCM_RIGHTS
+	h.SetLen(CmsgLen(datalen))
+	data := uintptr(cmsgData(h))
 	for _, fd := range fds {
 		*(*int32)(unsafe.Pointer(data)) = int32(fd)
 		data += 4
 	}
-
-	return buf
+	return b
 }
 
 // ParseUnixRights decodes a socket control message that contains an
 // integer array of open file descriptors from another process.
-func ParseUnixRights(msg *SocketControlMessage) ([]int, error) {
-	if msg.Header.Level != SOL_SOCKET {
+func ParseUnixRights(m *SocketControlMessage) ([]int, error) {
+	if m.Header.Level != SOL_SOCKET {
 		return nil, EINVAL
 	}
-	if msg.Header.Type != SCM_RIGHTS {
+	if m.Header.Type != SCM_RIGHTS {
 		return nil, EINVAL
 	}
-	fds := make([]int, len(msg.Data)>>2)
-	for i, j := 0, 0; i < len(msg.Data); i += 4 {
-		fds[j] = int(*(*int32)(unsafe.Pointer(&msg.Data[i])))
+	fds := make([]int, len(m.Data)>>2)
+	for i, j := 0, 0; i < len(m.Data); i += 4 {
+		fds[j] = int(*(*int32)(unsafe.Pointer(&m.Data[i])))
 		j++
 	}
 	return fds, nil
diff --git a/src/pkg/syscall/syscall.go b/src/pkg/syscall/syscall.go
index 335559f..f7473fd 100644
--- a/src/pkg/syscall/syscall.go
+++ b/src/pkg/syscall/syscall.go
@@ -3,10 +3,15 @@
 // license that can be found in the LICENSE file.
 
 // Package syscall contains an interface to the low-level operating system
-// primitives.  The details vary depending on the underlying system.
-// Its primary use is inside other packages that provide a more portable
-// interface to the system, such as "os", "time" and "net".  Use those
-// packages rather than this one if you can.
+// primitives.  The details vary depending on the underlying system, and
+// by default, godoc will display the syscall documentation for the current
+// system.  If you want godoc to display syscall documentation for another
+// system, set $GOOS and $GOARCH to the desired system.  For example, if
+// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
+// to freebsd and $GOARCH to arm.
+// The primary use of syscall is inside other packages that provide a more
+// portable interface to the system, such as "os", "time" and "net".  Use
+// those packages rather than this one if you can.
 // For details of the functions and data types in this package consult
 // the manuals for the appropriate operating system.
 // These calls return err == nil to indicate success; otherwise
@@ -14,18 +19,47 @@
 // On most systems, that error has type syscall.Errno.
 package syscall
 
-// StringByteSlice returns a NUL-terminated slice of bytes
-// containing the text of s.
+// StringByteSlice is deprecated. Use ByteSliceFromString instead.
+// If s contains a NUL byte this function panics instead of
+// returning an error.
 func StringByteSlice(s string) []byte {
+	a, err := ByteSliceFromString(s)
+	if err != nil {
+		panic("syscall: string with NUL passed to StringByteSlice")
+	}
+	return a
+}
+
+// ByteSliceFromString returns a NUL-terminated slice of bytes
+// containing the text of s. If s contains a NUL byte at any
+// location, it returns (nil, EINVAL).
+func ByteSliceFromString(s string) ([]byte, error) {
+	for i := 0; i < len(s); i++ {
+		if s[i] == 0 {
+			return nil, EINVAL
+		}
+	}
 	a := make([]byte, len(s)+1)
 	copy(a, s)
-	return a
+	return a, nil
 }
 
-// StringBytePtr returns a pointer to a NUL-terminated array of bytes
-// containing the text of s.
+// StringBytePtr is deprecated. Use BytePtrFromString instead.
+// If s contains a NUL byte this function panics instead of
+// returning an error.
 func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }
 
+// BytePtrFromString returns a pointer to a NUL-terminated array of
+// bytes containing the text of s. If s contains a NUL byte at any
+// location, it returns (nil, EINVAL).
+func BytePtrFromString(s string) (*byte, error) {
+	a, err := ByteSliceFromString(s)
+	if err != nil {
+		return nil, err
+	}
+	return &a[0], nil
+}
+
 // Single-word zero for use when we need a valid pointer to 0 bytes.
 // See mksyscall.pl.
 var _zero uintptr
diff --git a/src/pkg/syscall/syscall_bsd.go b/src/pkg/syscall/syscall_bsd.go
index c1a822a..a1e0d15 100644
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -20,6 +20,7 @@ import (
 /*
  * Pseudo-system calls
  */
+
 // The const provides a compile-time constant so clients
 // can adjust to whether there is a working Getwd and avoid
 // even linking this function into the binary.  See ../os/getwd.go.
@@ -304,6 +305,14 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
 	if err != nil {
 		return
 	}
+	if runtime.GOOS == "darwin" && len == 0 {
+		// Accepted socket has no address.
+		// This is likely due to a bug in xnu kernels,
+		// where instead of ECONNABORTED error socket
+		// is accepted, but has no address.
+		Close(nfd)
+		return 0, nil, ECONNABORTED
+	}
 	sa, err = anyToSockaddr(&rsa)
 	if err != nil {
 		Close(nfd)
@@ -354,10 +363,15 @@ func Socket(domain, typ, proto int) (fd int, err error) {
 	return
 }
 
-//sysnb socketpair(domain int, typ int, proto int, fd *[2]int) (err error)
+//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
 
 func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
-	err = socketpair(domain, typ, proto, &fd)
+	var fdx [2]int32
+	err = socketpair(domain, typ, proto, &fdx)
+	if err == nil {
+		fd[0] = int(fdx[0])
+		fd[1] = int(fdx[1])
+	}
 	return
 }
 
@@ -437,7 +451,9 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
 	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
 		return
 	}
-	from, err = anyToSockaddr(&rsa)
+	if rsa.Addr.Family != AF_UNSPEC {
+		from, err = anyToSockaddr(&rsa)
+	}
 	return
 }
 
@@ -553,16 +569,7 @@ func Sysctl(name string) (value string, err error) {
 		return "", err
 	}
 	if n == 0 {
-		// TODO(jsing): Remove after OpenBSD 5.2 release.
-		// Work around a bug that was fixed after OpenBSD 5.0.
-		// The length for kern.hostname and kern.domainname is always
-		// returned as 0 when a nil value is passed for oldp.
-		if runtime.GOOS == "openbsd" && (name == "kern.hostname" || name == "kern.domainname") {
-			// MAXHOSTNAMELEN
-			n = 256
-		} else {
-			return "", nil
-		}
+		return "", nil
 	}
 
 	// Read into buffer of that size.
@@ -605,6 +612,21 @@ func Utimes(path string, tv []Timeval) (err error) {
 	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
 }
 
+func UtimesNano(path string, ts []Timespec) error {
+	// TODO: The BSDs can do utimensat with SYS_UTIMENSAT but it
+	// isn't supported by darwin so this uses utimes instead
+	if len(ts) != 2 {
+		return EINVAL
+	}
+	// Not as efficient as it could be because Timespec and
+	// Timeval have different types in the different OSes
+	tv := [2]Timeval{
+		NsecToTimeval(TimespecToNsec(ts[0])),
+		NsecToTimeval(TimespecToNsec(ts[1])),
+	}
+	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
+
 //sys	futimes(fd int, timeval *[2]Timeval) (err error)
 func Futimes(fd int, tv []Timeval) (err error) {
 	if len(tv) != 2 {
diff --git a/src/pkg/syscall/syscall_darwin.go b/src/pkg/syscall/syscall_darwin.go
index c712f94..7fe406a 100644
--- a/src/pkg/syscall/syscall_darwin.go
+++ b/src/pkg/syscall/syscall_darwin.go
@@ -41,7 +41,10 @@ func nametomib(name string) (mib []_C_int, err error) {
 	n := uintptr(CTL_MAXNAME) * siz
 
 	p := (*byte)(unsafe.Pointer(&buf[0]))
-	bytes := StringByteSlice(name)
+	bytes, err := ByteSliceFromString(name)
+	if err != nil {
+		return nil, err
+	}
 
 	// Magic sysctl: "setting" 0.3 to a string name
 	// lets you read back the array of integers form.
@@ -94,7 +97,7 @@ func Pipe(p []int) (err error) {
 }
 
 // TODO
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	return -1, ENOSYS
 }
 
@@ -159,7 +162,7 @@ func Kill(pid int, signum Signal) (err error) { return kill(pid, int(signum), 1)
 //sys	Pathconf(path string, name int) (val int, err error)
 //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
 //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
-//sys	Read(fd int, p []byte) (n int, err error)
+//sys	read(fd int, p []byte) (n int, err error)
 //sys	Readlink(path string, buf []byte) (n int, err error)
 //sys	Rename(from string, to string) (err error)
 //sys	Revoke(path string) (err error)
@@ -188,11 +191,11 @@ func Kill(pid int, signum Signal) (err error) { return kill(pid, int(signum), 1)
 //sys	Undelete(path string) (err error)
 //sys	Unlink(path string) (err error)
 //sys	Unmount(path string, flags int) (err error)
-//sys	Write(fd int, p []byte) (n int, err error)
+//sys	write(fd int, p []byte) (n int, err error)
 //sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
 //sys   munmap(addr uintptr, length uintptr) (err error)
-//sys	read(fd int, buf *byte, nbuf int) (n int, err error)
-//sys	write(fd int, buf *byte, nbuf int) (n int, err error)
+//sys	readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
+//sys	writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
 
 /*
  * Unimplemented
@@ -331,7 +334,7 @@ func Kill(pid int, signum Signal) (err error) { return kill(pid, int(signum), 1)
 // __pthread_canceled
 // __semwait_signal
 // Proc_info
-// Sendfile
+// sendfile
 // Stat64_extended
 // Lstat64_extended
 // Fstat64_extended
diff --git a/src/pkg/syscall/syscall_freebsd.go b/src/pkg/syscall/syscall_freebsd.go
index 6556ea8..c7ffe22 100644
--- a/src/pkg/syscall/syscall_freebsd.go
+++ b/src/pkg/syscall/syscall_freebsd.go
@@ -41,7 +41,10 @@ func nametomib(name string) (mib []_C_int, err error) {
 	n := uintptr(CTL_MAXNAME) * siz
 
 	p := (*byte)(unsafe.Pointer(&buf[0]))
-	bytes := StringByteSlice(name)
+	bytes, err := ByteSliceFromString(name)
+	if err != nil {
+		return nil, err
+	}
 
 	// Magic sysctl: "setting" 0.3 to a string name
 	// lets you read back the array of integers form.
@@ -89,11 +92,6 @@ func Pipe(p []int) (err error) {
 	return
 }
 
-// TODO
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
-	return -1, ENOSYS
-}
-
 func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
 	var value IPMreqn
 	vallen := _Socklen(SizeofIPMreqn)
@@ -160,7 +158,7 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
 //sys	Pathconf(path string, name int) (val int, err error)
 //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
 //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
-//sys	Read(fd int, p []byte) (n int, err error)
+//sys	read(fd int, p []byte) (n int, err error)
 //sys	Readlink(path string, buf []byte) (n int, err error)
 //sys	Rename(from string, to string) (err error)
 //sys	Revoke(path string) (err error)
@@ -188,11 +186,11 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
 //sys	Undelete(path string) (err error)
 //sys	Unlink(path string) (err error)
 //sys	Unmount(path string, flags int) (err error)
-//sys	Write(fd int, p []byte) (n int, err error)
+//sys	write(fd int, p []byte) (n int, err error)
 //sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
 //sys   munmap(addr uintptr, length uintptr) (err error)
-//sys	read(fd int, buf *byte, nbuf int) (n int, err error)
-//sys	write(fd int, buf *byte, nbuf int) (n int, err error)
+//sys	readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
+//sys	writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
 
 /*
  * Unimplemented
@@ -331,7 +329,6 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
 // __pthread_canceled
 // __semwait_signal
 // Proc_info
-// Sendfile
 // Stat64_extended
 // Lstat64_extended
 // Fstat64_extended
diff --git a/src/pkg/syscall/syscall_freebsd_386.go b/src/pkg/syscall/syscall_freebsd_386.go
index fa322c5..ebd3d4c 100644
--- a/src/pkg/syscall/syscall_freebsd_386.go
+++ b/src/pkg/syscall/syscall_freebsd_386.go
@@ -4,6 +4,8 @@
 
 package syscall
 
+import "unsafe"
+
 func Getpagesize() int { return 4096 }
 
 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
@@ -41,4 +43,16 @@ func (cmsg *Cmsghdr) SetLen(length int) {
 	cmsg.Len = uint32(length)
 }
 
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	var writtenOut uint64 = 0
+	_, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr((*offset)>>32), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0)
+
+	written = int(writtenOut)
+
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
 func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // sic
diff --git a/src/pkg/syscall/syscall_freebsd_amd64.go b/src/pkg/syscall/syscall_freebsd_amd64.go
index 8c1ddf6..70c2ffb 100644
--- a/src/pkg/syscall/syscall_freebsd_amd64.go
+++ b/src/pkg/syscall/syscall_freebsd_amd64.go
@@ -4,6 +4,8 @@
 
 package syscall
 
+import "unsafe"
+
 func Getpagesize() int { return 4096 }
 
 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
@@ -40,3 +42,17 @@ func (msghdr *Msghdr) SetControllen(length int) {
 func (cmsg *Cmsghdr) SetLen(length int) {
 	cmsg.Len = uint32(length)
 }
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	var writtenOut uint64 = 0
+	_, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0, 0)
+
+	written = int(writtenOut)
+
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
diff --git a/src/pkg/syscall/syscall_freebsd_arm.go b/src/pkg/syscall/syscall_freebsd_arm.go
new file mode 100644
index 0000000..ab72871
--- /dev/null
+++ b/src/pkg/syscall/syscall_freebsd_arm.go
@@ -0,0 +1,58 @@
+// 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 syscall
+
+import "unsafe"
+
+func Getpagesize() int { return 4096 }
+
+func TimespecToNsec(ts Timespec) int64 { return ts.Sec*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+	ts.Sec = nsec / 1e9
+	ts.Nsec = int32(nsec % 1e9)
+	return
+}
+
+func TimevalToNsec(tv Timeval) int64 { return 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 = nsec / 1e9
+	return
+}
+
+func SetKevent(k *Kevent_t, fd, mode, flags int) {
+	k.Ident = uint32(fd)
+	k.Filter = int16(mode)
+	k.Flags = uint16(flags)
+}
+
+func (iov *Iovec) SetLen(length int) {
+	iov.Len = uint32(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+	msghdr.Controllen = uint32(length)
+}
+
+func (cmsg *Cmsghdr) SetLen(length int) {
+	cmsg.Len = uint32(length)
+}
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	var writtenOut uint64 = 0
+	_, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr((*offset)>>32), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0)
+
+	written = int(writtenOut)
+
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // sic
diff --git a/src/pkg/syscall/syscall_linux.go b/src/pkg/syscall/syscall_linux.go
index 89fb681..4f458be 100644
--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -18,16 +18,19 @@ import "unsafe"
  */
 
 //sys	open(path string, mode int, perm uint32) (fd int, err error)
+
 func Open(path string, mode int, perm uint32) (fd int, err error) {
 	return open(path, mode|O_LARGEFILE, perm)
 }
 
 //sys	openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
+
 func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
 	return openat(dirfd, path, flags|O_LARGEFILE, mode)
 }
 
 //sysnb	pipe(p *[2]_C_int) (err error)
+
 func Pipe(p []int) (err error) {
 	if len(p) != 2 {
 		return EINVAL
@@ -39,7 +42,21 @@ func Pipe(p []int) (err error) {
 	return
 }
 
+//sysnb pipe2(p *[2]_C_int, flags int) (err error)
+
+func Pipe2(p []int, flags int) (err error) {
+	if len(p) != 2 {
+		return EINVAL
+	}
+	var pp [2]_C_int
+	err = pipe2(&pp, flags)
+	p[0] = int(pp[0])
+	p[1] = int(pp[1])
+	return
+}
+
 //sys	utimes(path string, times *[2]Timeval) (err error)
+
 func Utimes(path string, tv []Timeval) (err error) {
 	if len(tv) != 2 {
 		return EINVAL
@@ -47,12 +64,37 @@ func Utimes(path string, tv []Timeval) (err error) {
 	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
 }
 
+//sys	utimensat(dirfd int, path string, times *[2]Timespec) (err error)
+
+func UtimesNano(path string, ts []Timespec) (err error) {
+	if len(ts) != 2 {
+		return EINVAL
+	}
+	err = utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])))
+	if err != ENOSYS {
+		return err
+	}
+	// If the utimensat syscall isn't available (utimensat was added to Linux
+	// in 2.6.22, Released, 8 July 2007) then fall back to utimes
+	var tv [2]Timeval
+	for i := 0; i < 2; i++ {
+		tv[i].Sec = ts[i].Sec
+		tv[i].Usec = ts[i].Nsec / 1000
+	}
+	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
+
 //sys	futimesat(dirfd int, path *byte, times *[2]Timeval) (err error)
+
 func Futimesat(dirfd int, path string, tv []Timeval) (err error) {
 	if len(tv) != 2 {
 		return EINVAL
 	}
-	return futimesat(dirfd, StringBytePtr(path), (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+	pathp, err := BytePtrFromString(path)
+	if err != nil {
+		return err
+	}
+	return futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
 }
 
 func Futimes(fd int, tv []Timeval) (err error) {
@@ -64,6 +106,7 @@ func Futimes(fd int, tv []Timeval) (err error) {
 const ImplementsGetwd = true
 
 //sys	Getcwd(buf []byte) (n int, err error)
+
 func Getwd() (wd string, err error) {
 	var buf [PathMax]byte
 	n, err := Getcwd(buf[0:])
@@ -173,6 +216,7 @@ func (w WaitStatus) TrapCause() int {
 }
 
 //sys	wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error)
+
 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
 	var status _C_int
 	wpid, err = wait4(pid, &status, options, rusage)
@@ -244,7 +288,7 @@ type SockaddrUnix struct {
 func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, error) {
 	name := sa.Name
 	n := len(name)
-	if n >= len(sa.raw.Path) || n == 0 {
+	if n >= len(sa.raw.Path) {
 		return 0, 0, EINVAL
 	}
 	sa.raw.Family = AF_UNIX
@@ -252,7 +296,10 @@ func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, error) {
 		sa.raw.Path[i] = int8(name[i])
 	}
 	// length is family (uint16), name, NUL.
-	sl := 2 + _Socklen(n) + 1
+	sl := _Socklen(2)
+	if n > 0 {
+		sl += _Socklen(n) + 1
+	}
 	if sa.raw.Path[0] == '@' {
 		sa.raw.Path[0] = 0
 		// Don't count trailing NUL for abstract address.
@@ -392,6 +439,21 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
 	return
 }
 
+func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
+	var rsa RawSockaddrAny
+	var len _Socklen = SizeofSockaddrAny
+	nfd, err = accept4(fd, &rsa, &len, flags)
+	if err != nil {
+		return
+	}
+	sa, err = anyToSockaddr(&rsa)
+	if err != nil {
+		Close(nfd)
+		nfd = 0
+	}
+	return
+}
+
 func Getsockname(fd int) (sa Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	var len _Socklen = SizeofSockaddrAny
@@ -435,7 +497,12 @@ func Socket(domain, typ, proto int) (fd int, err error) {
 }
 
 func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
-	err = socketpair(domain, typ, proto, &fd)
+	var fdx [2]int32
+	err = socketpair(domain, typ, proto, &fdx)
+	if err == nil {
+		fd[0] = int(fdx[0])
+		fd[1] = int(fdx[1])
+	}
 	return
 }
 
@@ -473,6 +540,13 @@ func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
 	return &value, err
 }
 
+func GetsockoptUcred(fd, level, opt int) (*Ucred, error) {
+	var value Ucred
+	vallen := _Socklen(SizeofUcred)
+	err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+	return &value, err
+}
+
 func SetsockoptInt(fd, level, opt int, value int) (err error) {
 	var n = int32(value)
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4)
@@ -512,7 +586,9 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
 	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
 		return
 	}
-	from, err = anyToSockaddr(&rsa)
+	if rsa.Addr.Family != AF_UNSPEC {
+		from, err = anyToSockaddr(&rsa)
+	}
 	return
 }
 
@@ -731,6 +807,10 @@ func PtraceCont(pid int, signal int) (err error) {
 	return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
 }
 
+func PtraceSyscall(pid int, signal int) (err error) {
+	return ptrace(PTRACE_SYSCALL, pid, 0, uintptr(signal))
+}
+
 func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
 
 func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
@@ -738,6 +818,7 @@ func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0)
 func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
 
 //sys	reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error)
+
 func Reboot(cmd int) (err error) {
 	return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
 }
@@ -777,13 +858,18 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
 }
 
 //sys	mount(source string, target string, fstype string, flags uintptr, data *byte) (err error)
+
 func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
 	// Certain file systems get rather angry and EINVAL if you give
 	// them an empty string of data, rather than NULL.
 	if data == "" {
 		return mount(source, target, fstype, flags, nil)
 	}
-	return mount(source, target, fstype, flags, StringBytePtr(data))
+	datap, err := BytePtrFromString(data)
+	if err != nil {
+		return err
+	}
+	return mount(source, target, fstype, flags, datap)
 }
 
 // Sendto
@@ -823,9 +909,9 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
 //sysnb	Getpgrp() (pid int)
 //sysnb	Getpid() (pid int)
 //sysnb	Getppid() (ppid int)
-//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error)
 //sysnb	Getrusage(who int, rusage *Rusage) (err error)
 //sysnb	Gettid() (tid int)
+//sys	Getxattr(path string, attr string, dest []byte) (sz int, err error)
 //sys	InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error)
 //sysnb	InotifyInit() (fd int, err error)
 //sysnb	InotifyInit1(flags int) (fd int, err error)
@@ -833,6 +919,7 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
 //sysnb	Kill(pid int, sig Signal) (err error)
 //sys	Klogctl(typ int, buf []byte) (n int, err error) = SYS_SYSLOG
 //sys	Link(oldpath string, newpath string) (err error)
+//sys	Listxattr(path string, dest []byte) (sz int, err error)
 //sys	Mkdir(path string, mode uint32) (err error)
 //sys	Mkdirat(dirfd int, path string, mode uint32) (err error)
 //sys	Mknod(path string, mode uint32, dev int) (err error)
@@ -840,18 +927,20 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
 //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
 //sys	Pause() (err error)
 //sys	PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
-//sys	Read(fd int, p []byte) (n int, err error)
+//sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
+//sys	read(fd int, p []byte) (n int, err error)
 //sys	Readlink(path string, buf []byte) (n int, err error)
+//sys	Removexattr(path string, attr string) (err error)
 //sys	Rename(oldpath string, newpath string) (err error)
 //sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
 //sys	Rmdir(path string) (err error)
 //sys	Setdomainname(p []byte) (err error)
 //sys	Sethostname(p []byte) (err error)
 //sysnb	Setpgid(pid int, pgid int) (err error)
-//sysnb	Setrlimit(resource int, rlim *Rlimit) (err error)
 //sysnb	Setsid() (pid int, err error)
 //sysnb	Settimeofday(tv *Timeval) (err error)
 //sysnb	Setuid(uid int) (err error)
+//sys	Setxattr(path string, attr string, data []byte, flags int) (err error)
 //sys	Symlink(oldpath string, newpath string) (err error)
 //sys	Sync()
 //sysnb	Sysinfo(info *Sysinfo_t) (err error)
@@ -866,10 +955,10 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
 //sys	Unshare(flags int) (err error)
 //sys	Ustat(dev int, ubuf *Ustat_t) (err error)
 //sys	Utime(path string, buf *Utimbuf) (err error)
-//sys	Write(fd int, p []byte) (n int, err error)
+//sys	write(fd int, p []byte) (n int, err error)
 //sys	exitThread(code int) (err error) = SYS_EXIT
-//sys	read(fd int, p *byte, np int) (n int, err error)
-//sys	write(fd int, p *byte, np int) (n int, err error)
+//sys	readlen(fd int, p *byte, np int) (n int, err error) = SYS_READ
+//sys	writelen(fd int, p *byte, np int) (n int, err error) = SYS_WRITE
 
 // mmap varies by architecture; see syscall_linux_*.go.
 //sys	munmap(addr uintptr, length uintptr) (err error)
@@ -931,7 +1020,6 @@ func Munmap(b []byte) (err error) {
 // Getitimer
 // Getpmsg
 // Getpriority
-// Getxattr
 // IoCancel
 // IoDestroy
 // IoGetevents
@@ -943,7 +1031,6 @@ func Munmap(b []byte) (err error) {
 // KexecLoad
 // Keyctl
 // Lgetxattr
-// Listxattr
 // Llistxattr
 // LookupDcookie
 // Lremovexattr
@@ -981,7 +1068,6 @@ func Munmap(b []byte) (err error) {
 // Readahead
 // Readv
 // RemapFilePages
-// Removexattr
 // RequestKey
 // RestartSyscall
 // RtSigaction
@@ -1010,7 +1096,6 @@ func Munmap(b []byte) (err error) {
 // SetThreadArea
 // SetTidAddress
 // Setpriority
-// Setxattr
 // Shmat
 // Shmctl
 // Shmdt
@@ -1036,5 +1121,4 @@ func Munmap(b []byte) (err error) {
 // Vmsplice
 // Vserver
 // Waitid
-// Writev
 // _Sysctl
diff --git a/src/pkg/syscall/syscall_linux_386.go b/src/pkg/syscall/syscall_linux_386.go
index b833db8..a0ded43 100644
--- a/src/pkg/syscall/syscall_linux_386.go
+++ b/src/pkg/syscall/syscall_linux_386.go
@@ -41,7 +41,7 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
 //sys	Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
 //sys	Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
 //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
-//sys	Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
+//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
@@ -67,6 +67,69 @@ func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int6
 	return mmap2(addr, length, prot, flags, fd, page)
 }
 
+type rlimit32 struct {
+	Cur uint32
+	Max uint32
+}
+
+//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT
+
+const rlimInf32 = ^uint32(0)
+const rlimInf64 = ^uint64(0)
+
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
+	err = prlimit(0, resource, rlim, nil)
+	if err != ENOSYS {
+		return err
+	}
+
+	rl := rlimit32{}
+	err = getrlimit(resource, &rl)
+	if err != nil {
+		return
+	}
+
+	if rl.Cur == rlimInf32 {
+		rlim.Cur = rlimInf64
+	} else {
+		rlim.Cur = uint64(rl.Cur)
+	}
+
+	if rl.Max == rlimInf32 {
+		rlim.Max = rlimInf64
+	} else {
+		rlim.Max = uint64(rl.Max)
+	}
+	return
+}
+
+//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
+
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
+	err = prlimit(0, resource, nil, rlim)
+	if err != ENOSYS {
+		return err
+	}
+
+	rl := rlimit32{}
+	if rlim.Cur == rlimInf64 {
+		rl.Cur = rlimInf32
+	} else if rlim.Cur < uint64(rlimInf32) {
+		rl.Cur = uint32(rlim.Cur)
+	} else {
+		return EINVAL
+	}
+	if rlim.Max == rlimInf64 {
+		rl.Max = rlimInf32
+	} else if rlim.Max < uint64(rlimInf32) {
+		rl.Max = uint32(rlim.Max)
+	} else {
+		return EINVAL
+	}
+
+	return setrlimit(resource, &rl)
+}
+
 // Underlying system call writes to newoffset via pointer.
 // Implemented in assembly to avoid allocation.
 func Seek(fd int, offset int64, whence int) (newoffset int64, err error)
@@ -101,6 +164,9 @@ const (
 	_GETSOCKOPT  = 15
 	_SENDMSG     = 16
 	_RECVMSG     = 17
+	_ACCEPT4     = 18
+	_RECVMMSG    = 19
+	_SENDMMSG    = 20
 )
 
 func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err Errno)
@@ -114,6 +180,14 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 	return
 }
 
+func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
+	fd, e := socketcall(_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0)
+	if e != 0 {
+		err = e
+	}
+	return
+}
+
 func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, e := rawsocketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
 	if e != 0 {
@@ -130,7 +204,7 @@ func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	return
 }
 
-func socketpair(domain int, typ int, flags int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, flags int, fd *[2]int32) (err error) {
 	_, e := rawsocketcall(_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e != 0 {
 		err = e
@@ -243,7 +317,11 @@ func Fstatfs(fd int, buf *Statfs_t) (err error) {
 }
 
 func Statfs(path string, buf *Statfs_t) (err error) {
-	_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
+	pathp, err := BytePtrFromString(path)
+	if err != nil {
+		return err
+	}
+	_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(pathp)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
 	if e != 0 {
 		err = e
 	}
diff --git a/src/pkg/syscall/syscall_linux_amd64.go b/src/pkg/syscall/syscall_linux_amd64.go
index 18b36b7..f4b73b2 100644
--- a/src/pkg/syscall/syscall_linux_amd64.go
+++ b/src/pkg/syscall/syscall_linux_amd64.go
@@ -12,6 +12,7 @@ package syscall
 //sysnb	Getegid() (egid int)
 //sysnb	Geteuid() (euid int)
 //sysnb	Getgid() (gid int)
+//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error)
 //sysnb	Getuid() (uid int)
 //sys	Ioperm(from int, num int, on int) (err error)
 //sys	Iopl(level int) (err error)
@@ -22,13 +23,14 @@ package syscall
 //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
 //sys	Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
 //sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
-//sys	Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
+//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)
+//sysnb	Setrlimit(resource int, rlim *Rlimit) (err error)
 //sysnb	Setreuid(ruid int, euid int) (err error)
 //sys	Shutdown(fd int, how int) (err error)
 //sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
@@ -37,6 +39,7 @@ package syscall
 //sys	SyncFileRange(fd int, off int64, n int64, flags int) (err error)
 //sys	Truncate(path string, length int64) (err error)
 //sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
+//sys	accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
 //sys	bind(s int, addr uintptr, addrlen _Socklen) (err error)
 //sys	connect(s int, addr uintptr, addrlen _Socklen) (err error)
 //sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
@@ -44,7 +47,7 @@ package syscall
 //sys	getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error)
 //sys	setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error)
 //sysnb	socket(domain int, typ int, proto int) (fd int, err error)
-//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int) (err error)
+//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
 //sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
 //sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
 //sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
diff --git a/src/pkg/syscall/syscall_linux_arm.go b/src/pkg/syscall/syscall_linux_arm.go
index 2f29079..7839d52 100644
--- a/src/pkg/syscall/syscall_linux_arm.go
+++ b/src/pkg/syscall/syscall_linux_arm.go
@@ -4,6 +4,8 @@
 
 package syscall
 
+import "unsafe"
+
 func Getpagesize() int { return 4096 }
 
 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
@@ -26,6 +28,7 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
 func Seek(fd int, offset int64, whence int) (newoffset int64, err error)
 
 //sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
+//sys	accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
 //sys	bind(s int, addr uintptr, addrlen _Socklen) (err error)
 //sys	connect(s int, addr uintptr, addrlen _Socklen) (err error)
 //sysnb	getgroups(n int, list *_Gid_t) (nn int, err error) = SYS_GETGROUPS32
@@ -37,7 +40,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error)
 //sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
 //sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
 //sys	sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error)
-//sysnb	socketpair(domain int, typ int, flags int, fd *[2]int) (err error)
+//sysnb	socketpair(domain int, typ int, flags int, fd *[2]int32) (err error)
 //sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
 //sys	sendmsg(s int, msg *Msghdr, flags int) (err error)
 
@@ -46,7 +49,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error)
 //sys	Chown(path string, uid int, gid int) (err error) = SYS_CHOWN32
 //sys	Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
 //sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
-//sys	Fstatfs(fd int, buf *Statfs_t) (err error) = SYS_FSTATFS64
 //sysnb	Getegid() (egid int) = SYS_GETEGID32
 //sysnb	Geteuid() (euid int) = SYS_GETEUID32
 //sysnb	Getgid() (gid int) = SYS_GETGID32
@@ -54,7 +56,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error)
 //sys	Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32
 //sys	Listen(s int, n int) (err error)
 //sys	Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
-//sys	Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
+//sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
 //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
@@ -66,7 +68,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error)
 //sys	Shutdown(fd int, how int) (err error)
 //sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
 //sys	Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
-//sys	Statfs(path string, buf *Statfs_t) (err error) = SYS_STATFS64
 
 // Vsyscalls on amd64.
 //sysnb	Gettimeofday(tv *Timeval) (err error)
@@ -79,6 +80,26 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error)
 
 //sys	mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
 
+func Fstatfs(fd int, buf *Statfs_t) (err error) {
+	_, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
+	if e != 0 {
+		err = e
+	}
+	return
+}
+
+func Statfs(path string, buf *Statfs_t) (err error) {
+	pathp, err := BytePtrFromString(path)
+	if err != nil {
+		return err
+	}
+	_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(pathp)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
+	if e != 0 {
+		err = e
+	}
+	return
+}
+
 func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
 	page := uintptr(offset / 4096)
 	if offset != int64(page)*4096 {
@@ -87,10 +108,72 @@ func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int6
 	return mmap2(addr, length, prot, flags, fd, page)
 }
 
-// TODO(kaib): add support for tracing
-func (r *PtraceRegs) PC() uint64 { return 0 }
+type rlimit32 struct {
+	Cur uint32
+	Max uint32
+}
+
+//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT
+
+const rlimInf32 = ^uint32(0)
+const rlimInf64 = ^uint64(0)
+
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
+	err = prlimit(0, resource, rlim, nil)
+	if err != ENOSYS {
+		return err
+	}
+
+	rl := rlimit32{}
+	err = getrlimit(resource, &rl)
+	if err != nil {
+		return
+	}
+
+	if rl.Cur == rlimInf32 {
+		rlim.Cur = rlimInf64
+	} else {
+		rlim.Cur = uint64(rl.Cur)
+	}
+
+	if rl.Max == rlimInf32 {
+		rlim.Max = rlimInf64
+	} else {
+		rlim.Max = uint64(rl.Max)
+	}
+	return
+}
+
+//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
+
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
+	err = prlimit(0, resource, nil, rlim)
+	if err != ENOSYS {
+		return err
+	}
+
+	rl := rlimit32{}
+	if rlim.Cur == rlimInf64 {
+		rl.Cur = rlimInf32
+	} else if rlim.Cur < uint64(rlimInf32) {
+		rl.Cur = uint32(rlim.Cur)
+	} else {
+		return EINVAL
+	}
+	if rlim.Max == rlimInf64 {
+		rl.Max = rlimInf32
+	} else if rlim.Max < uint64(rlimInf32) {
+		rl.Max = uint32(rlim.Max)
+	} else {
+		return EINVAL
+	}
+
+	return setrlimit(resource, &rl)
+}
+
+func (r *PtraceRegs) PC() uint64 { return uint64(r.Uregs[15]) }
 
-func (r *PtraceRegs) SetPC(pc uint64) {}
+func (r *PtraceRegs) SetPC(pc uint64) { r.Uregs[15] = uint32(pc) }
 
 func (iov *Iovec) SetLen(length int) {
 	iov.Len = uint32(length)
diff --git a/src/pkg/syscall/syscall_netbsd.go b/src/pkg/syscall/syscall_netbsd.go
index 3f6d16f..b0fa111 100644
--- a/src/pkg/syscall/syscall_netbsd.go
+++ b/src/pkg/syscall/syscall_netbsd.go
@@ -22,14 +22,72 @@ type SockaddrDatalink struct {
 	Nlen   uint8
 	Alen   uint8
 	Slen   uint8
-	Data   [24]int8
+	Data   [12]int8
 	raw    RawSockaddrDatalink
 }
 
 func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
 
+func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) {
+	var olen uintptr
+
+	// Get a list of all sysctl nodes below the given MIB by performing
+	// a sysctl for the given MIB with CTL_QUERY appended.
+	mib = append(mib, CTL_QUERY)
+	qnode := Sysctlnode{Flags: SYSCTL_VERS_1}
+	qp := (*byte)(unsafe.Pointer(&qnode))
+	sz := unsafe.Sizeof(qnode)
+	if err = sysctl(mib, nil, &olen, qp, sz); err != nil {
+		return nil, err
+	}
+
+	// Now that we know the size, get the actual nodes.
+	nodes = make([]Sysctlnode, olen/sz)
+	np := (*byte)(unsafe.Pointer(&nodes[0]))
+	if err = sysctl(mib, np, &olen, qp, sz); err != nil {
+		return nil, err
+	}
+
+	return nodes, nil
+}
+
 func nametomib(name string) (mib []_C_int, err error) {
-	return nil, EINVAL
+
+	// Split name into components.
+	var parts []string
+	last := 0
+	for i := 0; i < len(name); i++ {
+		if name[i] == '.' {
+			parts = append(parts, name[last:i])
+			last = i + 1
+		}
+	}
+	parts = append(parts, name[last:])
+
+	// Discover the nodes and construct the MIB OID.
+	for partno, part := range parts {
+		nodes, err := sysctlNodes(mib)
+		if err != nil {
+			return nil, err
+		}
+		for _, node := range nodes {
+			n := make([]byte, 0)
+			for i := range node.Name {
+				if node.Name[i] != 0 {
+					n = append(n, byte(node.Name[i]))
+				}
+			}
+			if string(n) == part {
+				mib = append(mib, _C_int(node.Num))
+				break
+			}
+		}
+		if len(mib) != partno+1 {
+			return nil, EINVAL
+		}
+	}
+
+	return mib, nil
 }
 
 // ParseDirent parses up to max directory entries in buf,
@@ -60,15 +118,12 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
 	return origlen - len(buf), count, names
 }
 
-//sysnb pipe2(p *[2]_C_int, flags _C_int) (err error)
+//sysnb pipe() (fd1 int, fd2 int, err error)
 func Pipe(p []int) (err error) {
 	if len(p) != 2 {
 		return EINVAL
 	}
-	var pp [2]_C_int
-	err = pipe2(&pp, 0)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	p[0], p[1], err = pipe()
 	return
 }
 
@@ -78,7 +133,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
 }
 
 // TODO
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	return -1, ENOSYS
 }
 
@@ -133,7 +188,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
 //sys	Pathconf(path string, name int) (val int, err error)
 //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
 //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
-//sys	Read(fd int, p []byte) (n int, err error)
+//sys	read(fd int, p []byte) (n int, err error)
 //sys	Readlink(path string, buf []byte) (n int, err error)
 //sys	Rename(from string, to string) (err error)
 //sys	Revoke(path string) (err error)
@@ -158,11 +213,11 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
 //sys	Umask(newmask int) (oldmask int)
 //sys	Unlink(path string) (err error)
 //sys	Unmount(path string, flags int) (err error)
-//sys	Write(fd int, p []byte) (n int, err error)
+//sys	write(fd int, p []byte) (n int, err error)
 //sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
 //sys	munmap(addr uintptr, length uintptr) (err error)
-//sys	read(fd int, buf *byte, nbuf int) (n int, err error)
-//sys	write(fd int, buf *byte, nbuf int) (n int, err error)
+//sys	readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
+//sys	writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
 
 /*
  * Unimplemented
diff --git a/src/pkg/syscall/syscall_netbsd_386.go b/src/pkg/syscall/syscall_netbsd_386.go
index 3c4c693..2dbff07 100644
--- a/src/pkg/syscall/syscall_netbsd_386.go
+++ b/src/pkg/syscall/syscall_netbsd_386.go
@@ -9,7 +9,7 @@ func Getpagesize() int { return 4096 }
 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
 
 func NsecToTimespec(nsec int64) (ts Timespec) {
-	ts.Sec = int32(nsec / 1e9)
+	ts.Sec = int64(nsec / 1e9)
 	ts.Nsec = int32(nsec % 1e9)
 	return
 }
@@ -19,14 +19,14 @@ func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)
 func NsecToTimeval(nsec int64) (tv Timeval) {
 	nsec += 999 // round up to microsecond
 	tv.Usec = int32(nsec % 1e9 / 1e3)
-	tv.Sec = int32(nsec / 1e9)
+	tv.Sec = int64(nsec / 1e9)
 	return
 }
 
 func SetKevent(k *Kevent_t, fd, mode, flags int) {
 	k.Ident = uint32(fd)
-	k.Filter = int16(mode)
-	k.Flags = uint16(flags)
+	k.Filter = uint32(mode)
+	k.Flags = uint32(flags)
 }
 
 func (iov *Iovec) SetLen(length int) {
diff --git a/src/pkg/syscall/syscall_netbsd_amd64.go b/src/pkg/syscall/syscall_netbsd_amd64.go
index 17485b1..5784db9 100644
--- a/src/pkg/syscall/syscall_netbsd_amd64.go
+++ b/src/pkg/syscall/syscall_netbsd_amd64.go
@@ -9,8 +9,8 @@ func Getpagesize() int { return 4096 }
 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
 
 func NsecToTimespec(nsec int64) (ts Timespec) {
-	ts.Sec = int32(nsec / 1e9)
-	ts.Nsec = nsec % 1e9
+	ts.Sec = int64(nsec / 1e9)
+	ts.Nsec = int64(nsec % 1e9)
 	return
 }
 
@@ -18,15 +18,15 @@ func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)
 
 func NsecToTimeval(nsec int64) (tv Timeval) {
 	nsec += 999 // round up to microsecond
-	tv.Usec = nsec % 1e9 / 1e3
+	tv.Usec = int32(nsec % 1e9 / 1e3)
 	tv.Sec = int64(nsec / 1e9)
 	return
 }
 
 func SetKevent(k *Kevent_t, fd, mode, flags int) {
 	k.Ident = uint64(fd)
-	k.Filter = int16(mode)
-	k.Flags = uint16(flags)
+	k.Filter = uint32(mode)
+	k.Flags = uint32(flags)
 }
 
 func (iov *Iovec) SetLen(length int) {
diff --git a/src/pkg/syscall/syscall_netbsd_arm.go b/src/pkg/syscall/syscall_netbsd_arm.go
new file mode 100644
index 0000000..659698a
--- /dev/null
+++ b/src/pkg/syscall/syscall_netbsd_arm.go
@@ -0,0 +1,42 @@
+// 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 syscall
+
+func Getpagesize() int { return 4096 }
+
+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
+}
+
+func SetKevent(k *Kevent_t, fd, mode, flags int) {
+	k.Ident = uint32(fd)
+	k.Filter = uint32(mode)
+	k.Flags = uint32(flags)
+}
+
+func (iov *Iovec) SetLen(length int) {
+	iov.Len = uint32(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+	msghdr.Controllen = uint32(length)
+}
+
+func (cmsg *Cmsghdr) SetLen(length int) {
+	cmsg.Len = uint32(length)
+}
diff --git a/src/pkg/syscall/syscall_openbsd.go b/src/pkg/syscall/syscall_openbsd.go
index 7cd1191..a146dca 100644
--- a/src/pkg/syscall/syscall_openbsd.go
+++ b/src/pkg/syscall/syscall_openbsd.go
@@ -91,7 +91,7 @@ func Pipe(p []int) (err error) {
 }
 
 // TODO
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	return -1, ENOSYS
 }
 
@@ -149,7 +149,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
 //sys	Pathconf(path string, name int) (val int, err error)
 //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
 //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
-//sys	Read(fd int, p []byte) (n int, err error)
+//sys	read(fd int, p []byte) (n int, err error)
 //sys	Readlink(path string, buf []byte) (n int, err error)
 //sys	Rename(from string, to string) (err error)
 //sys	Revoke(path string) (err error)
@@ -176,11 +176,11 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
 //sys	Umask(newmask int) (oldmask int)
 //sys	Unlink(path string) (err error)
 //sys	Unmount(path string, flags int) (err error)
-//sys	Write(fd int, p []byte) (n int, err error)
+//sys	write(fd int, p []byte) (n int, err error)
 //sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
 //sys	munmap(addr uintptr, length uintptr) (err error)
-//sys	read(fd int, buf *byte, nbuf int) (n int, err error)
-//sys	write(fd int, buf *byte, nbuf int) (n int, err error)
+//sys	readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
+//sys	writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
 
 /*
  * Unimplemented
diff --git a/src/pkg/syscall/syscall_plan9.go b/src/pkg/syscall/syscall_plan9.go
index 122a96f..bc25057 100644
--- a/src/pkg/syscall/syscall_plan9.go
+++ b/src/pkg/syscall/syscall_plan9.go
@@ -23,13 +23,28 @@ func (e ErrorString) Error() string { return string(e) }
 // NewError converts s to an ErrorString, which satisfies the Error interface.
 func NewError(s string) error { return ErrorString(s) }
 
+func (e ErrorString) Temporary() bool {
+	return e == EINTR || e == EMFILE || e.Timeout()
+}
+
+func (e ErrorString) Timeout() bool {
+	return e == EBUSY || e == ETIMEDOUT
+}
+
+// A Note is a string describing a process note.
+// It implements the os.Signal interface.
+type Note string
+
+func (n Note) Signal() {}
+
+func (n Note) String() string {
+	return string(n)
+}
+
 var (
 	Stdin  = 0
 	Stdout = 1
 	Stderr = 2
-
-	EAFNOSUPPORT = NewError("address family not supported by protocol")
-	EISDIR       = NewError("file is a directory")
 )
 
 // For testing: clients can set this flag to force
@@ -67,25 +82,10 @@ func errstr() string {
 	return cstring(buf[:])
 }
 
-func Getpagesize() int { return 4096 }
+// Implemented in assembly to import from runtime.
+func exit(int)
 
-//sys	exits(msg *byte)
-func Exits(msg *string) {
-	if msg == nil {
-		exits(nil)
-	}
-
-	exits(StringBytePtr(*msg))
-}
-
-func Exit(code int) {
-	if code == 0 {
-		Exits(nil)
-	}
-
-	msg := itoa(code)
-	Exits(&msg)
-}
+func Exit(code int) { exit(code) }
 
 func readnum(path string) (uint, error) {
 	var b [12]byte
@@ -120,13 +120,22 @@ func Getppid() (ppid int) {
 }
 
 func Read(fd int, p []byte) (n int, err error) {
-	return Pread(fd, p, -1)
+	n, err = Pread(fd, p, -1)
+	if raceenabled && err == nil {
+		raceAcquire(unsafe.Pointer(&ioSync))
+	}
+	return
 }
 
 func Write(fd int, p []byte) (n int, err error) {
+	if raceenabled {
+		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	}
 	return Pwrite(fd, p, -1)
 }
 
+var ioSync int64
+
 func Getwd() (wd string, err error) {
 	fd, e := Open(".", O_RDONLY)
 
@@ -240,19 +249,27 @@ func Await(w *Waitmsg) (err error) {
 }
 
 func Unmount(name, old string) (err error) {
-	oldp := uintptr(unsafe.Pointer(StringBytePtr(old)))
+	oldp, err := BytePtrFromString(old)
+	if err != nil {
+		return err
+	}
+	oldptr := uintptr(unsafe.Pointer(oldp))
 
 	var r0 uintptr
 	var e ErrorString
 
 	// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
 	if name == "" {
-		r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldp, 0)
+		r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
 	} else {
-		r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(name))), oldp, 0)
+		namep, err := BytePtrFromString(name)
+		if err != nil {
+			return err
+		}
+		r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
 	}
 
-	if int(r0) == -1 {
+	if int32(r0) == -1 {
 		err = e
 	}
 	return
@@ -300,29 +317,12 @@ func DecodeBintime(b []byte) (nsec int64, err error) {
 	return
 }
 
-func Gettimeofday(tv *Timeval) (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
-	var nsec int64
-
-	fd, e := Open("/dev/bintime", O_RDONLY)
+func Gettimeofday(tv *Timeval) error {
+	nsec, e := nanotime()
 	if e != nil {
 		return e
 	}
-	defer Close(fd)
-
-	if _, e = Pread(fd, b[:], 0); e != nil {
-		return e
-	}
-
-	if nsec, e = DecodeBintime(b[:]); e != nil {
-		return e
-	}
 	*tv = NsecToTimeval(nsec)
-
 	return e
 }
 
@@ -335,14 +335,6 @@ func Getgroups() (gids []int, err error) {
 	return make([]int, 0), nil
 }
 
-type Signal int
-
-func (s Signal) Signal() {}
-
-func (s Signal) String() string {
-	return ""
-}
-
 //sys	Dup(oldfd int, newfd int) (fd int, err error)
 //sys	Open(path string, mode int) (fd int, err error)
 //sys	Create(path string, mode int, perm uint32) (fd int, err error)
diff --git a/src/pkg/syscall/syscall_plan9_386.go b/src/pkg/syscall/syscall_plan9_386.go
index e82b540..7357e0b 100644
--- a/src/pkg/syscall/syscall_plan9_386.go
+++ b/src/pkg/syscall/syscall_plan9_386.go
@@ -3,3 +3,30 @@
 // 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
new file mode 100644
index 0000000..9387db3
--- /dev/null
+++ b/src/pkg/syscall/syscall_plan9_amd64.go
@@ -0,0 +1,14 @@
+// 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/syscall_unix.go b/src/pkg/syscall/syscall_unix.go
index d4e02f6..fee1fc4 100644
--- a/src/pkg/syscall/syscall_unix.go
+++ b/src/pkg/syscall/syscall_unix.go
@@ -127,3 +127,27 @@ func (s Signal) String() string {
 	}
 	return "signal " + itoa(int(s))
 }
+
+func Read(fd int, p []byte) (n int, err error) {
+	n, err = read(fd, p)
+	if raceenabled && err == nil {
+		raceAcquire(unsafe.Pointer(&ioSync))
+	}
+	return
+}
+
+func Write(fd int, p []byte) (n int, err error) {
+	if raceenabled {
+		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	}
+	return write(fd, p)
+}
+
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	if raceenabled {
+		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	}
+	return sendfile(outfd, infd, offset, count)
+}
+
+var ioSync int64
diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go
index 6b544f1..d7c3265 100644
--- a/src/pkg/syscall/syscall_windows.go
+++ b/src/pkg/syscall/syscall_windows.go
@@ -7,6 +7,8 @@
 package syscall
 
 import (
+	errorspkg "errors"
+	"sync"
 	"unicode/utf16"
 	"unsafe"
 )
@@ -15,46 +17,28 @@ type Handle uintptr
 
 const InvalidHandle = ^Handle(0)
 
-/*
-
-small demo to detect version of windows you are running:
-
-package main
-
-import (
-	"syscall"
-)
-
-func abort(funcname string, err error) {
-	panic(funcname + " failed: " + err.Error())
-}
-
-func print_version(v uint32) {
-	major := byte(v)
-	minor := uint8(v >> 8)
-	build := uint16(v >> 16)
-	print("windows version ", major, ".", minor, " (Build ", build, ")\n")
-}
-
-func main() {
-	h, err := syscall.LoadLibrary("kernel32.dll")
-	if err != nil {
-		abort("LoadLibrary", err)
-	}
-	defer syscall.FreeLibrary(h)
-	proc, err := syscall.GetProcAddress(h, "GetVersion")
+// StringToUTF16 is deprecated. Use UTF16FromString instead.
+// If s contains a NUL byte this function panics instead of
+// returning an error.
+func StringToUTF16(s string) []uint16 {
+	a, err := UTF16FromString(s)
 	if err != nil {
-		abort("GetProcAddress", err)
+		panic("syscall: string with NUL passed to StringToUTF16")
 	}
-	r, _, _ := syscall.Syscall(uintptr(proc), 0, 0, 0, 0)
-	print_version(uint32(r))
+	return a
 }
 
-*/
-
-// StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s,
-// with a terminating NUL added.
-func StringToUTF16(s string) []uint16 { return utf16.Encode([]rune(s + "\x00")) }
+// UTF16FromString returns the UTF-16 encoding of the UTF-8 string
+// s, with a terminating NUL added. If s contains a NUL byte at any
+// location, it returns (nil, EINVAL).
+func UTF16FromString(s string) ([]uint16, error) {
+	for i := 0; i < len(s); i++ {
+		if s[i] == 0 {
+			return nil, EINVAL
+		}
+	}
+	return utf16.Encode([]rune(s + "\x00")), nil
+}
 
 // UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s,
 // with a terminating NUL removed.
@@ -68,10 +52,22 @@ func UTF16ToString(s []uint16) string {
 	return string(utf16.Decode(s))
 }
 
-// StringToUTF16Ptr returns pointer to the UTF-16 encoding of
-// the UTF-8 string s, with a terminating NUL added.
+// StringToUTF16Ptr is deprecated. Use UTF16PtrFromString instead.
+// If s contains a NUL byte this function panics instead of
+// returning an error.
 func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] }
 
+// UTF16PtrFromString returns pointer to the UTF-16 encoding of
+// the UTF-8 string s, with a terminating NUL added. If s
+// contains a NUL byte at any location, it returns (nil, EINVAL).
+func UTF16PtrFromString(s string) (*uint16, error) {
+	a, err := UTF16FromString(s)
+	if err != nil {
+		return nil, err
+	}
+	return &a[0], nil
+}
+
 func Getpagesize() int { return 4096 }
 
 // Errno is the Windows error number.
@@ -90,9 +86,10 @@ func (e Errno) Error() string {
 	b := make([]uint16, 300)
 	n, err := FormatMessage(flags, 0, uint32(e), langid(LANG_ENGLISH, SUBLANG_ENGLISH_US), b, nil)
 	if err != nil {
-		// TODO(brainman): Call FormatMessage again asking for "native" error message.
-		// http://code.google.com/p/go/issues/detail?id=3376 must be resolved first.
-		return "winapi error #" + itoa(int(e))
+		n, err = FormatMessage(flags, 0, uint32(e), 0, b, nil)
+		if err != nil {
+			return "winapi error #" + itoa(int(e))
+		}
 	}
 	// trim terminating \r and \n
 	for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
@@ -111,7 +108,7 @@ func (e Errno) Timeout() bool {
 // Converts a Go function to a function pointer conforming
 // to the stdcall calling convention.  This is useful when
 // interoperating with Windows code requiring callbacks.
-// Implemented in ../runtime/windows/syscall.goc
+// Implemented in ../runtime/syscall_windows.goc
 func NewCallback(fn interface{}) uintptr
 
 // windows api calls
@@ -147,6 +144,7 @@ func NewCallback(fn interface{}) uintptr
 //sys	GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error)
 //sys	PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error)
 //sys	CancelIo(s Handle) (err error)
+//sys	CancelIoEx(s Handle, o *Overlapped) (err error)
 //sys	CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW
 //sys	OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error)
 //sys	TerminateProcess(handle Handle, exitcode uint32) (err error)
@@ -201,7 +199,10 @@ func NewCallback(fn interface{}) uintptr
 //sys	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) = advapi32.RegQueryInfoKeyW
 //sys	RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW
 //sys	RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW
-//sys	getCurrentProcessId() (pid uint32) = kernel32.getCurrentProcessId
+//sys	getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId
+//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
 
 // syscall interface implementation for other packages
 
@@ -218,6 +219,10 @@ func Open(path string, mode int, perm uint32) (fd Handle, err error) {
 	if len(path) == 0 {
 		return InvalidHandle, ERROR_FILE_NOT_FOUND
 	}
+	pathp, err := UTF16PtrFromString(path)
+	if err != nil {
+		return InvalidHandle, err
+	}
 	var access uint32
 	switch mode & (O_RDONLY | O_WRONLY | O_RDWR) {
 	case O_RDONLY:
@@ -252,7 +257,7 @@ func Open(path string, mode int, perm uint32) (fd Handle, err error) {
 	default:
 		createmode = OPEN_EXISTING
 	}
-	h, e := CreateFile(StringToUTF16Ptr(path), access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0)
+	h, e := CreateFile(pathp, access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0)
 	return h, e
 }
 
@@ -266,10 +271,16 @@ func Read(fd Handle, p []byte) (n int, err error) {
 		}
 		return 0, e
 	}
+	if raceenabled {
+		raceAcquire(unsafe.Pointer(&ioSync))
+	}
 	return int(done), nil
 }
 
 func Write(fd Handle, p []byte) (n int, err error) {
+	if raceenabled {
+		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	}
 	var done uint32
 	e := WriteFile(fd, p, &done, nil)
 	if e != nil {
@@ -278,6 +289,8 @@ func Write(fd Handle, p []byte) (n int, err error) {
 	return int(done), nil
 }
 
+var ioSync int64
+
 func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
 	var w uint32
 	switch whence {
@@ -330,24 +343,46 @@ func Getwd() (wd string, err error) {
 }
 
 func Chdir(path string) (err error) {
-	return SetCurrentDirectory(&StringToUTF16(path)[0])
+	pathp, err := UTF16PtrFromString(path)
+	if err != nil {
+		return err
+	}
+	return SetCurrentDirectory(pathp)
 }
 
 func Mkdir(path string, mode uint32) (err error) {
-	return CreateDirectory(&StringToUTF16(path)[0], nil)
+	pathp, err := UTF16PtrFromString(path)
+	if err != nil {
+		return err
+	}
+	return CreateDirectory(pathp, nil)
 }
 
 func Rmdir(path string) (err error) {
-	return RemoveDirectory(&StringToUTF16(path)[0])
+	pathp, err := UTF16PtrFromString(path)
+	if err != nil {
+		return err
+	}
+	return RemoveDirectory(pathp)
 }
 
 func Unlink(path string) (err error) {
-	return DeleteFile(&StringToUTF16(path)[0])
+	pathp, err := UTF16PtrFromString(path)
+	if err != nil {
+		return err
+	}
+	return DeleteFile(pathp)
 }
 
 func Rename(oldpath, newpath string) (err error) {
-	from := &StringToUTF16(oldpath)[0]
-	to := &StringToUTF16(newpath)[0]
+	from, err := UTF16PtrFromString(oldpath)
+	if err != nil {
+		return err
+	}
+	to, err := UTF16PtrFromString(newpath)
+	if err != nil {
+		return err
+	}
 	return MoveFile(from, to)
 }
 
@@ -403,7 +438,11 @@ func Utimes(path string, tv []Timeval) (err error) {
 	if len(tv) != 2 {
 		return EINVAL
 	}
-	h, e := CreateFile(StringToUTF16Ptr(path),
+	pathp, e := UTF16PtrFromString(path)
+	if e != nil {
+		return e
+	}
+	h, e := CreateFile(pathp,
 		FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
 		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
 	if e != nil {
@@ -415,6 +454,26 @@ func Utimes(path string, tv []Timeval) (err error) {
 	return SetFileTime(h, nil, &a, &w)
 }
 
+func UtimesNano(path string, ts []Timespec) (err error) {
+	if len(ts) != 2 {
+		return EINVAL
+	}
+	pathp, e := UTF16PtrFromString(path)
+	if e != nil {
+		return e
+	}
+	h, e := CreateFile(pathp,
+		FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
+		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
+	if e != nil {
+		return e
+	}
+	defer Close(h)
+	a := NsecToFiletime(TimespecToNsec(ts[0]))
+	w := NsecToFiletime(TimespecToNsec(ts[1]))
+	return SetFileTime(h, nil, &a, &w)
+}
+
 func Fsync(fd Handle) (err error) {
 	return FlushFileBuffers(fd)
 }
@@ -423,7 +482,10 @@ func Chmod(path string, mode uint32) (err error) {
 	if mode == 0 {
 		return EINVAL
 	}
-	p := StringToUTF16Ptr(path)
+	p, e := UTF16PtrFromString(path)
+	if e != nil {
+		return e
+	}
 	attrs, e := GetFileAttributes(p)
 	if e != nil {
 		return e
@@ -436,32 +498,41 @@ func Chmod(path string, mode uint32) (err error) {
 	return SetFileAttributes(p, attrs)
 }
 
+func LoadCancelIoEx() error {
+	return procCancelIoEx.Find()
+}
+
 // net api calls
 
+const socket_error = uintptr(^uint32(0))
+
 //sys	WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup
-//sys	WSACleanup() (err error) [failretval==-1] = ws2_32.WSACleanup
-//sys	WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==-1] = ws2_32.WSAIoctl
+//sys	WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup
+//sys	WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==socket_error] = ws2_32.WSAIoctl
 //sys	socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket
-//sys	Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==-1] = ws2_32.setsockopt
-//sys	bind(s Handle, name uintptr, namelen int32) (err error) [failretval==-1] = ws2_32.bind
-//sys	connect(s Handle, name uintptr, namelen int32) (err error) [failretval==-1] = ws2_32.connect
-//sys	getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==-1] = ws2_32.getsockname
-//sys	getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==-1] = ws2_32.getpeername
-//sys	listen(s Handle, backlog int32) (err error) [failretval==-1] = ws2_32.listen
-//sys	shutdown(s Handle, how int32) (err error) [failretval==-1] = ws2_32.shutdown
-//sys	Closesocket(s Handle) (err error) [failretval==-1] = ws2_32.closesocket
+//sys	Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt
+//sys	Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt
+//sys	bind(s Handle, name uintptr, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind
+//sys	connect(s Handle, name uintptr, namelen int32) (err error) [failretval==socket_error] = ws2_32.connect
+//sys	getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockname
+//sys	getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getpeername
+//sys	listen(s Handle, backlog int32) (err error) [failretval==socket_error] = ws2_32.listen
+//sys	shutdown(s Handle, how int32) (err error) [failretval==socket_error] = ws2_32.shutdown
+//sys	Closesocket(s Handle) (err error) [failretval==socket_error] = ws2_32.closesocket
 //sys	AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx
 //sys	GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs
-//sys	WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==-1] = ws2_32.WSARecv
-//sys	WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==-1] = ws2_32.WSASend
-//sys	WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32,  from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==-1] = ws2_32.WSARecvFrom
-//sys	WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32,  overlapped *Overlapped, croutine *byte) (err error) [failretval==-1] = ws2_32.WSASendTo
+//sys	WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecv
+//sys	WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend
+//sys	WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32,  from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecvFrom
+//sys	WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32,  overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASendTo
 //sys	GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname
 //sys	GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname
 //sys	Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs
 //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	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
 //sys	GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo
 
@@ -476,6 +547,14 @@ type RawSockaddrInet4 struct {
 	Zero   [8]uint8
 }
 
+type RawSockaddrInet6 struct {
+	Family   uint16
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
 type RawSockaddr struct {
 	Family uint16
 	Data   [14]int8
@@ -514,11 +593,22 @@ type SockaddrInet6 struct {
 	Port   int
 	ZoneId uint32
 	Addr   [16]byte
+	raw    RawSockaddrInet6
 }
 
 func (sa *SockaddrInet6) sockaddr() (uintptr, int32, error) {
-	// TODO(brainman): implement SockaddrInet6.sockaddr()
-	return 0, 0, EWINDOWS
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return 0, 0, EINVAL
+	}
+	sa.raw.Family = AF_INET6
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
+	p[0] = byte(sa.Port >> 8)
+	p[1] = byte(sa.Port)
+	sa.raw.Scope_id = sa.ZoneId
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i]
+	}
+	return uintptr(unsafe.Pointer(&sa.raw)), int32(unsafe.Sizeof(sa.raw)), nil
 }
 
 type SockaddrUnix struct {
@@ -546,7 +636,15 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
 		return sa, nil
 
 	case AF_INET6:
-		return nil, EWINDOWS
+		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
+		sa := new(SockaddrInet6)
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
+		sa.Port = int(p[0])<<8 + int(p[1])
+		sa.ZoneId = pp.Scope_id
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i]
+		}
+		return sa, nil
 	}
 	return nil, EAFNOSUPPORT
 }
@@ -613,6 +711,60 @@ func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32
 	return WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine)
 }
 
+func LoadGetAddrInfo() error {
+	return procGetAddrInfoW.Find()
+}
+
+var connectExFunc struct {
+	once sync.Once
+	addr uintptr
+	err  error
+}
+
+func LoadConnectEx() error {
+	connectExFunc.once.Do(func() {
+		var s Handle
+		s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
+		if connectExFunc.err != nil {
+			return
+		}
+		defer CloseHandle(s)
+		var n uint32
+		connectExFunc.err = WSAIoctl(s,
+			SIO_GET_EXTENSION_FUNCTION_POINTER,
+			(*byte)(unsafe.Pointer(&WSAID_CONNECTEX)),
+			uint32(unsafe.Sizeof(WSAID_CONNECTEX)),
+			(*byte)(unsafe.Pointer(&connectExFunc.addr)),
+			uint32(unsafe.Sizeof(connectExFunc.addr)),
+			&n, nil, 0)
+	})
+	return connectExFunc.err
+}
+
+func connectEx(s Handle, name uintptr, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) {
+	r1, _, e1 := Syscall9(connectExFunc.addr, 7, uintptr(s), uintptr(name), uintptr(namelen), uintptr(unsafe.Pointer(sendBuf)), uintptr(sendDataLen), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error {
+	err := LoadConnectEx()
+	if err != nil {
+		return errorspkg.New("failed to find ConnectEx: " + err.Error())
+	}
+	ptr, n, err := sa.sockaddr()
+	if err != nil {
+		return err
+	}
+	return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
+}
+
 // Invented structures to support what package os expects.
 type Rusage struct {
 	CreationTime Filetime
@@ -650,6 +802,14 @@ type Timespec struct {
 	Nsec int64
 }
 
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+	ts.Sec = nsec / 1e9
+	ts.Nsec = nsec % 1e9
+	return
+}
+
 // TODO(brainman): fix all needed for net
 
 func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS }
@@ -659,11 +819,23 @@ func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error)
 func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error)       { return EWINDOWS }
 func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS }
 
+// The Linger struct is wrong but we only noticed after Go 1.
+// sysLinger is the real system call structure.
+
+// BUG(brainman): The definition of Linger is not appropriate for direct use
+// with Setsockopt and Getsockopt.
+// Use SetsockoptLinger instead.
+
 type Linger struct {
 	Onoff  int32
 	Linger int32
 }
 
+type sysLinger struct {
+	Onoff  uint16
+	Linger uint16
+}
+
 type IPMreq struct {
 	Multiaddr [4]byte /* in_addr */
 	Interface [4]byte /* in_addr */
@@ -674,8 +846,13 @@ type IPv6Mreq struct {
 	Interface uint32
 }
 
-func GetsockoptInt(fd Handle, level, opt int) (int, error)              { return -1, EWINDOWS }
-func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { return EWINDOWS }
+func GetsockoptInt(fd Handle, level, opt int) (int, error) { return -1, EWINDOWS }
+
+func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) {
+	sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)}
+	return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys)))
+}
+
 func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) {
 	return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4)
 }
diff --git a/src/pkg/syscall/syscall_windows_test.go b/src/pkg/syscall/syscall_windows_test.go
index 79cd8f8..86842f2 100644
--- a/src/pkg/syscall/syscall_windows_test.go
+++ b/src/pkg/syscall/syscall_windows_test.go
@@ -35,7 +35,8 @@ func TestWin32finddata(t *testing.T) {
 	var want byte = 2 // it is unlikely to have this character in the filename
 	x := X{got: want}
 
-	h, err := syscall.FindFirstFile(syscall.StringToUTF16Ptr(path), &(x.fd))
+	pathp, _ := syscall.UTF16PtrFromString(path)
+	h, err := syscall.FindFirstFile(pathp, &(x.fd))
 	if err != nil {
 		t.Fatalf("FindFirstFile failed: %v", err)
 	}
@@ -48,3 +49,24 @@ func TestWin32finddata(t *testing.T) {
 		t.Fatalf("memory corruption: want=%d got=%d", want, x.got)
 	}
 }
+
+func abort(funcname string, err error) {
+	panic(funcname + " failed: " + err.Error())
+}
+
+func ExampleLoadLibrary() {
+	h, err := syscall.LoadLibrary("kernel32.dll")
+	if err != nil {
+		abort("LoadLibrary", err)
+	}
+	defer syscall.FreeLibrary(h)
+	proc, err := syscall.GetProcAddress(h, "GetVersion")
+	if err != nil {
+		abort("GetProcAddress", err)
+	}
+	r, _, _ := syscall.Syscall(uintptr(proc), 0, 0, 0, 0)
+	major := byte(r)
+	minor := uint8(r >> 8)
+	build := uint16(r >> 16)
+	print("windows version ", major, ".", minor, " (Build ", build, ")\n")
+}
diff --git a/src/pkg/syscall/types_darwin.go b/src/pkg/syscall/types_darwin.go
index b9c65e3..098bbff 100644
--- a/src/pkg/syscall/types_darwin.go
+++ b/src/pkg/syscall/types_darwin.go
@@ -20,6 +20,7 @@ package syscall
 #include <dirent.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <termios.h>
 #include <unistd.h>
 #include <mach/mach.h>
 #include <mach/message.h>
@@ -149,6 +150,8 @@ type Msghdr C.struct_msghdr
 
 type Cmsghdr C.struct_cmsghdr
 
+type Inet4Pktinfo C.struct_in_pktinfo
+
 type Inet6Pktinfo C.struct_in6_pktinfo
 
 const (
@@ -162,6 +165,7 @@ const (
 	SizeofIPv6Mreq         = C.sizeof_struct_ipv6_mreq
 	SizeofMsghdr           = C.sizeof_struct_msghdr
 	SizeofCmsghdr          = C.sizeof_struct_cmsghdr
+	SizeofInet4Pktinfo     = C.sizeof_struct_in_pktinfo
 	SizeofInet6Pktinfo     = C.sizeof_struct_in6_pktinfo
 )
 
@@ -226,3 +230,7 @@ type BpfProgram C.struct_bpf_program
 type BpfInsn C.struct_bpf_insn
 
 type BpfHdr C.struct_bpf_hdr
+
+// Terminal handling
+
+type Termios C.struct_termios
diff --git a/src/pkg/syscall/types_freebsd.go b/src/pkg/syscall/types_freebsd.go
index 6e1dd43..7d4923d 100644
--- a/src/pkg/syscall/types_freebsd.go
+++ b/src/pkg/syscall/types_freebsd.go
@@ -193,12 +193,13 @@ type FdSet C.fd_set
 // Routing and interface messages
 
 const (
-	SizeofIfMsghdr   = C.sizeof_struct_if_msghdr
-	SizeofIfData     = C.sizeof_struct_if_data
-	SizeofIfaMsghdr  = C.sizeof_struct_ifa_msghdr
-	SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
-	SizeofRtMsghdr   = C.sizeof_struct_rt_msghdr
-	SizeofRtMetrics  = C.sizeof_struct_rt_metrics
+	SizeofIfMsghdr         = C.sizeof_struct_if_msghdr
+	SizeofIfData           = C.sizeof_struct_if_data
+	SizeofIfaMsghdr        = C.sizeof_struct_ifa_msghdr
+	SizeofIfmaMsghdr       = C.sizeof_struct_ifma_msghdr
+	SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
+	SizeofRtMsghdr         = C.sizeof_struct_rt_msghdr
+	SizeofRtMetrics        = C.sizeof_struct_rt_metrics
 )
 
 type IfMsghdr C.struct_if_msghdr
@@ -209,6 +210,8 @@ type IfaMsghdr C.struct_ifa_msghdr
 
 type IfmaMsghdr C.struct_ifma_msghdr
 
+type IfAnnounceMsghdr C.struct_if_announcemsghdr
+
 type RtMsghdr C.struct_rt_msghdr
 
 type RtMetrics C.struct_rt_metrics
diff --git a/src/pkg/syscall/types_linux.go b/src/pkg/syscall/types_linux.go
index 0030960..1514cbc 100644
--- a/src/pkg/syscall/types_linux.go
+++ b/src/pkg/syscall/types_linux.go
@@ -73,7 +73,7 @@ struct sockaddr_any {
 	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
 };
 
-// copied from /usr/include/linux/un.h 
+// copied from /usr/include/linux/un.h
 struct my_sockaddr_un {
 	sa_family_t sun_family;
 #ifdef __ARM_EABI__
@@ -195,6 +195,8 @@ type Inet6Pktinfo C.struct_in6_pktinfo
 
 type Ucred C.struct_ucred
 
+type TCPInfo C.struct_tcp_info
+
 const (
 	SizeofSockaddrInet4     = C.sizeof_struct_sockaddr_in
 	SizeofSockaddrInet6     = C.sizeof_struct_sockaddr_in6
@@ -211,86 +213,103 @@ const (
 	SizeofInet4Pktinfo      = C.sizeof_struct_in_pktinfo
 	SizeofInet6Pktinfo      = C.sizeof_struct_in6_pktinfo
 	SizeofUcred             = C.sizeof_struct_ucred
+	SizeofTCPInfo           = C.sizeof_struct_tcp_info
 )
 
 // Netlink routing and interface messages
 
 const (
-	IFA_UNSPEC        = C.IFA_UNSPEC
-	IFA_ADDRESS       = C.IFA_ADDRESS
-	IFA_LOCAL         = C.IFA_LOCAL
-	IFA_LABEL         = C.IFA_LABEL
-	IFA_BROADCAST     = C.IFA_BROADCAST
-	IFA_ANYCAST       = C.IFA_ANYCAST
-	IFA_CACHEINFO     = C.IFA_CACHEINFO
-	IFA_MULTICAST     = C.IFA_MULTICAST
-	IFLA_UNSPEC       = C.IFLA_UNSPEC
-	IFLA_ADDRESS      = C.IFLA_ADDRESS
-	IFLA_BROADCAST    = C.IFLA_BROADCAST
-	IFLA_IFNAME       = C.IFLA_IFNAME
-	IFLA_MTU          = C.IFLA_MTU
-	IFLA_LINK         = C.IFLA_LINK
-	IFLA_QDISC        = C.IFLA_QDISC
-	IFLA_STATS        = C.IFLA_STATS
-	IFLA_COST         = C.IFLA_COST
-	IFLA_PRIORITY     = C.IFLA_PRIORITY
-	IFLA_MASTER       = C.IFLA_MASTER
-	IFLA_WIRELESS     = C.IFLA_WIRELESS
-	IFLA_PROTINFO     = C.IFLA_PROTINFO
-	IFLA_TXQLEN       = C.IFLA_TXQLEN
-	IFLA_MAP          = C.IFLA_MAP
-	IFLA_WEIGHT       = C.IFLA_WEIGHT
-	IFLA_OPERSTATE    = C.IFLA_OPERSTATE
-	IFLA_LINKMODE     = C.IFLA_LINKMODE
-	IFLA_LINKINFO     = C.IFLA_LINKINFO
-	IFLA_NET_NS_PID   = C.IFLA_NET_NS_PID
-	IFLA_IFALIAS      = C.IFLA_IFALIAS
-	IFLA_MAX          = C.IFLA_MAX
-	RT_SCOPE_UNIVERSE = C.RT_SCOPE_UNIVERSE
-	RT_SCOPE_SITE     = C.RT_SCOPE_SITE
-	RT_SCOPE_LINK     = C.RT_SCOPE_LINK
-	RT_SCOPE_HOST     = C.RT_SCOPE_HOST
-	RT_SCOPE_NOWHERE  = C.RT_SCOPE_NOWHERE
-	RT_TABLE_UNSPEC   = C.RT_TABLE_UNSPEC
-	RT_TABLE_COMPAT   = C.RT_TABLE_COMPAT
-	RT_TABLE_DEFAULT  = C.RT_TABLE_DEFAULT
-	RT_TABLE_MAIN     = C.RT_TABLE_MAIN
-	RT_TABLE_LOCAL    = C.RT_TABLE_LOCAL
-	RT_TABLE_MAX      = C.RT_TABLE_MAX
-	RTA_UNSPEC        = C.RTA_UNSPEC
-	RTA_DST           = C.RTA_DST
-	RTA_SRC           = C.RTA_SRC
-	RTA_IIF           = C.RTA_IIF
-	RTA_OIF           = C.RTA_OIF
-	RTA_GATEWAY       = C.RTA_GATEWAY
-	RTA_PRIORITY      = C.RTA_PRIORITY
-	RTA_PREFSRC       = C.RTA_PREFSRC
-	RTA_METRICS       = C.RTA_METRICS
-	RTA_MULTIPATH     = C.RTA_MULTIPATH
-	RTA_FLOW          = C.RTA_FLOW
-	RTA_CACHEINFO     = C.RTA_CACHEINFO
-	RTA_TABLE         = C.RTA_TABLE
-	RTN_UNSPEC        = C.RTN_UNSPEC
-	RTN_UNICAST       = C.RTN_UNICAST
-	RTN_LOCAL         = C.RTN_LOCAL
-	RTN_BROADCAST     = C.RTN_BROADCAST
-	RTN_ANYCAST       = C.RTN_ANYCAST
-	RTN_MULTICAST     = C.RTN_MULTICAST
-	RTN_BLACKHOLE     = C.RTN_BLACKHOLE
-	RTN_UNREACHABLE   = C.RTN_UNREACHABLE
-	RTN_PROHIBIT      = C.RTN_PROHIBIT
-	RTN_THROW         = C.RTN_THROW
-	RTN_NAT           = C.RTN_NAT
-	RTN_XRESOLVE      = C.RTN_XRESOLVE
-	SizeofNlMsghdr    = C.sizeof_struct_nlmsghdr
-	SizeofNlMsgerr    = C.sizeof_struct_nlmsgerr
-	SizeofRtGenmsg    = C.sizeof_struct_rtgenmsg
-	SizeofNlAttr      = C.sizeof_struct_nlattr
-	SizeofRtAttr      = C.sizeof_struct_rtattr
-	SizeofIfInfomsg   = C.sizeof_struct_ifinfomsg
-	SizeofIfAddrmsg   = C.sizeof_struct_ifaddrmsg
-	SizeofRtMsg       = C.sizeof_struct_rtmsg
-	SizeofRtNexthop   = C.sizeof_struct_rtnexthop
+	IFA_UNSPEC          = C.IFA_UNSPEC
+	IFA_ADDRESS         = C.IFA_ADDRESS
+	IFA_LOCAL           = C.IFA_LOCAL
+	IFA_LABEL           = C.IFA_LABEL
+	IFA_BROADCAST       = C.IFA_BROADCAST
+	IFA_ANYCAST         = C.IFA_ANYCAST
+	IFA_CACHEINFO       = C.IFA_CACHEINFO
+	IFA_MULTICAST       = C.IFA_MULTICAST
+	IFLA_UNSPEC         = C.IFLA_UNSPEC
+	IFLA_ADDRESS        = C.IFLA_ADDRESS
+	IFLA_BROADCAST      = C.IFLA_BROADCAST
+	IFLA_IFNAME         = C.IFLA_IFNAME
+	IFLA_MTU            = C.IFLA_MTU
+	IFLA_LINK           = C.IFLA_LINK
+	IFLA_QDISC          = C.IFLA_QDISC
+	IFLA_STATS          = C.IFLA_STATS
+	IFLA_COST           = C.IFLA_COST
+	IFLA_PRIORITY       = C.IFLA_PRIORITY
+	IFLA_MASTER         = C.IFLA_MASTER
+	IFLA_WIRELESS       = C.IFLA_WIRELESS
+	IFLA_PROTINFO       = C.IFLA_PROTINFO
+	IFLA_TXQLEN         = C.IFLA_TXQLEN
+	IFLA_MAP            = C.IFLA_MAP
+	IFLA_WEIGHT         = C.IFLA_WEIGHT
+	IFLA_OPERSTATE      = C.IFLA_OPERSTATE
+	IFLA_LINKMODE       = C.IFLA_LINKMODE
+	IFLA_LINKINFO       = C.IFLA_LINKINFO
+	IFLA_NET_NS_PID     = C.IFLA_NET_NS_PID
+	IFLA_IFALIAS        = C.IFLA_IFALIAS
+	IFLA_MAX            = C.IFLA_MAX
+	RT_SCOPE_UNIVERSE   = C.RT_SCOPE_UNIVERSE
+	RT_SCOPE_SITE       = C.RT_SCOPE_SITE
+	RT_SCOPE_LINK       = C.RT_SCOPE_LINK
+	RT_SCOPE_HOST       = C.RT_SCOPE_HOST
+	RT_SCOPE_NOWHERE    = C.RT_SCOPE_NOWHERE
+	RT_TABLE_UNSPEC     = C.RT_TABLE_UNSPEC
+	RT_TABLE_COMPAT     = C.RT_TABLE_COMPAT
+	RT_TABLE_DEFAULT    = C.RT_TABLE_DEFAULT
+	RT_TABLE_MAIN       = C.RT_TABLE_MAIN
+	RT_TABLE_LOCAL      = C.RT_TABLE_LOCAL
+	RT_TABLE_MAX        = C.RT_TABLE_MAX
+	RTA_UNSPEC          = C.RTA_UNSPEC
+	RTA_DST             = C.RTA_DST
+	RTA_SRC             = C.RTA_SRC
+	RTA_IIF             = C.RTA_IIF
+	RTA_OIF             = C.RTA_OIF
+	RTA_GATEWAY         = C.RTA_GATEWAY
+	RTA_PRIORITY        = C.RTA_PRIORITY
+	RTA_PREFSRC         = C.RTA_PREFSRC
+	RTA_METRICS         = C.RTA_METRICS
+	RTA_MULTIPATH       = C.RTA_MULTIPATH
+	RTA_FLOW            = C.RTA_FLOW
+	RTA_CACHEINFO       = C.RTA_CACHEINFO
+	RTA_TABLE           = C.RTA_TABLE
+	RTN_UNSPEC          = C.RTN_UNSPEC
+	RTN_UNICAST         = C.RTN_UNICAST
+	RTN_LOCAL           = C.RTN_LOCAL
+	RTN_BROADCAST       = C.RTN_BROADCAST
+	RTN_ANYCAST         = C.RTN_ANYCAST
+	RTN_MULTICAST       = C.RTN_MULTICAST
+	RTN_BLACKHOLE       = C.RTN_BLACKHOLE
+	RTN_UNREACHABLE     = C.RTN_UNREACHABLE
+	RTN_PROHIBIT        = C.RTN_PROHIBIT
+	RTN_THROW           = C.RTN_THROW
+	RTN_NAT             = C.RTN_NAT
+	RTN_XRESOLVE        = C.RTN_XRESOLVE
+	RTNLGRP_NONE        = C.RTNLGRP_NONE
+	RTNLGRP_LINK        = C.RTNLGRP_LINK
+	RTNLGRP_NOTIFY      = C.RTNLGRP_NOTIFY
+	RTNLGRP_NEIGH       = C.RTNLGRP_NEIGH
+	RTNLGRP_TC          = C.RTNLGRP_TC
+	RTNLGRP_IPV4_IFADDR = C.RTNLGRP_IPV4_IFADDR
+	RTNLGRP_IPV4_MROUTE = C.RTNLGRP_IPV4_MROUTE
+	RTNLGRP_IPV4_ROUTE  = C.RTNLGRP_IPV4_ROUTE
+	RTNLGRP_IPV4_RULE   = C.RTNLGRP_IPV4_RULE
+	RTNLGRP_IPV6_IFADDR = C.RTNLGRP_IPV6_IFADDR
+	RTNLGRP_IPV6_MROUTE = C.RTNLGRP_IPV6_MROUTE
+	RTNLGRP_IPV6_ROUTE  = C.RTNLGRP_IPV6_ROUTE
+	RTNLGRP_IPV6_IFINFO = C.RTNLGRP_IPV6_IFINFO
+	RTNLGRP_IPV6_PREFIX = C.RTNLGRP_IPV6_PREFIX
+	RTNLGRP_IPV6_RULE   = C.RTNLGRP_IPV6_RULE
+	RTNLGRP_ND_USEROPT  = C.RTNLGRP_ND_USEROPT
+	SizeofNlMsghdr      = C.sizeof_struct_nlmsghdr
+	SizeofNlMsgerr      = C.sizeof_struct_nlmsgerr
+	SizeofRtGenmsg      = C.sizeof_struct_rtgenmsg
+	SizeofNlAttr        = C.sizeof_struct_nlattr
+	SizeofRtAttr        = C.sizeof_struct_rtattr
+	SizeofIfInfomsg     = C.sizeof_struct_ifinfomsg
+	SizeofIfAddrmsg     = C.sizeof_struct_ifaddrmsg
+	SizeofRtMsg         = C.sizeof_struct_rtmsg
+	SizeofRtNexthop     = C.sizeof_struct_rtnexthop
 )
 
 type NlMsghdr C.struct_nlmsghdr
@@ -345,6 +364,10 @@ type Ustat_t C.struct_ustat
 
 type EpollEvent C.struct_my_epoll_event
 
+const (
+	_AT_FDCWD = C.AT_FDCWD
+)
+
 // Terminal handling
 
 type Termios C.struct_termios
diff --git a/src/pkg/syscall/types_netbsd.go b/src/pkg/syscall/types_netbsd.go
index 5186888..4906a99 100644
--- a/src/pkg/syscall/types_netbsd.go
+++ b/src/pkg/syscall/types_netbsd.go
@@ -31,6 +31,7 @@ package syscall
 #include <sys/signal.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/sysctl.h>
 #include <sys/time.h>
 #include <sys/uio.h>
 #include <sys/un.h>
@@ -97,23 +98,6 @@ type _Gid_t C.gid_t
 
 // Files
 
-const ( // Directory mode bits
-	S_IFMT   = C.S_IFMT
-	S_IFIFO  = C.S_IFIFO
-	S_IFCHR  = C.S_IFCHR
-	S_IFDIR  = C.S_IFDIR
-	S_IFBLK  = C.S_IFBLK
-	S_IFREG  = C.S_IFREG
-	S_IFLNK  = C.S_IFLNK
-	S_IFSOCK = C.S_IFSOCK
-	S_ISUID  = C.S_ISUID
-	S_ISGID  = C.S_ISGID
-	S_ISVTX  = C.S_ISVTX
-	S_IRUSR  = C.S_IRUSR
-	S_IWUSR  = C.S_IWUSR
-	S_IXUSR  = C.S_IXUSR
-)
-
 type Stat_t C.struct_stat
 
 type Statfs_t C.struct_statfs
@@ -187,11 +171,12 @@ type FdSet C.fd_set
 // Routing and interface messages
 
 const (
-	SizeofIfMsghdr  = C.sizeof_struct_if_msghdr
-	SizeofIfData    = C.sizeof_struct_if_data
-	SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
-	SizeofRtMsghdr  = C.sizeof_struct_rt_msghdr
-	SizeofRtMetrics = C.sizeof_struct_rt_metrics
+	SizeofIfMsghdr         = C.sizeof_struct_if_msghdr
+	SizeofIfData           = C.sizeof_struct_if_data
+	SizeofIfaMsghdr        = C.sizeof_struct_ifa_msghdr
+	SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
+	SizeofRtMsghdr         = C.sizeof_struct_rt_msghdr
+	SizeofRtMetrics        = C.sizeof_struct_rt_metrics
 )
 
 type IfMsghdr C.struct_if_msghdr
@@ -200,6 +185,8 @@ type IfData C.struct_if_data
 
 type IfaMsghdr C.struct_ifa_msghdr
 
+type IfAnnounceMsghdr C.struct_if_announcemsghdr
+
 type RtMsghdr C.struct_rt_msghdr
 
 type RtMetrics C.struct_rt_metrics
@@ -227,3 +214,7 @@ type BpfInsn C.struct_bpf_insn
 type BpfHdr C.struct_bpf_hdr
 
 type BpfTimeval C.struct_bpf_timeval
+
+// Sysctl
+
+type Sysctlnode C.struct_sysctlnode
diff --git a/src/pkg/syscall/types_openbsd.go b/src/pkg/syscall/types_openbsd.go
index 5186888..2430a16 100644
--- a/src/pkg/syscall/types_openbsd.go
+++ b/src/pkg/syscall/types_openbsd.go
@@ -187,11 +187,12 @@ type FdSet C.fd_set
 // Routing and interface messages
 
 const (
-	SizeofIfMsghdr  = C.sizeof_struct_if_msghdr
-	SizeofIfData    = C.sizeof_struct_if_data
-	SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
-	SizeofRtMsghdr  = C.sizeof_struct_rt_msghdr
-	SizeofRtMetrics = C.sizeof_struct_rt_metrics
+	SizeofIfMsghdr         = C.sizeof_struct_if_msghdr
+	SizeofIfData           = C.sizeof_struct_if_data
+	SizeofIfaMsghdr        = C.sizeof_struct_ifa_msghdr
+	SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
+	SizeofRtMsghdr         = C.sizeof_struct_rt_msghdr
+	SizeofRtMetrics        = C.sizeof_struct_rt_metrics
 )
 
 type IfMsghdr C.struct_if_msghdr
@@ -200,6 +201,8 @@ type IfData C.struct_if_data
 
 type IfaMsghdr C.struct_ifa_msghdr
 
+type IfAnnounceMsghdr C.struct_if_announcemsghdr
+
 type RtMsghdr C.struct_rt_msghdr
 
 type RtMetrics C.struct_rt_metrics
diff --git a/src/pkg/syscall/zerrors_darwin_386.go b/src/pkg/syscall/zerrors_darwin_386.go
index 09d7b0f..cdb8605 100644
--- a/src/pkg/syscall/zerrors_darwin_386.go
+++ b/src/pkg/syscall/zerrors_darwin_386.go
@@ -43,6 +43,29 @@ const (
 	AF_SYSTEM                         = 0x20
 	AF_UNIX                           = 0x1
 	AF_UNSPEC                         = 0x0
+	B0                                = 0x0
+	B110                              = 0x6e
+	B115200                           = 0x1c200
+	B1200                             = 0x4b0
+	B134                              = 0x86
+	B14400                            = 0x3840
+	B150                              = 0x96
+	B1800                             = 0x708
+	B19200                            = 0x4b00
+	B200                              = 0xc8
+	B230400                           = 0x38400
+	B2400                             = 0x960
+	B28800                            = 0x7080
+	B300                              = 0x12c
+	B38400                            = 0x9600
+	B4800                             = 0x12c0
+	B50                               = 0x32
+	B57600                            = 0xe100
+	B600                              = 0x258
+	B7200                             = 0x1c20
+	B75                               = 0x4b
+	B76800                            = 0x12c00
+	B9600                             = 0x2580
 	BIOCFLUSH                         = 0x20004268
 	BIOCGBLEN                         = 0x40044266
 	BIOCGDLT                          = 0x4004426a
@@ -108,6 +131,20 @@ const (
 	BPF_TXA                           = 0x80
 	BPF_W                             = 0x0
 	BPF_X                             = 0x8
+	BRKINT                            = 0x2
+	CFLUSH                            = 0xf
+	CLOCAL                            = 0x8000
+	CREAD                             = 0x800
+	CS5                               = 0x0
+	CS6                               = 0x100
+	CS7                               = 0x200
+	CS8                               = 0x300
+	CSIZE                             = 0x300
+	CSTART                            = 0x11
+	CSTATUS                           = 0x14
+	CSTOP                             = 0x13
+	CSTOPB                            = 0x400
+	CSUSP                             = 0x1a
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
 	DLT_APPLE_IP_OVER_IEEE1394        = 0x8a
@@ -186,6 +223,7 @@ const (
 	EXTPROC                           = 0x800
 	FD_CLOEXEC                        = 0x1
 	FD_SETSIZE                        = 0x400
+	FLUSHO                            = 0x800000
 	F_ADDFILESIGS                     = 0x3d
 	F_ADDSIGS                         = 0x3b
 	F_ALLOCATEALL                     = 0x4
@@ -233,6 +271,10 @@ const (
 	F_VOLPOSMODE                      = 0x4
 	F_WRITEBOOTSTRAP                  = 0x2f
 	F_WRLCK                           = 0x3
+	HUPCL                             = 0x4000
+	ICANON                            = 0x100
+	ICRNL                             = 0x100
+	IEXTEN                            = 0x400
 	IFF_ALLMULTI                      = 0x200
 	IFF_ALTPHYS                       = 0x4000
 	IFF_BROADCAST                     = 0x2
@@ -318,6 +360,12 @@ const (
 	IFT_X25DDN                        = 0x4
 	IFT_X25PLE                        = 0x28
 	IFT_XETHER                        = 0x1a
+	IGNBRK                            = 0x1
+	IGNCR                             = 0x80
+	IGNPAR                            = 0x4
+	IMAXBEL                           = 0x2000
+	INLCR                             = 0x40
+	INPCK                             = 0x10
 	IN_CLASSA_HOST                    = 0xffffff
 	IN_CLASSA_MAX                     = 0x80
 	IN_CLASSA_NET                     = 0xff000000
@@ -560,6 +608,12 @@ const (
 	IP_TRAFFIC_MGT_BACKGROUND         = 0x41
 	IP_TTL                            = 0x4
 	IP_UNBLOCK_SOURCE                 = 0x49
+	ISIG                              = 0x80
+	ISTRIP                            = 0x20
+	IUTF8                             = 0x4000
+	IXANY                             = 0x800
+	IXOFF                             = 0x400
+	IXON                              = 0x200
 	LOCK_EX                           = 0x2
 	LOCK_NB                           = 0x4
 	LOCK_SH                           = 0x1
@@ -619,6 +673,7 @@ const (
 	NET_RT_MAXID                      = 0xa
 	NET_RT_STAT                       = 0x4
 	NET_RT_TRASH                      = 0x5
+	NOFLSH                            = 0x80000000
 	NOTE_ABSOLUTE                     = 0x8
 	NOTE_ATTRIB                       = 0x8
 	NOTE_CHILD                        = 0x4
@@ -655,6 +710,14 @@ const (
 	NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000
 	NOTE_VM_PRESSURE_TERMINATE        = 0x40000000
 	NOTE_WRITE                        = 0x2
+	OCRNL                             = 0x10
+	OFDEL                             = 0x20000
+	OFILL                             = 0x80
+	ONLCR                             = 0x2
+	ONLRET                            = 0x40
+	ONOCR                             = 0x20
+	ONOEOT                            = 0x8
+	OPOST                             = 0x1
 	O_ACCMODE                         = 0x3
 	O_ALERT                           = 0x20000000
 	O_APPEND                          = 0x8
@@ -679,6 +742,10 @@ const (
 	O_SYNC                            = 0x80
 	O_TRUNC                           = 0x400
 	O_WRONLY                          = 0x1
+	PARENB                            = 0x1000
+	PARMRK                            = 0x8
+	PARODD                            = 0x2000
+	PENDIN                            = 0x20000000
 	PROT_EXEC                         = 0x4
 	PROT_NONE                         = 0x0
 	PROT_READ                         = 0x1
@@ -937,6 +1004,9 @@ const (
 	S_IXGRP                           = 0x8
 	S_IXOTH                           = 0x1
 	S_IXUSR                           = 0x40
+	TCIFLUSH                          = 0x1
+	TCIOFLUSH                         = 0x3
+	TCOFLUSH                          = 0x2
 	TCP_CONNECTIONTIMEOUT             = 0x20
 	TCP_KEEPALIVE                     = 0x10
 	TCP_MAXHLEN                       = 0x3c
@@ -953,6 +1023,7 @@ const (
 	TCP_NOPUSH                        = 0x4
 	TCP_RXT_CONNDROPTIME              = 0x80
 	TCP_RXT_FINDROP                   = 0x100
+	TCSAFLUSH                         = 0x2
 	TIOCCBRK                          = 0x2000747a
 	TIOCCDTR                          = 0x20007478
 	TIOCCONS                          = 0x80047462
@@ -1022,6 +1093,28 @@ const (
 	TIOCSWINSZ                        = 0x80087467
 	TIOCTIMESTAMP                     = 0x40087459
 	TIOCUCNTL                         = 0x80047466
+	TOSTOP                            = 0x400000
+	VDISCARD                          = 0xf
+	VDSUSP                            = 0xb
+	VEOF                              = 0x0
+	VEOL                              = 0x1
+	VEOL2                             = 0x2
+	VERASE                            = 0x3
+	VINTR                             = 0x8
+	VKILL                             = 0x5
+	VLNEXT                            = 0xe
+	VMIN                              = 0x10
+	VQUIT                             = 0x9
+	VREPRINT                          = 0x6
+	VSTART                            = 0xc
+	VSTATUS                           = 0x12
+	VSTOP                             = 0xd
+	VSUSP                             = 0xa
+	VT0                               = 0x0
+	VT1                               = 0x10000
+	VTDLY                             = 0x10000
+	VTIME                             = 0x11
+	VWERASE                           = 0x4
 	WCONTINUED                        = 0x10
 	WCOREFLAG                         = 0x80
 	WEXITED                           = 0x4
diff --git a/src/pkg/syscall/zerrors_darwin_amd64.go b/src/pkg/syscall/zerrors_darwin_amd64.go
index 7fa5cfc..8ffcbcc 100644
--- a/src/pkg/syscall/zerrors_darwin_amd64.go
+++ b/src/pkg/syscall/zerrors_darwin_amd64.go
@@ -43,6 +43,29 @@ const (
 	AF_SYSTEM                         = 0x20
 	AF_UNIX                           = 0x1
 	AF_UNSPEC                         = 0x0
+	B0                                = 0x0
+	B110                              = 0x6e
+	B115200                           = 0x1c200
+	B1200                             = 0x4b0
+	B134                              = 0x86
+	B14400                            = 0x3840
+	B150                              = 0x96
+	B1800                             = 0x708
+	B19200                            = 0x4b00
+	B200                              = 0xc8
+	B230400                           = 0x38400
+	B2400                             = 0x960
+	B28800                            = 0x7080
+	B300                              = 0x12c
+	B38400                            = 0x9600
+	B4800                             = 0x12c0
+	B50                               = 0x32
+	B57600                            = 0xe100
+	B600                              = 0x258
+	B7200                             = 0x1c20
+	B75                               = 0x4b
+	B76800                            = 0x12c00
+	B9600                             = 0x2580
 	BIOCFLUSH                         = 0x20004268
 	BIOCGBLEN                         = 0x40044266
 	BIOCGDLT                          = 0x4004426a
@@ -108,6 +131,20 @@ const (
 	BPF_TXA                           = 0x80
 	BPF_W                             = 0x0
 	BPF_X                             = 0x8
+	BRKINT                            = 0x2
+	CFLUSH                            = 0xf
+	CLOCAL                            = 0x8000
+	CREAD                             = 0x800
+	CS5                               = 0x0
+	CS6                               = 0x100
+	CS7                               = 0x200
+	CS8                               = 0x300
+	CSIZE                             = 0x300
+	CSTART                            = 0x11
+	CSTATUS                           = 0x14
+	CSTOP                             = 0x13
+	CSTOPB                            = 0x400
+	CSUSP                             = 0x1a
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
 	DLT_APPLE_IP_OVER_IEEE1394        = 0x8a
@@ -186,6 +223,7 @@ const (
 	EXTPROC                           = 0x800
 	FD_CLOEXEC                        = 0x1
 	FD_SETSIZE                        = 0x400
+	FLUSHO                            = 0x800000
 	F_ADDFILESIGS                     = 0x3d
 	F_ADDSIGS                         = 0x3b
 	F_ALLOCATEALL                     = 0x4
@@ -233,6 +271,10 @@ const (
 	F_VOLPOSMODE                      = 0x4
 	F_WRITEBOOTSTRAP                  = 0x2f
 	F_WRLCK                           = 0x3
+	HUPCL                             = 0x4000
+	ICANON                            = 0x100
+	ICRNL                             = 0x100
+	IEXTEN                            = 0x400
 	IFF_ALLMULTI                      = 0x200
 	IFF_ALTPHYS                       = 0x4000
 	IFF_BROADCAST                     = 0x2
@@ -318,6 +360,12 @@ const (
 	IFT_X25DDN                        = 0x4
 	IFT_X25PLE                        = 0x28
 	IFT_XETHER                        = 0x1a
+	IGNBRK                            = 0x1
+	IGNCR                             = 0x80
+	IGNPAR                            = 0x4
+	IMAXBEL                           = 0x2000
+	INLCR                             = 0x40
+	INPCK                             = 0x10
 	IN_CLASSA_HOST                    = 0xffffff
 	IN_CLASSA_MAX                     = 0x80
 	IN_CLASSA_NET                     = 0xff000000
@@ -560,6 +608,12 @@ const (
 	IP_TRAFFIC_MGT_BACKGROUND         = 0x41
 	IP_TTL                            = 0x4
 	IP_UNBLOCK_SOURCE                 = 0x49
+	ISIG                              = 0x80
+	ISTRIP                            = 0x20
+	IUTF8                             = 0x4000
+	IXANY                             = 0x800
+	IXOFF                             = 0x400
+	IXON                              = 0x200
 	LOCK_EX                           = 0x2
 	LOCK_NB                           = 0x4
 	LOCK_SH                           = 0x1
@@ -619,6 +673,7 @@ const (
 	NET_RT_MAXID                      = 0xa
 	NET_RT_STAT                       = 0x4
 	NET_RT_TRASH                      = 0x5
+	NOFLSH                            = 0x80000000
 	NOTE_ABSOLUTE                     = 0x8
 	NOTE_ATTRIB                       = 0x8
 	NOTE_CHILD                        = 0x4
@@ -655,6 +710,14 @@ const (
 	NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000
 	NOTE_VM_PRESSURE_TERMINATE        = 0x40000000
 	NOTE_WRITE                        = 0x2
+	OCRNL                             = 0x10
+	OFDEL                             = 0x20000
+	OFILL                             = 0x80
+	ONLCR                             = 0x2
+	ONLRET                            = 0x40
+	ONOCR                             = 0x20
+	ONOEOT                            = 0x8
+	OPOST                             = 0x1
 	O_ACCMODE                         = 0x3
 	O_ALERT                           = 0x20000000
 	O_APPEND                          = 0x8
@@ -679,6 +742,10 @@ const (
 	O_SYNC                            = 0x80
 	O_TRUNC                           = 0x400
 	O_WRONLY                          = 0x1
+	PARENB                            = 0x1000
+	PARMRK                            = 0x8
+	PARODD                            = 0x2000
+	PENDIN                            = 0x20000000
 	PROT_EXEC                         = 0x4
 	PROT_NONE                         = 0x0
 	PROT_READ                         = 0x1
@@ -937,6 +1004,9 @@ const (
 	S_IXGRP                           = 0x8
 	S_IXOTH                           = 0x1
 	S_IXUSR                           = 0x40
+	TCIFLUSH                          = 0x1
+	TCIOFLUSH                         = 0x3
+	TCOFLUSH                          = 0x2
 	TCP_CONNECTIONTIMEOUT             = 0x20
 	TCP_KEEPALIVE                     = 0x10
 	TCP_MAXHLEN                       = 0x3c
@@ -953,6 +1023,7 @@ const (
 	TCP_NOPUSH                        = 0x4
 	TCP_RXT_CONNDROPTIME              = 0x80
 	TCP_RXT_FINDROP                   = 0x100
+	TCSAFLUSH                         = 0x2
 	TIOCCBRK                          = 0x2000747a
 	TIOCCDTR                          = 0x20007478
 	TIOCCONS                          = 0x80047462
@@ -1022,6 +1093,28 @@ const (
 	TIOCSWINSZ                        = 0x80087467
 	TIOCTIMESTAMP                     = 0x40107459
 	TIOCUCNTL                         = 0x80047466
+	TOSTOP                            = 0x400000
+	VDISCARD                          = 0xf
+	VDSUSP                            = 0xb
+	VEOF                              = 0x0
+	VEOL                              = 0x1
+	VEOL2                             = 0x2
+	VERASE                            = 0x3
+	VINTR                             = 0x8
+	VKILL                             = 0x5
+	VLNEXT                            = 0xe
+	VMIN                              = 0x10
+	VQUIT                             = 0x9
+	VREPRINT                          = 0x6
+	VSTART                            = 0xc
+	VSTATUS                           = 0x12
+	VSTOP                             = 0xd
+	VSUSP                             = 0xa
+	VT0                               = 0x0
+	VT1                               = 0x10000
+	VTDLY                             = 0x10000
+	VTIME                             = 0x11
+	VWERASE                           = 0x4
 	WCONTINUED                        = 0x10
 	WCOREFLAG                         = 0x80
 	WEXITED                           = 0x4
diff --git a/src/pkg/syscall/zerrors_freebsd_386.go b/src/pkg/syscall/zerrors_freebsd_386.go
index cc00f0d..9cf82f9 100644
--- a/src/pkg/syscall/zerrors_freebsd_386.go
+++ b/src/pkg/syscall/zerrors_freebsd_386.go
@@ -369,6 +369,8 @@ const (
 	F_UNLCK                           = 0x2
 	F_UNLCKSYS                        = 0x4
 	F_WRLCK                           = 0x3
+	IFAN_ARRIVAL                      = 0x0
+	IFAN_DEPARTURE                    = 0x1
 	IFF_ALLMULTI                      = 0x200
 	IFF_ALTPHYS                       = 0x4000
 	IFF_BROADCAST                     = 0x2
diff --git a/src/pkg/syscall/zerrors_freebsd_amd64.go b/src/pkg/syscall/zerrors_freebsd_amd64.go
index b7b27b5..7325706 100644
--- a/src/pkg/syscall/zerrors_freebsd_amd64.go
+++ b/src/pkg/syscall/zerrors_freebsd_amd64.go
@@ -369,6 +369,8 @@ const (
 	F_UNLCK                           = 0x2
 	F_UNLCKSYS                        = 0x4
 	F_WRLCK                           = 0x3
+	IFAN_ARRIVAL                      = 0x0
+	IFAN_DEPARTURE                    = 0x1
 	IFF_ALLMULTI                      = 0x200
 	IFF_ALTPHYS                       = 0x4000
 	IFF_BROADCAST                     = 0x2
diff --git a/src/pkg/syscall/zerrors_freebsd_arm.go b/src/pkg/syscall/zerrors_freebsd_arm.go
new file mode 100644
index 0000000..92cade2
--- /dev/null
+++ b/src/pkg/syscall/zerrors_freebsd_arm.go
@@ -0,0 +1,1652 @@
+// mkerrors.sh
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- _const.go
+
+package syscall
+
+const (
+	//O_CLOEXEC                         = 0x100000
+	AF_APPLETALK                      = 0x10
+	AF_ARP                            = 0x23
+	AF_ATM                            = 0x1e
+	AF_BLUETOOTH                      = 0x24
+	AF_CCITT                          = 0xa
+	AF_CHAOS                          = 0x5
+	AF_CNT                            = 0x15
+	AF_COIP                           = 0x14
+	AF_DATAKIT                        = 0x9
+	AF_DECnet                         = 0xc
+	AF_DLI                            = 0xd
+	AF_E164                           = 0x1a
+	AF_ECMA                           = 0x8
+	AF_HYLINK                         = 0xf
+	AF_IEEE80211                      = 0x25
+	AF_IMPLINK                        = 0x3
+	AF_INET                           = 0x2
+	AF_INET6                          = 0x1c
+	AF_IPX                            = 0x17
+	AF_ISDN                           = 0x1a
+	AF_ISO                            = 0x7
+	AF_LAT                            = 0xe
+	AF_LINK                           = 0x12
+	AF_LOCAL                          = 0x1
+	AF_MAX                            = 0x26
+	AF_NATM                           = 0x1d
+	AF_NETBIOS                        = 0x6
+	AF_NETGRAPH                       = 0x20
+	AF_OSI                            = 0x7
+	AF_PUP                            = 0x4
+	AF_ROUTE                          = 0x11
+	AF_SCLUSTER                       = 0x22
+	AF_SIP                            = 0x18
+	AF_SLOW                           = 0x21
+	AF_SNA                            = 0xb
+	AF_UNIX                           = 0x1
+	AF_UNSPEC                         = 0x0
+	AF_VENDOR00                       = 0x27
+	AF_VENDOR01                       = 0x29
+	AF_VENDOR02                       = 0x2b
+	AF_VENDOR03                       = 0x2d
+	AF_VENDOR04                       = 0x2f
+	AF_VENDOR05                       = 0x31
+	AF_VENDOR06                       = 0x33
+	AF_VENDOR07                       = 0x35
+	AF_VENDOR08                       = 0x37
+	AF_VENDOR09                       = 0x39
+	AF_VENDOR10                       = 0x3b
+	AF_VENDOR11                       = 0x3d
+	AF_VENDOR12                       = 0x3f
+	AF_VENDOR13                       = 0x41
+	AF_VENDOR14                       = 0x43
+	AF_VENDOR15                       = 0x45
+	AF_VENDOR16                       = 0x47
+	AF_VENDOR17                       = 0x49
+	AF_VENDOR18                       = 0x4b
+	AF_VENDOR19                       = 0x4d
+	AF_VENDOR20                       = 0x4f
+	AF_VENDOR21                       = 0x51
+	AF_VENDOR22                       = 0x53
+	AF_VENDOR23                       = 0x55
+	AF_VENDOR24                       = 0x57
+	AF_VENDOR25                       = 0x59
+	AF_VENDOR26                       = 0x5b
+	AF_VENDOR27                       = 0x5d
+	AF_VENDOR28                       = 0x5f
+	AF_VENDOR29                       = 0x61
+	AF_VENDOR30                       = 0x63
+	AF_VENDOR31                       = 0x65
+	AF_VENDOR32                       = 0x67
+	AF_VENDOR33                       = 0x69
+	AF_VENDOR34                       = 0x6b
+	AF_VENDOR35                       = 0x6d
+	AF_VENDOR36                       = 0x6f
+	AF_VENDOR37                       = 0x71
+	AF_VENDOR38                       = 0x73
+	AF_VENDOR39                       = 0x75
+	AF_VENDOR40                       = 0x77
+	AF_VENDOR41                       = 0x79
+	AF_VENDOR42                       = 0x7b
+	AF_VENDOR43                       = 0x7d
+	AF_VENDOR44                       = 0x7f
+	AF_VENDOR45                       = 0x81
+	AF_VENDOR46                       = 0x83
+	AF_VENDOR47                       = 0x85
+	B0                                = 0x0
+	B110                              = 0x6e
+	B115200                           = 0x1c200
+	B1200                             = 0x4b0
+	B134                              = 0x86
+	B14400                            = 0x3840
+	B150                              = 0x96
+	B1800                             = 0x708
+	B19200                            = 0x4b00
+	B200                              = 0xc8
+	B230400                           = 0x38400
+	B2400                             = 0x960
+	B28800                            = 0x7080
+	B300                              = 0x12c
+	B38400                            = 0x9600
+	B460800                           = 0x70800
+	B4800                             = 0x12c0
+	B50                               = 0x32
+	B57600                            = 0xe100
+	B600                              = 0x258
+	B7200                             = 0x1c20
+	B75                               = 0x4b
+	B76800                            = 0x12c00
+	B921600                           = 0xe1000
+	B9600                             = 0x2580
+	BIOCFEEDBACK                      = 0x8004427c
+	BIOCFLUSH                         = 0x20004268
+	BIOCGBLEN                         = 0x40044266
+	BIOCGDIRECTION                    = 0x40044276
+	BIOCGDLT                          = 0x4004426a
+	BIOCGDLTLIST                      = 0xc0084279
+	BIOCGETBUFMODE                    = 0x4004427d
+	BIOCGETIF                         = 0x4020426b
+	BIOCGETZMAX                       = 0x4004427f
+	BIOCGHDRCMPLT                     = 0x40044274
+	BIOCGRSIG                         = 0x40044272
+	BIOCGRTIMEOUT                     = 0x400c426e
+	BIOCGSEESENT                      = 0x40044276
+	BIOCGSTATS                        = 0x4008426f
+	BIOCGTSTAMP                       = 0x40044283
+	BIOCIMMEDIATE                     = 0x80044270
+	BIOCLOCK                          = 0x2000427a
+	BIOCPROMISC                       = 0x20004269
+	BIOCROTZBUF                       = 0x400c4280
+	BIOCSBLEN                         = 0xc0044266
+	BIOCSDIRECTION                    = 0x80044277
+	BIOCSDLT                          = 0x80044278
+	BIOCSETBUFMODE                    = 0x8004427e
+	BIOCSETF                          = 0x80084267
+	BIOCSETFNR                        = 0x80084282
+	BIOCSETIF                         = 0x8020426c
+	BIOCSETWF                         = 0x8008427b
+	BIOCSETZBUF                       = 0x800c4281
+	BIOCSHDRCMPLT                     = 0x80044275
+	BIOCSRSIG                         = 0x80044273
+	BIOCSRTIMEOUT                     = 0x800c426d
+	BIOCSSEESENT                      = 0x80044277
+	BIOCSTSTAMP                       = 0x80044284
+	BIOCVERSION                       = 0x40044271
+	BPF_A                             = 0x10
+	BPF_ABS                           = 0x20
+	BPF_ADD                           = 0x0
+	BPF_ALIGNMENT                     = 0x4
+	BPF_ALU                           = 0x4
+	BPF_AND                           = 0x50
+	BPF_B                             = 0x10
+	BPF_BUFMODE_BUFFER                = 0x1
+	BPF_BUFMODE_ZBUF                  = 0x2
+	BPF_DIV                           = 0x30
+	BPF_H                             = 0x8
+	BPF_IMM                           = 0x0
+	BPF_IND                           = 0x40
+	BPF_JA                            = 0x0
+	BPF_JEQ                           = 0x10
+	BPF_JGE                           = 0x30
+	BPF_JGT                           = 0x20
+	BPF_JMP                           = 0x5
+	BPF_JSET                          = 0x40
+	BPF_K                             = 0x0
+	BPF_LD                            = 0x0
+	BPF_LDX                           = 0x1
+	BPF_LEN                           = 0x80
+	BPF_LSH                           = 0x60
+	BPF_MAJOR_VERSION                 = 0x1
+	BPF_MAXBUFSIZE                    = 0x80000
+	BPF_MAXINSNS                      = 0x200
+	BPF_MEM                           = 0x60
+	BPF_MEMWORDS                      = 0x10
+	BPF_MINBUFSIZE                    = 0x20
+	BPF_MINOR_VERSION                 = 0x1
+	BPF_MISC                          = 0x7
+	BPF_MSH                           = 0xa0
+	BPF_MUL                           = 0x20
+	BPF_NEG                           = 0x80
+	BPF_OR                            = 0x40
+	BPF_RELEASE                       = 0x30bb6
+	BPF_RET                           = 0x6
+	BPF_RSH                           = 0x70
+	BPF_ST                            = 0x2
+	BPF_STX                           = 0x3
+	BPF_SUB                           = 0x10
+	BPF_TAX                           = 0x0
+	BPF_TXA                           = 0x80
+	BPF_T_BINTIME                     = 0x2
+	BPF_T_BINTIME_FAST                = 0x102
+	BPF_T_BINTIME_MONOTONIC           = 0x202
+	BPF_T_BINTIME_MONOTONIC_FAST      = 0x302
+	BPF_T_FAST                        = 0x100
+	BPF_T_FLAG_MASK                   = 0x300
+	BPF_T_FORMAT_MASK                 = 0x3
+	BPF_T_MICROTIME                   = 0x0
+	BPF_T_MICROTIME_FAST              = 0x100
+	BPF_T_MICROTIME_MONOTONIC         = 0x200
+	BPF_T_MICROTIME_MONOTONIC_FAST    = 0x300
+	BPF_T_MONOTONIC                   = 0x200
+	BPF_T_MONOTONIC_FAST              = 0x300
+	BPF_T_NANOTIME                    = 0x1
+	BPF_T_NANOTIME_FAST               = 0x101
+	BPF_T_NANOTIME_MONOTONIC          = 0x201
+	BPF_T_NANOTIME_MONOTONIC_FAST     = 0x301
+	BPF_T_NONE                        = 0x3
+	BPF_T_NORMAL                      = 0x0
+	BPF_W                             = 0x0
+	BPF_X                             = 0x8
+	BRKINT                            = 0x2
+	CFLUSH                            = 0xf
+	CLOCAL                            = 0x8000
+	CREAD                             = 0x800
+	CS5                               = 0x0
+	CS6                               = 0x100
+	CS7                               = 0x200
+	CS8                               = 0x300
+	CSIZE                             = 0x300
+	CSTART                            = 0x11
+	CSTATUS                           = 0x14
+	CSTOP                             = 0x13
+	CSTOPB                            = 0x400
+	CSUSP                             = 0x1a
+	CTL_MAXNAME                       = 0x18
+	CTL_NET                           = 0x4
+	DLT_A429                          = 0xb8
+	DLT_A653_ICM                      = 0xb9
+	DLT_AIRONET_HEADER                = 0x78
+	DLT_AOS                           = 0xde
+	DLT_APPLE_IP_OVER_IEEE1394        = 0x8a
+	DLT_ARCNET                        = 0x7
+	DLT_ARCNET_LINUX                  = 0x81
+	DLT_ATM_CLIP                      = 0x13
+	DLT_ATM_RFC1483                   = 0xb
+	DLT_AURORA                        = 0x7e
+	DLT_AX25                          = 0x3
+	DLT_AX25_KISS                     = 0xca
+	DLT_BACNET_MS_TP                  = 0xa5
+	DLT_BLUETOOTH_HCI_H4              = 0xbb
+	DLT_BLUETOOTH_HCI_H4_WITH_PHDR    = 0xc9
+	DLT_CAN20B                        = 0xbe
+	DLT_CAN_SOCKETCAN                 = 0xe3
+	DLT_CHAOS                         = 0x5
+	DLT_CHDLC                         = 0x68
+	DLT_CISCO_IOS                     = 0x76
+	DLT_C_HDLC                        = 0x68
+	DLT_C_HDLC_WITH_DIR               = 0xcd
+	DLT_DBUS                          = 0xe7
+	DLT_DECT                          = 0xdd
+	DLT_DOCSIS                        = 0x8f
+	DLT_DVB_CI                        = 0xeb
+	DLT_ECONET                        = 0x73
+	DLT_EN10MB                        = 0x1
+	DLT_EN3MB                         = 0x2
+	DLT_ENC                           = 0x6d
+	DLT_ERF                           = 0xc5
+	DLT_ERF_ETH                       = 0xaf
+	DLT_ERF_POS                       = 0xb0
+	DLT_FC_2                          = 0xe0
+	DLT_FC_2_WITH_FRAME_DELIMS        = 0xe1
+	DLT_FDDI                          = 0xa
+	DLT_FLEXRAY                       = 0xd2
+	DLT_FRELAY                        = 0x6b
+	DLT_FRELAY_WITH_DIR               = 0xce
+	DLT_GCOM_SERIAL                   = 0xad
+	DLT_GCOM_T1E1                     = 0xac
+	DLT_GPF_F                         = 0xab
+	DLT_GPF_T                         = 0xaa
+	DLT_GPRS_LLC                      = 0xa9
+	DLT_GSMTAP_ABIS                   = 0xda
+	DLT_GSMTAP_UM                     = 0xd9
+	DLT_HHDLC                         = 0x79
+	DLT_IBM_SN                        = 0x92
+	DLT_IBM_SP                        = 0x91
+	DLT_IEEE802                       = 0x6
+	DLT_IEEE802_11                    = 0x69
+	DLT_IEEE802_11_RADIO              = 0x7f
+	DLT_IEEE802_11_RADIO_AVS          = 0xa3
+	DLT_IEEE802_15_4                  = 0xc3
+	DLT_IEEE802_15_4_LINUX            = 0xbf
+	DLT_IEEE802_15_4_NOFCS            = 0xe6
+	DLT_IEEE802_15_4_NONASK_PHY       = 0xd7
+	DLT_IEEE802_16_MAC_CPS            = 0xbc
+	DLT_IEEE802_16_MAC_CPS_RADIO      = 0xc1
+	DLT_IPFILTER                      = 0x74
+	DLT_IPMB                          = 0xc7
+	DLT_IPMB_LINUX                    = 0xd1
+	DLT_IPNET                         = 0xe2
+	DLT_IPOIB                         = 0xf2
+	DLT_IPV4                          = 0xe4
+	DLT_IPV6                          = 0xe5
+	DLT_IP_OVER_FC                    = 0x7a
+	DLT_JUNIPER_ATM1                  = 0x89
+	DLT_JUNIPER_ATM2                  = 0x87
+	DLT_JUNIPER_ATM_CEMIC             = 0xee
+	DLT_JUNIPER_CHDLC                 = 0xb5
+	DLT_JUNIPER_ES                    = 0x84
+	DLT_JUNIPER_ETHER                 = 0xb2
+	DLT_JUNIPER_FIBRECHANNEL          = 0xea
+	DLT_JUNIPER_FRELAY                = 0xb4
+	DLT_JUNIPER_GGSN                  = 0x85
+	DLT_JUNIPER_ISM                   = 0xc2
+	DLT_JUNIPER_MFR                   = 0x86
+	DLT_JUNIPER_MLFR                  = 0x83
+	DLT_JUNIPER_MLPPP                 = 0x82
+	DLT_JUNIPER_MONITOR               = 0xa4
+	DLT_JUNIPER_PIC_PEER              = 0xae
+	DLT_JUNIPER_PPP                   = 0xb3
+	DLT_JUNIPER_PPPOE                 = 0xa7
+	DLT_JUNIPER_PPPOE_ATM             = 0xa8
+	DLT_JUNIPER_SERVICES              = 0x88
+	DLT_JUNIPER_SRX_E2E               = 0xe9
+	DLT_JUNIPER_ST                    = 0xc8
+	DLT_JUNIPER_VP                    = 0xb7
+	DLT_JUNIPER_VS                    = 0xe8
+	DLT_LAPB_WITH_DIR                 = 0xcf
+	DLT_LAPD                          = 0xcb
+	DLT_LIN                           = 0xd4
+	DLT_LINUX_EVDEV                   = 0xd8
+	DLT_LINUX_IRDA                    = 0x90
+	DLT_LINUX_LAPD                    = 0xb1
+	DLT_LINUX_PPP_WITHDIRECTION       = 0xa6
+	DLT_LINUX_SLL                     = 0x71
+	DLT_LOOP                          = 0x6c
+	DLT_LTALK                         = 0x72
+	DLT_MATCHING_MAX                  = 0xf2
+	DLT_MATCHING_MIN                  = 0x68
+	DLT_MFR                           = 0xb6
+	DLT_MOST                          = 0xd3
+	DLT_MPLS                          = 0xdb
+	DLT_MTP2                          = 0x8c
+	DLT_MTP2_WITH_PHDR                = 0x8b
+	DLT_MTP3                          = 0x8d
+	DLT_MUX27010                      = 0xec
+	DLT_NETANALYZER                   = 0xf0
+	DLT_NETANALYZER_TRANSPARENT       = 0xf1
+	DLT_NFLOG                         = 0xef
+	DLT_NULL                          = 0x0
+	DLT_PCI_EXP                       = 0x7d
+	DLT_PFLOG                         = 0x75
+	DLT_PFSYNC                        = 0x79
+	DLT_PPI                           = 0xc0
+	DLT_PPP                           = 0x9
+	DLT_PPP_BSDOS                     = 0x10
+	DLT_PPP_ETHER                     = 0x33
+	DLT_PPP_PPPD                      = 0xa6
+	DLT_PPP_SERIAL                    = 0x32
+	DLT_PPP_WITH_DIR                  = 0xcc
+	DLT_PPP_WITH_DIRECTION            = 0xa6
+	DLT_PRISM_HEADER                  = 0x77
+	DLT_PRONET                        = 0x4
+	DLT_RAIF1                         = 0xc6
+	DLT_RAW                           = 0xc
+	DLT_RIO                           = 0x7c
+	DLT_SCCP                          = 0x8e
+	DLT_SITA                          = 0xc4
+	DLT_SLIP                          = 0x8
+	DLT_SLIP_BSDOS                    = 0xf
+	DLT_STANAG_5066_D_PDU             = 0xed
+	DLT_SUNATM                        = 0x7b
+	DLT_SYMANTEC_FIREWALL             = 0x63
+	DLT_TZSP                          = 0x80
+	DLT_USB                           = 0xba
+	DLT_USB_LINUX                     = 0xbd
+	DLT_USB_LINUX_MMAPPED             = 0xdc
+	DLT_USER0                         = 0x93
+	DLT_USER1                         = 0x94
+	DLT_USER10                        = 0x9d
+	DLT_USER11                        = 0x9e
+	DLT_USER12                        = 0x9f
+	DLT_USER13                        = 0xa0
+	DLT_USER14                        = 0xa1
+	DLT_USER15                        = 0xa2
+	DLT_USER2                         = 0x95
+	DLT_USER3                         = 0x96
+	DLT_USER4                         = 0x97
+	DLT_USER5                         = 0x98
+	DLT_USER6                         = 0x99
+	DLT_USER7                         = 0x9a
+	DLT_USER8                         = 0x9b
+	DLT_USER9                         = 0x9c
+	DLT_WIHART                        = 0xdf
+	DLT_X2E_SERIAL                    = 0xd5
+	DLT_X2E_XORAYA                    = 0xd6
+	DT_BLK                            = 0x6
+	DT_CHR                            = 0x2
+	DT_DIR                            = 0x4
+	DT_FIFO                           = 0x1
+	DT_LNK                            = 0xa
+	DT_REG                            = 0x8
+	DT_SOCK                           = 0xc
+	DT_UNKNOWN                        = 0x0
+	DT_WHT                            = 0xe
+	ECHO                              = 0x8
+	ECHOCTL                           = 0x40
+	ECHOE                             = 0x2
+	ECHOK                             = 0x4
+	ECHOKE                            = 0x1
+	ECHONL                            = 0x10
+	ECHOPRT                           = 0x20
+	EVFILT_AIO                        = -0x3
+	EVFILT_FS                         = -0x9
+	EVFILT_LIO                        = -0xa
+	EVFILT_PROC                       = -0x5
+	EVFILT_READ                       = -0x1
+	EVFILT_SIGNAL                     = -0x6
+	EVFILT_SYSCOUNT                   = 0xb
+	EVFILT_TIMER                      = -0x7
+	EVFILT_USER                       = -0xb
+	EVFILT_VNODE                      = -0x4
+	EVFILT_WRITE                      = -0x2
+	EV_ADD                            = 0x1
+	EV_CLEAR                          = 0x20
+	EV_DELETE                         = 0x2
+	EV_DISABLE                        = 0x8
+	EV_DISPATCH                       = 0x80
+	EV_ENABLE                         = 0x4
+	EV_EOF                            = 0x8000
+	EV_ERROR                          = 0x4000
+	EV_FLAG1                          = 0x2000
+	EV_ONESHOT                        = 0x10
+	EV_RECEIPT                        = 0x40
+	EV_SYSFLAGS                       = 0xf000
+	EXTA                              = 0x4b00
+	EXTB                              = 0x9600
+	EXTPROC                           = 0x800
+	FD_CLOEXEC                        = 0x1
+	FD_SETSIZE                        = 0x400
+	FLUSHO                            = 0x800000
+	F_CANCEL                          = 0x5
+	F_DUP2FD                          = 0xa
+	F_DUP2FD_CLOEXEC                  = 0x12
+	F_DUPFD                           = 0x0
+	F_DUPFD_CLOEXEC                   = 0x11
+	F_GETFD                           = 0x1
+	F_GETFL                           = 0x3
+	F_GETLK                           = 0xb
+	F_GETOWN                          = 0x5
+	F_OGETLK                          = 0x7
+	F_OK                              = 0x0
+	F_OSETLK                          = 0x8
+	F_OSETLKW                         = 0x9
+	F_RDAHEAD                         = 0x10
+	F_RDLCK                           = 0x1
+	F_READAHEAD                       = 0xf
+	F_SETFD                           = 0x2
+	F_SETFL                           = 0x4
+	F_SETLK                           = 0xc
+	F_SETLKW                          = 0xd
+	F_SETLK_REMOTE                    = 0xe
+	F_SETOWN                          = 0x6
+	F_UNLCK                           = 0x2
+	F_UNLCKSYS                        = 0x4
+	F_WRLCK                           = 0x3
+	HUPCL                             = 0x4000
+	ICANON                            = 0x100
+	ICRNL                             = 0x100
+	IEXTEN                            = 0x400
+	IFAN_ARRIVAL                      = 0x0
+	IFAN_DEPARTURE                    = 0x1
+	IFF_ALLMULTI                      = 0x200
+	IFF_ALTPHYS                       = 0x4000
+	IFF_BROADCAST                     = 0x2
+	IFF_CANTCHANGE                    = 0x218f72
+	IFF_CANTCONFIG                    = 0x10000
+	IFF_DEBUG                         = 0x4
+	IFF_DRV_OACTIVE                   = 0x400
+	IFF_DRV_RUNNING                   = 0x40
+	IFF_DYING                         = 0x200000
+	IFF_LINK0                         = 0x1000
+	IFF_LINK1                         = 0x2000
+	IFF_LINK2                         = 0x4000
+	IFF_LOOPBACK                      = 0x8
+	IFF_MONITOR                       = 0x40000
+	IFF_MULTICAST                     = 0x8000
+	IFF_NOARP                         = 0x80
+	IFF_OACTIVE                       = 0x400
+	IFF_POINTOPOINT                   = 0x10
+	IFF_PPROMISC                      = 0x20000
+	IFF_PROMISC                       = 0x100
+	IFF_RENAMING                      = 0x400000
+	IFF_RUNNING                       = 0x40
+	IFF_SIMPLEX                       = 0x800
+	IFF_SMART                         = 0x20
+	IFF_STATICARP                     = 0x80000
+	IFF_UP                            = 0x1
+	IFNAMSIZ                          = 0x10
+	IFT_1822                          = 0x2
+	IFT_A12MPPSWITCH                  = 0x82
+	IFT_AAL2                          = 0xbb
+	IFT_AAL5                          = 0x31
+	IFT_ADSL                          = 0x5e
+	IFT_AFLANE8023                    = 0x3b
+	IFT_AFLANE8025                    = 0x3c
+	IFT_ARAP                          = 0x58
+	IFT_ARCNET                        = 0x23
+	IFT_ARCNETPLUS                    = 0x24
+	IFT_ASYNC                         = 0x54
+	IFT_ATM                           = 0x25
+	IFT_ATMDXI                        = 0x69
+	IFT_ATMFUNI                       = 0x6a
+	IFT_ATMIMA                        = 0x6b
+	IFT_ATMLOGICAL                    = 0x50
+	IFT_ATMRADIO                      = 0xbd
+	IFT_ATMSUBINTERFACE               = 0x86
+	IFT_ATMVCIENDPT                   = 0xc2
+	IFT_ATMVIRTUAL                    = 0x95
+	IFT_BGPPOLICYACCOUNTING           = 0xa2
+	IFT_BRIDGE                        = 0xd1
+	IFT_BSC                           = 0x53
+	IFT_CCTEMUL                       = 0x3d
+	IFT_CEPT                          = 0x13
+	IFT_CES                           = 0x85
+	IFT_CHANNEL                       = 0x46
+	IFT_CNR                           = 0x55
+	IFT_COFFEE                        = 0x84
+	IFT_COMPOSITELINK                 = 0x9b
+	IFT_DCN                           = 0x8d
+	IFT_DIGITALPOWERLINE              = 0x8a
+	IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
+	IFT_DLSW                          = 0x4a
+	IFT_DOCSCABLEDOWNSTREAM           = 0x80
+	IFT_DOCSCABLEMACLAYER             = 0x7f
+	IFT_DOCSCABLEUPSTREAM             = 0x81
+	IFT_DS0                           = 0x51
+	IFT_DS0BUNDLE                     = 0x52
+	IFT_DS1FDL                        = 0xaa
+	IFT_DS3                           = 0x1e
+	IFT_DTM                           = 0x8c
+	IFT_DVBASILN                      = 0xac
+	IFT_DVBASIOUT                     = 0xad
+	IFT_DVBRCCDOWNSTREAM              = 0x93
+	IFT_DVBRCCMACLAYER                = 0x92
+	IFT_DVBRCCUPSTREAM                = 0x94
+	IFT_ENC                           = 0xf4
+	IFT_EON                           = 0x19
+	IFT_EPLRS                         = 0x57
+	IFT_ESCON                         = 0x49
+	IFT_ETHER                         = 0x6
+	IFT_FAITH                         = 0xf2
+	IFT_FAST                          = 0x7d
+	IFT_FASTETHER                     = 0x3e
+	IFT_FASTETHERFX                   = 0x45
+	IFT_FDDI                          = 0xf
+	IFT_FIBRECHANNEL                  = 0x38
+	IFT_FRAMERELAYINTERCONNECT        = 0x3a
+	IFT_FRAMERELAYMPI                 = 0x5c
+	IFT_FRDLCIENDPT                   = 0xc1
+	IFT_FRELAY                        = 0x20
+	IFT_FRELAYDCE                     = 0x2c
+	IFT_FRF16MFRBUNDLE                = 0xa3
+	IFT_FRFORWARD                     = 0x9e
+	IFT_G703AT2MB                     = 0x43
+	IFT_G703AT64K                     = 0x42
+	IFT_GIF                           = 0xf0
+	IFT_GIGABITETHERNET               = 0x75
+	IFT_GR303IDT                      = 0xb2
+	IFT_GR303RDT                      = 0xb1
+	IFT_H323GATEKEEPER                = 0xa4
+	IFT_H323PROXY                     = 0xa5
+	IFT_HDH1822                       = 0x3
+	IFT_HDLC                          = 0x76
+	IFT_HDSL2                         = 0xa8
+	IFT_HIPERLAN2                     = 0xb7
+	IFT_HIPPI                         = 0x2f
+	IFT_HIPPIINTERFACE                = 0x39
+	IFT_HOSTPAD                       = 0x5a
+	IFT_HSSI                          = 0x2e
+	IFT_HY                            = 0xe
+	IFT_IBM370PARCHAN                 = 0x48
+	IFT_IDSL                          = 0x9a
+	IFT_IEEE1394                      = 0x90
+	IFT_IEEE80211                     = 0x47
+	IFT_IEEE80212                     = 0x37
+	IFT_IEEE8023ADLAG                 = 0xa1
+	IFT_IFGSN                         = 0x91
+	IFT_IMT                           = 0xbe
+	IFT_INFINIBAND                    = 0xc7
+	IFT_INTERLEAVE                    = 0x7c
+	IFT_IP                            = 0x7e
+	IFT_IPFORWARD                     = 0x8e
+	IFT_IPOVERATM                     = 0x72
+	IFT_IPOVERCDLC                    = 0x6d
+	IFT_IPOVERCLAW                    = 0x6e
+	IFT_IPSWITCH                      = 0x4e
+	IFT_IPXIP                         = 0xf9
+	IFT_ISDN                          = 0x3f
+	IFT_ISDNBASIC                     = 0x14
+	IFT_ISDNPRIMARY                   = 0x15
+	IFT_ISDNS                         = 0x4b
+	IFT_ISDNU                         = 0x4c
+	IFT_ISO88022LLC                   = 0x29
+	IFT_ISO88023                      = 0x7
+	IFT_ISO88024                      = 0x8
+	IFT_ISO88025                      = 0x9
+	IFT_ISO88025CRFPINT               = 0x62
+	IFT_ISO88025DTR                   = 0x56
+	IFT_ISO88025FIBER                 = 0x73
+	IFT_ISO88026                      = 0xa
+	IFT_ISUP                          = 0xb3
+	IFT_L2VLAN                        = 0x87
+	IFT_L3IPVLAN                      = 0x88
+	IFT_L3IPXVLAN                     = 0x89
+	IFT_LAPB                          = 0x10
+	IFT_LAPD                          = 0x4d
+	IFT_LAPF                          = 0x77
+	IFT_LOCALTALK                     = 0x2a
+	IFT_LOOP                          = 0x18
+	IFT_MEDIAMAILOVERIP               = 0x8b
+	IFT_MFSIGLINK                     = 0xa7
+	IFT_MIOX25                        = 0x26
+	IFT_MODEM                         = 0x30
+	IFT_MPC                           = 0x71
+	IFT_MPLS                          = 0xa6
+	IFT_MPLSTUNNEL                    = 0x96
+	IFT_MSDSL                         = 0x8f
+	IFT_MVL                           = 0xbf
+	IFT_MYRINET                       = 0x63
+	IFT_NFAS                          = 0xaf
+	IFT_NSIP                          = 0x1b
+	IFT_OPTICALCHANNEL                = 0xc3
+	IFT_OPTICALTRANSPORT              = 0xc4
+	IFT_OTHER                         = 0x1
+	IFT_P10                           = 0xc
+	IFT_P80                           = 0xd
+	IFT_PARA                          = 0x22
+	IFT_PFLOG                         = 0xf6
+	IFT_PFSYNC                        = 0xf7
+	IFT_PLC                           = 0xae
+	IFT_POS                           = 0xab
+	IFT_PPP                           = 0x17
+	IFT_PPPMULTILINKBUNDLE            = 0x6c
+	IFT_PROPBWAP2MP                   = 0xb8
+	IFT_PROPCNLS                      = 0x59
+	IFT_PROPDOCSWIRELESSDOWNSTREAM    = 0xb5
+	IFT_PROPDOCSWIRELESSMACLAYER      = 0xb4
+	IFT_PROPDOCSWIRELESSUPSTREAM      = 0xb6
+	IFT_PROPMUX                       = 0x36
+	IFT_PROPVIRTUAL                   = 0x35
+	IFT_PROPWIRELESSP2P               = 0x9d
+	IFT_PTPSERIAL                     = 0x16
+	IFT_PVC                           = 0xf1
+	IFT_QLLC                          = 0x44
+	IFT_RADIOMAC                      = 0xbc
+	IFT_RADSL                         = 0x5f
+	IFT_REACHDSL                      = 0xc0
+	IFT_RFC1483                       = 0x9f
+	IFT_RS232                         = 0x21
+	IFT_RSRB                          = 0x4f
+	IFT_SDLC                          = 0x11
+	IFT_SDSL                          = 0x60
+	IFT_SHDSL                         = 0xa9
+	IFT_SIP                           = 0x1f
+	IFT_SLIP                          = 0x1c
+	IFT_SMDSDXI                       = 0x2b
+	IFT_SMDSICIP                      = 0x34
+	IFT_SONET                         = 0x27
+	IFT_SONETOVERHEADCHANNEL          = 0xb9
+	IFT_SONETPATH                     = 0x32
+	IFT_SONETVT                       = 0x33
+	IFT_SRP                           = 0x97
+	IFT_SS7SIGLINK                    = 0x9c
+	IFT_STACKTOSTACK                  = 0x6f
+	IFT_STARLAN                       = 0xb
+	IFT_STF                           = 0xd7
+	IFT_T1                            = 0x12
+	IFT_TDLC                          = 0x74
+	IFT_TERMPAD                       = 0x5b
+	IFT_TR008                         = 0xb0
+	IFT_TRANSPHDLC                    = 0x7b
+	IFT_TUNNEL                        = 0x83
+	IFT_ULTRA                         = 0x1d
+	IFT_USB                           = 0xa0
+	IFT_V11                           = 0x40
+	IFT_V35                           = 0x2d
+	IFT_V36                           = 0x41
+	IFT_V37                           = 0x78
+	IFT_VDSL                          = 0x61
+	IFT_VIRTUALIPADDRESS              = 0x70
+	IFT_VOICEEM                       = 0x64
+	IFT_VOICEENCAP                    = 0x67
+	IFT_VOICEFXO                      = 0x65
+	IFT_VOICEFXS                      = 0x66
+	IFT_VOICEOVERATM                  = 0x98
+	IFT_VOICEOVERFRAMERELAY           = 0x99
+	IFT_VOICEOVERIP                   = 0x68
+	IFT_X213                          = 0x5d
+	IFT_X25                           = 0x5
+	IFT_X25DDN                        = 0x4
+	IFT_X25HUNTGROUP                  = 0x7a
+	IFT_X25MLP                        = 0x79
+	IFT_X25PLE                        = 0x28
+	IFT_XETHER                        = 0x1a
+	IGNBRK                            = 0x1
+	IGNCR                             = 0x80
+	IGNPAR                            = 0x4
+	IMAXBEL                           = 0x2000
+	INLCR                             = 0x40
+	INPCK                             = 0x10
+	IN_CLASSA_HOST                    = 0xffffff
+	IN_CLASSA_MAX                     = 0x80
+	IN_CLASSA_NET                     = 0xff000000
+	IN_CLASSA_NSHIFT                  = 0x18
+	IN_CLASSB_HOST                    = 0xffff
+	IN_CLASSB_MAX                     = 0x10000
+	IN_CLASSB_NET                     = 0xffff0000
+	IN_CLASSB_NSHIFT                  = 0x10
+	IN_CLASSC_HOST                    = 0xff
+	IN_CLASSC_NET                     = 0xffffff00
+	IN_CLASSC_NSHIFT                  = 0x8
+	IN_CLASSD_HOST                    = 0xfffffff
+	IN_CLASSD_NET                     = 0xf0000000
+	IN_CLASSD_NSHIFT                  = 0x1c
+	IN_LOOPBACKNET                    = 0x7f
+	IN_RFC3021_MASK                   = 0xfffffffe
+	IPPROTO_3PC                       = 0x22
+	IPPROTO_ADFS                      = 0x44
+	IPPROTO_AH                        = 0x33
+	IPPROTO_AHIP                      = 0x3d
+	IPPROTO_APES                      = 0x63
+	IPPROTO_ARGUS                     = 0xd
+	IPPROTO_AX25                      = 0x5d
+	IPPROTO_BHA                       = 0x31
+	IPPROTO_BLT                       = 0x1e
+	IPPROTO_BRSATMON                  = 0x4c
+	IPPROTO_CARP                      = 0x70
+	IPPROTO_CFTP                      = 0x3e
+	IPPROTO_CHAOS                     = 0x10
+	IPPROTO_CMTP                      = 0x26
+	IPPROTO_CPHB                      = 0x49
+	IPPROTO_CPNX                      = 0x48
+	IPPROTO_DDP                       = 0x25
+	IPPROTO_DGP                       = 0x56
+	IPPROTO_DIVERT                    = 0x102
+	IPPROTO_DONE                      = 0x101
+	IPPROTO_DSTOPTS                   = 0x3c
+	IPPROTO_EGP                       = 0x8
+	IPPROTO_EMCON                     = 0xe
+	IPPROTO_ENCAP                     = 0x62
+	IPPROTO_EON                       = 0x50
+	IPPROTO_ESP                       = 0x32
+	IPPROTO_ETHERIP                   = 0x61
+	IPPROTO_FRAGMENT                  = 0x2c
+	IPPROTO_GGP                       = 0x3
+	IPPROTO_GMTP                      = 0x64
+	IPPROTO_GRE                       = 0x2f
+	IPPROTO_HELLO                     = 0x3f
+	IPPROTO_HMP                       = 0x14
+	IPPROTO_HOPOPTS                   = 0x0
+	IPPROTO_ICMP                      = 0x1
+	IPPROTO_ICMPV6                    = 0x3a
+	IPPROTO_IDP                       = 0x16
+	IPPROTO_IDPR                      = 0x23
+	IPPROTO_IDRP                      = 0x2d
+	IPPROTO_IGMP                      = 0x2
+	IPPROTO_IGP                       = 0x55
+	IPPROTO_IGRP                      = 0x58
+	IPPROTO_IL                        = 0x28
+	IPPROTO_INLSP                     = 0x34
+	IPPROTO_INP                       = 0x20
+	IPPROTO_IP                        = 0x0
+	IPPROTO_IPCOMP                    = 0x6c
+	IPPROTO_IPCV                      = 0x47
+	IPPROTO_IPEIP                     = 0x5e
+	IPPROTO_IPIP                      = 0x4
+	IPPROTO_IPPC                      = 0x43
+	IPPROTO_IPV4                      = 0x4
+	IPPROTO_IPV6                      = 0x29
+	IPPROTO_IRTP                      = 0x1c
+	IPPROTO_KRYPTOLAN                 = 0x41
+	IPPROTO_LARP                      = 0x5b
+	IPPROTO_LEAF1                     = 0x19
+	IPPROTO_LEAF2                     = 0x1a
+	IPPROTO_MAX                       = 0x100
+	IPPROTO_MAXID                     = 0x34
+	IPPROTO_MEAS                      = 0x13
+	IPPROTO_MH                        = 0x87
+	IPPROTO_MHRP                      = 0x30
+	IPPROTO_MICP                      = 0x5f
+	IPPROTO_MOBILE                    = 0x37
+	IPPROTO_MPLS                      = 0x89
+	IPPROTO_MTP                       = 0x5c
+	IPPROTO_MUX                       = 0x12
+	IPPROTO_ND                        = 0x4d
+	IPPROTO_NHRP                      = 0x36
+	IPPROTO_NONE                      = 0x3b
+	IPPROTO_NSP                       = 0x1f
+	IPPROTO_NVPII                     = 0xb
+	IPPROTO_OLD_DIVERT                = 0xfe
+	IPPROTO_OSPFIGP                   = 0x59
+	IPPROTO_PFSYNC                    = 0xf0
+	IPPROTO_PGM                       = 0x71
+	IPPROTO_PIGP                      = 0x9
+	IPPROTO_PIM                       = 0x67
+	IPPROTO_PRM                       = 0x15
+	IPPROTO_PUP                       = 0xc
+	IPPROTO_PVP                       = 0x4b
+	IPPROTO_RAW                       = 0xff
+	IPPROTO_RCCMON                    = 0xa
+	IPPROTO_RDP                       = 0x1b
+	IPPROTO_ROUTING                   = 0x2b
+	IPPROTO_RSVP                      = 0x2e
+	IPPROTO_RVD                       = 0x42
+	IPPROTO_SATEXPAK                  = 0x40
+	IPPROTO_SATMON                    = 0x45
+	IPPROTO_SCCSP                     = 0x60
+	IPPROTO_SCTP                      = 0x84
+	IPPROTO_SDRP                      = 0x2a
+	IPPROTO_SEND                      = 0x103
+	IPPROTO_SEP                       = 0x21
+	IPPROTO_SKIP                      = 0x39
+	IPPROTO_SPACER                    = 0x7fff
+	IPPROTO_SRPC                      = 0x5a
+	IPPROTO_ST                        = 0x7
+	IPPROTO_SVMTP                     = 0x52
+	IPPROTO_SWIPE                     = 0x35
+	IPPROTO_TCF                       = 0x57
+	IPPROTO_TCP                       = 0x6
+	IPPROTO_TLSP                      = 0x38
+	IPPROTO_TP                        = 0x1d
+	IPPROTO_TPXX                      = 0x27
+	IPPROTO_TRUNK1                    = 0x17
+	IPPROTO_TRUNK2                    = 0x18
+	IPPROTO_TTP                       = 0x54
+	IPPROTO_UDP                       = 0x11
+	IPPROTO_VINES                     = 0x53
+	IPPROTO_VISA                      = 0x46
+	IPPROTO_VMTP                      = 0x51
+	IPPROTO_WBEXPAK                   = 0x4f
+	IPPROTO_WBMON                     = 0x4e
+	IPPROTO_WSN                       = 0x4a
+	IPPROTO_XNET                      = 0xf
+	IPPROTO_XTP                       = 0x24
+	IPV6_AUTOFLOWLABEL                = 0x3b
+	IPV6_BINDANY                      = 0x40
+	IPV6_BINDV6ONLY                   = 0x1b
+	IPV6_CHECKSUM                     = 0x1a
+	IPV6_DEFAULT_MULTICAST_HOPS       = 0x1
+	IPV6_DEFAULT_MULTICAST_LOOP       = 0x1
+	IPV6_DEFHLIM                      = 0x40
+	IPV6_DONTFRAG                     = 0x3e
+	IPV6_DSTOPTS                      = 0x32
+	IPV6_FAITH                        = 0x1d
+	IPV6_FLOWINFO_MASK                = 0xffffff0f
+	IPV6_FLOWLABEL_MASK               = 0xffff0f00
+	IPV6_FRAGTTL                      = 0x78
+	IPV6_FW_ADD                       = 0x1e
+	IPV6_FW_DEL                       = 0x1f
+	IPV6_FW_FLUSH                     = 0x20
+	IPV6_FW_GET                       = 0x22
+	IPV6_FW_ZERO                      = 0x21
+	IPV6_HLIMDEC                      = 0x1
+	IPV6_HOPLIMIT                     = 0x2f
+	IPV6_HOPOPTS                      = 0x31
+	IPV6_IPSEC_POLICY                 = 0x1c
+	IPV6_JOIN_GROUP                   = 0xc
+	IPV6_LEAVE_GROUP                  = 0xd
+	IPV6_MAXHLIM                      = 0xff
+	IPV6_MAXOPTHDR                    = 0x800
+	IPV6_MAXPACKET                    = 0xffff
+	IPV6_MAX_GROUP_SRC_FILTER         = 0x200
+	IPV6_MAX_MEMBERSHIPS              = 0xfff
+	IPV6_MAX_SOCK_SRC_FILTER          = 0x80
+	IPV6_MIN_MEMBERSHIPS              = 0x1f
+	IPV6_MMTU                         = 0x500
+	IPV6_MSFILTER                     = 0x4a
+	IPV6_MULTICAST_HOPS               = 0xa
+	IPV6_MULTICAST_IF                 = 0x9
+	IPV6_MULTICAST_LOOP               = 0xb
+	IPV6_NEXTHOP                      = 0x30
+	IPV6_PATHMTU                      = 0x2c
+	IPV6_PKTINFO                      = 0x2e
+	IPV6_PORTRANGE                    = 0xe
+	IPV6_PORTRANGE_DEFAULT            = 0x0
+	IPV6_PORTRANGE_HIGH               = 0x1
+	IPV6_PORTRANGE_LOW                = 0x2
+	IPV6_PREFER_TEMPADDR              = 0x3f
+	IPV6_RECVDSTOPTS                  = 0x28
+	IPV6_RECVHOPLIMIT                 = 0x25
+	IPV6_RECVHOPOPTS                  = 0x27
+	IPV6_RECVPATHMTU                  = 0x2b
+	IPV6_RECVPKTINFO                  = 0x24
+	IPV6_RECVRTHDR                    = 0x26
+	IPV6_RECVTCLASS                   = 0x39
+	IPV6_RTHDR                        = 0x33
+	IPV6_RTHDRDSTOPTS                 = 0x23
+	IPV6_RTHDR_LOOSE                  = 0x0
+	IPV6_RTHDR_STRICT                 = 0x1
+	IPV6_RTHDR_TYPE_0                 = 0x0
+	IPV6_SOCKOPT_RESERVED1            = 0x3
+	IPV6_TCLASS                       = 0x3d
+	IPV6_UNICAST_HOPS                 = 0x4
+	IPV6_USE_MIN_MTU                  = 0x2a
+	IPV6_V6ONLY                       = 0x1b
+	IPV6_VERSION                      = 0x60
+	IPV6_VERSION_MASK                 = 0xf0
+	IP_ADD_MEMBERSHIP                 = 0xc
+	IP_ADD_SOURCE_MEMBERSHIP          = 0x46
+	IP_BINDANY                        = 0x18
+	IP_BLOCK_SOURCE                   = 0x48
+	IP_DEFAULT_MULTICAST_LOOP         = 0x1
+	IP_DEFAULT_MULTICAST_TTL          = 0x1
+	IP_DF                             = 0x4000
+	IP_DONTFRAG                       = 0x43
+	IP_DROP_MEMBERSHIP                = 0xd
+	IP_DROP_SOURCE_MEMBERSHIP         = 0x47
+	IP_DUMMYNET3                      = 0x31
+	IP_DUMMYNET_CONFIGURE             = 0x3c
+	IP_DUMMYNET_DEL                   = 0x3d
+	IP_DUMMYNET_FLUSH                 = 0x3e
+	IP_DUMMYNET_GET                   = 0x40
+	IP_FAITH                          = 0x16
+	IP_FW3                            = 0x30
+	IP_FW_ADD                         = 0x32
+	IP_FW_DEL                         = 0x33
+	IP_FW_FLUSH                       = 0x34
+	IP_FW_GET                         = 0x36
+	IP_FW_NAT_CFG                     = 0x38
+	IP_FW_NAT_DEL                     = 0x39
+	IP_FW_NAT_GET_CONFIG              = 0x3a
+	IP_FW_NAT_GET_LOG                 = 0x3b
+	IP_FW_RESETLOG                    = 0x37
+	IP_FW_TABLE_ADD                   = 0x28
+	IP_FW_TABLE_DEL                   = 0x29
+	IP_FW_TABLE_FLUSH                 = 0x2a
+	IP_FW_TABLE_GETSIZE               = 0x2b
+	IP_FW_TABLE_LIST                  = 0x2c
+	IP_FW_ZERO                        = 0x35
+	IP_HDRINCL                        = 0x2
+	IP_IPSEC_POLICY                   = 0x15
+	IP_MAXPACKET                      = 0xffff
+	IP_MAX_GROUP_SRC_FILTER           = 0x200
+	IP_MAX_MEMBERSHIPS                = 0xfff
+	IP_MAX_SOCK_MUTE_FILTER           = 0x80
+	IP_MAX_SOCK_SRC_FILTER            = 0x80
+	IP_MAX_SOURCE_FILTER              = 0x400
+	IP_MF                             = 0x2000
+	IP_MINTTL                         = 0x42
+	IP_MIN_MEMBERSHIPS                = 0x1f
+	IP_MSFILTER                       = 0x4a
+	IP_MSS                            = 0x240
+	IP_MULTICAST_IF                   = 0x9
+	IP_MULTICAST_LOOP                 = 0xb
+	IP_MULTICAST_TTL                  = 0xa
+	IP_MULTICAST_VIF                  = 0xe
+	IP_OFFMASK                        = 0x1fff
+	IP_ONESBCAST                      = 0x17
+	IP_OPTIONS                        = 0x1
+	IP_PORTRANGE                      = 0x13
+	IP_PORTRANGE_DEFAULT              = 0x0
+	IP_PORTRANGE_HIGH                 = 0x1
+	IP_PORTRANGE_LOW                  = 0x2
+	IP_RECVDSTADDR                    = 0x7
+	IP_RECVIF                         = 0x14
+	IP_RECVOPTS                       = 0x5
+	IP_RECVRETOPTS                    = 0x6
+	IP_RECVTOS                        = 0x44
+	IP_RECVTTL                        = 0x41
+	IP_RETOPTS                        = 0x8
+	IP_RF                             = 0x8000
+	IP_RSVP_OFF                       = 0x10
+	IP_RSVP_ON                        = 0xf
+	IP_RSVP_VIF_OFF                   = 0x12
+	IP_RSVP_VIF_ON                    = 0x11
+	IP_SENDSRCADDR                    = 0x7
+	IP_TOS                            = 0x3
+	IP_TTL                            = 0x4
+	IP_UNBLOCK_SOURCE                 = 0x49
+	ISIG                              = 0x80
+	ISTRIP                            = 0x20
+	IXANY                             = 0x800
+	IXOFF                             = 0x400
+	IXON                              = 0x200
+	LOCK_EX                           = 0x2
+	LOCK_NB                           = 0x4
+	LOCK_SH                           = 0x1
+	LOCK_UN                           = 0x8
+	MSG_COMPAT                        = 0x8000
+	MSG_CTRUNC                        = 0x20
+	MSG_DONTROUTE                     = 0x4
+	MSG_DONTWAIT                      = 0x80
+	MSG_EOF                           = 0x100
+	MSG_EOR                           = 0x8
+	MSG_NBIO                          = 0x4000
+	MSG_NOSIGNAL                      = 0x20000
+	MSG_NOTIFICATION                  = 0x2000
+	MSG_OOB                           = 0x1
+	MSG_PEEK                          = 0x2
+	MSG_TRUNC                         = 0x10
+	MSG_WAITALL                       = 0x40
+	NET_RT_DUMP                       = 0x1
+	NET_RT_FLAGS                      = 0x2
+	NET_RT_IFLIST                     = 0x3
+	NET_RT_IFLISTL                    = 0x5
+	NET_RT_IFMALIST                   = 0x4
+	NET_RT_MAXID                      = 0x6
+	NOFLSH                            = 0x80000000
+	NOTE_ATTRIB                       = 0x8
+	NOTE_CHILD                        = 0x4
+	NOTE_DELETE                       = 0x1
+	NOTE_EXEC                         = 0x20000000
+	NOTE_EXIT                         = 0x80000000
+	NOTE_EXTEND                       = 0x4
+	NOTE_FFAND                        = 0x40000000
+	NOTE_FFCOPY                       = 0xc0000000
+	NOTE_FFCTRLMASK                   = 0xc0000000
+	NOTE_FFLAGSMASK                   = 0xffffff
+	NOTE_FFNOP                        = 0x0
+	NOTE_FFOR                         = 0x80000000
+	NOTE_FORK                         = 0x40000000
+	NOTE_LINK                         = 0x10
+	NOTE_LOWAT                        = 0x1
+	NOTE_PCTRLMASK                    = 0xf0000000
+	NOTE_PDATAMASK                    = 0xfffff
+	NOTE_RENAME                       = 0x20
+	NOTE_REVOKE                       = 0x40
+	NOTE_TRACK                        = 0x1
+	NOTE_TRACKERR                     = 0x2
+	NOTE_TRIGGER                      = 0x1000000
+	NOTE_WRITE                        = 0x2
+	OCRNL                             = 0x10
+	ONLCR                             = 0x2
+	ONLRET                            = 0x40
+	ONOCR                             = 0x20
+	ONOEOT                            = 0x8
+	OPOST                             = 0x1
+	O_ACCMODE                         = 0x3
+	O_APPEND                          = 0x8
+	O_ASYNC                           = 0x40
+	O_CREAT                           = 0x200
+	O_DIRECT                          = 0x10000
+	O_DIRECTORY                       = 0x20000
+	O_EXCL                            = 0x800
+	O_EXEC                            = 0x40000
+	O_EXLOCK                          = 0x20
+	O_FSYNC                           = 0x80
+	O_NDELAY                          = 0x4
+	O_NOCTTY                          = 0x8000
+	O_NOFOLLOW                        = 0x100
+	O_NONBLOCK                        = 0x4
+	O_RDONLY                          = 0x0
+	O_RDWR                            = 0x2
+	O_SHLOCK                          = 0x10
+	O_SYNC                            = 0x80
+	O_TRUNC                           = 0x400
+	O_TTY_INIT                        = 0x80000
+	O_WRONLY                          = 0x1
+	PARENB                            = 0x1000
+	PARMRK                            = 0x8
+	PARODD                            = 0x2000
+	PENDIN                            = 0x20000000
+	RLIMIT_AS                         = 0xa
+	RLIMIT_CORE                       = 0x4
+	RLIMIT_CPU                        = 0x0
+	RLIMIT_DATA                       = 0x2
+	RLIMIT_FSIZE                      = 0x1
+	RLIMIT_NOFILE                     = 0x8
+	RLIMIT_STACK                      = 0x3
+	RLIM_INFINITY                     = 0x7fffffffffffffff
+	RTAX_AUTHOR                       = 0x6
+	RTAX_BRD                          = 0x7
+	RTAX_DST                          = 0x0
+	RTAX_GATEWAY                      = 0x1
+	RTAX_GENMASK                      = 0x3
+	RTAX_IFA                          = 0x5
+	RTAX_IFP                          = 0x4
+	RTAX_MAX                          = 0x8
+	RTAX_NETMASK                      = 0x2
+	RTA_AUTHOR                        = 0x40
+	RTA_BRD                           = 0x80
+	RTA_DST                           = 0x1
+	RTA_GATEWAY                       = 0x2
+	RTA_GENMASK                       = 0x8
+	RTA_IFA                           = 0x20
+	RTA_IFP                           = 0x10
+	RTA_NETMASK                       = 0x4
+	RTF_BLACKHOLE                     = 0x1000
+	RTF_BROADCAST                     = 0x400000
+	RTF_DONE                          = 0x40
+	RTF_DYNAMIC                       = 0x10
+	RTF_FMASK                         = 0x1004d808
+	RTF_GATEWAY                       = 0x2
+	RTF_HOST                          = 0x4
+	RTF_LLDATA                        = 0x400
+	RTF_LLINFO                        = 0x400
+	RTF_LOCAL                         = 0x200000
+	RTF_MODIFIED                      = 0x20
+	RTF_MULTICAST                     = 0x800000
+	RTF_PINNED                        = 0x100000
+	RTF_PRCLONING                     = 0x10000
+	RTF_PROTO1                        = 0x8000
+	RTF_PROTO2                        = 0x4000
+	RTF_PROTO3                        = 0x40000
+	RTF_REJECT                        = 0x8
+	RTF_RNH_LOCKED                    = 0x40000000
+	RTF_STATIC                        = 0x800
+	RTF_STICKY                        = 0x10000000
+	RTF_UP                            = 0x1
+	RTF_XRESOLVE                      = 0x200
+	RTM_ADD                           = 0x1
+	RTM_CHANGE                        = 0x3
+	RTM_DELADDR                       = 0xd
+	RTM_DELETE                        = 0x2
+	RTM_DELMADDR                      = 0x10
+	RTM_GET                           = 0x4
+	RTM_IEEE80211                     = 0x12
+	RTM_IFANNOUNCE                    = 0x11
+	RTM_IFINFO                        = 0xe
+	RTM_LOCK                          = 0x8
+	RTM_LOSING                        = 0x5
+	RTM_MISS                          = 0x7
+	RTM_NEWADDR                       = 0xc
+	RTM_NEWMADDR                      = 0xf
+	RTM_OLDADD                        = 0x9
+	RTM_OLDDEL                        = 0xa
+	RTM_REDIRECT                      = 0x6
+	RTM_RESOLVE                       = 0xb
+	RTM_RTTUNIT                       = 0xf4240
+	RTM_VERSION                       = 0x5
+	RTV_EXPIRE                        = 0x4
+	RTV_HOPCOUNT                      = 0x2
+	RTV_MTU                           = 0x1
+	RTV_RPIPE                         = 0x8
+	RTV_RTT                           = 0x40
+	RTV_RTTVAR                        = 0x80
+	RTV_SPIPE                         = 0x10
+	RTV_SSTHRESH                      = 0x20
+	RTV_WEIGHT                        = 0x100
+	RT_CACHING_CONTEXT                = 0x1
+	RT_DEFAULT_FIB                    = 0x0
+	RT_NORTREF                        = 0x2
+	RUSAGE_CHILDREN                   = -0x1
+	RUSAGE_SELF                       = 0x0
+	RUSAGE_THREAD                     = 0x1
+	SCM_BINTIME                       = 0x4
+	SCM_CREDS                         = 0x3
+	SCM_RIGHTS                        = 0x1
+	SCM_TIMESTAMP                     = 0x2
+	SHUT_RD                           = 0x0
+	SHUT_RDWR                         = 0x2
+	SHUT_WR                           = 0x1
+	SIOCADDMULTI                      = 0x80206931
+	SIOCADDRT                         = 0x8030720a
+	SIOCAIFADDR                       = 0x8044692b
+	SIOCAIFGROUP                      = 0x80246987
+	SIOCALIFADDR                      = 0x8118691b
+	SIOCATMARK                        = 0x40047307
+	SIOCDELMULTI                      = 0x80206932
+	SIOCDELRT                         = 0x8030720b
+	SIOCDIFADDR                       = 0x80206919
+	SIOCDIFGROUP                      = 0x80246989
+	SIOCDIFPHYADDR                    = 0x80206949
+	SIOCDLIFADDR                      = 0x8118691d
+	SIOCGDRVSPEC                      = 0xc01c697b
+	SIOCGETSGCNT                      = 0xc0147210
+	SIOCGETVIFCNT                     = 0xc014720f
+	SIOCGHIWAT                        = 0x40047301
+	SIOCGIFADDR                       = 0xc0206921
+	SIOCGIFBRDADDR                    = 0xc0206923
+	SIOCGIFCAP                        = 0xc020691f
+	SIOCGIFCONF                       = 0xc0086924
+	SIOCGIFDESCR                      = 0xc020692a
+	SIOCGIFDSTADDR                    = 0xc0206922
+	SIOCGIFFIB                        = 0xc020695c
+	SIOCGIFFLAGS                      = 0xc0206911
+	SIOCGIFGENERIC                    = 0xc020693a
+	SIOCGIFGMEMB                      = 0xc024698a
+	SIOCGIFGROUP                      = 0xc0246988
+	SIOCGIFINDEX                      = 0xc0206920
+	SIOCGIFMAC                        = 0xc0206926
+	SIOCGIFMEDIA                      = 0xc0286938
+	SIOCGIFMETRIC                     = 0xc0206917
+	SIOCGIFMTU                        = 0xc0206933
+	SIOCGIFNETMASK                    = 0xc0206925
+	SIOCGIFPDSTADDR                   = 0xc0206948
+	SIOCGIFPHYS                       = 0xc0206935
+	SIOCGIFPSRCADDR                   = 0xc0206947
+	SIOCGIFSTATUS                     = 0xc334693b
+	SIOCGLIFADDR                      = 0xc118691c
+	SIOCGLIFPHYADDR                   = 0xc118694b
+	SIOCGLOWAT                        = 0x40047303
+	SIOCGPGRP                         = 0x40047309
+	SIOCGPRIVATE_0                    = 0xc0206950
+	SIOCGPRIVATE_1                    = 0xc0206951
+	SIOCIFCREATE                      = 0xc020697a
+	SIOCIFCREATE2                     = 0xc020697c
+	SIOCIFDESTROY                     = 0x80206979
+	SIOCIFGCLONERS                    = 0xc00c6978
+	SIOCSDRVSPEC                      = 0x801c697b
+	SIOCSHIWAT                        = 0x80047300
+	SIOCSIFADDR                       = 0x8020690c
+	SIOCSIFBRDADDR                    = 0x80206913
+	SIOCSIFCAP                        = 0x8020691e
+	SIOCSIFDESCR                      = 0x80206929
+	SIOCSIFDSTADDR                    = 0x8020690e
+	SIOCSIFFIB                        = 0x8020695d
+	SIOCSIFFLAGS                      = 0x80206910
+	SIOCSIFGENERIC                    = 0x80206939
+	SIOCSIFLLADDR                     = 0x8020693c
+	SIOCSIFMAC                        = 0x80206927
+	SIOCSIFMEDIA                      = 0xc0206937
+	SIOCSIFMETRIC                     = 0x80206918
+	SIOCSIFMTU                        = 0x80206934
+	SIOCSIFNAME                       = 0x80206928
+	SIOCSIFNETMASK                    = 0x80206916
+	SIOCSIFPHYADDR                    = 0x80446946
+	SIOCSIFPHYS                       = 0x80206936
+	SIOCSIFRVNET                      = 0xc020695b
+	SIOCSIFVNET                       = 0xc020695a
+	SIOCSLIFPHYADDR                   = 0x8118694a
+	SIOCSLOWAT                        = 0x80047302
+	SIOCSPGRP                         = 0x80047308
+	SOCK_DGRAM                        = 0x2
+	SOCK_MAXADDRLEN                   = 0xff
+	SOCK_RAW                          = 0x3
+	SOCK_RDM                          = 0x4
+	SOCK_SEQPACKET                    = 0x5
+	SOCK_STREAM                       = 0x1
+	SOL_SOCKET                        = 0xffff
+	SOMAXCONN                         = 0x80
+	SO_ACCEPTCONN                     = 0x2
+	SO_ACCEPTFILTER                   = 0x1000
+	SO_BINTIME                        = 0x2000
+	SO_BROADCAST                      = 0x20
+	SO_DEBUG                          = 0x1
+	SO_DONTROUTE                      = 0x10
+	SO_ERROR                          = 0x1007
+	SO_KEEPALIVE                      = 0x8
+	SO_LABEL                          = 0x1009
+	SO_LINGER                         = 0x80
+	SO_LISTENINCQLEN                  = 0x1013
+	SO_LISTENQLEN                     = 0x1012
+	SO_LISTENQLIMIT                   = 0x1011
+	SO_NOSIGPIPE                      = 0x800
+	SO_NO_DDP                         = 0x8000
+	SO_NO_OFFLOAD                     = 0x4000
+	SO_OOBINLINE                      = 0x100
+	SO_PEERLABEL                      = 0x1010
+	SO_PROTOCOL                       = 0x1016
+	SO_PROTOTYPE                      = 0x1016
+	SO_RCVBUF                         = 0x1002
+	SO_RCVLOWAT                       = 0x1004
+	SO_RCVTIMEO                       = 0x1006
+	SO_REUSEADDR                      = 0x4
+	SO_REUSEPORT                      = 0x200
+	SO_SETFIB                         = 0x1014
+	SO_SNDBUF                         = 0x1001
+	SO_SNDLOWAT                       = 0x1003
+	SO_SNDTIMEO                       = 0x1005
+	SO_TIMESTAMP                      = 0x400
+	SO_TYPE                           = 0x1008
+	SO_USELOOPBACK                    = 0x40
+	SO_USER_COOKIE                    = 0x1015
+	TCIFLUSH                          = 0x1
+	TCIOFLUSH                         = 0x3
+	TCOFLUSH                          = 0x2
+	TCP_CA_NAME_MAX                   = 0x10
+	TCP_CONGESTION                    = 0x40
+	TCP_INFO                          = 0x20
+	TCP_KEEPCNT                       = 0x400
+	TCP_KEEPIDLE                      = 0x100
+	TCP_KEEPINIT                      = 0x80
+	TCP_KEEPINTVL                     = 0x200
+	TCP_MAXBURST                      = 0x4
+	TCP_MAXHLEN                       = 0x3c
+	TCP_MAXOLEN                       = 0x28
+	TCP_MAXSEG                        = 0x2
+	TCP_MAXWIN                        = 0xffff
+	TCP_MAX_SACK                      = 0x4
+	TCP_MAX_WINSHIFT                  = 0xe
+	TCP_MD5SIG                        = 0x10
+	TCP_MINMSS                        = 0xd8
+	TCP_MSS                           = 0x218
+	TCP_NODELAY                       = 0x1
+	TCP_NOOPT                         = 0x8
+	TCP_NOPUSH                        = 0x4
+	TCSAFLUSH                         = 0x2
+	TIOCCBRK                          = 0x2000747a
+	TIOCCDTR                          = 0x20007478
+	TIOCCONS                          = 0x80047462
+	TIOCDRAIN                         = 0x2000745e
+	TIOCEXCL                          = 0x2000740d
+	TIOCEXT                           = 0x80047460
+	TIOCFLUSH                         = 0x80047410
+	TIOCGDRAINWAIT                    = 0x40047456
+	TIOCGETA                          = 0x402c7413
+	TIOCGETD                          = 0x4004741a
+	TIOCGPGRP                         = 0x40047477
+	TIOCGPTN                          = 0x4004740f
+	TIOCGSID                          = 0x40047463
+	TIOCGWINSZ                        = 0x40087468
+	TIOCMBIC                          = 0x8004746b
+	TIOCMBIS                          = 0x8004746c
+	TIOCMGDTRWAIT                     = 0x4004745a
+	TIOCMGET                          = 0x4004746a
+	TIOCMSDTRWAIT                     = 0x8004745b
+	TIOCMSET                          = 0x8004746d
+	TIOCM_CAR                         = 0x40
+	TIOCM_CD                          = 0x40
+	TIOCM_CTS                         = 0x20
+	TIOCM_DCD                         = 0x40
+	TIOCM_DSR                         = 0x100
+	TIOCM_DTR                         = 0x2
+	TIOCM_LE                          = 0x1
+	TIOCM_RI                          = 0x80
+	TIOCM_RNG                         = 0x80
+	TIOCM_RTS                         = 0x4
+	TIOCM_SR                          = 0x10
+	TIOCM_ST                          = 0x8
+	TIOCNOTTY                         = 0x20007471
+	TIOCNXCL                          = 0x2000740e
+	TIOCOUTQ                          = 0x40047473
+	TIOCPKT                           = 0x80047470
+	TIOCPKT_DATA                      = 0x0
+	TIOCPKT_DOSTOP                    = 0x20
+	TIOCPKT_FLUSHREAD                 = 0x1
+	TIOCPKT_FLUSHWRITE                = 0x2
+	TIOCPKT_IOCTL                     = 0x40
+	TIOCPKT_NOSTOP                    = 0x10
+	TIOCPKT_START                     = 0x8
+	TIOCPKT_STOP                      = 0x4
+	TIOCPTMASTER                      = 0x2000741c
+	TIOCSBRK                          = 0x2000747b
+	TIOCSCTTY                         = 0x20007461
+	TIOCSDRAINWAIT                    = 0x80047457
+	TIOCSDTR                          = 0x20007479
+	TIOCSETA                          = 0x802c7414
+	TIOCSETAF                         = 0x802c7416
+	TIOCSETAW                         = 0x802c7415
+	TIOCSETD                          = 0x8004741b
+	TIOCSIG                           = 0x2004745f
+	TIOCSPGRP                         = 0x80047476
+	TIOCSTART                         = 0x2000746e
+	TIOCSTAT                          = 0x20007465
+	TIOCSTI                           = 0x80017472
+	TIOCSTOP                          = 0x2000746f
+	TIOCSWINSZ                        = 0x80087467
+	TIOCTIMESTAMP                     = 0x400c7459
+	TIOCUCNTL                         = 0x80047466
+	TOSTOP                            = 0x400000
+	VDISCARD                          = 0xf
+	VDSUSP                            = 0xb
+	VEOF                              = 0x0
+	VEOL                              = 0x1
+	VEOL2                             = 0x2
+	VERASE                            = 0x3
+	VERASE2                           = 0x7
+	VINTR                             = 0x8
+	VKILL                             = 0x5
+	VLNEXT                            = 0xe
+	VMIN                              = 0x10
+	VQUIT                             = 0x9
+	VREPRINT                          = 0x6
+	VSTART                            = 0xc
+	VSTATUS                           = 0x12
+	VSTOP                             = 0xd
+	VSUSP                             = 0xa
+	VTIME                             = 0x11
+	VWERASE                           = 0x4
+	WCONTINUED                        = 0x4
+	WCOREFLAG                         = 0x80
+	WLINUXCLONE                       = 0x80000000
+	WNOHANG                           = 0x1
+	WNOWAIT                           = 0x8
+	WSTOPPED                          = 0x2
+	WUNTRACED                         = 0x2
+)
+
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x30)
+	EADDRNOTAVAIL   = Errno(0x31)
+	EAFNOSUPPORT    = Errno(0x2f)
+	EAGAIN          = Errno(0x23)
+	EALREADY        = Errno(0x25)
+	EAUTH           = Errno(0x50)
+	EBADF           = Errno(0x9)
+	EBADMSG         = Errno(0x59)
+	EBADRPC         = Errno(0x48)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x55)
+	ECAPMODE        = Errno(0x5e)
+	ECHILD          = Errno(0xa)
+	ECONNABORTED    = Errno(0x35)
+	ECONNREFUSED    = Errno(0x3d)
+	ECONNRESET      = Errno(0x36)
+	EDEADLK         = Errno(0xb)
+	EDESTADDRREQ    = Errno(0x27)
+	EDOM            = Errno(0x21)
+	EDOOFUS         = Errno(0x58)
+	EDQUOT          = Errno(0x45)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EFTYPE          = Errno(0x4f)
+	EHOSTDOWN       = Errno(0x40)
+	EHOSTUNREACH    = Errno(0x41)
+	EIDRM           = Errno(0x52)
+	EILSEQ          = Errno(0x56)
+	EINPROGRESS     = Errno(0x24)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x38)
+	EISDIR          = Errno(0x15)
+	ELAST           = Errno(0x5e)
+	ELOOP           = Errno(0x3e)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x28)
+	EMULTIHOP       = Errno(0x5a)
+	ENAMETOOLONG    = Errno(0x3f)
+	ENEEDAUTH       = Errno(0x51)
+	ENETDOWN        = Errno(0x32)
+	ENETRESET       = Errno(0x34)
+	ENETUNREACH     = Errno(0x33)
+	ENFILE          = Errno(0x17)
+	ENOATTR         = Errno(0x57)
+	ENOBUFS         = Errno(0x37)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOLCK          = Errno(0x4d)
+	ENOLINK         = Errno(0x5b)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x53)
+	ENOPROTOOPT     = Errno(0x2a)
+	ENOSPC          = Errno(0x1c)
+	ENOSYS          = Errno(0x4e)
+	ENOTBLK         = Errno(0xf)
+	ENOTCAPABLE     = Errno(0x5d)
+	ENOTCONN        = Errno(0x39)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x42)
+	ENOTSOCK        = Errno(0x26)
+	ENOTSUP         = Errno(0x2d)
+	ENOTTY          = Errno(0x19)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x2d)
+	EOVERFLOW       = Errno(0x54)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x2e)
+	EPIPE           = Errno(0x20)
+	EPROCLIM        = Errno(0x43)
+	EPROCUNAVAIL    = Errno(0x4c)
+	EPROGMISMATCH   = Errno(0x4b)
+	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTO          = Errno(0x5c)
+	EPROTONOSUPPORT = Errno(0x2b)
+	EPROTOTYPE      = Errno(0x29)
+	ERANGE          = Errno(0x22)
+	EREMOTE         = Errno(0x47)
+	EROFS           = Errno(0x1e)
+	ERPCMISMATCH    = Errno(0x49)
+	ESHUTDOWN       = Errno(0x3a)
+	ESOCKTNOSUPPORT = Errno(0x2c)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESTALE          = Errno(0x46)
+	ETIMEDOUT       = Errno(0x3c)
+	ETOOMANYREFS    = Errno(0x3b)
+	ETXTBSY         = Errno(0x1a)
+	EUSERS          = Errno(0x44)
+	EWOULDBLOCK     = Errno(0x23)
+	EXDEV           = Errno(0x12)
+)
+
+// Signals
+const (
+	SIGABRT   = Signal(0x6)
+	SIGALRM   = Signal(0xe)
+	SIGBUS    = Signal(0xa)
+	SIGCHLD   = Signal(0x14)
+	SIGCONT   = Signal(0x13)
+	SIGEMT    = Signal(0x7)
+	SIGFPE    = Signal(0x8)
+	SIGHUP    = Signal(0x1)
+	SIGILL    = Signal(0x4)
+	SIGINFO   = Signal(0x1d)
+	SIGINT    = Signal(0x2)
+	SIGIO     = Signal(0x17)
+	SIGIOT    = Signal(0x6)
+	SIGKILL   = Signal(0x9)
+	SIGLIBRT  = Signal(0x21)
+	SIGLWP    = Signal(0x20)
+	SIGPIPE   = Signal(0xd)
+	SIGPROF   = Signal(0x1b)
+	SIGQUIT   = Signal(0x3)
+	SIGSEGV   = Signal(0xb)
+	SIGSTOP   = Signal(0x11)
+	SIGSYS    = Signal(0xc)
+	SIGTERM   = Signal(0xf)
+	SIGTHR    = Signal(0x20)
+	SIGTRAP   = Signal(0x5)
+	SIGTSTP   = Signal(0x12)
+	SIGTTIN   = Signal(0x15)
+	SIGTTOU   = Signal(0x16)
+	SIGURG    = Signal(0x10)
+	SIGUSR1   = Signal(0x1e)
+	SIGUSR2   = Signal(0x1f)
+	SIGVTALRM = Signal(0x1a)
+	SIGWINCH  = Signal(0x1c)
+	SIGXCPU   = Signal(0x18)
+	SIGXFSZ   = Signal(0x19)
+)
+
+// Error table
+var errors = [...]string{
+	1:  "operation not permitted",
+	2:  "no such file or directory",
+	3:  "no such process",
+	4:  "interrupted system call",
+	5:  "input/output error",
+	6:  "device not configured",
+	7:  "argument list too long",
+	8:  "exec format error",
+	9:  "bad file descriptor",
+	10: "no child processes",
+	11: "resource deadlock avoided",
+	12: "cannot allocate memory",
+	13: "permission denied",
+	14: "bad address",
+	15: "block device required",
+	16: "device busy",
+	17: "file exists",
+	18: "cross-device link",
+	19: "operation not supported by device",
+	20: "not a directory",
+	21: "is a directory",
+	22: "invalid argument",
+	23: "too many open files in system",
+	24: "too many open files",
+	25: "inappropriate ioctl for device",
+	26: "text file busy",
+	27: "file too large",
+	28: "no space left on device",
+	29: "illegal seek",
+	30: "read-only file system",
+	31: "too many links",
+	32: "broken pipe",
+	33: "numerical argument out of domain",
+	34: "result too large",
+	35: "resource temporarily unavailable",
+	36: "operation now in progress",
+	37: "operation already in progress",
+	38: "socket operation on non-socket",
+	39: "destination address required",
+	40: "message too long",
+	41: "protocol wrong type for socket",
+	42: "protocol not available",
+	43: "protocol not supported",
+	44: "socket type not supported",
+	45: "operation not supported",
+	46: "protocol family not supported",
+	47: "address family not supported by protocol family",
+	48: "address already in use",
+	49: "can't assign requested address",
+	50: "network is down",
+	51: "network is unreachable",
+	52: "network dropped connection on reset",
+	53: "software caused connection abort",
+	54: "connection reset by peer",
+	55: "no buffer space available",
+	56: "socket is already connected",
+	57: "socket is not connected",
+	58: "can't send after socket shutdown",
+	59: "too many references: can't splice",
+	60: "operation timed out",
+	61: "connection refused",
+	62: "too many levels of symbolic links",
+	63: "file name too long",
+	64: "host is down",
+	65: "no route to host",
+	66: "directory not empty",
+	67: "too many processes",
+	68: "too many users",
+	69: "disc quota exceeded",
+	70: "stale NFS file handle",
+	71: "too many levels of remote in path",
+	72: "RPC struct is bad",
+	73: "RPC version wrong",
+	74: "RPC prog. not avail",
+	75: "program version wrong",
+	76: "bad procedure for program",
+	77: "no locks available",
+	78: "function not implemented",
+	79: "inappropriate file type or format",
+	80: "authentication error",
+	81: "need authenticator",
+	82: "identifier removed",
+	83: "no message of desired type",
+	84: "value too large to be stored in data type",
+	85: "operation canceled",
+	86: "illegal byte sequence",
+	87: "attribute not found",
+	88: "programming error",
+	89: "bad message",
+	90: "multihop attempted",
+	91: "link has been severed",
+	92: "protocol error",
+	93: "capabilities insufficient",
+	94: "not permitted in capability mode",
+}
+
+// Signal table
+var signals = [...]string{
+	1:  "hangup",
+	2:  "interrupt",
+	3:  "quit",
+	4:  "illegal instruction",
+	5:  "trace/BPT trap",
+	6:  "abort trap",
+	7:  "EMT trap",
+	8:  "floating point exception",
+	9:  "killed",
+	10: "bus error",
+	11: "segmentation fault",
+	12: "bad system call",
+	13: "broken pipe",
+	14: "alarm clock",
+	15: "terminated",
+	16: "urgent I/O condition",
+	17: "suspended (signal)",
+	18: "suspended",
+	19: "continued",
+	20: "child exited",
+	21: "stopped (tty input)",
+	22: "stopped (tty output)",
+	23: "I/O possible",
+	24: "cputime limit exceeded",
+	25: "filesize limit exceeded",
+	26: "virtual timer expired",
+	27: "profiling timer expired",
+	28: "window size changes",
+	29: "information request",
+	30: "user defined signal 1",
+	31: "user defined signal 2",
+	32: "unknown signal",
+	33: "unknown signal",
+}
diff --git a/src/pkg/syscall/zerrors_linux_386.go b/src/pkg/syscall/zerrors_linux_386.go
index 065da8f..a689942 100644
--- a/src/pkg/syscall/zerrors_linux_386.go
+++ b/src/pkg/syscall/zerrors_linux_386.go
@@ -528,6 +528,7 @@ const (
 	MSG_DONTWAIT                     = 0x40
 	MSG_EOR                          = 0x80
 	MSG_ERRQUEUE                     = 0x2000
+	MSG_FASTOPEN                     = 0x20000000
 	MSG_FIN                          = 0x200
 	MSG_MORE                         = 0x8000
 	MSG_NOSIGNAL                     = 0x4000
diff --git a/src/pkg/syscall/zerrors_linux_amd64.go b/src/pkg/syscall/zerrors_linux_amd64.go
index 4e49184..a1ac177 100644
--- a/src/pkg/syscall/zerrors_linux_amd64.go
+++ b/src/pkg/syscall/zerrors_linux_amd64.go
@@ -528,6 +528,7 @@ const (
 	MSG_DONTWAIT                     = 0x40
 	MSG_EOR                          = 0x80
 	MSG_ERRQUEUE                     = 0x2000
+	MSG_FASTOPEN                     = 0x20000000
 	MSG_FIN                          = 0x200
 	MSG_MORE                         = 0x8000
 	MSG_NOSIGNAL                     = 0x4000
diff --git a/src/pkg/syscall/zerrors_linux_arm.go b/src/pkg/syscall/zerrors_linux_arm.go
index 9b99cf8..0730f21 100644
--- a/src/pkg/syscall/zerrors_linux_arm.go
+++ b/src/pkg/syscall/zerrors_linux_arm.go
@@ -523,6 +523,7 @@ const (
 	MSG_DONTWAIT                     = 0x40
 	MSG_EOR                          = 0x80
 	MSG_ERRQUEUE                     = 0x2000
+	MSG_FASTOPEN                     = 0x20000000
 	MSG_FIN                          = 0x200
 	MSG_MORE                         = 0x8000
 	MSG_NOSIGNAL                     = 0x4000
diff --git a/src/pkg/syscall/zerrors_netbsd_386.go b/src/pkg/syscall/zerrors_netbsd_386.go
index 52dc69a..68051f9 100644
--- a/src/pkg/syscall/zerrors_netbsd_386.go
+++ b/src/pkg/syscall/zerrors_netbsd_386.go
@@ -8,7 +8,8 @@ package syscall
 
 const (
 	AF_APPLETALK                      = 0x10
-	AF_BLUETOOTH                      = 0x20
+	AF_ARP                            = 0x1c
+	AF_BLUETOOTH                      = 0x1f
 	AF_CCITT                          = 0xa
 	AF_CHAOS                          = 0x5
 	AF_CNT                            = 0x15
@@ -18,67 +19,93 @@ const (
 	AF_DLI                            = 0xd
 	AF_E164                           = 0x1a
 	AF_ECMA                           = 0x8
-	AF_ENCAP                          = 0x1c
 	AF_HYLINK                         = 0xf
+	AF_IEEE80211                      = 0x20
 	AF_IMPLINK                        = 0x3
 	AF_INET                           = 0x2
 	AF_INET6                          = 0x18
 	AF_IPX                            = 0x17
 	AF_ISDN                           = 0x1a
 	AF_ISO                            = 0x7
-	AF_KEY                            = 0x1e
 	AF_LAT                            = 0xe
 	AF_LINK                           = 0x12
 	AF_LOCAL                          = 0x1
-	AF_MAX                            = 0x24
+	AF_MAX                            = 0x23
 	AF_MPLS                           = 0x21
 	AF_NATM                           = 0x1b
 	AF_NS                             = 0x6
+	AF_OROUTE                         = 0x11
 	AF_OSI                            = 0x7
 	AF_PUP                            = 0x4
-	AF_ROUTE                          = 0x11
-	AF_SIP                            = 0x1d
+	AF_ROUTE                          = 0x22
 	AF_SNA                            = 0xb
 	AF_UNIX                           = 0x1
 	AF_UNSPEC                         = 0x0
+	ARPHRD_ARCNET                     = 0x7
 	ARPHRD_ETHER                      = 0x1
 	ARPHRD_FRELAY                     = 0xf
 	ARPHRD_IEEE1394                   = 0x18
 	ARPHRD_IEEE802                    = 0x6
+	ARPHRD_STRIP                      = 0x17
+	B0                                = 0x0
+	B110                              = 0x6e
+	B115200                           = 0x1c200
+	B1200                             = 0x4b0
+	B134                              = 0x86
+	B14400                            = 0x3840
+	B150                              = 0x96
+	B1800                             = 0x708
+	B19200                            = 0x4b00
+	B200                              = 0xc8
+	B230400                           = 0x38400
+	B2400                             = 0x960
+	B28800                            = 0x7080
+	B300                              = 0x12c
+	B38400                            = 0x9600
+	B460800                           = 0x70800
+	B4800                             = 0x12c0
+	B50                               = 0x32
+	B57600                            = 0xe100
+	B600                              = 0x258
+	B7200                             = 0x1c20
+	B75                               = 0x4b
+	B76800                            = 0x12c00
+	B921600                           = 0xe1000
+	B9600                             = 0x2580
+	BIOCFEEDBACK                      = 0x8004427d
 	BIOCFLUSH                         = 0x20004268
 	BIOCGBLEN                         = 0x40044266
-	BIOCGDIRFILT                      = 0x4004427c
 	BIOCGDLT                          = 0x4004426a
-	BIOCGDLTLIST                      = 0xc008427b
-	BIOCGETIF                         = 0x4020426b
-	BIOCGFILDROP                      = 0x40044278
+	BIOCGDLTLIST                      = 0xc0084277
+	BIOCGETIF                         = 0x4090426b
+	BIOCGFEEDBACK                     = 0x4004427c
 	BIOCGHDRCMPLT                     = 0x40044274
-	BIOCGRSIG                         = 0x40044273
-	BIOCGRTIMEOUT                     = 0x4008426e
-	BIOCGSTATS                        = 0x4008426f
+	BIOCGRTIMEOUT                     = 0x400c427b
+	BIOCGSEESENT                      = 0x40044278
+	BIOCGSTATS                        = 0x4080426f
+	BIOCGSTATSOLD                     = 0x4008426f
 	BIOCIMMEDIATE                     = 0x80044270
-	BIOCLOCK                          = 0x20004276
 	BIOCPROMISC                       = 0x20004269
 	BIOCSBLEN                         = 0xc0044266
-	BIOCSDIRFILT                      = 0x8004427d
-	BIOCSDLT                          = 0x8004427a
+	BIOCSDLT                          = 0x80044276
 	BIOCSETF                          = 0x80084267
-	BIOCSETIF                         = 0x8020426c
-	BIOCSETWF                         = 0x80084277
-	BIOCSFILDROP                      = 0x80044279
+	BIOCSETIF                         = 0x8090426c
+	BIOCSFEEDBACK                     = 0x8004427d
 	BIOCSHDRCMPLT                     = 0x80044275
-	BIOCSRSIG                         = 0x80044272
-	BIOCSRTIMEOUT                     = 0x8008426d
+	BIOCSRTIMEOUT                     = 0x800c427a
+	BIOCSSEESENT                      = 0x80044279
+	BIOCSTCPF                         = 0x80084272
+	BIOCSUDPF                         = 0x80084273
 	BIOCVERSION                       = 0x40044271
 	BPF_A                             = 0x10
 	BPF_ABS                           = 0x20
 	BPF_ADD                           = 0x0
 	BPF_ALIGNMENT                     = 0x4
+	BPF_ALIGNMENT32                   = 0x4
 	BPF_ALU                           = 0x4
 	BPF_AND                           = 0x50
 	BPF_B                             = 0x10
-	BPF_DIRECTION_IN                  = 0x1
-	BPF_DIRECTION_OUT                 = 0x2
+	BPF_DFLTBUFSIZE                   = 0x100000
 	BPF_DIV                           = 0x30
 	BPF_H                             = 0x8
 	BPF_IMM                           = 0x0
@@ -95,7 +122,7 @@ const (
 	BPF_LEN                           = 0x80
 	BPF_LSH                           = 0x60
 	BPF_MAJOR_VERSION                 = 0x1
-	BPF_MAXBUFSIZE                    = 0x200000
+	BPF_MAXBUFSIZE                    = 0x1000000
 	BPF_MAXINSNS                      = 0x200
 	BPF_MEM                           = 0x60
 	BPF_MEMWORDS                      = 0x10
@@ -116,31 +143,151 @@ const (
 	BPF_TXA                           = 0x80
 	BPF_W                             = 0x0
 	BPF_X                             = 0x8
+	BRKINT                            = 0x2
+	CFLUSH                            = 0xf
+	CLOCAL                            = 0x8000
+	CREAD                             = 0x800
+	CS5                               = 0x0
+	CS6                               = 0x100
+	CS7                               = 0x200
+	CS8                               = 0x300
+	CSIZE                             = 0x300
+	CSTART                            = 0x11
+	CSTATUS                           = 0x14
+	CSTOP                             = 0x13
+	CSTOPB                            = 0x400
+	CSUSP                             = 0x1a
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
+	CTL_QUERY                         = -0x2
+	DIOCBSFLUSH                       = 0x20006478
+	DLT_A429                          = 0xb8
+	DLT_A653_ICM                      = 0xb9
+	DLT_AIRONET_HEADER                = 0x78
+	DLT_AOS                           = 0xde
+	DLT_APPLE_IP_OVER_IEEE1394        = 0x8a
 	DLT_ARCNET                        = 0x7
+	DLT_ARCNET_LINUX                  = 0x81
+	DLT_ATM_CLIP                      = 0x13
 	DLT_ATM_RFC1483                   = 0xb
+	DLT_AURORA                        = 0x7e
 	DLT_AX25                          = 0x3
+	DLT_AX25_KISS                     = 0xca
+	DLT_BACNET_MS_TP                  = 0xa5
+	DLT_BLUETOOTH_HCI_H4              = 0xbb
+	DLT_BLUETOOTH_HCI_H4_WITH_PHDR    = 0xc9
+	DLT_CAN20B                        = 0xbe
+	DLT_CAN_SOCKETCAN                 = 0xe3
 	DLT_CHAOS                         = 0x5
+	DLT_CISCO_IOS                     = 0x76
+	DLT_C_HDLC                        = 0x68
+	DLT_C_HDLC_WITH_DIR               = 0xcd
+	DLT_DECT                          = 0xdd
+	DLT_DOCSIS                        = 0x8f
+	DLT_ECONET                        = 0x73
 	DLT_EN10MB                        = 0x1
 	DLT_EN3MB                         = 0x2
-	DLT_ENC                           = 0xd
+	DLT_ENC                           = 0x6d
+	DLT_ERF                           = 0xc5
+	DLT_ERF_ETH                       = 0xaf
+	DLT_ERF_POS                       = 0xb0
+	DLT_FC_2                          = 0xe0
+	DLT_FC_2_WITH_FRAME_DELIMS        = 0xe1
 	DLT_FDDI                          = 0xa
+	DLT_FLEXRAY                       = 0xd2
+	DLT_FRELAY                        = 0x6b
+	DLT_FRELAY_WITH_DIR               = 0xce
+	DLT_GCOM_SERIAL                   = 0xad
+	DLT_GCOM_T1E1                     = 0xac
+	DLT_GPF_F                         = 0xab
+	DLT_GPF_T                         = 0xaa
+	DLT_GPRS_LLC                      = 0xa9
+	DLT_GSMTAP_ABIS                   = 0xda
+	DLT_GSMTAP_UM                     = 0xd9
+	DLT_HDLC                          = 0x10
+	DLT_HHDLC                         = 0x79
+	DLT_HIPPI                         = 0xf
+	DLT_IBM_SN                        = 0x92
+	DLT_IBM_SP                        = 0x91
 	DLT_IEEE802                       = 0x6
 	DLT_IEEE802_11                    = 0x69
 	DLT_IEEE802_11_RADIO              = 0x7f
-	DLT_LOOP                          = 0xc
+	DLT_IEEE802_11_RADIO_AVS          = 0xa3
+	DLT_IEEE802_15_4                  = 0xc3
+	DLT_IEEE802_15_4_LINUX            = 0xbf
+	DLT_IEEE802_15_4_NONASK_PHY       = 0xd7
+	DLT_IEEE802_16_MAC_CPS            = 0xbc
+	DLT_IEEE802_16_MAC_CPS_RADIO      = 0xc1
+	DLT_IPMB                          = 0xc7
+	DLT_IPMB_LINUX                    = 0xd1
+	DLT_IPNET                         = 0xe2
+	DLT_IPV4                          = 0xe4
+	DLT_IPV6                          = 0xe5
+	DLT_IP_OVER_FC                    = 0x7a
+	DLT_JUNIPER_ATM1                  = 0x89
+	DLT_JUNIPER_ATM2                  = 0x87
+	DLT_JUNIPER_CHDLC                 = 0xb5
+	DLT_JUNIPER_ES                    = 0x84
+	DLT_JUNIPER_ETHER                 = 0xb2
+	DLT_JUNIPER_FRELAY                = 0xb4
+	DLT_JUNIPER_GGSN                  = 0x85
+	DLT_JUNIPER_ISM                   = 0xc2
+	DLT_JUNIPER_MFR                   = 0x86
+	DLT_JUNIPER_MLFR                  = 0x83
+	DLT_JUNIPER_MLPPP                 = 0x82
+	DLT_JUNIPER_MONITOR               = 0xa4
+	DLT_JUNIPER_PIC_PEER              = 0xae
+	DLT_JUNIPER_PPP                   = 0xb3
+	DLT_JUNIPER_PPPOE                 = 0xa7
+	DLT_JUNIPER_PPPOE_ATM             = 0xa8
+	DLT_JUNIPER_SERVICES              = 0x88
+	DLT_JUNIPER_ST                    = 0xc8
+	DLT_JUNIPER_VP                    = 0xb7
+	DLT_LAPB_WITH_DIR                 = 0xcf
+	DLT_LAPD                          = 0xcb
+	DLT_LIN                           = 0xd4
+	DLT_LINUX_EVDEV                   = 0xd8
+	DLT_LINUX_IRDA                    = 0x90
+	DLT_LINUX_LAPD                    = 0xb1
+	DLT_LINUX_SLL                     = 0x71
+	DLT_LOOP                          = 0x6c
+	DLT_LTALK                         = 0x72
+	DLT_MFR                           = 0xb6
+	DLT_MOST                          = 0xd3
 	DLT_MPLS                          = 0xdb
+	DLT_MTP2                          = 0x8c
+	DLT_MTP2_WITH_PHDR                = 0x8b
+	DLT_MTP3                          = 0x8d
 	DLT_NULL                          = 0x0
+	DLT_PCI_EXP                       = 0x7d
 	DLT_PFLOG                         = 0x75
 	DLT_PFSYNC                        = 0x12
+	DLT_PPI                           = 0xc0
 	DLT_PPP                           = 0x9
-	DLT_PPP_BSDOS                     = 0x10
+	DLT_PPP_BSDOS                     = 0xe
 	DLT_PPP_ETHER                     = 0x33
+	DLT_PPP_PPPD                      = 0xa6
+	DLT_PPP_SERIAL                    = 0x32
+	DLT_PPP_WITH_DIR                  = 0xcc
+	DLT_PRISM_HEADER                  = 0x77
 	DLT_PRONET                        = 0x4
-	DLT_RAW                           = 0xe
+	DLT_RAIF1                         = 0xc6
+	DLT_RAW                           = 0xc
+	DLT_RAWAF_MASK                    = 0x2240000
+	DLT_RIO                           = 0x7c
+	DLT_SCCP                          = 0x8e
+	DLT_SITA                          = 0xc4
 	DLT_SLIP                          = 0x8
-	DLT_SLIP_BSDOS                    = 0xf
+	DLT_SLIP_BSDOS                    = 0xd
+	DLT_SUNATM                        = 0x7b
+	DLT_SYMANTEC_FIREWALL             = 0x63
+	DLT_TZSP                          = 0x80
+	DLT_USB                           = 0xba
+	DLT_USB_LINUX                     = 0xbd
+	DLT_USB_LINUX_MMAPPED             = 0xdc
+	DLT_WIHART                        = 0xdf
+	DLT_X2E_SERIAL                    = 0xd5
+	DLT_X2E_XORAYA                    = 0xd6
 	DT_BLK                            = 0x6
 	DT_CHR                            = 0x2
 	DT_DIR                            = 0x4
@@ -149,15 +296,33 @@ const (
 	DT_REG                            = 0x8
 	DT_SOCK                           = 0xc
 	DT_UNKNOWN                        = 0x0
-	EFER_LMA                          = 0x400
-	EFER_LME                          = 0x100
-	EFER_NXE                          = 0x800
-	EFER_SCE                          = 0x1
-	EMT_TAGOVF                        = 0x1
-	EMUL_ENABLED                      = 0x1
-	EMUL_NATIVE                       = 0x2
+	DT_WHT                            = 0xe
+	ECHO                              = 0x8
+	ECHOCTL                           = 0x40
+	ECHOE                             = 0x2
+	ECHOK                             = 0x4
+	ECHOKE                            = 0x1
+	ECHONL                            = 0x10
+	ECHOPRT                           = 0x20
+	EMUL_LINUX                        = 0x1
+	EMUL_LINUX32                      = 0x5
+	EMUL_MAXID                        = 0x6
+	EN_SW_CTL_INF                     = 0x1000
+	EN_SW_CTL_PREC                    = 0x300
+	EN_SW_CTL_ROUND                   = 0xc00
+	EN_SW_DATACHAIN                   = 0x80
+	EN_SW_DENORM                      = 0x2
+	EN_SW_INVOP                       = 0x1
+	EN_SW_OVERFLOW                    = 0x8
+	EN_SW_PRECLOSS                    = 0x20
+	EN_SW_UNDERFLOW                   = 0x10
+	EN_SW_ZERODIV                     = 0x4
+	ETHERCAP_JUMBO_MTU                = 0x4
+	ETHERCAP_VLAN_HWTAGGING           = 0x2
+	ETHERCAP_VLAN_MTU                 = 0x1
 	ETHERMIN                          = 0x2e
 	ETHERMTU                          = 0x5dc
+	ETHERMTU_JUMBO                    = 0x2328
 	ETHERTYPE_8023                    = 0x4
 	ETHERTYPE_AARP                    = 0x80f3
 	ETHERTYPE_ACCTON                  = 0x8390
@@ -165,7 +330,6 @@ const (
 	ETHERTYPE_ALPHA                   = 0x814a
 	ETHERTYPE_AMBER                   = 0x6008
 	ETHERTYPE_AMOEBA                  = 0x8145
-	ETHERTYPE_AOE                     = 0x88a2
 	ETHERTYPE_APOLLO                  = 0x80f7
 	ETHERTYPE_APOLLODOMAIN            = 0x8019
 	ETHERTYPE_APPLETALK               = 0x809b
@@ -236,7 +400,6 @@ const (
 	ETHERTYPE_LAT                     = 0x6004
 	ETHERTYPE_LBACK                   = 0x9000
 	ETHERTYPE_LITTLE                  = 0x8060
-	ETHERTYPE_LLDP                    = 0x88cc
 	ETHERTYPE_LOGICRAFT               = 0x8148
 	ETHERTYPE_LOOPBACK                = 0x9000
 	ETHERTYPE_MATRA                   = 0x807a
@@ -284,7 +447,6 @@ const (
 	ETHERTYPE_PRIMENTS                = 0x7031
 	ETHERTYPE_PUP                     = 0x200
 	ETHERTYPE_PUPAT                   = 0x200
-	ETHERTYPE_QINQ                    = 0x88a8
 	ETHERTYPE_RACAL                   = 0x7030
 	ETHERTYPE_RATIONAL                = 0x8150
 	ETHERTYPE_RAWFR                   = 0x6559
@@ -301,7 +463,7 @@ const (
 	ETHERTYPE_SG_NETGAMES             = 0x8014
 	ETHERTYPE_SG_RESV                 = 0x8015
 	ETHERTYPE_SIMNET                  = 0x5208
-	ETHERTYPE_SLOW                    = 0x8809
+	ETHERTYPE_SLOWPROTOCOLS           = 0x8809
 	ETHERTYPE_SNA                     = 0x80d5
 	ETHERTYPE_SNMP                    = 0x814c
 	ETHERTYPE_SONIX                   = 0xfaf5
@@ -344,24 +506,24 @@ const (
 	ETHERTYPE_XNSSM                   = 0x9001
 	ETHERTYPE_XTP                     = 0x817d
 	ETHER_ADDR_LEN                    = 0x6
-	ETHER_ALIGN                       = 0x2
 	ETHER_CRC_LEN                     = 0x4
 	ETHER_CRC_POLY_BE                 = 0x4c11db6
 	ETHER_CRC_POLY_LE                 = 0xedb88320
 	ETHER_HDR_LEN                     = 0xe
-	ETHER_MAX_DIX_LEN                 = 0x600
 	ETHER_MAX_LEN                     = 0x5ee
+	ETHER_MAX_LEN_JUMBO               = 0x233a
 	ETHER_MIN_LEN                     = 0x40
+	ETHER_PPPOE_ENCAP_LEN             = 0x8
 	ETHER_TYPE_LEN                    = 0x2
 	ETHER_VLAN_ENCAP_LEN              = 0x4
-	EVFILT_AIO                        = -0x3
-	EVFILT_PROC                       = -0x5
-	EVFILT_READ                       = -0x1
-	EVFILT_SIGNAL                     = -0x6
+	EVFILT_AIO                        = 0x2
+	EVFILT_PROC                       = 0x4
+	EVFILT_READ                       = 0x0
+	EVFILT_SIGNAL                     = 0x5
 	EVFILT_SYSCOUNT                   = 0x7
-	EVFILT_TIMER                      = -0x7
-	EVFILT_VNODE                      = -0x4
-	EVFILT_WRITE                      = -0x2
+	EVFILT_TIMER                      = 0x6
+	EVFILT_VNODE                      = 0x3
+	EVFILT_WRITE                      = 0x1
 	EV_ADD                            = 0x1
 	EV_CLEAR                          = 0x20
 	EV_DELETE                         = 0x2
@@ -376,25 +538,46 @@ const (
 	EXTB                              = 0x9600
 	EXTPROC                           = 0x800
 	FD_CLOEXEC                        = 0x1
-	FD_SETSIZE                        = 0x400
+	FD_SETSIZE                        = 0x100
+	FLUSHO                            = 0x800000
+	F_CLOSEM                          = 0xa
 	F_DUPFD                           = 0x0
-	F_DUPFD_CLOEXEC                   = 0xa
+	F_DUPFD_CLOEXEC                   = 0xc
+	F_FSCTL                           = -0x80000000
+	F_FSDIRMASK                       = 0x70000000
+	F_FSIN                            = 0x10000000
+	F_FSINOUT                         = 0x30000000
+	F_FSOUT                           = 0x20000000
+	F_FSPRIV                          = 0x8000
+	F_FSVOID                          = 0x40000000
 	F_GETFD                           = 0x1
 	F_GETFL                           = 0x3
 	F_GETLK                           = 0x7
+	F_GETNOSIGPIPE                    = 0xd
 	F_GETOWN                          = 0x5
+	F_MAXFD                           = 0xb
+	F_OK                              = 0x0
+	F_PARAM_MASK                      = 0xfff
+	F_PARAM_MAX                       = 0xfff
 	F_RDLCK                           = 0x1
 	F_SETFD                           = 0x2
 	F_SETFL                           = 0x4
 	F_SETLK                           = 0x8
 	F_SETLKW                          = 0x9
+	F_SETNOSIGPIPE                    = 0xe
 	F_SETOWN                          = 0x6
 	F_UNLCK                           = 0x2
 	F_WRLCK                           = 0x3
+	HUPCL                             = 0x4000
+	ICANON                            = 0x100
+	ICRNL                             = 0x100
+	IEXTEN                            = 0x400
+	IFAN_ARRIVAL                      = 0x0
+	IFAN_DEPARTURE                    = 0x1
 	IFA_ROUTE                         = 0x1
 	IFF_ALLMULTI                      = 0x200
 	IFF_BROADCAST                     = 0x2
-	IFF_CANTCHANGE                    = 0x8e52
+	IFF_CANTCHANGE                    = 0x8f52
 	IFF_DEBUG                         = 0x4
 	IFF_LINK0                         = 0x1000
 	IFF_LINK1                         = 0x2000
@@ -431,10 +614,9 @@ const (
 	IFT_ATMVCIENDPT                   = 0xc2
 	IFT_ATMVIRTUAL                    = 0x95
 	IFT_BGPPOLICYACCOUNTING           = 0xa2
-	IFT_BLUETOOTH                     = 0xf8
 	IFT_BRIDGE                        = 0xd1
 	IFT_BSC                           = 0x53
-	IFT_CARP                          = 0xf7
+	IFT_CARP                          = 0xf8
 	IFT_CCTEMUL                       = 0x3d
 	IFT_CEPT                          = 0x13
 	IFT_CES                           = 0x85
@@ -455,19 +637,17 @@ const (
 	IFT_DS1FDL                        = 0xaa
 	IFT_DS3                           = 0x1e
 	IFT_DTM                           = 0x8c
-	IFT_DUMMY                         = 0xf1
 	IFT_DVBASILN                      = 0xac
 	IFT_DVBASIOUT                     = 0xad
 	IFT_DVBRCCDOWNSTREAM              = 0x93
 	IFT_DVBRCCMACLAYER                = 0x92
 	IFT_DVBRCCUPSTREAM                = 0x94
 	IFT_ECONET                        = 0xce
-	IFT_ENC                           = 0xf4
 	IFT_EON                           = 0x19
 	IFT_EPLRS                         = 0x57
 	IFT_ESCON                         = 0x49
 	IFT_ETHER                         = 0x6
-	IFT_FAITH                         = 0xf3
+	IFT_FAITH                         = 0xf2
 	IFT_FAST                          = 0x7d
 	IFT_FASTETHER                     = 0x3e
 	IFT_FASTETHERFX                   = 0x45
@@ -555,7 +735,6 @@ const (
 	IFT_P80                           = 0xd
 	IFT_PARA                          = 0x22
 	IFT_PFLOG                         = 0xf5
-	IFT_PFLOW                         = 0xf9
 	IFT_PFSYNC                        = 0xf6
 	IFT_PLC                           = 0xae
 	IFT_PON155                        = 0xcf
@@ -573,7 +752,7 @@ const (
 	IFT_PROPVIRTUAL                   = 0x35
 	IFT_PROPWIRELESSP2P               = 0x9d
 	IFT_PTPSERIAL                     = 0x16
-	IFT_PVC                           = 0xf2
+	IFT_PVC                           = 0xf1
 	IFT_Q2931                         = 0xc9
 	IFT_QLLC                          = 0x44
 	IFT_RADIOMAC                      = 0xbc
@@ -599,6 +778,7 @@ const (
 	IFT_SS7SIGLINK                    = 0x9c
 	IFT_STACKTOSTACK                  = 0x6f
 	IFT_STARLAN                       = 0xb
+	IFT_STF                           = 0xd7
 	IFT_T1                            = 0x12
 	IFT_TDLC                          = 0x74
 	IFT_TELINK                        = 0xc8
@@ -633,6 +813,12 @@ const (
 	IFT_X25MLP                        = 0x79
 	IFT_X25PLE                        = 0x28
 	IFT_XETHER                        = 0x1a
+	IGNBRK                            = 0x1
+	IGNCR                             = 0x80
+	IGNPAR                            = 0x4
+	IMAXBEL                           = 0x2000
+	INLCR                             = 0x40
+	INPCK                             = 0x10
 	IN_CLASSA_HOST                    = 0xffffff
 	IN_CLASSA_MAX                     = 0x80
 	IN_CLASSA_NET                     = 0xff000000
@@ -648,12 +834,8 @@ const (
 	IN_CLASSD_NET                     = 0xf0000000
 	IN_CLASSD_NSHIFT                  = 0x1c
 	IN_LOOPBACKNET                    = 0x7f
-	IN_RFC3021_HOST                   = 0x1
-	IN_RFC3021_NET                    = 0xfffffffe
-	IN_RFC3021_NSHIFT                 = 0x1f
 	IPPROTO_AH                        = 0x33
 	IPPROTO_CARP                      = 0x70
-	IPPROTO_DIVERT                    = 0x102
 	IPPROTO_DONE                      = 0x101
 	IPPROTO_DSTOPTS                   = 0x3c
 	IPPROTO_EGP                       = 0x8
@@ -674,10 +856,10 @@ const (
 	IPPROTO_IPIP                      = 0x4
 	IPPROTO_IPV4                      = 0x4
 	IPPROTO_IPV6                      = 0x29
+	IPPROTO_IPV6_ICMP                 = 0x3a
 	IPPROTO_MAX                       = 0x100
-	IPPROTO_MAXID                     = 0x103
+	IPPROTO_MAXID                     = 0x34
 	IPPROTO_MOBILE                    = 0x37
-	IPPROTO_MPLS                      = 0x89
 	IPPROTO_NONE                      = 0x3b
 	IPPROTO_PFSYNC                    = 0xf0
 	IPPROTO_PIM                       = 0x67
@@ -688,16 +870,13 @@ const (
 	IPPROTO_TCP                       = 0x6
 	IPPROTO_TP                        = 0x1d
 	IPPROTO_UDP                       = 0x11
-	IPV6_AUTH_LEVEL                   = 0x35
-	IPV6_AUTOFLOWLABEL                = 0x3b
+	IPPROTO_VRRP                      = 0x70
 	IPV6_CHECKSUM                     = 0x1a
 	IPV6_DEFAULT_MULTICAST_HOPS       = 0x1
 	IPV6_DEFAULT_MULTICAST_LOOP       = 0x1
 	IPV6_DEFHLIM                      = 0x40
 	IPV6_DONTFRAG                     = 0x3e
 	IPV6_DSTOPTS                      = 0x32
-	IPV6_ESP_NETWORK_LEVEL            = 0x37
-	IPV6_ESP_TRANS_LEVEL              = 0x36
 	IPV6_FAITH                        = 0x1d
 	IPV6_FLOWINFO_MASK                = 0xffffff0f
 	IPV6_FLOWLABEL_MASK               = 0xffff0f00
@@ -705,7 +884,7 @@ const (
 	IPV6_HLIMDEC                      = 0x1
 	IPV6_HOPLIMIT                     = 0x2f
 	IPV6_HOPOPTS                      = 0x31
-	IPV6_IPCOMP_LEVEL                 = 0x3c
+	IPV6_IPSEC_POLICY                 = 0x1c
 	IPV6_JOIN_GROUP                   = 0xc
 	IPV6_LEAVE_GROUP                  = 0xd
 	IPV6_MAXHLIM                      = 0xff
@@ -715,9 +894,7 @@ const (
 	IPV6_MULTICAST_IF                 = 0x9
 	IPV6_MULTICAST_LOOP               = 0xb
 	IPV6_NEXTHOP                      = 0x30
-	IPV6_OPTIONS                      = 0x1
 	IPV6_PATHMTU                      = 0x2c
-	IPV6_PIPEX                        = 0x3f
 	IPV6_PKTINFO                      = 0x2e
 	IPV6_PORTRANGE                    = 0xe
 	IPV6_PORTRANGE_DEFAULT            = 0x0
@@ -730,7 +907,6 @@ const (
 	IPV6_RECVPKTINFO                  = 0x24
 	IPV6_RECVRTHDR                    = 0x26
 	IPV6_RECVTCLASS                   = 0x39
-	IPV6_RTABLE                       = 0x1021
 	IPV6_RTHDR                        = 0x33
 	IPV6_RTHDRDSTOPTS                 = 0x23
 	IPV6_RTHDR_LOOSE                  = 0x0
@@ -744,74 +920,105 @@ const (
 	IPV6_VERSION                      = 0x60
 	IPV6_VERSION_MASK                 = 0xf0
 	IP_ADD_MEMBERSHIP                 = 0xc
-	IP_AUTH_LEVEL                     = 0x14
 	IP_DEFAULT_MULTICAST_LOOP         = 0x1
 	IP_DEFAULT_MULTICAST_TTL          = 0x1
 	IP_DF                             = 0x4000
 	IP_DROP_MEMBERSHIP                = 0xd
-	IP_ESP_NETWORK_LEVEL              = 0x16
-	IP_ESP_TRANS_LEVEL                = 0x15
+	IP_EF                             = 0x8000
+	IP_ERRORMTU                       = 0x15
 	IP_HDRINCL                        = 0x2
-	IP_IPCOMP_LEVEL                   = 0x1d
-	IP_IPSEC_LOCAL_AUTH               = 0x1b
-	IP_IPSEC_LOCAL_CRED               = 0x19
-	IP_IPSEC_LOCAL_ID                 = 0x17
-	IP_IPSEC_REMOTE_AUTH              = 0x1c
-	IP_IPSEC_REMOTE_CRED              = 0x1a
-	IP_IPSEC_REMOTE_ID                = 0x18
+	IP_IPSEC_POLICY                   = 0x16
 	IP_MAXPACKET                      = 0xffff
-	IP_MAX_MEMBERSHIPS                = 0xfff
+	IP_MAX_MEMBERSHIPS                = 0x14
 	IP_MF                             = 0x2000
-	IP_MINTTL                         = 0x20
-	IP_MIN_MEMBERSHIPS                = 0xf
+	IP_MINFRAGSIZE                    = 0x45
+	IP_MINTTL                         = 0x18
 	IP_MSS                            = 0x240
 	IP_MULTICAST_IF                   = 0x9
 	IP_MULTICAST_LOOP                 = 0xb
 	IP_MULTICAST_TTL                  = 0xa
 	IP_OFFMASK                        = 0x1fff
 	IP_OPTIONS                        = 0x1
-	IP_PIPEX                          = 0x22
 	IP_PORTRANGE                      = 0x13
 	IP_PORTRANGE_DEFAULT              = 0x0
 	IP_PORTRANGE_HIGH                 = 0x1
 	IP_PORTRANGE_LOW                  = 0x2
 	IP_RECVDSTADDR                    = 0x7
-	IP_RECVDSTPORT                    = 0x21
-	IP_RECVIF                         = 0x1e
+	IP_RECVIF                         = 0x14
 	IP_RECVOPTS                       = 0x5
 	IP_RECVRETOPTS                    = 0x6
-	IP_RECVRTABLE                     = 0x23
-	IP_RECVTTL                        = 0x1f
+	IP_RECVTTL                        = 0x17
 	IP_RETOPTS                        = 0x8
 	IP_RF                             = 0x8000
-	IP_RTABLE                         = 0x1021
 	IP_TOS                            = 0x3
 	IP_TTL                            = 0x4
-	MAP_ET_KVAGUARD                   = 0x10
+	ISIG                              = 0x80
+	ISTRIP                            = 0x20
+	IXANY                             = 0x800
+	IXOFF                             = 0x400
+	IXON                              = 0x200
+	LOCK_EX                           = 0x2
+	LOCK_NB                           = 0x4
+	LOCK_SH                           = 0x1
+	LOCK_UN                           = 0x8
 	MSG_BCAST                         = 0x100
+	MSG_CMSG_CLOEXEC                  = 0x800
+	MSG_CONTROLMBUF                   = 0x2000000
 	MSG_CTRUNC                        = 0x20
 	MSG_DONTROUTE                     = 0x4
 	MSG_DONTWAIT                      = 0x80
 	MSG_EOR                           = 0x8
+	MSG_IOVUSRSPACE                   = 0x4000000
+	MSG_LENUSRSPACE                   = 0x8000000
 	MSG_MCAST                         = 0x200
+	MSG_NAMEMBUF                      = 0x1000000
+	MSG_NBIO                          = 0x1000
+	MSG_NOSIGNAL                      = 0x400
 	MSG_OOB                           = 0x1
 	MSG_PEEK                          = 0x2
 	MSG_TRUNC                         = 0x10
+	MSG_USERFLAGS                     = 0xffffff
 	MSG_WAITALL                       = 0x40
-	NAME_MAX                          = 0xff
+	NAME_MAX                          = 0x1ff
 	NET_RT_DUMP                       = 0x1
 	NET_RT_FLAGS                      = 0x2
-	NET_RT_IFLIST                     = 0x3
+	NET_RT_IFLIST                     = 0x5
 	NET_RT_MAXID                      = 0x6
-	NET_RT_STATS                      = 0x4
-	NET_RT_TABLE                      = 0x5
+	NET_RT_OIFLIST                    = 0x4
+	NET_RT_OOIFLIST                   = 0x3
+	NOFLSH                            = 0x80000000
+	NOTE_ATTRIB                       = 0x8
+	NOTE_CHILD                        = 0x4
+	NOTE_DELETE                       = 0x1
+	NOTE_EXEC                         = 0x20000000
+	NOTE_EXIT                         = 0x80000000
+	NOTE_EXTEND                       = 0x4
+	NOTE_FORK                         = 0x40000000
+	NOTE_LINK                         = 0x10
+	NOTE_LOWAT                        = 0x1
+	NOTE_PCTRLMASK                    = 0xf0000000
+	NOTE_PDATAMASK                    = 0xfffff
+	NOTE_RENAME                       = 0x20
+	NOTE_REVOKE                       = 0x40
+	NOTE_TRACK                        = 0x1
+	NOTE_TRACKERR                     = 0x2
+	NOTE_WRITE                        = 0x2
+	OCRNL                             = 0x10
+	OFIOGETBMAP                       = 0xc004667a
+	ONLCR                             = 0x2
+	ONLRET                            = 0x40
+	ONOCR                             = 0x20
+	ONOEOT                            = 0x8
+	OPOST                             = 0x1
 	O_ACCMODE                         = 0x3
+	O_ALT_IO                          = 0x40000
 	O_APPEND                          = 0x8
 	O_ASYNC                           = 0x40
-	O_CLOEXEC                         = 0x10000
+	O_CLOEXEC                         = 0x400000
 	O_CREAT                           = 0x200
-	O_DIRECTORY                       = 0x20000
-	O_DSYNC                           = 0x80
+	O_DIRECT                          = 0x80000
+	O_DIRECTORY                       = 0x200000
+	O_DSYNC                           = 0x10000
 	O_EXCL                            = 0x800
 	O_EXLOCK                          = 0x20
 	O_FSYNC                           = 0x80
@@ -819,13 +1026,27 @@ const (
 	O_NOCTTY                          = 0x8000
 	O_NOFOLLOW                        = 0x100
 	O_NONBLOCK                        = 0x4
+	O_NOSIGPIPE                       = 0x1000000
 	O_RDONLY                          = 0x0
 	O_RDWR                            = 0x2
-	O_RSYNC                           = 0x80
+	O_RSYNC                           = 0x20000
 	O_SHLOCK                          = 0x10
 	O_SYNC                            = 0x80
 	O_TRUNC                           = 0x400
 	O_WRONLY                          = 0x1
+	PARENB                            = 0x1000
+	PARMRK                            = 0x8
+	PARODD                            = 0x2000
+	PENDIN                            = 0x20000000
+	PRI_IOFLUSH                       = 0x7c
+	RLIMIT_AS                         = 0xa
+	RLIMIT_CORE                       = 0x4
+	RLIMIT_CPU                        = 0x0
+	RLIMIT_DATA                       = 0x2
+	RLIMIT_FSIZE                      = 0x1
+	RLIMIT_NOFILE                     = 0x8
+	RLIMIT_STACK                      = 0x3
+	RLIM_INFINITY                     = 0x7fffffffffffffff
 	RTAX_AUTHOR                       = 0x6
 	RTAX_BRD                          = 0x7
 	RTAX_DST                          = 0x0
@@ -833,11 +1054,9 @@ const (
 	RTAX_GENMASK                      = 0x3
 	RTAX_IFA                          = 0x5
 	RTAX_IFP                          = 0x4
-	RTAX_LABEL                        = 0xa
-	RTAX_MAX                          = 0xb
+	RTAX_MAX                          = 0x9
 	RTAX_NETMASK                      = 0x2
-	RTAX_SRC                          = 0x8
-	RTAX_SRCMASK                      = 0x9
+	RTAX_TAG                          = 0x8
 	RTA_AUTHOR                        = 0x40
 	RTA_BRD                           = 0x80
 	RTA_DST                           = 0x1
@@ -845,52 +1064,48 @@ const (
 	RTA_GENMASK                       = 0x8
 	RTA_IFA                           = 0x20
 	RTA_IFP                           = 0x10
-	RTA_LABEL                         = 0x400
 	RTA_NETMASK                       = 0x4
-	RTA_SRC                           = 0x100
-	RTA_SRCMASK                       = 0x200
-	RTF_ANNOUNCE                      = 0x4000
+	RTA_TAG                           = 0x100
+	RTF_ANNOUNCE                      = 0x20000
 	RTF_BLACKHOLE                     = 0x1000
-	RTF_CLONED                        = 0x10000
+	RTF_CLONED                        = 0x2000
 	RTF_CLONING                       = 0x100
 	RTF_DONE                          = 0x40
 	RTF_DYNAMIC                       = 0x10
-	RTF_FMASK                         = 0x8f808
 	RTF_GATEWAY                       = 0x2
 	RTF_HOST                          = 0x4
-	RTF_JUMBO                         = 0x80000
 	RTF_LLINFO                        = 0x400
 	RTF_MASK                          = 0x80
 	RTF_MODIFIED                      = 0x20
-	RTF_MPATH                         = 0x40000
-	RTF_MPLS                          = 0x100000
-	RTF_PERMANENT_ARP                 = 0x2000
 	RTF_PROTO1                        = 0x8000
 	RTF_PROTO2                        = 0x4000
-	RTF_PROTO3                        = 0x2000
 	RTF_REJECT                        = 0x8
-	RTF_SOURCE                        = 0x20000
+	RTF_SRC                           = 0x10000
 	RTF_STATIC                        = 0x800
-	RTF_TUNNEL                        = 0x100000
 	RTF_UP                            = 0x1
-	RTF_USETRAILERS                   = 0x8000
 	RTF_XRESOLVE                      = 0x200
 	RTM_ADD                           = 0x1
 	RTM_CHANGE                        = 0x3
+	RTM_CHGADDR                       = 0x15
 	RTM_DELADDR                       = 0xd
 	RTM_DELETE                        = 0x2
-	RTM_DESYNC                        = 0x10
 	RTM_GET                           = 0x4
-	RTM_IFANNOUNCE                    = 0xf
-	RTM_IFINFO                        = 0xe
+	RTM_IEEE80211                     = 0x11
+	RTM_IFANNOUNCE                    = 0x10
+	RTM_IFINFO                        = 0x14
+	RTM_LLINFO_UPD                    = 0x13
 	RTM_LOCK                          = 0x8
 	RTM_LOSING                        = 0x5
-	RTM_MAXSIZE                       = 0x800
 	RTM_MISS                          = 0x7
 	RTM_NEWADDR                       = 0xc
+	RTM_OIFINFO                       = 0xf
+	RTM_OLDADD                        = 0x9
+	RTM_OLDDEL                        = 0xa
+	RTM_OOIFINFO                      = 0xe
 	RTM_REDIRECT                      = 0x6
 	RTM_RESOLVE                       = 0xb
 	RTM_RTTUNIT                       = 0xf4240
+	RTM_SETGATE                       = 0x12
 	RTM_VERSION                       = 0x4
 	RTV_EXPIRE                        = 0x4
 	RTV_HOPCOUNT                      = 0x2
@@ -900,159 +1115,82 @@ const (
 	RTV_RTTVAR                        = 0x80
 	RTV_SPIPE                         = 0x10
 	RTV_SSTHRESH                      = 0x20
-	RT_TABLEID_MAX                    = 0xff
-	SCM_CREDS                         = 0x2
+	RUSAGE_CHILDREN                   = -0x1
+	RUSAGE_SELF                       = 0x0
+	SCM_CREDS                         = 0x4
 	SCM_RIGHTS                        = 0x1
-	SCM_TIMESTAMP                     = 0x4
+	SCM_TIMESTAMP                     = 0x8
 	SHUT_RD                           = 0x0
 	SHUT_RDWR                         = 0x2
 	SHUT_WR                           = 0x1
-	SIGABRT                           = 0x6
-	SIGALRM                           = 0xe
-	SIGBUS                            = 0xa
-	SIGCHLD                           = 0x14
-	SIGCONT                           = 0x13
-	SIGEMT                            = 0x7
-	SIGFPE                            = 0x8
-	SIGHUP                            = 0x1
-	SIGILL                            = 0x4
-	SIGINFO                           = 0x1d
-	SIGINT                            = 0x2
-	SIGIO                             = 0x17
-	SIGIOT                            = 0x6
-	SIGKILL                           = 0x9
-	SIGPIPE                           = 0xd
-	SIGPROF                           = 0x1b
-	SIGQUIT                           = 0x3
-	SIGSEGV                           = 0xb
-	SIGSTOP                           = 0x11
-	SIGSYS                            = 0xc
-	SIGTERM                           = 0xf
-	SIGTHR                            = 0x20
-	SIGTRAP                           = 0x5
-	SIGTSTP                           = 0x12
-	SIGTTIN                           = 0x15
-	SIGTTOU                           = 0x16
-	SIGURG                            = 0x10
-	SIGUSR1                           = 0x1e
-	SIGUSR2                           = 0x1f
-	SIGVTALRM                         = 0x1a
-	SIGWINCH                          = 0x1c
-	SIGXCPU                           = 0x18
-	SIGXFSZ                           = 0x19
-	SIOCADDMULTI                      = 0x80206931
+	SIOCADDMULTI                      = 0x80906931
+	SIOCADDRT                         = 0x8030720a
 	SIOCAIFADDR                       = 0x8040691a
-	SIOCAIFGROUP                      = 0x80246987
-	SIOCALIFADDR                      = 0x8218691c
+	SIOCALIFADDR                      = 0x8118691c
 	SIOCATMARK                        = 0x40047307
-	SIOCBRDGADD                       = 0x8054693c
-	SIOCBRDGADDS                      = 0x80546941
-	SIOCBRDGARL                       = 0x806e694d
-	SIOCBRDGDADDR                     = 0x80286947
-	SIOCBRDGDEL                       = 0x8054693d
-	SIOCBRDGDELS                      = 0x80546942
-	SIOCBRDGFLUSH                     = 0x80546948
-	SIOCBRDGFRL                       = 0x806e694e
-	SIOCBRDGGCACHE                    = 0xc0146941
-	SIOCBRDGGFD                       = 0xc0146952
-	SIOCBRDGGHT                       = 0xc0146951
-	SIOCBRDGGIFFLGS                   = 0xc054693e
-	SIOCBRDGGMA                       = 0xc0146953
-	SIOCBRDGGPARAM                    = 0xc0386958
-	SIOCBRDGGPRI                      = 0xc0146950
-	SIOCBRDGGRL                       = 0xc028694f
-	SIOCBRDGGSIFS                     = 0xc054693c
-	SIOCBRDGGTO                       = 0xc0146946
-	SIOCBRDGIFS                       = 0xc0546942
-	SIOCBRDGRTS                       = 0xc0186943
-	SIOCBRDGSADDR                     = 0xc0286944
-	SIOCBRDGSCACHE                    = 0x80146940
-	SIOCBRDGSFD                       = 0x80146952
-	SIOCBRDGSHT                       = 0x80146951
-	SIOCBRDGSIFCOST                   = 0x80546955
-	SIOCBRDGSIFFLGS                   = 0x8054693f
-	SIOCBRDGSIFPRIO                   = 0x80546954
-	SIOCBRDGSMA                       = 0x80146953
-	SIOCBRDGSPRI                      = 0x80146950
-	SIOCBRDGSPROTO                    = 0x8014695a
-	SIOCBRDGSTO                       = 0x80146945
-	SIOCBRDGSTXHC                     = 0x80146959
-	SIOCDELMULTI                      = 0x80206932
-	SIOCDIFADDR                       = 0x80206919
-	SIOCDIFGROUP                      = 0x80246989
-	SIOCDIFPHYADDR                    = 0x80206949
-	SIOCDLIFADDR                      = 0x8218691e
-	SIOCGETKALIVE                     = 0xc01869a4
-	SIOCGETLABEL                      = 0x8020699a
-	SIOCGETPFLOW                      = 0xc02069fe
-	SIOCGETPFSYNC                     = 0xc02069f8
+	SIOCDELMULTI                      = 0x80906932
+	SIOCDELRT                         = 0x8030720b
+	SIOCDIFADDR                       = 0x80906919
+	SIOCDIFPHYADDR                    = 0x80906949
+	SIOCDLIFADDR                      = 0x8118691e
+	SIOCGDRVSPEC                      = 0xc01c697b
+	SIOCGETPFSYNC                     = 0xc09069f8
 	SIOCGETSGCNT                      = 0xc0147534
 	SIOCGETVIFCNT                     = 0xc0147533
-	SIOCGETVLANPRIO                   = 0xc0206990
 	SIOCGHIWAT                        = 0x40047301
-	SIOCGIFADDR                       = 0xc0206921
-	SIOCGIFASYNCMAP                   = 0xc020697c
-	SIOCGIFBRDADDR                    = 0xc0206923
-	SIOCGIFCONF                       = 0xc0086924
-	SIOCGIFDATA                       = 0xc020691b
-	SIOCGIFDESCR                      = 0xc0206981
-	SIOCGIFDSTADDR                    = 0xc0206922
-	SIOCGIFFLAGS                      = 0xc0206911
-	SIOCGIFGATTR                      = 0xc024698b
-	SIOCGIFGENERIC                    = 0xc020693a
-	SIOCGIFGMEMB                      = 0xc024698a
-	SIOCGIFGROUP                      = 0xc0246988
+	SIOCGIFADDR                       = 0xc0906921
+	SIOCGIFADDRPREF                   = 0xc0946920
+	SIOCGIFALIAS                      = 0xc040691b
+	SIOCGIFBRDADDR                    = 0xc0906923
+	SIOCGIFCAP                        = 0xc0206976
+	SIOCGIFCONF                       = 0xc0086926
+	SIOCGIFDATA                       = 0xc0946985
+	SIOCGIFDLT                        = 0xc0906977
+	SIOCGIFDSTADDR                    = 0xc0906922
+	SIOCGIFFLAGS                      = 0xc0906911
+	SIOCGIFGENERIC                    = 0xc090693a
 	SIOCGIFMEDIA                      = 0xc0286936
-	SIOCGIFMETRIC                     = 0xc0206917
-	SIOCGIFMTU                        = 0xc020697e
-	SIOCGIFNETMASK                    = 0xc0206925
-	SIOCGIFPDSTADDR                   = 0xc0206948
-	SIOCGIFPRIORITY                   = 0xc020699c
-	SIOCGIFPSRCADDR                   = 0xc0206947
-	SIOCGIFRDOMAIN                    = 0xc02069a0
-	SIOCGIFRTLABEL                    = 0xc0206983
-	SIOCGIFTIMESLOT                   = 0xc0206986
-	SIOCGIFXFLAGS                     = 0xc020699e
-	SIOCGLIFADDR                      = 0xc218691d
-	SIOCGLIFPHYADDR                   = 0xc218694b
-	SIOCGLIFPHYRTABLE                 = 0xc02069a2
+	SIOCGIFMETRIC                     = 0xc0906917
+	SIOCGIFMTU                        = 0xc090697e
+	SIOCGIFNETMASK                    = 0xc0906925
+	SIOCGIFPDSTADDR                   = 0xc0906948
+	SIOCGIFPSRCADDR                   = 0xc0906947
+	SIOCGLIFADDR                      = 0xc118691d
+	SIOCGLIFPHYADDR                   = 0xc118694b
+	SIOCGLINKSTR                      = 0xc01c6987
 	SIOCGLOWAT                        = 0x40047303
 	SIOCGPGRP                         = 0x40047309
-	SIOCGVH                           = 0xc02069f6
-	SIOCIFCREATE                      = 0x8020697a
-	SIOCIFDESTROY                     = 0x80206979
+	SIOCGVH                           = 0xc0906983
+	SIOCIFCREATE                      = 0x8090697a
+	SIOCIFDESTROY                     = 0x80906979
 	SIOCIFGCLONERS                    = 0xc00c6978
-	SIOCSETKALIVE                     = 0x801869a3
-	SIOCSETLABEL                      = 0x80206999
-	SIOCSETPFLOW                      = 0x802069fd
-	SIOCSETPFSYNC                     = 0x802069f7
-	SIOCSETVLANPRIO                   = 0x8020698f
+	SIOCINITIFADDR                    = 0xc0446984
+	SIOCSDRVSPEC                      = 0x801c697b
+	SIOCSETPFSYNC                     = 0x809069f7
 	SIOCSHIWAT                        = 0x80047300
-	SIOCSIFADDR                       = 0x8020690c
-	SIOCSIFASYNCMAP                   = 0x8020697d
-	SIOCSIFBRDADDR                    = 0x80206913
-	SIOCSIFDESCR                      = 0x80206980
-	SIOCSIFDSTADDR                    = 0x8020690e
-	SIOCSIFFLAGS                      = 0x80206910
-	SIOCSIFGATTR                      = 0x8024698c
-	SIOCSIFGENERIC                    = 0x80206939
-	SIOCSIFLLADDR                     = 0x8020691f
-	SIOCSIFMEDIA                      = 0xc0206935
-	SIOCSIFMETRIC                     = 0x80206918
-	SIOCSIFMTU                        = 0x8020697f
-	SIOCSIFNETMASK                    = 0x80206916
+	SIOCSIFADDR                       = 0x8090690c
+	SIOCSIFADDRPREF                   = 0x8094691f
+	SIOCSIFBRDADDR                    = 0x80906913
+	SIOCSIFCAP                        = 0x80206975
+	SIOCSIFDSTADDR                    = 0x8090690e
+	SIOCSIFFLAGS                      = 0x80906910
+	SIOCSIFGENERIC                    = 0x80906939
+	SIOCSIFMEDIA                      = 0xc0906935
+	SIOCSIFMETRIC                     = 0x80906918
+	SIOCSIFMTU                        = 0x8090697f
+	SIOCSIFNETMASK                    = 0x80906916
 	SIOCSIFPHYADDR                    = 0x80406946
-	SIOCSIFPRIORITY                   = 0x8020699b
-	SIOCSIFRDOMAIN                    = 0x8020699f
-	SIOCSIFRTLABEL                    = 0x80206982
-	SIOCSIFTIMESLOT                   = 0x80206985
-	SIOCSIFXFLAGS                     = 0x8020699d
-	SIOCSLIFPHYADDR                   = 0x8218694a
-	SIOCSLIFPHYRTABLE                 = 0x802069a1
+	SIOCSLIFPHYADDR                   = 0x8118694a
+	SIOCSLINKSTR                      = 0x801c6988
 	SIOCSLOWAT                        = 0x80047302
 	SIOCSPGRP                         = 0x80047308
-	SIOCSVH                           = 0xc02069f5
+	SIOCSVH                           = 0xc0906982
+	SIOCZIFDATA                       = 0xc0946986
+	SOCK_CLOEXEC                      = 0x10000000
 	SOCK_DGRAM                        = 0x2
+	SOCK_FLAGS_MASK                   = 0xf0000000
+	SOCK_NONBLOCK                     = 0x20000000
+	SOCK_NOSIGPIPE                    = 0x40000000
 	SOCK_RAW                          = 0x3
 	SOCK_RDM                          = 0x4
 	SOCK_SEQPACKET                    = 0x5
@@ -1060,63 +1198,107 @@ const (
 	SOL_SOCKET                        = 0xffff
 	SOMAXCONN                         = 0x80
 	SO_ACCEPTCONN                     = 0x2
-	SO_BINDANY                        = 0x1000
+	SO_ACCEPTFILTER                   = 0x1000
 	SO_BROADCAST                      = 0x20
 	SO_DEBUG                          = 0x1
 	SO_DONTROUTE                      = 0x10
 	SO_ERROR                          = 0x1007
-	SO_JUMBO                          = 0x400
 	SO_KEEPALIVE                      = 0x8
 	SO_LINGER                         = 0x80
-	SO_NETPROC                        = 0x1020
+	SO_NOHEADER                       = 0x100a
+	SO_NOSIGPIPE                      = 0x800
 	SO_OOBINLINE                      = 0x100
-	SO_PEERCRED                       = 0x1022
+	SO_OVERFLOWED                     = 0x1009
 	SO_RCVBUF                         = 0x1002
 	SO_RCVLOWAT                       = 0x1004
-	SO_RCVTIMEO                       = 0x1006
+	SO_RCVTIMEO                       = 0x100c
 	SO_REUSEADDR                      = 0x4
 	SO_REUSEPORT                      = 0x200
-	SO_RTABLE                         = 0x1021
 	SO_SNDBUF                         = 0x1001
 	SO_SNDLOWAT                       = 0x1003
-	SO_SNDTIMEO                       = 0x1005
-	SO_SPLICE                         = 0x1023
-	SO_TIMESTAMP                      = 0x800
+	SO_SNDTIMEO                       = 0x100b
+	SO_TIMESTAMP                      = 0x2000
 	SO_TYPE                           = 0x1008
 	SO_USELOOPBACK                    = 0x40
+	SYSCTL_VERSION                    = 0x1000000
+	SYSCTL_VERS_0                     = 0x0
+	SYSCTL_VERS_1                     = 0x1000000
+	SYSCTL_VERS_MASK                  = 0xff000000
+	S_ARCH1                           = 0x10000
+	S_ARCH2                           = 0x20000
+	S_BLKSIZE                         = 0x200
+	S_IEXEC                           = 0x40
+	S_IFBLK                           = 0x6000
+	S_IFCHR                           = 0x2000
+	S_IFDIR                           = 0x4000
+	S_IFIFO                           = 0x1000
+	S_IFLNK                           = 0xa000
+	S_IFMT                            = 0xf000
+	S_IFREG                           = 0x8000
+	S_IFSOCK                          = 0xc000
+	S_IFWHT                           = 0xe000
+	S_IREAD                           = 0x100
+	S_IRGRP                           = 0x20
+	S_IROTH                           = 0x4
+	S_IRUSR                           = 0x100
+	S_IRWXG                           = 0x38
+	S_IRWXO                           = 0x7
+	S_IRWXU                           = 0x1c0
+	S_ISGID                           = 0x400
+	S_ISTXT                           = 0x200
+	S_ISUID                           = 0x800
+	S_ISVTX                           = 0x200
+	S_IWGRP                           = 0x10
+	S_IWOTH                           = 0x2
+	S_IWRITE                          = 0x80
+	S_IWUSR                           = 0x80
+	S_IXGRP                           = 0x8
+	S_IXOTH                           = 0x1
+	S_IXUSR                           = 0x40
+	S_LOGIN_SET                       = 0x1
+	TCIFLUSH                          = 0x1
+	TCIOFLUSH                         = 0x3
+	TCOFLUSH                          = 0x2
+	TCP_CONGCTL                       = 0x20
+	TCP_KEEPCNT                       = 0x6
+	TCP_KEEPIDLE                      = 0x3
+	TCP_KEEPINIT                      = 0x7
+	TCP_KEEPINTVL                     = 0x5
 	TCP_MAXBURST                      = 0x4
 	TCP_MAXSEG                        = 0x2
 	TCP_MAXWIN                        = 0xffff
-	TCP_MAX_SACK                      = 0x3
 	TCP_MAX_WINSHIFT                  = 0xe
-	TCP_MD5SIG                        = 0x4
-	TCP_MSS                           = 0x200
+	TCP_MD5SIG                        = 0x10
+	TCP_MINMSS                        = 0xd8
+	TCP_MSS                           = 0x218
 	TCP_NODELAY                       = 0x1
-	TCP_NSTATES                       = 0xb
-	TCP_SACK_ENABLE                   = 0x8
+	TCSAFLUSH                         = 0x2
 	TIOCCBRK                          = 0x2000747a
 	TIOCCDTR                          = 0x20007478
 	TIOCCONS                          = 0x80047462
+	TIOCDCDTIMESTAMP                  = 0x400c7458
 	TIOCDRAIN                         = 0x2000745e
 	TIOCEXCL                          = 0x2000740d
 	TIOCEXT                           = 0x80047460
+	TIOCFLAG_CDTRCTS                  = 0x10
 	TIOCFLAG_CLOCAL                   = 0x2
 	TIOCFLAG_CRTSCTS                  = 0x4
 	TIOCFLAG_MDMBUF                   = 0x8
-	TIOCFLAG_PPS                      = 0x10
 	TIOCFLAG_SOFTCAR                  = 0x1
 	TIOCFLUSH                         = 0x80047410
 	TIOCGETA                          = 0x402c7413
 	TIOCGETD                          = 0x4004741a
 	TIOCGFLAGS                        = 0x4004745d
+	TIOCGLINED                        = 0x40207442
 	TIOCGPGRP                         = 0x40047477
-	TIOCGTSTAMP                       = 0x4008745b
+	TIOCGQSIZE                        = 0x40047481
+	TIOCGRANTPT                       = 0x20007447
+	TIOCGSID                          = 0x40047463
+	TIOCGSIZE                         = 0x40087468
 	TIOCGWINSZ                        = 0x40087468
 	TIOCMBIC                          = 0x8004746b
 	TIOCMBIS                          = 0x8004746c
 	TIOCMGET                          = 0x4004746a
-	TIOCMODG                          = 0x4004746a
-	TIOCMODS                          = 0x8004746d
 	TIOCMSET                          = 0x8004746d
 	TIOCM_CAR                         = 0x40
 	TIOCM_CD                          = 0x40
@@ -1141,6 +1323,9 @@ const (
 	TIOCPKT_NOSTOP                    = 0x10
 	TIOCPKT_START                     = 0x8
 	TIOCPKT_STOP                      = 0x4
+	TIOCPTMGET                        = 0x40287446
+	TIOCPTSNAME                       = 0x40287448
+	TIOCRCVFRAME                      = 0x80047445
 	TIOCREMOTE                        = 0x80047469
 	TIOCSBRK                          = 0x2000747b
 	TIOCSCTTY                         = 0x20007461
@@ -1150,19 +1335,46 @@ const (
 	TIOCSETAW                         = 0x802c7415
 	TIOCSETD                          = 0x8004741b
 	TIOCSFLAGS                        = 0x8004745c
-	TIOCSIG                           = 0x8004745f
+	TIOCSIG                           = 0x2000745f
+	TIOCSLINED                        = 0x80207443
 	TIOCSPGRP                         = 0x80047476
+	TIOCSQSIZE                        = 0x80047480
+	TIOCSSIZE                         = 0x80087467
 	TIOCSTART                         = 0x2000746e
 	TIOCSTAT                          = 0x80047465
 	TIOCSTI                           = 0x80017472
 	TIOCSTOP                          = 0x2000746f
-	TIOCSTSTAMP                       = 0x8008745a
 	TIOCSWINSZ                        = 0x80087467
 	TIOCUCNTL                         = 0x80047466
+	TIOCXMTFRAME                      = 0x80047444
+	TOSTOP                            = 0x400000
+	VDISCARD                          = 0xf
+	VDSUSP                            = 0xb
+	VEOF                              = 0x0
+	VEOL                              = 0x1
+	VEOL2                             = 0x2
+	VERASE                            = 0x3
+	VINTR                             = 0x8
+	VKILL                             = 0x5
+	VLNEXT                            = 0xe
+	VMIN                              = 0x10
+	VQUIT                             = 0x9
+	VREPRINT                          = 0x6
+	VSTART                            = 0xc
+	VSTATUS                           = 0x12
+	VSTOP                             = 0xd
+	VSUSP                             = 0xa
+	VTIME                             = 0x11
+	VWERASE                           = 0x4
+	WALL                              = 0x8
+	WALLSIG                           = 0x8
 	WALTSIG                           = 0x4
-	WCONTINUED                        = 0x8
+	WCLONE                            = 0x4
 	WCOREFLAG                         = 0x80
 	WNOHANG                           = 0x1
+	WNOWAIT                           = 0x10000
+	WNOZOMBIE                         = 0x20000
+	WOPTSCHECKED                      = 0x40000
 	WSTOPPED                          = 0x7f
 	WUNTRACED                         = 0x2
 )
@@ -1178,17 +1390,11 @@ const (
 	EALREADY        = Errno(0x25)
 	EAUTH           = Errno(0x50)
 	EBADF           = Errno(0x9)
+	EBADMSG         = Errno(0x58)
 	EBADRPC         = Errno(0x48)
 	EBUSY           = Errno(0x10)
-	ECANCELED       = Errno(0x58)
+	ECANCELED       = Errno(0x57)
 	ECHILD          = Errno(0xa)
-	ECHO            = Errno(0x8)
-	ECHOCTL         = Errno(0x40)
-	ECHOE           = Errno(0x2)
-	ECHOK           = Errno(0x4)
-	ECHOKE          = Errno(0x1)
-	ECHONL          = Errno(0x10)
-	ECHOPRT         = Errno(0x20)
 	ECONNABORTED    = Errno(0x35)
 	ECONNREFUSED    = Errno(0x3d)
 	ECONNRESET      = Errno(0x36)
@@ -1202,50 +1408,51 @@ const (
 	EFTYPE          = Errno(0x4f)
 	EHOSTDOWN       = Errno(0x40)
 	EHOSTUNREACH    = Errno(0x41)
-	EIDRM           = Errno(0x59)
-	EILSEQ          = Errno(0x54)
+	EIDRM           = Errno(0x52)
+	EILSEQ          = Errno(0x55)
 	EINPROGRESS     = Errno(0x24)
 	EINTR           = Errno(0x4)
 	EINVAL          = Errno(0x16)
 	EIO             = Errno(0x5)
-	EIPSEC          = Errno(0x52)
 	EISCONN         = Errno(0x38)
 	EISDIR          = Errno(0x15)
-	ELAST           = Errno(0x5b)
+	ELAST           = Errno(0x60)
 	ELOOP           = Errno(0x3e)
-	EMEDIUMTYPE     = Errno(0x56)
 	EMFILE          = Errno(0x18)
 	EMLINK          = Errno(0x1f)
 	EMSGSIZE        = Errno(0x28)
+	EMULTIHOP       = Errno(0x5e)
 	ENAMETOOLONG    = Errno(0x3f)
-	ENDRUNDISC      = Errno(0x9)
 	ENEEDAUTH       = Errno(0x51)
 	ENETDOWN        = Errno(0x32)
 	ENETRESET       = Errno(0x34)
 	ENETUNREACH     = Errno(0x33)
 	ENFILE          = Errno(0x17)
-	ENOATTR         = Errno(0x53)
+	ENOATTR         = Errno(0x5d)
 	ENOBUFS         = Errno(0x37)
+	ENODATA         = Errno(0x59)
 	ENODEV          = Errno(0x13)
 	ENOENT          = Errno(0x2)
 	ENOEXEC         = Errno(0x8)
 	ENOLCK          = Errno(0x4d)
-	ENOMEDIUM       = Errno(0x55)
+	ENOLINK         = Errno(0x5f)
 	ENOMEM          = Errno(0xc)
-	ENOMSG          = Errno(0x5a)
+	ENOMSG          = Errno(0x53)
 	ENOPROTOOPT     = Errno(0x2a)
 	ENOSPC          = Errno(0x1c)
+	ENOSR           = Errno(0x5a)
+	ENOSTR          = Errno(0x5b)
 	ENOSYS          = Errno(0x4e)
 	ENOTBLK         = Errno(0xf)
 	ENOTCONN        = Errno(0x39)
 	ENOTDIR         = Errno(0x14)
 	ENOTEMPTY       = Errno(0x42)
 	ENOTSOCK        = Errno(0x26)
-	ENOTSUP         = Errno(0x5b)
+	ENOTSUP         = Errno(0x56)
 	ENOTTY          = Errno(0x19)
 	ENXIO           = Errno(0x6)
 	EOPNOTSUPP      = Errno(0x2d)
-	EOVERFLOW       = Errno(0x57)
+	EOVERFLOW       = Errno(0x54)
 	EPERM           = Errno(0x1)
 	EPFNOSUPPORT    = Errno(0x2e)
 	EPIPE           = Errno(0x20)
@@ -1253,6 +1460,7 @@ const (
 	EPROCUNAVAIL    = Errno(0x4c)
 	EPROGMISMATCH   = Errno(0x4b)
 	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTO          = Errno(0x60)
 	EPROTONOSUPPORT = Errno(0x2b)
 	EPROTOTYPE      = Errno(0x29)
 	ERANGE          = Errno(0x22)
@@ -1264,6 +1472,7 @@ const (
 	ESPIPE          = Errno(0x1d)
 	ESRCH           = Errno(0x3)
 	ESTALE          = Errno(0x46)
+	ETIME           = Errno(0x5c)
 	ETIMEDOUT       = Errno(0x3c)
 	ETOOMANYREFS    = Errno(0x3b)
 	ETXTBSY         = Errno(0x1a)
@@ -1272,6 +1481,43 @@ const (
 	EXDEV           = Errno(0x12)
 )
 
+// Signals
+const (
+	SIGABRT   = Signal(0x6)
+	SIGALRM   = Signal(0xe)
+	SIGBUS    = Signal(0xa)
+	SIGCHLD   = Signal(0x14)
+	SIGCONT   = Signal(0x13)
+	SIGEMT    = Signal(0x7)
+	SIGFPE    = Signal(0x8)
+	SIGHUP    = Signal(0x1)
+	SIGILL    = Signal(0x4)
+	SIGINFO   = Signal(0x1d)
+	SIGINT    = Signal(0x2)
+	SIGIO     = Signal(0x17)
+	SIGIOT    = Signal(0x6)
+	SIGKILL   = Signal(0x9)
+	SIGPIPE   = Signal(0xd)
+	SIGPROF   = Signal(0x1b)
+	SIGPWR    = Signal(0x20)
+	SIGQUIT   = Signal(0x3)
+	SIGSEGV   = Signal(0xb)
+	SIGSTOP   = Signal(0x11)
+	SIGSYS    = Signal(0xc)
+	SIGTERM   = Signal(0xf)
+	SIGTRAP   = Signal(0x5)
+	SIGTSTP   = Signal(0x12)
+	SIGTTIN   = Signal(0x15)
+	SIGTTOU   = Signal(0x16)
+	SIGURG    = Signal(0x10)
+	SIGUSR1   = Signal(0x1e)
+	SIGUSR2   = Signal(0x1f)
+	SIGVTALRM = Signal(0x1a)
+	SIGWINCH  = Signal(0x1c)
+	SIGXCPU   = Signal(0x18)
+	SIGXFSZ   = Signal(0x19)
+)
+
 // Error table
 var errors = [...]string{
 	1:  "operation not permitted",
@@ -1307,7 +1553,7 @@ var errors = [...]string{
 	31: "too many links",
 	32: "broken pipe",
 	33: "numerical argument out of domain",
-	34: "result too large",
+	34: "result too large or too small",
 	35: "resource temporarily unavailable",
 	36: "operation now in progress",
 	37: "operation already in progress",
@@ -1315,7 +1561,7 @@ var errors = [...]string{
 	39: "destination address required",
 	40: "message too long",
 	41: "protocol wrong type for socket",
-	42: "protocol not available",
+	42: "protocol option not available",
 	43: "protocol not supported",
 	44: "socket type not supported",
 	45: "operation not supported",
@@ -1355,14 +1601,55 @@ var errors = [...]string{
 	79: "inappropriate file type or format",
 	80: "authentication error",
 	81: "need authenticator",
-	82: "IPsec processing failure",
-	83: "attribute not found",
-	84: "illegal byte sequence",
-	85: "no medium found",
-	86: "wrong medium type",
-	87: "value too large to be stored in data type",
-	88: "operation canceled",
-	89: "identifier removed",
-	90: "no message of desired type",
-	91: "not supported",
+	82: "identifier removed",
+	83: "no message of desired type",
+	84: "value too large to be stored in data type",
+	85: "illegal byte sequence",
+	86: "not supported",
+	87: "operation Canceled",
+	88: "bad or Corrupt message",
+	89: "no message available",
+	90: "no STREAM resources",
+	91: "not a STREAM",
+	92: "STREAM ioctl timeout",
+	93: "attribute not found",
+	94: "multihop attempted",
+	95: "link has been severed",
+	96: "protocol error",
+}
+
+// Signal table
+var signals = [...]string{
+	1:  "hangup",
+	2:  "interrupt",
+	3:  "quit",
+	4:  "illegal instruction",
+	5:  "trace/BPT trap",
+	6:  "abort trap",
+	7:  "EMT trap",
+	8:  "floating point exception",
+	9:  "killed",
+	10: "bus error",
+	11: "segmentation fault",
+	12: "bad system call",
+	13: "broken pipe",
+	14: "alarm clock",
+	15: "terminated",
+	16: "urgent I/O condition",
+	17: "stopped (signal)",
+	18: "stopped",
+	19: "continued",
+	20: "child exited",
+	21: "stopped (tty input)",
+	22: "stopped (tty output)",
+	23: "I/O possible",
+	24: "cputime limit exceeded",
+	25: "filesize limit exceeded",
+	26: "virtual timer expired",
+	27: "profiling timer expired",
+	28: "window size changes",
+	29: "information request",
+	30: "user defined signal 1",
+	31: "user defined signal 2",
+	32: "power fail/restart",
 }
diff --git a/src/pkg/syscall/zerrors_netbsd_amd64.go b/src/pkg/syscall/zerrors_netbsd_amd64.go
index c6367fb..f719528 100644
--- a/src/pkg/syscall/zerrors_netbsd_amd64.go
+++ b/src/pkg/syscall/zerrors_netbsd_amd64.go
@@ -8,7 +8,8 @@ package syscall
 
 const (
 	AF_APPLETALK                      = 0x10
-	AF_BLUETOOTH                      = 0x20
+	AF_ARP                            = 0x1c
+	AF_BLUETOOTH                      = 0x1f
 	AF_CCITT                          = 0xa
 	AF_CHAOS                          = 0x5
 	AF_CNT                            = 0x15
@@ -18,67 +19,93 @@ const (
 	AF_DLI                            = 0xd
 	AF_E164                           = 0x1a
 	AF_ECMA                           = 0x8
-	AF_ENCAP                          = 0x1c
 	AF_HYLINK                         = 0xf
+	AF_IEEE80211                      = 0x20
 	AF_IMPLINK                        = 0x3
 	AF_INET                           = 0x2
 	AF_INET6                          = 0x18
 	AF_IPX                            = 0x17
 	AF_ISDN                           = 0x1a
 	AF_ISO                            = 0x7
-	AF_KEY                            = 0x1e
 	AF_LAT                            = 0xe
 	AF_LINK                           = 0x12
 	AF_LOCAL                          = 0x1
-	AF_MAX                            = 0x24
+	AF_MAX                            = 0x23
 	AF_MPLS                           = 0x21
 	AF_NATM                           = 0x1b
 	AF_NS                             = 0x6
+	AF_OROUTE                         = 0x11
 	AF_OSI                            = 0x7
 	AF_PUP                            = 0x4
-	AF_ROUTE                          = 0x11
-	AF_SIP                            = 0x1d
+	AF_ROUTE                          = 0x22
 	AF_SNA                            = 0xb
 	AF_UNIX                           = 0x1
 	AF_UNSPEC                         = 0x0
+	ARPHRD_ARCNET                     = 0x7
 	ARPHRD_ETHER                      = 0x1
 	ARPHRD_FRELAY                     = 0xf
 	ARPHRD_IEEE1394                   = 0x18
 	ARPHRD_IEEE802                    = 0x6
+	ARPHRD_STRIP                      = 0x17
+	B0                                = 0x0
+	B110                              = 0x6e
+	B115200                           = 0x1c200
+	B1200                             = 0x4b0
+	B134                              = 0x86
+	B14400                            = 0x3840
+	B150                              = 0x96
+	B1800                             = 0x708
+	B19200                            = 0x4b00
+	B200                              = 0xc8
+	B230400                           = 0x38400
+	B2400                             = 0x960
+	B28800                            = 0x7080
+	B300                              = 0x12c
+	B38400                            = 0x9600
+	B460800                           = 0x70800
+	B4800                             = 0x12c0
+	B50                               = 0x32
+	B57600                            = 0xe100
+	B600                              = 0x258
+	B7200                             = 0x1c20
+	B75                               = 0x4b
+	B76800                            = 0x12c00
+	B921600                           = 0xe1000
+	B9600                             = 0x2580
+	BIOCFEEDBACK                      = 0x8004427d
 	BIOCFLUSH                         = 0x20004268
 	BIOCGBLEN                         = 0x40044266
-	BIOCGDIRFILT                      = 0x4004427c
 	BIOCGDLT                          = 0x4004426a
-	BIOCGDLTLIST                      = 0xc010427b
-	BIOCGETIF                         = 0x4020426b
-	BIOCGFILDROP                      = 0x40044278
+	BIOCGDLTLIST                      = 0xc0104277
+	BIOCGETIF                         = 0x4090426b
+	BIOCGFEEDBACK                     = 0x4004427c
 	BIOCGHDRCMPLT                     = 0x40044274
-	BIOCGRSIG                         = 0x40044273
-	BIOCGRTIMEOUT                     = 0x4010426e
-	BIOCGSTATS                        = 0x4008426f
+	BIOCGRTIMEOUT                     = 0x4010427b
+	BIOCGSEESENT                      = 0x40044278
+	BIOCGSTATS                        = 0x4080426f
+	BIOCGSTATSOLD                     = 0x4008426f
 	BIOCIMMEDIATE                     = 0x80044270
-	BIOCLOCK                          = 0x20004276
 	BIOCPROMISC                       = 0x20004269
 	BIOCSBLEN                         = 0xc0044266
-	BIOCSDIRFILT                      = 0x8004427d
-	BIOCSDLT                          = 0x8004427a
+	BIOCSDLT                          = 0x80044276
 	BIOCSETF                          = 0x80104267
-	BIOCSETIF                         = 0x8020426c
-	BIOCSETWF                         = 0x80104277
-	BIOCSFILDROP                      = 0x80044279
+	BIOCSETIF                         = 0x8090426c
+	BIOCSFEEDBACK                     = 0x8004427d
 	BIOCSHDRCMPLT                     = 0x80044275
-	BIOCSRSIG                         = 0x80044272
-	BIOCSRTIMEOUT                     = 0x8010426d
+	BIOCSRTIMEOUT                     = 0x8010427a
+	BIOCSSEESENT                      = 0x80044279
+	BIOCSTCPF                         = 0x80104272
+	BIOCSUDPF                         = 0x80104273
 	BIOCVERSION                       = 0x40044271
 	BPF_A                             = 0x10
 	BPF_ABS                           = 0x20
 	BPF_ADD                           = 0x0
-	BPF_ALIGNMENT                     = 0x4
+	BPF_ALIGNMENT                     = 0x8
+	BPF_ALIGNMENT32                   = 0x4
 	BPF_ALU                           = 0x4
 	BPF_AND                           = 0x50
 	BPF_B                             = 0x10
-	BPF_DIRECTION_IN                  = 0x1
-	BPF_DIRECTION_OUT                 = 0x2
+	BPF_DFLTBUFSIZE                   = 0x100000
 	BPF_DIV                           = 0x30
 	BPF_H                             = 0x8
 	BPF_IMM                           = 0x0
@@ -95,7 +122,7 @@ const (
 	BPF_LEN                           = 0x80
 	BPF_LSH                           = 0x60
 	BPF_MAJOR_VERSION                 = 0x1
-	BPF_MAXBUFSIZE                    = 0x200000
+	BPF_MAXBUFSIZE                    = 0x1000000
 	BPF_MAXINSNS                      = 0x200
 	BPF_MEM                           = 0x60
 	BPF_MEMWORDS                      = 0x10
@@ -116,31 +143,151 @@ const (
 	BPF_TXA                           = 0x80
 	BPF_W                             = 0x0
 	BPF_X                             = 0x8
+	BRKINT                            = 0x2
+	CFLUSH                            = 0xf
+	CLOCAL                            = 0x8000
+	CREAD                             = 0x800
+	CS5                               = 0x0
+	CS6                               = 0x100
+	CS7                               = 0x200
+	CS8                               = 0x300
+	CSIZE                             = 0x300
+	CSTART                            = 0x11
+	CSTATUS                           = 0x14
+	CSTOP                             = 0x13
+	CSTOPB                            = 0x400
+	CSUSP                             = 0x1a
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
+	CTL_QUERY                         = -0x2
+	DIOCBSFLUSH                       = 0x20006478
+	DLT_A429                          = 0xb8
+	DLT_A653_ICM                      = 0xb9
+	DLT_AIRONET_HEADER                = 0x78
+	DLT_AOS                           = 0xde
+	DLT_APPLE_IP_OVER_IEEE1394        = 0x8a
 	DLT_ARCNET                        = 0x7
+	DLT_ARCNET_LINUX                  = 0x81
+	DLT_ATM_CLIP                      = 0x13
 	DLT_ATM_RFC1483                   = 0xb
+	DLT_AURORA                        = 0x7e
 	DLT_AX25                          = 0x3
+	DLT_AX25_KISS                     = 0xca
+	DLT_BACNET_MS_TP                  = 0xa5
+	DLT_BLUETOOTH_HCI_H4              = 0xbb
+	DLT_BLUETOOTH_HCI_H4_WITH_PHDR    = 0xc9
+	DLT_CAN20B                        = 0xbe
+	DLT_CAN_SOCKETCAN                 = 0xe3
 	DLT_CHAOS                         = 0x5
+	DLT_CISCO_IOS                     = 0x76
+	DLT_C_HDLC                        = 0x68
+	DLT_C_HDLC_WITH_DIR               = 0xcd
+	DLT_DECT                          = 0xdd
+	DLT_DOCSIS                        = 0x8f
+	DLT_ECONET                        = 0x73
 	DLT_EN10MB                        = 0x1
 	DLT_EN3MB                         = 0x2
-	DLT_ENC                           = 0xd
+	DLT_ENC                           = 0x6d
+	DLT_ERF                           = 0xc5
+	DLT_ERF_ETH                       = 0xaf
+	DLT_ERF_POS                       = 0xb0
+	DLT_FC_2                          = 0xe0
+	DLT_FC_2_WITH_FRAME_DELIMS        = 0xe1
 	DLT_FDDI                          = 0xa
+	DLT_FLEXRAY                       = 0xd2
+	DLT_FRELAY                        = 0x6b
+	DLT_FRELAY_WITH_DIR               = 0xce
+	DLT_GCOM_SERIAL                   = 0xad
+	DLT_GCOM_T1E1                     = 0xac
+	DLT_GPF_F                         = 0xab
+	DLT_GPF_T                         = 0xaa
+	DLT_GPRS_LLC                      = 0xa9
+	DLT_GSMTAP_ABIS                   = 0xda
+	DLT_GSMTAP_UM                     = 0xd9
+	DLT_HDLC                          = 0x10
+	DLT_HHDLC                         = 0x79
+	DLT_HIPPI                         = 0xf
+	DLT_IBM_SN                        = 0x92
+	DLT_IBM_SP                        = 0x91
 	DLT_IEEE802                       = 0x6
 	DLT_IEEE802_11                    = 0x69
 	DLT_IEEE802_11_RADIO              = 0x7f
-	DLT_LOOP                          = 0xc
+	DLT_IEEE802_11_RADIO_AVS          = 0xa3
+	DLT_IEEE802_15_4                  = 0xc3
+	DLT_IEEE802_15_4_LINUX            = 0xbf
+	DLT_IEEE802_15_4_NONASK_PHY       = 0xd7
+	DLT_IEEE802_16_MAC_CPS            = 0xbc
+	DLT_IEEE802_16_MAC_CPS_RADIO      = 0xc1
+	DLT_IPMB                          = 0xc7
+	DLT_IPMB_LINUX                    = 0xd1
+	DLT_IPNET                         = 0xe2
+	DLT_IPV4                          = 0xe4
+	DLT_IPV6                          = 0xe5
+	DLT_IP_OVER_FC                    = 0x7a
+	DLT_JUNIPER_ATM1                  = 0x89
+	DLT_JUNIPER_ATM2                  = 0x87
+	DLT_JUNIPER_CHDLC                 = 0xb5
+	DLT_JUNIPER_ES                    = 0x84
+	DLT_JUNIPER_ETHER                 = 0xb2
+	DLT_JUNIPER_FRELAY                = 0xb4
+	DLT_JUNIPER_GGSN                  = 0x85
+	DLT_JUNIPER_ISM                   = 0xc2
+	DLT_JUNIPER_MFR                   = 0x86
+	DLT_JUNIPER_MLFR                  = 0x83
+	DLT_JUNIPER_MLPPP                 = 0x82
+	DLT_JUNIPER_MONITOR               = 0xa4
+	DLT_JUNIPER_PIC_PEER              = 0xae
+	DLT_JUNIPER_PPP                   = 0xb3
+	DLT_JUNIPER_PPPOE                 = 0xa7
+	DLT_JUNIPER_PPPOE_ATM             = 0xa8
+	DLT_JUNIPER_SERVICES              = 0x88
+	DLT_JUNIPER_ST                    = 0xc8
+	DLT_JUNIPER_VP                    = 0xb7
+	DLT_LAPB_WITH_DIR                 = 0xcf
+	DLT_LAPD                          = 0xcb
+	DLT_LIN                           = 0xd4
+	DLT_LINUX_EVDEV                   = 0xd8
+	DLT_LINUX_IRDA                    = 0x90
+	DLT_LINUX_LAPD                    = 0xb1
+	DLT_LINUX_SLL                     = 0x71
+	DLT_LOOP                          = 0x6c
+	DLT_LTALK                         = 0x72
+	DLT_MFR                           = 0xb6
+	DLT_MOST                          = 0xd3
 	DLT_MPLS                          = 0xdb
+	DLT_MTP2                          = 0x8c
+	DLT_MTP2_WITH_PHDR                = 0x8b
+	DLT_MTP3                          = 0x8d
 	DLT_NULL                          = 0x0
+	DLT_PCI_EXP                       = 0x7d
 	DLT_PFLOG                         = 0x75
 	DLT_PFSYNC                        = 0x12
+	DLT_PPI                           = 0xc0
 	DLT_PPP                           = 0x9
-	DLT_PPP_BSDOS                     = 0x10
+	DLT_PPP_BSDOS                     = 0xe
 	DLT_PPP_ETHER                     = 0x33
+	DLT_PPP_PPPD                      = 0xa6
+	DLT_PPP_SERIAL                    = 0x32
+	DLT_PPP_WITH_DIR                  = 0xcc
+	DLT_PRISM_HEADER                  = 0x77
 	DLT_PRONET                        = 0x4
-	DLT_RAW                           = 0xe
+	DLT_RAIF1                         = 0xc6
+	DLT_RAW                           = 0xc
+	DLT_RAWAF_MASK                    = 0x2240000
+	DLT_RIO                           = 0x7c
+	DLT_SCCP                          = 0x8e
+	DLT_SITA                          = 0xc4
 	DLT_SLIP                          = 0x8
-	DLT_SLIP_BSDOS                    = 0xf
+	DLT_SLIP_BSDOS                    = 0xd
+	DLT_SUNATM                        = 0x7b
+	DLT_SYMANTEC_FIREWALL             = 0x63
+	DLT_TZSP                          = 0x80
+	DLT_USB                           = 0xba
+	DLT_USB_LINUX                     = 0xbd
+	DLT_USB_LINUX_MMAPPED             = 0xdc
+	DLT_WIHART                        = 0xdf
+	DLT_X2E_SERIAL                    = 0xd5
+	DLT_X2E_XORAYA                    = 0xd6
 	DT_BLK                            = 0x6
 	DT_CHR                            = 0x2
 	DT_DIR                            = 0x4
@@ -149,15 +296,23 @@ const (
 	DT_REG                            = 0x8
 	DT_SOCK                           = 0xc
 	DT_UNKNOWN                        = 0x0
-	EFER_LMA                          = 0x400
-	EFER_LME                          = 0x100
-	EFER_NXE                          = 0x800
-	EFER_SCE                          = 0x1
-	EMT_TAGOVF                        = 0x1
-	EMUL_ENABLED                      = 0x1
-	EMUL_NATIVE                       = 0x2
+	DT_WHT                            = 0xe
+	ECHO                              = 0x8
+	ECHOCTL                           = 0x40
+	ECHOE                             = 0x2
+	ECHOK                             = 0x4
+	ECHOKE                            = 0x1
+	ECHONL                            = 0x10
+	ECHOPRT                           = 0x20
+	EMUL_LINUX                        = 0x1
+	EMUL_LINUX32                      = 0x5
+	EMUL_MAXID                        = 0x6
+	ETHERCAP_JUMBO_MTU                = 0x4
+	ETHERCAP_VLAN_HWTAGGING           = 0x2
+	ETHERCAP_VLAN_MTU                 = 0x1
 	ETHERMIN                          = 0x2e
 	ETHERMTU                          = 0x5dc
+	ETHERMTU_JUMBO                    = 0x2328
 	ETHERTYPE_8023                    = 0x4
 	ETHERTYPE_AARP                    = 0x80f3
 	ETHERTYPE_ACCTON                  = 0x8390
@@ -165,7 +320,6 @@ const (
 	ETHERTYPE_ALPHA                   = 0x814a
 	ETHERTYPE_AMBER                   = 0x6008
 	ETHERTYPE_AMOEBA                  = 0x8145
-	ETHERTYPE_AOE                     = 0x88a2
 	ETHERTYPE_APOLLO                  = 0x80f7
 	ETHERTYPE_APOLLODOMAIN            = 0x8019
 	ETHERTYPE_APPLETALK               = 0x809b
@@ -236,7 +390,6 @@ const (
 	ETHERTYPE_LAT                     = 0x6004
 	ETHERTYPE_LBACK                   = 0x9000
 	ETHERTYPE_LITTLE                  = 0x8060
-	ETHERTYPE_LLDP                    = 0x88cc
 	ETHERTYPE_LOGICRAFT               = 0x8148
 	ETHERTYPE_LOOPBACK                = 0x9000
 	ETHERTYPE_MATRA                   = 0x807a
@@ -284,7 +437,6 @@ const (
 	ETHERTYPE_PRIMENTS                = 0x7031
 	ETHERTYPE_PUP                     = 0x200
 	ETHERTYPE_PUPAT                   = 0x200
-	ETHERTYPE_QINQ                    = 0x88a8
 	ETHERTYPE_RACAL                   = 0x7030
 	ETHERTYPE_RATIONAL                = 0x8150
 	ETHERTYPE_RAWFR                   = 0x6559
@@ -301,7 +453,7 @@ const (
 	ETHERTYPE_SG_NETGAMES             = 0x8014
 	ETHERTYPE_SG_RESV                 = 0x8015
 	ETHERTYPE_SIMNET                  = 0x5208
-	ETHERTYPE_SLOW                    = 0x8809
+	ETHERTYPE_SLOWPROTOCOLS           = 0x8809
 	ETHERTYPE_SNA                     = 0x80d5
 	ETHERTYPE_SNMP                    = 0x814c
 	ETHERTYPE_SONIX                   = 0xfaf5
@@ -344,24 +496,24 @@ const (
 	ETHERTYPE_XNSSM                   = 0x9001
 	ETHERTYPE_XTP                     = 0x817d
 	ETHER_ADDR_LEN                    = 0x6
-	ETHER_ALIGN                       = 0x2
 	ETHER_CRC_LEN                     = 0x4
 	ETHER_CRC_POLY_BE                 = 0x4c11db6
 	ETHER_CRC_POLY_LE                 = 0xedb88320
 	ETHER_HDR_LEN                     = 0xe
-	ETHER_MAX_DIX_LEN                 = 0x600
 	ETHER_MAX_LEN                     = 0x5ee
+	ETHER_MAX_LEN_JUMBO               = 0x233a
 	ETHER_MIN_LEN                     = 0x40
+	ETHER_PPPOE_ENCAP_LEN             = 0x8
 	ETHER_TYPE_LEN                    = 0x2
 	ETHER_VLAN_ENCAP_LEN              = 0x4
-	EVFILT_AIO                        = -0x3
-	EVFILT_PROC                       = -0x5
-	EVFILT_READ                       = -0x1
-	EVFILT_SIGNAL                     = -0x6
+	EVFILT_AIO                        = 0x2
+	EVFILT_PROC                       = 0x4
+	EVFILT_READ                       = 0x0
+	EVFILT_SIGNAL                     = 0x5
 	EVFILT_SYSCOUNT                   = 0x7
-	EVFILT_TIMER                      = -0x7
-	EVFILT_VNODE                      = -0x4
-	EVFILT_WRITE                      = -0x2
+	EVFILT_TIMER                      = 0x6
+	EVFILT_VNODE                      = 0x3
+	EVFILT_WRITE                      = 0x1
 	EV_ADD                            = 0x1
 	EV_CLEAR                          = 0x20
 	EV_DELETE                         = 0x2
@@ -376,25 +528,46 @@ const (
 	EXTB                              = 0x9600
 	EXTPROC                           = 0x800
 	FD_CLOEXEC                        = 0x1
-	FD_SETSIZE                        = 0x400
+	FD_SETSIZE                        = 0x100
+	FLUSHO                            = 0x800000
+	F_CLOSEM                          = 0xa
 	F_DUPFD                           = 0x0
-	F_DUPFD_CLOEXEC                   = 0xa
+	F_DUPFD_CLOEXEC                   = 0xc
+	F_FSCTL                           = -0x80000000
+	F_FSDIRMASK                       = 0x70000000
+	F_FSIN                            = 0x10000000
+	F_FSINOUT                         = 0x30000000
+	F_FSOUT                           = 0x20000000
+	F_FSPRIV                          = 0x8000
+	F_FSVOID                          = 0x40000000
 	F_GETFD                           = 0x1
 	F_GETFL                           = 0x3
 	F_GETLK                           = 0x7
+	F_GETNOSIGPIPE                    = 0xd
 	F_GETOWN                          = 0x5
+	F_MAXFD                           = 0xb
+	F_OK                              = 0x0
+	F_PARAM_MASK                      = 0xfff
+	F_PARAM_MAX                       = 0xfff
 	F_RDLCK                           = 0x1
 	F_SETFD                           = 0x2
 	F_SETFL                           = 0x4
 	F_SETLK                           = 0x8
 	F_SETLKW                          = 0x9
+	F_SETNOSIGPIPE                    = 0xe
 	F_SETOWN                          = 0x6
 	F_UNLCK                           = 0x2
 	F_WRLCK                           = 0x3
+	HUPCL                             = 0x4000
+	ICANON                            = 0x100
+	ICRNL                             = 0x100
+	IEXTEN                            = 0x400
+	IFAN_ARRIVAL                      = 0x0
+	IFAN_DEPARTURE                    = 0x1
 	IFA_ROUTE                         = 0x1
 	IFF_ALLMULTI                      = 0x200
 	IFF_BROADCAST                     = 0x2
-	IFF_CANTCHANGE                    = 0x8e52
+	IFF_CANTCHANGE                    = 0x8f52
 	IFF_DEBUG                         = 0x4
 	IFF_LINK0                         = 0x1000
 	IFF_LINK1                         = 0x2000
@@ -431,10 +604,9 @@ const (
 	IFT_ATMVCIENDPT                   = 0xc2
 	IFT_ATMVIRTUAL                    = 0x95
 	IFT_BGPPOLICYACCOUNTING           = 0xa2
-	IFT_BLUETOOTH                     = 0xf8
 	IFT_BRIDGE                        = 0xd1
 	IFT_BSC                           = 0x53
-	IFT_CARP                          = 0xf7
+	IFT_CARP                          = 0xf8
 	IFT_CCTEMUL                       = 0x3d
 	IFT_CEPT                          = 0x13
 	IFT_CES                           = 0x85
@@ -455,19 +627,17 @@ const (
 	IFT_DS1FDL                        = 0xaa
 	IFT_DS3                           = 0x1e
 	IFT_DTM                           = 0x8c
-	IFT_DUMMY                         = 0xf1
 	IFT_DVBASILN                      = 0xac
 	IFT_DVBASIOUT                     = 0xad
 	IFT_DVBRCCDOWNSTREAM              = 0x93
 	IFT_DVBRCCMACLAYER                = 0x92
 	IFT_DVBRCCUPSTREAM                = 0x94
 	IFT_ECONET                        = 0xce
-	IFT_ENC                           = 0xf4
 	IFT_EON                           = 0x19
 	IFT_EPLRS                         = 0x57
 	IFT_ESCON                         = 0x49
 	IFT_ETHER                         = 0x6
-	IFT_FAITH                         = 0xf3
+	IFT_FAITH                         = 0xf2
 	IFT_FAST                          = 0x7d
 	IFT_FASTETHER                     = 0x3e
 	IFT_FASTETHERFX                   = 0x45
@@ -555,7 +725,6 @@ const (
 	IFT_P80                           = 0xd
 	IFT_PARA                          = 0x22
 	IFT_PFLOG                         = 0xf5
-	IFT_PFLOW                         = 0xf9
 	IFT_PFSYNC                        = 0xf6
 	IFT_PLC                           = 0xae
 	IFT_PON155                        = 0xcf
@@ -573,7 +742,7 @@ const (
 	IFT_PROPVIRTUAL                   = 0x35
 	IFT_PROPWIRELESSP2P               = 0x9d
 	IFT_PTPSERIAL                     = 0x16
-	IFT_PVC                           = 0xf2
+	IFT_PVC                           = 0xf1
 	IFT_Q2931                         = 0xc9
 	IFT_QLLC                          = 0x44
 	IFT_RADIOMAC                      = 0xbc
@@ -599,6 +768,7 @@ const (
 	IFT_SS7SIGLINK                    = 0x9c
 	IFT_STACKTOSTACK                  = 0x6f
 	IFT_STARLAN                       = 0xb
+	IFT_STF                           = 0xd7
 	IFT_T1                            = 0x12
 	IFT_TDLC                          = 0x74
 	IFT_TELINK                        = 0xc8
@@ -633,6 +803,12 @@ const (
 	IFT_X25MLP                        = 0x79
 	IFT_X25PLE                        = 0x28
 	IFT_XETHER                        = 0x1a
+	IGNBRK                            = 0x1
+	IGNCR                             = 0x80
+	IGNPAR                            = 0x4
+	IMAXBEL                           = 0x2000
+	INLCR                             = 0x40
+	INPCK                             = 0x10
 	IN_CLASSA_HOST                    = 0xffffff
 	IN_CLASSA_MAX                     = 0x80
 	IN_CLASSA_NET                     = 0xff000000
@@ -648,12 +824,8 @@ const (
 	IN_CLASSD_NET                     = 0xf0000000
 	IN_CLASSD_NSHIFT                  = 0x1c
 	IN_LOOPBACKNET                    = 0x7f
-	IN_RFC3021_HOST                   = 0x1
-	IN_RFC3021_NET                    = 0xfffffffe
-	IN_RFC3021_NSHIFT                 = 0x1f
 	IPPROTO_AH                        = 0x33
 	IPPROTO_CARP                      = 0x70
-	IPPROTO_DIVERT                    = 0x102
 	IPPROTO_DONE                      = 0x101
 	IPPROTO_DSTOPTS                   = 0x3c
 	IPPROTO_EGP                       = 0x8
@@ -674,10 +846,10 @@ const (
 	IPPROTO_IPIP                      = 0x4
 	IPPROTO_IPV4                      = 0x4
 	IPPROTO_IPV6                      = 0x29
+	IPPROTO_IPV6_ICMP                 = 0x3a
 	IPPROTO_MAX                       = 0x100
-	IPPROTO_MAXID                     = 0x103
+	IPPROTO_MAXID                     = 0x34
 	IPPROTO_MOBILE                    = 0x37
-	IPPROTO_MPLS                      = 0x89
 	IPPROTO_NONE                      = 0x3b
 	IPPROTO_PFSYNC                    = 0xf0
 	IPPROTO_PIM                       = 0x67
@@ -688,16 +860,13 @@ const (
 	IPPROTO_TCP                       = 0x6
 	IPPROTO_TP                        = 0x1d
 	IPPROTO_UDP                       = 0x11
-	IPV6_AUTH_LEVEL                   = 0x35
-	IPV6_AUTOFLOWLABEL                = 0x3b
+	IPPROTO_VRRP                      = 0x70
 	IPV6_CHECKSUM                     = 0x1a
 	IPV6_DEFAULT_MULTICAST_HOPS       = 0x1
 	IPV6_DEFAULT_MULTICAST_LOOP       = 0x1
 	IPV6_DEFHLIM                      = 0x40
 	IPV6_DONTFRAG                     = 0x3e
 	IPV6_DSTOPTS                      = 0x32
-	IPV6_ESP_NETWORK_LEVEL            = 0x37
-	IPV6_ESP_TRANS_LEVEL              = 0x36
 	IPV6_FAITH                        = 0x1d
 	IPV6_FLOWINFO_MASK                = 0xffffff0f
 	IPV6_FLOWLABEL_MASK               = 0xffff0f00
@@ -705,7 +874,7 @@ const (
 	IPV6_HLIMDEC                      = 0x1
 	IPV6_HOPLIMIT                     = 0x2f
 	IPV6_HOPOPTS                      = 0x31
-	IPV6_IPCOMP_LEVEL                 = 0x3c
+	IPV6_IPSEC_POLICY                 = 0x1c
 	IPV6_JOIN_GROUP                   = 0xc
 	IPV6_LEAVE_GROUP                  = 0xd
 	IPV6_MAXHLIM                      = 0xff
@@ -715,9 +884,7 @@ const (
 	IPV6_MULTICAST_IF                 = 0x9
 	IPV6_MULTICAST_LOOP               = 0xb
 	IPV6_NEXTHOP                      = 0x30
-	IPV6_OPTIONS                      = 0x1
 	IPV6_PATHMTU                      = 0x2c
-	IPV6_PIPEX                        = 0x3f
 	IPV6_PKTINFO                      = 0x2e
 	IPV6_PORTRANGE                    = 0xe
 	IPV6_PORTRANGE_DEFAULT            = 0x0
@@ -730,7 +897,6 @@ const (
 	IPV6_RECVPKTINFO                  = 0x24
 	IPV6_RECVRTHDR                    = 0x26
 	IPV6_RECVTCLASS                   = 0x39
-	IPV6_RTABLE                       = 0x1021
 	IPV6_RTHDR                        = 0x33
 	IPV6_RTHDRDSTOPTS                 = 0x23
 	IPV6_RTHDR_LOOSE                  = 0x0
@@ -744,74 +910,105 @@ const (
 	IPV6_VERSION                      = 0x60
 	IPV6_VERSION_MASK                 = 0xf0
 	IP_ADD_MEMBERSHIP                 = 0xc
-	IP_AUTH_LEVEL                     = 0x14
 	IP_DEFAULT_MULTICAST_LOOP         = 0x1
 	IP_DEFAULT_MULTICAST_TTL          = 0x1
 	IP_DF                             = 0x4000
 	IP_DROP_MEMBERSHIP                = 0xd
-	IP_ESP_NETWORK_LEVEL              = 0x16
-	IP_ESP_TRANS_LEVEL                = 0x15
+	IP_EF                             = 0x8000
+	IP_ERRORMTU                       = 0x15
 	IP_HDRINCL                        = 0x2
-	IP_IPCOMP_LEVEL                   = 0x1d
-	IP_IPSEC_LOCAL_AUTH               = 0x1b
-	IP_IPSEC_LOCAL_CRED               = 0x19
-	IP_IPSEC_LOCAL_ID                 = 0x17
-	IP_IPSEC_REMOTE_AUTH              = 0x1c
-	IP_IPSEC_REMOTE_CRED              = 0x1a
-	IP_IPSEC_REMOTE_ID                = 0x18
+	IP_IPSEC_POLICY                   = 0x16
 	IP_MAXPACKET                      = 0xffff
-	IP_MAX_MEMBERSHIPS                = 0xfff
+	IP_MAX_MEMBERSHIPS                = 0x14
 	IP_MF                             = 0x2000
-	IP_MINTTL                         = 0x20
-	IP_MIN_MEMBERSHIPS                = 0xf
+	IP_MINFRAGSIZE                    = 0x45
+	IP_MINTTL                         = 0x18
 	IP_MSS                            = 0x240
 	IP_MULTICAST_IF                   = 0x9
 	IP_MULTICAST_LOOP                 = 0xb
 	IP_MULTICAST_TTL                  = 0xa
 	IP_OFFMASK                        = 0x1fff
 	IP_OPTIONS                        = 0x1
-	IP_PIPEX                          = 0x22
 	IP_PORTRANGE                      = 0x13
 	IP_PORTRANGE_DEFAULT              = 0x0
 	IP_PORTRANGE_HIGH                 = 0x1
 	IP_PORTRANGE_LOW                  = 0x2
 	IP_RECVDSTADDR                    = 0x7
-	IP_RECVDSTPORT                    = 0x21
-	IP_RECVIF                         = 0x1e
+	IP_RECVIF                         = 0x14
 	IP_RECVOPTS                       = 0x5
 	IP_RECVRETOPTS                    = 0x6
-	IP_RECVRTABLE                     = 0x23
-	IP_RECVTTL                        = 0x1f
+	IP_RECVTTL                        = 0x17
 	IP_RETOPTS                        = 0x8
 	IP_RF                             = 0x8000
-	IP_RTABLE                         = 0x1021
 	IP_TOS                            = 0x3
 	IP_TTL                            = 0x4
-	MAP_ET_KVAGUARD                   = 0x10
+	ISIG                              = 0x80
+	ISTRIP                            = 0x20
+	IXANY                             = 0x800
+	IXOFF                             = 0x400
+	IXON                              = 0x200
+	LOCK_EX                           = 0x2
+	LOCK_NB                           = 0x4
+	LOCK_SH                           = 0x1
+	LOCK_UN                           = 0x8
 	MSG_BCAST                         = 0x100
+	MSG_CMSG_CLOEXEC                  = 0x800
+	MSG_CONTROLMBUF                   = 0x2000000
 	MSG_CTRUNC                        = 0x20
 	MSG_DONTROUTE                     = 0x4
 	MSG_DONTWAIT                      = 0x80
 	MSG_EOR                           = 0x8
+	MSG_IOVUSRSPACE                   = 0x4000000
+	MSG_LENUSRSPACE                   = 0x8000000
 	MSG_MCAST                         = 0x200
+	MSG_NAMEMBUF                      = 0x1000000
+	MSG_NBIO                          = 0x1000
+	MSG_NOSIGNAL                      = 0x400
 	MSG_OOB                           = 0x1
 	MSG_PEEK                          = 0x2
 	MSG_TRUNC                         = 0x10
+	MSG_USERFLAGS                     = 0xffffff
 	MSG_WAITALL                       = 0x40
-	NAME_MAX                          = 0xff
+	NAME_MAX                          = 0x1ff
 	NET_RT_DUMP                       = 0x1
 	NET_RT_FLAGS                      = 0x2
-	NET_RT_IFLIST                     = 0x3
+	NET_RT_IFLIST                     = 0x5
 	NET_RT_MAXID                      = 0x6
-	NET_RT_STATS                      = 0x4
-	NET_RT_TABLE                      = 0x5
+	NET_RT_OIFLIST                    = 0x4
+	NET_RT_OOIFLIST                   = 0x3
+	NOFLSH                            = 0x80000000
+	NOTE_ATTRIB                       = 0x8
+	NOTE_CHILD                        = 0x4
+	NOTE_DELETE                       = 0x1
+	NOTE_EXEC                         = 0x20000000
+	NOTE_EXIT                         = 0x80000000
+	NOTE_EXTEND                       = 0x4
+	NOTE_FORK                         = 0x40000000
+	NOTE_LINK                         = 0x10
+	NOTE_LOWAT                        = 0x1
+	NOTE_PCTRLMASK                    = 0xf0000000
+	NOTE_PDATAMASK                    = 0xfffff
+	NOTE_RENAME                       = 0x20
+	NOTE_REVOKE                       = 0x40
+	NOTE_TRACK                        = 0x1
+	NOTE_TRACKERR                     = 0x2
+	NOTE_WRITE                        = 0x2
+	OCRNL                             = 0x10
+	OFIOGETBMAP                       = 0xc004667a
+	ONLCR                             = 0x2
+	ONLRET                            = 0x40
+	ONOCR                             = 0x20
+	ONOEOT                            = 0x8
+	OPOST                             = 0x1
 	O_ACCMODE                         = 0x3
+	O_ALT_IO                          = 0x40000
 	O_APPEND                          = 0x8
 	O_ASYNC                           = 0x40
-	O_CLOEXEC                         = 0x10000
+	O_CLOEXEC                         = 0x400000
 	O_CREAT                           = 0x200
-	O_DIRECTORY                       = 0x20000
-	O_DSYNC                           = 0x80
+	O_DIRECT                          = 0x80000
+	O_DIRECTORY                       = 0x200000
+	O_DSYNC                           = 0x10000
 	O_EXCL                            = 0x800
 	O_EXLOCK                          = 0x20
 	O_FSYNC                           = 0x80
@@ -819,13 +1016,27 @@ const (
 	O_NOCTTY                          = 0x8000
 	O_NOFOLLOW                        = 0x100
 	O_NONBLOCK                        = 0x4
+	O_NOSIGPIPE                       = 0x1000000
 	O_RDONLY                          = 0x0
 	O_RDWR                            = 0x2
-	O_RSYNC                           = 0x80
+	O_RSYNC                           = 0x20000
 	O_SHLOCK                          = 0x10
 	O_SYNC                            = 0x80
 	O_TRUNC                           = 0x400
 	O_WRONLY                          = 0x1
+	PARENB                            = 0x1000
+	PARMRK                            = 0x8
+	PARODD                            = 0x2000
+	PENDIN                            = 0x20000000
+	PRI_IOFLUSH                       = 0x7c
+	RLIMIT_AS                         = 0xa
+	RLIMIT_CORE                       = 0x4
+	RLIMIT_CPU                        = 0x0
+	RLIMIT_DATA                       = 0x2
+	RLIMIT_FSIZE                      = 0x1
+	RLIMIT_NOFILE                     = 0x8
+	RLIMIT_STACK                      = 0x3
+	RLIM_INFINITY                     = 0x7fffffffffffffff
 	RTAX_AUTHOR                       = 0x6
 	RTAX_BRD                          = 0x7
 	RTAX_DST                          = 0x0
@@ -833,11 +1044,9 @@ const (
 	RTAX_GENMASK                      = 0x3
 	RTAX_IFA                          = 0x5
 	RTAX_IFP                          = 0x4
-	RTAX_LABEL                        = 0xa
-	RTAX_MAX                          = 0xb
+	RTAX_MAX                          = 0x9
 	RTAX_NETMASK                      = 0x2
-	RTAX_SRC                          = 0x8
-	RTAX_SRCMASK                      = 0x9
+	RTAX_TAG                          = 0x8
 	RTA_AUTHOR                        = 0x40
 	RTA_BRD                           = 0x80
 	RTA_DST                           = 0x1
@@ -845,52 +1054,48 @@ const (
 	RTA_GENMASK                       = 0x8
 	RTA_IFA                           = 0x20
 	RTA_IFP                           = 0x10
-	RTA_LABEL                         = 0x400
 	RTA_NETMASK                       = 0x4
-	RTA_SRC                           = 0x100
-	RTA_SRCMASK                       = 0x200
-	RTF_ANNOUNCE                      = 0x4000
+	RTA_TAG                           = 0x100
+	RTF_ANNOUNCE                      = 0x20000
 	RTF_BLACKHOLE                     = 0x1000
-	RTF_CLONED                        = 0x10000
+	RTF_CLONED                        = 0x2000
 	RTF_CLONING                       = 0x100
 	RTF_DONE                          = 0x40
 	RTF_DYNAMIC                       = 0x10
-	RTF_FMASK                         = 0x8f808
 	RTF_GATEWAY                       = 0x2
 	RTF_HOST                          = 0x4
-	RTF_JUMBO                         = 0x80000
 	RTF_LLINFO                        = 0x400
 	RTF_MASK                          = 0x80
 	RTF_MODIFIED                      = 0x20
-	RTF_MPATH                         = 0x40000
-	RTF_MPLS                          = 0x100000
-	RTF_PERMANENT_ARP                 = 0x2000
 	RTF_PROTO1                        = 0x8000
 	RTF_PROTO2                        = 0x4000
-	RTF_PROTO3                        = 0x2000
 	RTF_REJECT                        = 0x8
-	RTF_SOURCE                        = 0x20000
+	RTF_SRC                           = 0x10000
 	RTF_STATIC                        = 0x800
-	RTF_TUNNEL                        = 0x100000
 	RTF_UP                            = 0x1
-	RTF_USETRAILERS                   = 0x8000
 	RTF_XRESOLVE                      = 0x200
 	RTM_ADD                           = 0x1
 	RTM_CHANGE                        = 0x3
+	RTM_CHGADDR                       = 0x15
 	RTM_DELADDR                       = 0xd
 	RTM_DELETE                        = 0x2
-	RTM_DESYNC                        = 0x10
 	RTM_GET                           = 0x4
-	RTM_IFANNOUNCE                    = 0xf
-	RTM_IFINFO                        = 0xe
+	RTM_IEEE80211                     = 0x11
+	RTM_IFANNOUNCE                    = 0x10
+	RTM_IFINFO                        = 0x14
+	RTM_LLINFO_UPD                    = 0x13
 	RTM_LOCK                          = 0x8
 	RTM_LOSING                        = 0x5
-	RTM_MAXSIZE                       = 0x800
 	RTM_MISS                          = 0x7
 	RTM_NEWADDR                       = 0xc
+	RTM_OIFINFO                       = 0xf
+	RTM_OLDADD                        = 0x9
+	RTM_OLDDEL                        = 0xa
+	RTM_OOIFINFO                      = 0xe
 	RTM_REDIRECT                      = 0x6
 	RTM_RESOLVE                       = 0xb
 	RTM_RTTUNIT                       = 0xf4240
+	RTM_SETGATE                       = 0x12
 	RTM_VERSION                       = 0x4
 	RTV_EXPIRE                        = 0x4
 	RTV_HOPCOUNT                      = 0x2
@@ -900,159 +1105,82 @@ const (
 	RTV_RTTVAR                        = 0x80
 	RTV_SPIPE                         = 0x10
 	RTV_SSTHRESH                      = 0x20
-	RT_TABLEID_MAX                    = 0xff
-	SCM_CREDS                         = 0x2
+	RUSAGE_CHILDREN                   = -0x1
+	RUSAGE_SELF                       = 0x0
+	SCM_CREDS                         = 0x4
 	SCM_RIGHTS                        = 0x1
-	SCM_TIMESTAMP                     = 0x4
+	SCM_TIMESTAMP                     = 0x8
 	SHUT_RD                           = 0x0
 	SHUT_RDWR                         = 0x2
 	SHUT_WR                           = 0x1
-	SIGABRT                           = 0x6
-	SIGALRM                           = 0xe
-	SIGBUS                            = 0xa
-	SIGCHLD                           = 0x14
-	SIGCONT                           = 0x13
-	SIGEMT                            = 0x7
-	SIGFPE                            = 0x8
-	SIGHUP                            = 0x1
-	SIGILL                            = 0x4
-	SIGINFO                           = 0x1d
-	SIGINT                            = 0x2
-	SIGIO                             = 0x17
-	SIGIOT                            = 0x6
-	SIGKILL                           = 0x9
-	SIGPIPE                           = 0xd
-	SIGPROF                           = 0x1b
-	SIGQUIT                           = 0x3
-	SIGSEGV                           = 0xb
-	SIGSTOP                           = 0x11
-	SIGSYS                            = 0xc
-	SIGTERM                           = 0xf
-	SIGTHR                            = 0x20
-	SIGTRAP                           = 0x5
-	SIGTSTP                           = 0x12
-	SIGTTIN                           = 0x15
-	SIGTTOU                           = 0x16
-	SIGURG                            = 0x10
-	SIGUSR1                           = 0x1e
-	SIGUSR2                           = 0x1f
-	SIGVTALRM                         = 0x1a
-	SIGWINCH                          = 0x1c
-	SIGXCPU                           = 0x18
-	SIGXFSZ                           = 0x19
-	SIOCADDMULTI                      = 0x80206931
+	SIOCADDMULTI                      = 0x80906931
+	SIOCADDRT                         = 0x8038720a
 	SIOCAIFADDR                       = 0x8040691a
-	SIOCAIFGROUP                      = 0x80286987
-	SIOCALIFADDR                      = 0x8218691c
+	SIOCALIFADDR                      = 0x8118691c
 	SIOCATMARK                        = 0x40047307
-	SIOCBRDGADD                       = 0x8058693c
-	SIOCBRDGADDS                      = 0x80586941
-	SIOCBRDGARL                       = 0x806e694d
-	SIOCBRDGDADDR                     = 0x80286947
-	SIOCBRDGDEL                       = 0x8058693d
-	SIOCBRDGDELS                      = 0x80586942
-	SIOCBRDGFLUSH                     = 0x80586948
-	SIOCBRDGFRL                       = 0x806e694e
-	SIOCBRDGGCACHE                    = 0xc0146941
-	SIOCBRDGGFD                       = 0xc0146952
-	SIOCBRDGGHT                       = 0xc0146951
-	SIOCBRDGGIFFLGS                   = 0xc058693e
-	SIOCBRDGGMA                       = 0xc0146953
-	SIOCBRDGGPARAM                    = 0xc0406958
-	SIOCBRDGGPRI                      = 0xc0146950
-	SIOCBRDGGRL                       = 0xc030694f
-	SIOCBRDGGSIFS                     = 0xc058693c
-	SIOCBRDGGTO                       = 0xc0146946
-	SIOCBRDGIFS                       = 0xc0586942
-	SIOCBRDGRTS                       = 0xc0206943
-	SIOCBRDGSADDR                     = 0xc0286944
-	SIOCBRDGSCACHE                    = 0x80146940
-	SIOCBRDGSFD                       = 0x80146952
-	SIOCBRDGSHT                       = 0x80146951
-	SIOCBRDGSIFCOST                   = 0x80586955
-	SIOCBRDGSIFFLGS                   = 0x8058693f
-	SIOCBRDGSIFPRIO                   = 0x80586954
-	SIOCBRDGSMA                       = 0x80146953
-	SIOCBRDGSPRI                      = 0x80146950
-	SIOCBRDGSPROTO                    = 0x8014695a
-	SIOCBRDGSTO                       = 0x80146945
-	SIOCBRDGSTXHC                     = 0x80146959
-	SIOCDELMULTI                      = 0x80206932
-	SIOCDIFADDR                       = 0x80206919
-	SIOCDIFGROUP                      = 0x80286989
-	SIOCDIFPHYADDR                    = 0x80206949
-	SIOCDLIFADDR                      = 0x8218691e
-	SIOCGETKALIVE                     = 0xc01869a4
-	SIOCGETLABEL                      = 0x8020699a
-	SIOCGETPFLOW                      = 0xc02069fe
-	SIOCGETPFSYNC                     = 0xc02069f8
+	SIOCDELMULTI                      = 0x80906932
+	SIOCDELRT                         = 0x8038720b
+	SIOCDIFADDR                       = 0x80906919
+	SIOCDIFPHYADDR                    = 0x80906949
+	SIOCDLIFADDR                      = 0x8118691e
+	SIOCGDRVSPEC                      = 0xc028697b
+	SIOCGETPFSYNC                     = 0xc09069f8
 	SIOCGETSGCNT                      = 0xc0207534
 	SIOCGETVIFCNT                     = 0xc0287533
-	SIOCGETVLANPRIO                   = 0xc0206990
 	SIOCGHIWAT                        = 0x40047301
-	SIOCGIFADDR                       = 0xc0206921
-	SIOCGIFASYNCMAP                   = 0xc020697c
-	SIOCGIFBRDADDR                    = 0xc0206923
-	SIOCGIFCONF                       = 0xc0106924
-	SIOCGIFDATA                       = 0xc020691b
-	SIOCGIFDESCR                      = 0xc0206981
-	SIOCGIFDSTADDR                    = 0xc0206922
-	SIOCGIFFLAGS                      = 0xc0206911
-	SIOCGIFGATTR                      = 0xc028698b
-	SIOCGIFGENERIC                    = 0xc020693a
-	SIOCGIFGMEMB                      = 0xc028698a
-	SIOCGIFGROUP                      = 0xc0286988
+	SIOCGIFADDR                       = 0xc0906921
+	SIOCGIFADDRPREF                   = 0xc0986920
+	SIOCGIFALIAS                      = 0xc040691b
+	SIOCGIFBRDADDR                    = 0xc0906923
+	SIOCGIFCAP                        = 0xc0206976
+	SIOCGIFCONF                       = 0xc0106926
+	SIOCGIFDATA                       = 0xc0986985
+	SIOCGIFDLT                        = 0xc0906977
+	SIOCGIFDSTADDR                    = 0xc0906922
+	SIOCGIFFLAGS                      = 0xc0906911
+	SIOCGIFGENERIC                    = 0xc090693a
 	SIOCGIFMEDIA                      = 0xc0306936
-	SIOCGIFMETRIC                     = 0xc0206917
-	SIOCGIFMTU                        = 0xc020697e
-	SIOCGIFNETMASK                    = 0xc0206925
-	SIOCGIFPDSTADDR                   = 0xc0206948
-	SIOCGIFPRIORITY                   = 0xc020699c
-	SIOCGIFPSRCADDR                   = 0xc0206947
-	SIOCGIFRDOMAIN                    = 0xc02069a0
-	SIOCGIFRTLABEL                    = 0xc0206983
-	SIOCGIFTIMESLOT                   = 0xc0206986
-	SIOCGIFXFLAGS                     = 0xc020699e
-	SIOCGLIFADDR                      = 0xc218691d
-	SIOCGLIFPHYADDR                   = 0xc218694b
-	SIOCGLIFPHYRTABLE                 = 0xc02069a2
+	SIOCGIFMETRIC                     = 0xc0906917
+	SIOCGIFMTU                        = 0xc090697e
+	SIOCGIFNETMASK                    = 0xc0906925
+	SIOCGIFPDSTADDR                   = 0xc0906948
+	SIOCGIFPSRCADDR                   = 0xc0906947
+	SIOCGLIFADDR                      = 0xc118691d
+	SIOCGLIFPHYADDR                   = 0xc118694b
+	SIOCGLINKSTR                      = 0xc0286987
 	SIOCGLOWAT                        = 0x40047303
 	SIOCGPGRP                         = 0x40047309
-	SIOCGVH                           = 0xc02069f6
-	SIOCIFCREATE                      = 0x8020697a
-	SIOCIFDESTROY                     = 0x80206979
+	SIOCGVH                           = 0xc0906983
+	SIOCIFCREATE                      = 0x8090697a
+	SIOCIFDESTROY                     = 0x80906979
 	SIOCIFGCLONERS                    = 0xc0106978
-	SIOCSETKALIVE                     = 0x801869a3
-	SIOCSETLABEL                      = 0x80206999
-	SIOCSETPFLOW                      = 0x802069fd
-	SIOCSETPFSYNC                     = 0x802069f7
-	SIOCSETVLANPRIO                   = 0x8020698f
+	SIOCINITIFADDR                    = 0xc0706984
+	SIOCSDRVSPEC                      = 0x8028697b
+	SIOCSETPFSYNC                     = 0x809069f7
 	SIOCSHIWAT                        = 0x80047300
-	SIOCSIFADDR                       = 0x8020690c
-	SIOCSIFASYNCMAP                   = 0x8020697d
-	SIOCSIFBRDADDR                    = 0x80206913
-	SIOCSIFDESCR                      = 0x80206980
-	SIOCSIFDSTADDR                    = 0x8020690e
-	SIOCSIFFLAGS                      = 0x80206910
-	SIOCSIFGATTR                      = 0x8028698c
-	SIOCSIFGENERIC                    = 0x80206939
-	SIOCSIFLLADDR                     = 0x8020691f
-	SIOCSIFMEDIA                      = 0xc0206935
-	SIOCSIFMETRIC                     = 0x80206918
-	SIOCSIFMTU                        = 0x8020697f
-	SIOCSIFNETMASK                    = 0x80206916
+	SIOCSIFADDR                       = 0x8090690c
+	SIOCSIFADDRPREF                   = 0x8098691f
+	SIOCSIFBRDADDR                    = 0x80906913
+	SIOCSIFCAP                        = 0x80206975
+	SIOCSIFDSTADDR                    = 0x8090690e
+	SIOCSIFFLAGS                      = 0x80906910
+	SIOCSIFGENERIC                    = 0x80906939
+	SIOCSIFMEDIA                      = 0xc0906935
+	SIOCSIFMETRIC                     = 0x80906918
+	SIOCSIFMTU                        = 0x8090697f
+	SIOCSIFNETMASK                    = 0x80906916
 	SIOCSIFPHYADDR                    = 0x80406946
-	SIOCSIFPRIORITY                   = 0x8020699b
-	SIOCSIFRDOMAIN                    = 0x8020699f
-	SIOCSIFRTLABEL                    = 0x80206982
-	SIOCSIFTIMESLOT                   = 0x80206985
-	SIOCSIFXFLAGS                     = 0x8020699d
-	SIOCSLIFPHYADDR                   = 0x8218694a
-	SIOCSLIFPHYRTABLE                 = 0x802069a1
+	SIOCSLIFPHYADDR                   = 0x8118694a
+	SIOCSLINKSTR                      = 0x80286988
 	SIOCSLOWAT                        = 0x80047302
 	SIOCSPGRP                         = 0x80047308
-	SIOCSVH                           = 0xc02069f5
+	SIOCSVH                           = 0xc0906982
+	SIOCZIFDATA                       = 0xc0986986
+	SOCK_CLOEXEC                      = 0x10000000
 	SOCK_DGRAM                        = 0x2
+	SOCK_FLAGS_MASK                   = 0xf0000000
+	SOCK_NONBLOCK                     = 0x20000000
+	SOCK_NOSIGPIPE                    = 0x40000000
 	SOCK_RAW                          = 0x3
 	SOCK_RDM                          = 0x4
 	SOCK_SEQPACKET                    = 0x5
@@ -1060,63 +1188,107 @@ const (
 	SOL_SOCKET                        = 0xffff
 	SOMAXCONN                         = 0x80
 	SO_ACCEPTCONN                     = 0x2
-	SO_BINDANY                        = 0x1000
+	SO_ACCEPTFILTER                   = 0x1000
 	SO_BROADCAST                      = 0x20
 	SO_DEBUG                          = 0x1
 	SO_DONTROUTE                      = 0x10
 	SO_ERROR                          = 0x1007
-	SO_JUMBO                          = 0x400
 	SO_KEEPALIVE                      = 0x8
 	SO_LINGER                         = 0x80
-	SO_NETPROC                        = 0x1020
+	SO_NOHEADER                       = 0x100a
+	SO_NOSIGPIPE                      = 0x800
 	SO_OOBINLINE                      = 0x100
-	SO_PEERCRED                       = 0x1022
+	SO_OVERFLOWED                     = 0x1009
 	SO_RCVBUF                         = 0x1002
 	SO_RCVLOWAT                       = 0x1004
-	SO_RCVTIMEO                       = 0x1006
+	SO_RCVTIMEO                       = 0x100c
 	SO_REUSEADDR                      = 0x4
 	SO_REUSEPORT                      = 0x200
-	SO_RTABLE                         = 0x1021
 	SO_SNDBUF                         = 0x1001
 	SO_SNDLOWAT                       = 0x1003
-	SO_SNDTIMEO                       = 0x1005
-	SO_SPLICE                         = 0x1023
-	SO_TIMESTAMP                      = 0x800
+	SO_SNDTIMEO                       = 0x100b
+	SO_TIMESTAMP                      = 0x2000
 	SO_TYPE                           = 0x1008
 	SO_USELOOPBACK                    = 0x40
+	SYSCTL_VERSION                    = 0x1000000
+	SYSCTL_VERS_0                     = 0x0
+	SYSCTL_VERS_1                     = 0x1000000
+	SYSCTL_VERS_MASK                  = 0xff000000
+	S_ARCH1                           = 0x10000
+	S_ARCH2                           = 0x20000
+	S_BLKSIZE                         = 0x200
+	S_IEXEC                           = 0x40
+	S_IFBLK                           = 0x6000
+	S_IFCHR                           = 0x2000
+	S_IFDIR                           = 0x4000
+	S_IFIFO                           = 0x1000
+	S_IFLNK                           = 0xa000
+	S_IFMT                            = 0xf000
+	S_IFREG                           = 0x8000
+	S_IFSOCK                          = 0xc000
+	S_IFWHT                           = 0xe000
+	S_IREAD                           = 0x100
+	S_IRGRP                           = 0x20
+	S_IROTH                           = 0x4
+	S_IRUSR                           = 0x100
+	S_IRWXG                           = 0x38
+	S_IRWXO                           = 0x7
+	S_IRWXU                           = 0x1c0
+	S_ISGID                           = 0x400
+	S_ISTXT                           = 0x200
+	S_ISUID                           = 0x800
+	S_ISVTX                           = 0x200
+	S_IWGRP                           = 0x10
+	S_IWOTH                           = 0x2
+	S_IWRITE                          = 0x80
+	S_IWUSR                           = 0x80
+	S_IXGRP                           = 0x8
+	S_IXOTH                           = 0x1
+	S_IXUSR                           = 0x40
+	S_LOGIN_SET                       = 0x1
+	TCIFLUSH                          = 0x1
+	TCIOFLUSH                         = 0x3
+	TCOFLUSH                          = 0x2
+	TCP_CONGCTL                       = 0x20
+	TCP_KEEPCNT                       = 0x6
+	TCP_KEEPIDLE                      = 0x3
+	TCP_KEEPINIT                      = 0x7
+	TCP_KEEPINTVL                     = 0x5
 	TCP_MAXBURST                      = 0x4
 	TCP_MAXSEG                        = 0x2
 	TCP_MAXWIN                        = 0xffff
-	TCP_MAX_SACK                      = 0x3
 	TCP_MAX_WINSHIFT                  = 0xe
-	TCP_MD5SIG                        = 0x4
-	TCP_MSS                           = 0x200
+	TCP_MD5SIG                        = 0x10
+	TCP_MINMSS                        = 0xd8
+	TCP_MSS                           = 0x218
 	TCP_NODELAY                       = 0x1
-	TCP_NSTATES                       = 0xb
-	TCP_SACK_ENABLE                   = 0x8
+	TCSAFLUSH                         = 0x2
 	TIOCCBRK                          = 0x2000747a
 	TIOCCDTR                          = 0x20007478
 	TIOCCONS                          = 0x80047462
+	TIOCDCDTIMESTAMP                  = 0x40107458
 	TIOCDRAIN                         = 0x2000745e
 	TIOCEXCL                          = 0x2000740d
 	TIOCEXT                           = 0x80047460
+	TIOCFLAG_CDTRCTS                  = 0x10
 	TIOCFLAG_CLOCAL                   = 0x2
 	TIOCFLAG_CRTSCTS                  = 0x4
 	TIOCFLAG_MDMBUF                   = 0x8
-	TIOCFLAG_PPS                      = 0x10
 	TIOCFLAG_SOFTCAR                  = 0x1
 	TIOCFLUSH                         = 0x80047410
 	TIOCGETA                          = 0x402c7413
 	TIOCGETD                          = 0x4004741a
 	TIOCGFLAGS                        = 0x4004745d
+	TIOCGLINED                        = 0x40207442
 	TIOCGPGRP                         = 0x40047477
-	TIOCGTSTAMP                       = 0x4010745b
+	TIOCGQSIZE                        = 0x40047481
+	TIOCGRANTPT                       = 0x20007447
+	TIOCGSID                          = 0x40047463
+	TIOCGSIZE                         = 0x40087468
 	TIOCGWINSZ                        = 0x40087468
 	TIOCMBIC                          = 0x8004746b
 	TIOCMBIS                          = 0x8004746c
 	TIOCMGET                          = 0x4004746a
-	TIOCMODG                          = 0x4004746a
-	TIOCMODS                          = 0x8004746d
 	TIOCMSET                          = 0x8004746d
 	TIOCM_CAR                         = 0x40
 	TIOCM_CD                          = 0x40
@@ -1141,6 +1313,9 @@ const (
 	TIOCPKT_NOSTOP                    = 0x10
 	TIOCPKT_START                     = 0x8
 	TIOCPKT_STOP                      = 0x4
+	TIOCPTMGET                        = 0x40287446
+	TIOCPTSNAME                       = 0x40287448
+	TIOCRCVFRAME                      = 0x80087445
 	TIOCREMOTE                        = 0x80047469
 	TIOCSBRK                          = 0x2000747b
 	TIOCSCTTY                         = 0x20007461
@@ -1150,19 +1325,46 @@ const (
 	TIOCSETAW                         = 0x802c7415
 	TIOCSETD                          = 0x8004741b
 	TIOCSFLAGS                        = 0x8004745c
-	TIOCSIG                           = 0x8004745f
+	TIOCSIG                           = 0x2000745f
+	TIOCSLINED                        = 0x80207443
 	TIOCSPGRP                         = 0x80047476
+	TIOCSQSIZE                        = 0x80047480
+	TIOCSSIZE                         = 0x80087467
 	TIOCSTART                         = 0x2000746e
 	TIOCSTAT                          = 0x80047465
 	TIOCSTI                           = 0x80017472
 	TIOCSTOP                          = 0x2000746f
-	TIOCSTSTAMP                       = 0x8008745a
 	TIOCSWINSZ                        = 0x80087467
 	TIOCUCNTL                         = 0x80047466
+	TIOCXMTFRAME                      = 0x80087444
+	TOSTOP                            = 0x400000
+	VDISCARD                          = 0xf
+	VDSUSP                            = 0xb
+	VEOF                              = 0x0
+	VEOL                              = 0x1
+	VEOL2                             = 0x2
+	VERASE                            = 0x3
+	VINTR                             = 0x8
+	VKILL                             = 0x5
+	VLNEXT                            = 0xe
+	VMIN                              = 0x10
+	VQUIT                             = 0x9
+	VREPRINT                          = 0x6
+	VSTART                            = 0xc
+	VSTATUS                           = 0x12
+	VSTOP                             = 0xd
+	VSUSP                             = 0xa
+	VTIME                             = 0x11
+	VWERASE                           = 0x4
+	WALL                              = 0x8
+	WALLSIG                           = 0x8
 	WALTSIG                           = 0x4
-	WCONTINUED                        = 0x8
+	WCLONE                            = 0x4
 	WCOREFLAG                         = 0x80
 	WNOHANG                           = 0x1
+	WNOWAIT                           = 0x10000
+	WNOZOMBIE                         = 0x20000
+	WOPTSCHECKED                      = 0x40000
 	WSTOPPED                          = 0x7f
 	WUNTRACED                         = 0x2
 )
@@ -1178,17 +1380,11 @@ const (
 	EALREADY        = Errno(0x25)
 	EAUTH           = Errno(0x50)
 	EBADF           = Errno(0x9)
+	EBADMSG         = Errno(0x58)
 	EBADRPC         = Errno(0x48)
 	EBUSY           = Errno(0x10)
-	ECANCELED       = Errno(0x58)
+	ECANCELED       = Errno(0x57)
 	ECHILD          = Errno(0xa)
-	ECHO            = Errno(0x8)
-	ECHOCTL         = Errno(0x40)
-	ECHOE           = Errno(0x2)
-	ECHOK           = Errno(0x4)
-	ECHOKE          = Errno(0x1)
-	ECHONL          = Errno(0x10)
-	ECHOPRT         = Errno(0x20)
 	ECONNABORTED    = Errno(0x35)
 	ECONNREFUSED    = Errno(0x3d)
 	ECONNRESET      = Errno(0x36)
@@ -1202,50 +1398,51 @@ const (
 	EFTYPE          = Errno(0x4f)
 	EHOSTDOWN       = Errno(0x40)
 	EHOSTUNREACH    = Errno(0x41)
-	EIDRM           = Errno(0x59)
-	EILSEQ          = Errno(0x54)
+	EIDRM           = Errno(0x52)
+	EILSEQ          = Errno(0x55)
 	EINPROGRESS     = Errno(0x24)
 	EINTR           = Errno(0x4)
 	EINVAL          = Errno(0x16)
 	EIO             = Errno(0x5)
-	EIPSEC          = Errno(0x52)
 	EISCONN         = Errno(0x38)
 	EISDIR          = Errno(0x15)
-	ELAST           = Errno(0x5b)
+	ELAST           = Errno(0x60)
 	ELOOP           = Errno(0x3e)
-	EMEDIUMTYPE     = Errno(0x56)
 	EMFILE          = Errno(0x18)
 	EMLINK          = Errno(0x1f)
 	EMSGSIZE        = Errno(0x28)
+	EMULTIHOP       = Errno(0x5e)
 	ENAMETOOLONG    = Errno(0x3f)
-	ENDRUNDISC      = Errno(0x9)
 	ENEEDAUTH       = Errno(0x51)
 	ENETDOWN        = Errno(0x32)
 	ENETRESET       = Errno(0x34)
 	ENETUNREACH     = Errno(0x33)
 	ENFILE          = Errno(0x17)
-	ENOATTR         = Errno(0x53)
+	ENOATTR         = Errno(0x5d)
 	ENOBUFS         = Errno(0x37)
+	ENODATA         = Errno(0x59)
 	ENODEV          = Errno(0x13)
 	ENOENT          = Errno(0x2)
 	ENOEXEC         = Errno(0x8)
 	ENOLCK          = Errno(0x4d)
-	ENOMEDIUM       = Errno(0x55)
+	ENOLINK         = Errno(0x5f)
 	ENOMEM          = Errno(0xc)
-	ENOMSG          = Errno(0x5a)
+	ENOMSG          = Errno(0x53)
 	ENOPROTOOPT     = Errno(0x2a)
 	ENOSPC          = Errno(0x1c)
+	ENOSR           = Errno(0x5a)
+	ENOSTR          = Errno(0x5b)
 	ENOSYS          = Errno(0x4e)
 	ENOTBLK         = Errno(0xf)
 	ENOTCONN        = Errno(0x39)
 	ENOTDIR         = Errno(0x14)
 	ENOTEMPTY       = Errno(0x42)
 	ENOTSOCK        = Errno(0x26)
-	ENOTSUP         = Errno(0x5b)
+	ENOTSUP         = Errno(0x56)
 	ENOTTY          = Errno(0x19)
 	ENXIO           = Errno(0x6)
 	EOPNOTSUPP      = Errno(0x2d)
-	EOVERFLOW       = Errno(0x57)
+	EOVERFLOW       = Errno(0x54)
 	EPERM           = Errno(0x1)
 	EPFNOSUPPORT    = Errno(0x2e)
 	EPIPE           = Errno(0x20)
@@ -1253,6 +1450,7 @@ const (
 	EPROCUNAVAIL    = Errno(0x4c)
 	EPROGMISMATCH   = Errno(0x4b)
 	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTO          = Errno(0x60)
 	EPROTONOSUPPORT = Errno(0x2b)
 	EPROTOTYPE      = Errno(0x29)
 	ERANGE          = Errno(0x22)
@@ -1264,6 +1462,7 @@ const (
 	ESPIPE          = Errno(0x1d)
 	ESRCH           = Errno(0x3)
 	ESTALE          = Errno(0x46)
+	ETIME           = Errno(0x5c)
 	ETIMEDOUT       = Errno(0x3c)
 	ETOOMANYREFS    = Errno(0x3b)
 	ETXTBSY         = Errno(0x1a)
@@ -1272,6 +1471,43 @@ const (
 	EXDEV           = Errno(0x12)
 )
 
+// Signals
+const (
+	SIGABRT   = Signal(0x6)
+	SIGALRM   = Signal(0xe)
+	SIGBUS    = Signal(0xa)
+	SIGCHLD   = Signal(0x14)
+	SIGCONT   = Signal(0x13)
+	SIGEMT    = Signal(0x7)
+	SIGFPE    = Signal(0x8)
+	SIGHUP    = Signal(0x1)
+	SIGILL    = Signal(0x4)
+	SIGINFO   = Signal(0x1d)
+	SIGINT    = Signal(0x2)
+	SIGIO     = Signal(0x17)
+	SIGIOT    = Signal(0x6)
+	SIGKILL   = Signal(0x9)
+	SIGPIPE   = Signal(0xd)
+	SIGPROF   = Signal(0x1b)
+	SIGPWR    = Signal(0x20)
+	SIGQUIT   = Signal(0x3)
+	SIGSEGV   = Signal(0xb)
+	SIGSTOP   = Signal(0x11)
+	SIGSYS    = Signal(0xc)
+	SIGTERM   = Signal(0xf)
+	SIGTRAP   = Signal(0x5)
+	SIGTSTP   = Signal(0x12)
+	SIGTTIN   = Signal(0x15)
+	SIGTTOU   = Signal(0x16)
+	SIGURG    = Signal(0x10)
+	SIGUSR1   = Signal(0x1e)
+	SIGUSR2   = Signal(0x1f)
+	SIGVTALRM = Signal(0x1a)
+	SIGWINCH  = Signal(0x1c)
+	SIGXCPU   = Signal(0x18)
+	SIGXFSZ   = Signal(0x19)
+)
+
 // Error table
 var errors = [...]string{
 	1:  "operation not permitted",
@@ -1307,7 +1543,7 @@ var errors = [...]string{
 	31: "too many links",
 	32: "broken pipe",
 	33: "numerical argument out of domain",
-	34: "result too large",
+	34: "result too large or too small",
 	35: "resource temporarily unavailable",
 	36: "operation now in progress",
 	37: "operation already in progress",
@@ -1315,7 +1551,7 @@ var errors = [...]string{
 	39: "destination address required",
 	40: "message too long",
 	41: "protocol wrong type for socket",
-	42: "protocol not available",
+	42: "protocol option not available",
 	43: "protocol not supported",
 	44: "socket type not supported",
 	45: "operation not supported",
@@ -1355,14 +1591,55 @@ var errors = [...]string{
 	79: "inappropriate file type or format",
 	80: "authentication error",
 	81: "need authenticator",
-	82: "IPsec processing failure",
-	83: "attribute not found",
-	84: "illegal byte sequence",
-	85: "no medium found",
-	86: "wrong medium type",
-	87: "value too large to be stored in data type",
-	88: "operation canceled",
-	89: "identifier removed",
-	90: "no message of desired type",
-	91: "not supported",
+	82: "identifier removed",
+	83: "no message of desired type",
+	84: "value too large to be stored in data type",
+	85: "illegal byte sequence",
+	86: "not supported",
+	87: "operation Canceled",
+	88: "bad or Corrupt message",
+	89: "no message available",
+	90: "no STREAM resources",
+	91: "not a STREAM",
+	92: "STREAM ioctl timeout",
+	93: "attribute not found",
+	94: "multihop attempted",
+	95: "link has been severed",
+	96: "protocol error",
+}
+
+// Signal table
+var signals = [...]string{
+	1:  "hangup",
+	2:  "interrupt",
+	3:  "quit",
+	4:  "illegal instruction",
+	5:  "trace/BPT trap",
+	6:  "abort trap",
+	7:  "EMT trap",
+	8:  "floating point exception",
+	9:  "killed",
+	10: "bus error",
+	11: "segmentation fault",
+	12: "bad system call",
+	13: "broken pipe",
+	14: "alarm clock",
+	15: "terminated",
+	16: "urgent I/O condition",
+	17: "stopped (signal)",
+	18: "stopped",
+	19: "continued",
+	20: "child exited",
+	21: "stopped (tty input)",
+	22: "stopped (tty output)",
+	23: "I/O possible",
+	24: "cputime limit exceeded",
+	25: "filesize limit exceeded",
+	26: "virtual timer expired",
+	27: "profiling timer expired",
+	28: "window size changes",
+	29: "information request",
+	30: "user defined signal 1",
+	31: "user defined signal 2",
+	32: "power fail/restart",
 }
diff --git a/src/pkg/syscall/zerrors_netbsd_arm.go b/src/pkg/syscall/zerrors_netbsd_arm.go
new file mode 100644
index 0000000..3899f6b
--- /dev/null
+++ b/src/pkg/syscall/zerrors_netbsd_arm.go
@@ -0,0 +1,1644 @@
+// mkerrors.sh -marm
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -marm _const.go
+
+package syscall
+
+const (
+	AF_APPLETALK                      = 0x10
+	AF_ARP                            = 0x1c
+	AF_BLUETOOTH                      = 0x1f
+	AF_CCITT                          = 0xa
+	AF_CHAOS                          = 0x5
+	AF_CNT                            = 0x15
+	AF_COIP                           = 0x14
+	AF_DATAKIT                        = 0x9
+	AF_DECnet                         = 0xc
+	AF_DLI                            = 0xd
+	AF_E164                           = 0x1a
+	AF_ECMA                           = 0x8
+	AF_HYLINK                         = 0xf
+	AF_IEEE80211                      = 0x20
+	AF_IMPLINK                        = 0x3
+	AF_INET                           = 0x2
+	AF_INET6                          = 0x18
+	AF_IPX                            = 0x17
+	AF_ISDN                           = 0x1a
+	AF_ISO                            = 0x7
+	AF_LAT                            = 0xe
+	AF_LINK                           = 0x12
+	AF_LOCAL                          = 0x1
+	AF_MAX                            = 0x23
+	AF_MPLS                           = 0x21
+	AF_NATM                           = 0x1b
+	AF_NS                             = 0x6
+	AF_OROUTE                         = 0x11
+	AF_OSI                            = 0x7
+	AF_PUP                            = 0x4
+	AF_ROUTE                          = 0x22
+	AF_SNA                            = 0xb
+	AF_UNIX                           = 0x1
+	AF_UNSPEC                         = 0x0
+	ARPHRD_ARCNET                     = 0x7
+	ARPHRD_ETHER                      = 0x1
+	ARPHRD_FRELAY                     = 0xf
+	ARPHRD_IEEE1394                   = 0x18
+	ARPHRD_IEEE802                    = 0x6
+	ARPHRD_STRIP                      = 0x17
+	B0                                = 0x0
+	B110                              = 0x6e
+	B115200                           = 0x1c200
+	B1200                             = 0x4b0
+	B134                              = 0x86
+	B14400                            = 0x3840
+	B150                              = 0x96
+	B1800                             = 0x708
+	B19200                            = 0x4b00
+	B200                              = 0xc8
+	B230400                           = 0x38400
+	B2400                             = 0x960
+	B28800                            = 0x7080
+	B300                              = 0x12c
+	B38400                            = 0x9600
+	B460800                           = 0x70800
+	B4800                             = 0x12c0
+	B50                               = 0x32
+	B57600                            = 0xe100
+	B600                              = 0x258
+	B7200                             = 0x1c20
+	B75                               = 0x4b
+	B76800                            = 0x12c00
+	B921600                           = 0xe1000
+	B9600                             = 0x2580
+	BIOCFEEDBACK                      = 0x8004427d
+	BIOCFLUSH                         = 0x20004268
+	BIOCGBLEN                         = 0x40044266
+	BIOCGDLT                          = 0x4004426a
+	BIOCGDLTLIST                      = 0xc0084277
+	BIOCGETIF                         = 0x4090426b
+	BIOCGFEEDBACK                     = 0x4004427c
+	BIOCGHDRCMPLT                     = 0x40044274
+	BIOCGRTIMEOUT                     = 0x400c427b
+	BIOCGSEESENT                      = 0x40044278
+	BIOCGSTATS                        = 0x4080426f
+	BIOCGSTATSOLD                     = 0x4008426f
+	BIOCIMMEDIATE                     = 0x80044270
+	BIOCPROMISC                       = 0x20004269
+	BIOCSBLEN                         = 0xc0044266
+	BIOCSDLT                          = 0x80044276
+	BIOCSETF                          = 0x80084267
+	BIOCSETIF                         = 0x8090426c
+	BIOCSFEEDBACK                     = 0x8004427d
+	BIOCSHDRCMPLT                     = 0x80044275
+	BIOCSRTIMEOUT                     = 0x800c427a
+	BIOCSSEESENT                      = 0x80044279
+	BIOCSTCPF                         = 0x80084272
+	BIOCSUDPF                         = 0x80084273
+	BIOCVERSION                       = 0x40044271
+	BPF_A                             = 0x10
+	BPF_ABS                           = 0x20
+	BPF_ADD                           = 0x0
+	BPF_ALIGNMENT                     = 0x4
+	BPF_ALIGNMENT32                   = 0x4
+	BPF_ALU                           = 0x4
+	BPF_AND                           = 0x50
+	BPF_B                             = 0x10
+	BPF_DFLTBUFSIZE                   = 0x100000
+	BPF_DIV                           = 0x30
+	BPF_H                             = 0x8
+	BPF_IMM                           = 0x0
+	BPF_IND                           = 0x40
+	BPF_JA                            = 0x0
+	BPF_JEQ                           = 0x10
+	BPF_JGE                           = 0x30
+	BPF_JGT                           = 0x20
+	BPF_JMP                           = 0x5
+	BPF_JSET                          = 0x40
+	BPF_K                             = 0x0
+	BPF_LD                            = 0x0
+	BPF_LDX                           = 0x1
+	BPF_LEN                           = 0x80
+	BPF_LSH                           = 0x60
+	BPF_MAJOR_VERSION                 = 0x1
+	BPF_MAXBUFSIZE                    = 0x1000000
+	BPF_MAXINSNS                      = 0x200
+	BPF_MEM                           = 0x60
+	BPF_MEMWORDS                      = 0x10
+	BPF_MINBUFSIZE                    = 0x20
+	BPF_MINOR_VERSION                 = 0x1
+	BPF_MISC                          = 0x7
+	BPF_MSH                           = 0xa0
+	BPF_MUL                           = 0x20
+	BPF_NEG                           = 0x80
+	BPF_OR                            = 0x40
+	BPF_RELEASE                       = 0x30bb6
+	BPF_RET                           = 0x6
+	BPF_RSH                           = 0x70
+	BPF_ST                            = 0x2
+	BPF_STX                           = 0x3
+	BPF_SUB                           = 0x10
+	BPF_TAX                           = 0x0
+	BPF_TXA                           = 0x80
+	BPF_W                             = 0x0
+	BPF_X                             = 0x8
+	BRKINT                            = 0x2
+	CFLUSH                            = 0xf
+	CLOCAL                            = 0x8000
+	CREAD                             = 0x800
+	CS5                               = 0x0
+	CS6                               = 0x100
+	CS7                               = 0x200
+	CS8                               = 0x300
+	CSIZE                             = 0x300
+	CSTART                            = 0x11
+	CSTATUS                           = 0x14
+	CSTOP                             = 0x13
+	CSTOPB                            = 0x400
+	CSUSP                             = 0x1a
+	CTL_MAXNAME                       = 0xc
+	CTL_NET                           = 0x4
+	CTL_QUERY                         = -0x2
+	DIOCBSFLUSH                       = 0x20006478
+	DLT_A429                          = 0xb8
+	DLT_A653_ICM                      = 0xb9
+	DLT_AIRONET_HEADER                = 0x78
+	DLT_AOS                           = 0xde
+	DLT_APPLE_IP_OVER_IEEE1394        = 0x8a
+	DLT_ARCNET                        = 0x7
+	DLT_ARCNET_LINUX                  = 0x81
+	DLT_ATM_CLIP                      = 0x13
+	DLT_ATM_RFC1483                   = 0xb
+	DLT_AURORA                        = 0x7e
+	DLT_AX25                          = 0x3
+	DLT_AX25_KISS                     = 0xca
+	DLT_BACNET_MS_TP                  = 0xa5
+	DLT_BLUETOOTH_HCI_H4              = 0xbb
+	DLT_BLUETOOTH_HCI_H4_WITH_PHDR    = 0xc9
+	DLT_CAN20B                        = 0xbe
+	DLT_CAN_SOCKETCAN                 = 0xe3
+	DLT_CHAOS                         = 0x5
+	DLT_CISCO_IOS                     = 0x76
+	DLT_C_HDLC                        = 0x68
+	DLT_C_HDLC_WITH_DIR               = 0xcd
+	DLT_DECT                          = 0xdd
+	DLT_DOCSIS                        = 0x8f
+	DLT_ECONET                        = 0x73
+	DLT_EN10MB                        = 0x1
+	DLT_EN3MB                         = 0x2
+	DLT_ENC                           = 0x6d
+	DLT_ERF                           = 0xc5
+	DLT_ERF_ETH                       = 0xaf
+	DLT_ERF_POS                       = 0xb0
+	DLT_FC_2                          = 0xe0
+	DLT_FC_2_WITH_FRAME_DELIMS        = 0xe1
+	DLT_FDDI                          = 0xa
+	DLT_FLEXRAY                       = 0xd2
+	DLT_FRELAY                        = 0x6b
+	DLT_FRELAY_WITH_DIR               = 0xce
+	DLT_GCOM_SERIAL                   = 0xad
+	DLT_GCOM_T1E1                     = 0xac
+	DLT_GPF_F                         = 0xab
+	DLT_GPF_T                         = 0xaa
+	DLT_GPRS_LLC                      = 0xa9
+	DLT_GSMTAP_ABIS                   = 0xda
+	DLT_GSMTAP_UM                     = 0xd9
+	DLT_HDLC                          = 0x10
+	DLT_HHDLC                         = 0x79
+	DLT_HIPPI                         = 0xf
+	DLT_IBM_SN                        = 0x92
+	DLT_IBM_SP                        = 0x91
+	DLT_IEEE802                       = 0x6
+	DLT_IEEE802_11                    = 0x69
+	DLT_IEEE802_11_RADIO              = 0x7f
+	DLT_IEEE802_11_RADIO_AVS          = 0xa3
+	DLT_IEEE802_15_4                  = 0xc3
+	DLT_IEEE802_15_4_LINUX            = 0xbf
+	DLT_IEEE802_15_4_NONASK_PHY       = 0xd7
+	DLT_IEEE802_16_MAC_CPS            = 0xbc
+	DLT_IEEE802_16_MAC_CPS_RADIO      = 0xc1
+	DLT_IPMB                          = 0xc7
+	DLT_IPMB_LINUX                    = 0xd1
+	DLT_IPNET                         = 0xe2
+	DLT_IPV4                          = 0xe4
+	DLT_IPV6                          = 0xe5
+	DLT_IP_OVER_FC                    = 0x7a
+	DLT_JUNIPER_ATM1                  = 0x89
+	DLT_JUNIPER_ATM2                  = 0x87
+	DLT_JUNIPER_CHDLC                 = 0xb5
+	DLT_JUNIPER_ES                    = 0x84
+	DLT_JUNIPER_ETHER                 = 0xb2
+	DLT_JUNIPER_FRELAY                = 0xb4
+	DLT_JUNIPER_GGSN                  = 0x85
+	DLT_JUNIPER_ISM                   = 0xc2
+	DLT_JUNIPER_MFR                   = 0x86
+	DLT_JUNIPER_MLFR                  = 0x83
+	DLT_JUNIPER_MLPPP                 = 0x82
+	DLT_JUNIPER_MONITOR               = 0xa4
+	DLT_JUNIPER_PIC_PEER              = 0xae
+	DLT_JUNIPER_PPP                   = 0xb3
+	DLT_JUNIPER_PPPOE                 = 0xa7
+	DLT_JUNIPER_PPPOE_ATM             = 0xa8
+	DLT_JUNIPER_SERVICES              = 0x88
+	DLT_JUNIPER_ST                    = 0xc8
+	DLT_JUNIPER_VP                    = 0xb7
+	DLT_LAPB_WITH_DIR                 = 0xcf
+	DLT_LAPD                          = 0xcb
+	DLT_LIN                           = 0xd4
+	DLT_LINUX_EVDEV                   = 0xd8
+	DLT_LINUX_IRDA                    = 0x90
+	DLT_LINUX_LAPD                    = 0xb1
+	DLT_LINUX_SLL                     = 0x71
+	DLT_LOOP                          = 0x6c
+	DLT_LTALK                         = 0x72
+	DLT_MFR                           = 0xb6
+	DLT_MOST                          = 0xd3
+	DLT_MPLS                          = 0xdb
+	DLT_MTP2                          = 0x8c
+	DLT_MTP2_WITH_PHDR                = 0x8b
+	DLT_MTP3                          = 0x8d
+	DLT_NULL                          = 0x0
+	DLT_PCI_EXP                       = 0x7d
+	DLT_PFLOG                         = 0x75
+	DLT_PFSYNC                        = 0x12
+	DLT_PPI                           = 0xc0
+	DLT_PPP                           = 0x9
+	DLT_PPP_BSDOS                     = 0xe
+	DLT_PPP_ETHER                     = 0x33
+	DLT_PPP_PPPD                      = 0xa6
+	DLT_PPP_SERIAL                    = 0x32
+	DLT_PPP_WITH_DIR                  = 0xcc
+	DLT_PRISM_HEADER                  = 0x77
+	DLT_PRONET                        = 0x4
+	DLT_RAIF1                         = 0xc6
+	DLT_RAW                           = 0xc
+	DLT_RAWAF_MASK                    = 0x2240000
+	DLT_RIO                           = 0x7c
+	DLT_SCCP                          = 0x8e
+	DLT_SITA                          = 0xc4
+	DLT_SLIP                          = 0x8
+	DLT_SLIP_BSDOS                    = 0xd
+	DLT_SUNATM                        = 0x7b
+	DLT_SYMANTEC_FIREWALL             = 0x63
+	DLT_TZSP                          = 0x80
+	DLT_USB                           = 0xba
+	DLT_USB_LINUX                     = 0xbd
+	DLT_USB_LINUX_MMAPPED             = 0xdc
+	DLT_WIHART                        = 0xdf
+	DLT_X2E_SERIAL                    = 0xd5
+	DLT_X2E_XORAYA                    = 0xd6
+	DT_BLK                            = 0x6
+	DT_CHR                            = 0x2
+	DT_DIR                            = 0x4
+	DT_FIFO                           = 0x1
+	DT_LNK                            = 0xa
+	DT_REG                            = 0x8
+	DT_SOCK                           = 0xc
+	DT_UNKNOWN                        = 0x0
+	DT_WHT                            = 0xe
+	ECHO                              = 0x8
+	ECHOCTL                           = 0x40
+	ECHOE                             = 0x2
+	ECHOK                             = 0x4
+	ECHOKE                            = 0x1
+	ECHONL                            = 0x10
+	ECHOPRT                           = 0x20
+	EMUL_LINUX                        = 0x1
+	EMUL_LINUX32                      = 0x5
+	EMUL_MAXID                        = 0x6
+	ETHERCAP_JUMBO_MTU                = 0x4
+	ETHERCAP_VLAN_HWTAGGING           = 0x2
+	ETHERCAP_VLAN_MTU                 = 0x1
+	ETHERMIN                          = 0x2e
+	ETHERMTU                          = 0x5dc
+	ETHERMTU_JUMBO                    = 0x2328
+	ETHERTYPE_8023                    = 0x4
+	ETHERTYPE_AARP                    = 0x80f3
+	ETHERTYPE_ACCTON                  = 0x8390
+	ETHERTYPE_AEONIC                  = 0x8036
+	ETHERTYPE_ALPHA                   = 0x814a
+	ETHERTYPE_AMBER                   = 0x6008
+	ETHERTYPE_AMOEBA                  = 0x8145
+	ETHERTYPE_APOLLO                  = 0x80f7
+	ETHERTYPE_APOLLODOMAIN            = 0x8019
+	ETHERTYPE_APPLETALK               = 0x809b
+	ETHERTYPE_APPLITEK                = 0x80c7
+	ETHERTYPE_ARGONAUT                = 0x803a
+	ETHERTYPE_ARP                     = 0x806
+	ETHERTYPE_AT                      = 0x809b
+	ETHERTYPE_ATALK                   = 0x809b
+	ETHERTYPE_ATOMIC                  = 0x86df
+	ETHERTYPE_ATT                     = 0x8069
+	ETHERTYPE_ATTSTANFORD             = 0x8008
+	ETHERTYPE_AUTOPHON                = 0x806a
+	ETHERTYPE_AXIS                    = 0x8856
+	ETHERTYPE_BCLOOP                  = 0x9003
+	ETHERTYPE_BOFL                    = 0x8102
+	ETHERTYPE_CABLETRON               = 0x7034
+	ETHERTYPE_CHAOS                   = 0x804
+	ETHERTYPE_COMDESIGN               = 0x806c
+	ETHERTYPE_COMPUGRAPHIC            = 0x806d
+	ETHERTYPE_COUNTERPOINT            = 0x8062
+	ETHERTYPE_CRONUS                  = 0x8004
+	ETHERTYPE_CRONUSVLN               = 0x8003
+	ETHERTYPE_DCA                     = 0x1234
+	ETHERTYPE_DDE                     = 0x807b
+	ETHERTYPE_DEBNI                   = 0xaaaa
+	ETHERTYPE_DECAM                   = 0x8048
+	ETHERTYPE_DECCUST                 = 0x6006
+	ETHERTYPE_DECDIAG                 = 0x6005
+	ETHERTYPE_DECDNS                  = 0x803c
+	ETHERTYPE_DECDTS                  = 0x803e
+	ETHERTYPE_DECEXPER                = 0x6000
+	ETHERTYPE_DECLAST                 = 0x8041
+	ETHERTYPE_DECLTM                  = 0x803f
+	ETHERTYPE_DECMUMPS                = 0x6009
+	ETHERTYPE_DECNETBIOS              = 0x8040
+	ETHERTYPE_DELTACON                = 0x86de
+	ETHERTYPE_DIDDLE                  = 0x4321
+	ETHERTYPE_DLOG1                   = 0x660
+	ETHERTYPE_DLOG2                   = 0x661
+	ETHERTYPE_DN                      = 0x6003
+	ETHERTYPE_DOGFIGHT                = 0x1989
+	ETHERTYPE_DSMD                    = 0x8039
+	ETHERTYPE_ECMA                    = 0x803
+	ETHERTYPE_ENCRYPT                 = 0x803d
+	ETHERTYPE_ES                      = 0x805d
+	ETHERTYPE_EXCELAN                 = 0x8010
+	ETHERTYPE_EXPERDATA               = 0x8049
+	ETHERTYPE_FLIP                    = 0x8146
+	ETHERTYPE_FLOWCONTROL             = 0x8808
+	ETHERTYPE_FRARP                   = 0x808
+	ETHERTYPE_GENDYN                  = 0x8068
+	ETHERTYPE_HAYES                   = 0x8130
+	ETHERTYPE_HIPPI_FP                = 0x8180
+	ETHERTYPE_HITACHI                 = 0x8820
+	ETHERTYPE_HP                      = 0x8005
+	ETHERTYPE_IEEEPUP                 = 0xa00
+	ETHERTYPE_IEEEPUPAT               = 0xa01
+	ETHERTYPE_IMLBL                   = 0x4c42
+	ETHERTYPE_IMLBLDIAG               = 0x424c
+	ETHERTYPE_IP                      = 0x800
+	ETHERTYPE_IPAS                    = 0x876c
+	ETHERTYPE_IPV6                    = 0x86dd
+	ETHERTYPE_IPX                     = 0x8137
+	ETHERTYPE_IPXNEW                  = 0x8037
+	ETHERTYPE_KALPANA                 = 0x8582
+	ETHERTYPE_LANBRIDGE               = 0x8038
+	ETHERTYPE_LANPROBE                = 0x8888
+	ETHERTYPE_LAT                     = 0x6004
+	ETHERTYPE_LBACK                   = 0x9000
+	ETHERTYPE_LITTLE                  = 0x8060
+	ETHERTYPE_LOGICRAFT               = 0x8148
+	ETHERTYPE_LOOPBACK                = 0x9000
+	ETHERTYPE_MATRA                   = 0x807a
+	ETHERTYPE_MAX                     = 0xffff
+	ETHERTYPE_MERIT                   = 0x807c
+	ETHERTYPE_MICP                    = 0x873a
+	ETHERTYPE_MOPDL                   = 0x6001
+	ETHERTYPE_MOPRC                   = 0x6002
+	ETHERTYPE_MOTOROLA                = 0x818d
+	ETHERTYPE_MPLS                    = 0x8847
+	ETHERTYPE_MPLS_MCAST              = 0x8848
+	ETHERTYPE_MUMPS                   = 0x813f
+	ETHERTYPE_NBPCC                   = 0x3c04
+	ETHERTYPE_NBPCLAIM                = 0x3c09
+	ETHERTYPE_NBPCLREQ                = 0x3c05
+	ETHERTYPE_NBPCLRSP                = 0x3c06
+	ETHERTYPE_NBPCREQ                 = 0x3c02
+	ETHERTYPE_NBPCRSP                 = 0x3c03
+	ETHERTYPE_NBPDG                   = 0x3c07
+	ETHERTYPE_NBPDGB                  = 0x3c08
+	ETHERTYPE_NBPDLTE                 = 0x3c0a
+	ETHERTYPE_NBPRAR                  = 0x3c0c
+	ETHERTYPE_NBPRAS                  = 0x3c0b
+	ETHERTYPE_NBPRST                  = 0x3c0d
+	ETHERTYPE_NBPSCD                  = 0x3c01
+	ETHERTYPE_NBPVCD                  = 0x3c00
+	ETHERTYPE_NBS                     = 0x802
+	ETHERTYPE_NCD                     = 0x8149
+	ETHERTYPE_NESTAR                  = 0x8006
+	ETHERTYPE_NETBEUI                 = 0x8191
+	ETHERTYPE_NOVELL                  = 0x8138
+	ETHERTYPE_NS                      = 0x600
+	ETHERTYPE_NSAT                    = 0x601
+	ETHERTYPE_NSCOMPAT                = 0x807
+	ETHERTYPE_NTRAILER                = 0x10
+	ETHERTYPE_OS9                     = 0x7007
+	ETHERTYPE_OS9NET                  = 0x7009
+	ETHERTYPE_PACER                   = 0x80c6
+	ETHERTYPE_PAE                     = 0x888e
+	ETHERTYPE_PCS                     = 0x4242
+	ETHERTYPE_PLANNING                = 0x8044
+	ETHERTYPE_PPP                     = 0x880b
+	ETHERTYPE_PPPOE                   = 0x8864
+	ETHERTYPE_PPPOEDISC               = 0x8863
+	ETHERTYPE_PRIMENTS                = 0x7031
+	ETHERTYPE_PUP                     = 0x200
+	ETHERTYPE_PUPAT                   = 0x200
+	ETHERTYPE_RACAL                   = 0x7030
+	ETHERTYPE_RATIONAL                = 0x8150
+	ETHERTYPE_RAWFR                   = 0x6559
+	ETHERTYPE_RCL                     = 0x1995
+	ETHERTYPE_RDP                     = 0x8739
+	ETHERTYPE_RETIX                   = 0x80f2
+	ETHERTYPE_REVARP                  = 0x8035
+	ETHERTYPE_SCA                     = 0x6007
+	ETHERTYPE_SECTRA                  = 0x86db
+	ETHERTYPE_SECUREDATA              = 0x876d
+	ETHERTYPE_SGITW                   = 0x817e
+	ETHERTYPE_SG_BOUNCE               = 0x8016
+	ETHERTYPE_SG_DIAG                 = 0x8013
+	ETHERTYPE_SG_NETGAMES             = 0x8014
+	ETHERTYPE_SG_RESV                 = 0x8015
+	ETHERTYPE_SIMNET                  = 0x5208
+	ETHERTYPE_SLOWPROTOCOLS           = 0x8809
+	ETHERTYPE_SNA                     = 0x80d5
+	ETHERTYPE_SNMP                    = 0x814c
+	ETHERTYPE_SONIX                   = 0xfaf5
+	ETHERTYPE_SPIDER                  = 0x809f
+	ETHERTYPE_SPRITE                  = 0x500
+	ETHERTYPE_STP                     = 0x8181
+	ETHERTYPE_TALARIS                 = 0x812b
+	ETHERTYPE_TALARISMC               = 0x852b
+	ETHERTYPE_TCPCOMP                 = 0x876b
+	ETHERTYPE_TCPSM                   = 0x9002
+	ETHERTYPE_TEC                     = 0x814f
+	ETHERTYPE_TIGAN                   = 0x802f
+	ETHERTYPE_TRAIL                   = 0x1000
+	ETHERTYPE_TRANSETHER              = 0x6558
+	ETHERTYPE_TYMSHARE                = 0x802e
+	ETHERTYPE_UBBST                   = 0x7005
+	ETHERTYPE_UBDEBUG                 = 0x900
+	ETHERTYPE_UBDIAGLOOP              = 0x7002
+	ETHERTYPE_UBDL                    = 0x7000
+	ETHERTYPE_UBNIU                   = 0x7001
+	ETHERTYPE_UBNMC                   = 0x7003
+	ETHERTYPE_VALID                   = 0x1600
+	ETHERTYPE_VARIAN                  = 0x80dd
+	ETHERTYPE_VAXELN                  = 0x803b
+	ETHERTYPE_VEECO                   = 0x8067
+	ETHERTYPE_VEXP                    = 0x805b
+	ETHERTYPE_VGLAB                   = 0x8131
+	ETHERTYPE_VINES                   = 0xbad
+	ETHERTYPE_VINESECHO               = 0xbaf
+	ETHERTYPE_VINESLOOP               = 0xbae
+	ETHERTYPE_VITAL                   = 0xff00
+	ETHERTYPE_VLAN                    = 0x8100
+	ETHERTYPE_VLTLMAN                 = 0x8080
+	ETHERTYPE_VPROD                   = 0x805c
+	ETHERTYPE_VURESERVED              = 0x8147
+	ETHERTYPE_WATERLOO                = 0x8130
+	ETHERTYPE_WELLFLEET               = 0x8103
+	ETHERTYPE_X25                     = 0x805
+	ETHERTYPE_X75                     = 0x801
+	ETHERTYPE_XNSSM                   = 0x9001
+	ETHERTYPE_XTP                     = 0x817d
+	ETHER_ADDR_LEN                    = 0x6
+	ETHER_CRC_LEN                     = 0x4
+	ETHER_CRC_POLY_BE                 = 0x4c11db6
+	ETHER_CRC_POLY_LE                 = 0xedb88320
+	ETHER_HDR_LEN                     = 0xe
+	ETHER_MAX_LEN                     = 0x5ee
+	ETHER_MAX_LEN_JUMBO               = 0x233a
+	ETHER_MIN_LEN                     = 0x40
+	ETHER_PPPOE_ENCAP_LEN             = 0x8
+	ETHER_TYPE_LEN                    = 0x2
+	ETHER_VLAN_ENCAP_LEN              = 0x4
+	EVFILT_AIO                        = 0x2
+	EVFILT_PROC                       = 0x4
+	EVFILT_READ                       = 0x0
+	EVFILT_SIGNAL                     = 0x5
+	EVFILT_SYSCOUNT                   = 0x7
+	EVFILT_TIMER                      = 0x6
+	EVFILT_VNODE                      = 0x3
+	EVFILT_WRITE                      = 0x1
+	EV_ADD                            = 0x1
+	EV_CLEAR                          = 0x20
+	EV_DELETE                         = 0x2
+	EV_DISABLE                        = 0x8
+	EV_ENABLE                         = 0x4
+	EV_EOF                            = 0x8000
+	EV_ERROR                          = 0x4000
+	EV_FLAG1                          = 0x2000
+	EV_ONESHOT                        = 0x10
+	EV_SYSFLAGS                       = 0xf000
+	EXTA                              = 0x4b00
+	EXTB                              = 0x9600
+	EXTPROC                           = 0x800
+	FD_CLOEXEC                        = 0x1
+	FD_SETSIZE                        = 0x100
+	FLUSHO                            = 0x800000
+	F_CLOSEM                          = 0xa
+	F_DUPFD                           = 0x0
+	F_DUPFD_CLOEXEC                   = 0xc
+	F_FSCTL                           = -0x80000000
+	F_FSDIRMASK                       = 0x70000000
+	F_FSIN                            = 0x10000000
+	F_FSINOUT                         = 0x30000000
+	F_FSOUT                           = 0x20000000
+	F_FSPRIV                          = 0x8000
+	F_FSVOID                          = 0x40000000
+	F_GETFD                           = 0x1
+	F_GETFL                           = 0x3
+	F_GETLK                           = 0x7
+	F_GETNOSIGPIPE                    = 0xd
+	F_GETOWN                          = 0x5
+	F_MAXFD                           = 0xb
+	F_OK                              = 0x0
+	F_PARAM_MASK                      = 0xfff
+	F_PARAM_MAX                       = 0xfff
+	F_RDLCK                           = 0x1
+	F_SETFD                           = 0x2
+	F_SETFL                           = 0x4
+	F_SETLK                           = 0x8
+	F_SETLKW                          = 0x9
+	F_SETNOSIGPIPE                    = 0xe
+	F_SETOWN                          = 0x6
+	F_UNLCK                           = 0x2
+	F_WRLCK                           = 0x3
+	HUPCL                             = 0x4000
+	ICANON                            = 0x100
+	ICRNL                             = 0x100
+	IEXTEN                            = 0x400
+	IFAN_ARRIVAL                      = 0x0
+	IFAN_DEPARTURE                    = 0x1
+	IFA_ROUTE                         = 0x1
+	IFF_ALLMULTI                      = 0x200
+	IFF_BROADCAST                     = 0x2
+	IFF_CANTCHANGE                    = 0x8f52
+	IFF_DEBUG                         = 0x4
+	IFF_LINK0                         = 0x1000
+	IFF_LINK1                         = 0x2000
+	IFF_LINK2                         = 0x4000
+	IFF_LOOPBACK                      = 0x8
+	IFF_MULTICAST                     = 0x8000
+	IFF_NOARP                         = 0x80
+	IFF_NOTRAILERS                    = 0x20
+	IFF_OACTIVE                       = 0x400
+	IFF_POINTOPOINT                   = 0x10
+	IFF_PROMISC                       = 0x100
+	IFF_RUNNING                       = 0x40
+	IFF_SIMPLEX                       = 0x800
+	IFF_UP                            = 0x1
+	IFNAMSIZ                          = 0x10
+	IFT_1822                          = 0x2
+	IFT_A12MPPSWITCH                  = 0x82
+	IFT_AAL2                          = 0xbb
+	IFT_AAL5                          = 0x31
+	IFT_ADSL                          = 0x5e
+	IFT_AFLANE8023                    = 0x3b
+	IFT_AFLANE8025                    = 0x3c
+	IFT_ARAP                          = 0x58
+	IFT_ARCNET                        = 0x23
+	IFT_ARCNETPLUS                    = 0x24
+	IFT_ASYNC                         = 0x54
+	IFT_ATM                           = 0x25
+	IFT_ATMDXI                        = 0x69
+	IFT_ATMFUNI                       = 0x6a
+	IFT_ATMIMA                        = 0x6b
+	IFT_ATMLOGICAL                    = 0x50
+	IFT_ATMRADIO                      = 0xbd
+	IFT_ATMSUBINTERFACE               = 0x86
+	IFT_ATMVCIENDPT                   = 0xc2
+	IFT_ATMVIRTUAL                    = 0x95
+	IFT_BGPPOLICYACCOUNTING           = 0xa2
+	IFT_BRIDGE                        = 0xd1
+	IFT_BSC                           = 0x53
+	IFT_CARP                          = 0xf8
+	IFT_CCTEMUL                       = 0x3d
+	IFT_CEPT                          = 0x13
+	IFT_CES                           = 0x85
+	IFT_CHANNEL                       = 0x46
+	IFT_CNR                           = 0x55
+	IFT_COFFEE                        = 0x84
+	IFT_COMPOSITELINK                 = 0x9b
+	IFT_DCN                           = 0x8d
+	IFT_DIGITALPOWERLINE              = 0x8a
+	IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
+	IFT_DLSW                          = 0x4a
+	IFT_DOCSCABLEDOWNSTREAM           = 0x80
+	IFT_DOCSCABLEMACLAYER             = 0x7f
+	IFT_DOCSCABLEUPSTREAM             = 0x81
+	IFT_DOCSCABLEUPSTREAMCHANNEL      = 0xcd
+	IFT_DS0                           = 0x51
+	IFT_DS0BUNDLE                     = 0x52
+	IFT_DS1FDL                        = 0xaa
+	IFT_DS3                           = 0x1e
+	IFT_DTM                           = 0x8c
+	IFT_DVBASILN                      = 0xac
+	IFT_DVBASIOUT                     = 0xad
+	IFT_DVBRCCDOWNSTREAM              = 0x93
+	IFT_DVBRCCMACLAYER                = 0x92
+	IFT_DVBRCCUPSTREAM                = 0x94
+	IFT_ECONET                        = 0xce
+	IFT_EON                           = 0x19
+	IFT_EPLRS                         = 0x57
+	IFT_ESCON                         = 0x49
+	IFT_ETHER                         = 0x6
+	IFT_FAITH                         = 0xf2
+	IFT_FAST                          = 0x7d
+	IFT_FASTETHER                     = 0x3e
+	IFT_FASTETHERFX                   = 0x45
+	IFT_FDDI                          = 0xf
+	IFT_FIBRECHANNEL                  = 0x38
+	IFT_FRAMERELAYINTERCONNECT        = 0x3a
+	IFT_FRAMERELAYMPI                 = 0x5c
+	IFT_FRDLCIENDPT                   = 0xc1
+	IFT_FRELAY                        = 0x20
+	IFT_FRELAYDCE                     = 0x2c
+	IFT_FRF16MFRBUNDLE                = 0xa3
+	IFT_FRFORWARD                     = 0x9e
+	IFT_G703AT2MB                     = 0x43
+	IFT_G703AT64K                     = 0x42
+	IFT_GIF                           = 0xf0
+	IFT_GIGABITETHERNET               = 0x75
+	IFT_GR303IDT                      = 0xb2
+	IFT_GR303RDT                      = 0xb1
+	IFT_H323GATEKEEPER                = 0xa4
+	IFT_H323PROXY                     = 0xa5
+	IFT_HDH1822                       = 0x3
+	IFT_HDLC                          = 0x76
+	IFT_HDSL2                         = 0xa8
+	IFT_HIPERLAN2                     = 0xb7
+	IFT_HIPPI                         = 0x2f
+	IFT_HIPPIINTERFACE                = 0x39
+	IFT_HOSTPAD                       = 0x5a
+	IFT_HSSI                          = 0x2e
+	IFT_HY                            = 0xe
+	IFT_IBM370PARCHAN                 = 0x48
+	IFT_IDSL                          = 0x9a
+	IFT_IEEE1394                      = 0x90
+	IFT_IEEE80211                     = 0x47
+	IFT_IEEE80212                     = 0x37
+	IFT_IEEE8023ADLAG                 = 0xa1
+	IFT_IFGSN                         = 0x91
+	IFT_IMT                           = 0xbe
+	IFT_INFINIBAND                    = 0xc7
+	IFT_INTERLEAVE                    = 0x7c
+	IFT_IP                            = 0x7e
+	IFT_IPFORWARD                     = 0x8e
+	IFT_IPOVERATM                     = 0x72
+	IFT_IPOVERCDLC                    = 0x6d
+	IFT_IPOVERCLAW                    = 0x6e
+	IFT_IPSWITCH                      = 0x4e
+	IFT_ISDN                          = 0x3f
+	IFT_ISDNBASIC                     = 0x14
+	IFT_ISDNPRIMARY                   = 0x15
+	IFT_ISDNS                         = 0x4b
+	IFT_ISDNU                         = 0x4c
+	IFT_ISO88022LLC                   = 0x29
+	IFT_ISO88023                      = 0x7
+	IFT_ISO88024                      = 0x8
+	IFT_ISO88025                      = 0x9
+	IFT_ISO88025CRFPINT               = 0x62
+	IFT_ISO88025DTR                   = 0x56
+	IFT_ISO88025FIBER                 = 0x73
+	IFT_ISO88026                      = 0xa
+	IFT_ISUP                          = 0xb3
+	IFT_L2VLAN                        = 0x87
+	IFT_L3IPVLAN                      = 0x88
+	IFT_L3IPXVLAN                     = 0x89
+	IFT_LAPB                          = 0x10
+	IFT_LAPD                          = 0x4d
+	IFT_LAPF                          = 0x77
+	IFT_LINEGROUP                     = 0xd2
+	IFT_LOCALTALK                     = 0x2a
+	IFT_LOOP                          = 0x18
+	IFT_MEDIAMAILOVERIP               = 0x8b
+	IFT_MFSIGLINK                     = 0xa7
+	IFT_MIOX25                        = 0x26
+	IFT_MODEM                         = 0x30
+	IFT_MPC                           = 0x71
+	IFT_MPLS                          = 0xa6
+	IFT_MPLSTUNNEL                    = 0x96
+	IFT_MSDSL                         = 0x8f
+	IFT_MVL                           = 0xbf
+	IFT_MYRINET                       = 0x63
+	IFT_NFAS                          = 0xaf
+	IFT_NSIP                          = 0x1b
+	IFT_OPTICALCHANNEL                = 0xc3
+	IFT_OPTICALTRANSPORT              = 0xc4
+	IFT_OTHER                         = 0x1
+	IFT_P10                           = 0xc
+	IFT_P80                           = 0xd
+	IFT_PARA                          = 0x22
+	IFT_PFLOG                         = 0xf5
+	IFT_PFSYNC                        = 0xf6
+	IFT_PLC                           = 0xae
+	IFT_PON155                        = 0xcf
+	IFT_PON622                        = 0xd0
+	IFT_POS                           = 0xab
+	IFT_PPP                           = 0x17
+	IFT_PPPMULTILINKBUNDLE            = 0x6c
+	IFT_PROPATM                       = 0xc5
+	IFT_PROPBWAP2MP                   = 0xb8
+	IFT_PROPCNLS                      = 0x59
+	IFT_PROPDOCSWIRELESSDOWNSTREAM    = 0xb5
+	IFT_PROPDOCSWIRELESSMACLAYER      = 0xb4
+	IFT_PROPDOCSWIRELESSUPSTREAM      = 0xb6
+	IFT_PROPMUX                       = 0x36
+	IFT_PROPVIRTUAL                   = 0x35
+	IFT_PROPWIRELESSP2P               = 0x9d
+	IFT_PTPSERIAL                     = 0x16
+	IFT_PVC                           = 0xf1
+	IFT_Q2931                         = 0xc9
+	IFT_QLLC                          = 0x44
+	IFT_RADIOMAC                      = 0xbc
+	IFT_RADSL                         = 0x5f
+	IFT_REACHDSL                      = 0xc0
+	IFT_RFC1483                       = 0x9f
+	IFT_RS232                         = 0x21
+	IFT_RSRB                          = 0x4f
+	IFT_SDLC                          = 0x11
+	IFT_SDSL                          = 0x60
+	IFT_SHDSL                         = 0xa9
+	IFT_SIP                           = 0x1f
+	IFT_SIPSIG                        = 0xcc
+	IFT_SIPTG                         = 0xcb
+	IFT_SLIP                          = 0x1c
+	IFT_SMDSDXI                       = 0x2b
+	IFT_SMDSICIP                      = 0x34
+	IFT_SONET                         = 0x27
+	IFT_SONETOVERHEADCHANNEL          = 0xb9
+	IFT_SONETPATH                     = 0x32
+	IFT_SONETVT                       = 0x33
+	IFT_SRP                           = 0x97
+	IFT_SS7SIGLINK                    = 0x9c
+	IFT_STACKTOSTACK                  = 0x6f
+	IFT_STARLAN                       = 0xb
+	IFT_STF                           = 0xd7
+	IFT_T1                            = 0x12
+	IFT_TDLC                          = 0x74
+	IFT_TELINK                        = 0xc8
+	IFT_TERMPAD                       = 0x5b
+	IFT_TR008                         = 0xb0
+	IFT_TRANSPHDLC                    = 0x7b
+	IFT_TUNNEL                        = 0x83
+	IFT_ULTRA                         = 0x1d
+	IFT_USB                           = 0xa0
+	IFT_V11                           = 0x40
+	IFT_V35                           = 0x2d
+	IFT_V36                           = 0x41
+	IFT_V37                           = 0x78
+	IFT_VDSL                          = 0x61
+	IFT_VIRTUALIPADDRESS              = 0x70
+	IFT_VIRTUALTG                     = 0xca
+	IFT_VOICEDID                      = 0xd5
+	IFT_VOICEEM                       = 0x64
+	IFT_VOICEEMFGD                    = 0xd3
+	IFT_VOICEENCAP                    = 0x67
+	IFT_VOICEFGDEANA                  = 0xd4
+	IFT_VOICEFXO                      = 0x65
+	IFT_VOICEFXS                      = 0x66
+	IFT_VOICEOVERATM                  = 0x98
+	IFT_VOICEOVERCABLE                = 0xc6
+	IFT_VOICEOVERFRAMERELAY           = 0x99
+	IFT_VOICEOVERIP                   = 0x68
+	IFT_X213                          = 0x5d
+	IFT_X25                           = 0x5
+	IFT_X25DDN                        = 0x4
+	IFT_X25HUNTGROUP                  = 0x7a
+	IFT_X25MLP                        = 0x79
+	IFT_X25PLE                        = 0x28
+	IFT_XETHER                        = 0x1a
+	IGNBRK                            = 0x1
+	IGNCR                             = 0x80
+	IGNPAR                            = 0x4
+	IMAXBEL                           = 0x2000
+	INLCR                             = 0x40
+	INPCK                             = 0x10
+	IN_CLASSA_HOST                    = 0xffffff
+	IN_CLASSA_MAX                     = 0x80
+	IN_CLASSA_NET                     = 0xff000000
+	IN_CLASSA_NSHIFT                  = 0x18
+	IN_CLASSB_HOST                    = 0xffff
+	IN_CLASSB_MAX                     = 0x10000
+	IN_CLASSB_NET                     = 0xffff0000
+	IN_CLASSB_NSHIFT                  = 0x10
+	IN_CLASSC_HOST                    = 0xff
+	IN_CLASSC_NET                     = 0xffffff00
+	IN_CLASSC_NSHIFT                  = 0x8
+	IN_CLASSD_HOST                    = 0xfffffff
+	IN_CLASSD_NET                     = 0xf0000000
+	IN_CLASSD_NSHIFT                  = 0x1c
+	IN_LOOPBACKNET                    = 0x7f
+	IPPROTO_AH                        = 0x33
+	IPPROTO_CARP                      = 0x70
+	IPPROTO_DONE                      = 0x101
+	IPPROTO_DSTOPTS                   = 0x3c
+	IPPROTO_EGP                       = 0x8
+	IPPROTO_ENCAP                     = 0x62
+	IPPROTO_EON                       = 0x50
+	IPPROTO_ESP                       = 0x32
+	IPPROTO_ETHERIP                   = 0x61
+	IPPROTO_FRAGMENT                  = 0x2c
+	IPPROTO_GGP                       = 0x3
+	IPPROTO_GRE                       = 0x2f
+	IPPROTO_HOPOPTS                   = 0x0
+	IPPROTO_ICMP                      = 0x1
+	IPPROTO_ICMPV6                    = 0x3a
+	IPPROTO_IDP                       = 0x16
+	IPPROTO_IGMP                      = 0x2
+	IPPROTO_IP                        = 0x0
+	IPPROTO_IPCOMP                    = 0x6c
+	IPPROTO_IPIP                      = 0x4
+	IPPROTO_IPV4                      = 0x4
+	IPPROTO_IPV6                      = 0x29
+	IPPROTO_IPV6_ICMP                 = 0x3a
+	IPPROTO_MAX                       = 0x100
+	IPPROTO_MAXID                     = 0x34
+	IPPROTO_MOBILE                    = 0x37
+	IPPROTO_NONE                      = 0x3b
+	IPPROTO_PFSYNC                    = 0xf0
+	IPPROTO_PIM                       = 0x67
+	IPPROTO_PUP                       = 0xc
+	IPPROTO_RAW                       = 0xff
+	IPPROTO_ROUTING                   = 0x2b
+	IPPROTO_RSVP                      = 0x2e
+	IPPROTO_TCP                       = 0x6
+	IPPROTO_TP                        = 0x1d
+	IPPROTO_UDP                       = 0x11
+	IPPROTO_VRRP                      = 0x70
+	IPV6_CHECKSUM                     = 0x1a
+	IPV6_DEFAULT_MULTICAST_HOPS       = 0x1
+	IPV6_DEFAULT_MULTICAST_LOOP       = 0x1
+	IPV6_DEFHLIM                      = 0x40
+	IPV6_DONTFRAG                     = 0x3e
+	IPV6_DSTOPTS                      = 0x32
+	IPV6_FAITH                        = 0x1d
+	IPV6_FLOWINFO_MASK                = 0xffffff0f
+	IPV6_FLOWLABEL_MASK               = 0xffff0f00
+	IPV6_FRAGTTL                      = 0x78
+	IPV6_HLIMDEC                      = 0x1
+	IPV6_HOPLIMIT                     = 0x2f
+	IPV6_HOPOPTS                      = 0x31
+	IPV6_IPSEC_POLICY                 = 0x1c
+	IPV6_JOIN_GROUP                   = 0xc
+	IPV6_LEAVE_GROUP                  = 0xd
+	IPV6_MAXHLIM                      = 0xff
+	IPV6_MAXPACKET                    = 0xffff
+	IPV6_MMTU                         = 0x500
+	IPV6_MULTICAST_HOPS               = 0xa
+	IPV6_MULTICAST_IF                 = 0x9
+	IPV6_MULTICAST_LOOP               = 0xb
+	IPV6_NEXTHOP                      = 0x30
+	IPV6_PATHMTU                      = 0x2c
+	IPV6_PKTINFO                      = 0x2e
+	IPV6_PORTRANGE                    = 0xe
+	IPV6_PORTRANGE_DEFAULT            = 0x0
+	IPV6_PORTRANGE_HIGH               = 0x1
+	IPV6_PORTRANGE_LOW                = 0x2
+	IPV6_RECVDSTOPTS                  = 0x28
+	IPV6_RECVHOPLIMIT                 = 0x25
+	IPV6_RECVHOPOPTS                  = 0x27
+	IPV6_RECVPATHMTU                  = 0x2b
+	IPV6_RECVPKTINFO                  = 0x24
+	IPV6_RECVRTHDR                    = 0x26
+	IPV6_RECVTCLASS                   = 0x39
+	IPV6_RTHDR                        = 0x33
+	IPV6_RTHDRDSTOPTS                 = 0x23
+	IPV6_RTHDR_LOOSE                  = 0x0
+	IPV6_RTHDR_STRICT                 = 0x1
+	IPV6_RTHDR_TYPE_0                 = 0x0
+	IPV6_SOCKOPT_RESERVED1            = 0x3
+	IPV6_TCLASS                       = 0x3d
+	IPV6_UNICAST_HOPS                 = 0x4
+	IPV6_USE_MIN_MTU                  = 0x2a
+	IPV6_V6ONLY                       = 0x1b
+	IPV6_VERSION                      = 0x60
+	IPV6_VERSION_MASK                 = 0xf0
+	IP_ADD_MEMBERSHIP                 = 0xc
+	IP_DEFAULT_MULTICAST_LOOP         = 0x1
+	IP_DEFAULT_MULTICAST_TTL          = 0x1
+	IP_DF                             = 0x4000
+	IP_DROP_MEMBERSHIP                = 0xd
+	IP_EF                             = 0x8000
+	IP_ERRORMTU                       = 0x15
+	IP_HDRINCL                        = 0x2
+	IP_IPSEC_POLICY                   = 0x16
+	IP_MAXPACKET                      = 0xffff
+	IP_MAX_MEMBERSHIPS                = 0x14
+	IP_MF                             = 0x2000
+	IP_MINFRAGSIZE                    = 0x45
+	IP_MINTTL                         = 0x18
+	IP_MSS                            = 0x240
+	IP_MULTICAST_IF                   = 0x9
+	IP_MULTICAST_LOOP                 = 0xb
+	IP_MULTICAST_TTL                  = 0xa
+	IP_OFFMASK                        = 0x1fff
+	IP_OPTIONS                        = 0x1
+	IP_PORTRANGE                      = 0x13
+	IP_PORTRANGE_DEFAULT              = 0x0
+	IP_PORTRANGE_HIGH                 = 0x1
+	IP_PORTRANGE_LOW                  = 0x2
+	IP_RECVDSTADDR                    = 0x7
+	IP_RECVIF                         = 0x14
+	IP_RECVOPTS                       = 0x5
+	IP_RECVRETOPTS                    = 0x6
+	IP_RECVTTL                        = 0x17
+	IP_RETOPTS                        = 0x8
+	IP_RF                             = 0x8000
+	IP_TOS                            = 0x3
+	IP_TTL                            = 0x4
+	ISIG                              = 0x80
+	ISTRIP                            = 0x20
+	IXANY                             = 0x800
+	IXOFF                             = 0x400
+	IXON                              = 0x200
+	LOCK_EX                           = 0x2
+	LOCK_NB                           = 0x4
+	LOCK_SH                           = 0x1
+	LOCK_UN                           = 0x8
+	MSG_BCAST                         = 0x100
+	MSG_CMSG_CLOEXEC                  = 0x800
+	MSG_CONTROLMBUF                   = 0x2000000
+	MSG_CTRUNC                        = 0x20
+	MSG_DONTROUTE                     = 0x4
+	MSG_DONTWAIT                      = 0x80
+	MSG_EOR                           = 0x8
+	MSG_IOVUSRSPACE                   = 0x4000000
+	MSG_LENUSRSPACE                   = 0x8000000
+	MSG_MCAST                         = 0x200
+	MSG_NAMEMBUF                      = 0x1000000
+	MSG_NBIO                          = 0x1000
+	MSG_NOSIGNAL                      = 0x400
+	MSG_OOB                           = 0x1
+	MSG_PEEK                          = 0x2
+	MSG_TRUNC                         = 0x10
+	MSG_USERFLAGS                     = 0xffffff
+	MSG_WAITALL                       = 0x40
+	NAME_MAX                          = 0x1ff
+	NET_RT_DUMP                       = 0x1
+	NET_RT_FLAGS                      = 0x2
+	NET_RT_IFLIST                     = 0x5
+	NET_RT_MAXID                      = 0x6
+	NET_RT_OIFLIST                    = 0x4
+	NET_RT_OOIFLIST                   = 0x3
+	NOFLSH                            = 0x80000000
+	NOTE_ATTRIB                       = 0x8
+	NOTE_CHILD                        = 0x4
+	NOTE_DELETE                       = 0x1
+	NOTE_EXEC                         = 0x20000000
+	NOTE_EXIT                         = 0x80000000
+	NOTE_EXTEND                       = 0x4
+	NOTE_FORK                         = 0x40000000
+	NOTE_LINK                         = 0x10
+	NOTE_LOWAT                        = 0x1
+	NOTE_PCTRLMASK                    = 0xf0000000
+	NOTE_PDATAMASK                    = 0xfffff
+	NOTE_RENAME                       = 0x20
+	NOTE_REVOKE                       = 0x40
+	NOTE_TRACK                        = 0x1
+	NOTE_TRACKERR                     = 0x2
+	NOTE_WRITE                        = 0x2
+	OCRNL                             = 0x10
+	OFIOGETBMAP                       = 0xc004667a
+	ONLCR                             = 0x2
+	ONLRET                            = 0x40
+	ONOCR                             = 0x20
+	ONOEOT                            = 0x8
+	OPOST                             = 0x1
+	O_ACCMODE                         = 0x3
+	O_ALT_IO                          = 0x40000
+	O_APPEND                          = 0x8
+	O_ASYNC                           = 0x40
+	O_CLOEXEC                         = 0x400000
+	O_CREAT                           = 0x200
+	O_DIRECT                          = 0x80000
+	O_DIRECTORY                       = 0x200000
+	O_DSYNC                           = 0x10000
+	O_EXCL                            = 0x800
+	O_EXLOCK                          = 0x20
+	O_FSYNC                           = 0x80
+	O_NDELAY                          = 0x4
+	O_NOCTTY                          = 0x8000
+	O_NOFOLLOW                        = 0x100
+	O_NONBLOCK                        = 0x4
+	O_NOSIGPIPE                       = 0x1000000
+	O_RDONLY                          = 0x0
+	O_RDWR                            = 0x2
+	O_RSYNC                           = 0x20000
+	O_SHLOCK                          = 0x10
+	O_SYNC                            = 0x80
+	O_TRUNC                           = 0x400
+	O_WRONLY                          = 0x1
+	PARENB                            = 0x1000
+	PARMRK                            = 0x8
+	PARODD                            = 0x2000
+	PENDIN                            = 0x20000000
+	PRI_IOFLUSH                       = 0x7c
+	RLIMIT_AS                         = 0xa
+	RLIMIT_CORE                       = 0x4
+	RLIMIT_CPU                        = 0x0
+	RLIMIT_DATA                       = 0x2
+	RLIMIT_FSIZE                      = 0x1
+	RLIMIT_NOFILE                     = 0x8
+	RLIMIT_STACK                      = 0x3
+	RLIM_INFINITY                     = 0x7fffffffffffffff
+	RTAX_AUTHOR                       = 0x6
+	RTAX_BRD                          = 0x7
+	RTAX_DST                          = 0x0
+	RTAX_GATEWAY                      = 0x1
+	RTAX_GENMASK                      = 0x3
+	RTAX_IFA                          = 0x5
+	RTAX_IFP                          = 0x4
+	RTAX_MAX                          = 0x9
+	RTAX_NETMASK                      = 0x2
+	RTAX_TAG                          = 0x8
+	RTA_AUTHOR                        = 0x40
+	RTA_BRD                           = 0x80
+	RTA_DST                           = 0x1
+	RTA_GATEWAY                       = 0x2
+	RTA_GENMASK                       = 0x8
+	RTA_IFA                           = 0x20
+	RTA_IFP                           = 0x10
+	RTA_NETMASK                       = 0x4
+	RTA_TAG                           = 0x100
+	RTF_ANNOUNCE                      = 0x20000
+	RTF_BLACKHOLE                     = 0x1000
+	RTF_CLONED                        = 0x2000
+	RTF_CLONING                       = 0x100
+	RTF_DONE                          = 0x40
+	RTF_DYNAMIC                       = 0x10
+	RTF_GATEWAY                       = 0x2
+	RTF_HOST                          = 0x4
+	RTF_LLINFO                        = 0x400
+	RTF_MASK                          = 0x80
+	RTF_MODIFIED                      = 0x20
+	RTF_PROTO1                        = 0x8000
+	RTF_PROTO2                        = 0x4000
+	RTF_REJECT                        = 0x8
+	RTF_SRC                           = 0x10000
+	RTF_STATIC                        = 0x800
+	RTF_UP                            = 0x1
+	RTF_XRESOLVE                      = 0x200
+	RTM_ADD                           = 0x1
+	RTM_CHANGE                        = 0x3
+	RTM_CHGADDR                       = 0x15
+	RTM_DELADDR                       = 0xd
+	RTM_DELETE                        = 0x2
+	RTM_GET                           = 0x4
+	RTM_IEEE80211                     = 0x11
+	RTM_IFANNOUNCE                    = 0x10
+	RTM_IFINFO                        = 0x14
+	RTM_LLINFO_UPD                    = 0x13
+	RTM_LOCK                          = 0x8
+	RTM_LOSING                        = 0x5
+	RTM_MISS                          = 0x7
+	RTM_NEWADDR                       = 0xc
+	RTM_OIFINFO                       = 0xf
+	RTM_OLDADD                        = 0x9
+	RTM_OLDDEL                        = 0xa
+	RTM_OOIFINFO                      = 0xe
+	RTM_REDIRECT                      = 0x6
+	RTM_RESOLVE                       = 0xb
+	RTM_RTTUNIT                       = 0xf4240
+	RTM_SETGATE                       = 0x12
+	RTM_VERSION                       = 0x4
+	RTV_EXPIRE                        = 0x4
+	RTV_HOPCOUNT                      = 0x2
+	RTV_MTU                           = 0x1
+	RTV_RPIPE                         = 0x8
+	RTV_RTT                           = 0x40
+	RTV_RTTVAR                        = 0x80
+	RTV_SPIPE                         = 0x10
+	RTV_SSTHRESH                      = 0x20
+	RUSAGE_CHILDREN                   = -0x1
+	RUSAGE_SELF                       = 0x0
+	SCM_CREDS                         = 0x4
+	SCM_RIGHTS                        = 0x1
+	SCM_TIMESTAMP                     = 0x8
+	SHUT_RD                           = 0x0
+	SHUT_RDWR                         = 0x2
+	SHUT_WR                           = 0x1
+	SIOCADDMULTI                      = 0x80906931
+	SIOCADDRT                         = 0x8030720a
+	SIOCAIFADDR                       = 0x8040691a
+	SIOCALIFADDR                      = 0x8118691c
+	SIOCATMARK                        = 0x40047307
+	SIOCDELMULTI                      = 0x80906932
+	SIOCDELRT                         = 0x8030720b
+	SIOCDIFADDR                       = 0x80906919
+	SIOCDIFPHYADDR                    = 0x80906949
+	SIOCDLIFADDR                      = 0x8118691e
+	SIOCGDRVSPEC                      = 0xc01c697b
+	SIOCGETPFSYNC                     = 0xc09069f8
+	SIOCGETSGCNT                      = 0xc0147534
+	SIOCGETVIFCNT                     = 0xc0147533
+	SIOCGHIWAT                        = 0x40047301
+	SIOCGIFADDR                       = 0xc0906921
+	SIOCGIFADDRPREF                   = 0xc0946920
+	SIOCGIFALIAS                      = 0xc040691b
+	SIOCGIFBRDADDR                    = 0xc0906923
+	SIOCGIFCAP                        = 0xc0206976
+	SIOCGIFCONF                       = 0xc0086926
+	SIOCGIFDATA                       = 0xc0946985
+	SIOCGIFDLT                        = 0xc0906977
+	SIOCGIFDSTADDR                    = 0xc0906922
+	SIOCGIFFLAGS                      = 0xc0906911
+	SIOCGIFGENERIC                    = 0xc090693a
+	SIOCGIFMEDIA                      = 0xc0286936
+	SIOCGIFMETRIC                     = 0xc0906917
+	SIOCGIFMTU                        = 0xc090697e
+	SIOCGIFNETMASK                    = 0xc0906925
+	SIOCGIFPDSTADDR                   = 0xc0906948
+	SIOCGIFPSRCADDR                   = 0xc0906947
+	SIOCGLIFADDR                      = 0xc118691d
+	SIOCGLIFPHYADDR                   = 0xc118694b
+	SIOCGLINKSTR                      = 0xc01c6987
+	SIOCGLOWAT                        = 0x40047303
+	SIOCGPGRP                         = 0x40047309
+	SIOCGVH                           = 0xc0906983
+	SIOCIFCREATE                      = 0x8090697a
+	SIOCIFDESTROY                     = 0x80906979
+	SIOCIFGCLONERS                    = 0xc00c6978
+	SIOCINITIFADDR                    = 0xc0446984
+	SIOCSDRVSPEC                      = 0x801c697b
+	SIOCSETPFSYNC                     = 0x809069f7
+	SIOCSHIWAT                        = 0x80047300
+	SIOCSIFADDR                       = 0x8090690c
+	SIOCSIFADDRPREF                   = 0x8094691f
+	SIOCSIFBRDADDR                    = 0x80906913
+	SIOCSIFCAP                        = 0x80206975
+	SIOCSIFDSTADDR                    = 0x8090690e
+	SIOCSIFFLAGS                      = 0x80906910
+	SIOCSIFGENERIC                    = 0x80906939
+	SIOCSIFMEDIA                      = 0xc0906935
+	SIOCSIFMETRIC                     = 0x80906918
+	SIOCSIFMTU                        = 0x8090697f
+	SIOCSIFNETMASK                    = 0x80906916
+	SIOCSIFPHYADDR                    = 0x80406946
+	SIOCSLIFPHYADDR                   = 0x8118694a
+	SIOCSLINKSTR                      = 0x801c6988
+	SIOCSLOWAT                        = 0x80047302
+	SIOCSPGRP                         = 0x80047308
+	SIOCSVH                           = 0xc0906982
+	SIOCZIFDATA                       = 0xc0946986
+	SOCK_CLOEXEC                      = 0x10000000
+	SOCK_DGRAM                        = 0x2
+	SOCK_FLAGS_MASK                   = 0xf0000000
+	SOCK_NONBLOCK                     = 0x20000000
+	SOCK_NOSIGPIPE                    = 0x40000000
+	SOCK_RAW                          = 0x3
+	SOCK_RDM                          = 0x4
+	SOCK_SEQPACKET                    = 0x5
+	SOCK_STREAM                       = 0x1
+	SOL_SOCKET                        = 0xffff
+	SOMAXCONN                         = 0x80
+	SO_ACCEPTCONN                     = 0x2
+	SO_ACCEPTFILTER                   = 0x1000
+	SO_BROADCAST                      = 0x20
+	SO_DEBUG                          = 0x1
+	SO_DONTROUTE                      = 0x10
+	SO_ERROR                          = 0x1007
+	SO_KEEPALIVE                      = 0x8
+	SO_LINGER                         = 0x80
+	SO_NOHEADER                       = 0x100a
+	SO_NOSIGPIPE                      = 0x800
+	SO_OOBINLINE                      = 0x100
+	SO_OVERFLOWED                     = 0x1009
+	SO_RCVBUF                         = 0x1002
+	SO_RCVLOWAT                       = 0x1004
+	SO_RCVTIMEO                       = 0x100c
+	SO_REUSEADDR                      = 0x4
+	SO_REUSEPORT                      = 0x200
+	SO_SNDBUF                         = 0x1001
+	SO_SNDLOWAT                       = 0x1003
+	SO_SNDTIMEO                       = 0x100b
+	SO_TIMESTAMP                      = 0x2000
+	SO_TYPE                           = 0x1008
+	SO_USELOOPBACK                    = 0x40
+	SYSCTL_VERSION                    = 0x1000000
+	SYSCTL_VERS_0                     = 0x0
+	SYSCTL_VERS_1                     = 0x1000000
+	SYSCTL_VERS_MASK                  = 0xff000000
+	S_ARCH1                           = 0x10000
+	S_ARCH2                           = 0x20000
+	S_BLKSIZE                         = 0x200
+	S_IEXEC                           = 0x40
+	S_IFBLK                           = 0x6000
+	S_IFCHR                           = 0x2000
+	S_IFDIR                           = 0x4000
+	S_IFIFO                           = 0x1000
+	S_IFLNK                           = 0xa000
+	S_IFMT                            = 0xf000
+	S_IFREG                           = 0x8000
+	S_IFSOCK                          = 0xc000
+	S_IFWHT                           = 0xe000
+	S_IREAD                           = 0x100
+	S_IRGRP                           = 0x20
+	S_IROTH                           = 0x4
+	S_IRUSR                           = 0x100
+	S_IRWXG                           = 0x38
+	S_IRWXO                           = 0x7
+	S_IRWXU                           = 0x1c0
+	S_ISGID                           = 0x400
+	S_ISTXT                           = 0x200
+	S_ISUID                           = 0x800
+	S_ISVTX                           = 0x200
+	S_IWGRP                           = 0x10
+	S_IWOTH                           = 0x2
+	S_IWRITE                          = 0x80
+	S_IWUSR                           = 0x80
+	S_IXGRP                           = 0x8
+	S_IXOTH                           = 0x1
+	S_IXUSR                           = 0x40
+	TCIFLUSH                          = 0x1
+	TCIOFLUSH                         = 0x3
+	TCOFLUSH                          = 0x2
+	TCP_CONGCTL                       = 0x20
+	TCP_KEEPCNT                       = 0x6
+	TCP_KEEPIDLE                      = 0x3
+	TCP_KEEPINIT                      = 0x7
+	TCP_KEEPINTVL                     = 0x5
+	TCP_MAXBURST                      = 0x4
+	TCP_MAXSEG                        = 0x2
+	TCP_MAXWIN                        = 0xffff
+	TCP_MAX_WINSHIFT                  = 0xe
+	TCP_MD5SIG                        = 0x10
+	TCP_MINMSS                        = 0xd8
+	TCP_MSS                           = 0x218
+	TCP_NODELAY                       = 0x1
+	TCSAFLUSH                         = 0x2
+	TIOCCBRK                          = 0x2000747a
+	TIOCCDTR                          = 0x20007478
+	TIOCCONS                          = 0x80047462
+	TIOCDCDTIMESTAMP                  = 0x400c7458
+	TIOCDRAIN                         = 0x2000745e
+	TIOCEXCL                          = 0x2000740d
+	TIOCEXT                           = 0x80047460
+	TIOCFLAG_CDTRCTS                  = 0x10
+	TIOCFLAG_CLOCAL                   = 0x2
+	TIOCFLAG_CRTSCTS                  = 0x4
+	TIOCFLAG_MDMBUF                   = 0x8
+	TIOCFLAG_SOFTCAR                  = 0x1
+	TIOCFLUSH                         = 0x80047410
+	TIOCGETA                          = 0x402c7413
+	TIOCGETD                          = 0x4004741a
+	TIOCGFLAGS                        = 0x4004745d
+	TIOCGLINED                        = 0x40207442
+	TIOCGPGRP                         = 0x40047477
+	TIOCGQSIZE                        = 0x40047481
+	TIOCGRANTPT                       = 0x20007447
+	TIOCGSID                          = 0x40047463
+	TIOCGSIZE                         = 0x40087468
+	TIOCGWINSZ                        = 0x40087468
+	TIOCMBIC                          = 0x8004746b
+	TIOCMBIS                          = 0x8004746c
+	TIOCMGET                          = 0x4004746a
+	TIOCMSET                          = 0x8004746d
+	TIOCM_CAR                         = 0x40
+	TIOCM_CD                          = 0x40
+	TIOCM_CTS                         = 0x20
+	TIOCM_DSR                         = 0x100
+	TIOCM_DTR                         = 0x2
+	TIOCM_LE                          = 0x1
+	TIOCM_RI                          = 0x80
+	TIOCM_RNG                         = 0x80
+	TIOCM_RTS                         = 0x4
+	TIOCM_SR                          = 0x10
+	TIOCM_ST                          = 0x8
+	TIOCNOTTY                         = 0x20007471
+	TIOCNXCL                          = 0x2000740e
+	TIOCOUTQ                          = 0x40047473
+	TIOCPKT                           = 0x80047470
+	TIOCPKT_DATA                      = 0x0
+	TIOCPKT_DOSTOP                    = 0x20
+	TIOCPKT_FLUSHREAD                 = 0x1
+	TIOCPKT_FLUSHWRITE                = 0x2
+	TIOCPKT_IOCTL                     = 0x40
+	TIOCPKT_NOSTOP                    = 0x10
+	TIOCPKT_START                     = 0x8
+	TIOCPKT_STOP                      = 0x4
+	TIOCPTMGET                        = 0x48087446
+	TIOCPTSNAME                       = 0x48087448
+	TIOCRCVFRAME                      = 0x80047445
+	TIOCREMOTE                        = 0x80047469
+	TIOCSBRK                          = 0x2000747b
+	TIOCSCTTY                         = 0x20007461
+	TIOCSDTR                          = 0x20007479
+	TIOCSETA                          = 0x802c7414
+	TIOCSETAF                         = 0x802c7416
+	TIOCSETAW                         = 0x802c7415
+	TIOCSETD                          = 0x8004741b
+	TIOCSFLAGS                        = 0x8004745c
+	TIOCSIG                           = 0x2000745f
+	TIOCSLINED                        = 0x80207443
+	TIOCSPGRP                         = 0x80047476
+	TIOCSQSIZE                        = 0x80047480
+	TIOCSSIZE                         = 0x80087467
+	TIOCSTART                         = 0x2000746e
+	TIOCSTAT                          = 0x80047465
+	TIOCSTI                           = 0x80017472
+	TIOCSTOP                          = 0x2000746f
+	TIOCSWINSZ                        = 0x80087467
+	TIOCUCNTL                         = 0x80047466
+	TIOCXMTFRAME                      = 0x80047444
+	TOSTOP                            = 0x400000
+	VDISCARD                          = 0xf
+	VDSUSP                            = 0xb
+	VEOF                              = 0x0
+	VEOL                              = 0x1
+	VEOL2                             = 0x2
+	VERASE                            = 0x3
+	VINTR                             = 0x8
+	VKILL                             = 0x5
+	VLNEXT                            = 0xe
+	VMIN                              = 0x10
+	VQUIT                             = 0x9
+	VREPRINT                          = 0x6
+	VSTART                            = 0xc
+	VSTATUS                           = 0x12
+	VSTOP                             = 0xd
+	VSUSP                             = 0xa
+	VTIME                             = 0x11
+	VWERASE                           = 0x4
+	WALL                              = 0x8
+	WALLSIG                           = 0x8
+	WALTSIG                           = 0x4
+	WCLONE                            = 0x4
+	WCOREFLAG                         = 0x80
+	WNOHANG                           = 0x1
+	WNOWAIT                           = 0x10000
+	WNOZOMBIE                         = 0x20000
+	WOPTSCHECKED                      = 0x40000
+	WSTOPPED                          = 0x7f
+	WUNTRACED                         = 0x2
+)
+
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x30)
+	EADDRNOTAVAIL   = Errno(0x31)
+	EAFNOSUPPORT    = Errno(0x2f)
+	EAGAIN          = Errno(0x23)
+	EALREADY        = Errno(0x25)
+	EAUTH           = Errno(0x50)
+	EBADF           = Errno(0x9)
+	EBADMSG         = Errno(0x58)
+	EBADRPC         = Errno(0x48)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x57)
+	ECHILD          = Errno(0xa)
+	ECONNABORTED    = Errno(0x35)
+	ECONNREFUSED    = Errno(0x3d)
+	ECONNRESET      = Errno(0x36)
+	EDEADLK         = Errno(0xb)
+	EDESTADDRREQ    = Errno(0x27)
+	EDOM            = Errno(0x21)
+	EDQUOT          = Errno(0x45)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EFTYPE          = Errno(0x4f)
+	EHOSTDOWN       = Errno(0x40)
+	EHOSTUNREACH    = Errno(0x41)
+	EIDRM           = Errno(0x52)
+	EILSEQ          = Errno(0x55)
+	EINPROGRESS     = Errno(0x24)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x38)
+	EISDIR          = Errno(0x15)
+	ELAST           = Errno(0x60)
+	ELOOP           = Errno(0x3e)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x28)
+	EMULTIHOP       = Errno(0x5e)
+	ENAMETOOLONG    = Errno(0x3f)
+	ENEEDAUTH       = Errno(0x51)
+	ENETDOWN        = Errno(0x32)
+	ENETRESET       = Errno(0x34)
+	ENETUNREACH     = Errno(0x33)
+	ENFILE          = Errno(0x17)
+	ENOATTR         = Errno(0x5d)
+	ENOBUFS         = Errno(0x37)
+	ENODATA         = Errno(0x59)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOLCK          = Errno(0x4d)
+	ENOLINK         = Errno(0x5f)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x53)
+	ENOPROTOOPT     = Errno(0x2a)
+	ENOSPC          = Errno(0x1c)
+	ENOSR           = Errno(0x5a)
+	ENOSTR          = Errno(0x5b)
+	ENOSYS          = Errno(0x4e)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x39)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x42)
+	ENOTSOCK        = Errno(0x26)
+	ENOTSUP         = Errno(0x56)
+	ENOTTY          = Errno(0x19)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x2d)
+	EOVERFLOW       = Errno(0x54)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x2e)
+	EPIPE           = Errno(0x20)
+	EPROCLIM        = Errno(0x43)
+	EPROCUNAVAIL    = Errno(0x4c)
+	EPROGMISMATCH   = Errno(0x4b)
+	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTO          = Errno(0x60)
+	EPROTONOSUPPORT = Errno(0x2b)
+	EPROTOTYPE      = Errno(0x29)
+	ERANGE          = Errno(0x22)
+	EREMOTE         = Errno(0x47)
+	EROFS           = Errno(0x1e)
+	ERPCMISMATCH    = Errno(0x49)
+	ESHUTDOWN       = Errno(0x3a)
+	ESOCKTNOSUPPORT = Errno(0x2c)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESTALE          = Errno(0x46)
+	ETIME           = Errno(0x5c)
+	ETIMEDOUT       = Errno(0x3c)
+	ETOOMANYREFS    = Errno(0x3b)
+	ETXTBSY         = Errno(0x1a)
+	EUSERS          = Errno(0x44)
+	EWOULDBLOCK     = Errno(0x23)
+	EXDEV           = Errno(0x12)
+)
+
+// Signals
+const (
+	SIGABRT   = Signal(0x6)
+	SIGALRM   = Signal(0xe)
+	SIGBUS    = Signal(0xa)
+	SIGCHLD   = Signal(0x14)
+	SIGCONT   = Signal(0x13)
+	SIGEMT    = Signal(0x7)
+	SIGFPE    = Signal(0x8)
+	SIGHUP    = Signal(0x1)
+	SIGILL    = Signal(0x4)
+	SIGINFO   = Signal(0x1d)
+	SIGINT    = Signal(0x2)
+	SIGIO     = Signal(0x17)
+	SIGIOT    = Signal(0x6)
+	SIGKILL   = Signal(0x9)
+	SIGPIPE   = Signal(0xd)
+	SIGPROF   = Signal(0x1b)
+	SIGPWR    = Signal(0x20)
+	SIGQUIT   = Signal(0x3)
+	SIGSEGV   = Signal(0xb)
+	SIGSTOP   = Signal(0x11)
+	SIGSYS    = Signal(0xc)
+	SIGTERM   = Signal(0xf)
+	SIGTRAP   = Signal(0x5)
+	SIGTSTP   = Signal(0x12)
+	SIGTTIN   = Signal(0x15)
+	SIGTTOU   = Signal(0x16)
+	SIGURG    = Signal(0x10)
+	SIGUSR1   = Signal(0x1e)
+	SIGUSR2   = Signal(0x1f)
+	SIGVTALRM = Signal(0x1a)
+	SIGWINCH  = Signal(0x1c)
+	SIGXCPU   = Signal(0x18)
+	SIGXFSZ   = Signal(0x19)
+)
+
+// Error table
+var errors = [...]string{
+	1:  "operation not permitted",
+	2:  "no such file or directory",
+	3:  "no such process",
+	4:  "interrupted system call",
+	5:  "input/output error",
+	6:  "device not configured",
+	7:  "argument list too long",
+	8:  "exec format error",
+	9:  "bad file descriptor",
+	10: "no child processes",
+	11: "resource deadlock avoided",
+	12: "cannot allocate memory",
+	13: "permission denied",
+	14: "bad address",
+	15: "block device required",
+	16: "device busy",
+	17: "file exists",
+	18: "cross-device link",
+	19: "operation not supported by device",
+	20: "not a directory",
+	21: "is a directory",
+	22: "invalid argument",
+	23: "too many open files in system",
+	24: "too many open files",
+	25: "inappropriate ioctl for device",
+	26: "text file busy",
+	27: "file too large",
+	28: "no space left on device",
+	29: "illegal seek",
+	30: "read-only file system",
+	31: "too many links",
+	32: "broken pipe",
+	33: "numerical argument out of domain",
+	34: "result too large or too small",
+	35: "resource temporarily unavailable",
+	36: "operation now in progress",
+	37: "operation already in progress",
+	38: "socket operation on non-socket",
+	39: "destination address required",
+	40: "message too long",
+	41: "protocol wrong type for socket",
+	42: "protocol option not available",
+	43: "protocol not supported",
+	44: "socket type not supported",
+	45: "operation not supported",
+	46: "protocol family not supported",
+	47: "address family not supported by protocol family",
+	48: "address already in use",
+	49: "can't assign requested address",
+	50: "network is down",
+	51: "network is unreachable",
+	52: "network dropped connection on reset",
+	53: "software caused connection abort",
+	54: "connection reset by peer",
+	55: "no buffer space available",
+	56: "socket is already connected",
+	57: "socket is not connected",
+	58: "can't send after socket shutdown",
+	59: "too many references: can't splice",
+	60: "connection timed out",
+	61: "connection refused",
+	62: "too many levels of symbolic links",
+	63: "file name too long",
+	64: "host is down",
+	65: "no route to host",
+	66: "directory not empty",
+	67: "too many processes",
+	68: "too many users",
+	69: "disc quota exceeded",
+	70: "stale NFS file handle",
+	71: "too many levels of remote in path",
+	72: "RPC struct is bad",
+	73: "RPC version wrong",
+	74: "RPC prog. not avail",
+	75: "program version wrong",
+	76: "bad procedure for program",
+	77: "no locks available",
+	78: "function not implemented",
+	79: "inappropriate file type or format",
+	80: "authentication error",
+	81: "need authenticator",
+	82: "identifier removed",
+	83: "no message of desired type",
+	84: "value too large to be stored in data type",
+	85: "illegal byte sequence",
+	86: "not supported",
+	87: "operation Canceled",
+	88: "bad or Corrupt message",
+	89: "no message available",
+	90: "no STREAM resources",
+	91: "not a STREAM",
+	92: "STREAM ioctl timeout",
+	93: "attribute not found",
+	94: "multihop attempted",
+	95: "link has been severed",
+	96: "protocol error",
+}
+
+// Signal table
+var signals = [...]string{
+	1:  "hangup",
+	2:  "interrupt",
+	3:  "quit",
+	4:  "illegal instruction",
+	5:  "trace/BPT trap",
+	6:  "abort trap",
+	7:  "EMT trap",
+	8:  "floating point exception",
+	9:  "killed",
+	10: "bus error",
+	11: "segmentation fault",
+	12: "bad system call",
+	13: "broken pipe",
+	14: "alarm clock",
+	15: "terminated",
+	16: "urgent I/O condition",
+	17: "stopped (signal)",
+	18: "stopped",
+	19: "continued",
+	20: "child exited",
+	21: "stopped (tty input)",
+	22: "stopped (tty output)",
+	23: "I/O possible",
+	24: "cputime limit exceeded",
+	25: "filesize limit exceeded",
+	26: "virtual timer expired",
+	27: "profiling timer expired",
+	28: "window size changes",
+	29: "information request",
+	30: "user defined signal 1",
+	31: "user defined signal 2",
+	32: "power fail/restart",
+}
diff --git a/src/pkg/syscall/zerrors_openbsd_386.go b/src/pkg/syscall/zerrors_openbsd_386.go
index 11074d5..5330d15 100644
--- a/src/pkg/syscall/zerrors_openbsd_386.go
+++ b/src/pkg/syscall/zerrors_openbsd_386.go
@@ -45,6 +45,29 @@ const (
 	ARPHRD_FRELAY                     = 0xf
 	ARPHRD_IEEE1394                   = 0x18
 	ARPHRD_IEEE802                    = 0x6
+	B0                                = 0x0
+	B110                              = 0x6e
+	B115200                           = 0x1c200
+	B1200                             = 0x4b0
+	B134                              = 0x86
+	B14400                            = 0x3840
+	B150                              = 0x96
+	B1800                             = 0x708
+	B19200                            = 0x4b00
+	B200                              = 0xc8
+	B230400                           = 0x38400
+	B2400                             = 0x960
+	B28800                            = 0x7080
+	B300                              = 0x12c
+	B38400                            = 0x9600
+	B4800                             = 0x12c0
+	B50                               = 0x32
+	B57600                            = 0xe100
+	B600                              = 0x258
+	B7200                             = 0x1c20
+	B75                               = 0x4b
+	B76800                            = 0x12c00
+	B9600                             = 0x2580
 	BIOCFLUSH                         = 0x20004268
 	BIOCGBLEN                         = 0x40044266
 	BIOCGDIRFILT                      = 0x4004427c
@@ -116,12 +139,28 @@ const (
 	BPF_TXA                           = 0x80
 	BPF_W                             = 0x0
 	BPF_X                             = 0x8
+	BRKINT                            = 0x2
+	CFLUSH                            = 0xf
+	CLOCAL                            = 0x8000
+	CREAD                             = 0x800
+	CS5                               = 0x0
+	CS6                               = 0x100
+	CS7                               = 0x200
+	CS8                               = 0x300
+	CSIZE                             = 0x300
+	CSTART                            = 0x11
+	CSTATUS                           = 0xff
+	CSTOP                             = 0x13
+	CSTOPB                            = 0x400
+	CSUSP                             = 0x1a
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
+	DIOCOSFPFLUSH                     = 0x2000444e
 	DLT_ARCNET                        = 0x7
 	DLT_ATM_RFC1483                   = 0xb
 	DLT_AX25                          = 0x3
 	DLT_CHAOS                         = 0x5
+	DLT_C_HDLC                        = 0x68
 	DLT_EN10MB                        = 0x1
 	DLT_EN3MB                         = 0x2
 	DLT_ENC                           = 0xd
@@ -137,6 +176,7 @@ const (
 	DLT_PPP                           = 0x9
 	DLT_PPP_BSDOS                     = 0x10
 	DLT_PPP_ETHER                     = 0x33
+	DLT_PPP_SERIAL                    = 0x32
 	DLT_PRONET                        = 0x4
 	DLT_RAW                           = 0xe
 	DLT_SLIP                          = 0x8
@@ -156,10 +196,6 @@ const (
 	ECHOKE                            = 0x1
 	ECHONL                            = 0x10
 	ECHOPRT                           = 0x20
-	EFER_LMA                          = 0x400
-	EFER_LME                          = 0x100
-	EFER_NXE                          = 0x800
-	EFER_SCE                          = 0x1
 	EMT_TAGOVF                        = 0x1
 	EMUL_ENABLED                      = 0x1
 	EMUL_NATIVE                       = 0x2
@@ -385,6 +421,7 @@ const (
 	EXTPROC                           = 0x800
 	FD_CLOEXEC                        = 0x1
 	FD_SETSIZE                        = 0x400
+	FLUSHO                            = 0x800000
 	F_DUPFD                           = 0x0
 	F_DUPFD_CLOEXEC                   = 0xa
 	F_GETFD                           = 0x1
@@ -400,6 +437,12 @@ const (
 	F_SETOWN                          = 0x6
 	F_UNLCK                           = 0x2
 	F_WRLCK                           = 0x3
+	HUPCL                             = 0x4000
+	ICANON                            = 0x100
+	ICRNL                             = 0x100
+	IEXTEN                            = 0x400
+	IFAN_ARRIVAL                      = 0x0
+	IFAN_DEPARTURE                    = 0x1
 	IFA_ROUTE                         = 0x1
 	IFF_ALLMULTI                      = 0x200
 	IFF_BROADCAST                     = 0x2
@@ -642,6 +685,12 @@ const (
 	IFT_X25MLP                        = 0x79
 	IFT_X25PLE                        = 0x28
 	IFT_XETHER                        = 0x1a
+	IGNBRK                            = 0x1
+	IGNCR                             = 0x80
+	IGNPAR                            = 0x4
+	IMAXBEL                           = 0x2000
+	INLCR                             = 0x40
+	INPCK                             = 0x10
 	IN_CLASSA_HOST                    = 0xffffff
 	IN_CLASSA_MAX                     = 0x80
 	IN_CLASSA_NET                     = 0xff000000
@@ -762,6 +811,7 @@ const (
 	IP_ESP_TRANS_LEVEL                = 0x15
 	IP_HDRINCL                        = 0x2
 	IP_IPCOMP_LEVEL                   = 0x1d
+	IP_IPSECFLOWINFO                  = 0x24
 	IP_IPSEC_LOCAL_AUTH               = 0x1b
 	IP_IPSEC_LOCAL_CRED               = 0x19
 	IP_IPSEC_LOCAL_ID                 = 0x17
@@ -796,17 +846,23 @@ const (
 	IP_RTABLE                         = 0x1021
 	IP_TOS                            = 0x3
 	IP_TTL                            = 0x4
+	ISIG                              = 0x80
+	ISTRIP                            = 0x20
+	IXANY                             = 0x800
+	IXOFF                             = 0x400
+	IXON                              = 0x200
+	LCNT_OVERLOAD_FLUSH               = 0x6
 	LOCK_EX                           = 0x2
 	LOCK_NB                           = 0x4
 	LOCK_SH                           = 0x1
 	LOCK_UN                           = 0x8
-	MAP_ET_KVAGUARD                   = 0x10
 	MSG_BCAST                         = 0x100
 	MSG_CTRUNC                        = 0x20
 	MSG_DONTROUTE                     = 0x4
 	MSG_DONTWAIT                      = 0x80
 	MSG_EOR                           = 0x8
 	MSG_MCAST                         = 0x200
+	MSG_NOSIGNAL                      = 0x400
 	MSG_OOB                           = 0x1
 	MSG_PEEK                          = 0x2
 	MSG_TRUNC                         = 0x10
@@ -818,6 +874,7 @@ const (
 	NET_RT_MAXID                      = 0x6
 	NET_RT_STATS                      = 0x4
 	NET_RT_TABLE                      = 0x5
+	NOFLSH                            = 0x80000000
 	NOTE_ATTRIB                       = 0x8
 	NOTE_CHILD                        = 0x4
 	NOTE_DELETE                       = 0x1
@@ -836,6 +893,12 @@ const (
 	NOTE_TRACKERR                     = 0x2
 	NOTE_TRUNCATE                     = 0x80
 	NOTE_WRITE                        = 0x2
+	OCRNL                             = 0x10
+	ONLCR                             = 0x2
+	ONLRET                            = 0x80
+	ONOCR                             = 0x40
+	ONOEOT                            = 0x8
+	OPOST                             = 0x1
 	O_ACCMODE                         = 0x3
 	O_APPEND                          = 0x8
 	O_ASYNC                           = 0x40
@@ -857,6 +920,12 @@ const (
 	O_SYNC                            = 0x80
 	O_TRUNC                           = 0x400
 	O_WRONLY                          = 0x1
+	PARENB                            = 0x1000
+	PARMRK                            = 0x8
+	PARODD                            = 0x2000
+	PENDIN                            = 0x20000000
+	PF_FLUSH                          = 0x1
+	PT_MASK                           = 0x3ff000
 	RLIMIT_CORE                       = 0x4
 	RLIMIT_CPU                        = 0x0
 	RLIMIT_DATA                       = 0x2
@@ -893,10 +962,9 @@ const (
 	RTF_CLONING                       = 0x100
 	RTF_DONE                          = 0x40
 	RTF_DYNAMIC                       = 0x10
-	RTF_FMASK                         = 0x8f808
+	RTF_FMASK                         = 0xf808
 	RTF_GATEWAY                       = 0x2
 	RTF_HOST                          = 0x4
-	RTF_JUMBO                         = 0x80000
 	RTF_LLINFO                        = 0x400
 	RTF_MASK                          = 0x80
 	RTF_MODIFIED                      = 0x20
@@ -942,7 +1010,6 @@ const (
 	RUSAGE_CHILDREN                   = -0x1
 	RUSAGE_SELF                       = 0x0
 	RUSAGE_THREAD                     = 0x1
-	SCM_CREDS                         = 0x2
 	SCM_RIGHTS                        = 0x1
 	SCM_TIMESTAMP                     = 0x4
 	SHUT_RD                           = 0x0
@@ -996,7 +1063,6 @@ const (
 	SIOCGETPFSYNC                     = 0xc02069f8
 	SIOCGETSGCNT                      = 0xc0147534
 	SIOCGETVIFCNT                     = 0xc0147533
-	SIOCGETVLANPRIO                   = 0xc0206990
 	SIOCGHIWAT                        = 0x40047301
 	SIOCGIFADDR                       = 0xc0206921
 	SIOCGIFASYNCMAP                   = 0xc020697c
@@ -1034,7 +1100,6 @@ const (
 	SIOCSETLABEL                      = 0x80206999
 	SIOCSETPFLOW                      = 0x802069fd
 	SIOCSETPFSYNC                     = 0x802069f7
-	SIOCSETVLANPRIO                   = 0x8020698f
 	SIOCSHIWAT                        = 0x80047300
 	SIOCSIFADDR                       = 0x8020690c
 	SIOCSIFASYNCMAP                   = 0x8020697d
@@ -1073,7 +1138,6 @@ const (
 	SO_DEBUG                          = 0x1
 	SO_DONTROUTE                      = 0x10
 	SO_ERROR                          = 0x1007
-	SO_JUMBO                          = 0x400
 	SO_KEEPALIVE                      = 0x8
 	SO_LINGER                         = 0x80
 	SO_NETPROC                        = 0x1020
@@ -1092,6 +1156,9 @@ const (
 	SO_TIMESTAMP                      = 0x800
 	SO_TYPE                           = 0x1008
 	SO_USELOOPBACK                    = 0x40
+	TCIFLUSH                          = 0x1
+	TCIOFLUSH                         = 0x3
+	TCOFLUSH                          = 0x2
 	TCP_MAXBURST                      = 0x4
 	TCP_MAXSEG                        = 0x2
 	TCP_MAXWIN                        = 0xffff
@@ -1102,6 +1169,7 @@ const (
 	TCP_NODELAY                       = 0x1
 	TCP_NSTATES                       = 0xb
 	TCP_SACK_ENABLE                   = 0x8
+	TCSAFLUSH                         = 0x2
 	TIOCCBRK                          = 0x2000747a
 	TIOCCDTR                          = 0x20007478
 	TIOCCONS                          = 0x80047462
@@ -1167,6 +1235,25 @@ const (
 	TIOCSTSTAMP                       = 0x8008745a
 	TIOCSWINSZ                        = 0x80087467
 	TIOCUCNTL                         = 0x80047466
+	TOSTOP                            = 0x400000
+	VDISCARD                          = 0xf
+	VDSUSP                            = 0xb
+	VEOF                              = 0x0
+	VEOL                              = 0x1
+	VEOL2                             = 0x2
+	VERASE                            = 0x3
+	VINTR                             = 0x8
+	VKILL                             = 0x5
+	VLNEXT                            = 0xe
+	VMIN                              = 0x10
+	VQUIT                             = 0x9
+	VREPRINT                          = 0x6
+	VSTART                            = 0xc
+	VSTATUS                           = 0x12
+	VSTOP                             = 0xd
+	VSUSP                             = 0xa
+	VTIME                             = 0x11
+	VWERASE                           = 0x4
 	WALTSIG                           = 0x4
 	WCONTINUED                        = 0x8
 	WCOREFLAG                         = 0x80
diff --git a/src/pkg/syscall/zerrors_openbsd_amd64.go b/src/pkg/syscall/zerrors_openbsd_amd64.go
index 91ea065..5a7edd3 100644
--- a/src/pkg/syscall/zerrors_openbsd_amd64.go
+++ b/src/pkg/syscall/zerrors_openbsd_amd64.go
@@ -45,6 +45,29 @@ const (
 	ARPHRD_FRELAY                     = 0xf
 	ARPHRD_IEEE1394                   = 0x18
 	ARPHRD_IEEE802                    = 0x6
+	B0                                = 0x0
+	B110                              = 0x6e
+	B115200                           = 0x1c200
+	B1200                             = 0x4b0
+	B134                              = 0x86
+	B14400                            = 0x3840
+	B150                              = 0x96
+	B1800                             = 0x708
+	B19200                            = 0x4b00
+	B200                              = 0xc8
+	B230400                           = 0x38400
+	B2400                             = 0x960
+	B28800                            = 0x7080
+	B300                              = 0x12c
+	B38400                            = 0x9600
+	B4800                             = 0x12c0
+	B50                               = 0x32
+	B57600                            = 0xe100
+	B600                              = 0x258
+	B7200                             = 0x1c20
+	B75                               = 0x4b
+	B76800                            = 0x12c00
+	B9600                             = 0x2580
 	BIOCFLUSH                         = 0x20004268
 	BIOCGBLEN                         = 0x40044266
 	BIOCGDIRFILT                      = 0x4004427c
@@ -116,12 +139,30 @@ const (
 	BPF_TXA                           = 0x80
 	BPF_W                             = 0x0
 	BPF_X                             = 0x8
+	BRKINT                            = 0x2
+	CCR0_FLUSH                        = 0x10
+	CFLUSH                            = 0xf
+	CLOCAL                            = 0x8000
+	CPUID_CFLUSH                      = 0x80000
+	CREAD                             = 0x800
+	CS5                               = 0x0
+	CS6                               = 0x100
+	CS7                               = 0x200
+	CS8                               = 0x300
+	CSIZE                             = 0x300
+	CSTART                            = 0x11
+	CSTATUS                           = 0xff
+	CSTOP                             = 0x13
+	CSTOPB                            = 0x400
+	CSUSP                             = 0x1a
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
+	DIOCOSFPFLUSH                     = 0x2000444e
 	DLT_ARCNET                        = 0x7
 	DLT_ATM_RFC1483                   = 0xb
 	DLT_AX25                          = 0x3
 	DLT_CHAOS                         = 0x5
+	DLT_C_HDLC                        = 0x68
 	DLT_EN10MB                        = 0x1
 	DLT_EN3MB                         = 0x2
 	DLT_ENC                           = 0xd
@@ -137,6 +178,7 @@ const (
 	DLT_PPP                           = 0x9
 	DLT_PPP_BSDOS                     = 0x10
 	DLT_PPP_ETHER                     = 0x33
+	DLT_PPP_SERIAL                    = 0x32
 	DLT_PRONET                        = 0x4
 	DLT_RAW                           = 0xe
 	DLT_SLIP                          = 0x8
@@ -385,6 +427,7 @@ const (
 	EXTPROC                           = 0x800
 	FD_CLOEXEC                        = 0x1
 	FD_SETSIZE                        = 0x400
+	FLUSHO                            = 0x800000
 	F_DUPFD                           = 0x0
 	F_DUPFD_CLOEXEC                   = 0xa
 	F_GETFD                           = 0x1
@@ -400,6 +443,12 @@ const (
 	F_SETOWN                          = 0x6
 	F_UNLCK                           = 0x2
 	F_WRLCK                           = 0x3
+	HUPCL                             = 0x4000
+	ICANON                            = 0x100
+	ICRNL                             = 0x100
+	IEXTEN                            = 0x400
+	IFAN_ARRIVAL                      = 0x0
+	IFAN_DEPARTURE                    = 0x1
 	IFA_ROUTE                         = 0x1
 	IFF_ALLMULTI                      = 0x200
 	IFF_BROADCAST                     = 0x2
@@ -642,6 +691,12 @@ const (
 	IFT_X25MLP                        = 0x79
 	IFT_X25PLE                        = 0x28
 	IFT_XETHER                        = 0x1a
+	IGNBRK                            = 0x1
+	IGNCR                             = 0x80
+	IGNPAR                            = 0x4
+	IMAXBEL                           = 0x2000
+	INLCR                             = 0x40
+	INPCK                             = 0x10
 	IN_CLASSA_HOST                    = 0xffffff
 	IN_CLASSA_MAX                     = 0x80
 	IN_CLASSA_NET                     = 0xff000000
@@ -762,6 +817,7 @@ const (
 	IP_ESP_TRANS_LEVEL                = 0x15
 	IP_HDRINCL                        = 0x2
 	IP_IPCOMP_LEVEL                   = 0x1d
+	IP_IPSECFLOWINFO                  = 0x24
 	IP_IPSEC_LOCAL_AUTH               = 0x1b
 	IP_IPSEC_LOCAL_CRED               = 0x19
 	IP_IPSEC_LOCAL_ID                 = 0x17
@@ -796,17 +852,23 @@ const (
 	IP_RTABLE                         = 0x1021
 	IP_TOS                            = 0x3
 	IP_TTL                            = 0x4
+	ISIG                              = 0x80
+	ISTRIP                            = 0x20
+	IXANY                             = 0x800
+	IXOFF                             = 0x400
+	IXON                              = 0x200
+	LCNT_OVERLOAD_FLUSH               = 0x6
 	LOCK_EX                           = 0x2
 	LOCK_NB                           = 0x4
 	LOCK_SH                           = 0x1
 	LOCK_UN                           = 0x8
-	MAP_ET_KVAGUARD                   = 0x10
 	MSG_BCAST                         = 0x100
 	MSG_CTRUNC                        = 0x20
 	MSG_DONTROUTE                     = 0x4
 	MSG_DONTWAIT                      = 0x80
 	MSG_EOR                           = 0x8
 	MSG_MCAST                         = 0x200
+	MSG_NOSIGNAL                      = 0x400
 	MSG_OOB                           = 0x1
 	MSG_PEEK                          = 0x2
 	MSG_TRUNC                         = 0x10
@@ -818,6 +880,7 @@ const (
 	NET_RT_MAXID                      = 0x6
 	NET_RT_STATS                      = 0x4
 	NET_RT_TABLE                      = 0x5
+	NOFLSH                            = 0x80000000
 	NOTE_ATTRIB                       = 0x8
 	NOTE_CHILD                        = 0x4
 	NOTE_DELETE                       = 0x1
@@ -836,6 +899,12 @@ const (
 	NOTE_TRACKERR                     = 0x2
 	NOTE_TRUNCATE                     = 0x80
 	NOTE_WRITE                        = 0x2
+	OCRNL                             = 0x10
+	ONLCR                             = 0x2
+	ONLRET                            = 0x80
+	ONOCR                             = 0x40
+	ONOEOT                            = 0x8
+	OPOST                             = 0x1
 	O_ACCMODE                         = 0x3
 	O_APPEND                          = 0x8
 	O_ASYNC                           = 0x40
@@ -857,6 +926,12 @@ const (
 	O_SYNC                            = 0x80
 	O_TRUNC                           = 0x400
 	O_WRONLY                          = 0x1
+	PARENB                            = 0x1000
+	PARMRK                            = 0x8
+	PARODD                            = 0x2000
+	PENDIN                            = 0x20000000
+	PF_FLUSH                          = 0x1
+	PMC5_PIPELINE_FLUSH               = 0x15
 	RLIMIT_CORE                       = 0x4
 	RLIMIT_CPU                        = 0x0
 	RLIMIT_DATA                       = 0x2
@@ -893,10 +968,9 @@ const (
 	RTF_CLONING                       = 0x100
 	RTF_DONE                          = 0x40
 	RTF_DYNAMIC                       = 0x10
-	RTF_FMASK                         = 0x8f808
+	RTF_FMASK                         = 0xf808
 	RTF_GATEWAY                       = 0x2
 	RTF_HOST                          = 0x4
-	RTF_JUMBO                         = 0x80000
 	RTF_LLINFO                        = 0x400
 	RTF_MASK                          = 0x80
 	RTF_MODIFIED                      = 0x20
@@ -942,7 +1016,6 @@ const (
 	RUSAGE_CHILDREN                   = -0x1
 	RUSAGE_SELF                       = 0x0
 	RUSAGE_THREAD                     = 0x1
-	SCM_CREDS                         = 0x2
 	SCM_RIGHTS                        = 0x1
 	SCM_TIMESTAMP                     = 0x4
 	SHUT_RD                           = 0x0
@@ -996,7 +1069,6 @@ const (
 	SIOCGETPFSYNC                     = 0xc02069f8
 	SIOCGETSGCNT                      = 0xc0207534
 	SIOCGETVIFCNT                     = 0xc0287533
-	SIOCGETVLANPRIO                   = 0xc0206990
 	SIOCGHIWAT                        = 0x40047301
 	SIOCGIFADDR                       = 0xc0206921
 	SIOCGIFASYNCMAP                   = 0xc020697c
@@ -1034,7 +1106,6 @@ const (
 	SIOCSETLABEL                      = 0x80206999
 	SIOCSETPFLOW                      = 0x802069fd
 	SIOCSETPFSYNC                     = 0x802069f7
-	SIOCSETVLANPRIO                   = 0x8020698f
 	SIOCSHIWAT                        = 0x80047300
 	SIOCSIFADDR                       = 0x8020690c
 	SIOCSIFASYNCMAP                   = 0x8020697d
@@ -1073,7 +1144,6 @@ const (
 	SO_DEBUG                          = 0x1
 	SO_DONTROUTE                      = 0x10
 	SO_ERROR                          = 0x1007
-	SO_JUMBO                          = 0x400
 	SO_KEEPALIVE                      = 0x8
 	SO_LINGER                         = 0x80
 	SO_NETPROC                        = 0x1020
@@ -1092,6 +1162,9 @@ const (
 	SO_TIMESTAMP                      = 0x800
 	SO_TYPE                           = 0x1008
 	SO_USELOOPBACK                    = 0x40
+	TCIFLUSH                          = 0x1
+	TCIOFLUSH                         = 0x3
+	TCOFLUSH                          = 0x2
 	TCP_MAXBURST                      = 0x4
 	TCP_MAXSEG                        = 0x2
 	TCP_MAXWIN                        = 0xffff
@@ -1102,6 +1175,7 @@ const (
 	TCP_NODELAY                       = 0x1
 	TCP_NSTATES                       = 0xb
 	TCP_SACK_ENABLE                   = 0x8
+	TCSAFLUSH                         = 0x2
 	TIOCCBRK                          = 0x2000747a
 	TIOCCDTR                          = 0x20007478
 	TIOCCONS                          = 0x80047462
@@ -1167,6 +1241,25 @@ const (
 	TIOCSTSTAMP                       = 0x8008745a
 	TIOCSWINSZ                        = 0x80087467
 	TIOCUCNTL                         = 0x80047466
+	TOSTOP                            = 0x400000
+	VDISCARD                          = 0xf
+	VDSUSP                            = 0xb
+	VEOF                              = 0x0
+	VEOL                              = 0x1
+	VEOL2                             = 0x2
+	VERASE                            = 0x3
+	VINTR                             = 0x8
+	VKILL                             = 0x5
+	VLNEXT                            = 0xe
+	VMIN                              = 0x10
+	VQUIT                             = 0x9
+	VREPRINT                          = 0x6
+	VSTART                            = 0xc
+	VSTATUS                           = 0x12
+	VSTOP                             = 0xd
+	VSUSP                             = 0xa
+	VTIME                             = 0x11
+	VWERASE                           = 0x4
 	WALTSIG                           = 0x4
 	WCONTINUED                        = 0x8
 	WCOREFLAG                         = 0x80
diff --git a/src/pkg/syscall/zerrors_plan9_386.go b/src/pkg/syscall/zerrors_plan9_386.go
index e7c993c..ede3d6a 100644
--- a/src/pkg/syscall/zerrors_plan9_386.go
+++ b/src/pkg/syscall/zerrors_plan9_386.go
@@ -4,8 +4,6 @@
 
 package syscall
 
-import "errors"
-
 // Constants
 const (
 	// Invented values to support what package os expects.
@@ -24,19 +22,27 @@ const (
 	S_IFREG  = 0x8000
 	S_IFLNK  = 0xa000
 	S_IFSOCK = 0xc000
-
-	SIGINT  = Signal(0x2)
-	SIGKILL = Signal(0x9)
 )
 
 // Errors
 var (
-	EINVAL       = errors.New("bad arg in system call")
-	ENOTDIR      = errors.New("not a directory")
-	ENOENT       = errors.New("file does not exist")
-	EEXIST       = errors.New("file already exists")
-	EIO          = errors.New("i/o error")
-	ENAMETOOLONG = errors.New("file name too long")
-	EPERM        = errors.New("permission denied")
-	EPLAN9       = errors.New("not supported by plan 9")
+	EINVAL       = NewError("bad arg in system call")
+	ENOTDIR      = NewError("not a directory")
+	EISDIR       = NewError("file is a directory")
+	ENOENT       = NewError("file does not exist")
+	EEXIST       = NewError("file already exists")
+	EMFILE       = NewError("no free file descriptors")
+	EIO          = NewError("i/o error")
+	ENAMETOOLONG = NewError("file name too long")
+	EINTR        = NewError("interrupted")
+	EPERM        = NewError("permission denied")
+	EBUSY        = NewError("no free devices")
+	ETIMEDOUT    = NewError("connection timed out")
+	EPLAN9       = NewError("not supported by plan 9")
+
+	// The following errors do not correspond to any
+	// Plan 9 system messages. Invented to support
+	// what package os and others expect.
+	EACCES       = NewError("access permission denied")
+	EAFNOSUPPORT = NewError("address family not supported by protocol")
 )
diff --git a/src/pkg/syscall/zerrors_plan9_amd64.go b/src/pkg/syscall/zerrors_plan9_amd64.go
new file mode 100644
index 0000000..ede3d6a
--- /dev/null
+++ b/src/pkg/syscall/zerrors_plan9_amd64.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 syscall
+
+// Constants
+const (
+	// Invented values to support what package os expects.
+	O_CREAT    = 0x02000
+	O_APPEND   = 0x00400
+	O_NOCTTY   = 0x00000
+	O_NONBLOCK = 0x00000
+	O_SYNC     = 0x00000
+	O_ASYNC    = 0x00000
+
+	S_IFMT   = 0x1f000
+	S_IFIFO  = 0x1000
+	S_IFCHR  = 0x2000
+	S_IFDIR  = 0x4000
+	S_IFBLK  = 0x6000
+	S_IFREG  = 0x8000
+	S_IFLNK  = 0xa000
+	S_IFSOCK = 0xc000
+)
+
+// Errors
+var (
+	EINVAL       = NewError("bad arg in system call")
+	ENOTDIR      = NewError("not a directory")
+	EISDIR       = NewError("file is a directory")
+	ENOENT       = NewError("file does not exist")
+	EEXIST       = NewError("file already exists")
+	EMFILE       = NewError("no free file descriptors")
+	EIO          = NewError("i/o error")
+	ENAMETOOLONG = NewError("file name too long")
+	EINTR        = NewError("interrupted")
+	EPERM        = NewError("permission denied")
+	EBUSY        = NewError("no free devices")
+	ETIMEDOUT    = NewError("connection timed out")
+	EPLAN9       = NewError("not supported by plan 9")
+
+	// The following errors do not correspond to any
+	// Plan 9 system messages. Invented to support
+	// what package os and others expect.
+	EACCES       = NewError("access permission denied")
+	EAFNOSUPPORT = NewError("address family not supported by protocol")
+)
diff --git a/src/pkg/syscall/zsyscall_darwin_386.go b/src/pkg/syscall/zsyscall_darwin_386.go
index b952ac4..2f99b7f 100644
--- a/src/pkg/syscall/zsyscall_darwin_386.go
+++ b/src/pkg/syscall/zsyscall_darwin_386.go
@@ -131,7 +131,7 @@ func Shutdown(s int, how int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e1 != 0 {
 		err = e1
@@ -223,7 +223,12 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func utimes(path string, timeval *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -286,7 +291,12 @@ func kill(pid int, signum int, posix int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -306,7 +316,12 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -316,7 +331,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -326,7 +346,12 @@ func Chflags(path string, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -336,7 +361,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -346,7 +376,12 @@ func Chown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -387,7 +422,17 @@ func Dup2(from int, to int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Exchangedata(path1 string, path2 string, options int) (err error) {
-	_, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(StringBytePtr(path1))), uintptr(unsafe.Pointer(StringBytePtr(path2))), uintptr(options))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path1)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(path2)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options))
 	if e1 != 0 {
 		err = e1
 	}
@@ -414,7 +459,12 @@ func Fchdir(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -675,7 +725,12 @@ func Kqueue() (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -685,7 +740,17 @@ func Lchown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -705,7 +770,12 @@ func Listen(s int, backlog int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -715,7 +785,12 @@ func Lstat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -725,7 +800,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkfifo(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -735,7 +815,12 @@ func Mkfifo(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -745,7 +830,12 @@ func Mknod(path string, mode uint32, dev int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -756,7 +846,12 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Pathconf(path string, name int) (val int, err error) {
-	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
 	val = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -800,7 +895,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -818,13 +913,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -835,7 +935,17 @@ func Readlink(path string, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rename(from string, to string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -845,7 +955,12 @@ func Rename(from string, to string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Revoke(path string) (err error) {
-	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -855,7 +970,12 @@ func Revoke(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -916,7 +1036,12 @@ func Setgid(gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Setlogin(name string) (err error) {
-	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(name)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1017,7 +1142,12 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1027,7 +1157,12 @@ func Stat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Statfs(path string, stat *Statfs_t) (err error) {
-	_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1037,7 +1172,17 @@ func Statfs(path string, stat *Statfs_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1057,7 +1202,12 @@ func Sync() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), uintptr(length>>32))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1075,7 +1225,12 @@ func Umask(newmask int) (oldmask int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Undelete(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1085,7 +1240,12 @@ func Undelete(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1095,7 +1255,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1104,7 +1269,7 @@ func Unmount(path string, flags int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -1142,7 +1307,7 @@ func munmap(addr uintptr, length uintptr) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, err error) {
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
@@ -1153,7 +1318,7 @@ func read(fd int, buf *byte, nbuf int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, err error) {
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
diff --git a/src/pkg/syscall/zsyscall_darwin_amd64.go b/src/pkg/syscall/zsyscall_darwin_amd64.go
index 104ee55..0f08df4 100644
--- a/src/pkg/syscall/zsyscall_darwin_amd64.go
+++ b/src/pkg/syscall/zsyscall_darwin_amd64.go
@@ -131,7 +131,7 @@ func Shutdown(s int, how int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e1 != 0 {
 		err = e1
@@ -223,7 +223,12 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func utimes(path string, timeval *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -286,7 +291,12 @@ func kill(pid int, signum int, posix int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -306,7 +316,12 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -316,7 +331,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -326,7 +346,12 @@ func Chflags(path string, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -336,7 +361,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -346,7 +376,12 @@ func Chown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -387,7 +422,17 @@ func Dup2(from int, to int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Exchangedata(path1 string, path2 string, options int) (err error) {
-	_, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(StringBytePtr(path1))), uintptr(unsafe.Pointer(StringBytePtr(path2))), uintptr(options))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path1)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(path2)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options))
 	if e1 != 0 {
 		err = e1
 	}
@@ -414,7 +459,12 @@ func Fchdir(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -675,7 +725,12 @@ func Kqueue() (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -685,7 +740,17 @@ func Lchown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -705,7 +770,12 @@ func Listen(s int, backlog int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -715,7 +785,12 @@ func Lstat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -725,7 +800,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkfifo(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -735,7 +815,12 @@ func Mkfifo(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -745,7 +830,12 @@ func Mknod(path string, mode uint32, dev int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -756,7 +846,12 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Pathconf(path string, name int) (val int, err error) {
-	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
 	val = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -800,7 +895,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -818,13 +913,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -835,7 +935,17 @@ func Readlink(path string, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rename(from string, to string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -845,7 +955,12 @@ func Rename(from string, to string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Revoke(path string) (err error) {
-	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -855,7 +970,12 @@ func Revoke(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -916,7 +1036,12 @@ func Setgid(gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Setlogin(name string) (err error) {
-	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(name)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1017,7 +1142,12 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1027,7 +1157,12 @@ func Stat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Statfs(path string, stat *Statfs_t) (err error) {
-	_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1037,7 +1172,17 @@ func Statfs(path string, stat *Statfs_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1057,7 +1202,12 @@ func Sync() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1075,7 +1225,12 @@ func Umask(newmask int) (oldmask int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Undelete(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1085,7 +1240,12 @@ func Undelete(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1095,7 +1255,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1104,7 +1269,7 @@ func Unmount(path string, flags int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -1142,7 +1307,7 @@ func munmap(addr uintptr, length uintptr) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, err error) {
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
@@ -1153,7 +1318,7 @@ func read(fd int, buf *byte, nbuf int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, err error) {
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
diff --git a/src/pkg/syscall/zsyscall_freebsd_386.go b/src/pkg/syscall/zsyscall_freebsd_386.go
index 4555754..5ca0bcb 100644
--- a/src/pkg/syscall/zsyscall_freebsd_386.go
+++ b/src/pkg/syscall/zsyscall_freebsd_386.go
@@ -131,7 +131,7 @@ func Shutdown(s int, how int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e1 != 0 {
 		err = e1
@@ -223,7 +223,12 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func utimes(path string, timeval *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -266,7 +271,12 @@ func pipe() (r int, w int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -286,7 +296,12 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -296,7 +311,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -306,7 +326,12 @@ func Chflags(path string, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -316,7 +341,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -326,7 +356,12 @@ func Chown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -384,7 +419,12 @@ func Fchdir(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -665,7 +705,12 @@ func Kqueue() (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -675,7 +720,17 @@ func Lchown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -695,7 +750,12 @@ func Listen(s int, backlog int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -705,7 +765,12 @@ func Lstat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -715,7 +780,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkfifo(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -725,7 +795,12 @@ func Mkfifo(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -745,7 +820,12 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -756,7 +836,12 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Pathconf(path string, name int) (val int, err error) {
-	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
 	val = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -800,7 +885,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -818,13 +903,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -835,7 +925,17 @@ func Readlink(path string, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rename(from string, to string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -845,7 +945,12 @@ func Rename(from string, to string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Revoke(path string) (err error) {
-	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -855,7 +960,12 @@ func Revoke(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -916,7 +1026,12 @@ func Setgid(gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Setlogin(name string) (err error) {
-	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(name)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1007,7 +1122,12 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1017,7 +1137,12 @@ func Stat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Statfs(path string, stat *Statfs_t) (err error) {
-	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1027,7 +1152,17 @@ func Statfs(path string, stat *Statfs_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1047,7 +1182,12 @@ func Sync() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), uintptr(length>>32))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1065,7 +1205,12 @@ func Umask(newmask int) (oldmask int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Undelete(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1075,7 +1220,12 @@ func Undelete(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1085,7 +1235,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1094,7 +1249,7 @@ func Unmount(path string, flags int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -1132,7 +1287,7 @@ func munmap(addr uintptr, length uintptr) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, err error) {
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
@@ -1143,7 +1298,7 @@ func read(fd int, buf *byte, nbuf int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, err error) {
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
diff --git a/src/pkg/syscall/zsyscall_freebsd_amd64.go b/src/pkg/syscall/zsyscall_freebsd_amd64.go
index 33b71b9..2606774 100644
--- a/src/pkg/syscall/zsyscall_freebsd_amd64.go
+++ b/src/pkg/syscall/zsyscall_freebsd_amd64.go
@@ -131,7 +131,7 @@ func Shutdown(s int, how int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e1 != 0 {
 		err = e1
@@ -223,7 +223,12 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func utimes(path string, timeval *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -266,7 +271,12 @@ func pipe() (r int, w int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -286,7 +296,12 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -296,7 +311,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -306,7 +326,12 @@ func Chflags(path string, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -316,7 +341,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -326,7 +356,12 @@ func Chown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -384,7 +419,12 @@ func Fchdir(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -665,7 +705,12 @@ func Kqueue() (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -675,7 +720,17 @@ func Lchown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -695,7 +750,12 @@ func Listen(s int, backlog int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -705,7 +765,12 @@ func Lstat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -715,7 +780,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkfifo(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -725,7 +795,12 @@ func Mkfifo(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -745,7 +820,12 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -756,7 +836,12 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Pathconf(path string, name int) (val int, err error) {
-	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
 	val = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -800,7 +885,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -818,13 +903,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -835,7 +925,17 @@ func Readlink(path string, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rename(from string, to string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -845,7 +945,12 @@ func Rename(from string, to string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Revoke(path string) (err error) {
-	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -855,7 +960,12 @@ func Revoke(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -916,7 +1026,12 @@ func Setgid(gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Setlogin(name string) (err error) {
-	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(name)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1007,7 +1122,12 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1017,7 +1137,12 @@ func Stat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Statfs(path string, stat *Statfs_t) (err error) {
-	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1027,7 +1152,17 @@ func Statfs(path string, stat *Statfs_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1047,7 +1182,12 @@ func Sync() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1065,7 +1205,12 @@ func Umask(newmask int) (oldmask int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Undelete(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1075,7 +1220,12 @@ func Undelete(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1085,7 +1235,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1094,7 +1249,7 @@ func Unmount(path string, flags int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -1132,7 +1287,7 @@ func munmap(addr uintptr, length uintptr) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, err error) {
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
@@ -1143,7 +1298,7 @@ func read(fd int, buf *byte, nbuf int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, err error) {
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
diff --git a/src/pkg/syscall/zsyscall_freebsd_arm.go b/src/pkg/syscall/zsyscall_freebsd_arm.go
new file mode 100644
index 0000000..925b83f
--- /dev/null
+++ b/src/pkg/syscall/zsyscall_freebsd_arm.go
@@ -0,0 +1,1308 @@
+// mksyscall.pl -l32 syscall_bsd.go syscall_freebsd.go syscall_freebsd_386.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 getgroups(ngid int, gid *_Gid_t) (n int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setgroups(ngid int, gid *_Gid_t) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
+	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
+	wpid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socket(domain int, typ int, proto int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
+	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
+	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Shutdown(s int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
+	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error) {
+	r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
+	var _p0 unsafe.Pointer
+	if len(mib) > 0 {
+		_p0 = unsafe.Pointer(&mib[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimes(path string, timeval *[2]Timeval) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func futimes(fd int, timeval *[2]Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe() (r int, w int, err error) {
+	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
+	r = int(r0)
+	w = int(r1)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Access(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chdir(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chflags(path string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chmod(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chown(path string, uid int, gid int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chroot(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(fd int) (nfd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(fd), 0, 0)
+	nfd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup2(from int, to int) (err error) {
+	_, _, e1 := RawSyscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) {
+	Syscall(SYS_EXIT, uintptr(code), 0, 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchflags(path string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmod(fd int, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchown(fd int, uid int, gid int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Flock(fd int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fpathconf(fd int, name int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstat(fd int, stat *Stat_t) (err error) {
+	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstatfs(fd int, stat *Statfs_t) (err error) {
+	_, _, e1 := Syscall(SYS_FSTATFS, 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 Fsync(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ftruncate(fd int, length int64) (err error) {
+	_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), uintptr(length>>32))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getdtablesize() (size int) {
+	r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0)
+	size = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getegid() (egid int) {
+	r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0)
+	egid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Geteuid() (uid int) {
+	r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), uintptr(len(buf)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+	r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)
+	gid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgid(pid int) (pgid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
+	pgid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgrp() (pgrp int) {
+	r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0)
+	pgrp = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpid() (pid int) {
+	r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
+	pid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getppid() (ppid int) {
+	r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0)
+	ppid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpriority(which int, who int) (prio int, err error) {
+	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
+	prio = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(which int, lim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrusage(who int, rusage *Rusage) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getsid(pid int) (sid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0)
+	sid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getuid() (uid int) {
+	r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Issetugid() (tainted bool) {
+	r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0)
+	tainted = bool(r0 != 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, signum Signal) (err error) {
+	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kqueue() (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lchown(path string, uid int, gid int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Link(path string, link string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listen(s int, backlog int) (err error) {
+	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lstat(path string, stat *Stat_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkdir(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkfifo(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mknod(path string, mode uint32, dev int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
+	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Open(path string, mode int, perm uint32) (fd int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pathconf(path string, name int) (val int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Readlink(path string, buf []byte) (n int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(buf) > 0 {
+		_p1 = unsafe.Pointer(&buf[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Rename(from string, to string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Revoke(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Rmdir(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
+	r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0)
+	newoffset = int64(int64(r1)<<32 | int64(r0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
+	_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setegid(egid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seteuid(euid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// 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 Setlogin(name string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(name)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpgid(pid int, pgid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpriority(which int, who int, prio int) (err error) {
+	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setregid(rgid int, egid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setreuid(ruid int, euid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setrlimit(which int, lim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setsid() (pid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+	pid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Settimeofday(tp *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// 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 Stat(path string, stat *Stat_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Statfs(path string, stat *Statfs_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Symlink(path string, link string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sync() (err error) {
+	_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Truncate(path string, length int64) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Umask(newmask int) (oldmask int) {
+	r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0)
+	oldmask = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Undelete(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unlink(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unmount(path string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
+	r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos), uintptr(pos>>32), 0, 0)
+	ret = uintptr(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func munmap(addr uintptr, length uintptr) (err error) {
+	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func write(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
diff --git a/src/pkg/syscall/zsyscall_linux_386.go b/src/pkg/syscall/zsyscall_linux_386.go
index 1752fe4..3f0470c 100644
--- a/src/pkg/syscall/zsyscall_linux_386.go
+++ b/src/pkg/syscall/zsyscall_linux_386.go
@@ -8,7 +8,12 @@ import "unsafe"
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -19,7 +24,12 @@ func open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
-	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), uintptr(mode), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode), 0, 0)
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -39,8 +49,38 @@ func pipe(p *[2]_C_int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func pipe2(p *[2]_C_int, flags int) (err error) {
+	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func utimes(path string, times *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(times)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
 	if e1 != 0 {
 		err = e1
 	}
@@ -98,7 +138,12 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
-	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(StringBytePtr(arg))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(arg)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -108,7 +153,22 @@ func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
-	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(StringBytePtr(source))), uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(unsafe.Pointer(StringBytePtr(fstype))), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(source)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(target)
+	if err != nil {
+		return
+	}
+	var _p2 *byte
+	_p2, err = BytePtrFromString(fstype)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -118,7 +178,12 @@ func mount(source string, target string, fstype string, flags uintptr, data *byt
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -128,7 +193,12 @@ func Access(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Acct(path string) (err error) {
-	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -149,7 +219,12 @@ func Adjtimex(buf *Timex) (state int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -159,7 +234,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -169,7 +249,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -189,7 +274,12 @@ func Close(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Creat(path string, mode uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -277,7 +367,12 @@ func Exit(code int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -317,7 +412,12 @@ func Fchmod(fd int, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -327,7 +427,12 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -429,16 +534,6 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(resource int, rlim *Rlimit) (err error) {
-	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
-	if e1 != 0 {
-		err = e1
-	}
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
 	if e1 != 0 {
@@ -457,8 +552,40 @@ func Gettid() (tid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	var _p2 unsafe.Pointer
+	if len(dest) > 0 {
+		_p2 = unsafe.Pointer(&dest[0])
+	} else {
+		_p2 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
+	sz = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
-	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(StringBytePtr(pathname))), uintptr(mask))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(pathname)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask))
 	watchdesc = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -529,7 +656,39 @@ func Klogctl(typ int, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(oldpath string, newpath string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listxattr(path string, dest []byte) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(dest) > 0 {
+		_p1 = unsafe.Pointer(&dest[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
+	sz = int(r0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -539,7 +698,12 @@ func Link(oldpath string, newpath string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -549,7 +713,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdirat(dirfd int, path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
 	if e1 != 0 {
 		err = e1
 	}
@@ -559,7 +728,12 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -569,7 +743,12 @@ func Mknod(path string, mode uint32, dev int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -599,7 +778,17 @@ func Pause() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func PivotRoot(newroot string, putold string) (err error) {
-	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(StringBytePtr(newroot))), uintptr(unsafe.Pointer(StringBytePtr(putold))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(newroot)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(putold)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -608,7 +797,17 @@ func PivotRoot(newroot string, putold string) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+	_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -626,13 +825,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -642,8 +846,38 @@ func Readlink(path string, buf []byte) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Removexattr(path string, attr string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Rename(oldpath string, newpath string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -653,7 +887,17 @@ func Rename(oldpath string, newpath string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
-	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(newdirfd), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -663,7 +907,12 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -714,8 +963,9 @@ func Setpgid(pid int, pgid int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(resource int, rlim *Rlimit) (err error) {
-	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+func Setsid() (pid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+	pid = int(r0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -724,9 +974,8 @@ func Setrlimit(resource int, rlim *Rlimit) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, err error) {
-	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
-	pid = int(r0)
+func Settimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -735,8 +984,8 @@ func Setsid() (pid int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tv *Timeval) (err error) {
-	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+func Setuid(uid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -745,8 +994,24 @@ 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)
+func Setxattr(path string, attr string, data []byte, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	var _p2 unsafe.Pointer
+	if len(data) > 0 {
+		_p2 = unsafe.Pointer(&data[0])
+	} else {
+		_p2 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -756,7 +1021,17 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(oldpath string, newpath string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -833,7 +1108,12 @@ func Uname(buf *Utsname) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -843,7 +1123,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlinkat(dirfd int, path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -853,7 +1138,12 @@ func Unlinkat(dirfd int, path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(target string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(target)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -883,7 +1173,12 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Utime(path string, buf *Utimbuf) (err error) {
-	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(buf)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -892,7 +1187,7 @@ func Utime(path string, buf *Utimbuf) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -919,7 +1214,7 @@ func exitThread(code int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, p *byte, np int) (n int, err error) {
+func readlen(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
 	if e1 != 0 {
@@ -930,7 +1225,7 @@ func read(fd int, p *byte, np int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, p *byte, np int) (n int, err error) {
+func writelen(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
 	if e1 != 0 {
@@ -1036,7 +1331,12 @@ func Munlockall() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN32, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN32, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1128,7 +1428,12 @@ func Iopl(level int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN32, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN32, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1138,7 +1443,12 @@ func Lchown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1181,7 +1491,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	r0, _, e1 := Syscall6(SYS_SENDFILE64, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
 	written = int(r0)
 	if e1 != 0 {
@@ -1274,7 +1584,12 @@ func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n i
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1294,7 +1609,12 @@ func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall(SYS_TRUNCATE64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), uintptr(length>>32))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE64, uintptr(unsafe.Pointer(_p0)), uintptr(length), uintptr(length>>32))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1346,6 +1666,26 @@ func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func getrlimit(resource int, rlim *rlimit32) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setrlimit(resource int, rlim *rlimit32) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Gettimeofday(tv *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
 	if e1 != 0 {
diff --git a/src/pkg/syscall/zsyscall_linux_amd64.go b/src/pkg/syscall/zsyscall_linux_amd64.go
index d27346f..43f24e7 100644
--- a/src/pkg/syscall/zsyscall_linux_amd64.go
+++ b/src/pkg/syscall/zsyscall_linux_amd64.go
@@ -8,7 +8,12 @@ import "unsafe"
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -19,7 +24,12 @@ func open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
-	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), uintptr(mode), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode), 0, 0)
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -39,8 +49,38 @@ func pipe(p *[2]_C_int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func pipe2(p *[2]_C_int, flags int) (err error) {
+	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func utimes(path string, times *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(times)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
 	if e1 != 0 {
 		err = e1
 	}
@@ -98,7 +138,12 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
-	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(StringBytePtr(arg))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(arg)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -108,7 +153,22 @@ func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
-	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(StringBytePtr(source))), uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(unsafe.Pointer(StringBytePtr(fstype))), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(source)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(target)
+	if err != nil {
+		return
+	}
+	var _p2 *byte
+	_p2, err = BytePtrFromString(fstype)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -118,7 +178,12 @@ func mount(source string, target string, fstype string, flags uintptr, data *byt
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -128,7 +193,12 @@ func Access(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Acct(path string) (err error) {
-	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -149,7 +219,12 @@ func Adjtimex(buf *Timex) (state int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -159,7 +234,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -169,7 +249,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -189,7 +274,12 @@ func Close(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Creat(path string, mode uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -277,7 +367,12 @@ func Exit(code int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -317,7 +412,12 @@ func Fchmod(fd int, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -327,7 +427,12 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -429,16 +534,6 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(resource int, rlim *Rlimit) (err error) {
-	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
-	if e1 != 0 {
-		err = e1
-	}
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
 	if e1 != 0 {
@@ -457,8 +552,40 @@ func Gettid() (tid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	var _p2 unsafe.Pointer
+	if len(dest) > 0 {
+		_p2 = unsafe.Pointer(&dest[0])
+	} else {
+		_p2 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
+	sz = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
-	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(StringBytePtr(pathname))), uintptr(mask))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(pathname)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask))
 	watchdesc = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -529,7 +656,39 @@ func Klogctl(typ int, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(oldpath string, newpath string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listxattr(path string, dest []byte) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(dest) > 0 {
+		_p1 = unsafe.Pointer(&dest[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
+	sz = int(r0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -539,7 +698,12 @@ func Link(oldpath string, newpath string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -549,7 +713,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdirat(dirfd int, path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
 	if e1 != 0 {
 		err = e1
 	}
@@ -559,7 +728,12 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -569,7 +743,12 @@ func Mknod(path string, mode uint32, dev int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -599,7 +778,17 @@ func Pause() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func PivotRoot(newroot string, putold string) (err error) {
-	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(StringBytePtr(newroot))), uintptr(unsafe.Pointer(StringBytePtr(putold))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(newroot)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(putold)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -608,7 +797,17 @@ func PivotRoot(newroot string, putold string) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+	_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -626,13 +825,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -642,8 +846,38 @@ func Readlink(path string, buf []byte) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Removexattr(path string, attr string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Rename(oldpath string, newpath string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -653,7 +887,17 @@ func Rename(oldpath string, newpath string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
-	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(newdirfd), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -663,7 +907,12 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -714,8 +963,9 @@ func Setpgid(pid int, pgid int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(resource int, rlim *Rlimit) (err error) {
-	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+func Setsid() (pid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+	pid = int(r0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -724,9 +974,8 @@ func Setrlimit(resource int, rlim *Rlimit) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, err error) {
-	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
-	pid = int(r0)
+func Settimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -735,8 +984,8 @@ func Setsid() (pid int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tv *Timeval) (err error) {
-	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+func Setuid(uid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -745,8 +994,24 @@ 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)
+func Setxattr(path string, attr string, data []byte, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	var _p2 unsafe.Pointer
+	if len(data) > 0 {
+		_p2 = unsafe.Pointer(&data[0])
+	} else {
+		_p2 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -756,7 +1021,17 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(oldpath string, newpath string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -833,7 +1108,12 @@ func Uname(buf *Utsname) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -843,7 +1123,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlinkat(dirfd int, path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -853,7 +1138,12 @@ func Unlinkat(dirfd int, path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(target string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(target)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -883,7 +1173,12 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Utime(path string, buf *Utimbuf) (err error) {
-	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(buf)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -892,7 +1187,7 @@ func Utime(path string, buf *Utimbuf) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -919,7 +1214,7 @@ func exitThread(code int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, p *byte, np int) (n int, err error) {
+func readlen(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
 	if e1 != 0 {
@@ -930,7 +1225,7 @@ func read(fd int, p *byte, np int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, p *byte, np int) (n int, err error) {
+func writelen(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
 	if e1 != 0 {
@@ -1036,7 +1331,12 @@ func Munlockall() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1109,6 +1409,16 @@ func Getgid() (gid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Getuid() (uid int) {
 	r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
 	uid = int(r0)
@@ -1138,7 +1448,12 @@ func Iopl(level int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1158,7 +1473,12 @@ func Listen(s int, n int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1223,7 +1543,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	r0, _, e1 := Syscall6(SYS_SENDFILE, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
 	written = int(r0)
 	if e1 != 0 {
@@ -1294,6 +1614,16 @@ func Setresuid(ruid int, euid int, suid int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Setreuid(ruid int, euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
 	if e1 != 0 {
@@ -1326,7 +1656,12 @@ func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n i
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1336,7 +1671,12 @@ func Stat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Statfs(path string, buf *Statfs_t) (err error) {
-	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(buf)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1356,7 +1696,12 @@ func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1376,6 +1721,17 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
+	r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
 	if e1 != 0 {
@@ -1448,7 +1804,7 @@ func socket(domain int, typ int, proto int) (fd int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e1 != 0 {
 		err = e1
diff --git a/src/pkg/syscall/zsyscall_linux_arm.go b/src/pkg/syscall/zsyscall_linux_arm.go
index b1a59a6..804821e 100644
--- a/src/pkg/syscall/zsyscall_linux_arm.go
+++ b/src/pkg/syscall/zsyscall_linux_arm.go
@@ -8,7 +8,12 @@ import "unsafe"
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -19,7 +24,12 @@ func open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
-	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), uintptr(mode), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode), 0, 0)
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -39,8 +49,38 @@ func pipe(p *[2]_C_int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func pipe2(p *[2]_C_int, flags int) (err error) {
+	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func utimes(path string, times *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(times)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
 	if e1 != 0 {
 		err = e1
 	}
@@ -98,7 +138,12 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
-	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(StringBytePtr(arg))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(arg)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -108,7 +153,22 @@ func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
-	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(StringBytePtr(source))), uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(unsafe.Pointer(StringBytePtr(fstype))), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(source)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(target)
+	if err != nil {
+		return
+	}
+	var _p2 *byte
+	_p2, err = BytePtrFromString(fstype)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -118,7 +178,12 @@ func mount(source string, target string, fstype string, flags uintptr, data *byt
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -128,7 +193,12 @@ func Access(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Acct(path string) (err error) {
-	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -149,7 +219,12 @@ func Adjtimex(buf *Timex) (state int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -159,7 +234,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -169,7 +249,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -189,7 +274,12 @@ func Close(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Creat(path string, mode uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -277,7 +367,12 @@ func Exit(code int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -317,7 +412,12 @@ func Fchmod(fd int, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -327,7 +427,12 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -429,16 +534,6 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(resource int, rlim *Rlimit) (err error) {
-	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
-	if e1 != 0 {
-		err = e1
-	}
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
 	if e1 != 0 {
@@ -457,8 +552,40 @@ func Gettid() (tid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	var _p2 unsafe.Pointer
+	if len(dest) > 0 {
+		_p2 = unsafe.Pointer(&dest[0])
+	} else {
+		_p2 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
+	sz = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
-	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(StringBytePtr(pathname))), uintptr(mask))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(pathname)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask))
 	watchdesc = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -529,7 +656,39 @@ func Klogctl(typ int, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(oldpath string, newpath string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listxattr(path string, dest []byte) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(dest) > 0 {
+		_p1 = unsafe.Pointer(&dest[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
+	sz = int(r0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -539,7 +698,12 @@ func Link(oldpath string, newpath string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -549,7 +713,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdirat(dirfd int, path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
 	if e1 != 0 {
 		err = e1
 	}
@@ -559,7 +728,12 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -569,7 +743,12 @@ func Mknod(path string, mode uint32, dev int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -599,7 +778,17 @@ func Pause() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func PivotRoot(newroot string, putold string) (err error) {
-	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(StringBytePtr(newroot))), uintptr(unsafe.Pointer(StringBytePtr(putold))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(newroot)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(putold)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -608,7 +797,17 @@ func PivotRoot(newroot string, putold string) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+	_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -626,13 +825,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -642,8 +846,38 @@ func Readlink(path string, buf []byte) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Removexattr(path string, attr string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Rename(oldpath string, newpath string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -653,7 +887,17 @@ func Rename(oldpath string, newpath string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
-	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(newdirfd), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -663,7 +907,12 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -714,8 +963,9 @@ func Setpgid(pid int, pgid int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(resource int, rlim *Rlimit) (err error) {
-	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+func Setsid() (pid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+	pid = int(r0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -724,9 +974,8 @@ func Setrlimit(resource int, rlim *Rlimit) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, err error) {
-	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
-	pid = int(r0)
+func Settimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -735,8 +984,8 @@ func Setsid() (pid int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tv *Timeval) (err error) {
-	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+func Setuid(uid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -745,8 +994,24 @@ 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)
+func Setxattr(path string, attr string, data []byte, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	var _p2 unsafe.Pointer
+	if len(data) > 0 {
+		_p2 = unsafe.Pointer(&data[0])
+	} else {
+		_p2 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -756,7 +1021,17 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(oldpath string, newpath string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -833,7 +1108,12 @@ func Uname(buf *Utsname) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -843,7 +1123,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlinkat(dirfd int, path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -853,7 +1138,12 @@ func Unlinkat(dirfd int, path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(target string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(target)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -883,7 +1173,12 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Utime(path string, buf *Utimbuf) (err error) {
-	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(buf)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -892,7 +1187,7 @@ func Utime(path string, buf *Utimbuf) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -919,7 +1214,7 @@ func exitThread(code int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, p *byte, np int) (n int, err error) {
+func readlen(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
 	if e1 != 0 {
@@ -930,7 +1225,7 @@ func read(fd int, p *byte, np int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, p *byte, np int) (n int, err error) {
+func writelen(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
 	if e1 != 0 {
@@ -1046,6 +1341,17 @@ func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
+	r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
 	if e1 != 0 {
@@ -1171,7 +1477,7 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err err
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, flags int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, flags int, fd *[2]int32) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e1 != 0 {
 		err = e1
@@ -1203,7 +1509,12 @@ func sendmsg(s int, msg *Msghdr, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN32, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN32, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1232,16 +1543,6 @@ func Fstat(fd int, stat *Stat_t) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstatfs(fd int, buf *Statfs_t) (err error) {
-	_, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
-	if e1 != 0 {
-		err = e1
-	}
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func Getegid() (egid int) {
 	r0, _, _ := RawSyscall(SYS_GETEGID32, 0, 0, 0)
 	egid = int(r0)
@@ -1275,7 +1576,12 @@ func Getuid() (uid int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN32, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN32, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1295,7 +1601,12 @@ func Listen(s int, n int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1304,7 +1615,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	r0, _, e1 := Syscall6(SYS_SENDFILE64, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
 	written = int(r0)
 	if e1 != 0 {
@@ -1418,17 +1729,12 @@ func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n i
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	if e1 != 0 {
-		err = e1
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
 	}
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func Statfs(path string, buf *Statfs_t) (err error) {
-	_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(buf)), 0)
+	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1493,7 +1799,12 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall6(SYS_TRUNCATE64, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length), uintptr(length>>32), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_TRUNCATE64, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1520,3 +1831,23 @@ func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset
 	}
 	return
 }
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getrlimit(resource int, rlim *rlimit32) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setrlimit(resource int, rlim *rlimit32) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
diff --git a/src/pkg/syscall/zsyscall_netbsd_386.go b/src/pkg/syscall/zsyscall_netbsd_386.go
index 6155a16..10ac072 100644
--- a/src/pkg/syscall/zsyscall_netbsd_386.go
+++ b/src/pkg/syscall/zsyscall_netbsd_386.go
@@ -131,7 +131,7 @@ func Shutdown(s int, how int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e1 != 0 {
 		err = e1
@@ -223,7 +223,12 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func utimes(path string, timeval *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -253,8 +258,10 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe2(p *[2]_C_int, flags _C_int) (err error) {
-	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+func pipe() (fd1 int, fd2 int, err error) {
+	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
+	fd1 = int(r0)
+	fd2 = int(r1)
 	if e1 != 0 {
 		err = e1
 	}
@@ -281,7 +288,12 @@ func getdents(fd int, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -301,7 +313,12 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -311,7 +328,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -321,7 +343,12 @@ func Chflags(path string, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -331,7 +358,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -341,7 +373,12 @@ func Chown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -399,7 +436,12 @@ func Fchdir(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -606,7 +648,7 @@ func Issetugid() (tainted bool) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kill(pid int, signum int) (err error) {
+func Kill(pid int, signum Signal) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0)
 	if e1 != 0 {
 		err = e1
@@ -628,7 +670,12 @@ func Kqueue() (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -638,7 +685,17 @@ func Lchown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -658,7 +715,12 @@ func Listen(s int, backlog int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -668,7 +730,12 @@ func Lstat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -678,7 +745,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkfifo(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -688,7 +760,12 @@ func Mkfifo(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -708,7 +785,12 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -719,7 +801,12 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Pathconf(path string, name int) (val int, err error) {
-	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
 	val = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -763,7 +850,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -781,13 +868,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -798,7 +890,17 @@ func Readlink(path string, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rename(from string, to string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -808,7 +910,12 @@ func Rename(from string, to string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Revoke(path string) (err error) {
-	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -818,7 +925,12 @@ func Revoke(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -960,7 +1072,12 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -970,7 +1087,17 @@ func Stat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -990,7 +1117,12 @@ func Sync() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length), uintptr(length>>32), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1008,7 +1140,12 @@ func Umask(newmask int) (oldmask int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1018,7 +1155,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1027,7 +1169,7 @@ func Unmount(path string, flags int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -1065,7 +1207,7 @@ func munmap(addr uintptr, length uintptr) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, err error) {
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
@@ -1076,7 +1218,7 @@ func read(fd int, buf *byte, nbuf int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, err error) {
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
diff --git a/src/pkg/syscall/zsyscall_netbsd_amd64.go b/src/pkg/syscall/zsyscall_netbsd_amd64.go
index d68cd86..f10dc0b 100644
--- a/src/pkg/syscall/zsyscall_netbsd_amd64.go
+++ b/src/pkg/syscall/zsyscall_netbsd_amd64.go
@@ -131,7 +131,7 @@ func Shutdown(s int, how int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e1 != 0 {
 		err = e1
@@ -223,7 +223,12 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func utimes(path string, timeval *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -253,8 +258,10 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe2(p *[2]_C_int, flags _C_int) (err error) {
-	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+func pipe() (fd1 int, fd2 int, err error) {
+	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
+	fd1 = int(r0)
+	fd2 = int(r1)
 	if e1 != 0 {
 		err = e1
 	}
@@ -281,7 +288,12 @@ func getdents(fd int, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -301,7 +313,12 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -311,7 +328,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -321,7 +343,12 @@ func Chflags(path string, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -331,7 +358,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -341,7 +373,12 @@ func Chown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -399,7 +436,12 @@ func Fchdir(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -606,7 +648,7 @@ func Issetugid() (tainted bool) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kill(pid int, signum int) (err error) {
+func Kill(pid int, signum Signal) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0)
 	if e1 != 0 {
 		err = e1
@@ -628,7 +670,12 @@ func Kqueue() (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -638,7 +685,17 @@ func Lchown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -658,7 +715,12 @@ func Listen(s int, backlog int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -668,7 +730,12 @@ func Lstat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -678,7 +745,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkfifo(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -688,7 +760,12 @@ func Mkfifo(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -708,7 +785,12 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -719,7 +801,12 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Pathconf(path string, name int) (val int, err error) {
-	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
 	val = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -763,7 +850,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -781,13 +868,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -798,7 +890,17 @@ func Readlink(path string, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rename(from string, to string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -808,7 +910,12 @@ func Rename(from string, to string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Revoke(path string) (err error) {
-	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -818,7 +925,12 @@ func Revoke(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -960,7 +1072,12 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -970,7 +1087,17 @@ func Stat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -990,7 +1117,12 @@ func Sync() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1008,7 +1140,12 @@ func Umask(newmask int) (oldmask int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1018,7 +1155,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1027,7 +1169,7 @@ func Unmount(path string, flags int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -1065,7 +1207,7 @@ func munmap(addr uintptr, length uintptr) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, err error) {
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
@@ -1076,7 +1218,7 @@ func read(fd int, buf *byte, nbuf int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, err error) {
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
diff --git a/src/pkg/syscall/zsyscall_netbsd_arm.go b/src/pkg/syscall/zsyscall_netbsd_arm.go
new file mode 100644
index 0000000..763a906
--- /dev/null
+++ b/src/pkg/syscall/zsyscall_netbsd_arm.go
@@ -0,0 +1,1228 @@
+// mksyscall.pl -l32 -netbsd syscall_bsd.go syscall_netbsd.go syscall_netbsd_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 getgroups(ngid int, gid *_Gid_t) (n int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setgroups(ngid int, gid *_Gid_t) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
+	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
+	wpid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socket(domain int, typ int, proto int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
+	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
+	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Shutdown(s int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
+	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error) {
+	r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
+	var _p0 unsafe.Pointer
+	if len(mib) > 0 {
+		_p0 = unsafe.Pointer(&mib[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimes(path string, timeval *[2]Timeval) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func futimes(fd int, timeval *[2]Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe() (fd1 int, fd2 int, err error) {
+	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
+	fd1 = int(r0)
+	fd2 = int(r1)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getdents(fd int, buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Access(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chdir(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chflags(path string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chmod(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chown(path string, uid int, gid int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chroot(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(fd int) (nfd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(fd), 0, 0)
+	nfd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup2(from int, to int) (err error) {
+	_, _, e1 := RawSyscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) {
+	Syscall(SYS_EXIT, uintptr(code), 0, 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchflags(path string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmod(fd int, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchown(fd int, uid int, gid int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Flock(fd int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fpathconf(fd int, name int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstat(fd int, stat *Stat_t) (err error) {
+	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fsync(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ftruncate(fd int, length int64) (err error) {
+	_, _, e1 := Syscall6(SYS_FTRUNCATE, uintptr(fd), 0, uintptr(length), uintptr(length>>32), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getegid() (egid int) {
+	r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0)
+	egid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Geteuid() (uid int) {
+	r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+	r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)
+	gid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgid(pid int) (pgid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
+	pgid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgrp() (pgrp int) {
+	r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0)
+	pgrp = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpid() (pid int) {
+	r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
+	pid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getppid() (ppid int) {
+	r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0)
+	ppid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpriority(which int, who int) (prio int, err error) {
+	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
+	prio = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(which int, lim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrusage(who int, rusage *Rusage) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getsid(pid int) (sid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0)
+	sid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getuid() (uid int) {
+	r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Issetugid() (tainted bool) {
+	r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0)
+	tainted = bool(r0 != 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, signum Signal) (err error) {
+	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kqueue() (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lchown(path string, uid int, gid int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Link(path string, link string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listen(s int, backlog int) (err error) {
+	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lstat(path string, stat *Stat_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkdir(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkfifo(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mknod(path string, mode uint32, dev int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
+	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Open(path string, mode int, perm uint32) (fd int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pathconf(path string, name int) (val int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Readlink(path string, buf []byte) (n int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(buf) > 0 {
+		_p1 = unsafe.Pointer(&buf[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Rename(from string, to string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Revoke(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Rmdir(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
+	r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), 0, uintptr(offset), uintptr(offset>>32), uintptr(whence), 0)
+	newoffset = int64(int64(r1)<<32 | int64(r0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
+	_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setegid(egid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seteuid(euid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// 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 Setpgid(pid int, pgid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 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 {
+		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 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setreuid(ruid int, euid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setrlimit(which int, lim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setsid() (pid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+	pid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Settimeofday(tp *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// 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 Stat(path string, stat *Stat_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Symlink(path string, link string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sync() (err error) {
+	_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Truncate(path string, length int64) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Umask(newmask int) (oldmask int) {
+	r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0)
+	oldmask = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unlink(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unmount(path string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func write(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
+	r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), uintptr(pos>>32), 0)
+	ret = uintptr(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func munmap(addr uintptr, length uintptr) (err error) {
+	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
diff --git a/src/pkg/syscall/zsyscall_openbsd_386.go b/src/pkg/syscall/zsyscall_openbsd_386.go
index c884923..60e907b 100644
--- a/src/pkg/syscall/zsyscall_openbsd_386.go
+++ b/src/pkg/syscall/zsyscall_openbsd_386.go
@@ -131,7 +131,7 @@ func Shutdown(s int, how int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e1 != 0 {
 		err = e1
@@ -223,7 +223,12 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func utimes(path string, timeval *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -264,7 +269,12 @@ func pipe(p *[2]_C_int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -284,7 +294,12 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -294,7 +309,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -304,7 +324,12 @@ func Chflags(path string, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -314,7 +339,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -324,7 +354,12 @@ func Chown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -382,7 +417,12 @@ func Fchdir(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -655,7 +695,12 @@ func Kqueue() (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -665,7 +710,17 @@ func Lchown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -685,7 +740,12 @@ func Listen(s int, backlog int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -695,7 +755,12 @@ func Lstat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -705,7 +770,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkfifo(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -715,7 +785,12 @@ func Mkfifo(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -735,7 +810,12 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -746,7 +826,12 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Pathconf(path string, name int) (val int, err error) {
-	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
 	val = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -790,7 +875,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -808,13 +893,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -825,7 +915,17 @@ func Readlink(path string, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rename(from string, to string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -835,7 +935,12 @@ func Rename(from string, to string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Revoke(path string) (err error) {
-	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -845,7 +950,12 @@ func Revoke(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -906,7 +1016,12 @@ func Setgid(gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Setlogin(name string) (err error) {
-	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(name)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -997,7 +1112,12 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1007,7 +1127,12 @@ func Stat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Statfs(path string, stat *Statfs_t) (err error) {
-	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1017,7 +1142,17 @@ func Statfs(path string, stat *Statfs_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1037,7 +1172,12 @@ func Sync() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length), uintptr(length>>32), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length), uintptr(length>>32), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1055,7 +1195,12 @@ func Umask(newmask int) (oldmask int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1065,7 +1210,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1074,7 +1224,7 @@ func Unmount(path string, flags int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -1112,7 +1262,7 @@ func munmap(addr uintptr, length uintptr) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, err error) {
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
@@ -1123,7 +1273,7 @@ func read(fd int, buf *byte, nbuf int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, err error) {
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
diff --git a/src/pkg/syscall/zsyscall_openbsd_amd64.go b/src/pkg/syscall/zsyscall_openbsd_amd64.go
index 7775646..1403dd7 100644
--- a/src/pkg/syscall/zsyscall_openbsd_amd64.go
+++ b/src/pkg/syscall/zsyscall_openbsd_amd64.go
@@ -131,7 +131,7 @@ func Shutdown(s int, how int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
 	if e1 != 0 {
 		err = e1
@@ -223,7 +223,12 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func utimes(path string, timeval *[2]Timeval) (err error) {
-	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -264,7 +269,12 @@ func pipe(p *[2]_C_int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Access(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -284,7 +294,12 @@ func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -294,7 +309,12 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -304,7 +324,12 @@ func Chflags(path string, flags int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chmod(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -314,7 +339,12 @@ func Chmod(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -324,7 +354,12 @@ func Chown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chroot(path string) (err error) {
-	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -382,7 +417,12 @@ func Fchdir(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Fchflags(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -655,7 +695,12 @@ func Kqueue() (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lchown(path string, uid int, gid int) (err error) {
-	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
 	if e1 != 0 {
 		err = e1
 	}
@@ -665,7 +710,17 @@ func Lchown(path string, uid int, gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Link(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -685,7 +740,12 @@ func Listen(s int, backlog int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Lstat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -695,7 +755,12 @@ func Lstat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkdir(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -705,7 +770,12 @@ func Mkdir(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mkfifo(path string, mode uint32) (err error) {
-	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -715,7 +785,12 @@ func Mkfifo(path string, mode uint32) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mknod(path string, mode uint32, dev int) (err error) {
-	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
 	if e1 != 0 {
 		err = e1
 	}
@@ -735,7 +810,12 @@ func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Open(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -746,7 +826,12 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Pathconf(path string, name int) (val int, err error) {
-	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0)
 	val = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -790,7 +875,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, err error) {
+func read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -808,13 +893,18 @@ func Read(fd int, p []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Readlink(path string, buf []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
+		_p1 = unsafe.Pointer(&buf[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -825,7 +915,17 @@ func Readlink(path string, buf []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rename(from string, to string) (err error) {
-	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -835,7 +935,12 @@ func Rename(from string, to string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Revoke(path string) (err error) {
-	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -845,7 +950,12 @@ func Revoke(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Rmdir(path string) (err error) {
-	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -906,7 +1016,12 @@ func Setgid(gid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Setlogin(name string) (err error) {
-	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(name)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -997,7 +1112,12 @@ func Setuid(uid int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, stat *Stat_t) (err error) {
-	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1007,7 +1127,12 @@ func Stat(path string, stat *Stat_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Statfs(path string, stat *Statfs_t) (err error) {
-	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1017,7 +1142,17 @@ func Statfs(path string, stat *Statfs_t) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Symlink(path string, link string) (err error) {
-	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1037,7 +1172,12 @@ func Sync() (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Truncate(path string, length int64) (err error) {
-	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length))
 	if e1 != 0 {
 		err = e1
 	}
@@ -1055,7 +1195,12 @@ func Umask(newmask int) (oldmask int) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unlink(path string) (err error) {
-	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1065,7 +1210,12 @@ func Unlink(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Unmount(path string, flags int) (err error) {
-	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
 	if e1 != 0 {
 		err = e1
 	}
@@ -1074,7 +1224,7 @@ func Unmount(path string, flags int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, err error) {
+func write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -1112,7 +1262,7 @@ func munmap(addr uintptr, length uintptr) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, err error) {
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
@@ -1123,7 +1273,7 @@ func read(fd int, buf *byte, nbuf int) (n int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, err error) {
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
 	if e1 != 0 {
diff --git a/src/pkg/syscall/zsyscall_plan9_386.go b/src/pkg/syscall/zsyscall_plan9_386.go
index 913c28f..5ffa0e4 100644
--- a/src/pkg/syscall/zsyscall_plan9_386.go
+++ b/src/pkg/syscall/zsyscall_plan9_386.go
@@ -7,13 +7,6 @@ import "unsafe"
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func exits(msg *byte) {
-	Syscall(SYS_EXITS, uintptr(unsafe.Pointer(msg)), 0, 0)
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func fd2path(fd int, buf []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
@@ -69,7 +62,12 @@ func Dup(oldfd int, newfd int) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Open(path string, mode int) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
 	fd = int(r0)
 	if int(r0) == -1 {
 		err = e1
@@ -80,7 +78,12 @@ func Open(path string, mode int) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Create(path string, mode int, perm uint32) (fd int, err error) {
-	r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
 	fd = int(r0)
 	if int(r0) == -1 {
 		err = e1
@@ -91,7 +94,12 @@ func Create(path string, mode int, perm uint32) (fd int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Remove(path string) (err error) {
-	r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if int(r0) == -1 {
 		err = e1
 	}
@@ -145,7 +153,12 @@ func Close(fd int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Chdir(path string) (err error) {
-	r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
 	if int(r0) == -1 {
 		err = e1
 	}
@@ -155,7 +168,17 @@ func Chdir(path string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Bind(name string, old string, flag int) (err error) {
-	r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(old))), uintptr(flag))
+	var _p0 *byte
+	_p0, err = BytePtrFromString(name)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(old)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
 	if int(r0) == -1 {
 		err = e1
 	}
@@ -165,7 +188,17 @@ func Bind(name string, old string, flag int) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
-	r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(StringBytePtr(old))), uintptr(flag), uintptr(unsafe.Pointer(StringBytePtr(aname))), 0)
+	var _p0 *byte
+	_p0, err = BytePtrFromString(old)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(aname)
+	if err != nil {
+		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 {
 		err = e1
 	}
@@ -175,13 +208,18 @@ func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Stat(path string, edir []byte) (n int, err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(edir) > 0 {
-		_p0 = unsafe.Pointer(&edir[0])
+		_p1 = unsafe.Pointer(&edir[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(edir)))
+	r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
 	n = int(r0)
 	if int(r0) == -1 {
 		err = e1
@@ -209,13 +247,18 @@ func Fstat(fd int, edir []byte) (n int, err error) {
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
 func Wstat(path string, edir []byte) (err error) {
-	var _p0 unsafe.Pointer
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
 	if len(edir) > 0 {
-		_p0 = unsafe.Pointer(&edir[0])
+		_p1 = unsafe.Pointer(&edir[0])
 	} else {
-		_p0 = unsafe.Pointer(&_zero)
+		_p1 = unsafe.Pointer(&_zero)
 	}
-	r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(edir)))
+	r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
 	if int(r0) == -1 {
 		err = e1
 	}
diff --git a/src/pkg/syscall/zsyscall_plan9_amd64.go b/src/pkg/syscall/zsyscall_plan9_amd64.go
new file mode 100644
index 0000000..c64533f
--- /dev/null
+++ b/src/pkg/syscall/zsyscall_plan9_amd64.go
@@ -0,0 +1,282 @@
+// mksyscall.pl -l32 -plan9 syscall_plan9.go syscall_plan9_amd64.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 fd2path(fd int, buf []byte) (err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe(p *[2]_C_int) (err error) {
+	r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func await(s []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(s) > 0 {
+		_p0 = unsafe.Pointer(&s[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
+	n = int(r0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int, newfd int) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
+	fd = int(r0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Open(path string, mode int) (fd int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+	fd = int(r0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Create(path string, mode int, perm uint32) (fd int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+	fd = int(r0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Remove(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+	n = int(r0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+	n = int(r0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+	r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chdir(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Bind(name string, old string, flag int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(name)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(old)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(old)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(aname)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Stat(path string, edir []byte) (n int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(edir) > 0 {
+		_p1 = unsafe.Pointer(&edir[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+	n = int(r0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstat(fd int, edir []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(edir) > 0 {
+		_p0 = unsafe.Pointer(&edir[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+	n = int(r0)
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Wstat(path string, edir []byte) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(edir) > 0 {
+		_p1 = unsafe.Pointer(&edir[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fwstat(fd int, edir []byte) (err error) {
+	var _p0 unsafe.Pointer
+	if len(edir) > 0 {
+		_p0 = unsafe.Pointer(&edir[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+	if int32(r0) == -1 {
+		err = e1
+	}
+	return
+}
diff --git a/src/pkg/syscall/zsyscall_windows_386.go b/src/pkg/syscall/zsyscall_windows_386.go
index 3022ce2..e5c4848 100644
--- a/src/pkg/syscall/zsyscall_windows_386.go
+++ b/src/pkg/syscall/zsyscall_windows_386.go
@@ -49,6 +49,7 @@ var (
 	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")
@@ -103,11 +104,16 @@ var (
 	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")
@@ -127,6 +133,8 @@ var (
 	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")
 	procTranslateNameW                   = modsecur32.NewProc("TranslateNameW")
@@ -142,7 +150,6 @@ var (
 	procOpenProcessToken                 = modadvapi32.NewProc("OpenProcessToken")
 	procGetTokenInformation              = modadvapi32.NewProc("GetTokenInformation")
 	procGetUserProfileDirectoryW         = moduserenv.NewProc("GetUserProfileDirectoryW")
-	procgetCurrentProcessId              = modkernel32.NewProc("GetCurrentProcessId")
 )
 
 func GetLastError() (lasterr error) {
@@ -154,7 +161,12 @@ func GetLastError() (lasterr error) {
 }
 
 func LoadLibrary(libname string) (handle Handle, err error) {
-	r0, _, e1 := Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(StringToUTF16Ptr(libname))), 0, 0)
+	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 {
@@ -168,7 +180,7 @@ func LoadLibrary(libname string) (handle Handle, err error) {
 
 func FreeLibrary(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -179,7 +191,12 @@ func FreeLibrary(handle Handle) (err error) {
 }
 
 func GetProcAddress(module Handle, procname string) (proc uintptr, err error) {
-	r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(StringBytePtr(procname))), 0)
+	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 {
@@ -245,7 +262,7 @@ func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (
 		_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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -261,7 +278,7 @@ func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped)
 		_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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -286,7 +303,7 @@ func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence
 
 func CloseHandle(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -324,7 +341,7 @@ func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err erro
 
 func findNextFile1(handle Handle, data *win32finddata1) (err error) {
 	r1, _, e1 := Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -336,7 +353,7 @@ func findNextFile1(handle Handle, data *win32finddata1) (err error) {
 
 func FindClose(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -348,7 +365,7 @@ func FindClose(handle Handle) (err error) {
 
 func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) {
 	r1, _, e1 := Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -373,7 +390,7 @@ func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) {
 
 func SetCurrentDirectory(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -385,7 +402,7 @@ func SetCurrentDirectory(path *uint16) (err error) {
 
 func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) {
 	r1, _, e1 := Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -397,7 +414,7 @@ func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) {
 
 func RemoveDirectory(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -409,7 +426,7 @@ func RemoveDirectory(path *uint16) (err error) {
 
 func DeleteFile(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -421,7 +438,7 @@ func DeleteFile(path *uint16) (err error) {
 
 func MoveFile(from *uint16, to *uint16) (err error) {
 	r1, _, e1 := Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -433,7 +450,7 @@ func MoveFile(from *uint16, to *uint16) (err error) {
 
 func GetComputerName(buf *uint16, n *uint32) (err error) {
 	r1, _, e1 := Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -445,7 +462,7 @@ func GetComputerName(buf *uint16, n *uint32) (err error) {
 
 func SetEndOfFile(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -488,7 +505,7 @@ func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, thre
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -500,7 +517,7 @@ func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overla
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -512,7 +529,19 @@ func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlap
 
 func CancelIo(s Handle) (err error) {
 	r1, _, e1 := Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0)
-	if int(r1) == 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 {
@@ -530,7 +559,7 @@ func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityA
 		_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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -561,7 +590,7 @@ func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err
 
 func TerminateProcess(handle Handle, exitcode uint32) (err error) {
 	r1, _, e1 := Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -573,7 +602,7 @@ func TerminateProcess(handle Handle, exitcode uint32) (err error) {
 
 func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) {
 	r1, _, e1 := Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -585,7 +614,7 @@ func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) {
 
 func GetStartupInfo(startupInfo *StartupInfo) (err error) {
 	r1, _, e1 := Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -610,7 +639,7 @@ func GetCurrentProcess() (pseudoHandle Handle, err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -628,7 +657,7 @@ func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetP
 		_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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -666,7 +695,7 @@ func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -691,7 +720,7 @@ func GetFileType(filehandle Handle) (n uint32, err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -703,7 +732,7 @@ func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16
 
 func CryptReleaseContext(provhandle Handle, flags uint32) (err error) {
 	r1, _, e1 := Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -715,7 +744,7 @@ func CryptReleaseContext(provhandle Handle, flags uint32) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -740,7 +769,7 @@ func GetEnvironmentStrings() (envs *uint16, err error) {
 
 func FreeEnvironmentStrings(envs *uint16) (err error) {
 	r1, _, e1 := Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -765,7 +794,7 @@ func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32
 
 func SetEnvironmentVariable(name *uint16, value *uint16) (err error) {
 	r1, _, e1 := Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -777,7 +806,7 @@ func SetEnvironmentVariable(name *uint16, value *uint16) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -802,7 +831,7 @@ func GetFileAttributes(name *uint16) (attrs uint32, err error) {
 
 func SetFileAttributes(name *uint16, attrs uint32) (err error) {
 	r1, _, e1 := Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -814,7 +843,7 @@ func SetFileAttributes(name *uint16, attrs uint32) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -858,7 +887,7 @@ func LocalFree(hmem Handle) (handle Handle, err error) {
 
 func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) {
 	r1, _, e1 := Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags))
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -870,7 +899,7 @@ func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error)
 
 func FlushFileBuffers(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -947,7 +976,7 @@ func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow ui
 
 func UnmapViewOfFile(addr uintptr) (err error) {
 	r1, _, e1 := Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -959,7 +988,7 @@ func UnmapViewOfFile(addr uintptr) (err error) {
 
 func FlushViewOfFile(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -971,7 +1000,7 @@ func FlushViewOfFile(addr uintptr, length uintptr) (err error) {
 
 func VirtualLock(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -983,7 +1012,7 @@ func VirtualLock(addr uintptr, length uintptr) (err error) {
 
 func VirtualUnlock(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -995,7 +1024,7 @@ func VirtualUnlock(addr uintptr, length uintptr) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1013,7 +1042,7 @@ func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree
 		_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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1064,7 +1093,7 @@ func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (contex
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1076,7 +1105,7 @@ func CertAddCertificateContextToStore(store Handle, certContext *CertContext, ad
 
 func CertCloseStore(store Handle, flags uint32) (err error) {
 	r1, _, e1 := Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1088,7 +1117,7 @@ func CertCloseStore(store Handle, flags uint32) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1118,7 +1147,7 @@ func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, en
 
 func CertFreeCertificateContext(ctx *CertContext) (err error) {
 	r1, _, e1 := Syscall(procCertFreeCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1130,7 +1159,7 @@ func CertFreeCertificateContext(ctx *CertContext) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1180,6 +1209,48 @@ func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32
 	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 {
@@ -1190,7 +1261,7 @@ func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
 
 func WSACleanup() (err error) {
 	r1, _, e1 := Syscall(procWSACleanup.Addr(), 0, 0, 0, 0)
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1202,7 +1273,7 @@ func WSACleanup() (err error) {
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1227,7 +1298,19 @@ func socket(af int32, typ int32, protocol int32) (handle Handle, err error) {
 
 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 int(r1) == -1 {
+	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 {
@@ -1239,7 +1322,7 @@ func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32
 
 func bind(s Handle, name uintptr, namelen int32) (err error) {
 	r1, _, e1 := Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1251,7 +1334,7 @@ func bind(s Handle, name uintptr, namelen int32) (err error) {
 
 func connect(s Handle, name uintptr, namelen int32) (err error) {
 	r1, _, e1 := Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1263,7 +1346,7 @@ func connect(s Handle, name uintptr, namelen int32) (err error) {
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1275,7 +1358,7 @@ func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) {
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1287,7 +1370,7 @@ func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) {
 
 func listen(s Handle, backlog int32) (err error) {
 	r1, _, e1 := Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0)
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1299,7 +1382,7 @@ func listen(s Handle, backlog int32) (err error) {
 
 func shutdown(s Handle, how int32) (err error) {
 	r1, _, e1 := Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0)
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1311,7 +1394,7 @@ func shutdown(s Handle, how int32) (err error) {
 
 func Closesocket(s Handle) (err error) {
 	r1, _, e1 := Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0)
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1323,7 +1406,7 @@ func Closesocket(s Handle) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1340,7 +1423,7 @@ func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1352,7 +1435,7 @@ func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1364,7 +1447,7 @@ func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32,
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1376,7 +1459,7 @@ func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *ui
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1387,7 +1470,12 @@ func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32
 }
 
 func GetHostByName(name string) (h *Hostent, err error) {
-	r0, _, e1 := Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	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 {
@@ -1400,7 +1488,17 @@ func GetHostByName(name string) (h *Hostent, err error) {
 }
 
 func GetServByName(name string, proto string) (s *Servent, err error) {
-	r0, _, e1 := Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(proto))), 0)
+	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 {
@@ -1419,7 +1517,12 @@ func Ntohs(netshort uint16) (u uint16) {
 }
 
 func GetProtoByName(name string) (p *Protoent, err error) {
-	r0, _, e1 := Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	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 {
@@ -1432,7 +1535,12 @@ func GetProtoByName(name string) (p *Protoent, err error) {
 }
 
 func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) {
-	r0, _, _ := Syscall6(procDnsQuery_W.Addr(), 6, uintptr(unsafe.Pointer(StringToUTF16Ptr(name))), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr)))
+	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)
 	}
@@ -1444,6 +1552,19 @@ func DnsRecordListFree(rl *DNSRecord, freetype uint32) {
 	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 {
@@ -1462,7 +1583,7 @@ func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) {
 
 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 int(r1)&0xff == 0 {
+	if r1&0xff == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1474,7 +1595,7 @@ func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint
 
 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 int(r1)&0xff == 0 {
+	if r1&0xff == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1502,7 +1623,7 @@ func NetApiBufferFree(buf *byte) (neterr error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1514,7 +1635,7 @@ func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint3
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1526,7 +1647,7 @@ func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen
 
 func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) {
 	r1, _, e1 := Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1538,7 +1659,7 @@ func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) {
 
 func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) {
 	r1, _, e1 := Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1556,7 +1677,7 @@ func GetLengthSid(sid *SID) (len uint32) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1568,7 +1689,7 @@ func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1580,7 +1701,7 @@ func OpenProcessToken(h Handle, access uint32, token *Token) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1592,7 +1713,7 @@ func GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32,
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1601,9 +1722,3 @@ func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) {
 	}
 	return
 }
-
-func getCurrentProcessId() (pid uint32) {
-	r0, _, _ := Syscall(procgetCurrentProcessId.Addr(), 0, 0, 0, 0)
-	pid = uint32(r0)
-	return
-}
diff --git a/src/pkg/syscall/zsyscall_windows_amd64.go b/src/pkg/syscall/zsyscall_windows_amd64.go
index ea0000c..465b509 100644
--- a/src/pkg/syscall/zsyscall_windows_amd64.go
+++ b/src/pkg/syscall/zsyscall_windows_amd64.go
@@ -49,6 +49,7 @@ var (
 	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")
@@ -103,11 +104,16 @@ var (
 	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")
@@ -127,6 +133,8 @@ var (
 	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")
 	procTranslateNameW                   = modsecur32.NewProc("TranslateNameW")
@@ -142,7 +150,6 @@ var (
 	procOpenProcessToken                 = modadvapi32.NewProc("OpenProcessToken")
 	procGetTokenInformation              = modadvapi32.NewProc("GetTokenInformation")
 	procGetUserProfileDirectoryW         = moduserenv.NewProc("GetUserProfileDirectoryW")
-	procgetCurrentProcessId              = modkernel32.NewProc("GetCurrentProcessId")
 )
 
 func GetLastError() (lasterr error) {
@@ -154,7 +161,12 @@ func GetLastError() (lasterr error) {
 }
 
 func LoadLibrary(libname string) (handle Handle, err error) {
-	r0, _, e1 := Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(StringToUTF16Ptr(libname))), 0, 0)
+	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 {
@@ -168,7 +180,7 @@ func LoadLibrary(libname string) (handle Handle, err error) {
 
 func FreeLibrary(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -179,7 +191,12 @@ func FreeLibrary(handle Handle) (err error) {
 }
 
 func GetProcAddress(module Handle, procname string) (proc uintptr, err error) {
-	r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(StringBytePtr(procname))), 0)
+	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 {
@@ -245,7 +262,7 @@ func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (
 		_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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -261,7 +278,7 @@ func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped)
 		_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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -286,7 +303,7 @@ func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence
 
 func CloseHandle(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -324,7 +341,7 @@ func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err erro
 
 func findNextFile1(handle Handle, data *win32finddata1) (err error) {
 	r1, _, e1 := Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -336,7 +353,7 @@ func findNextFile1(handle Handle, data *win32finddata1) (err error) {
 
 func FindClose(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -348,7 +365,7 @@ func FindClose(handle Handle) (err error) {
 
 func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) {
 	r1, _, e1 := Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -373,7 +390,7 @@ func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) {
 
 func SetCurrentDirectory(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -385,7 +402,7 @@ func SetCurrentDirectory(path *uint16) (err error) {
 
 func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) {
 	r1, _, e1 := Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -397,7 +414,7 @@ func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) {
 
 func RemoveDirectory(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -409,7 +426,7 @@ func RemoveDirectory(path *uint16) (err error) {
 
 func DeleteFile(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -421,7 +438,7 @@ func DeleteFile(path *uint16) (err error) {
 
 func MoveFile(from *uint16, to *uint16) (err error) {
 	r1, _, e1 := Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -433,7 +450,7 @@ func MoveFile(from *uint16, to *uint16) (err error) {
 
 func GetComputerName(buf *uint16, n *uint32) (err error) {
 	r1, _, e1 := Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -445,7 +462,7 @@ func GetComputerName(buf *uint16, n *uint32) (err error) {
 
 func SetEndOfFile(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -488,7 +505,7 @@ func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, thre
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -500,7 +517,7 @@ func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overla
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -512,7 +529,19 @@ func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlap
 
 func CancelIo(s Handle) (err error) {
 	r1, _, e1 := Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0)
-	if int(r1) == 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 {
@@ -530,7 +559,7 @@ func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityA
 		_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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -561,7 +590,7 @@ func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err
 
 func TerminateProcess(handle Handle, exitcode uint32) (err error) {
 	r1, _, e1 := Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -573,7 +602,7 @@ func TerminateProcess(handle Handle, exitcode uint32) (err error) {
 
 func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) {
 	r1, _, e1 := Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -585,7 +614,7 @@ func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) {
 
 func GetStartupInfo(startupInfo *StartupInfo) (err error) {
 	r1, _, e1 := Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -610,7 +639,7 @@ func GetCurrentProcess() (pseudoHandle Handle, err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -628,7 +657,7 @@ func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetP
 		_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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -666,7 +695,7 @@ func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -691,7 +720,7 @@ func GetFileType(filehandle Handle) (n uint32, err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -703,7 +732,7 @@ func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16
 
 func CryptReleaseContext(provhandle Handle, flags uint32) (err error) {
 	r1, _, e1 := Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -715,7 +744,7 @@ func CryptReleaseContext(provhandle Handle, flags uint32) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -740,7 +769,7 @@ func GetEnvironmentStrings() (envs *uint16, err error) {
 
 func FreeEnvironmentStrings(envs *uint16) (err error) {
 	r1, _, e1 := Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -765,7 +794,7 @@ func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32
 
 func SetEnvironmentVariable(name *uint16, value *uint16) (err error) {
 	r1, _, e1 := Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -777,7 +806,7 @@ func SetEnvironmentVariable(name *uint16, value *uint16) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -802,7 +831,7 @@ func GetFileAttributes(name *uint16) (attrs uint32, err error) {
 
 func SetFileAttributes(name *uint16, attrs uint32) (err error) {
 	r1, _, e1 := Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -814,7 +843,7 @@ func SetFileAttributes(name *uint16, attrs uint32) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -858,7 +887,7 @@ func LocalFree(hmem Handle) (handle Handle, err error) {
 
 func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) {
 	r1, _, e1 := Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags))
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -870,7 +899,7 @@ func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error)
 
 func FlushFileBuffers(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -947,7 +976,7 @@ func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow ui
 
 func UnmapViewOfFile(addr uintptr) (err error) {
 	r1, _, e1 := Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -959,7 +988,7 @@ func UnmapViewOfFile(addr uintptr) (err error) {
 
 func FlushViewOfFile(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -971,7 +1000,7 @@ func FlushViewOfFile(addr uintptr, length uintptr) (err error) {
 
 func VirtualLock(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -983,7 +1012,7 @@ func VirtualLock(addr uintptr, length uintptr) (err error) {
 
 func VirtualUnlock(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -995,7 +1024,7 @@ func VirtualUnlock(addr uintptr, length uintptr) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1013,7 +1042,7 @@ func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree
 		_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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1064,7 +1093,7 @@ func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (contex
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1076,7 +1105,7 @@ func CertAddCertificateContextToStore(store Handle, certContext *CertContext, ad
 
 func CertCloseStore(store Handle, flags uint32) (err error) {
 	r1, _, e1 := Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1088,7 +1117,7 @@ func CertCloseStore(store Handle, flags uint32) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1118,7 +1147,7 @@ func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, en
 
 func CertFreeCertificateContext(ctx *CertContext) (err error) {
 	r1, _, e1 := Syscall(procCertFreeCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1130,7 +1159,7 @@ func CertFreeCertificateContext(ctx *CertContext) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1180,6 +1209,48 @@ func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32
 	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 {
@@ -1190,7 +1261,7 @@ func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
 
 func WSACleanup() (err error) {
 	r1, _, e1 := Syscall(procWSACleanup.Addr(), 0, 0, 0, 0)
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1202,7 +1273,7 @@ func WSACleanup() (err error) {
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1227,7 +1298,19 @@ func socket(af int32, typ int32, protocol int32) (handle Handle, err error) {
 
 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 int(r1) == -1 {
+	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 {
@@ -1239,7 +1322,7 @@ func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32
 
 func bind(s Handle, name uintptr, namelen int32) (err error) {
 	r1, _, e1 := Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1251,7 +1334,7 @@ func bind(s Handle, name uintptr, namelen int32) (err error) {
 
 func connect(s Handle, name uintptr, namelen int32) (err error) {
 	r1, _, e1 := Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1263,7 +1346,7 @@ func connect(s Handle, name uintptr, namelen int32) (err error) {
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1275,7 +1358,7 @@ func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) {
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1287,7 +1370,7 @@ func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) {
 
 func listen(s Handle, backlog int32) (err error) {
 	r1, _, e1 := Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0)
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1299,7 +1382,7 @@ func listen(s Handle, backlog int32) (err error) {
 
 func shutdown(s Handle, how int32) (err error) {
 	r1, _, e1 := Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0)
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1311,7 +1394,7 @@ func shutdown(s Handle, how int32) (err error) {
 
 func Closesocket(s Handle) (err error) {
 	r1, _, e1 := Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0)
-	if int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1323,7 +1406,7 @@ func Closesocket(s Handle) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1340,7 +1423,7 @@ func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1352,7 +1435,7 @@ func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1364,7 +1447,7 @@ func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32,
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1376,7 +1459,7 @@ func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *ui
 
 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 int(r1) == -1 {
+	if r1 == socket_error {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1387,7 +1470,12 @@ func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32
 }
 
 func GetHostByName(name string) (h *Hostent, err error) {
-	r0, _, e1 := Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	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 {
@@ -1400,7 +1488,17 @@ func GetHostByName(name string) (h *Hostent, err error) {
 }
 
 func GetServByName(name string, proto string) (s *Servent, err error) {
-	r0, _, e1 := Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(proto))), 0)
+	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 {
@@ -1419,7 +1517,12 @@ func Ntohs(netshort uint16) (u uint16) {
 }
 
 func GetProtoByName(name string) (p *Protoent, err error) {
-	r0, _, e1 := Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	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 {
@@ -1432,7 +1535,12 @@ func GetProtoByName(name string) (p *Protoent, err error) {
 }
 
 func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) {
-	r0, _, _ := Syscall6(procDnsQuery_W.Addr(), 6, uintptr(unsafe.Pointer(StringToUTF16Ptr(name))), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr)))
+	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)
 	}
@@ -1444,6 +1552,19 @@ func DnsRecordListFree(rl *DNSRecord, freetype uint32) {
 	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 {
@@ -1462,7 +1583,7 @@ func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) {
 
 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 int(r1)&0xff == 0 {
+	if r1&0xff == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1474,7 +1595,7 @@ func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint
 
 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 int(r1)&0xff == 0 {
+	if r1&0xff == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1502,7 +1623,7 @@ func NetApiBufferFree(buf *byte) (neterr error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1514,7 +1635,7 @@ func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint3
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1526,7 +1647,7 @@ func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen
 
 func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) {
 	r1, _, e1 := Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1538,7 +1659,7 @@ func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) {
 
 func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) {
 	r1, _, e1 := Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid)), 0)
-	if int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1556,7 +1677,7 @@ func GetLengthSid(sid *SID) (len uint32) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1568,7 +1689,7 @@ func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1580,7 +1701,7 @@ func OpenProcessToken(h Handle, access uint32, token *Token) (err error) {
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1592,7 +1713,7 @@ func GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32,
 
 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 int(r1) == 0 {
+	if r1 == 0 {
 		if e1 != 0 {
 			err = error(e1)
 		} else {
@@ -1601,9 +1722,3 @@ func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) {
 	}
 	return
 }
-
-func getCurrentProcessId() (pid uint32) {
-	r0, _, _ := Syscall(procgetCurrentProcessId.Addr(), 0, 0, 0, 0)
-	pid = uint32(r0)
-	return
-}
diff --git a/src/pkg/syscall/zsysctl_openbsd.go b/src/pkg/syscall/zsysctl_openbsd.go
index fb13422..a5914f3 100644
--- a/src/pkg/syscall/zsysctl_openbsd.go
+++ b/src/pkg/syscall/zsysctl_openbsd.go
@@ -64,6 +64,7 @@ var sysctlMib = []mibentry{
 	{"kern.maxlocksperuid", []_C_int{1, 70}},
 	{"kern.maxpartitions", []_C_int{1, 23}},
 	{"kern.maxproc", []_C_int{1, 6}},
+	{"kern.maxthread", []_C_int{1, 25}},
 	{"kern.maxvnodes", []_C_int{1, 5}},
 	{"kern.mbstat", []_C_int{1, 59}},
 	{"kern.msgbuf", []_C_int{1, 48}},
@@ -75,6 +76,7 @@ var sysctlMib = []mibentry{
 	{"kern.nosuidcoredump", []_C_int{1, 32}},
 	{"kern.nprocs", []_C_int{1, 47}},
 	{"kern.nselcoll", []_C_int{1, 43}},
+	{"kern.nthreads", []_C_int{1, 26}},
 	{"kern.numvnodes", []_C_int{1, 58}},
 	{"kern.osrelease", []_C_int{1, 2}},
 	{"kern.osrevision", []_C_int{1, 3}},
diff --git a/src/pkg/syscall/zsysnum_freebsd_386.go b/src/pkg/syscall/zsysnum_freebsd_386.go
index e986aba..5a2bfd1 100644
--- a/src/pkg/syscall/zsysnum_freebsd_386.go
+++ b/src/pkg/syscall/zsysnum_freebsd_386.go
@@ -1,4 +1,4 @@
-// mksysnum_freebsd.pl 
+// mksysnum_freebsd.pl
 // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
 
 package syscall
diff --git a/src/pkg/syscall/zsysnum_freebsd_amd64.go b/src/pkg/syscall/zsysnum_freebsd_amd64.go
index e986aba..5a2bfd1 100644
--- a/src/pkg/syscall/zsysnum_freebsd_amd64.go
+++ b/src/pkg/syscall/zsysnum_freebsd_amd64.go
@@ -1,4 +1,4 @@
-// mksysnum_freebsd.pl 
+// mksysnum_freebsd.pl
 // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
 
 package syscall
diff --git a/src/pkg/syscall/zsysnum_freebsd_arm.go b/src/pkg/syscall/zsysnum_freebsd_arm.go
new file mode 100644
index 0000000..5a2bfd1
--- /dev/null
+++ b/src/pkg/syscall/zsysnum_freebsd_arm.go
@@ -0,0 +1,340 @@
+// mksysnum_freebsd.pl
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+	// SYS_NOSYS = 0;  // { int nosys(void); } syscall nosys_args int
+	SYS_EXIT                     = 1   // { void sys_exit(int rval); } exit \
+	SYS_FORK                     = 2   // { int fork(void); }
+	SYS_READ                     = 3   // { ssize_t read(int fd, void *buf, \
+	SYS_WRITE                    = 4   // { ssize_t write(int fd, const void *buf, \
+	SYS_OPEN                     = 5   // { int open(char *path, int flags, int mode); }
+	SYS_CLOSE                    = 6   // { int close(int fd); }
+	SYS_WAIT4                    = 7   // { int wait4(int pid, int *status, \
+	SYS_LINK                     = 9   // { int link(char *path, char *link); }
+	SYS_UNLINK                   = 10  // { int unlink(char *path); }
+	SYS_CHDIR                    = 12  // { int chdir(char *path); }
+	SYS_FCHDIR                   = 13  // { int fchdir(int fd); }
+	SYS_MKNOD                    = 14  // { int mknod(char *path, int mode, int dev); }
+	SYS_CHMOD                    = 15  // { int chmod(char *path, int mode); }
+	SYS_CHOWN                    = 16  // { int chown(char *path, int uid, int gid); }
+	SYS_OBREAK                   = 17  // { int obreak(char *nsize); } break \
+	SYS_GETPID                   = 20  // { pid_t getpid(void); }
+	SYS_MOUNT                    = 21  // { int mount(char *type, char *path, \
+	SYS_UNMOUNT                  = 22  // { int unmount(char *path, int flags); }
+	SYS_SETUID                   = 23  // { int setuid(uid_t uid); }
+	SYS_GETUID                   = 24  // { uid_t getuid(void); }
+	SYS_GETEUID                  = 25  // { uid_t geteuid(void); }
+	SYS_PTRACE                   = 26  // { int ptrace(int req, pid_t pid, \
+	SYS_RECVMSG                  = 27  // { int recvmsg(int s, struct msghdr *msg, \
+	SYS_SENDMSG                  = 28  // { int sendmsg(int s, struct msghdr *msg, \
+	SYS_RECVFROM                 = 29  // { int recvfrom(int s, caddr_t buf, \
+	SYS_ACCEPT                   = 30  // { int accept(int s, \
+	SYS_GETPEERNAME              = 31  // { int getpeername(int fdes, \
+	SYS_GETSOCKNAME              = 32  // { int getsockname(int fdes, \
+	SYS_ACCESS                   = 33  // { int access(char *path, int amode); }
+	SYS_CHFLAGS                  = 34  // { int chflags(char *path, int flags); }
+	SYS_FCHFLAGS                 = 35  // { int fchflags(int fd, int flags); }
+	SYS_SYNC                     = 36  // { int sync(void); }
+	SYS_KILL                     = 37  // { int kill(int pid, int signum); }
+	SYS_GETPPID                  = 39  // { pid_t getppid(void); }
+	SYS_DUP                      = 41  // { int dup(u_int fd); }
+	SYS_PIPE                     = 42  // { int pipe(void); }
+	SYS_GETEGID                  = 43  // { gid_t getegid(void); }
+	SYS_PROFIL                   = 44  // { int profil(caddr_t samples, size_t size, \
+	SYS_KTRACE                   = 45  // { int ktrace(const char *fname, int ops, \
+	SYS_GETGID                   = 47  // { gid_t getgid(void); }
+	SYS_GETLOGIN                 = 49  // { int getlogin(char *namebuf, u_int \
+	SYS_SETLOGIN                 = 50  // { int setlogin(char *namebuf); }
+	SYS_ACCT                     = 51  // { int acct(char *path); }
+	SYS_SIGALTSTACK              = 53  // { int sigaltstack(stack_t *ss, \
+	SYS_IOCTL                    = 54  // { int ioctl(int fd, u_long com, \
+	SYS_REBOOT                   = 55  // { int reboot(int opt); }
+	SYS_REVOKE                   = 56  // { int revoke(char *path); }
+	SYS_SYMLINK                  = 57  // { int symlink(char *path, char *link); }
+	SYS_READLINK                 = 58  // { ssize_t readlink(char *path, char *buf, \
+	SYS_EXECVE                   = 59  // { int execve(char *fname, char **argv, \
+	SYS_UMASK                    = 60  // { int umask(int newmask); } umask umask_args \
+	SYS_CHROOT                   = 61  // { int chroot(char *path); }
+	SYS_MSYNC                    = 65  // { int msync(void *addr, size_t len, \
+	SYS_VFORK                    = 66  // { int vfork(void); }
+	SYS_SBRK                     = 69  // { int sbrk(int incr); }
+	SYS_SSTK                     = 70  // { int sstk(int incr); }
+	SYS_OVADVISE                 = 72  // { int ovadvise(int anom); } vadvise \
+	SYS_MUNMAP                   = 73  // { int munmap(void *addr, size_t len); }
+	SYS_MPROTECT                 = 74  // { int mprotect(const void *addr, size_t len, \
+	SYS_MADVISE                  = 75  // { int madvise(void *addr, size_t len, \
+	SYS_MINCORE                  = 78  // { int mincore(const void *addr, size_t len, \
+	SYS_GETGROUPS                = 79  // { int getgroups(u_int gidsetsize, \
+	SYS_SETGROUPS                = 80  // { int setgroups(u_int gidsetsize, \
+	SYS_GETPGRP                  = 81  // { int getpgrp(void); }
+	SYS_SETPGID                  = 82  // { int setpgid(int pid, int pgid); }
+	SYS_SETITIMER                = 83  // { int setitimer(u_int which, struct \
+	SYS_SWAPON                   = 85  // { int swapon(char *name); }
+	SYS_GETITIMER                = 86  // { int getitimer(u_int which, \
+	SYS_GETDTABLESIZE            = 89  // { int getdtablesize(void); }
+	SYS_DUP2                     = 90  // { int dup2(u_int from, u_int to); }
+	SYS_FCNTL                    = 92  // { int fcntl(int fd, int cmd, long arg); }
+	SYS_SELECT                   = 93  // { int select(int nd, fd_set *in, fd_set *ou, \
+	SYS_FSYNC                    = 95  // { int fsync(int fd); }
+	SYS_SETPRIORITY              = 96  // { int setpriority(int which, int who, \
+	SYS_SOCKET                   = 97  // { int socket(int domain, int type, \
+	SYS_CONNECT                  = 98  // { int connect(int s, caddr_t name, \
+	SYS_GETPRIORITY              = 100 // { int getpriority(int which, int who); }
+	SYS_BIND                     = 104 // { int bind(int s, caddr_t name, \
+	SYS_SETSOCKOPT               = 105 // { int setsockopt(int s, int level, int name, \
+	SYS_LISTEN                   = 106 // { int listen(int s, int backlog); }
+	SYS_GETTIMEOFDAY             = 116 // { int gettimeofday(struct timeval *tp, \
+	SYS_GETRUSAGE                = 117 // { int getrusage(int who, \
+	SYS_GETSOCKOPT               = 118 // { int getsockopt(int s, int level, int name, \
+	SYS_READV                    = 120 // { int readv(int fd, struct iovec *iovp, \
+	SYS_WRITEV                   = 121 // { int writev(int fd, struct iovec *iovp, \
+	SYS_SETTIMEOFDAY             = 122 // { int settimeofday(struct timeval *tv, \
+	SYS_FCHOWN                   = 123 // { int fchown(int fd, int uid, int gid); }
+	SYS_FCHMOD                   = 124 // { int fchmod(int fd, int mode); }
+	SYS_SETREUID                 = 126 // { int setreuid(int ruid, int euid); }
+	SYS_SETREGID                 = 127 // { int setregid(int rgid, int egid); }
+	SYS_RENAME                   = 128 // { int rename(char *from, char *to); }
+	SYS_FLOCK                    = 131 // { int flock(int fd, int how); }
+	SYS_MKFIFO                   = 132 // { int mkfifo(char *path, int mode); }
+	SYS_SENDTO                   = 133 // { int sendto(int s, caddr_t buf, size_t len, \
+	SYS_SHUTDOWN                 = 134 // { int shutdown(int s, int how); }
+	SYS_SOCKETPAIR               = 135 // { int socketpair(int domain, int type, \
+	SYS_MKDIR                    = 136 // { int mkdir(char *path, int mode); }
+	SYS_RMDIR                    = 137 // { int rmdir(char *path); }
+	SYS_UTIMES                   = 138 // { int utimes(char *path, \
+	SYS_ADJTIME                  = 140 // { int adjtime(struct timeval *delta, \
+	SYS_SETSID                   = 147 // { int setsid(void); }
+	SYS_QUOTACTL                 = 148 // { int quotactl(char *path, int cmd, int uid, \
+	SYS_LGETFH                   = 160 // { int lgetfh(char *fname, \
+	SYS_GETFH                    = 161 // { int getfh(char *fname, \
+	SYS_SYSARCH                  = 165 // { int sysarch(int op, char *parms); }
+	SYS_RTPRIO                   = 166 // { int rtprio(int function, pid_t pid, \
+	SYS_FREEBSD6_PREAD           = 173 // { ssize_t freebsd6_pread(int fd, void *buf, \
+	SYS_FREEBSD6_PWRITE          = 174 // { ssize_t freebsd6_pwrite(int fd, \
+	SYS_SETFIB                   = 175 // { int setfib(int fibnum); }
+	SYS_NTP_ADJTIME              = 176 // { int ntp_adjtime(struct timex *tp); }
+	SYS_SETGID                   = 181 // { int setgid(gid_t gid); }
+	SYS_SETEGID                  = 182 // { int setegid(gid_t egid); }
+	SYS_SETEUID                  = 183 // { int seteuid(uid_t euid); }
+	SYS_STAT                     = 188 // { int stat(char *path, struct stat *ub); }
+	SYS_FSTAT                    = 189 // { int fstat(int fd, struct stat *sb); }
+	SYS_LSTAT                    = 190 // { int lstat(char *path, struct stat *ub); }
+	SYS_PATHCONF                 = 191 // { int pathconf(char *path, int name); }
+	SYS_FPATHCONF                = 192 // { int fpathconf(int fd, int name); }
+	SYS_GETRLIMIT                = 194 // { int getrlimit(u_int which, \
+	SYS_SETRLIMIT                = 195 // { int setrlimit(u_int which, \
+	SYS_GETDIRENTRIES            = 196 // { int getdirentries(int fd, char *buf, \
+	SYS_FREEBSD6_MMAP            = 197 // { caddr_t freebsd6_mmap(caddr_t addr, \
+	SYS_FREEBSD6_LSEEK           = 199 // { off_t freebsd6_lseek(int fd, int pad, \
+	SYS_FREEBSD6_TRUNCATE        = 200 // { int freebsd6_truncate(char *path, int pad, \
+	SYS_FREEBSD6_FTRUNCATE       = 201 // { int freebsd6_ftruncate(int fd, int pad, \
+	SYS___SYSCTL                 = 202 // { int __sysctl(int *name, u_int namelen, \
+	SYS_MLOCK                    = 203 // { int mlock(const void *addr, size_t len); }
+	SYS_MUNLOCK                  = 204 // { int munlock(const void *addr, size_t len); }
+	SYS_UNDELETE                 = 205 // { int undelete(char *path); }
+	SYS_FUTIMES                  = 206 // { int futimes(int fd, struct timeval *tptr); }
+	SYS_GETPGID                  = 207 // { int getpgid(pid_t pid); }
+	SYS_POLL                     = 209 // { int poll(struct pollfd *fds, u_int nfds, \
+	SYS_CLOCK_GETTIME            = 232 // { int clock_gettime(clockid_t clock_id, \
+	SYS_CLOCK_SETTIME            = 233 // { int clock_settime( \
+	SYS_CLOCK_GETRES             = 234 // { int clock_getres(clockid_t clock_id, \
+	SYS_KTIMER_CREATE            = 235 // { int ktimer_create(clockid_t clock_id, \
+	SYS_KTIMER_DELETE            = 236 // { int ktimer_delete(int timerid); }
+	SYS_KTIMER_SETTIME           = 237 // { int ktimer_settime(int timerid, int flags, \
+	SYS_KTIMER_GETTIME           = 238 // { int ktimer_gettime(int timerid, struct \
+	SYS_KTIMER_GETOVERRUN        = 239 // { int ktimer_getoverrun(int timerid); }
+	SYS_NANOSLEEP                = 240 // { int nanosleep(const struct timespec *rqtp, \
+	SYS_FFCLOCK_GETCOUNTER       = 241 // { int ffclock_getcounter(ffcounter *ffcount); }
+	SYS_FFCLOCK_SETESTIMATE      = 242 // { int ffclock_setestimate( \
+	SYS_FFCLOCK_GETESTIMATE      = 243 // { int ffclock_getestimate( \
+	SYS_NTP_GETTIME              = 248 // { int ntp_gettime(struct ntptimeval *ntvp); }
+	SYS_MINHERIT                 = 250 // { int minherit(void *addr, size_t len, \
+	SYS_RFORK                    = 251 // { int rfork(int flags); }
+	SYS_OPENBSD_POLL             = 252 // { int openbsd_poll(struct pollfd *fds, \
+	SYS_ISSETUGID                = 253 // { int issetugid(void); }
+	SYS_LCHOWN                   = 254 // { int lchown(char *path, int uid, int gid); }
+	SYS_GETDENTS                 = 272 // { int getdents(int fd, char *buf, \
+	SYS_LCHMOD                   = 274 // { int lchmod(char *path, mode_t mode); }
+	SYS_LUTIMES                  = 276 // { int lutimes(char *path, \
+	SYS_NSTAT                    = 278 // { int nstat(char *path, struct nstat *ub); }
+	SYS_NFSTAT                   = 279 // { int nfstat(int fd, struct nstat *sb); }
+	SYS_NLSTAT                   = 280 // { int nlstat(char *path, struct nstat *ub); }
+	SYS_PREADV                   = 289 // { ssize_t preadv(int fd, struct iovec *iovp, \
+	SYS_PWRITEV                  = 290 // { ssize_t pwritev(int fd, struct iovec *iovp, \
+	SYS_FHOPEN                   = 298 // { int fhopen(const struct fhandle *u_fhp, \
+	SYS_FHSTAT                   = 299 // { int fhstat(const struct fhandle *u_fhp, \
+	SYS_MODNEXT                  = 300 // { int modnext(int modid); }
+	SYS_MODSTAT                  = 301 // { int modstat(int modid, \
+	SYS_MODFNEXT                 = 302 // { int modfnext(int modid); }
+	SYS_MODFIND                  = 303 // { int modfind(const char *name); }
+	SYS_KLDLOAD                  = 304 // { int kldload(const char *file); }
+	SYS_KLDUNLOAD                = 305 // { int kldunload(int fileid); }
+	SYS_KLDFIND                  = 306 // { int kldfind(const char *file); }
+	SYS_KLDNEXT                  = 307 // { int kldnext(int fileid); }
+	SYS_KLDSTAT                  = 308 // { int kldstat(int fileid, struct \
+	SYS_KLDFIRSTMOD              = 309 // { int kldfirstmod(int fileid); }
+	SYS_GETSID                   = 310 // { int getsid(pid_t pid); }
+	SYS_SETRESUID                = 311 // { int setresuid(uid_t ruid, uid_t euid, \
+	SYS_SETRESGID                = 312 // { int setresgid(gid_t rgid, gid_t egid, \
+	SYS_YIELD                    = 321 // { int yield(void); }
+	SYS_MLOCKALL                 = 324 // { int mlockall(int how); }
+	SYS_MUNLOCKALL               = 325 // { int munlockall(void); }
+	SYS___GETCWD                 = 326 // { int __getcwd(u_char *buf, u_int buflen); }
+	SYS_SCHED_SETPARAM           = 327 // { int sched_setparam (pid_t pid, \
+	SYS_SCHED_GETPARAM           = 328 // { int sched_getparam (pid_t pid, struct \
+	SYS_SCHED_SETSCHEDULER       = 329 // { int sched_setscheduler (pid_t pid, int \
+	SYS_SCHED_GETSCHEDULER       = 330 // { int sched_getscheduler (pid_t pid); }
+	SYS_SCHED_YIELD              = 331 // { int sched_yield (void); }
+	SYS_SCHED_GET_PRIORITY_MAX   = 332 // { int sched_get_priority_max (int policy); }
+	SYS_SCHED_GET_PRIORITY_MIN   = 333 // { int sched_get_priority_min (int policy); }
+	SYS_SCHED_RR_GET_INTERVAL    = 334 // { int sched_rr_get_interval (pid_t pid, \
+	SYS_UTRACE                   = 335 // { int utrace(const void *addr, size_t len); }
+	SYS_KLDSYM                   = 337 // { int kldsym(int fileid, int cmd, \
+	SYS_JAIL                     = 338 // { int jail(struct jail *jail); }
+	SYS_SIGPROCMASK              = 340 // { int sigprocmask(int how, \
+	SYS_SIGSUSPEND               = 341 // { int sigsuspend(const sigset_t *sigmask); }
+	SYS_SIGPENDING               = 343 // { int sigpending(sigset_t *set); }
+	SYS_SIGTIMEDWAIT             = 345 // { int sigtimedwait(const sigset_t *set, \
+	SYS_SIGWAITINFO              = 346 // { int sigwaitinfo(const sigset_t *set, \
+	SYS___ACL_GET_FILE           = 347 // { int __acl_get_file(const char *path, \
+	SYS___ACL_SET_FILE           = 348 // { int __acl_set_file(const char *path, \
+	SYS___ACL_GET_FD             = 349 // { int __acl_get_fd(int filedes, \
+	SYS___ACL_SET_FD             = 350 // { int __acl_set_fd(int filedes, \
+	SYS___ACL_DELETE_FILE        = 351 // { int __acl_delete_file(const char *path, \
+	SYS___ACL_DELETE_FD          = 352 // { int __acl_delete_fd(int filedes, \
+	SYS___ACL_ACLCHECK_FILE      = 353 // { int __acl_aclcheck_file(const char *path, \
+	SYS___ACL_ACLCHECK_FD        = 354 // { int __acl_aclcheck_fd(int filedes, \
+	SYS_EXTATTRCTL               = 355 // { int extattrctl(const char *path, int cmd, \
+	SYS_EXTATTR_SET_FILE         = 356 // { int extattr_set_file( \
+	SYS_EXTATTR_GET_FILE         = 357 // { ssize_t extattr_get_file( \
+	SYS_EXTATTR_DELETE_FILE      = 358 // { int extattr_delete_file(const char *path, \
+	SYS_GETRESUID                = 360 // { int getresuid(uid_t *ruid, uid_t *euid, \
+	SYS_GETRESGID                = 361 // { int getresgid(gid_t *rgid, gid_t *egid, \
+	SYS_KQUEUE                   = 362 // { int kqueue(void); }
+	SYS_KEVENT                   = 363 // { int kevent(int fd, \
+	SYS_EXTATTR_SET_FD           = 371 // { int extattr_set_fd(int fd, \
+	SYS_EXTATTR_GET_FD           = 372 // { ssize_t extattr_get_fd(int fd, \
+	SYS_EXTATTR_DELETE_FD        = 373 // { int extattr_delete_fd(int fd, \
+	SYS___SETUGID                = 374 // { int __setugid(int flag); }
+	SYS_EACCESS                  = 376 // { int eaccess(char *path, int amode); }
+	SYS_NMOUNT                   = 378 // { int nmount(struct iovec *iovp, \
+	SYS___MAC_GET_PROC           = 384 // { int __mac_get_proc(struct mac *mac_p); }
+	SYS___MAC_SET_PROC           = 385 // { int __mac_set_proc(struct mac *mac_p); }
+	SYS___MAC_GET_FD             = 386 // { int __mac_get_fd(int fd, \
+	SYS___MAC_GET_FILE           = 387 // { int __mac_get_file(const char *path_p, \
+	SYS___MAC_SET_FD             = 388 // { int __mac_set_fd(int fd, \
+	SYS___MAC_SET_FILE           = 389 // { int __mac_set_file(const char *path_p, \
+	SYS_KENV                     = 390 // { int kenv(int what, const char *name, \
+	SYS_LCHFLAGS                 = 391 // { int lchflags(const char *path, int flags); }
+	SYS_UUIDGEN                  = 392 // { int uuidgen(struct uuid *store, \
+	SYS_SENDFILE                 = 393 // { int sendfile(int fd, int s, off_t offset, \
+	SYS_MAC_SYSCALL              = 394 // { int mac_syscall(const char *policy, \
+	SYS_GETFSSTAT                = 395 // { int getfsstat(struct statfs *buf, \
+	SYS_STATFS                   = 396 // { int statfs(char *path, \
+	SYS_FSTATFS                  = 397 // { int fstatfs(int fd, struct statfs *buf); }
+	SYS_FHSTATFS                 = 398 // { int fhstatfs(const struct fhandle *u_fhp, \
+	SYS___MAC_GET_PID            = 409 // { int __mac_get_pid(pid_t pid, \
+	SYS___MAC_GET_LINK           = 410 // { int __mac_get_link(const char *path_p, \
+	SYS___MAC_SET_LINK           = 411 // { int __mac_set_link(const char *path_p, \
+	SYS_EXTATTR_SET_LINK         = 412 // { int extattr_set_link( \
+	SYS_EXTATTR_GET_LINK         = 413 // { ssize_t extattr_get_link( \
+	SYS_EXTATTR_DELETE_LINK      = 414 // { int extattr_delete_link( \
+	SYS___MAC_EXECVE             = 415 // { int __mac_execve(char *fname, char **argv, \
+	SYS_SIGACTION                = 416 // { int sigaction(int sig, \
+	SYS_SIGRETURN                = 417 // { int sigreturn( \
+	SYS_GETCONTEXT               = 421 // { int getcontext(struct __ucontext *ucp); }
+	SYS_SETCONTEXT               = 422 // { int setcontext( \
+	SYS_SWAPCONTEXT              = 423 // { int swapcontext(struct __ucontext *oucp, \
+	SYS_SWAPOFF                  = 424 // { int swapoff(const char *name); }
+	SYS___ACL_GET_LINK           = 425 // { int __acl_get_link(const char *path, \
+	SYS___ACL_SET_LINK           = 426 // { int __acl_set_link(const char *path, \
+	SYS___ACL_DELETE_LINK        = 427 // { int __acl_delete_link(const char *path, \
+	SYS___ACL_ACLCHECK_LINK      = 428 // { int __acl_aclcheck_link(const char *path, \
+	SYS_SIGWAIT                  = 429 // { int sigwait(const sigset_t *set, \
+	SYS_THR_CREATE               = 430 // { int thr_create(ucontext_t *ctx, long *id, \
+	SYS_THR_EXIT                 = 431 // { void thr_exit(long *state); }
+	SYS_THR_SELF                 = 432 // { int thr_self(long *id); }
+	SYS_THR_KILL                 = 433 // { int thr_kill(long id, int sig); }
+	SYS__UMTX_LOCK               = 434 // { int _umtx_lock(struct umtx *umtx); }
+	SYS__UMTX_UNLOCK             = 435 // { int _umtx_unlock(struct umtx *umtx); }
+	SYS_JAIL_ATTACH              = 436 // { int jail_attach(int jid); }
+	SYS_EXTATTR_LIST_FD          = 437 // { ssize_t extattr_list_fd(int fd, \
+	SYS_EXTATTR_LIST_FILE        = 438 // { ssize_t extattr_list_file( \
+	SYS_EXTATTR_LIST_LINK        = 439 // { ssize_t extattr_list_link( \
+	SYS_THR_SUSPEND              = 442 // { int thr_suspend( \
+	SYS_THR_WAKE                 = 443 // { int thr_wake(long id); }
+	SYS_KLDUNLOADF               = 444 // { int kldunloadf(int fileid, int flags); }
+	SYS_AUDIT                    = 445 // { int audit(const void *record, \
+	SYS_AUDITON                  = 446 // { int auditon(int cmd, void *data, \
+	SYS_GETAUID                  = 447 // { int getauid(uid_t *auid); }
+	SYS_SETAUID                  = 448 // { int setauid(uid_t *auid); }
+	SYS_GETAUDIT                 = 449 // { int getaudit(struct auditinfo *auditinfo); }
+	SYS_SETAUDIT                 = 450 // { int setaudit(struct auditinfo *auditinfo); }
+	SYS_GETAUDIT_ADDR            = 451 // { int getaudit_addr( \
+	SYS_SETAUDIT_ADDR            = 452 // { int setaudit_addr( \
+	SYS_AUDITCTL                 = 453 // { int auditctl(char *path); }
+	SYS__UMTX_OP                 = 454 // { int _umtx_op(void *obj, int op, \
+	SYS_THR_NEW                  = 455 // { int thr_new(struct thr_param *param, \
+	SYS_SIGQUEUE                 = 456 // { int sigqueue(pid_t pid, int signum, void *value); }
+	SYS_ABORT2                   = 463 // { int abort2(const char *why, int nargs, void **args); }
+	SYS_THR_SET_NAME             = 464 // { int thr_set_name(long id, const char *name); }
+	SYS_RTPRIO_THREAD            = 466 // { int rtprio_thread(int function, \
+	SYS_SCTP_PEELOFF             = 471 // { int sctp_peeloff(int sd, uint32_t name); }
+	SYS_SCTP_GENERIC_SENDMSG     = 472 // { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
+	SYS_SCTP_GENERIC_SENDMSG_IOV = 473 // { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
+	SYS_SCTP_GENERIC_RECVMSG     = 474 // { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
+	SYS_PREAD                    = 475 // { ssize_t pread(int fd, void *buf, \
+	SYS_PWRITE                   = 476 // { ssize_t pwrite(int fd, const void *buf, \
+	SYS_MMAP                     = 477 // { caddr_t mmap(caddr_t addr, size_t len, \
+	SYS_LSEEK                    = 478 // { off_t lseek(int fd, off_t offset, \
+	SYS_TRUNCATE                 = 479 // { int truncate(char *path, off_t length); }
+	SYS_FTRUNCATE                = 480 // { int ftruncate(int fd, off_t length); }
+	SYS_THR_KILL2                = 481 // { int thr_kill2(pid_t pid, long id, int sig); }
+	SYS_SHM_OPEN                 = 482 // { int shm_open(const char *path, int flags, \
+	SYS_SHM_UNLINK               = 483 // { int shm_unlink(const char *path); }
+	SYS_CPUSET                   = 484 // { int cpuset(cpusetid_t *setid); }
+	SYS_CPUSET_SETID             = 485 // { int cpuset_setid(cpuwhich_t which, id_t id, \
+	SYS_CPUSET_GETID             = 486 // { int cpuset_getid(cpulevel_t level, \
+	SYS_CPUSET_GETAFFINITY       = 487 // { int cpuset_getaffinity(cpulevel_t level, \
+	SYS_CPUSET_SETAFFINITY       = 488 // { int cpuset_setaffinity(cpulevel_t level, \
+	SYS_FACCESSAT                = 489 // { int faccessat(int fd, char *path, int amode, \
+	SYS_FCHMODAT                 = 490 // { int fchmodat(int fd, char *path, mode_t mode, \
+	SYS_FCHOWNAT                 = 491 // { int fchownat(int fd, char *path, uid_t uid, \
+	SYS_FEXECVE                  = 492 // { int fexecve(int fd, char **argv, \
+	SYS_FSTATAT                  = 493 // { int fstatat(int fd, char *path, \
+	SYS_FUTIMESAT                = 494 // { int futimesat(int fd, char *path, \
+	SYS_LINKAT                   = 495 // { int linkat(int fd1, char *path1, int fd2, \
+	SYS_MKDIRAT                  = 496 // { int mkdirat(int fd, char *path, mode_t mode); }
+	SYS_MKFIFOAT                 = 497 // { int mkfifoat(int fd, char *path, mode_t mode); }
+	SYS_MKNODAT                  = 498 // { int mknodat(int fd, char *path, mode_t mode, \
+	SYS_OPENAT                   = 499 // { int openat(int fd, char *path, int flag, \
+	SYS_READLINKAT               = 500 // { int readlinkat(int fd, char *path, char *buf, \
+	SYS_RENAMEAT                 = 501 // { int renameat(int oldfd, char *old, int newfd, \
+	SYS_SYMLINKAT                = 502 // { int symlinkat(char *path1, int fd, \
+	SYS_UNLINKAT                 = 503 // { int unlinkat(int fd, char *path, int flag); }
+	SYS_POSIX_OPENPT             = 504 // { int posix_openpt(int flags); }
+	SYS_JAIL_GET                 = 506 // { int jail_get(struct iovec *iovp, \
+	SYS_JAIL_SET                 = 507 // { int jail_set(struct iovec *iovp, \
+	SYS_JAIL_REMOVE              = 508 // { int jail_remove(int jid); }
+	SYS_CLOSEFROM                = 509 // { int closefrom(int lowfd); }
+	SYS_LPATHCONF                = 513 // { int lpathconf(char *path, int name); }
+	SYS_CAP_NEW                  = 514 // { int cap_new(int fd, u_int64_t rights); }
+	SYS_CAP_GETRIGHTS            = 515 // { int cap_getrights(int fd, \
+	SYS_CAP_ENTER                = 516 // { int cap_enter(void); }
+	SYS_CAP_GETMODE              = 517 // { int cap_getmode(u_int *modep); }
+	SYS_PDFORK                   = 518 // { int pdfork(int *fdp, int flags); }
+	SYS_PDKILL                   = 519 // { int pdkill(int fd, int signum); }
+	SYS_PDGETPID                 = 520 // { int pdgetpid(int fd, pid_t *pidp); }
+	SYS_PSELECT                  = 522 // { int pselect(int nd, fd_set *in, \
+	SYS_GETLOGINCLASS            = 523 // { int getloginclass(char *namebuf, \
+	SYS_SETLOGINCLASS            = 524 // { int setloginclass(const char *namebuf); }
+	SYS_RCTL_GET_RACCT           = 525 // { int rctl_get_racct(const void *inbufp, \
+	SYS_RCTL_GET_RULES           = 526 // { int rctl_get_rules(const void *inbufp, \
+	SYS_RCTL_GET_LIMITS          = 527 // { int rctl_get_limits(const void *inbufp, \
+	SYS_RCTL_ADD_RULE            = 528 // { int rctl_add_rule(const void *inbufp, \
+	SYS_RCTL_REMOVE_RULE         = 529 // { int rctl_remove_rule(const void *inbufp, \
+	SYS_POSIX_FALLOCATE          = 530 // { int posix_fallocate(int fd, \
+	SYS_POSIX_FADVISE            = 531 // { int posix_fadvise(int fd, off_t offset, \
+)
diff --git a/src/pkg/syscall/zsysnum_linux_arm.go b/src/pkg/syscall/zsysnum_linux_arm.go
index 7f5d949..7068e4e 100644
--- a/src/pkg/syscall/zsysnum_linux_arm.go
+++ b/src/pkg/syscall/zsysnum_linux_arm.go
@@ -1,4 +1,4 @@
-// mksysnum_linux.pl 
+// mksysnum_linux.pl
 // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
 
 package syscall
diff --git a/src/pkg/syscall/zsysnum_netbsd_386.go b/src/pkg/syscall/zsysnum_netbsd_386.go
index e9a0bcf..c570965 100644
--- a/src/pkg/syscall/zsysnum_netbsd_386.go
+++ b/src/pkg/syscall/zsysnum_netbsd_386.go
@@ -1,4 +1,4 @@
-// mksysnum_netbsd.pl 
+// mksysnum_netbsd.pl
 // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
 
 package syscall
@@ -163,12 +163,6 @@ const (
 	SYS__LWP_SETNAME         = 323 // { int|sys||_lwp_setname(lwpid_t target, const char *name); }
 	SYS__LWP_GETNAME         = 324 // { int|sys||_lwp_getname(lwpid_t target, char *name, size_t len); }
 	SYS__LWP_CTL             = 325 // { int|sys||_lwp_ctl(int features, struct lwpctl **address); }
-	SYS_SA_REGISTER          = 330 // { int|sys||sa_register(sa_upcall_t new, sa_upcall_t *old, int flags, ssize_t stackinfo_offset); }
-	SYS_SA_STACKS            = 331 // { int|sys||sa_stacks(int num, stack_t *stacks); }
-	SYS_SA_ENABLE            = 332 // { int|sys||sa_enable(void); }
-	SYS_SA_SETCONCURRENCY    = 333 // { int|sys||sa_setconcurrency(int concurrency); }
-	SYS_SA_YIELD             = 334 // { int|sys||sa_yield(void); }
-	SYS_SA_PREEMPT           = 335 // { int|sys||sa_preempt(int sa_id); }
 	SYS___SIGACTION_SIGTRAMP = 340 // { int|sys||__sigaction_sigtramp(int signum, const struct sigaction *nsa, struct sigaction *osa, const void *tramp, int vers); }
 	SYS_PMC_GET_INFO         = 341 // { int|sys||pmc_get_info(int ctr, int op, void *args); }
 	SYS_PMC_CONTROL          = 342 // { int|sys||pmc_control(int ctr, int op, void *args); }
@@ -250,7 +244,6 @@ const (
 	SYS_WAIT4                = 449 // { int|sys|50|wait4(pid_t pid, int *status, int options, struct rusage *rusage); }
 	SYS_MKNOD                = 450 // { int|sys|50|mknod(const char *path, mode_t mode, dev_t dev); }
 	SYS_FHSTAT               = 451 // { int|sys|50|fhstat(const void *fhp, size_t fh_size, struct stat *sb); }
-	SYS_QUOTACTL             = 452 // { int|sys|50|quotactl(const char *path, struct plistref *pref); }
 	SYS_PIPE2                = 453 // { int|sys||pipe2(int *fildes, int flags); }
 	SYS_DUP3                 = 454 // { int|sys||dup3(int from, int to, int flags); }
 	SYS_KQUEUE1              = 455 // { int|sys||kqueue1(int flags); }
@@ -271,4 +264,8 @@ const (
 	SYS_SYMLINKAT            = 470 // { int|sys||symlinkat(const char *path1, int fd, const char *path2); }
 	SYS_UNLINKAT             = 471 // { int|sys||unlinkat(int fd, const char *path, int flag); }
 	SYS_FUTIMENS             = 472 // { int|sys||futimens(int fd, const struct timespec *tptr); }
+	SYS___QUOTACTL           = 473 // { int|sys||__quotactl(const char *path, struct quotactl_args *args); }
+	SYS_POSIX_SPAWN          = 474 // { int|sys||posix_spawn(pid_t *pid, const char *path, const struct posix_spawn_file_actions *file_actions, const struct posix_spawnattr *attrp, char *const *argv, char *const *envp); }
+	SYS_RECVMMSG             = 475 // { int|sys||recvmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags, struct timespec *timeout); }
+	SYS_SENDMMSG             = 476 // { int|sys||sendmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags); }
 )
diff --git a/src/pkg/syscall/zsysnum_netbsd_amd64.go b/src/pkg/syscall/zsysnum_netbsd_amd64.go
index e9a0bcf..c570965 100644
--- a/src/pkg/syscall/zsysnum_netbsd_amd64.go
+++ b/src/pkg/syscall/zsysnum_netbsd_amd64.go
@@ -1,4 +1,4 @@
-// mksysnum_netbsd.pl 
+// mksysnum_netbsd.pl
 // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
 
 package syscall
@@ -163,12 +163,6 @@ const (
 	SYS__LWP_SETNAME         = 323 // { int|sys||_lwp_setname(lwpid_t target, const char *name); }
 	SYS__LWP_GETNAME         = 324 // { int|sys||_lwp_getname(lwpid_t target, char *name, size_t len); }
 	SYS__LWP_CTL             = 325 // { int|sys||_lwp_ctl(int features, struct lwpctl **address); }
-	SYS_SA_REGISTER          = 330 // { int|sys||sa_register(sa_upcall_t new, sa_upcall_t *old, int flags, ssize_t stackinfo_offset); }
-	SYS_SA_STACKS            = 331 // { int|sys||sa_stacks(int num, stack_t *stacks); }
-	SYS_SA_ENABLE            = 332 // { int|sys||sa_enable(void); }
-	SYS_SA_SETCONCURRENCY    = 333 // { int|sys||sa_setconcurrency(int concurrency); }
-	SYS_SA_YIELD             = 334 // { int|sys||sa_yield(void); }
-	SYS_SA_PREEMPT           = 335 // { int|sys||sa_preempt(int sa_id); }
 	SYS___SIGACTION_SIGTRAMP = 340 // { int|sys||__sigaction_sigtramp(int signum, const struct sigaction *nsa, struct sigaction *osa, const void *tramp, int vers); }
 	SYS_PMC_GET_INFO         = 341 // { int|sys||pmc_get_info(int ctr, int op, void *args); }
 	SYS_PMC_CONTROL          = 342 // { int|sys||pmc_control(int ctr, int op, void *args); }
@@ -250,7 +244,6 @@ const (
 	SYS_WAIT4                = 449 // { int|sys|50|wait4(pid_t pid, int *status, int options, struct rusage *rusage); }
 	SYS_MKNOD                = 450 // { int|sys|50|mknod(const char *path, mode_t mode, dev_t dev); }
 	SYS_FHSTAT               = 451 // { int|sys|50|fhstat(const void *fhp, size_t fh_size, struct stat *sb); }
-	SYS_QUOTACTL             = 452 // { int|sys|50|quotactl(const char *path, struct plistref *pref); }
 	SYS_PIPE2                = 453 // { int|sys||pipe2(int *fildes, int flags); }
 	SYS_DUP3                 = 454 // { int|sys||dup3(int from, int to, int flags); }
 	SYS_KQUEUE1              = 455 // { int|sys||kqueue1(int flags); }
@@ -271,4 +264,8 @@ const (
 	SYS_SYMLINKAT            = 470 // { int|sys||symlinkat(const char *path1, int fd, const char *path2); }
 	SYS_UNLINKAT             = 471 // { int|sys||unlinkat(int fd, const char *path, int flag); }
 	SYS_FUTIMENS             = 472 // { int|sys||futimens(int fd, const struct timespec *tptr); }
+	SYS___QUOTACTL           = 473 // { int|sys||__quotactl(const char *path, struct quotactl_args *args); }
+	SYS_POSIX_SPAWN          = 474 // { int|sys||posix_spawn(pid_t *pid, const char *path, const struct posix_spawn_file_actions *file_actions, const struct posix_spawnattr *attrp, char *const *argv, char *const *envp); }
+	SYS_RECVMMSG             = 475 // { int|sys||recvmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags, struct timespec *timeout); }
+	SYS_SENDMMSG             = 476 // { int|sys||sendmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags); }
 )
diff --git a/src/pkg/syscall/zsysnum_netbsd_arm.go b/src/pkg/syscall/zsysnum_netbsd_arm.go
new file mode 100644
index 0000000..c570965
--- /dev/null
+++ b/src/pkg/syscall/zsysnum_netbsd_arm.go
@@ -0,0 +1,271 @@
+// mksysnum_netbsd.pl
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+	SYS_EXIT                 = 1   // { void|sys||exit(int rval); }
+	SYS_FORK                 = 2   // { int|sys||fork(void); }
+	SYS_READ                 = 3   // { ssize_t|sys||read(int fd, void *buf, size_t nbyte); }
+	SYS_WRITE                = 4   // { ssize_t|sys||write(int fd, const void *buf, size_t nbyte); }
+	SYS_OPEN                 = 5   // { int|sys||open(const char *path, int flags, ... mode_t mode); }
+	SYS_CLOSE                = 6   // { int|sys||close(int fd); }
+	SYS_LINK                 = 9   // { int|sys||link(const char *path, const char *link); }
+	SYS_UNLINK               = 10  // { int|sys||unlink(const char *path); }
+	SYS_CHDIR                = 12  // { int|sys||chdir(const char *path); }
+	SYS_FCHDIR               = 13  // { int|sys||fchdir(int fd); }
+	SYS_CHMOD                = 15  // { int|sys||chmod(const char *path, mode_t mode); }
+	SYS_CHOWN                = 16  // { int|sys||chown(const char *path, uid_t uid, gid_t gid); }
+	SYS_BREAK                = 17  // { int|sys||obreak(char *nsize); }
+	SYS_GETPID               = 20  // { pid_t|sys||getpid_with_ppid(void); }
+	SYS_UNMOUNT              = 22  // { int|sys||unmount(const char *path, int flags); }
+	SYS_SETUID               = 23  // { int|sys||setuid(uid_t uid); }
+	SYS_GETUID               = 24  // { uid_t|sys||getuid_with_euid(void); }
+	SYS_GETEUID              = 25  // { uid_t|sys||geteuid(void); }
+	SYS_PTRACE               = 26  // { int|sys||ptrace(int req, pid_t pid, void *addr, int data); }
+	SYS_RECVMSG              = 27  // { ssize_t|sys||recvmsg(int s, struct msghdr *msg, int flags); }
+	SYS_SENDMSG              = 28  // { ssize_t|sys||sendmsg(int s, const struct msghdr *msg, int flags); }
+	SYS_RECVFROM             = 29  // { ssize_t|sys||recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlenaddr); }
+	SYS_ACCEPT               = 30  // { int|sys||accept(int s, struct sockaddr *name, socklen_t *anamelen); }
+	SYS_GETPEERNAME          = 31  // { int|sys||getpeername(int fdes, struct sockaddr *asa, socklen_t *alen); }
+	SYS_GETSOCKNAME          = 32  // { int|sys||getsockname(int fdes, struct sockaddr *asa, socklen_t *alen); }
+	SYS_ACCESS               = 33  // { int|sys||access(const char *path, int flags); }
+	SYS_CHFLAGS              = 34  // { int|sys||chflags(const char *path, u_long flags); }
+	SYS_FCHFLAGS             = 35  // { int|sys||fchflags(int fd, u_long flags); }
+	SYS_SYNC                 = 36  // { void|sys||sync(void); }
+	SYS_KILL                 = 37  // { int|sys||kill(pid_t pid, int signum); }
+	SYS_GETPPID              = 39  // { pid_t|sys||getppid(void); }
+	SYS_DUP                  = 41  // { int|sys||dup(int fd); }
+	SYS_PIPE                 = 42  // { int|sys||pipe(void); }
+	SYS_GETEGID              = 43  // { gid_t|sys||getegid(void); }
+	SYS_PROFIL               = 44  // { int|sys||profil(char *samples, size_t size, u_long offset, u_int scale); }
+	SYS_KTRACE               = 45  // { int|sys||ktrace(const char *fname, int ops, int facs, pid_t pid); }
+	SYS_GETGID               = 47  // { gid_t|sys||getgid_with_egid(void); }
+	SYS___GETLOGIN           = 49  // { int|sys||__getlogin(char *namebuf, size_t namelen); }
+	SYS___SETLOGIN           = 50  // { int|sys||__setlogin(const char *namebuf); }
+	SYS_ACCT                 = 51  // { int|sys||acct(const char *path); }
+	SYS_IOCTL                = 54  // { int|sys||ioctl(int fd, u_long com, ... void *data); }
+	SYS_REVOKE               = 56  // { int|sys||revoke(const char *path); }
+	SYS_SYMLINK              = 57  // { int|sys||symlink(const char *path, const char *link); }
+	SYS_READLINK             = 58  // { ssize_t|sys||readlink(const char *path, char *buf, size_t count); }
+	SYS_EXECVE               = 59  // { int|sys||execve(const char *path, char * const *argp, char * const *envp); }
+	SYS_UMASK                = 60  // { mode_t|sys||umask(mode_t newmask); }
+	SYS_CHROOT               = 61  // { int|sys||chroot(const char *path); }
+	SYS_VFORK                = 66  // { int|sys||vfork(void); }
+	SYS_SBRK                 = 69  // { int|sys||sbrk(intptr_t incr); }
+	SYS_SSTK                 = 70  // { int|sys||sstk(int incr); }
+	SYS_VADVISE              = 72  // { int|sys||ovadvise(int anom); }
+	SYS_MUNMAP               = 73  // { int|sys||munmap(void *addr, size_t len); }
+	SYS_MPROTECT             = 74  // { int|sys||mprotect(void *addr, size_t len, int prot); }
+	SYS_MADVISE              = 75  // { int|sys||madvise(void *addr, size_t len, int behav); }
+	SYS_MINCORE              = 78  // { int|sys||mincore(void *addr, size_t len, char *vec); }
+	SYS_GETGROUPS            = 79  // { int|sys||getgroups(int gidsetsize, gid_t *gidset); }
+	SYS_SETGROUPS            = 80  // { int|sys||setgroups(int gidsetsize, const gid_t *gidset); }
+	SYS_GETPGRP              = 81  // { int|sys||getpgrp(void); }
+	SYS_SETPGID              = 82  // { int|sys||setpgid(pid_t pid, pid_t pgid); }
+	SYS_DUP2                 = 90  // { int|sys||dup2(int from, int to); }
+	SYS_FCNTL                = 92  // { int|sys||fcntl(int fd, int cmd, ... void *arg); }
+	SYS_FSYNC                = 95  // { int|sys||fsync(int fd); }
+	SYS_SETPRIORITY          = 96  // { int|sys||setpriority(int which, id_t who, int prio); }
+	SYS_CONNECT              = 98  // { int|sys||connect(int s, const struct sockaddr *name, socklen_t namelen); }
+	SYS_GETPRIORITY          = 100 // { int|sys||getpriority(int which, id_t who); }
+	SYS_BIND                 = 104 // { int|sys||bind(int s, const struct sockaddr *name, socklen_t namelen); }
+	SYS_SETSOCKOPT           = 105 // { int|sys||setsockopt(int s, int level, int name, const void *val, socklen_t valsize); }
+	SYS_LISTEN               = 106 // { int|sys||listen(int s, int backlog); }
+	SYS_GETSOCKOPT           = 118 // { int|sys||getsockopt(int s, int level, int name, void *val, socklen_t *avalsize); }
+	SYS_READV                = 120 // { ssize_t|sys||readv(int fd, const struct iovec *iovp, int iovcnt); }
+	SYS_WRITEV               = 121 // { ssize_t|sys||writev(int fd, const struct iovec *iovp, int iovcnt); }
+	SYS_FCHOWN               = 123 // { int|sys||fchown(int fd, uid_t uid, gid_t gid); }
+	SYS_FCHMOD               = 124 // { int|sys||fchmod(int fd, mode_t mode); }
+	SYS_SETREUID             = 126 // { int|sys||setreuid(uid_t ruid, uid_t euid); }
+	SYS_SETREGID             = 127 // { int|sys||setregid(gid_t rgid, gid_t egid); }
+	SYS_RENAME               = 128 // { int|sys||rename(const char *from, const char *to); }
+	SYS_FLOCK                = 131 // { int|sys||flock(int fd, int how); }
+	SYS_MKFIFO               = 132 // { int|sys||mkfifo(const char *path, mode_t mode); }
+	SYS_SENDTO               = 133 // { ssize_t|sys||sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); }
+	SYS_SHUTDOWN             = 134 // { int|sys||shutdown(int s, int how); }
+	SYS_SOCKETPAIR           = 135 // { int|sys||socketpair(int domain, int type, int protocol, int *rsv); }
+	SYS_MKDIR                = 136 // { int|sys||mkdir(const char *path, mode_t mode); }
+	SYS_RMDIR                = 137 // { int|sys||rmdir(const char *path); }
+	SYS_SETSID               = 147 // { int|sys||setsid(void); }
+	SYS_SYSARCH              = 165 // { int|sys||sysarch(int op, void *parms); }
+	SYS_PREAD                = 173 // { ssize_t|sys||pread(int fd, void *buf, size_t nbyte, int PAD, off_t offset); }
+	SYS_PWRITE               = 174 // { ssize_t|sys||pwrite(int fd, const void *buf, size_t nbyte, int PAD, off_t offset); }
+	SYS_NTP_ADJTIME          = 176 // { int|sys||ntp_adjtime(struct timex *tp); }
+	SYS_SETGID               = 181 // { int|sys||setgid(gid_t gid); }
+	SYS_SETEGID              = 182 // { int|sys||setegid(gid_t egid); }
+	SYS_SETEUID              = 183 // { int|sys||seteuid(uid_t euid); }
+	SYS_PATHCONF             = 191 // { long|sys||pathconf(const char *path, int name); }
+	SYS_FPATHCONF            = 192 // { long|sys||fpathconf(int fd, int name); }
+	SYS_GETRLIMIT            = 194 // { int|sys||getrlimit(int which, struct rlimit *rlp); }
+	SYS_SETRLIMIT            = 195 // { int|sys||setrlimit(int which, const struct rlimit *rlp); }
+	SYS_MMAP                 = 197 // { void *|sys||mmap(void *addr, size_t len, int prot, int flags, int fd, long PAD, off_t pos); }
+	SYS_LSEEK                = 199 // { off_t|sys||lseek(int fd, int PAD, off_t offset, int whence); }
+	SYS_TRUNCATE             = 200 // { int|sys||truncate(const char *path, int PAD, off_t length); }
+	SYS_FTRUNCATE            = 201 // { int|sys||ftruncate(int fd, int PAD, off_t length); }
+	SYS___SYSCTL             = 202 // { int|sys||__sysctl(const int *name, u_int namelen, void *old, size_t *oldlenp, const void *new, size_t newlen); }
+	SYS_MLOCK                = 203 // { int|sys||mlock(const void *addr, size_t len); }
+	SYS_MUNLOCK              = 204 // { int|sys||munlock(const void *addr, size_t len); }
+	SYS_UNDELETE             = 205 // { int|sys||undelete(const char *path); }
+	SYS_GETPGID              = 207 // { pid_t|sys||getpgid(pid_t pid); }
+	SYS_REBOOT               = 208 // { int|sys||reboot(int opt, char *bootstr); }
+	SYS_POLL                 = 209 // { int|sys||poll(struct pollfd *fds, u_int nfds, int timeout); }
+	SYS_SEMGET               = 221 // { int|sys||semget(key_t key, int nsems, int semflg); }
+	SYS_SEMOP                = 222 // { int|sys||semop(int semid, struct sembuf *sops, size_t nsops); }
+	SYS_SEMCONFIG            = 223 // { int|sys||semconfig(int flag); }
+	SYS_MSGGET               = 225 // { int|sys||msgget(key_t key, int msgflg); }
+	SYS_MSGSND               = 226 // { int|sys||msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); }
+	SYS_MSGRCV               = 227 // { ssize_t|sys||msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); }
+	SYS_SHMAT                = 228 // { void *|sys||shmat(int shmid, const void *shmaddr, int shmflg); }
+	SYS_SHMDT                = 230 // { int|sys||shmdt(const void *shmaddr); }
+	SYS_SHMGET               = 231 // { int|sys||shmget(key_t key, size_t size, int shmflg); }
+	SYS_TIMER_CREATE         = 235 // { int|sys||timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid); }
+	SYS_TIMER_DELETE         = 236 // { int|sys||timer_delete(timer_t timerid); }
+	SYS_TIMER_GETOVERRUN     = 239 // { int|sys||timer_getoverrun(timer_t timerid); }
+	SYS_FDATASYNC            = 241 // { int|sys||fdatasync(int fd); }
+	SYS_MLOCKALL             = 242 // { int|sys||mlockall(int flags); }
+	SYS_MUNLOCKALL           = 243 // { int|sys||munlockall(void); }
+	SYS_SIGQUEUEINFO         = 245 // { int|sys||sigqueueinfo(pid_t pid, const siginfo_t *info); }
+	SYS_MODCTL               = 246 // { int|sys||modctl(int cmd, void *arg); }
+	SYS___POSIX_RENAME       = 270 // { int|sys||__posix_rename(const char *from, const char *to); }
+	SYS_SWAPCTL              = 271 // { int|sys||swapctl(int cmd, void *arg, int misc); }
+	SYS_MINHERIT             = 273 // { int|sys||minherit(void *addr, size_t len, int inherit); }
+	SYS_LCHMOD               = 274 // { int|sys||lchmod(const char *path, mode_t mode); }
+	SYS_LCHOWN               = 275 // { int|sys||lchown(const char *path, uid_t uid, gid_t gid); }
+	SYS___POSIX_CHOWN        = 283 // { int|sys||__posix_chown(const char *path, uid_t uid, gid_t gid); }
+	SYS___POSIX_FCHOWN       = 284 // { int|sys||__posix_fchown(int fd, uid_t uid, gid_t gid); }
+	SYS___POSIX_LCHOWN       = 285 // { int|sys||__posix_lchown(const char *path, uid_t uid, gid_t gid); }
+	SYS_GETSID               = 286 // { pid_t|sys||getsid(pid_t pid); }
+	SYS___CLONE              = 287 // { pid_t|sys||__clone(int flags, void *stack); }
+	SYS_FKTRACE              = 288 // { int|sys||fktrace(int fd, int ops, int facs, pid_t pid); }
+	SYS_PREADV               = 289 // { ssize_t|sys||preadv(int fd, const struct iovec *iovp, int iovcnt, int PAD, off_t offset); }
+	SYS_PWRITEV              = 290 // { ssize_t|sys||pwritev(int fd, const struct iovec *iovp, int iovcnt, int PAD, off_t offset); }
+	SYS___GETCWD             = 296 // { int|sys||__getcwd(char *bufp, size_t length); }
+	SYS_FCHROOT              = 297 // { int|sys||fchroot(int fd); }
+	SYS_LCHFLAGS             = 304 // { int|sys||lchflags(const char *path, u_long flags); }
+	SYS_ISSETUGID            = 305 // { int|sys||issetugid(void); }
+	SYS_UTRACE               = 306 // { int|sys||utrace(const char *label, void *addr, size_t len); }
+	SYS_GETCONTEXT           = 307 // { int|sys||getcontext(struct __ucontext *ucp); }
+	SYS_SETCONTEXT           = 308 // { int|sys||setcontext(const struct __ucontext *ucp); }
+	SYS__LWP_CREATE          = 309 // { int|sys||_lwp_create(const struct __ucontext *ucp, u_long flags, lwpid_t *new_lwp); }
+	SYS__LWP_EXIT            = 310 // { int|sys||_lwp_exit(void); }
+	SYS__LWP_SELF            = 311 // { lwpid_t|sys||_lwp_self(void); }
+	SYS__LWP_WAIT            = 312 // { int|sys||_lwp_wait(lwpid_t wait_for, lwpid_t *departed); }
+	SYS__LWP_SUSPEND         = 313 // { int|sys||_lwp_suspend(lwpid_t target); }
+	SYS__LWP_CONTINUE        = 314 // { int|sys||_lwp_continue(lwpid_t target); }
+	SYS__LWP_WAKEUP          = 315 // { int|sys||_lwp_wakeup(lwpid_t target); }
+	SYS__LWP_GETPRIVATE      = 316 // { void *|sys||_lwp_getprivate(void); }
+	SYS__LWP_SETPRIVATE      = 317 // { void|sys||_lwp_setprivate(void *ptr); }
+	SYS__LWP_KILL            = 318 // { int|sys||_lwp_kill(lwpid_t target, int signo); }
+	SYS__LWP_DETACH          = 319 // { int|sys||_lwp_detach(lwpid_t target); }
+	SYS__LWP_UNPARK          = 321 // { int|sys||_lwp_unpark(lwpid_t target, const void *hint); }
+	SYS__LWP_UNPARK_ALL      = 322 // { ssize_t|sys||_lwp_unpark_all(const lwpid_t *targets, size_t ntargets, const void *hint); }
+	SYS__LWP_SETNAME         = 323 // { int|sys||_lwp_setname(lwpid_t target, const char *name); }
+	SYS__LWP_GETNAME         = 324 // { int|sys||_lwp_getname(lwpid_t target, char *name, size_t len); }
+	SYS__LWP_CTL             = 325 // { int|sys||_lwp_ctl(int features, struct lwpctl **address); }
+	SYS___SIGACTION_SIGTRAMP = 340 // { int|sys||__sigaction_sigtramp(int signum, const struct sigaction *nsa, struct sigaction *osa, const void *tramp, int vers); }
+	SYS_PMC_GET_INFO         = 341 // { int|sys||pmc_get_info(int ctr, int op, void *args); }
+	SYS_PMC_CONTROL          = 342 // { int|sys||pmc_control(int ctr, int op, void *args); }
+	SYS_RASCTL               = 343 // { int|sys||rasctl(void *addr, size_t len, int op); }
+	SYS_KQUEUE               = 344 // { int|sys||kqueue(void); }
+	SYS__SCHED_SETPARAM      = 346 // { int|sys||_sched_setparam(pid_t pid, lwpid_t lid, int policy, const struct sched_param *params); }
+	SYS__SCHED_GETPARAM      = 347 // { int|sys||_sched_getparam(pid_t pid, lwpid_t lid, int *policy, struct sched_param *params); }
+	SYS__SCHED_SETAFFINITY   = 348 // { int|sys||_sched_setaffinity(pid_t pid, lwpid_t lid, size_t size, const cpuset_t *cpuset); }
+	SYS__SCHED_GETAFFINITY   = 349 // { int|sys||_sched_getaffinity(pid_t pid, lwpid_t lid, size_t size, cpuset_t *cpuset); }
+	SYS_SCHED_YIELD          = 350 // { int|sys||sched_yield(void); }
+	SYS_FSYNC_RANGE          = 354 // { int|sys||fsync_range(int fd, int flags, off_t start, off_t length); }
+	SYS_UUIDGEN              = 355 // { int|sys||uuidgen(struct uuid *store, int count); }
+	SYS_GETVFSSTAT           = 356 // { int|sys||getvfsstat(struct statvfs *buf, size_t bufsize, int flags); }
+	SYS_STATVFS1             = 357 // { int|sys||statvfs1(const char *path, struct statvfs *buf, int flags); }
+	SYS_FSTATVFS1            = 358 // { int|sys||fstatvfs1(int fd, struct statvfs *buf, int flags); }
+	SYS_EXTATTRCTL           = 360 // { int|sys||extattrctl(const char *path, int cmd, const char *filename, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_SET_FILE     = 361 // { int|sys||extattr_set_file(const char *path, int attrnamespace, const char *attrname, const void *data, size_t nbytes); }
+	SYS_EXTATTR_GET_FILE     = 362 // { ssize_t|sys||extattr_get_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); }
+	SYS_EXTATTR_DELETE_FILE  = 363 // { int|sys||extattr_delete_file(const char *path, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_SET_FD       = 364 // { int|sys||extattr_set_fd(int fd, int attrnamespace, const char *attrname, const void *data, size_t nbytes); }
+	SYS_EXTATTR_GET_FD       = 365 // { ssize_t|sys||extattr_get_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); }
+	SYS_EXTATTR_DELETE_FD    = 366 // { int|sys||extattr_delete_fd(int fd, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_SET_LINK     = 367 // { int|sys||extattr_set_link(const char *path, int attrnamespace, const char *attrname, const void *data, size_t nbytes); }
+	SYS_EXTATTR_GET_LINK     = 368 // { ssize_t|sys||extattr_get_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); }
+	SYS_EXTATTR_DELETE_LINK  = 369 // { int|sys||extattr_delete_link(const char *path, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_LIST_FD      = 370 // { ssize_t|sys||extattr_list_fd(int fd, int attrnamespace, void *data, size_t nbytes); }
+	SYS_EXTATTR_LIST_FILE    = 371 // { ssize_t|sys||extattr_list_file(const char *path, int attrnamespace, void *data, size_t nbytes); }
+	SYS_EXTATTR_LIST_LINK    = 372 // { ssize_t|sys||extattr_list_link(const char *path, int attrnamespace, void *data, size_t nbytes); }
+	SYS_SETXATTR             = 375 // { int|sys||setxattr(const char *path, const char *name, const void *value, size_t size, int flags); }
+	SYS_LSETXATTR            = 376 // { int|sys||lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags); }
+	SYS_FSETXATTR            = 377 // { int|sys||fsetxattr(int fd, const char *name, const void *value, size_t size, int flags); }
+	SYS_GETXATTR             = 378 // { int|sys||getxattr(const char *path, const char *name, void *value, size_t size); }
+	SYS_LGETXATTR            = 379 // { int|sys||lgetxattr(const char *path, const char *name, void *value, size_t size); }
+	SYS_FGETXATTR            = 380 // { int|sys||fgetxattr(int fd, const char *name, void *value, size_t size); }
+	SYS_LISTXATTR            = 381 // { int|sys||listxattr(const char *path, char *list, size_t size); }
+	SYS_LLISTXATTR           = 382 // { int|sys||llistxattr(const char *path, char *list, size_t size); }
+	SYS_FLISTXATTR           = 383 // { int|sys||flistxattr(int fd, char *list, size_t size); }
+	SYS_REMOVEXATTR          = 384 // { int|sys||removexattr(const char *path, const char *name); }
+	SYS_LREMOVEXATTR         = 385 // { int|sys||lremovexattr(const char *path, const char *name); }
+	SYS_FREMOVEXATTR         = 386 // { int|sys||fremovexattr(int fd, const char *name); }
+	SYS_GETDENTS             = 390 // { int|sys|30|getdents(int fd, char *buf, size_t count); }
+	SYS_SOCKET               = 394 // { int|sys|30|socket(int domain, int type, int protocol); }
+	SYS_GETFH                = 395 // { int|sys|30|getfh(const char *fname, void *fhp, size_t *fh_size); }
+	SYS_MOUNT                = 410 // { int|sys|50|mount(const char *type, const char *path, int flags, void *data, size_t data_len); }
+	SYS_MREMAP               = 411 // { void *|sys||mremap(void *old_address, size_t old_size, void *new_address, size_t new_size, int flags); }
+	SYS_PSET_CREATE          = 412 // { int|sys||pset_create(psetid_t *psid); }
+	SYS_PSET_DESTROY         = 413 // { int|sys||pset_destroy(psetid_t psid); }
+	SYS_PSET_ASSIGN          = 414 // { int|sys||pset_assign(psetid_t psid, cpuid_t cpuid, psetid_t *opsid); }
+	SYS__PSET_BIND           = 415 // { int|sys||_pset_bind(idtype_t idtype, id_t first_id, id_t second_id, psetid_t psid, psetid_t *opsid); }
+	SYS_POSIX_FADVISE        = 416 // { int|sys|50|posix_fadvise(int fd, int PAD, off_t offset, off_t len, int advice); }
+	SYS_SELECT               = 417 // { int|sys|50|select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); }
+	SYS_GETTIMEOFDAY         = 418 // { int|sys|50|gettimeofday(struct timeval *tp, void *tzp); }
+	SYS_SETTIMEOFDAY         = 419 // { int|sys|50|settimeofday(const struct timeval *tv, const void *tzp); }
+	SYS_UTIMES               = 420 // { int|sys|50|utimes(const char *path, const struct timeval *tptr); }
+	SYS_ADJTIME              = 421 // { int|sys|50|adjtime(const struct timeval *delta, struct timeval *olddelta); }
+	SYS_FUTIMES              = 423 // { int|sys|50|futimes(int fd, const struct timeval *tptr); }
+	SYS_LUTIMES              = 424 // { int|sys|50|lutimes(const char *path, const struct timeval *tptr); }
+	SYS_SETITIMER            = 425 // { int|sys|50|setitimer(int which, const struct itimerval *itv, struct itimerval *oitv); }
+	SYS_GETITIMER            = 426 // { int|sys|50|getitimer(int which, struct itimerval *itv); }
+	SYS_CLOCK_GETTIME        = 427 // { int|sys|50|clock_gettime(clockid_t clock_id, struct timespec *tp); }
+	SYS_CLOCK_SETTIME        = 428 // { int|sys|50|clock_settime(clockid_t clock_id, const struct timespec *tp); }
+	SYS_CLOCK_GETRES         = 429 // { int|sys|50|clock_getres(clockid_t clock_id, struct timespec *tp); }
+	SYS_NANOSLEEP            = 430 // { int|sys|50|nanosleep(const struct timespec *rqtp, struct timespec *rmtp); }
+	SYS___SIGTIMEDWAIT       = 431 // { int|sys|50|__sigtimedwait(const sigset_t *set, siginfo_t *info, struct timespec *timeout); }
+	SYS__LWP_PARK            = 434 // { int|sys|50|_lwp_park(const struct timespec *ts, lwpid_t unpark, const void *hint, const void *unparkhint); }
+	SYS_KEVENT               = 435 // { int|sys|50|kevent(int fd, const struct kevent *changelist, size_t nchanges, struct kevent *eventlist, size_t nevents, const struct timespec *timeout); }
+	SYS_PSELECT              = 436 // { int|sys|50|pselect(int nd, fd_set *in, fd_set *ou, fd_set *ex, const struct timespec *ts, const sigset_t *mask); }
+	SYS_POLLTS               = 437 // { int|sys|50|pollts(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *mask); }
+	SYS_STAT                 = 439 // { int|sys|50|stat(const char *path, struct stat *ub); }
+	SYS_FSTAT                = 440 // { int|sys|50|fstat(int fd, struct stat *sb); }
+	SYS_LSTAT                = 441 // { int|sys|50|lstat(const char *path, struct stat *ub); }
+	SYS___SEMCTL             = 442 // { int|sys|50|__semctl(int semid, int semnum, int cmd, ... union __semun *arg); }
+	SYS_SHMCTL               = 443 // { int|sys|50|shmctl(int shmid, int cmd, struct shmid_ds *buf); }
+	SYS_MSGCTL               = 444 // { int|sys|50|msgctl(int msqid, int cmd, struct msqid_ds *buf); }
+	SYS_GETRUSAGE            = 445 // { int|sys|50|getrusage(int who, struct rusage *rusage); }
+	SYS_TIMER_SETTIME        = 446 // { int|sys|50|timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue); }
+	SYS_TIMER_GETTIME        = 447 // { int|sys|50|timer_gettime(timer_t timerid, struct itimerspec *value); }
+	SYS_NTP_GETTIME          = 448 // { int|sys|50|ntp_gettime(struct ntptimeval *ntvp); }
+	SYS_WAIT4                = 449 // { int|sys|50|wait4(pid_t pid, int *status, int options, struct rusage *rusage); }
+	SYS_MKNOD                = 450 // { int|sys|50|mknod(const char *path, mode_t mode, dev_t dev); }
+	SYS_FHSTAT               = 451 // { int|sys|50|fhstat(const void *fhp, size_t fh_size, struct stat *sb); }
+	SYS_PIPE2                = 453 // { int|sys||pipe2(int *fildes, int flags); }
+	SYS_DUP3                 = 454 // { int|sys||dup3(int from, int to, int flags); }
+	SYS_KQUEUE1              = 455 // { int|sys||kqueue1(int flags); }
+	SYS_PACCEPT              = 456 // { int|sys||paccept(int s, struct sockaddr *name, socklen_t *anamelen, const sigset_t *mask, int flags); }
+	SYS_LINKAT               = 457 // { int|sys||linkat(int fd1, const char *name1, int fd2, const char *name2, int flags); }
+	SYS_RENAMEAT             = 458 // { int|sys||renameat(int fromfd, const char *from, int tofd, const char *to); }
+	SYS_MKFIFOAT             = 459 // { int|sys||mkfifoat(int fd, const char *path, mode_t mode); }
+	SYS_MKNODAT              = 460 // { int|sys||mknodat(int fd, const char *path, mode_t mode, uint32_t dev); }
+	SYS_MKDIRAT              = 461 // { int|sys||mkdirat(int fd, const char *path, mode_t mode); }
+	SYS_FACCESSAT            = 462 // { int|sys||faccessat(int fd, const char *path, int amode, int flag); }
+	SYS_FCHMODAT             = 463 // { int|sys||fchmodat(int fd, const char *path, mode_t mode, int flag); }
+	SYS_FCHOWNAT             = 464 // { int|sys||fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag); }
+	SYS_FEXECVE              = 465 // { int|sys||fexecve(int fd, char * const *argp, char * const *envp); }
+	SYS_FSTATAT              = 466 // { int|sys||fstatat(int fd, const char *path, struct stat *buf, int flag); }
+	SYS_UTIMENSAT            = 467 // { int|sys||utimensat(int fd, const char *path, const struct timespec *tptr, int flag); }
+	SYS_OPENAT               = 468 // { int|sys||openat(int fd, const char *path, int oflags, ... mode_t mode); }
+	SYS_READLINKAT           = 469 // { int|sys||readlinkat(int fd, const char *path, char *buf, size_t bufsize); }
+	SYS_SYMLINKAT            = 470 // { int|sys||symlinkat(const char *path1, int fd, const char *path2); }
+	SYS_UNLINKAT             = 471 // { int|sys||unlinkat(int fd, const char *path, int flag); }
+	SYS_FUTIMENS             = 472 // { int|sys||futimens(int fd, const struct timespec *tptr); }
+	SYS___QUOTACTL           = 473 // { int|sys||__quotactl(const char *path, struct quotactl_args *args); }
+	SYS_POSIX_SPAWN          = 474 // { int|sys||posix_spawn(pid_t *pid, const char *path, const struct posix_spawn_file_actions *file_actions, const struct posix_spawnattr *attrp, char *const *argv, char *const *envp); }
+	SYS_RECVMMSG             = 475 // { int|sys||recvmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags, struct timespec *timeout); }
+	SYS_SENDMMSG             = 476 // { int|sys||sendmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags); }
+)
diff --git a/src/pkg/syscall/zsysnum_openbsd_386.go b/src/pkg/syscall/zsysnum_openbsd_386.go
index 1d97fe0..82c98b9 100644
--- a/src/pkg/syscall/zsysnum_openbsd_386.go
+++ b/src/pkg/syscall/zsysnum_openbsd_386.go
@@ -1,4 +1,4 @@
-// mksysnum_openbsd.pl 
+// mksysnum_openbsd.pl
 // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
 
 package syscall
@@ -11,6 +11,7 @@ const (
 	SYS_OPEN           = 5   // { int sys_open(const char *path, \
 	SYS_CLOSE          = 6   // { int sys_close(int fd); }
 	SYS_WAIT4          = 7   // { pid_t sys_wait4(pid_t pid, int *status, int options, \
+	SYS___TFORK        = 8   // { int sys___tfork(const struct __tfork *param, \
 	SYS_LINK           = 9   // { int sys_link(const char *path, const char *link); }
 	SYS_UNLINK         = 10  // { int sys_unlink(const char *path); }
 	SYS_CHDIR          = 12  // { int sys_chdir(const char *path); }
@@ -19,6 +20,7 @@ const (
 	SYS_CHMOD          = 15  // { int sys_chmod(const char *path, mode_t mode); }
 	SYS_CHOWN          = 16  // { int sys_chown(const char *path, uid_t uid, \
 	SYS_OBREAK         = 17  // { int sys_obreak(char *nsize); } break
+	SYS_GETDTABLECOUNT = 18  // { int sys_getdtablecount(void); }
 	SYS_GETPID         = 20  // { pid_t sys_getpid(void); }
 	SYS_MOUNT          = 21  // { int sys_mount(const char *type, const char *path, \
 	SYS_UNMOUNT        = 22  // { int sys_unmount(const char *path, int flags); }
@@ -111,10 +113,6 @@ const (
 	SYS_SETGID         = 181 // { int sys_setgid(gid_t gid); }
 	SYS_SETEGID        = 182 // { int sys_setegid(gid_t egid); }
 	SYS_SETEUID        = 183 // { int sys_seteuid(uid_t euid); }
-	LFS_BMAPV          = 184 // { int lfs_bmapv(fsid_t *fsidp, \
-	LFS_MARKV          = 185 // { int lfs_markv(fsid_t *fsidp, \
-	LFS_SEGCLEAN       = 186 // { int lfs_segclean(fsid_t *fsidp, u_long segment); }
-	LFS_SEGWAIT        = 187 // { int lfs_segwait(fsid_t *fsidp, struct timeval *tv); }
 	SYS_PATHCONF       = 191 // { long sys_pathconf(const char *path, int name); }
 	SYS_FPATHCONF      = 192 // { long sys_fpathconf(int fd, int name); }
 	SYS_SWAPCTL        = 193 // { int sys_swapctl(int cmd, const void *arg, int misc); }
@@ -129,7 +127,6 @@ const (
 	SYS_MUNLOCK        = 204 // { int sys_munlock(const void *addr, size_t len); }
 	SYS_FUTIMES        = 206 // { int sys_futimes(int fd, \
 	SYS_GETPGID        = 207 // { pid_t sys_getpgid(pid_t pid); }
-	SYS_NNPFSPIOCTL    = 208 // { int sys_nnpfspioctl(int operation, char *a_pathP, \
 	SYS_SEMGET         = 221 // { int sys_semget(key_t key, int nsems, int semflg); }
 	SYS_MSGGET         = 225 // { int sys_msgget(key_t key, int msgflg); }
 	SYS_MSGSND         = 226 // { int sys_msgsnd(int msqid, const void *msgp, size_t msgsz, \
@@ -141,7 +138,6 @@ const (
 	SYS_CLOCK_GETRES   = 234 // { int sys_clock_getres(clockid_t clock_id, \
 	SYS_NANOSLEEP      = 240 // { int sys_nanosleep(const struct timespec *rqtp, \
 	SYS_MINHERIT       = 250 // { int sys_minherit(void *addr, size_t len, \
-	SYS_RFORK          = 251 // { int sys_rfork(int flags); }
 	SYS_POLL           = 252 // { int sys_poll(struct pollfd *fds, \
 	SYS_ISSETUGID      = 253 // { int sys_issetugid(void); }
 	SYS_LCHOWN         = 254 // { int sys_lchown(const char *path, uid_t uid, gid_t gid); }
@@ -201,7 +197,6 @@ const (
 	SYS_UNLINKAT       = 325 // { int sys_unlinkat(int fd, const char *path, \
 	SYS_UTIMENSAT      = 326 // { int sys_utimensat(int fd, const char *path, \
 	SYS_FUTIMENS       = 327 // { int sys_futimens(int fd, \
-	SYS___TFORK        = 328 // { int sys___tfork(struct __tfork *param); }
 	SYS___SET_TCB      = 329 // { void sys___set_tcb(void *tcb); }
 	SYS___GET_TCB      = 330 // { void *sys___get_tcb(void); }
 )
diff --git a/src/pkg/syscall/zsysnum_openbsd_amd64.go b/src/pkg/syscall/zsysnum_openbsd_amd64.go
index 1d97fe0..82c98b9 100644
--- a/src/pkg/syscall/zsysnum_openbsd_amd64.go
+++ b/src/pkg/syscall/zsysnum_openbsd_amd64.go
@@ -1,4 +1,4 @@
-// mksysnum_openbsd.pl 
+// mksysnum_openbsd.pl
 // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
 
 package syscall
@@ -11,6 +11,7 @@ const (
 	SYS_OPEN           = 5   // { int sys_open(const char *path, \
 	SYS_CLOSE          = 6   // { int sys_close(int fd); }
 	SYS_WAIT4          = 7   // { pid_t sys_wait4(pid_t pid, int *status, int options, \
+	SYS___TFORK        = 8   // { int sys___tfork(const struct __tfork *param, \
 	SYS_LINK           = 9   // { int sys_link(const char *path, const char *link); }
 	SYS_UNLINK         = 10  // { int sys_unlink(const char *path); }
 	SYS_CHDIR          = 12  // { int sys_chdir(const char *path); }
@@ -19,6 +20,7 @@ const (
 	SYS_CHMOD          = 15  // { int sys_chmod(const char *path, mode_t mode); }
 	SYS_CHOWN          = 16  // { int sys_chown(const char *path, uid_t uid, \
 	SYS_OBREAK         = 17  // { int sys_obreak(char *nsize); } break
+	SYS_GETDTABLECOUNT = 18  // { int sys_getdtablecount(void); }
 	SYS_GETPID         = 20  // { pid_t sys_getpid(void); }
 	SYS_MOUNT          = 21  // { int sys_mount(const char *type, const char *path, \
 	SYS_UNMOUNT        = 22  // { int sys_unmount(const char *path, int flags); }
@@ -111,10 +113,6 @@ const (
 	SYS_SETGID         = 181 // { int sys_setgid(gid_t gid); }
 	SYS_SETEGID        = 182 // { int sys_setegid(gid_t egid); }
 	SYS_SETEUID        = 183 // { int sys_seteuid(uid_t euid); }
-	LFS_BMAPV          = 184 // { int lfs_bmapv(fsid_t *fsidp, \
-	LFS_MARKV          = 185 // { int lfs_markv(fsid_t *fsidp, \
-	LFS_SEGCLEAN       = 186 // { int lfs_segclean(fsid_t *fsidp, u_long segment); }
-	LFS_SEGWAIT        = 187 // { int lfs_segwait(fsid_t *fsidp, struct timeval *tv); }
 	SYS_PATHCONF       = 191 // { long sys_pathconf(const char *path, int name); }
 	SYS_FPATHCONF      = 192 // { long sys_fpathconf(int fd, int name); }
 	SYS_SWAPCTL        = 193 // { int sys_swapctl(int cmd, const void *arg, int misc); }
@@ -129,7 +127,6 @@ const (
 	SYS_MUNLOCK        = 204 // { int sys_munlock(const void *addr, size_t len); }
 	SYS_FUTIMES        = 206 // { int sys_futimes(int fd, \
 	SYS_GETPGID        = 207 // { pid_t sys_getpgid(pid_t pid); }
-	SYS_NNPFSPIOCTL    = 208 // { int sys_nnpfspioctl(int operation, char *a_pathP, \
 	SYS_SEMGET         = 221 // { int sys_semget(key_t key, int nsems, int semflg); }
 	SYS_MSGGET         = 225 // { int sys_msgget(key_t key, int msgflg); }
 	SYS_MSGSND         = 226 // { int sys_msgsnd(int msqid, const void *msgp, size_t msgsz, \
@@ -141,7 +138,6 @@ const (
 	SYS_CLOCK_GETRES   = 234 // { int sys_clock_getres(clockid_t clock_id, \
 	SYS_NANOSLEEP      = 240 // { int sys_nanosleep(const struct timespec *rqtp, \
 	SYS_MINHERIT       = 250 // { int sys_minherit(void *addr, size_t len, \
-	SYS_RFORK          = 251 // { int sys_rfork(int flags); }
 	SYS_POLL           = 252 // { int sys_poll(struct pollfd *fds, \
 	SYS_ISSETUGID      = 253 // { int sys_issetugid(void); }
 	SYS_LCHOWN         = 254 // { int sys_lchown(const char *path, uid_t uid, gid_t gid); }
@@ -201,7 +197,6 @@ const (
 	SYS_UNLINKAT       = 325 // { int sys_unlinkat(int fd, const char *path, \
 	SYS_UTIMENSAT      = 326 // { int sys_utimensat(int fd, const char *path, \
 	SYS_FUTIMENS       = 327 // { int sys_futimens(int fd, \
-	SYS___TFORK        = 328 // { int sys___tfork(struct __tfork *param); }
 	SYS___SET_TCB      = 329 // { void sys___set_tcb(void *tcb); }
 	SYS___GET_TCB      = 330 // { void *sys___get_tcb(void); }
 )
diff --git a/src/pkg/syscall/zsysnum_plan9_amd64.go b/src/pkg/syscall/zsysnum_plan9_amd64.go
new file mode 100644
index 0000000..c038646
--- /dev/null
+++ b/src/pkg/syscall/zsysnum_plan9_amd64.go
@@ -0,0 +1,48 @@
+// 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/syscall/ztypes_darwin_386.go b/src/pkg/syscall/ztypes_darwin_386.go
index 566b021..71346fb 100644
--- a/src/pkg/syscall/ztypes_darwin_386.go
+++ b/src/pkg/syscall/ztypes_darwin_386.go
@@ -226,6 +226,12 @@ type Cmsghdr struct {
 	Type  int32
 }
 
+type Inet4Pktinfo struct {
+	Ifindex  uint32
+	Spec_dst [4]byte /* in_addr */
+	Addr     [4]byte /* in_addr */
+}
+
 type Inet6Pktinfo struct {
 	Addr    [16]byte /* in6_addr */
 	Ifindex uint32
@@ -242,6 +248,7 @@ const (
 	SizeofIPv6Mreq         = 0x14
 	SizeofMsghdr           = 0x1c
 	SizeofCmsghdr          = 0xc
+	SizeofInet4Pktinfo     = 0xc
 	SizeofInet6Pktinfo     = 0x14
 )
 
@@ -416,3 +423,13 @@ type BpfHdr struct {
 	Hdrlen    uint16
 	Pad_cgo_0 [2]byte
 }
+
+type Termios struct {
+	Iflag  uint32
+	Oflag  uint32
+	Cflag  uint32
+	Lflag  uint32
+	Cc     [20]uint8
+	Ispeed uint32
+	Ospeed uint32
+}
diff --git a/src/pkg/syscall/ztypes_darwin_amd64.go b/src/pkg/syscall/ztypes_darwin_amd64.go
index 2c65311..f0809fe 100644
--- a/src/pkg/syscall/ztypes_darwin_amd64.go
+++ b/src/pkg/syscall/ztypes_darwin_amd64.go
@@ -234,6 +234,12 @@ type Cmsghdr struct {
 	Type  int32
 }
 
+type Inet4Pktinfo struct {
+	Ifindex  uint32
+	Spec_dst [4]byte /* in_addr */
+	Addr     [4]byte /* in_addr */
+}
+
 type Inet6Pktinfo struct {
 	Addr    [16]byte /* in6_addr */
 	Ifindex uint32
@@ -250,6 +256,7 @@ const (
 	SizeofIPv6Mreq         = 0x14
 	SizeofMsghdr           = 0x30
 	SizeofCmsghdr          = 0xc
+	SizeofInet4Pktinfo     = 0xc
 	SizeofInet6Pktinfo     = 0x14
 )
 
@@ -425,3 +432,14 @@ type BpfHdr struct {
 	Hdrlen    uint16
 	Pad_cgo_0 [2]byte
 }
+
+type Termios struct {
+	Iflag     uint64
+	Oflag     uint64
+	Cflag     uint64
+	Lflag     uint64
+	Cc        [20]uint8
+	Pad_cgo_0 [4]byte
+	Ispeed    uint64
+	Ospeed    uint64
+}
diff --git a/src/pkg/syscall/ztypes_freebsd_386.go b/src/pkg/syscall/ztypes_freebsd_386.go
index 4149948..89de58e 100644
--- a/src/pkg/syscall/ztypes_freebsd_386.go
+++ b/src/pkg/syscall/ztypes_freebsd_386.go
@@ -271,12 +271,13 @@ type FdSet struct {
 }
 
 const (
-	SizeofIfMsghdr   = 0x60
-	SizeofIfData     = 0x50
-	SizeofIfaMsghdr  = 0x14
-	SizeofIfmaMsghdr = 0x10
-	SizeofRtMsghdr   = 0x5c
-	SizeofRtMetrics  = 0x38
+	SizeofIfMsghdr         = 0x60
+	SizeofIfData           = 0x50
+	SizeofIfaMsghdr        = 0x14
+	SizeofIfmaMsghdr       = 0x10
+	SizeofIfAnnounceMsghdr = 0x18
+	SizeofRtMsghdr         = 0x5c
+	SizeofRtMetrics        = 0x38
 )
 
 type IfMsghdr struct {
@@ -339,6 +340,15 @@ type IfmaMsghdr struct {
 	Pad_cgo_0 [2]byte
 }
 
+type IfAnnounceMsghdr struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+	Index   uint16
+	Name    [16]int8
+	What    uint16
+}
+
 type RtMsghdr struct {
 	Msglen    uint16
 	Version   uint8
diff --git a/src/pkg/syscall/ztypes_freebsd_amd64.go b/src/pkg/syscall/ztypes_freebsd_amd64.go
index 80c12f6..d5e8768 100644
--- a/src/pkg/syscall/ztypes_freebsd_amd64.go
+++ b/src/pkg/syscall/ztypes_freebsd_amd64.go
@@ -273,12 +273,13 @@ type FdSet struct {
 }
 
 const (
-	SizeofIfMsghdr   = 0xa8
-	SizeofIfData     = 0x98
-	SizeofIfaMsghdr  = 0x14
-	SizeofIfmaMsghdr = 0x10
-	SizeofRtMsghdr   = 0x98
-	SizeofRtMetrics  = 0x70
+	SizeofIfMsghdr         = 0xa8
+	SizeofIfData           = 0x98
+	SizeofIfaMsghdr        = 0x14
+	SizeofIfmaMsghdr       = 0x10
+	SizeofIfAnnounceMsghdr = 0x18
+	SizeofRtMsghdr         = 0x98
+	SizeofRtMetrics        = 0x70
 )
 
 type IfMsghdr struct {
@@ -341,6 +342,15 @@ type IfmaMsghdr struct {
 	Pad_cgo_0 [2]byte
 }
 
+type IfAnnounceMsghdr struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+	Index   uint16
+	Name    [16]int8
+	What    uint16
+}
+
 type RtMsghdr struct {
 	Msglen    uint16
 	Version   uint8
diff --git a/src/pkg/syscall/ztypes_freebsd_arm.go b/src/pkg/syscall/ztypes_freebsd_arm.go
new file mode 100644
index 0000000..4f67a39
--- /dev/null
+++ b/src/pkg/syscall/ztypes_freebsd_arm.go
@@ -0,0 +1,436 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_freebsd.go
+
+package syscall
+
+const (
+	sizeofPtr      = 0x4
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x4
+	sizeofLongLong = 0x8
+)
+
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int32
+	_C_long_long int64
+)
+
+type Timespec struct {
+	Sec  int64
+	Nsec int32
+}
+
+type Timeval struct {
+	Sec  int64
+	Usec int32
+}
+
+type Rusage struct {
+	Utime    Timeval
+	Stime    Timeval
+	Maxrss   int32
+	Ixrss    int32
+	Idrss    int32
+	Isrss    int32
+	Minflt   int32
+	Majflt   int32
+	Nswap    int32
+	Inblock  int32
+	Oublock  int32
+	Msgsnd   int32
+	Msgrcv   int32
+	Nsignals int32
+	Nvcsw    int32
+	Nivcsw   int32
+}
+
+type Rlimit struct {
+	Cur int64
+	Max int64
+}
+
+type _Gid_t uint32
+
+const (
+	O_CLOEXEC = 0 // not supported
+)
+
+const (
+	S_IFMT   = 0xf000
+	S_IFIFO  = 0x1000
+	S_IFCHR  = 0x2000
+	S_IFDIR  = 0x4000
+	S_IFBLK  = 0x6000
+	S_IFREG  = 0x8000
+	S_IFLNK  = 0xa000
+	S_IFSOCK = 0xc000
+	S_ISUID  = 0x800
+	S_ISGID  = 0x400
+	S_ISVTX  = 0x200
+	S_IRUSR  = 0x100
+	S_IWUSR  = 0x80
+	S_IXUSR  = 0x40
+)
+
+type Stat_t struct {
+	Dev           uint32
+	Ino           uint32
+	Mode          uint16
+	Nlink         uint16
+	Uid           uint32
+	Gid           uint32
+	Rdev          uint32
+	Atimespec     Timespec
+	Mtimespec     Timespec
+	Ctimespec     Timespec
+	Size          int64
+	Blocks        int64
+	Blksize       uint32
+	Flags         uint32
+	Gen           uint32
+	Lspare        int32
+	Birthtimespec Timespec
+	Pad_cgo_0     [4]byte
+}
+
+type Statfs_t struct {
+	Version     uint32
+	Type        uint32
+	Flags       uint64
+	Bsize       uint64
+	Iosize      uint64
+	Blocks      uint64
+	Bfree       uint64
+	Bavail      int64
+	Files       uint64
+	Ffree       int64
+	Syncwrites  uint64
+	Asyncwrites uint64
+	Syncreads   uint64
+	Asyncreads  uint64
+	Spare       [10]uint64
+	Namemax     uint32
+	Owner       uint32
+	Fsid        Fsid
+	Charspare   [80]int8
+	Fstypename  [16]int8
+	Mntfromname [88]int8
+	Mntonname   [88]int8
+}
+
+type Flock_t struct {
+	Start  int64
+	Len    int64
+	Pid    int32
+	Type   int16
+	Whence int16
+	Sysid  int32
+}
+
+type Dirent struct {
+	Fileno uint32
+	Reclen uint16
+	Type   uint8
+	Namlen uint8
+	Name   [256]int8
+}
+
+type Fsid struct {
+	Val [2]int32
+}
+
+type RawSockaddrInet4 struct {
+	Len    uint8
+	Family uint8
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]int8
+}
+
+type RawSockaddrInet6 struct {
+	Len      uint8
+	Family   uint8
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+	Len       uint8
+	Family    uint8
+	Path      [104]int8
+	Pad_cgo_0 [2]byte
+}
+
+type RawSockaddrDatalink struct {
+	Len       uint8
+	Family    uint8
+	Index     uint16
+	Type      uint8
+	Nlen      uint8
+	Alen      uint8
+	Slen      uint8
+	Data      [46]int8
+	Pad_cgo_0 [2]byte
+}
+
+type RawSockaddr struct {
+	Len    uint8
+	Family uint8
+	Data   [14]int8
+}
+
+type RawSockaddrAny struct {
+	Addr RawSockaddr
+	Pad  [92]int8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+	Onoff  int32
+	Linger int32
+}
+
+type Iovec struct {
+	Base *byte
+	Len  uint32
+}
+
+type IPMreq struct {
+	Multiaddr [4]byte /* in_addr */
+	Interface [4]byte /* in_addr */
+}
+
+type IPMreqn struct {
+	Multiaddr [4]byte /* in_addr */
+	Address   [4]byte /* in_addr */
+	Ifindex   int32
+}
+
+type IPv6Mreq struct {
+	Multiaddr [16]byte /* in6_addr */
+	Interface uint32
+}
+
+type Msghdr struct {
+	Name       *byte
+	Namelen    uint32
+	Iov        *Iovec
+	Iovlen     int32
+	Control    *byte
+	Controllen uint32
+	Flags      int32
+}
+
+type Cmsghdr struct {
+	Len   uint32
+	Level int32
+	Type  int32
+}
+
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
+const (
+	SizeofSockaddrInet4    = 0x10
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x6c
+	SizeofSockaddrUnix     = 0x6c
+	SizeofSockaddrDatalink = 0x38
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPMreqn          = 0xc
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x1c
+	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
+)
+
+const (
+	PTRACE_TRACEME = 0x0
+	PTRACE_CONT    = 0x7
+	PTRACE_KILL    = 0x8
+)
+
+type Kevent_t struct {
+	Ident  uint32
+	Filter int16
+	Flags  uint16
+	Fflags uint32
+	Data   int32
+	Udata  *byte
+}
+
+type FdSet struct {
+	X__fds_bits [32]uint32
+}
+
+const (
+	SizeofIfMsghdr         = 0x68
+	SizeofIfData           = 0x58
+	SizeofIfaMsghdr        = 0x14
+	SizeofIfmaMsghdr       = 0x10
+	SizeofIfAnnounceMsghdr = 0x18
+	SizeofRtMsghdr         = 0x5c
+	SizeofRtMetrics        = 0x38
+)
+
+type IfMsghdr struct {
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Data      IfData
+}
+
+type IfData struct {
+	Type        uint8
+	Physical    uint8
+	Addrlen     uint8
+	Hdrlen      uint8
+	Link_state  uint8
+	Spare_char1 uint8 //Vhid        uint8
+	Spare_char2 uint8
+	Datalen     uint8
+	Mtu         uint32
+	Metric      uint32
+	Baudrate    uint32
+	Ipackets    uint32
+	Ierrors     uint32
+	Opackets    uint32
+	Oerrors     uint32
+	Collisions  uint32
+	Ibytes      uint32
+	Obytes      uint32
+	Imcasts     uint32
+	Omcasts     uint32
+	Iqdrops     uint32
+	Noproto     uint32
+	Hwassist    uint32
+	Epoch       int64
+	Lastchange  Timeval
+}
+
+type IfaMsghdr struct {
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Metric    int32
+}
+
+type IfmaMsghdr struct {
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+}
+
+type IfAnnounceMsghdr struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+	Index   uint16
+	Name    [16]int8
+	What    uint16
+}
+
+type RtMsghdr struct {
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Flags     int32
+	Addrs     int32
+	Pid       int32
+	Seq       int32
+	Errno     int32
+	Fmask     int32
+	Inits     uint32
+	Rmx       RtMetrics
+}
+
+type RtMetrics struct {
+	Locks    uint32
+	Mtu      uint32
+	Hopcount uint32
+	Expire   uint32
+	Recvpipe uint32
+	Sendpipe uint32
+	Ssthresh uint32
+	Rtt      uint32
+	Rttvar   uint32
+	Pksent   uint32
+	Weight   uint32
+	Filler   [3]uint32
+}
+
+const (
+	SizeofBpfVersion    = 0x4
+	SizeofBpfStat       = 0x8
+	SizeofBpfZbuf       = 0xc
+	SizeofBpfProgram    = 0x8
+	SizeofBpfInsn       = 0x8
+	SizeofBpfHdr        = 0x18
+	SizeofBpfZbufHeader = 0x20
+)
+
+type BpfVersion struct {
+	Major uint16
+	Minor uint16
+}
+
+type BpfStat struct {
+	Recv uint32
+	Drop uint32
+}
+
+type BpfZbuf struct {
+	Bufa   *byte
+	Bufb   *byte
+	Buflen uint32
+}
+
+type BpfProgram struct {
+	Len   uint32
+	Insns *BpfInsn
+}
+
+type BpfInsn struct {
+	Code uint16
+	Jt   uint8
+	Jf   uint8
+	K    uint32
+}
+
+type BpfHdr struct {
+	Tstamp    Timeval
+	Caplen    uint32
+	Datalen   uint32
+	Hdrlen    uint16
+	Pad_cgo_0 [2]byte
+}
+
+type BpfZbufHeader struct {
+	Kernel_gen uint32
+	Kernel_len uint32
+	User_gen   uint32
+	X_bzh_pad  [5]uint32
+}
diff --git a/src/pkg/syscall/ztypes_linux_386.go b/src/pkg/syscall/ztypes_linux_386.go
index fcead2f..e1c30b6 100644
--- a/src/pkg/syscall/ztypes_linux_386.go
+++ b/src/pkg/syscall/ztypes_linux_386.go
@@ -231,7 +231,7 @@ type Cmsghdr struct {
 	Len          uint32
 	Level        int32
 	Type         int32
-	X__cmsg_data [0]byte
+	X__cmsg_data [0]uint8
 }
 
 type Inet4Pktinfo struct {
@@ -251,6 +251,40 @@ type Ucred struct {
 	Gid uint32
 }
 
+type TCPInfo struct {
+	State          uint8
+	Ca_state       uint8
+	Retransmits    uint8
+	Probes         uint8
+	Backoff        uint8
+	Options        uint8
+	Pad_cgo_0      [2]byte
+	Rto            uint32
+	Ato            uint32
+	Snd_mss        uint32
+	Rcv_mss        uint32
+	Unacked        uint32
+	Sacked         uint32
+	Lost           uint32
+	Retrans        uint32
+	Fackets        uint32
+	Last_data_sent uint32
+	Last_ack_sent  uint32
+	Last_data_recv uint32
+	Last_ack_recv  uint32
+	Pmtu           uint32
+	Rcv_ssthresh   uint32
+	Rtt            uint32
+	Rttvar         uint32
+	Snd_ssthresh   uint32
+	Snd_cwnd       uint32
+	Advmss         uint32
+	Reordering     uint32
+	Rcv_rtt        uint32
+	Rcv_space      uint32
+	Total_retrans  uint32
+}
+
 const (
 	SizeofSockaddrInet4     = 0x10
 	SizeofSockaddrInet6     = 0x1c
@@ -267,84 +301,101 @@ const (
 	SizeofInet4Pktinfo      = 0xc
 	SizeofInet6Pktinfo      = 0x14
 	SizeofUcred             = 0xc
+	SizeofTCPInfo           = 0x68
 )
 
 const (
-	IFA_UNSPEC        = 0x0
-	IFA_ADDRESS       = 0x1
-	IFA_LOCAL         = 0x2
-	IFA_LABEL         = 0x3
-	IFA_BROADCAST     = 0x4
-	IFA_ANYCAST       = 0x5
-	IFA_CACHEINFO     = 0x6
-	IFA_MULTICAST     = 0x7
-	IFLA_UNSPEC       = 0x0
-	IFLA_ADDRESS      = 0x1
-	IFLA_BROADCAST    = 0x2
-	IFLA_IFNAME       = 0x3
-	IFLA_MTU          = 0x4
-	IFLA_LINK         = 0x5
-	IFLA_QDISC        = 0x6
-	IFLA_STATS        = 0x7
-	IFLA_COST         = 0x8
-	IFLA_PRIORITY     = 0x9
-	IFLA_MASTER       = 0xa
-	IFLA_WIRELESS     = 0xb
-	IFLA_PROTINFO     = 0xc
-	IFLA_TXQLEN       = 0xd
-	IFLA_MAP          = 0xe
-	IFLA_WEIGHT       = 0xf
-	IFLA_OPERSTATE    = 0x10
-	IFLA_LINKMODE     = 0x11
-	IFLA_LINKINFO     = 0x12
-	IFLA_NET_NS_PID   = 0x13
-	IFLA_IFALIAS      = 0x14
-	IFLA_MAX          = 0x1c
-	RT_SCOPE_UNIVERSE = 0x0
-	RT_SCOPE_SITE     = 0xc8
-	RT_SCOPE_LINK     = 0xfd
-	RT_SCOPE_HOST     = 0xfe
-	RT_SCOPE_NOWHERE  = 0xff
-	RT_TABLE_UNSPEC   = 0x0
-	RT_TABLE_COMPAT   = 0xfc
-	RT_TABLE_DEFAULT  = 0xfd
-	RT_TABLE_MAIN     = 0xfe
-	RT_TABLE_LOCAL    = 0xff
-	RT_TABLE_MAX      = 0xffffffff
-	RTA_UNSPEC        = 0x0
-	RTA_DST           = 0x1
-	RTA_SRC           = 0x2
-	RTA_IIF           = 0x3
-	RTA_OIF           = 0x4
-	RTA_GATEWAY       = 0x5
-	RTA_PRIORITY      = 0x6
-	RTA_PREFSRC       = 0x7
-	RTA_METRICS       = 0x8
-	RTA_MULTIPATH     = 0x9
-	RTA_FLOW          = 0xb
-	RTA_CACHEINFO     = 0xc
-	RTA_TABLE         = 0xf
-	RTN_UNSPEC        = 0x0
-	RTN_UNICAST       = 0x1
-	RTN_LOCAL         = 0x2
-	RTN_BROADCAST     = 0x3
-	RTN_ANYCAST       = 0x4
-	RTN_MULTICAST     = 0x5
-	RTN_BLACKHOLE     = 0x6
-	RTN_UNREACHABLE   = 0x7
-	RTN_PROHIBIT      = 0x8
-	RTN_THROW         = 0x9
-	RTN_NAT           = 0xa
-	RTN_XRESOLVE      = 0xb
-	SizeofNlMsghdr    = 0x10
-	SizeofNlMsgerr    = 0x14
-	SizeofRtGenmsg    = 0x1
-	SizeofNlAttr      = 0x4
-	SizeofRtAttr      = 0x4
-	SizeofIfInfomsg   = 0x10
-	SizeofIfAddrmsg   = 0x8
-	SizeofRtMsg       = 0xc
-	SizeofRtNexthop   = 0x8
+	IFA_UNSPEC          = 0x0
+	IFA_ADDRESS         = 0x1
+	IFA_LOCAL           = 0x2
+	IFA_LABEL           = 0x3
+	IFA_BROADCAST       = 0x4
+	IFA_ANYCAST         = 0x5
+	IFA_CACHEINFO       = 0x6
+	IFA_MULTICAST       = 0x7
+	IFLA_UNSPEC         = 0x0
+	IFLA_ADDRESS        = 0x1
+	IFLA_BROADCAST      = 0x2
+	IFLA_IFNAME         = 0x3
+	IFLA_MTU            = 0x4
+	IFLA_LINK           = 0x5
+	IFLA_QDISC          = 0x6
+	IFLA_STATS          = 0x7
+	IFLA_COST           = 0x8
+	IFLA_PRIORITY       = 0x9
+	IFLA_MASTER         = 0xa
+	IFLA_WIRELESS       = 0xb
+	IFLA_PROTINFO       = 0xc
+	IFLA_TXQLEN         = 0xd
+	IFLA_MAP            = 0xe
+	IFLA_WEIGHT         = 0xf
+	IFLA_OPERSTATE      = 0x10
+	IFLA_LINKMODE       = 0x11
+	IFLA_LINKINFO       = 0x12
+	IFLA_NET_NS_PID     = 0x13
+	IFLA_IFALIAS        = 0x14
+	IFLA_MAX            = 0x1d
+	RT_SCOPE_UNIVERSE   = 0x0
+	RT_SCOPE_SITE       = 0xc8
+	RT_SCOPE_LINK       = 0xfd
+	RT_SCOPE_HOST       = 0xfe
+	RT_SCOPE_NOWHERE    = 0xff
+	RT_TABLE_UNSPEC     = 0x0
+	RT_TABLE_COMPAT     = 0xfc
+	RT_TABLE_DEFAULT    = 0xfd
+	RT_TABLE_MAIN       = 0xfe
+	RT_TABLE_LOCAL      = 0xff
+	RT_TABLE_MAX        = 0xffffffff
+	RTA_UNSPEC          = 0x0
+	RTA_DST             = 0x1
+	RTA_SRC             = 0x2
+	RTA_IIF             = 0x3
+	RTA_OIF             = 0x4
+	RTA_GATEWAY         = 0x5
+	RTA_PRIORITY        = 0x6
+	RTA_PREFSRC         = 0x7
+	RTA_METRICS         = 0x8
+	RTA_MULTIPATH       = 0x9
+	RTA_FLOW            = 0xb
+	RTA_CACHEINFO       = 0xc
+	RTA_TABLE           = 0xf
+	RTN_UNSPEC          = 0x0
+	RTN_UNICAST         = 0x1
+	RTN_LOCAL           = 0x2
+	RTN_BROADCAST       = 0x3
+	RTN_ANYCAST         = 0x4
+	RTN_MULTICAST       = 0x5
+	RTN_BLACKHOLE       = 0x6
+	RTN_UNREACHABLE     = 0x7
+	RTN_PROHIBIT        = 0x8
+	RTN_THROW           = 0x9
+	RTN_NAT             = 0xa
+	RTN_XRESOLVE        = 0xb
+	RTNLGRP_NONE        = 0x0
+	RTNLGRP_LINK        = 0x1
+	RTNLGRP_NOTIFY      = 0x2
+	RTNLGRP_NEIGH       = 0x3
+	RTNLGRP_TC          = 0x4
+	RTNLGRP_IPV4_IFADDR = 0x5
+	RTNLGRP_IPV4_MROUTE = 0x6
+	RTNLGRP_IPV4_ROUTE  = 0x7
+	RTNLGRP_IPV4_RULE   = 0x8
+	RTNLGRP_IPV6_IFADDR = 0x9
+	RTNLGRP_IPV6_MROUTE = 0xa
+	RTNLGRP_IPV6_ROUTE  = 0xb
+	RTNLGRP_IPV6_IFINFO = 0xc
+	RTNLGRP_IPV6_PREFIX = 0x12
+	RTNLGRP_IPV6_RULE   = 0x13
+	RTNLGRP_ND_USEROPT  = 0x14
+	SizeofNlMsghdr      = 0x10
+	SizeofNlMsgerr      = 0x14
+	SizeofRtGenmsg      = 0x1
+	SizeofNlAttr        = 0x4
+	SizeofRtAttr        = 0x4
+	SizeofIfInfomsg     = 0x10
+	SizeofIfAddrmsg     = 0x8
+	SizeofRtMsg         = 0xc
+	SizeofRtNexthop     = 0x8
 )
 
 type NlMsghdr struct {
@@ -433,7 +484,7 @@ type InotifyEvent struct {
 	Mask   uint32
 	Cookie uint32
 	Len    uint32
-	Name   [0]byte
+	Name   [0]uint8
 }
 
 const SizeofInotifyEvent = 0x10
@@ -501,6 +552,10 @@ type EpollEvent struct {
 	Pad    int32
 }
 
+const (
+	_AT_FDCWD = -0x64
+)
+
 type Termios struct {
 	Iflag     uint32
 	Oflag     uint32
diff --git a/src/pkg/syscall/ztypes_linux_amd64.go b/src/pkg/syscall/ztypes_linux_amd64.go
index d5583a7..5800c3c 100644
--- a/src/pkg/syscall/ztypes_linux_amd64.go
+++ b/src/pkg/syscall/ztypes_linux_amd64.go
@@ -233,7 +233,7 @@ type Cmsghdr struct {
 	Len          uint64
 	Level        int32
 	Type         int32
-	X__cmsg_data [0]byte
+	X__cmsg_data [0]uint8
 }
 
 type Inet4Pktinfo struct {
@@ -253,6 +253,40 @@ type Ucred struct {
 	Gid uint32
 }
 
+type TCPInfo struct {
+	State          uint8
+	Ca_state       uint8
+	Retransmits    uint8
+	Probes         uint8
+	Backoff        uint8
+	Options        uint8
+	Pad_cgo_0      [2]byte
+	Rto            uint32
+	Ato            uint32
+	Snd_mss        uint32
+	Rcv_mss        uint32
+	Unacked        uint32
+	Sacked         uint32
+	Lost           uint32
+	Retrans        uint32
+	Fackets        uint32
+	Last_data_sent uint32
+	Last_ack_sent  uint32
+	Last_data_recv uint32
+	Last_ack_recv  uint32
+	Pmtu           uint32
+	Rcv_ssthresh   uint32
+	Rtt            uint32
+	Rttvar         uint32
+	Snd_ssthresh   uint32
+	Snd_cwnd       uint32
+	Advmss         uint32
+	Reordering     uint32
+	Rcv_rtt        uint32
+	Rcv_space      uint32
+	Total_retrans  uint32
+}
+
 const (
 	SizeofSockaddrInet4     = 0x10
 	SizeofSockaddrInet6     = 0x1c
@@ -269,84 +303,101 @@ const (
 	SizeofInet4Pktinfo      = 0xc
 	SizeofInet6Pktinfo      = 0x14
 	SizeofUcred             = 0xc
+	SizeofTCPInfo           = 0x68
 )
 
 const (
-	IFA_UNSPEC        = 0x0
-	IFA_ADDRESS       = 0x1
-	IFA_LOCAL         = 0x2
-	IFA_LABEL         = 0x3
-	IFA_BROADCAST     = 0x4
-	IFA_ANYCAST       = 0x5
-	IFA_CACHEINFO     = 0x6
-	IFA_MULTICAST     = 0x7
-	IFLA_UNSPEC       = 0x0
-	IFLA_ADDRESS      = 0x1
-	IFLA_BROADCAST    = 0x2
-	IFLA_IFNAME       = 0x3
-	IFLA_MTU          = 0x4
-	IFLA_LINK         = 0x5
-	IFLA_QDISC        = 0x6
-	IFLA_STATS        = 0x7
-	IFLA_COST         = 0x8
-	IFLA_PRIORITY     = 0x9
-	IFLA_MASTER       = 0xa
-	IFLA_WIRELESS     = 0xb
-	IFLA_PROTINFO     = 0xc
-	IFLA_TXQLEN       = 0xd
-	IFLA_MAP          = 0xe
-	IFLA_WEIGHT       = 0xf
-	IFLA_OPERSTATE    = 0x10
-	IFLA_LINKMODE     = 0x11
-	IFLA_LINKINFO     = 0x12
-	IFLA_NET_NS_PID   = 0x13
-	IFLA_IFALIAS      = 0x14
-	IFLA_MAX          = 0x1c
-	RT_SCOPE_UNIVERSE = 0x0
-	RT_SCOPE_SITE     = 0xc8
-	RT_SCOPE_LINK     = 0xfd
-	RT_SCOPE_HOST     = 0xfe
-	RT_SCOPE_NOWHERE  = 0xff
-	RT_TABLE_UNSPEC   = 0x0
-	RT_TABLE_COMPAT   = 0xfc
-	RT_TABLE_DEFAULT  = 0xfd
-	RT_TABLE_MAIN     = 0xfe
-	RT_TABLE_LOCAL    = 0xff
-	RT_TABLE_MAX      = 0xffffffff
-	RTA_UNSPEC        = 0x0
-	RTA_DST           = 0x1
-	RTA_SRC           = 0x2
-	RTA_IIF           = 0x3
-	RTA_OIF           = 0x4
-	RTA_GATEWAY       = 0x5
-	RTA_PRIORITY      = 0x6
-	RTA_PREFSRC       = 0x7
-	RTA_METRICS       = 0x8
-	RTA_MULTIPATH     = 0x9
-	RTA_FLOW          = 0xb
-	RTA_CACHEINFO     = 0xc
-	RTA_TABLE         = 0xf
-	RTN_UNSPEC        = 0x0
-	RTN_UNICAST       = 0x1
-	RTN_LOCAL         = 0x2
-	RTN_BROADCAST     = 0x3
-	RTN_ANYCAST       = 0x4
-	RTN_MULTICAST     = 0x5
-	RTN_BLACKHOLE     = 0x6
-	RTN_UNREACHABLE   = 0x7
-	RTN_PROHIBIT      = 0x8
-	RTN_THROW         = 0x9
-	RTN_NAT           = 0xa
-	RTN_XRESOLVE      = 0xb
-	SizeofNlMsghdr    = 0x10
-	SizeofNlMsgerr    = 0x14
-	SizeofRtGenmsg    = 0x1
-	SizeofNlAttr      = 0x4
-	SizeofRtAttr      = 0x4
-	SizeofIfInfomsg   = 0x10
-	SizeofIfAddrmsg   = 0x8
-	SizeofRtMsg       = 0xc
-	SizeofRtNexthop   = 0x8
+	IFA_UNSPEC          = 0x0
+	IFA_ADDRESS         = 0x1
+	IFA_LOCAL           = 0x2
+	IFA_LABEL           = 0x3
+	IFA_BROADCAST       = 0x4
+	IFA_ANYCAST         = 0x5
+	IFA_CACHEINFO       = 0x6
+	IFA_MULTICAST       = 0x7
+	IFLA_UNSPEC         = 0x0
+	IFLA_ADDRESS        = 0x1
+	IFLA_BROADCAST      = 0x2
+	IFLA_IFNAME         = 0x3
+	IFLA_MTU            = 0x4
+	IFLA_LINK           = 0x5
+	IFLA_QDISC          = 0x6
+	IFLA_STATS          = 0x7
+	IFLA_COST           = 0x8
+	IFLA_PRIORITY       = 0x9
+	IFLA_MASTER         = 0xa
+	IFLA_WIRELESS       = 0xb
+	IFLA_PROTINFO       = 0xc
+	IFLA_TXQLEN         = 0xd
+	IFLA_MAP            = 0xe
+	IFLA_WEIGHT         = 0xf
+	IFLA_OPERSTATE      = 0x10
+	IFLA_LINKMODE       = 0x11
+	IFLA_LINKINFO       = 0x12
+	IFLA_NET_NS_PID     = 0x13
+	IFLA_IFALIAS        = 0x14
+	IFLA_MAX            = 0x1d
+	RT_SCOPE_UNIVERSE   = 0x0
+	RT_SCOPE_SITE       = 0xc8
+	RT_SCOPE_LINK       = 0xfd
+	RT_SCOPE_HOST       = 0xfe
+	RT_SCOPE_NOWHERE    = 0xff
+	RT_TABLE_UNSPEC     = 0x0
+	RT_TABLE_COMPAT     = 0xfc
+	RT_TABLE_DEFAULT    = 0xfd
+	RT_TABLE_MAIN       = 0xfe
+	RT_TABLE_LOCAL      = 0xff
+	RT_TABLE_MAX        = 0xffffffff
+	RTA_UNSPEC          = 0x0
+	RTA_DST             = 0x1
+	RTA_SRC             = 0x2
+	RTA_IIF             = 0x3
+	RTA_OIF             = 0x4
+	RTA_GATEWAY         = 0x5
+	RTA_PRIORITY        = 0x6
+	RTA_PREFSRC         = 0x7
+	RTA_METRICS         = 0x8
+	RTA_MULTIPATH       = 0x9
+	RTA_FLOW            = 0xb
+	RTA_CACHEINFO       = 0xc
+	RTA_TABLE           = 0xf
+	RTN_UNSPEC          = 0x0
+	RTN_UNICAST         = 0x1
+	RTN_LOCAL           = 0x2
+	RTN_BROADCAST       = 0x3
+	RTN_ANYCAST         = 0x4
+	RTN_MULTICAST       = 0x5
+	RTN_BLACKHOLE       = 0x6
+	RTN_UNREACHABLE     = 0x7
+	RTN_PROHIBIT        = 0x8
+	RTN_THROW           = 0x9
+	RTN_NAT             = 0xa
+	RTN_XRESOLVE        = 0xb
+	RTNLGRP_NONE        = 0x0
+	RTNLGRP_LINK        = 0x1
+	RTNLGRP_NOTIFY      = 0x2
+	RTNLGRP_NEIGH       = 0x3
+	RTNLGRP_TC          = 0x4
+	RTNLGRP_IPV4_IFADDR = 0x5
+	RTNLGRP_IPV4_MROUTE = 0x6
+	RTNLGRP_IPV4_ROUTE  = 0x7
+	RTNLGRP_IPV4_RULE   = 0x8
+	RTNLGRP_IPV6_IFADDR = 0x9
+	RTNLGRP_IPV6_MROUTE = 0xa
+	RTNLGRP_IPV6_ROUTE  = 0xb
+	RTNLGRP_IPV6_IFINFO = 0xc
+	RTNLGRP_IPV6_PREFIX = 0x12
+	RTNLGRP_IPV6_RULE   = 0x13
+	RTNLGRP_ND_USEROPT  = 0x14
+	SizeofNlMsghdr      = 0x10
+	SizeofNlMsgerr      = 0x14
+	SizeofRtGenmsg      = 0x1
+	SizeofNlAttr        = 0x4
+	SizeofRtAttr        = 0x4
+	SizeofIfInfomsg     = 0x10
+	SizeofIfAddrmsg     = 0x8
+	SizeofRtMsg         = 0xc
+	SizeofRtNexthop     = 0x8
 )
 
 type NlMsghdr struct {
@@ -435,7 +486,7 @@ type InotifyEvent struct {
 	Mask   uint32
 	Cookie uint32
 	Len    uint32
-	Name   [0]byte
+	Name   [0]uint8
 }
 
 const SizeofInotifyEvent = 0x10
@@ -517,6 +568,10 @@ type EpollEvent struct {
 	Pad    int32
 }
 
+const (
+	_AT_FDCWD = -0x64
+)
+
 type Termios struct {
 	Iflag     uint32
 	Oflag     uint32
diff --git a/src/pkg/syscall/ztypes_linux_arm.go b/src/pkg/syscall/ztypes_linux_arm.go
index cd680c3..4a81d34 100644
--- a/src/pkg/syscall/ztypes_linux_arm.go
+++ b/src/pkg/syscall/ztypes_linux_arm.go
@@ -253,6 +253,40 @@ type Ucred struct {
 	Gid uint32
 }
 
+type TCPInfo struct {
+	State          uint8
+	Ca_state       uint8
+	Retransmits    uint8
+	Probes         uint8
+	Backoff        uint8
+	Options        uint8
+	Pad_cgo_0      [2]byte
+	Rto            uint32
+	Ato            uint32
+	Snd_mss        uint32
+	Rcv_mss        uint32
+	Unacked        uint32
+	Sacked         uint32
+	Lost           uint32
+	Retrans        uint32
+	Fackets        uint32
+	Last_data_sent uint32
+	Last_ack_sent  uint32
+	Last_data_recv uint32
+	Last_ack_recv  uint32
+	Pmtu           uint32
+	Rcv_ssthresh   uint32
+	Rtt            uint32
+	Rttvar         uint32
+	Snd_ssthresh   uint32
+	Snd_cwnd       uint32
+	Advmss         uint32
+	Reordering     uint32
+	Rcv_rtt        uint32
+	Rcv_space      uint32
+	Total_retrans  uint32
+}
+
 const (
 	SizeofSockaddrInet4     = 0x10
 	SizeofSockaddrInet6     = 0x1c
@@ -269,84 +303,101 @@ const (
 	SizeofInet4Pktinfo      = 0xc
 	SizeofInet6Pktinfo      = 0x14
 	SizeofUcred             = 0xc
+	SizeofTCPInfo           = 0x68
 )
 
 const (
-	IFA_UNSPEC        = 0x0
-	IFA_ADDRESS       = 0x1
-	IFA_LOCAL         = 0x2
-	IFA_LABEL         = 0x3
-	IFA_BROADCAST     = 0x4
-	IFA_ANYCAST       = 0x5
-	IFA_CACHEINFO     = 0x6
-	IFA_MULTICAST     = 0x7
-	IFLA_UNSPEC       = 0x0
-	IFLA_ADDRESS      = 0x1
-	IFLA_BROADCAST    = 0x2
-	IFLA_IFNAME       = 0x3
-	IFLA_MTU          = 0x4
-	IFLA_LINK         = 0x5
-	IFLA_QDISC        = 0x6
-	IFLA_STATS        = 0x7
-	IFLA_COST         = 0x8
-	IFLA_PRIORITY     = 0x9
-	IFLA_MASTER       = 0xa
-	IFLA_WIRELESS     = 0xb
-	IFLA_PROTINFO     = 0xc
-	IFLA_TXQLEN       = 0xd
-	IFLA_MAP          = 0xe
-	IFLA_WEIGHT       = 0xf
-	IFLA_OPERSTATE    = 0x10
-	IFLA_LINKMODE     = 0x11
-	IFLA_LINKINFO     = 0x12
-	IFLA_NET_NS_PID   = 0x13
-	IFLA_IFALIAS      = 0x14
-	IFLA_MAX          = 0x1c
-	RT_SCOPE_UNIVERSE = 0x0
-	RT_SCOPE_SITE     = 0xc8
-	RT_SCOPE_LINK     = 0xfd
-	RT_SCOPE_HOST     = 0xfe
-	RT_SCOPE_NOWHERE  = 0xff
-	RT_TABLE_UNSPEC   = 0x0
-	RT_TABLE_COMPAT   = 0xfc
-	RT_TABLE_DEFAULT  = 0xfd
-	RT_TABLE_MAIN     = 0xfe
-	RT_TABLE_LOCAL    = 0xff
-	RT_TABLE_MAX      = 0xffffffff
-	RTA_UNSPEC        = 0x0
-	RTA_DST           = 0x1
-	RTA_SRC           = 0x2
-	RTA_IIF           = 0x3
-	RTA_OIF           = 0x4
-	RTA_GATEWAY       = 0x5
-	RTA_PRIORITY      = 0x6
-	RTA_PREFSRC       = 0x7
-	RTA_METRICS       = 0x8
-	RTA_MULTIPATH     = 0x9
-	RTA_FLOW          = 0xb
-	RTA_CACHEINFO     = 0xc
-	RTA_TABLE         = 0xf
-	RTN_UNSPEC        = 0x0
-	RTN_UNICAST       = 0x1
-	RTN_LOCAL         = 0x2
-	RTN_BROADCAST     = 0x3
-	RTN_ANYCAST       = 0x4
-	RTN_MULTICAST     = 0x5
-	RTN_BLACKHOLE     = 0x6
-	RTN_UNREACHABLE   = 0x7
-	RTN_PROHIBIT      = 0x8
-	RTN_THROW         = 0x9
-	RTN_NAT           = 0xa
-	RTN_XRESOLVE      = 0xb
-	SizeofNlMsghdr    = 0x10
-	SizeofNlMsgerr    = 0x14
-	SizeofRtGenmsg    = 0x1
-	SizeofNlAttr      = 0x4
-	SizeofRtAttr      = 0x4
-	SizeofIfInfomsg   = 0x10
-	SizeofIfAddrmsg   = 0x8
-	SizeofRtMsg       = 0xc
-	SizeofRtNexthop   = 0x8
+	IFA_UNSPEC          = 0x0
+	IFA_ADDRESS         = 0x1
+	IFA_LOCAL           = 0x2
+	IFA_LABEL           = 0x3
+	IFA_BROADCAST       = 0x4
+	IFA_ANYCAST         = 0x5
+	IFA_CACHEINFO       = 0x6
+	IFA_MULTICAST       = 0x7
+	IFLA_UNSPEC         = 0x0
+	IFLA_ADDRESS        = 0x1
+	IFLA_BROADCAST      = 0x2
+	IFLA_IFNAME         = 0x3
+	IFLA_MTU            = 0x4
+	IFLA_LINK           = 0x5
+	IFLA_QDISC          = 0x6
+	IFLA_STATS          = 0x7
+	IFLA_COST           = 0x8
+	IFLA_PRIORITY       = 0x9
+	IFLA_MASTER         = 0xa
+	IFLA_WIRELESS       = 0xb
+	IFLA_PROTINFO       = 0xc
+	IFLA_TXQLEN         = 0xd
+	IFLA_MAP            = 0xe
+	IFLA_WEIGHT         = 0xf
+	IFLA_OPERSTATE      = 0x10
+	IFLA_LINKMODE       = 0x11
+	IFLA_LINKINFO       = 0x12
+	IFLA_NET_NS_PID     = 0x13
+	IFLA_IFALIAS        = 0x14
+	IFLA_MAX            = 0x1d
+	RT_SCOPE_UNIVERSE   = 0x0
+	RT_SCOPE_SITE       = 0xc8
+	RT_SCOPE_LINK       = 0xfd
+	RT_SCOPE_HOST       = 0xfe
+	RT_SCOPE_NOWHERE    = 0xff
+	RT_TABLE_UNSPEC     = 0x0
+	RT_TABLE_COMPAT     = 0xfc
+	RT_TABLE_DEFAULT    = 0xfd
+	RT_TABLE_MAIN       = 0xfe
+	RT_TABLE_LOCAL      = 0xff
+	RT_TABLE_MAX        = 0xffffffff
+	RTA_UNSPEC          = 0x0
+	RTA_DST             = 0x1
+	RTA_SRC             = 0x2
+	RTA_IIF             = 0x3
+	RTA_OIF             = 0x4
+	RTA_GATEWAY         = 0x5
+	RTA_PRIORITY        = 0x6
+	RTA_PREFSRC         = 0x7
+	RTA_METRICS         = 0x8
+	RTA_MULTIPATH       = 0x9
+	RTA_FLOW            = 0xb
+	RTA_CACHEINFO       = 0xc
+	RTA_TABLE           = 0xf
+	RTN_UNSPEC          = 0x0
+	RTN_UNICAST         = 0x1
+	RTN_LOCAL           = 0x2
+	RTN_BROADCAST       = 0x3
+	RTN_ANYCAST         = 0x4
+	RTN_MULTICAST       = 0x5
+	RTN_BLACKHOLE       = 0x6
+	RTN_UNREACHABLE     = 0x7
+	RTN_PROHIBIT        = 0x8
+	RTN_THROW           = 0x9
+	RTN_NAT             = 0xa
+	RTN_XRESOLVE        = 0xb
+	RTNLGRP_NONE        = 0x0
+	RTNLGRP_LINK        = 0x1
+	RTNLGRP_NOTIFY      = 0x2
+	RTNLGRP_NEIGH       = 0x3
+	RTNLGRP_TC          = 0x4
+	RTNLGRP_IPV4_IFADDR = 0x5
+	RTNLGRP_IPV4_MROUTE = 0x6
+	RTNLGRP_IPV4_ROUTE  = 0x7
+	RTNLGRP_IPV4_RULE   = 0x8
+	RTNLGRP_IPV6_IFADDR = 0x9
+	RTNLGRP_IPV6_MROUTE = 0xa
+	RTNLGRP_IPV6_ROUTE  = 0xb
+	RTNLGRP_IPV6_IFINFO = 0xc
+	RTNLGRP_IPV6_PREFIX = 0x12
+	RTNLGRP_IPV6_RULE   = 0x13
+	RTNLGRP_ND_USEROPT  = 0x14
+	SizeofNlMsghdr      = 0x10
+	SizeofNlMsgerr      = 0x14
+	SizeofRtGenmsg      = 0x1
+	SizeofNlAttr        = 0x4
+	SizeofRtAttr        = 0x4
+	SizeofIfInfomsg     = 0x10
+	SizeofIfAddrmsg     = 0x8
+	SizeofRtMsg         = 0xc
+	SizeofRtNexthop     = 0x8
 )
 
 type NlMsghdr struct {
@@ -488,6 +539,10 @@ type EpollEvent struct {
 	Pad    int32
 }
 
+const (
+	_AT_FDCWD = -0x64
+)
+
 type Termios struct {
 	Iflag     uint32
 	Oflag     uint32
diff --git a/src/pkg/syscall/ztypes_netbsd_386.go b/src/pkg/syscall/ztypes_netbsd_386.go
index ef9f33a..dd9cf22 100644
--- a/src/pkg/syscall/ztypes_netbsd_386.go
+++ b/src/pkg/syscall/ztypes_netbsd_386.go
@@ -19,12 +19,12 @@ type (
 )
 
 type Timespec struct {
-	Sec  int32
+	Sec  int64
 	Nsec int32
 }
 
 type Timeval struct {
-	Sec  int32
+	Sec  int64
 	Usec int32
 }
 
@@ -54,69 +54,27 @@ type Rlimit struct {
 
 type _Gid_t uint32
 
-const (
-	S_IFMT   = 0xf000
-	S_IFIFO  = 0x1000
-	S_IFCHR  = 0x2000
-	S_IFDIR  = 0x4000
-	S_IFBLK  = 0x6000
-	S_IFREG  = 0x8000
-	S_IFLNK  = 0xa000
-	S_IFSOCK = 0xc000
-	S_ISUID  = 0x800
-	S_ISGID  = 0x400
-	S_ISVTX  = 0x200
-	S_IRUSR  = 0x100
-	S_IWUSR  = 0x80
-	S_IXUSR  = 0x40
-)
-
 type Stat_t struct {
-	Dev            int32
-	Ino            uint32
-	Mode           uint32
-	Nlink          uint32
-	Uid            uint32
-	Gid            uint32
-	Rdev           int32
-	Lspare0        int32
-	Atim           Timespec
-	Mtim           Timespec
-	Ctim           Timespec
-	Size           int64
-	Blocks         int64
-	Blksize        uint32
-	Flags          uint32
-	Gen            uint32
-	Lspare1        int32
-	X__st_birthtim Timespec
-	Qspare         [2]int64
-}
-
-type Statfs_t struct {
-	F_flags       uint32
-	F_bsize       uint32
-	F_iosize      uint32
-	F_blocks      uint64
-	F_bfree       uint64
-	F_bavail      int64
-	F_files       uint64
-	F_ffree       uint64
-	F_favail      int64
-	F_syncwrites  uint64
-	F_syncreads   uint64
-	F_asyncwrites uint64
-	F_asyncreads  uint64
-	F_fsid        Fsid
-	F_namemax     uint32
-	F_owner       uint32
-	F_ctime       uint32
-	F_spare       [3]uint32
-	F_fstypename  [16]int8
-	F_mntonname   [90]int8
-	F_mntfromname [90]int8
-	Mount_info    [160]byte
-}
+	Dev           uint64
+	Mode          uint32
+	Ino           uint64
+	Nlink         uint32
+	Uid           uint32
+	Gid           uint32
+	Rdev          uint64
+	Atimespec     Timespec
+	Mtimespec     Timespec
+	Ctimespec     Timespec
+	Birthtimespec Timespec
+	Size          int64
+	Blocks        int64
+	Blksize       uint32
+	Flags         uint32
+	Gen           uint32
+	Spare         [2]uint32
+}
+
+type Statfs_t [0]byte
 
 type Flock_t struct {
 	Start  int64
@@ -127,15 +85,16 @@ type Flock_t struct {
 }
 
 type Dirent struct {
-	Fileno uint64
-	Reclen uint16
-	Namlen uint16
-	Type   uint8
-	Name   [512]int8
+	Fileno    uint64
+	Reclen    uint16
+	Namlen    uint16
+	Type      uint8
+	Name      [512]int8
+	Pad_cgo_0 [3]byte
 }
 
 type Fsid struct {
-	Val [2]int32
+	X__fsid_val [2]int32
 }
 
 type RawSockaddrInet4 struct {
@@ -169,7 +128,7 @@ type RawSockaddrDatalink struct {
 	Nlen   uint8
 	Alen   uint8
 	Slen   uint8
-	Data   [24]int8
+	Data   [12]int8
 }
 
 type RawSockaddr struct {
@@ -209,7 +168,7 @@ type Msghdr struct {
 	Name       *byte
 	Namelen    uint32
 	Iov        *Iovec
-	Iovlen     uint32
+	Iovlen     int32
 	Control    *byte
 	Controllen uint32
 	Flags      int32
@@ -231,7 +190,7 @@ const (
 	SizeofSockaddrInet6    = 0x1c
 	SizeofSockaddrAny      = 0x6c
 	SizeofSockaddrUnix     = 0x6a
-	SizeofSockaddrDatalink = 0x20
+	SizeofSockaddrDatalink = 0x14
 	SizeofLinger           = 0x8
 	SizeofIPMreq           = 0x8
 	SizeofIPv6Mreq         = 0x14
@@ -248,123 +207,116 @@ const (
 
 type Kevent_t struct {
 	Ident  uint32
-	Filter int16
-	Flags  uint16
+	Filter uint32
+	Flags  uint32
 	Fflags uint32
-	Data   int32
-	Udata  *byte
+	Data   int64
+	Udata  int32
 }
 
 type FdSet struct {
-	Bits [32]int32
+	Bits [8]uint32
 }
 
 const (
-	SizeofIfMsghdr  = 0xe8
-	SizeofIfData    = 0xd0
-	SizeofIfaMsghdr = 0x18
-	SizeofRtMsghdr  = 0x58
-	SizeofRtMetrics = 0x30
+	SizeofIfMsghdr         = 0x98
+	SizeofIfData           = 0x84
+	SizeofIfaMsghdr        = 0x18
+	SizeofIfAnnounceMsghdr = 0x18
+	SizeofRtMsghdr         = 0x78
+	SizeofRtMetrics        = 0x50
 )
 
 type IfMsghdr struct {
-	Msglen  uint16
-	Version uint8
-	Type    uint8
-	Hdrlen  uint16
-	Index   uint16
-	Tableid uint16
-	Pad1    uint8
-	Pad2    uint8
-	Addrs   int32
-	Flags   int32
-	Xflags  int32
-	Data    IfData
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Data      IfData
+	Pad_cgo_1 [4]byte
 }
 
 type IfData struct {
-	Type         uint8
-	Addrlen      uint8
-	Hdrlen       uint8
-	Link_state   uint8
-	Mtu          uint32
-	Metric       uint32
-	Pad          uint32
-	Baudrate     uint64
-	Ipackets     uint64
-	Ierrors      uint64
-	Opackets     uint64
-	Oerrors      uint64
-	Collisions   uint64
-	Ibytes       uint64
-	Obytes       uint64
-	Imcasts      uint64
-	Omcasts      uint64
-	Iqdrops      uint64
-	Noproto      uint64
-	Capabilities uint32
-	Lastchange   Timeval
-	Mclpool      [7]Mclpool
+	Type       uint8
+	Addrlen    uint8
+	Hdrlen     uint8
+	Pad_cgo_0  [1]byte
+	Link_state int32
+	Mtu        uint64
+	Metric     uint64
+	Baudrate   uint64
+	Ipackets   uint64
+	Ierrors    uint64
+	Opackets   uint64
+	Oerrors    uint64
+	Collisions uint64
+	Ibytes     uint64
+	Obytes     uint64
+	Imcasts    uint64
+	Omcasts    uint64
+	Iqdrops    uint64
+	Noproto    uint64
+	Lastchange Timespec
 }
 
 type IfaMsghdr struct {
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Metric    int32
+	Index     uint16
+	Pad_cgo_0 [6]byte
+}
+
+type IfAnnounceMsghdr struct {
 	Msglen  uint16
 	Version uint8
 	Type    uint8
-	Hdrlen  uint16
 	Index   uint16
-	Tableid uint16
-	Pad1    uint8
-	Pad2    uint8
-	Addrs   int32
-	Flags   int32
-	Metric  int32
+	Name    [16]int8
+	What    uint16
 }
 
 type RtMsghdr struct {
-	Msglen   uint16
-	Version  uint8
-	Type     uint8
-	Hdrlen   uint16
-	Index    uint16
-	Tableid  uint16
-	Priority uint8
-	Mpls     uint8
-	Addrs    int32
-	Flags    int32
-	Fmask    int32
-	Pid      int32
-	Seq      int32
-	Errno    int32
-	Inits    uint32
-	Rmx      RtMetrics
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Flags     int32
+	Addrs     int32
+	Pid       int32
+	Seq       int32
+	Errno     int32
+	Use       int32
+	Inits     int32
+	Pad_cgo_1 [4]byte
+	Rmx       RtMetrics
 }
 
 type RtMetrics struct {
-	Pksent   uint64
-	Locks    uint32
-	Mtu      uint32
-	Expire   uint32
-	Refcnt   uint32
-	Hopcount uint32
-	Recvpipe uint32
-	Sendpipe uint32
-	Ssthresh uint32
-	Rtt      uint32
-	Rttvar   uint32
-}
-
-type Mclpool struct {
-	Grown uint32
-	Alive uint16
-	Hwm   uint16
-	Cwm   uint16
-	Lwm   uint16
+	Locks    uint64
+	Mtu      uint64
+	Hopcount uint64
+	Recvpipe uint64
+	Sendpipe uint64
+	Ssthresh uint64
+	Rtt      uint64
+	Rttvar   uint64
+	Expire   int64
+	Pksent   int64
 }
 
+type Mclpool [0]byte
+
 const (
 	SizeofBpfVersion = 0x4
-	SizeofBpfStat    = 0x8
+	SizeofBpfStat    = 0x80
 	SizeofBpfProgram = 0x8
 	SizeofBpfInsn    = 0x8
 	SizeofBpfHdr     = 0x14
@@ -376,8 +328,10 @@ type BpfVersion struct {
 }
 
 type BpfStat struct {
-	Recv uint32
-	Drop uint32
+	Recv    uint64
+	Drop    uint64
+	Capt    uint64
+	Padding [13]uint64
 }
 
 type BpfProgram struct {
@@ -401,6 +355,19 @@ type BpfHdr struct {
 }
 
 type BpfTimeval struct {
-	Sec  uint32
-	Usec uint32
+	Sec  int32
+	Usec int32
+}
+
+type Sysctlnode struct {
+	Flags           uint32
+	Num             int32
+	Name            [32]int8
+	Ver             uint32
+	X__rsvd         uint32
+	Un              [16]byte
+	X_sysctl_size   [8]byte
+	X_sysctl_func   [8]byte
+	X_sysctl_parent [8]byte
+	X_sysctl_desc   [8]byte
 }
diff --git a/src/pkg/syscall/ztypes_netbsd_amd64.go b/src/pkg/syscall/ztypes_netbsd_amd64.go
index 3979d54..89d1ef8 100644
--- a/src/pkg/syscall/ztypes_netbsd_amd64.go
+++ b/src/pkg/syscall/ztypes_netbsd_amd64.go
@@ -19,14 +19,14 @@ type (
 )
 
 type Timespec struct {
-	Sec       int32
-	Pad_cgo_0 [4]byte
-	Nsec      int64
+	Sec  int64
+	Nsec int64
 }
 
 type Timeval struct {
-	Sec  int64
-	Usec int64
+	Sec       int64
+	Usec      int32
+	Pad_cgo_0 [4]byte
 }
 
 type Rusage struct {
@@ -55,71 +55,30 @@ type Rlimit struct {
 
 type _Gid_t uint32
 
-const (
-	S_IFMT   = 0xf000
-	S_IFIFO  = 0x1000
-	S_IFCHR  = 0x2000
-	S_IFDIR  = 0x4000
-	S_IFBLK  = 0x6000
-	S_IFREG  = 0x8000
-	S_IFLNK  = 0xa000
-	S_IFSOCK = 0xc000
-	S_ISUID  = 0x800
-	S_ISGID  = 0x400
-	S_ISVTX  = 0x200
-	S_IRUSR  = 0x100
-	S_IWUSR  = 0x80
-	S_IXUSR  = 0x40
-)
-
 type Stat_t struct {
-	Dev            int32
-	Ino            uint32
-	Mode           uint32
-	Nlink          uint32
-	Uid            uint32
-	Gid            uint32
-	Rdev           int32
-	Lspare0        int32
-	Atim           Timespec
-	Mtim           Timespec
-	Ctim           Timespec
-	Size           int64
-	Blocks         int64
-	Blksize        uint32
-	Flags          uint32
-	Gen            uint32
-	Lspare1        int32
-	X__st_birthtim Timespec
-	Qspare         [2]int64
-}
-
-type Statfs_t struct {
-	F_flags       uint32
-	F_bsize       uint32
-	F_iosize      uint32
+	Dev           uint64
+	Mode          uint32
 	Pad_cgo_0     [4]byte
-	F_blocks      uint64
-	F_bfree       uint64
-	F_bavail      int64
-	F_files       uint64
-	F_ffree       uint64
-	F_favail      int64
-	F_syncwrites  uint64
-	F_syncreads   uint64
-	F_asyncwrites uint64
-	F_asyncreads  uint64
-	F_fsid        Fsid
-	F_namemax     uint32
-	F_owner       uint32
-	F_ctime       uint32
-	F_spare       [3]uint32
-	F_fstypename  [16]int8
-	F_mntonname   [90]int8
-	F_mntfromname [90]int8
+	Ino           uint64
+	Nlink         uint32
+	Uid           uint32
+	Gid           uint32
 	Pad_cgo_1     [4]byte
-	Mount_info    [160]byte
-}
+	Rdev          uint64
+	Atimespec     Timespec
+	Mtimespec     Timespec
+	Ctimespec     Timespec
+	Birthtimespec Timespec
+	Size          int64
+	Blocks        int64
+	Blksize       uint32
+	Flags         uint32
+	Gen           uint32
+	Spare         [2]uint32
+	Pad_cgo_2     [4]byte
+}
+
+type Statfs_t [0]byte
 
 type Flock_t struct {
 	Start  int64
@@ -130,15 +89,16 @@ type Flock_t struct {
 }
 
 type Dirent struct {
-	Fileno uint64
-	Reclen uint16
-	Namlen uint16
-	Type   uint8
-	Name   [512]int8
+	Fileno    uint64
+	Reclen    uint16
+	Namlen    uint16
+	Type      uint8
+	Name      [512]int8
+	Pad_cgo_0 [3]byte
 }
 
 type Fsid struct {
-	Val [2]int32
+	X__fsid_val [2]int32
 }
 
 type RawSockaddrInet4 struct {
@@ -172,7 +132,7 @@ type RawSockaddrDatalink struct {
 	Nlen   uint8
 	Alen   uint8
 	Slen   uint8
-	Data   [24]int8
+	Data   [12]int8
 }
 
 type RawSockaddr struct {
@@ -213,7 +173,7 @@ type Msghdr struct {
 	Namelen    uint32
 	Pad_cgo_0  [4]byte
 	Iov        *Iovec
-	Iovlen     uint32
+	Iovlen     int32
 	Pad_cgo_1  [4]byte
 	Control    *byte
 	Controllen uint32
@@ -236,7 +196,7 @@ const (
 	SizeofSockaddrInet6    = 0x1c
 	SizeofSockaddrAny      = 0x6c
 	SizeofSockaddrUnix     = 0x6a
-	SizeofSockaddrDatalink = 0x20
+	SizeofSockaddrDatalink = 0x14
 	SizeofLinger           = 0x8
 	SizeofIPMreq           = 0x8
 	SizeofIPv6Mreq         = 0x14
@@ -252,49 +212,47 @@ const (
 )
 
 type Kevent_t struct {
-	Ident  uint64
-	Filter int16
-	Flags  uint16
-	Fflags uint32
-	Data   int32
-	Udata  *byte
+	Ident     uint64
+	Filter    uint32
+	Flags     uint32
+	Fflags    uint32
+	Pad_cgo_0 [4]byte
+	Data      int64
+	Udata     int64
 }
 
 type FdSet struct {
-	Bits [32]int32
+	Bits [8]uint32
 }
 
 const (
-	SizeofIfMsghdr  = 0xf0
-	SizeofIfData    = 0xd8
-	SizeofIfaMsghdr = 0x18
-	SizeofRtMsghdr  = 0x58
-	SizeofRtMetrics = 0x30
+	SizeofIfMsghdr         = 0x98
+	SizeofIfData           = 0x88
+	SizeofIfaMsghdr        = 0x18
+	SizeofIfAnnounceMsghdr = 0x18
+	SizeofRtMsghdr         = 0x78
+	SizeofRtMetrics        = 0x50
 )
 
 type IfMsghdr struct {
-	Msglen  uint16
-	Version uint8
-	Type    uint8
-	Hdrlen  uint16
-	Index   uint16
-	Tableid uint16
-	Pad1    uint8
-	Pad2    uint8
-	Addrs   int32
-	Flags   int32
-	Xflags  int32
-	Data    IfData
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Data      IfData
 }
 
 type IfData struct {
 	Type       uint8
 	Addrlen    uint8
 	Hdrlen     uint8
-	Link_state uint8
-	Mtu        uint32
-	Metric     uint32
-	Pad        uint32
+	Pad_cgo_0  [1]byte
+	Link_state int32
+	Mtu        uint64
+	Metric     uint64
 	Baudrate   uint64
 	Ipackets   uint64
 	Ierrors    uint64
@@ -307,72 +265,67 @@ type IfData struct {
 	Omcasts    uint64
 	Iqdrops    uint64
 	Noproto    uint64
-	Lastchange Timeval
-	Mclpool    [7]Mclpool
-	Pad_cgo_0  [4]byte
+	Lastchange Timespec
 }
 
 type IfaMsghdr struct {
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Metric    int32
+	Index     uint16
+	Pad_cgo_0 [6]byte
+}
+
+type IfAnnounceMsghdr struct {
 	Msglen  uint16
 	Version uint8
 	Type    uint8
-	Hdrlen  uint16
 	Index   uint16
-	Tableid uint16
-	Pad1    uint8
-	Pad2    uint8
-	Addrs   int32
-	Flags   int32
-	Metric  int32
+	Name    [16]int8
+	What    uint16
 }
 
 type RtMsghdr struct {
-	Msglen   uint16
-	Version  uint8
-	Type     uint8
-	Hdrlen   uint16
-	Index    uint16
-	Tableid  uint16
-	Priority uint8
-	Mpls     uint8
-	Addrs    int32
-	Flags    int32
-	Fmask    int32
-	Pid      int32
-	Seq      int32
-	Errno    int32
-	Inits    uint32
-	Rmx      RtMetrics
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Flags     int32
+	Addrs     int32
+	Pid       int32
+	Seq       int32
+	Errno     int32
+	Use       int32
+	Inits     int32
+	Pad_cgo_1 [4]byte
+	Rmx       RtMetrics
 }
 
 type RtMetrics struct {
-	Pksent   uint64
-	Locks    uint32
-	Mtu      uint32
-	Expire   uint32
-	Refcnt   uint32
-	Hopcount uint32
-	Recvpipe uint32
-	Sendpipe uint32
-	Ssthresh uint32
-	Rtt      uint32
-	Rttvar   uint32
-}
-
-type Mclpool struct {
-	Grown uint32
-	Alive uint16
-	Hwm   uint16
-	Cwm   uint16
-	Lwm   uint16
+	Locks    uint64
+	Mtu      uint64
+	Hopcount uint64
+	Recvpipe uint64
+	Sendpipe uint64
+	Ssthresh uint64
+	Rtt      uint64
+	Rttvar   uint64
+	Expire   int64
+	Pksent   int64
 }
 
+type Mclpool [0]byte
+
 const (
 	SizeofBpfVersion = 0x4
-	SizeofBpfStat    = 0x8
+	SizeofBpfStat    = 0x80
 	SizeofBpfProgram = 0x10
 	SizeofBpfInsn    = 0x8
-	SizeofBpfHdr     = 0x14
+	SizeofBpfHdr     = 0x20
 )
 
 type BpfVersion struct {
@@ -381,8 +334,10 @@ type BpfVersion struct {
 }
 
 type BpfStat struct {
-	Recv uint32
-	Drop uint32
+	Recv    uint64
+	Drop    uint64
+	Capt    uint64
+	Padding [13]uint64
 }
 
 type BpfProgram struct {
@@ -403,10 +358,23 @@ type BpfHdr struct {
 	Caplen    uint32
 	Datalen   uint32
 	Hdrlen    uint16
-	Pad_cgo_0 [2]byte
+	Pad_cgo_0 [6]byte
 }
 
 type BpfTimeval struct {
-	Sec  uint32
-	Usec uint32
+	Sec  int64
+	Usec int64
+}
+
+type Sysctlnode struct {
+	Flags           uint32
+	Num             int32
+	Name            [32]int8
+	Ver             uint32
+	X__rsvd         uint32
+	Un              [16]byte
+	X_sysctl_size   [8]byte
+	X_sysctl_func   [8]byte
+	X_sysctl_parent [8]byte
+	X_sysctl_desc   [8]byte
 }
diff --git a/src/pkg/syscall/ztypes_netbsd_arm.go b/src/pkg/syscall/ztypes_netbsd_arm.go
new file mode 100644
index 0000000..dd9cf22
--- /dev/null
+++ b/src/pkg/syscall/ztypes_netbsd_arm.go
@@ -0,0 +1,373 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_netbsd.go
+
+package syscall
+
+const (
+	sizeofPtr      = 0x4
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x4
+	sizeofLongLong = 0x8
+)
+
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int32
+	_C_long_long int64
+)
+
+type Timespec struct {
+	Sec  int64
+	Nsec int32
+}
+
+type Timeval struct {
+	Sec  int64
+	Usec int32
+}
+
+type Rusage struct {
+	Utime    Timeval
+	Stime    Timeval
+	Maxrss   int32
+	Ixrss    int32
+	Idrss    int32
+	Isrss    int32
+	Minflt   int32
+	Majflt   int32
+	Nswap    int32
+	Inblock  int32
+	Oublock  int32
+	Msgsnd   int32
+	Msgrcv   int32
+	Nsignals int32
+	Nvcsw    int32
+	Nivcsw   int32
+}
+
+type Rlimit struct {
+	Cur uint64
+	Max uint64
+}
+
+type _Gid_t uint32
+
+type Stat_t struct {
+	Dev           uint64
+	Mode          uint32
+	Ino           uint64
+	Nlink         uint32
+	Uid           uint32
+	Gid           uint32
+	Rdev          uint64
+	Atimespec     Timespec
+	Mtimespec     Timespec
+	Ctimespec     Timespec
+	Birthtimespec Timespec
+	Size          int64
+	Blocks        int64
+	Blksize       uint32
+	Flags         uint32
+	Gen           uint32
+	Spare         [2]uint32
+}
+
+type Statfs_t [0]byte
+
+type Flock_t struct {
+	Start  int64
+	Len    int64
+	Pid    int32
+	Type   int16
+	Whence int16
+}
+
+type Dirent struct {
+	Fileno    uint64
+	Reclen    uint16
+	Namlen    uint16
+	Type      uint8
+	Name      [512]int8
+	Pad_cgo_0 [3]byte
+}
+
+type Fsid struct {
+	X__fsid_val [2]int32
+}
+
+type RawSockaddrInet4 struct {
+	Len    uint8
+	Family uint8
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]int8
+}
+
+type RawSockaddrInet6 struct {
+	Len      uint8
+	Family   uint8
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+	Len    uint8
+	Family uint8
+	Path   [104]int8
+}
+
+type RawSockaddrDatalink struct {
+	Len    uint8
+	Family uint8
+	Index  uint16
+	Type   uint8
+	Nlen   uint8
+	Alen   uint8
+	Slen   uint8
+	Data   [12]int8
+}
+
+type RawSockaddr struct {
+	Len    uint8
+	Family uint8
+	Data   [14]int8
+}
+
+type RawSockaddrAny struct {
+	Addr RawSockaddr
+	Pad  [92]int8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+	Onoff  int32
+	Linger int32
+}
+
+type Iovec struct {
+	Base *byte
+	Len  uint32
+}
+
+type IPMreq struct {
+	Multiaddr [4]byte /* in_addr */
+	Interface [4]byte /* in_addr */
+}
+
+type IPv6Mreq struct {
+	Multiaddr [16]byte /* in6_addr */
+	Interface uint32
+}
+
+type Msghdr struct {
+	Name       *byte
+	Namelen    uint32
+	Iov        *Iovec
+	Iovlen     int32
+	Control    *byte
+	Controllen uint32
+	Flags      int32
+}
+
+type Cmsghdr struct {
+	Len   uint32
+	Level int32
+	Type  int32
+}
+
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
+const (
+	SizeofSockaddrInet4    = 0x10
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x6c
+	SizeofSockaddrUnix     = 0x6a
+	SizeofSockaddrDatalink = 0x14
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x1c
+	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
+)
+
+const (
+	PTRACE_TRACEME = 0x0
+	PTRACE_CONT    = 0x7
+	PTRACE_KILL    = 0x8
+)
+
+type Kevent_t struct {
+	Ident  uint32
+	Filter uint32
+	Flags  uint32
+	Fflags uint32
+	Data   int64
+	Udata  int32
+}
+
+type FdSet struct {
+	Bits [8]uint32
+}
+
+const (
+	SizeofIfMsghdr         = 0x98
+	SizeofIfData           = 0x84
+	SizeofIfaMsghdr        = 0x18
+	SizeofIfAnnounceMsghdr = 0x18
+	SizeofRtMsghdr         = 0x78
+	SizeofRtMetrics        = 0x50
+)
+
+type IfMsghdr struct {
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Data      IfData
+	Pad_cgo_1 [4]byte
+}
+
+type IfData struct {
+	Type       uint8
+	Addrlen    uint8
+	Hdrlen     uint8
+	Pad_cgo_0  [1]byte
+	Link_state int32
+	Mtu        uint64
+	Metric     uint64
+	Baudrate   uint64
+	Ipackets   uint64
+	Ierrors    uint64
+	Opackets   uint64
+	Oerrors    uint64
+	Collisions uint64
+	Ibytes     uint64
+	Obytes     uint64
+	Imcasts    uint64
+	Omcasts    uint64
+	Iqdrops    uint64
+	Noproto    uint64
+	Lastchange Timespec
+}
+
+type IfaMsghdr struct {
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Metric    int32
+	Index     uint16
+	Pad_cgo_0 [6]byte
+}
+
+type IfAnnounceMsghdr struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+	Index   uint16
+	Name    [16]int8
+	What    uint16
+}
+
+type RtMsghdr struct {
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Flags     int32
+	Addrs     int32
+	Pid       int32
+	Seq       int32
+	Errno     int32
+	Use       int32
+	Inits     int32
+	Pad_cgo_1 [4]byte
+	Rmx       RtMetrics
+}
+
+type RtMetrics struct {
+	Locks    uint64
+	Mtu      uint64
+	Hopcount uint64
+	Recvpipe uint64
+	Sendpipe uint64
+	Ssthresh uint64
+	Rtt      uint64
+	Rttvar   uint64
+	Expire   int64
+	Pksent   int64
+}
+
+type Mclpool [0]byte
+
+const (
+	SizeofBpfVersion = 0x4
+	SizeofBpfStat    = 0x80
+	SizeofBpfProgram = 0x8
+	SizeofBpfInsn    = 0x8
+	SizeofBpfHdr     = 0x14
+)
+
+type BpfVersion struct {
+	Major uint16
+	Minor uint16
+}
+
+type BpfStat struct {
+	Recv    uint64
+	Drop    uint64
+	Capt    uint64
+	Padding [13]uint64
+}
+
+type BpfProgram struct {
+	Len   uint32
+	Insns *BpfInsn
+}
+
+type BpfInsn struct {
+	Code uint16
+	Jt   uint8
+	Jf   uint8
+	K    uint32
+}
+
+type BpfHdr struct {
+	Tstamp    BpfTimeval
+	Caplen    uint32
+	Datalen   uint32
+	Hdrlen    uint16
+	Pad_cgo_0 [2]byte
+}
+
+type BpfTimeval struct {
+	Sec  int32
+	Usec int32
+}
+
+type Sysctlnode struct {
+	Flags           uint32
+	Num             int32
+	Name            [32]int8
+	Ver             uint32
+	X__rsvd         uint32
+	Un              [16]byte
+	X_sysctl_size   [8]byte
+	X_sysctl_func   [8]byte
+	X_sysctl_parent [8]byte
+	X_sysctl_desc   [8]byte
+}
diff --git a/src/pkg/syscall/ztypes_openbsd_386.go b/src/pkg/syscall/ztypes_openbsd_386.go
index 6c21e39..528e92c 100644
--- a/src/pkg/syscall/ztypes_openbsd_386.go
+++ b/src/pkg/syscall/ztypes_openbsd_386.go
@@ -260,11 +260,12 @@ type FdSet struct {
 }
 
 const (
-	SizeofIfMsghdr  = 0xe4
-	SizeofIfData    = 0xcc
-	SizeofIfaMsghdr = 0x18
-	SizeofRtMsghdr  = 0x58
-	SizeofRtMetrics = 0x30
+	SizeofIfMsghdr         = 0xe8
+	SizeofIfData           = 0xd0
+	SizeofIfaMsghdr        = 0x18
+	SizeofIfAnnounceMsghdr = 0x1a
+	SizeofRtMsghdr         = 0x58
+	SizeofRtMetrics        = 0x30
 )
 
 type IfMsghdr struct {
@@ -283,27 +284,28 @@ type IfMsghdr struct {
 }
 
 type IfData struct {
-	Type       uint8
-	Addrlen    uint8
-	Hdrlen     uint8
-	Link_state uint8
-	Mtu        uint32
-	Metric     uint32
-	Pad        uint32
-	Baudrate   uint64
-	Ipackets   uint64
-	Ierrors    uint64
-	Opackets   uint64
-	Oerrors    uint64
-	Collisions uint64
-	Ibytes     uint64
-	Obytes     uint64
-	Imcasts    uint64
-	Omcasts    uint64
-	Iqdrops    uint64
-	Noproto    uint64
-	Lastchange Timeval
-	Mclpool    [7]Mclpool
+	Type         uint8
+	Addrlen      uint8
+	Hdrlen       uint8
+	Link_state   uint8
+	Mtu          uint32
+	Metric       uint32
+	Pad          uint32
+	Baudrate     uint64
+	Ipackets     uint64
+	Ierrors      uint64
+	Opackets     uint64
+	Oerrors      uint64
+	Collisions   uint64
+	Ibytes       uint64
+	Obytes       uint64
+	Imcasts      uint64
+	Omcasts      uint64
+	Iqdrops      uint64
+	Noproto      uint64
+	Capabilities uint32
+	Lastchange   Timeval
+	Mclpool      [7]Mclpool
 }
 
 type IfaMsghdr struct {
@@ -320,6 +322,16 @@ type IfaMsghdr struct {
 	Metric  int32
 }
 
+type IfAnnounceMsghdr struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+	Hdrlen  uint16
+	Index   uint16
+	What    uint16
+	Name    [16]int8
+}
+
 type RtMsghdr struct {
 	Msglen   uint16
 	Version  uint8
diff --git a/src/pkg/syscall/ztypes_openbsd_amd64.go b/src/pkg/syscall/ztypes_openbsd_amd64.go
index 4d01578..4b93930 100644
--- a/src/pkg/syscall/ztypes_openbsd_amd64.go
+++ b/src/pkg/syscall/ztypes_openbsd_amd64.go
@@ -265,11 +265,12 @@ type FdSet struct {
 }
 
 const (
-	SizeofIfMsghdr  = 0xf0
-	SizeofIfData    = 0xd8
-	SizeofIfaMsghdr = 0x18
-	SizeofRtMsghdr  = 0x58
-	SizeofRtMetrics = 0x30
+	SizeofIfMsghdr         = 0xf8
+	SizeofIfData           = 0xe0
+	SizeofIfaMsghdr        = 0x18
+	SizeofIfAnnounceMsghdr = 0x1a
+	SizeofRtMsghdr         = 0x58
+	SizeofRtMetrics        = 0x30
 )
 
 type IfMsghdr struct {
@@ -288,28 +289,30 @@ type IfMsghdr struct {
 }
 
 type IfData struct {
-	Type       uint8
-	Addrlen    uint8
-	Hdrlen     uint8
-	Link_state uint8
-	Mtu        uint32
-	Metric     uint32
-	Pad        uint32
-	Baudrate   uint64
-	Ipackets   uint64
-	Ierrors    uint64
-	Opackets   uint64
-	Oerrors    uint64
-	Collisions uint64
-	Ibytes     uint64
-	Obytes     uint64
-	Imcasts    uint64
-	Omcasts    uint64
-	Iqdrops    uint64
-	Noproto    uint64
-	Lastchange Timeval
-	Mclpool    [7]Mclpool
-	Pad_cgo_0  [4]byte
+	Type         uint8
+	Addrlen      uint8
+	Hdrlen       uint8
+	Link_state   uint8
+	Mtu          uint32
+	Metric       uint32
+	Pad          uint32
+	Baudrate     uint64
+	Ipackets     uint64
+	Ierrors      uint64
+	Opackets     uint64
+	Oerrors      uint64
+	Collisions   uint64
+	Ibytes       uint64
+	Obytes       uint64
+	Imcasts      uint64
+	Omcasts      uint64
+	Iqdrops      uint64
+	Noproto      uint64
+	Capabilities uint32
+	Pad_cgo_0    [4]byte
+	Lastchange   Timeval
+	Mclpool      [7]Mclpool
+	Pad_cgo_1    [4]byte
 }
 
 type IfaMsghdr struct {
@@ -326,6 +329,16 @@ type IfaMsghdr struct {
 	Metric  int32
 }
 
+type IfAnnounceMsghdr struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+	Hdrlen  uint16
+	Index   uint16
+	What    uint16
+	Name    [16]int8
+}
+
 type RtMsghdr struct {
 	Msglen   uint16
 	Version  uint8
diff --git a/src/pkg/syscall/ztypes_plan9_386.go b/src/pkg/syscall/ztypes_plan9_amd64.go
similarity index 100%
copy from src/pkg/syscall/ztypes_plan9_386.go
copy to src/pkg/syscall/ztypes_plan9_amd64.go
diff --git a/src/pkg/syscall/ztypes_windows.go b/src/pkg/syscall/ztypes_windows.go
index b2dc12e..a2006f8 100644
--- a/src/pkg/syscall/ztypes_windows.go
+++ b/src/pkg/syscall/ztypes_windows.go
@@ -20,6 +20,7 @@ const (
 	ERROR_ENVVAR_NOT_FOUND    Errno = 203
 	ERROR_OPERATION_ABORTED   Errno = 995
 	ERROR_IO_PENDING          Errno = 997
+	ERROR_NOT_FOUND           Errno = 1168
 )
 
 const (
@@ -146,6 +147,7 @@ const (
 	WAIT_OBJECT_0  = 0x00000000
 	WAIT_FAILED    = 0xFFFFFFFF
 
+	CREATE_NEW_PROCESS_GROUP   = 0x00000200
 	CREATE_UNICODE_ENVIRONMENT = 0x00000400
 
 	PROCESS_QUERY_INFORMATION = 0x00000400
@@ -162,6 +164,9 @@ const (
 	FILE_MAP_WRITE   = 0x02
 	FILE_MAP_READ    = 0x04
 	FILE_MAP_EXECUTE = 0x20
+
+	CTRL_C_EVENT     = 0
+	CTRL_BREAK_EVENT = 1
 )
 
 const (
@@ -372,11 +377,9 @@ func copyFindData(dst *Win32finddata, src *win32finddata1) {
 	dst.Reserved0 = src.Reserved0
 	dst.Reserved1 = src.Reserved1
 
-	// The src is 1 element shorter than dst. Zero that last one.
+	// The src is 1 element bigger than dst, but it must be NUL.
 	copy(dst.FileName[:], src.FileName[:])
-	dst.FileName[len(dst.FileName)-1] = 0
 	copy(dst.AlternateFileName[:], src.AlternateFileName[:])
-	src.AlternateFileName[len(dst.AlternateFileName)-1] = 0
 }
 
 type ByHandleFileInformation struct {
@@ -493,15 +496,22 @@ const (
 	IPPROTO_TCP  = 6
 	IPPROTO_UDP  = 17
 
-	SOL_SOCKET               = 0xffff
-	SO_REUSEADDR             = 4
-	SO_KEEPALIVE             = 8
-	SO_DONTROUTE             = 16
-	SO_BROADCAST             = 32
-	SO_LINGER                = 128
-	SO_RCVBUF                = 0x1002
-	SO_SNDBUF                = 0x1001
-	SO_UPDATE_ACCEPT_CONTEXT = 0x700b
+	SOL_SOCKET                = 0xffff
+	SO_REUSEADDR              = 4
+	SO_KEEPALIVE              = 8
+	SO_DONTROUTE              = 16
+	SO_BROADCAST              = 32
+	SO_LINGER                 = 128
+	SO_RCVBUF                 = 0x1002
+	SO_SNDBUF                 = 0x1001
+	SO_UPDATE_ACCEPT_CONTEXT  = 0x700b
+	SO_UPDATE_CONNECT_CONTEXT = 0x7010
+
+	IOC_OUT                            = 0x40000000
+	IOC_IN                             = 0x80000000
+	IOC_INOUT                          = IOC_IN | IOC_OUT
+	IOC_WS2                            = 0x08000000
+	SIO_GET_EXTENSION_FUNCTION_POINTER = IOC_INOUT | IOC_WS2 | 6
 
 	// cf. http://support.microsoft.com/default.aspx?scid=kb;en-us;257460
 
@@ -921,3 +931,34 @@ const (
 	REG_DWORD = REG_DWORD_LITTLE_ENDIAN
 	REG_QWORD = REG_QWORD_LITTLE_ENDIAN
 )
+
+type AddrinfoW struct {
+	Flags     int32
+	Family    int32
+	Socktype  int32
+	Protocol  int32
+	Addrlen   uintptr
+	Canonname *uint16
+	Addr      uintptr
+	Next      *AddrinfoW
+}
+
+const (
+	AI_PASSIVE     = 1
+	AI_CANONNAME   = 2
+	AI_NUMERICHOST = 4
+)
+
+type GUID struct {
+	Data1 uint32
+	Data2 uint16
+	Data3 uint16
+	Data4 [8]byte
+}
+
+var WSAID_CONNECTEX = GUID{
+	0x25a207b9,
+	0xddf3,
+	0x4660,
+	[8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e},
+}
diff --git a/src/pkg/testing/allocs.go b/src/pkg/testing/allocs.go
new file mode 100644
index 0000000..d142a33
--- /dev/null
+++ b/src/pkg/testing/allocs.go
@@ -0,0 +1,41 @@
+// 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 testing
+
+import (
+	"runtime"
+)
+
+// AllocsPerRun returns the average number of allocations during calls to f.
+//
+// To compute the number of allocations, the function will first be run once as
+// a warm-up.  The average number of allocations over the specified number of
+// runs will then be measured and returned.
+//
+// AllocsPerRun sets GOMAXPROCS to 1 during its measurement and will restore
+// it before returning.
+func AllocsPerRun(runs int, f func()) (avg float64) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
+
+	// Warm up the function
+	f()
+
+	// Measure the starting statistics
+	var memstats runtime.MemStats
+	runtime.ReadMemStats(&memstats)
+	mallocs := 0 - memstats.Mallocs
+
+	// Run the function the specified number of times
+	for i := 0; i < runs; i++ {
+		f()
+	}
+
+	// Read the final statistics
+	runtime.ReadMemStats(&memstats)
+	mallocs += memstats.Mallocs
+
+	// Average the mallocs over the runs (not counting the warm-up)
+	return float64(mallocs) / float64(runs)
+}
diff --git a/src/pkg/testing/benchmark.go b/src/pkg/testing/benchmark.go
index 4129059..25fb2d6 100644
--- a/src/pkg/testing/benchmark.go
+++ b/src/pkg/testing/benchmark.go
@@ -9,11 +9,19 @@ import (
 	"fmt"
 	"os"
 	"runtime"
+	"sync"
 	"time"
 )
 
 var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
-var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
+var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
+var benchmarkMemory = flag.Bool("test.benchmem", false, "print memory allocations for benchmarks")
+
+// Global lock to ensure only one benchmark runs at a time.
+var benchmarkLock sync.Mutex
+
+// Used for every benchmark for measuring memory.
+var memStats runtime.MemStats
 
 // An internal type but exported because it is cross-package; part of the implementation
 // of the "go test" command.
@@ -26,11 +34,18 @@ type InternalBenchmark struct {
 // timing and to specify the number of iterations to run.
 type B struct {
 	common
-	N         int
-	benchmark InternalBenchmark
-	bytes     int64
-	timerOn   bool
-	result    BenchmarkResult
+	N               int
+	benchmark       InternalBenchmark
+	bytes           int64
+	timerOn         bool
+	showAllocResult bool
+	result          BenchmarkResult
+	// The initial states of memStats.Mallocs and memStats.TotalAlloc.
+	startAllocs uint64
+	startBytes  uint64
+	// The net total of this test after being run.
+	netAllocs uint64
+	netBytes  uint64
 }
 
 // StartTimer starts timing a test.  This function is called automatically
@@ -38,6 +53,9 @@ type B struct {
 // a call to StopTimer.
 func (b *B) StartTimer() {
 	if !b.timerOn {
+		runtime.ReadMemStats(&memStats)
+		b.startAllocs = memStats.Mallocs
+		b.startBytes = memStats.TotalAlloc
 		b.start = time.Now()
 		b.timerOn = true
 	}
@@ -49,6 +67,9 @@ func (b *B) StartTimer() {
 func (b *B) StopTimer() {
 	if b.timerOn {
 		b.duration += time.Now().Sub(b.start)
+		runtime.ReadMemStats(&memStats)
+		b.netAllocs += memStats.Mallocs - b.startAllocs
+		b.netBytes += memStats.TotalAlloc - b.startBytes
 		b.timerOn = false
 	}
 }
@@ -57,15 +78,27 @@ func (b *B) StopTimer() {
 // It does not affect whether the timer is running.
 func (b *B) ResetTimer() {
 	if b.timerOn {
+		runtime.ReadMemStats(&memStats)
+		b.startAllocs = memStats.Mallocs
+		b.startBytes = memStats.TotalAlloc
 		b.start = time.Now()
 	}
 	b.duration = 0
+	b.netAllocs = 0
+	b.netBytes = 0
 }
 
 // SetBytes records the number of bytes processed in a single operation.
 // If this is called, the benchmark will report ns/op and MB/s.
 func (b *B) SetBytes(n int64) { b.bytes = n }
 
+// ReportAllocs enables malloc statistics for this benchmark.
+// It is equivalent to setting -test.benchmem, but it only affects the
+// benchmark function that calls ReportAllocs.
+func (b *B) ReportAllocs() {
+	b.showAllocResult = true
+}
+
 func (b *B) nsPerOp() int64 {
 	if b.N <= 0 {
 		return 0
@@ -75,6 +108,8 @@ func (b *B) nsPerOp() int64 {
 
 // runN runs a single benchmark for the specified number of iterations.
 func (b *B) runN(n int) {
+	benchmarkLock.Lock()
+	defer benchmarkLock.Unlock()
 	// Try to get a comparable environment for each run
 	// by clearing garbage from previous runs.
 	runtime.GC()
@@ -151,7 +186,7 @@ func (b *B) launch() {
 
 	b.runN(n)
 	// Run the benchmark for at least the specified amount of time.
-	d := time.Duration(*benchTime * float64(time.Second))
+	d := *benchTime
 	for !b.failed && b.duration < d && n < 1e9 {
 		last := n
 		// Predict iterations/sec.
@@ -168,14 +203,16 @@ func (b *B) launch() {
 		n = roundUp(n)
 		b.runN(n)
 	}
-	b.result = BenchmarkResult{b.N, b.duration, b.bytes}
+	b.result = BenchmarkResult{b.N, b.duration, b.bytes, b.netAllocs, b.netBytes}
 }
 
 // The results of a benchmark run.
 type BenchmarkResult struct {
-	N     int           // The number of iterations.
-	T     time.Duration // The total time taken.
-	Bytes int64         // Bytes processed in one iteration.
+	N         int           // The number of iterations.
+	T         time.Duration // The total time taken.
+	Bytes     int64         // Bytes processed in one iteration.
+	MemAllocs uint64        // The total number of memory allocations.
+	MemBytes  uint64        // The total number of bytes allocated.
 }
 
 func (r BenchmarkResult) NsPerOp() int64 {
@@ -192,6 +229,20 @@ func (r BenchmarkResult) mbPerSec() float64 {
 	return (float64(r.Bytes) * float64(r.N) / 1e6) / r.T.Seconds()
 }
 
+func (r BenchmarkResult) AllocsPerOp() int64 {
+	if r.N <= 0 {
+		return 0
+	}
+	return int64(r.MemAllocs) / int64(r.N)
+}
+
+func (r BenchmarkResult) AllocedBytesPerOp() int64 {
+	if r.N <= 0 {
+		return 0
+	}
+	return int64(r.MemBytes) / int64(r.N)
+}
+
 func (r BenchmarkResult) String() string {
 	mbs := r.mbPerSec()
 	mb := ""
@@ -212,6 +263,11 @@ func (r BenchmarkResult) String() string {
 	return fmt.Sprintf("%8d\t%s%s", r.N, ns, mb)
 }
 
+func (r BenchmarkResult) MemString() string {
+	return fmt.Sprintf("%8d B/op\t%8d allocs/op",
+		r.AllocedBytesPerOp(), r.AllocsPerOp())
+}
+
 // An internal function but exported because it is cross-package; part of the implementation
 // of the "go test" command.
 func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
@@ -249,7 +305,11 @@ func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks [
 				fmt.Printf("--- FAIL: %s\n%s", benchName, b.output)
 				continue
 			}
-			fmt.Printf("%v\n", r)
+			results := r.String()
+			if *benchmarkMemory || b.showAllocResult {
+				results += "\t" + r.MemString()
+			}
+			fmt.Println(results)
 			// Unlike with tests, we ignore the -chatty flag and always print output for
 			// benchmarks since the output generation time will skew the results.
 			if len(b.output) > 0 {
diff --git a/src/pkg/testing/example.go b/src/pkg/testing/example.go
index 671c798..828c2d3 100644
--- a/src/pkg/testing/example.go
+++ b/src/pkg/testing/example.go
@@ -24,8 +24,6 @@ func RunExamples(matchString func(pat, str string) (bool, error), examples []Int
 
 	var eg InternalExample
 
-	stdout, stderr := os.Stdout, os.Stderr
-
 	for _, eg = range examples {
 		matched, err := matchString(*match, eg.Name)
 		if err != nil {
@@ -35,48 +33,68 @@ func RunExamples(matchString func(pat, str string) (bool, error), examples []Int
 		if !matched {
 			continue
 		}
-		if *chatty {
-			fmt.Printf("=== RUN: %s\n", eg.Name)
+		if !runExample(eg) {
+			ok = false
 		}
+	}
+
+	return
+}
+
+func runExample(eg InternalExample) (ok bool) {
+	if *chatty {
+		fmt.Printf("=== RUN: %s\n", eg.Name)
+	}
 
-		// capture stdout and stderr
-		r, w, err := os.Pipe()
+	// Capture stdout.
+	stdout := os.Stdout
+	r, w, err := os.Pipe()
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+	os.Stdout = w
+	outC := make(chan string)
+	go func() {
+		buf := new(bytes.Buffer)
+		_, err := io.Copy(buf, r)
+		r.Close()
 		if err != nil {
-			fmt.Fprintln(os.Stderr, err)
+			fmt.Fprintf(os.Stderr, "testing: copying pipe: %v\n", err)
 			os.Exit(1)
 		}
-		os.Stdout, os.Stderr = w, w
-		outC := make(chan string)
-		go func() {
-			buf := new(bytes.Buffer)
-			_, err := io.Copy(buf, r)
-			if err != nil {
-				fmt.Fprintf(stderr, "testing: copying pipe: %v\n", err)
-				os.Exit(1)
-			}
-			outC <- buf.String()
-		}()
+		outC <- buf.String()
+	}()
+
+	start := time.Now()
+	ok = true
 
-		// run example
-		t0 := time.Now()
-		eg.F()
-		dt := time.Now().Sub(t0)
+	// Clean up in a deferred call so we can recover if the example panics.
+	defer func() {
+		d := time.Now().Sub(start)
 
-		// close pipe, restore stdout/stderr, get output
+		// Close pipe, restore stdout, get output.
 		w.Close()
-		os.Stdout, os.Stderr = stdout, stderr
+		os.Stdout = stdout
 		out := <-outC
 
-		// report any errors
-		tstr := fmt.Sprintf("(%.2f seconds)", dt.Seconds())
-		if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e {
-			fmt.Printf("--- FAIL: %s %s\ngot:\n%s\nwant:\n%s\n",
-				eg.Name, tstr, g, e)
+		var fail string
+		err := recover()
+		if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e && err == nil {
+			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)
 			ok = false
 		} else if *chatty {
-			fmt.Printf("--- PASS: %s %s\n", eg.Name, tstr)
+			fmt.Printf("--- PASS: %s (%v)\n", eg.Name, d)
 		}
-	}
+		if err != nil {
+			panic(err)
+		}
+	}()
 
+	// Run example.
+	eg.F()
 	return
 }
diff --git a/src/pkg/testing/testing.go b/src/pkg/testing/testing.go
index f59ce8e..86cd46c 100644
--- a/src/pkg/testing/testing.go
+++ b/src/pkg/testing/testing.go
@@ -10,10 +10,21 @@
 // [a-z]) and serves to identify the test routine.
 // These TestXxx routines should be declared within the package they are testing.
 //
+// Tests and benchmarks may be skipped if not applicable like this:
+//     func TestTimeConsuming(t *testing.T) {
+//         if testing.Short() {
+//             t.Skip("skipping test in short mode.")
+//         }
+//         ...
+//     }
+//
 // Functions of the form
 //     func BenchmarkXxx(*testing.B)
 // are considered benchmarks, and are executed by the "go test" command when
-// the -test.bench flag is provided.
+// the -test.bench flag is provided. Benchmarks are run sequentially.
+//
+// For a description of the testing flags, see
+// http://golang.org/cmd/go/#Description_of_testing_flags.
 //
 // A sample benchmark function looks like this:
 //     func BenchmarkHello(b *testing.B) {
@@ -22,26 +33,26 @@
 //         }
 //     }
 //
+// The benchmark function must run the target code b.N times.
 // The benchmark package will vary b.N until the benchmark function lasts
 // long enough to be timed reliably.  The output
-//     testing.BenchmarkHello    10000000    282 ns/op
+//     BenchmarkHello    10000000    282 ns/op
 // means that the loop ran 10000000 times at a speed of 282 ns per loop.
 //
 // If a benchmark needs some expensive setup before running, the timer
-// may be stopped:
+// may be reset:
 //     func BenchmarkBigLen(b *testing.B) {
-//         b.StopTimer()
 //         big := NewBig()
-//         b.StartTimer()
+//         b.ResetTimer()
 //         for i := 0; i < b.N; i++ {
 //             big.Len()
 //         }
 //     }
 //
 // The package also runs and verifies example code. Example functions may
-// include a concluding comment that begins with "Output:" and is compared with
-// the standard output of the function when the tests are run, as in these
-// examples of an example:
+// include a concluding line comment that begins with "Output:" and is compared with
+// the standard output of the function when the tests are run. (The comparison
+// ignores leading and trailing space.) These are examples of an example:
 //
 //     func ExampleHello() {
 //             fmt.Println("hello")
@@ -79,6 +90,7 @@
 package testing
 
 import (
+	"bytes"
 	"flag"
 	"fmt"
 	"os"
@@ -86,6 +98,7 @@ import (
 	"runtime/pprof"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 )
 
@@ -98,14 +111,16 @@ var (
 	short = flag.Bool("test.short", false, "run smaller test suite to save time")
 
 	// Report as tests are run; default is silent for success.
-	chatty         = flag.Bool("test.v", false, "verbose: print additional output")
-	match          = flag.String("test.run", "", "regular expression to select tests and examples to run")
-	memProfile     = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
-	memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
-	cpuProfile     = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
-	timeout        = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
-	cpuListStr     = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
-	parallel       = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+	chatty           = flag.Bool("test.v", false, "verbose: print additional output")
+	match            = flag.String("test.run", "", "regular expression to select tests and examples to run")
+	memProfile       = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
+	memProfileRate   = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
+	cpuProfile       = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
+	blockProfile     = flag.String("test.blockprofile", "", "write a goroutine blocking profile to the named file after execution")
+	blockProfileRate = flag.Int("test.blockprofilerate", 1, "if >= 0, calls runtime.SetBlockProfileRate()")
+	timeout          = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
+	cpuListStr       = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+	parallel         = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
 
 	haveExamples bool // are there examples?
 
@@ -115,8 +130,11 @@ var (
 // common holds the elements common between T and B and
 // captures common methods such as Errorf.
 type common struct {
-	output   []byte    // Output generated by test or benchmark.
-	failed   bool      // Test or benchmark has failed.
+	mu      sync.RWMutex // guards output and failed
+	output  []byte       // Output generated by test or benchmark.
+	failed  bool         // Test or benchmark has failed.
+	skipped bool         // Test of benchmark has been skipped.
+
 	start    time.Time // Time test or benchmark started
 	duration time.Duration
 	self     interface{}      // To be sent on signal channel when done.
@@ -128,37 +146,43 @@ func Short() bool {
 	return *short
 }
 
-// decorate inserts the final newline if needed and indentation tabs for formatting.
-// If addFileLine is true, it also prefixes the string with the file and line of the call site.
-func decorate(s string, addFileLine bool) string {
-	if addFileLine {
-		_, file, line, ok := runtime.Caller(3) // decorate + log + public function.
-		if ok {
-			// Truncate file name at last file name separator.
-			if index := strings.LastIndex(file, "/"); index >= 0 {
-				file = file[index+1:]
-			} else if index = strings.LastIndex(file, "\\"); index >= 0 {
-				file = file[index+1:]
-			}
-		} else {
-			file = "???"
-			line = 1
+// Verbose reports whether the -test.v flag is set.
+func Verbose() bool {
+	return *chatty
+}
+
+// decorate prefixes the string with the file and line of the call site
+// and inserts the final newline if needed and indentation tabs for formatting.
+func decorate(s string) string {
+	_, file, line, ok := runtime.Caller(3) // decorate + log + public function.
+	if ok {
+		// Truncate file name at last file name separator.
+		if index := strings.LastIndex(file, "/"); index >= 0 {
+			file = file[index+1:]
+		} else if index = strings.LastIndex(file, "\\"); index >= 0 {
+			file = file[index+1:]
 		}
-		s = fmt.Sprintf("%s:%d: %s", file, line, s)
+	} else {
+		file = "???"
+		line = 1
 	}
-	s = "\t" + s // Every line is indented at least one tab.
-	n := len(s)
-	if n > 0 && s[n-1] != '\n' {
-		s += "\n"
-		n++
+	buf := new(bytes.Buffer)
+	// Every line is indented at least one tab.
+	buf.WriteByte('\t')
+	fmt.Fprintf(buf, "%s:%d: ", file, line)
+	lines := strings.Split(s, "\n")
+	if l := len(lines); l > 1 && lines[l-1] == "" {
+		lines = lines[:l-1]
 	}
-	for i := 0; i < n-1; i++ { // -1 to avoid final newline
-		if s[i] == '\n' {
+	for i, line := range lines {
+		if i > 0 {
 			// Second and subsequent lines are indented an extra tab.
-			return s[0:i+1] + "\t" + decorate(s[i+1:n], false)
+			buf.WriteString("\n\t\t")
 		}
+		buf.WriteString(line)
 	}
-	return s
+	buf.WriteByte('\n')
+	return buf.String()
 }
 
 // T is a type passed to Test functions to manage test state and support formatted test logs.
@@ -170,13 +194,25 @@ type T struct {
 }
 
 // Fail marks the function as having failed but continues execution.
-func (c *common) Fail() { c.failed = true }
+func (c *common) Fail() {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	c.failed = true
+}
 
-// Failed returns whether the function has failed.
-func (c *common) Failed() bool { return c.failed }
+// Failed reports whether the function has failed.
+func (c *common) Failed() bool {
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+	return c.failed
+}
 
 // FailNow marks the function as having failed and stops its execution.
 // Execution will continue at the next test or benchmark.
+// FailNow must be called from the goroutine running the
+// test or benchmark function, not from other goroutines
+// created during the test. Calling FailNow does not stop
+// those other goroutines.
 func (c *common) FailNow() {
 	c.Fail()
 
@@ -204,43 +240,80 @@ func (c *common) FailNow() {
 
 // log generates the output. It's always at the same stack depth.
 func (c *common) log(s string) {
-	c.output = append(c.output, decorate(s, true)...)
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	c.output = append(c.output, decorate(s)...)
 }
 
-// Log formats its arguments using default formatting, analogous to Println(),
+// Log formats its arguments using default formatting, analogous to Println,
 // and records the text in the error log.
 func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
 
-// Logf formats its arguments according to the format, analogous to Printf(),
+// Logf formats its arguments according to the format, analogous to Printf,
 // and records the text in the error log.
 func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
 
-// Error is equivalent to Log() followed by Fail().
+// Error is equivalent to Log followed by Fail.
 func (c *common) Error(args ...interface{}) {
 	c.log(fmt.Sprintln(args...))
 	c.Fail()
 }
 
-// Errorf is equivalent to Logf() followed by Fail().
+// Errorf is equivalent to Logf followed by Fail.
 func (c *common) Errorf(format string, args ...interface{}) {
 	c.log(fmt.Sprintf(format, args...))
 	c.Fail()
 }
 
-// Fatal is equivalent to Log() followed by FailNow().
+// Fatal is equivalent to Log followed by FailNow.
 func (c *common) Fatal(args ...interface{}) {
 	c.log(fmt.Sprintln(args...))
 	c.FailNow()
 }
 
-// Fatalf is equivalent to Logf() followed by FailNow().
+// Fatalf is equivalent to Logf followed by FailNow.
 func (c *common) Fatalf(format string, args ...interface{}) {
 	c.log(fmt.Sprintf(format, args...))
 	c.FailNow()
 }
 
-// Parallel signals that this test is to be run in parallel with (and only with) 
-// other parallel tests in this CPU group.
+// Skip is equivalent to Log followed by SkipNow.
+func (c *common) Skip(args ...interface{}) {
+	c.log(fmt.Sprintln(args...))
+	c.SkipNow()
+}
+
+// Skipf is equivalent to Logf followed by SkipNow.
+func (c *common) Skipf(format string, args ...interface{}) {
+	c.log(fmt.Sprintf(format, args...))
+	c.SkipNow()
+}
+
+// SkipNow marks the test as having been skipped and stops its execution.
+// Execution will continue at the next test or benchmark. See also FailNow.
+// SkipNow must be called from the goroutine running the test, not from
+// other goroutines created during the test. Calling SkipNow does not stop
+// those other goroutines.
+func (c *common) SkipNow() {
+	c.skip()
+	runtime.Goexit()
+}
+
+func (c *common) skip() {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	c.skipped = true
+}
+
+// Skipped reports whether the test was skipped.
+func (c *common) Skipped() bool {
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+	return c.skipped
+}
+
+// Parallel signals that this test is to be run in parallel with (and only with)
+// other parallel tests.
 func (t *T) Parallel() {
 	t.signal <- (*T)(nil) // Release main testing loop
 	<-t.startParallel     // Wait for serial tests to finish
@@ -257,7 +330,7 @@ func tRunner(t *T, test *InternalTest) {
 	t.start = time.Now()
 
 	// When this goroutine is done, either because test.F(t)
-	// returned normally or because a test failure triggered 
+	// returned normally or because a test failure triggered
 	// a call to runtime.Goexit, record the duration and send
 	// a signal saying that the test is done.
 	defer func() {
@@ -297,10 +370,14 @@ func Main(matchString func(pat, str string) (bool, error), tests []InternalTest,
 func (t *T) report() {
 	tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
 	format := "--- %s: %s %s\n%s"
-	if t.failed {
+	if t.Failed() {
 		fmt.Printf(format, "FAIL", t.name, tstr, t.output)
 	} else if *chatty {
-		fmt.Printf(format, "PASS", t.name, tstr, t.output)
+		if t.Skipped() {
+			fmt.Printf(format, "SKIP", t.name, tstr, t.output)
+		} else {
+			fmt.Printf(format, "PASS", t.name, tstr, t.output)
+		}
 	}
 }
 
@@ -356,7 +433,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
 				continue
 			}
 			t.report()
-			ok = ok && !out.failed
+			ok = ok && !out.Failed()
 		}
 
 		running := 0
@@ -369,7 +446,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
 			}
 			t := (<-collector).(*T)
 			t.report()
-			ok = ok && !t.failed
+			ok = ok && !t.Failed()
 			running--
 		}
 	}
@@ -394,7 +471,9 @@ func before() {
 		}
 		// Could save f so after can call f.Close; not worth the effort.
 	}
-
+	if *blockProfile != "" && *blockProfileRate >= 0 {
+		runtime.SetBlockProfileRate(*blockProfileRate)
+	}
 }
 
 // after runs after all testing.
@@ -413,6 +492,17 @@ func after() {
 		}
 		f.Close()
 	}
+	if *blockProfile != "" && *blockProfileRate >= 0 {
+		f, err := os.Create(*blockProfile)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: %s", err)
+			return
+		}
+		if err = pprof.Lookup("block").WriteTo(f, 0); err != nil {
+			fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *blockProfile, err)
+		}
+		f.Close()
+	}
 }
 
 var timer *time.Timer
diff --git a/src/pkg/text/scanner/scanner.go b/src/pkg/text/scanner/scanner.go
index 565650e..e0d86e3 100644
--- a/src/pkg/text/scanner/scanner.go
+++ b/src/pkg/text/scanner/scanner.go
@@ -5,7 +5,8 @@
 // Package scanner provides a scanner and tokenizer for UTF-8-encoded text.
 // It takes an io.Reader providing the source, which then can be tokenized
 // through repeated calls to the Scan function.  For compatibility with
-// existing tools, the NUL character is not allowed.
+// existing tools, the NUL character is not allowed. If the first character
+// in the source is a UTF-8 encoded byte order mark (BOM), it is discarded.
 //
 // By default, a Scanner skips white space and Go comments and recognizes all
 // literals as defined by the Go language specification.  It may be
@@ -208,11 +209,6 @@ func (s *Scanner) Init(src io.Reader) *Scanner {
 	return s
 }
 
-// TODO(gri): The code for next() and the internal scanner state could benefit
-//            from a rethink. While next() is optimized for the common ASCII
-//            case, the "corrections" needed for proper position tracking undo
-//            some of the attempts for fast-path optimization.
-
 // next reads and returns the next Unicode character. It is designed such
 // that only a minimal amount of work needs to be done in the common ASCII
 // case (one test to check for both ASCII and end-of-buffer, and one test
@@ -316,7 +312,11 @@ func (s *Scanner) Next() rune {
 // character of the source.
 func (s *Scanner) Peek() rune {
 	if s.ch < 0 {
+		// this code is only run for the very first character
 		s.ch = s.next()
+		if s.ch == '\uFEFF' {
+			s.ch = s.next() // ignore BOM
+		}
 	}
 	return s.ch
 }
@@ -389,15 +389,20 @@ func (s *Scanner) scanNumber(ch rune) (rune, rune) {
 		if ch == 'x' || ch == 'X' {
 			// hexadecimal int
 			ch = s.next()
+			hasMantissa := false
 			for digitVal(ch) < 16 {
 				ch = s.next()
+				hasMantissa = true
+			}
+			if !hasMantissa {
+				s.error("illegal hexadecimal number")
 			}
 		} else {
 			// octal int or float
-			seenDecimalDigit := false
+			has8or9 := false
 			for isDecimal(ch) {
 				if ch > '7' {
-					seenDecimalDigit = true
+					has8or9 = true
 				}
 				ch = s.next()
 			}
@@ -408,7 +413,7 @@ func (s *Scanner) scanNumber(ch rune) (rune, rune) {
 				return Float, ch
 			}
 			// octal int
-			if seenDecimalDigit {
+			if has8or9 {
 				s.error("illegal octal number")
 			}
 		}
diff --git a/src/pkg/text/scanner/scanner_test.go b/src/pkg/text/scanner/scanner_test.go
index bb3adb5..496eed4 100644
--- a/src/pkg/text/scanner/scanner_test.go
+++ b/src/pkg/text/scanner/scanner_test.go
@@ -358,8 +358,10 @@ func TestScanSelectedMask(t *testing.T) {
 }
 
 func TestScanNext(t *testing.T) {
-	s := new(Scanner).Init(bytes.NewBufferString("if a == bcd /* comment */ {\n\ta += c\n} // line comment ending in eof"))
-	checkTok(t, s, 1, s.Scan(), Ident, "if")
+	const BOM = '\uFEFF'
+	BOMs := string(BOM)
+	s := new(Scanner).Init(bytes.NewBufferString(BOMs + "if a == bcd /* com" + BOMs + "ment */ {\n\ta += c\n}" + BOMs + "// line comment ending in eof"))
+	checkTok(t, s, 1, s.Scan(), Ident, "if") // the first BOM is ignored
 	checkTok(t, s, 1, s.Scan(), Ident, "a")
 	checkTok(t, s, 1, s.Scan(), '=', "=")
 	checkTok(t, s, 0, s.Next(), '=', "")
@@ -372,6 +374,7 @@ func TestScanNext(t *testing.T) {
 	checkTok(t, s, 0, s.Next(), '=', "")
 	checkTok(t, s, 2, s.Scan(), Ident, "c")
 	checkTok(t, s, 3, s.Scan(), '}', "}")
+	checkTok(t, s, 3, s.Scan(), BOM, BOMs)
 	checkTok(t, s, 3, s.Scan(), -1, "")
 	if s.ErrorCount != 0 {
 		t.Errorf("%d errors", s.ErrorCount)
@@ -446,6 +449,9 @@ func TestError(t *testing.T) {
 	testError(t, `"\'"`, "1:3", "illegal char escape", String)
 
 	testError(t, `01238`, "1:6", "illegal octal number", Int)
+	testError(t, `01238123`, "1:9", "illegal octal number", Int)
+	testError(t, `0x`, "1:3", "illegal hexadecimal number", Int)
+	testError(t, `0xg`, "1:3", "illegal hexadecimal number", Int)
 	testError(t, `'aa'`, "1:4", "illegal char literal", Char)
 
 	testError(t, `'`, "1:2", "literal not terminated", Char)
diff --git a/src/pkg/text/tabwriter/tabwriter.go b/src/pkg/text/tabwriter/tabwriter.go
index ce84600..722ac8d 100644
--- a/src/pkg/text/tabwriter/tabwriter.go
+++ b/src/pkg/text/tabwriter/tabwriter.go
@@ -547,7 +547,7 @@ func (b *Writer) Write(buf []byte) (n int, err error) {
 }
 
 // NewWriter allocates and initializes a new tabwriter.Writer.
-// The parameters are the same as for the the Init function.
+// The parameters are the same as for the Init function.
 //
 func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer {
 	return new(Writer).Init(output, minwidth, tabwidth, padding, padchar, flags)
diff --git a/src/pkg/text/template/doc.go b/src/pkg/text/template/doc.go
index aa50ab9..2da339c 100644
--- a/src/pkg/text/template/doc.go
+++ b/src/pkg/text/template/doc.go
@@ -63,16 +63,16 @@ data, defined in detail below.
 		otherwise, T1 is executed.  Dot is unaffected.
 
 	{{range pipeline}} T1 {{end}}
-		The value of the pipeline must be an array, slice, or map. If
-		the value of the pipeline has length zero, nothing is output;
+		The value of the pipeline must be an array, slice, map, or channel.
+		If the value of the pipeline has length zero, nothing is output;
 		otherwise, dot is set to the successive elements of the array,
 		slice, or map and T1 is executed. If the value is a map and the
 		keys are of basic type with a defined order ("comparable"), the
 		elements will be visited in sorted key order.
 
 	{{range pipeline}} T1 {{else}} T0 {{end}}
-		The value of the pipeline must be an array, slice, or map. If
-		the value of the pipeline has length zero, dot is unaffected and
+		The value of the pipeline must be an array, slice, map, or channel.
+		If the value of the pipeline has length zero, dot is unaffected and
 		T0 is executed; otherwise, dot is set to the successive elements
 		of the array, slice, or map and T1 is executed.
 
@@ -100,6 +100,7 @@ An argument is a simple value, denoted by one of the following.
 	- A boolean, string, character, integer, floating-point, imaginary
 	  or complex constant in Go syntax. These behave like Go's untyped
 	  constants, although raw strings may not span newlines.
+	- The keyword nil, representing an untyped Go nil.
 	- The character '.' (period):
 		.
 	  The result is the value of dot.
@@ -147,6 +148,10 @@ An argument is a simple value, denoted by one of the following.
 	  The result is the value of invoking the function, fun(). The return
 	  types and values behave as in methods. Functions and function
 	  names are described below.
+	- A parenthesized instance of one the above, for grouping. The result
+	  may be accessed by a field or map key invocation.
+		print (.F1 arg1) (.F2 arg2)
+		(.StructValuedMethod "arg").Field
 
 Arguments may evaluate to any type; if they are pointers the implementation
 automatically indirects to the base type when required.
@@ -198,7 +203,7 @@ If a "range" action initializes a variable, the variable is set to the
 successive elements of the iteration.  Also, a "range" may declare two
 variables, separated by a comma:
 
-	$index, $element := pipeline
+	range $index, $element := pipeline
 
 in which case $index and $element are set to the successive values of the
 array/slice index or map key and element, respectively.  Note that if there is
@@ -227,6 +232,8 @@ All produce the quoted word "output":
 	{{"output" | printf "%q"}}
 		A function call whose final argument comes from the previous
 		command.
+	{{printf "%q" (print "out" "put")}}
+		A parenthesized argument.
 	{{"put" | printf "%s%s" "out" | printf "%q"}}
 		A more elaborate call.
 	{{"output" | printf "%s" | printf "%q"}}
diff --git a/src/pkg/text/template/example_test.go b/src/pkg/text/template/example_test.go
index ad49514..de1d518 100644
--- a/src/pkg/text/template/example_test.go
+++ b/src/pkg/text/template/example_test.go
@@ -47,25 +47,25 @@ Josie
 
 	// Output:
 	// Dear Aunt Mildred,
-	// 
+	//
 	// It was a pleasure to see you at the wedding.
 	// Thank you for the lovely bone china tea set.
-	// 
+	//
 	// Best wishes,
 	// Josie
-	// 
+	//
 	// Dear Uncle John,
-	// 
+	//
 	// It is a shame you couldn't make it to the wedding.
 	// Thank you for the lovely moleskin pants.
-	// 
+	//
 	// Best wishes,
 	// Josie
-	// 
+	//
 	// Dear Cousin Rodney,
-	// 
+	//
 	// It is a shame you couldn't make it to the wedding.
-	// 
+	//
 	// Best wishes,
 	// Josie
 }
diff --git a/src/pkg/text/template/exec.go b/src/pkg/text/template/exec.go
index aba21ce..b9c03d8 100644
--- a/src/pkg/text/template/exec.go
+++ b/src/pkg/text/template/exec.go
@@ -20,7 +20,7 @@ import (
 type state struct {
 	tmpl *Template
 	wr   io.Writer
-	line int        // line number for errors
+	node parse.Node // current node, for errors
 	vars []variable // push-down stack of variable values.
 }
 
@@ -63,17 +63,32 @@ func (s *state) varValue(name string) reflect.Value {
 
 var zero reflect.Value
 
+// at marks the state to be on node n, for error reporting.
+func (s *state) at(node parse.Node) {
+	s.node = node
+}
+
+// doublePercent returns the string with %'s replaced by %%, if necessary,
+// so it can be used safely inside a Printf format string.
+func doublePercent(str string) string {
+	if strings.Contains(str, "%") {
+		str = strings.Replace(str, "%", "%%", -1)
+	}
+	return str
+}
+
 // errorf formats the error and terminates processing.
 func (s *state) errorf(format string, args ...interface{}) {
-	format = fmt.Sprintf("template: %s:%d: %s", s.tmpl.Name(), s.line, format)
+	name := doublePercent(s.tmpl.Name())
+	if s.node == nil {
+		format = fmt.Sprintf("template: %s: %s", name, format)
+	} else {
+		location, context := s.tmpl.ErrorContext(s.node)
+		format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format)
+	}
 	panic(fmt.Errorf(format, args...))
 }
 
-// error terminates processing.
-func (s *state) error(err error) {
-	s.errorf("%s", err)
-}
-
 // errRecover is the handler that turns panics into returns from the top
 // level of Parse.
 func errRecover(errp *error) {
@@ -108,7 +123,6 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
 	state := &state{
 		tmpl: t,
 		wr:   wr,
-		line: 1,
 		vars: []variable{{"$", value}},
 	}
 	if t.Tree == nil || t.Root == nil {
@@ -120,38 +134,34 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
 
 // Walk functions step through the major pieces of the template structure,
 // generating output as they go.
-func (s *state) walk(dot reflect.Value, n parse.Node) {
-	switch n := n.(type) {
+func (s *state) walk(dot reflect.Value, node parse.Node) {
+	s.at(node)
+	switch node := node.(type) {
 	case *parse.ActionNode:
-		s.line = n.Line
 		// Do not pop variables so they persist until next end.
 		// Also, if the action declares variables, don't print the result.
-		val := s.evalPipeline(dot, n.Pipe)
-		if len(n.Pipe.Decl) == 0 {
-			s.printValue(n, val)
+		val := s.evalPipeline(dot, node.Pipe)
+		if len(node.Pipe.Decl) == 0 {
+			s.printValue(node, val)
 		}
 	case *parse.IfNode:
-		s.line = n.Line
-		s.walkIfOrWith(parse.NodeIf, dot, n.Pipe, n.List, n.ElseList)
+		s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
 	case *parse.ListNode:
-		for _, node := range n.Nodes {
+		for _, node := range node.Nodes {
 			s.walk(dot, node)
 		}
 	case *parse.RangeNode:
-		s.line = n.Line
-		s.walkRange(dot, n)
+		s.walkRange(dot, node)
 	case *parse.TemplateNode:
-		s.line = n.Line
-		s.walkTemplate(dot, n)
+		s.walkTemplate(dot, node)
 	case *parse.TextNode:
-		if _, err := s.wr.Write(n.Text); err != nil {
-			s.error(err)
+		if _, err := s.wr.Write(node.Text); err != nil {
+			s.errorf("%s", err)
 		}
 	case *parse.WithNode:
-		s.line = n.Line
-		s.walkIfOrWith(parse.NodeWith, dot, n.Pipe, n.List, n.ElseList)
+		s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
 	default:
-		s.errorf("unknown node: %s", n)
+		s.errorf("unknown node: %s", node)
 	}
 }
 
@@ -206,6 +216,7 @@ func isTrue(val reflect.Value) (truth, ok bool) {
 }
 
 func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
+	s.at(r)
 	defer s.pop(s.mark())
 	val, _ := indirect(s.evalPipeline(dot, r.Pipe))
 	// mark top of stack before any variables in the body are pushed.
@@ -266,6 +277,7 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
 }
 
 func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
+	s.at(t)
 	tmpl := s.tmpl.tmpl[t.Name]
 	if tmpl == nil {
 		s.errorf("template %q not defined", t.Name)
@@ -291,6 +303,7 @@ func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value ref
 	if pipe == nil {
 		return
 	}
+	s.at(pipe)
 	for _, cmd := range pipe.Cmds {
 		value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
 		// If the object has type interface{}, dig down one level to the thing inside.
@@ -315,18 +328,26 @@ func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final ref
 	switch n := firstWord.(type) {
 	case *parse.FieldNode:
 		return s.evalFieldNode(dot, n, cmd.Args, final)
+	case *parse.ChainNode:
+		return s.evalChainNode(dot, n, cmd.Args, final)
 	case *parse.IdentifierNode:
 		// Must be a function.
-		return s.evalFunction(dot, n.Ident, cmd.Args, final)
+		return s.evalFunction(dot, n, cmd, cmd.Args, final)
+	case *parse.PipeNode:
+		// Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored.
+		return s.evalPipeline(dot, n)
 	case *parse.VariableNode:
 		return s.evalVariableNode(dot, n, cmd.Args, final)
 	}
+	s.at(firstWord)
 	s.notAFunction(cmd.Args, final)
 	switch word := firstWord.(type) {
 	case *parse.BoolNode:
 		return reflect.ValueOf(word.True)
 	case *parse.DotNode:
 		return dot
+	case *parse.NilNode:
+		s.errorf("nil is not a command")
 	case *parse.NumberNode:
 		return s.idealConstant(word)
 	case *parse.StringNode:
@@ -344,6 +365,7 @@ func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
 	// These are ideal constants but we don't know the type
 	// and we have no context.  (If it was a method argument,
 	// we'd know what we need.) The syntax guides us to some extent.
+	s.at(constant)
 	switch {
 	case constant.IsComplex:
 		return reflect.ValueOf(constant.Complex128) // incontrovertible.
@@ -362,43 +384,57 @@ func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
 }
 
 func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value {
-	return s.evalFieldChain(dot, dot, field.Ident, args, final)
+	s.at(field)
+	return s.evalFieldChain(dot, dot, field, field.Ident, args, final)
+}
+
+func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value {
+	s.at(chain)
+	// (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields.
+	pipe := s.evalArg(dot, nil, chain.Node)
+	if len(chain.Field) == 0 {
+		s.errorf("internal error: no fields in evalChainNode")
+	}
+	return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final)
 }
 
-func (s *state) evalVariableNode(dot reflect.Value, v *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalVariableNode(dot reflect.Value, variable *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
 	// $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
-	value := s.varValue(v.Ident[0])
-	if len(v.Ident) == 1 {
+	s.at(variable)
+	value := s.varValue(variable.Ident[0])
+	if len(variable.Ident) == 1 {
 		s.notAFunction(args, final)
 		return value
 	}
-	return s.evalFieldChain(dot, value, v.Ident[1:], args, final)
+	return s.evalFieldChain(dot, value, variable, variable.Ident[1:], args, final)
 }
 
 // evalFieldChain evaluates .X.Y.Z possibly followed by arguments.
 // dot is the environment in which to evaluate arguments, while
 // receiver is the value being walked along the chain.
-func (s *state) evalFieldChain(dot, receiver reflect.Value, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
 	n := len(ident)
 	for i := 0; i < n-1; i++ {
-		receiver = s.evalField(dot, ident[i], nil, zero, receiver)
+		receiver = s.evalField(dot, ident[i], node, nil, zero, receiver)
 	}
 	// Now if it's a method, it gets the arguments.
-	return s.evalField(dot, ident[n-1], args, final, receiver)
+	return s.evalField(dot, ident[n-1], node, args, final, receiver)
 }
 
-func (s *state) evalFunction(dot reflect.Value, name string, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value {
+	s.at(node)
+	name := node.Ident
 	function, ok := findFunction(name, s.tmpl)
 	if !ok {
 		s.errorf("%q is not a defined function", name)
 	}
-	return s.evalCall(dot, function, name, args, final)
+	return s.evalCall(dot, function, cmd, name, args, final)
 }
 
 // evalField evaluates an expression like (.Field) or (.Field arg1 arg2).
 // The 'final' argument represents the return value from the preceding
 // value of the pipeline, if any.
-func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node, final, receiver reflect.Value) reflect.Value {
+func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value {
 	if !receiver.IsValid() {
 		return zero
 	}
@@ -411,26 +447,31 @@ func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node
 		ptr = ptr.Addr()
 	}
 	if method := ptr.MethodByName(fieldName); method.IsValid() {
-		return s.evalCall(dot, method, fieldName, args, final)
+		return s.evalCall(dot, method, node, fieldName, args, final)
 	}
 	hasArgs := len(args) > 1 || final.IsValid()
-	// It's not a method; is it a field of a struct?
+	// It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
 	receiver, isNil := indirect(receiver)
-	if receiver.Kind() == reflect.Struct {
+	if isNil {
+		s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
+	}
+	switch receiver.Kind() {
+	case reflect.Struct:
 		tField, ok := receiver.Type().FieldByName(fieldName)
 		if ok {
 			field := receiver.FieldByIndex(tField.Index)
-			if tField.PkgPath == "" { // field is exported
-				// If it's a function, we must call it.
-				if hasArgs {
-					s.errorf("%s has arguments but cannot be invoked as function", fieldName)
-				}
-				return field
+			if tField.PkgPath != "" { // field is unexported
+				s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
+			}
+			// If it's a function, we must call it.
+			if hasArgs {
+				s.errorf("%s has arguments but cannot be invoked as function", fieldName)
 			}
+			return field
 		}
-	}
-	// If it's a map, attempt to use the field name as a key.
-	if receiver.Kind() == reflect.Map {
+		s.errorf("%s is not a field of struct type %s", fieldName, typ)
+	case reflect.Map:
+		// If it's a map, attempt to use the field name as a key.
 		nameVal := reflect.ValueOf(fieldName)
 		if nameVal.Type().AssignableTo(receiver.Type().Key()) {
 			if hasArgs {
@@ -439,9 +480,6 @@ func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node
 			return receiver.MapIndex(nameVal)
 		}
 	}
-	if isNil {
-		s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
-	}
 	s.errorf("can't evaluate field %s in type %s", fieldName, typ)
 	panic("not reached")
 }
@@ -454,7 +492,7 @@ var (
 // evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
 // it looks just like a function call.  The arg list, if non-nil, includes (in the manner of the shell), arg[0]
 // as the function itself.
-func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node, final reflect.Value) reflect.Value {
+func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value {
 	if args != nil {
 		args = args[1:] // Zeroth arg is function name/node; not passed to function.
 	}
@@ -473,7 +511,8 @@ func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node,
 		s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args))
 	}
 	if !goodFunc(typ) {
-		s.errorf("can't handle multiple results from method/function %q", name)
+		// TODO: This could still be a confusing error; maybe goodFunc should provide info.
+		s.errorf("can't call method/function %q with %d results", name, typ.NumOut())
 	}
 	// Build the arg list.
 	argv := make([]reflect.Value, numIn)
@@ -500,24 +539,31 @@ func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node,
 	result := fun.Call(argv)
 	// If we have an error that is not nil, stop execution and return that error to the caller.
 	if len(result) == 2 && !result[1].IsNil() {
+		s.at(node)
 		s.errorf("error calling %s: %s", name, result[1].Interface().(error))
 	}
 	return result[0]
 }
 
+// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
+func canBeNil(typ reflect.Type) bool {
+	switch typ.Kind() {
+	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+		return true
+	}
+	return false
+}
+
 // validateType guarantees that the value is valid and assignable to the type.
 func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
 	if !value.IsValid() {
-		switch typ.Kind() {
-		case reflect.Interface, reflect.Ptr, reflect.Chan, reflect.Map, reflect.Slice, reflect.Func:
+		if typ == nil || canBeNil(typ) {
 			// An untyped nil interface{}. Accept as a proper nil value.
-			// TODO: Can we delete the other types in this list? Should we?
-			value = reflect.Zero(typ)
-		default:
-			s.errorf("invalid value; expected %s", typ)
+			return reflect.Zero(typ)
 		}
+		s.errorf("invalid value; expected %s", typ)
 	}
-	if !value.Type().AssignableTo(typ) {
+	if typ != nil && !value.Type().AssignableTo(typ) {
 		if value.Kind() == reflect.Interface && !value.IsNil() {
 			value = value.Elem()
 			if value.Type().AssignableTo(typ) {
@@ -542,13 +588,21 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
 }
 
 func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
 	switch arg := n.(type) {
 	case *parse.DotNode:
 		return s.validateType(dot, typ)
+	case *parse.NilNode:
+		if canBeNil(typ) {
+			return reflect.Zero(typ)
+		}
+		s.errorf("cannot assign nil to %s", typ)
 	case *parse.FieldNode:
 		return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ)
 	case *parse.VariableNode:
 		return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
+	case *parse.PipeNode:
+		return s.validateType(s.evalPipeline(dot, arg), typ)
 	}
 	switch typ.Kind() {
 	case reflect.Bool:
@@ -573,6 +627,7 @@ func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) refle
 }
 
 func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
 	if n, ok := n.(*parse.BoolNode); ok {
 		value := reflect.New(typ).Elem()
 		value.SetBool(n.True)
@@ -583,6 +638,7 @@ func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
 }
 
 func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
 	if n, ok := n.(*parse.StringNode); ok {
 		value := reflect.New(typ).Elem()
 		value.SetString(n.Text)
@@ -593,6 +649,7 @@ func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
 }
 
 func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
 	if n, ok := n.(*parse.NumberNode); ok && n.IsInt {
 		value := reflect.New(typ).Elem()
 		value.SetInt(n.Int64)
@@ -603,6 +660,7 @@ func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
 }
 
 func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
 	if n, ok := n.(*parse.NumberNode); ok && n.IsUint {
 		value := reflect.New(typ).Elem()
 		value.SetUint(n.Uint64)
@@ -613,6 +671,7 @@ func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Valu
 }
 
 func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value {
+	s.at(n)
 	if n, ok := n.(*parse.NumberNode); ok && n.IsFloat {
 		value := reflect.New(typ).Elem()
 		value.SetFloat(n.Float64)
@@ -633,6 +692,7 @@ func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value {
 }
 
 func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value {
+	s.at(n)
 	switch n := n.(type) {
 	case *parse.BoolNode:
 		return reflect.ValueOf(n.True)
@@ -641,13 +701,18 @@ func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Valu
 	case *parse.FieldNode:
 		return s.evalFieldNode(dot, n, nil, zero)
 	case *parse.IdentifierNode:
-		return s.evalFunction(dot, n.Ident, nil, zero)
+		return s.evalFunction(dot, n, n, nil, zero)
+	case *parse.NilNode:
+		// NilNode is handled in evalArg, the only place that calls here.
+		s.errorf("evalEmptyInterface: nil (can't happen)")
 	case *parse.NumberNode:
 		return s.idealConstant(n)
 	case *parse.StringNode:
 		return reflect.ValueOf(n.Text)
 	case *parse.VariableNode:
 		return s.evalVariableNode(dot, n, nil, zero)
+	case *parse.PipeNode:
+		return s.evalPipeline(dot, n)
 	}
 	s.errorf("can't handle assignment of %s to empty interface argument", n)
 	panic("not reached")
@@ -671,6 +736,7 @@ func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
 // printValue writes the textual representation of the value to the output of
 // the template.
 func (s *state) printValue(n parse.Node, v reflect.Value) {
+	s.at(n)
 	if v.Kind() == reflect.Ptr {
 		v, _ = indirect(v) // fmt.Fprint handles nil.
 	}
diff --git a/src/pkg/text/template/exec_test.go b/src/pkg/text/template/exec_test.go
index f4ae50f..683e9ac 100644
--- a/src/pkg/text/template/exec_test.go
+++ b/src/pkg/text/template/exec_test.go
@@ -63,8 +63,11 @@ type T struct {
 	BinaryFunc      func(string, string) string
 	VariadicFunc    func(...string) string
 	VariadicFuncInt func(int, ...string) string
+	NilOKFunc       func(*int) bool
 	// Template to test evaluation of templates.
 	Tmpl *Template
+	// Unexported field; cannot be accessed by template.
+	unexported int
 }
 
 type U struct {
@@ -125,6 +128,7 @@ var tVal = &T{
 	BinaryFunc:        func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) },
 	VariadicFunc:      func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
 	VariadicFuncInt:   func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
+	NilOKFunc:         func(s *int) bool { return s == nil },
 	Tmpl:              Must(New("x").Parse("test template")), // "x" is the value of .X
 }
 
@@ -220,6 +224,7 @@ var execTests = []execTest{
 	// Trivial cases.
 	{"empty", "", "", nil, true},
 	{"text", "some text", "some text", nil, true},
+	{"nil action", "{{nil}}", "", nil, false},
 
 	// Ideal constants.
 	{"ideal int", "{{typeOf 3}}", "int", 0, true},
@@ -228,10 +233,12 @@ var execTests = []execTest{
 	{"ideal complex", "{{typeOf 1i}}", "complex128", 0, true},
 	{"ideal int", "{{typeOf " + bigInt + "}}", "int", 0, true},
 	{"ideal too big", "{{typeOf " + bigUint + "}}", "", 0, false},
+	{"ideal nil without type", "{{nil}}", "", 0, false},
 
 	// Fields of structs.
 	{".X", "-{{.X}}-", "-x-", tVal, true},
 	{".U.V", "-{{.U.V}}-", "-v-", tVal, true},
+	{".unexported", "{{.unexported}}", "", tVal, false},
 
 	// Fields on maps.
 	{"map .one", "{{.MSI.one}}", "1", tVal, true},
@@ -292,7 +299,8 @@ var execTests = []execTest{
 	{".Method2(3, .X)", "-{{.Method2 3 .X}}-", "-Method2: 3 x-", tVal, true},
 	{".Method2(.U16, `str`)", "-{{.Method2 .U16 `str`}}-", "-Method2: 16 str-", tVal, true},
 	{".Method2(.U16, $x)", "{{if $x := .X}}-{{.Method2 .U16 $x}}{{end}}-", "-Method2: 16 x-", tVal, true},
-	{".Method3(nil)", "-{{.Method3 .MXI.unset}}-", "-Method3: <nil>-", tVal, true},
+	{".Method3(nil constant)", "-{{.Method3 nil}}-", "-Method3: <nil>-", tVal, true},
+	{".Method3(nil value)", "-{{.Method3 .MXI.unset}}-", "-Method3: <nil>-", tVal, true},
 	{"method on var", "{{if $x := .}}-{{$x.Method2 .U16 $x.X}}{{end}}-", "-Method2: 16 x-", tVal, true},
 	{"method on chained var",
 		"{{range .MSIone}}{{if $.U.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}",
@@ -303,6 +311,8 @@ var execTests = []execTest{
 	{"chained method on variable",
 		"{{with $x := .}}{{with .SI}}{{$.GetU.TrueFalse $.True}}{{end}}{{end}}",
 		"true", tVal, true},
+	{".NilOKFunc not nil", "{{call .NilOKFunc .PI}}", "false", tVal, true},
+	{".NilOKFunc nil", "{{call .NilOKFunc nil}}", "true", tVal, true},
 
 	// Function call builtin.
 	{".BinaryFunc", "{{call .BinaryFunc `1` `2`}}", "[1=2]", tVal, true},
@@ -321,14 +331,25 @@ var execTests = []execTest{
 	{".VariadicFuncBad0", "{{call .VariadicFunc 3}}", "", tVal, false},
 	{".VariadicFuncIntBad0", "{{call .VariadicFuncInt}}", "", tVal, false},
 	{".VariadicFuncIntBad`", "{{call .VariadicFuncInt `x`}}", "", tVal, false},
+	{".VariadicFuncNilBad", "{{call .VariadicFunc nil}}", "", tVal, false},
 
 	// Pipelines.
 	{"pipeline", "-{{.Method0 | .Method2 .U16}}-", "-Method2: 16 M0-", tVal, true},
 	{"pipeline func", "-{{call .VariadicFunc `llo` | call .VariadicFunc `he` }}-", "-<he+<llo>>-", tVal, true},
 
+	// Parenthesized expressions
+	{"parens in pipeline", "{{printf `%d %d %d` (1) (2 | add 3) (add 4 (add 5 6))}}", "1 5 15", tVal, true},
+
+	// Parenthesized expressions with field accesses
+	{"parens: $ in paren", "{{($).X}}", "x", tVal, true},
+	{"parens: $.GetU in paren", "{{($.GetU).V}}", "v", tVal, true},
+	{"parens: $ in paren in pipe", "{{($ | echo).X}}", "x", tVal, true},
+	{"parens: spaces and args", `{{(makemap "up" "down" "left" "right").left}}`, "right", tVal, true},
+
 	// If.
 	{"if true", "{{if true}}TRUE{{end}}", "TRUE", tVal, true},
 	{"if false", "{{if false}}TRUE{{else}}FALSE{{end}}", "FALSE", tVal, true},
+	{"if nil", "{{if nil}}TRUE{{end}}", "", tVal, false},
 	{"if 1", "{{if 1}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
 	{"if 0", "{{if 0}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
 	{"if 1.5", "{{if 1.5}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
@@ -348,7 +369,8 @@ var execTests = []execTest{
 
 	// Print etc.
 	{"print", `{{print "hello, print"}}`, "hello, print", tVal, true},
-	{"print", `{{print 1 2 3}}`, "1 2 3", tVal, true},
+	{"print 123", `{{print 1 2 3}}`, "1 2 3", tVal, true},
+	{"print nil", `{{print nil}}`, "<nil>", tVal, true},
 	{"println", `{{println 1 2 3}}`, "1 2 3\n", tVal, true},
 	{"printf int", `{{printf "%04x" 127}}`, "007f", tVal, true},
 	{"printf float", `{{printf "%g" 3.5}}`, "3.5", tVal, true},
@@ -387,7 +409,8 @@ var execTests = []execTest{
 	{"slice[WRONG]", "{{index .SI `hello`}}", "", tVal, false},
 	{"map[one]", "{{index .MSI `one`}}", "1", tVal, true},
 	{"map[two]", "{{index .MSI `two`}}", "2", tVal, true},
-	{"map[NO]", "{{index .MSI `XXX`}}", "", tVal, true},
+	{"map[NO]", "{{index .MSI `XXX`}}", "0", tVal, true},
+	{"map[nil]", "{{index .MSI nil}}", "0", tVal, true},
 	{"map[WRONG]", "{{index .MSI 10}}", "", tVal, false},
 	{"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true},
 
@@ -474,6 +497,8 @@ var execTests = []execTest{
 	// Pipelined arg was not being type-checked.
 	{"bug8a", "{{3|oneArg}}", "", tVal, false},
 	{"bug8b", "{{4|dddArg 3}}", "", tVal, false},
+	// A bug was introduced that broke map lookups for lower-case names.
+	{"bug9", "{{.cause}}", "neglect", map[string]string{"cause": "neglect"}, true},
 }
 
 func zeroArgs() string {
@@ -508,6 +533,29 @@ func vfunc(V, *V) string {
 	return "vfunc"
 }
 
+func add(args ...int) int {
+	sum := 0
+	for _, x := range args {
+		sum += x
+	}
+	return sum
+}
+
+func echo(arg interface{}) interface{} {
+	return arg
+}
+
+func makemap(arg ...string) map[string]string {
+	if len(arg)%2 != 0 {
+		panic("bad makemap")
+	}
+	m := make(map[string]string)
+	for i := 0; i < len(arg); i += 2 {
+		m[arg[i]] = arg[i+1]
+	}
+	return m
+}
+
 func stringer(s fmt.Stringer) string {
 	return s.String()
 }
@@ -515,8 +563,11 @@ func stringer(s fmt.Stringer) string {
 func testExecute(execTests []execTest, template *Template, t *testing.T) {
 	b := new(bytes.Buffer)
 	funcs := FuncMap{
+		"add":      add,
 		"count":    count,
 		"dddArg":   dddArg,
+		"echo":     echo,
+		"makemap":  makemap,
 		"oneArg":   oneArg,
 		"typeOf":   typeOf,
 		"vfunc":    vfunc,
@@ -624,6 +675,32 @@ func TestExecuteError(t *testing.T) {
 	}
 }
 
+const execErrorText = `line 1
+line 2
+line 3
+{{template "one" .}}
+{{define "one"}}{{template "two" .}}{{end}}
+{{define "two"}}{{template "three" .}}{{end}}
+{{define "three"}}{{index "hi" $}}{{end}}`
+
+// Check that an error from a nested template contains all the relevant information.
+func TestExecError(t *testing.T) {
+	tmpl, err := New("top").Parse(execErrorText)
+	if err != nil {
+		t.Fatal("parse error:", err)
+	}
+	var b bytes.Buffer
+	err = tmpl.Execute(&b, 5) // 5 is out of range indexing "hi"
+	if err == nil {
+		t.Fatal("expected error")
+	}
+	const want = `template: top:7:20: executing "three" at <index "hi" $>: error calling index: index out of range: 5`
+	got := err.Error()
+	if got != want {
+		t.Errorf("expected\n%q\ngot\n%q", want, got)
+	}
+}
+
 func TestJSEscaping(t *testing.T) {
 	testCases := []struct {
 		in, exp string
@@ -734,3 +811,8 @@ func TestTree(t *testing.T) {
 		t.Errorf("expected %q got %q", expect, result)
 	}
 }
+
+func TestExecuteOnNewTemplate(t *testing.T) {
+	// This is issue 3872.
+	_ = New("Name").Templates()
+}
diff --git a/src/pkg/text/template/funcs.go b/src/pkg/text/template/funcs.go
index 8fbf0ef..31549dc 100644
--- a/src/pkg/text/template/funcs.go
+++ b/src/pkg/text/template/funcs.go
@@ -54,7 +54,7 @@ func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
 			panic("value for " + name + " not a function")
 		}
 		if !goodFunc(v.Type()) {
-			panic(fmt.Errorf("can't handle multiple results from method/function %q", name))
+			panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut()))
 		}
 		out[name] = v
 	}
@@ -107,7 +107,7 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
 			return nil, fmt.Errorf("index of nil pointer")
 		}
 		switch v.Kind() {
-		case reflect.Array, reflect.Slice:
+		case reflect.Array, reflect.Slice, reflect.String:
 			var x int64
 			switch index.Kind() {
 			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -122,16 +122,19 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
 			}
 			v = v.Index(int(x))
 		case reflect.Map:
+			if !index.IsValid() {
+				index = reflect.Zero(v.Type().Key())
+			}
 			if !index.Type().AssignableTo(v.Type().Key()) {
 				return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
 			}
 			if x := v.MapIndex(index); x.IsValid() {
 				v = x
 			} else {
-				v = reflect.Zero(v.Type().Key())
+				v = reflect.Zero(v.Type().Elem())
 			}
 		default:
-			return nil, fmt.Errorf("can't index item of type %s", index.Type())
+			return nil, fmt.Errorf("can't index item of type %s", v.Type())
 		}
 	}
 	return v.Interface(), nil
@@ -154,7 +157,7 @@ func length(item interface{}) (int, error) {
 
 // Function invocation
 
-// call returns the result of evaluating the the first argument as a function.
+// call returns the result of evaluating the first argument as a function.
 // The function must return 1 result, or 2 results, the second of which is an error.
 func call(fn interface{}, args ...interface{}) (interface{}, error) {
 	v := reflect.ValueOf(fn)
@@ -187,10 +190,13 @@ func call(fn interface{}, args ...interface{}) (interface{}, error) {
 		} else {
 			argType = dddType
 		}
+		if !value.IsValid() && canBeNil(argType) {
+			value = reflect.Zero(argType)
+		}
 		if !value.Type().AssignableTo(argType) {
 			return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType)
 		}
-		argv[i] = reflect.ValueOf(arg)
+		argv[i] = value
 	}
 	result := v.Call(argv)
 	if len(result) == 2 {
diff --git a/src/pkg/text/template/parse/lex.go b/src/pkg/text/template/parse/lex.go
index 7705c0b..23c0cf0 100644
--- a/src/pkg/text/template/parse/lex.go
+++ b/src/pkg/text/template/parse/lex.go
@@ -13,8 +13,9 @@ import (
 
 // item represents a token or text string returned from the scanner.
 type item struct {
-	typ itemType
-	val string
+	typ itemType // The type of this item.
+	pos Pos      // The starting position, in bytes, of this item in the input string.
+	val string   // The value of this item.
 }
 
 func (i item) String() string {
@@ -42,65 +43,32 @@ const (
 	itemComplex                      // complex constant (1+2i); imaginary is just a number
 	itemColonEquals                  // colon-equals (':=') introducing a declaration
 	itemEOF
-	itemField      // alphanumeric identifier, starting with '.', possibly chained ('.x.y')
-	itemIdentifier // alphanumeric identifier
+	itemField      // alphanumeric identifier starting with '.'
+	itemIdentifier // alphanumeric identifier not starting with '.'
 	itemLeftDelim  // left action delimiter
+	itemLeftParen  // '(' inside action
 	itemNumber     // simple number, including imaginary
 	itemPipe       // pipe symbol
 	itemRawString  // raw quoted string (includes quotes)
 	itemRightDelim // right action delimiter
+	itemRightParen // ')' inside action
+	itemSpace      // run of spaces separating arguments
 	itemString     // quoted string (includes quotes)
 	itemText       // plain text
-	itemVariable   // variable starting with '$', such as '$' or  '$1' or '$hello'.
+	itemVariable   // variable starting with '$', such as '$' or  '$1' or '$hello'
 	// Keywords appear after all the rest.
 	itemKeyword  // used only to delimit the keywords
-	itemDot      // the cursor, spelled '.'.
+	itemDot      // the cursor, spelled '.'
 	itemDefine   // define keyword
 	itemElse     // else keyword
 	itemEnd      // end keyword
 	itemIf       // if keyword
+	itemNil      // the untyped nil constant, easiest to treat as a keyword
 	itemRange    // range keyword
 	itemTemplate // template keyword
 	itemWith     // with keyword
 )
 
-// Make the types prettyprint.
-var itemName = map[itemType]string{
-	itemError:        "error",
-	itemBool:         "bool",
-	itemChar:         "char",
-	itemCharConstant: "charconst",
-	itemComplex:      "complex",
-	itemColonEquals:  ":=",
-	itemEOF:          "EOF",
-	itemField:        "field",
-	itemIdentifier:   "identifier",
-	itemLeftDelim:    "left delim",
-	itemNumber:       "number",
-	itemPipe:         "pipe",
-	itemRawString:    "raw string",
-	itemRightDelim:   "right delim",
-	itemString:       "string",
-	itemVariable:     "variable",
-	// keywords
-	itemDot:      ".",
-	itemDefine:   "define",
-	itemElse:     "else",
-	itemIf:       "if",
-	itemEnd:      "end",
-	itemRange:    "range",
-	itemTemplate: "template",
-	itemWith:     "with",
-}
-
-func (i itemType) String() string {
-	s := itemName[i]
-	if s == "" {
-		return fmt.Sprintf("item%d", int(i))
-	}
-	return s
-}
-
 var key = map[string]itemType{
 	".":        itemDot,
 	"define":   itemDefine,
@@ -108,6 +76,7 @@ var key = map[string]itemType{
 	"end":      itemEnd,
 	"if":       itemIf,
 	"range":    itemRange,
+	"nil":      itemNil,
 	"template": itemTemplate,
 	"with":     itemWith,
 }
@@ -119,24 +88,27 @@ type stateFn func(*lexer) stateFn
 
 // lexer holds the state of the scanner.
 type lexer struct {
-	name       string    // the name of the input; used only for error reports.
-	input      string    // the string being scanned.
-	leftDelim  string    // start of action.
-	rightDelim string    // end of action.
-	state      stateFn   // the next lexing function to enter.
-	pos        int       // current position in the input.
-	start      int       // start position of this item.
-	width      int       // width of last rune read from input.
-	items      chan item // channel of scanned items.
+	name       string    // the name of the input; used only for error reports
+	input      string    // the string being scanned
+	leftDelim  string    // start of action
+	rightDelim string    // end of action
+	state      stateFn   // the next lexing function to enter
+	pos        Pos       // current position in the input
+	start      Pos       // start position of this item
+	width      Pos       // width of last rune read from input
+	lastPos    Pos       // position of most recent item returned by nextItem
+	items      chan item // channel of scanned items
+	parenDepth int       // nesting depth of ( ) exprs
 }
 
 // next returns the next rune in the input.
-func (l *lexer) next() (r rune) {
-	if l.pos >= len(l.input) {
+func (l *lexer) next() rune {
+	if int(l.pos) >= len(l.input) {
 		l.width = 0
 		return eof
 	}
-	r, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
+	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
+	l.width = Pos(w)
 	l.pos += l.width
 	return r
 }
@@ -155,7 +127,7 @@ func (l *lexer) backup() {
 
 // emit passes an item back to the client.
 func (l *lexer) emit(t itemType) {
-	l.items <- item{t, l.input[l.start:l.pos]}
+	l.items <- item{t, l.start, l.input[l.start:l.pos]}
 	l.start = l.pos
 }
 
@@ -180,30 +152,25 @@ func (l *lexer) acceptRun(valid string) {
 	l.backup()
 }
 
-// lineNumber reports which line we're on. Doing it this way
+// lineNumber reports which line we're on, based on the position of
+// the previous item returned by nextItem. Doing it this way
 // means we don't have to worry about peek double counting.
 func (l *lexer) lineNumber() int {
-	return 1 + strings.Count(l.input[:l.pos], "\n")
+	return 1 + strings.Count(l.input[:l.lastPos], "\n")
 }
 
-// error returns an error token and terminates the scan by passing
+// errorf returns an error token and terminates the scan by passing
 // back a nil pointer that will be the next state, terminating l.nextItem.
 func (l *lexer) errorf(format string, args ...interface{}) stateFn {
-	l.items <- item{itemError, fmt.Sprintf(format, args...)}
+	l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
 	return nil
 }
 
 // nextItem returns the next item from the input.
 func (l *lexer) nextItem() item {
-	for {
-		select {
-		case item := <-l.items:
-			return item
-		default:
-			l.state = l.state(l)
-		}
-	}
-	panic("not reached")
+	item := <-l.items
+	l.lastPos = item.pos
+	return item
 }
 
 // lex creates a new scanner for the input string.
@@ -219,12 +186,19 @@ func lex(name, input, left, right string) *lexer {
 		input:      input,
 		leftDelim:  left,
 		rightDelim: right,
-		state:      lexText,
-		items:      make(chan item, 2), // Two items of buffering is sufficient for all state functions
+		items:      make(chan item),
 	}
+	go l.run()
 	return l
 }
 
+// run runs the state machine for the lexer.
+func (l *lexer) run() {
+	for l.state = lexText; l.state != nil; {
+		l.state = l.state(l)
+	}
+}
+
 // state functions
 
 const (
@@ -257,28 +231,30 @@ func lexText(l *lexer) stateFn {
 
 // lexLeftDelim scans the left delimiter, which is known to be present.
 func lexLeftDelim(l *lexer) stateFn {
-	if strings.HasPrefix(l.input[l.pos:], l.leftDelim+leftComment) {
+	l.pos += Pos(len(l.leftDelim))
+	if strings.HasPrefix(l.input[l.pos:], leftComment) {
 		return lexComment
 	}
-	l.pos += len(l.leftDelim)
 	l.emit(itemLeftDelim)
+	l.parenDepth = 0
 	return lexInsideAction
 }
 
 // lexComment scans a comment. The left comment marker is known to be present.
 func lexComment(l *lexer) stateFn {
+	l.pos += Pos(len(leftComment))
 	i := strings.Index(l.input[l.pos:], rightComment+l.rightDelim)
 	if i < 0 {
 		return l.errorf("unclosed comment")
 	}
-	l.pos += i + len(rightComment) + len(l.rightDelim)
+	l.pos += Pos(i + len(rightComment) + len(l.rightDelim))
 	l.ignore()
 	return lexText
 }
 
 // lexRightDelim scans the right delimiter, which is known to be present.
 func lexRightDelim(l *lexer) stateFn {
-	l.pos += len(l.rightDelim)
+	l.pos += Pos(len(l.rightDelim))
 	l.emit(itemRightDelim)
 	return lexText
 }
@@ -286,16 +262,19 @@ func lexRightDelim(l *lexer) stateFn {
 // lexInsideAction scans the elements inside action delimiters.
 func lexInsideAction(l *lexer) stateFn {
 	// Either number, quoted string, or identifier.
-	// Spaces separate and are ignored.
+	// Spaces separate arguments; runs of spaces turn into itemSpace.
 	// Pipe symbols separate and are emitted.
 	if strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
-		return lexRightDelim
+		if l.parenDepth == 0 {
+			return lexRightDelim
+		}
+		return l.errorf("unclosed left paren")
 	}
 	switch r := l.next(); {
-	case r == eof || r == '\n':
+	case r == eof || isEndOfLine(r):
 		return l.errorf("unclosed action")
 	case isSpace(r):
-		l.ignore()
+		return lexSpace
 	case r == ':':
 		if l.next() != '=' {
 			return l.errorf("expected :=")
@@ -308,15 +287,15 @@ func lexInsideAction(l *lexer) stateFn {
 	case r == '`':
 		return lexRawQuote
 	case r == '$':
-		return lexIdentifier
+		return lexVariable
 	case r == '\'':
 		return lexChar
 	case r == '.':
 		// special look-ahead for ".field" so we don't break l.backup().
-		if l.pos < len(l.input) {
+		if l.pos < Pos(len(l.input)) {
 			r := l.input[l.pos]
 			if r < '0' || '9' < r {
-				return lexIdentifier // itemDot comes from the keyword table.
+				return lexField
 			}
 		}
 		fallthrough // '.' can start a number.
@@ -326,6 +305,17 @@ func lexInsideAction(l *lexer) stateFn {
 	case isAlphaNumeric(r):
 		l.backup()
 		return lexIdentifier
+	case r == '(':
+		l.emit(itemLeftParen)
+		l.parenDepth++
+		return lexInsideAction
+	case r == ')':
+		l.emit(itemRightParen)
+		l.parenDepth--
+		if l.parenDepth < 0 {
+			return l.errorf("unexpected right paren %#U", r)
+		}
+		return lexInsideAction
 	case r <= unicode.MaxASCII && unicode.IsPrint(r):
 		l.emit(itemChar)
 		return lexInsideAction
@@ -335,28 +325,34 @@ func lexInsideAction(l *lexer) stateFn {
 	return lexInsideAction
 }
 
-// lexIdentifier scans an alphanumeric or field.
+// lexSpace scans a run of space characters.
+// One space has already been seen.
+func lexSpace(l *lexer) stateFn {
+	for isSpace(l.peek()) {
+		l.next()
+	}
+	l.emit(itemSpace)
+	return lexInsideAction
+}
+
+// lexIdentifier scans an alphanumeric.
 func lexIdentifier(l *lexer) stateFn {
 Loop:
 	for {
 		switch r := l.next(); {
 		case isAlphaNumeric(r):
 			// absorb.
-		case r == '.' && (l.input[l.start] == '.' || l.input[l.start] == '$'):
-			// field chaining; absorb into one token.
 		default:
 			l.backup()
 			word := l.input[l.start:l.pos]
 			if !l.atTerminator() {
-				return l.errorf("unexpected character %+U", r)
+				return l.errorf("bad character %#U", r)
 			}
 			switch {
 			case key[word] > itemKeyword:
 				l.emit(key[word])
 			case word[0] == '.':
 				l.emit(itemField)
-			case word[0] == '$':
-				l.emit(itemVariable)
 			case word == "true", word == "false":
 				l.emit(itemBool)
 			default:
@@ -368,17 +364,59 @@ Loop:
 	return lexInsideAction
 }
 
+// lexField scans a field: .Alphanumeric.
+// The . has been scanned.
+func lexField(l *lexer) stateFn {
+	return lexFieldOrVariable(l, itemField)
+}
+
+// lexVariable scans a Variable: $Alphanumeric.
+// The $ has been scanned.
+func lexVariable(l *lexer) stateFn {
+	if l.atTerminator() { // Nothing interesting follows -> "$".
+		l.emit(itemVariable)
+		return lexInsideAction
+	}
+	return lexFieldOrVariable(l, itemVariable)
+}
+
+// lexVariable scans a field or variable: [.$]Alphanumeric.
+// The . or $ has been scanned.
+func lexFieldOrVariable(l *lexer, typ itemType) stateFn {
+	if l.atTerminator() { // Nothing interesting follows -> "." or "$".
+		if typ == itemVariable {
+			l.emit(itemVariable)
+		} else {
+			l.emit(itemDot)
+		}
+		return lexInsideAction
+	}
+	var r rune
+	for {
+		r = l.next()
+		if !isAlphaNumeric(r) {
+			l.backup()
+			break
+		}
+	}
+	if !l.atTerminator() {
+		return l.errorf("bad character %#U", r)
+	}
+	l.emit(typ)
+	return lexInsideAction
+}
+
 // atTerminator reports whether the input is at valid termination character to
-// appear after an identifier. Mostly to catch cases like "$x+2" not being
-// acceptable without a space, in case we decide one day to implement
-// arithmetic.
+// appear after an identifier. Breaks .X.Y into two pieces. Also catches cases
+// like "$x+2" not being acceptable without a space, in case we decide one
+// day to implement arithmetic.
 func (l *lexer) atTerminator() bool {
 	r := l.peek()
-	if isSpace(r) {
+	if isSpace(r) || isEndOfLine(r) {
 		return true
 	}
 	switch r {
-	case eof, ',', '|', ':':
+	case eof, '.', ',', '|', ':', ')', '(':
 		return true
 	}
 	// Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will
@@ -391,7 +429,7 @@ func (l *lexer) atTerminator() bool {
 }
 
 // lexChar scans a character constant. The initial quote is already
-// scanned.  Syntax checking is done by the parse.
+// scanned. Syntax checking is done by the parser.
 func lexChar(l *lexer) stateFn {
 Loop:
 	for {
@@ -411,7 +449,7 @@ Loop:
 	return lexInsideAction
 }
 
-// lexNumber scans a number: decimal, octal, hex, float, or imaginary.  This
+// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This
 // isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
 // and "089" - but when it's wrong the input is invalid and the parser (via
 // strconv) will notice.
@@ -420,7 +458,7 @@ func lexNumber(l *lexer) stateFn {
 		return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
 	}
 	if sign := l.peek(); sign == '+' || sign == '-' {
-		// Complex: 1+2i.  No spaces, must end in 'i'.
+		// Complex: 1+2i. No spaces, must end in 'i'.
 		if !l.scanNumber() || l.input[l.pos-1] != 'i' {
 			return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
 		}
@@ -494,11 +532,12 @@ Loop:
 
 // isSpace reports whether r is a space character.
 func isSpace(r rune) bool {
-	switch r {
-	case ' ', '\t', '\n', '\r':
-		return true
-	}
-	return false
+	return r == ' ' || r == '\t'
+}
+
+// isEndOfLine reports whether r is an end-of-line character.
+func isEndOfLine(r rune) bool {
+	return r == '\r' || r == '\n'
 }
 
 // isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
diff --git a/src/pkg/text/template/parse/lex_test.go b/src/pkg/text/template/parse/lex_test.go
index 6ee1b47..d2264c9 100644
--- a/src/pkg/text/template/parse/lex_test.go
+++ b/src/pkg/text/template/parse/lex_test.go
@@ -5,10 +5,52 @@
 package parse
 
 import (
-	"reflect"
+	"fmt"
 	"testing"
 )
 
+// Make the types prettyprint.
+var itemName = map[itemType]string{
+	itemError:        "error",
+	itemBool:         "bool",
+	itemChar:         "char",
+	itemCharConstant: "charconst",
+	itemComplex:      "complex",
+	itemColonEquals:  ":=",
+	itemEOF:          "EOF",
+	itemField:        "field",
+	itemIdentifier:   "identifier",
+	itemLeftDelim:    "left delim",
+	itemLeftParen:    "(",
+	itemNumber:       "number",
+	itemPipe:         "pipe",
+	itemRawString:    "raw string",
+	itemRightDelim:   "right delim",
+	itemRightParen:   ")",
+	itemSpace:        "space",
+	itemString:       "string",
+	itemVariable:     "variable",
+
+	// keywords
+	itemDot:      ".",
+	itemDefine:   "define",
+	itemElse:     "else",
+	itemIf:       "if",
+	itemEnd:      "end",
+	itemNil:      "nil",
+	itemRange:    "range",
+	itemTemplate: "template",
+	itemWith:     "with",
+}
+
+func (i itemType) String() string {
+	s := itemName[i]
+	if s == "" {
+		return fmt.Sprintf("item%d", int(i))
+	}
+	return s
+}
+
 type lexTest struct {
 	name  string
 	input string
@@ -16,173 +58,265 @@ type lexTest struct {
 }
 
 var (
-	tEOF      = item{itemEOF, ""}
-	tLeft     = item{itemLeftDelim, "{{"}
-	tRight    = item{itemRightDelim, "}}"}
-	tRange    = item{itemRange, "range"}
-	tPipe     = item{itemPipe, "|"}
-	tFor      = item{itemIdentifier, "for"}
-	tQuote    = item{itemString, `"abc \n\t\" "`}
+	tEOF      = item{itemEOF, 0, ""}
+	tFor      = item{itemIdentifier, 0, "for"}
+	tLeft     = item{itemLeftDelim, 0, "{{"}
+	tLpar     = item{itemLeftParen, 0, "("}
+	tPipe     = item{itemPipe, 0, "|"}
+	tQuote    = item{itemString, 0, `"abc \n\t\" "`}
+	tRange    = item{itemRange, 0, "range"}
+	tRight    = item{itemRightDelim, 0, "}}"}
+	tRpar     = item{itemRightParen, 0, ")"}
+	tSpace    = item{itemSpace, 0, " "}
 	raw       = "`" + `abc\n\t\" ` + "`"
-	tRawQuote = item{itemRawString, raw}
+	tRawQuote = item{itemRawString, 0, raw}
 )
 
 var lexTests = []lexTest{
 	{"empty", "", []item{tEOF}},
-	{"spaces", " \t\n", []item{{itemText, " \t\n"}, tEOF}},
-	{"text", `now is the time`, []item{{itemText, "now is the time"}, tEOF}},
+	{"spaces", " \t\n", []item{{itemText, 0, " \t\n"}, tEOF}},
+	{"text", `now is the time`, []item{{itemText, 0, "now is the time"}, tEOF}},
 	{"text with comment", "hello-{{/* this is a comment */}}-world", []item{
-		{itemText, "hello-"},
-		{itemText, "-world"},
+		{itemText, 0, "hello-"},
+		{itemText, 0, "-world"},
 		tEOF,
 	}},
-	{"punctuation", "{{,@%}}", []item{
+	{"punctuation", "{{,@% }}", []item{
 		tLeft,
-		{itemChar, ","},
-		{itemChar, "@"},
-		{itemChar, "%"},
+		{itemChar, 0, ","},
+		{itemChar, 0, "@"},
+		{itemChar, 0, "%"},
+		tSpace,
+		tRight,
+		tEOF,
+	}},
+	{"parens", "{{((3))}}", []item{
+		tLeft,
+		tLpar,
+		tLpar,
+		{itemNumber, 0, "3"},
+		tRpar,
+		tRpar,
 		tRight,
 		tEOF,
 	}},
 	{"empty action", `{{}}`, []item{tLeft, tRight, tEOF}},
-	{"for", `{{for }}`, []item{tLeft, tFor, tRight, tEOF}},
+	{"for", `{{for}}`, []item{tLeft, tFor, tRight, tEOF}},
 	{"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}},
 	{"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}},
 	{"numbers", "{{1 02 0x14 -7.2i 1e3 +1.2e-4 4.2i 1+2i}}", []item{
 		tLeft,
-		{itemNumber, "1"},
-		{itemNumber, "02"},
-		{itemNumber, "0x14"},
-		{itemNumber, "-7.2i"},
-		{itemNumber, "1e3"},
-		{itemNumber, "+1.2e-4"},
-		{itemNumber, "4.2i"},
-		{itemComplex, "1+2i"},
+		{itemNumber, 0, "1"},
+		tSpace,
+		{itemNumber, 0, "02"},
+		tSpace,
+		{itemNumber, 0, "0x14"},
+		tSpace,
+		{itemNumber, 0, "-7.2i"},
+		tSpace,
+		{itemNumber, 0, "1e3"},
+		tSpace,
+		{itemNumber, 0, "+1.2e-4"},
+		tSpace,
+		{itemNumber, 0, "4.2i"},
+		tSpace,
+		{itemComplex, 0, "1+2i"},
 		tRight,
 		tEOF,
 	}},
 	{"characters", `{{'a' '\n' '\'' '\\' '\u00FF' '\xFF' '本'}}`, []item{
 		tLeft,
-		{itemCharConstant, `'a'`},
-		{itemCharConstant, `'\n'`},
-		{itemCharConstant, `'\''`},
-		{itemCharConstant, `'\\'`},
-		{itemCharConstant, `'\u00FF'`},
-		{itemCharConstant, `'\xFF'`},
-		{itemCharConstant, `'本'`},
+		{itemCharConstant, 0, `'a'`},
+		tSpace,
+		{itemCharConstant, 0, `'\n'`},
+		tSpace,
+		{itemCharConstant, 0, `'\''`},
+		tSpace,
+		{itemCharConstant, 0, `'\\'`},
+		tSpace,
+		{itemCharConstant, 0, `'\u00FF'`},
+		tSpace,
+		{itemCharConstant, 0, `'\xFF'`},
+		tSpace,
+		{itemCharConstant, 0, `'本'`},
 		tRight,
 		tEOF,
 	}},
 	{"bools", "{{true false}}", []item{
 		tLeft,
-		{itemBool, "true"},
-		{itemBool, "false"},
+		{itemBool, 0, "true"},
+		tSpace,
+		{itemBool, 0, "false"},
 		tRight,
 		tEOF,
 	}},
 	{"dot", "{{.}}", []item{
 		tLeft,
-		{itemDot, "."},
+		{itemDot, 0, "."},
 		tRight,
 		tEOF,
 	}},
-	{"dots", "{{.x . .2 .x.y}}", []item{
+	{"nil", "{{nil}}", []item{
 		tLeft,
-		{itemField, ".x"},
-		{itemDot, "."},
-		{itemNumber, ".2"},
-		{itemField, ".x.y"},
+		{itemNil, 0, "nil"},
+		tRight,
+		tEOF,
+	}},
+	{"dots", "{{.x . .2 .x.y.z}}", []item{
+		tLeft,
+		{itemField, 0, ".x"},
+		tSpace,
+		{itemDot, 0, "."},
+		tSpace,
+		{itemNumber, 0, ".2"},
+		tSpace,
+		{itemField, 0, ".x"},
+		{itemField, 0, ".y"},
+		{itemField, 0, ".z"},
 		tRight,
 		tEOF,
 	}},
 	{"keywords", "{{range if else end with}}", []item{
 		tLeft,
-		{itemRange, "range"},
-		{itemIf, "if"},
-		{itemElse, "else"},
-		{itemEnd, "end"},
-		{itemWith, "with"},
+		{itemRange, 0, "range"},
+		tSpace,
+		{itemIf, 0, "if"},
+		tSpace,
+		{itemElse, 0, "else"},
+		tSpace,
+		{itemEnd, 0, "end"},
+		tSpace,
+		{itemWith, 0, "with"},
 		tRight,
 		tEOF,
 	}},
 	{"variables", "{{$c := printf $ $hello $23 $ $var.Field .Method}}", []item{
 		tLeft,
-		{itemVariable, "$c"},
-		{itemColonEquals, ":="},
-		{itemIdentifier, "printf"},
-		{itemVariable, "$"},
-		{itemVariable, "$hello"},
-		{itemVariable, "$23"},
-		{itemVariable, "$"},
-		{itemVariable, "$var.Field"},
-		{itemField, ".Method"},
+		{itemVariable, 0, "$c"},
+		tSpace,
+		{itemColonEquals, 0, ":="},
+		tSpace,
+		{itemIdentifier, 0, "printf"},
+		tSpace,
+		{itemVariable, 0, "$"},
+		tSpace,
+		{itemVariable, 0, "$hello"},
+		tSpace,
+		{itemVariable, 0, "$23"},
+		tSpace,
+		{itemVariable, 0, "$"},
+		tSpace,
+		{itemVariable, 0, "$var"},
+		{itemField, 0, ".Field"},
+		tSpace,
+		{itemField, 0, ".Method"},
+		tRight,
+		tEOF,
+	}},
+	{"variable invocation", "{{$x 23}}", []item{
+		tLeft,
+		{itemVariable, 0, "$x"},
+		tSpace,
+		{itemNumber, 0, "23"},
 		tRight,
 		tEOF,
 	}},
 	{"pipeline", `intro {{echo hi 1.2 |noargs|args 1 "hi"}} outro`, []item{
-		{itemText, "intro "},
+		{itemText, 0, "intro "},
 		tLeft,
-		{itemIdentifier, "echo"},
-		{itemIdentifier, "hi"},
-		{itemNumber, "1.2"},
+		{itemIdentifier, 0, "echo"},
+		tSpace,
+		{itemIdentifier, 0, "hi"},
+		tSpace,
+		{itemNumber, 0, "1.2"},
+		tSpace,
 		tPipe,
-		{itemIdentifier, "noargs"},
+		{itemIdentifier, 0, "noargs"},
 		tPipe,
-		{itemIdentifier, "args"},
-		{itemNumber, "1"},
-		{itemString, `"hi"`},
+		{itemIdentifier, 0, "args"},
+		tSpace,
+		{itemNumber, 0, "1"},
+		tSpace,
+		{itemString, 0, `"hi"`},
 		tRight,
-		{itemText, " outro"},
+		{itemText, 0, " outro"},
 		tEOF,
 	}},
 	{"declaration", "{{$v := 3}}", []item{
 		tLeft,
-		{itemVariable, "$v"},
-		{itemColonEquals, ":="},
-		{itemNumber, "3"},
+		{itemVariable, 0, "$v"},
+		tSpace,
+		{itemColonEquals, 0, ":="},
+		tSpace,
+		{itemNumber, 0, "3"},
 		tRight,
 		tEOF,
 	}},
 	{"2 declarations", "{{$v , $w := 3}}", []item{
 		tLeft,
-		{itemVariable, "$v"},
-		{itemChar, ","},
-		{itemVariable, "$w"},
-		{itemColonEquals, ":="},
-		{itemNumber, "3"},
+		{itemVariable, 0, "$v"},
+		tSpace,
+		{itemChar, 0, ","},
+		tSpace,
+		{itemVariable, 0, "$w"},
+		tSpace,
+		{itemColonEquals, 0, ":="},
+		tSpace,
+		{itemNumber, 0, "3"},
+		tRight,
+		tEOF,
+	}},
+	{"field of parenthesized expression", "{{(.X).Y}}", []item{
+		tLeft,
+		tLpar,
+		{itemField, 0, ".X"},
+		tRpar,
+		{itemField, 0, ".Y"},
 		tRight,
 		tEOF,
 	}},
 	// errors
 	{"badchar", "#{{\x01}}", []item{
-		{itemText, "#"},
+		{itemText, 0, "#"},
 		tLeft,
-		{itemError, "unrecognized character in action: U+0001"},
+		{itemError, 0, "unrecognized character in action: U+0001"},
 	}},
 	{"unclosed action", "{{\n}}", []item{
 		tLeft,
-		{itemError, "unclosed action"},
+		{itemError, 0, "unclosed action"},
 	}},
 	{"EOF in action", "{{range", []item{
 		tLeft,
 		tRange,
-		{itemError, "unclosed action"},
+		{itemError, 0, "unclosed action"},
 	}},
 	{"unclosed quote", "{{\"\n\"}}", []item{
 		tLeft,
-		{itemError, "unterminated quoted string"},
+		{itemError, 0, "unterminated quoted string"},
 	}},
 	{"unclosed raw quote", "{{`xx\n`}}", []item{
 		tLeft,
-		{itemError, "unterminated raw quoted string"},
+		{itemError, 0, "unterminated raw quoted string"},
 	}},
 	{"unclosed char constant", "{{'\n}}", []item{
 		tLeft,
-		{itemError, "unterminated character constant"},
+		{itemError, 0, "unterminated character constant"},
 	}},
 	{"bad number", "{{3k}}", []item{
 		tLeft,
-		{itemError, `bad number syntax: "3k"`},
+		{itemError, 0, `bad number syntax: "3k"`},
+	}},
+	{"unclosed paren", "{{(3}}", []item{
+		tLeft,
+		tLpar,
+		{itemNumber, 0, "3"},
+		{itemError, 0, `unclosed left paren`},
+	}},
+	{"extra right paren", "{{3)}}", []item{
+		tLeft,
+		{itemNumber, 0, "3"},
+		tRpar,
+		{itemError, 0, `unexpected right paren U+0029 ')'`},
 	}},
 
 	// Fixed bugs
@@ -198,6 +332,10 @@ var lexTests = []lexTest{
 		tRight,
 		tEOF,
 	}},
+	{"text with bad comment", "hello-{{/*/}}-world", []item{
+		{itemText, 0, "hello-"},
+		{itemError, 0, `unclosed comment`},
+	}},
 }
 
 // collect gathers the emitted items into a slice.
@@ -213,11 +351,29 @@ func collect(t *lexTest, left, right string) (items []item) {
 	return
 }
 
+func equal(i1, i2 []item, checkPos bool) bool {
+	if len(i1) != len(i2) {
+		return false
+	}
+	for k := range i1 {
+		if i1[k].typ != i2[k].typ {
+			return false
+		}
+		if i1[k].val != i2[k].val {
+			return false
+		}
+		if checkPos && i1[k].pos != i2[k].pos {
+			return false
+		}
+	}
+	return true
+}
+
 func TestLex(t *testing.T) {
 	for _, test := range lexTests {
 		items := collect(&test, "", "")
-		if !reflect.DeepEqual(items, test.items) {
-			t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+		if !equal(items, test.items, false) {
+			t.Errorf("%s: got\n\t%+v\nexpected\n\t%v", test.name, items, test.items)
 		}
 	}
 }
@@ -226,32 +382,74 @@ func TestLex(t *testing.T) {
 var lexDelimTests = []lexTest{
 	{"punctuation", "$$,@%{{}}@@", []item{
 		tLeftDelim,
-		{itemChar, ","},
-		{itemChar, "@"},
-		{itemChar, "%"},
-		{itemChar, "{"},
-		{itemChar, "{"},
-		{itemChar, "}"},
-		{itemChar, "}"},
+		{itemChar, 0, ","},
+		{itemChar, 0, "@"},
+		{itemChar, 0, "%"},
+		{itemChar, 0, "{"},
+		{itemChar, 0, "{"},
+		{itemChar, 0, "}"},
+		{itemChar, 0, "}"},
 		tRightDelim,
 		tEOF,
 	}},
 	{"empty action", `$$@@`, []item{tLeftDelim, tRightDelim, tEOF}},
-	{"for", `$$for @@`, []item{tLeftDelim, tFor, tRightDelim, tEOF}},
+	{"for", `$$for@@`, []item{tLeftDelim, tFor, tRightDelim, tEOF}},
 	{"quote", `$$"abc \n\t\" "@@`, []item{tLeftDelim, tQuote, tRightDelim, tEOF}},
 	{"raw quote", "$$" + raw + "@@", []item{tLeftDelim, tRawQuote, tRightDelim, tEOF}},
 }
 
 var (
-	tLeftDelim  = item{itemLeftDelim, "$$"}
-	tRightDelim = item{itemRightDelim, "@@"}
+	tLeftDelim  = item{itemLeftDelim, 0, "$$"}
+	tRightDelim = item{itemRightDelim, 0, "@@"}
 )
 
 func TestDelims(t *testing.T) {
 	for _, test := range lexDelimTests {
 		items := collect(&test, "$$", "@@")
-		if !reflect.DeepEqual(items, test.items) {
+		if !equal(items, test.items, false) {
+			t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+		}
+	}
+}
+
+var lexPosTests = []lexTest{
+	{"empty", "", []item{tEOF}},
+	{"punctuation", "{{,@%#}}", []item{
+		{itemLeftDelim, 0, "{{"},
+		{itemChar, 2, ","},
+		{itemChar, 3, "@"},
+		{itemChar, 4, "%"},
+		{itemChar, 5, "#"},
+		{itemRightDelim, 6, "}}"},
+		{itemEOF, 8, ""},
+	}},
+	{"sample", "0123{{hello}}xyz", []item{
+		{itemText, 0, "0123"},
+		{itemLeftDelim, 4, "{{"},
+		{itemIdentifier, 6, "hello"},
+		{itemRightDelim, 11, "}}"},
+		{itemText, 13, "xyz"},
+		{itemEOF, 16, ""},
+	}},
+}
+
+// The other tests don't check position, to make the test cases easier to construct.
+// This one does.
+func TestPos(t *testing.T) {
+	for _, test := range lexPosTests {
+		items := collect(&test, "", "")
+		if !equal(items, test.items, true) {
 			t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+			if len(items) == len(test.items) {
+				// Detailed print; avoid item.String() to expose the position value.
+				for i := range items {
+					if !equal(items[i:i+1], test.items[i:i+1], true) {
+						i1 := items[i]
+						i2 := test.items[i]
+						t.Errorf("\t#%d: got {%v %d %q} expected  {%v %d %q}", i, i1.typ, i1.pos, i1.val, i2.typ, i2.pos, i2.val)
+					}
+				}
+			}
 		}
 	}
 }
diff --git a/src/pkg/text/template/parse/node.go b/src/pkg/text/template/parse/node.go
index db64562..9d0d09e 100644
--- a/src/pkg/text/template/parse/node.go
+++ b/src/pkg/text/template/parse/node.go
@@ -13,7 +13,9 @@ import (
 	"strings"
 )
 
-// A node is an element in the parse tree. The interface is trivial.
+// A Node is an element in the parse tree. The interface is trivial.
+// The interface contains an unexported method so that only
+// types local to this package can satisfy it.
 type Node interface {
 	Type() NodeType
 	String() string
@@ -21,11 +23,27 @@ type Node interface {
 	// To avoid type assertions, some XxxNodes also have specialized
 	// 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()
 }
 
 // NodeType identifies the type of a parse tree node.
 type NodeType int
 
+// Pos represents a byte position in the original input text from which
+// this template was parsed.
+type Pos int
+
+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 {
@@ -34,8 +52,9 @@ func (t NodeType) Type() NodeType {
 
 const (
 	NodeText       NodeType = iota // Plain text.
-	NodeAction                     // A simple action such as field evaluation.
+	NodeAction                     // A non-control action such as a field evaluation.
 	NodeBool                       // A boolean constant.
+	NodeChain                      // A sequence of field accesses.
 	NodeCommand                    // An element of a pipeline.
 	NodeDot                        // The cursor, dot.
 	nodeElse                       // An else action. Not added to tree.
@@ -44,6 +63,7 @@ const (
 	NodeIdentifier                 // An identifier; always a function name.
 	NodeIf                         // An if action.
 	NodeList                       // A list of Nodes.
+	NodeNil                        // An untyped nil constant.
 	NodeNumber                     // A numerical constant.
 	NodePipe                       // A pipeline of commands.
 	NodeRange                      // A range action.
@@ -58,11 +78,12 @@ const (
 // ListNode holds a sequence of nodes.
 type ListNode struct {
 	NodeType
+	Pos
 	Nodes []Node // The element nodes in lexical order.
 }
 
-func newList() *ListNode {
-	return &ListNode{NodeType: NodeList}
+func newList(pos Pos) *ListNode {
+	return &ListNode{NodeType: NodeList, Pos: pos}
 }
 
 func (l *ListNode) append(n Node) {
@@ -81,7 +102,7 @@ func (l *ListNode) CopyList() *ListNode {
 	if l == nil {
 		return l
 	}
-	n := newList()
+	n := newList(l.Pos)
 	for _, elem := range l.Nodes {
 		n.append(elem.Copy())
 	}
@@ -95,11 +116,12 @@ func (l *ListNode) Copy() Node {
 // TextNode holds plain text.
 type TextNode struct {
 	NodeType
+	Pos
 	Text []byte // The text; may span newlines.
 }
 
-func newText(text string) *TextNode {
-	return &TextNode{NodeType: NodeText, Text: []byte(text)}
+func newText(pos Pos, text string) *TextNode {
+	return &TextNode{NodeType: NodeText, Pos: pos, Text: []byte(text)}
 }
 
 func (t *TextNode) String() string {
@@ -113,13 +135,14 @@ func (t *TextNode) Copy() Node {
 // PipeNode holds a pipeline with optional declaration
 type PipeNode struct {
 	NodeType
-	Line int             // The line number in the input.
+	Pos
+	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(line int, decl []*VariableNode) *PipeNode {
-	return &PipeNode{NodeType: NodePipe, Line: line, Decl: decl}
+func newPipeline(pos Pos, line int, decl []*VariableNode) *PipeNode {
+	return &PipeNode{NodeType: NodePipe, Pos: pos, Line: line, Decl: decl}
 }
 
 func (p *PipeNode) append(command *CommandNode) {
@@ -154,7 +177,7 @@ func (p *PipeNode) CopyPipe() *PipeNode {
 	for _, d := range p.Decl {
 		decl = append(decl, d.Copy().(*VariableNode))
 	}
-	n := newPipeline(p.Line, decl)
+	n := newPipeline(p.Pos, p.Line, decl)
 	for _, c := range p.Cmds {
 		n.append(c.Copy().(*CommandNode))
 	}
@@ -167,15 +190,16 @@ func (p *PipeNode) Copy() Node {
 
 // ActionNode holds an action (something bounded by delimiters).
 // Control actions have their own nodes; ActionNode represents simple
-// ones such as field evaluations.
+// ones such as field evaluations and parenthesized pipelines.
 type ActionNode struct {
 	NodeType
-	Line int       // The line number in the input.
+	Pos
+	Line int       // The line number in the input (deprecated; kept for compatibility)
 	Pipe *PipeNode // The pipeline in the action.
 }
 
-func newAction(line int, pipe *PipeNode) *ActionNode {
-	return &ActionNode{NodeType: NodeAction, Line: line, Pipe: pipe}
+func newAction(pos Pos, line int, pipe *PipeNode) *ActionNode {
+	return &ActionNode{NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe}
 }
 
 func (a *ActionNode) String() string {
@@ -184,18 +208,19 @@ func (a *ActionNode) String() string {
 }
 
 func (a *ActionNode) Copy() Node {
-	return newAction(a.Line, a.Pipe.CopyPipe())
+	return newAction(a.Pos, a.Line, a.Pipe.CopyPipe())
 
 }
 
 // CommandNode holds a command (a pipeline inside an evaluating action).
 type CommandNode struct {
 	NodeType
+	Pos
 	Args []Node // Arguments in lexical order: Identifier, field, or constant.
 }
 
-func newCommand() *CommandNode {
-	return &CommandNode{NodeType: NodeCommand}
+func newCommand(pos Pos) *CommandNode {
+	return &CommandNode{NodeType: NodeCommand, Pos: pos}
 }
 
 func (c *CommandNode) append(arg Node) {
@@ -208,6 +233,10 @@ func (c *CommandNode) String() string {
 		if i > 0 {
 			s += " "
 		}
+		if arg, ok := arg.(*PipeNode); ok {
+			s += "(" + arg.String() + ")"
+			continue
+		}
 		s += arg.String()
 	}
 	return s
@@ -217,7 +246,7 @@ func (c *CommandNode) Copy() Node {
 	if c == nil {
 		return c
 	}
-	n := newCommand()
+	n := newCommand(c.Pos)
 	for _, c := range c.Args {
 		n.append(c.Copy())
 	}
@@ -227,6 +256,7 @@ func (c *CommandNode) Copy() Node {
 // IdentifierNode holds an identifier.
 type IdentifierNode struct {
 	NodeType
+	Pos
 	Ident string // The identifier's name.
 }
 
@@ -235,23 +265,32 @@ func NewIdentifier(ident string) *IdentifierNode {
 	return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident}
 }
 
+// SetPos sets the position. NewIdentifier is a public method so we can't modify its signature.
+// Chained for convenience.
+// TODO: fix one day?
+func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode {
+	i.Pos = pos
+	return i
+}
+
 func (i *IdentifierNode) String() string {
 	return i.Ident
 }
 
 func (i *IdentifierNode) Copy() Node {
-	return NewIdentifier(i.Ident)
+	return NewIdentifier(i.Ident).SetPos(i.Pos)
 }
 
-// VariableNode holds a list of variable names. The dollar sign is
-// part of the name.
+// VariableNode holds a list of variable names, possibly with chained field
+// accesses. The dollar sign is part of the (first) name.
 type VariableNode struct {
 	NodeType
-	Ident []string // Variable names in lexical order.
+	Pos
+	Ident []string // Variable name and fields in lexical order.
 }
 
-func newVariable(ident string) *VariableNode {
-	return &VariableNode{NodeType: NodeVariable, Ident: strings.Split(ident, ".")}
+func newVariable(pos Pos, ident string) *VariableNode {
+	return &VariableNode{NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")}
 }
 
 func (v *VariableNode) String() string {
@@ -266,14 +305,16 @@ func (v *VariableNode) String() string {
 }
 
 func (v *VariableNode) Copy() Node {
-	return &VariableNode{NodeType: NodeVariable, Ident: append([]string{}, v.Ident...)}
+	return &VariableNode{NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)}
 }
 
-// DotNode holds the special identifier '.'. It is represented by a nil pointer.
-type DotNode bool
+// DotNode holds the special identifier '.'.
+type DotNode struct {
+	Pos
+}
 
-func newDot() *DotNode {
-	return nil
+func newDot(pos Pos) *DotNode {
+	return &DotNode{Pos: pos}
 }
 
 func (d *DotNode) Type() NodeType {
@@ -285,7 +326,28 @@ func (d *DotNode) String() string {
 }
 
 func (d *DotNode) Copy() Node {
-	return newDot()
+	return newDot(d.Pos)
+}
+
+// NilNode holds the special identifier 'nil' representing an untyped nil constant.
+type NilNode struct {
+	Pos
+}
+
+func newNil(pos Pos) *NilNode {
+	return &NilNode{Pos: pos}
+}
+
+func (n *NilNode) Type() NodeType {
+	return NodeNil
+}
+
+func (n *NilNode) String() string {
+	return "nil"
+}
+
+func (n *NilNode) Copy() Node {
+	return newNil(n.Pos)
 }
 
 // FieldNode holds a field (identifier starting with '.').
@@ -293,11 +355,12 @@ func (d *DotNode) Copy() Node {
 // The period is dropped from each ident.
 type FieldNode struct {
 	NodeType
+	Pos
 	Ident []string // The identifiers in lexical order.
 }
 
-func newField(ident string) *FieldNode {
-	return &FieldNode{NodeType: NodeField, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
+func newField(pos Pos, ident string) *FieldNode {
+	return &FieldNode{NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
 }
 
 func (f *FieldNode) String() string {
@@ -309,17 +372,59 @@ func (f *FieldNode) String() string {
 }
 
 func (f *FieldNode) Copy() Node {
-	return &FieldNode{NodeType: NodeField, Ident: append([]string{}, f.Ident...)}
+	return &FieldNode{NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)}
+}
+
+// ChainNode holds a term followed by a chain of field accesses (identifier starting with '.').
+// The names may be chained ('.x.y').
+// The periods are dropped from each ident.
+type ChainNode struct {
+	NodeType
+	Pos
+	Node  Node
+	Field []string // The identifiers in lexical order.
+}
+
+func newChain(pos Pos, node Node) *ChainNode {
+	return &ChainNode{NodeType: NodeChain, Pos: pos, Node: node}
+}
+
+// Add adds the named field (which should start with a period) to the end of the chain.
+func (c *ChainNode) Add(field string) {
+	if len(field) == 0 || field[0] != '.' {
+		panic("no dot in field")
+	}
+	field = field[1:] // Remove leading dot.
+	if field == "" {
+		panic("empty field")
+	}
+	c.Field = append(c.Field, field)
+}
+
+func (c *ChainNode) String() string {
+	s := c.Node.String()
+	if _, ok := c.Node.(*PipeNode); ok {
+		s = "(" + s + ")"
+	}
+	for _, field := range c.Field {
+		s += "." + field
+	}
+	return s
+}
+
+func (c *ChainNode) Copy() Node {
+	return &ChainNode{NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)}
 }
 
 // BoolNode holds a boolean constant.
 type BoolNode struct {
 	NodeType
+	Pos
 	True bool // The value of the boolean constant.
 }
 
-func newBool(true bool) *BoolNode {
-	return &BoolNode{NodeType: NodeBool, True: true}
+func newBool(pos Pos, true bool) *BoolNode {
+	return &BoolNode{NodeType: NodeBool, Pos: pos, True: true}
 }
 
 func (b *BoolNode) String() string {
@@ -330,7 +435,7 @@ func (b *BoolNode) String() string {
 }
 
 func (b *BoolNode) Copy() Node {
-	return newBool(b.True)
+	return newBool(b.Pos, b.True)
 }
 
 // NumberNode holds a number: signed or unsigned integer, float, or complex.
@@ -338,6 +443,7 @@ func (b *BoolNode) Copy() Node {
 // This simulates in a small amount of code the behavior of Go's ideal constants.
 type NumberNode struct {
 	NodeType
+	Pos
 	IsInt      bool       // Number has an integral value.
 	IsUint     bool       // Number has an unsigned integral value.
 	IsFloat    bool       // Number has a floating-point value.
@@ -349,8 +455,8 @@ type NumberNode struct {
 	Text       string     // The original textual representation from the input.
 }
 
-func newNumber(text string, typ itemType) (*NumberNode, error) {
-	n := &NumberNode{NodeType: NodeNumber, Text: text}
+func newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) {
+	n := &NumberNode{NodeType: NodeNumber, Pos: pos, Text: text}
 	switch typ {
 	case itemCharConstant:
 		rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
@@ -460,12 +566,13 @@ func (n *NumberNode) Copy() Node {
 // StringNode holds a string constant. The value has been "unquoted".
 type StringNode struct {
 	NodeType
+	Pos
 	Quoted string // The original text of the string, with quotes.
 	Text   string // The string, after quote processing.
 }
 
-func newString(orig, text string) *StringNode {
-	return &StringNode{NodeType: NodeString, Quoted: orig, Text: text}
+func newString(pos Pos, orig, text string) *StringNode {
+	return &StringNode{NodeType: NodeString, Pos: pos, Quoted: orig, Text: text}
 }
 
 func (s *StringNode) String() string {
@@ -473,15 +580,17 @@ func (s *StringNode) String() string {
 }
 
 func (s *StringNode) Copy() Node {
-	return newString(s.Quoted, s.Text)
+	return newString(s.Pos, s.Quoted, s.Text)
 }
 
-// endNode represents an {{end}} action. It is represented by a nil pointer.
+// endNode represents an {{end}} action.
 // It does not appear in the final parse tree.
-type endNode bool
+type endNode struct {
+	Pos
+}
 
-func newEnd() *endNode {
-	return nil
+func newEnd(pos Pos) *endNode {
+	return &endNode{Pos: pos}
 }
 
 func (e *endNode) Type() NodeType {
@@ -493,17 +602,18 @@ func (e *endNode) String() string {
 }
 
 func (e *endNode) Copy() Node {
-	return newEnd()
+	return newEnd(e.Pos)
 }
 
 // elseNode represents an {{else}} action. Does not appear in the final tree.
 type elseNode struct {
 	NodeType
-	Line int // The line number in the input.
+	Pos
+	Line int // The line number in the input (deprecated; kept for compatibility)
 }
 
-func newElse(line int) *elseNode {
-	return &elseNode{NodeType: nodeElse, Line: line}
+func newElse(pos Pos, line int) *elseNode {
+	return &elseNode{NodeType: nodeElse, Pos: pos, Line: line}
 }
 
 func (e *elseNode) Type() NodeType {
@@ -515,13 +625,14 @@ func (e *elseNode) String() string {
 }
 
 func (e *elseNode) Copy() Node {
-	return newElse(e.Line)
+	return newElse(e.Pos, e.Line)
 }
 
 // BranchNode is the common representation of if, range, and with.
 type BranchNode struct {
 	NodeType
-	Line     int       // The line number in the input.
+	Pos
+	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.
 	ElseList *ListNode // What to execute if the value is empty (nil if absent).
@@ -550,12 +661,12 @@ type IfNode struct {
 	BranchNode
 }
 
-func newIf(line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
-	return &IfNode{BranchNode{NodeType: NodeIf, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+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 (i *IfNode) Copy() Node {
-	return newIf(i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
+	return newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
 }
 
 // RangeNode represents a {{range}} action and its commands.
@@ -563,12 +674,12 @@ type RangeNode struct {
 	BranchNode
 }
 
-func newRange(line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
-	return &RangeNode{BranchNode{NodeType: NodeRange, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+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 (r *RangeNode) Copy() Node {
-	return newRange(r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
+	return newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
 }
 
 // WithNode represents a {{with}} action and its commands.
@@ -576,24 +687,25 @@ type WithNode struct {
 	BranchNode
 }
 
-func newWith(line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
-	return &WithNode{BranchNode{NodeType: NodeWith, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+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 (w *WithNode) Copy() Node {
-	return newWith(w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
+	return newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
 }
 
 // TemplateNode represents a {{template}} action.
 type TemplateNode struct {
 	NodeType
-	Line int       // The line number in the input.
+	Pos
+	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(line int, name string, pipe *PipeNode) *TemplateNode {
-	return &TemplateNode{NodeType: NodeTemplate, Line: line, Name: name, Pipe: pipe}
+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 *TemplateNode) String() string {
@@ -604,5 +716,5 @@ func (t *TemplateNode) String() string {
 }
 
 func (t *TemplateNode) Copy() Node {
-	return newTemplate(t.Line, t.Name, t.Pipe.CopyPipe())
+	return newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe())
 }
diff --git a/src/pkg/text/template/parse/parse.go b/src/pkg/text/template/parse/parse.go
index c0087b2..c0fb927 100644
--- a/src/pkg/text/template/parse/parse.go
+++ b/src/pkg/text/template/parse/parse.go
@@ -13,17 +13,20 @@ import (
 	"fmt"
 	"runtime"
 	"strconv"
+	"strings"
 	"unicode"
 )
 
 // Tree is the representation of a single parsed template.
 type Tree struct {
-	Name string    // name of the template represented by the tree.
-	Root *ListNode // top-level root of the tree.
+	Name      string    // name of the template represented by the tree.
+	ParseName string    // name of the top-level template during parsing, for error messages.
+	Root      *ListNode // top-level root of the tree.
+	text      string    // text parsed to create the template (or its parent)
 	// Parsing only; cleared after parse.
 	funcs     []map[string]interface{}
 	lex       *lexer
-	token     [2]item // two-token lookahead for parser.
+	token     [3]item // three-token lookahead for parser.
 	peekCount int
 	vars      []string // variables defined at the moment.
 }
@@ -34,7 +37,9 @@ type Tree struct {
 // empty map is returned with the error.
 func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (treeSet map[string]*Tree, err error) {
 	treeSet = make(map[string]*Tree)
-	_, err = New(name).Parse(text, leftDelim, rightDelim, treeSet, funcs...)
+	t := New(name)
+	t.text = text
+	_, err = t.Parse(text, leftDelim, rightDelim, treeSet, funcs...)
 	return
 }
 
@@ -53,12 +58,21 @@ func (t *Tree) backup() {
 	t.peekCount++
 }
 
-// backup2 backs the input stream up two tokens
+// backup2 backs the input stream up two tokens.
+// The zeroth token is already there.
 func (t *Tree) backup2(t1 item) {
 	t.token[1] = t1
 	t.peekCount = 2
 }
 
+// backup3 backs the input stream up three tokens
+// The zeroth token is already there.
+func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back.
+	t.token[1] = t1
+	t.token[2] = t2
+	t.peekCount = 3
+}
+
 // peek returns but does not consume the next token.
 func (t *Tree) peek() item {
 	if t.peekCount > 0 {
@@ -69,6 +83,29 @@ func (t *Tree) peek() item {
 	return t.token[0]
 }
 
+// nextNonSpace returns the next non-space token.
+func (t *Tree) nextNonSpace() (token item) {
+	for {
+		token = t.next()
+		if token.typ != itemSpace {
+			break
+		}
+	}
+	return token
+}
+
+// peekNonSpace returns but does not consume the next non-space token.
+func (t *Tree) peekNonSpace() (token item) {
+	for {
+		token = t.next()
+		if token.typ != itemSpace {
+			break
+		}
+	}
+	t.backup()
+	return token
+}
+
 // Parsing.
 
 // New allocates a new parse tree with the given name.
@@ -79,10 +116,29 @@ func New(name string, funcs ...map[string]interface{}) *Tree {
 	}
 }
 
+// ErrorContext returns a textual representation of the location of the node in the input text.
+func (t *Tree) ErrorContext(n Node) (location, context string) {
+	pos := int(n.Position())
+	text := t.text[:pos]
+	byteNum := strings.LastIndex(text, "\n")
+	if byteNum == -1 {
+		byteNum = pos // On first line.
+	} else {
+		byteNum++ // After the newline.
+		byteNum = pos - byteNum
+	}
+	lineNum := 1 + strings.Count(text, "\n")
+	context = n.String()
+	if len(context) > 20 {
+		context = fmt.Sprintf("%.20s...", context)
+	}
+	return fmt.Sprintf("%s:%d:%d", t.ParseName, lineNum, byteNum), context
+}
+
 // errorf formats the error and terminates processing.
 func (t *Tree) errorf(format string, args ...interface{}) {
 	t.Root = nil
-	format = fmt.Sprintf("template: %s:%d: %s", t.Name, t.lex.lineNumber(), format)
+	format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.lex.lineNumber(), format)
 	panic(fmt.Errorf(format, args...))
 }
 
@@ -93,18 +149,18 @@ func (t *Tree) error(err error) {
 
 // expect consumes the next token and guarantees it has the required type.
 func (t *Tree) expect(expected itemType, context string) item {
-	token := t.next()
+	token := t.nextNonSpace()
 	if token.typ != expected {
-		t.errorf("expected %s in %s; got %s", expected, context, token)
+		t.unexpected(token, context)
 	}
 	return token
 }
 
-// expectEither consumes the next token and guarantees it has one of the required types.
+// expectOneOf consumes the next token and guarantees it has one of the required types.
 func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
-	token := t.next()
+	token := t.nextNonSpace()
 	if token.typ != expected1 && token.typ != expected2 {
-		t.errorf("expected %s or %s in %s; got %s", expected1, expected2, context, token)
+		t.unexpected(token, context)
 	}
 	return token
 }
@@ -169,9 +225,11 @@ func (t *Tree) atEOF() bool {
 // the template for execution. If either action delimiter string is empty, the
 // default ("{{" or "}}") is used. Embedded template definitions are added to
 // the treeSet map.
-func (t *Tree) Parse(s, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
+func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
 	defer t.recover(&err)
-	t.startParse(funcs, lex(t.Name, s, leftDelim, rightDelim))
+	t.ParseName = t.Name
+	t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim))
+	t.text = text
 	t.parse(treeSet)
 	t.add(treeSet)
 	t.stopParse()
@@ -219,12 +277,14 @@ 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.Root = newList(t.peek().pos)
 	for t.peek().typ != itemEOF {
 		if t.peek().typ == itemLeftDelim {
 			delim := t.next()
-			if t.next().typ == itemDefine {
+			if t.nextNonSpace().typ == itemDefine {
 				newT := New("definition") // name will be updated once we know it.
+				newT.text = t.text
+				newT.ParseName = t.ParseName
 				newT.startParse(t.funcs, t.lex)
 				newT.parseDefinition(treeSet)
 				continue
@@ -257,16 +317,16 @@ func (t *Tree) parseDefinition(treeSet map[string]*Tree) {
 	if end.Type() != nodeEnd {
 		t.errorf("unexpected %s in %s", end, context)
 	}
-	t.stopParse()
 	t.add(treeSet)
+	t.stopParse()
 }
 
 // itemList:
 //	textOrAction*
 // Terminates at {{end}} or {{else}}, returned separately.
 func (t *Tree) itemList() (list *ListNode, next Node) {
-	list = newList()
-	for t.peek().typ != itemEOF {
+	list = newList(t.peekNonSpace().pos)
+	for t.peekNonSpace().typ != itemEOF {
 		n := t.textOrAction()
 		switch n.Type() {
 		case nodeEnd, nodeElse:
@@ -281,9 +341,9 @@ func (t *Tree) itemList() (list *ListNode, next Node) {
 // textOrAction:
 //	text | action
 func (t *Tree) textOrAction() Node {
-	switch token := t.next(); token.typ {
+	switch token := t.nextNonSpace(); token.typ {
 	case itemText:
-		return newText(token.val)
+		return newText(token.pos, token.val)
 	case itemLeftDelim:
 		return t.action()
 	default:
@@ -298,7 +358,7 @@ func (t *Tree) textOrAction() Node {
 // Left delim is past. Now get actions.
 // First word could be a keyword such as range.
 func (t *Tree) action() (n Node) {
-	switch token := t.next(); token.typ {
+	switch token := t.nextNonSpace(); token.typ {
 	case itemElse:
 		return t.elseControl()
 	case itemEnd:
@@ -314,24 +374,26 @@ func (t *Tree) action() (n Node) {
 	}
 	t.backup()
 	// Do not pop variables; they persist until "end".
-	return newAction(t.lex.lineNumber(), t.pipeline("command"))
+	return newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
 }
 
 // Pipeline:
-//	field or command
-//	pipeline "|" pipeline
+//	declarations? command ('|' command)*
 func (t *Tree) pipeline(context string) (pipe *PipeNode) {
 	var decl []*VariableNode
+	pos := t.peekNonSpace().pos
 	// Are there declarations?
 	for {
-		if v := t.peek(); v.typ == itemVariable {
+		if v := t.peekNonSpace(); v.typ == itemVariable {
 			t.next()
-			if next := t.peek(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
-				t.next()
-				variable := newVariable(v.val)
-				if len(variable.Ident) != 1 {
-					t.errorf("illegal variable in declaration: %s", v.val)
-				}
+			// Since space is a token, we need 3-token look-ahead here in the worst case:
+			// in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an
+			// argument variable rather than a declaration. So remember the token
+			// adjacent to the variable so we can push it back if necessary.
+			tokenAfterVariable := t.peek()
+			if next := t.peekNonSpace(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
+				t.nextNonSpace()
+				variable := newVariable(v.pos, v.val)
 				decl = append(decl, variable)
 				t.vars = append(t.vars, v.val)
 				if next.typ == itemChar && next.val == "," {
@@ -340,22 +402,27 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
 					}
 					t.errorf("too many declarations in %s", context)
 				}
+			} else if tokenAfterVariable.typ == itemSpace {
+				t.backup3(v, tokenAfterVariable)
 			} else {
 				t.backup2(v)
 			}
 		}
 		break
 	}
-	pipe = newPipeline(t.lex.lineNumber(), decl)
+	pipe = newPipeline(pos, t.lex.lineNumber(), decl)
 	for {
-		switch token := t.next(); token.typ {
-		case itemRightDelim:
+		switch token := t.nextNonSpace(); token.typ {
+		case itemRightDelim, itemRightParen:
 			if len(pipe.Cmds) == 0 {
 				t.errorf("missing value for %s", context)
 			}
+			if token.typ == itemRightParen {
+				t.backup()
+			}
 			return
 		case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
-			itemVariable, itemNumber, itemRawString, itemString:
+			itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen:
 			t.backup()
 			pipe.append(t.command())
 		default:
@@ -365,9 +432,9 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
 	return
 }
 
-func (t *Tree) parseControl(context string) (lineNum int, pipe *PipeNode, list, elseList *ListNode) {
-	lineNum = t.lex.lineNumber()
+func (t *Tree) parseControl(context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
 	defer t.popVars(len(t.vars))
+	line = t.lex.lineNumber()
 	pipe = t.pipeline(context)
 	var next Node
 	list, next = t.itemList()
@@ -380,7 +447,7 @@ func (t *Tree) parseControl(context string) (lineNum int, pipe *PipeNode, list,
 		}
 		elseList = elseList
 	}
-	return lineNum, pipe, list, elseList
+	return pipe.Position(), line, pipe, list, elseList
 }
 
 // If:
@@ -411,16 +478,14 @@ func (t *Tree) withControl() Node {
 //	{{end}}
 // End keyword is past.
 func (t *Tree) endControl() Node {
-	t.expect(itemRightDelim, "end")
-	return newEnd()
+	return newEnd(t.expect(itemRightDelim, "end").pos)
 }
 
 // Else:
 //	{{else}}
 // Else keyword is past.
 func (t *Tree) elseControl() Node {
-	t.expect(itemRightDelim, "else")
-	return newElse(t.lex.lineNumber())
+	return newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
 }
 
 // Template:
@@ -429,7 +494,8 @@ func (t *Tree) elseControl() Node {
 // to a string.
 func (t *Tree) templateControl() Node {
 	var name string
-	switch token := t.next(); token.typ {
+	token := t.nextNonSpace()
+	switch token.typ {
 	case itemString, itemRawString:
 		s, err := strconv.Unquote(token.val)
 		if err != nil {
@@ -440,57 +506,38 @@ func (t *Tree) templateControl() Node {
 		t.unexpected(token, "template invocation")
 	}
 	var pipe *PipeNode
-	if t.next().typ != itemRightDelim {
+	if t.nextNonSpace().typ != itemRightDelim {
 		t.backup()
 		// Do not pop variables; they persist until "end".
 		pipe = t.pipeline("template")
 	}
-	return newTemplate(t.lex.lineNumber(), name, pipe)
+	return newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
 }
 
 // command:
+//	operand (space operand)*
 // 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()
-Loop:
+	cmd := newCommand(t.peekNonSpace().pos)
 	for {
+		t.peekNonSpace() // skip leading spaces.
+		operand := t.operand()
+		if operand != nil {
+			cmd.append(operand)
+		}
 		switch token := t.next(); token.typ {
-		case itemRightDelim:
-			t.backup()
-			break Loop
-		case itemPipe:
-			break Loop
+		case itemSpace:
+			continue
 		case itemError:
 			t.errorf("%s", token.val)
-		case itemIdentifier:
-			if !t.hasFunction(token.val) {
-				t.errorf("function %q not defined", token.val)
-			}
-			cmd.append(NewIdentifier(token.val))
-		case itemDot:
-			cmd.append(newDot())
-		case itemVariable:
-			cmd.append(t.useVar(token.val))
-		case itemField:
-			cmd.append(newField(token.val))
-		case itemBool:
-			cmd.append(newBool(token.val == "true"))
-		case itemCharConstant, itemComplex, itemNumber:
-			number, err := newNumber(token.val, token.typ)
-			if err != nil {
-				t.error(err)
-			}
-			cmd.append(number)
-		case itemString, itemRawString:
-			s, err := strconv.Unquote(token.val)
-			if err != nil {
-				t.error(err)
-			}
-			cmd.append(newString(token.val, s))
+		case itemRightDelim, itemRightParen:
+			t.backup()
+		case itemPipe:
 		default:
-			t.unexpected(token, "command")
+			t.errorf("unexpected %s in operand; missing space?", token)
 		}
+		break
 	}
 	if len(cmd.Args) == 0 {
 		t.errorf("empty command")
@@ -498,6 +545,88 @@ Loop:
 	return cmd
 }
 
+// operand:
+//	term .Field*
+// An operand is a space-separated component of a command,
+// a term possibly followed by field accesses.
+// A nil return means the next item is not an operand.
+func (t *Tree) operand() Node {
+	node := t.term()
+	if node == nil {
+		return nil
+	}
+	if t.peek().typ == itemField {
+		chain := newChain(t.peek().pos, node)
+		for t.peek().typ == itemField {
+			chain.Add(t.next().val)
+		}
+		// Compatibility with original API: If the term is of type NodeField
+		// or NodeVariable, just put more fields on the original.
+		// Otherwise, keep the Chain node.
+		// TODO: Switch to Chains always when we can.
+		switch node.Type() {
+		case NodeField:
+			node = newField(chain.Position(), chain.String())
+		case NodeVariable:
+			node = newVariable(chain.Position(), chain.String())
+		default:
+			node = chain
+		}
+	}
+	return node
+}
+
+// term:
+//	literal (number, string, nil, boolean)
+//	function (identifier)
+//	.
+//	.Field
+//	$
+//	'(' pipeline ')'
+// A term is a simple "expression".
+// A nil return means the next item is not a term.
+func (t *Tree) term() Node {
+	switch token := t.nextNonSpace(); token.typ {
+	case itemError:
+		t.errorf("%s", token.val)
+	case itemIdentifier:
+		if !t.hasFunction(token.val) {
+			t.errorf("function %q not defined", token.val)
+		}
+		return NewIdentifier(token.val).SetPos(token.pos)
+	case itemDot:
+		return newDot(token.pos)
+	case itemNil:
+		return newNil(token.pos)
+	case itemVariable:
+		return t.useVar(token.pos, token.val)
+	case itemField:
+		return newField(token.pos, token.val)
+	case itemBool:
+		return newBool(token.pos, token.val == "true")
+	case itemCharConstant, itemComplex, itemNumber:
+		number, err := newNumber(token.pos, token.val, token.typ)
+		if err != nil {
+			t.error(err)
+		}
+		return number
+	case itemLeftParen:
+		pipe := t.pipeline("parenthesized pipeline")
+		if token := t.next(); token.typ != itemRightParen {
+			t.errorf("unclosed right paren: unexpected %s", token)
+		}
+		return pipe
+	case itemString, itemRawString:
+		s, err := strconv.Unquote(token.val)
+		if err != nil {
+			t.error(err)
+		}
+		return newString(token.pos, token.val, s)
+	}
+	t.backup()
+	return nil
+}
+
 // hasFunction reports if a function name exists in the Tree's maps.
 func (t *Tree) hasFunction(name string) bool {
 	for _, funcMap := range t.funcs {
@@ -518,8 +647,8 @@ 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(name string) Node {
-	v := newVariable(name)
+func (t *Tree) useVar(pos Pos, name string) Node {
+	v := 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/pkg/text/template/parse/parse_test.go
index b2e7882..695c76e 100644
--- a/src/pkg/text/template/parse/parse_test.go
+++ b/src/pkg/text/template/parse/parse_test.go
@@ -7,10 +7,11 @@ package parse
 import (
 	"flag"
 	"fmt"
+	"strings"
 	"testing"
 )
 
-var debug = flag.Bool("debug", false, "show the errors produced by the tests")
+var debug = flag.Bool("debug", false, "show the errors produced by the main tests")
 
 type numberTest struct {
 	text      string
@@ -84,7 +85,7 @@ func TestNumberParse(t *testing.T) {
 				typ = itemComplex
 			}
 		}
-		n, err := newNumber(test.text, typ)
+		n, err := 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)
@@ -185,6 +186,10 @@ var parseTests = []parseTest{
 		`{{.X | .Y}}`},
 	{"pipeline with decl", "{{$x := .X|.Y}}", noError,
 		`{{$x := .X | .Y}}`},
+	{"nested pipeline", "{{.X (.Y .Z) (.A | .B .C) (.E)}}", noError,
+		`{{.X (.Y .Z) (.A | .B .C) (.E)}}`},
+	{"field applied to parentheses", "{{(.Y .Z).Field}}", noError,
+		`{{(.Y .Z).Field}}`},
 	{"simple if", "{{if .X}}hello{{end}}", noError,
 		`{{if .X}}"hello"{{end}}`},
 	{"if with else", "{{if .X}}true{{else}}false{{end}}", noError,
@@ -205,8 +210,8 @@ var parseTests = []parseTest{
 		`{{range $x := .SI}}{{.}}{{end}}`},
 	{"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
 		`{{range $x, $y := .SI}}{{.}}{{end}}`},
-	{"constants", "{{range .SI 1 -3.2i true false 'a'}}{{end}}", noError,
-		`{{range .SI 1 -3.2i true false 'a'}}{{end}}`},
+	{"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError,
+		`{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`},
 	{"template", "{{template `x`}}", noError,
 		`{{template "x"}}`},
 	{"template with arg", "{{template `x` .Y}}", noError,
@@ -230,6 +235,9 @@ var parseTests = []parseTest{
 	{"invalid punctuation", "{{printf 3, 4}}", hasError, ""},
 	{"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""},
 	{"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""},
+	{"dot applied to parentheses", "{{printf (printf .).}}", hasError, ""},
+	{"adjacent args", "{{printf 3`x`}}", hasError, ""},
+	{"adjacent args with .", "{{printf `x`.}}", hasError, ""},
 	// Equals (and other chars) do not assignments make (yet).
 	{"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"},
 	{"bug0b", "{{$x = 1}}{{$x}}", hasError, ""},
@@ -316,3 +324,74 @@ func TestIsEmpty(t *testing.T) {
 		}
 	}
 }
+
+// All failures, and the result is a string that must appear in the error message.
+var errorTests = []parseTest{
+	// Check line numbers are accurate.
+	{"unclosed1",
+		"line1\n{{",
+		hasError, `unclosed1:2: unexpected unclosed action in command`},
+	{"unclosed2",
+		"line1\n{{define `x`}}line2\n{{",
+		hasError, `unclosed2:3: unexpected unclosed action in command`},
+	// Specific errors.
+	{"function",
+		"{{foo}}",
+		hasError, `function "foo" not defined`},
+	{"comment",
+		"{{/*}}",
+		hasError, `unclosed comment`},
+	{"lparen",
+		"{{.X (1 2 3}}",
+		hasError, `unclosed left paren`},
+	{"rparen",
+		"{{.X 1 2 3)}}",
+		hasError, `unexpected ")"`},
+	{"space",
+		"{{`x`3}}",
+		hasError, `missing space?`},
+	{"idchar",
+		"{{a#}}",
+		hasError, `'#'`},
+	{"charconst",
+		"{{'a}}",
+		hasError, `unterminated character constant`},
+	{"stringconst",
+		`{{"a}}`,
+		hasError, `unterminated quoted string`},
+	{"rawstringconst",
+		"{{`a}}",
+		hasError, `unterminated raw quoted string`},
+	{"number",
+		"{{0xi}}",
+		hasError, `number syntax`},
+	{"multidefine",
+		"{{define `a`}}a{{end}}{{define `a`}}b{{end}}",
+		hasError, `multiple definition of template`},
+	{"eof",
+		"{{range .X}}",
+		hasError, `unexpected EOF`},
+	{"variable",
+		// Declare $x so it's defined, to avoid that error, and then check we don't parse a declaration.
+		"{{$x := 23}}{{with $x.y := 3}}{{$x 23}}{{end}}",
+		hasError, `unexpected ":="`},
+	{"multidecl",
+		"{{$a,$b,$c := 23}}",
+		hasError, `too many declarations`},
+	{"undefvar",
+		"{{$a}}",
+		hasError, `undefined variable`},
+}
+
+func TestErrors(t *testing.T) {
+	for _, test := range errorTests {
+		_, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree))
+		if err == nil {
+			t.Errorf("%q: expected error", test.name)
+			continue
+		}
+		if !strings.Contains(err.Error(), test.result) {
+			t.Errorf("%q: error %q does not contain %q", test.name, err, test.result)
+		}
+	}
+}
diff --git a/src/pkg/text/template/template.go b/src/pkg/text/template/template.go
index 82fc9e5..a2b9062 100644
--- a/src/pkg/text/template/template.go
+++ b/src/pkg/text/template/template.go
@@ -117,6 +117,9 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error
 // Templates returns a slice of the templates associated with t, including t
 // itself.
 func (t *Template) Templates() []*Template {
+	if t.common == nil {
+		return nil
+	}
 	// Return a slice so we don't expose the map.
 	m := make([]*Template, 0, len(t.tmpl))
 	for _, v := range t.tmpl {
diff --git a/src/pkg/time/example_test.go b/src/pkg/time/example_test.go
index 944cc78..8928caa 100644
--- a/src/pkg/time/example_test.go
+++ b/src/pkg/time/example_test.go
@@ -56,3 +56,100 @@ func ExampleDate() {
 	fmt.Printf("Go launched at %s\n", t.Local())
 	// Output: Go launched at 2009-11-10 15:00:00 -0800 PST
 }
+
+func ExampleTime_Format() {
+	const format = "Jan 2, 2006 at 3:04pm (MST)"
+	t := time.Date(2009, time.November, 10, 15, 0, 0, 0, time.Local)
+	fmt.Println(t.Format(format))
+	fmt.Println(t.UTC().Format(format))
+	// Output:
+	// Nov 10, 2009 at 3:00pm (PST)
+	// Nov 10, 2009 at 11:00pm (UTC)
+}
+
+func ExampleParse() {
+	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
+	t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
+	fmt.Println(t)
+
+	// Note: without explicit zone, returns time in UTC.
+	const shortForm = "2006-Jan-02"
+	t, _ = time.Parse(shortForm, "2013-Feb-03")
+	fmt.Println(t)
+
+	// Output:
+	// 2013-02-03 19:54:00 -0800 PST
+	// 2013-02-03 00:00:00 +0000 UTC
+}
+
+func ExampleParseInLocation() {
+	loc, _ := time.LoadLocation("Europe/Berlin")
+
+	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
+	t, _ := time.ParseInLocation(longForm, "Jul 9, 2012 at 5:02am (CEST)", loc)
+	fmt.Println(t)
+
+	// Note: without explicit zone, returns time in given location.
+	const shortForm = "2006-Jan-02"
+	t, _ = time.ParseInLocation(shortForm, "2012-Jul-09", loc)
+	fmt.Println(t)
+
+	// Output:
+	// 2012-07-09 05:02:00 +0200 CEST
+	// 2012-07-09 00:00:00 +0200 CEST
+}
+
+func ExampleTime_Round() {
+	t := time.Date(0, 0, 0, 12, 15, 30, 918273645, time.UTC)
+	round := []time.Duration{
+		time.Nanosecond,
+		time.Microsecond,
+		time.Millisecond,
+		time.Second,
+		2 * time.Second,
+		time.Minute,
+		10 * time.Minute,
+		time.Hour,
+	}
+
+	for _, d := range round {
+		fmt.Printf("t.Round(%6s) = %s\n", d, t.Round(d).Format("15:04:05.999999999"))
+	}
+	// Output:
+	// t.Round(   1ns) = 12:15:30.918273645
+	// t.Round(   1us) = 12:15:30.918274
+	// t.Round(   1ms) = 12:15:30.918
+	// t.Round(    1s) = 12:15:31
+	// t.Round(    2s) = 12:15:30
+	// t.Round(  1m0s) = 12:16:00
+	// t.Round( 10m0s) = 12:20:00
+	// t.Round(1h0m0s) = 12:00:00
+}
+
+func ExampleTime_Truncate() {
+	t, _ := time.Parse("2006 Jan 02 15:04:05", "2012 Dec 07 12:15:30.918273645")
+	trunc := []time.Duration{
+		time.Nanosecond,
+		time.Microsecond,
+		time.Millisecond,
+		time.Second,
+		2 * time.Second,
+		time.Minute,
+		10 * time.Minute,
+		time.Hour,
+	}
+
+	for _, d := range trunc {
+		fmt.Printf("t.Truncate(%6s) = %s\n", d, t.Truncate(d).Format("15:04:05.999999999"))
+	}
+
+	// Output:
+	// t.Truncate(   1ns) = 12:15:30.918273645
+	// t.Truncate(   1us) = 12:15:30.918273
+	// t.Truncate(   1ms) = 12:15:30.918
+	// t.Truncate(    1s) = 12:15:30
+	// t.Truncate(    2s) = 12:15:30
+	// t.Truncate(  1m0s) = 12:15:00
+	// t.Truncate( 10m0s) = 12:10:00
+	// t.Truncate(1h0m0s) = 12:00:00
+}
diff --git a/src/pkg/time/export_test.go b/src/pkg/time/export_test.go
new file mode 100644
index 0000000..130ca8f
--- /dev/null
+++ b/src/pkg/time/export_test.go
@@ -0,0 +1,19 @@
+// 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 time
+
+import (
+	"sync"
+)
+
+func ResetLocalOnceForTest() {
+	localOnce = sync.Once{}
+	localLoc = Location{}
+}
+
+func ForceUSPacificForTesting() {
+	ResetLocalOnceForTest()
+	localOnce.Do(initTestingZone)
+}
diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go
index efca3a9..817c79a 100644
--- a/src/pkg/time/format.go
+++ b/src/pkg/time/format.go
@@ -9,7 +9,7 @@ import "errors"
 // These are predefined layouts for use in Time.Format.
 // The standard time used in the layouts is:
 //	Mon Jan 2 15:04:05 MST 2006
-// which is Unix time 1136243045. Since MST is GMT-0700,
+// which is Unix time 1136239445. Since MST is GMT-0700,
 // the standard time can be thought of as
 //	01/02 03:04:05PM '06 -0700
 // To define your own format, write down what the standard time would look
@@ -57,63 +57,74 @@ const (
 )
 
 const (
-	stdLongMonth      = "January"
-	stdMonth          = "Jan"
-	stdNumMonth       = "1"
-	stdZeroMonth      = "01"
-	stdLongWeekDay    = "Monday"
-	stdWeekDay        = "Mon"
-	stdDay            = "2"
-	stdUnderDay       = "_2"
-	stdZeroDay        = "02"
-	stdHour           = "15"
-	stdHour12         = "3"
-	stdZeroHour12     = "03"
-	stdMinute         = "4"
-	stdZeroMinute     = "04"
-	stdSecond         = "5"
-	stdZeroSecond     = "05"
-	stdLongYear       = "2006"
-	stdYear           = "06"
-	stdPM             = "PM"
-	stdpm             = "pm"
-	stdTZ             = "MST"
-	stdISO8601TZ      = "Z0700"  // prints Z for UTC
-	stdISO8601ColonTZ = "Z07:00" // prints Z for UTC
-	stdNumTZ          = "-0700"  // always numeric
-	stdNumShortTZ     = "-07"    // always numeric
-	stdNumColonTZ     = "-07:00" // always numeric
+	_                 = iota
+	stdLongMonth      = iota + stdNeedDate  // "January"
+	stdMonth                                // "Jan"
+	stdNumMonth                             // "1"
+	stdZeroMonth                            // "01"
+	stdLongWeekDay                          // "Monday"
+	stdWeekDay                              // "Mon"
+	stdDay                                  // "2"
+	stdUnderDay                             // "_2"
+	stdZeroDay                              // "02"
+	stdHour           = iota + stdNeedClock // "15"
+	stdHour12                               // "3"
+	stdZeroHour12                           // "03"
+	stdMinute                               // "4"
+	stdZeroMinute                           // "04"
+	stdSecond                               // "5"
+	stdZeroSecond                           // "05"
+	stdLongYear       = iota + stdNeedDate  // "2006"
+	stdYear                                 // "06"
+	stdPM             = iota + stdNeedClock // "PM"
+	stdpm                                   // "pm"
+	stdTZ             = iota                // "MST"
+	stdISO8601TZ                            // "Z0700"  // prints Z for UTC
+	stdISO8601ColonTZ                       // "Z07:00" // prints Z for UTC
+	stdNumTZ                                // "-0700"  // always numeric
+	stdNumShortTZ                           // "-07"    // always numeric
+	stdNumColonTZ                           // "-07:00" // always numeric
+	stdFracSecond0                          // ".0", ".00", ... , trailing zeros included
+	stdFracSecond9                          // ".9", ".99", ..., trailing zeros omitted
+
+	stdNeedDate  = 1 << 8             // need month, day, year
+	stdNeedClock = 2 << 8             // need hour, minute, second
+	stdArgShift  = 16                 // extra argument in high bits, above low stdArgShift
+	stdMask      = 1<<stdArgShift - 1 // mask out argument
 )
 
+// std0x records the std values for "01", "02", ..., "06".
+var std0x = [...]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear}
+
 // nextStdChunk finds the first occurrence of a std string in
 // layout and returns the text before, the std string, and the text after.
-func nextStdChunk(layout string) (prefix, std, suffix string) {
+func nextStdChunk(layout string) (prefix string, std int, suffix string) {
 	for i := 0; i < len(layout); i++ {
-		switch layout[i] {
+		switch c := int(layout[i]); c {
 		case 'J': // January, Jan
-			if len(layout) >= i+7 && layout[i:i+7] == stdLongMonth {
-				return layout[0:i], stdLongMonth, layout[i+7:]
-			}
-			if len(layout) >= i+3 && layout[i:i+3] == stdMonth {
+			if len(layout) >= i+3 && layout[i:i+3] == "Jan" {
+				if len(layout) >= i+7 && layout[i:i+7] == "January" {
+					return layout[0:i], stdLongMonth, layout[i+7:]
+				}
 				return layout[0:i], stdMonth, layout[i+3:]
 			}
 
 		case 'M': // Monday, Mon, MST
-			if len(layout) >= i+6 && layout[i:i+6] == stdLongWeekDay {
-				return layout[0:i], stdLongWeekDay, layout[i+6:]
-			}
 			if len(layout) >= i+3 {
-				if layout[i:i+3] == stdWeekDay {
+				if layout[i:i+3] == "Mon" {
+					if len(layout) >= i+6 && layout[i:i+6] == "Monday" {
+						return layout[0:i], stdLongWeekDay, layout[i+6:]
+					}
 					return layout[0:i], stdWeekDay, layout[i+3:]
 				}
-				if layout[i:i+3] == stdTZ {
+				if layout[i:i+3] == "MST" {
 					return layout[0:i], stdTZ, layout[i+3:]
 				}
 			}
 
 		case '0': // 01, 02, 03, 04, 05, 06
 			if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' {
-				return layout[0:i], layout[i : i+2], layout[i+2:]
+				return layout[0:i], std0x[layout[i+1]-'1'], layout[i+2:]
 			}
 
 		case '1': // 15, 1
@@ -123,7 +134,7 @@ func nextStdChunk(layout string) (prefix, std, suffix string) {
 			return layout[0:i], stdNumMonth, layout[i+1:]
 
 		case '2': // 2006, 2
-			if len(layout) >= i+4 && layout[i:i+4] == stdLongYear {
+			if len(layout) >= i+4 && layout[i:i+4] == "2006" {
 				return layout[0:i], stdLongYear, layout[i+4:]
 			}
 			return layout[0:i], stdDay, layout[i+1:]
@@ -133,35 +144,41 @@ func nextStdChunk(layout string) (prefix, std, suffix string) {
 				return layout[0:i], stdUnderDay, layout[i+2:]
 			}
 
-		case '3', '4', '5': // 3, 4, 5
-			return layout[0:i], layout[i : i+1], layout[i+1:]
+		case '3':
+			return layout[0:i], stdHour12, layout[i+1:]
+
+		case '4':
+			return layout[0:i], stdMinute, layout[i+1:]
+
+		case '5':
+			return layout[0:i], stdSecond, layout[i+1:]
 
 		case 'P': // PM
 			if len(layout) >= i+2 && layout[i+1] == 'M' {
-				return layout[0:i], layout[i : i+2], layout[i+2:]
+				return layout[0:i], stdPM, layout[i+2:]
 			}
 
 		case 'p': // pm
 			if len(layout) >= i+2 && layout[i+1] == 'm' {
-				return layout[0:i], layout[i : i+2], layout[i+2:]
+				return layout[0:i], stdpm, layout[i+2:]
 			}
 
 		case '-': // -0700, -07:00, -07
-			if len(layout) >= i+5 && layout[i:i+5] == stdNumTZ {
-				return layout[0:i], layout[i : i+5], layout[i+5:]
+			if len(layout) >= i+5 && layout[i:i+5] == "-0700" {
+				return layout[0:i], stdNumTZ, layout[i+5:]
 			}
-			if len(layout) >= i+6 && layout[i:i+6] == stdNumColonTZ {
-				return layout[0:i], layout[i : i+6], layout[i+6:]
+			if len(layout) >= i+6 && layout[i:i+6] == "-07:00" {
+				return layout[0:i], stdNumColonTZ, layout[i+6:]
 			}
-			if len(layout) >= i+3 && layout[i:i+3] == stdNumShortTZ {
-				return layout[0:i], layout[i : i+3], layout[i+3:]
+			if len(layout) >= i+3 && layout[i:i+3] == "-07" {
+				return layout[0:i], stdNumShortTZ, layout[i+3:]
 			}
 		case 'Z': // Z0700, Z07:00
-			if len(layout) >= i+5 && layout[i:i+5] == stdISO8601TZ {
-				return layout[0:i], layout[i : i+5], layout[i+5:]
+			if len(layout) >= i+5 && layout[i:i+5] == "Z0700" {
+				return layout[0:i], stdISO8601TZ, layout[i+5:]
 			}
-			if len(layout) >= i+6 && layout[i:i+6] == stdISO8601ColonTZ {
-				return layout[0:i], layout[i : i+6], layout[i+6:]
+			if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
+				return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
 			}
 		case '.': // .000 or .999 - repeated digits for fractional seconds.
 			if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
@@ -172,12 +189,17 @@ func nextStdChunk(layout string) (prefix, std, suffix string) {
 				}
 				// String of digits must end here - only fractional second is all digits.
 				if !isDigit(layout, j) {
-					return layout[0:i], layout[i:j], layout[j:]
+					std := stdFracSecond0
+					if layout[i+1] == '9' {
+						std = stdFracSecond9
+					}
+					std |= (j - (i + 1)) << stdArgShift
+					return layout[0:i], std, layout[j:]
 				}
 			}
 		}
 	}
-	return layout, "", ""
+	return layout, 0, ""
 }
 
 var longDayNames = []string{
@@ -259,27 +281,36 @@ func lookup(tab []string, val string) (int, string, error) {
 	return -1, val, errBad
 }
 
+// appendUint appends the decimal form of x to b and returns the result.
+// If x is a single-digit number and pad != 0, appendUint inserts the pad byte
+// before the digit.
 // Duplicates functionality in strconv, but avoids dependency.
-func itoa(x int) string {
+func appendUint(b []byte, x uint, pad byte) []byte {
+	if x < 10 {
+		if pad != 0 {
+			b = append(b, pad)
+		}
+		return append(b, byte('0'+x))
+	}
+	if x < 100 {
+		b = append(b, byte('0'+x/10))
+		b = append(b, byte('0'+x%10))
+		return b
+	}
+
 	var buf [32]byte
 	n := len(buf)
 	if x == 0 {
-		return "0"
-	}
-	u := uint(x)
-	if x < 0 {
-		u = -u
-	}
-	for u > 0 {
-		n--
-		buf[n] = byte(u%10 + '0')
-		u /= 10
+		return append(b, '0')
 	}
-	if x < 0 {
+	for x >= 10 {
 		n--
-		buf[n] = '-'
+		buf[n] = byte(x%10 + '0')
+		x /= 10
 	}
-	return string(buf[n:])
+	n--
+	buf[n] = byte(x + '0')
+	return append(b, buf[n:]...)
 }
 
 // Never printed, just needs to be non-nil for return by atoi.
@@ -292,7 +323,8 @@ func atoi(s string) (x int, err error) {
 		neg = true
 		s = s[1:]
 	}
-	x, rem, err := leadingInt(s)
+	q, rem, err := leadingInt(s)
+	x = int(q)
 	if err != nil || rem != "" {
 		return 0, atoiError
 	}
@@ -302,37 +334,30 @@ func atoi(s string) (x int, err error) {
 	return x, nil
 }
 
-func pad(i int, padding string) string {
-	s := itoa(i)
-	if i < 10 {
-		s = padding + s
+// formatNano appends a fractional second, as nanoseconds, to b
+// and returns the result.
+func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
+	u := nanosec
+	var buf [9]byte
+	for start := len(buf); start > 0; {
+		start--
+		buf[start] = byte(u%10 + '0')
+		u /= 10
 	}
-	return s
-}
-
-func zeroPad(i int) string { return pad(i, "0") }
 
-// formatNano formats a fractional second, as nanoseconds.
-func formatNano(nanosec, n int, trim bool) string {
-	// User might give us bad data. Make sure it's positive and in range.
-	// They'll get nonsense output but it will have the right format.
-	s := itoa(int(uint(nanosec) % 1e9))
-	// Zero pad left without fmt.
-	if len(s) < 9 {
-		s = "000000000"[:9-len(s)] + s
-	}
 	if n > 9 {
 		n = 9
 	}
 	if trim {
-		for n > 0 && s[n-1] == '0' {
+		for n > 0 && buf[n-1] == '0' {
 			n--
 		}
 		if n == 0 {
-			return ""
+			return b
 		}
 	}
-	return "." + s[:n]
+	b = append(b, '.')
+	return append(b, buf[:n]...)
 }
 
 // String returns the time formatted using the format string
@@ -341,16 +366,6 @@ func (t Time) String() string {
 	return t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
 }
 
-type buffer []byte
-
-func (b *buffer) WriteString(s string) {
-	*b = append(*b, s...)
-}
-
-func (b *buffer) String() string {
-	return string([]byte(*b))
-}
-
 // Format returns a textual representation of the time value formatted
 // according to layout.  The layout defines the format by showing the
 // representation of the standard time,
@@ -361,161 +376,172 @@ func (b *buffer) String() string {
 // definition of the standard time, see the documentation for ANSIC.
 func (t Time) Format(layout string) string {
 	var (
+		name, offset, abs = t.locabs()
+
 		year  int = -1
 		month Month
 		day   int
 		hour  int = -1
 		min   int
 		sec   int
-		b     buffer
+
+		b   []byte
+		buf [64]byte
 	)
+	max := len(layout) + 10
+	if max <= len(buf) {
+		b = buf[:0]
+	} else {
+		b = make([]byte, 0, max)
+	}
 	// Each iteration generates one std value.
-	for {
+	for layout != "" {
 		prefix, std, suffix := nextStdChunk(layout)
-		b.WriteString(prefix)
-		if std == "" {
+		if prefix != "" {
+			b = append(b, prefix...)
+		}
+		if std == 0 {
 			break
 		}
+		layout = suffix
 
 		// Compute year, month, day if needed.
-		if year < 0 {
-			// Jan 01 02 2006
-			if a, z := std[0], std[len(std)-1]; a == 'J' || a == 'j' || z == '1' || z == '2' || z == '6' {
-				year, month, day = t.Date()
-			}
+		if year < 0 && std&stdNeedDate != 0 {
+			year, month, day, _ = absDate(abs, true)
 		}
 
 		// Compute hour, minute, second if needed.
-		if hour < 0 {
-			// 03 04 05 15 pm
-			if z := std[len(std)-1]; z == '3' || z == '4' || z == '5' || z == 'm' || z == 'M' {
-				hour, min, sec = t.Clock()
-			}
+		if hour < 0 && std&stdNeedClock != 0 {
+			hour, min, sec = absClock(abs)
 		}
 
-		var p string
-		switch std {
+		switch std & stdMask {
 		case stdYear:
-			p = zeroPad(year % 100)
+			y := year
+			if y < 0 {
+				y = -y
+			}
+			b = appendUint(b, uint(y%100), '0')
 		case stdLongYear:
 			// Pad year to at least 4 digits.
-			p = itoa(year)
+			y := year
 			switch {
 			case year <= -1000:
-				// ok
+				b = append(b, '-')
+				y = -y
 			case year <= -100:
-				p = p[:1] + "0" + p[1:]
+				b = append(b, "-0"...)
+				y = -y
 			case year <= -10:
-				p = p[:1] + "00" + p[1:]
+				b = append(b, "-00"...)
+				y = -y
 			case year < 0:
-				p = p[:1] + "000" + p[1:]
+				b = append(b, "-000"...)
+				y = -y
 			case year < 10:
-				p = "000" + p
+				b = append(b, "000"...)
 			case year < 100:
-				p = "00" + p
+				b = append(b, "00"...)
 			case year < 1000:
-				p = "0" + p
+				b = append(b, '0')
 			}
+			b = appendUint(b, uint(y), 0)
 		case stdMonth:
-			p = month.String()[:3]
+			b = append(b, month.String()[:3]...)
 		case stdLongMonth:
-			p = month.String()
+			m := month.String()
+			b = append(b, m...)
 		case stdNumMonth:
-			p = itoa(int(month))
+			b = appendUint(b, uint(month), 0)
 		case stdZeroMonth:
-			p = zeroPad(int(month))
+			b = appendUint(b, uint(month), '0')
 		case stdWeekDay:
-			p = t.Weekday().String()[:3]
+			b = append(b, absWeekday(abs).String()[:3]...)
 		case stdLongWeekDay:
-			p = t.Weekday().String()
+			s := absWeekday(abs).String()
+			b = append(b, s...)
 		case stdDay:
-			p = itoa(day)
+			b = appendUint(b, uint(day), 0)
 		case stdUnderDay:
-			p = pad(day, " ")
+			b = appendUint(b, uint(day), ' ')
 		case stdZeroDay:
-			p = zeroPad(day)
+			b = appendUint(b, uint(day), '0')
 		case stdHour:
-			p = zeroPad(hour)
+			b = appendUint(b, uint(hour), '0')
 		case stdHour12:
 			// Noon is 12PM, midnight is 12AM.
 			hr := hour % 12
 			if hr == 0 {
 				hr = 12
 			}
-			p = itoa(hr)
+			b = appendUint(b, uint(hr), 0)
 		case stdZeroHour12:
 			// Noon is 12PM, midnight is 12AM.
 			hr := hour % 12
 			if hr == 0 {
 				hr = 12
 			}
-			p = zeroPad(hr)
+			b = appendUint(b, uint(hr), '0')
 		case stdMinute:
-			p = itoa(min)
+			b = appendUint(b, uint(min), 0)
 		case stdZeroMinute:
-			p = zeroPad(min)
+			b = appendUint(b, uint(min), '0')
 		case stdSecond:
-			p = itoa(sec)
+			b = appendUint(b, uint(sec), 0)
 		case stdZeroSecond:
-			p = zeroPad(sec)
+			b = appendUint(b, uint(sec), '0')
 		case stdPM:
 			if hour >= 12 {
-				p = "PM"
+				b = append(b, "PM"...)
 			} else {
-				p = "AM"
+				b = append(b, "AM"...)
 			}
 		case stdpm:
 			if hour >= 12 {
-				p = "pm"
+				b = append(b, "pm"...)
 			} else {
-				p = "am"
+				b = append(b, "am"...)
 			}
 		case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumColonTZ:
 			// Ugly special case.  We cheat and take the "Z" variants
 			// to mean "the time zone as formatted for ISO 8601".
-			_, offset := t.Zone()
-			if offset == 0 && std[0] == 'Z' {
-				p = "Z"
+			if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ) {
+				b = append(b, 'Z')
 				break
 			}
 			zone := offset / 60 // convert to minutes
 			if zone < 0 {
-				p = "-"
+				b = append(b, '-')
 				zone = -zone
 			} else {
-				p = "+"
+				b = append(b, '+')
 			}
-			p += zeroPad(zone / 60)
+			b = appendUint(b, uint(zone/60), '0')
 			if std == stdISO8601ColonTZ || std == stdNumColonTZ {
-				p += ":"
+				b = append(b, ':')
 			}
-			p += zeroPad(zone % 60)
+			b = appendUint(b, uint(zone%60), '0')
 		case stdTZ:
-			name, offset := t.Zone()
 			if name != "" {
-				p = name
-			} else {
-				// No time zone known for this time, but we must print one.
-				// Use the -0700 format.
-				zone := offset / 60 // convert to minutes
-				if zone < 0 {
-					p = "-"
-					zone = -zone
-				} else {
-					p = "+"
-				}
-				p += zeroPad(zone / 60)
-				p += zeroPad(zone % 60)
+				b = append(b, name...)
+				break
 			}
-		default:
-			if len(std) >= 2 && (std[0:2] == ".0" || std[0:2] == ".9") {
-				p = formatNano(t.Nanosecond(), len(std)-1, std[1] == '9')
+			// No time zone known for this time, but we must print one.
+			// Use the -0700 format.
+			zone := offset / 60 // convert to minutes
+			if zone < 0 {
+				b = append(b, '-')
+				zone = -zone
+			} else {
+				b = append(b, '+')
 			}
+			b = appendUint(b, uint(zone/60), '0')
+			b = appendUint(b, uint(zone%60), '0')
+		case stdFracSecond0, stdFracSecond9:
+			b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9)
 		}
-		b.WriteString(p)
-		layout = suffix
 	}
-	return b.String()
+	return string(b)
 }
 
 var errBad = errors.New("bad value for field") // placeholder not passed to user
@@ -585,14 +611,14 @@ func skip(value, prefix string) (string, error) {
 	for len(prefix) > 0 {
 		if prefix[0] == ' ' {
 			if len(value) > 0 && value[0] != ' ' {
-				return "", errBad
+				return value, errBad
 			}
 			prefix = cutspace(prefix)
 			value = cutspace(value)
 			continue
 		}
 		if len(value) == 0 || value[0] != prefix[0] {
-			return "", errBad
+			return value, errBad
 		}
 		prefix = prefix[1:]
 		value = value[1:]
@@ -611,10 +637,41 @@ func skip(value, prefix string) (string, error) {
 //
 // Elements omitted from the value are assumed to be zero or, when
 // zero is impossible, one, so parsing "3:04pm" returns the time
-// corresponding to Jan 1, year 0, 15:04:00 UTC.
+// corresponding to Jan 1, year 0, 15:04:00 UTC (note that because the year is
+// 0, this time is before the zero Time).
 // Years must be in the range 0000..9999. The day of the week is checked
 // for syntax but it is otherwise ignored.
+//
+// In the absence of a time zone indicator, Parse returns a time in UTC.
+//
+// When parsing a time with a zone offset like -0700, if the offset corresponds
+// to a time zone used by the current location (Local), then Parse uses that
+// location and zone in the returned time. Otherwise it records the time as
+// being in a fabricated location with time fixed at the given zone offset.
+//
+// When parsing a time with a zone abbreviation like MST, if the zone abbreviation
+// has a defined offset in the current location, then that offset is used.
+// The zone abbreviation "UTC" is recognized as UTC regardless of location.
+// 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
+// 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.
 func Parse(layout, value string) (Time, error) {
+	return parse(layout, value, UTC, Local)
+}
+
+// ParseInLocation is like Parse but differs in two important ways.
+// First, in the absence of time zone information, Parse interprets a time as UTC;
+// ParseInLocation interprets the time as in the given location.
+// Second, when given a zone offset or abbreviation, Parse tries to match it
+// against the Local location; ParseInLocation uses the given location.
+func ParseInLocation(layout, value string, loc *Location) (Time, error) {
+	return parse(layout, value, loc, loc)
+}
+
+func parse(layout, value string, defaultLocation, local *Location) (Time, error) {
 	alayout, avalue := layout, value
 	rangeErrString := "" // set if a value is out of range
 	amSet := false       // do we need to subtract 12 from the hour for midnight?
@@ -638,11 +695,12 @@ func Parse(layout, value string) (Time, error) {
 	for {
 		var err error
 		prefix, std, suffix := nextStdChunk(layout)
+		stdstr := layout[len(prefix) : len(layout)-len(suffix)]
 		value, err = skip(value, prefix)
 		if err != nil {
 			return Time{}, &ParseError{alayout, avalue, prefix, value, ""}
 		}
-		if len(std) == 0 {
+		if std == 0 {
 			if len(value) != 0 {
 				return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
 			}
@@ -650,7 +708,7 @@ func Parse(layout, value string) (Time, error) {
 		}
 		layout = suffix
 		var p string
-		switch std {
+		switch std & stdMask {
 		case stdYear:
 			if len(value) < 2 {
 				err = errBad
@@ -716,7 +774,8 @@ func Parse(layout, value string) (Time, error) {
 			// fractional second in the format?
 			if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
 				_, std, _ := nextStdChunk(layout)
-				if len(std) > 0 && std[0] == '.' && isDigit(std, 1) {
+				std &= stdMask
+				if std == stdFracSecond0 || std == stdFracSecond9 {
 					// Fractional second in the layout; proceed normally
 					break
 				}
@@ -756,7 +815,7 @@ func Parse(layout, value string) (Time, error) {
 				err = errBad
 			}
 		case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ:
-			if std[0] == 'Z' && len(value) >= 1 && value[0] == 'Z' {
+			if (std == stdISO8601TZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' {
 				value = value[1:]
 				z = UTC
 				break
@@ -824,21 +883,37 @@ func Parse(layout, value string) (Time, error) {
 			}
 			// It's a valid format.
 			zoneName = p
-		default:
-			if len(value) < len(std) {
+
+		case stdFracSecond0:
+			// stdFracSecond0 requires the exact number of digits as specified in
+			// the layout.
+			ndigit := 1 + (std >> stdArgShift)
+			if len(value) < ndigit {
 				err = errBad
 				break
 			}
-			if len(std) >= 2 && std[0:2] == ".0" {
-				nsec, rangeErrString, err = parseNanoseconds(value, len(std))
-				value = value[len(std):]
+			nsec, rangeErrString, err = parseNanoseconds(value, ndigit)
+			value = value[ndigit:]
+
+		case stdFracSecond9:
+			if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] {
+				// Fractional second omitted.
+				break
+			}
+			// Take any number of digits, even more than asked for,
+			// because it is what the stdSecond case would do.
+			i := 0
+			for i < 9 && i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' {
+				i++
 			}
+			nsec, rangeErrString, err = parseNanoseconds(value, 1+i)
+			value = value[1+i:]
 		}
 		if rangeErrString != "" {
-			return Time{}, &ParseError{alayout, avalue, std, value, ": " + rangeErrString + " out of range"}
+			return Time{}, &ParseError{alayout, avalue, stdstr, value, ": " + rangeErrString + " out of range"}
 		}
 		if err != nil {
-			return Time{}, &ParseError{alayout, avalue, std, value, ""}
+			return Time{}, &ParseError{alayout, avalue, stdstr, value, ""}
 		}
 	}
 	if pmSet && hour < 12 {
@@ -847,20 +922,19 @@ func Parse(layout, value string) (Time, error) {
 		hour = 0
 	}
 
-	// TODO: be more aggressive checking day?
 	if z != nil {
 		return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
 	}
 
-	t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
 	if zoneOffset != -1 {
+		t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
 		t.sec -= int64(zoneOffset)
 
 		// Look for local zone with the given offset.
 		// If that zone was in effect at the given time, use it.
-		name, offset, _, _, _ := Local.lookup(t.sec + internalToUnix)
+		name, offset, _, _, _ := local.lookup(t.sec + internalToUnix)
 		if offset == zoneOffset && (zoneName == "" || name == zoneName) {
-			t.loc = Local
+			t.loc = local
 			return t, nil
 		}
 
@@ -870,16 +944,14 @@ func Parse(layout, value string) (Time, error) {
 	}
 
 	if zoneName != "" {
+		t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
 		// Look for local zone with the given offset.
 		// If that zone was in effect at the given time, use it.
-		offset, _, ok := Local.lookupName(zoneName)
+		offset, _, ok := local.lookupName(zoneName, t.sec+internalToUnix)
 		if ok {
-			name, off, _, _, _ := Local.lookup(t.sec + internalToUnix - int64(offset))
-			if name == zoneName && off == offset {
-				t.sec -= int64(offset)
-				t.loc = Local
-				return t, nil
-			}
+			t.sec -= int64(offset)
+			t.loc = local
+			return t, nil
 		}
 
 		// Otherwise, create fake zone with unknown offset.
@@ -887,8 +959,8 @@ func Parse(layout, value string) (Time, error) {
 		return t, nil
 	}
 
-	// Otherwise, fall back to UTC.
-	return t, nil
+	// Otherwise, fall back to default.
+	return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
 }
 
 func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
@@ -896,8 +968,7 @@ func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string,
 		err = errBad
 		return
 	}
-	ns, err = atoi(value[1:nbytes])
-	if err != nil {
+	if ns, err = atoi(value[1:nbytes]); err != nil {
 		return
 	}
 	if ns < 0 || 1e9 <= ns {
@@ -917,18 +988,18 @@ func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string,
 var errLeadingInt = errors.New("time: bad [0-9]*") // never printed
 
 // leadingInt consumes the leading [0-9]* from s.
-func leadingInt(s string) (x int, rem string, err error) {
+func leadingInt(s string) (x int64, rem string, err error) {
 	i := 0
 	for ; i < len(s); i++ {
 		c := s[i]
 		if c < '0' || c > '9' {
 			break
 		}
-		if x >= (1<<31-10)/10 {
+		if x >= (1<<63-10)/10 {
 			// overflow
 			return 0, "", errLeadingInt
 		}
-		x = x*10 + int(c) - '0'
+		x = x*10 + int64(c) - '0'
 	}
 	return x, s[i:], nil
 }
@@ -973,7 +1044,7 @@ func ParseDuration(s string) (Duration, error) {
 	for s != "" {
 		g := float64(0) // this element of the sequence
 
-		var x int
+		var x int64
 		var err error
 
 		// The next character must be [0-9.]
diff --git a/src/pkg/time/internal_test.go b/src/pkg/time/internal_test.go
index b753896..918a9f3 100644
--- a/src/pkg/time/internal_test.go
+++ b/src/pkg/time/internal_test.go
@@ -6,7 +6,7 @@ package time
 
 func init() {
 	// force US/Pacific for time zone tests
-	localOnce.Do(initTestingZone)
+	ForceUSPacificForTesting()
 }
 
 var Interrupt = interrupt
diff --git a/src/pkg/time/sleep.go b/src/pkg/time/sleep.go
index 27820b0..591fa27 100644
--- a/src/pkg/time/sleep.go
+++ b/src/pkg/time/sleep.go
@@ -18,10 +18,25 @@ type runtimeTimer struct {
 	i      int32
 	when   int64
 	period int64
-	f      func(int64, interface{})
+	f      func(int64, interface{}) // NOTE: must not be closure
 	arg    interface{}
 }
 
+// when is a helper function for setting the 'when' field of a runtimeTimer.
+// It returns what the time will be, in nanoseconds, Duration d in the future.
+// If d is negative, it is ignored.  If the returned value would be less than
+// zero because of an overflow, MaxInt64 is returned.
+func when(d Duration) int64 {
+	if d <= 0 {
+		return nano()
+	}
+	t := nano() + int64(d)
+	if t < 0 {
+		t = 1<<63 - 1 // math.MaxInt64
+	}
+	return t
+}
+
 func startTimer(*runtimeTimer)
 func stopTimer(*runtimeTimer) bool
 
@@ -35,8 +50,10 @@ type Timer struct {
 
 // Stop prevents the Timer from firing.
 // It returns true if the call stops the timer, false if the timer has already
-// expired or stopped.
-func (t *Timer) Stop() (ok bool) {
+// expired or been stopped.
+// Stop does not close the channel, to prevent a read from the channel succeeding
+// incorrectly.
+func (t *Timer) Stop() bool {
 	return stopTimer(&t.r)
 }
 
@@ -47,7 +64,7 @@ func NewTimer(d Duration) *Timer {
 	t := &Timer{
 		C: c,
 		r: runtimeTimer{
-			when: nano() + int64(d),
+			when: when(d),
 			f:    sendTime,
 			arg:  c,
 		},
@@ -56,6 +73,17 @@ func NewTimer(d Duration) *Timer {
 	return t
 }
 
+// Reset changes the timer to expire after duration d.
+// 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 {
+	w := when(d)
+	active := stopTimer(&t.r)
+	t.r.when = w
+	startTimer(&t.r)
+	return active
+}
+
 func sendTime(now int64, c interface{}) {
 	// Non-blocking send of time on c.
 	// Used in NewTimer, it cannot block anyway (buffer).
@@ -81,7 +109,7 @@ func After(d Duration) <-chan Time {
 func AfterFunc(d Duration, f func()) *Timer {
 	t := &Timer{
 		r: runtimeTimer{
-			when: nano() + int64(d),
+			when: when(d),
 			f:    goFunc,
 			arg:  f,
 		},
diff --git a/src/pkg/time/sleep_test.go b/src/pkg/time/sleep_test.go
index e05773d..9908e22 100644
--- a/src/pkg/time/sleep_test.go
+++ b/src/pkg/time/sleep_test.go
@@ -54,9 +54,10 @@ func TestAfterStress(t *testing.T) {
 	go func() {
 		for atomic.LoadUint32(&stop) == 0 {
 			runtime.GC()
-			// Need to yield, because otherwise
-			// the main goroutine will never set the stop flag.
-			runtime.Gosched()
+			// Yield so that the OS can wake up the timer thread,
+			// so that it can generate channel sends for the main goroutine,
+			// which will eventually set stop = 1 for us.
+			Sleep(Nanosecond)
 		}
 	}()
 	c := Tick(1)
@@ -245,3 +246,70 @@ func TestSleepZeroDeadlock(t *testing.T) {
 	}
 	<-c
 }
+
+func testReset(d Duration) error {
+	t0 := NewTimer(2 * d)
+	Sleep(d)
+	if t0.Reset(3*d) != true {
+		return errors.New("resetting unfired timer returned false")
+	}
+	Sleep(2 * d)
+	select {
+	case <-t0.C:
+		return errors.New("timer fired early")
+	default:
+	}
+	Sleep(2 * d)
+	select {
+	case <-t0.C:
+	default:
+		return errors.New("reset timer did not fire")
+	}
+
+	if t0.Reset(50*Millisecond) != false {
+		return errors.New("resetting expired timer returned true")
+	}
+	return nil
+}
+
+func TestReset(t *testing.T) {
+	// We try to run this test with increasingly larger multiples
+	// until one works so slow, loaded hardware isn't as flaky,
+	// but without slowing down fast machines unnecessarily.
+	const unit = 25 * Millisecond
+	tries := []Duration{
+		1 * unit,
+		3 * unit,
+		7 * unit,
+		15 * unit,
+	}
+	var err error
+	for _, d := range tries {
+		err = testReset(d)
+		if err == nil {
+			t.Logf("passed using duration %v", d)
+			return
+		}
+	}
+	t.Error(err)
+}
+
+// Test that sleeping for an interval so large it overflows does not
+// result in a short sleep duration.
+func TestOverflowSleep(t *testing.T) {
+	const timeout = 25 * Millisecond
+	const big = Duration(int64(1<<63 - 1))
+	select {
+	case <-After(big):
+		t.Fatalf("big timeout fired")
+	case <-After(timeout):
+		// OK
+	}
+	const neg = Duration(-1 << 63)
+	select {
+	case <-After(neg):
+		// OK
+	case <-After(timeout):
+		t.Fatalf("negative timeout didn't fire")
+	}
+}
diff --git a/src/pkg/time/tick.go b/src/pkg/time/tick.go
index 8c6b9bc..b92c339 100644
--- a/src/pkg/time/tick.go
+++ b/src/pkg/time/tick.go
@@ -6,7 +6,7 @@ package time
 
 import "errors"
 
-// A Ticker holds a synchronous channel that delivers `ticks' of a clock
+// A Ticker holds a channel that delivers `ticks' of a clock
 // at intervals.
 type Ticker struct {
 	C <-chan Time // The channel on which the ticks are delivered.
@@ -39,6 +39,8 @@ func NewTicker(d Duration) *Ticker {
 }
 
 // Stop turns off a ticker.  After Stop, no more ticks will be sent.
+// Stop does not close the channel, to prevent a read from the channel succeeding
+// incorrectly.
 func (t *Ticker) Stop() {
 	stopTimer(&t.r)
 }
diff --git a/src/pkg/time/time.go b/src/pkg/time/time.go
index 2461dac..d291672 100644
--- a/src/pkg/time/time.go
+++ b/src/pkg/time/time.go
@@ -241,10 +241,10 @@ func (t Time) IsZero() bool {
 // It is called when computing a presentation property like Month or Hour.
 func (t Time) abs() uint64 {
 	l := t.loc
-	if l == nil {
-		l = &utcLoc
+	// Avoid function calls when possible.
+	if l == nil || l == &localLoc {
+		l = l.get()
 	}
-	// Avoid function call if we hit the local time cache.
 	sec := t.sec + internalToUnix
 	if l != &utcLoc {
 		if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
@@ -257,6 +257,30 @@ func (t Time) abs() uint64 {
 	return uint64(sec + (unixToInternal + internalToAbsolute))
 }
 
+// locabs is a combination of the Zone and abs methods,
+// extracting both return values from a single zone lookup.
+func (t Time) locabs() (name string, offset int, abs uint64) {
+	l := t.loc
+	if l == nil || l == &localLoc {
+		l = l.get()
+	}
+	// Avoid function call if we hit the local time cache.
+	sec := t.sec + internalToUnix
+	if l != &utcLoc {
+		if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
+			name = l.cacheZone.name
+			offset = l.cacheZone.offset
+		} else {
+			name, offset, _, _, _ = l.lookup(sec)
+		}
+		sec += int64(offset)
+	} else {
+		name = "UTC"
+	}
+	abs = uint64(sec + (unixToInternal + internalToAbsolute))
+	return
+}
+
 // Date returns the year, month, and day in which t occurs.
 func (t Time) Date() (year int, month Month, day int) {
 	year, month, day, _ = t.date(true)
@@ -283,8 +307,13 @@ func (t Time) Day() int {
 
 // Weekday returns the day of the week specified by t.
 func (t Time) Weekday() Weekday {
+	return absWeekday(t.abs())
+}
+
+// absWeekday is like Weekday but operates on an absolute time.
+func absWeekday(abs uint64) Weekday {
 	// January 1 of the absolute year, like January 1 of 2001, was a Monday.
-	sec := (t.abs() + uint64(Monday)*secondsPerDay) % secondsPerWeek
+	sec := (abs + uint64(Monday)*secondsPerDay) % secondsPerWeek
 	return Weekday(int(sec) / secondsPerDay)
 }
 
@@ -349,7 +378,12 @@ func (t Time) ISOWeek() (year, week int) {
 
 // Clock returns the hour, minute, and second within the day specified by t.
 func (t Time) Clock() (hour, min, sec int) {
-	sec = int(t.abs() % secondsPerDay)
+	return absClock(t.abs())
+}
+
+// absClock is like clock but operates on an absolute time.
+func absClock(abs uint64) (hour, min, sec int) {
+	sec = int(abs % secondsPerDay)
 	hour = sec / secondsPerHour
 	sec -= hour * secondsPerHour
 	min = sec / secondsPerMinute
@@ -378,6 +412,13 @@ func (t Time) Nanosecond() int {
 	return int(t.nsec)
 }
 
+// YearDay returns the day of the year specified by t, in the range [1,365] for non-leap years,
+// and [1,366] in leap years.
+func (t Time) YearDay() int {
+	_, _, _, yday := t.date(false)
+	return yday + 1
+}
+
 // A Duration represents the elapsed time between two instants
 // as an int64 nanosecond count.  The representation limits the
 // largest representable duration to approximately 290 years.
@@ -607,11 +648,16 @@ const (
 	days1970To2001   = 31*365 + 8
 )
 
-// date computes the year and, only when full=true,
+// date computes the year, day of year, and when full=true,
 // the month and day in which t occurs.
 func (t Time) date(full bool) (year int, month Month, day int, yday int) {
+	return absDate(t.abs(), full)
+}
+
+// absDate is like date but operates on an absolute time.
+func absDate(abs uint64, full bool) (year int, month Month, day int, yday int) {
 	// Split into time and day.
-	d := t.abs() / secondsPerDay
+	d := abs / secondsPerDay
 
 	// Account for 400 year cycles.
 	n := d / daysPer400Years
@@ -987,3 +1033,116 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T
 
 	return Time{unix + unixToInternal, int32(nsec), loc}
 }
+
+// Truncate returns the result of rounding t down to a multiple of d (since the zero time).
+// If d <= 0, Truncate returns t unchanged.
+func (t Time) Truncate(d Duration) Time {
+	if d <= 0 {
+		return t
+	}
+	_, r := div(t, d)
+	return t.Add(-r)
+}
+
+// Round returns the result of rounding t to the nearest multiple of d (since the zero time).
+// The rounding behavior for halfway values is to round up.
+// If d <= 0, Round returns t unchanged.
+func (t Time) Round(d Duration) Time {
+	if d <= 0 {
+		return t
+	}
+	_, r := div(t, d)
+	if r+r < d {
+		return t.Add(-r)
+	}
+	return t.Add(d - r)
+}
+
+// div divides t by d and returns the quotient parity and remainder.
+// We don't use the quotient parity anymore (round half up instead of round to even)
+// but it's still here in case we change our minds.
+func div(t Time, d Duration) (qmod2 int, r Duration) {
+	neg := false
+	if t.sec < 0 {
+		// Operate on absolute value.
+		neg = true
+		t.sec = -t.sec
+		t.nsec = -t.nsec
+		if t.nsec < 0 {
+			t.nsec += 1e9
+			t.sec-- // t.sec >= 1 before the -- so safe
+		}
+	}
+
+	switch {
+	// Special case: 2d divides 1 second.
+	case d < Second && Second%(d+d) == 0:
+		qmod2 = int(t.nsec/int32(d)) & 1
+		r = Duration(t.nsec % int32(d))
+
+	// Special case: d is a multiple of 1 second.
+	case d%Second == 0:
+		d1 := int64(d / Second)
+		qmod2 = int(t.sec/d1) & 1
+		r = Duration(t.sec%d1)*Second + Duration(t.nsec)
+
+	// General case.
+	// This could be faster if more cleverness were applied,
+	// but it's really only here to avoid special case restrictions in the API.
+	// No one will care about these cases.
+	default:
+		// Compute nanoseconds as 128-bit number.
+		sec := uint64(t.sec)
+		tmp := (sec >> 32) * 1e9
+		u1 := tmp >> 32
+		u0 := tmp << 32
+		tmp = uint64(sec&0xFFFFFFFF) * 1e9
+		u0x, u0 := u0, u0+tmp
+		if u0 < u0x {
+			u1++
+		}
+		u0x, u0 = u0, u0+uint64(t.nsec)
+		if u0 < u0x {
+			u1++
+		}
+
+		// Compute remainder by subtracting r<<k for decreasing k.
+		// Quotient parity is whether we subtract on last round.
+		d1 := uint64(d)
+		for d1>>63 != 1 {
+			d1 <<= 1
+		}
+		d0 := uint64(0)
+		for {
+			qmod2 = 0
+			if u1 > d1 || u1 == d1 && u0 >= d0 {
+				// subtract
+				qmod2 = 1
+				u0x, u0 = u0, u0-d0
+				if u0 > u0x {
+					u1--
+				}
+				u1 -= d1
+			}
+			if d1 == 0 && d0 == uint64(d) {
+				break
+			}
+			d0 >>= 1
+			d0 |= (d1 & 1) << 63
+			d1 >>= 1
+		}
+		r = Duration(u0)
+	}
+
+	if neg && r != 0 {
+		// If input was negative and not an exact multiple of d, we computed q, r such that
+		//	q*d + r = -t
+		// But the right answers are given by -(q-1), d-r:
+		//	q*d + r = -t
+		//	-q*d - r = t
+		//	-(q-1)*d + (d - r) = t
+		qmod2 ^= 1
+		r = d - r
+	}
+	return
+}
diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go
index 2804780..4b268f7 100644
--- a/src/pkg/time/time_test.go
+++ b/src/pkg/time/time_test.go
@@ -9,6 +9,7 @@ import (
 	"encoding/gob"
 	"encoding/json"
 	"fmt"
+	"math/big"
 	"math/rand"
 	"strconv"
 	"strings"
@@ -192,6 +193,184 @@ func TestNanosecondsToUTCAndBack(t *testing.T) {
 	}
 }
 
+// The time routines provide no way to get absolute time
+// (seconds since zero), but we need it to compute the right
+// answer for bizarre roundings like "to the nearest 3 ns".
+// Compute as t - year1 = (t - 1970) + (1970 - 2001) + (2001 - 1).
+// t - 1970 is returned by Unix and Nanosecond.
+// 1970 - 2001 is -(31*365+8)*86400 = -978307200 seconds.
+// 2001 - 1 is 2000*365.2425*86400 = 63113904000 seconds.
+const unixToZero = -978307200 + 63113904000
+
+// abs returns the absolute time stored in t, as seconds and nanoseconds.
+func abs(t Time) (sec, nsec int64) {
+	unix := t.Unix()
+	nano := t.Nanosecond()
+	return unix + unixToZero, int64(nano)
+}
+
+// absString returns abs as a decimal string.
+func absString(t Time) string {
+	sec, nsec := abs(t)
+	if sec < 0 {
+		sec = -sec
+		nsec = -nsec
+		if nsec < 0 {
+			nsec += 1e9
+			sec--
+		}
+		return fmt.Sprintf("-%d%09d", sec, nsec)
+	}
+	return fmt.Sprintf("%d%09d", sec, nsec)
+}
+
+var truncateRoundTests = []struct {
+	t Time
+	d Duration
+}{
+	{Date(-1, January, 1, 12, 15, 30, 5e8, UTC), 3},
+	{Date(-1, January, 1, 12, 15, 31, 5e8, UTC), 3},
+	{Date(2012, January, 1, 12, 15, 30, 5e8, UTC), Second},
+	{Date(2012, January, 1, 12, 15, 31, 5e8, UTC), Second},
+}
+
+func TestTruncateRound(t *testing.T) {
+	var (
+		bsec  = new(big.Int)
+		bnsec = new(big.Int)
+		bd    = new(big.Int)
+		bt    = new(big.Int)
+		br    = new(big.Int)
+		bq    = new(big.Int)
+		b1e9  = new(big.Int)
+	)
+
+	b1e9.SetInt64(1e9)
+
+	testOne := func(ti, tns, di int64) bool {
+		t0 := Unix(ti, int64(tns)).UTC()
+		d := Duration(di)
+		if d < 0 {
+			d = -d
+		}
+		if d <= 0 {
+			d = 1
+		}
+
+		// Compute bt = absolute nanoseconds.
+		sec, nsec := abs(t0)
+		bsec.SetInt64(sec)
+		bnsec.SetInt64(nsec)
+		bt.Mul(bsec, b1e9)
+		bt.Add(bt, bnsec)
+
+		// Compute quotient and remainder mod d.
+		bd.SetInt64(int64(d))
+		bq.DivMod(bt, bd, br)
+
+		// To truncate, subtract remainder.
+		// br is < d, so it fits in an int64.
+		r := br.Int64()
+		t1 := t0.Add(-Duration(r))
+
+		// Check that time.Truncate works.
+		if trunc := t0.Truncate(d); trunc != t1 {
+			t.Errorf("Time.Truncate(%s, %s) = %s, want %s\n"+
+				"%v trunc %v =\n%v want\n%v",
+				t0.Format(RFC3339Nano), d, trunc, t1.Format(RFC3339Nano),
+				absString(t0), int64(d), absString(trunc), absString(t1))
+			return false
+		}
+
+		// To round, add d back if remainder r > d/2 or r == exactly d/2.
+		// The commented out code would round half to even instead of up,
+		// but that makes it time-zone dependent, which is a bit strange.
+		if r > int64(d)/2 || r+r == int64(d) /*&& bq.Bit(0) == 1*/ {
+			t1 = t1.Add(Duration(d))
+		}
+
+		// Check that time.Round works.
+		if rnd := t0.Round(d); rnd != t1 {
+			t.Errorf("Time.Round(%s, %s) = %s, want %s\n"+
+				"%v round %v =\n%v want\n%v",
+				t0.Format(RFC3339Nano), d, rnd, t1.Format(RFC3339Nano),
+				absString(t0), int64(d), absString(rnd), absString(t1))
+			return false
+		}
+		return true
+	}
+
+	// manual test cases
+	for _, tt := range truncateRoundTests {
+		testOne(tt.t.Unix(), int64(tt.t.Nanosecond()), int64(tt.d))
+	}
+
+	// exhaustive near 0
+	for i := 0; i < 100; i++ {
+		for j := 1; j < 100; j++ {
+			testOne(unixToZero, int64(i), int64(j))
+			testOne(unixToZero, -int64(i), int64(j))
+			if t.Failed() {
+				return
+			}
+		}
+	}
+
+	if t.Failed() {
+		return
+	}
+
+	// randomly generated test cases
+	cfg := &quick.Config{MaxCount: 100000}
+	if testing.Short() {
+		cfg.MaxCount = 1000
+	}
+
+	// divisors of Second
+	f1 := func(ti int64, tns int32, logdi int32) bool {
+		d := Duration(1)
+		a, b := uint(logdi%9), (logdi>>16)%9
+		d <<= a
+		for i := 0; i < int(b); i++ {
+			d *= 5
+		}
+		return testOne(ti, int64(tns), int64(d))
+	}
+	quick.Check(f1, cfg)
+
+	// multiples of Second
+	f2 := func(ti int64, tns int32, di int32) bool {
+		d := Duration(di) * Second
+		if d < 0 {
+			d = -d
+		}
+		return testOne(ti, int64(tns), int64(d))
+	}
+	quick.Check(f2, cfg)
+
+	// halfway cases
+	f3 := func(tns, di int64) bool {
+		di &= 0xfffffffe
+		if di == 0 {
+			di = 2
+		}
+		tns -= tns % di
+		if tns < 0 {
+			tns += di / 2
+		} else {
+			tns -= di / 2
+		}
+		return testOne(0, tns, di)
+	}
+	quick.Check(f3, cfg)
+
+	// full generality
+	f4 := func(ti int64, tns int32, di int64) bool {
+		return testOne(ti, int64(tns), di)
+	}
+	quick.Check(f4, cfg)
+}
+
 type TimeFormatTest struct {
 	time           Time
 	formattedValue string
@@ -289,7 +468,7 @@ type ParseTest struct {
 	value      string
 	hasTZ      bool // contains a time zone
 	hasWD      bool // contains a weekday
-	yearSign   int  // sign of year
+	yearSign   int  // sign of year, -1 indicates the year is not present in the format
 	fracDigits int  // number of digits of fractional second
 }
 
@@ -299,6 +478,7 @@ var parseTests = []ParseTest{
 	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
 	{"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57 PST", true, true, 1, 0},
 	{"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57 PST", true, true, 1, 0},
+	{"RFC1123", RFC1123, "Thu, 04 Feb 2010 22:00:57 PDT", true, true, 1, 0},
 	{"RFC1123Z", RFC1123Z, "Thu, 04 Feb 2010 21:00:57 -0800", true, true, 1, 0},
 	{"RFC3339", RFC3339, "2010-02-04T21:00:57-08:00", true, false, 1, 0},
 	{"custom: \"2006-01-02 15:04:05-07\"", "2006-01-02 15:04:05-07", "2010-02-04 21:00:57-08", true, false, 1, 0},
@@ -324,6 +504,23 @@ var parseTests = []ParseTest{
 	// Leading zeros in other places should not be taken as fractional seconds.
 	{"zero1", "2006.01.02.15.04.05.0", "2010.02.04.21.00.57.0", false, false, 1, 1},
 	{"zero2", "2006.01.02.15.04.05.00", "2010.02.04.21.00.57.01", false, false, 1, 2},
+
+	// Accept any number of fractional second digits (including none) for .999...
+	// In Go 1, .999... was completely ignored in the format, meaning the first two
+	// cases would succeed, but the next four would not. Go 1.1 accepts all six.
+	{"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
+	{"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
+	{"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
+	{"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
+	{"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
+	{"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
+
+	// issue 4502.
+	{"", StampNano, "Feb  4 21:00:57.012345678", false, false, -1, 9},
+	{"", "Jan _2 15:04:05.999", "Feb  4 21:00:57.012300000", false, false, -1, 4},
+	{"", "Jan _2 15:04:05.999", "Feb  4 21:00:57.012345678", false, false, -1, 9},
+	{"", "Jan _2 15:04:05.999999999", "Feb  4 21:00:57.0123", false, false, -1, 4},
+	{"", "Jan _2 15:04:05.999999999", "Feb  4 21:00:57.012345678", false, false, -1, 9},
 }
 
 func TestParse(t *testing.T) {
@@ -337,6 +534,42 @@ func TestParse(t *testing.T) {
 	}
 }
 
+func TestParseInSydney(t *testing.T) {
+	loc, err := LoadLocation("Australia/Sydney")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Check that Parse (and ParseInLocation) understand
+	// that Feb EST and Aug EST are different time zones in Sydney
+	// even though both are called EST.
+	t1, err := ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 EST", loc)
+	if err != nil {
+		t.Fatal(err)
+	}
+	t2 := Date(2013, February, 1, 00, 00, 00, 0, loc)
+	if t1 != t2 {
+		t.Fatalf("ParseInLocation(Feb 01 2013 EST, Sydney) = %v, want %v", t1, t2)
+	}
+	_, offset := t1.Zone()
+	if offset != 11*60*60 {
+		t.Fatalf("ParseInLocation(Feb 01 2013 EST, Sydney).Zone = _, %d, want _, %d", offset, 11*60*60)
+	}
+
+	t1, err = ParseInLocation("Jan 02 2006 MST", "Aug 01 2013 EST", loc)
+	if err != nil {
+		t.Fatal(err)
+	}
+	t2 = Date(2013, August, 1, 00, 00, 00, 0, loc)
+	if t1 != t2 {
+		t.Fatalf("ParseInLocation(Aug 01 2013 EST, Sydney) = %v, want %v", t1, t2)
+	}
+	_, offset = t1.Zone()
+	if offset != 10*60*60 {
+		t.Fatalf("ParseInLocation(Aug 01 2013 EST, Sydney).Zone = _, %d, want _, %d", offset, 10*60*60)
+	}
+}
+
 var rubyTests = []ParseTest{
 	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
 	// Ignore the time zone in the test. If it parses, it'll be OK.
@@ -359,7 +592,7 @@ func TestRubyParse(t *testing.T) {
 
 func checkTime(time Time, test *ParseTest, t *testing.T) {
 	// The time should be Thu Feb  4 21:00:57 PST 2010
-	if test.yearSign*time.Year() != 2010 {
+	if test.yearSign >= 0 && test.yearSign*time.Year() != 2010 {
 		t.Errorf("%s: bad year: %d not %d", test.name, time.Year(), 2010)
 	}
 	if time.Month() != February {
@@ -440,6 +673,14 @@ var parseErrorTests = []ParseErrorTest{
 	{"Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 23:00:59x01 2010", "cannot parse"},
 	{"Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 23:00:59.xxx 2010", "cannot parse"},
 	{"Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 23:00:59.-123 2010", "fractional second out of range"},
+	// issue 4502. StampNano requires exactly 9 digits of precision.
+	{StampNano, "Dec  7 11:22:01.000000", `cannot parse ".000000" as ".000000000"`},
+	{StampNano, "Dec  7 11:22:01.0000000000", "extra text: 0"},
+	// issue 4493. Helpful errors.
+	{RFC3339, "2006-01-02T15:04:05Z07:00", `parsing time "2006-01-02T15:04:05Z07:00": extra text: 07:00`},
+	{RFC3339, "2006-01-02T15:04_abc", `parsing time "2006-01-02T15:04_abc" as "2006-01-02T15:04:05Z07:00": cannot parse "_abc" as ":"`},
+	{RFC3339, "2006-01-02T15:04:05_abc", `parsing time "2006-01-02T15:04:05_abc" as "2006-01-02T15:04:05Z07:00": cannot parse "_abc" as "Z07:00"`},
+	{RFC3339, "2006-01-02T15:04:05Z_abc", `parsing time "2006-01-02T15:04:05Z_abc": extra text: _abc`},
 }
 
 func TestParseErrors(t *testing.T) {
@@ -601,6 +842,103 @@ func TestISOWeek(t *testing.T) {
 	}
 }
 
+type YearDayTest struct {
+	year, month, day int
+	yday             int
+}
+
+// Test YearDay in several different scenarios
+// and corner cases
+var yearDayTests = []YearDayTest{
+	// Non-leap-year tests
+	{2007, 1, 1, 1},
+	{2007, 1, 15, 15},
+	{2007, 2, 1, 32},
+	{2007, 2, 15, 46},
+	{2007, 3, 1, 60},
+	{2007, 3, 15, 74},
+	{2007, 4, 1, 91},
+	{2007, 12, 31, 365},
+
+	// Leap-year tests
+	{2008, 1, 1, 1},
+	{2008, 1, 15, 15},
+	{2008, 2, 1, 32},
+	{2008, 2, 15, 46},
+	{2008, 3, 1, 61},
+	{2008, 3, 15, 75},
+	{2008, 4, 1, 92},
+	{2008, 12, 31, 366},
+
+	// Looks like leap-year (but isn't) tests
+	{1900, 1, 1, 1},
+	{1900, 1, 15, 15},
+	{1900, 2, 1, 32},
+	{1900, 2, 15, 46},
+	{1900, 3, 1, 60},
+	{1900, 3, 15, 74},
+	{1900, 4, 1, 91},
+	{1900, 12, 31, 365},
+
+	// Year one tests (non-leap)
+	{1, 1, 1, 1},
+	{1, 1, 15, 15},
+	{1, 2, 1, 32},
+	{1, 2, 15, 46},
+	{1, 3, 1, 60},
+	{1, 3, 15, 74},
+	{1, 4, 1, 91},
+	{1, 12, 31, 365},
+
+	// Year minus one tests (non-leap)
+	{-1, 1, 1, 1},
+	{-1, 1, 15, 15},
+	{-1, 2, 1, 32},
+	{-1, 2, 15, 46},
+	{-1, 3, 1, 60},
+	{-1, 3, 15, 74},
+	{-1, 4, 1, 91},
+	{-1, 12, 31, 365},
+
+	// 400 BC tests (leap-year)
+	{-400, 1, 1, 1},
+	{-400, 1, 15, 15},
+	{-400, 2, 1, 32},
+	{-400, 2, 15, 46},
+	{-400, 3, 1, 61},
+	{-400, 3, 15, 75},
+	{-400, 4, 1, 92},
+	{-400, 12, 31, 366},
+
+	// Special Cases
+
+	// Gregorian calendar change (no effect)
+	{1582, 10, 4, 277},
+	{1582, 10, 15, 288},
+}
+
+// Check to see if YearDay is location sensitive
+var yearDayLocations = []*Location{
+	FixedZone("UTC-8", -8*60*60),
+	FixedZone("UTC-4", -4*60*60),
+	UTC,
+	FixedZone("UTC+4", 4*60*60),
+	FixedZone("UTC+8", 8*60*60),
+}
+
+func TestYearDay(t *testing.T) {
+	for _, loc := range yearDayLocations {
+		for _, ydt := range yearDayTests {
+			dt := Date(ydt.year, Month(ydt.month), ydt.day, 0, 0, 0, 0, loc)
+			yday := dt.YearDay()
+			if yday != ydt.yday {
+				t.Errorf("got %d, expected %d for %d-%02d-%02d in %v",
+					yday, ydt.yday, ydt.year, ydt.month, ydt.day, loc)
+			}
+		}
+	}
+}
+
 var durationTests = []struct {
 	str string
 	d   Duration
@@ -741,7 +1079,7 @@ var gobTests = []Time{
 	Date(0, 1, 2, 3, 4, 5, 6, UTC),
 	Date(7, 8, 9, 10, 11, 12, 13, FixedZone("", 0)),
 	Unix(81985467080890095, 0x76543210), // Time.sec: 0x0123456789ABCDEF
-	Time{},                              // nil location
+	{}, // nil location
 	Date(1, 2, 3, 4, 5, 6, 7, FixedZone("", 32767*60)),
 	Date(1, 2, 3, 4, 5, 6, 7, FixedZone("", -32768*60)),
 }
@@ -805,7 +1143,7 @@ var jsonTests = []struct {
 	time Time
 	json string
 }{
-	{Date(9999, 4, 12, 23, 20, 50, .52*1e9, UTC), `"9999-04-12T23:20:50.52Z"`},
+	{Date(9999, 4, 12, 23, 20, 50, 520*1e6, UTC), `"9999-04-12T23:20:50.52Z"`},
 	{Date(1996, 12, 19, 16, 39, 57, 0, Local), `"1996-12-19T16:39:57-08:00"`},
 	{Date(0, 1, 1, 0, 0, 0, 1, FixedZone("", 1*60)), `"0000-01-01T00:00:00.000000001+00:01"`},
 }
@@ -892,6 +1230,8 @@ var parseDurationTests = []struct {
 	{"-2m3.4s", true, -(2*Minute + 3*Second + 400*Millisecond)},
 	{"1h2m3s4ms5us6ns", true, 1*Hour + 2*Minute + 3*Second + 4*Millisecond + 5*Microsecond + 6*Nanosecond},
 	{"39h9m14.425s", true, 39*Hour + 9*Minute + 14*Second + 425*Millisecond},
+	// large value
+	{"52763797000ns", true, 52763797000 * Nanosecond},
 
 	// errors
 	{"", false, 0},
@@ -928,16 +1268,86 @@ func TestParseDurationRoundTrip(t *testing.T) {
 	}
 }
 
+// golang.org/issue/4622
+func TestLocationRace(t *testing.T) {
+	ResetLocalOnceForTest() // reset the Once to trigger the race
+
+	c := make(chan string, 1)
+	go func() {
+		c <- Now().String()
+	}()
+	Now().String()
+	<-c
+	Sleep(100 * Millisecond)
+
+	// Back to Los Angeles for subsequent tests:
+	ForceUSPacificForTesting()
+}
+
+var (
+	t Time
+	u int64
+)
+
+var mallocTest = []struct {
+	count int
+	desc  string
+	fn    func()
+}{
+	{0, `time.Now()`, func() { t = Now() }},
+	{0, `time.Now().UnixNano()`, func() { u = Now().UnixNano() }},
+}
+
+func TestCountMallocs(t *testing.T) {
+	for _, mt := range mallocTest {
+		allocs := int(testing.AllocsPerRun(100, mt.fn))
+		if allocs > mt.count {
+			t.Errorf("%s: %d allocs, want %d", mt.desc, allocs, mt.count)
+		}
+	}
+}
+
+func TestLoadFixed(t *testing.T) {
+	// Issue 4064: handle locations without any zone transitions.
+	loc, err := LoadLocation("Etc/GMT+1")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// The tzdata name Etc/GMT+1 uses "east is negative",
+	// but Go and most other systems use "east is positive".
+	// So GMT+1 corresponds to -3600 in the Go zone, not +3600.
+	name, offset := Now().In(loc).Zone()
+	if name != "GMT+1" || offset != -1*60*60 {
+		t.Errorf("Now().In(loc).Zone() = %q, %d, want %q, %d", name, offset, "GMT+1", -1*60*60)
+	}
+}
+
 func BenchmarkNow(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Now()
+		t = Now()
+	}
+}
+
+func BenchmarkNowUnixNano(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		u = Now().UnixNano()
 	}
 }
 
 func BenchmarkFormat(b *testing.B) {
-	time := Unix(1265346057, 0)
+	t := Unix(1265346057, 0)
+	for i := 0; i < b.N; i++ {
+		t.Format("Mon Jan  2 15:04:05 2006")
+	}
+}
+
+func BenchmarkFormatNow(b *testing.B) {
+	// Like BenchmarkFormat, but easier, because the time zone
+	// lookup cache is optimized for the present.
+	t := Now()
 	for i := 0; i < b.N; i++ {
-		time.Format("Mon Jan  2 15:04:05 2006")
+		t.Format("Mon Jan  2 15:04:05 2006")
 	}
 }
 
diff --git a/src/pkg/time/zoneinfo.go b/src/pkg/time/zoneinfo.go
index 3c57744..c44477f 100644
--- a/src/pkg/time/zoneinfo.go
+++ b/src/pkg/time/zoneinfo.go
@@ -123,35 +123,58 @@ func (l *Location) lookup(sec int64) (name string, offset int, isDST bool, start
 	// Not using sort.Search to avoid dependencies.
 	tx := l.tx
 	end = 1<<63 - 1
-	for len(tx) > 1 {
-		m := len(tx) / 2
+	lo := 0
+	hi := len(tx)
+	for hi-lo > 1 {
+		m := lo + (hi-lo)/2
 		lim := tx[m].when
 		if sec < lim {
 			end = lim
-			tx = tx[0:m]
+			hi = m
 		} else {
-			tx = tx[m:]
+			lo = m
 		}
 	}
-	zone := &l.zone[tx[0].index]
+	zone := &l.zone[tx[lo].index]
 	name = zone.name
 	offset = zone.offset
 	isDST = zone.isDST
-	start = tx[0].when
+	start = tx[lo].when
 	// end = maintained during the search
 	return
 }
 
 // lookupName returns information about the time zone with
-// the given name (such as "EST").
-func (l *Location) lookupName(name string) (offset int, isDST bool, ok bool) {
+// the given name (such as "EST") at the given pseudo-Unix time
+// (what the given time of day would be in UTC).
+func (l *Location) lookupName(name string, unix int64) (offset int, isDST bool, ok bool) {
 	l = l.get()
+
+	// First try for a zone with the right name that was actually
+	// in effect at the given time. (In Sydney, Australia, both standard
+	// and daylight-savings time are abbreviated "EST". Using the
+	// offset helps us pick the right one for the given time.
+	// It's not perfect: during the backward transition we might pick
+	// either one.)
+	for i := range l.zone {
+		zone := &l.zone[i]
+		if zone.name == name {
+			nam, offset, isDST, _, _ := l.lookup(unix - int64(zone.offset))
+			if nam == zone.name {
+				return offset, isDST, true
+			}
+		}
+	}
+
+	// Otherwise fall back to an ordinary name match.
 	for i := range l.zone {
 		zone := &l.zone[i]
 		if zone.name == name {
 			return zone.offset, zone.isDST, true
 		}
 	}
+
+	// Otherwise, give up.
 	return
 }
 
diff --git a/src/pkg/time/zoneinfo_read.go b/src/pkg/time/zoneinfo_read.go
index ebb4205..4519c99 100644
--- a/src/pkg/time/zoneinfo_read.go
+++ b/src/pkg/time/zoneinfo_read.go
@@ -141,7 +141,7 @@ func loadZoneData(bytes []byte) (l *Location, err error) {
 		if n, ok = zonedata.big4(); !ok {
 			return nil, badData
 		}
-		zone[i].offset = int(n)
+		zone[i].offset = int(int32(n))
 		var b byte
 		if b, ok = zonedata.byte(); !ok {
 			return nil, badData
@@ -174,7 +174,13 @@ func loadZoneData(bytes []byte) (l *Location, err error) {
 		}
 	}
 
-	// Commited to succeed.
+	if len(tx) == 0 {
+		// Build fake transition to cover all time.
+		// This happens in fixed locations like "Etc/GMT0".
+		tx = append(tx, zoneTrans{when: -1 << 63, index: 0})
+	}
+
+	// Committed to succeed.
 	l = &Location{zone: zone, tx: tx}
 
 	// Fill in the cache with information about right now,
@@ -284,7 +290,7 @@ func loadZoneZip(zipfile, name string) (l *Location, err error) {
 		//	42	off[4]
 		//	46	name[namelen]
 		//	46+namelen+xlen+fclen - next header
-		//		
+		//
 		if get4(buf) != zcheader {
 			break
 		}
diff --git a/src/pkg/time/zoneinfo_windows.go b/src/pkg/time/zoneinfo_windows.go
index d596fab..a8d3dcb 100644
--- a/src/pkg/time/zoneinfo_windows.go
+++ b/src/pkg/time/zoneinfo_windows.go
@@ -15,9 +15,9 @@ import (
 // BUG(brainman,rsc): On Windows, the operating system does not provide complete
 // time zone information.
 // The implementation assumes that this year's rules for daylight savings
-// time apply to all previous and future years as well. 
+// time apply to all previous and future years as well.
 // Also, time zone abbreviations are unavailable.  The implementation constructs
-// them using the capital letters from a longer time zone description.	
+// them using the capital letters from a longer time zone description.
 
 // abbrev returns the abbreviation to use for the given zone name.
 func abbrev(name []uint16) string {
diff --git a/src/pkg/unicode/digit.go b/src/pkg/unicode/digit.go
index 4800bd6..53171b3 100644
--- a/src/pkg/unicode/digit.go
+++ b/src/pkg/unicode/digit.go
@@ -9,5 +9,5 @@ func IsDigit(r rune) bool {
 	if r <= MaxLatin1 {
 		return '0' <= r && r <= '9'
 	}
-	return Is(Digit, r)
+	return isExcludingLatin(Digit, r)
 }
diff --git a/src/pkg/unicode/graphic.go b/src/pkg/unicode/graphic.go
index 0de90eb..5b995fc 100644
--- a/src/pkg/unicode/graphic.go
+++ b/src/pkg/unicode/graphic.go
@@ -6,15 +6,17 @@ package unicode
 
 // Bit masks for each code point under U+0100, for fast lookup.
 const (
-	pC  = 1 << iota // a control character.
-	pP              // a punctuation character.
-	pN              // a numeral.
-	pS              // a symbolic character.
-	pZ              // a spacing character.
-	pLu             // an upper-case letter.
-	pLl             // a lower-case letter.
-	pp              // a printable character according to Go's definition.
-	pg  = pp | pZ   // a graphical character according to the Unicode definition.
+	pC     = 1 << iota // a control character.
+	pP                 // a punctuation character.
+	pN                 // a numeral.
+	pS                 // a symbolic character.
+	pZ                 // a spacing character.
+	pLu                // an upper-case letter.
+	pLl                // a lower-case letter.
+	pp                 // a printable character according to Go's definition.
+	pg     = pp | pZ   // a graphical character according to the Unicode definition.
+	pLo    = pLl | pLu // a letter that is neither upper nor lower case.
+	pLmask = pLo
 )
 
 // GraphicRanges defines the set of graphic characters according to Unicode.
@@ -76,15 +78,15 @@ func IsControl(r rune) bool {
 // IsLetter reports whether the rune is a letter (category L).
 func IsLetter(r rune) bool {
 	if uint32(r) <= MaxLatin1 {
-		return properties[uint8(r)]&(pLu|pLl) != 0
+		return properties[uint8(r)]&(pLmask) != 0
 	}
-	return Is(Letter, r)
+	return isExcludingLatin(Letter, r)
 }
 
 // IsMark reports whether the rune is a mark character (category M).
 func IsMark(r rune) bool {
 	// There are no mark characters in Latin-1.
-	return Is(Mark, r)
+	return isExcludingLatin(Mark, r)
 }
 
 // IsNumber reports whether the rune is a number (category N).
@@ -92,7 +94,7 @@ func IsNumber(r rune) bool {
 	if uint32(r) <= MaxLatin1 {
 		return properties[uint8(r)]&pN != 0
 	}
-	return Is(Number, r)
+	return isExcludingLatin(Number, r)
 }
 
 // IsPunct reports whether the rune is a Unicode punctuation character
@@ -119,7 +121,7 @@ func IsSpace(r rune) bool {
 		}
 		return false
 	}
-	return Is(White_Space, r)
+	return isExcludingLatin(White_Space, r)
 }
 
 // IsSymbol reports whether the rune is a symbolic character.
@@ -127,5 +129,5 @@ func IsSymbol(r rune) bool {
 	if uint32(r) <= MaxLatin1 {
 		return properties[uint8(r)]&pS != 0
 	}
-	return Is(Symbol, r)
+	return isExcludingLatin(Symbol, r)
 }
diff --git a/src/pkg/unicode/letter.go b/src/pkg/unicode/letter.go
index be48455..8d56363 100644
--- a/src/pkg/unicode/letter.go
+++ b/src/pkg/unicode/letter.go
@@ -19,8 +19,9 @@ const (
 // The two slices must be in sorted order and non-overlapping.
 // Also, R32 should contain only values >= 0x10000 (1<<16).
 type RangeTable struct {
-	R16 []Range16
-	R32 []Range32
+	R16         []Range16
+	R32         []Range32
+	LatinOffset int // number of entries in R16 with Hi <= MaxLatin1
 }
 
 // Range16 represents of a range of 16-bit Unicode code points.  The range runs from Lo to Hi
@@ -80,14 +81,31 @@ const (
 	UpperLower = MaxRune + 1 // (Cannot be a valid delta.)
 )
 
-// is16 uses binary search to test whether rune is in the specified slice of 16-bit ranges.
+// linearMax is the maximum size table for linear search for non-Latin1 rune.
+// Derived by running 'go test -calibrate'.
+const linearMax = 18
+
+// is16 reports whether r is in the sorted slice of 16-bit ranges.
 func is16(ranges []Range16, r uint16) bool {
+	if len(ranges) <= linearMax || r <= MaxLatin1 {
+		for i := range ranges {
+			range_ := &ranges[i]
+			if r < range_.Lo {
+				return false
+			}
+			if r <= range_.Hi {
+				return (r-range_.Lo)%range_.Stride == 0
+			}
+		}
+		return false
+	}
+
 	// binary search over ranges
 	lo := 0
 	hi := len(ranges)
 	for lo < hi {
 		m := lo + (hi-lo)/2
-		range_ := ranges[m]
+		range_ := &ranges[m]
 		if range_.Lo <= r && r <= range_.Hi {
 			return (r-range_.Lo)%range_.Stride == 0
 		}
@@ -100,8 +118,21 @@ func is16(ranges []Range16, r uint16) bool {
 	return false
 }
 
-// is32 uses binary search to test whether rune is in the specified slice of 32-bit ranges.
+// is32 reports whether r is in the sorted slice of 32-bit ranges.
 func is32(ranges []Range32, r uint32) bool {
+	if len(ranges) <= linearMax {
+		for i := range ranges {
+			range_ := &ranges[i]
+			if r < range_.Lo {
+				return false
+			}
+			if r <= range_.Hi {
+				return (r-range_.Lo)%range_.Stride == 0
+			}
+		}
+		return false
+	}
+
 	// binary search over ranges
 	lo := 0
 	hi := len(ranges)
@@ -122,21 +153,6 @@ func is32(ranges []Range32, r uint32) bool {
 
 // Is tests whether rune is in the specified table of ranges.
 func Is(rangeTab *RangeTable, r rune) bool {
-	// common case: rune is ASCII or Latin-1.
-	if uint32(r) <= MaxLatin1 {
-		// Only need to check R16, since R32 is always >= 1<<16.
-		r16 := uint16(r)
-		for _, r := range rangeTab.R16 {
-			if r16 > r.Hi {
-				continue
-			}
-			if r16 < r.Lo {
-				return false
-			}
-			return (r16-r.Lo)%r.Stride == 0
-		}
-		return false
-	}
 	r16 := rangeTab.R16
 	if len(r16) > 0 && r <= rune(r16[len(r16)-1].Hi) {
 		return is16(r16, uint16(r))
@@ -148,22 +164,34 @@ func Is(rangeTab *RangeTable, r rune) bool {
 	return false
 }
 
+func isExcludingLatin(rangeTab *RangeTable, r rune) bool {
+	r16 := rangeTab.R16
+	if off := rangeTab.LatinOffset; len(r16) > off && r <= rune(r16[len(r16)-1].Hi) {
+		return is16(r16[off:], uint16(r))
+	}
+	r32 := rangeTab.R32
+	if len(r32) > 0 && r >= rune(r32[0].Lo) {
+		return is32(r32, uint32(r))
+	}
+	return false
+}
+
 // IsUpper reports whether the rune is an upper case letter.
 func IsUpper(r rune) bool {
 	// See comment in IsGraphic.
 	if uint32(r) <= MaxLatin1 {
-		return properties[uint8(r)]&pLu != 0
+		return properties[uint8(r)]&pLmask == pLu
 	}
-	return Is(Upper, r)
+	return isExcludingLatin(Upper, r)
 }
 
 // IsLower reports whether the rune is a lower case letter.
 func IsLower(r rune) bool {
 	// See comment in IsGraphic.
 	if uint32(r) <= MaxLatin1 {
-		return properties[uint8(r)]&pLl != 0
+		return properties[uint8(r)]&pLmask == pLl
 	}
-	return Is(Lower, r)
+	return isExcludingLatin(Lower, r)
 }
 
 // IsTitle reports whether the rune is a title case letter.
@@ -171,7 +199,7 @@ func IsTitle(r rune) bool {
 	if r <= MaxLatin1 {
 		return false
 	}
-	return Is(Title, r)
+	return isExcludingLatin(Title, r)
 }
 
 // to maps the rune using the specified case mapping.
@@ -288,7 +316,7 @@ type foldPair struct {
 // SimpleFold iterates over Unicode code points equivalent under
 // the Unicode-defined simple case folding.  Among the code points
 // equivalent to rune (including rune itself), SimpleFold returns the
-// smallest rune >= r if one exists, or else the smallest rune >= 0. 
+// smallest rune >= r if one exists, or else the smallest rune >= 0.
 //
 // For example:
 //	SimpleFold('A') = 'a'
diff --git a/src/pkg/unicode/letter_test.go b/src/pkg/unicode/letter_test.go
index 2d80562..e4d5572 100644
--- a/src/pkg/unicode/letter_test.go
+++ b/src/pkg/unicode/letter_test.go
@@ -5,6 +5,10 @@
 package unicode_test
 
 import (
+	"flag"
+	"fmt"
+	"runtime"
+	"sort"
 	"testing"
 	. "unicode"
 )
@@ -427,3 +431,117 @@ func TestSimpleFold(t *testing.T) {
 		}
 	}
 }
+
+// Running 'go test -calibrate' runs the calibration to find a plausible
+// cutoff point for linear search of a range list vs. binary search.
+// We create a fake table and then time how long it takes to do a
+// sequence of searches within that table, for all possible inputs
+// relative to the ranges (something before all, in each, between each, after all).
+// This assumes that all possible runes are equally likely.
+// In practice most runes are ASCII so this is a conservative estimate
+// of an effective cutoff value. In practice we could probably set it higher
+// than what this function recommends.
+
+var calibrate = flag.Bool("calibrate", false, "compute crossover for linear vs. binary search")
+
+func TestCalibrate(t *testing.T) {
+	if !*calibrate {
+		return
+	}
+
+	if runtime.GOARCH == "amd64" {
+		fmt.Printf("warning: running calibration on %s\n", runtime.GOARCH)
+	}
+
+	// Find the point where binary search wins by more than 10%.
+	// The 10% bias gives linear search an edge when they're close,
+	// because on predominantly ASCII inputs linear search is even
+	// better than our benchmarks measure.
+	n := sort.Search(64, func(n int) bool {
+		tab := fakeTable(n)
+		blinear := func(b *testing.B) {
+			tab := tab
+			max := n*5 + 20
+			for i := 0; i < b.N; i++ {
+				for j := 0; j <= max; j++ {
+					linear(tab, uint16(j))
+				}
+			}
+		}
+		bbinary := func(b *testing.B) {
+			tab := tab
+			max := n*5 + 20
+			for i := 0; i < b.N; i++ {
+				for j := 0; j <= max; j++ {
+					binary(tab, uint16(j))
+				}
+			}
+		}
+		bmlinear := testing.Benchmark(blinear)
+		bmbinary := testing.Benchmark(bbinary)
+		fmt.Printf("n=%d: linear=%d binary=%d\n", n, bmlinear.NsPerOp(), bmbinary.NsPerOp())
+		return bmlinear.NsPerOp()*100 > bmbinary.NsPerOp()*110
+	})
+	fmt.Printf("calibration: linear cutoff = %d\n", n)
+}
+
+func fakeTable(n int) []Range16 {
+	var r16 []Range16
+	for i := 0; i < n; i++ {
+		r16 = append(r16, Range16{uint16(i*5 + 10), uint16(i*5 + 12), 1})
+	}
+	return r16
+}
+
+func linear(ranges []Range16, r uint16) bool {
+	for i := range ranges {
+		range_ := &ranges[i]
+		if r < range_.Lo {
+			return false
+		}
+		if r <= range_.Hi {
+			return (r-range_.Lo)%range_.Stride == 0
+		}
+	}
+	return false
+}
+
+func binary(ranges []Range16, r uint16) bool {
+	// binary search over ranges
+	lo := 0
+	hi := len(ranges)
+	for lo < hi {
+		m := lo + (hi-lo)/2
+		range_ := &ranges[m]
+		if range_.Lo <= r && r <= range_.Hi {
+			return (r-range_.Lo)%range_.Stride == 0
+		}
+		if r < range_.Lo {
+			hi = m
+		} else {
+			lo = m + 1
+		}
+	}
+	return false
+}
+
+func TestLatinOffset(t *testing.T) {
+	var maps = []map[string]*RangeTable{
+		Categories,
+		FoldCategory,
+		FoldScript,
+		Properties,
+		Scripts,
+	}
+	for _, m := range maps {
+		for name, tab := range m {
+			i := 0
+			for i < len(tab.R16) && tab.R16[i].Hi <= MaxLatin1 {
+				i++
+			}
+			if tab.LatinOffset != i {
+				t.Errorf("%s: LatinOffset=%d, want %d", name, tab.LatinOffset, i)
+			}
+		}
+	}
+}
diff --git a/src/pkg/unicode/maketables.go b/src/pkg/unicode/maketables.go
index fcd14fc..53d8b96 100644
--- a/src/pkg/unicode/maketables.go
+++ b/src/pkg/unicode/maketables.go
@@ -13,7 +13,6 @@ import (
 	"bufio"
 	"flag"
 	"fmt"
-	"io"
 	"log"
 	"net/http"
 	"os"
@@ -41,7 +40,7 @@ func main() {
 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.0.0/ucd/",
+	"http://www.unicode.org/Public/6.2.0/ucd/",
 	"URL of Unicode database directory")
 var tablelist = flag.String("tables",
 	"all",
@@ -321,16 +320,11 @@ func loadChars() {
 		flag.Set("data", *url+"UnicodeData.txt")
 	}
 	input := open(*dataURL)
+	defer input.close()
+	scanner := bufio.NewScanner(input)
 	var first rune = 0
-	for {
-		line, err := input.ReadString('\n')
-		if err != nil {
-			if err == io.EOF {
-				break
-			}
-			logger.Fatal(err)
-		}
-		switch parseCategory(line[0 : len(line)-1]) {
+	for scanner.Scan() {
+		switch parseCategory(scanner.Text()) {
 		case SNormal:
 			if first != 0 {
 				logger.Fatalf("bad state normal at %U", lastChar)
@@ -351,7 +345,9 @@ func loadChars() {
 			first = 0
 		}
 	}
-	input.close()
+	if scanner.Err() != nil {
+		logger.Fatal(scanner.Err())
+	}
 }
 
 func loadCasefold() {
@@ -359,15 +355,11 @@ func loadCasefold() {
 		flag.Set("casefolding", *url+"CaseFolding.txt")
 	}
 	input := open(*casefoldingURL)
-	for {
-		line, err := input.ReadString('\n')
-		if err != nil {
-			if err == io.EOF {
-				break
-			}
-			logger.Fatal(err)
-		}
-		if line[0] == '#' {
+	defer input.close()
+	scanner := bufio.NewScanner(input)
+	for scanner.Scan() {
+		line := scanner.Text()
+		if len(line) == 0 || line[0] == '#' || len(strings.TrimSpace(line)) == 0 {
 			continue
 		}
 		field := strings.Split(line, "; ")
@@ -389,7 +381,9 @@ func loadCasefold() {
 		}
 		chars[p1].foldCase = rune(p2)
 	}
-	input.close()
+	if scanner.Err() != nil {
+		logger.Fatal(scanner.Err())
+	}
 }
 
 const progHeader = `// Generated by running
@@ -503,6 +497,7 @@ const format = "\t\t{0x%04x, 0x%04x, %d},\n"
 func dumpRange(header string, inCategory Op) {
 	fmt.Print(header)
 	next := rune(0)
+	latinOffset := 0
 	fmt.Print("\tR16: []Range16{\n")
 	// one Range for each iteration
 	count := &range16Count
@@ -546,11 +541,17 @@ func dumpRange(header string, inCategory Op) {
 				break
 			}
 		}
+		if uint32(hi) <= unicode.MaxLatin1 {
+			latinOffset++
+		}
 		size, count = printRange(uint32(lo), uint32(hi), uint32(stride), size, count)
 		// next range: start looking where this range ends
 		next = hi + 1
 	}
 	fmt.Print("\t},\n")
+	if latinOffset > 0 {
+		fmt.Printf("\tLatinOffset: %d,\n", latinOffset)
+	}
 	fmt.Print("}\n\n")
 }
 
@@ -703,15 +704,12 @@ func printScriptOrProperty(doProps bool) {
 		return
 	}
 	input := open(*url + file)
-	for {
-		line, err := input.ReadString('\n')
-		if err != nil {
-			if err == io.EOF {
-				break
-			}
-			logger.Fatal(err)
-		}
-		parseScript(line[0:len(line)-1], table)
+	scanner := bufio.NewScanner(input)
+	for scanner.Scan() {
+		parseScript(scanner.Text(), table)
+	}
+	if scanner.Err() != nil {
+		logger.Fatal(scanner.Err())
 	}
 	input.close()
 
@@ -760,14 +758,17 @@ func printScriptOrProperty(doProps bool) {
 		}
 		ndecl++
 		fmt.Printf("var _%s = &RangeTable {\n", name)
-		fmt.Print("\tR16: []Range16{\n")
 		ranges := foldAdjacent(table[name])
+		fmt.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")
+		if off := findLatinOffset(ranges); off > 0 {
+			fmt.Printf("\tLatinOffset: %d,\n", off)
+		}
 		fmt.Print("}\n\n")
 	}
 	decl.Sort()
@@ -779,6 +780,14 @@ func printScriptOrProperty(doProps bool) {
 	fmt.Print(")\n\n")
 }
 
+func findLatinOffset(ranges []unicode.Range32) int {
+	i := 0
+	for i < len(ranges) && ranges[i].Hi <= unicode.MaxLatin1 {
+		i++
+	}
+	return i
+}
+
 const (
 	CaseUpper = 1 << iota
 	CaseLower
@@ -1022,6 +1031,8 @@ func printLatinProperties() {
 			property = "0"
 		case "Ll":
 			property = "pLl | pp"
+		case "Lo":
+			property = "pLo | pp"
 		case "Lu":
 			property = "pLu | pp"
 		case "Nd", "No":
diff --git a/src/pkg/unicode/script_test.go b/src/pkg/unicode/script_test.go
index 1c5b801..395cc71 100644
--- a/src/pkg/unicode/script_test.go
+++ b/src/pkg/unicode/script_test.go
@@ -14,7 +14,7 @@ type T struct {
 	script string
 }
 
-// Hand-chosen tests from Unicode 5.1.0 & 6.0..0, mostly to discover when new
+// Hand-chosen tests from Unicode 5.1.0, 6.0.0 and 6.2.0 mostly to discover when new
 // scripts and categories arise.
 var inTest = []T{
 	{0x06e2, "Arabic"},
@@ -31,6 +31,7 @@ var inTest = []T{
 	{0x11011, "Brahmi"},
 	{0x156d, "Canadian_Aboriginal"},
 	{0x102a9, "Carian"},
+	{0x11111, "Chakma"},
 	{0xaa4d, "Cham"},
 	{0x13c2, "Cherokee"},
 	{0x0020, "Common"},
@@ -76,6 +77,9 @@ var inTest = []T{
 	{0x0d42, "Malayalam"},
 	{0x0843, "Mandaic"},
 	{0xabd0, "Meetei_Mayek"},
+	{0x1099f, "Meroitic_Hieroglyphs"},
+	{0x109a0, "Meroitic_Cursive"},
+	{0x16f00, "Miao"},
 	{0x1822, "Mongolian"},
 	{0x104c, "Myanmar"},
 	{0x19c3, "New_Tai_Lue"},
@@ -94,8 +98,10 @@ var inTest = []T{
 	{0x16c0, "Runic"},
 	{0x081d, "Samaritan"},
 	{0xa892, "Saurashtra"},
+	{0x111a0, "Sharada"},
 	{0x10463, "Shavian"},
 	{0x0dbd, "Sinhala"},
+	{0x110d0, "Sora_Sompeng"},
 	{0x1ba3, "Sundanese"},
 	{0xa803, "Syloti_Nagri"},
 	{0x070f, "Syriac"},
@@ -104,6 +110,7 @@ var inTest = []T{
 	{0x1972, "Tai_Le"},
 	{0x1a62, "Tai_Tham"},
 	{0xaadc, "Tai_Viet"},
+	{0x116c9, "Takri"},
 	{0x0bbf, "Tamil"},
 	{0x0c55, "Telugu"},
 	{0x07a7, "Thaana"},
@@ -121,7 +128,7 @@ var outTest = []T{ // not really worth being thorough
 
 var inCategoryTest = []T{
 	{0x0081, "Cc"},
-	{0x17b4, "Cf"},
+	{0x200B, "Cf"},
 	{0xf0000, "Co"},
 	{0xdb80, "Cs"},
 	{0x0236, "Ll"},
diff --git a/src/pkg/unicode/tables.go b/src/pkg/unicode/tables.go
index ebd169b..36b5a31 100644
--- a/src/pkg/unicode/tables.go
+++ b/src/pkg/unicode/tables.go
@@ -1,11 +1,11 @@
 // Generated by running
-//	maketables --tables=all --data=http://www.unicode.org/Public/6.0.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/6.0.0/ucd/CaseFolding.txt
+//	maketables --tables=all --data=http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/6.2.0/ucd/CaseFolding.txt
 // DO NOT EDIT
 
 package unicode
 
 // Version is the Unicode edition from which the tables are derived.
-const Version = "6.0.0"
+const Version = "6.2.0"
 
 // Categories is the set of Unicode category tables.
 var Categories = map[string]*RangeTable{
@@ -52,9 +52,8 @@ var _C = &RangeTable{
 		{0x0001, 0x001f, 1},
 		{0x007f, 0x009f, 1},
 		{0x00ad, 0x0600, 1363},
-		{0x0601, 0x0603, 1},
+		{0x0601, 0x0604, 1},
 		{0x06dd, 0x070f, 50},
-		{0x17b4, 0x17b5, 1},
 		{0x200b, 0x200f, 1},
 		{0x202a, 0x202e, 1},
 		{0x2060, 0x2064, 1},
@@ -71,6 +70,7 @@ var _C = &RangeTable{
 		{0xf0000, 0xffffd, 1},
 		{0x100000, 0x10fffd, 1},
 	},
+	LatinOffset: 2,
 }
 
 var _Cc = &RangeTable{
@@ -78,14 +78,14 @@ var _Cc = &RangeTable{
 		{0x0001, 0x001f, 1},
 		{0x007f, 0x009f, 1},
 	},
+	LatinOffset: 2,
 }
 
 var _Cf = &RangeTable{
 	R16: []Range16{
 		{0x00ad, 0x0600, 1363},
-		{0x0601, 0x0603, 1},
+		{0x0601, 0x0604, 1},
 		{0x06dd, 0x070f, 50},
-		{0x17b4, 0x17b5, 1},
 		{0x200b, 0x200f, 1},
 		{0x202a, 0x202e, 1},
 		{0x2060, 0x2064, 1},
@@ -162,6 +162,8 @@ var _L = &RangeTable{
 		{0x081a, 0x0824, 10},
 		{0x0828, 0x0840, 24},
 		{0x0841, 0x0858, 1},
+		{0x08a0, 0x08a2, 2},
+		{0x08a3, 0x08ac, 1},
 		{0x0904, 0x0939, 1},
 		{0x093d, 0x0950, 19},
 		{0x0958, 0x0961, 1},
@@ -259,8 +261,9 @@ var _L = &RangeTable{
 		{0x0ebd, 0x0ec0, 3},
 		{0x0ec1, 0x0ec4, 1},
 		{0x0ec6, 0x0edc, 22},
-		{0x0edd, 0x0f00, 35},
-		{0x0f40, 0x0f47, 1},
+		{0x0edd, 0x0edf, 1},
+		{0x0f00, 0x0f40, 64},
+		{0x0f41, 0x0f47, 1},
 		{0x0f49, 0x0f6c, 1},
 		{0x0f88, 0x0f8c, 1},
 		{0x1000, 0x102a, 1},
@@ -273,9 +276,9 @@ var _L = &RangeTable{
 		{0x1075, 0x1081, 1},
 		{0x108e, 0x10a0, 18},
 		{0x10a1, 0x10c5, 1},
+		{0x10c7, 0x10cd, 6},
 		{0x10d0, 0x10fa, 1},
-		{0x10fc, 0x1100, 4},
-		{0x1101, 0x1248, 1},
+		{0x10fc, 0x1248, 1},
 		{0x124a, 0x124d, 1},
 		{0x1250, 0x1256, 1},
 		{0x1258, 0x125a, 2},
@@ -321,12 +324,13 @@ var _L = &RangeTable{
 		{0x1b45, 0x1b4b, 1},
 		{0x1b83, 0x1ba0, 1},
 		{0x1bae, 0x1baf, 1},
-		{0x1bc0, 0x1be5, 1},
+		{0x1bba, 0x1be5, 1},
 		{0x1c00, 0x1c23, 1},
 		{0x1c4d, 0x1c4f, 1},
 		{0x1c5a, 0x1c7d, 1},
 		{0x1ce9, 0x1cec, 1},
 		{0x1cee, 0x1cf1, 1},
+		{0x1cf5, 0x1cf6, 1},
 		{0x1d00, 0x1dbf, 1},
 		{0x1e00, 0x1f15, 1},
 		{0x1f18, 0x1f1d, 1},
@@ -362,8 +366,10 @@ var _L = &RangeTable{
 		{0x2c30, 0x2c5e, 1},
 		{0x2c60, 0x2ce4, 1},
 		{0x2ceb, 0x2cee, 1},
+		{0x2cf2, 0x2cf3, 1},
 		{0x2d00, 0x2d25, 1},
-		{0x2d30, 0x2d65, 1},
+		{0x2d27, 0x2d2d, 6},
+		{0x2d30, 0x2d67, 1},
 		{0x2d6f, 0x2d80, 17},
 		{0x2d81, 0x2d96, 1},
 		{0x2da0, 0x2da6, 1},
@@ -387,7 +393,7 @@ var _L = &RangeTable{
 		{0x31a0, 0x31ba, 1},
 		{0x31f0, 0x31ff, 1},
 		{0x3400, 0x4db5, 1},
-		{0x4e00, 0x9fcb, 1},
+		{0x4e00, 0x9fcc, 1},
 		{0xa000, 0xa48c, 1},
 		{0xa4d0, 0xa4fd, 1},
 		{0xa500, 0xa60c, 1},
@@ -399,9 +405,9 @@ var _L = &RangeTable{
 		{0xa717, 0xa71f, 1},
 		{0xa722, 0xa788, 1},
 		{0xa78b, 0xa78e, 1},
-		{0xa790, 0xa791, 1},
-		{0xa7a0, 0xa7a9, 1},
-		{0xa7fa, 0xa801, 1},
+		{0xa790, 0xa793, 1},
+		{0xa7a0, 0xa7aa, 1},
+		{0xa7f8, 0xa801, 1},
 		{0xa803, 0xa805, 1},
 		{0xa807, 0xa80a, 1},
 		{0xa80c, 0xa822, 1},
@@ -425,6 +431,8 @@ var _L = &RangeTable{
 		{0xaaba, 0xaabd, 1},
 		{0xaac0, 0xaac2, 2},
 		{0xaadb, 0xaadd, 1},
+		{0xaae0, 0xaaea, 1},
+		{0xaaf2, 0xaaf4, 1},
 		{0xab01, 0xab06, 1},
 		{0xab09, 0xab0e, 1},
 		{0xab11, 0xab16, 1},
@@ -434,8 +442,7 @@ var _L = &RangeTable{
 		{0xac00, 0xd7a3, 1},
 		{0xd7b0, 0xd7c6, 1},
 		{0xd7cb, 0xd7fb, 1},
-		{0xf900, 0xfa2d, 1},
-		{0xfa30, 0xfa6d, 1},
+		{0xf900, 0xfa6d, 1},
 		{0xfa70, 0xfad9, 1},
 		{0xfb00, 0xfb06, 1},
 		{0xfb13, 0xfb17, 1},
@@ -486,6 +493,8 @@ var _L = &RangeTable{
 		{0x10840, 0x10855, 1},
 		{0x10900, 0x10915, 1},
 		{0x10920, 0x10939, 1},
+		{0x10980, 0x109b7, 1},
+		{0x109be, 0x109bf, 1},
 		{0x10a00, 0x10a10, 16},
 		{0x10a11, 0x10a13, 1},
 		{0x10a15, 0x10a17, 1},
@@ -497,9 +506,17 @@ var _L = &RangeTable{
 		{0x10c00, 0x10c48, 1},
 		{0x11003, 0x11037, 1},
 		{0x11083, 0x110af, 1},
+		{0x110d0, 0x110e8, 1},
+		{0x11103, 0x11126, 1},
+		{0x11183, 0x111b2, 1},
+		{0x111c1, 0x111c4, 1},
+		{0x11680, 0x116aa, 1},
 		{0x12000, 0x1236e, 1},
 		{0x13000, 0x1342e, 1},
 		{0x16800, 0x16a38, 1},
+		{0x16f00, 0x16f44, 1},
+		{0x16f50, 0x16f93, 67},
+		{0x16f94, 0x16f9f, 1},
 		{0x1b000, 0x1b001, 1},
 		{0x1d400, 0x1d454, 1},
 		{0x1d456, 0x1d49c, 1},
@@ -531,18 +548,42 @@ var _L = &RangeTable{
 		{0x1d78a, 0x1d7a8, 1},
 		{0x1d7aa, 0x1d7c2, 1},
 		{0x1d7c4, 0x1d7cb, 1},
+		{0x1ee00, 0x1ee03, 1},
+		{0x1ee05, 0x1ee1f, 1},
+		{0x1ee21, 0x1ee22, 1},
+		{0x1ee24, 0x1ee27, 3},
+		{0x1ee29, 0x1ee32, 1},
+		{0x1ee34, 0x1ee37, 1},
+		{0x1ee39, 0x1ee3b, 2},
+		{0x1ee42, 0x1ee47, 5},
+		{0x1ee49, 0x1ee4d, 2},
+		{0x1ee4e, 0x1ee4f, 1},
+		{0x1ee51, 0x1ee52, 1},
+		{0x1ee54, 0x1ee57, 3},
+		{0x1ee59, 0x1ee61, 2},
+		{0x1ee62, 0x1ee64, 2},
+		{0x1ee67, 0x1ee6a, 1},
+		{0x1ee6c, 0x1ee72, 1},
+		{0x1ee74, 0x1ee77, 1},
+		{0x1ee79, 0x1ee7c, 1},
+		{0x1ee7e, 0x1ee80, 2},
+		{0x1ee81, 0x1ee89, 1},
+		{0x1ee8b, 0x1ee9b, 1},
+		{0x1eea1, 0x1eea3, 1},
+		{0x1eea5, 0x1eea9, 1},
+		{0x1eeab, 0x1eebb, 1},
 		{0x20000, 0x2a6d6, 1},
 		{0x2a700, 0x2b734, 1},
 		{0x2b740, 0x2b81d, 1},
 		{0x2f800, 0x2fa1d, 1},
 	},
+	LatinOffset: 6,
 }
 
 var _Ll = &RangeTable{
 	R16: []Range16{
 		{0x0061, 0x007a, 1},
-		{0x00aa, 0x00b5, 11},
-		{0x00ba, 0x00df, 37},
+		{0x00b5, 0x00df, 42},
 		{0x00e0, 0x00f6, 1},
 		{0x00f8, 0x00ff, 1},
 		{0x0101, 0x0137, 2},
@@ -593,7 +634,7 @@ var _Ll = &RangeTable{
 		{0x04cf, 0x0527, 2},
 		{0x0561, 0x0587, 1},
 		{0x1d00, 0x1d2b, 1},
-		{0x1d62, 0x1d77, 1},
+		{0x1d6b, 0x1d77, 1},
 		{0x1d79, 0x1d9a, 1},
 		{0x1e01, 0x1e95, 2},
 		{0x1e96, 0x1e9d, 1},
@@ -630,11 +671,12 @@ var _Ll = &RangeTable{
 		{0x2c66, 0x2c6c, 2},
 		{0x2c71, 0x2c73, 2},
 		{0x2c74, 0x2c76, 2},
-		{0x2c77, 0x2c7c, 1},
+		{0x2c77, 0x2c7b, 1},
 		{0x2c81, 0x2ce3, 2},
 		{0x2ce4, 0x2cec, 8},
-		{0x2cee, 0x2d00, 18},
-		{0x2d01, 0x2d25, 1},
+		{0x2cee, 0x2cf3, 5},
+		{0x2d00, 0x2d25, 1},
+		{0x2d27, 0x2d2d, 6},
 		{0xa641, 0xa66d, 2},
 		{0xa681, 0xa697, 2},
 		{0xa723, 0xa72f, 2},
@@ -644,8 +686,8 @@ var _Ll = &RangeTable{
 		{0xa77a, 0xa77c, 2},
 		{0xa77f, 0xa787, 2},
 		{0xa78c, 0xa78e, 2},
-		{0xa791, 0xa7a1, 16},
-		{0xa7a3, 0xa7a9, 2},
+		{0xa791, 0xa793, 2},
+		{0xa7a1, 0xa7a9, 2},
 		{0xa7fa, 0xfb00, 21254},
 		{0xfb01, 0xfb06, 1},
 		{0xfb13, 0xfb17, 1},
@@ -682,6 +724,7 @@ var _Ll = &RangeTable{
 		{0x1d7c4, 0x1d7c9, 1},
 		{0x1d7cb, 0x1d7cb, 1},
 	},
+	LatinOffset: 4,
 }
 
 var _Lm = &RangeTable{
@@ -701,14 +744,15 @@ var _Lm = &RangeTable{
 		{0x17d7, 0x1843, 108},
 		{0x1aa7, 0x1c78, 465},
 		{0x1c79, 0x1c7d, 1},
-		{0x1d2c, 0x1d61, 1},
+		{0x1d2c, 0x1d6a, 1},
 		{0x1d78, 0x1d9b, 35},
 		{0x1d9c, 0x1dbf, 1},
 		{0x2071, 0x207f, 14},
 		{0x2090, 0x209c, 1},
-		{0x2c7d, 0x2d6f, 242},
-		{0x2e2f, 0x3005, 470},
-		{0x3031, 0x3035, 1},
+		{0x2c7c, 0x2c7d, 1},
+		{0x2d6f, 0x2e2f, 192},
+		{0x3005, 0x3031, 44},
+		{0x3032, 0x3035, 1},
 		{0x303b, 0x309d, 98},
 		{0x309e, 0x30fc, 94},
 		{0x30fd, 0x30fe, 1},
@@ -717,14 +761,20 @@ var _Lm = &RangeTable{
 		{0xa60c, 0xa67f, 115},
 		{0xa717, 0xa71f, 1},
 		{0xa770, 0xa788, 24},
+		{0xa7f8, 0xa7f9, 1},
 		{0xa9cf, 0xaa70, 161},
-		{0xaadd, 0xff70, 21651},
+		{0xaadd, 0xaaf3, 22},
+		{0xaaf4, 0xff70, 21628},
 		{0xff9e, 0xff9f, 1},
 	},
+	R32: []Range32{
+		{0x16f93, 0x16f9f, 1},
+	},
 }
 
 var _Lo = &RangeTable{
 	R16: []Range16{
+		{0x00aa, 0x00ba, 16},
 		{0x01bb, 0x01c0, 5},
 		{0x01c1, 0x01c3, 1},
 		{0x0294, 0x05d0, 828},
@@ -744,6 +794,8 @@ var _Lo = &RangeTable{
 		{0x07cb, 0x07ea, 1},
 		{0x0800, 0x0815, 1},
 		{0x0840, 0x0858, 1},
+		{0x08a0, 0x08a2, 2},
+		{0x08a3, 0x08ac, 1},
 		{0x0904, 0x0939, 1},
 		{0x093d, 0x0950, 19},
 		{0x0958, 0x0961, 1},
@@ -840,7 +892,7 @@ var _Lo = &RangeTable{
 		{0x0eb2, 0x0eb3, 1},
 		{0x0ebd, 0x0ec0, 3},
 		{0x0ec1, 0x0ec4, 1},
-		{0x0edc, 0x0edd, 1},
+		{0x0edc, 0x0edf, 1},
 		{0x0f00, 0x0f40, 64},
 		{0x0f41, 0x0f47, 1},
 		{0x0f49, 0x0f6c, 1},
@@ -855,7 +907,7 @@ var _Lo = &RangeTable{
 		{0x1075, 0x1081, 1},
 		{0x108e, 0x10d0, 66},
 		{0x10d1, 0x10fa, 1},
-		{0x1100, 0x1248, 1},
+		{0x10fd, 0x1248, 1},
 		{0x124a, 0x124d, 1},
 		{0x1250, 0x1256, 1},
 		{0x1258, 0x125a, 2},
@@ -901,14 +953,15 @@ var _Lo = &RangeTable{
 		{0x1b45, 0x1b4b, 1},
 		{0x1b83, 0x1ba0, 1},
 		{0x1bae, 0x1baf, 1},
-		{0x1bc0, 0x1be5, 1},
+		{0x1bba, 0x1be5, 1},
 		{0x1c00, 0x1c23, 1},
 		{0x1c4d, 0x1c4f, 1},
 		{0x1c5a, 0x1c77, 1},
 		{0x1ce9, 0x1cec, 1},
 		{0x1cee, 0x1cf1, 1},
+		{0x1cf5, 0x1cf6, 1},
 		{0x2135, 0x2138, 1},
-		{0x2d30, 0x2d65, 1},
+		{0x2d30, 0x2d67, 1},
 		{0x2d80, 0x2d96, 1},
 		{0x2da0, 0x2da6, 1},
 		{0x2da8, 0x2dae, 1},
@@ -928,7 +981,7 @@ var _Lo = &RangeTable{
 		{0x31a0, 0x31ba, 1},
 		{0x31f0, 0x31ff, 1},
 		{0x3400, 0x4db5, 1},
-		{0x4e00, 0x9fcb, 1},
+		{0x4e00, 0x9fcc, 1},
 		{0xa000, 0xa014, 1},
 		{0xa016, 0xa48c, 1},
 		{0xa4d0, 0xa4f7, 1},
@@ -961,7 +1014,9 @@ var _Lo = &RangeTable{
 		{0xaaba, 0xaabd, 1},
 		{0xaac0, 0xaac2, 2},
 		{0xaadb, 0xaadc, 1},
-		{0xab01, 0xab06, 1},
+		{0xaae0, 0xaaea, 1},
+		{0xaaf2, 0xab01, 15},
+		{0xab02, 0xab06, 1},
 		{0xab09, 0xab0e, 1},
 		{0xab11, 0xab16, 1},
 		{0xab20, 0xab26, 1},
@@ -970,8 +1025,7 @@ var _Lo = &RangeTable{
 		{0xac00, 0xd7a3, 1},
 		{0xd7b0, 0xd7c6, 1},
 		{0xd7cb, 0xd7fb, 1},
-		{0xf900, 0xfa2d, 1},
-		{0xfa30, 0xfa6d, 1},
+		{0xf900, 0xfa6d, 1},
 		{0xfa70, 0xfad9, 1},
 		{0xfb1d, 0xfb1f, 2},
 		{0xfb20, 0xfb28, 1},
@@ -1020,6 +1074,8 @@ var _Lo = &RangeTable{
 		{0x10840, 0x10855, 1},
 		{0x10900, 0x10915, 1},
 		{0x10920, 0x10939, 1},
+		{0x10980, 0x109b7, 1},
+		{0x109be, 0x109bf, 1},
 		{0x10a00, 0x10a10, 16},
 		{0x10a11, 0x10a13, 1},
 		{0x10a15, 0x10a17, 1},
@@ -1031,15 +1087,47 @@ var _Lo = &RangeTable{
 		{0x10c00, 0x10c48, 1},
 		{0x11003, 0x11037, 1},
 		{0x11083, 0x110af, 1},
+		{0x110d0, 0x110e8, 1},
+		{0x11103, 0x11126, 1},
+		{0x11183, 0x111b2, 1},
+		{0x111c1, 0x111c4, 1},
+		{0x11680, 0x116aa, 1},
 		{0x12000, 0x1236e, 1},
 		{0x13000, 0x1342e, 1},
 		{0x16800, 0x16a38, 1},
-		{0x1b000, 0x1b001, 1},
+		{0x16f00, 0x16f44, 1},
+		{0x16f50, 0x1b000, 16560},
+		{0x1b001, 0x1ee00, 15871},
+		{0x1ee01, 0x1ee03, 1},
+		{0x1ee05, 0x1ee1f, 1},
+		{0x1ee21, 0x1ee22, 1},
+		{0x1ee24, 0x1ee27, 3},
+		{0x1ee29, 0x1ee32, 1},
+		{0x1ee34, 0x1ee37, 1},
+		{0x1ee39, 0x1ee3b, 2},
+		{0x1ee42, 0x1ee47, 5},
+		{0x1ee49, 0x1ee4d, 2},
+		{0x1ee4e, 0x1ee4f, 1},
+		{0x1ee51, 0x1ee52, 1},
+		{0x1ee54, 0x1ee57, 3},
+		{0x1ee59, 0x1ee61, 2},
+		{0x1ee62, 0x1ee64, 2},
+		{0x1ee67, 0x1ee6a, 1},
+		{0x1ee6c, 0x1ee72, 1},
+		{0x1ee74, 0x1ee77, 1},
+		{0x1ee79, 0x1ee7c, 1},
+		{0x1ee7e, 0x1ee80, 2},
+		{0x1ee81, 0x1ee89, 1},
+		{0x1ee8b, 0x1ee9b, 1},
+		{0x1eea1, 0x1eea3, 1},
+		{0x1eea5, 0x1eea9, 1},
+		{0x1eeab, 0x1eebb, 1},
 		{0x20000, 0x2a6d6, 1},
 		{0x2a700, 0x2b734, 1},
 		{0x2b740, 0x2b81d, 1},
 		{0x2f800, 0x2fa1d, 1},
 	},
+	LatinOffset: 1,
 }
 
 var _Lt = &RangeTable{
@@ -1109,6 +1197,7 @@ var _Lu = &RangeTable{
 		{0x04d0, 0x0526, 2},
 		{0x0531, 0x0556, 1},
 		{0x10a0, 0x10c5, 1},
+		{0x10c7, 0x10cd, 6},
 		{0x1e00, 0x1e94, 2},
 		{0x1e9e, 0x1efe, 2},
 		{0x1f08, 0x1f0f, 1},
@@ -1142,15 +1231,16 @@ var _Lu = &RangeTable{
 		{0x2c7e, 0x2c80, 1},
 		{0x2c82, 0x2ce2, 2},
 		{0x2ceb, 0x2ced, 2},
-		{0xa640, 0xa66c, 2},
+		{0x2cf2, 0xa640, 31054},
+		{0xa642, 0xa66c, 2},
 		{0xa680, 0xa696, 2},
 		{0xa722, 0xa72e, 2},
 		{0xa732, 0xa76e, 2},
 		{0xa779, 0xa77d, 2},
 		{0xa77e, 0xa786, 2},
 		{0xa78b, 0xa78d, 2},
-		{0xa790, 0xa7a0, 16},
-		{0xa7a2, 0xa7a8, 2},
+		{0xa790, 0xa792, 2},
+		{0xa7a0, 0xa7aa, 2},
 		{0xff21, 0xff3a, 1},
 	},
 	R32: []Range32{
@@ -1186,6 +1276,7 @@ var _Lu = &RangeTable{
 		{0x1d790, 0x1d7a8, 1},
 		{0x1d7ca, 0x1d7ca, 1},
 	},
+	LatinOffset: 3,
 }
 
 var _M = &RangeTable{
@@ -1212,6 +1303,7 @@ var _M = &RangeTable{
 		{0x0825, 0x0827, 1},
 		{0x0829, 0x082d, 1},
 		{0x0859, 0x085b, 1},
+		{0x08e4, 0x08fe, 1},
 		{0x0900, 0x0903, 1},
 		{0x093a, 0x093c, 1},
 		{0x093e, 0x094f, 1},
@@ -1302,7 +1394,7 @@ var _M = &RangeTable{
 		{0x1732, 0x1734, 1},
 		{0x1752, 0x1753, 1},
 		{0x1772, 0x1773, 1},
-		{0x17b6, 0x17d3, 1},
+		{0x17b4, 0x17d3, 1},
 		{0x17dd, 0x180b, 46},
 		{0x180c, 0x180d, 1},
 		{0x18a9, 0x1920, 119},
@@ -1318,12 +1410,13 @@ var _M = &RangeTable{
 		{0x1b34, 0x1b44, 1},
 		{0x1b6b, 0x1b73, 1},
 		{0x1b80, 0x1b82, 1},
-		{0x1ba1, 0x1baa, 1},
+		{0x1ba1, 0x1bad, 1},
 		{0x1be6, 0x1bf3, 1},
 		{0x1c24, 0x1c37, 1},
 		{0x1cd0, 0x1cd2, 1},
 		{0x1cd4, 0x1ce8, 1},
 		{0x1ced, 0x1cf2, 5},
+		{0x1cf3, 0x1cf4, 1},
 		{0x1dc0, 0x1de6, 1},
 		{0x1dfc, 0x1dff, 1},
 		{0x20d0, 0x20f0, 1},
@@ -1333,11 +1426,11 @@ var _M = &RangeTable{
 		{0x302a, 0x302f, 1},
 		{0x3099, 0x309a, 1},
 		{0xa66f, 0xa672, 1},
-		{0xa67c, 0xa67d, 1},
-		{0xa6f0, 0xa6f1, 1},
-		{0xa802, 0xa806, 4},
-		{0xa80b, 0xa823, 24},
-		{0xa824, 0xa827, 1},
+		{0xa674, 0xa67d, 1},
+		{0xa69f, 0xa6f0, 81},
+		{0xa6f1, 0xa802, 273},
+		{0xa806, 0xa80b, 5},
+		{0xa823, 0xa827, 1},
 		{0xa880, 0xa881, 1},
 		{0xa8b4, 0xa8c4, 1},
 		{0xa8e0, 0xa8f1, 1},
@@ -1352,8 +1445,10 @@ var _M = &RangeTable{
 		{0xaab3, 0xaab4, 1},
 		{0xaab7, 0xaab8, 1},
 		{0xaabe, 0xaabf, 1},
-		{0xaac1, 0xabe3, 290},
-		{0xabe4, 0xabea, 1},
+		{0xaac1, 0xaaeb, 42},
+		{0xaaec, 0xaaef, 1},
+		{0xaaf5, 0xaaf6, 1},
+		{0xabe3, 0xabea, 1},
 		{0xabec, 0xabed, 1},
 		{0xfb1e, 0xfe00, 738},
 		{0xfe01, 0xfe0f, 1},
@@ -1370,6 +1465,13 @@ var _M = &RangeTable{
 		{0x11038, 0x11046, 1},
 		{0x11080, 0x11082, 1},
 		{0x110b0, 0x110ba, 1},
+		{0x11100, 0x11102, 1},
+		{0x11127, 0x11134, 1},
+		{0x11180, 0x11182, 1},
+		{0x111b3, 0x111c0, 1},
+		{0x116ab, 0x116b7, 1},
+		{0x16f51, 0x16f7e, 1},
+		{0x16f8f, 0x16f92, 1},
 		{0x1d165, 0x1d169, 1},
 		{0x1d16d, 0x1d172, 1},
 		{0x1d17b, 0x1d182, 1},
@@ -1454,17 +1556,19 @@ var _Mc = &RangeTable{
 		{0x1b43, 0x1b44, 1},
 		{0x1b82, 0x1ba1, 31},
 		{0x1ba6, 0x1ba7, 1},
-		{0x1baa, 0x1be7, 61},
+		{0x1baa, 0x1bac, 2},
+		{0x1bad, 0x1be7, 58},
 		{0x1bea, 0x1bec, 1},
 		{0x1bee, 0x1bf2, 4},
 		{0x1bf3, 0x1c24, 49},
 		{0x1c25, 0x1c2b, 1},
 		{0x1c34, 0x1c35, 1},
 		{0x1ce1, 0x1cf2, 17},
-		{0xa823, 0xa824, 1},
-		{0xa827, 0xa880, 89},
-		{0xa881, 0xa8b4, 51},
-		{0xa8b5, 0xa8c3, 1},
+		{0x1cf3, 0x302e, 4923},
+		{0x302f, 0xa823, 30708},
+		{0xa824, 0xa827, 3},
+		{0xa880, 0xa881, 1},
+		{0xa8b4, 0xa8c3, 1},
 		{0xa952, 0xa953, 1},
 		{0xa983, 0xa9b4, 49},
 		{0xa9b5, 0xa9ba, 5},
@@ -1473,6 +1577,8 @@ 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},
@@ -1483,6 +1589,12 @@ var _Mc = &RangeTable{
 		{0x11002, 0x11082, 128},
 		{0x110b0, 0x110b2, 1},
 		{0x110b7, 0x110b8, 1},
+		{0x1112c, 0x11182, 86},
+		{0x111b3, 0x111b5, 1},
+		{0x111bf, 0x111c0, 1},
+		{0x116ac, 0x116ae, 2},
+		{0x116af, 0x116b6, 7},
+		{0x16f51, 0x16f7e, 1},
 		{0x1d165, 0x1d166, 1},
 		{0x1d16d, 0x1d172, 1},
 	},
@@ -1521,6 +1633,7 @@ var _Mn = &RangeTable{
 		{0x0825, 0x0827, 1},
 		{0x0829, 0x082d, 1},
 		{0x0859, 0x085b, 1},
+		{0x08e4, 0x08fe, 1},
 		{0x0900, 0x0902, 1},
 		{0x093a, 0x093c, 2},
 		{0x0941, 0x0948, 1},
@@ -1592,6 +1705,7 @@ var _Mn = &RangeTable{
 		{0x1732, 0x1734, 1},
 		{0x1752, 0x1753, 1},
 		{0x1772, 0x1773, 1},
+		{0x17b4, 0x17b5, 1},
 		{0x17b7, 0x17bd, 1},
 		{0x17c6, 0x17c9, 3},
 		{0x17ca, 0x17d3, 1},
@@ -1617,16 +1731,17 @@ var _Mn = &RangeTable{
 		{0x1b80, 0x1b81, 1},
 		{0x1ba2, 0x1ba5, 1},
 		{0x1ba8, 0x1ba9, 1},
-		{0x1be6, 0x1be8, 2},
-		{0x1be9, 0x1bed, 4},
-		{0x1bef, 0x1bf1, 1},
+		{0x1bab, 0x1be6, 59},
+		{0x1be8, 0x1be9, 1},
+		{0x1bed, 0x1bef, 2},
+		{0x1bf0, 0x1bf1, 1},
 		{0x1c2c, 0x1c33, 1},
 		{0x1c36, 0x1c37, 1},
 		{0x1cd0, 0x1cd2, 1},
 		{0x1cd4, 0x1ce0, 1},
 		{0x1ce2, 0x1ce8, 1},
-		{0x1ced, 0x1dc0, 211},
-		{0x1dc1, 0x1de6, 1},
+		{0x1ced, 0x1cf4, 7},
+		{0x1dc0, 0x1de6, 1},
 		{0x1dfc, 0x1dff, 1},
 		{0x20d0, 0x20dc, 1},
 		{0x20e1, 0x20e5, 4},
@@ -1634,10 +1749,11 @@ var _Mn = &RangeTable{
 		{0x2cef, 0x2cf1, 1},
 		{0x2d7f, 0x2de0, 97},
 		{0x2de1, 0x2dff, 1},
-		{0x302a, 0x302f, 1},
+		{0x302a, 0x302d, 1},
 		{0x3099, 0x309a, 1},
-		{0xa66f, 0xa67c, 13},
-		{0xa67d, 0xa6f0, 115},
+		{0xa66f, 0xa674, 5},
+		{0xa675, 0xa67d, 1},
+		{0xa69f, 0xa6f0, 81},
 		{0xa6f1, 0xa802, 273},
 		{0xa806, 0xa80b, 5},
 		{0xa825, 0xa826, 1},
@@ -1657,10 +1773,11 @@ var _Mn = &RangeTable{
 		{0xaab3, 0xaab4, 1},
 		{0xaab7, 0xaab8, 1},
 		{0xaabe, 0xaabf, 1},
-		{0xaac1, 0xabe5, 292},
-		{0xabe8, 0xabed, 5},
-		{0xfb1e, 0xfe00, 738},
-		{0xfe01, 0xfe0f, 1},
+		{0xaac1, 0xaaec, 43},
+		{0xaaed, 0xaaf6, 9},
+		{0xabe5, 0xabe8, 3},
+		{0xabed, 0xfb1e, 20273},
+		{0xfe00, 0xfe0f, 1},
 		{0xfe20, 0xfe26, 1},
 	},
 	R32: []Range32{
@@ -1674,6 +1791,15 @@ var _Mn = &RangeTable{
 		{0x11080, 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},
 		{0x1d167, 0x1d169, 1},
 		{0x1d17b, 0x1d182, 1},
 		{0x1d185, 0x1d18b, 1},
@@ -1735,6 +1861,7 @@ var _N = &RangeTable{
 		{0x3038, 0x303a, 1},
 		{0x3192, 0x3195, 1},
 		{0x3220, 0x3229, 1},
+		{0x3248, 0x324f, 1},
 		{0x3251, 0x325f, 1},
 		{0x3280, 0x3289, 1},
 		{0x32b1, 0x32bf, 1},
@@ -1764,11 +1891,16 @@ var _N = &RangeTable{
 		{0x10b78, 0x10b7f, 1},
 		{0x10e60, 0x10e7e, 1},
 		{0x11052, 0x1106f, 1},
+		{0x110f0, 0x110f9, 1},
+		{0x11136, 0x1113f, 1},
+		{0x111d0, 0x111d9, 1},
+		{0x116c0, 0x116c9, 1},
 		{0x12400, 0x12462, 1},
 		{0x1d360, 0x1d371, 1},
 		{0x1d7ce, 0x1d7ff, 1},
 		{0x1f100, 0x1f10a, 1},
 	},
+	LatinOffset: 4,
 }
 
 var _Nd = &RangeTable{
@@ -1812,8 +1944,13 @@ var _Nd = &RangeTable{
 	R32: []Range32{
 		{0x104a0, 0x104a9, 1},
 		{0x11066, 0x1106f, 1},
+		{0x110f0, 0x110f9, 1},
+		{0x11136, 0x1113f, 1},
+		{0x111d0, 0x111d9, 1},
+		{0x116c0, 0x116c9, 1},
 		{0x1d7ce, 0x1d7ff, 1},
 	},
+	LatinOffset: 1,
 }
 
 var _Nl = &RangeTable{
@@ -1858,6 +1995,7 @@ var _No = &RangeTable{
 		{0x2cfd, 0x3192, 1173},
 		{0x3193, 0x3195, 1},
 		{0x3220, 0x3229, 1},
+		{0x3248, 0x324f, 1},
 		{0x3251, 0x325f, 1},
 		{0x3280, 0x3289, 1},
 		{0x32b1, 0x32bf, 1},
@@ -1879,6 +2017,7 @@ var _No = &RangeTable{
 		{0x1d360, 0x1d371, 1},
 		{0x1f100, 0x1f10a, 1},
 	},
+	LatinOffset: 3,
 }
 
 var _P = &RangeTable{
@@ -1891,7 +2030,8 @@ var _P = &RangeTable{
 		{0x005b, 0x005d, 1},
 		{0x005f, 0x007b, 28},
 		{0x007d, 0x00a1, 36},
-		{0x00ab, 0x00b7, 12},
+		{0x00a7, 0x00ab, 4},
+		{0x00b6, 0x00b7, 1},
 		{0x00bb, 0x00bf, 4},
 		{0x037e, 0x0387, 9},
 		{0x055a, 0x055f, 1},
@@ -1910,16 +2050,18 @@ var _P = &RangeTable{
 		{0x0830, 0x083e, 1},
 		{0x085e, 0x0964, 262},
 		{0x0965, 0x0970, 11},
-		{0x0df4, 0x0e4f, 91},
-		{0x0e5a, 0x0e5b, 1},
-		{0x0f04, 0x0f12, 1},
-		{0x0f3a, 0x0f3d, 1},
+		{0x0af0, 0x0df4, 772},
+		{0x0e4f, 0x0e5a, 11},
+		{0x0e5b, 0x0f04, 169},
+		{0x0f05, 0x0f12, 1},
+		{0x0f14, 0x0f3a, 38},
+		{0x0f3b, 0x0f3d, 1},
 		{0x0f85, 0x0fd0, 75},
 		{0x0fd1, 0x0fd4, 1},
 		{0x0fd9, 0x0fda, 1},
 		{0x104a, 0x104f, 1},
-		{0x10fb, 0x1361, 614},
-		{0x1362, 0x1368, 1},
+		{0x10fb, 0x1360, 613},
+		{0x1361, 0x1368, 1},
 		{0x1400, 0x166d, 621},
 		{0x166e, 0x169b, 45},
 		{0x169c, 0x16eb, 79},
@@ -1936,6 +2078,7 @@ var _P = &RangeTable{
 		{0x1bfc, 0x1bff, 1},
 		{0x1c3b, 0x1c3f, 1},
 		{0x1c7e, 0x1c7f, 1},
+		{0x1cc0, 0x1cc7, 1},
 		{0x1cd3, 0x2010, 829},
 		{0x2011, 0x2027, 1},
 		{0x2030, 0x2043, 1},
@@ -1954,7 +2097,7 @@ var _P = &RangeTable{
 		{0x2cfe, 0x2cff, 1},
 		{0x2d70, 0x2e00, 144},
 		{0x2e01, 0x2e2e, 1},
-		{0x2e30, 0x2e31, 1},
+		{0x2e30, 0x2e3b, 1},
 		{0x3001, 0x3003, 1},
 		{0x3008, 0x3011, 1},
 		{0x3014, 0x301f, 1},
@@ -1973,6 +2116,7 @@ var _P = &RangeTable{
 		{0xa9de, 0xa9df, 1},
 		{0xaa5c, 0xaa5f, 1},
 		{0xaade, 0xaadf, 1},
+		{0xaaf0, 0xaaf1, 1},
 		{0xabeb, 0xfd3e, 20819},
 		{0xfd3f, 0xfe10, 209},
 		{0xfe11, 0xfe19, 1},
@@ -1991,7 +2135,7 @@ var _P = &RangeTable{
 		{0xff60, 0xff65, 1},
 	},
 	R32: []Range32{
-		{0x10100, 0x10101, 1},
+		{0x10100, 0x10102, 1},
 		{0x1039f, 0x103d0, 49},
 		{0x10857, 0x1091f, 200},
 		{0x1093f, 0x10a50, 273},
@@ -2001,8 +2145,11 @@ var _P = &RangeTable{
 		{0x11047, 0x1104d, 1},
 		{0x110bb, 0x110bc, 1},
 		{0x110be, 0x110c1, 1},
+		{0x11140, 0x11143, 1},
+		{0x111c5, 0x111c8, 1},
 		{0x12470, 0x12473, 1},
 	},
+	LatinOffset: 11,
 }
 
 var _Pc = &RangeTable{
@@ -2022,6 +2169,7 @@ var _Pd = &RangeTable{
 		{0x1806, 0x2010, 2058},
 		{0x2011, 0x2015, 1},
 		{0x2e17, 0x2e1a, 3},
+		{0x2e3a, 0x2e3b, 1},
 		{0x301c, 0x3030, 20},
 		{0x30a0, 0xfe31, 52625},
 		{0xfe32, 0xfe58, 38},
@@ -2053,6 +2201,7 @@ var _Pe = &RangeTable{
 		{0xff09, 0xff3d, 52},
 		{0xff5d, 0xff63, 3},
 	},
+	LatinOffset: 1,
 }
 
 var _Pf = &RangeTable{
@@ -2084,7 +2233,8 @@ var _Po = &RangeTable{
 		{0x002f, 0x003a, 11},
 		{0x003b, 0x003f, 4},
 		{0x0040, 0x005c, 28},
-		{0x00a1, 0x00b7, 22},
+		{0x00a1, 0x00a7, 6},
+		{0x00b6, 0x00b7, 1},
 		{0x00bf, 0x037e, 703},
 		{0x0387, 0x055a, 467},
 		{0x055b, 0x055f, 1},
@@ -2102,15 +2252,16 @@ var _Po = &RangeTable{
 		{0x0830, 0x083e, 1},
 		{0x085e, 0x0964, 262},
 		{0x0965, 0x0970, 11},
-		{0x0df4, 0x0e4f, 91},
-		{0x0e5a, 0x0e5b, 1},
-		{0x0f04, 0x0f12, 1},
-		{0x0f85, 0x0fd0, 75},
-		{0x0fd1, 0x0fd4, 1},
+		{0x0af0, 0x0df4, 772},
+		{0x0e4f, 0x0e5a, 11},
+		{0x0e5b, 0x0f04, 169},
+		{0x0f05, 0x0f12, 1},
+		{0x0f14, 0x0f85, 113},
+		{0x0fd0, 0x0fd4, 1},
 		{0x0fd9, 0x0fda, 1},
 		{0x104a, 0x104f, 1},
-		{0x10fb, 0x1361, 614},
-		{0x1362, 0x1368, 1},
+		{0x10fb, 0x1360, 613},
+		{0x1361, 0x1368, 1},
 		{0x166d, 0x166e, 1},
 		{0x16eb, 0x16ed, 1},
 		{0x1735, 0x1736, 1},
@@ -2126,6 +2277,7 @@ var _Po = &RangeTable{
 		{0x1bfc, 0x1bff, 1},
 		{0x1c3b, 0x1c3f, 1},
 		{0x1c7e, 0x1c7f, 1},
+		{0x1cc0, 0x1cc7, 1},
 		{0x1cd3, 0x2016, 835},
 		{0x2017, 0x2020, 9},
 		{0x2021, 0x2027, 1},
@@ -2146,7 +2298,7 @@ var _Po = &RangeTable{
 		{0x2e1b, 0x2e1e, 3},
 		{0x2e1f, 0x2e2a, 11},
 		{0x2e2b, 0x2e2e, 1},
-		{0x2e30, 0x2e31, 1},
+		{0x2e30, 0x2e39, 1},
 		{0x3001, 0x3003, 1},
 		{0x303d, 0x30fb, 190},
 		{0xa4fe, 0xa4ff, 1},
@@ -2162,6 +2314,7 @@ var _Po = &RangeTable{
 		{0xa9de, 0xa9df, 1},
 		{0xaa5c, 0xaa5f, 1},
 		{0xaade, 0xaadf, 1},
+		{0xaaf0, 0xaaf1, 1},
 		{0xabeb, 0xfe10, 21029},
 		{0xfe11, 0xfe16, 1},
 		{0xfe19, 0xfe30, 23},
@@ -2183,17 +2336,21 @@ var _Po = &RangeTable{
 	},
 	R32: []Range32{
 		{0x10100, 0x10100, 1},
-		{0x10101, 0x1039f, 670},
-		{0x103d0, 0x10857, 1159},
-		{0x1091f, 0x1093f, 32},
-		{0x10a50, 0x10a58, 1},
+		{0x10101, 0x10102, 1},
+		{0x1039f, 0x103d0, 49},
+		{0x10857, 0x1091f, 200},
+		{0x1093f, 0x10a50, 273},
+		{0x10a51, 0x10a58, 1},
 		{0x10a7f, 0x10b39, 186},
 		{0x10b3a, 0x10b3f, 1},
 		{0x11047, 0x1104d, 1},
 		{0x110bb, 0x110bc, 1},
 		{0x110be, 0x110c1, 1},
+		{0x11140, 0x11143, 1},
+		{0x111c5, 0x111c8, 1},
 		{0x12470, 0x12473, 1},
 	},
+	LatinOffset: 8,
 }
 
 var _Ps = &RangeTable{
@@ -2222,6 +2379,7 @@ var _Ps = &RangeTable{
 		{0xff5b, 0xff5f, 4},
 		{0xff62, 0xff62, 1},
 	},
+	LatinOffset: 1,
 }
 
 var _S = &RangeTable{
@@ -2230,10 +2388,11 @@ var _S = &RangeTable{
 		{0x003c, 0x003e, 1},
 		{0x005e, 0x0060, 2},
 		{0x007c, 0x007e, 2},
-		{0x00a2, 0x00a9, 1},
+		{0x00a2, 0x00a6, 1},
+		{0x00a8, 0x00a9, 1},
 		{0x00ac, 0x00ae, 2},
 		{0x00af, 0x00b1, 1},
-		{0x00b4, 0x00b8, 2},
+		{0x00b4, 0x00b8, 4},
 		{0x00d7, 0x00f7, 32},
 		{0x02c2, 0x02c5, 1},
 		{0x02d2, 0x02df, 1},
@@ -2242,8 +2401,8 @@ var _S = &RangeTable{
 		{0x02f0, 0x02ff, 1},
 		{0x0375, 0x0384, 15},
 		{0x0385, 0x03f6, 113},
-		{0x0482, 0x0606, 388},
-		{0x0607, 0x0608, 1},
+		{0x0482, 0x058f, 269},
+		{0x0606, 0x0608, 1},
 		{0x060b, 0x060e, 3},
 		{0x060f, 0x06de, 207},
 		{0x06e9, 0x06fd, 20},
@@ -2255,7 +2414,8 @@ var _S = &RangeTable{
 		{0x0c7f, 0x0d79, 250},
 		{0x0e3f, 0x0f01, 194},
 		{0x0f02, 0x0f03, 1},
-		{0x0f13, 0x0f17, 1},
+		{0x0f13, 0x0f15, 2},
+		{0x0f16, 0x0f17, 1},
 		{0x0f1a, 0x0f1f, 1},
 		{0x0f34, 0x0f38, 2},
 		{0x0fbe, 0x0fc5, 1},
@@ -2263,8 +2423,7 @@ var _S = &RangeTable{
 		{0x0fce, 0x0fcf, 1},
 		{0x0fd5, 0x0fd8, 1},
 		{0x109e, 0x109f, 1},
-		{0x1360, 0x1390, 48},
-		{0x1391, 0x1399, 1},
+		{0x1390, 0x1399, 1},
 		{0x17db, 0x1940, 357},
 		{0x19de, 0x19ff, 1},
 		{0x1b61, 0x1b6a, 1},
@@ -2278,7 +2437,7 @@ var _S = &RangeTable{
 		{0x2044, 0x2052, 14},
 		{0x207a, 0x207c, 1},
 		{0x208a, 0x208c, 1},
-		{0x20a0, 0x20b9, 1},
+		{0x20a0, 0x20ba, 1},
 		{0x2100, 0x2101, 1},
 		{0x2103, 0x2106, 1},
 		{0x2108, 0x2109, 1},
@@ -2299,9 +2458,7 @@ var _S = &RangeTable{
 		{0x2500, 0x26ff, 1},
 		{0x2701, 0x2767, 1},
 		{0x2794, 0x27c4, 1},
-		{0x27c7, 0x27ca, 1},
-		{0x27cc, 0x27ce, 2},
-		{0x27cf, 0x27e5, 1},
+		{0x27c7, 0x27e5, 1},
 		{0x27f0, 0x2982, 1},
 		{0x2999, 0x29d7, 1},
 		{0x29dc, 0x29fb, 1},
@@ -2321,8 +2478,9 @@ var _S = &RangeTable{
 		{0x3196, 0x319f, 1},
 		{0x31c0, 0x31e3, 1},
 		{0x3200, 0x321e, 1},
-		{0x322a, 0x3250, 1},
-		{0x3260, 0x327f, 1},
+		{0x322a, 0x3247, 1},
+		{0x3250, 0x3260, 16},
+		{0x3261, 0x327f, 1},
 		{0x328a, 0x32b0, 1},
 		{0x32c0, 0x32fe, 1},
 		{0x3300, 0x33ff, 1},
@@ -2349,8 +2507,7 @@ var _S = &RangeTable{
 		{0xfffc, 0xfffd, 1},
 	},
 	R32: []Range32{
-		{0x10102, 0x10137, 53},
-		{0x10138, 0x1013f, 1},
+		{0x10137, 0x1013f, 1},
 		{0x10179, 0x10189, 1},
 		{0x10190, 0x1019b, 1},
 		{0x101d0, 0x101fc, 1},
@@ -2369,6 +2526,7 @@ var _S = &RangeTable{
 		{0x1d735, 0x1d74f, 26},
 		{0x1d76f, 0x1d789, 26},
 		{0x1d7a9, 0x1d7c3, 26},
+		{0x1eef0, 0x1eef1, 1},
 		{0x1f000, 0x1f02b, 1},
 		{0x1f030, 0x1f093, 1},
 		{0x1f0a0, 0x1f0ae, 1},
@@ -2376,7 +2534,7 @@ var _S = &RangeTable{
 		{0x1f0c1, 0x1f0cf, 1},
 		{0x1f0d1, 0x1f0df, 1},
 		{0x1f110, 0x1f12e, 1},
-		{0x1f130, 0x1f169, 1},
+		{0x1f130, 0x1f16b, 1},
 		{0x1f170, 0x1f19a, 1},
 		{0x1f1e6, 0x1f202, 1},
 		{0x1f210, 0x1f23a, 1},
@@ -2394,37 +2552,32 @@ var _S = &RangeTable{
 		{0x1f443, 0x1f4f7, 1},
 		{0x1f4f9, 0x1f4fc, 1},
 		{0x1f500, 0x1f53d, 1},
+		{0x1f540, 0x1f543, 1},
 		{0x1f550, 0x1f567, 1},
-		{0x1f5fb, 0x1f5ff, 1},
-		{0x1f601, 0x1f610, 1},
-		{0x1f612, 0x1f614, 1},
-		{0x1f616, 0x1f61c, 2},
-		{0x1f61d, 0x1f61e, 1},
-		{0x1f620, 0x1f625, 1},
-		{0x1f628, 0x1f62b, 1},
-		{0x1f62d, 0x1f630, 3},
-		{0x1f631, 0x1f633, 1},
-		{0x1f635, 0x1f640, 1},
+		{0x1f5fb, 0x1f640, 1},
 		{0x1f645, 0x1f64f, 1},
 		{0x1f680, 0x1f6c5, 1},
 		{0x1f700, 0x1f773, 1},
 	},
+	LatinOffset: 10,
 }
 
 var _Sc = &RangeTable{
 	R16: []Range16{
 		{0x0024, 0x00a2, 126},
 		{0x00a3, 0x00a5, 1},
-		{0x060b, 0x09f2, 999},
-		{0x09f3, 0x09fb, 8},
-		{0x0af1, 0x0bf9, 264},
-		{0x0e3f, 0x17db, 2460},
-		{0x20a0, 0x20b9, 1},
+		{0x058f, 0x060b, 124},
+		{0x09f2, 0x09f3, 1},
+		{0x09fb, 0x0af1, 246},
+		{0x0bf9, 0x0e3f, 582},
+		{0x17db, 0x20a0, 2245},
+		{0x20a1, 0x20ba, 1},
 		{0xa838, 0xfdfc, 21956},
 		{0xfe69, 0xff04, 155},
 		{0xffe0, 0xffe1, 1},
 		{0xffe5, 0xffe6, 1},
 	},
+	LatinOffset: 2,
 }
 
 var _Sk = &RangeTable{
@@ -2452,6 +2605,7 @@ var _Sk = &RangeTable{
 		{0xff3e, 0xff40, 2},
 		{0xffe3, 0xffe3, 1},
 	},
+	LatinOffset: 3,
 }
 
 var _Sm = &RangeTable{
@@ -2485,9 +2639,7 @@ var _Sm = &RangeTable{
 		{0x25f8, 0x25ff, 1},
 		{0x266f, 0x27c0, 337},
 		{0x27c1, 0x27c4, 1},
-		{0x27c7, 0x27ca, 1},
-		{0x27cc, 0x27ce, 2},
-		{0x27cf, 0x27e5, 1},
+		{0x27c7, 0x27e5, 1},
 		{0x27f0, 0x27ff, 1},
 		{0x2900, 0x2982, 1},
 		{0x2999, 0x29d7, 1},
@@ -2509,14 +2661,15 @@ var _Sm = &RangeTable{
 		{0x1d735, 0x1d74f, 26},
 		{0x1d76f, 0x1d789, 26},
 		{0x1d7a9, 0x1d7c3, 26},
+		{0x1eef0, 0x1eef1, 1},
 	},
+	LatinOffset: 5,
 }
 
 var _So = &RangeTable{
 	R16: []Range16{
-		{0x00a6, 0x00a7, 1},
-		{0x00a9, 0x00ae, 5},
-		{0x00b0, 0x00b6, 6},
+		{0x00a6, 0x00a9, 3},
+		{0x00ae, 0x00b0, 2},
 		{0x0482, 0x060e, 396},
 		{0x060f, 0x06de, 207},
 		{0x06e9, 0x06fd, 20},
@@ -2526,7 +2679,8 @@ var _So = &RangeTable{
 		{0x0bfa, 0x0c7f, 133},
 		{0x0d79, 0x0f01, 392},
 		{0x0f02, 0x0f03, 1},
-		{0x0f13, 0x0f17, 1},
+		{0x0f13, 0x0f15, 2},
+		{0x0f16, 0x0f17, 1},
 		{0x0f1a, 0x0f1f, 1},
 		{0x0f34, 0x0f38, 2},
 		{0x0fbe, 0x0fc5, 1},
@@ -2534,8 +2688,7 @@ var _So = &RangeTable{
 		{0x0fce, 0x0fcf, 1},
 		{0x0fd5, 0x0fd8, 1},
 		{0x109e, 0x109f, 1},
-		{0x1360, 0x1390, 48},
-		{0x1391, 0x1399, 1},
+		{0x1390, 0x1399, 1},
 		{0x1940, 0x19de, 158},
 		{0x19df, 0x19ff, 1},
 		{0x1b61, 0x1b6a, 1},
@@ -2594,8 +2747,9 @@ var _So = &RangeTable{
 		{0x3196, 0x319f, 1},
 		{0x31c0, 0x31e3, 1},
 		{0x3200, 0x321e, 1},
-		{0x322a, 0x3250, 1},
-		{0x3260, 0x327f, 1},
+		{0x322a, 0x3247, 1},
+		{0x3250, 0x3260, 16},
+		{0x3261, 0x327f, 1},
 		{0x328a, 0x32b0, 1},
 		{0x32c0, 0x32fe, 1},
 		{0x3300, 0x33ff, 1},
@@ -2611,8 +2765,8 @@ var _So = &RangeTable{
 		{0xfffd, 0xfffd, 1},
 	},
 	R32: []Range32{
-		{0x10102, 0x10102, 1},
-		{0x10137, 0x1013f, 1},
+		{0x10137, 0x10137, 1},
+		{0x10138, 0x1013f, 1},
 		{0x10179, 0x10189, 1},
 		{0x10190, 0x1019b, 1},
 		{0x101d0, 0x101fc, 1},
@@ -2633,7 +2787,7 @@ var _So = &RangeTable{
 		{0x1f0c1, 0x1f0cf, 1},
 		{0x1f0d1, 0x1f0df, 1},
 		{0x1f110, 0x1f12e, 1},
-		{0x1f130, 0x1f169, 1},
+		{0x1f130, 0x1f16b, 1},
 		{0x1f170, 0x1f19a, 1},
 		{0x1f1e6, 0x1f202, 1},
 		{0x1f210, 0x1f23a, 1},
@@ -2651,21 +2805,14 @@ var _So = &RangeTable{
 		{0x1f443, 0x1f4f7, 1},
 		{0x1f4f9, 0x1f4fc, 1},
 		{0x1f500, 0x1f53d, 1},
+		{0x1f540, 0x1f543, 1},
 		{0x1f550, 0x1f567, 1},
-		{0x1f5fb, 0x1f5ff, 1},
-		{0x1f601, 0x1f610, 1},
-		{0x1f612, 0x1f614, 1},
-		{0x1f616, 0x1f61c, 2},
-		{0x1f61d, 0x1f61e, 1},
-		{0x1f620, 0x1f625, 1},
-		{0x1f628, 0x1f62b, 1},
-		{0x1f62d, 0x1f630, 3},
-		{0x1f631, 0x1f633, 1},
-		{0x1f635, 0x1f640, 1},
+		{0x1f5fb, 0x1f640, 1},
 		{0x1f645, 0x1f64f, 1},
 		{0x1f680, 0x1f6c5, 1},
 		{0x1f700, 0x1f773, 1},
 	},
+	LatinOffset: 2,
 }
 
 var _Z = &RangeTable{
@@ -2677,6 +2824,7 @@ var _Z = &RangeTable{
 		{0x202f, 0x205f, 48},
 		{0x3000, 0x3000, 1},
 	},
+	LatinOffset: 1,
 }
 
 var _Zl = &RangeTable{
@@ -2699,6 +2847,7 @@ var _Zs = &RangeTable{
 		{0x202f, 0x205f, 48},
 		{0x3000, 0x3000, 1},
 	},
+	LatinOffset: 1,
 }
 
 // These variables have type *RangeTable.
@@ -2753,7 +2902,7 @@ var (
 )
 
 // Generated by running
-//	maketables --scripts=all --url=http://www.unicode.org/Public/6.0.0/ucd/
+//	maketables --scripts=all --url=http://www.unicode.org/Public/6.2.0/ucd/
 // DO NOT EDIT
 
 // Scripts is the set of Unicode script tables.
@@ -2772,6 +2921,7 @@ var Scripts = map[string]*RangeTable{
 	"Buhid":                  Buhid,
 	"Canadian_Aboriginal":    Canadian_Aboriginal,
 	"Carian":                 Carian,
+	"Chakma":                 Chakma,
 	"Cham":                   Cham,
 	"Cherokee":               Cherokee,
 	"Common":                 Common,
@@ -2816,6 +2966,9 @@ var Scripts = map[string]*RangeTable{
 	"Malayalam":              Malayalam,
 	"Mandaic":                Mandaic,
 	"Meetei_Mayek":           Meetei_Mayek,
+	"Meroitic_Cursive":       Meroitic_Cursive,
+	"Meroitic_Hieroglyphs":   Meroitic_Hieroglyphs,
+	"Miao":                   Miao,
 	"Mongolian":              Mongolian,
 	"Myanmar":                Myanmar,
 	"New_Tai_Lue":            New_Tai_Lue,
@@ -2834,8 +2987,10 @@ var Scripts = map[string]*RangeTable{
 	"Runic":                  Runic,
 	"Samaritan":              Samaritan,
 	"Saurashtra":             Saurashtra,
+	"Sharada":                Sharada,
 	"Shavian":                Shavian,
 	"Sinhala":                Sinhala,
+	"Sora_Sompeng":           Sora_Sompeng,
 	"Sundanese":              Sundanese,
 	"Syloti_Nagri":           Syloti_Nagri,
 	"Syriac":                 Syriac,
@@ -2844,6 +2999,7 @@ var Scripts = map[string]*RangeTable{
 	"Tai_Le":                 Tai_Le,
 	"Tai_Tham":               Tai_Tham,
 	"Tai_Viet":               Tai_Viet,
+	"Takri":                  Takri,
 	"Tamil":                  Tamil,
 	"Telugu":                 Telugu,
 	"Thaana":                 Thaana,
@@ -2857,17 +3013,20 @@ var Scripts = map[string]*RangeTable{
 
 var _Arabic = &RangeTable{
 	R16: []Range16{
-		{0x0600, 0x0603, 1},
+		{0x0600, 0x0604, 1},
 		{0x0606, 0x060b, 1},
 		{0x060d, 0x061a, 1},
 		{0x061e, 0x061e, 1},
 		{0x0620, 0x063f, 1},
 		{0x0641, 0x064a, 1},
-		{0x0656, 0x065e, 1},
+		{0x0656, 0x065f, 1},
 		{0x066a, 0x066f, 1},
 		{0x0671, 0x06dc, 1},
 		{0x06de, 0x06ff, 1},
 		{0x0750, 0x077f, 1},
+		{0x08a0, 0x08a0, 1},
+		{0x08a2, 0x08ac, 1},
+		{0x08e4, 0x08fe, 1},
 		{0xfb50, 0xfbc1, 1},
 		{0xfbd3, 0xfd3d, 1},
 		{0xfd50, 0xfd8f, 1},
@@ -2878,6 +3037,40 @@ var _Arabic = &RangeTable{
 	},
 	R32: []Range32{
 		{0x10e60, 0x10e7e, 1},
+		{0x1ee00, 0x1ee03, 1},
+		{0x1ee05, 0x1ee1f, 1},
+		{0x1ee21, 0x1ee22, 1},
+		{0x1ee24, 0x1ee24, 1},
+		{0x1ee27, 0x1ee27, 1},
+		{0x1ee29, 0x1ee32, 1},
+		{0x1ee34, 0x1ee37, 1},
+		{0x1ee39, 0x1ee39, 1},
+		{0x1ee3b, 0x1ee3b, 1},
+		{0x1ee42, 0x1ee42, 1},
+		{0x1ee47, 0x1ee47, 1},
+		{0x1ee49, 0x1ee49, 1},
+		{0x1ee4b, 0x1ee4b, 1},
+		{0x1ee4d, 0x1ee4f, 1},
+		{0x1ee51, 0x1ee52, 1},
+		{0x1ee54, 0x1ee54, 1},
+		{0x1ee57, 0x1ee57, 1},
+		{0x1ee59, 0x1ee59, 1},
+		{0x1ee5b, 0x1ee5b, 1},
+		{0x1ee5d, 0x1ee5d, 1},
+		{0x1ee5f, 0x1ee5f, 1},
+		{0x1ee61, 0x1ee62, 1},
+		{0x1ee64, 0x1ee64, 1},
+		{0x1ee67, 0x1ee6a, 1},
+		{0x1ee6c, 0x1ee72, 1},
+		{0x1ee74, 0x1ee77, 1},
+		{0x1ee79, 0x1ee7c, 1},
+		{0x1ee7e, 0x1ee7e, 1},
+		{0x1ee80, 0x1ee89, 1},
+		{0x1ee8b, 0x1ee9b, 1},
+		{0x1eea1, 0x1eea3, 1},
+		{0x1eea5, 0x1eea9, 1},
+		{0x1eeab, 0x1eebb, 1},
+		{0x1eef0, 0x1eef1, 1},
 	},
 }
 
@@ -2887,6 +3080,7 @@ var _Armenian = &RangeTable{
 		{0x0559, 0x055f, 1},
 		{0x0561, 0x0587, 1},
 		{0x058a, 0x058a, 1},
+		{0x058f, 0x058f, 1},
 		{0xfb13, 0xfb17, 1},
 	},
 }
@@ -2990,6 +3184,14 @@ var _Carian = &RangeTable{
 	},
 }
 
+var _Chakma = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x11100, 0x11134, 1},
+		{0x11136, 0x11143, 1},
+	},
+}
+
 var _Cham = &RangeTable{
 	R16: []Range16{
 		{0xaa00, 0xaa36, 1},
@@ -3029,7 +3231,6 @@ var _Common = &RangeTable{
 		{0x0660, 0x0669, 1},
 		{0x06dd, 0x06dd, 1},
 		{0x0964, 0x0965, 1},
-		{0x0970, 0x0970, 1},
 		{0x0e3f, 0x0e3f, 1},
 		{0x0fd5, 0x0fd8, 1},
 		{0x10fb, 0x10fb, 1},
@@ -3040,13 +3241,14 @@ var _Common = &RangeTable{
 		{0x1cd3, 0x1cd3, 1},
 		{0x1ce1, 0x1ce1, 1},
 		{0x1ce9, 0x1cec, 1},
-		{0x1cee, 0x1cf2, 1},
+		{0x1cee, 0x1cf3, 1},
+		{0x1cf5, 0x1cf6, 1},
 		{0x2000, 0x200b, 1},
 		{0x200e, 0x2064, 1},
 		{0x206a, 0x2070, 1},
 		{0x2074, 0x207e, 1},
 		{0x2080, 0x208e, 1},
-		{0x20a0, 0x20b9, 1},
+		{0x20a0, 0x20ba, 1},
 		{0x2100, 0x2125, 1},
 		{0x2127, 0x2129, 1},
 		{0x212c, 0x2131, 1},
@@ -3057,12 +3259,10 @@ var _Common = &RangeTable{
 		{0x2400, 0x2426, 1},
 		{0x2440, 0x244a, 1},
 		{0x2460, 0x26ff, 1},
-		{0x2701, 0x27ca, 1},
-		{0x27cc, 0x27cc, 1},
-		{0x27ce, 0x27ff, 1},
+		{0x2701, 0x27ff, 1},
 		{0x2900, 0x2b4c, 1},
 		{0x2b50, 0x2b59, 1},
-		{0x2e00, 0x2e31, 1},
+		{0x2e00, 0x2e3b, 1},
 		{0x2ff0, 0x2ffb, 1},
 		{0x3000, 0x3004, 1},
 		{0x3006, 0x3006, 1},
@@ -3141,7 +3341,7 @@ var _Common = &RangeTable{
 		{0x1f0d1, 0x1f0df, 1},
 		{0x1f100, 0x1f10a, 1},
 		{0x1f110, 0x1f12e, 1},
-		{0x1f130, 0x1f169, 1},
+		{0x1f130, 0x1f16b, 1},
 		{0x1f170, 0x1f19a, 1},
 		{0x1f1e6, 0x1f1ff, 1},
 		{0x1f201, 0x1f202, 1},
@@ -3160,31 +3360,22 @@ var _Common = &RangeTable{
 		{0x1f442, 0x1f4f7, 1},
 		{0x1f4f9, 0x1f4fc, 1},
 		{0x1f500, 0x1f53d, 1},
+		{0x1f540, 0x1f543, 1},
 		{0x1f550, 0x1f567, 1},
-		{0x1f5fb, 0x1f5ff, 1},
-		{0x1f601, 0x1f610, 1},
-		{0x1f612, 0x1f614, 1},
-		{0x1f616, 0x1f616, 1},
-		{0x1f618, 0x1f618, 1},
-		{0x1f61a, 0x1f61a, 1},
-		{0x1f61c, 0x1f61e, 1},
-		{0x1f620, 0x1f625, 1},
-		{0x1f628, 0x1f62b, 1},
-		{0x1f62d, 0x1f62d, 1},
-		{0x1f630, 0x1f633, 1},
-		{0x1f635, 0x1f640, 1},
+		{0x1f5fb, 0x1f640, 1},
 		{0x1f645, 0x1f64f, 1},
 		{0x1f680, 0x1f6c5, 1},
 		{0x1f700, 0x1f773, 1},
 		{0xe0001, 0xe0001, 1},
 		{0xe0020, 0xe007f, 1},
 	},
+	LatinOffset: 7,
 }
 
 var _Coptic = &RangeTable{
 	R16: []Range16{
 		{0x03e2, 0x03ef, 1},
-		{0x2c80, 0x2cf1, 1},
+		{0x2c80, 0x2cf3, 1},
 		{0x2cf9, 0x2cff, 1},
 	},
 }
@@ -3217,8 +3408,8 @@ var _Cyrillic = &RangeTable{
 		{0x1d2b, 0x1d2b, 1},
 		{0x1d78, 0x1d78, 1},
 		{0x2de0, 0x2dff, 1},
-		{0xa640, 0xa673, 1},
-		{0xa67c, 0xa697, 1},
+		{0xa640, 0xa697, 1},
+		{0xa69f, 0xa69f, 1},
 	},
 }
 
@@ -3233,8 +3424,7 @@ var _Devanagari = &RangeTable{
 	R16: []Range16{
 		{0x0900, 0x0950, 1},
 		{0x0953, 0x0963, 1},
-		{0x0966, 0x096f, 1},
-		{0x0971, 0x0977, 1},
+		{0x0966, 0x0977, 1},
 		{0x0979, 0x097f, 1},
 		{0xa8e0, 0xa8fb, 1},
 	},
@@ -3287,9 +3477,13 @@ var _Ethiopic = &RangeTable{
 var _Georgian = &RangeTable{
 	R16: []Range16{
 		{0x10a0, 0x10c5, 1},
+		{0x10c7, 0x10c7, 1},
+		{0x10cd, 0x10cd, 1},
 		{0x10d0, 0x10fa, 1},
-		{0x10fc, 0x10fc, 1},
+		{0x10fc, 0x10ff, 1},
 		{0x2d00, 0x2d25, 1},
+		{0x2d27, 0x2d27, 1},
+		{0x2d2d, 0x2d2d, 1},
 	},
 }
 
@@ -3361,8 +3555,7 @@ var _Gujarati = &RangeTable{
 		{0x0acb, 0x0acd, 1},
 		{0x0ad0, 0x0ad0, 1},
 		{0x0ae0, 0x0ae3, 1},
-		{0x0ae6, 0x0aef, 1},
-		{0x0af1, 0x0af1, 1},
+		{0x0ae6, 0x0af1, 1},
 	},
 }
 
@@ -3397,9 +3590,8 @@ var _Han = &RangeTable{
 		{0x3021, 0x3029, 1},
 		{0x3038, 0x303b, 1},
 		{0x3400, 0x4db5, 1},
-		{0x4e00, 0x9fcb, 1},
-		{0xf900, 0xfa2d, 1},
-		{0xfa30, 0xfa6d, 1},
+		{0x4e00, 0x9fcc, 1},
+		{0xf900, 0xfa6d, 1},
 		{0xfa70, 0xfad9, 1},
 	},
 	R32: []Range32{
@@ -3473,13 +3665,13 @@ var _Inherited = &RangeTable{
 		{0x0300, 0x036f, 1},
 		{0x0485, 0x0486, 1},
 		{0x064b, 0x0655, 1},
-		{0x065f, 0x065f, 1},
 		{0x0670, 0x0670, 1},
 		{0x0951, 0x0952, 1},
 		{0x1cd0, 0x1cd2, 1},
 		{0x1cd4, 0x1ce0, 1},
 		{0x1ce2, 0x1ce8, 1},
 		{0x1ced, 0x1ced, 1},
+		{0x1cf4, 0x1cf4, 1},
 		{0x1dc0, 0x1de6, 1},
 		{0x1dfc, 0x1dff, 1},
 		{0x200c, 0x200d, 1},
@@ -3612,7 +3804,7 @@ var _Lao = &RangeTable{
 		{0x0ec6, 0x0ec6, 1},
 		{0x0ec8, 0x0ecd, 1},
 		{0x0ed0, 0x0ed9, 1},
-		{0x0edc, 0x0edd, 1},
+		{0x0edc, 0x0edf, 1},
 	},
 }
 
@@ -3642,13 +3834,14 @@ var _Latin = &RangeTable{
 		{0x2c60, 0x2c7f, 1},
 		{0xa722, 0xa787, 1},
 		{0xa78b, 0xa78e, 1},
-		{0xa790, 0xa791, 1},
-		{0xa7a0, 0xa7a9, 1},
-		{0xa7fa, 0xa7ff, 1},
+		{0xa790, 0xa793, 1},
+		{0xa7a0, 0xa7aa, 1},
+		{0xa7f8, 0xa7ff, 1},
 		{0xfb00, 0xfb06, 1},
 		{0xff21, 0xff3a, 1},
 		{0xff41, 0xff5a, 1},
 	},
+	LatinOffset: 6,
 }
 
 var _Lepcha = &RangeTable{
@@ -3728,11 +3921,36 @@ var _Mandaic = &RangeTable{
 
 var _Meetei_Mayek = &RangeTable{
 	R16: []Range16{
+		{0xaae0, 0xaaf6, 1},
 		{0xabc0, 0xabed, 1},
 		{0xabf0, 0xabf9, 1},
 	},
 }
 
+var _Meroitic_Cursive = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x109a0, 0x109b7, 1},
+		{0x109be, 0x109bf, 1},
+	},
+}
+
+var _Meroitic_Hieroglyphs = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10980, 0x1099f, 1},
+	},
+}
+
+var _Miao = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x16f00, 0x16f44, 1},
+		{0x16f50, 0x16f7e, 1},
+		{0x16f8f, 0x16f9f, 1},
+	},
+}
+
 var _Mongolian = &RangeTable{
 	R16: []Range16{
 		{0x1800, 0x1801, 1},
@@ -3877,6 +4095,14 @@ var _Saurashtra = &RangeTable{
 	},
 }
 
+var _Sharada = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x11180, 0x111c8, 1},
+		{0x111d0, 0x111d9, 1},
+	},
+}
+
 var _Shavian = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
@@ -3900,10 +4126,18 @@ var _Sinhala = &RangeTable{
 	},
 }
 
+var _Sora_Sompeng = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x110d0, 0x110e8, 1},
+		{0x110f0, 0x110f9, 1},
+	},
+}
+
 var _Sundanese = &RangeTable{
 	R16: []Range16{
-		{0x1b80, 0x1baa, 1},
-		{0x1bae, 0x1bb9, 1},
+		{0x1b80, 0x1bbf, 1},
+		{0x1cc0, 0x1cc7, 1},
 	},
 }
 
@@ -3960,6 +4194,14 @@ var _Tai_Viet = &RangeTable{
 	},
 }
 
+var _Takri = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x11680, 0x116b7, 1},
+		{0x116c0, 0x116c9, 1},
+	},
+}
+
 var _Tamil = &RangeTable{
 	R16: []Range16{
 		{0x0b82, 0x0b83, 1},
@@ -4027,7 +4269,7 @@ var _Tibetan = &RangeTable{
 
 var _Tifinagh = &RangeTable{
 	R16: []Range16{
-		{0x2d30, 0x2d65, 1},
+		{0x2d30, 0x2d67, 1},
 		{0x2d6f, 0x2d70, 1},
 		{0x2d7f, 0x2d7f, 1},
 	},
@@ -4070,6 +4312,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.
+	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.
 	Common                 = _Common                 // Common is the set of Unicode characters in script Common.
@@ -4114,6 +4357,9 @@ var (
 	Malayalam              = _Malayalam              // Malayalam is the set of Unicode characters in script Malayalam.
 	Mandaic                = _Mandaic                // Mandaic is the set of Unicode characters in script Mandaic.
 	Meetei_Mayek           = _Meetei_Mayek           // Meetei_Mayek is the set of Unicode characters in script Meetei_Mayek.
+	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.
 	Mongolian              = _Mongolian              // Mongolian is the set of Unicode characters in script Mongolian.
 	Myanmar                = _Myanmar                // Myanmar is the set of Unicode characters in script Myanmar.
 	New_Tai_Lue            = _New_Tai_Lue            // New_Tai_Lue is the set of Unicode characters in script New_Tai_Lue.
@@ -4132,8 +4378,10 @@ var (
 	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.
 	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.
 	Syloti_Nagri           = _Syloti_Nagri           // Syloti_Nagri is the set of Unicode characters in script Syloti_Nagri.
 	Syriac                 = _Syriac                 // Syriac is the set of Unicode characters in script Syriac.
@@ -4142,6 +4390,7 @@ var (
 	Tai_Le                 = _Tai_Le                 // Tai_Le is the set of Unicode characters in script Tai_Le.
 	Tai_Tham               = _Tai_Tham               // Tai_Tham is the set of Unicode characters in script Tai_Tham.
 	Tai_Viet               = _Tai_Viet               // Tai_Viet is the set of Unicode characters in script Tai_Viet.
+	Takri                  = _Takri                  // Takri is the set of Unicode characters in script Takri.
 	Tamil                  = _Tamil                  // Tamil is the set of Unicode characters in script Tamil.
 	Telugu                 = _Telugu                 // Telugu is the set of Unicode characters in script Telugu.
 	Thaana                 = _Thaana                 // Thaana is the set of Unicode characters in script Thaana.
@@ -4154,7 +4403,7 @@ var (
 )
 
 // Generated by running
-//	maketables --props=all --url=http://www.unicode.org/Public/6.0.0/ucd/
+//	maketables --props=all --url=http://www.unicode.org/Public/6.2.0/ucd/
 // DO NOT EDIT
 
 // Properties is the set of Unicode property tables.
@@ -4199,6 +4448,7 @@ var _ASCII_Hex_Digit = &RangeTable{
 		{0x0041, 0x0046, 1},
 		{0x0061, 0x0066, 1},
 	},
+	LatinOffset: 3,
 }
 
 var _Bidi_Control = &RangeTable{
@@ -4222,6 +4472,7 @@ var _Dash = &RangeTable{
 		{0x2212, 0x2212, 1},
 		{0x2e17, 0x2e17, 1},
 		{0x2e1a, 0x2e1a, 1},
+		{0x2e3a, 0x2e3b, 1},
 		{0x301c, 0x301c, 1},
 		{0x3030, 0x3030, 1},
 		{0x30a0, 0x30a0, 1},
@@ -4230,6 +4481,7 @@ var _Dash = &RangeTable{
 		{0xfe63, 0xfe63, 1},
 		{0xff0d, 0xff0d, 1},
 	},
+	LatinOffset: 1,
 }
 
 var _Deprecated = &RangeTable{
@@ -4278,6 +4530,7 @@ var _Diacritic = &RangeTable{
 		{0x07a6, 0x07b0, 1},
 		{0x07eb, 0x07f5, 1},
 		{0x0818, 0x0819, 1},
+		{0x08e4, 0x08fe, 1},
 		{0x093c, 0x093c, 1},
 		{0x094d, 0x094d, 1},
 		{0x0951, 0x0954, 1},
@@ -4320,11 +4573,12 @@ var _Diacritic = &RangeTable{
 		{0x1b34, 0x1b34, 1},
 		{0x1b44, 0x1b44, 1},
 		{0x1b6b, 0x1b73, 1},
-		{0x1baa, 0x1baa, 1},
+		{0x1baa, 0x1bab, 1},
 		{0x1c36, 0x1c37, 1},
 		{0x1c78, 0x1c7d, 1},
 		{0x1cd0, 0x1ce8, 1},
 		{0x1ced, 0x1ced, 1},
+		{0x1cf4, 0x1cf4, 1},
 		{0x1d2c, 0x1d6a, 1},
 		{0x1dc4, 0x1dcf, 1},
 		{0x1dfd, 0x1dff, 1},
@@ -4345,6 +4599,7 @@ var _Diacritic = &RangeTable{
 		{0xa6f0, 0xa6f1, 1},
 		{0xa717, 0xa721, 1},
 		{0xa788, 0xa788, 1},
+		{0xa7f8, 0xa7f9, 1},
 		{0xa8c4, 0xa8c4, 1},
 		{0xa8e0, 0xa8f1, 1},
 		{0xa92b, 0xa92e, 1},
@@ -4353,6 +4608,7 @@ var _Diacritic = &RangeTable{
 		{0xa9c0, 0xa9c0, 1},
 		{0xaa7b, 0xaa7b, 1},
 		{0xaabf, 0xaac2, 1},
+		{0xaaf6, 0xaaf6, 1},
 		{0xabec, 0xabed, 1},
 		{0xfb1e, 0xfb1e, 1},
 		{0xfe20, 0xfe26, 1},
@@ -4364,12 +4620,17 @@ var _Diacritic = &RangeTable{
 	},
 	R32: []Range32{
 		{0x110b9, 0x110ba, 1},
+		{0x11133, 0x11134, 1},
+		{0x111c0, 0x111c0, 1},
+		{0x116b6, 0x116b7, 1},
+		{0x16f8f, 0x16f9f, 1},
 		{0x1d167, 0x1d169, 1},
 		{0x1d16d, 0x1d172, 1},
 		{0x1d17b, 0x1d182, 1},
 		{0x1d185, 0x1d18b, 1},
 		{0x1d1aa, 0x1d1ad, 1},
 	},
+	LatinOffset: 6,
 }
 
 var _Extender = &RangeTable{
@@ -4380,6 +4641,7 @@ var _Extender = &RangeTable{
 		{0x07fa, 0x07fa, 1},
 		{0x0e46, 0x0e46, 1},
 		{0x0ec6, 0x0ec6, 1},
+		{0x180a, 0x180a, 1},
 		{0x1843, 0x1843, 1},
 		{0x1aa7, 0x1aa7, 1},
 		{0x1c36, 0x1c36, 1},
@@ -4393,8 +4655,10 @@ var _Extender = &RangeTable{
 		{0xa9cf, 0xa9cf, 1},
 		{0xaa70, 0xaa70, 1},
 		{0xaadd, 0xaadd, 1},
+		{0xaaf3, 0xaaf4, 1},
 		{0xff70, 0xff70, 1},
 	},
+	LatinOffset: 1,
 }
 
 var _Hex_Digit = &RangeTable{
@@ -4406,6 +4670,7 @@ var _Hex_Digit = &RangeTable{
 		{0xff21, 0xff26, 1},
 		{0xff41, 0xff46, 1},
 	},
+	LatinOffset: 3,
 }
 
 var _Hyphen = &RangeTable{
@@ -4421,6 +4686,7 @@ var _Hyphen = &RangeTable{
 		{0xff0d, 0xff0d, 1},
 		{0xff65, 0xff65, 1},
 	},
+	LatinOffset: 2,
 }
 
 var _IDS_Binary_Operator = &RangeTable{
@@ -4442,9 +4708,8 @@ var _Ideographic = &RangeTable{
 		{0x3021, 0x3029, 1},
 		{0x3038, 0x303a, 1},
 		{0x3400, 0x4db5, 1},
-		{0x4e00, 0x9fcb, 1},
-		{0xf900, 0xfa2d, 1},
-		{0xfa30, 0xfa6d, 1},
+		{0x4e00, 0x9fcc, 1},
+		{0xf900, 0xfa6d, 1},
 		{0xfa70, 0xfad9, 1},
 	},
 	R32: []Range32{
@@ -4519,6 +4784,8 @@ var _Other_Alphabetic = &RangeTable{
 		{0x081b, 0x0823, 1},
 		{0x0825, 0x0827, 1},
 		{0x0829, 0x082c, 1},
+		{0x08e4, 0x08e9, 1},
+		{0x08f0, 0x08fe, 1},
 		{0x0900, 0x0903, 1},
 		{0x093a, 0x093b, 1},
 		{0x093e, 0x094c, 1},
@@ -4615,11 +4882,14 @@ var _Other_Alphabetic = &RangeTable{
 		{0x1b35, 0x1b43, 1},
 		{0x1b80, 0x1b82, 1},
 		{0x1ba1, 0x1ba9, 1},
+		{0x1bac, 0x1bad, 1},
 		{0x1be7, 0x1bf1, 1},
 		{0x1c24, 0x1c35, 1},
-		{0x1cf2, 0x1cf2, 1},
+		{0x1cf2, 0x1cf3, 1},
 		{0x24b6, 0x24e9, 1},
 		{0x2de0, 0x2dff, 1},
+		{0xa674, 0xa67b, 1},
+		{0xa69f, 0xa69f, 1},
 		{0xa823, 0xa827, 1},
 		{0xa880, 0xa881, 1},
 		{0xa8b4, 0xa8c3, 1},
@@ -4634,6 +4904,8 @@ var _Other_Alphabetic = &RangeTable{
 		{0xaab2, 0xaab4, 1},
 		{0xaab7, 0xaab8, 1},
 		{0xaabe, 0xaabe, 1},
+		{0xaaeb, 0xaaef, 1},
+		{0xaaf5, 0xaaf5, 1},
 		{0xabe3, 0xabea, 1},
 		{0xfb1e, 0xfb1e, 1},
 	},
@@ -4645,6 +4917,12 @@ var _Other_Alphabetic = &RangeTable{
 		{0x11038, 0x11045, 1},
 		{0x11082, 0x11082, 1},
 		{0x110b0, 0x110b8, 1},
+		{0x11100, 0x11102, 1},
+		{0x11127, 0x11132, 1},
+		{0x11180, 0x11182, 1},
+		{0x111b3, 0x111bf, 1},
+		{0x116ab, 0x116b5, 1},
+		{0x16f51, 0x16f7e, 1},
 	},
 }
 
@@ -4652,6 +4930,7 @@ var _Other_Default_Ignorable_Code_Point = &RangeTable{
 	R16: []Range16{
 		{0x034f, 0x034f, 1},
 		{0x115f, 0x1160, 1},
+		{0x17b4, 0x17b5, 1},
 		{0x2065, 0x2069, 1},
 		{0x3164, 0x3164, 1},
 		{0xffa0, 0xffa0, 1},
@@ -4680,6 +4959,7 @@ var _Other_Grapheme_Extend = &RangeTable{
 		{0x0dcf, 0x0dcf, 1},
 		{0x0ddf, 0x0ddf, 1},
 		{0x200c, 0x200d, 1},
+		{0x302e, 0x302f, 1},
 		{0xff9e, 0xff9f, 1},
 	},
 	R32: []Range32{
@@ -4695,6 +4975,7 @@ var _Other_ID_Continue = &RangeTable{
 		{0x1369, 0x1371, 1},
 		{0x19da, 0x19da, 1},
 	},
+	LatinOffset: 1,
 }
 
 var _Other_ID_Start = &RangeTable{
@@ -4707,20 +4988,26 @@ var _Other_ID_Start = &RangeTable{
 
 var _Other_Lowercase = &RangeTable{
 	R16: []Range16{
+		{0x00aa, 0x00aa, 1},
+		{0x00ba, 0x00ba, 1},
 		{0x02b0, 0x02b8, 1},
 		{0x02c0, 0x02c1, 1},
 		{0x02e0, 0x02e4, 1},
 		{0x0345, 0x0345, 1},
 		{0x037a, 0x037a, 1},
-		{0x1d2c, 0x1d61, 1},
+		{0x1d2c, 0x1d6a, 1},
 		{0x1d78, 0x1d78, 1},
 		{0x1d9b, 0x1dbf, 1},
-		{0x2090, 0x2094, 1},
+		{0x2071, 0x2071, 1},
+		{0x207f, 0x207f, 1},
+		{0x2090, 0x209c, 1},
 		{0x2170, 0x217f, 1},
 		{0x24d0, 0x24e9, 1},
-		{0x2c7d, 0x2c7d, 1},
+		{0x2c7c, 0x2c7d, 1},
 		{0xa770, 0xa770, 1},
+		{0xa7f8, 0xa7f9, 1},
 	},
+	LatinOffset: 2,
 }
 
 var _Other_Math = &RangeTable{
@@ -4827,7 +5114,41 @@ var _Other_Math = &RangeTable{
 		{0x1d7aa, 0x1d7c2, 1},
 		{0x1d7c4, 0x1d7cb, 1},
 		{0x1d7ce, 0x1d7ff, 1},
-	},
+		{0x1ee00, 0x1ee03, 1},
+		{0x1ee05, 0x1ee1f, 1},
+		{0x1ee21, 0x1ee22, 1},
+		{0x1ee24, 0x1ee24, 1},
+		{0x1ee27, 0x1ee27, 1},
+		{0x1ee29, 0x1ee32, 1},
+		{0x1ee34, 0x1ee37, 1},
+		{0x1ee39, 0x1ee39, 1},
+		{0x1ee3b, 0x1ee3b, 1},
+		{0x1ee42, 0x1ee42, 1},
+		{0x1ee47, 0x1ee47, 1},
+		{0x1ee49, 0x1ee49, 1},
+		{0x1ee4b, 0x1ee4b, 1},
+		{0x1ee4d, 0x1ee4f, 1},
+		{0x1ee51, 0x1ee52, 1},
+		{0x1ee54, 0x1ee54, 1},
+		{0x1ee57, 0x1ee57, 1},
+		{0x1ee59, 0x1ee59, 1},
+		{0x1ee5b, 0x1ee5b, 1},
+		{0x1ee5d, 0x1ee5d, 1},
+		{0x1ee5f, 0x1ee5f, 1},
+		{0x1ee61, 0x1ee62, 1},
+		{0x1ee64, 0x1ee64, 1},
+		{0x1ee67, 0x1ee6a, 1},
+		{0x1ee6c, 0x1ee72, 1},
+		{0x1ee74, 0x1ee77, 1},
+		{0x1ee79, 0x1ee7c, 1},
+		{0x1ee7e, 0x1ee7e, 1},
+		{0x1ee80, 0x1ee89, 1},
+		{0x1ee8b, 0x1ee9b, 1},
+		{0x1eea1, 0x1eea3, 1},
+		{0x1eea5, 0x1eea9, 1},
+		{0x1eeab, 0x1eebb, 1},
+	},
+	LatinOffset: 1,
 }
 
 var _Other_Uppercase = &RangeTable{
@@ -4868,6 +5189,7 @@ var _Pattern_Syntax = &RangeTable{
 		{0xfd3e, 0xfd3f, 1},
 		{0xfe45, 0xfe46, 1},
 	},
+	LatinOffset: 15,
 }
 
 var _Pattern_White_Space = &RangeTable{
@@ -4878,6 +5200,7 @@ var _Pattern_White_Space = &RangeTable{
 		{0x200e, 0x200f, 1},
 		{0x2028, 0x2029, 1},
 	},
+	LatinOffset: 3,
 }
 
 var _Quotation_Mark = &RangeTable{
@@ -4895,6 +5218,7 @@ var _Quotation_Mark = &RangeTable{
 		{0xff07, 0xff07, 1},
 		{0xff62, 0xff63, 1},
 	},
+	LatinOffset: 4,
 }
 
 var _Radical = &RangeTable{
@@ -4944,6 +5268,7 @@ var _STerm = &RangeTable{
 		{0xa92f, 0xa92f, 1},
 		{0xa9c8, 0xa9c9, 1},
 		{0xaa5d, 0xaa5f, 1},
+		{0xaaf0, 0xaaf1, 1},
 		{0xabeb, 0xabeb, 1},
 		{0xfe52, 0xfe52, 1},
 		{0xfe56, 0xfe57, 1},
@@ -4956,7 +5281,10 @@ var _STerm = &RangeTable{
 		{0x10a56, 0x10a57, 1},
 		{0x11047, 0x11048, 1},
 		{0x110be, 0x110c1, 1},
+		{0x11141, 0x11143, 1},
+		{0x111c5, 0x111c6, 1},
 	},
+	LatinOffset: 3,
 }
 
 var _Soft_Dotted = &RangeTable{
@@ -4995,6 +5323,7 @@ var _Soft_Dotted = &RangeTable{
 		{0x1d65e, 0x1d65f, 1},
 		{0x1d692, 0x1d693, 1},
 	},
+	LatinOffset: 1,
 }
 
 var _Terminal_Punctuation = &RangeTable{
@@ -5048,6 +5377,7 @@ var _Terminal_Punctuation = &RangeTable{
 		{0xa9c7, 0xa9c9, 1},
 		{0xaa5d, 0xaa5f, 1},
 		{0xaadf, 0xaadf, 1},
+		{0xaaf0, 0xaaf1, 1},
 		{0xabeb, 0xabeb, 1},
 		{0xfe50, 0xfe52, 1},
 		{0xfe54, 0xfe57, 1},
@@ -5067,14 +5397,17 @@ var _Terminal_Punctuation = &RangeTable{
 		{0x10b3a, 0x10b3f, 1},
 		{0x11047, 0x1104d, 1},
 		{0x110be, 0x110c1, 1},
+		{0x11141, 0x11143, 1},
+		{0x111c5, 0x111c6, 1},
 		{0x12470, 0x12473, 1},
 	},
+	LatinOffset: 5,
 }
 
 var _Unified_Ideograph = &RangeTable{
 	R16: []Range16{
 		{0x3400, 0x4db5, 1},
-		{0x4e00, 0x9fcb, 1},
+		{0x4e00, 0x9fcc, 1},
 		{0xfa0e, 0xfa0f, 1},
 		{0xfa11, 0xfa11, 1},
 		{0xfa13, 0xfa14, 1},
@@ -5114,6 +5447,7 @@ var _White_Space = &RangeTable{
 		{0x205f, 0x205f, 1},
 		{0x3000, 0x3000, 1},
 	},
+	LatinOffset: 4,
 }
 
 // These variables have type *RangeTable.
@@ -5153,7 +5487,7 @@ var (
 )
 
 // Generated by running
-//	maketables --data=http://www.unicode.org/Public/6.0.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/6.0.0/ucd/CaseFolding.txt
+//	maketables --data=http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/6.2.0/ucd/CaseFolding.txt
 // DO NOT EDIT
 
 // CaseRanges is the table describing case mappings for all letters with
@@ -5254,6 +5588,7 @@ var _CaseRanges = []CaseRange{
 	{0x0260, 0x0260, d{-205, 0, -205}},
 	{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}},
@@ -5315,6 +5650,8 @@ var _CaseRanges = []CaseRange{
 	{0x0531, 0x0556, d{0, 48, 0}},
 	{0x0561, 0x0586, d{-48, 0, -48}},
 	{0x10A0, 0x10C5, d{0, 7264, 0}},
+	{0x10C7, 0x10C7, d{0, 7264, 0}},
+	{0x10CD, 0x10CD, d{0, 7264, 0}},
 	{0x1D79, 0x1D79, d{35332, 0, 35332}},
 	{0x1D7D, 0x1D7D, d{3814, 0, 3814}},
 	{0x1E00, 0x1E95, d{UpperLower, UpperLower, UpperLower}},
@@ -5402,7 +5739,10 @@ var _CaseRanges = []CaseRange{
 	{0x2C7E, 0x2C7F, d{0, -10815, 0}},
 	{0x2C80, 0x2CE3, d{UpperLower, UpperLower, UpperLower}},
 	{0x2CEB, 0x2CEE, d{UpperLower, UpperLower, UpperLower}},
+	{0x2CF2, 0x2CF3, d{UpperLower, UpperLower, UpperLower}},
 	{0x2D00, 0x2D25, d{-7264, 0, -7264}},
+	{0x2D27, 0x2D27, d{-7264, 0, -7264}},
+	{0x2D2D, 0x2D2D, d{-7264, 0, -7264}},
 	{0xA640, 0xA66D, d{UpperLower, UpperLower, UpperLower}},
 	{0xA680, 0xA697, d{UpperLower, UpperLower, UpperLower}},
 	{0xA722, 0xA72F, d{UpperLower, UpperLower, UpperLower}},
@@ -5412,8 +5752,9 @@ var _CaseRanges = []CaseRange{
 	{0xA77E, 0xA787, d{UpperLower, UpperLower, UpperLower}},
 	{0xA78B, 0xA78C, d{UpperLower, UpperLower, UpperLower}},
 	{0xA78D, 0xA78D, d{0, -42280, 0}},
-	{0xA790, 0xA791, d{UpperLower, UpperLower, UpperLower}},
+	{0xA790, 0xA793, d{UpperLower, UpperLower, UpperLower}},
 	{0xA7A0, 0xA7A9, d{UpperLower, UpperLower, UpperLower}},
+	{0xA7AA, 0xA7AA, d{0, -42308, 0}},
 	{0xFF21, 0xFF3A, d{0, 32, 0}},
 	{0xFF41, 0xFF5A, d{-32, 0, -32}},
 	{0x10400, 0x10427, d{0, 40, 0}},
@@ -5587,10 +5928,10 @@ var properties = [MaxLatin1 + 1]uint8{
 	0xA4: pS | pp,  // '¤'
 	0xA5: pS | pp,  // '¥'
 	0xA6: pS | pp,  // '¦'
-	0xA7: pS | pp,  // '§'
+	0xA7: pP | pp,  // '§'
 	0xA8: pS | pp,  // '¨'
 	0xA9: pS | pp,  // '©'
-	0xAA: pLl | pp, // 'ª'
+	0xAA: pLo | pp, // 'ª'
 	0xAB: pP | pp,  // '«'
 	0xAC: pS | pp,  // '¬'
 	0xAD: 0,        // '\u00ad'
@@ -5602,11 +5943,11 @@ var properties = [MaxLatin1 + 1]uint8{
 	0xB3: pN | pp,  // '³'
 	0xB4: pS | pp,  // '´'
 	0xB5: pLl | pp, // 'µ'
-	0xB6: pS | pp,  // '¶'
+	0xB6: pP | pp,  // '¶'
 	0xB7: pP | pp,  // '·'
 	0xB8: pS | pp,  // '¸'
 	0xB9: pN | pp,  // '¹'
-	0xBA: pLl | pp, // 'º'
+	0xBA: pLo | pp, // 'º'
 	0xBB: pP | pp,  // '»'
 	0xBC: pN | pp,  // '¼'
 	0xBD: pN | pp,  // '½'
@@ -5844,6 +6185,7 @@ var foldLl = &RangeTable{
 		{0x04d0, 0x0526, 2},
 		{0x0531, 0x0556, 1},
 		{0x10a0, 0x10c5, 1},
+		{0x10c7, 0x10cd, 6},
 		{0x1e00, 0x1e94, 2},
 		{0x1e9e, 0x1efe, 2},
 		{0x1f08, 0x1f0f, 1},
@@ -5873,20 +6215,22 @@ var foldLl = &RangeTable{
 		{0x2c7e, 0x2c80, 1},
 		{0x2c82, 0x2ce2, 2},
 		{0x2ceb, 0x2ced, 2},
-		{0xa640, 0xa66c, 2},
+		{0x2cf2, 0xa640, 31054},
+		{0xa642, 0xa66c, 2},
 		{0xa680, 0xa696, 2},
 		{0xa722, 0xa72e, 2},
 		{0xa732, 0xa76e, 2},
 		{0xa779, 0xa77d, 2},
 		{0xa77e, 0xa786, 2},
 		{0xa78b, 0xa78d, 2},
-		{0xa790, 0xa7a0, 16},
-		{0xa7a2, 0xa7a8, 2},
+		{0xa790, 0xa792, 2},
+		{0xa7a0, 0xa7aa, 2},
 		{0xff21, 0xff3a, 1},
 	},
 	R32: []Range32{
 		{0x10400, 0x10427, 1},
 	},
+	LatinOffset: 3,
 }
 
 var foldLt = &RangeTable{
@@ -5941,11 +6285,12 @@ var foldLu = &RangeTable{
 		{0x0256, 0x0257, 1},
 		{0x0259, 0x025b, 2},
 		{0x0260, 0x0263, 3},
-		{0x0265, 0x0268, 3},
-		{0x0269, 0x026b, 2},
-		{0x026f, 0x0271, 2},
-		{0x0272, 0x0275, 3},
-		{0x027d, 0x0283, 3},
+		{0x0265, 0x0266, 1},
+		{0x0268, 0x0269, 1},
+		{0x026b, 0x026f, 4},
+		{0x0271, 0x0272, 1},
+		{0x0275, 0x027d, 8},
+		{0x0280, 0x0283, 3},
 		{0x0288, 0x028c, 1},
 		{0x0292, 0x0345, 179},
 		{0x0371, 0x0373, 2},
@@ -5987,7 +6332,9 @@ var foldLu = &RangeTable{
 		{0x2c73, 0x2c76, 3},
 		{0x2c81, 0x2ce3, 2},
 		{0x2cec, 0x2cee, 2},
-		{0x2d00, 0x2d25, 1},
+		{0x2cf3, 0x2d00, 13},
+		{0x2d01, 0x2d25, 1},
+		{0x2d27, 0x2d2d, 6},
 		{0xa641, 0xa66d, 2},
 		{0xa681, 0xa697, 2},
 		{0xa723, 0xa72f, 2},
@@ -5995,12 +6342,14 @@ var foldLu = &RangeTable{
 		{0xa77a, 0xa77c, 2},
 		{0xa77f, 0xa787, 2},
 		{0xa78c, 0xa791, 5},
-		{0xa7a1, 0xa7a9, 2},
+		{0xa793, 0xa7a1, 14},
+		{0xa7a3, 0xa7a9, 2},
 		{0xff41, 0xff5a, 1},
 	},
 	R32: []Range32{
 		{0x10428, 0x1044f, 1},
 	},
+	LatinOffset: 4,
 }
 
 var foldM = &RangeTable{
@@ -6023,7 +6372,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: 3391 16-bit, 659 32-bit, 4050 total.
-// Range bytes: 20346 16-bit, 7908 32-bit, 28254 total.
+// Range entries: 3462 16-bit, 832 32-bit, 4294 total.
+// Range bytes: 20772 16-bit, 9984 32-bit, 30756 total.
 
 // Fold orbit bytes: 63 pairs, 252 bytes
diff --git a/src/pkg/unicode/utf8/example_test.go b/src/pkg/unicode/utf8/example_test.go
new file mode 100644
index 0000000..fe20373
--- /dev/null
+++ b/src/pkg/unicode/utf8/example_test.go
@@ -0,0 +1,192 @@
+package utf8_test
+
+import (
+	"fmt"
+	"unicode/utf8"
+)
+
+func ExampleDecodeLastRune() {
+	b := []byte("Hello, 世界")
+
+	for len(b) > 0 {
+		r, size := utf8.DecodeLastRune(b)
+		fmt.Printf("%c %v\n", r, size)
+
+		b = b[:len(b)-size]
+	}
+	// Output:
+	// 界 3
+	// 世 3
+	//   1
+	// , 1
+	// o 1
+	// l 1
+	// l 1
+	// e 1
+	// H 1
+}
+
+func ExampleDecodeLastRuneInString() {
+	str := "Hello, 世界"
+
+	for len(str) > 0 {
+		r, size := utf8.DecodeLastRuneInString(str)
+		fmt.Printf("%c %v\n", r, size)
+
+		str = str[:len(str)-size]
+	}
+	// Output:
+	// 界 3
+	// 世 3
+	//   1
+	// , 1
+	// o 1
+	// l 1
+	// l 1
+	// e 1
+	// H 1
+
+}
+
+func ExampleDecodeRune() {
+	b := []byte("Hello, 世界")
+
+	for len(b) > 0 {
+		r, size := utf8.DecodeRune(b)
+		fmt.Printf("%c %v\n", r, size)
+
+		b = b[size:]
+	}
+	// Output:
+	// H 1
+	// e 1
+	// l 1
+	// l 1
+	// o 1
+	// , 1
+	//   1
+	// 世 3
+	// 界 3
+}
+
+func ExampleDecodeRuneInString() {
+	str := "Hello, 世界"
+
+	for len(str) > 0 {
+		r, size := utf8.DecodeRuneInString(str)
+		fmt.Printf("%c %v\n", r, size)
+
+		str = str[size:]
+	}
+	// Output:
+	// H 1
+	// e 1
+	// l 1
+	// l 1
+	// o 1
+	// , 1
+	//   1
+	// 世 3
+	// 界 3
+}
+
+func ExampleEncodeRune() {
+	r := '世'
+	buf := make([]byte, 3)
+
+	n := utf8.EncodeRune(buf, r)
+
+	fmt.Println(buf)
+	fmt.Println(n)
+	// Output:
+	// [228 184 150]
+	// 3
+}
+
+func ExampleFullRune() {
+	buf := []byte{228, 184, 150} // 世
+	fmt.Println(utf8.FullRune(buf))
+	fmt.Println(utf8.FullRune(buf[:2]))
+	// Output:
+	// true
+	// false
+}
+
+func ExampleFullRuneInString() {
+	str := "世"
+	fmt.Println(utf8.FullRuneInString(str))
+	fmt.Println(utf8.FullRuneInString(str[:2]))
+	// Output:
+	// true
+	// false
+}
+
+func ExampleRuneCount() {
+	buf := []byte("Hello, 世界")
+	fmt.Println("bytes =", len(buf))
+	fmt.Println("runes =", utf8.RuneCount(buf))
+	// Output:
+	// bytes = 13
+	// runes = 9
+}
+
+func ExampleRuneCountInString() {
+	str := "Hello, 世界"
+	fmt.Println("bytes =", len(str))
+	fmt.Println("runes =", utf8.RuneCountInString(str))
+	// Output:
+	// bytes = 13
+	// runes = 9
+}
+
+func ExampleRuneLen() {
+	fmt.Println(utf8.RuneLen('a'))
+	fmt.Println(utf8.RuneLen('界'))
+	// Output:
+	// 1
+	// 3
+}
+
+func ExampleRuneStart() {
+	buf := []byte("a界")
+	fmt.Println(utf8.RuneStart(buf[0]))
+	fmt.Println(utf8.RuneStart(buf[1]))
+	fmt.Println(utf8.RuneStart(buf[2]))
+	// Output:
+	// true
+	// true
+	// false
+}
+
+func ExampleValid() {
+	valid := []byte("Hello, 世界")
+	invalid := []byte{0xff, 0xfe, 0xfd}
+
+	fmt.Println(utf8.Valid(valid))
+	fmt.Println(utf8.Valid(invalid))
+	// Output:
+	// true
+	// false
+}
+
+func ExampleValidRune() {
+	valid := 'a'
+	invalid := rune(0xfffffff)
+
+	fmt.Println(utf8.ValidRune(valid))
+	fmt.Println(utf8.ValidRune(invalid))
+	// Output:
+	// true
+	// false
+}
+
+func ExampleValidString() {
+	valid := "Hello, 世界"
+	invalid := string([]byte{0xff, 0xfe, 0xfd})
+
+	fmt.Println(utf8.ValidString(valid))
+	fmt.Println(utf8.ValidString(invalid))
+	// Output:
+	// true
+	// false
+}
diff --git a/src/pkg/unicode/utf8/utf8.go b/src/pkg/unicode/utf8/utf8.go
index 57ea19e..93d0be5 100644
--- a/src/pkg/unicode/utf8/utf8.go
+++ b/src/pkg/unicode/utf8/utf8.go
@@ -18,6 +18,12 @@ const (
 	UTFMax    = 4            // maximum number of bytes of a UTF-8 encoded Unicode character.
 )
 
+// Code points in the surrogate range are not valid for UTF-8.
+const (
+	surrogateMin = 0xD800
+	surrogateMax = 0xDFFF
+)
+
 const (
 	t1 = 0x00 // 0000 0000
 	tx = 0x80 // 1000 0000
@@ -34,7 +40,6 @@ const (
 	rune1Max = 1<<7 - 1
 	rune2Max = 1<<11 - 1
 	rune3Max = 1<<16 - 1
-	rune4Max = 1<<21 - 1
 )
 
 func decodeRuneInternal(p []byte) (r rune, size int, short bool) {
@@ -87,6 +92,9 @@ func decodeRuneInternal(p []byte) (r rune, size int, short bool) {
 		if r <= rune2Max {
 			return RuneError, 1, false
 		}
+		if surrogateMin <= r && r <= surrogateMax {
+			return RuneError, 1, false
+		}
 		return r, 3, false
 	}
 
@@ -102,7 +110,7 @@ func decodeRuneInternal(p []byte) (r rune, size int, short bool) {
 	// 4-byte, 21-bit sequence?
 	if c0 < t5 {
 		r = rune(c0&mask4)<<18 | rune(c1&maskx)<<12 | rune(c2&maskx)<<6 | rune(c3&maskx)
-		if r <= rune3Max {
+		if r <= rune3Max || MaxRune < r {
 			return RuneError, 1, false
 		}
 		return r, 4, false
@@ -162,6 +170,9 @@ func decodeRuneInStringInternal(s string) (r rune, size int, short bool) {
 		if r <= rune2Max {
 			return RuneError, 1, false
 		}
+		if surrogateMin <= r && r <= surrogateMax {
+			return RuneError, 1, false
+		}
 		return r, 3, false
 	}
 
@@ -177,7 +188,7 @@ func decodeRuneInStringInternal(s string) (r rune, size int, short bool) {
 	// 4-byte, 21-bit sequence?
 	if c0 < t5 {
 		r = rune(c0&mask4)<<18 | rune(c1&maskx)<<12 | rune(c2&maskx)<<6 | rune(c3&maskx)
-		if r <= rune3Max {
+		if r <= rune3Max || MaxRune < r {
 			return RuneError, 1, false
 		}
 		return r, 4, false
@@ -202,6 +213,9 @@ func FullRuneInString(s string) bool {
 
 // 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.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
 func DecodeRune(p []byte) (r rune, size int) {
 	r, size, _ = decodeRuneInternal(p)
 	return
@@ -209,6 +223,9 @@ func DecodeRune(p []byte) (r rune, size int) {
 
 // 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.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
 func DecodeRuneInString(s string) (r rune, size int) {
 	r, size, _ = decodeRuneInStringInternal(s)
 	return
@@ -216,6 +233,9 @@ func DecodeRuneInString(s string) (r rune, size int) {
 
 // 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.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
 func DecodeLastRune(p []byte) (r rune, size int) {
 	end := len(p)
 	if end == 0 {
@@ -250,6 +270,9 @@ func DecodeLastRune(p []byte) (r rune, size int) {
 
 // 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.
+// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
+// out of range, or is not the shortest possible UTF-8 encoding for the
+// value. No other validation is performed.
 func DecodeLastRuneInString(s string) (r rune, size int) {
 	end := len(s)
 	if end == 0 {
@@ -283,15 +306,20 @@ func DecodeLastRuneInString(s string) (r rune, size int) {
 }
 
 // RuneLen returns the number of bytes required to encode the rune.
+// It returns -1 if the rune is not a valid value to encode in UTF-8.
 func RuneLen(r rune) int {
 	switch {
+	case r < 0:
+		return -1
 	case r <= rune1Max:
 		return 1
 	case r <= rune2Max:
 		return 2
+	case surrogateMin <= r && r <= surrogateMax:
+		return -1
 	case r <= rune3Max:
 		return 3
-	case r <= rune4Max:
+	case r <= MaxRune:
 		return 4
 	}
 	return -1
@@ -316,6 +344,10 @@ func EncodeRune(p []byte, r rune) int {
 		r = RuneError
 	}
 
+	if surrogateMin <= r && r <= surrogateMax {
+		r = RuneError
+	}
+
 	if uint32(r) <= rune3Max {
 		p[0] = t3 | byte(r>>12)
 		p[1] = tx | byte(r>>6)&maskx
@@ -368,7 +400,7 @@ func Valid(p []byte) bool {
 		} else {
 			_, size := DecodeRune(p[i:])
 			if size == 1 {
-				// All valid runes of size of 1 (those
+				// All valid runes of size 1 (those
 				// below RuneSelf) were handled above.
 				// This must be a RuneError.
 				return false
@@ -395,3 +427,17 @@ func ValidString(s string) bool {
 	}
 	return true
 }
+
+// ValidRune reports whether r can be legally encoded as UTF-8.
+// Code points that are out of range or a surrogate half are illegal.
+func ValidRune(r rune) bool {
+	switch {
+	case r < 0:
+		return false
+	case surrogateMin <= r && r <= surrogateMax:
+		return false
+	case r > MaxRune:
+		return false
+	}
+	return true
+}
diff --git a/src/pkg/unicode/utf8/utf8_test.go b/src/pkg/unicode/utf8/utf8_test.go
index 4f73c8f..c516871 100644
--- a/src/pkg/unicode/utf8/utf8_test.go
+++ b/src/pkg/unicode/utf8/utf8_test.go
@@ -56,6 +56,8 @@ var utf8map = []Utf8Map{
 	{0x07ff, "\xdf\xbf"},
 	{0x0800, "\xe0\xa0\x80"},
 	{0x0801, "\xe0\xa0\x81"},
+	{0xd7ff, "\xed\x9f\xbf"}, // last code point before surrogate half.
+	{0xe000, "\xee\x80\x80"}, // first code point after surrogate half.
 	{0xfffe, "\xef\xbf\xbe"},
 	{0xffff, "\xef\xbf\xbf"},
 	{0x10000, "\xf0\x90\x80\x80"},
@@ -65,6 +67,11 @@ var utf8map = []Utf8Map{
 	{0xFFFD, "\xef\xbf\xbd"},
 }
 
+var surrogateMap = []Utf8Map{
+	{0xd800, "\xed\xa0\x80"}, // surrogate min decodes to (RuneError, 1)
+	{0xdfff, "\xed\xbf\xbf"}, // surrogate max decodes to (RuneError, 1)
+}
+
 var testStrings = []string{
 	"",
 	"abcd",
@@ -75,8 +82,7 @@ var testStrings = []string{
 }
 
 func TestFullRune(t *testing.T) {
-	for i := 0; i < len(utf8map); i++ {
-		m := utf8map[i]
+	for _, m := range utf8map {
 		b := []byte(m.str)
 		if !FullRune(b) {
 			t.Errorf("FullRune(%q) (%U) = false, want true", b, m.r)
@@ -97,8 +103,7 @@ func TestFullRune(t *testing.T) {
 }
 
 func TestEncodeRune(t *testing.T) {
-	for i := 0; i < len(utf8map); i++ {
-		m := utf8map[i]
+	for _, m := range utf8map {
 		b := []byte(m.str)
 		var buf [10]byte
 		n := EncodeRune(buf[0:], m.r)
@@ -110,8 +115,7 @@ func TestEncodeRune(t *testing.T) {
 }
 
 func TestDecodeRune(t *testing.T) {
-	for i := 0; i < len(utf8map); i++ {
-		m := utf8map[i]
+	for _, m := range utf8map {
 		b := []byte(m.str)
 		r, size := DecodeRune(b)
 		if r != m.r || size != len(b) {
@@ -168,6 +172,21 @@ func TestDecodeRune(t *testing.T) {
 	}
 }
 
+func TestDecodeSurrogateRune(t *testing.T) {
+	for _, m := range surrogateMap {
+		b := []byte(m.str)
+		r, size := DecodeRune(b)
+		if r != RuneError || size != 1 {
+			t.Errorf("DecodeRune(%q) = %x, %d want %x, %d", b, r, size, RuneError, 1)
+		}
+		s := m.str
+		r, size = DecodeRuneInString(s)
+		if r != RuneError || size != 1 {
+			t.Errorf("DecodeRune(%q) = %x, %d want %x, %d", b, r, size, RuneError, 1)
+		}
+	}
+}
+
 // Check that DecodeRune and DecodeLastRune correspond to
 // the equivalent range loop.
 func TestSequencing(t *testing.T) {
@@ -284,8 +303,7 @@ var runecounttests = []RuneCountTest{
 }
 
 func TestRuneCount(t *testing.T) {
-	for i := 0; i < len(runecounttests); i++ {
-		tt := runecounttests[i]
+	for _, tt := range runecounttests {
 		if out := RuneCountInString(tt.in); out != tt.out {
 			t.Errorf("RuneCountInString(%q) = %d, want %d", tt.in, out, tt.out)
 		}
@@ -295,6 +313,32 @@ func TestRuneCount(t *testing.T) {
 	}
 }
 
+type RuneLenTest struct {
+	r    rune
+	size int
+}
+
+var runelentests = []RuneLenTest{
+	{0, 1},
+	{'e', 1},
+	{'é', 2},
+	{'☺', 3},
+	{RuneError, 3},
+	{MaxRune, 4},
+	{0xD800, -1},
+	{0xDFFF, -1},
+	{MaxRune + 1, -1},
+	{-1, -1},
+}
+
+func TestRuneLen(t *testing.T) {
+	for _, tt := range runelentests {
+		if size := RuneLen(tt.r); size != tt.size {
+			t.Errorf("RuneLen(%#U) = %d, want %d", tt.r, size, tt.size)
+		}
+	}
+}
+
 type ValidTest struct {
 	in  string
 	out bool
@@ -311,15 +355,50 @@ var validTests = []ValidTest{
 	{string([]byte{66, 250}), false},
 	{string([]byte{66, 250, 67}), false},
 	{"a\uFFFDb", true},
+	{string("\xF4\x8F\xBF\xBF"), true},      // U+10FFFF
+	{string("\xF4\x90\x80\x80"), false},     // U+10FFFF+1; out of range
+	{string("\xF7\xBF\xBF\xBF"), false},     // 0x1FFFFF; out of range
+	{string("\xFB\xBF\xBF\xBF\xBF"), false}, // 0x3FFFFFF; out of range
+	{string("\xc0\x80"), false},             // U+0000 encoded in two bytes: incorrect
+	{string("\xed\xa0\x80"), false},         // U+D800 high surrogate (sic)
+	{string("\xed\xbf\xbf"), false},         // U+DFFF low surrogate (sic)
 }
 
 func TestValid(t *testing.T) {
-	for i, tt := range validTests {
+	for _, tt := range validTests {
 		if Valid([]byte(tt.in)) != tt.out {
-			t.Errorf("%d. Valid(%q) = %v; want %v", i, tt.in, !tt.out, tt.out)
+			t.Errorf("Valid(%q) = %v; want %v", tt.in, !tt.out, tt.out)
 		}
 		if ValidString(tt.in) != tt.out {
-			t.Errorf("%d. ValidString(%q) = %v; want %v", i, tt.in, !tt.out, tt.out)
+			t.Errorf("ValidString(%q) = %v; want %v", tt.in, !tt.out, tt.out)
+		}
+	}
+}
+
+type ValidRuneTest struct {
+	r  rune
+	ok bool
+}
+
+var validrunetests = []ValidRuneTest{
+	{0, true},
+	{'e', true},
+	{'é', true},
+	{'☺', true},
+	{RuneError, true},
+	{MaxRune, true},
+	{0xD7FF, true},
+	{0xD800, false},
+	{0xDFFF, false},
+	{0xE000, true},
+	{MaxRune + 1, false},
+	{-1, false},
+}
+
+func TestValidRune(t *testing.T) {
+	for _, tt := range validrunetests {
+		if ok := ValidRune(tt.r); ok != tt.ok {
+			t.Errorf("ValidRune(%#U) = %t, want %t", tt.r, ok, tt.ok)
 		}
 	}
 }
diff --git a/src/pkg/unsafe/unsafe.go b/src/pkg/unsafe/unsafe.go
index 024969b..83b2e14 100644
--- a/src/pkg/unsafe/unsafe.go
+++ b/src/pkg/unsafe/unsafe.go
@@ -11,7 +11,7 @@ package unsafe
 // part of the unsafe package.  It represents the type of an arbitrary Go expression.
 type ArbitraryType int
 
-// Pointer represents a pointer to an arbitrary type.  There are three special operations
+// Pointer represents a pointer to an arbitrary type.  There are four special operations
 // available for type Pointer that are not available for other types.
 //	1) A pointer value of any type can be converted to a Pointer.
 //	2) A Pointer can be converted to a pointer value of any type.
@@ -32,6 +32,6 @@ func Sizeof(v ArbitraryType) uintptr
 func Offsetof(v ArbitraryType) uintptr
 
 // Alignof returns the alignment of the value v.  It is the maximum value m such
-// that the address of a variable with the type of v will always always be zero mod m.
+// that the address of a variable with the type of v will always be zero mod m.
 // If v is of the form structValue.field, it returns the alignment of field f within struct object obj.
 func Alignof(v ArbitraryType) uintptr
diff --git a/src/race.bash b/src/race.bash
new file mode 100755
index 0000000..3cdc5e1
--- /dev/null
+++ b/src/race.bash
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+# 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.
+
+# race.bash tests the standard library under the race detector.
+# http://golang.org/doc/articles/race_detector.html
+
+set -e
+
+function usage {
+	echo 'race detector is only supported on linux/amd64 and darwin/amd64' 1>&2
+	exit 1
+}
+
+case $(uname) in
+"Darwin")
+	# why Apple? why?
+	if sysctl machdep.cpu.extfeatures | grep -qv EM64T; then
+		usage
+	fi 
+	;;
+"Linux")
+	if [ $(uname -m) != "x86_64" ]; then
+		usage
+	fi
+	;;
+*)
+	usage
+	;;
+esac
+
+if [ ! -f make.bash ]; then
+	echo 'race.bash must be run from $GOROOT/src' 1>&2
+	exit 1
+fi
+. ./make.bash --no-banner
+go install -race std
+go test -race -short std
+go test -race -run=nothingplease -bench=.* -benchtime=.1s -cpu=4 std
diff --git a/src/race.bat b/src/race.bat
new file mode 100644
index 0000000..989a2e7
--- /dev/null
+++ b/src/race.bat
@@ -0,0 +1,52 @@
+:: 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.
+
+:: race.bash tests the standard library under the race detector.
+:: http://golang.org/doc/articles/race_detector.html
+
+ at echo off
+
+setlocal
+
+if exist make.bat goto ok
+echo race.bat must be run from go\src
+:: cannot exit: would kill parent command interpreter
+goto end
+:ok
+
+call make.bat --dist-tool >NUL
+if errorlevel 1 goto fail
+.\cmd\dist\dist env -wp >env.bat
+if errorlevel 1 goto fail
+call env.bat
+del env.bat
+
+if %GOHOSTARCH% == amd64 goto continue
+echo Race detector is only supported on windows/amd64.
+goto fail
+
+:continue
+call make.bat --no-banner --no-local
+if %GOBUILDFAIL%==1 goto end
+echo # go install -race std
+go install -race std
+if errorlevel 1 goto fail
+echo # go test -race -short -std
+go test -race -short std
+if errorlevel 1 goto fail
+echo # go test -race -run=nothingplease -bench=.* -benchtime=.1s -cpu=4 std
+go test -race -run=nothingplease -bench=.* -benchtime=.1s -cpu=4 std
+if errorlevel 1 goto fail
+goto succ
+
+:fail
+set GOBUILDFAIL=1
+echo Fail.
+goto end
+
+:succ
+echo All tests passed.
+
+:end
+
diff --git a/src/run.bash b/src/run.bash
index ca84b70..a026b45 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -14,6 +14,12 @@ unset GOPATH    # we disallow local import for non-local packages, if $GOROOT ha
 # no core files, please
 ulimit -c 0
 
+# Raise soft limits to hard limits for NetBSD/OpenBSD.
+# We need at least 256 files and ~300 MB of bss.
+# On OS X ulimit -S -n rejects 'unlimited'.
+[ "$(ulimit -H -n)" == "unlimited" ] || ulimit -S -n $(ulimit -H -n)
+[ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -d $(ulimit -H -d)
+
 # allow all.bash to avoid double-build of everything
 rebuild=true
 if [ "$1" = "--no-rebuild" ]; then
@@ -40,6 +46,16 @@ echo
 echo '# sync -cpu=10'
 go test sync -short -timeout=120s -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 flag
+	go test -race -short flag
+esac
+
 xcd() {
 	echo
 	echo '#' $1
@@ -49,15 +65,16 @@ xcd() {
 [ "$CGO_ENABLED" != 1 ] ||
 [ "$GOHOSTOS" == windows ] ||
 (xcd ../misc/cgo/stdio
-./test.bash
+go run $GOROOT/test/run.go - .
 ) || exit $?
 
 [ "$CGO_ENABLED" != 1 ] ||
 (xcd ../misc/cgo/life
-./test.bash
+go run $GOROOT/test/run.go - .
 ) || exit $?
 
 [ "$CGO_ENABLED" != 1 ] ||
+[ "$GOHOSTOS" == openbsd ] || # issue 4878
 (xcd ../misc/cgo/test
 go test
 ) || exit $?
@@ -101,12 +118,13 @@ echo '#' ../test/bench/go1
 go test ../test/bench/go1
 
 (xcd ../test
+unset GOMAXPROCS
 time go run run.go
 ) || exit $?
 
 echo
 echo '# Checking API compatibility.'
-go tool api -c $GOROOT/api/go1.txt -next $GOROOT/api/next.txt
+go tool api -c $GOROOT/api/go1.txt -next $GOROOT/api/next.txt -except $GOROOT/api/except.txt
 
 echo
 echo ALL TESTS PASSED
diff --git a/src/run.bat b/src/run.bat
index 9a09d43..5f7164a 100644
--- a/src/run.bat
+++ b/src/run.bat
@@ -30,6 +30,13 @@ echo.
 :: at least runtime/debug test will fail.
 set GOROOT_FINAL=
 
+:: get CGO_ENABLED
+go env > env.bat
+if errorlevel 1 goto fail
+call env.bat
+del env.bat
+echo.
+
 echo # Testing packages.
 go test std -short -timeout=120s
 if errorlevel 1 goto fail
@@ -45,30 +52,70 @@ go test sync -short -timeout=120s -cpu=10
 if errorlevel 1 goto fail
 echo.
 
+if not "%GOHOSTOS%-%GOOS%-%GOARCH%-%CGO_ENABLED%" == "windows-windows-amd64-1" goto norace
+echo # Testing race detector.
+go test -race -i flag
+if errorlevel 1 goto fail
+go test -race -short flag
+if errorlevel 1 goto fail
+echo.
+:norace
+
 echo # ..\misc\dashboard\builder ..\misc\goplay
 go build ..\misc\dashboard\builder ..\misc\goplay
 if errorlevel 1 goto fail
 echo.
 
-:: TODO(brainman): disabled, because it fails with: mkdir C:\Users\ADMINI~1\AppData\Local\Temp\2.....\test\bench\: The filename or extension is too long.
-::echo # ..\test\bench\go1
-::go test ..\test\bench\go1
-::if errorlevel 1 goto fail
-::echo.
+echo # ..\test\bench\go1
+go test ..\test\bench\go1
+if errorlevel 1 goto fail
+echo.
+
+:: cgo tests
+:: issue 4955 - cgo is broken
+goto nocgo
+if x%CGO_ENABLED% == x0 goto nocgo
+echo # ..\misc\cgo\life
+go run %GOROOT%\test\run.go - ..\misc\cgo\life
+if errorlevel 1 goto fail
+echo.
+
+echo # ..\misc\cgo\stdio
+go run %GOROOT%\test\run.go - ..\misc\cgo\stdio
+if errorlevel 1 goto fail
+echo.
+
+echo # ..\misc\cgo\test
+go test ..\misc\cgo\test
+if errorlevel 1 goto fail
+echo.
+:nocgo
+
+echo # ..\doc\progs
+go run %GOROOT%\test\run.go - ..\doc\progs
+if errorlevel 1 goto fail
+echo.
 
 :: TODO: The other tests in run.bash.
 
-echo # test
+
+set OLDGOMAXPROCS=%GOMAXPROCS%
+
+echo # ..\test
 cd ..\test
 set FAIL=0
+set GOMAXPROCS=
 go run run.go
 if errorlevel 1 set FAIL=1
 cd ..\src
 echo.
 if %FAIL%==1 goto fail
 
+set GOMAXPROCS=%OLDGOMAXPROCS%
+set OLDGOMAXPROCS=
+
 echo # Checking API compatibility.
-go tool api -c ..\api\go1.txt -next ..\api\next.txt
+go tool api -c ..\api\go1.txt -next ..\api\next.txt -except ..\api\except.txt
 if errorlevel 1 goto fail
 echo.
 
diff --git a/src/run.rc b/src/run.rc
new file mode 100755
index 0000000..e493eae
--- /dev/null
+++ b/src/run.rc
@@ -0,0 +1,63 @@
+#!/bin/rc -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.
+
+rfork e
+
+eval `{go env}
+
+GOPATH = () # we disallow local import for non-local packges, if $GOROOT happens
+            # to be under $GOPATH, then some tests below will fail
+
+# allow all.rc to avoid double-build of everything
+rebuild = true
+if(~ $1 --no-rebuild)
+	shift
+if not {
+	# Run only one process at a time on 9vx.
+	if(~ $sysname vx32)
+		pflag = (-p 1)
+	echo '# Building packages and commands.'
+	time go install -a -v $pflag std
+	echo
+}
+
+# we must unset GOROOT_FINAL before tests, because runtime/debug requires
+# correct access to source code, so if we have GOROOT_FINAL in effect,
+# at least runtime/debug test will fail.
+GOROOT_FINAL = ()
+
+echo '# Testing packages.'
+time go test std -short -timeout 120s
+echo
+
+echo '# GOMAXPROCS=2 runtime -cpu=1,2,4'
+GOMAXPROCS=2 go test runtime -short -timeout 240s -cpu 1,2,4
+echo
+
+echo '# sync -cpu=10'
+go test sync -short -timeout 120s -cpu 10
+echo
+
+fn xcd {
+	echo
+	echo '#' $1
+	cd $"GOROOT/src/$1
+}
+
+echo
+echo '#' ../misc/dashboard/builder ../misc/goplay
+go build ../misc/dashboard/builder ../misc/gplay
+
+echo
+echo '#' ../test/bench/go1
+go test ../test/bench/go1
+
+@{
+	xcd ../test
+	GOMAXPROCS='' time go run run.go
+}
+
+echo
+echo ALL TESTS PASSED
diff --git a/src/sudo.bash b/src/sudo.bash
index 40f8d1a..7b7d4f1 100755
--- a/src/sudo.bash
+++ b/src/sudo.bash
@@ -12,6 +12,12 @@ Darwin)
 	exit 0
 esac
 
+# Check that the go command exists
+if ! go help >/dev/null 2>&1; then
+	echo "The go command is not in your PATH." >&2
+	exit 2
+fi
+
 eval $(go env)
 if ! [ -x $GOTOOLDIR/cov -a -x $GOTOOLDIR/prof ]; then
 	echo "You don't need to run sudo.bash." >&2
diff --git a/test/64bit.go b/test/64bit.go
index 9e91a97..d99d8e8 100644
--- a/test/64bit.go
+++ b/test/64bit.go
@@ -1,6 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
-// $G tmp.go && $L tmp.$A && ./$A.out || echo BUG: 64bit
-// rm -f tmp.go
+// runoutput
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -596,6 +594,19 @@ const binaryConstR = "func test%vBinaryR%v(a, add, sub, mul, div, mod, and, or,
 	"}\n" +
 	"\n"
 
+const binaryConstR0 = "func test%vBinaryR%v(a, add, sub, mul, div, mod, and, or, xor, andnot %v, dodiv bool) {\n" +
+	"	const b %v = %v;\n" +
+	"	const typ = `%s`;\n" +
+	"	if n, op, want := a + b, `+`, add; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a - b, `-`, sub; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a * b, `*`, mul; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a & b, `&`, and; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a | b, `|`, or; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a ^ b, `^`, xor; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a &^ b, `&^`, andnot; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"}\n" +
+	"\n"
+
 const shiftConstL = "func test%vShiftL%v(b uint64, left, right %v) {\n" +
 	"	const a %v = %v;\n" +
 	"	const typ = `%s`;\n" +
@@ -623,12 +634,20 @@ const shiftConstR = "func test%vShiftR%v(a, left, right %v) {\n" +
 func constTests() {
 	for i, a := range int64Values {
 		fmt.Fprintf(bout, binaryConstL, "Int64", i, "int64", "int64", a, "int64")
-		fmt.Fprintf(bout, binaryConstR, "Int64", i, "int64", "int64", a, "int64")
+		if a.hi == 0 && a.lo == 0 {
+			fmt.Fprintf(bout, binaryConstR0, "Int64", i, "int64", "int64", a, "int64")
+		} else {
+			fmt.Fprintf(bout, binaryConstR, "Int64", i, "int64", "int64", a, "int64")
+		}
 		fmt.Fprintf(bout, shiftConstL, "Int64", i, "int64", "int64", a, "int64")
 	}
 	for i, a := range uint64Values {
 		fmt.Fprintf(bout, binaryConstL, "Uint64", i, "uint64", "uint64", a, "uint64")
-		fmt.Fprintf(bout, binaryConstR, "Uint64", i, "uint64", "uint64", a, "uint64")
+		if a.hi == 0 && a.lo == 0 {
+			fmt.Fprintf(bout, binaryConstR0, "Uint64", i, "uint64", "uint64", a, "uint64")
+		} else {
+			fmt.Fprintf(bout, binaryConstR, "Uint64", i, "uint64", "uint64", a, "uint64")
+		}
 		fmt.Fprintf(bout, shiftConstL, "Uint64", i, "uint64", "uint64", a, "uint64")
 	}
 	for i, a := range shiftValues {
diff --git a/test/alias1.go b/test/alias1.go
index 4219af8..42cf693 100644
--- a/test/alias1.go
+++ b/test/alias1.go
@@ -17,7 +17,7 @@ func main() {
 	case uint8:
 		// ok
 	default:
-		println("byte != uint8")
+		panic("byte != uint8")
 	}
 
 	x = uint8(2)
@@ -25,7 +25,7 @@ func main() {
 	case byte:
 		// ok
 	default:
-		println("uint8 != byte")
+		panic("uint8 != byte")
 	}
 
 	rune32 := false
@@ -37,7 +37,7 @@ func main() {
 		// must be new code
 		rune32 = true
 	default:
-		println("rune != int and rune != int32")
+		panic("rune != int and rune != int32")
 	}
 
 	if rune32 {
@@ -49,6 +49,6 @@ func main() {
 	case rune:
 		// ok
 	default:
-		println("int (or int32) != rune")
+		panic("int (or int32) != rune")
 	}
 }
diff --git a/test/args.go b/test/args.go
index db624e9..0ffe810 100644
--- a/test/args.go
+++ b/test/args.go
@@ -1,4 +1,4 @@
-// $G $F.go && $L $F.$A && ./$A.out arg1 arg2
+// run arg1 arg2
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/bench/garbage/parser.go b/test/bench/garbage/parser.go
index d66281b..ff7630a 100644
--- a/test/bench/garbage/parser.go
+++ b/test/bench/garbage/parser.go
@@ -134,20 +134,31 @@ func main() {
 	}
 }
 
+// find . -type d -not -path "./exp" -not -path "./exp/*" -printf "\t\"%p\",\n" | sort | sed "s/\.\///" | grep -v testdata
 var packages = []string{
+	"archive",
 	"archive/tar",
-	"encoding/asn1",
-	"math/big",
+	"archive/zip",
 	"bufio",
+	"builtin",
 	"bytes",
-	"math/cmplx",
+	"compress",
+	"compress/bzip2",
 	"compress/flate",
 	"compress/gzip",
+	"compress/lzw",
 	"compress/zlib",
+	"container",
 	"container/heap",
 	"container/list",
 	"container/ring",
+	"crypto",
 	"crypto/aes",
+	"crypto/cipher",
+	"crypto/des",
+	"crypto/dsa",
+	"crypto/ecdsa",
+	"crypto/elliptic",
 	"crypto/hmac",
 	"crypto/md5",
 	"crypto/rand",
@@ -159,66 +170,112 @@ var packages = []string{
 	"crypto/subtle",
 	"crypto/tls",
 	"crypto/x509",
+	"crypto/x509/pkix",
+	"database",
+	"database/sql",
+	"database/sql/driver",
+	"debug",
 	"debug/dwarf",
-	"debug/macho",
 	"debug/elf",
 	"debug/gosym",
-	"exp/ebnf",
+	"debug/macho",
+	"debug/pe",
+	"encoding",
 	"encoding/ascii85",
+	"encoding/asn1",
+	"encoding/base32",
 	"encoding/base64",
 	"encoding/binary",
+	"encoding/csv",
+	"encoding/gob",
 	"encoding/hex",
+	"encoding/json",
 	"encoding/pem",
-	"os/exec",
+	"encoding/xml",
+	"errors",
+	"expvar",
 	"flag",
 	"fmt",
+	"go",
 	"go/ast",
+	"go/build",
 	"go/doc",
+	"go/format",
 	"go/parser",
 	"go/printer",
 	"go/scanner",
 	"go/token",
-	"encoding/gob",
+	"go/types",
 	"hash",
 	"hash/adler32",
 	"hash/crc32",
 	"hash/crc64",
-	"net/http",
+	"hash/fnv",
+	"html",
+	"html/template",
 	"image",
+	"image/color",
+	"image/draw",
+	"image/gif",
 	"image/jpeg",
 	"image/png",
+	"index",
+	"index/suffixarray",
 	"io",
 	"io/ioutil",
-	"encoding/json",
 	"log",
+	"log/syslog",
 	"math",
+	"math/big",
+	"math/cmplx",
+	"math/rand",
 	"mime",
+	"mime/multipart",
 	"net",
+	"net/http",
+	"net/http/cgi",
+	"net/http/cookiejar",
+	"net/http/fcgi",
+	"net/http/httptest",
+	"net/http/httputil",
+	"net/http/pprof",
+	"net/mail",
+	"net/rpc",
+	"net/rpc/jsonrpc",
+	"net/smtp",
+	"net/textproto",
+	"net/url",
 	"os",
-	"exp/signal",
+	"os/exec",
+	"os/signal",
+	"os/user",
 	"path",
-	"math/rand",
+	"path/filepath",
 	"reflect",
 	"regexp",
-	"net/rpc",
+	"regexp/syntax",
 	"runtime",
-	"text/scanner",
+	"runtime/cgo",
+	"runtime/debug",
+	"runtime/pprof",
+	"runtime/race",
 	"sort",
-	"net/smtp",
 	"strconv",
 	"strings",
 	"sync",
+	"sync/atomic",
 	"syscall",
-	"log/syslog",
-	"text/tabwriter",
-	"text/template",
 	"testing",
 	"testing/iotest",
 	"testing/quick",
-	"testing/script",
+	"text",
+	"text/scanner",
+	"text/tabwriter",
+	"text/template",
+	"text/template/parse",
 	"time",
 	"unicode",
-	"unicode/utf8",
 	"unicode/utf16",
-	"encoding/xml",
+	"unicode/utf8",
+	"unsafe",
 }
diff --git a/test/bench/garbage/stats.go b/test/bench/garbage/stats.go
index cdcb32f..6dc0aeb 100644
--- a/test/bench/garbage/stats.go
+++ b/test/bench/garbage/stats.go
@@ -14,16 +14,21 @@ import (
 func gcstats(name string, n int, t time.Duration) {
 	st := new(runtime.MemStats)
 	runtime.ReadMemStats(st)
-	fmt.Printf("garbage.%sMem Alloc=%d/%d Heap=%d NextGC=%d Mallocs=%d\n", name, st.Alloc, st.TotalAlloc, st.Sys, st.NextGC, st.Mallocs)
-	fmt.Printf("garbage.%s %d %d ns/op\n", name, n, t.Nanoseconds()/int64(n))
-	fmt.Printf("garbage.%sLastPause 1 %d ns/op\n", name, st.PauseNs[(st.NumGC-1)%uint32(len(st.PauseNs))])
-	fmt.Printf("garbage.%sPause %d %d ns/op\n", name, st.NumGC, int64(st.PauseTotalNs)/int64(st.NumGC))
+	nprocs := runtime.GOMAXPROCS(-1)
+	cpus := ""
+	if nprocs != 1 {
+		cpus = fmt.Sprintf("-%d", nprocs)
+	}
+	fmt.Printf("garbage.%sMem%s Alloc=%d/%d Heap=%d NextGC=%d Mallocs=%d\n", name, cpus, st.Alloc, st.TotalAlloc, st.Sys, st.NextGC, st.Mallocs)
+	fmt.Printf("garbage.%s%s %d %d ns/op\n", name, cpus, n, t.Nanoseconds()/int64(n))
+	fmt.Printf("garbage.%sLastPause%s 1 %d ns/op\n", name, cpus, st.PauseNs[(st.NumGC-1)%uint32(len(st.PauseNs))])
+	fmt.Printf("garbage.%sPause%s %d %d ns/op\n", name, cpus, st.NumGC, int64(st.PauseTotalNs)/int64(st.NumGC))
 	nn := int(st.NumGC)
 	if nn >= len(st.PauseNs) {
 		nn = len(st.PauseNs)
 	}
 	t1, t2, t3, t4, t5 := tukey5(st.PauseNs[0:nn])
-	fmt.Printf("garbage.%sPause5: %d %d %d %d %d\n", name, t1, t2, t3, t4, t5)
+	fmt.Printf("garbage.%sPause5%s: %d %d %d %d %d\n", name, cpus, t1, t2, t3, t4, t5)
 
 	//	fmt.Printf("garbage.%sScan: %v\n", name, st.ScanDist)
 }
diff --git a/test/bench/garbage/tree2.go b/test/bench/garbage/tree2.go
index 3db0a0b..a171c69 100644
--- a/test/bench/garbage/tree2.go
+++ b/test/bench/garbage/tree2.go
@@ -11,6 +11,7 @@ import (
 	"os"
 	"runtime"
 	"runtime/pprof"
+	"time"
 	"unsafe"
 )
 
@@ -83,7 +84,12 @@ func main() {
 		pprof.StartCPUProfile(f)
 		defer pprof.StopCPUProfile()
 	}
-	for i := 0; i < 10; i++ {
+	const N = 10
+	var t0 time.Time
+	for i := 0; i < N; i++ {
+		t0 = time.Now()
 		gc()
 	}
+	// Standard gotest benchmark output, collected by build dashboard.
+	gcstats("BenchmarkTree2", N, time.Now().Sub(t0))
 }
diff --git a/test/bench/go1/fasta_test.go b/test/bench/go1/fasta_test.go
index dcb2d10..bff056f 100644
--- a/test/bench/go1/fasta_test.go
+++ b/test/bench/go1/fasta_test.go
@@ -4,9 +4,24 @@
 
 package go1
 
+import "runtime"
+
 // Not a benchmark; input for revcomp.
 
-var fasta25m = fasta(25e6)
+var fastabytes = makefasta()
+
+func makefasta() []byte {
+	var n int = 25e6
+	if runtime.GOARCH == "arm" {
+		// TODO(dfc) remove this limitation after precise gc.
+		// A value of 25e6 consumes 465mb of heap on 32bit 
+		// platforms, which is too much for most ARM systems. 
+		// A value of 25e5 produces a memory layout that 
+		// confuses the gc on 32bit platforms. So 25e4 it is.
+		n = 25e4
+	}
+	return fasta(n)
+}
 
 func fasta(n int) []byte {
 	out := make(fastaBuffer, 0, 11*n)
diff --git a/test/bench/go1/gob_test.go b/test/bench/go1/gob_test.go
index 00eeed5..b172b80 100644
--- a/test/bench/go1/gob_test.go
+++ b/test/bench/go1/gob_test.go
@@ -21,9 +21,7 @@ var (
 	gobdata  *JSONResponse
 )
 
-func gobinit() {
-	// gobinit is called after json's init,
-	// because it uses jsondata.
+func init() {
 	gobdata = gobResponse(&jsondata)
 
 	var buf bytes.Buffer
diff --git a/test/bench/go1/json_test.go b/test/bench/go1/json_test.go
index 5a30121..614e24a 100644
--- a/test/bench/go1/json_test.go
+++ b/test/bench/go1/json_test.go
@@ -17,11 +17,11 @@ import (
 )
 
 var (
-	jsonbytes []byte
-	jsondata  JSONResponse
+	jsonbytes = makeJsonBytes()
+	jsondata  = makeJsonData()
 )
 
-func init() {
+func makeJsonBytes() []byte {
 	var r io.Reader
 	r = strings.NewReader(jsonbz2_base64)
 	r = base64.NewDecoder(base64.StdEncoding, r)
@@ -30,12 +30,15 @@ func init() {
 	if err != nil {
 		panic(err)
 	}
-	jsonbytes = b
+	return b
+}
 
-	if err := json.Unmarshal(jsonbytes, &jsondata); err != nil {
+func makeJsonData() JSONResponse {
+	var v JSONResponse
+	if err := json.Unmarshal(jsonbytes, &v); err != nil {
 		panic(err)
 	}
-	gobinit()
+	return v
 }
 
 type JSONResponse struct {
diff --git a/test/bench/go1/mandel_test.go b/test/bench/go1/mandel_test.go
new file mode 100644
index 0000000..888c5e4
--- /dev/null
+++ b/test/bench/go1/mandel_test.go
@@ -0,0 +1,41 @@
+// 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.
+
+// This benchmark, taken from the shootuot, tests floating point performance.
+
+package go1
+
+import "testing"
+
+func mandelbrot(n int) int {
+	const Iter = 50
+	const Zero float64 = 0
+	const Limit = 2.0
+	ok := 0
+	for y := 0; y < n; y++ {
+		for x := 0; x < n; x++ {
+			Zr, Zi, Tr, Ti := Zero, Zero, Zero, Zero
+			Cr := (2*float64(x)/float64(n) - 1.5)
+			Ci := (2*float64(y)/float64(n) - 1.0)
+
+			for i := 0; i < Iter && (Tr+Ti <= Limit*Limit); i++ {
+				Zi = 2*Zr*Zi + Ci
+				Zr = Tr - Ti + Cr
+				Tr = Zr * Zr
+				Ti = Zi * Zi
+			}
+
+			if Tr+Ti <= Limit*Limit {
+				ok++
+			}
+		}
+	}
+	return ok
+}
+
+func BenchmarkMandelbrot200(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		mandelbrot(200)
+	}
+}
diff --git a/test/bench/go1/parser_test.go b/test/bench/go1/parser_test.go
new file mode 100644
index 0000000..26580b8
--- /dev/null
+++ b/test/bench/go1/parser_test.go
@@ -0,0 +1,43 @@
+// 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 go1
+
+// go parser benchmark based on go/parser/performance_test.go
+
+import (
+	"compress/bzip2"
+	"encoding/base64"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+var (
+	parserbytes = makeParserBytes()
+)
+
+func makeParserBytes() []byte {
+	var r io.Reader
+	r = strings.NewReader(parserbz2_base64)
+	r = base64.NewDecoder(base64.StdEncoding, r)
+	r = bzip2.NewReader(r)
+	b, err := ioutil.ReadAll(r)
+	if err != nil {
+		panic(err)
+	}
+	return b
+}
+
+func BenchmarkParse(b *testing.B) {
+	b.SetBytes(int64(len(parserbytes)))
+	for i := 0; i < b.N; i++ {
+		if _, err := parser.ParseFile(token.NewFileSet(), "", parserbytes, parser.ParseComments); err != nil {
+			b.Fatalf("benchmark failed due to parse error: %s", err)
+		}
+	}
+}
diff --git a/test/bench/go1/parserdata_test.go b/test/bench/go1/parserdata_test.go
new file mode 100644
index 0000000..113e5e3
--- /dev/null
+++ b/test/bench/go1/parserdata_test.go
@@ -0,0 +1,245 @@
+// 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.
+
+// Input for parser benchmark.
+// This was generated by starting with a the contents of
+// src/pkg/go/parser/parser.go at rev 9b455eb64690, then 
+// compressing with bzip2 -9, then encoding to base64.
+// We compile the data into the binary so that the benchmark is
+// a stand-alone binary that can be copied easily from machine to
+// machine. parser_test.go decodes this during init.
+
+package go1
+
+var parserbz2_base64 = "QlpoOTFBWSZTWd3QmOEAIYdfgHwwf//6P7/v/+/////+YEhcAAAB7hwvVWWaZT1X0dt999296z5B" +
+	"3mcQqlBVVVB7hnASWJoFGq9jlHvZHRbdfIB0Hz6fW+jrz4dueD73be6c33tG7la1O9d154ntzzk7" +
+	"jnU+O50zayubCulvgBm7rou5jleOe730dzX2sUbWj1u215X2PBXY17GB3Y3NznVW7ubOuu5a5wHc" +
+	"d9h69Xtatru8+D21uj7bM3lBKdRzPul3bt3GUtvN7z1PfCU0QIAmppkxQYg0Ap5NQZTxR6myJp6m" +
+	"T1D1NMgYSmgQggmiajIZKep5R6mh6jyh6RoA0BoGmg9RoCTSREEEAnqnpqbKp+alNk0ajR+qeiNB" +
+	"k9TanpMhtQDQBJ6pSkSTyPVPU/VP1PShkepoaGTTDSBoaAAyANDQMIkRE0lPTaZBTyYlRp/ok1Pa" +
+	"Rkm09Gk1PaptQAaDR6gPUESRAmQQ0Cnqm9NNBNMlPyj0iPQyQaBp6gAaaB8HrtSFgsiaNsTLSbZS" +
+	"paVaq+DW1qDTQ1FEYixSRiwlmJFRJrBmbIYoNEYoylREClbZLFikJKNRBFApgUQ1GShKjaSyRCCG" +
+	"UixqTabS2lLZiEgaKDZLMoxFY1o2LULILGDEJsWwMhbMzWlpbZm0bCaSS0NlmDGZIiRWIoxorEiG" +
+	"IxTJIyIGU22xsKzSqlMUUmjYE0bTGWaalWxLIlMQqECLEliKYskmLSSjKTKRYGRZmUZpARUKYttm" +
+	"ajIMrKGY0UUglEiWbM0tJsbGyzIk2myi0ZVYlsNRhGlFhJVKmwxloaVklNFBtDIZTQkyhowI0Qxp" +
+	"JTJsyVRUijUs1e9rpIS0kNLGYkko0WswwxrCAwJFBiLERYpFI14/l8d//VUo/f2Ofl/4/PMmROiP" +
+	"+X86qHV/m2eKhwgQcW/w+YWCErVRZu5/WnEVaZnt7Tfo5OP8TQ/6bme17VqPoaBMhDbuEqkuzjiW" +
+	"z4vygpH+2bkcU5nBikvEzgwxXZ804V1e1KpfovBAJKnhrcaHdoN4aEJHqHLUlmyGcSUjUdCvTYRP" +
+	"65aIz4POFpBLH+m+1Lbs7kPa+GjGbi6lF6kRnzeuKKJqJcsR2+EnuemMS9kr4tXWry3r+bgQMkhI" +
+	"ZkgILVvncoXREIltDqJkTlIBmQtrNEYdUFfdE6C6Uevosypd0519H9t17FtHW8FHImhH595l8V5y" +
+	"Dy7pYjFXqJ5ud+fYaJuGUNoK/3zpKZs3XTCeRxe50nakx0WoD9OZ5fgiko2ifKT2JRWE470vIn9q" +
+	"YqZeDApYKszMZ8Mp+S+W5s96YNXPi2dlO/D+1qHRSrLkH4VE7L5oPiWGXTwos+dnwniXQoVKJu+K" +
+	"Y9bmXzt/02qIskOq0b5TG05twenXqbgV7hVAkTElgmqsqORvcte/dakNMsd39HphWvVaeJ3rcihv" +
+	"cJ044ShoPW1kUxBbyYXSVcHhwcPSlRcSVjjMnnOumoi8tmS0XNbV8t7YwYi/pxq8j4IDzF6Gjjac" +
+	"8IstxcUEu4RJ7FipOLfio4rt9s7lfyvvwluT97uTcrpUBmf+k4nmsClh3fSIXpUhCQj0vMkt3PMf" +
+	"iudzHKBAPMXLy7ghISaEuIIZU7ueq2srC6YYkS+GIpVA78WOscuCQLNvB3uP5O/z7mxPA5zkIjIv" +
+	"KdUOFSCIx8N/Dub3Ur4WwQSti9vd16B9/Bzk1g28aiXYmRHTrN0J4cW8xmekkkaIMQXypKnBPZeW" +
+	"OTnpXqdzrz3NXv88RyB3SuMMy9e+YJ0LfvtfRletL4X4fU0YyG2EurWAFBlGvZ9Lzc161b0vZR3B" +
+	"lL54b52XxrzvXeyu0qCh3+Nv1LgzQhtksL1Oay/Q6uVSRCofJ3ZjFUiG7BtUBQ3ZQrIHZJxdYAou" +
+	"EFtGQkRJCQq1JlE0w7e/NTTmJ5ifsE62XbIaTAca2fb4+p0d8L19KX8vFwTin/n8OvB6c+3w6PlS" +
+	"2goNsUIjAKysBZEGKrGSj9cuNPj5nrOYVHPsxLdGaeVHWXgKPR3anI5fKwnR8SM4fFetyzwPhxw0" +
+	"0lGM5Y02qqy7YY3+xFTHU9QtR7daZLEhpvsY3iDlipq2XAQehwfn9cm34kA9P19rUJ+RB7funX6O" +
+	"rB5/xJ4dxpknnVZFXSwLq0tDC4Oze4TN2dOHZ+HL8OJ6n/L8WuPeXeMpMQqItn4ZQfO+L6Ptnu6u" +
+	"udDLKkBnS6yOVFVGKAsixPT+D24mcn109jn27PhPK6x803RI7pvAz3Q/nYYY74mSvWccNSVVSvyz" +
+	"c5IPV1UejZKjmnB3wuXPfG8LTTGrMkIz6mh9EbgSSBOQqmfzXu/57PRZlKcl6buNSiCdgf939gq+" +
+	"zhn356ZdFGoGUfVHCdBp4HXcfZpWfVbdNxh1rxI/RvAK/e4fAR+AkS75mGZTvK5T2ob4g+HlN+LU" +
+	"ednbpvXKTzu+BgxnhWG7i9otZECZps3pIIspDTLQ0P+o0Ryw/UOpt+F7zIKwg3cxA7UQX8rxDUxI" +
+	"Ub/+uw6Qh0xwieVzEaeQKh8s5uI1o+buyWpo8kZVwjBN8JdsHV4lj5tdUIiOuIqskenyFpkcNGgK" +
+	"cV1ohgEbXdcF1bm2LHZwKinccZZqRh4EXGbbqNuTSUTM06DGbwI3IfZcrrVlRlyGvUPnKeM2tG+p" +
+	"U5Nk1fWcKXovwi7Bpm85156nFylux70tJGHWaxNqGt02UGzMM04bJc6GHl57m9PfjBeQ+vlgtDBA" +
+	"KJkoKJEjXjnqvAmY6RkaCUoeo1mVlVA+uUmbbBqU8dYZIxiwRH3Pxc3bOD9uB5Jlka6An6c9B9km" +
+	"OnDL+FHQTYNwgH8mavZz0iOu+Ut8/J5ZwyoIamzhyxBs8262E1X8Xfhle9iE4rVPPFLG0iTioWAU" +
+	"d3xVBGn0oRJqbxtUaxhpdln5NtolGMj59U8pg0/RSY4z7US2Ms+4/ppi54Z8T9x34FrNnEaNTupy" +
+	"0wwbD4jnv7F8vm1WllYykpcbxM8YVxcrK1o0GGUBvVUGqDpjwLUr17oxmaKusyyrqV4yu76rlNga" +
+	"TtCAVGwYMvm+SLMenn6P375gmvYRlpqskpNDxFJcfbkZ8bux2QkkYKLPJlJSlbCOPNDfSULNSdHM" +
+	"12MvGjz5tYTNEbhq9fk6J0QCf04np5cuTvdC7SzdPmMDWTDxiD5exXpVi41UM6eV+926tnWjqo1q" +
+	"KZvLp3rjuvrmxbB648TaJlIjEgjUx2qKW6HRaInEGHsXUxFRTPPAsGXwgtoi1905O44+FkV9ctb8" +
+	"7pZtlllncqNGbJqP2LVNqa9WBOlqMdkm1w8mO+Ln3BLUvtWWl/CjfABpSq7mjGtMdPHs3a9OeOVw" +
+	"FHvW2fQeG243Jl69jvgx4jbSeVZ39VcNZNO5EiPRfOTlBHsZXX27TyO0b+abrFZ3Bwdx+c+uRVo/" +
+	"TEFzLJ4uXS1FoXdJblwzfjW0rcGlZ5Jqs3Gb4iESyfmdVpU6i2DtBPBtsn+nlb95Y0pWMDBM3ZBZ" +
+	"pyIEncddO3bafpssEObXLaLNvraGuJMzgiNF3+t2uZC633wwUji1sLoiU6X4kuZkEjKHnqmi1zXF" +
+	"+dM6MTtO9N5yDve47yIt/CkoVoTbWfc9E1Gs8e19PLxPS0i18ldi6xjw2bsWfjR9Dp21w5ImY6xr" +
+	"3J+BF35JgmZMT8PbEXlDThrTfEMkkrCcD1u+XbyIkkjGCc6Vc2Vr5X53XPuwfOuM31yem0tXg9uZ" +
+	"1kj2P4Hx03wa13qdX0xDFNlPCYxkY+xVhq2lCzma5tkZ/FD3755LyZbdshsWTGsbInzJ39+zd/Ly" +
+	"PMkJ079dteGN01Roys7oKtfDIa/N26YWY4Poq35WHTCM1DF7S5me2r5ahhiLl0ch545YQ+r57a4+" +
+	"Ls9VjY5Pswwk2x9S45uMQ770ssfjbRB1U2hF/DV8nak751LqONvJs28E0JmDcmEwIr4sB1uClx2b" +
+	"PpWuRnAWq7oEmSBKbowbbW2lGqi1nh35psMxUZ4d+FxK4uHVZNA7vU5qm0rUs1IoT9jPLkrzJ83e" +
+	"t1ZM+BwItwHrFPb5jtL228eV0ZUpLZphfFKj2DCkzbKiv1ODiobghZh44PzyoxgKV5SnP3VUGTRN" +
+	"h9Nr5MyMQvBNTHpiwN1N4241qJaQRhUVtKiMhjJjCNoYkMErArCTYOiM3SF88PVh9B9XSdDzTkqF" +
+	"hbUSnyoH1EwYMUaOhcqJmWVqsWHxhPCckWK3GaoqMmowMyzTBWal1P5eL2sVtZ+drjsx40brxVOg" +
+	"xhzdgFm5kg3UcZubj4zvW6QQgvvcd3x612pOT21AWT5bhwppdXYsSL7GRd0DB39io1hcZp98dpdP" +
+	"I7tjczPaDZBPL3EuO1nUrIw7csHF06ZNzmmUd+3TFNPvpr63hVjYTlSF4RbMRaymDlUJwWzYoxO+" +
+	"Ig6OY5Pjo2li+/s0+z4u+7OhBI5khOnopHj9a8efW8cp+r7kZeu8s3bbvYS+DWbWy1roJ0p1AeY2" +
+	"X+fziwq7PTod5KluzFOwS5vjjtukunB1xtG3rkji+868nZBbnTAgkLNN9Ezlg98Zlxha5827EPn0" +
+	"5OW6tutYMa9O+U5TiKz0ggzo3G2J1u6vrY40j3UfBNuDg2ONsRwUmNyZMREtEUZK8Ifne0GcxmXx" +
+	"L3F7fRIQk3RU2t4jbit2VdddKuMkXMTSERChLhN68Hj0bbJ7JYxZ8evJ8+Y5Lg119jsTYSQ6dxXs" +
+	"VKvg4DSyNLKMC2MsbYLARKFWKlCw5wzKlkQYWgttGacw160+Qze+GHCZbC2hGlGVjaX3h5YYzj3f" +
+	"DFYvzyl4YkBZrrrZtfQbVtkyqYQ+rtBBDGBnuPOcHrLOPXfllLstfKRrywI0ctF5F0qltBsNN9Rh" +
+	"msY8es8xjHtcrxnobZe4k3Nuc51d2e2RHRpNSdoNbT25KkUrQtDy69Wxwnnyc1tdraRFtHagZVH9" +
+	"q2swXNQyLCahLQC4szGKaGZKqLSiD3FjPm/7PL5ZHq/XmHmEJ77utU9tZ2zp/ODPCfhI7MvpP+fy" +
+	"16rtvaad6gz2zk1d2YaqMavtFjzK6opMh34RTf/flWMJ0d7tOtpgM0vJ8dPn/rfB5LrZc+fPfnI5" +
+	"rc/tsb5rm3jyV0qOxk6ObY8ZOaTIvk1eLm6lLtZNvtx1laKDXauwgE+92StvSXJZab2zM2l3uYmi" +
+	"IVzSVvVOIE4TEEKad3HGSKygKpCaSo7ct+/dUzPu1tE3+lX/Z7WAD7kwJdnl+r5V6jq7Plwv+rjb" +
+	"GTGL+z9mNjB3cVT+p/DcR60xRs/IsnzfdPSZMlJLJOVkTvp0jO+LfL4X27EcdvPDw3v6OjWSz+TJ" +
+	"Z5l8HIoiquZXPPLqmEUOm39RGa3IwsOfguiZmZqIF2DsDpJJiTapSFYKFGDTr79fD/h/Z/kw1/A/" +
+	"zxQAZAP48GZxmZj/BHm7jPl4tco2zu/RSCM1VNCZI5cwWyltz3GeHlL+w1PK7o8fDTfJUfwq7AqK" +
+	"ElR/1UhrVBdYNUW0LBlGoIo+JbBiaGwNIKCvd/VrVuIOVY+HGZJzZzhRE6ckuA8ticpZOPpOuuXa" +
+	"KImu3UyMxO1amcSxC8mbshm5/lIYjo5kHcND4/kn8sbsRwh++dFinScFgHcTjpweH3aAkjJ7NZJh" +
+	"ddL2dOl6oL1jLNaYM1MgGs52V9cDhBLMwwtZ5YpSzsDNuTpQts24pU5iwhxqgIHKpU1yJCBXnBEJ" +
+	"mSqlV5u7exQh/p1mcnW7JmCri2y1MbKmcokR2TAXipUQkC6CwwQ12Gjnm44X1tVZUp3wlIdJOO5m" +
+	"wrczzu+aFaUilZUS7dnOxbWfWcQeSZ0hL7XHvhkbDzwo37Y5ckj7LmXmHin4QLlw9Ec5/JGyztRG" +
+	"X77Pgow2DsQ6pFw8CK6PUTSTZrWK6ms1J4xnhI0q8I+Ssvmmx/P/r7qE2bRAJB9mf25A5z30NtnL" +
+	"6Pmqft54xt9X3KrN/NSEF1a4R938Ou1vHaOqTRyvO2h+ZZqd1LGaryhzy460Fwfoi7DtiepNdA+V" +
+	"zXPjwfHd+wQOyGMkj0raTGF7VnkvOqpmpZThtUdNn0VJPsKqbdOUAo16juWVKpvxIwUefdTGVI2W" +
+	"xt5rY2t2viki9JK9xd3SJIkOhySAxWJLCGZb4LrTCT3qPu7MoTJE10zkYWgeyawo1blLhbkKGHiZ" +
+	"SLONHph0Zmnz1cYA3RqHbyrB/NqTf4rxWClAjux9sybomMloiRMm9QlnP6Jj5HvtjsYF7il7l0jX" +
+	"MtL9sUMBEpx91hbl+/jW3jqZXfdEZMIOccK6re+rHGqfbGxjYnnDOe8T4OziLqEn8cDo8U3uZNI9" +
+	"+rZY/1+m9aZrGv2EaunZM0m5cU7X1POp5guRbRg2tot/g+/jYyTAipiYd30IhHmjxz8Zc2rQjdcb" +
+	"5CZdXH3fH4T9H42O/j68ZVXgty63afB3lwUIheY9TdWksCKNItEw8L7kwgGaLvc85h6mRaQPm7YI" +
+	"mYnovikrbjd2eGmWNRN588bS0s7T3WjL59IZlW4eJhSFGPW6EDovZLjfDVL74o92s5lyAyQ4INyq" +
+	"gVzWv/j4aw+H6buyxIjRdfRDyZb+NHWrsD23UhRwlyzY42awYWc6lfzag5F55eStTf9rRhuzVROE" +
+	"jAmYZ2bWlICbSehLazA+NNsC7SnKNbXXUMrObZXU0bFu+phdvVja6/DNCQkzS4XqDWlrDytvLVIO" +
+	"fd2Xj0O24X1z453ylFk/j9ve4lz+B8utfOXokeilpTm1L/zvXc5+pNcY/uLmvZPpsezuc4Z+g7I8" +
+	"lVPy/Et9eH+Y3vZIZe+aB/CTMODCDJOMeDdsmKt29WEjDc9AfZ4u1pPukz03zhZ+vzRdmsXjjreU" +
+	"wgzctKJSRVDe5xLLIZmbgWLsFfHqm+F1I9+nyKo9edkYW3R9Ipo983Z02KIfdeHBkMHHn8DW4nz1" +
+	"+5mgdApk5IURBIgEE7boPGAFYAPquEaBic/Rwmnq20EA1FiEVQjBjJBIBfYUfkDwGbkAZUUtZlor" +
+	"CGHFFIkqUrRhxgMJB68bJedguTa7L1cmjNiwpEjFYmlAFEANGhRu+FBdJgUlb+itYpLhS9e+sqou" +
+	"8GwAGRQBD6gRE4/rD9x71IXGomMpBwzAxWCKQqUBQqNKgqXLiV3bppW8JdCriy8WRjlL/y1ldMRN" +
+	"K2pRQFbRHHIpqmjKgqoiL/dcyukplgqt/fhMTEmmVy2jHGg399Na2lx0mApifu28Z7LB3WyX7mAd" +
+	"D99Hq/Cj0hGInwCg7T8PY/TDUMet3DA3yc4aFiKkE/pSz+ovbPD+L8fxI+cfp22n9HmdfqF67pXR" +
+	"+uPpkTj7JuUM554R0uKFZo0uwL/244GOE/tg+zWdJ3fbGmaQg1dnHTLH4+KPnFDj9Vq1ZNL/eozL" +
+	"Oipce/ukJE/6vGGCvqFnbZvqQ34x9B/Cr02eF0o6TvQP8Djg+slju2sLO0IOiOv32aRo+4034LLE" +
+	"svPHM1XAdlzu7umNN0T+MWQPqHjxOSv6tjrUsed7MxDZ6lscn38Yw1ZDHN27SuxtezttN+ryiaRO" +
+	"XO4cZxK4nG9Sxll+s7P2/WoC06HgAniO1M0rO00euOEpcOtyWHtwG/d+iPxcl+LSkORcLIsRkQRY" +
+	"xZkpLTK1Uf7q5MMuiLCRIiIxg39+YMUrdMoqnzK8S9SZNNjS6vRlVG0vLrmmBkmElFkgUhqSZUoy" +
+	"UmokxRtubunYNSN3r7eVeSuxCvS8sVJUbTZpialZgpN5eSOUARUHSKXmk/EfaD1QAkB/R97g+n6D" +
+	"26vxDEMzIsfuDQBwA+SQf6mQD7t/2mqYNm7/n+41MP0TCXIP/o8z8QRjGRgqxFWaMY9g2K3/ibbn" +
+	"CVQUGLt/a2uMYK9wdkaT/RV/f+lsNgbDUGDIrtjJIGxuLmjHdRBiSlIeBRA55x/gJCZKPkGhb5gI" +
+	"JJWoXgE/xQxRGsG8zgwNRkv6s1qmrMuJy7kvcz9XJcvrH/OQ/BrAHAYpIjVX6fsgUoh9SE5Nnd3g" +
+	"zZ5U311/Jt21rX2reXWLDTZ/Plt2iTpC7o2wIXi1ZXpMuC6o8jl5NNK1ufiCI4QYZ8zRkXIHc+o2" +
+	"dz09LIeRrw6SiggEnXNekIZCX/GNh80mkAv64zdnUUYI0HBAe+mYJ+Nr1mrcgsto/JjUU7aG0HJw" +
+	"+mYzx3Gbozde2ufknoISciz5pzjP/aWwB0x5a9CZA/D50hrXtw0a0Z74AjpLgzVltLPpLeL6iG0q" +
+	"eT0iGQ45tex4C64YGHHmL7H5CevzIRfV6WbHr9aOqNxCD9C+CUGRTi4P7HgYpJAYcQYpUDlYDyTZ" +
+	"uEAOmsMCvAloH931YhIqh4pM4neZHlDC7ge0QXGq3/NLHebo/hoKeLx0j4W6vYfxgmqONk1Z7due" +
+	"evpJXmdZdgqUfrP4SJAw0cwobQOPhxgmZKfQ6vLuWksVK01CgzfuOkOo9dB+BxE22TtpuR0dZtWx" +
+	"5D1mSnijyQwYG81v3lFp1zqdJyCT3oUR+eWUtlMov3JgIyU0IgUjij0OEElhAMjJ+KcAgKEwiian" +
+	"dEBke53FPGUpTUCivh9BPQ6TeB4ItgkHv95D5ja/YbE5Kcso/Ah83Gd1SfgrmWZa+wPapwe4uj0T" +
+	"jpLP0z5aD7gqh2N4eknQHYyEYxifBLfE73Xh6/iQvh0EgZswbko0hjTQy+okSCPz/dRWAhP5wpqw" +
+	"140Z3KDUno9Mj1DVf4gJcEhAuAxueaRvE3g3ECbMUAsVZTVzNPYDHEzgiCIDpOcyoJLlCUYWcet4" +
+	"7ePfQZgnwEPNsoYMlyTqz+j5vpktwW0r+fzEMVLJS375MNcESaVLotl3VcK3PHTjsVVFJ3ImDNmM" +
+	"xZAMde2fScG8uc8ZcMpgfnzNJbcHJ2tm5zhDJDGicfN9dMfMjVUO1RR+3bf0eOIquh8+LnG2HusW" +
+	"sWYE+LoxjDBuDur0G2LibFPEDPZ4d2LsHxCzY+kya2SyDctcxxMbhDQmjhzXanEHsHH8Xxb+M/5d" +
+	"lqVPIKkHerSdSSUu9nMGRBMD0tkxGAww5uHB3dbnIY8H4jKEJt549/JdtanPlOc7z8dWrmousQIS" +
+	"QPL3dohW47oSBtCNlmbWOTkS4SZCy3G4kR8IhnaNmh5eqaUO9Tu3ljXXoe56jpfcnek/iH+H1vTx" +
+	"ToHonOg8Gwcx7QnNg24NQkJjgF94VHeqSTLUDqap8BMXW7Rgihk0fA15wQ+fmff999UT+MVilpVv" +
+	"9/P9iHQYfglcQJx1eTrPcf1s/YP0/8f1/u/caT99S5oXWNyhVBcMwDsM/jFSrOPBDwI70ki97A8P" +
+	"h7POfVftueN7/4bc3zV3EfGmj4EVKYLiCEiDYLHGYX9qm0SEAiRIEDuA8Z+YiYA/PUEkFF+MAKiR" +
+	"P2QpOQQdhjIkDIH1yFmsx7DTsealkpikVJonTCoxIp16sK8zzCRJJCfB+vkaptsMEMjbzVE6/9CC" +
+	"XslEEkDiZnPqb7xvvLWb6EBuGSpbCWJbOzPPIekhGTrDqCgCRGXg7wE/WCI+xZbbCVCIkySVhDU6" +
+	"iSHwoqKSnM9om4Z+VKwjShuINg52K8xiMgTwcy+gB5aaaOlIdh6ltZRzk3GM2E1j3QVv0JgtFBEi" +
+	"B9KFkiEEIztjqiVuhtcVgDgDMCQEiQclOBoAb8j0kNzmZqMgqIQiZyBxTqm6JIyIan6NinYhxYSG" +
+	"JyxBA7ymhR8re9Z0wbHbWDFwvUz+H2n2RjBgBMwyhQIayPV9Z14rzyRErRFjaGPLy67W6iyXl3Bi" +
+	"baZCCO67rXs83l5nOutKxBdZDJhhgR1o0apYxhmB4jBgRjEkIT4M9v1zp/I+fbCK8HnO575lkn/x" +
+	"DEhI1lUimGCeYmY5MEkeC/y8HN0fCoDIwZ9/3pzHcanVKpKQPfBNYgf8IpQ06r+VWJIT5W9+InZH" +
+	"GBcbENwEEToXgsIRM0+tLJYkbNix6sWTPLym4icYJ6NsCHrhCHEKRg49maIIwxhSFlsVLRgmJqBb" +
+	"AumFgMpAs0VWMksRvTYghmJ9oesSkwRgrCKDMOdW2onug6Y0rN142vIQBbkKICtRkQq6UsiWaIXf" +
+	"c4N2bAwue2bqKYCGpIiOjrJ9ILIqidEw1MsBF6lIgwsIUJQClSjJAxAJoD8OKwGYB+kzQbYCMTnC" +
+	"nptKOOJa5ZHsK0mYAYNjHHrhFUh+gdf22ft4lhwoht/4iB7pvf74yUstSpWW2BpaTEzMUNDT3+Xx" +
+	"tPZn5va3v7uWsyKsGANWqXAuyIX15bBzAkZcp8ThuDWjZkp7muszHKImsbggb0fmTRp3aoY0BZww" +
+	"qBtlHwvDMYcNnFUOcLBBiqRETh5a8C65MWUeQ3hMEGJA4axRgXCw3LeXMtTZrYS7gOPxqwk/9yho" +
+	"kEN2xaGzpqw0Sx7DP2Rx5OAjGC2nhkCp8eZ7Pcl6KjB7Y1OtCDUXvxr/fIo5Y61MRMo4QBdOORqc" +
+	"H7TSFEUZGRhWkgiiS2Vg2yEsAtkkoqEBBMU6tPGHlxJyOznTetzfbDkQQst0/e/824wA3uKb+eks" +
+	"8KhidRlsSMJBJEDAGfzk7/5Zwkpr3THH5M4PBEx5n17Ub0qggdJM6LfZGplTeD7d7M4RbsaW+zIh" +
+	"bbHrVtBWQYhgTBtzG8s+zmYYfbLM0FtOXg3zdMTnLhLwVII2G07inYX08zDn46f98SfttMDc7tdq" +
+	"tR1vJxHXPFvm56Di3fbb7CB5oO2a2Qkju78J+mXaTrL884tikdO2h9ScaToWOhUMzwO0W+zHSZ3r" +
+	"gy5mzHTPHYxsYRs8BGEQ+z4iyuKoWDUuxuuUwlwHdjD1w7IqRDSnYXEtsIFvacd43TY41gWmzczS" +
+	"imfZnvZw6hxrbbgziJaIZmveTeQXOoZsrON81oli52q8qR91ydprp136HHBswDP06BnoTlbpY3Bp" +
+	"hxKurWoC0sheZ0mG1NnXPK+WlJUMluUhjBkEb5UN5eLeEtxZkYYDTjx3XXn15raUWGBjKdQ2iYzq" +
+	"u80wb8DmFyWsdxFmhLGIyYgd3WU0Pd8HW9zvOpFDiJdh5QzUuMvN1MXW8Xc3O0TnOCSjDNYZY0OO" +
+	"1l7JZqnMMugzQwuoDOzTRBiDjHcGRGNUQQ2DOnKqECwRXKd7FCkOgWFiBxOkpCHZANAzRcxiCQYb" +
+	"TJBF6CLIoRQDtP4fLn9Peg4WBtZDpZ5UAwYLAEQURCfyfn6S47noxNAXMzYSQFhCCyECABAmB0Kz" +
+	"sw98wXf6rwgt4pBiQBukIhpoDiPT1PZtXMNxjvUQ4/qymZQ5rMw2BooMJn8SQkzvzpPgv1xtKu2M" +
+	"bMMfIRhYQNysAjqwTTY7i2ZqmOtw3gIc0oq6OqHWU39P0my8MNYbESokIP1kAOhFL2GQCw5GcPsj" +
+	"5BJdoBvGEeRzM8J2Jyx6nk5l6oJCrEGKvhCHMTXB1hYG1fP3a1n2ZA7vGrcbs+3KApFTBlZS2mMh" +
+	"JDECQxtcC34jSXUwOnsNeEHhiI8GWOiMInnEM6+bYdZ4z4ezEWCLEioyDEjAFmk+g8b2NRvRdMbj" +
+	"ZSNjM2KKmb6Ha6hS2zWlBqPh9L2eW2vVXy+veMsGVCKUsUCSoPWmmGMsjWUJLl8YlplnIPSBobnz" +
+	"ppHclkdYC2eWr5gqG0KcDtgoe2Bm1EVjFJ0rBCCqWhOGR00mSNBFDeJuA8I+jSGykN9il6Shmj1k" +
+	"D88BYgyLCe6lM1XjJDIY5DwVNmny26pmRqq5hxN0770E37hPulwMJkrjLS3TImIOLamTjAFEyWKm" +
+	"xQFKMhxOvYsr5MAgQ3/OJ4QOYm5WQP0hXg5AA5xQYME7fFCoBIJEOPM32CAfqQ2oO5cPfF8JERhB" +
+	"SU0J+SCWAXFy9RupRaY/bh9QdwQP3sZJHx6EPIQ+J8mOUvp8vfAfZP4sJgRGLbKMUgxAKRkKrCEi" +
+	"viWV+jrJIglYLIRqj0ko6QxcWWHtEoXyCSQbiZMgAicn6GG+0YcTCSFz0sVIOk4Sfnequ1CyymVQ" +
+	"LQ3mt2q9FRkJa3zVEkFgJjEzOjuygElBVCB2m2ZUnPzGrmfRqfDs8KSCiCMVjGD5EPW8dBEnA/dZ" +
+	"26RHQB3mI9AGQ0dG8Yez3OW9Uo2lBBthKkbYWuYUzxyEODR/OB+Mw09HWNPsDiBdsvpDYtitRVJQ" +
+	"bURSAxT1TiElh9RIO5SqWwOMh79GtpJXuRhkfidxAn0IIP0sULRYwRhbbbZVw8w3Dx69lZ8oQtn+" +
+	"wP+h0JOY/eeT4y/Y+mynVjc5IYJQb0t3QkHIPqgQ4JxJmb5W/6+t16TV6Q+by3Xlmv0stEbJZYrP" +
+	"3Vpoa9J+LBhGBGAPEoVOegvTxtQgwZRI2goEUkkG2VKwlJ0nh0HWKmRzfwpOI/YkTF/JwVzgiceK" +
+	"QIjIE8TnxOv173TUwNt4te2B1fU15wGEE6oPpez8o+JryMT3HvDXaF3ii9ywJEDh29LbRHw35sTZ" +
+	"HTbm0Dz3w6O+XOshot1XKs5Lyq9XgmgGRMLOl2h0wOL4dK8nS97r4YhKE+/uuOPkGz7ENQzrDqaK" +
+	"eCCxggisgKqJQkgGoosJGYdV6vjqW6etE4h8zj2jpuIA8yMkgoSDUix+cZAYrLAfWAwz41REqpH0" +
+	"nyD7fFGk2pLUWmZq0jVTaV87gpTimFoMk6CG0MKU9N2JZqGZMCzUFNQKXCFie2Bk6NFkN2iahqd0" +
+	"TUL0PoBd0Z290I/cUoEZ4MYRRbKLTp6ZNhloaSFsqo0paokUEGQjIQIiRYC/pNEC6IqiF8Dkeyqn" +
+	"JJo/j+AEzeusxpCBHZbt3Z3nEOiGpTDhSLd02YNlpvN3JN2biuIUTWVJkqlpZm2SadzIymtOoIwm" +
+	"9Cm4MSGFJl3fXvWwqG8TZUw4NAZGMJrJOfufKAya+i0Gw7zE2PDQVPZippYfkBJIblusI7LkQF4w" +
+	"TieqM1Q391XtVi1ECRGwuacU3RoM+hiBIFBRIZW/vXKsjEOMVmhRmGZaE7y9THsnwzG4vjKAkhGc" +
+	"wJ1qQdFgniU0EqNFctIja5vRKLqjOiKgxZIk7lAoBg22zgmZRQssDPaAyL90EObLBA6eghCMQhdt" +
+	"CL5/ses39Q/Kjqia4HvV7wOFvEaShymnHiMeJQ0SYBGE8aFnxalICkMPOw0qOUl3Nwgckkj8w0L4" +
+	"9fVrVNZNOPnwdJycD9FNJ9886azUp5tqGY+EAYeKTfvgnWyMDoYgZGLDNSmJnCqaAMIBkGdDc8rR" +
+	"RIpCpUktoRdFzBodMKjG1K865pNFr0q+DTbT9cKuI6noLmhbcIUQFHS5v377BVJTsRM38/k7bjVQ" +
+	"/QsGFAWOwy4omnhwaQ4dir9UBWLBQtxIJqOc0kd+1gLNFJRamnepDQhCb0D22mGERkybwyhxbkvG" +
+	"DfXrYw0hu4GOIYTDa3IR130b1DVq4FlBjTdyZZILa5cMBJorNMsfJKzYbIZibbkDp9eD+qcSCJ+Z" +
+	"Aw6J6JiTwaKiMsCRrPJo/VKomqUUaNX77+KQwCQBk8d+WuyGzDeB+XezzxcuJGLIhkMpMD6P173X" +
+	"LtobHIhvI8zl/jzAYzfP15Vtfno0bRSr3OiMZIyCc76lEhkyY6kJdFFExO7MSLFNET9zDMoTSfEm" +
+	"FECcF1Y5N4ToR0aUA3GSzFkiICKKM2wagnNB58ypLSPqzEaq0TxVGQloCZoMHKnM4RsYCB3sjADF" +
+	"0ulOqQx3OhD3kXkllMGDo+iI0e2gNQihIWnefq7k8HyQBTwO6HqOTDBbhLDMeBmE3d2ry1uaxUlV" +
+	"9WZLWNc18Mua2SNpqTx2umteedVqW9zIWW4rAboajE0SBhAcQLS6xZdoLE5myiDDRCnAer5IeqVC" +
+	"p4fZ8tnsnIL0sMgb0WgFSV2D9yOEDOg9ScQ8SeBT9Fu13qH0Ia/TilDH0r7/kCRPayBFqjiF41Pn" +
+	"B+IRYJBzdlB68ANn839DLohhGQB64qMgHpYhQyLpQVEYEQUCwmtEiprwfikV8whevoRXFAgbsEuM" +
+	"IAGJosjS1IzJmtC2QVIJ85D3MhplhRsD2JLlKgZlCBGRTx7OIFoaJDWV1p6ZY2MA3mTkVuTCLvkY" +
+	"B9GQuA5JGEEkAIzNyD7XtQedjp3G16IAZoIFHukAm/wpuNsrbW9+RESIe+yorMlloVIl62QMxK0l" +
+	"JIsGBZaSASHuIqUkoOtNsqdiQ01oDA3qvbA9AFEWBFXviyRgWqSxkWs2irRtSWyo4XBSwbCYjsF0" +
+	"JyEDqA876sc4VAoO4NNd5wAlkHoPthseqcSMzdXvnnuMNy9LCQ76CTonH2SJtAO7mFUwWlkEafWW" +
+	"UJgaipGBIwwcBTZozNJTWvxlhY6P1jTHN1r7qs+a63NG80pJo1FGpCgpWmW9G07U7LmClLJRMtIH" +
+	"+XRZByw0WARSKtIlpEEa++lAsGIXNYJSOdY0GZbMFERKblrWECLFCWULJbSgFSpXyNoOytD3YL90" +
+	"xYSQhlD1QLJLQI0He9BzCEnVUSqicw+8My4R9hISYkJGYIxj8ruAhMajQwXdcJGBSBFRYiEzLDQs" +
+	"CajBMxmCr9tr+pNttLXxe3r5N7djRszWjJLEZs1mapMmmTJTQTNpSqUZsNU0JRlqNljWTbV+p7df" +
+	"Lo0rUkVjdV+CKMDKORHjOxLhIwk9G21jFEYFD4XjWjw8wvyPogFPIeTDwiBloHASYHMk8xALgXwl" +
+	"ATRqLTEQYWQsVkWQUKaMBwo7AQKQfAF3fSVyBBLobqUc9N30Yhd9lPGGxI9LQNomLwZp5ZZsMZkl" +
+	"oF2Byvel2w26lwkZCYQKHFs8KDgeFO2+29nFIKMOG7yWYijLbKDKNtLaksQtZVRtZBGNkVAxCiCA" +
+	"Y0LYLJWyyolpYoiIlGrAkS1LLY5k3YQxlKvO3TdNkNSU2Rdd21cyEIcUog9BsnPOQYJDHgyjFjMY" +
+	"rbgvBfJuwtEhGMMokttuSiYYRmQzSrobTNZGFRBRJ0D9I/mJERaCCLCgGiqRrIBlFPnSl5lPE51v" +
+	"mPyjjESFnwAxWlkO96k1MjkQjxldSypErtlBcLC2xJa5YIMOc9hTxTkPSHujC48AnAicrbndNoPO" +
+	"N74pxoN1p5k0VDQyShtPkmhEPSBIBwWmSBAhFI4ntAwUbinCB4hQIFQWEEWCWrvE3qfzQrTTT7si" +
+	"6zQ8MvTyensgBuMEix6adydCOBCBUjFYG+R5YCfYgcfe3KBA528A6ViECYJgPJNB3nSTyDyPKUoB" +
+	"/mQIKxFDYbNYIYrQNbnFO2rWmvkt5vFGebcxXGlIkCiBwVLS2QolREpXmBd2Q8XDpAVtaSkE0BTO" +
+	"nujaCkO9awitnCKKcMnFFHh6fqiPxztdZntuRCeDzyIgwh826nhMzIM2TOwEXW01STLWw5saZe6L" +
+	"ZJoHfoIya3HY79edGjjYfToLT9W+yIpw8X2hhlKhzNjppSbn3t5mBXnyGl+qT7uQbI5+TV6rtb5z" +
+	"y+41+l5LWFxPpRlQGUYQndmJEQkgvWI4R/1s40rG2dyJDQtbruUVR5sPluFVcb5o5DQrT35OfHg6" +
+	"nXsdDhJ4Nkg6D223DHsUoizm1yj4XOdaoIMlVhMBJZJmCIHqgC0gfgz7LGB9HflZG54HCcBh4375" +
+	"6X1dGN+X5axnNu8vqiV7DyNFDXakMyESZcSBwet+6o/TaDQ2yz52GvPcN8lqBxN23CHsR/XQBTJC" +
+	"lBxVhYJyjcQgQvEU1rk+6HSk9vKX+aSBPeAzRGEsBBisD2+XwrWjbRJaEliHqYvlo00yzvSnv9dM" +
+	"IE4khSVKE0W3I2lkgwSAHIhNIEKQQELu+sjBqOm7Ur2wecZHEVHbQYRG+frxWHNZz8VZk4Em5sHZ" +
+	"45CsKUcCifEbXdlIxssZqYYyRUVA+UgcJuAeJwptCkVnJypDkksFFCXJaUuMU2A9AwjZg0nU3GQF" +
+	"qrx3zaKJS3bl733s0xg0apuNuDStMwxlcQVMQQKVQSCZvRLTcU76R4xLMmc45p69aBkD9poNHIAd" +
+	"IFnQkWRDo32AsplDEwLMsMJsGweqY8JPrmunefNpeK8/dLFIqiYhNYz0QzOmhJGEB4LqASPQy9S8" +
+	"obyytQSt66RgQTZZrWZKxiBqQEicBaQPIO6uPfxPFVgzwxzWUbAkltjaNVbTLUj8W+oEtzaWw8tn" +
+	"JhMw+KeonmDEPs9ppd82wYnDsFIVXJTYejCLMRdxe17QzSmWWQ5F4rbErEQhMxuQb6n4lrW+BF4V" +
+	"MbVfZ4moMOjGHVTmNx+DkrbHWs9JZwe2dbvDNDJnT1xJDMtVDIDNVn28eMDhnCKVCs4SsDGI3JRC" +
+	"4FRQycOmGmzVtDCswMNYHQutmo1uWyqAiLp4YmEIKcdLMpQRYzDRcy/Gryi4zHhmO2DrMlwtiFxs" +
+	"y2URYJEW2gl9WQpkJcLLPWevecJ17XXby7blWRRB4c6cgYhEYsM8wsNyABYwJtUgZTpNybGcdonJ" +
+	"jJYb3nicBcbBxDZzEMgiSIY4IkvGEhqJZLjBsFwzJlyJGR+DaLlt2SkuN17TCLhcW8YTBMwUziQJ" +
+	"n52sYOp21W0RM8UC+fKzk0bnoqBHWMxnAW7wCKc/x7rcjpmWhpRANpXlDKoBjEXS35bNSwzddkdA" +
+	"OajcSPD5WSQxnM63z99hzqciJVGxghWs2lipUVyOSjj0zMZ8aVDnmx9pb2tWoKtfFa3u2xrTKS1N" +
+	"7OFeumgtBKKaR+2UJzieUMYBjAIR0WTWmbctjckr7N3VPOru7XMVNk3dt2WIqK02ZudmLFCQkCqp" +
+	"qCyBjGVEdTfF1r7+h+B4O7cou29BYbMh0BFODClliYY5AfJs4+D71Yp7UjPhZjgi333MsPyptUte" +
+	"pFqLJSVa3K525vVziUCCba1HiWF6EI0alvjIt9W7XktfUWvmlum4Kk1aPtoT6dBkB9UaFZ5QZbHG" +
+	"W9Hx/keXtc/nnahU1Y7RoJIXYWFhEDWKe07iby+65oodgnCkf5NWkMTu19eoiz4tB2FkEbAkZFkC" +
+	"QJE2Av9uxj+i4HbYr0Tvi1I5100j8WCciL7h7fGgQTpfTgkJBFPsDsIMZBj5Wy+oD9j+QeOzkqpU" +
+	"q/oD+P02H4E8UHwsrFH7aSsGVsBMw62mEXoSkQ84lgDk6QPTQSKJ6IDuMet75Q5MuoXGTnYascmB" +
+	"kZYOrLA4yQwFTEheZ+Y+BIKiIshoD3MOAx7LfBLUJvRj7KCQhCEoyU2M7LULDIge6lGgjgY1GgVP" +
+	"1KiERIjIAqighIyEC+Xs59Werg1dzsxTVbdmPUHCsMCzELDJzLSojrMVCiDFw8Wmp7p8Vfz5LJrI" +
+	"SQcTIJk0em8ShhFjDJtzeGIl0lZ35N7yVChV+qBCJAjIDCMsy22FjGaitTTZRNUXvy4bk3m7YZ2P" +
+	"WRoBNMYUgOEQMeLhWFF1FeiKoHKwXDHI4GF4EzoogSYlFYVPFwyzgyUiM/HtTQzSwY3/935P/pVS" +
+	"I5ztPxjuSv4UbQOH7cbKdMD1cq9uVWjVUZovZM7cZLxSrw2eWrDGsDgVWAPhYSdXl3xfH0oaTwfb" +
+	"21zqsFhC8NIHdIQSGZveMwM7oSy4ZzP7nD3WnjXGmq73mP93ldP8PvgOpMwbfV1RvR+V/DOnF9rK" +
+	"v9hdyRThQkN3QmOE"
diff --git a/test/bench/go1/revcomp_test.go b/test/bench/go1/revcomp_test.go
index 9256164..6b6c1e5 100644
--- a/test/bench/go1/revcomp_test.go
+++ b/test/bench/go1/revcomp_test.go
@@ -77,9 +77,9 @@ func revcomp(data []byte) {
 	}
 }
 
-func BenchmarkRevcomp25M(b *testing.B) {
-	b.SetBytes(int64(len(fasta25m)))
+func BenchmarkRevcomp(b *testing.B) {
+	b.SetBytes(int64(len(fastabytes)))
 	for i := 0; i < b.N; i++ {
-		revcomp(fasta25m)
+		revcomp(fastabytes)
 	}
 }
diff --git a/test/bench/shootout/binary-tree.c b/test/bench/shootout/binary-tree.c
index 1b40704..9c35ac5 100644
--- a/test/bench/shootout/binary-tree.c
+++ b/test/bench/shootout/binary-tree.c
@@ -36,7 +36,6 @@ POSSIBILITY OF SUCH DAMAGE.
        icc -O3 -ip -unroll -static binary-trees.c -lm
 */
 
-#include <malloc.h>
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/test/bench/shootout/k-nucleotide.c b/test/bench/shootout/k-nucleotide.c
index 3bace39..9c30620 100644
--- a/test/bench/shootout/k-nucleotide.c
+++ b/test/bench/shootout/k-nucleotide.c
@@ -221,7 +221,7 @@ main ()
 
    free(s);
 
-   g_ptr_array_foreach(roots, free, NULL);
+   g_ptr_array_foreach(roots, (GFunc)free, NULL);
    g_ptr_array_free(roots, TRUE);
 
    return 0;
diff --git a/test/bench/shootout/mandelbrot.go b/test/bench/shootout/mandelbrot.go
index 1f9fbfd..df60343 100644
--- a/test/bench/shootout/mandelbrot.go
+++ b/test/bench/shootout/mandelbrot.go
@@ -50,21 +50,21 @@ func main() {
 	out := bufio.NewWriter(os.Stdout)
 	defer out.Flush()
 
-	w := *n
-	h := *n
+	w := float64(*n)
+	h := float64(*n)
 	bit_num := 0
 	byte_acc := byte(0)
 	const Iter = 50
 	const Zero float64 = 0
 	const Limit = 2.0
 
-	fmt.Fprintf(out, "P4\n%d %d\n", w, h)
+	fmt.Fprintf(out, "P4\n%d %d\n", *n, *n)
 
-	for y := 0; y < h; y++ {
-		for x := 0; x < w; x++ {
+	for y := 0.0; y < h; y++ {
+		for x := 0.0; x < w; x++ {
 			Zr, Zi, Tr, Ti := Zero, Zero, Zero, Zero
-			Cr := (2*float64(x)/float64(w) - 1.5)
-			Ci := (2*float64(y)/float64(h) - 1.0)
+			Cr := (2*x/w - 1.5)
+			Ci := (2*y/h - 1.0)
 
 			for i := 0; i < Iter && (Tr+Ti <= Limit*Limit); i++ {
 				Zi = 2*Zr*Zi + Ci
@@ -85,7 +85,7 @@ func main() {
 				byte_acc = 0
 				bit_num = 0
 			} else if x == w-1 {
-				byte_acc <<= uint(8 - w%8)
+				byte_acc <<= uint(8 - uint(*n)%8)
 				out.WriteByte(byte_acc)
 				byte_acc = 0
 				bit_num = 0
diff --git a/test/bench/shootout/threadring.c b/test/bench/shootout/threadring.c
index 2c4fb77..a518134 100644
--- a/test/bench/shootout/threadring.c
+++ b/test/bench/shootout/threadring.c
@@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
 * contributed by Premysl Hruby
 */
 
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <pthread.h>
@@ -57,7 +58,7 @@ static struct stack stacks[THREADS];
 
 static void* thread(void *num)
 {
-   int l = (int)num;
+   int l = (int)(uintptr_t)num;
    int r = (l+1) % THREADS;
    int token;
 
@@ -94,7 +95,7 @@ int main(int argc, char **argv)
       pthread_mutex_lock(mutex + i);
 
       pthread_attr_setstack(&stack_attr, &stacks[i], sizeof(struct stack));
-      pthread_create(&cthread, &stack_attr, thread, (void*)i);
+      pthread_create(&cthread, &stack_attr, thread, (void*)(uintptr_t)i);
    }
 
    pthread_mutex_unlock(mutex + 0);
diff --git a/test/bench/shootout/timing.log b/test/bench/shootout/timing.log
index 2541a76..ee1f889 100644
--- a/test/bench/shootout/timing.log
+++ b/test/bench/shootout/timing.log
@@ -900,3 +900,264 @@ threadring 50000000
 
 chameneos 6000000
 	gc chameneosredux	7.41u 0.00s 7.42r # -3%
+
+# A complete run at the Go 1 release.
+# Significant changes:
+# - gccgo is now enabled for all tests (goroutines are cheap enough)
+# - threadring and chameneos are 14% faster, probably due to runtime changes
+# - regex-dna 36% faster
+# - fannkuch-parallel (only) slowed down 40%
+# - gccgo on binary-tree-freelist is still optimized to nothing
+# Other changes are modest.
+
+fasta -n 25000000
+	gcc -O2 fasta.c	1.45u 0.02s 1.48r
+	gccgo -O2 fasta.go	1.46u 0.00s 1.47r
+	gc fasta	1.99u 0.01s 2.00r
+	gc_B fasta	1.99u 0.01s 2.01r
+
+reverse-complement < output-of-fasta-25000000
+	gcc -O2 reverse-complement.c	0.95u 0.48s 4.99r
+	gccgo -O2 reverse-complement.go	0.93u 0.16s 1.09r
+	gc reverse-complement	1.20u 0.19s 1.39r
+	gc_B reverse-complement	1.04u 0.16s 1.20r
+
+nbody -n 50000000
+	gcc -O2 -lm nbody.c	13.02u 0.00s 13.05r
+	gccgo -O2 nbody.go	14.46u 0.00s 14.49r
+	gc nbody	21.79u 0.00s 21.84r
+	gc_B nbody	21.74u 0.00s 21.79r
+
+binary-tree 15 # too slow to use 20
+	gcc -O2 binary-tree.c -lm	0.60u 0.01s 0.61r
+	gccgo -O2 binary-tree.go	1.30u 0.01s 1.32r
+	gccgo -O2 binary-tree-freelist.go	0.00u 0.00s 0.00r
+	gc binary-tree	1.84u 0.01s 1.86r
+	gc binary-tree-freelist	0.33u 0.00s 0.33r
+
+fannkuch 12
+	gcc -O2 fannkuch.c	45.24u 0.00s 45.34r
+	gccgo -O2 fannkuch.go	59.76u 0.01s 59.90r
+	gccgo -O2 fannkuch-parallel.go	218.20u 0.01s 61.60r
+	gc fannkuch	103.92u 0.00s 104.16r
+	gc fannkuch-parallel	221.61u 0.00s 60.49r
+	gc_B fannkuch	53.17u 0.00s 53.30r
+
+regex-dna 100000
+	gcc -O2 regex-dna.c -lpcre	0.47u 0.00s 0.48r
+	gccgo -O2 regex-dna.go	6.52u 0.00s 6.54r
+	gccgo -O2 regex-dna-parallel.go	14.40u 0.73s 4.35r
+	gc regex-dna	2.63u 0.02s 2.66r # -36%
+	gc regex-dna-parallel	2.87u 0.01s 1.11r
+	gc_B regex-dna	2.65u 0.00s 2.66r
+
+spectral-norm 5500
+	gcc -O2 spectral-norm.c -lm	15.78u 0.00s 15.82r
+	gccgo -O2 spectral-norm.go	15.79u 0.00s 15.83r
+	gc spectral-norm	19.76u 0.00s 19.80r
+	gc_B spectral-norm	19.73u 0.01s 19.78r
+
+k-nucleotide 1000000
+	gcc -O2  k-nucleotide.c	5.59u 0.03s 5.63r
+	gccgo -O2 k-nucleotide.go	4.09u 0.03s 4.13r
+	gccgo -O2 k-nucleotide-parallel.go	4.50u 0.06s 1.63r
+	gc k-nucleotide	9.23u 0.02s 9.27r
+	gc k-nucleotide-parallel	9.87u 0.03s 3.55r
+	gc_B k-nucleotide	9.20u 0.00s 9.22r
+
+mandelbrot 16000
+	gcc -O2 mandelbrot.c	36.09u 0.00s 36.18r
+	gccgo -O2 mandelbrot.go	41.69u 0.01s 41.80r
+	gc mandelbrot	60.91u 0.02s 61.07r
+	gc_B mandelbrot	60.90u 0.00s 61.04r
+
+meteor 2098
+	gcc -O2 meteor-contest.c	0.09u 0.00s 0.09r
+	gccgo -O2 meteor-contest.go	0.09u 0.00s 0.09r
+	gc meteor-contest	0.14u 0.00s 0.15r
+	gc_B meteor-contest	0.14u 0.00s 0.14r
+
+pidigits 10000
+	gcc -O2 pidigits.c -lgmp	2.27u 0.00s 2.27r
+	gccgo -O2 pidigits.go	8.65u 0.00s 8.67r
+	gc pidigits	3.70u 0.04s 3.75r
+	gc_B pidigits	3.72u 0.02s 3.75r
+
+threadring 50000000
+	gcc -O2 threadring.c	40.91u 369.85s 323.31r
+	gccgo -O2 threadring.go	26.97u 30.82s 57.93r
+	gc threadring	12.81u 0.01s 12.85r # -13%
+
+chameneos 6000000
+	gcc -O2 chameneosredux.c -lpthread	9.44u 72.90s 12.65r
+	gccgo -O2 chameneosredux.go	7.73u 7.53s 15.30r
+	gc chameneosredux	6.51u 0.00s 6.53r # - 14%
+
+# After http://codereview.appspot.com/6248049, moving panicindex
+# calls out of line (putting the likely code into a single path and shortening
+# loops). Significant changes since the last run (note: some are slower for
+# unrelated and as yet undiagnosed reasons):
+
+nbody -n 50000000
+	gc nbody	19.10u 0.01s 19.19r # -12%
+	gc_B nbody	19.19u 0.00s 19.23r # -12%
+
+binary-tree 15 # too slow to use 20
+	gc binary-tree	1.49u 0.01s 1.51r # -19%
+	
+fannkuch 12
+	gc fannkuch	60.79u 0.00s 60.92r # -41%
+	gc fannkuch-parallel	183.51u 0.01s 51.75r # -14%
+	gc_B fannkuch	51.68u 0.00s 51.79r # -3%
+
+k-nucleotide 1000000
+	gc k-nucleotide	9.74u 0.04s 9.80r # +6%
+	gc k-nucleotide-parallel	9.89u 0.05s 3.59r # +1%
+	gc_B k-nucleotide	9.39u 0.02s 9.43r # +2%
+
+mandelbrot (much slower, due to unrelated http://codereview.appspot.com/6209077)
+	gc mandelbrot	100.98u 0.00s 101.20r # +65%
+	gc_B mandelbrot	100.90u 0.01s 101.17r # +65%
+
+meteor 2098
+	gc meteor-contest	0.13u 0.00s 0.13r # -13%
+	gc_B meteor-contest	0.13u 0.00s 0.13r # -7%
+
+# May 30, 2012.
+# After http://codereview.appspot.com/6261051, restoring old code generated
+# for floating-point constants. Mandelbrot is back to its previous numbers.
+
+mandelbrot 16000
+	gcc -O2 mandelbrot.c	36.07u 0.00s 36.16r
+	gccgo -O2 mandelbrot.go	41.72u 0.01s 41.90r
+	gc mandelbrot	60.62u 0.00s 60.76r
+	gc_B mandelbrot	60.68u 0.00s 60.82r
+
+# May 30, 2012.
+# After http://codereview.appspot.com/6248068, better FP code
+# by avoiding MOVSD between registers.
+# Plus some other timing changes that have crept in from other speedups,
+# from garbage collection to Printf.
+
+fasta -n 25000000
+	gc fasta	1.76u 0.00s 1.76r # -12%
+	gc_B fasta	1.71u 0.00s 1.72r # -12%
+
+nbody -n 50000000
+	gc nbody	17.56u 0.00s 17.60r # -8%
+	gc_B nbody	17.30u 0.00s 17.34r # -10%
+
+fannkuch 12
+	gc fannkuch-parallel	155.92u 0.01s 44.05r # -15%
+
+k-nucleotide 1000000
+	gc k-nucleotide	9.22u 0.01s 9.26r # -5%
+	gc k-nucleotide-parallel	9.23u 0.03s 3.26r # -9%
+	gc_B k-nucleotide	9.22u 0.03s 9.28r # -2%
+
+mandelbrot 16000
+	gc mandelbrot	44.80u 0.00s 44.90r # -27%
+	gc_B mandelbrot	44.81u 0.00s 44.92r # -26%
+
+pidigits 10000
+	gc pidigits	3.51u 0.00s 3.52r # -6%
+	gc_B pidigits	3.51u 0.00s 3.52r # -6%
+
+# Aug 28, 2012
+# After some assembler work in package big.
+pidigits 10000
+	gc pidigits	2.85u 0.02s 2.88r # -22%
+	gc_B pidigits	2.88u 0.01s 2.90r # -21%
+
+# Sep 26, 2012
+# 64-bit ints, plus significantly better floating-point code.
+# Interesting details:
+# 	Generally something in the 0-10% slower range, some (binary tree) more
+#	Floating-point noticeably faster:
+#		nbody -25%
+#		mandelbrot -37% relative to Go 1.
+#	Other:
+#		regex-dna +47%
+fasta -n 25000000
+	gcc -O2 fasta.c	1.43u 0.03s 1.46r
+	gccgo -O2 fasta.go	1.47u 0.00s 1.47r
+	gc fasta	1.78u 0.01s 1.80r
+	gc_B fasta	1.76u 0.00s 1.76r
+
+reverse-complement < output-of-fasta-25000000
+	gcc -O2 reverse-complement.c	1.14u 0.39s 11.19r
+	gccgo -O2 reverse-complement.go	0.91u 0.17s 1.09r
+	gc reverse-complement	1.12u 0.18s 1.31r
+	gc_B reverse-complement	1.12u 0.15s 1.28r
+
+nbody -n 50000000
+	gcc -O2 nbody.c -lm	13.02u 0.00s 13.05r
+	gccgo -O2 nbody.go	13.90u 0.00s 13.93r
+	gc nbody	17.05u 0.00s 17.09r
+	gc_B nbody	16.30u 0.00s 16.34r
+
+binary-tree 15 # too slow to use 20
+	gcc -O2 binary-tree.c -lm	0.61u 0.00s 0.61r
+	gccgo -O2 binary-tree.go	1.24u 0.04s 1.29r
+	gccgo -O2 binary-tree-freelist.go	0.21u 0.01s 0.22r
+	gc binary-tree	1.93u 0.02s 1.96r
+	gc binary-tree-freelist	0.32u 0.00s 0.33r
+
+fannkuch 12
+	gcc -O2 fannkuch.c	45.19u 0.00s 45.29r
+	gccgo -O2 fannkuch.go	60.32u 0.00s 60.45r
+	gccgo -O2 fannkuch-parallel.go	185.59u 0.00s 59.49r
+	gc fannkuch	72.14u 0.00s 72.30r
+	gc fannkuch-parallel	172.54u 0.00s 43.59r
+	gc_B fannkuch	53.55u 0.00s 53.67r
+
+regex-dna 100000
+	gcc -O2 regex-dna.c -lpcre	0.47u 0.00s 0.47r
+	gccgo -O2 regex-dna.go	6.49u 0.05s 6.56r
+	gccgo -O2 regex-dna-parallel.go	14.60u 0.67s 4.42r
+	gc regex-dna	3.91u 0.00s 3.92r
+	gc regex-dna-parallel	4.01u 0.03s 1.56r
+	gc_B regex-dna	3.91u 0.00s 3.92r
+
+spectral-norm 5500
+	gcc -O2 spectral-norm.c -lm	15.85u 0.00s 15.89r
+	gccgo -O2 spectral-norm.go	15.86u 0.00s 15.89r
+	gc spectral-norm	19.72u 0.00s 19.76r
+	gc_B spectral-norm	19.68u 0.01s 19.74r
+
+k-nucleotide 1000000
+	gcc -O2 k-nucleotide.c -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -lglib-2.0 	4.90u 0.01s 4.93r
+	gccgo -O2 k-nucleotide.go	4.78u 0.01s 4.80r
+	gccgo -O2 k-nucleotide-parallel.go	6.49u 0.02s 2.18r
+	gc k-nucleotide	9.05u 0.02s 9.09r
+	gc k-nucleotide-parallel	9.27u 0.01s 3.29r
+	gc_B k-nucleotide	8.95u 0.03s 9.00r
+
+mandelbrot 16000
+	gcc -O2 mandelbrot.c	36.11u 0.00s 36.19r
+	gccgo -O2 mandelbrot.go	43.67u 0.00s 43.77r
+	gc mandelbrot	38.57u 0.00s 38.66r
+	gc_B mandelbrot	38.59u 0.00s 38.68r
+
+meteor 2098
+	gcc -O2 meteor-contest.c	0.09u 0.00s 0.09r
+	gccgo -O2 meteor-contest.go	0.09u 0.00s 0.09r
+	gc meteor-contest	0.13u 0.00s 0.14r
+	gc_B meteor-contest	0.12u 0.00s 0.13r
+
+pidigits 10000
+	gcc -O2 pidigits.c -lgmp	2.26u 0.00s 2.27r
+	gccgo -O2 pidigits.go	9.05u 0.00s 9.07r
+	gc pidigits	2.88u 0.02s 2.90r
+	gc_B pidigits	2.89u 0.00s 2.90r
+
+threadring 50000000
+	gcc -O2 threadring.c -lpthread	37.30u 327.81s 289.28r
+	gccgo -O2 threadring.go	42.83u 26.15s 69.14r
+	gc threadring	13.00u 0.00s 13.03r
+
+chameneos 6000000
+	gcc -O2 chameneosredux.c -lpthread	8.80u 71.67s 12.19r
+	gccgo -O2 chameneosredux.go	11.28u 6.68s 18.00r
+	gc chameneosredux	6.94u 0.00s 6.96r
+
diff --git a/test/bench/shootout/timing.sh b/test/bench/shootout/timing.sh
index dd3e664..2db895c 100755
--- a/test/bench/shootout/timing.sh
+++ b/test/bench/shootout/timing.sh
@@ -10,6 +10,14 @@ O=$GOCHAR
 GC="go tool ${O}g"
 LD="go tool ${O}l"
 
+gccm=""
+case "$O" in
+8)
+	gccm=-m32;;
+6)
+	gccm=-m64;;
+esac
+
 PATH=.:$PATH
 
 havegccgo=false
@@ -78,7 +86,7 @@ run() {
 
 fasta() {
 	runonly echo 'fasta -n 25000000'
-	run 'gcc -O2 fasta.c' a.out 25000000
+	run "gcc $gccm -O2 fasta.c" a.out 25000000
 	run 'gccgo -O2 fasta.go' a.out -n 25000000	#commented out until WriteString is in bufio
 	run 'gc fasta' $O.out -n 25000000
 	run 'gc_B fasta' $O.out -n 25000000
@@ -88,7 +96,7 @@ revcomp() {
 	runonly gcc -O2 fasta.c
 	runonly a.out 25000000 > x
 	runonly echo 'reverse-complement < output-of-fasta-25000000'
-	run 'gcc -O2 reverse-complement.c' a.out < x
+	run "gcc $gccm -O2 reverse-complement.c" a.out < x
 	run 'gccgo -O2 reverse-complement.go' a.out < x
 	run 'gc reverse-complement' $O.out < x
 	run 'gc_B reverse-complement' $O.out < x
@@ -97,7 +105,7 @@ revcomp() {
 
 nbody() {
 	runonly echo 'nbody -n 50000000'
-	run 'gcc -O2 -lm nbody.c' a.out 50000000
+	run "gcc $gccm -O2 nbody.c -lm" a.out 50000000
 	run 'gccgo -O2 nbody.go' a.out -n 50000000
 	run 'gc nbody' $O.out -n 50000000
 	run 'gc_B nbody' $O.out -n 50000000
@@ -105,16 +113,16 @@ nbody() {
 
 binarytree() {
 	runonly echo 'binary-tree 15 # too slow to use 20'
-	run 'gcc -O2 binary-tree.c -lm' a.out 15
+	run "gcc $gccm -O2 binary-tree.c -lm" a.out 15
 	run 'gccgo -O2 binary-tree.go' a.out -n 15
-	run 'gccgo -O2 binary-tree-freelist.go' $O.out -n 15
+	run 'gccgo -O2 binary-tree-freelist.go' a.out -n 15
 	run 'gc binary-tree' $O.out -n 15
 	run 'gc binary-tree-freelist' $O.out -n 15
 }
 
 fannkuch() {
 	runonly echo 'fannkuch 12'
-	run 'gcc -O2 fannkuch.c' a.out 12
+	run "gcc $gccm -O2 fannkuch.c" a.out 12
 	run 'gccgo -O2 fannkuch.go' a.out -n 12
 	run 'gccgo -O2 fannkuch-parallel.go' a.out -n 12
 	run 'gc fannkuch' $O.out -n 12
@@ -126,7 +134,7 @@ regexdna() {
 	runonly gcc -O2 fasta.c
 	runonly a.out 100000 > x
 	runonly echo 'regex-dna 100000'
-	run 'gcc -O2 regex-dna.c -lpcre' a.out <x
+	run "gcc $gccm -O2 regex-dna.c -lpcre" a.out <x
 	run 'gccgo -O2 regex-dna.go' a.out <x
 	run 'gccgo -O2 regex-dna-parallel.go' a.out <x
 	run 'gc regex-dna' $O.out <x
@@ -137,7 +145,7 @@ regexdna() {
 
 spectralnorm() {
 	runonly echo 'spectral-norm 5500'
-	run 'gcc -O2 spectral-norm.c -lm' a.out 5500
+	run "gcc $gccm -O2 spectral-norm.c -lm" a.out 5500
 	run 'gccgo -O2 spectral-norm.go' a.out -n 5500
 	run 'gc spectral-norm' $O.out -n 5500
 	run 'gc_B spectral-norm' $O.out -n 5500
@@ -147,7 +155,9 @@ knucleotide() {
 	runonly gcc -O2 fasta.c
 	runonly a.out 1000000 > x  # should be using 25000000
 	runonly echo 'k-nucleotide 1000000'
-	run 'gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0' a.out <x
+	if [ $mode = run ]; then
+		run "gcc -O2 k-nucleotide.c $(pkg-config glib-2.0 --cflags --libs)" a.out <x
+	fi
 	run 'gccgo -O2 k-nucleotide.go' a.out <x
 	run 'gccgo -O2 k-nucleotide-parallel.go' a.out <x
 	run 'gc k-nucleotide' $O.out <x
@@ -158,7 +168,7 @@ knucleotide() {
 
 mandelbrot() {
 	runonly echo 'mandelbrot 16000'
-	run 'gcc -O2 mandelbrot.c' a.out 16000
+	run "gcc $gccm -O2 mandelbrot.c" a.out 16000
 	run 'gccgo -O2 mandelbrot.go' a.out -n 16000
 	run 'gc mandelbrot' $O.out -n 16000
 	run 'gc_B mandelbrot' $O.out -n 16000
@@ -166,7 +176,7 @@ mandelbrot() {
 
 meteor() {
 	runonly echo 'meteor 2098'
-	run 'gcc -O2 meteor-contest.c' a.out 2098
+	run "gcc $gccm -O2 meteor-contest.c" a.out 2098
 	run 'gccgo -O2 meteor-contest.go' a.out -n 2098
 	run 'gc meteor-contest' $O.out -n 2098
 	run 'gc_B  meteor-contest' $O.out -n 2098
@@ -174,7 +184,7 @@ meteor() {
 
 pidigits() {
 	runonly echo 'pidigits 10000'
-	run 'gcc -O2 pidigits.c -lgmp' a.out 10000
+	run "gcc $gccm -O2 pidigits.c -lgmp" a.out 10000
 	run 'gccgo -O2 pidigits.go' a.out -n 10000
 	run 'gc pidigits' $O.out -n 10000
 	run 'gc_B  pidigits' $O.out -n 10000
@@ -182,14 +192,14 @@ pidigits() {
 
 threadring() {
 	runonly echo 'threadring 50000000'
-	run 'gcc -O2 threadring.c -lpthread' a.out 50000000
+	run "gcc $gccm -O2 threadring.c -lpthread" a.out 50000000
 	run 'gccgo -O2 threadring.go' a.out -n 50000000
 	run 'gc threadring' $O.out -n 50000000
 }
 
 chameneos() {
 	runonly echo 'chameneos 6000000'
-	run 'gcc -O2 chameneosredux.c -lpthread' a.out 6000000
+	run "gcc $gccm -O2 chameneosredux.c -lpthread" a.out 6000000
 	run 'gccgo -O2 chameneosredux.go' a.out 6000000
 	run 'gc chameneosredux' $O.out 6000000
 }
diff --git a/test/bigalg.go b/test/bigalg.go
index 55a15c3..60e8229 100644
--- a/test/bigalg.go
+++ b/test/bigalg.go
@@ -15,18 +15,21 @@ type T struct {
 	d byte
 }
 
-var a = []int{ 1, 2, 3 }
+var a = []int{1, 2, 3}
 var NIL []int
 
 func arraycmptest() {
 	if NIL != nil {
 		println("fail1:", NIL, "!= nil")
+		panic("bigalg")
 	}
 	if nil != NIL {
 		println("fail2: nil !=", NIL)
+		panic("bigalg")
 	}
 	if a == nil || nil == a {
 		println("fail3:", a, "== nil")
+		panic("bigalg")
 	}
 }
 
@@ -49,12 +52,14 @@ func maptest() {
 	t1 := mt[0]
 	if t1.a != t.a || t1.b != t.b || t1.c != t.c || t1.d != t.d {
 		println("fail: map val struct", t1.a, t1.b, t1.c, t1.d)
+		panic("bigalg")
 	}
 
 	ma[1] = a
 	a1 := ma[1]
 	if !SameArray(a, a1) {
 		println("fail: map val array", a, a1)
+		panic("bigalg")
 	}
 }
 
@@ -72,15 +77,18 @@ func chantest() {
 	t1 := <-ct
 	if t1.a != t.a || t1.b != t.b || t1.c != t.c || t1.d != t.d {
 		println("fail: map val struct", t1.a, t1.b, t1.c, t1.d)
+		panic("bigalg")
 	}
 
 	a1 := <-ca
 	if !SameArray(a, a1) {
 		println("fail: map val array", a, a1)
+		panic("bigalg")
 	}
 }
 
-type E struct { }
+type E struct{}
+
 var e E
 
 func interfacetest() {
@@ -90,6 +98,7 @@ func interfacetest() {
 	a1 := i.([]int)
 	if !SameArray(a, a1) {
 		println("interface <-> []int", a, a1)
+		panic("bigalg")
 	}
 	pa := new([]int)
 	*pa = a
@@ -97,12 +106,14 @@ func interfacetest() {
 	a1 = *i.(*[]int)
 	if !SameArray(a, a1) {
 		println("interface <-> *[]int", a, a1)
+		panic("bigalg")
 	}
 
 	i = t
 	t1 := i.(T)
 	if t1.a != t.a || t1.b != t.b || t1.c != t.c || t1.d != t.d {
 		println("interface <-> struct", t1.a, t1.b, t1.c, t1.d)
+		panic("bigalg")
 	}
 
 	i = e
diff --git a/test/blank.go b/test/blank.go
index 961ed15..7f7d9f6 100644
--- a/test/blank.go
+++ b/test/blank.go
@@ -8,6 +8,11 @@
 
 package main
 
+import (
+	"os"
+	"unsafe"
+)
+
 import _ "fmt"
 
 var call string
@@ -102,8 +107,19 @@ func main() {
 		panic(sum)
 	}
 
+	// exp/ssa/interp doesn't yet skip blank fields in struct
+	// equivalence.  It also cannot support unsafe.Pointer.
+	if os.Getenv("GOSSAINTERP") == "" {
+		type T1 struct{ x, y, z int }
+		t1 := *(*T)(unsafe.Pointer(&T1{1, 2, 3}))
+		t2 := *(*T)(unsafe.Pointer(&T1{4, 5, 6}))
+		if t1 != t2 {
+			panic("T{} != T{}")
+		}
+	}
+
 	h(a, b)
-	
+
 	m()
 }
 
@@ -113,7 +129,7 @@ type I interface {
 
 type TI struct{}
 
-func (TI) M(x int, y int) {
+func (_ TI) M(x int, y int) {
 	if x != y {
 		println("invalid M call:", x, y)
 		panic("bad M")
@@ -133,14 +149,13 @@ func fp1(x, y int) {
 	}
 }
 
-
 func m() {
 	var i I
-	
+
 	i = TI{}
 	i.M(1, 1)
 	i.M(2, 2)
-	
+
 	fp(1, 1)
 	fp(2, 2)
 }
@@ -162,4 +177,3 @@ func _() {
 func ff() {
 	var _ int = 1
 }
-
diff --git a/test/blank1.go b/test/blank1.go
index c6e038a..4edb2db 100644
--- a/test/blank1.go
+++ b/test/blank1.go
@@ -9,8 +9,13 @@
 
 package _	// ERROR "invalid package name _"
 
+var t struct {
+	_ int
+}
+
 func main() {
 	_()	// ERROR "cannot use _ as value"
 	x := _+1	// ERROR "cannot use _ as value"
 	_ = x
+	_ = t._ // ERROR "cannot refer to blank field"
 }
diff --git a/test/bom.go b/test/bom.go
new file mode 100644
index 0000000..37f73bc
--- /dev/null
+++ b/test/bom.go
@@ -0,0 +1,26 @@
+// runoutput
+
+// 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.
+
+// Test source file beginning with a byte order mark.
+
+package main
+
+import (
+	"fmt"
+	"strings"
+)
+
+func main() {
+	prog = strings.Replace(prog, "BOM", "\uFEFF", -1)
+	fmt.Print(prog)
+}
+
+var prog = `BOM
+package main
+
+func main() {
+}
+`
diff --git a/test/bombad.go b/test/bombad.go
new file mode 100644
index 0000000..b894d9b
--- /dev/null
+++ b/test/bombad.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// 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.
+
+// Here for reference, but hard to test automatically
+// because the BOM muddles the
+// processing done by ../run.
+
+package main
+
+func main() {
+	// There's a bom here.	// ERROR "BOM"
+	// And here.	// ERROR "BOM"
+	/* And here.*/	// ERROR "BOM"
+	println("hi there") // and here	// ERROR "BOM"
+}
diff --git a/test/bounds.go b/test/bounds.go
new file mode 100644
index 0000000..50f7ad7
--- /dev/null
+++ b/test/bounds.go
@@ -0,0 +1,270 @@
+// errorcheck -0 -m -l
+
+// 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, using compiler diagnostic flags, that bounds check elimination
+// is eliminating the correct checks.
+
+package foo
+
+var (
+	s []int
+
+	a1 [1]int
+	a1k [1000]int
+	a100k [100000]int
+
+	p1 *[1]int
+	p1k *[1000]int
+	p100k *[100000]int
+
+	i int
+	ui uint
+	i8 int8
+	ui8 uint8
+	i16 int16
+	ui16 uint16
+	i32 int32
+	ui32 uint32
+	i64 int64
+	ui64 uint64
+)
+
+func main() {
+	// Most things need checks.
+	use(s[i])
+	use(a1[i])
+	use(a1k[i])
+	use(a100k[i])
+	use(p1[i])
+	use(p1k[i])
+	use(p100k[i])
+
+	use(s[ui])
+	use(a1[ui])
+	use(a1k[ui])
+	use(a100k[ui])
+	use(p1[ui])
+	use(p1k[ui])
+	use(p100k[ui])
+
+	use(s[i8])
+	use(a1[i8])
+	use(a1k[i8])
+	use(a100k[i8])
+	use(p1[i8])
+	use(p1k[i8])
+	use(p100k[i8])
+
+	// Unsigned 8-bit numbers don't need checks for len >= 2⁸.
+	use(s[ui8])
+	use(a1[ui8])
+	use(a1k[ui8])  // ERROR "index bounds check elided"
+	use(a100k[ui8])  // ERROR "index bounds check elided"
+	use(p1[ui8])
+	use(p1k[ui8])  // ERROR "index bounds check elided"
+	use(p100k[ui8])  // ERROR "index bounds check elided"
+
+	use(s[i16])
+	use(a1[i16])
+	use(a1k[i16])
+	use(a100k[i16])
+	use(p1[i16])
+	use(p1k[i16])
+	use(p100k[i16])
+
+	// Unsigned 16-bit numbers don't need checks for len >= 2¹⁶.
+	use(s[ui16])
+	use(a1[ui16])
+	use(a1k[ui16])
+	use(a100k[ui16])  // ERROR "index bounds check elided"
+	use(p1[ui16])
+	use(p1k[ui16])
+	use(p100k[ui16])  // ERROR "index bounds check elided"
+
+	use(s[i32])
+	use(a1[i32])
+	use(a1k[i32])
+	use(a100k[i32])
+	use(p1[i32])
+	use(p1k[i32])
+	use(p100k[i32])
+
+	use(s[ui32])
+	use(a1[ui32])
+	use(a1k[ui32])
+	use(a100k[ui32])
+	use(p1[ui32])
+	use(p1k[ui32])
+	use(p100k[ui32])
+
+	use(s[i64])
+	use(a1[i64])
+	use(a1k[i64])
+	use(a100k[i64])
+	use(p1[i64])
+	use(p1k[i64])
+	use(p100k[i64])
+
+	use(s[ui64])
+	use(a1[ui64])
+	use(a1k[ui64])
+	use(a100k[ui64])
+	use(p1[ui64])
+	use(p1k[ui64])
+	use(p100k[ui64])
+
+	// Mod truncates the maximum value to one less than the argument,
+	// but signed mod can be negative, so only unsigned mod counts.
+	use(s[i%999])
+	use(a1[i%999])
+	use(a1k[i%999])
+	use(a100k[i%999])
+	use(p1[i%999])
+	use(p1k[i%999])
+	use(p100k[i%999])
+
+	use(s[ui%999])
+	use(a1[ui%999])
+	use(a1k[ui%999])  // ERROR "index bounds check elided"
+	use(a100k[ui%999])  // ERROR "index bounds check elided"
+	use(p1[ui%999])
+	use(p1k[ui%999])  // ERROR "index bounds check elided"
+	use(p100k[ui%999])  // ERROR "index bounds check elided"
+
+	use(s[i%1000])
+	use(a1[i%1000])
+	use(a1k[i%1000])
+	use(a100k[i%1000])
+	use(p1[i%1000])
+	use(p1k[i%1000])
+	use(p100k[i%1000])
+
+	use(s[ui%1000])
+	use(a1[ui%1000])
+	use(a1k[ui%1000])  // ERROR "index bounds check elided"
+	use(a100k[ui%1000])  // ERROR "index bounds check elided"
+	use(p1[ui%1000])
+	use(p1k[ui%1000])  // ERROR "index bounds check elided"
+	use(p100k[ui%1000])  // ERROR "index bounds check elided"
+
+	use(s[i%1001])
+	use(a1[i%1001])
+	use(a1k[i%1001])
+	use(a100k[i%1001])
+	use(p1[i%1001])
+	use(p1k[i%1001])
+	use(p100k[i%1001])
+
+	use(s[ui%1001])
+	use(a1[ui%1001])
+	use(a1k[ui%1001])
+	use(a100k[ui%1001])  // ERROR "index bounds check elided"
+	use(p1[ui%1001])
+	use(p1k[ui%1001])
+	use(p100k[ui%1001])  // ERROR "index bounds check elided"
+
+	// Bitwise and truncates the maximum value to the mask value.
+	// The result (for a positive mask) cannot be negative, so elision
+	// applies to both signed and unsigned indexes.
+	use(s[i&999])
+	use(a1[i&999])
+	use(a1k[i&999])  // ERROR "index bounds check elided"
+	use(a100k[i&999])  // ERROR "index bounds check elided"
+	use(p1[i&999])
+	use(p1k[i&999])  // ERROR "index bounds check elided"
+	use(p100k[i&999])  // ERROR "index bounds check elided"
+
+	use(s[ui&999])
+	use(a1[ui&999])
+	use(a1k[ui&999])  // ERROR "index bounds check elided"
+	use(a100k[ui&999])  // ERROR "index bounds check elided"
+	use(p1[ui&999])
+	use(p1k[ui&999])  // ERROR "index bounds check elided"
+	use(p100k[ui&999])  // ERROR "index bounds check elided"
+
+	use(s[i&1000])
+	use(a1[i&1000])
+	use(a1k[i&1000])
+	use(a100k[i&1000])  // ERROR "index bounds check elided"
+	use(p1[i&1000])
+	use(p1k[i&1000])
+	use(p100k[i&1000])  // ERROR "index bounds check elided"
+
+	use(s[ui&1000])
+	use(a1[ui&1000])
+	use(a1k[ui&1000])
+	use(a100k[ui&1000])  // ERROR "index bounds check elided"
+	use(p1[ui&1000])
+	use(p1k[ui&1000])
+	use(p100k[ui&1000])  // ERROR "index bounds check elided"
+
+	// Right shift cuts the effective number of bits in the index,
+	// but only for unsigned (signed stays negative).
+	use(s[i32>>22])
+	use(a1[i32>>22])
+	use(a1k[i32>>22])
+	use(a100k[i32>>22])
+	use(p1[i32>>22])
+	use(p1k[i32>>22])
+	use(p100k[i32>>22])
+
+	use(s[ui32>>22])
+	use(a1[ui32>>22])
+	use(a1k[ui32>>22])
+	use(a100k[ui32>>22])  // ERROR "index bounds check elided"
+	use(p1[ui32>>22])
+	use(p1k[ui32>>22])
+	use(p100k[ui32>>22])  // ERROR "index bounds check elided"
+
+	use(s[i32>>23])
+	use(a1[i32>>23])
+	use(a1k[i32>>23])
+	use(a100k[i32>>23])
+	use(p1[i32>>23])
+	use(p1k[i32>>23])
+	use(p100k[i32>>23])
+
+	use(s[ui32>>23])
+	use(a1[ui32>>23])
+	use(a1k[ui32>>23])  // ERROR "index bounds check elided"
+	use(a100k[ui32>>23])  // ERROR "index bounds check elided"
+	use(p1[ui32>>23])
+	use(p1k[ui32>>23])  // ERROR "index bounds check elided"
+	use(p100k[ui32>>23])  // ERROR "index bounds check elided"
+
+	// Division cuts the range like right shift does.
+	use(s[i/1e6])
+	use(a1[i/1e6])
+	use(a1k[i/1e6])
+	use(a100k[i/1e6])
+	use(p1[i/1e6])
+	use(p1k[i/1e6])
+	use(p100k[i/1e6])
+
+	use(s[ui/1e6])
+	use(a1[ui/1e6])
+	use(a1k[ui/1e6])
+	use(p1[ui/1e6])
+	use(p1k[ui/1e6])
+
+	use(s[i/1e7])
+	use(a1[i/1e7])
+	use(a1k[i/1e7])
+	use(a100k[i/1e7])
+	use(p1[i/1e7])
+	use(p1k[i/1e7])
+	use(p100k[i/1e7])
+
+	use(s[ui/1e7])
+	use(a1[ui/1e7])
+	use(p1[ui/1e7])
+}
+
+var sum int 
+
+func use(x int) {
+	sum += x
+}
diff --git a/test/bugs/bug395.go b/test/bugs/bug395.go
index adf7449..4632dcd 100644
--- a/test/bugs/bug395.go
+++ b/test/bugs/bug395.go
@@ -1,6 +1,9 @@
 // echo bug395 is broken  # takes 90+ seconds to break
 // # $G $D/$F.go || echo bug395
 
+// 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.
+
 // 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/test/chan/select5.go b/test/chan/select5.go
index 13cde1a..f72cfe4 100644
--- a/test/chan/select5.go
+++ b/test/chan/select5.go
@@ -1,6 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
-// $G tmp.go && $L tmp.$A && ./$A.out || echo BUG: select5
-// rm -f tmp.go
+// runoutput
 
 // Copyright 2011 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/closure.go b/test/closure.go
index ae38900..c4a3124 100644
--- a/test/closure.go
+++ b/test/closure.go
@@ -81,6 +81,7 @@ func h() {
 func newfunc() func(int) int { return func(x int) int { return x } }
 
 func main() {
+	runtime.GOMAXPROCS(1)
 	var fail bool
 
 	go f()
diff --git a/test/cmp.go b/test/cmp.go
index a56ca6e..5be6456 100644
--- a/test/cmp.go
+++ b/test/cmp.go
@@ -8,9 +8,13 @@
 
 package main
 
-import "unsafe"
+import (
+	"os"
+	"unsafe"
+)
 
 var global bool
+
 func use(b bool) { global = b }
 
 func stringptr(s string) uintptr { return *(*uintptr)(unsafe.Pointer(&s)) }
@@ -38,8 +42,12 @@ func main() {
 	var c string = "hello"
 	var d string = "hel" // try to get different pointer
 	d = d + "lo"
-	if stringptr(c) == stringptr(d) {
-		panic("compiler too smart -- got same string")
+
+	// exp/ssa/interp can't handle unsafe.Pointer.
+	if os.Getenv("GOSSAINTERP") != "" {
+		if stringptr(c) == stringptr(d) {
+			panic("compiler too smart -- got same string")
+		}
 	}
 
 	var e = make(chan int)
@@ -283,7 +291,7 @@ func main() {
 		isfalse(ix != z)
 		isfalse(iz != x)
 	}
-	
+
 	// structs with _ fields
 	{
 		var x = struct {
@@ -296,7 +304,7 @@ func main() {
 			x: 1, y: 2, z: 3,
 		}
 		var ix interface{} = x
-		
+
 		istrue(x == x)
 		istrue(x == ix)
 		istrue(ix == x)
diff --git a/test/cmplxdivide.go b/test/cmplxdivide.go
index 92a9835..40c8448 100644
--- a/test/cmplxdivide.go
+++ b/test/cmplxdivide.go
@@ -45,4 +45,7 @@ func main() {
 			fmt.Printf("%v/%v: expected %v error; got %v\n", t.f, t.g, t.out, x)
 		}
 	}
+	if bad {
+		panic("cmplxdivide failed.")
+	}
 }
diff --git a/test/const.go b/test/const.go
index 80fbfaf..d583659 100644
--- a/test/const.go
+++ b/test/const.go
@@ -8,27 +8,29 @@
 
 package main
 
+import "os"
+
 const (
-	c0 = 0
-	cm1 = -1
-	chuge = 1 << 100
+	c0      = 0
+	cm1     = -1
+	chuge   = 1 << 100
 	chuge_1 = chuge - 1
-	c1 = chuge >> 100
-	c3div2 = 3/2
-	c1e3 = 1e3
+	c1      = chuge >> 100
+	c3div2  = 3 / 2
+	c1e3    = 1e3
 
-	ctrue = true
+	ctrue  = true
 	cfalse = !ctrue
 )
 
 const (
-	f0 = 0.0
-	fm1 = -1.
-	fhuge float64 = 1 << 100
+	f0              = 0.0
+	fm1             = -1.
+	fhuge   float64 = 1 << 100
 	fhuge_1 float64 = chuge - 1
-	f1 float64 = chuge >> 100
-	f3div2 = 3./2.
-	f1e3 float64 = 1e3
+	f1      float64 = chuge >> 100
+	f3div2          = 3. / 2.
+	f1e3    float64 = 1e3
 )
 
 func assert(t bool, s string) {
@@ -41,8 +43,8 @@ func ints() {
 	assert(c0 == 0, "c0")
 	assert(c1 == 1, "c1")
 	assert(chuge > chuge_1, "chuge")
-	assert(chuge_1 + 1 == chuge, "chuge 1")
-	assert(chuge + cm1 +1  == chuge, "cm1")
+	assert(chuge_1+1 == chuge, "chuge 1")
+	assert(chuge+cm1+1 == chuge, "cm1")
 	assert(c3div2 == 1, "3/2")
 	assert(c1e3 == 1000, "c1e3 int")
 	assert(c1e3 == 1e3, "c1e3 float")
@@ -81,9 +83,12 @@ func ints() {
 func floats() {
 	assert(f0 == c0, "f0")
 	assert(f1 == c1, "f1")
-	assert(fhuge == fhuge_1, "fhuge")	// float64 can't distinguish fhuge, fhuge_1.
-	assert(fhuge_1 + 1 == fhuge, "fhuge 1")
-	assert(fhuge + fm1 +1  == fhuge, "fm1")
+	// TODO(gri): exp/ssa/interp constant folding is incorrect.
+	if os.Getenv("GOSSAINTERP") == "" {
+		assert(fhuge == fhuge_1, "fhuge") // float64 can't distinguish fhuge, fhuge_1.
+	}
+	assert(fhuge_1+1 == fhuge, "fhuge 1")
+	assert(fhuge+fm1+1 == fhuge, "fm1")
 	assert(f3div2 == 1.5, "3./2.")
 	assert(f1e3 == 1000, "f1e3 int")
 	assert(f1e3 == 1.e3, "f1e3 float")
diff --git a/test/const1.go b/test/const1.go
index bc399c0..a170ce9 100644
--- a/test/const1.go
+++ b/test/const1.go
@@ -9,6 +9,8 @@
 
 package main
 
+import "unsafe"
+
 type I interface{}
 
 const (
@@ -66,7 +68,7 @@ var (
 	c3 float64 = float64(Big) * Big // ERROR "overflow"
 	c4         = Big * Big          // ERROR "overflow"
 	c5         = Big / 0            // ERROR "division by zero"
-	c6         = 1000 % 1e3         // ERROR "floating-point % operation"
+	c6         = 1000 % 1e3         // ERROR "floating-point % operation|expected integer type"
 )
 
 func f(int)
@@ -86,3 +88,7 @@ func main() {
 }
 
 const ptr = nil // ERROR "const.*nil"
+const _ = string([]byte(nil)) // ERROR "is not a constant"
+const _ = uintptr(unsafe.Pointer((*int)(nil))) // ERROR "is not a constant"
+const _ = unsafe.Pointer((*int)(nil)) // ERROR "cannot be nil"
+const _ = (*int)(nil) // ERROR "cannot be nil"
diff --git a/test/const2.go b/test/const2.go
index 97d3d4c..048d0cb 100644
--- a/test/const2.go
+++ b/test/const2.go
@@ -16,6 +16,6 @@ const (
 
 const LargeA = 1000000000000000000
 const LargeB = LargeA * LargeA * LargeA
-const LargeC = LargeB * LargeB * LargeB // ERROR "constant multiplication overflow"
+const LargeC = LargeB * LargeB * LargeB // GC_ERROR "constant multiplication overflow"
 
-const AlsoLargeA = LargeA << 400 << 400 >> 400 >> 400 // ERROR "constant shift overflow"
+const AlsoLargeA = LargeA << 400 << 400 >> 400 >> 400 // GC_ERROR "constant shift overflow"
diff --git a/test/const4.go b/test/const4.go
index 677fcef..2fb2d06 100644
--- a/test/const4.go
+++ b/test/const4.go
@@ -9,7 +9,7 @@
 package main
 
 var b struct {
-	a[10]int
+	a [10]int
 }
 
 var m map[string][20]int
@@ -61,17 +61,22 @@ var c1 = func() chan *[70]int {
 func main() {
 	if n1 != 10 || n2 != 20 || n3 != 30 || n4 != 40 || n5 != 50 || n6 != 60 || n7 != 70 {
 		println("BUG:", n1, n2, n3, n4, n5, n6, n7)
+		panic("fail")
 	}
 	if !calledF {
 		println("BUG: did not call f")
+		panic("fail")
 	}
 	if <-c == nil {
 		println("BUG: did not receive from c")
+		panic("fail")
 	}
 	if !calledG {
 		println("BUG: did not call g")
+		panic("fail")
 	}
 	if <-c1 == nil {
 		println("BUG: did not receive from c1")
+		panic("fail")
 	}
 }
diff --git a/test/const5.go b/test/const5.go
index 8e0385e..87fe33a 100644
--- a/test/const5.go
+++ b/test/const5.go
@@ -24,10 +24,10 @@ const (
 	n2 = len(m[""])
 	n3 = len(s[10])
 
-	n4 = len(f())  // ERROR "must be constant"
-	n5 = len(<-c) // ERROR "must be constant"
+	n4 = len(f())  // ERROR "is not a constant|is not constant"
+	n5 = len(<-c) // ERROR "is not a constant|is not constant"
 
-	n6 = cap(f())  // ERROR "must be constant"
-	n7 = cap(<-c) // ERROR "must be constant"
+	n6 = cap(f())  // ERROR "is not a constant|is not constant"
+	n7 = cap(<-c) // ERROR "is not a constant|is not constant"
 )
 
diff --git a/test/const6.go b/test/const6.go
new file mode 100644
index 0000000..c04435d
--- /dev/null
+++ b/test/const6.go
@@ -0,0 +1,30 @@
+// errorcheck
+
+// 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.
+
+// Ideal vs non-ideal bool. See issue 3915, 3923.
+
+package p
+
+type mybool bool
+type mybool1 bool
+
+var (
+	x, y int = 1, 2
+	c1 bool = x < y
+	c2 mybool = x < y
+	c3 mybool = c2 == (x < y)
+	c4 mybool = c2 == (1 < 2)
+	c5 mybool = 1 < 2
+	c6 mybool1 = x < y
+	c7 = c1 == c2 // ERROR "mismatched types"
+	c8 = c2 == c6 // ERROR "mismatched types"
+	c9 = c1 == c6 // ERROR "mismatched types"
+	_ = c2 && (x < y)
+	_ = c2 && (1 < 2)
+	_ = c1 && c2 // ERROR "mismatched types"
+	_ = c2 && c6 // ERROR "mismatched types"
+	_ = c1 && c6 // ERROR "mismatched types"
+)
diff --git a/test/convT2X.go b/test/convT2X.go
new file mode 100644
index 0000000..7e27f06
--- /dev/null
+++ b/test/convT2X.go
@@ -0,0 +1,195 @@
+// run
+
+// 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 conversion from non-interface types to the empty interface.
+
+package main
+
+type J interface {
+	Method()
+}
+
+type (
+	U16  uint16
+	U32  uint32
+	U64  uint64
+	U128 [2]uint64
+	F32  float32
+	F64  float64
+	C128 complex128
+	S    string
+	B    []byte
+	M    map[int]int
+	C    chan int
+	Z    struct{}
+)
+
+func (U16) Method()  {}
+func (U32) Method()  {}
+func (U64) Method()  {}
+func (U128) Method() {}
+func (F32) Method()  {}
+func (F64) Method()  {}
+func (C128) Method() {}
+func (S) Method()    {}
+func (B) Method()    {}
+func (M) Method()    {}
+func (C) Method()    {}
+func (Z) Method()    {}
+
+var (
+	u16  = U16(1)
+	u32  = U32(2)
+	u64  = U64(3)
+	u128 = U128{4, 5}
+	f32  = F32(6)
+	f64  = F64(7)
+	c128 = C128(8 + 9i)
+	s    = S("10")
+	b    = B("11")
+	m    = M{12: 13}
+	c    = make(C, 14)
+	z    = Z{}
+	p    = &z
+	pp   = &p
+)
+
+var (
+	iu16  interface{} = u16
+	iu32  interface{} = u32
+	iu64  interface{} = u64
+	iu128 interface{} = u128
+	if32  interface{} = f32
+	if64  interface{} = f64
+	ic128 interface{} = c128
+	is    interface{} = s
+	ib    interface{} = b
+	im    interface{} = m
+	ic    interface{} = c
+	iz    interface{} = z
+	ip    interface{} = p
+	ipp   interface{} = pp
+
+	ju16  J = u16
+	ju32  J = u32
+	ju64  J = u64
+	ju128 J = u128
+	jf32  J = f32
+	jf64  J = f64
+	jc128 J = c128
+	js    J = s
+	jb    J = b
+	jm    J = m
+	jc    J = c
+	jz J = z
+	jp J = p // The method set for *T contains the methods for T.
+	// pp does not implement error.
+)
+
+func second(a ...interface{}) interface{} {
+	return a[1]
+}
+
+func main() {
+	// Test equality.
+	if u16 != iu16 {
+		panic("u16 != iu16")
+	}
+	if u16 != ju16 {
+		panic("u16 != ju16")
+	}
+	if u32 != iu32 {
+		panic("u32 != iu32")
+	}
+	if u32 != ju32 {
+		panic("u32 != ju32")
+	}
+	if u64 != iu64 {
+		panic("u64 != iu64")
+	}
+	if u64 != ju64 {
+		panic("u64 != ju64")
+	}
+	if u128 != iu128 {
+		panic("u128 != iu128")
+	}
+	if u128 != ju128 {
+		panic("u128 != ju128")
+	}
+	if f32 != if32 {
+		panic("f32 != if32")
+	}
+	if f32 != jf32 {
+		panic("f32 != jf32")
+	}
+	if f64 != if64 {
+		panic("f64 != if64")
+	}
+	if f64 != jf64 {
+		panic("f64 != jf64")
+	}
+	if c128 != ic128 {
+		panic("c128 != ic128")
+	}
+	if c128 != jc128 {
+		panic("c128 != jc128")
+	}
+	if s != is {
+		panic("s != is")
+	}
+	if s != js {
+		panic("s != js")
+	}
+	if c != ic {
+		panic("c != ic")
+	}
+	if c != jc {
+		panic("c != jc")
+	}
+	// There are no tests for b and m, as slices and maps are not comparable by ==.
+	if z != iz {
+		panic("z != iz")
+	}
+	if z != jz {
+		panic("z != jz")
+	}
+	if p != ip {
+		panic("p != ip")
+	}
+	if p != jp {
+		panic("p != jp")
+	}
+	if pp != ipp {
+		panic("pp != ipp")
+	}
+	// pp does not implement J.
+
+	// Test that non-interface types can be used as ...interface{} arguments.
+	if got := second(z, p, pp, u16, u32, u64, u128, f32, f64, c128, s, b, m, c); got != ip {
+		println("second: got", got, "want", ip)
+		panic("fail")
+	}
+
+	// Test that non-interface types can be sent on a chan interface{}.
+	const n = 100
+	uc := make(chan interface{})
+	go func() {
+		for i := 0; i < n; i++ {
+			select {
+			case uc <- nil:
+			case uc <- u32:
+			case uc <- u64:
+			case uc <- u128:
+			}
+		}
+	}()
+	for i := 0; i < n; i++ {
+		if got := <-uc; got != nil && got != u32 && got != u64 && got != u128 {
+			println("recv: i", i, "got", got)
+			panic("fail")
+		}
+	}
+}
diff --git a/test/copy.go b/test/copy.go
index 65ffb6f..e6108d9 100644
--- a/test/copy.go
+++ b/test/copy.go
@@ -132,6 +132,7 @@ func verify8(length, in, out, m int) {
 	n := ncopied(length, in, out)
 	if m != n {
 		fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+		os.Exit(1)
 		return
 	}
 	// before
@@ -172,6 +173,7 @@ func verifyS(length, in, out, m int) {
 	n := ncopied(length, in, out)
 	if m != n {
 		fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+		os.Exit(1)
 		return
 	}
 	// before
@@ -212,6 +214,7 @@ func verify16(length, in, out, m int) {
 	n := ncopied(length, in, out)
 	if m != n {
 		fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+		os.Exit(1)
 		return
 	}
 	// before
@@ -252,6 +255,7 @@ func verify32(length, in, out, m int) {
 	n := ncopied(length, in, out)
 	if m != n {
 		fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+		os.Exit(1)
 		return
 	}
 	// before
@@ -292,6 +296,7 @@ func verify64(length, in, out, m int) {
 	n := ncopied(length, in, out)
 	if m != n {
 		fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+		os.Exit(1)
 		return
 	}
 	// before
diff --git a/test/crlf.go b/test/crlf.go
index 292b63b..2d56889 100644
--- a/test/crlf.go
+++ b/test/crlf.go
@@ -1,6 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
-// $G tmp.go && $L tmp.$A && ./$A.out
-// rm -f tmp.go
+// runoutput
 
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/ddd1.go b/test/ddd1.go
index 1e07009..07981af 100644
--- a/test/ddd1.go
+++ b/test/ddd1.go
@@ -22,6 +22,16 @@ var (
 	_ = sum([]int{1}) // ERROR "\[\]int literal.*as type int|incompatible"
 )
 
+func sum3(int, int, int) int { return 0 }
+func tuple() (int, int, int) { return 1, 2, 3 }
+
+var (
+	_ = sum(tuple())
+	_ = sum(tuple()...) // ERROR "multiple-value|[.][.][.]"
+	_ = sum3(tuple())
+	_ = sum3(tuple()...) // ERROR "multiple-value|[.][.][.]" "not enough"
+)
+
 type T []T
 
 func funny(args ...T) int { return 0 }
diff --git a/test/ddd2.dir/ddd2.go b/test/ddd2.dir/ddd2.go
new file mode 100644
index 0000000..c9a2675
--- /dev/null
+++ b/test/ddd2.dir/ddd2.go
@@ -0,0 +1,16 @@
+// 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.
+
+// This file is compiled and then imported by ddd3.go.
+
+package ddd
+
+func Sum(args ...int) int {
+	s := 0
+	for _, v := range args {
+		s += v
+	}
+	return s
+}
+
diff --git a/test/ddd2.dir/ddd3.go b/test/ddd2.dir/ddd3.go
new file mode 100644
index 0000000..5486fe8
--- /dev/null
+++ b/test/ddd2.dir/ddd3.go
@@ -0,0 +1,28 @@
+// 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 that variadic functions work across package boundaries.
+
+package main
+
+import "./ddd2"
+
+func main() {
+	if x := ddd.Sum(1, 2, 3); x != 6 {
+		println("ddd.Sum 6", x)
+		panic("fail")
+	}
+	if x := ddd.Sum(); x != 0 {
+		println("ddd.Sum 0", x)
+		panic("fail")
+	}
+	if x := ddd.Sum(10); x != 10 {
+		println("ddd.Sum 10", x)
+		panic("fail")
+	}
+	if x := ddd.Sum(1, 8); x != 9 {
+		println("ddd.Sum 9", x)
+		panic("fail")
+	}
+}
diff --git a/test/ddd2.go b/test/ddd2.go
index a141a39..0d9f634 100644
--- a/test/ddd2.go
+++ b/test/ddd2.go
@@ -1,18 +1,9 @@
-// skip
+// rundir
 
 // 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.
 
-// This file is compiled and then imported by ddd3.go.
-
-package ddd
-
-func Sum(args ...int) int {
-	s := 0
-	for _, v := range args {
-		s += v
-	}
-	return s
-}
+// Test that variadic functions work across package boundaries.
 
+package ignored
diff --git a/test/ddd3.go b/test/ddd3.go
deleted file mode 100644
index 82fce31..0000000
--- a/test/ddd3.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// $G $D/ddd2.go && $G $D/$F.go && $L $F.$A && ./$A.out
-
-// 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 that variadic functions work across package boundaries.
-
-package main
-
-import "./ddd2"
-
-func main() {
-	if x := ddd.Sum(1, 2, 3); x != 6 {
-		println("ddd.Sum 6", x)
-		panic("fail")
-	}
-	if x := ddd.Sum(); x != 0 {
-		println("ddd.Sum 0", x)
-		panic("fail")
-	}
-	if x := ddd.Sum(10); x != 10 {
-		println("ddd.Sum 10", x)
-		panic("fail")
-	}
-	if x := ddd.Sum(1, 8); x != 9 {
-		println("ddd.Sum 9", x)
-		panic("fail")
-	}
-}
diff --git a/test/decl.go b/test/decl.go
index 6f84245..e2f126a 100644
--- a/test/decl.go
+++ b/test/decl.go
@@ -33,8 +33,9 @@ func main() {
 		m, h, s := f3()
 		_, _, _, _, _, _, _, _, _ = i, f, s, j, k, m, g, s, h
 	}
-	if x() != "3" {
-		println("x() failed")
+	if y := x(); y != "3" {
+		println("x() failed", y)
+		panic("fail")
 	}
 	_, _, _, _, _, _, _, _, _ = i, f, s, j, k, m, g, s, h
 }
diff --git a/test/declbad.go b/test/declbad.go
index 32d68e7..728eceb 100644
--- a/test/declbad.go
+++ b/test/declbad.go
@@ -39,6 +39,14 @@ func main() {
 		_, _, _ = i, f, s
 	}
 	{
+		// multiline no new variables
+		i := f1
+		i := func() int { // ERROR "redeclared|no new|incompatible"
+			return 0
+		}
+		_ = i
+	}
+	{
 		// single redeclaration
 		i, f, s := f3()
 		i := 1 // ERROR "redeclared|no new|incompatible"
diff --git a/test/defer.go b/test/defer.go
index 2f67d35..6731ab7 100644
--- a/test/defer.go
+++ b/test/defer.go
@@ -25,6 +25,7 @@ func test1() {
 	test1helper()
 	if result != "9876543210" {
 		fmt.Printf("test1: bad defer result (should be 9876543210): %q\n", result)
+		panic("defer")
 	}
 }
 
@@ -41,6 +42,7 @@ func test2() {
 	test2helper()
 	if result != "9876543210" {
 		fmt.Printf("test2: bad defer result (should be 9876543210): %q\n", result)
+		panic("defer")
 	}
 }
 
diff --git a/test/divide.go b/test/divide.go
index c91a33e..b20f106 100644
--- a/test/divide.go
+++ b/test/divide.go
@@ -13,36 +13,44 @@ import "fmt"
 func f8(x, y, q, r int8) {
 	if t := x / y; t != q {
 		fmt.Printf("%d/%d = %d, want %d\n", x, y, t, q)
+		panic("divide")
 	}
 	if t := x % y; t != r {
 		fmt.Printf("%d%%%d = %d, want %d\n", x, y, t, r)
+		panic("divide")
 	}
 }
 
 func f16(x, y, q, r int16) {
 	if t := x / y; t != q {
 		fmt.Printf("%d/%d = %d, want %d\n", x, y, t, q)
+		panic("divide")
 	}
 	if t := x % y; t != r {
 		fmt.Printf("%d%%%d = %d, want %d\n", x, y, t, r)
+		panic("divide")
 	}
 }
 
 func f32(x, y, q, r int32) {
 	if t := x / y; t != q {
 		fmt.Printf("%d/%d = %d, want %d\n", x, y, t, q)
+		panic("divide")
 	}
 	if t := x % y; t != r {
 		fmt.Printf("%d%%%d = %d, want %d\n", x, y, t, r)
+		panic("divide")
 	}
 }
 
 func f64(x, y, q, r int64) {
 	if t := x / y; t != q {
 		fmt.Printf("%d/%d = %d, want %d\n", x, y, t, q)
+		panic("divide")
 	}
 	if t := x % y; t != r {
 		fmt.Printf("%d%%%d = %d, want %d\n", x, y, t, r)
+		panic("divide")
 	}
 }
 
diff --git a/test/dwarf/dwarf.dir/main.go b/test/dwarf/dwarf.dir/main.go
new file mode 100644
index 0000000..175a09c
--- /dev/null
+++ b/test/dwarf/dwarf.dir/main.go
@@ -0,0 +1,32 @@
+// $G $D/$F.go $D/z*.go && $L $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.
+
+// 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 main
+func main() {
+F1()
+F2()
+F3()
+F4()
+F5()
+F6()
+F7()
+F8()
+F9()
+F10()
+F11()
+F12()
+F13()
+F14()
+F15()
+F16()
+F17()
+F18()
+F19()
+F20()
+}
diff --git a/test/dwarf/z1.go b/test/dwarf/dwarf.dir/z1.go
similarity index 100%
rename from test/dwarf/z1.go
rename to test/dwarf/dwarf.dir/z1.go
diff --git a/test/dwarf/z10.go b/test/dwarf/dwarf.dir/z10.go
similarity index 100%
rename from test/dwarf/z10.go
rename to test/dwarf/dwarf.dir/z10.go
diff --git a/test/dwarf/z11.go b/test/dwarf/dwarf.dir/z11.go
similarity index 100%
rename from test/dwarf/z11.go
rename to test/dwarf/dwarf.dir/z11.go
diff --git a/test/dwarf/z12.go b/test/dwarf/dwarf.dir/z12.go
similarity index 100%
rename from test/dwarf/z12.go
rename to test/dwarf/dwarf.dir/z12.go
diff --git a/test/dwarf/z13.go b/test/dwarf/dwarf.dir/z13.go
similarity index 100%
rename from test/dwarf/z13.go
rename to test/dwarf/dwarf.dir/z13.go
diff --git a/test/dwarf/z14.go b/test/dwarf/dwarf.dir/z14.go
similarity index 100%
rename from test/dwarf/z14.go
rename to test/dwarf/dwarf.dir/z14.go
diff --git a/test/dwarf/z15.go b/test/dwarf/dwarf.dir/z15.go
similarity index 100%
rename from test/dwarf/z15.go
rename to test/dwarf/dwarf.dir/z15.go
diff --git a/test/dwarf/z16.go b/test/dwarf/dwarf.dir/z16.go
similarity index 100%
rename from test/dwarf/z16.go
rename to test/dwarf/dwarf.dir/z16.go
diff --git a/test/dwarf/z17.go b/test/dwarf/dwarf.dir/z17.go
similarity index 100%
rename from test/dwarf/z17.go
rename to test/dwarf/dwarf.dir/z17.go
diff --git a/test/dwarf/z18.go b/test/dwarf/dwarf.dir/z18.go
similarity index 100%
rename from test/dwarf/z18.go
rename to test/dwarf/dwarf.dir/z18.go
diff --git a/test/dwarf/z19.go b/test/dwarf/dwarf.dir/z19.go
similarity index 100%
rename from test/dwarf/z19.go
rename to test/dwarf/dwarf.dir/z19.go
diff --git a/test/dwarf/z2.go b/test/dwarf/dwarf.dir/z2.go
similarity index 100%
rename from test/dwarf/z2.go
rename to test/dwarf/dwarf.dir/z2.go
diff --git a/test/dwarf/z20.go b/test/dwarf/dwarf.dir/z20.go
similarity index 100%
rename from test/dwarf/z20.go
rename to test/dwarf/dwarf.dir/z20.go
diff --git a/test/dwarf/z3.go b/test/dwarf/dwarf.dir/z3.go
similarity index 100%
rename from test/dwarf/z3.go
rename to test/dwarf/dwarf.dir/z3.go
diff --git a/test/dwarf/z4.go b/test/dwarf/dwarf.dir/z4.go
similarity index 100%
rename from test/dwarf/z4.go
rename to test/dwarf/dwarf.dir/z4.go
diff --git a/test/dwarf/z5.go b/test/dwarf/dwarf.dir/z5.go
similarity index 100%
rename from test/dwarf/z5.go
rename to test/dwarf/dwarf.dir/z5.go
diff --git a/test/dwarf/z6.go b/test/dwarf/dwarf.dir/z6.go
similarity index 100%
rename from test/dwarf/z6.go
rename to test/dwarf/dwarf.dir/z6.go
diff --git a/test/dwarf/z7.go b/test/dwarf/dwarf.dir/z7.go
similarity index 100%
rename from test/dwarf/z7.go
rename to test/dwarf/dwarf.dir/z7.go
diff --git a/test/dwarf/z8.go b/test/dwarf/dwarf.dir/z8.go
similarity index 100%
rename from test/dwarf/z8.go
rename to test/dwarf/dwarf.dir/z8.go
diff --git a/test/dwarf/z9.go b/test/dwarf/dwarf.dir/z9.go
similarity index 100%
rename from test/dwarf/z9.go
rename to test/dwarf/dwarf.dir/z9.go
diff --git a/test/dwarf/dwarf.go b/test/dwarf/dwarf.go
new file mode 100644
index 0000000..32dd7d3
--- /dev/null
+++ b/test/dwarf/dwarf.go
@@ -0,0 +1,10 @@
+// rundir
+
+// 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 issue 2241 and issue 1878: dwarf include stack size
+// issues in linker.
+
+package ignored
diff --git a/test/dwarf/main.go b/test/dwarf/main.go
deleted file mode 100644
index 7f2ec4c..0000000
--- a/test/dwarf/main.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// $G $D/$F.go $D/z*.go && $L $F.$A && ./$A.out
-
-// 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 main
-func main() {
-F1()
-F2()
-F3()
-F4()
-F5()
-F6()
-F7()
-F8()
-F9()
-F10()
-F11()
-F12()
-F13()
-F14()
-F15()
-F16()
-F17()
-F18()
-F19()
-F20()
-}
diff --git a/test/escape.go b/test/escape.go
index e487bb8..252a1e5 100644
--- a/test/escape.go
+++ b/test/escape.go
@@ -18,15 +18,15 @@ var allptr = make([]*int, 0, 100)
 
 func noalias(p, q *int, s string) {
 	n := len(allptr)
-	*p = -(n+1)
-	*q = -(n+2)
-	allptr = allptr[0:n+2]
+	*p = -(n + 1)
+	*q = -(n + 2)
+	allptr = allptr[0 : n+2]
 	allptr[n] = p
 	allptr[n+1] = q
 	n += 2
 	for i := 0; i < n; i++ {
 		if allptr[i] != nil && *allptr[i] != -(i+1) {
-			println("aliased pointers", -(i+1), *allptr[i], "after", s)
+			println("aliased pointers", -(i + 1), *allptr[i], "after", s)
 			allptr[i] = nil
 			bad = true
 		}
@@ -52,9 +52,11 @@ func chk(p, q *int, v int, s string) {
 func chkalias(p, q *int, v int, s string) {
 	if p != q {
 		println("want aliased pointers but got different after", s)
+		bad = true
 	}
 	if *q != v+1 {
 		println("wrong value want", v+1, "got", *q, "after", s)
+		bad = true
 	}
 }
 
@@ -141,15 +143,27 @@ func for_escapes2(x int, y int) (*int, *int) {
 	return p[0], p[1]
 }
 
+func for_escapes3(x int, y int) (*int, *int) {
+	var f [2]func() *int
+	n := 0
+	for i := x; n < 2; i = y {
+		p := new(int)
+		*p = i
+		f[n] = func() *int { return p }
+		n++
+	}
+	return f[0](), f[1]()
+}
+
 func out_escapes(i int) (x int, p *int) {
 	x = i
-	p = &x	// ERROR "address of out parameter"
+	p = &x // ERROR "address of out parameter"
 	return
 }
 
 func out_escapes_2(i int) (x int, p *int) {
 	x = i
-	return x, &x	// ERROR "address of out parameter"
+	return x, &x // ERROR "address of out parameter"
 }
 
 func defer1(i int) (x int) {
@@ -187,6 +201,9 @@ func main() {
 	p, q = for_escapes2(103, 104)
 	chkalias(p, q, 103, "for_escapes2")
 
+	p, q = for_escapes3(105, 106)
+	chk(p, q, 105, "for_escapes3")
+
 	_, p = out_escapes(15)
 	_, q = out_escapes(16)
 	chk(p, q, 15, "out_escapes")
diff --git a/test/escape2.go b/test/escape2.go
index 0bf02c5..9481619 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -1,4 +1,4 @@
-// errchk -0 $G -m -l $D/$F.go
+// errorcheck -0 -m -l
 
 // Copyright 2010 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -142,13 +142,13 @@ func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b"
 }
 
 func (b Bar) LeaksToo() *int { // ERROR "leaking param: b"
-	v := 0	// ERROR "moved to heap: v"
+	v := 0    // ERROR "moved to heap: v"
 	b.ii = &v // ERROR "&v escapes"
 	return b.ii
 }
 
 func (b *Bar) LeaksABit() *int { // ERROR "b does not escape"
-	v := 0	// ERROR "moved to heap: v"
+	v := 0    // ERROR "moved to heap: v"
 	b.ii = &v // ERROR "&v escapes"
 	return b.ii
 }
@@ -540,6 +540,19 @@ func foo74() {
 	}
 }
 
+// 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
 }
@@ -548,12 +561,21 @@ func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not esca
 	return &x[0] // ERROR "&x.0. escapes to heap"
 }
 
-func foo75(z *int) { // ERROR "leaking param: z"
+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 escapes to heap"
+	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"
@@ -561,7 +583,7 @@ func foo76(z *int) { // ERROR "leaking param: z"
 }
 
 func foo76a(z *int) { // ERROR "leaking param: z"
-	myprint1(nil, z) // ERROR "[.][.][.] argument escapes to heap"
+	myprint1(nil, z) // ERROR "[.][.][.] argument does not escape"
 }
 
 func foo76b() {
@@ -569,7 +591,7 @@ func foo76b() {
 }
 
 func foo76c() {
-	myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+	myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
 }
 
 func foo76d() {
@@ -577,7 +599,7 @@ func foo76d() {
 }
 
 func foo76e() {
-	defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+	defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
 }
 
 func foo76f() {
@@ -597,10 +619,15 @@ func foo77(z []interface{}) { // ERROR "z does not escape"
 	myprint(nil, z...) // z does not escape
 }
 
-func foo77a(z []interface{}) { // ERROR "leaking param: z"
+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"
 }
@@ -633,6 +660,21 @@ func foo81() *int {
 	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()
 }
@@ -1066,29 +1108,29 @@ 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 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 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
+	var px *int // loopdepth 0
 	for {
 		// loopdepth 1
-		var i int  // ERROR "moved to heap"
+		var i int // ERROR "moved to heap"
 		func() {  // ERROR "func literal does not escape"
-			px = &i  // ERROR "&i escapes"
+			px = &i // ERROR "&i escapes"
 		}()
 	}
 }
@@ -1096,8 +1138,8 @@ func foo126() {
 var px *int
 
 func foo127() {
-	var i int  // ERROR "moved to heap: i"
-	p := &i  // ERROR "&i escapes to heap"
+	var i int // ERROR "moved to heap: i"
+	p := &i   // ERROR "&i escapes to heap"
 	q := p
 	px = q
 }
@@ -1110,12 +1152,12 @@ func foo128() {
 }
 
 func foo129() {
-	var i int  // ERROR "moved to heap: i"
-	p := &i  // ERROR "&i escapes to heap"
+	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"
+		q := p   // ERROR "leaking closure reference p"
+		func() { // ERROR "func literal does not escape"
+			r := q // ERROR "leaking closure reference q"
 			px = r
 		}()
 	}()
@@ -1123,40 +1165,40 @@ func foo129() {
 
 func foo130() {
 	for {
-		var i int  // ERROR "moved to heap"
+		var i int // ERROR "moved to heap"
 		func() {  // ERROR "func literal does not escape"
-			px = &i  // ERROR "&i escapes" "leaking closure reference i"
+			px = &i // ERROR "&i escapes" "leaking closure reference i"
 		}()
 	}
 }
 
 func foo131() {
-	var i int  // ERROR "moved to heap"
+	var i int // ERROR "moved to heap"
 	func() {  // ERROR "func literal does not escape"
-		px = &i  // ERROR "&i escapes" "leaking closure reference i"
+		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"
+	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"
+	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"
+	func() { // ERROR "func literal does not escape"
 		q := p
-		func() {  // ERROR "func literal does not escape"
+		func() { // ERROR "func literal does not escape"
 			r := q
 			_ = r
 		}()
@@ -1164,11 +1206,11 @@ func foo134() {
 }
 
 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"
+	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
 		}()
@@ -1176,11 +1218,11 @@ func foo135() {
 }
 
 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"
+	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
 		}()
@@ -1188,13 +1230,73 @@ func foo136() {
 }
 
 func foo137() {
-	var i int  // ERROR "moved to heap: i"
-	p := &i  // ERROR "&i escapes to heap"
+	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"
+		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 := 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"
+}
diff --git a/test/escape4.go b/test/escape4.go
index 8875708..83bc8eb 100644
--- a/test/escape4.go
+++ b/test/escape4.go
@@ -1,4 +1,4 @@
-// errchk -0 $G -m $D/$F.go
+// errorcheck -0 -m
 
 // Copyright 2010 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -37,3 +37,21 @@ func f2() {} // ERROR "can inline f2"
 // No inline for panic, recover.
 func f3() { panic(1) }
 func f4() { recover() }
+
+func f5() *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 f6() *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"
+}
diff --git a/test/escape5.go b/test/escape5.go
new file mode 100644
index 0000000..6b327fe
--- /dev/null
+++ b/test/escape5.go
@@ -0,0 +1,144 @@
+// errorcheck -0 -m -l
+
+// 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, using compiler diagnostic flags, that the escape analysis is working.
+// Compiles but does not run.  Inlining is disabled.
+
+package foo
+
+func noleak(p *int) int { // ERROR "p does not escape"
+	return *p
+}
+
+func leaktoret(p *int) *int { // ERROR "leaking param: p to result"
+	return p
+}
+
+func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result .anon1" "leaking param: p to result .anon2"
+	return p, p
+}
+
+func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon2" "leaking param: q to result .anon3"
+	return p, q
+}
+
+func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2"
+	return leaktoret22(q, p)
+}
+
+func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2"
+	r, s := leaktoret22(q, p)
+	return r, s
+}
+
+func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
+	r, s = leaktoret22(q, p)
+	return
+}
+
+func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
+	r, s = leaktoret22(q, p)
+	return r, s
+}
+
+func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
+	rr, ss := leaktoret22(q, p)
+	return rr, ss
+}
+
+var gp *int
+
+func leaktosink(p *int) *int { // ERROR "leaking param: p"
+	gp = p
+	return p
+}
+
+func f1() {
+	var x int
+	p := noleak(&x) // ERROR "&x does not escape"
+	_ = p
+}
+
+func f2() {
+	var x int
+	p := leaktoret(&x) // ERROR "&x does not escape"
+	_ = p
+}
+
+func f3() {
+	var x int          // ERROR "moved to heap: x"
+	p := leaktoret(&x) // ERROR "&x escapes to heap"
+	gp = p
+}
+
+func f4() {
+	var x int              // ERROR "moved to heap: x"
+	p, q := leaktoret2(&x) // ERROR "&x escapes to heap"
+	gp = p
+	gp = q
+}
+
+func f5() {
+	var x int
+	leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape"
+}
+
+func f6() {
+	var x int                               // ERROR "moved to heap: x"
+	px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap"
+	gp = px1
+	_ = px2
+}
+
+type T struct{ x int }
+
+func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result"
+	t.x += u
+	return t, true
+}
+
+func f7() *T {
+	r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap"
+	return r
+}
+
+func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
+	return leakrecursive2(q, p)
+}
+
+func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
+	if *p > *q {
+		return leakrecursive1(q, p)
+	}
+	// without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges.
+	return p, q
+}
+
+
+var global interface{}
+
+type T1 struct {
+	X *int
+}
+
+type T2 struct {
+	Y *T1
+}
+
+func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
+	if p == nil {
+		k = T2{}
+		return
+	}
+
+	global = p // should make p leak always
+	return T2{p}
+}
+
+func f9() {
+	var j T1 // ERROR "moved to heap: j"
+	f8(&j) // ERROR "&j escapes to heap"
+}
diff --git a/test/fixedbugs/bug083.go b/test/fixedbugs/bug083.go
index 984969d..54a1742 100644
--- a/test/fixedbugs/bug083.go
+++ b/test/fixedbugs/bug083.go
@@ -1,7 +1,7 @@
-// $G $D/$F.dir/bug0.go && errchk $G $D/$F.dir/bug1.go
+// errorcheckdir
 
 // 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.
 
-ignored
+package ignored
diff --git a/test/fixedbugs/bug085.go b/test/fixedbugs/bug085.go
index 93ae7e0..dae83f8 100644
--- a/test/fixedbugs/bug085.go
+++ b/test/fixedbugs/bug085.go
@@ -20,7 +20,7 @@ Bus error
 
 /* expected scope hierarchy (outermost to innermost)
 
-universe scope (contains predeclared identifiers int, float, int32, len, etc.)
+universe scope (contains predeclared identifiers int, float32, int32, len, etc.)
 "solar" scope (just holds the package name P so it can be found but doesn't conflict)
 global scope (the package global scope)
 local scopes (function scopes)
diff --git a/test/fixedbugs/bug088.go b/test/fixedbugs/bug088.go
index 9715a70..3b99da8 100644
--- a/test/fixedbugs/bug088.go
+++ b/test/fixedbugs/bug088.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/bug0.go && $G $D/$F.dir/bug1.go || echo BUG: fails incorrectly
+// compiledir
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug106.go b/test/fixedbugs/bug106.go
index 1874b20..3b99da8 100644
--- a/test/fixedbugs/bug106.go
+++ b/test/fixedbugs/bug106.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/bug0.go && $G $D/$F.dir/bug1.go || echo BUG: failed to compile
+// compiledir
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug133.go b/test/fixedbugs/bug133.go
index 2beeb07..54a1742 100644
--- a/test/fixedbugs/bug133.go
+++ b/test/fixedbugs/bug133.go
@@ -1,7 +1,7 @@
-// $G $D/$F.dir/bug0.go && $G $D/$F.dir/bug1.go && errchk $G $D/$F.dir/bug2.go
+// errorcheckdir
 
 // 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.
 
-ignored
+package ignored
diff --git a/test/fixedbugs/bug160.go b/test/fixedbugs/bug160.go
index 8fd53ea..fde797b 100644
--- a/test/fixedbugs/bug160.go
+++ b/test/fixedbugs/bug160.go
@@ -1,7 +1,7 @@
-// $G $D/bug160.dir/x.go && $G $D/bug160.dir/y.go && $L y.$A && ./$A.out
+// rundir
 
 // 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.
 
-nothing to see here
+package ignored
diff --git a/test/fixedbugs/bug191.dir/main.go b/test/fixedbugs/bug191.dir/main.go
new file mode 100644
index 0000000..995134c
--- /dev/null
+++ b/test/fixedbugs/bug191.dir/main.go
@@ -0,0 +1,14 @@
+// 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 main
+
+import . "./a"
+import . "./b"
+
+var _ T
+var _ V
+
+func main() {
+}
diff --git a/test/fixedbugs/bug191.go b/test/fixedbugs/bug191.go
index 44fcccf..acb4796 100644
--- a/test/fixedbugs/bug191.go
+++ b/test/fixedbugs/bug191.go
@@ -1,16 +1,9 @@
-// $G $D/bug191.dir/a.go && $G $D/bug191.dir/b.go && $G $D/$F.go && $L $F.$A
+// rundircmpout
 
 // 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 main
+// Tests bug with dot imports.
 
-import . "./a"
-import . "./b"
-
-var _ T
-var _ V
-
-func main() {
-}
+package ignored
diff --git a/test/fixedbugs/bug191.out b/test/fixedbugs/bug191.out
new file mode 100644
index 0000000..0e1677a
--- /dev/null
+++ b/test/fixedbugs/bug191.out
@@ -0,0 +1,2 @@
+b
+a
diff --git a/test/fixedbugs/bug205.go b/test/fixedbugs/bug205.go
index de17cb6..769837d 100644
--- a/test/fixedbugs/bug205.go
+++ b/test/fixedbugs/bug205.go
@@ -11,8 +11,8 @@ var s string;
 var m map[string]int;
 
 func main() {
-	println(t["hi"]);	// ERROR "integer"
-	println(s["hi"]);	// ERROR "integer" "to type uint"
-	println(m[0]);	// ERROR "map index"
+	println(t["hi"]);	// ERROR "non-integer slice index"
+	println(s["hi"]);	// ERROR "non-integer string index"
+	println(m[0]);	// ERROR "as type string in map index"
 }
 
diff --git a/test/fixedbugs/bug206.go b/test/fixedbugs/bug206.go
index 7efc0b1..c2382ac 100644
--- a/test/fixedbugs/bug206.go
+++ b/test/fixedbugs/bug206.go
@@ -1,4 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out >/dev/null 2>&1 || echo BUG: bug206
+// cmpout
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug206.out b/test/fixedbugs/bug206.out
new file mode 100644
index 0000000..aa47d0d
--- /dev/null
+++ b/test/fixedbugs/bug206.out
@@ -0,0 +1,2 @@
+0
+0
diff --git a/test/fixedbugs/bug222.go b/test/fixedbugs/bug222.go
index 5c23a53..3b99da8 100644
--- a/test/fixedbugs/bug222.go
+++ b/test/fixedbugs/bug222.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/chanbug.go && $G -I. $D/$F.dir/chanbug2.go
+// compiledir
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug223.go b/test/fixedbugs/bug223.go
index eccf574..29ae53c 100644
--- a/test/fixedbugs/bug223.go
+++ b/test/fixedbugs/bug223.go
@@ -18,4 +18,4 @@ func f() {
 	}
 }
 
-var m = map[string]F{"f": f} // ERROR "initialization loop"
+var m = map[string]F{"f": f} // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/bug228.go b/test/fixedbugs/bug228.go
index 3d23609..3fccd17 100644
--- a/test/fixedbugs/bug228.go
+++ b/test/fixedbugs/bug228.go
@@ -8,11 +8,11 @@ package main
 
 func f(x int, y ...int)	// ok
 
-func g(x int, y float) (...)	// ERROR "[.][.][.]" "final argument"
+func g(x int, y float32) (...)	// ERROR "[.][.][.]" "final argument"
 
 func h(x, y ...int)		// ERROR "[.][.][.]"
 
-func i(x int, y ...int, z float)	// ERROR "[.][.][.]"
+func i(x int, y ...int, z float32)	// ERROR "[.][.][.]"
 
 var x ...int;		// ERROR "[.][.][.]|syntax|type"
 
diff --git a/test/fixedbugs/bug248.go b/test/fixedbugs/bug248.go
index 055bf1f..98cda35 100644
--- a/test/fixedbugs/bug248.go
+++ b/test/fixedbugs/bug248.go
@@ -5,6 +5,9 @@
 // $L bug2.$A &&
 // ./$A.out || echo BUG: failed to compile
 
+// 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.
+
 // 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.
diff --git a/test/fixedbugs/bug255.go b/test/fixedbugs/bug255.go
index dbd41cc..acf4f23 100644
--- a/test/fixedbugs/bug255.go
+++ b/test/fixedbugs/bug255.go
@@ -12,4 +12,4 @@ 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 "overflows"
+var g [1<<65]int	// ERROR "array bound is too large|overflows"
diff --git a/test/fixedbugs/bug273.go b/test/fixedbugs/bug273.go
index b35b17d..aabb912 100644
--- a/test/fixedbugs/bug273.go
+++ b/test/fixedbugs/bug273.go
@@ -8,14 +8,15 @@
 
 package main
 
-import "unsafe"
-
 var bug = false
 
 var minus1 = -1
+var five = 5
 var big int64 = 10 | 1<<32
 
-var g1 []int
+type block [1<<19]byte
+
+var g1 []block
 
 func shouldfail(f func(), desc string) {
 	defer func() { recover() }()
@@ -28,55 +29,47 @@ func shouldfail(f func(), desc string) {
 }
 
 func badlen() {
-	g1 = make([]int, minus1)
+	g1 = make([]block, minus1)
 }
 
 func biglen() {
-	g1 = make([]int, big)
+	g1 = make([]block, big)
 }
 
 func badcap() {
-	g1 = make([]int, 10, minus1)
+	g1 = make([]block, 10, minus1)
 }
 
 func badcap1() {
-	g1 = make([]int, 10, 5)
+	g1 = make([]block, 10, five)
 }
 
 func bigcap() {
-	g1 = make([]int, 10, big)
+	g1 = make([]block, 10, big)
 }
 
-var g3 map[int]int
+var g3 map[block]block
 func badmapcap() {
-	g3 = make(map[int]int, minus1)
+	g3 = make(map[block]block, minus1)
 }
 
 func bigmapcap() {
-	g3 = make(map[int]int, big)
+	g3 = make(map[block]block, big)
 }
 
-var g4 chan int
+type cblock [1<<16-1]byte
+
+var g4 chan cblock
 func badchancap() {
-	g4 = make(chan int, minus1)
+	g4 = make(chan cblock, minus1)
 }
 
 func bigchancap() {
-	g4 = make(chan int, big)
+	g4 = make(chan cblock, big)
 }
 
-const addrBits = unsafe.Sizeof((*byte)(nil))
-
-var g5 chan [1<<15]byte
 func overflowchan() {
-	if addrBits == 32 {
-		g5 = make(chan [1<<15]byte, 1<<20)
-	} else {
-		// cannot overflow on 64-bit, because
-		// int is 32 bits and max chan value size
-		// in the implementation is 64 kB.
-		panic(1)
-	}
+	g4 = make(chan cblock, 1<<30)
 }
 
 func main() {
diff --git a/test/fixedbugs/bug282.go b/test/fixedbugs/bug282.go
index 463f21e..3b99da8 100644
--- a/test/fixedbugs/bug282.go
+++ b/test/fixedbugs/bug282.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/p1.go && $G $D/$F.dir/p2.go
+// compiledir
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug297.go b/test/fixedbugs/bug297.go
index b5dfa8d..ee2ff92 100644
--- a/test/fixedbugs/bug297.go
+++ b/test/fixedbugs/bug297.go
@@ -11,5 +11,5 @@ package main
 type ByteSize float64
 const (
 	_ = iota;   // ignore first value by assigning to blank identifier
-	KB ByteSize = 1<<(10*X) // ERROR "undefined" "as type ByteSize"
+	KB ByteSize = 1<<(10*X) // ERROR "undefined" "is not a constant|as type ByteSize"
 )
diff --git a/test/fixedbugs/bug302.go b/test/fixedbugs/bug302.go
index 1088b2f..dc7637f 100644
--- a/test/fixedbugs/bug302.go
+++ b/test/fixedbugs/bug302.go
@@ -1,5 +1,8 @@
 // $G $D/bug302.dir/p.go && pack grc pp.a p.$A && $G $D/bug302.dir/main.go
 
+// 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.
+
 // 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.
diff --git a/test/fixedbugs/bug306.go b/test/fixedbugs/bug306.go
index a0a4350..e8967c2 100644
--- a/test/fixedbugs/bug306.go
+++ b/test/fixedbugs/bug306.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/p1.go && $G $D/$F.dir/p2.go
+// compiledir
 
 // Copyright 2010 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug313.go b/test/fixedbugs/bug313.go
index eb2a022..a7c1d36 100644
--- a/test/fixedbugs/bug313.go
+++ b/test/fixedbugs/bug313.go
@@ -1,4 +1,4 @@
-// errchk $G -e $D/$F.dir/[ab].go
+// errorcheckdir
 
 // Copyright 2010 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug322.go b/test/fixedbugs/bug322.go
index ad0e62d..21efbb5 100644
--- a/test/fixedbugs/bug322.go
+++ b/test/fixedbugs/bug322.go
@@ -1,8 +1,8 @@
-// $G $D/$F.dir/lib.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out || echo BUG: fails incorrectly
+// rundir
 
 // 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.
 
 // Test case for issue 1402.
-ignored
+package ignored
diff --git a/test/fixedbugs/bug324.dir/main.go b/test/fixedbugs/bug324.dir/prog.go
similarity index 100%
rename from test/fixedbugs/bug324.dir/main.go
rename to test/fixedbugs/bug324.dir/prog.go
diff --git a/test/fixedbugs/bug324.go b/test/fixedbugs/bug324.go
index 3da7563..36b8b56 100644
--- a/test/fixedbugs/bug324.go
+++ b/test/fixedbugs/bug324.go
@@ -1,8 +1,10 @@
-// $G $D/$F.dir/p.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out
+// rundir
 
 // 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.
 
-// Test case for issue 1550
-ignored
+// Test case for issue 1550: a type cannot implement an interface
+// from another package with a private method, and type assertions
+// should fail.
+package ignored
diff --git a/test/fixedbugs/bug335.dir/a.go b/test/fixedbugs/bug335.dir/a.go
index 5a8112a..256c110 100644
--- a/test/fixedbugs/bug335.dir/a.go
+++ b/test/fixedbugs/bug335.dir/a.go
@@ -4,6 +4,8 @@
 
 package a
 
-import "./b"
+type T interface{}
 
-var Bar = b.Foo
+func f() T { return nil }
+
+var Foo T = f()
diff --git a/test/fixedbugs/bug335.dir/b.go b/test/fixedbugs/bug335.dir/b.go
index 7428c2a..1474470 100644
--- a/test/fixedbugs/bug335.dir/b.go
+++ b/test/fixedbugs/bug335.dir/b.go
@@ -4,8 +4,6 @@
 
 package b
 
-type T interface{}
+import "./a"
 
-func f() T { return nil }
-
-var Foo T = f()
+var Bar = a.Foo
diff --git a/test/fixedbugs/bug335.go b/test/fixedbugs/bug335.go
index 915b746..37c97d7 100644
--- a/test/fixedbugs/bug335.go
+++ b/test/fixedbugs/bug335.go
@@ -1,5 +1,4 @@
-// $G $D/$F.dir/b.go && $G $D/$F.dir/a.go
-// rm -f a.$A b.$A
+// compiledir
 
 // Copyright 2011 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -7,4 +6,4 @@
 
 // Issue 1705.
 
-unused (see script at top of file)
+package ignored
diff --git a/test/fixedbugs/bug345.go b/test/fixedbugs/bug345.go
index 874710c..e3705f6 100644
--- a/test/fixedbugs/bug345.go
+++ b/test/fixedbugs/bug345.go
@@ -1,5 +1,8 @@
 // $G $D/$F.dir/io.go && errchk $G -e $D/$F.dir/main.go
 
+// 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.
+
 // 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/test/fixedbugs/bug357.go b/test/fixedbugs/bug357.go
index 2ac64a8..ceb2009 100644
--- a/test/fixedbugs/bug357.go
+++ b/test/fixedbugs/bug357.go
@@ -15,7 +15,7 @@ func bla1() bool {
 
 func bla5() bool {
 	_ = 1
-	false  // ERROR "false not used|value computed is not used"
+	false  // ERROR "false evaluated but not used|value computed is not used"
 	_ = 2
 	return false
 }
diff --git a/test/fixedbugs/bug358.go b/test/fixedbugs/bug358.go
index 6a00848..063c2e0 100644
--- a/test/fixedbugs/bug358.go
+++ b/test/fixedbugs/bug358.go
@@ -12,7 +12,7 @@ package main
 import (
 	"io/ioutil"	// GCCGO_ERROR "imported and not used"
 	"net/http"
-	"os"
+	"os"		// GCCGO_ERROR "imported and not used"
 )
 
 func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
diff --git a/test/fixedbugs/bug367.dir/main.go b/test/fixedbugs/bug367.dir/prog.go
similarity index 100%
rename from test/fixedbugs/bug367.dir/main.go
rename to test/fixedbugs/bug367.dir/prog.go
diff --git a/test/fixedbugs/bug367.go b/test/fixedbugs/bug367.go
index 25d11a1..05252cd 100644
--- a/test/fixedbugs/bug367.go
+++ b/test/fixedbugs/bug367.go
@@ -1,7 +1,10 @@
-// $G $D/$F.dir/p.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out || echo BUG: should not fail
+// rundir
 
 // 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.
 
+// Issue 1536: bug when handling imported interfaces with
+// private methods.
+
 package ignored
diff --git a/test/fixedbugs/bug369.go b/test/fixedbugs/bug369.go
index 4d98e85..6d52622 100644
--- a/test/fixedbugs/bug369.go
+++ b/test/fixedbugs/bug369.go
@@ -2,6 +2,9 @@
 // $G -o fast.$A $D/bug369.dir/pkg.go &&
 // run
 
+// 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.
+
 // 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.
@@ -35,9 +38,9 @@ func BenchmarkSlowNonASCII(b *testing.B) {
 }
 
 func main() {
-	os.Args = []string{os.Args[0], "-test.benchtime=0.1"}
+	os.Args = []string{os.Args[0], "-test.benchtime=100ms"}
 	flag.Parse()
-	
+
 	rslow := testing.Benchmark(BenchmarkSlowNonASCII)
 	rfast := testing.Benchmark(BenchmarkFastNonASCII)
 	tslow := rslow.NsPerOp()
diff --git a/test/fixedbugs/bug377.go b/test/fixedbugs/bug377.go
index e905e34..22df005 100644
--- a/test/fixedbugs/bug377.go
+++ b/test/fixedbugs/bug377.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/one.go && $G $D/$F.dir/two.go
+// compiledir
 
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug379.go b/test/fixedbugs/bug379.go
index 81e9c26..14abe46 100644
--- a/test/fixedbugs/bug379.go
+++ b/test/fixedbugs/bug379.go
@@ -14,5 +14,5 @@
 package main
 
 func main() {
-	1 + 2 // ERROR "1 \+ 2 not used|value computed is not used"
+	1 + 2 // ERROR "1 \+ 2 evaluated but not used|value computed is not used"
 }
diff --git a/test/fixedbugs/bug382.dir/prog.go b/test/fixedbugs/bug382.dir/prog.go
new file mode 100644
index 0000000..b74a82d
--- /dev/null
+++ b/test/fixedbugs/bug382.dir/prog.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
+
+// Issue 2529
+
+package main
+
+import "./pkg"
+
+var x = pkg.E
+
+var fo = struct{ F pkg.T }{F: x}
diff --git a/test/fixedbugs/bug382.go b/test/fixedbugs/bug382.go
index 3f5d05c..6039939 100644
--- a/test/fixedbugs/bug382.go
+++ b/test/fixedbugs/bug382.go
@@ -1,14 +1,9 @@
-// $G $D/$F.dir/pkg.go && $G $D/$F.go || echo "Bug 382"
+// compiledir
 
 // 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
 
-// Issue 2529
+// Issue 2529.
 
-package main
-import "./pkg"
-
-var x = pkg.E
-
-var fo = struct {F pkg.T}{F: x}
+package ignored
diff --git a/test/fixedbugs/bug385_32.go b/test/fixedbugs/bug385_32.go
index b9ecbb4..724ed93 100644
--- a/test/fixedbugs/bug385_32.go
+++ b/test/fixedbugs/bug385_32.go
@@ -1,4 +1,5 @@
-// [ $A == 6 ] || errchk $G -e $D/$F.go
+// +build 386 arm
+// errorcheck
 
 // Copyright 2011 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -11,4 +12,4 @@ func main() {
 	var arr [1000200030]int   // ERROR "type .* too large"
 	arr_bkup := arr
 	_ = arr_bkup
-}
\ No newline at end of file
+}
diff --git a/test/fixedbugs/bug385_64.go b/test/fixedbugs/bug385_64.go
index 7476b17..b5621b2 100644
--- a/test/fixedbugs/bug385_64.go
+++ b/test/fixedbugs/bug385_64.go
@@ -1,15 +1,22 @@
-// [ $A != 6 ]  || errchk $G -e $D/$F.go
+// +build amd64
+// errorcheck
 
 // 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.
 
 // Issue 2444
+// Issue 4666: issue with arrays of exactly 4GB.
 
 package main
-func main() {  // ERROR "stack frame too large"
-	var arr [1000200030]int
+
+func main() { // ERROR "stack frame too large"
+	var arr [1000200030]int32
 	arr_bkup := arr
 	_ = arr_bkup
 }
 
+func F() { // ERROR "stack frame too large"
+	var arr [1 << 30]int32
+	_ = arr[42]
+}
diff --git a/test/fixedbugs/bug392.dir/pkg2.go b/test/fixedbugs/bug392.dir/pkg2.go
new file mode 100644
index 0000000..8320b2f
--- /dev/null
+++ b/test/fixedbugs/bug392.dir/pkg2.go
@@ -0,0 +1,25 @@
+// 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.
+
+// Use the functions in one.go so that the inlined
+// forms get type-checked.
+
+package pkg2
+
+import "./one"
+
+func use() {
+	one.F1(nil)
+	one.F2(nil)
+	one.F3()
+	one.F4(1)
+
+	var t *one.T
+	t.M()
+	t.MM()
+}
+
+var V = []one.PB{{}, {}}
+
+func F() *one.PB
diff --git a/test/fixedbugs/bug392.dir/pkg3.go b/test/fixedbugs/bug392.dir/pkg3.go
new file mode 100644
index 0000000..402c3b0
--- /dev/null
+++ b/test/fixedbugs/bug392.dir/pkg3.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.
+
+// Use the functions in pkg2.go so that the inlined
+// forms get type-checked.
+
+package pkg3
+
+import "./pkg2"
+
+var x = pkg2.F()
+var v = pkg2.V
diff --git a/test/fixedbugs/bug392.dir/three.go b/test/fixedbugs/bug392.dir/three.go
deleted file mode 100644
index a6193bf..0000000
--- a/test/fixedbugs/bug392.dir/three.go
+++ /dev/null
@@ -1,13 +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.
-
-// Use the functions in one.go so that the inlined
-// forms get type-checked.
-
-package three
-
-import "./two"
-
-var x = two.F()
-var v = two.V
diff --git a/test/fixedbugs/bug392.dir/two.go b/test/fixedbugs/bug392.dir/two.go
deleted file mode 100644
index a9033db..0000000
--- a/test/fixedbugs/bug392.dir/two.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2012 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Use the functions in one.go so that the inlined
-// forms get type-checked.
-
-package two
-
-import "./one"
-
-func use() {
-	one.F1(nil)
-	one.F2(nil)
-	one.F3()
-	one.F4(1)
-
-	var t *one.T
-	t.M()
-	t.MM()
-}
-
-var V = []one.PB{{}, {}}
-
-func F() *one.PB
diff --git a/test/fixedbugs/bug392.go b/test/fixedbugs/bug392.go
index a7a4216..48b79e0 100644
--- a/test/fixedbugs/bug392.go
+++ b/test/fixedbugs/bug392.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/one.go && $G $D/$F.dir/two.go && $G $D/$F.dir/three.go
+// compiledir
 
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug396.dir/one.go b/test/fixedbugs/bug396.dir/one.go
index 7902a07..96a1dd7 100644
--- a/test/fixedbugs/bug396.dir/one.go
+++ b/test/fixedbugs/bug396.dir/one.go
@@ -4,6 +4,7 @@
 
 package one
 
+// Issue 2687
 type T struct { int }
 
 func New(i int) T { return T{i} }
diff --git a/test/fixedbugs/bug396.go b/test/fixedbugs/bug396.go
index 50af600..48b79e0 100644
--- a/test/fixedbugs/bug396.go
+++ b/test/fixedbugs/bug396.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/one.go && $G $D/$F.dir/two.go
+// compiledir
 
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug404.go b/test/fixedbugs/bug404.go
index ac9e575..481acda 100644
--- a/test/fixedbugs/bug404.go
+++ b/test/fixedbugs/bug404.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/one.go && $G $D/$F.dir/two.go
+// compiledir
 
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug407.go b/test/fixedbugs/bug407.go
index 50af600..48b79e0 100644
--- a/test/fixedbugs/bug407.go
+++ b/test/fixedbugs/bug407.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/one.go && $G $D/$F.dir/two.go
+// compiledir
 
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug410.go b/test/fixedbugs/bug410.go
index 35ecbfc..430ddcb 100644
--- a/test/fixedbugs/bug410.go
+++ b/test/fixedbugs/bug410.go
@@ -18,7 +18,7 @@ func zzz () {
     for s := range arr {
         x := make([]byte, 10)
         for i := 0; i < 100 ; i++ {
-            x[i] ^= k[i-arr[s].num%0]
+            x[i] ^= k[i-arr[s].num%3]
         }
     }
 }
diff --git a/test/fixedbugs/bug412.go b/test/fixedbugs/bug412.go
index 9148b68..8dd0a5f 100644
--- a/test/fixedbugs/bug412.go
+++ b/test/fixedbugs/bug412.go
@@ -7,10 +7,10 @@
 package p
 
 type t struct {
-	x int  // ERROR "duplicate field x"
+	x int  // ERROR "duplicate field x|duplicate field name .x."
 	x int
 }
 
 func f(t *t) int {
-	return t.x  // ERROR "ambiguous selector t.x"
+	return t.x  // GC_ERROR "ambiguous selector t.x"
 }
diff --git a/test/fixedbugs/bug413.go b/test/fixedbugs/bug413.go
index 41270d9..ba80464 100644
--- a/test/fixedbugs/bug413.go
+++ b/test/fixedbugs/bug413.go
@@ -8,4 +8,4 @@ package p
 
 func f(i int) int { return i }
 
-var i = func() int {a := f(i); return a}()  // ERROR "initialization loop"
\ No newline at end of file
+var i = func() int {a := f(i); return a}()  // ERROR "initialization loop|depends upon itself"
diff --git a/test/fixedbugs/bug414.dir/main.go b/test/fixedbugs/bug414.dir/main.go
deleted file mode 100644
index 5200123..0000000
--- a/test/fixedbugs/bug414.dir/main.go
+++ /dev/null
@@ -1,18 +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 main
-	
-	  import "./p1"
-	
-	  type MyObject struct {
-	    p1.Fer
-	  }
-	
-	  func main() {
-	    var b p1.Fer = &p1.Object{}
-	    p1.PrintFer(b)
-	    var c p1.Fer = &MyObject{b}
-	    p1.PrintFer(c)
-	  }
diff --git a/test/fixedbugs/bug414.dir/p1.go b/test/fixedbugs/bug414.dir/p1.go
index 7768818..2463834 100644
--- a/test/fixedbugs/bug414.dir/p1.go
+++ b/test/fixedbugs/bug414.dir/p1.go
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-	  package p1
-	
-	  import "fmt"
-	
-	  type Fer interface {
-	    f() string
-	  }
-	
-	  type Object struct {}
-	
-	  func (this *Object) f() string {
-	    return "Object.f"
-	  }
-	
-	  func PrintFer(fer Fer) {
-	    fmt.Sprintln(fer.f())
-	  }
+package p1
+
+import "fmt"
+
+type Fer interface {
+	f() string
+}
+
+type Object struct{}
+
+func (this *Object) f() string {
+	return "Object.f"
+}
+
+func PrintFer(fer Fer) {
+	fmt.Sprintln(fer.f())
+}
diff --git a/test/fixedbugs/bug414.dir/prog.go b/test/fixedbugs/bug414.dir/prog.go
new file mode 100644
index 0000000..f55d946
--- /dev/null
+++ b/test/fixedbugs/bug414.dir/prog.go
@@ -0,0 +1,18 @@
+// 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 main
+
+import "./p1"
+
+type MyObject struct {
+	p1.Fer
+}
+
+func main() {
+	var b p1.Fer = &p1.Object{}
+	p1.PrintFer(b)
+	var c p1.Fer = &MyObject{b}
+	p1.PrintFer(c)
+}
diff --git a/test/fixedbugs/bug414.go b/test/fixedbugs/bug414.go
index 8824b1a..35e19be 100644
--- a/test/fixedbugs/bug414.go
+++ b/test/fixedbugs/bug414.go
@@ -1,7 +1,9 @@
-// $G $D/$F.dir/p1.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out
+// rundir
 
 // 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.
 
+// Issue 1743: test embedding of imported types with private methods.
+
 package ignored
diff --git a/test/fixedbugs/bug415.dir/main.go b/test/fixedbugs/bug415.dir/prog.go
similarity index 100%
rename from test/fixedbugs/bug415.dir/main.go
rename to test/fixedbugs/bug415.dir/prog.go
diff --git a/test/fixedbugs/bug415.go b/test/fixedbugs/bug415.go
index fbf0342..8cd4c49 100644
--- a/test/fixedbugs/bug415.go
+++ b/test/fixedbugs/bug415.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/p.go && $G $D/$F.dir/main.go
+// compiledir
 
 // Copyright 2012 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug416.go b/test/fixedbugs/bug416.go
index c128538..1d24fa9 100644
--- a/test/fixedbugs/bug416.go
+++ b/test/fixedbugs/bug416.go
@@ -10,4 +10,4 @@ type T struct {
 	X int
 }
 
-func (t *T) X() {} // ERROR "type T has both field and method named X"
+func (t *T) X() {} // ERROR "type T has both field and method named X|redeclares struct field name"
diff --git a/test/fixedbugs/bug424.dir/main.go b/test/fixedbugs/bug424.dir/main.go
new file mode 100644
index 0000000..c2fe146
--- /dev/null
+++ b/test/fixedbugs/bug424.dir/main.go
@@ -0,0 +1,97 @@
+// 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 that method calls through an interface always
+// call the locally defined method localT.m independent
+// at which embedding level it is and in which order
+// embedding is done.
+
+package main
+
+import "./lib"
+import "reflect"
+import "fmt"
+
+type localI interface {
+	m() string
+}
+
+type localT struct{}
+
+func (t *localT) m() string {
+	return "main.localT.m"
+}
+
+type myT1 struct {
+	localT
+}
+
+type myT2 struct {
+	localT
+	lib.T
+}
+
+type myT3 struct {
+	lib.T
+	localT
+}
+
+func main() {
+	var i localI
+
+	i = new(localT)
+	if i.m() != "main.localT.m" {
+		println("BUG: localT:", i.m(), "called")
+	}
+
+	i = new(myT1)
+	if i.m() != "main.localT.m" {
+		println("BUG: myT1:", i.m(), "called")
+	}
+
+	i = new(myT2)
+	if i.m() != "main.localT.m" {
+		println("BUG: myT2:", i.m(), "called")
+	}
+
+	t3 := new(myT3)
+	if t3.m() != "main.localT.m" {
+		println("BUG: t3:", t3.m(), "called")
+	}
+	
+	i = new(myT3)
+	if i.m() != "main.localT.m" {
+		t := reflect.TypeOf(i)
+		n := t.NumMethod()
+		for j := 0; j < n; j++ {
+			m := t.Method(j)
+			fmt.Printf("#%d: %s.%s %s\n", j, m.PkgPath, m.Name, m.Type)
+		}
+		println("BUG: myT3:", i.m(), "called")
+	}
+	
+	var t4 struct {
+		localT
+		lib.T
+	}
+	if t4.m() != "main.localT.m" {
+		println("BUG: t4:", t4.m(), "called")
+	}
+	i = &t4
+	if i.m() != "main.localT.m" {
+		println("BUG: myT4:", i.m(), "called")
+	}
+	
+	var t5 struct {
+		lib.T
+		localT
+	}
+	if t5.m() != "main.localT.m" {
+		println("BUG: t5:", t5.m(), "called")
+	}
+	i = &t5
+	if i.m() != "main.localT.m" {
+		println("BUG: myT5:", i.m(), "called")
+	}
+}
diff --git a/test/fixedbugs/bug424.go b/test/fixedbugs/bug424.go
index 42cff54..59c2cd3 100644
--- a/test/fixedbugs/bug424.go
+++ b/test/fixedbugs/bug424.go
@@ -1,4 +1,4 @@
-// $G $D/$F.dir/lib.go && $G $D/$F.go && $L $F.$A && ./$A.out
+// rundir
 
 // Copyright 2012 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -9,91 +9,5 @@
 // at which embedding level it is and in which order
 // embedding is done.
 
-package main
+package ignored
 
-import "./lib"
-import "reflect"
-import "fmt"
-
-type localI interface {
-	m() string
-}
-
-type localT struct{}
-
-func (t *localT) m() string {
-	return "main.localT.m"
-}
-
-type myT1 struct {
-	localT
-}
-
-type myT2 struct {
-	localT
-	lib.T
-}
-
-type myT3 struct {
-	lib.T
-	localT
-}
-
-func main() {
-	var i localI
-
-	i = new(localT)
-	if i.m() != "main.localT.m" {
-		println("BUG: localT:", i.m(), "called")
-	}
-
-	i = new(myT1)
-	if i.m() != "main.localT.m" {
-		println("BUG: myT1:", i.m(), "called")
-	}
-
-	i = new(myT2)
-	if i.m() != "main.localT.m" {
-		println("BUG: myT2:", i.m(), "called")
-	}
-
-	t3 := new(myT3)
-	if t3.m() != "main.localT.m" {
-		println("BUG: t3:", t3.m(), "called")
-	}
-	
-	i = new(myT3)
-	if i.m() != "main.localT.m" {
-		t := reflect.TypeOf(i)
-		n := t.NumMethod()
-		for j := 0; j < n; j++ {
-			m := t.Method(j)
-			fmt.Printf("#%d: %s.%s %s\n", j, m.PkgPath, m.Name, m.Type)
-		}
-		println("BUG: myT3:", i.m(), "called")
-	}
-	
-	var t4 struct {
-		localT
-		lib.T
-	}
-	if t4.m() != "main.localT.m" {
-		println("BUG: t4:", t4.m(), "called")
-	}
-	i = &t4
-	if i.m() != "main.localT.m" {
-		println("BUG: myT4:", i.m(), "called")
-	}
-	
-	var t5 struct {
-		lib.T
-		localT
-	}
-	if t5.m() != "main.localT.m" {
-		println("BUG: t5:", t5.m(), "called")
-	}
-	i = &t5
-	if i.m() != "main.localT.m" {
-		println("BUG: myT5:", i.m(), "called")
-	}
-}
diff --git a/test/fixedbugs/bug429.go b/test/fixedbugs/bug429.go
index c1bd1d4..794d293 100644
--- a/test/fixedbugs/bug429.go
+++ b/test/fixedbugs/bug429.go
@@ -1,5 +1,8 @@
 // $G $D/$F.go && $L $F.$A && ! ./$A.out || echo BUG: bug429
 
+// 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.
+
 // 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/test/fixedbugs/bug430.go b/test/fixedbugs/bug430.go
new file mode 100644
index 0000000..93d5cf2
--- /dev/null
+++ b/test/fixedbugs/bug430.go
@@ -0,0 +1,22 @@
+// compile
+
+// 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.
+
+// gccgo crashed compiling this.
+
+package main
+
+type S struct {
+	f [2][]int
+}
+
+func F() (r [2][]int) {
+	return
+}
+
+func main() {
+	var a []S
+	a[0].f = F()
+}
diff --git a/test/fixedbugs/bug431.go b/test/fixedbugs/bug431.go
new file mode 100644
index 0000000..1057dad
--- /dev/null
+++ b/test/fixedbugs/bug431.go
@@ -0,0 +1,18 @@
+// compile
+
+// 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.
+
+// gccgo gave an invalid error ("floating point constant truncated to
+// integer") compiling this.
+
+package p
+
+const C = 1<<63 - 1
+
+func F(i int64) int64 {
+	return i
+}
+
+var V = F(int64(C) / 1e6)
diff --git a/test/fixedbugs/bug432.go b/test/fixedbugs/bug432.go
new file mode 100644
index 0000000..0c1a914
--- /dev/null
+++ b/test/fixedbugs/bug432.go
@@ -0,0 +1,13 @@
+// compile
+
+// 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.
+
+// gccgo crashed compiling this.
+
+package p
+
+var v struct{ I }
+
+type I interface{}
diff --git a/test/fixedbugs/bug433.go b/test/fixedbugs/bug433.go
new file mode 100644
index 0000000..1139dfa
--- /dev/null
+++ b/test/fixedbugs/bug433.go
@@ -0,0 +1,39 @@
+// run
+
+// 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 that initializing struct fields out of order still runs
+// functions in the right order.  This failed with gccgo.
+
+package main
+
+type S struct {
+	i1, i2, i3 int
+}
+
+var G int
+
+func v(i int) int {
+	if i != G {
+		panic(i)
+	}
+	G = i + 1
+	return G
+}
+
+func F() S {
+	return S{
+		i1: v(0),
+		i3: v(1),
+		i2: v(2),
+	}
+}
+
+func main() {
+	s := F()
+	if s != (S{1, 3, 2}) {
+		panic(s)
+	}
+}
diff --git a/test/fixedbugs/bug434.go b/test/fixedbugs/bug434.go
new file mode 100644
index 0000000..5abb567
--- /dev/null
+++ b/test/fixedbugs/bug434.go
@@ -0,0 +1,32 @@
+// run
+
+// 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 that typed and untyped negative zero floating point constants
+// are treated as equivalent to zero constants.
+
+package main
+
+import "math"
+
+const zero = 0.0
+
+func main() {
+	x := -zero
+	b := math.Float64bits(x)
+	if b != 0 {
+		panic(b)
+	}
+	x = -float64(zero)
+	b = math.Float64bits(x)
+	if b != 0 {
+		panic(b)
+	}
+	v := x
+	b = math.Float64bits(-v)
+	if b != 0x8000000000000000 {
+		panic(b)
+	}
+}
diff --git a/test/fixedbugs/bug435.go b/test/fixedbugs/bug435.go
new file mode 100644
index 0000000..9c30b14
--- /dev/null
+++ b/test/fixedbugs/bug435.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// 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 that a syntax error caused by an unexpected EOF
+// gives an error message with the correct line number.
+//
+// https://code.google.com/p/go/issues/detail?id=3392
+
+package main
+
+func foo() {
+	bar(1, // ERROR "unexpected|missing|undefined"
diff --git a/test/fixedbugs/bug436.go b/test/fixedbugs/bug436.go
new file mode 100644
index 0000000..e848eae
--- /dev/null
+++ b/test/fixedbugs/bug436.go
@@ -0,0 +1,32 @@
+// run
+
+// 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.
+
+// Gccgo used to crash compiling this.
+
+package main
+
+func foo() (int, int) {
+	return 1, 2
+}
+
+var c = b
+var a, b = foo()
+var d = b + 1
+
+func main() {
+	if a != 1 {
+		panic(a)
+	}
+	if b != 2 {
+		panic(b)
+	}
+	if c != 2 {
+		panic(c)
+	}
+	if d != 3 {
+		panic(d)
+	}
+}
diff --git a/test/fixedbugs/bug437.dir/one.go b/test/fixedbugs/bug437.dir/one.go
new file mode 100644
index 0000000..8d3caad
--- /dev/null
+++ b/test/fixedbugs/bug437.dir/one.go
@@ -0,0 +1,18 @@
+// 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 one
+
+type I1 interface {
+	f()
+}
+
+type S1 struct {
+}
+
+func (s S1) f() {
+}
+
+func F1(i1 I1) {
+}
diff --git a/test/fixedbugs/bug437.dir/two.go b/test/fixedbugs/bug437.dir/two.go
new file mode 100644
index 0000000..406dd59
--- /dev/null
+++ b/test/fixedbugs/bug437.dir/two.go
@@ -0,0 +1,11 @@
+// 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 two
+
+import "./one"
+
+type S2 struct {
+	one.S1
+}
diff --git a/test/fixedbugs/bug437.dir/x.go b/test/fixedbugs/bug437.dir/x.go
new file mode 100644
index 0000000..364d017
--- /dev/null
+++ b/test/fixedbugs/bug437.dir/x.go
@@ -0,0 +1,25 @@
+// 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 converting a type defined in a different package to an
+// interface defined in a third package, where the interface has a
+// hidden method.  This used to cause a link error with gccgo.
+
+package main
+
+import (
+	"./one"
+	"./two"
+)
+
+func F(i1 one.I1) {
+	switch v := i1.(type) {
+	case two.S2:
+		one.F1(v)
+	}
+}
+
+func main() {
+	F(nil)
+}
diff --git a/test/fixedbugs/bug437.go b/test/fixedbugs/bug437.go
new file mode 100644
index 0000000..5c4a2ad
--- /dev/null
+++ b/test/fixedbugs/bug437.go
@@ -0,0 +1,11 @@
+// rundir
+
+// 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 converting a type defined in a different package to an
+// interface defined in a third package, where the interface has a
+// hidden method.  This used to cause a link error with gccgo.
+
+package ignored
diff --git a/test/fixedbugs/bug438.go b/test/fixedbugs/bug438.go
new file mode 100644
index 0000000..15d3fda
--- /dev/null
+++ b/test/fixedbugs/bug438.go
@@ -0,0 +1,16 @@
+// compile
+
+// 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.
+
+// Gccgo used to incorrectly give an error when compiling this.
+
+package p
+
+func F() (i int) {
+	for first := true; first; first = false {
+		i++
+	}
+	return
+}
diff --git a/test/fixedbugs/bug439.go b/test/fixedbugs/bug439.go
new file mode 100644
index 0000000..87d4ae0
--- /dev/null
+++ b/test/fixedbugs/bug439.go
@@ -0,0 +1,22 @@
+// compile
+
+// 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.
+
+// Gccgo used to crash compiling this.
+
+package p
+
+type E int
+
+func (e E) P() *E { return &e }
+
+const (
+	C1 E = 0
+	C2 = C1
+)
+
+func F() *E {
+	return C2.P()
+}
diff --git a/test/fixedbugs/bug440_32.go b/test/fixedbugs/bug440_32.go
new file mode 100644
index 0000000..2d26fbb
--- /dev/null
+++ b/test/fixedbugs/bug440_32.go
@@ -0,0 +1,21 @@
+// run
+
+// Test for 8g register move bug.  The optimizer gets confused
+// about 16- vs 32-bit moves during splitContractIndex.
+
+// Issue 3910.
+
+package main
+
+func main() {
+	const c = 0x12345678
+	index, n, offset := splitContractIndex(c)
+	if index != int((c&0xffff)>>5) || n != int(c&(1<<5-1)) || offset != (c>>16)&(1<<14-1) {
+		println("BUG", index, n, offset)
+	}
+}
+
+func splitContractIndex(ce uint32) (index, n, offset int) {
+	h := uint16(ce)
+	return int(h >> 5), int(h & (1<<5 - 1)), int(ce>>16) & (1<<14 - 1)
+}
diff --git a/test/fixedbugs/bug440_64.go b/test/fixedbugs/bug440_64.go
new file mode 100644
index 0000000..3ab3e56
--- /dev/null
+++ b/test/fixedbugs/bug440_64.go
@@ -0,0 +1,21 @@
+// run
+
+// Test for 6g register move bug.  The optimizer gets confused
+// about 32- vs 64-bit moves during splitContractIndex.
+
+// Issue 3918.
+
+package main
+
+func main() {
+	const c = 0x123400005678
+	index, offset := splitContractIndex(c)
+	if index != (c&0xffffffff)>>5 || offset != c+1 {
+		println("BUG", index, offset)
+	}
+}
+
+func splitContractIndex(ce uint64) (index uint32, offset uint64) {
+	h := uint32(ce)
+	return h >> 5, ce + 1
+}
diff --git a/test/fixedbugs/bug444.go b/test/fixedbugs/bug444.go
index 0bbd16f..b54fb4f 100644
--- a/test/fixedbugs/bug444.go
+++ b/test/fixedbugs/bug444.go
@@ -6,6 +6,7 @@
 
 // The no-op conversion here used to confuse the compiler
 // into doing a load-effective-address of nil.
+// See issue 3670.
 
 package main
 
@@ -13,7 +14,23 @@ import "reflect"
 
 type T interface {}
 
+var x bool
+
 func main() {
         reflect.TypeOf(nil)
-        reflect.TypeOf(T(nil)) // used to fail
+        reflect.TypeOf(T(nil)) // used to miscompile
+        shouldPanic()
+}
+
+func f() byte {
+	return []byte(nil)[0] // used to miscompile
+}
+
+func shouldPanic() {
+	defer func() {
+		if recover() == nil {
+			panic("not panicking")
+		}
+	}()
+	f()
 }
diff --git a/test/fixedbugs/bug445.go b/test/fixedbugs/bug445.go
new file mode 100644
index 0000000..497ecd3
--- /dev/null
+++ b/test/fixedbugs/bug445.go
@@ -0,0 +1,14 @@
+// compile
+
+// 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.
+
+// Issue 3765
+
+package main
+
+func f(x uint) uint {
+	m := ^(1 << x)
+	return uint(m)
+}
diff --git a/test/fixedbugs/bug446.go b/test/fixedbugs/bug446.go
new file mode 100644
index 0000000..1e435e1
--- /dev/null
+++ b/test/fixedbugs/bug446.go
@@ -0,0 +1,36 @@
+// run
+
+// 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.
+
+// Issue 3824.
+// Method calls are ignored when deciding initialization
+// order.
+
+package main
+
+type T int
+
+func (r T) Method1() int { return a }
+func (r T) Method2() int { return b }
+
+// dummy1 and dummy2 must be initialized after a and b.
+var dummy1 = T(0).Method1()
+var dummy2 = T.Method2(0)
+
+// Use a function call to force generating code.
+var a = identity(1)
+var b = identity(2)
+
+func identity(a int) int { return a }
+
+func main() {
+	if dummy1 != 1 {
+		panic("dummy1 != 1")
+	}
+	if dummy2 != 2 {
+		panic("dummy2 != 2")
+	}
+}
+
diff --git a/test/fixedbugs/bug447.go b/test/fixedbugs/bug447.go
new file mode 100644
index 0000000..a4c871b
--- /dev/null
+++ b/test/fixedbugs/bug447.go
@@ -0,0 +1,105 @@
+// runoutput
+
+// 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.
+
+// Issue 3804
+// test all possible float -> integer conversions
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+)
+
+var (
+	intWidths = []int{8, 16, 32, 64} // int%d and uint%d
+	floatWidths = []int{32, 64} // float%d
+)
+
+func main() {
+
+	var names, funcs bytes.Buffer
+
+	for _, iWidth := range intWidths {
+		for _, typ := range []string{"int", "uint"} {
+			var segs bytes.Buffer
+			itype := fmt.Sprintf("%s%d", typ, iWidth)
+			names.WriteString("\ttest" + itype + ",\n")
+			for _, fWidth := range floatWidths {
+				ftype := fmt.Sprintf("float%d", fWidth)
+				seg := strings.Replace(testSegment, "$F", ftype, -1)
+				seg = strings.Replace(seg, "$I", itype, -1)
+				segs.WriteString(seg)
+			}
+			body := strings.Replace(testFunc, "$I", itype, -1)
+			if typ[0] == 'u' {
+				body = strings.Replace(body, "$TEST", " || i < 0", 1)
+			} else {
+				body = strings.Replace(body, "$TEST", "", 1)
+			}
+			body = strings.Replace(body, "$TESTSEGMENTS", segs.String(), 1)
+			funcs.WriteString(body)
+		}
+	}
+
+	program = strings.Replace(program, "$NAMES", names.String(), 1)
+	program = strings.Replace(program, "$FUNCS", funcs.String(), 1)
+	fmt.Print(program)
+}
+
+const testSegment = `
+	f$F := $F(f)
+	if math.Abs(float64(f$F) - f) < 0.05 {
+		if v := $I(f$F); v != $I(i) {
+			fmt.Printf("$I($F(%f)) = %v, expected %v\n", f, v, i)
+		}
+	}`
+
+const testFunc =
+`func test$I(f float64, i int64) {
+	if i != int64($I(i))$TEST {
+		return
+	}
+$TESTSEGMENTS
+}
+`
+
+var program =
+`package main
+
+import (
+	"fmt"
+	"math"
+)
+
+var tests = []struct {
+	f float64
+	i int64
+}{
+	{39.7, 39},
+	{-39.7, -39},
+	{258.6, 258},
+	{-258.6, -258},
+	{65538.9, 65538},
+	{-65538.9, -65538},
+	{4294967298.8, 4294967298},
+	{-4294967298.8, -4294967298},
+}
+
+var funcs = []func(float64, int64){
+$NAMES
+}
+
+$FUNCS
+func main() {
+	for _, t := range tests {
+		for _, f := range funcs {
+			f(t.f, t.i)
+		}
+	}
+}
+`
diff --git a/test/fixedbugs/bug448.dir/pkg1.go b/test/fixedbugs/bug448.dir/pkg1.go
new file mode 100644
index 0000000..032e5d9
--- /dev/null
+++ b/test/fixedbugs/bug448.dir/pkg1.go
@@ -0,0 +1,11 @@
+// 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 pkg1
+
+var x = make(chan interface{})
+
+func Do() int {
+	return (<-x).(int)
+}
diff --git a/test/fixedbugs/bug448.dir/pkg2.go b/test/fixedbugs/bug448.dir/pkg2.go
new file mode 100644
index 0000000..5c78c7d
--- /dev/null
+++ b/test/fixedbugs/bug448.dir/pkg2.go
@@ -0,0 +1,14 @@
+// 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.
+
+// Issue 3843: inlining bug due to wrong receive operator precedence.
+
+package pkg2
+
+import "./pkg1"
+
+func F() {
+	pkg1.Do()
+}
+
diff --git a/test/fixedbugs/bug448.go b/test/fixedbugs/bug448.go
new file mode 100644
index 0000000..242f599
--- /dev/null
+++ b/test/fixedbugs/bug448.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// 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 ignored
diff --git a/test/fixedbugs/bug449.go b/test/fixedbugs/bug449.go
new file mode 100644
index 0000000..a9650f4
--- /dev/null
+++ b/test/fixedbugs/bug449.go
@@ -0,0 +1,69 @@
+// runoutput
+
+// 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.
+
+// Issue 3866
+// runtime.equal failed to take padding between arguments and
+// return values into account, so in certain cases gc-generated
+// code will read a random bool from the stack as the result of
+// the comparison.
+// This program generates a lot of equality tests and hopes to
+// catch this.
+// NOTE: this program assumes comparing instance of T and T's
+// underlying []byte will make gc emit calls to runtime.equal,
+// and if gc optimizes this case, then the test will no longer
+// be correct (in the sense that it no longer tests runtime.equal).
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+const ntest = 1024
+
+func main() {
+	var decls, calls bytes.Buffer
+
+	for i := 1; i <= ntest; i++ {
+		s := strconv.Itoa(i)
+		decls.WriteString(strings.Replace(decl, "$", s, -1))
+		calls.WriteString(strings.Replace("call(test$)\n\t", "$", s, -1))
+	}
+
+	program = strings.Replace(program, "$DECLS", decls.String(), 1)
+	program = strings.Replace(program, "$CALLS", calls.String(), 1)
+	fmt.Print(program)
+}
+
+var program = `package main
+
+var count int
+
+func call(f func() bool) {
+	if f() {
+		count++
+	}
+}
+
+$DECLS
+
+func main() {
+	$CALLS
+	if count != 0 {
+		println("failed", count, "case(s)")
+	}
+}
+`
+
+const decl = `
+type T$ [$]uint8
+func test$() bool {
+	v := T${1}
+	return v == [$]uint8{2} || v != [$]uint8{1}
+}`
diff --git a/test/fixedbugs/bug450.go b/test/fixedbugs/bug450.go
new file mode 100644
index 0000000..3f13de1
--- /dev/null
+++ b/test/fixedbugs/bug450.go
@@ -0,0 +1,28 @@
+// run
+
+// 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.
+
+// Issue 3899: 8g incorrectly thinks a variable is
+// "set but not used" and elides an assignment, causing
+// variables to end up with wrong data.
+//
+// The reason is a miscalculation of variable width.
+
+package main
+
+func bar(f func()) {
+	f()
+}
+
+func foo() {
+	f := func() {}
+	if f == nil {
+	}
+	bar(f)
+}
+
+func main() {
+	foo()
+}
diff --git a/test/fixedbugs/bug451.go b/test/fixedbugs/bug451.go
new file mode 100644
index 0000000..75ce974
--- /dev/null
+++ b/test/fixedbugs/bug451.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// 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 main
+
+type T x.T // ERROR "undefined|expected package"
+
+// bogus "invalid recursive type"
diff --git a/test/fixedbugs/bug452.go b/test/fixedbugs/bug452.go
new file mode 100644
index 0000000..d2e4a0b
--- /dev/null
+++ b/test/fixedbugs/bug452.go
@@ -0,0 +1,38 @@
+// run
+
+// 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.
+
+// Issue 3835: 8g tries to optimize arithmetic involving integer
+// constants, but can run out of registers in the process.
+
+package main
+
+var a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G int
+
+func foo() int {
+	return a + 1 + b + 2 + c + 3 + d + 4 + e + 5 + f + 6 + g + 7 + h + 8 + i + 9 + j + 10 +
+		k + 1 + l + 2 + m + 3 + n + 4 + o + 5 + p + 6 + q + 7 + r + 8 + s + 9 + t + 10 +
+		u + 1 + v + 2 + w + 3 + x + 4 + y + 5 + z + 6 + A + 7 + B + 8 + C + 9 + D + 10 +
+		E + 1 + F + 2 + G + 3
+}
+
+func bar() int8 {
+	var (
+		W int16
+		X int32
+		Y int32
+		Z int32
+	)
+	return int8(W+int16(X+3)+3) * int8(Y+3+Z*3)
+}
+
+func main() {
+	if foo() == 0 {
+		panic("foo")
+	}
+	if bar() == 0 {
+		panic("bar")
+	}
+}
diff --git a/test/fixedbugs/bug453.go b/test/fixedbugs/bug453.go
new file mode 100644
index 0000000..136abef
--- /dev/null
+++ b/test/fixedbugs/bug453.go
@@ -0,0 +1,39 @@
+// run
+
+// 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.
+
+// Issue 4138: bug in floating-point registers numbering.
+// Makes 6g unable to use more than 11 registers.
+
+package main
+
+func formula() float32 {
+	mA := [1]float32{1.0}
+	det1 := mA[0]
+	det2 := mA[0]
+	det3 := mA[0]
+	det4 := mA[0]
+	det5 := mA[0]
+	det6 := mA[0]
+	det7 := mA[0]
+	det8 := mA[0]
+	det9 := mA[0]
+	det10 := mA[0]
+	det11 := mA[0]
+	det12 := mA[0]
+
+	return det1 + det2*det3 +
+		det4*det5 + det6*det7 +
+		det8*det9 + det10*det11 +
+		det12
+}
+
+func main() {
+	x := formula()
+	if x != 7.0 {
+		println(x, 7.0)
+		panic("x != 7.0")
+	}
+}
diff --git a/test/fixedbugs/bug454.go b/test/fixedbugs/bug454.go
new file mode 100644
index 0000000..a10abba
--- /dev/null
+++ b/test/fixedbugs/bug454.go
@@ -0,0 +1,21 @@
+// run
+
+// 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.
+
+// Issue 4173
+
+package main
+
+func main() {
+	var arr *[10]int
+	s := 0
+	for i, _ := range arr {
+		// used to panic trying to access arr[i]
+		s += i
+	}
+	if s != 45 {
+		println("BUG")
+	}
+}
diff --git a/test/fixedbugs/bug455.go b/test/fixedbugs/bug455.go
new file mode 100644
index 0000000..8e3c770
--- /dev/null
+++ b/test/fixedbugs/bug455.go
@@ -0,0 +1,54 @@
+// run
+
+// 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.
+
+// Issue 4156: out of fixed registers when chaining method calls.
+// Used to happen with 6g.
+
+package main
+
+type test_i interface {
+	Test() test_i
+	Result() bool
+}
+
+type test_t struct {
+}
+
+func newTest() *test_t {
+	return &test_t{}
+}
+
+type testFn func(string) testFn
+
+func main() {
+	test := newTest()
+
+	switch {
+	case test.
+		Test().
+		Test().
+		Test().
+		Test().
+		Test().
+		Test().
+		Test().
+		Test().
+		Test().
+		Test().
+		Result():
+		// case worked
+	default:
+		panic("Result returned false unexpectedly")
+	}
+}
+
+func (t *test_t) Test() test_i {
+	return t
+}
+
+func (t *test_t) Result() bool {
+	return true
+}
diff --git a/test/fixedbugs/bug456.go b/test/fixedbugs/bug456.go
new file mode 100644
index 0000000..064e1aa
--- /dev/null
+++ b/test/fixedbugs/bug456.go
@@ -0,0 +1,26 @@
+// run
+
+// 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.
+
+// Issue 3907: out of fixed registers in nested byte multiply.
+// Used to happen with both 6g and 8g.
+
+package main
+
+func F(a, b, c, d uint8) uint8 {
+	return a * (b * (c * (d *
+		(a * (b * (c * (d *
+			(a * (b * (c * (d *
+				a * (b * (c * d)))))))))))))
+}
+
+func main() {
+	var a, b, c, d uint8 = 1, 1, 1, 1
+	x := F(a, b, c, d)
+	if x != 1 {
+		println(x)
+		panic("x != 1")
+	}
+}
diff --git a/test/fixedbugs/bug457.go b/test/fixedbugs/bug457.go
new file mode 100644
index 0000000..ee70489
--- /dev/null
+++ b/test/fixedbugs/bug457.go
@@ -0,0 +1,15 @@
+// run
+
+// 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.
+
+// Issue 4197: growing a slice of zero-width elements
+// panics on a division by zero.
+
+package main
+
+func main() {
+	var x []struct{}
+	x = append(x, struct{}{})
+}
diff --git a/test/fixedbugs/bug458.go b/test/fixedbugs/bug458.go
new file mode 100644
index 0000000..ddc97bd
--- /dev/null
+++ b/test/fixedbugs/bug458.go
@@ -0,0 +1,22 @@
+// compile
+
+// 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.
+
+// Issue 4200: 6g crashes when a type is larger than 4GB.
+
+package main
+
+import "unsafe"
+
+// N=16 on 32-bit arches, 256 on 64-bit arches.
+// On 32-bit arches we don't want to test types
+// that are over 4GB large.
+const N = 1 << unsafe.Sizeof(uintptr(0))
+
+type T [N][10][10][10][10][3]byte
+
+func F(t *T) byte {
+	return t[0][0][0][0][0][0]
+}
diff --git a/test/fixedbugs/bug459.go b/test/fixedbugs/bug459.go
new file mode 100644
index 0000000..80abe5d
--- /dev/null
+++ b/test/fixedbugs/bug459.go
@@ -0,0 +1,35 @@
+// errorcheck
+
+// 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.
+
+// Issue 3890: missing detection of init loop involving
+// method calls in function bodies.
+
+package flag
+
+var commandLine = NewFlagSet() // ERROR "loop"
+
+type FlagSet struct {
+}
+
+func (f *FlagSet) failf(format string, a ...interface{}) {
+	f.usage()
+}
+
+func (f *FlagSet) usage() {
+	if f == commandLine {
+		panic(3)
+	}
+}
+
+func NewFlagSet() *FlagSet {
+	f := &FlagSet{}
+	f.setErrorHandling(true)
+	return f
+}
+
+func (f *FlagSet) setErrorHandling(b bool) {
+	f.failf("DIE")
+}
diff --git a/test/fixedbugs/bug460.dir/a.go b/test/fixedbugs/bug460.dir/a.go
new file mode 100644
index 0000000..02a287b
--- /dev/null
+++ b/test/fixedbugs/bug460.dir/a.go
@@ -0,0 +1,9 @@
+// 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 a
+
+type Foo struct {
+	int
+}
diff --git a/test/fixedbugs/bug460.dir/b.go b/test/fixedbugs/bug460.dir/b.go
new file mode 100644
index 0000000..1868afe
--- /dev/null
+++ b/test/fixedbugs/bug460.dir/b.go
@@ -0,0 +1,14 @@
+// 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 b
+
+import "./a"
+
+var x a.Foo
+
+func main() {
+	x.int = 20 // ERROR "unexported field"
+}
+
diff --git a/test/fixedbugs/bug460.go b/test/fixedbugs/bug460.go
new file mode 100644
index 0000000..79234a3
--- /dev/null
+++ b/test/fixedbugs/bug460.go
@@ -0,0 +1,10 @@
+// errorcheckdir
+
+// 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.
+
+// part one of issue 4124. Make sure that the compiler rejects access attempts.
+
+package ignored
+
diff --git a/test/fixedbugs/bug461.go b/test/fixedbugs/bug461.go
new file mode 100644
index 0000000..f0f7b0e
--- /dev/null
+++ b/test/fixedbugs/bug461.go
@@ -0,0 +1,23 @@
+// run
+
+// 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.
+
+// part two of issue 4124. Make sure reflect doesn't mark the field as exported.
+
+package main
+
+import "reflect"
+
+var T struct {
+	int
+}
+
+func main() {
+	v := reflect.ValueOf(&T)
+	v = v.Elem().Field(0)
+	if v.CanSet() {
+		panic("int should be unexported")
+	}
+}
diff --git a/test/fixedbugs/bug462.go b/test/fixedbugs/bug462.go
new file mode 100644
index 0000000..6434255
--- /dev/null
+++ b/test/fixedbugs/bug462.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// 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 main
+
+import "os"
+
+type T struct {
+	File int
+}
+
+func main() {
+	_ = T {
+		os.File: 1, // ERROR "unknown T field"
+	}
+}
diff --git a/test/fixedbugs/bug463.go b/test/fixedbugs/bug463.go
new file mode 100644
index 0000000..3e7a184
--- /dev/null
+++ b/test/fixedbugs/bug463.go
@@ -0,0 +1,22 @@
+// errorcheck
+
+// 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.
+
+// Issue 3757: unhelpful typechecking loop message
+// for constants that refer to themselves.
+
+package main
+
+const a = a // ERROR "refers to itself|definition loop"
+
+const (
+	X    = A
+	A    = B // ERROR "refers to itself|definition loop"
+	B    = D
+	C, D = 1, A
+)
+
+func main() {
+}
diff --git a/test/fixedbugs/bug464.go b/test/fixedbugs/bug464.go
new file mode 100644
index 0000000..5821939
--- /dev/null
+++ b/test/fixedbugs/bug464.go
@@ -0,0 +1,12 @@
+// errorcheck
+
+// 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.
+
+// Issue 3937: unhelpful typechecking loop message
+// for identifiers wrongly used as types.
+
+package main
+
+func foo(x foo) {} // ERROR "expected type|not a type"
diff --git a/test/fixedbugs/bug465.dir/a.go b/test/fixedbugs/bug465.dir/a.go
new file mode 100644
index 0000000..c5d410d
--- /dev/null
+++ b/test/fixedbugs/bug465.dir/a.go
@@ -0,0 +1,61 @@
+// 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 a
+
+type T struct{ A, B int }
+
+type A []int
+
+type M map[int]int
+
+func F1() int {
+	if (T{1, 2}) == (T{3, 4}) {
+		return 1
+	}
+	return 0
+}
+
+func F2() int {
+	if (M{1: 2}) == nil {
+		return 1
+	}
+	return 0
+}
+
+func F3() int {
+	if nil == (A{}) {
+		return 1
+	}
+	return 0
+}
+
+func F4() int {
+	if a := (A{}); a == nil {
+		return 1
+	}
+	return 0
+}
+
+func F5() int {
+	for k, v := range (M{1: 2}) {
+		return v - k
+	}
+	return 0
+}
+
+func F6() int {
+	switch a := (T{1, 1}); a == (T{1, 2}) {
+	default:
+		return 1
+	}
+	return 0
+}
+
+func F7() int {
+	for m := (M{}); len(m) < (T{1, 2}).A; m[1] = (A{1})[0] {
+		return 1
+	}
+	return 0
+}
diff --git a/test/fixedbugs/bug465.dir/b.go b/test/fixedbugs/bug465.dir/b.go
new file mode 100644
index 0000000..0f4909f
--- /dev/null
+++ b/test/fixedbugs/bug465.dir/b.go
@@ -0,0 +1,17 @@
+// 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 main
+
+import "./a"
+
+func main() {
+	for _, f := range []func() int{
+		a.F1, a.F2, a.F3, a.F4,
+		a.F5, a.F6, a.F7} {
+		if f() > 1 {
+			panic("f() > 1")
+		}
+	}
+}
diff --git a/test/fixedbugs/bug465.go b/test/fixedbugs/bug465.go
new file mode 100644
index 0000000..a6ef587
--- /dev/null
+++ b/test/fixedbugs/bug465.go
@@ -0,0 +1,10 @@
+// rundir
+
+// 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.
+
+// Issue 4230: inlining bug for composite literal in
+// if, for, switch statements.
+
+package ignored
diff --git a/test/fixedbugs/bug466.dir/a.go b/test/fixedbugs/bug466.dir/a.go
new file mode 100644
index 0000000..b9de63e
--- /dev/null
+++ b/test/fixedbugs/bug466.dir/a.go
@@ -0,0 +1,15 @@
+// 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 a
+
+const N = 2+3i
+
+func Func() []complex128 {
+	return []complex128{1, complex(2, 3), complex(4, 5)}
+}
+
+func Mul(z complex128) complex128 {
+	return z * (3 + 4i)
+}
diff --git a/test/fixedbugs/bug466.dir/b.go b/test/fixedbugs/bug466.dir/b.go
new file mode 100644
index 0000000..82d66ea
--- /dev/null
+++ b/test/fixedbugs/bug466.dir/b.go
@@ -0,0 +1,30 @@
+// 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 main
+
+import "./a"
+
+func main() {
+	s := a.Func()
+	if s[0] != 1 {
+		println(s[0])
+		panic("s[0] != 1")
+	}
+	if s[1] != 2+3i {
+		println(s[1])
+		panic("s[1] != 2+3i")
+	}
+	if s[2] != 4+5i {
+		println(s[2])
+		panic("s[2] != 4+5i")
+	}
+
+	x := 1 + 2i
+	y := a.Mul(x)
+	if y != (1+2i)*(3+4i) {
+		println(y)
+		panic("y != (1+2i)*(3+4i)")
+	}
+}
diff --git a/test/fixedbugs/bug466.go b/test/fixedbugs/bug466.go
new file mode 100644
index 0000000..6b65b33
--- /dev/null
+++ b/test/fixedbugs/bug466.go
@@ -0,0 +1,11 @@
+// rundir
+
+// 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.
+
+// Issue 4159: exported inlinable functions squash
+// complex literals "a+bi" to "a+b".
+
+package ignored
+
diff --git a/test/fixedbugs/bug467.dir/p1.go b/test/fixedbugs/bug467.dir/p1.go
new file mode 100644
index 0000000..538b554
--- /dev/null
+++ b/test/fixedbugs/bug467.dir/p1.go
@@ -0,0 +1,5 @@
+package p1
+
+type SockaddrUnix int
+
+func (s SockaddrUnix) Error() string { return "blah" }
diff --git a/test/fixedbugs/bug467.dir/p2.go b/test/fixedbugs/bug467.dir/p2.go
new file mode 100644
index 0000000..d80d3a3
--- /dev/null
+++ b/test/fixedbugs/bug467.dir/p2.go
@@ -0,0 +1,5 @@
+package p2
+
+import "./p1"
+
+func SockUnix() error { var s *p1.SockaddrUnix; return s }
diff --git a/test/fixedbugs/bug467.dir/p3.go b/test/fixedbugs/bug467.dir/p3.go
new file mode 100644
index 0000000..c795646
--- /dev/null
+++ b/test/fixedbugs/bug467.dir/p3.go
@@ -0,0 +1,7 @@
+package main
+
+import "./p2"
+
+func main() {
+	_ = p2.SockUnix()
+}
diff --git a/test/fixedbugs/bug467.go b/test/fixedbugs/bug467.go
new file mode 100644
index 0000000..d73adba
--- /dev/null
+++ b/test/fixedbugs/bug467.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// 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.
+
+// Exported data for inlining could forget types of
+// local variables declared in inlinable bodies.
+
+package ignored
diff --git a/test/fixedbugs/bug468.dir/p1.go b/test/fixedbugs/bug468.dir/p1.go
new file mode 100644
index 0000000..ca17577
--- /dev/null
+++ b/test/fixedbugs/bug468.dir/p1.go
@@ -0,0 +1,7 @@
+// 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 p1
+
+type S struct { X, Y int }
diff --git a/test/fixedbugs/bug468.dir/p2.go b/test/fixedbugs/bug468.dir/p2.go
new file mode 100644
index 0000000..1793c0e
--- /dev/null
+++ b/test/fixedbugs/bug468.dir/p2.go
@@ -0,0 +1,25 @@
+// 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 main
+
+import (
+	"reflect"
+
+	"./p1"
+)
+
+func main() {
+	var v1 = p1.S{1, 2}
+	var v2 = struct { X, Y int }{1, 2}
+	v1 = v2
+	t1 := reflect.TypeOf(v1)
+	t2 := reflect.TypeOf(v2)
+	if !t1.AssignableTo(t2) {
+		panic(0)
+	}
+	if !t2.AssignableTo(t1) {
+		panic(1)
+	}
+}
diff --git a/test/fixedbugs/bug468.go b/test/fixedbugs/bug468.go
new file mode 100644
index 0000000..12e4997
--- /dev/null
+++ b/test/fixedbugs/bug468.go
@@ -0,0 +1,10 @@
+// rundir
+
+// 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.
+
+// The reflect package was not correctly checking field names
+// when checking for struct assignability.
+
+package ignored
diff --git a/test/fixedbugs/bug469.go b/test/fixedbugs/bug469.go
new file mode 100644
index 0000000..71157a4
--- /dev/null
+++ b/test/fixedbugs/bug469.go
@@ -0,0 +1,13 @@
+// compile
+
+// 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.
+
+// The gccgo compiler would complain about a redefinition of i, but
+// the spec imposes no requirements on parameter names in a function
+// type.
+
+package p
+
+type F func(i int) (i int)
diff --git a/test/fixedbugs/bug470.go b/test/fixedbugs/bug470.go
new file mode 100644
index 0000000..0a35918
--- /dev/null
+++ b/test/fixedbugs/bug470.go
@@ -0,0 +1,26 @@
+// run
+
+// 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.
+
+// Converting constants between types must introduce rounding.
+
+package main
+
+import "fmt"
+
+const (
+    F32 = 0.00999999977648258209228515625
+    F64 = 0.01000000000000000020816681711721685132943093776702880859375
+)
+
+var F = float64(float32(0.01))
+
+func main() {
+	// 0.01 rounded to float32 then to float64 is F32.
+	// 0.01 represented directly in float64 is F64.
+	if F != F32 {
+		panic(fmt.Sprintf("F=%.1000g, want %.1000g", F, F32))
+	}
+}
diff --git a/test/fixedbugs/bug471.go b/test/fixedbugs/bug471.go
new file mode 100644
index 0000000..e454259
--- /dev/null
+++ b/test/fixedbugs/bug471.go
@@ -0,0 +1,18 @@
+// compile
+
+// 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.
+
+// Caused an internal compiler error in gccgo.
+
+package p
+
+type C chan struct{}
+
+func (c C) F() {
+	select {
+	case c <- struct{}{}:
+	default:
+	}
+}
diff --git a/test/fixedbugs/bug472.dir/p1.go b/test/fixedbugs/bug472.dir/p1.go
new file mode 100644
index 0000000..9d47fd8
--- /dev/null
+++ b/test/fixedbugs/bug472.dir/p1.go
@@ -0,0 +1,17 @@
+// 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 p1
+
+import "runtime"
+
+func E() func() int { return runtime.NumCPU }
+
+func F() func() { return runtime.Gosched }
+
+func G() func() string { return runtime.GOROOT }
+
+func H() func() { return runtime.GC }
+
+func I() func() string { return runtime.Version }
diff --git a/test/fixedbugs/bug472.dir/p2.go b/test/fixedbugs/bug472.dir/p2.go
new file mode 100644
index 0000000..34a3f04
--- /dev/null
+++ b/test/fixedbugs/bug472.dir/p2.go
@@ -0,0 +1,17 @@
+// 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 p2
+
+import "runtime"
+
+func E() func() int { return runtime.NumCPU }
+
+func F() func() { return runtime.GC }
+
+func G() func() string { return runtime.GOROOT }
+
+func H() func() { return runtime.Gosched }
+
+func I() func() string { return runtime.Version }
diff --git a/test/fixedbugs/bug472.dir/z.go b/test/fixedbugs/bug472.dir/z.go
new file mode 100644
index 0000000..6c29dd0
--- /dev/null
+++ b/test/fixedbugs/bug472.dir/z.go
@@ -0,0 +1,13 @@
+// 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 main
+
+import (
+	_ "./p1"
+	_ "./p2"
+)
+
+func main() {
+}
diff --git a/test/fixedbugs/bug472.go b/test/fixedbugs/bug472.go
new file mode 100644
index 0000000..c79c64c
--- /dev/null
+++ b/test/fixedbugs/bug472.go
@@ -0,0 +1,10 @@
+// rundir
+
+// 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.
+
+// Linker would incorrectly parse export data and think
+// definitions are inconsistent.
+
+package ignored
diff --git a/test/fixedbugs/bug473.go b/test/fixedbugs/bug473.go
new file mode 100644
index 0000000..49ce7d7
--- /dev/null
+++ b/test/fixedbugs/bug473.go
@@ -0,0 +1,69 @@
+// 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.
+
+// Used to be miscompiled by gccgo, due to a bug in handling
+// initialization ordering.
+
+package main
+
+func F(a ...interface{}) interface{} {
+	s := 0
+	for _, v := range a {
+		s += v.(int)
+	}
+	return s
+}
+
+var V1 = F(V10, V4, V3, V11)
+
+var V2 = F(V1)
+
+var V3 = F(1)
+
+var V4 = F(2)
+
+var V5 = F(3)
+
+var V6 = F(4)
+
+var V7 = F(5)
+
+var V8 = F(V14, V7, V3, V6, V5)
+
+var V9 = F(V4, F(V12))
+
+var V10 = F(V4, V9)
+
+var V11 = F(6)
+
+var V12 = F(V5, V3, V8)
+
+var V13 = F(7)
+
+var V14 = F(8)
+
+func expect(name string, a interface{}, b int) {
+	if a.(int) != b {
+		panic(name)
+	}
+}
+
+func main() {
+	expect("V1", V1, 38)
+	expect("V2", V2, 38)
+	expect("V3", V3, 1)
+	expect("V4", V4, 2)
+	expect("V5", V5, 3)
+	expect("V6", V6, 4)
+	expect("V7", V7, 5)
+	expect("V8", V8, 21)
+	expect("V9", V9, 27)
+	expect("V10", V10, 29)
+	expect("V11", V11, 6)
+	expect("V12", V12, 25)
+	expect("V13", V13, 7)
+	expect("V14", V14, 8)
+}
diff --git a/test/fixedbugs/issue2615.go b/test/fixedbugs/issue2615.go
new file mode 100644
index 0000000..686e1e1
--- /dev/null
+++ b/test/fixedbugs/issue2615.go
@@ -0,0 +1,547 @@
+// run
+
+// 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.
+
+// Issue 2615: a long chain of else if's causes an overflow
+// in the parser stack.
+
+package main
+
+// test returns the index of the lowest set bit in a 256-bit vector.
+func test(x [4]uint64) int {
+	if x[0]&(1<<0) != 0 {
+		return 0
+	} else if x[0]&(1<<1) != 0 {
+		return 1
+	} else if x[0]&(1<<2) != 0 {
+		return 2
+	} else if x[0]&(1<<3) != 0 {
+		return 3
+	} else if x[0]&(1<<4) != 0 {
+		return 4
+	} else if x[0]&(1<<5) != 0 {
+		return 5
+	} else if x[0]&(1<<6) != 0 {
+		return 6
+	} else if x[0]&(1<<7) != 0 {
+		return 7
+	} else if x[0]&(1<<8) != 0 {
+		return 8
+	} else if x[0]&(1<<9) != 0 {
+		return 9
+	} else if x[0]&(1<<10) != 0 {
+		return 10
+	} else if x[0]&(1<<11) != 0 {
+		return 11
+	} else if x[0]&(1<<12) != 0 {
+		return 12
+	} else if x[0]&(1<<13) != 0 {
+		return 13
+	} else if x[0]&(1<<14) != 0 {
+		return 14
+	} else if x[0]&(1<<15) != 0 {
+		return 15
+	} else if x[0]&(1<<16) != 0 {
+		return 16
+	} else if x[0]&(1<<17) != 0 {
+		return 17
+	} else if x[0]&(1<<18) != 0 {
+		return 18
+	} else if x[0]&(1<<19) != 0 {
+		return 19
+	} else if x[0]&(1<<20) != 0 {
+		return 20
+	} else if x[0]&(1<<21) != 0 {
+		return 21
+	} else if x[0]&(1<<22) != 0 {
+		return 22
+	} else if x[0]&(1<<23) != 0 {
+		return 23
+	} else if x[0]&(1<<24) != 0 {
+		return 24
+	} else if x[0]&(1<<25) != 0 {
+		return 25
+	} else if x[0]&(1<<26) != 0 {
+		return 26
+	} else if x[0]&(1<<27) != 0 {
+		return 27
+	} else if x[0]&(1<<28) != 0 {
+		return 28
+	} else if x[0]&(1<<29) != 0 {
+		return 29
+	} else if x[0]&(1<<30) != 0 {
+		return 30
+	} else if x[0]&(1<<31) != 0 {
+		return 31
+	} else if x[0]&(1<<32) != 0 {
+		return 32
+	} else if x[0]&(1<<33) != 0 {
+		return 33
+	} else if x[0]&(1<<34) != 0 {
+		return 34
+	} else if x[0]&(1<<35) != 0 {
+		return 35
+	} else if x[0]&(1<<36) != 0 {
+		return 36
+	} else if x[0]&(1<<37) != 0 {
+		return 37
+	} else if x[0]&(1<<38) != 0 {
+		return 38
+	} else if x[0]&(1<<39) != 0 {
+		return 39
+	} else if x[0]&(1<<40) != 0 {
+		return 40
+	} else if x[0]&(1<<41) != 0 {
+		return 41
+	} else if x[0]&(1<<42) != 0 {
+		return 42
+	} else if x[0]&(1<<43) != 0 {
+		return 43
+	} else if x[0]&(1<<44) != 0 {
+		return 44
+	} else if x[0]&(1<<45) != 0 {
+		return 45
+	} else if x[0]&(1<<46) != 0 {
+		return 46
+	} else if x[0]&(1<<47) != 0 {
+		return 47
+	} else if x[0]&(1<<48) != 0 {
+		return 48
+	} else if x[0]&(1<<49) != 0 {
+		return 49
+	} else if x[0]&(1<<50) != 0 {
+		return 50
+	} else if x[0]&(1<<51) != 0 {
+		return 51
+	} else if x[0]&(1<<52) != 0 {
+		return 52
+	} else if x[0]&(1<<53) != 0 {
+		return 53
+	} else if x[0]&(1<<54) != 0 {
+		return 54
+	} else if x[0]&(1<<55) != 0 {
+		return 55
+	} else if x[0]&(1<<56) != 0 {
+		return 56
+	} else if x[0]&(1<<57) != 0 {
+		return 57
+	} else if x[0]&(1<<58) != 0 {
+		return 58
+	} else if x[0]&(1<<59) != 0 {
+		return 59
+	} else if x[0]&(1<<60) != 0 {
+		return 60
+	} else if x[0]&(1<<61) != 0 {
+		return 61
+	} else if x[0]&(1<<62) != 0 {
+		return 62
+	} else if x[0]&(1<<63) != 0 {
+		return 63
+	} else if x[1]&(1<<0) != 0 {
+		return 64
+	} else if x[1]&(1<<1) != 0 {
+		return 65
+	} else if x[1]&(1<<2) != 0 {
+		return 66
+	} else if x[1]&(1<<3) != 0 {
+		return 67
+	} else if x[1]&(1<<4) != 0 {
+		return 68
+	} else if x[1]&(1<<5) != 0 {
+		return 69
+	} else if x[1]&(1<<6) != 0 {
+		return 70
+	} else if x[1]&(1<<7) != 0 {
+		return 71
+	} else if x[1]&(1<<8) != 0 {
+		return 72
+	} else if x[1]&(1<<9) != 0 {
+		return 73
+	} else if x[1]&(1<<10) != 0 {
+		return 74
+	} else if x[1]&(1<<11) != 0 {
+		return 75
+	} else if x[1]&(1<<12) != 0 {
+		return 76
+	} else if x[1]&(1<<13) != 0 {
+		return 77
+	} else if x[1]&(1<<14) != 0 {
+		return 78
+	} else if x[1]&(1<<15) != 0 {
+		return 79
+	} else if x[1]&(1<<16) != 0 {
+		return 80
+	} else if x[1]&(1<<17) != 0 {
+		return 81
+	} else if x[1]&(1<<18) != 0 {
+		return 82
+	} else if x[1]&(1<<19) != 0 {
+		return 83
+	} else if x[1]&(1<<20) != 0 {
+		return 84
+	} else if x[1]&(1<<21) != 0 {
+		return 85
+	} else if x[1]&(1<<22) != 0 {
+		return 86
+	} else if x[1]&(1<<23) != 0 {
+		return 87
+	} else if x[1]&(1<<24) != 0 {
+		return 88
+	} else if x[1]&(1<<25) != 0 {
+		return 89
+	} else if x[1]&(1<<26) != 0 {
+		return 90
+	} else if x[1]&(1<<27) != 0 {
+		return 91
+	} else if x[1]&(1<<28) != 0 {
+		return 92
+	} else if x[1]&(1<<29) != 0 {
+		return 93
+	} else if x[1]&(1<<30) != 0 {
+		return 94
+	} else if x[1]&(1<<31) != 0 {
+		return 95
+	} else if x[1]&(1<<32) != 0 {
+		return 96
+	} else if x[1]&(1<<33) != 0 {
+		return 97
+	} else if x[1]&(1<<34) != 0 {
+		return 98
+	} else if x[1]&(1<<35) != 0 {
+		return 99
+	} else if x[1]&(1<<36) != 0 {
+		return 100
+	} else if x[1]&(1<<37) != 0 {
+		return 101
+	} else if x[1]&(1<<38) != 0 {
+		return 102
+	} else if x[1]&(1<<39) != 0 {
+		return 103
+	} else if x[1]&(1<<40) != 0 {
+		return 104
+	} else if x[1]&(1<<41) != 0 {
+		return 105
+	} else if x[1]&(1<<42) != 0 {
+		return 106
+	} else if x[1]&(1<<43) != 0 {
+		return 107
+	} else if x[1]&(1<<44) != 0 {
+		return 108
+	} else if x[1]&(1<<45) != 0 {
+		return 109
+	} else if x[1]&(1<<46) != 0 {
+		return 110
+	} else if x[1]&(1<<47) != 0 {
+		return 111
+	} else if x[1]&(1<<48) != 0 {
+		return 112
+	} else if x[1]&(1<<49) != 0 {
+		return 113
+	} else if x[1]&(1<<50) != 0 {
+		return 114
+	} else if x[1]&(1<<51) != 0 {
+		return 115
+	} else if x[1]&(1<<52) != 0 {
+		return 116
+	} else if x[1]&(1<<53) != 0 {
+		return 117
+	} else if x[1]&(1<<54) != 0 {
+		return 118
+	} else if x[1]&(1<<55) != 0 {
+		return 119
+	} else if x[1]&(1<<56) != 0 {
+		return 120
+	} else if x[1]&(1<<57) != 0 {
+		return 121
+	} else if x[1]&(1<<58) != 0 {
+		return 122
+	} else if x[1]&(1<<59) != 0 {
+		return 123
+	} else if x[1]&(1<<60) != 0 {
+		return 124
+	} else if x[1]&(1<<61) != 0 {
+		return 125
+	} else if x[1]&(1<<62) != 0 {
+		return 126
+	} else if x[1]&(1<<63) != 0 {
+		return 127
+	} else if x[2]&(1<<0) != 0 {
+		return 128
+	} else if x[2]&(1<<1) != 0 {
+		return 129
+	} else if x[2]&(1<<2) != 0 {
+		return 130
+	} else if x[2]&(1<<3) != 0 {
+		return 131
+	} else if x[2]&(1<<4) != 0 {
+		return 132
+	} else if x[2]&(1<<5) != 0 {
+		return 133
+	} else if x[2]&(1<<6) != 0 {
+		return 134
+	} else if x[2]&(1<<7) != 0 {
+		return 135
+	} else if x[2]&(1<<8) != 0 {
+		return 136
+	} else if x[2]&(1<<9) != 0 {
+		return 137
+	} else if x[2]&(1<<10) != 0 {
+		return 138
+	} else if x[2]&(1<<11) != 0 {
+		return 139
+	} else if x[2]&(1<<12) != 0 {
+		return 140
+	} else if x[2]&(1<<13) != 0 {
+		return 141
+	} else if x[2]&(1<<14) != 0 {
+		return 142
+	} else if x[2]&(1<<15) != 0 {
+		return 143
+	} else if x[2]&(1<<16) != 0 {
+		return 144
+	} else if x[2]&(1<<17) != 0 {
+		return 145
+	} else if x[2]&(1<<18) != 0 {
+		return 146
+	} else if x[2]&(1<<19) != 0 {
+		return 147
+	} else if x[2]&(1<<20) != 0 {
+		return 148
+	} else if x[2]&(1<<21) != 0 {
+		return 149
+	} else if x[2]&(1<<22) != 0 {
+		return 150
+	} else if x[2]&(1<<23) != 0 {
+		return 151
+	} else if x[2]&(1<<24) != 0 {
+		return 152
+	} else if x[2]&(1<<25) != 0 {
+		return 153
+	} else if x[2]&(1<<26) != 0 {
+		return 154
+	} else if x[2]&(1<<27) != 0 {
+		return 155
+	} else if x[2]&(1<<28) != 0 {
+		return 156
+	} else if x[2]&(1<<29) != 0 {
+		return 157
+	} else if x[2]&(1<<30) != 0 {
+		return 158
+	} else if x[2]&(1<<31) != 0 {
+		return 159
+	} else if x[2]&(1<<32) != 0 {
+		return 160
+	} else if x[2]&(1<<33) != 0 {
+		return 161
+	} else if x[2]&(1<<34) != 0 {
+		return 162
+	} else if x[2]&(1<<35) != 0 {
+		return 163
+	} else if x[2]&(1<<36) != 0 {
+		return 164
+	} else if x[2]&(1<<37) != 0 {
+		return 165
+	} else if x[2]&(1<<38) != 0 {
+		return 166
+	} else if x[2]&(1<<39) != 0 {
+		return 167
+	} else if x[2]&(1<<40) != 0 {
+		return 168
+	} else if x[2]&(1<<41) != 0 {
+		return 169
+	} else if x[2]&(1<<42) != 0 {
+		return 170
+	} else if x[2]&(1<<43) != 0 {
+		return 171
+	} else if x[2]&(1<<44) != 0 {
+		return 172
+	} else if x[2]&(1<<45) != 0 {
+		return 173
+	} else if x[2]&(1<<46) != 0 {
+		return 174
+	} else if x[2]&(1<<47) != 0 {
+		return 175
+	} else if x[2]&(1<<48) != 0 {
+		return 176
+	} else if x[2]&(1<<49) != 0 {
+		return 177
+	} else if x[2]&(1<<50) != 0 {
+		return 178
+	} else if x[2]&(1<<51) != 0 {
+		return 179
+	} else if x[2]&(1<<52) != 0 {
+		return 180
+	} else if x[2]&(1<<53) != 0 {
+		return 181
+	} else if x[2]&(1<<54) != 0 {
+		return 182
+	} else if x[2]&(1<<55) != 0 {
+		return 183
+	} else if x[2]&(1<<56) != 0 {
+		return 184
+	} else if x[2]&(1<<57) != 0 {
+		return 185
+	} else if x[2]&(1<<58) != 0 {
+		return 186
+	} else if x[2]&(1<<59) != 0 {
+		return 187
+	} else if x[2]&(1<<60) != 0 {
+		return 188
+	} else if x[2]&(1<<61) != 0 {
+		return 189
+	} else if x[2]&(1<<62) != 0 {
+		return 190
+	} else if x[2]&(1<<63) != 0 {
+		return 191
+	} else if x[3]&(1<<0) != 0 {
+		return 192
+	} else if x[3]&(1<<1) != 0 {
+		return 193
+	} else if x[3]&(1<<2) != 0 {
+		return 194
+	} else if x[3]&(1<<3) != 0 {
+		return 195
+	} else if x[3]&(1<<4) != 0 {
+		return 196
+	} else if x[3]&(1<<5) != 0 {
+		return 197
+	} else if x[3]&(1<<6) != 0 {
+		return 198
+	} else if x[3]&(1<<7) != 0 {
+		return 199
+	} else if x[3]&(1<<8) != 0 {
+		return 200
+	} else if x[3]&(1<<9) != 0 {
+		return 201
+	} else if x[3]&(1<<10) != 0 {
+		return 202
+	} else if x[3]&(1<<11) != 0 {
+		return 203
+	} else if x[3]&(1<<12) != 0 {
+		return 204
+	} else if x[3]&(1<<13) != 0 {
+		return 205
+	} else if x[3]&(1<<14) != 0 {
+		return 206
+	} else if x[3]&(1<<15) != 0 {
+		return 207
+	} else if x[3]&(1<<16) != 0 {
+		return 208
+	} else if x[3]&(1<<17) != 0 {
+		return 209
+	} else if x[3]&(1<<18) != 0 {
+		return 210
+	} else if x[3]&(1<<19) != 0 {
+		return 211
+	} else if x[3]&(1<<20) != 0 {
+		return 212
+	} else if x[3]&(1<<21) != 0 {
+		return 213
+	} else if x[3]&(1<<22) != 0 {
+		return 214
+	} else if x[3]&(1<<23) != 0 {
+		return 215
+	} else if x[3]&(1<<24) != 0 {
+		return 216
+	} else if x[3]&(1<<25) != 0 {
+		return 217
+	} else if x[3]&(1<<26) != 0 {
+		return 218
+	} else if x[3]&(1<<27) != 0 {
+		return 219
+	} else if x[3]&(1<<28) != 0 {
+		return 220
+	} else if x[3]&(1<<29) != 0 {
+		return 221
+	} else if x[3]&(1<<30) != 0 {
+		return 222
+	} else if x[3]&(1<<31) != 0 {
+		return 223
+	} else if x[3]&(1<<32) != 0 {
+		return 224
+	} else if x[3]&(1<<33) != 0 {
+		return 225
+	} else if x[3]&(1<<34) != 0 {
+		return 226
+	} else if x[3]&(1<<35) != 0 {
+		return 227
+	} else if x[3]&(1<<36) != 0 {
+		return 228
+	} else if x[3]&(1<<37) != 0 {
+		return 229
+	} else if x[3]&(1<<38) != 0 {
+		return 230
+	} else if x[3]&(1<<39) != 0 {
+		return 231
+	} else if x[3]&(1<<40) != 0 {
+		return 232
+	} else if x[3]&(1<<41) != 0 {
+		return 233
+	} else if x[3]&(1<<42) != 0 {
+		return 234
+	} else if x[3]&(1<<43) != 0 {
+		return 235
+	} else if x[3]&(1<<44) != 0 {
+		return 236
+	} else if x[3]&(1<<45) != 0 {
+		return 237
+	} else if x[3]&(1<<46) != 0 {
+		return 238
+	} else if x[3]&(1<<47) != 0 {
+		return 239
+	} else if x[3]&(1<<48) != 0 {
+		return 240
+	} else if x[3]&(1<<49) != 0 {
+		return 241
+	} else if x[3]&(1<<50) != 0 {
+		return 242
+	} else if x[3]&(1<<51) != 0 {
+		return 243
+	} else if x[3]&(1<<52) != 0 {
+		return 244
+	} else if x[3]&(1<<53) != 0 {
+		return 245
+	} else if x[3]&(1<<54) != 0 {
+		return 246
+	} else if x[3]&(1<<55) != 0 {
+		return 247
+	} else if x[3]&(1<<56) != 0 {
+		return 248
+	} else if x[3]&(1<<57) != 0 {
+		return 249
+	} else if x[3]&(1<<58) != 0 {
+		return 250
+	} else if x[3]&(1<<59) != 0 {
+		return 251
+	} else if x[3]&(1<<60) != 0 {
+		return 252
+	} else if x[3]&(1<<61) != 0 {
+		return 253
+	} else if x[3]&(1<<62) != 0 {
+		return 254
+	} else if x[3]&(1<<63) != 0 {
+		return 255
+	}
+	return -1
+}
+
+func main() {
+	const ones = ^uint64(0)
+	for i := 0; i < 256; i++ {
+		bits := [4]uint64{ones, ones, ones, ones}
+
+		// clear bottom i bits
+		bits[i/64] ^= 1<<(uint(i)&63) - 1
+		for j := i/64 - 1; j >= 0; j-- {
+			bits[j] = 0
+		}
+
+		k := test(bits)
+		if k != i {
+			print("test(bits)=", k, " want ", i, "\n")
+			panic("failed")
+		}
+	}
+}
diff --git a/test/fixedbugs/issue3552.dir/one.go b/test/fixedbugs/issue3552.dir/one.go
new file mode 100644
index 0000000..491ada1
--- /dev/null
+++ b/test/fixedbugs/issue3552.dir/one.go
@@ -0,0 +1,28 @@
+// 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 one
+
+// Issue 3552
+
+type T struct { int }
+
+func (t T) F() int { return t.int }
+
+type U struct { int int }
+
+func (u U) F() int { return u.int }
+
+type lint int
+
+type V struct { lint }
+
+func (v V) F() int { return int(v.lint) }
+
+type W struct { lint lint }
+
+func (w W) F() int { return int(w.lint) }
+
+
+
diff --git a/test/fixedbugs/issue3552.dir/two.go b/test/fixedbugs/issue3552.dir/two.go
new file mode 100644
index 0000000..1366d24
--- /dev/null
+++ b/test/fixedbugs/issue3552.dir/two.go
@@ -0,0 +1,22 @@
+// 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.
+
+// Use the functions in one.go so that the inlined
+// forms get type-checked.
+
+package two
+
+import "./one"
+
+func use() {
+	var t one.T
+	var u one.U
+	var v one.V
+	var w one.W
+
+	_ = t.F()
+	_ = u.F()
+	_ = v.F()
+	_ = w.F()
+}
diff --git a/test/fixedbugs/issue3552.go b/test/fixedbugs/issue3552.go
new file mode 100644
index 0000000..a198dbe
--- /dev/null
+++ b/test/fixedbugs/issue3552.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// 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.
+
+// Issue 3552: cross-package inlining misbehaves when
+// referencing embedded builtins.
+
+package ignored
diff --git a/test/fixedbugs/issue3705.go b/test/fixedbugs/issue3705.go
new file mode 100644
index 0000000..c19bcea
--- /dev/null
+++ b/test/fixedbugs/issue3705.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// 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 p
+
+func init() // ERROR "missing function body"
diff --git a/test/fixedbugs/issue3783.go b/test/fixedbugs/issue3783.go
new file mode 100644
index 0000000..35df5d8
--- /dev/null
+++ b/test/fixedbugs/issue3783.go
@@ -0,0 +1,12 @@
+// errorcheck
+
+// 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 foo
+
+var i int
+
+func (*i) bar() // ERROR "not a type"
+
diff --git a/test/fixedbugs/issue3924.go b/test/fixedbugs/issue3924.go
new file mode 100644
index 0000000..d4739b2
--- /dev/null
+++ b/test/fixedbugs/issue3924.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// 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 foo
+
+type mybool bool
+
+var x, y = 1, 2
+var _ mybool = x < y && x < y // ERROR "cannot use"
+var _ mybool = x < y || x < y // ERROR "cannot use"
diff --git a/test/fixedbugs/issue3925.go b/test/fixedbugs/issue3925.go
new file mode 100644
index 0000000..2f8786f
--- /dev/null
+++ b/test/fixedbugs/issue3925.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// 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.
+
+// Issue 3925: wrong line number for error message "missing key in map literal"
+
+// also a test for correct line number in other malformed composite literals.
+
+package foo
+
+var _ = map[string]string{
+	"1": "2",
+	"3", "4", // ERROR "missing key"
+}
+
+var _ = []string{
+	"foo",
+	"bar",
+	20, // ERROR "cannot use"
+}
+
diff --git a/test/fixedbugs/issue4066.go b/test/fixedbugs/issue4066.go
new file mode 100644
index 0000000..19cfe66
--- /dev/null
+++ b/test/fixedbugs/issue4066.go
@@ -0,0 +1,37 @@
+// run
+
+// 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.
+
+// issue 4066: return values not being spilled eagerly enough
+
+package main
+
+func main() {
+	n := foo()
+	if n != 2 {
+		println(n)
+		panic("wrong return value")
+	}
+}
+
+type terr struct{}
+
+func foo() (val int) {
+	val = 0
+	defer func() {
+		if x := recover(); x != nil {
+			_ = x.(terr)
+		}
+	}()
+	for {
+		val = 2
+		foo1()
+	}
+	panic("unreachable")
+}
+
+func foo1() {
+	panic(terr{})
+}
diff --git a/test/fixedbugs/issue4085a.go b/test/fixedbugs/issue4085a.go
new file mode 100644
index 0000000..8a52b26
--- /dev/null
+++ b/test/fixedbugs/issue4085a.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// 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 main
+
+type T []int
+
+func main() {
+	_ = make(T, -1)       // ERROR "negative"
+	_ = make(T, 0.5)       // ERROR "constant 0.5 truncated to integer"
+	_ = make(T, 1.0)       // ok
+	_ = make(T, 1<<63)  // ERROR "len argument too large"
+	_ = make(T, 0, -1)    // ERROR "negative cap"
+	_ = make(T, 10, 0) // ERROR "len larger than cap"
+}
diff --git a/test/fixedbugs/issue4085b.go b/test/fixedbugs/issue4085b.go
new file mode 100644
index 0000000..63aca23
--- /dev/null
+++ b/test/fixedbugs/issue4085b.go
@@ -0,0 +1,49 @@
+// 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.
+
+package main
+
+import (
+	"strings"
+	"unsafe"
+)
+
+type T []int
+
+func main() {
+	n := -1
+	shouldPanic("len out of range", func() {_ = make(T, n)})
+	shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+	var t *byte
+	if unsafe.Sizeof(t) == 8 {
+		n = 1<<20
+		n <<= 20
+		shouldPanic("len out of range", func() {_ = make(T, n)})
+		shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+		n <<= 20
+		shouldPanic("len out of range", func() {_ = make(T, n)})
+		shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+	} else {
+		n = 1<<31 - 1
+		shouldPanic("len out of range", func() {_ = make(T, n)})
+		shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+	}
+}
+
+func shouldPanic(str string, f func()) {
+	defer func() {
+		err := recover()
+		if err == nil {
+			panic("did not panic")
+		}
+		s := err.(error).Error()
+		if !strings.Contains(s, str) {
+			panic("got panic " + s + ", want " + str)
+		}
+	}()
+	
+	f()
+}
diff --git a/test/fixedbugs/issue4097.go b/test/fixedbugs/issue4097.go
new file mode 100644
index 0000000..fa942c9
--- /dev/null
+++ b/test/fixedbugs/issue4097.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// 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 foo
+
+var s [][10]int
+const m = len(s[len(s)-1]) // ERROR "is not a constant" 
+
diff --git a/test/fixedbugs/issue4099.go b/test/fixedbugs/issue4099.go
new file mode 100644
index 0000000..89392bf
--- /dev/null
+++ b/test/fixedbugs/issue4099.go
@@ -0,0 +1,26 @@
+// errorcheck -0 -m
+
+// 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.
+
+// Check go:noescape annotations.
+
+package p
+
+// The noescape comment only applies to the next func,
+// which must not have a body.
+
+//go:noescape
+
+func F1([]byte)
+
+func F2([]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"
+}
diff --git a/test/fixedbugs/issue4162.go b/test/fixedbugs/issue4162.go
new file mode 100644
index 0000000..c2a8338
--- /dev/null
+++ b/test/fixedbugs/issue4162.go
@@ -0,0 +1,17 @@
+// compile
+
+// 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.
+
+// Issue 4162. Trailing commas now allowed in conversions.
+
+package p
+
+// All these are valid now.
+var (
+	_ = int(1.0,)      // comma was always permitted (like function call)
+	_ = []byte("foo",) // was syntax error: unexpected comma
+	_ = chan int(nil,) // was syntax error: unexpected comma
+	_ = (func())(nil,) // was syntax error: unexpected comma
+)
diff --git a/test/fixedbugs/issue4167.go b/test/fixedbugs/issue4167.go
new file mode 100644
index 0000000..4e35331
--- /dev/null
+++ b/test/fixedbugs/issue4167.go
@@ -0,0 +1,50 @@
+// run
+
+// 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.
+
+// Issue 4167: inlining of a (*T).Method expression taking
+// its arguments from a multiple return breaks the compiler.
+
+package main
+
+type pa []int
+
+type p int
+
+func (this *pa) func1() (v *p, c int) {
+	for _ = range *this {
+		c++
+	}
+	v = (*p)(&c)
+	return
+}
+
+func (this *pa) func2() p {
+	return (*p).func3(this.func1())
+}
+
+func (this *p) func3(f int) p {
+	return *this
+}
+
+func (this *pa) func2dots() p {
+	return (*p).func3(this.func1())
+}
+
+func (this *p) func3dots(f ...int) p {
+	return *this
+}
+
+func main() {
+	arr := make(pa, 13)
+	length := arr.func2()
+	if int(length) != len(arr) {
+		panic("length != len(arr)")
+	}
+	length = arr.func2dots()
+	if int(length) != len(arr) {
+		panic("length != len(arr)")
+	}
+}
diff --git a/test/fixedbugs/issue4232.go b/test/fixedbugs/issue4232.go
new file mode 100644
index 0000000..29ddfa8
--- /dev/null
+++ b/test/fixedbugs/issue4232.go
@@ -0,0 +1,33 @@
+// errorcheck
+
+// 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 p
+
+func f() {
+	var a [10]int
+	_ = a[-1] // ERROR "invalid array index -1"
+	_ = a[-1:] // ERROR "invalid slice index -1"
+	_ = a[:-1] // ERROR "invalid slice index -1"
+	_ = a[10] // ERROR "invalid array index 10"
+
+	var s []int
+	_ = s[-1] // ERROR "invalid slice index -1"
+	_ = s[-1:] // ERROR "invalid slice index -1"
+	_ = s[:-1] // ERROR "invalid slice index -1"
+	_ = s[10]
+
+	const c = "foo"
+	_ = c[-1] // ERROR "invalid string index -1"
+	_ = c[-1:] // ERROR "invalid slice index -1"
+	_ = c[:-1] // ERROR "invalid slice index -1"
+	_ = c[3] // ERROR "invalid string index 3"
+
+	var t string
+	_ = t[-1] // ERROR "invalid string index -1"
+	_ = t[-1:] // ERROR "invalid slice index -1"
+	_ = t[:-1] // ERROR "invalid slice index -1"
+	_ = t[3]
+}
diff --git a/test/fixedbugs/issue4251.go b/test/fixedbugs/issue4251.go
new file mode 100644
index 0000000..a14e089
--- /dev/null
+++ b/test/fixedbugs/issue4251.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// 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.
+
+// Issue 4251: slice with inverted range is an error.
+
+package p
+
+func F1(s []byte) []byte {
+	return s[2:1]		// ERROR "inverted"
+}
+
+func F2(a [10]byte) []byte {
+	return a[2:1]		// ERROR "inverted"
+}
+
+func F3(s string) string {
+	return s[2:1]		// ERROR "inverted"
+}
diff --git a/test/fixedbugs/issue4252.dir/a.go b/test/fixedbugs/issue4252.dir/a.go
new file mode 100644
index 0000000..089b6f2
--- /dev/null
+++ b/test/fixedbugs/issue4252.dir/a.go
@@ -0,0 +1,35 @@
+// 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.
+
+// A package that redeclares common builtin names.
+package a
+
+var true = 0 == 1
+var false = 0 == 0
+var nil = 1
+
+const append = 42
+
+type error bool
+type int interface{}
+
+func len(interface{}) int32 { return 42 }
+
+func Test() {
+	var array [append]int
+	if true {
+		panic("unexpected builtin true instead of redeclared one")
+	}
+	if !false {
+		panic("unexpected builtin false instead of redeclared one")
+	}
+	if len(array) != 42 {
+		println(len(array))
+		panic("unexpected call of builtin len")
+	}
+}
+
+func InlinedFakeTrue() error  { return error(true) }
+func InlinedFakeFalse() error { return error(false) }
+func InlinedFakeNil() int     { return nil }
diff --git a/test/fixedbugs/issue4252.dir/main.go b/test/fixedbugs/issue4252.dir/main.go
new file mode 100644
index 0000000..28e4342
--- /dev/null
+++ b/test/fixedbugs/issue4252.dir/main.go
@@ -0,0 +1,20 @@
+// 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 main
+
+import "./a"
+
+func main() {
+	if a.InlinedFakeTrue() {
+		panic("returned true was the real one")
+	}
+	if !a.InlinedFakeFalse() {
+		panic("returned false was the real one")
+	}
+	if a.InlinedFakeNil() == nil {
+		panic("returned nil was the real one")
+	}
+	a.Test()
+}
diff --git a/test/fixedbugs/issue4252.go b/test/fixedbugs/issue4252.go
new file mode 100644
index 0000000..1b0e5b2
--- /dev/null
+++ b/test/fixedbugs/issue4252.go
@@ -0,0 +1,11 @@
+// rundir
+
+// 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.
+
+// Issue 4252: tests that fixing the issue still allow
+// builtins to be redeclared and are not corrupted
+// in export data.
+
+package ignored
diff --git a/test/fixedbugs/issue4264.go b/test/fixedbugs/issue4264.go
new file mode 100644
index 0000000..6273932
--- /dev/null
+++ b/test/fixedbugs/issue4264.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// 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.
+
+// issue 4264: reject int division by const 0
+
+package main
+
+func main() {
+	var x int
+	var y float64
+	var z complex128
+
+	println(x/0) // ERROR "division by zero"
+	println(y/0)
+	println(z/0)
+}
\ No newline at end of file
diff --git a/test/fixedbugs/issue4283.go b/test/fixedbugs/issue4283.go
new file mode 100644
index 0000000..128c872
--- /dev/null
+++ b/test/fixedbugs/issue4283.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// 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.
+
+// Issue 4283: nil == nil can't be done as the type is unknown.
+
+package p
+
+func F1() bool {
+	return nil == nil	// ERROR "invalid"
+}
+
+func F2() bool {
+	return nil != nil	// ERROR "invalid"
+}
diff --git a/test/fixedbugs/issue4313.go b/test/fixedbugs/issue4313.go
new file mode 100644
index 0000000..b2f69db
--- /dev/null
+++ b/test/fixedbugs/issue4313.go
@@ -0,0 +1,28 @@
+// run
+
+// 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.
+
+// Order of operations in select.
+
+package main
+
+func main() {
+	c := make(chan int, 1)
+	x := 0
+	select {
+	case c <- x: // should see x = 0, not x = 42 (after makec)
+	case <-makec(&x): // should be evaluated only after c and x on previous line
+	}
+	y := <-c
+	if y != 0 {
+		panic(y)
+	}
+}
+
+func makec(px *int) chan bool {
+	if false { for {} }
+	*px = 42
+	return make(chan bool, 0)
+}
diff --git a/test/fixedbugs/issue4316.go b/test/fixedbugs/issue4316.go
new file mode 100644
index 0000000..bb18a08
--- /dev/null
+++ b/test/fixedbugs/issue4316.go
@@ -0,0 +1,64 @@
+// run
+
+// 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.
+
+// Issue 4316: the stack overflow check in the linker
+// is confused when it encounters a split-stack function
+// that needs 0 bytes of stack space.
+
+package main
+
+type Peano *Peano
+
+func makePeano(n int) *Peano {
+	if n == 0 {
+		return nil
+	}
+	p := Peano(makePeano(n - 1))
+	return &p
+}
+
+var countArg Peano
+var countResult int
+
+func countPeano() {
+	if countArg == nil {
+		countResult = 0
+		return
+	}
+	countArg = *countArg
+	countPeano()
+	countResult++
+}
+
+var s = "(())"
+var pT = 0
+
+func p() {
+	if pT >= len(s) {
+		return
+	}
+	if s[pT] == '(' {
+		pT += 1
+		p()
+		if pT < len(s) && s[pT] == ')' {
+			pT += 1
+		} else {
+			return
+		}
+		p()
+	}
+}
+
+func main() {
+	countArg = makePeano(4096)
+	countPeano()
+	if countResult != 4096 {
+		println("countResult =", countResult)
+		panic("countResult != 4096")
+	}
+
+	p()
+}
diff --git a/test/fixedbugs/issue4323.go b/test/fixedbugs/issue4323.go
new file mode 100644
index 0000000..6bb78f4
--- /dev/null
+++ b/test/fixedbugs/issue4323.go
@@ -0,0 +1,31 @@
+// compile
+
+// 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.
+
+// Issue 4323: inlining of functions with local variables
+// forgets to typecheck the declarations in the inlined copy.
+
+package main
+
+type reader struct {
+	C chan T
+}
+
+type T struct{ C chan []byte }
+
+var r = newReader()
+
+func newReader() *reader { return new(reader) }
+
+func (r *reader) Read(n int) ([]byte, error) {
+	req := T{C: make(chan []byte)}
+	r.C <- req
+	return <-req.C, nil
+}
+
+func main() {
+	s, err := r.Read(1)
+	_, _ = s, err
+}
diff --git a/test/fixedbugs/issue4326.dir/p1.go b/test/fixedbugs/issue4326.dir/p1.go
new file mode 100644
index 0000000..ab214be
--- /dev/null
+++ b/test/fixedbugs/issue4326.dir/p1.go
@@ -0,0 +1,12 @@
+package p1
+
+type O map[string]map[string]string
+
+func (opts O) RemoveOption(sect, opt string) bool {
+	if _, ok := opts[sect]; !ok {
+		return false
+	}
+	_, ok := opts[sect][opt]
+	delete(opts[sect], opt)
+	return ok
+}
diff --git a/test/fixedbugs/issue4326.dir/p2.go b/test/fixedbugs/issue4326.dir/p2.go
new file mode 100644
index 0000000..8e86266
--- /dev/null
+++ b/test/fixedbugs/issue4326.dir/p2.go
@@ -0,0 +1,5 @@
+package p2
+
+import "./p1"
+
+func NewO() p1.O { return nil }
diff --git a/test/fixedbugs/issue4326.dir/q1.go b/test/fixedbugs/issue4326.dir/q1.go
new file mode 100644
index 0000000..f118eb0
--- /dev/null
+++ b/test/fixedbugs/issue4326.dir/q1.go
@@ -0,0 +1,8 @@
+package q1
+
+func Deref(typ interface{}) interface{} {
+      if typ, ok := typ.(*int); ok {
+            return *typ
+      }
+      return typ
+}
diff --git a/test/fixedbugs/issue4326.dir/q2.go b/test/fixedbugs/issue4326.dir/q2.go
new file mode 100644
index 0000000..075e2b2
--- /dev/null
+++ b/test/fixedbugs/issue4326.dir/q2.go
@@ -0,0 +1,11 @@
+package main
+
+import "./q1"
+
+func main() {
+      x := 1
+      y := q1.Deref(&x)
+      if y != 1 {
+            panic("y != 1")
+      }
+}
diff --git a/test/fixedbugs/issue4326.dir/z.go b/test/fixedbugs/issue4326.dir/z.go
new file mode 100644
index 0000000..9b222e8
--- /dev/null
+++ b/test/fixedbugs/issue4326.dir/z.go
@@ -0,0 +1,7 @@
+package z
+
+import "./p2"
+
+func main() {
+	p2.NewO().RemoveOption("hello", "world")
+}
diff --git a/test/fixedbugs/issue4326.go b/test/fixedbugs/issue4326.go
new file mode 100644
index 0000000..5ce2eea
--- /dev/null
+++ b/test/fixedbugs/issue4326.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// 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.
+
+// Printing local variables in inliner shadows global names.
+
+package ignored
diff --git a/test/fixedbugs/issue4348.go b/test/fixedbugs/issue4348.go
new file mode 100644
index 0000000..3dac8f7
--- /dev/null
+++ b/test/fixedbugs/issue4348.go
@@ -0,0 +1,29 @@
+// compile
+
+// 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.
+
+// Issue 4348. After switch to 64-bit ints the compiler generates
+// illegal instructions when using large array bounds or indexes.
+
+package main
+
+// 1<<32 on a 64-bit machine, 1 otherwise.
+const LARGE = ^uint(0)>>32 + 1
+
+func A() int {
+	var a []int
+	return a[LARGE]
+}
+
+var b [LARGE]int
+
+func B(i int) int {
+	return b[i]
+}
+
+func main() {
+	n := A()
+	B(n)
+}
diff --git a/test/fixedbugs/issue4353.go b/test/fixedbugs/issue4353.go
new file mode 100644
index 0000000..defe7c3
--- /dev/null
+++ b/test/fixedbugs/issue4353.go
@@ -0,0 +1,19 @@
+// run
+
+// 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.
+
+// Issue 4353. An optimizer bug in 8g triggers a runtime fault
+// instead of an out of bounds panic.
+
+package main
+
+var aib [100000]int
+var paib *[100000]int = &aib
+var i64 int64 = 100023
+
+func main() {
+	defer func() { recover() }()
+	_ = paib[i64]
+}
diff --git a/test/fixedbugs/issue4359.go b/test/fixedbugs/issue4359.go
new file mode 100644
index 0000000..b5adb40
--- /dev/null
+++ b/test/fixedbugs/issue4359.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// 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.
+
+// Issue 4359: wrong handling of broken struct fields
+// causes "internal compiler error: lookdot badwidth".
+
+package main
+
+type T struct {
+	x T1 // ERROR "undefined"
+}
+
+func f() {
+	var t *T
+	_ = t.x
+}
diff --git a/test/fixedbugs/issue4370.dir/p1.go b/test/fixedbugs/issue4370.dir/p1.go
new file mode 100644
index 0000000..d732c8b
--- /dev/null
+++ b/test/fixedbugs/issue4370.dir/p1.go
@@ -0,0 +1,20 @@
+// 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 p1
+
+type Magic int
+
+type T struct {
+	x interface{}
+}
+
+func (t *T) M() bool {
+	_, ok := t.x.(Magic)
+	return ok
+}
+
+func F(t *T) {
+	println(t)
+}
diff --git a/test/fixedbugs/issue4370.dir/p2.go b/test/fixedbugs/issue4370.dir/p2.go
new file mode 100644
index 0000000..33370d0
--- /dev/null
+++ b/test/fixedbugs/issue4370.dir/p2.go
@@ -0,0 +1,16 @@
+// 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 p2
+
+import "./p1"
+
+type T struct {
+	p1.T
+}
+
+func F() {
+	var t T
+	p1.F(&t.T)
+}
diff --git a/test/fixedbugs/issue4370.dir/p3.go b/test/fixedbugs/issue4370.dir/p3.go
new file mode 100644
index 0000000..13c996b
--- /dev/null
+++ b/test/fixedbugs/issue4370.dir/p3.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.
+
+package p3
+
+import "./p2"
+
+func F() {
+	p2.F()
+	var t p2.T
+	println(t.T.M())
+}
diff --git a/test/fixedbugs/issue4370.go b/test/fixedbugs/issue4370.go
new file mode 100644
index 0000000..76b47e1
--- /dev/null
+++ b/test/fixedbugs/issue4370.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// 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.
+
+// Re-exporting inlined function bodies missed types in x, ok := v.(Type)
+
+package ignored
diff --git a/test/fixedbugs/issue4396a.go b/test/fixedbugs/issue4396a.go
new file mode 100644
index 0000000..11ae1f7
--- /dev/null
+++ b/test/fixedbugs/issue4396a.go
@@ -0,0 +1,27 @@
+// run
+
+// 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.
+
+// Issue 4396. Arrays of bytes are not required to be
+// word aligned. 5g should use MOVB to load the address
+// of s.g[0] for its nil check.
+//
+// This test _may_ fail on arm, but requires the host to 
+// trap unaligned loads. This is generally done with
+//
+// echo "4" > /proc/cpu/alignment
+
+package main
+
+var s = struct {
+	// based on lzw.decoder
+	a, b, c, d, e uint16
+	f             [4096]uint8
+	g             [4096]uint8
+}{}
+
+func main() {
+	s.g[0] = 1
+}
diff --git a/test/fixedbugs/issue4396b.go b/test/fixedbugs/issue4396b.go
new file mode 100644
index 0000000..d0bf28f
--- /dev/null
+++ b/test/fixedbugs/issue4396b.go
@@ -0,0 +1,29 @@
+// run
+
+// 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.
+
+// This test _may_ fail on arm, but requires the host to
+// trap unaligned loads. This is generally done with
+//
+// echo "4" > /proc/cpu/alignment
+
+package main
+
+type T struct {
+	U uint16
+	V T2
+}
+
+type T2 struct {
+	pad    [4096]byte
+	A, B byte
+}
+
+var s, t = new(T), new(T)
+
+func main() {
+	var u, v *T2 = &s.V, &t.V
+	u.B = v.B
+}
diff --git a/test/fixedbugs/issue4399.go b/test/fixedbugs/issue4399.go
new file mode 100644
index 0000000..6674db9
--- /dev/null
+++ b/test/fixedbugs/issue4399.go
@@ -0,0 +1,15 @@
+// compile
+
+// 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.
+
+// Issue 4399: 8g would print "gins LEAQ nil *A".
+
+package main
+
+type A struct{ a int }
+
+func main() {
+	println(((*A)(nil)).a)
+}
diff --git a/test/fixedbugs/issue4405.go b/test/fixedbugs/issue4405.go
new file mode 100644
index 0000000..c0d8085
--- /dev/null
+++ b/test/fixedbugs/issue4405.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// 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 p
+
+const (
+	_ = iota
+	_ // ERROR "illegal character"
+	_  // ERROR "illegal character"
+	_  // ERROR "illegal character"
+	_  // ERROR "illegal character"
+)
diff --git a/test/fixedbugs/issue4429.go b/test/fixedbugs/issue4429.go
new file mode 100644
index 0000000..8a93b02
--- /dev/null
+++ b/test/fixedbugs/issue4429.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// 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 p
+
+type a struct {
+  a int
+}
+
+func main() {
+  av := a{};
+  *a(av); // ERROR "invalid indirect"
+}
diff --git a/test/fixedbugs/issue4448.go b/test/fixedbugs/issue4448.go
new file mode 100644
index 0000000..fa1d9fe
--- /dev/null
+++ b/test/fixedbugs/issue4448.go
@@ -0,0 +1,37 @@
+// run
+
+// 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.
+
+// Issue 4448: 64-bit indices that are statically known
+// to be bounded make 5g and 8g generate a dangling branch.
+
+package main
+
+const b26 uint64 = 0x022fdd63cc95386d
+
+var bitPos [64]int
+
+func init() {
+	for p := uint(0); p < 64; p++ {
+		bitPos[b26<<p>>58] = int(p)
+	}
+}
+
+func MinPos(w uint64) int {
+	if w == 0 {
+		panic("bit: MinPos(0) undefined")
+	}
+	return bitPos[((w&-w)*b26)>>58]
+}
+
+func main() {
+	const one = uint64(1)
+	for i := 0; i < 64; i++ {
+		if MinPos(1<<uint(i)) != i {
+			println("i =", i)
+			panic("MinPos(1<<uint(i)) != i")
+		}
+	}
+}
diff --git a/test/fixedbugs/issue4452.go b/test/fixedbugs/issue4452.go
new file mode 100644
index 0000000..c75da90
--- /dev/null
+++ b/test/fixedbugs/issue4452.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// 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.
+
+// Issue 4452. Used to print many errors, now just one.
+
+package main
+
+func main() {
+	_ = [...]int(4) // ERROR "use of \[\.\.\.\] array outside of array literal"
+}
diff --git a/test/fixedbugs/issue4458.go b/test/fixedbugs/issue4458.go
new file mode 100644
index 0000000..8ee3e87
--- /dev/null
+++ b/test/fixedbugs/issue4458.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// 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.
+
+// Issue 4458: gc accepts invalid method expressions
+// like (**T).Method.
+
+package main
+
+type T struct{}
+
+func (T) foo() {}
+
+func main() {
+	av := T{}
+	pav := &av
+	(**T).foo(&pav) // ERROR "no method foo"
+}
diff --git a/test/fixedbugs/issue4463.go b/test/fixedbugs/issue4463.go
new file mode 100644
index 0000000..fe07af7
--- /dev/null
+++ b/test/fixedbugs/issue4463.go
@@ -0,0 +1,87 @@
+// errorcheck
+
+// 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.
+
+// Issue 4463: test builtin functions in statement context and in
+// go/defer functions.
+
+package p
+
+import "unsafe"
+
+func F() {
+	var a []int
+	var c chan int
+	var m map[int]int
+	var s struct{ f int }
+
+	append(a, 0)			// ERROR "not used"
+	cap(a)				// ERROR "not used"
+	complex(1, 2)			// ERROR "not used"
+	imag(1i)			// ERROR "not used"
+	len(a)				// ERROR "not used"
+	make([]int, 10)			// ERROR "not used"
+	new(int)			// ERROR "not used"
+	real(1i)			// ERROR "not used"
+	unsafe.Alignof(a)		// ERROR "not used"
+	unsafe.Offsetof(s.f)		// ERROR "not used"
+	unsafe.Sizeof(a)		// ERROR "not used"
+
+	close(c)
+	copy(a, a)
+	delete(m, 0)
+	panic(0)
+	print("foo")
+	println("bar")
+	recover()
+
+	(close(c))
+	(copy(a, a))
+	(delete(m, 0))
+	(panic(0))
+	(print("foo"))
+	(println("bar"))
+	(recover())
+
+	go append(a, 0)			// ERROR "discards result"
+	go cap(a)			// ERROR "discards result"
+	go complex(1, 2)		// ERROR "discards result"
+	go imag(1i)			// ERROR "discards result"
+	go len(a)			// ERROR "discards result"
+	go make([]int, 10)		// ERROR "discards result"
+	go new(int)			// ERROR "discards result"
+	go real(1i)			// ERROR "discards result"
+	go unsafe.Alignof(a)		// ERROR "discards result"
+	go unsafe.Offsetof(s.f)		// ERROR "discards result"
+	go unsafe.Sizeof(a)		// ERROR "discards result"
+
+	go close(c)
+	go copy(a, a)
+	go delete(m, 0)
+	go panic(0)
+	go print("foo")
+	go println("bar")
+	go recover()
+
+	defer append(a, 0)		// ERROR "discards result"
+	defer cap(a)			// ERROR "discards result"
+	defer complex(1, 2)		// ERROR "discards result"
+	defer imag(1i)			// ERROR "discards result"
+	defer len(a)			// ERROR "discards result"
+	defer make([]int, 10)		// ERROR "discards result"
+	defer new(int)			// ERROR "discards result"
+	defer real(1i)			// ERROR "discards result"
+	defer unsafe.Alignof(a)		// ERROR "discards result"
+	defer unsafe.Offsetof(s.f)	// ERROR "discards result"
+	defer unsafe.Sizeof(a)		// ERROR "discards result"
+
+	defer close(c)
+	defer copy(a, a)
+	defer delete(m, 0)
+	defer panic(0)
+	defer print("foo")
+	defer println("bar")
+	defer recover()
+}
diff --git a/test/fixedbugs/issue4468.go b/test/fixedbugs/issue4468.go
new file mode 100644
index 0000000..ef0b46b
--- /dev/null
+++ b/test/fixedbugs/issue4468.go
@@ -0,0 +1,28 @@
+// errorcheck
+
+// 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.
+
+// Issue 4468: go/defer calls may not be parenthesized.
+
+package p
+
+type T int
+
+func (t *T) F() T {
+	return *t
+}
+
+type S struct {
+	t T
+}
+
+func F() {
+	go (F())	// ERROR "must be function call"
+	defer (F())	// ERROR "must be function call"
+	var s S
+	(&s.t).F()
+	go (&s.t).F()
+	defer (&s.t).F()
+}
diff --git a/test/fixedbugs/issue4470.go b/test/fixedbugs/issue4470.go
new file mode 100644
index 0000000..5ed09ca
--- /dev/null
+++ b/test/fixedbugs/issue4470.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// 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.
+
+// Issue 4470: parens are not allowed around .(type) "expressions"
+
+package main
+
+func main() {
+	var i interface{}
+	switch (i.(type)) { // ERROR "outside type switch"
+	default:
+	}
+}
diff --git a/test/fixedbugs/issue4495.go b/test/fixedbugs/issue4495.go
new file mode 100644
index 0000000..7ec1134
--- /dev/null
+++ b/test/fixedbugs/issue4495.go
@@ -0,0 +1,29 @@
+// run
+
+// 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 main
+
+type I interface {
+	m() int
+}
+
+type T struct{}
+
+func (T) m() int {
+	return 3
+}
+
+var t T
+
+var ret = I.m(t)
+
+func main() {
+	if ret != 3 {
+		println("ret = ", ret)
+		panic("ret != 3")
+	}
+}
+
diff --git a/test/fixedbugs/issue4510.dir/f1.go b/test/fixedbugs/issue4510.dir/f1.go
new file mode 100644
index 0000000..1e642e4
--- /dev/null
+++ b/test/fixedbugs/issue4510.dir/f1.go
@@ -0,0 +1,9 @@
+// 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 p
+
+import "fmt" // ERROR "fmt redeclared"
+
+var _ = fmt.Printf
diff --git a/test/fixedbugs/issue4510.dir/f2.go b/test/fixedbugs/issue4510.dir/f2.go
new file mode 100644
index 0000000..895fc34
--- /dev/null
+++ b/test/fixedbugs/issue4510.dir/f2.go
@@ -0,0 +1,7 @@
+// 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 p
+
+func fmt() {}
diff --git a/test/fixedbugs/issue4510.go b/test/fixedbugs/issue4510.go
new file mode 100644
index 0000000..003f9e8
--- /dev/null
+++ b/test/fixedbugs/issue4510.go
@@ -0,0 +1,7 @@
+// errorcheckdir
+
+// 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 ignored
diff --git a/test/fixedbugs/issue4517a.go b/test/fixedbugs/issue4517a.go
new file mode 100644
index 0000000..a1b6b57
--- /dev/null
+++ b/test/fixedbugs/issue4517a.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// 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 p
+
+var init = 1 // ERROR "cannot declare init - must be func"
diff --git a/test/fixedbugs/issue4517b.go b/test/fixedbugs/issue4517b.go
new file mode 100644
index 0000000..f04103f
--- /dev/null
+++ b/test/fixedbugs/issue4517b.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// 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 p
+
+const init = 1 // ERROR "cannot declare init - must be func"
diff --git a/test/fixedbugs/issue4517c.go b/test/fixedbugs/issue4517c.go
new file mode 100644
index 0000000..47b21cf
--- /dev/null
+++ b/test/fixedbugs/issue4517c.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// 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 p
+
+type init byte // ERROR "cannot declare init - must be func"
diff --git a/test/fixedbugs/issue4518.go b/test/fixedbugs/issue4518.go
new file mode 100644
index 0000000..e64b069
--- /dev/null
+++ b/test/fixedbugs/issue4518.go
@@ -0,0 +1,67 @@
+// run
+
+// 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.
+
+// Issue 4518. In some circumstances "return F(...)"
+// where F has multiple returns is miscompiled by 6g due to
+// bold assumptions in componentgen.
+
+package main
+
+func DontInline() {}
+
+func F(e interface{}) (int, int) {
+	DontInline()
+	return 3, 7
+}
+
+func G() (int, int) {
+	DontInline()
+	return 3, 7
+}
+
+func bogus1(d interface{}) (int, int) {
+	switch {
+	default:
+		return F(d)
+	}
+	return 0, 0
+}
+
+func bogus2() (int, int) {
+	switch {
+	default:
+		return F(3)
+	}
+	return 0, 0
+}
+
+func bogus3(d interface{}) (int, int) {
+	switch {
+	default:
+		return G()
+	}
+	return 0, 0
+}
+
+func bogus4() (int, int) {
+	switch {
+	default:
+		return G()
+	}
+	return 0, 0
+}
+
+func check(a, b int) {
+	if a != 3 || b != 7 {
+		println(a, b)
+		panic("a != 3 || b != 7")
+	}
+}
+
+func main() {
+	check(bogus1(42))
+	check(bogus2())
+}
diff --git a/test/fixedbugs/issue4529.go b/test/fixedbugs/issue4529.go
new file mode 100644
index 0000000..4f37e7c
--- /dev/null
+++ b/test/fixedbugs/issue4529.go
@@ -0,0 +1,33 @@
+// compile
+
+// 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.
+
+// Issue 4529: escape analysis crashes on "go f(g())"
+// when g has multiple returns.
+
+package main
+
+type M interface{}
+
+type A struct {
+	a string
+	b chan M
+}
+
+func (a *A) I() (b <-chan M, c chan<- M) {
+	a.b, c = make(chan M), make(chan M)
+	b = a.b
+
+	return
+}
+
+func Init(a string, b *A, c interface {
+	I() (<-chan M, chan<- M)
+}) {
+	b.a = a
+	go b.c(c.I())
+}
+
+func (a *A) c(b <-chan M, _ chan<- M) {}
diff --git a/test/fixedbugs/issue4545.go b/test/fixedbugs/issue4545.go
new file mode 100644
index 0000000..3f2de16
--- /dev/null
+++ b/test/fixedbugs/issue4545.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// 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.
+
+// Issue 4545: untyped constants are incorrectly coerced
+// to concrete types when used in interface{} context.
+
+package main
+
+import "fmt"
+
+func main() {
+	var s uint
+	fmt.Println(1.0 + 1<<s) // ERROR "invalid operation"
+	x := 1.0 + 1<<s         // ERROR "invalid operation"
+	_ = x
+}
diff --git a/test/fixedbugs/issue4562.go b/test/fixedbugs/issue4562.go
new file mode 100644
index 0000000..29d98b0
--- /dev/null
+++ b/test/fixedbugs/issue4562.go
@@ -0,0 +1,49 @@
+// run
+
+// 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 main
+
+import (
+	"fmt"
+	"runtime"
+	"strings"
+)
+
+type T struct {
+	val int
+}
+
+func main() {
+	defer expectError(22)
+	var pT *T
+	switch pT.val { // error should be here - line 22
+	case 0:
+		fmt.Println("0")
+	case 1: // used to show up here instead
+		fmt.Println("1")
+	case 2:
+		fmt.Println("2")
+	}
+	fmt.Println("finished")
+}
+
+func expectError(expectLine int) {
+	if recover() == nil {
+		panic("did not crash")
+	}
+	for i := 1;; i++ {
+		_, file, line, ok := runtime.Caller(i)
+		if !ok {
+			panic("cannot find issue4562.go on stack")
+		}
+		if strings.HasSuffix(file, "issue4562.go") {
+			if line != expectLine {
+				panic(fmt.Sprintf("crashed at line %d, wanted line %d", line, expectLine))
+			}
+			break
+		}
+	}
+}
diff --git a/test/fixedbugs/issue4585.go b/test/fixedbugs/issue4585.go
new file mode 100644
index 0000000..ad1242d
--- /dev/null
+++ b/test/fixedbugs/issue4585.go
@@ -0,0 +1,151 @@
+// 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.
+
+// Issue 4585: comparisons and hashes process blank
+// fields and padding in structs.
+
+package main
+
+import "unsafe"
+
+// T is a structure with padding.
+type T struct {
+	A     int16
+	B     int64
+	C     int16
+	D     int64
+	Dummy [64]byte
+}
+
+// U is a structure with a blank field
+type U struct {
+	A, _, B int
+	Dummy   [64]byte
+}
+
+// USmall is like U but the frontend will inline comparison
+// instead of calling the generated eq function.
+type USmall struct {
+	A, _, B int32
+}
+
+// V has padding but not on the first field.
+type V struct {
+	A1, A2, A3 int32
+	B          int16
+	C          int32
+}
+
+// W has padding at the end.
+type W struct {
+	A1, A2, A3 int32
+	B          int32
+	C          int8
+}
+
+func test1() {
+	var a, b U
+	m := make(map[U]int)
+	copy((*[16]byte)(unsafe.Pointer(&a))[:], "hello world!")
+	a.A, a.B = 1, 2
+	b.A, b.B = 1, 2
+	if a != b {
+		panic("broken equality: a != b")
+	}
+
+	m[a] = 1
+	m[b] = 2
+	if len(m) == 2 {
+		panic("broken hash: len(m) == 2")
+	}
+	if m[a] != 2 {
+		panic("m[a] != 2")
+	}
+}
+
+func test2() {
+	var a, b T
+	m := make(map[T]int)
+
+	copy((*[16]byte)(unsafe.Pointer(&a))[:], "hello world!")
+	a.A, a.B, a.C, a.D = 1, 2, 3, 4
+	b.A, b.B, b.C, b.D = 1, 2, 3, 4
+
+	if a != b {
+		panic("broken equality: a != b")
+	}
+
+	m[a] = 1
+	m[b] = 2
+	if len(m) == 2 {
+		panic("broken hash: len(m) == 2")
+	}
+	if m[a] != 2 {
+		panic("m[a] != 2")
+	}
+}
+
+func test3() {
+	var a, b USmall
+	copy((*[12]byte)(unsafe.Pointer(&a))[:], "hello world!")
+	a.A, a.B = 1, 2
+	b.A, b.B = 1, 2
+	if a != b {
+		panic("broken equality: a != b")
+	}
+}
+
+func test4() {
+	var a, b V
+	m := make(map[V]int)
+
+	copy((*[20]byte)(unsafe.Pointer(&a))[:], "Hello World, Gopher!")
+	a.A1, a.A2, a.A3, a.B, a.C = 1, 2, 3, 4, 5
+	b.A1, b.A2, b.A3, b.B, b.C = 1, 2, 3, 4, 5
+
+	if a != b {
+		panic("broken equality: a != b")
+	}
+
+	m[a] = 1
+	m[b] = 2
+	if len(m) == 2 {
+		panic("broken hash: len(m) == 2")
+	}
+	if m[a] != 2 {
+		panic("m[a] != 2")
+	}
+}
+
+func test5() {
+	var a, b W
+	m := make(map[W]int)
+
+	copy((*[20]byte)(unsafe.Pointer(&a))[:], "Hello World, Gopher!")
+	a.A1, a.A2, a.A3, a.B, a.C = 1, 2, 3, 4, 5
+	b.A1, b.A2, b.A3, b.B, b.C = 1, 2, 3, 4, 5
+
+	if a != b {
+		panic("broken equality: a != b")
+	}
+
+	m[a] = 1
+	m[b] = 2
+	if len(m) == 2 {
+		panic("broken hash: len(m) == 2")
+	}
+	if m[a] != 2 {
+		panic("m[a] != 2")
+	}
+}
+
+func main() {
+	test1()
+	test2()
+	test3()
+	test4()
+	test5()
+}
diff --git a/test/fixedbugs/issue4590.dir/pkg1.go b/test/fixedbugs/issue4590.dir/pkg1.go
new file mode 100644
index 0000000..c447371
--- /dev/null
+++ b/test/fixedbugs/issue4590.dir/pkg1.go
@@ -0,0 +1,26 @@
+// 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 pkg1
+
+type A interface {
+	Write() error
+}
+
+type B interface {
+	Hello()
+	world()
+}
+
+type C struct{}
+
+func (c C) Write() error { return nil }
+
+var T = struct{ A }{nil}
+var U = struct{ B }{nil}
+var V A = struct{ *C }{nil}
+var W = interface {
+	Write() error
+	Hello()
+}(nil)
diff --git a/test/fixedbugs/issue4590.dir/pkg2.go b/test/fixedbugs/issue4590.dir/pkg2.go
new file mode 100644
index 0000000..61c01d7
--- /dev/null
+++ b/test/fixedbugs/issue4590.dir/pkg2.go
@@ -0,0 +1,15 @@
+// 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 pkg2
+
+import "./pkg1"
+
+var T = struct{ pkg1.A }{nil}
+var U = struct{ pkg1.B }{nil}
+var V pkg1.A = struct{ *pkg1.C }{nil}
+var W = interface {
+	Write() error
+	Hello()
+}(nil)
diff --git a/test/fixedbugs/issue4590.dir/prog.go b/test/fixedbugs/issue4590.dir/prog.go
new file mode 100644
index 0000000..3220e85
--- /dev/null
+++ b/test/fixedbugs/issue4590.dir/prog.go
@@ -0,0 +1,25 @@
+// 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 main
+
+import (
+	"./pkg1"
+	"./pkg2"
+)
+
+func main() {
+	if pkg1.T != pkg2.T {
+		panic("pkg1.T != pkg2.T")
+	}
+	if pkg1.U != pkg2.U {
+		panic("pkg1.U != pkg2.U")
+	}
+	if pkg1.V != pkg2.V {
+		panic("pkg1.V != pkg2.V")
+	}
+	if pkg1.W != pkg2.W {
+		panic("pkg1.W != pkg2.W")
+	}
+}
diff --git a/test/fixedbugs/issue4590.go b/test/fixedbugs/issue4590.go
new file mode 100644
index 0000000..faeb1ad
--- /dev/null
+++ b/test/fixedbugs/issue4590.go
@@ -0,0 +1,10 @@
+// rundir
+
+// 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.
+
+// Issue 4590: linker fails on multiple imports of
+// an anonymous struct with methods.
+
+package ignored
diff --git a/test/fixedbugs/issue4610.go b/test/fixedbugs/issue4610.go
new file mode 100644
index 0000000..bc6bfe7
--- /dev/null
+++ b/test/fixedbugs/issue4610.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// 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 main
+
+type bar struct {
+	x int
+}
+
+func main() {
+	var foo bar
+	_ = &foo{} // ERROR "is not a type"
+}
+
diff --git a/test/fixedbugs/issue4614.go b/test/fixedbugs/issue4614.go
new file mode 100644
index 0000000..1aa318c
--- /dev/null
+++ b/test/fixedbugs/issue4614.go
@@ -0,0 +1,20 @@
+// compile
+
+// 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.
+
+// Issue 4614: slicing of nil slices confuses the compiler
+// with a uintptr(nil) node.
+
+package p
+
+import "unsafe"
+
+var n int
+
+var _ = []int(nil)[1:]
+var _ = []int(nil)[n:]
+
+var _ = uintptr(unsafe.Pointer(nil))
+var _ = unsafe.Pointer(uintptr(0))
diff --git a/test/fixedbugs/issue4618.go b/test/fixedbugs/issue4618.go
new file mode 100644
index 0000000..335feaa
--- /dev/null
+++ b/test/fixedbugs/issue4618.go
@@ -0,0 +1,40 @@
+// 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.
+
+package main
+
+import (
+	"fmt"
+	"os"
+	"testing"
+)
+
+type T struct { int }
+
+var globl *T
+
+func F() {
+	t := &T{}
+	globl = t
+}
+
+func G() {
+	t := &T{}
+	_ = t
+}
+
+func main() {
+	nf := testing.AllocsPerRun(100, F)
+	ng := testing.AllocsPerRun(100, G)
+	if int(nf) != 1 {
+		fmt.Printf("AllocsPerRun(100, F) = %v, want 1\n", nf)
+		os.Exit(1)
+	}
+	if int(ng) != 0 {
+		fmt.Printf("AllocsPerRun(100, G) = %v, want 0\n", ng)
+		os.Exit(1)
+	}
+}
diff --git a/test/fixedbugs/issue4620.go b/test/fixedbugs/issue4620.go
new file mode 100644
index 0000000..7b4ebf9
--- /dev/null
+++ b/test/fixedbugs/issue4620.go
@@ -0,0 +1,21 @@
+// 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.
+
+// Issue 4620: map indexes are not evaluated before assignment of other elements
+
+package main
+
+import "fmt"
+
+func main() {
+	m := map[int]int{0:1}
+	i := 0
+	i, m[i] = 1, 2
+	if m[0] != 2 {
+		fmt.Println(m)
+		panic("m[i] != 2")
+	}
+}
diff --git a/test/fixedbugs/issue4654.go b/test/fixedbugs/issue4654.go
new file mode 100644
index 0000000..170594e
--- /dev/null
+++ b/test/fixedbugs/issue4654.go
@@ -0,0 +1,71 @@
+// errorcheck
+
+// 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.
+
+// Issue 4654.
+// Check error for conversion and 'not used' in defer/go.
+
+package p
+
+import "unsafe"
+
+func f() {
+	defer int(0) // ERROR "defer requires function call, not conversion"
+	go string([]byte("abc")) // ERROR "go requires function call, not conversion"
+	
+	var c complex128
+	var f float64
+	var t struct {X int}
+
+	var x []int
+	defer append(x, 1) // ERROR "defer discards result of append"
+	defer cap(x) // ERROR "defer discards result of cap"
+	defer complex(1, 2) // ERROR "defer discards result of complex"
+	defer complex(f, 1) // ERROR "defer discards result of complex"
+	defer imag(1i) // ERROR "defer discards result of imag"
+	defer imag(c) // ERROR "defer discards result of imag"
+	defer len(x) // ERROR "defer discards result of len"
+	defer make([]int, 1) // ERROR "defer discards result of make"
+	defer make(chan bool) // ERROR "defer discards result of make"
+	defer make(map[string]int) // ERROR "defer discards result of make"
+	defer new(int) // ERROR "defer discards result of new"
+	defer real(1i) // ERROR "defer discards result of real"
+	defer real(c) // ERROR "defer discards result of real"
+	defer append(x, 1) // ERROR "defer discards result of append"
+	defer append(x, 1) // ERROR "defer discards result of append"
+	defer unsafe.Alignof(t.X) // ERROR "defer discards result of unsafe.Alignof"
+	defer unsafe.Offsetof(t.X) // ERROR "defer discards result of unsafe.Offsetof"
+	defer unsafe.Sizeof(t) // ERROR "defer discards result of unsafe.Sizeof"
+	
+	defer copy(x, x) // ok
+	m := make(map[int]int)
+	defer delete(m, 1) // ok
+	defer panic(1) // ok
+	defer print(1) // ok
+	defer println(1) // ok
+	defer recover() // ok
+
+	int(0) // ERROR "int\(0\) evaluated but not used"
+	string([]byte("abc")) // ERROR "string\(.*\) evaluated but not used"
+
+	append(x, 1) // ERROR "not used"
+	cap(x) // ERROR "not used"
+	complex(1, 2) // ERROR "not used"
+	complex(f, 1) // ERROR "not used"
+	imag(1i) // ERROR "not used"
+	imag(c) // ERROR "not used"
+	len(x) // ERROR "not used"
+	make([]int, 1) // ERROR "not used"
+	make(chan bool) // ERROR "not used"
+	make(map[string]int) // ERROR "not used"
+	new(int) // ERROR "not used"
+	real(1i) // ERROR "not used"
+	real(c) // ERROR "not used"
+	append(x, 1) // ERROR "not used"
+	append(x, 1) // ERROR "not used"
+	unsafe.Alignof(t.X) // ERROR "not used"
+	unsafe.Offsetof(t.X) // ERROR "not used"
+	unsafe.Sizeof(t) // ERROR "not used"
+}
diff --git a/test/fixedbugs/issue4663.go b/test/fixedbugs/issue4663.go
new file mode 100644
index 0000000..b3d6602
--- /dev/null
+++ b/test/fixedbugs/issue4663.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// 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.
+
+// Issue 4663.
+// Make sure 'not used' message is placed correctly.
+
+package main
+
+func a(b int) int64 {
+  b // ERROR "not used"
+}
diff --git a/test/fixedbugs/issue4667.go b/test/fixedbugs/issue4667.go
new file mode 100644
index 0000000..3a00a31
--- /dev/null
+++ b/test/fixedbugs/issue4667.go
@@ -0,0 +1,37 @@
+// 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.
+
+package main
+
+import (
+	"fmt"
+	"os"
+	"testing"
+)
+
+var globl *int
+
+func G() {
+	F()
+}
+
+func F() {
+	var x int
+	globl = &x
+}
+
+func main() {
+	nf := testing.AllocsPerRun(100, F)
+	ng := testing.AllocsPerRun(100, G)
+	if int(nf) != 1 {
+		fmt.Printf("AllocsPerRun(100, F) = %v, want 1\n", nf)
+		os.Exit(1)
+	}
+	if int(ng) != 1 {
+		fmt.Printf("AllocsPerRun(100, G) = %v, want 1\n", ng)
+		os.Exit(1)
+	}
+}
diff --git a/test/fixedbugs/issue4734.go b/test/fixedbugs/issue4734.go
new file mode 100644
index 0000000..69f66f2
--- /dev/null
+++ b/test/fixedbugs/issue4734.go
@@ -0,0 +1,21 @@
+// compile
+
+// 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.
+
+// Caused gccgo to emit multiple definitions of the same symbol.
+
+package p
+
+type S1 struct{}
+
+func (s *S1) M() {}
+
+type S2 struct {
+	F struct{ *S1 }
+}
+
+func F() {
+	_ = struct{ *S1 }{}
+}
diff --git a/test/fixedbugs/issue4748.go b/test/fixedbugs/issue4748.go
new file mode 100644
index 0000000..73c7539
--- /dev/null
+++ b/test/fixedbugs/issue4748.go
@@ -0,0 +1,20 @@
+// 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.
+
+// Issue 4748.
+// This program used to complain because inlining created two exit labels.
+
+package main
+
+func jump() {
+        goto exit
+exit:
+        return
+}
+func main() {
+        jump()
+        jump()
+}
diff --git a/test/fixedbugs/issue4752.go b/test/fixedbugs/issue4752.go
new file mode 100644
index 0000000..d6781e3
--- /dev/null
+++ b/test/fixedbugs/issue4752.go
@@ -0,0 +1,26 @@
+// 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.
+
+package main
+
+func F(xi, yi interface{}) uint64 {
+	x, y := xi.(uint64), yi.(uint64)
+	return x &^ y
+}
+
+func G(xi, yi interface{}) uint64 {
+	return xi.(uint64) &^ yi.(uint64) // generates incorrect code
+}
+
+func main() {
+	var x, y uint64 = 0, 1 << 63
+	f := F(x, y)
+	g := G(x, y)
+	if f != 0 || g != 0 {
+		println("F", f, "G", g)
+		panic("bad")
+	}
+}
diff --git a/test/fixedbugs/issue4785.go b/test/fixedbugs/issue4785.go
new file mode 100644
index 0000000..c3dd629
--- /dev/null
+++ b/test/fixedbugs/issue4785.go
@@ -0,0 +1,20 @@
+// 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.
+
+// issue 4785: used to fail to compile
+
+package main
+
+func t(x, y interface{}) interface{} {
+	return x.(float64) > y.(float64)
+}
+
+func main() {
+	v := t(1.0, 2.0)
+	if v != false {
+		panic("bad comparison")
+	}
+}
diff --git a/test/fixedbugs/issue4879.dir/a.go b/test/fixedbugs/issue4879.dir/a.go
new file mode 100644
index 0000000..7ee7c48
--- /dev/null
+++ b/test/fixedbugs/issue4879.dir/a.go
@@ -0,0 +1,33 @@
+package a
+
+import (
+	"unsafe"
+)
+
+type Collection struct {
+	root unsafe.Pointer
+}
+
+type nodeLoc struct{}
+
+type slice []int
+
+type maptype map[int]int
+
+func MakePrivateCollection() *Collection {
+	return &Collection{
+		root: unsafe.Pointer(&nodeLoc{}),
+	}
+}
+
+func MakePrivateCollection2() *Collection {
+	return &Collection{
+		root: unsafe.Pointer(&slice{}),
+	}
+}
+func MakePrivateCollection3() *Collection {
+	return &Collection{
+		root: unsafe.Pointer(&maptype{}),
+	}
+}
+
diff --git a/test/fixedbugs/issue4879.dir/b.go b/test/fixedbugs/issue4879.dir/b.go
new file mode 100644
index 0000000..d8fb569
--- /dev/null
+++ b/test/fixedbugs/issue4879.dir/b.go
@@ -0,0 +1,9 @@
+package b
+
+import "./a"
+
+func F() {
+      a.MakePrivateCollection()
+      a.MakePrivateCollection2()
+      a.MakePrivateCollection3()
+}
diff --git a/test/fixedbugs/issue4879.go b/test/fixedbugs/issue4879.go
new file mode 100644
index 0000000..842c811
--- /dev/null
+++ b/test/fixedbugs/issue4879.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// 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.
+
+// Issue 4879: export data misses the '&' for some
+// composite literals in inlined bodies.
+
+package ignored
diff --git a/test/fixedbugs/issue4932.dir/foo.go b/test/fixedbugs/issue4932.dir/foo.go
new file mode 100644
index 0000000..19b73a0
--- /dev/null
+++ b/test/fixedbugs/issue4932.dir/foo.go
@@ -0,0 +1,7 @@
+// 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 foo
+
+type Op struct{}
diff --git a/test/fixedbugs/issue4932.dir/state.go b/test/fixedbugs/issue4932.dir/state.go
new file mode 100644
index 0000000..c017b96
--- /dev/null
+++ b/test/fixedbugs/issue4932.dir/state.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 state
+
+import "./foo"
+
+func Public() {
+	var s Settings
+	s.op()
+}
+
+type State struct{}
+
+func (s *State) x(*Settings) {}
+
+type Settings struct{}
+
+func (c *Settings) x() {
+	run([]foo.Op{{}})
+}
+
+func run([]foo.Op) {}
+
+func (s *Settings) op() foo.Op {
+	return foo.Op{}
+}
diff --git a/test/fixedbugs/issue4932.dir/state2.go b/test/fixedbugs/issue4932.dir/state2.go
new file mode 100644
index 0000000..50f75db
--- /dev/null
+++ b/test/fixedbugs/issue4932.dir/state2.go
@@ -0,0 +1,9 @@
+// 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 state2
+
+import "./state"
+
+type Foo *state.State
diff --git a/test/fixedbugs/issue4932.go b/test/fixedbugs/issue4932.go
new file mode 100644
index 0000000..2a6bc69
--- /dev/null
+++ b/test/fixedbugs/issue4932.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// 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.
+
+// Issue 4932: regression in export of composite literals.
+
+package ignored
diff --git a/test/fixedbugs/issue887.go b/test/fixedbugs/issue887.go
new file mode 100644
index 0000000..5bc193b
--- /dev/null
+++ b/test/fixedbugs/issue887.go
@@ -0,0 +1,36 @@
+// compile
+
+// 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.
+
+// Used to leak registers on 8g.
+
+package p
+
+func f(x byte, y uint64) {
+	var r byte
+	switch y {
+	case 1:
+		r = x << y // '>>' triggers it too
+	case 2:
+		r = x << y
+	case 3:
+		r = x << y
+	case 4:
+		r = x << y
+	case 5:
+		r = x << y
+	case 6:
+		r = x << y
+	case 7:
+		r = x << y
+	case 8:
+		r = x << y
+	case 9:
+		r = x << y
+	case 10:
+		r = x << y
+	}
+	_ = r
+}
diff --git a/test/float_lit.go b/test/float_lit.go
index 2912c37..4efae23 100644
--- a/test/float_lit.go
+++ b/test/float_lit.go
@@ -196,4 +196,8 @@ func main() {
 	if !close(-210.012e19, -210012, 1000, 19) {
 		print("-210.012e19 is ", -210.012e19, "\n")
 	}
+
+	if bad {
+		panic("float_lit")
+	}
 }
diff --git a/test/floatcmp.go b/test/floatcmp.go
index f9f59a9..6c424cc 100644
--- a/test/floatcmp.go
+++ b/test/floatcmp.go
@@ -87,4 +87,7 @@ func main() {
 			println(t.name, "=", t.expr, "want", t.want)
 		}
 	}
+	if bad {
+		panic("floatcmp failed")
+	}
 }
diff --git a/test/func7.go b/test/func7.go
index 6f6766f..2d646b6 100644
--- a/test/func7.go
+++ b/test/func7.go
@@ -17,7 +17,7 @@ func f() int {
 
 func g() int {
 	if !calledf {
-		println("BUG: func7 - called g before f")
+		panic("BUG: func7 - called g before f")
 	}
 	return 0
 }
@@ -28,4 +28,3 @@ func main() {
 		panic("wrong answer")
 	}
 }
-
diff --git a/test/func8.go b/test/func8.go
index 7defe26..1305180 100644
--- a/test/func8.go
+++ b/test/func8.go
@@ -37,13 +37,13 @@ func y() string {
 
 func main() {
 	if f() == g() {
-		println("wrong f,g order")
+		panic("wrong f,g order")
 	}
 
 	if x() == (y() == "abc") {
 		panic("wrong compare")
 	}
 	if xy != "xy" {
-		println("wrong x,y order")
+		panic("wrong x,y order")
 	}
 }
diff --git a/test/golden.out b/test/golden.out
index 376af8e..742a5d3 100644
--- a/test/golden.out
+++ b/test/golden.out
@@ -16,7 +16,7 @@
 == fixedbugs/
 
 =========== fixedbugs/bug429.go
-throw: all goroutines are asleep - deadlock!
+fatal error: all goroutines are asleep - deadlock!
 
 == bugs/
 
diff --git a/test/import2.dir/import2.go b/test/import2.dir/import2.go
new file mode 100644
index 0000000..8bb1eb9
--- /dev/null
+++ b/test/import2.dir/import2.go
@@ -0,0 +1,42 @@
+// 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.
+
+// Various declarations of exported variables and functions.
+
+package p
+
+var C1 chan <- chan int = (chan<- (chan int))(nil)
+var C2 chan (<- chan int) = (chan (<-chan int))(nil)
+var C3 <- chan chan int = (<-chan (chan int))(nil)
+var C4 chan chan <- int = (chan (chan<- int))(nil)
+
+var C5 <- chan <- chan int = (<-chan (<-chan int))(nil)
+var C6 chan <- <- chan int = (chan<- (<-chan int))(nil)
+var C7 chan <- chan <- int = (chan<- (chan<- int))(nil)
+
+var C8 <- chan <- chan chan int = (<-chan (<-chan (chan int)))(nil)
+var C9 <- chan chan <- chan int = (<-chan (chan<- (chan int)))(nil)
+var C10 chan <- <- chan chan int = (chan<- (<-chan (chan int)))(nil)
+var C11 chan <- chan <- chan int = (chan<- (chan<- (chan int)))(nil)
+var C12 chan chan <- <- chan int = (chan (chan<- (<-chan int)))(nil)
+var C13 chan chan <- chan <- int = (chan (chan<- (chan<- int)))(nil)
+
+var R1 chan<- (chan int) = (chan <- chan int)(nil)
+var R3 <-chan (chan int) = (<- chan chan int)(nil)
+var R4 chan (chan<- int) = (chan chan <- int)(nil)
+
+var R5 <-chan (<-chan int) = (<- chan <- chan int)(nil)
+var R6 chan<- (<-chan int) = (chan <- <- chan int)(nil)
+var R7 chan<- (chan<- int) = (chan <- chan <- int)(nil)
+
+var R8 <-chan (<-chan (chan int)) = (<- chan <- chan chan int)(nil)
+var R9 <-chan (chan<- (chan int)) = (<- chan chan <- chan int)(nil)
+var R10 chan<- (<-chan (chan int)) = (chan <- <- chan chan int)(nil)
+var R11 chan<- (chan<- (chan int)) = (chan <- chan <- chan int)(nil)
+var R12 chan (chan<- (<-chan int)) = (chan chan <- <- chan int)(nil)
+var R13 chan (chan<- (chan<- int)) = (chan chan <- chan <- int)(nil)
+
+var F1 func() func() int
+func F2() func() func() int
+func F3(func() func() int)
diff --git a/test/import2.dir/import3.go b/test/import2.dir/import3.go
new file mode 100644
index 0000000..d7fe37b
--- /dev/null
+++ b/test/import2.dir/import3.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.
+
+// Test that all the types from import2.go made it
+// intact and with the same meaning, by assigning to or using them.
+
+package main
+
+import "./import2"
+
+func f3(func() func() int)
+
+func main() {
+	p.F3(p.F1)
+	p.F3(p.F2())
+	f3(p.F1)
+	f3(p.F2())
+
+	p.C1 = (chan<- (chan int))(nil)
+	p.C2 = (chan (<-chan int))(nil)
+	p.C3 = (<-chan (chan int))(nil)
+	p.C4 = (chan (chan<- int))(nil)
+
+	p.C5 = (<-chan (<-chan int))(nil)
+	p.C6 = (chan<- (<-chan int))(nil)
+	p.C7 = (chan<- (chan<- int))(nil)
+
+	p.C8 = (<-chan (<-chan (chan int)))(nil)
+	p.C9 = (<-chan (chan<- (chan int)))(nil)
+	p.C10 = (chan<- (<-chan (chan int)))(nil)
+	p.C11 = (chan<- (chan<- (chan int)))(nil)
+	p.C12 = (chan (chan<- (<-chan int)))(nil)
+	p.C13 = (chan (chan<- (chan<- int)))(nil)
+
+	p.R1 = (chan <- chan int)(nil)
+	p.R3 = (<- chan chan int)(nil)
+	p.R4 = (chan chan <- int)(nil)
+
+	p.R5 = (<- chan <- chan int)(nil)
+	p.R6 = (chan <- <- chan int)(nil)
+	p.R7 = (chan <- chan <- int)(nil)
+
+	p.R8 = (<- chan <- chan chan int)(nil)
+	p.R9 = (<- chan chan <- chan int)(nil)
+	p.R10 = (chan <- <- chan chan int)(nil)
+	p.R11 = (chan <- chan <- chan int)(nil)
+	p.R12 = (chan chan <- <- chan int)(nil)
+	p.R13 = (chan chan <- chan <- int)(nil)
+
+}
+
diff --git a/test/import2.go b/test/import2.go
index 5c275f3..f8d0b0a 100644
--- a/test/import2.go
+++ b/test/import2.go
@@ -1,45 +1,8 @@
-// skip # used by import3
+// compiledir
 
 // 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.
 
-// Various declarations of exported variables and functions.
-// Imported by import3.go.
-
-package p
-
-var C1 chan <- chan int = (chan<- (chan int))(nil)
-var C2 chan (<- chan int) = (chan (<-chan int))(nil)
-var C3 <- chan chan int = (<-chan (chan int))(nil)
-var C4 chan chan <- int = (chan (chan<- int))(nil)
-
-var C5 <- chan <- chan int = (<-chan (<-chan int))(nil)
-var C6 chan <- <- chan int = (chan<- (<-chan int))(nil)
-var C7 chan <- chan <- int = (chan<- (chan<- int))(nil)
-
-var C8 <- chan <- chan chan int = (<-chan (<-chan (chan int)))(nil)
-var C9 <- chan chan <- chan int = (<-chan (chan<- (chan int)))(nil)
-var C10 chan <- <- chan chan int = (chan<- (<-chan (chan int)))(nil)
-var C11 chan <- chan <- chan int = (chan<- (chan<- (chan int)))(nil)
-var C12 chan chan <- <- chan int = (chan (chan<- (<-chan int)))(nil)
-var C13 chan chan <- chan <- int = (chan (chan<- (chan<- int)))(nil)
-
-var R1 chan<- (chan int) = (chan <- chan int)(nil)
-var R3 <-chan (chan int) = (<- chan chan int)(nil)
-var R4 chan (chan<- int) = (chan chan <- int)(nil)
-
-var R5 <-chan (<-chan int) = (<- chan <- chan int)(nil)
-var R6 chan<- (<-chan int) = (chan <- <- chan int)(nil)
-var R7 chan<- (chan<- int) = (chan <- chan <- int)(nil)
-
-var R8 <-chan (<-chan (chan int)) = (<- chan <- chan chan int)(nil)
-var R9 <-chan (chan<- (chan int)) = (<- chan chan <- chan int)(nil)
-var R10 chan<- (<-chan (chan int)) = (chan <- <- chan chan int)(nil)
-var R11 chan<- (chan<- (chan int)) = (chan <- chan <- chan int)(nil)
-var R12 chan (chan<- (<-chan int)) = (chan chan <- <- chan int)(nil)
-var R13 chan (chan<- (chan<- int)) = (chan chan <- chan <- int)(nil)
-
-var F1 func() func() int
-func F2() func() func() int
-func F3(func() func() int)
+// Tests that export data does not corrupt type syntax.
+package ignored
diff --git a/test/import3.go b/test/import3.go
deleted file mode 100644
index 274fcfe..0000000
--- a/test/import3.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// $G $D/import2.go && $G $D/$F.go
-
-// 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 that all the types from import2.go made it
-// intact and with the same meaning, by assigning to or using them.
-
-package main
-
-import "./import2"
-
-func f3(func() func() int)
-
-func main() {
-	p.F3(p.F1)
-	p.F3(p.F2())
-	f3(p.F1)
-	f3(p.F2())
-
-	p.C1 = (chan<- (chan int))(nil)
-	p.C2 = (chan (<-chan int))(nil)
-	p.C3 = (<-chan (chan int))(nil)
-	p.C4 = (chan (chan<- int))(nil)
-
-	p.C5 = (<-chan (<-chan int))(nil)
-	p.C6 = (chan<- (<-chan int))(nil)
-	p.C7 = (chan<- (chan<- int))(nil)
-
-	p.C8 = (<-chan (<-chan (chan int)))(nil)
-	p.C9 = (<-chan (chan<- (chan int)))(nil)
-	p.C10 = (chan<- (<-chan (chan int)))(nil)
-	p.C11 = (chan<- (chan<- (chan int)))(nil)
-	p.C12 = (chan (chan<- (<-chan int)))(nil)
-	p.C13 = (chan (chan<- (chan<- int)))(nil)
-
-	p.R1 = (chan <- chan int)(nil)
-	p.R3 = (<- chan chan int)(nil)
-	p.R4 = (chan chan <- int)(nil)
-
-	p.R5 = (<- chan <- chan int)(nil)
-	p.R6 = (chan <- <- chan int)(nil)
-	p.R7 = (chan <- chan <- int)(nil)
-
-	p.R8 = (<- chan <- chan chan int)(nil)
-	p.R9 = (<- chan chan <- chan int)(nil)
-	p.R10 = (chan <- <- chan chan int)(nil)
-	p.R11 = (chan <- chan <- chan int)(nil)
-	p.R12 = (chan chan <- <- chan int)(nil)
-	p.R13 = (chan chan <- chan <- int)(nil)
-
-}
-
diff --git a/test/import4.dir/empty.go b/test/import4.dir/empty.go
new file mode 100644
index 0000000..c8214f3
--- /dev/null
+++ b/test/import4.dir/empty.go
@@ -0,0 +1,10 @@
+// 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 P
+
+import ( )
+const ( )
+var ( )
+type ( )
diff --git a/test/import4.dir/import4.go b/test/import4.dir/import4.go
new file mode 100644
index 0000000..b9f973f
--- /dev/null
+++ b/test/import4.dir/import4.go
@@ -0,0 +1,24 @@
+// 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.
+
+// Verify that various kinds of "imported and not used"
+// errors are caught by the compiler.
+// Does not compile.
+
+package main
+
+// standard
+import "fmt"	// ERROR "imported and not used.*fmt"
+
+// renamed
+import X "math"	// ERROR "imported and not used.*math"
+
+// import dot
+import . "bufio"	// ERROR "imported and not used.*bufio"
+
+// again, package without anything in it
+import "./empty"	// ERROR "imported and not used.*empty"
+import Z "./empty"	// ERROR "imported and not used.*empty"
+import . "./empty"	// ERROR "imported and not used.*empty"
+
diff --git a/test/import4.go b/test/import4.go
index cbfebf7..875bf89 100644
--- a/test/import4.go
+++ b/test/import4.go
@@ -1,4 +1,4 @@
-// $G $D/empty.go && errchk $G $D/$F.go
+// errorcheckdir
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -8,19 +8,4 @@
 // errors are caught by the compiler.
 // Does not compile.
 
-package main
-
-// standard
-import "fmt"	// ERROR "imported and not used.*fmt"
-
-// renamed
-import X "math"	// ERROR "imported and not used.*math"
-
-// import dot
-import . "bufio"	// ERROR "imported and not used.*bufio"
-
-// again, package without anything in it
-import "./empty"	// ERROR "imported and not used.*empty"
-import Z "./empty"	// ERROR "imported and not used.*empty"
-import . "./empty"	// ERROR "imported and not used.*empty"
-
+package ignored
diff --git a/test/index.go b/test/index.go
index f9e2413..daab45f 100644
--- a/test/index.go
+++ b/test/index.go
@@ -1,23 +1,19 @@
-// $G $D/$F.go && $L $F.$A &&
-// ./$A.out -pass 0 >tmp.go && $G tmp.go && $L -o $A.out1 tmp.$A && ./$A.out1 &&
-// ./$A.out -pass 1 >tmp.go && errchk $G -e tmp.go &&
-// ./$A.out -pass 2 >tmp.go && errchk $G -e tmp.go
-// rm -f tmp.go $A.out1
+// skip
 
 // 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.
 
 // Generate test of index and slice bounds checks.
-// The output is compiled and run.
+// The actual tests are index0.go, index1.go, index2.go.
 
 package main
 
 import (
 	"bufio"
-	"flag"
 	"fmt"
 	"os"
+	"unsafe"
 )
 
 const prolog = `
@@ -151,14 +147,13 @@ func bug() {
 func main() {
 `
 
-// Passes:
+// pass variable set in index[012].go
 //	0 - dynamic checks
 //	1 - static checks of invalid constants (cannot assign to types)
 //	2 - static checks of array bounds
-var pass = flag.Int("pass", 0, "which test (0,1,2)")
 
 func testExpr(b *bufio.Writer, expr string) {
-	if *pass == 0 {
+	if pass == 0 {
 		fmt.Fprintf(b, "\ttest(func(){use(%s)}, %q)\n", expr, expr)
 	} else {
 		fmt.Fprintf(b, "\tuse(%s)  // ERROR \"index|overflow\"\n", expr)
@@ -168,12 +163,10 @@ func testExpr(b *bufio.Writer, expr string) {
 func main() {
 	b := bufio.NewWriter(os.Stdout)
 
-	flag.Parse()
-	
-	if *pass == 0 {
-		fmt.Fprint(b, "// $G $D/$F.go && $L $F.$A && ./$A.out\n\n")
+	if pass == 0 {
+		fmt.Fprint(b, "// run\n\n")
 	} else {
-		fmt.Fprint(b, "// errchk $G -e $D/$F.go\n\n")
+		fmt.Fprint(b, "// errorcheck\n\n")
 	}
 	fmt.Fprint(b, prolog)
 	
@@ -221,6 +214,11 @@ func main() {
 				// the next pass from running.
 				// So run it as a separate check.
 				thisPass = 1
+			} else if a == "s" && n == "" && (i == "i64big" || i == "i64bigger") && unsafe.Sizeof(int(0)) > 4 {
+				// If int is 64 bits, these huge
+				// numbers do fit in an int, so they
+				// are not rejected at compile time.
+				thisPass = 0
 			} else {
 				thisPass = 2
 			}
@@ -232,7 +230,7 @@ func main() {
 		}
 
 		// Only print the test case if it is appropriate for this pass.
-		if thisPass == *pass {
+		if thisPass == pass {
 			pae := p+a+e+big
 			cni := c+n+i
 			
diff --git a/test/index0.go b/test/index0.go
new file mode 100644
index 0000000..04a1619
--- /dev/null
+++ b/test/index0.go
@@ -0,0 +1,12 @@
+// runoutput ./index.go
+
+// 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.
+
+// Generate test of index and slice bounds checks.
+// The output is compiled and run.
+
+package main
+
+const pass = 0
diff --git a/test/index1.go b/test/index1.go
new file mode 100644
index 0000000..e28efa3
--- /dev/null
+++ b/test/index1.go
@@ -0,0 +1,12 @@
+// errorcheckoutput ./index.go
+
+// 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.
+
+// Generate test of index and slice bounds checks.
+// The output is error checked.
+
+package main
+
+const pass = 1
diff --git a/test/index2.go b/test/index2.go
new file mode 100644
index 0000000..a7107cc
--- /dev/null
+++ b/test/index2.go
@@ -0,0 +1,12 @@
+// errorcheckoutput ./index.go
+
+// 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.
+
+// Generate test of index and slice bounds checks.
+// The output is error checked.
+
+package main
+
+const pass = 2
diff --git a/test/init1.go b/test/init1.go
index a888ad7..f6eda6e 100644
--- a/test/init1.go
+++ b/test/init1.go
@@ -33,6 +33,7 @@ func init() {
 	sys1 := memstats.Sys
 	if sys1-sys > chunk*50 {
 		println("allocated 1000 chunks of", chunk, "and used ", sys1-sys, "memory")
+		panic("init1")
 	}
 }
 
diff --git a/test/initializerr.go b/test/initializerr.go
index 48908c3..ca05414 100644
--- a/test/initializerr.go
+++ b/test/initializerr.go
@@ -26,3 +26,15 @@ var a5 = []byte { x: 2 }	// ERROR "index"
 
 var ok1 = S { }	// should be ok
 var ok2 = T { S: ok1 }	// should be ok
+
+// These keys can be computed at compile time but they are
+// not constants as defined by the spec, so they do not trigger
+// compile-time errors about duplicate key values.
+// See issue 4555.
+
+type Key struct {X, Y int}
+
+var _ = map[Key]string{
+	Key{1,2}: "hello",
+	Key{1,2}: "world",
+}
diff --git a/test/interface/embed0.go b/test/interface/embed0.go
deleted file mode 100644
index e2ee20a..0000000
--- a/test/interface/embed0.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// skip # used by embed1.go
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test that embedded interface types can have local methods.
-
-package p
-
-type T int
-func (t T) m() {}
-
-type I interface { m() }
-type J interface { I }
-
-func main() {
-	var i I
-	var j J
-	var t T
-	i = t
-	j = t
-	_ = i
-	_ = j
-	i = j
-	_ = i
-	j = i
-	_ = j
-}
diff --git a/test/interface/embed1.dir/embed0.go b/test/interface/embed1.dir/embed0.go
new file mode 100644
index 0000000..728bec7
--- /dev/null
+++ b/test/interface/embed1.dir/embed0.go
@@ -0,0 +1,27 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that embedded interface types can have local methods.
+
+package p
+
+type T int
+func (t T) m() {}
+
+type I interface { m() }
+type J interface { I }
+
+func main() {
+	var i I
+	var j J
+	var t T
+	i = t
+	j = t
+	_ = i
+	_ = j
+	i = j
+	_ = i
+	j = i
+	_ = j
+}
diff --git a/test/interface/embed1.dir/embed1.go b/test/interface/embed1.dir/embed1.go
new file mode 100644
index 0000000..7dfb1db
--- /dev/null
+++ b/test/interface/embed1.dir/embed1.go
@@ -0,0 +1,43 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that embedded interface types can have local methods.
+
+package main
+
+import "./embed0"
+
+type T int
+func (t T) m() {}
+
+type I interface { m() }
+type J interface { I }
+
+type PI interface { p.I }
+type PJ interface { p.J }
+
+func main() {
+	var i I
+	var j J
+	var t T
+	i = t
+	j = t
+	_ = i
+	_ = j
+	i = j
+	_ = i
+	j = i
+	_ = j
+	var pi PI
+	var pj PJ
+	var pt p.T
+	pi = pt
+	pj = pt
+	_ = pi
+	_ = pj
+	pi = pj
+	_ = pi
+	pj = pi
+	_ = pj
+}
diff --git a/test/interface/embed1.go b/test/interface/embed1.go
index ee502a1..784b82b 100644
--- a/test/interface/embed1.go
+++ b/test/interface/embed1.go
@@ -1,4 +1,4 @@
-// $G $D/embed0.go && $G $D/$F.go && $L $F.$A && ./$A.out
+// rundir
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -6,40 +6,4 @@
 
 // Test that embedded interface types can have local methods.
 
-package main
-
-import "./embed0"
-
-type T int
-func (t T) m() {}
-
-type I interface { m() }
-type J interface { I }
-
-type PI interface { p.I }
-type PJ interface { p.J }
-
-func main() {
-	var i I
-	var j J
-	var t T
-	i = t
-	j = t
-	_ = i
-	_ = j
-	i = j
-	_ = i
-	j = i
-	_ = j
-	var pi PI
-	var pj PJ
-	var pt p.T
-	pi = pt
-	pj = pt
-	_ = pi
-	_ = pj
-	pi = pj
-	_ = pi
-	pj = pi
-	_ = pj
-}
+package ignored
diff --git a/test/interface/explicit.go b/test/interface/explicit.go
index d19480a..eb81156 100644
--- a/test/interface/explicit.go
+++ b/test/interface/explicit.go
@@ -15,6 +15,10 @@ type T struct {
 
 var t *T
 
+type X int
+
+func (x *X) M() {}
+
 type I interface {
 	M()
 }
@@ -40,7 +44,7 @@ func main() {
 	// because i has an extra method
 	// that t does not, so i cannot contain a t.
 	i = t // ERROR "incompatible|missing M method"
-	t = i // ERROR "incompatible|need type assertion"
+	t = i // ERROR "incompatible|assignment$"
 
 	i = i2 // ok
 	i2 = i // ERROR "incompatible|missing N method"
@@ -66,6 +70,8 @@ func (Int) M(float64) {}
 
 var _ = m.(Int) // ERROR "impossible type assertion"
 
+var _ = m.(X) // ERROR "pointer receiver"
+
 var ii int
 var jj Int
 
diff --git a/test/interface/private.dir/private1.go b/test/interface/private.dir/private1.go
new file mode 100644
index 0000000..75eee51
--- /dev/null
+++ b/test/interface/private.dir/private1.go
@@ -0,0 +1,18 @@
+// 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.
+
+// Imported by private.go, which should not be able to see the private method.
+
+package p
+
+type Exported interface {
+	private()
+}
+
+type Implementation struct{}
+
+func (p *Implementation) private() {}
+
+var X = new(Implementation)
+
diff --git a/test/interface/private.dir/prog.go b/test/interface/private.dir/prog.go
new file mode 100644
index 0000000..abea7d6
--- /dev/null
+++ b/test/interface/private.dir/prog.go
@@ -0,0 +1,33 @@
+// 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.
+
+// Test that unexported methods are not visible outside the package.
+// Does not compile.
+
+package main
+
+import "./private1"
+
+type Exported interface {
+	private()
+}
+
+type Implementation struct{}
+
+func (p *Implementation) private() {}
+
+func main() {
+	var x Exported
+	x = new(Implementation)
+	x.private()
+
+	var px p.Exported
+	px = p.X
+
+	px.private()			// ERROR "private"
+
+	px = new(Implementation)	// ERROR "private"
+
+	x = px				// ERROR "private"
+}
diff --git a/test/interface/private.go b/test/interface/private.go
index 14dfc1a..a0da249 100644
--- a/test/interface/private.go
+++ b/test/interface/private.go
@@ -1,4 +1,4 @@
-// $G $D/${F}1.go && errchk $G $D/$F.go
+// errorcheckdir
 
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -7,29 +7,4 @@
 // Test that unexported methods are not visible outside the package.
 // Does not compile.
 
-package main
-
-import "./private1"
-
-type Exported interface {
-	private()
-}
-
-type Implementation struct{}
-
-func (p *Implementation) private() {}
-
-func main() {
-	var x Exported
-	x = new(Implementation)
-	x.private()
-
-	var px p.Exported
-	px = p.X
-
-	px.private()			// ERROR "private"
-
-	px = new(Implementation)	// ERROR "private"
-
-	x = px				// ERROR "private"
-}
+package ignored
diff --git a/test/interface/private1.go b/test/interface/private1.go
deleted file mode 100644
index 3281c38..0000000
--- a/test/interface/private1.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// skip # used by private.go
-
-// 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.
-
-// Imported by private.go, which should not be able to see the private method.
-
-package p
-
-type Exported interface {
-	private()
-}
-
-type Implementation struct{}
-
-func (p *Implementation) private() {}
-
-var X = new(Implementation)
-
diff --git a/test/interface/recursive1.dir/recursive1.go b/test/interface/recursive1.dir/recursive1.go
new file mode 100644
index 0000000..441f0ec
--- /dev/null
+++ b/test/interface/recursive1.dir/recursive1.go
@@ -0,0 +1,15 @@
+// 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.
+
+// Mutually recursive type definitions imported and used by recursive1.go.
+
+package p
+
+type I1 interface {
+	F() I2
+}
+
+type I2 interface {
+	I1
+}
diff --git a/test/interface/recursive1.dir/recursive2.go b/test/interface/recursive1.dir/recursive2.go
new file mode 100644
index 0000000..e8048c6
--- /dev/null
+++ b/test/interface/recursive1.dir/recursive2.go
@@ -0,0 +1,20 @@
+// 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 that the mutually recursive types in recursive1.go made it
+// intact and with the same meaning, by assigning to or using them.
+
+package main
+
+import "./recursive1"
+
+func main() {
+	var i1 p.I1
+	var i2 p.I2
+	i1 = i2
+	i2 = i1
+	i1 = i2.F()
+	i2 = i1.F()
+	_, _ = i1, i2
+}
diff --git a/test/interface/recursive1.go b/test/interface/recursive1.go
index cc3cdc3..62f6108 100644
--- a/test/interface/recursive1.go
+++ b/test/interface/recursive1.go
@@ -1,4 +1,4 @@
-// skip # used by recursive2
+// compiledir
 
 // Copyright 2012 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -6,12 +6,4 @@
 
 // Mutually recursive type definitions imported and used by recursive1.go.
 
-package p
-
-type I1 interface {
-	F() I2
-}
-
-type I2 interface {
-	I1
-}
+package ignored
diff --git a/test/interface/recursive2.go b/test/interface/recursive2.go
deleted file mode 100644
index 5129ceb..0000000
--- a/test/interface/recursive2.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// $G $D/recursive1.go && $G $D/$F.go
-
-// 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 that the mutually recursive types in recursive1.go made it
-// intact and with the same meaning, by assigning to or using them.
-
-package main
-
-import "./recursive1"
-
-func main() {
-	var i1 p.I1
-	var i2 p.I2
-	i1 = i2
-	i2 = i1
-	i1 = i2.F()
-	i2 = i1.F()
-	_, _ = i1, i2
-}
diff --git a/test/linkx.go b/test/linkx.go
index d2c9545..12d446f 100644
--- a/test/linkx.go
+++ b/test/linkx.go
@@ -1,5 +1,8 @@
 // $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.
+
 // 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/test/literal.go b/test/literal.go
index ba185fc..c3d6bc1 100644
--- a/test/literal.go
+++ b/test/literal.go
@@ -24,7 +24,6 @@ func equal(a, b float32) bool {
 	return a == b
 }
 
-
 func main() {
 	// bool
 	var t bool = true
@@ -225,6 +224,6 @@ func main() {
 	assert(sj0 == sj3, "sj3")
 
 	if nbad > 0 {
-		println()
+		panic("literal failed")
 	}
 }
diff --git a/test/map.go b/test/map.go
index 6dec0df..041c8fb 100644
--- a/test/map.go
+++ b/test/map.go
@@ -41,7 +41,7 @@ func testbasic() {
 	for i := 0; i < len(mlit); i++ {
 		s := string([]byte{byte(i) + '0'})
 		if mlit[s] != i {
-			fmt.Printf("mlit[%s] = %d\n", s, mlit[s])
+			panic(fmt.Sprintf("mlit[%s] = %d\n", s, mlit[s]))
 		}
 	}
 
@@ -102,46 +102,46 @@ func testbasic() {
 
 	// test len
 	if len(mib) != count {
-		fmt.Printf("len(mib) = %d\n", len(mib))
+		panic(fmt.Sprintf("len(mib) = %d\n", len(mib)))
 	}
 	if len(mii) != count {
-		fmt.Printf("len(mii) = %d\n", len(mii))
+		panic(fmt.Sprintf("len(mii) = %d\n", len(mii)))
 	}
 	if len(mfi) != count {
-		fmt.Printf("len(mfi) = %d\n", len(mfi))
+		panic(fmt.Sprintf("len(mfi) = %d\n", len(mfi)))
 	}
 	if len(mif) != count {
-		fmt.Printf("len(mif) = %d\n", len(mif))
+		panic(fmt.Sprintf("len(mif) = %d\n", len(mif)))
 	}
 	if len(msi) != count {
-		fmt.Printf("len(msi) = %d\n", len(msi))
+		panic(fmt.Sprintf("len(msi) = %d\n", len(msi)))
 	}
 	if len(mis) != count {
-		fmt.Printf("len(mis) = %d\n", len(mis))
+		panic(fmt.Sprintf("len(mis) = %d\n", len(mis)))
 	}
 	if len(mss) != count {
-		fmt.Printf("len(mss) = %d\n", len(mss))
+		panic(fmt.Sprintf("len(mss) = %d\n", len(mss)))
 	}
 	if len(mspa) != count {
-		fmt.Printf("len(mspa) = %d\n", len(mspa))
+		panic(fmt.Sprintf("len(mspa) = %d\n", len(mspa)))
 	}
 	if len(mipT) != count {
-		fmt.Printf("len(mipT) = %d\n", len(mipT))
+		panic(fmt.Sprintf("len(mipT) = %d\n", len(mipT)))
 	}
 	if len(mpTi) != count {
-		fmt.Printf("len(mpTi) = %d\n", len(mpTi))
+		panic(fmt.Sprintf("len(mpTi) = %d\n", len(mpTi)))
 	}
 	//	if len(mti) != count {
-	//		fmt.Printf("len(mti) = %d\n", len(mti))
+	//              panic(fmt.Sprintf("len(mti) = %d\n", len(mti)))
 	//	}
 	if len(mipM) != count {
-		fmt.Printf("len(mipM) = %d\n", len(mipM))
+		panic(fmt.Sprintf("len(mipM) = %d\n", len(mipM)))
 	}
 	//	if len(mti) != count {
-	//		fmt.Printf("len(mti) = %d\n", len(mti))
+	//		panic(fmt.Sprintf("len(mti) = %d\n", len(mti)))
 	//	}
 	if len(mit) != count {
-		fmt.Printf("len(mit) = %d\n", len(mit))
+		panic(fmt.Sprintf("len(mit) = %d\n", len(mit)))
 	}
 
 	// test construction directly
@@ -151,48 +151,48 @@ func testbasic() {
 		f := float32(i)
 		// BUG m := M(i, i+1)
 		if mib[i] != (i != 0) {
-			fmt.Printf("mib[%d] = %t\n", i, mib[i])
+			panic(fmt.Sprintf("mib[%d] = %t\n", i, mib[i]))
 		}
 		if mii[i] != 10*i {
-			fmt.Printf("mii[%d] = %d\n", i, mii[i])
+			panic(fmt.Sprintf("mii[%d] = %d\n", i, mii[i]))
 		}
 		if mfi[f] != 10*i {
-			fmt.Printf("mfi[%d] = %d\n", i, mfi[f])
+			panic(fmt.Sprintf("mfi[%d] = %d\n", i, mfi[f]))
 		}
 		if mif[i] != 10.0*f {
-			fmt.Printf("mif[%d] = %g\n", i, mif[i])
+			panic(fmt.Sprintf("mif[%d] = %g\n", i, mif[i]))
 		}
 		if mis[i] != s {
-			fmt.Printf("mis[%d] = %s\n", i, mis[i])
+			panic(fmt.Sprintf("mis[%d] = %s\n", i, mis[i]))
 		}
 		if msi[s] != i {
-			fmt.Printf("msi[%s] = %d\n", s, msi[s])
+			panic(fmt.Sprintf("msi[%s] = %d\n", s, msi[s]))
 		}
 		if mss[s] != s10 {
-			fmt.Printf("mss[%s] = %g\n", s, mss[s])
+			panic(fmt.Sprintf("mss[%s] = %g\n", s, mss[s]))
 		}
 		for j := 0; j < len(mspa[s]); j++ {
 			if mspa[s][j] != s10 {
-				fmt.Printf("mspa[%s][%d] = %s\n", s, j, mspa[s][j])
+				panic(fmt.Sprintf("mspa[%s][%d] = %s\n", s, j, mspa[s][j]))
 			}
 		}
 		if mipT[i].i != int64(i) || mipT[i].f != f {
-			fmt.Printf("mipT[%d] = %v\n", i, mipT[i])
+			panic(fmt.Sprintf("mipT[%d] = %v\n", i, mipT[i]))
 		}
 		if mpTi[apT[i]] != i {
-			fmt.Printf("mpTi[apT[%d]] = %d\n", i, mpTi[apT[i]])
+			panic(fmt.Sprintf("mpTi[apT[%d]] = %d\n", i, mpTi[apT[i]]))
 		}
 		//	if(mti[t] != i) {
-		//		fmt.Printf("mti[%s] = %s\n", s, mti[t])
+		//		panic(fmt.Sprintf("mti[%s] = %s\n", s, mti[t]))
 		//	}
 		if mipM[i][i] != i+1 {
-			fmt.Printf("mipM[%d][%d] = %d\n", i, i, mipM[i][i])
+			panic(fmt.Sprintf("mipM[%d][%d] = %d\n", i, i, mipM[i][i]))
 		}
 		//	if(mti[t] != i) {
-		//		fmt.Printf("mti[%v] = %d\n", t, mti[t])
+		//		panic(fmt.Sprintf("mti[%v] = %d\n", t, mti[t]))
 		//	}
 		if mit[i].i != int64(i) || mit[i].f != f {
-			fmt.Printf("mit[%d] = {%d %g}\n", i, mit[i].i, mit[i].f)
+			panic(fmt.Sprintf("mit[%d] = {%d %g}\n", i, mit[i].i, mit[i].f))
 		}
 	}
 
@@ -204,131 +204,131 @@ func testbasic() {
 		{
 			_, b := mib[i]
 			if !b {
-				fmt.Printf("tuple existence decl: mib[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mib[%d]\n", i))
 			}
 			_, b = mib[i]
 			if !b {
-				fmt.Printf("tuple existence assign: mib[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mib[%d]\n", i))
 			}
 		}
 		{
 			_, b := mii[i]
 			if !b {
-				fmt.Printf("tuple existence decl: mii[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mii[%d]\n", i))
 			}
 			_, b = mii[i]
 			if !b {
-				fmt.Printf("tuple existence assign: mii[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mii[%d]\n", i))
 			}
 		}
 		{
 			_, b := mfi[f]
 			if !b {
-				fmt.Printf("tuple existence decl: mfi[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mfi[%d]\n", i))
 			}
 			_, b = mfi[f]
 			if !b {
-				fmt.Printf("tuple existence assign: mfi[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mfi[%d]\n", i))
 			}
 		}
 		{
 			_, b := mif[i]
 			if !b {
-				fmt.Printf("tuple existence decl: mif[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mif[%d]\n", i))
 			}
 			_, b = mif[i]
 			if !b {
-				fmt.Printf("tuple existence assign: mif[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mif[%d]\n", i))
 			}
 		}
 		{
 			_, b := mis[i]
 			if !b {
-				fmt.Printf("tuple existence decl: mis[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mis[%d]\n", i))
 			}
 			_, b = mis[i]
 			if !b {
-				fmt.Printf("tuple existence assign: mis[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mis[%d]\n", i))
 			}
 		}
 		{
 			_, b := msi[s]
 			if !b {
-				fmt.Printf("tuple existence decl: msi[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: msi[%d]\n", i))
 			}
 			_, b = msi[s]
 			if !b {
-				fmt.Printf("tuple existence assign: msi[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: msi[%d]\n", i))
 			}
 		}
 		{
 			_, b := mss[s]
 			if !b {
-				fmt.Printf("tuple existence decl: mss[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mss[%d]\n", i))
 			}
 			_, b = mss[s]
 			if !b {
-				fmt.Printf("tuple existence assign: mss[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mss[%d]\n", i))
 			}
 		}
 		{
 			_, b := mspa[s]
 			if !b {
-				fmt.Printf("tuple existence decl: mspa[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mspa[%d]\n", i))
 			}
 			_, b = mspa[s]
 			if !b {
-				fmt.Printf("tuple existence assign: mspa[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mspa[%d]\n", i))
 			}
 		}
 		{
 			_, b := mipT[i]
 			if !b {
-				fmt.Printf("tuple existence decl: mipT[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mipT[%d]\n", i))
 			}
 			_, b = mipT[i]
 			if !b {
-				fmt.Printf("tuple existence assign: mipT[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mipT[%d]\n", i))
 			}
 		}
 		{
 			_, b := mpTi[apT[i]]
 			if !b {
-				fmt.Printf("tuple existence decl: mpTi[apT[%d]]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mpTi[apT[%d]]\n", i))
 			}
 			_, b = mpTi[apT[i]]
 			if !b {
-				fmt.Printf("tuple existence assign: mpTi[apT[%d]]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mpTi[apT[%d]]\n", i))
 			}
 		}
 		{
 			_, b := mipM[i]
 			if !b {
-				fmt.Printf("tuple existence decl: mipM[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mipM[%d]\n", i))
 			}
 			_, b = mipM[i]
 			if !b {
-				fmt.Printf("tuple existence assign: mipM[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mipM[%d]\n", i))
 			}
 		}
 		{
 			_, b := mit[i]
 			if !b {
-				fmt.Printf("tuple existence decl: mit[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence decl: mit[%d]\n", i))
 			}
 			_, b = mit[i]
 			if !b {
-				fmt.Printf("tuple existence assign: mit[%d]\n", i)
+				panic(fmt.Sprintf("tuple existence assign: mit[%d]\n", i))
 			}
 		}
 		//		{
 		//			_, b := mti[t]
 		//			if !b {
-		//				fmt.Printf("tuple existence decl: mti[%d]\n", i)
+		//				panic(fmt.Sprintf("tuple existence decl: mti[%d]\n", i))
 		//			}
 		//			_, b = mti[t]
 		//			if !b {
-		//				fmt.Printf("tuple existence assign: mti[%d]\n", i)
+		//				panic(fmt.Sprintf("tuple existence assign: mti[%d]\n", i))
 		//			}
 		//		}
 	}
@@ -341,131 +341,131 @@ func testbasic() {
 		{
 			_, b := mib[i]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mib[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mib[%d]", i))
 			}
 			_, b = mib[i]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mib[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mib[%d]", i))
 			}
 		}
 		{
 			_, b := mii[i]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mii[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mii[%d]", i))
 			}
 			_, b = mii[i]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mii[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mii[%d]", i))
 			}
 		}
 		{
 			_, b := mfi[f]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mfi[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mfi[%d]", i))
 			}
 			_, b = mfi[f]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mfi[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mfi[%d]", i))
 			}
 		}
 		{
 			_, b := mif[i]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mif[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mif[%d]", i))
 			}
 			_, b = mif[i]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mif[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mif[%d]", i))
 			}
 		}
 		{
 			_, b := mis[i]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mis[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mis[%d]", i))
 			}
 			_, b = mis[i]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mis[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mis[%d]", i))
 			}
 		}
 		{
 			_, b := msi[s]
 			if b {
-				fmt.Printf("tuple nonexistence decl: msi[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: msi[%d]", i))
 			}
 			_, b = msi[s]
 			if b {
-				fmt.Printf("tuple nonexistence assign: msi[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: msi[%d]", i))
 			}
 		}
 		{
 			_, b := mss[s]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mss[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mss[%d]", i))
 			}
 			_, b = mss[s]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mss[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mss[%d]", i))
 			}
 		}
 		{
 			_, b := mspa[s]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mspa[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mspa[%d]", i))
 			}
 			_, b = mspa[s]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mspa[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mspa[%d]", i))
 			}
 		}
 		{
 			_, b := mipT[i]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mipT[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mipT[%d]", i))
 			}
 			_, b = mipT[i]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mipT[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mipT[%d]", i))
 			}
 		}
 		{
 			_, b := mpTi[apT[i]]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mpTi[apt[%d]]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mpTi[apt[%d]]", i))
 			}
 			_, b = mpTi[apT[i]]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mpTi[apT[%d]]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mpTi[apT[%d]]", i))
 			}
 		}
 		{
 			_, b := mipM[i]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mipM[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mipM[%d]", i))
 			}
 			_, b = mipM[i]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mipM[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mipM[%d]", i))
 			}
 		}
 		//		{
 		//			_, b := mti[t]
 		//			if b {
-		//				fmt.Printf("tuple nonexistence decl: mti[%d]", i)
+		//				panic(fmt.Sprintf("tuple nonexistence decl: mti[%d]", i))
 		//			}
 		//			_, b = mti[t]
 		//			if b {
-		//				fmt.Printf("tuple nonexistence assign: mti[%d]", i)
+		//				panic(fmt.Sprintf("tuple nonexistence assign: mti[%d]", i))
 		//			}
 		//		}
 		{
 			_, b := mit[i]
 			if b {
-				fmt.Printf("tuple nonexistence decl: mit[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence decl: mit[%d]", i))
 			}
 			_, b = mit[i]
 			if b {
-				fmt.Printf("tuple nonexistence assign: mit[%d]", i)
+				panic(fmt.Sprintf("tuple nonexistence assign: mit[%d]", i))
 			}
 		}
 	}
@@ -475,21 +475,25 @@ func testbasic() {
 		s := strconv.Itoa(i)
 		mspa[s][i%2] = "deleted"
 		if mspa[s][i%2] != "deleted" {
-			fmt.Printf("update mspa[%s][%d] = %s\n", s, i%2, mspa[s][i%2])
+			panic(fmt.Sprintf("update mspa[%s][%d] = %s\n", s, i%2, mspa[s][i%2]))
+
 		}
 
 		mipT[i].i += 1
 		if mipT[i].i != int64(i)+1 {
-			fmt.Printf("update mipT[%d].i = %d\n", i, mipT[i].i)
+			panic(fmt.Sprintf("update mipT[%d].i = %d\n", i, mipT[i].i))
+
 		}
 		mipT[i].f = float32(i + 1)
 		if mipT[i].f != float32(i+1) {
-			fmt.Printf("update mipT[%d].f = %g\n", i, mipT[i].f)
+			panic(fmt.Sprintf("update mipT[%d].f = %g\n", i, mipT[i].f))
+
 		}
 
 		mipM[i][i]++
 		if mipM[i][i] != (i+1)+1 {
-			fmt.Printf("update mipM[%d][%d] = %d\n", i, i, mipM[i][i])
+			panic(fmt.Sprintf("update mipM[%d][%d] = %d\n", i, i, mipM[i][i]))
+
 		}
 	}
 
@@ -519,29 +523,29 @@ func testfloat() {
 			nanb: "NaN",
 		}
 		if m[pz] != "+0" {
-			fmt.Println("float32 map cannot read back m[+0]:", m[pz])
+			panic(fmt.Sprintln("float32 map cannot read back m[+0]:", m[pz]))
 		}
 		if m[nz] != "+0" {
-			fmt.Println("float32 map does not treat", pz, "and", nz, "as equal for read")
-			fmt.Println("float32 map does not treat -0 and +0 as equal for read")
+			fmt.Sprintln("float32 map does not treat", pz, "and", nz, "as equal for read")
+			panic(fmt.Sprintln("float32 map does not treat -0 and +0 as equal for read"))
 		}
 		m[nz] = "-0"
 		if m[pz] != "-0" {
-			fmt.Println("float32 map does not treat -0 and +0 as equal for write")
+			panic(fmt.Sprintln("float32 map does not treat -0 and +0 as equal for write"))
 		}
 		if _, ok := m[nana]; ok {
-			fmt.Println("float32 map allows NaN lookup (a)")
+			panic(fmt.Sprintln("float32 map allows NaN lookup (a)"))
 		}
 		if _, ok := m[nanb]; ok {
-			fmt.Println("float32 map allows NaN lookup (b)")
+			panic(fmt.Sprintln("float32 map allows NaN lookup (b)"))
 		}
 		if len(m) != 3 {
-			fmt.Println("float32 map should have 3 entries:", m)
+			panic(fmt.Sprintln("float32 map should have 3 entries:", m))
 		}
 		m[nana] = "NaN"
 		m[nanb] = "NaN"
 		if len(m) != 5 {
-			fmt.Println("float32 map should have 5 entries:", m)
+			panic(fmt.Sprintln("float32 map should have 5 entries:", m))
 		}
 	}
 
@@ -559,25 +563,25 @@ func testfloat() {
 			nanb: "NaN",
 		}
 		if m[nz] != "+0" {
-			fmt.Println("float64 map does not treat -0 and +0 as equal for read")
+			panic(fmt.Sprintln("float64 map does not treat -0 and +0 as equal for read"))
 		}
 		m[nz] = "-0"
 		if m[pz] != "-0" {
-			fmt.Println("float64 map does not treat -0 and +0 as equal for write")
+			panic(fmt.Sprintln("float64 map does not treat -0 and +0 as equal for write"))
 		}
 		if _, ok := m[nana]; ok {
-			fmt.Println("float64 map allows NaN lookup (a)")
+			panic(fmt.Sprintln("float64 map allows NaN lookup (a)"))
 		}
 		if _, ok := m[nanb]; ok {
-			fmt.Println("float64 map allows NaN lookup (b)")
+			panic(fmt.Sprintln("float64 map allows NaN lookup (b)"))
 		}
 		if len(m) != 3 {
-			fmt.Println("float64 map should have 3 entries:", m)
+			panic(fmt.Sprintln("float64 map should have 3 entries:", m))
 		}
 		m[nana] = "NaN"
 		m[nanb] = "NaN"
 		if len(m) != 5 {
-			fmt.Println("float64 map should have 5 entries:", m)
+			panic(fmt.Sprintln("float64 map should have 5 entries:", m))
 		}
 	}
 
@@ -595,25 +599,25 @@ func testfloat() {
 			nanb: "NaN",
 		}
 		if m[nz] != "+0" {
-			fmt.Println("complex64 map does not treat -0 and +0 as equal for read")
+			panic(fmt.Sprintln("complex64 map does not treat -0 and +0 as equal for read"))
 		}
 		m[nz] = "-0"
 		if m[pz] != "-0" {
-			fmt.Println("complex64 map does not treat -0 and +0 as equal for write")
+			panic(fmt.Sprintln("complex64 map does not treat -0 and +0 as equal for write"))
 		}
 		if _, ok := m[nana]; ok {
-			fmt.Println("complex64 map allows NaN lookup (a)")
+			panic(fmt.Sprintln("complex64 map allows NaN lookup (a)"))
 		}
 		if _, ok := m[nanb]; ok {
-			fmt.Println("complex64 map allows NaN lookup (b)")
+			panic(fmt.Sprintln("complex64 map allows NaN lookup (b)"))
 		}
 		if len(m) != 3 {
-			fmt.Println("complex64 map should have 3 entries:", m)
+			panic(fmt.Sprintln("complex64 map should have 3 entries:", m))
 		}
 		m[nana] = "NaN"
 		m[nanb] = "NaN"
 		if len(m) != 5 {
-			fmt.Println("complex64 map should have 5 entries:", m)
+			panic(fmt.Sprintln("complex64 map should have 5 entries:", m))
 		}
 	}
 
@@ -631,25 +635,25 @@ func testfloat() {
 			nanb: "NaN",
 		}
 		if m[nz] != "+0" {
-			fmt.Println("complex128 map does not treat -0 and +0 as equal for read")
+			panic(fmt.Sprintln("complex128 map does not treat -0 and +0 as equal for read"))
 		}
 		m[nz] = "-0"
 		if m[pz] != "-0" {
-			fmt.Println("complex128 map does not treat -0 and +0 as equal for write")
+			panic(fmt.Sprintln("complex128 map does not treat -0 and +0 as equal for write"))
 		}
 		if _, ok := m[nana]; ok {
-			fmt.Println("complex128 map allows NaN lookup (a)")
+			panic(fmt.Sprintln("complex128 map allows NaN lookup (a)"))
 		}
 		if _, ok := m[nanb]; ok {
-			fmt.Println("complex128 map allows NaN lookup (b)")
+			panic(fmt.Sprintln("complex128 map allows NaN lookup (b)"))
 		}
 		if len(m) != 3 {
-			fmt.Println("complex128 map should have 3 entries:", m)
+			panic(fmt.Sprintln("complex128 map should have 3 entries:", m))
 		}
 		m[nana] = "NaN"
 		m[nanb] = "NaN"
 		if len(m) != 5 {
-			fmt.Println("complex128 map should have 5 entries:", m)
+			panic(fmt.Sprintln("complex128 map should have 5 entries:", m))
 		}
 	}
 }
@@ -685,7 +689,7 @@ func testnan() {
 		}
 		fails++
 		if fails == 4 {
-			fmt.Printf("too slow: %d inserts: %v; %d inserts: %v\n", n, t1, 2*n, t2)
+			panic(fmt.Sprintf("too slow: %d inserts: %v; %d inserts: %v\n", n, t1, 2*n, t2))
 			return
 		}
 		n *= 2
diff --git a/test/method.go b/test/method.go
index 0c239af..d97bc4a 100644
--- a/test/method.go
+++ b/test/method.go
@@ -128,13 +128,13 @@ func main() {
 		panic("fail")
 	}
 
-	var zs struct { S }
-	var zps struct { *S1 }
-	var zi struct { I }
-	var zpi struct { *I1 }
-	var zpt struct { *T1 }
-	var zt struct { T }
-	var zv struct { Val }
+	var zs struct{ S }
+	var zps struct{ *S1 }
+	var zi struct{ I }
+	var zpi struct{ *I1 }
+	var zpt struct{ *T1 }
+	var zt struct{ T }
+	var zv struct{ Val }
 
 	if zs.val() != 1 {
 		println("zs.val:", zs.val())
@@ -247,4 +247,61 @@ func main() {
 		println("zv.val():", zv.val())
 		panic("fail")
 	}
+
+	promotion()
+}
+
+type A struct{ B }
+type B struct {
+	C
+	*D
+}
+type C int
+
+func (C) f()  {} // value receiver, direct field of A
+func (*C) g() {} // pointer receiver
+
+type D int
+
+func (D) h()  {} // value receiver, indirect field of A
+func (*D) i() {} // pointer receiver
+
+func expectPanic() {
+	if r := recover(); r == nil {
+		panic("expected nil dereference")
+	}
+}
+
+func promotion() {
+	var a A
+	// Addressable value receiver.
+	a.f()
+	a.g()
+	func() {
+		defer expectPanic()
+		a.h() // dynamic error: nil dereference in a.B.D->f()
+	}()
+	a.i()
+
+	// Non-addressable value receiver.
+	A(a).f()
+	// A(a).g() // static error: cannot call pointer method on A literal.B.C
+	func() {
+		defer expectPanic()
+		A(a).h() // dynamic error: nil dereference in A().B.D->f()
+	}()
+	A(a).i()
+
+	// Pointer receiver.
+	(&a).f()
+	(&a).g()
+	func() {
+		defer expectPanic()
+		(&a).h() // dynamic error: nil deref: nil dereference in (&a).B.D->f()
+	}()
+	(&a).i()
+
+	c := new(C)
+	c.f() // makes a copy
+	c.g()
 }
diff --git a/test/method4.dir/method4a.go b/test/method4.dir/method4a.go
new file mode 100644
index 0000000..a7df04c
--- /dev/null
+++ b/test/method4.dir/method4a.go
@@ -0,0 +1,37 @@
+// 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 method expressions with arguments.
+
+package method4a
+
+type T1 int
+
+type T2 struct {
+	F int
+}
+
+type I1 interface {
+	Sum([]int, int) int
+}
+
+type I2 interface {
+	Sum(a []int, b int) int
+}
+
+func (i T1) Sum(a []int, b int) int {
+	r := int(i) + b
+	for _, v := range a {
+		r += v
+	}
+	return r
+}
+
+func (p *T2) Sum(a []int, b int) int {
+	r := p.F + b
+	for _, v := range a {
+		r += v
+	}
+	return r
+}
diff --git a/test/method4.dir/prog.go b/test/method4.dir/prog.go
new file mode 100644
index 0000000..77d580c
--- /dev/null
+++ b/test/method4.dir/prog.go
@@ -0,0 +1,104 @@
+// 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 method expressions with arguments.
+
+package main
+
+import "./method4a"
+
+type T1 int
+
+type T2 struct {
+	f int
+}
+
+type I1 interface {
+	Sum([]int, int) int
+}
+
+type I2 interface {
+	Sum(a []int, b int) int
+}
+
+func (i T1) Sum(a []int, b int) int {
+	r := int(i) + b
+	for _, v := range a {
+		r += v
+	}
+	return r
+}
+
+func (p *T2) Sum(a []int, b int) int {
+	r := p.f + b
+	for _, v := range a {
+		r += v
+	}
+	return r
+}
+
+func eq(v1, v2 int) {
+	if v1 != v2 {
+		panic(0)
+	}
+}
+
+func main() {
+	a := []int{1, 2, 3}
+	t1 := T1(4)
+	t2 := &T2{4}
+
+	eq(t1.Sum(a, 5), 15)
+	eq(t2.Sum(a, 6), 16)
+
+	eq(T1.Sum(t1, a, 7), 17)
+	eq((*T2).Sum(t2, a, 8), 18)
+
+	f1 := T1.Sum
+	eq(f1(t1, a, 9), 19)
+	f2 := (*T2).Sum
+	eq(f2(t2, a, 10), 20)
+
+	eq(I1.Sum(t1, a, 11), 21)
+	eq(I1.Sum(t2, a, 12), 22)
+
+	f3 := I1.Sum
+	eq(f3(t1, a, 13), 23)
+	eq(f3(t2, a, 14), 24)
+
+	eq(I2.Sum(t1, a, 15), 25)
+	eq(I2.Sum(t2, a, 16), 26)
+
+	f4 := I2.Sum
+	eq(f4(t1, a, 17), 27)
+	eq(f4(t2, a, 18), 28)
+	
+	mt1 := method4a.T1(4)
+	mt2 := &method4a.T2{4}
+
+	eq(mt1.Sum(a, 30), 40)
+	eq(mt2.Sum(a, 31), 41)
+
+	eq(method4a.T1.Sum(mt1, a, 32), 42)
+	eq((*method4a.T2).Sum(mt2, a, 33), 43)
+
+	g1 := method4a.T1.Sum
+	eq(g1(mt1, a, 34), 44)
+	g2 := (*method4a.T2).Sum
+	eq(g2(mt2, a, 35), 45)
+
+	eq(method4a.I1.Sum(mt1, a, 36), 46)
+	eq(method4a.I1.Sum(mt2, a, 37), 47)
+
+	g3 := method4a.I1.Sum
+	eq(g3(mt1, a, 38), 48)
+	eq(g3(mt2, a, 39), 49)
+
+	eq(method4a.I2.Sum(mt1, a, 40), 50)
+	eq(method4a.I2.Sum(mt2, a, 41), 51)
+
+	g4 := method4a.I2.Sum
+	eq(g4(mt1, a, 42), 52)
+	eq(g4(mt2, a, 43), 53)
+}
diff --git a/test/method4.go b/test/method4.go
index 77e409b..813892b 100644
--- a/test/method4.go
+++ b/test/method4.go
@@ -1,106 +1,8 @@
-// $G $D/method4a.go && $G $D/$F.go && $L $F.$A && ./$A.out
+// rundir
 
 // 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 method expressions with arguments.
-
-package main
-
-import "./method4a"
-
-type T1 int
-
-type T2 struct {
-	f int
-}
-
-type I1 interface {
-	Sum([]int, int) int
-}
-
-type I2 interface {
-	Sum(a []int, b int) int
-}
-
-func (i T1) Sum(a []int, b int) int {
-	r := int(i) + b
-	for _, v := range a {
-		r += v
-	}
-	return r
-}
-
-func (p *T2) Sum(a []int, b int) int {
-	r := p.f + b
-	for _, v := range a {
-		r += v
-	}
-	return r
-}
-
-func eq(v1, v2 int) {
-	if v1 != v2 {
-		panic(0)
-	}
-}
-
-func main() {
-	a := []int{1, 2, 3}
-	t1 := T1(4)
-	t2 := &T2{4}
-
-	eq(t1.Sum(a, 5), 15)
-	eq(t2.Sum(a, 6), 16)
-
-	eq(T1.Sum(t1, a, 7), 17)
-	eq((*T2).Sum(t2, a, 8), 18)
-
-	f1 := T1.Sum
-	eq(f1(t1, a, 9), 19)
-	f2 := (*T2).Sum
-	eq(f2(t2, a, 10), 20)
-
-	eq(I1.Sum(t1, a, 11), 21)
-	eq(I1.Sum(t2, a, 12), 22)
-
-	f3 := I1.Sum
-	eq(f3(t1, a, 13), 23)
-	eq(f3(t2, a, 14), 24)
-
-	eq(I2.Sum(t1, a, 15), 25)
-	eq(I2.Sum(t2, a, 16), 26)
-
-	f4 := I2.Sum
-	eq(f4(t1, a, 17), 27)
-	eq(f4(t2, a, 18), 28)
-	
-	mt1 := method4a.T1(4)
-	mt2 := &method4a.T2{4}
-
-	eq(mt1.Sum(a, 30), 40)
-	eq(mt2.Sum(a, 31), 41)
-
-	eq(method4a.T1.Sum(mt1, a, 32), 42)
-	eq((*method4a.T2).Sum(mt2, a, 33), 43)
-
-	g1 := method4a.T1.Sum
-	eq(g1(mt1, a, 34), 44)
-	g2 := (*method4a.T2).Sum
-	eq(g2(mt2, a, 35), 45)
-
-	eq(method4a.I1.Sum(mt1, a, 36), 46)
-	eq(method4a.I1.Sum(mt2, a, 37), 47)
-
-	g3 := method4a.I1.Sum
-	eq(g3(mt1, a, 38), 48)
-	eq(g3(mt2, a, 39), 49)
-
-	eq(method4a.I2.Sum(mt1, a, 40), 50)
-	eq(method4a.I2.Sum(mt2, a, 41), 51)
-
-	g4 := method4a.I2.Sum
-	eq(g4(mt1, a, 42), 52)
-	eq(g4(mt2, a, 43), 53)
-}
+package ignored
diff --git a/test/method4a.go b/test/method4a.go
deleted file mode 100644
index d23039b..0000000
--- a/test/method4a.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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 method expressions with arguments.
-// This file is not tested by itself; it is imported by method4.go.
-
-package method4a
-
-type T1 int
-
-type T2 struct {
-	F int
-}
-
-type I1 interface {
-	Sum([]int, int) int
-}
-
-type I2 interface {
-	Sum(a []int, b int) int
-}
-
-func (i T1) Sum(a []int, b int) int {
-	r := int(i) + b
-	for _, v := range a {
-		r += v
-	}
-	return r
-}
-
-func (p *T2) Sum(a []int, b int) int {
-	r := p.F + b
-	for _, v := range a {
-		r += v
-	}
-	return r
-}
diff --git a/test/nil.go b/test/nil.go
index 9f7bcbb..f8300bf 100644
--- a/test/nil.go
+++ b/test/nil.go
@@ -115,7 +115,7 @@ func chantest() {
 	})
 	shouldBlock(func() {
 		x, ok := <-ch
-		println(x, ok)
+		println(x, ok) // unreachable
 	})
 
 	if len(ch) != 0 {
@@ -147,13 +147,13 @@ func maptest() {
 		panic(v)
 	}
 
+	// can delete (non-existent) entries
+	delete(m, 2)
+
 	// but cannot be written to
 	shouldPanic(func() {
 		m[2] = 3
 	})
-	shouldPanic(func() {
-		delete(m, 2)
-	})
 }
 
 // nil slice
diff --git a/test/nul1.go b/test/nul1.go
index 142d4de..20426b4 100644
--- a/test/nul1.go
+++ b/test/nul1.go
@@ -1,7 +1,4 @@
-// [ "$GORUN" == "" ] || exit 0  # Android runner gets confused by the NUL output 
-// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
-// errchk $G -e tmp.go
-// rm -f tmp.go
+// errorcheckoutput
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/range.go b/test/range.go
index 68b0c9a..8effbe9 100644
--- a/test/range.go
+++ b/test/range.go
@@ -55,10 +55,10 @@ func testslice() {
 		panic("fail")
 	}
 	if s != 15 {
-		println("wrong sum ranging over makeslice")
+		println("wrong sum ranging over makeslice", s)
 		panic("fail")
 	}
-	
+
 	x := []int{10, 20}
 	y := []int{99}
 	i := 1
@@ -82,7 +82,7 @@ func testslice1() {
 		panic("fail")
 	}
 	if s != 10 {
-		println("wrong sum ranging over makeslice")
+		println("wrong sum ranging over makeslice", s)
 		panic("fail")
 	}
 }
@@ -106,7 +106,7 @@ func testarray() {
 		panic("fail")
 	}
 	if s != 15 {
-		println("wrong sum ranging over makearray")
+		println("wrong sum ranging over makearray", s)
 		panic("fail")
 	}
 }
@@ -122,7 +122,7 @@ func testarray1() {
 		panic("fail")
 	}
 	if s != 10 {
-		println("wrong sum ranging over makearray")
+		println("wrong sum ranging over makearray", s)
 		panic("fail")
 	}
 }
@@ -155,7 +155,7 @@ func testarrayptr() {
 		panic("fail")
 	}
 	if s != 15 {
-		println("wrong sum ranging over makearrayptr")
+		println("wrong sum ranging over makearrayptr", s)
 		panic("fail")
 	}
 }
@@ -171,7 +171,7 @@ func testarrayptr1() {
 		panic("fail")
 	}
 	if s != 10 {
-		println("wrong sum ranging over makearrayptr")
+		println("wrong sum ranging over makearrayptr", s)
 		panic("fail")
 	}
 }
@@ -195,7 +195,7 @@ func teststring() {
 		panic("fail")
 	}
 	if s != 'a'+'b'+'c'+'d'+'☺' {
-		println("wrong sum ranging over makestring")
+		println("wrong sum ranging over makestring", s)
 		panic("fail")
 	}
 }
@@ -211,7 +211,7 @@ func teststring1() {
 		panic("fail")
 	}
 	if s != 10 {
-		println("wrong sum ranging over makestring")
+		println("wrong sum ranging over makestring", s)
 		panic("fail")
 	}
 }
@@ -235,7 +235,7 @@ func testmap() {
 		panic("fail")
 	}
 	if s != 'a'+'b'+'c'+'d'+'☺' {
-		println("wrong sum ranging over makemap")
+		println("wrong sum ranging over makemap", s)
 		panic("fail")
 	}
 }
@@ -251,7 +251,7 @@ func testmap1() {
 		panic("fail")
 	}
 	if s != 10 {
-		println("wrong sum ranging over makemap")
+		println("wrong sum ranging over makemap", s)
 		panic("fail")
 	}
 }
diff --git a/test/recover.go b/test/recover.go
index eea655e..7c27d7c 100644
--- a/test/recover.go
+++ b/test/recover.go
@@ -8,15 +8,21 @@
 
 package main
 
-import "runtime"
+import (
+	"os"
+	"runtime"
+)
 
 func main() {
 	test1()
 	test1WithClosures()
 	test2()
 	test3()
-	test4()
-	test5()
+	// exp/ssa/interp still has some bugs in recover().
+	if os.Getenv("GOSSAINTERP") == "" {
+		test4()
+		test5()
+	}
 	test6()
 	test6WithClosures()
 	test7()
diff --git a/test/recover3.go b/test/recover3.go
index 9870023..ebfa0a3 100644
--- a/test/recover3.go
+++ b/test/recover3.go
@@ -71,6 +71,10 @@ func main() {
 	inter = 1
 	check("type-concrete", func() { println(inter.(string)) }, "int, not string")
 	check("type-interface", func() { println(inter.(m)) }, "missing method m")
+
+	if didbug {
+		panic("recover3")
+	}
 }
 
 type m interface {
diff --git a/test/rename.go b/test/rename.go
index e544274..dc43417 100644
--- a/test/rename.go
+++ b/test/rename.go
@@ -8,7 +8,10 @@
 
 package main
 
-import "fmt"
+import (
+	"fmt"
+	"runtime"
+)
 
 func main() {
 	n :=
@@ -52,6 +55,7 @@ func main() {
 			iota
 	if n != NUM*(NUM-1)/2 {
 		fmt.Println("BUG: wrong n", n, NUM*(NUM-1)/2)
+		runtime.Breakpoint() // panic is inaccessible
 	}
 }
 
diff --git a/test/reorder.go b/test/reorder.go
index 007039e..8fd623c 100644
--- a/test/reorder.go
+++ b/test/reorder.go
@@ -42,7 +42,7 @@ func check3(x, y, z, xx, yy, zz int) {
 }
 
 func p1() {
-	x := []int{1,2,3}
+	x := []int{1, 2, 3}
 	i := 0
 	i, x[i] = 1, 100
 	_ = i
@@ -50,7 +50,7 @@ func p1() {
 }
 
 func p2() {
-	x := []int{1,2,3}
+	x := []int{1, 2, 3}
 	i := 0
 	x[i], i = 100, 1
 	_ = i
@@ -58,7 +58,7 @@ func p2() {
 }
 
 func p3() {
-	x := []int{1,2,3}
+	x := []int{1, 2, 3}
 	y := x
 	gx = x
 	x[1], y[0] = f(0), f(1)
@@ -66,7 +66,7 @@ func p3() {
 }
 
 func p4() {
-	x := []int{1,2,3}
+	x := []int{1, 2, 3}
 	y := x
 	gx = x
 	x[1], y[0] = gx[0], gx[1]
@@ -74,7 +74,7 @@ func p4() {
 }
 
 func p5() {
-	x := []int{1,2,3}
+	x := []int{1, 2, 3}
 	y := x
 	p := &x[0]
 	q := &x[1]
@@ -89,7 +89,7 @@ func p6() {
 	px := &x
 	py := &y
 	*px, *py = y, x
-	check3(x, y, z, 2, 1, 3)	
+	check3(x, y, z, 2, 1, 3)
 }
 
 func f1(x, y, z int) (xx, yy, zz int) {
@@ -106,16 +106,9 @@ func p7() {
 }
 
 func p8() {
-	x := []int{1,2,3}
-
-	defer func() {
-		err := recover()
-		if err == nil {
-			panic("not panicking")
-		}
-		check(x, 100, 2, 3)
-	}()
-
-	i := 0
-	i, x[i], x[5] = 1, 100, 500
+	m := make(map[int]int)
+	m[0] = len(m)
+	if m[0] != 0 {
+		panic(m[0])
+	}
 }
diff --git a/test/rotate.go b/test/rotate.go
new file mode 100644
index 0000000..1d71497
--- /dev/null
+++ b/test/rotate.go
@@ -0,0 +1,166 @@
+// skip
+
+// NOTE: the actual tests to run are rotate[0123].go
+
+// 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.
+
+// Generate test of shift and rotate by constants.
+// The output is compiled and run.
+//
+// The integer type depends on the value of mode (rotate direction,
+// signedness).
+
+package main
+
+import (
+	"bufio"
+	"flag"
+	"fmt"
+	"os"
+	"strings"
+)
+
+func main() {
+	flag.Parse()
+
+	b := bufio.NewWriter(os.Stdout)
+	defer b.Flush()
+
+	fmt.Fprintf(b, "%s\n", prolog)
+
+	for logBits := uint(3); logBits <= 6; logBits++ {
+		typ := fmt.Sprintf("int%d", 1<<logBits)
+		fmt.Fprint(b, strings.Replace(checkFunc, "XXX", typ, -1))
+		fmt.Fprint(b, strings.Replace(checkFunc, "XXX", "u"+typ, -1))
+		gentest(b, 1<<logBits, mode&1 != 0, mode&2 != 0)
+	}
+}
+
+const prolog = `
+
+package main
+
+import (
+	"fmt"
+	"os"
+)
+
+var (
+	i8 int8 = 0x12
+	i16 int16 = 0x1234
+	i32 int32 = 0x12345678
+	i64 int64 = 0x123456789abcdef0
+	ui8 uint8 = 0x12
+	ui16 uint16 = 0x1234
+	ui32 uint32 = 0x12345678
+	ui64 uint64 = 0x123456789abcdef0
+
+	ni8 = ^i8
+	ni16 = ^i16
+	ni32 = ^i32
+	ni64 = ^i64
+	nui8 = ^ui8
+	nui16 = ^ui16
+	nui32 = ^ui32
+	nui64 = ^ui64
+)
+
+var nfail = 0
+
+func main() {
+	if nfail > 0 {
+		fmt.Printf("BUG\n")
+	}
+}
+
+`
+
+const checkFunc = `
+func check_XXX(desc string, have, want XXX) {
+	if have != want {
+		nfail++
+		fmt.Printf("%s = %T(%#x), want %T(%#x)\n", desc, have, have, want, want)
+		if nfail >= 100 {
+			fmt.Printf("BUG: stopping after 100 failures\n")
+			os.Exit(0)
+		}
+	}
+}
+`
+
+var (
+	uop = [2]func(x, y uint64) uint64{
+		func(x, y uint64) uint64 {
+			return x | y
+		},
+		func(x, y uint64) uint64 {
+			return x ^ y
+		},
+	}
+	iop = [2]func(x, y int64) int64{
+		func(x, y int64) int64 {
+			return x | y
+		},
+		func(x, y int64) int64 {
+			return x ^ y
+		},
+	}
+	cop = [2]byte{'|', '^'}
+)
+
+func gentest(b *bufio.Writer, bits uint, unsigned, inverted bool) {
+	fmt.Fprintf(b, "func init() {\n")
+	defer fmt.Fprintf(b, "}\n")
+	n := 0
+
+	// Generate tests for left/right and right/left.
+	for l := uint(0); l <= bits; l++ {
+		for r := uint(0); r <= bits; r++ {
+			for o, op := range cop {
+				typ := fmt.Sprintf("int%d", bits)
+				v := fmt.Sprintf("i%d", bits)
+				if unsigned {
+					typ = "u" + typ
+					v = "u" + v
+				}
+				v0 := int64(0x123456789abcdef0)
+				if inverted {
+					v = "n" + v
+					v0 = ^v0
+				}
+				expr1 := fmt.Sprintf("%s<<%d %c %s>>%d", v, l, op, v, r)
+				expr2 := fmt.Sprintf("%s>>%d %c %s<<%d", v, r, op, v, l)
+
+				var result string
+				if unsigned {
+					v := uint64(v0) >> (64 - bits)
+					v = uop[o](v<<l, v>>r)
+					v <<= 64 - bits
+					v >>= 64 - bits
+					result = fmt.Sprintf("%#x", v)
+				} else {
+					v := int64(v0) >> (64 - bits)
+					v = iop[o](v<<l, v>>r)
+					v <<= 64 - bits
+					v >>= 64 - bits
+					result = fmt.Sprintf("%#x", v)
+				}
+
+				fmt.Fprintf(b, "\tcheck_%s(%q, %s, %s(%s))\n", typ, expr1, expr1, typ, result)
+				fmt.Fprintf(b, "\tcheck_%s(%q, %s, %s(%s))\n", typ, expr2, expr2, typ, result)
+
+				// Chop test into multiple functions so that there's not one
+				// enormous function to compile/link.
+				// All the functions are named init so we don't have to do
+				// anything special to call them.  ☺
+				if n++; n >= 50 {
+					fmt.Fprintf(b, "}\n")
+					fmt.Fprintf(b, "func init() {\n")
+					n = 0
+				}
+			}
+		}
+	}
+}
diff --git a/test/rotate0.go b/test/rotate0.go
new file mode 100644
index 0000000..400b225
--- /dev/null
+++ b/test/rotate0.go
@@ -0,0 +1,12 @@
+// runoutput ./rotate.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.
+
+// Generate test of bit rotations.
+// The output is compiled and run.
+
+package main
+
+const mode = 0
diff --git a/test/rotate1.go b/test/rotate1.go
new file mode 100644
index 0000000..98b0b1c
--- /dev/null
+++ b/test/rotate1.go
@@ -0,0 +1,12 @@
+// runoutput ./rotate.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.
+
+// Generate test of bit rotations.
+// The output is compiled and run.
+
+package main
+
+const mode = 1
diff --git a/test/rotate2.go b/test/rotate2.go
new file mode 100644
index 0000000..c50f8ce
--- /dev/null
+++ b/test/rotate2.go
@@ -0,0 +1,12 @@
+// runoutput ./rotate.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.
+
+// Generate test of bit rotations.
+// The output is compiled and run.
+
+package main
+
+const mode = 2
diff --git a/test/rotate3.go b/test/rotate3.go
new file mode 100644
index 0000000..73d47d8
--- /dev/null
+++ b/test/rotate3.go
@@ -0,0 +1,12 @@
+// runoutput ./rotate.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.
+
+// Generate test of bit rotations.
+// The output is compiled and run.
+
+package main
+
+const mode = 3
diff --git a/test/run b/test/run
index 302578e..d206312 100755
--- a/test/run
+++ b/test/run
@@ -54,6 +54,8 @@ true >pass.out >times.out
 exclude=false	# exclude nothing
 golden=golden.out
 
+rm -f tmp.go  # generated by some tests, left behind if interrupted
+
 filterout() {
 	grep '^'"$2"'$' $1 >/dev/null
 }
@@ -100,7 +102,7 @@ do
 			echo $i >>pass.out
 		fi
 		echo $(awk 'NR==1{print $2}' "$TMP2FILE") $D/$F >>times.out
-		rm -f $F.$A $A.out
+		rm -f $F.$A $A.out tmp.go
 	) done
 done | # clean up some stack noise
 	egrep -v '^(r[0-9a-z]+|[cfg]s)  +0x'  |
diff --git a/test/run.go b/test/run.go
index ac6e3c0..5e167d6 100644
--- a/test/run.go
+++ b/test/run.go
@@ -5,7 +5,7 @@
 // license that can be found in the LICENSE file.
 
 // Run runs tests in the test directory.
-// 
+//
 // TODO(bradfitz): docs of some sort, once we figure out how we're changing
 // headers of files
 package main
@@ -20,6 +20,7 @@ import (
 	"log"
 	"os"
 	"os/exec"
+	"path"
 	"path/filepath"
 	"regexp"
 	"runtime"
@@ -29,10 +30,11 @@ import (
 )
 
 var (
-	verbose     = flag.Bool("v", false, "verbose. if set, parallelism is set to 1.")
-	numParallel = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run")
-	summary     = flag.Bool("summary", false, "show summary of results")
-	showSkips   = flag.Bool("show_skips", false, "show skipped tests")
+	verbose        = flag.Bool("v", false, "verbose. if set, parallelism is set to 1.")
+	numParallel    = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run")
+	summary        = flag.Bool("summary", false, "show summary of results")
+	showSkips      = flag.Bool("show_skips", false, "show skipped tests")
+	runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run")
 )
 
 var (
@@ -52,6 +54,10 @@ var (
 	// toRun is the channel of tests to run.
 	// It is nil until the first test is started.
 	toRun chan *test
+
+	// rungatec controls the max number of runoutput tests
+	// executed in parallel as they can each consume a lot of memory.
+	rungatec chan bool
 )
 
 // maxTests is an upper bound on the total number of tests.
@@ -67,6 +73,7 @@ func main() {
 	}
 
 	ratec = make(chan bool, *numParallel)
+	rungatec = make(chan bool, *runoutputLimit)
 	var err error
 	letter, err = build.ArchChar(build.Default.GOARCH)
 	check(err)
@@ -77,16 +84,23 @@ func main() {
 	if flag.NArg() > 0 {
 		for _, arg := range flag.Args() {
 			if arg == "-" || arg == "--" {
-				// Permit running either:
+				// Permit running:
 				// $ go run run.go - env.go
 				// $ go run run.go -- env.go
+				// $ go run run.go - ./fixedbugs
+				// $ go run run.go -- ./fixedbugs
 				continue
 			}
-			if !strings.HasSuffix(arg, ".go") {
-				log.Fatalf("can't yet deal with non-go file %q", arg)
+			if fi, err := os.Stat(arg); err == nil && fi.IsDir() {
+				for _, baseGoFile := range goFiles(arg) {
+					tests = append(tests, startTest(arg, baseGoFile))
+				}
+			} else if strings.HasSuffix(arg, ".go") {
+				dir, file := filepath.Split(arg)
+				tests = append(tests, startTest(dir, file))
+			} else {
+				log.Fatalf("can't yet deal with non-directory and non-go file %q", arg)
 			}
-			dir, file := filepath.Split(arg)
-			tests = append(tests, startTest(dir, file))
 		}
 	} else {
 		for _, dir := range dirs {
@@ -102,15 +116,17 @@ func main() {
 		<-test.donec
 		_, isSkip := test.err.(skipError)
 		errStr := "pass"
-		if isSkip {
-			errStr = "skip"
-		}
 		if test.err != nil {
 			errStr = test.err.Error()
 			if !isSkip {
 				failed = true
 			}
 		}
+		if isSkip && !skipOkay[path.Join(test.dir, test.gofile)] {
+			errStr = "unexpected skip for " + path.Join(test.dir, test.gofile) + ": " + errStr
+			isSkip = false
+			failed = true
+		}
 		resCount[errStr]++
 		if isSkip && !*verbose && !*showSkips {
 			continue
@@ -118,7 +134,7 @@ func main() {
 		if !*verbose && test.err == nil {
 			continue
 		}
-		fmt.Printf("%-10s %-20s: %s\n", test.action, test.goFileName(), errStr)
+		fmt.Printf("%-20s %-20s: %s\n", test.action, test.goFileName(), errStr)
 	}
 
 	if *summary {
@@ -155,6 +171,26 @@ func goFiles(dir string) []string {
 	return names
 }
 
+type runCmd func(...string) ([]byte, error)
+
+func compileFile(runcmd runCmd, longname string) (out []byte, err error) {
+	return runcmd("go", "tool", gc, "-e", longname)
+}
+
+func compileInDir(runcmd runCmd, dir string, names ...string) (out []byte, err error) {
+	cmd := []string{"go", "tool", gc, "-e", "-D", ".", "-I", "."}
+	for _, name := range names {
+		cmd = append(cmd, filepath.Join(dir, name))
+	}
+	return runcmd(cmd...)
+}
+
+func linkFile(runcmd runCmd, goname string) (err error) {
+	pfile := strings.Replace(goname, ".go", "."+letter, -1)
+	_, err = runcmd("go", "tool", ld, "-o", "a.exe", "-L", ".", pfile)
+	return
+}
+
 // skipError describes why a test was skipped.
 type skipError string
 
@@ -172,13 +208,13 @@ type test struct {
 	donec       chan bool // closed when done
 
 	src    string
-	action string // "compile", "build", "run", "errorcheck", "skip"
+	action string // "compile", "build", etc.
 
 	tempDir string
 	err     error
 }
 
-// startTest 
+// startTest
 func startTest(dir, gofile string) *test {
 	t := &test{
 		dir:    dir,
@@ -216,6 +252,97 @@ func (t *test) goFileName() string {
 	return filepath.Join(t.dir, t.gofile)
 }
 
+func (t *test) goDirName() string {
+	return filepath.Join(t.dir, strings.Replace(t.gofile, ".go", ".dir", -1))
+}
+
+func goDirFiles(longdir string) (filter []os.FileInfo, err error) {
+	files, dirErr := ioutil.ReadDir(longdir)
+	if dirErr != nil {
+		return nil, dirErr
+	}
+	for _, gofile := range files {
+		if filepath.Ext(gofile.Name()) == ".go" {
+			filter = append(filter, gofile)
+		}
+	}
+	return
+}
+
+var packageRE = regexp.MustCompile(`(?m)^package (\w+)`)
+
+func goDirPackages(longdir string) ([][]string, error) {
+	files, err := goDirFiles(longdir)
+	if err != nil {
+		return nil, err
+	}
+	var pkgs [][]string
+	m := make(map[string]int)
+	for _, file := range files {
+		name := file.Name()
+		data, err := ioutil.ReadFile(filepath.Join(longdir, name))
+		if err != nil {
+			return nil, err
+		}
+		pkgname := packageRE.FindStringSubmatch(string(data))
+		if pkgname == nil {
+			return nil, fmt.Errorf("cannot find package name in %s", name)
+		}
+		i, ok := m[pkgname[1]]
+		if !ok {
+			i = len(pkgs)
+			pkgs = append(pkgs, nil)
+			m[pkgname[1]] = i
+		}
+		pkgs[i] = append(pkgs[i], name)
+	}
+	return pkgs, nil
+}
+
+// shouldTest looks for build tags in a source file and returns
+// whether the file should be used according to the tags.
+func shouldTest(src string, goos, goarch string) (ok bool, whyNot string) {
+	if idx := strings.Index(src, "\npackage"); idx >= 0 {
+		src = src[:idx]
+	}
+	notgoos := "!" + goos
+	notgoarch := "!" + goarch
+	for _, line := range strings.Split(src, "\n") {
+		line = strings.TrimSpace(line)
+		if strings.HasPrefix(line, "//") {
+			line = line[2:]
+		} else {
+			continue
+		}
+		line = strings.TrimSpace(line)
+		if len(line) == 0 || line[0] != '+' {
+			continue
+		}
+		words := strings.Fields(line)
+		if words[0] == "+build" {
+			for _, word := range words {
+				switch word {
+				case goos, goarch:
+					return true, ""
+				case notgoos, notgoarch:
+					continue
+				default:
+					if word[0] == '!' {
+						// NOT something-else
+						return true, ""
+					}
+				}
+			}
+			// no matching tag found.
+			return false, line
+		}
+	}
+	// no build tags.
+	return true, ""
+}
+
+func init() { checkShouldTest() }
+
 // run runs a test.
 func (t *test) run() {
 	defer close(t.donec)
@@ -235,12 +362,24 @@ func (t *test) run() {
 		t.err = errors.New("double newline not found")
 		return
 	}
+	if ok, why := shouldTest(t.src, runtime.GOOS, runtime.GOARCH); !ok {
+		t.action = "skip"
+		if *showSkips {
+			fmt.Printf("%-20s %-20s: %s\n", t.action, t.goFileName(), why)
+		}
+		return
+	}
 	action := t.src[:pos]
+	if nl := strings.Index(action, "\n"); nl >= 0 && strings.Contains(action[:nl], "+build") {
+		// skip first line
+		action = action[nl+1:]
+	}
 	if strings.HasPrefix(action, "//") {
 		action = action[2:]
 	}
 
-	var args []string
+	var args, flags []string
+	wantError := false
 	f := strings.Fields(action)
 	if len(f) > 0 {
 		action = f[0]
@@ -248,11 +387,25 @@ func (t *test) run() {
 	}
 
 	switch action {
+	case "rundircmpout":
+		action = "rundir"
+		t.action = "rundir"
 	case "cmpout":
 		action = "run" // the run case already looks for <dir>/<test>.out files
 		fallthrough
-	case "compile", "build", "run", "errorcheck":
+	case "compile", "compiledir", "build", "run", "runoutput", "rundir":
 		t.action = action
+	case "errorcheck", "errorcheckdir", "errorcheckoutput":
+		t.action = action
+		wantError = true
+		for len(args) > 0 && strings.HasPrefix(args[0], "-") {
+			if args[0] == "-0" {
+				wantError = false
+			} else {
+				flags = append(flags, args[0])
+			}
+			args = args[1:]
+		}
 	case "skip":
 		t.action = "skip"
 		return
@@ -280,8 +433,12 @@ func (t *test) run() {
 		cmd.Stderr = &buf
 		if useTmp {
 			cmd.Dir = t.tempDir
+			cmd.Env = envForDir(cmd.Dir)
 		}
 		err := cmd.Run()
+		if err != nil {
+			err = fmt.Errorf("%s\n%s", err, buf.Bytes())
+		}
 		return buf.Bytes(), err
 	}
 
@@ -291,31 +448,175 @@ func (t *test) run() {
 		t.err = fmt.Errorf("unimplemented action %q", action)
 
 	case "errorcheck":
-		out, _ := runcmd("go", "tool", gc, "-e", "-o", "a."+letter, long)
+		cmdline := []string{"go", "tool", gc, "-e", "-o", "a." + letter}
+		cmdline = append(cmdline, flags...)
+		cmdline = append(cmdline, long)
+		out, err := runcmd(cmdline...)
+		if wantError {
+			if err == nil {
+				t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out)
+				return
+			}
+		} else {
+			if err != nil {
+				t.err = err
+				return
+			}
+		}
 		t.err = t.errorCheck(string(out), long, t.gofile)
 		return
 
 	case "compile":
-		out, err := runcmd("go", "tool", gc, "-e", "-o", "a."+letter, long)
+		_, t.err = compileFile(runcmd, long)
+
+	case "compiledir":
+		// Compile all files in the directory in lexicographic order.
+		longdir := filepath.Join(cwd, t.goDirName())
+		pkgs, err := goDirPackages(longdir)
 		if err != nil {
-			t.err = fmt.Errorf("%s\n%s", err, out)
+			t.err = err
+			return
+		}
+		for _, gofiles := range pkgs {
+			_, t.err = compileInDir(runcmd, longdir, gofiles...)
+			if t.err != nil {
+				return
+			}
+		}
+
+	case "errorcheckdir":
+		// errorcheck all files in lexicographic order
+		// useful for finding importing errors
+		longdir := filepath.Join(cwd, t.goDirName())
+		pkgs, err := goDirPackages(longdir)
+		if err != nil {
+			t.err = err
+			return
+		}
+		for i, gofiles := range pkgs {
+			out, err := compileInDir(runcmd, longdir, gofiles...)
+			if i == len(pkgs)-1 {
+				if wantError && err == nil {
+					t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out)
+					return
+				} else if !wantError && err != nil {
+					t.err = err
+					return
+				}
+			} else if err != nil {
+				t.err = err
+				return
+			}
+			var fullshort []string
+			for _, name := range gofiles {
+				fullshort = append(fullshort, filepath.Join(longdir, name), name)
+			}
+			t.err = t.errorCheck(string(out), fullshort...)
+			if t.err != nil {
+				break
+			}
+		}
+
+	case "rundir":
+		// Compile all files in the directory in lexicographic order.
+		// then link as if the last file is the main package and run it
+		longdir := filepath.Join(cwd, t.goDirName())
+		pkgs, err := goDirPackages(longdir)
+		if err != nil {
+			t.err = err
+			return
+		}
+		for i, gofiles := range pkgs {
+			_, err := compileInDir(runcmd, longdir, gofiles...)
+			if err != nil {
+				t.err = err
+				return
+			}
+			if i == len(pkgs)-1 {
+				err = linkFile(runcmd, gofiles[0])
+				if err != nil {
+					t.err = err
+					return
+				}
+				out, err := runcmd(append([]string{filepath.Join(t.tempDir, "a.exe")}, 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)
+				}
+			}
 		}
 
 	case "build":
-		out, err := runcmd("go", "build", "-o", "a.exe", long)
+		_, err := runcmd("go", "build", "-o", "a.exe", long)
 		if err != nil {
-			t.err = fmt.Errorf("%s\n%s", err, out)
+			t.err = err
 		}
 
 	case "run":
 		useTmp = false
 		out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
 		if err != nil {
-			t.err = fmt.Errorf("%s\n%s", err, out)
+			t.err = err
+		}
+		if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
+			t.err = fmt.Errorf("incorrect output\n%s", out)
+		}
+
+	case "runoutput":
+		rungatec <- true
+		defer func() {
+			<-rungatec
+		}()
+		useTmp = false
+		out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
+		if err != nil {
+			t.err = err
+		}
+		tfile := filepath.Join(t.tempDir, "tmp__.go")
+		if err := ioutil.WriteFile(tfile, out, 0666); err != nil {
+			t.err = fmt.Errorf("write tempfile:%s", err)
+			return
+		}
+		out, err = runcmd("go", "run", tfile)
+		if err != nil {
+			t.err = err
 		}
 		if string(out) != t.expectedOutput() {
 			t.err = fmt.Errorf("incorrect output\n%s", out)
 		}
+
+	case "errorcheckoutput":
+		useTmp = false
+		out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
+		if err != nil {
+			t.err = err
+		}
+		tfile := filepath.Join(t.tempDir, "tmp__.go")
+		err = ioutil.WriteFile(tfile, out, 0666)
+		if err != nil {
+			t.err = fmt.Errorf("write tempfile:%s", err)
+			return
+		}
+		cmdline := []string{"go", "tool", gc, "-e", "-o", "a." + letter}
+		cmdline = append(cmdline, flags...)
+		cmdline = append(cmdline, tfile)
+		out, err = runcmd(cmdline...)
+		if wantError {
+			if err == nil {
+				t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out)
+				return
+			}
+		} else {
+			if err != nil {
+				t.err = err
+				return
+			}
+		}
+		t.err = t.errorCheck(string(out), tfile, "tmp__.go")
+		return
 	}
 }
 
@@ -337,7 +638,7 @@ func (t *test) expectedOutput() string {
 	return string(b)
 }
 
-func (t *test) errorCheck(outStr string, full, short string) (err error) {
+func (t *test) errorCheck(outStr string, fullshort ...string) (err error) {
 	defer func() {
 		if *verbose && err != nil {
 			log.Printf("%s gc output:\n%s", t, outStr)
@@ -349,19 +650,33 @@ func (t *test) errorCheck(outStr string, full, short string) (err error) {
 	// 6g error messages continue onto additional lines with leading tabs.
 	// Split the output at the beginning of each line that doesn't begin with a tab.
 	for _, line := range strings.Split(outStr, "\n") {
+		if strings.HasSuffix(line, "\r") { // remove '\r', output by compiler on windows
+			line = line[:len(line)-1]
+		}
 		if strings.HasPrefix(line, "\t") {
 			out[len(out)-1] += "\n" + line
-		} else {
+		} else if strings.HasPrefix(line, "go tool") {
+			continue
+		} else if strings.TrimSpace(line) != "" {
 			out = append(out, line)
 		}
 	}
 
 	// Cut directory name.
 	for i := range out {
-		out[i] = strings.Replace(out[i], full, short, -1)
+		for j := 0; j < len(fullshort); j += 2 {
+			full, short := fullshort[j], fullshort[j+1]
+			out[i] = strings.Replace(out[i], full, short, -1)
+		}
+	}
+
+	var want []wantedError
+	for j := 0; j < len(fullshort); j += 2 {
+		full, short := fullshort[j], fullshort[j+1]
+		want = append(want, t.wantedErrors(full, short)...)
 	}
 
-	for _, we := range t.wantedErrors() {
+	for _, we := range want {
 		var errmsgs []string
 		errmsgs, out = partitionStrings(we.filterRe, out)
 		if len(errmsgs) == 0 {
@@ -369,6 +684,7 @@ func (t *test) errorCheck(outStr string, full, short string) (err error) {
 			continue
 		}
 		matched := false
+		n := len(out)
 		for _, errmsg := range errmsgs {
 			if we.re.MatchString(errmsg) {
 				matched = true
@@ -377,11 +693,18 @@ func (t *test) errorCheck(outStr string, full, short string) (err error) {
 			}
 		}
 		if !matched {
-			errs = append(errs, fmt.Errorf("%s:%d: no match for %q in%s", we.file, we.lineNum, we.reStr, strings.Join(out, "\n")))
+			errs = append(errs, fmt.Errorf("%s:%d: no match for %#q in:\n\t%s", we.file, we.lineNum, we.reStr, strings.Join(out[n:], "\n\t")))
 			continue
 		}
 	}
 
+	if len(out) > 0 {
+		errs = append(errs, fmt.Errorf("Unmatched Errors:"))
+		for _, errLine := range out {
+			errs = append(errs, fmt.Errorf("%s", errLine))
+		}
+	}
+
 	if len(errs) == 0 {
 		return nil
 	}
@@ -422,8 +745,9 @@ var (
 	lineRx      = regexp.MustCompile(`LINE(([+-])([0-9]+))?`)
 )
 
-func (t *test) wantedErrors() (errs []wantedError) {
-	for i, line := range strings.Split(t.src, "\n") {
+func (t *test) wantedErrors(file, short string) (errs []wantedError) {
+	src, _ := ioutil.ReadFile(file)
+	for i, line := range strings.Split(string(src), "\n") {
 		lineNum := i + 1
 		if strings.Contains(line, "////") {
 			// double comment disables ERROR
@@ -436,7 +760,7 @@ func (t *test) wantedErrors() (errs []wantedError) {
 		all := m[1]
 		mm := errQuotesRx.FindAllStringSubmatch(all, -1)
 		if mm == nil {
-			log.Fatalf("invalid errchk line in %s: %s", t.goFileName(), line)
+			log.Fatalf("%s:%d: invalid errchk line: %s", t.goFileName(), lineNum, line)
 		}
 		for _, m := range mm {
 			rx := lineRx.ReplaceAllStringFunc(m[1], func(m string) string {
@@ -448,18 +772,77 @@ func (t *test) wantedErrors() (errs []wantedError) {
 					delta, _ := strconv.Atoi(m[5:])
 					n -= delta
 				}
-				return fmt.Sprintf("%s:%d", t.gofile, n)
+				return fmt.Sprintf("%s:%d", short, n)
 			})
-			filterPattern := fmt.Sprintf(`^(\w+/)?%s:%d[:[]`, t.gofile, lineNum)
+			re, err := regexp.Compile(rx)
+			if err != nil {
+				log.Fatalf("%s:%d: invalid regexp in ERROR line: %v", t.goFileName(), lineNum, err)
+			}
+			filterPattern := fmt.Sprintf(`^(\w+/)?%s:%d[:[]`, regexp.QuoteMeta(short), lineNum)
 			errs = append(errs, wantedError{
 				reStr:    rx,
-				re:       regexp.MustCompile(rx),
+				re:       re,
 				filterRe: regexp.MustCompile(filterPattern),
 				lineNum:  lineNum,
-				file:     t.gofile,
+				file:     short,
 			})
 		}
 	}
 
 	return
 }
+
+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.
+	"fixedbugs/bug369.go": true, // needs compiler flags.
+	"fixedbugs/bug429.go": true, // like "run" but program should fail
+	"bugs/bug395.go":      true,
+}
+
+// defaultRunOutputLimit returns the number of runoutput tests that
+// can be executed in parallel.
+func defaultRunOutputLimit() int {
+	const maxArmCPU = 2
+
+	cpu := runtime.NumCPU()
+	if runtime.GOARCH == "arm" && cpu > maxArmCPU {
+		cpu = maxArmCPU
+	}
+	return cpu
+}
+
+// checkShouldTest runs canity checks on the shouldTest function.
+func checkShouldTest() {
+	assert := func(ok bool, _ string) {
+		if !ok {
+			panic("fail")
+		}
+	}
+	assertNot := func(ok bool, _ string) { assert(!ok, "") }
+	assert(shouldTest("// +build linux", "linux", "arm"))
+	assert(shouldTest("// +build !windows", "linux", "arm"))
+	assertNot(shouldTest("// +build !windows", "windows", "amd64"))
+	assertNot(shouldTest("// +build arm 386", "linux", "amd64"))
+	assert(shouldTest("// This is a test.", "os", "arch"))
+}
+
+// envForDir returns a copy of the environment
+// suitable for running in the given directory.
+// The environment is the current process's environment
+// but with an updated $PWD, so that an os.Getwd in the
+// child will be faster.
+func envForDir(dir string) []string {
+	env := os.Environ()
+	for i, kv := range env {
+		if strings.HasPrefix(kv, "PWD=") {
+			env[i] = "PWD=" + dir
+			return env
+		}
+	}
+	env = append(env, "PWD="+dir)
+	return env
+}
diff --git a/test/safe/nousesafe.go b/test/safe/nousesafe.go
index f61e7fe..fcd25af 100644
--- a/test/safe/nousesafe.go
+++ b/test/safe/nousesafe.go
@@ -1,4 +1,4 @@
-// $G $D/pkg.go && pack grc pkg.a pkg.$A 2> /dev/null && rm pkg.$A && errchk $G -I. -u $D/main.go
+// $G $D/pkg.go && pack grc pkg.a pkg.$A 2> /dev/null && rm pkg.$A && errchk $G -I . -u $D/main.go
 // rm -f pkg.a
 
 // Copyright 2012 The Go Authors. All rights reserved.
diff --git a/test/safe/usesafe.go b/test/safe/usesafe.go
index 07c13c1..5d0829e 100644
--- a/test/safe/usesafe.go
+++ b/test/safe/usesafe.go
@@ -1,4 +1,4 @@
-// $G $D/pkg.go && pack grcS pkg.a pkg.$A 2> /dev/null && rm pkg.$A && $G -I. -u $D/main.go
+// $G $D/pkg.go && pack grcS pkg.a pkg.$A 2> /dev/null && rm pkg.$A && $G -I . -u $D/main.go
 // rm -f pkg.a
 
 // Copyright 2012 The Go Authors. All rights reserved.
diff --git a/test/shift1.go b/test/shift1.go
index b33d22f..f1ec0bf 100644
--- a/test/shift1.go
+++ b/test/shift1.go
@@ -36,3 +36,10 @@ var (
 	b2     = 1.0 << c    // ERROR "overflow"
 	d2     = f(1.0 << c) // ERROR "overflow"
 )
+
+var (
+	// issues 4882, 4936.
+	a3 = 1.0<<s + 0 // ERROR "invalid operation|shift of non-integer operand"
+	// issue 4937
+	b3 = 1<<s + 1 + 1.0 // ERROR "invalid operation|shift of non-integer operand"
+)
diff --git a/test/sigchld.go b/test/sigchld.go
index 25625a6..a60d28d 100644
--- a/test/sigchld.go
+++ b/test/sigchld.go
@@ -1,5 +1,5 @@
-// [ "$GOOS" == windows ] ||
-// ($G $D/$F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out)
+// +build !windows
+// cmpout
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/sinit.go b/test/sinit.go
index 1bc2810..5e50e11 100644
--- a/test/sinit.go
+++ b/test/sinit.go
@@ -1,5 +1,8 @@
 // $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.
+
 // 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.
@@ -256,3 +259,13 @@ var copy_pt0a = pt0a
 var copy_pt0b = pt0b
 var copy_pt1 = pt1
 var copy_pt1a = pt1a
+
+var _ interface{} = 1
+
+type T1 int
+
+func (t *T1) M() {}
+
+type Mer interface { M() }
+
+var _ Mer = (*T1)(nil)
diff --git a/test/string_lit.go b/test/string_lit.go
index 9563300..fea6f55 100644
--- a/test/string_lit.go
+++ b/test/string_lit.go
@@ -33,6 +33,7 @@ func assert(a, b, c string) {
 				print("\ta[", i, "] = ", ac, "; b[", i, "] =", bc, "\n")
 			}
 		}
+		panic("string_lit")
 	}
 }
 
@@ -93,7 +94,7 @@ func main() {
 		"backslashes 2 (backquote)")
 	assert("\\x\\u\\U\\", `\x\u\U\`, "backslash 3 (backquote)")
 
-	// test large runes. perhaps not the most logical place for this test.
+	// test large and surrogate-half runes. perhaps not the most logical place for these tests.
 	var r int32
 	r = 0x10ffff // largest rune value
 	s = string(r)
@@ -101,6 +102,28 @@ func main() {
 	r = 0x10ffff + 1
 	s = string(r)
 	assert(s, "\xef\xbf\xbd", "too-large rune")
+	r = 0xD800
+	s = string(r)
+	assert(s, "\xef\xbf\xbd", "surrogate rune min")
+	r = 0xDFFF
+	s = string(r)
+	assert(s, "\xef\xbf\xbd", "surrogate rune max")
+	r = -1
+	s = string(r)
+	assert(s, "\xef\xbf\xbd", "negative rune")
+
+	// the large rune tests again, this time using constants instead of a variable.
+	// these conversions will be done at compile time.
+	s = string(0x10ffff) // largest rune value
+	assert(s, "\xf4\x8f\xbf\xbf", "largest rune constant")
+	s = string(0x10ffff + 1)
+	assert(s, "\xef\xbf\xbd", "too-large rune constant")
+	s = string(0xD800)
+	assert(s, "\xef\xbf\xbd", "surrogate rune min constant")
+	s = string(0xDFFF)
+	assert(s, "\xef\xbf\xbd", "surrogate rune max constant")
+	s = string(-1)
+	assert(s, "\xef\xbf\xbd", "negative rune")
 
 	assert(string(gr1), gx1, "global ->[]rune")
 	assert(string(gr2), gx2fix, "global invalid ->[]rune")
diff --git a/test/stringrange.go b/test/stringrange.go
index daaba91..99e5edb 100644
--- a/test/stringrange.go
+++ b/test/stringrange.go
@@ -57,6 +57,13 @@ func main() {
 		ok = false
 	}
 
+	for _, c := range "a\xed\xa0\x80a" {
+		if c != 'a' && c != utf8.RuneError {
+			fmt.Printf("surrogate UTF-8 does not error: %U\n", c)
+			ok = false
+		}
+	}
+
 	if !ok {
 		fmt.Println("BUG: stringrange")
 		os.Exit(1)
diff --git a/test/switch.go b/test/switch.go
index 09bf434..bcbde68 100644
--- a/test/switch.go
+++ b/test/switch.go
@@ -284,12 +284,129 @@ func main() {
 	default:
 	}
 
+	// switch on interface.
+	switch i := interface{}("hello"); i {
+	case 42:
+		assert(false, `i should be "hello"`)
+	case "hello":
+		assert(true, "hello")
+	default:
+		assert(false, `i should be "hello"`)
+	}
+
+	// switch on implicit bool converted to interface
+	// was broken: see issue 3980
+	switch i := interface{}(true); {
+	case i:
+		assert(true, "true")
+	case false:
+		assert(false, "i should be true")
+	default:
+		assert(false, "i should be true")
+	}
+
+	// switch on interface with constant cases differing by type.
+	// was rejected by compiler: see issue 4781
+	type T int
+	type B bool
+	type F float64
+	type S string
+	switch i := interface{}(float64(1.0)); i {
+	case nil:
+		assert(false, "i should be float64(1.0)")
+	case (*int)(nil):
+		assert(false, "i should be float64(1.0)")
+	case 1:
+		assert(false, "i should be float64(1.0)")
+	case T(1):
+		assert(false, "i should be float64(1.0)")
+	case F(1.0):
+		assert(false, "i should be float64(1.0)")
+	case 1.0:
+		assert(true, "true")
+	case "hello":
+		assert(false, "i should be float64(1.0)")
+	case S("hello"):
+		assert(false, "i should be float64(1.0)")
+	case true, B(false):
+		assert(false, "i should be float64(1.0)")
+	case false, B(true):
+		assert(false, "i should be float64(1.0)")
+	}
+
+	// switch on array.
+	switch ar := [3]int{1, 2, 3}; ar {
+	case [3]int{1, 2, 3}:
+		assert(true, "[1 2 3]")
+	case [3]int{4, 5, 6}:
+		assert(false, "ar should be [1 2 3]")
+	default:
+		assert(false, "ar should be [1 2 3]")
+	}
+
+	// switch on channel
+	switch c1, c2 := make(chan int), make(chan int); c1 {
+	case nil:
+		assert(false, "c1 did not match itself")
+	case c2:
+		assert(false, "c1 did not match itself")
+	case c1:
+		assert(true, "chan")
+	default:
+		assert(false, "c1 did not match itself")
+	}
+
+	// empty switch
+	switch {
+	}
+
+	// empty switch with default case.
+	fired = false
+	switch {
+	default:
+		fired = true
+	}
+	assert(fired, "fail")
+
+	// Default and fallthrough.
+	count = 0
+	switch {
+	default:
+		count++
+		fallthrough
+	case false:
+		count++
+	}
+	assert(count == 2, "fail")
+
+	// fallthrough to default, which is not at end.
+	count = 0
+	switch i5 {
+	case 5:
+		count++
+		fallthrough
+	default:
+		count++
+	case 6:
+		count++
+	}
+	assert(count == 2, "fail")
+
+	// fallthrough in final case.
+	count = 0
+	switch i5 {
+	case 5:
+		count++
+		fallthrough
+	}
+	assert(count == 1, "fail")
+
 	i := 0
 	switch x := 5; {
-		case i < x:
-			os.Exit(0)
-		case i == x:
-		case i > x:
-			os.Exit(1)
+	case i < x:
+		os.Exit(0)
+	case i == x:
+	case i > x:
+		os.Exit(1)
 	}
 }
diff --git a/test/switch3.go b/test/switch3.go
index dcb6fff..28705e4 100644
--- a/test/switch3.go
+++ b/test/switch3.go
@@ -45,6 +45,17 @@ func bad() {
 	case f1: // ERROR "can only compare func f to nil|func can only be compared to nil"
 	default:
 	}
+
+	var ar, ar1 [4]func()
+	switch ar { // ERROR "cannot switch on"
+	case ar1:
+	default:
+	}
+
+	var st, st1 struct{ f func() }
+	switch st { // ERROR "cannot switch on"
+	case st1:
+	}
 }
 
 func good() {
diff --git a/test/syntax/composite.go b/test/syntax/composite.go
new file mode 100644
index 0000000..6565334
--- /dev/null
+++ b/test/syntax/composite.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// 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 main
+
+var a = []int{
+	3 // ERROR "need trailing comma before newline in composite literal"
+}
diff --git a/test/testlib b/test/testlib
index 3858431..de138b1 100644
--- a/test/testlib
+++ b/test/testlib
@@ -5,14 +5,104 @@
 # These function names are also known to
 # (and are the plan for transitioning to) run.go.
 
+# helper (not known to run.go)
+# group file list by packages and return list of packages
+# each package is a comma-separated list of go files.
+pkgs() {
+	pkglist=$(grep -h '^package ' $* | awk '{print $2}' | sort -u)
+	for p in $pkglist
+	do
+		echo $(grep -l "^package $p\$" $*) | tr ' ' ,
+	done | sort
+}
+
+# +build aborts execution if the supplied tags don't match,
+# i.e. none of the tags (x or !x) matches GOARCH or GOOS.
++build() {
+	if (( $# == 0 )); then
+		return
+	fi
+	for tag; do
+		case $tag in
+		$GOARCH|$GOOS)
+			#echo >&2 "match $tag in $1"
+			return # don't exclude.
+			;;
+		'!'$GOARCH|'!'$GOOS)
+			;;
+		'!'*)
+			# not x where x is neither GOOS nor GOARCH.
+			#echo >&2 "match $tag in $1"
+			return # don't exclude
+			;;
+		esac
+	done
+	# no match.
+	exit 0
+}
+
 compile() {
 	$G $D/$F.go
 }
 
+compiledir() {
+	for pkg in $(pkgs $D/$F.dir/*.go)
+	do
+		$G -I . $(echo $pkg | tr , ' ') || return 1
+	done
+}
+
+errorcheckdir() {
+	lastzero=""
+	if [ "$1" = "-0" ]; then
+		lastzero="-0"
+	fi
+	pkgs=$(pkgs $D/$F.dir/*.go)
+	for pkg in $pkgs.last
+	do
+		zero="-0"
+		case $pkg in
+		*.last)
+			pkg=$(echo $pkg |sed 's/\.last$//')
+			zero=$lastzero
+		esac
+		errchk $zero $G -D . -I . -e $(echo $pkg | tr , ' ')
+	done
+}
+
+rundir() {
+	lastfile=""
+	for pkg in $(pkgs $D/$F.dir/*.go)
+	do
+		name=$(echo $pkg | sed 's/\.go.*//; s/.*\///')
+		$G -D . -I . -e $(echo $pkg | tr , ' ') || return 1
+		lastfile=$name
+	done
+	$L -o $A.out -L . $lastfile.$A
+	./$A.out
+}
+
+rundircmpout() {
+	lastfile=""
+	for pkg in $(pkgs $D/$F.dir/*.go)
+	do
+		name=$(echo $pkg | sed 's/\.go.*//; s/.*\///')
+		$G -D . -I . -e $(echo $pkg | tr , ' ') || return 1
+		lastfile=$name
+	done
+	$L -o $A.out -L . $lastfile.$A
+	./$A.out 2>&1 | cmp - $D/$F.out
+}
+
 build() {
 	$G $D/$F.go && $L $F.$A
 }
 
+runoutput() {
+	go run "$D/$F.go" "$@" > tmp.go
+	go run tmp.go
+}
+
 run() {
 	gofiles=""
 	ingo=true
@@ -36,7 +126,22 @@ cmpout() {
 }
 
 errorcheck() {
-	errchk $G -e $D/$F.go
+	zero=""
+	if [ "$1" = "-0" ]; then
+		zero="-0"
+		shift
+	fi
+	errchk $zero $G -e $* $D/$F.go
+}
+
+errorcheckoutput() {
+	zero=""
+	if [ "$1" = "-0" ]; then
+		zero="-0"
+		shift
+	fi
+	go run "$D/$F.go" "$@" > tmp.go
+	errchk $zero $G -e tmp.go
 }
 
 skip() {
diff --git a/test/torture.go b/test/torture.go
new file mode 100644
index 0000000..bbf6d34
--- /dev/null
+++ b/test/torture.go
@@ -0,0 +1,339 @@
+// compile
+
+// 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.
+
+// Various tests for expressions with high complexity.
+
+package main
+
+// Concatenate 16 4-bit integers into a 64-bit number.
+func concat(s *[16]byte) uint64 {
+	r := (((((((((((((((uint64(s[0])<<4|
+		uint64(s[1]))<<4|
+		uint64(s[2]))<<4|
+		uint64(s[3]))<<4|
+		uint64(s[4]))<<4|
+		uint64(s[5]))<<4|
+		uint64(s[6]))<<4|
+		uint64(s[7]))<<4|
+		uint64(s[8]))<<4|
+		uint64(s[9]))<<4|
+		uint64(s[10]))<<4|
+		uint64(s[11]))<<4|
+		uint64(s[12]))<<4|
+		uint64(s[13]))<<4|
+		uint64(s[14]))<<4 |
+		uint64(s[15]))
+	return r
+}
+
+// Compute the determinant of a 4x4-matrix by the sum
+// over all index permutations.
+func determinant(m [4][4]float64) float64 {
+	return m[0][0]*m[1][1]*m[2][2]*m[3][3] -
+		m[0][0]*m[1][1]*m[2][3]*m[3][2] -
+		m[0][0]*m[1][2]*m[2][1]*m[3][3] +
+		m[0][0]*m[1][2]*m[2][3]*m[3][1] +
+		m[0][0]*m[1][3]*m[2][1]*m[3][2] -
+		m[0][0]*m[1][3]*m[2][2]*m[3][1] -
+		m[0][1]*m[1][0]*m[2][2]*m[3][3] +
+		m[0][1]*m[1][0]*m[2][3]*m[3][2] +
+		m[0][1]*m[1][2]*m[2][0]*m[3][3] -
+		m[0][1]*m[1][2]*m[2][3]*m[3][0] -
+		m[0][1]*m[1][3]*m[2][0]*m[3][2] +
+		m[0][1]*m[1][3]*m[2][2]*m[3][0] +
+		m[0][2]*m[1][0]*m[2][1]*m[3][3] -
+		m[0][2]*m[1][0]*m[2][3]*m[3][1] -
+		m[0][2]*m[1][1]*m[2][0]*m[3][3] +
+		m[0][2]*m[1][1]*m[2][3]*m[3][0] +
+		m[0][2]*m[1][3]*m[2][0]*m[3][1] -
+		m[0][2]*m[1][3]*m[2][1]*m[3][0] -
+		m[0][3]*m[1][0]*m[2][1]*m[3][2] +
+		m[0][3]*m[1][0]*m[2][2]*m[3][1] +
+		m[0][3]*m[1][1]*m[2][0]*m[3][2] -
+		m[0][3]*m[1][1]*m[2][2]*m[3][0] -
+		m[0][3]*m[1][2]*m[2][0]*m[3][1] +
+		m[0][3]*m[1][2]*m[2][1]*m[3][0]
+}
+
+// Compute the determinant of a 4x4-matrix by the sum
+// over all index permutations.
+func determinantInt(m [4][4]int) int {
+	return m[0][0]*m[1][1]*m[2][2]*m[3][3] -
+		m[0][0]*m[1][1]*m[2][3]*m[3][2] -
+		m[0][0]*m[1][2]*m[2][1]*m[3][3] +
+		m[0][0]*m[1][2]*m[2][3]*m[3][1] +
+		m[0][0]*m[1][3]*m[2][1]*m[3][2] -
+		m[0][0]*m[1][3]*m[2][2]*m[3][1] -
+		m[0][1]*m[1][0]*m[2][2]*m[3][3] +
+		m[0][1]*m[1][0]*m[2][3]*m[3][2] +
+		m[0][1]*m[1][2]*m[2][0]*m[3][3] -
+		m[0][1]*m[1][2]*m[2][3]*m[3][0] -
+		m[0][1]*m[1][3]*m[2][0]*m[3][2] +
+		m[0][1]*m[1][3]*m[2][2]*m[3][0] +
+		m[0][2]*m[1][0]*m[2][1]*m[3][3] -
+		m[0][2]*m[1][0]*m[2][3]*m[3][1] -
+		m[0][2]*m[1][1]*m[2][0]*m[3][3] +
+		m[0][2]*m[1][1]*m[2][3]*m[3][0] +
+		m[0][2]*m[1][3]*m[2][0]*m[3][1] -
+		m[0][2]*m[1][3]*m[2][1]*m[3][0] -
+		m[0][3]*m[1][0]*m[2][1]*m[3][2] +
+		m[0][3]*m[1][0]*m[2][2]*m[3][1] +
+		m[0][3]*m[1][1]*m[2][0]*m[3][2] -
+		m[0][3]*m[1][1]*m[2][2]*m[3][0] -
+		m[0][3]*m[1][2]*m[2][0]*m[3][1] +
+		m[0][3]*m[1][2]*m[2][1]*m[3][0]
+}
+
+// Compute the determinant of a 4x4-matrix by the sum
+// over all index permutations.
+func determinantByte(m [4][4]byte) byte {
+	return m[0][0]*m[1][1]*m[2][2]*m[3][3] -
+		m[0][0]*m[1][1]*m[2][3]*m[3][2] -
+		m[0][0]*m[1][2]*m[2][1]*m[3][3] +
+		m[0][0]*m[1][2]*m[2][3]*m[3][1] +
+		m[0][0]*m[1][3]*m[2][1]*m[3][2] -
+		m[0][0]*m[1][3]*m[2][2]*m[3][1] -
+		m[0][1]*m[1][0]*m[2][2]*m[3][3] +
+		m[0][1]*m[1][0]*m[2][3]*m[3][2] +
+		m[0][1]*m[1][2]*m[2][0]*m[3][3] -
+		m[0][1]*m[1][2]*m[2][3]*m[3][0] -
+		m[0][1]*m[1][3]*m[2][0]*m[3][2] +
+		m[0][1]*m[1][3]*m[2][2]*m[3][0] +
+		m[0][2]*m[1][0]*m[2][1]*m[3][3] -
+		m[0][2]*m[1][0]*m[2][3]*m[3][1] -
+		m[0][2]*m[1][1]*m[2][0]*m[3][3] +
+		m[0][2]*m[1][1]*m[2][3]*m[3][0] +
+		m[0][2]*m[1][3]*m[2][0]*m[3][1] -
+		m[0][2]*m[1][3]*m[2][1]*m[3][0] -
+		m[0][3]*m[1][0]*m[2][1]*m[3][2] +
+		m[0][3]*m[1][0]*m[2][2]*m[3][1] +
+		m[0][3]*m[1][1]*m[2][0]*m[3][2] -
+		m[0][3]*m[1][1]*m[2][2]*m[3][0] -
+		m[0][3]*m[1][2]*m[2][0]*m[3][1] +
+		m[0][3]*m[1][2]*m[2][1]*m[3][0]
+}
+
+type A []A
+
+// A sequence of constant indexings.
+func IndexChain1(s A) A {
+	return s[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]
+}
+
+// A sequence of non-constant indexings.
+func IndexChain2(s A, i int) A {
+	return s[i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i]
+}
+
+// Another sequence of indexings.
+func IndexChain3(s []int) int {
+	return s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[0]]]]]]]]]]]]]]]]]]]]]
+}
+
+// A right-leaning tree of byte multiplications.
+func righttree(a, b, c, d uint8) uint8 {
+	return a * (b * (c * (d *
+		(a * (b * (c * (d *
+			(a * (b * (c * (d *
+				(a * (b * (c * (d *
+					(a * (b * (c * (d *
+						a * (b * (c * d)))))))))))))))))))))
+
+}
+
+// A left-leaning tree of byte multiplications.
+func lefttree(a, b, c, d uint8) uint8 {
+	return ((((((((((((((((((a * b) * c) * d *
+		a) * b) * c) * d *
+		a) * b) * c) * d *
+		a) * b) * c) * d *
+		a) * b) * c) * d *
+		a) * b) * c) * d)
+}
+
+type T struct {
+	Next I
+}
+
+type I interface{}
+
+// A chains of type assertions.
+func ChainT(t *T) *T {
+	return t.
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T).
+		Next.(*T)
+}
+
+type U struct {
+	Children []J
+}
+
+func (u *U) Child(n int) J { return u.Children[n] }
+
+type J interface {
+	Child(n int) J
+}
+
+func ChainUAssert(u *U) *U {
+	return u.Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U).
+		Child(0).(*U)
+}
+
+func ChainUNoAssert(u *U) *U {
+	return u.Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).
+		Child(0).(*U)
+}
+
+// Type assertions and slice indexing. See issue 4207.
+func ChainAssertIndex(u *U) J {
+	return u.
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0].(*U).
+		Children[0]
+}
+
+type UArr struct {
+	Children [2]J
+}
+
+func (u *UArr) Child(n int) J { return u.Children[n] }
+
+func ChainAssertArrayIndex(u *UArr) J {
+	return u.
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0].(*UArr).
+		Children[0]
+}
+
+type UArrPtr struct {
+	Children *[2]J
+}
+
+func (u *UArrPtr) Child(n int) J { return u.Children[n] }
+
+func ChainAssertArrayptrIndex(u *UArrPtr) J {
+	return u.
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0].(*UArrPtr).
+		Children[0]
+}
+
+// Chains of divisions. See issue 4201.
+
+func ChainDiv(a, b int) int {
+	return a / b / a / b / a / b / a / b /
+		a / b / a / b / a / b / a / b /
+		a / b / a / b / a / b / a / b
+}
+
+func ChainDivRight(a, b int) int {
+	return a / (b / (a / (b /
+		(a / (b / (a / (b /
+			(a / (b / (a / (b /
+				(a / (b / (a / (b /
+					(a / (b / (a / b))))))))))))))))))
+}
+
+func ChainDivConst(a int) int {
+	return a / 17 / 17 / 17 /
+		17 / 17 / 17 / 17 /
+		17 / 17 / 17 / 17
+}
+
+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
+}
diff --git a/test/typecheck.go b/test/typecheck.go
new file mode 100644
index 0000000..239ceac
--- /dev/null
+++ b/test/typecheck.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Verify that the Go compiler will not
+// die after running into an undefined
+// type in the argument list for a
+// function.
+// Does not compile.
+
+package main
+
+func mine(int b) int {	// ERROR "undefined.*b"
+	return b + 2	// ERROR "undefined.*b"
+}
+
+func main() {
+	mine()
+	c = mine()	// ERROR "undefined.*c" "cannot assign to c"
+}
diff --git a/test/typeswitch3.go b/test/typeswitch3.go
index 5475a8a..287e32e 100644
--- a/test/typeswitch3.go
+++ b/test/typeswitch3.go
@@ -36,7 +36,7 @@ func main(){
 	}
 	
 	// Issue 2827.
-	switch _ := r.(type) {  // ERROR "invalid variable name _"
+	switch _ := r.(type) {  // ERROR "invalid variable name _|no new variables"
 	}
 }
 
diff --git a/test/zerodivide.go b/test/zerodivide.go
index 673d1d1..9ab2713 100644
--- a/test/zerodivide.go
+++ b/test/zerodivide.go
@@ -237,4 +237,7 @@ func main() {
 			fmt.Printf("%v/%v: expected %g error; got %g\n", t.f, t.g, t.out, x)
 		}
 	}
+	if bad {
+		panic("zerodivide")
+	}
 }

-- 
Packaging for Google Go



More information about the pkg-golang-commits mailing list